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