X-Git-Url: http://git.sameswireless.fr/l2tpns.git/blobdiff_plain/8d94f2020d372385156e9618d6279ba964ba8870..92bfbe46e854e7ff40d6d4297c8df74f1efcf10f:/l2tpns.c diff --git a/l2tpns.c b/l2tpns.c index dd1e8ae..5445013 100644 --- a/l2tpns.c +++ b/l2tpns.c @@ -77,7 +77,7 @@ int cluster_sockfd = -1; // Intra-cluster communications socket. int epollfd = -1; // event polling time_t basetime = 0; // base clock char hostname[MAXHOSTNAME] = ""; // us. -static int tunidx; // ifr_ifindex of tun device +int tunidx; // ifr_ifindex of tun device int nlseqnum = 0; // netlink sequence number int min_initok_nlseqnum = 0; // minimun seq number for messages after init is ok static int syslog_log = 0; // are we logging to syslog @@ -94,10 +94,11 @@ uint16_t MSS = 0; // TCP MSS struct cli_session_actions *cli_session_actions = NULL; // Pending session changes requested by CLI struct cli_tunnel_actions *cli_tunnel_actions = NULL; // Pending tunnel changes required by CLI -union iphash { +union iphash +{ sessionidt sess; union iphash *idx; -} ip_hash[256]; // Mapping from IP address to session structures. +}ip_hash[256]; // Mapping from IP address to session structures. struct ipv6radix { sessionidt sess; @@ -188,6 +189,7 @@ config_descriptt config_values[] = { CONFIG("disable_sending_hello", disable_sending_hello, BOOL), CONFIG("disable_no_spoof", disable_no_spoof, BOOL), CONFIG("bind_multi_address", bind_multi_address, STRING), + CONFIG("grp_txrate_average_time", grp_txrate_average_time, INT), CONFIG("pppoe_only_equal_svc_name", pppoe_only_equal_svc_name, BOOL), CONFIG("multi_hostname", multi_hostname, STRING), CONFIG("no_throttle_local_IP", no_throttle_local_IP, BOOL), @@ -225,6 +227,7 @@ tunnelt *tunnel = NULL; // Array of tunnel structures. bundlet *bundle = NULL; // Array of bundle structures. fragmentationt *frag = NULL; // Array of fragmentation structures. sessiont *session = NULL; // Array of session structures. +groupsesst *grpsession = NULL; // Array of groupsesst structures. sessionlocalt *sess_local = NULL; // Array of local per-session counters. radiust *radius = NULL; // Array of radius structures. ippoolt *ip_address_pool = NULL; // Array of dynamic IP addresses. @@ -235,9 +238,6 @@ struct Tstats *_statistics = NULL; struct Tringbuffer *ringbuffer = NULL; #endif -static ssize_t netlink_send(struct nlmsghdr *nh); -static void netlink_addattr(struct nlmsghdr *nh, int type, const void *data, int alen); -static void cache_ipmap(in_addr_t ip, sessionidt s); static void uncache_ipmap(in_addr_t ip); static void cache_ipv6map(struct in6_addr ip, int prefixlen, sessionidt s); static void free_ip_address(sessionidt s); @@ -266,8 +266,9 @@ static clockt now(double *f) if (f) *f = t.tv_sec + t.tv_usec / 1000000.0; if (t.tv_sec != time_now) { - time_now = t.tv_sec; - time_changed++; + time_now = t.tv_sec; + time_changed++; + grp_time_changed(); } // Time in milliseconds @@ -626,7 +627,7 @@ static void initnetlink(void) } } -static ssize_t netlink_send(struct nlmsghdr *nh) +ssize_t netlink_send(struct nlmsghdr *nh) { struct sockaddr_nl nladdr; struct iovec iov; @@ -662,7 +663,7 @@ static ssize_t netlink_recv(void *buf, ssize_t len) } /* adapted from iproute2 */ -static void netlink_addattr(struct nlmsghdr *nh, int type, const void *data, int alen) +void netlink_addattr(struct nlmsghdr *nh, int type, const void *data, int alen) { int len = RTA_LENGTH(alen); struct rtattr *rta; @@ -982,7 +983,6 @@ static sessionidt lookup_ipv6map(struct in6_addr ip) int s; char ipv6addr[INET6_ADDRSTRLEN]; - curnode = &ipv6_hash[ip.s6_addr[0]]; curnode = &ipv6_hash[((ip.s6_addr[0]) & 0xF0)>>4]; i = 1; s = curnode->sess; @@ -1060,7 +1060,7 @@ sessionidt sessionbyipv6new(struct in6_addr ip) // // (It's actually cached in network order) // -static void cache_ipmap(in_addr_t ip, sessionidt s) +void cache_ipmap(in_addr_t ip, sessionidt s) { in_addr_t nip = htonl(ip); // MUST be in network order. I.e. MSB must in be ((char *) (&ip))[0] uint8_t *a = (uint8_t *) &nip; @@ -1079,7 +1079,6 @@ static void cache_ipmap(in_addr_t ip, sessionidt s) if (s > 0) LOG(4, s, session[s].tunnel, "Caching ip address %s\n", fmtaddr(nip, 0)); - else if (s == 0) LOG(4, 0, 0, "Un-caching ip address %s\n", fmtaddr(nip, 0)); // else a map to an ip pool index. @@ -1447,6 +1446,7 @@ static void update_session_out_stat(sessionidt s, sessiont *sp, int len) void processipout(uint8_t *buf, int len) { sessionidt s; + groupidt g; sessiont *sp; tunnelidt t; in_addr_t ip, ip_src; @@ -1484,7 +1484,31 @@ void processipout(uint8_t *buf, int len) ip_src = *(uint32_t *)(buf + 12); ip = *(uint32_t *)(buf + 16); - if (!(s = sessionbyip(ip))) + if ((g = grp_groupbyip(ip))) + { + s = grp_getnextsession(g, &ip, &ip_src, 0); + if (!s) + { + // Is this a packet for a session that doesn't exist? + static int rate = 0; // Number of ICMP packets we've sent this second. + static int last = 0; // Last time we reset the ICMP packet counter 'rate'. + + if (last != time_now) + { + last = time_now; + rate = 0; + } + + if (rate++ < config->icmp_rate) // Only send a max of icmp_rate per second. + { + LOG(4, 0, 0, "IP: Sending ICMP host unreachable to %s\n", fmtaddr(*(in_addr_t *)(buf + 12), 0)); + host_unreachable(*(in_addr_t *)(buf + 12), *(uint16_t *)(buf + 4), + config->bind_address ? config->bind_address : my_address, buf, len); + } + return; + } + } + else if (!(s = sessionbyip(ip))) { // Is this a packet for a session that doesn't exist? static int rate = 0; // Number of ICMP packets we've sent this second. @@ -1713,9 +1737,11 @@ void processipout(uint8_t *buf, int len) static void processipv6out(uint8_t * buf, int len) { sessionidt s; + groupidt g; sessiont *sp; tunnelidt t; - struct in6_addr ip6; + struct in6_addr *p_ip6; + struct in6_addr *p_ip6_src; uint8_t *data = buf; // Keep a copy of the originals. int size = len; @@ -1748,12 +1774,16 @@ static void processipv6out(uint8_t * buf, int len) return; } - ip6 = *(struct in6_addr *)(buf+24); - s = sessionbyipv6(ip6); + p_ip6_src = (struct in6_addr *)(buf+8); + p_ip6 = (struct in6_addr *)(buf+24); - if (s == 0) + if ((g = grp_groupbyipv6(*p_ip6))) { - s = sessionbyipv6new(ip6); + s = grp_getnextsession(g, p_ip6, p_ip6_src, 1); + } + else if (!(s = sessionbyipv6(*p_ip6))) + { + s = sessionbyipv6new(*p_ip6); } if (s == 0) @@ -2127,7 +2157,7 @@ void sessionshutdown(sessionidt s, char const *reason, int cdn_result, int cdn_e session[s].die = TIME + 150; // Clean up in 15 seconds if (session[s].ip) - { // IP allocated, clear and unroute + { // IP allocated, clear and unroute int r; int routed = 0; for (r = 0; r < MAXROUTE && session[s].route[r].ip; r++) @@ -2342,6 +2372,8 @@ static void sessionclear(sessionidt s) // kill a session now void sessionkill(sessionidt s, char *reason) { + groupidt g; + CSTAT(sessionkill); if (!session[s].opened) // not alive @@ -2370,6 +2402,12 @@ void sessionkill(sessionidt s, char *reason) } LOG(2, s, session[s].tunnel, "Kill session %d (%s): %s\n", s, session[s].user, reason); + + if ((g = grp_groupbysession(s))) + { + grp_removesession(g, s); + } + sessionclear(s); cluster_send_session(s); } @@ -3781,7 +3819,7 @@ static void regular_cleanups(double period) // No data in ECHO_TIMEOUT seconds, send LCP ECHO if (session[s].ppp.phase >= Establish && (time_now - session[s].last_packet >= config->echo_timeout) && - (time_now - sess_local[s].last_echo >= ECHO_TIMEOUT)) + (time_now - sess_local[s].last_echo >= config->echo_timeout)) { uint8_t b[MAXETHER]; @@ -4718,6 +4756,8 @@ static void initdata(int optdebug, char *optconfig) #endif /* BGP */ lac_initremotelnsdata(); + + grp_initdata(); } static int assign_ip_address(sessionidt s) @@ -5260,6 +5300,9 @@ int main(int argc, char *argv[]) LOG(0, 0, 0, "Can't lock pages: %s\n", strerror(errno)); } + //LOG(3, 0, 0, "Debug sizeof struct: sessiont %lu, tunnelt %lu, bundlet %lu, groupsesst %lu\n", + // sizeof(sessiont), sizeof(tunnelt), sizeof(bundlet), sizeof(groupsesst)); + mainloop(); /* remove plugins (so cleanup code gets run) */ @@ -5771,6 +5814,7 @@ int sessionsetup(sessionidt s, tunnelidt t) if (!session[s].bundle || (bundle[session[s].bundle].num_of_links == 1)) { int routed = 0; + groupidt g; // Add the route for this session. for (r = 0; r < MAXROUTE && session[s].route[r].ip; r++) @@ -5793,6 +5837,12 @@ int sessionsetup(sessionidt s, tunnelidt t) } else cache_ipmap(session[s].ip, s); + + if ((g = grp_groupbysession(s))) + { + grp_setgrouproute(g, 1); + cluster_send_groupe(g); + } } sess_local[s].lcp_authtype = 0; // RADIUS authentication complete @@ -5916,9 +5966,12 @@ int load_session(sessionidt s, sessiont *new) } // check v6 routing - for (i = 0; i < MAXROUTE6 && new->route6[i].ipv6prefixlen; i++) + if (new->ppp.ipv6cp == Opened && session[s].ppp.ipv6cp != Opened) { - route6set(s, new->route6[i].ipv6route, new->route6[i].ipv6prefixlen, 1); + for (i = 0; i < MAXROUTE6 && new->route6[i].ipv6prefixlen; i++) + { + route6set(s, new->route6[i].ipv6route, new->route6[i].ipv6prefixlen, 1); + } } if (new->ipv6address.s6_addr[0] && new->ppp.ipv6cp == Opened && session[s].ppp.ipv6cp != Opened)