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