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