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