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