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