config: set RFC defaults for preferred lifetime
[project/odhcpd.git] / src / netlink.c
1 /**
2 * Copyright (C) 2017 Hans Dedecker <dedeckeh@gmail.com>
3 *
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.
7 *
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.
12 *
13 */
14
15 #include <errno.h>
16 #include <string.h>
17 #include <syslog.h>
18
19 #include <linux/netlink.h>
20 #include <linux/if_addr.h>
21 #include <linux/neighbour.h>
22 #include <linux/rtnetlink.h>
23
24 #include <netlink/msg.h>
25 #include <netlink/socket.h>
26 #include <netlink/attr.h>
27
28 #include <arpa/inet.h>
29 #include <libubox/list.h>
30
31 #include "odhcpd.h"
32
33 struct event_socket {
34 struct odhcpd_event ev;
35 struct nl_sock *sock;
36 int sock_bufsize;
37 };
38
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);
43
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 = {
47 .ev = {
48 .uloop = {.fd = - 1, },
49 .handle_dgram = NULL,
50 .handle_error = catch_rtnl_err,
51 .recv_msgs = handle_rtnl_event,
52 },
53 .sock = NULL,
54 .sock_bufsize = 133120,
55 };
56
57 int netlink_init(void)
58 {
59 rtnl_socket = create_socket(NETLINK_ROUTE);
60 if (!rtnl_socket) {
61 syslog(LOG_ERR, "Unable to open nl socket: %m");
62 goto err;
63 }
64
65 rtnl_event.sock = create_socket(NETLINK_ROUTE);
66 if (!rtnl_event.sock) {
67 syslog(LOG_ERR, "Unable to open nl event socket: %m");
68 goto err;
69 }
70
71 rtnl_event.ev.uloop.fd = nl_socket_get_fd(rtnl_event.sock);
72
73 if (nl_socket_set_buffer_size(rtnl_event.sock, rtnl_event.sock_bufsize, 0))
74 goto err;
75
76 nl_socket_disable_seq_check(rtnl_event.sock);
77
78 nl_socket_modify_cb(rtnl_event.sock, NL_CB_VALID, NL_CB_CUSTOM,
79 cb_rtnl_valid, NULL);
80
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))
85 goto err;
86
87 odhcpd_register(&rtnl_event.ev);
88
89 return 0;
90
91 err:
92 if (rtnl_socket) {
93 nl_socket_free(rtnl_socket);
94 rtnl_socket = NULL;
95 }
96
97 if (rtnl_event.sock) {
98 nl_socket_free(rtnl_event.sock);
99 rtnl_event.sock = NULL;
100 rtnl_event.ev.uloop.fd = -1;
101 }
102
103 return -1;
104 }
105
106
107 int netlink_add_netevent_handler(struct netevent_handler *handler)
108 {
109 if (!handler->cb)
110 return -1;
111
112 list_add(&handler->head, &netevent_handler_list);
113
114 return 0;
115 }
116
117 static void call_netevent_handler_list(unsigned long event, struct netevent_handler_info *info)
118 {
119 struct netevent_handler *handler;
120
121 list_for_each_entry(handler, &netevent_handler_list, head)
122 handler->cb(event, info);
123 }
124
125 static void handle_rtnl_event(struct odhcpd_event *e)
126 {
127 struct event_socket *ev_sock = container_of(e, struct event_socket, ev);
128
129 nl_recvmsgs_default(ev_sock->sock);
130 }
131
132 static void refresh_iface_addr4(int ifindex)
133 {
134 struct odhcpd_ipaddr *addr = NULL;
135 struct interface *iface;
136 ssize_t len = netlink_get_interface_addrs(ifindex, false, &addr);
137 bool change = false;
138
139 if (len < 0)
140 return;
141
142 avl_for_each_element(&interfaces, iface, avl) {
143 struct netevent_handler_info event_info;
144
145 if (iface->ifindex != ifindex)
146 continue;
147
148 memset(&event_info, 0, sizeof(event_info));
149 event_info.iface = iface;
150 event_info.addrs_old.addrs = iface->addr4;
151 event_info.addrs_old.len = iface->addr4_len;
152
153 if (!change) {
154 change = len != (ssize_t)iface->addr4_len;
155 for (ssize_t i = 0; !change && i < len; ++i) {
156 if (addr[i].addr.in.s_addr != iface->addr4[i].addr.in.s_addr)
157 change = true;
158 }
159 }
160
161 iface->addr4 = addr;
162 iface->addr4_len = len;
163
164 if (change)
165 call_netevent_handler_list(NETEV_ADDRLIST_CHANGE, &event_info);
166
167 free(event_info.addrs_old.addrs);
168
169 if (!len)
170 continue;
171
172 addr = malloc(len * sizeof(*addr));
173 if (!addr)
174 break;
175
176 memcpy(addr, iface->addr4, len * sizeof(*addr));
177 }
178
179 free(addr);
180 }
181
182 static void refresh_iface_addr6(int ifindex)
183 {
184 struct odhcpd_ipaddr *addr = NULL;
185 struct interface *iface;
186 ssize_t len = netlink_get_interface_addrs(ifindex, true, &addr);
187 time_t now = odhcpd_time();
188 bool change = false;
189
190 if (len < 0)
191 return;
192
193 avl_for_each_element(&interfaces, iface, avl) {
194 struct netevent_handler_info event_info;
195
196 if (iface->ifindex != ifindex)
197 continue;
198
199 memset(&event_info, 0, sizeof(event_info));
200 event_info.iface = iface;
201 event_info.addrs_old.addrs = iface->addr6;
202 event_info.addrs_old.len = iface->addr6_len;
203
204 if (!change) {
205 change = len != (ssize_t)iface->addr6_len;
206 for (ssize_t i = 0; !change && i < len; ++i) {
207 if (!IN6_ARE_ADDR_EQUAL(&addr[i].addr.in6, &iface->addr6[i].addr.in6) ||
208 addr[i].prefix != iface->addr6[i].prefix ||
209 (addr[i].preferred > (uint32_t)now) != (iface->addr6[i].preferred > (uint32_t)now) ||
210 addr[i].valid < iface->addr6[i].valid || addr[i].preferred < iface->addr6[i].preferred)
211 change = true;
212 }
213
214 if (change) {
215 /*
216 * Keep track on removed prefixes, so we could advertise them as invalid
217 * for at least a couple of times.
218 *
219 * RFC7084 ยง 4.3 :
220 * L-13: If the delegated prefix changes, i.e., the current prefix is
221 * replaced with a new prefix without any overlapping time
222 * period, then the IPv6 CE router MUST immediately advertise the
223 * old prefix with a Preferred Lifetime of zero and a Valid
224 * Lifetime of either a) zero or b) the lower of the current
225 * Valid Lifetime and two hours (which must be decremented in
226 * real time) in a Router Advertisement message as described in
227 * Section 5.5.3, (e) of [RFC4862].
228 */
229
230 for (size_t i = 0; i < iface->addr6_len; ++i) {
231 bool removed = true;
232
233 if (iface->addr6[i].valid <= (uint32_t)now)
234 continue;
235
236 for (ssize_t j = 0; removed && j < len; ++j) {
237 size_t plen = min(addr[j].prefix, iface->addr6[i].prefix);
238
239 if (odhcpd_bmemcmp(&addr[j].addr.in6, &iface->addr6[i].addr.in6, plen) == 0)
240 removed = false;
241 }
242
243 for (size_t j = 0; removed && j < iface->invalid_addr6_len; ++j) {
244 size_t plen = min(iface->invalid_addr6[j].prefix, iface->addr6[i].prefix);
245
246 if (odhcpd_bmemcmp(&iface->invalid_addr6[j].addr.in6, &iface->addr6[i].addr.in6, plen) == 0)
247 removed = false;
248 }
249
250 if (removed) {
251 size_t pos = iface->invalid_addr6_len;
252 struct odhcpd_ipaddr *new_invalid_addr6 = realloc(iface->invalid_addr6,
253 sizeof(*iface->invalid_addr6) * (pos + 1));
254
255 if (!new_invalid_addr6)
256 break;
257
258 iface->invalid_addr6 = new_invalid_addr6;
259 iface->invalid_addr6_len++;
260 memcpy(&iface->invalid_addr6[pos], &iface->addr6[i], sizeof(*iface->invalid_addr6));
261 iface->invalid_addr6[pos].valid = iface->invalid_addr6[pos].preferred = (uint32_t)now;
262
263 if (iface->invalid_addr6[pos].prefix < 64)
264 iface->invalid_addr6[pos].prefix = 64;
265 }
266 }
267 }
268 }
269
270 iface->addr6 = addr;
271 iface->addr6_len = len;
272
273 if (change)
274 call_netevent_handler_list(NETEV_ADDR6LIST_CHANGE, &event_info);
275
276 free(event_info.addrs_old.addrs);
277
278 if (!len)
279 continue;
280
281 addr = malloc(len * sizeof(*addr));
282 if (!addr)
283 break;
284
285 memcpy(addr, iface->addr6, len * sizeof(*addr));
286 }
287
288 free(addr);
289 }
290
291 static int handle_rtm_link(struct nlmsghdr *hdr)
292 {
293 struct ifinfomsg *ifi = nlmsg_data(hdr);
294 struct nlattr *nla[__IFLA_MAX];
295 struct interface *iface;
296 struct netevent_handler_info event_info;
297 const char *ifname;
298
299 memset(&event_info, 0, sizeof(event_info));
300
301 if (!nlmsg_valid_hdr(hdr, sizeof(*ifi)) || ifi->ifi_family != AF_UNSPEC)
302 return NL_SKIP;
303
304 nlmsg_parse(hdr, sizeof(*ifi), nla, __IFLA_MAX - 1, NULL);
305 if (!nla[IFLA_IFNAME])
306 return NL_SKIP;
307
308 ifname = nla_get_string(nla[IFLA_IFNAME]);
309
310 avl_for_each_element(&interfaces, iface, avl) {
311 if (strcmp(iface->ifname, ifname))
312 continue;
313
314 iface->ifflags = ifi->ifi_flags;
315
316 /*
317 * Assume for link event of the same index, that link changed
318 * and reload services to enable or disable them based on the
319 * RUNNING state of the interface.
320 */
321 if (iface->ifindex == ifi->ifi_index) {
322 reload_services(iface);
323 continue;
324 }
325
326 iface->ifindex = ifi->ifi_index;
327 event_info.iface = iface;
328 call_netevent_handler_list(NETEV_IFINDEX_CHANGE, &event_info);
329 }
330
331 return NL_OK;
332 }
333
334 static int handle_rtm_route(struct nlmsghdr *hdr, bool add)
335 {
336 struct rtmsg *rtm = nlmsg_data(hdr);
337 struct nlattr *nla[__RTA_MAX];
338 struct interface *iface;
339 struct netevent_handler_info event_info;
340 int ifindex = 0;
341
342 if (!nlmsg_valid_hdr(hdr, sizeof(*rtm)) || rtm->rtm_family != AF_INET6)
343 return NL_SKIP;
344
345 nlmsg_parse(hdr, sizeof(*rtm), nla, __RTA_MAX - 1, NULL);
346
347 memset(&event_info, 0, sizeof(event_info));
348 event_info.rt.dst_len = rtm->rtm_dst_len;
349
350 if (nla[RTA_DST])
351 nla_memcpy(&event_info.rt.dst, nla[RTA_DST],
352 sizeof(event_info.rt.dst));
353
354 if (nla[RTA_OIF])
355 ifindex = nla_get_u32(nla[RTA_OIF]);
356
357 if (nla[RTA_GATEWAY])
358 nla_memcpy(&event_info.rt.gateway, nla[RTA_GATEWAY],
359 sizeof(event_info.rt.gateway));
360
361 avl_for_each_element(&interfaces, iface, avl) {
362 if (ifindex && iface->ifindex != ifindex)
363 continue;
364
365 event_info.iface = ifindex ? iface : NULL;
366 call_netevent_handler_list(add ? NETEV_ROUTE6_ADD : NETEV_ROUTE6_DEL,
367 &event_info);
368 }
369
370 return NL_OK;
371 }
372
373 static int handle_rtm_addr(struct nlmsghdr *hdr, bool add)
374 {
375 struct ifaddrmsg *ifa = nlmsg_data(hdr);
376 struct nlattr *nla[__IFA_MAX];
377 struct interface *iface;
378 struct netevent_handler_info event_info;
379 char buf[INET6_ADDRSTRLEN];
380
381 if (!nlmsg_valid_hdr(hdr, sizeof(*ifa)) ||
382 (ifa->ifa_family != AF_INET6 &&
383 ifa->ifa_family != AF_INET))
384 return NL_SKIP;
385
386 memset(&event_info, 0, sizeof(event_info));
387
388 nlmsg_parse(hdr, sizeof(*ifa), nla, __IFA_MAX - 1, NULL);
389
390 if (ifa->ifa_family == AF_INET6) {
391 if (!nla[IFA_ADDRESS])
392 return NL_SKIP;
393
394 nla_memcpy(&event_info.addr, nla[IFA_ADDRESS], sizeof(event_info.addr));
395
396 if (IN6_IS_ADDR_MULTICAST(&event_info.addr))
397 return NL_SKIP;
398
399 inet_ntop(AF_INET6, &event_info.addr, buf, sizeof(buf));
400
401 avl_for_each_element(&interfaces, iface, avl) {
402 if (iface->ifindex != (int)ifa->ifa_index)
403 continue;
404
405 if (add && IN6_IS_ADDR_LINKLOCAL(&event_info.addr)) {
406 iface->have_link_local = true;
407 return NL_SKIP;
408 }
409
410 syslog(LOG_DEBUG, "Netlink %s %s on %s", add ? "newaddr" : "deladdr",
411 buf, iface->name);
412
413 event_info.iface = iface;
414 call_netevent_handler_list(add ? NETEV_ADDR6_ADD : NETEV_ADDR6_DEL,
415 &event_info);
416 }
417
418 refresh_iface_addr6(ifa->ifa_index);
419 } else {
420 if (!nla[IFA_LOCAL])
421 return NL_SKIP;
422
423 nla_memcpy(&event_info.addr, nla[IFA_LOCAL], sizeof(event_info.addr));
424
425 inet_ntop(AF_INET, &event_info.addr, buf, sizeof(buf));
426
427 avl_for_each_element(&interfaces, iface, avl) {
428 if (iface->ifindex != (int)ifa->ifa_index)
429 continue;
430
431 syslog(LOG_DEBUG, "Netlink %s %s on %s", add ? "newaddr" : "deladdr",
432 buf, iface->name);
433
434 event_info.iface = iface;
435 call_netevent_handler_list(add ? NETEV_ADDR_ADD : NETEV_ADDR_DEL,
436 &event_info);
437 }
438
439 refresh_iface_addr4(ifa->ifa_index);
440 }
441
442 return NL_OK;
443 }
444
445 static int handle_rtm_neigh(struct nlmsghdr *hdr, bool add)
446 {
447 struct ndmsg *ndm = nlmsg_data(hdr);
448 struct nlattr *nla[__NDA_MAX];
449 struct interface *iface;
450 struct netevent_handler_info event_info;
451 char buf[INET6_ADDRSTRLEN];
452
453 if (!nlmsg_valid_hdr(hdr, sizeof(*ndm)) ||
454 ndm->ndm_family != AF_INET6)
455 return NL_SKIP;
456
457 nlmsg_parse(hdr, sizeof(*ndm), nla, __NDA_MAX - 1, NULL);
458 if (!nla[NDA_DST])
459 return NL_SKIP;
460
461 memset(&event_info, 0, sizeof(event_info));
462
463 nla_memcpy(&event_info.neigh.dst, nla[NDA_DST], sizeof(event_info.neigh.dst));
464
465 if (IN6_IS_ADDR_LINKLOCAL(&event_info.neigh.dst) ||
466 IN6_IS_ADDR_MULTICAST(&event_info.neigh.dst))
467 return NL_SKIP;
468
469 inet_ntop(AF_INET6, &event_info.neigh.dst, buf, sizeof(buf));
470
471 avl_for_each_element(&interfaces, iface, avl) {
472 if (iface->ifindex != ndm->ndm_ifindex)
473 continue;
474
475 syslog(LOG_DEBUG, "Netlink %s %s on %s", true ? "newneigh" : "delneigh",
476 buf, iface->name);
477
478 event_info.iface = iface;
479 event_info.neigh.state = ndm->ndm_state;
480 event_info.neigh.flags = ndm->ndm_flags;
481
482 call_netevent_handler_list(add ? NETEV_NEIGH6_ADD : NETEV_NEIGH6_DEL,
483 &event_info);
484 }
485
486 return NL_OK;
487 }
488
489 /* Handler for neighbor cache entries from the kernel. This is our source
490 * to learn and unlearn hosts on interfaces. */
491 static int cb_rtnl_valid(struct nl_msg *msg, _unused void *arg)
492 {
493 struct nlmsghdr *hdr = nlmsg_hdr(msg);
494 int ret = NL_SKIP;
495 bool add = false;
496
497 switch (hdr->nlmsg_type) {
498 case RTM_NEWLINK:
499 ret = handle_rtm_link(hdr);
500 break;
501
502 case RTM_NEWROUTE:
503 add = true;
504 /* fall through */
505 case RTM_DELROUTE:
506 ret = handle_rtm_route(hdr, add);
507 break;
508
509 case RTM_NEWADDR:
510 add = true;
511 /* fall through */
512 case RTM_DELADDR:
513 ret = handle_rtm_addr(hdr, add);
514 break;
515
516 case RTM_NEWNEIGH:
517 add = true;
518 /* fall through */
519 case RTM_DELNEIGH:
520 ret = handle_rtm_neigh(hdr, add);
521 break;
522
523 default:
524 break;
525 }
526
527 return ret;
528 }
529
530 static void catch_rtnl_err(struct odhcpd_event *e, int error)
531 {
532 struct event_socket *ev_sock = container_of(e, struct event_socket, ev);
533
534 if (error != ENOBUFS)
535 goto err;
536
537 /* Double netlink event buffer size */
538 ev_sock->sock_bufsize *= 2;
539
540 if (nl_socket_set_buffer_size(ev_sock->sock, ev_sock->sock_bufsize, 0))
541 goto err;
542
543 netlink_dump_addr_table(true);
544 return;
545
546 err:
547 odhcpd_deregister(e);
548 }
549
550 static struct nl_sock *create_socket(int protocol)
551 {
552 struct nl_sock *nl_sock;
553
554 nl_sock = nl_socket_alloc();
555 if (!nl_sock)
556 goto err;
557
558 if (nl_connect(nl_sock, protocol) < 0)
559 goto err;
560
561 return nl_sock;
562
563 err:
564 if (nl_sock)
565 nl_socket_free(nl_sock);
566
567 return NULL;
568 }
569
570
571 struct addr_info {
572 int ifindex;
573 int af;
574 struct odhcpd_ipaddr **addrs;
575 int pending;
576 ssize_t ret;
577 };
578
579
580 static int cb_addr_valid(struct nl_msg *msg, void *arg)
581 {
582 struct addr_info *ctxt = (struct addr_info *)arg;
583 struct odhcpd_ipaddr *addrs = *(ctxt->addrs);
584 struct nlmsghdr *hdr = nlmsg_hdr(msg);
585 struct ifaddrmsg *ifa;
586 struct nlattr *nla[__IFA_MAX], *nla_addr = NULL;
587
588 if (hdr->nlmsg_type != RTM_NEWADDR)
589 return NL_SKIP;
590
591 ifa = NLMSG_DATA(hdr);
592 if (ifa->ifa_scope != RT_SCOPE_UNIVERSE ||
593 (ctxt->af != ifa->ifa_family) ||
594 (ctxt->ifindex && ifa->ifa_index != (unsigned)ctxt->ifindex))
595 return NL_SKIP;
596
597 nlmsg_parse(hdr, sizeof(*ifa), nla, __IFA_MAX - 1, NULL);
598
599 switch (ifa->ifa_family) {
600 case AF_INET6:
601 if (nla[IFA_ADDRESS])
602 nla_addr = nla[IFA_ADDRESS];
603 break;
604
605 case AF_INET:
606 if (nla[IFA_LOCAL])
607 nla_addr = nla[IFA_LOCAL];
608 break;
609
610 default:
611 break;
612 }
613 if (!nla_addr)
614 return NL_SKIP;
615
616 addrs = realloc(addrs, sizeof(*addrs)*(ctxt->ret + 1));
617 if (!addrs)
618 return NL_SKIP;
619
620 memset(&addrs[ctxt->ret], 0, sizeof(addrs[ctxt->ret]));
621 addrs[ctxt->ret].prefix = ifa->ifa_prefixlen;
622
623 nla_memcpy(&addrs[ctxt->ret].addr, nla_addr,
624 sizeof(addrs[ctxt->ret].addr));
625
626 if (nla[IFA_BROADCAST])
627 nla_memcpy(&addrs[ctxt->ret].broadcast, nla[IFA_BROADCAST],
628 sizeof(addrs[ctxt->ret].broadcast));
629
630 if (nla[IFA_CACHEINFO]) {
631 struct ifa_cacheinfo *ifc = nla_data(nla[IFA_CACHEINFO]);
632
633 addrs[ctxt->ret].preferred = ifc->ifa_prefered;
634 addrs[ctxt->ret].valid = ifc->ifa_valid;
635 }
636
637 if (ifa->ifa_flags & IFA_F_DEPRECATED)
638 addrs[ctxt->ret].preferred = 0;
639
640 if (ifa->ifa_family == AF_INET6 &&
641 ifa->ifa_flags & IFA_F_TENTATIVE)
642 addrs[ctxt->ret].tentative = true;
643
644 ctxt->ret++;
645 *(ctxt->addrs) = addrs;
646
647 return NL_OK;
648 }
649
650
651 static int cb_addr_finish(_unused struct nl_msg *msg, void *arg)
652 {
653 struct addr_info *ctxt = (struct addr_info *)arg;
654
655 ctxt->pending = 0;
656
657 return NL_STOP;
658 }
659
660
661 static int cb_addr_error(_unused struct sockaddr_nl *nla, struct nlmsgerr *err,
662 void *arg)
663 {
664 struct addr_info *ctxt = (struct addr_info *)arg;
665
666 ctxt->pending = 0;
667 ctxt->ret = err->error;
668
669 return NL_STOP;
670 }
671
672
673 static int prefix_cmp(const void *va, const void *vb)
674 {
675 const struct odhcpd_ipaddr *a = va, *b = vb;
676 int ret = 0;
677
678 if (a->prefix == b->prefix) {
679 ret = (ntohl(a->addr.in.s_addr) < ntohl(b->addr.in.s_addr)) ? 1 :
680 (ntohl(a->addr.in.s_addr) > ntohl(b->addr.in.s_addr)) ? -1 : 0;
681 } else
682 ret = a->prefix < b->prefix ? 1 : -1;
683
684 return ret;
685 }
686
687
688 /* compare IPv6 prefixes */
689 static int prefix6_cmp(const void *va, const void *vb)
690 {
691 const struct odhcpd_ipaddr *a = va, *b = vb;
692 uint32_t a_pref = IN6_IS_ADDR_ULA(&a->addr.in6) ? 1 : a->preferred;
693 uint32_t b_pref = IN6_IS_ADDR_ULA(&b->addr.in6) ? 1 : b->preferred;
694 return (a_pref < b_pref) ? 1 : (a_pref > b_pref) ? -1 : 0;
695 }
696
697
698 /* Detect an IPV6-address currently assigned to the given interface */
699 ssize_t netlink_get_interface_addrs(int ifindex, bool v6, struct odhcpd_ipaddr **addrs)
700 {
701 struct nl_msg *msg;
702 struct ifaddrmsg ifa = {
703 .ifa_family = v6? AF_INET6: AF_INET,
704 .ifa_prefixlen = 0,
705 .ifa_flags = 0,
706 .ifa_scope = 0,
707 .ifa_index = ifindex, };
708 struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT);
709 struct addr_info ctxt = {
710 .ifindex = ifindex,
711 .af = v6? AF_INET6: AF_INET,
712 .addrs = addrs,
713 .ret = 0,
714 .pending = 1,
715 };
716
717 if (!cb) {
718 ctxt.ret = -1;
719 goto out;
720 }
721
722 msg = nlmsg_alloc_simple(RTM_GETADDR, NLM_F_REQUEST | NLM_F_DUMP);
723
724 if (!msg) {
725 ctxt.ret = - 1;
726 goto out;
727 }
728
729 nlmsg_append(msg, &ifa, sizeof(ifa), 0);
730
731 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, cb_addr_valid, &ctxt);
732 nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, cb_addr_finish, &ctxt);
733 nl_cb_err(cb, NL_CB_CUSTOM, cb_addr_error, &ctxt);
734
735 ctxt.ret = nl_send_auto_complete(rtnl_socket, msg);
736 if (ctxt.ret < 0)
737 goto free;
738
739 ctxt.ret = 0;
740 while (ctxt.pending > 0)
741 nl_recvmsgs(rtnl_socket, cb);
742
743 if (ctxt.ret <= 0)
744 goto free;
745
746 time_t now = odhcpd_time();
747 struct odhcpd_ipaddr *addr = *addrs;
748
749 qsort(addr, ctxt.ret, sizeof(*addr), v6 ? prefix6_cmp : prefix_cmp);
750
751 for (ssize_t i = 0; i < ctxt.ret; ++i) {
752 if (addr[i].preferred < UINT32_MAX - now)
753 addr[i].preferred += now;
754
755 if (addr[i].valid < UINT32_MAX - now)
756 addr[i].valid += now;
757 }
758
759 free:
760 nlmsg_free(msg);
761 out:
762 nl_cb_put(cb);
763
764 return ctxt.ret;
765 }
766
767
768 static int cb_linklocal_valid(struct nl_msg *msg, void *arg)
769 {
770 struct addr_info *ctxt = (struct addr_info *)arg;
771 struct odhcpd_ipaddr *addrs = *(ctxt->addrs);
772 struct nlmsghdr *hdr = nlmsg_hdr(msg);
773 struct ifaddrmsg *ifa;
774 struct nlattr *nla[__IFA_MAX], *nla_addr = NULL;
775 struct in6_addr addr;
776
777 if (hdr->nlmsg_type != RTM_NEWADDR)
778 return NL_SKIP;
779
780 ifa = NLMSG_DATA(hdr);
781 if (ifa->ifa_scope != RT_SCOPE_LINK ||
782 (ctxt->af != ifa->ifa_family) ||
783 (ctxt->ifindex && ifa->ifa_index != (unsigned)ctxt->ifindex))
784 return NL_SKIP;
785
786 nlmsg_parse(hdr, sizeof(*ifa), nla, __IFA_MAX - 1, NULL);
787
788 switch (ifa->ifa_family) {
789 case AF_INET6:
790 if (nla[IFA_ADDRESS])
791 nla_addr = nla[IFA_ADDRESS];
792 break;
793
794 default:
795 break;
796 }
797 if (!nla_addr)
798 return NL_SKIP;
799
800 nla_memcpy(&addr, nla_addr, sizeof(addr));
801
802 if (!IN6_IS_ADDR_LINKLOCAL(&addr))
803 return NL_SKIP;
804
805 addrs = realloc(addrs, sizeof(*addrs)*(ctxt->ret + 1));
806 if (!addrs)
807 return NL_SKIP;
808
809 memset(&addrs[ctxt->ret], 0, sizeof(addrs[ctxt->ret]));
810
811 addrs = realloc(addrs, sizeof(*addrs)*(ctxt->ret + 1));
812 if (!addrs)
813 return NL_SKIP;
814
815
816 memcpy(&addrs[ctxt->ret].addr, &addr, sizeof(addrs[ctxt->ret].addr));
817
818 if (ifa->ifa_flags & IFA_F_TENTATIVE)
819 addrs[ctxt->ret].tentative = true;
820
821 ctxt->ret++;
822 *(ctxt->addrs) = addrs;
823
824 return NL_OK;
825 }
826
827
828 static int cb_linklocal_finish(_unused struct nl_msg *msg, void *arg)
829 {
830 struct addr_info *ctxt = (struct addr_info *)arg;
831
832 ctxt->pending = 0;
833
834 return NL_STOP;
835 }
836
837
838 static int cb_linklocal_error(_unused struct sockaddr_nl *nla, struct nlmsgerr *err,
839 void *arg)
840 {
841 struct addr_info *ctxt = (struct addr_info *)arg;
842
843 ctxt->pending = 0;
844 ctxt->ret = err->error;
845
846 return NL_STOP;
847 }
848
849
850 /* Detect a link local IPV6-address currently assigned to the given interface */
851 ssize_t netlink_get_interface_linklocal(int ifindex, struct odhcpd_ipaddr **addrs)
852 {
853 struct nl_msg *msg;
854 struct ifaddrmsg ifa = {
855 .ifa_family = AF_INET6,
856 .ifa_prefixlen = 0,
857 .ifa_flags = 0,
858 .ifa_scope = 0,
859 .ifa_index = ifindex, };
860 struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT);
861 struct addr_info ctxt = {
862 .ifindex = ifindex,
863 .af = AF_INET6,
864 .addrs = addrs,
865 .ret = 0,
866 .pending = 1,
867 };
868
869 if (!cb) {
870 ctxt.ret = -1;
871 goto out;
872 }
873
874 msg = nlmsg_alloc_simple(RTM_GETADDR, NLM_F_REQUEST | NLM_F_DUMP);
875
876 if (!msg) {
877 ctxt.ret = - 1;
878 goto out;
879 }
880
881 nlmsg_append(msg, &ifa, sizeof(ifa), 0);
882
883 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, cb_linklocal_valid, &ctxt);
884 nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, cb_linklocal_finish, &ctxt);
885 nl_cb_err(cb, NL_CB_CUSTOM, cb_linklocal_error, &ctxt);
886
887 ctxt.ret = nl_send_auto_complete(rtnl_socket, msg);
888 if (ctxt.ret < 0)
889 goto free;
890
891 ctxt.ret = 0;
892 while (ctxt.pending > 0)
893 nl_recvmsgs(rtnl_socket, cb);
894
895 if (ctxt.ret <= 0)
896 goto free;
897
898 free:
899 nlmsg_free(msg);
900 out:
901 nl_cb_put(cb);
902
903 return ctxt.ret;
904 }
905
906
907 struct neigh_info {
908 int ifindex;
909 int pending;
910 const struct in6_addr *addr;
911 int ret;
912 };
913
914
915 static int cb_proxy_neigh_valid(struct nl_msg *msg, void *arg)
916 {
917 struct neigh_info *ctxt = (struct neigh_info *)arg;
918 struct nlmsghdr *hdr = nlmsg_hdr(msg);
919 struct ndmsg *ndm;
920 struct nlattr *nla_dst;
921
922 if (hdr->nlmsg_type != RTM_NEWNEIGH)
923 return NL_SKIP;
924
925 ndm = NLMSG_DATA(hdr);
926 if (ndm->ndm_family != AF_INET6 ||
927 (ctxt->ifindex && ndm->ndm_ifindex != ctxt->ifindex))
928 return NL_SKIP;
929
930 if (!(ndm->ndm_flags & NTF_PROXY))
931 return NL_SKIP;
932
933 nla_dst = nlmsg_find_attr(hdr, sizeof(*ndm), NDA_DST);
934 if (!nla_dst)
935 return NL_SKIP;
936
937 if (nla_memcmp(nla_dst,ctxt->addr, 16) == 0)
938 ctxt->ret = 1;
939
940 return NL_OK;
941 }
942
943
944 static int cb_proxy_neigh_finish(_unused struct nl_msg *msg, void *arg)
945 {
946 struct neigh_info *ctxt = (struct neigh_info *)arg;
947
948 ctxt->pending = 0;
949
950 return NL_STOP;
951 }
952
953
954 static int cb_proxy_neigh_error(_unused struct sockaddr_nl *nla, struct nlmsgerr *err,
955 void *arg)
956 {
957 struct neigh_info *ctxt = (struct neigh_info *)arg;
958
959 ctxt->pending = 0;
960 ctxt->ret = err->error;
961
962 return NL_STOP;
963 }
964
965 /* Detect an IPV6-address proxy neighbor for the given interface */
966 int netlink_get_interface_proxy_neigh(int ifindex, const struct in6_addr *addr)
967 {
968 struct nl_msg *msg;
969 struct ndmsg ndm = {
970 .ndm_family = AF_INET6,
971 .ndm_flags = NTF_PROXY,
972 .ndm_ifindex = ifindex,
973 };
974 struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT);
975 struct neigh_info ctxt = {
976 .ifindex = ifindex,
977 .addr = addr,
978 .ret = 0,
979 .pending = 1,
980 };
981
982 if (!cb) {
983 ctxt.ret = -1;
984 goto out;
985 }
986
987 msg = nlmsg_alloc_simple(RTM_GETNEIGH, NLM_F_REQUEST | NLM_F_MATCH);
988
989 if (!msg) {
990 ctxt.ret = -1;
991 goto out;
992 }
993
994 nlmsg_append(msg, &ndm, sizeof(ndm), 0);
995 nla_put(msg, NDA_DST, sizeof(*addr), addr);
996
997 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, cb_proxy_neigh_valid, &ctxt);
998 nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, cb_proxy_neigh_finish, &ctxt);
999 nl_cb_err(cb, NL_CB_CUSTOM, cb_proxy_neigh_error, &ctxt);
1000
1001 ctxt.ret = nl_send_auto_complete(rtnl_socket, msg);
1002 if (ctxt.ret < 0)
1003 goto free;
1004
1005 while (ctxt.pending > 0)
1006 nl_recvmsgs(rtnl_socket, cb);
1007
1008 free:
1009 nlmsg_free(msg);
1010 out:
1011 nl_cb_put(cb);
1012
1013 return ctxt.ret;
1014 }
1015
1016
1017 int netlink_setup_route(const struct in6_addr *addr, const int prefixlen,
1018 const int ifindex, const struct in6_addr *gw,
1019 const uint32_t metric, const bool add)
1020 {
1021 struct nl_msg *msg;
1022 struct rtmsg rtm = {
1023 .rtm_family = AF_INET6,
1024 .rtm_dst_len = prefixlen,
1025 .rtm_src_len = 0,
1026 .rtm_table = RT_TABLE_MAIN,
1027 .rtm_protocol = (add ? RTPROT_STATIC : RTPROT_UNSPEC),
1028 .rtm_scope = (add ? (gw ? RT_SCOPE_UNIVERSE : RT_SCOPE_LINK) : RT_SCOPE_NOWHERE),
1029 .rtm_type = (add ? RTN_UNICAST : RTN_UNSPEC),
1030 };
1031 int ret = 0;
1032
1033 msg = nlmsg_alloc_simple(add ? RTM_NEWROUTE : RTM_DELROUTE,
1034 add ? NLM_F_CREATE | NLM_F_REPLACE : 0);
1035 if (!msg)
1036 return -1;
1037
1038 nlmsg_append(msg, &rtm, sizeof(rtm), 0);
1039
1040 nla_put(msg, RTA_DST, sizeof(*addr), addr);
1041 nla_put_u32(msg, RTA_OIF, ifindex);
1042 nla_put_u32(msg, RTA_PRIORITY, metric);
1043
1044 if (gw)
1045 nla_put(msg, RTA_GATEWAY, sizeof(*gw), gw);
1046
1047 ret = nl_send_auto_complete(rtnl_socket, msg);
1048 nlmsg_free(msg);
1049
1050 if (ret < 0)
1051 return ret;
1052
1053 return nl_wait_for_ack(rtnl_socket);
1054 }
1055
1056
1057 int netlink_setup_proxy_neigh(const struct in6_addr *addr,
1058 const int ifindex, const bool add)
1059 {
1060 struct nl_msg *msg;
1061 struct ndmsg ndm = {
1062 .ndm_family = AF_INET6,
1063 .ndm_flags = NTF_PROXY,
1064 .ndm_ifindex = ifindex,
1065 };
1066 int ret = 0, flags = NLM_F_REQUEST;
1067
1068 if (add)
1069 flags |= NLM_F_REPLACE | NLM_F_CREATE;
1070
1071 msg = nlmsg_alloc_simple(add ? RTM_NEWNEIGH : RTM_DELNEIGH, flags);
1072 if (!msg)
1073 return -1;
1074
1075 nlmsg_append(msg, &ndm, sizeof(ndm), 0);
1076
1077 nla_put(msg, NDA_DST, sizeof(*addr), addr);
1078
1079 ret = nl_send_auto_complete(rtnl_socket, msg);
1080 nlmsg_free(msg);
1081
1082 if (ret < 0)
1083 return ret;
1084
1085 return nl_wait_for_ack(rtnl_socket);
1086 }
1087
1088
1089 int netlink_setup_addr(struct odhcpd_ipaddr *addr,
1090 const int ifindex, const bool v6, const bool add)
1091 {
1092 struct nl_msg *msg;
1093 struct ifaddrmsg ifa = {
1094 .ifa_family = v6 ? AF_INET6 : AF_INET,
1095 .ifa_prefixlen = addr->prefix,
1096 .ifa_flags = 0,
1097 .ifa_scope = 0,
1098 .ifa_index = ifindex, };
1099 int ret = 0, flags = NLM_F_REQUEST;
1100
1101 if (add)
1102 flags |= NLM_F_REPLACE | NLM_F_CREATE;
1103
1104 msg = nlmsg_alloc_simple(add ? RTM_NEWADDR : RTM_DELADDR, 0);
1105 if (!msg)
1106 return -1;
1107
1108 nlmsg_append(msg, &ifa, sizeof(ifa), flags);
1109 nla_put(msg, IFA_LOCAL, v6 ? 16 : 4, &addr->addr);
1110 if (v6) {
1111 struct ifa_cacheinfo cinfo = { .ifa_prefered = 0xffffffffU,
1112 .ifa_valid = 0xffffffffU,
1113 .cstamp = 0,
1114 .tstamp = 0 };
1115 time_t now = odhcpd_time();
1116
1117 if (addr->preferred) {
1118 int64_t preferred = addr->preferred - now;
1119 if (preferred < 0)
1120 preferred = 0;
1121 else if (preferred > UINT32_MAX)
1122 preferred = UINT32_MAX;
1123
1124 cinfo.ifa_prefered = preferred;
1125 }
1126
1127 if (addr->valid) {
1128 int64_t valid = addr->valid - now;
1129 if (valid <= 0) {
1130 nlmsg_free(msg);
1131 return -1;
1132 }
1133 else if (valid > UINT32_MAX)
1134 valid = UINT32_MAX;
1135
1136 cinfo.ifa_valid = valid;
1137 }
1138
1139 nla_put(msg, IFA_CACHEINFO, sizeof(cinfo), &cinfo);
1140
1141 nla_put_u32(msg, IFA_FLAGS, IFA_F_NOPREFIXROUTE);
1142 } else {
1143 if (addr->broadcast.s_addr)
1144 nla_put_u32(msg, IFA_BROADCAST, addr->broadcast.s_addr);
1145 }
1146
1147 ret = nl_send_auto_complete(rtnl_socket, msg);
1148 nlmsg_free(msg);
1149
1150 if (ret < 0)
1151 return ret;
1152
1153 return nl_wait_for_ack(rtnl_socket);
1154 }
1155
1156 void netlink_dump_neigh_table(const bool proxy)
1157 {
1158 struct nl_msg *msg;
1159 struct ndmsg ndm = {
1160 .ndm_family = AF_INET6,
1161 .ndm_flags = proxy ? NTF_PROXY : 0,
1162 };
1163
1164 msg = nlmsg_alloc_simple(RTM_GETNEIGH, NLM_F_REQUEST | NLM_F_DUMP);
1165 if (!msg)
1166 return;
1167
1168 nlmsg_append(msg, &ndm, sizeof(ndm), 0);
1169
1170 nl_send_auto_complete(rtnl_event.sock, msg);
1171
1172 nlmsg_free(msg);
1173 }
1174
1175 void netlink_dump_addr_table(const bool v6)
1176 {
1177 struct nl_msg *msg;
1178 struct ifaddrmsg ifa = {
1179 .ifa_family = v6 ? AF_INET6 : AF_INET,
1180 };
1181
1182 msg = nlmsg_alloc_simple(RTM_GETADDR, NLM_F_REQUEST | NLM_F_DUMP);
1183 if (!msg)
1184 return;
1185
1186 nlmsg_append(msg, &ifa, sizeof(ifa), 0);
1187
1188 nl_send_auto_complete(rtnl_event.sock, msg);
1189
1190 nlmsg_free(msg);
1191 }