Changeset View
Changeset View
Standalone View
Standalone View
sys/netinet/in_pcb.c
Show First 20 Lines • Show All 82 Lines • ▼ Show 20 Lines | |||||
#include <net/rss_config.h> | #include <net/rss_config.h> | ||||
#include <net/vnet.h> | #include <net/vnet.h> | ||||
#if defined(INET) || defined(INET6) | #if defined(INET) || defined(INET6) | ||||
#include <netinet/in.h> | #include <netinet/in.h> | ||||
#include <netinet/in_pcb.h> | #include <netinet/in_pcb.h> | ||||
#ifdef INET | #ifdef INET | ||||
#include <netinet/in_var.h> | #include <netinet/in_var.h> | ||||
#include <netinet/in_fib.h> | |||||
#endif | #endif | ||||
#include <netinet/ip_var.h> | #include <netinet/ip_var.h> | ||||
#include <netinet/tcp_var.h> | #include <netinet/tcp_var.h> | ||||
#ifdef TCPHPTS | #ifdef TCPHPTS | ||||
#include <netinet/tcp_hpts.h> | #include <netinet/tcp_hpts.h> | ||||
#endif | #endif | ||||
#include <netinet/udp.h> | #include <netinet/udp.h> | ||||
#include <netinet/udp_var.h> | #include <netinet/udp_var.h> | ||||
#ifdef INET6 | #ifdef INET6 | ||||
#include <netinet/ip6.h> | #include <netinet/ip6.h> | ||||
#include <netinet6/in6_pcb.h> | #include <netinet6/in6_pcb.h> | ||||
#include <netinet6/in6_var.h> | #include <netinet6/in6_var.h> | ||||
#include <netinet6/ip6_var.h> | #include <netinet6/ip6_var.h> | ||||
#endif /* INET6 */ | #endif /* INET6 */ | ||||
#include <net/route/nhop.h> | |||||
#endif | #endif | ||||
#include <netipsec/ipsec_support.h> | #include <netipsec/ipsec_support.h> | ||||
#include <security/mac/mac_framework.h> | #include <security/mac/mac_framework.h> | ||||
#define INPCBLBGROUP_SIZMIN 8 | #define INPCBLBGROUP_SIZMIN 8 | ||||
#define INPCBLBGROUP_SIZMAX 256 | #define INPCBLBGROUP_SIZMAX 256 | ||||
▲ Show 20 Lines • Show All 915 Lines • ▼ Show 20 Lines | |||||
* of connect. Take jails into account as well. | * of connect. Take jails into account as well. | ||||
*/ | */ | ||||
int | int | ||||
in_pcbladdr(struct inpcb *inp, struct in_addr *faddr, struct in_addr *laddr, | in_pcbladdr(struct inpcb *inp, struct in_addr *faddr, struct in_addr *laddr, | ||||
struct ucred *cred) | struct ucred *cred) | ||||
{ | { | ||||
struct ifaddr *ifa; | struct ifaddr *ifa; | ||||
struct sockaddr *sa; | struct sockaddr *sa; | ||||
struct sockaddr_in *sin; | struct sockaddr_in *sin, dst; | ||||
struct route sro; | struct nhop_object *nh; | ||||
int error; | int error; | ||||
NET_EPOCH_ASSERT(); | NET_EPOCH_ASSERT(); | ||||
KASSERT(laddr != NULL, ("%s: laddr NULL", __func__)); | KASSERT(laddr != NULL, ("%s: laddr NULL", __func__)); | ||||
/* | /* | ||||
* Bypass source address selection and use the primary jail IP | * Bypass source address selection and use the primary jail IP | ||||
* if requested. | * if requested. | ||||
*/ | */ | ||||
if (cred != NULL && !prison_saddrsel_ip4(cred, laddr)) | if (cred != NULL && !prison_saddrsel_ip4(cred, laddr)) | ||||
return (0); | return (0); | ||||
error = 0; | error = 0; | ||||
bzero(&sro, sizeof(sro)); | |||||
sin = (struct sockaddr_in *)&sro.ro_dst; | nh = NULL; | ||||
bzero(&dst, sizeof(dst)); | |||||
sin = &dst; | |||||
sin->sin_family = AF_INET; | sin->sin_family = AF_INET; | ||||
sin->sin_len = sizeof(struct sockaddr_in); | sin->sin_len = sizeof(struct sockaddr_in); | ||||
sin->sin_addr.s_addr = faddr->s_addr; | sin->sin_addr.s_addr = faddr->s_addr; | ||||
/* | /* | ||||
* If route is known our src addr is taken from the i/f, | * If route is known our src addr is taken from the i/f, | ||||
* else punt. | * else punt. | ||||
* | * | ||||
* Find out route to destination. | * Find out route to destination. | ||||
*/ | */ | ||||
if ((inp->inp_socket->so_options & SO_DONTROUTE) == 0) | if ((inp->inp_socket->so_options & SO_DONTROUTE) == 0) | ||||
in_rtalloc_ign(&sro, 0, inp->inp_inc.inc_fibnum); | nh = fib4_lookup(inp->inp_inc.inc_fibnum, *faddr, | ||||
0, NHR_NONE, 0); | |||||
/* | /* | ||||
* If we found a route, use the address corresponding to | * If we found a route, use the address corresponding to | ||||
* the outgoing interface. | * the outgoing interface. | ||||
* | * | ||||
* Otherwise assume faddr is reachable on a directly connected | * Otherwise assume faddr is reachable on a directly connected | ||||
* network and try to find a corresponding interface to take | * network and try to find a corresponding interface to take | ||||
* the source address from. | * the source address from. | ||||
*/ | */ | ||||
if (sro.ro_rt == NULL || sro.ro_rt->rt_ifp == NULL) { | if (nh == NULL || nh->nh_ifp == NULL) { | ||||
struct in_ifaddr *ia; | struct in_ifaddr *ia; | ||||
struct ifnet *ifp; | struct ifnet *ifp; | ||||
ia = ifatoia(ifa_ifwithdstaddr((struct sockaddr *)sin, | ia = ifatoia(ifa_ifwithdstaddr((struct sockaddr *)sin, | ||||
inp->inp_socket->so_fibnum)); | inp->inp_socket->so_fibnum)); | ||||
if (ia == NULL) { | if (ia == NULL) { | ||||
ia = ifatoia(ifa_ifwithnet((struct sockaddr *)sin, 0, | ia = ifatoia(ifa_ifwithnet((struct sockaddr *)sin, 0, | ||||
inp->inp_socket->so_fibnum)); | inp->inp_socket->so_fibnum)); | ||||
Show All 36 Lines | in_pcbladdr(struct inpcb *inp, struct in_addr *faddr, struct in_addr *laddr, | ||||
* If the outgoing interface on the route found is not | * If the outgoing interface on the route found is not | ||||
* a loopback interface, use the address from that interface. | * a loopback interface, use the address from that interface. | ||||
* In case of jails do those three steps: | * In case of jails do those three steps: | ||||
* 1. check if the interface address belongs to the jail. If so use it. | * 1. check if the interface address belongs to the jail. If so use it. | ||||
* 2. check if we have any address on the outgoing interface | * 2. check if we have any address on the outgoing interface | ||||
* belonging to this jail. If so use it. | * belonging to this jail. If so use it. | ||||
* 3. as a last resort return the 'default' jail address. | * 3. as a last resort return the 'default' jail address. | ||||
*/ | */ | ||||
if ((sro.ro_rt->rt_ifp->if_flags & IFF_LOOPBACK) == 0) { | if ((nh->nh_ifp->if_flags & IFF_LOOPBACK) == 0) { | ||||
struct in_ifaddr *ia; | struct in_ifaddr *ia; | ||||
struct ifnet *ifp; | struct ifnet *ifp; | ||||
/* If not jailed, use the default returned. */ | /* If not jailed, use the default returned. */ | ||||
if (cred == NULL || !prison_flag(cred, PR_IP4)) { | if (cred == NULL || !prison_flag(cred, PR_IP4)) { | ||||
ia = (struct in_ifaddr *)sro.ro_rt->rt_ifa; | ia = (struct in_ifaddr *)nh->nh_ifa; | ||||
laddr->s_addr = ia->ia_addr.sin_addr.s_addr; | laddr->s_addr = ia->ia_addr.sin_addr.s_addr; | ||||
goto done; | goto done; | ||||
} | } | ||||
/* Jailed. */ | /* Jailed. */ | ||||
/* 1. Check if the iface address belongs to the jail. */ | /* 1. Check if the iface address belongs to the jail. */ | ||||
sin = (struct sockaddr_in *)sro.ro_rt->rt_ifa->ifa_addr; | sin = (struct sockaddr_in *)nh->nh_ifa->ifa_addr; | ||||
if (prison_check_ip4(cred, &sin->sin_addr) == 0) { | if (prison_check_ip4(cred, &sin->sin_addr) == 0) { | ||||
ia = (struct in_ifaddr *)sro.ro_rt->rt_ifa; | ia = (struct in_ifaddr *)nh->nh_ifa; | ||||
laddr->s_addr = ia->ia_addr.sin_addr.s_addr; | laddr->s_addr = ia->ia_addr.sin_addr.s_addr; | ||||
goto done; | goto done; | ||||
} | } | ||||
/* | /* | ||||
* 2. Check if we have any address on the outgoing interface | * 2. Check if we have any address on the outgoing interface | ||||
* belonging to this jail. | * belonging to this jail. | ||||
*/ | */ | ||||
ia = NULL; | ia = NULL; | ||||
ifp = sro.ro_rt->rt_ifp; | ifp = nh->nh_ifp; | ||||
CK_STAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { | CK_STAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { | ||||
sa = ifa->ifa_addr; | sa = ifa->ifa_addr; | ||||
if (sa->sa_family != AF_INET) | if (sa->sa_family != AF_INET) | ||||
continue; | continue; | ||||
sin = (struct sockaddr_in *)sa; | sin = (struct sockaddr_in *)sa; | ||||
if (prison_check_ip4(cred, &sin->sin_addr) == 0) { | if (prison_check_ip4(cred, &sin->sin_addr) == 0) { | ||||
ia = (struct in_ifaddr *)ifa; | ia = (struct in_ifaddr *)ifa; | ||||
break; | break; | ||||
Show All 13 Lines | in_pcbladdr(struct inpcb *inp, struct in_addr *faddr, struct in_addr *laddr, | ||||
* The outgoing interface is marked with 'loopback net', so a route | * The outgoing interface is marked with 'loopback net', so a route | ||||
* to ourselves is here. | * to ourselves is here. | ||||
* Try to find the interface of the destination address and then | * Try to find the interface of the destination address and then | ||||
* take the address from there. That interface is not necessarily | * take the address from there. That interface is not necessarily | ||||
* a loopback interface. | * a loopback interface. | ||||
* In case of jails, check that it is an address of the jail | * In case of jails, check that it is an address of the jail | ||||
* and if we cannot find, fall back to the 'default' jail address. | * and if we cannot find, fall back to the 'default' jail address. | ||||
*/ | */ | ||||
if ((sro.ro_rt->rt_ifp->if_flags & IFF_LOOPBACK) != 0) { | if ((nh->nh_ifp->if_flags & IFF_LOOPBACK) != 0) { | ||||
struct sockaddr_in sain; | struct sockaddr_in sain; | ||||
ae: It looks like we can use `sin' that is already initialized. | |||||
melifaroAuthorUnsubmitted Done Inline ActionsGood catch! Will update the review shortly. melifaro: Good catch! Will update the review shortly. | |||||
struct in_ifaddr *ia; | struct in_ifaddr *ia; | ||||
bzero(&sain, sizeof(struct sockaddr_in)); | bzero(&sain, sizeof(struct sockaddr_in)); | ||||
sain.sin_family = AF_INET; | sain.sin_family = AF_INET; | ||||
sain.sin_len = sizeof(struct sockaddr_in); | sain.sin_len = sizeof(struct sockaddr_in); | ||||
sain.sin_addr.s_addr = faddr->s_addr; | sain.sin_addr.s_addr = faddr->s_addr; | ||||
ia = ifatoia(ifa_ifwithdstaddr(sintosa(&sain), | ia = ifatoia(ifa_ifwithdstaddr(sintosa(&sain), | ||||
Show All 37 Lines | if ((nh->nh_ifp->if_flags & IFF_LOOPBACK) != 0) { | ||||
} | } | ||||
/* 3. As a last resort return the 'default' jail address. */ | /* 3. As a last resort return the 'default' jail address. */ | ||||
error = prison_get_ip4(cred, laddr); | error = prison_get_ip4(cred, laddr); | ||||
goto done; | goto done; | ||||
} | } | ||||
done: | done: | ||||
if (sro.ro_rt != NULL) | |||||
RTFREE(sro.ro_rt); | |||||
return (error); | return (error); | ||||
} | } | ||||
/* | /* | ||||
* Set up for a connect from a socket to the specified address. | * Set up for a connect from a socket to the specified address. | ||||
* On entry, *laddrp and *lportp should contain the current local | * On entry, *laddrp and *lportp should contain the current local | ||||
* address and port for the PCB; these are updated to the values | * address and port for the PCB; these are updated to the values | ||||
* that should be placed in inp_laddr and inp_lport to complete | * that should be placed in inp_laddr and inp_lport to complete | ||||
▲ Show 20 Lines • Show All 2,229 Lines • Show Last 20 Lines |
It looks like we can use `sin' that is already initialized.