2 * Copyright (C) 2017 Hans Dedecker <dedeckeh@gmail.com>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License v2 as published by
6 * the Free Software Foundation.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
19 #include <linux/netlink.h>
20 #include <linux/if_addr.h>
21 #include <linux/neighbour.h>
22 #include <linux/rtnetlink.h>
24 #include <netlink/msg.h>
25 #include <netlink/socket.h>
26 #include <netlink/attr.h>
28 #include <arpa/inet.h>
29 #include <libubox/list.h>
34 struct odhcpd_event ev;
39 static void handle_rtnl_event(struct odhcpd_event *ev);
40 static int cb_rtnl_valid(struct nl_msg *msg, void *arg);
41 static void catch_rtnl_err(struct odhcpd_event *e, int error);
42 static struct nl_sock *create_socket(int protocol);
44 static struct nl_sock *rtnl_socket = NULL;
45 struct list_head netevent_handler_list = LIST_HEAD_INIT(netevent_handler_list);
46 static struct event_socket rtnl_event = {
48 .uloop = {.fd = - 1, },
50 .handle_error = catch_rtnl_err,
51 .recv_msgs = handle_rtnl_event,
54 .sock_bufsize = 133120,
57 int netlink_init(void)
59 rtnl_socket = create_socket(NETLINK_ROUTE);
61 syslog(LOG_ERR, "Unable to open nl socket: %m");
65 rtnl_event.sock = create_socket(NETLINK_ROUTE);
66 if (!rtnl_event.sock) {
67 syslog(LOG_ERR, "Unable to open nl event socket: %m");
71 rtnl_event.ev.uloop.fd = nl_socket_get_fd(rtnl_event.sock);
73 if (nl_socket_set_buffer_size(rtnl_event.sock, rtnl_event.sock_bufsize, 0))
76 nl_socket_disable_seq_check(rtnl_event.sock);
78 nl_socket_modify_cb(rtnl_event.sock, NL_CB_VALID, NL_CB_CUSTOM,
81 /* Receive IPv4 address, IPv6 address, IPv6 routes and neighbor events */
82 if (nl_socket_add_memberships(rtnl_event.sock, RTNLGRP_IPV4_IFADDR,
83 RTNLGRP_IPV6_IFADDR, RTNLGRP_IPV6_ROUTE,
84 RTNLGRP_NEIGH, RTNLGRP_LINK, 0))
87 odhcpd_register(&rtnl_event.ev);
93 nl_socket_free(rtnl_socket);
97 if (rtnl_event.sock) {
98 nl_socket_free(rtnl_event.sock);
99 rtnl_event.sock = NULL;
100 rtnl_event.ev.uloop.fd = -1;
107 int netlink_add_netevent_handler(struct netevent_handler *handler)
112 list_add(&handler->head, &netevent_handler_list);
117 static void call_netevent_handler_list(unsigned long event, struct netevent_handler_info *info)
119 struct netevent_handler *handler;
121 list_for_each_entry(handler, &netevent_handler_list, head)
122 handler->cb(event, info);
125 static void handle_rtnl_event(struct odhcpd_event *e)
127 struct event_socket *ev_sock = container_of(e, struct event_socket, ev);
129 nl_recvmsgs_default(ev_sock->sock);
132 static void refresh_iface_addr4(struct netevent_handler_info *event_info)
134 struct odhcpd_ipaddr *addr = NULL;
135 struct interface *iface = event_info->iface;
136 ssize_t len = netlink_get_interface_addrs(iface->ifindex, false, &addr);
141 bool change = len != (ssize_t)iface->addr4_len;
142 for (ssize_t i = 0; !change && i < len; ++i)
143 if (addr[i].addr.in.s_addr != iface->addr4[i].addr.in.s_addr)
146 event_info->addrs_old.addrs = iface->addr4;
147 event_info->addrs_old.len = iface->addr4_len;
150 iface->addr4_len = len;
153 call_netevent_handler_list(NETEV_ADDRLIST_CHANGE, event_info);
155 free(event_info->addrs_old.addrs);
158 static void refresh_iface_addr6(struct netevent_handler_info *event_info)
160 struct odhcpd_ipaddr *addr = NULL;
161 struct interface *iface = event_info->iface;
162 ssize_t len = netlink_get_interface_addrs(iface->ifindex, true, &addr);
163 time_t now = odhcpd_time();
168 bool change = len != (ssize_t)iface->addr6_len;
169 for (ssize_t i = 0; !change && i < len; ++i)
170 if (!IN6_ARE_ADDR_EQUAL(&addr[i].addr.in6, &iface->addr6[i].addr.in6) ||
171 (addr[i].preferred > (uint32_t)now) != (iface->addr6[i].preferred > (uint32_t)now) ||
172 addr[i].valid < iface->addr6[i].valid ||
173 addr[i].preferred < iface->addr6[i].preferred)
176 event_info->addrs_old.addrs = iface->addr6;
177 event_info->addrs_old.len = iface->addr6_len;
180 iface->addr6_len = len;
183 call_netevent_handler_list(NETEV_ADDR6LIST_CHANGE, event_info);
185 free(event_info->addrs_old.addrs);
188 /* Handler for neighbor cache entries from the kernel. This is our source
189 * to learn and unlearn hosts on interfaces. */
190 static int cb_rtnl_valid(struct nl_msg *msg, _unused void *arg)
192 struct nlmsghdr *hdr = nlmsg_hdr(msg);
193 struct netevent_handler_info event_info;
195 char ipbuf[INET6_ADDRSTRLEN];
197 memset(&event_info, 0, sizeof(event_info));
198 switch (hdr->nlmsg_type) {
200 struct ifinfomsg *ifi = nlmsg_data(hdr);
201 struct nlattr *nla[__IFLA_MAX];
203 if (!nlmsg_valid_hdr(hdr, sizeof(*ifi)) ||
204 ifi->ifi_family != AF_UNSPEC)
207 nlmsg_parse(hdr, sizeof(*ifi), nla, __IFLA_MAX - 1, NULL);
208 if (!nla[IFLA_IFNAME])
211 event_info.iface = odhcpd_get_interface_by_name(nla_get_string(nla[IFLA_IFNAME]));
212 if (!event_info.iface)
215 if (event_info.iface->ifindex != ifi->ifi_index) {
216 event_info.iface->ifindex = ifi->ifi_index;
217 call_netevent_handler_list(NETEV_IFINDEX_CHANGE, &event_info);
226 struct rtmsg *rtm = nlmsg_data(hdr);
227 struct nlattr *nla[__RTA_MAX];
229 if (!nlmsg_valid_hdr(hdr, sizeof(*rtm)) ||
230 rtm->rtm_family != AF_INET6)
233 nlmsg_parse(hdr, sizeof(*rtm), nla, __RTA_MAX - 1, NULL);
235 event_info.rt.dst_len = rtm->rtm_dst_len;
237 nla_memcpy(&event_info.rt.dst, nla[RTA_DST],
238 sizeof(event_info.rt.dst));
241 event_info.iface = odhcpd_get_interface_by_index(nla_get_u32(nla[RTA_OIF]));
243 if (nla[RTA_GATEWAY])
244 nla_memcpy(&event_info.rt.gateway, nla[RTA_GATEWAY],
245 sizeof(event_info.rt.gateway));
247 call_netevent_handler_list(add ? NETEV_ROUTE6_ADD : NETEV_ROUTE6_DEL,
256 struct ifaddrmsg *ifa = nlmsg_data(hdr);
257 struct nlattr *nla[__IFA_MAX];
259 if (!nlmsg_valid_hdr(hdr, sizeof(*ifa)) ||
260 (ifa->ifa_family != AF_INET6 &&
261 ifa->ifa_family != AF_INET))
264 event_info.iface = odhcpd_get_interface_by_index(ifa->ifa_index);
265 if (!event_info.iface)
268 nlmsg_parse(hdr, sizeof(*ifa), nla, __IFA_MAX - 1, NULL);
270 if (ifa->ifa_family == AF_INET6) {
271 if (!nla[IFA_ADDRESS])
274 nla_memcpy(&event_info.addr, nla[IFA_ADDRESS], sizeof(event_info.addr));
276 if (IN6_IS_ADDR_LINKLOCAL(&event_info.addr) ||
277 IN6_IS_ADDR_MULTICAST(&event_info.addr))
280 inet_ntop(AF_INET6, &event_info.addr, ipbuf, sizeof(ipbuf));
281 syslog(LOG_DEBUG, "Netlink %s %s%%%s", add ? "newaddr" : "deladdr",
282 ipbuf, event_info.iface->ifname);
284 call_netevent_handler_list(add ? NETEV_ADDR6_ADD : NETEV_ADDR6_DEL,
287 refresh_iface_addr6(&event_info);
292 nla_memcpy(&event_info.addr, nla[IFA_LOCAL], sizeof(event_info.addr));
294 inet_ntop(AF_INET, &event_info.addr, ipbuf, sizeof(ipbuf));
295 syslog(LOG_DEBUG, "Netlink %s %s%%%s", add ? "newaddr" : "deladdr",
296 ipbuf, event_info.iface->ifname);
298 call_netevent_handler_list(add ? NETEV_ADDR_ADD : NETEV_ADDR_DEL,
301 refresh_iface_addr4(&event_info);
310 struct ndmsg *ndm = nlmsg_data(hdr);
311 struct nlattr *nla[__NDA_MAX];
313 if (!nlmsg_valid_hdr(hdr, sizeof(*ndm)) ||
314 ndm->ndm_family != AF_INET6)
317 event_info.iface = odhcpd_get_interface_by_index(ndm->ndm_ifindex);
318 if (!event_info.iface)
321 nlmsg_parse(hdr, sizeof(*ndm), nla, __NDA_MAX - 1, NULL);
325 nla_memcpy(&event_info.neigh.dst, nla[NDA_DST], sizeof(event_info.neigh.dst));
327 if (IN6_IS_ADDR_LINKLOCAL(&event_info.neigh.dst) ||
328 IN6_IS_ADDR_MULTICAST(&event_info.neigh.dst))
331 inet_ntop(AF_INET6, &event_info.neigh.dst, ipbuf, sizeof(ipbuf));
332 syslog(LOG_DEBUG, "Netlink %s %s%%%s", true ? "newneigh" : "delneigh",
333 ipbuf, event_info.iface->ifname);
335 event_info.neigh.state = ndm->ndm_state;
336 event_info.neigh.flags = ndm->ndm_flags;
338 call_netevent_handler_list(add ? NETEV_NEIGH6_ADD : NETEV_NEIGH6_DEL,
350 static void catch_rtnl_err(struct odhcpd_event *e, int error)
352 struct event_socket *ev_sock = container_of(e, struct event_socket, ev);
354 if (error != ENOBUFS)
357 /* Double netlink event buffer size */
358 ev_sock->sock_bufsize *= 2;
360 if (nl_socket_set_buffer_size(ev_sock->sock, ev_sock->sock_bufsize, 0))
363 netlink_dump_addr_table(true);
367 odhcpd_deregister(e);
370 static struct nl_sock *create_socket(int protocol)
372 struct nl_sock *nl_sock;
374 nl_sock = nl_socket_alloc();
378 if (nl_connect(nl_sock, protocol) < 0)
385 nl_socket_free(nl_sock);
394 struct odhcpd_ipaddr **addrs;
400 static int cb_valid_handler(struct nl_msg *msg, void *arg)
402 struct addr_info *ctxt = (struct addr_info *)arg;
403 struct odhcpd_ipaddr *addrs = *(ctxt->addrs);
404 struct nlmsghdr *hdr = nlmsg_hdr(msg);
405 struct ifaddrmsg *ifa;
406 struct nlattr *nla[__IFA_MAX], *nla_addr = NULL;
408 if (hdr->nlmsg_type != RTM_NEWADDR)
411 ifa = NLMSG_DATA(hdr);
412 if (ifa->ifa_scope != RT_SCOPE_UNIVERSE ||
413 (ctxt->af != ifa->ifa_family) ||
414 (ctxt->ifindex && ifa->ifa_index != (unsigned)ctxt->ifindex))
417 nlmsg_parse(hdr, sizeof(*ifa), nla, __IFA_MAX - 1, NULL);
419 switch (ifa->ifa_family) {
421 if (nla[IFA_ADDRESS])
422 nla_addr = nla[IFA_ADDRESS];
427 nla_addr = nla[IFA_LOCAL];
436 addrs = realloc(addrs, sizeof(*addrs)*(ctxt->ret + 1));
440 memset(&addrs[ctxt->ret], 0, sizeof(addrs[ctxt->ret]));
441 addrs[ctxt->ret].prefix = ifa->ifa_prefixlen;
443 nla_memcpy(&addrs[ctxt->ret].addr, nla_addr,
444 sizeof(addrs[ctxt->ret].addr));
446 if (nla[IFA_BROADCAST])
447 nla_memcpy(&addrs[ctxt->ret].broadcast, nla[IFA_BROADCAST],
448 sizeof(addrs[ctxt->ret].broadcast));
450 if (nla[IFA_CACHEINFO]) {
451 struct ifa_cacheinfo *ifc = nla_data(nla[IFA_CACHEINFO]);
453 addrs[ctxt->ret].preferred = ifc->ifa_prefered;
454 addrs[ctxt->ret].valid = ifc->ifa_valid;
457 if (ifa->ifa_flags & IFA_F_DEPRECATED)
458 addrs[ctxt->ret].preferred = 0;
461 *(ctxt->addrs) = addrs;
467 static int cb_finish_handler(_unused struct nl_msg *msg, void *arg)
469 struct addr_info *ctxt = (struct addr_info *)arg;
477 static int cb_error_handler(_unused struct sockaddr_nl *nla, struct nlmsgerr *err,
480 struct addr_info *ctxt = (struct addr_info *)arg;
483 ctxt->ret = err->error;
489 static int prefix_cmp(const void *va, const void *vb)
491 const struct odhcpd_ipaddr *a = va, *b = vb;
494 if (a->prefix == b->prefix) {
495 ret = (ntohl(a->addr.in.s_addr) < ntohl(b->addr.in.s_addr)) ? 1 :
496 (ntohl(a->addr.in.s_addr) > ntohl(b->addr.in.s_addr)) ? -1 : 0;
498 ret = a->prefix < b->prefix ? 1 : -1;
504 /* compare IPv6 prefixes */
505 static int prefix6_cmp(const void *va, const void *vb)
507 const struct odhcpd_ipaddr *a = va, *b = vb;
508 uint32_t a_pref = IN6_IS_ADDR_ULA(&a->addr.in6) ? 1 : a->preferred;
509 uint32_t b_pref = IN6_IS_ADDR_ULA(&b->addr.in6) ? 1 : b->preferred;
510 return (a_pref < b_pref) ? 1 : (a_pref > b_pref) ? -1 : 0;
514 /* Detect an IPV6-address currently assigned to the given interface */
515 ssize_t netlink_get_interface_addrs(int ifindex, bool v6, struct odhcpd_ipaddr **addrs)
518 struct ifaddrmsg ifa = {
519 .ifa_family = v6? AF_INET6: AF_INET,
523 .ifa_index = ifindex, };
524 struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT);
525 struct addr_info ctxt = {
527 .af = v6? AF_INET6: AF_INET,
538 msg = nlmsg_alloc_simple(RTM_GETADDR, NLM_F_REQUEST | NLM_F_DUMP);
545 nlmsg_append(msg, &ifa, sizeof(ifa), 0);
547 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, cb_valid_handler, &ctxt);
548 nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, cb_finish_handler, &ctxt);
549 nl_cb_err(cb, NL_CB_CUSTOM, cb_error_handler, &ctxt);
551 nl_send_auto_complete(rtnl_socket, msg);
552 while (ctxt.pending > 0)
553 nl_recvmsgs(rtnl_socket, cb);
560 time_t now = odhcpd_time();
561 struct odhcpd_ipaddr *addr = *addrs;
563 qsort(addr, ctxt.ret, sizeof(*addr), v6 ? prefix6_cmp : prefix_cmp);
565 for (ssize_t i = 0; i < ctxt.ret; ++i) {
566 if (addr[i].preferred < UINT32_MAX - now)
567 addr[i].preferred += now;
569 if (addr[i].valid < UINT32_MAX - now)
570 addr[i].valid += now;
580 int netlink_setup_route(const struct in6_addr *addr, const int prefixlen,
581 const int ifindex, const struct in6_addr *gw,
582 const uint32_t metric, const bool add)
586 .rtm_family = AF_INET6,
587 .rtm_dst_len = prefixlen,
589 .rtm_table = RT_TABLE_MAIN,
590 .rtm_protocol = (add ? RTPROT_STATIC : RTPROT_UNSPEC),
591 .rtm_scope = (add ? (gw ? RT_SCOPE_UNIVERSE : RT_SCOPE_LINK) : RT_SCOPE_NOWHERE),
592 .rtm_type = (add ? RTN_UNICAST : RTN_UNSPEC),
596 msg = nlmsg_alloc_simple(add ? RTM_NEWROUTE : RTM_DELROUTE,
597 add ? NLM_F_CREATE | NLM_F_REPLACE : 0);
601 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
603 nla_put(msg, RTA_DST, sizeof(*addr), addr);
604 nla_put_u32(msg, RTA_OIF, ifindex);
605 nla_put_u32(msg, RTA_PRIORITY, metric);
608 nla_put(msg, RTA_GATEWAY, sizeof(*gw), gw);
610 ret = nl_send_auto_complete(rtnl_socket, msg);
616 return nl_wait_for_ack(rtnl_socket);
620 int netlink_setup_proxy_neigh(const struct in6_addr *addr,
621 const int ifindex, const bool add)
625 .ndm_family = AF_INET6,
626 .ndm_flags = NTF_PROXY,
627 .ndm_ifindex = ifindex,
629 int ret = 0, flags = NLM_F_REQUEST;
632 flags |= NLM_F_REPLACE | NLM_F_CREATE;
634 msg = nlmsg_alloc_simple(add ? RTM_NEWNEIGH : RTM_DELNEIGH, flags);
638 nlmsg_append(msg, &ndm, sizeof(ndm), 0);
640 nla_put(msg, NDA_DST, sizeof(*addr), addr);
642 ret = nl_send_auto_complete(rtnl_socket, msg);
648 return nl_wait_for_ack(rtnl_socket);
652 int netlink_setup_addr(struct odhcpd_ipaddr *addr,
653 const int ifindex, const bool v6, const bool add)
656 struct ifaddrmsg ifa = {
657 .ifa_family = v6 ? AF_INET6 : AF_INET,
658 .ifa_prefixlen = addr->prefix,
661 .ifa_index = ifindex, };
662 int ret = 0, flags = NLM_F_REQUEST;
665 flags |= NLM_F_REPLACE | NLM_F_CREATE;
667 msg = nlmsg_alloc_simple(add ? RTM_NEWADDR : RTM_DELADDR, 0);
671 nlmsg_append(msg, &ifa, sizeof(ifa), flags);
672 nla_put(msg, IFA_LOCAL, v6 ? 16 : 4, &addr->addr);
674 struct ifa_cacheinfo cinfo = { .ifa_prefered = 0xffffffffU,
675 .ifa_valid = 0xffffffffU,
678 time_t now = odhcpd_time();
680 if (addr->preferred) {
681 int64_t preferred = addr->preferred - now;
684 else if (preferred > UINT32_MAX)
685 preferred = UINT32_MAX;
687 cinfo.ifa_prefered = preferred;
691 int64_t valid = addr->valid - now;
696 else if (valid > UINT32_MAX)
699 cinfo.ifa_valid = valid;
702 nla_put(msg, IFA_CACHEINFO, sizeof(cinfo), &cinfo);
704 nla_put_u32(msg, IFA_FLAGS, IFA_F_NOPREFIXROUTE);
706 if (addr->broadcast.s_addr)
707 nla_put_u32(msg, IFA_BROADCAST, addr->broadcast.s_addr);
710 ret = nl_send_auto_complete(rtnl_socket, msg);
716 return nl_wait_for_ack(rtnl_socket);
719 void netlink_dump_neigh_table(const bool proxy)
723 .ndm_family = AF_INET6,
724 .ndm_flags = proxy ? NTF_PROXY : 0,
727 msg = nlmsg_alloc_simple(RTM_GETNEIGH, NLM_F_REQUEST | NLM_F_DUMP);
731 nlmsg_append(msg, &ndm, sizeof(ndm), 0);
733 nl_send_auto_complete(rtnl_event.sock, msg);
738 void netlink_dump_addr_table(const bool v6)
741 struct ifaddrmsg ifa = {
742 .ifa_family = v6 ? AF_INET6 : AF_INET,
745 msg = nlmsg_alloc_simple(RTM_GETADDR, NLM_F_REQUEST | NLM_F_DUMP);
749 nlmsg_append(msg, &ifa, sizeof(ifa), 0);
751 nl_send_auto_complete(rtnl_event.sock, msg);