Added ability to define up to 5 IPv6 prefix delegation by user
[l2tpns.git] / radius.c
index e783323..4eda15f 100644 (file)
--- a/radius.c
+++ b/radius.c
 
 #include "md5.h"
 #include "constants.h"
+#include "dhcp6.h"
 #include "l2tpns.h"
 #include "plugin.h"
 #include "util.h"
 #include "cluster.h"
 
-#ifdef LAC
 #include "l2tplac.h"
-#endif
+#include "pppoe.h"
 
 extern radiust *radius;
 extern sessiont *session;
@@ -533,12 +533,11 @@ void processrad(uint8_t *buf, int len, char socket_index)
        sessionidt s;
        tunnelidt t = 0;
        hasht hash;
-       uint8_t routes = 0;
+       int routes = 0;
+       int routes6 = 0;
        int r_code;
        int r_id;
-#ifdef LAC
        int OpentunnelReq = 0;
-#endif
 
        CSTAT(processrad);
 
@@ -600,51 +599,16 @@ void processrad(uint8_t *buf, int len, char socket_index)
                        run_plugins(PLUGIN_POST_AUTH, &packet);
                        r_code = packet.auth_allowed ? AccessAccept : AccessReject;
 
-#ifndef LAC
-                       // process auth response
-                       if (radius[r].chap)
-                       {
-                               // CHAP
-                               uint8_t *p = makeppp(b, sizeof(b), 0, 0, s, t, PPPCHAP, 0, 0, 0);
-                               if (!p) return; // Abort!
-
-                               *p = (r_code == AccessAccept) ? 3 : 4;     // ack/nak
-                               p[1] = radius[r].id;
-                               *(uint16_t *) (p + 2) = ntohs(4); // no message
-                               tunnelsend(b, (p - b) + 4, t); // send it
-
-                               LOG(3, s, session[s].tunnel, "   CHAP User %s authentication %s.\n", session[s].user,
-                                               (r_code == AccessAccept) ? "allowed" : "denied");
-                       }
-                       else
-                       {
-                               // PAP
-                               uint8_t *p = makeppp(b, sizeof(b), 0, 0, s, t, PPPPAP, 0, 0, 0);
-                               if (!p) return;         // Abort!
-
-                               // ack/nak
-                               *p = r_code;
-                               p[1] = radius[r].id;
-                               *(uint16_t *) (p + 2) = ntohs(5);
-                               p[4] = 0; // no message
-                               tunnelsend(b, (p - b) + 5, t); // send it
-
-                               LOG(3, s, session[s].tunnel, "   PAP User %s authentication %s.\n", session[s].user,
-                                               (r_code == AccessAccept) ? "allowed" : "denied");
-                       }
-#endif
-
                        if (r_code == AccessAccept)
                        {
                                // Login successful
                                // Extract IP, routes, etc
                                uint8_t *p = buf + 20;
                                uint8_t *e = buf + len;
-#ifdef LAC
                                uint8_t tag;
                                uint8_t strtemp[256];
                                lac_reset_rad_tag_tunnel_ctxt();
-#endif
+
                                for (; p + 2 <= e && p[1] && p + p[1] <= e; p += p[1])
                                {
                                        if (*p == 26 && p[1] >= 7)
@@ -811,7 +775,7 @@ void processrad(uint8_t *buf, int len, char socket_index)
                                                int prefixlen;
                                                uint8_t *n = p + 2;
                                                uint8_t *e = p + p[1];
-                                               uint8_t *m = memchr(n, '/', e - p);
+                                               uint8_t *m = memchr(n, '/', e - n);
 
                                                *m++ = 0;
                                                inet_pton(AF_INET6, (char *) n, &r6);
@@ -823,11 +787,48 @@ void processrad(uint8_t *buf, int len, char socket_index)
 
                                                if (prefixlen)
                                                {
-                                                       LOG(3, s, session[s].tunnel,
-                                                               "   Radius reply contains route for %s/%d\n",
-                                                               n, prefixlen);
-                                                       session[s].ipv6route = r6;
-                                                       session[s].ipv6prefixlen = prefixlen;
+                                                       if (routes6 == MAXROUTE6)
+                                                       {
+                                                               LOG(1, s, session[s].tunnel, "   Too many IPv6 routes\n");
+                                                       }
+                                                       else
+                                                       {
+                                                               LOG(3, s, session[s].tunnel, "   Radius reply contains route for %s/%d\n", n, prefixlen);
+                                                               session[s].route6[routes6].ipv6route = r6;
+                                                               session[s].route6[routes6].ipv6prefixlen = prefixlen;
+                                                               routes6++;
+                                                       }
+                                               }
+                                       }
+                                       else if (*p == 123)
+                                       {
+                                               // Delegated-IPv6-Prefix
+                                               if ((p[1] > 4) && (p[3] > 0) && (p[3] <= 128))
+                                               {
+                                                       char ipv6addr[INET6_ADDRSTRLEN];
+
+                                                       if (routes6 == MAXROUTE6)
+                                                       {
+                                                               LOG(1, s, session[s].tunnel, "   Too many IPv6 routes\n");
+                                                       }
+                                                       else
+                                                       {
+                                                               memcpy(&session[s].route6[routes6].ipv6route, &p[4], p[1] - 4);
+                                                               session[s].route6[routes6].ipv6prefixlen = p[3];
+                                                               LOG(3, s, session[s].tunnel, "   Radius reply contains Delegated IPv6 Prefix %s/%d\n",
+                                                                       inet_ntop(AF_INET6, &session[s].route6[routes6].ipv6route, ipv6addr, INET6_ADDRSTRLEN), session[s].route6[routes6].ipv6prefixlen);
+                                                               routes6++;
+                                                       }
+                                               }
+                                       }
+                                       else if (*p == 168)
+                                       {
+                                               // Framed-IPv6-Address
+                                               if (p[1] == 18)
+                                               {
+                                                       char ipv6addr[INET6_ADDRSTRLEN];
+                                                       memcpy(&session[s].ipv6address, &p[2], 16);
+                                                       LOG(3, s, session[s].tunnel, "   Radius reply contains Framed-IPv6-Address %s\n", inet_ntop(AF_INET6, &session[s].ipv6address, ipv6addr, INET6_ADDRSTRLEN));
                                                }
                                        }
                                        else if (*p == 25)
@@ -839,7 +840,6 @@ void processrad(uint8_t *buf, int len, char socket_index)
                                                        session[s].classlen = MAXCLASS;
                                                memcpy(session[s].class, p + 2, session[s].classlen);
                                        }
-#ifdef LAC
                                        else if (*p == 64)
                                        {
                                                // Tunnel-Type
@@ -928,7 +928,6 @@ void processrad(uint8_t *buf, int len, char socket_index)
                                                // Fill context
                                                lac_set_rad_tag_tunnel_assignment_id(tag, (char *) strtemp);
                                        }
-#endif
                                }
                        }
                        else if (r_code == AccessReject)
@@ -938,7 +937,6 @@ void processrad(uint8_t *buf, int len, char socket_index)
                                break;
                        }
 
-#ifdef LAC
                        if ((!config->disable_lac_func) && OpentunnelReq)
                        {
                                char assignment_id[256];
@@ -995,7 +993,6 @@ void processrad(uint8_t *buf, int len, char socket_index)
                                LOG(3, s, session[s].tunnel, "   PAP User %s authentication %s.\n", session[s].user,
                                                (r_code == AccessAccept) ? "allowed" : "denied");
                        }
-#endif
 
                        if (!session[s].dns1 && config->default_dns1)
                        {
@@ -1340,7 +1337,6 @@ void processdae(uint8_t *buf, int len, struct sockaddr_in *addr, int alen, struc
                LOG(0, 0, 0, "Error sending DAE response packet: %s\n", strerror(errno));
 }
 
-#ifdef LAC
 // Decrypte the encrypted Tunnel Password.
 // Defined in RFC-2868.
 // the pl2tpsecret buffer must set to 256 characters.
@@ -1431,4 +1427,3 @@ int rad_tunnel_pwdecode(uint8_t *pl2tpsecret, size_t *pl2tpsecretlen,
 
        return decodedlen;
 };
-#endif /* LAC */