blob: 1e39d8a7a975fff9f0172aba0f23cf9c24599bad [file] [log] [blame]
paul718e3742002-12-13 20:15:29 +00001/* Kernel routing table updates using netlink over GNU/Linux system.
2 * Copyright (C) 1997, 98, 99 Kunihiro Ishiguro
3 *
4 * This file is part of GNU Zebra.
5 *
6 * GNU Zebra is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2, or (at your option) any
9 * later version.
10 *
11 * GNU Zebra is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with GNU Zebra; see the file COPYING. If not, write to the Free
18 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
19 * 02111-1307, USA.
20 */
21
22#include <zebra.h>
23
24/* Hack for GNU libc version 2. */
25#ifndef MSG_TRUNC
26#define MSG_TRUNC 0x20
27#endif /* MSG_TRUNC */
28
29#include "linklist.h"
30#include "if.h"
31#include "log.h"
32#include "prefix.h"
33#include "connected.h"
34#include "table.h"
35#include "rib.h"
36
37#include "zebra/zserv.h"
38#include "zebra/redistribute.h"
39#include "zebra/interface.h"
40#include "zebra/debug.h"
41
42/* Socket interface to kernel */
43struct nlsock
44{
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 */
52
53struct message nlmsg_str[] =
54{
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}
65};
66
67extern int rtm_table_default;
68
69/* Make socket for Linux netlink interface. */
70static int
71netlink_socket (struct nlsock *nl, unsigned long groups)
72{
73 int ret;
74 struct sockaddr_nl snl;
75 int sock;
76 int namelen;
77
78 sock = socket (AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
79 if (sock < 0)
80 {
81 zlog (NULL, LOG_ERR, "Can't open %s socket: %s", nl->name,
82 strerror (errno));
83 return -1;
84 }
85
86 ret = fcntl (sock, F_SETFL, O_NONBLOCK);
87 if (ret < 0)
88 {
89 zlog (NULL, LOG_ERR, "Can't set %s socket flags: %s", nl->name,
90 strerror (errno));
91 close (sock);
92 return -1;
93 }
94
95 memset (&snl, 0, sizeof snl);
96 snl.nl_family = AF_NETLINK;
97 snl.nl_groups = groups;
98
99 /* Bind the socket to the netlink structure for anything. */
100 ret = bind (sock, (struct sockaddr *) &snl, sizeof snl);
101 if (ret < 0)
102 {
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;
107 }
108
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)
113 {
114 zlog (NULL, LOG_ERR, "Can't get %s socket name: %s", nl->name,
115 strerror (errno));
116 close (sock);
117 return -1;
118 }
119
120 nl->snl = snl;
121 nl->sock = sock;
122 return ret;
123}
124
125/* Get type specified information from netlink. */
126static int
127netlink_request (int family, int type, struct nlsock *nl)
128{
129 int ret;
130 struct sockaddr_nl snl;
131
132 struct
133 {
134 struct nlmsghdr nlh;
135 struct rtgenmsg g;
136 } req;
137
138
139 /* Check netlink socket. */
140 if (nl->sock < 0)
141 {
142 zlog (NULL, LOG_ERR, "%s socket isn't active.", nl->name);
143 return -1;
144 }
145
146 memset (&snl, 0, sizeof snl);
147 snl.nl_family = AF_NETLINK;
148
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;
155
156 ret = sendto (nl->sock, (void*) &req, sizeof req, 0,
157 (struct sockaddr*) &snl, sizeof snl);
158 if (ret < 0)
159 {
160 zlog (NULL, LOG_ERR, "%s sendto failed: %s", nl->name, strerror (errno));
161 return -1;
162 }
163 return 0;
164}
165
166/* Receive message from netlink interface and pass those information
167 to the given function. */
168static int
169netlink_parse_info (int (*filter) (struct sockaddr_nl *, struct nlmsghdr *),
170 struct nlsock *nl)
171{
172 int status;
173 int ret = 0;
174 int error;
175
176 while (1)
177 {
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;
183
184 status = recvmsg (nl->sock, &msg, 0);
185
186 if (status < 0)
187 {
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;
194 }
195
196 if (status == 0)
197 {
198 zlog (NULL, LOG_ERR, "%s EOF", nl->name);
199 return -1;
200 }
201
202 if (msg.msg_namelen != sizeof snl)
203 {
204 zlog (NULL, LOG_ERR, "%s sender address length error: length %d",
205 nl->name, msg.msg_namelen);
206 return -1;
207 }
208
209 for (h = (struct nlmsghdr *) buf; NLMSG_OK (h, status);
210 h = NLMSG_NEXT (h, status))
211 {
212 /* Finish of reading. */
213 if (h->nlmsg_type == NLMSG_DONE)
214 return ret;
215
216 /* Error handling. */
217 if (h->nlmsg_type == NLMSG_ERROR)
218 {
219 struct nlmsgerr *err = (struct nlmsgerr *) NLMSG_DATA (h);
220
221 /* If the error field is zero, then this is an ACK */
222 if (err->error == 0)
223 {
224 if (IS_ZEBRA_DEBUG_KERNEL)
225 {
226 zlog_info("%s: %s ACK: type=%s(%u), seq=%u, pid=%d",
227 __FUNCTION__, nl->name,
228 lookup (nlmsg_str, err->msg.nlmsg_type),
229 err->msg.nlmsg_type, err->msg.nlmsg_seq,
230 err->msg.nlmsg_pid);
231 }
232
233 /* return if not a multipart message, otherwise continue */
234 if(!(h->nlmsg_flags & NLM_F_MULTI))
235 {
236 return 0;
237 }
238 continue;
239 }
240
241 if (h->nlmsg_len < NLMSG_LENGTH (sizeof (struct nlmsgerr)))
242 {
243 zlog (NULL, LOG_ERR, "%s error: message truncated",
244 nl->name);
245 return -1;
246 }
247 zlog (NULL, LOG_ERR, "%s error: %s, type=%s(%u), seq=%u, pid=%d",
248 nl->name, strerror (-err->error),
249 lookup (nlmsg_str, err->msg.nlmsg_type),
250 err->msg.nlmsg_type, err->msg.nlmsg_seq,
251 err->msg.nlmsg_pid);
252 /*
253 ret = -1;
254 continue;
255 */
256 return -1;
257 }
258
259 /* OK we got netlink message. */
260 if (IS_ZEBRA_DEBUG_KERNEL)
261 zlog_info ("netlink_parse_info: %s type %s(%u), seq=%u, pid=%d",
262 nl->name,
263 lookup (nlmsg_str, h->nlmsg_type), h->nlmsg_type,
264 h->nlmsg_seq, h->nlmsg_pid);
265
266 /* skip unsolicited messages originating from command socket */
267 if (nl != &netlink_cmd && h->nlmsg_pid == netlink_cmd.snl.nl_pid)
268 {
269 if (IS_ZEBRA_DEBUG_KERNEL)
270 zlog_info ("netlink_parse_info: %s packet comes from %s",
271 nl->name, netlink_cmd.name);
272 continue;
273 }
274
275 error = (*filter) (&snl, h);
276 if (error < 0)
277 {
278 zlog (NULL, LOG_ERR, "%s filter function error", nl->name);
279 ret = error;
280 }
281 }
282
283 /* After error care. */
284 if (msg.msg_flags & MSG_TRUNC)
285 {
286 zlog (NULL, LOG_ERR, "%s error: message truncated", nl->name);
287 continue;
288 }
289 if (status)
290 {
291 zlog (NULL, LOG_ERR, "%s error: data remnant size %d", nl->name,
292 status);
293 return -1;
294 }
295 }
296 return ret;
297}
298
299/* Utility function for parse rtattr. */
300static void
301netlink_parse_rtattr (struct rtattr **tb, int max, struct rtattr *rta, int len)
302{
303 while (RTA_OK(rta, len))
304 {
305 if (rta->rta_type <= max)
306 tb[rta->rta_type] = rta;
307 rta = RTA_NEXT(rta,len);
308 }
309}
310
311/* Called from interface_lookup_netlink(). This function is only used
312 during bootstrap. */
313int
314netlink_interface (struct sockaddr_nl *snl, struct nlmsghdr *h)
315{
316 int len;
317 struct ifinfomsg *ifi;
318 struct rtattr *tb[IFLA_MAX + 1];
319 struct interface *ifp;
320 char *name;
321 int i;
322
323 ifi = NLMSG_DATA (h);
324
325 if (h->nlmsg_type != RTM_NEWLINK)
326 return 0;
327
328 len = h->nlmsg_len - NLMSG_LENGTH (sizeof (struct ifinfomsg));
329 if (len < 0)
330 return -1;
331
332 /* Looking up interface name. */
333 memset (tb, 0, sizeof tb);
334 netlink_parse_rtattr (tb, IFLA_MAX, IFLA_RTA (ifi), len);
335 if (tb[IFLA_IFNAME] == NULL)
336 return -1;
337 name = (char *)RTA_DATA(tb[IFLA_IFNAME]);
338
339 /* Add interface. */
340 ifp = if_get_by_name (name);
341
342 ifp->ifindex = ifi->ifi_index;
343 ifp->flags = ifi->ifi_flags & 0x0000fffff;
344 ifp->mtu = *(int *)RTA_DATA (tb[IFLA_MTU]);
345 ifp->metric = 1;
346
347 /* Hardware type and address. */
348 ifp->hw_type = ifi->ifi_type;
349
350 if (tb[IFLA_ADDRESS])
351 {
352 int hw_addr_len;
353
354 hw_addr_len = RTA_PAYLOAD(tb[IFLA_ADDRESS]);
355
356 if (hw_addr_len > INTERFACE_HWADDR_MAX)
357 zlog_warn ("Hardware address is too large: %d", hw_addr_len);
358 else
359 {
360 ifp->hw_addr_len = hw_addr_len;
361 memcpy (ifp->hw_addr, RTA_DATA(tb[IFLA_ADDRESS]), hw_addr_len);
362
363 for (i = 0; i < hw_addr_len; i++)
364 if (ifp->hw_addr[i] != 0)
365 break;
366
367 if (i == hw_addr_len)
368 ifp->hw_addr_len = 0;
369 else
370 ifp->hw_addr_len = hw_addr_len;
371 }
372 }
373
374 if_add_update (ifp);
375
376 return 0;
377}
378
379/* Lookup interface IPv4/IPv6 address. */
380int
381netlink_interface_addr (struct sockaddr_nl *snl, struct nlmsghdr *h)
382{
383 int len;
384 struct ifaddrmsg *ifa;
385 struct rtattr *tb [IFA_MAX + 1];
386 struct interface *ifp;
387 void *addr = NULL;
388 void *broad = NULL;
389 u_char flags = 0;
390 char *label = NULL;
paul00df0c12002-12-13 21:07:36 +0000391 int peeronly = 0;
paul718e3742002-12-13 20:15:29 +0000392
393 ifa = NLMSG_DATA (h);
394
395 if (ifa->ifa_family != AF_INET
396#ifdef HAVE_IPV6
397 && ifa->ifa_family != AF_INET6
398#endif /* HAVE_IPV6 */
399 )
400 return 0;
401
402 if (h->nlmsg_type != RTM_NEWADDR && h->nlmsg_type != RTM_DELADDR)
403 return 0;
404
405 len = h->nlmsg_len - NLMSG_LENGTH(sizeof (struct ifaddrmsg));
406 if (len < 0)
407 return -1;
408
409 memset (tb, 0, sizeof tb);
410 netlink_parse_rtattr (tb, IFA_MAX, IFA_RTA (ifa), len);
411
412 ifp = if_lookup_by_index (ifa->ifa_index);
413 if (ifp == NULL)
414 {
415 zlog_err ("netlink_interface_addr can't find interface by index %d",
416 ifa->ifa_index);
417 return -1;
418 }
419
paul00df0c12002-12-13 21:07:36 +0000420 if (IS_ZEBRA_DEBUG_KERNEL) /* remove this line to see initial ifcfg */
paul718e3742002-12-13 20:15:29 +0000421 {
paul00df0c12002-12-13 21:07:36 +0000422 char buf[BUFSIZ];
423 zlog_info ("netlink_interface_addr %s %s/%d:",
424 lookup (nlmsg_str, h->nlmsg_type),
425 ifp->name, ifa->ifa_prefixlen);
paul718e3742002-12-13 20:15:29 +0000426 if (tb[IFA_LOCAL])
paul00df0c12002-12-13 21:07:36 +0000427 zlog_info (" IFA_LOCAL %s", inet_ntop (ifa->ifa_family,
428 RTA_DATA (tb[IFA_LOCAL]), buf, BUFSIZ));
paul718e3742002-12-13 20:15:29 +0000429 if (tb[IFA_ADDRESS])
paul00df0c12002-12-13 21:07:36 +0000430 zlog_info (" IFA_ADDRESS %s", inet_ntop (ifa->ifa_family,
431 RTA_DATA (tb[IFA_ADDRESS]), buf, BUFSIZ));
paul718e3742002-12-13 20:15:29 +0000432 if (tb[IFA_BROADCAST])
paul00df0c12002-12-13 21:07:36 +0000433 zlog_info (" IFA_BROADCAST %s", inet_ntop (ifa->ifa_family,
434 RTA_DATA (tb[IFA_BROADCAST]), buf, BUFSIZ));
435 if (tb[IFA_LABEL] && strcmp (ifp->name, RTA_DATA (tb[IFA_LABEL])))
436 zlog_info (" IFA_LABEL %s", RTA_DATA (tb[IFA_LABEL]));
paul718e3742002-12-13 20:15:29 +0000437 }
438
paul00df0c12002-12-13 21:07:36 +0000439 /* peer or broadcast network? */
440 if (ifa->ifa_family == AF_INET)
441 peeronly = if_is_pointopoint (ifp) ||
442 ifa->ifa_prefixlen >= IPV4_MAX_PREFIXLEN - 1;
443#ifdef HAVE_IPV6
444 if (ifa->ifa_family == AF_INET6)
445 peeronly = if_is_pointopoint (ifp) ||
446 ifa->ifa_prefixlen >= IPV6_MAX_PREFIXLEN - 1;
447#endif /* HAVE_IPV6*/
448
449 /* network. prefixlen applies to IFA_ADDRESS rather than IFA_LOCAL */
450 if (tb[IFA_ADDRESS] && !peeronly)
451 addr = RTA_DATA (tb[IFA_ADDRESS]);
452 else if (tb[IFA_LOCAL])
453 addr = RTA_DATA (tb[IFA_LOCAL]);
454 else
455 addr = NULL;
456
457 /* broadcast/peer */
458 if (tb[IFA_BROADCAST])
459 broad = RTA_DATA (tb[IFA_BROADCAST]);
460 else if (tb[IFA_ADDRESS] && peeronly)
461 broad = RTA_DATA (tb[IFA_ADDRESS]); /* peer address specified */
462 else
463 broad = NULL;
464
paul718e3742002-12-13 20:15:29 +0000465 /* Flags. */
466 if (ifa->ifa_flags & IFA_F_SECONDARY)
467 SET_FLAG (flags, ZEBRA_IFA_SECONDARY);
468
469 /* Label */
470 if (tb[IFA_LABEL])
471 label = (char *) RTA_DATA (tb[IFA_LABEL]);
472
473 if (ifp && label && strcmp (ifp->name, label) == 0)
474 label = NULL;
475
476 /* Register interface address to the interface. */
477 if (ifa->ifa_family == AF_INET)
478 {
479 if (h->nlmsg_type == RTM_NEWADDR)
480 connected_add_ipv4 (ifp, flags,
481 (struct in_addr *) addr, ifa->ifa_prefixlen,
482 (struct in_addr *) broad, label);
483 else
484 connected_delete_ipv4 (ifp, flags,
485 (struct in_addr *) addr, ifa->ifa_prefixlen,
486 (struct in_addr *) broad, label);
487 }
488#ifdef HAVE_IPV6
489 if (ifa->ifa_family == AF_INET6)
490 {
491 if (h->nlmsg_type == RTM_NEWADDR)
492 connected_add_ipv6 (ifp,
493 (struct in6_addr *) addr, ifa->ifa_prefixlen,
494 (struct in6_addr *) broad);
495 else
496 connected_delete_ipv6 (ifp,
497 (struct in6_addr *) addr, ifa->ifa_prefixlen,
498 (struct in6_addr *) broad);
499 }
500#endif /* HAVE_IPV6*/
501
502 return 0;
503}
504
505/* Looking up routing table by netlink interface. */
506int
507netlink_routing_table (struct sockaddr_nl *snl, struct nlmsghdr *h)
508{
509 int len;
510 struct rtmsg *rtm;
511 struct rtattr *tb [RTA_MAX + 1];
512 u_char flags = 0;
513
514 char anyaddr[16] = {0};
515
516 int index;
517 int table;
518 void *dest;
519 void *gate;
520
521 rtm = NLMSG_DATA (h);
522
523 if (h->nlmsg_type != RTM_NEWROUTE)
524 return 0;
525 if (rtm->rtm_type != RTN_UNICAST)
526 return 0;
527
528 table = rtm->rtm_table;
529#if 0 /* we weed them out later in rib_weed_tables () */
530 if (table != RT_TABLE_MAIN && table != rtm_table_default)
531 return 0;
532#endif
533
534 len = h->nlmsg_len - NLMSG_LENGTH(sizeof (struct rtmsg));
535 if (len < 0)
536 return -1;
537
538 memset (tb, 0, sizeof tb);
539 netlink_parse_rtattr (tb, RTA_MAX, RTM_RTA (rtm), len);
540
541 if (rtm->rtm_flags & RTM_F_CLONED)
542 return 0;
543 if (rtm->rtm_protocol == RTPROT_REDIRECT)
544 return 0;
545 if (rtm->rtm_protocol == RTPROT_KERNEL)
546 return 0;
547
548 if (rtm->rtm_src_len != 0)
549 return 0;
550
551 /* Route which inserted by Zebra. */
552 if (rtm->rtm_protocol == RTPROT_ZEBRA)
553 flags |= ZEBRA_FLAG_SELFROUTE;
554
555 index = 0;
556 dest = NULL;
557 gate = NULL;
558
559 if (tb[RTA_OIF])
560 index = *(int *) RTA_DATA (tb[RTA_OIF]);
561
562 if (tb[RTA_DST])
563 dest = RTA_DATA (tb[RTA_DST]);
564 else
565 dest = anyaddr;
566
567 /* Multipath treatment is needed. */
568 if (tb[RTA_GATEWAY])
569 gate = RTA_DATA (tb[RTA_GATEWAY]);
570
571 if (rtm->rtm_family == AF_INET)
572 {
573 struct prefix_ipv4 p;
574 p.family = AF_INET;
575 memcpy (&p.prefix, dest, 4);
576 p.prefixlen = rtm->rtm_dst_len;
577
578 rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, flags, &p, gate, index, table, 0, 0);
579 }
580#ifdef HAVE_IPV6
581 if (rtm->rtm_family == AF_INET6)
582 {
583 struct prefix_ipv6 p;
584 p.family = AF_INET6;
585 memcpy (&p.prefix, dest, 16);
586 p.prefixlen = rtm->rtm_dst_len;
587
588 rib_add_ipv6 (ZEBRA_ROUTE_KERNEL, flags, &p, gate, index, table);
589 }
590#endif /* HAVE_IPV6 */
591
592 return 0;
593}
594
595struct message rtproto_str [] =
596{
597 {RTPROT_REDIRECT, "redirect"},
598 {RTPROT_KERNEL, "kernel"},
599 {RTPROT_BOOT, "boot"},
600 {RTPROT_STATIC, "static"},
601 {RTPROT_GATED, "GateD"},
602 {RTPROT_RA, "router advertisement"},
603 {RTPROT_MRT, "MRT"},
604 {RTPROT_ZEBRA, "Zebra"},
605#ifdef RTPROT_BIRD
606 {RTPROT_BIRD, "BIRD"},
607#endif /* RTPROT_BIRD */
608 {0, NULL}
609};
610
611/* Routing information change from the kernel. */
612int
613netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h)
614{
615 int len;
616 struct rtmsg *rtm;
617 struct rtattr *tb [RTA_MAX + 1];
618
619 char anyaddr[16] = {0};
620
621 int index;
622 int table;
623 void *dest;
624 void *gate;
625
626 rtm = NLMSG_DATA (h);
627
628 if (! (h->nlmsg_type == RTM_NEWROUTE || h->nlmsg_type == RTM_DELROUTE))
629 {
630 /* If this is not route add/delete message print warning. */
631 zlog_warn ("Kernel message: %d\n", h->nlmsg_type);
632 return 0;
633 }
634
635 /* Connected route. */
636 if (IS_ZEBRA_DEBUG_KERNEL)
637 zlog_info ("%s %s %s proto %s",
638 h->nlmsg_type == RTM_NEWROUTE ? "RTM_NEWROUTE" : "RTM_DELROUTE",
639 rtm->rtm_family == AF_INET ? "ipv4" : "ipv6",
640 rtm->rtm_type == RTN_UNICAST ? "unicast" : "multicast",
641 lookup (rtproto_str, rtm->rtm_protocol));
642
643 if (rtm->rtm_type != RTN_UNICAST)
644 {
645 return 0;
646 }
647
648 table = rtm->rtm_table;
649 if (table != RT_TABLE_MAIN && table != rtm_table_default)
650 {
651 return 0;
652 }
653
654 len = h->nlmsg_len - NLMSG_LENGTH(sizeof (struct rtmsg));
655 if (len < 0)
656 return -1;
657
658 memset (tb, 0, sizeof tb);
659 netlink_parse_rtattr (tb, RTA_MAX, RTM_RTA (rtm), len);
660
661 if (rtm->rtm_flags & RTM_F_CLONED)
662 return 0;
663 if (rtm->rtm_protocol == RTPROT_REDIRECT)
664 return 0;
665 if (rtm->rtm_protocol == RTPROT_KERNEL)
666 return 0;
667
668 if (rtm->rtm_protocol == RTPROT_ZEBRA && h->nlmsg_type == RTM_NEWROUTE)
669 return 0;
670
671 if (rtm->rtm_src_len != 0)
672 {
673 zlog_warn ("netlink_route_change(): no src len");
674 return 0;
675 }
676
677 index = 0;
678 dest = NULL;
679 gate = NULL;
680
681 if (tb[RTA_OIF])
682 index = *(int *) RTA_DATA (tb[RTA_OIF]);
683
684 if (tb[RTA_DST])
685 dest = RTA_DATA (tb[RTA_DST]);
686 else
687 dest = anyaddr;
688
689 if (tb[RTA_GATEWAY])
690 gate = RTA_DATA (tb[RTA_GATEWAY]);
691
692 if (rtm->rtm_family == AF_INET)
693 {
694 struct prefix_ipv4 p;
695 p.family = AF_INET;
696 memcpy (&p.prefix, dest, 4);
697 p.prefixlen = rtm->rtm_dst_len;
698
699 if (IS_ZEBRA_DEBUG_KERNEL)
700 {
701 if (h->nlmsg_type == RTM_NEWROUTE)
702 zlog_info ("RTM_NEWROUTE %s/%d",
703 inet_ntoa (p.prefix), p.prefixlen);
704 else
705 zlog_info ("RTM_DELROUTE %s/%d",
706 inet_ntoa (p.prefix), p.prefixlen);
707 }
708
709 if (h->nlmsg_type == RTM_NEWROUTE)
710 rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, index, table, 0, 0);
711 else
712 rib_delete_ipv4 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, index, table);
713 }
714
715#ifdef HAVE_IPV6
716 if (rtm->rtm_family == AF_INET6)
717 {
718 struct prefix_ipv6 p;
719 char buf[BUFSIZ];
720
721 p.family = AF_INET6;
722 memcpy (&p.prefix, dest, 16);
723 p.prefixlen = rtm->rtm_dst_len;
724
725 if (IS_ZEBRA_DEBUG_KERNEL)
726 {
727 if (h->nlmsg_type == RTM_NEWROUTE)
728 zlog_info ("RTM_NEWROUTE %s/%d",
729 inet_ntop (AF_INET6, &p.prefix, buf, BUFSIZ),
730 p.prefixlen);
731 else
732 zlog_info ("RTM_DELROUTE %s/%d",
733 inet_ntop (AF_INET6, &p.prefix, buf, BUFSIZ),
734 p.prefixlen);
735 }
736
737 if (h->nlmsg_type == RTM_NEWROUTE)
738 rib_add_ipv6 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, index, 0);
739 else
740 rib_delete_ipv6 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, index, 0);
741 }
742#endif /* HAVE_IPV6 */
743
744 return 0;
745}
746
747int
748netlink_link_change (struct sockaddr_nl *snl, struct nlmsghdr *h)
749{
750 int len;
751 struct ifinfomsg *ifi;
752 struct rtattr *tb [IFLA_MAX + 1];
753 struct interface *ifp;
754 char *name;
755
756 ifi = NLMSG_DATA (h);
757
758 if (! (h->nlmsg_type == RTM_NEWLINK || h->nlmsg_type == RTM_DELLINK))
759 {
760 /* If this is not link add/delete message so print warning. */
761 zlog_warn ("netlink_link_change: wrong kernel message %d\n",
762 h->nlmsg_type);
763 return 0;
764 }
765
766 len = h->nlmsg_len - NLMSG_LENGTH (sizeof (struct ifinfomsg));
767 if (len < 0)
768 return -1;
769
770 /* Looking up interface name. */
771 memset (tb, 0, sizeof tb);
772 netlink_parse_rtattr (tb, IFLA_MAX, IFLA_RTA (ifi), len);
773 if (tb[IFLA_IFNAME] == NULL)
774 return -1;
775 name = (char *)RTA_DATA(tb[IFLA_IFNAME]);
776
777 /* Add interface. */
778 if (h->nlmsg_type == RTM_NEWLINK)
779 {
780 ifp = if_lookup_by_name (name);
781
782 if (ifp == NULL || ! CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE))
783 {
784 if (ifp == NULL)
785 ifp = if_get_by_name (name);
786
787 ifp->ifindex = ifi->ifi_index;
788 ifp->flags = ifi->ifi_flags & 0x0000fffff;
789 ifp->mtu = *(int *)RTA_DATA (tb[IFLA_MTU]);
790 ifp->metric = 1;
791
792 /* If new link is added. */
793 if_add_update(ifp);
794 }
795 else
796 {
797 /* Interface status change. */
798 ifp->ifindex = ifi->ifi_index;
799 ifp->mtu = *(int *)RTA_DATA (tb[IFLA_MTU]);
800 ifp->metric = 1;
801
paul2e3b2e42002-12-13 21:03:13 +0000802 if (if_is_operative (ifp))
paul718e3742002-12-13 20:15:29 +0000803 {
804 ifp->flags = ifi->ifi_flags & 0x0000fffff;
paul2e3b2e42002-12-13 21:03:13 +0000805 if (! if_is_operative (ifp))
paul718e3742002-12-13 20:15:29 +0000806 if_down (ifp);
807 }
808 else
809 {
810 ifp->flags = ifi->ifi_flags & 0x0000fffff;
paul2e3b2e42002-12-13 21:03:13 +0000811 if (if_is_operative (ifp))
paul718e3742002-12-13 20:15:29 +0000812 if_up (ifp);
813 }
814 }
815 }
816 else
817 {
818 /* RTM_DELLINK. */
819 ifp = if_lookup_by_name (name);
820
821 if (ifp == NULL)
822 {
823 zlog (NULL, LOG_WARNING, "interface %s is deleted but can't find",
824 name);
825 return 0;
826 }
827
828 if_delete_update (ifp);
829 }
830
831 return 0;
832}
833
834int
835netlink_information_fetch (struct sockaddr_nl *snl, struct nlmsghdr *h)
836{
837 switch (h->nlmsg_type)
838 {
839 case RTM_NEWROUTE:
840 return netlink_route_change (snl, h);
841 break;
842 case RTM_DELROUTE:
843 return netlink_route_change (snl, h);
844 break;
845 case RTM_NEWLINK:
846 return netlink_link_change (snl, h);
847 break;
848 case RTM_DELLINK:
849 return netlink_link_change (snl, h);
850 break;
851 case RTM_NEWADDR:
852 return netlink_interface_addr (snl, h);
853 break;
854 case RTM_DELADDR:
855 return netlink_interface_addr (snl, h);
856 break;
857 default:
858 zlog_warn ("Unknown netlink nlmsg_type %d\n", h->nlmsg_type);
859 break;
860 }
861 return 0;
862}
863
864/* Interface lookup by netlink socket. */
865int
866interface_lookup_netlink ()
867{
868 int ret;
869
870 /* Get interface information. */
871 ret = netlink_request (AF_PACKET, RTM_GETLINK, &netlink_cmd);
872 if (ret < 0)
873 return ret;
874 ret = netlink_parse_info (netlink_interface, &netlink_cmd);
875 if (ret < 0)
876 return ret;
877
878 /* Get IPv4 address of the interfaces. */
879 ret = netlink_request (AF_INET, RTM_GETADDR, &netlink_cmd);
880 if (ret < 0)
881 return ret;
882 ret = netlink_parse_info (netlink_interface_addr, &netlink_cmd);
883 if (ret < 0)
884 return ret;
885
886#ifdef HAVE_IPV6
887 /* Get IPv6 address of the interfaces. */
888 ret = netlink_request (AF_INET6, RTM_GETADDR, &netlink_cmd);
889 if (ret < 0)
890 return ret;
891 ret = netlink_parse_info (netlink_interface_addr, &netlink_cmd);
892 if (ret < 0)
893 return ret;
894#endif /* HAVE_IPV6 */
895
896 return 0;
897}
898
899/* Routing table read function using netlink interface. Only called
900 bootstrap time. */
901int
902netlink_route_read ()
903{
904 int ret;
905
906 /* Get IPv4 routing table. */
907 ret = netlink_request (AF_INET, RTM_GETROUTE, &netlink_cmd);
908 if (ret < 0)
909 return ret;
910 ret = netlink_parse_info (netlink_routing_table, &netlink_cmd);
911 if (ret < 0)
912 return ret;
913
914#ifdef HAVE_IPV6
915 /* Get IPv6 routing table. */
916 ret = netlink_request (AF_INET6, RTM_GETROUTE, &netlink_cmd);
917 if (ret < 0)
918 return ret;
919 ret = netlink_parse_info (netlink_routing_table, &netlink_cmd);
920 if (ret < 0)
921 return ret;
922#endif /* HAVE_IPV6 */
923
924 return 0;
925}
926
927/* Utility function comes from iproute2.
928 Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru> */
929int
930addattr_l (struct nlmsghdr *n, int maxlen, int type, void *data, int alen)
931{
932 int len;
933 struct rtattr *rta;
934
935 len = RTA_LENGTH(alen);
936
937 if (NLMSG_ALIGN(n->nlmsg_len) + len > maxlen)
938 return -1;
939
940 rta = (struct rtattr*) (((char*)n) + NLMSG_ALIGN (n->nlmsg_len));
941 rta->rta_type = type;
942 rta->rta_len = len;
943 memcpy (RTA_DATA(rta), data, alen);
944 n->nlmsg_len = NLMSG_ALIGN (n->nlmsg_len) + len;
945
946 return 0;
947}
948
949int
950rta_addattr_l (struct rtattr *rta, int maxlen, int type, void *data, int alen)
951{
952 int len;
953 struct rtattr *subrta;
954
955 len = RTA_LENGTH(alen);
956
957 if (RTA_ALIGN(rta->rta_len) + len > maxlen)
958 return -1;
959
960 subrta = (struct rtattr*) (((char*)rta) + RTA_ALIGN (rta->rta_len));
961 subrta->rta_type = type;
962 subrta->rta_len = len;
963 memcpy (RTA_DATA(subrta), data, alen);
964 rta->rta_len = NLMSG_ALIGN (rta->rta_len) + len;
965
966 return 0;
967}
968
969/* Utility function comes from iproute2.
970 Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru> */
971int
972addattr32 (struct nlmsghdr *n, int maxlen, int type, int data)
973{
974 int len;
975 struct rtattr *rta;
976
977 len = RTA_LENGTH(4);
978
979 if (NLMSG_ALIGN (n->nlmsg_len) + len > maxlen)
980 return -1;
981
982 rta = (struct rtattr*) (((char*)n) + NLMSG_ALIGN (n->nlmsg_len));
983 rta->rta_type = type;
984 rta->rta_len = len;
985 memcpy (RTA_DATA(rta), &data, 4);
986 n->nlmsg_len = NLMSG_ALIGN (n->nlmsg_len) + len;
987
988 return 0;
989}
990
991static int
992netlink_talk_filter (struct sockaddr_nl *snl, struct nlmsghdr *h)
993{
994 zlog_warn ("netlink_talk: ignoring message type 0x%04x", h->nlmsg_type);
995 return 0;
996}
997
998/* sendmsg() to netlink socket then recvmsg(). */
999int
1000netlink_talk (struct nlmsghdr *n, struct nlsock *nl)
1001{
1002 int status;
1003 struct sockaddr_nl snl;
1004 struct iovec iov = { (void*) n, n->nlmsg_len };
1005 struct msghdr msg = {(void*) &snl, sizeof snl, &iov, 1, NULL, 0, 0};
1006 int flags = 0;
1007
1008 memset (&snl, 0, sizeof snl);
1009 snl.nl_family = AF_NETLINK;
1010
1011 n->nlmsg_seq = ++netlink_cmd.seq;
1012
1013 /* Request an acknowledgement by setting NLM_F_ACK */
1014 n->nlmsg_flags |= NLM_F_ACK;
1015
1016 if (IS_ZEBRA_DEBUG_KERNEL)
1017 zlog_info ("netlink_talk: %s type %s(%u), seq=%u", netlink_cmd.name,
1018 lookup (nlmsg_str, n->nlmsg_type), n->nlmsg_type,
1019 n->nlmsg_seq);
1020
1021 /* Send message to netlink interface. */
1022 status = sendmsg (nl->sock, &msg, 0);
1023 if (status < 0)
1024 {
1025 zlog (NULL, LOG_ERR, "netlink_talk sendmsg() error: %s",
1026 strerror (errno));
1027 return -1;
1028 }
1029
1030 /*
1031 * Change socket flags for blocking I/O.
1032 * This ensures we wait for a reply in netlink_parse_info().
1033 */
1034 if((flags = fcntl(nl->sock, F_GETFL, 0)) < 0)
1035 {
1036 zlog (NULL, LOG_ERR, "%s:%i F_GETFL error: %s",
1037 __FUNCTION__, __LINE__, strerror (errno));
1038 }
1039 flags &= ~O_NONBLOCK;
1040 if(fcntl(nl->sock, F_SETFL, flags) < 0)
1041 {
1042 zlog (NULL, LOG_ERR, "%s:%i F_SETFL error: %s",
1043 __FUNCTION__, __LINE__, strerror (errno));
1044 }
1045
1046 /*
1047 * Get reply from netlink socket.
1048 * The reply should either be an acknowlegement or an error.
1049 */
1050 status = netlink_parse_info (netlink_talk_filter, nl);
1051
1052 /* Restore socket flags for nonblocking I/O */
1053 flags |= O_NONBLOCK;
1054 if(fcntl(nl->sock, F_SETFL, flags) < 0)
1055 {
1056 zlog (NULL, LOG_ERR, "%s:%i F_SETFL error: %s",
1057 __FUNCTION__, __LINE__, strerror (errno));
1058 }
1059
1060 return status;
1061}
1062
1063/* Routing table change via netlink interface. */
1064int
1065netlink_route (int cmd, int family, void *dest, int length, void *gate,
1066 int index, int zebra_flags, int table)
1067{
1068 int ret;
1069 int bytelen;
1070 struct sockaddr_nl snl;
1071 int discard;
1072
1073 struct
1074 {
1075 struct nlmsghdr n;
1076 struct rtmsg r;
1077 char buf[1024];
1078 } req;
1079
1080 memset (&req, 0, sizeof req);
1081
1082 bytelen = (family == AF_INET ? 4 : 16);
1083
1084 req.n.nlmsg_len = NLMSG_LENGTH (sizeof (struct rtmsg));
1085 req.n.nlmsg_flags = NLM_F_CREATE | NLM_F_REQUEST;
1086 req.n.nlmsg_type = cmd;
1087 req.r.rtm_family = family;
1088 req.r.rtm_table = table;
1089 req.r.rtm_dst_len = length;
1090
1091 if (zebra_flags & ZEBRA_FLAG_BLACKHOLE)
1092 discard = 1;
1093 else
1094 discard = 0;
1095
1096 if (cmd == RTM_NEWROUTE)
1097 {
1098 req.r.rtm_protocol = RTPROT_ZEBRA;
1099 req.r.rtm_scope = RT_SCOPE_UNIVERSE;
1100
1101 if (discard)
1102 req.r.rtm_type = RTN_BLACKHOLE;
1103 else
1104 req.r.rtm_type = RTN_UNICAST;
1105 }
1106
1107 if (dest)
1108 addattr_l (&req.n, sizeof req, RTA_DST, dest, bytelen);
1109
1110 if (! discard)
1111 {
1112 if (gate)
1113 addattr_l (&req.n, sizeof req, RTA_GATEWAY, gate, bytelen);
1114 if (index > 0)
1115 addattr32 (&req.n, sizeof req, RTA_OIF, index);
1116 }
1117
1118 /* Destination netlink address. */
1119 memset (&snl, 0, sizeof snl);
1120 snl.nl_family = AF_NETLINK;
1121
1122 /* Talk to netlink socket. */
1123 ret = netlink_talk (&req.n, &netlink);
1124 if (ret < 0)
1125 return -1;
1126
1127 return 0;
1128}
1129
1130/* Routing table change via netlink interface. */
1131int
1132netlink_route_multipath (int cmd, struct prefix *p, struct rib *rib,
1133 int family)
1134{
1135 int bytelen;
1136 struct sockaddr_nl snl;
1137 struct nexthop *nexthop = NULL;
1138 int nexthop_num = 0;
1139 struct nlsock *nl;
1140 int discard;
1141
1142 struct
1143 {
1144 struct nlmsghdr n;
1145 struct rtmsg r;
1146 char buf[1024];
1147 } req;
1148
1149 memset (&req, 0, sizeof req);
1150
1151 bytelen = (family == AF_INET ? 4 : 16);
1152
1153 req.n.nlmsg_len = NLMSG_LENGTH (sizeof (struct rtmsg));
1154 req.n.nlmsg_flags = NLM_F_CREATE | NLM_F_REQUEST;
1155 req.n.nlmsg_type = cmd;
1156 req.r.rtm_family = family;
1157 req.r.rtm_table = rib->table;
1158 req.r.rtm_dst_len = p->prefixlen;
1159
1160 if (rib->flags & ZEBRA_FLAG_BLACKHOLE)
1161 discard = 1;
1162 else
1163 discard = 0;
1164
1165 if (cmd == RTM_NEWROUTE)
1166 {
1167 req.r.rtm_protocol = RTPROT_ZEBRA;
1168 req.r.rtm_scope = RT_SCOPE_UNIVERSE;
1169
1170 if (discard)
1171 req.r.rtm_type = RTN_BLACKHOLE;
1172 else
1173 req.r.rtm_type = RTN_UNICAST;
1174 }
1175
1176 addattr_l (&req.n, sizeof req, RTA_DST, &p->u.prefix, bytelen);
1177
1178 /* Metric. */
1179 addattr32 (&req.n, sizeof req, RTA_PRIORITY, rib->metric);
1180
1181 if (discard)
1182 {
1183 if (cmd == RTM_NEWROUTE)
1184 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
1185 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1186 goto skip;
1187 }
1188
1189 /* Multipath case. */
1190 if (rib->nexthop_active_num == 1 || MULTIPATH_NUM == 1)
1191 {
1192 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
1193 {
1194 if ((cmd == RTM_NEWROUTE
1195 && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))
1196 || (cmd == RTM_DELROUTE
1197 && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)))
1198 {
1199 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
1200 {
1201 if (nexthop->rtype == NEXTHOP_TYPE_IPV4
1202 || nexthop->rtype == NEXTHOP_TYPE_IPV4_IFINDEX)
1203 addattr_l (&req.n, sizeof req, RTA_GATEWAY,
1204 &nexthop->rgate.ipv4, bytelen);
1205#ifdef HAVE_IPV6
1206 if (nexthop->rtype == NEXTHOP_TYPE_IPV6
1207 || nexthop->rtype == NEXTHOP_TYPE_IPV6_IFINDEX
1208 || nexthop->rtype == NEXTHOP_TYPE_IPV6_IFNAME)
1209 addattr_l (&req.n, sizeof req, RTA_GATEWAY,
1210 &nexthop->rgate.ipv6, bytelen);
1211#endif /* HAVE_IPV6 */
1212 if (nexthop->rtype == NEXTHOP_TYPE_IFINDEX
1213 || nexthop->rtype == NEXTHOP_TYPE_IFNAME
1214 || nexthop->rtype == NEXTHOP_TYPE_IPV4_IFINDEX
1215 || nexthop->rtype == NEXTHOP_TYPE_IPV6_IFINDEX
1216 || nexthop->rtype == NEXTHOP_TYPE_IPV6_IFNAME)
1217 addattr32 (&req.n, sizeof req, RTA_OIF,
1218 nexthop->rifindex);
1219 }
1220 else
1221 {
1222 if (nexthop->type == NEXTHOP_TYPE_IPV4
1223 || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX)
1224 addattr_l (&req.n, sizeof req, RTA_GATEWAY,
1225 &nexthop->gate.ipv4, bytelen);
1226#ifdef HAVE_IPV6
1227 if (nexthop->type == NEXTHOP_TYPE_IPV6
1228 || nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME
1229 || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX)
1230 addattr_l (&req.n, sizeof req, RTA_GATEWAY,
1231 &nexthop->gate.ipv6, bytelen);
1232#endif /* HAVE_IPV6 */
1233 if (nexthop->type == NEXTHOP_TYPE_IFINDEX
1234 || nexthop->type == NEXTHOP_TYPE_IFNAME
1235 || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX
1236 || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX
1237 || nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME)
1238 addattr32 (&req.n, sizeof req, RTA_OIF, nexthop->ifindex);
1239 }
1240
1241 if (cmd == RTM_NEWROUTE)
1242 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1243
1244 nexthop_num++;
1245 break;
1246 }
1247 }
1248 }
1249 else
1250 {
1251 char buf[1024];
1252 struct rtattr *rta = (void *) buf;
1253 struct rtnexthop *rtnh;
1254
1255 rta->rta_type = RTA_MULTIPATH;
1256 rta->rta_len = RTA_LENGTH(0);
1257 rtnh = RTA_DATA(rta);
1258
1259 nexthop_num = 0;
1260 for (nexthop = rib->nexthop;
1261 nexthop && (MULTIPATH_NUM == 0 || nexthop_num < MULTIPATH_NUM);
1262 nexthop = nexthop->next)
1263 {
1264 if ((cmd == RTM_NEWROUTE
1265 && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))
1266 || (cmd == RTM_DELROUTE
1267 && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)))
1268 {
1269 nexthop_num++;
1270
1271 rtnh->rtnh_len = sizeof (*rtnh);
1272 rtnh->rtnh_flags = 0;
1273 rtnh->rtnh_hops = 0;
1274 rta->rta_len += rtnh->rtnh_len;
1275
1276 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
1277 {
1278 if (nexthop->rtype == NEXTHOP_TYPE_IPV4
1279 || nexthop->rtype == NEXTHOP_TYPE_IPV4_IFINDEX)
1280 {
1281 rta_addattr_l (rta, 4096, RTA_GATEWAY,
1282 &nexthop->rgate.ipv4, bytelen);
1283 rtnh->rtnh_len += sizeof (struct rtattr) + 4;
1284 }
1285#ifdef HAVE_IPV6
1286 if (nexthop->rtype == NEXTHOP_TYPE_IPV6
1287 || nexthop->rtype == NEXTHOP_TYPE_IPV6_IFNAME
1288 || nexthop->rtype == NEXTHOP_TYPE_IPV6_IFINDEX)
1289 rta_addattr_l (rta, 4096, RTA_GATEWAY,
1290 &nexthop->rgate.ipv6, bytelen);
1291#endif /* HAVE_IPV6 */
1292 /* ifindex */
1293 if (nexthop->rtype == NEXTHOP_TYPE_IFINDEX
1294 || nexthop->rtype == NEXTHOP_TYPE_IFNAME
1295 || nexthop->rtype == NEXTHOP_TYPE_IPV4_IFINDEX
1296 || nexthop->rtype == NEXTHOP_TYPE_IPV6_IFINDEX
1297 || nexthop->rtype == NEXTHOP_TYPE_IPV6_IFNAME)
1298 rtnh->rtnh_ifindex = nexthop->rifindex;
1299 else
1300 rtnh->rtnh_ifindex = 0;
1301 }
1302 else
1303 {
1304 if (nexthop->type == NEXTHOP_TYPE_IPV4
1305 || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX)
1306 {
1307 rta_addattr_l (rta, 4096, RTA_GATEWAY,
1308 &nexthop->gate.ipv4, bytelen);
1309 rtnh->rtnh_len += sizeof (struct rtattr) + 4;
1310 }
1311#ifdef HAVE_IPV6
1312 if (nexthop->type == NEXTHOP_TYPE_IPV6
1313 || nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME
1314 || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX)
1315 rta_addattr_l (rta, 4096, RTA_GATEWAY,
1316 &nexthop->gate.ipv6, bytelen);
1317#endif /* HAVE_IPV6 */
1318 /* ifindex */
1319 if (nexthop->type == NEXTHOP_TYPE_IFINDEX
1320 || nexthop->type == NEXTHOP_TYPE_IFNAME
1321 || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX
1322 || nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME
1323 || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX)
1324 rtnh->rtnh_ifindex = nexthop->ifindex;
1325 else
1326 rtnh->rtnh_ifindex = 0;
1327 }
1328 rtnh = RTNH_NEXT(rtnh);
1329
1330 if (cmd == RTM_NEWROUTE)
1331 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1332 }
1333 }
1334
1335 if (rta->rta_len > RTA_LENGTH (0))
1336 addattr_l (&req.n, 1024, RTA_MULTIPATH, RTA_DATA(rta),
1337 RTA_PAYLOAD(rta));
1338 }
1339
1340 /* If there is no useful nexthop then return. */
1341 if (nexthop_num == 0)
1342 {
1343 if (IS_ZEBRA_DEBUG_KERNEL)
1344 zlog_info ("netlink_route_multipath(): No useful nexthop.");
1345 return 0;
1346 }
1347
1348 skip:
1349
1350 /* Destination netlink address. */
1351 memset (&snl, 0, sizeof snl);
1352 snl.nl_family = AF_NETLINK;
1353
1354 if (family == AF_INET)
1355 nl = &netlink_cmd;
1356 else
1357 nl = &netlink;
1358
1359 /* Talk to netlink socket. */
1360 return netlink_talk (&req.n, nl);
1361}
1362
1363int
1364kernel_add_ipv4 (struct prefix *p, struct rib *rib)
1365{
1366 return netlink_route_multipath (RTM_NEWROUTE, p, rib, AF_INET);
1367}
1368
1369int
1370kernel_delete_ipv4 (struct prefix *p, struct rib *rib)
1371{
1372 return netlink_route_multipath (RTM_DELROUTE, p, rib, AF_INET);
1373}
1374
1375#ifdef HAVE_IPV6
1376int
1377kernel_add_ipv6 (struct prefix *p, struct rib *rib)
1378{
1379 return netlink_route_multipath (RTM_NEWROUTE, p, rib, AF_INET6);
1380}
1381
1382int
1383kernel_delete_ipv6 (struct prefix *p, struct rib *rib)
1384{
1385 return netlink_route_multipath (RTM_DELROUTE, p, rib, AF_INET6);
1386}
1387
1388/* Delete IPv6 route from the kernel. */
1389int
1390kernel_delete_ipv6_old (struct prefix_ipv6 *dest, struct in6_addr *gate,
1391 int index, int flags, int table)
1392{
1393 return netlink_route (RTM_DELROUTE, AF_INET6, &dest->prefix, dest->prefixlen,
1394 gate, index, flags, table);
1395}
1396#endif /* HAVE_IPV6 */
1397
1398/* Interface address modification. */
1399int
1400netlink_address (int cmd, int family, struct interface *ifp,
1401 struct connected *ifc)
1402{
1403 int bytelen;
1404 struct prefix *p;
1405
1406 struct
1407 {
1408 struct nlmsghdr n;
1409 struct ifaddrmsg ifa;
1410 char buf[1024];
1411 } req;
1412
1413 p = ifc->address;
1414 memset (&req, 0, sizeof req);
1415
1416 bytelen = (family == AF_INET ? 4 : 16);
1417
1418 req.n.nlmsg_len = NLMSG_LENGTH (sizeof(struct ifaddrmsg));
1419 req.n.nlmsg_flags = NLM_F_REQUEST;
1420 req.n.nlmsg_type = cmd;
1421 req.ifa.ifa_family = family;
1422
1423 req.ifa.ifa_index = ifp->ifindex;
1424 req.ifa.ifa_prefixlen = p->prefixlen;
1425
1426 addattr_l (&req.n, sizeof req, IFA_LOCAL, &p->u.prefix, bytelen);
1427
1428 if (family == AF_INET && cmd == RTM_NEWADDR)
1429 {
1430 if (if_is_broadcast (ifp) && ifc->destination)
1431 {
1432 p = ifc->destination;
1433 addattr_l(&req.n, sizeof req, IFA_BROADCAST, &p->u.prefix, bytelen);
1434 }
1435 }
1436
1437 if (CHECK_FLAG (ifc->flags, ZEBRA_IFA_SECONDARY))
1438 SET_FLAG (req.ifa.ifa_flags, IFA_F_SECONDARY);
1439
1440 if (ifc->label)
1441 addattr_l (&req.n, sizeof req, IFA_LABEL, ifc->label,
1442 strlen (ifc->label) + 1);
1443
1444 return netlink_talk (&req.n, &netlink_cmd);
1445}
1446
1447int
1448kernel_address_add_ipv4 (struct interface *ifp, struct connected *ifc)
1449{
1450 return netlink_address (RTM_NEWADDR, AF_INET, ifp, ifc);
1451}
1452
1453int
1454kernel_address_delete_ipv4 (struct interface *ifp, struct connected *ifc)
1455{
1456 return netlink_address (RTM_DELADDR, AF_INET, ifp, ifc);
1457}
1458
1459#include "thread.h"
1460
1461extern struct thread_master *master;
1462
1463/* Kernel route reflection. */
1464int
1465kernel_read (struct thread *thread)
1466{
1467 int ret;
1468 int sock;
1469
1470 sock = THREAD_FD (thread);
1471 ret = netlink_parse_info (netlink_information_fetch, &netlink);
1472 thread_add_read (master, kernel_read, NULL, netlink.sock);
1473
1474 return 0;
1475}
1476
1477/* Exported interface function. This function simply calls
1478 netlink_socket (). */
1479void
1480kernel_init ()
1481{
1482 unsigned long groups;
1483
1484 groups = RTMGRP_LINK|RTMGRP_IPV4_ROUTE|RTMGRP_IPV4_IFADDR;
1485#ifdef HAVE_IPV6
1486 groups |= RTMGRP_IPV6_ROUTE|RTMGRP_IPV6_IFADDR;
1487#endif /* HAVE_IPV6 */
1488 netlink_socket (&netlink, groups);
1489 netlink_socket (&netlink_cmd, 0);
1490
1491 /* Register kernel socket. */
1492 if (netlink.sock > 0)
1493 thread_add_read (master, kernel_read, NULL, netlink.sock);
1494}