diff options
Diffstat (limited to 'sys/net')
-rw-r--r-- | sys/net/ieee8023ad_lacp.c | 14 | ||||
-rw-r--r-- | sys/net/radix.c | 10 | ||||
-rw-r--r-- | sys/net/route.c | 42 | ||||
-rw-r--r-- | sys/net/route.h | 4 | ||||
-rw-r--r-- | sys/net/rtsock.c | 117 |
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) { |