summaryrefslogtreecommitdiff
path: root/sys/netinet
diff options
context:
space:
mode:
authorTheo de Raadt <deraadt@cvs.openbsd.org>1999-02-05 05:58:55 +0000
committerTheo de Raadt <deraadt@cvs.openbsd.org>1999-02-05 05:58:55 +0000
commite689014cc2747748c76a2b3f492470f1362031e2 (patch)
tree30f2062ed5c01f4b6d08d952c92e6e0c432b485f /sys/netinet
parent20a077f722546853c96c85750162a4b9c096033b (diff)
ipf 3.2.10; work by kjell
Diffstat (limited to 'sys/netinet')
-rw-r--r--sys/netinet/fil.c220
-rw-r--r--sys/netinet/ip_auth.c17
-rw-r--r--sys/netinet/ip_auth.h6
-rw-r--r--sys/netinet/ip_fil.c23
-rw-r--r--sys/netinet/ip_fil.h59
-rw-r--r--sys/netinet/ip_fil_compat.h91
-rw-r--r--sys/netinet/ip_frag.c34
-rw-r--r--sys/netinet/ip_frag.h6
-rw-r--r--sys/netinet/ip_ftp_pxy.c381
-rw-r--r--sys/netinet/ip_log.c59
-rw-r--r--sys/netinet/ip_nat.c283
-rw-r--r--sys/netinet/ip_nat.h19
-rw-r--r--sys/netinet/ip_proxy.c270
-rw-r--r--sys/netinet/ip_proxy.h45
-rw-r--r--sys/netinet/ip_state.c51
-rw-r--r--sys/netinet/ip_state.h7
16 files changed, 964 insertions, 607 deletions
diff --git a/sys/netinet/fil.c b/sys/netinet/fil.c
index 91f7bcae0b1..004cd4dd9e7 100644
--- a/sys/netinet/fil.c
+++ b/sys/netinet/fil.c
@@ -1,6 +1,6 @@
-/* $OpenBSD: fil.c,v 1.13 1998/09/15 09:51:17 pattonme Exp $ */
+/* $OpenBSD: fil.c,v 1.14 1999/02/05 05:58:49 deraadt Exp $ */
/*
- * Copyright (C) 1993-1997 by Darren Reed.
+ * Copyright (C) 1993-1998 by Darren Reed.
*
* Redistribution and use in source and binary forms are permitted
* provided that this notice is preserved and due credit is given
@@ -8,7 +8,7 @@
*/
#if !defined(lint)
static const char sccsid[] = "@(#)fil.c 1.36 6/5/96 (C) 1993-1996 Darren Reed";
-static const char rcsid[] = "@(#)$Id: fil.c,v 1.13 1998/09/15 09:51:17 pattonme Exp $";
+static const char rcsid[] = "@(#)$Id: fil.c,v 1.14 1999/02/05 05:58:49 deraadt Exp $";
#endif
#include <sys/errno.h>
@@ -31,7 +31,9 @@ static const char rcsid[] = "@(#)$Id: fil.c,v 1.13 1998/09/15 09:51:17 pattonme
# endif
#else
# include <sys/byteorder.h>
+# if SOLARIS2 < 5
# include <sys/dditypes.h>
+# endif
# include <sys/stream.h>
#endif
#ifndef linux
@@ -93,13 +95,8 @@ extern int opts;
# define FR_VERBOSE(verb_pr)
# define FR_DEBUG(verb_pr)
# define IPLLOG(a, c, d, e) ipflog(a, c, d, e)
-# if SOLARIS
-extern krwlock_t ipf_mutex, ipf_auth;
-# endif
-# if defined(__sgi)
-extern kmutex_t ipf_mutex, ipf_auth;
-# endif
# if SOLARIS || defined(__sgi)
+extern KRWLOCK_T ipf_mutex, ipf_auth;
extern kmutex_t ipf_rw;
# endif
# if SOLARIS
@@ -206,7 +203,6 @@ fr_info_t *fin;
{
struct optlist *op;
tcphdr_t *tcp;
- icmphdr_t *icmp;
fr_ip_t *fi = &fin->fin_fi;
u_short optmsk = 0, secmsk = 0, auth = 0;
int i, mv, ol, off;
@@ -227,14 +223,13 @@ fr_info_t *fin;
fin->fin_hlen = hlen;
fin->fin_dlen = ip->ip_len - hlen;
tcp = (tcphdr_t *)((char *)ip + hlen);
- icmp = (icmphdr_t *)tcp;
fin->fin_dp = (void *)tcp;
(*(((u_short *)fi) + 1)) = (*(((u_short *)ip) + 4));
(*(((u_32_t *)fi) + 1)) = (*(((u_32_t *)ip) + 3));
(*(((u_32_t *)fi) + 2)) = (*(((u_32_t *)ip) + 4));
fi->fi_fl = (hlen > sizeof(ip_t)) ? FI_OPTIONS : 0;
- off = (ip->ip_off & 0x1fff) << 3;
+ off = (ip->ip_off & IP_OFFMASK) << 3;
if (ip->ip_off & 0x3fff)
fi->fi_fl |= FI_FRAG;
switch (ip->ip_p)
@@ -242,10 +237,12 @@ fr_info_t *fin;
case IPPROTO_ICMP :
{
int minicmpsz = sizeof(struct icmp);
+ icmphdr_t *icmp;
- if (!off && ip->ip_len > ICMP_MINLEN + hlen &&
- (icmp->icmp_type == ICMP_ECHOREPLY ||
- icmp->icmp_type == ICMP_UNREACH))
+ icmp = (icmphdr_t *)tcp;
+
+ if (!off && (icmp->icmp_type == ICMP_ECHOREPLY ||
+ icmp->icmp_type == ICMP_ECHO))
minicmpsz = ICMP_MINLEN;
if ((!(ip->ip_len >= hlen + minicmpsz) && !off) ||
(off && off < sizeof(struct icmp)))
@@ -408,7 +405,7 @@ fr_info_t *fin;
/*
* Match the flags ? If not, abort this match.
*/
- if (fr->fr_tcpf &&
+ if (fr->fr_tcpfm &&
fr->fr_tcpf != (fin->fin_tcpf & fr->fr_tcpfm)) {
FR_DEBUG(("f. %#x & %#x != %#x\n", fin->fin_tcpf,
fr->fr_tcpfm, fr->fr_tcpf));
@@ -437,7 +434,7 @@ void *m;
fin->fin_fr = NULL;
fin->fin_rule = 0;
fin->fin_group = 0;
- off = ip->ip_off & 0x1fff;
+ off = ip->ip_off & IP_OFFMASK;
pass |= (fi->fi_fl << 24);
if ((fi->fi_fl & FI_TCPUDP) && (fin->fin_dlen > 3) && !off)
@@ -557,7 +554,7 @@ void *m;
/*
* frcheck - filter check
- * check using source and destination addresses/pors in a packet whether
+ * check using source and destination addresses/ports in a packet whether
* or not to pass it on or not.
*/
int fr_check(ip, hlen, ifp, out
@@ -605,19 +602,20 @@ int out;
ip->ip_p == IPPROTO_ICMP)) {
int plen = 0;
- switch(ip->ip_p)
- {
- case IPPROTO_TCP:
- plen = sizeof(tcphdr_t);
- break;
- case IPPROTO_UDP:
- plen = sizeof(udphdr_t);
- break;
- case IPPROTO_ICMP:
+ if ((ip->ip_off & IP_OFFMASK) == 0)
+ switch(ip->ip_p)
+ {
+ case IPPROTO_TCP:
+ plen = sizeof(tcphdr_t);
+ break;
+ case IPPROTO_UDP:
+ plen = sizeof(udphdr_t);
+ break;
/* 96 - enough for complete ICMP error IP header */
- plen = sizeof(struct icmp) + sizeof(ip_t) + 8;
- break;
- }
+ case IPPROTO_ICMP:
+ plen = 76 + sizeof(struct icmp);
+ break;
+ }
up = MIN(hlen + plen, ip->ip_len);
if (up > m->m_len) {
@@ -957,63 +955,90 @@ ip_t *ip;
tcphdr_t *tcp;
int len;
{
+ u_short *sp, slen, ts;
+ u_int sum, sum2;
+ int hlen;
+
+
+ /*
+ * Add up IP Header portion
+ */
+ hlen = ip->ip_hl << 2;
+ slen = ip->ip_len - hlen;
+ sum = htons(ip->ip_p);
+ sum += htons(slen);
+ sp = (u_short *)&ip->ip_src;
+ sum += *sp++; /* ip_src */
+ sum += *sp++;
+ sum += *sp++; /* ip_dst */
+ sum += *sp++;
+ ts = tcp->th_sum;
+ tcp->th_sum = 0;
+#ifdef KERNEL
+# if SOLARIS
+ sum2 = ip_cksum(m, hlen, sum);
+ sum2 = (sum2 & 0xffff) + (sum2 >> 16);
+ sum2 = ~sum2 & 0xffff;
+# else /* SOLARIS */
+# if defined(BSD) || defined(sun)
+# if BSD >= 199306
+ m->m_data += hlen;
+# else
+ m->m_off += hlen;
+# endif
+ m->m_len -= hlen;
+ sum2 = in_cksum(m, slen);
+ m->m_len += hlen;
+# if BSD >= 199306
+ m->m_data -= hlen;
+# else
+ m->m_off -= hlen;
+# endif
+ /*
+ * Both sum and sum2 are partial sums, so combine them together.
+ */
+ sum = (sum & 0xffff) + (sum >> 16);
+ sum = ~sum & 0xffff;
+ sum2 += sum;
+ sum2 = (sum2 & 0xffff) + (sum2 >> 16);
+# else /* defined(BSD) || defined(sun) */
+{
+
union {
u_char c[2];
u_short s;
} bytes;
u_32_t sum;
- u_short *sp;
-# if SOLARIS || defined(__sgi)
- int add, hlen;
+ u_short *sp, slen;
+# if defined(__sgi)
+ int add;
# endif
/*
* Add up IP Header portion
*/
- bytes.c[0] = 0;
- bytes.c[1] = IPPROTO_TCP;
+ sp = (u_short *)&ip->ip_src;
len -= (ip->ip_hl << 2);
- sum = bytes.s;
+ sum = ntohs(IPPROTO_TCP);
sum += htons((u_short)len);
- sp = (u_short *)&ip->ip_src;
- sum += *sp++;
- sum += *sp++;
+ sum += *sp++; /* ip_src */
sum += *sp++;
+ sum += *sp++; /* ip_dst */
sum += *sp++;
if (sp != (u_short *)tcp)
sp = (u_short *)tcp;
+ sum += *sp++; /* sport */
+ sum += *sp++; /* dport */
+ sum += *sp++; /* seq */
sum += *sp++;
+ sum += *sp++; /* ack */
sum += *sp++;
- sum += *sp++;
- sum += *sp++;
- sum += *sp++;
- sum += *sp++;
- sum += *sp++;
- sum += *sp;
+ sum += *sp++; /* off */
+ sum += *sp; /* win */
sp += 2; /* Skip over checksum */
- sum += *sp++;
+ sum += *sp++; /* urp */
-#if SOLARIS
- /*
- * In case we had to copy the IP & TCP header out of mblks,
- * skip over the mblk bits which are the header
- */
- if ((caddr_t)ip != (caddr_t)m->b_rptr) {
- hlen = (caddr_t)sp - (caddr_t)ip;
- while (hlen) {
- add = MIN(hlen, m->b_wptr - m->b_rptr);
- sp = (u_short *)((caddr_t)m->b_rptr + add);
- hlen -= add;
- if ((caddr_t)sp >= (caddr_t)m->b_wptr) {
- m = m->b_cont;
- PANIC((!m),("fr_tcpsum: not enough data"));
- if (!hlen)
- sp = (u_short *)m->b_rptr;
- }
- }
- }
-#endif
-#ifdef __sgi
+# ifdef __sgi
/*
* In case we had to copy the IP & TCP header out of mbufs,
* skip over the mbuf bits which are the header
@@ -1024,52 +1049,57 @@ int len;
add = MIN(hlen, m->m_len);
sp = (u_short *)(mtod(m, caddr_t) + add);
hlen -= add;
- if (add >= m->m_len) {
+ if (add == m->m_len) {
m = m->m_next;
- PANIC((!m),("fr_tcpsum: not enough data"));
- if (!hlen)
+ if (!hlen) {
+ if (!m)
+ break;
sp = mtod(m, u_short *);
+ }
+ PANIC((!m),("fr_tcpsum(1): not enough data"));
}
}
}
-#endif
+# endif
if (!(len -= sizeof(*tcp)))
goto nodata;
- while (len > 0) {
-#if SOLARIS
- while ((caddr_t)sp >= (caddr_t)m->b_wptr) {
- m = m->b_cont;
- PANIC((!m),("fr_tcpsum: not enough data"));
- sp = (u_short *)m->b_rptr;
+ while (len > 1) {
+ if (((caddr_t)sp - mtod(m, caddr_t)) >= m->m_len) {
+ m = m->m_next;
+ PANIC((!m),("fr_tcpsum(2): not enough data"));
+ sp = mtod(m, u_short *);
}
-#else
- while (((caddr_t)sp - mtod(m, caddr_t)) >= m->m_len)
- {
+ if (((caddr_t)(sp + 1) - mtod(m, caddr_t)) > m->m_len) {
+ bytes.c[0] = *(u_char *)sp;
m = m->m_next;
- PANIC((!m),("fr_tcpsum: not enough data"));
+ PANIC((!m),("fr_tcpsum(3): not enough data"));
sp = mtod(m, u_short *);
+ bytes.c[1] = *(u_char *)sp;
+ sum += bytes.s;
+ sp = (u_short *)((u_char *)sp + 1);
}
-#endif /* SOLARIS */
- if (len < 2)
- break;
- if((u_long)sp & 1) {
+ if ((u_long)sp & 1) {
bcopy((char *)sp++, (char *)&bytes.s, sizeof(bytes.s));
sum += bytes.s;
} else
sum += *sp++;
len -= 2;
}
- if (len) {
- bytes.c[1] = 0;
- bytes.c[0] = *(u_char *)sp;
- sum += bytes.s;
- }
+ if (len)
+ sum += ntohs(*(u_char *)sp << 8);
nodata:
- sum = (sum >> 16) + (sum & 0xffff);
- sum += (sum >> 16);
- sum = (u_short)((~sum) & 0xffff);
- return sum;
+ while (sum > 0xffff)
+ sum = (sum & 0xffff) + (sum >> 16);
+ sum2 = (u_short)(~sum & 0xffff);
+}
+# endif /* defined(BSD) || defined(sun) */
+# endif /* SOLARIS */
+#else /* KERNEL */
+ sum2 = 0;
+#endif /* KERNEL */
+ tcp->th_sum = ts;
+ return sum2;
}
@@ -1107,7 +1137,7 @@ nodata:
* SUCH DAMAGE.
*
* @(#)uipc_mbuf.c 8.2 (Berkeley) 1/4/94
- * $Id: fil.c,v 1.13 1998/09/15 09:51:17 pattonme Exp $
+ * $Id: fil.c,v 1.14 1999/02/05 05:58:49 deraadt Exp $
*/
/*
* Copy data from an mbuf chain starting "off" bytes from the beginning,
diff --git a/sys/netinet/ip_auth.c b/sys/netinet/ip_auth.c
index fb7d9b660f3..e41404626ff 100644
--- a/sys/netinet/ip_auth.c
+++ b/sys/netinet/ip_auth.c
@@ -1,24 +1,25 @@
-/* $OpenBSD: ip_auth.c,v 1.4 1998/09/15 09:51:17 pattonme Exp $ */
+/* $OpenBSD: ip_auth.c,v 1.5 1999/02/05 05:58:49 deraadt Exp $ */
/*
- * Copyright (C) 1997 by Darren Reed & Guido van Rooij.
+ * Copyright (C) 1998 by Darren Reed & Guido van Rooij.
*
* Redistribution and use in source and binary forms are permitted
* provided that this notice is preserved and due credit is given
* to the original author and the contributors.
*/
#if !defined(lint)
-static const char rcsid[] = "@(#)$Id: ip_auth.c,v 1.4 1998/09/15 09:51:17 pattonme Exp $";
+static const char rcsid[] = "@(#)$Id: ip_auth.c,v 1.5 1999/02/05 05:58:49 deraadt Exp $";
#endif
-#if !defined(_KERNEL) && !defined(KERNEL)
-# include <stdlib.h>
-# include <string.h>
-#endif
#include <sys/errno.h>
#include <sys/types.h>
#include <sys/param.h>
#include <sys/time.h>
#include <sys/file.h>
+#if !defined(_KERNEL) && !defined(KERNEL)
+# include <stdio.h>
+# include <stdlib.h>
+# include <string.h>
+#endif
#if defined(KERNEL) && (__FreeBSD_version >= 220000)
# include <sys/filio.h>
# include <sys/fcntl.h>
@@ -98,7 +99,7 @@ extern struct ifqueue ipintrq; /* ip packet input queue */
#if (SOLARIS || defined(__sgi)) && defined(_KERNEL)
-extern krwlock_t ipf_auth;
+extern KRWLOCK_T ipf_auth;
extern kmutex_t ipf_authmx;
# if SOLARIS
extern kcondvar_t ipfauthwait;
diff --git a/sys/netinet/ip_auth.h b/sys/netinet/ip_auth.h
index bf058fbc007..71c1c43ff6f 100644
--- a/sys/netinet/ip_auth.h
+++ b/sys/netinet/ip_auth.h
@@ -1,12 +1,12 @@
-/* $OpenBSD: ip_auth.h,v 1.2 1998/02/17 01:39:02 dgregor Exp $ */
+/* $OpenBSD: ip_auth.h,v 1.3 1999/02/05 05:58:50 deraadt Exp $ */
/*
- * Copyright (C) 1997 by Darren Reed & Guido Van Rooij.
+ * Copyright (C) 1997-1998 by Darren Reed & Guido Van Rooij.
*
* Redistribution and use in source and binary forms are permitted
* provided that this notice is preserved and due credit is given
* to the original author and the contributors.
*
- * $Id: ip_auth.h,v 1.2 1998/02/17 01:39:02 dgregor Exp $
+ * $Id: ip_auth.h,v 1.3 1999/02/05 05:58:50 deraadt Exp $
*
*/
#ifndef __IP_AUTH_H__
diff --git a/sys/netinet/ip_fil.c b/sys/netinet/ip_fil.c
index 8baf73cf264..02d5728de22 100644
--- a/sys/netinet/ip_fil.c
+++ b/sys/netinet/ip_fil.c
@@ -1,6 +1,6 @@
-/* $OpenBSD: ip_fil.c,v 1.19 1998/09/15 09:51:17 pattonme Exp $ */
+/* $OpenBSD: ip_fil.c,v 1.20 1999/02/05 05:58:50 deraadt Exp $ */
/*
- * Copyright (C) 1993-1997 by Darren Reed.
+ * Copyright (C) 1993-1998 by Darren Reed.
*
* Redistribution and use in source and binary forms are permitted
* provided that this notice is preserved and due credit is given
@@ -8,7 +8,7 @@
*/
#if !defined(lint)
static const char sccsid[] = "@(#)ip_fil.c 2.41 6/5/96 (C) 1993-1995 Darren Reed";
-static const char rcsid[] = "@(#)$Id: ip_fil.c,v 1.19 1998/09/15 09:51:17 pattonme Exp $";
+static const char rcsid[] = "@(#)$Id: ip_fil.c,v 1.20 1999/02/05 05:58:50 deraadt Exp $";
#endif
#ifndef SOLARIS
@@ -141,6 +141,9 @@ static int frrequest __P((int, int, caddr_t, int));
#endif
#ifdef _KERNEL
static int (*fr_savep) __P((ip_t *, int, void *, int, struct mbuf **));
+# ifdef __sgi
+extern kmutex_t ipf_rw;
+# endif
#else
int ipllog __P((void));
void init_ifp __P((void));
@@ -1006,9 +1009,16 @@ frdest_t *fdp;
/*
* For input packets which are being "fastrouted", they won't
* go back through output filtering and miss their chance to get
- * NAT'd.
+ * NAT'd and counted.
*/
- (void) ip_natout(ip, hlen, fin);
+ if (fin->fin_out == 0) {
+ if ((fin->fin_fr = ipacct[1][fr_active]) &&
+ (FR_SCANLIST(FR_NOMATCH, ip, fin, m) & FR_ACCOUNT)) {
+ ATOMIC_INC(frstats[1].fr_acct);
+ }
+ fin->fin_fr = NULL;
+ (void) ip_natout(ip, hlen, fin);
+ }
if (fin->fin_out)
ip->ip_sum = 0;
/*
@@ -1124,9 +1134,8 @@ done:
else
ipl_frouteok[1]++;
- if (ro->ro_rt) {
+ if (ro->ro_rt)
RTFREE(ro->ro_rt);
- }
return;
bad:
m_freem(m);
diff --git a/sys/netinet/ip_fil.h b/sys/netinet/ip_fil.h
index 7ece4cbb8da..0340b0676e6 100644
--- a/sys/netinet/ip_fil.h
+++ b/sys/netinet/ip_fil.h
@@ -1,18 +1,22 @@
-/* $OpenBSD: ip_fil.h,v 1.11 1998/09/15 09:51:18 pattonme Exp $ */
+/* $OpenBSD: ip_fil.h,v 1.12 1999/02/05 05:58:50 deraadt Exp $ */
/*
- * Copyright (C) 1993-1997 by Darren Reed.
+ * Copyright (C) 1993-1998 by Darren Reed.
*
* Redistribution and use in source and binary forms are permitted
* provided that this notice is preserved and due credit is given
* to the original author and the contributors.
*
* @(#)ip_fil.h 1.35 6/5/96
- * $Id: ip_fil.h,v 1.11 1998/09/15 09:51:18 pattonme Exp $
+ * $Id: ip_fil.h,v 1.12 1999/02/05 05:58:50 deraadt Exp $
*/
#ifndef __IP_FIL_H__
#define __IP_FIL_H__
+#if defined(__NetBSD__) && defined(PFIL_HOOKS)
+#include "opt_pfil_hooks.h"
+#endif
+
/*
* Pathnames for various IP Filter control devices. Used by LKM
* and userland, so defined here.
@@ -85,14 +89,14 @@
typedef struct fr_ip {
u_char fi_v:4; /* IP version */
u_char fi_fl:4; /* packet flags */
- u_char fi_tos;
- u_char fi_ttl;
- u_char fi_p;
- struct in_addr fi_src;
- struct in_addr fi_dst;
+ u_char fi_tos; /* IP packet TOS */
+ u_char fi_ttl; /* IP packet TTL */
+ u_char fi_p; /* IP packet protocol */
+ struct in_addr fi_src; /* source address from packet */
+ struct in_addr fi_dst; /* destination address from packet */
u_32_t fi_optmsk; /* bitmask composed from IP options */
u_short fi_secmsk; /* bitmask composed from IP security options */
- u_short fi_auth;
+ u_short fi_auth; /* authentication code from IP sec. options */
} fr_ip_t;
#define FI_OPTIONS (FF_OPTIONS >> 24)
@@ -101,34 +105,35 @@ typedef struct fr_ip {
#define FI_SHORT (FF_SHORT >> 24)
typedef struct fr_info {
- struct fr_ip fin_fi;
- u_short fin_data[2];
- u_short fin_out;
- u_short fin_hlen;
- u_char fin_tcpf;
- u_char fin_icode; /* From here on is packet specific */
- u_short fin_rule;
- u_short fin_group;
- u_short fin_dlen;
- u_short fin_id;
- void *fin_ifp;
- struct frentry *fin_fr;
+ struct fr_ip fin_fi; /* IP Packet summary */
+ u_short fin_data[2]; /* TCP/UDP ports, ICMP code/type */
+ u_short fin_out; /* in or out ? 1 == out, 0 == in */
+ u_short fin_hlen; /* length of IP header in bytes */
+ u_char fin_tcpf; /* TCP header flags (SYN, ACK, etc) */
+ /* From here on is packet specific */
+ u_char fin_icode; /* ICMP error to return */
+ u_short fin_rule; /* rule # last matched */
+ u_short fin_group; /* group number, -1 for none */
+ u_short fin_dlen; /* length of data portion of packet */
+ u_short fin_id; /* IP packet id field */
+ void *fin_ifp; /* interface packet is `on' */
+ struct frentry *fin_fr; /* last matching rule */
char *fin_dp; /* start of data past IP header */
- void *fin_mp;
+ void *fin_mp; /* pointer to pointer to mbuf */
#if SOLARIS && defined(_KERNEL)
- void *fin_qfm;
+ void *fin_qfm; /* pointer to mblk where pkt starts */
#endif
} fr_info_t;
/*
* Size for compares on fr_info structures
*/
-#define FI_CSIZE (sizeof(struct fr_ip) + sizeof(u_short) * 4 + \
- sizeof(u_char))
+#define FI_CSIZE offsetof(fr_info_t, fin_icode)
+
/*
* Size for copying cache fr_info structure
*/
-#define FI_COPYSIZE (sizeof(fr_info_t) - sizeof(void *) * 2)
+#define FI_COPYSIZE offsetof(fr_info_t, fin_dp)
typedef struct frdest {
void *fd_ifp;
@@ -266,6 +271,8 @@ typedef struct filterstats {
u_long fr_tcpbad; /* TCP checksum check failures */
u_long fr_pull[2]; /* good and bad pullup attempts */
#if SOLARIS
+ u_long fr_notdata; /* PROTO/PCPROTO that have no data */
+ u_long fr_nodata; /* mblks that have no data */
u_long fr_bad; /* bad IP packets to the filter */
u_long fr_notip; /* packets passed through no on ip queue */
u_long fr_drop; /* packets dropped - no info for them! */
diff --git a/sys/netinet/ip_fil_compat.h b/sys/netinet/ip_fil_compat.h
index e098abfba05..e78149c266b 100644
--- a/sys/netinet/ip_fil_compat.h
+++ b/sys/netinet/ip_fil_compat.h
@@ -1,13 +1,13 @@
-/* $OpenBSD: ip_fil_compat.h,v 1.9 1998/09/15 09:51:18 pattonme Exp $ */
+/* $OpenBSD: ip_fil_compat.h,v 1.10 1999/02/05 05:58:51 deraadt Exp $ */
/*
- * Copyright (C) 1993-1997 by Darren Reed.
+ * Copyright (C) 1993-1998 by Darren Reed.
*
* Redistribution and use in source and binary forms are permitted
* provided that this notice is preserved and due credit is given
* to the original author and the contributors.
*
* @(#)ip_compat.h 1.8 1/14/96
- * $Id: ip_fil_compat.h,v 1.9 1998/09/15 09:51:18 pattonme Exp $
+ * $Id: ip_fil_compat.h,v 1.10 1999/02/05 05:58:51 deraadt Exp $
*/
#ifndef __IP_COMPAT_H__
@@ -26,25 +26,28 @@
#define SOLARIS (defined(sun) && (defined(__svr4__) || defined(__SVR4)))
#endif
-#if defined(_KERNEL) && !defined(KERNEL)
+#if defined(_KERNEL) || defined(KERNEL) || defined(__KERNEL__)
+# undef KERNEL
+# undef _KERNEL
+# undef __KERNEL__
# define KERNEL
-#endif
-#if defined(KERNEL) && !defined(_KERNEL)
# define _KERNEL
-#endif
-#if!defined(__KERNEL__) && defined(KERNEL)
# define __KERNEL__
#endif
#if defined(__SVR4) || defined(__svr4__) || defined(__sgi)
#define index strchr
-# if !defined(_KERNEL)
+# if !defined(KERNEL)
# define bzero(a,b) memset(a,0,b)
# define bcmp memcmp
# define bcopy(a,b,c) memmove(b,a,c)
# endif
#endif
+#ifndef offsetof
+#define offsetof(t,m) (int)((&((t *)0L)->m))
+#endif
+
#if defined(__sgi) || defined(bsdi)
struct ether_addr {
u_char ether_addr_octet[6];
@@ -81,7 +84,7 @@ struct ether_addr {
# undef IPOPT_LSRR
# undef IPOPT_RR
# undef IPOPT_SSRR
-# ifndef _KERNEL
+# ifndef KERNEL
# define _KERNEL
# undef RES_INIT
# include <inet/common.h>
@@ -207,10 +210,23 @@ typedef unsigned long u_32_t;
# define ATOMIC_DEC(x) { mutex_enter(&ipf_rw); (x)--; \
mutex_exit(&ipf_rw); }
# define MUTEX_ENTER(x) mutex_enter(x)
-# define READ_ENTER(x) rw_enter(x, RW_READER)
-# define WRITE_ENTER(x) rw_enter(x, RW_WRITER)
-# define MUTEX_DOWNGRADE(x) rw_downgrade(x)
-# define RWLOCK_EXIT(x) rw_exit(x)
+# if 1
+# define KRWLOCK_T krwlock_t
+# define READ_ENTER(x) rw_enter(x, RW_READER)
+# define WRITE_ENTER(x) rw_enter(x, RW_WRITER)
+# define MUTEX_DOWNGRADE(x) rw_downgrade(x)
+# define RWLOCK_INIT(x, y, z) rw_init((x), (y), RW_DRIVER, (z))
+# define RWLOCK_EXIT(x) rw_exit(x)
+# define RW_DESTROY(x) rw_destroy(x)
+# else
+# define KRWLOCK_T kmutex_t
+# define READ_ENTER(x) mutex_enter(x)
+# define WRITE_ENTER(x) mutex_enter(x)
+# define MUTEX_DOWNGRADE(x) ;
+# define RWLOCK_INIT(x, y, z) mutex_init((x), (y), MUTEX_DRIVER, (z))
+# define RWLOCK_EXIT(x) mutex_exit(x)
+# define RW_DESTROY(x) mutex_destroy(x)
+# endif
# define MUTEX_EXIT(x) mutex_exit(x)
# define MTOD(m,t) (t)((m)->b_rptr)
# define IRCOPY(a,b,c) copyin((a), (b), (c))
@@ -262,11 +278,12 @@ typedef struct {
lock_t *l;
int pl;
} kmutex_t;
-# define ATOMIC_INC(x) { MUTEX_ENTER(&ipf_rw); \
+# define ATOMIC_INC(x) { MUTEX_ENTER(&ipf_rw); \
(x)++; MUTEX_EXIT(&ipf_rw); }
-# define ATOMIC_DEC(x) { MUTEX_ENTER(&ipf_rw); \
+# define ATOMIC_DEC(x) { MUTEX_ENTER(&ipf_rw); \
(x)--; MUTEX_EXIT(&ipf_rw); }
# define MUTEX_ENTER(x) (x)->pl = LOCK((x)->l, IPF_LOCK_PL);
+# define KRWLOCK_T kmutex_t
# define READ_ENTER(x) MUTEX_ENTER(x)
# define WRITE_ENTER(x) MUTEX_ENTER(x)
# define MUTEX_DOWNGRADE(x) ;
@@ -386,7 +403,15 @@ extern vm_map_t kmem_map;
typedef mblk_t mb_t;
#else
# ifdef linux
+# ifndef kernel
+typedef struct mb {
+ struct mb *next;
+ u_int len;
+ u_char *data;
+} mb_t;
+# else
typedef struct sk_buff mb_t;
+# endif
# else
typedef struct mbuf mb_t;
# endif
@@ -521,6 +546,7 @@ typedef struct mbuf mb_t;
#endif /* linux || __sgi */
#ifdef linux
+#include <linux/in_systm.h>
/*
* TCP States
*/
@@ -542,8 +568,13 @@ typedef struct mbuf mb_t;
/*
* file flags.
*/
+#ifdef WRITE
#define FWRITE WRITE
#define FREAD READ
+#else
+#define FWRITE _IOC_WRITE
+#define FREAD _IOC_READ
+#endif
/*
* mbuf related problems.
*/
@@ -551,7 +582,10 @@ typedef struct mbuf mb_t;
#define m_len len
#define m_next next
-#define IP_DF 0x8000
+#ifdef IP_DF
+#undef IP_DF
+#endif
+#define IP_DF 0x4000
typedef struct {
__u16 th_sport;
@@ -603,15 +637,15 @@ typedef struct {
* Structure of an icmp header.
*/
typedef struct icmp {
- u_char icmp_type; /* type of message, see below */
- u_char icmp_code; /* type sub code */
- u_short icmp_cksum; /* ones complement cksum of struct */
+ __u8 icmp_type; /* type of message, see below */
+ __u8 icmp_code; /* type sub code */
+ __u16 icmp_cksum; /* ones complement cksum of struct */
union {
- u_char ih_pptr; /* ICMP_PARAMPROB */
- struct in_addr ih_gwaddr; /* ICMP_REDIRECT */
- struct ih_idseq {
- n_short icd_id;
- n_short icd_seq;
+ __u8 ih_pptr; /* ICMP_PARAMPROB */
+ struct in_addr ih_gwaddr; /* ICMP_REDIRECT */
+ struct ih_idseq {
+ __u16 icd_id;
+ __u16 icd_seq;
} ih_idseq;
int ih_void;
} icmp_hun;
@@ -752,5 +786,12 @@ struct ether_addr {
#ifndef ICMP_ROUTERSOLICIT
# define ICMP_ROUTERSOLICIT 10
#endif
+/*
+ * ICMP error replies have an IP header (20 bytes), 8 bytes of ICMP data,
+ * another IP header and then 64 bits of data, totalling 56. Of course,
+ * the last 64 bits is dependant on that being available.
+ */
+#define ICMPERR_MINPKTLEN (20 + 8 + 20)
+#define ICMPERR_MAXPKTLEN (20 + 8 + 20 + 8)
#endif /* __IP_COMPAT_H__ */
diff --git a/sys/netinet/ip_frag.c b/sys/netinet/ip_frag.c
index 885a53bc3b5..d3b059cbb5c 100644
--- a/sys/netinet/ip_frag.c
+++ b/sys/netinet/ip_frag.c
@@ -1,6 +1,6 @@
-/* $OpenBSD: ip_frag.c,v 1.10 1998/09/15 09:51:18 pattonme Exp $ */
+/* $OpenBSD: ip_frag.c,v 1.11 1999/02/05 05:58:51 deraadt Exp $ */
/*
- * Copyright (C) 1993-1997 by Darren Reed.
+ * Copyright (C) 1993-1998 by Darren Reed.
*
* Redistribution and use in source and binary forms are permitted
* provided that this notice is preserved and due credit is given
@@ -8,18 +8,19 @@
*/
#if !defined(lint)
static const char sccsid[] = "@(#)ip_frag.c 1.11 3/24/96 (C) 1993-1995 Darren Reed";
-static const char rcsid[] = "@(#)$Id: ip_frag.c,v 1.10 1998/09/15 09:51:18 pattonme Exp $";
+static const char rcsid[] = "@(#)$Id: ip_frag.c,v 1.11 1999/02/05 05:58:51 deraadt Exp $";
#endif
-#if !defined(_KERNEL) && !defined(KERNEL)
-# include <string.h>
-# include <stdlib.h>
-#endif
#include <sys/errno.h>
#include <sys/types.h>
#include <sys/param.h>
#include <sys/time.h>
#include <sys/file.h>
+#if !defined(_KERNEL) && !defined(KERNEL)
+# include <stdio.h>
+# include <string.h>
+# include <stdlib.h>
+#endif
#if defined(KERNEL) && (__FreeBSD_version >= 220000)
#include <sys/filio.h>
#include <sys/fcntl.h>
@@ -81,7 +82,7 @@ int ipfr_inuse = 0,
extern int ipfr_timer_id;
#endif
#if (SOLARIS || defined(__sgi)) && defined(_KERNEL)
-extern krwlock_t ipf_frag, ipf_natfrag, ipf_nat;
+extern KRWLOCK_T ipf_frag, ipf_natfrag, ipf_nat;
extern kmutex_t ipf_rw;
#endif
@@ -160,7 +161,7 @@ ipfr_t *table[];
/*
* Compute the offset of the expected start of the next packet.
*/
- fr->ipfr_off = (ip->ip_off & 0x1fff) + (fin->fin_dlen >> 3);
+ fr->ipfr_off = (ip->ip_off & IP_OFFMASK) + (fin->fin_dlen >> 3);
ATOMIC_INC(ipfr_stats.ifs_new);
ATOMIC_INC(ipfr_inuse);
return fr;
@@ -190,7 +191,8 @@ nat_t *nat;
ipfr_t *ipf;
WRITE_ENTER(&ipf_natfrag);
- if ((ipf = ipfr_new(ip, fin, pass, ipfr_nattab))) {
+ ipf = ipfr_new(ip, fin, pass, ipfr_nattab);
+ if (ipf != NULL) {
ipf->ipfr_data = nat;
nat->nat_data = ipf;
}
@@ -255,7 +257,7 @@ ipfr_t *table[];
* If we've follwed the fragments, and this is the
* last (in order), shrink expiration time.
*/
- if ((off & 0x1fff) == f->ipfr_off) {
+ if ((off & IP_OFFMASK) == f->ipfr_off) {
if (!(off & IP_MF))
f->ipfr_ttl = 1;
else
@@ -280,12 +282,12 @@ fr_info_t *fin;
READ_ENTER(&ipf_natfrag);
ipf = ipfr_lookup(ip, fin, ipfr_nattab);
- if (ipf) {
+ if (ipf != NULL) {
nat = ipf->ipfr_data;
/*
* This is the last fragment for this packet.
*/
- if (ipf->ipfr_ttl == 1) {
+ if ((ipf->ipfr_ttl == 1) && (nat != NULL)) {
nat->nat_data = NULL;
ipf->ipfr_data = NULL;
}
@@ -355,7 +357,8 @@ void ipfr_unload()
for (idx = IPFT_SIZE - 1; idx >= 0; idx--)
for (fp = &ipfr_nattab[idx]; (fr = *fp); ) {
*fp = fr->ipfr_next;
- if ((nat = (nat_t *)fr->ipfr_data)) {
+ nat = (nat_t *)fr->ipfr_data;
+ if (nat != NULL) {
if (nat->nat_data == fr)
nat->nat_data = NULL;
}
@@ -434,7 +437,8 @@ int ipfr_slowtimer()
*fp = fr->ipfr_next;
ATOMIC_INC(ipfr_stats.ifs_expire);
ATOMIC_DEC(ipfr_inuse);
- if ((nat = (nat_t *)fr->ipfr_data)) {
+ nat = (nat_t *)fr->ipfr_data;
+ if (nat != NULL) {
if (nat->nat_data == fr)
nat->nat_data = NULL;
}
diff --git a/sys/netinet/ip_frag.h b/sys/netinet/ip_frag.h
index df88bc34ac7..54e92d29bbf 100644
--- a/sys/netinet/ip_frag.h
+++ b/sys/netinet/ip_frag.h
@@ -1,13 +1,13 @@
-/* $OpenBSD: ip_frag.h,v 1.7 1998/02/17 01:39:04 dgregor Exp $ */
+/* $OpenBSD: ip_frag.h,v 1.8 1999/02/05 05:58:51 deraadt Exp $ */
/*
- * Copyright (C) 1993-1997 by Darren Reed.
+ * Copyright (C) 1993-1998 by Darren Reed.
*
* Redistribution and use in source and binary forms are permitted
* provided that this notice is preserved and due credit is given
* to the original author and the contributors.
*
* @(#)ip_frag.h 1.5 3/24/96
- * $Id: ip_frag.h,v 1.7 1998/02/17 01:39:04 dgregor Exp $
+ * $Id: ip_frag.h,v 1.8 1999/02/05 05:58:51 deraadt Exp $
*/
#ifndef __IP_FRAG_H__
diff --git a/sys/netinet/ip_ftp_pxy.c b/sys/netinet/ip_ftp_pxy.c
index fe978aeca6a..7079c4efa1c 100644
--- a/sys/netinet/ip_ftp_pxy.c
+++ b/sys/netinet/ip_ftp_pxy.c
@@ -1,8 +1,11 @@
-/* $OpenBSD: ip_ftp_pxy.c,v 1.3 1998/09/15 09:51:18 pattonme Exp $
- * $Id: ip_ftp_pxy.c,v 1.3 1998/09/15 09:51:18 pattonme Exp $
+/* $OpenBSD: ip_ftp_pxy.c,v 1.4 1999/02/05 05:58:52 deraadt Exp $
+ * $Id: ip_ftp_pxy.c,v 1.4 1999/02/05 05:58:52 deraadt Exp $
* Simple FTP transparent proxy for in-kernel use. For use with the NAT
* code.
*/
+#if SOLARIS && defined(_KERNEL)
+extern kmutex_t ipf_rw;
+#endif
#define isdigit(x) ((x) >= '0' && (x) <= '9')
@@ -10,71 +13,35 @@
#define IPF_MINPORTLEN 18
#define IPF_MAXPORTLEN 30
+#define IPF_MIN227LEN 39
+#define IPF_MAX227LEN 51
-int ippr_ftp_init __P((fr_info_t *, ip_t *, tcphdr_t *,
- ap_session_t *, nat_t *));
-int ippr_ftp_in __P((fr_info_t *, ip_t *, tcphdr_t *,
- ap_session_t *, nat_t *));
-int ippr_ftp_out __P((fr_info_t *, ip_t *, tcphdr_t *,
- ap_session_t *, nat_t *));
-u_short ipf_ftp_atoi __P((char **));
-
-
-int ippr_ftp_init __P((fr_info_t *, ip_t *, tcphdr_t *, ap_session_t *,
- nat_t *));
-int ippr_ftp_in __P((fr_info_t *, ip_t *, tcphdr_t *, ap_session_t *,
- nat_t *));
-int ippr_ftp_out __P((fr_info_t *, ip_t *, tcphdr_t *, ap_session_t *,
- nat_t *));
-
+int ippr_ftp_init __P((fr_info_t *, ip_t *, ap_session_t *, nat_t *));
+int ippr_ftp_out __P((fr_info_t *, ip_t *, ap_session_t *, nat_t *));
+int ippr_ftp_in __P((fr_info_t *, ip_t *, ap_session_t *, nat_t *));
+int ippr_ftp_portmsg __P((fr_info_t *, ip_t *, nat_t *nat));
+int ippr_ftp_pasvmsg __P((fr_info_t *, ip_t *, tcphdr_t *, nat_t *));
u_short ipf_ftp_atoi __P((char **));
-
/*
* FTP application proxy initialization.
*/
-int ippr_ftp_init(fin, ip, tcp, aps, nat)
+int ippr_ftp_init(fin, ip, aps, nat)
fr_info_t *fin;
ip_t *ip;
-tcphdr_t *tcp;
ap_session_t *aps;
nat_t *nat;
{
+ tcphdr_t *tcp = (tcphdr_t *)fin->fin_dp;
+
aps->aps_sport = tcp->th_sport;
aps->aps_dport = tcp->th_dport;
return 0;
}
-int ippr_ftp_in(fin, ip, tcp, aps, nat)
-fr_info_t *fin;
-ip_t *ip;
-tcphdr_t *tcp;
-ap_session_t *aps;
-nat_t *nat;
-{
- u_32_t sum1, sum2;
- short sel;
-
- if (tcp->th_sport == aps->aps_dport) {
- sum2 = (u_32_t)ntohl(tcp->th_ack);
- sel = aps->aps_sel;
- if ((aps->aps_after[!sel] > aps->aps_after[sel]) &&
- (sum2 > aps->aps_after[!sel])) {
- sel = aps->aps_sel = !sel; /* switch to other set */
- }
- if (aps->aps_seqoff[sel] && (sum2 > aps->aps_after[sel])) {
- sum1 = (u_32_t)aps->aps_seqoff[sel];
- tcp->th_ack = htonl(sum2 - sum1);
- return 2;
- }
- }
- return 0;
-}
-
-
/*
* ipf_ftp_atoi - implement a version of atoi which processes numbers in
* pairs separated by commas (which are expected to be in the range 0 - 255),
@@ -104,29 +71,29 @@ char **ptr;
}
-int ippr_ftp_out(fin, ip, tcp, aps, nat)
+int ippr_ftp_portmsg(fin, ip, nat)
fr_info_t *fin;
ip_t *ip;
-tcphdr_t *tcp;
-ap_session_t *aps;
nat_t *nat;
{
- register u_32_t sum1, sum2;
- char newbuf[IPF_MAXPORTLEN+1];
- char portbuf[IPF_MAXPORTLEN+1], *s;
- int ch = 0, off = (ip->ip_hl << 2) + (tcp->th_off << 2);
- u_int a1, a2, a3, a4;
- u_short a5, a6;
- int olen, dlen, nlen = 0, inc = 0;
- tcphdr_t tcph, *tcp2 = &tcph;
- void *savep;
- nat_t *ipn;
- struct in_addr swip;
- mb_t *m = *(mb_t **)fin->fin_mp;
-
+ char portbuf[IPF_MAXPORTLEN + 1], newbuf[IPF_MAXPORTLEN + 1], *s;
+ int off, olen, dlen, nlen = 0, inc = 0;
+ u_int a1, a2, a3, a4;
+ tcphdr_t *tcp, tcph, *tcp2 = &tcph;
+ struct in_addr swip;
+ u_short a5, a6, sp, dp;
+ fr_info_t fi;
+ nat_t *ipn;
+ mb_t *m;
#if SOLARIS
mb_t *m1;
+#endif
+
+ tcp = (tcphdr_t *)fin->fin_dp;
+ off = (ip->ip_hl << 2) + (tcp->th_off << 2);
+ m = *(mb_t **)fin->fin_mp;
+#if SOLARIS
m = fin->fin_qfm;
dlen = msgdsize(m) - off;
@@ -137,10 +104,14 @@ nat_t *nat;
bzero(portbuf, sizeof(portbuf));
m_copydata(m, off, MIN(sizeof(portbuf), dlen), portbuf);
#endif
- portbuf[IPF_MAXPORTLEN] = '\0';
+ portbuf[sizeof(portbuf) - 1] = '\0';
+ *newbuf = '\0';
- if ((dlen < IPF_MINPORTLEN) || strncmp(portbuf, "PORT ", 5))
- goto adjust_seqack;
+ if (!strncmp(portbuf, "PORT ", 5)) {
+ if (dlen < IPF_MINPORTLEN)
+ return 0;
+ } else
+ return 0;
/*
* Skip the PORT command + space
@@ -149,21 +120,34 @@ nat_t *nat;
/*
* Pick out the address components, two at a time.
*/
- (void) ipf_ftp_atoi(&s);
+ a1 = ipf_ftp_atoi(&s);
if (!s)
- goto adjust_seqack;
- (void) ipf_ftp_atoi(&s);
+ return 0;
+ a2 = ipf_ftp_atoi(&s);
if (!s)
- goto adjust_seqack;
+ return 0;
+
+ /*
+ * check that IP address in the PORT/PASV reply is the same as the
+ * sender of the command - prevents using PORT for port scanning.
+ */
+ a1 <<= 16;
+ a1 |= a2;
+ if (a1 != ntohl(nat->nat_inip.s_addr))
+ return 0;
+
a5 = ipf_ftp_atoi(&s);
if (!s)
- goto adjust_seqack;
+ return 0;
+
/*
* check for CR-LF at the end.
*/
- if (*s != '\n' || *(s - 1) != '\r')
- goto adjust_seqack;
- a6 = a5 & 0xff;
+ if (((*s == '\r') && (*(s + 1) == '\n')) ||
+ ((*(s - 1) == '\r') && (*s == '\n')))
+ a6 = a5 & 0xff;
+ else
+ return 0;
a5 >>= 8;
/*
* Calculate new address parts for PORT command
@@ -174,25 +158,210 @@ nat_t *nat;
a4 = a1 & 0xff;
a1 >>= 24;
olen = s - portbuf + 1;
- (void) sprintf(newbuf, "PORT %d,%d,%d,%d,%d,%d\r\n",
- a1, a2, a3, a4, a5, a6);
+ (void) sprintf(newbuf, "%s %d,%d,%d,%d,%d,%d\r\n",
+ "PORT", a1, a2, a3, a4, a5, a6);
+
+ nlen = strlen(newbuf);
+ inc = nlen - olen;
+#if SOLARIS
+ for (m1 = m; m1->b_cont; m1 = m1->b_cont)
+ ;
+ if ((inc > 0) && (m1->b_datap->db_lim - m1->b_wptr < inc)) {
+ mblk_t *nm;
+
+ /* alloc enough to keep same trailer space for lower driver */
+ nm = allocb(nlen, BPRI_MED);
+ PANIC((!nm),("ippr_ftp_out: allocb failed"));
+
+ nm->b_band = m1->b_band;
+ nm->b_wptr += nlen;
+
+ m1->b_wptr -= olen;
+ PANIC((m1->b_wptr < m1->b_rptr),
+ ("ippr_ftp_out: cannot handle fragmented data block"));
+
+ linkb(m1, nm);
+ } else {
+ m1->b_wptr += inc;
+ }
+ copyin_mblk(m, off, nlen, newbuf);
+#else
+ if (inc < 0)
+ m_adj(m, inc);
+ /* the mbuf chain will be extended if necessary by m_copyback() */
+ m_copyback(m, off, nlen, newbuf);
+#endif
+ if (inc) {
+#if SOLARIS || defined(__sgi)
+ register u_32_t sum1, sum2;
+
+ sum1 = ip->ip_len;
+ sum2 = ip->ip_len + inc;
+
+ /* Because ~1 == -2, We really need ~1 == -1 */
+ if (sum1 > sum2)
+ sum2--;
+ sum2 -= sum1;
+ sum2 = (sum2 & 0xffff) + (sum2 >> 16);
+
+ fix_outcksum(&ip->ip_sum, sum2);
+#endif
+ ip->ip_len += inc;
+ }
+
+ /*
+ * Add skeleton NAT entry for connection which will come back the
+ * other way.
+ */
+ sp = htons(a5 << 8 | a6);
+ dp = htons(fin->fin_data[1] - 1);
+ ipn = nat_outlookup(fin->fin_ifp, IPN_TCP, nat->nat_inip, sp,
+ ip->ip_dst, dp);
+ if (ipn == NULL) {
+ bcopy((char *)fin, (char *)&fi, sizeof(fi));
+ bzero((char *)tcp2, sizeof(*tcp2));
+ tcp2->th_sport = sp;
+ tcp2->th_dport = dp;
+ fi.fin_dp = (char *)tcp2;
+ swip = ip->ip_src;
+ ip->ip_src = nat->nat_inip;
+ ipn = nat_new(nat->nat_ptr, ip, &fi, IPN_TCP, NAT_OUTBOUND);
+ if (ipn != NULL) {
+ ipn->nat_age = fr_defnatage;
+ (void) fr_addstate(ip, &fi, FR_INQUE|FR_PASS|
+ FR_QUICK|FR_KEEPSTATE);
+ }
+ ip->ip_src = swip;
+ }
+ return inc;
+}
+
+
+int ippr_ftp_out(fin, ip, aps, nat)
+fr_info_t *fin;
+ip_t *ip;
+ap_session_t *aps;
+nat_t *nat;
+{
+ return ippr_ftp_portmsg(fin, ip, nat);
+}
+
+
+int ippr_ftp_pasvmsg(fin, ip, tcp, nat)
+fr_info_t *fin;
+ip_t *ip;
+tcphdr_t *tcp;
+nat_t *nat;
+{
+ char portbuf[IPF_MAX227LEN + 1], newbuf[IPF_MAX227LEN + 1], *s;
+ int off, olen, dlen, nlen = 0, inc = 0;
+ u_int a1, a2, a3, a4;
+ tcphdr_t tcph, *tcp2 = &tcph;
+ struct in_addr swip;
+ u_short a5, a6;
+ fr_info_t fi;
+ nat_t *ipn;
+ mb_t *m;
+#if SOLARIS
+ mb_t *m1;
+#endif
+
+ off = (ip->ip_hl << 2) + (tcp->th_off << 2);
+ m = *(mb_t **)fin->fin_mp;
+
+#if SOLARIS
+ m = fin->fin_qfm;
+
+ dlen = msgdsize(m) - off;
+ bzero(portbuf, sizeof(portbuf));
+ copyout_mblk(m, off, MIN(sizeof(portbuf), dlen), portbuf);
+#else
+ dlen = mbufchainlen(m) - off;
+ bzero(portbuf, sizeof(portbuf));
+ m_copydata(m, off, MIN(sizeof(portbuf), dlen), portbuf);
+#endif
+ portbuf[sizeof(portbuf) - 1] = '\0';
+ *newbuf = '\0';
+
+ if (!strncmp(portbuf, "227 ", 4)) {
+ if (dlen < IPF_MIN227LEN)
+ return 0;
+ else if (strncmp(portbuf, "227 Entering Passive Mode", 25))
+ return 0;
+#ifndef notyet
+ return 0;
+#endif
+ } else
+ return 0;
+
+ /*
+ * Skip the PORT command + space
+ */
+ s = portbuf + 25;
+ while (*s && !isdigit(*s))
+ s++;
+ /*
+ * Pick out the address components, two at a time.
+ */
+ a1 = ipf_ftp_atoi(&s);
+ if (!s)
+ return 0;
+ a2 = ipf_ftp_atoi(&s);
+ if (!s)
+ return 0;
+
+ /*
+ * check that IP address in the PORT/PASV reply is the same as the
+ * sender of the command - prevents using PORT for port scanning.
+ */
+ a1 <<= 16;
+ a1 |= a2;
+ if (a1 != ntohl(nat->nat_oip.s_addr))
+ return 0;
+
+ a5 = ipf_ftp_atoi(&s);
+ if (!s)
+ return 0;
+
+ /*
+ * check for CR-LF at the end.
+ */
+ if (((*s == '\r') && (*(s + 1) == '\n')) ||
+ ((*(s - 1) == '\r') && (*s == '\n')))
+ a6 = a5 & 0xff;
+ else
+ return 0;
+ a5 >>= 8;
+ /*
+ * Calculate new address parts for 227 reply
+ */
+ a1 = ntohl(nat->nat_inip.s_addr);
+ a2 = (a1 >> 16) & 0xff;
+ a3 = (a1 >> 8) & 0xff;
+ a4 = a1 & 0xff;
+ a1 >>= 24;
+ olen = s - portbuf + 1;
+ (void) sprintf(newbuf, "%s %d,%d,%d,%d,%d,%d\r\n",
+ "227 Entering Passive Mode", a1, a2, a3, a4, a5, a6);
+
nlen = strlen(newbuf);
inc = nlen - olen;
#if SOLARIS
for (m1 = m; m1->b_cont; m1 = m1->b_cont)
;
- if (inc > 0) {
+ if ((inc > 0) && (m1->b_datap->db_lim - m1->b_wptr < inc)) {
mblk_t *nm;
/* alloc enough to keep same trailer space for lower driver */
- nm = allocb(nlen + m1->b_datap->db_lim - m1->b_wptr, BPRI_MED);
+ nm = allocb(nlen, BPRI_MED);
PANIC((!nm),("ippr_ftp_out: allocb failed"));
nm->b_band = m1->b_band;
nm->b_wptr += nlen;
m1->b_wptr -= olen;
- PANIC((m1->b_wptr < m1->b_rptr),("ippr_ftp_out: cannot handle fragmented data block"));
+ PANIC((m1->b_wptr < m1->b_rptr),
+ ("ippr_ftp_out: cannot handle fragmented data block"));
linkb(m1, nm);
} else {
@@ -207,6 +376,8 @@ nat_t *nat;
#endif
if (inc) {
#if SOLARIS || defined(__sgi)
+ register u_32_t sum1, sum2;
+
sum1 = ip->ip_len;
sum2 = ip->ip_len + inc;
@@ -220,48 +391,32 @@ nat_t *nat;
#endif
ip->ip_len += inc;
}
- ch = 1;
/*
* Add skeleton NAT entry for connection which will come back the
* other way.
*/
- savep = fin->fin_dp;
- fin->fin_dp = (char *)tcp2;
+ bcopy((char *)fin, (char *)&fi, sizeof(fi));
bzero((char *)tcp2, sizeof(*tcp2));
tcp2->th_sport = htons(a5 << 8 | a6);
- tcp2->th_dport = htons(20);
+ fi.fin_dp = (char *)tcp2;
swip = ip->ip_src;
- ip->ip_src = nat->nat_inip;
- if ((ipn = nat_new(nat->nat_ptr, ip, fin, IPN_TCP, NAT_OUTBOUND)))
+ ip->ip_src = nat->nat_oip;
+ ipn = nat_new(nat->nat_ptr, ip, &fi, IPN_TCP, NAT_INBOUND);
+ if (ipn != NULL)
ipn->nat_age = fr_defnatage;
- (void) fr_addstate(ip, fin, FR_INQUE|FR_PASS|FR_QUICK|FR_KEEPSTATE);
+ (void) fr_addstate(ip, &fi, FR_INQUE|FR_PASS|FR_QUICK|FR_KEEPSTATE);
ip->ip_src = swip;
- fin->fin_dp = (char *)savep;
-
-adjust_seqack:
- if (tcp->th_dport == aps->aps_dport) {
- sum2 = (u_32_t)ntohl(tcp->th_seq);
- off = aps->aps_sel;
- if ((aps->aps_after[!off] > aps->aps_after[off]) &&
- (sum2 > aps->aps_after[!off])) {
- off = aps->aps_sel = !off; /* switch to other set */
- }
- if (aps->aps_seqoff[off]) {
- sum1 = (u_32_t)aps->aps_after[off] -
- aps->aps_seqoff[off];
- if (sum2 > sum1) {
- sum1 = (u_32_t)aps->aps_seqoff[off];
- sum2 += sum1;
- tcp->th_seq = htonl(sum2);
- ch = 1;
- }
- }
+ return inc;
+}
- if (inc && (sum2 > aps->aps_after[!off])) {
- aps->aps_after[!off] = sum2 + nlen - 1;
- aps->aps_seqoff[!off] = aps->aps_seqoff[off] + inc;
- }
- }
- return ch ? 2 : 0;
+int ippr_ftp_in(fin, ip, aps, nat)
+fr_info_t *fin;
+ip_t *ip;
+ap_session_t *aps;
+nat_t *nat;
+{
+ tcphdr_t *tcp = (tcphdr_t *)fin->fin_dp;
+
+ return ippr_ftp_pasvmsg(fin, ip, tcp, nat);
}
diff --git a/sys/netinet/ip_log.c b/sys/netinet/ip_log.c
index 1b9326b4f3c..414bf35c88d 100644
--- a/sys/netinet/ip_log.c
+++ b/sys/netinet/ip_log.c
@@ -1,12 +1,12 @@
-/* $OpenBSD: ip_log.c,v 1.3 1998/09/15 09:51:18 pattonme Exp $ */
+/* $OpenBSD: ip_log.c,v 1.4 1999/02/05 05:58:52 deraadt Exp $ */
/*
- * Copyright (C) 1997 by Darren Reed.
+ * Copyright (C) 1997-1998 by Darren Reed.
*
* Redistribution and use in source and binary forms are permitted
* provided that this notice is preserved and due credit is given
* to the original author and the contributors.
*
- * $Id: ip_log.c,v 1.3 1998/09/15 09:51:18 pattonme Exp $
+ * $Id: ip_log.c,v 1.4 1999/02/05 05:58:52 deraadt Exp $
*/
#ifdef IPFILTER_LOG
# ifndef SOLARIS
@@ -184,29 +184,36 @@ mb_t *m;
* calculate header size.
*/
hlen = fin->fin_hlen;
- if (ip->ip_p == IPPROTO_TCP)
- hlen += MIN(sizeof(tcphdr_t), fin->fin_dlen);
- else if (ip->ip_p == IPPROTO_UDP)
- hlen += MIN(sizeof(udphdr_t), fin->fin_dlen);
- else if (ip->ip_p == IPPROTO_ICMP) {
- struct icmp *icmp = (struct icmp *)((char *)ip + hlen);
-
- /*
- * For ICMP, if the packet is an error packet, also include
- * the information about the packet which caused the error.
- */
- switch (icmp->icmp_type)
- {
- case ICMP_UNREACH :
- case ICMP_SOURCEQUENCH :
- case ICMP_REDIRECT :
- case ICMP_TIMXCEED :
- case ICMP_PARAMPROB :
- hlen += MIN(sizeof(struct icmp) + 8, fin->fin_dlen);
- break;
- default :
- hlen += MIN(sizeof(struct icmp), fin->fin_dlen);
- break;
+ if ((ip->ip_off & IP_OFFMASK) == 0) {
+ if (ip->ip_p == IPPROTO_TCP)
+ hlen += MIN(sizeof(tcphdr_t), fin->fin_dlen);
+ else if (ip->ip_p == IPPROTO_UDP)
+ hlen += MIN(sizeof(udphdr_t), fin->fin_dlen);
+ else if (ip->ip_p == IPPROTO_ICMP) {
+ struct icmp *icmp;
+
+ icmp = (struct icmp *)((char *)ip + hlen);
+
+ /*
+ * For ICMP, if the packet is an error packet, also
+ * include the information about the packet which
+ * caused the error.
+ */
+ switch (icmp->icmp_type)
+ {
+ case ICMP_UNREACH :
+ case ICMP_SOURCEQUENCH :
+ case ICMP_REDIRECT :
+ case ICMP_TIMXCEED :
+ case ICMP_PARAMPROB :
+ hlen += MIN(sizeof(struct icmp) + 8,
+ fin->fin_dlen);
+ break;
+ default :
+ hlen += MIN(sizeof(struct icmp),
+ fin->fin_dlen);
+ break;
+ }
}
}
/*
diff --git a/sys/netinet/ip_nat.c b/sys/netinet/ip_nat.c
index cb868ed521d..412cfbf2f5f 100644
--- a/sys/netinet/ip_nat.c
+++ b/sys/netinet/ip_nat.c
@@ -1,6 +1,6 @@
-/* $OpenBSD: ip_nat.c,v 1.19 1999/02/01 07:45:53 d Exp $ */
+/* $OpenBSD: ip_nat.c,v 1.20 1999/02/05 05:58:52 deraadt Exp $ */
/*
- * Copyright (C) 1995-1997 by Darren Reed.
+ * Copyright (C) 1995-1998 by Darren Reed.
*
* Redistribution and use in source and binary forms are permitted
* provided that this notice is preserved and due credit is given
@@ -10,23 +10,23 @@
*/
#if !defined(lint)
static const char sccsid[] = "@(#)ip_nat.c 1.11 6/5/96 (C) 1995 Darren Reed";
-static const char rcsid[] = "@(#)$Id: ip_nat.c,v 1.19 1999/02/01 07:45:53 d Exp $";
+static const char rcsid[] = "@(#)$Id: ip_nat.c,v 1.20 1999/02/05 05:58:52 deraadt Exp $";
#endif
#if defined(__FreeBSD__) && defined(KERNEL) && !defined(_KERNEL)
#define _KERNEL
#endif
-#if !defined(_KERNEL) && !defined(KERNEL)
-# include <stdio.h>
-# include <string.h>
-# include <stdlib.h>
-#endif
#include <sys/errno.h>
#include <sys/types.h>
#include <sys/param.h>
#include <sys/time.h>
#include <sys/file.h>
+#if !defined(_KERNEL) && !defined(KERNEL)
+# include <stdio.h>
+# include <string.h>
+# include <stdlib.h>
+#endif
#if defined(KERNEL) && (__FreeBSD_version >= 220000)
# include <sys/filio.h>
# include <sys/fcntl.h>
@@ -111,7 +111,7 @@ u_long fr_defnatage = 1200, /* 10 minutes (600 seconds) */
natstat_t nat_stats;
#if (SOLARIS || defined(__sgi)) && defined(_KERNEL)
extern kmutex_t ipf_rw;
-extern krwlock_t ipf_nat;
+extern KRWLOCK_T ipf_nat;
#endif
static int nat_flushtable __P((void));
@@ -123,11 +123,10 @@ static int nat_ifpaddr __P((nat_t *, void *, struct in_addr *));
#define LONG_SUM(in) (((in) & 0xffff) + ((in) >> 16))
#define CALC_SUMD(s1, s2, sd) { \
- /* Do it twice */ \
- (s1) = ((s1) & 0xffff) + ((s1) >> 16); \
(s1) = ((s1) & 0xffff) + ((s1) >> 16); \
- /* Do it twice */ \
(s2) = ((s2) & 0xffff) + ((s2) >> 16); \
+ /* Do it twice */ \
+ (s1) = ((s1) & 0xffff) + ((s1) >> 16); \
(s2) = ((s2) & 0xffff) + ((s2) >> 16); \
/* Because ~1 == -2, We really need ~1 == -1 */ \
if ((s1) > (s2)) (s2)--; \
@@ -257,7 +256,13 @@ int mode;
n->in_ifp = (void *)GETUNIT(n->in_ifname);
if (!n->in_ifp)
n->in_ifp = (void *)-1;
- n->in_apr = ap_match(n->in_p, n->in_plabel);
+ if (n->in_plabel[0] != '\0') {
+ n->in_apr = ap_match(n->in_p, n->in_plabel);
+ if (!n->in_apr) {
+ error = ENOENT;
+ break;
+ }
+ }
n->in_next = *np;
n->in_use = 0;
n->in_space = ~(0xffffffff & ntohl(n->in_outmsk));
@@ -281,7 +286,7 @@ int mode;
/* Otherwise, these fields are preset */
*np = n;
n = NULL;
- ATOMIC_INC(nat_stats.ns_rules);
+ nat_stats.ns_rules++;
break;
case SIOCRMNAT :
if (!(mode & FWRITE)) {
@@ -298,7 +303,7 @@ int mode;
if (n->in_apr)
ap_free(n->in_apr);
KFREE(n);
- ATOMIC_DEC(nat_stats.ns_rules);
+ nat_stats.ns_rules--;
} else {
n->in_flags |= IPN_DELETE;
n->in_next = NULL;
@@ -310,6 +315,7 @@ int mode;
nat_stats.ns_table[0] = nat_table[0];
nat_stats.ns_table[1] = nat_table[1];
nat_stats.ns_list = nat_list;
+ nat_stats.ns_apslist = ap_sess_list;
IWCOPY((char *)&nat_stats, (char *)data, sizeof(nat_stats));
break;
case SIOCGNATL :
@@ -331,7 +337,6 @@ int mode;
break;
}
ret = nat_flushtable();
- (void) ap_unload();
MUTEX_DOWNGRADE(&ipf_nat);
IWCOPY((caddr_t)&ret, data, sizeof(ret));
break;
@@ -355,7 +360,7 @@ int mode;
error = EINVAL;
break;
}
- RWLOCK_EXIT(&ipf_nat);
+ RWLOCK_EXIT(&ipf_nat); /* READ/WRITE */
SPL_X(s);
if (nt)
KFREE(nt);
@@ -392,7 +397,7 @@ struct nat *natd;
* longer being used.
*/
if ((ipn = natd->nat_ptr)) {
- ATOMIC_INC(ipn->in_space);
+ ipn->in_space++;
ipn->in_use--;
if (!ipn->in_use && (ipn->in_flags & IPN_DELETE)) {
if (ipn->in_apr)
@@ -407,6 +412,8 @@ struct nat *natd;
* dereference that as well.
*/
ipfr_forget((void *)natd);
+ aps_free(natd->nat_aps);
+ nat_stats.ns_inuse--;
KFREE(natd);
}
@@ -418,9 +425,9 @@ static int nat_flushtable()
{
register nat_t *nat, **natp;
register int j = 0;
-
+
/*
- * Everything will be deleted, so lets just make it the deletions
+ * ALL NAT mappings deleted, so lets just make it the deletions
* quicker.
*/
bzero((char *)nat_table[0], sizeof(nat_table[0]));
@@ -431,13 +438,13 @@ static int nat_flushtable()
nat_delete(nat);
j++;
}
-
+ nat_stats.ns_inuse = 0;
return j;
}
/*
- * nat_clearlist - delete all entries in the active NAT mapping list.
+ * nat_clearlist - delete all rules in the active NAT mapping list.
*/
static int nat_clearlist()
{
@@ -450,14 +457,13 @@ static int nat_clearlist()
if (n->in_apr)
ap_free(n->in_apr);
KFREE(n);
- ATOMIC_DEC(nat_stats.ns_rules);
- i++;
+ nat_stats.ns_rules--;
} else {
n->in_flags |= IPN_DELETE;
n->in_next = NULL;
}
+ i++;
}
- nat_stats.ns_inuse = 0;
return i;
}
@@ -531,6 +537,7 @@ struct in_addr *inp;
/*
* Create a new NAT table entry.
+ * NOTE: assumes write lock on ipf_nat has been obtained already.
*/
nat_t *nat_new(np, ip, fin, flags, direction)
ipnat_t *np;
@@ -566,14 +573,31 @@ int direction;
*/
if (direction == NAT_OUTBOUND) {
/*
+ * Values at which the search for a free resouce starts.
+ */
+ u_32_t st_ip;
+ u_short st_port;
+
+ /*
* If it's an outbound packet which doesn't match any existing
* record, then create a new port
*/
l = 0;
+ st_ip = np->in_nip;
+ st_port = np->in_pnext;
+
do {
l++;
port = 0;
in.s_addr = np->in_nip;
+ if ((np->in_outmsk == 0xffffffff) &&
+ (np->in_pnext == 0)) {
+ if (l > 1) {
+ KFREE(nat);
+ return NULL;
+ }
+ }
+
if (!in.s_addr && (np->in_outmsk == 0xffffffff)) {
if ((l > 1) ||
nat_ifpaddr(nat, fin->fin_ifp, &in) == -1) {
@@ -586,19 +610,21 @@ int direction;
return NULL;
}
in.s_addr = ntohl(ip->ip_src.s_addr);
- if (nflags & IPN_TCPUDP)
- port = sport;
- } else if (nflags & IPN_TCPUDP) {
+ } else if ((nflags & IPN_TCPUDP)) {
port = htons(np->in_pnext++);
if (np->in_pnext >= ntohs(np->in_pmax)) {
np->in_pnext = ntohs(np->in_pmin);
- np->in_space--;
if (np->in_outmsk != 0xffffffff)
np->in_nip++;
}
- } else if (np->in_outmsk != 0xffffffff) {
- np->in_space--;
+ } else if (np->in_outmsk != 0xffffffff)
np->in_nip++;
+
+ if (!np->in_nip && (nflags & IPN_TCPUDP) &&
+ (np->in_pnext != 0)) {
+ port = htons(np->in_pnext++);
+ if (np->in_pnext >= ntohs(np->in_pmax))
+ np->in_pnext = ntohs(np->in_pmin);
}
if (!port && (flags & IPN_TCPUDP))
@@ -606,9 +632,23 @@ int direction;
if ((np->in_nip & ntohl(np->in_outmsk)) >
ntohl(np->in_outip))
np->in_nip = ntohl(np->in_outip) + 1;
+
+ /*
+ * Has the search wrapped around and come back to the
+ * start ?
+ */
+ if ((np->in_pnext != 0) && (st_port == np->in_pnext) &&
+ (np->in_nip != 0) && (st_ip == np->in_nip)) {
+ KFREE(nat);
+ return NULL;
+ }
+
} while (nat_inlookup(fin->fin_ifp, flags, ip->ip_dst,
dport, in, port));
+ if (np->in_space > 1)
+ np->in_space--;
+
/* Setup the NAT table */
nat->nat_inip = ip->ip_src;
nat->nat_outip.s_addr = htonl(in.s_addr);
@@ -652,12 +692,10 @@ int direction;
}
}
- /* Do it twice */
- sum1 = (sum1 & 0xffff) + (sum1 >> 16);
sum1 = (sum1 & 0xffff) + (sum1 >> 16);
-
- /* Do it twice */
sum2 = (sum2 & 0xffff) + (sum2 >> 16);
+ /* Do it twice */
+ sum1 = (sum1 & 0xffff) + (sum1 >> 16);
sum2 = (sum2 & 0xffff) + (sum2 >> 16);
if (sum1 > sum2)
@@ -676,12 +714,10 @@ int direction;
sum2 = (in.s_addr & 0xffff) + (in.s_addr >> 16);
- /* Do it twice */
- sum1 = (sum1 & 0xffff) + (sum1 >> 16);
sum1 = (sum1 & 0xffff) + (sum1 >> 16);
-
- /* Do it twice */
sum2 = (sum2 & 0xffff) + (sum2 >> 16);
+ /* Do it twice */
+ sum1 = (sum1 & 0xffff) + (sum1 >> 16);
sum2 = (sum2 & 0xffff) + (sum2 >> 16);
if (sum1 > sum2)
@@ -708,6 +744,7 @@ int direction;
nat->nat_pkts = 0;
nat->nat_ifp = fin->fin_ifp;
nat->nat_dir = direction;
+ nat->nat_age = fr_defnatage;
if (direction == NAT_OUTBOUND) {
if (flags & IPN_TCPUDP)
tcp->th_sport = port;
@@ -715,9 +752,9 @@ int direction;
if (flags & IPN_TCPUDP)
tcp->th_dport = nport;
}
- ATOMIC_INC(nat_stats.ns_added);
- ATOMIC_INC(nat_stats.ns_inuse);
- ATOMIC_INC(np->in_use);
+ nat_stats.ns_added++;
+ nat_stats.ns_inuse++;
+ np->in_use++;
return nat;
}
@@ -737,7 +774,7 @@ fr_info_t *fin;
* Only a basic IP header (no options) should be with an ICMP error
* header.
*/
- if ((ip->ip_hl != 5) || (ip->ip_len < sizeof(*icmp) + sizeof(ip_t)))
+ if ((ip->ip_hl != 5) || (ip->ip_len < ICMPERR_MINPKTLEN))
return NULL;
type = icmp->icmp_type;
/*
@@ -749,6 +786,8 @@ fr_info_t *fin;
return NULL;
oip = (ip_t *)((char *)fin->fin_dp + 8);
+ if (ip->ip_len < ICMPERR_MAXPKTLEN + ((oip->ip_hl - 5) << 2))
+ return NULL;
if (oip->ip_p == IPPROTO_TCP)
flags = IPN_TCP;
else if (oip->ip_p == IPPROTO_UDP)
@@ -758,7 +797,7 @@ fr_info_t *fin;
return nat_inlookup(fin->fin_ifp, flags, oip->ip_dst,
tcp->th_dport, oip->ip_src, tcp->th_sport);
}
- return nat_inlookup(fin->fin_ifp, 0, oip->ip_src, 0, oip->ip_dst, 0);
+ return nat_inlookup(fin->fin_ifp, 0, oip->ip_dst, 0, oip->ip_src, 0);
}
@@ -771,6 +810,8 @@ ip_t *ip;
fr_info_t *fin;
int *nflags;
{
+ u_32_t sum1, sum2, sumd;
+ struct in_addr in;
icmphdr_t *icmp;
nat_t *nat;
ip_t *oip;
@@ -778,10 +819,9 @@ int *nflags;
if (!(nat = nat_icmpinlookup(ip, fin)))
return NULL;
-
*nflags = IPN_ICMPERR;
icmp = (icmphdr_t *)fin->fin_dp;
- oip = (ip_t *)((char *)icmp + 8);
+ oip = (ip_t *)&icmp->icmp_ip;
if (oip->ip_p == IPPROTO_TCP)
flags = IPN_TCP;
else if (oip->ip_p == IPPROTO_UDP)
@@ -795,54 +835,62 @@ int *nflags;
* to only modify the checksum once for the port # and twice
* for the IP#.
*/
- if (flags & IPN_TCPUDP) {
- tcphdr_t *tcp = (tcphdr_t *)(oip + 1);
- u_32_t sum1, sum2, sumd;
- struct in_addr in;
+ if (nat->nat_dir == NAT_OUTBOUND) {
+ sum1 = LONG_SUM(ntohl(oip->ip_src.s_addr));
+ in = nat->nat_inip;
+ oip->ip_src = in;
+ } else {
+ sum1 = LONG_SUM(ntohl(oip->ip_dst.s_addr));
+ in = nat->nat_outip;
+ oip->ip_dst = in;
+ }
- if (nat->nat_dir == NAT_OUTBOUND) {
- sum1 = LONG_SUM(ntohl(oip->ip_src.s_addr));
- in = nat->nat_outip;
- oip->ip_src = in;
- tcp->th_sport = nat->nat_outport;
- } else {
- sum1 = LONG_SUM(ntohl(oip->ip_dst.s_addr));
- in = nat->nat_inip;
- oip->ip_dst = in;
- tcp->th_dport = nat->nat_inport;
- }
+ sum2 = LONG_SUM(ntohl(in.s_addr));
- sum2 = LONG_SUM(in.s_addr);
+ CALC_SUMD(sum1, sum2, sumd);
- CALC_SUMD(sum1, sum2, sumd);
- sumd = (sumd & 0xffff) + (sumd >> 16);
+ if (nat->nat_dir == NAT_OUTBOUND) {
+ fix_incksum(&oip->ip_sum, sumd);
+
+ sumd += (sumd & 0xffff);
+ while (sumd > 0xffff)
+ sumd = (sumd & 0xffff) + (sumd >> 16);
+ fix_outcksum(&icmp->icmp_cksum, sumd);
+ } else {
+ fix_outcksum(&oip->ip_sum, sumd);
+
+ sumd += (sumd & 0xffff);
+ while (sumd > 0xffff)
+ sumd = (sumd & 0xffff) + (sumd >> 16);
+ fix_incksum(&icmp->icmp_cksum, sumd);
+ }
+
+
+ if ((flags & IPN_TCPUDP) != 0) {
+ tcphdr_t *tcp;
+
+ /* XXX - what if this is bogus hl and we go off the end ? */
+ tcp = (tcphdr_t *)((((char *)oip) + (oip->ip_hl << 2)));
if (nat->nat_dir == NAT_OUTBOUND) {
- fix_incksum(&oip->ip_sum, sumd);
- fix_incksum(&icmp->icmp_cksum, sumd);
+ if (tcp->th_sport != nat->nat_inport) {
+ sum1 = ntohs(tcp->th_sport);
+ sum2 = ntohs(nat->nat_inport);
+ CALC_SUMD(sum1, sum2, sumd);
+ tcp->th_sport = nat->nat_inport;
+ fix_outcksum(&icmp->icmp_cksum, sumd);
+ }
} else {
- fix_outcksum(&oip->ip_sum, sumd);
- fix_outcksum(&icmp->icmp_cksum, sumd);
- }
-
- /*
- * TCP checksum doesn't make it into the 1st eight
- * bytes but UDP does.
- */
- if (ip->ip_p == IPPROTO_UDP) {
- udphdr_t *udp = (udphdr_t *)tcp;
-
- if (udp->uh_sum) {
- if (nat->nat_dir == NAT_OUTBOUND)
- fix_incksum(&udp->uh_sum,
- nat->nat_sumd);
- else
- fix_outcksum(&udp->uh_sum,
- nat->nat_sumd);
+ if (tcp->th_dport != nat->nat_outport) {
+ sum1 = ntohs(tcp->th_dport);
+ sum2 = ntohs(nat->nat_outport);
+ CALC_SUMD(sum1, sum2, sumd);
+ tcp->th_dport = nat->nat_outport;
+ fix_incksum(&icmp->icmp_cksum, sumd);
}
}
- } else
- ip->ip_dst = nat->nat_outip;
+ }
+
nat->nat_age = fr_defnaticmpage;
return nat;
}
@@ -996,12 +1044,12 @@ fr_info_t *fin;
else
ifp = fin->fin_ifp;
- if (!(ip->ip_off & 0x1fff) && !(fin->fin_fi.fi_fl & FI_SHORT)) {
+ if (!(ip->ip_off & IP_OFFMASK) && !(fin->fin_fi.fi_fl & FI_SHORT)) {
if (ip->ip_p == IPPROTO_TCP)
nflags = IPN_TCP;
else if (ip->ip_p == IPPROTO_UDP)
nflags = IPN_UDP;
- if (nflags) {
+ if ((nflags & IPN_TCPUDP)) {
tcp = (tcphdr_t *)fin->fin_dp;
sport = tcp->th_sport;
dport = tcp->th_dport;
@@ -1049,7 +1097,7 @@ fr_info_t *fin;
#endif
break;
}
- MUTEX_DOWNGRADE(&ipf_nat);
+ MUTEX_DOWNGRADE(&ipf_nat);
}
if (nat) {
@@ -1073,11 +1121,14 @@ fr_info_t *fin;
fix_incksum(&ip->ip_sum, nat->nat_ipsumd);
#endif
- if (nflags && !(ip->ip_off & 0x1fff) &&
+ if (!(ip->ip_off & IP_OFFMASK) &&
!(fin->fin_fi.fi_fl & FI_SHORT)) {
- if (nat->nat_outport)
+ if ((nat->nat_outport != 0) &&
+ (nflags & IPN_TCPUDP)) {
tcp->th_sport = nat->nat_outport;
+ fin->fin_data[0] = ntohs(tcp->th_sport);
+ }
if (ip->ip_p == IPPROTO_TCP) {
csump = &tcp->th_sum;
@@ -1098,10 +1149,6 @@ fr_info_t *fin;
if (udp->uh_sum)
csump = &udp->uh_sum;
- } else if (ip->ip_p == IPPROTO_ICMP) {
- icmphdr_t *ic = (icmphdr_t *)tcp;
-
- csump = &ic->icmp_cksum;
}
if (csump) {
if (nat->nat_dir == NAT_OUTBOUND)
@@ -1112,12 +1159,12 @@ fr_info_t *fin;
nat->nat_sumd);
}
}
- (void) ap_check(ip, tcp, fin, nat);
+ (void) ap_check(ip, fin, nat);
ATOMIC_INC(nat_stats.ns_mapped[1]);
- RWLOCK_EXIT(&ipf_nat);
+ RWLOCK_EXIT(&ipf_nat); /* READ */
return -2;
}
- RWLOCK_EXIT(&ipf_nat);
+ RWLOCK_EXIT(&ipf_nat); /* READ/WRITE */
return 0;
}
@@ -1139,13 +1186,13 @@ fr_info_t *fin;
nat_t *nat;
int nflags = 0, natadd = 1;
- if (!(ip->ip_off & 0x1fff) && !(fin->fin_fi.fi_fl & FI_SHORT)) {
+ if (!(ip->ip_off & IP_OFFMASK) && !(fin->fin_fi.fi_fl & FI_SHORT)) {
if (ip->ip_p == IPPROTO_TCP)
nflags = IPN_TCP;
else if (ip->ip_p == IPPROTO_UDP)
nflags = IPN_UDP;
- if (nflags) {
- tcp = (tcphdr_t *)((char *)ip + hlen);
+ if ((nflags & IPN_TCPUDP)) {
+ tcp = (tcphdr_t *)fin->fin_dp;
dport = tcp->th_dport;
sport = tcp->th_sport;
}
@@ -1185,14 +1232,14 @@ fr_info_t *fin;
#endif
break;
}
- MUTEX_DOWNGRADE(&ipf_nat);
+ MUTEX_DOWNGRADE(&ipf_nat);
}
if (nat) {
if (natadd && fin->fin_fi.fi_fl & FI_FRAG)
ipfr_nat_newfrag(ip, fin, 0, nat);
- MUTEX_ENTER(&ipf_rw);
- (void) ap_check(ip, tcp, fin, nat);
+ (void) ap_check(ip, fin, nat);
+ MUTEX_ENTER(&ipf_rw);
if (nflags != IPN_ICMPERR)
nat->nat_age = fr_defnatage;
@@ -1200,6 +1247,7 @@ fr_info_t *fin;
nat->nat_pkts++;
MUTEX_EXIT(&ipf_rw);
ip->ip_dst = nat->nat_inip;
+ fin->fin_fi.fi_dst = nat->nat_inip;
/*
* Fix up checksums, not by recalculating them, but
@@ -1211,11 +1259,14 @@ fr_info_t *fin;
else
fix_outcksum(&ip->ip_sum, nat->nat_ipsumd);
#endif
- if ((nflags & IPN_TCPUDP) && !(ip->ip_off & 0x1fff) &&
+ if (!(ip->ip_off & IP_OFFMASK) &&
!(fin->fin_fi.fi_fl & FI_SHORT)) {
- if (nat->nat_inport)
+ if ((nat->nat_inport != 0) &&
+ (nflags & IPN_TCPUDP)) {
tcp->th_dport = nat->nat_inport;
+ fin->fin_data[1] = ntohs(tcp->th_dport);
+ }
if (ip->ip_p == IPPROTO_TCP) {
csump = &tcp->th_sum;
@@ -1236,10 +1287,6 @@ fr_info_t *fin;
if (udp->uh_sum)
csump = &udp->uh_sum;
- } else if (ip->ip_p == IPPROTO_ICMP) {
- icmphdr_t *ic = (icmphdr_t *)tcp;
-
- csump = &ic->icmp_cksum;
}
if (csump) {
if (nat->nat_dir == NAT_OUTBOUND)
@@ -1251,10 +1298,10 @@ fr_info_t *fin;
}
}
ATOMIC_INC(nat_stats.ns_mapped[0]);
- RWLOCK_EXIT(&ipf_nat);
+ RWLOCK_EXIT(&ipf_nat); /* READ */
return -2;
}
- RWLOCK_EXIT(&ipf_nat);
+ RWLOCK_EXIT(&ipf_nat); /* READ/WRITE */
return 0;
}
@@ -1267,7 +1314,6 @@ void ip_natunload()
WRITE_ENTER(&ipf_nat);
(void) nat_clearlist();
(void) nat_flushtable();
- (void) ap_unload();
RWLOCK_EXIT(&ipf_nat);
}
@@ -1286,7 +1332,7 @@ void ip_natexpire()
SPL_NET(s);
WRITE_ENTER(&ipf_nat);
for (natp = &nat_instances; (nat = *natp); ) {
- ATOMIC_DEC(nat->nat_age);
+ nat->nat_age--;
if (nat->nat_age) {
natp = &nat->nat_next;
continue;
@@ -1296,11 +1342,8 @@ void ip_natexpire()
nat_log(nat, NL_EXPIRE);
#endif
nat_delete(nat);
- ATOMIC_INC(nat_stats.ns_expire);
+ nat_stats.ns_expire++;
}
-
- ap_expire();
-
RWLOCK_EXIT(&ipf_nat);
SPL_X(s);
}
@@ -1344,10 +1387,10 @@ void *ifp;
* Do it twice
*/
sum1 = (sum1 & 0xffff) + (sum1 >> 16);
- sum1 = (sum1 & 0xffff) + (sum1 >> 16);
+ sum2 = (sum2 & 0xffff) + (sum2 >> 16);
/* Do it twice */
- sum2 = (sum2 & 0xffff) + (sum2 >> 16);
+ sum1 = (sum1 & 0xffff) + (sum1 >> 16);
sum2 = (sum2 & 0xffff) + (sum2 >> 16);
/* Because ~1 == -2, We really need ~1 == -1 */
diff --git a/sys/netinet/ip_nat.h b/sys/netinet/ip_nat.h
index f68c6a5c6b0..435758221b8 100644
--- a/sys/netinet/ip_nat.h
+++ b/sys/netinet/ip_nat.h
@@ -1,13 +1,13 @@
-/* $OpenBSD: ip_nat.h,v 1.10 1998/09/15 09:51:18 pattonme Exp $ */
+/* $OpenBSD: ip_nat.h,v 1.11 1999/02/05 05:58:53 deraadt Exp $ */
/*
- * Copyright (C) 1995-1997 by Darren Reed.
+ * Copyright (C) 1995-1998 by Darren Reed.
*
* Redistribution and use in source and binary forms are permitted
* provided that this notice is preserved and due credit is given
* to the original author and the contributors.
*
* @(#)ip_nat.h 1.5 2/4/96
- * $Id: ip_nat.h,v 1.10 1998/09/15 09:51:18 pattonme Exp $
+ * $Id: ip_nat.h,v 1.11 1999/02/05 05:58:53 deraadt Exp $
*/
#ifndef __IP_NAT_H__
@@ -48,17 +48,18 @@ typedef struct nat {
u_32_t nat_sumd;
u_32_t nat_ipsumd;
void *nat_data;
+ void *nat_aps; /* proxy session */
struct in_addr nat_inip;
struct in_addr nat_outip;
struct in_addr nat_oip; /* other ip */
U_QUAD_T nat_pkts;
U_QUAD_T nat_bytes;
- u_short nat_oport; /* other port */
+ u_short nat_oport; /* other port */
u_short nat_inport;
u_short nat_outport;
u_short nat_use;
u_char nat_state[2];
- struct ipnat *nat_ptr;
+ struct ipnat *nat_ptr; /* pointer back to the rule */
struct nat *nat_next;
struct nat *nat_hnext[2];
struct nat **nat_hstart[2];
@@ -68,8 +69,8 @@ typedef struct nat {
typedef struct ipnat {
struct ipnat *in_next;
- void *in_ifp;
- void *in_apr;
+ void *in_ifp; /* interface pointer */
+ void *in_apr; /* proxy structure ptr */
u_int in_space;
u_int in_use;
struct in_addr in_nextip;
@@ -100,8 +101,7 @@ typedef struct ipnat {
#define NAT_REDIRECT 0x02
#define NAT_BIMAP (NAT_MAP|NAT_REDIRECT)
-#define IPN_CMPSIZ (sizeof(struct in_addr) * 4 + sizeof(u_short) * 3 + \
- sizeof(int) + IFNAMSIZ + APR_LABELLEN + sizeof(char))
+#define IPN_CMPSIZ (sizeof(ipnat_t) - offsetof(ipnat_t, in_flags))
typedef struct natlookup {
struct in_addr nl_inip;
@@ -123,6 +123,7 @@ typedef struct natstat {
u_long ns_logfail;
nat_t **ns_table[2];
ipnat_t *ns_list;
+ void *ns_apslist;
} natstat_t;
#define IPN_ANY 0x00
diff --git a/sys/netinet/ip_proxy.c b/sys/netinet/ip_proxy.c
index 891a12df8bb..c8a14ebc798 100644
--- a/sys/netinet/ip_proxy.c
+++ b/sys/netinet/ip_proxy.c
@@ -1,24 +1,19 @@
-/* $OpenBSD: ip_proxy.c,v 1.3 1998/09/15 09:51:18 pattonme Exp $ */
+/* $OpenBSD: ip_proxy.c,v 1.4 1999/02/05 05:58:53 deraadt Exp $ */
/*
- * Copyright (C) 1997 by Darren Reed.
+ * Copyright (C) 1997-1998 by Darren Reed.
*
* Redistribution and use in source and binary forms are permitted
* provided that this notice is preserved and due credit is given
* to the original author and the contributors.
*/
#if !defined(lint)
-static const char rcsid[] = "@(#)$Id: ip_proxy.c,v 1.3 1998/09/15 09:51:18 pattonme Exp $";
+static const char rcsid[] = "@(#)$Id: ip_proxy.c,v 1.4 1999/02/05 05:58:53 deraadt Exp $";
#endif
#if defined(__FreeBSD__) && defined(KERNEL) && !defined(_KERNEL)
# define _KERNEL
#endif
-#if !defined(_KERNEL) && !defined(KERNEL)
-# include <stdio.h>
-# include <string.h>
-# include <stdlib.h>
-#endif
#include <sys/errno.h>
#include <sys/types.h>
#include <sys/param.h>
@@ -27,6 +22,11 @@ static const char rcsid[] = "@(#)$Id: ip_proxy.c,v 1.3 1998/09/15 09:51:18 patto
#include <sys/ioctl.h>
#include <sys/fcntl.h>
#include <sys/uio.h>
+#if !defined(_KERNEL) && !defined(KERNEL)
+# include <stdio.h>
+# include <string.h>
+# include <stdlib.h>
+#endif
#ifndef linux
# include <sys/protosw.h>
#endif
@@ -80,11 +80,8 @@ static const char rcsid[] = "@(#)$Id: ip_proxy.c,v 1.3 1998/09/15 09:51:18 patto
#define MIN(a,b) (((a)<(b))?(a):(b))
#endif
-static ap_session_t *ap_find __P((ip_t *, tcphdr_t *));
-static ap_session_t *ap_new_session __P((aproxy_t *, ip_t *, tcphdr_t *,
+static ap_session_t *ap_new_session __P((aproxy_t *, ip_t *,
fr_info_t *, nat_t *));
-static int ap_matchsrcdst __P((ap_session_t *, struct in_addr,
- struct in_addr, void *, u_short, u_short));
#define AP_SESS_SIZE 53
@@ -94,6 +91,7 @@ static int ap_matchsrcdst __P((ap_session_t *, struct in_addr,
#endif
ap_session_t *ap_sess_tab[AP_SESS_SIZE];
+ap_session_t *ap_sess_list = NULL;
aproxy_t ap_proxies[] = {
#ifdef IPF_FTP_PROXY
{ "ftp", (char)IPPROTO_TCP, 0, 0, ippr_ftp_init, ippr_ftp_in, ippr_ftp_out },
@@ -119,79 +117,32 @@ ipnat_t *nat;
}
-static int
-ap_matchsrcdst(aps, src, dst, tcp, sport, dport)
-ap_session_t *aps;
-struct in_addr src, dst;
-void *tcp;
-u_short sport, dport;
-{
- if (aps->aps_dst.s_addr == dst.s_addr) {
- if ((aps->aps_src.s_addr == src.s_addr) &&
- (!tcp || ((sport == aps->aps_sport) &&
- (dport == aps->aps_dport))))
- return 1;
- } else if (aps->aps_dst.s_addr == src.s_addr) {
- if ((aps->aps_src.s_addr == dst.s_addr) &&
- (!tcp || ((sport == aps->aps_dport) &&
- (dport == aps->aps_sport))))
- return 1;
- }
- return 0;
-}
-
-
-static ap_session_t *ap_find(ip, tcp)
-ip_t *ip;
-tcphdr_t *tcp;
-{
- register u_char p = ip->ip_p;
- register ap_session_t *aps;
- register u_short sp, dp;
- register u_long hv;
- struct in_addr src, dst;
-
- src = ip->ip_src, dst = ip->ip_dst;
- sp = dp = 0; /* XXX gcc -Wunitialized */
-
- hv = ip->ip_src.s_addr ^ ip->ip_dst.s_addr;
- hv *= 651733;
- if (tcp) {
- sp = tcp->th_sport;
- dp = tcp->th_dport;
- hv ^= (sp + dp);
- hv *= 5;
- }
- hv %= AP_SESS_SIZE;
-
- for (aps = ap_sess_tab[hv]; aps; aps = aps->aps_next)
- if ((aps->aps_p == p) &&
- ap_matchsrcdst(aps, src, dst, tcp, sp, dp))
- break;
- return aps;
-}
-
-
/*
* Allocate a new application proxy structure and fill it in with the
* relevant details. call the init function once complete, prior to
* returning.
*/
-static ap_session_t *ap_new_session(apr, ip, tcp, fin, nat)
+static ap_session_t *ap_new_session(apr, ip, fin, nat)
aproxy_t *apr;
ip_t *ip;
-tcphdr_t *tcp;
fr_info_t *fin;
nat_t *nat;
{
register ap_session_t *aps;
+ tcphdr_t *tcp;
u_short dport;
- u_long hv;
+ u_int hv;
if (!apr || (apr && (apr->apr_flags & APR_DELETE)) ||
(ip->ip_p != apr->apr_p))
return NULL;
+
+ if (!(fin->fin_fi.fi_fl & FI_TCPUDP))
+ tcp = NULL;
+ else
+ tcp = (tcphdr_t *)fin->fin_dp;
dport = nat->nat_ptr->in_dport;
+
if ((tcp && (tcp->th_dport != dport)) || (!tcp && dport))
return NULL;
@@ -211,16 +162,20 @@ nat_t *nat;
aps->aps_src = ip->ip_src;
aps->aps_dst = ip->ip_dst;
aps->aps_p = ip->ip_p;
- aps->aps_tout = 1200; /* XXX */
if (tcp) {
aps->aps_sport = tcp->th_sport;
aps->aps_dport = tcp->th_dport;
}
aps->aps_data = NULL;
aps->aps_psiz = 0;
- aps->aps_next = ap_sess_tab[hv];
+ aps->aps_hnext = ap_sess_tab[hv];
+ aps->aps_next = ap_sess_list;
+ ap_sess_list = aps;
+ aps->aps_nat = nat;
+ aps->aps_hv = hv;
+ nat->nat_aps = aps;
ap_sess_tab[hv] = aps;
- (void) (*apr->apr_init)(fin, ip, tcp, aps, nat);
+ (void) (*apr->apr_init)(fin, ip, aps, nat);
return aps;
}
@@ -229,23 +184,21 @@ nat_t *nat;
* check to see if a packet should be passed through an active proxy routine
* if one has been setup for it.
*/
-int ap_check(ip, tcp, fin, nat)
+int ap_check(ip, fin, nat)
ip_t *ip;
-tcphdr_t *tcp;
fr_info_t *fin;
nat_t *nat;
{
ap_session_t *aps;
aproxy_t *apr;
+ tcphdr_t *tcp = NULL;
u_32_t sum;
int err;
- if (!(fin->fin_fi.fi_fl & FI_TCPUDP))
- tcp = NULL;
-
- if ((aps = ap_find(ip, tcp)) ||
- (aps = ap_new_session(nat->nat_ptr->in_apr, ip, tcp, fin, nat))) {
+ if ((aps = nat->nat_aps) ||
+ (aps = ap_new_session(nat->nat_ptr->in_apr, ip, fin, nat))) {
if (ip->ip_p == IPPROTO_TCP) {
+ tcp = (tcphdr_t *)fin->fin_dp;
/*
* verify that the checksum is correct. If not, then
* don't do anything with this packet.
@@ -260,32 +213,31 @@ nat_t *nat;
frstats[fin->fin_out].fr_tcpbad++;
return -1;
}
- fr_tcp_age(&aps->aps_tout, aps->aps_state, ip, fin,
- tcp->th_sport == aps->aps_sport);
}
apr = aps->aps_apr;
err = 0;
if (fin->fin_out) {
if (apr->apr_outpkt)
- err = (*apr->apr_outpkt)(fin, ip, tcp,
- aps, nat);
+ err = (*apr->apr_outpkt)(fin, ip, aps, nat);
} else {
if (apr->apr_inpkt)
- err = (*apr->apr_inpkt)(fin, ip, tcp,
- aps, nat);
+ err = (*apr->apr_inpkt)(fin, ip, aps, nat);
}
- if (err == 2) {
+
+ if (tcp != NULL) {
+ err = ap_fixseqack(fin, ip, aps, err);
#if SOLARIS && defined(_KERNEL)
- tcp->th_sum = fr_tcpsum(fin->fin_qfm, ip,
- tcp, ip->ip_len);
+ tcp->th_sum = fr_tcpsum(fin->fin_qfm, ip, tcp,
+ ip->ip_len);
#else
tcp->th_sum = fr_tcpsum(*(mb_t **)fin->fin_mp, ip,
tcp, ip->ip_len);
#endif
- err = 0;
}
- return err;
+ aps->aps_bytes += ip->ip_len;
+ aps->aps_pkts++;
+ return 2;
}
return -1;
}
@@ -317,38 +269,128 @@ aproxy_t *ap;
void aps_free(aps)
ap_session_t *aps;
{
- if (aps->aps_data && aps->aps_psiz)
- KFREES(aps->aps_data, aps->aps_psiz);
- KFREE(aps);
-}
+ ap_session_t *a, **ap;
+ u_int hv;
+ if (!aps)
+ return;
-void ap_unload()
-{
- ap_session_t *aps;
- int i;
+ hv = aps->aps_hv;
- for (i = 0; i < AP_SESS_SIZE; i++)
- while ((aps = ap_sess_tab[i])) {
- ap_sess_tab[i] = aps->aps_next;
- aps_free(aps);
+ for (ap = ap_sess_tab + hv; (a = *ap); ap = &a->aps_hnext)
+ if (a == aps) {
+ *ap = a->aps_hnext;
+ break;
+ }
+
+ for (ap = &ap_sess_list; (a = *ap); ap = &a->aps_next)
+ if (a == aps) {
+ *ap = a->aps_next;
+ break;
}
+
+ if (a) {
+ if (aps->aps_data && aps->aps_psiz)
+ KFREES(aps->aps_data, aps->aps_psiz);
+ KFREE(aps);
+ }
}
-void ap_expire()
+int ap_fixseqack(fin, ip, aps, inc)
+fr_info_t *fin;
+ip_t *ip;
+ap_session_t *aps;
+int inc;
{
- ap_session_t *aps, **apsp;
- int i;
-
- for (i = 0; i < AP_SESS_SIZE; i++)
- for (apsp = &ap_sess_tab[i]; (aps = *apsp); ) {
- aps->aps_tout--;
- if (!aps->aps_tout) {
- ap_sess_tab[i] = aps->aps_next;
- aps_free(aps);
- *apsp = aps->aps_next;
- } else
- apsp = &aps->aps_next;
+ int sel, ch = 0, out, nlen;
+ u_32_t seq1, seq2;
+ tcphdr_t *tcp;
+
+ tcp = (tcphdr_t *)fin->fin_dp;
+ out = fin->fin_out;
+ nlen = ip->ip_len;
+ nlen -= (ip->ip_hl << 2) + (tcp->th_off << 2);
+
+ if (out != 0) {
+ seq1 = (u_32_t)ntohl(tcp->th_seq);
+ sel = aps->aps_sel[out];
+
+ /* switch to other set ? */
+ if ((aps->aps_seqmin[!sel] > aps->aps_seqmin[sel]) &&
+ (seq1 > aps->aps_seqmin[!sel]))
+ sel = aps->aps_sel[out] = !sel;
+
+ if (aps->aps_seqoff[sel]) {
+ seq2 = aps->aps_seqmin[sel] - aps->aps_seqoff[sel];
+ if (seq1 > seq2) {
+ seq2 = aps->aps_seqoff[sel];
+ seq1 += seq2;
+ tcp->th_seq = htonl(seq1);
+ ch = 1;
+ }
+ }
+
+ if (inc && (seq1 > aps->aps_seqmin[!sel])) {
+ aps->aps_seqmin[!sel] = seq1 + nlen - 1;
+ aps->aps_seqoff[!sel] = aps->aps_seqoff[sel] + inc;
+ }
+
+ /***/
+
+ seq1 = ntohl(tcp->th_ack);
+ sel = aps->aps_sel[1 - out];
+
+ /* switch to other set ? */
+ if ((aps->aps_ackmin[!sel] > aps->aps_ackmin[sel]) &&
+ (seq1 > aps->aps_ackmin[!sel]))
+ sel = aps->aps_sel[1 - out] = !sel;
+
+ if (aps->aps_ackoff[sel] && (seq1 > aps->aps_ackmin[sel])) {
+ seq2 = aps->aps_ackoff[sel];
+ tcp->th_ack = htonl(seq1 - seq2);
+ ch = 1;
}
+ } else {
+ seq1 = ntohl(tcp->th_seq);
+ sel = aps->aps_sel[out];
+
+ /* switch to other set ? */
+ if ((aps->aps_ackmin[!sel] > aps->aps_ackmin[sel]) &&
+ (seq1 > aps->aps_ackmin[!sel]))
+ sel = aps->aps_sel[out] = !sel;
+
+ if (aps->aps_ackoff[sel]) {
+ seq2 = aps->aps_ackmin[sel] -
+ aps->aps_ackoff[sel];
+ if (seq1 > seq2) {
+ seq2 = aps->aps_ackoff[sel];
+ seq1 += seq2;
+ tcp->th_seq = htonl(seq1);
+ ch = 1;
+ }
+ }
+
+ if (inc && (seq1 > aps->aps_ackmin[!sel])) {
+ aps->aps_ackmin[!sel] = seq1 + nlen - 1;
+ aps->aps_ackoff[!sel] = aps->aps_ackoff[sel] + inc;
+ }
+
+ /***/
+
+ seq1 = ntohl(tcp->th_ack);
+ sel = aps->aps_sel[1 - out];
+
+ /* switch to other set ? */
+ if ((aps->aps_seqmin[!sel] > aps->aps_seqmin[sel]) &&
+ (seq1 > aps->aps_seqmin[!sel]))
+ sel = aps->aps_sel[1 - out] = !sel;
+
+ if (aps->aps_seqoff[sel] && (seq1 > aps->aps_seqmin[sel])) {
+ seq2 = aps->aps_seqoff[sel];
+ tcp->th_ack = htonl(seq1 - seq2);
+ ch = 1;
+ }
+ }
+ return ch ? 2 : 0;
}
diff --git a/sys/netinet/ip_proxy.h b/sys/netinet/ip_proxy.h
index 8aeafe5fd8a..e13444be48f 100644
--- a/sys/netinet/ip_proxy.h
+++ b/sys/netinet/ip_proxy.h
@@ -1,12 +1,12 @@
-/* $OpenBSD: ip_proxy.h,v 1.2 1998/02/17 01:39:06 dgregor Exp $ */
+/* $OpenBSD: ip_proxy.h,v 1.3 1999/02/05 05:58:54 deraadt Exp $ */
/*
- * Copyright (C) 1997 by Darren Reed.
+ * Copyright (C) 1997-1998 by Darren Reed.
*
* Redistribution and use in source and binary forms are permitted
* provided that this notice is preserved and due credit is given
* to the original author and the contributors.
*
- * $Id: ip_proxy.h,v 1.2 1998/02/17 01:39:06 dgregor Exp $
+ * $Id: ip_proxy.h,v 1.3 1999/02/05 05:58:54 deraadt Exp $
*/
#ifndef __IP_PROXY_H__
@@ -27,9 +27,11 @@ struct ipnat;
typedef struct ap_tcp {
u_short apt_sport; /* source port */
u_short apt_dport; /* destination port */
- short apt_sel; /* seqoff/after set selector */
+ short apt_sel[2]; /* {seq,ack}{off,min} set selector */
short apt_seqoff[2]; /* sequence # difference */
- tcp_seq apt_after[2]; /* don't change seq-off until after this */
+ tcp_seq apt_seqmin[2]; /* don't change seq-off until after this */
+ short apt_ackoff[2]; /* sequence # difference */
+ tcp_seq apt_ackmin[2]; /* don't change seq-off until after this */
u_char apt_state[2]; /* connection state */
} ap_tcp_t;
@@ -47,12 +49,14 @@ typedef struct ap_session {
struct ap_tcp apu_tcp;
struct ap_udp apu_udp;
} aps_un;
+ u_int aps_hv;
u_int aps_flags;
- QUAD_T aps_bytes; /* bytes sent */
- QUAD_T aps_pkts; /* packets sent */
- u_long aps_tout; /* time left before expiring */
+ U_QUAD_T aps_bytes; /* bytes sent */
+ U_QUAD_T aps_pkts; /* packets sent */
+ void *aps_nat; /* pointer back to nat struct */
void *aps_data; /* private data */
int aps_psiz; /* size of private data */
+ struct ap_session *aps_hnext;
struct ap_session *aps_next;
} ap_session_t ;
@@ -60,8 +64,10 @@ typedef struct ap_session {
#define aps_dport aps_un.apu_tcp.apt_dport
#define aps_sel aps_un.apu_tcp.apt_sel
#define aps_seqoff aps_un.apu_tcp.apt_seqoff
-#define aps_after aps_un.apu_tcp.apt_after
+#define aps_seqmin aps_un.apu_tcp.apt_seqmin
#define aps_state aps_un.apu_tcp.apt_state
+#define aps_ackoff aps_un.apu_tcp.apt_ackoff
+#define aps_ackmin aps_un.apu_tcp.apt_ackmin
typedef struct aproxy {
@@ -69,11 +75,11 @@ typedef struct aproxy {
u_char apr_p; /* protocol */
int apr_ref; /* +1 per rule referencing it */
int apr_flags;
- int (* apr_init) __P((fr_info_t *, ip_t *, tcphdr_t *,
+ int (* apr_init) __P((fr_info_t *, ip_t *,
ap_session_t *, struct nat *));
- int (* apr_inpkt) __P((fr_info_t *, ip_t *, tcphdr_t *,
+ int (* apr_inpkt) __P((fr_info_t *, ip_t *,
ap_session_t *, struct nat *));
- int (* apr_outpkt) __P((fr_info_t *, ip_t *, tcphdr_t *,
+ int (* apr_outpkt) __P((fr_info_t *, ip_t *,
ap_session_t *, struct nat *));
} aproxy_t;
@@ -81,14 +87,23 @@ typedef struct aproxy {
extern ap_session_t *ap_sess_tab[AP_SESS_SIZE];
+extern ap_session_t *ap_sess_list;
extern aproxy_t ap_proxies[];
extern int ap_ok __P((ip_t *, tcphdr_t *, struct ipnat *));
-extern void ap_unload __P((void));
extern void ap_free __P((aproxy_t *));
extern void aps_free __P((ap_session_t *));
-extern int ap_check __P((ip_t *, tcphdr_t *, fr_info_t *, struct nat *));
+extern int ap_check __P((ip_t *, fr_info_t *, struct nat *));
extern aproxy_t *ap_match __P((u_char, char *));
-extern void ap_expire __P((void));
+extern int ap_fixseqack __P((fr_info_t *, ip_t *, ap_session_t *, int inc));
+
#endif /* __IP_PROXY_H__ */
+
+
+
+
+
+
+
+
diff --git a/sys/netinet/ip_state.c b/sys/netinet/ip_state.c
index 3130877b2d9..51aa6302d36 100644
--- a/sys/netinet/ip_state.c
+++ b/sys/netinet/ip_state.c
@@ -1,6 +1,6 @@
-/* $OpenBSD: ip_state.c,v 1.12 1998/09/15 09:51:19 pattonme Exp $ */
+/* $OpenBSD: ip_state.c,v 1.13 1999/02/05 05:58:54 deraadt Exp $ */
/*
- * Copyright (C) 1995-1997 by Darren Reed.
+ * Copyright (C) 1995-1998 by Darren Reed.
*
* Redistribution and use in source and binary forms are permitted
* provided that this notice is preserved and due credit is given
@@ -8,10 +8,15 @@
*/
#if !defined(lint)
static const char sccsid[] = "@(#)ip_state.c 1.8 6/5/96 (C) 1993-1995 Darren Reed";
-static const char rcsid[] = "@(#)$Id: ip_state.c,v 1.12 1998/09/15 09:51:19 pattonme Exp $";
+static const char rcsid[] = "@(#)$Id: ip_state.c,v 1.13 1999/02/05 05:58:54 deraadt Exp $";
#endif
+#include <sys/errno.h>
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/file.h>
#if !defined(_KERNEL) && !defined(KERNEL) && !defined(__KERNEL__)
+# include <stdio.h>
# include <stdlib.h>
# include <string.h>
#else
@@ -20,10 +25,6 @@ static const char rcsid[] = "@(#)$Id: ip_state.c,v 1.12 1998/09/15 09:51:19 patt
# include <linux/module.h>
# endif
#endif
-#include <sys/errno.h>
-#include <sys/types.h>
-#include <sys/param.h>
-#include <sys/file.h>
#if defined(KERNEL) && (__FreeBSD_version >= 220000)
# include <sys/filio.h>
# include <sys/fcntl.h>
@@ -87,7 +88,7 @@ ipstate_t *ips_table[IPSTATE_SIZE];
int ips_num = 0;
ips_stat_t ips_stats;
#if (SOLARIS || defined(__sgi)) && defined(_KERNEL)
-extern krwlock_t ipf_state;
+extern KRWLOCK_T ipf_state;
extern kmutex_t ipf_rw;
#endif
@@ -223,7 +224,7 @@ u_int pass;
register ipstate_t *is = &ips;
register u_int hv;
- if ((ip->ip_off & 0x1fff) || (fin->fin_fi.fi_fl & FI_SHORT))
+ if ((ip->ip_off & IP_OFFMASK) || (fin->fin_fi.fi_fl & FI_SHORT))
return -1;
if (ips_num == IPSTATE_MAX) {
ips_stats.iss_max++;
@@ -369,8 +370,8 @@ ip_t *ip;
tcphdr_t *tcp;
{
register int seqskew, ackskew;
- register u_short swin, dwin;
register tcp_seq seq, ack;
+ u_short win;
int source;
/*
@@ -390,7 +391,7 @@ tcphdr_t *tcp;
*/
is->is_seq = seq;
seqskew = seq - is->is_seq;
- ackskew = ack - is->is_ack;
+ ackskew = (ack - 1) - is->is_ack;
} else {
if (!is->is_ack)
/*
@@ -398,7 +399,7 @@ tcphdr_t *tcp;
*/
is->is_ack = seq;
ackskew = seq - is->is_ack;
- seqskew = ack - is->is_seq;
+ seqskew = (ack - 1) - is->is_seq;
}
/*
@@ -414,23 +415,18 @@ tcphdr_t *tcp;
* window size of the connection, store these values and match
* the packet.
*/
- if (source) {
- swin = is->is_swin;
- dwin = is->is_dwin;
- } else {
- dwin = is->is_swin;
- swin = is->is_dwin;
- }
-
- if ((seqskew <= dwin) && (ackskew <= swin)) {
+ win = ntohs(tcp->th_win);
+ if ((seqskew <= is->is_dwin) && (ackskew <= is->is_swin)) {
if (source) {
is->is_seq = seq;
is->is_ack = ack;
- is->is_swin = ntohs(tcp->th_win);
+ if (win != 0)
+ is->is_swin = win;
} else {
is->is_seq = ack;
is->is_ack = seq;
- is->is_dwin = ntohs(tcp->th_win);
+ if (win != 0)
+ is->is_dwin = win;
}
ATOMIC_INC(ips_stats.iss_hits);
is->is_pkts++;
@@ -529,7 +525,7 @@ fr_info_t *fin;
tcphdr_t *tcp;
u_int hv, hlen, pass;
- if ((ip->ip_off & 0x1fff) || (fin->fin_fi.fi_fl & FI_SHORT))
+ if ((ip->ip_off & IP_OFFMASK) || (fin->fin_fi.fi_fl & FI_SHORT))
return 0;
hlen = fin->fin_hlen;
@@ -657,6 +653,7 @@ void fr_stateunload()
*isp = is->is_next;
KFREE(is);
}
+ ips_num = 0;
RWLOCK_EXIT(&ipf_state);
}
@@ -793,16 +790,20 @@ u_short type;
size_t sizes[1];
int types[1];
+ ipsl.isl_type = type;
ipsl.isl_pkts = is->is_pkts;
ipsl.isl_bytes = is->is_bytes;
ipsl.isl_src = is->is_src;
ipsl.isl_dst = is->is_dst;
ipsl.isl_p = is->is_p;
ipsl.isl_flags = is->is_flags;
- ipsl.isl_type = type;
if (ipsl.isl_p == IPPROTO_TCP || ipsl.isl_p == IPPROTO_UDP) {
ipsl.isl_sport = is->is_sport;
ipsl.isl_dport = is->is_dport;
+ if (ipsl.isl_p == IPPROTO_TCP) {
+ ipsl.isl_state[0] = is->is_state[0];
+ ipsl.isl_state[1] = is->is_state[1];
+ }
} else if (ipsl.isl_p == IPPROTO_ICMP)
ipsl.isl_itype = is->is_icmp.ics_type;
else {
diff --git a/sys/netinet/ip_state.h b/sys/netinet/ip_state.h
index db8d3f750aa..20aa1b819d3 100644
--- a/sys/netinet/ip_state.h
+++ b/sys/netinet/ip_state.h
@@ -1,13 +1,13 @@
-/* $OpenBSD: ip_state.h,v 1.8 1998/09/15 09:51:19 pattonme Exp $ */
+/* $OpenBSD: ip_state.h,v 1.9 1999/02/05 05:58:54 deraadt Exp $ */
/*
- * Copyright (C) 1995-1997 by Darren Reed.
+ * Copyright (C) 1995-1998 by Darren Reed.
*
* Redistribution and use in source and binary forms are permitted
* provided that this notice is preserved and due credit is given
* to the original author and the contributors.
*
* @(#)ip_state.h 1.3 1/12/96 (C) 1995 Darren Reed
- * $Id: ip_state.h,v 1.8 1998/09/15 09:51:19 pattonme Exp $
+ * $Id: ip_state.h,v 1.9 1999/02/05 05:58:54 deraadt Exp $
*/
#ifndef __IP_STATE_H__
#define __IP_STATE_H__
@@ -88,6 +88,7 @@ typedef struct ipslog {
struct in_addr isl_dst;
u_char isl_p;
u_char isl_flags;
+ u_char isl_state[2];
u_short isl_type;
union {
u_short isl_filler[2];