re-order sessiont elements to remove padding
[l2tpns.git] / l2tpns.c
index f96ac79..98f4b86 100644 (file)
--- a/l2tpns.c
+++ b/l2tpns.c
@@ -4,7 +4,7 @@
 // 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.93 2005-05-05 10:02:07 bodea Exp $";
+char const *cvs_id_l2tpns = "$Id: l2tpns.c,v 1.99 2005-05-07 13:12:25 bodea Exp $";
 
 #include <arpa/inet.h>
 #include <assert.h>
@@ -1458,20 +1458,16 @@ void sessionshutdown(sessionidt s, char *reason, int result, int error)
                // RADIUS Stop message
                uint16_t r = sess_local[s].radius;
                if (!r)
+                       r = radiusnew(s);
+
+               if (r)
                {
-                       if (!(r = radiusnew(s)))
-                       {
-                               LOG(1, s, session[s].tunnel, "No free RADIUS sessions for Stop message\n");
-                               STAT(radius_overflow);
-                       }
-                       else
-                       {
-                               random_data(radius[r].auth, sizeof(radius[r].auth));
-                       }
+                       // stop, if not already trying
+                       if (radius[r].state != RADIUSSTOP)
+                               radiussend(r, RADIUSSTOP);
                }
-
-               if (r && radius[r].state != RADIUSSTOP)
-                       radiussend(r, RADIUSSTOP); // stop, if not already trying
+               else
+                       LOG(1, s, session[s].tunnel, "No free RADIUS sessions for Stop message\n");
 
                // Save counters to dump to accounting file
                if (*config->accounting_dir && shut_acct_n < sizeof(shut_acct) / sizeof(*shut_acct))
@@ -1546,6 +1542,12 @@ void sendipcp(tunnelidt t, sessionidt s)
        if (!r)
                r = radiusnew(s);
 
+       if (!r)
+       {
+               sessionshutdown(s, "No free RADIUS sessions for IPCP", 3, 0);
+               return;
+       }
+
        if (radius[r].state != RADIUSIPCP)
        {
                radius[r].state = RADIUSIPCP;
@@ -1600,6 +1602,17 @@ void sendipcp(tunnelidt t, sessionidt s)
        }
 }
 
+static void sessionclear(sessionidt s)
+{
+       memset(&session[s], 0, sizeof(session[s]));
+       memset(&sess_local[s], 0, sizeof(sess_local[s]));
+       memset(&cli_session_actions[s], 0, sizeof(cli_session_actions[s]));
+
+       session[s].tunnel = T_FREE;     // Mark it as free.
+       session[s].next = sessionfree;
+       sessionfree = s;
+}
+
 // kill a session now
 void sessionkill(sessionidt s, char *reason)
 {
@@ -1621,12 +1634,7 @@ void sessionkill(sessionidt s, char *reason)
                radiusclear(sess_local[s].radius, s); // cant send clean accounting data, session is killed
 
        LOG(2, s, session[s].tunnel, "Kill session %d (%s): %s\n", s, session[s].user, reason);
-
-       memset(&session[s], 0, sizeof(session[s]));
-       session[s].tunnel = T_FREE;     // Mark it as free.
-       session[s].next = sessionfree;
-       sessionfree = s;
-       cli_session_actions[s].action = 0;
+       sessionclear(s);
        cluster_send_session(s);
 }
 
@@ -1793,12 +1801,11 @@ void processudp(uint8_t * buf, int len, struct sockaddr_in *addr)
                uint16_t message = 0xFFFF;      // message type
                uint8_t fatal = 0;
                uint8_t mandatory = 0;
-               uint8_t chap = 0;               // if CHAP being used
+               uint8_t authtype = 0;           // proxy auth type
                uint16_t asession = 0;          // assigned session
                uint32_t amagic = 0;            // magic number
                uint8_t aflags = 0;             // flags from last LCF
                uint16_t version = 0x0100;      // protocol version (we handle 0.0 as well and send that back just in case)
-               int requestchap = 0;            // do we request PAP instead of original CHAP request?
                char called[MAXTEL] = "";       // called number
                char calling[MAXTEL] = "";      // calling number
 
@@ -2081,14 +2088,14 @@ void processudp(uint8_t * buf, int len, struct sockaddr_in *addr)
 //                                     LOG(4, s, t, "Firmware revision\n");
                                        break;
                                case 7:     // host name
