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.c54
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) \