X-Git-Url: http://git.sameswireless.fr/l2tpns.git/blobdiff_plain/12835e031e502885bce44c5e6b59fa12e0564ca0..30b561eb71683b52894abacf0a607d7d6932e4c1:/l2tpns.c diff --git a/l2tpns.c b/l2tpns.c index 84bb7a7..867730b 100644 --- a/l2tpns.c +++ b/l2tpns.c @@ -10,6 +10,7 @@ #include #include #define SYSLOG_NAMES +#include #include #include #include @@ -19,7 +20,6 @@ #include #include #include -#include #include #include #include @@ -185,6 +185,7 @@ config_descriptt config_values[] = { 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), { NULL, 0, 0, 0 } }; @@ -1009,8 +1010,10 @@ sessionidt sessionbyipv6(struct in6_addr ip) ip.s6_addr[1] == 0x80 && ip.s6_addr16[1] == 0 && ip.s6_addr16[2] == 0 && - ip.s6_addr16[3] == 0)) { - s = lookup_ipmap(*(in_addr_t *) &ip.s6_addr[8]); + ip.s6_addr16[3] == 0)) + { + in_addr_t *pipv4 = (in_addr_t *) &ip.s6_addr[8]; + s = lookup_ipmap(*pipv4); } else { s = lookup_ipv6map(ip); } @@ -1096,7 +1099,7 @@ static void cache_ipv6map(struct in6_addr ip, int prefixlen, sessionidt s) // // CLI list to dump current ipcache. // -int cmd_show_ipcache(struct cli_def *cli, char *command, char **argv, int argc) +int cmd_show_ipcache(struct cli_def *cli, const char *command, char **argv, int argc) { union iphash *d = ip_hash, *e, *f, *g; int i, j, k, l; @@ -1412,7 +1415,7 @@ void processipout(uint8_t *buf, int len) groupidt g; sessiont *sp; tunnelidt t; - in_addr_t ip; + in_addr_t ip, ip_src; uint8_t *data = buf; // Keep a copy of the originals. int size = len; @@ -1445,10 +1448,11 @@ void processipout(uint8_t *buf, int len) return; } + ip_src = *(uint32_t *)(buf + 12); ip = *(uint32_t *)(buf + 16); if ((g = grp_groupbyip(ip))) { - s = grp_getnextsession(g, ip); + s = grp_getnextsession(g, ip, ip_src); if (!s) { // Is this a packet for a session that doesn't exist? @@ -1820,6 +1824,8 @@ static void send_ipout(sessionidt s, uint8_t *buf, int len) { sessiont *sp; tunnelidt t; + uint8_t *p; + uint8_t *data = buf; // Keep a copy of the originals. uint8_t b[MAXETHER + 20]; @@ -1842,11 +1848,14 @@ static void send_ipout(sessionidt s, uint8_t *buf, int len) LOG(5, s, t, "Ethernet -> Tunnel (%d bytes)\n", len); // Add on L2TP header - { - uint8_t *p = makeppp(b, sizeof(b), buf, len, s, t, PPPIP, 0, 0, 0); - if (!p) return; - tunnelsend(b, len + (p-b), t); // send it... - } + if (*(uint16_t *) (data + 2) == htons(PKTIPV6)) + p = makeppp(b, sizeof(b), buf, len, s, t, PPPIPV6, 0, 0, 0); // IPV6 + else + p = makeppp(b, sizeof(b), buf, len, s, t, PPPIP, 0, 0, 0); // IPV4 + + if (!p) return; + + tunnelsend(b, len + (p-b), t); // send it... // Snooping this session. if (sp->snoop_ip && sp->snoop_port) @@ -1865,10 +1874,11 @@ static void send_ipout(sessionidt s, uint8_t *buf, int len) static void control16(controlt * c, uint16_t avp, uint16_t val, uint8_t m) { uint16_t l = (m ? 0x8008 : 0x0008); - *(uint16_t *) (c->buf + c->length + 0) = htons(l); - *(uint16_t *) (c->buf + c->length + 2) = htons(0); - *(uint16_t *) (c->buf + c->length + 4) = htons(avp); - *(uint16_t *) (c->buf + c->length + 6) = htons(val); + uint16_t *pint16 = (uint16_t *) (c->buf + c->length + 0); + pint16[0] = htons(l); + pint16[1] = htons(0); + pint16[2] = htons(avp); + pint16[3] = htons(val); c->length += 8; } @@ -1876,10 +1886,12 @@ static void control16(controlt * c, uint16_t avp, uint16_t val, uint8_t m) static void control32(controlt * c, uint16_t avp, uint32_t val, uint8_t m) { uint16_t l = (m ? 0x800A : 0x000A); - *(uint16_t *) (c->buf + c->length + 0) = htons(l); - *(uint16_t *) (c->buf + c->length + 2) = htons(0); - *(uint16_t *) (c->buf + c->length + 4) = htons(avp); - *(uint32_t *) (c->buf + c->length + 6) = htonl(val); + uint16_t *pint16 = (uint16_t *) (c->buf + c->length + 0); + uint32_t *pint32 = (uint32_t *) (c->buf + c->length + 6); + pint16[0] = htons(l); + pint16[1] = htons(0); + pint16[2] = htons(avp); + pint32[0] = htonl(val); c->length += 10; } @@ -1887,9 +1899,10 @@ static void control32(controlt * c, uint16_t avp, uint32_t val, uint8_t m) static void controls(controlt * c, uint16_t avp, char *val, uint8_t m) { uint16_t l = ((m ? 0x8000 : 0) + strlen(val) + 6); - *(uint16_t *) (c->buf + c->length + 0) = htons(l); - *(uint16_t *) (c->buf + c->length + 2) = htons(0); - *(uint16_t *) (c->buf + c->length + 4) = htons(avp); + uint16_t *pint16 = (uint16_t *) (c->buf + c->length + 0); + pint16[0] = htons(l); + pint16[1] = htons(0); + pint16[2] = htons(avp); memcpy(c->buf + c->length + 6, val, strlen(val)); c->length += 6 + strlen(val); } @@ -1898,9 +1911,10 @@ static void controls(controlt * c, uint16_t avp, char *val, uint8_t m) static void controlb(controlt * c, uint16_t avp, uint8_t *val, unsigned int len, uint8_t m) { uint16_t l = ((m ? 0x8000 : 0) + len + 6); - *(uint16_t *) (c->buf + c->length + 0) = htons(l); - *(uint16_t *) (c->buf + c->length + 2) = htons(0); - *(uint16_t *) (c->buf + c->length + 4) = htons(avp); + uint16_t *pint16 = (uint16_t *) (c->buf + c->length + 0); + pint16[0] = htons(l); + pint16[1] = htons(0); + pint16[2] = htons(avp); memcpy(c->buf + c->length + 6, val, len); c->length += 6 + len; } @@ -1945,10 +1959,11 @@ static void controlnull(tunnelidt t) // add a control message to a tunnel, and send if within window static void controladd(controlt *c, sessionidt far, tunnelidt t) { - *(uint16_t *) (c->buf + 2) = htons(c->length); // length - *(uint16_t *) (c->buf + 4) = htons(tunnel[t].far); // tunnel - *(uint16_t *) (c->buf + 6) = htons(far); // session - *(uint16_t *) (c->buf + 8) = htons(tunnel[t].ns); // sequence + uint16_t *pint16 = (uint16_t *) (c->buf + 2); + pint16[0] = htons(c->length); // length + pint16[1] = htons(tunnel[t].far); // tunnel + pint16[2] = htons(far); // session + pint16[3] = htons(tunnel[t].ns); // sequence tunnel[t].ns++; // advance sequence // link in message in to queue if (tunnel[t].controlc) @@ -2442,7 +2457,8 @@ static void tunnelshutdown(tunnelidt t, char *reason, int result, int error, cha // read and process packet on tunnel (UDP) void processudp(uint8_t *buf, int len, struct sockaddr_in *addr, uint16_t indexudpfd) { - uint8_t *chapresponse = NULL; + uint8_t *sendchalresponse = NULL; + uint8_t *recvchalresponse = NULL; uint16_t l = len, t = 0, s = 0, ns = 0, nr = 0; uint8_t *p = buf + 2; @@ -2846,17 +2862,20 @@ void processudp(uint8_t *buf, int len, struct sockaddr_in *addr, uint16_t indexu tunnel[t].window = 1; // window of 0 is silly LOG(4, s, t, " rx window = %u\n", tunnel[t].window); break; - case 11: // Challenge + case 11: // Request Challenge { LOG(4, s, t, " LAC requested CHAP authentication for tunnel\n"); - build_chap_response(b, 2, n, &chapresponse); + if (message == 1) + build_chap_response(b, 2, n, &sendchalresponse); + else if (message == 2) + build_chap_response(b, 3, n, &sendchalresponse); } break; - case 13: // Response + case 13: // receive challenge Response if (tunnel[t].isremotelns) { - chapresponse = calloc(17, 1); - memcpy(chapresponse, b, (n < 17) ? n : 16); + recvchalresponse = calloc(17, 1); + memcpy(recvchalresponse, b, (n < 17) ? n : 16); LOG(3, s, t, "received challenge response from REMOTE LNS\n"); } else @@ -3092,8 +3111,8 @@ void processudp(uint8_t *buf, int len, struct sockaddr_in *addr, uint16_t indexu controlt *c = controlnew(2); // sending SCCRP control16(c, 2, version, 1); // protocol version control32(c, 3, 3, 1); // framing - controls(c, 7, hostname, 1); // host name - if (chapresponse) controlb(c, 13, chapresponse, 16, 1); // Challenge response + controls(c, 7, config->multi_n_hostname[tunnel[t].indexudp][0]?config->multi_n_hostname[tunnel[t].indexudp]:hostname, 1); // host name + if (sendchalresponse) controlb(c, 13, sendchalresponse, 16, 1); // Send Challenge response control16(c, 9, t, 1); // assigned tunnel controladd(c, 0, t); // send the resply } @@ -3108,20 +3127,21 @@ void processudp(uint8_t *buf, int len, struct sockaddr_in *addr, uint16_t indexu LOG(3, s, t, "Received SCCRP\n"); if (main_quit != QUIT_SHUTDOWN) { - if (tunnel[t].isremotelns && chapresponse) + if (tunnel[t].isremotelns && recvchalresponse) { hasht hash; lac_calc_rlns_auth(t, 2, hash); // id = 2 (SCCRP) // check authenticator - if (memcmp(hash, chapresponse, 16) == 0) + if (memcmp(hash, recvchalresponse, 16) == 0) { LOG(3, s, t, "sending SCCCN to REMOTE LNS\n"); controlt *c = controlnew(3); // sending SCCCN - controls(c, 7, hostname, 1); // host name + controls(c, 7, config->multi_n_hostname[tunnel[t].indexudp][0]?config->multi_n_hostname[tunnel[t].indexudp]:hostname, 1); // host name controls(c, 8, Vendor_name, 1); // Vendor name control16(c, 2, version, 1); // protocol version control32(c, 3, 3, 1); // framing Capabilities + if (sendchalresponse) controlb(c, 13, sendchalresponse, 16, 1); // Challenge response control16(c, 9, t, 1); // assigned tunnel controladd(c, 0, t); // send } @@ -3242,7 +3262,7 @@ void processudp(uint8_t *buf, int len, struct sockaddr_in *addr, uint16_t indexu // Set multilink options before sending initial LCP packet sess_local[s].mp_mrru = 1614; - sess_local[s].mp_epdis = ntohl(config->iftun_n_address[tunnel[t].indexudp] ? config->iftun_n_address[tunnel[t].indexudp] : my_address); + sess_local[s].mp_epdis = ntohl(config->iftun_address ? config->iftun_address : my_address); sendlcp(s, t); change_state(s, lcp, RequestSent); @@ -3264,7 +3284,8 @@ void processudp(uint8_t *buf, int len, struct sockaddr_in *addr, uint16_t indexu LOG(1, s, t, "Unknown message type %u\n", message); break; } - if (chapresponse) free(chapresponse); + if (sendchalresponse) free(sendchalresponse); + if (recvchalresponse) free(recvchalresponse); cluster_send_tunnel(t); } else @@ -5067,9 +5088,9 @@ int main(int argc, char *argv[]) case 'd': if (fork()) exit(0); setsid(); - freopen("/dev/null", "r", stdin); - freopen("/dev/null", "w", stdout); - freopen("/dev/null", "w", stderr); + if(!freopen("/dev/null", "r", stdin)) LOG(0, 0, 0, "Error freopen stdin: %s\n", strerror(errno)); + if(!freopen("/dev/null", "w", stdout)) LOG(0, 0, 0, "Error freopen stdout: %s\n", strerror(errno)); + if(!freopen("/dev/null", "w", stderr)) LOG(0, 0, 0, "Error freopen stderr: %s\n", strerror(errno)); break; case 'v': optdebug++; @@ -5120,7 +5141,7 @@ int main(int argc, char *argv[]) LOG(0, 0, 0, "Can't set ulimit: %s\n", strerror(errno)); // Make core dumps go to /tmp - chdir("/tmp"); + if(chdir("/tmp")) LOG(0, 0, 0, "Error chdir /tmp: %s\n", strerror(errno)); } if (config->scheduler_fifo) @@ -5455,6 +5476,8 @@ static void update_config() config->iftun_n_address[config->nbmultiaddress] = htonl(ip); config->nbmultiaddress++; LOG(1, 0, 0, "Bind address %s\n", fmtaddr(htonl(ip), 0)); + + if (config->nbmultiaddress >= MAX_BINDADDR) break; } sip = n; @@ -5473,6 +5496,42 @@ static void update_config() config->iftun_n_address[0] = config->iftun_address; } + if (*config->multi_hostname) + { + char *shost = config->multi_hostname; + char *n = shost; + char *e = config->multi_hostname + strlen(config->multi_hostname); + config->nbmultihostname = 0; + + while (*shost && (shost < e)) + { + while ((n < e) && (*n == ' ' || *n == ',' || *n == '\t')) n++; + + i = 0; + while (n < e && (*n != ',') && (*n != '\t')) + { + config->multi_n_hostname[config->nbmultihostname][i] = *n; + n++;i++; + } + + if (i > 0) + { + config->multi_n_hostname[config->nbmultihostname][i] = 0; + LOG(1, 0, 0, "Bind Hostname %s\n", config->multi_n_hostname[config->nbmultihostname]); + config->nbmultihostname++; + if (config->nbmultihostname >= MAX_NBHOSTNAME) break; + } + + shost = n; + } + + if (config->nbmultihostname >= 1) + { + strcpy(hostname, config->multi_n_hostname[0]); + strcpy(config->hostname, hostname); + } + } + if (!*config->pppoe_ac_name) strncpy(config->pppoe_ac_name, DEFAULT_PPPOE_AC_NAME, sizeof(config->pppoe_ac_name) - 1); @@ -5798,6 +5857,10 @@ int load_session(sessionidt s, sessiont *new) uncache_ipmap(session[s].ip); } + // remove old IPV6 routes... + if (session[s].ipv6route.s6_addr[0] && session[s].ipv6prefixlen) + route6set(s, session[s].ipv6route, session[s].ipv6prefixlen, 0); + routed = 0; // add new routes... @@ -6272,7 +6335,7 @@ void become_master(void) } } -int cmd_show_hist_idle(struct cli_def *cli, char *command, char **argv, int argc) +int cmd_show_hist_idle(struct cli_def *cli, const char *command, char **argv, int argc) { int s, i; int count = 0; @@ -6310,7 +6373,7 @@ int cmd_show_hist_idle(struct cli_def *cli, char *command, char **argv, int argc return CLI_OK; } -int cmd_show_hist_open(struct cli_def *cli, char *command, char **argv, int argc) +int cmd_show_hist_open(struct cli_def *cli, const char *command, char **argv, int argc) { int s, i; int count = 0; @@ -6554,7 +6617,7 @@ void lac_send_SCCRQ(tunnelidt t, uint8_t * auth, unsigned int auth_len) // Sent SCCRQ - Start Control Connection Request controlt *c = controlnew(1); // sending SCCRQ - controls(c, 7, hostname, 1); // host name + controls(c, 7, config->multi_n_hostname[tunnel[t].indexudp][0]?config->multi_n_hostname[tunnel[t].indexudp]:hostname, 1); // host name controls(c, 8, Vendor_name, 1); // Vendor name control16(c, 2, version, 1); // protocol version control32(c, 3, 3, 1); // framing Capabilities