summaryrefslogtreecommitdiffstats
path: root/zebra/kernel_socket.c
diff options
context:
space:
mode:
Diffstat (limited to 'zebra/kernel_socket.c')
-rw-r--r--zebra/kernel_socket.c2046
1 files changed, 1026 insertions, 1020 deletions
diff --git a/zebra/kernel_socket.c b/zebra/kernel_socket.c
index 5b9236f7f..4b63a3eb0 100644
--- a/zebra/kernel_socket.c
+++ b/zebra/kernel_socket.c
@@ -90,7 +90,8 @@ extern struct zebra_privs_t zserv_privs;
* intentional, to provoke filing bug reports with operating systems
* that don't define RT_ROUNDUP or equivalent.
*/
-#warning "net/route.h does not define RT_ROUNDUP; making unwarranted assumptions!"
+#warning \
+ "net/route.h does not define RT_ROUNDUP; making unwarranted assumptions!"
/* OS X (Xcode as of 2014-12) is known not to define RT_ROUNDUP */
#ifdef __APPLE__
@@ -99,8 +100,9 @@ extern struct zebra_privs_t zserv_privs;
#define ROUNDUP_TYPE long
#endif
-#define ROUNDUP(a) \
- ((a) > 0 ? (1 + (((a) - 1) | (sizeof(ROUNDUP_TYPE) - 1))) : sizeof(ROUNDUP_TYPE))
+#define ROUNDUP(a) \
+ ((a) > 0 ? (1 + (((a)-1) | (sizeof(ROUNDUP_TYPE) - 1))) \
+ : sizeof(ROUNDUP_TYPE))
#endif /* defined(ROUNDUP) */
@@ -115,13 +117,14 @@ extern struct zebra_privs_t zserv_privs;
* One would hope all fixed-size structure definitions are aligned,
* but round them up nonetheless.
*/
-#define SAROUNDUP(X) \
- (((struct sockaddr *)(X))->sa_family == AF_INET ? \
- ROUNDUP(sizeof(struct sockaddr_in)):\
- (((struct sockaddr *)(X))->sa_family == AF_INET6 ? \
- ROUNDUP(sizeof(struct sockaddr_in6)) : \
- (((struct sockaddr *)(X))->sa_family == AF_LINK ? \
- ROUNDUP(sizeof(struct sockaddr_dl)) : sizeof(struct sockaddr))))
+#define SAROUNDUP(X) \
+ (((struct sockaddr *)(X))->sa_family == AF_INET \
+ ? ROUNDUP(sizeof(struct sockaddr_in)) \
+ : (((struct sockaddr *)(X))->sa_family == AF_INET6 \
+ ? ROUNDUP(sizeof(struct sockaddr_in6)) \
+ : (((struct sockaddr *)(X))->sa_family == AF_LINK \
+ ? ROUNDUP(sizeof(struct sockaddr_dl)) \
+ : sizeof(struct sockaddr))))
#endif /* HAVE_STRUCT_SOCKADDR_SA_LEN */
#endif /* !SA_SIZE */
@@ -133,152 +136,140 @@ extern struct zebra_privs_t zserv_privs;
* 2. So the compiler doesn't complain when DEST is NULL, which is only true
* when we are skipping the copy and incrementing to the next SA
*/
-static inline void
-rta_copy (union sockunion *dest, caddr_t src) {
- int len;
- if (!dest)
- return;
+static inline void rta_copy(union sockunion *dest, caddr_t src)
+{
+ int len;
+ if (!dest)
+ return;
#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
- len = (((struct sockaddr *)src)->sa_len > sizeof (*dest)) ?
- sizeof (*dest) : ((struct sockaddr *)src)->sa_len ;
+ len = (((struct sockaddr *)src)->sa_len > sizeof(*dest))
+ ? sizeof(*dest)
+ : ((struct sockaddr *)src)->sa_len;
#else
- len = (SAROUNDUP (src) > sizeof (*dest)) ?
- sizeof (*dest) : SAROUNDUP (src) ;
+ len = (SAROUNDUP(src) > sizeof(*dest)) ? sizeof(*dest) : SAROUNDUP(src);
#endif
- memcpy (dest, src, len);
+ memcpy(dest, src, len);
}
-#define RTA_ADDR_GET(DEST, RTA, RTMADDRS, PNT) \
- if ((RTMADDRS) & (RTA)) \
- { \
- int len = SAROUNDUP ((PNT)); \
- if (af_check (((struct sockaddr *)(PNT))->sa_family)) \
- rta_copy((DEST), (PNT)); \
- (PNT) += len; \
- }
-#define RTA_ATTR_GET(DEST, RTA, RTMADDRS, PNT) \
- if ((RTMADDRS) & (RTA)) \
- { \
- int len = SAROUNDUP ((PNT)); \
- rta_copy((DEST), (PNT)); \
- (PNT) += len; \
- }
-
-#define RTA_NAME_GET(DEST, RTA, RTMADDRS, PNT, LEN) \
- if ((RTMADDRS) & (RTA)) \
- { \
- u_char *pdest = (u_char *) (DEST); \
- int len = SAROUNDUP ((PNT)); \
- struct sockaddr_dl *sdl = (struct sockaddr_dl *)(PNT); \
- if (IS_ZEBRA_DEBUG_KERNEL) \
- zlog_debug ("%s: RTA_SDL_GET nlen %d, alen %d", \
- __func__, sdl->sdl_nlen, sdl->sdl_alen); \
- if ( ((DEST) != NULL) && (sdl->sdl_family == AF_LINK) \
- && (sdl->sdl_nlen < IFNAMSIZ) && (sdl->sdl_nlen <= len) ) \
- { \
- memcpy (pdest, sdl->sdl_data, sdl->sdl_nlen); \
- pdest[sdl->sdl_nlen] = '\0'; \
- (LEN) = sdl->sdl_nlen; \
- } \
- (PNT) += len; \
- } \
- else \
- { \
- (LEN) = 0; \
- }
+#define RTA_ADDR_GET(DEST, RTA, RTMADDRS, PNT) \
+ if ((RTMADDRS) & (RTA)) { \
+ int len = SAROUNDUP((PNT)); \
+ if (af_check(((struct sockaddr *)(PNT))->sa_family)) \
+ rta_copy((DEST), (PNT)); \
+ (PNT) += len; \
+ }
+#define RTA_ATTR_GET(DEST, RTA, RTMADDRS, PNT) \
+ if ((RTMADDRS) & (RTA)) { \
+ int len = SAROUNDUP((PNT)); \
+ rta_copy((DEST), (PNT)); \
+ (PNT) += len; \
+ }
+
+#define RTA_NAME_GET(DEST, RTA, RTMADDRS, PNT, LEN) \
+ if ((RTMADDRS) & (RTA)) { \
+ u_char *pdest = (u_char *)(DEST); \
+ int len = SAROUNDUP((PNT)); \
+ struct sockaddr_dl *sdl = (struct sockaddr_dl *)(PNT); \
+ if (IS_ZEBRA_DEBUG_KERNEL) \
+ zlog_debug("%s: RTA_SDL_GET nlen %d, alen %d", \
+ __func__, sdl->sdl_nlen, sdl->sdl_alen); \
+ if (((DEST) != NULL) && (sdl->sdl_family == AF_LINK) \
+ && (sdl->sdl_nlen < IFNAMSIZ) && (sdl->sdl_nlen <= len)) { \
+ memcpy(pdest, sdl->sdl_data, sdl->sdl_nlen); \
+ pdest[sdl->sdl_nlen] = '\0'; \
+ (LEN) = sdl->sdl_nlen; \
+ } \
+ (PNT) += len; \
+ } else { \
+ (LEN) = 0; \
+ }
/* Routing socket message types. */
-const struct message rtm_type_str[] =
-{
- {RTM_ADD, "RTM_ADD"},
- {RTM_DELETE, "RTM_DELETE"},
- {RTM_CHANGE, "RTM_CHANGE"},
- {RTM_GET, "RTM_GET"},
- {RTM_LOSING, "RTM_LOSING"},
- {RTM_REDIRECT, "RTM_REDIRECT"},
- {RTM_MISS, "RTM_MISS"},
- {RTM_LOCK, "RTM_LOCK"},
+const struct message rtm_type_str[] = {{RTM_ADD, "RTM_ADD"},
+ {RTM_DELETE, "RTM_DELETE"},
+ {RTM_CHANGE, "RTM_CHANGE"},
+ {RTM_GET, "RTM_GET"},
+ {RTM_LOSING, "RTM_LOSING"},
+ {RTM_REDIRECT, "RTM_REDIRECT"},
+ {RTM_MISS, "RTM_MISS"},
+ {RTM_LOCK, "RTM_LOCK"},
#ifdef OLDADD
- {RTM_OLDADD, "RTM_OLDADD"},
+ {RTM_OLDADD, "RTM_OLDADD"},
#endif /* RTM_OLDADD */
#ifdef RTM_OLDDEL
- {RTM_OLDDEL, "RTM_OLDDEL"},
+ {RTM_OLDDEL, "RTM_OLDDEL"},
#endif /* RTM_OLDDEL */
- {RTM_RESOLVE, "RTM_RESOLVE"},
- {RTM_NEWADDR, "RTM_NEWADDR"},
- {RTM_DELADDR, "RTM_DELADDR"},
- {RTM_IFINFO, "RTM_IFINFO"},
+ {RTM_RESOLVE, "RTM_RESOLVE"},
+ {RTM_NEWADDR, "RTM_NEWADDR"},
+ {RTM_DELADDR, "RTM_DELADDR"},
+ {RTM_IFINFO, "RTM_IFINFO"},
#ifdef RTM_OIFINFO
- {RTM_OIFINFO, "RTM_OIFINFO"},
+ {RTM_OIFINFO, "RTM_OIFINFO"},
#endif /* RTM_OIFINFO */
#ifdef RTM_NEWMADDR
- {RTM_NEWMADDR, "RTM_NEWMADDR"},
+ {RTM_NEWMADDR, "RTM_NEWMADDR"},
#endif /* RTM_NEWMADDR */
#ifdef RTM_DELMADDR
- {RTM_DELMADDR, "RTM_DELMADDR"},
+ {RTM_DELMADDR, "RTM_DELMADDR"},
#endif /* RTM_DELMADDR */
#ifdef RTM_IFANNOUNCE
- {RTM_IFANNOUNCE, "RTM_IFANNOUNCE"},
+ {RTM_IFANNOUNCE, "RTM_IFANNOUNCE"},
#endif /* RTM_IFANNOUNCE */
- { 0 }
-};
-
-static const struct message rtm_flag_str[] =
-{
- {RTF_UP, "UP"},
- {RTF_GATEWAY, "GATEWAY"},
- {RTF_HOST, "HOST"},
- {RTF_REJECT, "REJECT"},
- {RTF_DYNAMIC, "DYNAMIC"},
- {RTF_MODIFIED, "MODIFIED"},
- {RTF_DONE, "DONE"},
+ {0}};
+
+static const struct message rtm_flag_str[] = {{RTF_UP, "UP"},
+ {RTF_GATEWAY, "GATEWAY"},
+ {RTF_HOST, "HOST"},
+ {RTF_REJECT, "REJECT"},
+ {RTF_DYNAMIC, "DYNAMIC"},
+ {RTF_MODIFIED, "MODIFIED"},
+ {RTF_DONE, "DONE"},
#ifdef RTF_MASK
- {RTF_MASK, "MASK"},
+ {RTF_MASK, "MASK"},
#endif /* RTF_MASK */
#ifdef RTF_CLONING
- {RTF_CLONING, "CLONING"},
+ {RTF_CLONING, "CLONING"},
#endif /* RTF_CLONING */
#ifdef RTF_XRESOLVE
- {RTF_XRESOLVE, "XRESOLVE"},
+ {RTF_XRESOLVE, "XRESOLVE"},
#endif /* RTF_XRESOLVE */
#ifdef RTF_LLINFO
- {RTF_LLINFO, "LLINFO"},
+ {RTF_LLINFO, "LLINFO"},
#endif /* RTF_LLINFO */
- {RTF_STATIC, "STATIC"},
- {RTF_BLACKHOLE, "BLACKHOLE"},
+ {RTF_STATIC, "STATIC"},
+ {RTF_BLACKHOLE, "BLACKHOLE"},
#ifdef RTF_PRIVATE
- {RTF_PRIVATE, "PRIVATE"},
+ {RTF_PRIVATE, "PRIVATE"},
#endif /* RTF_PRIVATE */
- {RTF_PROTO1, "PROTO1"},
- {RTF_PROTO2, "PROTO2"},
+ {RTF_PROTO1, "PROTO1"},
+ {RTF_PROTO2, "PROTO2"},
#ifdef RTF_PRCLONING
- {RTF_PRCLONING, "PRCLONING"},
+ {RTF_PRCLONING, "PRCLONING"},
#endif /* RTF_PRCLONING */
#ifdef RTF_WASCLONED
- {RTF_WASCLONED, "WASCLONED"},
+ {RTF_WASCLONED, "WASCLONED"},
#endif /* RTF_WASCLONED */
#ifdef RTF_PROTO3
- {RTF_PROTO3, "PROTO3"},
+ {RTF_PROTO3, "PROTO3"},
#endif /* RTF_PROTO3 */
#ifdef RTF_PINNED
- {RTF_PINNED, "PINNED"},
+ {RTF_PINNED, "PINNED"},
#endif /* RTF_PINNED */
#ifdef RTF_LOCAL
- {RTF_LOCAL, "LOCAL"},
+ {RTF_LOCAL, "LOCAL"},
#endif /* RTF_LOCAL */
#ifdef RTF_BROADCAST
- {RTF_BROADCAST, "BROADCAST"},
+ {RTF_BROADCAST, "BROADCAST"},
#endif /* RTF_BROADCAST */
#ifdef RTF_MULTICAST
- {RTF_MULTICAST, "MULTICAST"},
+ {RTF_MULTICAST, "MULTICAST"},
#endif /* RTF_MULTICAST */
#ifdef RTF_MULTIRT
- {RTF_MULTIRT, "MULTIRT"},
+ {RTF_MULTIRT, "MULTIRT"},
#endif /* RTF_MULTIRT */
#ifdef RTF_SETSRC
- {RTF_SETSRC, "SETSRC"},
+ {RTF_SETSRC, "SETSRC"},
#endif /* RTF_SETSRC */
- { 0 }
-};
+ {0}};
/* Kernel routing update socket. */
int routing_sock = -1;
@@ -287,115 +278,117 @@ int routing_sock = -1;
/* #define DEBUG */
/* Supported address family check. */
-static inline int
-af_check (int family)
+static inline int af_check(int family)
{
- if (family == AF_INET)
- return 1;
- if (family == AF_INET6)
- return 1;
- return 0;
+ if (family == AF_INET)
+ return 1;
+ if (family == AF_INET6)
+ return 1;
+ return 0;
}
/* Dump routing table flag for debug purpose. */
-static void
-rtm_flag_dump (int flag)
+static void rtm_flag_dump(int flag)
{
- const struct message *mes;
- static char buf[BUFSIZ];
-
- buf[0] = '\0';
- for (mes = rtm_flag_str; mes->key != 0; mes++)
- {
- if (mes->key & flag)
- {
- strlcat (buf, mes->str, BUFSIZ);
- strlcat (buf, " ", BUFSIZ);
+ const struct message *mes;
+ static char buf[BUFSIZ];
+
+ buf[0] = '\0';
+ for (mes = rtm_flag_str; mes->key != 0; mes++) {
+ if (mes->key & flag) {
+ strlcat(buf, mes->str, BUFSIZ);
+ strlcat(buf, " ", BUFSIZ);
+ }
}
- }
- zlog_debug ("Kernel: %s", buf);
+ zlog_debug("Kernel: %s", buf);
}
#ifdef RTM_IFANNOUNCE
/* Interface adding function */
-static int
-ifan_read (struct if_announcemsghdr *ifan)
+static int ifan_read(struct if_announcemsghdr *ifan)
{
- struct interface *ifp;
-
- ifp = if_lookup_by_index (ifan->ifan_index, VRF_DEFAULT);
-
- if (ifp)
- assert ( (ifp->ifindex == ifan->ifan_index)
- || (ifp->ifindex == IFINDEX_INTERNAL) );
-
- if ( (ifp == NULL)
- || ((ifp->ifindex == IFINDEX_INTERNAL)
- && (ifan->ifan_what == IFAN_ARRIVAL)) )
- {
- if (IS_ZEBRA_DEBUG_KERNEL)
- zlog_debug ("%s: creating interface for ifindex %d, name %s",
- __func__, ifan->ifan_index, ifan->ifan_name);
-
- /* Create Interface */
- ifp = if_get_by_name_len(ifan->ifan_name,
- strnlen(ifan->ifan_name,
- sizeof(ifan->ifan_name)),
- VRF_DEFAULT, 0);
- ifp->ifindex = ifan->ifan_index;
-
- if_get_metric (ifp);
- if_add_update (ifp);
- }
- else if (ifp != NULL && ifan->ifan_what == IFAN_DEPARTURE)
- if_delete_update (ifp);
-
- if_get_flags (ifp);
- if_get_mtu (ifp);
- if_get_metric (ifp);
-
- if (IS_ZEBRA_DEBUG_KERNEL)
- zlog_debug ("%s: interface %s index %d",
- __func__, ifan->ifan_name, ifan->ifan_index);
-
- return 0;
+ struct interface *ifp;
+
+ ifp = if_lookup_by_index(ifan->ifan_index, VRF_DEFAULT);
+
+ if (ifp)
+ assert((ifp->ifindex == ifan->ifan_index)
+ || (ifp->ifindex == IFINDEX_INTERNAL));
+
+ if ((ifp == NULL) || ((ifp->ifindex == IFINDEX_INTERNAL)
+ && (ifan->ifan_what == IFAN_ARRIVAL))) {
+ if (IS_ZEBRA_DEBUG_KERNEL)
+ zlog_debug(
+ "%s: creating interface for ifindex %d, name %s",
+ __func__, ifan->ifan_index, ifan->ifan_name);
+
+ /* Create Interface */
+ ifp = if_get_by_name_len(
+ ifan->ifan_name,
+ strnlen(ifan->ifan_name, sizeof(ifan->ifan_name)),
+ VRF_DEFAULT, 0);
+ ifp->ifindex = ifan->ifan_index;
+
+ if_get_metric(ifp);
+ if_add_update(ifp);
+ } else if (ifp != NULL && ifan->ifan_what == IFAN_DEPARTURE)
+ if_delete_update(ifp);
+
+ if_get_flags(ifp);
+ if_get_mtu(ifp);
+ if_get_metric(ifp);
+
+ if (IS_ZEBRA_DEBUG_KERNEL)
+ zlog_debug("%s: interface %s index %d", __func__,
+ ifan->ifan_name, ifan->ifan_index);
+
+ return 0;
}
#endif /* RTM_IFANNOUNCE */
#ifdef HAVE_BSD_IFI_LINK_STATE
/* BSD link detect translation */
-static void
-bsd_linkdetect_translate (struct if_msghdr *ifm)
+static void bsd_linkdetect_translate(struct if_msghdr *ifm)
{
- if ((ifm->ifm_data.ifi_link_state >= LINK_STATE_UP) ||
- (ifm->ifm_data.ifi_link_state == LINK_STATE_UNKNOWN))
- SET_FLAG(ifm->ifm_flags, IFF_RUNNING);
- else
- UNSET_FLAG(ifm->ifm_flags, IFF_RUNNING);
+ if ((ifm->ifm_data.ifi_link_state >= LINK_STATE_UP)
+ || (ifm->ifm_data.ifi_link_state == LINK_STATE_UNKNOWN))
+ SET_FLAG(ifm->ifm_flags, IFF_RUNNING);
+ else
+ UNSET_FLAG(ifm->ifm_flags, IFF_RUNNING);
}
#endif /* HAVE_BSD_IFI_LINK_STATE */
-static enum zebra_link_type
-sdl_to_zebra_link_type (unsigned int sdlt)
+static enum zebra_link_type sdl_to_zebra_link_type(unsigned int sdlt)
{
- switch (sdlt)
- {
- case IFT_ETHER: return ZEBRA_LLT_ETHER;
- case IFT_X25: return ZEBRA_LLT_X25;
- case IFT_FDDI: return ZEBRA_LLT_FDDI;
- case IFT_PPP: return ZEBRA_LLT_PPP;
- case IFT_LOOP: return ZEBRA_LLT_LOOPBACK;
- case IFT_SLIP: return ZEBRA_LLT_SLIP;
- case IFT_ARCNET: return ZEBRA_LLT_ARCNET;
- case IFT_ATM: return ZEBRA_LLT_ATM;
- case IFT_LOCALTALK: return ZEBRA_LLT_LOCALTLK;
- case IFT_HIPPI: return ZEBRA_LLT_HIPPI;
+ switch (sdlt) {
+ case IFT_ETHER:
+ return ZEBRA_LLT_ETHER;
+ case IFT_X25:
+ return ZEBRA_LLT_X25;
+ case IFT_FDDI:
+ return ZEBRA_LLT_FDDI;
+ case IFT_PPP:
+ return ZEBRA_LLT_PPP;
+ case IFT_LOOP:
+ return ZEBRA_LLT_LOOPBACK;
+ case IFT_SLIP:
+ return ZEBRA_LLT_SLIP;
+ case IFT_ARCNET:
+ return ZEBRA_LLT_ARCNET;
+ case IFT_ATM:
+ return ZEBRA_LLT_ATM;
+ case IFT_LOCALTALK:
+ return ZEBRA_LLT_LOCALTLK;
+ case IFT_HIPPI:
+ return ZEBRA_LLT_HIPPI;
#ifdef IFT_IEEE1394
- case IFT_IEEE1394: return ZEBRA_LLT_IEEE1394;
+ case IFT_IEEE1394:
+ return ZEBRA_LLT_IEEE1394;
#endif
- default: return ZEBRA_LLT_UNKNOWN;
- }
+ default:
+ return ZEBRA_LLT_UNKNOWN;
+ }
}
/*
@@ -403,341 +396,338 @@ sdl_to_zebra_link_type (unsigned int sdlt)
* sysctl (from interface_list). There may or may not be sockaddrs
* present after the header.
*/
-int
-ifm_read (struct if_msghdr *ifm)
+int ifm_read(struct if_msghdr *ifm)
{
- struct interface *ifp = NULL;
- struct sockaddr_dl *sdl;
- char ifname[IFNAMSIZ];
- short ifnlen = 0;
- caddr_t cp;
-
- /* terminate ifname at head (for strnlen) and tail (for safety) */
- ifname[IFNAMSIZ - 1] = '\0';
-
- /* paranoia: sanity check structure */
- if (ifm->ifm_msglen < sizeof(struct if_msghdr))
- {
- zlog_err ("ifm_read: ifm->ifm_msglen %d too short\n",
- ifm->ifm_msglen);
- return -1;
- }
-
- /*
- * Check for a sockaddr_dl following the message. First, point to
- * where a socakddr might be if one follows the message.
- */
- cp = (void *)(ifm + 1);
+ struct interface *ifp = NULL;
+ struct sockaddr_dl *sdl;
+ char ifname[IFNAMSIZ];
+ short ifnlen = 0;
+ caddr_t cp;
+
+ /* terminate ifname at head (for strnlen) and tail (for safety) */
+ ifname[IFNAMSIZ - 1] = '\0';
+
+ /* paranoia: sanity check structure */
+ if (ifm->ifm_msglen < sizeof(struct if_msghdr)) {
+ zlog_err("ifm_read: ifm->ifm_msglen %d too short\n",
+ ifm->ifm_msglen);
+ return -1;
+ }
+
+ /*
+ * Check for a sockaddr_dl following the message. First, point to
+ * where a socakddr might be if one follows the message.
+ */
+ cp = (void *)(ifm + 1);
#ifdef SUNOS_5
- /*
- * XXX This behavior should be narrowed to only the kernel versions
- * for which the structures returned do not match the headers.
- *
- * if_msghdr_t on 64 bit kernels in Solaris 9 and earlier versions
- * is 12 bytes larger than the 32 bit version.
- */
- if (((struct sockaddr *) cp)->sa_family == AF_UNSPEC)
- cp = cp + 12;
+ /*
+ * XXX This behavior should be narrowed to only the kernel versions
+ * for which the structures returned do not match the headers.
+ *
+ * if_msghdr_t on 64 bit kernels in Solaris 9 and earlier versions
+ * is 12 bytes larger than the 32 bit version.
+ */
+ if (((struct sockaddr *)cp)->sa_family == AF_UNSPEC)
+ cp = cp + 12;
#endif
- RTA_ADDR_GET (NULL, RTA_DST, ifm->ifm_addrs, cp);
- RTA_ADDR_GET (NULL, RTA_GATEWAY, ifm->ifm_addrs, cp);
- RTA_ATTR_GET (NULL, RTA_NETMASK, ifm->ifm_addrs, cp);
- RTA_ADDR_GET (NULL, RTA_GENMASK, ifm->ifm_addrs, cp);
- sdl = (struct sockaddr_dl *)cp;
- RTA_NAME_GET (ifname, RTA_IFP, ifm->ifm_addrs, cp, ifnlen);
- RTA_ADDR_GET (NULL, RTA_IFA, ifm->ifm_addrs, cp);
- RTA_ADDR_GET (NULL, RTA_AUTHOR, ifm->ifm_addrs, cp);
- RTA_ADDR_GET (NULL, RTA_BRD, ifm->ifm_addrs, cp);
-
- if (IS_ZEBRA_DEBUG_KERNEL)
- zlog_debug ("%s: sdl ifname %s", __func__, (ifnlen ? ifname : "(nil)"));
-
- /*
- * Look up on ifindex first, because ifindices are the primary handle for
- * interfaces across the user/kernel boundary, for most systems. (Some
- * messages, such as up/down status changes on NetBSD, do not include a
- * sockaddr_dl).
- */
- if ( (ifp = if_lookup_by_index (ifm->ifm_index, VRF_DEFAULT)) != NULL )
- {
- /* we have an ifp, verify that the name matches as some systems,
- * eg Solaris, have a 1:many association of ifindex:ifname
- * if they dont match, we dont have the correct ifp and should
- * set it back to NULL to let next check do lookup by name
- */
- if (ifnlen && (strncmp (ifp->name, ifname, IFNAMSIZ) != 0) )
- {
- if (IS_ZEBRA_DEBUG_KERNEL)
- zlog_debug ("%s: ifp name %s doesnt match sdl name %s",
- __func__, ifp->name, ifname);
- ifp = NULL;
- }
- }
-
- /*
- * If we dont have an ifp, try looking up by name. Particularly as some
- * systems (Solaris) have a 1:many mapping of ifindex:ifname - the ifname
- * is therefore our unique handle to that interface.
- *
- * Interfaces specified in the configuration file for which the ifindex
- * has not been determined will have ifindex == IFINDEX_INTERNAL, and such
- * interfaces are found by this search, and then their ifindex values can
- * be filled in.
- */
- if ( (ifp == NULL) && ifnlen)
- ifp = if_lookup_by_name (ifname, VRF_DEFAULT);
-
- /*
- * If ifp still does not exist or has an invalid index (IFINDEX_INTERNAL),
- * create or fill in an interface.
- */
- if ((ifp == NULL) || (ifp->ifindex == IFINDEX_INTERNAL))
- {
- /*
- * To create or fill in an interface, a sockaddr_dl (via
- * RTA_IFP) is required.
- */
- if (!ifnlen)
- {
- zlog_warn ("Interface index %d (new) missing ifname\n",
- ifm->ifm_index);
- return -1;
+ RTA_ADDR_GET(NULL, RTA_DST, ifm->ifm_addrs, cp);
+ RTA_ADDR_GET(NULL, RTA_GATEWAY, ifm->ifm_addrs, cp);
+ RTA_ATTR_GET(NULL, RTA_NETMASK, ifm->ifm_addrs, cp);
+ RTA_ADDR_GET(NULL, RTA_GENMASK, ifm->ifm_addrs, cp);
+ sdl = (struct sockaddr_dl *)cp;
+ RTA_NAME_GET(ifname, RTA_IFP, ifm->ifm_addrs, cp, ifnlen);
+ RTA_ADDR_GET(NULL, RTA_IFA, ifm->ifm_addrs, cp);
+ RTA_ADDR_GET(NULL, RTA_AUTHOR, ifm->ifm_addrs, cp);
+ RTA_ADDR_GET(NULL, RTA_BRD, ifm->ifm_addrs, cp);
+
+ if (IS_ZEBRA_DEBUG_KERNEL)
+ zlog_debug("%s: sdl ifname %s", __func__,
+ (ifnlen ? ifname : "(nil)"));
+
+ /*
+ * Look up on ifindex first, because ifindices are the primary handle
+ * for
+ * interfaces across the user/kernel boundary, for most systems. (Some
+ * messages, such as up/down status changes on NetBSD, do not include a
+ * sockaddr_dl).
+ */
+ if ((ifp = if_lookup_by_index(ifm->ifm_index, VRF_DEFAULT)) != NULL) {
+ /* we have an ifp, verify that the name matches as some systems,
+ * eg Solaris, have a 1:many association of ifindex:ifname
+ * if they dont match, we dont have the correct ifp and should
+ * set it back to NULL to let next check do lookup by name
+ */
+ if (ifnlen && (strncmp(ifp->name, ifname, IFNAMSIZ) != 0)) {
+ if (IS_ZEBRA_DEBUG_KERNEL)
+ zlog_debug(
+ "%s: ifp name %s doesnt match sdl name %s",
+ __func__, ifp->name, ifname);
+ ifp = NULL;
+ }
}
+ /*
+ * If we dont have an ifp, try looking up by name. Particularly as some
+ * systems (Solaris) have a 1:many mapping of ifindex:ifname - the
+ * ifname
+ * is therefore our unique handle to that interface.
+ *
+ * Interfaces specified in the configuration file for which the ifindex
+ * has not been determined will have ifindex == IFINDEX_INTERNAL, and
+ * such
+ * interfaces are found by this search, and then their ifindex values
+ * can
+ * be filled in.
+ */
+ if ((ifp == NULL) && ifnlen)
+ ifp = if_lookup_by_name(ifname, VRF_DEFAULT);
+
+ /*
+ * If ifp still does not exist or has an invalid index
+ * (IFINDEX_INTERNAL),
+ * create or fill in an interface.
+ */
+ if ((ifp == NULL) || (ifp->ifindex == IFINDEX_INTERNAL)) {
+ /*
+ * To create or fill in an interface, a sockaddr_dl (via
+ * RTA_IFP) is required.
+ */
+ if (!ifnlen) {
+ zlog_warn("Interface index %d (new) missing ifname\n",
+ ifm->ifm_index);
+ return -1;
+ }
+
#ifndef RTM_IFANNOUNCE
- /* Down->Down interface should be ignored here.
- * See further comment below.
- */
- if (!CHECK_FLAG (ifm->ifm_flags, IFF_UP))
- return 0;
+ /* Down->Down interface should be ignored here.
+ * See further comment below.
+ */
+ if (!CHECK_FLAG(ifm->ifm_flags, IFF_UP))
+ return 0;
#endif /* !RTM_IFANNOUNCE */
-
- if (ifp == NULL)
- {
- /* Interface that zebra was not previously aware of, so create. */
- ifp = if_create (ifname, ifnlen, VRF_DEFAULT);
- if (IS_ZEBRA_DEBUG_KERNEL)
- zlog_debug ("%s: creating ifp for ifindex %d",
- __func__, ifm->ifm_index);
- }
-
- if (IS_ZEBRA_DEBUG_KERNEL)
- zlog_debug ("%s: updated/created ifp, ifname %s, ifindex %d",
- __func__, ifp->name, ifp->ifindex);
- /*
- * Fill in newly created interface structure, or larval
- * structure with ifindex IFINDEX_INTERNAL.
- */
- ifp->ifindex = ifm->ifm_index;
-
+
+ if (ifp == NULL) {
+ /* Interface that zebra was not previously aware of, so
+ * create. */
+ ifp = if_create(ifname, ifnlen, VRF_DEFAULT);
+ if (IS_ZEBRA_DEBUG_KERNEL)
+ zlog_debug("%s: creating ifp for ifindex %d",
+ __func__, ifm->ifm_index);
+ }
+
+ if (IS_ZEBRA_DEBUG_KERNEL)
+ zlog_debug(
+ "%s: updated/created ifp, ifname %s, ifindex %d",
+ __func__, ifp->name, ifp->ifindex);
+ /*
+ * Fill in newly created interface structure, or larval
+ * structure with ifindex IFINDEX_INTERNAL.
+ */
+ ifp->ifindex = ifm->ifm_index;
+
#ifdef HAVE_BSD_IFI_LINK_STATE /* translate BSD kernel msg for link-state */
- bsd_linkdetect_translate(ifm);
+ bsd_linkdetect_translate(ifm);
#endif /* HAVE_BSD_IFI_LINK_STATE */
- if_flags_update (ifp, ifm->ifm_flags);
+ if_flags_update(ifp, ifm->ifm_flags);
#if defined(__bsdi__)
- if_kvm_get_mtu (ifp);
+ if_kvm_get_mtu(ifp);
#else
- if_get_mtu (ifp);
+ if_get_mtu(ifp);
#endif /* __bsdi__ */
- if_get_metric (ifp);
-
- /*
- * XXX sockaddr_dl contents can be larger than the structure
- * definition. There are 2 big families here:
- * - BSD has sdl_len + sdl_data[16] + overruns sdl_data
- * we MUST use sdl_len here or we'll truncate data.
- * - Solaris has no sdl_len, but sdl_data[244]
- * presumably, it's not going to run past that, so sizeof()
- * is fine here.
- * a nonzero ifnlen from RTA_NAME_GET() means sdl is valid
- */
- ifp->ll_type = ZEBRA_LLT_UNKNOWN;
- ifp->hw_addr_len = 0;
- if (ifnlen)
- {
+ if_get_metric(ifp);
+
+ /*
+ * XXX sockaddr_dl contents can be larger than the structure
+ * definition. There are 2 big families here:
+ * - BSD has sdl_len + sdl_data[16] + overruns sdl_data
+ * we MUST use sdl_len here or we'll truncate data.
+ * - Solaris has no sdl_len, but sdl_data[244]
+ * presumably, it's not going to run past that, so sizeof()
+ * is fine here.
+ * a nonzero ifnlen from RTA_NAME_GET() means sdl is valid
+ */
+ ifp->ll_type = ZEBRA_LLT_UNKNOWN;
+ ifp->hw_addr_len = 0;
+ if (ifnlen) {
#ifdef HAVE_STRUCT_SOCKADDR_DL_SDL_LEN
- memcpy (&((struct zebra_if *)ifp->info)->sdl, sdl, sdl->sdl_len);
+ memcpy(&((struct zebra_if *)ifp->info)->sdl, sdl,
+ sdl->sdl_len);
#else
- memcpy (&((struct zebra_if *)ifp->info)->sdl, sdl, sizeof (struct sockaddr_dl));
+ memcpy(&((struct zebra_if *)ifp->info)->sdl, sdl,
+ sizeof(struct sockaddr_dl));
#endif /* HAVE_STRUCT_SOCKADDR_DL_SDL_LEN */
- ifp->ll_type = sdl_to_zebra_link_type (sdl->sdl_type);
- if (sdl->sdl_alen <= sizeof(ifp->hw_addr))
- {
- memcpy (ifp->hw_addr, LLADDR(sdl), sdl->sdl_alen);
- ifp->hw_addr_len = sdl->sdl_alen;
- }
- }
-
- if_add_update (ifp);
- }
- else
- /*
- * Interface structure exists. Adjust stored flags from
- * notification. If interface has up->down or down->up
- * transition, call state change routines (to adjust routes,
- * notify routing daemons, etc.). (Other flag changes are stored
- * but apparently do not trigger action.)
- */
- {
- if (ifp->ifindex != ifm->ifm_index)
- {
- zlog_warn ("%s: index mismatch, ifname %s, ifp index %d, "
- "ifm index %d",
- __func__, ifp->name, ifp->ifindex, ifm->ifm_index);
- return -1;
- }
-
+ ifp->ll_type = sdl_to_zebra_link_type(sdl->sdl_type);
+ if (sdl->sdl_alen <= sizeof(ifp->hw_addr)) {
+ memcpy(ifp->hw_addr, LLADDR(sdl),
+ sdl->sdl_alen);
+ ifp->hw_addr_len = sdl->sdl_alen;
+ }
+ }
+
+ if_add_update(ifp);
+ } else
+ /*
+ * Interface structure exists. Adjust stored flags from
+ * notification. If interface has up->down or down->up
+ * transition, call state change routines (to adjust routes,
+ * notify routing daemons, etc.). (Other flag changes are stored
+ * but apparently do not trigger action.)
+ */
+ {
+ if (ifp->ifindex != ifm->ifm_index) {
+ zlog_warn(
+ "%s: index mismatch, ifname %s, ifp index %d, "
+ "ifm index %d",
+ __func__, ifp->name, ifp->ifindex,
+ ifm->ifm_index);
+ return -1;
+ }
+
#ifdef HAVE_BSD_IFI_LINK_STATE /* translate BSD kernel msg for link-state */
- bsd_linkdetect_translate(ifm);
+ bsd_linkdetect_translate(ifm);
#endif /* HAVE_BSD_IFI_LINK_STATE */
- /* update flags and handle operative->inoperative transition, if any */
- if_flags_update (ifp, ifm->ifm_flags);
-
+ /* update flags and handle operative->inoperative transition, if
+ * any */
+ if_flags_update(ifp, ifm->ifm_flags);
+
#ifndef RTM_IFANNOUNCE
- if (!if_is_up (ifp))
- {
- /* No RTM_IFANNOUNCE on this platform, so we can never
- * distinguish between ~IFF_UP and delete. We must presume
- * it has been deleted.
- * Eg, Solaris will not notify us of unplumb.
- *
- * XXX: Fixme - this should be runtime detected
- * So that a binary compiled on a system with IFANNOUNCE
- * will still behave correctly if run on a platform without
- */
- if_delete_update (ifp);
- }
+ if (!if_is_up(ifp)) {
+ /* No RTM_IFANNOUNCE on this platform, so we can never
+ * distinguish between ~IFF_UP and delete. We must
+ * presume
+ * it has been deleted.
+ * Eg, Solaris will not notify us of unplumb.
+ *
+ * XXX: Fixme - this should be runtime detected
+ * So that a binary compiled on a system with IFANNOUNCE
+ * will still behave correctly if run on a platform
+ * without
+ */
+ if_delete_update(ifp);
+ }
#endif /* RTM_IFANNOUNCE */
- if (if_is_up (ifp))
- {
+ if (if_is_up(ifp)) {
#if defined(__bsdi__)
- if_kvm_get_mtu (ifp);
+ if_kvm_get_mtu(ifp);
#else
- if_get_mtu (ifp);
+ if_get_mtu(ifp);
#endif /* __bsdi__ */
- if_get_metric (ifp);
- }
- }
+ if_get_metric(ifp);
+ }
+ }
#ifdef HAVE_NET_RT_IFLIST
- ifp->stats = ifm->ifm_data;
+ ifp->stats = ifm->ifm_data;
#endif /* HAVE_NET_RT_IFLIST */
- if (IS_ZEBRA_DEBUG_KERNEL)
- zlog_debug ("%s: interface %s index %d",
- __func__, ifp->name, ifp->ifindex);
+ if (IS_ZEBRA_DEBUG_KERNEL)
+ zlog_debug("%s: interface %s index %d", __func__, ifp->name,
+ ifp->ifindex);
- return 0;
+ return 0;
}
/* Address read from struct ifa_msghdr. */
-static void
-ifam_read_mesg (struct ifa_msghdr *ifm,
- union sockunion *addr,
- union sockunion *mask,
- union sockunion *brd,
- char *ifname,
- short *ifnlen)
+static void ifam_read_mesg(struct ifa_msghdr *ifm, union sockunion *addr,
+ union sockunion *mask, union sockunion *brd,
+ char *ifname, short *ifnlen)
{
- caddr_t pnt, end;
- union sockunion dst;
- union sockunion gateway;
-
- pnt = (caddr_t)(ifm + 1);
- end = ((caddr_t)ifm) + ifm->ifam_msglen;
-
- /* Be sure structure is cleared */
- memset (mask, 0, sizeof (union sockunion));
- memset (addr, 0, sizeof (union sockunion));
- memset (brd, 0, sizeof (union sockunion));
- memset (&dst, 0, sizeof (union sockunion));
- memset (&gateway, 0, sizeof (union sockunion));
-
- /* We fetch each socket variable into sockunion. */
- RTA_ADDR_GET (&dst, RTA_DST, ifm->ifam_addrs, pnt);
- RTA_ADDR_GET (&gateway, RTA_GATEWAY, ifm->ifam_addrs, pnt);
- RTA_ATTR_GET (mask, RTA_NETMASK, ifm->ifam_addrs, pnt);
- RTA_ADDR_GET (NULL, RTA_GENMASK, ifm->ifam_addrs, pnt);
- RTA_NAME_GET (ifname, RTA_IFP, ifm->ifam_addrs, pnt, *ifnlen);
- RTA_ADDR_GET (addr, RTA_IFA, ifm->ifam_addrs, pnt);
- RTA_ADDR_GET (NULL, RTA_AUTHOR, ifm->ifam_addrs, pnt);
- RTA_ADDR_GET (brd, RTA_BRD, ifm->ifam_addrs, pnt);
-
- if (IS_ZEBRA_DEBUG_KERNEL)
- {
- int family = sockunion_family(addr);
- switch (family)
- {
- case AF_INET:
- case AF_INET6:
- {
- char buf[4][INET6_ADDRSTRLEN];
- zlog_debug ("%s: ifindex %d, ifname %s, ifam_addrs 0x%x, "
- "ifam_flags 0x%x, addr %s/%d broad %s dst %s "
- "gateway %s",
- __func__, ifm->ifam_index,
- (ifnlen ? ifname : "(nil)"), ifm->ifam_addrs,
- ifm->ifam_flags,
- inet_ntop(family,&addr->sin.sin_addr,
- buf[0],sizeof(buf[0])),
- ip_masklen(mask->sin.sin_addr),
- inet_ntop(family,&brd->sin.sin_addr,
- buf[1],sizeof(buf[1])),
- inet_ntop(family,&dst.sin.sin_addr,
- buf[2],sizeof(buf[2])),
- inet_ntop(family,&gateway.sin.sin_addr,
- buf[3],sizeof(buf[3])));
- }
- break;
- default:
- zlog_debug ("%s: ifindex %d, ifname %s, ifam_addrs 0x%x",
- __func__, ifm->ifam_index,
- (ifnlen ? ifname : "(nil)"), ifm->ifam_addrs);
- break;
- }
- }
-
- /* Assert read up end point matches to end point */
- if (pnt != end)
- zlog_warn ("ifam_read() doesn't read all socket data");
+ caddr_t pnt, end;
+ union sockunion dst;
+ union sockunion gateway;
+
+ pnt = (caddr_t)(ifm + 1);
+ end = ((caddr_t)ifm) + ifm->ifam_msglen;
+
+ /* Be sure structure is cleared */
+ memset(mask, 0, sizeof(union sockunion));
+ memset(addr, 0, sizeof(union sockunion));
+ memset(brd, 0, sizeof(union sockunion));
+ memset(&dst, 0, sizeof(union sockunion));
+ memset(&gateway, 0, sizeof(union sockunion));
+
+ /* We fetch each socket variable into sockunion. */
+ RTA_ADDR_GET(&dst, RTA_DST, ifm->ifam_addrs, pnt);
+ RTA_ADDR_GET(&gateway, RTA_GATEWAY, ifm->ifam_addrs, pnt);
+ RTA_ATTR_GET(mask, RTA_NETMASK, ifm->ifam_addrs, pnt);
+ RTA_ADDR_GET(NULL, RTA_GENMASK, ifm->ifam_addrs, pnt);
+ RTA_NAME_GET(ifname, RTA_IFP, ifm->ifam_addrs, pnt, *ifnlen);
+ RTA_ADDR_GET(addr, RTA_IFA, ifm->ifam_addrs, pnt);
+ RTA_ADDR_GET(NULL, RTA_AUTHOR, ifm->ifam_addrs, pnt);
+ RTA_ADDR_GET(brd, RTA_BRD, ifm->ifam_addrs, pnt);
+
+ if (IS_ZEBRA_DEBUG_KERNEL) {
+ int family = sockunion_family(addr);
+ switch (family) {
+ case AF_INET:
+ case AF_INET6: {
+ char buf[4][INET6_ADDRSTRLEN];
+ zlog_debug(
+ "%s: ifindex %d, ifname %s, ifam_addrs 0x%x, "
+ "ifam_flags 0x%x, addr %s/%d broad %s dst %s "
+ "gateway %s",
+ __func__, ifm->ifam_index,
+ (ifnlen ? ifname : "(nil)"), ifm->ifam_addrs,
+ ifm->ifam_flags,
+ inet_ntop(family, &addr->sin.sin_addr, buf[0],
+ sizeof(buf[0])),
+ ip_masklen(mask->sin.sin_addr),
+ inet_ntop(family, &brd->sin.sin_addr, buf[1],
+ sizeof(buf[1])),
+ inet_ntop(family, &dst.sin.sin_addr, buf[2],
+ sizeof(buf[2])),
+ inet_ntop(family, &gateway.sin.sin_addr, buf[3],
+ sizeof(buf[3])));
+ } break;
+ default:
+ zlog_debug("%s: ifindex %d, ifname %s, ifam_addrs 0x%x",
+ __func__, ifm->ifam_index,
+ (ifnlen ? ifname : "(nil)"),
+ ifm->ifam_addrs);
+ break;
+ }
+ }
+
+ /* Assert read up end point matches to end point */
+ if (pnt != end)
+ zlog_warn("ifam_read() doesn't read all socket data");
}
/* Interface's address information get. */
-int
-ifam_read (struct ifa_msghdr *ifam)
+int ifam_read(struct ifa_msghdr *ifam)
{
- struct interface *ifp = NULL;
- union sockunion addr, mask, brd;
- char ifname[INTERFACE_NAMSIZ];
- short ifnlen = 0;
- char isalias = 0;
- int flags = 0;
-
- ifname[0] = ifname[INTERFACE_NAMSIZ - 1] = '\0';
-
- /* Allocate and read address information. */
- ifam_read_mesg (ifam, &addr, &mask, &brd, ifname, &ifnlen);
-
- if ((ifp = if_lookup_by_index(ifam->ifam_index, VRF_DEFAULT)) == NULL)
- {
- zlog_warn ("%s: no interface for ifname %s, index %d",
- __func__, ifname, ifam->ifam_index);
- return -1;
- }
-
- if (ifnlen && strncmp (ifp->name, ifname, INTERFACE_NAMSIZ))
- isalias = 1;
-
- /* N.B. The info in ifa_msghdr does not tell us whether the RTA_BRD
- field contains a broadcast address or a peer address, so we are forced to
- rely upon the interface type. */
- if (if_is_pointopoint(ifp))
- SET_FLAG(flags, ZEBRA_IFA_PEER);
+ struct interface *ifp = NULL;
+ union sockunion addr, mask, brd;
+ char ifname[INTERFACE_NAMSIZ];
+ short ifnlen = 0;
+ char isalias = 0;
+ int flags = 0;
+
+ ifname[0] = ifname[INTERFACE_NAMSIZ - 1] = '\0';
+
+ /* Allocate and read address information. */
+ ifam_read_mesg(ifam, &addr, &mask, &brd, ifname, &ifnlen);
+
+ if ((ifp = if_lookup_by_index(ifam->ifam_index, VRF_DEFAULT)) == NULL) {
+ zlog_warn("%s: no interface for ifname %s, index %d", __func__,
+ ifname, ifam->ifam_index);
+ return -1;
+ }
+
+ if (ifnlen && strncmp(ifp->name, ifname, INTERFACE_NAMSIZ))
+ isalias = 1;
+
+ /* N.B. The info in ifa_msghdr does not tell us whether the RTA_BRD
+ field contains a broadcast address or a peer address, so we are
+ forced to
+ rely upon the interface type. */
+ if (if_is_pointopoint(ifp))
+ SET_FLAG(flags, ZEBRA_IFA_PEER);
#if 0
/* it might seem cute to grab the interface metric here, however
@@ -748,450 +738,477 @@ ifam_read (struct ifa_msghdr *ifam)
ifp->metric = ifam->ifam_metric;
#endif
- /* Add connected address. */
- switch (sockunion_family (&addr))
- {
- case AF_INET:
- if (ifam->ifam_type == RTM_NEWADDR)
- connected_add_ipv4 (ifp, flags, &addr.sin.sin_addr,
- ip_masklen (mask.sin.sin_addr),
- &brd.sin.sin_addr,
- (isalias ? ifname : NULL));
- else
- connected_delete_ipv4 (ifp, flags, &addr.sin.sin_addr,
- ip_masklen (mask.sin.sin_addr),
- &brd.sin.sin_addr);
- break;
- case AF_INET6:
- /* Unset interface index from link-local address when IPv6 stack
- is KAME. */
- if (IN6_IS_ADDR_LINKLOCAL (&addr.sin6.sin6_addr))
- {
- SET_IN6_LINKLOCAL_IFINDEX (addr.sin6.sin6_addr, 0);
- }
-
- if (ifam->ifam_type == RTM_NEWADDR)
- connected_add_ipv6 (ifp, flags, &addr.sin6.sin6_addr,
- ip6_masklen (mask.sin6.sin6_addr),
- &brd.sin6.sin6_addr,
- (isalias ? ifname : NULL));
- else
- connected_delete_ipv6 (ifp,
- &addr.sin6.sin6_addr,
- ip6_masklen (mask.sin6.sin6_addr),
- &brd.sin6.sin6_addr);
- break;
- default:
- /* Unsupported family silently ignore... */
- break;
- }
-
- /* Check interface flag for implicit up of the interface. */
- if_refresh (ifp);
+ /* Add connected address. */
+ switch (sockunion_family(&addr)) {
+ case AF_INET:
+ if (ifam->ifam_type == RTM_NEWADDR)
+ connected_add_ipv4(ifp, flags, &addr.sin.sin_addr,
+ ip_masklen(mask.sin.sin_addr),
+ &brd.sin.sin_addr,
+ (isalias ? ifname : NULL));
+ else
+ connected_delete_ipv4(ifp, flags, &addr.sin.sin_addr,
+ ip_masklen(mask.sin.sin_addr),
+ &brd.sin.sin_addr);
+ break;
+ case AF_INET6:
+ /* Unset interface index from link-local address when IPv6 stack
+ is KAME. */
+ if (IN6_IS_ADDR_LINKLOCAL(&addr.sin6.sin6_addr)) {
+ SET_IN6_LINKLOCAL_IFINDEX(addr.sin6.sin6_addr, 0);
+ }
+
+ if (ifam->ifam_type == RTM_NEWADDR)
+ connected_add_ipv6(ifp, flags, &addr.sin6.sin6_addr,
+ ip6_masklen(mask.sin6.sin6_addr),
+ &brd.sin6.sin6_addr,
+ (isalias ? ifname : NULL));
+ else
+ connected_delete_ipv6(ifp, &addr.sin6.sin6_addr,
+ ip6_masklen(mask.sin6.sin6_addr),
+ &brd.sin6.sin6_addr);
+ break;
+ default:
+ /* Unsupported family silently ignore... */
+ break;
+ }
+
+ /* Check interface flag for implicit up of the interface. */
+ if_refresh(ifp);
#ifdef SUNOS_5
- /* In addition to lacking IFANNOUNCE, on SUNOS IFF_UP is strange.
- * See comments for SUNOS_5 in interface.c::if_flags_mangle.
- *
- * Here we take care of case where the real IFF_UP was previously
- * unset (as kept in struct zebra_if.primary_state) and the mangled
- * IFF_UP (ie IFF_UP set || listcount(connected) has now transitioned
- * to unset due to the lost non-primary address having DELADDR'd.
- *
- * we must delete the interface, because in between here and next
- * event for this interface-name the administrator could unplumb
- * and replumb the interface.
- */
- if (!if_is_up (ifp))
- if_delete_update (ifp);
+ /* In addition to lacking IFANNOUNCE, on SUNOS IFF_UP is strange.
+ * See comments for SUNOS_5 in interface.c::if_flags_mangle.
+ *
+ * Here we take care of case where the real IFF_UP was previously
+ * unset (as kept in struct zebra_if.primary_state) and the mangled
+ * IFF_UP (ie IFF_UP set || listcount(connected) has now transitioned
+ * to unset due to the lost non-primary address having DELADDR'd.
+ *
+ * we must delete the interface, because in between here and next
+ * event for this interface-name the administrator could unplumb
+ * and replumb the interface.
+ */
+ if (!if_is_up(ifp))
+ if_delete_update(ifp);
#endif /* SUNOS_5 */
-
- return 0;
+
+ return 0;
}
/* Interface function for reading kernel routing table information. */
-static int
-rtm_read_mesg (struct rt_msghdr *rtm,
- union sockunion *dest,
- union sockunion *mask,
- union sockunion *gate,
- char *ifname,
- short *ifnlen)
+static int rtm_read_mesg(struct rt_msghdr *rtm, union sockunion *dest,
+ union sockunion *mask, union sockunion *gate,
+ char *ifname, short *ifnlen)
{
- caddr_t pnt, end;
-
- /* Pnt points out socket data start point. */
- pnt = (caddr_t)(rtm + 1);
- end = ((caddr_t)rtm) + rtm->rtm_msglen;
-
- /* rt_msghdr version check. */
- if (rtm->rtm_version != RTM_VERSION)
- zlog_warn("Routing message version different %d should be %d." "This may cause problem\n",
- rtm->rtm_version, RTM_VERSION);
-
- /* Be sure structure is cleared */
- memset (dest, 0, sizeof (union sockunion));
- memset (gate, 0, sizeof (union sockunion));
- memset (mask, 0, sizeof (union sockunion));
-
- /* We fetch each socket variable into sockunion. */
- RTA_ADDR_GET (dest, RTA_DST, rtm->rtm_addrs, pnt);
- RTA_ADDR_GET (gate, RTA_GATEWAY, rtm->rtm_addrs, pnt);
- RTA_ATTR_GET (mask, RTA_NETMASK, rtm->rtm_addrs, pnt);
- RTA_ADDR_GET (NULL, RTA_GENMASK, rtm->rtm_addrs, pnt);
- RTA_NAME_GET (ifname, RTA_IFP, rtm->rtm_addrs, pnt, *ifnlen);
- RTA_ADDR_GET (NULL, RTA_IFA, rtm->rtm_addrs, pnt);
- RTA_ADDR_GET (NULL, RTA_AUTHOR, rtm->rtm_addrs, pnt);
- RTA_ADDR_GET (NULL, RTA_BRD, rtm->rtm_addrs, pnt);
-
- /* If there is netmask information set it's family same as
- destination family*/
- if (rtm->rtm_addrs & RTA_NETMASK)
- mask->sa.sa_family = dest->sa.sa_family;
-
- /* Assert read up to the end of pointer. */
- if (pnt != end)
- zlog_warn("rtm_read() doesn't read all socket data.");
-
- return rtm->rtm_flags;
+ caddr_t pnt, end;
+
+ /* Pnt points out socket data start point. */
+ pnt = (caddr_t)(rtm + 1);
+ end = ((caddr_t)rtm) + rtm->rtm_msglen;
+
+ /* rt_msghdr version check. */
+ if (rtm->rtm_version != RTM_VERSION)
+ zlog_warn(
+ "Routing message version different %d should be %d."
+ "This may cause problem\n",
+ rtm->rtm_version, RTM_VERSION);
+
+ /* Be sure structure is cleared */
+ memset(dest, 0, sizeof(union sockunion));
+ memset(gate, 0, sizeof(union sockunion));
+ memset(mask, 0, sizeof(union sockunion));
+
+ /* We fetch each socket variable into sockunion. */
+ RTA_ADDR_GET(dest, RTA_DST, rtm->rtm_addrs, pnt);
+ RTA_ADDR_GET(gate, RTA_GATEWAY, rtm->rtm_addrs, pnt);
+ RTA_ATTR_GET(mask, RTA_NETMASK, rtm->rtm_addrs, pnt);
+ RTA_ADDR_GET(NULL, RTA_GENMASK, rtm->rtm_addrs, pnt);
+ RTA_NAME_GET(ifname, RTA_IFP, rtm->rtm_addrs, pnt, *ifnlen);
+ RTA_ADDR_GET(NULL, RTA_IFA, rtm->rtm_addrs, pnt);
+ RTA_ADDR_GET(NULL, RTA_AUTHOR, rtm->rtm_addrs, pnt);
+ RTA_ADDR_GET(NULL, RTA_BRD, rtm->rtm_addrs, pnt);
+
+ /* If there is netmask information set it's family same as
+ destination family*/
+ if (rtm->rtm_addrs & RTA_NETMASK)
+ mask->sa.sa_family = dest->sa.sa_family;
+
+ /* Assert read up to the end of pointer. */
+ if (pnt != end)
+ zlog_warn("rtm_read() doesn't read all socket data.");
+
+ return rtm->rtm_flags;
}
-void
-rtm_read (struct rt_msghdr *rtm)
+void rtm_read(struct rt_msghdr *rtm)
{
- int flags;
- u_char zebra_flags;
- union sockunion dest, mask, gate;
- char ifname[INTERFACE_NAMSIZ + 1];
- short ifnlen = 0;
-
- zebra_flags = 0;
-
- /* Read destination and netmask and gateway from rtm message
- structure. */
- flags = rtm_read_mesg (rtm, &dest, &mask, &gate, ifname, &ifnlen);
- if (!(flags & RTF_DONE))
- return;
- if (IS_ZEBRA_DEBUG_KERNEL)
- zlog_debug ("%s: got rtm of type %d (%s)", __func__, rtm->rtm_type,
- lookup_msg(rtm_type_str, rtm->rtm_type, NULL));
-
-#ifdef RTF_CLONED /*bsdi, netbsd 1.6*/
- if (flags & RTF_CLONED)
- return;
+ int flags;
+ u_char zebra_flags;
+ union sockunion dest, mask, gate;
+ char ifname[INTERFACE_NAMSIZ + 1];
+ short ifnlen = 0;
+
+ zebra_flags = 0;
+
+ /* Read destination and netmask and gateway from rtm message
+ structure. */
+ flags = rtm_read_mesg(rtm, &dest, &mask, &gate, ifname, &ifnlen);
+ if (!(flags & RTF_DONE))
+ return;
+ if (IS_ZEBRA_DEBUG_KERNEL)
+ zlog_debug("%s: got rtm of type %d (%s)", __func__,
+ rtm->rtm_type,
+ lookup_msg(rtm_type_str, rtm->rtm_type, NULL));
+
+#ifdef RTF_CLONED /*bsdi, netbsd 1.6*/
+ if (flags & RTF_CLONED)
+ return;
#endif
-#ifdef RTF_WASCLONED /*freebsd*/
- if (flags & RTF_WASCLONED)
- return;
+#ifdef RTF_WASCLONED /*freebsd*/
+ if (flags & RTF_WASCLONED)
+ return;
#endif
- if ((rtm->rtm_type == RTM_ADD || rtm->rtm_type == RTM_CHANGE) && ! (flags & RTF_UP))
- return;
-
- /* This is connected route. */
- if (! (flags & RTF_GATEWAY))
- return;
-
- if (flags & RTF_PROTO1)
- SET_FLAG (zebra_flags, ZEBRA_FLAG_SELFROUTE);
-
- /* This is persistent route. */
- if (flags & RTF_STATIC)
- SET_FLAG (zebra_flags, ZEBRA_FLAG_STATIC);
-
- /* This is a reject or blackhole route */
- if (flags & RTF_REJECT)
- SET_FLAG (zebra_flags, ZEBRA_FLAG_REJECT);
- if (flags & RTF_BLACKHOLE)
- SET_FLAG (zebra_flags, ZEBRA_FLAG_BLACKHOLE);
-
- if (dest.sa.sa_family == AF_INET)
- {
- struct prefix p;
-
- p.family = AF_INET;
- p.u.prefix4 = dest.sin.sin_addr;
- if (flags & RTF_HOST)
- p.prefixlen = IPV4_MAX_PREFIXLEN;
- else
- p.prefixlen = ip_masklen (mask.sin.sin_addr);
-
- /* Catch self originated messages and match them against our current RIB.
- * At the same time, ignore unconfirmed messages, they should be tracked
- * by rtm_write() and kernel_rtm_ipv4().
- */
- if (rtm->rtm_type != RTM_GET && rtm->rtm_pid == pid)
- {
- char buf[PREFIX_STRLEN], gate_buf[INET_ADDRSTRLEN];
- int ret;
- if (! IS_ZEBRA_DEBUG_RIB)
- return;
- ret = rib_lookup_ipv4_route ((struct prefix_ipv4 *)&p, &gate, VRF_DEFAULT);
- prefix2str (&p, buf, sizeof(buf));
- switch (rtm->rtm_type)
- {
- case RTM_ADD:
- case RTM_GET:
- case RTM_CHANGE:
- /* The kernel notifies us about a new route in FIB created by us.
- Do we have a correspondent entry in our RIB? */
- switch (ret)
- {
- case ZEBRA_RIB_NOTFOUND:
- zlog_debug ("%s: %s %s: desync: RR isn't yet in RIB, while already in FIB",
- __func__, lookup_msg(rtm_type_str, rtm->rtm_type, NULL), buf);
- break;
- case ZEBRA_RIB_FOUND_CONNECTED:
- case ZEBRA_RIB_FOUND_NOGATE:
- inet_ntop (AF_INET, &gate.sin.sin_addr, gate_buf, INET_ADDRSTRLEN);
- zlog_debug ("%s: %s %s: desync: RR is in RIB, but gate differs (ours is %s)",
- __func__, lookup_msg(rtm_type_str, rtm->rtm_type, NULL), buf, gate_buf);
- break;
- case ZEBRA_RIB_FOUND_EXACT: /* RIB RR == FIB RR */
- zlog_debug ("%s: %s %s: done Ok",
- __func__, lookup_msg(rtm_type_str, rtm->rtm_type, NULL), buf);
- rib_lookup_and_dump ((struct prefix_ipv4 *)&p, VRF_DEFAULT);
- return;
- break;
- }
- break;
- case RTM_DELETE:
- /* The kernel notifies us about a route deleted by us. Do we still
- have it in the RIB? Do we have anything instead? */
- switch (ret)
- {
- case ZEBRA_RIB_FOUND_EXACT:
- zlog_debug ("%s: %s %s: desync: RR is still in RIB, while already not in FIB",
- __func__, lookup_msg(rtm_type_str, rtm->rtm_type, NULL), buf);
- rib_lookup_and_dump ((struct prefix_ipv4 *)&p, VRF_DEFAULT);
- break;
- case ZEBRA_RIB_FOUND_CONNECTED:
- case ZEBRA_RIB_FOUND_NOGATE:
- zlog_debug ("%s: %s %s: desync: RR is still in RIB, plus gate differs",
- __func__, lookup_msg(rtm_type_str, rtm->rtm_type, NULL), buf);
- rib_lookup_and_dump ((struct prefix_ipv4 *)&p, VRF_DEFAULT);
- break;
- case ZEBRA_RIB_NOTFOUND: /* RIB RR == FIB RR */
- zlog_debug ("%s: %s %s: done Ok",
- __func__, lookup_msg(rtm_type_str, rtm->rtm_type, NULL), buf);
- rib_lookup_and_dump ((struct prefix_ipv4 *)&p, VRF_DEFAULT);
- return;
- break;
- }
- break;
- default:
- zlog_debug ("%s: %s: warning: loopback RTM of type %s received",
- __func__, buf, lookup_msg(rtm_type_str, rtm->rtm_type, NULL));
- }
- return;
- }
-
- /* Change, delete the old prefix, we have no further information
- * to specify the route really
- */
- if (rtm->rtm_type == RTM_CHANGE)
- rib_delete (AFI_IP, SAFI_UNICAST, VRF_DEFAULT, ZEBRA_ROUTE_KERNEL,
- 0, zebra_flags, &p, NULL, NULL, 0, 0);
-
- union g_addr ggate = { .ipv4 = gate.sin.sin_addr };
- if (rtm->rtm_type == RTM_GET
- || rtm->rtm_type == RTM_ADD
- || rtm->rtm_type == RTM_CHANGE)
- rib_add (AFI_IP, SAFI_UNICAST, VRF_DEFAULT, ZEBRA_ROUTE_KERNEL, 0, zebra_flags,
- &p, NULL, &ggate, NULL, 0, 0, 0, 0, 0);
- else
- rib_delete (AFI_IP, SAFI_UNICAST, VRF_DEFAULT, ZEBRA_ROUTE_KERNEL,
- 0, zebra_flags, &p, NULL, &ggate, 0, 0);
- }
- if (dest.sa.sa_family == AF_INET6)
- {
- /* One day we might have a debug section here like one in the
- * IPv4 case above. Just ignore own messages at the moment.
- */
- if (rtm->rtm_type != RTM_GET && rtm->rtm_pid == pid)
- return;
- struct prefix p;
- ifindex_t ifindex = 0;
-
- p.family = AF_INET6;
- p.u.prefix6 = dest.sin6.sin6_addr;
- if (flags & RTF_HOST)
- p.prefixlen = IPV6_MAX_PREFIXLEN;
- else
- p.prefixlen = ip6_masklen (mask.sin6.sin6_addr);
+ if ((rtm->rtm_type == RTM_ADD || rtm->rtm_type == RTM_CHANGE)
+ && !(flags & RTF_UP))
+ return;
+
+ /* This is connected route. */
+ if (!(flags & RTF_GATEWAY))
+ return;
+
+ if (flags & RTF_PROTO1)
+ SET_FLAG(zebra_flags, ZEBRA_FLAG_SELFROUTE);
+
+ /* This is persistent route. */
+ if (flags & RTF_STATIC)
+ SET_FLAG(zebra_flags, ZEBRA_FLAG_STATIC);
+
+ /* This is a reject or blackhole route */
+ if (flags & RTF_REJECT)
+ SET_FLAG(zebra_flags, ZEBRA_FLAG_REJECT);
+ if (flags & RTF_BLACKHOLE)
+ SET_FLAG(zebra_flags, ZEBRA_FLAG_BLACKHOLE);
+
+ if (dest.sa.sa_family == AF_INET) {
+ struct prefix p;
+
+ p.family = AF_INET;
+ p.u.prefix4 = dest.sin.sin_addr;
+ if (flags & RTF_HOST)
+ p.prefixlen = IPV4_MAX_PREFIXLEN;
+ else
+ p.prefixlen = ip_masklen(mask.sin.sin_addr);
+
+ /* Catch self originated messages and match them against our
+ * current RIB.
+ * At the same time, ignore unconfirmed messages, they should be
+ * tracked
+ * by rtm_write() and kernel_rtm_ipv4().
+ */
+ if (rtm->rtm_type != RTM_GET && rtm->rtm_pid == pid) {
+ char buf[PREFIX_STRLEN], gate_buf[INET_ADDRSTRLEN];
+ int ret;
+ if (!IS_ZEBRA_DEBUG_RIB)
+ return;
+ ret = rib_lookup_ipv4_route((struct prefix_ipv4 *)&p,
+ &gate, VRF_DEFAULT);
+ prefix2str(&p, buf, sizeof(buf));
+ switch (rtm->rtm_type) {
+ case RTM_ADD:
+ case RTM_GET:
+ case RTM_CHANGE:
+ /* The kernel notifies us about a new route in
+ FIB created by us.
+ Do we have a correspondent entry in our RIB?
+ */
+ switch (ret) {
+ case ZEBRA_RIB_NOTFOUND:
+ zlog_debug(
+ "%s: %s %s: desync: RR isn't yet in RIB, while already in FIB",
+ __func__,
+ lookup_msg(rtm_type_str,
+ rtm->rtm_type, NULL),
+ buf);
+ break;
+ case ZEBRA_RIB_FOUND_CONNECTED:
+ case ZEBRA_RIB_FOUND_NOGATE:
+ inet_ntop(AF_INET, &gate.sin.sin_addr,
+ gate_buf, INET_ADDRSTRLEN);
+ zlog_debug(
+ "%s: %s %s: desync: RR is in RIB, but gate differs (ours is %s)",
+ __func__,
+ lookup_msg(rtm_type_str,
+ rtm->rtm_type, NULL),
+ buf, gate_buf);
+ break;
+ case ZEBRA_RIB_FOUND_EXACT: /* RIB RR == FIB RR
+ */
+ zlog_debug(
+ "%s: %s %s: done Ok", __func__,
+ lookup_msg(rtm_type_str,
+ rtm->rtm_type, NULL),
+ buf);
+ rib_lookup_and_dump(
+ (struct prefix_ipv4 *)&p,
+ VRF_DEFAULT);
+ return;
+ break;
+ }
+ break;
+ case RTM_DELETE:
+ /* The kernel notifies us about a route deleted
+ by us. Do we still
+ have it in the RIB? Do we have anything
+ instead? */
+ switch (ret) {
+ case ZEBRA_RIB_FOUND_EXACT:
+ zlog_debug(
+ "%s: %s %s: desync: RR is still in RIB, while already not in FIB",
+ __func__,
+ lookup_msg(rtm_type_str,
+ rtm->rtm_type, NULL),
+ buf);
+ rib_lookup_and_dump(
+ (struct prefix_ipv4 *)&p,
+ VRF_DEFAULT);
+ break;
+ case ZEBRA_RIB_FOUND_CONNECTED:
+ case ZEBRA_RIB_FOUND_NOGATE:
+ zlog_debug(
+ "%s: %s %s: desync: RR is still in RIB, plus gate differs",
+ __func__,
+ lookup_msg(rtm_type_str,
+ rtm->rtm_type, NULL),
+ buf);
+ rib_lookup_and_dump(
+ (struct prefix_ipv4 *)&p,
+ VRF_DEFAULT);
+ break;
+ case ZEBRA_RIB_NOTFOUND: /* RIB RR == FIB RR */
+ zlog_debug(
+ "%s: %s %s: done Ok", __func__,
+ lookup_msg(rtm_type_str,
+ rtm->rtm_type, NULL),
+ buf);
+ rib_lookup_and_dump(
+ (struct prefix_ipv4 *)&p,
+ VRF_DEFAULT);
+ return;
+ break;
+ }
+ break;
+ default:
+ zlog_debug(
+ "%s: %s: warning: loopback RTM of type %s received",
+ __func__, buf,
+ lookup_msg(rtm_type_str, rtm->rtm_type,
+ NULL));
+ }
+ return;
+ }
+
+ /* Change, delete the old prefix, we have no further information
+ * to specify the route really
+ */
+ if (rtm->rtm_type == RTM_CHANGE)
+ rib_delete(AFI_IP, SAFI_UNICAST, VRF_DEFAULT,
+ ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &p, NULL,
+ NULL, 0, 0);
+
+ union g_addr ggate = {.ipv4 = gate.sin.sin_addr};
+ if (rtm->rtm_type == RTM_GET || rtm->rtm_type == RTM_ADD
+ || rtm->rtm_type == RTM_CHANGE)
+ rib_add(AFI_IP, SAFI_UNICAST, VRF_DEFAULT,
+ ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &p, NULL,
+ &ggate, NULL, 0, 0, 0, 0, 0);
+ else
+ rib_delete(AFI_IP, SAFI_UNICAST, VRF_DEFAULT,
+ ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &p, NULL,
+ &ggate, 0, 0);
+ }
+ if (dest.sa.sa_family == AF_INET6) {
+ /* One day we might have a debug section here like one in the
+ * IPv4 case above. Just ignore own messages at the moment.
+ */
+ if (rtm->rtm_type != RTM_GET && rtm->rtm_pid == pid)
+ return;
+ struct prefix p;
+ ifindex_t ifindex = 0;
+
+ p.family = AF_INET6;
+ p.u.prefix6 = dest.sin6.sin6_addr;
+ if (flags & RTF_HOST)
+ p.prefixlen = IPV6_MAX_PREFIXLEN;
+ else
+ p.prefixlen = ip6_masklen(mask.sin6.sin6_addr);
#ifdef KAME
- if (IN6_IS_ADDR_LINKLOCAL (&gate.sin6.sin6_addr))
- {
- ifindex = IN6_LINKLOCAL_IFINDEX (gate.sin6.sin6_addr);
- SET_IN6_LINKLOCAL_IFINDEX (gate.sin6.sin6_addr, 0);
- }
+ if (IN6_IS_ADDR_LINKLOCAL(&gate.sin6.sin6_addr)) {
+ ifindex = IN6_LINKLOCAL_IFINDEX(gate.sin6.sin6_addr);
+ SET_IN6_LINKLOCAL_IFINDEX(gate.sin6.sin6_addr, 0);
+ }
#endif /* KAME */
- /* CHANGE: delete the old prefix, we have no further information
- * to specify the route really
- */
- if (rtm->rtm_type == RTM_CHANGE)
- rib_delete (AFI_IP6, SAFI_UNICAST, VRF_DEFAULT, ZEBRA_ROUTE_KERNEL,
- 0, zebra_flags, &p, NULL, NULL, 0, 0);
-
- union g_addr ggate = { .ipv6 = gate.sin6.sin6_addr };
- if (rtm->rtm_type == RTM_GET
- || rtm->rtm_type == RTM_ADD
- || rtm->rtm_type == RTM_CHANGE)
- rib_add (AFI_IP6, SAFI_UNICAST, VRF_DEFAULT, ZEBRA_ROUTE_KERNEL,
- 0, zebra_flags, &p, NULL, &ggate, NULL, ifindex,
- 0, 0, 0, 0);
- else
- rib_delete (AFI_IP6, SAFI_UNICAST, VRF_DEFAULT, ZEBRA_ROUTE_KERNEL,
- 0, zebra_flags, &p, NULL, &ggate, ifindex, 0);
- }
+ /* CHANGE: delete the old prefix, we have no further information
+ * to specify the route really
+ */
+ if (rtm->rtm_type == RTM_CHANGE)
+ rib_delete(AFI_IP6, SAFI_UNICAST, VRF_DEFAULT,
+ ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &p, NULL,
+ NULL, 0, 0);
+
+ union g_addr ggate = {.ipv6 = gate.sin6.sin6_addr};
+ if (rtm->rtm_type == RTM_GET || rtm->rtm_type == RTM_ADD
+ || rtm->rtm_type == RTM_CHANGE)
+ rib_add(AFI_IP6, SAFI_UNICAST, VRF_DEFAULT,
+ ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &p, NULL,
+ &ggate, NULL, ifindex, 0, 0, 0, 0);
+ else
+ rib_delete(AFI_IP6, SAFI_UNICAST, VRF_DEFAULT,
+ ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &p, NULL,
+ &ggate, ifindex, 0);
+ }
}
/* Interface function for the kernel routing table updates. Support
* for RTM_CHANGE will be needed.
* Exported only for rt_socket.c
*/
-int
-rtm_write (int message,
- union sockunion *dest,
- union sockunion *mask,
- union sockunion *gate,
- union sockunion *mpls,
- unsigned int index,
- int zebra_flags,
- int metric)
+int rtm_write(int message, union sockunion *dest, union sockunion *mask,
+ union sockunion *gate, union sockunion *mpls, unsigned int index,
+ int zebra_flags, int metric)
{
- int ret;
- caddr_t pnt;
- struct interface *ifp;
-
- /* Sequencial number of routing message. */
- static int msg_seq = 0;
-
- /* Struct of rt_msghdr and buffer for storing socket's data. */
- struct
- {
- struct rt_msghdr rtm;
- char buf[512];
- } msg;
-
- if (routing_sock < 0)
- return ZEBRA_ERR_EPERM;
-
- /* Clear and set rt_msghdr values */
- memset (&msg, 0, sizeof (struct rt_msghdr));
- msg.rtm.rtm_version = RTM_VERSION;
- msg.rtm.rtm_type = message;
- msg.rtm.rtm_seq = msg_seq++;
- msg.rtm.rtm_addrs = RTA_DST;
- msg.rtm.rtm_addrs |= RTA_GATEWAY;
- msg.rtm.rtm_flags = RTF_UP;
+ int ret;
+ caddr_t pnt;
+ struct interface *ifp;
+
+ /* Sequencial number of routing message. */
+ static int msg_seq = 0;
+
+ /* Struct of rt_msghdr and buffer for storing socket's data. */
+ struct {
+ struct rt_msghdr rtm;
+ char buf[512];
+ } msg;
+
+ if (routing_sock < 0)
+ return ZEBRA_ERR_EPERM;
+
+ /* Clear and set rt_msghdr values */
+ memset(&msg, 0, sizeof(struct rt_msghdr));
+ msg.rtm.rtm_version = RTM_VERSION;
+ msg.rtm.rtm_type = message;
+ msg.rtm.rtm_seq = msg_seq++;
+ msg.rtm.rtm_addrs = RTA_DST;
+ msg.rtm.rtm_addrs |= RTA_GATEWAY;
+ msg.rtm.rtm_flags = RTF_UP;
#ifdef __OpenBSD__
- msg.rtm.rtm_flags |= RTF_MPATH;
- msg.rtm.rtm_fmask = RTF_MPLS;
+ msg.rtm.rtm_flags |= RTF_MPATH;
+ msg.rtm.rtm_fmask = RTF_MPLS;
#endif
- msg.rtm.rtm_index = index;
+ msg.rtm.rtm_index = index;
- if (metric != 0)
- {
- msg.rtm.rtm_rmx.rmx_hopcount = metric;
- msg.rtm.rtm_inits |= RTV_HOPCOUNT;
- }
+ if (metric != 0) {
+ msg.rtm.rtm_rmx.rmx_hopcount = metric;
+ msg.rtm.rtm_inits |= RTV_HOPCOUNT;
+ }
- ifp = if_lookup_by_index (index, VRF_DEFAULT);
+ ifp = if_lookup_by_index(index, VRF_DEFAULT);
- if (gate && (message == RTM_ADD || message == RTM_CHANGE))
- msg.rtm.rtm_flags |= RTF_GATEWAY;
+ if (gate && (message == RTM_ADD || message == RTM_CHANGE))
+ msg.rtm.rtm_flags |= RTF_GATEWAY;
- /* When RTF_CLONING is unavailable on BSD, should we set some
- * other flag instead?
- */
+/* When RTF_CLONING is unavailable on BSD, should we set some
+ * other flag instead?
+ */
#ifdef RTF_CLONING
- if (! gate && (message == RTM_ADD || message == RTM_CHANGE) && ifp &&
- (ifp->flags & IFF_POINTOPOINT) == 0)
- msg.rtm.rtm_flags |= RTF_CLONING;
+ if (!gate && (message == RTM_ADD || message == RTM_CHANGE) && ifp
+ && (ifp->flags & IFF_POINTOPOINT) == 0)
+ msg.rtm.rtm_flags |= RTF_CLONING;
#endif /* RTF_CLONING */
- /* If no protocol specific gateway is specified, use link
- address for gateway. */
- if (! gate)
- {
- if (!ifp)
- {
- char dest_buf[INET_ADDRSTRLEN] = "NULL", mask_buf[INET_ADDRSTRLEN] = "255.255.255.255";
- if (dest)
- inet_ntop (AF_INET, &dest->sin.sin_addr, dest_buf, INET_ADDRSTRLEN);
- if (mask)
- inet_ntop (AF_INET, &mask->sin.sin_addr, mask_buf, INET_ADDRSTRLEN);
- zlog_warn ("%s: %s/%s: gate == NULL and no gateway found for ifindex %d",
- __func__, dest_buf, mask_buf, index);
- return -1;
- }
- gate = (union sockunion *) &((struct zebra_if *)ifp->info)->sdl;
- }
-
- if (mask)
- msg.rtm.rtm_addrs |= RTA_NETMASK;
- else if (message == RTM_ADD || message == RTM_CHANGE)
- msg.rtm.rtm_flags |= RTF_HOST;
+ /* If no protocol specific gateway is specified, use link
+ address for gateway. */
+ if (!gate) {
+ if (!ifp) {
+ char dest_buf[INET_ADDRSTRLEN] = "NULL",
+ mask_buf[INET_ADDRSTRLEN] = "255.255.255.255";
+ if (dest)
+ inet_ntop(AF_INET, &dest->sin.sin_addr,
+ dest_buf, INET_ADDRSTRLEN);
+ if (mask)
+ inet_ntop(AF_INET, &mask->sin.sin_addr,
+ mask_buf, INET_ADDRSTRLEN);
+ zlog_warn(
+ "%s: %s/%s: gate == NULL and no gateway found for ifindex %d",
+ __func__, dest_buf, mask_buf, index);
+ return -1;
+ }
+ gate = (union sockunion *)&((struct zebra_if *)ifp->info)->sdl;
+ }
+
+ if (mask)
+ msg.rtm.rtm_addrs |= RTA_NETMASK;
+ else if (message == RTM_ADD || message == RTM_CHANGE)
+ msg.rtm.rtm_flags |= RTF_HOST;
#ifdef __OpenBSD__
- if (mpls)
- {
- msg.rtm.rtm_addrs |= RTA_SRC;
- msg.rtm.rtm_flags |= RTF_MPLS;
-
- if (mpls->smpls.smpls_label != htonl (MPLS_IMP_NULL_LABEL << MPLS_LABEL_OFFSET))
- msg.rtm.rtm_mpls = MPLS_OP_PUSH;
- }
+ if (mpls) {
+ msg.rtm.rtm_addrs |= RTA_SRC;
+ msg.rtm.rtm_flags |= RTF_MPLS;
+
+ if (mpls->smpls.smpls_label
+ != htonl(MPLS_IMP_NULL_LABEL << MPLS_LABEL_OFFSET))
+ msg.rtm.rtm_mpls = MPLS_OP_PUSH;
+ }
#endif
- /* Tagging route with flags */
- msg.rtm.rtm_flags |= (RTF_PROTO1);
+ /* Tagging route with flags */
+ msg.rtm.rtm_flags |= (RTF_PROTO1);
- /* Additional flags. */
- if (zebra_flags & ZEBRA_FLAG_BLACKHOLE)
- msg.rtm.rtm_flags |= RTF_BLACKHOLE;
- if (zebra_flags & ZEBRA_FLAG_REJECT)
- msg.rtm.rtm_flags |= RTF_REJECT;
+ /* Additional flags. */
+ if (zebra_flags & ZEBRA_FLAG_BLACKHOLE)
+ msg.rtm.rtm_flags |= RTF_BLACKHOLE;
+ if (zebra_flags & ZEBRA_FLAG_REJECT)
+ msg.rtm.rtm_flags |= RTF_REJECT;
-#define SOCKADDRSET(X,R) \
- if (msg.rtm.rtm_addrs & (R)) \
- { \
- int len = SAROUNDUP (X); \
- memcpy (pnt, (caddr_t)(X), len); \
- pnt += len; \
- }
+#define SOCKADDRSET(X, R) \
+ if (msg.rtm.rtm_addrs & (R)) { \
+ int len = SAROUNDUP(X); \
+ memcpy(pnt, (caddr_t)(X), len); \
+ pnt += len; \
+ }
- pnt = (caddr_t) msg.buf;
+ pnt = (caddr_t)msg.buf;
- /* Write each socket data into rtm message buffer */
- SOCKADDRSET (dest, RTA_DST);
- SOCKADDRSET (gate, RTA_GATEWAY);
- SOCKADDRSET (mask, RTA_NETMASK);
+ /* Write each socket data into rtm message buffer */
+ SOCKADDRSET(dest, RTA_DST);
+ SOCKADDRSET(gate, RTA_GATEWAY);
+ SOCKADDRSET(mask, RTA_NETMASK);
#ifdef __OpenBSD__
- SOCKADDRSET (mpls, RTA_SRC);
+ SOCKADDRSET(mpls, RTA_SRC);
#endif
- msg.rtm.rtm_msglen = pnt - (caddr_t) &msg;
-
- ret = write (routing_sock, &msg, msg.rtm.rtm_msglen);
-
- if (ret != msg.rtm.rtm_msglen)
- {
- if (errno == EEXIST)
- return ZEBRA_ERR_RTEXIST;
- if (errno == ENETUNREACH)
- return ZEBRA_ERR_RTUNREACH;
- if (errno == ESRCH)
- return ZEBRA_ERR_RTNOEXIST;
-
- zlog_warn ("%s: write : %s (%d)", __func__, safe_strerror (errno), errno);
- return ZEBRA_ERR_KERNEL;
- }
- return ZEBRA_ERR_NOERROR;
+ msg.rtm.rtm_msglen = pnt - (caddr_t)&msg;
+
+ ret = write(routing_sock, &msg, msg.rtm.rtm_msglen);
+
+ if (ret != msg.rtm.rtm_msglen) {
+ if (errno == EEXIST)
+ return ZEBRA_ERR_RTEXIST;
+ if (errno == ENETUNREACH)
+ return ZEBRA_ERR_RTUNREACH;
+ if (errno == ESRCH)
+ return ZEBRA_ERR_RTNOEXIST;
+
+ zlog_warn("%s: write : %s (%d)", __func__, safe_strerror(errno),
+ errno);
+ return ZEBRA_ERR_KERNEL;
+ }
+ return ZEBRA_ERR_NOERROR;
}
@@ -1199,14 +1216,14 @@ rtm_write (int message,
#include "zebra/zserv.h"
/* For debug purpose. */
-static void
-rtmsg_debug (struct rt_msghdr *rtm)
+static void rtmsg_debug(struct rt_msghdr *rtm)
{
- zlog_debug ("Kernel: Len: %d Type: %s", rtm->rtm_msglen, lookup_msg(rtm_type_str, rtm->rtm_type, NULL));
- rtm_flag_dump (rtm->rtm_flags);
- zlog_debug ("Kernel: message seq %d", rtm->rtm_seq);
- zlog_debug ("Kernel: pid %lld, rtm_addrs 0x%x",
- (long long)rtm->rtm_pid, rtm->rtm_addrs);
+ zlog_debug("Kernel: Len: %d Type: %s", rtm->rtm_msglen,
+ lookup_msg(rtm_type_str, rtm->rtm_type, NULL));
+ rtm_flag_dump(rtm->rtm_flags);
+ zlog_debug("Kernel: message seq %d", rtm->rtm_seq);
+ zlog_debug("Kernel: pid %lld, rtm_addrs 0x%x", (long long)rtm->rtm_pid,
+ rtm->rtm_addrs);
}
/* This is pretty gross, better suggestions welcome -- mhandler */
@@ -1219,154 +1236,143 @@ rtmsg_debug (struct rt_msghdr *rtm)
#endif /* RTAX_MAX */
/* Kernel routing table and interface updates via routing socket. */
-static int
-kernel_read (struct thread *thread)
+static int kernel_read(struct thread *thread)
{
- int sock;
- int nbytes;
- struct rt_msghdr *rtm;
-
- /*
- * This must be big enough for any message the kernel might send.
- * Rather than determining how many sockaddrs of what size might be
- * in each particular message, just use RTAX_MAX of sockaddr_storage
- * for each. Note that the sockaddrs must be after each message
- * definition, or rather after whichever happens to be the largest,
- * since the buffer needs to be big enough for a message and the
- * sockaddrs together.
- */
- union
- {
- /* Routing information. */
- struct
- {
- struct rt_msghdr rtm;
- struct sockaddr_storage addr[RTAX_MAX];
- } r;
-
- /* Interface information. */
- struct
- {
- struct if_msghdr ifm;
- struct sockaddr_storage addr[RTAX_MAX];
- } im;
-
- /* Interface address information. */
- struct
- {
- struct ifa_msghdr ifa;
- struct sockaddr_storage addr[RTAX_MAX];
- } ia;
+ int sock;
+ int nbytes;
+ struct rt_msghdr *rtm;
+
+ /*
+ * This must be big enough for any message the kernel might send.
+ * Rather than determining how many sockaddrs of what size might be
+ * in each particular message, just use RTAX_MAX of sockaddr_storage
+ * for each. Note that the sockaddrs must be after each message
+ * definition, or rather after whichever happens to be the largest,
+ * since the buffer needs to be big enough for a message and the
+ * sockaddrs together.
+ */
+ union {
+ /* Routing information. */
+ struct {
+ struct rt_msghdr rtm;
+ struct sockaddr_storage addr[RTAX_MAX];
+ } r;
+
+ /* Interface information. */
+ struct {
+ struct if_msghdr ifm;
+ struct sockaddr_storage addr[RTAX_MAX];
+ } im;
+
+ /* Interface address information. */
+ struct {
+ struct ifa_msghdr ifa;
+ struct sockaddr_storage addr[RTAX_MAX];
+ } ia;
#ifdef RTM_IFANNOUNCE
- /* Interface arrival/departure */
- struct
- {
- struct if_announcemsghdr ifan;
- struct sockaddr_storage addr[RTAX_MAX];
- } ian;
+ /* Interface arrival/departure */
+ struct {
+ struct if_announcemsghdr ifan;
+ struct sockaddr_storage addr[RTAX_MAX];
+ } ian;
#endif /* RTM_IFANNOUNCE */
- } buf;
+ } buf;
- /* Fetch routing socket. */
- sock = THREAD_FD (thread);
+ /* Fetch routing socket. */
+ sock = THREAD_FD(thread);
- nbytes= read (sock, &buf, sizeof buf);
+ nbytes = read(sock, &buf, sizeof buf);
- if (nbytes <= 0)
- {
- if (nbytes < 0 && errno != EWOULDBLOCK && errno != EAGAIN)
- zlog_warn ("routing socket error: %s", safe_strerror (errno));
- return 0;
- }
+ if (nbytes <= 0) {
+ if (nbytes < 0 && errno != EWOULDBLOCK && errno != EAGAIN)
+ zlog_warn("routing socket error: %s",
+ safe_strerror(errno));
+ return 0;
+ }
- thread_add_read(zebrad.master, kernel_read, NULL, sock, NULL);
+ thread_add_read(zebrad.master, kernel_read, NULL, sock, NULL);
- if (IS_ZEBRA_DEBUG_KERNEL)
- rtmsg_debug (&buf.r.rtm);
+ if (IS_ZEBRA_DEBUG_KERNEL)
+ rtmsg_debug(&buf.r.rtm);
- rtm = &buf.r.rtm;
+ rtm = &buf.r.rtm;
- /*
- * Ensure that we didn't drop any data, so that processing routines
- * can assume they have the whole message.
- */
- if (rtm->rtm_msglen != nbytes)
- {
- zlog_warn ("kernel_read: rtm->rtm_msglen %d, nbytes %d, type %d\n",
- rtm->rtm_msglen, nbytes, rtm->rtm_type);
- return -1;
- }
-
- switch (rtm->rtm_type)
- {
- case RTM_ADD:
- case RTM_DELETE:
- case RTM_CHANGE:
- rtm_read (rtm);
- break;
- case RTM_IFINFO:
- ifm_read (&buf.im.ifm);
- break;
- case RTM_NEWADDR:
- case RTM_DELADDR:
- ifam_read (&buf.ia.ifa);
- break;
+ /*
+ * Ensure that we didn't drop any data, so that processing routines
+ * can assume they have the whole message.
+ */
+ if (rtm->rtm_msglen != nbytes) {
+ zlog_warn(
+ "kernel_read: rtm->rtm_msglen %d, nbytes %d, type %d\n",
+ rtm->rtm_msglen, nbytes, rtm->rtm_type);
+ return -1;
+ }
+
+ switch (rtm->rtm_type) {
+ case RTM_ADD:
+ case RTM_DELETE:
+ case RTM_CHANGE:
+ rtm_read(rtm);
+ break;
+ case RTM_IFINFO:
+ ifm_read(&buf.im.ifm);
+ break;
+ case RTM_NEWADDR:
+ case RTM_DELADDR:
+ ifam_read(&buf.ia.ifa);
+ break;
#ifdef RTM_IFANNOUNCE
- case RTM_IFANNOUNCE:
- ifan_read (&buf.ian.ifan);
- break;
+ case RTM_IFANNOUNCE:
+ ifan_read(&buf.ian.ifan);
+ break;
#endif /* RTM_IFANNOUNCE */
- default:
- if (IS_ZEBRA_DEBUG_KERNEL)
- zlog_debug("Unprocessed RTM_type: %d", rtm->rtm_type);
- break;
- }
- return 0;
+ default:
+ if (IS_ZEBRA_DEBUG_KERNEL)
+ zlog_debug("Unprocessed RTM_type: %d", rtm->rtm_type);
+ break;
+ }
+ return 0;
}
/* Make routing socket. */
-static void
-routing_socket (struct zebra_ns *zns)
+static void routing_socket(struct zebra_ns *zns)
{
- if ( zserv_privs.change (ZPRIVS_RAISE) )
- zlog_err ("routing_socket: Can't raise privileges");
-
- routing_sock = socket (AF_ROUTE, SOCK_RAW, 0);
-
- if (routing_sock < 0)
- {
- if ( zserv_privs.change (ZPRIVS_LOWER) )
- zlog_err ("routing_socket: Can't lower privileges");
- zlog_warn ("Can't init kernel routing socket");
- return;
- }
-
- /* XXX: Socket should be NONBLOCK, however as we currently
- * discard failed writes, this will lead to inconsistencies.
- * For now, socket must be blocking.
- */
- /*if (fcntl (routing_sock, F_SETFL, O_NONBLOCK) < 0)
- zlog_warn ("Can't set O_NONBLOCK to routing socket");*/
-
- if ( zserv_privs.change (ZPRIVS_LOWER) )
- zlog_err ("routing_socket: Can't lower privileges");
-
- /* kernel_read needs rewrite. */
- thread_add_read(zebrad.master, kernel_read, NULL, routing_sock, NULL);
+ if (zserv_privs.change(ZPRIVS_RAISE))
+ zlog_err("routing_socket: Can't raise privileges");
+
+ routing_sock = socket(AF_ROUTE, SOCK_RAW, 0);
+
+ if (routing_sock < 0) {
+ if (zserv_privs.change(ZPRIVS_LOWER))
+ zlog_err("routing_socket: Can't lower privileges");
+ zlog_warn("Can't init kernel routing socket");
+ return;
+ }
+
+ /* XXX: Socket should be NONBLOCK, however as we currently
+ * discard failed writes, this will lead to inconsistencies.
+ * For now, socket must be blocking.
+ */
+ /*if (fcntl (routing_sock, F_SETFL, O_NONBLOCK) < 0)
+ zlog_warn ("Can't set O_NONBLOCK to routing socket");*/
+
+ if (zserv_privs.change(ZPRIVS_LOWER))
+ zlog_err("routing_socket: Can't lower privileges");
+
+ /* kernel_read needs rewrite. */
+ thread_add_read(zebrad.master, kernel_read, NULL, routing_sock, NULL);
}
/* Exported interface function. This function simply calls
routing_socket (). */
-void
-kernel_init (struct zebra_ns *zns)
+void kernel_init(struct zebra_ns *zns)
{
- routing_socket (zns);
+ routing_socket(zns);
}
-void
-kernel_terminate (struct zebra_ns *zns)
+void kernel_terminate(struct zebra_ns *zns)
{
- return;
+ return;
}