]> git.proxmox.com Git - mirror_frr.git/blob - zebra/rt_netlink.c
Add comment questioning part of previous change (Denis?).
[mirror_frr.git] / zebra / rt_netlink.c
1 /* Kernel routing table updates using netlink over GNU/Linux system.
2 * Copyright (C) 1997, 98, 99 Kunihiro Ishiguro
3 *
4 * This file is part of GNU Zebra.
5 *
6 * GNU Zebra is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2, or (at your option) any
9 * later version.
10 *
11 * GNU Zebra is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with GNU Zebra; see the file COPYING. If not, write to the Free
18 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
19 * 02111-1307, USA.
20 */
21
22 #include <zebra.h>
23
24 /* Hack for GNU libc version 2. */
25 #ifndef MSG_TRUNC
26 #define MSG_TRUNC 0x20
27 #endif /* MSG_TRUNC */
28
29 #include "linklist.h"
30 #include "if.h"
31 #include "log.h"
32 #include "prefix.h"
33 #include "connected.h"
34 #include "table.h"
35 #include "rib.h"
36 #include "thread.h"
37 #include "privs.h"
38
39 #include "zebra/zserv.h"
40 #include "zebra/rt.h"
41 #include "zebra/redistribute.h"
42 #include "zebra/interface.h"
43 #include "zebra/debug.h"
44
45 /* Socket interface to kernel */
46 struct nlsock
47 {
48 int sock;
49 int seq;
50 struct sockaddr_nl snl;
51 const char *name;
52 } netlink = { -1, 0, {0}, "netlink-listen"}, /* kernel messages */
53 netlink_cmd = { -1, 0, {0}, "netlink-cmd"}; /* command channel */
54
55 struct message nlmsg_str[] = {
56 {RTM_NEWROUTE, "RTM_NEWROUTE"},
57 {RTM_DELROUTE, "RTM_DELROUTE"},
58 {RTM_GETROUTE, "RTM_GETROUTE"},
59 {RTM_NEWLINK, "RTM_NEWLINK"},
60 {RTM_DELLINK, "RTM_DELLINK"},
61 {RTM_GETLINK, "RTM_GETLINK"},
62 {RTM_NEWADDR, "RTM_NEWADDR"},
63 {RTM_DELADDR, "RTM_DELADDR"},
64 {RTM_GETADDR, "RTM_GETADDR"},
65 {0, NULL}
66 };
67
68 const char *nexthop_types_desc[] =
69 {
70 "none",
71 "Directly connected",
72 "Interface route",
73 "IPv4 nexthop",
74 "IPv4 nexthop with ifindex",
75 "IPv4 nexthop with ifname",
76 "IPv6 nexthop",
77 "IPv6 nexthop with ifindex",
78 "IPv6 nexthop with ifname",
79 "Null0 nexthop",
80 };
81
82
83 extern struct zebra_t zebrad;
84
85 extern struct zebra_privs_t zserv_privs;
86
87 extern u_int32_t nl_rcvbufsize;
88
89 /* Note: on netlink systems, there should be a 1-to-1 mapping between interface
90 names and ifindex values. */
91 static void
92 set_ifindex(struct interface *ifp, unsigned int ifi_index)
93 {
94 struct interface *oifp;
95
96 if (((oifp = if_lookup_by_index(ifi_index)) != NULL) && (oifp != ifp))
97 {
98 if (ifi_index == IFINDEX_INTERNAL)
99 zlog_err("Netlink is setting interface %s ifindex to reserved "
100 "internal value %u", ifp->name, ifi_index);
101 else
102 {
103 if (IS_ZEBRA_DEBUG_KERNEL)
104 zlog_debug("interface index %d was renamed from %s to %s",
105 ifi_index, oifp->name, ifp->name);
106 if (if_is_up(oifp))
107 zlog_err("interface rename detected on up interface: index %d "
108 "was renamed from %s to %s, results are uncertain!",
109 ifi_index, oifp->name, ifp->name);
110 if_delete_update(oifp);
111 }
112 }
113 ifp->ifindex = ifi_index;
114 }
115
116 /* Make socket for Linux netlink interface. */
117 static int
118 netlink_socket (struct nlsock *nl, unsigned long groups)
119 {
120 int ret;
121 struct sockaddr_nl snl;
122 int sock;
123 int namelen;
124 int save_errno;
125
126 sock = socket (AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
127 if (sock < 0)
128 {
129 zlog (NULL, LOG_ERR, "Can't open %s socket: %s", nl->name,
130 safe_strerror (errno));
131 return -1;
132 }
133
134 ret = fcntl (sock, F_SETFL, O_NONBLOCK);
135 if (ret < 0)
136 {
137 zlog (NULL, LOG_ERR, "Can't set %s socket flags: %s", nl->name,
138 safe_strerror (errno));
139 close (sock);
140 return -1;
141 }
142
143 /* Set receive buffer size if it's set from command line */
144 if (nl_rcvbufsize)
145 {
146 u_int32_t oldsize, oldlen;
147 u_int32_t newsize, newlen;
148
149 oldlen = sizeof(oldsize);
150 newlen = sizeof(newsize);
151
152 ret = getsockopt(sock, SOL_SOCKET, SO_RCVBUF, &oldsize, &oldlen);
153 if (ret < 0)
154 {
155 zlog (NULL, LOG_ERR, "Can't get %s receive buffer size: %s", nl->name,
156 safe_strerror (errno));
157 close (sock);
158 return -1;
159 }
160
161 ret = setsockopt(sock, SOL_SOCKET, SO_RCVBUF, &nl_rcvbufsize,
162 sizeof(nl_rcvbufsize));
163 if (ret < 0)
164 {
165 zlog (NULL, LOG_ERR, "Can't set %s receive buffer size: %s", nl->name,
166 safe_strerror (errno));
167 close (sock);
168 return -1;
169 }
170
171 ret = getsockopt(sock, SOL_SOCKET, SO_RCVBUF, &newsize, &newlen);
172 if (ret < 0)
173 {
174 zlog (NULL, LOG_ERR, "Can't get %s receive buffer size: %s", nl->name,
175 safe_strerror (errno));
176 close (sock);
177 return -1;
178 }
179
180 zlog (NULL, LOG_INFO,
181 "Setting netlink socket receive buffer size: %u -> %u",
182 oldsize, newsize);
183 }
184
185 memset (&snl, 0, sizeof snl);
186 snl.nl_family = AF_NETLINK;
187 snl.nl_groups = groups;
188
189 /* Bind the socket to the netlink structure for anything. */
190 if (zserv_privs.change (ZPRIVS_RAISE))
191 {
192 zlog (NULL, LOG_ERR, "Can't raise privileges");
193 return -1;
194 }
195
196 ret = bind (sock, (struct sockaddr *) &snl, sizeof snl);
197 save_errno = errno;
198 if (zserv_privs.change (ZPRIVS_LOWER))
199 zlog (NULL, LOG_ERR, "Can't lower privileges");
200
201 if (ret < 0)
202 {
203 zlog (NULL, LOG_ERR, "Can't bind %s socket to group 0x%x: %s",
204 nl->name, snl.nl_groups, safe_strerror (save_errno));
205 close (sock);
206 return -1;
207 }
208
209 /* multiple netlink sockets will have different nl_pid */
210 namelen = sizeof snl;
211 ret = getsockname (sock, (struct sockaddr *) &snl, (socklen_t *) &namelen);
212 if (ret < 0 || namelen != sizeof snl)
213 {
214 zlog (NULL, LOG_ERR, "Can't get %s socket name: %s", nl->name,
215 safe_strerror (errno));
216 close (sock);
217 return -1;
218 }
219
220 nl->snl = snl;
221 nl->sock = sock;
222 return ret;
223 }
224
225 int
226 set_netlink_blocking (struct nlsock *nl, int *flags)
227 {
228
229 /* Change socket flags for blocking I/O. */
230 if ((*flags = fcntl (nl->sock, F_GETFL, 0)) < 0)
231 {
232 zlog (NULL, LOG_ERR, "%s:%i F_GETFL error: %s",
233 __FUNCTION__, __LINE__, safe_strerror (errno));
234 return -1;
235 }
236 *flags &= ~O_NONBLOCK;
237 if (fcntl (nl->sock, F_SETFL, *flags) < 0)
238 {
239 zlog (NULL, LOG_ERR, "%s:%i F_SETFL error: %s",
240 __FUNCTION__, __LINE__, safe_strerror (errno));
241 return -1;
242 }
243 return 0;
244 }
245
246 int
247 set_netlink_nonblocking (struct nlsock *nl, int *flags)
248 {
249 /* Restore socket flags for nonblocking I/O */
250 *flags |= O_NONBLOCK;
251 if (fcntl (nl->sock, F_SETFL, *flags) < 0)
252 {
253 zlog (NULL, LOG_ERR, "%s:%i F_SETFL error: %s",
254 __FUNCTION__, __LINE__, safe_strerror (errno));
255 return -1;
256 }
257 return 0;
258 }
259
260 /* Get type specified information from netlink. */
261 static int
262 netlink_request (int family, int type, struct nlsock *nl)
263 {
264 int ret;
265 struct sockaddr_nl snl;
266 int save_errno;
267
268 struct
269 {
270 struct nlmsghdr nlh;
271 struct rtgenmsg g;
272 } req;
273
274
275 /* Check netlink socket. */
276 if (nl->sock < 0)
277 {
278 zlog (NULL, LOG_ERR, "%s socket isn't active.", nl->name);
279 return -1;
280 }
281
282 memset (&snl, 0, sizeof snl);
283 snl.nl_family = AF_NETLINK;
284
285 memset (&req, 0, sizeof req);
286 req.nlh.nlmsg_len = sizeof req;
287 req.nlh.nlmsg_type = type;
288 req.nlh.nlmsg_flags = NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST;
289 req.nlh.nlmsg_pid = 0;
290 req.nlh.nlmsg_seq = ++nl->seq;
291 req.g.rtgen_family = family;
292
293 /* linux appears to check capabilities on every message
294 * have to raise caps for every message sent
295 */
296 if (zserv_privs.change (ZPRIVS_RAISE))
297 {
298 zlog (NULL, LOG_ERR, "Can't raise privileges");
299 return -1;
300 }
301
302 ret = sendto (nl->sock, (void *) &req, sizeof req, 0,
303 (struct sockaddr *) &snl, sizeof snl);
304 save_errno = errno;
305
306 if (zserv_privs.change (ZPRIVS_LOWER))
307 zlog (NULL, LOG_ERR, "Can't lower privileges");
308
309 if (ret < 0)
310 {
311 zlog (NULL, LOG_ERR, "%s sendto failed: %s", nl->name,
312 safe_strerror (save_errno));
313 return -1;
314 }
315
316 return 0;
317 }
318
319 /* Receive message from netlink interface and pass those information
320 to the given function. */
321 static int
322 netlink_parse_info (int (*filter) (struct sockaddr_nl *, struct nlmsghdr *),
323 struct nlsock *nl)
324 {
325 int status;
326 int ret = 0;
327 int error;
328
329 while (1)
330 {
331 char buf[4096];
332 struct iovec iov = { buf, sizeof buf };
333 struct sockaddr_nl snl;
334 struct msghdr msg = { (void *) &snl, sizeof snl, &iov, 1, NULL, 0, 0 };
335 struct nlmsghdr *h;
336 int save_errno;
337
338 if (zserv_privs.change (ZPRIVS_RAISE))
339 zlog (NULL, LOG_ERR, "Can't raise privileges");
340
341 status = recvmsg (nl->sock, &msg, 0);
342 save_errno = errno;
343
344 if (zserv_privs.change (ZPRIVS_LOWER))
345 zlog (NULL, LOG_ERR, "Can't lower privileges");
346
347 if (status < 0)
348 {
349 if (save_errno == EINTR)
350 continue;
351 if (save_errno == EWOULDBLOCK || save_errno == EAGAIN)
352 break;
353 zlog (NULL, LOG_ERR, "%s recvmsg overrun: %s",
354 nl->name, safe_strerror(save_errno));
355 continue;
356 }
357
358 if (status == 0)
359 {
360 zlog (NULL, LOG_ERR, "%s EOF", nl->name);
361 return -1;
362 }
363
364 if (msg.msg_namelen != sizeof snl)
365 {
366 zlog (NULL, LOG_ERR, "%s sender address length error: length %d",
367 nl->name, msg.msg_namelen);
368 return -1;
369 }
370
371 /* JF: Ignore messages that aren't from the kernel */
372 if ( snl.nl_pid != 0 )
373 {
374 zlog ( NULL, LOG_ERR, "Ignoring message from pid %u", snl.nl_pid );
375 continue;
376 }
377
378 for (h = (struct nlmsghdr *) buf; NLMSG_OK (h, (unsigned int) status);
379 h = NLMSG_NEXT (h, status))
380 {
381 /* Finish of reading. */
382 if (h->nlmsg_type == NLMSG_DONE)
383 return ret;
384
385 /* Error handling. */
386 if (h->nlmsg_type == NLMSG_ERROR)
387 {
388 struct nlmsgerr *err = (struct nlmsgerr *) NLMSG_DATA (h);
389
390 /* If the error field is zero, then this is an ACK */
391 if (err->error == 0)
392 {
393 if (IS_ZEBRA_DEBUG_KERNEL)
394 {
395 zlog_debug ("%s: %s ACK: type=%s(%u), seq=%u, pid=%u",
396 __FUNCTION__, nl->name,
397 lookup (nlmsg_str, err->msg.nlmsg_type),
398 err->msg.nlmsg_type, err->msg.nlmsg_seq,
399 err->msg.nlmsg_pid);
400 }
401
402 /* return if not a multipart message, otherwise continue */
403 if (!(h->nlmsg_flags & NLM_F_MULTI))
404 {
405 return 0;
406 }
407 continue;
408 }
409
410 if (h->nlmsg_len < NLMSG_LENGTH (sizeof (struct nlmsgerr)))
411 {
412 zlog (NULL, LOG_ERR, "%s error: message truncated",
413 nl->name);
414 return -1;
415 }
416
417 /* Deal with Error Noise - MAG */
418 {
419 int loglvl = LOG_ERR;
420 int errnum = err->error;
421 int msg_type = err->msg.nlmsg_type;
422
423 if (nl == &netlink_cmd
424 && (-errnum == ENODEV || -errnum == ESRCH)
425 && (msg_type == RTM_NEWROUTE || msg_type == RTM_DELROUTE))
426 loglvl = LOG_DEBUG;
427
428 zlog (NULL, loglvl, "%s error: %s, type=%s(%u), "
429 "seq=%u, pid=%u",
430 nl->name, safe_strerror (-errnum),
431 lookup (nlmsg_str, msg_type),
432 msg_type, err->msg.nlmsg_seq, err->msg.nlmsg_pid);
433 }
434 /*
435 ret = -1;
436 continue;
437 */
438 return -1;
439 }
440
441 /* OK we got netlink message. */
442 if (IS_ZEBRA_DEBUG_KERNEL)
443 zlog_debug ("netlink_parse_info: %s type %s(%u), seq=%u, pid=%u",
444 nl->name,
445 lookup (nlmsg_str, h->nlmsg_type), h->nlmsg_type,
446 h->nlmsg_seq, h->nlmsg_pid);
447
448 /* skip unsolicited messages originating from command socket */
449 if (nl != &netlink_cmd && h->nlmsg_pid == netlink_cmd.snl.nl_pid)
450 {
451 if (IS_ZEBRA_DEBUG_KERNEL)
452 zlog_debug ("netlink_parse_info: %s packet comes from %s",
453 netlink_cmd.name, nl->name);
454 continue;
455 }
456
457 error = (*filter) (&snl, h);
458 if (error < 0)
459 {
460 zlog (NULL, LOG_ERR, "%s filter function error", nl->name);
461 ret = error;
462 }
463 }
464
465 /* After error care. */
466 if (msg.msg_flags & MSG_TRUNC)
467 {
468 zlog (NULL, LOG_ERR, "%s error: message truncated", nl->name);
469 continue;
470 }
471 if (status)
472 {
473 zlog (NULL, LOG_ERR, "%s error: data remnant size %d", nl->name,
474 status);
475 return -1;
476 }
477 }
478 return ret;
479 }
480
481 /* Utility function for parse rtattr. */
482 static void
483 netlink_parse_rtattr (struct rtattr **tb, int max, struct rtattr *rta,
484 int len)
485 {
486 while (RTA_OK (rta, len))
487 {
488 if (rta->rta_type <= max)
489 tb[rta->rta_type] = rta;
490 rta = RTA_NEXT (rta, len);
491 }
492 }
493
494 /* Called from interface_lookup_netlink(). This function is only used
495 during bootstrap. */
496 int
497 netlink_interface (struct sockaddr_nl *snl, struct nlmsghdr *h)
498 {
499 int len;
500 struct ifinfomsg *ifi;
501 struct rtattr *tb[IFLA_MAX + 1];
502 struct interface *ifp;
503 char *name;
504 int i;
505
506 ifi = NLMSG_DATA (h);
507
508 if (h->nlmsg_type != RTM_NEWLINK)
509 return 0;
510
511 len = h->nlmsg_len - NLMSG_LENGTH (sizeof (struct ifinfomsg));
512 if (len < 0)
513 return -1;
514
515 /* Looking up interface name. */
516 memset (tb, 0, sizeof tb);
517 netlink_parse_rtattr (tb, IFLA_MAX, IFLA_RTA (ifi), len);
518
519 #ifdef IFLA_WIRELESS
520 /* check for wireless messages to ignore */
521 if ((tb[IFLA_WIRELESS] != NULL) && (ifi->ifi_change == 0))
522 {
523 if (IS_ZEBRA_DEBUG_KERNEL)
524 zlog_debug ("%s: ignoring IFLA_WIRELESS message", __func__);
525 return 0;
526 }
527 #endif /* IFLA_WIRELESS */
528
529 if (tb[IFLA_IFNAME] == NULL)
530 return -1;
531 name = (char *) RTA_DATA (tb[IFLA_IFNAME]);
532
533 /* Add interface. */
534 ifp = if_get_by_name (name);
535 set_ifindex(ifp, ifi->ifi_index);
536 ifp->flags = ifi->ifi_flags & 0x0000fffff;
537 ifp->mtu6 = ifp->mtu = *(int *) RTA_DATA (tb[IFLA_MTU]);
538 ifp->metric = 1;
539
540 /* Hardware type and address. */
541 ifp->hw_type = ifi->ifi_type;
542
543 if (tb[IFLA_ADDRESS])
544 {
545 int hw_addr_len;
546
547 hw_addr_len = RTA_PAYLOAD (tb[IFLA_ADDRESS]);
548
549 if (hw_addr_len > INTERFACE_HWADDR_MAX)
550 zlog_warn ("Hardware address is too large: %d", hw_addr_len);
551 else
552 {
553 ifp->hw_addr_len = hw_addr_len;
554 memcpy (ifp->hw_addr, RTA_DATA (tb[IFLA_ADDRESS]), hw_addr_len);
555
556 for (i = 0; i < hw_addr_len; i++)
557 if (ifp->hw_addr[i] != 0)
558 break;
559
560 if (i == hw_addr_len)
561 ifp->hw_addr_len = 0;
562 else
563 ifp->hw_addr_len = hw_addr_len;
564 }
565 }
566
567 if_add_update (ifp);
568
569 return 0;
570 }
571
572 /* Lookup interface IPv4/IPv6 address. */
573 int
574 netlink_interface_addr (struct sockaddr_nl *snl, struct nlmsghdr *h)
575 {
576 int len;
577 struct ifaddrmsg *ifa;
578 struct rtattr *tb[IFA_MAX + 1];
579 struct interface *ifp;
580 void *addr;
581 void *broad;
582 u_char flags = 0;
583 char *label = NULL;
584
585 ifa = NLMSG_DATA (h);
586
587 if (ifa->ifa_family != AF_INET
588 #ifdef HAVE_IPV6
589 && ifa->ifa_family != AF_INET6
590 #endif /* HAVE_IPV6 */
591 )
592 return 0;
593
594 if (h->nlmsg_type != RTM_NEWADDR && h->nlmsg_type != RTM_DELADDR)
595 return 0;
596
597 len = h->nlmsg_len - NLMSG_LENGTH (sizeof (struct ifaddrmsg));
598 if (len < 0)
599 return -1;
600
601 memset (tb, 0, sizeof tb);
602 netlink_parse_rtattr (tb, IFA_MAX, IFA_RTA (ifa), len);
603
604 ifp = if_lookup_by_index (ifa->ifa_index);
605 if (ifp == NULL)
606 {
607 zlog_err ("netlink_interface_addr can't find interface by index %d",
608 ifa->ifa_index);
609 return -1;
610 }
611
612 if (IS_ZEBRA_DEBUG_KERNEL) /* remove this line to see initial ifcfg */
613 {
614 char buf[BUFSIZ];
615 zlog_debug ("netlink_interface_addr %s %s:",
616 lookup (nlmsg_str, h->nlmsg_type), ifp->name);
617 if (tb[IFA_LOCAL])
618 zlog_debug (" IFA_LOCAL %s/%d",
619 inet_ntop (ifa->ifa_family, RTA_DATA (tb[IFA_LOCAL]),
620 buf, BUFSIZ), ifa->ifa_prefixlen);
621 if (tb[IFA_ADDRESS])
622 zlog_debug (" IFA_ADDRESS %s/%d",
623 inet_ntop (ifa->ifa_family, RTA_DATA (tb[IFA_ADDRESS]),
624 buf, BUFSIZ), ifa->ifa_prefixlen);
625 if (tb[IFA_BROADCAST])
626 zlog_debug (" IFA_BROADCAST %s/%d",
627 inet_ntop (ifa->ifa_family, RTA_DATA (tb[IFA_BROADCAST]),
628 buf, BUFSIZ), ifa->ifa_prefixlen);
629 if (tb[IFA_LABEL] && strcmp (ifp->name, RTA_DATA (tb[IFA_LABEL])))
630 zlog_debug (" IFA_LABEL %s", (char *)RTA_DATA (tb[IFA_LABEL]));
631
632 if (tb[IFA_CACHEINFO])
633 {
634 struct ifa_cacheinfo *ci = RTA_DATA (tb[IFA_CACHEINFO]);
635 zlog_debug (" IFA_CACHEINFO pref %d, valid %d",
636 ci->ifa_prefered, ci->ifa_valid);
637 }
638 }
639
640 /* logic copied from iproute2/ip/ipaddress.c:print_addrinfo() */
641 if (tb[IFA_LOCAL] == NULL)
642 tb[IFA_LOCAL] = tb[IFA_ADDRESS];
643 if (tb[IFA_ADDRESS] == NULL)
644 tb[IFA_ADDRESS] = tb[IFA_LOCAL];
645
646 /* local interface address */
647 addr = (tb[IFA_LOCAL] ? RTA_DATA(tb[IFA_LOCAL]) : NULL);
648
649 /* is there a peer address? */
650 /* N.B. I do not understand why the memcmp compares 4 bytes regardless
651 of address family, but this is exactly how it appears in
652 print_addrinfo. I wonder if it should be RTA_PAYLOAD(tb[IFA_ADDRESS])
653 instead of 4... */
654 if (tb[IFA_ADDRESS] &&
655 memcmp(RTA_DATA(tb[IFA_ADDRESS]), RTA_DATA(tb[IFA_LOCAL]), 4))
656 {
657 broad = RTA_DATA(tb[IFA_ADDRESS]);
658 SET_FLAG (flags, ZEBRA_IFA_PEER);
659 }
660 else
661 /* seeking a broadcast address */
662 broad = (tb[IFA_BROADCAST] ? RTA_DATA(tb[IFA_BROADCAST]) : NULL);
663
664 /* addr is primary key, SOL if we don't have one */
665 if (addr == NULL)
666 {
667 zlog_debug ("%s: NULL address", __func__);
668 return -1;
669 }
670
671 /* Flags. */
672 if (ifa->ifa_flags & IFA_F_SECONDARY)
673 SET_FLAG (flags, ZEBRA_IFA_SECONDARY);
674
675 /* Label */
676 if (tb[IFA_LABEL])
677 label = (char *) RTA_DATA (tb[IFA_LABEL]);
678
679 if (ifp && label && strcmp (ifp->name, label) == 0)
680 label = NULL;
681
682 /* Register interface address to the interface. */
683 if (ifa->ifa_family == AF_INET)
684 {
685 if (h->nlmsg_type == RTM_NEWADDR)
686 connected_add_ipv4 (ifp, flags,
687 (struct in_addr *) addr, ifa->ifa_prefixlen,
688 (struct in_addr *) broad, label);
689 else
690 connected_delete_ipv4 (ifp, flags,
691 (struct in_addr *) addr, ifa->ifa_prefixlen,
692 (struct in_addr *) broad);
693 }
694 #ifdef HAVE_IPV6
695 if (ifa->ifa_family == AF_INET6)
696 {
697 if (h->nlmsg_type == RTM_NEWADDR)
698 connected_add_ipv6 (ifp, flags,
699 (struct in6_addr *) addr, ifa->ifa_prefixlen,
700 (struct in6_addr *) broad, label);
701 else
702 connected_delete_ipv6 (ifp,
703 (struct in6_addr *) addr, ifa->ifa_prefixlen,
704 (struct in6_addr *) broad);
705 }
706 #endif /* HAVE_IPV6 */
707
708 return 0;
709 }
710
711 /* Looking up routing table by netlink interface. */
712 int
713 netlink_routing_table (struct sockaddr_nl *snl, struct nlmsghdr *h)
714 {
715 int len;
716 struct rtmsg *rtm;
717 struct rtattr *tb[RTA_MAX + 1];
718 u_char flags = 0;
719
720 char anyaddr[16] = { 0 };
721
722 int index;
723 int table;
724 int metric;
725
726 void *dest;
727 void *gate;
728 void *src;
729
730 rtm = NLMSG_DATA (h);
731
732 if (h->nlmsg_type != RTM_NEWROUTE)
733 return 0;
734 if (rtm->rtm_type != RTN_UNICAST)
735 return 0;
736
737 table = rtm->rtm_table;
738 #if 0 /* we weed them out later in rib_weed_tables () */
739 if (table != RT_TABLE_MAIN && table != zebrad.rtm_table_default)
740 return 0;
741 #endif
742
743 len = h->nlmsg_len - NLMSG_LENGTH (sizeof (struct rtmsg));
744 if (len < 0)
745 return -1;
746
747 memset (tb, 0, sizeof tb);
748 netlink_parse_rtattr (tb, RTA_MAX, RTM_RTA (rtm), len);
749
750 if (rtm->rtm_flags & RTM_F_CLONED)
751 return 0;
752 if (rtm->rtm_protocol == RTPROT_REDIRECT)
753 return 0;
754 if (rtm->rtm_protocol == RTPROT_KERNEL)
755 return 0;
756
757 if (rtm->rtm_src_len != 0)
758 return 0;
759
760 /* Route which inserted by Zebra. */
761 if (rtm->rtm_protocol == RTPROT_ZEBRA)
762 flags |= ZEBRA_FLAG_SELFROUTE;
763
764 index = 0;
765 metric = 0;
766 dest = NULL;
767 gate = NULL;
768 src = NULL;
769
770 if (tb[RTA_OIF])
771 index = *(int *) RTA_DATA (tb[RTA_OIF]);
772
773 if (tb[RTA_DST])
774 dest = RTA_DATA (tb[RTA_DST]);
775 else
776 dest = anyaddr;
777
778 if (tb[RTA_PREFSRC])
779 src = RTA_DATA (tb[RTA_PREFSRC]);
780
781 /* Multipath treatment is needed. */
782 if (tb[RTA_GATEWAY])
783 gate = RTA_DATA (tb[RTA_GATEWAY]);
784
785 if (tb[RTA_PRIORITY])
786 metric = *(int *) RTA_DATA(tb[RTA_PRIORITY]);
787
788 if (rtm->rtm_family == AF_INET)
789 {
790 struct prefix_ipv4 p;
791 p.family = AF_INET;
792 memcpy (&p.prefix, dest, 4);
793 p.prefixlen = rtm->rtm_dst_len;
794
795 rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, flags, &p, gate, src, index, table, metric, 0);
796 }
797 #ifdef HAVE_IPV6
798 if (rtm->rtm_family == AF_INET6)
799 {
800 struct prefix_ipv6 p;
801 p.family = AF_INET6;
802 memcpy (&p.prefix, dest, 16);
803 p.prefixlen = rtm->rtm_dst_len;
804
805 rib_add_ipv6 (ZEBRA_ROUTE_KERNEL, flags, &p, gate, index, table,
806 metric, 0);
807 }
808 #endif /* HAVE_IPV6 */
809
810 return 0;
811 }
812
813 struct message rtproto_str[] = {
814 {RTPROT_REDIRECT, "redirect"},
815 {RTPROT_KERNEL, "kernel"},
816 {RTPROT_BOOT, "boot"},
817 {RTPROT_STATIC, "static"},
818 {RTPROT_GATED, "GateD"},
819 {RTPROT_RA, "router advertisement"},
820 {RTPROT_MRT, "MRT"},
821 {RTPROT_ZEBRA, "Zebra"},
822 #ifdef RTPROT_BIRD
823 {RTPROT_BIRD, "BIRD"},
824 #endif /* RTPROT_BIRD */
825 {0, NULL}
826 };
827
828 /* Routing information change from the kernel. */
829 int
830 netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h)
831 {
832 int len;
833 struct rtmsg *rtm;
834 struct rtattr *tb[RTA_MAX + 1];
835
836 char anyaddr[16] = { 0 };
837
838 int index;
839 int table;
840 void *dest;
841 void *gate;
842 void *src;
843
844 rtm = NLMSG_DATA (h);
845
846 if (!(h->nlmsg_type == RTM_NEWROUTE || h->nlmsg_type == RTM_DELROUTE))
847 {
848 /* If this is not route add/delete message print warning. */
849 zlog_warn ("Kernel message: %d\n", h->nlmsg_type);
850 return 0;
851 }
852
853 /* Connected route. */
854 if (IS_ZEBRA_DEBUG_KERNEL)
855 zlog_debug ("%s %s %s proto %s",
856 h->nlmsg_type ==
857 RTM_NEWROUTE ? "RTM_NEWROUTE" : "RTM_DELROUTE",
858 rtm->rtm_family == AF_INET ? "ipv4" : "ipv6",
859 rtm->rtm_type == RTN_UNICAST ? "unicast" : "multicast",
860 lookup (rtproto_str, rtm->rtm_protocol));
861
862 if (rtm->rtm_type != RTN_UNICAST)
863 {
864 return 0;
865 }
866
867 table = rtm->rtm_table;
868 if (table != RT_TABLE_MAIN && table != zebrad.rtm_table_default)
869 {
870 return 0;
871 }
872
873 len = h->nlmsg_len - NLMSG_LENGTH (sizeof (struct rtmsg));
874 if (len < 0)
875 return -1;
876
877 memset (tb, 0, sizeof tb);
878 netlink_parse_rtattr (tb, RTA_MAX, RTM_RTA (rtm), len);
879
880 if (rtm->rtm_flags & RTM_F_CLONED)
881 return 0;
882 if (rtm->rtm_protocol == RTPROT_REDIRECT)
883 return 0;
884 if (rtm->rtm_protocol == RTPROT_KERNEL)
885 return 0;
886
887 if (rtm->rtm_protocol == RTPROT_ZEBRA && h->nlmsg_type == RTM_NEWROUTE)
888 return 0;
889
890 if (rtm->rtm_src_len != 0)
891 {
892 zlog_warn ("netlink_route_change(): no src len");
893 return 0;
894 }
895
896 index = 0;
897 dest = NULL;
898 gate = NULL;
899 src = NULL;
900
901 if (tb[RTA_OIF])
902 index = *(int *) RTA_DATA (tb[RTA_OIF]);
903
904 if (tb[RTA_DST])
905 dest = RTA_DATA (tb[RTA_DST]);
906 else
907 dest = anyaddr;
908
909 if (tb[RTA_GATEWAY])
910 gate = RTA_DATA (tb[RTA_GATEWAY]);
911
912 if (tb[RTA_PREFSRC])
913 src = RTA_DATA (tb[RTA_PREFSRC]);
914
915 if (rtm->rtm_family == AF_INET)
916 {
917 struct prefix_ipv4 p;
918 p.family = AF_INET;
919 memcpy (&p.prefix, dest, 4);
920 p.prefixlen = rtm->rtm_dst_len;
921
922 if (IS_ZEBRA_DEBUG_KERNEL)
923 {
924 if (h->nlmsg_type == RTM_NEWROUTE)
925 zlog_debug ("RTM_NEWROUTE %s/%d",
926 inet_ntoa (p.prefix), p.prefixlen);
927 else
928 zlog_debug ("RTM_DELROUTE %s/%d",
929 inet_ntoa (p.prefix), p.prefixlen);
930 }
931
932 if (h->nlmsg_type == RTM_NEWROUTE)
933 rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, src, index, table, 0, 0);
934 else
935 rib_delete_ipv4 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, index, table);
936 }
937
938 #ifdef HAVE_IPV6
939 if (rtm->rtm_family == AF_INET6)
940 {
941 struct prefix_ipv6 p;
942 char buf[BUFSIZ];
943
944 p.family = AF_INET6;
945 memcpy (&p.prefix, dest, 16);
946 p.prefixlen = rtm->rtm_dst_len;
947
948 if (IS_ZEBRA_DEBUG_KERNEL)
949 {
950 if (h->nlmsg_type == RTM_NEWROUTE)
951 zlog_debug ("RTM_NEWROUTE %s/%d",
952 inet_ntop (AF_INET6, &p.prefix, buf, BUFSIZ),
953 p.prefixlen);
954 else
955 zlog_debug ("RTM_DELROUTE %s/%d",
956 inet_ntop (AF_INET6, &p.prefix, buf, BUFSIZ),
957 p.prefixlen);
958 }
959
960 if (h->nlmsg_type == RTM_NEWROUTE)
961 rib_add_ipv6 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, index, 0, 0, 0);
962 else
963 rib_delete_ipv6 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, index, 0);
964 }
965 #endif /* HAVE_IPV6 */
966
967 return 0;
968 }
969
970 int
971 netlink_link_change (struct sockaddr_nl *snl, struct nlmsghdr *h)
972 {
973 int len;
974 struct ifinfomsg *ifi;
975 struct rtattr *tb[IFLA_MAX + 1];
976 struct interface *ifp;
977 char *name;
978
979 ifi = NLMSG_DATA (h);
980
981 if (!(h->nlmsg_type == RTM_NEWLINK || h->nlmsg_type == RTM_DELLINK))
982 {
983 /* If this is not link add/delete message so print warning. */
984 zlog_warn ("netlink_link_change: wrong kernel message %d\n",
985 h->nlmsg_type);
986 return 0;
987 }
988
989 len = h->nlmsg_len - NLMSG_LENGTH (sizeof (struct ifinfomsg));
990 if (len < 0)
991 return -1;
992
993 /* Looking up interface name. */
994 memset (tb, 0, sizeof tb);
995 netlink_parse_rtattr (tb, IFLA_MAX, IFLA_RTA (ifi), len);
996
997 #ifdef IFLA_WIRELESS
998 /* check for wireless messages to ignore */
999 if ((tb[IFLA_WIRELESS] != NULL) && (ifi->ifi_change == 0))
1000 {
1001 if (IS_ZEBRA_DEBUG_KERNEL)
1002 zlog_debug ("%s: ignoring IFLA_WIRELESS message", __func__);
1003 return 0;
1004 }
1005 #endif /* IFLA_WIRELESS */
1006
1007 if (tb[IFLA_IFNAME] == NULL)
1008 return -1;
1009 name = (char *) RTA_DATA (tb[IFLA_IFNAME]);
1010
1011 /* Add interface. */
1012 if (h->nlmsg_type == RTM_NEWLINK)
1013 {
1014 ifp = if_lookup_by_name (name);
1015
1016 if (ifp == NULL || !CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE))
1017 {
1018 if (ifp == NULL)
1019 ifp = if_get_by_name (name);
1020
1021 set_ifindex(ifp, ifi->ifi_index);
1022 ifp->flags = ifi->ifi_flags & 0x0000fffff;
1023 ifp->mtu6 = ifp->mtu = *(int *) RTA_DATA (tb[IFLA_MTU]);
1024 ifp->metric = 1;
1025
1026 /* If new link is added. */
1027 if_add_update (ifp);
1028 }
1029 else
1030 {
1031 /* Interface status change. */
1032 set_ifindex(ifp, ifi->ifi_index);
1033 ifp->mtu6 = ifp->mtu = *(int *) RTA_DATA (tb[IFLA_MTU]);
1034 ifp->metric = 1;
1035
1036 if (if_is_operative (ifp))
1037 {
1038 ifp->flags = ifi->ifi_flags & 0x0000fffff;
1039 if (!if_is_operative (ifp))
1040 if_down (ifp);
1041 else
1042 /* Must notify client daemons of new interface status. */
1043 zebra_interface_up_update (ifp);
1044 }
1045 else
1046 {
1047 ifp->flags = ifi->ifi_flags & 0x0000fffff;
1048 if (if_is_operative (ifp))
1049 if_up (ifp);
1050 }
1051 }
1052 }
1053 else
1054 {
1055 /* RTM_DELLINK. */
1056 ifp = if_lookup_by_name (name);
1057
1058 if (ifp == NULL)
1059 {
1060 zlog (NULL, LOG_WARNING, "interface %s is deleted but can't find",
1061 name);
1062 return 0;
1063 }
1064
1065 if_delete_update (ifp);
1066 }
1067
1068 return 0;
1069 }
1070
1071 int
1072 netlink_information_fetch (struct sockaddr_nl *snl, struct nlmsghdr *h)
1073 {
1074 switch (h->nlmsg_type)
1075 {
1076 case RTM_NEWROUTE:
1077 return netlink_route_change (snl, h);
1078 break;
1079 case RTM_DELROUTE:
1080 return netlink_route_change (snl, h);
1081 break;
1082 case RTM_NEWLINK:
1083 return netlink_link_change (snl, h);
1084 break;
1085 case RTM_DELLINK:
1086 return netlink_link_change (snl, h);
1087 break;
1088 case RTM_NEWADDR:
1089 return netlink_interface_addr (snl, h);
1090 break;
1091 case RTM_DELADDR:
1092 return netlink_interface_addr (snl, h);
1093 break;
1094 default:
1095 zlog_warn ("Unknown netlink nlmsg_type %d\n", h->nlmsg_type);
1096 break;
1097 }
1098 return 0;
1099 }
1100
1101 /* Interface lookup by netlink socket. */
1102 int
1103 interface_lookup_netlink (void)
1104 {
1105 int ret;
1106 int flags;
1107 int snb_ret;
1108
1109 /*
1110 * Change netlink socket flags to blocking to ensure we get
1111 * a reply via nelink_parse_info
1112 */
1113 snb_ret = set_netlink_blocking (&netlink_cmd, &flags);
1114 if (snb_ret < 0)
1115 zlog (NULL, LOG_WARNING,
1116 "%s:%i Warning: Could not set netlink socket to blocking.",
1117 __FUNCTION__, __LINE__);
1118
1119 /* Get interface information. */
1120 ret = netlink_request (AF_PACKET, RTM_GETLINK, &netlink_cmd);
1121 if (ret < 0)
1122 return ret;
1123 ret = netlink_parse_info (netlink_interface, &netlink_cmd);
1124 if (ret < 0)
1125 return ret;
1126
1127 /* Get IPv4 address of the interfaces. */
1128 ret = netlink_request (AF_INET, RTM_GETADDR, &netlink_cmd);
1129 if (ret < 0)
1130 return ret;
1131 ret = netlink_parse_info (netlink_interface_addr, &netlink_cmd);
1132 if (ret < 0)
1133 return ret;
1134
1135 #ifdef HAVE_IPV6
1136 /* Get IPv6 address of the interfaces. */
1137 ret = netlink_request (AF_INET6, RTM_GETADDR, &netlink_cmd);
1138 if (ret < 0)
1139 return ret;
1140 ret = netlink_parse_info (netlink_interface_addr, &netlink_cmd);
1141 if (ret < 0)
1142 return ret;
1143 #endif /* HAVE_IPV6 */
1144
1145 /* restore socket flags */
1146 if (snb_ret == 0)
1147 set_netlink_nonblocking (&netlink_cmd, &flags);
1148 return 0;
1149 }
1150
1151 /* Routing table read function using netlink interface. Only called
1152 bootstrap time. */
1153 int
1154 netlink_route_read (void)
1155 {
1156 int ret;
1157 int flags;
1158 int snb_ret;
1159
1160 /*
1161 * Change netlink socket flags to blocking to ensure we get
1162 * a reply via nelink_parse_info
1163 */
1164 snb_ret = set_netlink_blocking (&netlink_cmd, &flags);
1165 if (snb_ret < 0)
1166 zlog (NULL, LOG_WARNING,
1167 "%s:%i Warning: Could not set netlink socket to blocking.",
1168 __FUNCTION__, __LINE__);
1169
1170 /* Get IPv4 routing table. */
1171 ret = netlink_request (AF_INET, RTM_GETROUTE, &netlink_cmd);
1172 if (ret < 0)
1173 return ret;
1174 ret = netlink_parse_info (netlink_routing_table, &netlink_cmd);
1175 if (ret < 0)
1176 return ret;
1177
1178 #ifdef HAVE_IPV6
1179 /* Get IPv6 routing table. */
1180 ret = netlink_request (AF_INET6, RTM_GETROUTE, &netlink_cmd);
1181 if (ret < 0)
1182 return ret;
1183 ret = netlink_parse_info (netlink_routing_table, &netlink_cmd);
1184 if (ret < 0)
1185 return ret;
1186 #endif /* HAVE_IPV6 */
1187
1188 /* restore flags */
1189 if (snb_ret == 0)
1190 set_netlink_nonblocking (&netlink_cmd, &flags);
1191 return 0;
1192 }
1193
1194 /* Utility function comes from iproute2.
1195 Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru> */
1196 int
1197 addattr_l (struct nlmsghdr *n, int maxlen, int type, void *data, int alen)
1198 {
1199 int len;
1200 struct rtattr *rta;
1201
1202 len = RTA_LENGTH (alen);
1203
1204 if (NLMSG_ALIGN (n->nlmsg_len) + len > maxlen)
1205 return -1;
1206
1207 rta = (struct rtattr *) (((char *) n) + NLMSG_ALIGN (n->nlmsg_len));
1208 rta->rta_type = type;
1209 rta->rta_len = len;
1210 memcpy (RTA_DATA (rta), data, alen);
1211 n->nlmsg_len = NLMSG_ALIGN (n->nlmsg_len) + len;
1212
1213 return 0;
1214 }
1215
1216 int
1217 rta_addattr_l (struct rtattr *rta, int maxlen, int type, void *data, int alen)
1218 {
1219 int len;
1220 struct rtattr *subrta;
1221
1222 len = RTA_LENGTH (alen);
1223
1224 if (RTA_ALIGN (rta->rta_len) + len > maxlen)
1225 return -1;
1226
1227 subrta = (struct rtattr *) (((char *) rta) + RTA_ALIGN (rta->rta_len));
1228 subrta->rta_type = type;
1229 subrta->rta_len = len;
1230 memcpy (RTA_DATA (subrta), data, alen);
1231 rta->rta_len = NLMSG_ALIGN (rta->rta_len) + len;
1232
1233 return 0;
1234 }
1235
1236 /* Utility function comes from iproute2.
1237 Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru> */
1238 int
1239 addattr32 (struct nlmsghdr *n, int maxlen, int type, int data)
1240 {
1241 int len;
1242 struct rtattr *rta;
1243
1244 len = RTA_LENGTH (4);
1245
1246 if (NLMSG_ALIGN (n->nlmsg_len) + len > maxlen)
1247 return -1;
1248
1249 rta = (struct rtattr *) (((char *) n) + NLMSG_ALIGN (n->nlmsg_len));
1250 rta->rta_type = type;
1251 rta->rta_len = len;
1252 memcpy (RTA_DATA (rta), &data, 4);
1253 n->nlmsg_len = NLMSG_ALIGN (n->nlmsg_len) + len;
1254
1255 return 0;
1256 }
1257
1258 static int
1259 netlink_talk_filter (struct sockaddr_nl *snl, struct nlmsghdr *h)
1260 {
1261 zlog_warn ("netlink_talk: ignoring message type 0x%04x", h->nlmsg_type);
1262 return 0;
1263 }
1264
1265 /* sendmsg() to netlink socket then recvmsg(). */
1266 int
1267 netlink_talk (struct nlmsghdr *n, struct nlsock *nl)
1268 {
1269 int status;
1270 struct sockaddr_nl snl;
1271 struct iovec iov = { (void *) n, n->nlmsg_len };
1272 struct msghdr msg = { (void *) &snl, sizeof snl, &iov, 1, NULL, 0, 0 };
1273 int flags = 0;
1274 int snb_ret;
1275 int save_errno;
1276
1277 memset (&snl, 0, sizeof snl);
1278 snl.nl_family = AF_NETLINK;
1279
1280 n->nlmsg_seq = ++nl->seq;
1281
1282 /* Request an acknowledgement by setting NLM_F_ACK */
1283 n->nlmsg_flags |= NLM_F_ACK;
1284
1285 if (IS_ZEBRA_DEBUG_KERNEL)
1286 zlog_debug ("netlink_talk: %s type %s(%u), seq=%u", nl->name,
1287 lookup (nlmsg_str, n->nlmsg_type), n->nlmsg_type,
1288 n->nlmsg_seq);
1289
1290 /* Send message to netlink interface. */
1291 if (zserv_privs.change (ZPRIVS_RAISE))
1292 zlog (NULL, LOG_ERR, "Can't raise privileges");
1293 status = sendmsg (nl->sock, &msg, 0);
1294 save_errno = errno;
1295 if (zserv_privs.change (ZPRIVS_LOWER))
1296 zlog (NULL, LOG_ERR, "Can't lower privileges");
1297
1298 if (status < 0)
1299 {
1300 zlog (NULL, LOG_ERR, "netlink_talk sendmsg() error: %s",
1301 safe_strerror (save_errno));
1302 return -1;
1303 }
1304
1305 /*
1306 * Change socket flags for blocking I/O.
1307 * This ensures we wait for a reply in netlink_parse_info().
1308 */
1309 snb_ret = set_netlink_blocking (nl, &flags);
1310 if (snb_ret < 0)
1311 zlog (NULL, LOG_WARNING,
1312 "%s:%i Warning: Could not set netlink socket to blocking.",
1313 __FUNCTION__, __LINE__);
1314
1315 /*
1316 * Get reply from netlink socket.
1317 * The reply should either be an acknowlegement or an error.
1318 */
1319 status = netlink_parse_info (netlink_talk_filter, nl);
1320
1321 /* Restore socket flags for nonblocking I/O */
1322 if (snb_ret == 0)
1323 set_netlink_nonblocking (nl, &flags);
1324
1325 return status;
1326 }
1327
1328 /* Routing table change via netlink interface. */
1329 int
1330 netlink_route (int cmd, int family, void *dest, int length, void *gate,
1331 int index, int zebra_flags, int table)
1332 {
1333 int ret;
1334 int bytelen;
1335 struct sockaddr_nl snl;
1336 int discard;
1337
1338 struct
1339 {
1340 struct nlmsghdr n;
1341 struct rtmsg r;
1342 char buf[1024];
1343 } req;
1344
1345 memset (&req, 0, sizeof req);
1346
1347 bytelen = (family == AF_INET ? 4 : 16);
1348
1349 req.n.nlmsg_len = NLMSG_LENGTH (sizeof (struct rtmsg));
1350 req.n.nlmsg_flags = NLM_F_CREATE | NLM_F_REQUEST;
1351 req.n.nlmsg_type = cmd;
1352 req.r.rtm_family = family;
1353 req.r.rtm_table = table;
1354 req.r.rtm_dst_len = length;
1355
1356 if ((zebra_flags & ZEBRA_FLAG_BLACKHOLE)
1357 || (zebra_flags & ZEBRA_FLAG_REJECT))
1358 discard = 1;
1359 else
1360 discard = 0;
1361
1362 if (cmd == RTM_NEWROUTE)
1363 {
1364 req.r.rtm_protocol = RTPROT_ZEBRA;
1365 req.r.rtm_scope = RT_SCOPE_UNIVERSE;
1366
1367 if (discard)
1368 {
1369 if (zebra_flags & ZEBRA_FLAG_BLACKHOLE)
1370 req.r.rtm_type = RTN_BLACKHOLE;
1371 else if (zebra_flags & ZEBRA_FLAG_REJECT)
1372 req.r.rtm_type = RTN_UNREACHABLE;
1373 else
1374 assert (RTN_BLACKHOLE != RTN_UNREACHABLE); /* false */
1375 }
1376 else
1377 req.r.rtm_type = RTN_UNICAST;
1378 }
1379
1380 if (dest)
1381 addattr_l (&req.n, sizeof req, RTA_DST, dest, bytelen);
1382
1383 if (!discard)
1384 {
1385 if (gate)
1386 addattr_l (&req.n, sizeof req, RTA_GATEWAY, gate, bytelen);
1387 if (index > 0)
1388 addattr32 (&req.n, sizeof req, RTA_OIF, index);
1389 }
1390
1391 /* Destination netlink address. */
1392 memset (&snl, 0, sizeof snl);
1393 snl.nl_family = AF_NETLINK;
1394
1395 /* Talk to netlink socket. */
1396 ret = netlink_talk (&req.n, &netlink_cmd);
1397 if (ret < 0)
1398 return -1;
1399
1400 return 0;
1401 }
1402
1403 /* Routing table change via netlink interface. */
1404 int
1405 netlink_route_multipath (int cmd, struct prefix *p, struct rib *rib,
1406 int family)
1407 {
1408 int bytelen;
1409 struct sockaddr_nl snl;
1410 struct nexthop *nexthop = NULL;
1411 int nexthop_num = 0;
1412 int discard;
1413
1414 struct
1415 {
1416 struct nlmsghdr n;
1417 struct rtmsg r;
1418 char buf[1024];
1419 } req;
1420
1421 memset (&req, 0, sizeof req);
1422
1423 bytelen = (family == AF_INET ? 4 : 16);
1424
1425 req.n.nlmsg_len = NLMSG_LENGTH (sizeof (struct rtmsg));
1426 req.n.nlmsg_flags = NLM_F_CREATE | NLM_F_REQUEST;
1427 req.n.nlmsg_type = cmd;
1428 req.r.rtm_family = family;
1429 req.r.rtm_table = rib->table;
1430 req.r.rtm_dst_len = p->prefixlen;
1431
1432 if ((rib->flags & ZEBRA_FLAG_BLACKHOLE) || (rib->flags & ZEBRA_FLAG_REJECT))
1433 discard = 1;
1434 else
1435 discard = 0;
1436
1437 if (cmd == RTM_NEWROUTE)
1438 {
1439 req.r.rtm_protocol = RTPROT_ZEBRA;
1440 req.r.rtm_scope = RT_SCOPE_UNIVERSE;
1441
1442 if (discard)
1443 {
1444 if (rib->flags & ZEBRA_FLAG_BLACKHOLE)
1445 req.r.rtm_type = RTN_BLACKHOLE;
1446 else if (rib->flags & ZEBRA_FLAG_REJECT)
1447 req.r.rtm_type = RTN_UNREACHABLE;
1448 else
1449 assert (RTN_BLACKHOLE != RTN_UNREACHABLE); /* false */
1450 }
1451 else
1452 req.r.rtm_type = RTN_UNICAST;
1453 }
1454
1455 addattr_l (&req.n, sizeof req, RTA_DST, &p->u.prefix, bytelen);
1456
1457 /* Metric. */
1458 addattr32 (&req.n, sizeof req, RTA_PRIORITY, rib->metric);
1459
1460 if (discard)
1461 {
1462 if (cmd == RTM_NEWROUTE)
1463 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
1464 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1465 goto skip;
1466 }
1467
1468 /* Multipath case. */
1469 if (rib->nexthop_active_num == 1 || MULTIPATH_NUM == 1)
1470 {
1471 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
1472 {
1473
1474 if ((cmd == RTM_NEWROUTE
1475 && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))
1476 || (cmd == RTM_DELROUTE
1477 && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)))
1478 {
1479
1480 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
1481 {
1482 if (IS_ZEBRA_DEBUG_KERNEL)
1483 {
1484 zlog_debug
1485 ("netlink_route_multipath() (recursive, 1 hop): "
1486 "%s %s/%d, type %s", lookup (nlmsg_str, cmd),
1487 #ifdef HAVE_IPV6
1488 (family == AF_INET) ? inet_ntoa (p->u.prefix4) :
1489 inet6_ntoa (p->u.prefix6),
1490 #else
1491 inet_ntoa (p->u.prefix4),
1492 #endif /* HAVE_IPV6 */
1493
1494 p->prefixlen, nexthop_types_desc[nexthop->rtype]);
1495 }
1496
1497 if (nexthop->rtype == NEXTHOP_TYPE_IPV4
1498 || nexthop->rtype == NEXTHOP_TYPE_IPV4_IFINDEX)
1499 {
1500 addattr_l (&req.n, sizeof req, RTA_GATEWAY,
1501 &nexthop->rgate.ipv4, bytelen);
1502 if (nexthop->src.ipv4.s_addr)
1503 addattr_l(&req.n, sizeof req, RTA_PREFSRC,
1504 &nexthop->src.ipv4, bytelen);
1505 if (IS_ZEBRA_DEBUG_KERNEL)
1506 zlog_debug("netlink_route_multipath() (recursive, "
1507 "1 hop): nexthop via %s if %u",
1508 inet_ntoa (nexthop->rgate.ipv4),
1509 nexthop->rifindex);
1510 }
1511 #ifdef HAVE_IPV6
1512 if (nexthop->rtype == NEXTHOP_TYPE_IPV6
1513 || nexthop->rtype == NEXTHOP_TYPE_IPV6_IFINDEX
1514 || nexthop->rtype == NEXTHOP_TYPE_IPV6_IFNAME)
1515 {
1516 addattr_l (&req.n, sizeof req, RTA_GATEWAY,
1517 &nexthop->rgate.ipv6, bytelen);
1518
1519 if (IS_ZEBRA_DEBUG_KERNEL)
1520 zlog_debug("netlink_route_multipath() (recursive, "
1521 "1 hop): nexthop via %s if %u",
1522 inet6_ntoa (nexthop->rgate.ipv6),
1523 nexthop->rifindex);
1524 }
1525 #endif /* HAVE_IPV6 */
1526 if (nexthop->rtype == NEXTHOP_TYPE_IFINDEX
1527 || nexthop->rtype == NEXTHOP_TYPE_IFNAME
1528 || nexthop->rtype == NEXTHOP_TYPE_IPV4_IFINDEX
1529 || nexthop->rtype == NEXTHOP_TYPE_IPV6_IFINDEX
1530 || nexthop->rtype == NEXTHOP_TYPE_IPV6_IFNAME)
1531 {
1532 addattr32 (&req.n, sizeof req, RTA_OIF,
1533 nexthop->rifindex);
1534 if ((nexthop->rtype == NEXTHOP_TYPE_IPV4_IFINDEX
1535 || nexthop->rtype == NEXTHOP_TYPE_IFINDEX)
1536 && nexthop->src.ipv4.s_addr)
1537 addattr_l (&req.n, sizeof req, RTA_PREFSRC,
1538 &nexthop->src.ipv4, bytelen);
1539
1540 if (IS_ZEBRA_DEBUG_KERNEL)
1541 zlog_debug("netlink_route_multipath() (recursive, "
1542 "1 hop): nexthop via if %u",
1543 nexthop->rifindex);
1544 }
1545 }
1546 else
1547 {
1548 if (IS_ZEBRA_DEBUG_KERNEL)
1549 {
1550 zlog_debug
1551 ("netlink_route_multipath() (single hop): "
1552 "%s %s/%d, type %s", lookup (nlmsg_str, cmd),
1553 #ifdef HAVE_IPV6
1554 (family == AF_INET) ? inet_ntoa (p->u.prefix4) :
1555 inet6_ntoa (p->u.prefix6),
1556 #else
1557 inet_ntoa (p->u.prefix4),
1558 #endif /* HAVE_IPV6 */
1559 p->prefixlen, nexthop_types_desc[nexthop->type]);
1560 }
1561
1562 if (nexthop->type == NEXTHOP_TYPE_IPV4
1563 || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX)
1564 {
1565 addattr_l (&req.n, sizeof req, RTA_GATEWAY,
1566 &nexthop->gate.ipv4, bytelen);
1567 if (nexthop->src.ipv4.s_addr)
1568 addattr_l (&req.n, sizeof req, RTA_PREFSRC,
1569 &nexthop->src.ipv4, bytelen);
1570
1571 if (IS_ZEBRA_DEBUG_KERNEL)
1572 zlog_debug("netlink_route_multipath() (single hop): "
1573 "nexthop via %s if %u",
1574 inet_ntoa (nexthop->gate.ipv4),
1575 nexthop->ifindex);
1576 }
1577 #ifdef HAVE_IPV6
1578 if (nexthop->type == NEXTHOP_TYPE_IPV6
1579 || nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME
1580 || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX)
1581 {
1582 addattr_l (&req.n, sizeof req, RTA_GATEWAY,
1583 &nexthop->gate.ipv6, bytelen);
1584
1585 if (IS_ZEBRA_DEBUG_KERNEL)
1586 zlog_debug("netlink_route_multipath() (single hop): "
1587 "nexthop via %s if %u",
1588 inet6_ntoa (nexthop->gate.ipv6),
1589 nexthop->ifindex);
1590 }
1591 #endif /* HAVE_IPV6 */
1592 if (nexthop->type == NEXTHOP_TYPE_IFINDEX
1593 || nexthop->type == NEXTHOP_TYPE_IFNAME
1594 || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX)
1595 {
1596 addattr32 (&req.n, sizeof req, RTA_OIF, nexthop->ifindex);
1597
1598 if (nexthop->src.ipv4.s_addr)
1599 addattr_l (&req.n, sizeof req, RTA_PREFSRC,
1600 &nexthop->src.ipv4, bytelen);
1601
1602 if (IS_ZEBRA_DEBUG_KERNEL)
1603 zlog_debug("netlink_route_multipath() (single hop): "
1604 "nexthop via if %u", nexthop->ifindex);
1605 }
1606 else if (nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX
1607 || nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME)
1608 {
1609 addattr32 (&req.n, sizeof req, RTA_OIF, nexthop->ifindex);
1610
1611 if (IS_ZEBRA_DEBUG_KERNEL)
1612 zlog_debug("netlink_route_multipath() (single hop): "
1613 "nexthop via if %u", nexthop->ifindex);
1614 }
1615 }
1616
1617 if (cmd == RTM_NEWROUTE)
1618 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1619
1620 nexthop_num++;
1621 break;
1622 }
1623 }
1624 }
1625 else
1626 {
1627 char buf[1024];
1628 struct rtattr *rta = (void *) buf;
1629 struct rtnexthop *rtnh;
1630 union g_addr *src = NULL;
1631
1632 rta->rta_type = RTA_MULTIPATH;
1633 rta->rta_len = RTA_LENGTH (0);
1634 rtnh = RTA_DATA (rta);
1635
1636 nexthop_num = 0;
1637 for (nexthop = rib->nexthop;
1638 nexthop && (MULTIPATH_NUM == 0 || nexthop_num < MULTIPATH_NUM);
1639 nexthop = nexthop->next)
1640 {
1641 if ((cmd == RTM_NEWROUTE
1642 && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))
1643 || (cmd == RTM_DELROUTE
1644 && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)))
1645 {
1646 nexthop_num++;
1647
1648 rtnh->rtnh_len = sizeof (*rtnh);
1649 rtnh->rtnh_flags = 0;
1650 rtnh->rtnh_hops = 0;
1651 rta->rta_len += rtnh->rtnh_len;
1652
1653 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
1654 {
1655 if (IS_ZEBRA_DEBUG_KERNEL)
1656 {
1657 zlog_debug ("netlink_route_multipath() "
1658 "(recursive, multihop): %s %s/%d type %s",
1659 lookup (nlmsg_str, cmd),
1660 #ifdef HAVE_IPV6
1661 (family == AF_INET) ? inet_ntoa (p->u.prefix4) :
1662 inet6_ntoa (p->u.prefix6),
1663 #else
1664 inet_ntoa (p->u.prefix4),
1665 #endif /* HAVE_IPV6 */
1666 p->prefixlen, nexthop_types_desc[nexthop->rtype]);
1667 }
1668 if (nexthop->rtype == NEXTHOP_TYPE_IPV4
1669 || nexthop->rtype == NEXTHOP_TYPE_IPV4_IFINDEX)
1670 {
1671 rta_addattr_l (rta, 4096, RTA_GATEWAY,
1672 &nexthop->rgate.ipv4, bytelen);
1673 rtnh->rtnh_len += sizeof (struct rtattr) + 4;
1674
1675 if (nexthop->src.ipv4.s_addr)
1676 src = &nexthop->src;
1677
1678 if (IS_ZEBRA_DEBUG_KERNEL)
1679 zlog_debug("netlink_route_multipath() (recursive, "
1680 "multihop): nexthop via %s if %u",
1681 inet_ntoa (nexthop->rgate.ipv4),
1682 nexthop->rifindex);
1683 }
1684 #ifdef HAVE_IPV6
1685 if (nexthop->rtype == NEXTHOP_TYPE_IPV6
1686 || nexthop->rtype == NEXTHOP_TYPE_IPV6_IFNAME
1687 || nexthop->rtype == NEXTHOP_TYPE_IPV6_IFINDEX)
1688 {
1689 rta_addattr_l (rta, 4096, RTA_GATEWAY,
1690 &nexthop->rgate.ipv6, bytelen);
1691
1692 if (IS_ZEBRA_DEBUG_KERNEL)
1693 zlog_debug("netlink_route_multipath() (recursive, "
1694 "multihop): nexthop via %s if %u",
1695 inet6_ntoa (nexthop->rgate.ipv6),
1696 nexthop->rifindex);
1697 }
1698 #endif /* HAVE_IPV6 */
1699 /* ifindex */
1700 if (nexthop->rtype == NEXTHOP_TYPE_IPV4_IFINDEX
1701 || nexthop->rtype == NEXTHOP_TYPE_IFINDEX
1702 || nexthop->rtype == NEXTHOP_TYPE_IFNAME)
1703 {
1704 rtnh->rtnh_ifindex = nexthop->rifindex;
1705 if (nexthop->src.ipv4.s_addr)
1706 src = &nexthop->src;
1707
1708 if (IS_ZEBRA_DEBUG_KERNEL)
1709 zlog_debug("netlink_route_multipath() (recursive, "
1710 "multihop): nexthop via if %u",
1711 nexthop->rifindex);
1712 }
1713 else if (nexthop->rtype == NEXTHOP_TYPE_IPV6_IFINDEX
1714 || nexthop->rtype == NEXTHOP_TYPE_IPV6_IFNAME)
1715 {
1716 rtnh->rtnh_ifindex = nexthop->rifindex;
1717
1718 if (IS_ZEBRA_DEBUG_KERNEL)
1719 zlog_debug("netlink_route_multipath() (recursive, "
1720 "multihop): nexthop via if %u",
1721 nexthop->rifindex);
1722 }
1723 else
1724 {
1725 rtnh->rtnh_ifindex = 0;
1726 }
1727 }
1728 else
1729 {
1730 if (IS_ZEBRA_DEBUG_KERNEL)
1731 {
1732 zlog_debug ("netlink_route_multipath() (multihop): "
1733 "%s %s/%d, type %s", lookup (nlmsg_str, cmd),
1734 #ifdef HAVE_IPV6
1735 (family == AF_INET) ? inet_ntoa (p->u.prefix4) :
1736 inet6_ntoa (p->u.prefix6),
1737 #else
1738 inet_ntoa (p->u.prefix4),
1739 #endif /* HAVE_IPV6 */
1740 p->prefixlen, nexthop_types_desc[nexthop->type]);
1741 }
1742 if (nexthop->type == NEXTHOP_TYPE_IPV4
1743 || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX)
1744 {
1745 rta_addattr_l (rta, 4096, RTA_GATEWAY,
1746 &nexthop->gate.ipv4, bytelen);
1747 rtnh->rtnh_len += sizeof (struct rtattr) + 4;
1748
1749 if (nexthop->src.ipv4.s_addr)
1750 src = &nexthop->src;
1751
1752 if (IS_ZEBRA_DEBUG_KERNEL)
1753 zlog_debug("netlink_route_multipath() (multihop): "
1754 "nexthop via %s if %u",
1755 inet_ntoa (nexthop->gate.ipv4),
1756 nexthop->ifindex);
1757 }
1758 #ifdef HAVE_IPV6
1759 if (nexthop->type == NEXTHOP_TYPE_IPV6
1760 || nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME
1761 || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX)
1762 {
1763 rta_addattr_l (rta, 4096, RTA_GATEWAY,
1764 &nexthop->gate.ipv6, bytelen);
1765
1766 if (IS_ZEBRA_DEBUG_KERNEL)
1767 zlog_debug("netlink_route_multipath() (multihop): "
1768 "nexthop via %s if %u",
1769 inet6_ntoa (nexthop->gate.ipv6),
1770 nexthop->ifindex);
1771 }
1772 #endif /* HAVE_IPV6 */
1773 /* ifindex */
1774 if (nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX
1775 || nexthop->type == NEXTHOP_TYPE_IFINDEX
1776 || nexthop->type == NEXTHOP_TYPE_IFNAME)
1777 {
1778 rtnh->rtnh_ifindex = nexthop->ifindex;
1779 if (nexthop->src.ipv4.s_addr)
1780 src = &nexthop->src;
1781 if (IS_ZEBRA_DEBUG_KERNEL)
1782 zlog_debug("netlink_route_multipath() (multihop): "
1783 "nexthop via if %u", nexthop->ifindex);
1784 }
1785 else if (nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME
1786 || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX)
1787 {
1788 rtnh->rtnh_ifindex = nexthop->ifindex;
1789
1790 if (IS_ZEBRA_DEBUG_KERNEL)
1791 zlog_debug("netlink_route_multipath() (multihop): "
1792 "nexthop via if %u", nexthop->ifindex);
1793 }
1794 else
1795 {
1796 rtnh->rtnh_ifindex = 0;
1797 }
1798 }
1799 rtnh = RTNH_NEXT (rtnh);
1800
1801 if (cmd == RTM_NEWROUTE)
1802 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1803 }
1804 }
1805 if (src)
1806 addattr_l (&req.n, sizeof req, RTA_PREFSRC, &src->ipv4, bytelen);
1807
1808 if (rta->rta_len > RTA_LENGTH (0))
1809 addattr_l (&req.n, 1024, RTA_MULTIPATH, RTA_DATA (rta),
1810 RTA_PAYLOAD (rta));
1811 }
1812
1813 /* If there is no useful nexthop then return. */
1814 if (nexthop_num == 0)
1815 {
1816 if (IS_ZEBRA_DEBUG_KERNEL)
1817 zlog_debug ("netlink_route_multipath(): No useful nexthop.");
1818 return 0;
1819 }
1820
1821 skip:
1822
1823 /* Destination netlink address. */
1824 memset (&snl, 0, sizeof snl);
1825 snl.nl_family = AF_NETLINK;
1826
1827 /* Talk to netlink socket. */
1828 return netlink_talk (&req.n, &netlink_cmd);
1829 }
1830
1831 int
1832 kernel_add_ipv4 (struct prefix *p, struct rib *rib)
1833 {
1834 return netlink_route_multipath (RTM_NEWROUTE, p, rib, AF_INET);
1835 }
1836
1837 int
1838 kernel_delete_ipv4 (struct prefix *p, struct rib *rib)
1839 {
1840 return netlink_route_multipath (RTM_DELROUTE, p, rib, AF_INET);
1841 }
1842
1843 #ifdef HAVE_IPV6
1844 int
1845 kernel_add_ipv6 (struct prefix *p, struct rib *rib)
1846 {
1847 return netlink_route_multipath (RTM_NEWROUTE, p, rib, AF_INET6);
1848 }
1849
1850 int
1851 kernel_delete_ipv6 (struct prefix *p, struct rib *rib)
1852 {
1853 return netlink_route_multipath (RTM_DELROUTE, p, rib, AF_INET6);
1854 }
1855
1856 /* Delete IPv6 route from the kernel. */
1857 int
1858 kernel_delete_ipv6_old (struct prefix_ipv6 *dest, struct in6_addr *gate,
1859 unsigned int index, int flags, int table)
1860 {
1861 return netlink_route (RTM_DELROUTE, AF_INET6, &dest->prefix,
1862 dest->prefixlen, gate, index, flags, table);
1863 }
1864 #endif /* HAVE_IPV6 */
1865 \f
1866 /* Interface address modification. */
1867 int
1868 netlink_address (int cmd, int family, struct interface *ifp,
1869 struct connected *ifc)
1870 {
1871 int bytelen;
1872 struct prefix *p;
1873
1874 struct
1875 {
1876 struct nlmsghdr n;
1877 struct ifaddrmsg ifa;
1878 char buf[1024];
1879 } req;
1880
1881 p = ifc->address;
1882 memset (&req, 0, sizeof req);
1883
1884 bytelen = (family == AF_INET ? 4 : 16);
1885
1886 req.n.nlmsg_len = NLMSG_LENGTH (sizeof (struct ifaddrmsg));
1887 req.n.nlmsg_flags = NLM_F_REQUEST;
1888 req.n.nlmsg_type = cmd;
1889 req.ifa.ifa_family = family;
1890
1891 req.ifa.ifa_index = ifp->ifindex;
1892 req.ifa.ifa_prefixlen = p->prefixlen;
1893
1894 addattr_l (&req.n, sizeof req, IFA_LOCAL, &p->u.prefix, bytelen);
1895
1896 if (family == AF_INET && cmd == RTM_NEWADDR)
1897 {
1898 if (!CONNECTED_PEER(ifc) && ifc->destination)
1899 {
1900 p = ifc->destination;
1901 addattr_l (&req.n, sizeof req, IFA_BROADCAST, &p->u.prefix,
1902 bytelen);
1903 }
1904 }
1905
1906 if (CHECK_FLAG (ifc->flags, ZEBRA_IFA_SECONDARY))
1907 SET_FLAG (req.ifa.ifa_flags, IFA_F_SECONDARY);
1908
1909 if (ifc->label)
1910 addattr_l (&req.n, sizeof req, IFA_LABEL, ifc->label,
1911 strlen (ifc->label) + 1);
1912
1913 return netlink_talk (&req.n, &netlink_cmd);
1914 }
1915
1916 int
1917 kernel_address_add_ipv4 (struct interface *ifp, struct connected *ifc)
1918 {
1919 return netlink_address (RTM_NEWADDR, AF_INET, ifp, ifc);
1920 }
1921
1922 int
1923 kernel_address_delete_ipv4 (struct interface *ifp, struct connected *ifc)
1924 {
1925 return netlink_address (RTM_DELADDR, AF_INET, ifp, ifc);
1926 }
1927
1928
1929 extern struct thread_master *master;
1930
1931 /* Kernel route reflection. */
1932 int
1933 kernel_read (struct thread *thread)
1934 {
1935 int ret;
1936 int sock;
1937
1938 sock = THREAD_FD (thread);
1939 ret = netlink_parse_info (netlink_information_fetch, &netlink);
1940 thread_add_read (zebrad.master, kernel_read, NULL, netlink.sock);
1941
1942 return 0;
1943 }
1944
1945 /* Exported interface function. This function simply calls
1946 netlink_socket (). */
1947 void
1948 kernel_init (void)
1949 {
1950 unsigned long groups;
1951
1952 groups = RTMGRP_LINK | RTMGRP_IPV4_ROUTE | RTMGRP_IPV4_IFADDR;
1953 #ifdef HAVE_IPV6
1954 groups |= RTMGRP_IPV6_ROUTE | RTMGRP_IPV6_IFADDR;
1955 #endif /* HAVE_IPV6 */
1956 netlink_socket (&netlink, groups);
1957 netlink_socket (&netlink_cmd, 0);
1958
1959 /* Register kernel socket. */
1960 if (netlink.sock > 0)
1961 thread_add_read (zebrad.master, kernel_read, NULL, netlink.sock);
1962 }