From 60329986b242e766fc965b853fb24694b710698d Mon Sep 17 00:00:00 2001 From: Samuel Thibault Date: Tue, 18 Apr 2023 00:07:40 +0200 Subject: [PATCH] Rename netlink infrastructure to rtnetlink We will introduce genetlink infrastructure just after this. --- l2tpns.c | 161 ++++++++++++++++++++++++++++++++++--------------------- l2tpns.h | 4 +- util.c | 2 +- 3 files changed, 102 insertions(+), 65 deletions(-) diff --git a/l2tpns.c b/l2tpns.c index 43c6413..05986ba 100644 --- a/l2tpns.c +++ b/l2tpns.c @@ -63,7 +63,7 @@ uint32_t call_serial_number = 0; // Globals configt *config = NULL; // all configuration -int nlfd = -1; // netlink socket +int rtnlfd = -1; // route netlink socket int tunfd = -1; // tun interface file handle. (network device) int udpfd[MAX_UDPFD + 1] = INIT_TABUDPFD; // array UDP file handle + 1 for lac udp int udplacfd = -1; // UDP LAC file handle @@ -78,8 +78,8 @@ int epollfd = -1; // event polling time_t basetime = 0; // base clock char hostname[MAXHOSTNAME] = ""; // 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 +int rtnlseqnum = 0; // route netlink sequence number +int min_initok_rtnlseqnum = 0; // minimun seq number for messages after init is ok static int syslog_log = 0; // are we logging to syslog 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 @@ -240,8 +240,9 @@ 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 ssize_t rtnetlink_send(struct nlmsghdr *nh); +static int netlink_handle_ack(struct nlmsghdr *nh, int min_initok_nlseqnum, char *tun_nl_phase_msg[]); +static void rtnetlink_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); @@ -497,20 +498,20 @@ static void routeset(sessionidt s, in_addr_t ip, int prefixlen, in_addr_t gw, in req.rt.rtm_scope = RT_SCOPE_LINK; req.rt.rtm_type = RTN_UNICAST; - netlink_addattr(&req.nh, RTA_OIF, &tunidx, sizeof(int)); + rtnetlink_addattr(&req.nh, RTA_OIF, &tunidx, sizeof(int)); n_ip = htonl(ip); - netlink_addattr(&req.nh, RTA_DST, &n_ip, sizeof(n_ip)); + rtnetlink_addattr(&req.nh, RTA_DST, &n_ip, sizeof(n_ip)); if (gw) { n_ip = htonl(gw); - netlink_addattr(&req.nh, RTA_GATEWAY, &n_ip, sizeof(n_ip)); + rtnetlink_addattr(&req.nh, RTA_GATEWAY, &n_ip, sizeof(n_ip)); } LOG(1, s, session[s].tunnel, "Route %s %s/%d%s%s\n", add ? "add" : "del", fmtaddr(htonl(ip), 0), prefixlen, gw ? " via" : "", gw ? fmtaddr(htonl(gw), 2) : ""); - if (netlink_send(&req.nh) < 0) + if (rtnetlink_send(&req.nh) < 0) LOG(0, 0, 0, "routeset() error in sending netlink message: %s\n", strerror(errno)); #ifdef BGP @@ -576,17 +577,17 @@ void route6set(sessionidt s, struct in6_addr ip, int prefixlen, int add) 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)); + rtnetlink_addattr(&req.nh, RTA_OIF, &tunidx, sizeof(int)); + rtnetlink_addattr(&req.nh, RTA_DST, &ip, sizeof(ip)); metric = 1; - netlink_addattr(&req.nh, RTA_METRICS, &metric, sizeof(metric)); + rtnetlink_addattr(&req.nh, RTA_METRICS, &metric, sizeof(metric)); LOG(1, s, session[s].tunnel, "Route %s %s/%d\n", add ? "add" : "del", inet_ntop(AF_INET6, &ip, ipv6addr, INET6_ADDRSTRLEN), prefixlen); - if (netlink_send(&req.nh) < 0) + if (rtnetlink_send(&req.nh) < 0) LOG(0, 0, 0, "route6set() error in sending netlink message: %s\n", strerror(errno)); #ifdef BGP @@ -613,10 +614,10 @@ static void initnetlink(void) { struct sockaddr_nl nladdr; - nlfd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE); - if (nlfd < 0) + rtnlfd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE); + if (rtnlfd < 0) { - LOG(0, 0, 0, "Can't create netlink socket: %s\n", strerror(errno)); + LOG(0, 0, 0, "Can't create route netlink socket: %s\n", strerror(errno)); exit(1); } @@ -624,21 +625,23 @@ static void initnetlink(void) nladdr.nl_family = AF_NETLINK; nladdr.nl_pid = getpid(); - if (bind(nlfd, (struct sockaddr *)&nladdr, sizeof(nladdr)) < 0) + if (bind(rtnlfd, (struct sockaddr *)&nladdr, sizeof(nladdr)) < 0) { - LOG(0, 0, 0, "Can't bind netlink socket: %s\n", strerror(errno)); + LOG(0, 0, 0, "Can't bind route netlink socket: %s\n", strerror(errno)); exit(1); } } -static ssize_t netlink_send(struct nlmsghdr *nh) +// +// Send message to a netlink socket +static ssize_t netlink_send(int fd, int *seqnum, struct nlmsghdr *nh) { struct sockaddr_nl nladdr; struct iovec iov; struct msghdr msg; nh->nlmsg_pid = getpid(); - nh->nlmsg_seq = ++nlseqnum; + nh->nlmsg_seq = ++*seqnum; // set kernel address memset(&nladdr, 0, sizeof(nladdr)); @@ -647,10 +650,19 @@ static ssize_t netlink_send(struct nlmsghdr *nh) 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); + return sendmsg(fd, &msg, 0); } -static ssize_t netlink_recv(void *buf, ssize_t len) +// +// Send message to the route netlink socket +static ssize_t rtnetlink_send(struct nlmsghdr *nh) +{ + return netlink_send(rtnlfd, &rtnlseqnum, nh); +} + +// +// Receive a message from a netlink socket +static ssize_t netlink_recv(int fd, void *buf, ssize_t len) { struct sockaddr_nl nladdr; struct iovec iov; @@ -663,11 +675,52 @@ static ssize_t netlink_recv(void *buf, ssize_t len) iov = (struct iovec){ buf, len }; msg = (struct msghdr){ (void *)&nladdr, sizeof(nladdr), &iov, 1, NULL, 0, 0 }; - return recvmsg(nlfd, &msg, 0); + return recvmsg(fd, &msg, 0); } +// +// Receive a message from the route netlink socket +static ssize_t rtnetlink_recv(void *buf, ssize_t len) +{ + return netlink_recv(rtnlfd, buf, len); +} + +// +// Look ack netlink message for errors +static int netlink_handle_ack(struct nlmsghdr *nh, int min_initok_nlseqnum, char *tun_nl_phase_msg[]) +{ + 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, "For netlink request %d, got a netlink error: %s\n", errmsg->msg.nlmsg_type, strerror(-errmsg->error)); + errno = -errmsg->error; + return -1; + } + } + // else it's an ack + return 0; + } + else + { + LOG(1, 0, 0, "Got an unknown netlink message: type %d seq %d flags %d\n", nh->nlmsg_type, nh->nlmsg_seq, nh->nlmsg_flags); + errno = EIO; + return -1; + } +} + +// +// Add an attribute to a message for a route netlink socket /* adapted from iproute2 */ -static void netlink_addattr(struct nlmsghdr *nh, int type, const void *data, int alen) +static void rtnetlink_addattr(struct nlmsghdr *nh, int type, const void *data, int alen) { int len = RTA_LENGTH(alen); struct rtattr *rta; @@ -680,7 +733,7 @@ static void netlink_addattr(struct nlmsghdr *nh, int type, const void *data, int } // messages corresponding to different phases seq number -static char *tun_nl_phase_msg[] = { +static char *tun_rtnl_phase_msg[] = { "initialized", "getting tun interface index", "setting tun interface parameters", @@ -753,12 +806,12 @@ static void inittun(void) /* Bump up the qlen to deal with bursts from the network */ txqlen = 1000; - netlink_addattr(&req.nh, IFLA_TXQLEN, &txqlen, sizeof(txqlen)); + rtnetlink_addattr(&req.nh, IFLA_TXQLEN, &txqlen, sizeof(txqlen)); /* set MTU to modem MRU */ mtu = MRU; - netlink_addattr(&req.nh, IFLA_MTU, &mtu, sizeof(mtu)); + rtnetlink_addattr(&req.nh, IFLA_MTU, &mtu, sizeof(mtu)); - if (netlink_send(&req.nh) < 0) + if (rtnetlink_send(&req.nh) < 0) goto senderror; memset(&req, 0, sizeof(req)); @@ -778,8 +831,8 @@ static void inittun(void) for (i = 0; i < config->nbmultiaddress ; i++) { ip = config->iftun_n_address[i]; - netlink_addattr(&req.nh, IFA_LOCAL, &ip, sizeof(ip)); - if (netlink_send(&req.nh) < 0) + rtnetlink_addattr(&req.nh, IFA_LOCAL, &ip, sizeof(ip)); + if (rtnetlink_send(&req.nh) < 0) goto senderror; } } @@ -789,9 +842,9 @@ static void inittun(void) ip = config->iftun_address; else ip = 0x01010101; // 1.1.1.1 - netlink_addattr(&req.nh, IFA_LOCAL, &ip, sizeof(ip)); + rtnetlink_addattr(&req.nh, IFA_LOCAL, &ip, sizeof(ip)); - if (netlink_send(&req.nh) < 0) + if (rtnetlink_send(&req.nh) < 0) goto senderror; } @@ -817,9 +870,9 @@ static void inittun(void) ip6.s6_addr[0] = 0xFE; ip6.s6_addr[1] = 0x80; ip6.s6_addr[15] = 1; - netlink_addattr(&req.nh, IFA_LOCAL, &ip6, sizeof(ip6)); + rtnetlink_addattr(&req.nh, IFA_LOCAL, &ip6, sizeof(ip6)); - if (netlink_send(&req.nh) < 0) + if (rtnetlink_send(&req.nh) < 0) goto senderror; memset(&req, 0, sizeof(req)); @@ -836,9 +889,9 @@ static void inittun(void) // Global address is prefix::1 ip6 = config->ipv6_prefix; ip6.s6_addr[15] = 1; - netlink_addattr(&req.nh, IFA_LOCAL, &ip6, sizeof(ip6)); + rtnetlink_addattr(&req.nh, IFA_LOCAL, &ip6, sizeof(ip6)); - if (netlink_send(&req.nh) < 0) + if (rtnetlink_send(&req.nh) < 0) goto senderror; } @@ -847,15 +900,15 @@ static void inittun(void) req.nh.nlmsg_type = NLMSG_DONE; req.nh.nlmsg_len = NLMSG_LENGTH(0); - if (netlink_send(&req.nh) < 0) + if (rtnetlink_send(&req.nh) < 0) goto senderror; // 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 + min_initok_rtnlseqnum = 5 + 1; // idx + if + addr + 2*addr6 else - min_initok_nlseqnum = 3 + 1; // idx + if + addr + min_initok_rtnlseqnum = 3 + 1; // idx + if + addr } return; @@ -4135,8 +4188,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, nlfd=%d , udplacfd=%d, pppoefd=%d, pppoesessfd=%d\n", - clifd, cluster_sockfd, tunfd, udpfd[0], controlfd, daefd, nlfd, udplacfd, pppoediscfd, pppoesessfd); + LOG(4, 0, 0, "Beginning of main loop. clifd=%d, cluster_sockfd=%d, tunfd=%d, udpfd=%d, controlfd=%d, daefd=%d, rtnlfd=%d , udplacfd=%d, pppoefd=%d, pppoesessfd=%d\n", + clifd, cluster_sockfd, tunfd, udpfd[0], controlfd, daefd, rtnlfd, udplacfd, pppoediscfd, pppoesessfd); /* setup our fds to poll for input */ { @@ -4169,9 +4222,9 @@ static void mainloop(void) e.data.ptr = &d[i++]; epoll_ctl(epollfd, EPOLL_CTL_ADD, daefd, &e); - d[i].type = FD_TYPE_NETLINK; + d[i].type = FD_TYPE_RTNETLINK; e.data.ptr = &d[i++]; - epoll_ctl(epollfd, EPOLL_CTL_ADD, nlfd, &e); + epoll_ctl(epollfd, EPOLL_CTL_ADD, rtnlfd, &e); d[i].type = FD_TYPE_PPPOEDISC; e.data.ptr = &d[i++]; @@ -4334,27 +4387,11 @@ static void mainloop(void) break; #endif /* BGP */ - case FD_TYPE_NETLINK: + case FD_TYPE_RTNETLINK: { struct nlmsghdr *nh = (struct nlmsghdr *)p; - s = netlink_recv(p, size_bufp); - 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); + s = rtnetlink_recv(p, size_bufp); + netlink_handle_ack(nh, min_initok_rtnlseqnum, tun_rtnl_phase_msg); n--; break; } diff --git a/l2tpns.h b/l2tpns.h index 6d815ff..aa0ef46 100644 --- a/l2tpns.h +++ b/l2tpns.h @@ -1037,7 +1037,7 @@ extern uint32_t last_id; extern struct Tstats *_statistics; extern in_addr_t my_address; extern int clifd; -extern int nlfd; +extern int rtnlfd; extern int epollfd; extern FILE *log_stream; @@ -1051,7 +1051,7 @@ struct event_data { FD_TYPE_DAE, FD_TYPE_RADIUS, FD_TYPE_BGP, - FD_TYPE_NETLINK, + FD_TYPE_RTNETLINK, FD_TYPE_PPPOEDISC, FD_TYPE_PPPOESESS } type; diff --git a/util.c b/util.c index c6a51c8..c9bc54e 100644 --- a/util.c +++ b/util.c @@ -120,7 +120,7 @@ pid_t fork_and_close() close(bgp_peers[i].sock); #endif /* BGP */ - if (nlfd != -1) close(nlfd); + if (rtnlfd != -1) close(rtnlfd); if (pppoediscfd != -1) close(pppoediscfd); if (pppoesessfd != -1) close(pppoesessfd);