summaryrefslogtreecommitdiff
path: root/sys/netinet
diff options
context:
space:
mode:
authorCedric Berger <cedric@cvs.openbsd.org>2004-06-06 16:49:10 +0000
committerCedric Berger <cedric@cvs.openbsd.org>2004-06-06 16:49:10 +0000
commit9e25ab1fcd3c8a3b75b6ae3c7ca26a172a86d2e8 (patch)
tree021044703db486221cd747d714184ece1513b162 /sys/netinet
parentac4791c970556454694a0c9ab754ea95de5b9bc1 (diff)
extend routing table to be able to match and route packets based on
their *source* IP address in addition to their destination address. routing table "destination" now contains a "struct sockaddr_rtin" for IPv4 instead of a "struct sockaddr_in". the routing socket has been extended in a backward-compatible way. todo: PMTU enhancements, IPv6. ok deraadt@ mcbride@
Diffstat (limited to 'sys/netinet')
-rw-r--r--sys/netinet/in.h13
-rw-r--r--sys/netinet/in_pcb.c5
-rw-r--r--sys/netinet/ip_icmp.c6
-rw-r--r--sys/netinet/ip_input.c39
-rw-r--r--sys/netinet/ip_output.c41
-rw-r--r--sys/netinet/ip_var.h4
6 files changed, 74 insertions, 34 deletions
diff --git a/sys/netinet/in.h b/sys/netinet/in.h
index 4e8b331de54..34704080c3a 100644
--- a/sys/netinet/in.h
+++ b/sys/netinet/in.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: in.h,v 1.61 2004/02/15 11:16:08 markus Exp $ */
+/* $OpenBSD: in.h,v 1.62 2004/06/06 16:49:09 cedric Exp $ */
/* $NetBSD: in.h,v 1.20 1996/02/13 23:41:47 christos Exp $ */
/*
@@ -217,6 +217,15 @@ struct sockaddr_in {
int8_t sin_zero[8];
};
+struct sockaddr_rtin {
+ u_int8_t rtin_len;
+ sa_family_t rtin_family;
+ in_port_t rtin_port;
+ struct in_addr rtin_dst;
+ struct in_addr rtin_src;
+ int8_t rtin_zero[4];
+};
+
/*
* Structure used to describe IP options.
* Used to store options internally, to pass them to a process,
@@ -616,4 +625,6 @@ char *inet_ntoa(struct in_addr);
#define sintosa(sin) ((struct sockaddr *)(sin))
#define ifatoia(ifa) ((struct in_ifaddr *)(ifa))
#endif /* _KERNEL */
+#define satortin(rtin) ((struct sockaddr_rtin *)(rtin))
+
#endif /* _NETINET_IN_H_ */
diff --git a/sys/netinet/in_pcb.c b/sys/netinet/in_pcb.c
index bcb820627d5..dd9ac63edf4 100644
--- a/sys/netinet/in_pcb.c
+++ b/sys/netinet/in_pcb.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: in_pcb.c,v 1.75 2004/03/12 17:49:23 claudio Exp $ */
+/* $OpenBSD: in_pcb.c,v 1.76 2004/06/06 16:49:09 cedric Exp $ */
/* $NetBSD: in_pcb.c,v 1.25 1996/02/13 23:41:53 christos Exp $ */
/*
@@ -841,7 +841,8 @@ in_pcbrtentry(inp)
break;
ro->ro_dst.sa_family = AF_INET;
ro->ro_dst.sa_len = sizeof(ro->ro_dst);
- satosin(&ro->ro_dst)->sin_addr = inp->inp_faddr;
+ satortin(&ro->ro_dst)->rtin_dst = inp->inp_faddr;
+ satortin(&ro->ro_dst)->rtin_src = inp->inp_laddr;
rtalloc(ro);
break;
}
diff --git a/sys/netinet/ip_icmp.c b/sys/netinet/ip_icmp.c
index 01008af1c97..15cf7cd391c 100644
--- a/sys/netinet/ip_icmp.c
+++ b/sys/netinet/ip_icmp.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip_icmp.c,v 1.63 2004/04/26 01:47:24 deraadt Exp $ */
+/* $OpenBSD: ip_icmp.c,v 1.64 2004/06/06 16:49:09 cedric Exp $ */
/* $NetBSD: ip_icmp.c,v 1.19 1996/02/13 23:42:22 christos Exp $ */
/*
@@ -564,7 +564,7 @@ reflect:
icmpsrc.sin_addr = icp->icmp_ip.ip_dst;
rt = NULL;
rtredirect(sintosa(&icmpsrc), sintosa(&icmpdst),
- (struct sockaddr *)0, RTF_GATEWAY | RTF_HOST,
+ (struct sockaddr *)&rt_defmask4, RTF_GATEWAY | RTF_HOST,
sintosa(&icmpgw), (struct rtentry **)&rt);
if (rt != NULL && icmp_redirtimeout != 0) {
(void)rt_timer_add(rt, icmp_redirect_timeout,
@@ -850,7 +850,7 @@ icmp_mtudisc_clone(struct sockaddr *dst)
error = rtrequest((int) RTM_ADD, dst,
(struct sockaddr *) rt->rt_gateway,
- (struct sockaddr *) 0,
+ sroute_clone_mask4(rt_mask(rt), NULL),
RTF_GATEWAY | RTF_HOST | RTF_DYNAMIC, &nrt);
if (error) {
rtfree(rt);
diff --git a/sys/netinet/ip_input.c b/sys/netinet/ip_input.c
index 15d1c6b7e42..e087115e8c8 100644
--- a/sys/netinet/ip_input.c
+++ b/sys/netinet/ip_input.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip_input.c,v 1.118 2004/03/15 09:45:31 tedu Exp $ */
+/* $OpenBSD: ip_input.c,v 1.119 2004/06/06 16:49:09 cedric Exp $ */
/* $NetBSD: ip_input.c,v 1.30 1996/03/16 23:53:58 christos Exp $ */
/*
@@ -1093,7 +1093,7 @@ ip_dooptions(m)
if ((ia = (INA)ifa_ifwithdstaddr((SA)&ipaddr)) == 0)
ia = (INA)ifa_ifwithnet((SA)&ipaddr);
} else
- ia = ip_rtaddr(ipaddr.sin_addr);
+ ia = ip_rtaddr(ipaddr.sin_addr, ip->ip_src);
if (ia == 0) {
type = ICMP_UNREACH;
code = ICMP_UNREACH_SRCFAIL;
@@ -1132,7 +1132,8 @@ ip_dooptions(m)
* use the incoming interface (should be same).
*/
if ((ia = (INA)ifa_ifwithaddr((SA)&ipaddr)) == 0 &&
- (ia = ip_rtaddr(ipaddr.sin_addr)) == 0) {
+ (ia = ip_rtaddr(ipaddr.sin_addr, ip->ip_src)) == 0)
+ {
type = ICMP_UNREACH;
code = ICMP_UNREACH_HOST;
goto bad;
@@ -1211,21 +1212,22 @@ bad:
* return internet address info of interface to be used to get there.
*/
struct in_ifaddr *
-ip_rtaddr(dst)
- struct in_addr dst;
+ip_rtaddr(struct in_addr dst, struct in_addr src)
{
- struct sockaddr_in *sin;
+ struct sockaddr_rtin *rtin;
- sin = satosin(&ipforward_rt.ro_dst);
+ rtin = satortin(&ipforward_rt.ro_dst);
- if (ipforward_rt.ro_rt == 0 || dst.s_addr != sin->sin_addr.s_addr) {
+ if (ipforward_rt.ro_rt == 0 || dst.s_addr != rtin->rtin_dst.s_addr ||
+ src.s_addr != rtin->rtin_src.s_addr) {
if (ipforward_rt.ro_rt) {
RTFREE(ipforward_rt.ro_rt);
ipforward_rt.ro_rt = 0;
}
- sin->sin_family = AF_INET;
- sin->sin_len = sizeof(*sin);
- sin->sin_addr = dst;
+ rtin->rtin_family = AF_INET;
+ rtin->rtin_len = sizeof(*rtin);
+ rtin->rtin_dst = dst;
+ rtin->rtin_src = src;
rtalloc(&ipforward_rt);
}
@@ -1273,6 +1275,7 @@ ip_weadvertise(addr)
sin.sin_len = sizeof(sin);
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = addr;
+ sin.sin_srcaddr.s_addr = 0;
sin.sin_other = SIN_PROXY;
rt = rtalloc1(sintosa(&sin), 0);
if (rt == 0)
@@ -1427,7 +1430,7 @@ ip_forward(m, srcrt)
int srcrt;
{
struct ip *ip = mtod(m, struct ip *);
- struct sockaddr_in *sin;
+ struct sockaddr_rtin *rtin;
struct rtentry *rt;
int error, type = 0, code = 0;
struct mbuf *mcopy;
@@ -1454,16 +1457,18 @@ ip_forward(m, srcrt)
}
ip->ip_ttl -= IPTTLDEC;
- sin = satosin(&ipforward_rt.ro_dst);
+ rtin = satortin(&ipforward_rt.ro_dst);
if ((rt = ipforward_rt.ro_rt) == 0 ||
- ip->ip_dst.s_addr != sin->sin_addr.s_addr) {
+ ip->ip_dst.s_addr != rtin->rtin_dst.s_addr ||
+ ip->ip_src.s_addr != rtin->rtin_src.s_addr) {
if (ipforward_rt.ro_rt) {
RTFREE(ipforward_rt.ro_rt);
ipforward_rt.ro_rt = 0;
}
- sin->sin_family = AF_INET;
- sin->sin_len = sizeof(*sin);
- sin->sin_addr = ip->ip_dst;
+ rtin->rtin_family = AF_INET;
+ rtin->rtin_len = sizeof(*rtin);
+ rtin->rtin_dst = ip->ip_dst;
+ rtin->rtin_src = ip->ip_src;
rtalloc(&ipforward_rt);
if (ipforward_rt.ro_rt == 0) {
diff --git a/sys/netinet/ip_output.c b/sys/netinet/ip_output.c
index c156f1fc066..f5dffcf92cf 100644
--- a/sys/netinet/ip_output.c
+++ b/sys/netinet/ip_output.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip_output.c,v 1.162 2004/05/18 10:31:09 dhartmei Exp $ */
+/* $OpenBSD: ip_output.c,v 1.163 2004/06/06 16:49:09 cedric Exp $ */
/* $NetBSD: ip_output.c,v 1.28 1996/02/13 23:43:07 christos Exp $ */
/*
@@ -98,6 +98,7 @@ ip_output(struct mbuf *m0, ...)
int len, error = 0;
struct route iproute;
struct sockaddr_in *dst;
+ struct sockaddr_rtin *rtin;
struct in_ifaddr *ia;
struct mbuf *opt;
struct route *ro;
@@ -174,6 +175,7 @@ ip_output(struct mbuf *m0, ...)
bzero((caddr_t)ro, sizeof (*ro));
}
+ rtin = satortin(&ro->ro_dst);
dst = satosin(&ro->ro_dst);
/*
@@ -181,15 +183,17 @@ ip_output(struct mbuf *m0, ...)
* destination and is still up. If not, free it and try again.
*/
if (ro->ro_rt && ((ro->ro_rt->rt_flags & RTF_UP) == 0 ||
- dst->sin_addr.s_addr != ip->ip_dst.s_addr)) {
+ rtin->rtin_dst.s_addr != ip->ip_dst.s_addr ||
+ rtin->rtin_src.s_addr != ip->ip_src.s_addr)) {
RTFREE(ro->ro_rt);
ro->ro_rt = (struct rtentry *)0;
}
if (ro->ro_rt == 0) {
- dst->sin_family = AF_INET;
- dst->sin_len = sizeof(*dst);
- dst->sin_addr = ip->ip_dst;
+ rtin->rtin_family = AF_INET;
+ rtin->rtin_len = sizeof(*rtin);
+ rtin->rtin_dst = ip->ip_dst;
+ rtin->rtin_src = ip->ip_src;
}
/*
@@ -230,6 +234,14 @@ ip_output(struct mbuf *m0, ...)
if (ro->ro_rt->rt_flags & RTF_GATEWAY)
dst = satosin(ro->ro_rt->rt_gateway);
+ else if (rtin->rtin_src.s_addr) {
+ if (ro != &iproute) {
+ iproute.ro_dst = ro->ro_dst;
+ rtin = satortin(&iproute.ro_dst);
+ dst = satosin(&iproute.ro_dst);
+ }
+ rtin->rtin_src.s_addr = 0;
+ }
}
/* Set the source IP address */
@@ -341,6 +353,7 @@ ip_output(struct mbuf *m0, ...)
bzero((caddr_t)ro, sizeof (*ro));
}
+ rtin = satortin(&ro->ro_dst);
dst = satosin(&ro->ro_dst);
/*
@@ -348,15 +361,17 @@ ip_output(struct mbuf *m0, ...)
* destination and is still up. If not, free it and try again.
*/
if (ro->ro_rt && ((ro->ro_rt->rt_flags & RTF_UP) == 0 ||
- dst->sin_addr.s_addr != ip->ip_dst.s_addr)) {
+ rtin->rtin_dst.s_addr != ip->ip_dst.s_addr ||
+ rtin->rtin_src.s_addr != ip->ip_src.s_addr)) {
RTFREE(ro->ro_rt);
ro->ro_rt = (struct rtentry *)0;
}
if (ro->ro_rt == 0) {
- dst->sin_family = AF_INET;
- dst->sin_len = sizeof(*dst);
- dst->sin_addr = ip->ip_dst;
+ rtin->rtin_family = AF_INET;
+ rtin->rtin_len = sizeof(*rtin);
+ rtin->rtin_dst = ip->ip_dst;
+ rtin->rtin_src = ip->ip_src;
}
/*
@@ -397,6 +412,14 @@ ip_output(struct mbuf *m0, ...)
if (ro->ro_rt->rt_flags & RTF_GATEWAY)
dst = satosin(ro->ro_rt->rt_gateway);
+ else if (rtin->rtin_src.s_addr) {
+ if (ro != &iproute) {
+ iproute.ro_dst = ro->ro_dst;
+ rtin = satortin(&iproute.ro_dst);
+ dst = satosin(&iproute.ro_dst);
+ }
+ rtin->rtin_src.s_addr = 0;
+ }
}
/* Set the source IP address */
diff --git a/sys/netinet/ip_var.h b/sys/netinet/ip_var.h
index cbcc0ed8629..f14af1156bf 100644
--- a/sys/netinet/ip_var.h
+++ b/sys/netinet/ip_var.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip_var.h,v 1.30 2004/04/28 02:51:58 cedric Exp $ */
+/* $OpenBSD: ip_var.h,v 1.31 2004/06/06 16:49:09 cedric Exp $ */
/* $NetBSD: ip_var.h,v 1.16 1996/02/13 23:43:20 christos Exp $ */
/*
@@ -183,7 +183,7 @@ struct mbuf *
struct in_ifaddr *
in_iawithaddr(struct in_addr, struct mbuf *);
struct in_ifaddr *
- ip_rtaddr(struct in_addr);
+ ip_rtaddr(struct in_addr, struct in_addr);
u_int16_t
ip_randomid(void);
int ip_setmoptions(int, struct ip_moptions **, struct mbuf *);