Upgraded IPFilter to 4.1.8

This commit is contained in:
martti 2005-04-03 15:05:30 +00:00
parent c775aec128
commit 58b8abcbf8
25 changed files with 1406 additions and 649 deletions

74
dist/ipf/HISTORY vendored
View File

@ -10,6 +10,80 @@
# and especially those who have found the time to port IP Filter to new
# platforms.
#
4.1.8 - Released 29 March 2005
include path from Phil Dibowitz for sorting ipfstat -t output by source or
destination port.
fix a bug in printing rules where interface names could not be printed,
even if they're in the rule structure.
fix BSD/kupgrade to correctly change ipfilter lkm Makefile for FreeBSD
add 2 new features to SIOCGNATL:
- if IPN_FINDFORWARD is set, check if the respective MAP is already
present in the outbound table
- if IPN_IN is set, search for a matching MAP entry instead of RDR
(Peter Potsma)
turn off function inlining for freebsd 5.3+
UDP doesn't pullup enough data which can sometimes cause a panic.
Fix other protocols, as required, where a similar problem may exist.
overhaul the timeout queue management, especially that for user defined queues
which are now only freed in an orderly manner.
4.1.7 - Released 13 March 2005
Using the GRE call field is almost impossible because it is unbalanced and
both call fields are not present in each v1 header.
Fix a problem where it was possible to load duplicate rules into ipf
patch from John Wehle to address problems with fastroute on solaris
Copying data out for ipf -z failed because it tried to copy out to an address
that is a kernel pointer in user space.
add "ip" timeout for both NAT & state that's for non-TCP/UDP/ICMP
synch up with NetBSD's changes
fix problems parsing long lines of text in the ftp proxy where they would not
be parsed properly and stop the session from working
enhance the PPTP proxy so that it tries to decode messages in the TCP stream
so it knows when to create and destroy the state/nat sessions for GRE. There
are also 4 new regression tests for it, testing map/rdr rules.
impose some limits on the size of data that can be moved with SIOCSTPUT in
the NAT code and also prevent a duplicate session entry from being created
using this method.
add a new flag (IPN_FINDFORWARD) to NAT code that can be used with SIOCGNATL
to check if it is possible to create an outgoing transparent NAT mapping to
compliment the redirect being investigated.
Linux requires that the checksums in the IP header get adjusted
only resolve unknown interfaces in fr_stinsert, and nuke all interface pointers
in SIOCSTPUT to prevent bad data being loaded from userspace.
make the byte counting for state correct (was counting data from ICMP packet
twice)
print out the keyword "frag-body" if the flag is set.
fix ipfs loading/restoring NAT sessions
patch from Frank to correctly format IP addresses in ipfstat -t output
parsing port numbers in ipf/ipnat was confusing as the port number was returned
in an int that was also overloaded to be the suceess/failure. instead, change
the port using pass by reference and only use the return value for indicating
success or failure.
4.1.6 - Released 19 February 2005
add a new timeout number to NAT (fr_defnatipage) that is used for all

6
dist/ipf/ipf.h vendored
View File

@ -1,4 +1,4 @@
/* $NetBSD: ipf.h,v 1.9 2005/02/19 21:30:24 martti Exp $ */
/* $NetBSD: ipf.h,v 1.10 2005/04/03 15:05:30 martti Exp $ */
/*
* Copyright (C) 1993-2001, 2003 by Darren Reed.
@ -6,7 +6,7 @@
* See the IPFILTER.LICENCE file for details on licencing.
*
* @(#)ipf.h 1.12 6/5/96
* Id: ipf.h,v 2.71.2.5 2005/02/01 02:44:34 darrenr Exp
* Id: ipf.h,v 2.71.2.6 2005/02/21 05:05:29 darrenr Exp
*/
#ifndef __IPF_H__
@ -196,7 +196,7 @@ extern char *fac_toname __P((int));
extern int fac_findname __P((char *));
extern void fill6bits __P((int, u_int *));
extern int gethost __P((char *, u_32_t *));
extern int getport __P((struct frentry *, char *));
extern int getport __P((struct frentry *, char *, u_short *));
extern int getportproto __P((char *, int));
extern int getproto __P((char *));
extern char *getline __P((char *, size_t, FILE *, int *));

View File

