IPv6 load-balancing
[l2tpns.git] / ppp.c
diff --git a/ppp.c b/ppp.c
index 0259ab7..29bf1bc 100644 (file)
--- a/ppp.c
+++ b/ppp.c
@@ -1481,11 +1481,15 @@ void processipcp(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l)
 
 static void ipv6cp_open(sessionidt s, tunnelidt t)
 {
+       int i;
+       groupidt g;
        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])
        {
@@ -1494,6 +1498,12 @@ static void ipv6cp_open(sessionidt s, tunnelidt t)
                        route6set(s, session[s].ipv6address, 128, 1);
        }
 
+       if ((g = grp_groupbysession(s)))
+       {
+               grp_setgrouproute6(g, 1);
+               cluster_send_groupe(g);
+       }
+
        // Send an initial RA (TODO: Should we send these regularly?)
        send_ipv6_ra(s, t, NULL);
 }
@@ -1579,8 +1589,16 @@ void processipv6cp(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l)
                                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)))
                                {
@@ -2253,7 +2271,19 @@ void processipv6in(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l)
                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) &&
+                       (!grp_groupbyipv6(ip)))
+               {
+                       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",