- Add support for LCP Ident and CallBack (rejection only) from Yuri
[l2tpns.git] / l2tpns.c
index c3443bd..8571762 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
 
 // 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.13 2004/07/11 07:57:35 bodea Exp $";
+char const *cvs_id_l2tpns = "$Id: l2tpns.c,v 1.20 2004/08/02 05:40:21 fred_nerk Exp $";
 
 #include <arpa/inet.h>
 #include <assert.h>
 
 #include <arpa/inet.h>
 #include <assert.h>
@@ -94,12 +94,15 @@ int bgp_configured = 0;
 struct config_descriptt config_values[] = {
        CONFIG("debug", debug, INT),
        CONFIG("log_file", log_filename, STRING),
 struct config_descriptt config_values[] = {
        CONFIG("debug", debug, INT),
        CONFIG("log_file", log_filename, STRING),
+       CONFIG("pid_file", pid_file, STRING),
        CONFIG("l2tp_secret", l2tpsecret, STRING),
        CONFIG("primary_dns", default_dns1, IP),
        CONFIG("secondary_dns", default_dns2, IP),
        CONFIG("save_state", save_state, BOOL),
        CONFIG("primary_radius", radiusserver[0], IP),
        CONFIG("secondary_radius", radiusserver[1], IP),
        CONFIG("l2tp_secret", l2tpsecret, STRING),
        CONFIG("primary_dns", default_dns1, IP),
        CONFIG("secondary_dns", default_dns2, IP),
        CONFIG("save_state", save_state, BOOL),
        CONFIG("primary_radius", radiusserver[0], IP),
        CONFIG("secondary_radius", radiusserver[1], IP),
+       CONFIG("primary_radius_port",radiusport[0], SHORT),
+       CONFIG("secondary_radius_port",radiusport[1], SHORT),
        CONFIG("radius_accounting", radius_accounting, BOOL),
        CONFIG("radius_secret", radiussecret, STRING),
        CONFIG("bind_address", bind_address, IP),
        CONFIG("radius_accounting", radius_accounting, BOOL),
        CONFIG("radius_secret", radiussecret, STRING),
        CONFIG("bind_address", bind_address, IP),
@@ -111,6 +114,7 @@ struct config_descriptt config_values[] = {
        CONFIG("cleanup_interval", cleanup_interval, INT),
        CONFIG("multi_read_count", multi_read_count, INT),
        CONFIG("scheduler_fifo", scheduler_fifo, BOOL),
        CONFIG("cleanup_interval", cleanup_interval, INT),
        CONFIG("multi_read_count", multi_read_count, INT),
        CONFIG("scheduler_fifo", scheduler_fifo, BOOL),
+       CONFIG("lock_pages", lock_pages, BOOL),
        CONFIG("icmp_rate", icmp_rate, INT),
        CONFIG("cluster_address", cluster_address, IP),
        CONFIG("cluster_interface", cluster_interface, STRING),
        CONFIG("icmp_rate", icmp_rate, INT),
        CONFIG("cluster_address", cluster_address, IP),
        CONFIG("cluster_interface", cluster_interface, STRING),
@@ -143,10 +147,10 @@ char *plugin_functions[] = {
 
 #define max_plugin_functions (sizeof(plugin_functions) / sizeof(char *))
 
 
 #define max_plugin_functions (sizeof(plugin_functions) / sizeof(char *))
 
-tunnelt *tunnel = NULL;                // Array of tunnel structures.
-sessiont *session = NULL;      // Array of session structures.
+tunnelt *tunnel = NULL;                        // Array of tunnel structures.
+sessiont *session = NULL;              // Array of session structures.
 sessioncountt *sess_count = NULL;      // Array of partial per-session traffic counters.
 sessioncountt *sess_count = NULL;      // Array of partial per-session traffic counters.
-radiust *radius = NULL;                // Array of radius structures.
+radiust *radius = NULL;                        // Array of radius structures.
 ippoolt *ip_address_pool = NULL;       // Array of dynamic IP addresses.
 controlt *controlfree = 0;
 struct Tstats *_statistics = NULL;
 ippoolt *ip_address_pool = NULL;       // Array of dynamic IP addresses.
 controlt *controlfree = 0;
 struct Tstats *_statistics = NULL;
@@ -1111,7 +1115,7 @@ void sendipcp(tunnelidt t, sessionidt s)
        *(u16 *) (q + 2) = htons(10);
        q[4] = 3;
        q[5] = 6;
        *(u16 *) (q + 2) = htons(10);
        q[4] = 3;
        q[5] = 6;
-       *(u32 *) (q + 6) = config->bind_address; // send my IP
+       *(u32 *) (q + 6) = config->bind_address ? config->bind_address : my_address; // send my IP
        tunnelsend(buf, 10 + (q - buf), t); // send it
        session[s].flags &= ~SF_IPCP_ACKED;     // Clear flag.
 }
        tunnelsend(buf, 10 + (q - buf), t); // send it
        session[s].flags &= ~SF_IPCP_ACKED;     // Clear flag.
 }
@@ -1556,6 +1560,8 @@ void processudp(u8 * buf, int len, struct sockaddr_in *addr)
                                        memcpy(calling, b, (n >= MAXTEL) ? (MAXTEL-1) : n);
                                        log(4, ntohl(addr->sin_addr.s_addr), s, t, "   Calling <%s>\n", calling);
                                        break;
                                        memcpy(calling, b, (n >= MAXTEL) ? (MAXTEL-1) : n);
                                        log(4, ntohl(addr->sin_addr.s_addr), s, t, "   Calling <%s>\n", calling);
                                        break;
+                               case 23:    // subtype
+                                       break;
                                case 24:    // tx connect speed
                                        if (n == 4)
                                        {
                                case 24:    // tx connect speed
                                        if (n == 4)
                                        {
@@ -2029,7 +2035,7 @@ int regular_cleanups(void)
                if (!session[s].tunnel) // Session isn't in use
                        continue;
 
                if (!session[s].tunnel) // Session isn't in use
                        continue;
 
-               if (!session[s].die && session[s].ip && !(session[s].flags & SF_IPCP_ACKED) )
+               if (!session[s].die && session[s].ip && !(session[s].flags & SF_IPCP_ACKED))
                {
                        // IPCP has not completed yet. Resend
                        log(3, session[s].ip, s, session[s].tunnel, "No ACK for initial IPCP ConfigReq... resending\n");
                {
                        // IPCP has not completed yet. Resend
                        log(3, session[s].ip, s, session[s].tunnel, "No ACK for initial IPCP ConfigReq... resending\n");
@@ -2836,6 +2842,7 @@ void dump_acct_info()
 int main(int argc, char *argv[])
 {
        int o;
 int main(int argc, char *argv[])
 {
        int o;
+       int optdebug = 0;
 
        _program_name = strdup(argv[0]);
 
 
        _program_name = strdup(argv[0]);
 
@@ -2852,7 +2859,7 @@ int main(int argc, char *argv[])
                                if (fork()) exit(0);
                                break;
                        case 'v':
                                if (fork()) exit(0);
                                break;
                        case 'v':
-                               config->debug++;
+                               optdebug++;
                                break;
                        case 'h':
                                snprintf(hostname, sizeof(hostname), "%s", optarg);
                                break;
                        case 'h':
                                snprintf(hostname, sizeof(hostname), "%s", optarg);
@@ -2880,6 +2887,9 @@ int main(int argc, char *argv[])
        initiptables();
        initplugins();
        initdata();
        initiptables();
        initplugins();
        initdata();
+
+       config->debug = optdebug;
+
        init_tbf();
        init_cli(hostname);
        read_config_file();
        init_tbf();
        init_cli(hostname);
        read_config_file();
@@ -2955,6 +2965,15 @@ int main(int argc, char *argv[])
        signal(SIGQUIT, sigquit_handler);
        signal(SIGCHLD, sigchild_handler);
 
        signal(SIGQUIT, sigquit_handler);
        signal(SIGCHLD, sigchild_handler);
 
+       // Prevent us from getting paged out
+       if (config->lock_pages)
+       {
+               if (!mlockall(MCL_CURRENT))
+                       log(1, 0, 0, 0, "Locking pages into memory\n");
+               else
+                       log(0, 0, 0, 0, "Can't lock pages: %s\n", strerror(errno));
+       }
+
        alarm(1);
 
        // Drop privileges here
        alarm(1);
 
        // Drop privileges here
@@ -2977,6 +2996,10 @@ int main(int argc, char *argv[])
        /* remove plugins (so cleanup code gets run) */
        plugins_done();
 
        /* remove plugins (so cleanup code gets run) */
        plugins_done();
 
+       // Remove the PID file if we wrote it
+       if (config->wrote_pid && *config->pid_file == '/')
+               unlink(config->pid_file);
+
        /* kill CLI children */
        signal(SIGTERM, SIG_IGN);
        kill(0, SIGTERM);
        /* kill CLI children */
        signal(SIGTERM, SIG_IGN);
        kill(0, SIGTERM);
@@ -3311,7 +3334,21 @@ void update_config()
        // Update radius
        config->numradiusservers = 0;
        for (i = 0; i < MAXRADSERVER; i++)
        // Update radius
        config->numradiusservers = 0;
        for (i = 0; i < MAXRADSERVER; i++)
-               if (config->radiusserver[i]) config->numradiusservers++;
+               if (config->radiusserver[i])
+               {
+                       config->numradiusservers++;
+                       // Set radius port: if not set, take the port from the
+                       // first radius server.  For the first radius server,
+                       // take the #defined default value from l2tpns.h
+
+                       // 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])
+                               config->radiusport[i] = config->radiusport[i-1];
+                       if (!config->radiusport[i])
+                               config->radiusport[i] = RADPORT;
+               }
 
        if (!config->numradiusservers)
        {
 
        if (!config->numradiusservers)
        {
@@ -3369,6 +3406,22 @@ void update_config()
                timeout = config->cluster_hb_timeout;
        }
 
                timeout = config->cluster_hb_timeout;
        }
 
+       // Write PID file
+       if (*config->pid_file == '/' && !config->wrote_pid)
+       {
+               FILE *f;
+               if ((f = fopen(config->pid_file, "w")))
+               {
+                       fprintf(f, "%d\n", getpid());
+                       fclose(f);
+                       config->wrote_pid = 1;
+               }
+               else
+               {
+                       log(0, 0, 0, 0, "Can't write to PID file %s: %s\n", config->pid_file, strerror(errno));
+               }
+       }
+
        config->reload_config = 0;
 }
 
        config->reload_config = 0;
 }
 
@@ -3444,7 +3497,9 @@ int sessionsetup(tunnelidt t, sessionidt s)
        for (r = 0; r < MAXROUTE && session[s].route[r].ip; r++)
                routeset(s, session[s].route[r].ip, session[s].route[r].mask, session[s].ip, 1);
 
        for (r = 0; r < MAXROUTE && session[s].route[r].ip; r++)
                routeset(s, session[s].route[r].ip, session[s].route[r].mask, session[s].ip, 1);
 
-       if (!session[s].sid) {  // did this session just finish radius?
+       if (!session[s].sid)
+       {
+               // did this session just finish radius?
                log(3, session[s].ip, s, t, "Sending initial IPCP to client\n");
                sendipcp(t, s);
                session[s].sid = ++last_sid;
                log(3, session[s].ip, s, t, "Sending initial IPCP to client\n");
                sendipcp(t, s);
                session[s].sid = ++last_sid;