diff options
| author | Alexander V. Chernikov <melifaro@FreeBSD.org> | 2014-05-08 21:03:31 +0000 |
|---|---|---|
| committer | Alexander V. Chernikov <melifaro@FreeBSD.org> | 2014-05-08 21:03:31 +0000 |
| commit | f4ab388dc67c49181cd5e82c5b5d93c35b96067b (patch) | |
| tree | de4f158e6da3ea5d7a35c686cb4981bd6c2aa95c /sys/net | |
| parent | b1c906c0a492f7e3bd14240276b85a14a3bb0491 (diff) | |
Notes
Diffstat (limited to 'sys/net')
| -rw-r--r-- | sys/net/route.c | 97 | ||||
| -rw-r--r-- | sys/net/route.h | 6 | ||||
| -rw-r--r-- | sys/net/rtsock.c | 150 |
3 files changed, 175 insertions, 78 deletions
diff --git a/sys/net/route.c b/sys/net/route.c index 1db844dcc7a4..47d89787275e 100644 --- a/sys/net/route.c +++ b/sys/net/route.c @@ -37,6 +37,7 @@ #include "opt_inet.h" #include "opt_inet6.h" #include "opt_route.h" +#include "opt_sctp.h" #include "opt_mrouting.h" #include "opt_mpath.h" @@ -85,6 +86,13 @@ #define RT_NUMFIBS 1 #endif +#if defined(INET) || defined(INET6) +#ifdef SCTP +extern void sctp_addr_change(struct ifaddr *ifa, int cmd); +#endif /* SCTP */ +#endif + + /* This is read-only.. */ u_int rt_numfibs = RT_NUMFIBS; SYSCTL_UINT(_net, OID_AUTO, fibs, CTLFLAG_RD, &rt_numfibs, 0, ""); @@ -117,7 +125,8 @@ VNET_DEFINE(int, rttrash); /* routes not in table but not freed */ /* compare two sockaddr structures */ -#define sa_equal(a1, a2) (bcmp((a1), (a2), (a1)->sa_len) == 0) +#define sa_equal(a1, a2) (((a1)->sa_len == (a2)->sa_len) && \ + (bcmp((a1), (a2), (a1)->sa_len) == 0)) /* * Convert a 'struct radix_node *' to a 'struct rtentry *'. @@ -1756,3 +1765,89 @@ rtinit(struct ifaddr *ifa, int cmd, int flags) } return (rtinit1(ifa, cmd, flags, fib)); } + +/* + * Announce interface address arrival/withdraw + * Returns 0 on success. + */ +int +rt_addrmsg(int cmd, struct ifaddr *ifa, int fibnum) +{ + + KASSERT(cmd == RTM_ADD || cmd == RTM_DELETE, + ("unexpected cmd %d", cmd)); + + KASSERT(fibnum == RT_ALL_FIBS || (fibnum >= 0 && fibnum < rt_numfibs), + ("%s: fib out of range 0 <=%d<%d", __func__, fibnum, rt_numfibs)); + + return (rtsock_addrmsg(cmd, ifa, fibnum)); +} + +/* + * Announce route addition/removal. + * Users of this function MUST validate input data BEFORE calling. + * However we have to be able to handle invalid data: + * if some userland app sends us "invalid" route message (invalid mask, + * no dst, wrong address families, etc...) we need to pass it back + * to app (and any other rtsock consumers) with rtm_errno field set to + * non-zero value. + * Returns 0 on success. + */ +int +rt_routemsg(int cmd, struct ifnet *ifp, int error, struct rtentry *rt, + int fibnum) +{ + + KASSERT(cmd == RTM_ADD || cmd == RTM_DELETE, + ("unexpected cmd %d", cmd)); + + KASSERT(fibnum == RT_ALL_FIBS || (fibnum >= 0 && fibnum < rt_numfibs), + ("%s: fib out of range 0 <=%d<%d", __func__, fibnum, rt_numfibs)); + + KASSERT(rt_key(rt) != NULL, (":%s: rt_key must be supplied", __func__)); + + return (rtsock_routemsg(cmd, ifp, error, rt, fibnum)); +} + +void +rt_newaddrmsg(int cmd, struct ifaddr *ifa, int error, struct rtentry *rt) +{ + + rt_newaddrmsg_fib(cmd, ifa, error, rt, RT_ALL_FIBS); +} + +/* + * This is called to generate messages from the routing socket + * indicating a network interface has had addresses associated with it. + */ +void +rt_newaddrmsg_fib(int cmd, struct ifaddr *ifa, int error, struct rtentry *rt, + int fibnum) +{ + + KASSERT(cmd == RTM_ADD || cmd == RTM_DELETE, + ("unexpected cmd %u", cmd)); + KASSERT(fibnum == RT_ALL_FIBS || (fibnum >= 0 && fibnum < rt_numfibs), + ("%s: fib out of range 0 <=%d<%d", __func__, fibnum, rt_numfibs)); + +#if defined(INET) || defined(INET6) +#ifdef SCTP + /* + * notify the SCTP stack + * this will only get called when an address is added/deleted + * XXX pass the ifaddr struct instead if ifa->ifa_addr... + */ + sctp_addr_change(ifa, cmd); +#endif /* SCTP */ +#endif + if (cmd == RTM_ADD) { + rt_addrmsg(cmd, ifa, fibnum); + if (rt != NULL) + rt_routemsg(cmd, ifa->ifa_ifp, error, rt, fibnum); + } else { + if (rt != NULL) + rt_routemsg(cmd, ifa->ifa_ifp, error, rt, fibnum); + rt_addrmsg(cmd, ifa, fibnum); + } +} + diff --git a/sys/net/route.h b/sys/net/route.h index 234b53634b44..244eea29c76d 100644 --- a/sys/net/route.h +++ b/sys/net/route.h @@ -85,6 +85,7 @@ struct rt_metrics { #define RT_DEFAULT_FIB 0 /* Explicitly mark fib=0 restricted cases */ #define RT_ALL_FIBS -1 /* Announce event for every fib */ extern u_int rt_numfibs; /* number of usable routing tables */ +extern u_int rt_add_addr_allfibs; /* Announce interfaces to all fibs */ /* * We distinguish between routes to hosts and routes to networks, @@ -343,10 +344,15 @@ void rt_missmsg(int, struct rt_addrinfo *, int, int); void rt_missmsg_fib(int, struct rt_addrinfo *, int, int, int); void rt_newaddrmsg(int, struct ifaddr *, int, struct rtentry *); void rt_newaddrmsg_fib(int, struct ifaddr *, int, struct rtentry *, int); +int rt_addrmsg(int, struct ifaddr *, int); +int rt_routemsg(int, struct ifnet *ifp, int, struct rtentry *, int); void rt_newmaddrmsg(int, struct ifmultiaddr *); int rt_setgate(struct rtentry *, struct sockaddr *, struct sockaddr *); void rt_maskedcopy(struct sockaddr *, struct sockaddr *, struct sockaddr *); +int rtsock_addrmsg(int, struct ifaddr *, int); +int rtsock_routemsg(int, struct ifnet *ifp, int, struct rtentry *, int); + /* * Note the following locking behavior: * diff --git a/sys/net/rtsock.c b/sys/net/rtsock.c index 798ed43b6a6c..1979ea0282be 100644 --- a/sys/net/rtsock.c +++ b/sys/net/rtsock.c @@ -30,7 +30,6 @@ * $FreeBSD$ */ #include "opt_compat.h" -#include "opt_sctp.h" #include "opt_mpath.h" #include "opt_inet.h" #include "opt_inet6.h" @@ -70,12 +69,6 @@ #include <netinet6/scope6_var.h> #endif -#if defined(INET) || defined(INET6) -#ifdef SCTP -extern void sctp_addr_change(struct ifaddr *ifa, int cmd); -#endif /* SCTP */ -#endif - #ifdef COMPAT_FREEBSD32 #include <sys/mount.h> #include <compat/freebsd32/freebsd32.h> @@ -1327,89 +1320,92 @@ rt_ifmsg(struct ifnet *ifp) } /* - * This is called to generate messages from the routing socket - * indicating a network interface has had addresses associated with it. - * if we ever reverse the logic and replace messages TO the routing - * socket indicate a request to configure interfaces, then it will - * be unnecessary as the routing socket will automatically generate - * copies of it. + * Announce interface address arrival/withdraw. + * Please do not call directly, use rt_addrmsg(). + * Assume input data to be valid. + * Returns 0 on success. */ -void -rt_newaddrmsg_fib(int cmd, struct ifaddr *ifa, int error, struct rtentry *rt, - int fibnum) +int +rtsock_addrmsg(int cmd, struct ifaddr *ifa, int fibnum) { struct rt_addrinfo info; - struct sockaddr *sa = NULL; - int pass; - struct mbuf *m = NULL; + struct sockaddr *sa; + int ncmd; + struct mbuf *m; + struct ifa_msghdr *ifam; struct ifnet *ifp = ifa->ifa_ifp; - KASSERT(cmd == RTM_ADD || cmd == RTM_DELETE, - ("unexpected cmd %u", cmd)); -#if defined(INET) || defined(INET6) -#ifdef SCTP - /* - * notify the SCTP stack - * this will only get called when an address is added/deleted - * XXX pass the ifaddr struct instead if ifa->ifa_addr... - */ - sctp_addr_change(ifa, cmd); -#endif /* SCTP */ -#endif if (route_cb.any_count == 0) - return; - for (pass = 1; pass < 3; pass++) { - bzero((caddr_t)&info, sizeof(info)); - if ((cmd == RTM_ADD && pass == 1) || - (cmd == RTM_DELETE && pass == 2)) { - struct ifa_msghdr *ifam; - int ncmd = cmd == RTM_ADD ? RTM_NEWADDR : RTM_DELADDR; + return (0); - 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_BRD] = ifa->ifa_dstaddr; - if ((m = rt_msg1(ncmd, &info)) == NULL) - continue; - ifam = mtod(m, struct ifa_msghdr *); - ifam->ifam_index = ifp->if_index; - ifam->ifam_metric = ifa->ifa_metric; - ifam->ifam_flags = ifa->ifa_flags; - ifam->ifam_addrs = info.rti_addrs; - } - if ((cmd == RTM_ADD && pass == 2) || - (cmd == RTM_DELETE && pass == 1)) { - struct rt_msghdr *rtm; + ncmd = cmd == RTM_ADD ? RTM_NEWADDR : RTM_DELADDR; - if (rt == NULL) - continue; - info.rti_info[RTAX_NETMASK] = rt_mask(rt); - info.rti_info[RTAX_DST] = sa = rt_key(rt); - info.rti_info[RTAX_GATEWAY] = rt->rt_gateway; - if ((m = rt_msg1(cmd, &info)) == NULL) - continue; - rtm = mtod(m, struct rt_msghdr *); - rtm->rtm_index = ifp->if_index; - rtm->rtm_flags |= rt->rt_flags; - rtm->rtm_errno = error; - rtm->rtm_addrs = info.rti_addrs; - } - if (fibnum != RT_ALL_FIBS) { - KASSERT(fibnum >= 0 && fibnum < rt_numfibs, ("%s: " - "fibnum out of range 0 <= %d < %d", __func__, - fibnum, rt_numfibs)); - M_SETFIB(m, fibnum); - m->m_flags |= RTS_FILTER_FIB; - } - rt_dispatch(m, sa ? sa->sa_family : AF_UNSPEC); + 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_BRD] = ifa->ifa_dstaddr; + if ((m = rt_msg1(ncmd, &info)) == NULL) + return (ENOBUFS); + ifam = mtod(m, struct ifa_msghdr *); + ifam->ifam_index = ifp->if_index; + ifam->ifam_metric = ifa->ifa_metric; + ifam->ifam_flags = ifa->ifa_flags; + ifam->ifam_addrs = info.rti_addrs; + + if (fibnum != RT_ALL_FIBS) { + M_SETFIB(m, fibnum); + m->m_flags |= RTS_FILTER_FIB; } + + rt_dispatch(m, sa ? sa->sa_family : AF_UNSPEC); + + return (0); } -void -rt_newaddrmsg(int cmd, struct ifaddr *ifa, int error, struct rtentry *rt) +/* + * Announce route addition/removal. + * Please do not call directly, use rt_routemsg(). + * Note that @rt data MAY be inconsistent/invalid: + * if some userland app sends us "invalid" route message (invalid mask, + * no dst, wrong address families, etc...) we need to pass it back + * to app (and any other rtsock consumers) with rtm_errno field set to + * non-zero value. + * + * Returns 0 on success. + */ +int +rtsock_routemsg(int cmd, struct ifnet *ifp, int error, struct rtentry *rt, + int fibnum) { + struct rt_addrinfo info; + struct sockaddr *sa; + struct mbuf *m; + struct rt_msghdr *rtm; + + if (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_GATEWAY] = rt->rt_gateway; + if ((m = rt_msg1(cmd, &info)) == NULL) + return (ENOBUFS); + rtm = mtod(m, struct rt_msghdr *); + rtm->rtm_index = ifp->if_index; + rtm->rtm_flags |= rt->rt_flags; + rtm->rtm_errno = error; + rtm->rtm_addrs = info.rti_addrs; - rt_newaddrmsg_fib(cmd, ifa, error, rt, RT_ALL_FIBS); + if (fibnum != RT_ALL_FIBS) { + M_SETFIB(m, fibnum); + m->m_flags |= RTS_FILTER_FIB; + } + + rt_dispatch(m, sa ? sa->sa_family : AF_UNSPEC); + + return (0); } /* |
