blob: 94573aa53f2df3fa3c58cfd3ccfd0a4e723888aa [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
paul8fdcfde2003-01-19 20:52:55 +0000445 if (ifa->ifa_family == AF_INET6) {
paul00df0c12002-12-13 21:07:36 +0000446 peeronly = if_is_pointopoint (ifp) ||
447 ifa->ifa_prefixlen >= IPV6_MAX_PREFIXLEN - 1;
paul8fdcfde2003-01-19 20:52:55 +0000448 }
paul00df0c12002-12-13 21:07:36 +0000449#endif /* HAVE_IPV6*/
paul8fdcfde2003-01-19 20:52:55 +0000450 if (!(tb[IFA_LOCAL] && tb[IFA_ADDRESS])) {
451 /* FIXME: IPv6 Appears to have only IFA_ADDRESS */
452 peeronly=0;
453 }
paul00df0c12002-12-13 21:07:36 +0000454
455 /* network. prefixlen applies to IFA_ADDRESS rather than IFA_LOCAL */
456 if (tb[IFA_ADDRESS] && !peeronly)
457 addr = RTA_DATA (tb[IFA_ADDRESS]);
458 else if (tb[IFA_LOCAL])
459 addr = RTA_DATA (tb[IFA_LOCAL]);
460 else
461 addr = NULL;
462
463 /* broadcast/peer */
464 if (tb[IFA_BROADCAST])
465 broad = RTA_DATA (tb[IFA_BROADCAST]);
466 else if (tb[IFA_ADDRESS] && peeronly)
467 broad = RTA_DATA (tb[IFA_ADDRESS]); /* peer address specified */
468 else
469 broad = NULL;
470
paul718e3742002-12-13 20:15:29 +0000471 /* Flags. */
472 if (ifa->ifa_flags & IFA_F_SECONDARY)
473 SET_FLAG (flags, ZEBRA_IFA_SECONDARY);
474
475 /* Label */
476 if (tb[IFA_LABEL])
477 label = (char *) RTA_DATA (tb[IFA_LABEL]);
478
479 if (ifp && label && strcmp (ifp->name, label) == 0)
480 label = NULL;
481
482 /* Register interface address to the interface. */
483 if (ifa->ifa_family == AF_INET)
484 {
485 if (h->nlmsg_type == RTM_NEWADDR)
486 connected_add_ipv4 (ifp, flags,
487 (struct in_addr *) addr, ifa->ifa_prefixlen,
488 (struct in_addr *) broad, label);
489 else
490 connected_delete_ipv4 (ifp, flags,
491 (struct in_addr *) addr, ifa->ifa_prefixlen,
492 (struct in_addr *) broad, label);
493 }
494#ifdef HAVE_IPV6
495 if (ifa->ifa_family == AF_INET6)
496 {
497 if (h->nlmsg_type == RTM_NEWADDR)
498 connected_add_ipv6 (ifp,
499 (struct in6_addr *) addr, ifa->ifa_prefixlen,
500 (struct in6_addr *) broad);
501 else
502 connected_delete_ipv6 (ifp,
503 (struct in6_addr *) addr, ifa->ifa_prefixlen,
504 (struct in6_addr *) broad);
505 }
506#endif /* HAVE_IPV6*/
507
508 return 0;
509}
510
511/* Looking up routing table by netlink interface. */
512int
513netlink_routing_table (struct sockaddr_nl *snl, struct nlmsghdr *h)
514{
515 int len;
516 struct rtmsg *rtm;
517 struct rtattr *tb [RTA_MAX + 1];
518 u_char flags = 0;
519
520 char anyaddr[16] = {0};
521
522 int index;
523 int table;
524 void *dest;
525 void *gate;
526
527 rtm = NLMSG_DATA (h);
528
529 if (h->nlmsg_type != RTM_NEWROUTE)
530 return 0;
531 if (rtm->rtm_type != RTN_UNICAST)
532 return 0;
533
534 table = rtm->rtm_table;
535#if 0 /* we weed them out later in rib_weed_tables () */
536 if (table != RT_TABLE_MAIN && table != rtm_table_default)
537 return 0;
538#endif
539
540 len = h->nlmsg_len - NLMSG_LENGTH(sizeof (struct rtmsg));
541 if (len < 0)
542 return -1;
543
544 memset (tb, 0, sizeof tb);
545 netlink_parse_rtattr (tb, RTA_MAX, RTM_RTA (rtm), len);
546
547 if (rtm->rtm_flags & RTM_F_CLONED)
548 return 0;
549 if (rtm->rtm_protocol == RTPROT_REDIRECT)
550 return 0;
551 if (rtm->rtm_protocol == RTPROT_KERNEL)
552 return 0;
553
554 if (rtm->rtm_src_len != 0)
555 return 0;
556
557 /* Route which inserted by Zebra. */
558 if (rtm->rtm_protocol == RTPROT_ZEBRA)
559 flags |= ZEBRA_FLAG_SELFROUTE;
560
561 index = 0;
562 dest = NULL;
563 gate = NULL;
564
565 if (tb[RTA_OIF])
566 index = *(int *) RTA_DATA (tb[RTA_OIF]);
567
568 if (tb[RTA_DST])
569 dest = RTA_DATA (tb[RTA_DST]);
570 else
571 dest = anyaddr;
572
573 /* Multipath treatment is needed. */
574 if (tb[RTA_GATEWAY])
575 gate = RTA_DATA (tb[RTA_GATEWAY]);
576
577 if (rtm->rtm_family == AF_INET)
578 {
579 struct prefix_ipv4 p;
580 p.family = AF_INET;
581 memcpy (&p.prefix, dest, 4);
582 p.prefixlen = rtm->rtm_dst_len;
583
584 rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, flags, &p, gate, index, table, 0, 0);
585 }
586#ifdef HAVE_IPV6
587 if (rtm->rtm_family == AF_INET6)
588 {
589 struct prefix_ipv6 p;
590 p.family = AF_INET6;
591 memcpy (&p.prefix, dest, 16);
592 p.prefixlen = rtm->rtm_dst_len;
593
594 rib_add_ipv6 (ZEBRA_ROUTE_KERNEL, flags, &p, gate, index, table);
595 }
596#endif /* HAVE_IPV6 */
597
598 return 0;
599}
600
601struct message rtproto_str [] =
602{
603 {RTPROT_REDIRECT, "redirect"},
604 {RTPROT_KERNEL, "kernel"},
605 {RTPROT_BOOT, "boot"},
606 {RTPROT_STATIC, "static"},
607 {RTPROT_GATED, "GateD"},
608 {RTPROT_RA, "router advertisement"},
609 {RTPROT_MRT, "MRT"},
610 {RTPROT_ZEBRA, "Zebra"},
611#ifdef RTPROT_BIRD
612 {RTPROT_BIRD, "BIRD"},
613#endif /* RTPROT_BIRD */
614 {0, NULL}
615};
616
617/* Routing information change from the kernel. */
618int
619netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h)
620{
621 int len;
622 struct rtmsg *rtm;
623 struct rtattr *tb [RTA_MAX + 1];
624
625 char anyaddr[16] = {0};
626
627 int index;
628 int table;
629 void *dest;
630 void *gate;
631
632 rtm = NLMSG_DATA (h);
633
634 if (! (h->nlmsg_type == RTM_NEWROUTE || h->nlmsg_type == RTM_DELROUTE))
635 {
636 /* If this is not route add/delete message print warning. */
637 zlog_warn ("Kernel message: %d\n", h->nlmsg_type);
638 return 0;
639 }
640
641 /* Connected route. */
642 if (IS_ZEBRA_DEBUG_KERNEL)
643 zlog_info ("%s %s %s proto %s",
644 h->nlmsg_type == RTM_NEWROUTE ? "RTM_NEWROUTE" : "RTM_DELROUTE",
645 rtm->rtm_family == AF_INET ? "ipv4" : "ipv6",
646 rtm->rtm_type == RTN_UNICAST ? "unicast" : "multicast",
647 lookup (rtproto_str, rtm->rtm_protocol));
648
649 if (rtm->rtm_type != RTN_UNICAST)
650 {
651 return 0;
652 }
653
654 table = rtm->rtm_table;
655 if (table != RT_TABLE_MAIN && table != rtm_table_default)
656 {
657 return 0;
658 }
659
660 len = h->nlmsg_len - NLMSG_LENGTH(sizeof (struct rtmsg));
661 if (len < 0)
662 return -1;
663
664 memset (tb, 0, sizeof tb);
665 netlink_parse_rtattr (tb, RTA_MAX, RTM_RTA (rtm), len);
666
667 if (rtm->rtm_flags & RTM_F_CLONED)
668 return 0;
669 if (rtm->rtm_protocol == RTPROT_REDIRECT)
670 return 0;
671 if (rtm->rtm_protocol == RTPROT_KERNEL)
672 return 0;
673
674 if (rtm->rtm_protocol == RTPROT_ZEBRA && h->nlmsg_type == RTM_NEWROUTE)
675 return 0;
676
677 if (rtm->rtm_src_len != 0)
678 {
679 zlog_warn ("netlink_route_change(): no src len");
680 return 0;
681 }
682
683 index = 0;
684 dest = NULL;
685 gate = NULL;
686
687 if (tb[RTA_OIF])
688 index = *(int *) RTA_DATA (tb[RTA_OIF]);
689
690 if (tb[RTA_DST])
691 dest = RTA_DATA (tb[RTA_DST]);
692 else
693 dest = anyaddr;
694
695 if (tb[RTA_GATEWAY])
696 gate = RTA_DATA (tb[RTA_GATEWAY]);
697
698 if (rtm->rtm_family == AF_INET)
699 {
700 struct prefix_ipv4 p;
701 p.family = AF_INET;
702 memcpy (&p.prefix, dest, 4);
703 p.prefixlen = rtm->rtm_dst_len;
704
705 if (IS_ZEBRA_DEBUG_KERNEL)
706 {
707 if (h->nlmsg_type == RTM_NEWROUTE)
708 zlog_info ("RTM_NEWROUTE %s/%d",
709 inet_ntoa (p.prefix), p.prefixlen);
710 else
711 zlog_info ("RTM_DELROUTE %s/%d",
712 inet_ntoa (p.prefix), p.prefixlen);
713 }
714
715 if (h->nlmsg_type == RTM_NEWROUTE)
716 rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, index, table, 0, 0);
717 else
718 rib_delete_ipv4 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, index, table);
719 }
720
721#ifdef HAVE_IPV6
722 if (rtm->rtm_family == AF_INET6)
723 {
724 struct prefix_ipv6 p;
725 char buf[BUFSIZ];
726
727 p.family = AF_INET6;
728 memcpy (&p.prefix, dest, 16);
729 p.prefixlen = rtm->rtm_dst_len;
730
731 if (IS_ZEBRA_DEBUG_KERNEL)
732 {
733 if (h->nlmsg_type == RTM_NEWROUTE)
734 zlog_info ("RTM_NEWROUTE %s/%d",
735 inet_ntop (AF_INET6, &p.prefix, buf, BUFSIZ),
736 p.prefixlen);
737 else
738 zlog_info ("RTM_DELROUTE %s/%d",
739 inet_ntop (AF_INET6, &p.prefix, buf, BUFSIZ),
740 p.prefixlen);
741 }
742
743 if (h->nlmsg_type == RTM_NEWROUTE)
744 rib_add_ipv6 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, index, 0);
745 else
746 rib_delete_ipv6 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, index, 0);
747 }
748#endif /* HAVE_IPV6 */
749
750 return 0;
751}
752
753int
754netlink_link_change (struct sockaddr_nl *snl, struct nlmsghdr *h)
755{
756 int len;
757 struct ifinfomsg *ifi;
758 struct rtattr *tb [IFLA_MAX + 1];
759 struct interface *ifp;
760 char *name;
761
762 ifi = NLMSG_DATA (h);
763
764 if (! (h->nlmsg_type == RTM_NEWLINK || h->nlmsg_type == RTM_DELLINK))
765 {
766 /* If this is not link add/delete message so print warning. */
767 zlog_warn ("netlink_link_change: wrong kernel message %d\n",
768 h->nlmsg_type);
769 return 0;
770 }
771
772 len = h->nlmsg_len - NLMSG_LENGTH (sizeof (struct ifinfomsg));
773 if (len < 0)
774 return -1;
775
776 /* Looking up interface name. */
777 memset (tb, 0, sizeof tb);
778 netlink_parse_rtattr (tb, IFLA_MAX, IFLA_RTA (ifi), len);
779 if (tb[IFLA_IFNAME] == NULL)
780 return -1;
781 name = (char *)RTA_DATA(tb[IFLA_IFNAME]);
782
783 /* Add interface. */
784 if (h->nlmsg_type == RTM_NEWLINK)
785 {
786 ifp = if_lookup_by_name (name);
787
788 if (ifp == NULL || ! CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE))
789 {
790 if (ifp == NULL)
791 ifp = if_get_by_name (name);
792
793 ifp->ifindex = ifi->ifi_index;
794 ifp->flags = ifi->ifi_flags & 0x0000fffff;
795 ifp->mtu = *(int *)RTA_DATA (tb[IFLA_MTU]);
796 ifp->metric = 1;
797
798 /* If new link is added. */
799 if_add_update(ifp);
800 }
801 else
802 {
803 /* Interface status change. */
804 ifp->ifindex = ifi->ifi_index;
805 ifp->mtu = *(int *)RTA_DATA (tb[IFLA_MTU]);
806 ifp->metric = 1;
807
paul2e3b2e42002-12-13 21:03:13 +0000808 if (if_is_operative (ifp))
paul718e3742002-12-13 20:15:29 +0000809 {
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_down (ifp);
813 }
814 else
815 {
816 ifp->flags = ifi->ifi_flags & 0x0000fffff;
paul2e3b2e42002-12-13 21:03:13 +0000817 if (if_is_operative (ifp))
paul718e3742002-12-13 20:15:29 +0000818 if_up (ifp);
819 }
820 }
821 }
822 else
823 {
824 /* RTM_DELLINK. */
825 ifp = if_lookup_by_name (name);
826
827 if (ifp == NULL)
828 {
829 zlog (NULL, LOG_WARNING, "interface %s is deleted but can't find",
830 name);
831 return 0;
832 }
833
834 if_delete_update (ifp);
835 }
836
837 return 0;
838}
839
840int
841netlink_information_fetch (struct sockaddr_nl *snl, struct nlmsghdr *h)
842{
843 switch (h->nlmsg_type)
844 {
845 case RTM_NEWROUTE:
846 return netlink_route_change (snl, h);
847 break;
848 case RTM_DELROUTE:
849 return netlink_route_change (snl, h);
850 break;
851 case RTM_NEWLINK:
852 return netlink_link_change (snl, h);
853 break;
854 case RTM_DELLINK:
855 return netlink_link_change (snl, h);
856 break;
857 case RTM_NEWADDR:
858 return netlink_interface_addr (snl, h);
859 break;
860 case RTM_DELADDR:
861 return netlink_interface_addr (snl, h);
862 break;
863 default:
864 zlog_warn ("Unknown netlink nlmsg_type %d\n", h->nlmsg_type);
865 break;
866 }
867 return 0;
868}
869
870/* Interface lookup by netlink socket. */
871int
872interface_lookup_netlink ()
873{
874 int ret;
875
876 /* Get interface information. */
877 ret = netlink_request (AF_PACKET, RTM_GETLINK, &netlink_cmd);
878 if (ret < 0)
879 return ret;
880 ret = netlink_parse_info (netlink_interface, &netlink_cmd);
881 if (ret < 0)
882 return ret;
883
884 /* Get IPv4 address of the interfaces. */
885 ret = netlink_request (AF_INET, RTM_GETADDR, &netlink_cmd);
886 if (ret < 0)
887 return ret;
888 ret = netlink_parse_info (netlink_interface_addr, &netlink_cmd);
889 if (ret < 0)
890 return ret;
891
892#ifdef HAVE_IPV6
893 /* Get IPv6 address of the interfaces. */
894 ret = netlink_request (AF_INET6, RTM_GETADDR, &netlink_cmd);
895 if (ret < 0)
896 return ret;
897 ret = netlink_parse_info (netlink_interface_addr, &netlink_cmd);
898 if (ret < 0)
899 return ret;
900#endif /* HAVE_IPV6 */
901
902 return 0;
903}
904
905/* Routing table read function using netlink interface. Only called
906 bootstrap time. */
907int
908netlink_route_read ()
909{
910 int ret;
911
912 /* Get IPv4 routing table. */
913 ret = netlink_request (AF_INET, RTM_GETROUTE, &netlink_cmd);
914 if (ret < 0)
915 return ret;
916 ret = netlink_parse_info (netlink_routing_table, &netlink_cmd);
917 if (ret < 0)
918 return ret;
919
920#ifdef HAVE_IPV6
921 /* Get IPv6 routing table. */
922 ret = netlink_request (AF_INET6, RTM_GETROUTE, &netlink_cmd);
923 if (ret < 0)
924 return ret;
925 ret = netlink_parse_info (netlink_routing_table, &netlink_cmd);
926 if (ret < 0)
927 return ret;
928#endif /* HAVE_IPV6 */
929
930 return 0;
931}
932
933/* Utility function comes from iproute2.
934 Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru> */
935int
936addattr_l (struct nlmsghdr *n, int maxlen, int type, void *data, int alen)
937{
938 int len;
939 struct rtattr *rta;
940
941 len = RTA_LENGTH(alen);
942
943 if (NLMSG_ALIGN(n->nlmsg_len) + len > maxlen)
944 return -1;
945
946 rta = (struct rtattr*) (((char*)n) + NLMSG_ALIGN (n->nlmsg_len));
947 rta->rta_type = type;
948 rta->rta_len = len;
949 memcpy (RTA_DATA(rta), data, alen);
950 n->nlmsg_len = NLMSG_ALIGN (n->nlmsg_len) + len;
951
952 return 0;
953}
954
955int
956rta_addattr_l (struct rtattr *rta, int maxlen, int type, void *data, int alen)
957{
958 int len;
959 struct rtattr *subrta;
960
961 len = RTA_LENGTH(alen);
962
963 if (RTA_ALIGN(rta->rta_len) + len > maxlen)
964 return -1;
965
966 subrta = (struct rtattr*) (((char*)rta) + RTA_ALIGN (rta->rta_len));
967 subrta->rta_type = type;
968 subrta->rta_len = len;
969 memcpy (RTA_DATA(subrta), data, alen);
970 rta->rta_len = NLMSG_ALIGN (rta->rta_len) + len;
971
972 return 0;
973}
974
975/* Utility function comes from iproute2.
976 Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru> */
977int
978addattr32 (struct nlmsghdr *n, int maxlen, int type, int data)
979{
980 int len;
981 struct rtattr *rta;
982
983 len = RTA_LENGTH(4);
984
985 if (NLMSG_ALIGN (n->nlmsg_len) + len > maxlen)
986 return -1;
987
988 rta = (struct rtattr*) (((char*)n) + NLMSG_ALIGN (n->nlmsg_len));
989 rta->rta_type = type;
990 rta->rta_len = len;
991 memcpy (RTA_DATA(rta), &data, 4);
992 n->nlmsg_len = NLMSG_ALIGN (n->nlmsg_len) + len;
993
994 return 0;
995}
996
997static int
998netlink_talk_filter (struct sockaddr_nl *snl, struct nlmsghdr *h)
999{
1000 zlog_warn ("netlink_talk: ignoring message type 0x%04x", h->nlmsg_type);
1001 return 0;
1002}
1003
1004/* sendmsg() to netlink socket then recvmsg(). */
1005int
1006netlink_talk (struct nlmsghdr *n, struct nlsock *nl)
1007{
1008 int status;
1009 struct sockaddr_nl snl;
1010 struct iovec iov = { (void*) n, n->nlmsg_len };
1011 struct msghdr msg = {(void*) &snl, sizeof snl, &iov, 1, NULL, 0, 0};
1012 int flags = 0;
1013
1014 memset (&snl, 0, sizeof snl);
1015 snl.nl_family = AF_NETLINK;
1016
1017 n->nlmsg_seq = ++netlink_cmd.seq;
1018
1019 /* Request an acknowledgement by setting NLM_F_ACK */
1020 n->nlmsg_flags |= NLM_F_ACK;
1021
1022 if (IS_ZEBRA_DEBUG_KERNEL)
1023 zlog_info ("netlink_talk: %s type %s(%u), seq=%u", netlink_cmd.name,
1024 lookup (nlmsg_str, n->nlmsg_type), n->nlmsg_type,
1025 n->nlmsg_seq);
1026
1027 /* Send message to netlink interface. */
1028 status = sendmsg (nl->sock, &msg, 0);
1029 if (status < 0)
1030 {
1031 zlog (NULL, LOG_ERR, "netlink_talk sendmsg() error: %s",
1032 strerror (errno));
1033 return -1;
1034 }
1035
1036 /*
1037 * Change socket flags for blocking I/O.
1038 * This ensures we wait for a reply in netlink_parse_info().
1039 */
1040 if((flags = fcntl(nl->sock, F_GETFL, 0)) < 0)
1041 {
1042 zlog (NULL, LOG_ERR, "%s:%i F_GETFL error: %s",
1043 __FUNCTION__, __LINE__, strerror (errno));
1044 }
1045 flags &= ~O_NONBLOCK;
1046 if(fcntl(nl->sock, F_SETFL, flags) < 0)
1047 {
1048 zlog (NULL, LOG_ERR, "%s:%i F_SETFL error: %s",
1049 __FUNCTION__, __LINE__, strerror (errno));
1050 }
1051
1052 /*
1053 * Get reply from netlink socket.
1054 * The reply should either be an acknowlegement or an error.
1055 */
1056 status = netlink_parse_info (netlink_talk_filter, nl);
1057
1058 /* Restore socket flags for nonblocking I/O */
1059 flags |= O_NONBLOCK;
1060 if(fcntl(nl->sock, F_SETFL, flags) < 0)
1061 {
1062 zlog (NULL, LOG_ERR, "%s:%i F_SETFL error: %s",
1063 __FUNCTION__, __LINE__, strerror (errno));
1064 }
1065
1066 return status;
1067}
1068
1069/* Routing table change via netlink interface. */
1070int
1071netlink_route (int cmd, int family, void *dest, int length, void *gate,
1072 int index, int zebra_flags, int table)
1073{
1074 int ret;
1075 int bytelen;
1076 struct sockaddr_nl snl;
1077 int discard;
1078
1079 struct
1080 {
1081 struct nlmsghdr n;
1082 struct rtmsg r;
1083 char buf[1024];
1084 } req;
1085
1086 memset (&req, 0, sizeof req);
1087
1088 bytelen = (family == AF_INET ? 4 : 16);
1089
1090 req.n.nlmsg_len = NLMSG_LENGTH (sizeof (struct rtmsg));
1091 req.n.nlmsg_flags = NLM_F_CREATE | NLM_F_REQUEST;
1092 req.n.nlmsg_type = cmd;
1093 req.r.rtm_family = family;
1094 req.r.rtm_table = table;
1095 req.r.rtm_dst_len = length;
1096
1097 if (zebra_flags & ZEBRA_FLAG_BLACKHOLE)
1098 discard = 1;
1099 else
1100 discard = 0;
1101
1102 if (cmd == RTM_NEWROUTE)
1103 {
1104 req.r.rtm_protocol = RTPROT_ZEBRA;
1105 req.r.rtm_scope = RT_SCOPE_UNIVERSE;
1106
1107 if (discard)
1108 req.r.rtm_type = RTN_BLACKHOLE;
1109 else
1110 req.r.rtm_type = RTN_UNICAST;
1111 }
1112
1113 if (dest)
1114 addattr_l (&req.n, sizeof req, RTA_DST, dest, bytelen);
1115
1116 if (! discard)
1117 {
1118 if (gate)
1119 addattr_l (&req.n, sizeof req, RTA_GATEWAY, gate, bytelen);
1120 if (index > 0)
1121 addattr32 (&req.n, sizeof req, RTA_OIF, index);
1122 }
1123
1124 /* Destination netlink address. */
1125 memset (&snl, 0, sizeof snl);
1126 snl.nl_family = AF_NETLINK;
1127
1128 /* Talk to netlink socket. */
1129 ret = netlink_talk (&req.n, &netlink);
1130 if (ret < 0)
1131 return -1;
1132
1133 return 0;
1134}
1135
1136/* Routing table change via netlink interface. */
1137int
1138netlink_route_multipath (int cmd, struct prefix *p, struct rib *rib,
1139 int family)
1140{
1141 int bytelen;
1142 struct sockaddr_nl snl;
1143 struct nexthop *nexthop = NULL;
1144 int nexthop_num = 0;
1145 struct nlsock *nl;
1146 int discard;
1147
1148 struct
1149 {
1150 struct nlmsghdr n;
1151 struct rtmsg r;
1152 char buf[1024];
1153 } req;
1154
1155 memset (&req, 0, sizeof req);
1156
1157 bytelen = (family == AF_INET ? 4 : 16);
1158
1159 req.n.nlmsg_len = NLMSG_LENGTH (sizeof (struct rtmsg));
1160 req.n.nlmsg_flags = NLM_F_CREATE | NLM_F_REQUEST;
1161 req.n.nlmsg_type = cmd;
1162 req.r.rtm_family = family;
1163 req.r.rtm_table = rib->table;
1164 req.r.rtm_dst_len = p->prefixlen;
1165
1166 if (rib->flags & ZEBRA_FLAG_BLACKHOLE)
1167 discard = 1;
1168 else
1169 discard = 0;
1170
1171 if (cmd == RTM_NEWROUTE)
1172 {
1173 req.r.rtm_protocol = RTPROT_ZEBRA;
1174 req.r.rtm_scope = RT_SCOPE_UNIVERSE;
1175
1176 if (discard)
1177 req.r.rtm_type = RTN_BLACKHOLE;
1178 else
1179 req.r.rtm_type = RTN_UNICAST;
1180 }
1181
1182 addattr_l (&req.n, sizeof req, RTA_DST, &p->u.prefix, bytelen);
1183
1184 /* Metric. */
1185 addattr32 (&req.n, sizeof req, RTA_PRIORITY, rib->metric);
1186
1187 if (discard)
1188 {
1189 if (cmd == RTM_NEWROUTE)
1190 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
1191 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1192 goto skip;
1193 }
1194
1195 /* Multipath case. */
1196 if (rib->nexthop_active_num == 1 || MULTIPATH_NUM == 1)
1197 {
1198 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
1199 {
1200 if ((cmd == RTM_NEWROUTE
1201 && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))
1202 || (cmd == RTM_DELROUTE
1203 && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)))
1204 {
1205 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
1206 {
1207 if (nexthop->rtype == NEXTHOP_TYPE_IPV4
1208 || nexthop->rtype == NEXTHOP_TYPE_IPV4_IFINDEX)
1209 addattr_l (&req.n, sizeof req, RTA_GATEWAY,
1210 &nexthop->rgate.ipv4, bytelen);
1211#ifdef HAVE_IPV6
1212 if (nexthop->rtype == NEXTHOP_TYPE_IPV6
1213 || nexthop->rtype == NEXTHOP_TYPE_IPV6_IFINDEX
1214 || nexthop->rtype == NEXTHOP_TYPE_IPV6_IFNAME)
1215 addattr_l (&req.n, sizeof req, RTA_GATEWAY,
1216 &nexthop->rgate.ipv6, bytelen);
1217#endif /* HAVE_IPV6 */
1218 if (nexthop->rtype == NEXTHOP_TYPE_IFINDEX
1219 || nexthop->rtype == NEXTHOP_TYPE_IFNAME
1220 || nexthop->rtype == NEXTHOP_TYPE_IPV4_IFINDEX
1221 || nexthop->rtype == NEXTHOP_TYPE_IPV6_IFINDEX
1222 || nexthop->rtype == NEXTHOP_TYPE_IPV6_IFNAME)
1223 addattr32 (&req.n, sizeof req, RTA_OIF,
1224 nexthop->rifindex);
1225 }
1226 else
1227 {
1228 if (nexthop->type == NEXTHOP_TYPE_IPV4
1229 || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX)
1230 addattr_l (&req.n, sizeof req, RTA_GATEWAY,
1231 &nexthop->gate.ipv4, bytelen);
1232#ifdef HAVE_IPV6
1233 if (nexthop->type == NEXTHOP_TYPE_IPV6
1234 || nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME
1235 || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX)
1236 addattr_l (&req.n, sizeof req, RTA_GATEWAY,
1237 &nexthop->gate.ipv6, bytelen);
1238#endif /* HAVE_IPV6 */
1239 if (nexthop->type == NEXTHOP_TYPE_IFINDEX
1240 || nexthop->type == NEXTHOP_TYPE_IFNAME
1241 || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX
1242 || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX
1243 || nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME)
1244 addattr32 (&req.n, sizeof req, RTA_OIF, nexthop->ifindex);
1245 }
1246
1247 if (cmd == RTM_NEWROUTE)
1248 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1249
1250 nexthop_num++;
1251 break;
1252 }
1253 }
1254 }
1255 else
1256 {
1257 char buf[1024];
1258 struct rtattr *rta = (void *) buf;
1259 struct rtnexthop *rtnh;
1260
1261 rta->rta_type = RTA_MULTIPATH;
1262 rta->rta_len = RTA_LENGTH(0);
1263 rtnh = RTA_DATA(rta);
1264
1265 nexthop_num = 0;
1266 for (nexthop = rib->nexthop;
1267 nexthop && (MULTIPATH_NUM == 0 || nexthop_num < MULTIPATH_NUM);
1268 nexthop = nexthop->next)
1269 {
1270 if ((cmd == RTM_NEWROUTE
1271 && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))
1272 || (cmd == RTM_DELROUTE
1273 && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)))
1274 {
1275 nexthop_num++;
1276
1277 rtnh->rtnh_len = sizeof (*rtnh);
1278 rtnh->rtnh_flags = 0;
1279 rtnh->rtnh_hops = 0;
1280 rta->rta_len += rtnh->rtnh_len;
1281
1282 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
1283 {
1284 if (nexthop->rtype == NEXTHOP_TYPE_IPV4
1285 || nexthop->rtype == NEXTHOP_TYPE_IPV4_IFINDEX)
1286 {
1287 rta_addattr_l (rta, 4096, RTA_GATEWAY,
1288 &nexthop->rgate.ipv4, bytelen);
1289 rtnh->rtnh_len += sizeof (struct rtattr) + 4;
1290 }
1291#ifdef HAVE_IPV6
1292 if (nexthop->rtype == NEXTHOP_TYPE_IPV6
1293 || nexthop->rtype == NEXTHOP_TYPE_IPV6_IFNAME
1294 || nexthop->rtype == NEXTHOP_TYPE_IPV6_IFINDEX)
1295 rta_addattr_l (rta, 4096, RTA_GATEWAY,
1296 &nexthop->rgate.ipv6, bytelen);
1297#endif /* HAVE_IPV6 */
1298 /* ifindex */
1299 if (nexthop->rtype == NEXTHOP_TYPE_IFINDEX
1300 || nexthop->rtype == NEXTHOP_TYPE_IFNAME
1301 || nexthop->rtype == NEXTHOP_TYPE_IPV4_IFINDEX
1302 || nexthop->rtype == NEXTHOP_TYPE_IPV6_IFINDEX
1303 || nexthop->rtype == NEXTHOP_TYPE_IPV6_IFNAME)
1304 rtnh->rtnh_ifindex = nexthop->rifindex;
1305 else
1306 rtnh->rtnh_ifindex = 0;
1307 }
1308 else
1309 {
1310 if (nexthop->type == NEXTHOP_TYPE_IPV4
1311 || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX)
1312 {
1313 rta_addattr_l (rta, 4096, RTA_GATEWAY,
1314 &nexthop->gate.ipv4, bytelen);
1315 rtnh->rtnh_len += sizeof (struct rtattr) + 4;
1316 }
1317#ifdef HAVE_IPV6
1318 if (nexthop->type == NEXTHOP_TYPE_IPV6
1319 || nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME
1320 || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX)
1321 rta_addattr_l (rta, 4096, RTA_GATEWAY,
1322 &nexthop->gate.ipv6, bytelen);
1323#endif /* HAVE_IPV6 */
1324 /* ifindex */
1325 if (nexthop->type == NEXTHOP_TYPE_IFINDEX
1326 || nexthop->type == NEXTHOP_TYPE_IFNAME
1327 || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX
1328 || nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME
1329 || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX)
1330 rtnh->rtnh_ifindex = nexthop->ifindex;
1331 else
1332 rtnh->rtnh_ifindex = 0;
1333 }
1334 rtnh = RTNH_NEXT(rtnh);
1335
1336 if (cmd == RTM_NEWROUTE)
1337 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1338 }
1339 }
1340
1341 if (rta->rta_len > RTA_LENGTH (0))
1342 addattr_l (&req.n, 1024, RTA_MULTIPATH, RTA_DATA(rta),
1343 RTA_PAYLOAD(rta));
1344 }
1345
1346 /* If there is no useful nexthop then return. */
1347 if (nexthop_num == 0)
1348 {
1349 if (IS_ZEBRA_DEBUG_KERNEL)
1350 zlog_info ("netlink_route_multipath(): No useful nexthop.");
1351 return 0;
1352 }
1353
1354 skip:
1355
1356 /* Destination netlink address. */
1357 memset (&snl, 0, sizeof snl);
1358 snl.nl_family = AF_NETLINK;
1359
1360 if (family == AF_INET)
1361 nl = &netlink_cmd;
1362 else
1363 nl = &netlink;
1364
1365 /* Talk to netlink socket. */
1366 return netlink_talk (&req.n, nl);
1367}
1368
1369int
1370kernel_add_ipv4 (struct prefix *p, struct rib *rib)
1371{
1372 return netlink_route_multipath (RTM_NEWROUTE, p, rib, AF_INET);
1373}
1374
1375int
1376kernel_delete_ipv4 (struct prefix *p, struct rib *rib)
1377{
1378 return netlink_route_multipath (RTM_DELROUTE, p, rib, AF_INET);
1379}
1380
1381#ifdef HAVE_IPV6
1382int
1383kernel_add_ipv6 (struct prefix *p, struct rib *rib)
1384{
1385 return netlink_route_multipath (RTM_NEWROUTE, p, rib, AF_INET6);
1386}
1387
1388int
1389kernel_delete_ipv6 (struct prefix *p, struct rib *rib)
1390{
1391 return netlink_route_multipath (RTM_DELROUTE, p, rib, AF_INET6);
1392}
1393
1394/* Delete IPv6 route from the kernel. */
1395int
1396kernel_delete_ipv6_old (struct prefix_ipv6 *dest, struct in6_addr *gate,
1397 int index, int flags, int table)
1398{
1399 return netlink_route (RTM_DELROUTE, AF_INET6, &dest->prefix, dest->prefixlen,
1400 gate, index, flags, table);
1401}
1402#endif /* HAVE_IPV6 */
1403
1404/* Interface address modification. */
1405int
1406netlink_address (int cmd, int family, struct interface *ifp,
1407 struct connected *ifc)
1408{
1409 int bytelen;
1410 struct prefix *p;
1411
1412 struct
1413 {
1414 struct nlmsghdr n;
1415 struct ifaddrmsg ifa;
1416 char buf[1024];
1417 } req;
1418
1419 p = ifc->address;
1420 memset (&req, 0, sizeof req);
1421
1422 bytelen = (family == AF_INET ? 4 : 16);
1423
1424 req.n.nlmsg_len = NLMSG_LENGTH (sizeof(struct ifaddrmsg));
1425 req.n.nlmsg_flags = NLM_F_REQUEST;
1426 req.n.nlmsg_type = cmd;
1427 req.ifa.ifa_family = family;
1428
1429 req.ifa.ifa_index = ifp->ifindex;
1430 req.ifa.ifa_prefixlen = p->prefixlen;
1431
1432 addattr_l (&req.n, sizeof req, IFA_LOCAL, &p->u.prefix, bytelen);
1433
1434 if (family == AF_INET && cmd == RTM_NEWADDR)
1435 {
1436 if (if_is_broadcast (ifp) && ifc->destination)
1437 {
1438 p = ifc->destination;
1439 addattr_l(&req.n, sizeof req, IFA_BROADCAST, &p->u.prefix, bytelen);
1440 }
1441 }
1442
1443 if (CHECK_FLAG (ifc->flags, ZEBRA_IFA_SECONDARY))
1444 SET_FLAG (req.ifa.ifa_flags, IFA_F_SECONDARY);
1445
1446 if (ifc->label)
1447 addattr_l (&req.n, sizeof req, IFA_LABEL, ifc->label,
1448 strlen (ifc->label) + 1);
1449
1450 return netlink_talk (&req.n, &netlink_cmd);
1451}
1452
1453int
1454kernel_address_add_ipv4 (struct interface *ifp, struct connected *ifc)
1455{
1456 return netlink_address (RTM_NEWADDR, AF_INET, ifp, ifc);
1457}
1458
1459int
1460kernel_address_delete_ipv4 (struct interface *ifp, struct connected *ifc)
1461{
1462 return netlink_address (RTM_DELADDR, AF_INET, ifp, ifc);
1463}
1464
paul718e3742002-12-13 20:15:29 +00001465
1466extern struct thread_master *master;
1467
1468/* Kernel route reflection. */
1469int
1470kernel_read (struct thread *thread)
1471{
1472 int ret;
1473 int sock;
1474
1475 sock = THREAD_FD (thread);
1476 ret = netlink_parse_info (netlink_information_fetch, &netlink);
1477 thread_add_read (master, kernel_read, NULL, netlink.sock);
1478
1479 return 0;
1480}
1481
1482/* Exported interface function. This function simply calls
1483 netlink_socket (). */
1484void
1485kernel_init ()
1486{
1487 unsigned long groups;
1488
1489 groups = RTMGRP_LINK|RTMGRP_IPV4_ROUTE|RTMGRP_IPV4_IFADDR;
1490#ifdef HAVE_IPV6
1491 groups |= RTMGRP_IPV6_ROUTE|RTMGRP_IPV6_IFADDR;
1492#endif /* HAVE_IPV6 */
1493 netlink_socket (&netlink, groups);
1494 netlink_socket (&netlink_cmd, 0);
1495
1496 /* Register kernel socket. */
1497 if (netlink.sock > 0)
1498 thread_add_read (master, kernel_read, NULL, netlink.sock);
1499}