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