X-Git-Url: http://git.sameswireless.fr/l2tpns.git/blobdiff_plain/5cd5238b2f551cccbe6d7dc4bbec76c4c2ce7af6..4344f5e9c73e2ac36b67e72a400114063f037031:/l2tpns.c diff --git a/l2tpns.c b/l2tpns.c index 3d53622..9f5e901 100644 --- a/l2tpns.c +++ b/l2tpns.c @@ -73,6 +73,7 @@ time_t basetime = 0; // base clock char hostname[1000] = ""; // us. static 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 static FILE *log_stream = 0; // file handle for direct logging (i.e. direct into file, not via syslog). uint32_t last_id = 0; // Unique ID for radius accounting @@ -559,7 +560,7 @@ static ssize_t netlink_send(struct nlmsghdr *nh) return sendmsg(nlfd, &msg, 0); } -static ssize_t netlink_recv(char *buf, ssize_t len) +static ssize_t netlink_recv(void *buf, ssize_t len) { struct sockaddr_nl nladdr; struct iovec iov; @@ -575,6 +576,16 @@ static ssize_t netlink_recv(char *buf, ssize_t len) return recvmsg(nlfd, &msg, 0); } +// messages corresponding to different phases seq number +static char *tun_nl_phase_msg[] = { + "initialized", + "getting tun interface index", + "setting tun interface parameters", + "setting tun IPv4 address", + "setting tun LL IPv6 address", + "setting tun global IPv6 address", +}; + // // Set up TUN interface static void inittun(void) @@ -600,8 +611,8 @@ static void inittun(void) LOG(0, 0, 0, "Can't set tun interface: %s\n", strerror(errno)); exit(1); } - assert(strlen(ifr.ifr_name) < sizeof(config->tundevice)); - strncpy(config->tundevice, ifr.ifr_name, sizeof(config->tundevice) - 1); + assert(strlen(ifr.ifr_name) < sizeof(config->tundevice) - 1); + strncpy(config->tundevice, ifr.ifr_name, sizeof(config->tundevice)); { // get the interface index @@ -636,7 +647,7 @@ static void inittun(void) resp_nh = (struct nlmsghdr *)buf; if (!NLMSG_OK (resp_nh, len)) { - LOG(0, 0, 0, "Malformed answer getting tun ifindex %d\n", len); + LOG(0, 0, 0, "Malformed answer getting tun ifindex %ld\n", len); exit(1); } @@ -712,7 +723,7 @@ static void inittun(void) req.ifmsg.ifaddr.ifa_index = ifinfo.ifi_index; ipv4_attr.rta.rta_len = RTA_LENGTH(sizeof(ipv4_attr.addr)); - ipv4_attr.rta.rta_type = IFA_ADDRESS; + ipv4_attr.rta.rta_type = IFA_LOCAL; ipv4_attr.addr.s_addr = config->bind_address ? config->bind_address : 0x01010101; // 1.1.1.1 memcpy(NLMSG_DATA(&req.nh) + sizeof(req.ifmsg.ifaddr), &ipv4_attr, sizeof(ipv4_attr)); @@ -793,6 +804,13 @@ static void inittun(void) LOG(0, 0, 0, "Error finishing setting up tun device: %s\n", strerror(errno)); exit(1); } + + // if we get an error for seqnum < min_initok_nlseqnum, + // we must exit as initialization went wrong + if (config->ipv6_prefix.s6_addr[0]) + min_initok_nlseqnum = 5 + 1; // idx + if + addr + 2*addr6 + else + min_initok_nlseqnum = 3 + 1; // idx + if + addr } } @@ -3669,8 +3687,8 @@ static int still_busy(void) # include "fake_epoll.h" #endif -// the base set of fds polled: cli, cluster, tun, udp, control, dae -#define BASE_FDS 6 +// the base set of fds polled: cli, cluster, tun, udp, control, dae, netlink +#define BASE_FDS 7 // additional polled fds #ifdef BGP @@ -3694,8 +3712,8 @@ static void mainloop(void) exit(1); } - LOG(4, 0, 0, "Beginning of main loop. clifd=%d, cluster_sockfd=%d, tunfd=%d, udpfd=%d, controlfd=%d, daefd=%d\n", - clifd, cluster_sockfd, tunfd, udpfd, controlfd, daefd); + 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); /* setup our fds to poll for input */ { @@ -3731,6 +3749,10 @@ static void mainloop(void) d[i].type = FD_TYPE_DAE; e.data.ptr = &d[i++]; epoll_ctl(epollfd, EPOLL_CTL_ADD, daefd, &e); + + d[i].type = FD_TYPE_NETLINK; + e.data.ptr = &d[i++]; + epoll_ctl(epollfd, EPOLL_CTL_ADD, nlfd, &e); } #ifdef BGP @@ -3867,6 +3889,32 @@ static void mainloop(void) break; #endif /* BGP */ + case FD_TYPE_NETLINK: + { + struct nlmsghdr *nh = (struct nlmsghdr *)buf; + s = netlink_recv(buf, sizeof(buf)); + if (nh->nlmsg_type == NLMSG_ERROR) + { + struct nlmsgerr *errmsg = NLMSG_DATA(nh); + if (errmsg->error) + { + if (errmsg->msg.nlmsg_seq < min_initok_nlseqnum) + { + LOG(0, 0, 0, "Got a fatal netlink error (while %s): %s\n", tun_nl_phase_msg[nh->nlmsg_seq], strerror(-errmsg->error)); + exit(1); + } + else + + LOG(0, 0, 0, "Got a netlink error: %s\n", strerror(-errmsg->error)); + } + // else it's a ack + } + else + LOG(1, 0, 0, "Got a unknown netlink message: type %d seq %d flags %d\n", nh->nlmsg_type, nh->nlmsg_seq, nh->nlmsg_flags); + n--; + break; + } + default: LOG(0, 0, 0, "Unexpected fd type returned from epoll_wait: %d\n", d->type); }