diff options
Diffstat (limited to 'zebra/kernel_socket.c')
-rw-r--r-- | zebra/kernel_socket.c | 54 |
1 files changed, 45 insertions, 9 deletions
diff --git a/zebra/kernel_socket.c b/zebra/kernel_socket.c index feeaf5d0..d0908115 100644 --- a/zebra/kernel_socket.c +++ b/zebra/kernel_socket.c @@ -253,6 +253,25 @@ rtm_flag_dump (int flag) zlog_debug ("Kernel: %s", buf); } +/* NetBSD IPSRCSEL preference readback */ +static int +if_get_addrpref (const char *ifname, struct sockaddr_in *addr) +{ +#ifdef SIOCSIFADDRPREF + int ret; + struct if_addrprefreq ifapr; + + memset (&ifapr, 0, sizeof ifapr); + strncpy ((char *)&ifapr.ifap_name, ifname, sizeof ifapr.ifap_name); + memcpy (&ifapr.ifap_addr, addr, sizeof (struct sockaddr_in)); + + ret = if_ioctl (SIOCGIFADDRPREF, (caddr_t) &ifapr); + if (ret == 0) + return ifapr.ifap_preference; +#endif + return 0; +} + #ifdef RTM_IFANNOUNCE /* Interface adding function */ static int @@ -319,6 +338,7 @@ int ifm_read (struct if_msghdr *ifm) { struct interface *ifp = NULL; + struct sockaddr_dl *sdl; char ifname[IFNAMSIZ]; short ifnlen = 0; caddr_t *cp; @@ -356,6 +376,7 @@ ifm_read (struct if_msghdr *ifm) 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); @@ -454,6 +475,16 @@ ifm_read (struct if_msghdr *ifm) #endif /* __bsdi__ */ if_get_metric (ifp); + /* + * XXX sockaddr_dl contents can be larger than the structure + * definition, so the user of the stored structure must be + * careful not to read off the end. + * + * a nonzero ifnlen from RTA_NAME_GET() means sdl is valid + */ + if (ifnlen) + memcpy (&ifp->sdl, sdl, sizeof (struct sockaddr_dl)); + if_add_update (ifp); } else @@ -619,6 +650,7 @@ ifam_read (struct ifa_msghdr *ifam) short ifnlen = 0; char isalias = 0; int flags = 0; + int preference = 0; ifname[0] = ifname[INTERFACE_NAMSIZ - 1] = '\0'; @@ -649,6 +681,9 @@ ifam_read (struct ifa_msghdr *ifam) */ ifp->metric = ifam->ifam_metric; #endif + if (sockunion_family (&addr) == AF_INET + && ifam->ifam_type == RTM_NEWADDR) + preference = if_get_addrpref (ifp->name, &addr.sin); /* Add connected address. */ switch (sockunion_family (&addr)) @@ -658,7 +693,7 @@ ifam_read (struct ifa_msghdr *ifam) connected_add_ipv4 (ifp, flags, &addr.sin.sin_addr, ip_masklen (mask.sin.sin_addr), &brd.sin.sin_addr, - (isalias ? ifname : NULL)); + (isalias ? ifname : NULL), 0, preference); else connected_delete_ipv4 (ifp, flags, &addr.sin.sin_addr, ip_masklen (mask.sin.sin_addr), @@ -675,7 +710,7 @@ ifam_read (struct ifa_msghdr *ifam) connected_add_ipv6 (ifp, flags, &addr.sin6.sin6_addr, ip6_masklen (mask.sin6.sin6_addr), &brd.sin6.sin6_addr, - (isalias ? ifname : NULL)); + (isalias ? ifname : NULL), 0); else connected_delete_ipv6 (ifp, &addr.sin6.sin6_addr, @@ -804,9 +839,9 @@ rtm_read (struct rt_msghdr *rtm) /* This is a reject or blackhole route */ if (flags & RTF_REJECT) - SET_FLAG (zebra_flags, ZEBRA_FLAG_REJECT); + SET_FLAG (zebra_flags, RIB_ZF_REJECT << 8); if (flags & RTF_BLACKHOLE) - SET_FLAG (zebra_flags, ZEBRA_FLAG_BLACKHOLE); + SET_FLAG (zebra_flags, RIB_ZF_BLACKHOLE << 8); if (dest.sa.sa_family == AF_INET) { @@ -1037,11 +1072,12 @@ rtm_write (int message, 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; - + if (RIB_ZF_BLACKHOLE_FLAGS (zebra_flags >> 8)) + { + unsigned bh_type = RIB_ZF_BLACKHOLE_FLAGS(zebra_flags >> 8); + msg.rtm.rtm_flags |= (bh_type == RIB_ZF_REJECT) + ? RTF_REJECT : RTF_BLACKHOLE; + } #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN #define SOCKADDRSET(X,R) \ |