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