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