X-Git-Url: http://git.sameswireless.fr/l2tpns.git/blobdiff_plain/5e65215ed4758c8fcd26ecaadc4b6121b93dab1c..eecccf0b30d5ec19960633d1b62cf5f9936d1f16:/l2tpns.c diff --git a/l2tpns.c b/l2tpns.c index 694726d..34e4a7a 100644 --- a/l2tpns.c +++ b/l2tpns.c @@ -56,6 +56,7 @@ #ifdef LAC #include "l2tplac.h" #endif +#include "pppoe.h" #ifdef LAC char * Vendor_name = "Linux L2TPNS"; @@ -80,7 +81,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 @@ -97,10 +98,7 @@ 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 { - 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,11 +176,21 @@ config_descriptt config_values[] = { #endif CONFIG("echo_timeout", echo_timeout, INT), 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 - { NULL, 0, 0, 0 }, + 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("grp_txrate_average_time", grp_txrate_average_time, INT), + { NULL, 0, 0, 0 } }; static char *plugin_functions[] = { @@ -210,6 +218,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. @@ -220,9 +229,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); @@ -251,12 +257,14 @@ 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 - time_now_ms = (t.tv_sec * 1000) + (t.tv_usec/1000); + // TODO FOR MLPPP DEV + //time_now_ms = (t.tv_sec * 1000) + (t.tv_usec/1000); return (t.tv_sec - basetime) * 10 + t.tv_usec / 100000 + 1; } @@ -292,7 +300,7 @@ void _log(int level, sessionidt s, tunnelidt t, const char *format, ...) ringbuffer->buffer[ringbuffer->tail].session = s; ringbuffer->buffer[ringbuffer->tail].tunnel = t; va_start(ap, format); - vsnprintf(ringbuffer->buffer[ringbuffer->tail].message, 4095, format, ap); + vsnprintf(ringbuffer->buffer[ringbuffer->tail].message, MAX_LOG_LENGTH, format, ap); va_end(ap); } #endif @@ -610,7 +618,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; @@ -646,7 +654,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; @@ -687,15 +695,19 @@ static void inittun(void) int flags = fcntl(tunfd, F_GETFL, 0); fcntl(tunfd, F_SETFL, flags | O_NONBLOCK); } + + if (*config->tundevicename) + strncpy(ifr.ifr_name, config->tundevicename, IFNAMSIZ); + if (ioctl(tunfd, TUNSETIFF, (void *) &ifr) < 0) { LOG(0, 0, 0, "Can't set tun interface: %s\n", strerror(errno)); exit(1); } - assert(strlen(ifr.ifr_name) < sizeof(config->tundevice) - 1); - strncpy(config->tundevice, ifr.ifr_name, sizeof(config->tundevice)); + assert(strlen(ifr.ifr_name) < sizeof(config->tundevicename) - 1); + strncpy(config->tundevicename, ifr.ifr_name, sizeof(config->tundevicename)); - tunidx = if_nametoindex(config->tundevice); + tunidx = if_nametoindex(config->tundevicename); if (tunidx == 0) { LOG(0, 0, 0, "Can't get tun interface index\n"); @@ -747,8 +759,8 @@ static void inittun(void) req.ifmsg.ifaddr.ifa_scope = RT_SCOPE_UNIVERSE; req.ifmsg.ifaddr.ifa_index = tunidx; - if (config->bind_address) - ip = config->bind_address; + if (config->iftun_address) + ip = config->iftun_address; else ip = 0x01010101; // 1.1.1.1 netlink_addattr(&req.nh, IFA_LOCAL, &ip, sizeof(ip)); @@ -878,6 +890,7 @@ static void initudp(void) 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)); { @@ -987,7 +1000,7 @@ sessionidt sessionbyipv6(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; @@ -1185,6 +1198,12 @@ void tunnelsend(uint8_t * buf, uint16_t l, tunnelidt t) return; } + if (t == TUNNEL_ID_PPPOE) + { + pppoe_sess_send(buf, l, t); + return; + } + if (!tunnel[t].ip) { LOG(1, 0, t, "Error sending data out tunnel: no remote endpoint (tunnel not set up)\n"); @@ -1353,6 +1372,7 @@ static void update_session_out_stat(sessionidt s, sessiont *sp, int len) { 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; @@ -1366,6 +1386,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; @@ -1402,7 +1423,31 @@ void processipout(uint8_t *buf, int len) } 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. @@ -1604,17 +1649,15 @@ void processipout(uint8_t *buf, int len) else { // Send it as one frame (NO MPPP Frame) - uint8_t *p = makeppp(fragbuf, sizeof(fragbuf), buf, len, s, t, PPPIP, 0, 0, 0); - if (!p) return; - tunnelsend(fragbuf, len + (p-fragbuf), t); // send it... + uint8_t *p = opt_makeppp(buf, len, s, t, PPPIP, 0, 0, 0); + tunnelsend(p, len + (buf-p), t); // send it... update_session_out_stat(s, sp, len); } } else { - uint8_t *p = makeppp(fragbuf, sizeof(fragbuf), buf, len, s, t, PPPIP, 0, 0, 0); - if (!p) return; - tunnelsend(fragbuf, len + (p-fragbuf), t); // send it... + uint8_t *p = opt_makeppp(buf, len, s, t, PPPIP, 0, 0, 0); + tunnelsend(p, len + (buf-p), t); // send it... update_session_out_stat(s, sp, len); } @@ -1739,6 +1782,7 @@ static void processipv6out(uint8_t * buf, int len) increment_counter(&sp->cout, &sp->cout_wrap, len); // byte count sp->cout_delta += len; + sp->coutgrp_delta += len; sp->pout++; udp_tx += len; @@ -1788,6 +1832,7 @@ static void send_ipout(sessionidt s, uint8_t *buf, int len) increment_counter(&sp->cout, &sp->cout_wrap, len); // byte count sp->cout_delta += len; + sp->coutgrp_delta += len; sp->pout++; udp_tx += len; @@ -2006,7 +2051,6 @@ void sessionshutdown(sessionidt s, char const *reason, int cdn_result, int cdn_e struct param_kill_session data = { &tunnel[session[s].tunnel], &session[s] }; LOG(2, s, session[s].tunnel, "Shutting down session %u: %s\n", s, reason); run_plugins(PLUGIN_KILL_SESSION, &data); - session[s].die = TIME + 150; // Clean up in 15 seconds } if (session[s].ip && !walled_garden && !session[s].die) @@ -2031,8 +2075,11 @@ void sessionshutdown(sessionidt s, char const *reason, int cdn_result, int cdn_e memcpy(&shut_acct[shut_acct_n++], &session[s], sizeof(session[s])); } + if (!session[s].die) + 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++) @@ -2124,20 +2171,28 @@ void sessionshutdown(sessionidt s, char const *reason, int cdn_result, int cdn_e throttle_session(s, 0, 0); if (cdn_result) - { // Send CDN - controlt *c = controlnew(14); // sending CDN - if (cdn_error) + { + if (session[s].tunnel == TUNNEL_ID_PPPOE) { - uint16_t buf[2]; - buf[0] = htons(cdn_result); - buf[1] = htons(cdn_error); - controlb(c, 1, (uint8_t *)buf, 4, 1); + pppoe_shutdown_session(s); } else - control16(c, 1, cdn_result, 1); + { + // Send CDN + controlt *c = controlnew(14); // sending CDN + if (cdn_error) + { + uint16_t buf[2]; + buf[0] = htons(cdn_result); + buf[1] = htons(cdn_error); + controlb(c, 1, (uint8_t *)buf, 4, 1); + } + else + control16(c, 1, cdn_result, 1); - control16(c, 14, s, 1); // assigned session (our end) - controladd(c, session[s].far, session[s].tunnel); // send the message + control16(c, 14, s, 1); // assigned session (our end) + controladd(c, session[s].far, session[s].tunnel); // send the message + } } // update filter refcounts @@ -2177,7 +2232,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->bind_address ? config->bind_address : + config->iftun_address ? config->iftun_address : my_address; // send my IP tunnelsend(buf, 10 + (q - buf), t); // send it @@ -2224,6 +2279,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 @@ -2254,6 +2311,12 @@ void sessionkill(sessionidt s, char *reason) #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); } @@ -2404,6 +2467,12 @@ void processudp(uint8_t *buf, int len, struct sockaddr_in *addr) STAT(tunnel_rx_errors); return; } + if (t == TUNNEL_ID_PPPOE) + { + LOG(1, s, t, "Received UDP packet with tunnel ID reserved for pppoe\n"); + STAT(tunnel_rx_errors); + return; + } if (*buf & 0x08) { // ns/nr ns = ntohs(*(uint16_t *) p); @@ -3062,6 +3131,7 @@ void processudp(uint8_t *buf, int len, struct sockaddr_in *addr) tunnelshutdown(t, "Stopped", 0, 0, 0); // Shut down cleanly break; case 6: // HELLO + LOG(3, s, t, "Received HELLO\n"); controlnull(t); // simply ACK break; case 7: // OCRQ @@ -3157,7 +3227,7 @@ void processudp(uint8_t *buf, int len, struct sockaddr_in *addr) // Set multilink options before sending initial LCP packet sess_local[s].mp_mrru = 1614; - sess_local[s].mp_epdis = ntohl(config->bind_address ? config->bind_address : my_address); + sess_local[s].mp_epdis = ntohl(config->iftun_address ? config->iftun_address : my_address); sendlcp(s, t); change_state(s, lcp, RequestSent); @@ -3219,10 +3289,22 @@ void processudp(uint8_t *buf, int len, struct sockaddr_in *addr) if (session[s].forwardtosession) { LOG(5, s, t, "Forwarding data session to session %u\n", session[s].forwardtosession); - // Forward to LAC or Remote LNS session - lac_session_forward(buf, len, s, proto); + // Forward to LAC/BAS or Remote LNS session + lac_session_forward(buf, len, s, proto, addr->sin_addr.s_addr, addr->sin_port); return; } + else if (config->auth_tunnel_change_addr_src) + { + if (tunnel[t].ip != ntohl(addr->sin_addr.s_addr) && + tunnel[t].port == ntohs(addr->sin_port)) + { + // The remotes BAS are a clustered l2tpns server and the source IP has changed + LOG(5, s, t, "The tunnel IP source (%s) has changed by new IP (%s)\n", + fmtaddr(htonl(tunnel[t].ip), 0), fmtaddr(addr->sin_addr.s_addr, 0)); + + tunnel[t].ip = ntohl(addr->sin_addr.s_addr); + } + } #endif /* LAC */ if (s && !session[s].opened) // Is something wrong?? @@ -3418,6 +3500,9 @@ static void regular_cleanups(double period) if (t > config->cluster_highest_tunnelid) t = 1; + if (t == TUNNEL_ID_PPPOE) + continue; + // check for expired tunnels if (tunnel[t].die && tunnel[t].die <= TIME) { @@ -3450,10 +3535,13 @@ static void regular_cleanups(double period) // Send hello if (tunnel[t].state == TUNNELOPEN && !tunnel[t].controlc && (time_now - tunnel[t].lastrec) > 60) { - controlt *c = controlnew(6); // sending HELLO - controladd(c, 0, t); // send the message - LOG(3, 0, t, "Sending HELLO message\n"); - t_actions++; + if (!config->disable_sending_hello) + { + controlt *c = controlnew(6); // sending HELLO + controladd(c, 0, t); // send the message + LOG(3, 0, t, "Sending HELLO message\n"); + t_actions++; + } } // Check for tunnel changes requested from the CLI @@ -3627,7 +3715,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]; @@ -3641,7 +3729,8 @@ static void regular_cleanups(double period) 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 + + tunnelsend(b, (q - b) + 8, session[s].tunnel); // send it sess_local[s].last_echo = time_now; s_actions++; } @@ -3893,11 +3982,11 @@ static int still_busy(void) #endif #ifdef LAC -// the base set of fds polled: cli, cluster, tun, udp, control, dae, netlink, udplac -#define BASE_FDS 8 +// 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 -#define BASE_FDS 7 +// the base set of fds polled: cli, cluster, tun, udp, control, dae, netlink, pppoedisc, pppoesess +#define BASE_FDS 9 #endif // additional polled fds @@ -3912,8 +4001,9 @@ static void mainloop(void) { int i; uint8_t buf[65536]; - uint8_t *p = buf + 8; // for the hearder of the forwarded MPPP packet (see C_MPPP_FORWARD) - int size_bufp = sizeof(buf) - 8; + uint8_t *p = buf + 32; // for the hearder of the forwarded MPPP packet (see C_MPPP_FORWARD) + // and the forwarded pppoe session + int size_bufp = sizeof(buf) - 32; clockt next_cluster_ping = 0; // send initial ping immediately struct epoll_event events[BASE_FDS + RADIUS_FDS + EXTRA_FDS]; int maxevent = sizeof(events)/sizeof(*events); @@ -3925,11 +4015,11 @@ static void mainloop(void) } #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\n", - clifd, cluster_sockfd, tunfd, udpfd, controlfd, daefd, nlfd, udplacfd); + 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\n", - clifd, cluster_sockfd, tunfd, udpfd, controlfd, daefd, nlfd); + 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 /* setup our fds to poll for input */ @@ -3976,6 +4066,14 @@ static void mainloop(void) 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); + + d[i].type = FD_TYPE_PPPOESESS; + e.data.ptr = &d[i++]; + epoll_ctl(epollfd, EPOLL_CTL_ADD, pppoesessfd, &e); } #ifdef BGP @@ -4042,6 +4140,8 @@ static void mainloop(void) int udplac_ready = 0; int udplac_pkts = 0; #endif + int pppoesess_ready = 0; + int pppoesess_pkts = 0; int tun_ready = 0; int cluster_ready = 0; int udp_pkts = 0; @@ -4082,28 +4182,36 @@ static void mainloop(void) #ifdef LAC case FD_TYPE_UDPLAC: udplac_ready++; break; #endif + case FD_TYPE_PPPOESESS: pppoesess_ready++; break; + + case FD_TYPE_PPPOEDISC: // pppoe discovery + s = read(pppoediscfd, p, size_bufp); + if (s > 0) process_pppoe_disc(p, s); + n--; + break; + case FD_TYPE_CONTROL: // nsctl commands alen = sizeof(addr); - s = recvfromto(controlfd, buf, sizeof(buf), MSG_WAITALL, (struct sockaddr *) &addr, &alen, &local); - if (s > 0) processcontrol(buf, s, &addr, alen, &local); + s = recvfromto(controlfd, p, size_bufp, MSG_WAITALL, (struct sockaddr *) &addr, &alen, &local); + if (s > 0) processcontrol(p, s, &addr, alen, &local); n--; break; case FD_TYPE_DAE: // DAE requests alen = sizeof(addr); - s = recvfromto(daefd, buf, sizeof(buf), MSG_WAITALL, (struct sockaddr *) &addr, &alen, &local); - if (s > 0) processdae(buf, s, &addr, alen, &local); + s = recvfromto(daefd, p, size_bufp, MSG_WAITALL, (struct sockaddr *) &addr, &alen, &local); + if (s > 0) processdae(p, s, &addr, alen, &local); n--; break; case FD_TYPE_RADIUS: // RADIUS response alen = sizeof(addr); - s = recvfrom(radfds[d->index], buf, sizeof(buf), MSG_WAITALL, (struct sockaddr *) &addr, &alen); + s = recvfrom(radfds[d->index], p, size_bufp, MSG_WAITALL, (struct sockaddr *) &addr, &alen); if (s >= 0 && config->cluster_iam_master) { if (addr.sin_addr.s_addr == config->radiusserver[0] || addr.sin_addr.s_addr == config->radiusserver[1]) - processrad(buf, s, d->index); + processrad(p, s, d->index); else LOG(3, 0, 0, "Dropping RADIUS packet from unknown source %s\n", fmtaddr(addr.sin_addr.s_addr, 0)); @@ -4121,8 +4229,8 @@ static void mainloop(void) case FD_TYPE_NETLINK: { - struct nlmsghdr *nh = (struct nlmsghdr *)buf; - s = netlink_recv(buf, sizeof(buf)); + struct nlmsghdr *nh = (struct nlmsghdr *)p; + s = netlink_recv(p, size_bufp); if (nh->nlmsg_type == NLMSG_ERROR) { struct nlmsgerr *errmsg = NLMSG_DATA(nh); @@ -4160,9 +4268,9 @@ static void mainloop(void) if (udp_ready) { alen = sizeof(addr); - if ((s = recvfrom(udpfd, buf, sizeof(buf), 0, (void *) &addr, &alen)) > 0) + if ((s = recvfrom(udpfd, p, size_bufp, 0, (void *) &addr, &alen)) > 0) { - processudp(buf, s, &addr); + processudp(p, s, &addr); udp_pkts++; } else @@ -4176,10 +4284,10 @@ static void mainloop(void) if (udplac_ready) { alen = sizeof(addr); - if ((s = recvfrom(udplacfd, buf, sizeof(buf), 0, (void *) &addr, &alen)) > 0) + if ((s = recvfrom(udplacfd, p, size_bufp, 0, (void *) &addr, &alen)) > 0) { if (!config->disable_lac_func) - processudp(buf, s, &addr); + processudp(p, s, &addr); udplac_pkts++; } @@ -4196,7 +4304,7 @@ static void mainloop(void) if ((s = read(tunfd, p, size_bufp)) > 0) { processtun(p, s); - tun_pkts++; + tun_pkts++; } else { @@ -4205,13 +4313,28 @@ static void mainloop(void) } } + // pppoe session + if (pppoesess_ready) + { + if ((s = read(pppoesessfd, p, size_bufp)) > 0) + { + process_pppoe_sess(p, s); + pppoesess_pkts++; + } + else + { + pppoesess_ready = 0; + n--; + } + } + // cluster if (cluster_ready) { alen = sizeof(addr); - if ((s = recvfrom(cluster_sockfd, buf, sizeof(buf), MSG_WAITALL, (void *) &addr, &alen)) > 0) + if ((s = recvfrom(cluster_sockfd, p, size_bufp, MSG_WAITALL, (void *) &addr, &alen)) > 0) { - processcluster(buf, s, addr.sin_addr.s_addr); + processcluster(p, s, addr.sin_addr.s_addr); cluster_pkts++; } else @@ -4228,11 +4351,11 @@ static void mainloop(void) if (c >= config->multi_read_count) { #ifdef LAC - LOG(3, 0, 0, "Reached multi_read_count (%d); processed %d udp, %d tun and %d cluster %d rmlns packets\n", - config->multi_read_count, udp_pkts, tun_pkts, cluster_pkts, udplac_pkts); + 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 and %d cluster packets\n", - config->multi_read_count, udp_pkts, tun_pkts, cluster_pkts); + 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 STAT(multi_read_exceeded); more++; @@ -4571,6 +4694,8 @@ static void initdata(int optdebug, char *optconfig) #ifdef LAC lac_initremotelnsdata(); #endif + + grp_initdata(); } static int assign_ip_address(sessionidt s) @@ -4887,7 +5012,7 @@ static int dump_session(FILE **f, sessiont *s) "# uptime: %ld\n" "# format: username ip qos uptxoctets downrxoctets\n", hostname, - fmtaddr(config->bind_address ? config->bind_address : my_address, 0), + fmtaddr(config->iftun_address ? config->iftun_address : my_address, 0), now, now - basetime); } @@ -5034,8 +5159,13 @@ int main(int argc, char *argv[]) exit(1); inittun(); - LOG(1, 0, 0, "Set up on interface %s\n", config->tundevice); + LOG(1, 0, 0, "Set up on interface %s\n", config->tundevicename); + if (*config->pppoe_if_to_bind) + { + init_pppoe(); + LOG(1, 0, 0, "Set up on pppoe interface %s\n", config->pppoe_if_to_bind); + } initudp(); initrad(); initippool(); @@ -5271,7 +5401,14 @@ static void update_config() #ifdef LAC if(!config->bind_portremotelns) config->bind_portremotelns = L2TPLACPORT; + if(!config->bind_address_remotelns) + config->bind_address_remotelns = INADDR_ANY; #endif + if(!config->iftun_address) + config->iftun_address = config->bind_address; + + if (!*config->pppoe_ac_name) + strncpy(config->pppoe_ac_name, DEFAULT_PPPOE_AC_NAME, sizeof(config->pppoe_ac_name) - 1); // re-initialise the random number source initrandom(config->random_device); @@ -5451,8 +5588,7 @@ int sessionsetup(sessionidt s, tunnelidt t) if (ip == session[i].ip) { - sessionkill(i, "Duplicate IP address"); - cluster_listinvert_session(s, i); + sessionshutdown(i, "Duplicate IP address", CDN_ADMIN_DISC, TERM_ADMIN_RESET); // close radius/routes, etc. continue; } @@ -5473,7 +5609,7 @@ int sessionsetup(sessionidt s, tunnelidt t) // Drop the new session in case of duplicate sessionss, not the old one. if (!strcasecmp(user, session[i].user)) - sessionkill(i, "Duplicate session for users"); + sessionshutdown(i, "Duplicate session for users", CDN_ADMIN_DISC, TERM_ADMIN_RESET); // close radius/routes, etc. } } @@ -5481,6 +5617,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++) @@ -5503,6 +5640,11 @@ int sessionsetup(sessionidt s, tunnelidt t) } 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 @@ -6009,7 +6151,7 @@ static tunnelidt new_tunnel() tunnelidt i; for (i = 1; i < MAXTUNNEL; i++) { - if (tunnel[i].state == TUNNELFREE) + if ((tunnel[i].state == TUNNELFREE) && (i != TUNNEL_ID_PPPOE)) { LOG(4, 0, i, "Assigning tunnel ID %u\n", i); if (i > config->cluster_highest_tunnelid)