X-Git-Url: http://git.sameswireless.fr/l2tpns.git/blobdiff_plain/c266121a2c5e1b073dcf26c1ab64bd7b5febe4f3..52cb7687d356002adccc46d0f5d690267442bc99:/l2tpns.c diff --git a/l2tpns.c b/l2tpns.c index ae7d2e4..9e9b34a 100644 --- 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.97 2005/05/07 08:53:23 bodea Exp $"; +char const *cvs_id_l2tpns = "$Id: l2tpns.c,v 1.103 2005/05/13 01:29:40 bodea Exp $"; #include #include @@ -1323,11 +1323,11 @@ static void controlnull(tunnelidt t) } // add a control message to a tunnel, and send if within window -static void controladd(controlt * c, tunnelidt t, sessionidt s) +static void controladd(controlt * c, tunnelidt t, sessionidt far) { *(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(s ? session[s].far : 0); // session + *(uint16_t *) (c->buf + 6) = htons(far); // session *(uint16_t *) (c->buf + 8) = htons(tunnel[t].ns); // sequence tunnel[t].ns++; // advance sequence // link in message in to queue @@ -1518,7 +1518,7 @@ void sessionshutdown(sessionidt s, char *reason, int result, int error) control16(c, 1, result, 1); control16(c, 14, s, 1); // assigned session (our end) - controladd(c, session[s].tunnel, s); // send the message + controladd(c, session[s].tunnel, session[s].far); // send the message } if (!session[s].die) @@ -1801,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 @@ -2187,7 +2186,11 @@ 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 @@ -2224,8 +2227,10 @@ void processudp(uint8_t * buf, int len, struct sockaddr_in *addr) { 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 @@ -2272,7 +2277,7 @@ void processudp(uint8_t * buf, int len, struct sockaddr_in *addr) controls(c, 7, tunnel[t].hostname, 1); // host name (TBA) if (chapresponse) controlb(c, 13, chapresponse, 16, 1); // Challenge response control16(c, 9, t, 1); // assigned tunnel - controladd(c, t, s); // send the resply + controladd(c, t, 0); // send the resply } tunnel[t].state = TUNNELOPENING; break; @@ -2300,16 +2305,9 @@ void processudp(uint8_t * buf, int len, struct sockaddr_in *addr) // TBA break; case 10: // ICRQ - if (!sessionfree) - { - STAT(session_overflow); - LOG(1, 0, t, "No free sessions\n"); - return; - } - else + if (sessionfree) { uint16_t r; - controlt *c; s = sessionfree; sessionfree = session[s].next; @@ -2319,28 +2317,40 @@ void processudp(uint8_t * buf, int len, struct sockaddr_in *addr) config->cluster_highest_sessionid = s; // make a RADIUS session - if (!(r = radiusnew(s))) + if ((r = radiusnew(s))) { - LOG(1, s, t, "No free RADIUS sessions for ICRQ\n"); - sessionclear(s); - return; + controlt *c = controlnew(11); // sending ICRP + session[s].opened = time_now; + session[s].tunnel = t; + session[s].far = asession; + session[s].last_packet = time_now; + LOG(3, s, t, "New session (%d/%d)\n", tunnel[t].far, session[s].far); + control16(c, 14, s, 1); // assigned session + controladd(c, t, asession); // send the reply + + 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); + STAT(session_created); + break; } - c = controlnew(11); // sending ICRP - session[s].opened = time_now; - session[s].tunnel = t; - session[s].far = asession; - session[s].last_packet = time_now; - LOG(3, s, t, "New session (%d/%d)\n", tunnel[t].far, session[s].far); - control16(c, 14, s, 1); // assigned session - controladd(c, t, s); // send the reply - - 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); - STAT(session_created); + + LOG(1, s, t, "No free RADIUS sessions for ICRQ\n"); + sessionclear(s); } - break; + else + { + STAT(session_overflow); + LOG(1, 0, t, "No free sessions\n"); + } + + { + controlt *c = controlnew(14); // CDN + control16(c, 1, 4, 1); // temporary lack of resources + controladd(c, session[s].tunnel, asession); // send the message + } + return; case 11: // ICRP // TBA break; @@ -2350,9 +2360,12 @@ 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 (!(config->radius_authtypes & authtype)) + authtype = config->radius_authprefer; + + // start LCP + sendlcp(t, s, authtype); break; case 14: // CDN controlnull(t); // ack @@ -3983,7 +3996,7 @@ static void update_config() // test twice, In case someone works with // a secondary radius server without defining // a primary one, this will work even then. - if (i>0 && !config->radiusport[i]) + if (i > 0 && !config->radiusport[i]) config->radiusport[i] = config->radiusport[i-1]; if (!config->radiusport[i]) config->radiusport[i] = RADPORT; @@ -3997,7 +4010,7 @@ static void update_config() // parse radius_authtypes_s config->radius_authtypes = config->radius_authprefer = 0; p = config->radius_authtypes_s; - while (*p) + while (p && *p) { char *s = strpbrk(p, " \t,"); int type = 0; @@ -4022,6 +4035,8 @@ static void update_config() config->radius_authtypes |= type; if (!config->radius_authprefer) config->radius_authprefer = type; + + p = s; } if (!config->radius_authtypes) @@ -4421,6 +4436,7 @@ static int add_plugin(char *plugin_name) radiusnew, radiussend, getconfig, + sessionshutdown, sessionkill, throttle_session, cluster_send_session,