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