-                                       memset(tunnel[t].hostname, 0, 128);
-                                       memcpy(tunnel[t].hostname, b, (n >= 127) ? 127 : n);
+                                       memset(tunnel[t].hostname, 0, sizeof(tunnel[t].hostname));
+                                       memcpy(tunnel[t].hostname, b, (n < sizeof(tunnel[t].hostname)) ? n : sizeof(tunnel[t].hostname) - 1);
                                        LOG(4, s, t, "   Tunnel hostname = \"%s\"\n", tunnel[t].hostname);
                                        // TBA - to send to RADIUS
                                        break;
                                case 8:     // vendor name
                                        memset(tunnel[t].vendor, 0, sizeof(tunnel[t].vendor));
-                                       memcpy(tunnel[t].vendor, b, (n >= sizeof(tunnel[t].vendor) - 1) ? sizeof(tunnel[t].vendor) - 1 : n);
+                                       memcpy(tunnel[t].vendor, b, (n < sizeof(tunnel[t].vendor)) ? n : sizeof(tunnel[t].vendor) - 1);
                                        LOG(4, s, t, "   Vendor name = \"%s\"\n", tunnel[t].vendor);
                                        break;
                                case 9:     // assigned tunnel
@@ -2128,13 +2135,13 @@ void processudp(uint8_t * buf, int len, struct sockaddr_in *addr)
                                        // TBA
                                        break;
                                case 21:    // called number
-                                       memset(called, 0, MAXTEL);
-                                       memcpy(called, b, (n >= MAXTEL) ? (MAXTEL-1) : n);
+                                       memset(called, 0, sizeof(called));
+                                       memcpy(called, b, (n < sizeof(called)) ? n : sizeof(called) - 1);
                                        LOG(4, s, t, "   Called <%s>\n", called);
                                        break;
                                case 22:    // calling number
-                                       memset(calling, 0, MAXTEL);
-                                       memcpy(calling, b, (n >= MAXTEL) ? (MAXTEL-1) : n);
+                                       memset(calling, 0, sizeof(calling));
+                                       memcpy(calling, b, (n < sizeof(calling)) ? n : sizeof(calling) - 1);
                                        LOG(4, s, t, "   Calling <%s>\n", calling);
                                        break;
                                case 23:    // subtype
@@ -2147,8 +2154,9 @@ void processudp(uint8_t * buf, int len, struct sockaddr_in *addr)
                                        else
                                        {
                                                // AS5300s send connect speed as a string
-                                               char tmp[30] = {0};
-                                               memcpy(tmp, b, (n >= 30) ? 30 : n);
+                                               char tmp[30];
+                                               memset(tmp, 0, sizeof(tmp));
+                                               memcpy(tmp, b, (n < sizeof(tmp)) ? n : sizeof(tmp) - 1);
                                                session[s].tx_connect_speed = atol(tmp);
                                        }
                                        LOG(4, s, t, "   TX connect speed <%u>\n", session[s].tx_connect_speed);
@@ -2161,8 +2169,9 @@ void processudp(uint8_t * buf, int len, struct sockaddr_in *addr)
                                        else
                                        {
                                                // AS5300s send connect speed as a string
-                                               char tmp[30] = {0};
-                                               memcpy(tmp, b, (n >= 30) ? 30 : n);
+                                               char tmp[30];
+                                               memset(tmp, 0, sizeof(tmp));
+                                               memcpy(tmp, b, (n < sizeof(tmp)) ? n : sizeof(tmp) - 1);
                                                session[s].rx_connect_speed = atol(tmp);
                                        }
                                        LOG(4, s, t, "   RX connect speed <%u>\n", session[s].rx_connect_speed);
@@ -2177,13 +2186,18 @@ void processudp(uint8_t * buf, int len, struct sockaddr_in *addr)
                                        {
                                                uint16_t atype = ntohs(*(uint16_t *)b);
                                                LOG(4, s, t, "   Proxy Auth Type %d (%s)\n", atype, auth_type(atype));
-                                               requestchap = (atype == 2);
+                                               if (atype == 2)
+                                                       authtype = AUTHCHAP;
+                                               else if (atype == 3)
+                                                       authtype = AUTHPAP;
+
                                                break;
                                        }
                                case 30:    // Proxy Authentication Name
                                        {
-                                               char authname[64] = {0};
-                                               memcpy(authname, b, (n > 63) ? 63 : n);
+                                               char authname[64];
+                                               memset(authname, 0, sizeof(authname));
+                                               memcpy(authname, b, (n < sizeof(authname)) ? n : sizeof(authname) - 1);
                                                LOG(4, s, t, "   Proxy Auth Name (%s)\n",
                                                        authname);
                                                break;
@@ -2204,21 +2218,19 @@ void processudp(uint8_t * buf, int len, struct sockaddr_in *addr)
                                                break;
                                        }
                                case 33:    // Proxy Authentication Response
