#include <unistd.h>
#include <errno.h>
#include <stdlib.h>
-#include <sys/socket.h>
#include <linux/rtnetlink.h>
+#include <netinet/ip6.h>
+#include "dhcp6.h"
#include "l2tpns.h"
#include "constants.h"
#include "plugin.h"
static void ipv6cp_open(sessionidt s, tunnelidt t)
{
+ int i;
LOG(3, s, t, "IPV6CP: Opened\n");
change_state(s, ipv6cp, Opened);
- if (session[s].ipv6prefixlen)
- route6set(s, session[s].ipv6route, session[s].ipv6prefixlen, 1);
+ for (i = 0; i < MAXROUTE6 && session[s].route6[i].ipv6prefixlen; i++)
+ {
+ route6set(s, session[s].route6[i].ipv6route, session[s].route6[i].ipv6prefixlen, 1);
+ }
+
+ if (session[s].ipv6address.s6_addr[0])
+ {
+ // Check if included in prefix
+ if (sessionbyipv6(session[s].ipv6address) != s)
+ route6set(s, session[s].ipv6address, 128, 1);
+ }
// Send an initial RA (TODO: Should we send these regularly?)
send_ipv6_ra(s, t, NULL);
gotip++; // seen address
if (o[1] != 10) return;
- ident[0] = htonl(session[s].ip);
- ident[1] = 0;
+ if (session[s].ipv6address.s6_addr[0])
+ {
+ // LSB 64bits of assigned IPv6 address to user (see radius attribut Framed-IPv6-Address)
+ memcpy(&ident[0], &session[s].ipv6address.s6_addr[8], 8);
+ }
+ else
+ {
+ ident[0] = htonl(session[s].ip);
+ ident[1] = 0;
+ }
if (memcmp(o + 2, ident, sizeof(ident)))
{
// (i.e. this routine writes to p[-4]).
void processipin(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l)
{
- in_addr_t ip;
+ in_addr_t ip, ip_dst;
CSTAT(processipin);
}
ip = ntohl(*(uint32_t *)(p + 12));
+ ip_dst = *(uint32_t *)(p + 16);
if (l > MAXETHER)
{
if (session[s].tbf_in)
{
- // Are we throttling this session?
- if (config->cluster_iam_master)
- tbf_queue_packet(session[s].tbf_in, p, l);
- else
- master_throttle_packet(session[s].tbf_in, p, l);
- return;
+ if (!config->no_throttle_local_IP || !sessionbyip(ip_dst))
+ {
+ // Are we throttling this session?
+ if (config->cluster_iam_master)
+ tbf_queue_packet(session[s].tbf_in, p, l);
+ else
+ master_throttle_packet(session[s].tbf_in, p, l);
+ return;
+ }
}
// send to ethernet
return;
// no spoof
- if ((ipv4 != session[s].ip || memcmp(&config->ipv6_prefix, &ip, 8)) && sessionbyipv6(ip) != s)
+ if (session[s].ipv6address.s6_addr[0])
+ {
+ if ((sessionbyipv6new(ip) != s) &&
+ (ip.s6_addr[0] != 0xFE || ip.s6_addr[1] != 0x80 || ip.s6_addr16[1] != 0 || ip.s6_addr16[2] != 0 || ip.s6_addr16[3] != 0))
+ {
+ char str[INET6_ADDRSTRLEN];
+ LOG(5, s, t, "Dropping packet with spoofed IP %s\n",
+ inet_ntop(AF_INET6, &ip, str, INET6_ADDRSTRLEN));
+ return;
+ }
+ }
+ else if ((ipv4 != session[s].ip || memcmp(&config->ipv6_prefix, &ip, 8)) && sessionbyipv6(ip) != s)
{
char str[INET6_ADDRSTRLEN];
LOG(5, s, t, "Dropping packet with spoofed IP %s\n",
return;
}
+ // 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_process(s, t, p, l);
+ return;
+ }
+
// Add on the tun header
p -= 4;
*(uint32_t *) p = htonl(PKTIPV6);