From: fendo Date: Wed, 6 Mar 2013 23:45:05 +0000 (+0100) Subject: merge from multibind X-Git-Tag: 2.2.1-2sames3.8~6 X-Git-Url: http://git.sameswireless.fr/l2tpns.git/commitdiff_plain/a478f1c2a22514a4de4521ffe3ed93d3c2c427b8?ds=sidebyside;hp=-c merge from multibind --- a478f1c2a22514a4de4521ffe3ed93d3c2c427b8 diff --combined Makefile index ee05e2c,23189e0..c0c7c4e --- a/Makefile +++ b/Makefile @@@ -26,7 -26,7 +26,7 @@@ INSTALL = install -c -D -o root -g roo l2tpns.LIBS = -lm -lcli -ldl OBJS = arp.o cli.o cluster.o constants.o control.o icmp.o l2tpns.o \ - ll.o md5.o ppp.o radius.o tbf.o util.o pppoe.o grpsess.o - ll.o md5.o ppp.o radius.o tbf.o util.o pppoe.o l2tplac.o ++ ll.o md5.o ppp.o radius.o tbf.o util.o pppoe.o l2tplac.o grpsess.o PROGRAMS = l2tpns nsctl PLUGINS = autosnoop.so autothrottle.so garden.so sessionctl.so \ @@@ -43,9 -43,6 +43,6 @@@ endi DEFINES += -DBGP OBJS += bgp.o - DEFINES += -DLAC - OBJS += l2tplac.o - all: programs plugins programs: $(PROGRAMS) plugins: $(PLUGINS) @@@ -129,9 -126,8 +126,9 @@@ radius.o: radius.c md5.h constants.h l2 tbf.o: tbf.c l2tpns.h util.h tbf.h util.o: util.c l2tpns.h bgp.h pppoe.o: pppoe.c l2tpns.h cluster.h constants.h md5.h util.h + l2tplac.o: l2tplac.c md5.h l2tpns.h util.h cluster.h l2tplac.h pppoe.h +grpsess.o: grpsess.c l2tpns.h util.h bgp.h bgp.o: bgp.c l2tpns.h bgp.h util.h - l2tplac.o: l2tplac.c md5.h l2tpns.h util.h cluster.h l2tplac.h pppoe.h autosnoop.so: autosnoop.c l2tpns.h plugin.h autothrottle.so: autothrottle.c l2tpns.h plugin.h garden.so: garden.c l2tpns.h plugin.h control.h diff --combined cli.c index c39eac0,fc150d7..e5ac57c --- a/cli.c +++ b/cli.c @@@ -21,7 -21,6 +21,7 @@@ #include #include #include +#include #include "l2tpns.h" #include "constants.h" @@@ -32,9 -31,7 +32,7 @@@ #ifdef BGP #include "bgp.h" #endif - #ifdef LAC #include "l2tplac.h" - #endif extern tunnelt *tunnel; extern bundlet *bundle; @@@ -78,7 -75,6 +76,7 @@@ static char *debug_levels[] = #endif static int cmd_show_session(struct cli_def *cli, char *command, char **argv, int argc); +static int cmd_show_group(struct cli_def *cli, char *command, char **argv, int argc); static int cmd_show_tunnels(struct cli_def *cli, char *command, char **argv, int argc); static int cmd_show_users(struct cli_def *cli, char *command, char **argv, int argc); static int cmd_show_radius(struct cli_def *cli, char *command, char **argv, int argc); @@@ -104,10 -100,8 +102,8 @@@ static int cmd_remove_plugin(struct cli static int cmd_uptime(struct cli_def *cli, char *command, char **argv, int argc); static int cmd_shutdown(struct cli_def *cli, char *command, char **argv, int argc); static int cmd_reload(struct cli_def *cli, char *command, char **argv, int argc); - #ifdef LAC static int cmd_setforward(struct cli_def *cli, char *command, char **argv, int argc); static int cmd_show_rmtlnsconf(struct cli_def *cli, char *command, char **argv, int argc); - #endif static int regular_stuff(struct cli_def *cli); @@@ -158,11 -152,8 +154,9 @@@ void init_cli( cli_register_command(cli, c, "pool", cmd_show_pool, PRIVILEGE_UNPRIVILEGED, MODE_EXEC, "Show the IP address allocation pool"); cli_register_command(cli, c, "radius", cmd_show_radius, PRIVILEGE_UNPRIVILEGED, MODE_EXEC, "Show active radius queries"); cli_register_command(cli, c, "running-config", cmd_show_run, PRIVILEGE_PRIVILEGED, MODE_EXEC, "Show the currently running configuration"); - #ifdef LAC cli_register_command(cli, c, "remotelns-conf", cmd_show_rmtlnsconf, PRIVILEGE_PRIVILEGED, MODE_EXEC, "Show a list of remote LNS configuration"); - #endif cli_register_command(cli, c, "session", cmd_show_session, PRIVILEGE_UNPRIVILEGED, MODE_EXEC, "Show a list of sessions or details for a single session"); + cli_register_command(cli, c, "group", cmd_show_group, PRIVILEGE_UNPRIVILEGED, MODE_EXEC, "Show a list of groups or details for a single group"); cli_register_command(cli, c, "tbf", cmd_show_tbf, PRIVILEGE_UNPRIVILEGED, MODE_EXEC, "List all token bucket filters in use"); cli_register_command(cli, c, "throttle", cmd_show_throttle, PRIVILEGE_UNPRIVILEGED, MODE_EXEC, "List all throttled sessions and associated TBFs"); cli_register_command(cli, c, "tunnels", cmd_show_tunnels, PRIVILEGE_UNPRIVILEGED, MODE_EXEC, "Show a list of tunnels or details for a single tunnel"); @@@ -234,9 -225,7 +228,7 @@@ cli_register_command(cli, NULL, "set", cmd_set, PRIVILEGE_PRIVILEGED, MODE_CONFIG, "Set a configuration variable"); - #ifdef LAC cli_register_command(cli, NULL, "setforward", cmd_setforward, PRIVILEGE_PRIVILEGED, MODE_CONFIG, "Set the Remote LNS Forward"); - #endif c = cli_register_command(cli, NULL, "ip", NULL, PRIVILEGE_PRIVILEGED, MODE_CONFIG, NULL); cli_register_command(cli, c, "access-list", cmd_ip_access_list, PRIVILEGE_PRIVILEGED, MODE_CONFIG, "Add named access-list"); @@@ -545,15 -534,9 +537,9 @@@ static int cmd_show_session(struct cli_ } // Show Summary - #ifdef LAC cli_print(cli, "%5s %7s %4s %-32s %-15s %s %s %s %s %10s %10s %10s %4s %10s %-18s %s", - #else - cli_print(cli, "%5s %4s %-32s %-15s %s %s %s %s %10s %10s %10s %4s %10s %-15s %s", - #endif "SID", - #ifdef LAC "LkToSID", - #endif "TID", "Username", "IP", @@@ -566,11 -549,7 +552,7 @@@ "uploaded", "idle", "Rem.Time", - #ifdef LAC "LAC(L)/RLNS(R)/PPPOE(P)", - #else - "LAC(L)/PPPOE(P)", - #endif "CLI"); for (i = 1; i < MAXSESSION; i++) @@@ -581,15 -560,9 +563,9 @@@ 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; - #ifdef LAC cli_print(cli, "%5d %7d %4d %-32s %-15s %s %s %s %s %10u %10lu %10lu %4u %10lu %3s%-20s %s", - #else - cli_print(cli, "%5d %4d %-32s %-15s %s %s %s %s %10u %10lu %10lu %4u %10lu %3s%-20s %s", - #endif i, - #ifdef LAC session[i].forwardtosession, - #endif session[i].tunnel, session[i].user[0] ? session[i].user : "*", fmtaddr(htonl(session[i].ip), 0), @@@ -602,11 -575,7 +578,7 @@@ (unsigned long)session[i].cin, abs(time_now - (session[i].last_packet ? session[i].last_packet : time_now)), (unsigned long)(rem_time), - #ifdef LAC (session[i].tunnel == TUNNEL_ID_PPPOE)?"(P)":(tunnel[session[i].tunnel].isremotelns?"(R)":"(L)"), - #else - (session[i].tunnel == TUNNEL_ID_PPPOE)?"(P)":"(L)", - #endif (session[i].tunnel == TUNNEL_ID_PPPOE)?fmtMacAddr(session[i].src_hwaddr):fmtaddr(htonl(tunnel[session[i].tunnel].ip), 1), session[i].calling[0] ? session[i].calling : "*"); } @@@ -697,11 -666,7 +669,7 @@@ static int cmd_show_tunnels(struct cli_ fmtaddr(htonl(tunnel[i].ip), 0), states[tunnel[i].state], sessions - #ifdef LAC ,(i == TUNNEL_ID_PPPOE)?"Tunnel pppoe":(tunnel[i].isremotelns?"Tunnel To Remote LNS":"Tunnel To LAC") - #else - ,(i == TUNNEL_ID_PPPOE)?"Tunnel pppoe":"Tunnel To LAC" - #endif ); } @@@ -1312,13 -1277,11 +1280,11 @@@ static int cmd_drop_session(struct cli_ cli_print(cli, "Dropping session %d", s); cli_session_actions[s].action |= CLI_SESS_KILL; } - #ifdef LAC else if (session[s].forwardtosession && session[s].opened && !session[s].die) { cli_print(cli, "Dropping session %d", s); cli_session_actions[s].action |= CLI_SESS_KILL; } - #endif else { cli_error(cli, "Session %d is not active.", s); @@@ -3147,79 -3110,6 +3113,77 @@@ static int cmd_reload(struct cli_def *c return CLI_OK; } +static int cmd_show_group(struct cli_def *cli, char *command, char **argv, int argc) +{ + int i; + groupidt g; + + if (CLI_HELP_REQUESTED) + return cli_arg_help(cli, 1, + "<1-%d>", MAXGROUPE-1, "Show specific group by id", + NULL); + + time(&time_now); + if (argc > 0) + { + // Show individual group + for (i = 0; i < argc; i++) + { + sessionidt s; + + g = atoi(argv[i]); + if (g <= 0 || g >= MAXGROUPE) + { + cli_print(cli, "Invalid group id \"%s\"", argv[i]); + continue; + } + + cli_print(cli, "\r\nGroup %d:", g); + cli_print(cli, "\tNb Session:\t\t%d", grpsession[g].nbsession); + cli_print(cli, "\tNb Routes:\t\t%d", grpsession[g].nbroutesgrp); + cli_print(cli, "\ttime_changed:\t\t%d\n", grpsession[g].time_changed); + + for (i = 0; i < grpsession[g].nbsession; i++) + { + if ((s = grpsession[g].sesslist[i].sid)) + { + cli_print(cli, "\tSession:\t%d\tTx Rate:%d Kbps\t\t\tweight:\t%d", + s, + grpsession[g].sesslist[i].tx_rate/(1024/8), + grpsession[g].sesslist[i].weight); + } + } + + for (i = 0; i < grpsession[g].nbroutesgrp; i++) + { + if (grpsession[g].route[i].ip != 0) + { + cli_print(cli, "\tRoute:\t%s/%d", fmtaddr(htonl(grpsession[g].route[i].ip), 0), grpsession[g].route[i].prefixlen); + } + } + } + return CLI_OK; + } + + // Show Summary + cli_print(cli, "%5s %7s %9s %12s", + "GID", + "Nb Sess", + "Nb Routes", + "Time changed"); + + for (g = gnextgrpid; g != 0; g = grpsession[g].prev) + { + cli_print(cli, "%5d %7d %9d %12d", + g, + grpsession[g].nbsession, + grpsession[g].nbroutesgrp, + grpsession[g].time_changed); + } + + return CLI_OK; +} + - #ifdef LAC - static int cmd_setforward(struct cli_def *cli, char *command, char **argv, int argc) { int ret; @@@ -3290,4 -3180,3 +3254,3 @@@ static int cmd_show_rmtlnsconf(struct c return CLI_OK; } - #endif diff --combined cluster.c index 4b85f67,651307a..5b6f208 --- a/cluster.c +++ b/cluster.c @@@ -16,7 -16,6 +16,7 @@@ #include #include #include +#include #include "l2tpns.h" #include "cluster.h" @@@ -306,10 -305,11 +306,11 @@@ static int _forward_packet(uint8_t *dat // The master just processes the payload as if it had // received it off the tun device. //(note: THIS ROUTINE WRITES TO pack[-6]). - int master_forward_packet(uint8_t *data, int size, in_addr_t addr, int port) + int master_forward_packet(uint8_t *data, int size, in_addr_t addr, uint16_t port, uint16_t indexudp) { uint8_t *p = data - (3 * sizeof(uint32_t)); uint8_t *psave = p; + uint32_t indexandport = port | ((indexudp << 16) & 0xFFFF0000); if (!config->cluster_master_address) // No election has been held yet. Just skip it. return -1; @@@ -317,7 -317,7 +318,7 @@@ LOG(4, 0, 0, "Forwarding packet from %s to master (size %d)\n", fmtaddr(addr, 0), size); STAT(c_forwarded); - add_type(&p, C_FORWARD, addr, (uint8_t *) &port, sizeof(port)); // ick. should be uint16_t + add_type(&p, C_FORWARD, addr, (uint8_t *) &indexandport, sizeof(indexandport)); return peer_send_data(config->cluster_master_address, psave, size + (3 * sizeof(uint32_t))); } @@@ -710,7 -710,6 +711,7 @@@ void cluster_check_master(void increment_counter(&session[i].cout, &session[i].cout_wrap, sess_local[i].cout); session[i].cin_delta += sess_local[i].cin; session[i].cout_delta += sess_local[i].cout; + session[i].coutgrp_delta += sess_local[i].cout; session[i].pin += sess_local[i].pin; session[i].pout += sess_local[i].pout; @@@ -1265,7 -1264,6 +1266,7 @@@ static int cluster_handle_bytes(uint8_ session[b->sid].cin_delta += b->cin; session[b->sid].cout_delta += b->cout; + session[b->sid].coutgrp_delta += b->cout; if (b->cin) session[b->sid].last_packet = session[b->sid].last_data = time_now; @@@ -1506,17 -1504,10 +1507,10 @@@ static int cluster_process_heartbeat(ui int i, type; int hb_ver = more; - #ifdef LAC #if HB_VERSION != 7 # error "need to update cluster_process_heartbeat()" - #endif - #else - #if HB_VERSION != 6 - # error "need to update cluster_process_heartbeat()" - #endif #endif - // we handle versions 5 through 7 if (hb_ver < 5 || hb_ver > HB_VERSION) { LOG(0, 0, 0, "Received a heartbeat version that I don't support (%d)!\n", hb_ver); @@@ -1729,12 -1720,8 +1723,8 @@@ size = rle_decompress((uint8_t **) &p, s, c, sizeof(c)); s -= (p - orig_p); - #ifdef LAC if ( ((hb_ver >= HB_VERSION) && (size != sizeof(tunnelt))) || ((hb_ver < HB_VERSION) && (size > sizeof(tunnelt))) ) - #else - if (size != sizeof(tunnelt) ) - #endif { // Ouch! Very very bad! LOG(0, 0, 0, "DANGER: Received a CTUNNEL that didn't decompress correctly!\n"); // Now what? Should exit! No-longer up to date! @@@ -1857,9 -1844,11 +1847,11 @@@ int processcluster(uint8_t *data, int s else { struct sockaddr_in a; + uint16_t indexudp; a.sin_addr.s_addr = more; - a.sin_port = *(int *) p; + a.sin_port = (*(int *) p) & 0xFFFF; + indexudp = ((*(int *) p) >> 16) & 0xFFFF; s -= sizeof(int); p += sizeof(int); @@@ -1874,7 -1863,7 +1866,7 @@@ processdae(p, s, &a, sizeof(a), &local); } else - processudp(p, s, &a); + processudp(p, s, &a, indexudp); return 0; } diff --combined l2tplac.c index 442f08a,0d11b45..d41a26d --- a/l2tplac.c +++ b/l2tplac.c @@@ -7,8 -7,6 +7,8 @@@ #include #include +#include +#include #include "md5.h" #include "l2tpns.h" @@@ -297,6 -295,7 +297,7 @@@ static int lac_create_tunnelsession(tun tunnel[t].port = pconfigrlns[i_conf].port; tunnel[t].window = 4; // default window tunnel[t].isremotelns = i_conf; + tunnel[t].indexudp = config->indexlacudpfd; STAT(tunnel_created); random_data(pconfigrlns[i_conf].auth, sizeof(pconfigrlns[i_conf].auth)); @@@ -451,7 -450,7 +452,7 @@@ void lac_calc_rlns_auth(tunnelidt t, ui } // Forward session to LAC or Remote LNS - int lac_session_forward(uint8_t *buf, int len, sessionidt sess, uint16_t proto, in_addr_t s_addr, int sin_port) + int lac_session_forward(uint8_t *buf, int len, sessionidt sess, uint16_t proto, in_addr_t s_addr, int sin_port, uint16_t indexudpfd) { uint16_t t = 0, s = 0; uint8_t *p = buf + 2; // First word L2TP options @@@ -484,7 -483,7 +485,7 @@@ (proto == PPPCCP) ) { session[sess].last_packet = time_now; - master_forward_packet(buf, len, s_addr, sin_port); + master_forward_packet(buf, len, s_addr, sin_port, indexudpfd); return 1; } } @@@ -527,7 -526,6 +528,7 @@@ // Update STAT OUT increment_counter(&session[s].cout, &session[s].cout_wrap, len); // byte count session[s].cout_delta += len; + session[s].coutgrp_delta += len; session[s].pout++; sess_local[s].cout += len; sess_local[s].pout++; diff --combined l2tpns.c index 392668b,4545d6c..08c8bed --- a/l2tpns.c +++ b/l2tpns.c @@@ -53,24 -53,18 +53,18 @@@ #include "bgp.h" #endif - #ifdef LAC #include "l2tplac.h" - #endif #include "pppoe.h" - #ifdef LAC char * Vendor_name = "Linux L2TPNS"; uint32_t call_serial_number = 0; - #endif // Globals configt *config = NULL; // all configuration int nlfd = -1; // netlink socket int tunfd = -1; // tun interface file handle. (network device) - int udpfd = -1; // UDP file handle - #ifdef LAC + int udpfd[MAX_UDPFD + 1] = INIT_TABUDPFD; // array UDP file handle + 1 for lac udp int udplacfd = -1; // UDP LAC file handle - #endif int controlfd = -1; // Control signal handle int clifd = -1; // Socket listening for CLI connections. int daefd = -1; // Socket listening for DAE connections. @@@ -81,7 -75,7 +75,7 @@@ int cluster_sockfd = -1; // Intra-clust 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 @@@ -98,7 -92,10 +92,7 @@@ uint16_t MSS = 0; // TCP MS 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 { - sessionidt sess; - union iphash *idx; -} ip_hash[256]; // Mapping from IP address to session structures. +union iphash ip_hash[256]; // Mapping from IP address to session structures. struct ipv6radix { sessionidt sess; @@@ -178,18 -175,16 +172,17 @@@ config_descriptt config_values[] = CONFIG("idle_echo_timeout", idle_echo_timeout, INT), CONFIG("iftun_address", iftun_address, IPv4), CONFIG("tundevicename", tundevicename, STRING), - #ifdef LAC CONFIG("disable_lac_func", disable_lac_func, BOOL), CONFIG("auth_tunnel_change_addr_src", auth_tunnel_change_addr_src, BOOL), CONFIG("bind_address_remotelns", bind_address_remotelns, IPv4), CONFIG("bind_portremotelns", bind_portremotelns, SHORT), - #endif CONFIG("pppoe_if_to_bind", pppoe_if_to_bind, STRING), CONFIG("pppoe_service_name", pppoe_service_name, STRING), CONFIG("pppoe_ac_name", pppoe_ac_name, STRING), 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), { NULL, 0, 0, 0 } }; @@@ -218,7 -213,6 +211,7 @@@ tunnelt *tunnel = NULL; // Array of t 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. @@@ -229,6 -223,9 +222,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); @@@ -257,9 -254,8 +250,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 @@@ -618,7 -614,7 +611,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; @@@ -654,7 -650,7 +647,7 @@@ static ssize_t netlink_recv(void *buf, } /* 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; @@@ -697,7 -693,7 +690,7 @@@ static void inittun(void } if (*config->tundevicename) - strncpy(ifr.ifr_name, config->tundevicename, IFNAMSIZ); + strncpy(ifr.ifr_name, config->tundevicename, IFNAMSIZ); if (ioctl(tunfd, TUNSETIFF, (void *) &ifr) < 0) { @@@ -759,14 -755,30 +752,30 @@@ req.ifmsg.ifaddr.ifa_scope = RT_SCOPE_UNIVERSE; req.ifmsg.ifaddr.ifa_index = tunidx; - if (config->iftun_address) - ip = config->iftun_address; + if (config->nbmultiaddress > 1) + { + int i; + for (i = 0; i < config->nbmultiaddress ; i++) + { + ip = config->iftun_n_address[i]; + netlink_addattr(&req.nh, IFA_LOCAL, &ip, sizeof(ip)); + if (netlink_send(&req.nh) < 0) + goto senderror; + } + } else - ip = 0x01010101; // 1.1.1.1 - netlink_addattr(&req.nh, IFA_LOCAL, &ip, sizeof(ip)); + { + if (config->iftun_address) + ip = config->iftun_address; + else + ip = 0x01010101; // 1.1.1.1 + netlink_addattr(&req.nh, IFA_LOCAL, &ip, sizeof(ip)); + + if (netlink_send(&req.nh) < 0) + goto senderror; + } + - if (netlink_send(&req.nh) < 0) - goto senderror; // Only setup IPv6 on the tun device if we have a configured prefix if (config->ipv6_prefix.s6_addr[0]) { @@@ -836,28 -848,35 +845,35 @@@ senderror exit(1); } - // set up UDP ports - static void initudp(void) + // set up LAC UDP ports + static void initlacudp(void) { int on = 1; struct sockaddr_in addr; - // Tunnel + // Tunnel to Remote LNS memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; - addr.sin_port = htons(L2TPPORT); - addr.sin_addr.s_addr = config->bind_address; - udpfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); - setsockopt(udpfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); + addr.sin_port = htons(config->bind_portremotelns); + addr.sin_addr.s_addr = config->bind_address_remotelns; + udplacfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + setsockopt(udplacfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); { - int flags = fcntl(udpfd, F_GETFL, 0); - fcntl(udpfd, F_SETFL, flags | O_NONBLOCK); + int flags = fcntl(udplacfd, F_GETFL, 0); + fcntl(udplacfd, F_SETFL, flags | O_NONBLOCK); } - if (bind(udpfd, (struct sockaddr *) &addr, sizeof(addr)) < 0) + if (bind(udplacfd, (struct sockaddr *) &addr, sizeof(addr)) < 0) { - LOG(0, 0, 0, "Error in UDP bind: %s\n", strerror(errno)); + LOG(0, 0, 0, "Error in UDP REMOTE LNS bind: %s\n", strerror(errno)); exit(1); } + } + + // set up control ports + static void initcontrol(void) + { + int on = 1; + struct sockaddr_in addr; // Control memset(&addr, 0, sizeof(addr)); @@@ -871,6 -890,13 +887,13 @@@ LOG(0, 0, 0, "Error in control bind: %s\n", strerror(errno)); exit(1); } + } + + // set up Dynamic Authorization Extensions to RADIUS port + static void initdae(void) + { + int on = 1; + struct sockaddr_in addr; // Dynamic Authorization Extensions to RADIUS memset(&addr, 0, sizeof(addr)); @@@ -884,28 -910,30 +907,30 @@@ LOG(0, 0, 0, "Error in DAE bind: %s\n", strerror(errno)); exit(1); } + } - #ifdef LAC - // Tunnel to Remote LNS + // set up UDP ports + static void initudp(int * pudpfd, in_addr_t ip_bind) + { + int on = 1; + struct sockaddr_in addr; + + // Tunnel memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; - addr.sin_port = htons(config->bind_portremotelns); - addr.sin_addr.s_addr = config->bind_address_remotelns; - udplacfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); - setsockopt(udplacfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); + addr.sin_port = htons(L2TPPORT); + addr.sin_addr.s_addr = ip_bind; + (*pudpfd) = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + setsockopt((*pudpfd), SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); { - int flags = fcntl(udplacfd, F_GETFL, 0); - fcntl(udplacfd, F_SETFL, flags | O_NONBLOCK); + int flags = fcntl((*pudpfd), F_GETFL, 0); + fcntl((*pudpfd), F_SETFL, flags | O_NONBLOCK); } - if (bind(udplacfd, (struct sockaddr *) &addr, sizeof(addr)) < 0) + if (bind((*pudpfd), (struct sockaddr *) &addr, sizeof(addr)) < 0) { - LOG(0, 0, 0, "Error in UDP REMOTE LNS bind: %s\n", strerror(errno)); + LOG(0, 0, 0, "Error in UDP bind: %s\n", strerror(errno)); exit(1); } - #endif - - // Intercept - snoopfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); } // @@@ -1000,7 -1028,7 +1025,7 @@@ sessionidt sessionbyipv6(struct in6_add // // (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; @@@ -1230,14 -1258,11 +1255,11 @@@ void tunnelsend(uint8_t * buf, uint16_ LOG(3, 0, t, "Control message resend try %d\n", tunnel[t].try); } } - #ifdef LAC - if (sendto((tunnel[t].isremotelns?udplacfd:udpfd), buf, l, 0, (void *) &addr, sizeof(addr)) < 0) - #else - if (sendto(udpfd, buf, l, 0, (void *) &addr, sizeof(addr)) < 0) - #endif + + if (sendto(udpfd[tunnel[t].indexudp], buf, l, 0, (void *) &addr, sizeof(addr)) < 0) { LOG(0, ntohs((*(uint16_t *) (buf + 6))), t, "Error sending data out tunnel: %s (udpfd=%d, buf=%p, len=%d, dest=%s)\n", - strerror(errno), udpfd, buf, l, inet_ntoa(addr.sin_addr)); + strerror(errno), udpfd[tunnel[t].indexudp], buf, l, inet_ntoa(addr.sin_addr)); STAT(tunnel_tx_errors); return; } @@@ -1372,7 -1397,6 +1394,7 @@@ static void update_session_out_stat(ses { increment_counter(&sp->cout, &sp->cout_wrap, len); // byte count sp->cout_delta += len; + sp->coutgrp_delta += len; sp->pout++; sp->last_data = time_now; @@@ -1386,7 -1410,6 +1408,7 @@@ void processipout(uint8_t *buf, int len) { sessionidt s; + groupidt g; sessiont *sp; tunnelidt t; in_addr_t ip; @@@ -1423,31 -1446,7 +1445,31 @@@ } ip = *(uint32_t *)(buf + 16); - if (!(s = sessionbyip(ip))) + if ((g = grp_groupbyip(ip))) + { + s = grp_getnextsession(g, ip); + 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. @@@ -1782,7 -1781,6 +1804,7 @@@ static void processipv6out(uint8_t * bu increment_counter(&sp->cout, &sp->cout_wrap, len); // byte count sp->cout_delta += len; + sp->coutgrp_delta += len; sp->pout++; udp_tx += len; @@@ -1832,7 -1830,6 +1854,7 @@@ static void send_ipout(sessionidt s, ui increment_counter(&sp->cout, &sp->cout_wrap, len); // byte count sp->cout_delta += len; + sp->coutgrp_delta += len; sp->pout++; udp_tx += len; @@@ -2080,7 -2077,7 +2102,7 @@@ void sessionshutdown(sessionidt s, cha 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++) @@@ -2233,7 -2230,7 +2255,7 @@@ void sendipcp(sessionidt s, tunnelidt t q[4] = 3; // ip address option q[5] = 6; // option length *(in_addr_t *) (q + 6) = config->peer_address ? config->peer_address : - config->iftun_address ? config->iftun_address : + config->iftun_n_address[tunnel[t].indexudp] ? config->iftun_n_address[tunnel[t].indexudp] : my_address; // send my IP tunnelsend(buf, 10 + (q - buf), t); // send it @@@ -2280,8 -2277,6 +2302,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 @@@ -2299,7 -2294,6 +2321,6 @@@ if (sess_local[s].radius) radiusclear(sess_local[s].radius, s); // cant send clean accounting data, session is killed - #ifdef LAC if (session[s].forwardtosession) { sessionidt sess = session[s].forwardtosession; @@@ -2309,15 -2303,8 +2330,14 @@@ sessionshutdown(sess, reason, CDN_ADMIN_DISC, TERM_ADMIN_RESET); } } - #endif 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); } @@@ -2421,7 -2408,7 +2441,7 @@@ static void tunnelshutdown(tunnelidt t } // read and process packet on tunnel (UDP) - void processudp(uint8_t *buf, int len, struct sockaddr_in *addr) + void processudp(uint8_t *buf, int len, struct sockaddr_in *addr, uint16_t indexudpfd) { uint8_t *chapresponse = NULL; uint16_t l = len, t = 0, s = 0, ns = 0, nr = 0; @@@ -2512,7 -2499,7 +2532,7 @@@ if (!config->cluster_iam_master) { - master_forward_packet(buf, len, addr->sin_addr.s_addr, addr->sin_port); + master_forward_packet(buf, len, addr->sin_addr.s_addr, addr->sin_port, indexudpfd); return; } @@@ -2562,6 -2549,7 +2582,7 @@@ tunnel[t].ip = ntohl(*(in_addr_t *) & addr->sin_addr); tunnel[t].port = ntohs(addr->sin_port); tunnel[t].window = 4; // default window + tunnel[t].indexudp = indexudpfd; STAT(tunnel_created); LOG(1, 0, t, " New tunnel from %s:%u ID %u\n", fmtaddr(htonl(tunnel[t].ip), 0), tunnel[t].port, t); @@@ -2833,7 -2821,6 +2854,6 @@@ } break; case 13: // Response - #ifdef LAC if (tunnel[t].isremotelns) { chapresponse = calloc(17, 1); @@@ -2841,7 -2828,6 +2861,6 @@@ LOG(3, s, t, "received challenge response from REMOTE LNS\n"); } else - #endif /* LAC */ // Why did they send a response? We never challenge. LOG(2, s, t, " received unexpected challenge response\n"); break; @@@ -3087,7 -3073,6 +3106,6 @@@ case 2: // SCCRP tunnel[t].state = TUNNELOPEN; tunnel[t].lastrec = time_now; - #ifdef LAC LOG(3, s, t, "Received SCCRP\n"); if (main_quit != QUIT_SHUTDOWN) { @@@ -3118,7 -3103,6 +3136,6 @@@ { tunnelshutdown(t, "Shutting down", 6, 0, 0); } - #endif /* LAC */ break; case 3: // SCCN LOG(3, s, t, "Received SCCN\n"); @@@ -3196,7 -3180,6 +3213,6 @@@ } return; case 11: // ICRP - #ifdef LAC LOG(3, s, t, "Received ICRP\n"); if (session[s].forwardtosession) { @@@ -3212,7 -3195,6 +3228,6 @@@ controladd(c, asession, t); // send the message LOG(3, s, t, "Sending ICCN\n"); } - #endif /* LAC */ break; case 12: // ICCN LOG(3, s, t, "Received ICCN\n"); @@@ -3228,7 -3210,7 +3243,7 @@@ // Set multilink options before sending initial LCP packet sess_local[s].mp_mrru = 1614; - sess_local[s].mp_epdis = ntohl(config->iftun_address ? config->iftun_address : my_address); + sess_local[s].mp_epdis = ntohl(config->iftun_n_address[tunnel[t].indexudp] ? config->iftun_n_address[tunnel[t].indexudp] : my_address); sendlcp(s, t); change_state(s, lcp, RequestSent); @@@ -3286,12 -3268,11 +3301,11 @@@ l -= 2; } - #ifdef LAC if (session[s].forwardtosession) { LOG(5, s, t, "Forwarding data session to session %u\n", session[s].forwardtosession); // Forward to LAC/BAS or Remote LNS session - lac_session_forward(buf, len, s, proto, addr->sin_addr.s_addr, addr->sin_port); + lac_session_forward(buf, len, s, proto, addr->sin_addr.s_addr, addr->sin_port, indexudpfd); return; } else if (config->auth_tunnel_change_addr_src) @@@ -3306,14 -3287,13 +3320,13 @@@ tunnel[t].ip = ntohl(addr->sin_addr.s_addr); } } - #endif /* LAC */ if (s && !session[s].opened) // Is something wrong?? { if (!config->cluster_iam_master) { // Pass it off to the master to deal with.. - master_forward_packet(buf, len, addr->sin_addr.s_addr, addr->sin_port); + master_forward_packet(buf, len, addr->sin_addr.s_addr, addr->sin_port, indexudpfd); return; } @@@ -3325,37 -3305,37 +3338,37 @@@ if (proto == PPPPAP) { session[s].last_packet = time_now; - if (!config->cluster_iam_master) { master_forward_packet(buf, len, addr->sin_addr.s_addr, addr->sin_port); return; } + if (!config->cluster_iam_master) { master_forward_packet(buf, len, addr->sin_addr.s_addr, addr->sin_port, indexudpfd); return; } processpap(s, t, p, l); } else if (proto == PPPCHAP) { session[s].last_packet = time_now; - if (!config->cluster_iam_master) { master_forward_packet(buf, len, addr->sin_addr.s_addr, addr->sin_port); return; } + if (!config->cluster_iam_master) { master_forward_packet(buf, len, addr->sin_addr.s_addr, addr->sin_port, indexudpfd); return; } processchap(s, t, p, l); } else if (proto == PPPLCP) { session[s].last_packet = time_now; - if (!config->cluster_iam_master) { master_forward_packet(buf, len, addr->sin_addr.s_addr, addr->sin_port); return; } + if (!config->cluster_iam_master) { master_forward_packet(buf, len, addr->sin_addr.s_addr, addr->sin_port, indexudpfd); return; } processlcp(s, t, p, l); } else if (proto == PPPIPCP) { session[s].last_packet = time_now; - if (!config->cluster_iam_master) { master_forward_packet(buf, len, addr->sin_addr.s_addr, addr->sin_port); return; } + if (!config->cluster_iam_master) { master_forward_packet(buf, len, addr->sin_addr.s_addr, addr->sin_port, indexudpfd); return; } processipcp(s, t, p, l); } else if (proto == PPPIPV6CP && config->ipv6_prefix.s6_addr[0]) { session[s].last_packet = time_now; - if (!config->cluster_iam_master) { master_forward_packet(buf, len, addr->sin_addr.s_addr, addr->sin_port); return; } + if (!config->cluster_iam_master) { master_forward_packet(buf, len, addr->sin_addr.s_addr, addr->sin_port, indexudpfd); return; } processipv6cp(s, t, p, l); } else if (proto == PPPCCP) { session[s].last_packet = time_now; - if (!config->cluster_iam_master) { master_forward_packet(buf, len, addr->sin_addr.s_addr, addr->sin_port); return; } + if (!config->cluster_iam_master) { master_forward_packet(buf, len, addr->sin_addr.s_addr, addr->sin_port, indexudpfd); return; } processccp(s, t, p, l); } else if (proto == PPPIP) @@@ -3369,7 -3349,7 +3382,7 @@@ session[s].last_packet = session[s].last_data = time_now; if (session[s].walled_garden && !config->cluster_iam_master) { - master_forward_packet(buf, len, addr->sin_addr.s_addr, addr->sin_port); + master_forward_packet(buf, len, addr->sin_addr.s_addr, addr->sin_port, indexudpfd); return; } @@@ -3387,7 -3367,7 +3400,7 @@@ if (!config->cluster_iam_master) { // The fragments reconstruction is managed by the Master. - master_forward_packet(buf, len, addr->sin_addr.s_addr, addr->sin_port); + master_forward_packet(buf, len, addr->sin_addr.s_addr, addr->sin_port, indexudpfd); return; } @@@ -3404,7 -3384,7 +3417,7 @@@ session[s].last_packet = session[s].last_data = time_now; if (session[s].walled_garden && !config->cluster_iam_master) { - master_forward_packet(buf, len, addr->sin_addr.s_addr, addr->sin_port); + master_forward_packet(buf, len, addr->sin_addr.s_addr, addr->sin_port, indexudpfd); return; } @@@ -3413,7 -3393,7 +3426,7 @@@ else if (session[s].ppp.lcp == Opened) { session[s].last_packet = time_now; - if (!config->cluster_iam_master) { master_forward_packet(buf, len, addr->sin_addr.s_addr, addr->sin_port); return; } + if (!config->cluster_iam_master) { master_forward_packet(buf, len, addr->sin_addr.s_addr, addr->sin_port, indexudpfd); return; } protoreject(s, t, p, l, proto); } else @@@ -3716,7 -3696,7 +3729,7 @@@ static void regular_cleanups(double per // 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]; @@@ -3982,13 -3962,8 +3995,8 @@@ static int still_busy(void # include "fake_epoll.h" #endif - #ifdef LAC - // the base set of fds polled: cli, cluster, tun, udp, control, dae, netlink, udplac, pppoedisc, pppoesess - #define BASE_FDS 10 - #else - // the base set of fds polled: cli, cluster, tun, udp, control, dae, netlink, pppoedisc, pppoesess - #define BASE_FDS 9 - #endif + // the base set of fds polled: cli, cluster, tun, udp (MAX_UDPFD), control, dae, netlink, udplac, pppoedisc, pppoesess + #define BASE_FDS (9 + MAX_UDPFD) // additional polled fds #ifdef BGP @@@ -4000,7 -3975,7 +4008,7 @@@ // main loop - gets packets on tun or udp and processes them static void mainloop(void) { - int i; + int i, j; uint8_t buf[65536]; uint8_t *p = buf + 32; // for the hearder of the forwarded MPPP packet (see C_MPPP_FORWARD) // and the forwarded pppoe session @@@ -4015,13 -3990,8 +4023,8 @@@ exit(1); } - #ifdef LAC LOG(4, 0, 0, "Beginning of main loop. clifd=%d, cluster_sockfd=%d, tunfd=%d, udpfd=%d, controlfd=%d, daefd=%d, nlfd=%d , udplacfd=%d, pppoefd=%d, pppoesessfd=%d\n", - clifd, cluster_sockfd, tunfd, udpfd, controlfd, daefd, nlfd, udplacfd, pppoediscfd, pppoesessfd); - #else - LOG(4, 0, 0, "Beginning of main loop. clifd=%d, cluster_sockfd=%d, tunfd=%d, udpfd=%d, controlfd=%d, daefd=%d, nlfd=%d, pppoefd=%d, pppoesessfd=%d\n", - clifd, cluster_sockfd, tunfd, udpfd, controlfd, daefd, nlfd, pppoediscfd, pppoesessfd); - #endif + clifd, cluster_sockfd, tunfd, udpfd[0], controlfd, daefd, nlfd, udplacfd, pppoediscfd, pppoesessfd); /* setup our fds to poll for input */ { @@@ -4046,10 -4016,6 +4049,6 @@@ e.data.ptr = &d[i++]; epoll_ctl(epollfd, EPOLL_CTL_ADD, tunfd, &e); - d[i].type = FD_TYPE_UDP; - e.data.ptr = &d[i++]; - epoll_ctl(epollfd, EPOLL_CTL_ADD, udpfd, &e); - d[i].type = FD_TYPE_CONTROL; e.data.ptr = &d[i++]; epoll_ctl(epollfd, EPOLL_CTL_ADD, controlfd, &e); @@@ -4062,12 -4028,6 +4061,6 @@@ e.data.ptr = &d[i++]; epoll_ctl(epollfd, EPOLL_CTL_ADD, nlfd, &e); - #ifdef LAC - d[i].type = FD_TYPE_UDPLAC; - e.data.ptr = &d[i++]; - epoll_ctl(epollfd, EPOLL_CTL_ADD, udplacfd, &e); - #endif - d[i].type = FD_TYPE_PPPOEDISC; e.data.ptr = &d[i++]; epoll_ctl(epollfd, EPOLL_CTL_ADD, pppoediscfd, &e); @@@ -4075,6 -4035,14 +4068,14 @@@ d[i].type = FD_TYPE_PPPOESESS; e.data.ptr = &d[i++]; epoll_ctl(epollfd, EPOLL_CTL_ADD, pppoesessfd, &e); + + for (j = 0; j < config->nbudpfd; j++) + { + d[i].type = FD_TYPE_UDP; + d[i].index = j; + e.data.ptr = &d[i++]; + epoll_ctl(epollfd, EPOLL_CTL_ADD, udpfd[j], &e); + } } #ifdef BGP @@@ -4136,16 -4104,12 +4137,12 @@@ struct in_addr local; socklen_t alen; int c, s; - int udp_ready = 0; - #ifdef LAC - int udplac_ready = 0; - int udplac_pkts = 0; - #endif + int udp_ready[MAX_UDPFD + 1] = INIT_TABUDPVAR; int pppoesess_ready = 0; int pppoesess_pkts = 0; int tun_ready = 0; int cluster_ready = 0; - int udp_pkts = 0; + int udp_pkts[MAX_UDPFD + 1] = INIT_TABUDPVAR; int tun_pkts = 0; int cluster_pkts = 0; #ifdef BGP @@@ -4179,10 -4143,7 +4176,7 @@@ // these are handled below, with multiple interleaved reads case FD_TYPE_CLUSTER: cluster_ready++; break; case FD_TYPE_TUN: tun_ready++; break; - case FD_TYPE_UDP: udp_ready++; break; - #ifdef LAC - case FD_TYPE_UDPLAC: udplac_ready++; break; - #endif + case FD_TYPE_UDP: udp_ready[d->index]++; break; case FD_TYPE_PPPOESESS: pppoesess_ready++; break; case FD_TYPE_PPPOEDISC: // pppoe discovery @@@ -4223,8 -4184,8 +4217,8 @@@ #ifdef BGP case FD_TYPE_BGP: - bgp_events[d->index] = events[i].events; - n--; + bgp_events[d->index] = events[i].events; + n--; break; #endif /* BGP */ @@@ -4243,7 -4204,6 +4237,6 @@@ exit(1); } else - LOG(0, 0, 0, "Got a netlink error: %s\n", strerror(-errmsg->error)); } // else it's a ack @@@ -4255,7 -4215,7 +4248,7 @@@ } default: - LOG(0, 0, 0, "Unexpected fd type returned from epoll_wait: %d\n", d->type); + LOG(0, 0, 0, "Unexpected fd type returned from epoll_wait: %d\n", d->type); } } @@@ -4265,40 -4225,25 +4258,25 @@@ for (c = 0; n && c < config->multi_read_count; c++) { - // L2TP - if (udp_ready) + for (j = 0; j < config->nbudpfd; j++) { - alen = sizeof(addr); - if ((s = recvfrom(udpfd, p, size_bufp, 0, (void *) &addr, &alen)) > 0) - { - processudp(p, s, &addr); - udp_pkts++; - } - else + // L2TP and L2TP REMOTE LNS + if (udp_ready[j]) { - udp_ready = 0; - n--; + alen = sizeof(addr); + if ((s = recvfrom(udpfd[j], p, size_bufp, 0, (void *) &addr, &alen)) > 0) + { + processudp(p, s, &addr, j); + udp_pkts[j]++; + } + else + { + udp_ready[j] = 0; + n--; + } } } - #ifdef LAC - // L2TP REMOTE LNS - if (udplac_ready) - { - alen = sizeof(addr); - if ((s = recvfrom(udplacfd, p, size_bufp, 0, (void *) &addr, &alen)) > 0) - { - if (!config->disable_lac_func) - processudp(p, s, &addr); - udplac_pkts++; - } - else - { - udplac_ready = 0; - n--; - } - } - #endif // incoming IP if (tun_ready) { @@@ -4346,18 -4291,13 +4324,13 @@@ } } - if (udp_pkts > 1 || tun_pkts > 1 || cluster_pkts > 1) + if (udp_pkts[0] > 1 || tun_pkts > 1 || cluster_pkts > 1) STAT(multi_read_used); if (c >= config->multi_read_count) { - #ifdef LAC - LOG(3, 0, 0, "Reached multi_read_count (%d); processed %d udp, %d tun %d cluster %d rmlns and %d pppoe packets\n", - config->multi_read_count, udp_pkts, tun_pkts, cluster_pkts, udplac_pkts, pppoesess_pkts); - #else LOG(3, 0, 0, "Reached multi_read_count (%d); processed %d udp, %d tun %d cluster and %d pppoe packets\n", - config->multi_read_count, udp_pkts, tun_pkts, cluster_pkts, pppoesess_pkts); - #endif + config->multi_read_count, udp_pkts[0], tun_pkts, cluster_pkts, pppoesess_pkts); STAT(multi_read_exceeded); more++; } @@@ -4692,11 -4632,7 +4665,9 @@@ static void initdata(int optdebug, cha } #endif /* BGP */ - #ifdef LAC lac_initremotelnsdata(); - #endif + + grp_initdata(); } static int assign_ip_address(sessionidt s) @@@ -4983,11 -4919,7 +4954,7 @@@ void snoop_send_packet(uint8_t *packet static int dump_session(FILE **f, sessiont *s) { - #ifdef LAC if (!s->opened || (!s->ip && !s->forwardtosession) || !(s->cin_delta || s->cout_delta) || !*s->user || s->walled_garden) - #else - if (!s->opened || !s->ip || !(s->cin_delta || s->cout_delta) || !*s->user || s->walled_garden) - #endif return 1; if (!*f) @@@ -5013,7 -4945,7 +4980,7 @@@ "# uptime: %ld\n" "# format: username ip qos uptxoctets downrxoctets\n", hostname, - fmtaddr(config->iftun_address ? config->iftun_address : my_address, 0), + fmtaddr(config->iftun_n_address[tunnel[s->tunnel].indexudp] ? config->iftun_n_address[tunnel[s->tunnel].indexudp] : my_address, 0), now, now - basetime); } @@@ -5167,7 -5099,26 +5134,26 @@@ int main(int argc, char *argv[] init_pppoe(); LOG(1, 0, 0, "Set up on pppoe interface %s\n", config->pppoe_if_to_bind); } - initudp(); + + if (!config->nbmultiaddress) + { + config->bind_n_address[0] = config->bind_address; + config->nbmultiaddress++; + } + config->nbudpfd = config->nbmultiaddress; + for (i = 0; i < config->nbudpfd; i++) + initudp(&udpfd[i], config->bind_n_address[i]); + initlacudp(); + config->indexlacudpfd = config->nbudpfd; + udpfd[config->indexlacudpfd] = udplacfd; + config->nbudpfd++; + + initcontrol(); + initdae(); + + // Intercept + snoopfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + initrad(); initippool(); @@@ -5399,14 -5350,62 +5385,62 @@@ static void update_config( if (!config->radius_dae_port) config->radius_dae_port = DAEPORT; - #ifdef LAC if(!config->bind_portremotelns) config->bind_portremotelns = L2TPLACPORT; if(!config->bind_address_remotelns) config->bind_address_remotelns = INADDR_ANY; - #endif + + if (*config->bind_multi_address) + { + char *sip = config->bind_multi_address; + char *n = sip; + char *e = config->bind_multi_address + strlen(config->bind_multi_address); + config->nbmultiaddress = 0; + + while (*sip && (sip < e)) + { + in_addr_t ip = 0; + uint8_t u = 0; + + while (n < e && (*n == ',' || *n == ' ')) n++; + + while (n < e && (isdigit(*n) || *n == '.')) + { + if (*n == '.') + { + ip = (ip << 8) + u; + u = 0; + } + else + u = u * 10 + *n - '0'; + n++; + } + ip = (ip << 8) + u; + n++; + + if (ip) + { + config->bind_n_address[config->nbmultiaddress] = htonl(ip); + config->iftun_n_address[config->nbmultiaddress] = htonl(ip); + config->nbmultiaddress++; + LOG(1, 0, 0, "Bind address %s\n", fmtaddr(htonl(ip), 0)); + } + + sip = n; + } + + if (config->nbmultiaddress >= 1) + { + config->bind_address = config->bind_n_address[0]; + config->iftun_address = config->bind_address; + } + } + if(!config->iftun_address) + { config->iftun_address = config->bind_address; + config->iftun_n_address[0] = config->iftun_address; + } if (!*config->pppoe_ac_name) strncpy(config->pppoe_ac_name, DEFAULT_PPPOE_AC_NAME, sizeof(config->pppoe_ac_name) - 1); @@@ -5618,7 -5617,6 +5652,7 @@@ int sessionsetup(sessionidt s, tunnelid 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++) @@@ -5641,11 -5639,6 +5675,11 @@@ } else cache_ipmap(session[s].ip, s); + + if ((g = grp_groupbysession(s))) + { + grp_setgrouproute(g, 1); + } } sess_local[s].lcp_authtype = 0; // RADIUS authentication complete @@@ -6470,8 -6463,6 +6504,6 @@@ int ip_filter(uint8_t *buf, int len, ui return 0; } - #ifdef LAC - tunnelidt lac_new_tunnel() { return new_tunnel(); @@@ -6517,4 -6508,3 +6549,3 @@@ void lac_tunnelshutdown(tunnelidt t, ch tunnelshutdown(t, reason, result, error, msg); } - #endif diff --combined l2tpns.h index 2274e0a,e962256..4fe9a5c --- a/l2tpns.h +++ b/l2tpns.h @@@ -24,10 -24,6 +24,10 @@@ #define MAXADDRESS 20 // Maximum length for the Endpoint Discrminiator address #define MAXSESSION 60000 // could be up to 65535 #define MAXTBFS 6000 // Maximum token bucket filters. Might need up to 2 * session. +#define MAXSESSINGRP 12 // Maximum number of member links in grouped session +#define MAXGRPINSESS 12 // Maximum number of member links in session group +#define MAXGROUPE 300 // could be up to 65535, Maximum number of grouped session +#define MAXROUTEINGRP 15 // max static routes per group // Tunnel Id reserved for pppoe #define TUNNEL_ID_PPPOE 1 @@@ -70,6 -66,13 +70,13 @@@ // it's not expected to have a space for more than 10 unassembled packets = 10 * MAXBUNDLESES #define MAXFRAGNUM_MASK (MAXFRAGNUM - 1) // Must be equal to MAXFRAGNUM-1 + // Multi bind address constants + #define MAX_UDPFD 4 + #define MAX_BINDADDR MAX_UDPFD + // 4 + 1 for the udplac + #define INIT_TABUDPFD {-1, -1, -1, -1, -1} + #define INIT_TABUDPVAR {0, 0, 0, 0, 0} + // Constants #ifndef ETCDIR #define ETCDIR "/etc/l2tpns" @@@ -211,7 -214,6 +218,7 @@@ enum typedef uint16_t sessionidt; typedef uint16_t bundleidt; typedef uint16_t tunnelidt; +typedef uint16_t groupidt; typedef uint32_t clockt; typedef uint8_t hasht[16]; @@@ -327,45 -329,12 +334,39 @@@ typedef struc char class[MAXCLASS]; uint8_t ipv6prefixlen; // IPv6 route prefix length struct in6_addr ipv6route; // Static IPv6 route - #ifdef LAC sessionidt forwardtosession; // LNS id_session to forward uint8_t src_hwaddr[ETH_ALEN]; // MAC addr source (for pppoe sessions 6 bytes) - char reserved[4]; // Space to expand structure without changing HB_VERSION + uint32_t coutgrp_delta; - #else - uint8_t src_hwaddr[ETH_ALEN]; // MAC addr source (for pppoe sessions 6 bytes) - uint32_t coutgrp_delta; - char reserved[2]; // Space to expand structure without changing HB_VERSION - #endif } sessiont; +typedef struct +{ + uint32_t tx_rate; + sessionidt sid; + uint8_t weight; +} +groupsessionidt; + +typedef struct +{ + uint32_t time_changed; + groupidt prev; + sessionidt smax; + sessionidt smin; + groupsessionidt sesslist[MAXSESSINGRP]; + routet route[MAXROUTEINGRP]; // static routes + uint8_t nbroutesgrp; + uint8_t nbsession; +} +groupsesst; + +union iphash +{ + sessionidt sess; + union iphash *idx; +}; // Mapping from IP address to session structures. + typedef struct { int state; // current state (bundlestate enum) @@@ -482,12 -451,9 +483,9 @@@ typedef struc uint16_t controlc; // outstaind messages in queue controlt *controls; // oldest message controlt *controle; // newest message - #ifdef LAC uint16_t isremotelns; // != 0 if the tunnel is to remote LNS (== index on the conf remote lns) - char reserved[14]; // Space to expand structure without changing HB_VERSION - #else - char reserved[16]; // Space to expand structure without changing HB_VERSION - #endif + uint16_t indexudp; // Index UDP file handle (in udpfd[]) + char reserved[12]; // Space to expand structure without changing HB_VERSION } tunnelt; @@@ -798,20 -764,23 +796,24 @@@ typedef struc int idle_echo_timeout; // Time between last packet seen and // Drop sessions who have not responded within IDLE_ECHO_TIMEOUT seconds in_addr_t iftun_address; - #ifdef LAC int disable_lac_func; int auth_tunnel_change_addr_src; int highest_rlnsid; uint16_t bind_portremotelns; in_addr_t bind_address_remotelns; - #endif char pppoe_if_to_bind[IFNAMSIZ]; // Name pppoe interface to bind char pppoe_service_name[64]; // pppoe service name char pppoe_ac_name[64]; uint8_t pppoe_hwaddr[ETH_ALEN]; // MAC addr of interface pppoe to bind int disable_sending_hello; // Disable l2tp sending HELLO message for Apple compatibility. int disable_no_spoof; // Disable no spoof (permit load balancing client --> internet) + int nbudpfd; // number UDP file handle + int nbmultiaddress; // number multi address to bind + int indexlacudpfd; // Index UDP LAC file handle (in udpfd[]) + in_addr_t bind_n_address[MAX_BINDADDR]; + in_addr_t iftun_n_address[MAX_BINDADDR]; + char bind_multi_address[256]; + int grp_txrate_average_time; // caculation txrate average time (default 10s) } configt; enum config_typet { INT, STRING, UNSIGNED_LONG, SHORT, BOOL, IPv4, IPv6 }; @@@ -947,9 -916,7 +949,7 @@@ void radiusretry(uint16_t r) uint16_t radiusnew(sessionidt s); void radiusclear(uint16_t r, sessionidt s); void processdae(uint8_t *buf, int len, struct sockaddr_in *addr, int alen, struct in_addr *local); - #ifdef LAC int rad_tunnel_pwdecode(uint8_t *pl2tpsecret, size_t *pl2tpsecretlen, const char *radiussecret, const uint8_t * auth); - #endif // l2tpns.c clockt backoff(uint8_t try); @@@ -969,7 -936,7 +969,7 @@@ int tun_write(uint8_t *data, int size) void adjust_tcp_mss(sessionidt s, tunnelidt t, uint8_t *buf, int len, uint8_t *tcp); void sendipcp(sessionidt s, tunnelidt t); void sendipv6cp(sessionidt s, tunnelidt t); - void processudp(uint8_t *buf, int len, struct sockaddr_in *addr); + void processudp(uint8_t *buf, int len, struct sockaddr_in *addr, uint16_t indexudpfd); void processipout(uint8_t *buf, int len); void snoop_send_packet(uint8_t *packet, uint16_t size, in_addr_t destination, uint16_t port); int find_filter(char const *name, size_t len); @@@ -977,28 -944,12 +977,26 @@@ int ip_filter(uint8_t *buf, int len, ui int cmd_show_ipcache(struct cli_def *cli, char *command, char **argv, int argc); int cmd_show_hist_idle(struct cli_def *cli, char *command, char **argv, int argc); int cmd_show_hist_open(struct cli_def *cli, char *command, char **argv, int argc); +void netlink_addattr(struct nlmsghdr *nh, int type, const void *data, int alen); +ssize_t netlink_send(struct nlmsghdr *nh); +void cache_ipmap(in_addr_t ip, sessionidt s); + - #ifdef LAC tunnelidt lac_new_tunnel(); void lac_tunnelclear(tunnelidt t); void lac_send_SCCRQ(tunnelidt t, uint8_t * auth, unsigned int auth_len); void lac_send_ICRQ(tunnelidt t, sessionidt s); void lac_tunnelshutdown(tunnelidt t, char *reason, int result, int error, char *msg); - #endif +// grpsess.c +sessionidt grp_getnextsession(groupidt g, in_addr_t ip); +void grp_initdata(void); +void grp_processvendorspecific(sessionidt s, uint8_t *pvs); +groupidt grp_groupbysession(sessionidt s); +groupidt grp_groupbyip(in_addr_t ip); +void grp_setgrouproute(groupidt g, int add); +void grp_time_changed(void); +void grp_removesession(groupidt g, sessionidt s); + #undef LOG #undef LOG_HEX #define LOG(D, s, t, f, ...) ({ if (D <= config->debug) _log(D, s, t, f, ## __VA_ARGS__); }) @@@ -1033,8 -984,6 +1031,8 @@@ extern bundlet *bundle extern sessiont *session; extern sessionlocalt *sess_local; extern ippoolt *ip_address_pool; +extern groupsesst *grpsession; +groupidt gnextgrpid; #define sessionfree (session[0].next) @@@ -1047,8 -996,6 +1045,8 @@@ extern struct Tstats *_statistics extern in_addr_t my_address; extern int clifd; extern int epollfd; +extern int tunidx; // ifr_ifindex of tun device +extern union iphash ip_hash[256]; struct event_data { enum { @@@ -1061,13 -1008,10 +1059,10 @@@ FD_TYPE_RADIUS, FD_TYPE_BGP, FD_TYPE_NETLINK, - #ifdef LAC - FD_TYPE_UDPLAC, - #endif FD_TYPE_PPPOEDISC, FD_TYPE_PPPOESESS } type; - int index; // for RADIUS, BGP + int index; // for RADIUS, BGP, UDP }; #define TIME (config->current_time) diff --combined ppp.c index 5c4e51b,960a269..c8e128e --- a/ppp.c +++ b/ppp.c @@@ -5,9 -5,6 +5,9 @@@ #include #include #include +#include +#include + #include "l2tpns.h" #include "constants.h" #include "plugin.h" @@@ -15,9 -12,7 +15,7 @@@ #include "tbf.h" #include "cluster.h" - #ifdef LAC #include "l2tplac.h" - #endif #include "pppoe.h" extern tunnelt *tunnel; @@@ -108,13 -103,11 +106,11 @@@ void processpap(sessionidt s, tunnelid LOG(3, s, t, "PAP login %s/%s\n", user, pass); } - #ifdef LAC if ((!config->disable_lac_func) && lac_conf_forwardtoremotelns(s, user)) { // Creating a tunnel/session has been started return; } - #endif if (session[s].ip || !(r = radiusnew(s))) { @@@ -267,7 -260,6 +263,6 @@@ void processchap(sessionidt s, tunnelid packet.username = calloc(l + 1, 1); memcpy(packet.username, p, l); - #ifdef LAC if ((!config->disable_lac_func) && lac_conf_forwardtoremotelns(s, packet.username)) { free(packet.username); @@@ -275,7 -267,6 +270,6 @@@ // Creating a tunnel/session has been started return; } - #endif run_plugins(PLUGIN_PRE_AUTH, &packet); if (!packet.continue_auth) diff --combined pppoe.c index ca1c5e4,01cc153..f804b0e --- a/pppoe.c +++ b/pppoe.c @@@ -21,7 -21,6 +21,7 @@@ #include #include #include +#include #include "l2tpns.h" #include "cluster.h" @@@ -903,7 -902,6 +903,6 @@@ void process_pppoe_disc(uint8_t *pack, } } - #ifdef LAC // Forward from pppoe to l2tp remote LNS static void pppoe_forwardto_session_rmlns(uint8_t *pack, int size, sessionidt sess, uint16_t proto) { @@@ -957,7 -955,6 +956,7 @@@ // Update STAT OUT increment_counter(&session[s].cout, &session[s].cout_wrap, ll2tp); // byte count session[s].cout_delta += ll2tp; + session[s].coutgrp_delta += ll2tp; session[s].pout++; sess_local[s].cout += ll2tp; sess_local[s].pout++; @@@ -1029,7 -1026,6 +1028,7 @@@ void pppoe_forwardto_session_pppoe(uint // Update STAT OUT increment_counter(&session[s].cout, &session[s].cout_wrap, lpppoe); // byte count session[s].cout_delta += lpppoe; + session[s].coutgrp_delta += lpppoe; session[s].pout++; sess_local[s].cout += lpppoe; sess_local[s].pout++; @@@ -1039,7 -1035,6 +1038,6 @@@ tunnelsend(p, lpppoe, t); // send it.... } - #endif void process_pppoe_sess(uint8_t *pack, int size) { @@@ -1104,13 -1099,11 +1102,11 @@@ lppp -= 2; } - #ifdef LAC if (session[sid].forwardtosession) { // Must be forwaded to a remote lns tunnel l2tp pppoe_forwardto_session_rmlns(pack, size, sid, proto); return; } - #endif if (proto == PPPPAP) { diff --combined radius.c index 6b6be70,8481561..266f100 --- a/radius.c +++ b/radius.c @@@ -11,7 -11,6 +11,7 @@@ #include #include #include +#include #include "md5.h" #include "constants.h" @@@ -20,9 -19,7 +20,7 @@@ #include "util.h" #include "cluster.h" - #ifdef LAC #include "l2tplac.h" - #endif #include "pppoe.h" extern radiust *radius; @@@ -538,9 -535,7 +536,7 @@@ void processrad(uint8_t *buf, int len, uint8_t routes = 0; int r_code; int r_id; - #ifdef LAC int OpentunnelReq = 0; - #endif CSTAT(processrad); @@@ -642,11 -637,10 +638,10 @@@ // Extract IP, routes, etc uint8_t *p = buf + 20; uint8_t *e = buf + len; - #ifdef LAC uint8_t tag; uint8_t strtemp[256]; lac_reset_rad_tag_tunnel_ctxt(); - #endif + for (; p + 2 <= e && p[1] && p + p[1] <= e; p += p[1]) { if (*p == 26 && p[1] >= 7) @@@ -669,19 -663,11 +664,19 @@@ else if (vendor == 529 && attrib >= 135 && attrib <= 136) // Ascend { // handle old-format ascend DNS attributes below - p += 6; + p += 6; + } + else if (vendor == 64520) // Sames + { + //Sames vendor-specific 64520 + uint8_t *pvs = p + 6; // pvs set to begin to attribute + LOG(3, s, session[s].tunnel, " Sames vendor-specific: %d, Attrib: %d, lenght: %d\n", vendor, attrib, attrib_length); + grp_processvendorspecific(s, pvs); + continue; } else { - LOG(3, s, session[s].tunnel, " Unknown vendor-specific\n"); + LOG(3, s, session[s].tunnel, " Unknown vendor-specific: %d, Attrib: %d\n", vendor, attrib); continue; } } @@@ -849,7 -835,6 +844,6 @@@ session[s].classlen = MAXCLASS; memcpy(session[s].class, p + 2, session[s].classlen); } - #ifdef LAC else if (*p == 64) { // Tunnel-Type @@@ -938,7 -923,6 +932,6 @@@ // Fill context lac_set_rad_tag_tunnel_assignment_id(tag, (char *) strtemp); } - #endif } } else if (r_code == AccessReject) @@@ -948,7 -932,6 +941,6 @@@ break; } - #ifdef LAC if ((!config->disable_lac_func) && OpentunnelReq) { char assignment_id[256]; @@@ -1005,7 -988,6 +997,6 @@@ LOG(3, s, session[s].tunnel, " PAP User %s authentication %s.\n", session[s].user, (r_code == AccessAccept) ? "allowed" : "denied"); } - #endif if (!session[s].dns1 && config->default_dns1) { @@@ -1350,7 -1332,6 +1341,6 @@@ void processdae(uint8_t *buf, int len, LOG(0, 0, 0, "Error sending DAE response packet: %s\n", strerror(errno)); } - #ifdef LAC // Decrypte the encrypted Tunnel Password. // Defined in RFC-2868. // the pl2tpsecret buffer must set to 256 characters. @@@ -1441,4 -1422,3 +1431,3 @@@ int rad_tunnel_pwdecode(uint8_t *pl2tps return decodedlen; }; - #endif /* LAC */ diff --combined util.c index 65f8dc3,bbf94ba..e412fc1 --- a/util.c +++ b/util.c @@@ -8,7 -8,6 +8,7 @@@ #include #include #include +#include #include "l2tpns.h" #ifdef BGP @@@ -52,100 -51,109 +52,109 @@@ void *shared_malloc(unsigned int size } extern int forked; - extern int cluster_sockfd, tunfd, udpfd, controlfd, daefd, snoopfd, ifrfd, ifr6fd, rand_fd; + extern int cluster_sockfd, tunfd, controlfd, daefd, snoopfd, ifrfd, ifr6fd, rand_fd; + extern int pppoediscfd, pppoesessfd; extern int *radfds; + extern int udpfd[MAX_UDPFD + 1]; pid_t fork_and_close() { - pid_t pid = fork(); - int i; - - if (pid) - return pid; - - forked++; - if (config->scheduler_fifo) - { - struct sched_param params = {0}; - params.sched_priority = 0; - if (sched_setscheduler(0, SCHED_OTHER, ¶ms)) + pid_t pid = fork(); + int i; + + if (pid) + return pid; + + forked++; + if (config->scheduler_fifo) + { + struct sched_param params = {0}; + params.sched_priority = 0; + if (sched_setscheduler(0, SCHED_OTHER, ¶ms)) + { + LOG(0, 0, 0, "Error setting scheduler to OTHER after fork: %s\n", strerror(errno)); + LOG(0, 0, 0, "This is probably really really bad.\n"); + } + } + + signal(SIGPIPE, SIG_DFL); + signal(SIGCHLD, SIG_DFL); + signal(SIGHUP, SIG_DFL); + signal(SIGUSR1, SIG_DFL); + signal(SIGQUIT, SIG_DFL); + signal(SIGKILL, SIG_DFL); + signal(SIGTERM, SIG_DFL); + + // Close sockets + if (clifd != -1) close(clifd); + if (cluster_sockfd != -1) close(cluster_sockfd); + if (tunfd != -1) close(tunfd); + + for (i = 0; i < config->nbudpfd; i++) { - LOG(0, 0, 0, "Error setting scheduler to OTHER after fork: %s\n", strerror(errno)); - LOG(0, 0, 0, "This is probably really really bad.\n"); + if (udpfd[i] != -1) close(udpfd[i]); } - } - - signal(SIGPIPE, SIG_DFL); - signal(SIGCHLD, SIG_DFL); - signal(SIGHUP, SIG_DFL); - signal(SIGUSR1, SIG_DFL); - signal(SIGQUIT, SIG_DFL); - signal(SIGKILL, SIG_DFL); - signal(SIGTERM, SIG_DFL); - - // Close sockets - if (clifd != -1) close(clifd); - if (cluster_sockfd != -1) close(cluster_sockfd); - if (tunfd != -1) close(tunfd); - if (udpfd != -1) close(udpfd); - if (controlfd != -1) close(controlfd); - if (daefd != -1) close(daefd); - if (snoopfd != -1) close(snoopfd); - if (rand_fd != -1) close(rand_fd); - if (epollfd != -1) close(epollfd); - - for (i = 0; radfds && i < RADIUS_FDS; i++) - close(radfds[i]); + + if (pppoediscfd != -1) close(pppoediscfd); + if (pppoediscfd != -1) close(pppoediscfd); + if (controlfd != -1) close(controlfd); + if (daefd != -1) close(daefd); + if (snoopfd != -1) close(snoopfd); + if (rand_fd != -1) close(rand_fd); + if (epollfd != -1) close(epollfd); + + for (i = 0; radfds && i < RADIUS_FDS; i++) + close(radfds[i]); #ifdef BGP - for (i = 0; i < BGP_NUM_PEERS; i++) - if (bgp_peers[i].sock != -1) - close(bgp_peers[i].sock); + for (i = 0; i < BGP_NUM_PEERS; i++) + if (bgp_peers[i].sock != -1) + close(bgp_peers[i].sock); #endif /* BGP */ return pid; } ssize_t recvfromto(int s, void *buf, size_t len, int flags, - struct sockaddr *from, socklen_t *fromlen, struct in_addr *toaddr) + struct sockaddr *from, socklen_t *fromlen, struct in_addr *toaddr) { - ssize_t r; - struct msghdr msg; - struct cmsghdr *cmsg; - struct iovec vec; - char cbuf[128]; + ssize_t r; + struct msghdr msg; + struct cmsghdr *cmsg; + struct iovec vec; + char cbuf[128]; - memset(&msg, 0, sizeof(msg)); - msg.msg_name = from; - msg.msg_namelen = *fromlen; + memset(&msg, 0, sizeof(msg)); + msg.msg_name = from; + msg.msg_namelen = *fromlen; - vec.iov_base = buf; - vec.iov_len = len; - msg.msg_iov = &vec; - msg.msg_iovlen = 1; - msg.msg_flags = 0; + vec.iov_base = buf; + vec.iov_len = len; + msg.msg_iov = &vec; + msg.msg_iovlen = 1; + msg.msg_flags = 0; - msg.msg_control = cbuf; - msg.msg_controllen = sizeof(cbuf); + msg.msg_control = cbuf; + msg.msg_controllen = sizeof(cbuf); - if ((r = recvmsg(s, &msg, flags)) < 0) - return r; + if ((r = recvmsg(s, &msg, flags)) < 0) + return r; - if (fromlen) - *fromlen = msg.msg_namelen; + if (fromlen) + *fromlen = msg.msg_namelen; - memset(toaddr, 0, sizeof(*toaddr)); - for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) - { - if (cmsg->cmsg_level == SOL_IP && cmsg->cmsg_type == IP_PKTINFO) + memset(toaddr, 0, sizeof(*toaddr)); + for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) { - struct in_pktinfo *i = (struct in_pktinfo *) CMSG_DATA(cmsg); - memcpy(toaddr, &i->ipi_addr, sizeof(*toaddr)); - break; + if (cmsg->cmsg_level == SOL_IP && cmsg->cmsg_type == IP_PKTINFO) + { + struct in_pktinfo *i = (struct in_pktinfo *) CMSG_DATA(cmsg); + memcpy(toaddr, &i->ipi_addr, sizeof(*toaddr)); + break; + } } - } - return r; + return r; } ssize_t sendtofrom(int s, void const *buf, size_t len, int flags,