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