blob: b84cdbac364eafc235472b65e70636e3b6576958 [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
paul5f37d862003-04-19 00:11:28 +0000126int set_netlink_blocking(struct nlsock *nl, int *flags)
127{
128
129 /* Change socket flags for blocking I/O. */
130 if((*flags = fcntl(nl->sock, F_GETFL, 0)) < 0)
131 {
132 zlog (NULL, LOG_ERR, "%s:%i F_GETFL error: %s",
133 __FUNCTION__, __LINE__, strerror (errno));
134 return -1;
135 }
136 *flags &= ~O_NONBLOCK;
137 if(fcntl(nl->sock, F_SETFL, *flags) < 0)
138 {
139 zlog (NULL, LOG_ERR, "%s:%i F_SETFL error: %s",
140 __FUNCTION__, __LINE__, strerror (errno));
141 return -1;
142 }
143 return 0;
144}
145
146int set_netlink_nonblocking(struct nlsock *nl, int *flags)
147{
148 /* Restore socket flags for nonblocking I/O */
149 *flags |= O_NONBLOCK;
150 if(fcntl(nl->sock, F_SETFL, *flags) < 0)
151 {
152 zlog (NULL, LOG_ERR, "%s:%i F_SETFL error: %s",
153 __FUNCTION__, __LINE__, strerror (errno));
154 return -1;
155 }
156 return 0;
157}
158
paul718e3742002-12-13 20:15:29 +0000159/* Get type specified information from netlink. */
160static int
161netlink_request (int family, int type, struct nlsock *nl)
162{
163 int ret;
164 struct sockaddr_nl snl;
165
166 struct
167 {
168 struct nlmsghdr nlh;
169 struct rtgenmsg g;
170 } req;
171
172
173 /* Check netlink socket. */
174 if (nl->sock < 0)
175 {
176 zlog (NULL, LOG_ERR, "%s socket isn't active.", nl->name);
177 return -1;
178 }
179
180 memset (&snl, 0, sizeof snl);
181 snl.nl_family = AF_NETLINK;
182
183 req.nlh.nlmsg_len = sizeof req;
184 req.nlh.nlmsg_type = type;
185 req.nlh.nlmsg_flags = NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST;
186 req.nlh.nlmsg_pid = 0;
187 req.nlh.nlmsg_seq = ++nl->seq;
188 req.g.rtgen_family = family;
189
190 ret = sendto (nl->sock, (void*) &req, sizeof req, 0,
191 (struct sockaddr*) &snl, sizeof snl);
192 if (ret < 0)
193 {
194 zlog (NULL, LOG_ERR, "%s sendto failed: %s", nl->name, strerror (errno));
195 return -1;
196 }
197 return 0;
198}
199
200/* Receive message from netlink interface and pass those information
201 to the given function. */
202static int
203netlink_parse_info (int (*filter) (struct sockaddr_nl *, struct nlmsghdr *),
204 struct nlsock *nl)
205{
206 int status;
207 int ret = 0;
208 int error;
209
210 while (1)
211 {
212 char buf[4096];
213 struct iovec iov = { buf, sizeof buf };
214 struct sockaddr_nl snl;
215 struct msghdr msg = { (void*)&snl, sizeof snl, &iov, 1, NULL, 0, 0};
216 struct nlmsghdr *h;
217
218 status = recvmsg (nl->sock, &msg, 0);
219
220 if (status < 0)
221 {
222 if (errno == EINTR)
223 continue;
224 if (errno == EWOULDBLOCK || errno == EAGAIN)
225 break;
226 zlog (NULL, LOG_ERR, "%s recvmsg overrun", nl->name);
227 continue;
228 }
229
230 if (status == 0)
231 {
232 zlog (NULL, LOG_ERR, "%s EOF", nl->name);
233 return -1;
234 }
235
236 if (msg.msg_namelen != sizeof snl)
237 {
238 zlog (NULL, LOG_ERR, "%s sender address length error: length %d",
239 nl->name, msg.msg_namelen);
240 return -1;
241 }
242
243 for (h = (struct nlmsghdr *) buf; NLMSG_OK (h, status);
244 h = NLMSG_NEXT (h, status))
245 {
246 /* Finish of reading. */
247 if (h->nlmsg_type == NLMSG_DONE)
248 return ret;
249
250 /* Error handling. */
251 if (h->nlmsg_type == NLMSG_ERROR)
252 {
253 struct nlmsgerr *err = (struct nlmsgerr *) NLMSG_DATA (h);
254
255 /* If the error field is zero, then this is an ACK */
256 if (err->error == 0)
257 {
258 if (IS_ZEBRA_DEBUG_KERNEL)
259 {
260 zlog_info("%s: %s ACK: type=%s(%u), seq=%u, pid=%d",
261 __FUNCTION__, nl->name,
262 lookup (nlmsg_str, err->msg.nlmsg_type),
263 err->msg.nlmsg_type, err->msg.nlmsg_seq,
264 err->msg.nlmsg_pid);
265 }
266
267 /* return if not a multipart message, otherwise continue */
268 if(!(h->nlmsg_flags & NLM_F_MULTI))
269 {
270 return 0;
271 }
272 continue;
273 }
274
275 if (h->nlmsg_len < NLMSG_LENGTH (sizeof (struct nlmsgerr)))
276 {
277 zlog (NULL, LOG_ERR, "%s error: message truncated",
278 nl->name);
279 return -1;
280 }
pauld753e9e2003-01-22 19:45:50 +0000281
282 /* Deal with Error Noise - MAG*/
283 {
284 int loglvl = LOG_ERR;
285 int errnum = err->error;
286 int msg_type = err->msg.nlmsg_type;
287
288 if (nl == &netlink_cmd
289 && (-errnum == ENODEV || -errnum == ESRCH)
290 && (msg_type == RTM_NEWROUTE
291 || msg_type == RTM_DELROUTE))
292 loglvl = LOG_DEBUG;
293
294 zlog (NULL, loglvl, "%s error: %s, type=%s(%u), "
295 "seq=%u, pid=%d",
296 nl->name, strerror (-errnum),
297 lookup (nlmsg_str, msg_type),
298 msg_type, err->msg.nlmsg_seq,
paul718e3742002-12-13 20:15:29 +0000299 err->msg.nlmsg_pid);
pauld753e9e2003-01-22 19:45:50 +0000300 }
paul718e3742002-12-13 20:15:29 +0000301 /*
302 ret = -1;
303 continue;
304 */
305 return -1;
306 }
307
308 /* OK we got netlink message. */
309 if (IS_ZEBRA_DEBUG_KERNEL)
310 zlog_info ("netlink_parse_info: %s type %s(%u), seq=%u, pid=%d",
311 nl->name,
312 lookup (nlmsg_str, h->nlmsg_type), h->nlmsg_type,
313 h->nlmsg_seq, h->nlmsg_pid);
314
315 /* skip unsolicited messages originating from command socket */
316 if (nl != &netlink_cmd && h->nlmsg_pid == netlink_cmd.snl.nl_pid)
317 {
318 if (IS_ZEBRA_DEBUG_KERNEL)
319 zlog_info ("netlink_parse_info: %s packet comes from %s",
320 nl->name, netlink_cmd.name);
321 continue;
322 }
323
324 error = (*filter) (&snl, h);
325 if (error < 0)
326 {
327 zlog (NULL, LOG_ERR, "%s filter function error", nl->name);
328 ret = error;
329 }
330 }
331
332 /* After error care. */
333 if (msg.msg_flags & MSG_TRUNC)
334 {
335 zlog (NULL, LOG_ERR, "%s error: message truncated", nl->name);
336 continue;
337 }
338 if (status)
339 {
340 zlog (NULL, LOG_ERR, "%s error: data remnant size %d", nl->name,
341 status);
342 return -1;
343 }
344 }
345 return ret;
346}
347
348/* Utility function for parse rtattr. */
349static void
350netlink_parse_rtattr (struct rtattr **tb, int max, struct rtattr *rta, int len)
351{
352 while (RTA_OK(rta, len))
353 {
354 if (rta->rta_type <= max)
355 tb[rta->rta_type] = rta;
356 rta = RTA_NEXT(rta,len);
357 }
358}
359
360/* Called from interface_lookup_netlink(). This function is only used
361 during bootstrap. */
362int
363netlink_interface (struct sockaddr_nl *snl, struct nlmsghdr *h)
364{
365 int len;
366 struct ifinfomsg *ifi;
367 struct rtattr *tb[IFLA_MAX + 1];
368 struct interface *ifp;
369 char *name;
370 int i;
371
372 ifi = NLMSG_DATA (h);
373
374 if (h->nlmsg_type != RTM_NEWLINK)
375 return 0;
376
377 len = h->nlmsg_len - NLMSG_LENGTH (sizeof (struct ifinfomsg));
378 if (len < 0)
379 return -1;
380
381 /* Looking up interface name. */
382 memset (tb, 0, sizeof tb);
383 netlink_parse_rtattr (tb, IFLA_MAX, IFLA_RTA (ifi), len);
384 if (tb[IFLA_IFNAME] == NULL)
385 return -1;
386 name = (char *)RTA_DATA(tb[IFLA_IFNAME]);
387
388 /* Add interface. */
389 ifp = if_get_by_name (name);
390
391 ifp->ifindex = ifi->ifi_index;
392 ifp->flags = ifi->ifi_flags & 0x0000fffff;
393 ifp->mtu = *(int *)RTA_DATA (tb[IFLA_MTU]);
394 ifp->metric = 1;
395
396 /* Hardware type and address. */
397 ifp->hw_type = ifi->ifi_type;
398
399 if (tb[IFLA_ADDRESS])
400 {
401 int hw_addr_len;
402
403 hw_addr_len = RTA_PAYLOAD(tb[IFLA_ADDRESS]);
404
405 if (hw_addr_len > INTERFACE_HWADDR_MAX)
406 zlog_warn ("Hardware address is too large: %d", hw_addr_len);
407 else
408 {
409 ifp->hw_addr_len = hw_addr_len;
410 memcpy (ifp->hw_addr, RTA_DATA(tb[IFLA_ADDRESS]), hw_addr_len);
411
412 for (i = 0; i < hw_addr_len; i++)
413 if (ifp->hw_addr[i] != 0)
414 break;
415
416 if (i == hw_addr_len)
417 ifp->hw_addr_len = 0;
418 else
419 ifp->hw_addr_len = hw_addr_len;
420 }
421 }
422
423 if_add_update (ifp);
424
425 return 0;
426}
427
428/* Lookup interface IPv4/IPv6 address. */
429int
430netlink_interface_addr (struct sockaddr_nl *snl, struct nlmsghdr *h)
431{
432 int len;
433 struct ifaddrmsg *ifa;
434 struct rtattr *tb [IFA_MAX + 1];
435 struct interface *ifp;
436 void *addr = NULL;
437 void *broad = NULL;
438 u_char flags = 0;
439 char *label = NULL;
paul00df0c12002-12-13 21:07:36 +0000440 int peeronly = 0;
paul718e3742002-12-13 20:15:29 +0000441
442 ifa = NLMSG_DATA (h);
443
444 if (ifa->ifa_family != AF_INET
445#ifdef HAVE_IPV6
446 && ifa->ifa_family != AF_INET6
447#endif /* HAVE_IPV6 */
448 )
449 return 0;
450
451 if (h->nlmsg_type != RTM_NEWADDR && h->nlmsg_type != RTM_DELADDR)
452 return 0;
453
454 len = h->nlmsg_len - NLMSG_LENGTH(sizeof (struct ifaddrmsg));
455 if (len < 0)
456 return -1;
457
458 memset (tb, 0, sizeof tb);
459 netlink_parse_rtattr (tb, IFA_MAX, IFA_RTA (ifa), len);
460
461 ifp = if_lookup_by_index (ifa->ifa_index);
462 if (ifp == NULL)
463 {
464 zlog_err ("netlink_interface_addr can't find interface by index %d",
465 ifa->ifa_index);
466 return -1;
467 }
468
paul00df0c12002-12-13 21:07:36 +0000469 if (IS_ZEBRA_DEBUG_KERNEL) /* remove this line to see initial ifcfg */
paul718e3742002-12-13 20:15:29 +0000470 {
paul00df0c12002-12-13 21:07:36 +0000471 char buf[BUFSIZ];
472 zlog_info ("netlink_interface_addr %s %s/%d:",
473 lookup (nlmsg_str, h->nlmsg_type),
474 ifp->name, ifa->ifa_prefixlen);
paul718e3742002-12-13 20:15:29 +0000475 if (tb[IFA_LOCAL])
paul00df0c12002-12-13 21:07:36 +0000476 zlog_info (" IFA_LOCAL %s", inet_ntop (ifa->ifa_family,
477 RTA_DATA (tb[IFA_LOCAL]), buf, BUFSIZ));
paul718e3742002-12-13 20:15:29 +0000478 if (tb[IFA_ADDRESS])
paul00df0c12002-12-13 21:07:36 +0000479 zlog_info (" IFA_ADDRESS %s", inet_ntop (ifa->ifa_family,
480 RTA_DATA (tb[IFA_ADDRESS]), buf, BUFSIZ));
paul718e3742002-12-13 20:15:29 +0000481 if (tb[IFA_BROADCAST])
paul00df0c12002-12-13 21:07:36 +0000482 zlog_info (" IFA_BROADCAST %s", inet_ntop (ifa->ifa_family,
483 RTA_DATA (tb[IFA_BROADCAST]), buf, BUFSIZ));
484 if (tb[IFA_LABEL] && strcmp (ifp->name, RTA_DATA (tb[IFA_LABEL])))
485 zlog_info (" IFA_LABEL %s", RTA_DATA (tb[IFA_LABEL]));
paul718e3742002-12-13 20:15:29 +0000486 }
487
paul00df0c12002-12-13 21:07:36 +0000488 /* peer or broadcast network? */
489 if (ifa->ifa_family == AF_INET)
490 peeronly = if_is_pointopoint (ifp) ||
491 ifa->ifa_prefixlen >= IPV4_MAX_PREFIXLEN - 1;
492#ifdef HAVE_IPV6
paul8fdcfde2003-01-19 20:52:55 +0000493 if (ifa->ifa_family == AF_INET6) {
paul00df0c12002-12-13 21:07:36 +0000494 peeronly = if_is_pointopoint (ifp) ||
495 ifa->ifa_prefixlen >= IPV6_MAX_PREFIXLEN - 1;
paul8fdcfde2003-01-19 20:52:55 +0000496 }
paul00df0c12002-12-13 21:07:36 +0000497#endif /* HAVE_IPV6*/
paul8fdcfde2003-01-19 20:52:55 +0000498 if (!(tb[IFA_LOCAL] && tb[IFA_ADDRESS])) {
499 /* FIXME: IPv6 Appears to have only IFA_ADDRESS */
500 peeronly=0;
501 }
paul00df0c12002-12-13 21:07:36 +0000502
503 /* network. prefixlen applies to IFA_ADDRESS rather than IFA_LOCAL */
504 if (tb[IFA_ADDRESS] && !peeronly)
505 addr = RTA_DATA (tb[IFA_ADDRESS]);
506 else if (tb[IFA_LOCAL])
507 addr = RTA_DATA (tb[IFA_LOCAL]);
508 else
509 addr = NULL;
510
511 /* broadcast/peer */
512 if (tb[IFA_BROADCAST])
513 broad = RTA_DATA (tb[IFA_BROADCAST]);
514 else if (tb[IFA_ADDRESS] && peeronly)
515 broad = RTA_DATA (tb[IFA_ADDRESS]); /* peer address specified */
516 else
517 broad = NULL;
518
paul718e3742002-12-13 20:15:29 +0000519 /* Flags. */
520 if (ifa->ifa_flags & IFA_F_SECONDARY)
521 SET_FLAG (flags, ZEBRA_IFA_SECONDARY);
522
523 /* Label */
524 if (tb[IFA_LABEL])
525 label = (char *) RTA_DATA (tb[IFA_LABEL]);
526
527 if (ifp && label && strcmp (ifp->name, label) == 0)
528 label = NULL;
529
530 /* Register interface address to the interface. */
531 if (ifa->ifa_family == AF_INET)
532 {
533 if (h->nlmsg_type == RTM_NEWADDR)
534 connected_add_ipv4 (ifp, flags,
535 (struct in_addr *) addr, ifa->ifa_prefixlen,
536 (struct in_addr *) broad, label);
537 else
538 connected_delete_ipv4 (ifp, flags,
539 (struct in_addr *) addr, ifa->ifa_prefixlen,
540 (struct in_addr *) broad, label);
541 }
542#ifdef HAVE_IPV6
543 if (ifa->ifa_family == AF_INET6)
544 {
545 if (h->nlmsg_type == RTM_NEWADDR)
546 connected_add_ipv6 (ifp,
547 (struct in6_addr *) addr, ifa->ifa_prefixlen,
548 (struct in6_addr *) broad);
549 else
550 connected_delete_ipv6 (ifp,
551 (struct in6_addr *) addr, ifa->ifa_prefixlen,
552 (struct in6_addr *) broad);
553 }
554#endif /* HAVE_IPV6*/
555
556 return 0;
557}
558
559/* Looking up routing table by netlink interface. */
560int
561netlink_routing_table (struct sockaddr_nl *snl, struct nlmsghdr *h)
562{
563 int len;
564 struct rtmsg *rtm;
565 struct rtattr *tb [RTA_MAX + 1];
566 u_char flags = 0;
567
568 char anyaddr[16] = {0};
569
570 int index;
571 int table;
572 void *dest;
573 void *gate;
574
575 rtm = NLMSG_DATA (h);
576
577 if (h->nlmsg_type != RTM_NEWROUTE)
578 return 0;
579 if (rtm->rtm_type != RTN_UNICAST)
580 return 0;
581
582 table = rtm->rtm_table;
583#if 0 /* we weed them out later in rib_weed_tables () */
584 if (table != RT_TABLE_MAIN && table != rtm_table_default)
585 return 0;
586#endif
587
588 len = h->nlmsg_len - NLMSG_LENGTH(sizeof (struct rtmsg));
589 if (len < 0)
590 return -1;
591
592 memset (tb, 0, sizeof tb);
593 netlink_parse_rtattr (tb, RTA_MAX, RTM_RTA (rtm), len);
594
595 if (rtm->rtm_flags & RTM_F_CLONED)
596 return 0;
597 if (rtm->rtm_protocol == RTPROT_REDIRECT)
598 return 0;
599 if (rtm->rtm_protocol == RTPROT_KERNEL)
600 return 0;
601
602 if (rtm->rtm_src_len != 0)
603 return 0;
604
605 /* Route which inserted by Zebra. */
606 if (rtm->rtm_protocol == RTPROT_ZEBRA)
607 flags |= ZEBRA_FLAG_SELFROUTE;
608
609 index = 0;
610 dest = NULL;
611 gate = NULL;
612
613 if (tb[RTA_OIF])
614 index = *(int *) RTA_DATA (tb[RTA_OIF]);
615
616 if (tb[RTA_DST])
617 dest = RTA_DATA (tb[RTA_DST]);
618 else
619 dest = anyaddr;
620
621 /* Multipath treatment is needed. */
622 if (tb[RTA_GATEWAY])
623 gate = RTA_DATA (tb[RTA_GATEWAY]);
624
625 if (rtm->rtm_family == AF_INET)
626 {
627 struct prefix_ipv4 p;
628 p.family = AF_INET;
629 memcpy (&p.prefix, dest, 4);
630 p.prefixlen = rtm->rtm_dst_len;
631
632 rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, flags, &p, gate, index, table, 0, 0);
633 }
634#ifdef HAVE_IPV6
635 if (rtm->rtm_family == AF_INET6)
636 {
637 struct prefix_ipv6 p;
638 p.family = AF_INET6;
639 memcpy (&p.prefix, dest, 16);
640 p.prefixlen = rtm->rtm_dst_len;
641
642 rib_add_ipv6 (ZEBRA_ROUTE_KERNEL, flags, &p, gate, index, table);
643 }
644#endif /* HAVE_IPV6 */
645
646 return 0;
647}
648
649struct message rtproto_str [] =
650{
651 {RTPROT_REDIRECT, "redirect"},
652 {RTPROT_KERNEL, "kernel"},
653 {RTPROT_BOOT, "boot"},
654 {RTPROT_STATIC, "static"},
655 {RTPROT_GATED, "GateD"},
656 {RTPROT_RA, "router advertisement"},
657 {RTPROT_MRT, "MRT"},
658 {RTPROT_ZEBRA, "Zebra"},
659#ifdef RTPROT_BIRD
660 {RTPROT_BIRD, "BIRD"},
661#endif /* RTPROT_BIRD */
662 {0, NULL}
663};
664
665/* Routing information change from the kernel. */
666int
667netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h)
668{
669 int len;
670 struct rtmsg *rtm;
671 struct rtattr *tb [RTA_MAX + 1];
672
673 char anyaddr[16] = {0};
674
675 int index;
676 int table;
677 void *dest;
678 void *gate;
679
680 rtm = NLMSG_DATA (h);
681
682 if (! (h->nlmsg_type == RTM_NEWROUTE || h->nlmsg_type == RTM_DELROUTE))
683 {
684 /* If this is not route add/delete message print warning. */
685 zlog_warn ("Kernel message: %d\n", h->nlmsg_type);
686 return 0;
687 }
688
689 /* Connected route. */
690 if (IS_ZEBRA_DEBUG_KERNEL)
691 zlog_info ("%s %s %s proto %s",
692 h->nlmsg_type == RTM_NEWROUTE ? "RTM_NEWROUTE" : "RTM_DELROUTE",
693 rtm->rtm_family == AF_INET ? "ipv4" : "ipv6",
694 rtm->rtm_type == RTN_UNICAST ? "unicast" : "multicast",
695 lookup (rtproto_str, rtm->rtm_protocol));
696
697 if (rtm->rtm_type != RTN_UNICAST)
698 {
699 return 0;
700 }
701
702 table = rtm->rtm_table;
703 if (table != RT_TABLE_MAIN && table != rtm_table_default)
704 {
705 return 0;
706 }
707
708 len = h->nlmsg_len - NLMSG_LENGTH(sizeof (struct rtmsg));
709 if (len < 0)
710 return -1;
711
712 memset (tb, 0, sizeof tb);
713 netlink_parse_rtattr (tb, RTA_MAX, RTM_RTA (rtm), len);
714
715 if (rtm->rtm_flags & RTM_F_CLONED)
716 return 0;
717 if (rtm->rtm_protocol == RTPROT_REDIRECT)
718 return 0;
719 if (rtm->rtm_protocol == RTPROT_KERNEL)
720 return 0;
721
722 if (rtm->rtm_protocol == RTPROT_ZEBRA && h->nlmsg_type == RTM_NEWROUTE)
723 return 0;
724
725 if (rtm->rtm_src_len != 0)
726 {
727 zlog_warn ("netlink_route_change(): no src len");
728 return 0;
729 }
730
731 index = 0;
732 dest = NULL;
733 gate = NULL;
734
735 if (tb[RTA_OIF])
736 index = *(int *) RTA_DATA (tb[RTA_OIF]);
737
738 if (tb[RTA_DST])
739 dest = RTA_DATA (tb[RTA_DST]);
740 else
741 dest = anyaddr;
742
743 if (tb[RTA_GATEWAY])
744 gate = RTA_DATA (tb[RTA_GATEWAY]);
745
746 if (rtm->rtm_family == AF_INET)
747 {
748 struct prefix_ipv4 p;
749 p.family = AF_INET;
750 memcpy (&p.prefix, dest, 4);
751 p.prefixlen = rtm->rtm_dst_len;
752
753 if (IS_ZEBRA_DEBUG_KERNEL)
754 {
755 if (h->nlmsg_type == RTM_NEWROUTE)
756 zlog_info ("RTM_NEWROUTE %s/%d",
757 inet_ntoa (p.prefix), p.prefixlen);
758 else
759 zlog_info ("RTM_DELROUTE %s/%d",
760 inet_ntoa (p.prefix), p.prefixlen);
761 }
762
763 if (h->nlmsg_type == RTM_NEWROUTE)
764 rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, index, table, 0, 0);
765 else
766 rib_delete_ipv4 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, index, table);
767 }
768
769#ifdef HAVE_IPV6
770 if (rtm->rtm_family == AF_INET6)
771 {
772 struct prefix_ipv6 p;
773 char buf[BUFSIZ];
774
775 p.family = AF_INET6;
776 memcpy (&p.prefix, dest, 16);
777 p.prefixlen = rtm->rtm_dst_len;
778
779 if (IS_ZEBRA_DEBUG_KERNEL)
780 {
781 if (h->nlmsg_type == RTM_NEWROUTE)
782 zlog_info ("RTM_NEWROUTE %s/%d",
783 inet_ntop (AF_INET6, &p.prefix, buf, BUFSIZ),
784 p.prefixlen);
785 else
786 zlog_info ("RTM_DELROUTE %s/%d",
787 inet_ntop (AF_INET6, &p.prefix, buf, BUFSIZ),
788 p.prefixlen);
789 }
790
791 if (h->nlmsg_type == RTM_NEWROUTE)
792 rib_add_ipv6 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, index, 0);
793 else
794 rib_delete_ipv6 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, index, 0);
795 }
796#endif /* HAVE_IPV6 */
797
798 return 0;
799}
800
801int
802netlink_link_change (struct sockaddr_nl *snl, struct nlmsghdr *h)
803{
804 int len;
805 struct ifinfomsg *ifi;
806 struct rtattr *tb [IFLA_MAX + 1];
807 struct interface *ifp;
808 char *name;
809
810 ifi = NLMSG_DATA (h);
811
812 if (! (h->nlmsg_type == RTM_NEWLINK || h->nlmsg_type == RTM_DELLINK))
813 {
814 /* If this is not link add/delete message so print warning. */
815 zlog_warn ("netlink_link_change: wrong kernel message %d\n",
816 h->nlmsg_type);
817 return 0;
818 }
819
820 len = h->nlmsg_len - NLMSG_LENGTH (sizeof (struct ifinfomsg));
821 if (len < 0)
822 return -1;
823
824 /* Looking up interface name. */
825 memset (tb, 0, sizeof tb);
826 netlink_parse_rtattr (tb, IFLA_MAX, IFLA_RTA (ifi), len);
827 if (tb[IFLA_IFNAME] == NULL)
828 return -1;
829 name = (char *)RTA_DATA(tb[IFLA_IFNAME]);
830
831 /* Add interface. */
832 if (h->nlmsg_type == RTM_NEWLINK)
833 {
834 ifp = if_lookup_by_name (name);
835
836 if (ifp == NULL || ! CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE))
837 {
838 if (ifp == NULL)
839 ifp = if_get_by_name (name);
840
841 ifp->ifindex = ifi->ifi_index;
842 ifp->flags = ifi->ifi_flags & 0x0000fffff;
843 ifp->mtu = *(int *)RTA_DATA (tb[IFLA_MTU]);
844 ifp->metric = 1;
845
846 /* If new link is added. */
847 if_add_update(ifp);
848 }
849 else
850 {
851 /* Interface status change. */
852 ifp->ifindex = ifi->ifi_index;
853 ifp->mtu = *(int *)RTA_DATA (tb[IFLA_MTU]);
854 ifp->metric = 1;
855
paul2e3b2e42002-12-13 21:03:13 +0000856 if (if_is_operative (ifp))
paul718e3742002-12-13 20:15:29 +0000857 {
858 ifp->flags = ifi->ifi_flags & 0x0000fffff;
paul2e3b2e42002-12-13 21:03:13 +0000859 if (! if_is_operative (ifp))
paul718e3742002-12-13 20:15:29 +0000860 if_down (ifp);
861 }
862 else
863 {
864 ifp->flags = ifi->ifi_flags & 0x0000fffff;
paul2e3b2e42002-12-13 21:03:13 +0000865 if (if_is_operative (ifp))
paul718e3742002-12-13 20:15:29 +0000866 if_up (ifp);
867 }
868 }
869 }
870 else
871 {
872 /* RTM_DELLINK. */
873 ifp = if_lookup_by_name (name);
874
875 if (ifp == NULL)
876 {
877 zlog (NULL, LOG_WARNING, "interface %s is deleted but can't find",
878 name);
879 return 0;
880 }
881
882 if_delete_update (ifp);
883 }
884
885 return 0;
886}
887
888int
889netlink_information_fetch (struct sockaddr_nl *snl, struct nlmsghdr *h)
890{
891 switch (h->nlmsg_type)
892 {
893 case RTM_NEWROUTE:
894 return netlink_route_change (snl, h);
895 break;
896 case RTM_DELROUTE:
897 return netlink_route_change (snl, h);
898 break;
899 case RTM_NEWLINK:
900 return netlink_link_change (snl, h);
901 break;
902 case RTM_DELLINK:
903 return netlink_link_change (snl, h);
904 break;
905 case RTM_NEWADDR:
906 return netlink_interface_addr (snl, h);
907 break;
908 case RTM_DELADDR:
909 return netlink_interface_addr (snl, h);
910 break;
911 default:
912 zlog_warn ("Unknown netlink nlmsg_type %d\n", h->nlmsg_type);
913 break;
914 }
915 return 0;
916}
917
918/* Interface lookup by netlink socket. */
919int
920interface_lookup_netlink ()
921{
922 int ret;
paul5f37d862003-04-19 00:11:28 +0000923 int flags;
924 int snb_ret;
925
926 /*
927 * Change netlink socket flags to blocking to ensure we get
928 * a reply via nelink_parse_info
929 */
930 snb_ret = set_netlink_blocking(&netlink_cmd, &flags);
931 if(snb_ret < 0)
932 zlog (NULL, LOG_WARNING,
933 "%s:%i Warning: Could not set netlink socket to blocking.",
934 __FUNCTION__, __LINE__);
935
paul718e3742002-12-13 20:15:29 +0000936 /* Get interface information. */
937 ret = netlink_request (AF_PACKET, RTM_GETLINK, &netlink_cmd);
938 if (ret < 0)
939 return ret;
940 ret = netlink_parse_info (netlink_interface, &netlink_cmd);
941 if (ret < 0)
942 return ret;
943
944 /* Get IPv4 address of the interfaces. */
945 ret = netlink_request (AF_INET, RTM_GETADDR, &netlink_cmd);
946 if (ret < 0)
947 return ret;
948 ret = netlink_parse_info (netlink_interface_addr, &netlink_cmd);
949 if (ret < 0)
950 return ret;
951
952#ifdef HAVE_IPV6
953 /* Get IPv6 address of the interfaces. */
954 ret = netlink_request (AF_INET6, RTM_GETADDR, &netlink_cmd);
955 if (ret < 0)
956 return ret;
957 ret = netlink_parse_info (netlink_interface_addr, &netlink_cmd);
958 if (ret < 0)
959 return ret;
960#endif /* HAVE_IPV6 */
961
paul5f37d862003-04-19 00:11:28 +0000962 /* restore socket flags */
963 if(snb_ret == 0)
964 set_netlink_nonblocking(&netlink_cmd, &flags);
paul718e3742002-12-13 20:15:29 +0000965 return 0;
966}
967
968/* Routing table read function using netlink interface. Only called
969 bootstrap time. */
970int
971netlink_route_read ()
972{
973 int ret;
paul5f37d862003-04-19 00:11:28 +0000974 int flags;
975 int snb_ret;
976
977 /*
978 * Change netlink socket flags to blocking to ensure we get
979 * a reply via nelink_parse_info
980 */
981 snb_ret = set_netlink_blocking(&netlink_cmd, &flags);
982 if(snb_ret < 0)
983 zlog (NULL, LOG_WARNING,
984 "%s:%i Warning: Could not set netlink socket to blocking.",
985 __FUNCTION__, __LINE__);
986
paul718e3742002-12-13 20:15:29 +0000987 /* Get IPv4 routing table. */
988 ret = netlink_request (AF_INET, RTM_GETROUTE, &netlink_cmd);
989 if (ret < 0)
990 return ret;
991 ret = netlink_parse_info (netlink_routing_table, &netlink_cmd);
992 if (ret < 0)
993 return ret;
994
995#ifdef HAVE_IPV6
996 /* Get IPv6 routing table. */
997 ret = netlink_request (AF_INET6, RTM_GETROUTE, &netlink_cmd);
998 if (ret < 0)
999 return ret;
1000 ret = netlink_parse_info (netlink_routing_table, &netlink_cmd);
1001 if (ret < 0)
1002 return ret;
1003#endif /* HAVE_IPV6 */
1004
paul5f37d862003-04-19 00:11:28 +00001005 /* restore flags */
1006 if(snb_ret == 0)
1007 set_netlink_nonblocking(&netlink_cmd, &flags);
paul718e3742002-12-13 20:15:29 +00001008 return 0;
1009}
1010
1011/* Utility function comes from iproute2.
1012 Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru> */
1013int
1014addattr_l (struct nlmsghdr *n, int maxlen, int type, void *data, int alen)
1015{
1016 int len;
1017 struct rtattr *rta;
1018
1019 len = RTA_LENGTH(alen);
1020
1021 if (NLMSG_ALIGN(n->nlmsg_len) + len > maxlen)
1022 return -1;
1023
1024 rta = (struct rtattr*) (((char*)n) + NLMSG_ALIGN (n->nlmsg_len));
1025 rta->rta_type = type;
1026 rta->rta_len = len;
1027 memcpy (RTA_DATA(rta), data, alen);
1028 n->nlmsg_len = NLMSG_ALIGN (n->nlmsg_len) + len;
1029
1030 return 0;
1031}
1032
1033int
1034rta_addattr_l (struct rtattr *rta, int maxlen, int type, void *data, int alen)
1035{
1036 int len;
1037 struct rtattr *subrta;
1038
1039 len = RTA_LENGTH(alen);
1040
1041 if (RTA_ALIGN(rta->rta_len) + len > maxlen)
1042 return -1;
1043
1044 subrta = (struct rtattr*) (((char*)rta) + RTA_ALIGN (rta->rta_len));
1045 subrta->rta_type = type;
1046 subrta->rta_len = len;
1047 memcpy (RTA_DATA(subrta), data, alen);
1048 rta->rta_len = NLMSG_ALIGN (rta->rta_len) + len;
1049
1050 return 0;
1051}
1052
1053/* Utility function comes from iproute2.
1054 Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru> */
1055int
1056addattr32 (struct nlmsghdr *n, int maxlen, int type, int data)
1057{
1058 int len;
1059 struct rtattr *rta;
1060
1061 len = RTA_LENGTH(4);
1062
1063 if (NLMSG_ALIGN (n->nlmsg_len) + len > maxlen)
1064 return -1;
1065
1066 rta = (struct rtattr*) (((char*)n) + NLMSG_ALIGN (n->nlmsg_len));
1067 rta->rta_type = type;
1068 rta->rta_len = len;
1069 memcpy (RTA_DATA(rta), &data, 4);
1070 n->nlmsg_len = NLMSG_ALIGN (n->nlmsg_len) + len;
1071
1072 return 0;
1073}
1074
1075static int
1076netlink_talk_filter (struct sockaddr_nl *snl, struct nlmsghdr *h)
1077{
1078 zlog_warn ("netlink_talk: ignoring message type 0x%04x", h->nlmsg_type);
1079 return 0;
1080}
1081
1082/* sendmsg() to netlink socket then recvmsg(). */
1083int
1084netlink_talk (struct nlmsghdr *n, struct nlsock *nl)
1085{
1086 int status;
1087 struct sockaddr_nl snl;
1088 struct iovec iov = { (void*) n, n->nlmsg_len };
1089 struct msghdr msg = {(void*) &snl, sizeof snl, &iov, 1, NULL, 0, 0};
1090 int flags = 0;
paul5f37d862003-04-19 00:11:28 +00001091 int snb_ret;
paul718e3742002-12-13 20:15:29 +00001092
1093 memset (&snl, 0, sizeof snl);
1094 snl.nl_family = AF_NETLINK;
1095
1096 n->nlmsg_seq = ++netlink_cmd.seq;
1097
1098 /* Request an acknowledgement by setting NLM_F_ACK */
1099 n->nlmsg_flags |= NLM_F_ACK;
1100
1101 if (IS_ZEBRA_DEBUG_KERNEL)
1102 zlog_info ("netlink_talk: %s type %s(%u), seq=%u", netlink_cmd.name,
1103 lookup (nlmsg_str, n->nlmsg_type), n->nlmsg_type,
1104 n->nlmsg_seq);
1105
1106 /* Send message to netlink interface. */
1107 status = sendmsg (nl->sock, &msg, 0);
1108 if (status < 0)
1109 {
1110 zlog (NULL, LOG_ERR, "netlink_talk sendmsg() error: %s",
1111 strerror (errno));
1112 return -1;
1113 }
1114
1115 /*
1116 * Change socket flags for blocking I/O.
1117 * This ensures we wait for a reply in netlink_parse_info().
1118 */
paul5f37d862003-04-19 00:11:28 +00001119 snb_ret = set_netlink_blocking(nl, &flags);
1120 if(snb_ret < 0)
1121 zlog (NULL, LOG_WARNING,
1122 "%s:%i Warning: Could not set netlink socket to blocking.",
1123 __FUNCTION__, __LINE__);
paul718e3742002-12-13 20:15:29 +00001124
1125 /*
1126 * Get reply from netlink socket.
1127 * The reply should either be an acknowlegement or an error.
1128 */
1129 status = netlink_parse_info (netlink_talk_filter, nl);
1130
1131 /* Restore socket flags for nonblocking I/O */
paul5f37d862003-04-19 00:11:28 +00001132 if(snb_ret == 0)
1133 set_netlink_nonblocking(nl, &flags);
paul718e3742002-12-13 20:15:29 +00001134
1135 return status;
1136}
1137
1138/* Routing table change via netlink interface. */
1139int
1140netlink_route (int cmd, int family, void *dest, int length, void *gate,
1141 int index, int zebra_flags, int table)
1142{
1143 int ret;
1144 int bytelen;
1145 struct sockaddr_nl snl;
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 = table;
1164 req.r.rtm_dst_len = length;
1165
1166 if (zebra_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 if (dest)
1183 addattr_l (&req.n, sizeof req, RTA_DST, dest, bytelen);
1184
1185 if (! discard)
1186 {
1187 if (gate)
1188 addattr_l (&req.n, sizeof req, RTA_GATEWAY, gate, bytelen);
1189 if (index > 0)
1190 addattr32 (&req.n, sizeof req, RTA_OIF, index);
1191 }
1192
1193 /* Destination netlink address. */
1194 memset (&snl, 0, sizeof snl);
1195 snl.nl_family = AF_NETLINK;
1196
1197 /* Talk to netlink socket. */
1198 ret = netlink_talk (&req.n, &netlink);
1199 if (ret < 0)
1200 return -1;
1201
1202 return 0;
1203}
1204
1205/* Routing table change via netlink interface. */
1206int
1207netlink_route_multipath (int cmd, struct prefix *p, struct rib *rib,
1208 int family)
1209{
1210 int bytelen;
1211 struct sockaddr_nl snl;
1212 struct nexthop *nexthop = NULL;
1213 int nexthop_num = 0;
1214 struct nlsock *nl;
1215 int discard;
1216
1217 struct
1218 {
1219 struct nlmsghdr n;
1220 struct rtmsg r;
1221 char buf[1024];
1222 } req;
1223
1224 memset (&req, 0, sizeof req);
1225
1226 bytelen = (family == AF_INET ? 4 : 16);
1227
1228 req.n.nlmsg_len = NLMSG_LENGTH (sizeof (struct rtmsg));
1229 req.n.nlmsg_flags = NLM_F_CREATE | NLM_F_REQUEST;
1230 req.n.nlmsg_type = cmd;
1231 req.r.rtm_family = family;
1232 req.r.rtm_table = rib->table;
1233 req.r.rtm_dst_len = p->prefixlen;
1234
paul13766da2003-02-07 14:46:23 +00001235#ifdef RTM_F_EQUALIZE
1236 req.r.rtm_flags |= RTM_F_EQUALIZE;
1237#endif /* RTM_F_EQUALIZE */
1238
paul718e3742002-12-13 20:15:29 +00001239 if (rib->flags & ZEBRA_FLAG_BLACKHOLE)
1240 discard = 1;
1241 else
1242 discard = 0;
1243
1244 if (cmd == RTM_NEWROUTE)
1245 {
1246 req.r.rtm_protocol = RTPROT_ZEBRA;
1247 req.r.rtm_scope = RT_SCOPE_UNIVERSE;
1248
1249 if (discard)
1250 req.r.rtm_type = RTN_BLACKHOLE;
1251 else
1252 req.r.rtm_type = RTN_UNICAST;
1253 }
1254
1255 addattr_l (&req.n, sizeof req, RTA_DST, &p->u.prefix, bytelen);
1256
1257 /* Metric. */
1258 addattr32 (&req.n, sizeof req, RTA_PRIORITY, rib->metric);
1259
1260 if (discard)
1261 {
1262 if (cmd == RTM_NEWROUTE)
1263 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
1264 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1265 goto skip;
1266 }
1267
1268 /* Multipath case. */
1269 if (rib->nexthop_active_num == 1 || MULTIPATH_NUM == 1)
1270 {
1271 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
1272 {
1273 if ((cmd == RTM_NEWROUTE
1274 && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))
1275 || (cmd == RTM_DELROUTE
1276 && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)))
1277 {
1278 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
1279 {
1280 if (nexthop->rtype == NEXTHOP_TYPE_IPV4
1281 || nexthop->rtype == NEXTHOP_TYPE_IPV4_IFINDEX)
1282 addattr_l (&req.n, sizeof req, RTA_GATEWAY,
1283 &nexthop->rgate.ipv4, bytelen);
1284#ifdef HAVE_IPV6
1285 if (nexthop->rtype == NEXTHOP_TYPE_IPV6
1286 || nexthop->rtype == NEXTHOP_TYPE_IPV6_IFINDEX
1287 || nexthop->rtype == NEXTHOP_TYPE_IPV6_IFNAME)
1288 addattr_l (&req.n, sizeof req, RTA_GATEWAY,
1289 &nexthop->rgate.ipv6, bytelen);
1290#endif /* HAVE_IPV6 */
1291 if (nexthop->rtype == NEXTHOP_TYPE_IFINDEX
1292 || nexthop->rtype == NEXTHOP_TYPE_IFNAME
1293 || nexthop->rtype == NEXTHOP_TYPE_IPV4_IFINDEX
1294 || nexthop->rtype == NEXTHOP_TYPE_IPV6_IFINDEX
1295 || nexthop->rtype == NEXTHOP_TYPE_IPV6_IFNAME)
1296 addattr32 (&req.n, sizeof req, RTA_OIF,
1297 nexthop->rifindex);
1298 }
1299 else
1300 {
1301 if (nexthop->type == NEXTHOP_TYPE_IPV4
1302 || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX)
1303 addattr_l (&req.n, sizeof req, RTA_GATEWAY,
1304 &nexthop->gate.ipv4, bytelen);
1305#ifdef HAVE_IPV6
1306 if (nexthop->type == NEXTHOP_TYPE_IPV6
1307 || nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME
1308 || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX)
1309 addattr_l (&req.n, sizeof req, RTA_GATEWAY,
1310 &nexthop->gate.ipv6, bytelen);
1311#endif /* HAVE_IPV6 */
1312 if (nexthop->type == NEXTHOP_TYPE_IFINDEX
1313 || nexthop->type == NEXTHOP_TYPE_IFNAME
1314 || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX
1315 || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX
1316 || nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME)
1317 addattr32 (&req.n, sizeof req, RTA_OIF, nexthop->ifindex);
1318 }
1319
1320 if (cmd == RTM_NEWROUTE)
1321 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1322
1323 nexthop_num++;
1324 break;
1325 }
1326 }
1327 }
1328 else
1329 {
1330 char buf[1024];
1331 struct rtattr *rta = (void *) buf;
1332 struct rtnexthop *rtnh;
1333
1334 rta->rta_type = RTA_MULTIPATH;
1335 rta->rta_len = RTA_LENGTH(0);
1336 rtnh = RTA_DATA(rta);
1337
1338 nexthop_num = 0;
1339 for (nexthop = rib->nexthop;
1340 nexthop && (MULTIPATH_NUM == 0 || nexthop_num < MULTIPATH_NUM);
1341 nexthop = nexthop->next)
1342 {
1343 if ((cmd == RTM_NEWROUTE
1344 && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))
1345 || (cmd == RTM_DELROUTE
1346 && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)))
1347 {
1348 nexthop_num++;
1349
1350 rtnh->rtnh_len = sizeof (*rtnh);
1351 rtnh->rtnh_flags = 0;
1352 rtnh->rtnh_hops = 0;
1353 rta->rta_len += rtnh->rtnh_len;
1354
1355 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
1356 {
1357 if (nexthop->rtype == NEXTHOP_TYPE_IPV4
1358 || nexthop->rtype == NEXTHOP_TYPE_IPV4_IFINDEX)
1359 {
1360 rta_addattr_l (rta, 4096, RTA_GATEWAY,
1361 &nexthop->rgate.ipv4, bytelen);
1362 rtnh->rtnh_len += sizeof (struct rtattr) + 4;
1363 }
1364#ifdef HAVE_IPV6
1365 if (nexthop->rtype == NEXTHOP_TYPE_IPV6
1366 || nexthop->rtype == NEXTHOP_TYPE_IPV6_IFNAME
1367 || nexthop->rtype == NEXTHOP_TYPE_IPV6_IFINDEX)
1368 rta_addattr_l (rta, 4096, RTA_GATEWAY,
1369 &nexthop->rgate.ipv6, bytelen);
1370#endif /* HAVE_IPV6 */
1371 /* ifindex */
1372 if (nexthop->rtype == NEXTHOP_TYPE_IFINDEX
1373 || nexthop->rtype == NEXTHOP_TYPE_IFNAME
1374 || nexthop->rtype == NEXTHOP_TYPE_IPV4_IFINDEX
1375 || nexthop->rtype == NEXTHOP_TYPE_IPV6_IFINDEX
1376 || nexthop->rtype == NEXTHOP_TYPE_IPV6_IFNAME)
1377 rtnh->rtnh_ifindex = nexthop->rifindex;
1378 else
1379 rtnh->rtnh_ifindex = 0;
1380 }
1381 else
1382 {
1383 if (nexthop->type == NEXTHOP_TYPE_IPV4
1384 || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX)
1385 {
1386 rta_addattr_l (rta, 4096, RTA_GATEWAY,
1387 &nexthop->gate.ipv4, bytelen);
1388 rtnh->rtnh_len += sizeof (struct rtattr) + 4;
1389 }
1390#ifdef HAVE_IPV6
1391 if (nexthop->type == NEXTHOP_TYPE_IPV6
1392 || nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME
1393 || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX)
1394 rta_addattr_l (rta, 4096, RTA_GATEWAY,
1395 &nexthop->gate.ipv6, bytelen);
1396#endif /* HAVE_IPV6 */
1397 /* ifindex */
1398 if (nexthop->type == NEXTHOP_TYPE_IFINDEX
1399 || nexthop->type == NEXTHOP_TYPE_IFNAME
1400 || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX
1401 || nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME
1402 || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX)
1403 rtnh->rtnh_ifindex = nexthop->ifindex;
1404 else
1405 rtnh->rtnh_ifindex = 0;
1406 }
1407 rtnh = RTNH_NEXT(rtnh);
1408
1409 if (cmd == RTM_NEWROUTE)
1410 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1411 }
1412 }
1413
1414 if (rta->rta_len > RTA_LENGTH (0))
1415 addattr_l (&req.n, 1024, RTA_MULTIPATH, RTA_DATA(rta),
1416 RTA_PAYLOAD(rta));
1417 }
1418
1419 /* If there is no useful nexthop then return. */
1420 if (nexthop_num == 0)
1421 {
1422 if (IS_ZEBRA_DEBUG_KERNEL)
1423 zlog_info ("netlink_route_multipath(): No useful nexthop.");
1424 return 0;
1425 }
1426
1427 skip:
1428
1429 /* Destination netlink address. */
1430 memset (&snl, 0, sizeof snl);
1431 snl.nl_family = AF_NETLINK;
1432
1433 if (family == AF_INET)
1434 nl = &netlink_cmd;
1435 else
1436 nl = &netlink;
1437
1438 /* Talk to netlink socket. */
1439 return netlink_talk (&req.n, nl);
1440}
1441
1442int
1443kernel_add_ipv4 (struct prefix *p, struct rib *rib)
1444{
1445 return netlink_route_multipath (RTM_NEWROUTE, p, rib, AF_INET);
1446}
1447
1448int
1449kernel_delete_ipv4 (struct prefix *p, struct rib *rib)
1450{
1451 return netlink_route_multipath (RTM_DELROUTE, p, rib, AF_INET);
1452}
1453
1454#ifdef HAVE_IPV6
1455int
1456kernel_add_ipv6 (struct prefix *p, struct rib *rib)
1457{
1458 return netlink_route_multipath (RTM_NEWROUTE, p, rib, AF_INET6);
1459}
1460
1461int
1462kernel_delete_ipv6 (struct prefix *p, struct rib *rib)
1463{
1464 return netlink_route_multipath (RTM_DELROUTE, p, rib, AF_INET6);
1465}
1466
1467/* Delete IPv6 route from the kernel. */
1468int
1469kernel_delete_ipv6_old (struct prefix_ipv6 *dest, struct in6_addr *gate,
1470 int index, int flags, int table)
1471{
1472 return netlink_route (RTM_DELROUTE, AF_INET6, &dest->prefix, dest->prefixlen,
1473 gate, index, flags, table);
1474}
1475#endif /* HAVE_IPV6 */
1476
1477/* Interface address modification. */
1478int
1479netlink_address (int cmd, int family, struct interface *ifp,
1480 struct connected *ifc)
1481{
1482 int bytelen;
1483 struct prefix *p;
1484
1485 struct
1486 {
1487 struct nlmsghdr n;
1488 struct ifaddrmsg ifa;
1489 char buf[1024];
1490 } req;
1491
1492 p = ifc->address;
1493 memset (&req, 0, sizeof req);
1494
1495 bytelen = (family == AF_INET ? 4 : 16);
1496
1497 req.n.nlmsg_len = NLMSG_LENGTH (sizeof(struct ifaddrmsg));
1498 req.n.nlmsg_flags = NLM_F_REQUEST;
1499 req.n.nlmsg_type = cmd;
1500 req.ifa.ifa_family = family;
1501
1502 req.ifa.ifa_index = ifp->ifindex;
1503 req.ifa.ifa_prefixlen = p->prefixlen;
1504
1505 addattr_l (&req.n, sizeof req, IFA_LOCAL, &p->u.prefix, bytelen);
1506
1507 if (family == AF_INET && cmd == RTM_NEWADDR)
1508 {
1509 if (if_is_broadcast (ifp) && ifc->destination)
1510 {
1511 p = ifc->destination;
1512 addattr_l(&req.n, sizeof req, IFA_BROADCAST, &p->u.prefix, bytelen);
1513 }
1514 }
1515
1516 if (CHECK_FLAG (ifc->flags, ZEBRA_IFA_SECONDARY))
1517 SET_FLAG (req.ifa.ifa_flags, IFA_F_SECONDARY);
1518
1519 if (ifc->label)
1520 addattr_l (&req.n, sizeof req, IFA_LABEL, ifc->label,
1521 strlen (ifc->label) + 1);
1522
1523 return netlink_talk (&req.n, &netlink_cmd);
1524}
1525
1526int
1527kernel_address_add_ipv4 (struct interface *ifp, struct connected *ifc)
1528{
1529 return netlink_address (RTM_NEWADDR, AF_INET, ifp, ifc);
1530}
1531
1532int
1533kernel_address_delete_ipv4 (struct interface *ifp, struct connected *ifc)
1534{
1535 return netlink_address (RTM_DELADDR, AF_INET, ifp, ifc);
1536}
1537
paul718e3742002-12-13 20:15:29 +00001538
1539extern struct thread_master *master;
1540
1541/* Kernel route reflection. */
1542int
1543kernel_read (struct thread *thread)
1544{
1545 int ret;
1546 int sock;
1547
1548 sock = THREAD_FD (thread);
1549 ret = netlink_parse_info (netlink_information_fetch, &netlink);
1550 thread_add_read (master, kernel_read, NULL, netlink.sock);
1551
1552 return 0;
1553}
1554
1555/* Exported interface function. This function simply calls
1556 netlink_socket (). */
1557void
1558kernel_init ()
1559{
1560 unsigned long groups;
1561
1562 groups = RTMGRP_LINK|RTMGRP_IPV4_ROUTE|RTMGRP_IPV4_IFADDR;
1563#ifdef HAVE_IPV6
1564 groups |= RTMGRP_IPV6_ROUTE|RTMGRP_IPV6_IFADDR;
1565#endif /* HAVE_IPV6 */
1566 netlink_socket (&netlink, groups);
1567 netlink_socket (&netlink_cmd, 0);
1568
1569 /* Register kernel socket. */
1570 if (netlink.sock > 0)
1571 thread_add_read (master, kernel_read, NULL, netlink.sock);
1572}