summaryrefslogtreecommitdiffstats
path: root/sys/netinet/in.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/netinet/in.c')
-rw-r--r--sys/netinet/in.c117
1 files changed, 46 insertions, 71 deletions
diff --git a/sys/netinet/in.c b/sys/netinet/in.c
index da4e8a0..bba364d 100644
--- a/sys/netinet/in.c
+++ b/sys/netinet/in.c
@@ -76,11 +76,6 @@ static int in_ifinit(struct ifnet *,
struct in_ifaddr *, struct sockaddr_in *, int);
static void in_purgemaddrs(struct ifnet *);
-static VNET_DEFINE(int, subnetsarelocal);
-#define V_subnetsarelocal VNET(subnetsarelocal)
-SYSCTL_VNET_INT(_net_inet_ip, OID_AUTO, subnets_are_local, CTLFLAG_RW,
- &VNET_NAME(subnetsarelocal), 0,
- "Treat all subnets as directly connected");
static VNET_DEFINE(int, sameprefixcarponly);
#define V_sameprefixcarponly VNET(sameprefixcarponly)
SYSCTL_VNET_INT(_net_inet_ip, OID_AUTO, same_prefix_carp_only, CTLFLAG_RW,
@@ -95,9 +90,7 @@ VNET_DECLARE(struct arpstat, arpstat); /* ARP statistics, see if_arp.h */
/*
* Return 1 if an internet address is for a ``local'' host
- * (one to which we have a connection). If subnetsarelocal
- * is true, this includes other subnets of the local net.
- * Otherwise, it includes only the directly-connected (sub)nets.
+ * (one to which we have a connection).
*/
int
in_localaddr(struct in_addr in)
@@ -106,19 +99,10 @@ in_localaddr(struct in_addr in)
register struct in_ifaddr *ia;
IN_IFADDR_RLOCK();
- if (V_subnetsarelocal) {
- TAILQ_FOREACH(ia, &V_in_ifaddrhead, ia_link) {
- if ((i & ia->ia_netmask) == ia->ia_net) {
- IN_IFADDR_RUNLOCK();
- return (1);
- }
- }
- } else {
- TAILQ_FOREACH(ia, &V_in_ifaddrhead, ia_link) {
- if ((i & ia->ia_subnetmask) == ia->ia_subnet) {
- IN_IFADDR_RUNLOCK();
- return (1);
- }
+ TAILQ_FOREACH(ia, &V_in_ifaddrhead, ia_link) {
+ if ((i & ia->ia_subnetmask) == ia->ia_subnet) {
+ IN_IFADDR_RUNLOCK();
+ return (1);
}
}
IN_IFADDR_RUNLOCK();
@@ -845,7 +829,7 @@ in_ifinit(struct ifnet *ifp, struct in_ifaddr *ia, struct sockaddr_in *sin,
{
register u_long i = ntohl(sin->sin_addr.s_addr);
struct sockaddr_in oldaddr;
- int s = splimp(), flags = RTF_UP, error = 0;
+ int flags = RTF_UP, error = 0;
oldaddr = ia->ia_addr;
if (oldaddr.sin_family == AF_INET)
@@ -865,7 +849,6 @@ in_ifinit(struct ifnet *ifp, struct in_ifaddr *ia, struct sockaddr_in *sin,
if (ifp->if_ioctl != NULL) {
error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, (caddr_t)ia);
if (error) {
- splx(s);
/* LIST_REMOVE(ia, ia_hash) is done in in_control */
ia->ia_addr = oldaddr;
IN_IFADDR_WLOCK();
@@ -884,29 +867,24 @@ in_ifinit(struct ifnet *ifp, struct in_ifaddr *ia, struct sockaddr_in *sin,
return (error);
}
}
- splx(s);
if (scrub) {
ia->ia_ifa.ifa_addr = (struct sockaddr *)&oldaddr;
in_ifscrub(ifp, ia, LLE_STATIC);
ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr;
}
- if (IN_CLASSA(i))
- ia->ia_netmask = IN_CLASSA_NET;
- else if (IN_CLASSB(i))
- ia->ia_netmask = IN_CLASSB_NET;
- else
- ia->ia_netmask = IN_CLASSC_NET;
/*
- * The subnet mask usually includes at least the standard network part,
- * but may may be smaller in the case of supernetting.
- * If it is set, we believe it.
+ * Be compatible with network classes, if netmask isn't supplied,
+ * guess it based on classes.
*/
if (ia->ia_subnetmask == 0) {
- ia->ia_subnetmask = ia->ia_netmask;
+ if (IN_CLASSA(i))
+ ia->ia_subnetmask = IN_CLASSA_NET;
+ else if (IN_CLASSB(i))
+ ia->ia_subnetmask = IN_CLASSB_NET;
+ else
+ ia->ia_subnetmask = IN_CLASSC_NET;
ia->ia_sockmask.sin_addr.s_addr = htonl(ia->ia_subnetmask);
- } else
- ia->ia_netmask &= ia->ia_subnetmask;
- ia->ia_net = i & ia->ia_netmask;
+ }
ia->ia_subnet = i & ia->ia_subnetmask;
in_socktrim(&ia->ia_sockmask);
/*
@@ -919,10 +897,11 @@ in_ifinit(struct ifnet *ifp, struct in_ifaddr *ia, struct sockaddr_in *sin,
*/
ia->ia_ifa.ifa_metric = ifp->if_metric;
if (ifp->if_flags & IFF_BROADCAST) {
- ia->ia_broadaddr.sin_addr.s_addr =
- htonl(ia->ia_subnet | ~ia->ia_subnetmask);
- ia->ia_netbroadcast.s_addr =
- htonl(ia->ia_net | ~ ia->ia_netmask);
+ if (ia->ia_subnetmask == IN_RFC3021_MASK)
+ ia->ia_broadaddr.sin_addr.s_addr = INADDR_BROADCAST;
+ else
+ ia->ia_broadaddr.sin_addr.s_addr =
+ htonl(ia->ia_subnet | ~ia->ia_subnetmask);
} else if (ifp->if_flags & IFF_LOOPBACK) {
ia->ia_dstaddr = ia->ia_addr;
flags |= RTF_HOST;
@@ -1126,8 +1105,10 @@ in_scrubprefix(struct in_ifaddr *target, u_int flags)
RT_LOCK(ia_ro.ro_rt);
if (ia_ro.ro_rt->rt_refcnt <= 1)
freeit = 1;
- else
+ else if (flags & LLE_STATIC) {
RT_REMREF(ia_ro.ro_rt);
+ target->ia_flags &= ~IFA_RTSELF;
+ }
RTFREE_LOCKED(ia_ro.ro_rt);
}
if (freeit && (flags & LLE_STATIC)) {
@@ -1136,7 +1117,8 @@ in_scrubprefix(struct in_ifaddr *target, u_int flags)
if (error == 0)
target->ia_flags &= ~IFA_RTSELF;
}
- if (flags & LLE_STATIC)
+ if ((flags & LLE_STATIC) &&
+ !(target->ia_ifp->if_flags & IFF_NOARP))
/* remove arp cache */
arp_ifscrub(target->ia_ifp, IA_SIN(target)->sin_addr.s_addr);
}
@@ -1250,11 +1232,12 @@ in_broadcast(struct in_addr in, struct ifnet *ifp)
TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link)
if (ifa->ifa_addr->sa_family == AF_INET &&
(in.s_addr == ia->ia_broadaddr.sin_addr.s_addr ||
- in.s_addr == ia->ia_netbroadcast.s_addr ||
/*
- * Check for old-style (host 0) broadcast.
+ * Check for old-style (host 0) broadcast, but
+ * taking into account that RFC 3021 obsoletes it.
*/
- t == ia->ia_subnet || t == ia->ia_net) &&
+ (ia->ia_subnetmask != IN_RFC3021_MASK &&
+ t == ia->ia_subnet)) &&
/*
* Check for an all one subnetmask. These
* only exist when an interface gets a secondary
@@ -1411,8 +1394,6 @@ static int
in_lltable_rtcheck(struct ifnet *ifp, u_int flags, const struct sockaddr *l3addr)
{
struct rtentry *rt;
- struct ifnet *xifp;
- int error = 0;
KASSERT(l3addr->sa_family == AF_INET,
("sin_family %d", l3addr->sa_family));
@@ -1429,21 +1410,16 @@ in_lltable_rtcheck(struct ifnet *ifp, u_int flags, const struct sockaddr *l3addr
* such as MANET, and the interface is of the correct type, then
* allow for ARP to proceed.
*/
- if (rt->rt_flags & (RTF_GATEWAY | RTF_HOST)) {
- xifp = rt->rt_ifp;
-
- if (xifp && (xifp->if_type != IFT_ETHER ||
- (xifp->if_flags & (IFF_NOARP | IFF_STATICARP)) != 0))
- error = EINVAL;
-
- if (memcmp(rt->rt_gateway->sa_data, l3addr->sa_data,
- sizeof(in_addr_t)) != 0)
- error = EINVAL;
- }
-
if (rt->rt_flags & RTF_GATEWAY) {
- RTFREE_LOCKED(rt);
- return (EINVAL);
+ if (!(rt->rt_flags & RTF_HOST) || !rt->rt_ifp ||
+ rt->rt_ifp->if_type != IFT_ETHER ||
+ (rt->rt_ifp->if_flags &
+ (IFF_NOARP | IFF_STATICARP)) != 0 ||
+ memcmp(rt->rt_gateway->sa_data, l3addr->sa_data,
+ sizeof(in_addr_t)) != 0) {
+ RTFREE_LOCKED(rt);
+ return (EINVAL);
+ }
}
/*
@@ -1452,32 +1428,31 @@ in_lltable_rtcheck(struct ifnet *ifp, u_int flags, const struct sockaddr *l3addr
* interfaces have the same prefix. An incoming packet arrives
* on one interface and the corresponding outgoing packet leaves
* another interface.
- *
*/
if (rt->rt_ifp != ifp) {
- char *sa, *mask, *addr, *lim;
+ const char *sa, *mask, *addr, *lim;
int len;
- sa = (char *)rt_key(rt);
- mask = (char *)rt_mask(rt);
- addr = (char *)__DECONST(struct sockaddr *, l3addr);
- len = ((struct sockaddr_in *)__DECONST(struct sockaddr *, l3addr))->sin_len;
+ sa = (const char *)rt_key(rt);
+ mask = (const char *)rt_mask(rt);
+ addr = (const char *)l3addr;
+ len = ((const struct sockaddr_in *)l3addr)->sin_len;
lim = addr + len;
for ( ; addr < lim; sa++, mask++, addr++) {
if ((*sa ^ *addr) & *mask) {
- error = EINVAL;
#ifdef DIAGNOSTIC
log(LOG_INFO, "IPv4 address: \"%s\" is not on the network\n",
inet_ntoa(((const struct sockaddr_in *)l3addr)->sin_addr));
#endif
- break;
+ RTFREE_LOCKED(rt);
+ return (EINVAL);
}
}
}
RTFREE_LOCKED(rt);
- return (error);
+ return (0);
}
/*
OpenPOWER on IntegriCloud