]> git.proxmox.com Git - mirror_frr.git/blob - zebra/rt_netlink.c
ospf6d: ospfv3-abr-ecmp-support.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 u_char zebra_flags = 0;
843
844 char anyaddr[16] = { 0 };
845
846 int index;
847 int table;
848 int metric;
849
850 void *dest;
851 void *gate;
852 void *src;
853
854 rtm = NLMSG_DATA (h);
855
856 if (!(h->nlmsg_type == RTM_NEWROUTE || h->nlmsg_type == RTM_DELROUTE))
857 {
858 /* If this is not route add/delete message print warning. */
859 zlog_warn ("Kernel message: %d\n", h->nlmsg_type);
860 return 0;
861 }
862
863 /* Connected route. */
864 if (IS_ZEBRA_DEBUG_KERNEL)
865 zlog_debug ("%s %s %s proto %s",
866 h->nlmsg_type ==
867 RTM_NEWROUTE ? "RTM_NEWROUTE" : "RTM_DELROUTE",
868 rtm->rtm_family == AF_INET ? "ipv4" : "ipv6",
869 rtm->rtm_type == RTN_UNICAST ? "unicast" : "multicast",
870 lookup (rtproto_str, rtm->rtm_protocol));
871
872 if (rtm->rtm_type != RTN_UNICAST)
873 {
874 return 0;
875 }
876
877 table = rtm->rtm_table;
878 if (table != RT_TABLE_MAIN && table != zebrad.rtm_table_default)
879 {
880 return 0;
881 }
882
883 len = h->nlmsg_len - NLMSG_LENGTH (sizeof (struct rtmsg));
884 if (len < 0)
885 return -1;
886
887 memset (tb, 0, sizeof tb);
888 netlink_parse_rtattr (tb, RTA_MAX, RTM_RTA (rtm), len);
889
890 if (rtm->rtm_flags & RTM_F_CLONED)
891 return 0;
892 if (rtm->rtm_protocol == RTPROT_REDIRECT)
893 return 0;
894 if (rtm->rtm_protocol == RTPROT_KERNEL)
895 return 0;
896
897 if (rtm->rtm_protocol == RTPROT_ZEBRA && h->nlmsg_type == RTM_NEWROUTE)
898 return 0;
899 if (rtm->rtm_protocol == RTPROT_ZEBRA)
900 SET_FLAG(zebra_flags, ZEBRA_FLAG_SELFROUTE);
901
902 if (rtm->rtm_src_len != 0)
903 {
904 zlog_warn ("netlink_route_change(): no src len");
905 return 0;
906 }
907
908 index = 0;
909 metric = 0;
910 dest = NULL;
911 gate = NULL;
912 src = NULL;
913
914 if (tb[RTA_OIF])
915 index = *(int *) RTA_DATA (tb[RTA_OIF]);
916
917 if (tb[RTA_DST])
918 dest = RTA_DATA (tb[RTA_DST]);
919 else
920 dest = anyaddr;
921
922 if (tb[RTA_GATEWAY])
923 gate = RTA_DATA (tb[RTA_GATEWAY]);
924
925 if (tb[RTA_PREFSRC])
926 src = RTA_DATA (tb[RTA_PREFSRC]);
927
928 if (h->nlmsg_type == RTM_NEWROUTE && tb[RTA_PRIORITY])
929 metric = *(int *) RTA_DATA(tb[RTA_PRIORITY]);
930
931 if (rtm->rtm_family == AF_INET)
932 {
933 struct prefix_ipv4 p;
934 p.family = AF_INET;
935 memcpy (&p.prefix, dest, 4);
936 p.prefixlen = rtm->rtm_dst_len;
937
938 if (IS_ZEBRA_DEBUG_KERNEL)
939 {
940 if (h->nlmsg_type == RTM_NEWROUTE)
941 zlog_debug ("RTM_NEWROUTE %s/%d",
942 inet_ntoa (p.prefix), p.prefixlen);
943 else
944 zlog_debug ("RTM_DELROUTE %s/%d",
945 inet_ntoa (p.prefix), p.prefixlen);
946 }
947
948 if (h->nlmsg_type == RTM_NEWROUTE)
949 {
950 if (!tb[RTA_MULTIPATH])
951 rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, src, index, table,
952 metric, 0, SAFI_UNICAST);
953 else
954 {
955 /* This is a multipath route */
956
957 struct rib *rib;
958 struct rtnexthop *rtnh =
959 (struct rtnexthop *) RTA_DATA (tb[RTA_MULTIPATH]);
960
961 len = RTA_PAYLOAD (tb[RTA_MULTIPATH]);
962
963 rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
964 rib->type = ZEBRA_ROUTE_KERNEL;
965 rib->distance = 0;
966 rib->flags = 0;
967 rib->metric = metric;
968 rib->table = table;
969 rib->nexthop_num = 0;
970 rib->uptime = time (NULL);
971
972 for (;;)
973 {
974 if (len < (int) sizeof (*rtnh) || rtnh->rtnh_len > len)
975 break;
976
977 rib->nexthop_num++;
978 index = rtnh->rtnh_ifindex;
979 gate = 0;
980 if (rtnh->rtnh_len > sizeof (*rtnh))
981 {
982 memset (tb, 0, sizeof (tb));
983 netlink_parse_rtattr (tb, RTA_MAX, RTNH_DATA (rtnh),
984 rtnh->rtnh_len - sizeof (*rtnh));
985 if (tb[RTA_GATEWAY])
986 gate = RTA_DATA (tb[RTA_GATEWAY]);
987 }
988
989 if (gate)
990 {
991 if (index)
992 nexthop_ipv4_ifindex_add (rib, gate, src, index);
993 else
994 nexthop_ipv4_add (rib, gate, src);
995 }
996 else
997 nexthop_ifindex_add (rib, index);
998
999 len -= NLMSG_ALIGN(rtnh->rtnh_len);
1000 rtnh = RTNH_NEXT(rtnh);
1001 }
1002
1003 if (rib->nexthop_num == 0)
1004 XFREE (MTYPE_RIB, rib);
1005 else
1006 rib_add_ipv4_multipath (&p, rib, SAFI_UNICAST);
1007 }
1008 }
1009 else
1010 rib_delete_ipv4 (ZEBRA_ROUTE_KERNEL, zebra_flags, &p, gate, index,
1011 table, SAFI_UNICAST);
1012 }
1013
1014 #ifdef HAVE_IPV6
1015 if (rtm->rtm_family == AF_INET6)
1016 {
1017 struct prefix_ipv6 p;
1018 char buf[BUFSIZ];
1019
1020 p.family = AF_INET6;
1021 memcpy (&p.prefix, dest, 16);
1022 p.prefixlen = rtm->rtm_dst_len;
1023
1024 if (IS_ZEBRA_DEBUG_KERNEL)
1025 {
1026 if (h->nlmsg_type == RTM_NEWROUTE)
1027 zlog_debug ("RTM_NEWROUTE %s/%d",
1028 inet_ntop (AF_INET6, &p.prefix, buf, BUFSIZ),
1029 p.prefixlen);
1030 else
1031 zlog_debug ("RTM_DELROUTE %s/%d",
1032 inet_ntop (AF_INET6, &p.prefix, buf, BUFSIZ),
1033 p.prefixlen);
1034 }
1035
1036 if (h->nlmsg_type == RTM_NEWROUTE)
1037 rib_add_ipv6 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, index, table, metric, 0, SAFI_UNICAST);
1038 else
1039 rib_delete_ipv6 (ZEBRA_ROUTE_KERNEL, zebra_flags, &p, gate, index,
1040 table, SAFI_UNICAST);
1041 }
1042 #endif /* HAVE_IPV6 */
1043
1044 return 0;
1045 }
1046
1047 static int
1048 netlink_link_change (struct sockaddr_nl *snl, struct nlmsghdr *h)
1049 {
1050 int len;
1051 struct ifinfomsg *ifi;
1052 struct rtattr *tb[IFLA_MAX + 1];
1053 struct interface *ifp;
1054 char *name;
1055
1056 ifi = NLMSG_DATA (h);
1057
1058 if (!(h->nlmsg_type == RTM_NEWLINK || h->nlmsg_type == RTM_DELLINK))
1059 {
1060 /* If this is not link add/delete message so print warning. */
1061 zlog_warn ("netlink_link_change: wrong kernel message %d\n",
1062 h->nlmsg_type);
1063 return 0;
1064 }
1065
1066 len = h->nlmsg_len - NLMSG_LENGTH (sizeof (struct ifinfomsg));
1067 if (len < 0)
1068 return -1;
1069
1070 /* Looking up interface name. */
1071 memset (tb, 0, sizeof tb);
1072 netlink_parse_rtattr (tb, IFLA_MAX, IFLA_RTA (ifi), len);
1073
1074 #ifdef IFLA_WIRELESS
1075 /* check for wireless messages to ignore */
1076 if ((tb[IFLA_WIRELESS] != NULL) && (ifi->ifi_change == 0))
1077 {
1078 if (IS_ZEBRA_DEBUG_KERNEL)
1079 zlog_debug ("%s: ignoring IFLA_WIRELESS message", __func__);
1080 return 0;
1081 }
1082 #endif /* IFLA_WIRELESS */
1083
1084 if (tb[IFLA_IFNAME] == NULL)
1085 return -1;
1086 name = (char *) RTA_DATA (tb[IFLA_IFNAME]);
1087
1088 /* Add interface. */
1089 if (h->nlmsg_type == RTM_NEWLINK)
1090 {
1091 ifp = if_lookup_by_name (name);
1092
1093 if (ifp == NULL || !CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE))
1094 {
1095 if (ifp == NULL)
1096 ifp = if_get_by_name (name);
1097
1098 set_ifindex(ifp, ifi->ifi_index);
1099 ifp->flags = ifi->ifi_flags & 0x0000fffff;
1100 ifp->mtu6 = ifp->mtu = *(int *) RTA_DATA (tb[IFLA_MTU]);
1101 ifp->metric = 0;
1102
1103 netlink_interface_update_hw_addr (tb, ifp);
1104
1105 /* If new link is added. */
1106 if_add_update (ifp);
1107 }
1108 else
1109 {
1110 /* Interface status change. */
1111 set_ifindex(ifp, ifi->ifi_index);
1112 ifp->mtu6 = ifp->mtu = *(int *) RTA_DATA (tb[IFLA_MTU]);
1113 ifp->metric = 0;
1114
1115 netlink_interface_update_hw_addr (tb, ifp);
1116
1117 if (if_is_no_ptm_operative (ifp))
1118 {
1119 ifp->flags = ifi->ifi_flags & 0x0000fffff;
1120 if (!if_is_no_ptm_operative (ifp))
1121 if_down (ifp);
1122 else if (if_is_operative (ifp))
1123 /* Must notify client daemons of new interface status. */
1124 zebra_interface_up_update (ifp);
1125 }
1126 else
1127 {
1128 ifp->flags = ifi->ifi_flags & 0x0000fffff;
1129 if (if_is_operative (ifp))
1130 if_up (ifp);
1131 }
1132 }
1133 }
1134 else
1135 {
1136 /* RTM_DELLINK. */
1137 ifp = if_lookup_by_name (name);
1138
1139 if (ifp == NULL)
1140 {
1141 zlog (NULL, LOG_WARNING, "interface %s is deleted but can't find",
1142 name);
1143 return 0;
1144 }
1145
1146 if_delete_update (ifp);
1147 }
1148
1149 return 0;
1150 }
1151
1152 static int
1153 netlink_information_fetch (struct sockaddr_nl *snl, struct nlmsghdr *h)
1154 {
1155 /* JF: Ignore messages that aren't from the kernel */
1156 if ( snl->nl_pid != 0 )
1157 {
1158 zlog ( NULL, LOG_ERR, "Ignoring message from pid %u", snl->nl_pid );
1159 return 0;
1160 }
1161
1162 switch (h->nlmsg_type)
1163 {
1164 case RTM_NEWROUTE:
1165 return netlink_route_change (snl, h);
1166 break;
1167 case RTM_DELROUTE:
1168 return netlink_route_change (snl, h);
1169 break;
1170 case RTM_NEWLINK:
1171 return netlink_link_change (snl, h);
1172 break;
1173 case RTM_DELLINK:
1174 return netlink_link_change (snl, h);
1175 break;
1176 case RTM_NEWADDR:
1177 return netlink_interface_addr (snl, h);
1178 break;
1179 case RTM_DELADDR:
1180 return netlink_interface_addr (snl, h);
1181 break;
1182 default:
1183 zlog_warn ("Unknown netlink nlmsg_type %d\n", h->nlmsg_type);
1184 break;
1185 }
1186 return 0;
1187 }
1188
1189 /* Interface lookup by netlink socket. */
1190 int
1191 interface_lookup_netlink (void)
1192 {
1193 int ret;
1194
1195 /* Get interface information. */
1196 ret = netlink_request (AF_PACKET, RTM_GETLINK, &netlink_cmd);
1197 if (ret < 0)
1198 return ret;
1199 ret = netlink_parse_info (netlink_interface, &netlink_cmd);
1200 if (ret < 0)
1201 return ret;
1202
1203 /* Get IPv4 address of the interfaces. */
1204 ret = netlink_request (AF_INET, RTM_GETADDR, &netlink_cmd);
1205 if (ret < 0)
1206 return ret;
1207 ret = netlink_parse_info (netlink_interface_addr, &netlink_cmd);
1208 if (ret < 0)
1209 return ret;
1210
1211 #ifdef HAVE_IPV6
1212 /* Get IPv6 address of the interfaces. */
1213 ret = netlink_request (AF_INET6, RTM_GETADDR, &netlink_cmd);
1214 if (ret < 0)
1215 return ret;
1216 ret = netlink_parse_info (netlink_interface_addr, &netlink_cmd);
1217 if (ret < 0)
1218 return ret;
1219 #endif /* HAVE_IPV6 */
1220
1221 return 0;
1222 }
1223
1224 /* Routing table read function using netlink interface. Only called
1225 bootstrap time. */
1226 int
1227 netlink_route_read (void)
1228 {
1229 int ret;
1230
1231 /* Get IPv4 routing table. */
1232 ret = netlink_request (AF_INET, RTM_GETROUTE, &netlink_cmd);
1233 if (ret < 0)
1234 return ret;
1235 ret = netlink_parse_info (netlink_routing_table, &netlink_cmd);
1236 if (ret < 0)
1237 return ret;
1238
1239 #ifdef HAVE_IPV6
1240 /* Get IPv6 routing table. */
1241 ret = netlink_request (AF_INET6, RTM_GETROUTE, &netlink_cmd);
1242 if (ret < 0)
1243 return ret;
1244 ret = netlink_parse_info (netlink_routing_table, &netlink_cmd);
1245 if (ret < 0)
1246 return ret;
1247 #endif /* HAVE_IPV6 */
1248
1249 return 0;
1250 }
1251
1252 /* Utility function comes from iproute2.
1253 Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru> */
1254 int
1255 addattr_l (struct nlmsghdr *n, int maxlen, int type, void *data, int alen)
1256 {
1257 int len;
1258 struct rtattr *rta;
1259
1260 len = RTA_LENGTH (alen);
1261
1262 if (NLMSG_ALIGN (n->nlmsg_len) + len > maxlen)
1263 return -1;
1264
1265 rta = (struct rtattr *) (((char *) n) + NLMSG_ALIGN (n->nlmsg_len));
1266 rta->rta_type = type;
1267 rta->rta_len = len;
1268 memcpy (RTA_DATA (rta), data, alen);
1269 n->nlmsg_len = NLMSG_ALIGN (n->nlmsg_len) + len;
1270
1271 return 0;
1272 }
1273
1274 int
1275 rta_addattr_l (struct rtattr *rta, int maxlen, int type, void *data, int alen)
1276 {
1277 int len;
1278 struct rtattr *subrta;
1279
1280 len = RTA_LENGTH (alen);
1281
1282 if (RTA_ALIGN (rta->rta_len) + len > maxlen)
1283 return -1;
1284
1285 subrta = (struct rtattr *) (((char *) rta) + RTA_ALIGN (rta->rta_len));
1286 subrta->rta_type = type;
1287 subrta->rta_len = len;
1288 memcpy (RTA_DATA (subrta), data, alen);
1289 rta->rta_len = NLMSG_ALIGN (rta->rta_len) + len;
1290
1291 return 0;
1292 }
1293
1294 /* Utility function comes from iproute2.
1295 Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru> */
1296 int
1297 addattr32 (struct nlmsghdr *n, int maxlen, int type, int data)
1298 {
1299 int len;
1300 struct rtattr *rta;
1301
1302 len = RTA_LENGTH (4);
1303
1304 if (NLMSG_ALIGN (n->nlmsg_len) + len > maxlen)
1305 return -1;
1306
1307 rta = (struct rtattr *) (((char *) n) + NLMSG_ALIGN (n->nlmsg_len));
1308 rta->rta_type = type;
1309 rta->rta_len = len;
1310 memcpy (RTA_DATA (rta), &data, 4);
1311 n->nlmsg_len = NLMSG_ALIGN (n->nlmsg_len) + len;
1312
1313 return 0;
1314 }
1315
1316 static int
1317 netlink_talk_filter (struct sockaddr_nl *snl, struct nlmsghdr *h)
1318 {
1319 zlog_warn ("netlink_talk: ignoring message type 0x%04x", h->nlmsg_type);
1320 return 0;
1321 }
1322
1323 /* sendmsg() to netlink socket then recvmsg(). */
1324 static int
1325 netlink_talk (struct nlmsghdr *n, struct nlsock *nl)
1326 {
1327 int status;
1328 struct sockaddr_nl snl;
1329 struct iovec iov = {
1330 .iov_base = (void *) n,
1331 .iov_len = n->nlmsg_len
1332 };
1333 struct msghdr msg = {
1334 .msg_name = (void *) &snl,
1335 .msg_namelen = sizeof snl,
1336 .msg_iov = &iov,
1337 .msg_iovlen = 1,
1338 };
1339 int save_errno;
1340
1341 memset (&snl, 0, sizeof snl);
1342 snl.nl_family = AF_NETLINK;
1343
1344 n->nlmsg_seq = ++nl->seq;
1345
1346 /* Request an acknowledgement by setting NLM_F_ACK */
1347 n->nlmsg_flags |= NLM_F_ACK;
1348
1349 if (IS_ZEBRA_DEBUG_KERNEL)
1350 zlog_debug ("netlink_talk: %s type %s(%u), seq=%u", nl->name,
1351 lookup (nlmsg_str, n->nlmsg_type), n->nlmsg_type,
1352 n->nlmsg_seq);
1353
1354 /* Send message to netlink interface. */
1355 if (zserv_privs.change (ZPRIVS_RAISE))
1356 zlog (NULL, LOG_ERR, "Can't raise privileges");
1357 status = sendmsg (nl->sock, &msg, 0);
1358 save_errno = errno;
1359 if (zserv_privs.change (ZPRIVS_LOWER))
1360 zlog (NULL, LOG_ERR, "Can't lower privileges");
1361
1362 if (status < 0)
1363 {
1364 zlog (NULL, LOG_ERR, "netlink_talk sendmsg() error: %s",
1365 safe_strerror (save_errno));
1366 return -1;
1367 }
1368
1369
1370 /*
1371 * Get reply from netlink socket.
1372 * The reply should either be an acknowlegement or an error.
1373 */
1374 return netlink_parse_info (netlink_talk_filter, nl);
1375 }
1376
1377 /* Routing table change via netlink interface. */
1378 static int
1379 netlink_route (int cmd, int family, void *dest, int length, void *gate,
1380 int index, int zebra_flags, int table)
1381 {
1382 int ret;
1383 int bytelen;
1384 struct sockaddr_nl snl;
1385 int discard;
1386
1387 struct
1388 {
1389 struct nlmsghdr n;
1390 struct rtmsg r;
1391 char buf[NL_PKT_BUF_SIZE];
1392 } req;
1393
1394 memset (&req, 0, sizeof req - NL_PKT_BUF_SIZE);
1395
1396 bytelen = (family == AF_INET ? 4 : 16);
1397
1398 req.n.nlmsg_len = NLMSG_LENGTH (sizeof (struct rtmsg));
1399 req.n.nlmsg_flags = NLM_F_CREATE | NLM_F_REQUEST;
1400 req.n.nlmsg_type = cmd;
1401 req.r.rtm_family = family;
1402 req.r.rtm_table = table;
1403 req.r.rtm_dst_len = length;
1404 req.r.rtm_protocol = RTPROT_ZEBRA;
1405 req.r.rtm_scope = RT_SCOPE_UNIVERSE;
1406
1407 if ((zebra_flags & ZEBRA_FLAG_BLACKHOLE)
1408 || (zebra_flags & ZEBRA_FLAG_REJECT))
1409 discard = 1;
1410 else
1411 discard = 0;
1412
1413 if (cmd == RTM_NEWROUTE)
1414 {
1415 if (discard)
1416 {
1417 if (zebra_flags & ZEBRA_FLAG_BLACKHOLE)
1418 req.r.rtm_type = RTN_BLACKHOLE;
1419 else if (zebra_flags & ZEBRA_FLAG_REJECT)
1420 req.r.rtm_type = RTN_UNREACHABLE;
1421 else
1422 assert (RTN_BLACKHOLE != RTN_UNREACHABLE); /* false */
1423
1424 if (IS_ZEBRA_DEBUG_KERNEL)
1425 zlog_debug ("%s: Adding discard route for family %s\n",
1426 __FUNCTION__, family == AF_INET ? "IPv4" : "IPv6");
1427 }
1428 else
1429 req.r.rtm_type = RTN_UNICAST;
1430 }
1431
1432 if (dest)
1433 addattr_l (&req.n, sizeof req, RTA_DST, dest, bytelen);
1434
1435 if (!discard)
1436 {
1437 if (gate)
1438 addattr_l (&req.n, sizeof req, RTA_GATEWAY, gate, bytelen);
1439 if (index > 0)
1440 addattr32 (&req.n, sizeof req, RTA_OIF, index);
1441 }
1442
1443 /* Destination netlink address. */
1444 memset (&snl, 0, sizeof snl);
1445 snl.nl_family = AF_NETLINK;
1446
1447 /* Talk to netlink socket. */
1448 ret = netlink_talk (&req.n, &netlink_cmd);
1449 if (ret < 0)
1450 return -1;
1451
1452 return 0;
1453 }
1454
1455 /* This function takes a nexthop as argument and adds
1456 * the appropriate netlink attributes to an existing
1457 * netlink message.
1458 *
1459 * @param routedesc: Human readable description of route type
1460 * (direct/recursive, single-/multipath)
1461 * @param bytelen: Length of addresses in bytes.
1462 * @param nexthop: Nexthop information
1463 * @param nlmsg: nlmsghdr structure to fill in.
1464 * @param req_size: The size allocated for the message.
1465 */
1466 static void
1467 _netlink_route_build_singlepath(
1468 const char *routedesc,
1469 int bytelen,
1470 struct nexthop *nexthop,
1471 struct nlmsghdr *nlmsg,
1472 struct rtmsg *rtmsg,
1473 size_t req_size,
1474 int cmd)
1475 {
1476 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ONLINK))
1477 rtmsg->rtm_flags |= RTNH_F_ONLINK;
1478 if (nexthop->type == NEXTHOP_TYPE_IPV4
1479 || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX)
1480 {
1481 addattr_l (nlmsg, req_size, RTA_GATEWAY,
1482 &nexthop->gate.ipv4, bytelen);
1483
1484 if (nexthop->rmap_src.ipv4.s_addr && (cmd == RTM_NEWROUTE))
1485 addattr_l (nlmsg, req_size, RTA_PREFSRC,
1486 &nexthop->rmap_src.ipv4, bytelen);
1487 else if (nexthop->src.ipv4.s_addr && (cmd == RTM_NEWROUTE))
1488 addattr_l (nlmsg, req_size, RTA_PREFSRC,
1489 &nexthop->src.ipv4, bytelen);
1490
1491 if (IS_ZEBRA_DEBUG_KERNEL)
1492 zlog_debug("netlink_route_multipath() (%s): "
1493 "nexthop via %s if %u",
1494 routedesc,
1495 inet_ntoa (nexthop->gate.ipv4),
1496 nexthop->ifindex);
1497 }
1498 #ifdef HAVE_IPV6
1499 if (nexthop->type == NEXTHOP_TYPE_IPV6
1500 || nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME
1501 || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX)
1502 {
1503 addattr_l (nlmsg, req_size, RTA_GATEWAY,
1504 &nexthop->gate.ipv6, bytelen);
1505
1506 if (IS_ZEBRA_DEBUG_KERNEL)
1507 zlog_debug("netlink_route_multipath() (%s): "
1508 "nexthop via %s if %u",
1509 routedesc,
1510 inet6_ntoa (nexthop->gate.ipv6),
1511 nexthop->ifindex);
1512 }
1513 #endif /* HAVE_IPV6 */
1514 if (nexthop->type == NEXTHOP_TYPE_IFINDEX
1515 || nexthop->type == NEXTHOP_TYPE_IFNAME
1516 || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX)
1517 {
1518 addattr32 (nlmsg, req_size, RTA_OIF, nexthop->ifindex);
1519
1520 if (nexthop->rmap_src.ipv4.s_addr && (cmd == RTM_NEWROUTE))
1521 addattr_l (nlmsg, req_size, RTA_PREFSRC,
1522 &nexthop->rmap_src.ipv4, bytelen);
1523 else if (nexthop->src.ipv4.s_addr && (cmd == RTM_NEWROUTE))
1524 addattr_l (nlmsg, req_size, RTA_PREFSRC,
1525 &nexthop->src.ipv4, bytelen);
1526
1527 if (IS_ZEBRA_DEBUG_KERNEL)
1528 zlog_debug("netlink_route_multipath() (%s): "
1529 "nexthop via if %u", routedesc, nexthop->ifindex);
1530 }
1531
1532 if (nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX
1533 || nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME)
1534 {
1535 addattr32 (nlmsg, req_size, RTA_OIF, nexthop->ifindex);
1536
1537 if (IS_ZEBRA_DEBUG_KERNEL)
1538 zlog_debug("netlink_route_multipath() (%s): "
1539 "nexthop via if %u", routedesc, nexthop->ifindex);
1540 }
1541 }
1542
1543 /* This function takes a nexthop as argument and
1544 * appends to the given rtattr/rtnexthop pair the
1545 * representation of the nexthop. If the nexthop
1546 * defines a preferred source, the src parameter
1547 * will be modified to point to that src, otherwise
1548 * it will be kept unmodified.
1549 *
1550 * @param routedesc: Human readable description of route type
1551 * (direct/recursive, single-/multipath)
1552 * @param bytelen: Length of addresses in bytes.
1553 * @param nexthop: Nexthop information
1554 * @param rta: rtnetlink attribute structure
1555 * @param rtnh: pointer to an rtnetlink nexthop structure
1556 * @param src: pointer pointing to a location where
1557 * the prefsrc should be stored.
1558 */
1559 static void
1560 _netlink_route_build_multipath(
1561 const char *routedesc,
1562 int bytelen,
1563 struct nexthop *nexthop,
1564 struct rtattr *rta,
1565 struct rtnexthop *rtnh,
1566 union g_addr **src
1567 )
1568 {
1569 rtnh->rtnh_len = sizeof (*rtnh);
1570 rtnh->rtnh_flags = 0;
1571 rtnh->rtnh_hops = 0;
1572 rta->rta_len += rtnh->rtnh_len;
1573
1574 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ONLINK))
1575 rtnh->rtnh_flags |= RTNH_F_ONLINK;
1576
1577 if (nexthop->type == NEXTHOP_TYPE_IPV4
1578 || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX)
1579 {
1580 rta_addattr_l (rta, NL_PKT_BUF_SIZE, RTA_GATEWAY,
1581 &nexthop->gate.ipv4, bytelen);
1582 rtnh->rtnh_len += sizeof (struct rtattr) + 4;
1583
1584 if (nexthop->rmap_src.ipv4.s_addr)
1585 *src = &nexthop->rmap_src;
1586 else if (nexthop->src.ipv4.s_addr)
1587 *src = &nexthop->src;
1588
1589 if (IS_ZEBRA_DEBUG_KERNEL)
1590 zlog_debug("netlink_route_multipath() (%s): "
1591 "nexthop via %s if %u",
1592 routedesc,
1593 inet_ntoa (nexthop->gate.ipv4),
1594 nexthop->ifindex);
1595 }
1596 #ifdef HAVE_IPV6
1597 if (nexthop->type == NEXTHOP_TYPE_IPV6
1598 || nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME
1599 || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX)
1600 {
1601 rta_addattr_l (rta, NL_PKT_BUF_SIZE, RTA_GATEWAY,
1602 &nexthop->gate.ipv6, bytelen);
1603 rtnh->rtnh_len += sizeof (struct rtattr) + bytelen;
1604 if (IS_ZEBRA_DEBUG_KERNEL)
1605 zlog_debug("netlink_route_multipath() (%s): "
1606 "nexthop via %s if %u",
1607 routedesc,
1608 inet6_ntoa (nexthop->gate.ipv6),
1609 nexthop->ifindex);
1610 }
1611 #endif /* HAVE_IPV6 */
1612 /* ifindex */
1613 if (nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX
1614 || nexthop->type == NEXTHOP_TYPE_IFINDEX
1615 || nexthop->type == NEXTHOP_TYPE_IFNAME)
1616 {
1617 rtnh->rtnh_ifindex = nexthop->ifindex;
1618
1619 if (nexthop->rmap_src.ipv4.s_addr)
1620 *src = &nexthop->rmap_src;
1621 else if (nexthop->src.ipv4.s_addr)
1622 *src = &nexthop->src;
1623
1624 if (IS_ZEBRA_DEBUG_KERNEL)
1625 zlog_debug("netlink_route_multipath() (%s): "
1626 "nexthop via if %u", routedesc, nexthop->ifindex);
1627 }
1628 else if (nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME
1629 || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX)
1630 {
1631 rtnh->rtnh_ifindex = nexthop->ifindex;
1632
1633 if (IS_ZEBRA_DEBUG_KERNEL)
1634 zlog_debug("netlink_route_multipath() (%s): "
1635 "nexthop via if %u", routedesc, nexthop->ifindex);
1636 }
1637 else
1638 {
1639 rtnh->rtnh_ifindex = 0;
1640 }
1641 }
1642
1643 /* Log debug information for netlink_route_multipath
1644 * if debug logging is enabled.
1645 *
1646 * @param cmd: Netlink command which is to be processed
1647 * @param p: Prefix for which the change is due
1648 * @param nexthop: Nexthop which is currently processed
1649 * @param routedesc: Semantic annotation for nexthop
1650 * (recursive, multipath, etc.)
1651 * @param family: Address family which the change concerns
1652 */
1653 static void
1654 _netlink_route_debug(
1655 int cmd,
1656 struct prefix *p,
1657 struct nexthop *nexthop,
1658 const char *routedesc,
1659 int family)
1660 {
1661 if (IS_ZEBRA_DEBUG_KERNEL)
1662 {
1663 zlog_debug ("netlink_route_multipath() (%s): %s %s/%d type %s",
1664 routedesc,
1665 lookup (nlmsg_str, cmd),
1666 #ifdef HAVE_IPV6
1667 (family == AF_INET) ? inet_ntoa (p->u.prefix4) :
1668 inet6_ntoa (p->u.prefix6),
1669 #else
1670 inet_ntoa (p->u.prefix4),
1671 #endif /* HAVE_IPV6 */
1672 p->prefixlen, nexthop_type_to_str (nexthop->type));
1673 }
1674 }
1675
1676 /* Routing table change via netlink interface. */
1677 static int
1678 netlink_route_multipath (int cmd, struct prefix *p, struct rib *rib,
1679 int family)
1680 {
1681 int bytelen;
1682 struct sockaddr_nl snl;
1683 struct nexthop *nexthop = NULL, *tnexthop;
1684 int recursing;
1685 int nexthop_num;
1686 int discard;
1687 const char *routedesc;
1688 int setsrc = 0;
1689 union g_addr src;
1690
1691 struct
1692 {
1693 struct nlmsghdr n;
1694 struct rtmsg r;
1695 char buf[NL_PKT_BUF_SIZE];
1696 } req;
1697
1698 memset (&req, 0, sizeof req - NL_PKT_BUF_SIZE);
1699
1700 bytelen = (family == AF_INET ? 4 : 16);
1701
1702 req.n.nlmsg_len = NLMSG_LENGTH (sizeof (struct rtmsg));
1703 req.n.nlmsg_flags = NLM_F_CREATE | NLM_F_REQUEST;
1704 req.n.nlmsg_type = cmd;
1705 req.r.rtm_family = family;
1706 req.r.rtm_table = rib->table;
1707 req.r.rtm_dst_len = p->prefixlen;
1708 req.r.rtm_protocol = RTPROT_ZEBRA;
1709 req.r.rtm_scope = RT_SCOPE_UNIVERSE;
1710
1711 if ((rib->flags & ZEBRA_FLAG_BLACKHOLE) || (rib->flags & ZEBRA_FLAG_REJECT))
1712 discard = 1;
1713 else
1714 discard = 0;
1715
1716 if (cmd == RTM_NEWROUTE)
1717 {
1718 if (discard)
1719 {
1720 if (rib->flags & ZEBRA_FLAG_BLACKHOLE)
1721 req.r.rtm_type = RTN_BLACKHOLE;
1722 else if (rib->flags & ZEBRA_FLAG_REJECT)
1723 req.r.rtm_type = RTN_UNREACHABLE;
1724 else
1725 assert (RTN_BLACKHOLE != RTN_UNREACHABLE); /* false */
1726 }
1727 else
1728 req.r.rtm_type = RTN_UNICAST;
1729 }
1730
1731 addattr_l (&req.n, sizeof req, RTA_DST, &p->u.prefix, bytelen);
1732
1733 /* Metric. */
1734 /* Hardcode the metric for all routes coming from zebra. Metric isn't used
1735 * either by the kernel or by zebra. Its purely for calculating best path(s)
1736 * by the routing protocol and for communicating with protocol peers.
1737 */
1738 addattr32 (&req.n, sizeof req, RTA_PRIORITY, NL_DEFAULT_ROUTE_METRIC);
1739
1740 if (discard)
1741 {
1742 if (cmd == RTM_NEWROUTE)
1743 for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing))
1744 {
1745 /* We shouldn't encounter recursive nexthops on discard routes,
1746 * but it is probably better to handle that case correctly anyway.
1747 */
1748 if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
1749 continue;
1750 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1751 }
1752 goto skip;
1753 }
1754
1755 /* Count overall nexthops so we can decide whether to use singlepath
1756 * or multipath case. */
1757 nexthop_num = 0;
1758 for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing))
1759 {
1760 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
1761 continue;
1762 if (cmd == RTM_NEWROUTE && !CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE))
1763 continue;
1764 if (cmd == RTM_DELROUTE && !CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
1765 continue;
1766
1767 nexthop_num++;
1768 }
1769
1770 /* Singlepath case. */
1771 if (nexthop_num == 1 || MULTIPATH_NUM == 1)
1772 {
1773 nexthop_num = 0;
1774 for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing))
1775 {
1776 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
1777 {
1778 /* This only works for IPv4 now */
1779 if (!setsrc)
1780 {
1781 if (nexthop->rmap_src.ipv4.s_addr != 0)
1782 {
1783 src.ipv4 = nexthop->rmap_src.ipv4;
1784 setsrc = 1;
1785 }
1786 else if (nexthop->src.ipv4.s_addr != 0)
1787 {
1788 src.ipv4 = nexthop->src.ipv4;
1789 setsrc = 1;
1790 }
1791 }
1792 continue;
1793 }
1794
1795 if ((cmd == RTM_NEWROUTE
1796 && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))
1797 || (cmd == RTM_DELROUTE
1798 && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)))
1799 {
1800 routedesc = recursing ? "recursive, 1 hop" : "single hop";
1801
1802 _netlink_route_debug(cmd, p, nexthop, routedesc, family);
1803 _netlink_route_build_singlepath(routedesc, bytelen,
1804 nexthop, &req.n, &req.r,
1805 sizeof req, cmd);
1806
1807 if (cmd == RTM_NEWROUTE)
1808 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1809
1810 nexthop_num++;
1811 break;
1812 }
1813 }
1814 if (setsrc && (cmd == RTM_NEWROUTE))
1815 addattr_l (&req.n, sizeof req, RTA_PREFSRC, &src.ipv4, bytelen);
1816 }
1817 else
1818 {
1819 char buf[NL_PKT_BUF_SIZE];
1820 struct rtattr *rta = (void *) buf;
1821 struct rtnexthop *rtnh;
1822 union g_addr *src1 = NULL;
1823
1824 rta->rta_type = RTA_MULTIPATH;
1825 rta->rta_len = RTA_LENGTH (0);
1826 rtnh = RTA_DATA (rta);
1827
1828 nexthop_num = 0;
1829 for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing))
1830 {
1831 if (MULTIPATH_NUM != 0 && nexthop_num >= MULTIPATH_NUM)
1832 break;
1833
1834 if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
1835 {
1836 /* This only works for IPv4 now */
1837 if (!setsrc)
1838 {
1839 if (nexthop->rmap_src.ipv4.s_addr != 0)
1840 {
1841 src.ipv4 = nexthop->rmap_src.ipv4;
1842 setsrc = 1;
1843 }
1844 else if (nexthop->src.ipv4.s_addr != 0)
1845 {
1846 src.ipv4 = nexthop->src.ipv4;
1847 setsrc = 1;
1848 }
1849 }
1850 continue;
1851 }
1852
1853 if ((cmd == RTM_NEWROUTE
1854 && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))
1855 || (cmd == RTM_DELROUTE
1856 && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)))
1857 {
1858 routedesc = recursing ? "recursive, multihop" : "multihop";
1859 nexthop_num++;
1860
1861 _netlink_route_debug(cmd, p, nexthop,
1862 routedesc, family);
1863 _netlink_route_build_multipath(routedesc, bytelen,
1864 nexthop, rta, rtnh, &src1);
1865 rtnh = RTNH_NEXT (rtnh);
1866
1867 if (cmd == RTM_NEWROUTE)
1868 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1869
1870 if (!setsrc && src1)
1871 {
1872 src.ipv4 = src1->ipv4;
1873 setsrc = 1;
1874 }
1875 }
1876 }
1877 if (setsrc && (cmd == RTM_NEWROUTE))
1878 addattr_l (&req.n, sizeof req, RTA_PREFSRC, &src.ipv4, bytelen);
1879
1880 if (rta->rta_len > RTA_LENGTH (0))
1881 addattr_l (&req.n, NL_PKT_BUF_SIZE, RTA_MULTIPATH, RTA_DATA (rta),
1882 RTA_PAYLOAD (rta));
1883 }
1884
1885 /* If there is no useful nexthop then return. */
1886 if (nexthop_num == 0)
1887 {
1888 if (IS_ZEBRA_DEBUG_KERNEL)
1889 zlog_debug ("netlink_route_multipath(): No useful nexthop.");
1890 return 0;
1891 }
1892
1893 skip:
1894
1895 /* Destination netlink address. */
1896 memset (&snl, 0, sizeof snl);
1897 snl.nl_family = AF_NETLINK;
1898
1899 /* Talk to netlink socket. */
1900 return netlink_talk (&req.n, &netlink_cmd);
1901 }
1902
1903 int
1904 kernel_add_ipv4 (struct prefix *p, struct rib *rib)
1905 {
1906 return netlink_route_multipath (RTM_NEWROUTE, p, rib, AF_INET);
1907 }
1908
1909 int
1910 kernel_delete_ipv4 (struct prefix *p, struct rib *rib)
1911 {
1912 return netlink_route_multipath (RTM_DELROUTE, p, rib, AF_INET);
1913 }
1914
1915 #ifdef HAVE_IPV6
1916 int
1917 kernel_add_ipv6 (struct prefix *p, struct rib *rib)
1918 {
1919 {
1920 return netlink_route_multipath (RTM_NEWROUTE, p, rib, AF_INET6);
1921 }
1922 }
1923
1924 int
1925 kernel_delete_ipv6 (struct prefix *p, struct rib *rib)
1926 {
1927 {
1928 return netlink_route_multipath (RTM_DELROUTE, p, rib, AF_INET6);
1929 }
1930 }
1931
1932 /* Delete IPv6 route from the kernel. */
1933 int
1934 kernel_delete_ipv6_old (struct prefix_ipv6 *dest, struct in6_addr *gate,
1935 unsigned int index, int flags, int table)
1936 {
1937 return netlink_route (RTM_DELROUTE, AF_INET6, &dest->prefix,
1938 dest->prefixlen, gate, index, flags, table);
1939 }
1940 #endif /* HAVE_IPV6 */
1941
1942 /* Interface address modification. */
1943 static int
1944 netlink_address (int cmd, int family, struct interface *ifp,
1945 struct connected *ifc)
1946 {
1947 int bytelen;
1948 struct prefix *p;
1949
1950 struct
1951 {
1952 struct nlmsghdr n;
1953 struct ifaddrmsg ifa;
1954 char buf[NL_PKT_BUF_SIZE];
1955 } req;
1956
1957 p = ifc->address;
1958 memset (&req, 0, sizeof req - NL_PKT_BUF_SIZE);
1959
1960 bytelen = (family == AF_INET ? 4 : 16);
1961
1962 req.n.nlmsg_len = NLMSG_LENGTH (sizeof (struct ifaddrmsg));
1963 req.n.nlmsg_flags = NLM_F_REQUEST;
1964 req.n.nlmsg_type = cmd;
1965 req.ifa.ifa_family = family;
1966
1967 req.ifa.ifa_index = ifp->ifindex;
1968 req.ifa.ifa_prefixlen = p->prefixlen;
1969
1970 addattr_l (&req.n, sizeof req, IFA_LOCAL, &p->u.prefix, bytelen);
1971
1972 if (family == AF_INET && cmd == RTM_NEWADDR)
1973 {
1974 if (!CONNECTED_PEER(ifc) && ifc->destination)
1975 {
1976 p = ifc->destination;
1977 addattr_l (&req.n, sizeof req, IFA_BROADCAST, &p->u.prefix,
1978 bytelen);
1979 }
1980 }
1981
1982 if (CHECK_FLAG (ifc->flags, ZEBRA_IFA_SECONDARY))
1983 SET_FLAG (req.ifa.ifa_flags, IFA_F_SECONDARY);
1984
1985 if (ifc->label)
1986 addattr_l (&req.n, sizeof req, IFA_LABEL, ifc->label,
1987 strlen (ifc->label) + 1);
1988
1989 return netlink_talk (&req.n, &netlink_cmd);
1990 }
1991
1992 int
1993 kernel_address_add_ipv4 (struct interface *ifp, struct connected *ifc)
1994 {
1995 return netlink_address (RTM_NEWADDR, AF_INET, ifp, ifc);
1996 }
1997
1998 int
1999 kernel_address_delete_ipv4 (struct interface *ifp, struct connected *ifc)
2000 {
2001 return netlink_address (RTM_DELADDR, AF_INET, ifp, ifc);
2002 }
2003
2004
2005 extern struct thread_master *master;
2006
2007 /* Kernel route reflection. */
2008 static int
2009 kernel_read (struct thread *thread)
2010 {
2011 netlink_parse_info (netlink_information_fetch, &netlink);
2012 thread_add_read (zebrad.master, kernel_read, NULL, netlink.sock);
2013
2014 return 0;
2015 }
2016
2017 /* Filter out messages from self that occur on listener socket,
2018 caused by our actions on the command socket
2019 */
2020 static void netlink_install_filter (int sock, __u32 pid)
2021 {
2022 struct sock_filter filter[] = {
2023 /* 0: ldh [4] */
2024 BPF_STMT(BPF_LD|BPF_ABS|BPF_H, offsetof(struct nlmsghdr, nlmsg_type)),
2025 /* 1: jeq 0x18 jt 3 jf 6 */
2026 BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, htons(RTM_NEWROUTE), 1, 0),
2027 /* 2: jeq 0x19 jt 3 jf 6 */
2028 BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, htons(RTM_DELROUTE), 0, 3),
2029 /* 3: ldw [12] */
2030 BPF_STMT(BPF_LD|BPF_ABS|BPF_W, offsetof(struct nlmsghdr, nlmsg_pid)),
2031 /* 4: jeq XX jt 5 jf 6 */
2032 BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, htonl(pid), 0, 1),
2033 /* 5: ret 0 (skip) */
2034 BPF_STMT(BPF_RET|BPF_K, 0),
2035 /* 6: ret 0xffff (keep) */
2036 BPF_STMT(BPF_RET|BPF_K, 0xffff),
2037 };
2038
2039 struct sock_fprog prog = {
2040 .len = array_size(filter),
2041 .filter = filter,
2042 };
2043
2044 if (setsockopt(sock, SOL_SOCKET, SO_ATTACH_FILTER, &prog, sizeof(prog)) < 0)
2045 zlog_warn ("Can't install socket filter: %s\n", safe_strerror(errno));
2046 }
2047
2048 /* Exported interface function. This function simply calls
2049 netlink_socket (). */
2050 void
2051 kernel_init (void)
2052 {
2053 unsigned long groups;
2054
2055 groups = RTMGRP_LINK | RTMGRP_IPV4_ROUTE | RTMGRP_IPV4_IFADDR;
2056 #ifdef HAVE_IPV6
2057 groups |= RTMGRP_IPV6_ROUTE | RTMGRP_IPV6_IFADDR;
2058 #endif /* HAVE_IPV6 */
2059 netlink_socket (&netlink, groups);
2060 netlink_socket (&netlink_cmd, 0);
2061
2062 /* Register kernel socket. */
2063 if (netlink.sock > 0)
2064 {
2065 /* Only want non-blocking on the netlink event socket */
2066 if (fcntl (netlink.sock, F_SETFL, O_NONBLOCK) < 0)
2067 zlog (NULL, LOG_ERR, "Can't set %s socket flags: %s", netlink.name,
2068 safe_strerror (errno));
2069
2070 /* Set receive buffer size if it's set from command line */
2071 if (nl_rcvbufsize)
2072 netlink_recvbuf (&netlink, nl_rcvbufsize);
2073
2074 netlink_install_filter (netlink.sock, netlink_cmd.snl.nl_pid);
2075 thread_add_read (zebrad.master, kernel_read, NULL, netlink.sock);
2076 }
2077 }
2078
2079 /*
2080 * nl_msg_type_to_str
2081 */
2082 const char *
2083 nl_msg_type_to_str (uint16_t msg_type)
2084 {
2085 return lookup (nlmsg_str, msg_type);
2086 }
2087
2088 /*
2089 * nl_rtproto_to_str
2090 */
2091 const char *
2092 nl_rtproto_to_str (u_char rtproto)
2093 {
2094 return lookup (rtproto_str, rtproto);
2095 }