#include <fcntl.h>
#include <linux/if_tun.h>
#define SYSLOG_NAMES
+#include <stdio.h>
#include <syslog.h>
#include <malloc.h>
#include <net/route.h>
#include <netinet/ip6.h>
#include <stdarg.h>
#include <stdlib.h>
-#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <sys/ioctl.h>
#include <linux/rtnetlink.h>
#include "md5.h"
+#include "dhcp6.h"
#include "l2tpns.h"
#include "cluster.h"
#include "plugin.h"
#include "l2tplac.h"
#include "pppoe.h"
+#include "dhcp6.h"
char * Vendor_name = "Linux L2TPNS";
uint32_t call_serial_number = 0;
CONFIG("bind_multi_address", bind_multi_address, STRING),
CONFIG("grp_txrate_average_time", grp_txrate_average_time, INT),
CONFIG("pppoe_only_equal_svc_name", pppoe_only_equal_svc_name, BOOL),
+ CONFIG("multi_hostname", multi_hostname, STRING),
+ CONFIG("no_throttle_local_IP", no_throttle_local_IP, BOOL),
+ CONFIG("dhcp6_preferred_lifetime", dhcp6_preferred_lifetime, INT),
+ CONFIG("dhcp6_valid_lifetime", dhcp6_valid_lifetime, INT),
+ CONFIG("dhcp6_server_duid", dhcp6_server_duid, INT),
+ CONFIG("primary_ipv6_dns", default_ipv6_dns1, IPv6),
+ CONFIG("secondary_ipv6_dns", default_ipv6_dns2, IPv6),
+ CONFIG("default_ipv6_domain_list", default_ipv6_domain_list, STRING),
{ NULL, 0, 0, 0 }
};
ip.s6_addr[1] == 0x80 &&
ip.s6_addr16[1] == 0 &&
ip.s6_addr16[2] == 0 &&
- ip.s6_addr16[3] == 0)) {
- s = lookup_ipmap(*(in_addr_t *) &ip.s6_addr[8]);
+ ip.s6_addr16[3] == 0))
+ {
+ in_addr_t *pipv4 = (in_addr_t *) &ip.s6_addr[8];
+ s = lookup_ipmap(*pipv4);
} else {
s = lookup_ipv6map(ip);
}
//
// CLI list to dump current ipcache.
//
-int cmd_show_ipcache(struct cli_def *cli, char *command, char **argv, int argc)
+int cmd_show_ipcache(struct cli_def *cli, const char *command, char **argv, int argc)
{
union iphash *d = ip_hash, *e, *f, *g;
int i, j, k, l;
groupidt g;
sessiont *sp;
tunnelidt t;
- in_addr_t ip;
+ in_addr_t ip, ip_src;
uint8_t *data = buf; // Keep a copy of the originals.
int size = len;
return;
}
+ ip_src = *(uint32_t *)(buf + 12);
ip = *(uint32_t *)(buf + 16);
if ((g = grp_groupbyip(ip)))
{
- s = grp_getnextsession(g, ip);
+ s = grp_getnextsession(g, ip, ip_src);
if (!s)
{
// Is this a packet for a session that doesn't exist?
if (sp->tbf_out)
{
- // Are we throttling this session?
- if (config->cluster_iam_master)
- tbf_queue_packet(sp->tbf_out, data, size);
- else
- master_throttle_packet(sp->tbf_out, data, size);
- return;
+ if (!config->no_throttle_local_IP || !sessionbyip(ip_src))
+ {
+ // Are we throttling this session?
+ if (config->cluster_iam_master)
+ tbf_queue_packet(sp->tbf_out, data, size);
+ else
+ master_throttle_packet(sp->tbf_out, data, size);
+ return;
+ }
}
if (sp->walled_garden && !config->cluster_iam_master)
{
sessiont *sp;
tunnelidt t;
+ uint8_t *p;
+ uint8_t *data = buf; // Keep a copy of the originals.
uint8_t b[MAXETHER + 20];
LOG(5, s, t, "Ethernet -> Tunnel (%d bytes)\n", len);
// Add on L2TP header
- {
- uint8_t *p = makeppp(b, sizeof(b), buf, len, s, t, PPPIP, 0, 0, 0);
- if (!p) return;
- tunnelsend(b, len + (p-b), t); // send it...
- }
+ if (*(uint16_t *) (data + 2) == htons(PKTIPV6))
+ p = makeppp(b, sizeof(b), buf, len, s, t, PPPIPV6, 0, 0, 0); // IPV6
+ else
+ p = makeppp(b, sizeof(b), buf, len, s, t, PPPIP, 0, 0, 0); // IPV4
+
+ if (!p) return;
+
+ tunnelsend(b, len + (p-b), t); // send it...
// Snooping this session.
if (sp->snoop_ip && sp->snoop_port)
static void control16(controlt * c, uint16_t avp, uint16_t val, uint8_t m)
{
uint16_t l = (m ? 0x8008 : 0x0008);
- *(uint16_t *) (c->buf + c->length + 0) = htons(l);
- *(uint16_t *) (c->buf + c->length + 2) = htons(0);
- *(uint16_t *) (c->buf + c->length + 4) = htons(avp);
- *(uint16_t *) (c->buf + c->length + 6) = htons(val);
+ uint16_t *pint16 = (uint16_t *) (c->buf + c->length + 0);
+ pint16[0] = htons(l);
+ pint16[1] = htons(0);
+ pint16[2] = htons(avp);
+ pint16[3] = htons(val);
c->length += 8;
}
static void control32(controlt * c, uint16_t avp, uint32_t val, uint8_t m)
{
uint16_t l = (m ? 0x800A : 0x000A);
- *(uint16_t *) (c->buf + c->length + 0) = htons(l);
- *(uint16_t *) (c->buf + c->length + 2) = htons(0);
- *(uint16_t *) (c->buf + c->length + 4) = htons(avp);
- *(uint32_t *) (c->buf + c->length + 6) = htonl(val);
+ uint16_t *pint16 = (uint16_t *) (c->buf + c->length + 0);
+ uint32_t *pint32 = (uint32_t *) (c->buf + c->length + 6);
+ pint16[0] = htons(l);
+ pint16[1] = htons(0);
+ pint16[2] = htons(avp);
+ pint32[0] = htonl(val);
c->length += 10;
}
static void controls(controlt * c, uint16_t avp, char *val, uint8_t m)
{
uint16_t l = ((m ? 0x8000 : 0) + strlen(val) + 6);
- *(uint16_t *) (c->buf + c->length + 0) = htons(l);
- *(uint16_t *) (c->buf + c->length + 2) = htons(0);
- *(uint16_t *) (c->buf + c->length + 4) = htons(avp);
+ uint16_t *pint16 = (uint16_t *) (c->buf + c->length + 0);
+ pint16[0] = htons(l);
+ pint16[1] = htons(0);
+ pint16[2] = htons(avp);
memcpy(c->buf + c->length + 6, val, strlen(val));
c->length += 6 + strlen(val);
}
static void controlb(controlt * c, uint16_t avp, uint8_t *val, unsigned int len, uint8_t m)
{
uint16_t l = ((m ? 0x8000 : 0) + len + 6);
- *(uint16_t *) (c->buf + c->length + 0) = htons(l);
- *(uint16_t *) (c->buf + c->length + 2) = htons(0);
- *(uint16_t *) (c->buf + c->length + 4) = htons(avp);
+ uint16_t *pint16 = (uint16_t *) (c->buf + c->length + 0);
+ pint16[0] = htons(l);
+ pint16[1] = htons(0);
+ pint16[2] = htons(avp);
memcpy(c->buf + c->length + 6, val, len);
c->length += 6 + len;
}
// add a control message to a tunnel, and send if within window
static void controladd(controlt *c, sessionidt far, tunnelidt t)
{
- *(uint16_t *) (c->buf + 2) = htons(c->length); // length
- *(uint16_t *) (c->buf + 4) = htons(tunnel[t].far); // tunnel
- *(uint16_t *) (c->buf + 6) = htons(far); // session
- *(uint16_t *) (c->buf + 8) = htons(tunnel[t].ns); // sequence
+ uint16_t *pint16 = (uint16_t *) (c->buf + 2);
+ pint16[0] = htons(c->length); // length
+ pint16[1] = htons(tunnel[t].far); // tunnel
+ pint16[2] = htons(far); // session
+ pint16[3] = htons(tunnel[t].ns); // sequence
tunnel[t].ns++; // advance sequence
// link in message in to queue
if (tunnel[t].controlc)
free_ip_address(s);
// unroute IPv6, if setup
- if (session[s].ppp.ipv6cp == Opened && session[s].ipv6prefixlen && del_routes)
+ if (session[s].ipv6route.s6_addr[0] && session[s].ipv6prefixlen && del_routes)
route6set(s, session[s].ipv6route, session[s].ipv6prefixlen, 0);
-
+
+ if (session[s].ipv6address.s6_addr[0] && del_routes)
+ {
+ route6set(s, session[s].ipv6address, 128, 0);
+ }
+
if (b)
{
// This session was part of a bundle
// IPV6 route
if (session[new_s].ipv6prefixlen)
cache_ipv6map(session[new_s].ipv6route, session[new_s].ipv6prefixlen, new_s);
+
+ if (session[new_s].ipv6address.s6_addr[0])
+ {
+ cache_ipv6map(session[new_s].ipv6address, 128, new_s);
+ }
}
}
}
// read and process packet on tunnel (UDP)
void processudp(uint8_t *buf, int len, struct sockaddr_in *addr, uint16_t indexudpfd)
{
- uint8_t *chapresponse = NULL;
+ uint8_t *sendchalresponse = NULL;
+ uint8_t *recvchalresponse = NULL;
uint16_t l = len, t = 0, s = 0, ns = 0, nr = 0;
uint8_t *p = buf + 2;
tunnel[t].window = 1; // window of 0 is silly
LOG(4, s, t, " rx window = %u\n", tunnel[t].window);
break;
- case 11: // Challenge
+ case 11: // Request Challenge
{
LOG(4, s, t, " LAC requested CHAP authentication for tunnel\n");
- build_chap_response(b, 2, n, &chapresponse);
+ if (message == 1)
+ build_chap_response(b, 2, n, &sendchalresponse);
+ else if (message == 2)
+ build_chap_response(b, 3, n, &sendchalresponse);
}
break;
- case 13: // Response
+ case 13: // receive challenge Response
if (tunnel[t].isremotelns)
{
- chapresponse = calloc(17, 1);
- memcpy(chapresponse, b, (n < 17) ? n : 16);
+ recvchalresponse = calloc(17, 1);
+ memcpy(recvchalresponse, b, (n < 17) ? n : 16);
LOG(3, s, t, "received challenge response from REMOTE LNS\n");
}
else
controlt *c = controlnew(2); // sending SCCRP
control16(c, 2, version, 1); // protocol version
control32(c, 3, 3, 1); // framing
- controls(c, 7, hostname, 1); // host name
- if (chapresponse) controlb(c, 13, chapresponse, 16, 1); // Challenge response
+ controls(c, 7, config->multi_n_hostname[tunnel[t].indexudp][0]?config->multi_n_hostname[tunnel[t].indexudp]:hostname, 1); // host name
+ if (sendchalresponse) controlb(c, 13, sendchalresponse, 16, 1); // Send Challenge response
control16(c, 9, t, 1); // assigned tunnel
controladd(c, 0, t); // send the resply
}
LOG(3, s, t, "Received SCCRP\n");
if (main_quit != QUIT_SHUTDOWN)
{
- if (tunnel[t].isremotelns && chapresponse)
+ if (tunnel[t].isremotelns && recvchalresponse)
{
hasht hash;
lac_calc_rlns_auth(t, 2, hash); // id = 2 (SCCRP)
// check authenticator
- if (memcmp(hash, chapresponse, 16) == 0)
+ if (memcmp(hash, recvchalresponse, 16) == 0)
{
LOG(3, s, t, "sending SCCCN to REMOTE LNS\n");
controlt *c = controlnew(3); // sending SCCCN
- controls(c, 7, hostname, 1); // host name
+ controls(c, 7, config->multi_n_hostname[tunnel[t].indexudp][0]?config->multi_n_hostname[tunnel[t].indexudp]:hostname, 1); // host name
controls(c, 8, Vendor_name, 1); // Vendor name
control16(c, 2, version, 1); // protocol version
control32(c, 3, 3, 1); // framing Capabilities
+ if (sendchalresponse) controlb(c, 13, sendchalresponse, 16, 1); // Challenge response
control16(c, 9, t, 1); // assigned tunnel
controladd(c, 0, t); // send
}
// Set multilink options before sending initial LCP packet
sess_local[s].mp_mrru = 1614;
- sess_local[s].mp_epdis = ntohl(config->iftun_n_address[tunnel[t].indexudp] ? config->iftun_n_address[tunnel[t].indexudp] : my_address);
+ sess_local[s].mp_epdis = ntohl(config->iftun_address ? config->iftun_address : my_address);
sendlcp(s, t);
change_state(s, lcp, RequestSent);
LOG(1, s, t, "Unknown message type %u\n", message);
break;
}
- if (chapresponse) free(chapresponse);
+ if (sendchalresponse) free(sendchalresponse);
+ if (recvchalresponse) free(recvchalresponse);
cluster_send_tunnel(t);
}
else
return;
}
+ if (!config->cluster_iam_master)
+ {
+ // Check if DhcpV6, IP dst: FF02::1:2, Src Port 0x0222 (546), Dst Port 0x0223 (547)
+ if (*(p + 6) == 17 && *(p + 24) == 0xFF && *(p + 25) == 2 &&
+ *(uint32_t *)(p + 26) == 0 && *(uint32_t *)(p + 30) == 0 &&
+ *(uint16_t *)(p + 34) == 0 && *(p + 36) == 0 && *(p + 37) == 1 && *(p + 38) == 0 && *(p + 39) == 2 &&
+ *(p + 40) == 2 && *(p + 41) == 0x22 && *(p + 42) == 2 && *(p + 43) == 0x23)
+ {
+ // DHCPV6 must be managed by the Master.
+ master_forward_packet(buf, len, addr->sin_addr.s_addr, addr->sin_port, indexudpfd);
+ return;
+ }
+ }
+
processipv6in(s, t, p, l);
}
else if (session[s].ppp.lcp == Opened)
case 'd':
if (fork()) exit(0);
setsid();
- freopen("/dev/null", "r", stdin);
- freopen("/dev/null", "w", stdout);
- freopen("/dev/null", "w", stderr);
+ if(!freopen("/dev/null", "r", stdin)) LOG(0, 0, 0, "Error freopen stdin: %s\n", strerror(errno));
+ if(!freopen("/dev/null", "w", stdout)) LOG(0, 0, 0, "Error freopen stdout: %s\n", strerror(errno));
+ if(!freopen("/dev/null", "w", stderr)) LOG(0, 0, 0, "Error freopen stderr: %s\n", strerror(errno));
break;
case 'v':
optdebug++;
init_tbf(config->num_tbfs);
LOG(0, 0, 0, "L2TPNS version " VERSION "\n");
+ LOG(0, 0, 0, "Copyright (c) 2012, 2013, 2014 ISP FDN & SAMESWIRELESS\n");
LOG(0, 0, 0, "Copyright (c) 2003, 2004, 2005, 2006 Optus Internet Engineering\n");
LOG(0, 0, 0, "Copyright (c) 2002 FireBrick (Andrews & Arnold Ltd / Watchfront Ltd) - GPL licenced\n");
{
LOG(0, 0, 0, "Can't set ulimit: %s\n", strerror(errno));
// Make core dumps go to /tmp
- chdir("/tmp");
+ if(chdir("/tmp")) LOG(0, 0, 0, "Error chdir /tmp: %s\n", strerror(errno));
}
if (config->scheduler_fifo)
initrad();
initippool();
+ dhcpv6_init();
// seed prng
{
config->iftun_n_address[config->nbmultiaddress] = htonl(ip);
config->nbmultiaddress++;
LOG(1, 0, 0, "Bind address %s\n", fmtaddr(htonl(ip), 0));
+
+ if (config->nbmultiaddress >= MAX_BINDADDR) break;
}
sip = n;
config->iftun_n_address[0] = config->iftun_address;
}
+ if (*config->multi_hostname)
+ {
+ char *shost = config->multi_hostname;
+ char *n = shost;
+ char *e = config->multi_hostname + strlen(config->multi_hostname);
+ config->nbmultihostname = 0;
+
+ while (*shost && (shost < e))
+ {
+ while ((n < e) && (*n == ' ' || *n == ',' || *n == '\t')) n++;
+
+ i = 0;
+ while (n < e && (*n != ',') && (*n != '\t'))
+ {
+ config->multi_n_hostname[config->nbmultihostname][i] = *n;
+ n++;i++;
+ }
+
+ if (i > 0)
+ {
+ config->multi_n_hostname[config->nbmultihostname][i] = 0;
+ LOG(1, 0, 0, "Bind Hostname %s\n", config->multi_n_hostname[config->nbmultihostname]);
+ config->nbmultihostname++;
+ if (config->nbmultihostname >= MAX_NBHOSTNAME) break;
+ }
+
+ shost = n;
+ }
+
+ if (config->nbmultihostname >= 1)
+ {
+ strcpy(hostname, config->multi_n_hostname[0]);
+ strcpy(config->hostname, hostname);
+ }
+ }
+
if (!*config->pppoe_ac_name)
strncpy(config->pppoe_ac_name, DEFAULT_PPPOE_AC_NAME, sizeof(config->pppoe_ac_name) - 1);
uncache_ipmap(session[s].ip);
}
+ // remove old IPV6 routes...
+ if (session[s].ipv6route.s6_addr[0] && session[s].ipv6prefixlen)
+ route6set(s, session[s].ipv6route, session[s].ipv6prefixlen, 0);
+
+ if (session[s].ipv6address.s6_addr[0])
+ {
+ route6set(s, session[s].ipv6address, 128, 0);
+ }
+
routed = 0;
// add new routes...
// check v6 routing
if (new->ipv6prefixlen && new->ppp.ipv6cp == Opened && session[s].ppp.ipv6cp != Opened)
- route6set(s, new->ipv6route, new->ipv6prefixlen, 1);
+ route6set(s, new->ipv6route, new->ipv6prefixlen, 1);
+
+ if (new->ipv6address.s6_addr[0] && new->ppp.ipv6cp == Opened && session[s].ppp.ipv6cp != Opened)
+ {
+ // Check if included in prefix
+ if (sessionbyipv6(new->ipv6address) != s)
+ route6set(s, new->ipv6address, 128, 1);
+ }
// check filters
if (new->filter_in && (new->filter_in > MAXFILTER || !ip_filters[new->filter_in - 1].name[0]))
}
}
-int cmd_show_hist_idle(struct cli_def *cli, char *command, char **argv, int argc)
+int cmd_show_hist_idle(struct cli_def *cli, const char *command, char **argv, int argc)
{
int s, i;
int count = 0;
return CLI_OK;
}
-int cmd_show_hist_open(struct cli_def *cli, char *command, char **argv, int argc)
+int cmd_show_hist_open(struct cli_def *cli, const char *command, char **argv, int argc)
{
int s, i;
int count = 0;
// Sent SCCRQ - Start Control Connection Request
controlt *c = controlnew(1); // sending SCCRQ
- controls(c, 7, hostname, 1); // host name
+ controls(c, 7, config->multi_n_hostname[tunnel[t].indexudp][0]?config->multi_n_hostname[tunnel[t].indexudp]:hostname, 1); // host name
controls(c, 8, Vendor_name, 1); // Vendor name
control16(c, 2, version, 1); // protocol version
control32(c, 3, 3, 1); // framing Capabilities