Changeset View
Changeset View
Standalone View
Standalone View
net/route.c
Show First 20 Lines • Show All 464 Lines • ▼ Show 20 Lines | |||||
* @lifetime_sec: time in seconds to expire this redirect. | * @lifetime_sec: time in seconds to expire this redirect. | ||||
* | * | ||||
* Retuns 0 on success, errno otherwise. | * Retuns 0 on success, errno otherwise. | ||||
*/ | */ | ||||
int | int | ||||
rib_add_redirect(u_int fibnum, struct sockaddr *dst, struct sockaddr *gateway, | rib_add_redirect(u_int fibnum, struct sockaddr *dst, struct sockaddr *gateway, | ||||
struct sockaddr *author, struct ifnet *ifp, int flags, int lifetime_sec) | struct sockaddr *author, struct ifnet *ifp, int flags, int lifetime_sec) | ||||
{ | { | ||||
struct rtentry *rt; | struct rib_cmd_info rc; | ||||
int error; | int error; | ||||
struct rt_addrinfo info; | struct rt_addrinfo info; | ||||
struct rt_metrics rti_rmx; | struct rt_metrics rti_rmx; | ||||
struct ifaddr *ifa; | struct ifaddr *ifa; | ||||
NET_EPOCH_ASSERT(); | NET_EPOCH_ASSERT(); | ||||
if (rt_tables_get_rnh(fibnum, dst->sa_family) == NULL) | if (rt_tables_get_rnh(fibnum, dst->sa_family) == NULL) | ||||
Show All 17 Lines | rib_add_redirect(u_int fibnum, struct sockaddr *dst, struct sockaddr *gateway, | ||||
/* Setup route metrics to define expire time. */ | /* Setup route metrics to define expire time. */ | ||||
bzero(&rti_rmx, sizeof(rti_rmx)); | bzero(&rti_rmx, sizeof(rti_rmx)); | ||||
/* Set expire time as absolute. */ | /* Set expire time as absolute. */ | ||||
rti_rmx.rmx_expire = lifetime_sec + time_second; | rti_rmx.rmx_expire = lifetime_sec + time_second; | ||||
info.rti_mflags |= RTV_EXPIRE; | info.rti_mflags |= RTV_EXPIRE; | ||||
info.rti_rmx = &rti_rmx; | info.rti_rmx = &rti_rmx; | ||||
error = rtrequest1_fib(RTM_ADD, &info, &rt, fibnum); | error = rib_action(fibnum, RTM_ADD, &info, &rc); | ||||
ifa_free(ifa); | ifa_free(ifa); | ||||
if (error != 0) { | if (error != 0) { | ||||
/* TODO: add per-fib redirect stats. */ | /* TODO: add per-fib redirect stats. */ | ||||
return (error); | return (error); | ||||
} | } | ||||
RT_LOCK(rt); | RT_LOCK(rc.rc_rt); | ||||
flags = rt->rt_flags; | flags = rc.rc_rt->rt_flags; | ||||
RT_UNLOCK(rt); | RT_UNLOCK(rc.rc_rt); | ||||
RTSTAT_INC(rts_dynamic); | RTSTAT_INC(rts_dynamic); | ||||
/* Send notification of a route addition to userland. */ | /* Send notification of a route addition to userland. */ | ||||
bzero(&info, sizeof(info)); | bzero(&info, sizeof(info)); | ||||
info.rti_info[RTAX_DST] = dst; | info.rti_info[RTAX_DST] = dst; | ||||
info.rti_info[RTAX_GATEWAY] = gateway; | info.rti_info[RTAX_GATEWAY] = gateway; | ||||
info.rti_info[RTAX_AUTHOR] = author; | info.rti_info[RTAX_AUTHOR] = author; | ||||
▲ Show 20 Lines • Show All 71 Lines • ▼ Show 20 Lines | if (ifa->ifa_addr->sa_family != dst->sa_family) { | ||||
ifa = ifaof_ifpforaddr(dst, ifa->ifa_ifp); | ifa = ifaof_ifpforaddr(dst, ifa->ifa_ifp); | ||||
if (ifa == NULL) | if (ifa == NULL) | ||||
ifa = oifa; | ifa = oifa; | ||||
} | } | ||||
return (ifa); | return (ifa); | ||||
} | } | ||||
/* | |||||
* Do appropriate manipulations of a routing tree given | |||||
* all the bits of info needed | |||||
*/ | |||||
int | |||||
rtrequest_fib(int req, | |||||
struct sockaddr *dst, | |||||
struct sockaddr *gateway, | |||||
struct sockaddr *netmask, | |||||
int flags, | |||||
struct rtentry **ret_nrt, | |||||
u_int fibnum) | |||||
{ | |||||
struct rt_addrinfo info; | |||||
if (dst->sa_len == 0) | |||||
return(EINVAL); | |||||
bzero((caddr_t)&info, sizeof(info)); | |||||
info.rti_flags = flags; | |||||
info.rti_info[RTAX_DST] = dst; | |||||
info.rti_info[RTAX_GATEWAY] = gateway; | |||||
info.rti_info[RTAX_NETMASK] = netmask; | |||||
return rtrequest1_fib(req, &info, ret_nrt, fibnum); | |||||
} | |||||
/* | /* | ||||
* Copy most of @rt data into @info. | * - * Copy most of @rt data into @info. | ||||
* | * | ||||
* If @flags contains NHR_COPY, copies dst,netmask and gw to the | * If @flags contains NHR_COPY, copies dst,netmask and gw to the | ||||
* pointers specified by @info structure. Assume such pointers | * pointers specified by @info structure. Assume such pointers | ||||
* are zeroed sockaddr-like structures with sa_len field initialized | * are zeroed sockaddr-like structures with sa_len field initialized | ||||
* to reflect size of the provided buffer. if no NHR_COPY is specified, | * to reflect size of the provided buffer. if no NHR_COPY is specified, | ||||
* point dst,netmask and gw @info fields to appropriate @rt values. | * point dst,netmask and gw @info fields to appropriate @rt values. | ||||
* | * | ||||
* if @flags contains NHR_REF, do refcouting on rt_ifp and rt_ifa. | * if @flags contains NHR_REF, do refcouting on rt_ifp and rt_ifa. | ||||
▲ Show 20 Lines • Show All 501 Lines • ▼ Show 20 Lines | rt_mpath_unlink(struct rib_head *rnh, struct rt_addrinfo *info, | ||||
if (rt_mpath_deldup(rto, rt) == 0) | if (rt_mpath_deldup(rto, rt) == 0) | ||||
panic ("rtrequest1: rt_mpath_deldup"); | panic ("rtrequest1: rt_mpath_deldup"); | ||||
*perror = 0; | *perror = 0; | ||||
rn = (struct radix_node *)rt; | rn = (struct radix_node *)rt; | ||||
return (rn); | return (rn); | ||||
} | } | ||||
#endif | #endif | ||||
int | |||||
rtrequest1_fib(int req, struct rt_addrinfo *info, struct rtentry **ret_nrt, | |||||
u_int fibnum) | |||||
{ | |||||
const struct sockaddr *dst; | |||||
struct rib_head *rnh; | |||||
struct rib_cmd_info rc; | |||||
int error; | |||||
KASSERT((fibnum < rt_numfibs), ("rtrequest1_fib: bad fibnum")); | |||||
KASSERT((info->rti_flags & RTF_RNH_LOCKED) == 0, ("rtrequest1_fib: locked")); | |||||
NET_EPOCH_ASSERT(); | |||||
dst = info->rti_info[RTAX_DST]; | |||||
switch (dst->sa_family) { | |||||
case AF_INET6: | |||||
case AF_INET: | |||||
/* We support multiple FIBs. */ | |||||
break; | |||||
default: | |||||
fibnum = RT_DEFAULT_FIB; | |||||
break; | |||||
} | |||||
/* | |||||
* Find the correct routing tree to use for this Address Family | |||||
*/ | |||||
rnh = rt_tables_get_rnh(fibnum, dst->sa_family); | |||||
if (rnh == NULL) | |||||
return (EAFNOSUPPORT); | |||||
/* | |||||
* If we are adding a host route then we don't want to put | |||||
* a netmask in the tree, nor do we want to clone it. | |||||
*/ | |||||
if (info->rti_flags & RTF_HOST) | |||||
info->rti_info[RTAX_NETMASK] = NULL; | |||||
bzero(&rc, sizeof(struct rib_cmd_info)); | |||||
error = 0; | |||||
switch (req) { | |||||
case RTM_DELETE: | |||||
error = del_route(rnh, info, &rc); | |||||
break; | |||||
case RTM_RESOLVE: | |||||
/* | |||||
* resolve was only used for route cloning | |||||
* here for compat | |||||
*/ | |||||
break; | |||||
case RTM_ADD: | |||||
error = add_route(rnh, info, &rc); | |||||
break; | |||||
case RTM_CHANGE: | |||||
error = change_route(rnh, info, &rc); | |||||
break; | |||||
default: | |||||
error = EOPNOTSUPP; | |||||
} | |||||
if (ret_nrt != NULL) | |||||
*ret_nrt = rc.rc_rt; | |||||
return (error); | |||||
} | |||||
void | void | ||||
rt_setmetrics(const struct rt_addrinfo *info, struct rtentry *rt) | rt_setmetrics(const struct rt_addrinfo *info, struct rtentry *rt) | ||||
{ | { | ||||
if (info->rti_mflags & RTV_WEIGHT) | if (info->rti_mflags & RTV_WEIGHT) | ||||
rt->rt_weight = info->rti_rmx->rmx_weight; | rt->rt_weight = info->rti_rmx->rmx_weight; | ||||
/* Kernel -> userland timebase conversion. */ | /* Kernel -> userland timebase conversion. */ | ||||
if (info->rti_mflags & RTV_EXPIRE) | if (info->rti_mflags & RTV_EXPIRE) | ||||
Show All 27 Lines | |||||
#define _SOCKADDR_TMPSIZE 128 /* Not too big.. kernel stack size is limited */ | #define _SOCKADDR_TMPSIZE 128 /* Not too big.. kernel stack size is limited */ | ||||
static inline int | static inline int | ||||
rtinit1(struct ifaddr *ifa, int cmd, int flags, int fibnum) | rtinit1(struct ifaddr *ifa, int cmd, int flags, int fibnum) | ||||
{ | { | ||||
RIB_RLOCK_TRACKER; | RIB_RLOCK_TRACKER; | ||||
struct epoch_tracker et; | struct epoch_tracker et; | ||||
struct sockaddr *dst; | struct sockaddr *dst; | ||||
struct sockaddr *netmask; | struct sockaddr *netmask; | ||||
struct rtentry *rt = NULL; | struct rib_cmd_info rc; | ||||
struct rt_addrinfo info; | struct rt_addrinfo info; | ||||
int error = 0; | int error = 0; | ||||
int startfib, endfib; | int startfib, endfib; | ||||
char tempbuf[_SOCKADDR_TMPSIZE]; | char tempbuf[_SOCKADDR_TMPSIZE]; | ||||
int didwork = 0; | int didwork = 0; | ||||
int a_failure = 0; | int a_failure = 0; | ||||
struct sockaddr_dl_short *sdl = NULL; | struct sockaddr_dl_short *sdl = NULL; | ||||
struct rib_head *rnh; | struct rib_head *rnh; | ||||
▲ Show 20 Lines • Show All 114 Lines • ▼ Show 20 Lines | #endif | ||||
* doing this for compatibility reasons | * doing this for compatibility reasons | ||||
*/ | */ | ||||
if (cmd == RTM_ADD) | if (cmd == RTM_ADD) | ||||
info.rti_info[RTAX_GATEWAY] = (struct sockaddr *)sdl; | info.rti_info[RTAX_GATEWAY] = (struct sockaddr *)sdl; | ||||
else | else | ||||
info.rti_info[RTAX_GATEWAY] = ifa->ifa_addr; | info.rti_info[RTAX_GATEWAY] = ifa->ifa_addr; | ||||
info.rti_info[RTAX_NETMASK] = netmask; | info.rti_info[RTAX_NETMASK] = netmask; | ||||
NET_EPOCH_ENTER(et); | NET_EPOCH_ENTER(et); | ||||
error = rtrequest1_fib(cmd, &info, &rt, fibnum); | error = rib_action(fibnum, cmd, &info, &rc); | ||||
if (error == 0 && rt != NULL) { | if (error == 0 && rc.rc_rt != NULL) { | ||||
/* | /* | ||||
* notify any listening routing agents of the change | * notify any listening routing agents of the change | ||||
*/ | */ | ||||
/* TODO: interface routes/aliases */ | /* TODO: interface routes/aliases */ | ||||
rt_newaddrmsg_fib(cmd, ifa, rt, fibnum); | rt_newaddrmsg_fib(cmd, ifa, rc.rc_rt, fibnum); | ||||
didwork = 1; | didwork = 1; | ||||
} | } | ||||
NET_EPOCH_EXIT(et); | NET_EPOCH_EXIT(et); | ||||
if (error) | if (error) | ||||
a_failure = error; | a_failure = error; | ||||
} | } | ||||
if (cmd == RTM_DELETE) { | if (cmd == RTM_DELETE) { | ||||
if (didwork) { | if (didwork) { | ||||
▲ Show 20 Lines • Show All 131 Lines • Show Last 20 Lines |