diff options
author | Theo de Raadt <deraadt@cvs.openbsd.org> | 1999-02-05 05:58:55 +0000 |
---|---|---|
committer | Theo de Raadt <deraadt@cvs.openbsd.org> | 1999-02-05 05:58:55 +0000 |
commit | e689014cc2747748c76a2b3f492470f1362031e2 (patch) | |
tree | 30f2062ed5c01f4b6d08d952c92e6e0c432b485f /sys/netinet | |
parent | 20a077f722546853c96c85750162a4b9c096033b (diff) |
ipf 3.2.10; work by kjell
Diffstat (limited to 'sys/netinet')
-rw-r--r-- | sys/netinet/fil.c | 220 | ||||
-rw-r--r-- | sys/netinet/ip_auth.c | 17 | ||||
-rw-r--r-- | sys/netinet/ip_auth.h | 6 | ||||
-rw-r--r-- | sys/netinet/ip_fil.c | 23 | ||||
-rw-r--r-- | sys/netinet/ip_fil.h | 59 | ||||
-rw-r--r-- | sys/netinet/ip_fil_compat.h | 91 | ||||
-rw-r--r-- | sys/netinet/ip_frag.c | 34 | ||||
-rw-r--r-- | sys/netinet/ip_frag.h | 6 | ||||
-rw-r--r-- | sys/netinet/ip_ftp_pxy.c | 381 | ||||
-rw-r--r-- | sys/netinet/ip_log.c | 59 | ||||
-rw-r--r-- | sys/netinet/ip_nat.c | 283 | ||||
-rw-r--r-- | sys/netinet/ip_nat.h | 19 | ||||
-rw-r--r-- | sys/netinet/ip_proxy.c | 270 | ||||
-rw-r--r-- | sys/netinet/ip_proxy.h | 45 | ||||
-rw-r--r-- | sys/netinet/ip_state.c | 51 | ||||
-rw-r--r-- | sys/netinet/ip_state.h | 7 |
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]; |