diff options
Diffstat (limited to 'zebra/kernel_socket.c')
| -rw-r--r-- | zebra/kernel_socket.c | 2050 | 
1 files changed, 1028 insertions, 1022 deletions
diff --git a/zebra/kernel_socket.c b/zebra/kernel_socket.c index 70effade27..efe33c8389 100644 --- a/zebra/kernel_socket.c +++ b/zebra/kernel_socket.c @@ -16,7 +16,7 @@   * You should have received a copy of the GNU General Public License   * along with GNU Zebra; see the file COPYING.  If not, write to the Free   * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA.   + * 02111-1307, USA.   */  #include <zebra.h> @@ -91,7 +91,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__ @@ -100,8 +101,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) */ @@ -116,13 +118,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 */ @@ -134,152 +137,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; @@ -288,115 +279,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; +	}  }  /* @@ -404,342 +397,339 @@ 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 */ -  ifp->speed = ifm->ifm_data.ifi_baudrate / 1000000; +	ifp->speed = ifm->ifm_data.ifi_baudrate / 1000000; -  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 @@ -750,450 +740,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;  } @@ -1201,14 +1218,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 */ @@ -1221,154 +1238,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); +	thread_add_read(zebrad.master, kernel_read, NULL, sock); -  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); +	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);  }  /* 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;  }  | 
