// Copyright (c) 2002 FireBrick (Andrews & Arnold Ltd / Watchfront Ltd) - GPL licenced
// vim: sw=8 ts=8
-char const *cvs_id_l2tpns = "$Id: l2tpns.c,v 1.141 2005-09-19 00:29:12 bodea Exp $";
+char const *cvs_id_l2tpns = "$Id: l2tpns.c,v 1.152 2005-12-14 02:19:15 bodea Exp $";
#include <arpa/inet.h>
#include <assert.h>
static uint32_t ip_pool_size = 1; // Size of the pool of addresses used for dynamic address allocation.
time_t time_now = 0; // Current time in seconds since epoch.
static char time_now_string[64] = {0}; // Current time as a string.
-int time_changed = 0; // time_now changed
+static int time_changed = 0; // time_now changed
char main_quit = 0; // True if we're in the process of exiting.
-char main_reload = 0; // Re-load pending
+static char main_reload = 0; // Re-load pending
linked_list *loaded_plugins;
linked_list *plugins[MAX_PLUGIN_TYPES];
"plugin_control",
"plugin_radius_response",
"plugin_radius_reset",
+ "plugin_radius_account",
"plugin_become_master",
"plugin_new_session_master",
};
LOG(0, 0, 0, "Error setting tun queue length: %s\n", strerror(errno));
exit(1);
}
+ /* set MTU to modem MRU + 4 (tun header) */
+ ifr.ifr_mtu = MRU + 4;
+ if (ioctl(ifrfd, SIOCSIFMTU, (void *) &ifr) < 0)
+ {
+ LOG(0, 0, 0, "Error setting tun MTU: %s\n", strerror(errno));
+ exit(1);
+ }
ifr.ifr_flags = IFF_UP;
if (ioctl(ifrfd, SIOCSIFFLAGS, (void *) &ifr) < 0)
{
if (!t)
{
- static int backtrace_count = 0;
LOG(0, 0, t, "tunnelsend called with 0 as tunnel id\n");
STAT(tunnel_tx_errors);
- log_backtrace(backtrace_count, 5)
return;
}
if (!tunnel[t].ip)
{
- static int backtrace_count = 0;
LOG(1, 0, t, "Error sending data out tunnel: no remote endpoint (tunnel not set up)\n");
- log_backtrace(backtrace_count, 5)
STAT(tunnel_tx_errors);
return;
}
{
tunnel[t].last = time_now; // control message sent
tunnel[t].retry = backoff(tunnel[t].try); // when to resend
- if (tunnel[t].try > 1)
+ if (tunnel[t].try)
{
STAT(tunnel_retries);
LOG(3, 0, t, "Control message resend try %d\n", tunnel[t].try);
sum = orig + (~MSS & 0xffff);
sum += ntohs(*(uint16_t *) (tcp + 16));
sum = (sum & 0xffff) + (sum >> 16);
- *(uint16_t *) (tcp + 16) = htons(sum);
+ *(uint16_t *) (tcp + 16) = htons(sum + (sum >> 16));
}
// process outgoing (to tunnel) IP
master_throttle_packet(sp->tbf_out, data, size);
return;
}
- else if (sp->walled_garden && !config->cluster_iam_master)
+
+ if (sp->walled_garden && !config->cluster_iam_master)
{
// We are walled-gardening this
master_garden_packet(s, data, size);
my_address; // send my IP
tunnelsend(buf, 10 + (q - buf), t); // send it
+ restart_timer(s, ipcp);
}
void sendipv6cp(sessionidt s, tunnelidt t)
q[13] = 1;
tunnelsend(buf, 14 + (q - buf), t); // send it
+ restart_timer(s, ipv6cp);
}
static void sessionclear(sessionidt s)
if (*p == 5 && p[1] == 6) // Magic-Number
amagic = ntohl(*(uint32_t *) (p + 2));
else if (*p == 7) // Protocol-Field-Compression
- aflags |= SESSIONPFC;
+ aflags |= SESSION_PFC;
else if (*p == 8) // Address-and-Control-Field-Compression
- aflags |= SESSIONACFC;
+ aflags |= SESSION_ACFC;
p += p[1];
}
}
case 12: // ICCN
if (amagic == 0) amagic = time_now;
session[s].magic = amagic; // set magic number
- session[s].l2tp_flags = aflags; // set flags received
+ session[s].flags = aflags; // set flags received
session[s].mru = PPPMTU; // default
controlnull(t); // ack
// start LCP
- sess_local[s].lcp.restart = time_now + config->ppp_restart_time;
- sess_local[s].lcp.conf_sent = 1;
- sess_local[s].lcp.nak_sent = 0;
sess_local[s].lcp_authtype = config->radius_authprefer;
sess_local[s].ppp_mru = MRU;
- session[s].ppp.lcp = RequestSent;
sendlcp(s, t);
-
+ change_state(s, lcp, RequestSent);
break;
+
case 14: // CDN
controlnull(t); // ack
sessionshutdown(s, "Closed (Received CDN).", 0, 0);
}
else if (session[s].ppp.lcp == Opened)
{
- uint8_t buf[MAXETHER];
- uint8_t *q;
- int mru = session[s].mru;
- if (mru > sizeof(buf)) mru = sizeof(buf);
-
- l += 6;
- if (l > mru) l = mru;
-
- q = makeppp(buf, sizeof(buf), 0, 0, s, t, PPPLCP);
- if (!q) return;
-
- *q = ProtocolRej;
- *(q + 1) = ++sess_local[s].lcp_ident;
- *(uint16_t *)(q + 2) = htons(l);
- *(uint16_t *)(q + 4) = htons(proto);
- memcpy(q + 6, p, l - 6);
-
- if (proto == PPPIPV6CP)
- LOG(3, s, t, "LCP: send ProtocolRej (IPV6CP: not configured)\n");
- else
- LOG(2, s, t, "LCP: sent ProtocolRej (0x%04X: unsupported)\n", proto);
-
- tunnelsend(buf, l + (q - buf), t);
+ session[s].last_packet = time_now;
+ if (!config->cluster_iam_master) { master_forward_packet(buf, len, addr->sin_addr.s_addr, addr->sin_port); return; }
+ protoreject(s, t, p, l, proto);
}
else
{
}
}
// Send hello
- if (tunnel[t].state == TUNNELOPEN && (time_now - tunnel[t].lastrec) > 60)
+ if (tunnel[t].state == TUNNELOPEN && !tunnel[t].controlc && (time_now - tunnel[t].lastrec) > 60)
{
controlt *c = controlnew(6); // sending HELLO
controladd(c, 0, t); // send the message
if (sess_local[s].lcp.conf_sent < config->ppp_max_configure)
{
LOG(3, s, session[s].tunnel, "No ACK for LCP ConfigReq... resending\n");
- sess_local[s].lcp.restart = time_now + config->ppp_restart_time;
- sess_local[s].lcp.conf_sent++;
sendlcp(s, session[s].tunnel);
change_state(s, lcp, next_state);
}
if (sess_local[s].ipcp.conf_sent < config->ppp_max_configure)
{
LOG(3, s, session[s].tunnel, "No ACK for IPCP ConfigReq... resending\n");
- sess_local[s].ipcp.restart = time_now + config->ppp_restart_time;
- sess_local[s].ipcp.conf_sent++;
sendipcp(s, session[s].tunnel);
change_state(s, ipcp, next_state);
}
if (sess_local[s].ipv6cp.conf_sent < config->ppp_max_configure)
{
LOG(3, s, session[s].tunnel, "No ACK for IPV6CP ConfigReq... resending\n");
- sess_local[s].ipv6cp.restart = time_now + config->ppp_restart_time;
- sess_local[s].ipv6cp.conf_sent++;
sendipv6cp(s, session[s].tunnel);
change_state(s, ipv6cp, next_state);
}
if (sess_local[s].ccp.conf_sent < config->ppp_max_configure)
{
LOG(3, s, session[s].tunnel, "No ACK for CCP ConfigReq... resending\n");
- sess_local[s].ccp.restart = time_now + config->ppp_restart_time;
- sess_local[s].ccp.conf_sent++;
sendccp(s, session[s].tunnel);
change_state(s, ccp, next_state);
}
}
// No data in ECHO_TIMEOUT seconds, send LCP ECHO
- if (session[s].ppp.phase >= Establish && (time_now - session[s].last_packet >= ECHO_TIMEOUT))
+ if (session[s].ppp.phase >= Establish && (time_now - session[s].last_packet >= ECHO_TIMEOUT) &&
+ (time_now - sess_local[s].last_echo >= ECHO_TIMEOUT))
{
uint8_t b[MAXETHER];
LOG(4, s, session[s].tunnel, "No data in %d seconds, sending LCP ECHO\n",
(int)(time_now - session[s].last_packet));
tunnelsend(b, 24, session[s].tunnel); // send it
+ sess_local[s].last_echo = time_now;
s_actions++;
}
if (time_changed)
{
- double Mbps = ((1024.0 / 1024.0) * 8) / time_changed;
- time_changed = 0;
+ double Mbps = 1024.0 * 1024.0 / 8 * time_changed;
// Log current traffic stats
snprintf(config->bandwidth, sizeof(config->bandwidth),
"UDP-ETH:%1.0f/%1.0f ETH-UDP:%1.0f/%1.0f TOTAL:%0.1f IN:%u OUT:%u",
(udp_rx / Mbps), (eth_tx / Mbps), (eth_rx / Mbps), (udp_tx / Mbps),
- ((udp_tx + udp_rx + eth_tx + eth_rx) / Mbps), udp_rx_pkt, eth_rx_pkt);
+ ((udp_tx + udp_rx + eth_tx + eth_rx) / Mbps),
+ udp_rx_pkt / time_changed, eth_rx_pkt / time_changed);
udp_tx = udp_rx = 0;
udp_rx_pkt = eth_rx_pkt = 0;
eth_tx = eth_rx = 0;
+ time_changed = 0;
if (config->dump_speed)
printf("%s\n", config->bandwidth);
if (frag_offset)
{
- if (!rule->frag || rule->action == FILTER_ACTION_DENY)
+ // layer 4 deny rules are skipped
+ if (rule->action == FILTER_ACTION_DENY &&
+ (rule->src_ports.op || rule->dst_ports.op || rule->tcp_flag_op))
continue;
}
else