Changeset View
Changeset View
Standalone View
Standalone View
sys/netinet/in.c
Show First 20 Lines • Show All 72 Lines • ▼ Show 20 Lines | |||||
#include <netinet/udp_var.h> | #include <netinet/udp_var.h> | ||||
static int in_aifaddr_ioctl(u_long, caddr_t, struct ifnet *, struct thread *); | static int in_aifaddr_ioctl(u_long, caddr_t, struct ifnet *, struct thread *); | ||||
static int in_difaddr_ioctl(u_long, caddr_t, struct ifnet *, struct thread *); | static int in_difaddr_ioctl(u_long, caddr_t, struct ifnet *, struct thread *); | ||||
static void in_socktrim(struct sockaddr_in *); | static void in_socktrim(struct sockaddr_in *); | ||||
static void in_purgemaddrs(struct ifnet *); | static void in_purgemaddrs(struct ifnet *); | ||||
static void in_rtrequest(int req, struct rtentry *rt, struct rt_addrinfo *info); | |||||
static VNET_DEFINE(int, nosameprefix); | static VNET_DEFINE(int, nosameprefix); | ||||
#define V_nosameprefix VNET(nosameprefix) | #define V_nosameprefix VNET(nosameprefix) | ||||
SYSCTL_INT(_net_inet_ip, OID_AUTO, no_same_prefix, CTLFLAG_VNET | CTLFLAG_RW, | SYSCTL_INT(_net_inet_ip, OID_AUTO, no_same_prefix, CTLFLAG_VNET | CTLFLAG_RW, | ||||
&VNET_NAME(nosameprefix), 0, | &VNET_NAME(nosameprefix), 0, | ||||
"Refuse to create same prefixes on different interfaces"); | "Refuse to create same prefixes on different interfaces"); | ||||
VNET_DECLARE(struct inpcbinfo, ripcbinfo); | VNET_DECLARE(struct inpcbinfo, ripcbinfo); | ||||
#define V_ripcbinfo VNET(ripcbinfo) | #define V_ripcbinfo VNET(ripcbinfo) | ||||
▲ Show 20 Lines • Show All 307 Lines • ▼ Show 20 Lines | in_aifaddr_ioctl(u_long cmd, caddr_t data, struct ifnet *ifp, struct thread *td) | ||||
ifa = ifa_alloc(sizeof(struct in_ifaddr), M_WAITOK); | ifa = ifa_alloc(sizeof(struct in_ifaddr), M_WAITOK); | ||||
ia = (struct in_ifaddr *)ifa; | ia = (struct in_ifaddr *)ifa; | ||||
ifa->ifa_addr = (struct sockaddr *)&ia->ia_addr; | ifa->ifa_addr = (struct sockaddr *)&ia->ia_addr; | ||||
ifa->ifa_dstaddr = (struct sockaddr *)&ia->ia_dstaddr; | ifa->ifa_dstaddr = (struct sockaddr *)&ia->ia_dstaddr; | ||||
ifa->ifa_netmask = (struct sockaddr *)&ia->ia_sockmask; | ifa->ifa_netmask = (struct sockaddr *)&ia->ia_sockmask; | ||||
callout_init_rw(&ia->ia_garp_timer, &ifp->if_addr_lock, | callout_init_rw(&ia->ia_garp_timer, &ifp->if_addr_lock, | ||||
CALLOUT_RETURNUNLOCKED); | CALLOUT_RETURNUNLOCKED); | ||||
ifa->ifa_rtrequest = in_rtrequest; | |||||
ia->ia_ifp = ifp; | ia->ia_ifp = ifp; | ||||
ia->ia_addr = *addr; | ia->ia_addr = *addr; | ||||
if (mask->sin_len != 0) { | if (mask->sin_len != 0) { | ||||
ia->ia_sockmask = *mask; | ia->ia_sockmask = *mask; | ||||
ia->ia_subnetmask = ntohl(ia->ia_sockmask.sin_addr.s_addr); | ia->ia_subnetmask = ntohl(ia->ia_sockmask.sin_addr.s_addr); | ||||
} else { | } else { | ||||
in_addr_t i = ntohl(addr->sin_addr.s_addr); | in_addr_t i = ntohl(addr->sin_addr.s_addr); | ||||
▲ Show 20 Lines • Show All 1,079 Lines • ▼ Show 20 Lines | |||||
void | void | ||||
in_domifdetach(struct ifnet *ifp, void *aux) | in_domifdetach(struct ifnet *ifp, void *aux) | ||||
{ | { | ||||
struct in_ifinfo *ii = (struct in_ifinfo *)aux; | struct in_ifinfo *ii = (struct in_ifinfo *)aux; | ||||
igmp_domifdetach(ifp); | igmp_domifdetach(ifp); | ||||
lltable_free(ii->ii_llt); | lltable_free(ii->ii_llt); | ||||
free(ii, M_IFADDR); | free(ii, M_IFADDR); | ||||
} | |||||
/* | |||||
* Return true if the route described by info is the local subnet route for | |||||
* ifa, or false otherwise. | |||||
*/ | |||||
static int | |||||
in_is_subnet_route(struct ifaddr *ifa, struct rt_addrinfo *info) | |||||
{ | |||||
struct sockaddr *tmp_sa; | |||||
struct sockaddr_storage tmp_storage; | |||||
if (info->rti_info[RTAX_DST] == NULL || info->rti_info[RTAX_NETMASK] == NULL) | |||||
return (0); | |||||
/* First test that the ifaddr falls into the subnet described by the route. */ | |||||
tmp_sa = (struct sockaddr*)&tmp_storage; | |||||
rt_maskedcopy(ifa->ifa_addr, tmp_sa, ifa->ifa_netmask); | |||||
if (!sa_equal(tmp_sa, info->rti_info[RTAX_DST])) | |||||
return (0); | |||||
/* | |||||
* Now test that the subnet mask is the same for the address and | |||||
* the route. If they are different then the route has a different | |||||
* prefix size and ifa just happens to fall within that route. | |||||
* | |||||
* For some reason ifa->ifa_netmask sa_len field is not | |||||
* sizeof(struct sockaddr_in). This causes attempts to directly | |||||
* compare against info->rti_info[RTAX_NETMASK] to incorrectly | |||||
* fail even if the netmasks are the same. Fix this by making a | |||||
* copy of ifa->ifa_netmask with the length field correct. | |||||
*/ | |||||
bzero(tmp_sa, sizeof(struct sockaddr_in)); | |||||
memcpy(tmp_sa, ifa->ifa_netmask, ifa->ifa_netmask->sa_len); | |||||
tmp_sa->sa_len = sizeof(struct sockaddr_in); | |||||
return (sa_equal(info->rti_info[RTAX_NETMASK], tmp_sa)); | |||||
} | |||||
static void | |||||
in_rtrequest(int req, struct rtentry *rt, struct rt_addrinfo *info) | |||||
{ | |||||
/* | |||||
* If we are modifying a route to a subnet, we need to migrate the IFA_ROUTE | |||||
* flag to the new source ifa for the route. | |||||
*/ | |||||
if (req == RTM_DELETE && rt->rt_ifa->ifa_flags & IFA_ROUTE && | |||||
info->rti_ifa != NULL && in_is_subnet_route(rt->rt_ifa, info)) { | |||||
rt->rt_ifa->ifa_flags &= ~IFA_ROUTE; | |||||
info->rti_ifa->ifa_flags |= IFA_ROUTE; | |||||
} | |||||
} | } |