summaryrefslogtreecommitdiff
path: root/sys/netinet
diff options
context:
space:
mode:
authorDavid Gwynne <dlg@cvs.openbsd.org>2011-07-06 01:57:38 +0000
committerDavid Gwynne <dlg@cvs.openbsd.org>2011-07-06 01:57:38 +0000
commit331b4363053aa0348db11124ffb4bbe57f433a8a (patch)
treeaafbb1d01e016aee46e6313cb4ccf591c05833ca /sys/netinet
parent45b3845c4bcc6cce64d0a683b18f928a9bda8d6a (diff)
allow /31s on broadcast interfaces (eg ethernet) to work as per rfc3021.
the issue in our kernel was the broadcast address calculated on the /31 caused a ton of checks for use of broadcast addresses to kick in and prevent one of the two addresses on the /31 from being used. this diff basically detects if a /31 has been configured and doesnt configure a broadcast address for it, which makes the ips usable for normal traffic. i wrote this so i could interoperate with "carrier" network gear better, and sthen wants it so he can conserve address space use. the further special casing of broadcast address handling was from claudio@ ok claudio@ markus@ sthen@ henning@
Diffstat (limited to 'sys/netinet')
-rw-r--r--sys/netinet/in.c10
-rw-r--r--sys/netinet/in.h8
-rw-r--r--sys/netinet/in_pcb.c8
-rw-r--r--sys/netinet/ip_icmp.c11
4 files changed, 27 insertions, 10 deletions
diff --git a/sys/netinet/in.c b/sys/netinet/in.c
index 5ac859edea9..9167486dd95 100644
--- a/sys/netinet/in.c
+++ b/sys/netinet/in.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: in.c,v 1.67 2011/07/03 06:24:13 dlg Exp $ */
+/* $OpenBSD: in.c,v 1.68 2011/07/06 01:57:37 dlg Exp $ */
/* $NetBSD: in.c,v 1.26 1996/02/13 23:41:39 christos Exp $ */
/*
@@ -700,8 +700,12 @@ 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 =
- ia->ia_net | ~ia->ia_netmask;
+ if (IN_RFC3021_SUBNET(ia->ia_netmask))
+ ia->ia_broadaddr.sin_addr.s_addr = 0;
+ else {
+ ia->ia_broadaddr.sin_addr.s_addr =
+ ia->ia_net | ~ia->ia_netmask;
+ }
} else if (ifp->if_flags & IFF_LOOPBACK) {
ia->ia_dstaddr = ia->ia_addr;
flags |= RTF_HOST;
diff --git a/sys/netinet/in.h b/sys/netinet/in.h
index 979f61ff831..adfd4b31f6f 100644
--- a/sys/netinet/in.h
+++ b/sys/netinet/in.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: in.h,v 1.89 2011/06/15 09:11:01 mikeb Exp $ */
+/* $OpenBSD: in.h,v 1.90 2011/07/06 01:57:37 dlg Exp $ */
/* $NetBSD: in.h,v 1.20 1996/02/13 23:41:47 christos Exp $ */
/*
@@ -187,6 +187,12 @@ struct in_addr {
#define IN_CLASSD_HOST __IPADDR(0x0fffffff)
#define IN_MULTICAST(i) IN_CLASSD(i)
+#define IN_RFC3021_NET __IPADDR(0xfffffffe)
+#define IN_RFC3021_NSHIFT 31
+#define IN_RFC3021_HOST __IPADDR(0x00000001)
+#define IN_RFC3021_SUBNET(n) (((u_int32_t)(n) & IN_RFC3021_NET) == \
+ IN_RFC3021_NET)
+
#define IN_EXPERIMENTAL(i) (((u_int32_t)(i) & __IPADDR(0xf0000000)) == \
__IPADDR(0xf0000000))
#define IN_BADCLASS(i) (((u_int32_t)(i) & __IPADDR(0xf0000000)) == \
diff --git a/sys/netinet/in_pcb.c b/sys/netinet/in_pcb.c
index df5c49d2b37..a36b09cbb6c 100644
--- a/sys/netinet/in_pcb.c
+++ b/sys/netinet/in_pcb.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: in_pcb.c,v 1.123 2011/07/05 21:40:38 dhill Exp $ */
+/* $OpenBSD: in_pcb.c,v 1.124 2011/07/06 01:57:37 dlg Exp $ */
/* $NetBSD: in_pcb.c,v 1.25 1996/02/13 23:41:53 christos Exp $ */
/*
@@ -402,8 +402,10 @@ in_pcbconnect(void *v, struct mbuf *nam)
if (sin->sin_addr.s_addr == INADDR_ANY)
sin->sin_addr = TAILQ_FIRST(&in_ifaddr)->ia_addr.sin_addr;
else if (sin->sin_addr.s_addr == INADDR_BROADCAST &&
- (TAILQ_FIRST(&in_ifaddr)->ia_ifp->if_flags & IFF_BROADCAST))
- sin->sin_addr = TAILQ_FIRST(&in_ifaddr)->ia_broadaddr.sin_addr;
+ (TAILQ_FIRST(&in_ifaddr)->ia_ifp->if_flags & IFF_BROADCAST) &&
+ TAILQ_FIRST(&in_ifaddr)->ia_broadaddr.sin_addr.s_addr)
+ sin->sin_addr =
+ TAILQ_FIRST(&in_ifaddr)->ia_broadaddr.sin_addr;
}
if (inp->inp_laddr.s_addr == INADDR_ANY) {
int error;
diff --git a/sys/netinet/ip_icmp.c b/sys/netinet/ip_icmp.c
index b69264495f9..8fdbef04b10 100644
--- a/sys/netinet/ip_icmp.c
+++ b/sys/netinet/ip_icmp.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip_icmp.c,v 1.93 2011/04/04 16:33:52 claudio Exp $ */
+/* $OpenBSD: ip_icmp.c,v 1.94 2011/07/06 01:57:37 dlg Exp $ */
/* $NetBSD: ip_icmp.c,v 1.19 1996/02/13 23:42:22 christos Exp $ */
/*
@@ -533,8 +533,12 @@ icmp_input(struct mbuf *m, ...)
icp->icmp_type = ICMP_MASKREPLY;
icp->icmp_mask = ia->ia_sockmask.sin_addr.s_addr;
if (ip->ip_src.s_addr == 0) {
- if (ia->ia_ifp->if_flags & IFF_BROADCAST)
- ip->ip_src = ia->ia_broadaddr.sin_addr;
+ if (ia->ia_ifp->if_flags & IFF_BROADCAST) {
+ if (ia->ia_broadaddr.sin_addr.s_addr)
+ ip->ip_src = ia->ia_broadaddr.sin_addr;
+ else
+ ip->ip_src.s_addr = INADDR_BROADCAST;
+ }
else if (ia->ia_ifp->if_flags & IFF_POINTOPOINT)
ip->ip_src = ia->ia_dstaddr.sin_addr;
}
@@ -674,6 +678,7 @@ icmp_reflect(struct mbuf *m, struct mbuf **op, struct in_ifaddr *ia)
if (t.s_addr == ia->ia_addr.sin_addr.s_addr)
break;
if ((ia->ia_ifp->if_flags & IFF_BROADCAST) &&
+ ia->ia_broadaddr.sin_addr.s_addr != 0 &&
t.s_addr == ia->ia_broadaddr.sin_addr.s_addr)
break;
}