X-Git-Url: http://git.sameswireless.fr/l2tpns.git/blobdiff_plain/7d193dfb51ba1e81499985d23e5880740401bf39..b866448a74e526665477b5ea055ba4e970852b2f:/l2tpns.c diff --git a/l2tpns.c b/l2tpns.c index a55854a..db73793 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.73.2.6 2005/04/01 06:37:19 bodea Exp $"; +char const *cvs_id_l2tpns = "$Id: l2tpns.c,v 1.73.2.11 2005/05/30 02:55:41 bodea Exp $"; #include #include @@ -83,7 +83,7 @@ uint32_t eth_tx = 0; static uint32_t ip_pool_size = 1; // Size of the pool of addresses used for dynamic address allocation. time_t time_now = 0; // Current time in seconds since epoch. static char time_now_string[64] = {0}; // Current time as a string. -static char main_quit = 0; // True if we're in the process of exiting. +char main_quit = 0; // True if we're in the process of exiting. linked_list *loaded_plugins; linked_list *plugins[MAX_PLUGIN_TYPES]; @@ -113,6 +113,7 @@ config_descriptt config_values[] = { CONFIG("setuid", target_uid, INT), CONFIG("dump_speed", dump_speed, BOOL), CONFIG("cleanup_interval", cleanup_interval, INT), + CONFIG("cleanup_limit", cleanup_limit, INT), CONFIG("multi_read_count", multi_read_count, INT), CONFIG("scheduler_fifo", scheduler_fifo, BOOL), CONFIG("lock_pages", lock_pages, BOOL), @@ -122,6 +123,7 @@ config_descriptt config_values[] = { CONFIG("cluster_interface", cluster_interface, STRING), CONFIG("cluster_hb_interval", cluster_hb_interval, INT), CONFIG("cluster_hb_timeout", cluster_hb_timeout, INT), + CONFIG("cluster_master_min_adv", cluster_master_min_adv, INT), { NULL, 0, 0, 0 }, }; @@ -180,6 +182,9 @@ static void processcontrol(uint8_t *buf, int len, struct sockaddr_in *addr, int static tunnelidt new_tunnel(void); static int unhide_avp(uint8_t *avp, tunnelidt t, sessionidt s, uint16_t length); +// on slaves, alow BGP to withdraw cleanly before exiting +#define QUIT_DELAY 5 + // return internal time (10ths since process startup) static clockt now(void) { @@ -1117,7 +1122,6 @@ void sessionshutdown(sessionidt s, char *reason) if (!(r = radiusnew(s))) { LOG(1, s, session[s].tunnel, "No free RADIUS sessions for Stop message\n"); - STAT(radius_overflow); } else { @@ -1189,6 +1193,12 @@ void sendipcp(tunnelidt t, sessionidt s) if (!r) r = radiusnew(s); + if (!r) + { + sessionshutdown(s, "No free RADIUS sessions for IPCP"); + return; + } + if (radius[r].state != RADIUSIPCP) { radius[r].state = RADIUSIPCP; @@ -1207,7 +1217,7 @@ void sendipcp(tunnelidt t, sessionidt s) if (!q) return; *q = ConfigReq; - q[1] = r << RADIUS_SHIFT; // ID, dont care, we only send one type of request + q[1] = r >> RADIUS_SHIFT; // ID, dont care, we only send one type of request *(uint16_t *) (q + 2) = htons(10); q[4] = 3; q[5] = 6; @@ -1219,6 +1229,17 @@ void sendipcp(tunnelidt t, sessionidt s) session[s].flags &= ~SF_IPCP_ACKED; // Clear flag. } +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) { @@ -1240,12 +1261,7 @@ void sessionkill(sessionidt s, char *reason) radiusclear(session[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); } @@ -1847,7 +1863,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 @@ -1866,7 +1882,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; } @@ -2047,12 +2063,7 @@ static void processtun(uint8_t * buf, int len) // Else discard. } -// -// Maximum number of actions to complete. -// This is to avoid sending out too many packets -// at once. -#define MAX_ACTIONS 500 - +// Handle retries, timeouts static int regular_cleanups(void) { static sessionidt s = 0; // Next session to check for actions on. @@ -2146,7 +2157,7 @@ static int regular_cleanups(void) if (session[s].die && session[s].die <= TIME) { sessionkill(s, "Expired"); - if (++count >= MAX_ACTIONS) break; + if (++count >= config->cleanup_limit) break; continue; } @@ -2155,7 +2166,7 @@ static int regular_cleanups(void) { sessionshutdown(s, "No response to LCP ECHO requests"); STAT(session_timeout); - if (++count >= MAX_ACTIONS) break; + if (++count >= config->cleanup_limit) break; continue; } @@ -2175,7 +2186,7 @@ static int regular_cleanups(void) LOG(4, s, session[s].tunnel, "No data in %d seconds, sending LCP ECHO\n", (int)(time_now - session[s].last_packet)); tunnelsend(b, 24, session[s].tunnel); // send it - if (++count >= MAX_ACTIONS) break; + if (++count >= config->cleanup_limit) break; } // Check for actions requested from the CLI @@ -2244,7 +2255,7 @@ static int regular_cleanups(void) if (send) cluster_send_session(s); - if (++count >= MAX_ACTIONS) break; + if (++count >= config->cleanup_limit) break; } } @@ -2266,7 +2277,7 @@ static int regular_cleanups(void) } } - if (count >= MAX_ACTIONS) + if (count >= config->cleanup_limit) return 1; // Didn't finish! LOG(3, 0, 0, "End regular cleanup (%d actions), next in %d seconds\n", count, config->cleanup_interval); @@ -2281,8 +2292,39 @@ static int regular_cleanups(void) static int still_busy(void) { int i; + static time_t stopped_bgp = 0; static clockt last_talked = 0; static clockt start_busy_wait = 0; + + if (!config->cluster_iam_master) + { +#ifdef BGP + if (bgp_configured) + { + if (!stopped_bgp) + { + 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]); + + stopped_bgp = time_now; + + // we don't want to become master + cluster_send_ping(0); + + return 1; + } + + if (time_now < (stopped_bgp + QUIT_DELAY)) + return 1; + } +#endif /* BGP */ + + return 0; + } + if (start_busy_wait == 0) start_busy_wait = TIME; @@ -2560,7 +2602,6 @@ static void mainloop(void) /* Handle timeouts. Make sure that this gets run anyway, even if there was * something to read, else under load this will never actually run.... - * */ if (config->cluster_iam_master && next_clean <= time_now) { @@ -2586,6 +2627,7 @@ static void mainloop(void) // // Important!!! We MUST not process any packets past this point! + LOG(1, 0, 0, "Clean shutdown complete\n"); } static void stripdomain(char *host) @@ -2674,6 +2716,7 @@ static void initdata(int optdebug, char *optconfig) config->debug = optdebug; config->num_tbfs = MAXTBFS; config->rl_rate = 28; // 28kbps + config->cluster_master_min_adv = 1; if (!(tunnel = shared_malloc(sizeof(tunnelt) * MAXTUNNEL))) { @@ -3265,14 +3308,6 @@ int main(int argc, char *argv[]) mainloop(); -#ifdef BGP - /* try to shut BGP down cleanly; with luck the sockets will be - writable since we're out of the select */ - for (i = 0; i < BGP_NUM_PEERS; i++) - if (bgp_peers[i].state == Established) - bgp_stop(&bgp_peers[i]); -#endif /* BGP */ - /* remove plugins (so cleanup code gets run) */ plugins_done(); @@ -3647,7 +3682,7 @@ static void update_config() if (!config->numradiusservers) LOG(0, 0, 0, "No RADIUS servers defined!\n"); - config->num_radfds = 2 << RADIUS_SHIFT; + config->num_radfds = 1 << RADIUS_SHIFT; // Update plugins for (i = 0; i < MAXPLUGINS; i++) @@ -3667,7 +3702,8 @@ static void update_config() } } memcpy(config->old_plugins, config->plugins, sizeof(config->plugins)); - if (!config->cleanup_interval) config->cleanup_interval = 10; + if (!config->cleanup_interval) config->cleanup_interval = 2; + if (!config->cleanup_limit) config->cleanup_limit = 50; if (!config->multi_read_count) config->multi_read_count = 10; if (!config->cluster_address) config->cluster_address = inet_addr(DEFAULT_MCAST_ADDR); if (!*config->cluster_interface)