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