@ -1,8 +1,9 @@
#include "ipf.h"
int getport(fr, name)
int getport(fr, name, port)
frentry_t *fr;
char *name;
u_short *port;
{
struct protoent *p;
struct servent *s;
@ -10,8 +11,10 @@ char *name;
if (fr == NULL || fr->fr_type != FR_T_IPF) {
s = getservbyname(name, NULL);
if (s != NULL)
return s->s_port;
if (s != NULL) {
*port = s->s_port;
return 0;
}
return -1;
}
@ -27,13 +30,15 @@ char *name;
s = getservbyname(name, "udp");
if (s == NULL || s->s_port != p1)
return -1;
return p1;
*port = p1;
return 0;
}
p = getprotobynumber(fr->fr_proto);
s = getservbyname(name, p ? p->p_name : NULL);
if (s != NULL)
return s->s_port;
if (s != NULL) {
*port = s->s_port;
return 0;
}
return -1;
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: proxy.c,v 1.5 2005/02/19 21:30:25 martti Exp $ */
/* $NetBSD: proxy.c,v 1.6 2005/04/03 15:05:30 martti Exp $ */
/*
* Sample transparent proxy program.
@ -101,7 +101,7 @@ char *argv[];
* Open the NAT device and lookup the mapping pair.
*/
fd = open(IPNAT_NAME, O_RDONLY);
if (ioctl(fd, SIOCGNATL, &natlookp) == -1) {
if (ioctl(fd, SIOCGNATL, &obj) == -1) {
perror("ioctl(SIOCGNATL)");
exit(-1);
}

View File

@ -67,6 +67,7 @@ static struct wordtab logwords[33];
frentry_t fr;
frtuc_t *frt;
struct alist_s *alist;
u_short port;
struct {
u_short p1;
u_short p2;
@ -79,7 +80,8 @@ static struct wordtab logwords[33];
union i6addr ip6;
};
%type <num> portnum facility priority icmpcode seclevel secname icmptype
%type <port> portnum
%type <num> facility priority icmpcode seclevel secname icmptype
%type <num> opt compare range opttype flagset optlist ipv6hdrlist ipv6hdr
%type <num> portc porteq
%type <ipa> hostname ipv4 ipv4mask ipv4_16 ipv4_24
@ -1084,15 +1086,15 @@ stateopt:
;
portnum:
servicename { $$ = getport(frc, $1);
if ($$ == -1)
servicename { if (getport(frc, $1, &($$)) == -1)
yyerror("service unknown");
$$ = ntohs($$);
free($1);
}
| YY_NUMBER { $$ = $1;
if ($$ < 0 || $$ > 65535)
| YY_NUMBER { if ($1 > 65535) /* Unsigned */
yyerror("invalid port number");
else
$$ = $1;
}
;
@ -2042,7 +2044,7 @@ void *ptr;
if ((opts & OPT_ZERORULEST) != 0) {
if ((*ioctlfunc)(fd, add, (void *)&obj) == -1) {
if ((opts & OPT_DONOTHING) != 0) {
if ((opts & OPT_DONOTHING) == 0) {
fprintf(stderr, "%d:", yylineNum);
perror("ioctl(SIOCZRLST)");
}

21
dist/ipf/tools/ipfs.c vendored
View File

@ -1,4 +1,4 @@
/* $NetBSD: ipfs.c,v 1.5 2005/02/08 07:01:54 martti Exp $ */
/* $NetBSD: ipfs.c,v 1.6 2005/04/03 15:05:30 martti Exp $ */
/*
* Copyright (C) 1999-2001, 2003 by Darren Reed.
@ -587,16 +587,12 @@ char *file;
return 1;
}
if (ipn.ipn_dsize > 0) {
n = ipn.ipn_dsize;
in = (nat_save_t *)malloc(ipn.ipn_dsize);
if (!in)
break;
if (n > sizeof(ipn.ipn_data))
n -= sizeof(ipn.ipn_data);
else
n = 0;
in = malloc(sizeof(*in) + n);
if (!in)
break;
if (ipn.ipn_dsize > sizeof(ipn)) {
n = ipn.ipn_dsize - sizeof(ipn);
if (n > 0) {
s = in->ipn_data + sizeof(in->ipn_data);
i = read(nfd, s, n);
@ -610,9 +606,6 @@ char *file;
return 1;
}
}
} else {
ipn.ipn_dsize = 0;
in = (nat_save_t *)malloc(sizeof(*in));
}
bcopy((char *)&ipn, (char *)in, sizeof(ipn));
@ -751,7 +744,7 @@ char *file;
if (opts & OPT_VERBOSE)
printf("Got nat next %p ipn_dsize %d ng_sz %d\n",
ipnp->ipn_next, ipnp->ipn_dsize, ng.ng_sz);
if (write(nfd, ipnp, ng.ng_sz) != ng.ng_sz) {
if (write(nfd, ipnp, ipnp->ipn_dsize) != ipnp->ipn_dsize) {
perror("nat:write");
close(nfd);
free(ipnp);

View File

@ -1,4 +1,4 @@
/* $NetBSD: ipfstat.c,v 1.9 2005/02/08 07:01:54 martti Exp $ */
/* $NetBSD: ipfstat.c,v 1.10 2005/04/03 15:05:30 martti Exp $ */
/*
* Copyright (C) 1993-2001, 2003 by Darren Reed.
@ -70,7 +70,7 @@
#if !defined(lint)
static const char sccsid[] = "@(#)fils.c 1.21 4/20/96 (C) 1993-2000 Darren Reed";
static const char rcsid[] = "@(#)Id: ipfstat.c,v 1.44.2.9 2004/12/09 19:41:26 darrenr Exp";
static const char rcsid[] = "@(#)Id: ipfstat.c,v 1.44.2.11 2005/03/30 14:09:57 darrenr Exp";
#endif
#ifdef __hpux
@ -107,8 +107,10 @@ int ipf_fd = -1;
#define STSORT_BYTES 2
#define STSORT_TTL 3
#define STSORT_SRCIP 4
#define STSORT_DSTIP 5
#define STSORT_MAX STSORT_DSTIP
#define STSORT_SRCPT 5
#define STSORT_DSTIP 6
#define STSORT_DSTPT 7
#define STSORT_MAX STSORT_DSTPT
#define STSORT_DEFAULT STSORT_BYTES
@ -153,7 +155,9 @@ static int sort_pkts __P((const void *, const void *));
static int sort_bytes __P((const void *, const void *));
static int sort_ttl __P((const void *, const void *));
static int sort_srcip __P((const void *, const void *));
static int sort_srcpt __P((const void *, const void *));
static int sort_dstip __P((const void *, const void *));
static int sort_dstpt __P((const void *, const void *));
#endif
@ -1175,10 +1179,18 @@ int topclosed;
qsort(tstable, tsentry + 1,
sizeof(statetop_t), sort_srcip);
break;
case STSORT_SRCPT:
qsort(tstable, tsentry +1,
sizeof(statetop_t), sort_srcpt);
break;
case STSORT_DSTIP:
qsort(tstable, tsentry + 1,
sizeof(statetop_t), sort_dstip);
break;
case STSORT_DSTPT:
qsort(tstable, tsentry + 1,
sizeof(statetop_t), sort_dstpt);
break;
default:
break;
}
@ -1257,9 +1269,15 @@ int topclosed;
case STSORT_SRCIP:
sprintf(str4, "src ip");
break;
case STSORT_SRCPT:
sprintf(str4, "src port");
break;
case STSORT_DSTIP:
sprintf(str4, "dest ip");
break;
case STSORT_DSTPT:
sprintf(str4, "dest port");
break;
default:
sprintf(str4, "unknown");
break;
@ -1273,18 +1291,27 @@ int topclosed;
printw("Src: %s, Dest: %s, Proto: %s, Sorted by: %s\n\n",
str1, str2, str3, str4);
/* need at least 14 + 7 characters */
if (srclen < 14)
srclen = 14;
if (dstlen < 14)
dstlen = 14;
/*
* For an IPv4 IP address we need at most 15 characters,
* 4 tuples of 3 digits, separated by 3 dots. Enforce this
* length, so the colums do not change positions based
* on the size of the IP address. This length makes the
* output fit in a 80 column terminal.
* We are lacking a good solution for IPv6 addresses (that
* can be longer that 15 characters), so we do not enforce
* a maximum on the IP field size.
*/
if (srclen < 15)
srclen = 15;
if (dstlen < 15)
dstlen = 15;
/* print column description */
winy += 2;
move(winy,0);
attron(A_BOLD);
printw("%-*s %-*s %3s %4s %7s %9s %9s\n",
srclen + 7, "Source IP", dstlen + 7, "Destination IP",
srclen + 6, "Source IP", dstlen + 6, "Destination IP",
"ST", "PR", "#pkts", "#bytes", "ttl");
attroff(A_BOLD);
@ -1313,7 +1340,7 @@ int topclosed;
}
winy++;
move(winy, 0);
printw("%-*s %-*s", srclen + 7, str1, dstlen + 7, str2);
printw("%-*s %-*s", srclen + 6, str1, dstlen + 6, str2);
/* print state */
sprintf(str1, "%X/%X", tp->st_state[0],
@ -1717,6 +1744,20 @@ const void *b;
return -1;
}
static int sort_srcpt(a, b)
const void *a;
const void *b;
{
register const statetop_t *ap = a;
register const statetop_t *bp = b;
if (htons(ap->st_sport) == htons(bp->st_sport))
return 0;
else if (htons(ap->st_sport) > htons(bp->st_sport))
return 1;
return -1;
}
static int sort_dstip(a, b)
const void *a;
const void *b;
@ -1742,4 +1783,19 @@ const void *b;
}
return -1;
}
static int sort_dstpt(a, b)
const void *a;
const void *b;
{
register const statetop_t *ap = a;
register const statetop_t *bp = b;
if (htons(ap->st_dport) == htons(bp->st_dport))
return 0;
else if (htons(ap->st_dport) > htons(bp->st_dport))
return 1;
return -1;
}
#endif

View File

@ -1,3 +1,5 @@
/* $NetBSD: ipnat_y.y,v 1.13 2005/04/03 15:05:30 martti Exp $ */
%{
#ifdef __FreeBSD__
# ifndef __FreeBSD_cc_version
@ -63,6 +65,7 @@ static void setnatproto __P((int));
struct in_addr ipa;
frentry_t fr;
frtuc_t *frt;
u_short port;
struct {
u_short p1;
u_short p2;
@ -87,7 +90,8 @@ static void setnatproto __P((int));
%token IPNY_ROUNDROBIN IPNY_FRAG IPNY_AGE IPNY_ICMPIDMAP IPNY_PROXY
%token IPNY_TCP IPNY_UDP IPNY_TCPUDP IPNY_STICKY IPNY_MSSCLAMP IPNY_TAG
%token IPNY_TLATE
%type <num> hexnumber compare range proto portspec
%type <port> portspec
%type <num> hexnumber compare range proto
%type <ipa> hostname ipv4
%type <ipp> addr nummask rhaddr
%type <pc> portstuff
@ -308,14 +312,14 @@ dip:
;
portspec:
YY_NUMBER { $$ = $1;
if ($$ < 0 || $$ > 65535)
YY_NUMBER { if ($1 > 65535) /* Unsigned */
yyerror("invalid port number");
else
$$ = $1;
}
| YY_STR { int p = getport(NULL, $1);
if (p < 0)
| YY_STR { if (getport(NULL, $1, &($$)) == -1)
yyerror("invalid port number");
$$ = ntohs(p);
$$ = ntohs($$);
}
;

View File

@ -1,4 +1,4 @@
# $NetBSD: Makefile,v 1.9 2005/02/19 21:30:25 martti Exp $
# $NetBSD: Makefile,v 1.10 2005/04/03 15:05:30 martti Exp $
#
# (C)opyright 1993-1996 by Darren Reed.
#
@ -28,7 +28,7 @@ ptests: i1 i2 i3 i4 i5 i6 i7 i8 i9 i10 i11 i12 i13 i14 i15
ntests: n1 n2 n3 n4 n5 n6 n7 n8 n9 n10 n11 n12
nitests: ni1 ni2 ni3 ni4 ni5 ni6 ni7 ni8 ni9 ni10 ni11 ni12
nitests: ni1 ni2 ni3 ni4 ni5 ni6 ni7 ni8 ni9 ni10 ni11 ni12 ni13 ni14 ni15 ni16
intests: in1 in2 in3 in4 in5 in6
@ -56,7 +56,7 @@ n1 n2 n3 n4 n5 n6 n7 n8 n9 n10 n11 n12:
@${HOST_SH} ${.CURDIR}/nattest ${.CURDIR} \
`${AWK} "/^$@ / { print; } " ${.CURDIR}/test.format`
ni1 ni2 ni3 ni4 ni5 ni7 ni8 ni9 ni10 ni11 ni12:
ni1 ni2 ni3 ni4 ni5 ni7 ni8 ni9 ni10 ni11 ni12 ni13 ni14 ni15 ni16:
@${HOST_SH} ${.CURDIR}/natipftest ${.CURDIR} single \
`${AWK} "/^$@ / { print; } " ${.CURDIR}/test.format`
@ -92,7 +92,8 @@ clean:
/bin/rm -f f1 f2 f3 f4 f5 f6 f7 f8 f9 f10 f11 f12 f13 f14 f15 f16 f17
/bin/rm -f i1 i2 i3 i4 i5 i6 i7 i8 i9 i10 i11 i12 i13 i14 i15
/bin/rm -f n1 n2 n3 n4 n5 n6 n7 n8 n9 n10 n11 n12
/bin/rm -f ni1 ni2 ni3 ni4 ni5 ni6 ni7 ni8 ni9 ni10 ni11 ni12
/bin/rm -f ni1 ni2 ni3 ni4 ni5 ni6 ni7 ni8 ni9
/bin/rm -f ni10 ni11 ni12 ni13 ni14 ni15 ni16
/bin/rm -f in1 in2 in3 in4 in5 in6
/bin/rm -f p1 p2 p3 ip1
/bin/rm -f l1

View File

@ -3,7 +3,6 @@
4500 0028 0001 4000 ff06 02ff 0101 0101 96cb e002 8032 0015 bd6b c9c9 3786 76c5 5010 269c 5aa0 0000
4500 006f ffde 4000 ef06 5330 96cb e002 c0a8 0103 0015 8032 3786 76c5 bd6b c9c9 5018 269c 967e 0000 3232 302d 636f 6f6d 6273 2e61 6e75 2e65 6475 2e61 7520 4e63 4654 5064 2053 6572 7665 7220 2866 7265 6520 6564 7563 6174 696f 6e61 6c20 6c69 6365 6e73 6529 2072 6561 6479 2e0d 0a
4500 0028 0002 4000 ff06 02fe 0101 0101 96cb e002 8032 0015 bd6b c9c9 3786 770c 5010 269c 5a59 0000
ippr_ftp_server_valid:junk after cmd[220-Maintained by RSSS and RSPAS IT Staff (previously known as Coombs Comp]
4500 00c7 ffdf 4000 ef06 52d7 96cb e002 c0a8 0103 0015 8032 3786 770c bd6b c9c9 5018 269c 1087 0000 3232 302d 0d0a 3232 302d 4d61 696e 7461 696e 6564 2062 7920 5253 5353 2061 6e64 2052 5350 4153 2049 5420 5374 6166 6620 2870 7265 7669 6f75 736c 7920 6b6e 6f77 6e20 6173 2043 6f6f 6d62 7320 436f 6d70 7574 696e 6720 556e 6974 290d 0a32 3230 2d41 6e79 2070 726f 626c 656d 7320 636f 6e74 6163 7420 6674 706d 6173 7465 7240 636f 6f6d 6273 2e61 6e75 2e65 6475 2e61 750d 0a32 3230 2d0d 0a32 3230 200d 0a
4500 0028 0003 4000 ff06 02fd 0101 0101 96cb e002 8032 0015 bd6b c9c9 3786 77ab 5010 269c 59ba 0000
4500 0038 0004 4000 ff06 02ec 0101 0101 96cb e002 8032 0015 bd6b c9c9 3786 77ab 5018 269c d1c5 0000 5553 4552 2061 6e6f 6e79 6d6f 7573 0d0a

View File

@ -1,4 +1,4 @@
/* $NetBSD: fil.c,v 1.12 2005/03/26 18:08:42 christos Exp $ */
/* $NetBSD: fil.c,v 1.13 2005/04/03 15:05:30 martti Exp $ */
/*
* Copyright (C) 1993-2003 by Darren Reed.
@ -135,10 +135,10 @@ struct file;
#if !defined(lint)
#if defined(__NetBSD__)
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: fil.c,v 1.12 2005/03/26 18:08:42 christos Exp $");
__KERNEL_RCSID(0, "$NetBSD: fil.c,v 1.13 2005/04/03 15:05:30 martti Exp $");
#else
static const char sccsid[] = "@(#)fil.c 1.36 6/5/96 (C) 1993-2000 Darren Reed";
static const char rcsid[] = "@(#)Id: fil.c,v 2.243.2.50 2005/02/17 05:32:24 darrenr Exp";
static const char rcsid[] = "@(#)Id: fil.c,v 2.243.2.57 2005/03/28 10:47:50 darrenr Exp";
#endif
#endif
@ -365,6 +365,8 @@ int min;
if (off == 0) {
if (fin->fin_plen < fin->fin_hlen + min)
fi->fi_flx |= FI_SHORT;
} else if (off < min) {
fi->fi_flx |= FI_SHORT;
}
}
@ -488,6 +490,21 @@ fr_info_t *fin;
break;
}
hdrcount++;
/*
* It is important to note that at this point, for the
* extension headers (go != 0), the entire header may not have
* been pulled up when the code gets to this point. This is
* only done for "go != 0" because the other header handlers
* will all pullup their complete header and the other
* indicator of an incomplete header is that this eas just an
* extension header.
*/
if ((go != 0) && (p != IPPROTO_NONE) &&
(frpr_pullup(fin, 0) == -1)) {
p = IPPROTO_NONE;
go = 0;
}
}
fi->fi_p = p;
}
@ -606,6 +623,12 @@ fr_info_t *fin;
fin->fin_flx |= (FI_FRAG|FI_V6EXTHDR);
/* 8 is default length of extension hdr */
if ((fin->fin_dlen - 8) < 0) {
fin->fin_flx |= FI_SHORT;
return IPPROTO_NONE;
}
/*
* Only one frgament header is allowed per IPv6 packet but it need
* not be the first nor last (not possible in some cases.)
@ -621,7 +644,7 @@ fr_info_t *fin;
fin->fin_optmsk |= ip6exthdr[i].ol_bit;
if (frpr_pullup(fin, 8) == -1)
if (frpr_pullup(fin, sizeof(*frag)) == -1)
return IPPROTO_NONE;
hdr = fin->fin_dp;
@ -1079,13 +1102,13 @@ fr_info_t *fin;
fi = &fin->fin_fi;
fi->fi_flx |= FI_TCPUDP;
if (fin->fin_off != 0)
return;
if (frpr_pullup(fin, sizeof(*udp)) == -1)
return;
if (!fin->fin_off && (fin->fin_dlen > 3)) {
if (frpr_pullup(fin, sizeof(*udp)) == -1) {
fi->fi_flx |= FI_SHORT;
return;
}
if (fin->fin_dlen > 3) {
udp = fin->fin_dp;
fin->fin_sport = ntohs(udp->uh_sport);
@ -1170,6 +1193,8 @@ fr_info_t *fin;
static INLINE void frpr_gre(fin)
fr_info_t *fin;
{
grehdr_t *gre;
if (frpr_pullup(fin, sizeof(grehdr_t)) == -1)
return;
@ -1179,6 +1204,9 @@ fr_info_t *fin;
else if (fin->fin_v == 6)
frpr_short6(fin, sizeof(grehdr_t));
#endif
gre = fin->fin_dp;
if (GRE_REV(gre->gr_flags) == 1)
fin->fin_data[0] = gre->gr_call;
}
@ -2903,7 +2931,7 @@ nodata:
* SUCH DAMAGE.
*
* @(#)uipc_mbuf.c 8.2 (Berkeley) 1/4/94
* Id: fil.c,v 2.243.2.50 2005/02/17 05:32:24 darrenr Exp
* Id: fil.c,v 2.243.2.57 2005/03/28 10:47:50 darrenr Exp
*/
/*
* Copy data from an mbuf chain starting "off" bytes from the beginning,
@ -3873,10 +3901,10 @@ caddr_t data;
{
frentry_t frd, *fp, *f, **fprev, **ftail;
int error = 0, in, v;
void *ptr, *uptr;
u_int *p, *pp;
frgroup_t *fg;
char *group;
void *ptr;
fg = NULL;
fp = &frd;
@ -3900,6 +3928,7 @@ caddr_t data;
return EINVAL;
v = fp->fr_v;
uptr = fp->fr_data;
/*
* Only filter rules for IPv4 or IPv6 are accepted.
@ -3981,7 +4010,7 @@ caddr_t data;
}
for (f = *fprev; (f = *fprev) != NULL; fprev = &f->fr_next)
if (fp->fr_collect < f->fr_collect)
if (fp->fr_collect <= f->fr_collect)
break;
ftail = fprev;
@ -3993,9 +4022,9 @@ caddr_t data;
KMALLOCS(ptr, void *, fp->fr_dsize);
if (!ptr)
return ENOMEM;
error = COPYIN(fp->fr_data, ptr, fp->fr_dsize);
error = COPYIN(uptr, ptr, fp->fr_dsize);
} else {
ptr = fp->fr_data;
ptr = uptr;
error = 0;
}
if (error != 0) {
@ -4125,8 +4154,8 @@ caddr_t data;
for (; (f = *ftail) != NULL; ftail = &f->fr_next)
if ((fp->fr_cksum == f->fr_cksum) &&
(f->fr_dsize == fp->fr_dsize) &&
!bcmp((char *)&f->fr_dsize,
(char *)&fp->fr_dsize, FR_CMPSIZ) &&
!bcmp((char *)&f->fr_func,
(char *)&fp->fr_func, FR_CMPSIZ) &&
(!ptr || !f->fr_data ||
!bcmp((char *)ptr, (char *)f->fr_data, f->fr_dsize)))
break;
@ -4138,10 +4167,27 @@ caddr_t data;
if (f == NULL)
error = ESRCH;
else {
error = fr_outobj(data, f, IPFOBJ_FRENTRY);
/*
* Copy and reduce lock because of impending copyout.
* Well we should, but if we do then the atomicity of
* this call and the correctness of fr_hits and
* fr_bytes cannot be guaranteed. As it is, this code
* only resets them to 0 if they are successfully
* copied out into user space.
*/
bcopy((char *)f, (char *)fp, sizeof(*f));
/* MUTEX_DOWNGRADE(&ipf_mutex); */
/*
* When we copy this rule back out, set the data
* pointer to be what it was in user space.
*/
fp->fr_data = uptr;
error = fr_outobj(data, fp, IPFOBJ_FRENTRY);
if (error == 0) {
if (f->fr_dsize != 0 && f->fr_data != NULL)
error = COPYOUT(f->fr_data, ptr,
if ((f->fr_dsize != 0) && (uptr != NULL))
error = COPYOUT(f->fr_data, uptr,
f->fr_dsize);
if (error == 0) {
f->fr_hits = 0;
@ -4150,7 +4196,7 @@ caddr_t data;
}
}
if (ptr != NULL && makecopy != 0) {
if ((ptr != NULL) && (makecopy != 0)) {
KFREES(ptr, fp->fr_dsize);
}
RWLOCK_EXIT(&ipf_mutex);
@ -4323,8 +4369,8 @@ ipfunc_t funcptr;
/* */
/* Copy in a ipfunc_resolve_t structure and then fill in the missing field. */
/* This will either be the function name (if the pointer is set) or the */
/* function pointer if the name is set. When found, fill in the details so */
/* it can be copied back to user space. */
/* function pointer if the name is set. When found, fill in the other one */
/* so that the entire, complete, structure can be copied back to user space.*/
/* ------------------------------------------------------------------------ */
int fr_resolvefunc(data)
void *data;
@ -4541,6 +4587,16 @@ u_32_t *passp;
}
#endif /* IPFILTER_LOOKUP */
/*
* Queue functions
* ===============
* These functions manage objects on queues for efficient timeouts. There are
* a number of system defined queues as well as user defined timeouts. It is
* expected that a lock is held in the domain in which the queue belongs
* (i.e. either state or NAT) when calling any of these functions that prevents
* fr_freetimeoutqueue() from being called at the same time as any other.
*/
/* ------------------------------------------------------------------------ */
/* Function: fr_addtimeoutqueue */
@ -4554,26 +4610,35 @@ u_32_t *passp;
/* being requested. If it finds one, increments the reference counter and */
/* returns a pointer to it. If none are found, it allocates a new one and */
/* inserts it at the top of the list. */
/* */
/* Locking. */
/* It is assumed that the caller of this function has an appropriate lock */
/* held (exclusively) in the domain that encompases 'parent'. */
/* ------------------------------------------------------------------------ */
ipftq_t *fr_addtimeoutqueue(parent, seconds)
ipftq_t **parent;
u_int seconds;
{
u_int period;
ipftq_t *ifq;
u_int period;
period = seconds * IPF_HZ_DIVIDE;
MUTEX_ENTER(&ipf_timeoutlock);
for (ifq = *parent; ifq != NULL; ifq = ifq->ifq_next)
if (ifq->ifq_ttl == period)
break;
if (ifq != NULL) {
MUTEX_ENTER(&ifq->ifq_lock);
ifq->ifq_ref++;
MUTEX_EXIT(&ifq->ifq_lock);
MUTEX_EXIT(&ipf_timeoutlock);
return ifq;
MUTEX_ENTER(&ipf_timeoutlock);
for (ifq = *parent; ifq != NULL; ifq = ifq->ifq_next) {
if (ifq->ifq_ttl == period) {
/*
* Reset the delete flag, if set, so the structure
* gets reused rather than freed and reallocated.
*/
MUTEX_ENTER(&ifq->ifq_lock);
ifq->ifq_flags &= ~IFQF_DELETE;
ifq->ifq_ref++;
MUTEX_EXIT(&ifq->ifq_lock);
MUTEX_EXIT(&ipf_timeoutlock);
return ifq;
}
}
KMALLOC(ifq, ipftq_t *);
@ -4597,37 +4662,107 @@ u_int seconds;
/* ------------------------------------------------------------------------ */
/* Function: fr_deletetimeoutqueue */
/* Returns: Nil */
/* Parameters: difp(I) - timeout queue which is losing a reference. */
/* Returns: int - new reference count value of the timeout queue */
/* Parameters: ifq(I) - timeout queue which is losing a reference. */
/* Locks: ifq->ifq_lock */
/* */
/* This routine must be called when we're discarding a pointer to a timeout */
/* queue object. It takes care of the reference counter and free's it when */
/* it reaches 0. */
/* queue object, taking care of the reference counter. */
/* */
/* Now that this just sets a DELETE flag, it requires the expire code to */
/* check the list of user defined timeout queues and call the free function */
/* below (currently commented out) to stop memory leaking. It is done this */
/* way because the locking may not be sufficient to safely do a free when */
/* this function is called. */
/* ------------------------------------------------------------------------ */
void fr_deletetimeoutqueue(ifq)
int fr_deletetimeoutqueue(ifq)
ipftq_t *ifq;
{
MUTEX_ENTER(&ipf_timeoutlock);
MUTEX_ENTER(&ifq->ifq_lock);
ifq->ifq_ref--;
if ((ifq->ifq_ref == 0) && (ifq->ifq_head == NULL)) {
/*
* Remove from its position in the list.
*/
*ifq->ifq_pnext = ifq->ifq_next;
if (ifq->ifq_next != NULL)
ifq->ifq_next->ifq_pnext = ifq->ifq_pnext;
MUTEX_EXIT(&ifq->ifq_lock); /* Tru64 */
MUTEX_DESTROY(&ifq->ifq_lock);
KFREE(ifq);
fr_userifqs--;
} else {
MUTEX_EXIT(&ifq->ifq_lock);
if ((ifq->ifq_ref == 0) && ((ifq->ifq_flags & IFQF_USER) != 0)) {
ifq->ifq_flags |= IFQF_DELETE;
}
MUTEX_EXIT(&ipf_timeoutlock);
return ifq->ifq_ref;
}
/* ------------------------------------------------------------------------ */
/* Function: fr_freetimeoutqueue */
/* Parameters: ifq(I) - timeout queue which is losing a reference. */
/* Returns: Nil */
/* */
/* Locking: */
/* It is assumed that the caller of this function has an appropriate lock */
/* held (exclusively) in the domain that encompases the callers "domain". */
/* The ifq_lock for this structure should not be held. */
/* */
/* Remove a user definde timeout queue from the list of queues it is in and */
/* tidy up after this is done. */
/* ------------------------------------------------------------------------ */
void fr_freetimeoutqueue(ifq)
ipftq_t *ifq;
{
if (((ifq->ifq_flags & IFQF_DELETE) == 0) || (ifq->ifq_ref != 0) ||
((ifq->ifq_flags & IFQF_USER) == 0)) {
printf("fr_freetimeoutqueue(%lx) flags 0x%x ttl %d ref %d\n",
(u_long)ifq, ifq->ifq_flags, ifq->ifq_ttl,
ifq->ifq_ref);
return;
}
/*
* Remove from its position in the list.
*/
*ifq->ifq_pnext = ifq->ifq_next;
if (ifq->ifq_next != NULL)
ifq->ifq_next->ifq_pnext = ifq->ifq_pnext;
MUTEX_DESTROY(&ifq->ifq_lock);
fr_userifqs--;
KFREE(ifq);
}
/* ------------------------------------------------------------------------ */
/* Function: fr_deletequeueentry */
/* Returns: Nil */
/* Parameters: tqe(I) - timeout queue entry to delete */
/* ifq(I) - timeout queue to remove entry from */
/* */
/* Remove a tail queue entry from its queue and make it an orphan. */
/* fr_deletetimeoutqueue is called to make sure the reference count on the */
/* queue is correct. We can't, however, call fr_freetimeoutqueue because */
/* the correct lock(s) may not be held that would make it safe to do so. */
/* ------------------------------------------------------------------------ */
void fr_deletequeueentry(tqe)
ipftqent_t *tqe;
{
ipftq_t *ifq;
ifq = tqe->tqe_ifq;
if (ifq == NULL)
return;
MUTEX_ENTER(&ifq->ifq_lock);
if (tqe->tqe_pnext != NULL) {
*tqe->tqe_pnext = tqe->tqe_next;
if (tqe->tqe_next != NULL)
tqe->tqe_next->tqe_pnext = tqe->tqe_pnext;
else /* we must be the tail anyway */
ifq->ifq_tail = tqe->tqe_pnext;
tqe->tqe_pnext = NULL;
tqe->tqe_ifq = NULL;
}
(void) fr_deletetimeoutqueue(ifq);
MUTEX_EXIT(&ifq->ifq_lock);
}
@ -4647,8 +4782,8 @@ ipftqent_t *tqe;
if (ifq == NULL)
return;
MUTEX_ENTER(&ifq->ifq_lock);
if (ifq->ifq_head != tqe) {
MUTEX_ENTER(&ifq->ifq_lock);
*tqe->tqe_pnext = tqe->tqe_next;
if (tqe->tqe_next)
tqe->tqe_next->tqe_pnext = tqe->tqe_pnext;
@ -4659,8 +4794,8 @@ ipftqent_t *tqe;
ifq->ifq_head->tqe_pnext = &tqe->tqe_next;
ifq->ifq_head = tqe;
tqe->tqe_pnext = &ifq->ifq_head;
MUTEX_EXIT(&ifq->ifq_lock);
}
MUTEX_EXIT(&ifq->ifq_lock);
}
@ -4681,10 +4816,12 @@ ipftqent_t *tqe;
return;
tqe->tqe_die = fr_ticks + ifq->ifq_ttl;
if (tqe->tqe_next == NULL) /* at the end already ? */
return;
MUTEX_ENTER(&ifq->ifq_lock);
if (tqe->tqe_next == NULL) { /* at the end already ? */
MUTEX_EXIT(&ifq->ifq_lock);
return;
}
/*
* Remove from list
*/
@ -4725,6 +4862,7 @@ void *parent;
tqe->tqe_next = NULL;
tqe->tqe_ifq = ifq;
tqe->tqe_die = fr_ticks + ifq->ifq_ttl;
ifq->ifq_ref++;
MUTEX_EXIT(&ifq->ifq_lock);
}
@ -4747,13 +4885,15 @@ ipftq_t *oifq, *nifq;
/*
* Is the operation here going to be a no-op ?
*/
if (oifq == nifq && *oifq->ifq_tail == tqe)
MUTEX_ENTER(&oifq->ifq_lock);
if (oifq == nifq && *oifq->ifq_tail == tqe) {
MUTEX_EXIT(&oifq->ifq_lock);
return;
}
/*
* Remove from the old queue
*/
MUTEX_ENTER(&oifq->ifq_lock);
*tqe->tqe_pnext = tqe->tqe_next;
if (tqe->tqe_next)
tqe->tqe_next->tqe_pnext = tqe->tqe_pnext;
@ -4768,11 +4908,13 @@ ipftq_t *oifq, *nifq;
*/
if (oifq != nifq) {
tqe->tqe_ifq = NULL;
(void) fr_deletetimeoutqueue(oifq);
MUTEX_EXIT(&oifq->ifq_lock);
if ((oifq->ifq_flags & IFQF_USER) != 0)
fr_deletetimeoutqueue(oifq);
MUTEX_ENTER(&nifq->ifq_lock);
tqe->tqe_ifq = nifq;
nifq->ifq_ref++;
}
@ -5500,6 +5642,8 @@ ipftuneable_t ipf_tuneables[] = {
sizeof(fr_icmptimeout), IPFT_WRDISABLED },
{ { &fr_icmpacktimeout }, "fr_icmpacktimeout", 1, 0x7fffffff,
sizeof(fr_icmpacktimeout), IPFT_WRDISABLED },
{ { &fr_iptimeout }, "fr_iptimeout", 1, 0x7fffffff,
sizeof(fr_iptimeout), IPFT_WRDISABLED },
{ { &fr_statemax }, "fr_statemax", 1, 0x7fffffff,
sizeof(fr_statemax), 0 },
{ { &fr_statesize }, "fr_statesize", 1, 0x7fffffff,

View File

@ -1,4 +1,4 @@
/* $NetBSD: ip_compat.h,v 1.4 2005/02/08 07:01:55 martti Exp $ */
/* $NetBSD: ip_compat.h,v 1.5 2005/04/03 15:05:30 martti Exp $ */
/*
* Copyright (C) 1993-2001, 2003 by Darren Reed.
@ -6,7 +6,7 @@
* See the IPFILTER.LICENCE file for details on licencing.
*
* @(#)ip_compat.h 1.8 1/14/96
* Id: ip_compat.h,v 2.142.2.24 2005/01/08 14:22:59 darrenr Exp
* Id: ip_compat.h,v 2.142.2.25 2005/03/28 09:33:36 darrenr Exp
*/
#ifndef _NETINET_IP_COMPAT_H_
@ -1280,12 +1280,13 @@ typedef union {
#define ipf_isw ipf_lkun_s.ipf_sw
#define ipf_magic ipf_lkun_s.ipf_magic
#ifdef __GNUC__
# define INLINE __inline__
#else
#if !defined(__GNUC__) || \
(defined(__FreeBSD_version) && (__FreeBSD_version >= 503000))
# ifndef INLINE
# define INLINE
# endif
#else
# define INLINE __inline__
#endif
#if defined(linux) && defined(_KERNEL)

View File

@ -1,4 +1,4 @@
/* $NetBSD: ip_fil.h,v 1.2 2005/02/08 07:01:55 martti Exp $ */
/* $NetBSD: ip_fil.h,v 1.3 2005/04/03 15:05:30 martti Exp $ */
/*
* Copyright (C) 1993-2001, 2003 by Darren Reed.
@ -6,7 +6,7 @@
* See the IPFILTER.LICENCE file for details on licencing.
*
* @(#)ip_fil.h 1.35 6/5/96
* Id: ip_fil.h,v 2.170.2.15 2005/01/08 14:26:18 darrenr Exp
* Id: ip_fil.h,v 2.170.2.18 2005/03/28 10:47:52 darrenr Exp
*/
#ifndef _NETINET_IP_FIL_H_
@ -120,6 +120,7 @@ typedef union i6addr {
lookupfunc_t lptr[2];
} i6addr_t;
#endif
#define in4_addr in4.s_addr
#define iplookupnum i6[0]
#define iplookuptype i6[1]
@ -579,7 +580,7 @@ typedef struct frentry {
#define offsetof(t,m) (int)((&((t *)0L)->m))
#endif
#define FR_CMPSIZ (sizeof(struct frentry) - \
offsetof(struct frentry, fr_dsize))
offsetof(struct frentry, fr_func))
/*
* fr_type
@ -911,26 +912,23 @@ typedef struct tcpinfo {
tcpdata_t ts_data[2];
} tcpinfo_t;
typedef struct greinfo {
u_short gs_flags;
u_short gs_ptype;
u_short gs_call;
} greinfo_t;
struct grebits {
u_32_t grb_C:1;
u_32_t grb_R:1;
u_32_t grb_K:1;
u_32_t grb_S:1;
u_32_t grb_s:1;
u_32_t grb_recur:1;
u_32_t grb_A:1;
u_32_t grb_flags:3;
u_32_t grb_ver:3;
u_short grb_ptype;
};
typedef struct grehdr {
union {
struct grebits {
u_32_t grub_C:1;
u_32_t grub_R:1;
u_32_t grub_K:1;
u_32_t grub_S:1;
u_32_t grub_s:1;
u_32_t grub_recur:1;
u_32_t grub_A:1;
u_32_t grub_flags:3;
u_32_t grub_ver:3;
u_short grub_ptype;
} gru_bits;
struct grebits gru_bits;
u_short gru_flags;
} gr_un;
u_short gr_len;
@ -939,15 +937,24 @@ typedef struct grehdr {
#define gr_flags gr_un.gru_flags
#define gr_bits gr_un.gru_bits
#define gr_ptype gr_bits.grub_ptype
#define gr_C gr_bits.grub_C
#define gr_R gr_bits.grub_R
#define gr_K gr_bits.grub_K
#define gr_S gr_bits.grub_S
#define gr_s gr_bits.grub_s
#define gr_recur gr_bits.grub_recur
#define gr_A gr_bits.grub_A
#define gr_ver gr_bits.grub_ver
#define gr_ptype gr_bits.grb_ptype
#define gr_C gr_bits.grb_C
#define gr_R gr_bits.grb_R
#define gr_K gr_bits.grb_K
#define gr_S gr_bits.grb_S
#define gr_s gr_bits.grb_s
#define gr_recur gr_bits.grb_recur
#define gr_A gr_bits.grb_A
#define gr_ver gr_bits.grb_ver
typedef struct greinfo {
u_short gs_call[2];
u_short gs_flags;
u_short gs_ptype;
} greinfo_t;
#define GRE_REV(x) ((ntohs(x) >> 13) & 7)
/*
@ -982,6 +989,8 @@ typedef struct ipftq {
} ipftq_t;
#define IFQF_USER 0x01 /* User defined aging */
#define IFQF_DELETE 0x02 /* Marked for deletion */
#define IFQF_PROXY 0x04 /* Timeout queue in use by a proxy */
#define IPF_HZ_MULT 1
#define IPF_HZ_DIVIDE 2 /* How many times a second ipfilter */
@ -1255,7 +1264,9 @@ extern int fr_send_reset __P((fr_info_t *));
extern int ppsratecheck __P((struct timeval *, int *, int));
#endif
extern ipftq_t *fr_addtimeoutqueue __P((ipftq_t **, u_int));
extern void fr_deletetimeoutqueue __P((ipftq_t *));
extern void fr_deletequeueentry __P((ipftqent_t *));
extern int fr_deletetimeoutqueue __P((ipftq_t *));
extern void fr_freetimeoutqueue __P((ipftq_t *));
extern void fr_movequeue __P((ipftqent_t *, ipftq_t *, ipftq_t *));
extern void fr_queueappend __P((ipftqent_t *, ipftq_t *, void *));
extern void fr_queueback __P((ipftqent_t *));

View File

@ -1,4 +1,4 @@
/* $NetBSD: ip_fil_netbsd.c,v 1.12 2005/03/26 18:08:42 christos Exp $ */
/* $NetBSD: ip_fil_netbsd.c,v 1.13 2005/04/03 15:05:30 martti Exp $ */
/*
* Copyright (C) 1993-2003 by Darren Reed.
@ -7,7 +7,7 @@
*/
#if !defined(lint)
static const char sccsid[] = "@(#)ip_fil.c 2.41 6/5/96 (C) 1993-2000 Darren Reed";
static const char rcsid[] = "@(#)Id: ip_fil_netbsd.c,v 2.55.2.25 2005/02/01 03:14:31 darrenr Exp";
static const char rcsid[] = "@(#)Id: ip_fil_netbsd.c,v 2.55.2.27 2005/02/21 22:51:08 darrenr Exp";
#endif
#if defined(KERNEL) || defined(_KERNEL)
@ -46,8 +46,8 @@ static const char rcsid[] = "@(#)Id: ip_fil_netbsd.c,v 2.55.2.25 2005/02/01 03:1
#include <netinet/ip_var.h>
#include <netinet/tcp.h>
#if __NetBSD_Version__ >= 105190000 /* 1.5T */
#include <netinet/tcp_timer.h>
#include <netinet/tcp_var.h>
# include <netinet/tcp_timer.h>
# include <netinet/tcp_var.h>
#endif
#include <netinet/udp.h>
#include <netinet/tcpip.h>
@ -137,6 +137,7 @@ int dir;
{
struct ip *ip;
int rv, hlen;
#if __NetBSD_Version__ >= 200080000
/*
* ensure that mbufs are writable beforehand
@ -205,7 +206,7 @@ struct mbuf **mp;
struct ifnet *ifp;
int dir;
{
return (fr_check(mtod(*mp, struct ip *), sizeof(struct ip6_hdr),
ifp, (dir == PFIL_OUT), mp));
}
@ -855,10 +856,10 @@ fr_info_t *fin;
mb_t *m, **mpp;
{
fr_info_t fnew;
ip_t *ip;
#ifdef INET
ip_t *oip;
#endif
ip_t *ip;
int hlen;
ip = mtod(m, ip_t *);
@ -1121,16 +1122,19 @@ frdest_t *fdp;
}
return error;
}
#ifndef INET
return EPROTONOSUPPORT;
#else
hlen = fin->fin_hlen;
ip = mtod(m0, struct ip *);
#if defined(M_CSUM_IPv4)
# if defined(M_CSUM_IPv4)
/*
* Clear any in-bound checksum flags for this packet.
*/
m0->m_pkthdr.csuminfo = 0;
#endif /* __NetBSD__ && M_CSUM_IPv4 */
# endif /* __NetBSD__ && M_CSUM_IPv4 */
/*
* Route packet.
@ -1230,22 +1234,20 @@ frdest_t *fdp;
ip->ip_len = htons(ip->ip_len);
ip->ip_off = htons(ip->ip_off);
#ifdef INET
#if defined(M_CSUM_IPv4)
# if (__NetBSD_Version__ >= 105009999)
# if defined(M_CSUM_IPv4)
# if (__NetBSD_Version__ >= 105009999)
if (ifp->if_csum_flags_tx & M_CSUM_IPv4)
m->m_pkthdr.csuminfo |= M_CSUM_IPv4;
# else
# else
if (ifp->if_capabilities & IFCAP_CSUM_IPv4)
m->m_pkthdr.csuminfo |= M_CSUM_IPv4;
# endif /* (__NetBSD_Version__ >= 105009999) */
# endif /* (__NetBSD_Version__ >= 105009999) */
else if (ip->ip_sum == 0)
ip->ip_sum = in_cksum(m, hlen);
#else
# else
if (!ip->ip_sum)
ip->ip_sum = in_cksum(m, hlen);
#endif /* M_CSUM_IPv4 */
#endif /* INET */
# endif /* M_CSUM_IPv4 */
error = (*ifp->if_output)(ifp, m, (struct sockaddr *)dst,
ro->ro_rt);
if (i) {
@ -1281,11 +1283,11 @@ frdest_t *fdp;
m0 = m;
mhlen = sizeof (struct ip);
for (off = hlen + len; off < ip->ip_len; off += len) {
#ifdef MGETHDR
# ifdef MGETHDR
MGETHDR(m, M_DONTWAIT, MT_HEADER);
#else
# else
MGET(m, M_DONTWAIT, MT_HEADER);
#endif
# endif
if (m == 0) {
m = m0;
error = ENOBUFS;
@ -1343,7 +1345,7 @@ sendorfree:
else
FREE_MB_T(m);
}
}
}
done:
if (!error)
fr_frouteok[0]++;
@ -1367,6 +1369,7 @@ bad:
}
FREE_MB_T(m);
goto done;
#endif /* INET */
}
@ -1543,7 +1546,7 @@ fr_info_t *fin;
{
#if __NetBSD_Version__ >= 105190000 /* 1.5T */
size_t asz;
if (fin->fin_v == 4)
asz = sizeof(struct in_addr);
else if (fin->fin_v == 6)
@ -1551,11 +1554,11 @@ fr_info_t *fin;
else /* XXX: no way to return error */
return 0;
return tcp_new_iss1((void *)&fin->fin_src, (void *)&fin->fin_dst,
fin->fin_sport, fin->fin_dport, asz, 0);
fin->fin_sport, fin->fin_dport, asz, 0);
#else
u_32_t newiss;
static int iss_seq_off = 0;
u_char hash[16];
u_32_t newiss;
MD5_CTX ctx;
/*

View File

@ -1,7 +1,7 @@
/* $NetBSD: ip_ftp_pxy.c,v 1.6 2005/02/19 21:30:25 martti Exp $ */
/* $NetBSD: ip_ftp_pxy.c,v 1.7 2005/04/03 15:05:30 martti Exp $ */
#include <sys/cdefs.h>
__KERNEL_RCSID(1, "$NetBSD: ip_ftp_pxy.c,v 1.6 2005/02/19 21:30:25 martti Exp $");
__KERNEL_RCSID(1, "$NetBSD: ip_ftp_pxy.c,v 1.7 2005/04/03 15:05:30 martti Exp $");
/*
* Copyright (C) 1997-2003 by Darren Reed
@ -11,7 +11,7 @@ __KERNEL_RCSID(1, "$NetBSD: ip_ftp_pxy.c,v 1.6 2005/02/19 21:30:25 martti Exp $"
* Simple FTP transparent proxy for in-kernel use. For use with the NAT
* code.
*
* Id: ip_ftp_pxy.c,v 2.88.2.10 2005/02/04 10:22:54 darrenr Exp
* Id: ip_ftp_pxy.c,v 2.88.2.15 2005/03/19 19:38:10 darrenr Exp
*/
#define IPF_FTP_PROXY
@ -22,14 +22,6 @@ __KERNEL_RCSID(1, "$NetBSD: ip_ftp_pxy.c,v 1.6 2005/02/19 21:30:25 martti Exp $"
#define IPF_MAX227LEN 51
#define IPF_MIN229LEN 47
#define IPF_MAX229LEN 51
/*
* On Unix, a pathname can be upto 256 bytes long, so that must fit in half
* of the buffer. Why half? Because we allow a message being parsed to
* start upto half way into the buffer so less arbitrary moving around of
* data to make messages fit is required. And so, 526 is 2*(4+1+256+2)
* (XXXX path\r\n)
*/
#define IPF_FTPBUFSZ 526 /* This *MUST* be >= 53! */
#define FTPXY_GO 0
#define FTPXY_INIT 1
@ -190,7 +182,7 @@ int dlen;
if (dlen < IPF_MINPORTLEN) {
if (ippr_ftp_debug > 1)
printf("ippr_ftp_port:dlen(%d) < IPF_MINPORTLEN\n",
dlen);
dlen);
return 0;
}
/*
@ -212,6 +204,7 @@ int dlen;
printf("ippr_ftp_port:ippr_ftp_atoi(%d) failed\n", 2);
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.
@ -249,8 +242,19 @@ int dlen;
printf("ippr_ftp_port:missing %s\n", "cr-lf");
return 0;
}
a5 >>= 8;
a5 &= 0xff;
sp = a5 << 8 | a6;
/*
* Don't allow the PORT command to specify a port < 1024 due to
* security crap.
*/
if (sp < 1024) {
if (ippr_ftp_debug > 0)
printf("ippr_ftp_port:sp(%d) < 1024\n", sp);
return 0;
}
/*
* Calculate new address parts for PORT command
*/
@ -277,7 +281,7 @@ int dlen;
if ((inc + ip->ip_len) > 65535) {
if (ippr_ftp_debug > 0)
printf("ippr_ftp_port:inc(%d) + ip->ip_len > 65535\n",
inc);
inc);
return 0;
}
@ -287,16 +291,16 @@ int dlen;
# if defined(MENTAT)
if (inc < 0)
(void)adjmsg(m, inc);
# else
# else /* defined(MENTAT) */
/*
* m_adj takes care of pkthdr.len, if required and treats inc<0 to
* mean remove -len bytes from the end of the packet.
* The mbuf chain will be extended if necessary by m_copyback().
*/
if (inc < 0)
m_adj(m, inc);
# ifdef M_PKTHDR
if (!(m->m_flags & M_PKTHDR))
m->m_pkthdr.len += inc;
# endif
# endif
#endif
/* the mbuf chain will be extended if necessary by m_copyback() */
# endif /* defined(MENTAT) */
#endif /* !defined(_KERNEL) */
COPYBACK(m, off, nlen, newbuf);
if (inc != 0) {
@ -305,20 +309,6 @@ int dlen;
fin->fin_plen += inc;
}
/*
* Add skeleton NAT entry for connection which will come back the
* other way.
*/
sp = a5 << 8 | a6;
/*
* Don't allow the PORT command to specify a port < 1024 due to
* security crap.
*/
if (sp < 1024) {
if (ippr_ftp_debug > 0)
printf("ippr_ftp_port:sp(%d) < 1024\n", sp);
return 0;
}
/*
* The server may not make the connection back from port 20, but
* it is the most likely so use it here to check for a conflicting
@ -330,6 +320,10 @@ int dlen;
fi.fin_flx |= FI_IGNORE;
fi.fin_data[0] = sp;
fi.fin_data[1] = fin->fin_data[1] - 1;
/*
* Add skeleton NAT entry for connection which will come back the
* other way.
*/
if (nat->nat_dir == NAT_OUTBOUND)
nat2 = nat_outlookup(&fi, NAT_SEARCH|IPN_TCP, nat->nat_p,
nat->nat_inip, nat->nat_oip);
@ -490,7 +484,7 @@ int dlen;
ftp->ftp_side[0].ftps_cmds != FTPXY_C_PASV) {
if (ippr_ftp_debug > 0)
printf("ippr_ftp_pasv:ftps_cmds(%d) != FTPXY_C_PASV\n",
ftp->ftp_side[0].ftps_cmds);
ftp->ftp_side[0].ftps_cmds);
return 0;
}
@ -503,7 +497,7 @@ int dlen;
if (dlen < IPF_MIN227LEN) {
if (ippr_ftp_debug > 1)
printf("ippr_ftp_pasv:dlen(%d) < IPF_MIN227LEN\n",
dlen);
dlen);
return 0;
} else if (strncmp(f->ftps_rptr,
"227 Entering Passive Mod", PASV_REPLEN)) {
@ -645,20 +639,24 @@ u_int data_ip;
if ((inc + ip->ip_len) > 65535) {
if (ippr_ftp_debug > 0)
printf("ippr_ftp_pasv:inc(%d) + ip->ip_len > 65535\n",
inc);
inc);
return 0;
}
#if !defined(_KERNEL)
bcopy(newmsg, (char *)m + off, nlen);
bcopy(newmsg, MTOD(m, char *) + off, nlen);
#else
# if defined(MENTAT)
if (inc < 0)
(void)adjmsg(m, inc);
# else /* defined(MENTAT) */
/*
* m_adj takes care of pkthdr.len, if required and treats inc<0 to
* mean remove -len bytes from the end of the packet.
* The mbuf chain will be extended if necessary by m_copyback().
*/
if (inc < 0)
m_adj(m, inc);
/* the mbuf chain will be extended if necessary by m_copyback() */
# endif /* defined(MENTAT) */
#endif /* !defined(_KERNEL) */
COPYBACK(m, off, nlen, newmsg);
@ -832,18 +830,23 @@ ftpside_t *ftps;
char *buf;
size_t len;
{
register char *s, c;
register char *s, c, pc;
register size_t i = len;
char cmd[5];
s = buf;
if (ftps->ftps_junk == 1)
return 1;
if (i < 5) {
if (ippr_ftp_debug > 3)
printf("ippr_ftp_client_valid:i(%d) < 5\n", (int)i);
return 2;
}
s = buf;
c = *s++;
i--;
c = *s++;
if (ISALPHA(c)) {
cmd[0] = TOUPPER(c);
@ -872,15 +875,17 @@ size_t len;
} else {
bad_client_command:
if (ippr_ftp_debug > 3)
printf("ippr_ftp_client_valid:bad:junk %d len %d/%d c 0x%x buf [%*.*s]\n",
ftps->ftps_junk, (int)len, (int)i, c,
(int)len, (int)len, buf);
printf("%s:bad:junk %d len %d/%d c 0x%x buf [%*.*s]\n",
"ippr_ftp_client_valid",
ftps->ftps_junk, (int)len, (int)i, c,
(int)len, (int)len, buf);
return 1;
}
for (; i; i--) {
pc = c;
c = *s++;
if (c == '\n') {
if ((pc == '\r') && (c == '\n')) {
cmd[4] = '\0';
if (!strcmp(cmd, "PASV"))
ftps->ftps_cmds = FTPXY_C_PASV;
@ -890,7 +895,8 @@ bad_client_command:
}
}
#if !defined(_KERNEL)
printf("ippr_ftp_client_valid:junk after cmd[%s]\n", buf);
printf("ippr_ftp_client_valid:junk after cmd[%*.*s]\n",
(int)len, (int)len, buf);
#endif
return 2;
}
@ -901,17 +907,24 @@ ftpside_t *ftps;
char *buf;
size_t len;
{
register char *s, c;
register char *s, c, pc;
register size_t i = len;
int cmd;
if (i < 5)
return 2;
s = buf;
c = *s++;
cmd = 0;
i--;
if (ftps->ftps_junk == 1)
return 1;
if (i < 5) {
if (ippr_ftp_debug > 3)
printf("ippr_ftp_servert_valid:i(%d) < 5\n", (int)i);
return 2;
}
c = *s++;
i--;
if (c == ' ')
goto search_eol;
@ -936,22 +949,24 @@ size_t len;
} else {
bad_server_command:
if (ippr_ftp_debug > 3)
printf("ippr_ftp_server_valid:bad:junk %d len %d/%d c 0x%x buf [%*.*s]\n",
ftps->ftps_junk, (int)len, (int)i,
c, (int)len, (int)len, buf);
printf("%s:bad:junk %d len %d/%d c 0x%x buf [%*.*s]\n",
"ippr_ftp_server_valid",
ftps->ftps_junk, (int)len, (int)i,
c, (int)len, (int)len, buf);
return 1;
}
search_eol:
for (; i; i--) {
pc = c;
c = *s++;
if (c == '\n') {
if ((pc == '\r') && (c == '\n')) {
ftps->ftps_cmds = cmd;
return 0;
}
}
if (ippr_ftp_debug > 1)
if (ippr_ftp_debug > 3)
printf("ippr_ftp_server_valid:junk after cmd[%*.*s]\n",
(int)len, (int)len, buf);
(int)len, (int)len, buf);
return 2;
}
@ -990,8 +1005,8 @@ ftpinfo_t *ftp;
int rv;
{
int mlen, len, off, inc, i, sel, sel2, ok, ackoff, seqoff;
char *rptr, *wptr, *s;
u_32_t thseq, thack;
char *rptr, *wptr;
ap_session_t *aps;
ftpside_t *f, *t;
tcphdr_t *tcp;
@ -1038,14 +1053,14 @@ int rv;
seqoff = aps->aps_ackoff[sel];
if (ippr_ftp_debug > 2)
printf("seqoff %d thseq %x ackmin %x\n", seqoff, thseq,
aps->aps_ackmin[sel]);
aps->aps_ackmin[sel]);
if (aps->aps_ackmin[sel] > seqoff + thseq)
seqoff = aps->aps_ackoff[!sel];
ackoff = aps->aps_seqoff[sel2];
if (ippr_ftp_debug > 2)
printf("ackoff %d thack %x seqmin %x\n", ackoff, thack,
aps->aps_seqmin[sel2]);
aps->aps_seqmin[sel2]);
if (ackoff > 0) {
if (aps->aps_seqmin[sel2] > ackoff + thack)
ackoff = aps->aps_seqoff[!sel2];
@ -1056,14 +1071,14 @@ int rv;
}
if (ippr_ftp_debug > 2) {
printf("%s: %x seq %x/%d ack %x/%d len %d/%d off %d\n",
rv ? "IN" : "OUT", tcp->th_flags, thseq, seqoff,
thack, ackoff, mlen, fin->fin_plen, off);
rv ? "IN" : "OUT", tcp->th_flags, thseq, seqoff,
thack, ackoff, mlen, fin->fin_plen, off);
printf("sel %d seqmin %x/%x offset %d/%d\n", sel,
aps->aps_seqmin[sel], aps->aps_seqmin[sel2],
aps->aps_seqoff[sel], aps->aps_seqoff[sel2]);
aps->aps_seqmin[sel], aps->aps_seqmin[sel2],
aps->aps_seqoff[sel], aps->aps_seqoff[sel2]);
printf("sel %d ackmin %x/%x offset %d/%d\n", sel2,
aps->aps_ackmin[sel], aps->aps_ackmin[sel2],
aps->aps_ackoff[sel], aps->aps_ackoff[sel2]);
aps->aps_ackmin[sel], aps->aps_ackmin[sel2],
aps->aps_ackoff[sel], aps->aps_ackoff[sel2]);
}
/*
@ -1073,7 +1088,7 @@ int rv;
*/
if (ippr_ftp_debug > 2) {
printf("rv %d t:seq[0] %x seq[1] %x %d/%d\n",
rv, t->ftps_seq[0], t->ftps_seq[1], seqoff, ackoff);
rv, t->ftps_seq[0], t->ftps_seq[1], seqoff, ackoff);
}
ok = 0;
@ -1111,14 +1126,15 @@ int rv;
if (!mlen) {
if (t->ftps_seq[0] + ackoff != thack) {
if (ippr_ftp_debug > 1) {
printf("ippr_ftp_process:seq[0](%x) + ackoff(%x) != thack(%x)\n",
t->ftps_seq[0], ackoff, thack);
printf("%s:seq[0](%x) + (%x) != (%x)\n",
"ippr_ftp_process", t->ftps_seq[0],
ackoff, thack);
}
return APR_ERR(1);
}
if (ippr_ftp_debug > 2) {
printf("f:seq[0] %x seq[1] %x\n",
printf("ippr_ftp_process:f:seq[0] %x seq[1] %x\n",
f->ftps_seq[0], f->ftps_seq[1]);
}
@ -1129,7 +1145,7 @@ int rv;
} else {
if (ippr_ftp_debug > 1) {
printf("FIN: thseq %x seqoff %d ftps_seq %x\n",
thseq, seqoff, f->ftps_seq[0]);
thseq, seqoff, f->ftps_seq[0]);
}
return APR_ERR(1);
}
@ -1154,11 +1170,11 @@ int rv;
if (ippr_ftp_debug > 1) {
printf("inc %d sel %d rv %d\n", inc, sel, rv);
printf("th_seq %x ftps_seq %x/%x\n",
thseq, f->ftps_seq[0], f->ftps_seq[1]);
thseq, f->ftps_seq[0], f->ftps_seq[1]);
printf("ackmin %x ackoff %d\n", aps->aps_ackmin[sel],
aps->aps_ackoff[sel]);
aps->aps_ackoff[sel]);
printf("seqmin %x seqoff %d\n", aps->aps_seqmin[sel],
aps->aps_seqoff[sel]);
aps->aps_seqoff[sel]);
}
return APR_ERR(1);
@ -1172,29 +1188,58 @@ int rv;
f->ftps_len = mlen;
while (mlen > 0) {
len = MIN(mlen, FTP_BUFSZ / 2);
len = MIN(mlen, sizeof(f->ftps_buf) - (wptr - rptr));
COPYDATA(m, off, len, wptr);
mlen -= len;
off += len;
wptr += len;
if (ippr_ftp_debug > 3)
printf("ippr_ftp_process:len %d/%d off %d wptr %lx junk %d\n",
len, mlen, off, (u_long)wptr, f->ftps_junk);
printf("%s:len %d/%d off %d wptr %lx junk %d [%*.*s]\n",
"ippr_ftp_process",
len, mlen, off, (u_long)wptr, f->ftps_junk,
len, len, rptr);
f->ftps_wptr = wptr;
if (f->ftps_junk == 2)
if (f->ftps_junk != 0) {
i = f->ftps_junk;
f->ftps_junk = ippr_ftp_valid(ftp, rv, rptr,
wptr - rptr);
if (ippr_ftp_debug > 5)
printf("%s:junk %d -> %d\n",
"ippr_ftp_process", i, f->ftps_junk);
if (f->ftps_junk != 0) {
if (wptr - rptr == sizeof(f->ftps_buf)) {
if (ippr_ftp_debug > 4)
printf("%s:full buffer\n",
"ippr_ftp_process");
f->ftps_rptr = f->ftps_buf;
f->ftps_wptr = f->ftps_buf;
rptr = f->ftps_rptr;
wptr = f->ftps_wptr;
/*
* Because we throw away data here that
* we would otherwise parse, set the
* junk flag to indicate just ignore
* any data upto the next CRLF.
*/
f->ftps_junk = 1;
continue;
}
}
}
while ((f->ftps_junk == 0) && (wptr > rptr)) {
len = wptr - rptr;
f->ftps_junk = ippr_ftp_valid(ftp, rv, rptr, len);
if (ippr_ftp_debug > 3) {
printf("ippr_ftp_valid=%d len %d rv %d ptr %lx/%lx\n",
f->ftps_junk, len, rv, (u_long)rptr,
(u_long)wptr);
printf("%s=%d len %d rv %d ptr %lx/%lx ",
"ippr_ftp_valid",
f->ftps_junk, len, rv, (u_long)rptr,
(u_long)wptr);
printf("buf [%*.*s]\n", len, len, rptr);
}
@ -1219,45 +1264,39 @@ int rv;
/* f->ftps_seq[1] += inc; */
if (ippr_ftp_debug > 1)
printf("ippr_ftp_process:cmds == 0 junk == %d\n", 1);
printf("%s:cmds == 0 junk == 1\n",
"ippr_ftp_process");
return APR_ERR(2);
}
while ((f->ftps_junk == 1) && (rptr < wptr)) {
while ((rptr < wptr) && (*rptr != '\r'))
rptr++;
if (*rptr == '\r') {
if (rptr + 1 < wptr) {
if (*(rptr + 1) == '\n') {
rptr += 2;
f->ftps_junk = 0;
} else
rptr++;
} else
if ((f->ftps_junk != 0) && (rptr < wptr)) {
for (s = rptr; s < wptr; s++) {
if ((*s == '\r') && (s + 1 < wptr) &&
(*(s + 1) == '\n')) {
rptr = s + 2;
f->ftps_junk = 0;
break;
}
}
}
f->ftps_rptr = rptr;
if (rptr == wptr) {
rptr = wptr = f->ftps_buf;
} else {
if ((wptr > f->ftps_buf + FTP_BUFSZ / 2)) {
i = wptr - rptr;
if ((rptr == f->ftps_buf) ||
(wptr - rptr > FTP_BUFSZ / 2)) {
f->ftps_junk = 1;
rptr = wptr = f->ftps_buf;
} else {
bcopy(rptr, f->ftps_buf, i);
wptr = f->ftps_buf + i;
rptr = f->ftps_buf;
}
/*
* Compact the buffer back to the start. The junk
* flag should already be set and because we're not
* throwing away any data, it is preserved from its
* current state.
*/
if (rptr > f->ftps_buf) {
bcopy(rptr, f->ftps_buf, len);
wptr -= rptr - f->ftps_buf;
rptr = f->ftps_buf;
}
f->ftps_rptr = rptr;
f->ftps_wptr = wptr;
}
f->ftps_rptr = rptr;
f->ftps_wptr = wptr;
}
/* f->ftps_seq[1] += inc; */
@ -1271,7 +1310,7 @@ int rv;
#endif
mlen -= off;
printf("ftps_seq[1] = %x inc %d len %d\n",
f->ftps_seq[1], inc, mlen);
f->ftps_seq[1], inc, mlen);
}
f->ftps_rptr = rptr;
@ -1416,36 +1455,3 @@ int dlen;
return ippr_ftp_pasvreply(fin, ip, nat, f, (u_int)ap, newbuf, s,
ip->ip_src.s_addr);
}
#if 0
ippr_ftp_parse(str, len)
{
char *s, c;
if (len < 5)
return -1;
s = str;
if (*s++ != '|')
return -1;
c = *s++;
if (c != '|') {
if (*s++ != '|')
return -1;
} else
c = '1';
if (c == '1') {
/*
* IPv4 dotted quad.
*/
return 0;
} else if (c == '2') {
/*
* IPv6 hex string
*/
return 0;
}
return -1;
}
#endif

