X-Git-Url: http://git.sameswireless.fr/l2tpns.git/blobdiff_plain/7aa8cc3dc0df081350a7f9b4a30ef8490ee74fe0..5cd5238b2f551cccbe6d7dc4bbec76c4c2ce7af6:/l2tpns.c diff --git a/l2tpns.c b/l2tpns.c index 8230945..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,47 +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, int msg_count) -{ - ssize_t len; - uint32_t seqnum; - - // 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; - } - } - 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]; - struct nlmsghdr resp_nh; memset(&ifr, 0, sizeof(ifr)); ifr.ifr_flags = IFF_TUN; @@ -642,13 +605,15 @@ 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; + char buf[4096]; + ssize_t len; + struct nlmsghdr *resp_nh; req.nh.nlmsg_type = RTM_GETLINK; req.nh.nlmsg_flags = NLM_F_REQUEST; @@ -659,163 +624,173 @@ static void inittun(void) 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) + req.nh.nlmsg_len = NLMSG_LENGTH(sizeof(req.ifinfo) + + req.ifname_rta.rta_len); + + 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); } resp_nh = (struct nlmsghdr *)buf; - if (NLMSG_OK (resp_nh, len) && resp_nh.nlmsg_type == RTM_GETLINK) + if (!NLMSG_OK (resp_nh, len)) { - 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"); + LOG(0, 0, 0, "Malformed answer getting tun ifindex %d\n", len); 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_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.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.ifinfo = ifinfo; - req.ifinfo.ifi_flags |= IFF_UP; // set interface up - req.ifinfo.ifi_change = IFF_UP; // only change this flag + buf_ptr = NLMSG_DATA(&req.nh) + sizeof(req.ifmsg.ifinfo); - req.txqlen_rta.rta_len = RTA_LENGTH(sizeof(req.txqlen)); - req.txqlen_rta.rta_type = IFLA_TXQLEN; + 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_rla.rta_len - + req.mtu_rta.rta_len); + req.nh.nlmsg_len = NLMSG_LENGTH(sizeof(req.ifmsg.ifinfo) + + u32_attr.rta.rta_len * 2); - req.addr_nh.nlmsg_type = RTM_NEWADDR; - req.addr_nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_MULTI; + if (netlink_send(&req.nh) < 0) + { + LOG(0, 0, 0, "Error setting up tun device interface: %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.ifaddr.ifa_family = AF_INET; - req.ifaddr.ifa_prefixlen = 32; - req.ifaddr.ifa_index = ifinfo.ifi_index; + req.ifmsg.ifaddr.ifa_family = AF_INET; + req.ifmsg.ifaddr.ifa_prefixlen = 32; + req.ifmsg.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 ? + 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.addr_nh.nlmsg_len = NLMSG_LENGTH(sizeof(req.ifaddr) - + req.addr_rta.rta_len); + req.nh.nlmsg_len = NLMSG_LENGTH(sizeof(req.ifmsg.ifaddr) + + ipv4_attr.rta.rta_len); + + if (netlink_send(&req.nh) < 0) + { + LOG(0, 0, 0, "Error setting up tun device IPv4 address: %s\n", strerror(errno)); + exit(1); + } // 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; + memset(&req, 0, sizeof(req)); - 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.nh.nlmsg_type = RTM_NEWADDR; + req.nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_MULTI; - req.lladdr6_rta.rta_len = RTA_LENGTH(sizeof(req.lladdr6)); - req.lladdr6_rta.rta_type = IFA_LOCAL; + 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(&req.lladdr6, 0, sizeof(req.lladdr6)); - req.lladdr6.s6_addr[0] = 0xFE; - req.lladdr6.s6_addr[1] = 0x80; - req.lladdr6.s6_addr[15] = 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) < 0) + { + LOG(0, 0, 0, "Error setting up tun device IPv6 LL address: %s\n", strerror(errno)); + exit(1); + } - req.lladdr6_nh.nlmsg_len = NLMSG_LENGTH(sizeof(req.ifaddr) - + req.lladdr6_rta.rta_len); + memset(&req, 0, sizeof(req)); - req.addr6_nh.nlmsg_type = RTM_NEWADDR; - req.addr6_nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_MULTI; + req.nh.nlmsg_type = RTM_NEWADDR; + req.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.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; - req.addr6_rta.rta_len = RTA_LENGTH(sizeof(req.addr6)); - req.addr6_rta.rta_type = IFA_LOCAL; + ipv6_attr.rta.rta_len = RTA_LENGTH(sizeof(ipv6_attr.addr6)); + ipv6_attr.rta.rta_type = IFA_LOCAL; // Global address is prefix::1 - req.addr6 = config->ipv6_prefix; - req.addr6.s6_addr[15] = 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.lladdr6_nh.nlmsg_len = NLMSG_LENGTH(sizeof(req.ifaddr) - + req.lladdr6_rta.rta_len); + req.nh.nlmsg_len = NLMSG_LENGTH(sizeof(req.ifmsg.ifaddr) + + ipv6_attr.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); + if (netlink_send(&req.nh) < 0) + { + LOG(0, 0, 0, "Error setting up tun device IPv6 global address: %s\n", strerror(errno)); + exit(1); + } } - if (netlink_send(&req.nh, 1) < 0) - LOG(0, 0, 0, "Error setting up tun device: %s\n", strerror(errno)); - exit(1); - } + memset(&req, 0, sizeof(req)); - if (netlink_recv(buf, sizeof(buf)) < 0) - { - LOG(0, 0, 0, "Error waiting ack for setting up tun device: %s\n", strerror(errno)); - exit(1); - } + req.nh.nlmsg_type = NLMSG_DONE; + req.nh.nlmsg_len = NLMSG_LENGTH(0); - resp_nh = (struct nlmsghdr *)buf; - if ((err = netlink_check_ack(resp_nh, 4))) + if (netlink_send(&req.nh) < 0) { - 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 finishing setting up tun device: %s\n", strerror(errno)); exit(1); } } @@ -4733,6 +4708,8 @@ int main(int argc, char *argv[]) } } + initnetlink(); + /* Set up the cluster communications port. */ if (cluster_init() < 0) exit(1);