-                                       {
-                                               char authresp[64] = {0};
-                                               memcpy(authresp, b, (n > 63) ? 63 : n);
-                                               LOG(4, s, t, "   Proxy Auth Response\n");
-                                               break;
-                                       }
-                               case 27:    // last send lcp
+                                       LOG(4, s, t, "   Proxy Auth Response\n");
+                                       break;
+                               case 27:    // last sent lcp
                                        {        // find magic number
                                                uint8_t *p = b, *e = p + n;
                                                while (p + 1 < e && p[1] && p + p[1] <= e)
                                                {
                                                        if (*p == 5 && p[1] == 6) // Magic-Number
                                                                amagic = ntohl(*(uint32_t *) (p + 2));
-                                                       else if (*p == 3 && p[1] == 5 && *(uint16_t *) (p + 2) == htons(PPPCHAP) && p[4] == 5) // Authentication-Protocol
-                                                               chap = 1;
+                                                       else if (*p == 3 && p[1] == 4 && *(uint16_t *) (p + 2) == htons(PPPPAP)) // Authentication-Protocol (PAP)
+                                                               authtype = AUTHPAP;
+                                                       else if (*p == 3 && p[1] == 5 && *(uint16_t *) (p + 2) == htons(PPPCHAP) && p[4] == 5) // Authentication-Protocol (CHAP)
+                                                               authtype = AUTHCHAP;
                                                        else if (*p == 7) // Protocol-Field-Compression
                                                                aflags |= SESSIONPFC;
                                                        else if (*p == 8) // Address-and-Control-Field-Compression
@@ -2296,7 +2308,7 @@ void processudp(uint8_t * buf, int len, struct sockaddr_in *addr)
                                        if (!sessionfree)
                                        {
                                                STAT(session_overflow);
-                                               LOG(1, 0, t, "No free sessions");
+                                               LOG(1, 0, t, "No free sessions\n");
                                                return;
                                        }
                                        else
@@ -2315,7 +2327,7 @@ void processudp(uint8_t * buf, int len, struct sockaddr_in *addr)
                                                if (!(r = radiusnew(s)))
                                                {
                                                        LOG(1, s, t, "No free RADIUS sessions for ICRQ\n");
-                                                       sessionkill(s, "no free RADIUS sesions");
+                                                       sessionclear(s);
                                                        return;
                                                }
 
@@ -2328,8 +2340,6 @@ void processudp(uint8_t * buf, int len, struct sockaddr_in *addr)
                                                control16(c, 14, s, 1); // assigned session
                                                controladd(c, t, s); // send the reply
 
-                                               // Generate a random challenge
-                                               random_data(radius[r].auth, sizeof(radius[r].auth));
                                                strncpy(radius[r].calling, calling, sizeof(radius[r].calling) - 1);
                                                strncpy(session[s].called, called, sizeof(session[s].called) - 1);
                                                strncpy(session[s].calling, calling, sizeof(session[s].calling) - 1);
@@ -2345,9 +2355,9 @@ void processudp(uint8_t * buf, int len, struct sockaddr_in *addr)
                                        session[s].l2tp_flags = aflags; // set flags received
                                        LOG(3, s, t, "Magic %X Flags %X\n", amagic, aflags);
                                        controlnull(t); // ack
-                                       // In CHAP state, request PAP instead
-                                       if (requestchap)
-                                               initlcp(t, s);
+                                       // proxy authentication type is not supported
+                                       if (authtype && !(config->radius_authtypes & authtype))
+                                               sendlcp(t, s, config->radius_authprefer);
                                        break;
                                case 14:      // CDN
                                        controlnull(t); // ack
@@ -2741,15 +2751,13 @@ static int regular_cleanups(void)
                    && !sess_local[s].radius // RADIUS already in progress
                    && time_now - sess_local[s].last_interim >= config->radius_interim)
                {
-                       if (!radiusnew(s))
+                       if (!(r = radiusnew(s)))
                        {
                                LOG(1, s, session[s].tunnel, "No free RADIUS sessions for Interim message\n");
                                STAT(radius_overflow);
                                continue;
                        }
 
-                       random_data(radius[r].auth, sizeof(radius[r].auth));
-
                        LOG(3, s, session[s].tunnel, "Sending RADIUS Interim for %s (%u)\n",
                                session[s].user, session[s].unique_id);
 
@@ -4014,7 +4022,7 @@ static void update_config()
                else if (!strncasecmp("pap", p, strlen(p)))
                        type = AUTHPAP;
                else
-                       LOG(0, 0, 0, "Invalid RADIUS authentication type \"%s\"", p);
+                       LOG(0, 0, 0, "Invalid RADIUS authentication type \"%s\"\n", p);
 
                config->radius_authtypes |= type;
                if (!config->radius_authprefer)