blob: 60043c9b6784f9f5f9aa495740863be0b394a7b8 [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
hasso81dfcaa2003-05-25 19:21:25 +00001166 if ((zebra_flags & ZEBRA_FLAG_BLACKHOLE)
1167 || (zebra_flags & ZEBRA_FLAG_REJECT))
paul718e3742002-12-13 20:15:29 +00001168 discard = 1;
1169 else
1170 discard = 0;
1171
1172 if (cmd == RTM_NEWROUTE)
1173 {
1174 req.r.rtm_protocol = RTPROT_ZEBRA;
1175 req.r.rtm_scope = RT_SCOPE_UNIVERSE;
1176
hasso81dfcaa2003-05-25 19:21:25 +00001177 if (discard) {
1178 if (zebra_flags & ZEBRA_FLAG_BLACKHOLE)
1179 req.r.rtm_type = RTN_BLACKHOLE;
1180 else if (zebra_flags & ZEBRA_FLAG_REJECT)
1181 req.r.rtm_type = RTN_UNREACHABLE;
1182 else assert(RTN_BLACKHOLE != RTN_UNREACHABLE); /* false */
1183 } else
paul718e3742002-12-13 20:15:29 +00001184 req.r.rtm_type = RTN_UNICAST;
1185 }
1186
1187 if (dest)
1188 addattr_l (&req.n, sizeof req, RTA_DST, dest, bytelen);
1189
1190 if (! discard)
1191 {
1192 if (gate)
1193 addattr_l (&req.n, sizeof req, RTA_GATEWAY, gate, bytelen);
1194 if (index > 0)
1195 addattr32 (&req.n, sizeof req, RTA_OIF, index);
1196 }
1197
1198 /* Destination netlink address. */
1199 memset (&snl, 0, sizeof snl);
1200 snl.nl_family = AF_NETLINK;
1201
1202 /* Talk to netlink socket. */
1203 ret = netlink_talk (&req.n, &netlink);
1204 if (ret < 0)
1205 return -1;
1206
1207 return 0;
1208}
1209
1210/* Routing table change via netlink interface. */
1211int
1212netlink_route_multipath (int cmd, struct prefix *p, struct rib *rib,
1213 int family)
1214{
1215 int bytelen;
1216 struct sockaddr_nl snl;
1217 struct nexthop *nexthop = NULL;
1218 int nexthop_num = 0;
1219 struct nlsock *nl;
1220 int discard;
1221
1222 struct
1223 {
1224 struct nlmsghdr n;
1225 struct rtmsg r;
1226 char buf[1024];
1227 } req;
1228
1229 memset (&req, 0, sizeof req);
1230
1231 bytelen = (family == AF_INET ? 4 : 16);
1232
1233 req.n.nlmsg_len = NLMSG_LENGTH (sizeof (struct rtmsg));
1234 req.n.nlmsg_flags = NLM_F_CREATE | NLM_F_REQUEST;
1235 req.n.nlmsg_type = cmd;
1236 req.r.rtm_family = family;
1237 req.r.rtm_table = rib->table;
1238 req.r.rtm_dst_len = p->prefixlen;
1239
paul13766da2003-02-07 14:46:23 +00001240#ifdef RTM_F_EQUALIZE
1241 req.r.rtm_flags |= RTM_F_EQUALIZE;
1242#endif /* RTM_F_EQUALIZE */
1243
hasso81dfcaa2003-05-25 19:21:25 +00001244 if ((rib->flags & ZEBRA_FLAG_BLACKHOLE)
1245 || (rib->flags & ZEBRA_FLAG_REJECT))
paul718e3742002-12-13 20:15:29 +00001246 discard = 1;
1247 else
1248 discard = 0;
1249
1250 if (cmd == RTM_NEWROUTE)
1251 {
1252 req.r.rtm_protocol = RTPROT_ZEBRA;
1253 req.r.rtm_scope = RT_SCOPE_UNIVERSE;
1254
hasso81dfcaa2003-05-25 19:21:25 +00001255 if (discard) {
1256 if (rib->flags & ZEBRA_FLAG_BLACKHOLE)
1257 req.r.rtm_type = RTN_BLACKHOLE;
1258 else if (rib->flags & ZEBRA_FLAG_REJECT)
1259 req.r.rtm_type = RTN_UNREACHABLE;
1260 else assert(RTN_BLACKHOLE != RTN_UNREACHABLE); /* false */
1261 } else
paul718e3742002-12-13 20:15:29 +00001262 req.r.rtm_type = RTN_UNICAST;
1263 }
1264
1265 addattr_l (&req.n, sizeof req, RTA_DST, &p->u.prefix, bytelen);
1266
1267 /* Metric. */
1268 addattr32 (&req.n, sizeof req, RTA_PRIORITY, rib->metric);
1269
1270 if (discard)
1271 {
1272 if (cmd == RTM_NEWROUTE)
1273 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
1274 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1275 goto skip;
1276 }
1277
1278 /* Multipath case. */
1279 if (rib->nexthop_active_num == 1 || MULTIPATH_NUM == 1)
1280 {
1281 for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
1282 {
1283 if ((cmd == RTM_NEWROUTE
1284 && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))
1285 || (cmd == RTM_DELROUTE
1286 && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)))
1287 {
1288 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
1289 {
1290 if (nexthop->rtype == NEXTHOP_TYPE_IPV4
1291 || nexthop->rtype == NEXTHOP_TYPE_IPV4_IFINDEX)
1292 addattr_l (&req.n, sizeof req, RTA_GATEWAY,
1293 &nexthop->rgate.ipv4, bytelen);
1294#ifdef HAVE_IPV6
1295 if (nexthop->rtype == NEXTHOP_TYPE_IPV6
1296 || nexthop->rtype == NEXTHOP_TYPE_IPV6_IFINDEX
1297 || nexthop->rtype == NEXTHOP_TYPE_IPV6_IFNAME)
1298 addattr_l (&req.n, sizeof req, RTA_GATEWAY,
1299 &nexthop->rgate.ipv6, bytelen);
1300#endif /* HAVE_IPV6 */
1301 if (nexthop->rtype == NEXTHOP_TYPE_IFINDEX
1302 || nexthop->rtype == NEXTHOP_TYPE_IFNAME
1303 || nexthop->rtype == NEXTHOP_TYPE_IPV4_IFINDEX
1304 || nexthop->rtype == NEXTHOP_TYPE_IPV6_IFINDEX
1305 || nexthop->rtype == NEXTHOP_TYPE_IPV6_IFNAME)
1306 addattr32 (&req.n, sizeof req, RTA_OIF,
1307 nexthop->rifindex);
1308 }
1309 else
1310 {
1311 if (nexthop->type == NEXTHOP_TYPE_IPV4
1312 || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX)
1313 addattr_l (&req.n, sizeof req, RTA_GATEWAY,
1314 &nexthop->gate.ipv4, bytelen);
1315#ifdef HAVE_IPV6
1316 if (nexthop->type == NEXTHOP_TYPE_IPV6
1317 || nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME
1318 || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX)
1319 addattr_l (&req.n, sizeof req, RTA_GATEWAY,
1320 &nexthop->gate.ipv6, bytelen);
1321#endif /* HAVE_IPV6 */
1322 if (nexthop->type == NEXTHOP_TYPE_IFINDEX
1323 || nexthop->type == NEXTHOP_TYPE_IFNAME
1324 || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX
1325 || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX
1326 || nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME)
1327 addattr32 (&req.n, sizeof req, RTA_OIF, nexthop->ifindex);
1328 }
1329
1330 if (cmd == RTM_NEWROUTE)
1331 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1332
1333 nexthop_num++;
1334 break;
1335 }
1336 }
1337 }
1338 else
1339 {
1340 char buf[1024];
1341 struct rtattr *rta = (void *) buf;
1342 struct rtnexthop *rtnh;
1343
1344 rta->rta_type = RTA_MULTIPATH;
1345 rta->rta_len = RTA_LENGTH(0);
1346 rtnh = RTA_DATA(rta);
1347
1348 nexthop_num = 0;
1349 for (nexthop = rib->nexthop;
1350 nexthop && (MULTIPATH_NUM == 0 || nexthop_num < MULTIPATH_NUM);
1351 nexthop = nexthop->next)
1352 {
1353 if ((cmd == RTM_NEWROUTE
1354 && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))
1355 || (cmd == RTM_DELROUTE
1356 && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)))
1357 {
1358 nexthop_num++;
1359
1360 rtnh->rtnh_len = sizeof (*rtnh);
1361 rtnh->rtnh_flags = 0;
1362 rtnh->rtnh_hops = 0;
1363 rta->rta_len += rtnh->rtnh_len;
1364
1365 if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
1366 {
1367 if (nexthop->rtype == NEXTHOP_TYPE_IPV4
1368 || nexthop->rtype == NEXTHOP_TYPE_IPV4_IFINDEX)
1369 {
1370 rta_addattr_l (rta, 4096, RTA_GATEWAY,
1371 &nexthop->rgate.ipv4, bytelen);
1372 rtnh->rtnh_len += sizeof (struct rtattr) + 4;
1373 }
1374#ifdef HAVE_IPV6
1375 if (nexthop->rtype == NEXTHOP_TYPE_IPV6
1376 || nexthop->rtype == NEXTHOP_TYPE_IPV6_IFNAME
1377 || nexthop->rtype == NEXTHOP_TYPE_IPV6_IFINDEX)
1378 rta_addattr_l (rta, 4096, RTA_GATEWAY,
1379 &nexthop->rgate.ipv6, bytelen);
1380#endif /* HAVE_IPV6 */
1381 /* ifindex */
1382 if (nexthop->rtype == NEXTHOP_TYPE_IFINDEX
1383 || nexthop->rtype == NEXTHOP_TYPE_IFNAME
1384 || nexthop->rtype == NEXTHOP_TYPE_IPV4_IFINDEX
1385 || nexthop->rtype == NEXTHOP_TYPE_IPV6_IFINDEX
1386 || nexthop->rtype == NEXTHOP_TYPE_IPV6_IFNAME)
1387 rtnh->rtnh_ifindex = nexthop->rifindex;
1388 else
1389 rtnh->rtnh_ifindex = 0;
1390 }
1391 else
1392 {
1393 if (nexthop->type == NEXTHOP_TYPE_IPV4
1394 || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX)
1395 {
1396 rta_addattr_l (rta, 4096, RTA_GATEWAY,
1397 &nexthop->gate.ipv4, bytelen);
1398 rtnh->rtnh_len += sizeof (struct rtattr) + 4;
1399 }
1400#ifdef HAVE_IPV6
1401 if (nexthop->type == NEXTHOP_TYPE_IPV6
1402 || nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME
1403 || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX)
1404 rta_addattr_l (rta, 4096, RTA_GATEWAY,
1405 &nexthop->gate.ipv6, bytelen);
1406#endif /* HAVE_IPV6 */
1407 /* ifindex */
1408 if (nexthop->type == NEXTHOP_TYPE_IFINDEX
1409 || nexthop->type == NEXTHOP_TYPE_IFNAME
1410 || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX
1411 || nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME
1412 || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX)
1413 rtnh->rtnh_ifindex = nexthop->ifindex;
1414 else
1415 rtnh->rtnh_ifindex = 0;
1416 }
1417 rtnh = RTNH_NEXT(rtnh);
1418
1419 if (cmd == RTM_NEWROUTE)
1420 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
1421 }
1422 }
1423
1424 if (rta->rta_len > RTA_LENGTH (0))
1425 addattr_l (&req.n, 1024, RTA_MULTIPATH, RTA_DATA(rta),
1426 RTA_PAYLOAD(rta));
1427 }
1428
1429 /* If there is no useful nexthop then return. */
1430 if (nexthop_num == 0)
1431 {
1432 if (IS_ZEBRA_DEBUG_KERNEL)
1433 zlog_info ("netlink_route_multipath(): No useful nexthop.");
1434 return 0;
1435 }
1436
1437 skip:
1438
1439 /* Destination netlink address. */
1440 memset (&snl, 0, sizeof snl);
1441 snl.nl_family = AF_NETLINK;
1442
1443 if (family == AF_INET)
1444 nl = &netlink_cmd;
1445 else
1446 nl = &netlink;
1447
1448 /* Talk to netlink socket. */
1449 return netlink_talk (&req.n, nl);
1450}
1451
1452int
1453kernel_add_ipv4 (struct prefix *p, struct rib *rib)
1454{
1455 return netlink_route_multipath (RTM_NEWROUTE, p, rib, AF_INET);
1456}
1457
1458int
1459kernel_delete_ipv4 (struct prefix *p, struct rib *rib)
1460{
1461 return netlink_route_multipath (RTM_DELROUTE, p, rib, AF_INET);
1462}
1463
1464#ifdef HAVE_IPV6
1465int
1466kernel_add_ipv6 (struct prefix *p, struct rib *rib)
1467{
1468 return netlink_route_multipath (RTM_NEWROUTE, p, rib, AF_INET6);
1469}
1470
1471int
1472kernel_delete_ipv6 (struct prefix *p, struct rib *rib)
1473{
1474 return netlink_route_multipath (RTM_DELROUTE, p, rib, AF_INET6);
1475}
1476
1477/* Delete IPv6 route from the kernel. */
1478int
1479kernel_delete_ipv6_old (struct prefix_ipv6 *dest, struct in6_addr *gate,
1480 int index, int flags, int table)
1481{
1482 return netlink_route (RTM_DELROUTE, AF_INET6, &dest->prefix, dest->prefixlen,
1483 gate, index, flags, table);
1484}
1485#endif /* HAVE_IPV6 */
1486
1487/* Interface address modification. */
1488int
1489netlink_address (int cmd, int family, struct interface *ifp,
1490 struct connected *ifc)
1491{
1492 int bytelen;
1493 struct prefix *p;
1494
1495 struct
1496 {
1497 struct nlmsghdr n;
1498 struct ifaddrmsg ifa;
1499 char buf[1024];
1500 } req;
1501
1502 p = ifc->address;
1503 memset (&req, 0, sizeof req);
1504
1505 bytelen = (family == AF_INET ? 4 : 16);
1506
1507 req.n.nlmsg_len = NLMSG_LENGTH (sizeof(struct ifaddrmsg));
1508 req.n.nlmsg_flags = NLM_F_REQUEST;
1509 req.n.nlmsg_type = cmd;
1510 req.ifa.ifa_family = family;
1511
1512 req.ifa.ifa_index = ifp->ifindex;
1513 req.ifa.ifa_prefixlen = p->prefixlen;
1514
1515 addattr_l (&req.n, sizeof req, IFA_LOCAL, &p->u.prefix, bytelen);
1516
1517 if (family == AF_INET && cmd == RTM_NEWADDR)
1518 {
1519 if (if_is_broadcast (ifp) && ifc->destination)
1520 {
1521 p = ifc->destination;
1522 addattr_l(&req.n, sizeof req, IFA_BROADCAST, &p->u.prefix, bytelen);
1523 }
1524 }
1525
1526 if (CHECK_FLAG (ifc->flags, ZEBRA_IFA_SECONDARY))
1527 SET_FLAG (req.ifa.ifa_flags, IFA_F_SECONDARY);
1528
1529 if (ifc->label)
1530 addattr_l (&req.n, sizeof req, IFA_LABEL, ifc->label,
1531 strlen (ifc->label) + 1);
1532
1533 return netlink_talk (&req.n, &netlink_cmd);
1534}
1535
1536int
1537kernel_address_add_ipv4 (struct interface *ifp, struct connected *ifc)
1538{
1539 return netlink_address (RTM_NEWADDR, AF_INET, ifp, ifc);
1540}
1541
1542int
1543kernel_address_delete_ipv4 (struct interface *ifp, struct connected *ifc)
1544{
1545 return netlink_address (RTM_DELADDR, AF_INET, ifp, ifc);
1546}
1547
paul718e3742002-12-13 20:15:29 +00001548
1549extern struct thread_master *master;
1550
1551/* Kernel route reflection. */
1552int
1553kernel_read (struct thread *thread)
1554{
1555 int ret;
1556 int sock;
1557
1558 sock = THREAD_FD (thread);
1559 ret = netlink_parse_info (netlink_information_fetch, &netlink);
1560 thread_add_read (master, kernel_read, NULL, netlink.sock);
1561
1562 return 0;
1563}
1564
1565/* Exported interface function. This function simply calls
1566 netlink_socket (). */
1567void
1568kernel_init ()
1569{
1570 unsigned long groups;
1571
1572 groups = RTMGRP_LINK|RTMGRP_IPV4_ROUTE|RTMGRP_IPV4_IFADDR;
1573#ifdef HAVE_IPV6
1574 groups |= RTMGRP_IPV6_ROUTE|RTMGRP_IPV6_IFADDR;
1575#endif /* HAVE_IPV6 */
1576 netlink_socket (&netlink, groups);
1577 netlink_socket (&netlink_cmd, 0);
1578
1579 /* Register kernel socket. */
1580 if (netlink.sock > 0)
1581 thread_add_read (master, kernel_read, NULL, netlink.sock);
1582}