Merge branch 'rfc4760' into fdn-mods
authorBenjamin Cama <benoar@dolka.fr>
Fri, 29 Jul 2011 11:04:31 +0000 (13:04 +0200)
committerBenjamin Cama <benoar@dolka.fr>
Fri, 29 Jul 2011 11:04:31 +0000 (13:04 +0200)
bgp.c
bgp.h
cli.c
etc/startup-config.default
l2tpns.c
l2tpns.h
ppp.c

diff --git a/bgp.c b/bgp.c
index 4a4bea0..600c950 100644 (file)
--- a/bgp.c
+++ b/bgp.c
@@ -101,7 +101,7 @@ int bgp_setup(int as)
 
 /* start connection with a peer */
 int bgp_start(struct bgp_peer *peer, char *name, int as, int keepalive,
-    int hold, int enable)
+    int hold, struct in_addr update_source, int enable)
 {
     struct hostent *h;
     int ibgp;
@@ -130,6 +130,7 @@ int bgp_start(struct bgp_peer *peer, char *name, int as, int keepalive,
     }
 
     memcpy(&peer->addr, h->h_addr, sizeof(peer->addr));
+    peer->source_addr = update_source.s_addr;
     peer->as = as > 0 ? as : our_as;
     ibgp = peer->as == our_as;
 
@@ -232,7 +233,14 @@ int bgp_start(struct bgp_peer *peer, char *name, int as, int keepalive,
     /* NEXT_HOP */
     a.flags = BGP_PATH_ATTR_FLAG_TRANS;
     a.code = BGP_PATH_ATTR_CODE_NEXT_HOP;
-    ip = my_address; /* we're it */
+    if (config->nexthop_address)
+    {
+       ip = config->nexthop_address;
+    }
+    else
+    {
+       ip = my_address; /* we're it */
+    }
     a.data.s.len = sizeof(ip);
     memcpy(a.data.s.value, &ip, sizeof(ip));
 
@@ -905,6 +913,7 @@ static int bgp_connect(struct bgp_peer *peer)
 {
     static int bgp_port = 0;
     struct sockaddr_in addr;
+    struct sockaddr_in source_addr;
     struct epoll_event ev;
 
     if (!bgp_port)
@@ -936,6 +945,19 @@ static int bgp_connect(struct bgp_peer *peer)
     /* set to non-blocking */
     fcntl(peer->sock, F_SETFL, fcntl(peer->sock, F_GETFL, 0) | O_NONBLOCK);
 
+    /* set source address */
+    memset(&source_addr, 0, sizeof(source_addr));
+    source_addr.sin_family = AF_INET;
+    source_addr.sin_addr.s_addr = peer->source_addr; /* defaults to INADDR_ANY */
+    if (bind(peer->sock, (struct sockaddr *) &source_addr, sizeof(source_addr)) < 0)
+    {
+       LOG(1, 0, 0, "Can't set source address to %s: %s\n",
+           inet_ntoa(source_addr.sin_addr), strerror(errno));
+
+       bgp_set_retry(peer);
+       return 0;
+    }
+
     /* try connect */
     memset(&addr, 0, sizeof(addr));
     addr.sin_family = AF_INET;
@@ -1294,7 +1316,7 @@ static int bgp_handle_input(struct bgp_peer *peer)
            if (notification->error_code == BGP_ERR_CEASE)
            {
                LOG(4, 0, 0, "BGP peer %s sent CEASE\n", peer->name);
-               bgp_restart(peer);
+               bgp_set_retry(peer);
                return 0;
            }
 
diff --git a/bgp.h b/bgp.h
index fc2e517..bf429bd 100644 (file)
--- a/bgp.h
+++ b/bgp.h
@@ -223,6 +223,7 @@ enum bgp_mp_handling {
 struct bgp_peer {
     char name[32];                     /* peer name */
     in_addr_t addr;                    /* peer address */
+    in_addr_t source_addr;             /* our source address */
     int as;                            /* AS number */
     int sock;
     enum bgp_state state;              /* FSM state */
@@ -265,7 +266,7 @@ extern int bgp_configured;
 /* actions */
 int bgp_setup(int as);
 int bgp_start(struct bgp_peer *peer, char *name, int as, int keepalive,
-    int hold, int enable);
+    int hold, struct in_addr update_source, int enable);
 
 void bgp_stop(struct bgp_peer *peer);
 void bgp_halt(struct bgp_peer *peer);
diff --git a/cli.c b/cli.c
index 7fbe3d1..9433106 100644 (file)
--- a/cli.c
+++ b/cli.c
@@ -283,6 +283,7 @@ void init_cli(char *hostname)
                fcntl(clifd, F_SETFL, flags | O_NONBLOCK);
        }
        addr.sin_family = AF_INET;
+       addr.sin_addr.s_addr = config->cli_bind_address; /* defaults to INADDR_ANY */
        addr.sin_port = htons(23);
        if (bind(clifd, (void *) &addr, sizeof(addr)) < 0)
        {
@@ -443,6 +444,14 @@ static int cmd_show_session(struct cli_def *cli, char *command, char **argv, int
                        if (session[s].idle_timeout)
                                cli_print(cli, "\tIdle Timeout:\t%u seconds", session[s].idle_timeout - (session[s].last_data ? abs(time_now - session[s].last_data) : 0));
 
+                       if (session[s].timeout)
+                       {
+                               cli_print(cli, "\tRemaining time:\t%u",
+                                       (session[s].bundle && bundle[session[s].bundle].num_of_links > 1)
+                                       ? (unsigned) (session[s].timeout - bundle[session[s].bundle].online_time)
+                                       : (unsigned) (session[s].timeout - (time_now - session[s].opened)));
+                       }
+
                        cli_print(cli, "\tBytes In/Out:\t%u/%u", session[s].cout, session[s].cin);
                        cli_print(cli, "\tPkts In/Out:\t%u/%u", session[s].pout, session[s].pin);
                        cli_print(cli, "\tMRU:\t\t%d", session[s].mru);
@@ -510,7 +519,7 @@ static int cmd_show_session(struct cli_def *cli, char *command, char **argv, int
        }
 
        // Show Summary
-       cli_print(cli, "%5s %4s %-32s %-15s %s %s %s %s %10s %10s %10s %4s %-15s %s",
+       cli_print(cli, "%5s %4s %-32s %-15s %s %s %s %s %10s %10s %10s %4s %10s %-15s %s",
                        "SID",
                        "TID",
                        "Username",
@@ -523,13 +532,20 @@ static int cmd_show_session(struct cli_def *cli, char *command, char **argv, int
                        "downloaded",
                        "uploaded",
                        "idle",
+                       "Rem.Time",
                        "LAC",
                        "CLI");
 
        for (i = 1; i < MAXSESSION; i++)
        {
+               uint32_t rem_time;
                if (!session[i].opened) continue;
-               cli_print(cli, "%5d %4d %-32s %-15s %s %s %s %s %10u %10lu %10lu %4u %-15s %s",
+               if (session[i].bundle && bundle[session[i].bundle].num_of_links > 1)
+                       rem_time = session[i].timeout ? (session[i].timeout - bundle[session[i].bundle].online_time) : 0;
+               else
+                       rem_time = session[i].timeout ? (session[i].timeout - (time_now-session[i].opened)) : 0;
+
+               cli_print(cli, "%5d %4d %-32s %-15s %s %s %s %s %10u %10lu %10lu %4u %10lu %-15s %s",
                                i,
                                session[i].tunnel,
                                session[i].user[0] ? session[i].user : "*",
@@ -542,6 +558,7 @@ static int cmd_show_session(struct cli_def *cli, char *command, char **argv, int
                                (unsigned long)session[i].cout,
                                (unsigned long)session[i].cin,
                                abs(time_now - (session[i].last_packet ? session[i].last_packet : time_now)),
+                               (unsigned long)(rem_time),
                                fmtaddr(htonl(tunnel[ session[i].tunnel ].ip), 1),
                                session[i].calling[0] ? session[i].calling : "*");
        }
@@ -1022,6 +1039,11 @@ static int cmd_show_run(struct cli_def *cli, char *command, char **argv, int arg
                                h = BGP_HOLD_TIME;
 
                        cli_print(cli, " neighbour %s timers %d %d", config->neighbour[i].name, k, h);
+
+                       if (config->neighbour[i].update_source.s_addr != INADDR_ANY)
+                               cli_print(cli, " neighbour %s update-source %s",
+                                               config->neighbour[i].name,
+                                               inet_ntoa(config->neighbour[i].update_source));
                }
        }
 #endif
@@ -2048,6 +2070,7 @@ static int cmd_router_bgp_neighbour(struct cli_def *cli, char *command, char **a
                        return cli_arg_help(cli, 0,
                                "remote-as", "Set remote autonomous system number",
                                "timers",    "Set timers",
+                               "update-source",    "Set source address to use for the BGP session",
                                NULL);
 
                default:
@@ -2066,6 +2089,9 @@ static int cmd_router_bgp_neighbour(struct cli_def *cli, char *command, char **a
                                        return cli_arg_help(cli, 1, NULL);
                        }
 
+                       if (MATCH("update-source", argv[1]))
+                               return cli_arg_help(cli, argc > 3, "A.B.C.D", "Source IP address", NULL);
+
                        return CLI_OK;
                }
        }
@@ -2102,12 +2128,33 @@ static int cmd_router_bgp_neighbour(struct cli_def *cli, char *command, char **a
                        snprintf(config->neighbour[i].name, sizeof(config->neighbour[i].name), "%s", argv[0]);
                        config->neighbour[i].keepalive = -1;
                        config->neighbour[i].hold = -1;
+                       config->neighbour[i].update_source.s_addr = INADDR_ANY;
                }
 
                config->neighbour[i].as = as;
                return CLI_OK;
        }
 
+       if (MATCH("update-source", argv[1]))
+       {
+               struct in_addr addr;
+
+               if (!config->neighbour[i].name[0])
+               {
+                       cli_error(cli, "Specify remote-as first");
+                       return CLI_OK;
+               }
+
+               if (!inet_aton(argv[2], &addr))
+               {
+                       cli_error(cli, "Cannot parse IP \"%s\"", argv[2]);
+                       return CLI_OK;
+               }
+
+               config->neighbour[i].update_source = addr;
+               return CLI_OK;
+       }
+
        if (argc != 4 || !MATCH("timers", argv[1]))
        {
                cli_error(cli, "Invalid arguments");
index 4a3ac84..f86e2aa 100644 (file)
@@ -7,6 +7,9 @@ set log_file "/var/log/l2tpns"
 # Write pid to this file
 set pid_file "/var/run/l2tpns.pid"
 
+# This host name, if different from the OS one
+#set hostname "localhost"
+
 # Shared secret with LAC
 set l2tp_secret "secret"
 
@@ -53,6 +56,9 @@ set accounting_dir "/var/run/l2tpns/acct"
 # Listen address for L2TP
 #set bind_address 1.1.1.1
 
+# Listen address for CLI
+#set cli_bind_address 127.0.0.1
+
 # Send a gratiuitous ARP for bind address
 #set send_garp no
 
index 6a4656e..61b2184 100644 (file)
--- a/l2tpns.c
+++ b/l2tpns.c
@@ -69,7 +69,7 @@ int rand_fd = -1;             // Random data source
 int cluster_sockfd = -1;       // Intra-cluster communications socket.
 int epollfd = -1;              // event polling
 time_t basetime = 0;           // base clock
-char hostname[1000] = "";      // us.
+char hostname[MAXHOSTNAME] = "";       // us.
 static int tunidx;             // ifr_ifindex of tun device
 static int syslog_log = 0;     // are we logging to syslog
 static FILE *log_stream = 0;   // file handle for direct logging (i.e. direct into file, not via syslog).
@@ -157,6 +157,9 @@ config_descriptt config_values[] = {
        CONFIG("cluster_hb_timeout", cluster_hb_timeout, INT),
        CONFIG("cluster_master_min_adv", cluster_master_min_adv, INT),
        CONFIG("ipv6_prefix", ipv6_prefix, IPv6),
+       CONFIG("cli_bind_address", cli_bind_address, IPv4),
+       CONFIG("hostname", hostname, STRING),
+       CONFIG("nexthop_address", nexthop_address, IPv4),
        CONFIG("nexthop6_address", nexthop6_address, IPv6),
        { NULL, 0, 0, 0 },
 };
@@ -165,8 +168,6 @@ static char *plugin_functions[] = {
        NULL,
        "plugin_pre_auth",
        "plugin_post_auth",
-       "plugin_packet_rx",
-       "plugin_packet_tx",
        "plugin_timer",
        "plugin_new_session",
        "plugin_kill_session",
@@ -3403,35 +3404,36 @@ static int still_busy(void)
        static clockt last_talked = 0;
        static clockt start_busy_wait = 0;
 
-       if (!config->cluster_iam_master)
-       {
 #ifdef BGP
-               static time_t stopped_bgp = 0;
-               if (bgp_configured)
+       static time_t stopped_bgp = 0;
+       if (bgp_configured)
+       {
+               if (!stopped_bgp)
                {
-                       if (!stopped_bgp)
-                       {
-                               LOG(1, 0, 0, "Shutting down in %d seconds, stopping BGP...\n", QUIT_DELAY);
+                       LOG(1, 0, 0, "Shutting down in %d seconds, stopping BGP...\n", QUIT_DELAY);
 
-                               for (i = 0; i < BGP_NUM_PEERS; i++)
-                                       if (bgp_peers[i].state == Established)
-                                               bgp_stop(&bgp_peers[i]);
+                       for (i = 0; i < BGP_NUM_PEERS; i++)
+                               if (bgp_peers[i].state == Established)
+                                       bgp_stop(&bgp_peers[i]);
 
-                               stopped_bgp = time_now;
+                       stopped_bgp = time_now;
 
+                       if (!config->cluster_iam_master)
+                       {
                                // we don't want to become master
                                cluster_send_ping(0);
 
                                return 1;
                        }
-
-                       if (time_now < (stopped_bgp + QUIT_DELAY))
-                               return 1;
                }
+
+               if (!config->cluster_iam_master && time_now < (stopped_bgp + QUIT_DELAY))
+                       return 1;
+       }
 #endif /* BGP */
 
+       if (!config->cluster_iam_master)
                return 0;
-       }
 
        if (main_quit == QUIT_SHUTDOWN)
        {
@@ -3572,7 +3574,8 @@ static void mainloop(void)
                if (config->neighbour[i].name[0])
                        bgp_start(&bgp_peers[i], config->neighbour[i].name,
                                config->neighbour[i].as, config->neighbour[i].keepalive,
-                               config->neighbour[i].hold, 0); /* 0 = routing disabled */
+                               config->neighbour[i].hold, config->neighbour[i].update_source,
+                               0); /* 0 = routing disabled */
        }
 #endif /* BGP */
 
@@ -4073,9 +4076,14 @@ static void initdata(int optdebug, char *optconfig)
 
        if (!*hostname)
        {
-               // Grab my hostname unless it's been specified
-               gethostname(hostname, sizeof(hostname));
-               stripdomain(hostname);
+               if (!*config->hostname)
+               {
+                       // Grab my hostname unless it's been specified
+                       gethostname(hostname, sizeof(hostname));
+                       stripdomain(hostname);
+               }
+               else
+                       strcpy(hostname, config->hostname);
        }
 
        _statistics->start_time = _statistics->last_reset = time(NULL);
index 55de73f..4f7fad9 100644 (file)
--- a/l2tpns.h
+++ b/l2tpns.h
@@ -38,6 +38,7 @@
 #define PPPoE_MRU      1492            // maximum PPPoE MRU (rfc2516: 1500 less PPPoE header (6) and PPP protocol ID (2))
 #define MAXETHER       (MAXMTU+18)     // max packet we try sending to tun
 #define MAXTEL         96              // telephone number
+#define MAXHOSTNAME    256             // hostname
 #define MAXUSER                128             // username
 #define MAXPASS                128             // password
 #define MAXPLUGINS     20              // maximum number of plugins to load
@@ -712,6 +713,8 @@ typedef struct
 
        int             cluster_master_min_adv;         // Master advertises routes while the number of up to date
                                                        // slaves is less than this value.
+       in_addr_t       cli_bind_address;               // bind address for CLI
+       char            hostname[MAXHOSTNAME];  // hostname (overridden by -h on command line)
        // Guest change
        char            guest_user[MAXUSER];            // Guest account username
 
@@ -723,7 +726,9 @@ typedef struct
                uint16_t as;
                int keepalive;
                int hold;
+               struct in_addr update_source;
        } neighbour[BGP_NUM_PEERS];
+       in_addr_t       nexthop_address;
        struct in6_addr nexthop6_address;
 #endif
 } configt;
diff --git a/ppp.c b/ppp.c
index 7942e6e..7be79ce 100644 (file)
--- a/ppp.c
+++ b/ppp.c
@@ -821,6 +821,10 @@ void processlcp(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l)
 
                        break;
 
+               case Closing:
+                       sessionshutdown(s, "LCP: ConfigReq in state Closing. This should not happen. Killing session.", CDN_ADMIN_DISC, TERM_LOST_SERVICE);
+                       break;
+
                default:
                        LOG(2, s, t, "LCP: ignoring %s in state %s\n", ppp_code(*p), ppp_state(session[s].ppp.lcp));
                        return;