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