summaryrefslogtreecommitdiffstats
path: root/sys/net
diff options
context:
space:
mode:
Diffstat (limited to 'sys/net')
-rw-r--r--sys/net/ieee8023ad_lacp.c14
-rw-r--r--sys/net/radix.c10
-rw-r--r--sys/net/route.c42
-rw-r--r--sys/net/route.h4
-rw-r--r--sys/net/rtsock.c117
5 files changed, 106 insertions, 81 deletions
diff --git a/sys/net/ieee8023ad_lacp.c b/sys/net/ieee8023ad_lacp.c
index b023c6c..aa38efa 100644
--- a/sys/net/ieee8023ad_lacp.c
+++ b/sys/net/ieee8023ad_lacp.c
@@ -590,10 +590,20 @@ lacp_req(struct lagg_softc *sc, caddr_t data)
{
struct lacp_opreq *req = (struct lacp_opreq *)data;
struct lacp_softc *lsc = LACP_SOFTC(sc);
- struct lacp_aggregator *la = lsc->lsc_active_aggregator;
+ struct lacp_aggregator *la;
- LACP_LOCK(lsc);
bzero(req, sizeof(struct lacp_opreq));
+
+ /*
+ * If the LACP softc is NULL, return with the opreq structure full of
+ * zeros. It is normal for the softc to be NULL while the lagg is
+ * being destroyed.
+ */
+ if (NULL == lsc)
+ return;
+
+ la = lsc->lsc_active_aggregator;
+ LACP_LOCK(lsc);
if (la != NULL) {
req->actor_prio = ntohs(la->la_actor.lip_systemid.lsi_prio);
memcpy(&req->actor_mac, &la->la_actor.lip_systemid.lsi_mac,
diff --git a/sys/net/radix.c b/sys/net/radix.c
index 2f52c3a..62f57f8 100644
--- a/sys/net/radix.c
+++ b/sys/net/radix.c
@@ -971,6 +971,8 @@ rn_walktree_from(struct radix_node_head *h, void *a, void *m,
int stopping = 0;
int lastb;
+ KASSERT(m != NULL, ("%s: mask needs to be specified", __func__));
+
/*
* rn_search_m is sort-of-open-coded here. We cannot use the
* function because we need to keep track of the last node seen.
@@ -994,11 +996,11 @@ rn_walktree_from(struct radix_node_head *h, void *a, void *m,
/*
* Two cases: either we stepped off the end of our mask,
* in which case last == rn, or we reached a leaf, in which
- * case we want to start from the last node we looked at.
- * Either way, last is the node we want to start from.
+ * case we want to start from the leaf.
*/
- rn = last;
- lastb = rn->rn_bit;
+ if (rn->rn_bit >= 0)
+ rn = last;
+ lastb = last->rn_bit;
/* printf("rn %p, lastb %d\n", rn, lastb);*/
diff --git a/sys/net/route.c b/sys/net/route.c
index 0feadb8..d6e6d93 100644
--- a/sys/net/route.c
+++ b/sys/net/route.c
@@ -142,6 +142,7 @@ static VNET_DEFINE(uma_zone_t, rtzone); /* Routing table UMA zone. */
static int rtrequest1_fib_change(struct radix_node_head *, struct rt_addrinfo *,
struct rtentry **, u_int);
+static void rt_setmetrics(const struct rt_addrinfo *, struct rtentry *);
/*
* handler for net.my_fibnum
@@ -401,15 +402,6 @@ rtalloc1_fib(struct sockaddr *dst, int report, u_long ignflags,
int needlock;
KASSERT((fibnum < rt_numfibs), ("rtalloc1_fib: bad fibnum"));
- switch (dst->sa_family) {
- case AF_INET6:
- case AF_INET:
- /* We support multiple FIBs. */
- break;
- default:
- fibnum = RT_DEFAULT_FIB;
- break;
- }
rnh = rt_tables_get_rnh(fibnum, dst->sa_family);
newrt = NULL;
if (rnh == NULL)
@@ -897,7 +889,7 @@ rt_getifa_fib(struct rt_addrinfo *info, u_int fibnum)
* The route must be locked.
*/
int
-rtexpunge(struct rtentry *rt)
+rt_expunge(struct radix_node_head *rnh, struct rtentry *rt)
{
#if !defined(RADIX_MPATH)
struct radix_node *rn;
@@ -906,17 +898,10 @@ rtexpunge(struct rtentry *rt)
int fib;
struct rtentry *rt0;
#endif
- struct radix_node_head *rnh;
struct ifaddr *ifa;
int error = 0;
- /*
- * Find the correct routing tree to use for this Address Family
- */
- rnh = rt_tables_get_rnh(rt->rt_fibnum, rt_key(rt)->sa_family);
RT_LOCK_ASSERT(rt);
- if (rnh == NULL)
- return (EAFNOSUPPORT);
RADIX_NODE_HEAD_LOCK_ASSERT(rnh);
#ifdef RADIX_MPATH
@@ -1401,6 +1386,8 @@ rtrequest1_fib(int req, struct rt_addrinfo *info, struct rtentry **ret_nrt,
if (ifa->ifa_rtrequest)
ifa->ifa_rtrequest(req, rt, info);
+ rt_setmetrics(info, rt);
+
/*
* actually return a resultant rtentry and
* give the caller a single reference.
@@ -1431,7 +1418,6 @@ bad:
#undef ifpaddr
#undef flags
-#define senderr(e) { error = e; goto bad; }
static int
rtrequest1_fib_change(struct radix_node_head *rnh, struct rt_addrinfo *info,
struct rtentry **ret_nrt, u_int fibnum)
@@ -1476,7 +1462,7 @@ rtrequest1_fib_change(struct radix_node_head *rnh, struct rt_addrinfo *info,
free_ifa = 1;
if (error != 0)
- senderr(error);
+ goto bad;
}
/* Check if outgoing interface has changed */
@@ -1489,7 +1475,7 @@ rtrequest1_fib_change(struct radix_node_head *rnh, struct rt_addrinfo *info,
if (info->rti_info[RTAX_GATEWAY] != NULL) {
error = rt_setgate(rt, rt_key(rt), info->rti_info[RTAX_GATEWAY]);
if (error != 0)
- senderr(error);
+ goto bad;
rt->rt_flags &= ~RTF_GATEWAY;
rt->rt_flags |= (RTF_GATEWAY & info->rti_flags);
@@ -1507,6 +1493,8 @@ rtrequest1_fib_change(struct radix_node_head *rnh, struct rt_addrinfo *info,
if (rt->rt_ifa && rt->rt_ifa->ifa_rtrequest != NULL)
rt->rt_ifa->ifa_rtrequest(RTM_ADD, rt, info);
+ rt_setmetrics(info, rt);
+
if (ret_nrt) {
*ret_nrt = rt;
RT_ADDREF(rt);
@@ -1517,8 +1505,20 @@ bad:
ifa_free(info->rti_ifa);
return (error);
}
-#undef senderr
+static void
+rt_setmetrics(const struct rt_addrinfo *info, struct rtentry *rt)
+{
+
+ if (info->rti_mflags & RTV_MTU)
+ rt->rt_mtu = info->rti_rmx->rmx_mtu;
+ if (info->rti_mflags & RTV_WEIGHT)
+ rt->rt_weight = info->rti_rmx->rmx_weight;
+ /* Kernel -> userland timebase conversion. */
+ if (info->rti_mflags & RTV_EXPIRE)
+ rt->rt_expire = info->rti_rmx->rmx_expire ?
+ info->rti_rmx->rmx_expire - time_second + time_uptime : 0;
+}
int
rt_setgate(struct rtentry *rt, struct sockaddr *dst, struct sockaddr *gate)
diff --git a/sys/net/route.h b/sys/net/route.h
index 913828a..df2fc58 100644
--- a/sys/net/route.h
+++ b/sys/net/route.h
@@ -261,6 +261,8 @@ struct rt_addrinfo {
int rti_flags;
struct ifaddr *rti_ifa;
struct ifnet *rti_ifp;
+ u_long rti_mflags;
+ struct rt_metrics *rti_rmx;
};
/*
@@ -369,7 +371,7 @@ int rtsock_routemsg(int, struct ifnet *ifp, int, struct rtentry *, int);
* RTFREE() uses an unlocked entry.
*/
-int rtexpunge(struct rtentry *);
+int rt_expunge(struct radix_node_head *, struct rtentry *);
void rtfree(struct rtentry *);
int rt_check(struct rtentry **, struct rtentry **, struct sockaddr *);
diff --git a/sys/net/rtsock.c b/sys/net/rtsock.c
index a40f067..3a6afca 100644
--- a/sys/net/rtsock.c
+++ b/sys/net/rtsock.c
@@ -151,7 +151,7 @@ struct walkarg {
};
static void rts_input(struct mbuf *m);
-static struct mbuf *rt_msg1(int type, struct rt_addrinfo *rtinfo);
+static struct mbuf *rtsock_msg_mbuf(int type, struct rt_addrinfo *rtinfo);
static int rtsock_msg_buffer(int type, struct rt_addrinfo *rtinfo,
struct walkarg *w, int *plen);
static int rt_xaddrs(caddr_t cp, caddr_t cplim,
@@ -160,9 +160,10 @@ static int sysctl_dumpentry(struct radix_node *rn, void *vw);
static int sysctl_iflist(int af, struct walkarg *w);
static int sysctl_ifmalist(int af, struct walkarg *w);
static int route_output(struct mbuf *m, struct socket *so);
-static void rt_setmetrics(const struct rt_msghdr *rtm, struct rtentry *rt);
static void rt_getmetrics(const struct rtentry *rt, struct rt_metrics *out);
static void rt_dispatch(struct mbuf *, sa_family_t);
+static struct sockaddr *rtsock_fix_netmask(struct sockaddr *dst,
+ struct sockaddr *smask, struct sockaddr_storage *dmask);
static struct netisr_handler rtsock_nh = {
.nh_name = "rtsock",
@@ -521,8 +522,8 @@ route_output(struct mbuf *m, struct socket *so)
struct rtentry *rt = NULL;
struct radix_node_head *rnh;
struct rt_addrinfo info;
-#ifdef INET6
struct sockaddr_storage ss;
+#ifdef INET6
struct sockaddr_in6 *sin6;
int i, rti_need_deembed = 0;
#endif
@@ -532,7 +533,6 @@ route_output(struct mbuf *m, struct socket *so)
sa_family_t saf = AF_UNSPEC;
struct rawcb *rp = NULL;
struct walkarg w;
- char msgbuf[512];
fibnum = so->so_fibnum;
@@ -549,20 +549,12 @@ route_output(struct mbuf *m, struct socket *so)
/*
* Most of current messages are in range 200-240 bytes,
- * minimize possible failures by using on-stack buffer
- * which should fit for most messages.
- * However, use stable memory if we need to handle
- * something large.
+ * minimize possible re-allocation on reply using larger size
+ * buffer aligned on 1k boundaty.
*/
- if (len < sizeof(msgbuf)) {
- alloc_len = sizeof(msgbuf);
- rtm = (struct rt_msghdr *)msgbuf;
- } else {
- alloc_len = roundup2(len, 1024);
- rtm = malloc(alloc_len, M_TEMP, M_NOWAIT);
- if (rtm == NULL)
- senderr(ENOBUFS);
- }
+ alloc_len = roundup2(len, 1024);
+ if ((rtm = malloc(alloc_len, M_TEMP, M_NOWAIT)) == NULL)
+ senderr(ENOBUFS);
m_copydata(m, 0, len, (caddr_t)rtm);
bzero(&info, sizeof(info));
@@ -570,8 +562,7 @@ route_output(struct mbuf *m, struct socket *so)
if (rtm->rtm_version != RTM_VERSION) {
/* Do not touch message since format is unknown */
- if ((char *)rtm != msgbuf)
- free(rtm, M_TEMP);
+ free(rtm, M_TEMP);
rtm = NULL;
senderr(EPROTONOSUPPORT);
}
@@ -584,6 +575,10 @@ route_output(struct mbuf *m, struct socket *so)
rtm->rtm_pid = curproc->p_pid;
info.rti_addrs = rtm->rtm_addrs;
+
+ info.rti_mflags = rtm->rtm_inits;
+ info.rti_rmx = &rtm->rtm_rmx;
+
/*
* rt_xaddrs() performs s6_addr[2] := sin6_scope_id for AF_INET6
* link-local address because rtrequest requires addresses with
@@ -670,7 +665,6 @@ route_output(struct mbuf *m, struct socket *so)
rti_need_deembed = (V_deembed_scopeid) ? 1 : 0;
#endif
RT_LOCK(saved_nrt);
- rt_setmetrics(rtm, saved_nrt);
rtm->rtm_index = saved_nrt->rt_ifp->if_index;
RT_REMREF(saved_nrt);
RT_UNLOCK(saved_nrt);
@@ -792,7 +786,8 @@ report:
}
info.rti_info[RTAX_DST] = rt_key(rt);
info.rti_info[RTAX_GATEWAY] = rt->rt_gateway;
- info.rti_info[RTAX_NETMASK] = rt_mask(rt);
+ info.rti_info[RTAX_NETMASK] = rtsock_fix_netmask(rt_key(rt),
+ rt_mask(rt), &ss);
info.rti_info[RTAX_GENMASK] = 0;
if (rtm->rtm_addrs & (RTA_IFP | RTA_IFA)) {
ifp = rt->rt_ifp;
@@ -859,7 +854,7 @@ flush:
*/
if ((so->so_options & SO_USELOOPBACK) == 0) {
if (V_route_cb.any_count <= 1) {
- if (rtm != NULL && (char *)rtm != msgbuf)
+ if (rtm != NULL)
free(rtm, M_TEMP);
m_freem(m);
return (error);
@@ -897,8 +892,7 @@ flush:
} else if (m->m_pkthdr.len > rtm->rtm_msglen)
m_adj(m, rtm->rtm_msglen - m->m_pkthdr.len);
- if ((char *)rtm != msgbuf)
- free(rtm, M_TEMP);
+ free(rtm, M_TEMP);
}
if (m != NULL) {
M_SETFIB(m, fibnum);
@@ -920,20 +914,6 @@ flush:
}
static void
-rt_setmetrics(const struct rt_msghdr *rtm, struct rtentry *rt)
-{
-
- if (rtm->rtm_inits & RTV_MTU)
- rt->rt_mtu = rtm->rtm_rmx.rmx_mtu;
- if (rtm->rtm_inits & RTV_WEIGHT)
- rt->rt_weight = rtm->rtm_rmx.rmx_weight;
- /* Kernel -> userland timebase conversion. */
- if (rtm->rtm_inits & RTV_EXPIRE)
- rt->rt_expire = rtm->rtm_rmx.rmx_expire ?
- rtm->rtm_rmx.rmx_expire - time_second + time_uptime : 0;
-}
-
-static void
rt_getmetrics(const struct rtentry *rt, struct rt_metrics *out)
{
@@ -990,10 +970,33 @@ rt_xaddrs(caddr_t cp, caddr_t cplim, struct rt_addrinfo *rtinfo)
}
/*
- * Used by the routing socket.
+ * Fill in @dmask with valid netmask leaving original @smask
+ * intact. Mostly used with radix netmasks.
+ */
+static struct sockaddr *
+rtsock_fix_netmask(struct sockaddr *dst, struct sockaddr *smask,
+ struct sockaddr_storage *dmask)
+{
+ if (dst == NULL || smask == NULL)
+ return (NULL);
+
+ memset(dmask, 0, dst->sa_len);
+ memcpy(dmask, smask, smask->sa_len);
+ dmask->ss_len = dst->sa_len;
+ dmask->ss_family = dst->sa_family;
+
+ return ((struct sockaddr *)dmask);
+}
+
+/*
+ * Writes information related to @rtinfo object to newly-allocated mbuf.
+ * Assumes MCLBYTES is enough to construct any message.
+ * Used for OS notifications of vaious events (if/ifa announces,etc)
+ *
+ * Returns allocated mbuf or NULL on failure.
*/
static struct mbuf *
-rt_msg1(int type, struct rt_addrinfo *rtinfo)
+rtsock_msg_mbuf(int type, struct rt_addrinfo *rtinfo)
{
struct rt_msghdr *rtm;
struct mbuf *m;
@@ -1205,7 +1208,7 @@ rt_missmsg_fib(int type, struct rt_addrinfo *rtinfo, int flags, int error,
if (V_route_cb.any_count == 0)
return;
- m = rt_msg1(type, rtinfo);
+ m = rtsock_msg_mbuf(type, rtinfo);
if (m == NULL)
return;
@@ -1244,7 +1247,7 @@ rt_ifmsg(struct ifnet *ifp)
if (V_route_cb.any_count == 0)
return;
bzero((caddr_t)&info, sizeof(info));
- m = rt_msg1(RTM_IFINFO, &info);
+ m = rtsock_msg_mbuf(RTM_IFINFO, &info);
if (m == NULL)
return;
ifm = mtod(m, struct if_msghdr *);
@@ -1270,6 +1273,7 @@ rtsock_addrmsg(int cmd, struct ifaddr *ifa, int fibnum)
struct mbuf *m;
struct ifa_msghdr *ifam;
struct ifnet *ifp = ifa->ifa_ifp;
+ struct sockaddr_storage ss;
if (V_route_cb.any_count == 0)
return (0);
@@ -1279,9 +1283,10 @@ rtsock_addrmsg(int cmd, struct ifaddr *ifa, int fibnum)
bzero((caddr_t)&info, sizeof(info));
info.rti_info[RTAX_IFA] = sa = ifa->ifa_addr;
info.rti_info[RTAX_IFP] = ifp->if_addr->ifa_addr;
- info.rti_info[RTAX_NETMASK] = ifa->ifa_netmask;
+ info.rti_info[RTAX_NETMASK] = rtsock_fix_netmask(
+ info.rti_info[RTAX_IFP], ifa->ifa_netmask, &ss);
info.rti_info[RTAX_BRD] = ifa->ifa_dstaddr;
- if ((m = rt_msg1(ncmd, &info)) == NULL)
+ if ((m = rtsock_msg_mbuf(ncmd, &info)) == NULL)
return (ENOBUFS);
ifam = mtod(m, struct ifa_msghdr *);
ifam->ifam_index = ifp->if_index;
@@ -1318,15 +1323,16 @@ rtsock_routemsg(int cmd, struct ifnet *ifp, int error, struct rtentry *rt,
struct sockaddr *sa;
struct mbuf *m;
struct rt_msghdr *rtm;
+ struct sockaddr_storage ss;
if (V_route_cb.any_count == 0)
return (0);
bzero((caddr_t)&info, sizeof(info));
- info.rti_info[RTAX_NETMASK] = rt_mask(rt);
info.rti_info[RTAX_DST] = sa = rt_key(rt);
+ info.rti_info[RTAX_NETMASK] = rtsock_fix_netmask(sa, rt_mask(rt), &ss);
info.rti_info[RTAX_GATEWAY] = rt->rt_gateway;
- if ((m = rt_msg1(cmd, &info)) == NULL)
+ if ((m = rtsock_msg_mbuf(cmd, &info)) == NULL)
return (ENOBUFS);
rtm = mtod(m, struct rt_msghdr *);
rtm->rtm_index = ifp->if_index;
@@ -1368,7 +1374,7 @@ rt_newmaddrmsg(int cmd, struct ifmultiaddr *ifma)
* (similarly to how ARP entries, e.g., are presented).
*/
info.rti_info[RTAX_GATEWAY] = ifma->ifma_lladdr;
- m = rt_msg1(cmd, &info);
+ m = rtsock_msg_mbuf(cmd, &info);
if (m == NULL)
return;
ifmam = mtod(m, struct ifma_msghdr *);
@@ -1389,7 +1395,7 @@ rt_makeifannouncemsg(struct ifnet *ifp, int type, int what,
if (V_route_cb.any_count == 0)
return NULL;
bzero((caddr_t)info, sizeof(*info));
- m = rt_msg1(type, info);
+ m = rtsock_msg_mbuf(type, info);
if (m != NULL) {
ifan = mtod(m, struct if_announcemsghdr *);
ifan->ifan_index = ifp->if_index;
@@ -1496,6 +1502,7 @@ sysctl_dumpentry(struct radix_node *rn, void *vw)
struct rtentry *rt = (struct rtentry *)rn;
int error = 0, size;
struct rt_addrinfo info;
+ struct sockaddr_storage ss;
if (w->w_op == NET_RT_FLAGS && !(rt->rt_flags & w->w_arg))
return 0;
@@ -1506,7 +1513,8 @@ sysctl_dumpentry(struct radix_node *rn, void *vw)
bzero((caddr_t)&info, sizeof(info));
info.rti_info[RTAX_DST] = rt_key(rt);
info.rti_info[RTAX_GATEWAY] = rt->rt_gateway;
- info.rti_info[RTAX_NETMASK] = rt_mask(rt);
+ info.rti_info[RTAX_NETMASK] = rtsock_fix_netmask(rt_key(rt),
+ rt_mask(rt), &ss);
info.rti_info[RTAX_GENMASK] = 0;
if (rt->rt_ifp) {
info.rti_info[RTAX_IFP] = rt->rt_ifp->if_addr->ifa_addr;
@@ -1682,6 +1690,7 @@ sysctl_iflist(int af, struct walkarg *w)
struct ifaddr *ifa;
struct rt_addrinfo info;
int len, error = 0;
+ struct sockaddr_storage ss;
bzero((caddr_t)&info, sizeof(info));
IFNET_RLOCK_NOSLEEP();
@@ -1710,7 +1719,8 @@ sysctl_iflist(int af, struct walkarg *w)
ifa->ifa_addr) != 0)
continue;
info.rti_info[RTAX_IFA] = ifa->ifa_addr;
- info.rti_info[RTAX_NETMASK] = ifa->ifa_netmask;
+ info.rti_info[RTAX_NETMASK] = rtsock_fix_netmask(
+ ifa->ifa_addr, ifa->ifa_netmask, &ss);
info.rti_info[RTAX_BRD] = ifa->ifa_dstaddr;
error = rtsock_msg_buffer(RTM_NEWADDR, &info, w, &len);
if (error != 0)
@@ -1727,8 +1737,9 @@ sysctl_iflist(int af, struct walkarg *w)
}
}
IF_ADDR_RUNLOCK(ifp);
- info.rti_info[RTAX_IFA] = info.rti_info[RTAX_NETMASK] =
- info.rti_info[RTAX_BRD] = NULL;
+ info.rti_info[RTAX_IFA] = NULL;
+ info.rti_info[RTAX_NETMASK] = NULL;
+ info.rti_info[RTAX_BRD] = NULL;
}
done:
if (ifp != NULL)
@@ -1764,7 +1775,7 @@ sysctl_ifmalist(int af, struct walkarg *w)
info.rti_info[RTAX_GATEWAY] =
(ifma->ifma_addr->sa_family != AF_LINK) ?
ifma->ifma_lladdr : NULL;
- error = rtsock_msg_buffer(RTM_NEWADDR, &info, w, &len);
+ error = rtsock_msg_buffer(RTM_NEWMADDR, &info, w, &len);
if (error != 0)
goto done;
if (w->w_req && w->w_tmem) {
OpenPOWER on IntegriCloud