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