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