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