add radius_bind_{min,max} options
[l2tpns.git] / l2tpns.c
index 60fc7c8..d70786b 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.167 2006/06/11 12:46:18 bodea Exp $";
+char const *cvs_id_l2tpns = "$Id: l2tpns.c,v 1.169 2006/07/01 12:40:17 bodea Exp $";
 
 #include <arpa/inet.h>
 #include <assert.h>
@@ -126,6 +126,8 @@ config_descriptt config_values[] = {
        CONFIG("radius_secret", radiussecret, STRING),
        CONFIG("radius_authtypes", radius_authtypes_s, STRING),
        CONFIG("radius_dae_port", radius_dae_port, SHORT),
+       CONFIG("radius_bind_min", radius_bind_min, SHORT),
+       CONFIG("radius_bind_max", radius_bind_max, SHORT),
        CONFIG("allow_duplicate_users", allow_duplicate_users, BOOL),
        CONFIG("guest_account", guest_user, STRING),
        CONFIG("bind_address", bind_address, IPv4),
@@ -625,7 +627,7 @@ static void initudp(void)
                int flags = fcntl(udpfd, F_GETFL, 0);
                fcntl(udpfd, F_SETFL, flags | O_NONBLOCK);
        }
-       if (bind(udpfd, (void *) &addr, sizeof(addr)) < 0)
+       if (bind(udpfd, (struct sockaddr *) &addr, sizeof(addr)) < 0)
        {
                LOG(0, 0, 0, "Error in UDP bind: %s\n", strerror(errno));
                exit(1);
@@ -638,7 +640,7 @@ static void initudp(void)
        controlfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
        setsockopt(controlfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
        setsockopt(controlfd, SOL_IP, IP_PKTINFO, &on, sizeof(on)); // recvfromto
-       if (bind(controlfd, (void *) &addr, sizeof(addr)) < 0)
+       if (bind(controlfd, (struct sockaddr *) &addr, sizeof(addr)) < 0)
        {
                LOG(0, 0, 0, "Error in control bind: %s\n", strerror(errno));
                exit(1);
@@ -651,7 +653,7 @@ static void initudp(void)
        daefd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
        setsockopt(daefd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
        setsockopt(daefd, SOL_IP, IP_PKTINFO, &on, sizeof(on)); // recvfromto
-       if (bind(daefd, (void *) &addr, sizeof(addr)) < 0)
+       if (bind(daefd, (struct sockaddr *) &addr, sizeof(addr)) < 0)
        {
                LOG(0, 0, 0, "Error in DAE bind: %s\n", strerror(errno));
                exit(1);
@@ -2184,9 +2186,10 @@ void processudp(uint8_t *buf, int len, struct sockaddr_in *addr)
                        int error = 0;
                        char *msg = 0;
 
-                       // default disconnect cause/message on receipt
-                       // of CDN (set to more specific value from
-                       // attribute 46 if present below).
+                       // Default disconnect cause/message on receipt of CDN.  Set to
+                       // more specific value from attribute 1 (result code) or 46
+                       // (disconnect cause) if present below.
+                       int disc_cause_set = 0;
                        int disc_cause = TERM_NAS_REQUEST;
                        char const *disc_reason = "Closed (Received CDN).";
 
@@ -2296,25 +2299,41 @@ void processudp(uint8_t *buf, int len, struct sockaddr_in *addr)
                                case 1:     // result code
                                        {
                                                uint16_t rescode = ntohs(*(uint16_t *) b);
-                                               const char* resdesc = "(unknown)";
+                                               char const *resdesc = "(unknown)";
+                                               char const *errdesc = NULL;
+                                               int cause = 0;
+
                                                if (message == 4)
                                                { /* StopCCN */
                                                        resdesc = l2tp_stopccn_result_code(rescode);
+                                                       cause = TERM_LOST_SERVICE;
                                                }
                                                else if (message == 14)
                                                { /* CDN */
                                                        resdesc = l2tp_cdn_result_code(rescode);
+                                                       if (rescode == 1)
+                                                               cause = TERM_LOST_CARRIER;
+                                                       else
+                                                               cause = TERM_ADMIN_RESET;
                                                }
 
                                                LOG(4, s, t, "   Result Code %u: %s\n", rescode, resdesc);
                                                if (n >= 4)
                                                {
                                                        uint16_t errcode = ntohs(*(uint16_t *)(b + 2));
-                                                       LOG(4, s, t, "   Error Code %u: %s\n", errcode, l2tp_error_code(errcode));
+                                                       errdesc = l2tp_error_code(errcode);
+                                                       LOG(4, s, t, "   Error Code %u: %s\n", errcode, errdesc);
                                                }
                                                if (n > 4)
                                                        LOG(4, s, t, "   Error String: %.*s\n", n-4, b+4);
 
+                                               if (cause && disc_cause_set < mtype) // take cause from attrib 46 in preference
+                                               {
+                                                       disc_cause_set = mtype;
+                                                       disc_reason = errdesc ? errdesc : resdesc;
+                                                       disc_cause = cause;
+                                               }
+
                                                break;
                                        }
                                        break;
@@ -2506,6 +2525,8 @@ void processudp(uint8_t *buf, int len, struct sockaddr_in *addr)
                                                        "(code=%u, proto=%04X, dir=%u, msg=\"%.*s\")\n",
                                                        code, proto, dir, n - 5, b + 5);
 
+                                               disc_cause_set = mtype;
+
                                                switch (code)
                                                {
                                                case 1: // admin disconnect