Annotation of embedaddon/quagga/zebra/kernel_socket.c, revision 1.1.1.4
1.1 misho 1: /* Kernel communication using routing socket.
2: * Copyright (C) 1999 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>
1.1.1.4 ! misho 23: #include <net/if_types.h>
1.1 misho 24:
25: #include "if.h"
26: #include "prefix.h"
27: #include "sockunion.h"
28: #include "connected.h"
29: #include "memory.h"
30: #include "ioctl.h"
31: #include "log.h"
32: #include "str.h"
33: #include "table.h"
34: #include "rib.h"
35: #include "privs.h"
1.1.1.4 ! misho 36: #include "vrf.h"
1.1 misho 37:
38: #include "zebra/interface.h"
39: #include "zebra/zserv.h"
40: #include "zebra/debug.h"
41: #include "zebra/kernel_socket.h"
1.1.1.4 ! misho 42: #include "zebra/rib.h"
1.1 misho 43:
44: extern struct zebra_privs_t zserv_privs;
45: extern struct zebra_t zebrad;
46:
47: /*
1.1.1.4 ! misho 48: * Historically, the BSD routing socket has aligned data following a
! 49: * struct sockaddr to sizeof(long), which was 4 bytes on some
! 50: * platforms, and 8 bytes on others. NetBSD 6 changed the routing
! 51: * socket to align to sizeof(uint64_t), which is 8 bytes. OS X
! 52: * appears to align to sizeof(int), which is 4 bytes.
1.1 misho 53: *
1.1.1.4 ! misho 54: * Alignment of zero-sized sockaddrs is nonsensical, but historically
! 55: * BSD defines RT_ROUNDUP(0) to be the alignment interval (rather than
! 56: * 0). We follow this practice without questioning it, but it is a
! 57: * bug if quagga calls ROUNDUP with 0.
1.1 misho 58: */
1.1.1.4 ! misho 59:
! 60: /*
! 61: * Because of these varying conventions, the only sane approach is for
! 62: * the <net/route.h> header to define some flavor of ROUNDUP macro.
! 63: */
! 64:
! 65: #if defined(SA_SIZE)
! 66: /* SAROUNDUP is the only thing we need, and SA_SIZE provides that */
! 67: #define SAROUNDUP(a) SA_SIZE(a)
! 68: #else /* !SA_SIZE */
! 69:
! 70: #if defined(RT_ROUNDUP)
! 71: #define ROUNDUP(a) RT_ROUNDUP(a)
! 72: #endif /* defined(RT_ROUNDUP) */
! 73:
! 74: #if defined(SUNOS_5)
! 75: /* Solaris has struct sockaddr_in[6] definitions at 16 / 32 bytes size,
! 76: * so the whole concept doesn't really apply. */
! 77: #define ROUNDUP(a) (a)
! 78: #endif
! 79:
! 80: /*
! 81: * If ROUNDUP has not yet been defined in terms of platform-provided
! 82: * defines, attempt to cope with heuristics.
! 83: */
! 84: #if !defined(ROUNDUP)
! 85:
! 86: /*
! 87: * It's a bug for a platform not to define rounding/alignment for
! 88: * sockaddrs on the routing socket. This warning really is
! 89: * intentional, to provoke filing bug reports with operating systems
! 90: * that don't define RT_ROUNDUP or equivalent.
! 91: */
! 92: #warning "net/route.h does not define RT_ROUNDUP; making unwarranted assumptions!"
! 93:
! 94: /* OS X (Xcode as of 2014-12) is known not to define RT_ROUNDUP */
1.1.1.3 misho 95: #ifdef __APPLE__
1.1.1.4 ! misho 96: #define ROUNDUP_TYPE int
1.1.1.3 misho 97: #else
1.1.1.4 ! misho 98: #define ROUNDUP_TYPE long
1.1.1.3 misho 99: #endif
1.1 misho 100:
1.1.1.4 ! misho 101: #define ROUNDUP(a) \
! 102: ((a) > 0 ? (1 + (((a) - 1) | (sizeof(ROUNDUP_TYPE) - 1))) : sizeof(ROUNDUP_TYPE))
! 103:
! 104: #endif /* defined(ROUNDUP) */
! 105:
1.1 misho 106: /*
107: * Given a pointer (sockaddr or void *), return the number of bytes
108: * taken up by the sockaddr and any padding needed for alignment.
109: */
110: #if defined(HAVE_STRUCT_SOCKADDR_SA_LEN)
111: #define SAROUNDUP(X) ROUNDUP(((struct sockaddr *)(X))->sa_len)
112: #elif defined(HAVE_IPV6)
113: /*
114: * One would hope all fixed-size structure definitions are aligned,
115: * but round them up nonetheless.
116: */
117: #define SAROUNDUP(X) \
118: (((struct sockaddr *)(X))->sa_family == AF_INET ? \
119: ROUNDUP(sizeof(struct sockaddr_in)):\
120: (((struct sockaddr *)(X))->sa_family == AF_INET6 ? \
121: ROUNDUP(sizeof(struct sockaddr_in6)) : \
122: (((struct sockaddr *)(X))->sa_family == AF_LINK ? \
123: ROUNDUP(sizeof(struct sockaddr_dl)) : sizeof(struct sockaddr))))
124: #else /* HAVE_IPV6 */
125: #define SAROUNDUP(X) \
126: (((struct sockaddr *)(X))->sa_family == AF_INET ? \
127: ROUNDUP(sizeof(struct sockaddr_in)):\
128: (((struct sockaddr *)(X))->sa_family == AF_LINK ? \
129: ROUNDUP(sizeof(struct sockaddr_dl)) : sizeof(struct sockaddr)))
130: #endif /* HAVE_STRUCT_SOCKADDR_SA_LEN */
131:
1.1.1.4 ! misho 132: #endif /* !SA_SIZE */
! 133:
1.1.1.3 misho 134: /*
135: * We use a call to an inline function to copy (PNT) to (DEST)
136: * 1. Calculating the length of the copy requires an #ifdef to determine
137: * if sa_len is a field and can't be used directly inside a #define
138: * 2. So the compiler doesn't complain when DEST is NULL, which is only true
139: * when we are skipping the copy and incrementing to the next SA
1.1 misho 140: */
1.1.1.4 ! misho 141: static inline void
1.1.1.3 misho 142: rta_copy (union sockunion *dest, caddr_t src) {
143: int len;
1.1.1.4 ! misho 144: if (!dest)
! 145: return;
1.1.1.3 misho 146: #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
147: len = (((struct sockaddr *)src)->sa_len > sizeof (*dest)) ?
148: sizeof (*dest) : ((struct sockaddr *)src)->sa_len ;
149: #else
150: len = (SAROUNDUP (src) > sizeof (*dest)) ?
151: sizeof (*dest) : SAROUNDUP (src) ;
152: #endif
153: memcpy (dest, src, len);
154: }
155:
1.1 misho 156: #define RTA_ADDR_GET(DEST, RTA, RTMADDRS, PNT) \
157: if ((RTMADDRS) & (RTA)) \
158: { \
159: int len = SAROUNDUP ((PNT)); \
1.1.1.4 ! misho 160: if (af_check (((struct sockaddr *)(PNT))->sa_family)) \
1.1.1.3 misho 161: rta_copy((DEST), (PNT)); \
1.1 misho 162: (PNT) += len; \
163: }
164: #define RTA_ATTR_GET(DEST, RTA, RTMADDRS, PNT) \
165: if ((RTMADDRS) & (RTA)) \
166: { \
167: int len = SAROUNDUP ((PNT)); \
1.1.1.4 ! misho 168: rta_copy((DEST), (PNT)); \
1.1 misho 169: (PNT) += len; \
170: }
171:
172: #define RTA_NAME_GET(DEST, RTA, RTMADDRS, PNT, LEN) \
173: if ((RTMADDRS) & (RTA)) \
174: { \
175: u_char *pdest = (u_char *) (DEST); \
176: int len = SAROUNDUP ((PNT)); \
177: struct sockaddr_dl *sdl = (struct sockaddr_dl *)(PNT); \
178: if (IS_ZEBRA_DEBUG_KERNEL) \
179: zlog_debug ("%s: RTA_SDL_GET nlen %d, alen %d", \
180: __func__, sdl->sdl_nlen, sdl->sdl_alen); \
181: if ( ((DEST) != NULL) && (sdl->sdl_family == AF_LINK) \
182: && (sdl->sdl_nlen < IFNAMSIZ) && (sdl->sdl_nlen <= len) ) \
183: { \
184: memcpy (pdest, sdl->sdl_data, sdl->sdl_nlen); \
185: pdest[sdl->sdl_nlen] = '\0'; \
186: (LEN) = sdl->sdl_nlen; \
187: } \
188: (PNT) += len; \
189: } \
190: else \
191: { \
192: (LEN) = 0; \
193: }
194: /* Routing socket message types. */
195: const struct message rtm_type_str[] =
196: {
197: {RTM_ADD, "RTM_ADD"},
198: {RTM_DELETE, "RTM_DELETE"},
199: {RTM_CHANGE, "RTM_CHANGE"},
200: {RTM_GET, "RTM_GET"},
201: {RTM_LOSING, "RTM_LOSING"},
202: {RTM_REDIRECT, "RTM_REDIRECT"},
203: {RTM_MISS, "RTM_MISS"},
204: {RTM_LOCK, "RTM_LOCK"},
205: #ifdef OLDADD
206: {RTM_OLDADD, "RTM_OLDADD"},
207: #endif /* RTM_OLDADD */
208: #ifdef RTM_OLDDEL
209: {RTM_OLDDEL, "RTM_OLDDEL"},
210: #endif /* RTM_OLDDEL */
211: {RTM_RESOLVE, "RTM_RESOLVE"},
212: {RTM_NEWADDR, "RTM_NEWADDR"},
213: {RTM_DELADDR, "RTM_DELADDR"},
214: {RTM_IFINFO, "RTM_IFINFO"},
215: #ifdef RTM_OIFINFO
216: {RTM_OIFINFO, "RTM_OIFINFO"},
217: #endif /* RTM_OIFINFO */
218: #ifdef RTM_NEWMADDR
219: {RTM_NEWMADDR, "RTM_NEWMADDR"},
220: #endif /* RTM_NEWMADDR */
221: #ifdef RTM_DELMADDR
222: {RTM_DELMADDR, "RTM_DELMADDR"},
223: #endif /* RTM_DELMADDR */
224: #ifdef RTM_IFANNOUNCE
225: {RTM_IFANNOUNCE, "RTM_IFANNOUNCE"},
226: #endif /* RTM_IFANNOUNCE */
227: {0, NULL}
228: };
229:
230: static const struct message rtm_flag_str[] =
231: {
232: {RTF_UP, "UP"},
233: {RTF_GATEWAY, "GATEWAY"},
234: {RTF_HOST, "HOST"},
235: {RTF_REJECT, "REJECT"},
236: {RTF_DYNAMIC, "DYNAMIC"},
237: {RTF_MODIFIED, "MODIFIED"},
238: {RTF_DONE, "DONE"},
239: #ifdef RTF_MASK
240: {RTF_MASK, "MASK"},
241: #endif /* RTF_MASK */
242: #ifdef RTF_CLONING
243: {RTF_CLONING, "CLONING"},
244: #endif /* RTF_CLONING */
245: {RTF_XRESOLVE, "XRESOLVE"},
1.1.1.4 ! misho 246: #ifdef RTF_LLINFO
1.1 misho 247: {RTF_LLINFO, "LLINFO"},
1.1.1.4 ! misho 248: #endif /* RTF_LLINFO */
1.1 misho 249: {RTF_STATIC, "STATIC"},
250: {RTF_BLACKHOLE, "BLACKHOLE"},
251: #ifdef RTF_PRIVATE
252: {RTF_PRIVATE, "PRIVATE"},
253: #endif /* RTF_PRIVATE */
254: {RTF_PROTO1, "PROTO1"},
255: {RTF_PROTO2, "PROTO2"},
256: #ifdef RTF_PRCLONING
257: {RTF_PRCLONING, "PRCLONING"},
258: #endif /* RTF_PRCLONING */
259: #ifdef RTF_WASCLONED
260: {RTF_WASCLONED, "WASCLONED"},
261: #endif /* RTF_WASCLONED */
262: #ifdef RTF_PROTO3
263: {RTF_PROTO3, "PROTO3"},
264: #endif /* RTF_PROTO3 */
265: #ifdef RTF_PINNED
266: {RTF_PINNED, "PINNED"},
267: #endif /* RTF_PINNED */
268: #ifdef RTF_LOCAL
269: {RTF_LOCAL, "LOCAL"},
270: #endif /* RTF_LOCAL */
271: #ifdef RTF_BROADCAST
272: {RTF_BROADCAST, "BROADCAST"},
273: #endif /* RTF_BROADCAST */
274: #ifdef RTF_MULTICAST
275: {RTF_MULTICAST, "MULTICAST"},
276: #endif /* RTF_MULTICAST */
277: #ifdef RTF_MULTIRT
278: {RTF_MULTIRT, "MULTIRT"},
279: #endif /* RTF_MULTIRT */
280: #ifdef RTF_SETSRC
281: {RTF_SETSRC, "SETSRC"},
282: #endif /* RTF_SETSRC */
283: {0, NULL}
284: };
285:
286: /* Kernel routing update socket. */
287: int routing_sock = -1;
288:
289: /* Yes I'm checking ugly routing socket behavior. */
290: /* #define DEBUG */
291:
292: /* Supported address family check. */
1.1.1.4 ! misho 293: static inline int
1.1 misho 294: af_check (int family)
295: {
296: if (family == AF_INET)
297: return 1;
298: #ifdef HAVE_IPV6
299: if (family == AF_INET6)
300: return 1;
301: #endif /* HAVE_IPV6 */
302: return 0;
303: }
1.1.1.4 ! misho 304:
1.1 misho 305: /* Dump routing table flag for debug purpose. */
306: static void
307: rtm_flag_dump (int flag)
308: {
309: const struct message *mes;
310: static char buf[BUFSIZ];
311:
312: buf[0] = '\0';
313: for (mes = rtm_flag_str; mes->key != 0; mes++)
314: {
315: if (mes->key & flag)
316: {
317: strlcat (buf, mes->str, BUFSIZ);
318: strlcat (buf, " ", BUFSIZ);
319: }
320: }
321: zlog_debug ("Kernel: %s", buf);
322: }
323:
324: #ifdef RTM_IFANNOUNCE
325: /* Interface adding function */
326: static int
327: ifan_read (struct if_announcemsghdr *ifan)
328: {
329: struct interface *ifp;
330:
331: ifp = if_lookup_by_index (ifan->ifan_index);
332:
333: if (ifp)
334: assert ( (ifp->ifindex == ifan->ifan_index)
335: || (ifp->ifindex == IFINDEX_INTERNAL) );
336:
337: if ( (ifp == NULL)
338: || ((ifp->ifindex == IFINDEX_INTERNAL)
339: && (ifan->ifan_what == IFAN_ARRIVAL)) )
340: {
341: if (IS_ZEBRA_DEBUG_KERNEL)
342: zlog_debug ("%s: creating interface for ifindex %d, name %s",
343: __func__, ifan->ifan_index, ifan->ifan_name);
344:
345: /* Create Interface */
346: ifp = if_get_by_name_len(ifan->ifan_name,
347: strnlen(ifan->ifan_name,
348: sizeof(ifan->ifan_name)));
349: ifp->ifindex = ifan->ifan_index;
350:
1.1.1.4 ! misho 351: if_get_metric (ifp);
1.1 misho 352: if_add_update (ifp);
353: }
354: else if (ifp != NULL && ifan->ifan_what == IFAN_DEPARTURE)
355: if_delete_update (ifp);
356:
357: if_get_flags (ifp);
358: if_get_mtu (ifp);
359: if_get_metric (ifp);
360:
361: if (IS_ZEBRA_DEBUG_KERNEL)
362: zlog_debug ("%s: interface %s index %d",
363: __func__, ifan->ifan_name, ifan->ifan_index);
364:
365: return 0;
366: }
367: #endif /* RTM_IFANNOUNCE */
368:
1.1.1.3 misho 369: #ifdef HAVE_BSD_IFI_LINK_STATE
1.1 misho 370: /* BSD link detect translation */
371: static void
372: bsd_linkdetect_translate (struct if_msghdr *ifm)
373: {
374: if ((ifm->ifm_data.ifi_link_state >= LINK_STATE_UP) ||
375: (ifm->ifm_data.ifi_link_state == LINK_STATE_UNKNOWN))
376: SET_FLAG(ifm->ifm_flags, IFF_RUNNING);
377: else
378: UNSET_FLAG(ifm->ifm_flags, IFF_RUNNING);
379: }
1.1.1.3 misho 380: #endif /* HAVE_BSD_IFI_LINK_STATE */
1.1 misho 381:
1.1.1.4 ! misho 382: static enum zebra_link_type
! 383: sdl_to_zebra_link_type (unsigned int sdlt)
! 384: {
! 385: switch (sdlt)
! 386: {
! 387: case IFT_ETHER: return ZEBRA_LLT_ETHER;
! 388: case IFT_X25: return ZEBRA_LLT_X25;
! 389: case IFT_FDDI: return ZEBRA_LLT_FDDI;
! 390: case IFT_PPP: return ZEBRA_LLT_PPP;
! 391: case IFT_LOOP: return ZEBRA_LLT_LOOPBACK;
! 392: case IFT_SLIP: return ZEBRA_LLT_SLIP;
! 393: case IFT_ARCNET: return ZEBRA_LLT_ARCNET;
! 394: case IFT_ATM: return ZEBRA_LLT_ATM;
! 395: case IFT_LOCALTALK: return ZEBRA_LLT_LOCALTLK;
! 396: case IFT_HIPPI: return ZEBRA_LLT_HIPPI;
! 397: #ifdef IFT_IEEE1394
! 398: case IFT_IEEE1394: return ZEBRA_LLT_IEEE1394;
! 399: #endif
! 400:
! 401: default: return ZEBRA_LLT_UNKNOWN;
! 402: }
! 403: }
! 404:
1.1 misho 405: /*
406: * Handle struct if_msghdr obtained from reading routing socket or
407: * sysctl (from interface_list). There may or may not be sockaddrs
408: * present after the header.
409: */
410: int
411: ifm_read (struct if_msghdr *ifm)
412: {
413: struct interface *ifp = NULL;
1.1.1.2 misho 414: struct sockaddr_dl *sdl;
1.1 misho 415: char ifname[IFNAMSIZ];
416: short ifnlen = 0;
1.1.1.3 misho 417: caddr_t cp;
1.1 misho 418:
419: /* terminate ifname at head (for strnlen) and tail (for safety) */
420: ifname[IFNAMSIZ - 1] = '\0';
421:
422: /* paranoia: sanity check structure */
423: if (ifm->ifm_msglen < sizeof(struct if_msghdr))
424: {
425: zlog_err ("ifm_read: ifm->ifm_msglen %d too short\n",
426: ifm->ifm_msglen);
427: return -1;
428: }
429:
430: /*
431: * Check for a sockaddr_dl following the message. First, point to
432: * where a socakddr might be if one follows the message.
433: */
434: cp = (void *)(ifm + 1);
435:
436: #ifdef SUNOS_5
437: /*
438: * XXX This behavior should be narrowed to only the kernel versions
439: * for which the structures returned do not match the headers.
440: *
441: * if_msghdr_t on 64 bit kernels in Solaris 9 and earlier versions
442: * is 12 bytes larger than the 32 bit version.
443: */
444: if (((struct sockaddr *) cp)->sa_family == AF_UNSPEC)
445: cp = cp + 12;
446: #endif
447:
448: RTA_ADDR_GET (NULL, RTA_DST, ifm->ifm_addrs, cp);
449: RTA_ADDR_GET (NULL, RTA_GATEWAY, ifm->ifm_addrs, cp);
450: RTA_ATTR_GET (NULL, RTA_NETMASK, ifm->ifm_addrs, cp);
451: RTA_ADDR_GET (NULL, RTA_GENMASK, ifm->ifm_addrs, cp);
1.1.1.2 misho 452: sdl = (struct sockaddr_dl *)cp;
1.1 misho 453: RTA_NAME_GET (ifname, RTA_IFP, ifm->ifm_addrs, cp, ifnlen);
454: RTA_ADDR_GET (NULL, RTA_IFA, ifm->ifm_addrs, cp);
455: RTA_ADDR_GET (NULL, RTA_AUTHOR, ifm->ifm_addrs, cp);
456: RTA_ADDR_GET (NULL, RTA_BRD, ifm->ifm_addrs, cp);
457:
458: if (IS_ZEBRA_DEBUG_KERNEL)
459: zlog_debug ("%s: sdl ifname %s", __func__, (ifnlen ? ifname : "(nil)"));
460:
461: /*
462: * Look up on ifindex first, because ifindices are the primary handle for
463: * interfaces across the user/kernel boundary, for most systems. (Some
464: * messages, such as up/down status changes on NetBSD, do not include a
465: * sockaddr_dl).
466: */
467: if ( (ifp = if_lookup_by_index (ifm->ifm_index)) != NULL )
468: {
469: /* we have an ifp, verify that the name matches as some systems,
470: * eg Solaris, have a 1:many association of ifindex:ifname
471: * if they dont match, we dont have the correct ifp and should
472: * set it back to NULL to let next check do lookup by name
473: */
474: if (ifnlen && (strncmp (ifp->name, ifname, IFNAMSIZ) != 0) )
475: {
476: if (IS_ZEBRA_DEBUG_KERNEL)
477: zlog_debug ("%s: ifp name %s doesnt match sdl name %s",
478: __func__, ifp->name, ifname);
479: ifp = NULL;
480: }
481: }
482:
483: /*
484: * If we dont have an ifp, try looking up by name. Particularly as some
485: * systems (Solaris) have a 1:many mapping of ifindex:ifname - the ifname
486: * is therefore our unique handle to that interface.
487: *
488: * Interfaces specified in the configuration file for which the ifindex
489: * has not been determined will have ifindex == IFINDEX_INTERNAL, and such
490: * interfaces are found by this search, and then their ifindex values can
491: * be filled in.
492: */
493: if ( (ifp == NULL) && ifnlen)
494: ifp = if_lookup_by_name (ifname);
495:
496: /*
497: * If ifp still does not exist or has an invalid index (IFINDEX_INTERNAL),
498: * create or fill in an interface.
499: */
500: if ((ifp == NULL) || (ifp->ifindex == IFINDEX_INTERNAL))
501: {
502: /*
503: * To create or fill in an interface, a sockaddr_dl (via
504: * RTA_IFP) is required.
505: */
506: if (!ifnlen)
507: {
508: zlog_warn ("Interface index %d (new) missing ifname\n",
509: ifm->ifm_index);
510: return -1;
511: }
512:
513: #ifndef RTM_IFANNOUNCE
514: /* Down->Down interface should be ignored here.
515: * See further comment below.
516: */
517: if (!CHECK_FLAG (ifm->ifm_flags, IFF_UP))
518: return 0;
519: #endif /* !RTM_IFANNOUNCE */
520:
521: if (ifp == NULL)
522: {
523: /* Interface that zebra was not previously aware of, so create. */
524: ifp = if_create (ifname, ifnlen);
525: if (IS_ZEBRA_DEBUG_KERNEL)
526: zlog_debug ("%s: creating ifp for ifindex %d",
527: __func__, ifm->ifm_index);
528: }
529:
530: if (IS_ZEBRA_DEBUG_KERNEL)
531: zlog_debug ("%s: updated/created ifp, ifname %s, ifindex %d",
532: __func__, ifp->name, ifp->ifindex);
533: /*
534: * Fill in newly created interface structure, or larval
535: * structure with ifindex IFINDEX_INTERNAL.
536: */
537: ifp->ifindex = ifm->ifm_index;
538:
1.1.1.3 misho 539: #ifdef HAVE_BSD_IFI_LINK_STATE /* translate BSD kernel msg for link-state */
1.1 misho 540: bsd_linkdetect_translate(ifm);
1.1.1.3 misho 541: #endif /* HAVE_BSD_IFI_LINK_STATE */
1.1 misho 542:
543: if_flags_update (ifp, ifm->ifm_flags);
544: #if defined(__bsdi__)
545: if_kvm_get_mtu (ifp);
546: #else
547: if_get_mtu (ifp);
548: #endif /* __bsdi__ */
549: if_get_metric (ifp);
550:
1.1.1.2 misho 551: /*
552: * XXX sockaddr_dl contents can be larger than the structure
1.1.1.3 misho 553: * definition. There are 2 big families here:
554: * - BSD has sdl_len + sdl_data[16] + overruns sdl_data
555: * we MUST use sdl_len here or we'll truncate data.
556: * - Solaris has no sdl_len, but sdl_data[244]
557: * presumably, it's not going to run past that, so sizeof()
558: * is fine here.
1.1.1.2 misho 559: * a nonzero ifnlen from RTA_NAME_GET() means sdl is valid
560: */
1.1.1.4 ! misho 561: ifp->ll_type = ZEBRA_LLT_UNKNOWN;
! 562: ifp->hw_addr_len = 0;
1.1.1.2 misho 563: if (ifnlen)
1.1.1.4 ! misho 564: {
1.1.1.3 misho 565: #ifdef HAVE_STRUCT_SOCKADDR_DL_SDL_LEN
1.1.1.4 ! misho 566: memcpy (&((struct zebra_if *)ifp->info)->sdl, sdl, sdl->sdl_len);
1.1.1.3 misho 567: #else
1.1.1.4 ! misho 568: memcpy (&((struct zebra_if *)ifp->info)->sdl, sdl, sizeof (struct sockaddr_dl));
1.1.1.3 misho 569: #endif /* HAVE_STRUCT_SOCKADDR_DL_SDL_LEN */
1.1.1.4 ! misho 570:
! 571: ifp->ll_type = sdl_to_zebra_link_type (sdl->sdl_type);
! 572: if (sdl->sdl_alen <= sizeof(ifp->hw_addr))
! 573: {
! 574: memcpy (ifp->hw_addr, LLADDR(sdl), sdl->sdl_alen);
! 575: ifp->hw_addr_len = sdl->sdl_alen;
! 576: }
! 577: }
1.1.1.2 misho 578:
1.1 misho 579: if_add_update (ifp);
580: }
581: else
582: /*
583: * Interface structure exists. Adjust stored flags from
584: * notification. If interface has up->down or down->up
585: * transition, call state change routines (to adjust routes,
586: * notify routing daemons, etc.). (Other flag changes are stored
587: * but apparently do not trigger action.)
588: */
589: {
590: if (ifp->ifindex != ifm->ifm_index)
591: {
592: zlog_warn ("%s: index mismatch, ifname %s, ifp index %d, "
593: "ifm index %d",
594: __func__, ifp->name, ifp->ifindex, ifm->ifm_index);
595: return -1;
596: }
597:
1.1.1.3 misho 598: #ifdef HAVE_BSD_IFI_LINK_STATE /* translate BSD kernel msg for link-state */
1.1 misho 599: bsd_linkdetect_translate(ifm);
1.1.1.3 misho 600: #endif /* HAVE_BSD_IFI_LINK_STATE */
1.1 misho 601:
602: /* update flags and handle operative->inoperative transition, if any */
603: if_flags_update (ifp, ifm->ifm_flags);
604:
605: #ifndef RTM_IFANNOUNCE
606: if (!if_is_up (ifp))
607: {
608: /* No RTM_IFANNOUNCE on this platform, so we can never
609: * distinguish between ~IFF_UP and delete. We must presume
610: * it has been deleted.
611: * Eg, Solaris will not notify us of unplumb.
612: *
613: * XXX: Fixme - this should be runtime detected
614: * So that a binary compiled on a system with IFANNOUNCE
615: * will still behave correctly if run on a platform without
616: */
617: if_delete_update (ifp);
618: }
619: #endif /* RTM_IFANNOUNCE */
620: if (if_is_up (ifp))
621: {
622: #if defined(__bsdi__)
623: if_kvm_get_mtu (ifp);
624: #else
625: if_get_mtu (ifp);
626: #endif /* __bsdi__ */
627: if_get_metric (ifp);
628: }
629: }
630:
631: #ifdef HAVE_NET_RT_IFLIST
632: ifp->stats = ifm->ifm_data;
633: #endif /* HAVE_NET_RT_IFLIST */
634:
635: if (IS_ZEBRA_DEBUG_KERNEL)
636: zlog_debug ("%s: interface %s index %d",
637: __func__, ifp->name, ifp->ifindex);
638:
639: return 0;
640: }
1.1.1.4 ! misho 641:
1.1 misho 642: /* Address read from struct ifa_msghdr. */
643: static void
644: ifam_read_mesg (struct ifa_msghdr *ifm,
645: union sockunion *addr,
646: union sockunion *mask,
647: union sockunion *brd,
648: char *ifname,
649: short *ifnlen)
650: {
651: caddr_t pnt, end;
652: union sockunion dst;
653: union sockunion gateway;
654:
655: pnt = (caddr_t)(ifm + 1);
656: end = ((caddr_t)ifm) + ifm->ifam_msglen;
657:
658: /* Be sure structure is cleared */
659: memset (mask, 0, sizeof (union sockunion));
660: memset (addr, 0, sizeof (union sockunion));
661: memset (brd, 0, sizeof (union sockunion));
662: memset (&dst, 0, sizeof (union sockunion));
663: memset (&gateway, 0, sizeof (union sockunion));
664:
665: /* We fetch each socket variable into sockunion. */
666: RTA_ADDR_GET (&dst, RTA_DST, ifm->ifam_addrs, pnt);
667: RTA_ADDR_GET (&gateway, RTA_GATEWAY, ifm->ifam_addrs, pnt);
668: RTA_ATTR_GET (mask, RTA_NETMASK, ifm->ifam_addrs, pnt);
669: RTA_ADDR_GET (NULL, RTA_GENMASK, ifm->ifam_addrs, pnt);
670: RTA_NAME_GET (ifname, RTA_IFP, ifm->ifam_addrs, pnt, *ifnlen);
671: RTA_ADDR_GET (addr, RTA_IFA, ifm->ifam_addrs, pnt);
672: RTA_ADDR_GET (NULL, RTA_AUTHOR, ifm->ifam_addrs, pnt);
673: RTA_ADDR_GET (brd, RTA_BRD, ifm->ifam_addrs, pnt);
674:
675: if (IS_ZEBRA_DEBUG_KERNEL)
676: {
1.1.1.4 ! misho 677: int family = sockunion_family(addr);
! 678: switch (family)
1.1 misho 679: {
680: case AF_INET:
681: #ifdef HAVE_IPV6
682: case AF_INET6:
1.1.1.4 ! misho 683: #endif
1.1 misho 684: {
685: char buf[4][INET6_ADDRSTRLEN];
686: zlog_debug ("%s: ifindex %d, ifname %s, ifam_addrs 0x%x, "
687: "ifam_flags 0x%x, addr %s/%d broad %s dst %s "
688: "gateway %s",
1.1.1.4 ! misho 689: __func__, ifm->ifam_index,
1.1 misho 690: (ifnlen ? ifname : "(nil)"), ifm->ifam_addrs,
691: ifm->ifam_flags,
1.1.1.4 ! misho 692: inet_ntop(family,&addr->sin.sin_addr,
1.1 misho 693: buf[0],sizeof(buf[0])),
1.1.1.4 ! misho 694: ip_masklen(mask->sin.sin_addr),
! 695: inet_ntop(family,&brd->sin.sin_addr,
1.1 misho 696: buf[1],sizeof(buf[1])),
1.1.1.4 ! misho 697: inet_ntop(family,&dst.sin.sin_addr,
1.1 misho 698: buf[2],sizeof(buf[2])),
1.1.1.4 ! misho 699: inet_ntop(family,&gateway.sin.sin_addr,
1.1 misho 700: buf[3],sizeof(buf[3])));
701: }
702: break;
703: default:
704: zlog_debug ("%s: ifindex %d, ifname %s, ifam_addrs 0x%x",
705: __func__, ifm->ifam_index,
706: (ifnlen ? ifname : "(nil)"), ifm->ifam_addrs);
707: break;
708: }
709: }
710:
711: /* Assert read up end point matches to end point */
712: if (pnt != end)
1.1.1.2 misho 713: zlog_warn ("ifam_read() doesn't read all socket data");
1.1 misho 714: }
715:
716: /* Interface's address information get. */
717: int
718: ifam_read (struct ifa_msghdr *ifam)
719: {
720: struct interface *ifp = NULL;
721: union sockunion addr, mask, brd;
722: char ifname[INTERFACE_NAMSIZ];
723: short ifnlen = 0;
724: char isalias = 0;
725: int flags = 0;
726:
727: ifname[0] = ifname[INTERFACE_NAMSIZ - 1] = '\0';
728:
729: /* Allocate and read address information. */
730: ifam_read_mesg (ifam, &addr, &mask, &brd, ifname, &ifnlen);
731:
732: if ((ifp = if_lookup_by_index(ifam->ifam_index)) == NULL)
733: {
734: zlog_warn ("%s: no interface for ifname %s, index %d",
735: __func__, ifname, ifam->ifam_index);
736: return -1;
737: }
738:
739: if (ifnlen && strncmp (ifp->name, ifname, INTERFACE_NAMSIZ))
740: isalias = 1;
741:
742: /* N.B. The info in ifa_msghdr does not tell us whether the RTA_BRD
743: field contains a broadcast address or a peer address, so we are forced to
744: rely upon the interface type. */
745: if (if_is_pointopoint(ifp))
746: SET_FLAG(flags, ZEBRA_IFA_PEER);
747:
748: #if 0
749: /* it might seem cute to grab the interface metric here, however
750: * we're processing an address update message, and so some systems
751: * (e.g. FBSD) dont bother to fill in ifam_metric. Disabled, but left
752: * in deliberately, as comment.
753: */
754: ifp->metric = ifam->ifam_metric;
755: #endif
756:
757: /* Add connected address. */
758: switch (sockunion_family (&addr))
759: {
760: case AF_INET:
761: if (ifam->ifam_type == RTM_NEWADDR)
762: connected_add_ipv4 (ifp, flags, &addr.sin.sin_addr,
763: ip_masklen (mask.sin.sin_addr),
764: &brd.sin.sin_addr,
765: (isalias ? ifname : NULL));
766: else
767: connected_delete_ipv4 (ifp, flags, &addr.sin.sin_addr,
768: ip_masklen (mask.sin.sin_addr),
769: &brd.sin.sin_addr);
770: break;
771: #ifdef HAVE_IPV6
772: case AF_INET6:
773: /* Unset interface index from link-local address when IPv6 stack
774: is KAME. */
775: if (IN6_IS_ADDR_LINKLOCAL (&addr.sin6.sin6_addr))
1.1.1.4 ! misho 776: {
! 777: SET_IN6_LINKLOCAL_IFINDEX (addr.sin6.sin6_addr, 0);
! 778: }
1.1 misho 779:
780: if (ifam->ifam_type == RTM_NEWADDR)
781: connected_add_ipv6 (ifp, flags, &addr.sin6.sin6_addr,
782: ip6_masklen (mask.sin6.sin6_addr),
783: &brd.sin6.sin6_addr,
784: (isalias ? ifname : NULL));
785: else
786: connected_delete_ipv6 (ifp,
787: &addr.sin6.sin6_addr,
788: ip6_masklen (mask.sin6.sin6_addr),
789: &brd.sin6.sin6_addr);
790: break;
791: #endif /* HAVE_IPV6 */
792: default:
793: /* Unsupported family silently ignore... */
794: break;
795: }
796:
797: /* Check interface flag for implicit up of the interface. */
798: if_refresh (ifp);
799:
800: #ifdef SUNOS_5
801: /* In addition to lacking IFANNOUNCE, on SUNOS IFF_UP is strange.
802: * See comments for SUNOS_5 in interface.c::if_flags_mangle.
803: *
804: * Here we take care of case where the real IFF_UP was previously
805: * unset (as kept in struct zebra_if.primary_state) and the mangled
806: * IFF_UP (ie IFF_UP set || listcount(connected) has now transitioned
807: * to unset due to the lost non-primary address having DELADDR'd.
808: *
809: * we must delete the interface, because in between here and next
810: * event for this interface-name the administrator could unplumb
811: * and replumb the interface.
812: */
813: if (!if_is_up (ifp))
814: if_delete_update (ifp);
815: #endif /* SUNOS_5 */
816:
817: return 0;
818: }
1.1.1.4 ! misho 819:
1.1 misho 820: /* Interface function for reading kernel routing table information. */
821: static int
822: rtm_read_mesg (struct rt_msghdr *rtm,
823: union sockunion *dest,
824: union sockunion *mask,
825: union sockunion *gate,
826: char *ifname,
827: short *ifnlen)
828: {
829: caddr_t pnt, end;
830:
831: /* Pnt points out socket data start point. */
832: pnt = (caddr_t)(rtm + 1);
833: end = ((caddr_t)rtm) + rtm->rtm_msglen;
834:
835: /* rt_msghdr version check. */
836: if (rtm->rtm_version != RTM_VERSION)
837: zlog (NULL, LOG_WARNING,
838: "Routing message version different %d should be %d."
839: "This may cause problem\n", rtm->rtm_version, RTM_VERSION);
840:
841: /* Be sure structure is cleared */
842: memset (dest, 0, sizeof (union sockunion));
843: memset (gate, 0, sizeof (union sockunion));
844: memset (mask, 0, sizeof (union sockunion));
845:
846: /* We fetch each socket variable into sockunion. */
847: RTA_ADDR_GET (dest, RTA_DST, rtm->rtm_addrs, pnt);
848: RTA_ADDR_GET (gate, RTA_GATEWAY, rtm->rtm_addrs, pnt);
849: RTA_ATTR_GET (mask, RTA_NETMASK, rtm->rtm_addrs, pnt);
850: RTA_ADDR_GET (NULL, RTA_GENMASK, rtm->rtm_addrs, pnt);
851: RTA_NAME_GET (ifname, RTA_IFP, rtm->rtm_addrs, pnt, *ifnlen);
852: RTA_ADDR_GET (NULL, RTA_IFA, rtm->rtm_addrs, pnt);
853: RTA_ADDR_GET (NULL, RTA_AUTHOR, rtm->rtm_addrs, pnt);
854: RTA_ADDR_GET (NULL, RTA_BRD, rtm->rtm_addrs, pnt);
855:
856: /* If there is netmask information set it's family same as
857: destination family*/
858: if (rtm->rtm_addrs & RTA_NETMASK)
859: mask->sa.sa_family = dest->sa.sa_family;
860:
861: /* Assert read up to the end of pointer. */
862: if (pnt != end)
1.1.1.2 misho 863: zlog (NULL, LOG_WARNING, "rtm_read() doesn't read all socket data.");
1.1 misho 864:
865: return rtm->rtm_flags;
866: }
867:
868: void
869: rtm_read (struct rt_msghdr *rtm)
870: {
871: int flags;
872: u_char zebra_flags;
873: union sockunion dest, mask, gate;
874: char ifname[INTERFACE_NAMSIZ + 1];
875: short ifnlen = 0;
876:
877: zebra_flags = 0;
878:
879: /* Read destination and netmask and gateway from rtm message
880: structure. */
881: flags = rtm_read_mesg (rtm, &dest, &mask, &gate, ifname, &ifnlen);
882: if (!(flags & RTF_DONE))
883: return;
884: if (IS_ZEBRA_DEBUG_KERNEL)
885: zlog_debug ("%s: got rtm of type %d (%s)", __func__, rtm->rtm_type,
886: lookup (rtm_type_str, rtm->rtm_type));
887:
888: #ifdef RTF_CLONED /*bsdi, netbsd 1.6*/
889: if (flags & RTF_CLONED)
890: return;
891: #endif
892: #ifdef RTF_WASCLONED /*freebsd*/
893: if (flags & RTF_WASCLONED)
894: return;
895: #endif
896:
1.1.1.4 ! misho 897: if ((rtm->rtm_type == RTM_ADD || rtm->rtm_type == RTM_CHANGE) && ! (flags & RTF_UP))
1.1 misho 898: return;
899:
900: /* This is connected route. */
901: if (! (flags & RTF_GATEWAY))
902: return;
903:
904: if (flags & RTF_PROTO1)
905: SET_FLAG (zebra_flags, ZEBRA_FLAG_SELFROUTE);
906:
907: /* This is persistent route. */
908: if (flags & RTF_STATIC)
909: SET_FLAG (zebra_flags, ZEBRA_FLAG_STATIC);
910:
911: /* This is a reject or blackhole route */
912: if (flags & RTF_REJECT)
913: SET_FLAG (zebra_flags, ZEBRA_FLAG_REJECT);
914: if (flags & RTF_BLACKHOLE)
915: SET_FLAG (zebra_flags, ZEBRA_FLAG_BLACKHOLE);
916:
917: if (dest.sa.sa_family == AF_INET)
918: {
919: struct prefix_ipv4 p;
920:
921: p.family = AF_INET;
922: p.prefix = dest.sin.sin_addr;
923: if (flags & RTF_HOST)
924: p.prefixlen = IPV4_MAX_PREFIXLEN;
925: else
926: p.prefixlen = ip_masklen (mask.sin.sin_addr);
927:
928: /* Catch self originated messages and match them against our current RIB.
929: * At the same time, ignore unconfirmed messages, they should be tracked
930: * by rtm_write() and kernel_rtm_ipv4().
931: */
932: if (rtm->rtm_type != RTM_GET && rtm->rtm_pid == pid)
933: {
1.1.1.4 ! misho 934: char buf[PREFIX_STRLEN], gate_buf[INET_ADDRSTRLEN];
1.1 misho 935: int ret;
936: if (! IS_ZEBRA_DEBUG_RIB)
937: return;
1.1.1.4 ! misho 938: ret = rib_lookup_ipv4_route (&p, &gate, VRF_DEFAULT);
! 939: prefix2str (&p, buf, sizeof(buf));
1.1 misho 940: switch (rtm->rtm_type)
941: {
942: case RTM_ADD:
943: case RTM_GET:
944: case RTM_CHANGE:
945: /* The kernel notifies us about a new route in FIB created by us.
946: Do we have a correspondent entry in our RIB? */
947: switch (ret)
948: {
949: case ZEBRA_RIB_NOTFOUND:
1.1.1.4 ! misho 950: zlog_debug ("%s: %s %s: desync: RR isn't yet in RIB, while already in FIB",
! 951: __func__, lookup (rtm_type_str, rtm->rtm_type), buf);
1.1 misho 952: break;
953: case ZEBRA_RIB_FOUND_CONNECTED:
954: case ZEBRA_RIB_FOUND_NOGATE:
955: inet_ntop (AF_INET, &gate.sin.sin_addr, gate_buf, INET_ADDRSTRLEN);
1.1.1.4 ! misho 956: zlog_debug ("%s: %s %s: desync: RR is in RIB, but gate differs (ours is %s)",
! 957: __func__, lookup (rtm_type_str, rtm->rtm_type), buf, gate_buf);
1.1 misho 958: break;
959: case ZEBRA_RIB_FOUND_EXACT: /* RIB RR == FIB RR */
1.1.1.4 ! misho 960: zlog_debug ("%s: %s %s: done Ok",
! 961: __func__, lookup (rtm_type_str, rtm->rtm_type), buf);
1.1 misho 962: rib_lookup_and_dump (&p);
963: return;
964: break;
965: }
966: break;
967: case RTM_DELETE:
968: /* The kernel notifies us about a route deleted by us. Do we still
969: have it in the RIB? Do we have anything instead? */
970: switch (ret)
971: {
972: case ZEBRA_RIB_FOUND_EXACT:
1.1.1.4 ! misho 973: zlog_debug ("%s: %s %s: desync: RR is still in RIB, while already not in FIB",
! 974: __func__, lookup (rtm_type_str, rtm->rtm_type), buf);
1.1 misho 975: rib_lookup_and_dump (&p);
976: break;
977: case ZEBRA_RIB_FOUND_CONNECTED:
978: case ZEBRA_RIB_FOUND_NOGATE:
1.1.1.4 ! misho 979: zlog_debug ("%s: %s %s: desync: RR is still in RIB, plus gate differs",
! 980: __func__, lookup (rtm_type_str, rtm->rtm_type), buf);
1.1 misho 981: rib_lookup_and_dump (&p);
982: break;
983: case ZEBRA_RIB_NOTFOUND: /* RIB RR == FIB RR */
1.1.1.4 ! misho 984: zlog_debug ("%s: %s %s: done Ok",
! 985: __func__, lookup (rtm_type_str, rtm->rtm_type), buf);
1.1 misho 986: rib_lookup_and_dump (&p);
987: return;
988: break;
989: }
990: break;
991: default:
1.1.1.4 ! misho 992: zlog_debug ("%s: %s: warning: loopback RTM of type %s received",
! 993: __func__, buf, lookup (rtm_type_str, rtm->rtm_type));
1.1 misho 994: }
995: return;
996: }
997:
998: /* Change, delete the old prefix, we have no further information
999: * to specify the route really
1000: */
1001: if (rtm->rtm_type == RTM_CHANGE)
1002: rib_delete_ipv4 (ZEBRA_ROUTE_KERNEL, zebra_flags, &p,
1.1.1.4 ! misho 1003: NULL, 0, VRF_DEFAULT, SAFI_UNICAST);
1.1 misho 1004:
1005: if (rtm->rtm_type == RTM_GET
1006: || rtm->rtm_type == RTM_ADD
1007: || rtm->rtm_type == RTM_CHANGE)
1.1.1.4 ! misho 1008: rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, zebra_flags, &p, &gate.sin.sin_addr,
! 1009: NULL, 0, VRF_DEFAULT, 0, 0, 0, 0, SAFI_UNICAST);
1.1 misho 1010: else
1.1.1.4 ! misho 1011: rib_delete_ipv4 (ZEBRA_ROUTE_KERNEL, zebra_flags, &p,
! 1012: &gate.sin.sin_addr, 0, VRF_DEFAULT, SAFI_UNICAST);
1.1 misho 1013: }
1014: #ifdef HAVE_IPV6
1015: if (dest.sa.sa_family == AF_INET6)
1016: {
1017: /* One day we might have a debug section here like one in the
1018: * IPv4 case above. Just ignore own messages at the moment.
1019: */
1020: if (rtm->rtm_type != RTM_GET && rtm->rtm_pid == pid)
1021: return;
1022: struct prefix_ipv6 p;
1.1.1.4 ! misho 1023: ifindex_t ifindex = 0;
1.1 misho 1024:
1025: p.family = AF_INET6;
1026: p.prefix = dest.sin6.sin6_addr;
1027: if (flags & RTF_HOST)
1028: p.prefixlen = IPV6_MAX_PREFIXLEN;
1029: else
1030: p.prefixlen = ip6_masklen (mask.sin6.sin6_addr);
1031:
1032: #ifdef KAME
1033: if (IN6_IS_ADDR_LINKLOCAL (&gate.sin6.sin6_addr))
1034: {
1035: ifindex = IN6_LINKLOCAL_IFINDEX (gate.sin6.sin6_addr);
1036: SET_IN6_LINKLOCAL_IFINDEX (gate.sin6.sin6_addr, 0);
1037: }
1038: #endif /* KAME */
1039:
1040: /* CHANGE: delete the old prefix, we have no further information
1041: * to specify the route really
1042: */
1043: if (rtm->rtm_type == RTM_CHANGE)
1044: rib_delete_ipv6 (ZEBRA_ROUTE_KERNEL, zebra_flags, &p,
1.1.1.4 ! misho 1045: NULL, 0, VRF_DEFAULT, SAFI_UNICAST);
1.1 misho 1046:
1047: if (rtm->rtm_type == RTM_GET
1048: || rtm->rtm_type == RTM_ADD
1049: || rtm->rtm_type == RTM_CHANGE)
1.1.1.4 ! misho 1050: rib_add_ipv6 (ZEBRA_ROUTE_KERNEL, zebra_flags, &p, &gate.sin6.sin6_addr,
! 1051: ifindex, VRF_DEFAULT, RT_TABLE_MAIN, 0, 0, 0, SAFI_UNICAST);
1.1 misho 1052: else
1.1.1.4 ! misho 1053: rib_delete_ipv6 (ZEBRA_ROUTE_KERNEL, zebra_flags, &p,
! 1054: &gate.sin6.sin6_addr, ifindex,
! 1055: VRF_DEFAULT, SAFI_UNICAST);
1.1 misho 1056: }
1057: #endif /* HAVE_IPV6 */
1058: }
1059:
1060: /* Interface function for the kernel routing table updates. Support
1061: * for RTM_CHANGE will be needed.
1062: * Exported only for rt_socket.c
1063: */
1064: int
1065: rtm_write (int message,
1066: union sockunion *dest,
1067: union sockunion *mask,
1068: union sockunion *gate,
1069: unsigned int index,
1070: int zebra_flags,
1071: int metric)
1072: {
1073: int ret;
1074: caddr_t pnt;
1075: struct interface *ifp;
1076:
1077: /* Sequencial number of routing message. */
1078: static int msg_seq = 0;
1079:
1080: /* Struct of rt_msghdr and buffer for storing socket's data. */
1081: struct
1082: {
1083: struct rt_msghdr rtm;
1084: char buf[512];
1085: } msg;
1086:
1087: if (routing_sock < 0)
1088: return ZEBRA_ERR_EPERM;
1089:
1090: /* Clear and set rt_msghdr values */
1091: memset (&msg, 0, sizeof (struct rt_msghdr));
1092: msg.rtm.rtm_version = RTM_VERSION;
1093: msg.rtm.rtm_type = message;
1094: msg.rtm.rtm_seq = msg_seq++;
1095: msg.rtm.rtm_addrs = RTA_DST;
1096: msg.rtm.rtm_addrs |= RTA_GATEWAY;
1097: msg.rtm.rtm_flags = RTF_UP;
1098: msg.rtm.rtm_index = index;
1099:
1100: if (metric != 0)
1101: {
1102: msg.rtm.rtm_rmx.rmx_hopcount = metric;
1103: msg.rtm.rtm_inits |= RTV_HOPCOUNT;
1104: }
1105:
1106: ifp = if_lookup_by_index (index);
1107:
1.1.1.4 ! misho 1108: if (gate && (message == RTM_ADD || message == RTM_CHANGE))
1.1 misho 1109: msg.rtm.rtm_flags |= RTF_GATEWAY;
1110:
1111: /* When RTF_CLONING is unavailable on BSD, should we set some
1112: * other flag instead?
1113: */
1114: #ifdef RTF_CLONING
1.1.1.4 ! misho 1115: if (! gate && (message == RTM_ADD || message == RTM_CHANGE) && ifp &&
1.1 misho 1116: (ifp->flags & IFF_POINTOPOINT) == 0)
1117: msg.rtm.rtm_flags |= RTF_CLONING;
1118: #endif /* RTF_CLONING */
1119:
1120: /* If no protocol specific gateway is specified, use link
1121: address for gateway. */
1122: if (! gate)
1123: {
1124: if (!ifp)
1125: {
1126: char dest_buf[INET_ADDRSTRLEN] = "NULL", mask_buf[INET_ADDRSTRLEN] = "255.255.255.255";
1127: if (dest)
1128: inet_ntop (AF_INET, &dest->sin.sin_addr, dest_buf, INET_ADDRSTRLEN);
1129: if (mask)
1130: inet_ntop (AF_INET, &mask->sin.sin_addr, mask_buf, INET_ADDRSTRLEN);
1131: zlog_warn ("%s: %s/%s: gate == NULL and no gateway found for ifindex %d",
1132: __func__, dest_buf, mask_buf, index);
1133: return -1;
1134: }
1.1.1.4 ! misho 1135: gate = (union sockunion *) &((struct zebra_if *)ifp->info)->sdl;
1.1 misho 1136: }
1137:
1138: if (mask)
1139: msg.rtm.rtm_addrs |= RTA_NETMASK;
1.1.1.4 ! misho 1140: else if (message == RTM_ADD || message == RTM_CHANGE)
1.1 misho 1141: msg.rtm.rtm_flags |= RTF_HOST;
1142:
1143: /* Tagging route with flags */
1144: msg.rtm.rtm_flags |= (RTF_PROTO1);
1145:
1146: /* Additional flags. */
1147: if (zebra_flags & ZEBRA_FLAG_BLACKHOLE)
1148: msg.rtm.rtm_flags |= RTF_BLACKHOLE;
1149: if (zebra_flags & ZEBRA_FLAG_REJECT)
1150: msg.rtm.rtm_flags |= RTF_REJECT;
1151:
1152:
1153: #define SOCKADDRSET(X,R) \
1154: if (msg.rtm.rtm_addrs & (R)) \
1155: { \
1156: int len = SAROUNDUP (X); \
1157: memcpy (pnt, (caddr_t)(X), len); \
1158: pnt += len; \
1159: }
1160:
1161: pnt = (caddr_t) msg.buf;
1162:
1163: /* Write each socket data into rtm message buffer */
1164: SOCKADDRSET (dest, RTA_DST);
1165: SOCKADDRSET (gate, RTA_GATEWAY);
1166: SOCKADDRSET (mask, RTA_NETMASK);
1167:
1168: msg.rtm.rtm_msglen = pnt - (caddr_t) &msg;
1169:
1170: ret = write (routing_sock, &msg, msg.rtm.rtm_msglen);
1171:
1172: if (ret != msg.rtm.rtm_msglen)
1173: {
1174: if (errno == EEXIST)
1175: return ZEBRA_ERR_RTEXIST;
1176: if (errno == ENETUNREACH)
1177: return ZEBRA_ERR_RTUNREACH;
1178: if (errno == ESRCH)
1179: return ZEBRA_ERR_RTNOEXIST;
1180:
1181: zlog_warn ("%s: write : %s (%d)", __func__, safe_strerror (errno), errno);
1182: return ZEBRA_ERR_KERNEL;
1183: }
1184: return ZEBRA_ERR_NOERROR;
1185: }
1186:
1.1.1.4 ! misho 1187:
1.1 misho 1188: #include "thread.h"
1189: #include "zebra/zserv.h"
1190:
1191: /* For debug purpose. */
1192: static void
1193: rtmsg_debug (struct rt_msghdr *rtm)
1194: {
1195: zlog_debug ("Kernel: Len: %d Type: %s", rtm->rtm_msglen, lookup (rtm_type_str, rtm->rtm_type));
1196: rtm_flag_dump (rtm->rtm_flags);
1197: zlog_debug ("Kernel: message seq %d", rtm->rtm_seq);
1.1.1.4 ! misho 1198: zlog_debug ("Kernel: pid %lld, rtm_addrs 0x%x",
! 1199: (long long)rtm->rtm_pid, rtm->rtm_addrs);
1.1 misho 1200: }
1201:
1202: /* This is pretty gross, better suggestions welcome -- mhandler */
1203: #ifndef RTAX_MAX
1204: #ifdef RTA_NUMBITS
1205: #define RTAX_MAX RTA_NUMBITS
1206: #else
1207: #define RTAX_MAX 8
1208: #endif /* RTA_NUMBITS */
1209: #endif /* RTAX_MAX */
1210:
1211: /* Kernel routing table and interface updates via routing socket. */
1212: static int
1213: kernel_read (struct thread *thread)
1214: {
1215: int sock;
1216: int nbytes;
1217: struct rt_msghdr *rtm;
1218:
1219: /*
1220: * This must be big enough for any message the kernel might send.
1221: * Rather than determining how many sockaddrs of what size might be
1222: * in each particular message, just use RTAX_MAX of sockaddr_storage
1223: * for each. Note that the sockaddrs must be after each message
1224: * definition, or rather after whichever happens to be the largest,
1225: * since the buffer needs to be big enough for a message and the
1226: * sockaddrs together.
1227: */
1228: union
1229: {
1230: /* Routing information. */
1231: struct
1232: {
1233: struct rt_msghdr rtm;
1234: struct sockaddr_storage addr[RTAX_MAX];
1235: } r;
1236:
1237: /* Interface information. */
1238: struct
1239: {
1240: struct if_msghdr ifm;
1241: struct sockaddr_storage addr[RTAX_MAX];
1242: } im;
1243:
1244: /* Interface address information. */
1245: struct
1246: {
1247: struct ifa_msghdr ifa;
1248: struct sockaddr_storage addr[RTAX_MAX];
1249: } ia;
1250:
1251: #ifdef RTM_IFANNOUNCE
1252: /* Interface arrival/departure */
1253: struct
1254: {
1255: struct if_announcemsghdr ifan;
1256: struct sockaddr_storage addr[RTAX_MAX];
1257: } ian;
1258: #endif /* RTM_IFANNOUNCE */
1259:
1260: } buf;
1261:
1262: /* Fetch routing socket. */
1263: sock = THREAD_FD (thread);
1264:
1265: nbytes= read (sock, &buf, sizeof buf);
1266:
1267: if (nbytes <= 0)
1268: {
1269: if (nbytes < 0 && errno != EWOULDBLOCK && errno != EAGAIN)
1270: zlog_warn ("routing socket error: %s", safe_strerror (errno));
1271: return 0;
1272: }
1273:
1274: thread_add_read (zebrad.master, kernel_read, NULL, sock);
1275:
1276: if (IS_ZEBRA_DEBUG_KERNEL)
1277: rtmsg_debug (&buf.r.rtm);
1278:
1279: rtm = &buf.r.rtm;
1280:
1281: /*
1282: * Ensure that we didn't drop any data, so that processing routines
1283: * can assume they have the whole message.
1284: */
1285: if (rtm->rtm_msglen != nbytes)
1286: {
1287: zlog_warn ("kernel_read: rtm->rtm_msglen %d, nbytes %d, type %d\n",
1288: rtm->rtm_msglen, nbytes, rtm->rtm_type);
1289: return -1;
1290: }
1291:
1292: switch (rtm->rtm_type)
1293: {
1294: case RTM_ADD:
1295: case RTM_DELETE:
1296: case RTM_CHANGE:
1297: rtm_read (rtm);
1298: break;
1299: case RTM_IFINFO:
1300: ifm_read (&buf.im.ifm);
1301: break;
1302: case RTM_NEWADDR:
1303: case RTM_DELADDR:
1304: ifam_read (&buf.ia.ifa);
1305: break;
1306: #ifdef RTM_IFANNOUNCE
1307: case RTM_IFANNOUNCE:
1308: ifan_read (&buf.ian.ifan);
1309: break;
1310: #endif /* RTM_IFANNOUNCE */
1311: default:
1312: if (IS_ZEBRA_DEBUG_KERNEL)
1313: zlog_debug("Unprocessed RTM_type: %d", rtm->rtm_type);
1314: break;
1315: }
1316: return 0;
1317: }
1318:
1319: /* Make routing socket. */
1320: static void
1.1.1.4 ! misho 1321: routing_socket (struct zebra_vrf *zvrf)
1.1 misho 1322: {
1.1.1.4 ! misho 1323: if (zvrf->vrf_id != VRF_DEFAULT)
! 1324: return;
! 1325:
1.1 misho 1326: if ( zserv_privs.change (ZPRIVS_RAISE) )
1327: zlog_err ("routing_socket: Can't raise privileges");
1328:
1329: routing_sock = socket (AF_ROUTE, SOCK_RAW, 0);
1330:
1331: if (routing_sock < 0)
1332: {
1333: if ( zserv_privs.change (ZPRIVS_LOWER) )
1334: zlog_err ("routing_socket: Can't lower privileges");
1335: zlog_warn ("Can't init kernel routing socket");
1336: return;
1337: }
1338:
1339: /* XXX: Socket should be NONBLOCK, however as we currently
1340: * discard failed writes, this will lead to inconsistencies.
1341: * For now, socket must be blocking.
1342: */
1343: /*if (fcntl (routing_sock, F_SETFL, O_NONBLOCK) < 0)
1344: zlog_warn ("Can't set O_NONBLOCK to routing socket");*/
1345:
1346: if ( zserv_privs.change (ZPRIVS_LOWER) )
1347: zlog_err ("routing_socket: Can't lower privileges");
1348:
1349: /* kernel_read needs rewrite. */
1350: thread_add_read (zebrad.master, kernel_read, NULL, routing_sock);
1351: }
1352:
1353: /* Exported interface function. This function simply calls
1354: routing_socket (). */
1355: void
1.1.1.4 ! misho 1356: kernel_init (struct zebra_vrf *zvrf)
! 1357: {
! 1358: routing_socket (zvrf);
! 1359: }
! 1360:
! 1361: void
! 1362: kernel_terminate (struct zebra_vrf *zvrf)
1.1 misho 1363: {
1.1.1.4 ! misho 1364: return;
1.1 misho 1365: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>