From c7b02a09277af710d0e77813ca644a50737e9ac5 Mon Sep 17 00:00:00 2001 From: Benjamin Cama Date: Sun, 14 Aug 2011 22:56:35 +0200 Subject: [PATCH 01/16] First netlink functions. Signed-off-by: Benjamin Cama --- l2tpns.c | 84 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) diff --git a/l2tpns.c b/l2tpns.c index 8fdcb53..af19f9a 100644 --- a/l2tpns.c +++ b/l2tpns.c @@ -39,6 +39,7 @@ char const *cvs_id_l2tpns = "$Id: l2tpns.c,v 1.176 2011/01/20 12:48:40 bodea Exp #include #include #include +#include #include "md5.h" #include "l2tpns.h" @@ -56,6 +57,7 @@ char const *cvs_id_l2tpns = "$Id: l2tpns.c,v 1.176 2011/01/20 12:48:40 bodea Exp // 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 int controlfd = -1; // Control signal handle @@ -71,6 +73,7 @@ int epollfd = -1; // event polling time_t basetime = 0; // base clock char hostname[1000] = ""; // us. static int tunidx; // ifr_ifindex of tun device +int nlseqnum = 0; // netlink sequence number 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 @@ -514,6 +517,79 @@ void route6set(sessionidt s, struct in6_addr ip, int prefixlen, int add) return; } +// +// Set up netlink socket +static void initnetlink(void) +{ + struct sockaddr_nl nladdr; + + nlfd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE); + if (nlfd < 0) + return; // don't use netlink + + memset(&nladdr, 0, sizeof(nladdr)); + nladdr.nl_family = AF_NETLINK; + nladdr.nl_pid = getpid(); + + if (bind(fd, (struct sockaddr *)&nladdr, sizeof(nladdr)) < 0) + { + close(fd); + fd = -1; + return; // don't use netlink + } +} + +static ssize_t netlink_send(struct nlmsghdr *nh) +{ + struct sockaddr_nl nladdr; + struct iovec iov; + struct msghdr msg; + ssize_t len; + char buf[4096]; + struct nlmsghdr *ack_nh; + + nh->nlmsg_pid = getpid(); + nh->nlmsg_seq = ++nlseqnum; + nh->nlmsg_flags |= NLM_F_ACK; + + iov = { (void *)nh, nh->msg_len }; + // set kernel address + memset(nladdr, 0, sizeof(nladdr)); + nladdr.nl_family = AF_NETLINK; + msg = { (void *)&nladdr, sizeof(nladdr), &iov, 1, NULL, 0, 0 }; + + if ((len = sendmsg(nlfd, &msg, 0)) < 0) + return len; // return error code + + // expect ack + iov = { buf, sizeof(buf) }; + msg = { (void *)&nladdr, sizeof(nladdr), &iov, 1, NULL, 0, 0 }; + if ((len = recvmsg(nlfd, &msg, 0)) < 0) + return len; // return error code + + for (ack_nh = (struct nlmsghdr *)buf; NLMSG_OK (ack_nh, len); + ack_nh = NLMSG_NEXT (ack_nh, len)) + { + if (ack_nh->nlmsg_type == NLMSG_DONE) + return 1; // didn't get the ack + + if (ack_nh->nlmsg_type == NLMSG_ERROR) + { + struct nlmsgerr *errmsg = NLMSG_DATA(ack_nh); + if (errmsg->error) + return errmsg->error; // got an error back + if (errmsg->msg.nlmsg_seq == nh->nlmsg_seq) + return 0; // ack received + else + return 2; // wrong seq number?! + } + // unknown message + LOG(3, 0, 0, "Got an unknown netlink message: type %d\n", ack_nh->nlmsg_type); + } + + return 3; // no end message?! +} + // defined in linux/ipv6.h, but tricky to include from user-space // TODO: move routing to use netlink rather than ioctl struct in6_ifreq { @@ -549,6 +625,14 @@ static void inittun(void) } assert(strlen(ifr.ifr_name) < sizeof(config->tundevice)); strncpy(config->tundevice, ifr.ifr_name, sizeof(config->tundevice) - 1); + { + struct nlmsghdr nlh; + + { + LOG(0, 0, 0, "Error setting up tun device: %s", strerror(errno)); + exit(1); + } + } ifrfd = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP); sin.sin_family = AF_INET; From 7aa8cc3dc0df081350a7f9b4a30ef8490ee74fe0 Mon Sep 17 00:00:00 2001 From: Benjamin Cama Date: Mon, 15 Aug 2011 22:59:13 +0200 Subject: [PATCH 02/16] Further netlink implementation. Not working yet. Signed-off-by: Benjamin Cama --- l2tpns.c | 321 ++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 220 insertions(+), 101 deletions(-) diff --git a/l2tpns.c b/l2tpns.c index af19f9a..8230945 100644 --- a/l2tpns.c +++ b/l2tpns.c @@ -40,6 +40,7 @@ char const *cvs_id_l2tpns = "$Id: l2tpns.c,v 1.176 2011/01/20 12:48:40 bodea Exp #include #include #include +#include #include "md5.h" #include "l2tpns.h" @@ -65,8 +66,6 @@ int clifd = -1; // Socket listening for CLI connections. int daefd = -1; // Socket listening for DAE connections. int snoopfd = -1; // UDP file handle for sending out intercept data int *radfds = NULL; // RADIUS requests file handles -int ifrfd = -1; // File descriptor for routing, etc -int ifr6fd = -1; // File descriptor for IPv6 routing, etc int rand_fd = -1; // Random data source int cluster_sockfd = -1; // Intra-cluster communications socket. int epollfd = -1; // event polling @@ -525,86 +524,101 @@ static void initnetlink(void) nlfd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE); if (nlfd < 0) - return; // don't use netlink + { + LOG(0, 0, 0, "Can't create netlink socket: %s\n", strerror(errno)); + exit(1); + } memset(&nladdr, 0, sizeof(nladdr)); nladdr.nl_family = AF_NETLINK; nladdr.nl_pid = getpid(); - if (bind(fd, (struct sockaddr *)&nladdr, sizeof(nladdr)) < 0) + if (bind(nlfd, (struct sockaddr *)&nladdr, sizeof(nladdr)) < 0) { - close(fd); - fd = -1; - return; // don't use netlink + LOG(0, 0, 0, "Can't bind netlink socket: %s\n", strerror(errno)); + exit(1); } } -static ssize_t netlink_send(struct nlmsghdr *nh) +static ssize_t netlink_send(struct nlmsghdr *nh, int want_ack) { struct sockaddr_nl nladdr; struct iovec iov; struct msghdr msg; - ssize_t len; - char buf[4096]; - struct nlmsghdr *ack_nh; nh->nlmsg_pid = getpid(); nh->nlmsg_seq = ++nlseqnum; - nh->nlmsg_flags |= NLM_F_ACK; + if (want_ack) + nh->nlmsg_flags |= NLM_F_ACK; - iov = { (void *)nh, nh->msg_len }; // set kernel address - memset(nladdr, 0, sizeof(nladdr)); + memset(&nladdr, 0, sizeof(nladdr)); nladdr.nl_family = AF_NETLINK; - msg = { (void *)&nladdr, sizeof(nladdr), &iov, 1, NULL, 0, 0 }; - if ((len = sendmsg(nlfd, &msg, 0)) < 0) - return len; // return error code + iov = (struct iovec){ (void *)nh, nh->nlmsg_len }; + msg = (struct msghdr){ (void *)&nladdr, sizeof(nladdr), &iov, 1, NULL, 0, 0 }; + + return sendmsg(nlfd, &msg, 0); +} + +static ssize_t netlink_recv(char *buf, ssize_t len) +{ + struct sockaddr_nl nladdr; + struct iovec iov; + struct msghdr msg; + + // set kernel address + memset(&nladdr, 0, sizeof(nladdr)); + nladdr.nl_family = AF_NETLINK; + + iov = (struct iovec){ buf, len }; + msg = (struct msghdr){ (void *)&nladdr, sizeof(nladdr), &iov, 1, NULL, 0, 0 }; + + return recvmsg(nlfd, &msg, 0); +} + +static ssize_t netlink_check_ack(struct nlmsghdr *ack_nh, int msg_count) +{ + ssize_t len; + uint32_t seqnum; // expect ack - iov = { buf, sizeof(buf) }; - msg = { (void *)&nladdr, sizeof(nladdr), &iov, 1, NULL, 0, 0 }; - if ((len = recvmsg(nlfd, &msg, 0)) < 0) - return len; // return error code - - for (ack_nh = (struct nlmsghdr *)buf; NLMSG_OK (ack_nh, len); - ack_nh = NLMSG_NEXT (ack_nh, len)) + for (; NLMSG_OK (ack_nh, len); ack_nh = NLMSG_NEXT (ack_nh, len)) { if (ack_nh->nlmsg_type == NLMSG_DONE) - return 1; // didn't get the ack + return msg_count != 0 || seqnum != nlseqnum; + // 1 => lost an ack if (ack_nh->nlmsg_type == NLMSG_ERROR) { struct nlmsgerr *errmsg = NLMSG_DATA(ack_nh); if (errmsg->error) return errmsg->error; // got an error back - if (errmsg->msg.nlmsg_seq == nh->nlmsg_seq) - return 0; // ack received else - return 2; // wrong seq number?! + { + // ack received + --msg_count; + if (errmsg->msg.nlmsg_seq > seqnum); + seqnum = errmsg->msg.nlmsg_seq; + } } - // unknown message - LOG(3, 0, 0, "Got an unknown netlink message: type %d\n", ack_nh->nlmsg_type); + else + // unknown message + LOG(3, 0, 0, "Got an unknown netlink message: type %d\n", ack_nh->nlmsg_type); } - return 3; // no end message?! + return 1; // malformed message?! } -// defined in linux/ipv6.h, but tricky to include from user-space -// TODO: move routing to use netlink rather than ioctl -struct in6_ifreq { - struct in6_addr ifr6_addr; - __u32 ifr6_prefixlen; - unsigned int ifr6_ifindex; -}; - // // Set up TUN interface static void inittun(void) { + struct ifinfomsg ifinfo; struct ifreq ifr; - struct in6_ifreq ifr6; - struct sockaddr_in sin = {0}; + char buf[4096]; + struct nlmsghdr resp_nh; + memset(&ifr, 0, sizeof(ifr)); ifr.ifr_flags = IFF_TUN; @@ -625,79 +639,184 @@ static void inittun(void) } assert(strlen(ifr.ifr_name) < sizeof(config->tundevice)); strncpy(config->tundevice, ifr.ifr_name, sizeof(config->tundevice) - 1); - { - struct nlmsghdr nlh; + { + // get the interface index + ssize_t len; + struct { + struct nlmsghdr nh; + struct ifinfomsg ifinfo __attribute__ ((aligned(NLMSG_ALIGNTO))); + struct rtattr ifname_rta __attribute__ ((aligned(RTA_ALIGNTO))); + char ifname[IFNAMSIZ]; + } req; + + req.nh.nlmsg_type = RTM_GETLINK; + req.nh.nlmsg_flags = NLM_F_REQUEST; + + req.ifinfo.ifi_family = AF_UNSPEC; // as the man says + + req.ifname_rta.rta_len = RTA_LENGTH(strlen(config->tundevice)+1); + req.ifname_rta.rta_type = IFLA_IFNAME; + strncpy(req.ifname, config->tundevice, IFNAMSIZ-1); + + if(netlink_send(&req.nh, 0) < 0 || (len = netlink_recv(buf, sizeof(buf))) < 0) { - LOG(0, 0, 0, "Error setting up tun device: %s", strerror(errno)); + LOG(0, 0, 0, "Error getting tun ifindex: %s\n", strerror(errno)); + exit(1); + } + + resp_nh = (struct nlmsghdr *)buf; + if (NLMSG_OK (resp_nh, len) && resp_nh.nlmsg_type == RTM_GETLINK) + { + memcpy(&ifinfo, NLMSG_DATA(resp_nh), sizeof(ifinfo)); + // got index + tunidx = ifinfo.ifi_index; + } + else + { + LOG(0, 0, 0, "Malformed answer getting tun ifindex\n"); exit(1); } } - ifrfd = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP); + { + ssize_t err; + struct { + // interface setting + struct nlmsghdr nh; + struct ifinfomsg ifinfo __attribute__ ((aligned(NLMSG_ALIGNTO))); + struct rtattr txqlen_rta __attribute__ ((aligned(RTA_ALIGNTO))); + uint32_t txqlen; + struct rtattr mtu_rta __attribute__ ((aligned(RTA_ALIGNTO))); + uint32_t mtu; - sin.sin_family = AF_INET; - sin.sin_addr.s_addr = config->bind_address ? config->bind_address : 0x01010101; // 1.1.1.1 - memcpy(&ifr.ifr_addr, &sin, sizeof(struct sockaddr)); + // IPv4 address + struct nlmsghdr addr_nh __attribute __ ((aligned(NLMSG_ALIGNTO))); + struct ifaddrmsg ifaddr __attribute __ ((aligned(NLMSG_ALIGNTO))); + struct rtattr addr_rta __attribute __ ((aligned(RTA_ALIGNTO))); + struct in_addr addr; - if (ioctl(ifrfd, SIOCSIFADDR, (void *) &ifr) < 0) - { - LOG(0, 0, 0, "Error setting tun address: %s\n", strerror(errno)); - exit(1); - } - /* Bump up the qlen to deal with bursts from the network */ - ifr.ifr_qlen = 1000; - if (ioctl(ifrfd, SIOCSIFTXQLEN, (void *) &ifr) < 0) - { - LOG(0, 0, 0, "Error setting tun queue length: %s\n", strerror(errno)); - exit(1); - } - /* set MTU to modem MRU */ - ifr.ifr_mtu = MRU; - if (ioctl(ifrfd, SIOCSIFMTU, (void *) &ifr) < 0) - { - LOG(0, 0, 0, "Error setting tun MTU: %s\n", strerror(errno)); - exit(1); - } - ifr.ifr_flags = IFF_UP; - if (ioctl(ifrfd, SIOCSIFFLAGS, (void *) &ifr) < 0) - { - LOG(0, 0, 0, "Error setting tun flags: %s\n", strerror(errno)); - exit(1); - } - if (ioctl(ifrfd, SIOCGIFINDEX, (void *) &ifr) < 0) - { - LOG(0, 0, 0, "Error getting tun ifindex: %s\n", strerror(errno)); - exit(1); - } - tunidx = ifr.ifr_ifindex; + // IPv6 LL address + struct nlmsghdr lladdr6_nh __attribute __ ((aligned(NLMSG_ALIGNTO))); + struct ifaddrmsg llifaddr6 __attribute __ ((aligned(NLMSG_ALIGNTO))); + struct rtattr lladdr6_rta __attribute __ ((aligned(RTA_ALIGNTO))); + struct in6_addr lladdr6; - // Only setup IPv6 on the tun device if we have a configured prefix - if (config->ipv6_prefix.s6_addr[0]) { - ifr6fd = socket(PF_INET6, SOCK_DGRAM, 0); + // IPv6 global address + struct nlmsghdr addr6_nh __attribute __ ((aligned(NLMSG_ALIGNTO))); + struct ifaddrmsg ifaddr6 __attribute __ ((aligned(NLMSG_ALIGNTO))); + struct rtattr addr6_rta __attribute __ ((aligned(RTA_ALIGNTO))); + struct in6_addr addr6; - // Link local address is FE80::1 - memset(&ifr6.ifr6_addr, 0, sizeof(ifr6.ifr6_addr)); - ifr6.ifr6_addr.s6_addr[0] = 0xFE; - ifr6.ifr6_addr.s6_addr[1] = 0x80; - ifr6.ifr6_addr.s6_addr[15] = 1; - ifr6.ifr6_prefixlen = 64; - ifr6.ifr6_ifindex = ifr.ifr_ifindex; - if (ioctl(ifr6fd, SIOCSIFADDR, (void *) &ifr6) < 0) + // end header + struct nlmsghdr end_nh __attribute __ ((aligned(NLMSG_ALIGNTO))); + } req; + char buf[4096]; + + memset(&req, 0, sizeof(req)); + + req.nh.nlmsg_type = RTM_NEWLINK; + req.nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_MULTI; + + req.ifinfo = ifinfo; + req.ifinfo.ifi_flags |= IFF_UP; // set interface up + req.ifinfo.ifi_change = IFF_UP; // only change this flag + + req.txqlen_rta.rta_len = RTA_LENGTH(sizeof(req.txqlen)); + req.txqlen_rta.rta_type = IFLA_TXQLEN; + /* Bump up the qlen to deal with bursts from the network */ + req.txqlen = 1000; + + req.mtu_rta.rta_len = RTA_LENGTH(sizeof(req.txqlen)); + req.mtu_rta.rta_type = IFLA_MTU; + /* set MTU to modem MRU */ + req.mtu = MRU; + + req.nh.nlmsg_len = NLMSG_LENGTH(sizeof(req.ifinfo) + + req.txqlen_rla.rta_len + + req.mtu_rta.rta_len); + + req.addr_nh.nlmsg_type = RTM_NEWADDR; + req.addr_nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_MULTI; + + req.ifaddr.ifa_family = AF_INET; + req.ifaddr.ifa_prefixlen = 32; + req.ifaddr.ifa_index = ifinfo.ifi_index; + + req.addr_rta.rta_len = RTA_LENGTH(sizeof(req.addr)); + req.addr_rta.rta_type = IFA_ADDRESS; + req.addr.s_addr = config->bind_address ? + config->bind_address : 0x01010101; // 1.1.1.1 + + req.addr_nh.nlmsg_len = NLMSG_LENGTH(sizeof(req.ifaddr) + + req.addr_rta.rta_len); + + // Only setup IPv6 on the tun device if we have a configured prefix + if (config->ipv6_prefix.s6_addr[0]) { + req.lladdr6_nh.nlmsg_type = RTM_NEWADDR; + req.lladdr6_nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_MULTI; + + req.llifaddr6.ifa_family = AF_INET6; + req.llifaddr6.ifa_prefixlen = 64; + req.llifaddr6.ifa_scope = RT_SCOPE_LINK; + req.llifaddr6.ifa_index = ifinfo.ifi_index; + + req.lladdr6_rta.rta_len = RTA_LENGTH(sizeof(req.lladdr6)); + req.lladdr6_rta.rta_type = IFA_LOCAL; + // Link local address is FE80::1 + memset(&req.lladdr6, 0, sizeof(req.lladdr6)); + req.lladdr6.s6_addr[0] = 0xFE; + req.lladdr6.s6_addr[1] = 0x80; + req.lladdr6.s6_addr[15] = 1; + + req.lladdr6_nh.nlmsg_len = NLMSG_LENGTH(sizeof(req.ifaddr) + + req.lladdr6_rta.rta_len); + + req.addr6_nh.nlmsg_type = RTM_NEWADDR; + req.addr6_nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_MULTI; + + req.ifaddr6.ifa_family = AF_INET6; + req.ifaddr6.ifa_prefixlen = 64; + req.ifaddr6.ifa_scope = RT_SCOPE_UNIVERSE; + req.ifaddr6.ifa_index = ifinfo.ifi_index; + + req.addr6_rta.rta_len = RTA_LENGTH(sizeof(req.addr6)); + req.addr6_rta.rta_type = IFA_LOCAL; + // Global address is prefix::1 + req.addr6 = config->ipv6_prefix; + req.addr6.s6_addr[15] = 1; + + req.lladdr6_nh.nlmsg_len = NLMSG_LENGTH(sizeof(req.ifaddr) + + req.lladdr6_rta.rta_len); + + req.end_nh.nlmsg_type = NLMSG_DONE; + req.end_nh.nlmsg_len = NLMSG_LENGTH(0); + } + else { - LOG(0, 0, 0, "Error setting tun IPv6 link local address:" - " %s\n", strerror(errno)); + // we terminate at the beginning of IPv6 stuff + req.lladdr6_nh.nlmsg_type = NLMSG_DONE; + req.lladdr6_nh.nlmsg_len = NLMSG_LENGTH(0); } - // Global address is prefix::1 - memset(&ifr6.ifr6_addr, 0, sizeof(ifr6.ifr6_addr)); - ifr6.ifr6_addr = config->ipv6_prefix; - ifr6.ifr6_addr.s6_addr[15] = 1; - ifr6.ifr6_prefixlen = 64; - ifr6.ifr6_ifindex = ifr.ifr_ifindex; - if (ioctl(ifr6fd, SIOCSIFADDR, (void *) &ifr6) < 0) + if (netlink_send(&req.nh, 1) < 0) + LOG(0, 0, 0, "Error setting up tun device: %s\n", strerror(errno)); + exit(1); + } + + if (netlink_recv(buf, sizeof(buf)) < 0) { - LOG(0, 0, 0, "Error setting tun IPv6 global address: %s\n", - strerror(errno)); + LOG(0, 0, 0, "Error waiting ack for setting up tun device: %s\n", strerror(errno)); + exit(1); + } + + resp_nh = (struct nlmsghdr *)buf; + if ((err = netlink_check_ack(resp_nh, 4))) + { + if (err < 0) + LOG(0, 0, 0, "Error while receiving tun device ack: %s\n", strerror(errno)); + else + LOG(0, 0, 0, "Error while receiving tun device ack\n", strerror(errno)); + exit(1); } } } From c23922ce7c5a688ba6f77e90992c15242a139ea7 Mon Sep 17 00:00:00 2001 From: Benjamin Cama Date: Tue, 16 Aug 2011 00:12:23 +0200 Subject: [PATCH 03/16] Netlink bugfixes. Signed-off-by: Benjamin Cama --- l2tpns.c | 34 ++++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/l2tpns.c b/l2tpns.c index 8230945..7548771 100644 --- a/l2tpns.c +++ b/l2tpns.c @@ -617,7 +617,6 @@ static void inittun(void) struct ifinfomsg ifinfo; struct ifreq ifr; char buf[4096]; - struct nlmsghdr resp_nh; memset(&ifr, 0, sizeof(ifr)); ifr.ifr_flags = IFF_TUN; @@ -649,6 +648,7 @@ static void inittun(void) struct rtattr ifname_rta __attribute__ ((aligned(RTA_ALIGNTO))); char ifname[IFNAMSIZ]; } req; + struct nlmsghdr *resp_nh; req.nh.nlmsg_type = RTM_GETLINK; req.nh.nlmsg_flags = NLM_F_REQUEST; @@ -666,7 +666,7 @@ static void inittun(void) } resp_nh = (struct nlmsghdr *)buf; - if (NLMSG_OK (resp_nh, len) && resp_nh.nlmsg_type == RTM_GETLINK) + if (NLMSG_OK (resp_nh, len) && resp_nh->nlmsg_type == RTM_GETLINK) { memcpy(&ifinfo, NLMSG_DATA(resp_nh), sizeof(ifinfo)); // got index @@ -690,25 +690,25 @@ static void inittun(void) uint32_t mtu; // IPv4 address - struct nlmsghdr addr_nh __attribute __ ((aligned(NLMSG_ALIGNTO))); - struct ifaddrmsg ifaddr __attribute __ ((aligned(NLMSG_ALIGNTO))); - struct rtattr addr_rta __attribute __ ((aligned(RTA_ALIGNTO))); + struct nlmsghdr addr_nh __attribute__ ((aligned(NLMSG_ALIGNTO))); + struct ifaddrmsg ifaddr __attribute__ ((aligned(NLMSG_ALIGNTO))); + struct rtattr addr_rta __attribute__ ((aligned(RTA_ALIGNTO))); struct in_addr addr; // IPv6 LL address - struct nlmsghdr lladdr6_nh __attribute __ ((aligned(NLMSG_ALIGNTO))); - struct ifaddrmsg llifaddr6 __attribute __ ((aligned(NLMSG_ALIGNTO))); - struct rtattr lladdr6_rta __attribute __ ((aligned(RTA_ALIGNTO))); + struct nlmsghdr lladdr6_nh __attribute__ ((aligned(NLMSG_ALIGNTO))); + struct ifaddrmsg llifaddr6 __attribute__ ((aligned(NLMSG_ALIGNTO))); + struct rtattr lladdr6_rta __attribute__ ((aligned(RTA_ALIGNTO))); struct in6_addr lladdr6; // IPv6 global address - struct nlmsghdr addr6_nh __attribute __ ((aligned(NLMSG_ALIGNTO))); - struct ifaddrmsg ifaddr6 __attribute __ ((aligned(NLMSG_ALIGNTO))); - struct rtattr addr6_rta __attribute __ ((aligned(RTA_ALIGNTO))); + struct nlmsghdr addr6_nh __attribute__ ((aligned(NLMSG_ALIGNTO))); + struct ifaddrmsg ifaddr6 __attribute__ ((aligned(NLMSG_ALIGNTO))); + struct rtattr addr6_rta __attribute__ ((aligned(RTA_ALIGNTO))); struct in6_addr addr6; // end header - struct nlmsghdr end_nh __attribute __ ((aligned(NLMSG_ALIGNTO))); + struct nlmsghdr end_nh __attribute__ ((aligned(NLMSG_ALIGNTO))); } req; char buf[4096]; @@ -732,7 +732,7 @@ static void inittun(void) req.mtu = MRU; req.nh.nlmsg_len = NLMSG_LENGTH(sizeof(req.ifinfo) - + req.txqlen_rla.rta_len + + req.txqlen_rta.rta_len + req.mtu_rta.rta_len); req.addr_nh.nlmsg_type = RTM_NEWADDR; @@ -799,6 +799,7 @@ static void inittun(void) } if (netlink_send(&req.nh, 1) < 0) + { LOG(0, 0, 0, "Error setting up tun device: %s\n", strerror(errno)); exit(1); } @@ -809,13 +810,12 @@ static void inittun(void) exit(1); } - resp_nh = (struct nlmsghdr *)buf; - if ((err = netlink_check_ack(resp_nh, 4))) + if ((err = netlink_check_ack((struct nlmsghdr *)buf, 4))) { if (err < 0) LOG(0, 0, 0, "Error while receiving tun device ack: %s\n", strerror(errno)); else - LOG(0, 0, 0, "Error while receiving tun device ack\n", strerror(errno)); + LOG(0, 0, 0, "Error while receiving tun device ack\n"); exit(1); } } @@ -4733,6 +4733,8 @@ int main(int argc, char *argv[]) } } + initnetlink(); + /* Set up the cluster communications port. */ if (cluster_init() < 0) exit(1); From ba87a9d8744d179dd7bc3a57cf8b1e506bcfae54 Mon Sep 17 00:00:00 2001 From: Benjamin Cama Date: Tue, 16 Aug 2011 16:06:33 +0200 Subject: [PATCH 04/16] Commiting the rework I have done until now. But I will remove the ack stuff, too complicated. Signed-off-by: Benjamin Cama --- l2tpns.c | 282 ++++++++++++++++++++++++++++++++----------------------- 1 file changed, 162 insertions(+), 120 deletions(-) diff --git a/l2tpns.c b/l2tpns.c index 7548771..d849711 100644 --- a/l2tpns.c +++ b/l2tpns.c @@ -577,10 +577,9 @@ static ssize_t netlink_recv(char *buf, ssize_t len) return recvmsg(nlfd, &msg, 0); } -static ssize_t netlink_check_ack(struct nlmsghdr *ack_nh, int msg_count) +static ssize_t netlink_check_ack(struct nlmsghdr *ack_nh, ssize_t len, int msg_count) { - ssize_t len; - uint32_t seqnum; + uint32_t seqnum = 0; // expect ack for (; NLMSG_OK (ack_nh, len); ack_nh = NLMSG_NEXT (ack_nh, len)) @@ -600,6 +599,9 @@ static ssize_t netlink_check_ack(struct nlmsghdr *ack_nh, int msg_count) --msg_count; if (errmsg->msg.nlmsg_seq > seqnum); seqnum = errmsg->msg.nlmsg_seq; + // if this is a single message, return now + if (!(ack_nh->nlmsg_flags & NLM_F_MULTI)) + return msg_count != 0 || seqnum != nlseqnum; } } else @@ -617,6 +619,8 @@ static void inittun(void) struct ifinfomsg ifinfo; struct ifreq ifr; char buf[4096]; + ssize_t len; + struct nlmsghdr *resp_nh; memset(&ifr, 0, sizeof(ifr)); ifr.ifr_flags = IFF_TUN; @@ -641,14 +645,12 @@ static void inittun(void) { // get the interface index - ssize_t len; struct { struct nlmsghdr nh; struct ifinfomsg ifinfo __attribute__ ((aligned(NLMSG_ALIGNTO))); struct rtattr ifname_rta __attribute__ ((aligned(RTA_ALIGNTO))); char ifname[IFNAMSIZ]; } req; - struct nlmsghdr *resp_nh; req.nh.nlmsg_type = RTM_GETLINK; req.nh.nlmsg_flags = NLM_F_REQUEST; @@ -659,6 +661,9 @@ static void inittun(void) req.ifname_rta.rta_type = IFLA_IFNAME; strncpy(req.ifname, config->tundevice, IFNAMSIZ-1); + req.nh.nlmsg_len = NLMSG_LENGTH(sizeof(req.ifinfo) + + req.ifname_rta.rta_len); + if(netlink_send(&req.nh, 0) < 0 || (len = netlink_recv(buf, sizeof(buf))) < 0) { LOG(0, 0, 0, "Error getting tun ifindex: %s\n", strerror(errno)); @@ -666,151 +671,188 @@ static void inittun(void) } resp_nh = (struct nlmsghdr *)buf; - if (NLMSG_OK (resp_nh, len) && resp_nh->nlmsg_type == RTM_GETLINK) - { - memcpy(&ifinfo, NLMSG_DATA(resp_nh), sizeof(ifinfo)); - // got index - tunidx = ifinfo.ifi_index; - } - else + if (!NLMSG_OK (resp_nh, len)) { LOG(0, 0, 0, "Malformed answer getting tun ifindex\n"); exit(1); } + + memcpy(&ifinfo, NLMSG_DATA(resp_nh), sizeof(ifinfo)); + // got index + tunidx = ifinfo.ifi_index; } { ssize_t err; struct { // interface setting struct nlmsghdr nh; - struct ifinfomsg ifinfo __attribute__ ((aligned(NLMSG_ALIGNTO))); - struct rtattr txqlen_rta __attribute__ ((aligned(RTA_ALIGNTO))); - uint32_t txqlen; - struct rtattr mtu_rta __attribute__ ((aligned(RTA_ALIGNTO))); - uint32_t mtu; - - // IPv4 address - struct nlmsghdr addr_nh __attribute__ ((aligned(NLMSG_ALIGNTO))); - struct ifaddrmsg ifaddr __attribute__ ((aligned(NLMSG_ALIGNTO))); - struct rtattr addr_rta __attribute__ ((aligned(RTA_ALIGNTO))); - struct in_addr addr; - - // IPv6 LL address - struct nlmsghdr lladdr6_nh __attribute__ ((aligned(NLMSG_ALIGNTO))); - struct ifaddrmsg llifaddr6 __attribute__ ((aligned(NLMSG_ALIGNTO))); - struct rtattr lladdr6_rta __attribute__ ((aligned(RTA_ALIGNTO))); - struct in6_addr lladdr6; - - // IPv6 global address - struct nlmsghdr addr6_nh __attribute__ ((aligned(NLMSG_ALIGNTO))); - struct ifaddrmsg ifaddr6 __attribute__ ((aligned(NLMSG_ALIGNTO))); - struct rtattr addr6_rta __attribute__ ((aligned(RTA_ALIGNTO))); - struct in6_addr addr6; - - // end header - struct nlmsghdr end_nh __attribute__ ((aligned(NLMSG_ALIGNTO))); + union { + struct ifinfomsg ifinfo; + struct ifaddrmsg ifaddr; + } ifmsg __attribute__ ((aligned(NLMSG_ALIGNTO))); + char rtdata[32]; // 32 should be enough } req; - char buf[4096]; + struct { + struct rtattr rta; + uint32_t u32 __attribute__ ((aligned(RTA_ALIGNTO)));; + } u32_attr; + struct { + struct rtattr rta; + struct in_addr addr __attribute__ ((aligned(RTA_ALIGNTO)));; + } ipv4_attr; + struct { + struct rtattr rta; + struct in6_addr addr6 __attribute__ ((aligned(RTA_ALIGNTO)));; + } ipv6_attr; + char buf[256]; + ssize_t buf_len; + char *buf_ptr; memset(&req, 0, sizeof(req)); - req.nh.nlmsg_type = RTM_NEWLINK; - req.nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_MULTI; + req.nh.nlmsg_type = RTM_SETLINK; + req.nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_MULTI; - req.ifinfo = ifinfo; - req.ifinfo.ifi_flags |= IFF_UP; // set interface up - req.ifinfo.ifi_change = IFF_UP; // only change this flag + req.ifmsg.ifinfo = ifinfo; + req.ifmsg.ifinfo.ifi_flags |= IFF_UP; // set interface up + req.ifmsg.ifinfo.ifi_change = IFF_UP; // only change this flag - req.txqlen_rta.rta_len = RTA_LENGTH(sizeof(req.txqlen)); - req.txqlen_rta.rta_type = IFLA_TXQLEN; + buf_ptr = NLMSG_DATA(&req.nh) + sizeof(req.ifmsg.ifinfo); + + u32_attr.rta.rta_len = RTA_LENGTH(sizeof(u32_attr.u32)); + u32_attr.rta.rta_type = IFLA_TXQLEN; /* Bump up the qlen to deal with bursts from the network */ - req.txqlen = 1000; + u32_attr.u32 = 1000; + memcpy(buf_ptr, &u32_attr, sizeof(u32_attr)); - req.mtu_rta.rta_len = RTA_LENGTH(sizeof(req.txqlen)); - req.mtu_rta.rta_type = IFLA_MTU; + buf_ptr += RTA_ALIGN(u32_attr.rta.rta_len); + + u32_attr.rta.rta_len = RTA_LENGTH(sizeof(u32_attr.u32)); + u32_attr.rta.rta_type = IFLA_MTU; /* set MTU to modem MRU */ - req.mtu = MRU; + u32_attr.u32 = MRU; + memcpy(buf_ptr, &u32_attr, sizeof(u32_attr)); - req.nh.nlmsg_len = NLMSG_LENGTH(sizeof(req.ifinfo) - + req.txqlen_rta.rta_len - + req.mtu_rta.rta_len); - - req.addr_nh.nlmsg_type = RTM_NEWADDR; - req.addr_nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_MULTI; - - req.ifaddr.ifa_family = AF_INET; - req.ifaddr.ifa_prefixlen = 32; - req.ifaddr.ifa_index = ifinfo.ifi_index; - - req.addr_rta.rta_len = RTA_LENGTH(sizeof(req.addr)); - req.addr_rta.rta_type = IFA_ADDRESS; - req.addr.s_addr = config->bind_address ? - config->bind_address : 0x01010101; // 1.1.1.1 - - req.addr_nh.nlmsg_len = NLMSG_LENGTH(sizeof(req.ifaddr) - + req.addr_rta.rta_len); - - // Only setup IPv6 on the tun device if we have a configured prefix - if (config->ipv6_prefix.s6_addr[0]) { - req.lladdr6_nh.nlmsg_type = RTM_NEWADDR; - req.lladdr6_nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_MULTI; - - req.llifaddr6.ifa_family = AF_INET6; - req.llifaddr6.ifa_prefixlen = 64; - req.llifaddr6.ifa_scope = RT_SCOPE_LINK; - req.llifaddr6.ifa_index = ifinfo.ifi_index; - - req.lladdr6_rta.rta_len = RTA_LENGTH(sizeof(req.lladdr6)); - req.lladdr6_rta.rta_type = IFA_LOCAL; - // Link local address is FE80::1 - memset(&req.lladdr6, 0, sizeof(req.lladdr6)); - req.lladdr6.s6_addr[0] = 0xFE; - req.lladdr6.s6_addr[1] = 0x80; - req.lladdr6.s6_addr[15] = 1; - - req.lladdr6_nh.nlmsg_len = NLMSG_LENGTH(sizeof(req.ifaddr) - + req.lladdr6_rta.rta_len); - - req.addr6_nh.nlmsg_type = RTM_NEWADDR; - req.addr6_nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_MULTI; - - req.ifaddr6.ifa_family = AF_INET6; - req.ifaddr6.ifa_prefixlen = 64; - req.ifaddr6.ifa_scope = RT_SCOPE_UNIVERSE; - req.ifaddr6.ifa_index = ifinfo.ifi_index; - - req.addr6_rta.rta_len = RTA_LENGTH(sizeof(req.addr6)); - req.addr6_rta.rta_type = IFA_LOCAL; - // Global address is prefix::1 - req.addr6 = config->ipv6_prefix; - req.addr6.s6_addr[15] = 1; - - req.lladdr6_nh.nlmsg_len = NLMSG_LENGTH(sizeof(req.ifaddr) - + req.lladdr6_rta.rta_len); - - req.end_nh.nlmsg_type = NLMSG_DONE; - req.end_nh.nlmsg_len = NLMSG_LENGTH(0); - } - else - { - // we terminate at the beginning of IPv6 stuff - req.lladdr6_nh.nlmsg_type = NLMSG_DONE; - req.lladdr6_nh.nlmsg_len = NLMSG_LENGTH(0); - } + req.nh.nlmsg_len = NLMSG_LENGTH(sizeof(req.ifmsg.ifinfo) + + u32_attr.rta.rta_len * 2); if (netlink_send(&req.nh, 1) < 0) { - LOG(0, 0, 0, "Error setting up tun device: %s\n", strerror(errno)); + LOG(0, 0, 0, "Error setting up tun device interface: %s\n", strerror(errno)); exit(1); } - if (netlink_recv(buf, sizeof(buf)) < 0) + memset(&req, 0, sizeof(req)); + + req.nh.nlmsg_type = RTM_NEWADDR; + req.nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_MULTI; + + req.ifmsg.ifaddr.ifa_family = AF_INET; + req.ifmsg.ifaddr.ifa_prefixlen = 32; + 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.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)); + + req.nh.nlmsg_len = NLMSG_LENGTH(sizeof(req.ifmsg.ifaddr) + + ipv4_attr.rta.rta_len); + + if (netlink_send(&req.nh, 1) < 0) { - LOG(0, 0, 0, "Error waiting ack for setting up tun device: %s\n", strerror(errno)); + LOG(0, 0, 0, "Error setting up tun device IPv4 address: %s\n", strerror(errno)); exit(1); } - if ((err = netlink_check_ack((struct nlmsghdr *)buf, 4))) + memset(&req, 0, sizeof(req)); + + // Only setup IPv6 on the tun device if we have a configured prefix + if (config->ipv6_prefix.s6_addr[0]) { + req.nh.nlmsg_type = RTM_NEWADDR; + req.nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_MULTI; + + req.ifmsg.ifaddr.ifa_family = AF_INET6; + req.ifmsg.ifaddr.ifa_prefixlen = 64; + req.ifmsg.ifaddr.ifa_scope = RT_SCOPE_LINK; + req.ifmsg.ifaddr.ifa_index = ifinfo.ifi_index; + + ipv6_attr.rta.rta_len = RTA_LENGTH(sizeof(ipv6_attr.addr6)); + ipv6_attr.rta.rta_type = IFA_LOCAL; + // Link local address is FE80::1 + memset(&ipv6_attr.addr6, 0, sizeof(ipv6_attr.addr6)); + ipv6_attr.addr6.s6_addr[0] = 0xFE; + ipv6_attr.addr6.s6_addr[1] = 0x80; + ipv6_attr.addr6.s6_addr[15] = 1; + memcpy(NLMSG_DATA(&req.nh) + sizeof(req.ifmsg.ifaddr), &ipv6_attr, sizeof(ipv6_attr)); + + req.nh.nlmsg_len = NLMSG_LENGTH(sizeof(req.ifmsg.ifaddr) + + ipv6_attr.rta.rta_len); + + if (netlink_send(&req.nh, 1) < 0) + { + LOG(0, 0, 0, "Error setting up tun device IPv6 LL address: %s\n", strerror(errno)); + exit(1); + } + + memset(&req, 0, sizeof(req)); + + req.nh.nlmsg_type = RTM_NEWADDR; + req.nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_MULTI; + + req.ifmsg.ifaddr.ifa_family = AF_INET6; + req.ifmsg.ifaddr.ifa_prefixlen = 64; + req.ifmsg.ifaddr.ifa_scope = RT_SCOPE_UNIVERSE; + req.ifmsg.ifaddr.ifa_index = ifinfo.ifi_index; + + ipv6_attr.rta.rta_len = RTA_LENGTH(sizeof(ipv6_attr.addr6)); + ipv6_attr.rta.rta_type = IFA_LOCAL; + // Global address is prefix::1 + ipv6_attr.addr6 = config->ipv6_prefix; + ipv6_attr.addr6.s6_addr[15] = 1; + memcpy(NLMSG_DATA(&req.nh) + sizeof(req.ifmsg.ifaddr), &ipv6_attr, sizeof(ipv6_attr)); + + req.nh.nlmsg_len = NLMSG_LENGTH(sizeof(req.ifmsg.ifaddr) + + ipv6_attr.rta.rta_len); + + if (netlink_send(&req.nh, 1) < 0) + { + LOG(0, 0, 0, "Error setting up tun device IPv6 global address: %s\n", strerror(errno)); + exit(1); + } + + memset(&req, 0, sizeof(req)); + } + + req.nh.nlmsg_type = NLMSG_DONE; + req.nh.nlmsg_len = NLMSG_LENGTH(0); + + if (netlink_send(&req.nh, 1) < 0) + { + LOG(0, 0, 0, "Error finishing setting up tun device: %s\n", strerror(errno)); + exit(1); + } + + buf_ptr = buf; + buf_len = sizeof(buf); + do + { + len = netlink_recv(buf_ptr, sizeof(buf_len)); + if (len < 0) + { + LOG(0, 0, 0, "Error waiting for ack setting up tun device: %s\n", strerror(errno)); + exit(1); + } + + resp_nh = (struct nlmsghdr *)buf_ptr; + buf_len -= len; + buf_ptr += len; + } + while (buf_len > 0 && (resp_nh->nlmsg_flags & NLM_F_MULTI) + && resp_nh->nlmsg_type != NLMSG_DONE); + + if ((err = netlink_check_ack((struct nlmsghdr *)buf, buf_len, 4))) { if (err < 0) LOG(0, 0, 0, "Error while receiving tun device ack: %s\n", strerror(errno)); From 5cd5238b2f551cccbe6d7dc4bbec76c4c2ce7af6 Mon Sep 17 00:00:00 2001 From: Benjamin Cama Date: Tue, 16 Aug 2011 16:42:13 +0200 Subject: [PATCH 05/16] Remove all acknoledgement stuff. Still doesn't work. Signed-off-by: Benjamin Cama --- l2tpns.c | 97 +++++++++----------------------------------------------- 1 file changed, 15 insertions(+), 82 deletions(-) diff --git a/l2tpns.c b/l2tpns.c index d849711..3d53622 100644 --- a/l2tpns.c +++ b/l2tpns.c @@ -540,7 +540,7 @@ static void initnetlink(void) } } -static ssize_t netlink_send(struct nlmsghdr *nh, int want_ack) +static ssize_t netlink_send(struct nlmsghdr *nh) { struct sockaddr_nl nladdr; struct iovec iov; @@ -548,8 +548,6 @@ static ssize_t netlink_send(struct nlmsghdr *nh, int want_ack) nh->nlmsg_pid = getpid(); nh->nlmsg_seq = ++nlseqnum; - if (want_ack) - nh->nlmsg_flags |= NLM_F_ACK; // set kernel address memset(&nladdr, 0, sizeof(nladdr)); @@ -577,50 +575,12 @@ static ssize_t netlink_recv(char *buf, ssize_t len) return recvmsg(nlfd, &msg, 0); } -static ssize_t netlink_check_ack(struct nlmsghdr *ack_nh, ssize_t len, int msg_count) -{ - uint32_t seqnum = 0; - - // expect ack - for (; NLMSG_OK (ack_nh, len); ack_nh = NLMSG_NEXT (ack_nh, len)) - { - if (ack_nh->nlmsg_type == NLMSG_DONE) - return msg_count != 0 || seqnum != nlseqnum; - // 1 => lost an ack - - if (ack_nh->nlmsg_type == NLMSG_ERROR) - { - struct nlmsgerr *errmsg = NLMSG_DATA(ack_nh); - if (errmsg->error) - return errmsg->error; // got an error back - else - { - // ack received - --msg_count; - if (errmsg->msg.nlmsg_seq > seqnum); - seqnum = errmsg->msg.nlmsg_seq; - // if this is a single message, return now - if (!(ack_nh->nlmsg_flags & NLM_F_MULTI)) - return msg_count != 0 || seqnum != nlseqnum; - } - } - else - // unknown message - LOG(3, 0, 0, "Got an unknown netlink message: type %d\n", ack_nh->nlmsg_type); - } - - return 1; // malformed message?! -} - // // Set up TUN interface static void inittun(void) { struct ifinfomsg ifinfo; struct ifreq ifr; - char buf[4096]; - ssize_t len; - struct nlmsghdr *resp_nh; memset(&ifr, 0, sizeof(ifr)); ifr.ifr_flags = IFF_TUN; @@ -651,6 +611,9 @@ static void inittun(void) struct rtattr ifname_rta __attribute__ ((aligned(RTA_ALIGNTO))); char ifname[IFNAMSIZ]; } req; + char buf[4096]; + ssize_t len; + struct nlmsghdr *resp_nh; req.nh.nlmsg_type = RTM_GETLINK; req.nh.nlmsg_flags = NLM_F_REQUEST; @@ -664,7 +627,7 @@ static void inittun(void) req.nh.nlmsg_len = NLMSG_LENGTH(sizeof(req.ifinfo) + req.ifname_rta.rta_len); - if(netlink_send(&req.nh, 0) < 0 || (len = netlink_recv(buf, sizeof(buf))) < 0) + if(netlink_send(&req.nh) < 0 || (len = netlink_recv(buf, sizeof(buf))) < 0) { LOG(0, 0, 0, "Error getting tun ifindex: %s\n", strerror(errno)); exit(1); @@ -673,7 +636,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\n"); + LOG(0, 0, 0, "Malformed answer getting tun ifindex %d\n", len); exit(1); } @@ -682,7 +645,6 @@ static void inittun(void) tunidx = ifinfo.ifi_index; } { - ssize_t err; struct { // interface setting struct nlmsghdr nh; @@ -704,8 +666,6 @@ static void inittun(void) struct rtattr rta; struct in6_addr addr6 __attribute__ ((aligned(RTA_ALIGNTO)));; } ipv6_attr; - char buf[256]; - ssize_t buf_len; char *buf_ptr; memset(&req, 0, sizeof(req)); @@ -736,7 +696,7 @@ static void inittun(void) req.nh.nlmsg_len = NLMSG_LENGTH(sizeof(req.ifmsg.ifinfo) + u32_attr.rta.rta_len * 2); - if (netlink_send(&req.nh, 1) < 0) + if (netlink_send(&req.nh) < 0) { LOG(0, 0, 0, "Error setting up tun device interface: %s\n", strerror(errno)); exit(1); @@ -760,16 +720,16 @@ static void inittun(void) req.nh.nlmsg_len = NLMSG_LENGTH(sizeof(req.ifmsg.ifaddr) + ipv4_attr.rta.rta_len); - if (netlink_send(&req.nh, 1) < 0) + if (netlink_send(&req.nh) < 0) { LOG(0, 0, 0, "Error setting up tun device IPv4 address: %s\n", strerror(errno)); exit(1); } - memset(&req, 0, sizeof(req)); - // Only setup IPv6 on the tun device if we have a configured prefix if (config->ipv6_prefix.s6_addr[0]) { + memset(&req, 0, sizeof(req)); + req.nh.nlmsg_type = RTM_NEWADDR; req.nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_MULTI; @@ -790,7 +750,7 @@ static void inittun(void) req.nh.nlmsg_len = NLMSG_LENGTH(sizeof(req.ifmsg.ifaddr) + ipv6_attr.rta.rta_len); - if (netlink_send(&req.nh, 1) < 0) + if (netlink_send(&req.nh) < 0) { LOG(0, 0, 0, "Error setting up tun device IPv6 LL address: %s\n", strerror(errno)); exit(1); @@ -816,50 +776,23 @@ static void inittun(void) req.nh.nlmsg_len = NLMSG_LENGTH(sizeof(req.ifmsg.ifaddr) + ipv6_attr.rta.rta_len); - if (netlink_send(&req.nh, 1) < 0) + if (netlink_send(&req.nh) < 0) { LOG(0, 0, 0, "Error setting up tun device IPv6 global address: %s\n", strerror(errno)); exit(1); } - - memset(&req, 0, sizeof(req)); } + memset(&req, 0, sizeof(req)); + req.nh.nlmsg_type = NLMSG_DONE; req.nh.nlmsg_len = NLMSG_LENGTH(0); - if (netlink_send(&req.nh, 1) < 0) + if (netlink_send(&req.nh) < 0) { LOG(0, 0, 0, "Error finishing setting up tun device: %s\n", strerror(errno)); exit(1); } - - buf_ptr = buf; - buf_len = sizeof(buf); - do - { - len = netlink_recv(buf_ptr, sizeof(buf_len)); - if (len < 0) - { - LOG(0, 0, 0, "Error waiting for ack setting up tun device: %s\n", strerror(errno)); - exit(1); - } - - resp_nh = (struct nlmsghdr *)buf_ptr; - buf_len -= len; - buf_ptr += len; - } - while (buf_len > 0 && (resp_nh->nlmsg_flags & NLM_F_MULTI) - && resp_nh->nlmsg_type != NLMSG_DONE); - - if ((err = netlink_check_ack((struct nlmsghdr *)buf, buf_len, 4))) - { - if (err < 0) - LOG(0, 0, 0, "Error while receiving tun device ack: %s\n", strerror(errno)); - else - LOG(0, 0, 0, "Error while receiving tun device ack\n"); - exit(1); - } } } From 7bdb42fe548e6b2f13b6c1d7b6cb47656639787d Mon Sep 17 00:00:00 2001 From: Benjamin Cama Date: Tue, 16 Aug 2011 17:19:42 +0200 Subject: [PATCH 06/16] Add netlink fd polling. Signed-off-by: Benjamin Cama --- l2tpns.c | 45 +++++++++++++++++++++++++++++++++++++++------ l2tpns.h | 1 + 2 files changed, 40 insertions(+), 6 deletions(-) diff --git a/l2tpns.c b/l2tpns.c index 3d53622..8517ccf 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; @@ -636,7 +637,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); } @@ -793,6 +794,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 = 3 + 1; // idx + if + addr + else + min_initok_nlseqnum = 5 + 1; // idx + if + addr + 2*addr6 } } @@ -3669,8 +3677,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 +3702,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 +3739,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 +3879,27 @@ 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 && errmsg->msg.nlmsg_seq < min_initok_nlseqnum) + { + LOG(0, 0, 0, "Got a fatal netlink error: seq %d flags %d code %d\n", nh->nlmsg_seq, nh->nlmsg_flags, errmsg->error); + exit(1); + } + else + LOG(1, 0, 0, "Got a netlink error: seq %d flags %d code %d\n", nh->nlmsg_seq, nh->nlmsg_flags, errmsg->error); + } + 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); } diff --git a/l2tpns.h b/l2tpns.h index 6849be9..26928d1 100644 --- a/l2tpns.h +++ b/l2tpns.h @@ -935,6 +935,7 @@ struct event_data { FD_TYPE_DAE, FD_TYPE_RADIUS, FD_TYPE_BGP, + FD_TYPE_NETLINK, } type; int index; // for RADIUS, BGP }; From 1df1b625a854aecac219436c132f3c63c577a9dc Mon Sep 17 00:00:00 2001 From: Benjamin Cama Date: Tue, 16 Aug 2011 18:45:53 +0200 Subject: [PATCH 07/16] netlink: Better error handling. Signed-off-by: Benjamin Cama --- l2tpns.c | 29 ++++++++++++++++++++++------- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/l2tpns.c b/l2tpns.c index 8517ccf..96c6b00 100644 --- a/l2tpns.c +++ b/l2tpns.c @@ -576,6 +576,16 @@ static ssize_t netlink_recv(void *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) @@ -798,9 +808,9 @@ static void inittun(void) // 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 = 3 + 1; // idx + if + addr - else min_initok_nlseqnum = 5 + 1; // idx + if + addr + 2*addr6 + else + min_initok_nlseqnum = 3 + 1; // idx + if + addr } } @@ -3886,13 +3896,18 @@ static void mainloop(void) if (nh->nlmsg_type == NLMSG_ERROR) { struct nlmsgerr *errmsg = NLMSG_DATA(nh); - if (errmsg->error && errmsg->msg.nlmsg_seq < min_initok_nlseqnum) + if (errmsg->error) { - LOG(0, 0, 0, "Got a fatal netlink error: seq %d flags %d code %d\n", nh->nlmsg_seq, nh->nlmsg_flags, errmsg->error); - exit(1); + 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 - LOG(1, 0, 0, "Got a netlink error: seq %d flags %d code %d\n", nh->nlmsg_seq, nh->nlmsg_flags, 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); From 8f944eeb2197070c98c0e98b92d95cf3d35fdf67 Mon Sep 17 00:00:00 2001 From: Benjamin Cama Date: Tue, 16 Aug 2011 19:04:08 +0200 Subject: [PATCH 08/16] Fix wrong rta type. Signed-off-by: Benjamin Cama --- l2tpns.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/l2tpns.c b/l2tpns.c index 96c6b00..8224275 100644 --- a/l2tpns.c +++ b/l2tpns.c @@ -723,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)); From 4344f5e9c73e2ac36b67e72a400114063f037031 Mon Sep 17 00:00:00 2001 From: Benjamin Cama Date: Wed, 17 Aug 2011 00:23:25 +0200 Subject: [PATCH 09/16] Better tun device name length handling. Signed-off-by: Benjamin Cama --- l2tpns.c | 4 ++-- l2tpns.h | 6 +++++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/l2tpns.c b/l2tpns.c index 8224275..9f5e901 100644 --- a/l2tpns.c +++ b/l2tpns.c @@ -611,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 diff --git a/l2tpns.h b/l2tpns.h index 26928d1..b9a0714 100644 --- a/l2tpns.h +++ b/l2tpns.h @@ -616,6 +616,10 @@ struct Tstats #define SET_STAT(x, y) #endif +#ifndef IFNAMSIZ +# define IFNAMSIZ 16 +#endif + typedef struct { int debug; // debugging level @@ -631,7 +635,7 @@ typedef struct int reload_config; // flag to re-read config (set by cli) int multi_read_count; // amount of packets to read per fd in processing loop - char tundevice[10]; // tun device name + char tundevice[IFNAMSIZ]; // tun device name char log_filename[128]; char l2tp_secret[64]; // L2TP shared secret From e6bf06aa1b0d74bf2d748dbff76192d11c328592 Mon Sep 17 00:00:00 2001 From: Benjamin Cama Date: Wed, 17 Aug 2011 00:45:27 +0200 Subject: [PATCH 10/16] Simplify route attribute appending. Signed-off-by: Benjamin Cama --- l2tpns.c | 132 +++++++++++++++++++++---------------------------------- 1 file changed, 51 insertions(+), 81 deletions(-) diff --git a/l2tpns.c b/l2tpns.c index 9f5e901..57e3215 100644 --- a/l2tpns.c +++ b/l2tpns.c @@ -576,6 +576,19 @@ static ssize_t netlink_recv(void *buf, ssize_t len) return recvmsg(nlfd, &msg, 0); } +/* adapted from iproute2 */ +void netlink_addattr(struct nlmsghdr *nh, int type, const void *data, int alen) +{ + int len = RTA_LENGTH(alen); + struct rtattr *rta; + + rta = (struct rtattr *)(((void *)nh) + NLMSG_ALIGN(nh->nlmsg_len)); + rta->rta_type = type; + rta->rta_len = len; + memcpy(RTA_DATA(rta), data, alen); + nh->nlmsg_len = NLMSG_ALIGN(nh->nlmsg_len) + RTA_ALIGN(len); +} + // messages corresponding to different phases seq number static char *tun_nl_phase_msg[] = { "initialized", @@ -628,15 +641,11 @@ static void inittun(void) req.nh.nlmsg_type = RTM_GETLINK; req.nh.nlmsg_flags = NLM_F_REQUEST; + req.nh.nlmsg_len = NLMSG_LENGTH(sizeof(req.ifinfo)); req.ifinfo.ifi_family = AF_UNSPEC; // as the man says - req.ifname_rta.rta_len = RTA_LENGTH(strlen(config->tundevice)+1); - req.ifname_rta.rta_type = IFLA_IFNAME; - strncpy(req.ifname, config->tundevice, IFNAMSIZ-1); - - req.nh.nlmsg_len = NLMSG_LENGTH(sizeof(req.ifinfo) - + req.ifname_rta.rta_len); + netlink_addattr(&req.nh, IFLA_IFNAME, config->tundevice, strlen(config->tundevice)+1); if(netlink_send(&req.nh) < 0 || (len = netlink_recv(buf, sizeof(buf))) < 0) { @@ -665,133 +674,91 @@ static void inittun(void) } ifmsg __attribute__ ((aligned(NLMSG_ALIGNTO))); char rtdata[32]; // 32 should be enough } req; - struct { - struct rtattr rta; - uint32_t u32 __attribute__ ((aligned(RTA_ALIGNTO)));; - } u32_attr; - struct { - struct rtattr rta; - struct in_addr addr __attribute__ ((aligned(RTA_ALIGNTO)));; - } ipv4_attr; - struct { - struct rtattr rta; - struct in6_addr addr6 __attribute__ ((aligned(RTA_ALIGNTO)));; - } ipv6_attr; - char *buf_ptr; + uint32_t txqlen, mtu; + struct in_addr ip; memset(&req, 0, sizeof(req)); req.nh.nlmsg_type = RTM_SETLINK; req.nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_MULTI; + req.nh.nlmsg_len = NLMSG_LENGTH(sizeof(req.ifmsg.ifinfo)); req.ifmsg.ifinfo = ifinfo; req.ifmsg.ifinfo.ifi_flags |= IFF_UP; // set interface up req.ifmsg.ifinfo.ifi_change = IFF_UP; // only change this flag - buf_ptr = NLMSG_DATA(&req.nh) + sizeof(req.ifmsg.ifinfo); - - u32_attr.rta.rta_len = RTA_LENGTH(sizeof(u32_attr.u32)); - u32_attr.rta.rta_type = IFLA_TXQLEN; /* Bump up the qlen to deal with bursts from the network */ - u32_attr.u32 = 1000; - memcpy(buf_ptr, &u32_attr, sizeof(u32_attr)); - - buf_ptr += RTA_ALIGN(u32_attr.rta.rta_len); - - u32_attr.rta.rta_len = RTA_LENGTH(sizeof(u32_attr.u32)); - u32_attr.rta.rta_type = IFLA_MTU; + txqlen = 1000; + netlink_addattr(&req.nh, IFLA_TXQLEN, &txqlen, sizeof(txqlen)); /* set MTU to modem MRU */ - u32_attr.u32 = MRU; - memcpy(buf_ptr, &u32_attr, sizeof(u32_attr)); - - req.nh.nlmsg_len = NLMSG_LENGTH(sizeof(req.ifmsg.ifinfo) - + u32_attr.rta.rta_len * 2); + mtu = MRU; + netlink_addattr(&req.nh, IFLA_MTU, &mtu, sizeof(mtu)); if (netlink_send(&req.nh) < 0) - { - LOG(0, 0, 0, "Error setting up tun device interface: %s\n", strerror(errno)); - exit(1); - } + goto senderror; memset(&req, 0, sizeof(req)); req.nh.nlmsg_type = RTM_NEWADDR; req.nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_MULTI; + req.nh.nlmsg_len = NLMSG_LENGTH(sizeof(req.ifmsg.ifaddr)); req.ifmsg.ifaddr.ifa_family = AF_INET; req.ifmsg.ifaddr.ifa_prefixlen = 32; 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_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)); - - req.nh.nlmsg_len = NLMSG_LENGTH(sizeof(req.ifmsg.ifaddr) - + ipv4_attr.rta.rta_len); + if (config->bind_address) + ip.s_addr = config->bind_address; + else + ip.s_addr = 0x01010101, // 1.1.1.1 + netlink_addattr(&req.nh, IFA_LOCAL, &ip, sizeof(ip)); if (netlink_send(&req.nh) < 0) - { - LOG(0, 0, 0, "Error setting up tun device IPv4 address: %s\n", strerror(errno)); - exit(1); - } + goto senderror; // Only setup IPv6 on the tun device if we have a configured prefix if (config->ipv6_prefix.s6_addr[0]) { + struct in6_addr ip6; + memset(&req, 0, sizeof(req)); req.nh.nlmsg_type = RTM_NEWADDR; req.nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_MULTI; + req.nh.nlmsg_len = NLMSG_LENGTH(sizeof(req.ifmsg.ifaddr)); req.ifmsg.ifaddr.ifa_family = AF_INET6; req.ifmsg.ifaddr.ifa_prefixlen = 64; req.ifmsg.ifaddr.ifa_scope = RT_SCOPE_LINK; req.ifmsg.ifaddr.ifa_index = ifinfo.ifi_index; - ipv6_attr.rta.rta_len = RTA_LENGTH(sizeof(ipv6_attr.addr6)); - ipv6_attr.rta.rta_type = IFA_LOCAL; // Link local address is FE80::1 - memset(&ipv6_attr.addr6, 0, sizeof(ipv6_attr.addr6)); - ipv6_attr.addr6.s6_addr[0] = 0xFE; - ipv6_attr.addr6.s6_addr[1] = 0x80; - ipv6_attr.addr6.s6_addr[15] = 1; - memcpy(NLMSG_DATA(&req.nh) + sizeof(req.ifmsg.ifaddr), &ipv6_attr, sizeof(ipv6_attr)); - - req.nh.nlmsg_len = NLMSG_LENGTH(sizeof(req.ifmsg.ifaddr) - + ipv6_attr.rta.rta_len); + memset(&ip6, 0, sizeof(ip6)); + ip6.s6_addr[0] = 0xFE; + ip6.s6_addr[1] = 0x80; + ip6.s6_addr[15] = 1; + netlink_addattr(&req.nh, IFA_LOCAL, &ip6, sizeof(ip6)); if (netlink_send(&req.nh) < 0) - { - LOG(0, 0, 0, "Error setting up tun device IPv6 LL address: %s\n", strerror(errno)); - exit(1); - } + goto senderror; memset(&req, 0, sizeof(req)); req.nh.nlmsg_type = RTM_NEWADDR; req.nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_MULTI; + req.nh.nlmsg_len = NLMSG_LENGTH(sizeof(req.ifmsg.ifaddr)); req.ifmsg.ifaddr.ifa_family = AF_INET6; req.ifmsg.ifaddr.ifa_prefixlen = 64; req.ifmsg.ifaddr.ifa_scope = RT_SCOPE_UNIVERSE; req.ifmsg.ifaddr.ifa_index = ifinfo.ifi_index; - ipv6_attr.rta.rta_len = RTA_LENGTH(sizeof(ipv6_attr.addr6)); - ipv6_attr.rta.rta_type = IFA_LOCAL; // Global address is prefix::1 - ipv6_attr.addr6 = config->ipv6_prefix; - ipv6_attr.addr6.s6_addr[15] = 1; - memcpy(NLMSG_DATA(&req.nh) + sizeof(req.ifmsg.ifaddr), &ipv6_attr, sizeof(ipv6_attr)); - - req.nh.nlmsg_len = NLMSG_LENGTH(sizeof(req.ifmsg.ifaddr) - + ipv6_attr.rta.rta_len); + ip6 = config->ipv6_prefix; + ip6.s6_addr[15] = 1; + netlink_addattr(&req.nh, IFA_LOCAL, &ip6, sizeof(ip6)); if (netlink_send(&req.nh) < 0) - { - LOG(0, 0, 0, "Error setting up tun device IPv6 global address: %s\n", strerror(errno)); - exit(1); - } + goto senderror; } memset(&req, 0, sizeof(req)); @@ -800,10 +767,7 @@ static void inittun(void) req.nh.nlmsg_len = NLMSG_LENGTH(0); if (netlink_send(&req.nh) < 0) - { - LOG(0, 0, 0, "Error finishing setting up tun device: %s\n", strerror(errno)); - exit(1); - } + goto senderror; // if we get an error for seqnum < min_initok_nlseqnum, // we must exit as initialization went wrong @@ -812,6 +776,12 @@ static void inittun(void) else min_initok_nlseqnum = 3 + 1; // idx + if + addr } + + return; + +senderror: + LOG(0, 0, 0, "Error while setting up tun device: %s\n", strerror(errno)); + exit(1); } // set up UDP ports From 7c474381d4dcc23b9fb4d3a2401971a9ef79c889 Mon Sep 17 00:00:00 2001 From: Benjamin Cama Date: Wed, 17 Aug 2011 01:41:54 +0200 Subject: [PATCH 11/16] Switch from masks to CIDR globally for IPv4. Signed-off-by: Benjamin Cama --- bgp.c | 32 ++++++-------------------- bgp.h | 4 ++-- l2tpns.c | 70 +++++++++++++++++++++++++++++--------------------------- l2tpns.h | 2 +- radius.c | 29 ++++++++--------------- 5 files changed, 55 insertions(+), 82 deletions(-) diff --git a/bgp.c b/bgp.c index 6a868fa..eca1518 100644 --- a/bgp.c +++ b/bgp.c @@ -29,7 +29,7 @@ char const *cvs_id_bgp = "$Id: bgp.c,v 1.12 2005/09/02 23:39:36 bodea Exp $"; static void bgp_clear(struct bgp_peer *peer); static void bgp_set_retry(struct bgp_peer *peer); -static void bgp_cidr(in_addr_t ip, in_addr_t mask, struct bgp_ip_prefix *pfx); +static void bgp_cidr(in_addr_t ip, int prefixlen, struct bgp_ip_prefix *pfx); static struct bgp_route_list *bgp_insert_route(struct bgp_route_list *head, struct bgp_route_list *new); @@ -327,26 +327,6 @@ static void bgp_set_retry(struct bgp_peer *peer) bgp_halt(peer); /* give up */ } -/* convert ip/mask to CIDR notation */ -static void bgp_cidr(in_addr_t ip, in_addr_t mask, struct bgp_ip_prefix *pfx) -{ - int i; - uint32_t b; - - /* convert to prefix notation */ - pfx->len = 32; - pfx->prefix = ip; - - if (!mask) /* bogus */ - mask = 0xffffffff; - - for (i = 0; i < 32 && ((b = ntohl(1 << i)), !(mask & b)); i++) - { - pfx->len--; - pfx->prefix &= ~b; - } -} - /* insert route into list; sorted */ static struct bgp_route_list *bgp_insert_route(struct bgp_route_list *head, struct bgp_route_list *new) @@ -381,13 +361,14 @@ static struct bgp_route_list *bgp_insert_route(struct bgp_route_list *head, * that if that route is later deleted we don't have to be concerned * about adding back the more specific one). */ -int bgp_add_route(in_addr_t ip, in_addr_t mask) +int bgp_add_route(in_addr_t ip, int prefixlen) { struct bgp_route_list *r = bgp_routes; struct bgp_route_list add; int i; - bgp_cidr(ip, mask, &add.dest); + add.dest.prefix = ip; + add.dest.len = prefixlen; add.next = 0; /* check for duplicate */ @@ -427,14 +408,15 @@ int bgp_add_route(in_addr_t ip, in_addr_t mask) } /* remove route from list for peers */ -int bgp_del_route(in_addr_t ip, in_addr_t mask) +int bgp_del_route(in_addr_t ip, int prefixlen) { struct bgp_route_list *r = bgp_routes; struct bgp_route_list *e = 0; struct bgp_route_list del; int i; - bgp_cidr(ip, mask, &del.dest); + del.dest.ip = ip; + del.dest.len = prefixlen; del.next = 0; /* find entry in routes list and remove */ diff --git a/bgp.h b/bgp.h index 0a2e59c..f8b52d6 100644 --- a/bgp.h +++ b/bgp.h @@ -193,8 +193,8 @@ int bgp_start(struct bgp_peer *peer, char *name, int as, int keepalive, void bgp_stop(struct bgp_peer *peer); void bgp_halt(struct bgp_peer *peer); int bgp_restart(struct bgp_peer *peer); -int bgp_add_route(in_addr_t ip, in_addr_t mask); -int bgp_del_route(in_addr_t ip, in_addr_t mask); +int bgp_add_route(in_addr_t ip, int prefixlen); +int bgp_del_route(in_addr_t ip, int prefixlen); void bgp_enable_routing(int enable); int bgp_set_poll(void); int bgp_process(uint32_t events[]); diff --git a/l2tpns.c b/l2tpns.c index 57e3215..f530955 100644 --- a/l2tpns.c +++ b/l2tpns.c @@ -419,16 +419,19 @@ void random_data(uint8_t *buf, int len) // via BGP if enabled, and stuffs it into the // 'sessionbyip' cache. // -// 'ip' and 'mask' must be in _host_ order. +// 'ip' must be in _host_ order. // -static void routeset(sessionidt s, in_addr_t ip, in_addr_t mask, in_addr_t gw, int add) +static void routeset(sessionidt s, in_addr_t ip, int prefixlen, in_addr_t gw, int add) { struct rtentry r; + in_addr_t mask; int i; - if (!mask) mask = 0xffffffff; + if (!prefixlen) prefixlen = 32; - ip &= mask; // Force the ip to be the first one in the route. + mask = 0xffffffff << (32 - prefixlen); + + ip &= mask; // Force the ip to be the first one in the route. memset(&r, 0, sizeof(r)); r.rt_dev = config->tundevice; @@ -441,11 +444,11 @@ static void routeset(sessionidt s, in_addr_t ip, in_addr_t mask, in_addr_t gw, i r.rt_flags = (RTF_UP | RTF_STATIC); if (gw) r.rt_flags |= RTF_GATEWAY; - else if (mask == 0xffffffff) + else if (prefixlen == 32) r.rt_flags |= RTF_HOST; - LOG(1, s, 0, "Route %s %s/%s%s%s\n", add ? "add" : "del", - fmtaddr(htonl(ip), 0), fmtaddr(htonl(mask), 1), + LOG(1, s, 0, "Route %s %s/%d%s%s\n", add ? "add" : "del", + fmtaddr(htonl(ip), 0), prefixlen, gw ? " via" : "", gw ? fmtaddr(htonl(gw), 2) : ""); if (ioctl(ifrfd, add ? SIOCADDRT : SIOCDELRT, (void *) &r) < 0) @@ -453,9 +456,9 @@ static void routeset(sessionidt s, in_addr_t ip, in_addr_t mask, in_addr_t gw, i #ifdef BGP if (add) - bgp_add_route(htonl(ip), htonl(mask)); + bgp_add_route(htonl(ip), prefixlen); else - bgp_del_route(htonl(ip), htonl(mask)); + bgp_del_route(htonl(ip), prefixlen); #endif /* BGP */ // Add/Remove the IPs to the 'sessionbyip' cache. @@ -471,7 +474,7 @@ static void routeset(sessionidt s, in_addr_t ip, in_addr_t mask, in_addr_t gw, i if (!add) // Are we deleting a route? s = 0; // Caching the session as '0' is the same as uncaching. - for (i = ip; (i&mask) == (ip&mask) ; ++i) + for (i = ip; i < ip+(1<<(32-prefixlen)) ; ++i) cache_ipmap(i, s); } } @@ -1927,11 +1930,11 @@ void sessionshutdown(sessionidt s, char const *reason, int cdn_result, int cdn_e int routed = 0; for (r = 0; r < MAXROUTE && session[s].route[r].ip; r++) { - if ((session[s].ip & session[s].route[r].mask) == - (session[s].route[r].ip & session[s].route[r].mask)) + if ((session[s].ip >> (32-session[s].route[r].prefixlen)) == + (session[s].route[r].ip >> (32-session[s].route[r].prefixlen))) routed++; - if (del_routes) routeset(s, session[s].route[r].ip, session[s].route[r].mask, 0, 0); + if (del_routes) routeset(s, session[s].route[r].ip, session[s].route[r].prefixlen, 0, 0); session[s].route[r].ip = 0; } @@ -4443,18 +4446,18 @@ static void fix_address_pool(int sid) // // Add a block of addresses to the IP pool to hand out. // -static void add_to_ip_pool(in_addr_t addr, in_addr_t mask) +static void add_to_ip_pool(in_addr_t addr, int prefixlen) { int i; - if (mask == 0) - mask = 0xffffffff; // Host route only. + if (prefixlen == 0) + prefixlen = 32; // Host route only. - addr &= mask; + addr &= 0xffffffff << (32 - prefixlen); if (ip_pool_size >= MAXIPPOOL) // Pool is full! return ; - for (i = addr ;(i & mask) == addr; ++i) + for (i = addr ; i < addr+(1<<(32-prefixlen)); ++i) { if ((i & 0xff) == 0 || (i&0xff) == 255) continue; // Skip 0 and broadcast addresses. @@ -4512,7 +4515,7 @@ static void initippool() { // It's a range int numbits = 0; - in_addr_t start = 0, mask = 0; + in_addr_t start = 0; LOG(2, 0, 0, "Adding IP address range %s\n", buf); *p++ = 0; @@ -4522,15 +4525,14 @@ static void initippool() continue; } start = ntohl(inet_addr(pool)); - mask = (in_addr_t) (pow(2, numbits) - 1) << (32 - numbits); // Add a static route for this pool - LOG(5, 0, 0, "Adding route for address pool %s/%u\n", - fmtaddr(htonl(start), 0), 32 + mask); + LOG(5, 0, 0, "Adding route for address pool %s/%d\n", + fmtaddr(htonl(start), 0), numbits); - routeset(0, start, mask, 0, 1); + routeset(0, start, numbits, 0, 1); - add_to_ip_pool(start, mask); + add_to_ip_pool(start, numbits); } else { @@ -5179,11 +5181,11 @@ int sessionsetup(sessionidt s, tunnelidt t) // Add the route for this session. for (r = 0; r < MAXROUTE && session[s].route[r].ip; r++) { - if ((session[s].ip & session[s].route[r].mask) == - (session[s].route[r].ip & session[s].route[r].mask)) + if ((session[s].ip >> (32-session[s].route[r].prefixlen)) == + (session[s].route[r].ip >> (32-session[s].route[r].prefixlen))) routed++; - routeset(s, session[s].route[r].ip, session[s].route[r].mask, 0, 1); + routeset(s, session[s].route[r].ip, session[s].route[r].prefixlen, 0, 1); } // Static IPs need to be routed if not already @@ -5254,7 +5256,7 @@ int load_session(sessionidt s, sessiont *new) for (i = 0; !newip && i < MAXROUTE && (session[s].route[i].ip || new->route[i].ip); i++) if (new->route[i].ip != session[s].route[i].ip || - new->route[i].mask != session[s].route[i].mask) + new->route[i].prefixlen != session[s].route[i].prefixlen) newip++; // needs update @@ -5265,11 +5267,11 @@ int load_session(sessionidt s, sessiont *new) // remove old routes... for (i = 0; i < MAXROUTE && session[s].route[i].ip; i++) { - if ((session[s].ip & session[s].route[i].mask) == - (session[s].route[i].ip & session[s].route[i].mask)) + if ((session[s].ip >> (32-session[s].route[i].prefixlen)) == + (session[s].route[i].ip >> (32-session[s].route[i].prefixlen))) routed++; - routeset(s, session[s].route[i].ip, session[s].route[i].mask, 0, 0); + routeset(s, session[s].route[i].ip, session[s].route[i].prefixlen, 0, 0); } // ...ip @@ -5288,11 +5290,11 @@ int load_session(sessionidt s, sessiont *new) // add new routes... for (i = 0; i < MAXROUTE && new->route[i].ip; i++) { - if ((new->ip & new->route[i].mask) == - (new->route[i].ip & new->route[i].mask)) + if ((new->ip >> (32-new->route[i].prefixlen)) == + (new->route[i].ip >> (32-new->route[i].prefixlen))) routed++; - routeset(s, new->route[i].ip, new->route[i].mask, 0, 1); + routeset(s, new->route[i].ip, new->route[i].prefixlen, 0, 1); } // ...ip diff --git a/l2tpns.h b/l2tpns.h index b9a0714..bab2921 100644 --- a/l2tpns.h +++ b/l2tpns.h @@ -233,7 +233,7 @@ struct cli_tunnel_actions { typedef struct // route { in_addr_t ip; - in_addr_t mask; + int prefixlen; } routet; diff --git a/radius.c b/radius.c index 93a1cde..e337a75 100644 --- a/radius.c +++ b/radius.c @@ -402,21 +402,11 @@ void radiussend(uint16_t r, uint8_t state) int r; for (r = 0; s && r < MAXROUTE && session[s].route[r].ip; r++) { - int width = 32; - if (session[s].route[r].mask) - { - int mask = session[s].route[r].mask; - while (!(mask & 1)) - { - width--; - mask >>= 1; - } - } - *p = 22; // Framed-Route p[1] = sprintf((char *) p + 2, "%s/%d %s 1", fmtaddr(htonl(session[s].route[r].ip), 0), - width, fmtaddr(htonl(session[s].ip), 1)) + 2; + session[s].route[r].prefixlen, + fmtaddr(htonl(session[s].ip), 1)) + 2; p += p[1]; } @@ -696,7 +686,7 @@ void processrad(uint8_t *buf, int len, char socket_index) else if (*p == 22) { // Framed-Route - in_addr_t ip = 0, mask = 0; + in_addr_t ip = 0; uint8_t u = 0; uint8_t bits = 0; uint8_t *n = p + 2; @@ -718,14 +708,13 @@ void processrad(uint8_t *buf, int len, char socket_index) n++; while (n < e && isdigit(*n)) bits = bits * 10 + *n++ - '0'; - mask = (( -1) << (32 - bits)); } else if ((ip >> 24) < 128) - mask = 0xFF0000; + bits = 8; else if ((ip >> 24) < 192) - mask = 0xFFFF0000; + bits = 16; else - mask = 0xFFFFFF00; + bits = 24; if (routes == MAXROUTE) { @@ -733,11 +722,11 @@ void processrad(uint8_t *buf, int len, char socket_index) } else if (ip) { - LOG(3, s, session[s].tunnel, " Radius reply contains route for %s/%s\n", - fmtaddr(htonl(ip), 0), fmtaddr(htonl(mask), 1)); + LOG(3, s, session[s].tunnel, " Radius reply contains route for %s/%d\n", + fmtaddr(htonl(ip), 0), bits, 1)); session[s].route[routes].ip = ip; - session[s].route[routes].mask = mask; + session[s].route[routes].prefixlen = bits; routes++; } } From 3190b01adac79f00390f9e70a3017411be75a7bc Mon Sep 17 00:00:00 2001 From: Benjamin Cama Date: Wed, 17 Aug 2011 02:21:01 +0200 Subject: [PATCH 12/16] Fix last commit on switching to CIDR. Signed-off-by: Benjamin Cama --- bgp.c | 2 +- radius.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bgp.c b/bgp.c index eca1518..f1d0ec2 100644 --- a/bgp.c +++ b/bgp.c @@ -415,7 +415,7 @@ int bgp_del_route(in_addr_t ip, int prefixlen) struct bgp_route_list del; int i; - del.dest.ip = ip; + del.dest.prefix = ip; del.dest.len = prefixlen; del.next = 0; diff --git a/radius.c b/radius.c index e337a75..4e67e63 100644 --- a/radius.c +++ b/radius.c @@ -723,7 +723,7 @@ void processrad(uint8_t *buf, int len, char socket_index) else if (ip) { LOG(3, s, session[s].tunnel, " Radius reply contains route for %s/%d\n", - fmtaddr(htonl(ip), 0), bits, 1)); + fmtaddr(htonl(ip), 0), bits); session[s].route[routes].ip = ip; session[s].route[routes].prefixlen = bits; From d02a2433978f0919a780073b2f49af4b5d3ba9ea Mon Sep 17 00:00:00 2001 From: Benjamin Cama Date: Wed, 17 Aug 2011 02:22:01 +0200 Subject: [PATCH 13/16] Route setting sockets don't exist anymore; remove them. Signed-off-by: Benjamin Cama --- util.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/util.c b/util.c index f3303b4..78ec78b 100644 --- a/util.c +++ b/util.c @@ -81,8 +81,6 @@ pid_t fork_and_close() if (controlfd != -1) close(controlfd); if (daefd != -1) close(daefd); if (snoopfd != -1) close(snoopfd); - if (ifrfd != -1) close(ifrfd); - if (ifr6fd != -1) close(ifr6fd); if (rand_fd != -1) close(rand_fd); if (epollfd != -1) close(epollfd); From 1455a9c9bbb752e0c94a8b3a8087c2182ac9c609 Mon Sep 17 00:00:00 2001 From: Benjamin Cama Date: Wed, 17 Aug 2011 02:23:13 +0200 Subject: [PATCH 14/16] Make routset()/route6set() use netlink. Signed-off-by: Benjamin Cama --- l2tpns.c | 102 ++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 68 insertions(+), 34 deletions(-) diff --git a/l2tpns.c b/l2tpns.c index f530955..110029a 100644 --- a/l2tpns.c +++ b/l2tpns.c @@ -200,6 +200,8 @@ 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); @@ -423,36 +425,51 @@ void random_data(uint8_t *buf, int len) // static void routeset(sessionidt s, in_addr_t ip, int prefixlen, in_addr_t gw, int add) { - struct rtentry r; - in_addr_t mask; + struct { + struct nlmsghdr nh; + struct rtmsg rt; + char buf[32]; + } req; int i; + in_addr_t n_ip; if (!prefixlen) prefixlen = 32; - mask = 0xffffffff << (32 - prefixlen); + ip &= 0xffffffff << (32 - prefixlen);; // Force the ip to be the first one in the route. - ip &= mask; // Force the ip to be the first one in the route. + memset(&req, 0, sizeof(req)); - memset(&r, 0, sizeof(r)); - r.rt_dev = config->tundevice; - r.rt_dst.sa_family = AF_INET; - *(uint32_t *) & (((struct sockaddr_in *) &r.rt_dst)->sin_addr.s_addr) = htonl(ip); - r.rt_gateway.sa_family = AF_INET; - *(uint32_t *) & (((struct sockaddr_in *) &r.rt_gateway)->sin_addr.s_addr) = htonl(gw); - r.rt_genmask.sa_family = AF_INET; - *(uint32_t *) & (((struct sockaddr_in *) &r.rt_genmask)->sin_addr.s_addr) = htonl(mask); - r.rt_flags = (RTF_UP | RTF_STATIC); + if (add) + { + req.nh.nlmsg_type = RTM_NEWROUTE; + req.nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_REPLACE; + } + else + req.nh.nlmsg_type = RTM_DELROUTE; + req.nh.nlmsg_len = NLMSG_LENGTH(sizeof(req.rt)); + + req.rt.rtm_family = AF_INET; + req.rt.rtm_dst_len = prefixlen; + req.rt.rtm_table = RT_TABLE_MAIN; + req.rt.rtm_protocol = RTPROT_BOOT; // XXX + req.rt.rtm_scope = RT_SCOPE_LINK; + req.rt.rtm_type = RTN_UNICAST; + + netlink_addattr(&req.nh, RTA_OIF, &tunidx, sizeof(int)); + n_ip = htonl(ip); + netlink_addattr(&req.nh, RTA_DST, &n_ip, sizeof(n_ip)); if (gw) - r.rt_flags |= RTF_GATEWAY; - else if (prefixlen == 32) - r.rt_flags |= RTF_HOST; + { + n_ip = htonl(gw); + netlink_addattr(&req.nh, RTA_GATEWAY, &n_ip, sizeof(n_ip)); + } LOG(1, s, 0, "Route %s %s/%d%s%s\n", add ? "add" : "del", fmtaddr(htonl(ip), 0), prefixlen, gw ? " via" : "", gw ? fmtaddr(htonl(gw), 2) : ""); - if (ioctl(ifrfd, add ? SIOCADDRT : SIOCDELRT, (void *) &r) < 0) - LOG(0, 0, 0, "routeset() error in ioctl: %s\n", strerror(errno)); + if (netlink_send(&req.nh) < 0) + LOG(0, 0, 0, "routeset() error in sending netlink message: %s\n", strerror(errno)); #ifdef BGP if (add) @@ -481,31 +498,50 @@ static void routeset(sessionidt s, in_addr_t ip, int prefixlen, in_addr_t gw, in void route6set(sessionidt s, struct in6_addr ip, int prefixlen, int add) { - struct in6_rtmsg rt; + struct { + struct nlmsghdr nh; + struct rtmsg rt; + char buf[64]; + } req; + int metric; char ipv6addr[INET6_ADDRSTRLEN]; - if (ifr6fd < 0) + if (!config->ipv6_prefix.s6_addr[0]) { LOG(0, 0, 0, "Asked to set IPv6 route, but IPv6 not setup.\n"); return; } - memset(&rt, 0, sizeof(rt)); + memset(&req, 0, sizeof(req)); - memcpy(&rt.rtmsg_dst, &ip, sizeof(struct in6_addr)); - rt.rtmsg_dst_len = prefixlen; - rt.rtmsg_metric = 1; - rt.rtmsg_flags = RTF_UP; - rt.rtmsg_ifindex = tunidx; + if (add) + { + req.nh.nlmsg_type = RTM_NEWROUTE; + req.nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_REPLACE; + } + else + req.nh.nlmsg_type = RTM_DELROUTE; + req.nh.nlmsg_len = NLMSG_LENGTH(sizeof(req.rt)); + + req.rt.rtm_family = AF_INET6; + req.rt.rtm_dst_len = prefixlen; + req.rt.rtm_table = RT_TABLE_MAIN; + req.rt.rtm_protocol = RTPROT_BOOT; // XXX + req.rt.rtm_scope = RT_SCOPE_LINK; + req.rt.rtm_type = RTN_UNICAST; + + netlink_addattr(&req.nh, RTA_OIF, &tunidx, sizeof(int)); + netlink_addattr(&req.nh, RTA_DST, &ip, sizeof(ip)); + metric = 1; + netlink_addattr(&req.nh, RTA_METRICS, &metric, sizeof(metric)); LOG(1, 0, 0, "Route %s %s/%d\n", add ? "add" : "del", inet_ntop(AF_INET6, &ip, ipv6addr, INET6_ADDRSTRLEN), prefixlen); - if (ioctl(ifr6fd, add ? SIOCADDRT : SIOCDELRT, (void *) &rt) < 0) - LOG(0, 0, 0, "route6set() error in ioctl: %s\n", - strerror(errno)); + if (netlink_send(&req.nh) < 0) + LOG(0, 0, 0, "route6set() error in sending netlink message: %s\n", strerror(errno)); // FIXME: need to add BGP routing (RFC2858) @@ -580,7 +616,7 @@ static ssize_t netlink_recv(void *buf, ssize_t len) } /* adapted from iproute2 */ -void netlink_addattr(struct nlmsghdr *nh, int type, const void *data, int alen) +static void netlink_addattr(struct nlmsghdr *nh, int type, const void *data, int alen) { int len = RTA_LENGTH(alen); struct rtattr *rta; @@ -634,9 +670,7 @@ static void inittun(void) // get the interface index struct { struct nlmsghdr nh; - struct ifinfomsg ifinfo __attribute__ ((aligned(NLMSG_ALIGNTO))); - struct rtattr ifname_rta __attribute__ ((aligned(RTA_ALIGNTO))); - char ifname[IFNAMSIZ]; + struct ifinfomsg ifinfo; } req; char buf[4096]; ssize_t len; @@ -674,7 +708,7 @@ static void inittun(void) union { struct ifinfomsg ifinfo; struct ifaddrmsg ifaddr; - } ifmsg __attribute__ ((aligned(NLMSG_ALIGNTO))); + } ifmsg; char rtdata[32]; // 32 should be enough } req; uint32_t txqlen, mtu; From 464a2bb072ee5a243fd13ac96f3a7200ebf36c21 Mon Sep 17 00:00:00 2001 From: Benjamin Cama Date: Wed, 17 Aug 2011 02:28:33 +0200 Subject: [PATCH 15/16] Since 7c47438 we can remove math.h. Signed-off-by: Benjamin Cama --- l2tpns.c | 1 - 1 file changed, 1 deletion(-) diff --git a/l2tpns.c b/l2tpns.c index 110029a..4b7d93f 100644 --- a/l2tpns.c +++ b/l2tpns.c @@ -14,7 +14,6 @@ char const *cvs_id_l2tpns = "$Id: l2tpns.c,v 1.176 2011/01/20 12:48:40 bodea Exp #define SYSLOG_NAMES #include #include -#include #include #include #include From 1b372e5d46ee1e3ed35270504e92339d1aba1d11 Mon Sep 17 00:00:00 2001 From: Benjamin Cama Date: Wed, 17 Aug 2011 17:16:30 +0200 Subject: [PATCH 16/16] Fix a stray comma, and replace existing routes. Signed-off-by: Benjamin Cama --- l2tpns.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/l2tpns.c b/l2tpns.c index 4b7d93f..c34dc63 100644 --- a/l2tpns.c +++ b/l2tpns.c @@ -711,7 +711,7 @@ static void inittun(void) char rtdata[32]; // 32 should be enough } req; uint32_t txqlen, mtu; - struct in_addr ip; + in_addr_t ip; memset(&req, 0, sizeof(req)); @@ -736,17 +736,18 @@ static void inittun(void) memset(&req, 0, sizeof(req)); req.nh.nlmsg_type = RTM_NEWADDR; - req.nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_MULTI; + req.nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_REPLACE | NLM_F_MULTI; req.nh.nlmsg_len = NLMSG_LENGTH(sizeof(req.ifmsg.ifaddr)); req.ifmsg.ifaddr.ifa_family = AF_INET; req.ifmsg.ifaddr.ifa_prefixlen = 32; + req.ifmsg.ifaddr.ifa_scope = RT_SCOPE_UNIVERSE; req.ifmsg.ifaddr.ifa_index = ifinfo.ifi_index; if (config->bind_address) - ip.s_addr = config->bind_address; + ip = config->bind_address; else - ip.s_addr = 0x01010101, // 1.1.1.1 + ip = 0x01010101; // 1.1.1.1 netlink_addattr(&req.nh, IFA_LOCAL, &ip, sizeof(ip)); if (netlink_send(&req.nh) < 0) @@ -759,7 +760,7 @@ static void inittun(void) memset(&req, 0, sizeof(req)); req.nh.nlmsg_type = RTM_NEWADDR; - req.nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_MULTI; + req.nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_REPLACE | NLM_F_MULTI; req.nh.nlmsg_len = NLMSG_LENGTH(sizeof(req.ifmsg.ifaddr)); req.ifmsg.ifaddr.ifa_family = AF_INET6; @@ -780,7 +781,7 @@ static void inittun(void) memset(&req, 0, sizeof(req)); req.nh.nlmsg_type = RTM_NEWADDR; - req.nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_MULTI; + req.nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_REPLACE | NLM_F_MULTI; req.nh.nlmsg_len = NLMSG_LENGTH(sizeof(req.ifmsg.ifaddr)); req.ifmsg.ifaddr.ifa_family = AF_INET6;