// 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.152 2005/12/14 02:19:15 bodea Exp $";
+char const *cvs_id_l2tpns = "$Id: l2tpns.c,v 1.159 2006/04/05 02:13:48 bodea Exp $";
#include <arpa/inet.h>
#include <assert.h>
static int add_plugin(char *plugin_name);
static int remove_plugin(char *plugin_name);
static void plugins_done(void);
-static void processcontrol(uint8_t *buf, int len, struct sockaddr_in *addr, int alen);
+static void processcontrol(uint8_t *buf, int len, struct sockaddr_in *addr, int alen, struct in_addr *local);
static tunnelidt new_tunnel(void);
static void unhide_value(uint8_t *value, size_t len, uint16_t type, uint8_t *vector, size_t vec_len);
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;
+ /* set MTU to modem MRU */
+ ifr.ifr_mtu = MRU;
if (ioctl(ifrfd, SIOCSIFMTU, (void *) &ifr) < 0)
{
LOG(0, 0, 0, "Error setting tun MTU: %s\n", strerror(errno));
addr.sin_port = htons(NSCTL_PORT);
controlfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
setsockopt(controlfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
+ setsockopt(controlfd, SOL_IP, IP_PKTINFO, &on, sizeof(on)); // recvfromto
if (bind(controlfd, (void *) &addr, sizeof(addr)) < 0)
{
LOG(0, 0, 0, "Error in control bind: %s\n", strerror(errno));
addr.sin_port = htons(config->radius_dae_port);
daefd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
setsockopt(daefd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
+ setsockopt(daefd, SOL_IP, IP_PKTINFO, &on, sizeof(on)); // recvfromto
if (bind(daefd, (void *) &addr, sizeof(addr)) < 0)
{
LOG(0, 0, 0, "Error in DAE bind: %s\n", strerror(errno));
if (amagic == 0) amagic = time_now;
session[s].magic = amagic; // set magic number
session[s].flags = aflags; // set flags received
- session[s].mru = PPPMTU; // default
+ session[s].mru = PPPoE_MRU; // default
controlnull(t); // ack
// start LCP
*q = EchoReq;
*(uint8_t *)(q + 1) = (time_now % 255); // ID
*(uint16_t *)(q + 2) = htons(8); // Length
- *(uint32_t *)(q + 4) = 0; // Magic Number (not supported)
+ *(uint32_t *)(q + 4) = session[s].ppp.lcp == Opened ? htonl(session[s].magic) : 0; // Magic Number
LOG(4, s, session[s].tunnel, "No data in %d seconds, sending LCP ECHO\n",
(int)(time_now - session[s].last_packet));
if (n)
{
struct sockaddr_in addr;
+ struct in_addr local;
socklen_t alen;
int c, s;
int udp_ready = 0;
for (c = n, i = 0; i < c; i++)
{
struct event_data *d = events[i].data.ptr;
+
switch (d->type)
{
case FD_TYPE_CLI: // CLI connections
case FD_TYPE_CONTROL: // nsctl commands
alen = sizeof(addr);
- processcontrol(buf, recvfrom(controlfd, buf, sizeof(buf), MSG_WAITALL, (void *) &addr, &alen), &addr, alen);
+ s = recvfromto(controlfd, buf, sizeof(buf), MSG_WAITALL, (struct sockaddr *) &addr, &alen, &local);
+ if (s > 0) processcontrol(buf, s, &addr, alen, &local);
n--;
break;
case FD_TYPE_DAE: // DAE requests
alen = sizeof(addr);
- processdae(buf, recvfrom(daefd, buf, sizeof(buf), MSG_WAITALL, (void *) &addr, &alen), &addr, alen);
+ s = recvfromto(daefd, buf, sizeof(buf), MSG_WAITALL, (struct sockaddr *) &addr, &alen, &local);
+ if (s > 0) processdae(buf, s, &addr, alen, &local);
n--;
break;
case FD_TYPE_RADIUS: // RADIUS response
- s = recv(radfds[d->index], buf, sizeof(buf), 0);
+ alen = sizeof(addr);
+ s = recvfrom(radfds[d->index], buf, sizeof(buf), MSG_WAITALL, (struct sockaddr *) &addr, &alen);
if (s >= 0 && config->cluster_iam_master)
- processrad(buf, s, d->index);
+ {
+ if (addr.sin_addr.s_addr == config->radiusserver[0] ||
+ addr.sin_addr.s_addr == config->radiusserver[1])
+ processrad(buf, s, d->index);
+ else
+ LOG(3, 0, 0, "Dropping RADIUS packet from unknown source %s\n",
+ fmtaddr(addr.sin_addr.s_addr, 0));
+ }
n--;
break;
else
{
// It's a single ip address
- add_to_ip_pool(inet_addr(pool), 0);
+ add_to_ip_pool(ntohl(inet_addr(pool)), 0);
}
}
fclose(f);
#define L2TP_HDRS (20+8+6+4) // L2TP data encaptulation: ip + udp + l2tp (data) + ppp (inc hdlc)
#define TCP_HDRS (20+20) // TCP encapsulation: ip + tcp
- if (config->l2tp_mtu <= 0) config->l2tp_mtu = PPPMTU;
+ if (config->l2tp_mtu <= 0) config->l2tp_mtu = 1500; // ethernet default
else if (config->l2tp_mtu < MINMTU) config->l2tp_mtu = MINMTU;
else if (config->l2tp_mtu > MAXMTU) config->l2tp_mtu = MAXMTU;
// reset MRU/MSS globals
MRU = config->l2tp_mtu - L2TP_HDRS;
+ if (MRU > PPPoE_MRU)
+ MRU = PPPoE_MRU;
+
MSS = MRU - TCP_HDRS;
// Update radius
run_plugin_done(p);
}
-static void processcontrol(uint8_t *buf, int len, struct sockaddr_in *addr, int alen)
+static void processcontrol(uint8_t *buf, int len, struct sockaddr_in *addr, int alen, struct in_addr *local)
{
struct nsctl request;
struct nsctl response;
r = pack_control(buf, NSCTL_MAX_PKT_SZ, response.type, response.argc, response.argv);
if (r > 0)
{
- sendto(controlfd, buf, r, 0, (const struct sockaddr *) addr, alen);
+ sendtofrom(controlfd, buf, r, 0, (const struct sockaddr *) addr, alen, local);
if (log_stream && config->debug >= 4)
{
LOG(4, 0, 0, "Sent [%s] ", fmtaddr(addr->sin_addr.s_addr, 0));