Changeset View
Changeset View
Standalone View
Standalone View
sys/netinet/in.c
Show All 40 Lines | |||||
#include <sys/sockio.h> | #include <sys/sockio.h> | ||||
#include <sys/malloc.h> | #include <sys/malloc.h> | ||||
#include <sys/priv.h> | #include <sys/priv.h> | ||||
#include <sys/socket.h> | #include <sys/socket.h> | ||||
#include <sys/jail.h> | #include <sys/jail.h> | ||||
#include <sys/kernel.h> | #include <sys/kernel.h> | ||||
#include <sys/lock.h> | #include <sys/lock.h> | ||||
#include <sys/proc.h> | #include <sys/proc.h> | ||||
#include <sys/rmlock.h> | |||||
#include <sys/sysctl.h> | #include <sys/sysctl.h> | ||||
#include <sys/syslog.h> | #include <sys/syslog.h> | ||||
#include <sys/sx.h> | #include <sys/sx.h> | ||||
#include <net/if.h> | #include <net/if.h> | ||||
#include <net/if_var.h> | #include <net/if_var.h> | ||||
#include <net/if_arp.h> | #include <net/if_arp.h> | ||||
#include <net/if_dl.h> | #include <net/if_dl.h> | ||||
▲ Show 20 Lines • Show All 61 Lines • ▼ Show 20 Lines | in_localaddr(struct in_addr in) | ||||
return (0); | return (0); | ||||
} | } | ||||
/* | /* | ||||
* Return 1 if an internet address is for the local host and configured | * Return 1 if an internet address is for the local host and configured | ||||
* on one of its interfaces. | * on one of its interfaces. | ||||
*/ | */ | ||||
int | bool | ||||
in_localip(struct in_addr in) | in_localip(struct in_addr in) | ||||
{ | { | ||||
struct rm_priotracker in_ifa_tracker; | |||||
struct in_ifaddr *ia; | struct in_ifaddr *ia; | ||||
IN_IFADDR_RLOCK(&in_ifa_tracker); | NET_EPOCH_ASSERT(); | ||||
LIST_FOREACH(ia, INADDR_HASH(in.s_addr), ia_hash) { | |||||
if (IA_SIN(ia)->sin_addr.s_addr == in.s_addr) { | CK_LIST_FOREACH(ia, INADDR_HASH(in.s_addr), ia_hash) | ||||
IN_IFADDR_RUNLOCK(&in_ifa_tracker); | if (IA_SIN(ia)->sin_addr.s_addr == in.s_addr) | ||||
return (1); | return (true); | ||||
return (false); | |||||
} | } | ||||
} | |||||
IN_IFADDR_RUNLOCK(&in_ifa_tracker); | |||||
return (0); | |||||
} | |||||
/* | /* | ||||
* Return 1 if an internet address is configured on an interface. | * Return 1 if an internet address is configured on an interface. | ||||
*/ | */ | ||||
int | int | ||||
in_ifhasaddr(struct ifnet *ifp, struct in_addr in) | in_ifhasaddr(struct ifnet *ifp, struct in_addr in) | ||||
{ | { | ||||
struct ifaddr *ifa; | struct ifaddr *ifa; | ||||
Show All 14 Lines | |||||
/* | /* | ||||
* Return a reference to the interface address which is different to | * Return a reference to the interface address which is different to | ||||
* the supplied one but with same IP address value. | * the supplied one but with same IP address value. | ||||
*/ | */ | ||||
static struct in_ifaddr * | static struct in_ifaddr * | ||||
in_localip_more(struct in_ifaddr *original_ia) | in_localip_more(struct in_ifaddr *original_ia) | ||||
{ | { | ||||
struct rm_priotracker in_ifa_tracker; | struct epoch_tracker et; | ||||
in_addr_t original_addr = IA_SIN(original_ia)->sin_addr.s_addr; | in_addr_t original_addr = IA_SIN(original_ia)->sin_addr.s_addr; | ||||
uint32_t original_fib = original_ia->ia_ifa.ifa_ifp->if_fib; | uint32_t original_fib = original_ia->ia_ifa.ifa_ifp->if_fib; | ||||
struct in_ifaddr *ia; | struct in_ifaddr *ia; | ||||
IN_IFADDR_RLOCK(&in_ifa_tracker); | NET_EPOCH_ENTER(et); | ||||
LIST_FOREACH(ia, INADDR_HASH(original_addr), ia_hash) { | CK_LIST_FOREACH(ia, INADDR_HASH(original_addr), ia_hash) { | ||||
in_addr_t addr = IA_SIN(ia)->sin_addr.s_addr; | in_addr_t addr = IA_SIN(ia)->sin_addr.s_addr; | ||||
uint32_t fib = ia->ia_ifa.ifa_ifp->if_fib; | uint32_t fib = ia->ia_ifa.ifa_ifp->if_fib; | ||||
if (!V_rt_add_addr_allfibs && (original_fib != fib)) | if (!V_rt_add_addr_allfibs && (original_fib != fib)) | ||||
continue; | continue; | ||||
if ((original_ia != ia) && (original_addr == addr)) { | if ((original_ia != ia) && (original_addr == addr)) { | ||||
ifa_ref(&ia->ia_ifa); | ifa_ref(&ia->ia_ifa); | ||||
IN_IFADDR_RUNLOCK(&in_ifa_tracker); | NET_EPOCH_EXIT(et); | ||||
return (ia); | return (ia); | ||||
} | } | ||||
} | } | ||||
IN_IFADDR_RUNLOCK(&in_ifa_tracker); | NET_EPOCH_EXIT(et); | ||||
return (NULL); | return (NULL); | ||||
} | } | ||||
/* | /* | ||||
* Tries to find first IPv4 address in the provided fib. | * Tries to find first IPv4 address in the provided fib. | ||||
* Prefers non-loopback addresses and return loopback IFF | * Prefers non-loopback addresses and return loopback IFF | ||||
* @loopback_ok is set. | * @loopback_ok is set. | ||||
▲ Show 20 Lines • Show All 296 Lines • ▼ Show 20 Lines | in_aifaddr_ioctl(u_long cmd, caddr_t data, struct ifnet *ifp, struct thread *td) | ||||
} | } | ||||
/* if_addrhead is already referenced by ifa_alloc() */ | /* if_addrhead is already referenced by ifa_alloc() */ | ||||
IF_ADDR_WLOCK(ifp); | IF_ADDR_WLOCK(ifp); | ||||
CK_STAILQ_INSERT_TAIL(&ifp->if_addrhead, ifa, ifa_link); | CK_STAILQ_INSERT_TAIL(&ifp->if_addrhead, ifa, ifa_link); | ||||
IF_ADDR_WUNLOCK(ifp); | IF_ADDR_WUNLOCK(ifp); | ||||
ifa_ref(ifa); /* in_ifaddrhead */ | ifa_ref(ifa); /* in_ifaddrhead */ | ||||
IN_IFADDR_WLOCK(); | sx_assert(&in_control_sx, SA_XLOCKED); | ||||
CK_STAILQ_INSERT_TAIL(&V_in_ifaddrhead, ia, ia_link); | CK_STAILQ_INSERT_TAIL(&V_in_ifaddrhead, ia, ia_link); | ||||
LIST_INSERT_HEAD(INADDR_HASH(ia->ia_addr.sin_addr.s_addr), ia, ia_hash); | CK_LIST_INSERT_HEAD(INADDR_HASH(ia->ia_addr.sin_addr.s_addr), ia, | ||||
IN_IFADDR_WUNLOCK(); | ia_hash); | ||||
/* | /* | ||||
* Give the interface a chance to initialize | * Give the interface a chance to initialize | ||||
* if this is its first address, | * if this is its first address, | ||||
* and to validate the address if necessary. | * and to validate the address if necessary. | ||||
*/ | */ | ||||
if (ifp->if_ioctl != NULL) { | if (ifp->if_ioctl != NULL) { | ||||
error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, (caddr_t)ia); | error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, (caddr_t)ia); | ||||
▲ Show 20 Lines • Show All 55 Lines • ▼ Show 20 Lines | fail1: | ||||
if (ia->ia_ifa.ifa_carp) | if (ia->ia_ifa.ifa_carp) | ||||
(*carp_detach_p)(&ia->ia_ifa, false); | (*carp_detach_p)(&ia->ia_ifa, false); | ||||
IF_ADDR_WLOCK(ifp); | IF_ADDR_WLOCK(ifp); | ||||
CK_STAILQ_REMOVE(&ifp->if_addrhead, &ia->ia_ifa, ifaddr, ifa_link); | CK_STAILQ_REMOVE(&ifp->if_addrhead, &ia->ia_ifa, ifaddr, ifa_link); | ||||
IF_ADDR_WUNLOCK(ifp); | IF_ADDR_WUNLOCK(ifp); | ||||
ifa_free(&ia->ia_ifa); /* if_addrhead */ | ifa_free(&ia->ia_ifa); /* if_addrhead */ | ||||
IN_IFADDR_WLOCK(); | sx_assert(&in_control_sx, SA_XLOCKED); | ||||
CK_STAILQ_REMOVE(&V_in_ifaddrhead, ia, in_ifaddr, ia_link); | CK_STAILQ_REMOVE(&V_in_ifaddrhead, ia, in_ifaddr, ia_link); | ||||
LIST_REMOVE(ia, ia_hash); | CK_LIST_REMOVE(ia, ia_hash); | ||||
IN_IFADDR_WUNLOCK(); | |||||
ifa_free(&ia->ia_ifa); /* in_ifaddrhead */ | ifa_free(&ia->ia_ifa); /* in_ifaddrhead */ | ||||
return (error); | return (error); | ||||
} | } | ||||
static int | static int | ||||
in_difaddr_ioctl(u_long cmd, caddr_t data, struct ifnet *ifp, struct thread *td) | in_difaddr_ioctl(u_long cmd, caddr_t data, struct ifnet *ifp, struct thread *td) | ||||
{ | { | ||||
▲ Show 20 Lines • Show All 44 Lines • ▼ Show 20 Lines | if (ia == NULL) { | ||||
IF_ADDR_WUNLOCK(ifp); | IF_ADDR_WUNLOCK(ifp); | ||||
return (EADDRNOTAVAIL); | return (EADDRNOTAVAIL); | ||||
} | } | ||||
CK_STAILQ_REMOVE(&ifp->if_addrhead, &ia->ia_ifa, ifaddr, ifa_link); | CK_STAILQ_REMOVE(&ifp->if_addrhead, &ia->ia_ifa, ifaddr, ifa_link); | ||||
IF_ADDR_WUNLOCK(ifp); | IF_ADDR_WUNLOCK(ifp); | ||||
ifa_free(&ia->ia_ifa); /* if_addrhead */ | ifa_free(&ia->ia_ifa); /* if_addrhead */ | ||||
IN_IFADDR_WLOCK(); | sx_assert(&in_control_sx, SA_XLOCKED); | ||||
CK_STAILQ_REMOVE(&V_in_ifaddrhead, ia, in_ifaddr, ia_link); | CK_STAILQ_REMOVE(&V_in_ifaddrhead, ia, in_ifaddr, ia_link); | ||||
LIST_REMOVE(ia, ia_hash); | CK_LIST_REMOVE(ia, ia_hash); | ||||
IN_IFADDR_WUNLOCK(); | |||||
/* | /* | ||||
* in_scrubprefix() kills the interface route. | * in_scrubprefix() kills the interface route. | ||||
*/ | */ | ||||
in_scrubprefix(ia, LLE_STATIC); | in_scrubprefix(ia, LLE_STATIC); | ||||
/* | /* | ||||
* in_ifadown gets rid of all the rest of | * in_ifadown gets rid of all the rest of | ||||
▲ Show 20 Lines • Show All 1,053 Lines • Show Last 20 Lines |