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