[prev in list] [next in list] [prev in thread] [next in thread]
List: openbsd-bugs
Subject: kernel/883: ip_nat fights with multihomed net
From: Geoff Steckel <gwes () oat ! com>
Date: 1999-07-25 14:20:57
[Download RAW message or body]
>Number: 883
>Category: kernel
>Synopsis: ipnat mapping fails on multihomed network
>Confidential: no
>Severity: serious
>Priority: low
>Responsible: bugs
>State: open
>Class: change-request
>Submitter-Id: net
>Arrival-Date: Sun Jul 25 13:20:02 MDT 1999
>Last-Modified:
>Originator: Geoff Steckel
>Organization:
Omnivore Technology
net
>Release: 2.5
>Environment:
System : OpenBSD 2.5
Architecture: OpenBSD.i386
Machine : i386
>Description:
ip_nat.c attempts to recognize outgoing packets which correspond
to a connection initiated from outside by comparing destination interface
address and port #s. This fails on a multihomed host/net if the
default outbound interface is not the same as the interface on which
the incoming connection request was received. Instead, a new port
number will be assigned and a new nat structure created. This results
in connections in the SYN_SENT state which are hung.
>How-To-Repeat:
Set up a host with two interfaces pointing to two gateways to another network.
route default -gateway gw1
From another machine, attempt to telnet to victim host via the
address for if2. The connection will hang "half-established".
>Fix:
Change if_nat.{c,h} to allow multiple equivalent interfaces in
rdr and map ipnat entries. Use a syntax of
interfacename[,interfacename...]
so that no changes need be made to ipnat other than recompilation
and documentation.
The deltas between the original ipnat.{c,h} and what I'm running
with follow. The last time I looked, the "current" versions of these
files have not changed since 2.5.
*** ip_nat.h Tue Jul 13 18:27:33 1999
--- ip_nat.h.orig Tue Jul 13 14:31:20 1999
***************
*** 63,77 ****
struct nat *nat_next;
struct nat *nat_hnext[2];
struct nat **nat_hstart[2];
! void **nat_ifpp; /* potentially matching interfaces */
! int nat_ifpn ; /* # of potential interfaces */
int nat_dir;
} nat_t;
typedef struct ipnat {
struct ipnat *in_next;
! u_int in_ifpn ; /* # interfaces in array */
! void **in_ifpp; /* interface pointer array */
void *in_apr; /* proxy structure ptr */
u_int in_space;
u_int in_use;
--- 63,75 ----
struct nat *nat_next;
struct nat *nat_hnext[2];
struct nat **nat_hstart[2];
! void *nat_ifp;
int nat_dir;
} nat_t;
typedef struct ipnat {
struct ipnat *in_next;
! void *in_ifp; /* interface pointer */
void *in_apr; /* proxy structure ptr */
u_int in_space;
u_int in_use;
*** ip_nat.c Sun Jul 25 14:13:36 1999
--- ip_nat.c.orig Tue Jul 13 14:31:13 1999
***************
*** 214,226 ****
#if defined(_KERNEL) && !SOLARIS
int s;
#endif
- int i ;
- char *p, *q ;
- char namebuf[32] ;
nat = NULL; /* XXX gcc -Wuninitialized */
KMALLOC(nt, ipnat_t *, sizeof(*nt));
- nt->in_ifpp = NULL ;
if ((cmd == SIOCADNAT) || (cmd == SIOCRMNAT))
IRCOPY(data, (char *)&natd, sizeof(natd));
--- 214,222 ----
***************
*** 257,285 ****
break;
}
bcopy((char *)nat, (char *)n, sizeof(*n));
! /*
! * count interface names & allocate array of ptrs
! */
! for (i = 1, p = n->in_ifname ; p && *p ; p++, i++) {
! p = memchr(p, ',', strlen(p)) ;
! if (!p)
! break ;
! }
! n->in_ifpn = i ;
! KMALLOC(n->in_ifpp, void **, i * sizeof (void *)) ;
! for (i = 0, p = n->in_ifname ; i < n->in_ifpn ; i++) {
! q = memchr(p, ',', strlen(p)) ;
! if (q) {
! strncpy(namebuf, p, q - p) ;
! namebuf[q - p] = '\0' ;
! }
! else
! strcpy(namebuf, p) ;
! n->in_ifpp[i] = (void *)GETUNIT(namebuf) ;
! if (!n->in_ifpp[i])
! n->in_ifpp[i] = (void *)-1;
! p = q + 1 ;
! }
if (n->in_plabel[0] != '\0') {
n->in_apr = ap_match(n->in_p, n->in_plabel);
if (!n->in_apr) {
--- 253,261 ----
break;
}
bcopy((char *)nat, (char *)n, sizeof(*n));
! n->in_ifp = (void *)GETUNIT(n->in_ifname);
! if (!n->in_ifp)
! n->in_ifp = (void *)-1;
if (n->in_plabel[0] != '\0') {
n->in_apr = ap_match(n->in_p, n->in_plabel);
if (!n->in_apr) {
***************
*** 326,332 ****
if (!n->in_use) {
if (n->in_apr)
ap_free(n->in_apr);
- KFREE(n->in_ifpp) ;
KFREE(n);
nat_stats.ns_rules--;
} else {
--- 302,307 ----
***************
*** 387,397 ****
}
RWLOCK_EXIT(&ipf_nat); /* READ/WRITE */
SPL_X(s);
! if (nt) {
! if (nt->in_ifpp)
! KFREE(nt->in_ifpp) ;
KFREE(nt);
- }
return error;
}
--- 362,369 ----
}
RWLOCK_EXIT(&ipf_nat); /* READ/WRITE */
SPL_X(s);
! if (nt)
KFREE(nt);
return error;
}
***************
*** 430,436 ****
if (!ipn->in_use && (ipn->in_flags & IPN_DELETE)) {
if (ipn->in_apr)
ap_free(ipn->in_apr);
- KFREE(ipn->in_ifpp) ;
KFREE(ipn);
nat_stats.ns_rules--;
}
--- 402,407 ----
***************
*** 485,491 ****
if (!n->in_use) {
if (n->in_apr)
ap_free(n->in_apr);
- KFREE(n->in_ifpp) ;
KFREE(n);
nat_stats.ns_rules--;
} else {
--- 456,461 ----
***************
*** 591,607 ****
}
/* Give me a new nat */
! KMALLOC(nat, nat_t *, sizeof(*nat) + np->in_ifpn * sizeof (void *));
if (nat == NULL)
return NULL;
bzero((char *)nat, sizeof(*nat));
nat->nat_flags = flags;
- nat->nat_ifpp = (void **) (nat + 1) ;
- nat->nat_ifpn = np->in_ifpn ;
- bcopy((char *) np->in_ifpp, (char *) nat->nat_ifpp,
- np->in_ifpn * sizeof (void *)) ;
-
/*
* Search the current table for a match.
*/
--- 561,573 ----
}
/* Give me a new nat */
! KMALLOC(nat, nat_t *, sizeof(*nat));
if (nat == NULL)
return NULL;
+
bzero((char *)nat, sizeof(*nat));
nat->nat_flags = flags;
/*
* Search the current table for a match.
*/
***************
*** 776,784 ****
nat->nat_ptr = np;
nat->nat_bytes = 0;
nat->nat_pkts = 0;
- #if 0
nat->nat_ifp = fin->fin_ifp;
- #endif
nat->nat_dir = direction;
nat->nat_age = fr_defnatage;
if (direction == NAT_OUTBOUND) {
--- 742,748 ----
***************
*** 953,979 ****
#endif
{
register nat_t *nat;
- int i ;
flags &= IPN_TCPUDP;
nat = nat_table[1][mapdst.s_addr % NAT_SIZE];
! for (; nat; nat = nat->nat_hnext[1]) {
! if (ifp) {
! for (i = 0 ; i < nat->nat_ifpn ; i++)
! if (ifp == nat->nat_ifpp[i])
! goto match ;
! continue ;
! }
! match:
! if (
nat->nat_oip.s_addr == src.s_addr &&
nat->nat_outip.s_addr == mapdst.s_addr &&
flags == nat->nat_flags && (!flags ||
(nat->nat_oport == sport &&
nat->nat_outport == mapdport)))
return nat;
- }
return NULL;
}
--- 917,934 ----
#endif
{
register nat_t *nat;
flags &= IPN_TCPUDP;
nat = nat_table[1][mapdst.s_addr % NAT_SIZE];
! for (; nat; nat = nat->nat_hnext[1])
! if ((!ifp || ifp == nat->nat_ifp) &&
nat->nat_oip.s_addr == src.s_addr &&
nat->nat_outip.s_addr == mapdst.s_addr &&
flags == nat->nat_flags && (!flags ||
(nat->nat_oport == sport &&
nat->nat_outport == mapdport)))
return nat;
return NULL;
}
***************
*** 995,1014 ****
#endif
{
register nat_t *nat;
- int i ;
flags &= IPN_TCPUDP;
nat = nat_table[0][src.s_addr % NAT_SIZE];
for (; nat; nat = nat->nat_hnext[0]) {
! if (ifp) {
! for (i = 0 ; i < nat->nat_ifpn ; i++)
! if (ifp == nat->nat_ifpp[i])
! goto match ;
! continue ;
! }
! match:
! if (
nat->nat_inip.s_addr == src.s_addr &&
nat->nat_oip.s_addr == dst.s_addr &&
flags == nat->nat_flags && (!flags ||
--- 950,961 ----
#endif
{
register nat_t *nat;
flags &= IPN_TCPUDP;
nat = nat_table[0][src.s_addr % NAT_SIZE];
for (; nat; nat = nat->nat_hnext[0]) {
! if ((!ifp || ifp == nat->nat_ifp) &&
nat->nat_inip.s_addr == src.s_addr &&
nat->nat_oip.s_addr == dst.s_addr &&
flags == nat->nat_flags && (!flags ||
***************
*** 1035,1061 ****
#endif
{
register nat_t *nat;
- int i ;
flags &= IPN_TCPUDP;
nat = nat_table[1][mapsrc.s_addr % NAT_SIZE];
! for (; nat; nat = nat->nat_hnext[0]) {
! if (ifp) {
! for (i = 0 ; i < nat->nat_ifpn ; i++)
! if (ifp == nat->nat_ifpp[i])
! goto match ;
! continue ;
! }
! match:
! if (
nat->nat_oip.s_addr == dst.s_addr &&
nat->nat_outip.s_addr == mapsrc.s_addr &&
flags == nat->nat_flags && (!flags ||
(nat->nat_outport == mapsport &&
nat->nat_oport == dport)))
return nat;
- }
return NULL;
}
--- 982,999 ----
#endif
{
register nat_t *nat;
flags &= IPN_TCPUDP;
nat = nat_table[1][mapsrc.s_addr % NAT_SIZE];
! for (; nat; nat = nat->nat_hnext[0])
! if ((!ifp || ifp == nat->nat_ifp) &&
nat->nat_oip.s_addr == dst.s_addr &&
nat->nat_outip.s_addr == mapsrc.s_addr &&
flags == nat->nat_flags && (!flags ||
(nat->nat_outport == mapsport &&
nat->nat_oport == dport)))
return nat;
return NULL;
}
***************
*** 1099,1105 ****
frentry_t *fr;
nat_t *nat;
int natadd = 1;
- int i ;
if ((fr = fin->fin_fr) && !(fr->fr_flags & FR_DUP) &&
fr->fr_tif.fd_ifp && fr->fr_tif.fd_ifp != (void *)-1)
--- 1037,1042 ----
***************
*** 1135,1147 ****
* If there is no current entry in the nat table for this IP#,
* create one for it (if there is a matching rule).
*/
! for (np = nat_list; np; np = np->in_next) {
! for (i = 0 ; i < np->in_ifpn ; i++)
! if (ifp == np->in_ifpp[i])
! goto match ;
! continue ;
! match:
! if (np->in_space &&
(!np->in_flags || (np->in_flags & nflags)) &&
((ipa & np->in_inmsk) == np->in_inip) &&
((np->in_redir & NAT_MAP) ||
--- 1072,1079 ----
* If there is no current entry in the nat table for this IP#,
* create one for it (if there is a matching rule).
*/
! for (np = nat_list; np; np = np->in_next)
! if ((np->in_ifp == ifp) && np->in_space &&
(!np->in_flags || (np->in_flags & nflags)) &&
((ipa & np->in_inmsk) == np->in_inip) &&
((np->in_redir & NAT_MAP) ||
***************
*** 1165,1171 ****
#endif
break;
}
- }
MUTEX_DOWNGRADE(&ipf_nat);
}
--- 1097,1102 ----
***************
*** 1254,1260 ****
u_short sport = 0, dport = 0, *csump = NULL;
nat_t *nat;
int nflags = 0, natadd = 1;
- int i ;
if (!(ip->ip_off & IP_OFFMASK) && !(fin->fin_fi.fi_fl & FI_SHORT)) {
if (ip->ip_p == IPPROTO_TCP)
--- 1185,1190 ----
***************
*** 1287,1299 ****
* If there is no current entry in the nat table for this IP#,
* create one for it (if there is a matching rule).
*/
! for (np = nat_list; np; np = np->in_next) {
! for (i = 0 ; i < np->in_ifpn ; i++)
! if (np->in_ifpp[i] == ifp)
! goto match ;
! continue ;
! match:
! if (
(!np->in_flags || (nflags & np->in_flags)) &&
((in.s_addr & np->in_outmsk) == np->in_outip) &&
(np->in_redir & NAT_REDIRECT) &&
--- 1217,1224 ----
* If there is no current entry in the nat table for this IP#,
* create one for it (if there is a matching rule).
*/
! for (np = nat_list; np; np = np->in_next)
! if ((np->in_ifp == ifp) &&
(!np->in_flags || (nflags & np->in_flags)) &&
((in.s_addr & np->in_outmsk) == np->in_outip) &&
(np->in_redir & NAT_REDIRECT) &&
***************
*** 1307,1313 ****
#endif
break;
}
- }
MUTEX_DOWNGRADE(&ipf_nat);
}
if (nat) {
--- 1232,1237 ----
***************
*** 1426,1432 ****
/*
- * Adjust mappings on change of IP address
*/
#ifdef __STDC__
void ip_natsync(void *ifp)
--- 1350,1355 ----
***************
*** 1442,1454 ****
#if defined(_KERNEL) && !SOLARIS
int s;
#endif
- int i ;
SPL_NET(s);
WRITE_ENTER(&ipf_nat);
for (nat = nat_instances; nat; nat = nat->nat_next)
! for (i = 0 ; i < nat->nat_ifpn ; i++)
! if ((ifp == nat->nat_ifpp[i]) && (np = nat->nat_ptr))
if ((np->in_outmsk == 0xffffffff) && !np->in_nip) {
/*
* Change the map-to address to be the same
--- 1365,1375 ----
#if defined(_KERNEL) && !SOLARIS
int s;
#endif
SPL_NET(s);
WRITE_ENTER(&ipf_nat);
for (nat = nat_instances; nat; nat = nat->nat_next)
! if ((ifp == nat->nat_ifp) && (np = nat->nat_ptr))
if ((np->in_outmsk == 0xffffffff) && !np->in_nip) {
/*
* Change the map-to address to be the same
>Audit-Trail:
>Unformatted:
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic