MiniDLNA update: 1.0.19.1 to 1.0.20
[tomato.git] / release / src / router / zebra / zebra / rt_netlink.c
blobbc265709309a131d694b44d56e6c5518e6587ad2
1 /* Kernel routing table updates using netlink over GNU/Linux system.
2 * Copyright (C) 1997, 98, 99 Kunihiro Ishiguro
4 * This file is part of GNU Zebra.
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.
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.
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.
22 #include <zebra.h>
24 /* Hack for GNU libc version 2. */
25 #ifndef MSG_TRUNC
26 #define MSG_TRUNC 0x20
27 #endif /* MSG_TRUNC */
29 #include "linklist.h"
30 #include "if.h"
31 #include "log.h"
32 #include "prefix.h"
33 #include "connected.h"
34 #include "table.h"
35 #include "rib.h"
37 #include "zebra/zserv.h"
38 #include "zebra/redistribute.h"
39 #include "zebra/interface.h"
40 #include "zebra/debug.h"
42 /* Socket interface to kernel */
43 struct nlsock
45 int sock;
46 int seq;
47 struct sockaddr_nl snl;
48 char *name;
49 } netlink = { -1, 0, {0}, "netlink-listen" }, /* kernel messages */
50 netlink_cmd = { -1, 0, {0}, "netlink-cmd" }, /* command channel */
51 netlink_addr = {-1, 0, {0}, "netlink-addr" }; /* address channel */
53 struct message nlmsg_str[] =
55 {RTM_NEWROUTE, "RTM_NEWROUTE"},
56 {RTM_DELROUTE, "RTM_DELROUTE"},
57 {RTM_GETROUTE, "RTM_GETROUTE"},
58 {RTM_NEWLINK, "RTM_NEWLINK"},
59 {RTM_DELLINK, "RTM_DELLINK"},
60 {RTM_GETLINK, "RTM_GETLINK"},
61 {RTM_NEWADDR, "RTM_NEWADDR"},
62 {RTM_DELADDR, "RTM_DELADDR"},
63 {RTM_GETADDR, "RTM_GETADDR"},
64 {0, NULL}
67 extern int rtm_table_default;
69 /* Make socket for Linux netlink interface. */
70 static int
71 netlink_socket (struct nlsock *nl, unsigned long groups)
73 int ret;
74 struct sockaddr_nl snl;
75 int sock;
76 int namelen;
78 sock = socket (AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
79 if (sock < 0)
81 zlog (NULL, LOG_ERR, "Can't open %s socket: %s", nl->name,
82 strerror (errno));
83 return -1;
86 ret = fcntl (sock, F_SETFL, O_NONBLOCK);
87 if (ret < 0)
89 zlog (NULL, LOG_ERR, "Can't set %s socket flags: %s", nl->name,
90 strerror (errno));
91 close (sock);
92 return -1;
95 memset (&snl, 0, sizeof snl);
96 snl.nl_family = AF_NETLINK;
97 snl.nl_groups = groups;
99 /* Bind the socket to the netlink structure for anything. */
100 ret = bind (sock, (struct sockaddr *) &snl, sizeof snl);
101 if (ret < 0)
103 zlog (NULL, LOG_ERR, "Can't bind %s socket to group 0x%x: %s",
104 nl->name, snl.nl_groups, strerror (errno));
105 close (sock);
106 return -1;
109 /* multiple netlink sockets will have different nl_pid */
110 namelen = sizeof snl;
111 ret = getsockname (sock, (struct sockaddr *) &snl, &namelen);
112 if (ret < 0 || namelen != sizeof snl)
114 zlog (NULL, LOG_ERR, "Can't get %s socket name: %s", nl->name,
115 strerror (errno));
116 close (sock);
117 return -1;
120 nl->snl = snl;
121 nl->sock = sock;
122 return ret;
125 /* Get type specified information from netlink. */
126 static int
127 netlink_request (int family, int type, struct nlsock *nl)
129 int ret;
130 struct sockaddr_nl snl;
132 struct
134 struct nlmsghdr nlh;
135 struct rtgenmsg g;
136 } req;
139 /* Check netlink socket. */
140 if (nl->sock < 0)
142 zlog (NULL, LOG_ERR, "%s socket isn't active.", nl->name);
143 return -1;
146 memset (&snl, 0, sizeof snl);
147 snl.nl_family = AF_NETLINK;
149 req.nlh.nlmsg_len = sizeof req;
150 req.nlh.nlmsg_type = type;
151 req.nlh.nlmsg_flags = NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST;
152 req.nlh.nlmsg_pid = 0;
153 req.nlh.nlmsg_seq = ++nl->seq;
154 req.g.rtgen_family = family;
156 ret = sendto (nl->sock, (void*) &req, sizeof req, 0,
157 (struct sockaddr*) &snl, sizeof snl);
158 if (ret < 0)
160 zlog (NULL, LOG_ERR, "%s sendto failed: %s", nl->name, strerror (errno));
161 return -1;
163 return 0;
166 /* Receive message from netlink interface and pass those information
167 to the given function. */
168 static int
169 netlink_parse_info (int (*filter) (struct sockaddr_nl *, struct nlmsghdr *),
170 struct nlsock *nl)
172 int status;
173 int ret = 0;
174 int error;
176 while (1)
178 char buf[4096];
179 struct iovec iov = { buf, sizeof buf };
180 struct sockaddr_nl snl;
181 struct msghdr msg = { (void*)&snl, sizeof snl, &iov, 1, NULL, 0, 0};
182 struct nlmsghdr *h;
184 status = recvmsg (nl->sock, &msg, 0);
186 if (status < 0)
188 if (errno == EINTR)
189 continue;
190 if (errno == EWOULDBLOCK || errno == EAGAIN)
191 break;
192 zlog (NULL, LOG_ERR, "%s recvmsg overrun", nl->name);
193 continue;
196 if (snl.nl_pid != 0)
198 zlog (NULL, LOG_ERR, "Ignoring non kernel message from pid %u",
199 snl.nl_pid);
200 continue;
203 if (status == 0)
205 zlog (NULL, LOG_ERR, "%s EOF", nl->name);
206 return -1;
209 if (msg.msg_namelen != sizeof snl)
211 zlog (NULL, LOG_ERR, "%s sender address length error: length %d",
212 nl->name, msg.msg_namelen);
213 return -1;
216 for (h = (struct nlmsghdr *) buf; NLMSG_OK (h, status);
217 h = NLMSG_NEXT (h, status))
219 /* Finish of reading. */
220 if (h->nlmsg_type == NLMSG_DONE)
221 return ret;
223 /* Error handling. */
224 if (h->nlmsg_type == NLMSG_ERROR)
226 struct nlmsgerr *err = (struct nlmsgerr *) NLMSG_DATA (h);
228 /* If the error field is zero, then this is an ACK */
229 if (err->error == 0)
231 if (IS_ZEBRA_DEBUG_KERNEL)
233 zlog_info("%s: %s ACK: type=%s(%u), seq=%u, pid=%d",
234 __FUNCTION__, nl->name,
235 lookup (nlmsg_str, err->msg.nlmsg_type),
236 err->msg.nlmsg_type, err->msg.nlmsg_seq,
237 err->msg.nlmsg_pid);
240 /* return if not a multipart message, otherwise continue */
241 if(!(h->nlmsg_flags & NLM_F_MULTI))
243 return 0;
245 continue;
248 if (h->nlmsg_len < NLMSG_LENGTH (sizeof (struct nlmsgerr)))
250 zlog (NULL, LOG_ERR, "%s error: message truncated",
251 nl->name);
252 return -1;
254 zlog (NULL, LOG_ERR, "%s error: %s, type=%s(%u), seq=%u, pid=%d",
255 nl->name, strerror (-err->error),
256 lookup (nlmsg_str, err->msg.nlmsg_type),
257 err->msg.nlmsg_type, err->msg.nlmsg_seq,
258 err->msg.nlmsg_pid);
260 ret = -1;
261 continue;
263 return -1;
266 /* OK we got netlink message. */
267 if (IS_ZEBRA_DEBUG_KERNEL)
268 zlog_info ("netlink_parse_info: %s type %s(%u), seq=%u, pid=%d",
269 nl->name,
270 lookup (nlmsg_str, h->nlmsg_type), h->nlmsg_type,
271 h->nlmsg_seq, h->nlmsg_pid);
273 /* skip unsolicited messages originating from command socket */
274 if (nl != &netlink_cmd && h->nlmsg_pid == netlink_cmd.snl.nl_pid)
276 if (IS_ZEBRA_DEBUG_KERNEL)
277 zlog_info ("netlink_parse_info: %s packet comes from %s",
278 nl->name, netlink_cmd.name);
279 continue;
282 error = (*filter) (&snl, h);
283 if (error < 0)
285 zlog (NULL, LOG_ERR, "%s filter function error", nl->name);
286 ret = error;
290 /* After error care. */
291 if (msg.msg_flags & MSG_TRUNC)
293 zlog (NULL, LOG_ERR, "%s error: message truncated", nl->name);
294 continue;
296 if (status)
298 zlog (NULL, LOG_ERR, "%s error: data remnant size %d", nl->name,
299 status);
300 return -1;
303 return ret;
306 /* Utility function for parse rtattr. */
307 static void
308 netlink_parse_rtattr (struct rtattr **tb, int max, struct rtattr *rta, int len)
310 while (RTA_OK(rta, len))
312 if (rta->rta_type <= max)
313 tb[rta->rta_type] = rta;
314 rta = RTA_NEXT(rta,len);
318 /* Called from interface_lookup_netlink(). This function is only used
319 during bootstrap. */
321 netlink_interface (struct sockaddr_nl *snl, struct nlmsghdr *h)
323 int len;
324 struct ifinfomsg *ifi;
325 struct rtattr *tb[IFLA_MAX + 1];
326 struct interface *ifp;
327 char *name;
328 int i;
330 ifi = NLMSG_DATA (h);
332 if (h->nlmsg_type != RTM_NEWLINK)
333 return 0;
335 len = h->nlmsg_len - NLMSG_LENGTH (sizeof (struct ifinfomsg));
336 if (len < 0)
337 return -1;
339 /* Looking up interface name. */
340 memset (tb, 0, sizeof tb);
341 netlink_parse_rtattr (tb, IFLA_MAX, IFLA_RTA (ifi), len);
342 if (tb[IFLA_IFNAME] == NULL)
343 return -1;
344 name = (char *)RTA_DATA(tb[IFLA_IFNAME]);
346 /* Add interface. */
347 ifp = if_get_by_name (name);
349 ifp->ifindex = ifi->ifi_index;
350 ifp->flags = ifi->ifi_flags & 0x0000fffff;
351 ifp->mtu = *(int *)RTA_DATA (tb[IFLA_MTU]);
352 ifp->metric = 1;
354 /* Hardware type and address. */
355 ifp->hw_type = ifi->ifi_type;
357 if (tb[IFLA_ADDRESS])
359 int hw_addr_len;
361 hw_addr_len = RTA_PAYLOAD(tb[IFLA_ADDRESS]);
363 if (hw_addr_len > INTERFACE_HWADDR_MAX)
364 zlog_warn ("Hardware address is too large: %d", hw_addr_len);
365 else
367 ifp->hw_addr_len = hw_addr_len;
368 memcpy (ifp->hw_addr, RTA_DATA(tb[IFLA_ADDRESS]), hw_addr_len);
370 for (i = 0; i < hw_addr_len; i++)
371 if (ifp->hw_addr[i] != 0)
372 break;
374 if (i == hw_addr_len)
375 ifp->hw_addr_len = 0;
376 else
377 ifp->hw_addr_len = hw_addr_len;
381 if_add_update (ifp);
383 return 0;
386 /* Lookup interface IPv4/IPv6 address. */
388 netlink_interface_addr (struct sockaddr_nl *snl, struct nlmsghdr *h)
390 int len;
391 struct ifaddrmsg *ifa;
392 struct rtattr *tb [IFA_MAX + 1];
393 struct interface *ifp;
394 void *addr = NULL;
395 void *broad = NULL;
396 u_char flags = 0;
397 char *label = NULL;
399 ifa = NLMSG_DATA (h);
401 if (ifa->ifa_family != AF_INET
402 #ifdef HAVE_IPV6
403 && ifa->ifa_family != AF_INET6
404 #endif /* HAVE_IPV6 */
406 return 0;
408 if (h->nlmsg_type != RTM_NEWADDR && h->nlmsg_type != RTM_DELADDR)
409 return 0;
411 len = h->nlmsg_len - NLMSG_LENGTH(sizeof (struct ifaddrmsg));
412 if (len < 0)
413 return -1;
415 memset (tb, 0, sizeof tb);
416 netlink_parse_rtattr (tb, IFA_MAX, IFA_RTA (ifa), len);
418 ifp = if_lookup_by_index (ifa->ifa_index);
419 if (ifp == NULL)
421 zlog_err ("netlink_interface_addr can't find interface by index %d",
422 ifa->ifa_index);
423 return -1;
426 if (tb[IFA_ADDRESS] == NULL)
427 tb[IFA_ADDRESS] = tb[IFA_LOCAL];
429 if (ifp->flags & IFF_POINTOPOINT)
431 if (tb[IFA_LOCAL])
433 addr = RTA_DATA (tb[IFA_LOCAL]);
434 if (tb[IFA_ADDRESS])
435 broad = RTA_DATA (tb[IFA_ADDRESS]);
436 else
437 broad = NULL;
439 else
441 if (tb[IFA_ADDRESS])
442 addr = RTA_DATA (tb[IFA_ADDRESS]);
443 else
444 addr = NULL;
447 else
449 if (tb[IFA_ADDRESS])
450 addr = RTA_DATA (tb[IFA_ADDRESS]);
451 else
452 addr = NULL;
454 if (tb[IFA_BROADCAST])
455 broad = RTA_DATA(tb[IFA_BROADCAST]);
456 else
457 broad = NULL;
460 /* Flags. */
461 if (ifa->ifa_flags & IFA_F_SECONDARY)
462 SET_FLAG (flags, ZEBRA_IFA_SECONDARY);
464 /* Label */
465 if (tb[IFA_LABEL])
466 label = (char *) RTA_DATA (tb[IFA_LABEL]);
468 if (ifp && label && strcmp (ifp->name, label) == 0)
469 label = NULL;
471 /* Register interface address to the interface. */
472 if (ifa->ifa_family == AF_INET)
474 if (h->nlmsg_type == RTM_NEWADDR)
475 connected_add_ipv4 (ifp, flags,
476 (struct in_addr *) addr, ifa->ifa_prefixlen,
477 (struct in_addr *) broad, label);
478 else
479 connected_delete_ipv4 (ifp, flags,
480 (struct in_addr *) addr, ifa->ifa_prefixlen,
481 (struct in_addr *) broad, label);
483 #ifdef HAVE_IPV6
484 if (ifa->ifa_family == AF_INET6)
486 if (h->nlmsg_type == RTM_NEWADDR)
487 connected_add_ipv6 (ifp,
488 (struct in6_addr *) addr, ifa->ifa_prefixlen,
489 (struct in6_addr *) broad);
490 else
491 connected_delete_ipv6 (ifp,
492 (struct in6_addr *) addr, ifa->ifa_prefixlen,
493 (struct in6_addr *) broad);
495 #endif /* HAVE_IPV6*/
497 return 0;
500 /* Looking up routing table by netlink interface. */
502 netlink_routing_table (struct sockaddr_nl *snl, struct nlmsghdr *h)
504 int len;
505 struct rtmsg *rtm;
506 struct rtattr *tb [RTA_MAX + 1];
507 u_char flags = 0;
509 char anyaddr[16] = {0};
511 int index;
512 int table;
513 void *dest;
514 void *gate;
516 rtm = NLMSG_DATA (h);
518 if (h->nlmsg_type != RTM_NEWROUTE)
519 return 0;
520 if (rtm->rtm_type != RTN_UNICAST)
521 return 0;
523 table = rtm->rtm_table;
524 #if 0 /* we weed them out later in rib_weed_tables () */
525 if (table != RT_TABLE_MAIN && table != rtm_table_default)
526 return 0;
527 #endif
529 len = h->nlmsg_len - NLMSG_LENGTH(sizeof (struct rtmsg));
530 if (len < 0)
531 return -1;
533 memset (tb, 0, sizeof tb);
534 netlink_parse_rtattr (tb, RTA_MAX, RTM_RTA (rtm), len);
536 if (rtm->rtm_flags & RTM_F_CLONED)
537 return 0;
538 if (rtm->rtm_protocol == RTPROT_REDIRECT)
539 return 0;
540 if (rtm->rtm_protocol == RTPROT_KERNEL)
541 return 0;
543 if (rtm->rtm_src_len != 0)
544 return 0;
546 /* Route which inserted by Zebra. */
547 if (rtm->rtm_protocol == RTPROT_ZEBRA)
548 flags |= ZEBRA_FLAG_SELFROUTE;
550 index = 0;
551 dest = NULL;
552 gate = NULL;
554 if (tb[RTA_OIF])
555 index = *(int *) RTA_DATA (tb[RTA_OIF]);
557 if (tb[RTA_DST])
558 dest = RTA_DATA (tb[RTA_DST]);
559 else
560 dest = anyaddr;
562 /* Multipath treatment is needed. */
563 if (tb[RTA_GATEWAY])
564 gate = RTA_DATA (tb[RTA_GATEWAY]);
566 if (rtm->rtm_family == AF_INET)
568 struct prefix_ipv4 p;
569 p.family = AF_INET;
570 memcpy (&p.prefix, dest, 4);
571 p.prefixlen = rtm->rtm_dst_len;
573 rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, flags, &p, gate, index, table, 0, 0);
575 #ifdef HAVE_IPV6
576 if (rtm->rtm_family == AF_INET6)
578 struct prefix_ipv6 p;
579 p.family = AF_INET6;
580 memcpy (&p.prefix, dest, 16);
581 p.prefixlen = rtm->rtm_dst_len;
583 rib_add_ipv6 (ZEBRA_ROUTE_KERNEL, flags, &p, gate, index, table);
585 #endif /* HAVE_IPV6 */
587 return 0;
590 struct message rtproto_str [] =
592 {RTPROT_REDIRECT, "redirect"},
593 {RTPROT_KERNEL, "kernel"},
594 {RTPROT_BOOT, "boot"},
595 {RTPROT_STATIC, "static"},
596 {RTPROT_GATED, "GateD"},
597 {RTPROT_RA, "router advertisement"},
598 {RTPROT_MRT, "MRT"},
599 {RTPROT_ZEBRA, "Zebra"},
600 #ifdef RTPROT_BIRD
601 {RTPROT_BIRD, "BIRD"},
602 #endif /* RTPROT_BIRD */
603 {0, NULL}
606 /* Routing information change from the kernel. */
608 netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h)
610 int len;
611 struct rtmsg *rtm;
612 struct rtattr *tb [RTA_MAX + 1];
614 char anyaddr[16] = {0};
616 int index;
617 int table;
618 void *dest;
619 void *gate;
621 rtm = NLMSG_DATA (h);
623 if (! (h->nlmsg_type == RTM_NEWROUTE || h->nlmsg_type == RTM_DELROUTE))
625 /* If this is not route add/delete message print warning. */
626 zlog_warn ("Kernel message: %d\n", h->nlmsg_type);
627 return 0;
630 /* Connected route. */
631 if (IS_ZEBRA_DEBUG_KERNEL)
632 zlog_info ("%s %s %s proto %s",
633 h->nlmsg_type == RTM_NEWROUTE ? "RTM_NEWROUTE" : "RTM_DELROUTE",
634 rtm->rtm_family == AF_INET ? "ipv4" : "ipv6",
635 rtm->rtm_type == RTN_UNICAST ? "unicast" : "multicast",
636 lookup (rtproto_str, rtm->rtm_protocol));
638 if (rtm->rtm_type != RTN_UNICAST)
640 return 0;
643 table = rtm->rtm_table;
644 if (table != RT_TABLE_MAIN && table != rtm_table_default)
646 return 0;
649 len = h->nlmsg_len - NLMSG_LENGTH(sizeof (struct rtmsg));
650 if (len < 0)
651 return -1;
653 memset (tb, 0, sizeof tb);
654 netlink_parse_rtattr (tb, RTA_MAX, RTM_RTA (rtm), len);
656 if (rtm->rtm_flags & RTM_F_CLONED)
657 return 0;
658 if (rtm->rtm_protocol == RTPROT_REDIRECT)
659 return 0;
660 if (rtm->rtm_protocol == RTPROT_KERNEL)
661 return 0;
663 if (rtm->rtm_protocol == RTPROT_ZEBRA && h->nlmsg_type == RTM_NEWROUTE)
664 return 0;
666 if (rtm->rtm_src_len != 0)
668 zlog_warn ("netlink_route_change(): no src len");
669 return 0;
672 index = 0;
673 dest = NULL;
674 gate = NULL;
676 if (tb[RTA_OIF])
677 index = *(int *) RTA_DATA (tb[RTA_OIF]);
679 if (tb[RTA_DST])
680 dest = RTA_DATA (tb[RTA_DST]);
681 else
682 dest = anyaddr;
684 if (tb[RTA_GATEWAY])
685 gate = RTA_DATA (tb[RTA_GATEWAY]);
687 if (rtm->rtm_family == AF_INET)
689 struct prefix_ipv4 p;
690 p.family = AF_INET;
691 memcpy (&p.prefix, dest, 4);
692 p.prefixlen = rtm->rtm_dst_len;
694 if (IS_ZEBRA_DEBUG_KERNEL)
696 if (h->nlmsg_type == RTM_NEWROUTE)
697 zlog_info ("RTM_NEWROUTE %s/%d",
698 inet_ntoa (p.prefix), p.prefixlen);
699 else
700 zlog_info ("RTM_DELROUTE %s/%d",
701 inet_ntoa (p.prefix), p.prefixlen);
704 if (h->nlmsg_type == RTM_NEWROUTE)
705 rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, index, table, 0, 0);
706 else
707 rib_delete_ipv4 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, index, table);
710 #ifdef HAVE_IPV6
711 if (rtm->rtm_family == AF_INET6)
713 struct prefix_ipv6 p;
714 char buf[BUFSIZ];
716 p.family = AF_INET6;
717 memcpy (&p.prefix, dest, 16);
718 p.prefixlen = rtm->rtm_dst_len;
720 if (IS_ZEBRA_DEBUG_KERNEL)
722 if (h->nlmsg_type == RTM_NEWROUTE)
723 zlog_info ("RTM_NEWROUTE %s/%d",
724 inet_ntop (AF_INET6, &p.prefix, buf, BUFSIZ),
725 p.prefixlen);
726 else
727 zlog_info ("RTM_DELROUTE %s/%d",
728 inet_ntop (AF_INET6, &p.prefix, buf, BUFSIZ),
729 p.prefixlen);
732 if (h->nlmsg_type == RTM_NEWROUTE)
733 rib_add_ipv6 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, index, 0);
734 else
735 rib_delete_ipv6 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, index, 0);
737 #endif /* HAVE_IPV6 */
739 return 0;
743 netlink_link_change (struct sockaddr_nl *snl, struct nlmsghdr *h)
745 int len;
746 struct ifinfomsg *ifi;
747 struct rtattr *tb [IFLA_MAX + 1];
748 struct interface *ifp;
749 char *name;
751 ifi = NLMSG_DATA (h);
753 if (! (h->nlmsg_type == RTM_NEWLINK || h->nlmsg_type == RTM_DELLINK))
755 /* If this is not link add/delete message so print warning. */
756 zlog_warn ("netlink_link_change: wrong kernel message %d\n",
757 h->nlmsg_type);
758 return 0;
761 len = h->nlmsg_len - NLMSG_LENGTH (sizeof (struct ifinfomsg));
762 if (len < 0)
763 return -1;
765 /* Looking up interface name. */
766 memset (tb, 0, sizeof tb);
767 netlink_parse_rtattr (tb, IFLA_MAX, IFLA_RTA (ifi), len);
768 if (tb[IFLA_IFNAME] == NULL)
769 return -1;
770 name = (char *)RTA_DATA(tb[IFLA_IFNAME]);
772 /* Add interface. */
773 if (h->nlmsg_type == RTM_NEWLINK)
775 ifp = if_lookup_by_name (name);
777 if (ifp == NULL || ! CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE))
779 if (ifp == NULL)
780 ifp = if_get_by_name (name);
782 ifp->ifindex = ifi->ifi_index;
783 ifp->flags = ifi->ifi_flags & 0x0000fffff;
784 ifp->mtu = *(int *)RTA_DATA (tb[IFLA_MTU]);
785 ifp->metric = 1;
787 /* If new link is added. */
788 if_add_update(ifp);
790 else
792 /* Interface status change. */
793 ifp->ifindex = ifi->ifi_index;
794 ifp->mtu = *(int *)RTA_DATA (tb[IFLA_MTU]);
795 ifp->metric = 1;
797 if (if_is_up (ifp))
799 ifp->flags = ifi->ifi_flags & 0x0000fffff;
800 if (! if_is_up (ifp))
801 if_down (ifp);
803 else
805 ifp->flags = ifi->ifi_flags & 0x0000fffff;
806 if (if_is_up (ifp))
807 if_up (ifp);
811 else
813 /* RTM_DELLINK. */
814 ifp = if_lookup_by_name (name);
816 if (ifp == NULL)
818 zlog (NULL, LOG_WARNING, "interface %s is deleted but can't find",
819 name);
820 return 0;
823 if_delete_update (ifp);
826 return 0;
830 netlink_information_fetch (struct sockaddr_nl *snl, struct nlmsghdr *h)
832 switch (h->nlmsg_type)
834 case RTM_NEWROUTE:
835 return netlink_route_change (snl, h);
836 break;
837 case RTM_DELROUTE:
838 return netlink_route_change (snl, h);
839 break;
840 case RTM_NEWLINK:
841 return netlink_link_change (snl, h);
842 break;
843 case RTM_DELLINK:
844 return netlink_link_change (snl, h);
845 break;
846 case RTM_NEWADDR:
847 return netlink_interface_addr (snl, h);
848 break;
849 case RTM_DELADDR:
850 return netlink_interface_addr (snl, h);
851 break;
852 default:
853 zlog_warn ("Unknown netlink nlmsg_type %d\n", h->nlmsg_type);
854 break;
856 return 0;
859 /* Interface lookup by netlink socket. */
861 interface_lookup_netlink ()
863 int ret;
865 /* Get interface information. */
866 ret = netlink_request (AF_PACKET, RTM_GETLINK, &netlink_cmd);
867 if (ret < 0)
868 return ret;
869 ret = netlink_parse_info (netlink_interface, &netlink_cmd);
870 if (ret < 0)
871 return ret;
873 /* Get IPv4 address of the interfaces. */
874 ret = netlink_request (AF_INET, RTM_GETADDR, &netlink_cmd);
875 if (ret < 0)
876 return ret;
877 ret = netlink_parse_info (netlink_interface_addr, &netlink_cmd);
878 if (ret < 0)
879 return ret;
881 #ifdef HAVE_IPV6
882 /* Get IPv6 address of the interfaces. */
883 ret = netlink_request (AF_INET6, RTM_GETADDR, &netlink_cmd);
884 if (ret < 0)
885 return ret;
886 ret = netlink_parse_info (netlink_interface_addr, &netlink_cmd);
887 if (ret < 0)
888 return ret;
889 #endif /* HAVE_IPV6 */
891 return 0;
894 /* Routing table read function using netlink interface. Only called
895 bootstrap time. */
897 netlink_route_read ()
899 int ret;
901 /* Get IPv4 routing table. */
902 ret = netlink_request (AF_INET, RTM_GETROUTE, &netlink_cmd);
903 if (ret < 0)
904 return ret;
905 ret = netlink_parse_info (netlink_routing_table, &netlink_cmd);
906 if (ret < 0)
907 return ret;
909 #ifdef HAVE_IPV6
910 /* Get IPv6 routing table. */
911 ret = netlink_request (AF_INET6, RTM_GETROUTE, &netlink_cmd);
912 if (ret < 0)
913 return ret;
914 ret = netlink_parse_info (netlink_routing_table, &netlink_cmd);
915 if (ret < 0)
916 return ret;
917 #endif /* HAVE_IPV6 */
919 return 0;
922 /* Utility function comes from iproute2.
923 Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru> */
925 addattr_l (struct nlmsghdr *n, int maxlen, int type, void *data, int alen)
927 int len;
928 struct rtattr *rta;
930 len = RTA_LENGTH(alen);
932 if (NLMSG_ALIGN(n->nlmsg_len) + len > maxlen)
933 return -1;
935 rta = (struct rtattr*) (((char*)n) + NLMSG_ALIGN (n->nlmsg_len));
936 rta->rta_type = type;
937 rta->rta_len = len;
938 memcpy (RTA_DATA(rta), data, alen);
939 n->nlmsg_len = NLMSG_ALIGN (n->nlmsg_len) + len;
941 return 0;
945 rta_addattr_l (struct rtattr *rta, int maxlen, int type, void *data, int alen)
947 int len;
948 struct rtattr *subrta;
950 len = RTA_LENGTH(alen);
952 if (RTA_ALIGN(rta->rta_len) + len > maxlen)
953 return -1;
955 subrta = (struct rtattr*) (((char*)rta) + RTA_ALIGN (rta->rta_len));
956 subrta->rta_type = type;
957 subrta->rta_len = len;
958 memcpy (RTA_DATA(subrta), data, alen);
959 rta->rta_len = NLMSG_ALIGN (rta->rta_len) + len;
961 return 0;
964 /* Utility function comes from iproute2.
965 Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru> */
967 addattr32 (struct nlmsghdr *n, int maxlen, int type, int data)
969 int len;
970 struct rtattr *rta;
972 len = RTA_LENGTH(4);
974 if (NLMSG_ALIGN (n->nlmsg_len) + len > maxlen)
975 return -1;
977 rta = (struct rtattr*) (((char*)n) + NLMSG_ALIGN (n->nlmsg_len));
978 rta->rta_type = type;
979 rta->rta_len = len;
980 memcpy (RTA_DATA(rta), &data, 4);
981 n->nlmsg_len = NLMSG_ALIGN (n->nlmsg_len) + len;
983 return 0;
986 static int
987 netlink_talk_filter (struct sockaddr_nl *snl, struct nlmsghdr *h)
989 zlog_warn ("netlink_talk: ignoring message type 0x%04x", h->nlmsg_type);
990 return 0;
993 /* sendmsg() to netlink socket then recvmsg(). */
995 netlink_talk (struct nlmsghdr *n, struct nlsock *nl)
997 int status;
998 struct sockaddr_nl snl;
999 struct iovec iov = { (void*) n, n->nlmsg_len };
1000 struct msghdr msg = {(void*) &snl, sizeof snl, &iov, 1, NULL, 0, 0};
1001 int flags = 0;
1003 memset (&snl, 0, sizeof snl);
1004 snl.nl_family = AF_NETLINK;
1006 n->nlmsg_seq = ++netlink_cmd.seq;
1008 /* Request an acknowledgement by setting NLM_F_ACK */
1009 n->nlmsg_flags |= NLM_F_ACK;
1011 if (IS_ZEBRA_DEBUG_KERNEL)
1012 zlog_info ("netlink_talk: %s type %s(%u), seq=%u", netlink_cmd.name,
1013 lookup (nlmsg_str, n->nlmsg_type), n->nlmsg_type,
1014 n->nlmsg_seq);
1016 /* Send message to netlink interface. */
1017 status = sendmsg (nl->sock, &msg, 0);
1018 if (status < 0)
1020 zlog (NULL, LOG_ERR, "netlink_talk sendmsg() error: %s",
1021 strerror (errno));
1022 return -1;
1026 * Change socket flags for blocking I/O.
1027 * This ensures we wait for a reply in netlink_parse_info().
1029 if((flags = fcntl(nl->sock, F_GETFL, 0)) < 0)
1031 zlog (NULL, LOG_ERR, "%s:%i F_GETFL error: %s",
1032 __FUNCTION__, __LINE__, strerror (errno));
1034 flags &= ~O_NONBLOCK;
1035 if(fcntl(nl->sock, F_SETFL, flags) < 0)
1037 zlog (NULL, LOG_ERR, "%s:%i F_SETFL error: %s",
1038 __FUNCTION__, __LINE__, strerror (errno));
1042 * Get reply from netlink socket.
1043 * The reply should either be an acknowlegement or an error.
1045 status = netlink_parse_info (netlink_talk_filter, nl);
1047 /* Restore socket flags for nonblocking I/O */
1048 flags |= O_NONBLOCK;
1049 if(fcntl(nl->sock, F_SETFL, flags) < 0)
1051 zlog (NULL, LOG_ERR, "%s:%i F_SETFL error: %s",
1052 __FUNCTION__, __LINE__, strerror (errno));
1055 return status;
1058 /* Routing table change via netlink interface. */
1060 netlink_route (int cmd, int family, void *dest, int length, void *gate,
1061 int index, int zebra_flags, int table)
1063 int ret;
1064 int bytelen;
1065 struct sockaddr_nl snl;
1066 int discard;
1068 struct
1070 struct nlmsghdr n;
1071 struct rtmsg r;
1072 char buf[1024];
1073 } req;
1075 memset (&req, 0, sizeof req);
1077 bytelen = (family == AF_INET ? 4 : 16);
1079 req.n.nlmsg_len = NLMSG_LENGTH (sizeof (struct rtmsg));
1080 req.n.nlmsg_flags = NLM_F_CREATE | NLM_F_REQUEST;
1081 req.n.nlmsg_type = cmd;
1082 req.r.rtm_family = family;
1083 req.r.rtm_table = table;
1084 req.r.rtm_dst_len = length;
1086 if (zebra_flags & ZEBRA_FLAG_BLACKHOLE)
1087 discard = 1;
1088 else
1089 discard = 0;
1091 if (cmd == RTM_NEWROUTE)
1093 #if 0
1094 req.r.rtm_protocol = RTPROT_ZEBRA;
1095 #endif
1096 req.r.rtm_scope = RT_SCOPE_UNIVERSE;
1098 if (discard)
1099 req.r.rtm_type = RTN_BLACKHOLE;
1100 else
1101 req.r.rtm_type = RTN_UNICAST;
1104 if (dest)
1105 addattr_l (&req.n, sizeof req, RTA_DST, dest, bytelen);
1107 if (! discard)
1109 if (gate)
1110 addattr_l (&req.n, sizeof req, RTA_GATEWAY, gate, bytelen);
1111 if (index > 0)
1112 addattr32 (&req.n, sizeof req, RTA_OIF, index);
1115 /* Destination netlink address. */
1116 memset (&snl, 0, sizeof snl);
1117 snl.nl_family = AF_NETLINK;
1119 /* Talk to netlink socket. */
1120 ret = netlink_talk (&req.n, &netlink);
1121 if (ret < 0)
1122 return -1;
1124 return 0;
1127 /* Routing table change via netlink interface. */
1129 netlink_route_multipath (int cmd, struct prefix *p, struct rib *rib,
1130 int family)
1132 int bytelen;
1133 struct sockaddr_nl snl;
1134 struct nexthop *nexthop = NULL;
1135 int nexthop_num = 0;
1136 struct nlsock *nl;
1137 int discard;
1139 struct
1141 struct nlmsghdr n;
1142 struct rtmsg r;
1143 char buf[1024];
1144 } req;
1146 memset (&req, 0, sizeof req);
1148 bytelen = (family == AF_INET ? 4 : 16);
1150 req.n.nlmsg_len = NLMSG_LENGTH (sizeof (struct rtmsg));
1151 req.n.nlmsg_flags = NLM_F_CREATE | NLM_F_REQUEST;
1152 req.n.nlmsg_type = cmd;
1153 req.r.rtm_family = family;
1154 req.r.rtm_table = rib->table;
1155 req.r.rtm_dst_len = p->prefixlen;
1157 #ifdef RTM_F_EQUALIZE
1158 req.r.rtm_flags |= RTM_F_EQUALIZE;
1159 #endif /* RTM_F_EQUALIZE */
1161 if (rib->flags & ZEBRA_FLAG_BLACKHOLE)
1162 discard = 1;
1163 else
1164 discard = 0;
1166 if (cmd == RTM_NEWROUTE)
1168 req.r.rtm_protocol = RTPROT_ZEBRA;
1169 req.r.rtm_scope = RT_SCOPE_UNIVERSE;
1171 if (discard)
1172 req.r.rtm_type = RTN_BLACKHOLE;
1173 else
1174 req.r.rtm_type = RTN_UNICAST;
1177 addattr_l (&req.n, sizeof req, RTA_DST, &p->u.prefix, bytelen);
1179 /* Metric. */
1180 addattr32 (&req.n, sizeof req, RTA_PRIORITY, rib->metric);
1182 if (discard)
1184 if (cmd == RTM_NEWROUTE)
1185 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
1186 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1187 goto skip;
1190 /* Multipath case. */
1191 if (rib->nexthop_active_num == 1 || MULTIPATH_NUM == 1)
1193 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
1195 if ((cmd == RTM_NEWROUTE
1196 && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))
1197 || (cmd == RTM_DELROUTE
1198 && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)))
1200 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
1202 if (nexthop->rtype == NEXTHOP_TYPE_IPV4
1203 || nexthop->rtype == NEXTHOP_TYPE_IPV4_IFINDEX)
1204 addattr_l (&req.n, sizeof req, RTA_GATEWAY,
1205 &nexthop->rgate.ipv4, bytelen);
1206 #ifdef HAVE_IPV6
1207 if (nexthop->rtype == NEXTHOP_TYPE_IPV6
1208 || nexthop->rtype == NEXTHOP_TYPE_IPV6_IFINDEX
1209 || nexthop->rtype == NEXTHOP_TYPE_IPV6_IFNAME)
1210 addattr_l (&req.n, sizeof req, RTA_GATEWAY,
1211 &nexthop->rgate.ipv6, bytelen);
1212 #endif /* HAVE_IPV6 */
1213 if (nexthop->rtype == NEXTHOP_TYPE_IFINDEX
1214 || nexthop->rtype == NEXTHOP_TYPE_IFNAME
1215 || nexthop->rtype == NEXTHOP_TYPE_IPV4_IFINDEX
1216 || nexthop->rtype == NEXTHOP_TYPE_IPV6_IFINDEX
1217 || nexthop->rtype == NEXTHOP_TYPE_IPV6_IFNAME)
1218 addattr32 (&req.n, sizeof req, RTA_OIF,
1219 nexthop->rifindex);
1221 else
1223 if (nexthop->type == NEXTHOP_TYPE_IPV4
1224 || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX)
1225 addattr_l (&req.n, sizeof req, RTA_GATEWAY,
1226 &nexthop->gate.ipv4, bytelen);
1227 #ifdef HAVE_IPV6
1228 if (nexthop->type == NEXTHOP_TYPE_IPV6
1229 || nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME
1230 || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX)
1231 addattr_l (&req.n, sizeof req, RTA_GATEWAY,
1232 &nexthop->gate.ipv6, bytelen);
1233 #endif /* HAVE_IPV6 */
1234 if (nexthop->type == NEXTHOP_TYPE_IFINDEX
1235 || nexthop->type == NEXTHOP_TYPE_IFNAME
1236 || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX
1237 || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX
1238 || nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME)
1239 addattr32 (&req.n, sizeof req, RTA_OIF, nexthop->ifindex);
1242 if (cmd == RTM_NEWROUTE)
1243 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1245 nexthop_num++;
1246 break;
1250 else
1252 char buf[1024];
1253 struct rtattr *rta = (void *) buf;
1254 struct rtnexthop *rtnh;
1256 rta->rta_type = RTA_MULTIPATH;
1257 rta->rta_len = RTA_LENGTH(0);
1258 rtnh = RTA_DATA(rta);
1260 nexthop_num = 0;
1261 for (nexthop = rib->nexthop;
1262 nexthop && (MULTIPATH_NUM == 0 || nexthop_num < MULTIPATH_NUM);
1263 nexthop = nexthop->next)
1265 if ((cmd == RTM_NEWROUTE
1266 && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))
1267 || (cmd == RTM_DELROUTE
1268 && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)))
1270 nexthop_num++;
1272 rtnh->rtnh_len = sizeof (*rtnh);
1273 rtnh->rtnh_flags = 0;
1274 rtnh->rtnh_hops = 0;
1275 rta->rta_len += rtnh->rtnh_len;
1277 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
1279 if (nexthop->rtype == NEXTHOP_TYPE_IPV4
1280 || nexthop->rtype == NEXTHOP_TYPE_IPV4_IFINDEX)
1282 rta_addattr_l (rta, 4096, RTA_GATEWAY,
1283 &nexthop->rgate.ipv4, bytelen);
1284 rtnh->rtnh_len += sizeof (struct rtattr) + 4;
1286 #ifdef HAVE_IPV6
1287 if (nexthop->rtype == NEXTHOP_TYPE_IPV6
1288 || nexthop->rtype == NEXTHOP_TYPE_IPV6_IFNAME
1289 || nexthop->rtype == NEXTHOP_TYPE_IPV6_IFINDEX)
1290 rta_addattr_l (rta, 4096, RTA_GATEWAY,
1291 &nexthop->rgate.ipv6, bytelen);
1292 #endif /* HAVE_IPV6 */
1293 /* ifindex */
1294 if (nexthop->rtype == NEXTHOP_TYPE_IFINDEX
1295 || nexthop->rtype == NEXTHOP_TYPE_IFNAME
1296 || nexthop->rtype == NEXTHOP_TYPE_IPV4_IFINDEX
1297 || nexthop->rtype == NEXTHOP_TYPE_IPV6_IFINDEX
1298 || nexthop->rtype == NEXTHOP_TYPE_IPV6_IFNAME)
1299 rtnh->rtnh_ifindex = nexthop->rifindex;
1300 else
1301 rtnh->rtnh_ifindex = 0;
1303 else
1305 if (nexthop->type == NEXTHOP_TYPE_IPV4
1306 || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX)
1308 rta_addattr_l (rta, 4096, RTA_GATEWAY,
1309 &nexthop->gate.ipv4, bytelen);
1310 rtnh->rtnh_len += sizeof (struct rtattr) + 4;
1312 #ifdef HAVE_IPV6
1313 if (nexthop->type == NEXTHOP_TYPE_IPV6
1314 || nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME
1315 || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX)
1316 rta_addattr_l (rta, 4096, RTA_GATEWAY,
1317 &nexthop->gate.ipv6, bytelen);
1318 #endif /* HAVE_IPV6 */
1319 /* ifindex */
1320 if (nexthop->type == NEXTHOP_TYPE_IFINDEX
1321 || nexthop->type == NEXTHOP_TYPE_IFNAME
1322 || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX
1323 || nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME
1324 || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX)
1325 rtnh->rtnh_ifindex = nexthop->ifindex;
1326 else
1327 rtnh->rtnh_ifindex = 0;
1329 rtnh = RTNH_NEXT(rtnh);
1331 if (cmd == RTM_NEWROUTE)
1332 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1336 if (rta->rta_len > RTA_LENGTH (0))
1337 addattr_l (&req.n, 1024, RTA_MULTIPATH, RTA_DATA(rta),
1338 RTA_PAYLOAD(rta));
1341 /* If there is no useful nexthop then return. */
1342 if (nexthop_num == 0)
1344 if (IS_ZEBRA_DEBUG_KERNEL)
1345 zlog_info ("netlink_route_multipath(): No useful nexthop.");
1346 return 0;
1349 skip:
1351 /* Destination netlink address. */
1352 memset (&snl, 0, sizeof snl);
1353 snl.nl_family = AF_NETLINK;
1355 if (family == AF_INET)
1356 nl = &netlink_cmd;
1357 else
1358 nl = &netlink;
1360 /* Talk to netlink socket. */
1361 return netlink_talk (&req.n, nl);
1365 kernel_add_ipv4 (struct prefix *p, struct rib *rib)
1367 return netlink_route_multipath (RTM_NEWROUTE, p, rib, AF_INET);
1371 kernel_delete_ipv4 (struct prefix *p, struct rib *rib)
1373 return netlink_route_multipath (RTM_DELROUTE, p, rib, AF_INET);
1376 #ifdef HAVE_IPV6
1378 kernel_add_ipv6 (struct prefix *p, struct rib *rib)
1380 return netlink_route_multipath (RTM_NEWROUTE, p, rib, AF_INET6);
1384 kernel_delete_ipv6 (struct prefix *p, struct rib *rib)
1386 return netlink_route_multipath (RTM_DELROUTE, p, rib, AF_INET6);
1389 /* Delete IPv6 route from the kernel. */
1391 kernel_delete_ipv6_old (struct prefix_ipv6 *dest, struct in6_addr *gate,
1392 int index, int flags, int table)
1394 return netlink_route (RTM_DELROUTE, AF_INET6, &dest->prefix, dest->prefixlen,
1395 gate, index, flags, table);
1397 #endif /* HAVE_IPV6 */
1399 /* Interface address modification. */
1401 netlink_address (int cmd, int family, struct interface *ifp,
1402 struct connected *ifc)
1404 int bytelen;
1405 struct prefix *p;
1407 struct
1409 struct nlmsghdr n;
1410 struct ifaddrmsg ifa;
1411 char buf[1024];
1412 } req;
1414 p = ifc->address;
1415 memset (&req, 0, sizeof req);
1417 bytelen = (family == AF_INET ? 4 : 16);
1419 req.n.nlmsg_len = NLMSG_LENGTH (sizeof(struct ifaddrmsg));
1420 req.n.nlmsg_flags = NLM_F_REQUEST;
1421 req.n.nlmsg_type = cmd;
1422 req.ifa.ifa_family = family;
1424 req.ifa.ifa_index = ifp->ifindex;
1425 req.ifa.ifa_prefixlen = p->prefixlen;
1427 addattr_l (&req.n, sizeof req, IFA_LOCAL, &p->u.prefix, bytelen);
1429 if (family == AF_INET && cmd == RTM_NEWADDR)
1431 if (if_is_broadcast (ifp) && ifc->destination)
1433 p = ifc->destination;
1434 addattr_l(&req.n, sizeof req, IFA_BROADCAST, &p->u.prefix, bytelen);
1438 if (CHECK_FLAG (ifc->flags, ZEBRA_IFA_SECONDARY))
1439 SET_FLAG (req.ifa.ifa_flags, IFA_F_SECONDARY);
1441 if (ifc->label)
1442 addattr_l (&req.n, sizeof req, IFA_LABEL, ifc->label,
1443 strlen (ifc->label) + 1);
1445 return netlink_talk (&req.n, &netlink_cmd);
1449 kernel_address_add_ipv4 (struct interface *ifp, struct connected *ifc)
1451 return netlink_address (RTM_NEWADDR, AF_INET, ifp, ifc);
1455 kernel_address_delete_ipv4 (struct interface *ifp, struct connected *ifc)
1457 return netlink_address (RTM_DELADDR, AF_INET, ifp, ifc);
1460 #include "thread.h"
1462 extern struct thread_master *master;
1464 /* Kernel route reflection. */
1466 kernel_read (struct thread *thread)
1468 int ret;
1469 int sock;
1471 sock = THREAD_FD (thread);
1472 ret = netlink_parse_info (netlink_information_fetch, &netlink);
1473 thread_add_read (master, kernel_read, NULL, netlink.sock);
1475 return 0;
1478 /* Exported interface function. This function simply calls
1479 netlink_socket (). */
1480 void
1481 kernel_init ()
1483 unsigned long groups;
1485 groups = RTMGRP_LINK|RTMGRP_IPV4_ROUTE|RTMGRP_IPV4_IFADDR;
1486 #ifdef HAVE_IPV6
1487 groups |= RTMGRP_IPV6_ROUTE|RTMGRP_IPV6_IFADDR;
1488 #endif /* HAVE_IPV6 */
1489 netlink_socket (&netlink, groups);
1490 netlink_socket (&netlink_cmd, 0);
1492 /* Register kernel socket. */
1493 if (netlink.sock > 0)
1494 thread_add_read (master, kernel_read, NULL, netlink.sock);