Changeset View
Changeset View
Standalone View
Standalone View
sys/net/rtsock.c
Show First 20 Lines • Show All 64 Lines • ▼ Show 20 Lines | |||||
#include <net/route/route_ctl.h> | #include <net/route/route_ctl.h> | ||||
#include <net/route/route_var.h> | #include <net/route/route_var.h> | ||||
#include <net/vnet.h> | #include <net/vnet.h> | ||||
#include <netinet/in.h> | #include <netinet/in.h> | ||||
#include <netinet/if_ether.h> | #include <netinet/if_ether.h> | ||||
#include <netinet/ip_carp.h> | #include <netinet/ip_carp.h> | ||||
#ifdef INET6 | #ifdef INET6 | ||||
#include <netinet6/in6_var.h> | |||||
#include <netinet6/ip6_var.h> | #include <netinet6/ip6_var.h> | ||||
donner: Duplicate | |||||
#include <netinet6/scope6_var.h> | #include <netinet6/scope6_var.h> | ||||
#endif | #endif | ||||
#include <net/route/nhop.h> | #include <net/route/nhop.h> | ||||
#ifdef COMPAT_FREEBSD32 | #ifdef COMPAT_FREEBSD32 | ||||
#include <sys/mount.h> | #include <sys/mount.h> | ||||
#include <compat/freebsd32/freebsd32.h> | #include <compat/freebsd32/freebsd32.h> | ||||
▲ Show 20 Lines • Show All 86 Lines • ▼ Show 20 Lines | |||||
}; | }; | ||||
static void rts_input(struct mbuf *m); | static void rts_input(struct mbuf *m); | ||||
static struct mbuf *rtsock_msg_mbuf(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, | static int rtsock_msg_buffer(int type, struct rt_addrinfo *rtinfo, | ||||
struct walkarg *w, int *plen); | struct walkarg *w, int *plen); | ||||
static int rt_xaddrs(caddr_t cp, caddr_t cplim, | static int rt_xaddrs(caddr_t cp, caddr_t cplim, | ||||
struct rt_addrinfo *rtinfo); | struct rt_addrinfo *rtinfo); | ||||
static int cleanup_xaddrs(struct rt_addrinfo *info); | |||||
static int sysctl_dumpentry(struct rtentry *rt, void *vw); | static int sysctl_dumpentry(struct rtentry *rt, void *vw); | ||||
static int sysctl_dumpnhop(struct rtentry *rt, struct nhop_object *nh, | static int sysctl_dumpnhop(struct rtentry *rt, struct nhop_object *nh, | ||||
uint32_t weight, struct walkarg *w); | uint32_t weight, struct walkarg *w); | ||||
static int sysctl_iflist(int af, struct walkarg *w); | static int sysctl_iflist(int af, struct walkarg *w); | ||||
static int sysctl_ifmalist(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 int route_output(struct mbuf *m, struct socket *so, ...); | ||||
static void rt_getmetrics(const struct rtentry *rt, | static void rt_getmetrics(const struct rtentry *rt, | ||||
const struct nhop_object *nh, struct rt_metrics *out); | const struct nhop_object *nh, struct rt_metrics *out); | ||||
▲ Show 20 Lines • Show All 447 Lines • ▼ Show 20 Lines | fill_addrinfo(struct rt_msghdr *rtm, int len, u_int fibnum, struct rt_addrinfo *info) | ||||
* rt_xaddrs() performs s6_addr[2] := sin6_scope_id for AF_INET6 | * rt_xaddrs() performs s6_addr[2] := sin6_scope_id for AF_INET6 | ||||
* link-local address because rtrequest requires addresses with | * link-local address because rtrequest requires addresses with | ||||
* embedded scope id. | * embedded scope id. | ||||
*/ | */ | ||||
if (rt_xaddrs((caddr_t)(rtm + 1), len + (caddr_t)rtm, info)) | if (rt_xaddrs((caddr_t)(rtm + 1), len + (caddr_t)rtm, info)) | ||||
return (EINVAL); | return (EINVAL); | ||||
info->rti_flags = rtm->rtm_flags; | info->rti_flags = rtm->rtm_flags; | ||||
if (info->rti_info[RTAX_DST] == NULL || | error = cleanup_xaddrs(info); | ||||
info->rti_info[RTAX_DST]->sa_family >= AF_MAX || | if (error != 0) | ||||
(info->rti_info[RTAX_GATEWAY] != NULL && | return (error); | ||||
info->rti_info[RTAX_GATEWAY]->sa_family >= AF_MAX)) | |||||
return (EINVAL); | |||||
saf = info->rti_info[RTAX_DST]->sa_family; | saf = info->rti_info[RTAX_DST]->sa_family; | ||||
/* | /* | ||||
* Verify that the caller has the appropriate privilege; RTM_GET | * Verify that the caller has the appropriate privilege; RTM_GET | ||||
* is the only operation the non-superuser is allowed. | * is the only operation the non-superuser is allowed. | ||||
*/ | */ | ||||
if (rtm->rtm_type != RTM_GET) { | if (rtm->rtm_type != RTM_GET) { | ||||
error = priv_check(curthread, PRIV_NET_ROUTE); | error = priv_check(curthread, PRIV_NET_ROUTE); | ||||
if (error != 0) | if (error != 0) | ||||
▲ Show 20 Lines • Show All 82 Lines • ▼ Show 20 Lines | handle_rtm_get(struct rt_addrinfo *info, u_int fibnum, | ||||
saf = info->rti_info[RTAX_DST]->sa_family; | saf = info->rti_info[RTAX_DST]->sa_family; | ||||
rnh = rt_tables_get_rnh(fibnum, saf); | rnh = rt_tables_get_rnh(fibnum, saf); | ||||
if (rnh == NULL) | if (rnh == NULL) | ||||
return (EAFNOSUPPORT); | return (EAFNOSUPPORT); | ||||
RIB_RLOCK(rnh); | RIB_RLOCK(rnh); | ||||
if (info->rti_info[RTAX_NETMASK] == NULL) { | |||||
/* | /* | ||||
* By (implicit) convention host route (one without netmask) | |||||
* means longest-prefix-match request and the route with netmask | |||||
* means exact-match lookup. | |||||
* As cleanup_xaddrs() cleans up info flags&addrs for the /32,/128 | |||||
* prefixes, use original data to check for the netmask presence. | |||||
*/ | |||||
if ((rtm->rtm_addrs & RTA_NETMASK) == 0) { | |||||
Not Done Inline ActionsWhy rtm? Below in the new functions, the rti_addrs flags are modified with &= ~RTA_NETMASK donner: Why rtm? Below in the new functions, the rti_addrs flags are modified with &= ~RTA_NETMASK | |||||
/* | |||||
* Provide longest prefix match for | * Provide longest prefix match for | ||||
* address lookup (no mask). | * address lookup (no mask). | ||||
* 'route -n get addr' | * 'route -n get addr' | ||||
*/ | */ | ||||
rc->rc_rt = (struct rtentry *) rnh->rnh_matchaddr( | rc->rc_rt = (struct rtentry *) rnh->rnh_matchaddr( | ||||
info->rti_info[RTAX_DST], &rnh->head); | info->rti_info[RTAX_DST], &rnh->head); | ||||
} else | } else | ||||
rc->rc_rt = (struct rtentry *) rnh->rnh_lookup( | rc->rc_rt = (struct rtentry *) rnh->rnh_lookup( | ||||
▲ Show 20 Lines • Show All 527 Lines • ▼ Show 20 Lines | #ifdef INET6 | ||||
if (sa->sa_family == AF_INET6) | if (sa->sa_family == AF_INET6) | ||||
sa6_embedscope((struct sockaddr_in6 *)sa, | sa6_embedscope((struct sockaddr_in6 *)sa, | ||||
V_ip6_use_defzone); | V_ip6_use_defzone); | ||||
#endif | #endif | ||||
rtinfo->rti_info[i] = sa; | rtinfo->rti_info[i] = sa; | ||||
cp += SA_SIZE(sa); | cp += SA_SIZE(sa); | ||||
} | } | ||||
return (0); | return (0); | ||||
} | |||||
static inline void | |||||
Not Done Inline Actionsinline? donner: inline? | |||||
fill_sockaddr_inet(struct sockaddr_in *sin, struct in_addr addr) | |||||
{ | |||||
const struct sockaddr_in nsin = { | |||||
.sin_family = AF_INET, | |||||
.sin_len = sizeof(struct sockaddr_in), | |||||
.sin_addr = addr, | |||||
}; | |||||
*sin = nsin; | |||||
} | |||||
static inline void | |||||
fill_sockaddr_inet6(struct sockaddr_in6 *sin6, const struct in6_addr *addr6, | |||||
uint32_t scopeid) | |||||
{ | |||||
const struct sockaddr_in6 nsin6 = { | |||||
.sin6_family = AF_INET6, | |||||
.sin6_len = sizeof(struct sockaddr_in6), | |||||
.sin6_addr = *addr6, | |||||
.sin6_scope_id = scopeid, | |||||
}; | |||||
*sin6 = nsin6; | |||||
} | |||||
static int | |||||
cleanup_xaddrs_gateway(struct rt_addrinfo *info) | |||||
{ | |||||
struct sockaddr *gw = info->rti_info[RTAX_GATEWAY]; | |||||
Done Inline Actions#ifdef INET donner: #ifdef INET | |||||
switch (gw->sa_family) { | |||||
#ifdef INET | |||||
case AF_INET: | |||||
{ | |||||
struct sockaddr_in *gw_sin = (struct sockaddr_in *)gw; | |||||
if (gw_sin->sin_len < sizeof(struct sockaddr_in)) { | |||||
printf("gw sin_len too small\n"); | |||||
return (EINVAL); | |||||
} | |||||
fill_sockaddr_inet(gw_sin, gw_sin->sin_addr); | |||||
Done Inline Actions#ifdef INET6 donner: #ifdef INET6 | |||||
} | |||||
break; | |||||
#endif | |||||
#ifdef INET6 | |||||
case AF_INET6: | |||||
{ | |||||
struct sockaddr_in6 *gw_sin6 = (struct sockaddr_in6 *)gw; | |||||
if (gw_sin6->sin6_len < sizeof(struct sockaddr_in6)) { | |||||
printf("gw sin6_len too small\n"); | |||||
return (EINVAL); | |||||
} | |||||
fill_sockaddr_inet6(gw_sin6, &gw_sin6->sin6_addr, 0); | |||||
break; | |||||
} | |||||
#endif | |||||
case AF_LINK: | |||||
{ | |||||
struct sockaddr_dl_short *gw_sdl; | |||||
gw_sdl = (struct sockaddr_dl_short *)gw; | |||||
if (gw_sdl->sdl_len < sizeof(struct sockaddr_dl_short)) { | |||||
printf("gw sdl_len too small\n"); | |||||
return (EINVAL); | |||||
} | |||||
const struct sockaddr_dl_short sdl = { | |||||
.sdl_family = AF_LINK, | |||||
.sdl_len = sizeof(struct sockaddr_dl_short), | |||||
.sdl_index = gw_sdl->sdl_index, | |||||
}; | |||||
*gw_sdl = sdl; | |||||
break; | |||||
} | |||||
} | |||||
return (0); | |||||
} | |||||
static int | |||||
cleanup_xaddrs_inet(struct rt_addrinfo *info) | |||||
{ | |||||
struct sockaddr_in *dst_sa, *mask_sa; | |||||
/* Check & fixup dst/netmask combination first */ | |||||
dst_sa = (struct sockaddr_in *)info->rti_info[RTAX_DST]; | |||||
mask_sa = (struct sockaddr_in *)info->rti_info[RTAX_NETMASK]; | |||||
struct in_addr mask = { | |||||
.s_addr = mask_sa ? mask_sa->sin_addr.s_addr : INADDR_BROADCAST, | |||||
}; | |||||
struct in_addr dst = { | |||||
.s_addr = htonl(ntohl(dst_sa->sin_addr.s_addr) & ntohl(mask.s_addr)) | |||||
}; | |||||
if (dst_sa->sin_len < sizeof(struct sockaddr_in)) { | |||||
printf("dst sin_len too small\n"); | |||||
return (EINVAL); | |||||
} | |||||
if (mask_sa && mask_sa->sin_len < sizeof(struct sockaddr_in)) { | |||||
printf("mask sin_len too small\n"); | |||||
return (EINVAL); | |||||
} | |||||
fill_sockaddr_inet(dst_sa, dst); | |||||
if (mask.s_addr != INADDR_BROADCAST) | |||||
fill_sockaddr_inet(mask_sa, mask); | |||||
else { | |||||
info->rti_info[RTAX_NETMASK] = NULL; | |||||
info->rti_flags |= RTF_HOST; | |||||
info->rti_addrs &= ~RTA_NETMASK; | |||||
} | |||||
/* Check gateway */ | |||||
if (info->rti_info[RTAX_GATEWAY] != NULL) | |||||
return (cleanup_xaddrs_gateway(info)); | |||||
return (0); | |||||
} | |||||
static int | |||||
cleanup_xaddrs_inet6(struct rt_addrinfo *info) | |||||
{ | |||||
struct sockaddr_in6 *dst_sa, *mask_sa; | |||||
struct in6_addr mask; | |||||
/* Check & fixup dst/netmask combination first */ | |||||
dst_sa = (struct sockaddr_in6 *)info->rti_info[RTAX_DST]; | |||||
mask_sa = (struct sockaddr_in6 *)info->rti_info[RTAX_NETMASK]; | |||||
mask = mask_sa ? mask_sa->sin6_addr : in6mask128; | |||||
IN6_MASK_ADDR(&dst_sa->sin6_addr, &mask); | |||||
if (dst_sa->sin6_len < sizeof(struct sockaddr_in6)) { | |||||
printf("dst sin6_len too small\n"); | |||||
return (EINVAL); | |||||
} | |||||
if (mask_sa && mask_sa->sin6_len < sizeof(struct sockaddr_in6)) { | |||||
printf("mask sin6_len too small\n"); | |||||
return (EINVAL); | |||||
} | |||||
fill_sockaddr_inet6(dst_sa, &dst_sa->sin6_addr, 0); | |||||
if (!IN6_ARE_ADDR_EQUAL(&mask, &in6mask128)) | |||||
fill_sockaddr_inet6(mask_sa, &mask, 0); | |||||
else { | |||||
info->rti_info[RTAX_NETMASK] = NULL; | |||||
info->rti_flags |= RTF_HOST; | |||||
info->rti_addrs &= ~RTA_NETMASK; | |||||
} | |||||
/* Check gateway */ | |||||
if (info->rti_info[RTAX_GATEWAY] != NULL) | |||||
return (cleanup_xaddrs_gateway(info)); | |||||
return (0); | |||||
} | |||||
static int | |||||
cleanup_xaddrs(struct rt_addrinfo *info) | |||||
{ | |||||
int error = EAFNOSUPPORT; | |||||
if (info->rti_info[RTAX_DST] == NULL) | |||||
return (EINVAL); | |||||
switch (info->rti_info[RTAX_DST]->sa_family) { | |||||
#ifdef INET | |||||
case AF_INET: | |||||
error = cleanup_xaddrs_inet(info); | |||||
break; | |||||
#endif | |||||
#ifdef INET6 | |||||
case AF_INET6: | |||||
error = cleanup_xaddrs_inet6(info); | |||||
break; | |||||
#endif | |||||
} | |||||
return (error); | |||||
} | } | ||||
/* | /* | ||||
* Fill in @dmask with valid netmask leaving original @smask | * Fill in @dmask with valid netmask leaving original @smask | ||||
* intact. Mostly used with radix netmasks. | * intact. Mostly used with radix netmasks. | ||||
*/ | */ | ||||
struct sockaddr * | struct sockaddr * | ||||
rtsock_fix_netmask(const struct sockaddr *dst, const struct sockaddr *smask, | rtsock_fix_netmask(const struct sockaddr *dst, const struct sockaddr *smask, | ||||
▲ Show 20 Lines • Show All 1,085 Lines • Show Last 20 Lines |
Duplicate