View File

@ -1,4 +1,4 @@
/* $NetBSD: ip_ipsec_pxy.c,v 1.2 2005/02/19 21:30:25 martti Exp $ */
/* $NetBSD: ip_ipsec_pxy.c,v 1.3 2005/04/03 15:05:30 martti Exp $ */
/*
* Copyright (C) 2001-2003 by Darren Reed
@ -8,11 +8,11 @@
* Simple ISAKMP transparent proxy for in-kernel use. For use with the NAT
* code.
*
* Id: ip_ipsec_pxy.c,v 2.20.2.4 2005/02/04 10:22:55 darrenr Exp
* Id: ip_ipsec_pxy.c,v 2.20.2.6 2005/03/28 10:47:53 darrenr Exp
*
*/
__KERNEL_RCSID(1, "$NetBSD: ip_ipsec_pxy.c,v 1.2 2005/02/19 21:30:25 martti Exp $");
__KERNEL_RCSID(1, "$NetBSD: ip_ipsec_pxy.c,v 1.3 2005/04/03 15:05:30 martti Exp $");
#define IPF_IPSEC_PROXY
@ -30,6 +30,7 @@ static ipftq_t *ipsecstatetqe;
static char ipsec_buffer[1500];
int ipsec_proxy_init = 0;
int ipsec_proxy_ttl = 60;
/*
* IPSec application proxy initialization.
@ -42,28 +43,37 @@ int ippr_ipsec_init()
MUTEX_INIT(&ipsecfr.fr_lock, "IPsec proxy rule lock");
ipsec_proxy_init = 1;
ipsecnattqe = fr_addtimeoutqueue(&nat_utqe, 60);
ipsecnattqe = fr_addtimeoutqueue(&nat_utqe, ipsec_proxy_ttl);
if (ipsecnattqe == NULL)
return -1;
ipsecstatetqe = fr_addtimeoutqueue(&ips_utqe, 60);
ipsecstatetqe = fr_addtimeoutqueue(&ips_utqe, ipsec_proxy_ttl);
if (ipsecstatetqe == NULL) {
fr_deletetimeoutqueue(ipsecnattqe);
if (fr_deletetimeoutqueue(ipsecnattqe) == 0)
fr_freetimeoutqueue(ipsecnattqe);
ipsecnattqe = NULL;
return -1;
}
ipsecfr.fr_age[0] = 60;
ipsecfr.fr_age[1] = 60;
ipsecnattqe->ifq_flags |= IFQF_PROXY;
ipsecstatetqe->ifq_flags |= IFQF_PROXY;
ipsecfr.fr_age[0] = ipsec_proxy_ttl;
ipsecfr.fr_age[1] = ipsec_proxy_ttl;
return 0;
}
void ippr_ipsec_fini()
{
if (ipsecnattqe != NULL)
fr_deletetimeoutqueue(ipsecnattqe);
if (ipsecnattqe != NULL) {
if (fr_deletetimeoutqueue(ipsecnattqe) == 0)
fr_freetimeoutqueue(ipsecnattqe);
}
ipsecnattqe = NULL;
if (ipsecstatetqe != NULL)
fr_deletetimeoutqueue(ipsecstatetqe);
if (ipsecstatetqe != NULL) {
if (fr_deletetimeoutqueue(ipsecstatetqe) == 0)
fr_freetimeoutqueue(ipsecstatetqe);
}
ipsecstatetqe = NULL;
if (ipsec_proxy_init == 1) {
@ -146,7 +156,7 @@ nat_t *nat;
fi.fin_data[1] = 0;
p = ip->ip_p;
ip->ip_p = IPPROTO_ESP;
fi.fin_flx &= ~FI_TCPUDP;
fi.fin_flx &= ~(FI_TCPUDP|FI_STATE|FI_FRAG);
fi.fin_flx |= FI_IGNORE;
ptr = ipsec_buffer;
@ -214,7 +224,7 @@ nat_t *nat;
fi.fin_data[0] = 0;
fi.fin_data[1] = 0;
ip->ip_p = IPPROTO_ESP;
fi.fin_flx &= ~FI_TCPUDP;
fi.fin_flx &= ~(FI_TCPUDP|FI_STATE|FI_FRAG);
fi.fin_flx |= FI_IGNORE;
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: ip_nat.c,v 1.6 2005/03/26 18:08:42 christos Exp $ */
/* $NetBSD: ip_nat.c,v 1.7 2005/04/03 15:05:30 martti Exp $ */
/*
* Copyright (C) 1995-2003 by Darren Reed.
@ -107,7 +107,7 @@ extern struct ifnet vpnif;
#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 2.195.2.30 2005/02/04 09:44:37 darrenr Exp";
static const char rcsid[] = "@(#)Id: ip_nat.c,v 2.195.2.38 2005/03/28 11:09:54 darrenr Exp";
#endif
@ -178,7 +178,7 @@ static void nat_delrdr __P((struct ipnat *));
static void nat_delnat __P((struct ipnat *));
static int fr_natgetent __P((caddr_t));
static int fr_natgetsz __P((caddr_t));
static int fr_natputent __P((caddr_t));
static int fr_natputent __P((caddr_t, int));
static void nat_tabmove __P((nat_t *));
static int nat_match __P((fr_info_t *, ipnat_t *));
static INLINE int nat_newmap __P((fr_info_t *, nat_t *, natinfo_t *));
@ -267,16 +267,19 @@ int fr_natinit()
nat_tqb[IPF_TCPS_CLOSED].ifq_ttl = fr_tcplastack;
nat_tqb[IPF_TCP_NSTATES - 1].ifq_next = &nat_udptq;
nat_udptq.ifq_ttl = fr_defnatage;
nat_udptq.ifq_ref = 1;
nat_udptq.ifq_head = NULL;
nat_udptq.ifq_tail = &nat_udptq.ifq_head;
MUTEX_INIT(&nat_udptq.ifq_lock, "nat ipftq udp tab");
nat_udptq.ifq_next = &nat_icmptq;
nat_icmptq.ifq_ttl = fr_defnaticmpage;
nat_icmptq.ifq_ref = 1;
nat_icmptq.ifq_head = NULL;
nat_icmptq.ifq_tail = &nat_icmptq.ifq_head;
MUTEX_INIT(&nat_icmptq.ifq_lock, "nat icmp ipftq tab");
nat_icmptq.ifq_next = &nat_iptq;
nat_iptq.ifq_ttl = fr_defnatipage;
nat_iptq.ifq_ref = 1;
nat_iptq.ifq_head = NULL;
nat_iptq.ifq_tail = &nat_iptq.ifq_head;
MUTEX_INIT(&nat_iptq.ifq_lock, "nat ip ipftq tab");
@ -758,13 +761,13 @@ int mode;
READ_ENTER(&ipf_nat);
}
error = fr_inobj(data, &nl, IPFOBJ_NATLOOKUP);
if (error)
break;
if (nat_lookupredir(&nl)) {
error = fr_outobj(data, &nl, IPFOBJ_NATLOOKUP);
} else
error = ESRCH;
if (error == 0) {
if (nat_lookupredir(&nl) != NULL) {
error = fr_outobj(data, &nl, IPFOBJ_NATLOOKUP);
} else {
error = ESRCH;
}
}
if (getlock) {
RWLOCK_EXIT(&ipf_nat);
}
@ -786,14 +789,11 @@ int mode;
else
error = EINVAL;
if (getlock) {
MUTEX_DOWNGRADE(&ipf_nat);
RWLOCK_EXIT(&ipf_nat);
}
if (error == 0) {
BCOPYOUT(&ret, data, sizeof(ret));
}
if (getlock) {
RWLOCK_EXIT(&ipf_nat);
}
break;
case SIOCPROXY :
error = appr_ioctl(data, cmd, mode);
@ -803,15 +803,10 @@ int mode;
break;
case SIOCSTPUT :
if (fr_nat_lock) {
if (getlock) {
WRITE_ENTER(&ipf_nat);
}
error = fr_natputent(data);
if (getlock) {
RWLOCK_EXIT(&ipf_nat);
}
} else
error = fr_natputent(data, getlock);
} else {
error = EACCES;
}
break;
case SIOCSTGSZ :
if (fr_nat_lock) {
@ -872,6 +867,9 @@ int getlock;
return ENOENT;
}
if ((n->in_age[0] == 0) && (n->in_age[1] != 0))
return EINVAL;
n->in_use = 0;
if (n->in_redir & NAT_MAPBLK)
n->in_space = USABLE_PORTS * ~ntohl(n->in_outmsk);
@ -1040,11 +1038,17 @@ int getlock;
rdr_masks = 0;
}
if (n->in_tqehead[0] != NULL)
fr_deletetimeoutqueue(n->in_tqehead[0]);
if (n->in_tqehead[0] != NULL) {
if (fr_deletetimeoutqueue(n->in_tqehead[0]) == 0) {
fr_freetimeoutqueue(n->in_tqehead[1]);
}
}
if (n->in_tqehead[1] != NULL)
fr_deletetimeoutqueue(n->in_tqehead[1]);
if (n->in_tqehead[1] != NULL) {
if (fr_deletetimeoutqueue(n->in_tqehead[1]) == 0) {
fr_freetimeoutqueue(n->in_tqehead[1]);
}
}
*np = n->in_next;
@ -1149,6 +1153,9 @@ caddr_t data;
if (error != 0)
return error;
if ((ipns.ipn_dsize < sizeof(ipns)) || (ipns.ipn_dsize > 81920))
return EINVAL;
KMALLOCS(ipn, nat_save_t *, ipns.ipn_dsize);
if (ipn == NULL)
return ENOMEM;
@ -1204,7 +1211,7 @@ caddr_t data;
* private data saved along side it by the proxy.
*/
aps = nat->nat_aps;
outsize = ipn->ipn_dsize - sizeof(*ipn) + 4;
outsize = ipn->ipn_dsize - sizeof(*ipn) + sizeof(ipn->ipn_data);
if (aps != NULL) {
char *s;
@ -1237,20 +1244,24 @@ finished:
/* ------------------------------------------------------------------------ */
/* Function: fr_natputent */
/* Returns: int - 0 == success, != 0 is the error value. */
/* Parameters: data(I) - pointer to natget structure with NAT structure */
/* information to load into the kernel. */
/* Parameters: data(I) - pointer to natget structure with NAT */
/* structure information to load into the kernel */
/* getlock(I) - flag indicating whether or not a write lock */
/* on ipf_nat is already held. */
/* */
/* Handle SIOCSTPUT. */
/* Loads a NAT table entry from user space, including a NAT rule, proxy and */
/* firewall rule data structures, if pointers to them indicate so. */
/* ------------------------------------------------------------------------ */
static int fr_natputent(data)
static int fr_natputent(data, getlock)
caddr_t data;
int getlock;
{
nat_save_t ipn, *ipnn;
ap_session_t *aps;
nat_t *n, *nat;
frentry_t *fr;
fr_info_t fin;
ipnat_t *in;
int error;
@ -1258,9 +1269,25 @@ caddr_t data;
if (error != 0)
return error;
/*
* Initialise early because of code at junkput label.
*/
in = NULL;
aps = NULL;
nat = NULL;
ipnn = NULL;
/*
* New entry, copy in the rest of the NAT entry if it's size is more
* than just the nat_t structure.
*/
fr = NULL;
if (ipn.ipn_dsize > sizeof(ipn)) {
if (ipn.ipn_dsize > 81920) {
error = ENOMEM;
goto junkput;
}
KMALLOCS(ipnn, nat_save_t *, ipn.ipn_dsize);
if (ipnn == NULL)
return ENOMEM;
@ -1283,9 +1310,6 @@ caddr_t data;
/*
* Initialize all these so that nat_delete() doesn't cause a crash.
*/
fr = nat->nat_fr;
aps = nat->nat_aps;
in = nat->nat_ptr;
bzero((char *)nat, offsetof(struct nat, nat_tqe));
nat->nat_tqe.tqe_pnext = NULL;
nat->nat_tqe.tqe_next = NULL;
@ -1295,13 +1319,14 @@ caddr_t data;
/*
* Restore the rule associated with this nat session
*/
in = ipnn->ipn_nat.nat_ptr;
if (in != NULL) {
KMALLOC(in, ipnat_t *);
nat->nat_ptr = in;
if (in == NULL) {
error = ENOMEM;
goto junkput;
}
nat->nat_ptr = in;
bzero((char *)in, offsetof(struct ipnat, in_next6));
bcopy((char *)&ipnn->ipn_ipnat, (char *)in, sizeof(*in));
in->in_use = 1;
@ -1312,26 +1337,56 @@ caddr_t data;
nat_resolverule(in);
}
/*
* Check that the NAT entry doesn't already exist in the kernel.
*/
bzero((char *)&fin, sizeof(fin));
fin.fin_p = nat->nat_p;
if (nat->nat_dir == NAT_OUTBOUND) {
fin.fin_data[0] = ntohs(nat->nat_oport);
fin.fin_data[1] = ntohs(nat->nat_outport);
fin.fin_ifp = nat->nat_ifps[1];
if (nat_inlookup(&fin, 0, fin.fin_p, nat->nat_oip,
nat->nat_inip) != NULL) {
error = EEXIST;
goto junkput;
}
} else if (nat->nat_dir == NAT_INBOUND) {
fin.fin_data[0] = ntohs(nat->nat_outport);
fin.fin_data[1] = ntohs(nat->nat_oport);
fin.fin_ifp = nat->nat_ifps[0];
if (nat_outlookup(&fin, 0, fin.fin_p, nat->nat_outip,
nat->nat_oip) != NULL) {
error = EEXIST;
goto junkput;
}
} else {
error = EINVAL;
goto junkput;
}
/*
* Restore ap_session_t structure. Include the private data allocated
* if it was there.
*/
aps = nat->nat_aps;
if (aps != NULL) {
KMALLOC(aps, ap_session_t *);
nat->nat_aps = aps;
if (aps == NULL) {
error = ENOMEM;
goto junkput;
}
nat->nat_aps = aps;
aps->aps_next = ap_sess_list;
ap_sess_list = aps;
bcopy(ipnn->ipn_data, (char *)aps, sizeof(*aps));
if (in != NULL)
aps->aps_apr = in->in_apr;
else
aps->aps_apr = NULL;
aps->aps_nat = nat;
if (aps->aps_psiz != 0) {
if (aps->aps_psiz > 81920) {
error = ENOMEM;
goto junkput;
}
KMALLOCS(aps->aps_data, void *, aps->aps_psiz);
if (aps->aps_data == NULL) {
error = ENOMEM;
@ -1349,6 +1404,7 @@ caddr_t data;
* If there was a filtering rule associated with this entry then
* build up a new one.
*/
fr = nat->nat_fr;
if (fr != NULL) {
if ((nat->nat_flags & SI_NEWFR) != 0) {
KMALLOC(fr, frentry_t *);
@ -1358,15 +1414,24 @@ caddr_t data;
goto junkput;
}
ipnn->ipn_nat.nat_fr = fr;
fr->fr_ref = 0;
fr->fr_ref = 1;
(void) fr_outobj(data, ipnn, IPFOBJ_NATSAVE);
bcopy((char *)&ipnn->ipn_fr, (char *)fr, sizeof(*fr));
MUTEX_NUKE(&fr->fr_lock);
MUTEX_INIT(&fr->fr_lock, "nat-filter rule lock");
} else {
READ_ENTER(&ipf_nat);
for (n = nat_instances; n; n = n->nat_next)
if (n->nat_fr == fr)
break;
if (n != NULL) {
MUTEX_ENTER(&fr->fr_lock);
fr->fr_ref++;
MUTEX_EXIT(&fr->fr_lock);
}
RWLOCK_EXIT(&ipf_nat);
if (!n) {
error = ESRCH;
goto junkput;
@ -1378,32 +1443,43 @@ caddr_t data;
KFREES(ipnn, ipn.ipn_dsize);
ipnn = NULL;
}
if (nat_insert(nat, nat->nat_rev) == 0) {
if (fr != NULL) {
MUTEX_ENTER(&fr->fr_lock);
fr->fr_ref++;
MUTEX_EXIT(&fr->fr_lock);
}
return 0;
if (getlock) {
WRITE_ENTER(&ipf_nat);
}
error = nat_insert(nat, nat->nat_rev);
if ((error == 0) && (aps != NULL)) {
aps->aps_next = ap_sess_list;
ap_sess_list = aps;
}
if (getlock) {
RWLOCK_EXIT(&ipf_nat);
}
if (error == 0)
return 0;
error = ENOMEM;
junkput:
if (fr != NULL)
fr_derefrule(&fr);
if ((ipnn != NULL) && (ipnn != &ipn)) {
KFREES(ipnn, ipn.ipn_dsize);
}
if (nat != NULL) {
if (nat->nat_fr) {
MUTEX_DESTROY(&nat->nat_fr->fr_lock);
KFREE(nat->nat_fr);
}
if (aps != NULL) {
if (aps->aps_data != NULL) {
KFREES(aps->aps_data, aps->aps_psiz);
}
KFREE(aps);
}
if (in != NULL) {
if (in->in_apr)
appr_free(in->in_apr);
KFREE(in);
}
KFREE(nat);
}
return error;
@ -1424,9 +1500,7 @@ static void nat_delete(nat, logtype)
struct nat *nat;
int logtype;
{
ipftqent_t *tqe;
struct ipnat *ipn;
ipftq_t *ifq;
if (logtype != 0 && nat_logging != 0)
nat_log(nat, logtype);
@ -1471,19 +1545,7 @@ int logtype;
nat->nat_me = NULL;
}
tqe = &nat->nat_tqe;
ifq = tqe->tqe_ifq;
if (ifq != NULL) {
*tqe->tqe_pnext = tqe->tqe_next;
if (tqe->tqe_next != NULL)
tqe->tqe_next->tqe_pnext = tqe->tqe_pnext;
else
ifq->ifq_tail = tqe->tqe_pnext;
tqe->tqe_ifq = NULL;
if ((ifq->ifq_flags & IFQF_USER) != 0)
fr_deletetimeoutqueue(ifq);
}
fr_deletequeueentry(&nat->nat_tqe);
nat->nat_ref--;
if (nat->nat_ref > 0) {
@ -1861,6 +1923,17 @@ natinfo_t *ni;
((icmphdr_t *)fin->fin_dp)->icmp_id = port;
nat->nat_inport = port;
nat->nat_outport = port;
} else if (fin->fin_p == IPPROTO_GRE) {
#if 0
nat->nat_gre.gs_flags = ((grehdr_t *)fin->fin_dp)->gr_flags;
if (GRE_REV(nat->nat_gre.gs_flags) == 1) {
nat->nat_oport = 0;/*fin->fin_data[1];*/
nat->nat_inport = 0;/*fin->fin_data[0];*/
nat->nat_outport = 0;/*fin->fin_data[0];*/
nat->nat_call[0] = fin->fin_data[0];
nat->nat_call[1] = fin->fin_data[0];
}
#endif
}
ni->nai_ip.s_addr = in.s_addr;
ni->nai_port = port;
@ -2020,6 +2093,17 @@ natinfo_t *ni;
((icmphdr_t *)fin->fin_dp)->icmp_id = nport;
nat->nat_inport = nport;
nat->nat_outport = nport;
} else if (fin->fin_p == IPPROTO_GRE) {
#if 0
nat->nat_gre.gs_flags = ((grehdr_t *)fin->fin_dp)->gr_flags;
if (GRE_REV(nat->nat_gre.gs_flags) == 1) {
nat->nat_call[0] = fin->fin_data[0];
nat->nat_call[1] = fin->fin_data[1];
nat->nat_oport = 0; /*fin->fin_data[0];*/
nat->nat_inport = 0; /*fin->fin_data[1];*/
nat->nat_outport = 0; /*fin->fin_data[1];*/
}
#endif
}
return move;
@ -2954,9 +3038,6 @@ struct in_addr src , mapdst;
else
dport = fin->fin_data[1];
break;
case IPPROTO_GRE :
gre = fin->fin_dp;
break;
default :
break;
}
@ -2990,7 +3071,7 @@ struct in_addr src , mapdst;
{
#if 0
case IPPROTO_GRE :
if (gre->gr_call != nat->nat_gre.gs_call)
if (nat->nat_call[1] != fin->fin_data[0])
continue;
break;
#endif
@ -3239,7 +3320,7 @@ struct in_addr src , dst;
{
#if 0
case IPPROTO_GRE :
if (gre->gr_call != nat->nat_gre.gs_call)
if (nat->nat_call[1] != fin->fin_data[0])
continue;
break;
#endif
@ -3349,8 +3430,13 @@ natlookup_t *np;
nat_t *nat;
bzero((char *)&fi, sizeof(fi));
fi.fin_data[0] = ntohs(np->nl_inport);
fi.fin_data[1] = ntohs(np->nl_outport);
if (np->nl_flags & IPN_IN) {
fi.fin_data[0] = ntohs(np->nl_realport);
fi.fin_data[1] = ntohs(np->nl_outport);
} else {
fi.fin_data[0] = ntohs(np->nl_inport);
fi.fin_data[1] = ntohs(np->nl_outport);
}
if (np->nl_flags & IPN_TCP)
fi.fin_p = IPPROTO_TCP;
else if (np->nl_flags & IPN_UDP)
@ -3359,14 +3445,42 @@ natlookup_t *np;
fi.fin_p = IPPROTO_ICMP;
/*
* If nl_inip is non null, this is a lookup based on the real
* ip address. Else, we use the fake.
* We can do two sorts of lookups:
* - IPN_IN: we have the `real' and `out' address, look for `in'.
* - default: we have the `in' and `out' address, look for `real'.
*/
if ((nat = nat_outlookup(&fi, np->nl_flags, fi.fin_p, np->nl_inip,
np->nl_outip))) {
np->nl_realip = nat->nat_outip;
np->nl_realport = nat->nat_outport;
}
if (np->nl_flags & IPN_IN) {
if ((nat = nat_inlookup(&fi, np->nl_flags, fi.fin_p,
np->nl_realip, np->nl_outip))) {
np->nl_inip = nat->nat_inip;
np->nl_inport = nat->nat_inport;
}
} else {
/*
* If nl_inip is non null, this is a lookup based on the real
* ip address. Else, we use the fake.
*/
if ((nat = nat_outlookup(&fi, np->nl_flags, fi.fin_p,
np->nl_inip, np->nl_outip))) {
if ((np->nl_flags & IPN_FINDFORWARD) != 0) {
fr_info_t fin;
bzero((char *)&fin, sizeof(fin));
fin.fin_p = nat->nat_p;
fin.fin_data[0] = ntohs(nat->nat_outport);
fin.fin_data[1] = ntohs(nat->nat_oport);
if (nat_inlookup(&fin, np->nl_flags, fin.fin_p,
nat->nat_outip,
nat->nat_oip) != NULL) {
np->nl_flags &= ~IPN_FINDFORWARD;
}
}
np->nl_realip = nat->nat_outip;
np->nl_realport = nat->nat_outport;
}
}
return nat;
}
@ -4000,7 +4114,8 @@ u_32_t nflags;
* fast forwarding (so that it doesn't need to be recomputed) but with
* header checksum offloading, perhaps it is a moot point.
*/
#if !defined(_KERNEL) || defined(MENTAT) || defined(__sgi) || defined(__osf__)
#if !defined(_KERNEL) || defined(MENTAT) || defined(__sgi) || \
defined(__osf__) || defined(linux)
if (nat->nat_dir == NAT_OUTBOUND)
fix_incksum(fin, &fin->fin_ip->ip_sum, nat->nat_ipsumd);
else
@ -4118,9 +4233,25 @@ u_int nflags;
/* ------------------------------------------------------------------------ */
void fr_natunload()
{
ipftq_t *ifq, *ifqnext;
(void) nat_clearlist();
(void) nat_flushtable();
/*
* Proxy timeout queues are not cleaned here because although they
* exist on the NAT list, appr_unload is called after fr_natunload
* and the proxies actually are responsible for them being created.
* Should the proxy timeouts have their own list? There's no real
* justification as this is the only complication.
*/
for (ifq = nat_utqe; ifq != NULL; ifq = ifqnext) {
ifqnext = ifq->ifq_next;
if (((ifq->ifq_flags & IFQF_PROXY) == 0) &&
(fr_deletetimeoutqueue(ifq) == 0))
fr_freetimeoutqueue(ifq);
}
if (nat_table[0] != NULL) {
KFREES(nat_table[0], sizeof(nat_t *) * ipf_nattable_sz);
nat_table[0] = NULL;
@ -4211,6 +4342,15 @@ void fr_natexpire()
}
}
for (ifq = nat_utqe; ifq != NULL; ifq = ifqnext) {
ifqnext = ifq->ifq_next;
if (((ifq->ifq_flags & IFQF_DELETE) != 0) &&
(ifq->ifq_ref == 0)) {
fr_freetimeoutqueue(ifq);
}
}
RWLOCK_EXIT(&ipf_nat);
SPL_X(s);
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: ip_nat.h,v 1.4 2005/02/19 21:30:25 martti Exp $ */
/* $NetBSD: ip_nat.h,v 1.5 2005/04/03 15:05:30 martti Exp $ */
/*
* Copyright (C) 1995-2001, 2003 by Darren Reed.
@ -6,7 +6,7 @@
* See the IPFILTER.LICENCE file for details on licencing.
*
* @(#)ip_nat.h 1.5 2/4/96
* Id: ip_nat.h,v 2.90.2.6 2005/02/04 09:56:15 darrenr Exp
* Id: ip_nat.h,v 2.90.2.9 2005/03/28 11:09:55 darrenr Exp
*/
#ifndef __IP_NAT_H__
@ -137,7 +137,6 @@ typedef struct nat {
#define nat_seq nat_un.nat_uni.ici_seq
#define nat_id nat_un.nat_uni.ici_id
#define nat_tcpstate nat_tqe.tqe_state
#define nat_gre nat_un.nat_ugre
/*
* Values for nat_dir
@ -251,6 +250,8 @@ typedef struct ipnat {
#define IPN_STICKY 0x80000
#define IPN_FRAG 0x100000
#define IPN_FIXEDDPORT 0x200000
#define IPN_FINDFORWARD 0x400000
#define IPN_IN 0x800000
#define IPN_USERFLAGS (IPN_TCPUDP|IPN_AUTOPORTMAP|IPN_IPRANGE|IPN_SPLIT|\
IPN_ROUNDR|IPN_FILTER|IPN_NOTSRC|IPN_NOTDST|\
IPN_FRAG|IPN_STICKY|IPN_FIXEDDPORT|IPN_ICMPQUERY)

View File

@ -1,4 +1,4 @@
/* $NetBSD: ip_pptp_pxy.c,v 1.2 2005/02/08 07:01:55 martti Exp $ */
/* $NetBSD: ip_pptp_pxy.c,v 1.3 2005/04/03 15:05:30 martti Exp $ */
/*
* Copyright (C) 2002-2003 by Darren Reed
@ -6,18 +6,33 @@
* Simple PPTP transparent proxy for in-kernel use. For use with the NAT
* code.
*
* Id: ip_pptp_pxy.c,v 2.10.2.6 2004/11/25 15:37:37 darrenr Exp
* Id: ip_pptp_pxy.c,v 2.10.2.9 2005/03/16 18:17:34 darrenr Exp
*
*/
#define IPF_PPTP_PROXY
typedef struct pptp_pxy {
ipnat_t pptp_rule;
nat_t *pptp_nat;
ipstate_t *pptp_state;
int pptp_seencookie;
u_32_t pptp_cookie;
} pptp_pxy_t;
typedef struct pptp_hdr {
u_short pptph_len;
u_short pptph_type;
u_32_t pptph_cookie;
} pptp_hdr_t;
#define PPTP_MSGTYPE_CTL 1
#define PPTP_MTCTL_STARTREQ 1
#define PPTP_MTCTL_STARTREP 2
#define PPTP_MTCTL_STOPREQ 3
#define PPTP_MTCTL_STOPREP 4
#define PPTP_MTCTL_ECHOREQ 5
#define PPTP_MTCTL_ECHOREP 6
#define PPTP_MTCTL_OUTREQ 7
#define PPTP_MTCTL_OUTREP 8
#define PPTP_MTCTL_INREQ 9
#define PPTP_MTCTL_INREP 10
#define PPTP_MTCTL_INCONNECT 11
#define PPTP_MTCTL_CLEAR 12
#define PPTP_MTCTL_DISCONNECT 13
#define PPTP_MTCTL_WANERROR 14
#define PPTP_MTCTL_LINKINFO 15
int ippr_pptp_init __P((void));
@ -25,11 +40,16 @@ void ippr_pptp_fini __P((void));
int ippr_pptp_new __P((fr_info_t *, ap_session_t *, nat_t *));
void ippr_pptp_del __P((ap_session_t *));
int ippr_pptp_inout __P((fr_info_t *, ap_session_t *, nat_t *));
int ippr_pptp_match __P((fr_info_t *, ap_session_t *, nat_t *));
void ippr_pptp_donatstate __P((fr_info_t *, nat_t *, pptp_pxy_t *));
int ippr_pptp_message __P((fr_info_t *, nat_t *, pptp_pxy_t *, pptp_side_t *));
int ippr_pptp_nextmessage __P((fr_info_t *, nat_t *, pptp_pxy_t *, int));
int ippr_pptp_mctl __P((fr_info_t *, nat_t *, pptp_pxy_t *, pptp_side_t *));
static frentry_t pptpfr;
int pptp_proxy_init = 0;
int ippr_pptp_debug = 0;
int ippr_pptp_gretimeout = IPF_TTLVAL(120); /* 2 minutes */
/*
@ -39,6 +59,8 @@ int ippr_pptp_init()
{
bzero((char *)&pptpfr, sizeof(pptpfr));
pptpfr.fr_ref = 1;
pptpfr.fr_age[0] = ippr_pptp_gretimeout;
pptpfr.fr_age[1] = ippr_pptp_gretimeout;
pptpfr.fr_flags = FR_OUTQUE|FR_PASS|FR_QUICK|FR_KEEPSTATE;
MUTEX_INIT(&pptpfr.fr_lock, "PPTP proxy rule lock");
pptp_proxy_init = 1;
@ -65,72 +87,379 @@ ap_session_t *aps;
nat_t *nat;
{
pptp_pxy_t *pptp;
fr_info_t fi;
ipnat_t *ipn;
nat_t *nat2;
int p, off;
ip_t *ip;
int off;
ip = fin->fin_ip;
off = fin->fin_hlen + sizeof(udphdr_t);
if (nat_outlookup(fin, 0, IPPROTO_GRE, nat->nat_inip,
ip->ip_dst) != NULL)
ip->ip_dst) != NULL) {
if (ippr_pptp_debug > 0)
printf("ippr_pptp_new: GRE session already exists\n");
return -1;
}
aps->aps_psiz = sizeof(*pptp);
KMALLOCS(aps->aps_data, pptp_pxy_t *, sizeof(*pptp));
if (aps->aps_data == NULL)
if (aps->aps_data == NULL) {
if (ippr_pptp_debug > 0)
printf("ippr_pptp_new: malloc for aps_data failed\n");
return -1;
ip = fin->fin_ip;
pptp = aps->aps_data;
bzero((char *)pptp, sizeof(*pptp));
}
/*
* Create NAT rule against which the tunnel/transport mapping is
* created. This is required because the current NAT rule does not
* describe GRE but TCP instead.
*/
pptp = aps->aps_data;
bzero((char *)pptp, sizeof(*pptp));
ipn = &pptp->pptp_rule;
ipn->in_ifps[0] = fin->fin_ifp;
ipn->in_apr = NULL;
ipn->in_use = 1;
ipn->in_hits = 1;
ipn->in_nip = ntohl(nat->nat_outip.s_addr);
ipn->in_ippip = 1;
if (nat->nat_dir == NAT_OUTBOUND) {
ipn->in_nip = ntohl(nat->nat_outip.s_addr);
ipn->in_outip = fin->fin_saddr;
ipn->in_redir = NAT_MAP;
} else if (nat->nat_dir == NAT_INBOUND) {
ipn->in_nip = 0;
ipn->in_outip = nat->nat_outip.s_addr;
ipn->in_redir = NAT_REDIRECT;
}
ipn->in_inip = nat->nat_inip.s_addr;
ipn->in_inmsk = 0xffffffff;
ipn->in_outip = fin->fin_saddr;
ipn->in_outmsk = nat->nat_outip.s_addr;
ipn->in_outmsk = 0xffffffff;
ipn->in_srcip = fin->fin_saddr;
ipn->in_srcmsk = 0xffffffff;
ipn->in_redir = NAT_MAP;
bcopy(nat->nat_ptr->in_ifnames[0], ipn->in_ifnames[0],
sizeof(ipn->in_ifnames[0]));
ipn->in_p = IPPROTO_GRE;
bcopy((char *)fin, (char *)&fi, sizeof(fi));
fi.fin_fi.fi_p = IPPROTO_GRE;
fi.fin_fr = &pptpfr;
fi.fin_data[0] = 0;
fi.fin_data[1] = 0;
pptp->pptp_side[0].pptps_wptr = pptp->pptp_side[0].pptps_buffer;
pptp->pptp_side[1].pptps_wptr = pptp->pptp_side[1].pptps_buffer;
return 0;
}
void ippr_pptp_donatstate(fin, nat, pptp)
fr_info_t *fin;
nat_t *nat;
pptp_pxy_t *pptp;
{
fr_info_t fi;
grehdr_t gre;
nat_t *nat2;
u_char p;
ip_t *ip;
ip = fin->fin_ip;
p = ip->ip_p;
ip->ip_p = IPPROTO_GRE;
fi.fin_flx &= ~FI_TCPUDP;
fi.fin_flx |= FI_IGNORE;
nat2 = nat_new(&fi, ipn, &pptp->pptp_nat, NAT_SLAVE, NAT_OUTBOUND);
pptp->pptp_nat = nat2;
if (nat2 != NULL) {
(void) nat_proto(&fi, nat2, 0);
nat_update(&fi, nat2, nat2->nat_ptr);
nat2 = pptp->pptp_nat;
if ((nat2 == NULL) || (pptp->pptp_state == NULL)) {
bcopy((char *)fin, (char *)&fi, sizeof(fi));
bzero((char *)&gre, sizeof(gre));
fi.fin_state = NULL;
fi.fin_nat = NULL;
fi.fin_fi.fi_p = IPPROTO_GRE;
fi.fin_fr = &pptpfr;
if ((nat->nat_dir == NAT_OUTBOUND && fin->fin_out) ||
(nat->nat_dir == NAT_INBOUND && !fin->fin_out)) {
fi.fin_data[0] = pptp->pptp_call[0];
fi.fin_data[1] = pptp->pptp_call[1];
} else {
fi.fin_data[0] = pptp->pptp_call[1];
fi.fin_data[1] = pptp->pptp_call[0];
}
ip = fin->fin_ip;
ip->ip_p = IPPROTO_GRE;
fi.fin_flx &= ~(FI_TCPUDP|FI_STATE|FI_FRAG);
fi.fin_flx |= FI_IGNORE;
fi.fin_dp = &gre;
gre.gr_flags = htons(1 << 13);
if (fin->fin_out && nat->nat_dir == NAT_INBOUND) {
fi.fin_fi.fi_saddr = fin->fin_fi.fi_daddr;
fi.fin_fi.fi_daddr = nat->nat_outip.s_addr;
} else if (!fin->fin_out && nat->nat_dir == NAT_OUTBOUND) {
fi.fin_fi.fi_saddr = nat->nat_inip.s_addr;
fi.fin_fi.fi_daddr = fin->fin_fi.fi_saddr;
}
}
fi.fin_data[0] = 0;
fi.fin_data[1] = 0;
pptp->pptp_state = fr_addstate(&fi, &pptp->pptp_state, 0);
/*
* Update NAT timeout/create NAT if missing.
*/
if (nat2 != NULL)
fr_queueback(&nat2->nat_tqe);
else {
nat2 = nat_new(&fi, &pptp->pptp_rule, &pptp->pptp_nat,
NAT_SLAVE, nat->nat_dir);
pptp->pptp_nat = nat2;
if (nat2 != NULL) {
(void) nat_proto(&fi, nat2, 0);
nat_update(&fi, nat2, nat2->nat_ptr);
}
}
READ_ENTER(&ipf_state);
if (pptp->pptp_state != NULL) {
fr_queueback(&pptp->pptp_state->is_sti);
RWLOCK_EXIT(&ipf_state);
} else {
RWLOCK_EXIT(&ipf_state);
if (nat->nat_dir == NAT_INBOUND)
fi.fin_fi.fi_daddr = nat2->nat_inip.s_addr;
else
fi.fin_fi.fi_saddr = nat2->nat_inip.s_addr;
fi.fin_ifp = NULL;
pptp->pptp_state = fr_addstate(&fi, &pptp->pptp_state,
0);
if (fi.fin_state != NULL)
fr_statederef(&fi, (ipstate_t **)&fi.fin_state);
}
ip->ip_p = p;
return;
}
/*
* Try and build up the next PPTP message in the TCP stream and if we can
* build it up completely (fits in our buffer) then pass it off to the message
* parsing function.
*/
int ippr_pptp_nextmessage(fin, nat, pptp, rev)
fr_info_t *fin;
nat_t *nat;
pptp_pxy_t *pptp;
int rev;
{
static char *funcname = "ippr_pptp_nextmessage";
pptp_side_t *pptps;
u_32_t start, end;
pptp_hdr_t *hdr;
tcphdr_t *tcp;
int dlen, off;
u_short len;
char *msg;
tcp = fin->fin_dp;
dlen = fin->fin_dlen - (TCP_OFF(tcp) << 2);
start = ntohl(tcp->th_seq);
pptps = &pptp->pptp_side[rev];
off = (char *)tcp - (char *)fin->fin_ip + (TCP_OFF(tcp) << 2) +
fin->fin_ipoff;
if (dlen <= 0)
return 0;
/*
* If the complete data packet is before what we expect to see
* "next", just ignore it as the chances are we've already seen it.
* The next if statement following this one really just causes packets
* ahead of what we've seen to be dropped, implying that something in
* the middle went missing and we want to see that first.
*/
end = start + dlen;
if (pptps->pptps_next > end && pptps->pptps_next > start)
return 0;
if (pptps->pptps_next != start) {
if (ippr_pptp_debug > 5)
printf("%s: next (%x) != start (%x)\n", funcname,
pptps->pptps_next, start);
return -1;
}
msg = (char *)fin->fin_dp + (TCP_OFF(tcp) << 2);
while (dlen > 0) {
off += pptps->pptps_bytes;
if (pptps->pptps_gothdr == 0) {
/*
* PPTP has an 8 byte header that inclues the cookie.
* The start of every message should include one and
* it should match 1a2b3c4d. Byte order is ignored,
* deliberately, when printing out the error.
*/
len = MIN(8 - pptps->pptps_bytes, dlen);
COPYDATA(fin->fin_m, off, len, pptps->pptps_wptr);
pptps->pptps_bytes += len;
pptps->pptps_wptr += len;
hdr = (pptp_hdr_t *)pptps->pptps_buffer;
if (pptps->pptps_bytes == 8) {
pptps->pptps_next += 8;
if (ntohl(hdr->pptph_cookie) != 0x1a2b3c4d) {
if (ippr_pptp_debug > 1)
printf("%s: bad cookie (%x)\n",
funcname,
hdr->pptph_cookie);
return -1;
}
}
dlen -= len;
msg += len;
off += len;
pptps->pptps_gothdr = 1;
len = ntohs(hdr->pptph_len);
pptps->pptps_len = len;
pptps->pptps_nexthdr += len;
/*
* If a message is too big for the buffer, just set
* the fields for the next message to come along.
* The messages defined in RFC 2637 will not exceed
* 512 bytes (in total length) so this is likely a
* bad data packet, anyway.
*/
if (len > sizeof(pptps->pptps_buffer)) {
if (ippr_pptp_debug > 3)
printf("%s: message too big (%d)\n",
funcname, len);
pptps->pptps_next = pptps->pptps_nexthdr;
pptps->pptps_wptr = pptps->pptps_buffer;
pptps->pptps_gothdr = 0;
pptps->pptps_bytes = 0;
pptps->pptps_len = 0;
break;
}
}
len = MIN(pptps->pptps_len - pptps->pptps_bytes, dlen);
COPYDATA(fin->fin_m, off, len, pptps->pptps_wptr);
pptps->pptps_bytes += len;
pptps->pptps_wptr += len;
pptps->pptps_next += len;
if (pptps->pptps_len > pptps->pptps_bytes)
break;
ippr_pptp_message(fin, nat, pptp, pptps);
pptps->pptps_wptr = pptps->pptps_buffer;
pptps->pptps_gothdr = 0;
pptps->pptps_bytes = 0;
pptps->pptps_len = 0;
start += len;
msg += len;
dlen -= len;
}
return 0;
}
/*
* handle a complete PPTP message
*/
int ippr_pptp_message(fin, nat, pptp, pptps)
fr_info_t *fin;
nat_t *nat;
pptp_pxy_t *pptp;
pptp_side_t *pptps;
{
pptp_hdr_t *hdr = (pptp_hdr_t *)pptps->pptps_buffer;
switch (ntohs(hdr->pptph_type))
{
case PPTP_MSGTYPE_CTL :
ippr_pptp_mctl(fin, nat, pptp, pptps);
break;
default :
break;
}
return 0;
}
/*
* handle a complete PPTP control message
*/
int ippr_pptp_mctl(fin, nat, pptp, pptps)
fr_info_t *fin;
nat_t *nat;
pptp_pxy_t *pptp;
pptp_side_t *pptps;
{
u_short *buffer = (u_short *)(pptps->pptps_buffer);
pptp_side_t *pptpo;
if (pptps == &pptp->pptp_side[0])
pptpo = &pptp->pptp_side[1];
else
pptpo = &pptp->pptp_side[0];
/*
* Breakout to handle all the various messages. Most are just state
* transition.
*/
switch (ntohs(buffer[4]))
{
case PPTP_MTCTL_STARTREQ :
pptps->pptps_state = PPTP_MTCTL_STARTREQ;
break;
case PPTP_MTCTL_STARTREP :
if (pptpo->pptps_state == PPTP_MTCTL_STARTREQ)
pptps->pptps_state = PPTP_MTCTL_STARTREP;
break;
case PPTP_MTCTL_STOPREQ :
pptps->pptps_state = PPTP_MTCTL_STOPREQ;
break;
case PPTP_MTCTL_STOPREP :
if (pptpo->pptps_state == PPTP_MTCTL_STOPREQ)
pptps->pptps_state = PPTP_MTCTL_STOPREP;
break;
case PPTP_MTCTL_ECHOREQ :
pptps->pptps_state = PPTP_MTCTL_ECHOREQ;
break;
case PPTP_MTCTL_ECHOREP :
if (pptpo->pptps_state == PPTP_MTCTL_ECHOREQ)
pptps->pptps_state = PPTP_MTCTL_ECHOREP;
break;
case PPTP_MTCTL_OUTREQ :
pptps->pptps_state = PPTP_MTCTL_OUTREQ;
break;
case PPTP_MTCTL_OUTREP :
if (pptpo->pptps_state == PPTP_MTCTL_OUTREQ) {
pptps->pptps_state = PPTP_MTCTL_OUTREP;
pptp->pptp_call[0] = buffer[7];
pptp->pptp_call[1] = buffer[6];
ippr_pptp_donatstate(fin, nat, pptp);
}
break;
case PPTP_MTCTL_INREQ :
pptps->pptps_state = PPTP_MTCTL_INREQ;
break;
case PPTP_MTCTL_INREP :
if (pptpo->pptps_state == PPTP_MTCTL_INREQ) {
pptps->pptps_state = PPTP_MTCTL_INREP;
pptp->pptp_call[0] = buffer[7];
pptp->pptp_call[1] = buffer[6];
ippr_pptp_donatstate(fin, nat, pptp);
}
break;
case PPTP_MTCTL_INCONNECT :
pptps->pptps_state = PPTP_MTCTL_INCONNECT;
break;
case PPTP_MTCTL_CLEAR :
pptps->pptps_state = PPTP_MTCTL_CLEAR;
break;
case PPTP_MTCTL_DISCONNECT :
pptps->pptps_state = PPTP_MTCTL_DISCONNECT;
break;
case PPTP_MTCTL_WANERROR :
pptps->pptps_state = PPTP_MTCTL_WANERROR;
break;
case PPTP_MTCTL_LINKINFO :
pptps->pptps_state = PPTP_MTCTL_LINKINFO;
break;
}
return 0;
}
@ -145,66 +474,26 @@ ap_session_t *aps;
nat_t *nat;
{
pptp_pxy_t *pptp;
fr_info_t fi;
nat_t *nat2;
ip_t *ip;
int p;
tcphdr_t *tcp;
int rev;
if ((fin->fin_out == 1) && (nat->nat_dir == NAT_INBOUND))
return 0;
rev = 1;
else if ((fin->fin_out == 0) && (nat->nat_dir == NAT_OUTBOUND))
rev = 1;
else
rev = 0;
if ((fin->fin_out == 0) && (nat->nat_dir == NAT_OUTBOUND))
return 0;
pptp = aps->aps_data;
if (pptp != NULL) {
ip = fin->fin_ip;
p = ip->ip_p;
if ((pptp->pptp_nat == NULL) || (pptp->pptp_state == NULL)) {
bcopy((char *)fin, (char *)&fi, sizeof(fi));
fi.fin_fi.fi_p = IPPROTO_GRE;
fi.fin_fr = &pptpfr;
fi.fin_data[0] = 0;
fi.fin_data[1] = 0;
ip->ip_p = IPPROTO_GRE;
fi.fin_flx &= ~FI_TCPUDP;
fi.fin_flx |= FI_IGNORE;
}
/*
* Update NAT timeout/create NAT if missing.
*/
if (pptp->pptp_nat != NULL)
fr_queueback(&pptp->pptp_nat->nat_tqe);
else {
nat2 = nat_new(&fi, &pptp->pptp_rule, &pptp->pptp_nat,
NAT_SLAVE, nat->nat_dir);
pptp->pptp_nat = nat2;
if (nat2 != NULL) {
(void) nat_proto(&fi, nat2, 0);
nat_update(&fi, nat2, nat2->nat_ptr);
}
}
/*
* Update state timeout/create state if missing.
*/
READ_ENTER(&ipf_state);
if (pptp->pptp_state != NULL) {
fr_queueback(&pptp->pptp_state->is_sti);
RWLOCK_EXIT(&ipf_state);
} else {
RWLOCK_EXIT(&ipf_state);
fi.fin_data[0] = 0;
fi.fin_data[1] = 0;
pptp->pptp_state = fr_addstate(&fi, &pptp->pptp_state,
0);
}
ip->ip_p = p;
tcp = (tcphdr_t *)fin->fin_dp;
if ((tcp->th_flags & TH_OPENING) == TH_OPENING) {
pptp = (pptp_pxy_t *)aps->aps_data;
pptp->pptp_side[1 - rev].pptps_next = ntohl(tcp->th_ack);
pptp->pptp_side[1 - rev].pptps_nexthdr = ntohl(tcp->th_ack);
pptp->pptp_side[rev].pptps_next = ntohl(tcp->th_seq) + 1;
pptp->pptp_side[rev].pptps_nexthdr = ntohl(tcp->th_seq) + 1;
}
return 0;
return ippr_pptp_nextmessage(fin, nat, (pptp_pxy_t *)aps->aps_data,
rev);
}
@ -236,36 +525,3 @@ ap_session_t *aps;
pptp->pptp_nat = NULL;
}
}
int ippr_pptp_match(fin, aps, nat)
fr_info_t *fin;
ap_session_t *aps;
nat_t *nat;
{
pptp_pxy_t *pptp;
tcphdr_t *tcp;
u_32_t cookie;
pptp = aps->aps_data;
tcp = fin->fin_dp;
if ((pptp != NULL) && (fin->fin_dlen - (TCP_OFF(tcp) << 2) >= 8)) {
u_char *cs;
cs = (u_char *)tcp + (TCP_OFF(tcp) << 2) + 4;
if (pptp->pptp_seencookie == 0) {
pptp->pptp_seencookie = 1;
pptp->pptp_cookie = (cs[0] << 24) | (cs[1] << 16) |
(cs[2] << 8) | cs[3];
} else {
cookie = (cs[0] << 24) | (cs[1] << 16) |
(cs[2] << 8) | cs[3];
if (cookie != pptp->pptp_cookie)
return -1;
}
}
return 0;
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: ip_proxy.c,v 1.5 2005/02/19 21:30:25 martti Exp $ */
/* $NetBSD: ip_proxy.c,v 1.6 2005/04/03 15:05:30 martti Exp $ */
/*
* Copyright (C) 1997-2003 by Darren Reed.
@ -105,7 +105,7 @@ struct file;
/* END OF INCLUDES */
#if !defined(lint)
static const char rcsid[] = "@(#)Id: ip_proxy.c,v 2.62.2.10 2005/02/17 04:40:03 darrenr Exp";
static const char rcsid[] = "@(#)Id: ip_proxy.c,v 2.62.2.12 2005/03/03 14:28:24 darrenr Exp";
#endif
static int appr_fixseqack __P((fr_info_t *, ip_t *, ap_session_t *, int ));
@ -153,7 +153,7 @@ aproxy_t ap_proxies[] = {
#ifdef IPF_PPTP_PROXY
{ NULL, "pptp", (char)IPPROTO_TCP, 0, 0,
ippr_pptp_init, ippr_pptp_fini, ippr_pptp_new, ippr_pptp_del,
ippr_pptp_inout, ippr_pptp_inout, ippr_pptp_match, NULL },
ippr_pptp_inout, ippr_pptp_inout, NULL, NULL },
#endif
#ifdef IPF_H323_PROXY
{ NULL, "h323", (char)IPPROTO_TCP, 0, 0, ippr_h323_init, ippr_h323_fini,

View File

@ -1,4 +1,4 @@
/* $NetBSD: ip_proxy.h,v 1.1.1.2 2005/04/03 15:02:14 martti Exp $ */
/* $NetBSD: ip_proxy.h,v 1.2 2005/04/03 15:05:30 martti Exp $ */
/*
* Copyright (C) 1997-2001 by Darren Reed.
@ -8,8 +8,8 @@
* Id: ip_proxy.h,v 2.31.2.2 2005/03/12 19:33:48 darrenr Exp
*/
#ifndef __IP_PROXY_H__
#define __IP_PROXY_H__
#ifndef _NETINET_IP_PROXY_H_
#define _NETINET_IP_PROXY_H_
#ifndef SOLARIS
#define SOLARIS (defined(sun) && (defined(__svr4__) || defined(__SVR4)))
@ -450,4 +450,4 @@ extern aproxy_t *appr_lookup __P((u_int, char *));
extern int appr_new __P((fr_info_t *, struct nat *));
extern int appr_ioctl __P((caddr_t, ioctlcmd_t, int));
#endif /* __IP_PROXY_H__ */
#endif /* _NETINET_IP_PROXY_H_ */

View File

@ -1,4 +1,4 @@
/* $NetBSD: ip_state.c,v 1.6 2005/03/26 18:08:42 christos Exp $ */
/* $NetBSD: ip_state.c,v 1.7 2005/04/03 15:05:30 martti Exp $ */
/*
* Copyright (C) 1995-2003 by Darren Reed.
@ -110,10 +110,10 @@ struct file;
#if !defined(lint)
#if defined(__NetBSD__)
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: ip_state.c,v 1.6 2005/03/26 18:08:42 christos Exp $");
__KERNEL_RCSID(0, "$NetBSD: ip_state.c,v 1.7 2005/04/03 15:05:30 martti Exp $");
#else
static const char sccsid[] = "@(#)ip_state.c 1.8 6/5/96 (C) 1993-2000 Darren Reed";
static const char rcsid[] = "@(#)Id: ip_state.c,v 2.186.2.25 2005/02/17 05:56:26 darrenr Exp";
static const char rcsid[] = "@(#)Id: ip_state.c,v 2.186.2.29 2005/03/28 10:47:54 darrenr Exp";
#endif
#endif
@ -157,7 +157,8 @@ u_long fr_tcpidletimeout = FIVE_DAYS,
fr_udptimeout = IPF_TTLVAL(120),
fr_udpacktimeout = IPF_TTLVAL(12),
fr_icmptimeout = IPF_TTLVAL(60),
fr_icmpacktimeout = IPF_TTLVAL(6);
fr_icmpacktimeout = IPF_TTLVAL(6),
fr_iptimeout = IPF_TTLVAL(60);
int fr_statemax = IPSTATE_MAX,
fr_statesize = IPSTATE_SIZE;
int fr_state_doflush = 0,
@ -168,6 +169,7 @@ int fr_state_doflush = 0,
ipftq_t ips_tqtqb[IPF_TCP_NSTATES],
ips_udptq,
ips_udpacktq,
ips_iptq,
ips_icmptq,
ips_icmpacktq,
*ips_utqe = NULL;
@ -247,25 +249,35 @@ int fr_stateinit()
fr_sttab_init(ips_tqtqb);
ips_tqtqb[IPF_TCP_NSTATES - 1].ifq_next = &ips_udptq;
ips_udptq.ifq_ttl = (u_long)fr_udptimeout;
ips_udptq.ifq_ref = 1;
ips_udptq.ifq_head = NULL;
ips_udptq.ifq_tail = &ips_udptq.ifq_head;
MUTEX_INIT(&ips_udptq.ifq_lock, "ipftq udp tab");
ips_udptq.ifq_next = &ips_udpacktq;
ips_udpacktq.ifq_ttl = (u_long)fr_udpacktimeout;
ips_udpacktq.ifq_ref = 1;
ips_udpacktq.ifq_head = NULL;
ips_udpacktq.ifq_tail = &ips_udpacktq.ifq_head;
MUTEX_INIT(&ips_udpacktq.ifq_lock, "ipftq udpack tab");
ips_udpacktq.ifq_next = &ips_icmptq;
ips_icmptq.ifq_ttl = (u_long)fr_icmptimeout;
ips_icmptq.ifq_ref = 1;
ips_icmptq.ifq_head = NULL;
ips_icmptq.ifq_tail = &ips_icmptq.ifq_head;
MUTEX_INIT(&ips_icmptq.ifq_lock, "ipftq icmp tab");
ips_icmptq.ifq_next = &ips_icmpacktq;
ips_icmpacktq.ifq_ttl = (u_long)fr_icmpacktimeout;
ips_icmpacktq.ifq_ref = 1;
ips_icmpacktq.ifq_head = NULL;
ips_icmpacktq.ifq_tail = &ips_icmpacktq.ifq_head;
MUTEX_INIT(&ips_icmpacktq.ifq_lock, "ipftq icmpack tab");
ips_icmpacktq.ifq_next = NULL;
ips_icmpacktq.ifq_next = &ips_iptq;
ips_iptq.ifq_ttl = (u_long)fr_iptimeout;
ips_iptq.ifq_ref = 1;
ips_iptq.ifq_head = NULL;
ips_iptq.ifq_tail = &ips_iptq.ifq_head;
MUTEX_INIT(&ips_iptq.ifq_lock, "ipftq ip tab");
ips_iptq.ifq_next = NULL;
RWLOCK_INIT(&ipf_state, "ipf IP state rwlock");
MUTEX_INIT(&ipf_stinsert, "ipf state insert mutex");
@ -286,10 +298,26 @@ int fr_stateinit()
/* ------------------------------------------------------------------------ */
void fr_stateunload()
{
ipftq_t *ifq, *ifqnext;
ipstate_t *is;
while ((is = ips_list) != NULL)
fr_delstate(is, 0);
/*
* Proxy timeout queues are not cleaned here because although they
* exist on the state list, appr_unload is called after fr_stateunload
* and the proxies actually are responsible for them being created.
* Should the proxy timeouts have their own list? There's no real
* justification as this is the only complicationA
*/
for (ifq = ips_utqe; ifq != NULL; ifq = ifqnext) {
ifqnext = ifq->ifq_next;
if (((ifq->ifq_flags & IFQF_PROXY) == 0) &&
(fr_deletetimeoutqueue(ifq) == 0))
fr_freetimeoutqueue(ifq);
}
ips_stats.iss_inuse = 0;
ips_num = 0;
@ -299,6 +327,7 @@ void fr_stateunload()
MUTEX_DESTROY(&ips_icmptq.ifq_lock);
MUTEX_DESTROY(&ips_udpacktq.ifq_lock);
MUTEX_DESTROY(&ips_icmpacktq.ifq_lock);
MUTEX_DESTROY(&ips_iptq.ifq_lock);
}
if (ips_table != NULL) {
@ -601,6 +630,10 @@ caddr_t data;
isn->is_sti.tqe_next = NULL;
isn->is_sti.tqe_ifq = NULL;
isn->is_sti.tqe_parent = isn;
isn->is_ifp[0] = NULL;
isn->is_ifp[1] = NULL;
isn->is_ifp[2] = NULL;
isn->is_ifp[3] = NULL;
isn->is_sync = NULL;
fr = ips.ips_rule;
@ -710,8 +743,11 @@ int rev;
/*
* Look up all the interface names in the state entry.
*/
for (i = 0; i < 4; i++)
for (i = 0; i < 4; i++) {
if (is->is_ifp[i] != NULL)
continue;
is->is_ifp[i] = fr_resolvenic(is->is_ifname[i], is->is_v);
}
/*
* If we could trust is_hv, then the modulous would not be needed, but
@ -815,7 +851,6 @@ u_int flags;
is = &ips;
bzero((char *)is, sizeof(*is));
is->is_die = 1 + fr_ticks;
is->is_flags = flags & IS_INHERITED;
/*
* Copy and calculate...
@ -842,7 +877,7 @@ u_int flags;
* solicit message to put in the state structure and
* we could use that without a wildcard flag too...
*/
is->is_flags |= SI_W_DADDR;
flags |= SI_W_DADDR;
hv -= is->is_daddr;
} else {
hv += is->is_dst.i6[1];
@ -902,8 +937,10 @@ u_int flags;
is->is_gre.gs_flags = gre->gr_flags;
is->is_gre.gs_ptype = gre->gr_ptype;
is->is_gre.gs_call = gre->gr_call;
hv += is->is_gre.gs_call;
if (GRE_REV(is->is_gre.gs_flags) == 1) {
is->is_call[0] = fin->fin_data[0];
is->is_call[1] = fin->fin_data[1];
}
break;
case IPPROTO_TCP :
@ -958,7 +995,7 @@ u_int flags;
}
if ((tcp->th_flags & TH_OPENING) == TH_SYN)
is->is_flags |= IS_TCPFSM;
flags |= IS_TCPFSM;
else {
is->is_maxdwin = is->is_maxswin * 2;
is->is_dend = ntohl(tcp->th_ack);
@ -993,6 +1030,7 @@ u_int flags;
hv = DOUBLE_HASH(hv);
is->is_hv = hv;
is->is_rule = fr;
is->is_flags = flags & IS_INHERITED;
/*
* Look for identical state.
@ -1025,12 +1063,14 @@ u_int flags;
if (fr->fr_age[0] != 0) {
is->is_tqehead[0] = fr_addtimeoutqueue(&ips_utqe,
fr->fr_age[0]);
is->is_tqehead[1] = is->is_tqehead[0];
is->is_sti.tqe_flags |= TQE_RULEBASED;
}
if (fr->fr_age[0] != 0 && fr->fr_age[1] != fr->fr_age[0])
if (fr->fr_age[1] != 0) {
is->is_tqehead[1] = fr_addtimeoutqueue(&ips_utqe,
fr->fr_age[1]);
is->is_sti.tqe_flags |= TQE_RULEBASED;
}
is->is_tag = fr->fr_logtag;
is->is_ifp[(out << 1) + 1] = fr->fr_ifas[1];
@ -1072,7 +1112,7 @@ u_int flags;
is->is_pkts[3] = 0, is->is_bytes[3] = 0;
if ((fin->fin_flx & FI_IGNORE) == 0) {
is->is_pkts[out] = 1;
is->is_bytes[out] = fin->fin_dlen + fin->fin_hlen;
is->is_bytes[out] = fin->fin_plen;
is->is_flx[out][0] = fin->fin_flx & FI_CMP;
is->is_flx[out][0] &= ~FI_OOW;
}
@ -1599,15 +1639,16 @@ u_32_t cmask;
rev = IP6_NEQ(&is->is_dst, dst);
ifp = fin->fin_ifp;
out = fin->fin_out;
flags = is->is_flags & (SI_WILDA);
flags = is->is_flags;
sp = 0;
dp = 0;
if (tcp != NULL) {
flags = is->is_flags;
sp = tcp->th_sport;
dp = tcp->th_dport;
if (!rev) {
sp = htons(fin->fin_sport);
dp = ntohs(fin->fin_dport);
}
if (!rev) {
if (tcp != NULL) {
if (!(flags & SI_W_SPORT) && (sp != is->is_sport))
rev = 1;
else if (!(flags & SI_W_DPORT) && (dp != is->is_dport))
@ -1635,19 +1676,28 @@ u_32_t cmask;
*/
if (rev == 0) {
if ((IP6_EQ(&is->is_dst, dst) || (flags & SI_W_DADDR)) &&
(IP6_EQ(&is->is_src, src) || (flags & SI_W_SADDR)) &&
(!tcp || ((sp == is->is_sport || flags & SI_W_SPORT) &&
(dp == is->is_dport || flags & SI_W_DPORT)))) {
ret = 1;
(IP6_EQ(&is->is_src, src) || (flags & SI_W_SADDR))) {
if (tcp) {
if ((sp == is->is_sport || flags & SI_W_SPORT)&&
(dp == is->is_dport || flags & SI_W_DPORT))
ret = 1;
} else {
ret = 1;
}
}
} else {
if ((IP6_EQ(&is->is_dst, src) || (flags & SI_W_DADDR)) &&
(IP6_EQ(&is->is_src, dst) || (flags & SI_W_SADDR)) &&
(!tcp || ((sp == is->is_dport || flags & SI_W_DPORT) &&
(dp == is->is_sport || flags & SI_W_SPORT)))) {
ret = 1;
(IP6_EQ(&is->is_src, dst) || (flags & SI_W_SADDR))) {
if (tcp) {
if ((dp == is->is_sport || flags & SI_W_SPORT)&&
(sp == is->is_dport || flags & SI_W_DPORT))
ret = 1;
} else {
ret = 1;
}
}
}
if (ret == 0)
return NULL;
@ -1981,13 +2031,13 @@ fr_info_t *fin;
* compared to the state
*/
backward = IP6_NEQ(&is->is_src, &src);
fin->fin_rev = !backward;
i = (!backward << 1) + fin->fin_out;
oi = (backward << 1) + ofin.fin_out;
if (is->is_icmppkts[i] > is->is_pkts[oi])
continue;
ips_stats.iss_hits++;
is->is_icmppkts[i]++;
is->is_bytes[i] += fin->fin_plen;
return is;
}
}
@ -2036,6 +2086,7 @@ fr_info_t *fin;
* the state
*/
backward = IP6_NEQ(&is->is_src, &src);
fin->fin_rev = !backward;
i = (!backward << 1) + fin->fin_out;
oi = (backward << 1) + ofin.fin_out;
@ -2044,7 +2095,6 @@ fr_info_t *fin;
break;
ips_stats.iss_hits++;
is->is_icmppkts[i]++;
is->is_bytes[i] += fin->fin_plen;
/*
* we deliberately do not touch the timeouts
* for the accompanying state table entry.
@ -2128,7 +2178,6 @@ ipftq_t **ifqp;
u_short dport, sport;
i6addr_t src, dst;
struct icmp *ic;
grehdr_t *gre;
ipftq_t *ifq;
int oow;
@ -2167,7 +2216,6 @@ ipftq_t **ifqp;
{
#ifdef USE_INET6
case IPPROTO_ICMPV6 :
tcp = NULL;
tryagain = 0;
if (v == 6) {
if ((ic->icmp_type == ICMP6_ECHO_REQUEST) ||
@ -2186,12 +2234,10 @@ icmp6again:
if (is != NULL &&
fr_matchicmpqueryreply(v, &is->is_icmp,
ic, fin->fin_rev)) {
if (!(is->is_sti.tqe_flags & TQE_RULEBASED)) {
if (fin->fin_rev)
ifq = &ips_icmpacktq;
else
ifq = &ips_icmptq;
}
if (fin->fin_rev)
ifq = &ips_icmpacktq;
else
ifq = &ips_icmptq;
break;
}
}
@ -2250,12 +2296,10 @@ icmp6again:
if (is != NULL &&
fr_matchicmpqueryreply(v, &is->is_icmp,
ic, fin->fin_rev)) {
if (!(is->is_sti.tqe_flags & TQE_RULEBASED)) {
if (fin->fin_rev)
ifq = &ips_icmpacktq;
else
ifq = &ips_icmptq;
}
if (fin->fin_rev)
ifq = &ips_icmpacktq;
else
ifq = &ips_icmptq;
break;
}
}
@ -2264,27 +2308,6 @@ icmp6again:
}
break;
case IPPROTO_GRE :
gre = fin->fin_dp;
hv += gre->gr_call;
tcp = NULL;
ifqp = NULL;
hv = DOUBLE_HASH(hv);
READ_ENTER(&ipf_state);
for (isp = &ips_table[hv]; ((is = *isp) != NULL); ) {
isp = &is->is_hnext;
if ((is->is_p != IPPROTO_GRE) || (is->is_v != v) ||
(is->is_gre.gs_call != gre->gr_call))
continue;
is = fr_matchsrcdst(fin, is, &src, &dst, NULL, FI_CMP);
if (is != NULL)
break;
}
if (is == NULL) {
RWLOCK_EXIT(&ipf_state);
}
break;
case IPPROTO_TCP :
case IPPROTO_UDP :
ifqp = NULL;
@ -2335,8 +2358,15 @@ retry_tcpudp:
fin->fin_flx |= oow;
break;
#if 0
case IPPROTO_GRE :
gre = fin->fin_dp;
if (GRE_REV(gre->gr_flags) == 1) {
hv += gre->gr_call;
}
/* FALLTHROUGH */
#endif
default :
tcp = NULL;
ifqp = NULL;
hvm = DOUBLE_HASH(hv);
READ_ENTER(&ipf_state);
@ -2345,8 +2375,10 @@ retry_tcpudp:
if ((is->is_p != pr) || (is->is_v != v))
continue;
is = fr_matchsrcdst(fin, is, &src, &dst, NULL, FI_CMP);
if (is != NULL)
if (is != NULL) {
ifq = &ips_iptq;
break;
}
}
if (is == NULL) {
RWLOCK_EXIT(&ipf_state);
@ -2354,6 +2386,9 @@ retry_tcpudp:
break;
}
if ((is != NULL) && ((is->is_sti.tqe_flags & TQE_RULEBASED) != 0) &&
(is->is_tqehead[fin->fin_rev] != NULL))
ifq = is->is_tqehead[fin->fin_rev];
if (ifq != NULL && ifqp != NULL)
*ifqp = ifq;
return is;
@ -2669,8 +2704,6 @@ static void fr_delstate(is, why)
ipstate_t *is;
int why;
{
ipftqent_t *tqe;
ipftq_t *ifq;
ASSERT(rw_read_locked(&ipf_state.ipf_lk) == 0);
@ -2715,21 +2748,11 @@ int why;
/*
* Next, remove it from the timeout queue it is in.
*/
tqe = &is->is_sti;
ifq = tqe->tqe_ifq;
if (ifq != NULL) {
if (tqe->tqe_pnext != NULL) {
*tqe->tqe_pnext = tqe->tqe_next;
if (tqe->tqe_next != NULL)
tqe->tqe_next->tqe_pnext = tqe->tqe_pnext;
else /* we must be the tail anyway */
ifq->ifq_tail = tqe->tqe_pnext;
tqe->tqe_pnext = NULL;
tqe->tqe_ifq = NULL;
}
fr_deletequeueentry(&is->is_sti);
if ((ifq->ifq_flags & IFQF_USER) != 0)
fr_deletetimeoutqueue(ifq);
if (is->is_me != NULL) {
*is->is_me = NULL;
is->is_me = NULL;
}
/*
@ -2740,6 +2763,15 @@ int why;
if (is->is_ref > 0)
return;
if (is->is_tqehead[0] != NULL) {
if (fr_deletetimeoutqueue(is->is_tqehead[0]) == 0)
fr_freetimeoutqueue(is->is_tqehead[0]);
}
if (is->is_tqehead[1] != NULL) {
if (fr_deletetimeoutqueue(is->is_tqehead[1]) == 0)
fr_freetimeoutqueue(is->is_tqehead[1]);
}
#ifdef IPFILTER_SYNC
if (is->is_sync)
ipfsync_del(is->is_sync);
@ -2803,10 +2835,21 @@ void fr_timeoutstate()
fr_delstate(is, ISL_EXPIRE);
}
}
for (ifq = ips_utqe; ifq != NULL; ifq = ifqnext) {
ifqnext = ifq->ifq_next;
if (((ifq->ifq_flags & IFQF_DELETE) != 0) &&
(ifq->ifq_ref == 0)) {
fr_freetimeoutqueue(ifq);
}
}
if (fr_state_doflush) {
(void) fr_state_flush(2, 0);
fr_state_doflush = 0;
}
RWLOCK_EXIT(&ipf_state);
SPL_X(s);
}
@ -3497,9 +3540,9 @@ fr_info_t *fin;
(ic->ici_type - 1 == oic->icmp6_type )) {
ips_stats.iss_hits++;
backward = IP6_NEQ(&is->is_dst, &src);
fin->fin_rev = !backward;
i = (backward << 1) + fin->fin_out;
is->is_pkts[i]++;
is->is_bytes[i] += fin->fin_plen;
is->is_icmppkts[i]++;
return is;
}
}
@ -3547,9 +3590,9 @@ fr_info_t *fin;
if (is != NULL) {
ips_stats.iss_hits++;
backward = IP6_NEQ(&is->is_dst, &src);
fin->fin_rev = !backward;
i = (backward << 1) + fin->fin_out;
is->is_pkts[i]++;
is->is_bytes[i] += fin->fin_plen;
is->is_icmppkts[i]++;
/*
* we deliberately do not touch the timeouts
* for the accompanying state table entry.
@ -3578,6 +3621,7 @@ ipftq_t *tqp;
for (i = IPF_TCP_NSTATES - 1; i >= 0; i--) {
tqp[i].ifq_ttl = 0;
tqp[i].ifq_ref = 1;
tqp[i].ifq_head = NULL;
tqp[i].ifq_tail = &tqp[i].ifq_head;
tqp[i].ifq_next = tqp + i + 1;
@ -3740,12 +3784,17 @@ int rev;
case IPPROTO_TCP :
nifq = ips_tqtqb + is->is_state[rev];
break;
default :
case IPPROTO_UDP :
if (rev == 1)
nifq = &ips_udpacktq;
else
nifq = &ips_udptq;
break;
default :
nifq = &ips_iptq;
break;
}
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: ip_state.h,v 1.2 2005/02/08 07:01:56 martti Exp $ */
/* $NetBSD: ip_state.h,v 1.3 2005/04/03 15:05:30 martti Exp $ */
/*
* Copyright (C) 1995-2001 by Darren Reed.
@ -6,7 +6,7 @@
* See the IPFILTER.LICENCE file for details on licencing.
*
* @(#)ip_state.h 1.3 1/12/96 (C) 1995 Darren Reed
* Id: ip_state.h,v 2.68.2.2 2004/10/31 18:44:39 darrenr Exp
* Id: ip_state.h,v 2.68.2.3 2005/03/03 14:24:11 darrenr Exp
*/
#ifndef _NETINET_IP_STATE_H_
#define _NETINET_IP_STATE_H_
@ -107,6 +107,7 @@ typedef struct ipstate {
#define is_ifpin is_ifp[0]
#define is_ifpout is_ifp[2]
#define is_gre is_ps.is_ug
#define is_call is_gre.gs_call
#define IS_WSPORT SI_W_SPORT /* 0x00100 */
#define IS_WDPORT SI_W_DPORT /* 0x00200 */
@ -227,6 +228,7 @@ extern u_long fr_udptimeout;
extern u_long fr_udpacktimeout;
extern u_long fr_icmptimeout;
extern u_long fr_icmpacktimeout;
extern u_long fr_iptimeout;
extern int fr_statemax;
extern int fr_statesize;
extern int fr_state_lock;

View File

@ -1,4 +1,4 @@
/* $NetBSD: ip_sync.c,v 1.2 2005/02/08 07:01:56 martti Exp $ */
/* $NetBSD: ip_sync.c,v 1.3 2005/04/03 15:05:30 martti Exp $ */
/*
* Copyright (C) 1995-1998 by Darren Reed.
@ -98,7 +98,7 @@ struct file;
/* END OF INCLUDES */
#if !defined(lint)
static const char rcsid[] = "@(#)Id: ip_sync.c,v 2.40.2.2 2004/10/31 18:45:58 darrenr Exp";
static const char rcsid[] = "@(#)Id: ip_sync.c,v 2.40.2.3 2005/02/18 13:06:29 darrenr Exp";
#endif
#define SYNC_STATETABSZ 256
@ -319,7 +319,7 @@ struct uio *uio;
if (sh.sm_magic != SYNHDRMAGIC) {
if (ipf_sync_debug > 2)
printf("uiomove(header) invalud %x\n",
printf("uiomove(header) invalud %s\n",
"magic");
return EINVAL;
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: ipl.h,v 1.3 2005/02/19 21:30:25 martti Exp $ */
/* $NetBSD: ipl.h,v 1.4 2005/04/03 15:05:30 martti Exp $ */
/*
* Copyright (C) 1993-2001, 2003 by Darren Reed.
@ -6,14 +6,14 @@
* See the IPFILTER.LICENCE file for details on licencing.
*
* @(#)ipl.h 1.21 6/5/96
* Id: ipl.h,v 2.52.2.7 2005/02/19 01:33:24 darrenr Exp
* Id: ipl.h,v 2.52.2.9 2005/03/30 14:14:05 darrenr Exp
*/
#ifndef __IPL_H__
#define __IPL_H__
#define IPL_VERSION "IP Filter: v4.1.6"
#define IPL_VERSION "IP Filter: v4.1.8"
#define IPFILTER_VERSION 4010600
#define IPFILTER_VERSION 4010800
#endif