diff options
author | Cedric Berger <cedric@cvs.openbsd.org> | 2004-06-06 16:49:10 +0000 |
---|---|---|
committer | Cedric Berger <cedric@cvs.openbsd.org> | 2004-06-06 16:49:10 +0000 |
commit | 9e25ab1fcd3c8a3b75b6ae3c7ca26a172a86d2e8 (patch) | |
tree | 021044703db486221cd747d714184ece1513b162 /sys/netinet | |
parent | ac4791c970556454694a0c9ab754ea95de5b9bc1 (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.h | 13 | ||||
-rw-r--r-- | sys/netinet/in_pcb.c | 5 | ||||
-rw-r--r-- | sys/netinet/ip_icmp.c | 6 | ||||
-rw-r--r-- | sys/netinet/ip_input.c | 39 | ||||
-rw-r--r-- | sys/netinet/ip_output.c | 41 | ||||
-rw-r--r-- | sys/netinet/ip_var.h | 4 |
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 *); |