aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDarren Reed <darrenr@FreeBSD.org>1997-02-09 22:50:16 +0000
committerDarren Reed <darrenr@FreeBSD.org>1997-02-09 22:50:16 +0000
commitb4ebec5bf8828aa1cc3f5a1a50faf812b5b6ba48 (patch)
tree93c7db298b1fd70f9e27663b3fd527da063d0008
downloadsrc-b4ebec5bf8828aa1cc3f5a1a50faf812b5b6ba48.tar.gz
src-b4ebec5bf8828aa1cc3f5a1a50faf812b5b6ba48.zip
Import IP Filter v3.1.7 into FreeBSD treevendor/ipfilter/3.1.7
Notes
Notes: svn path=/vendor/ipfilter/dist/; revision=22514 svn path=/vendor/ipfilter/3.1.7/; revision=22516; tag=vendor/ipfilter/3.1.7
-rw-r--r--contrib/ipfilter/BNF64
-rw-r--r--contrib/ipfilter/COMPILE.2.511
-rw-r--r--contrib/ipfilter/FWTK/README16
-rw-r--r--contrib/ipfilter/FWTK/ftp-gw.diff237
-rw-r--r--contrib/ipfilter/FWTK/fwtkp812
-rw-r--r--contrib/ipfilter/HISTORY567
-rw-r--r--contrib/ipfilter/IMPORTANT41
-rw-r--r--contrib/ipfilter/INSTALL.FreeBSD41
-rw-r--r--contrib/ipfilter/INSTALL.NetBSD48
-rw-r--r--contrib/ipfilter/INSTALL.Sol227
-rw-r--r--contrib/ipfilter/INSTALL.SunOS36
-rw-r--r--contrib/ipfilter/INSTALL.xBSD39
-rw-r--r--contrib/ipfilter/LICENCE16
-rw-r--r--contrib/ipfilter/Makefile158
-rw-r--r--contrib/ipfilter/README93
-rwxr-xr-xcontrib/ipfilter/bsdinstall83
-rwxr-xr-xcontrib/ipfilter/buildsunos23
-rw-r--r--contrib/ipfilter/etc/protocols95
-rw-r--r--contrib/ipfilter/etc/services731
-rw-r--r--contrib/ipfilter/fil.c762
-rw-r--r--contrib/ipfilter/fils.c366
-rw-r--r--contrib/ipfilter/inet_addr.c182
-rw-r--r--contrib/ipfilter/ip_compat.h342
-rw-r--r--contrib/ipfilter/ip_fil.c885
-rw-r--r--contrib/ipfilter/ip_fil.h293
-rw-r--r--contrib/ipfilter/ip_frag.c278
-rw-r--r--contrib/ipfilter/ip_frag.h47
-rw-r--r--contrib/ipfilter/ip_nat.c886
-rw-r--r--contrib/ipfilter/ip_nat.h118
-rw-r--r--contrib/ipfilter/ip_sfil.c731
-rw-r--r--contrib/ipfilter/ip_state.c536
-rw-r--r--contrib/ipfilter/ip_state.h86
-rw-r--r--contrib/ipfilter/ipf.c434
-rw-r--r--contrib/ipfilter/ipf.h67
-rw-r--r--contrib/ipfilter/ipft_ef.c148
-rw-r--r--contrib/ipfilter/ipft_hx.c140
-rw-r--r--contrib/ipfilter/ipft_pc.c224
-rw-r--r--contrib/ipfilter/ipft_sn.c206
-rw-r--r--contrib/ipfilter/ipft_td.c184
-rw-r--r--contrib/ipfilter/ipft_tx.c338
-rw-r--r--contrib/ipfilter/ipl.h16
-rw-r--r--contrib/ipfilter/ipl_ldev.c83
-rw-r--r--contrib/ipfilter/ipmon.c582
-rw-r--r--contrib/ipfilter/ipnat.c692
-rw-r--r--contrib/ipfilter/ipsd/Makefile63
-rw-r--r--contrib/ipfilter/ipsd/README32
-rw-r--r--contrib/ipfilter/ipsd/ip_compat.h201
-rw-r--r--contrib/ipfilter/ipsd/ipsd.c297
-rw-r--r--contrib/ipfilter/ipsd/ipsd.h30
-rw-r--r--contrib/ipfilter/ipsd/ipsdr.c315
-rw-r--r--contrib/ipfilter/ipsd/linux.h17
-rw-r--r--contrib/ipfilter/ipsd/sbpf.c195
-rw-r--r--contrib/ipfilter/ipsd/sdlpi.c263
-rw-r--r--contrib/ipfilter/ipsd/slinux.c120
-rw-r--r--contrib/ipfilter/ipsd/snit.c230
-rw-r--r--contrib/ipfilter/ipsend/44arp.c95
-rw-r--r--contrib/ipfilter/ipsend/Crashable20
-rw-r--r--contrib/ipfilter/ipsend/Makefile91
-rw-r--r--contrib/ipfilter/ipsend/arp.c119
-rw-r--r--contrib/ipfilter/ipsend/dlcommon.c1359
-rw-r--r--contrib/ipfilter/ipsend/dltest.h32
-rw-r--r--contrib/ipfilter/ipsend/in_var.h177
-rw-r--r--contrib/ipfilter/ipsend/ip.c346
-rw-r--r--contrib/ipfilter/ipsend/ip_compat.h242
-rw-r--r--contrib/ipfilter/ipsend/ip_var.h123
-rw-r--r--contrib/ipfilter/ipsend/ipresend.c165
-rw-r--r--contrib/ipfilter/ipsend/ipsend.c350
-rw-r--r--contrib/ipfilter/ipsend/ipsopt.c111
-rw-r--r--contrib/ipfilter/ipsend/iptest.c211
-rw-r--r--contrib/ipfilter/ipsend/iptests.c1296
-rw-r--r--contrib/ipfilter/ipsend/larp.c85
-rw-r--r--contrib/ipfilter/ipsend/linux.h17
-rw-r--r--contrib/ipfilter/ipsend/lsock.c261
-rw-r--r--contrib/ipfilter/ipsend/resend.c130
-rw-r--r--contrib/ipfilter/ipsend/sbpf.c136
-rw-r--r--contrib/ipfilter/ipsend/sdlpi.c130
-rw-r--r--contrib/ipfilter/ipsend/slinux.c94
-rw-r--r--contrib/ipfilter/ipsend/snit.c160
-rw-r--r--contrib/ipfilter/ipsend/sock.c370
-rw-r--r--contrib/ipfilter/ipsend/tcpip.h38
-rw-r--r--contrib/ipfilter/ipt.c199
-rw-r--r--contrib/ipfilter/ipt.h16
-rw-r--r--contrib/ipfilter/kmem.c68
-rw-r--r--contrib/ipfilter/kmem.h12
-rw-r--r--contrib/ipfilter/linux.h19
-rw-r--r--contrib/ipfilter/man/Makefile21
-rw-r--r--contrib/ipfilter/man/ipf.1109
-rw-r--r--contrib/ipfilter/man/ipf.4184
-rw-r--r--contrib/ipfilter/man/ipf.5433
-rw-r--r--contrib/ipfilter/man/ipfstat.873
-rw-r--r--contrib/ipfilter/man/ipftest.1127
-rw-r--r--contrib/ipfilter/man/ipl.462
-rw-r--r--contrib/ipfilter/man/ipmon.856
-rw-r--r--contrib/ipfilter/man/ipnat.145
-rw-r--r--contrib/ipfilter/man/ipnat.488
-rw-r--r--contrib/ipfilter/man/ipnat.570
-rw-r--r--contrib/ipfilter/misc.c85
-rw-r--r--contrib/ipfilter/mkfilters65
-rw-r--r--contrib/ipfilter/ml_ipl.c167
-rw-r--r--contrib/ipfilter/mln_ipl.c237
-rw-r--r--contrib/ipfilter/mls_ipl.c174
-rw-r--r--contrib/ipfilter/opt.c134
-rw-r--r--contrib/ipfilter/parse.c1249
-rw-r--r--contrib/ipfilter/pcap.h35
-rw-r--r--contrib/ipfilter/relay.c179
-rw-r--r--contrib/ipfilter/rules/example.14
-rw-r--r--contrib/ipfilter/rules/example.1012
-rw-r--r--contrib/ipfilter/rules/example.1126
-rw-r--r--contrib/ipfilter/rules/example.1217
-rw-r--r--contrib/ipfilter/rules/example.1317
-rw-r--r--contrib/ipfilter/rules/example.24
-rw-r--r--contrib/ipfilter/rules/example.340
-rw-r--r--contrib/ipfilter/rules/example.44
-rw-r--r--contrib/ipfilter/rules/example.525
-rw-r--r--contrib/ipfilter/rules/example.65
-rw-r--r--contrib/ipfilter/rules/example.712
-rw-r--r--contrib/ipfilter/rules/example.810
-rw-r--r--contrib/ipfilter/rules/example.912
-rw-r--r--contrib/ipfilter/rules/example.sr61
-rw-r--r--contrib/ipfilter/rules/nat.eg14
-rw-r--r--contrib/ipfilter/rules/server11
-rw-r--r--contrib/ipfilter/rules/tcpstate13
-rw-r--r--contrib/ipfilter/snoop.h42
-rw-r--r--contrib/ipfilter/solaris.c1018
-rw-r--r--contrib/ipfilter/test/Makefile39
-rw-r--r--contrib/ipfilter/test/dotest26
-rw-r--r--contrib/ipfilter/test/expected/116
-rw-r--r--contrib/ipfilter/test/expected/10108
-rw-r--r--contrib/ipfilter/test/expected/1166
-rw-r--r--contrib/ipfilter/test/expected/1254
-rw-r--r--contrib/ipfilter/test/expected/236
-rw-r--r--contrib/ipfilter/test/expected/340
-rw-r--r--contrib/ipfilter/test/expected/440
-rw-r--r--contrib/ipfilter/test/expected/51344
-rw-r--r--contrib/ipfilter/test/expected/61344
-rw-r--r--contrib/ipfilter/test/expected/754
-rw-r--r--contrib/ipfilter/test/expected/836
-rw-r--r--contrib/ipfilter/test/expected/9108
-rw-r--r--contrib/ipfilter/test/expected/i111
-rw-r--r--contrib/ipfilter/test/expected/i104
-rw-r--r--contrib/ipfilter/test/expected/i114
-rw-r--r--contrib/ipfilter/test/expected/i26
-rw-r--r--contrib/ipfilter/test/expected/i38
-rw-r--r--contrib/ipfilter/test/expected/i47
-rw-r--r--contrib/ipfilter/test/expected/i55
-rw-r--r--contrib/ipfilter/test/expected/i64
-rw-r--r--contrib/ipfilter/test/expected/i73
-rw-r--r--contrib/ipfilter/test/expected/i82
-rw-r--r--contrib/ipfilter/test/expected/i95
-rw-r--r--contrib/ipfilter/test/hextest23
-rw-r--r--contrib/ipfilter/test/input/14
-rw-r--r--contrib/ipfilter/test/input/106
-rw-r--r--contrib/ipfilter/test/input/1111
-rw-r--r--contrib/ipfilter/test/input/1235
-rw-r--r--contrib/ipfilter/test/input/1339
-rw-r--r--contrib/ipfilter/test/input/26
-rw-r--r--contrib/ipfilter/test/input/35
-rw-r--r--contrib/ipfilter/test/input/45
-rw-r--r--contrib/ipfilter/test/input/528
-rw-r--r--contrib/ipfilter/test/input/628
-rw-r--r--contrib/ipfilter/test/input/79
-rw-r--r--contrib/ipfilter/test/input/86
-rw-r--r--contrib/ipfilter/test/input/96
-rw-r--r--contrib/ipfilter/test/itest21
-rw-r--r--contrib/ipfilter/test/regress/14
-rw-r--r--contrib/ipfilter/test/regress/1018
-rw-r--r--contrib/ipfilter/test/regress/116
-rw-r--r--contrib/ipfilter/test/regress/126
-rw-r--r--contrib/ipfilter/test/regress/136
-rw-r--r--contrib/ipfilter/test/regress/26
-rw-r--r--contrib/ipfilter/test/regress/38
-rw-r--r--contrib/ipfilter/test/regress/48
-rw-r--r--contrib/ipfilter/test/regress/548
-rw-r--r--contrib/ipfilter/test/regress/648
-rw-r--r--contrib/ipfilter/test/regress/76
-rw-r--r--contrib/ipfilter/test/regress/86
-rw-r--r--contrib/ipfilter/test/regress/918
-rw-r--r--contrib/ipfilter/test/regress/i111
-rw-r--r--contrib/ipfilter/test/regress/i104
-rw-r--r--contrib/ipfilter/test/regress/i114
-rw-r--r--contrib/ipfilter/test/regress/i26
-rw-r--r--contrib/ipfilter/test/regress/i38
-rw-r--r--contrib/ipfilter/test/regress/i47
-rw-r--r--contrib/ipfilter/test/regress/i55
-rw-r--r--contrib/ipfilter/test/regress/i64
-rw-r--r--contrib/ipfilter/test/regress/i73
-rw-r--r--contrib/ipfilter/test/regress/i82
-rw-r--r--contrib/ipfilter/test/regress/i95
-rw-r--r--contrib/ipfilter/todo19
189 files changed, 28807 insertions, 0 deletions
diff --git a/contrib/ipfilter/BNF b/contrib/ipfilter/BNF
new file mode 100644
index 000000000000..7cb556e1a0a8
--- /dev/null
+++ b/contrib/ipfilter/BNF
@@ -0,0 +1,64 @@
+filter-rule = [ insert ] action in-out [ options ] [ tos ] [ ttl ]
+ [ proto ] [ ip ] .
+
+insert = "@" decnumber .
+action = block | "pass" | log | "count" | call .
+in-out = "in" | "out" .
+options = [ log ] [ "quick" ] [ "on" interface-name [ dup ] [ froute ] ] .
+tos = "tos" decnumber | "tos" hexnumber .
+ttl = "ttl" decnumber .
+proto = "proto" protocol .
+ip = srcdst [ flags ] [ with withopt ] [ icmp ] [ keep ] .
+
+block = "block" [ "return-icmp"[return-code] | "return-rst" ] .
+log = "log" [ "body" ] [ "first" ] [ "or-block" ] .
+call = "call" [ "now" ] function-name .
+dup = "dup-to" interface-name[":"ipaddr] .
+froute = "fastroute" | "to" interface-name .
+protocol = "tcp/udp" | "udp" | "tcp" | "icmp" | decnumber .
+srcdst = "all" | fromto .
+fromto = "from" object "to" object .
+
+object = addr [ port-comp | port-range ] .
+addr = "any" | nummask | host-name [ "mask" ipaddr | "mask" hexnumber ] .
+port-comp = "port" compare port-num .
+port-range = "port" port-num range port-num .
+flags = "flags" flag { flag } [ "/" flag { flag } ] .
+with = "with" | "and" .
+icmp = "icmp-type" icmp-type [ "code" decnumber ] .
+return-code = "("icmp-code")" .
+keep = "keep" "state" | "keep" "frags" .
+
+nummask = host-name [ "/" decnumber ] .
+host-name = ipaddr | hostname | "any" .
+ipaddr = host-num "." host-num "." host-num "." host-num .
+host-num = digit [ digit [ digit ] ] .
+port-num = service-name | decnumber .
+
+withopt = [ "not" | "no" ] opttype [ withopt ] .
+opttype = "ipopts" | "short" | "frag" | "opt" ipopts .
+optname = ipopts [ "," optname ] .
+ipopts = optlist | "sec-class" [ secname ] .
+secname = seclvl [ "," secname ] .
+seclvl = "unclass" | "confid" | "reserv-1" | "reserv-2" | "reserv-3" |
+ "reserv-4" | "secret" | "topsecret" .
+icmp-type = "unreach" | "echo" | "echorep" | "squench" | "redir" |
+ "timex" | "paramprob" | "timest" | "timestrep" | "inforeq" |
+ "inforep" | "maskreq" | "maskrep" | decnumber .
+icmp-code = decumber | "net-unr" | "host-unr" | "proto-unr" | "port-unr" |
+ "needfrag" | "srcfail" | "net-unk" | "host-unk" | "isolate" |
+ "net-prohib" | "host-prohib" | "net-tos" | "host-tos" .
+optlist = "nop" | "rr" | "zsu" | "mtup" | "mtur" | "encode" | "ts" | "tr" |
+ "sec" | "lsrr" | "e-sec" | "cipso" | "satid" | "ssrr" | "addext" |
+ "visa" | "imitd" | "eip" | "finn" .
+
+hexnumber = "0" "x" hexstring .
+hexstring = hexdigit [ hexstring ] .
+decnumber = digit [ decnumber ] .
+
+compare = "=" | "!=" | "<" | ">" | "<=" | ">=" | "eq" | "ne" | "lt" | "gt" |
+ "le" | "ge" .
+range = "<>" | "><" .
+hexdigit = digit | "a" | "b" | "c" | "d" | "e" | "f" .
+digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" .
+flag = "F" | "S" | "R" | "P" | "A" | "U" .
diff --git a/contrib/ipfilter/COMPILE.2.5 b/contrib/ipfilter/COMPILE.2.5
new file mode 100644
index 000000000000..ae550f896e49
--- /dev/null
+++ b/contrib/ipfilter/COMPILE.2.5
@@ -0,0 +1,11 @@
+
+If you get the following error whilst compiling:
+
+In file included from /usr/local/lib/gcc-lib/sparc-sun-solaris2.3/2.6.3/include/sys/user.h:48,
+ from /usr/include/sys/file.h:15,
+ from ../ip_nat.c:15:
+/usr/include/sys/psw.h:19: #error Kernel include of psw.h
+
+Remove (comment out) the line in
+/usr/local/lib/gcc-lib/sparc-sun-solaris2.3/2.6.3include/sys/user.h
+which includes psw.h
diff --git a/contrib/ipfilter/FWTK/README b/contrib/ipfilter/FWTK/README
new file mode 100644
index 000000000000..216d20582036
--- /dev/null
+++ b/contrib/ipfilter/FWTK/README
@@ -0,0 +1,16 @@
+
+There are two patch files in this directory, each allowing for the Firewall
+Toolkit to be used in a transparent proxy configuration.
+
+ftp-gw.diff - A patch written by myself for use only with IP Filter and
+ ftp-gw from the Firewall Toolkit.
+
+fwtkp - A set of patches written by James B. Croall (jcroall@foo.org)
+ for use with both IP Filter and ipfwadm (for Linux) and more
+ of the various FWTK gateway plugins, including:
+ ftp-gw http-gw plug-gw rlogin-gw tn-gw
+
+Both patches when applied to the Firewall toolkit require the same
+configuration for IP Filter.
+
+Darren
diff --git a/contrib/ipfilter/FWTK/ftp-gw.diff b/contrib/ipfilter/FWTK/ftp-gw.diff
new file mode 100644
index 000000000000..075e6eb2fdb8
--- /dev/null
+++ b/contrib/ipfilter/FWTK/ftp-gw.diff
@@ -0,0 +1,237 @@
+*** ftp-gw.c.orig Sat Nov 5 10:30:16 1994
+--- ftp-gw.c Sun Jul 7 12:25:15 1996
+***************
+*** 11,31 ****
+ */
+ static char RcsId[] = "$Header: /devel/CVS/IP-Filter/FWTK/ftp-gw.diff,v 2.0.1.1 1997/01/09 15:14:46 darrenr Exp $";
+
+
+ #include <stdio.h>
+ #include <ctype.h>
+ #include <syslog.h>
+ #include <sys/signal.h>
+ #include <sys/ioctl.h>
+ #include <sys/errno.h>
+- extern int errno;
+- extern char *sys_errlist[];
+ #include <arpa/ftp.h>
+ #include <arpa/telnet.h>
+ #include <sys/time.h>
+ #include <sys/types.h>
+ #include <sys/socket.h>
+ #include <netinet/in.h>
+
+ extern char *rindex();
+ extern char *index();
+--- 11,37 ----
+ */
+ static char RcsId[] = "$Header: /devel/CVS/IP-Filter/FWTK/ftp-gw.diff,v 2.0.1.1 1997/01/09 15:14:46 darrenr Exp $";
+
++ /*
++ * Patches for IP Filter NAT extensions written by Darren Reed, 7/7/96
++ * darrenr@cyber.com.au
++ */
++ static char vIpFilter[] = "v3.1.0";
+
+ #include <stdio.h>
+ #include <ctype.h>
+ #include <syslog.h>
++ #include <unistd.h>
++ #include <fcntl.h>
+ #include <sys/signal.h>
+ #include <sys/ioctl.h>
+ #include <sys/errno.h>
+ #include <arpa/ftp.h>
+ #include <arpa/telnet.h>
+ #include <sys/time.h>
+ #include <sys/types.h>
+ #include <sys/socket.h>
+ #include <netinet/in.h>
++ #include <net/if.h>
+
+ extern char *rindex();
+ extern char *index();
+***************
+*** 36,41 ****
+--- 42,48 ----
+
+ #include "firewall.h"
+
++ #include "ip_nat.h"
+
+ #ifndef BSIZ
+ #define BSIZ 2048
+***************
+*** 83,88 ****
+--- 90,97 ----
+ static int cmd_noop();
+ static int cmd_abor();
+ static int cmd_passthru();
++ static int nat_destination();
++ static int connectdest();
+ static void saveline();
+ static void flushsaved();
+ static void trap_sigurg();
+***************
+*** 317,323 ****
+ if(authallflg)
+ if(say(0,"220-Proxy first requires authentication"))
+ exit(1);
+! sprintf(xuf,"220 %s FTP proxy (Version %s) ready.",huf,FWTK_VERSION_MINOR);
+ if(say(0,xuf))
+ exit(1);
+ }
+--- 326,335 ----
+ if(authallflg)
+ if(say(0,"220-Proxy first requires authentication"))
+ exit(1);
+! sprintf(xuf,"220-%s FTP proxy (Version %s) ready.",huf,FWTK_VERSION_MINOR);
+! if(say(0,xuf))
+! exit(1);
+! sprintf(xuf,"220-%s TIS ftp-gw with IP Filter %s NAT extensions",huf,vIpFilter);
+ if(say(0,xuf))
+ exit(1);
+ }
+***************
+*** 338,343 ****
+--- 350,357 ----
+ exit(1);
+ }
+
++ nat_destination(0);
++
+ /* main loop */
+ while(1) {
+ FD_ZERO(&rdy);
+***************
+*** 608,619 ****
+ static char narg[] = "501 Missing or extra username";
+ static char noad[] = "501 Use user@site to connect via proxy";
+ char buf[1024];
+- char mbuf[512];
+ char *p;
+ char *dest;
+ char *user;
+ int x;
+- int msg_int;
+ short port = FTPPORT;
+
+ /* kludgy but effective. if authorizing everything call auth instead */
+--- 622,631 ----
+***************
+*** 643,648 ****
+--- 655,681 ----
+ return(sayn(0,noad,sizeof(noad)));
+ }
+
++ if((rfd == -1) && (x = connectdest(dest,port)))
++ return x;
++ sprintf(buf,"USER %s",user);
++ if(say(rfd,buf))
++ return(1);
++ x = getresp(rfd,buf,sizeof(buf),1);
++ if(sendsaved(0,x))
++ return(1);
++ return(say(0,buf));
++ }
++
++ static int
++ connectdest(dest,port)
++ char *dest;
++ short port;
++ {
++ char buf[1024];
++ char mbuf[512];
++ int msg_int;
++ int x;
++
+ if(*dest == '\0')
+ dest = "localhost";
+
+***************
+*** 685,691 ****
+ char ebuf[512];
+
+ strcpy(ebuf,buf);
+! sprintf(buf,"521 %s: %s",dest,ebuf);
+ return(say(0,buf));
+ }
+ sprintf(buf,"----GATEWAY CONNECTED TO %s----",dest);
+--- 718,724 ----
+ char ebuf[512];
+
+ strcpy(ebuf,buf);
+! sprintf(buf,"521 %s,%d: %s",dest,ntohs(port),ebuf);
+ return(say(0,buf));
+ }
+ sprintf(buf,"----GATEWAY CONNECTED TO %s----",dest);
+***************
+*** 698,711 ****
+ return(say(0,buf));
+ }
+ saveline(buf);
+!
+! sprintf(buf,"USER %s",user);
+! if(say(rfd,buf))
+! return(1);
+! x = getresp(rfd,buf,sizeof(buf),1);
+! if(sendsaved(0,x))
+! return(1);
+! return(say(0,buf));
+ }
+
+
+--- 731,738 ----
+ return(say(0,buf));
+ }
+ saveline(buf);
+! sendsaved(0,-1);
+! return 0;
+ }
+
+
+***************
+*** 1591,1593 ****
+--- 1618,1659 ----
+ dup(nread);
+ }
+ #endif
++
++
++ static int
++ nat_destination(fd)
++ int fd;
++ {
++ struct sockaddr_in laddr, faddr;
++ struct natlookup natlookup;
++ char *dest;
++ int slen, natfd;
++
++ bzero((char *)&laddr, sizeof(laddr));
++ bzero((char *)&faddr, sizeof(faddr));
++ slen = sizeof(laddr);
++ if(getsockname(fd,(struct sockaddr *)&laddr,&slen) < 0) {
++ perror("getsockname");
++ exit(1);
++ }
++ slen = sizeof(faddr);
++ if(getpeername(fd,(struct sockaddr *)&faddr,&slen) < 0) {
++ perror("getsockname");
++ exit(1);
++ }
++
++ natlookup.nl_inport = laddr.sin_port;
++ natlookup.nl_outport = faddr.sin_port;
++ natlookup.nl_inip = laddr.sin_addr;
++ natlookup.nl_outip = faddr.sin_addr;
++ if((natfd = open("/dev/ipl", O_RDONLY)) < 0) {
++ perror("open");
++ exit(1);
++ }
++ if(ioctl(natfd, SIOCGNATL, &natlookup) == -1) {
++ perror("ioctl");
++ exit(1);
++ }
++ close(natfd);
++ return connectdest(inet_ntoa(natlookup.nl_inip),ntohs(natlookup.nl_inport));
++ }
diff --git a/contrib/ipfilter/FWTK/fwtkp b/contrib/ipfilter/FWTK/fwtkp
new file mode 100644
index 000000000000..8f4819a16f81
--- /dev/null
+++ b/contrib/ipfilter/FWTK/fwtkp
@@ -0,0 +1,812 @@
+diff -c -r ./ftp-gw/ftp-gw.c ../../NEW/fwtk/ftp-gw/ftp-gw.c
+*** ./ftp-gw/ftp-gw.c Fri Sep 6 12:55:05 1996
+--- ../../NEW/fwtk/ftp-gw/ftp-gw.c Wed Oct 9 02:51:35 1996
+***************
+*** 40,47 ****
+
+ extern char *optarg;
+
+! #include "firewall.h"
+
+
+ #ifndef BSIZ
+ #define BSIZ 2048
+--- 40,48 ----
+
+ extern char *optarg;
+
+! char *getdsthost();
+
++ #include "firewall.h"
+
+ #ifndef BSIZ
+ #define BSIZ 2048
+***************
+*** 84,89 ****
+--- 85,92 ----
+ static int cmdcnt = 0;
+ static int timeout = PROXY_TIMEOUT;
+
++ static int do_transparent=0;
++
+
+ static int cmd_user();
+ static int cmd_authorize();
+***************
+*** 98,103 ****
+--- 101,107 ----
+ static void saveline();
+ static void flushsaved();
+ static void trap_sigurg();
++ static int connectdest();
+
+ #define OP_CONN 001 /* only valid if connected */
+ #define OP_WCON 002 /* writethrough if connected */
+***************
+*** 170,175 ****
+--- 174,180 ----
+ char xuf[1024];
+ char huf[128];
+ char *passuser = (char *)0; /* passed user as av */
++ char *psychic, *hotline;
+
+ #ifndef LOG_DAEMON
+ openlog("ftp-gw",LOG_PID);
+***************
+*** 314,319 ****
+--- 319,326 ----
+ } else
+ timeout = 60*60;
+
++ psychic=getdsthost(0,NULL);
++ if(psychic) { do_transparent++; }
+
+ /* display a welcome file or message */
+ if(passuser == (char *)0) {
+***************
+*** 322,327 ****
+--- 329,340 ----
+ syslog(LLEV,"fwtkcfgerr: welcome-msg must have one parameter, line %d",cf->ln);
+ exit(1);
+ }
++ if(do_transparent) {
++ if(sayfile2(0,cf->argv[0],220)) {
++ syslog(LLEV,"fwtksyserr: cannot display welcome %s: %m",cf->argv[0]);
++ exit(1);
++ }
++ } else
+ if(sayfile(0,cf->argv[0],220)) {
+ syslog(LLEV,"fwtksyserr: cannot display welcome %s: %m",cf->argv[0]);
+ exit(1);
+***************
+*** 332,338 ****
+ if(authallflg)
+ if(say(0,"220-Proxy first requires authentication"))
+ exit(1);
+! sprintf(xuf,"220 %s FTP proxy (Version %s) ready.",huf,FWTK_VERSION_MINOR);
+ if(say(0,xuf))
+ exit(1);
+ }
+--- 345,357 ----
+ if(authallflg)
+ if(say(0,"220-Proxy first requires authentication"))
+ exit(1);
+! /* foo */
+! if(do_transparent)
+! sprintf(xuf,"220-%s FTP proxy (Version %s) ready.",huf,FWTK_VERSION_MINOR);
+! else
+! sprintf(xuf,"220 %s FTP Proxy (Version %s) ready.",huf,FWTK_VERSION_MINOR);
+! /* foo */
+!
+ if(say(0,xuf))
+ exit(1);
+ }
+***************
+*** 353,358 ****
+--- 372,381 ----
+ exit(1);
+ }
+
++ if(do_transparent) {
++ connectdest(psychic,21);
++ }
++
+ /* main loop */
+ while(1) {
+ FD_ZERO(&rdy);
+***************
+*** 676,681 ****
+--- 699,713 ----
+ return(sayn(0,noad,sizeof(noad)-1));
+ }
+
++ if(do_transparent) {
++ if((rfd==(-1)) && (x=connectdest(dest,port))) return x;
++ sprintf(buf,"USER %s",user);
++ if(say(rfd,buf)) return(1);
++ x=getresp(rfd,buf,sizeof(buf),1);
++ if(sendsaved(0,x)) return(1);
++ return(say(0,buf));
++ }
++
+ if(*dest == '\0')
+ dest = "localhost";
+
+***************
+*** 701,708 ****
+ if(msg_int == 1) {
+ sprintf(mbuf,"Permission denied for user %s to connect to %s",authuser,dest);
+ syslog(LLEV,"deny host=%s/%s connect to %s user=%s",rladdr,riaddr,dest,authuser);
+! say(0,mbuf);
+! return(1);
+ } else {
+ if(msg_int == -1) {
+ sprintf(mbuf,"No match in netperm-table for %s to ftp to %s",authuser,dest);
+--- 733,740 ----
+ if(msg_int == 1) {
+ sprintf(mbuf,"Permission denied for user %s to connect to %s",authuser,dest);
+ syslog(LLEV,"deny host=%s/%s connect to %s user=%s",rladdr,riaddr,dest,authuser);
+! say(0,mbuf);
+! return(1);
+ } else {
+ if(msg_int == -1) {
+ sprintf(mbuf,"No match in netperm-table for %s to ftp to %s",authuser,dest);
+***************
+*** 717,723 ****
+ char ebuf[512];
+
+ strcpy(ebuf,buf);
+! sprintf(buf,"521 %s: %s",dest,ebuf);
+ rfd = -1;
+ return(say(0,buf));
+ }
+--- 749,759 ----
+ char ebuf[512];
+
+ strcpy(ebuf,buf);
+! if(do_transparent) {
+! sprintf(buf,"521 %s,%d: %s",dest,ntohs(port),ebuf);
+! } else {
+! sprintf(buf,"521 %s: %s",dest,ebuf);
+! }
+ rfd = -1;
+ return(say(0,buf));
+ }
+***************
+*** 732,737 ****
+--- 768,778 ----
+ }
+ saveline(buf);
+
++ /* if(do_transparent) {
++ sendsaved(0,-1);
++ return(0);
++ } /* EEEk. I can't remember what this does. */
++
+ sprintf(buf,"USER %s",user);
+ if(say(rfd,buf))
+ return(1);
+***************
+*** 744,749 ****
+--- 785,860 ----
+ return 0;
+ }
+
++ static int connectdest(dest, port)
++ char *dest;
++ short port;
++ {
++ char buf[1024], mbuf[512];
++ int msg_int, x;
++
++ if(*dest == '\0')
++ dest = "localhost";
++
++ if(validests != (char **)0) {
++ char **xp;
++ int x;
++
++ for(xp = validests; *xp != (char *)0; xp++) {
++ if(**xp == '!' && hostmatch(*xp + 1,dest)) {
++ return(baddest(0,dest));
++ } else {
++ if(hostmatch(*xp,dest))
++ break;
++ }
++ }
++ if(*xp == (char *)0)
++ return(baddest(0,dest));
++ }
++
++ /* Extended permissions processing goes in here for destination */
++ if(extendperm) {
++ msg_int = auth_perm(confp, authuser, "ftp-gw", dest,(char *)0);
++ if(msg_int == 1) {
++ sprintf(mbuf,"Permission denied for user %s to connect to %s",authuser,dest);
++ syslog(LLEV,"deny host=%s/%s connect to %s user=%s",rladdr,riaddr,dest,authuser);
++ say(0,mbuf);
++ return(1);
++ } else {
++ if(msg_int == -1) {
++ sprintf(mbuf,"No match in netperm-table for %s to ftp to %s",authuser,dest);
++ say(0,mbuf);
++ return(1);
++ }
++ }
++ }
++
++ syslog(LLEV,"permit host=%s/%s connect to %s",rladdr,riaddr,dest);
++
++ if((rfd = conn_server(dest,port,0,buf)) < 0) {
++ char ebuf[512];
++
++ strcpy(ebuf,buf);
++ sprintf(buf,"521 %s: %s",dest,ebuf);
++ rfd = -1;
++ return(say(0,buf));
++ }
++ if(!do_transparent) {
++ sprintf(buf,"----GATEWAY CONNECTED TO %s----",dest);
++ saveline(buf);
++ }
++
++ /* we are now connected and need to try the autologin thing */
++ x = getresp(rfd,buf,sizeof(buf),1);
++ if(x / 100 != COMPLETE) {
++ sendsaved(0,-1);
++ return(say(0,buf));
++ }
++ saveline(buf);
++
++ sendsaved(0,-1);
++ return 0;
++ }
++
+
+
+ static int
+***************
+*** 1053,1058 ****
+--- 1164,1171 ----
+ static char nprn[] = "500 cannot get peername";
+ char buf[512];
+
++ /* syslog(LLEV,"DEBUG: port cmd"); */
++
+ if(ac < 2)
+ return(sayn(0,narg,sizeof(narg)-1));
+
+***************
+*** 1119,1124 ****
+--- 1232,1238 ----
+ #define UC(c) (((int)c) & 0xff)
+ sprintf(buf,"PORT %d,%d,%d,%d,%d,%d\r\n",UC(k[0]),UC(k[1]),UC(k[2]),
+ UC(k[3]),UC(l[0]),UC(l[1]));
++ /* syslog(LLEV,"DEBUG: %s",buf); */
+ s = strlen(buf);
+ if (write(rfd, buf, s) != s)
+ return 1;
+***************
+*** 1330,1335 ****
+--- 1444,1450 ----
+ callback()
+ {
+ /* if we haven't gotten a valid PORT scrub the connection */
++ /* syslog(LLEV,"DEBUG: callback()."); */
+ if((outgoing = accept(boundport,(struct sockaddr *)0,(int *)0)) < 0 || clntport.sin_port == 0)
+ goto bomb;
+ if(pasvport != -1) { /* incoming handled by PASVcallback */
+***************
+*** 1796,1801 ****
+--- 1911,1960 ----
+ }
+ return(0);
+ }
++
++ /* ok, so i'm in a hurry. english paper due RSN. */
++ sayfile2(fd,fn,code)
++ int fd;
++ char *fn;
++ int code;
++ {
++ FILE *f;
++ char buf[BUFSIZ];
++ char yuf[BUFSIZ];
++ char *c;
++ int x;
++ int saidsomething = 0;
++
++ if((f = fopen(fn,"r")) == (FILE *)0)
++ return(1);
++ while(fgets(buf,sizeof(buf),f) != (char *)0) {
++ if((c = index(buf,'\n')) != (char *)0)
++ *c = '\0';
++ x = fgetc(f);
++ if(feof(f))
++ sprintf(yuf,"%3.3d-%s",code,buf);
++ else {
++ sprintf(yuf,"%3.3d-%s",code,buf);
++ ungetc(x,f);
++ }
++ if(say(fd,yuf)) {
++ fclose(f);
++ return(1);
++ }
++ saidsomething++;
++ }
++ fclose(f);
++ if (!saidsomething) {
++ syslog(LLEV,"fwtkcfgerr: sayfile for %d is empty",code);
++ sprintf(yuf, "%3.3d The file to display is empty",code);
++ if(say(fd,yuf)) {
++ fclose(f);
++ return(1);
++ }
++ }
++ return(0);
++ }
++
+
+
+ porttoaddr(s,a)
+diff -c -r ./http-gw/http-gw.c ../../NEW/fwtk/http-gw/http-gw.c
+*** ./http-gw/http-gw.c Mon Sep 9 14:40:53 1996
+--- ../../NEW/fwtk/http-gw/http-gw.c Wed Oct 9 02:51:57 1996
+***************
+*** 27,32 ****
+--- 27,37 ----
+ static char http_buffer[8192];
+ static char reason[8192];
+ static int checkBrowserType = 1;
++ /* foo */
++ static int do_transparent=0;
++ /* foo */
++
++ char *getdsthost();
+
+ static void do_logging()
+ { char *proto = "GOPHER";
+***************
+*** 422,427 ****
+--- 427,443 ----
+ /*(NOT A SPECIAL FORM)*/
+
+ if((rem_type & TYPE_LOCAL)== 0){
++ /* foo */
++ char *psychic=getdsthost(sockfd,&def_port);
++ if(psychic) {
++ if(strlen(psychic)<=MAXHOSTNAMELEN) {
++ do_transparent++;
++ strncpy(def_httpd,psychic,strlen(psychic));
++ strncpy(def_server,psychic,strlen(psychic));
++ }
++ }
++
++ /* foo */
+ /* See if it can be forwarded */
+
+ if( can_forward(buf)){
+***************
+*** 1513,1519 ****
+ parse_vec[0],
+ parse_vec[1],
+ ourname, ourport);
+! }else{
+ sprintf(new_reply,"%s\tgopher://%s:%s/%c%s\t%s\t%u",
+ parse_vec[0], parse_vec[2],
+ parse_vec[3], chk_type_ch,
+--- 1529,1541 ----
+ parse_vec[0],
+ parse_vec[1],
+ ourname, ourport);
+! }
+! /* FOO */
+! else if(do_transparent) {
+! sprintf(new_reply,"%s\t%s\t%s\t%s",parse_vec[0],parse_vec[1],parse_vec[2],parse_vec[3]);
+! }
+! /* FOO */
+! else{
+ sprintf(new_reply,"%s\tgopher://%s:%s/%c%s\t%s\t%u",
+ parse_vec[0], parse_vec[2],
+ parse_vec[3], chk_type_ch,
+diff -c -r ./lib/hnam.c ../../NEW/fwtk/lib/hnam.c
+*** ./lib/hnam.c Fri Nov 4 18:30:19 1994
+--- ../../NEW/fwtk/lib/hnam.c Wed Oct 9 02:34:13 1996
+***************
+*** 22,27 ****
+--- 22,31 ----
+
+
+ #include "firewall.h"
++ #ifdef __FreeBSD__
++ #include <net/if.h>
++ #include "ip_nat.h"
++ #endif /* __FreeBSD__ */
+
+
+ char *
+***************
+*** 44,47 ****
+--- 48,115 ----
+
+ bcopy(hp->h_addr,&sin.sin_addr,hp->h_length);
+ return(inet_ntoa(sin.sin_addr));
++ }
++
++ char *getdsthost(fd, ptr)
++ int fd;
++ int *ptr;
++ {
++ struct sockaddr_in sin;
++ struct hostent *hp;
++ int sl=sizeof(struct sockaddr_in), err=0, local_h=0, i=0;
++ char buf[255], hostbuf[255];
++ #ifdef __FreeBSD__
++ struct sockaddr_in rsin;
++ struct natlookup natlookup;
++ #endif
++
++ #ifdef linux
++ /* This should also work for UDP. Unfortunately, it doesn't.
++ Maybe when the Linux UDP proxy code gets a little cleaner.
++ */
++ if(!(err=getsockname(0,&sin,&sl))) {
++ if(ptr) *ptr=ntohs(sin.sin_port);
++ sprintf(buf,"%s",inet_ntoa(sin.sin_addr));
++ gethostname(hostbuf,254);
++ hp=gethostbyname(hostbuf);
++ while(hp->h_addr_list[i]) {
++ bzero(&sin,&sl);
++ memcpy(&sin.sin_addr,hp->h_addr_list[i++],sizeof(hp->h_addr_list[i++]));
++ if(!strcmp(buf,inet_ntoa(sin.sin_addr))) local_h++;
++ }
++ if(local_h) { /* syslog(LLEV,"DEBUG: hnam.c: non-transparent."); */ return(NULL); }
++ else { return(buf); }
++ }
++ #endif
++
++ #ifdef __FreeBSD__
++ /* The basis for this block of code is Darren Reed's
++ patches to the TIS ftwk's ftp-gw.
++ */
++ bzero((char*)&sin,sizeof(sin));
++ bzero((char*)&rsin,sizeof(rsin));
++ if(getsockname(fd,(struct sockaddr*)&sin,&sl)<0) {
++ return NULL;
++ }
++ sl=sizeof(rsin);
++ if(getpeername(fd,(struct sockaddr*)&rsin,&sl)<0) {
++ return NULL;
++ }
++ natlookup.nl_inport=sin.sin_port;
++ natlookup.nl_outport=rsin.sin_port;
++ natlookup.nl_inip=sin.sin_addr;
++ natlookup.nl_outip=rsin.sin_addr;
++ if((natfd=open("/dev/ipl",O_RDONLY))<0) {
++ return(NULL);
++ }
++ if(ioctl(natfd,SIOCGNATL,&natlookup)==(-1)) {
++ return(NULL);
++ }
++ close(natfd);
++ if(ptr) *ptr=ntohs(natlookup.nl_inport);
++ sprintf(buf,"%s",inet_ntoa(natlookup.nl_inip));
++ #endif
++
++ /* No transparent proxy support */
++ return(NULL);
+ }
+Only in ./lib: hnam.c.orig
+diff -c -r ./plug-gw/plug-gw.c ../../NEW/fwtk/plug-gw/plug-gw.c
+*** ./plug-gw/plug-gw.c Thu Sep 5 15:36:33 1996
+--- ../../NEW/fwtk/plug-gw/plug-gw.c Wed Oct 9 02:46:48 1996
+***************
+*** 39,44 ****
+--- 39,48 ----
+ static char **validdests = (char **)0;
+ static Cfg *confp;
+
++ int do_transparent=0;
++
++ char *getdsthost();
++
+ main(ac,av)
+ int ac;
+ char *av[];
+***************
+*** 193,201 ****
+--- 197,213 ----
+ char *ptr;
+ int state = 0;
+ int ssl_plug = 0;
++ int pport=0;
+
+ struct timeval timo;
+
++ /* Transparent plug-gw is probably a bad idea, but hey .. */
++ dhost=getdsthost(0,&pport);
++ if(dhost) {
++ do_transparent++;
++ portid=pport;
++ }
++
+ if(c->flags & PERM_DENY) {
+ if (p == -1)
+ syslog(LLEV,"deny host=%s/%s port=any",rhost,raddr);
+***************
+*** 215,221 ****
+ syslog(LLEV,"fwtkcfgerr: -plug-to takes an argument, line %d",c->ln);
+ exit (1);
+ }
+! dhost = av[x];
+ continue;
+ }
+
+--- 227,234 ----
+ syslog(LLEV,"fwtkcfgerr: -plug-to takes an argument, line %d",c->ln);
+ exit (1);
+ }
+! if(!dhost) dhost = av[x];
+! /* syslog(LLEV,"DEBUG: dhost now is [%s]",dhost); */
+ continue;
+ }
+
+diff -c -r ./rlogin-gw/rlogin-gw.c ../../NEW/fwtk/rlogin-gw/rlogin-gw.c
+*** ./rlogin-gw/rlogin-gw.c Fri Sep 6 12:56:33 1996
+--- ../../NEW/fwtk/rlogin-gw/rlogin-gw.c Wed Oct 9 02:49:04 1996
+***************
+*** 39,45 ****
+--- 39,47 ----
+
+
+ extern char *maphostname();
++ char *getdsthost();
+
++ int do_transparent=0;
+
+ static int cmd_quit();
+ static int cmd_help();
+***************
+*** 120,125 ****
+--- 122,130 ----
+ static char *tokav[56];
+ int tokac;
+ struct timeval timo;
++ /* foo */
++ char *psychic;
++ /* foo */
+
+ #ifndef LOG_NDELAY
+ openlog("rlogin-gw",LOG_PID);
+***************
+*** 185,191 ****
+ xforwarder = cf->argv[0];
+ }
+
+!
+
+ if((cf = cfg_get("directory",confp)) != (Cfg *)0) {
+ if(cf->argc != 1) {
+--- 190,203 ----
+ xforwarder = cf->argv[0];
+ }
+
+! /* foo */
+! psychic=getdsthost(0,NULL);
+! if(psychic) {
+! do_transparent++;
+! strncpy(dest,psychic,511);
+! dest[511]='\0';
+! }
+! /* foo */
+
+ if((cf = cfg_get("directory",confp)) != (Cfg *)0) {
+ if(cf->argc != 1) {
+***************
+*** 260,269 ****
+ }
+
+ /* if present a host name, chop and save username and hostname */
+! dest[0] = '\0';
+ if((p = index(rusername,'@')) != (char *)0) {
+ char *namp;
+
+ *p++ = '\0';
+ if(*p == '\0')
+ p = "localhost";
+--- 272,282 ----
+ }
+
+ /* if present a host name, chop and save username and hostname */
+! /* dest[0] = '\0'; */
+ if((p = index(rusername,'@')) != (char *)0) {
+ char *namp;
+
++ dest[0] = '\0';
+ *p++ = '\0';
+ if(*p == '\0')
+ p = "localhost";
+***************
+*** 293,300 ****
+--- 306,326 ----
+ goto leave;
+ }
+
++ /* syslog(LLEV,"DEBUG: Uh-oh, $dest = %s\n",dest); */
++
+ if(dest[0] != '\0') {
+ /* Setup connection directly to remote machine */
++ if((cf = cfg_get("welcome-msg",confp)) != (Cfg *)0) {
++ if(cf->argc != 1) {
++ syslog(LLEV,"fwtkcfgerr: welcome-msg must have one parameter, line %d",cf->ln);
++ exit(1);
++ }
++ if(sayfile(0,cf->argv[0])) {
++ syslog(LLEV,"fwtksyserr: cannot display welcome %s: %m",cf->argv[0]);
++ exit(1);
++ }
++ }
++ /* Does this cmd_connect thing feel like a kludge or what? */
+ sprintf(buf,"connect %.1000s",dest);
+ tokac = enargv(buf, tokav, 56, tokbuf, sizeof(tokbuf));
+ if (cmd_connect(tokac, tokav, buf) != 2)
+***************
+*** 526,539 ****
+ char ebuf[512];
+
+ syslog(LLEV,"permit host=%s/%s connect to %s",rhost,raddr,namp);
+ if(strlen(namp) > 20)
+ namp[20] = '\0';
+ if(rusername[0] != '\0')
+ sprintf(ebuf,"Trying %s@%s...",rusername,namp);
+ else
+ sprintf(ebuf,"Trying %s...",namp);
+! if(say(0,ebuf))
+! return(1);
+ } else
+ syslog(LLEV,"permit host=%s/%s connect to %s",rhost,raddr,av[1]);
+ if((serfd = conn_server(av[1],RLOGINPORT,1,buf)) < 0) {
+--- 552,567 ----
+ char ebuf[512];
+
+ syslog(LLEV,"permit host=%s/%s connect to %s",rhost,raddr,namp);
++ if(!do_transparent) {
+ if(strlen(namp) > 20)
+ namp[20] = '\0';
+ if(rusername[0] != '\0')
+ sprintf(ebuf,"Trying %s@%s...",rusername,namp);
+ else
+ sprintf(ebuf,"Trying %s...",namp);
+! if(say(0,ebuf))
+! return(1);
+! }
+ } else
+ syslog(LLEV,"permit host=%s/%s connect to %s",rhost,raddr,av[1]);
+ if((serfd = conn_server(av[1],RLOGINPORT,1,buf)) < 0) {
+diff -c -r ./tn-gw/tn-gw.c ../../NEW/fwtk/tn-gw/tn-gw.c
+*** ./tn-gw/tn-gw.c Fri Sep 6 12:55:48 1996
+--- ../../NEW/fwtk/tn-gw/tn-gw.c Wed Oct 9 02:50:17 1996
+***************
+*** 87,92 ****
+--- 87,94 ----
+ static int cmd_xforward();
+ static int cmd_timeout();
+
++ char *getdsthost();
++
+ static int tn3270 = 1; /* don't do tn3270 stuff */
+ static int doX;
+
+***************
+*** 97,102 ****
+--- 99,106 ----
+ static int timeout = PROXY_TIMEOUT;
+ static char timed_out_msg[] = "\r\nConnection closed due to inactivity";
+
++ int do_transparent=0;
++
+ typedef struct {
+ char *name;
+ char *hmsg;
+***************
+*** 140,145 ****
+--- 144,151 ----
+ char tokbuf[BSIZ];
+ char *tokav[56];
+ int tokac;
++ int port;
++ char *psychic;
+
+ #ifndef LOG_DAEMON
+ openlog("tn-gw",LOG_PID);
+***************
+*** 308,313 ****
+--- 314,346 ----
+ }
+ }
+
++ psychic=getdsthost(0,&port);
++ if(psychic) {
++ if((strlen(psychic) + 10) < 510) {
++ do_transparent++;
++ if(port)
++ sprintf(dest,"%s:%d",psychic,port);
++ else
++ sprintf(dest,"%s",psychic);
++
++
++ if(!welcomedone)
++ if((cf = cfg_get("welcome-msg",confp)) != (Cfg *)0) {
++ if(cf->argc != 1) {
++ syslog(LLEV,"fwtkcfgerr: welcome-msg must have one parameter, line %d",cf->ln);
++ exit(1);
++ }
++ if(sayfile(0,cf->argv[0])) {
++ syslog(LLEV,"fwtksyserr: cannot display welcome %s:%m",cf->argv[0]);
++ exit(1);
++ }
++ welcomedone = 1;
++ }
++
++
++ }
++ }
++
+ while (argc > 1) {
+ argc--;
+ argv++;
+***************
+*** 864,877 ****
+ }
+ }
+
+-
+ if((namp = maphostname(av[1])) != (char *)0) {
+ char ebuf[512];
+
+ syslog(LLEV,"permit host=%s/%s destination=%s",rladdr,riaddr,namp);
+! sprintf(ebuf,"Trying %s port %d...",namp,port);
+! if(say(0,ebuf))
+! return(1);
+ } else
+ syslog(LLEV,"permit host=%s/%s destination=%s",rladdr,riaddr,av[1]);
+
+--- 897,911 ----
+ }
+ }
+
+ if((namp = maphostname(av[1])) != (char *)0) {
+ char ebuf[512];
+
+ syslog(LLEV,"permit host=%s/%s destination=%s",rladdr,riaddr,namp);
+! if(!do_transparent) {
+! sprintf(ebuf,"Trying %s port %d...",namp,port);
+! if(say(0,ebuf))
+! return(1);
+! }
+ } else
+ syslog(LLEV,"permit host=%s/%s destination=%s",rladdr,riaddr,av[1]);
+
+***************
+*** 903,910 ****
+
+ syslog(LLEV,"connected host=%s/%s destination=%s",rladdr,riaddr,av[1]);
+ strncpy(dest,av[1], 511);
+! sprintf(buf, "Connected to %s.", dest);
+! say(0, buf);
+ return(2);
+ }
+
+--- 937,946 ----
+
+ syslog(LLEV,"connected host=%s/%s destination=%s",rladdr,riaddr,av[1]);
+ strncpy(dest,av[1], 511);
+! if(!do_transparent) {
+! sprintf(buf, "Connected to %s.", dest);
+! say(0, buf);
+! }
+ return(2);
+ }
+
+
+
diff --git a/contrib/ipfilter/HISTORY b/contrib/ipfilter/HISTORY
new file mode 100644
index 000000000000..7cd91069beb4
--- /dev/null
+++ b/contrib/ipfilter/HISTORY
@@ -0,0 +1,567 @@
+#
+# NOTE: Quite a few patches and suggestions come from other sources, to whom
+# I'm greatly indebted, even if no names are mentioned.
+#
+# Thanks to Craig Bishop of connect.com.au and Sun Microsystems for the
+# loan of a machine to work on a Solaris 2.x port of this software.
+#
+3.1.7 8/2/97 - Released
+
+Macros used for ntohs/htons supplied with gcc don't always work very well
+when the assignment is the same variable being converted.
+
+Filter matching doesn't not match rule which checks tcp flags on packets
+which are fragments - David Wilson
+
+3.1.7beta 30/1/97 - Released
+
+Fix up NAT bugs introduced in last major change (now tested), including
+nat_delete(), nat_lookupredir(), checksum changes, etc.
+
+3.1.7alpha 30/1/97 - Released
+
+Many changes to NAT code, including contributions from Laurent Joncheray
+<lpj@ans.net>
+
+Use "NO_SLEEP" when allocating memory under SunOS.
+
+Make kernel printf's nicer for BSD/SunOS4
+
+Always do a checksum for packets being filtered going out and being
+processed by fastroute.
+
+Leave kernel to play with cdevsw on *BSD systems with LKM's.
+
+ipnat.1 man page fixes.
+
+3.1.6 21/1/97 - Released
+
+Allow NAT to work on BSD systems in conjunction with "pass .. to ifname"
+
+Memory leak introduced in 3.1.3 in NAT lists, clearing of NAT table tried
+to free memory twice.
+
+NAT recalculates IP header checksum based on difference between IP#'s and
+port numbers - should be just IP#'s (Solaris2 only)
+
+3.1.5 13/1/97 - Released
+
+fixed setting of NAT timeouts and use different timeouts for concurrent
+TCP sessions using the same IP# mapping (when port mapping isn't used)
+
+multiple loading/unloading of LKM's doesn't clean up cdevsw properly for
+*BSD systems.
+
+3.1.4 10/1/97 - Released
+
+add command line options -C and -F to ipnat to flush NAT list and table
+
+ipnat -l loops on output - Neil Readwin (nreadwin@nysales.micrognosis.com)
+
+NetBSD/FreeBSD kernel malloc changes - Daniel Carosone
+
+3.1.3 10/1/97 - Released
+
+NAT chains not constructed correctly in hash tables - Antony Y.R Lu
+(antony@hawk.ee.ncku.edu.tw)
+
+Updated INSTALL.NetBSD, INSTALL.FreeBSD and INSTALL.Sol2
+
+man page update (ipf.5) from Daniel Carosone (dan@geek.com.au)
+
+ICMP header checksum update now included in NAT.
+
+Solaris2 needs to modify IP header checksums in ip_natin and ip_natout.
+
+3.1.2 4/12/96 - Released
+
+ipmon doesn't use syslog all the time when given -s option
+
+fixed mclput panic in ip_input.c and replace ntohs() with NTOHS() macro
+
+check the results of hostname resolution in ipnat
+
+"make *install" fixed for subdirectories.
+
+problems with "ARCH:=" and gnu make resolved
+
+parser reports an error for lines with whitespaces only rather than skipping
+them. D.Carosone@abm.com.au (Daniel Carosone)
+
+patches for integration into NetBSD-current (post 1.2).
+
+add an option to allow non-IP packets going up/down the stream on Solaris2
+to be dropped. John Bass.
+
+3.1.2beta 21/11/96 - Released
+
+make ipsend compile on Linux 2.0.24
+
+changes to TCP kept state algorithm, making it watch state on TCP
+connections in both directions. Also use the same algorithm for NAT TCP.
+
+-Wall cleanup - Bernd Ernesti
+
+added "or-block" for "pass .. log or-block" after a suggestion from
+David Oppenheim (davido@optimation.com.au)
+
+added subdirectories for building IP Filter in SunOS5/BSD for different
+cpu architecures
+
+Solaris2 fixes to logging and pre-filtering packet processing - 3.1.1p2
+
+mbuf logging not using mtod(), remove iplbusy - 3.1.1p1 1/11/96
+
+3.1.1 28/10/96 - Released
+
+Installation script fixes and deinstall scripts for IP Filter on:
+SunOS4/FreeBSD/NetBSD
+
+Man page fixes - Paul Dubois (dubois@primate.wisc.edu)
+
+Fix use of SOLARIS macro in ipmon, rewrote ipllog() (again!)
+
+parsing isn't completely case insensitive - David Wilson
+(davidw@optimation.com.au)
+
+Release ipl_mutex across uiomove() calls
+
+print entire rule entries out for "ipf -z" when zero'ing per-rule stats.
+
+ipfstat returns same output for "hits" in "ipfstat -aio" - Terletsky Slavik
+(ts@polynet.lviv.ua)
+
+New algorithm for setting timeouts for TCP connection (more closely follow
+TCP FSM) - Pradeep Krishnan (pkrishna@netcom.com)
+
+Track both window sizes for TCP connections through "keep state".
+
+Solaris2 doesn't like _KERNEL defined in stdargs.h - Jos van Wezel
+(wezel@bio.vu.nl)
+
+3.1.1-beta2 6/10/96 - Released
+
+Solaris2 fastroute/dup-to/to now works
+
+ipmon `record' reading rewritten
+
+Added post-NetBSD1.2 packet filter patches - Mathew Green (mrg@eterna.com.au)
+
+Attempt to use in_proto.c.diff, not "..diffs" for SunOS4 - David Wilson
+(davidw@optimation.com.au)
+
+Michael Ryan (mike@NetworX.ie) reports the following:
+* The Trumpet WinSock under Windows always sends its SYN packet with an ACK
+ value of 1, unlike any other implementation I've seen, which would set it
+ to zero. The "keep state" feature of IP Filter doesn't work when receiving
+ non-zero ACK values on new connection requests.
+* */Makefile install rule doesn't install all the binaries/man pages
+* Make ipnat use "tcp/udp" instead of "tcpudp"
+* Print out "tcp/udp" properly
+* ipnat "portmap tcp" matches "portmap udp" when adding/removing
+* NAT dest. ip# increased by one on mask of 0xffffffff when it shouldn't
+
+3.1.1-beta 1/9/96 - Released
+
+add better detection of TCP connections closing to TCP state monitoring.
+
+fr_addstate() not called correctly for fragments. "keep state" and
+"keep frag" code don't work together 100% - Songqing Cai
+(songqing_cai@sterling.com)
+
+call to fr_addstate() incorrect for adding state in combination with keeping
+fragment information - Songqing Cai (songqing_cai@sterling.com)
+
+KFREE() passed fp (incorrect) and not fr (correct) in ip_frag.c - John Hood
+(cgull@smoke.marlboro.vt.us)
+
+make ipf parser recognise '\\' as a `continued line' marker - Dima Ruban
+(dima@best.net)
+
+3.1.1-alpha 23/8/96 - Released
+
+kernel panic's when ICMP packets go through NAT code
+
+stats aren't zero'd properly with ipf -Z
+
+ipnat doesn't show port numbers correctly all the time and also add the
+protocol (tcp/udp/tcpudp) to rdr output - Carson Gaspar (carson@lehman.com)
+
+fast checksum fixing not 100% - backout patch - Bill Dorsey (dorsey@lila.com)
+
+NetBSD-1.2 patches from - VaX#n8 <vax@linkdead.paranoia.com>
+
+Usage() call error in fils.c - Ajay Shekhawat (ajay@cedar.buffalo.edu)
+
+ip_optcopy() staticly defined in ip_output.c in SunOS4 - Nick Hall
+(nrh@tardis.ed.ac.uk)
+
+3.1.0 7/7/96 - Released
+
+Reformatted ipnat output to be compatible with it's input, so that
+"ipnat -l | ipnat -rf -" is possible.
+
+3.1.0beta 30/6/96 - Released
+
+NetBSD-1.2 patches from Greg Woods (woods@most.weird.com)
+
+kernel module must not be installed stripped (Solaris2), as created by
+"make package" for Solaris2 - Peter Heimann
+(peter@i3.informatik.rwth-aachen.de)
+
+3.1.0alpha 5/6/96 - Released
+
+include examples in package for solaris2
+
+patches for removing an extra ip header checksum (FreeBSD/NetBSD/SunOS)
+
+removed trailing space from printouts of rules in ipf.
+
+ipresend supports the same range of inputs that ipftest does.
+
+sending a duplicate copy of a packet to another network devices is now
+supported. ("dup-to")
+
+sending a packet to an arbitary interface is now supported, irrespective
+of its actual route, with no ttl decrement. Can also be routed without
+the ttl being decremented. ("to" and "fastroute").
+
+"call" option added to support calling a generic function if a packet is
+matched.
+
+show all (upto 4) recorded bytes from the interface name in logging from
+ipmon.
+
+support for using unix file permissions for read/write access on the device
+is now in place.
+
+recursive mutex in nat_new() for Solaris 2.x - Per L. Hagen <per@stibo.dk>
+
+ipftest doesn't call initparse() for THISHOST - Catherine Allen
+(cla@connect.com.au)
+
+Man page corrections from Rex Bona (rex@pengo.comsmiths.com.au)
+
+3.0.4 10/4/96 - Released
+
+looop in `parsing' IP packets with optlen 0 for ip options.
+
+rule number not initialized and resulted in unexpected results for state
+maching.
+
+option parsing and printing bugs - Pradeep Krishnan
+
+3.0.4beta 25/3/96 - Released
+
+wouldn't parse "keep flags keep state" correctly.
+
+SunOS4.1.x ip_input.c doesn't recognise all 1s broadcast address - Nigel Verdon
+
+patches for BSDI's BSD/OS 2.1 and libpcap reader on little endian systems
+from Thorsten Lockert <tholo@tetherless.com>
+
+b* functions in fil.c on Solaris 2.4
+
+3.0.3 17/3/96 - Released
+
+added patches to support IP Filter initialisation when compiled into the
+kernel.
+
+added -x option to ipmon to display hex dumps of logged packets.
+
+added -H option to ipftest to allow ascii-hex formatted input to specify
+arbitary IP packets.
+
+Sending TCP RSTs as a response now work for Solaris2 x86
+
+add patches to make IP Filter compile into NetBSD kernels properly.
+
+patch to stop SunOS 4.1.x kernels panicing with "data traps".
+
+ipfboot script unloads and reloads ipf module on Solaris2 if it is already
+loaded into the kernel.
+
+Installation of IP Filter as a Solaris2 package is now supported.
+
+Man pages for ipnat.4, ipnat.5 added.
+
+added some more regression tests and fixed up IP Filter to pass the new tests
+(previous versions failed some of the tests in set 12).
+
+IP option filter processing has changed so that saying "with opt lsrr" will
+check only for that one, but not mask out other options, so a packet with
+strict source routing, along with loose source routing will match all of
+"with opt lsrr", "with opt ssrr" and "with opt lsrr,ssrr".
+
+IPL_NAME needed in ipnat.c - Kelly (kelly@count04.mry.scruznet.com)
+
+patches for clean NetBSD compilation from Bernd Ernesti (bernd@arresum.inka.de)
+
+make install is incorrect - Julian Briggs (julian@lightwork.co.uk)
+
+strtol() returns 0x7fffffff for all negative numbers,
+printfr() generates incorrect output for "opt sec-class *",
+handling of "not opt xxx opt yyy" incorrect.
+- Minh Tonthat (minht@sbei.com)/Pradeep Krishnan (pradeepk@sbei.com)
+
+m_pullup() called only for input and not output; caused problems
+with filtering icmp - Nigel Verdon (verdenn@gb.swissbank.com)
+
+parsing problem for "port 1" and NetBSD patches incorrect -
+Andreas Gustafsson (gson@guava.araneus.fi)
+
+3.0.2 4/2/96 - Released
+
+Corrected bug where NAT recalculates checksums for fragments.
+
+make NAT recalculate UDP checksums (rather than setting them to 0),
+if they're non-zero.
+
+DNS patches - Real Page (Real.Page@Matrox.com)
+
+alteration of checksum recalculations in NAT code and addition of
+redirection with NAT - Mike Neuman
+
+core dump, if tcp/udp is used with a port number and not service name,
+in ipf - Mike Neuman (mcn@engarde.com)
+
+initparse() call, missing to prime "<thishost>" hook - Craig Bishop
+
+3.0.1 14/1/96 - Released
+
+miscellaneous patches for Solaris2
+
+3.0 14/1/96 - Released
+
+Patch included for FDDI, from Richard Ohnemus
+(Richard_Ohnemus@dallas.csd.sterling.com)
+
+Code cleanup for release.
+
+3.0beta4 10/1/96
+
+recursive mutex in ipfr_slowtimer fixed, reported by Craig Bishop
+
+recursive mutex in sending TCP RSTs fixed, reported by Tony Becker
+
+3.0beta3 9/1/96
+
+FIxup for Solaris2.5 install and interface name bug in ipftest from
+Julian Briggs (julian@lightwork.co.uk)
+
+Byte order patches for ipmon from Tony Becker (tony@mcrsys.com)
+
+3.0beta2 7/1/96
+
+Added the (somewhat warped) IP accounting as it exists in ipfw on FreeBSD.
+Note, this isn't really what one would call IP account, when compared to
+process accounting, sigh.
+
+Split up ipresend into iptest/ipresend/ipsend
+
+Added another m_pullup() inside fr_check() for BSD style kernels and
+added some checks to ipllog() to not log more than is present (for short
+packets).
+
+Fixed bug where failed hostname/netname resolution goes undetecte and
+becomes 0.0.0.0 (any) (reported Guido van Rooij)
+
+3.0beta 11/11/95 - Released
+
+Rewrote the way rule testing is done, reducing the number of files needed and
+generated.
+
+SIOCIPFFL was incorrectly affected by IPFILTER_LOG (Mathew Green)
+
+Patches from Guido van Rooij to fix sending back TCP RSTs on Net-2/Net-3
+BSD based Unixes (panic'd)
+
+Patches for FreeBSD/i86 ipmon from Riku Kalinen <riku@tequila.nixu.fi>
+(I think someone else already told me about these but they got lost :-/)
+
+Changed Makefile structure to build object files for different operating
+systems in separate directories by default.
+
+BSDI has ef0 for first ethernet interface
+
+Allow for a "not" operator before optional keywords.
+
+The "rule number" was being incorrectly incremented every time it went through
+the loop rather than when it matched a rule.
+
+2.8.2 24/10/95 - Released
+
+Fixed up problems with "textip" for doing lots of testing.
+
+Fixed bug in detection of "short" tcp/ip packets (all reported as being short).
+
+Solaris 2.4 port now works 100%.
+
+Man page errors reported and fixed.
+
+Removed duplicate entry in etc/services for login on port 49 (Craig Bishop).
+
+Fixed ipmon output to put a space after the log-letter.
+
+Patch from Guido van Rooij to fix parsing problem.
+
+2.8.1 15/10/95 - Released
+
+Added ttl and tos filtering.
+
+Patches for fixing up compilation and port problems (little endian)
+from Guido van Rooij <guido@IAEhv.nl>.
+
+Man page problems reported and fixed by Carson Gaspar <carson@lehman.com>.
+
+ipsend doesn't compile properly on Solaris2.4
+
+Lots of work done for Solaris2.4 to make it MT/MP safe and work.
+
+2.8 15/9/95 - Released
+
+ipmon can now send messages to syslogd (-s) and use names instead of
+numbers (-N).
+
+IP packets are now "compiled" into a structure only containing filterable
+bits.
+
+Added regression testing in the test/ subdirectory, using a new option
+(-b) with the ipftest program.
+
+Added "nomatch" return to filter results. These are counted and show
+up in reports from ipfstat.
+
+Moved filter code out of ip_fil.c and into fil.c - there is now only one
+instance of it in the package.
+
+Added Solaris 2.4 support.
+
+Added IPSO basic security option filtering.
+
+Added name support for filtering on all 19 named IP options.
+
+Patches from Ivan Brawley to log packet contents as well as packet headers.
+
+Update for sun/conf.c.diff from Ivan Brawley <ibrawley@awadi.com.AU>
+
+Added patches for FreeBSD 1, and added two new switches (-E, -D) to ipf,
+along with a new ioctl, SIOCFRENB.
+From: Dieter Dworkin Muller <dworkin@village.org>
+
+2.7.3 31/7.95 - Released
+
+Didn't compile cleanly without IPFILTER_LOG defined (Mathew Green).
+
+ipftest now deals with tcpdump3 binary output files (from libpcap) with -P.
+
+Brought ipftest program upto date with actual filter code.
+
+Filter would cause a match to occur when it wasn't meant to if the packet
+had short headers and was missing portions that should have been there.
+Err, it would rightly not match on them, but their absence caused a match
+when it shouldn't have been.
+
+2.7.2 26/7/95 - Released
+
+Problem with filtering just SYN flagged packets reported by
+Dieter Dworkin Muller <dworkin@village.org>. To solve this
+problem, added support for masking TCP flags for comparison "flags X/Y".
+
+2.7.1 9/7/95 - Released
+
+Added ip_dirbroadcast support for Sun ip_input.c
+
+Fixed up the install scripts for FreeBSD/NetBSD to recognise where they are
+better.
+
+2.7 7/7/95 - Released
+
+Added "return-rst" to return TCP RST's to TCP packets.
+
+Actually ported it to FreeBSD-i386 2.0.0, so it works there properly now.
+
+Added insertion of filter rules. Use "@<#>" at the beginning of a filter
+to insert a rule at row #.
+
+Filter keeps track of how many times each rule is matched.
+
+Changed compile time things to match kernel option (IPFILTER_LKM &
+IPFILTER_LOG).
+
+Updated ip_input.c and ip_output.c with paches for 3.5 Multicast IP.
+(No change required for 3.6)
+
+Now includes TCP fragments which start inside the TCP header as being short.
+Added counting the number of times each rule is matched.
+
+
+2.6 11/5/95 - Released
+
+Added -n option to ipf: when supplied, no changes are made to the kernel.
+
+Added installation scripts for SunOS 4.1.x and NetBSD/FreeBSD/BSDI.
+
+Rewrote filtering to use a more generic mask & match procedure for
+checking if a packet matches a rule.
+
+2.5.2 27/4/95 - Released
+
+"tcp/udp" and a non-initialised pointer caused the "proto" to become
+a `random' value; added "ip#/dotted.mask" notation to the BNF.
+From Adam W. Feigin <feigin@iis.ee.ethz.ch>
+
+2.5.1 22/3/95 - Released
+
+"tcp/udp" had a strange effect (undesired) on getserv*() functions,
+causing protocol/service lookups to fail. Reported by Matthew Green.
+
+2.5 17/3/95 - Released
+
+Added a new keyword "all" to BNF and parsing of tcpdump/etherfind/snoop
+output through the ipftest program. Suggestions from:
+Michael Ciavarella (mikec@phyto.apana.org.au)
+
+Conflicts occur when "general" filter rules are used for ports and the
+lack of a "proto" when used with "port" matches other packets when only
+TCP/UDP are implied.
+Reported Matthew Green (mrg@fulcom.com.au);
+reported & fixed 6-8/3/95
+
+Added filtering of short TCP packets using "with short" 28/2/95
+(These can possibly slip by checks for the various flags). Short UDP
+or ICMP are dropped to the floor and logged.
+
+Added filtering of fragmented packets using "with frag" 24/2/95
+
+Port to NetBSD-current completed 20/2/95, using LKM.
+
+Added logging of the rule # which caused the logging to happen and the
+interface on which the packet is currently as suggested by
+Andreas Greulich (greulich@math-stat.unibe.ch) 10/2/95
+
+2.4 9/2/95 - Released
+Fixed saving of IP headers in ICMP packets.
+
+2.3 29/1/95
+Added ipf -F [in|out|all] to flush filter rule sets (SIOCIPFFL).
+Fixed iplread() and iplsave() with help from Marc Huber.
+
+2.2 7/1/95 - Released
+Added code from Marc Huber <huber@fzi.de> to allow it to allocate
+its own major char number dynamically when modload'ing. Fixed up
+use of <, >, <=, >= and >< for ports.
+
+2.1 21/12/94 - Released
+repackaged to include the correct ip_output.c and ip_input.c *goof*
+
+2.0 18/12/94 - Released
+added code to check for port ranges - complete.
+rewrote to work as a loadable kernel module - complete.
+
+1.1
+added code for ouput filtering as well as input filtering and added support for logging to a simple character device of packet headers.
+
+1.0 22/04/93 - Released
+First release cut.
+
diff --git a/contrib/ipfilter/IMPORTANT b/contrib/ipfilter/IMPORTANT
new file mode 100644
index 000000000000..00272f2b1f53
--- /dev/null
+++ b/contrib/ipfilter/IMPORTANT
@@ -0,0 +1,41 @@
+ ****************************************
+ IMPORTANT NOTICE
+ ****************************************
+1)
+
+If you're using this software and have a rule which ends like this:
+
+flags S
+
+(for TCP), then to make it totally effective, you need to change it to appear
+as follows:
+
+flags S/SA
+
+The problem is that the old code would compare all the TCP flags against the
+rule (which just has "S") to see if that matched exactly. It is very possible
+for this to not be the case and in these cases, the rule would fail to match
+a 'valid' TCP SYN packet.
+
+Why does it need to be "S/SA" and not "S/S" ?
+
+"S/S" will match the SYN-ACK as well the SYN.
+
+By defalt, "flags S" will now be converted to "flags S/AUPRFS".
+
+If you have any queries regarding this, see the examples and ipf(4).
+If you still have a query or suggestion, please email me.
+
+
+2)
+
+If a filter rule used, in combination port comparisons and the flags
+keywords, a "short" TCP packet, if not explicitly blocked high up in
+the list of packets, would actually get matched even though it would
+otherwise not have been (due to the ports not). This behaviour has
+subsequently been fixed.
+
+
+Darren
+darrenr@cyber.com.au
+ ****************************************
diff --git a/contrib/ipfilter/INSTALL.FreeBSD b/contrib/ipfilter/INSTALL.FreeBSD
new file mode 100644
index 000000000000..3910f4d47577
--- /dev/null
+++ b/contrib/ipfilter/INSTALL.FreeBSD
@@ -0,0 +1,41 @@
+
+To build a kernel for use with the loadable kernel module, follow these
+steps:
+ 1. do "make bsd"
+
+ 2. do "make install-bsd"
+ (probably has to be done as root)
+
+ 3. run "FreeBSD/minstall" as root
+
+ 4. build a new kernel
+
+ 5. install and reboot with the new kernel
+
+ 6. use modload(8) to load the packet filter with:
+ modload if_ipl.o
+
+ 7. do "modstat" to confirm that it has been loaded successfully.
+
+There is no need to use mknod to create the device in /dev;
+- upon loading the module, it will create itself with the correct values,
+ under the name (IPL_NAME) from the Makefile. It will also remove itself
+ from /dev when it is modunload'd.
+
+To build a kernel with the IP filter, follow these steps:
+
+ 1. do "make bsd"
+
+ 2. do "make install-bsd"
+ (probably has to be done as root)
+
+ 3. run "FreeBSD/kinstall" as root
+
+ 4. build a new kernel
+
+ 5. create /dev/ipl with "mknod /dev/ipl c 20 0".
+
+ 6. install and reboot with the new kernel
+
+Darren Reed
+darrenr@cyber.com.au
diff --git a/contrib/ipfilter/INSTALL.NetBSD b/contrib/ipfilter/INSTALL.NetBSD
new file mode 100644
index 000000000000..2387827ea3ca
--- /dev/null
+++ b/contrib/ipfilter/INSTALL.NetBSD
@@ -0,0 +1,48 @@
+
+To build a kernel for use with the loadable kernel module, follow these
+steps:
+ 1. do "make bsd"
+
+ 2. do "make install-bsd"
+ (probably has to be done as root)
+
+ 3(a) NetBSD systems prior to 1.2:
+ run "NetBSD/minstall" as root
+ 3(b) NetBSD 1.2 systems or later:
+ run "NetBSD-1.2/minstall" as root
+
+ 4. build a new kernel
+
+ 5. install and reboot with the new kernel
+
+ 6. use modload(8) to load the packet filter with:
+ modload if_ipl.o
+
+ 7. do "modstat" to confirm that it has been loaded successfully.
+
+There is no need to use mknod to create the device in /dev;
+- upon loading the module, it will create itself with the correct values,
+ under the name (IPL_NAME) from the Makefile. It will also remove itself
+ from /dev when it is modunload'd.
+
+To build a kernel with the IP filter, follow these steps:
+
+ 1. do "make bsd"
+
+ 2. do "make install-bsd"
+ (probably has to be done as root)
+
+ 3(a) NetBSD systems prior to 1.2:
+ run "NetBSD/kinstall" as root
+ 3(b) NetBSD 1.2 systems or later:
+ run "NetBSD-1.2/kinstall" as root
+
+ 4. build a new kernel
+
+ 5. create /dev/ipl with "mknod /dev/ipl c 59 0".
+ (for NetBSD-1.2, use "mknod /dev/ipl c 49 0")
+
+ 6. install and reboot with the new kernel
+
+Darren Reed
+darrenr@cyber.com.au
diff --git a/contrib/ipfilter/INSTALL.Sol2 b/contrib/ipfilter/INSTALL.Sol2
new file mode 100644
index 000000000000..6ed6473579dc
--- /dev/null
+++ b/contrib/ipfilter/INSTALL.Sol2
@@ -0,0 +1,27 @@
+
+For those running Solaris 2.5, please read COMPILE.2.5 before building
+IP Filter.
+
+Type "make solaris" to build all the required binaries.
+
+Once IP Filter has been successfully compiled, you may then install it using
+the usual package method (using pkgadd), however, the package needs to be
+created, prior to pkgadd'ing. To create the package in /var/spoo/pkg, change
+directory to SunOS5 and enter the following command:
+
+make package
+
+If you wish to then install it using `pkgadd', run the following command:
+
+pkgadd -s '/var/spool/pkg'
+
+As part of the postinstall script, it will install loadable kernel module
+as part of Solaris 2 (using add_drv) making it available for immeadiate use.
+
+IP Filter will be installed into /opt/CYBSipf (programs, manual pages and
+examples) and create a directory /etc/opt/CYBSipf with a null body file
+called "ipf.conf" using touch. The rc scripts have been written to look
+for the configuration file here, using the installed binaries in /sbin.
+
+Darren Reed
+darrenr@cyber.com.au
diff --git a/contrib/ipfilter/INSTALL.SunOS b/contrib/ipfilter/INSTALL.SunOS
new file mode 100644
index 000000000000..836d1214589a
--- /dev/null
+++ b/contrib/ipfilter/INSTALL.SunOS
@@ -0,0 +1,36 @@
+
+To install as a Loadable Kernel Module (LKM):
+
+ 1. do a "make sunos4" in this directory
+
+ 2. Run the script "SunOS4/minstall" as root.
+
+ 3. change directory to SunOS4 and run "make install"
+
+ 4. Reboot using the new kernel
+
+ 5. use modload(8) to load the packet filter with:
+ modload if_ipl.o
+
+ 6. do "modstat" to confirm that it has been loaded successfully.
+
+ There is no need to use mknod to create the device in /dev;
+ - upon loading the module, it will create itself with the correct
+ values, under the name (IPL_NAME) from the Makefile. It will
+ also remove itself from /dev when it is modunload'd.
+
+
+To install as part of a SunOS 4.1.x kernel:
+
+ 1. do a "make sunos4" in this directory
+
+ 2. Run the script "SunOS4/kinstall" as root.
+ NOTE: This script sets up /dev/ipl as char. device 59,0
+ in /sys/sun/conf.c
+
+ 3. Do "mknod /dev/ipl c 59 0" as root.
+
+ 4. Reboot using the new kernel
+
+Darren Reed
+darrenr@cyber.com.au
diff --git a/contrib/ipfilter/INSTALL.xBSD b/contrib/ipfilter/INSTALL.xBSD
new file mode 100644
index 000000000000..9ab66f12932c
--- /dev/null
+++ b/contrib/ipfilter/INSTALL.xBSD
@@ -0,0 +1,39 @@
+
+To build a kernel for use with the loadable kernel module, follow these
+steps:
+ 1. do "make bsd"
+
+ 2. cd to the "BSD" directory and type "make install"
+
+ 3. run "4bsd/minstall" as root
+
+ 4. build a new kernel
+
+ 5. install and reboot with the new kernel
+
+ 6. use modload(8) to load the packet filter with:
+ modload if_ipl.o
+
+ 7. do "modstat" to confirm that it has been loaded successfully.
+
+There is no need to use mknod to create the device in /dev;
+- upon loading the module, it will create itself with the correct values,
+ under the name (IPL_NAME) from the Makefile. It will also remove itself
+ from /dev when it is modunload'd.
+
+To build a kernel with the IP filter, follow these steps:
+
+ 1. do "make bsd"
+
+ 2. cd to the "BSD" directory and type "make install"
+
+ 3. run "4bsd/kinstall" as root
+
+ 4. build a new kernel
+
+ 5. create /dev/ipl with "mknod /dev/ipl c 59 0".
+
+ 6. install and reboot with the new kernel
+
+Darren
+darrenr@cyber.com.au
diff --git a/contrib/ipfilter/LICENCE b/contrib/ipfilter/LICENCE
new file mode 100644
index 000000000000..c5a7767d12cf
--- /dev/null
+++ b/contrib/ipfilter/LICENCE
@@ -0,0 +1,16 @@
+/*
+ * (C)opyright 1993, 1994, 1995 by Darren Reed.
+ *
+ * The author accepts no responsibility for the use of this software and
+ * provides it on an ``as is'' basis without express or implied warranty.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that this notice is preserved and due credit is given
+ * to the original author and the contributors.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * I hate legaleese, don't you ?
+ */
diff --git a/contrib/ipfilter/Makefile b/contrib/ipfilter/Makefile
new file mode 100644
index 000000000000..d0d5309d98e6
--- /dev/null
+++ b/contrib/ipfilter/Makefile
@@ -0,0 +1,158 @@
+#
+# (C)opyright 1993, 1994, 1995 by Darren Reed.
+#
+# This code may be freely distributed as long as it retains this notice
+# and is not changed in any way. The author accepts no responsibility
+# for the use of this software. I hate legaleese, don't you ?
+#
+# $Id: Makefile,v 2.0.1.4 1997/02/08 06:39:28 darrenr Exp $
+#
+# where to put things.
+#
+BINDEST=/usr/local/ip_fil3.1.1/bin
+SBINDEST=/usr/local/ip_fil3.1.1/sbin
+MANDIR=/usr/local/ip_fil3.1.1/man
+CC=gcc
+DEBUG=-g
+CFLAGS=-I$$(TOP)
+DCPU=`uname -m`
+#
+# To enable this to work as a Loadable Kernel Module...
+#
+IPFLKM=-DIPFILTER_LKM
+#
+# To enable logging of blocked/passed packets...
+#
+IPFLOG=-DIPFILTER_LOG
+#
+# The facility you wish to log messages from ipmon to syslogd with.
+#
+LOGFAC=-DLOGFAC=LOG_LOCAL0
+#
+# For packets which don't match any pass rules or any block rules, set either
+# FR_PASS or FR_BLOCK (respectively). It defaults to FR_PASS if left
+# undefined. This is ignored for ipftest, which can thus return three
+# results: pass, block and nomatch. This is the sort of "block unless
+# explicitly allowed" type #define switch.
+#
+POLICY=-DNOMATCH=FR_PASS
+#
+MFLAGS="BINDEST=$(BINDEST)" "SBINDEST=$(SBINDEST)" "MANDIR=$(MANDIR)" \
+ "CC=$(CC)" 'CFLAGS=$(CFLAGS) $(SOLARIS2)' "IPFLKM=$(IPFLKM)" \
+ "IPFLOG=$(IPFLOG)" "LOGFAC=$(LOGFAC)" "POLICY=$(POLICY)" \
+ "SOLARIS2=$(SOLARIS2)" "DEBUG=$(DEBUG)" "ARCH=$(ARCH)"
+#
+########## ########## ########## ########## ########## ########## ##########
+#
+CP=/bin/cp
+RM=/bin/rm
+CHMOD=/bin/chmod
+INSTALL=install
+#
+DFLAGS=$(IPFLKM) $(IPFLOG) $(DEF)
+
+all:
+ @echo "Chose one of the following targets for making IP filter:"
+ @echo ""
+ @echo "solaris - auto-selects SunOS4.1.x/Solaris 2.[45]/Soalris2.[45]-x86"
+ @echo "bsd - compile for 4.4BSD based Unixes (FreeBSD/NetBSD/OpenBSD)"
+ @echo "bsdi - compile for BSD/OS"
+ @echo ""
+
+tests:
+ @if [ -d test ]; then (cd test; make) \
+ else echo test directory not present, sorry; fi
+
+sunos solaris:
+ ./buildsunos
+
+sunos4 solaris1:
+ (cd SunOS4; make build TOP=.. $(MFLAGS); cd ..)
+ (cd SunOS4; make -f Makefile.ipsend TOP=.. $(MFLAGS); cd ..)
+
+sunos5 solaris2:
+ (cd SunOS5/$(DCPU); make build TOP=../.. $(MFLAGS) "SOLARIS2=$(SOLARIS2)" "CPU=-Dsparc -D__sparc__"; cd ..)
+ (cd SunOS5/$(DCPU); make -f Makefile.ipsend TOP=../.. $(MFLAGS); cd ..)
+
+sunos5x86 solaris2x86:
+ (cd SunOS5/$(DCPU); make build TOP=../.. $(MFLAGS) "SOLARIS2=$(SOLARIS2)" "CPU=-Di86pc -Di386 -D__i386__"; cd ..)
+ (cd SunOS5/$(DCPU); make -f Makefile.ipsend TOP=../.. $(MFLAGS); cd ..)
+
+bsd netbsd freebsd:
+ -if [ ! -d BSD/$(DCPU) ] ; then mkdir BSD/$(DCPU); fi
+ -rm -f BSD/$(DCPU)/Makefile BSD/$(DCPU)/Makefile.ipsend
+ -ln -s ../Makefile BSD/$(DCPU)/Makefile
+ -ln -s ../Makefile.ipsend BSD/$(DCPU)/Makefile.ipsend
+ (cd BSD/$(DCPU); make build "TOP=../.." $(MFLAGS); cd ..)
+ (cd BSD/$(DCPU); make -f Makefile.ipsend "TOP=../.." $(MFLAGS); cd ..)
+
+bsdi bsdos:
+ -if [ ! -d BSD/$(DCPU) ] ; then mkdir BSD/$(DCPU); fi
+ -rm -f BSD/$(DCPU)/Makefile BSD/$(DCPU)/Makefile.ipsend
+ -ln -s ../Makefile BSD/$(DCPU)/Makefile
+ -ln -s ../Makefile.ipsend BSD/$(DCPU)/Makefile.ipsend
+ (cd BSD/$(DCPU); make build "TOP=../.." $(MFLAGS) LKM= ; cd ..)
+ (cd BSD/$(DCPU); make -f Makefile.ipsend "TOP=../.." $(MFLAGS); cd ..)
+
+clean:
+ ${RM} -f core *.o ipt fils ipf ipfstat ipftest ipmon if_ipl \
+ vnode_if.h $(LKM)
+ (cd SunOS4; make clean)
+ (cd SunOS5; make clean)
+ (cd BSD; make clean)
+ [ -d test ] && (cd test; make clean)
+ (cd ipsend; make clean)
+
+clean-bsd:
+ (cd BSD; make clean)
+
+clean-sunos4:
+ (cd SunOS4; make clean)
+
+clean-sunos5:
+ (cd SunOS5; make clean)
+
+get:
+ -@for i in ipf.c ipt.h solaris.c ipf.h kmem.c ipft_ef.c linux.h \
+ ipft_pc.c fil.c ipft_sn.c mln_ipl.c fils.c ipft_td.c \
+ mls_ipl.c ip_compat.h ipl.h opt.c ip_fil.c ipl_ldev.c \
+ parse.c ip_fil.h ipmon.c pcap.h ip_sfil.c ipt.c snoop.h \
+ ip_state.c ip_state.h ip_nat.c ip_nat.h ip_frag.c \
+ ip_frag.h ip_sfil.c misc.c; do \
+ if [ ! -f $$i ] ; then \
+ echo "getting $$i"; \
+ sccs get $$i; \
+ fi \
+ done
+
+install-bsd: bsd
+ (cd BSD/$(DCPU); $(MAKE) "TOP=../.." install)
+install-sunos4: solaris
+ (cd SunOS4; $(MAKE) "TOP=.." install)
+install-sunos5: solaris
+ (cd SunOS5; $(MAKE) "TOP=.." install)
+
+# XXX FIXME: bogus to depend on all!
+install: all ip_fil.h
+ -$(CP) ip_fil.h /usr/include/netinet/ip_fil.h
+ -$(CHMOD) 444 /usr/include/netinet/ip_fil.h
+ -$(INSTALL) -cs -g wheel -m 755 -o root ipfstat ipf ipnat $(SBINDEST)
+ -$(INSTALL) -cs -g wheel -m 755 -o root ipmon ipftest $(BINDEST)
+ (cd man; $(MAKE) INSTALL=$(INSTALL) MANDIR=$(MANDIR) install; cd ..)
+
+rcsget:
+ -@for i in ipf.c ipt.h solaris.c ipf.h kmem.c ipft_ef.c linux.h \
+ ipft_pc.c fil.c ipft_sn.c mln_ipl.c fils.c ipft_td.c \
+ mls_ipl.c ip_compat.h ipl.h opt.c ip_fil.c ipl_ldev.c \
+ parse.c ip_fil.h ipmon.c pcap.h ip_sfil.c ipt.c snoop.h \
+ ip_state.c ip_state.h ip_nat.c ip_nat.h ip_frag.c \
+ ip_frag.h ip_sfil.c misc.c; do \
+ if [ ! -f $$i ] ; then \
+ echo "getting $$i"; \
+ co $$i; \
+ fi \
+ done
+
+do-cvs:
+ find . -type d -name CVS -print | xargs /bin/rm -rf
+ find . -type f -name .cvsignore -print | xargs /bin/rm -f
diff --git a/contrib/ipfilter/README b/contrib/ipfilter/README
new file mode 100644
index 000000000000..b959d408f293
--- /dev/null
+++ b/contrib/ipfilter/README
@@ -0,0 +1,93 @@
+IP Filter - What's this about ?
+============================
+
+ The idea behind this package is allow those who use Unix workstations as
+routers (a common occurance in Universities it appears) to apply packet
+filtering to packets going in and out of them. This package has been
+tested on all versions of SunOS 4.1 and Solaris 2.4/2.5, running on Sparcs.
+It is also quite possible for this small kernel extension to be installed
+and used effectively on Sun workstations which don't route IP, just for
+added security. It can also be integrated with the multicast patches.
+It has also been tested successfully on all of the modern free BSDs as
+well as BSDI.
+
+ The filter keeps a rule list for both inbound and outbound sides of
+the IP packet queue and a check is made as early as possible, aiming to
+stop the packet before it even gets as far as being checked for source
+route options. In the file "BNF", a set of rules for constructing filter
+rules understood by this package is given. The files in the directory
+"rules", "example.1" ... "example.sr" show example rules you might apply.
+
+ In practise, I've successfully isolated a workstation from all
+machines except the NFS file servers on its local subnets (yeah, ok, so
+this doesn't really increase security, because of NFS, but you get the
+drift on how it can be applied and used). I've also successfully
+setup and maintained my own firewalls using it with TIS's Firewall Toolkit,
+including using it on an mbone router.
+
+ When using it with multicast IP, the calls to fr_check() should be
+before the packet is unwrapped and after it is encapsulated. So the
+filter routines will see the packet as a UDP packet, protocol XYZ.
+Whether this is better or worse than having it filter on class D addresses
+is debateable, but the idea behind this package is to be able to
+discriminate between packets as they are on the 'wire', before they
+get routed anywhere, etc.
+
+ It is worth noting, that it is possible, using a small MTU and
+generating tiny fragmented IP packets to generate a TCP packet which
+doesn't contain enough information to filter on the "flags". Filtering
+on these types of packets is possible, but under the more general case
+of the packets being "short". ICMP and UDP packets which are too small
+(they don't contain a complete header) are dropped and logged, no questions
+asked. When filtering on fragmented packets, the last fragment will get
+through for TCP/UDP/ICMP packets.
+
+
+Some general notes.
+-------------------
+ To add/delete a rule from memory, access to the device in /dev is needed,
+allowing non-root maintenaince. The filter list in kernel memory is built
+from the kernel's heap. Each packet coming *in* or *out* is checked against
+the appropriate list, rejects dropped, others passed through. Thus this will
+work on an individual host, not just gateways. Presently there is only one
+list for all interfaces, the changes required to make it a per-interface list
+require more .o replacements for the kernel. When checking a packet, the
+packet is compared to the entire list from top to bottom, the last matching
+line being effective.
+
+
+What does what ?
+----------------
+if_fil.o (Loadable kernel module)
+ - additional kernel routines to check an access list as to whether
+ or not to drop or pass a packet. It currently defaults to pass
+ on all packets.
+
+ipfstat
+ - digs through your kernel (need to check #define VMUNIX in fils.c)
+ and /dev/kmem for the access filter list and mini stats table.
+ Obviously needs to be run priviledged if required.
+
+ipf
+ - reads the files passed as parameters as input files containing new
+ filter rules to add/delete to the kernel list. The lines are
+ inserted in order; the first line is inserted first, and ends up
+ first on the list. Subsequent invocations append to the list
+ unless specified otherwise.
+
+ipftest
+ - test the ruleset given by filename. Reads in the ruleset and then
+ waits for stdin.
+
+ See the man pages (ipf.1, ipftest.1, ipfstat.8) for more detailed
+ information on what the above do.
+
+mkfilters
+ - suggests a set of filter rules to employ and suggests how to add
+ routes to back these up.
+
+BNF
+ - BNF rule set for the filter rules
+
+Darren Reed
+darrenr@cyber.com.au
diff --git a/contrib/ipfilter/bsdinstall b/contrib/ipfilter/bsdinstall
new file mode 100755
index 000000000000..ce921b60fa47
--- /dev/null
+++ b/contrib/ipfilter/bsdinstall
@@ -0,0 +1,83 @@
+#! /bin/sh
+#
+# @(#)install.sh 4.5 (Berkeley) 10/12/83
+#
+cmd=/bin/mv
+strip=""
+chmod="chmod 755"
+chown="chown -f root"
+chgrp="chgrp -f bin"
+while true ; do
+ case $1 in
+ -s ) strip="strip"
+ shift
+ ;;
+ -c ) cmd="cp"
+ shift
+ ;;
+ -m ) chmod="chmod $2"
+ shift
+ shift
+ ;;
+ -o ) chown="chown -f $2"
+ shift
+ shift
+ ;;
+ -g ) chgrp="chgrp -f $2"
+ shift
+ shift
+ ;;
+ -d ) cmd="mkdir"
+ shift
+ ;;
+ * ) break
+ ;;
+ esac
+done
+
+if [ ! ${2-""} ]
+then echo "install: no destination specified"
+ exit 1
+fi
+if [ ${3-""} ]
+then echo "install: too many files specified -> $*"
+ exit 1
+fi
+if [ $1 = $2 -o $2 = . ]
+then echo "install: can't move $1 onto itself"
+ exit 1
+fi
+case $cmd in
+/bin/mkdir )
+ file=$2/$1
+ ;;
+* )
+ if [ '!' -f $1 ]
+ then echo "install: can't open $1"
+ exit 1
+ fi
+ if [ -d $2 ]
+ then file=$2/$1
+ else file=$2
+ fi
+ /bin/rm -f $file
+ ;;
+esac
+
+case $cmd in
+/bin/mkdir )
+ if [ ! -d "$file" ]
+ then $cmd $file
+ fi
+ ;;
+* )
+ $cmd $1 $file
+ if [ $strip ]
+ then $strip $file
+ fi
+ ;;
+esac
+
+$chown $file
+$chgrp $file
+$chmod $file
diff --git a/contrib/ipfilter/buildsunos b/contrib/ipfilter/buildsunos
new file mode 100755
index 000000000000..dd2aa38a36ca
--- /dev/null
+++ b/contrib/ipfilter/buildsunos
@@ -0,0 +1,23 @@
+#! /bin/sh
+# $Id: buildsunos,v 2.0.1.1 1997/01/09 15:14:43 darrenr Exp $
+:
+rev=`uname -r | sed -e 's/^\([^\.]*\)\..*/\1/'`
+cpu=`uname -m`
+if [ $rev = 5 ] ; then
+ solrev=`uname -r | sed -e 's/^\([0-9]*\)\.\([0-9]*\)$/\2/'`
+ mkdir -p SunOS5/${cpu}
+ /bin/rm -f SunOS5/${cpu}/Makefile
+ /bin/rm -f SunOS5/${cpu}/Makefile.ipsend
+ ln -s ../Makefile SunOS5/${cpu}/Makefile
+ ln -s ../Makefile.ipsend SunOS5/${cpu}/Makefile.ipsend
+fi
+if [ $cpu = i86pc ] ; then
+ make ${1+"$@"} sunos5x86 SOLARIS2="-DSOLARIS2=$solrev" DCPU=${cpu}
+ exit $?
+fi
+if [ x$solrev = x ] ; then
+ make ${1+"$@"} sunos$rev "ARCH=`uname -m`"
+ exit $?
+fi
+make ${1+"$@"} sunos$rev SOLARIS2="-DSOLARIS2=$solrev" DCPU=${cpu}
+exit $?
diff --git a/contrib/ipfilter/etc/protocols b/contrib/ipfilter/etc/protocols
new file mode 100644
index 000000000000..b41aa1df4372
--- /dev/null
+++ b/contrib/ipfilter/etc/protocols
@@ -0,0 +1,95 @@
+icmp 1 ICMP # Internet Control Message
+igmp 2 IGMP # Internet Group Management
+ggp 3 GGP # Gateway-to-Gateway
+ip 4 IP # IP in IP (encasulation)
+st 5 ST # Stream
+tcp 6 TCP # Transmission Control
+ucl 7 UCL # UCL
+egp 8 EGP # Exterior Gateway Protocol
+igp 9 IGP # any private interior gateway
+bbn-rcc-mon 10 BBN-RCC-MON # BBN RCC Monitoring
+nvp-ii 11 NVP-II # Network Voice Protocol
+pup 12 PUP # PUP
+argus 13 ARGUS # ARGUS
+emcon 14 EMCON # EMCON
+xnet 15 XNET # Cross Net Debugger
+chaos 16 CHAOS # Chaos
+udp 17 UDP # User Datagram
+mux 18 MUX # Multiplexing
+dcn-meas 19 DCN-MEAS # DCN Measurement Subsystems
+hmp 20 HMP # Host Monitoring
+prm 21 PRM # Packet Radio Measurement
+xns-idp 22 XNS-IDP # XEROX NS IDP
+trunk-1 23 TRUNK-1 # Trunk-1
+trunk-2 24 TRUNK-2 # Trunk-2
+leaf-1 25 LEAF-1 # Leaf-1
+leaf-2 26 LEAF-2 # Leaf-2
+rdp 27 RDP # Reliable Data Protocol
+irtp 28 IRTP # Internet Reliable Transaction
+iso-tp4 29 ISO-TP4 # ISO Transport Protocol Class 4
+netblt 30 NETBLT # Bulk Data Transfer Protocol
+mfe-nsp 31 MFE-NSP # MFE Network Services Protocol
+merit-inp 32 MERIT-INP # MERIT Internodal Protocol
+sep 33 SEP # Sequential Exchange Protocol
+3pc 34 3PC # Third Party Connect Protocol
+idpr 35 IDPR # Inter-Domain Policy Routing Protocol
+xtp 36 XTP # XTP
+ddp 37 DDP # Datagram Delivery Protocol
+idpr-cmtp 38 IDPR-CMTP # IDPR Control Message Transport Proto
+tp++ 39 TP++ # TP++ Transport Protocol
+il 40 IL # IL Transport Protocol
+sip 41 SIP # Simple Internet Protocol
+sdrp 42 SDRP # Source Demand Routing Protocol
+sip-sr 43 SIP-SR # SIP Source Route
+sip-frag 44 SIP-FRAG # SIP Fragment
+idrp 45 IDRP # Inter-Domain Routing Protocol
+rsvp 46 RSVP # Reservation Protocol
+gre 47 GRE # General Routing Encapsulation
+mhrp 48 MHRP # Mobile Host Routing Protocol
+bna 49 BNA # BNA
+sipp-esp 50 SIPP-ESP # SIPP Encap Security Payload
+sipp-ah 51 SIPP-AH # SIPP Authentication Header
+i-nlsp 52 I-NLSP # Integrated Net Layer Security TUBA
+swipe 53 SWIPE # IP with Encryption
+nhrp 54 NHRP # NBMA Next Hop Resolution Protocol
+any 61 any # host internal protocol
+cftp 62 CFTP # CFTP
+any 63 any # local network
+sat-expak 64 SAT-EXPAK # SATNET and Backroom EXPAK
+kryptolan 65 KRYPTOLAN # Kryptolan
+rvd 66 RVD # MIT Remote Virtual Disk Protocol
+ippc 67 IPPC # Internet Pluribus Packet Core
+any 68 any # distributed file system
+sat-mon 69 SAT-MON # SATNET Monitoring
+visa 70 VISA # VISA Protocol
+ipcv 71 IPCV # Internet Packet Core Utility
+cpnx 72 CPNX # Computer Protocol Network Executive
+cphb 73 CPHB # Computer Protocol Heart Beat
+wsn 74 WSN # Wang Span Network
+pvp 75 PVP # Packet Video Protocol
+br-sat-mon 76 BR-SAT-MON # Backroom SATNET Monitoring
+sun-nd 77 SUN-ND # SUN ND PROTOCOL-Temporary
+wb-mon 78 WB-MON # WIDEBAND Monitoring
+wb-expak 79 WB-EXPAK # WIDEBAND EXPAK
+iso-ip 80 ISO-IP # ISO Internet Protocol
+vmtp 81 VMTP # VMTP
+secure-vmtp 82 SECURE-VMTP # SECURE-VMTP
+vines 83 VINES # VINES
+ttp 84 TTP # TTP
+nsfnet-igp 85 NSFNET-IGP # NSFNET-IGP
+dgp 86 DGP # Dissimilar Gateway Protocol
+tcf 87 TCF # TCF
+igrp 88 IGRP # IGRP
+ospfigp 89 OSPFIGP # OSPFIGP
+sprite-rpc 90 Sprite-RPC # Sprite RPC Protocol
+larp 91 LARP # Locus Address Resolution Protocol
+mtp 92 MTP # Multicast Transport Protocol
+ax.25 93 AX.25 # AX.25 Frames
+ipip 94 IPIP # IP-within-IP Encapsulation Protocol
+micp 95 MICP # Mobile Internetworking Control Pro.
+scc-sp 96 SCC-SP # Semaphore Communications Sec. Pro.
+etherip 97 ETHERIP # Ethernet-within-IP Encapsulation
+encap 98 ENCAP # Encapsulation Header
+any 99 any # private encryption scheme
+gmtp 100 GMTP # GMTP
+reserved 255 Reserved #
diff --git a/contrib/ipfilter/etc/services b/contrib/ipfilter/etc/services
new file mode 100644
index 000000000000..90dd07af595b
--- /dev/null
+++ b/contrib/ipfilter/etc/services
@@ -0,0 +1,731 @@
+tcpmux 1/tcp # TCP Port Service Multiplexer
+tcpmux 1/udp # TCP Port Service Multiplexer
+compressnet 2/tcp # Management Utility
+compressnet 2/udp # Management Utility
+compressnet 3/tcp # Compression Process
+compressnet 3/udp # Compression Process
+rje 5/tcp # Remote Job Entry
+rje 5/udp # Remote Job Entry
+echo 7/tcp # Echo
+echo 7/udp # Echo
+discard 9/tcp # Discard
+discard 9/udp # Discard
+systat 11/tcp # Active Users
+systat 11/udp # Active Users
+daytime 13/tcp # Daytime
+daytime 13/udp # Daytime
+qotd 17/tcp # Quote of the Day
+qotd 17/udp # Quote of the Day
+msp 18/tcp # Message Send Protocol
+msp 18/udp # Message Send Protocol
+chargen 19/tcp # Character Generator
+chargen 19/udp # Character Generator
+ftp-data 20/tcp # File Transfer
+ftp-data 20/udp # File Transfer
+ftp 21/tcp # File Transfer
+ftp 21/udp # File Transfer
+telnet 23/tcp # Telnet
+telnet 23/udp # Telnet
+smtp 25/tcp # Simple Mail Transfer
+smtp 25/udp # Simple Mail Transfer
+nsw-fe 27/tcp # NSW User System FE
+nsw-fe 27/udp # NSW User System FE
+msg-icp 29/tcp # MSG ICP
+msg-icp 29/udp # MSG ICP
+msg-auth 31/tcp # MSG Authentication
+msg-auth 31/udp # MSG Authentication
+dsp 33/tcp # Display Support Protocol
+dsp 33/udp # Display Support Protocol
+time 37/tcp # Time
+time 37/udp # Time
+rap 38/tcp # Route Access Protocol
+rap 38/udp # Route Access Protocol
+rlp 39/tcp # Resource Location Protocol
+rlp 39/udp # Resource Location Protocol
+graphics 41/tcp # Graphics
+graphics 41/udp # Graphics
+nameserver 42/tcp # Host Name Server
+nameserver 42/udp # Host Name Server
+nicname 43/tcp # Who Is
+nicname 43/udp # Who Is
+mpm-flags 44/tcp # MPM FLAGS Protocol
+mpm-flags 44/udp # MPM FLAGS Protocol
+mpm 45/tcp # Message Processing Module
+mpm 45/udp # Message Processing Module
+mpm-snd 46/tcp # MPM
+mpm-snd 46/udp # MPM
+ni-ftp 47/tcp # NI FTP
+ni-ftp 47/udp # NI FTP
+auditd 48/tcp # Digital Audit Daemon
+auditd 48/udp # Digital Audit Daemon
+re-mail-ck 50/tcp # Remote Mail Checking Protocol
+re-mail-ck 50/udp # Remote Mail Checking Protocol
+la-maint 51/tcp # IMP Logical Address Maintenance
+la-maint 51/udp # IMP Logical Address Maintenance
+xns-time 52/tcp # XNS Time Protocol
+xns-time 52/udp # XNS Time Protocol
+domain 53/tcp # Domain Name Server
+domain 53/udp # Domain Name Server
+xns-ch 54/tcp # XNS Clearinghouse
+xns-ch 54/udp # XNS Clearinghouse
+isi-gl 55/tcp # ISI Graphics Language
+isi-gl 55/udp # ISI Graphics Language
+xns-auth 56/tcp # XNS Authentication
+xns-auth 56/udp # XNS Authentication
+xns-mail 58/tcp # XNS Mail
+xns-mail 58/udp # XNS Mail
+ni-mail 61/tcp # NI MAIL
+ni-mail 61/udp # NI MAIL
+acas 62/tcp # ACA Services
+acas 62/udp # ACA Services
+covia 64/tcp # Communications Integrator (CI)
+covia 64/udp # Communications Integrator (CI)
+tacacs-ds 65/tcp # TACACS-Database Service
+tacacs-ds 65/udp # TACACS-Database Service
+sql*net 66/tcp # Oracle SQL*NET
+sql*net 66/udp # Oracle SQL*NET
+bootps 67/tcp # Bootstrap Protocol Server
+bootps 67/udp # Bootstrap Protocol Server
+bootpc 68/tcp # Bootstrap Protocol Client
+bootpc 68/udp # Bootstrap Protocol Client
+tftp 69/tcp # Trivial File Transfer
+tftp 69/udp # Trivial File Transfer
+gopher 70/tcp # Gopher
+gopher 70/udp # Gopher
+netrjs-1 71/tcp # Remote Job Service
+netrjs-1 71/udp # Remote Job Service
+netrjs-2 72/tcp # Remote Job Service
+netrjs-2 72/udp # Remote Job Service
+netrjs-3 73/tcp # Remote Job Service
+netrjs-3 73/udp # Remote Job Service
+netrjs-4 74/tcp # Remote Job Service
+netrjs-4 74/udp # Remote Job Service
+deos 76/tcp # Distributed External Object Store
+deos 76/udp # Distributed External Object Store
+vettcp 78/tcp # vettcp
+vettcp 78/udp # vettcp
+finger 79/tcp # Finger
+finger 79/udp # Finger
+www-http 80/tcp # World Wide Web HTTP
+www-http 80/udp # World Wide Web HTTP
+hosts2-ns 81/tcp # HOSTS2 Name Server
+hosts2-ns 81/udp # HOSTS2 Name Server
+xfer 82/tcp # XFER Utility
+xfer 82/udp # XFER Utility
+mit-ml-dev 83/tcp # MIT ML Device
+mit-ml-dev 83/udp # MIT ML Device
+ctf 84/tcp # Common Trace Facility
+ctf 84/udp # Common Trace Facility
+mit-ml-dev 85/tcp # MIT ML Device
+mit-ml-dev 85/udp # MIT ML Device
+mfcobol 86/tcp # Micro Focus Cobol
+mfcobol 86/udp # Micro Focus Cobol
+kerberos 88/tcp # Kerberos
+kerberos 88/udp # Kerberos
+su-mit-tg 89/tcp # SU/MIT Telnet Gateway
+su-mit-tg 89/udp # SU/MIT Telnet Gateway
+dnsix 90/tcp # DNSIX Securit Attribute Token Map
+dnsix 90/udp # DNSIX Securit Attribute Token Map
+mit-dov 91/tcp # MIT Dover Spooler
+mit-dov 91/udp # MIT Dover Spooler
+npp 92/tcp # Network Printing Protocol
+npp 92/udp # Network Printing Protocol
+dcp 93/tcp # Device Control Protocol
+dcp 93/udp # Device Control Protocol
+objcall 94/tcp # Tivoli Object Dispatcher
+objcall 94/udp # Tivoli Object Dispatcher
+supdup 95/tcp # SUPDUP
+supdup 95/udp # SUPDUP
+dixie 96/tcp # DIXIE Protocol Specification
+dixie 96/udp # DIXIE Protocol Specification
+swift-rvf 97/tcp # Swift Remote Vitural File Protocol
+swift-rvf 97/udp # Swift Remote Vitural File Protocol
+tacnews 98/tcp # TAC News
+tacnews 98/udp # TAC News
+metagram 99/tcp # Metagram Relay
+metagram 99/udp # Metagram Relay
+newacct 100/tcp
+hostname 101/tcp # NIC Host Name Server
+hostname 101/udp # NIC Host Name Server
+iso-tsap 102/tcp # ISO-TSAP
+iso-tsap 102/udp # ISO-TSAP
+gppitnp 103/tcp # Genesis Point-to-Point Trans Net
+gppitnp 103/udp # Genesis Point-to-Point Trans Net
+acr-nema 104/tcp # ACR-NEMA Digital Imag. & Comm. 300
+acr-nema 104/udp # ACR-NEMA Digital Imag. & Comm. 300
+csnet-ns 105/tcp # Mailbox Name Nameserver
+csnet-ns 105/udp # Mailbox Name Nameserver
+3com-tsmux 106/tcp # 3COM-TSMUX
+3com-tsmux 106/udp # 3COM-TSMUX
+rtelnet 107/tcp # Remote Telnet Service
+rtelnet 107/udp # Remote Telnet Service
+snagas 108/tcp # SNA Gateway Access Server
+snagas 108/udp # SNA Gateway Access Server
+pop2 109/tcp # Post Office Protocol - Version 2
+pop2 109/udp # Post Office Protocol - Version 2
+pop3 110/tcp # Post Office Protocol - Version 3
+pop3 110/udp # Post Office Protocol - Version 3
+sunrpc 111/tcp # SUN Remote Procedure Call
+sunrpc 111/udp # SUN Remote Procedure Call
+mcidas 112/tcp # McIDAS Data Transmission Protocol
+mcidas 112/udp # McIDAS Data Transmission Protocol
+auth 113/tcp # Authentication Service
+auth 113/udp # Authentication Service
+audionews 114/tcp # Audio News Multicast
+audionews 114/udp # Audio News Multicast
+sftp 115/tcp # Simple File Transfer Protocol
+sftp 115/udp # Simple File Transfer Protocol
+ansanotify 116/tcp # ANSA REX Notify
+ansanotify 116/udp # ANSA REX Notify
+uucp-path 117/tcp # UUCP Path Service
+uucp-path 117/udp # UUCP Path Service
+sqlserv 118/tcp # SQL Services
+sqlserv 118/udp # SQL Services
+nntp 119/tcp # Network News Transfer Protocol
+nntp 119/udp # Network News Transfer Protocol
+cfdptkt 120/tcp # CFDPTKT
+cfdptkt 120/udp # CFDPTKT
+erpc 121/tcp # Encore Expedited Remote Pro.Call
+erpc 121/udp # Encore Expedited Remote Pro.Call
+smakynet 122/tcp # SMAKYNET
+smakynet 122/udp # SMAKYNET
+ntp 123/tcp # Network Time Protocol
+ntp 123/udp # Network Time Protocol
+ansatrader 124/tcp # ANSA REX Trader
+ansatrader 124/udp # ANSA REX Trader
+locus-map 125/tcp # Locus PC-Interface Net Map Ser
+locus-map 125/udp # Locus PC-Interface Net Map Ser
+unitary 126/tcp # Unisys Unitary Login
+unitary 126/udp # Unisys Unitary Login
+locus-con 127/tcp # Locus PC-Interface Conn Server
+locus-con 127/udp # Locus PC-Interface Conn Server
+gss-xlicen 128/tcp # GSS X License Verification
+gss-xlicen 128/udp # GSS X License Verification
+pwdgen 129/tcp # Password Generator Protocol
+pwdgen 129/udp # Password Generator Protocol
+cisco-fna 130/tcp # cisco FNATIVE
+cisco-fna 130/udp # cisco FNATIVE
+cisco-tna 131/tcp # cisco TNATIVE
+cisco-tna 131/udp # cisco TNATIVE
+cisco-sys 132/tcp # cisco SYSMAINT
+cisco-sys 132/udp # cisco SYSMAINT
+statsrv 133/tcp # Statistics Service
+statsrv 133/udp # Statistics Service
+ingres-net 134/tcp # INGRES-NET Service
+ingres-net 134/udp # INGRES-NET Service
+loc-srv 135/tcp # Location Service
+loc-srv 135/udp # Location Service
+profile 136/tcp # PROFILE Naming System
+profile 136/udp # PROFILE Naming System
+netbios-ns 137/tcp # NETBIOS Name Service
+netbios-ns 137/udp # NETBIOS Name Service
+netbios-dgm 138/tcp # NETBIOS Datagram Service
+netbios-dgm 138/udp # NETBIOS Datagram Service
+netbios-ssn 139/tcp # NETBIOS Session Service
+netbios-ssn 139/udp # NETBIOS Session Service
+emfis-data 140/tcp # EMFIS Data Service
+emfis-data 140/udp # EMFIS Data Service
+emfis-cntl 141/tcp # EMFIS Control Service
+emfis-cntl 141/udp # EMFIS Control Service
+bl-idm 142/tcp # Britton-Lee IDM
+bl-idm 142/udp # Britton-Lee IDM
+imap2 143/tcp # Interim Mail Access Protocol v2
+imap2 143/udp # Interim Mail Access Protocol v2
+news 144/tcp # NewS
+news 144/udp # NewS
+uaac 145/tcp # UAAC Protocol
+uaac 145/udp # UAAC Protocol
+iso-tp0 146/tcp # ISO-IP0
+iso-tp0 146/udp # ISO-IP0
+iso-ip 147/tcp # ISO-IP
+iso-ip 147/udp # ISO-IP
+cronus 148/tcp # CRONUS-SUPPORT
+cronus 148/udp # CRONUS-SUPPORT
+aed-512 149/tcp # AED 512 Emulation Service
+aed-512 149/udp # AED 512 Emulation Service
+sql-net 150/tcp # SQL-NET
+sql-net 150/udp # SQL-NET
+hems 151/tcp # HEMS
+hems 151/udp # HEMS
+bftp 152/tcp # Background File Transfer Program
+bftp 152/udp # Background File Transfer Program
+sgmp 153/tcp # SGMP
+sgmp 153/udp # SGMP
+netsc-prod 154/tcp # NETSC
+netsc-prod 154/udp # NETSC
+netsc-dev 155/tcp # NETSC
+netsc-dev 155/udp # NETSC
+sqlsrv 156/tcp # SQL Service
+sqlsrv 156/udp # SQL Service
+knet-cmp 157/tcp # KNET/VM Command/Message Protocol
+knet-cmp 157/udp # KNET/VM Command/Message Protocol
+pcmail-srv 158/tcp # PCMail Server
+pcmail-srv 158/udp # PCMail Server
+nss-routing 159/tcp # NSS-Routing
+nss-routing 159/udp # NSS-Routing
+sgmp-traps 160/tcp # SGMP-TRAPS
+sgmp-traps 160/udp # SGMP-TRAPS
+snmp 161/tcp # SNMP
+snmp 161/udp # SNMP
+snmptrap 162/tcp # SNMPTRAP
+snmptrap 162/udp # SNMPTRAP
+cmip-man 163/tcp # CMIP/TCP Manager
+cmip-man 163/udp # CMIP/TCP Manager
+cmip-agent 164/tcp # CMIP/TCP Agent
+smip-agent 164/udp # CMIP/TCP Agent
+xns-courier 165/tcp # Xerox
+xns-courier 165/udp # Xerox
+s-net 166/tcp # Sirius Systems
+s-net 166/udp # Sirius Systems
+namp 167/tcp # NAMP
+namp 167/udp # NAMP
+rsvd 168/tcp # RSVD
+rsvd 168/udp # RSVD
+send 169/tcp # SEND
+send 169/udp # SEND
+print-srv 170/tcp # Network PostScript
+print-srv 170/udp # Network PostScript
+multiplex 171/tcp # Network Innovations Multiplex
+multiplex 171/udp # Network Innovations Multiplex
+cl/1 172/tcp # Network Innovations CL/1
+cl/1 172/udp # Network Innovations CL/1
+xyplex-mux 173/tcp # Xyplex
+xyplex-mux 173/udp # Xyplex
+mailq 174/tcp # MAILQ
+mailq 174/udp # MAILQ
+vmnet 175/tcp # VMNET
+vmnet 175/udp # VMNET
+genrad-mux 176/tcp # GENRAD-MUX
+genrad-mux 176/udp # GENRAD-MUX
+xdmcp 177/tcp # X Display Manager Control Protocol
+xdmcp 177/udp # X Display Manager Control Protocol
+nextstep 178/tcp # NextStep Window Server
+NextStep 178/udp # NextStep Window Server
+bgp 179/tcp # Border Gateway Protocol
+bgp 179/udp # Border Gateway Protocol
+ris 180/tcp # Intergraph
+ris 180/udp # Intergraph
+unify 181/tcp # Unify
+unify 181/udp # Unify
+audit 182/tcp # Unisys Audit SITP
+audit 182/udp # Unisys Audit SITP
+ocbinder 183/tcp # OCBinder
+ocbinder 183/udp # OCBinder
+ocserver 184/tcp # OCServer
+ocserver 184/udp # OCServer
+remote-kis 185/tcp # Remote-KIS
+remote-kis 185/udp # Remote-KIS
+kis 186/tcp # KIS Protocol
+kis 186/udp # KIS Protocol
+aci 187/tcp # Application Communication Interface
+aci 187/udp # Application Communication Interface
+mumps 188/tcp # Plus Five's MUMPS
+mumps 188/udp # Plus Five's MUMPS
+qft 189/tcp # Queued File Transport
+qft 189/udp # Queued File Transport
+gacp 190/tcp # Gateway Access Control Protocol
+cacp 190/udp # Gateway Access Control Protocol
+prospero 191/tcp # Prospero Directory Service
+prospero 191/udp # Prospero Directory Service
+osu-nms 192/tcp # OSU Network Monitoring System
+osu-nms 192/udp # OSU Network Monitoring System
+srmp 193/tcp # Spider Remote Monitoring Protocol
+srmp 193/udp # Spider Remote Monitoring Protocol
+irc 194/tcp # Internet Relay Chat Protocol
+irc 194/udp # Internet Relay Chat Protocol
+dn6-nlm-aud 195/tcp # DNSIX Network Level Module Audit
+dn6-nlm-aud 195/udp # DNSIX Network Level Module Audit
+dn6-smm-red 196/tcp # DNSIX Session Mgt Module Audit Redir
+dn6-smm-red 196/udp # DNSIX Session Mgt Module Audit Redir
+dls 197/tcp # Directory Location Service
+dls 197/udp # Directory Location Service
+dls-mon 198/tcp # Directory Location Service Monitor
+dls-mon 198/udp # Directory Location Service Monitor
+smux 199/tcp # SMUX
+smux 199/udp # SMUX
+src 200/tcp # IBM System Resource Controller
+src 200/udp # IBM System Resource Controller
+at-rtmp 201/tcp # AppleTalk Routing Maintenance
+at-rtmp 201/udp # AppleTalk Routing Maintenance
+at-nbp 202/tcp # AppleTalk Name Binding
+at-nbp 202/udp # AppleTalk Name Binding
+at-3 203/tcp # AppleTalk Unused
+at-3 203/udp # AppleTalk Unused
+at-echo 204/tcp # AppleTalk Echo
+at-echo 204/udp # AppleTalk Echo
+at-5 205/tcp # AppleTalk Unused
+at-5 205/udp # AppleTalk Unused
+at-zis 206/tcp # AppleTalk Zone Information
+at-zis 206/udp # AppleTalk Zone Information
+at-7 207/tcp # AppleTalk Unused
+at-7 207/udp # AppleTalk Unused
+at-8 208/tcp # AppleTalk Unused
+at-8 208/udp # AppleTalk Unused
+tam 209/tcp # Trivial Authenticated Mail Protocol
+tam 209/udp # Trivial Authenticated Mail Protocol
+z39.50 210/tcp # ANSI Z39.50
+z39.50 210/udp # ANSI Z39.50
+914c/g 211/tcp # Texas Instruments 914C/G Terminal
+914c/g 211/udp # Texas Instruments 914C/G Terminal
+anet 212/tcp # ATEXSSTR
+anet 212/udp # ATEXSSTR
+ipx 213/tcp # IPX
+ipx 213/udp # IPX
+vmpwscs 214/tcp # VM PWSCS
+vmpwscs 214/udp # VM PWSCS
+softpc 215/tcp # Insignia Solutions
+softpc 215/udp # Insignia Solutions
+atls 216/tcp # Access Technology License Server
+atls 216/udp # Access Technology License Server
+dbase 217/tcp # dBASE Unix
+dbase 217/udp # dBASE Unix
+mpp 218/tcp # Netix Message Posting Protocol
+mpp 218/udp # Netix Message Posting Protocol
+uarps 219/tcp # Unisys ARPs
+uarps 219/udp # Unisys ARPs
+imap3 220/tcp # Interactive Mail Access Protocol v3
+imap3 220/udp # Interactive Mail Access Protocol v3
+fln-spx 221/tcp # Berkeley rlogind with SPX auth
+fln-spx 221/udp # Berkeley rlogind with SPX auth
+rsh-spx 222/tcp # Berkeley rshd with SPX auth
+rsh-spx 222/udp # Berkeley rshd with SPX auth
+cdc 223/tcp # Certificate Distribution Center
+cdc 223/udp # Certificate Distribution Center
+sur-meas 243/tcp # Survey Measurement
+sur-meas 243/udp # Survey Measurement
+link 245/tcp # LINK
+link 245/udp # LINK
+dsp3270 246/tcp # Display Systems Protocol
+dsp3270 246/udp # Display Systems Protocol
+pdap 344/tcp # Prospero Data Access Protocol
+pdap 344/udp # Prospero Data Access Protocol
+pawserv 345/tcp # Perf Analysis Workbench
+pawserv 345/udp # Perf Analysis Workbench
+zserv 346/tcp # Zebra server
+zserv 346/udp # Zebra server
+fatserv 347/tcp # Fatmen Server
+fatserv 347/udp # Fatmen Server
+csi-sgwp 348/tcp # Cabletron Management Protocol
+csi-sgwp 348/udp # Cabletron Management Protocol
+clearcase 371/tcp # Clearcase
+clearcase 371/udp # Clearcase
+ulistserv 372/tcp # Unix Listserv
+ulistserv 372/udp # Unix Listserv
+legent-1 373/tcp # Legent Corporation
+legent-1 373/udp # Legent Corporation
+legent-2 374/tcp # Legent Corporation
+legent-2 374/udp # Legent Corporation
+hassle 375/tcp # Hassle
+hassle 375/udp # Hassle
+nip 376/tcp # Amiga Envoy Network Inquiry Proto
+nip 376/udp # Amiga Envoy Network Inquiry Proto
+tnETOS 377/tcp # NEC Corporation
+tnETOS 377/udp # NEC Corporation
+dsETOS 378/tcp # NEC Corporation
+dsETOS 378/udp # NEC Corporation
+is99c 379/tcp # TIA/EIA/IS-99 modem client
+is99c 379/udp # TIA/EIA/IS-99 modem client
+is99s 380/tcp # TIA/EIA/IS-99 modem server
+is99s 380/udp # TIA/EIA/IS-99 modem server
+hp-collector 381/tcp # hp performance data collector
+hp-collector 381/udp # hp performance data collector
+hp-managed-node 382/tcp # hp performance data managed node
+hp-managed-node 382/udp # hp performance data managed node
+hp-alarm-mgr 383/tcp # hp performance data alarm manager
+hp-alarm-mgr 383/udp # hp performance data alarm manager
+arns 384/tcp # A Remote Network Server System
+arns 384/udp # A Remote Network Server System
+ibm-app 385/tcp # IBM Application
+ibm-app 385/tcp # IBM Application
+asa 386/tcp # ASA Message Router Object Def.
+asa 386/udp # ASA Message Router Object Def.
+aurp 387/tcp # Appletalk Update-Based Routing Pro.
+aurp 387/udp # Appletalk Update-Based Routing Pro.
+unidata-ldm 388/tcp # Unidata LDM Version 4
+unidata-ldm 388/udp # Unidata LDM Version 4
+ldap 389/tcp # Lightweight Directory Access Protocol
+ldap 389/udp # Lightweight Directory Access Protocol
+uis 390/tcp # UIS
+uis 390/udp # UIS
+synotics-relay 391/tcp # SynOptics SNMP Relay Port
+synotics-relay 391/udp # SynOptics SNMP Relay Port
+synotics-broker 392/tcp # SynOptics Port Broker Port
+synotics-broker 392/udp # SynOptics Port Broker Port
+dis 393/tcp # Data Interpretation System
+dis 393/udp # Data Interpretation System
+embl-ndt 394/tcp # EMBL Nucleic Data Transfer
+embl-ndt 394/udp # EMBL Nucleic Data Transfer
+netcp 395/tcp # NETscout Control Protocol
+netcp 395/udp # NETscout Control Protocol
+netware-ip 396/tcp # Novell Netware over IP
+netware-ip 396/udp # Novell Netware over IP
+mptn 397/tcp # Multi Protocol Trans. Net.
+mptn 397/udp # Multi Protocol Trans. Net.
+kryptolan 398/tcp # Kryptolan
+kryptolan 398/udp # Kryptolan
+work-sol 400/tcp # Workstation Solutions
+work-sol 400/udp # Workstation Solutions
+ups 401/tcp # Uninterruptible Power Supply
+ups 401/udp # Uninterruptible Power Supply
+genie 402/tcp # Genie Protocol
+genie 402/udp # Genie Protocol
+decap 403/tcp # decap
+decap 403/udp # decap
+nced 404/tcp # nced
+nced 404/udp # nced
+ncld 405/tcp # ncld
+ncld 405/udp # ncld
+imsp 406/tcp # Interactive Mail Support Protocol
+imsp 406/udp # Interactive Mail Support Protocol
+timbuktu 407/tcp # Timbuktu
+timbuktu 407/udp # Timbuktu
+prm-sm 408/tcp # Prospero Resource Manager Sys. Man.
+prm-sm 408/udp # Prospero Resource Manager Sys. Man.
+prm-nm 409/tcp # Prospero Resource Manager Node Man.
+prm-nm 409/udp # Prospero Resource Manager Node Man.
+decladebug 410/tcp # DECLadebug Remote Debug Protocol
+decladebug 410/udp # DECLadebug Remote Debug Protocol
+rmt 411/tcp # Remote MT Protocol
+rmt 411/udp # Remote MT Protocol
+synoptics-trap 412/tcp # Trap Convention Port
+synoptics-trap 412/udp # Trap Convention Port
+smsp 413/tcp # SMSP
+smsp 413/udp # SMSP
+infoseek 414/tcp # InfoSeek
+infoseek 414/udp # InfoSeek
+bnet 415/tcp # BNet
+bnet 415/udp # BNet
+silverplatter 416/tcp # Silverplatter
+silverplatter 416/udp # Silverplatter
+onmux 417/tcp # Onmux
+onmux 417/udp # Onmux
+hyper-g 418/tcp # Hyper-G
+hyper-g 418/udp # Hyper-G
+ariel1 419/tcp # Ariel
+ariel1 419/udp # Ariel
+smpte 420/tcp # SMPTE
+smpte 420/udp # SMPTE
+ariel2 421/tcp # Ariel
+ariel2 421/udp # Ariel
+ariel3 422/tcp # Ariel
+ariel3 422/udp # Ariel
+opc-job-start 423/tcp # IBM Operations Planning and Control Start
+opc-job-start 423/udp # IBM Operations Planning and Control Start
+opc-job-track 424/tcp # IBM Operations Planning and Control Track
+opc-job-track 424/udp # IBM Operations Planning and Control Track
+icad-el 425/tcp # ICAD
+icad-el 425/udp # ICAD
+smartsdp 426/tcp # smartsdp
+smartsdp 426/udp # smartsdp
+svrloc 427/tcp # Server Location
+svrloc 427/udp # Server Location
+ocs_cmu 428/tcp # OCS_CMU
+ocs_cmu 428/udp # OCS_CMU
+ocs_amu 429/tcp # OCS_AMU
+ocs_amu 429/udp # OCS_AMU
+utmpsd 430/tcp # UTMPSD
+utmpsd 430/udp # UTMPSD
+utmpcd 431/tcp # UTMPCD
+utmpcd 431/udp # UTMPCD
+iasd 432/tcp # IASD
+iasd 432/udp # IASD
+nnsp 433/tcp # NNSP
+nnsp 433/udp # NNSP
+mobileip-agent 434/tcp # MobileIP-Agent
+mobileip-agent 434/udp # MobileIP-Agent
+mobilip-mn 435/tcp # MobilIP-MN
+mobilip-mn 435/udp # MobilIP-MN
+dna-cml 436/tcp # DNA-CML
+dna-cml 436/udp # DNA-CML
+comscm 437/tcp # comscm
+comscm 437/udp # comscm
+dsfgw 438/tcp # dsfgw
+dsfgw 438/udp # dsfgw
+dasp 439/tcp # dasp Thomas Obermair
+dasp 439/udp # dasp tommy@inlab.m.eunet.de
+sgcp 440/tcp # sgcp
+sgcp 440/udp # sgcp
+decvms-sysmgt 441/tcp # decvms-sysmgt
+decvms-sysmgt 441/udp # decvms-sysmgt
+cvc_hostd 442/tcp # cvc_hostd
+cvc_hostd 442/udp # cvc_hostd
+https 443/tcp # https MCom
+https 443/udp # https MCom
+snpp 444/tcp # Simple Network Paging Protocol
+snpp 444/udp # Simple Network Paging Protocol
+microsoft-ds 445/tcp # Microsoft-DS
+microsoft-ds 445/udp # Microsoft-DS
+ddm-rdb 446/tcp # DDM-RDB
+ddm-rdb 446/udp # DDM-RDB
+ddm-dfm 447/tcp # DDM-RFM
+ddm-dfm 447/udp # DDM-RFM
+ddm-byte 448/tcp # DDM-BYTE
+ddm-byte 448/udp # DDM-BYTE
+as-servermap 449/tcp # AS Server Mapper
+as-servermap 449/udp # AS Server Mapper
+tserver 450/tcp # TServer
+tserver 450/udp # TServer
+exec 512/tcp # remote process execution;
+biff 512/udp # used by mail system to notify users
+login 513/tcp # remote login a la telnet;
+who 513/udp # maintains data bases showing who's
+cmd 514/tcp # like exec, but automatic
+syslog 514/udp
+printer 515/tcp # spooler
+printer 515/udp # spooler
+talk 517/tcp # like tenex link, but across
+talk 517/udp # like tenex link, but across tcp connection is established)
+ntalk 518/tcp
+ntalk 518/udp
+utime 519/tcp # unixtime
+utime 519/udp # unixtime
+efs 520/tcp # extended file name server
+router 520/udp # local routing process (on site);
+timed 525/tcp # timeserver
+timed 525/udp # timeserver
+tempo 526/tcp # newdate
+tempo 526/udp # newdate
+courier 530/tcp # rpc
+courier 530/udp # rpc
+conference 531/tcp # chat
+conference 531/udp # chat
+netnews 532/tcp # readnews
+netnews 532/udp # readnews
+netwall 533/tcp # for emergency broadcasts
+netwall 533/udp # for emergency broadcasts
+apertus-ldp 539/tcp # Apertus Technologies Load Determination
+apertus-ldp 539/udp # Apertus Technologies Load Determination
+uucp 540/tcp # uucpd
+uucp 540/udp # uucpd
+uucp-rlogin 541/tcp # uucp-rlogin Stuart Lynne
+uucp-rlogin 541/udp # uucp-rlogin sl@wimsey.com
+klogin 543/tcp
+klogin 543/udp
+kshell 544/tcp # krcmd
+kshell 544/udp # krcmd
+new-rwho 550/tcp # new-who
+new-rwho 550/udp # new-who
+dsf 555/tcp
+dsf 555/udp
+remotefs 556/tcp # rfs server
+remotefs 556/udp # rfs server
+rmonitor 560/tcp # rmonitord
+rmonitor 560/udp # rmonitord
+monitor 561/tcp
+monitor 561/udp
+chshell 562/tcp # chcmd
+chshell 562/udp # chcmd
+9pfs 564/tcp # plan 9 file service
+9pfs 564/udp # plan 9 file service
+whoami 565/tcp # whoami
+whoami 565/udp # whoami
+meter 570/tcp # demon
+meter 570/udp # demon
+meter 571/tcp # udemon
+meter 571/udp # udemon
+ipcserver 600/tcp # Sun IPC server
+ipcserver 600/udp # Sun IPC server
+nqs 607/tcp # nqs
+nqs 607/udp # nqs
+urm 606/tcp # Cray Unified Resource Manager
+urm 606/udp # Cray Unified Resource Manager
+sift-uft 608/tcp # Sender-Initiated/Unsolicited File Transfer
+sift-uft 608/udp # Sender-Initiated/Unsolicited File Transfer
+npmp-trap 609/tcp # npmp-trap
+npmp-trap 609/udp # npmp-trap
+npmp-local 610/tcp # npmp-local
+npmp-local 610/udp # npmp-local
+npmp-gui 611/tcp # npmp-gui
+npmp-gui 611/udp # npmp-gui
+ginad 634/tcp # ginad
+ginad 634/udp # ginad
+mdqs 666/tcp
+mdqs 666/udp
+doom 666/tcp # doom Id Software
+doom 666/tcp # doom Id Software
+elcsd 704/tcp # errlog copy/server daemon
+elcsd 704/udp # errlog copy/server daemon
+entrustmanager 709/tcp # EntrustManager
+entrustmanager 709/udp # EntrustManager
+netviewdm1 729/tcp # IBM NetView DM/6000 Server/Client
+netviewdm1 729/udp # IBM NetView DM/6000 Server/Client
+netviewdm2 730/tcp # IBM NetView DM/6000 send/tcp
+netviewdm2 730/udp # IBM NetView DM/6000 send/tcp
+netviewdm3 731/tcp # IBM NetView DM/6000 receive/tcp
+netviewdm3 731/udp # IBM NetView DM/6000 receive/tcp
+netgw 741/tcp # netGW
+netgw 741/udp # netGW
+netrcs 742/tcp # Network based Rev. Cont. Sys.
+netrcs 742/udp # Network based Rev. Cont. Sys.
+flexlm 744/tcp # Flexible License Manager
+flexlm 744/udp # Flexible License Manager
+fujitsu-dev 747/tcp # Fujitsu Device Control
+fujitsu-dev 747/udp # Fujitsu Device Control
+ris-cm 748/tcp # Russell Info Sci Calendar Manager
+ris-cm 748/udp # Russell Info Sci Calendar Manager
+kerberos-adm 749/tcp # kerberos administration
+kerberos-adm 749/udp # kerberos administration
+rfile 750/tcp
+loadav 750/udp
+pump 751/tcp
+pump 751/udp
+qrh 752/tcp
+qrh 752/udp
+rrh 753/tcp
+rrh 753/udp
+tell 754/tcp # send
+tell 754/udp # send
+nlogin 758/tcp
+nlogin 758/udp
+con 759/tcp
+con 759/udp
+ns 760/tcp
+ns 760/udp
+rxe 761/tcp
+rxe 761/udp
+quotad 762/tcp
+quotad 762/udp
+cycleserv 763/tcp
+cycleserv 763/udp
+omserv 764/tcp
+omserv 764/udp
+webster 765/tcp
+webster 765/udp
+phonebook 767/tcp # phone
+phonebook 767/udp # phone
+vid 769/tcp
+vid 769/udp
+cadlock 770/tcp
+cadlock 770/udp
+rtip 771/tcp
+rtip 771/udp
+cycleserv2 772/tcp
+cycleserv2 772/udp
+submit 773/tcp
+notify 773/udp
+rpasswd 774/tcp
+acmaint_dbd 774/udp
+entomb 775/tcp
+acmaint_transd 775/udp
+wpages 776/tcp
+wpages 776/udp
+wpgs 780/tcp
+wpgs 780/udp
+concert 786/tcp # Concert
+concert 786/udp # Concert
+mdbs_daemon 800/tcp
+mdbs_daemon 800/udp
+device 801/tcp
+device 801/udp
+xtreelic 996/tcp # Central Point Software
+xtreelic 996/udp # Central Point Software
+maitrd 997/tcp
+maitrd 997/udp
+busboy 998/tcp
+puparp 998/udp
+garcon 999/tcp
+applix 999/udp # Applix ac
+puprouter 999/tcp
+puprouter 999/udp
+cadlock 1000/tcp
+ock 1000/udp
diff --git a/contrib/ipfilter/fil.c b/contrib/ipfilter/fil.c
new file mode 100644
index 000000000000..de776f9fc5c8
--- /dev/null
+++ b/contrib/ipfilter/fil.c
@@ -0,0 +1,762 @@
+/*
+ * (C)opyright 1993-1996 by Darren Reed.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that this notice is preserved and due credit is given
+ * to the original author and the contributors.
+ */
+#if !defined(lint) && defined(LIBC_SCCS)
+static char sccsid[] = "@(#)fil.c 1.36 6/5/96 (C) 1993-1996 Darren Reed";
+static char rcsid[] = "$Id: fil.c,v 2.0.1.4 1997/02/04 13:59:41 darrenr Exp $";
+#endif
+
+#include <sys/errno.h>
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/file.h>
+#include <sys/ioctl.h>
+#if defined(_KERNEL) || defined(KERNEL)
+# include <sys/systm.h>
+#else
+# include <stdio.h>
+# include <string.h>
+#endif
+#include <sys/uio.h>
+#if !defined(__SVR4) && !defined(__svr4__)
+# include <sys/mbuf.h>
+#else
+# include <sys/byteorder.h>
+# include <sys/dditypes.h>
+# include <sys/stream.h>
+#endif
+#include <sys/protosw.h>
+#include <sys/socket.h>
+#include <net/if.h>
+#ifdef sun
+# include <net/af.h>
+#endif
+#include <net/route.h>
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/ip_var.h>
+#include <netinet/tcp.h>
+#include <netinet/udp.h>
+#include <netinet/tcpip.h>
+#include <netinet/ip_icmp.h>
+#include "ip_fil.h"
+#include "ip_compat.h"
+#include "ip_nat.h"
+#include "ip_frag.h"
+#include "ip_state.h"
+#ifndef MIN
+#define MIN(a,b) (((a)<(b))?(a):(b))
+#endif
+
+#ifndef _KERNEL
+#include "ipf.h"
+extern int opts;
+extern void debug(), verbose();
+
+#define FR_IFVERBOSE(ex,second,verb_pr) if (ex) { verbose verb_pr; second; }
+#define FR_IFDEBUG(ex,second,verb_pr) if (ex) { debug verb_pr; second; }
+#define FR_VERBOSE(verb_pr) verbose verb_pr
+#define FR_DEBUG(verb_pr) debug verb_pr
+#define FR_SCANLIST(p, ip, fi, m) fr_scanlist(p, ip, fi)
+# if SOLARIS
+# define bcmp memcmp
+# endif
+#else
+#define FR_IFVERBOSE(ex,second,verb_pr) ;
+#define FR_IFDEBUG(ex,second,verb_pr) ;
+#define FR_VERBOSE(verb_pr)
+#define FR_DEBUG(verb_pr)
+#define FR_SCANLIST(p, ip, fi, m) fr_scanlist(p, ip, fi, m)
+extern int send_reset();
+# if SOLARIS
+extern int icmp_error(), ipfr_fastroute();
+extern kmutex_t ipf_mutex, ipl_mutex;
+# else
+extern void ipfr_fastroute();
+# endif
+extern int ipl_unreach, ipllog();
+#endif
+
+#if SOLARIS
+# define SEND_RESET(ip, if, q) send_reset(ip, qif, q)
+# define ICMP_ERROR(b, ip, t, c, if, src) \
+ icmp_error(b, ip, t, c, if, src)
+#else
+# define SEND_RESET(ip, if, q) send_reset(ip)
+# if BSD < 199103
+# define ICMP_ERROR(b, ip, t, c, if, src) \
+ icmp_error(mtod(b, ip_t *), t, c, if, src)
+# else
+# define ICMP_ERROR(b, ip, t, c, if, src) \
+ icmp_error(b, t, c, (src).s_addr, if)
+# endif
+#endif
+
+struct filterstats frstats[2] = {{0,0,0,0,0},{0,0,0,0,0}};
+struct frentry *ipfilter[2][2] = { { NULL, NULL }, { NULL, NULL } },
+ *ipacct[2][2] = { { NULL, NULL }, { NULL, NULL } };
+int fr_flags = 0, fr_active = 0;
+
+fr_info_t frcache[2];
+
+
+/*
+ * bit values for identifying presence of individual IP options
+ */
+struct optlist ipopts[20] = {
+ { IPOPT_NOP, 0x000001 },
+ { IPOPT_RR, 0x000002 },
+ { IPOPT_ZSU, 0x000004 },
+ { IPOPT_MTUP, 0x000008 },
+ { IPOPT_MTUR, 0x000010 },
+ { IPOPT_ENCODE, 0x000020 },
+ { IPOPT_TS, 0x000040 },
+ { IPOPT_TR, 0x000080 },
+ { IPOPT_SECURITY, 0x000100 },
+ { IPOPT_LSRR, 0x000200 },
+ { IPOPT_E_SEC, 0x000400 },
+ { IPOPT_CIPSO, 0x000800 },
+ { IPOPT_SATID, 0x001000 },
+ { IPOPT_SSRR, 0x002000 },
+ { IPOPT_ADDEXT, 0x004000 },
+ { IPOPT_VISA, 0x008000 },
+ { IPOPT_IMITD, 0x010000 },
+ { IPOPT_EIP, 0x020000 },
+ { IPOPT_FINN, 0x040000 },
+ { 0, 0x000000 }
+};
+
+/*
+ * bit values for identifying presence of individual IP security options
+ */
+struct optlist secopt[8] = {
+ { IPSO_CLASS_RES4, 0x01 },
+ { IPSO_CLASS_TOPS, 0x02 },
+ { IPSO_CLASS_SECR, 0x04 },
+ { IPSO_CLASS_RES3, 0x08 },
+ { IPSO_CLASS_CONF, 0x10 },
+ { IPSO_CLASS_UNCL, 0x20 },
+ { IPSO_CLASS_RES2, 0x40 },
+ { IPSO_CLASS_RES1, 0x80 }
+};
+
+
+/*
+ * compact the IP header into a structure which contains just the info.
+ * which is useful for comparing IP headers with.
+ */
+void fr_makefrip(hlen, ip, fin)
+int hlen;
+ip_t *ip;
+fr_info_t *fin;
+{
+ struct optlist *op;
+ tcphdr_t *tcp;
+ fr_ip_t *fi = &fin->fin_fi;
+ u_short optmsk = 0, secmsk = 0, auth = 0;
+ int i, mv, ol, off;
+ u_char *s, opt;
+
+ fin->fin_fr = NULL;
+ fin->fin_tcpf = 0;
+ fin->fin_data[0] = 0;
+ fin->fin_data[1] = 0;
+ fin->fin_rule = -1;
+#ifdef _KERNEL
+ fin->fin_icode = ipl_unreach;
+#endif
+ fi->fi_v = ip->ip_v;
+ fi->fi_tos = ip->ip_tos;
+ fin->fin_hlen = hlen;
+ fin->fin_dlen = ip->ip_len - hlen;
+ tcp = (tcphdr_t *)((char *)ip + hlen);
+ fin->fin_dp = (void *)tcp;
+ (*(((u_short *)fi) + 1)) = (*(((u_short *)ip) + 4));
+ (*(((u_long *)fi) + 1)) = (*(((u_long *)ip) + 3));
+ (*(((u_long *)fi) + 2)) = (*(((u_long *)ip) + 4));
+
+ fi->fi_fl = (hlen > sizeof(struct ip)) ? FI_OPTIONS : 0;
+ off = (ip->ip_off & 0x1fff) << 3;
+ if (ip->ip_off & 0x3fff)
+ fi->fi_fl |= FI_FRAG;
+ switch (ip->ip_p)
+ {
+ case IPPROTO_ICMP :
+ if ((!IPMINLEN(ip, icmp) && !off) ||
+ (off && off < sizeof(struct icmp)))
+ fi->fi_fl |= FI_SHORT;
+ if (fin->fin_dlen > 1)
+ fin->fin_data[0] = *(u_short *)tcp;
+ break;
+ case IPPROTO_TCP :
+ fi->fi_fl |= FI_TCPUDP;
+ if ((!IPMINLEN(ip, tcphdr) && !off) ||
+ (off && off < sizeof(struct tcphdr)))
+ fi->fi_fl |= FI_SHORT;
+ if (!(fi->fi_fl & FI_SHORT) && !off)
+ fin->fin_tcpf = tcp->th_flags;
+ goto getports;
+ case IPPROTO_UDP :
+ fi->fi_fl |= FI_TCPUDP;
+ if ((!IPMINLEN(ip, udphdr) && !off) ||
+ (off && off < sizeof(struct udphdr)))
+ fi->fi_fl |= FI_SHORT;
+getports:
+ if (!off && (fin->fin_dlen > 3)) {
+ fin->fin_data[0] = ntohs(tcp->th_sport);
+ fin->fin_data[1] = ntohs(tcp->th_dport);
+ }
+ break;
+ default :
+ break;
+ }
+
+
+ for (s = (u_char *)(ip + 1), hlen -= sizeof(*ip); hlen; ) {
+ if (!(opt = *s))
+ break;
+ ol = (opt == IPOPT_NOP) ? 1 : (int)*(s+1);
+ if (opt > 1 && (ol < 2 || ol > hlen))
+ break;
+ for (i = 9, mv = 4; mv >= 0; ) {
+ op = ipopts + i;
+ if (opt == (u_char)op->ol_val) {
+ optmsk |= op->ol_bit;
+ if (opt == IPOPT_SECURITY) {
+ struct optlist *sp;
+ u_char sec;
+ int j, m;
+
+ sec = *(s + 2); /* classification */
+ for (j = 3, m = 2; m >= 0; ) {
+ sp = secopt + j;
+ if (sec == sp->ol_val) {
+ secmsk |= sp->ol_bit;
+ auth = *(s + 3);
+ auth *= 256;
+ auth += *(s + 4);
+ break;
+ }
+ if (sec < sp->ol_val)
+ j -= m--;
+ else
+ j += m--;
+ }
+ }
+ break;
+ }
+ if (opt < op->ol_val)
+ i -= mv--;
+ else
+ i += mv--;
+ }
+ hlen -= ol;
+ s += ol;
+ }
+ if (auth && !(auth & 0x0100))
+ auth &= 0xff00;
+ fi->fi_optmsk = optmsk;
+ fi->fi_secmsk = secmsk;
+ fi->fi_auth = auth;
+}
+
+
+/*
+ * check an IP packet for TCP/UDP characteristics such as ports and flags.
+ */
+int fr_tcpudpchk(fr, fin)
+frentry_t *fr;
+fr_info_t *fin;
+{
+ register u_short po, tup;
+ register char i;
+ register int err = 1;
+
+ /*
+ * Both ports should *always* be in the first fragment.
+ * So far, I cannot find any cases where they can not be.
+ *
+ * compare destination ports
+ */
+ if ((i = (int)fr->fr_dcmp)) {
+ po = fr->fr_dport;
+ tup = fin->fin_data[1];
+ /*
+ * Do opposite test to that required and
+ * continue if that succeeds.
+ */
+ if (!--i && tup != po) /* EQUAL */
+ err = 0;
+ else if (!--i && tup == po) /* NOTEQUAL */
+ err = 0;
+ else if (!--i && tup >= po) /* LESSTHAN */
+ err = 0;
+ else if (!--i && tup <= po) /* GREATERTHAN */
+ err = 0;
+ else if (!--i && tup > po) /* LT or EQ */
+ err = 0;
+ else if (!--i && tup < po) /* GT or EQ */
+ err = 0;
+ else if (!--i && /* Out of range */
+ (tup >= po && tup <= fr->fr_dtop))
+ err = 0;
+ else if (!--i && /* In range */
+ (tup <= po || tup >= fr->fr_dtop))
+ err = 0;
+ }
+ /*
+ * compare source ports
+ */
+ if (err && (i = (int)fr->fr_scmp)) {
+ po = fr->fr_sport;
+ tup = fin->fin_data[0];
+ if (!--i && tup != po)
+ err = 0;
+ else if (!--i && tup == po)
+ err = 0;
+ else if (!--i && tup >= po)
+ err = 0;
+ else if (!--i && tup <= po)
+ err = 0;
+ else if (!--i && tup > po)
+ err = 0;
+ else if (!--i && tup < po)
+ err = 0;
+ else if (!--i && /* Out of range */
+ (tup >= po && tup <= fr->fr_stop))
+ err = 0;
+ else if (!--i && /* In range */
+ (tup <= po || tup >= fr->fr_stop))
+ err = 0;
+ }
+
+ /*
+ * If we don't have all the TCP/UDP header, then how can we
+ * expect to do any sort of match on it ? If we were looking for
+ * TCP flags, then NO match. If not, then match (which should
+ * satisfy the "short" class too).
+ */
+ if (err && (fin->fin_fi.fi_p == IPPROTO_TCP)) {
+ if (fin->fin_fi.fi_fl & FI_SHORT)
+ return !(fr->fr_tcpf | fr->fr_tcpfm);
+ /*
+ * Match the flags ? If not, abort this match.
+ */
+ if (fr->fr_tcpf &&
+ fr->fr_tcpf != (fin->fin_tcpf & fr->fr_tcpfm)) {
+ FR_DEBUG(("f. %#x & %#x != %#x\n", fin->fin_tcpf,
+ fr->fr_tcpfm, fr->fr_tcpf));
+ err = 0;
+ }
+ }
+ return err;
+}
+
+/*
+ * Check the input/output list of rules for a match and result.
+ * Could be per interface, but this gets real nasty when you don't have
+ * kernel sauce.
+ */
+int fr_scanlist(pass, ip, fin, m)
+int pass;
+ip_t *ip;
+register fr_info_t *fin;
+void *m;
+{
+ register struct frentry *fr;
+ register fr_ip_t *fi = &fin->fin_fi;
+ int rulen, portcmp = 0, off;
+
+ fr = fin->fin_fr;
+ fin->fin_fr = NULL;
+ fin->fin_rule = 0;
+ off = ip->ip_off & 0x1fff;
+ pass |= (fi->fi_fl << 20);
+
+ if ((fi->fi_fl & FI_TCPUDP) && (fin->fin_dlen > 3) && !off)
+ portcmp = 1;
+
+ for (rulen = 0; fr; fr = fr->fr_next, rulen++) {
+ /*
+ * In all checks below, a null (zero) value in the
+ * filter struture is taken to mean a wildcard.
+ *
+ * check that we are working for the right interface
+ */
+#ifdef _KERNEL
+ if (fr->fr_ifa && fr->fr_ifa != fin->fin_ifp)
+ continue;
+#else
+ if (opts & (OPT_VERBOSE|OPT_DEBUG))
+ printf("\n");
+ FR_VERBOSE(("%c", (pass & FR_PASS) ? 'p' : 'b'));
+ if (fin->fin_ifp && *fr->fr_ifname &&
+ strcasecmp((char *)fin->fin_ifp, fr->fr_ifname))
+ continue;
+ FR_VERBOSE((":i"));
+#endif
+ {
+ register u_long *ld, *lm, *lip;
+ register int i;
+
+ lip = (u_long *)fi;
+ lm = (u_long *)&fr->fr_mip;
+ ld = (u_long *)&fr->fr_ip;
+ i = ((lip[0] & lm[0]) != ld[0]);
+ FR_IFDEBUG(i,continue,("0. %#08x & %#08x != %#08x\n",
+ lip[0], lm[0], ld[0]));
+ i |= ((lip[1] & lm[1]) != ld[1]);
+ FR_IFDEBUG(i,continue,("1. %#08x & %#08x != %#08x\n",
+ lip[1], lm[1], ld[1]));
+ i |= ((lip[2] & lm[2]) != ld[2]);
+ FR_IFDEBUG(i,continue,("2. %#08x & %#08x != %#08x\n",
+ lip[2], lm[2], ld[2]));
+ i |= ((lip[3] & lm[3]) != ld[3]);
+ FR_IFDEBUG(i,continue,("3. %#08x & %#08x != %#08x\n",
+ lip[3], lm[3], ld[3]));
+ i |= ((lip[4] & lm[4]) != ld[4]);
+ FR_IFDEBUG(i,continue,("4. %#08x & %#08x != %#08x\n",
+ lip[4], lm[4], ld[4]));
+ if (i)
+ continue;
+ }
+
+ /*
+ * If a fragment, then only the first has what we're looking
+ * for here...
+ */
+ if (fi->fi_fl & FI_TCPUDP) {
+ if (portcmp) {
+ if (!fr_tcpudpchk(fr, fin))
+ continue;
+ } else if (fr->fr_dcmp || fr->fr_scmp || fr->fr_tcpf ||
+ fr->fr_tcpfm)
+ continue;
+ } else if (fi->fi_p == IPPROTO_ICMP) {
+ if (!off && (fin->fin_dlen > 1)) {
+ if ((fin->fin_data[0] & fr->fr_icmpm) !=
+ fr->fr_icmp) {
+ FR_DEBUG(("i. %#x & %#x != %#x\n",
+ fin->fin_data[0],
+ fr->fr_icmpm, fr->fr_icmp));
+ continue;
+ }
+ } else if (fr->fr_icmpm || fr->fr_icmp)
+ continue;
+ }
+ FR_VERBOSE(("*"));
+ /*
+ * Just log this packet...
+ */
+ pass = fr->fr_flags;
+ if ((pass & FR_CALLNOW) && fr->fr_func)
+ pass = (*fr->fr_func)(pass, ip, fin);
+#ifdef IPFILTER_LOG
+ if ((pass & FR_LOGMASK) == FR_LOG) {
+ if (!ipllog(fr->fr_flags, ip, fin, m))
+ frstats[fin->fin_out].fr_skip++;
+ frstats[fin->fin_out].fr_pkl++;
+ }
+#endif /* IPFILTER_LOG */
+ FR_DEBUG(("pass %#x\n", pass));
+ fr->fr_hits++;
+ if (pass & FR_ACCOUNT)
+ fr->fr_bytes += ip->ip_len;
+ else
+ fin->fin_icode = fr->fr_icode;
+ fin->fin_rule = rulen;
+ fin->fin_fr = fr;
+ if (pass & FR_QUICK)
+ break;
+ }
+ return pass;
+}
+
+
+/*
+ * frcheck - filter check
+ * check using source and destination addresses/pors in a packet whether
+ * or not to pass it on or not.
+ */
+int fr_check(ip, hlen, ifp, out
+#ifdef _KERNEL
+# if SOLARIS
+, qif, q, mp)
+qif_t *qif;
+queue_t *q;
+mblk_t **mp;
+# else
+, mp)
+struct mbuf **mp;
+# endif
+#else
+)
+#endif
+ip_t *ip;
+int hlen;
+struct ifnet *ifp;
+int out;
+{
+ /*
+ * The above really sucks, but short of writing a diff
+ */
+ fr_info_t frinfo, *fc;
+ register fr_info_t *fin = &frinfo;
+ frentry_t *fr = NULL;
+ int pass, changed;
+
+#if !defined(__SVR4) && !defined(__svr4__) && defined(_KERNEL)
+ register struct mbuf *m = *mp;
+ struct mbuf *mc = NULL;
+
+ if ((ip->ip_p == IPPROTO_TCP || ip->ip_p == IPPROTO_UDP ||
+ ip->ip_p == IPPROTO_ICMP)) {
+ register int up = MIN(hlen + 8, ip->ip_len);
+
+ if (up > m->m_len) {
+ if ((*mp = m_pullup(m, up)) == 0) {
+ frstats[out].fr_pull[1]++;
+ return -1;
+ } else {
+ frstats[out].fr_pull[0]++;
+ m = *mp;
+ ip = mtod(m, struct ip *);
+ }
+ }
+ }
+#endif
+#if SOLARIS && defined(_KERNEL)
+ mblk_t *mc = NULL, *m = qif->qf_m;
+#endif
+ fr_makefrip(hlen, ip, fin);
+ fin->fin_ifp = ifp;
+ fin->fin_out = out;
+
+ MUTEX_ENTER(&ipf_mutex);
+ if (!out) {
+ changed = ip_natin(ip, hlen, fin);
+ if ((fin->fin_fr = ipacct[0][fr_active]) &&
+ (FR_SCANLIST(FR_NOMATCH, ip, fin, m) & FR_ACCOUNT))
+ frstats[0].fr_acct++;
+ }
+
+ if ((pass = ipfr_knownfrag(ip, fin))) {
+ if ((pass & FR_KEEPSTATE)) {
+ if (fr_addstate(ip, fin, pass) == -1)
+ frstats[out].fr_bads++;
+ else
+ frstats[out].fr_ads++;
+ }
+ } else if ((pass = fr_checkstate(ip, fin))) {
+ if ((pass & FR_KEEPFRAG)) {
+ if (fin->fin_fi.fi_fl & FI_FRAG) {
+ if (ipfr_newfrag(ip, fin, pass) == -1)
+ frstats[out].fr_bnfr++;
+ else
+ frstats[out].fr_nfr++;
+ } else
+ frstats[out].fr_cfr++;
+ }
+ } else {
+ fc = frcache + out;
+ if (fc->fin_fr && !bcmp((char *)fin, (char *)fc, FI_CSIZE)) {
+ /*
+ * copy cached data so we can unlock the mutex
+ * earlier.
+ */
+ bcopy((char *)fc, (char *)fin, sizeof(*fin));
+ frstats[out].fr_chit++;
+ pass = fin->fin_fr->fr_flags;
+ } else {
+ pass = FR_NOMATCH;
+ if ((fin->fin_fr = ipfilter[out][fr_active]))
+ pass = FR_SCANLIST(FR_NOMATCH, ip, fin, m);
+ bcopy((char *)fin, (char *)fc, FI_CSIZE);
+ if (pass & FR_NOMATCH) {
+ frstats[out].fr_nom++;
+#ifdef NOMATCH
+ pass |= NOMATCH;
+#endif
+ }
+ }
+ fr = fin->fin_fr;
+
+ if ((pass & FR_KEEPFRAG)) {
+ if (fin->fin_fi.fi_fl & FI_FRAG) {
+ if (ipfr_newfrag(ip, fin, pass) == -1)
+ frstats[out].fr_bnfr++;
+ else
+ frstats[out].fr_nfr++;
+ } else
+ frstats[out].fr_cfr++;
+ }
+ if (pass & FR_KEEPSTATE) {
+ if (fr_addstate(ip, fin, pass) == -1)
+ frstats[out].fr_bads++;
+ else
+ frstats[out].fr_ads++;
+ }
+ }
+
+ if (fr && fr->fr_func)
+ pass = (*fr->fr_func)(pass, ip, fin);
+
+ if (out) {
+ if ((fin->fin_fr = ipacct[1][fr_active]) &&
+ (FR_SCANLIST(FR_NOMATCH, ip, fin, m) & FR_ACCOUNT))
+ frstats[1].fr_acct++;
+ fin->fin_fr = NULL;
+ changed = ip_natout(ip, hlen, fin);
+ }
+ fin->fin_fr = fr;
+ MUTEX_EXIT(&ipf_mutex);
+
+#ifdef IPFILTER_LOG
+ if ((fr_flags & FF_LOGGING) || (pass & FR_LOGMASK)) {
+ if ((fr_flags & FF_LOGNOMATCH) && (pass & FR_NOMATCH)) {
+ pass |= FF_LOGNOMATCH;
+ frstats[out].fr_npkl++;
+ goto logit;
+ } else if (((pass & FR_LOGMASK) == FR_LOGP) ||
+ ((pass & FR_PASS) && (fr_flags & FF_LOGPASS))) {
+ if ((pass & FR_LOGMASK) != FR_LOGP)
+ pass |= FF_LOGPASS;
+ frstats[out].fr_ppkl++;
+ goto logit;
+ } else if (((pass & FR_LOGMASK) == FR_LOGB) ||
+ ((pass & FR_BLOCK) && (fr_flags & FF_LOGBLOCK))) {
+ if ((pass & FR_LOGMASK) != FR_LOGB)
+ pass |= FF_LOGBLOCK;
+ frstats[out].fr_bpkl++;
+logit:
+ if (!ipllog(pass, ip, fin, m)) {
+ frstats[out].fr_skip++;
+ if ((pass & (FR_PASS|FR_LOGORBLOCK)) ==
+ (FR_PASS|FR_LOGORBLOCK))
+ pass ^= FR_PASS|FR_BLOCK;
+ }
+ }
+ }
+#endif /* IPFILTER_LOG */
+
+ if (pass & FR_PASS)
+ frstats[out].fr_pass++;
+ else if (pass & FR_BLOCK) {
+ frstats[out].fr_block++;
+ /*
+ * Should we return an ICMP packet to indicate error
+ * status passing through the packet filter ?
+ */
+#ifdef _KERNEL
+ if (pass & FR_RETICMP) {
+# if SOLARIS
+ ICMP_ERROR(q, ip, ICMP_UNREACH, fin->fin_icode,
+ qif, ip->ip_src);
+# else
+ ICMP_ERROR(m, ip, ICMP_UNREACH, fin->fin_icode,
+ ifp, ip->ip_src);
+ m = NULL; /* freed by icmp_error() */
+# endif
+
+ frstats[0].fr_ret++;
+ } else if ((pass & FR_RETRST) &&
+ !(fin->fin_fi.fi_fl & FI_SHORT)) {
+ if (SEND_RESET(ip, qif, q) == 0)
+ frstats[1].fr_ret++;
+ }
+#else
+ if (pass & FR_RETICMP) {
+ verbose("- ICMP unreachable sent\n");
+ frstats[0].fr_ret++;
+ } else if ((pass & FR_RETRST) &&
+ !(fin->fin_fi.fi_fl & FI_SHORT)) {
+ verbose("- TCP RST sent\n");
+ frstats[1].fr_ret++;
+ }
+#endif
+ }
+#ifdef _KERNEL
+# if !SOLARIS
+ if (pass & FR_DUP)
+ mc = m_copy(m, 0, M_COPYALL);
+ if (fr) {
+ frdest_t *fdp = &fr->fr_tif;
+
+ if ((pass & FR_FASTROUTE) ||
+ (fdp->fd_ifp && fdp->fd_ifp != (struct ifnet *)-1)) {
+ ipfr_fastroute(m, fin, fdp);
+ m = *mp = NULL;
+ pass = 0;
+ }
+ if (mc)
+ ipfr_fastroute(mc, fin, &fr->fr_dif);
+ }
+ if (!(pass & FR_PASS) && m)
+ m_freem(m);
+ return (pass & FR_PASS) ? 0 : -1;
+# else
+ if (pass & FR_DUP)
+ mc = dupmsg(m);
+ if (fr) {
+ frdest_t *fdp = &fr->fr_tif;
+
+ if ((pass & FR_FASTROUTE) ||
+ (fdp->fd_ifp && fdp->fd_ifp != (struct ifnet *)-1)) {
+ ipfr_fastroute(qif, ip, m, mp, fin, fdp);
+ m = *mp = NULL;
+ }
+ if (mc)
+ ipfr_fastroute(qif, ip, mc, mp, fin, &fr->fr_dif);
+ }
+ return (pass & FR_PASS) ? changed : -1;
+# endif
+#else
+ if (pass & FR_NOMATCH)
+ return 1;
+ if (pass & FR_PASS)
+ return 0;
+ return -1;
+#endif
+}
+
+
+#ifdef IPFILTER_LOG
+# if !(defined(_KERNEL))
+static void ipllog()
+{
+ verbose("l");
+}
+# endif
+
+
+int fr_copytolog(buf, len)
+char *buf;
+int len;
+{
+ int clen, tail;
+
+ tail = (iplh >= iplt) ? (iplbuf + IPLLOGSIZE - iplh) : (iplt - iplh);
+ clen = MIN(tail, len);
+ bcopy(buf, iplh, clen);
+ len -= clen;
+ tail -= clen;
+ iplh += clen;
+ buf += clen;
+ if (iplh == iplbuf + IPLLOGSIZE) {
+ iplh = iplbuf;
+ tail = iplt - iplh;
+ }
+ if (len && tail) {
+ clen = MIN(tail, len);
+ bcopy(buf, iplh, clen);
+ len -= clen;
+ iplh += clen;
+ }
+ return len;
+}
+#endif
diff --git a/contrib/ipfilter/fils.c b/contrib/ipfilter/fils.c
new file mode 100644
index 000000000000..249611b25343
--- /dev/null
+++ b/contrib/ipfilter/fils.c
@@ -0,0 +1,366 @@
+/*
+ * (C)opyright 1993-1996 by Darren Reed.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that this notice is preserved and due credit is given
+ * to the original author and the contributors.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#if !defined(__SVR4) && !defined(__svr4__)
+#include <strings.h>
+#endif
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/file.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <stddef.h>
+#include <nlist.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <net/if.h>
+#include "ip_fil.h"
+#include "ip_compat.h"
+#include "ip_nat.h"
+#include "ip_frag.h"
+#include "ip_state.h"
+#include <netdb.h>
+#include <arpa/nameser.h>
+#include <resolv.h>
+#include "ipf.h"
+#include "kmem.h"
+#ifdef __NetBSD__
+#include <paths.h>
+#endif
+
+#if !defined(lint) && defined(LIBC_SCCS)
+static char sccsid[] = "@(#)fils.c 1.21 4/20/96 (C) 1993-1996 Darren Reed";
+static char rcsid[] = "$Id: fils.c,v 2.0.1.2 1997/01/30 10:21:48 darrenr Exp $";
+#endif
+#ifdef _PATH_UNIX
+#define VMUNIX _PATH_UNIX
+#else
+#define VMUNIX "/vmunix"
+#endif
+
+extern char *optarg;
+
+#define PRINTF (void)printf
+#define FPRINTF (void)fprintf
+#define F_IN 0
+#define F_OUT 1
+#define F_AC 2
+static char *filters[4] = { "ipfilter(in)", "ipfilter(out)",
+ "ipacct(in)", "ipacct(out)" };
+
+int opts = 0;
+
+static void showstats(), showfrstates();
+static void showlist(), showipstates();
+
+void Usage(name)
+char *name;
+{
+ fprintf(stderr, "Usage: %s [-afhIiosv] [-d <device>]\n", name);
+ exit(1);
+}
+
+
+int main(argc,argv)
+int argc;
+char *argv[];
+{
+ friostat_t fio;
+ ips_stat_t ipsst;
+ ipfrstat_t ifrst;
+ char c, *name = NULL, *device = IPL_NAME;
+ int fd;
+
+ if (openkmem() == -1)
+ exit(-1);
+
+ (void)setuid(getuid());
+ (void)setgid(getgid());
+
+ while ((c = getopt(argc, argv, "afhIiosvd:")) != -1)
+ {
+ switch (c)
+ {
+ case 'a' :
+ opts |= OPT_ACCNT|OPT_SHOWLIST;
+ break;
+ case 'd' :
+ device = optarg;
+ break;
+ case 'f' :
+ opts |= OPT_FRSTATES;
+ break;
+ case 'h' :
+ opts |= OPT_HITS;
+ break;
+ case 'i' :
+ opts |= OPT_INQUE|OPT_SHOWLIST;
+ break;
+ case 'n' :
+ opts |= OPT_SHOWLINENO;
+ break;
+ case 'I' :
+ opts |= OPT_INACTIVE;
+ break;
+ case 'o' :
+ opts |= OPT_OUTQUE|OPT_SHOWLIST;
+ break;
+ case 's' :
+ opts |= OPT_IPSTATES;
+ break;
+ case 'v' :
+ opts |= OPT_VERBOSE;
+ break;
+ default :
+ Usage(argv[0]);
+ break;
+ }
+ }
+
+ if ((fd = open(device, O_RDONLY)) < 0) {
+ perror("open");
+ exit(-1);
+ }
+
+ bzero((char *)&fio, sizeof(fio));
+ bzero((char *)&ipsst, sizeof(ipsst));
+ bzero((char *)&ifrst, sizeof(ifrst));
+
+ if (ioctl(fd, SIOCGETFS, &fio) == -1) {
+ perror("ioctl(SIOCGETFS)");
+ exit(-1);
+ }
+ if ((opts & OPT_IPSTATES) && (ioctl(fd, SIOCGIPST, &ipsst) == -1)) {
+ perror("ioctl(SIOCGIPST)");
+ exit(-1);
+ }
+ if ((opts & OPT_FRSTATES) && (ioctl(fd, SIOCGFRST, &ifrst) == -1)) {
+ perror("ioctl(SIOCGFRST)");
+ exit(-1);
+ }
+
+ if (opts & OPT_VERBOSE)
+ PRINTF("opts %#x name %s\n", opts, name ? name : "<>");
+ if (opts & OPT_SHOWLIST) {
+ showlist(&fio);
+ if((opts & OPT_OUTQUE) && (opts & OPT_INQUE)){
+ opts &= ~OPT_OUTQUE;
+ showlist(&fio);
+ }
+ } else {
+ if (opts & OPT_IPSTATES)
+ showipstates(fd, &ipsst);
+ else if (opts & OPT_FRSTATES)
+ showfrstates(fd, &ifrst);
+ else
+ showstats(fd, &fio);
+ }
+ return 0;
+}
+
+
+/*
+ * read the kernel stats for packets blocked and passed
+ */
+static void showstats(fd, fp)
+int fd;
+struct friostat *fp;
+{
+ int frf = 0;
+
+ if (ioctl(fd, SIOCGETFF, &frf) == -1)
+ perror("ioctl(SIOCGETFF)");
+
+#if SOLARIS
+ PRINTF("dropped packets:\tin %lu\tout %lu\n",
+ fp->f_st[0].fr_drop, fp->f_st[1].fr_drop);
+ PRINTF("non-ip packets:\t\tin %lu\tout %lu\n",
+ fp->f_st[0].fr_notip, fp->f_st[1].fr_notip);
+ PRINTF(" bad packets:\t\tin %lu\tout %lu\n",
+ fp->f_st[0].fr_bad, fp->f_st[1].fr_bad);
+#endif
+ PRINTF(" input packets:\t\tblocked %lu passed %lu nomatch %lu",
+ fp->f_st[0].fr_block, fp->f_st[0].fr_pass,
+ fp->f_st[0].fr_nom);
+ PRINTF(" counted %lu\n", fp->f_st[0].fr_acct);
+ PRINTF("output packets:\t\tblocked %lu passed %lu nomatch %lu",
+ fp->f_st[1].fr_block, fp->f_st[1].fr_pass,
+ fp->f_st[1].fr_nom);
+ PRINTF(" counted %lu\n", fp->f_st[0].fr_acct);
+ PRINTF(" input packets logged:\tblocked %lu passed %lu\n",
+ fp->f_st[0].fr_bpkl, fp->f_st[0].fr_ppkl);
+ PRINTF("output packets logged:\tblocked %lu passed %lu\n",
+ fp->f_st[1].fr_bpkl, fp->f_st[1].fr_ppkl);
+ PRINTF(" packets logged:\tinput %lu output %lu\n",
+ fp->f_st[0].fr_pkl, fp->f_st[1].fr_pkl);
+ PRINTF(" log failures:\t\tinput %lu output %lu\n",
+ fp->f_st[0].fr_skip, fp->f_st[1].fr_skip);
+ PRINTF("fragment state(in):\tkept %lu\tlost %lu\n",
+ fp->f_st[0].fr_nfr, fp->f_st[0].fr_bnfr);
+ PRINTF("fragment state(out):\tkept %lu\tlost %lu\n",
+ fp->f_st[1].fr_nfr, fp->f_st[1].fr_bnfr);
+ PRINTF("packet state(in):\tkept %lu\tlost %lu\n",
+ fp->f_st[0].fr_ads, fp->f_st[0].fr_bads);
+ PRINTF("packet state(out):\tkept %lu\tlost %lu\n",
+ fp->f_st[1].fr_ads, fp->f_st[1].fr_bads);
+ PRINTF("ICMP replies:\t%lu\tTCP RSTs sent:\t%lu\n",
+ fp->f_st[0].fr_ret, fp->f_st[1].fr_ret);
+ PRINTF("Result cache hits(in):\t%lu\t(out):\t%lu\n",
+ fp->f_st[0].fr_chit, fp->f_st[1].fr_chit);
+ PRINTF("IN Pullups succeeded:\t%lu\tfailed:\t%lu\n",
+ fp->f_st[0].fr_pull[0], fp->f_st[0].fr_pull[1]);
+ PRINTF("OUT Pullups succeeded:\t%lu\tfailed:\t%lu\n",
+ fp->f_st[1].fr_pull[0], fp->f_st[1].fr_pull[1]);
+
+ PRINTF("Packet log flags set: (%#x)\n", frf);
+ if (frf & FF_LOGPASS)
+ PRINTF("\tpackets passed through filter\n");
+ if (frf & FF_LOGBLOCK)
+ PRINTF("\tpackets blocked by filter\n");
+ if (!frf)
+ PRINTF("\tnone\n");
+}
+
+/*
+ * print out filter rule list
+ */
+static void showlist(fiop)
+struct friostat *fiop;
+{
+ struct frentry fb;
+ struct frentry *fp = NULL;
+ int i, set, n;
+
+ set = fiop->f_active;
+ if (opts & OPT_INACTIVE)
+ set = 1 - set;
+ if (opts & OPT_ACCNT) {
+ i = F_AC;
+ if (opts & OPT_OUTQUE) {
+ fp = (struct frentry *)fiop->f_acctout[set];
+ i++;
+ } else if (opts & OPT_INQUE)
+ fp = (struct frentry *)fiop->f_acctin[set];
+ } else if (opts & OPT_OUTQUE) {
+ i = F_OUT;
+ fp = (struct frentry *)fiop->f_fout[set];
+ } else if (opts & OPT_INQUE) {
+ i = F_IN;
+ fp = (struct frentry *)fiop->f_fin[set];
+ } else
+ return;
+ if (opts & OPT_VERBOSE)
+ FPRINTF(stderr, "showlist:opts %#x i %d\n", opts, i);
+
+ if (opts & OPT_VERBOSE)
+ PRINTF("fp %#x set %d\n", (u_int)fp, set);
+ if (!fp) {
+ FPRINTF(stderr, "empty list for %s%s\n",
+ (opts & OPT_INACTIVE) ? "inactive " : "", filters[i]);
+ return;
+ }
+
+ for (n = 1; fp; n++) {
+ if (kmemcpy((char *)&fb, (u_long)fp, sizeof(fb)) == -1) {
+ perror("kmemcpy");
+ return;
+ }
+ fp = &fb;
+ if (opts & OPT_OUTQUE)
+ fp->fr_flags |= FR_OUTQUE;
+ if (opts & (OPT_HITS|OPT_VERBOSE))
+ PRINTF("%ld ", fp->fr_hits);
+ if (opts & (OPT_ACCNT|OPT_VERBOSE))
+ PRINTF("%ld ", fp->fr_bytes);
+ if (opts & OPT_SHOWLINENO)
+ PRINTF("@%d ", n);
+ printfr(fp);
+ if (opts & OPT_VERBOSE)
+ binprint(fp);
+ fp = fp->fr_next;
+ }
+}
+
+
+static void showipstates(fd, ipsp)
+int fd;
+ips_stat_t *ipsp;
+{
+ ipstate_t *istab[IPSTATE_SIZE], ips;
+ int i;
+
+ PRINTF("IP states added:\n\t%lu TCP\n\t%lu UDP\n\t%lu ICMP\n",
+ ipsp->iss_tcp, ipsp->iss_udp, ipsp->iss_icmp);
+ PRINTF("\t%lu hits\n\t%lu misses\n", ipsp->iss_hits, ipsp->iss_miss);
+ PRINTF("\t%lu maximum\n\t%lu no memory\n",
+ ipsp->iss_max, ipsp->iss_nomem);
+ PRINTF("\t%lu active\n\t%lu expired\n\t%lu closed\n",
+ ipsp->iss_active, ipsp->iss_expire, ipsp->iss_fin);
+ if (kmemcpy((char *)istab, (u_long)ipsp->iss_table, sizeof(istab)))
+ return;
+ for (i = 0; i < IPSTATE_SIZE; i++)
+ while (istab[i]) {
+ if (kmemcpy(&ips, istab[i], sizeof(ips)) == -1)
+ break;
+ PRINTF("%s -> ", inet_ntoa(ips.is_src));
+ PRINTF("%s age %d pass %d pr %d state %d/%d\n",
+ inet_ntoa(ips.is_dst), ips.is_age,
+ ips.is_pass, ips.is_p, ips.is_state[0],
+ ips.is_state[1]);
+ if (ips.is_p == IPPROTO_TCP)
+ PRINTF("\t%hu -> %hu %lu:%lu %hu:%hu\n",
+ ntohs(ips.is_sport),
+ ntohs(ips.is_dport),
+ ips.is_seq, ips.is_ack,
+ ips.is_swin, ips.is_dwin);
+ else if (ips.is_p == IPPROTO_UDP)
+ PRINTF("\t%hu -> %hu\n", ntohs(ips.is_sport),
+ ntohs(ips.is_dport));
+ else if (ips.is_p == IPPROTO_ICMP)
+ PRINTF("\t%hu %hu %d\n", ips.is_icmp.ics_id,
+ ips.is_icmp.ics_seq,
+ ips.is_icmp.ics_type);
+ istab[i] = ips.is_next;
+ }
+}
+
+
+static void showfrstates(fd, ifsp)
+int fd;
+ipfrstat_t *ifsp;
+{
+ struct ipfr *ipfrtab[IPFT_SIZE], ifr;
+ int i;
+
+ PRINTF("IP fragment states:\n\t%lu new\n\t%lu expired\n\t%lu hits\n",
+ ifsp->ifs_new, ifsp->ifs_expire, ifsp->ifs_hits);
+ PRINTF("\t%lu no memory\n\t%lu already exist\n",
+ ifsp->ifs_nomem, ifsp->ifs_exists);
+ PRINTF("\t%lu inuse\n", ifsp->ifs_inuse);
+ if (kmemcpy((char *)ipfrtab, (u_long)ifsp->ifs_table, sizeof(ipfrtab)))
+ return;
+ for (i = 0; i < IPFT_SIZE; i++)
+ while (ipfrtab[i]) {
+ if (kmemcpy(&ifr, (u_long)ipfrtab[i],
+ sizeof(ifr)) == -1)
+ break;
+ PRINTF("%s -> ", inet_ntoa(ifr.ipfr_src));
+ PRINTF("%s %d %d %d %#02x = %#x\n",
+ inet_ntoa(ifr.ipfr_dst), ifr.ipfr_id,
+ ifr.ipfr_ttl, ifr.ipfr_p, ifr.ipfr_tos,
+ ifr.ipfr_pass);
+ ipfrtab[i] = ifr.ipfr_next;
+ }
+}
diff --git a/contrib/ipfilter/inet_addr.c b/contrib/ipfilter/inet_addr.c
new file mode 100644
index 000000000000..91faec3eeed7
--- /dev/null
+++ b/contrib/ipfilter/inet_addr.c
@@ -0,0 +1,182 @@
+/*
+ * ++Copyright++ 1983, 1990, 1993
+ * -
+ * Copyright (c) 1983, 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * -
+ * Portions Copyright (c) 1993 by Digital Equipment Corporation.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies, and that
+ * the name of Digital Equipment Corporation not be used in advertising or
+ * publicity pertaining to distribution of the document or software without
+ * specific, written prior permission.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
+ * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ * -
+ * --Copyright--
+ */
+
+#if !defined(lint) && defined(LIBC_SCCS)
+static char sccsid[] = "@(#)inet_addr.c 8.1 (Berkeley) 6/17/93";
+static char rcsid[] = "$Id: inet_addr.c,v 2.0.1.1 1997/01/09 15:14:43 darrenr Exp $";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/param.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <ctype.h>
+
+/*
+ * Check whether "cp" is a valid ascii representation
+ * of an Internet address and convert to a binary address.
+ * Returns 1 if the address is valid, 0 if not.
+ * This replaces inet_addr, the return value from which
+ * cannot distinguish between failure and a local broadcast address.
+ */
+int
+inet_aton(cp, addr)
+ register const char *cp;
+ struct in_addr *addr;
+{
+ register u_long val;
+ register int base, n;
+ register char c;
+ u_int parts[4];
+ register u_int *pp = parts;
+
+ c = *cp;
+ for (;;) {
+ /*
+ * Collect number up to ``.''.
+ * Values are specified as for C:
+ * 0x=hex, 0=octal, isdigit=decimal.
+ */
+ if (!isdigit(c))
+ return (0);
+ val = 0; base = 10;
+ if (c == '0') {
+ c = *++cp;
+ if (c == 'x' || c == 'X')
+ base = 16, c = *++cp;
+ else
+ base = 8;
+ }
+ for (;;) {
+ if (isascii(c) && isdigit(c)) {
+ val = (val * base) + (c - '0');
+ c = *++cp;
+ } else if (base == 16 && isascii(c) && isxdigit(c)) {
+ val = (val << 4) |
+ (c + 10 - (islower(c) ? 'a' : 'A'));
+ c = *++cp;
+ } else
+ break;
+ }
+ if (c == '.') {
+ /*
+ * Internet format:
+ * a.b.c.d
+ * a.b.c (with c treated as 16 bits)
+ * a.b (with b treated as 24 bits)
+ */
+ if (pp >= parts + 3)
+ return (0);
+ *pp++ = val;
+ c = *++cp;
+ } else
+ break;
+ }
+ /*
+ * Check for trailing characters.
+ */
+ if (c != '\0' && (!isascii(c) || !isspace(c)))
+ return (0);
+ /*
+ * Concoct the address according to
+ * the number of parts specified.
+ */
+ n = pp - parts + 1;
+ switch (n) {
+
+ case 0:
+ return (0); /* initial nondigit */
+
+ case 1: /* a -- 32 bits */
+ break;
+
+ case 2: /* a.b -- 8.24 bits */
+ if (val > 0xffffff)
+ return (0);
+ val |= parts[0] << 24;
+ break;
+
+ case 3: /* a.b.c -- 8.8.16 bits */
+ if (val > 0xffff)
+ return (0);
+ val |= (parts[0] << 24) | (parts[1] << 16);
+ break;
+
+ case 4: /* a.b.c.d -- 8.8.8.8 bits */
+ if (val > 0xff)
+ return (0);
+ val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8);
+ break;
+ }
+ if (addr)
+ addr->s_addr = htonl(val);
+ return (1);
+}
+
+/* these are compatibility routines, not needed on recent BSD releases */
+
+/*
+ * Ascii internet address interpretation routine.
+ * The value returned is in network order.
+ */
+u_long
+inet_addr(cp)
+ register const char *cp;
+{
+ struct in_addr val;
+
+ if (inet_aton(cp, &val))
+ return (val.s_addr);
+ return (0xffffffff);
+}
diff --git a/contrib/ipfilter/ip_compat.h b/contrib/ipfilter/ip_compat.h
new file mode 100644
index 000000000000..5a36cc318ad6
--- /dev/null
+++ b/contrib/ipfilter/ip_compat.h
@@ -0,0 +1,342 @@
+/*
+ * (C)opyright 1993, 1994, 1995 by Darren Reed.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that this notice is preserved and due credit is given
+ * to the original author and the contributors.
+ *
+ * @(#)ip_compat.h 1.8 1/14/96
+ * $Id: ip_compat.h,v 2.0.1.4 1997/02/04 14:24:25 darrenr Exp $
+ */
+
+#ifndef __IP_COMPAT_H_
+#define __IP_COMPAT_H__
+
+#ifndef SOLARIS
+#define SOLARIS (defined(sun) && (defined(__svr4__) || defined(__SVR4)))
+#endif
+#if SOLARIS
+#define MTYPE(m) ((m)->b_datap->db_type)
+#endif
+#define IPMINLEN(i, h) ((i)->ip_len >= ((i)->ip_hl * 4 + sizeof(struct h)))
+
+#ifndef IP_OFFMASK
+#define IP_OFFMASK 0x1fff
+#endif
+
+#ifndef MAX
+#define MAX(a,b) (((a) > (b)) ? (a) : (b))
+#endif
+
+/*
+ * Security Options for Intenet Protocol (IPSO) as defined in RFC 1108.
+ *
+ * Basic Option
+ *
+ * 00000001 - (Reserved 4)
+ * 00111101 - Top Secret
+ * 01011010 - Secret
+ * 10010110 - Confidential
+ * 01100110 - (Reserved 3)
+ * 11001100 - (Reserved 2)
+ * 10101011 - Unclassified
+ * 11110001 - (Reserved 1)
+ */
+#define IPSO_CLASS_RES4 0x01
+#define IPSO_CLASS_TOPS 0x3d
+#define IPSO_CLASS_SECR 0x5a
+#define IPSO_CLASS_CONF 0x96
+#define IPSO_CLASS_RES3 0x66
+#define IPSO_CLASS_RES2 0xcc
+#define IPSO_CLASS_UNCL 0xab
+#define IPSO_CLASS_RES1 0xf1
+
+#define IPSO_AUTH_GENSER 0x80
+#define IPSO_AUTH_ESI 0x40
+#define IPSO_AUTH_SCI 0x20
+#define IPSO_AUTH_NSA 0x10
+#define IPSO_AUTH_DOE 0x08
+#define IPSO_AUTH_UN 0x06
+#define IPSO_AUTH_FTE 0x01
+
+/*
+ * IP option #defines
+ */
+/*#define IPOPT_RR 7 */
+#define IPOPT_ZSU 10 /* ZSU */
+#define IPOPT_MTUP 11 /* MTUP */
+#define IPOPT_MTUR 12 /* MTUR */
+#define IPOPT_ENCODE 15 /* ENCODE */
+/*#define IPOPT_TS 68 */
+#define IPOPT_TR 82 /* TR */
+/*#define IPOPT_SECURITY 130 */
+/*#define IPOPT_LSRR 131 */
+#define IPOPT_E_SEC 133 /* E-SEC */
+#define IPOPT_CIPSO 134 /* CIPSO */
+/*#define IPOPT_SATID 136 */
+#ifndef IPOPT_SID
+# define IPOPT_SID IPOPT_SATID
+#endif
+/*#define IPOPT_SSRR 137 */
+#define IPOPT_ADDEXT 147 /* ADDEXT */
+#define IPOPT_VISA 142 /* VISA */
+#define IPOPT_IMITD 144 /* IMITD */
+#define IPOPT_EIP 145 /* EIP */
+#define IPOPT_FINN 205 /* FINN */
+
+
+/*
+ * Build some macros and #defines to enable the same code to compile anywhere
+ * Well, that's the idea, anyway :-)
+ */
+#ifdef _KERNEL
+# if SOLARIS
+# define MUTEX_ENTER(x) mutex_enter(x)
+# define MUTEX_EXIT(x) mutex_exit(x)
+# define MTOD(m,t) (t)((m)->b_rptr)
+# define IRCOPY(a,b,c) copyin((a), (b), (c))
+# define IWCOPY(a,b,c) copyout((a), (b), (c))
+# else
+# define MUTEX_ENTER(x) ;
+# define MUTEX_EXIT(x) ;
+# ifndef linux
+# define MTOD(m,t) mtod(m,t)
+# define IRCOPY(a,b,c) bcopy((a), (b), (c))
+# define IWCOPY(a,b,c) bcopy((a), (b), (c))
+# endif
+# endif /* SOLARIS */
+
+# ifdef sun
+# if defined(__svr4__) || defined(__SVR4)
+# define GETUNIT(n) get_unit((n))
+# else
+# include <sys/kmem_alloc.h>
+# define GETUNIT(n) ifunit((n), IFNAMSIZ)
+# endif
+# else
+# define GETUNIT(n) ifunit((n))
+# endif /* sun */
+
+# if defined(sun) && !defined(linux)
+# define UIOMOVE(a,b,c,d) uiomove(a,b,c,d)
+# define SLEEP(id, n) sleep((id), PZERO+1)
+# define KFREE(x) kmem_free((char *)(x), sizeof(*(x)))
+# if SOLARIS
+typedef struct qif {
+ struct qif *qf_next;
+ ill_t *qf_ill;
+ kmutex_t qf_lock;
+ void *qf_iptr;
+ void *qf_optr;
+ queue_t *qf_in;
+ queue_t *qf_out;
+ void *qf_wqinfo;
+ void *qf_rqinfo;
+ int (*qf_inp)();
+ int (*qf_outp)();
+ mblk_t *qf_m;
+ int qf_len;
+ char qf_name[8];
+ /*
+ * in case the ILL has disappeared...
+ */
+ int qf_hl; /* header length */
+} qif_t;
+# define SPLNET(x) ;
+# undef SPLX
+# define SPLX(x) ;
+# ifdef sparc
+# define ntohs(x) (x)
+# define ntohl(x) (x)
+# define htons(x) (x)
+# define htonl(x) (x)
+# endif
+# define KMALLOC(x) kmem_alloc((x), KM_NOSLEEP)
+# define GET_MINOR(x) getminor(x)
+# else
+# define KMALLOC(x) new_kmem_alloc((x), KMEM_NOSLEEP)
+# endif /* __svr4__ */
+# endif /* sun && !linux */
+# ifndef GET_MINOR
+# define GET_MINOR(x) minor(x)
+# endif
+# if BSD >= 199306 || defined(__FreeBSD__)
+# include <vm/vm.h>
+# if !defined(__FreeBSD__)
+# include <vm/vm_extern.h>
+# include <sys/proc.h>
+extern vm_map_t kmem_map;
+# else
+# include <vm/vm_kern.h>
+# endif /* __FreeBSD__ */
+/*
+** # define KMALLOC(x) kmem_alloc(kmem_map, (x))
+** # define KFREE(x) kmem_free(kmem_map, (vm_offset_t)(x), \
+ sizeof(*(x)))
+*/
+# ifdef M_PFIL
+# define KMALLOC(x) malloc((x), M_PFIL, M_NOWAIT)
+# define KFREE(x) FREE((x), M_PFIL)
+# else
+# define KMALLOC(x) malloc((x), M_TEMP, M_NOWAIT)
+# define KFREE(x) FREE((x), M_TEMP)
+# endif
+# define UIOMOVE(a,b,c,d) uiomove(a,b,d)
+# define SLEEP(id, n) tsleep((id), PPAUSE|PCATCH, n, 0)
+# endif /* BSD */
+# if defined(NetBSD1_0) && (NetBSD1_0 > 1)
+# define SPLNET(x) x = splsoftnet()
+# else
+# if !SOLARIS
+# define SPLNET(x) x = splnet()
+# define SPLX(x) (void) splx(x)
+# endif
+# endif
+#else
+# ifndef linux
+# define MUTEX_ENTER(x) ;
+# define MUTEX_EXIT(x) ;
+# define SPLNET(x) ;
+# define SPLX(x) ;
+# define KMALLOC(x) malloc(x)
+# define KFREE(x) free(x)
+# define GETUNIT(x) (x)
+# define IRCOPY(a,b,c) bcopy((a), (b), (c))
+# define IWCOPY(a,b,c) bcopy((a), (b), (c))
+# endif
+#endif /* KERNEL */
+
+#ifdef linux
+# define ICMP_UNREACH ICMP_DEST_UNREACH
+# define ICMP_SOURCEQUENCH ICMP_SOURCE_QUENCH
+# define ICMP_TIMXCEED ICMP_TIME_EXCEEDED
+# define ICMP_PARAMPROB ICMP_PARAMETERPROB
+
+# define TH_FIN 0x01
+# define TH_SYN 0x02
+# define TH_RST 0x04
+# define TH_PUSH 0x08
+# define TH_ACK 0x10
+# define TH_URG 0x20
+
+typedef struct {
+ __u16 th_sport;
+ __u16 th_dport;
+ __u32 th_seq;
+ __u32 th_ack;
+ __u8 th_x;
+ __u8 th_flags;
+ __u16 th_win;
+ __u16 th_sum;
+ __u16 th_urp;
+} tcphdr_t;
+
+typedef struct {
+ __u16 uh_sport;
+ __u16 uh_dport;
+ __u16 uh_ulen;
+ __u16 uh_sun;
+} udphdr_t;
+
+typedef struct {
+# if defined(__i386__) || defined(__MIPSEL__) || defined(__alpha__) ||\
+ defined(vax)
+ __u8 ip_hl:4;
+ __u8 ip_v:4;
+# else
+ __u8 ip_hl:4;
+ __u8 ip_v:4;
+# endif
+ __u8 ip_tos;
+ __u16 ip_len;
+ __u16 ip_id;
+ __u16 ip_off;
+ __u8 ip_ttl;
+ __u8 ip_p;
+ __u16 ip_sum;
+ struct in_addr ip_src;
+ struct in_addr ip_dst;
+} ip_t;
+
+/*
+ * Structure of an icmp header.
+ */
+struct icmp {
+ u_char icmp_type; /* type of message, see below */
+ u_char icmp_code; /* type sub code */
+ u_short icmp_cksum; /* ones complement cksum of struct */
+ union {
+ u_char ih_pptr; /* ICMP_PARAMPROB */
+ struct in_addr ih_gwaddr; /* ICMP_REDIRECT */
+ struct ih_idseq {
+ n_short icd_id;
+ n_short icd_seq;
+ } ih_idseq;
+ int ih_void;
+ } icmp_hun;
+# define icmp_pptr icmp_hun.ih_pptr
+# define icmp_gwaddr icmp_hun.ih_gwaddr
+# define icmp_id icmp_hun.ih_idseq.icd_id
+# define icmp_seq icmp_hun.ih_idseq.icd_seq
+# define icmp_void icmp_hun.ih_void
+ union {
+ struct id_ts {
+ n_time its_otime;
+ n_time its_rtime;
+ n_time its_ttime;
+ } id_ts;
+ struct id_ip {
+ ip_t idi_ip;
+ /* options and then 64 bits of data */
+ } id_ip;
+ u_long id_mask;
+ char id_data[1];
+ } icmp_dun;
+# define icmp_otime icmp_dun.id_ts.its_otime
+# define icmp_rtime icmp_dun.id_ts.its_rtime
+# define icmp_ttime icmp_dun.id_ts.its_ttime
+# define icmp_ip icmp_dun.id_ip.idi_ip
+# define icmp_mask icmp_dun.id_mask
+# define icmp_data icmp_dun.id_data
+};
+
+struct ipovly {
+ caddr_t ih_next, ih_prev; /* for protocol sequence q's */
+ u_char ih_x1; /* (unused) */
+ u_char ih_pr; /* protocol */
+ short ih_len; /* protocol length */
+ struct in_addr ih_src; /* source internet address */
+ struct in_addr ih_dst; /* destination internet address */
+};
+
+# define SPLX(x) (void)
+# define SPLNET(x) (void)
+
+# define bcopy(a,b,c) memmove(b,a,c)
+# define bcmp(a,b,c) memcmp(a,b,c)
+
+# define UNITNAME(n) dev_get((n))
+# define ifnet device
+
+# define KMALLOC(x) kmalloc((x), GFP_ATOMIC)
+# define KFREE(x) kfree_s((x), sizeof(*(x)))
+# define IRCOPY(a,b,c) { \
+ error = verify_area(VERIFY_READ, \
+ (b) ,sizeof((b))); \
+ if (!error) \
+ memcpy_fromfs((b), (a), (c)); \
+ }
+# define IWCOPY(a,b,c) { \
+ error = verify_area(VERIFY_WRITE, \
+ (b) ,sizeof((b))); \
+ if (!error) \
+ memcpy_tofs((b), (a), (c)); \
+ }
+#else
+typedef struct tcphdr tcphdr_t;
+typedef struct udphdr udphdr_t;
+typedef struct icmp icmphdr_t;
+typedef struct ip ip_t;
+#endif /* linux */
+
+#endif /* __IP_COMPAT_H__ */
diff --git a/contrib/ipfilter/ip_fil.c b/contrib/ipfilter/ip_fil.c
new file mode 100644
index 000000000000..7a244345640e
--- /dev/null
+++ b/contrib/ipfilter/ip_fil.c
@@ -0,0 +1,885 @@
+/*
+ * (C)opyright 1993,1994,1995 by Darren Reed.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that this notice is preserved and due credit is given
+ * to the original author and the contributors.
+ */
+#if !defined(lint) && defined(LIBC_SCCS)
+static char sccsid[] = "@(#)ip_fil.c 2.41 6/5/96 (C) 1993-1995 Darren Reed";
+static char rcsid[] = "$Id: ip_fil.c,v 2.0.1.5 1997/01/29 13:41:45 darrenr Exp $";
+#endif
+
+#include <sys/errno.h>
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/file.h>
+#include <sys/ioctl.h>
+#include <sys/systm.h>
+#include <sys/uio.h>
+#include <sys/mbuf.h>
+#include <sys/protosw.h>
+#include <sys/socket.h>
+
+#include <net/if.h>
+#ifdef sun
+#include <net/af.h>
+#endif
+#include <net/route.h>
+#include <netinet/in.h>
+#include <netinet/in_var.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/ip_var.h>
+#include <netinet/tcp.h>
+#include <netinet/udp.h>
+#include <netinet/tcpip.h>
+#include <netinet/ip_icmp.h>
+#include <syslog.h>
+#include "ip_fil.h"
+#include "ip_compat.h"
+#include "ip_frag.h"
+#include "ip_nat.h"
+#include "ip_state.h"
+#ifndef MIN
+#define MIN(a,b) (((a)<(b))?(a):(b))
+#endif
+
+extern fr_flags, fr_active;
+extern struct protosw inetsw[];
+extern int (*fr_checkp)();
+#if BSD < 199306
+extern int ipfr_slowtimer();
+static int (*fr_saveslowtimo)();
+extern int tcp_ttl;
+#else
+extern void ipfr_slowtimer();
+static void (*fr_saveslowtimo)();
+#endif
+
+int ipl_inited = 0;
+int ipl_unreach = ICMP_UNREACH_FILTER;
+int send_reset();
+
+#ifdef IPFILTER_LOG
+# define LOGSIZE 8192
+int ipllog();
+char iplbuf[LOGSIZE];
+caddr_t iplh = iplbuf, iplt = iplbuf;
+static int iplused = 0;
+#endif /* IPFILTER_LOG */
+static void frflush();
+static int frrequest();
+static int (*fr_savep)();
+
+#if _BSDI_VERSION >= 199501
+# include <sys/device.h>
+# include <sys/conf.h>
+
+int iplioctl __P((dev_t, int, caddr_t, int, struct proc *));
+int iplopen __P((dev_t, int, int, struct proc *));
+int iplclose __P((dev_t, int, int, struct proc *));
+# ifdef IPFILTER_LOG
+int iplread __P((dev_t, struct uio *, int));
+# else
+# define iplread noread
+# endif
+int iplioctl __P((dev_t, int, caddr_t, int, struct proc *));
+
+struct cfdriver iplcd = {
+ NULL, "ipl", NULL, NULL, DV_DULL, 0
+};
+
+struct devsw iplsw = {
+ &iplcd,
+ iplopen, iplclose, iplread, nowrite, iplioctl, noselect, nommap,
+ nostrat, nodump, nopsize, 0,
+ nostop
+};
+#endif /* _BSDI_VERSION >= 199501 */
+
+#ifdef IPFILTER_LKM
+int iplidentify(s)
+char *s;
+{
+ if (strcmp(s, "ipl") == 0)
+ return 1;
+ return 0;
+}
+#endif /* IPFILTER_LKM */
+
+
+int iplattach()
+{
+ int s;
+
+ SPLNET(s);
+ if (ipl_inited || (fr_checkp == fr_check)) {
+ printf("IP Filter: already initialized\n");
+ SPLX(s);
+ return EBUSY;
+ }
+ ipl_inited = 1;
+ bzero((char *)nat_table, sizeof(nat_t *) * NAT_SIZE * 2);
+ fr_savep = fr_checkp;
+ fr_checkp = fr_check;
+ fr_saveslowtimo = inetsw[0].pr_slowtimo;
+ inetsw[0].pr_slowtimo = ipfr_slowtimer;
+ SPLX(s);
+ return 0;
+}
+
+
+int ipldetach()
+{
+ int s, i = FR_INQUE|FR_OUTQUE;
+
+ SPLNET(s);
+ if (!ipl_inited)
+ {
+ printf("IP Filter: not initialized\n");
+ SPLX(s);
+ return EBUSY;
+ }
+
+ fr_checkp = fr_savep;
+ inetsw[0].pr_slowtimo = fr_saveslowtimo;
+ frflush((caddr_t)&i);
+ ipl_inited = 0;
+
+ ipfr_unload();
+ ip_natunload();
+ fr_stateunload();
+
+ SPLX(s);
+ return 0;
+}
+
+
+static void frzerostats(data)
+caddr_t data;
+{
+ struct friostat fio;
+
+ bcopy((char *)frstats, (char *)fio.f_st,
+ sizeof(struct filterstats) * 2);
+ fio.f_fin[0] = ipfilter[0][0];
+ fio.f_fin[1] = ipfilter[0][1];
+ fio.f_fout[0] = ipfilter[1][0];
+ fio.f_fout[1] = ipfilter[1][1];
+ fio.f_acctin[0] = ipacct[0][0];
+ fio.f_acctin[1] = ipacct[0][1];
+ fio.f_acctout[0] = ipacct[1][0];
+ fio.f_acctout[1] = ipacct[1][1];
+ fio.f_active = fr_active;
+ IWCOPY((caddr_t)&fio, data, sizeof(fio));
+ bzero((char *)frstats, sizeof(*frstats) * 2);
+}
+
+
+static void frflush(data)
+caddr_t data;
+{
+ struct frentry *f, **fp;
+ int flags = *(int *)data, flushed = 0, set = fr_active;
+
+ bzero((char *)frcache, sizeof(frcache[0]) * 2);
+
+ if (flags & FR_INACTIVE)
+ set = 1 - set;
+ if (flags & FR_OUTQUE) {
+ for (fp = &ipfilter[1][set]; (f = *fp); ) {
+ *fp = f->fr_next;
+ KFREE(f);
+ flushed++;
+ }
+ for (fp = &ipacct[1][set]; (f = *fp); ) {
+ *fp = f->fr_next;
+ KFREE(f);
+ flushed++;
+ }
+ }
+ if (flags & FR_INQUE) {
+ for (fp = &ipfilter[0][set]; (f = *fp); ) {
+ *fp = f->fr_next;
+ KFREE(f);
+ flushed++;
+ }
+ for (fp = &ipacct[0][set]; (f = *fp); ) {
+ *fp = f->fr_next;
+ KFREE(f);
+ flushed++;
+ }
+ }
+ *(int *)data = flushed;
+}
+
+
+/*
+ * Filter ioctl interface.
+ */
+int iplioctl(dev, cmd, data, mode
+#if _BSDI_VERSION >= 199501
+, p)
+struct proc *p;
+#else
+)
+#endif
+dev_t dev;
+int cmd;
+caddr_t data;
+int mode;
+{
+ int error = 0, s, unit;
+
+ unit = minor(dev);
+ if (unit != 0)
+ return ENXIO;
+
+ SPLNET(s);
+ switch (cmd) {
+ case FIONREAD :
+#ifdef IPFILTER_LOG
+ *(int *)data = iplused;
+#endif
+ break;
+#ifndef IPFILTER_LKM
+ case SIOCFRENB :
+ {
+ u_int enable;
+
+ if (!(mode & FWRITE))
+ error = EPERM;
+ else {
+ IRCOPY(data, (caddr_t)&enable, sizeof(enable));
+ if (enable)
+ error = iplattach();
+ else
+ error = ipldetach();
+ }
+ break;
+ }
+#endif
+ case SIOCSETFF :
+ if (!(mode & FWRITE))
+ error = EPERM;
+ else
+ IRCOPY(data, (caddr_t)&fr_flags, sizeof(fr_flags));
+ break;
+ case SIOCGETFF :
+ IWCOPY((caddr_t)&fr_flags, data, sizeof(fr_flags));
+ break;
+ case SIOCINAFR :
+ case SIOCRMAFR :
+ case SIOCADAFR :
+ case SIOCZRLST :
+ if (!(mode & FWRITE))
+ error = EPERM;
+ else
+ error = frrequest(cmd, data, fr_active);
+ break;
+ case SIOCINIFR :
+ case SIOCRMIFR :
+ case SIOCADIFR :
+ if (!(mode & FWRITE))
+ error = EPERM;
+ else
+ error = frrequest(cmd, data, 1 - fr_active);
+ break;
+ case SIOCSWAPA :
+ if (!(mode & FWRITE))
+ error = EPERM;
+ else {
+ bzero((char *)frcache, sizeof(frcache[0]) * 2);
+ *(u_int *)data = fr_active;
+ fr_active = 1 - fr_active;
+ }
+ break;
+ case SIOCGETFS :
+ {
+ struct friostat fio;
+
+ bcopy((char *)frstats, (char *)fio.f_st,
+ sizeof(struct filterstats) * 2);
+ fio.f_fin[0] = ipfilter[0][0];
+ fio.f_fin[1] = ipfilter[0][1];
+ fio.f_fout[0] = ipfilter[1][0];
+ fio.f_fout[1] = ipfilter[1][1];
+ fio.f_acctin[0] = ipacct[0][0];
+ fio.f_acctin[1] = ipacct[0][1];
+ fio.f_acctout[0] = ipacct[1][0];
+ fio.f_acctout[1] = ipacct[1][1];
+ fio.f_active = fr_active;
+ IWCOPY((caddr_t)&fio, data, sizeof(fio));
+ break;
+ }
+ case SIOCFRZST :
+ if (!(mode & FWRITE))
+ error = EPERM;
+ else
+ frzerostats(data);
+ break;
+ case SIOCIPFFL :
+ if (!(mode & FWRITE))
+ error = EPERM;
+ else
+ frflush(data);
+ break;
+#ifdef IPFILTER_LOG
+ case SIOCIPFFB :
+ if (!(mode & FWRITE))
+ error = EPERM;
+ else {
+ *(int *)data = iplused;
+ iplh = iplt = iplbuf;
+ iplused = 0;
+ }
+ break;
+#endif /* IPFILTER_LOG */
+ case SIOCADNAT :
+ case SIOCRMNAT :
+ case SIOCGNATS :
+ case SIOCGNATL :
+ case SIOCFLNAT :
+ case SIOCCNATL :
+ error = nat_ioctl(data, cmd, mode);
+ break;
+ case SIOCGFRST :
+ IWCOPY((caddr_t)ipfr_fragstats(), data, sizeof(ipfrstat_t));
+ break;
+ case SIOCGIPST :
+ IWCOPY((caddr_t)fr_statetstats(), data, sizeof(ips_stat_t));
+ break;
+ default :
+ error = EINVAL;
+ break;
+ }
+ SPLX(s);
+ return error;
+}
+
+
+static int frrequest(req, data, set)
+int req, set;
+caddr_t data;
+{
+ register frentry_t *fp, *f, **fprev;
+ register frentry_t **ftail;
+ frentry_t fr;
+ frdest_t *fdp;
+ struct frentry frd;
+ int error = 0, in;
+
+ fp = &fr;
+ IRCOPY(data, (caddr_t)fp, sizeof(*fp));
+
+ bzero((char *)frcache, sizeof(frcache[0]) * 2);
+
+ in = (fp->fr_flags & FR_INQUE) ? 0 : 1;
+ if (fp->fr_flags & FR_ACCOUNT) {
+ ftail = fprev = &ipacct[in][set];
+ } else if (fp->fr_flags & (FR_OUTQUE|FR_INQUE))
+ ftail = fprev = &ipfilter[in][set];
+ else
+ return ESRCH;
+
+ IRCOPY((char *)fp, (char *)&frd, sizeof(frd));
+ fp = &frd;
+ if (*fp->fr_ifname) {
+ fp->fr_ifa = GETUNIT(fp->fr_ifname);
+ if (!fp->fr_ifa)
+ fp->fr_ifa = (struct ifnet *)-1;
+ }
+
+ fdp = &fp->fr_dif;
+ fp->fr_flags &= ~FR_DUP;
+ if (*fdp->fd_ifname) {
+ fdp->fd_ifp = GETUNIT(fdp->fd_ifname);
+ if (!fdp->fd_ifp)
+ fdp->fd_ifp = (struct ifnet *)-1;
+ else
+ fp->fr_flags |= FR_DUP;
+ }
+
+ fdp = &fp->fr_tif;
+ if (*fdp->fd_ifname) {
+ fdp->fd_ifp = GETUNIT(fdp->fd_ifname);
+ if (!fdp->fd_ifp)
+ fdp->fd_ifp = (struct ifnet *)-1;
+ }
+
+ /*
+ * Look for a matching filter rule, but don't include the next or
+ * interface pointer in the comparison (fr_next, fr_ifa).
+ */
+ for (; (f = *ftail); ftail = &f->fr_next)
+ if (bcmp((char *)&f->fr_ip, (char *)&fp->fr_ip,
+ FR_CMPSIZ) == 0)
+ break;
+
+ /*
+ * If zero'ing statistics, copy current to caller and zero.
+ */
+ if (req == SIOCZRLST) {
+ if (!f)
+ return ESRCH;
+ IWCOPY((caddr_t)f, data, sizeof(*f));
+ f->fr_hits = 0;
+ f->fr_bytes = 0;
+ return 0;
+ }
+
+ if (!f) {
+ ftail = fprev;
+ if (req != SIOCINAFR && req != SIOCINIFR)
+ while ((f = *ftail))
+ ftail = &f->fr_next;
+ else if (fp->fr_hits)
+ while (--fp->fr_hits && (f = *ftail))
+ ftail = &f->fr_next;
+ f = NULL;
+ }
+
+ if (req == SIOCDELFR || req == SIOCRMIFR) {
+ if (!f)
+ error = ESRCH;
+ else {
+ *ftail = f->fr_next;
+ (void) KFREE(f);
+ }
+ } else {
+ if (f)
+ error = EEXIST;
+ else {
+ if ((f = (struct frentry *)KMALLOC(sizeof(*f)))) {
+ bcopy((char *)fp, (char *)f, sizeof(*f));
+ f->fr_hits = 0;
+ f->fr_next = *ftail;
+ *ftail = f;
+ } else
+ error = ENOMEM;
+ }
+ }
+ return (error);
+}
+
+
+#if !defined(linux)
+/*
+ * routines below for saving IP headers to buffer
+ */
+int iplopen(dev, flags
+#if _BSDI_VERSION >= 199501
+, devtype, p)
+int devtype;
+struct proc *p;
+#else
+)
+#endif
+dev_t dev;
+int flags;
+{
+ u_int min = minor(dev);
+
+ if (min)
+ min = ENXIO;
+ return min;
+}
+
+
+int iplclose(dev, flags
+#if _BSDI_VERSION >= 199501
+, devtype, p)
+int devtype;
+struct proc *p;
+#else
+)
+#endif
+dev_t dev;
+int flags;
+{
+ u_int min = minor(dev);
+
+ if (min)
+ min = ENXIO;
+ return min;
+}
+
+# ifdef IPFILTER_LOG
+/*
+ * iplread/ipllog
+ * both of these must operate with at least splnet() lest they be
+ * called during packet processing and cause an inconsistancy to appear in
+ * the filter lists.
+ */
+# if BSD >= 199306
+int iplread(dev, uio, ioflag)
+int ioflag;
+# else
+int iplread(dev, uio)
+# endif
+dev_t dev;
+register struct uio *uio;
+{
+ register int ret, s;
+ register size_t sz, sx;
+ int error;
+
+ if (!uio->uio_resid)
+ return 0;
+ while (!iplused) {
+ error = SLEEP(iplbuf, "ipl sleep");
+ if (error)
+ return error;
+ }
+ SPLNET(s);
+
+ sx = sz = MIN(uio->uio_resid, iplused);
+ if (iplh < iplt)
+ sz = MIN(sz, LOGSIZE - (iplt - iplbuf));
+ sx -= sz;
+
+# if BSD >= 199306 || defined(__FreeBSD__)
+ uio->uio_rw = UIO_READ;
+# endif
+ if (!(ret = UIOMOVE(iplt, sz, UIO_READ, uio))) {
+ iplt += sz;
+ iplused -= sz;
+ if ((iplh < iplt) && (iplt == iplbuf + LOGSIZE))
+ iplt = iplbuf;
+
+ if (sx && !(ret = UIOMOVE(iplt, sx, UIO_READ, uio))) {
+ iplt += sx;
+ iplused -= sx;
+ if ((iplh < iplt) && (iplt == iplbuf + LOGSIZE))
+ iplt = iplbuf;
+ }
+ if (!iplused) /* minimise wrapping around the end */
+ iplh = iplt = iplbuf;
+ }
+ SPLX(s);
+ return ret;
+}
+# endif /* IPFILTER_LOG */
+#endif /* linux */
+
+
+#ifdef IPFILTER_LOG
+int ipllog(flags, ip, fin, m)
+u_int flags;
+ip_t *ip;
+register fr_info_t *fin;
+struct mbuf *m;
+{
+ struct ipl_ci iplci;
+ register int len, mlen, hlen;
+ struct ifnet *ifp = fin->fin_ifp;
+
+ hlen = fin->fin_hlen;
+ if (ip->ip_p == IPPROTO_TCP || ip->ip_p == IPPROTO_UDP)
+ hlen += MIN(sizeof(tcphdr_t), fin->fin_dlen);
+ else if (ip->ip_p == IPPROTO_ICMP) {
+ struct icmp *icmp = (struct icmp *)((char *)ip + hlen);
+
+ switch (icmp->icmp_type) {
+ case ICMP_UNREACH :
+ case ICMP_SOURCEQUENCH :
+ case ICMP_REDIRECT :
+ case ICMP_TIMXCEED :
+ case ICMP_PARAMPROB :
+ hlen += MIN(sizeof(struct icmp) + 8, fin->fin_dlen);
+ break;
+ default :
+ hlen += MIN(sizeof(struct icmp), fin->fin_dlen);
+ break;
+ }
+ }
+
+ mlen = (flags & FR_LOGBODY) ? MIN(ip->ip_len - hlen, 128) : 0;
+ len = hlen + sizeof(iplci) + mlen;
+ if (iplused + len > LOGSIZE)
+ return 0;
+ iplused += len;
+
+# ifdef sun
+ uniqtime(&iplci);
+# endif
+# if BSD >= 199306 || defined(__FreeBSD__)
+ microtime((struct timeval *)&iplci);
+# endif
+ iplci.flags = flags;
+ iplci.hlen = (u_char)hlen;
+ iplci.plen = (u_char)mlen;
+ iplci.rule = fin->fin_rule;
+# if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199603))
+ strncpy(iplci.ifname, ifp->if_xname, IFNAMSIZ);
+# else
+ iplci.unit = (u_char)ifp->if_unit;
+ if ((iplci.ifname[0] = ifp->if_name[0]))
+ if ((iplci.ifname[1] = ifp->if_name[1]))
+ if ((iplci.ifname[2] = ifp->if_name[2]))
+ iplci.ifname[3] = ifp->if_name[3];
+# endif
+ /*
+ * Gauranteed to succeed from above
+ */
+ (void) fr_copytolog(&iplci, sizeof(iplci));
+
+ for (len -= sizeof(iplci); m && len > 0; m = m->m_next, len -= hlen) {
+ hlen = MIN(len, m->m_len);
+ if (fr_copytolog(mtod(m, char *), hlen))
+ break;
+ }
+
+ wakeup(iplbuf);
+ return 1;
+}
+#endif /* IPFILTER_LOG */
+
+/*
+ * send_reset - this could conceivably be a call to tcp_respond(), but that
+ * requires a large amount of setting up and isn't any more efficient.
+ */
+int send_reset(ti)
+struct tcpiphdr *ti;
+{
+ struct tcpiphdr *tp;
+ struct ip *ip;
+ struct tcphdr *tcp;
+ struct mbuf *m;
+ int tlen = 0;
+
+ if (ti->ti_flags & TH_RST)
+ return -1; /* feedback loop */
+#if BSD < 199306
+ m = m_get(M_DONTWAIT, MT_HEADER);
+#else
+ m = m_gethdr(M_DONTWAIT, MT_HEADER);
+ m->m_data += max_linkhdr;
+#endif
+ if (m == NULL)
+ return -1;
+
+ if (ti->ti_flags & TH_SYN)
+ tlen = 1;
+ m->m_len = sizeof (struct tcpiphdr);
+#if BSD >= 199306
+ m->m_pkthdr.len = sizeof (struct tcpiphdr);
+ m->m_pkthdr.rcvif = (struct ifnet *)0;
+#endif
+ bzero(mtod(m, char *), sizeof(struct tcpiphdr));
+ ip = mtod(m, struct ip *);
+ tp = mtod(m, struct tcpiphdr *);
+ tcp = (struct tcphdr *)((char *)ip + sizeof(struct ip));
+
+ ip->ip_src.s_addr = ti->ti_dst.s_addr;
+ ip->ip_dst.s_addr = ti->ti_src.s_addr;
+ tcp->th_dport = ti->ti_sport;
+ tcp->th_sport = ti->ti_dport;
+ tcp->th_ack = htonl(ntohl(ti->ti_seq) + tlen);
+ tcp->th_off = sizeof(struct tcphdr) >> 2;
+ tcp->th_flags = TH_RST|TH_ACK;
+ tp->ti_pr = ((struct ip *)ti)->ip_p;
+ tp->ti_len = htons(sizeof(struct tcphdr));
+ tcp->th_sum = in_cksum(m, sizeof(struct tcpiphdr));
+
+ ip->ip_tos = ((struct ip *)ti)->ip_tos;
+ ip->ip_p = ((struct ip *)ti)->ip_p;
+ ip->ip_len = sizeof (struct tcpiphdr);
+#if BSD < 199306
+ ip->ip_ttl = tcp_ttl;
+#else
+ ip->ip_ttl = ip_defttl;
+#endif
+
+ /*
+ * extra 0 in case of multicast
+ */
+ (void) ip_output(m, (struct mbuf *)0, 0, 0, 0);
+ return 0;
+}
+
+
+#ifndef IPFILTER_LKM
+void iplinit()
+{
+ (void) iplattach();
+ ip_init();
+}
+#endif
+
+
+void ipfr_fastroute(m0, fin, fdp)
+struct mbuf *m0;
+fr_info_t *fin;
+frdest_t *fdp;
+{
+ register struct ip *ip, *mhip;
+ register struct mbuf *m = m0;
+ register struct route *ro;
+ struct ifnet *ifp = fdp->fd_ifp;
+ int len, off, error = 0;
+ int hlen = fin->fin_hlen;
+ struct route iproute;
+ struct sockaddr_in *dst;
+
+ ip = mtod(m0, struct ip *);
+ /*
+ * Route packet.
+ */
+ ro = &iproute;
+ bzero((caddr_t)ro, sizeof (*ro));
+ dst = (struct sockaddr_in *)&ro->ro_dst;
+ dst->sin_family = AF_INET;
+ dst->sin_addr = fdp->fd_ip.s_addr ? fdp->fd_ip : ip->ip_dst;
+#if (BSD >= 199306) && !defined(__NetBSD__) && !defined(__bsdi__)
+# ifdef RTF_CLONING
+ rtalloc_ign(ro, RTF_CLONING);
+# else
+ rtalloc_ign(ro, RTF_PRCLONING);
+# endif
+#else
+ rtalloc(ro);
+#endif
+ if (!ifp) {
+ if (!(fin->fin_fr->fr_flags & FR_FASTROUTE)) {
+ error = -2;
+ goto bad;
+ }
+ if (ro->ro_rt == 0 || (ifp = ro->ro_rt->rt_ifp) == 0) {
+ if (in_localaddr(ip->ip_dst))
+ error = EHOSTUNREACH;
+ else
+ error = ENETUNREACH;
+ goto bad;
+ }
+ if (ro->ro_rt->rt_flags & RTF_GATEWAY)
+ dst = (struct sockaddr_in *)&ro->ro_rt->rt_gateway;
+ }
+ ro->ro_rt->rt_use++;
+
+ /*
+ * For input packets which are being "fastrouted", they won't
+ * go back through output filtering and miss their chance to get
+ * NAT'd.
+ */
+ (void) ip_natout(ip, hlen, fin);
+ if (fin->fin_out)
+ ip->ip_sum = 0;
+ /*
+ * If small enough for interface, can just send directly.
+ */
+ if (ip->ip_len <= ifp->if_mtu) {
+#ifndef sparc
+ ip->ip_id = htons(ip->ip_id);
+ ip->ip_len = htons(ip->ip_len);
+ ip->ip_off = htons(ip->ip_off);
+#endif
+ if (!ip->ip_sum)
+ ip->ip_sum = in_cksum(m, hlen);
+#if BSD >= 199306
+ error = (*ifp->if_output)(ifp, m, (struct sockaddr *)dst,
+ ro->ro_rt);
+
+#else
+ error = (*ifp->if_output)(ifp, m, (struct sockaddr *)dst);
+#endif
+ goto done;
+ }
+ /*
+ * Too large for interface; fragment if possible.
+ * Must be able to put at least 8 bytes per fragment.
+ */
+ if (ip->ip_off & IP_DF) {
+ error = EMSGSIZE;
+ goto bad;
+ }
+ len = (ifp->if_mtu - hlen) &~ 7;
+ if (len < 8) {
+ error = EMSGSIZE;
+ goto bad;
+ }
+
+ {
+ int mhlen, firstlen = len;
+ struct mbuf **mnext = &m->m_act;
+
+ /*
+ * Loop through length of segment after first fragment,
+ * make new header and copy data of each part and link onto chain.
+ */
+ m0 = m;
+ mhlen = sizeof (struct ip);
+ for (off = hlen + len; off < ip->ip_len; off += len) {
+ MGET(m, M_DONTWAIT, MT_HEADER);
+ if (m == 0) {
+ error = ENOBUFS;
+ goto bad;
+ }
+#if BSD >= 199306
+ m->m_data += max_linkhdr;
+#else
+ m->m_off = MMAXOFF - hlen;
+#endif
+ mhip = mtod(m, struct ip *);
+ bcopy((char *)ip, (char *)mhip, sizeof(*ip));
+ if (hlen > sizeof (struct ip)) {
+ mhlen = ip_optcopy(ip, mhip) + sizeof (struct ip);
+ mhip->ip_hl = mhlen >> 2;
+ }
+ m->m_len = mhlen;
+ mhip->ip_off = ((off - hlen) >> 3) + (ip->ip_off & ~IP_MF);
+ if (ip->ip_off & IP_MF)
+ mhip->ip_off |= IP_MF;
+ if (off + len >= ip->ip_len)
+ len = ip->ip_len - off;
+ else
+ mhip->ip_off |= IP_MF;
+ mhip->ip_len = htons((u_short)(len + mhlen));
+ m->m_next = m_copy(m0, off, len);
+ if (m->m_next == 0) {
+ error = ENOBUFS; /* ??? */
+ goto sendorfree;
+ }
+#ifndef sparc
+ mhip->ip_off = htons((u_short)mhip->ip_off);
+#endif
+ mhip->ip_sum = 0;
+ mhip->ip_sum = in_cksum(m, mhlen);
+ *mnext = m;
+ mnext = &m->m_act;
+ }
+ /*
+ * Update first fragment by trimming what's been copied out
+ * and updating header, then send each fragment (in order).
+ */
+ m_adj(m0, hlen + firstlen - ip->ip_len);
+ ip->ip_len = htons((u_short)(hlen + firstlen));
+ ip->ip_off = htons((u_short)(ip->ip_off | IP_MF));
+ ip->ip_sum = 0;
+ ip->ip_sum = in_cksum(m0, hlen);
+sendorfree:
+ for (m = m0; m; m = m0) {
+ m0 = m->m_act;
+ m->m_act = 0;
+ if (error == 0)
+#if BSD >= 199306
+ error = (*ifp->if_output)(ifp, m,
+ (struct sockaddr *)dst, ro->ro_rt);
+#else
+ error = (*ifp->if_output)(ifp, m,
+ (struct sockaddr *)dst);
+#endif
+ else
+ m_freem(m);
+ }
+ }
+done:
+ if (ro->ro_rt) {
+ RTFREE(ro->ro_rt);
+ }
+ return;
+bad:
+ m_freem(m);
+ goto done;
+}
diff --git a/contrib/ipfilter/ip_fil.h b/contrib/ipfilter/ip_fil.h
new file mode 100644
index 000000000000..389a161bc2df
--- /dev/null
+++ b/contrib/ipfilter/ip_fil.h
@@ -0,0 +1,293 @@
+/*
+ * (C)opyright 1993-1996 by Darren Reed.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that this notice is preserved and due credit is given
+ * to the original author and the contributors.
+ *
+ * @(#)ip_fil.h 1.35 6/5/96
+ * $Id: ip_fil.h,v 2.0.1.2 1997/01/10 00:28:15 darrenr Exp $
+ */
+
+#ifndef __IP_FIL_H__
+#define __IP_FIL_H__
+
+#ifndef SOLARIS
+#define SOLARIS (defined(sun) && (defined(__svr4__) || defined(__SVR4)))
+#endif
+
+#if defined(KERNEL) && !defined(_KERNEL)
+#define _KERNEL
+#endif
+#if SOLARIS
+# include <sys/ioccom.h>
+# include <sys/sysmacros.h>
+# ifdef _KERNEL
+# include <inet/common.h>
+/*
+ * because Solaris 2 defines these in two places :-/
+ */
+#undef IPOPT_EOL
+#undef IPOPT_NOP
+#undef IPOPT_LSRR
+#undef IPOPT_RR
+#undef IPOPT_SSRR
+# include <inet/ip.h>
+# endif
+#endif
+
+#if defined(__STDC__) || defined(__GNUC__)
+#define SIOCADAFR _IOW('r', 60, struct frentry)
+#define SIOCRMAFR _IOW('r', 61, struct frentry)
+#define SIOCSETFF _IOW('r', 62, u_int)
+#define SIOCGETFF _IOR('r', 63, u_int)
+#define SIOCGETFS _IOR('r', 64, struct friostat)
+#define SIOCIPFFL _IOWR('r', 65, int)
+#define SIOCIPFFB _IOR('r', 66, int)
+#define SIOCADIFR _IOW('r', 67, struct frentry)
+#define SIOCRMIFR _IOW('r', 68, struct frentry)
+#define SIOCSWAPA _IOR('r', 69, u_int)
+#define SIOCINAFR _IOW('r', 70, struct frentry)
+#define SIOCINIFR _IOW('r', 71, struct frentry)
+#define SIOCFRENB _IOW('r', 72, u_int)
+#define SIOCFRSYN _IOW('r', 73, u_int)
+#define SIOCFRZST _IOWR('r', 74, struct friostat)
+#define SIOCZRLST _IOWR('r', 75, struct frentry)
+#else
+#define SIOCADAFR _IOW(r, 60, struct frentry)
+#define SIOCRMAFR _IOW(r, 61, struct frentry)
+#define SIOCSETFF _IOW(r, 62, u_int)
+#define SIOCGETFF _IOR(r, 63, u_int)
+#define SIOCGETFS _IOR(r, 64, struct friostat)
+#define SIOCIPFFL _IOWR(r, 65, int)
+#define SIOCIPFFB _IOR(r, 66, int)
+#define SIOCADIFR _IOW(r, 67, struct frentry)
+#define SIOCRMIFR _IOW(r, 68, struct frentry)
+#define SIOCSWAPA _IOR(r, 69, u_int)
+#define SIOCINAFR _IOW(r, 70, struct frentry)
+#define SIOCINIFR _IOW(r, 71, struct frentry)
+#define SIOCFRENB _IOW(r, 72, u_int)
+#define SIOCFRSYN _IOW(r, 73, u_int)
+#define SIOCFRZST _IOWR(r, 74, struct friostat)
+#define SIOCZRLST _IOWR(r, 75, struct frentry)
+#endif
+#define SIOCADDFR SIOCADAFR
+#define SIOCDELFR SIOCRMAFR
+#define SIOCINSFR SIOCINAFR
+
+typedef struct fr_ip {
+ u_char fi_v:4; /* IP version */
+ u_char fi_fl:4; /* packet flags */
+ u_char fi_tos;
+ u_char fi_ttl;
+ u_char fi_p;
+ struct in_addr fi_src;
+ struct in_addr fi_dst;
+ u_long fi_optmsk; /* bitmask composed from IP options */
+ u_short fi_secmsk; /* bitmask composed from IP security options */
+ u_short fi_auth;
+} fr_ip_t;
+
+#define FI_OPTIONS 0x01
+#define FI_TCPUDP 0x02 /* TCP/UCP implied comparison involved */
+#define FI_FRAG 0x04
+#define FI_SHORT 0x08
+
+typedef struct fr_info {
+ struct fr_ip fin_fi;
+ void *fin_ifp;
+ u_short fin_data[2];
+ u_short fin_out;
+ u_char fin_tcpf;
+ u_char fin_icode;
+ u_short fin_rule;
+ u_short fin_hlen;
+ u_short fin_dlen;
+ char *fin_dp; /* start of data past IP header */
+ struct frentry *fin_fr;
+} fr_info_t;
+
+#define FI_CSIZE (sizeof(struct fr_ip) + 11)
+
+typedef struct frdest {
+ void *fd_ifp;
+ struct in_addr fd_ip;
+ char fd_ifname[IFNAMSIZ];
+} frdest_t;
+
+typedef struct frentry {
+ struct frentry *fr_next;
+ struct ifnet *fr_ifa;
+ u_long fr_hits;
+ u_long fr_bytes; /* this is only incremented when a packet */
+ /* matches this rule and it is the last match*/
+ /*
+ * Fields after this may not change whilst in the kernel.
+ */
+ struct fr_ip fr_ip;
+ struct fr_ip fr_mip; /* mask structure */
+
+ u_char fr_tcpfm; /* tcp flags mask */
+ u_char fr_tcpf; /* tcp flags */
+
+ u_short fr_icmpm; /* data for ICMP packets (mask) */
+ u_short fr_icmp;
+
+ u_char fr_scmp; /* data for port comparisons */
+ u_char fr_dcmp;
+ u_short fr_dport;
+ u_short fr_sport;
+ u_short fr_stop; /* top port for <> and >< */
+ u_short fr_dtop; /* top port for <> and >< */
+ u_long fr_flags; /* per-rule flags && options (see below) */
+ int (*fr_func)(); /* call this function */
+ char fr_icode; /* return ICMP code */
+ char fr_ifname[IFNAMSIZ];
+ struct frdest fr_tif; /* "to" interface */
+ struct frdest fr_dif; /* duplicate packet interfaces */
+} frentry_t;
+
+#define fr_proto fr_ip.fi_p
+#define fr_ttl fr_ip.fi_ttl
+#define fr_tos fr_ip.fi_tos
+#define fr_dst fr_ip.fi_dst
+#define fr_src fr_ip.fi_src
+#define fr_dmsk fr_mip.fi_dst
+#define fr_smsk fr_mip.fi_src
+
+#ifndef offsetof
+#define offsetof(t,m) (int)((&((t *)0L)->m))
+#endif
+#define FR_CMPSIZ (sizeof(struct frentry) - offsetof(frentry_t, fr_ip))
+
+/*
+ * fr_flags
+*/
+#define FR_BLOCK 0x00001
+#define FR_PASS 0x00002
+#define FR_OUTQUE 0x00004
+#define FR_INQUE 0x00008
+#define FR_LOG 0x00010 /* Log */
+#define FR_LOGB 0x00011 /* Log-fail */
+#define FR_LOGP 0x00012 /* Log-pass */
+#define FR_LOGBODY 0x00020 /* Log the body */
+#define FR_LOGFIRST 0x00040 /* Log the first byte if state held */
+#define FR_RETRST 0x00080 /* Return TCP RST packet - reset connection */
+#define FR_RETICMP 0x00100 /* Return ICMP unreachable packet */
+#define FR_NOMATCH 0x00200
+#define FR_ACCOUNT 0x00400 /* count packet bytes */
+#define FR_KEEPFRAG 0x00800 /* keep fragment information */
+#define FR_KEEPSTATE 0x01000 /* keep `connection' state information */
+#define FR_INACTIVE 0x02000
+#define FR_QUICK 0x04000 /* match & stop processing list */
+#define FR_FASTROUTE 0x08000 /* bypass normal routing */
+#define FR_CALLNOW 0x10000 /* call another function (fr_func) if matches */
+#define FR_DUP 0x20000 /* duplicate packet */
+#define FR_LOGORBLOCK 0x40000 /* block the packet if it can't be logged */
+
+#define FR_LOGMASK (FR_LOG|FR_LOGP|FR_LOGB)
+/*
+ * recognized flags for SIOCGETFF and SIOCSETFF
+ */
+#define FF_LOGPASS 0x100000
+#define FF_LOGBLOCK 0x200000
+#define FF_LOGNOMATCH 0x400000
+#define FF_LOGGING (FF_LOGPASS|FF_LOGBLOCK|FF_LOGNOMATCH)
+#define FF_BLOCKNONIP 0x800000 /* Solaris2 Only */
+
+#define FR_NONE 0
+#define FR_EQUAL 1
+#define FR_NEQUAL 2
+#define FR_LESST 3
+#define FR_GREATERT 4
+#define FR_LESSTE 5
+#define FR_GREATERTE 6
+#define FR_OUTRANGE 7
+#define FR_INRANGE 8
+
+typedef struct filterstats {
+ u_long fr_pass; /* packets allowed */
+ u_long fr_block; /* packets denied */
+ u_long fr_nom; /* packets which don't match any rule */
+ u_long fr_ppkl; /* packets allowed and logged */
+ u_long fr_bpkl; /* packets denied and logged */
+ u_long fr_npkl; /* packets unmatched and logged */
+ u_long fr_pkl; /* packets logged */
+ u_long fr_skip; /* packets to be logged but buffer full */
+ u_long fr_ret; /* packets for which a return is sent */
+ u_long fr_acct; /* packets for which counting was performed */
+ u_long fr_bnfr; /* bad attempts to allocate fragment state */
+ u_long fr_nfr; /* new fragment state kept */
+ u_long fr_cfr; /* add new fragment state but complete pkt */
+ u_long fr_bads; /* bad attempts to allocate packet state */
+ u_long fr_ads; /* new packet state kept */
+ u_long fr_chit; /* cached hit */
+ u_long fr_pull[2]; /* good and bad pullup attempts */
+#if SOLARIS
+ u_long fr_bad; /* bad IP packets to the filter */
+ u_long fr_notip; /* packets passed through no on ip queue */
+ u_long fr_drop; /* packets dropped - no info for them! */
+#endif
+} filterstats_t;
+
+/*
+ * For SIOCGETFS
+ */
+typedef struct friostat {
+ struct filterstats f_st[2];
+ struct frentry *f_fin[2];
+ struct frentry *f_fout[2];
+ struct frentry *f_acctin[2];
+ struct frentry *f_acctout[2];
+ int f_active;
+} friostat_t;
+
+typedef struct optlist {
+ u_short ol_val;
+ int ol_bit;
+} optlist_t;
+
+/*
+ * Log structure. Each packet header logged is prepended by one of these,
+ * minimize size to make most effective use of log space which should
+ * (ideally) be a muliple of the most common log entry size.
+ */
+typedef struct ipl_ci {
+ u_long sec;
+ u_long usec;
+ u_char hlen;
+ u_char plen;
+ u_short rule; /* assume never more than 64k rules, total */
+#if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199603))
+ u_long flags;
+ u_char ifname[IFNAMSIZ]; /* = 32 bytes */
+#else
+ u_long flags:24;
+ u_long unit:8;
+ u_char ifname[4]; /* = 20 bytes */
+#endif
+} ipl_ci_t;
+
+
+#ifndef ICMP_UNREACH_FILTER
+#define ICMP_UNREACH_FILTER 13
+#endif
+
+#define IPMINLEN(i, h) ((i)->ip_len >= ((i)->ip_hl * 4 + sizeof(struct h)))
+#define IPLLOGSIZE 8192
+
+extern int fr_check();
+extern int fr_copytolog();
+extern fr_info_t frcache[];
+extern char *iplh, *iplt;
+extern char iplbuf[IPLLOGSIZE];
+
+#ifdef _KERNEL
+
+extern struct frentry *ipfilter[2][2], *ipacct[2][2];
+extern struct filterstats frstats[];
+# if SOLARIS
+extern int ipfsync();
+# endif
+#endif /* _KERNEL */
+#endif /* __IP_FIL_H__ */
diff --git a/contrib/ipfilter/ip_frag.c b/contrib/ipfilter/ip_frag.c
new file mode 100644
index 000000000000..6665404b9830
--- /dev/null
+++ b/contrib/ipfilter/ip_frag.c
@@ -0,0 +1,278 @@
+/*
+ * (C)opyright 1993,1994,1995 by Darren Reed.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that this notice is preserved and due credit is given
+ * to the original author and the contributors.
+ */
+#if !defined(lint) && defined(LIBC_SCCS)
+static char sccsid[] = "@(#)ip_frag.c 1.11 3/24/96 (C) 1993-1995 Darren Reed";
+static char rcsid[] = "$Id: ip_frag.c,v 2.0.1.1 1997/01/09 15:14:43 darrenr Exp $";
+#endif
+
+#if !defined(_KERNEL) && !defined(KERNEL)
+# include <string.h>
+# include <stdlib.h>
+#endif
+#include <sys/errno.h>
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/file.h>
+#include <sys/ioctl.h>
+#include <sys/uio.h>
+#include <sys/protosw.h>
+#include <sys/socket.h>
+#ifdef _KERNEL
+# include <sys/systm.h>
+#endif
+#if !defined(__SVR4) && !defined(__svr4__)
+# include <sys/mbuf.h>
+#else
+# include <sys/byteorder.h>
+# include <sys/dditypes.h>
+# include <sys/stream.h>
+# include <sys/kmem.h>
+#endif
+
+#include <net/if.h>
+#ifdef sun
+#include <net/af.h>
+#endif
+#include <net/route.h>
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/ip_var.h>
+#include <netinet/tcp.h>
+#include <netinet/udp.h>
+#include <netinet/tcpip.h>
+#include <netinet/ip_icmp.h>
+#include "ip_fil.h"
+#include "ip_compat.h"
+#include "ip_frag.h"
+#include "ip_nat.h"
+#include "ip_state.h"
+
+ipfr_t *ipfr_heads[IPFT_SIZE];
+ipfrstat_t ipfr_stats;
+u_long ipfr_inuse = 0,
+ fr_ipfrttl = 120; /* 60 seconds */
+#ifdef _KERNEL
+extern int ipfr_timer_id;
+#endif
+#if SOLARIS
+# ifdef _KERNEL
+extern kmutex_t ipf_frag;
+# else
+#define bcmp(a,b,c) memcmp(a,b,c)
+#define bcopy(a,b,c) memmove(b,a,c)
+# endif
+#endif
+
+
+ipfrstat_t *ipfr_fragstats()
+{
+ ipfr_stats.ifs_table = ipfr_heads;
+ ipfr_stats.ifs_inuse = ipfr_inuse;
+ return &ipfr_stats;
+}
+
+
+/*
+ * add a new entry to the fragment cache, registering it as having come
+ * through this box, with the result of the filter operation.
+ */
+int ipfr_newfrag(ip, fin, pass)
+ip_t *ip;
+fr_info_t *fin;
+int pass;
+{
+ ipfr_t **fp, *fr, frag;
+ u_int idx;
+
+ frag.ipfr_p = ip->ip_p;
+ idx = ip->ip_p;
+ frag.ipfr_id = ip->ip_id;
+ idx += ip->ip_id;
+ frag.ipfr_tos = ip->ip_tos;
+ frag.ipfr_src.s_addr = ip->ip_src.s_addr;
+ idx += ip->ip_src.s_addr;
+ frag.ipfr_dst.s_addr = ip->ip_dst.s_addr;
+ idx += ip->ip_dst.s_addr;
+ idx *= 127;
+ idx %= IPFT_SIZE;
+
+ /*
+ * first, make sure it isn't already there...
+ */
+ MUTEX_ENTER(&ipf_frag);
+ for (fp = &ipfr_heads[idx]; (fr = *fp); fp = &fr->ipfr_next)
+ if (!bcmp((char *)&frag.ipfr_src, (char *)&fr->ipfr_src,
+ IPFR_CMPSZ)) {
+ ipfr_stats.ifs_exists++;
+ MUTEX_EXIT(&ipf_frag);
+ return -1;
+ }
+
+ if (!(fr = (ipfr_t *)KMALLOC(sizeof(*fr)))) {
+ ipfr_stats.ifs_nomem++;
+ MUTEX_EXIT(&ipf_frag);
+ return -1;
+ }
+ if ((fr->ipfr_next = ipfr_heads[idx]))
+ ipfr_heads[idx]->ipfr_prev = fr;
+ fr->ipfr_prev = NULL;
+ ipfr_heads[idx] = fr;
+ bcopy((char *)&frag.ipfr_src, (char *)&fr->ipfr_src, IPFR_CMPSZ);
+ fr->ipfr_ttl = fr_ipfrttl;
+ fr->ipfr_pass = pass & ~(FR_LOGFIRST|FR_LOG);
+ fr->ipfr_off = (ip->ip_off & 0x1fff) + (fin->fin_dlen >> 3);
+ *fp = fr;
+ ipfr_stats.ifs_new++;
+ ipfr_inuse++;
+ MUTEX_EXIT(&ipf_frag);
+ return 0;
+}
+
+
+/*
+ * check the fragment cache to see if there is already a record of this packet
+ * with its filter result known.
+ */
+int ipfr_knownfrag(ip, fin)
+ip_t *ip;
+fr_info_t *fin;
+{
+ ipfr_t *f, frag;
+ u_int idx;
+ int ret;
+
+ /*
+ * For fragments, we record protocol, packet id, TOS and both IP#'s
+ * (these should all be the same for all fragments of a packet).
+ */
+ frag.ipfr_p = ip->ip_p;
+ idx = ip->ip_p;
+ frag.ipfr_id = ip->ip_id;
+ idx += ip->ip_id;
+ frag.ipfr_tos = ip->ip_tos;
+ frag.ipfr_src.s_addr = ip->ip_src.s_addr;
+ idx += ip->ip_src.s_addr;
+ frag.ipfr_dst.s_addr = ip->ip_dst.s_addr;
+ idx += ip->ip_dst.s_addr;
+ idx *= 127;
+ idx %= IPFT_SIZE;
+
+ MUTEX_ENTER(&ipf_frag);
+ for (f = ipfr_heads[idx]; f; f = f->ipfr_next)
+ if (!bcmp((char *)&frag.ipfr_src, (char *)&f->ipfr_src,
+ IPFR_CMPSZ)) {
+ u_short atoff, off;
+
+ if (f != ipfr_heads[idx]) {
+ /*
+ * move fragment info. to the top of the list
+ * to speed up searches.
+ */
+ if ((f->ipfr_prev->ipfr_next = f->ipfr_next))
+ f->ipfr_next->ipfr_prev = f->ipfr_prev;
+ f->ipfr_next = ipfr_heads[idx];
+ ipfr_heads[idx]->ipfr_prev = f;
+ f->ipfr_prev = NULL;
+ ipfr_heads[idx] = f;
+ }
+ ret = f->ipfr_pass;
+ off = ip->ip_off;
+ atoff = (off & 0x1fff) - (fin->fin_dlen >> 3);
+ /*
+ * If we've follwed the fragments, and this is the
+ * last (in order), shrink expiration time.
+ */
+ if (atoff == f->ipfr_off) {
+ if (!(off & IP_MF))
+ f->ipfr_ttl = 1;
+ else
+ f->ipfr_off = off;
+ }
+ ipfr_stats.ifs_hits++;
+ MUTEX_EXIT(&ipf_frag);
+ return ret;
+ }
+ MUTEX_EXIT(&ipf_frag);
+ return 0;
+}
+
+
+/*
+ * Free memory in use by fragment state info. kept.
+ */
+void ipfr_unload()
+{
+ ipfr_t **fp, *fr;
+ int idx;
+#if !SOLARIS && defined(_KERNEL)
+ int s;
+#endif
+
+ MUTEX_ENTER(&ipf_frag);
+ SPLNET(s);
+ for (idx = IPFT_SIZE - 1; idx >= 0; idx--)
+ for (fp = &ipfr_heads[idx]; (fr = *fp); ) {
+ *fp = fr->ipfr_next;
+ KFREE(fr);
+ }
+ SPLX(s);
+ MUTEX_EXIT(&ipf_frag);
+}
+
+
+#ifdef _KERNEL
+/*
+ * Slowly expire held state for fragments. Timeouts are set * in expectation
+ * of this being called twice per second.
+ */
+# if BSD < 199306
+int ipfr_slowtimer()
+# else
+void ipfr_slowtimer()
+# endif
+{
+ ipfr_t **fp, *fr;
+ int s, idx;
+
+ MUTEX_ENTER(&ipf_frag);
+ SPLNET(s);
+
+ for (idx = IPFT_SIZE - 1; idx >= 0; idx--)
+ for (fp = &ipfr_heads[idx]; (fr = *fp); ) {
+ --fr->ipfr_ttl;
+ if (fr->ipfr_ttl == 0) {
+ if (fr->ipfr_prev)
+ fr->ipfr_prev->ipfr_next =
+ fr->ipfr_next;
+ if (fr->ipfr_next)
+ fr->ipfr_next->ipfr_prev =
+ fr->ipfr_prev;
+ *fp = fr->ipfr_next;
+ ipfr_stats.ifs_expire++;
+ ipfr_inuse--;
+ KFREE(fr);
+ } else
+ fp = &fr->ipfr_next;
+ }
+ SPLX(s);
+# if SOLARIS
+ MUTEX_EXIT(&ipf_frag);
+ fr_timeoutstate();
+ ip_natexpire();
+ ipfr_timer_id = timeout(ipfr_slowtimer, NULL, HZ/2);
+# else
+ fr_timeoutstate();
+ ip_natexpire();
+ ip_slowtimo();
+# if BSD < 199306
+ return 0;
+# endif
+# endif
+}
+#endif /* defined(_KERNEL) */
diff --git a/contrib/ipfilter/ip_frag.h b/contrib/ipfilter/ip_frag.h
new file mode 100644
index 000000000000..a356785e528c
--- /dev/null
+++ b/contrib/ipfilter/ip_frag.h
@@ -0,0 +1,47 @@
+/*
+ * (C)opyright 1993, 1994, 1995 by Darren Reed.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that this notice is preserved and due credit is given
+ * to the original author and the contributors.
+ *
+ * @(#)ip_frag.h 1.5 3/24/96
+ * $Id: ip_frag.h,v 2.0.1.1 1997/01/09 15:14:43 darrenr Exp $
+ */
+
+#ifndef __IP_FRAG_H_
+#define __IP_FRAG_H__
+
+#define IPFT_SIZE 257
+
+typedef struct ipfr {
+ struct ipfr *ipfr_next, *ipfr_prev;
+ struct in_addr ipfr_src;
+ struct in_addr ipfr_dst;
+ u_short ipfr_id;
+ u_char ipfr_p;
+ u_char ipfr_tos;
+ u_short ipfr_off;
+ u_short ipfr_ttl;
+ u_char ipfr_pass;
+} ipfr_t;
+
+
+typedef struct ipfrstat {
+ u_long ifs_exists; /* add & already exists */
+ u_long ifs_nomem;
+ u_long ifs_new;
+ u_long ifs_hits;
+ u_long ifs_expire;
+ u_long ifs_inuse;
+ struct ipfr **ifs_table;
+} ipfrstat_t;
+
+#define IPFR_CMPSZ (4 + 4 + 2 + 1 + 1)
+
+extern ipfrstat_t *ipfr_fragstats();
+extern int ipfr_newfrag(), ipfr_knownfrag();
+# ifdef _KERNEL
+extern void ipfr_unload();
+# endif
+#endif /* __IP_FIL_H__ */
diff --git a/contrib/ipfilter/ip_nat.c b/contrib/ipfilter/ip_nat.c
new file mode 100644
index 000000000000..afe9761bc093
--- /dev/null
+++ b/contrib/ipfilter/ip_nat.c
@@ -0,0 +1,886 @@
+/*
+ * (C)opyright 1995-1996 by Darren Reed.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that this notice is preserved and due credit is given
+ * to the original author and the contributors.
+ *
+ * Added redirect stuff and a LOT of bug fixes. (mcn@EnGarde.com)
+ */
+#if !defined(lint) && defined(LIBC_SCCS)
+static char sccsid[] = "@(#)ip_nat.c 1.11 6/5/96 (C) 1995 Darren Reed";
+static char rcsid[] = "$Id: ip_nat.c,v 2.0.1.10 1997/02/08 06:38:49 darrenr Exp $";
+#endif
+
+#if !defined(_KERNEL) && !defined(KERNEL)
+# include <stdio.h>
+# include <string.h>
+# include <stdlib.h>
+#endif
+#include <sys/errno.h>
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/file.h>
+#include <sys/ioctl.h>
+#include <sys/uio.h>
+#include <sys/protosw.h>
+#include <sys/socket.h>
+#ifdef _KERNEL
+# include <sys/systm.h>
+#endif
+#if !defined(__SVR4) && !defined(__svr4__)
+# include <sys/mbuf.h>
+#else
+# include <sys/byteorder.h>
+# include <sys/dditypes.h>
+# include <sys/stream.h>
+# include <sys/kmem.h>
+#endif
+
+#include <net/if.h>
+#ifdef sun
+#include <net/af.h>
+#endif
+#include <net/route.h>
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+
+#ifdef RFC1825
+#include <vpn/md5.h>
+#include <vpn/ipsec.h>
+extern struct ifnet vpnif;
+#endif
+
+#include <netinet/ip_var.h>
+#include <netinet/tcp.h>
+#include <netinet/udp.h>
+#include <netinet/tcpip.h>
+#include <netinet/ip_icmp.h>
+#include "ip_fil.h"
+#include "ip_compat.h"
+#include "ip_nat.h"
+#include "ip_state.h"
+#ifndef MIN
+#define MIN(a,b) (((a)<(b))?(a):(b))
+#endif
+
+nat_t *nat_table[2][NAT_SIZE], *nat_instances = NULL;
+ipnat_t *nat_list = NULL;
+u_long nat_inuse = 0,
+ fr_defnatage = 1200;
+natstat_t nat_stats;
+#if SOLARIS
+# ifndef _KERNEL
+#define bzero(a,b) memset(a,0,b)
+#define bcmp(a,b,c) memcpy(a,b,c)
+#define bcopy(a,b,c) memmove(b,a,c)
+# else
+extern kmutex_t ipf_nat;
+# endif
+#endif
+
+static int flush_nattable(), clear_natlist();
+static void nattable_sync();
+
+void fix_outcksum(sp, n)
+u_short *sp;
+u_long n;
+{
+ register u_short sumshort;
+ register u_long sum1;
+
+#ifdef sparc
+ sum1 = (~(*sp)) & 0xffff;
+#else
+ sum1 = (~ntohs(*sp)) & 0xffff;
+#endif
+ sum1 += (n);
+ sum1 = (sum1 >> 16) + (sum1 & 0xffff);
+ /* Again */
+ sum1 = (sum1 >> 16) + (sum1 & 0xffff);
+ sumshort = ~(u_short)sum1;
+ *(sp) = htons(sumshort);
+}
+
+
+void fix_incksum(sp, n)
+u_short *sp;
+u_long n;
+{
+ register u_short sumshort;
+ register u_long sum1;
+
+#ifdef sparc
+ sum1 = (~(*sp)) & 0xffff;
+#else
+ sum1 = (~ntohs(*sp)) & 0xffff;
+#endif
+ sum1 += ~(n) & 0xffff;
+ sum1 = (sum1 >> 16) + (sum1 & 0xffff);
+ /* Again */
+ sum1 = (sum1 >> 16) + (sum1 & 0xffff);
+ sumshort = ~(u_short)sum1;
+ *(sp) = htons(sumshort);
+}
+
+
+/*
+ * How the NAT is organised and works.
+ *
+ * Inside (interface y) NAT Outside (interface x)
+ * -------------------- -+- -------------------------------------
+ * Packet going | out, processsed by ip_natout() for x
+ * ------------> | ------------>
+ * src=10.1.1.1 | src=192.1.1.1
+ * |
+ * | in, processed by ip_natin() for x
+ * <------------ | <------------
+ * dst=10.1.1.1 | dst=192.1.1.1
+ * -------------------- -+- -------------------------------------
+ * ip_natout() - changes ip_src and if required, sport
+ * - creates a new mapping, if required.
+ * ip_natin() - changes ip_dst and if required, dport
+ *
+ * In the NAT table, internal source is recorded as "in" and externally
+ * seen as "out".
+ */
+
+/*
+ * Handle ioctls which manipulate the NAT.
+ */
+int nat_ioctl(data, cmd, mode)
+caddr_t data;
+int cmd, mode;
+{
+ register ipnat_t *nat, *n = NULL, **np = NULL;
+ ipnat_t natd;
+ int error = 0, ret;
+
+ /*
+ * For add/delete, look to see if the NAT entry is already present
+ */
+ MUTEX_ENTER(&ipf_nat);
+ if ((cmd == SIOCADNAT) || (cmd == SIOCRMNAT)) {
+ IRCOPY(data, (char *)&natd, sizeof(natd));
+ nat = &natd;
+ for (np = &nat_list; (n = *np); np = &n->in_next)
+ if (!bcmp((char *)&nat->in_flags, (char *)&n->in_flags,
+ IPN_CMPSIZ))
+ break;
+ }
+
+ switch (cmd)
+ {
+ case SIOCADNAT :
+ if (!(mode & FWRITE)) {
+ error = EPERM;
+ break;
+ }
+ if (n) {
+ error = EEXIST;
+ break;
+ }
+ if (!(n = (ipnat_t *)KMALLOC(sizeof(*n)))) {
+ error = ENOMEM;
+ break;
+ }
+ IRCOPY((char *)data, (char *)n, sizeof(*n));
+ n->in_ifp = (void *)GETUNIT(n->in_ifname);
+ n->in_next = *np;
+ n->in_use = 0;
+ n->in_space = ~(0xffffffff & ntohl(n->in_outmsk));
+ if (n->in_space) /* lose 2: broadcast + network address */
+ n->in_space -= 2;
+ else
+ n->in_space = 1; /* single IP# mapping */
+ if (n->in_outmsk != 0xffffffff)
+ n->in_nip = ntohl(n->in_outip) + 1;
+ else
+ n->in_nip = ntohl(n->in_outip);
+ if (n->in_redir == NAT_MAP) {
+ n->in_pnext = ntohs(n->in_pmin);
+ /*
+ * Multiply by the number of ports made available.
+ */
+ if (ntohs(n->in_pmax) > ntohs(n->in_pmin))
+ n->in_space *= (ntohs(n->in_pmax) -
+ ntohs(n->in_pmin));
+ }
+ /* Otherwise, these fields are preset */
+ *np = n;
+ break;
+ case SIOCRMNAT :
+ if (!(mode & FWRITE)) {
+ error = EPERM;
+ break;
+ }
+ if (!n) {
+ error = ESRCH;
+ break;
+ }
+ *np = n->in_next;
+
+ KFREE(n);
+ nattable_sync();
+ break;
+ case SIOCGNATS :
+ nat_stats.ns_table[0] = nat_table[0];
+ nat_stats.ns_table[1] = nat_table[1];
+ nat_stats.ns_list = nat_list;
+ nat_stats.ns_inuse = nat_inuse;
+ IWCOPY((char *)&nat_stats, (char *)data, sizeof(nat_stats));
+ break;
+ case SIOCGNATL :
+ {
+ natlookup_t nl;
+
+ IRCOPY((char *)data, (char *)&nl, sizeof(nl));
+
+ if (nat_lookupredir(&nl))
+ IWCOPY((char *)&nl, (char *)data, sizeof(nl));
+ else
+ error = ESRCH;
+ break;
+ }
+ case SIOCFLNAT :
+ if (!(mode & FWRITE)) {
+ error = EPERM;
+ break;
+ }
+ ret = flush_nattable();
+ IWCOPY((caddr_t)&ret, data, sizeof(ret));
+ break;
+ case SIOCCNATL :
+ if (!(mode & FWRITE)) {
+ error = EPERM;
+ break;
+ }
+ ret = clear_natlist();
+ IWCOPY((caddr_t)&ret, data, sizeof(ret));
+ break;
+ }
+ MUTEX_EXIT(&ipf_nat);
+ return error;
+}
+
+
+static void nat_delete(natd)
+struct nat *natd;
+{
+ register struct nat **natp, *nat;
+
+ for (natp = natd->nat_hstart[0]; (nat = *natp);
+ natp = &nat->nat_hnext[0])
+ if (nat == natd) {
+ *natp = nat->nat_hnext[0];
+ break;
+ }
+
+ for (natp = natd->nat_hstart[1]; (nat = *natp);
+ natp = &nat->nat_hnext[1])
+ if (nat == natd) {
+ *natp = nat->nat_hnext[1];
+ break;
+ }
+
+ if (natd->nat_ptr) {
+ natd->nat_ptr->in_space++;
+ natd->nat_ptr->in_use--;
+ }
+ KFREE(natd);
+ nat_inuse--;
+}
+
+
+/*
+ * flush_nattable - clear the NAT table of all mapping entries.
+ */
+static int flush_nattable()
+{
+ register nat_t *nat, **natp;
+ register int j = 0;
+
+ /*
+ * Everything will be deleted, so lets just make it the deletions
+ * quicker.
+ */
+ bzero((char *)nat_table[0], sizeof(nat_table[0]));
+ bzero((char *)nat_table[1], sizeof(nat_table[1]));
+
+ for (natp = &nat_instances; (nat = *natp); ) {
+ *natp = nat->nat_next;
+ nat_delete(nat);
+ j++;
+ }
+
+ return j;
+}
+
+
+/*
+ * I know this is O(N*M), but it can't be avoided.
+ */
+static void nattable_sync()
+{
+ register nat_t *nat;
+ register ipnat_t *np;
+ int i;
+
+ for (i = NAT_SIZE - 1; i >= 0; i--)
+ for (nat = nat_instances; nat; nat = nat->nat_next) {
+ for (np = nat_list; np; np = np->in_next)
+ if (nat->nat_ptr == np)
+ break;
+ /*
+ * XXX - is it better to remove this if ? works the
+ * same if it is just "nat->nat_ptr = np".
+ */
+ if (!np)
+ nat->nat_ptr = NULL;
+ }
+}
+
+
+/*
+ * clear_natlist - delete all entries in the active NAT mapping list.
+ */
+static int clear_natlist()
+{
+ register ipnat_t *n, **np;
+ int i = 0;
+
+ for (np = &nat_list; (n = *np); i++) {
+ *np = n->in_next;
+ KFREE(n);
+ }
+
+ nattable_sync();
+ return i;
+}
+
+
+/*
+ * Create a new NAT table entry.
+ */
+nat_t *nat_new(np, ip, fin, flags, direction)
+ipnat_t *np;
+ip_t *ip;
+fr_info_t *fin;
+u_short flags;
+int direction;
+{
+ register u_long sum1, sum2, sumd;
+ u_short port = 0, sport = 0, dport = 0, nport = 0;
+ struct in_addr in;
+ tcphdr_t *tcp = NULL;
+ nat_t *nat, **natp;
+ u_short nflags;
+
+ nflags = flags & np->in_flags;
+ if (flags & IPN_TCPUDP) {
+ tcp = (tcphdr_t *)fin->fin_dp;
+ sport = tcp->th_sport;
+ dport = tcp->th_dport;
+ }
+
+ /* Give me a new nat */
+ if (!(nat = (nat_t *)KMALLOC(sizeof(*nat))))
+ return NULL;
+
+ bzero((char *)nat, sizeof(*nat));
+
+ /*
+ * Search the current table for a match.
+ */
+ if (direction == NAT_OUTBOUND) {
+ /*
+ * If it's an outbound packet which doesn't match any existing
+ * record, then create a new port
+ */
+ do {
+ port = 0;
+ in.s_addr = np->in_nip;
+ if (nflags & IPN_TCPUDP) {
+ port = htons(np->in_pnext++);
+ if (np->in_pnext >= ntohs(np->in_pmax)) {
+ np->in_pnext = ntohs(np->in_pmin);
+ np->in_space--;
+ if (np->in_outmsk != 0xffffffff)
+ np->in_nip++;
+ }
+ } else if (np->in_outmsk != 0xffffffff) {
+ np->in_space--;
+ np->in_nip++;
+ }
+
+ if (!port && (flags & IPN_TCPUDP))
+ port = sport;
+ if ((np->in_nip & ntohl(np->in_outmsk)) >
+ ntohl(np->in_outip))
+ np->in_nip = ntohl(np->in_outip) + 1;
+ } while (nat_inlookup(flags, ip->ip_dst, dport, in, port));
+
+ /* Setup the NAT table */
+ nat->nat_inip = ip->ip_src;
+ nat->nat_outip.s_addr = htonl(in.s_addr);
+ nat->nat_oip = ip->ip_dst;
+
+ sum1 = (ntohl(ip->ip_src.s_addr) & 0xffff) +
+ (ntohl(ip->ip_src.s_addr) >> 16) + ntohs(sport);
+
+ sum2 = (in.s_addr & 0xffff) + (in.s_addr >> 16) + ntohs(port);
+
+ if (flags & IPN_TCPUDP) {
+ nat->nat_inport = sport;
+ nat->nat_outport = port;
+ nat->nat_oport = dport;
+ }
+ } else {
+
+ /*
+ * Otherwise, it's an inbound packet. Most likely, we don't
+ * want to rewrite source ports and source addresses. Instead,
+ * we want to rewrite to a fixed internal address and fixed
+ * internal port.
+ */
+ in.s_addr = ntohl(np->in_inip);
+ if (!(nport = np->in_pnext))
+ nport = dport;
+
+ nat->nat_inip.s_addr = htonl(in.s_addr);
+ nat->nat_outip = ip->ip_dst;
+ nat->nat_oip = ip->ip_src;
+
+ sum1 = (ntohl(ip->ip_dst.s_addr) & 0xffff) +
+ (ntohl(ip->ip_dst.s_addr) >> 16) + ntohs(dport);
+
+ sum2 = (in.s_addr & 0xffff) + (in.s_addr >> 16) + ntohs(nport);
+
+ if (flags & IPN_TCPUDP) {
+ nat->nat_inport = nport;
+ nat->nat_outport = dport;
+ nat->nat_oport = sport;
+ }
+ }
+
+ /* Do it twice */
+ sum1 = (sum1 & 0xffff) + (sum1 >> 16);
+ sum1 = (sum1 & 0xffff) + (sum1 >> 16);
+
+ /* Do it twice */
+ sum2 = (sum2 & 0xffff) + (sum2 >> 16);
+ sum2 = (sum2 & 0xffff) + (sum2 >> 16);
+
+ if (sum1 > sum2)
+ sum2--; /* Because ~1 == -2, We really need ~1 == -1 */
+ sumd = sum2 - sum1;
+ sumd = (sumd & 0xffff) + (sumd >> 16);
+ nat->nat_sumd = (sumd & 0xffff) + (sumd >> 16);
+
+ if ((flags & IPN_TCPUDP) && ((sport != port) || (dport != nport))) {
+ if (direction == NAT_OUTBOUND)
+ sum1 = (ntohl(ip->ip_src.s_addr) & 0xffff) +
+ (ntohl(ip->ip_src.s_addr) >> 16);
+ else
+ sum1 = (ntohl(ip->ip_dst.s_addr) & 0xffff) +
+ (ntohl(ip->ip_dst.s_addr) >> 16);
+
+ sum2 = (in.s_addr & 0xffff) + (in.s_addr >> 16);
+
+ /* Do it twice */
+ sum1 = (sum1 & 0xffff) + (sum1 >> 16);
+ sum1 = (sum1 & 0xffff) + (sum1 >> 16);
+
+ /* Do it twice */
+ sum2 = (sum2 & 0xffff) + (sum2 >> 16);
+ sum2 = (sum2 & 0xffff) + (sum2 >> 16);
+
+ if (sum1 > sum2)
+ sum2--; /* Because ~1 == -2, We really need ~1 == -1 */
+ sumd = sum2 - sum1;
+ sumd = (sumd & 0xffff) + (sumd >> 16);
+ nat->nat_ipsumd = (sumd & 0xffff) + (sumd >> 16);
+ } else
+ nat->nat_ipsumd = nat->nat_sumd;
+
+ in.s_addr = htonl(in.s_addr);
+ nat->nat_next = nat_instances;
+ nat_instances = nat;
+ natp = &nat_table[0][nat->nat_inip.s_addr % NAT_SIZE];
+ nat->nat_hstart[0] = natp;
+ nat->nat_hnext[0] = *natp;
+ *natp = nat;
+ natp = &nat_table[1][nat->nat_outip.s_addr % NAT_SIZE];
+ nat->nat_hstart[1] = natp;
+ nat->nat_hnext[1] = *natp;
+ *natp = nat;
+ nat->nat_ptr = np;
+ np->in_use++;
+ if (direction == NAT_OUTBOUND) {
+ if (flags & IPN_TCPUDP)
+ tcp->th_sport = htons(port);
+ } else {
+ if (flags & IPN_TCPUDP)
+ tcp->th_dport = htons(nport);
+ }
+ nat_stats.ns_added++;
+ nat_inuse++;
+ return nat;
+}
+
+
+/*
+ * NB: these lookups don't lock access to the list, it assume it has already
+ * been done!
+ */
+/*
+ * Lookup a nat entry based on the mapped destination ip address/port and
+ * real source address/port. We use this lookup when receiving a packet,
+ * we're looking for a table entry, based on the destination address.
+ * NOTE: THE PACKET BEING CHECKED (IF FOUND) HAS A MAPPING ALREADY.
+ */
+nat_t *nat_inlookup(flags, src, sport, mapdst, mapdport)
+register int flags;
+struct in_addr src , mapdst;
+u_short sport, mapdport;
+{
+ register nat_t *nat;
+
+ flags &= IPN_TCPUDP;
+
+ nat = nat_table[1][mapdst.s_addr % NAT_SIZE];
+ for (; nat; nat = nat->nat_hnext[1])
+ if (nat->nat_oip.s_addr == src.s_addr &&
+ nat->nat_outip.s_addr == mapdst.s_addr &&
+ (!flags || (nat->nat_oport == sport &&
+ nat->nat_outport == mapdport)))
+ return nat;
+ return NULL;
+}
+
+
+/*
+ * Lookup a nat entry based on the source 'real' ip address/port and
+ * destination address/port. We use this lookup when sending a packet out,
+ * we're looking for a table entry, based on the source address.
+ * NOTE: THE PACKET BEING CHECKED (IF FOUND) HAS A MAPPING ALREADY.
+ */
+nat_t *nat_outlookup(flags, src, sport, dst, dport)
+register int flags;
+struct in_addr src , dst;
+u_short sport, dport;
+{
+ register nat_t *nat;
+
+ flags &= IPN_TCPUDP;
+
+ nat = nat_table[0][src.s_addr % NAT_SIZE];
+ for (; nat; nat = nat->nat_hnext[0])
+ if (nat->nat_inip.s_addr == src.s_addr &&
+ nat->nat_oip.s_addr == dst.s_addr &&
+ (!flags || (nat->nat_inport == sport &&
+ nat->nat_oport == dport)))
+ return nat;
+ return NULL;
+}
+
+
+/*
+ * Lookup a nat entry based on the mapped source ip address/port and
+ * real destination address/port. We use this lookup when sending a packet
+ * out, we're looking for a table entry, based on the source address.
+ */
+nat_t *nat_lookupmapip(flags, mapsrc, mapsport, dst, dport)
+register int flags;
+struct in_addr mapsrc , dst;
+u_short mapsport, dport;
+{
+ register nat_t *nat;
+
+ flags &= IPN_TCPUDP;
+
+ nat = nat_table[1][mapsrc.s_addr % NAT_SIZE];
+ for (; nat; nat = nat->nat_hnext[0])
+ if (nat->nat_outip.s_addr == mapsrc.s_addr &&
+ nat->nat_oip.s_addr == dst.s_addr &&
+ (!flags || (nat->nat_outport == mapsport &&
+ nat->nat_oport == dport)))
+ return nat;
+ return NULL;
+}
+
+
+/*
+ * Lookup the NAT tables to search for a matching redirect
+ */
+nat_t *nat_lookupredir(np)
+register natlookup_t *np;
+{
+ nat_t *nat;
+
+ /*
+ * 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(IPN_TCPUDP, np->nl_inip, np->nl_inport,
+ np->nl_outip, np->nl_outport))) {
+ np->nl_inip = nat->nat_outip;
+ np->nl_inport = nat->nat_outport;
+ }
+ return nat;
+}
+
+
+/*
+ * Packets going out on the external interface go through this.
+ * Here, the source address requires alteration, if anything.
+ */
+int ip_natout(ip, hlen, fin)
+ip_t *ip;
+int hlen;
+fr_info_t *fin;
+{
+ register ipnat_t *np;
+ register u_long ipa;
+ tcphdr_t *tcp = NULL;
+ nat_t *nat;
+ u_short nflags = 0, sport = 0, dport = 0, *csump = NULL;
+ struct ifnet *ifp;
+ frentry_t *fr;
+
+ if ((fr = fin->fin_fr) && !(fr->fr_flags & FR_DUP) &&
+ fr->fr_tif.fd_ifp && fr->fr_tif.fd_ifp != (void *)-1)
+ ifp = fr->fr_tif.fd_ifp;
+ else
+ ifp = fin->fin_ifp;
+
+ if (!(ip->ip_off & 0x1fff) && !(fin->fin_fi.fi_fl & FI_SHORT)) {
+ if (ip->ip_p == IPPROTO_TCP)
+ nflags = IPN_TCP;
+ else if (ip->ip_p == IPPROTO_UDP)
+ nflags = IPN_UDP;
+ if (nflags) {
+ tcp = (tcphdr_t *)fin->fin_dp;
+ sport = tcp->th_sport;
+ dport = tcp->th_dport;
+ }
+ }
+
+ ipa = ip->ip_src.s_addr;
+
+ MUTEX_ENTER(&ipf_nat);
+ for (np = nat_list; np; np = np->in_next)
+ if ((np->in_ifp == ifp) && np->in_space &&
+ (!np->in_flags || (np->in_flags & nflags)) &&
+ ((ipa & np->in_inmsk) == np->in_inip) &&
+ ((np->in_redir == NAT_MAP) ||
+ (np->in_pnext == sport))) {
+ /*
+ * If there is no current entry in the nat table for
+ * this IP#, create one for it.
+ */
+ if (!(nat = nat_outlookup(nflags, ip->ip_src, sport,
+ ip->ip_dst, dport))) {
+ if (np->in_redir == NAT_REDIRECT)
+ continue;
+ /*
+ * if it's a redirection, then we don't want
+ * to create new outgoing port stuff.
+ * Redirections are only for incoming
+ * connections.
+ */
+ if (!(nat = nat_new(np, ip, fin, nflags,
+ NAT_OUTBOUND)))
+ break;
+ }
+ ip->ip_src = nat->nat_outip;
+
+ nat->nat_age = fr_defnatage; /* 5 mins */
+
+ /*
+ * Fix up checksums, not by recalculating them, but
+ * simply computing adjustments.
+ */
+#if SOLARIS
+ if (np->in_redir == NAT_MAP)
+ fix_outcksum(&ip->ip_sum, nat->nat_ipsumd);
+ else
+ fix_incksum(&ip->ip_sum, nat->nat_ipsumd);
+#endif
+
+ if (nflags && !(ip->ip_off & 0x1fff) &&
+ !(fin->fin_fi.fi_fl & FI_SHORT)) {
+
+ if (nat->nat_outport)
+ tcp->th_sport = nat->nat_outport;
+
+ if (ip->ip_p == IPPROTO_TCP) {
+ csump = &tcp->th_sum;
+ set_tcp_age(&nat->nat_age,
+ nat->nat_state, ip, fin,1);
+ } else if (ip->ip_p == IPPROTO_UDP) {
+ udphdr_t *udp = (udphdr_t *)tcp;
+
+ if (udp->uh_sum)
+ csump = &udp->uh_sum;
+ } else if (ip->ip_p == IPPROTO_ICMP) {
+ icmphdr_t *ic = (icmphdr_t *)tcp;
+
+ csump = &ic->icmp_cksum;
+ }
+ if (csump) {
+ if (np->in_redir == NAT_MAP)
+ fix_outcksum(csump,
+ nat->nat_sumd);
+ else
+ fix_incksum(csump,
+ nat->nat_sumd);
+ }
+ }
+ nat_stats.ns_mapped[1]++;
+ MUTEX_EXIT(&ipf_nat);
+ return 1;
+ }
+ MUTEX_EXIT(&ipf_nat);
+ return 0;
+}
+
+
+/*
+ * Packets coming in from the external interface go through this.
+ * Here, the destination address requires alteration, if anything.
+ */
+int ip_natin(ip, hlen, fin)
+ip_t *ip;
+int hlen;
+fr_info_t *fin;
+{
+ register ipnat_t *np;
+ register struct in_addr in;
+ struct ifnet *ifp = fin->fin_ifp;
+ tcphdr_t *tcp = NULL;
+ u_short sport = 0, dport = 0, nflags = 0, *csump = NULL;
+ nat_t *nat;
+
+ if (!(ip->ip_off & 0x1fff) && !(fin->fin_fi.fi_fl & FI_SHORT)) {
+ if (ip->ip_p == IPPROTO_TCP)
+ nflags = IPN_TCP;
+ else if (ip->ip_p == IPPROTO_UDP)
+ nflags = IPN_UDP;
+ if (nflags) {
+ tcp = (tcphdr_t *)((char *)ip + hlen);
+ dport = tcp->th_dport;
+ sport = tcp->th_sport;
+ }
+ }
+
+ in = ip->ip_dst;
+
+ MUTEX_ENTER(&ipf_nat);
+ for (np = nat_list; np; np = np->in_next)
+ if ((np->in_ifp == ifp) &&
+ (!np->in_flags || (nflags & np->in_flags)) &&
+ ((in.s_addr & np->in_outmsk) == np->in_outip) &&
+ (np->in_redir == NAT_MAP || np->in_pmin == dport)) {
+ if (!(nat = nat_inlookup(nflags, ip->ip_src, sport,
+ ip->ip_dst, dport))) {
+ if (np->in_redir == NAT_MAP)
+ continue;
+ else {
+ /*
+ * If this rule (np) is a redirection,
+ * rather than a mapping, then do a
+ * nat_new. Otherwise, if it's just a
+ * mapping, do a continue;
+ */
+ if (!(nat = nat_new(np, ip, fin,
+ nflags,
+ NAT_INBOUND)))
+ break;
+ }
+ }
+ ip->ip_dst = nat->nat_inip;
+
+ nat->nat_age = fr_defnatage;
+
+ /*
+ * Fix up checksums, not by recalculating them, but
+ * simply computing adjustments.
+ */
+#if SOLARIS
+ if (np->in_redir == NAT_MAP)
+ fix_incksum(&ip->ip_sum, nat->nat_ipsumd);
+ else
+ fix_outcksum(&ip->ip_sum, nat->nat_ipsumd);
+#endif
+ if (nflags && !(ip->ip_off & 0x1fff) &&
+ !(fin->fin_fi.fi_fl & FI_SHORT)) {
+
+ if (nat->nat_inport)
+ tcp->th_dport = nat->nat_inport;
+
+ if (ip->ip_p == IPPROTO_TCP) {
+ csump = &tcp->th_sum;
+ set_tcp_age(&nat->nat_age,
+ nat->nat_state, ip, fin,0);
+ } else if (ip->ip_p == IPPROTO_UDP) {
+ udphdr_t *udp = (udphdr_t *)tcp;
+
+ if (udp->uh_sum)
+ csump = &udp->uh_sum;
+ } else if (ip->ip_p == IPPROTO_ICMP) {
+ icmphdr_t *ic = (icmphdr_t *)tcp;
+
+ csump = &ic->icmp_cksum;
+ }
+ if (csump) {
+ if (np->in_redir == NAT_MAP)
+ fix_incksum(csump,
+ nat->nat_sumd);
+ else
+ fix_outcksum(csump,
+ nat->nat_sumd);
+ }
+ }
+ nat_stats.ns_mapped[0]++;
+ MUTEX_EXIT(&ipf_nat);
+ return 1;
+ }
+ MUTEX_EXIT(&ipf_nat);
+ return 0;
+}
+
+
+/*
+ * Free all memory used by NAT structures allocated at runtime.
+ */
+void ip_natunload()
+{
+ MUTEX_ENTER(&ipf_nat);
+
+ (void) clear_natlist();
+ (void) flush_nattable();
+
+ MUTEX_EXIT(&ipf_nat);
+}
+
+
+/*
+ * Slowly expire held state for NAT entries. Timeouts are set in
+ * expectation of this being called twice per second.
+ */
+void ip_natexpire()
+{
+ register struct nat *nat, **natp;
+
+ MUTEX_ENTER(&ipf_nat);
+ for (natp = &nat_instances; (nat = *natp); natp = &nat->nat_next) {
+ if (--nat->nat_age)
+ continue;
+ *natp = nat->nat_next;
+ nat_delete(nat);
+ nat_stats.ns_expire++;
+ }
+ MUTEX_EXIT(&ipf_nat);
+}
diff --git a/contrib/ipfilter/ip_nat.h b/contrib/ipfilter/ip_nat.h
new file mode 100644
index 000000000000..d64183ac3920
--- /dev/null
+++ b/contrib/ipfilter/ip_nat.h
@@ -0,0 +1,118 @@
+/*
+ * (C)opyright 1995 by Darren Reed.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that this notice is preserved and due credit is given
+ * to the original author and the contributors.
+ *
+ * @(#)ip_nat.h 1.5 2/4/96
+ * $Id: ip_nat.h,v 2.0.1.7 1997/01/30 12:39:41 darrenr Exp $
+ */
+
+#ifndef __IP_NAT_H_
+#define __IP_NAT_H__
+
+#ifndef SOLARIS
+#define SOLARIS (defined(sun) && (defined(__svr4__) || defined(__SVR4)))
+#endif
+
+#if defined(__STDC__) || defined(__GNUC__)
+#define SIOCADNAT _IOW('r', 80, struct ipnat)
+#define SIOCRMNAT _IOW('r', 81, struct ipnat)
+#define SIOCGNATS _IOR('r', 82, struct natstat)
+#define SIOCGNATL _IOWR('r', 83, struct natlookup)
+#define SIOCGFRST _IOR('r', 84, struct ipfrstat)
+#define SIOCGIPST _IOR('r', 85, struct ips_stat)
+#define SIOCFLNAT _IOWR('r', 86, int)
+#define SIOCCNATL _IOWR('r', 87, int)
+
+#else
+#define SIOCADNAT _IOW(r, 80, struct ipnat)
+#define SIOCRMNAT _IOW(r, 81, struct ipnat)
+#define SIOCGNATS _IOR(r, 82, struct natstat)
+#define SIOCGNATL _IOWR(r, 83, struct natlookup)
+#define SIOCGFRST _IOR(r, 84, struct ipfrstat)
+#define SIOCGIPST _IOR(r, 85, struct ips_stat)
+#define SIOCFLNAT _IOWR(r, 86, int)
+#define SIOCCNATL _IOWR(r, 87, int)
+#endif
+
+#define NAT_SIZE 367
+
+typedef struct nat {
+ int nat_age;
+ u_long nat_sumd;
+ u_long nat_ipsumd;
+ struct in_addr nat_inip;
+ struct in_addr nat_outip;
+ struct in_addr nat_oip; /* other ip */
+ u_short nat_oport; /* other port */
+ u_short nat_inport;
+ u_short nat_outport;
+ u_short nat_use;
+ u_char nat_state[2];
+ struct ipnat *nat_ptr;
+ struct nat *nat_next;
+ struct nat *nat_hnext[2];
+ struct nat **nat_hstart[2];
+} nat_t;
+
+typedef struct ipnat {
+ struct ipnat *in_next;
+ void *in_ifp;
+ u_int in_space;
+ u_int in_use;
+ struct in_addr in_nextip;
+ u_short in_pnext;
+ u_short in_flags;
+ u_short in_port[2];
+ struct in_addr in_in[2];
+ struct in_addr in_out[2];
+ int in_redir; /* 0 if it's a mapping, 1 if it's a hard redir */
+ char in_ifname[IFNAMSIZ];
+} ipnat_t;
+
+#define in_pmin in_port[0] /* Also holds static redir port */
+#define in_pmax in_port[1]
+#define in_nip in_nextip.s_addr
+#define in_inip in_in[0].s_addr
+#define in_inmsk in_in[1].s_addr
+#define in_outip in_out[0].s_addr
+#define in_outmsk in_out[1].s_addr
+
+#define NAT_INBOUND 0
+#define NAT_OUTBOUND 1
+
+#define NAT_MAP 0
+#define NAT_REDIRECT 1
+
+#define IPN_CMPSIZ (sizeof(struct in_addr) * 4 + sizeof(u_short) * 3 + \
+ sizeof(int))
+
+typedef struct natlookup {
+ struct in_addr nl_inip;
+ struct in_addr nl_outip;
+ u_short nl_inport;
+ u_short nl_outport;
+} natlookup_t;
+
+typedef struct natstat {
+ u_long ns_mapped[2];
+ u_long ns_added;
+ u_long ns_expire;
+ u_long ns_inuse;
+ nat_t **ns_table[2];
+ ipnat_t *ns_list;
+} natstat_t;
+
+#define IPN_ANY 0
+#define IPN_TCP 1
+#define IPN_UDP 2
+#define IPN_TCPUDP 3
+
+extern nat_t *nat_table[2][NAT_SIZE];
+extern int nat_ioctl();
+extern nat_t *nat_outlookup(), *nat_inlookup(), *nat_lookupredir();
+extern int ip_natout(), ip_natin();
+extern void ip_natunload(), ip_natexpire();
+#endif /* __IP_NAT_H__ */
diff --git a/contrib/ipfilter/ip_sfil.c b/contrib/ipfilter/ip_sfil.c
new file mode 100644
index 000000000000..debc512707d6
--- /dev/null
+++ b/contrib/ipfilter/ip_sfil.c
@@ -0,0 +1,731 @@
+/*
+ * (C)opyright 1993,1994,1995 by Darren Reed.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that this notice is preserved and due credit is given
+ * to the original author and the contributors.
+ *
+ * I hate legaleese, don't you ?
+ */
+#if !defined(lint) && defined(LIBC_SCCS)
+static char sccsid[] = "%W% %G% (C) 1993-1995 Darren Reed";
+static char rcsid[] = "$Id: ip_sfil.c,v 2.0.1.3 1997/02/04 14:49:15 darrenr Exp $";
+#endif
+
+#include <sys/types.h>
+#include <sys/errno.h>
+#include <sys/param.h>
+#include <sys/cpuvar.h>
+#include <sys/open.h>
+#include <sys/ioctl.h>
+#include <sys/systm.h>
+#include <sys/cred.h>
+#include <sys/ddi.h>
+#include <sys/sunddi.h>
+#include <sys/ksynch.h>
+#include <sys/kmem.h>
+#include <sys/mkdev.h>
+#include <sys/protosw.h>
+#include <sys/socket.h>
+#include <sys/dditypes.h>
+#include <sys/cmn_err.h>
+#include <net/if.h>
+#include <net/af.h>
+#include <net/route.h>
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/ip_var.h>
+#include <netinet/tcp.h>
+#include <netinet/udp.h>
+#include <netinet/tcpip.h>
+#include <netinet/ip_icmp.h>
+#include "ip_fil.h"
+#include "ip_compat.h"
+#include "ip_state.h"
+#include "ip_frag.h"
+#include "ip_nat.h"
+#include <inet/ip_ire.h>
+#ifndef MIN
+#define MIN(a,b) (((a)<(b))?(a):(b))
+#endif
+
+extern fr_flags, fr_active;
+
+int ipfr_timer_id = 0;
+int ipl_unreach = ICMP_UNREACH_HOST;
+int send_reset();
+
+#ifdef IPFILTER_LOG
+int ipllog();
+static void frflush();
+char iplbuf[IPLLOGSIZE];
+caddr_t iplh = iplbuf, iplt = iplbuf;
+static int iplused = 0;
+#endif /* IPFILTER_LOG */
+static int frrequest();
+kmutex_t ipl_mutex, ipf_mutex, ipfs_mutex;
+kmutex_t ipf_frag, ipf_state, ipf_nat;
+kcondvar_t iplwait;
+
+extern void ipfr_slowtimer();
+
+
+int ipldetach()
+{
+ int i = FR_INQUE|FR_OUTQUE;
+
+ untimeout(ipfr_timer_id);
+ frflush((caddr_t)&i);
+ ipfr_unload();
+ fr_stateunload();
+ ip_natunload();
+ cv_destroy(&iplwait);
+ mutex_destroy(&ipl_mutex);
+ mutex_destroy(&ipf_mutex);
+ mutex_destroy(&ipfs_mutex);
+ mutex_destroy(&ipf_frag);
+ mutex_destroy(&ipf_state);
+ mutex_destroy(&ipf_nat);
+ return 0;
+}
+
+
+int iplattach()
+{
+ bzero((char *)nat_table, sizeof(nat_t *) * NAT_SIZE * 2);
+ mutex_init(&ipl_mutex, "ipf log mutex", MUTEX_DRIVER, NULL);
+ mutex_init(&ipf_mutex, "ipf filter mutex", MUTEX_DRIVER, NULL);
+ mutex_init(&ipfs_mutex, "ipf solaris mutex", MUTEX_DRIVER, NULL);
+ mutex_init(&ipf_frag, "ipf fragment mutex", MUTEX_DRIVER, NULL);
+ mutex_init(&ipf_state, "ipf IP state mutex", MUTEX_DRIVER, NULL);
+ mutex_init(&ipf_nat, "ipf IP NAT mutex", MUTEX_DRIVER, NULL);
+ cv_init(&iplwait, "ipl condvar", CV_DRIVER, NULL);
+ ipfr_timer_id = timeout(ipfr_slowtimer, NULL, HZ/2);
+ return 0;
+}
+
+
+static void frzerostats(data)
+caddr_t data;
+{
+ struct friostat fio;
+
+ bcopy((char *)frstats, (char *)fio.f_st,
+ sizeof(struct filterstats) * 2);
+ fio.f_fin[0] = ipfilter[0][0];
+ fio.f_fin[1] = ipfilter[0][1];
+ fio.f_fout[0] = ipfilter[1][0];
+ fio.f_fout[1] = ipfilter[1][1];
+ fio.f_acctin[0] = ipacct[0][0];
+ fio.f_acctin[1] = ipacct[0][1];
+ fio.f_acctout[0] = ipacct[1][0];
+ fio.f_acctout[1] = ipacct[1][1];
+ fio.f_active = fr_active;
+ IWCOPY((caddr_t)&fio, data, sizeof(fio));
+ bzero((char *)frstats, sizeof(*frstats) * 2);
+}
+
+
+#ifdef IPFILTER_LOG
+static void frflush(data)
+caddr_t data;
+{
+ struct frentry *f, **fp;
+ int flags, flushed = 0, set = fr_active;
+
+ IRCOPY(data, (caddr_t)&flags, sizeof(flags));
+ bzero((char *)frcache, sizeof(frcache[0]) * 2);
+
+ if (flags & FR_INACTIVE)
+ set = 1 - set;
+ if (flags & FR_OUTQUE) {
+ for (fp = &ipfilter[1][set]; (f = *fp); ) {
+ *fp = f->fr_next;
+ KFREE(f);
+ flushed++;
+ }
+ for (fp = &ipacct[1][set]; (f = *fp); ) {
+ *fp = f->fr_next;
+ KFREE(f);
+ flushed++;
+ }
+ }
+ if (flags & FR_INQUE) {
+ for (fp = &ipfilter[0][set]; (f = *fp); ) {
+ *fp = f->fr_next;
+ KFREE(f);
+ flushed++;
+ }
+ for (fp = &ipacct[0][set]; (f = *fp); ) {
+ *fp = f->fr_next;
+ KFREE(f);
+ flushed++;
+ }
+ }
+
+ IWCOPY((caddr_t)&flushed, data, sizeof(flushed));
+}
+#endif /* IPFILTER_LOG */
+
+
+/*
+ * Filter ioctl interface.
+ */
+int iplioctl(dev, cmd, data, mode, cp, rp)
+dev_t dev;
+int cmd;
+caddr_t data;
+int mode;
+cred_t *cp;
+int *rp;
+{
+ int error = 0;
+
+ switch (cmd) {
+ case SIOCFRENB :
+ {
+ u_int enable;
+
+ if (!(mode & FWRITE))
+ return EPERM;
+ IRCOPY(data, (caddr_t)&enable, sizeof(enable));
+ break;
+ }
+ case SIOCSETFF :
+ if (!(mode & FWRITE))
+ return EPERM;
+ mutex_enter(&ipf_mutex);
+ IRCOPY(data, (caddr_t)&fr_flags, sizeof(fr_flags));
+ mutex_exit(&ipf_mutex);
+ break;
+ case SIOCGETFF :
+ IWCOPY((caddr_t)&fr_flags, data, sizeof(fr_flags));
+ break;
+ case SIOCINAFR :
+ case SIOCRMAFR :
+ case SIOCADAFR :
+ case SIOCZRLST :
+ if (!(mode & FWRITE))
+ return EPERM;
+ mutex_enter(&ipf_mutex);
+ error = frrequest(cmd, data, fr_active);
+ mutex_exit(&ipf_mutex);
+ break;
+ case SIOCINIFR :
+ case SIOCRMIFR :
+ case SIOCADIFR :
+ if (!(mode & FWRITE))
+ return EPERM;
+ mutex_enter(&ipf_mutex);
+ error = frrequest(cmd, data, 1 - fr_active);
+ mutex_exit(&ipf_mutex);
+ break;
+ case SIOCSWAPA :
+ if (!(mode & FWRITE))
+ return EPERM;
+ mutex_enter(&ipf_mutex);
+ bzero((char *)frcache, sizeof(frcache[0]) * 2);
+ IWCOPY((caddr_t)&fr_active, (caddr_t)data, sizeof(fr_active));
+ fr_active = 1 - fr_active;
+ mutex_exit(&ipf_mutex);
+ break;
+ case SIOCGETFS :
+ {
+ struct friostat fio;
+
+ mutex_enter(&ipf_mutex);
+ bcopy((char *)frstats, (char *)fio.f_st,
+ sizeof(struct filterstats) * 2);
+ fio.f_fin[0] = ipfilter[0][0];
+ fio.f_fin[1] = ipfilter[0][1];
+ fio.f_fout[0] = ipfilter[1][0];
+ fio.f_fout[1] = ipfilter[1][1];
+ fio.f_acctin[0] = ipacct[0][0];
+ fio.f_acctin[1] = ipacct[0][1];
+ fio.f_acctout[0] = ipacct[1][0];
+ fio.f_acctout[1] = ipacct[1][1];
+ fio.f_active = fr_active;
+ mutex_exit(&ipf_mutex);
+ IWCOPY((caddr_t)&fio, data, sizeof(fio));
+ break;
+ }
+ case SIOCFRZST :
+ if (!(mode & FWRITE))
+ return EPERM;
+ frzerostats(data);
+ break;
+#ifdef IPFILTER_LOG
+ case SIOCIPFFL :
+ if (!(mode & FWRITE))
+ return EPERM;
+ mutex_enter(&ipf_mutex);
+ frflush(data);
+ mutex_exit(&ipf_mutex);
+ break;
+ case SIOCIPFFB :
+ if (!(mode & FWRITE))
+ return EPERM;
+ mutex_enter(&ipl_mutex);
+ IWCOPY((caddr_t)&iplused, data, sizeof(iplused));
+ iplh = iplt = iplbuf;
+ iplused = 0;
+ mutex_exit(&ipl_mutex);
+ break;
+#endif /* IPFILTER_LOG */
+ case SIOCFRSYN :
+ if (!(mode & FWRITE))
+ return EPERM;
+ error = ipfsync();
+ break;
+ case SIOCADNAT :
+ case SIOCRMNAT :
+ case SIOCGNATS :
+ case SIOCGNATL :
+ case SIOCFLNAT :
+ case SIOCCNATL :
+ error = nat_ioctl(data, cmd, mode);
+ break;
+ case SIOCGFRST :
+ IWCOPY((caddr_t)ipfr_fragstats(), data, sizeof(ipfrstat_t));
+ break;
+ case SIOCGIPST :
+ IWCOPY((caddr_t)fr_statetstats(), data, sizeof(ips_stat_t));
+ break;
+ default :
+ error = EINVAL;
+ break;
+ }
+ return error;
+}
+
+
+ill_t *get_unit(name)
+char *name;
+{
+ ill_t *il;
+ int len = strlen(name) + 1; /* includes \0 */
+
+ for (il = ill_g_head; il; il = il->ill_next)
+ if ((len == il->ill_name_length) &&
+ !strncmp(il->ill_name, name, len))
+ return il;
+ return NULL;
+}
+
+
+static int frrequest(req, data, set)
+int req, set;
+caddr_t data;
+{
+ register frentry_t *fp, *f, **fprev;
+ register frentry_t **ftail;
+ frentry_t fr;
+ frdest_t *fdp;
+ int error = 0, in;
+ ill_t *ill;
+ ipif_t *ipif;
+ ire_t *ire;
+
+ fp = &fr;
+ IRCOPY(data, (caddr_t)fp, sizeof(*fp));
+
+ bzero((char *)frcache, sizeof(frcache[0]) * 2);
+
+ in = (fp->fr_flags & FR_INQUE) ? 0 : 1;
+ if (fp->fr_flags & FR_ACCOUNT)
+ ftail = fprev = &ipacct[in][set];
+ else if (fp->fr_flags & (FR_OUTQUE|FR_INQUE))
+ ftail = fprev = &ipfilter[in][set];
+ else
+ return ESRCH;
+
+ if (*fp->fr_ifname) {
+ fp->fr_ifa = (struct ifnet *)get_unit((char *)fp->fr_ifname);
+ if (!fp->fr_ifa)
+ fp->fr_ifa = (struct ifnet *)-1;
+ }
+
+ fdp = &fp->fr_dif;
+ fp->fr_flags &= ~FR_DUP;
+ if (*fdp->fd_ifname) {
+ ill = get_unit(fdp->fd_ifname);
+ if (!ill)
+ ire = (ire_t *)-1;
+ else if ((ipif = ill->ill_ipif)) {
+ ire = ire_lookup_myaddr(ipif->ipif_local_addr);
+ if (!ire)
+ ire = (ire_t *)-1;
+ else
+ fp->fr_flags |= FR_DUP;
+ }
+ fdp->fd_ifp = (struct ifnet *)ire;
+ }
+
+ fdp = &fp->fr_tif;
+ if (*fdp->fd_ifname) {
+ ill = get_unit(fdp->fd_ifname);
+ if (!ill)
+ ire = (ire_t *)-1;
+ else if ((ipif = ill->ill_ipif)) {
+ ire = ire_lookup_myaddr(ipif->ipif_local_addr);
+ if (!ire)
+ ire = (ire_t *)-1;
+ }
+ fdp->fd_ifp = (struct ifnet *)ire;
+ }
+
+ /*
+ * Look for a matching filter rule, but don't include the next or
+ * interface pointer in the comparison (fr_next, fr_ifa).
+ */
+ for (; (f = *ftail); ftail = &f->fr_next)
+ if (bcmp((char *)&f->fr_ip, (char *)&fp->fr_ip,
+ FR_CMPSIZ) == 0)
+ break;
+
+ /*
+ * If zero'ing statistics, copy current to caller and zero.
+ */
+ if (req == SIOCZRLST) {
+ if (!f)
+ return ESRCH;
+ IWCOPY((caddr_t)f, data, sizeof(*f));
+ f->fr_hits = 0;
+ f->fr_bytes = 0;
+ return 0;
+ }
+
+ if (!f) {
+ ftail = fprev;
+ if (req != SIOCINAFR && req != SIOCINIFR)
+ while ((f = *ftail))
+ ftail = &f->fr_next;
+ else if (fp->fr_hits)
+ while (--fp->fr_hits && (f = *ftail))
+ ftail = &f->fr_next;
+ f = NULL;
+ }
+
+ if (req == SIOCDELFR || req == SIOCRMIFR) {
+ if (!f)
+ error = ESRCH;
+ else {
+ *ftail = f->fr_next;
+ KFREE(f);
+ }
+ } else {
+ if (f)
+ error = EEXIST;
+ else {
+ if ((f = (struct frentry *)KMALLOC(sizeof(*f)))) {
+ bcopy((char *)fp, (char *)f, sizeof(*f));
+ f->fr_hits = 0;
+ f->fr_next = *ftail;
+ *ftail = f;
+ } else
+ error = ENOMEM;
+ }
+ }
+ return (error);
+}
+
+
+/*
+ * routines below for saving IP headers to buffer
+ */
+int iplopen(devp, flags, otype, cred)
+dev_t *devp;
+int flags, otype;
+cred_t *cred;
+{
+ u_int min = getminor(*devp);
+
+ if (!(otype & OTYP_CHR))
+ return ENXIO;
+ if (min)
+ min = ENXIO;
+ return min;
+}
+
+
+int iplclose(dev, flags, otype, cred)
+dev_t dev;
+int flags, otype;
+cred_t *cred;
+{
+ u_int min = getminor(dev);
+
+ if (min)
+ min = ENXIO;
+ return min;
+}
+
+#ifdef IPFILTER_LOG
+/*
+ * iplread/ipllog
+ * both of these must operate with at least splnet() lest they be
+ * called during packet processing and cause an inconsistancy to appear in
+ * the filter lists.
+ */
+int iplread(dev, uio, cp)
+dev_t dev;
+register struct uio *uio;
+cred_t *cp;
+{
+ register int ret;
+ register size_t sz, sx;
+ char *h, *t;
+ int error, used, usedo, copied;
+
+ if (!uio->uio_resid)
+ return 0;
+ if ((uio->uio_resid < 0) || (uio->uio_resid > IPLLOGSIZE))
+ return EINVAL;
+
+ /*
+ * Lock the log so we can snapshot the variables. Wait for a signal
+ * if the log is empty.
+ */
+ mutex_enter(&ipl_mutex);
+ while (!iplused) {
+ error = cv_wait_sig(&iplwait, &ipl_mutex);
+ if (!error) {
+ mutex_exit(&ipl_mutex);
+ return EINTR;
+ }
+ }
+ h = iplh;
+ t = iplt;
+ used = iplused;
+ mutex_exit(&ipl_mutex);
+ usedo = used;
+
+ /*
+ * Given up the mutex, the log can grow more, but we can't hold the
+ * mutex across the uiomove's.
+ */
+ sx = sz = MIN(uio->uio_resid, used);
+ if (h <= t)
+ sz = MIN(sz, IPLLOGSIZE + iplbuf - t);
+
+ if (!(ret = uiomove(t, sz, UIO_READ, uio))) {
+ t += sz;
+ sx -= sz;
+ used -= sz;
+ if ((h < t) && (t >= iplbuf + IPLLOGSIZE))
+ t = iplbuf;
+
+ if (sx && !(ret = uiomove(t, sx, UIO_READ, uio)))
+ used -= sx;
+ }
+
+ /*
+ * copied all the data, now adjust variables to match this.
+ */
+ mutex_enter(&ipl_mutex);
+ copied = usedo - used;
+ iplused -= copied;
+
+ if (!iplused) /* minimise wrapping around the end */
+ iplh = iplt = iplbuf;
+ else {
+ iplt += copied;
+ if (iplt >= iplbuf + IPLLOGSIZE)
+ iplt -= IPLLOGSIZE;
+ if (iplt == iplbuf + IPLLOGSIZE)
+ iplt = iplbuf;
+ }
+ mutex_exit(&ipl_mutex);
+ return ret;
+}
+
+
+int ipllog(flags, ip, fin, m)
+u_int flags;
+ip_t *ip;
+fr_info_t *fin;
+mblk_t *m;
+{
+ struct ipl_ci iplci;
+ register int len, mlen, hlen;
+ register u_char *s = (u_char *)ip;
+ ill_t *il = fin->fin_ifp;
+
+ hlen = fin->fin_hlen;
+ if (ip->ip_p == IPPROTO_TCP || ip->ip_p == IPPROTO_UDP)
+ hlen += MIN(sizeof(tcphdr_t), fin->fin_dlen);
+ else if (ip->ip_p == IPPROTO_ICMP) {
+ struct icmp *icmp = (struct icmp *)(s + hlen);
+
+ switch (icmp->icmp_type) {
+ case ICMP_UNREACH :
+ case ICMP_SOURCEQUENCH :
+ case ICMP_REDIRECT :
+ case ICMP_TIMXCEED :
+ case ICMP_PARAMPROB :
+ hlen += MIN(sizeof(struct icmp) + 8, fin->fin_dlen);
+ break;
+ default :
+ hlen += MIN(sizeof(struct icmp), fin->fin_dlen);
+ break;
+ }
+ }
+
+ mlen = (flags & FR_LOGBODY) ? MIN(msgdsize(m) - hlen, 128) : 0;
+ len = hlen + sizeof(iplci) + mlen;
+ mutex_enter(&ipl_mutex);
+ if ((iplused + len) > IPLLOGSIZE) {
+ mutex_exit(&ipl_mutex);
+ return 0;
+ }
+ iplused += len;
+
+ uniqtime((struct timeval *)&iplci);
+ iplci.flags = flags;
+ iplci.hlen = (u_char)hlen;
+ iplci.plen = (u_char)mlen;
+ iplci.rule = fin->fin_rule;
+ iplci.unit = (u_char)il->ill_ppa;
+ bcopy(il->ill_name, (char *)iplci.ifname, MIN(il->ill_name_length, 4));
+
+ /*
+ * Gauranteed to succeed from above
+ */
+ (void) fr_copytolog(&iplci, sizeof(iplci));
+ len -= sizeof(iplci);
+
+ if (len && m) {
+ s = m->b_rptr;
+ do {
+ if ((hlen = MIN(m->b_wptr - s, len))) {
+ if (fr_copytolog(s, hlen))
+ break;
+ len -= hlen;
+ }
+ if ((m = m->b_cont))
+ s = m->b_rptr;
+ } while (m && len);
+ }
+
+ cv_signal(&iplwait);
+ mutex_exit(&ipl_mutex);
+ return 1;
+}
+#endif /* IPFILTER_LOG */
+
+
+u_short ipf_cksum(addr, len)
+register u_short *addr;
+register int len;
+{
+ register u_long sum = 0;
+
+ for (sum = 0; len > 1; len -= 2)
+ sum += *addr++;
+
+ /* mop up an odd byte, if necessary */
+ if (len == 1)
+ sum += *(u_char *)addr;
+
+ /*
+ * add back carry outs from top 16 bits to low 16 bits
+ */
+ sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */
+ sum += (sum >> 16); /* add carry */
+ return (u_short)(~sum);
+}
+
+/*
+ * send_reset - this could conceivably be a call to tcp_respond(), but that
+ * requires a large amount of setting up and isn't any more efficient.
+ */
+int send_reset(ti, qif, q)
+struct tcpiphdr *ti;
+qif_t *qif;
+queue_t *q;
+{
+ struct ip *ip;
+ struct tcphdr *tcp;
+ mblk_t *m;
+ int tlen = 0;
+
+ if (ti->ti_flags & TH_RST)
+ return -1;
+ if (ti->ti_flags & TH_SYN)
+ tlen = 1;
+ if ((m = (mblk_t *)allocb(sizeof(struct tcpiphdr), BPRI_HI)) == NULL)
+ return -1;
+
+ MTYPE(m) = M_DATA;
+ m->b_wptr += sizeof(struct tcpiphdr);
+ bzero((char *)m->b_rptr, sizeof(struct tcpiphdr));
+ ip = (ip_t *)m->b_rptr;
+ tcp = (struct tcphdr *)(m->b_rptr + sizeof(*ip));
+
+ ip->ip_src.s_addr = ti->ti_dst.s_addr;
+ ip->ip_dst.s_addr = ti->ti_src.s_addr;
+ tcp->th_dport = ti->ti_sport;
+ tcp->th_sport = ti->ti_dport;
+ tcp->th_ack = htonl(ntohl(ti->ti_seq) + tlen);
+ tcp->th_off = sizeof(struct tcphdr) >> 2;
+ tcp->th_flags = TH_RST|TH_ACK;
+ /*
+ * This is to get around a bug in the Solaris 2.4/2.5 TCP checksum
+ * computation that is done by their put routine.
+ */
+ tcp->th_sum = htons(0x14);
+ ip->ip_hl = sizeof(*ip) >> 2;
+ ip->ip_v = IPVERSION;
+ ip->ip_p = IPPROTO_TCP;
+ ip->ip_len = htons(sizeof(struct tcpiphdr));
+ ip->ip_tos = ((struct ip *)ti)->ip_tos;
+ ip->ip_off = 0;
+ ip->ip_ttl = 60;
+ ip->ip_sum = 0;
+ ip_wput(qif->qf_ill->ill_wq, m);
+ return 0;
+}
+
+
+int icmp_error(q, ip, type, code, qif, src)
+queue_t *q;
+ip_t *ip;
+int type, code;
+qif_t *qif;
+struct in_addr src;
+{
+ mblk_t *mb;
+ struct icmp *icmp;
+ ip_t *nip;
+ int sz = sizeof(*nip) + sizeof(*icmp) + 8;
+
+ if ((mb = (mblk_t *)allocb(sz, BPRI_HI)) == NULL)
+ return -1;
+ MTYPE(mb) = M_DATA;
+ mb->b_wptr += sz;
+ bzero((char *)mb->b_rptr, sz);
+ nip = (ip_t *)mb->b_rptr;
+ icmp = (struct icmp *)(nip + 1);
+
+ nip->ip_v = IPVERSION;
+ nip->ip_hl = (sizeof(*nip) >> 2);
+ nip->ip_p = IPPROTO_ICMP;
+ nip->ip_id = ip->ip_id;
+ nip->ip_sum = 0;
+ nip->ip_ttl = 60;
+ nip->ip_tos = ip->ip_tos;
+ nip->ip_len = htons(sz);
+ nip->ip_src.s_addr = ip->ip_dst.s_addr;
+ nip->ip_dst.s_addr = ip->ip_src.s_addr;
+
+ icmp->icmp_type = type;
+ icmp->icmp_code = code;
+ icmp->icmp_cksum = 0;
+ bcopy((char *)ip, (char *)&icmp->icmp_ip, sizeof(*ip));
+ bcopy((char *)ip + (ip->ip_hl << 2),
+ (char *)&icmp->icmp_ip + sizeof(*ip), 8); /* 64 bits */
+ icmp->icmp_cksum = ipf_cksum(icmp, sizeof(*icmp) + 8);
+ ip_wput(qif->qf_ill->ill_wq, mb);
+ return 0;
+}
diff --git a/contrib/ipfilter/ip_state.c b/contrib/ipfilter/ip_state.c
new file mode 100644
index 000000000000..62a49aa250ed
--- /dev/null
+++ b/contrib/ipfilter/ip_state.c
@@ -0,0 +1,536 @@
+/*
+ * (C)opyright 1995 by Darren Reed.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that this notice is preserved and due credit is given
+ * to the original author and the contributors.
+ */
+#if !defined(lint) && defined(LIBC_SCCS)
+static char sccsid[] = "@(#)ip_state.c 1.8 6/5/96 (C) 1993-1995 Darren Reed";
+static char rcsid[] = "$Id: ip_state.c,v 2.0.1.2 1997/01/09 15:22:45 darrenr Exp $";
+#endif
+
+#if !defined(_KERNEL) && !defined(KERNEL)
+# include <stdlib.h>
+# include <string.h>
+#endif
+#include <sys/errno.h>
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/file.h>
+#include <sys/ioctl.h>
+#include <sys/uio.h>
+#include <sys/protosw.h>
+#include <sys/socket.h>
+#ifdef _KERNEL
+# include <sys/systm.h>
+#endif
+#if !defined(__SVR4) && !defined(__svr4__)
+# include <sys/mbuf.h>
+#else
+# include <sys/byteorder.h>
+# include <sys/dditypes.h>
+# include <sys/stream.h>
+# include <sys/kmem.h>
+#endif
+
+#include <net/if.h>
+#ifdef sun
+#include <net/af.h>
+#endif
+#include <net/route.h>
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/ip_var.h>
+#include <netinet/tcp.h>
+#include <netinet/tcp_fsm.h>
+#include <netinet/udp.h>
+#include <netinet/tcpip.h>
+#include <netinet/ip_icmp.h>
+#include "ip_fil.h"
+#include "ip_compat.h"
+#include "ip_state.h"
+#ifndef MIN
+#define MIN(a,b) (((a)<(b))?(a):(b))
+#endif
+
+void set_tcp_age();
+
+#define TCP_CLOSE (TH_FIN|TH_RST)
+
+ipstate_t *ips_table[IPSTATE_SIZE];
+int ips_num = 0;
+ips_stat_t ips_stats;
+#if SOLARIS
+extern kmutex_t ipf_state;
+# if !defined(_KERNEL)
+#define bcopy(a,b,c) memmove(b,a,c)
+# endif
+#endif
+
+
+#define FIVE_DAYS (2 * 5 * 86400) /* 5 days: half closed session */
+
+u_long fr_tcpidletimeout = FIVE_DAYS,
+ fr_tcpclosewait = 60,
+ fr_tcplastack = 20,
+ fr_tcptimeout = 120,
+ fr_tcpclosed = 1,
+ fr_udptimeout = 120,
+ fr_icmptimeout = 120;
+
+
+ips_stat_t *fr_statetstats()
+{
+ ips_stats.iss_active = ips_num;
+ ips_stats.iss_table = ips_table;
+ return &ips_stats;
+}
+
+
+#define PAIRS(s1,d1,s2,d2) ((((s1) == (s2)) && ((d1) == (d2))) ||\
+ (((s1) == (d2)) && ((d1) == (s2))))
+#define IPPAIR(s1,d1,s2,d2) PAIRS((s1).s_addr, (d1).s_addr, \
+ (s2).s_addr, (d2).s_addr)
+
+/*
+ * Create a new ipstate structure and hang it off the hash table.
+ */
+int fr_addstate(ip, fin, pass)
+ip_t *ip;
+fr_info_t *fin;
+u_int pass;
+{
+ ipstate_t ips;
+ register ipstate_t *is = &ips;
+ register u_int hv;
+
+ if ((ip->ip_off & 0x1fff) || (fin->fin_fi.fi_fl & FI_SHORT))
+ return -1;
+ if (ips_num == IPSTATE_MAX) {
+ ips_stats.iss_max++;
+ return -1;
+ }
+ ips.is_age = 1;
+ ips.is_state[0] = 0;
+ ips.is_state[1] = 0;
+ /*
+ * Copy and calculate...
+ */
+ hv = (is->is_p = ip->ip_p);
+ hv += (is->is_src.s_addr = ip->ip_src.s_addr);
+ hv += (is->is_dst.s_addr = ip->ip_dst.s_addr);
+
+ switch (ip->ip_p)
+ {
+ case IPPROTO_ICMP :
+ {
+ struct icmp *ic = (struct icmp *)fin->fin_dp;
+
+ switch (ic->icmp_type)
+ {
+ case ICMP_ECHO :
+ is->is_icmp.ics_type = 0;
+ hv += (is->is_icmp.ics_id = ic->icmp_id);
+ hv += (is->is_icmp.ics_seq = ic->icmp_seq);
+ break;
+ case ICMP_TSTAMP :
+ case ICMP_IREQ :
+ case ICMP_MASKREQ :
+ is->is_icmp.ics_type = ic->icmp_type + 1;
+ break;
+ default :
+ return -1;
+ }
+ ips_stats.iss_icmp++;
+ is->is_age = fr_icmptimeout;
+ break;
+ }
+ case IPPROTO_TCP :
+ {
+ register tcphdr_t *tcp = (tcphdr_t *)fin->fin_dp;
+
+ /*
+ * The endian of the ports doesn't matter, but the ack and
+ * sequence numbers do as we do mathematics on them later.
+ */
+ hv += (is->is_dport = tcp->th_dport);
+ hv += (is->is_sport = tcp->th_sport);
+ is->is_seq = ntohl(tcp->th_seq);
+ is->is_ack = ntohl(tcp->th_ack);
+ is->is_swin = ntohs(tcp->th_win);
+ is->is_dwin = is->is_swin; /* start them the same */
+ ips_stats.iss_tcp++;
+ /*
+ * If we're creating state for a starting connectoin, start the
+ * timer on it as we'll never see an error if it fails to
+ * connect.
+ */
+ if ((tcp->th_flags & (TH_SYN|TH_ACK)) == TH_SYN)
+ is->is_ack = 0; /* Trumpet WinSock 'ism */
+ set_tcp_age(&is->is_age, is->is_state, ip, fin,
+ tcp->th_sport == is->is_sport);
+ break;
+ }
+ case IPPROTO_UDP :
+ {
+ register tcphdr_t *tcp = (tcphdr_t *)fin->fin_dp;
+
+ hv += (is->is_dport = tcp->th_dport);
+ hv += (is->is_sport = tcp->th_sport);
+ ips_stats.iss_udp++;
+ is->is_age = fr_udptimeout;
+ break;
+ }
+ default :
+ return -1;
+ }
+
+ if (!(is = (ipstate_t *)KMALLOC(sizeof(*is)))) {
+ ips_stats.iss_nomem++;
+ return -1;
+ }
+ bcopy((char *)&ips, (char *)is, sizeof(*is));
+ hv %= IPSTATE_SIZE;
+ MUTEX_ENTER(&ipf_state);
+ is->is_next = ips_table[hv];
+ ips_table[hv] = is;
+ is->is_pass = pass;
+ if (pass & FR_LOGFIRST)
+ is->is_pass &= ~(FR_LOGFIRST|FR_LOG);
+ ips_num++;
+ MUTEX_EXIT(&ipf_state);
+ return 0;
+}
+
+
+/*
+ * check to see if a packet with TCP headers fits within the TCP window.
+ * change timeout depending on whether new packet is a SYN-ACK returning for a
+ * SYN or a RST or FIN which indicate time to close up shop.
+ */
+int fr_tcpstate(is, fin, ip, tcp, sport
+#ifndef _KERNEL
+,isp)
+ipstate_t **isp;
+#else
+)
+#endif
+register ipstate_t *is;
+fr_info_t *fin;
+ip_t *ip;
+tcphdr_t *tcp;
+u_short sport;
+{
+ register int seqskew, ackskew;
+ register u_short swin, dwin;
+ register tcp_seq seq, ack;
+ int source;
+
+ /*
+ * Find difference between last checked packet and this packet.
+ */
+ seq = ntohl(tcp->th_seq);
+ ack = ntohl(tcp->th_ack);
+ if (sport == is->is_sport) {
+ seqskew = seq - is->is_seq;
+ ackskew = ack - is->is_ack;
+ } else {
+ seqskew = ack - is->is_seq;
+ if (!is->is_ack)
+ /*
+ * Must be a SYN-ACK in reply to a SYN.
+ */
+ is->is_ack = seq;
+ ackskew = seq - is->is_ack;
+ }
+
+ /*
+ * Make skew values absolute
+ */
+ if (seqskew < 0)
+ seqskew = -seqskew;
+ if (ackskew < 0)
+ ackskew = -ackskew;
+
+ /*
+ * If the difference in sequence and ack numbers is within the
+ * window size of the connection, store these values and match
+ * the packet.
+ */
+ if ((source = (sport == is->is_sport))) {
+ swin = is->is_swin;
+ dwin = is->is_dwin;
+ } else {
+ dwin = is->is_swin;
+ swin = is->is_dwin;
+ }
+
+ if ((seqskew <= swin) && (ackskew <= dwin)) {
+ if (source) {
+ is->is_seq = seq;
+ is->is_ack = ack;
+ is->is_swin = ntohs(tcp->th_win);
+ } else {
+ is->is_seq = ack;
+ is->is_ack = seq;
+ is->is_dwin = ntohs(tcp->th_win);
+ }
+ ips_stats.iss_hits++;
+ /*
+ * Nearing end of connection, start timeout.
+ */
+ set_tcp_age(&is->is_age, is->is_state, ip, fin,
+ tcp->th_sport == is->is_sport);
+ return 1;
+ }
+ return 0;
+}
+
+
+/*
+ * Check if a packet has a registered state.
+ */
+int fr_checkstate(ip, fin)
+ip_t *ip;
+fr_info_t *fin;
+{
+ register struct in_addr dst, src;
+ register ipstate_t *is, **isp;
+ register u_char pr;
+ struct icmp *ic;
+ tcphdr_t *tcp;
+ u_int hv, hlen;
+
+ if ((ip->ip_off & 0x1fff) || (fin->fin_fi.fi_fl & FI_SHORT))
+ return 0;
+
+ hlen = fin->fin_hlen;
+ tcp = (tcphdr_t *)((char *)ip + hlen);
+ ic = (struct icmp *)tcp;
+ hv = (pr = ip->ip_p);
+ hv += (src.s_addr = ip->ip_src.s_addr);
+ hv += (dst.s_addr = ip->ip_dst.s_addr);
+
+ /*
+ * Search the hash table for matching packet header info.
+ */
+ switch (ip->ip_p)
+ {
+ case IPPROTO_ICMP :
+ hv += ic->icmp_id;
+ hv += ic->icmp_seq;
+ hv %= IPSTATE_SIZE;
+ MUTEX_ENTER(&ipf_state);
+ for (isp = &ips_table[hv]; (is = *isp); isp = &is->is_next)
+ if ((is->is_p == pr) &&
+ (ic->icmp_id == is->is_icmp.ics_id) &&
+ (ic->icmp_seq == is->is_icmp.ics_seq) &&
+ IPPAIR(src, dst, is->is_src, is->is_dst)) {
+ /*
+ * If we have type 0 stored, allow any icmp
+ * replies through.
+ */
+ if (is->is_icmp.ics_type &&
+ is->is_icmp.ics_type != ic->icmp_type)
+ continue;
+ is->is_age = fr_icmptimeout;
+ ips_stats.iss_hits++;
+ MUTEX_EXIT(&ipf_state);
+ return is->is_pass;
+ }
+ MUTEX_EXIT(&ipf_state);
+ break;
+ case IPPROTO_TCP :
+ {
+ register u_short dport = tcp->th_dport, sport = tcp->th_sport;
+
+ hv += dport;
+ hv += sport;
+ hv %= IPSTATE_SIZE;
+ MUTEX_ENTER(&ipf_state);
+ for (isp = &ips_table[hv]; (is = *isp); isp = &is->is_next) {
+ if ((is->is_p == pr) &&
+ PAIRS(sport, dport, is->is_sport, is->is_dport) &&
+ IPPAIR(src, dst, is->is_src, is->is_dst))
+ if (fr_tcpstate(is, fin, ip, tcp, sport)) {
+#ifdef _KERNEL
+ MUTEX_EXIT(&ipf_state);
+ return is->is_pass;
+#else
+ int pass = is->is_pass;
+
+ if (tcp->th_flags & TCP_CLOSE) {
+ *isp = is->is_next;
+ isp = &ips_table[hv];
+ KFREE(is);
+ }
+ return pass;
+#endif
+ }
+ }
+ MUTEX_EXIT(&ipf_state);
+ break;
+ }
+ case IPPROTO_UDP :
+ {
+ register u_short dport = tcp->th_dport, sport = tcp->th_sport;
+
+ hv += dport;
+ hv += sport;
+ hv %= IPSTATE_SIZE;
+ /*
+ * Nothing else to match on but ports. and IP#'s
+ */
+ MUTEX_ENTER(&ipf_state);
+ for (is = ips_table[hv]; is; is = is->is_next)
+ if ((is->is_p == pr) &&
+ PAIRS(sport, dport, is->is_sport, is->is_dport) &&
+ IPPAIR(src, dst, is->is_src, is->is_dst)) {
+ ips_stats.iss_hits++;
+ is->is_age = fr_udptimeout;
+ MUTEX_EXIT(&ipf_state);
+ return is->is_pass;
+ }
+ MUTEX_EXIT(&ipf_state);
+ break;
+ }
+ default :
+ break;
+ }
+ ips_stats.iss_miss++;
+ return 0;
+}
+
+
+/*
+ * Free memory in use by all state info. kept.
+ */
+void fr_stateunload()
+{
+ register int i;
+ register ipstate_t *is, **isp;
+
+ MUTEX_ENTER(&ipf_state);
+ for (i = 0; i < IPSTATE_SIZE; i++)
+ for (isp = &ips_table[i]; (is = *isp); ) {
+ *isp = is->is_next;
+ KFREE(is);
+ }
+ MUTEX_EXIT(&ipf_state);
+}
+
+
+/*
+ * Slowly expire held state for thingslike UDP and ICMP. Timeouts are set
+ * in expectation of this being called twice per second.
+ */
+void fr_timeoutstate()
+{
+ register int i;
+ register ipstate_t *is, **isp;
+
+ MUTEX_ENTER(&ipf_state);
+ for (i = 0; i < IPSTATE_SIZE; i++)
+ for (isp = &ips_table[i]; (is = *isp); )
+ if (is->is_age && !--is->is_age) {
+ *isp = is->is_next;
+ if (is->is_p == IPPROTO_TCP)
+ ips_stats.iss_fin++;
+ else
+ ips_stats.iss_expire++;
+ KFREE(is);
+ ips_num--;
+ } else
+ isp = &is->is_next;
+ MUTEX_EXIT(&ipf_state);
+}
+
+
+/*
+ * Original idea freom Pradeep Krishnan for use primarily with NAT code.
+ * (pkrishna@netcom.com)
+ */
+void set_tcp_age(age, state, ip, fin, dir)
+int *age;
+u_char *state;
+ip_t *ip;
+fr_info_t *fin;
+int dir;
+{
+ tcphdr_t *tcp = (tcphdr_t *)fin->fin_dp;
+ u_char flags = tcp->th_flags;
+ int dlen, ostate;
+
+ ostate = state[1 - dir];
+
+ dlen = ip->ip_len - fin->fin_hlen - (tcp->th_off << 2);
+
+ if (flags & TH_RST) {
+ if (!(tcp->th_flags & TH_PUSH) && !dlen) {
+ *age = fr_tcpclosed;
+ state[dir] = TCPS_CLOSED;
+ } else {
+ *age = fr_tcpclosewait;
+ state[dir] = TCPS_CLOSE_WAIT;
+ }
+ return;
+ }
+
+ *age = fr_tcptimeout; /* 1 min */
+
+ switch(state[dir])
+ {
+ case TCPS_FIN_WAIT_2:
+ case TCPS_CLOSED:
+ if ((flags & TH_OPENING) == TH_OPENING)
+ state[dir] = TCPS_SYN_RECEIVED;
+ else if (flags & TH_SYN)
+ state[dir] = TCPS_SYN_SENT;
+ break;
+ case TCPS_SYN_RECEIVED:
+ if ((flags & (TH_FIN|TH_ACK)) == TH_ACK) {
+ state[dir] = TCPS_ESTABLISHED;
+ *age = fr_tcpidletimeout;
+ }
+ break;
+ case TCPS_SYN_SENT:
+ if ((flags & (TH_FIN|TH_ACK)) == TH_ACK) {
+ state[dir] = TCPS_ESTABLISHED;
+ *age = fr_tcpidletimeout;
+ }
+ break;
+ case TCPS_ESTABLISHED:
+ if (flags & TH_FIN) {
+ state[dir] = TCPS_CLOSE_WAIT;
+ if (!(flags & TH_PUSH) && !dlen &&
+ ostate > TCPS_ESTABLISHED)
+ *age = fr_tcplastack;
+ else
+ *age = fr_tcpclosewait;
+ } else
+ *age = fr_tcpidletimeout;
+ break;
+ case TCPS_CLOSE_WAIT:
+ if ((flags & TH_FIN) && !(flags & TH_PUSH) && !dlen &&
+ ostate > TCPS_ESTABLISHED) {
+ *age = fr_tcplastack;
+ state[dir] = TCPS_LAST_ACK;
+ } else
+ *age = fr_tcpclosewait;
+ break;
+ case TCPS_LAST_ACK:
+ if (flags & TH_ACK) {
+ state[dir] = TCPS_FIN_WAIT_2;
+ if (!(flags & TH_PUSH) && !dlen &&
+ ostate > TCPS_ESTABLISHED)
+ *age = fr_tcplastack;
+ else {
+ *age = fr_tcpclosewait;
+ state[dir] = TCPS_CLOSE_WAIT;
+ }
+ }
+ break;
+ }
+}
diff --git a/contrib/ipfilter/ip_state.h b/contrib/ipfilter/ip_state.h
new file mode 100644
index 000000000000..ee30b986d844
--- /dev/null
+++ b/contrib/ipfilter/ip_state.h
@@ -0,0 +1,86 @@
+/*
+ * (C)opyright 1995 by Darren Reed.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that this notice is preserved and due credit is given
+ * to the original author and the contributors.
+ *
+ * @(#)ip_state.h 1.3 1/12/96 (C) 1995 Darren Reed
+ * $Id: ip_state.h,v 2.0.1.1 1997/01/09 15:14:43 darrenr Exp $
+ */
+#ifndef __IP_STATE_H__
+#define __IP_STATE_H__
+
+#define IPSTATE_SIZE 257
+#define IPSTATE_MAX 2048 /* Maximum number of states held */
+
+typedef struct udpstate {
+ u_short us_sport;
+ u_short us_dport;
+} udpstate_t;
+
+typedef struct icmpstate {
+ u_short ics_id;
+ u_short ics_seq;
+ u_char ics_type;
+} icmpstate_t;
+
+typedef struct tcpstate {
+ u_short ts_sport;
+ u_short ts_dport;
+ u_long ts_seq;
+ u_long ts_ack;
+ u_short ts_swin;
+ u_short ts_dwin;
+ u_char ts_state[2];
+} tcpstate_t;
+
+typedef struct ipstate {
+ struct ipstate *is_next;
+ int is_age;
+ u_int is_pass;
+ struct in_addr is_src;
+ struct in_addr is_dst;
+ u_char is_p;
+ u_char is_flags;
+ union {
+ icmpstate_t is_ics;
+ tcpstate_t is_ts;
+ udpstate_t is_us;
+ } is_ps;
+} ipstate_t;
+
+#define is_icmp is_ps.is_ics
+#define is_tcp is_ps.is_ts
+#define is_udp is_ps.is_us
+#define is_seq is_tcp.ts_seq
+#define is_ack is_tcp.ts_ack
+#define is_dwin is_tcp.ts_dwin
+#define is_swin is_tcp.ts_swin
+#define is_sport is_tcp.ts_sport
+#define is_dport is_tcp.ts_dport
+#define is_state is_tcp.ts_state
+
+#define TH_OPENING (TH_SYN|TH_ACK)
+
+typedef struct ips_stat {
+ u_long iss_hits;
+ u_long iss_miss;
+ u_long iss_max;
+ u_long iss_tcp;
+ u_long iss_udp;
+ u_long iss_icmp;
+ u_long iss_nomem;
+ u_long iss_expire;
+ u_long iss_fin;
+ u_long iss_active;
+ ipstate_t **iss_table;
+} ips_stat_t;
+
+extern ips_stat_t *fr_statetstats();
+extern int fr_addstate(), fr_checkstate();
+extern void fr_timeoutstate(), set_tcp_age();
+# ifdef _KERNEL
+extern void fr_stateunload();
+# endif
+#endif /* __IP_STATE_H__ */
diff --git a/contrib/ipfilter/ipf.c b/contrib/ipfilter/ipf.c
new file mode 100644
index 000000000000..da6baa244648
--- /dev/null
+++ b/contrib/ipfilter/ipf.c
@@ -0,0 +1,434 @@
+/*
+ * (C)opyright 1993,1994,1995 by Darren Reed.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that this notice is preserved and due credit is given
+ * to the original author and the contributors.
+ */
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <fcntl.h>
+#include <errno.h>
+#if !defined(__SVR4) && !defined(__GNUC__)
+#include <strings.h>
+#endif
+#if !defined(__SVR4) && defined(__GNUC__)
+extern char *index();
+#endif
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/file.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <stddef.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <net/if.h>
+#include <netinet/ip.h>
+#include "ip_fil.h"
+#include <netdb.h>
+#include <arpa/nameser.h>
+#include <resolv.h>
+#include "ipf.h"
+
+#if !defined(lint) && defined(LIBC_SCCS)
+static char sccsid[] = "@(#)ipf.c 1.23 6/5/96 (C) 1993-1995 Darren Reed";
+static char rcsid[] = "$Id: ipf.c,v 2.0.1.2 1997/02/04 14:37:46 darrenr Exp $";
+#endif
+
+#if SOLARIS
+void frsync(), blockunknown();
+#endif
+void zerostats();
+
+extern char *optarg;
+
+int opts = 0;
+
+static int fd = -1;
+
+static void procfile(), flushfilter(), set_state();
+static void packetlogon(), swapactive(), showstats();
+static char *getline();
+
+int main(argc,argv)
+int argc;
+char *argv[];
+{
+ char c;
+
+ while ((c = getopt(argc, argv, "AdDEf:F:Il:noprsUvyzZ")) != -1) {
+ switch (c)
+ {
+ case 'E' :
+ set_state(1);
+ break;
+ case 'D' :
+ set_state(0);
+ break;
+ case 'A' :
+ opts &= ~OPT_INACTIVE;
+ break;
+ case 'd' :
+ opts |= OPT_DEBUG;
+ break;
+ case 'f' :
+ procfile(argv[0], optarg);
+ break;
+ case 'F' :
+ flushfilter(optarg);
+ break;
+ case 'I' :
+ opts |= OPT_INACTIVE;
+ break;
+ case 'l' :
+ packetlogon(optarg);
+ break;
+ case 'n' :
+ opts |= OPT_DONOTHING;
+ break;
+ case 'o' :
+ opts |= OPT_OUTQUE;
+ break;
+ case 'p' :
+ opts |= OPT_PRINTFR;
+ break;
+ case 'r' :
+ opts |= OPT_REMOVE;
+ break;
+ case 's' :
+ swapactive();
+ break;
+#if SOLARIS
+ case 'U' :
+ blockunknown();
+ break;
+#endif
+ case 'v' :
+ opts |= OPT_VERBOSE;
+ break;
+#if SOLARIS
+ case 'y' :
+ frsync();
+ break;
+#endif
+ case 'z' :
+ opts |= OPT_ZERORULEST;
+ break;
+ case 'Z' :
+ zerostats();
+ break;
+ }
+ }
+
+ if (fd != -1)
+ (void) close(fd);
+
+ exit(0);
+ /* NOTREACHED */
+}
+
+
+static int opendevice()
+{
+ if (opts & OPT_DONOTHING)
+ return -2;
+
+ if (!(opts & OPT_DONOTHING) && fd == -1)
+ if ((fd = open(IPL_NAME, O_RDWR)) == -1)
+ if ((fd = open(IPL_NAME, O_RDONLY)) == -1)
+ perror("open device");
+ return fd;
+}
+
+
+static void set_state(enable)
+u_int enable;
+{
+ if (opendevice() != -2)
+ if (ioctl(fd, SIOCFRENB, &enable) == -1)
+ perror("SIOCFRENB");
+ return;
+}
+
+static void procfile(name, file)
+char *name, *file;
+{
+ FILE *fp;
+ char line[513], *s;
+ struct frentry *fr;
+ u_int add = SIOCADAFR, del = SIOCRMAFR;
+
+ (void) opendevice();
+
+ if (opts & OPT_INACTIVE) {
+ add = SIOCADIFR;
+ del = SIOCRMIFR;
+ }
+ if (opts & OPT_DEBUG)
+ printf("add %x del %x\n", add, del);
+
+ initparse();
+
+ if (!strcmp(file, "-"))
+ fp = stdin;
+ else if (!(fp = fopen(file, "r"))) {
+ fprintf(stderr, "%s: fopen(%s) failed: %s\n", name, file,
+ STRERROR(errno));
+ exit(1);
+ }
+
+ while (getline(line, sizeof(line)-1, fp)) {
+ /*
+ * treat both CR and LF as EOL
+ */
+ if ((s = index(line, '\n')))
+ *s = '\0';
+ if ((s = index(line, '\r')))
+ *s = '\0';
+ /*
+ * # is comment marker, everything after is a ignored
+ */
+ if ((s = index(line, '#')))
+ *s = '\0';
+
+ if (!*line)
+ continue;
+
+ if (opts & OPT_VERBOSE)
+ (void)fprintf(stderr, "[%s]\n",line);
+
+ fr = parse(line);
+ (void)fflush(stdout);
+
+ if (fr) {
+ if (opts & OPT_ZERORULEST)
+ add = SIOCZRLST;
+ else if (opts & OPT_INACTIVE)
+ add = fr->fr_hits ? SIOCINIFR : SIOCADIFR;
+ else
+ add = fr->fr_hits ? SIOCINAFR : SIOCADAFR;
+ if (fr->fr_hits)
+ fr->fr_hits--;
+ if (fr && (opts & OPT_VERBOSE))
+ printfr(fr);
+ if (fr && (opts & OPT_OUTQUE))
+ fr->fr_flags |= FR_OUTQUE;
+
+ if (opts & OPT_DEBUG)
+ binprint(fr);
+
+ if ((opts & OPT_ZERORULEST) &&
+ !(opts & OPT_DONOTHING)) {
+ if (ioctl(fd, add, fr) == -1)
+ perror("ioctl(SIOCZRLST)");
+ else {
+ printf("hits %ld bytes %ld ",
+ fr->fr_hits, fr->fr_bytes);
+ printfr(fr);
+ }
+ } else if ((opts & OPT_REMOVE) &&
+ !(opts & OPT_DONOTHING)) {
+ if (ioctl(fd, del, fr) == -1)
+ perror("ioctl(SIOCDELFR)");
+ } else if (!(opts & OPT_DONOTHING)) {
+ if (ioctl(fd, add, fr) == -1)
+ perror("ioctl(SIOCADDFR)");
+ }
+ }
+ }
+ (void)fclose(fp);
+}
+
+/*
+ * Similar to fgets(3) but can handle '\\'
+ */
+static char *getline(str, size, file)
+register char *str;
+size_t size;
+FILE *file;
+{
+ register char *p;
+
+ do {
+ for (p = str;; p+= strlen(p) - 1) {
+ if (!fgets(p, size, file))
+ return(NULL);
+ p[strlen(p) -1] = '\0';
+ if (p[strlen(p) - 1] != '\\')
+ break;
+ }
+ } while (*str == '\0' || *str == '\n');
+ return(str);
+}
+
+
+static void packetlogon(opt)
+char *opt;
+{
+ int err, flag = 0;
+
+ if ((opts & (OPT_DONOTHING|OPT_VERBOSE)) == OPT_VERBOSE) {
+ if ((err = ioctl(fd, SIOCGETFF, &flag)))
+ perror("ioctl(SIOCGETFF)");
+
+ printf("log flag is currently %#x\n", flag);
+ }
+
+ flag &= ~(FF_LOGPASS|FF_LOGNOMATCH|FF_LOGBLOCK);
+
+ if (index(opt, 'p')) {
+ flag |= FF_LOGPASS;
+ if (opts & OPT_VERBOSE)
+ printf("set log flag: pass\n");
+ }
+ if (index(opt, 'm') && (*opt == 'n' || *opt == 'N')) {
+ flag |= FF_LOGNOMATCH;
+ if (opts & OPT_VERBOSE)
+ printf("set log flag: nomatch\n");
+ }
+ if (index(opt, 'b') || index(opt, 'd')) {
+ flag |= FF_LOGBLOCK;
+ if (opts & OPT_VERBOSE)
+ printf("set log flag: block\n");
+ }
+
+ if (opendevice() != -2 && (err = ioctl(fd, SIOCSETFF, &flag)))
+ perror("ioctl(SIOCSETFF)");
+
+ if ((opts & (OPT_DONOTHING|OPT_VERBOSE)) == OPT_VERBOSE) {
+ if ((err = ioctl(fd, SIOCGETFF, &flag)))
+ perror("ioctl(SIOCGETFF)");
+
+ printf("log flag is now %#x\n", flag);
+ }
+}
+
+
+static void flushfilter(arg)
+char *arg;
+{
+ int fl = 0, rem;
+
+ if (!arg || !*arg)
+ return;
+ if (strchr(arg, 'i') || strchr(arg, 'I'))
+ fl = FR_INQUE;
+ if (strchr(arg, 'o') || strchr(arg, 'O'))
+ fl = FR_OUTQUE;
+ if (strchr(arg, 'a') || strchr(arg, 'A'))
+ fl = FR_OUTQUE|FR_INQUE;
+ fl |= (opts & FR_INACTIVE);
+ rem = fl;
+
+ if (opendevice() != -2 && ioctl(fd, SIOCIPFFL, &fl) == -1)
+ perror("ioctl(SIOCIPFFL)");
+ if ((opts & (OPT_DONOTHING|OPT_VERBOSE)) == OPT_VERBOSE) {
+ printf("remove flags %s%s (%d)\n", (rem & FR_INQUE) ? "I" : "",
+ (rem & FR_OUTQUE) ? "O" : "", rem);
+ printf("removed %d filter rules\n", fl);
+ }
+ return;
+}
+
+
+static void swapactive()
+{
+ int in = 2;
+
+ if (opendevice() != -2 && ioctl(fd, SIOCSWAPA, &in) == -1)
+ perror("ioctl(SIOCSWAPA)");
+ else
+ printf("Set %d now inactive\n", in);
+}
+
+
+#if defined(sun) && (defined(__SVR4) || defined(__svr4__))
+void frsync()
+{
+ if (opendevice() != -2 && ioctl(fd, SIOCFRSYN, 0) == -1)
+ perror("SIOCFRSYN");
+ else
+ printf("filter sync'd\n");
+}
+#endif
+
+
+void zerostats()
+{
+ friostat_t fio;
+
+ if (opendevice() != -2) {
+ if (ioctl(fd, SIOCFRZST, &fio) == -1) {
+ perror("ioctl(SIOCFRZST)");
+ exit(-1);
+ }
+ showstats(&fio);
+ }
+
+}
+
+
+/*
+ * read the kernel stats for packets blocked and passed
+ */
+static void showstats(fp)
+friostat_t *fp;
+{
+#if SOLARIS
+ printf("dropped packets:\tin %lu\tout %lu\n",
+ fp->f_st[0].fr_drop, fp->f_st[1].fr_drop);
+ printf("non-ip packets:\t\tin %lu\tout %lu\n",
+ fp->f_st[0].fr_notip, fp->f_st[1].fr_notip);
+ printf(" bad packets:\t\tin %lu\tout %lu\n",
+ fp->f_st[0].fr_bad, fp->f_st[1].fr_bad);
+#endif
+ printf(" input packets:\t\tblocked %lu passed %lu nomatch %lu",
+ fp->f_st[0].fr_block, fp->f_st[0].fr_pass,
+ fp->f_st[0].fr_nom);
+ printf(" counted %lu\n", fp->f_st[0].fr_acct);
+ printf("output packets:\t\tblocked %lu passed %lu nomatch %lu",
+ fp->f_st[1].fr_block, fp->f_st[1].fr_pass,
+ fp->f_st[1].fr_nom);
+ printf(" counted %lu\n", fp->f_st[0].fr_acct);
+ printf(" input packets logged:\tblocked %lu passed %lu\n",
+ fp->f_st[0].fr_bpkl, fp->f_st[0].fr_ppkl);
+ printf("output packets logged:\tblocked %lu passed %lu\n",
+ fp->f_st[1].fr_bpkl, fp->f_st[1].fr_ppkl);
+ printf(" packets logged:\tinput %lu-%lu output %lu-%lu\n",
+ fp->f_st[0].fr_pkl, fp->f_st[0].fr_skip,
+ fp->f_st[1].fr_pkl, fp->f_st[1].fr_skip);
+}
+
+
+#if SOLARIS
+void blockunknown()
+{
+ int flag;
+
+ if (opendevice() == -1)
+ return;
+
+ if ((opts & (OPT_DONOTHING|OPT_VERBOSE)) == OPT_VERBOSE) {
+ if (ioctl(fd, SIOCGETFF, &flag))
+ perror("ioctl(SIOCGETFF)");
+
+ printf("log flag is currently %#x\n", flag);
+ }
+
+ flag ^= FF_BLOCKNONIP;
+
+ if (opendevice() != -2 && ioctl(fd, SIOCSETFF, &flag))
+ perror("ioctl(SIOCSETFF)");
+
+ if ((opts & (OPT_DONOTHING|OPT_VERBOSE)) == OPT_VERBOSE) {
+ if (ioctl(fd, SIOCGETFF, &flag))
+ perror("ioctl(SIOCGETFF)");
+
+ printf("log flag is now %#x\n", flag);
+ }
+}
+#endif
diff --git a/contrib/ipfilter/ipf.h b/contrib/ipfilter/ipf.h
new file mode 100644
index 000000000000..3ac76fc288e5
--- /dev/null
+++ b/contrib/ipfilter/ipf.h
@@ -0,0 +1,67 @@
+/*
+ * (C)opyright 1993-1996 by Darren Reed.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that this notice is preserved and due credit is given
+ * to the original author and the contributors.
+ *
+ * @(#)ipf.h 1.12 6/5/96
+ * $Id: ipf.h,v 2.0.1.1 1997/01/09 15:14:43 darrenr Exp $
+ */
+
+#ifndef SOLARIS
+#define SOLARIS (defined(sun) && (defined(__svr4__) || defined(__SVR4)))
+#endif
+#define OPT_REMOVE 0x00001
+#define OPT_DEBUG 0x00002
+#define OPT_OUTQUE FR_OUTQUE /* 0x0004 */
+#define OPT_INQUE FR_INQUE /* 0x0008 */
+#define OPT_LOG FR_LOG /* 0x0010 */
+#define OPT_SHOWLIST 0x00020
+#define OPT_VERBOSE 0x00040
+#define OPT_DONOTHING 0x00080
+#define OPT_HITS 0x00100
+#define OPT_BRIEF 0x00200
+#define OPT_ACCNT FR_ACCOUNT /* 0x0400 */
+#define OPT_FRSTATES FR_KEEPFRAG /* 0x0800 */
+#define OPT_IPSTATES FR_KEEPSTATE /* 0x1000 */
+#define OPT_INACTIVE FR_INACTIVE /* 0x2000 */
+#define OPT_SHOWLINENO 0x04000
+#define OPT_PRINTFR 0x08000
+#define OPT_ZERORULEST 0x10000
+
+extern struct frentry *parse();
+
+extern void printfr(), binprint(), initparse();
+
+#if defined(__SVR4) || defined(__svr4__)
+#define index strchr
+#define bzero(a,b) memset(a, 0, b)
+#define bcopy(a,b,c) memmove(b,a,c)
+#endif
+
+struct ipopt_names {
+ int on_value;
+ int on_bit;
+ int on_siz;
+ char *on_name;
+};
+
+
+extern u_long hostnum(), optname();
+extern void printpacket();
+#if SOLARIS
+extern int inet_aton();
+#endif
+
+#ifdef sun
+#define STRERROR(x) sys_errlist[x]
+extern char *sys_errlist[];
+#else
+#define STRERROR(x) strerror(x)
+#endif
+
+#ifndef MIN
+#define MIN(a,b) ((a) > (b) ? (b) : (a))
+#endif
+
diff --git a/contrib/ipfilter/ipft_ef.c b/contrib/ipfilter/ipft_ef.c
new file mode 100644
index 000000000000..2c4cc0f0d21b
--- /dev/null
+++ b/contrib/ipfilter/ipft_ef.c
@@ -0,0 +1,148 @@
+/*
+ * (C)opyright 1993,1994,1995 by Darren Reed.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that this notice is preserved and due credit is given
+ * to the original author and the contributors.
+ */
+
+/*
+ icmp type
+ lnth proto source destination src port dst port
+
+etherfind -n
+
+ 60 tcp 128.250.20.20 128.250.133.13 2419 telnet
+
+etherfind -n -t
+
+ 0.32 91 04 131.170.1.10 128.250.133.13
+ 0.33 566 udp 128.250.37.155 128.250.133.3 901 901
+*/
+#include <stdio.h>
+#include <string.h>
+#if !defined(__SVR4) && !defined(__GNUC__)
+#include <strings.h>
+#endif
+#include <sys/types.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <stddef.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <sys/param.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip_var.h>
+#include <netinet/ip.h>
+#include <netinet/tcp.h>
+#include <netinet/udp.h>
+#include <netinet/ip_icmp.h>
+#include <netinet/tcpip.h>
+#include <net/if.h>
+#include <netdb.h>
+#include "ipf.h"
+#include "ipt.h"
+
+#if !defined(lint) && defined(LIBC_SCCS)
+static char sccsid[] = "@(#)ipft_ef.c 1.6 2/4/96 (C)1995 Darren Reed";
+static char rcsid[] = "$Id: ipft_ef.c,v 2.0.1.1 1997/01/09 15:14:43 darrenr Exp $";
+#endif
+
+static int etherf_open(), etherf_close(), etherf_readip();
+
+struct ipread etherf = { etherf_open, etherf_close, etherf_readip };
+
+static FILE *efp = NULL;
+static int efd = -1;
+
+
+static int etherf_open(fname)
+char *fname;
+{
+ if (efd != -1)
+ return efd;
+
+ if (!strcmp(fname, "-")) {
+ efd = 0;
+ efp = stdin;
+ } else {
+ efd = open(fname, O_RDONLY);
+ efp = fdopen(efd, "r");
+ }
+ return efd;
+}
+
+
+static int etherf_close()
+{
+ return close(efd);
+}
+
+
+static int etherf_readip(buf, cnt, ifn, dir)
+char *buf, **ifn;
+int cnt, *dir;
+{
+ struct tcpiphdr pkt;
+ struct ip *ip = (struct ip *)&pkt;
+ struct protoent *p = NULL;
+ char src[16], dst[16], sprt[16], dprt[16];
+ char lbuf[128], len[8], prot[8], time[8], *s;
+ int slen, extra = 0, i, n;
+
+ if (!fgets(lbuf, sizeof(lbuf) - 1, efp))
+ return 0;
+
+ if ((s = strchr(lbuf, '\n')))
+ *s = '\0';
+ lbuf[sizeof(lbuf)-1] = '\0';
+
+ bzero(&pkt, sizeof(pkt));
+
+ if ((n = sscanf(lbuf, "%s %s %s %s %s %s", len, prot, src, dst,
+ sprt, dprt)) != 6)
+ if ((n = sscanf(lbuf, "%s %s %s %s %s %s %s", time,
+ len, prot, src, dst, sprt, dprt)) != 7)
+ return -1;
+
+ ip->ip_p = atoi(prot);
+ if (ip->ip_p == 0) {
+ if (!(p = getprotobyname(prot)))
+ return -1;
+ ip->ip_p = p->p_proto;
+ }
+
+ switch (ip->ip_p) {
+ case IPPROTO_TCP :
+ case IPPROTO_UDP :
+ s = strtok(NULL, " :");
+ ip->ip_len += atoi(s);
+ if (p->p_proto == IPPROTO_TCP)
+ extra = sizeof(struct tcphdr);
+ else if (p->p_proto == IPPROTO_UDP)
+ extra = sizeof(struct udphdr);
+ break;
+#ifdef IGMP
+ case IPPROTO_IGMP :
+ extra = sizeof(struct igmp);
+ break;
+#endif
+ case IPPROTO_ICMP :
+ extra = sizeof(struct icmp);
+ break;
+ default :
+ break;
+ }
+
+ (void) inet_aton(src, &ip->ip_src);
+ (void) inet_aton(dst, &ip->ip_dst);
+ ip->ip_len = atoi(len);
+ ip->ip_hl = sizeof(struct ip);
+
+ slen = ip->ip_hl + extra;
+ i = MIN(cnt, slen);
+ bcopy((char *)&pkt, buf, i);
+ return i;
+}
diff --git a/contrib/ipfilter/ipft_hx.c b/contrib/ipfilter/ipft_hx.c
new file mode 100644
index 000000000000..26dbc83d15a4
--- /dev/null
+++ b/contrib/ipfilter/ipft_hx.c
@@ -0,0 +1,140 @@
+/*
+ * (C)opyright 1995 by Darren Reed.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that this notice is preserved and due credit is given
+ * to the original author and the contributors.
+ */
+#include <stdio.h>
+#include <ctype.h>
+#include <assert.h>
+#include <string.h>
+#if !defined(__SVR4) && !defined(__svr4__)
+#include <strings.h>
+#else
+#include <sys/byteorder.h>
+#endif
+#include <sys/types.h>
+#include <sys/param.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <stddef.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip_var.h>
+#include <netinet/ip.h>
+#include <netinet/udp.h>
+#include <netinet/tcp.h>
+#include <netinet/ip_icmp.h>
+#include <netinet/tcpip.h>
+#include <net/if.h>
+#include <netdb.h>
+#include <arpa/nameser.h>
+#include <resolv.h>
+#include "ipf.h"
+#include "ipt.h"
+
+#if !defined(lint) && defined(LIBC_SCCS)
+static char sccsid[] = "@(#)ipft_hx.c 1.1 3/9/96 (C) 1996 Darren Reed";
+static char rcsid[] = "$Id: ipft_hx.c,v 2.0.1.2 1997/02/04 13:57:56 darrenr Exp $";
+#endif
+
+extern int opts;
+extern u_short portnum();
+extern u_long buildopts();
+
+static int hex_open(), hex_close(), hex_readip();
+static char *readhex();
+
+struct ipread iphex = { hex_open, hex_close, hex_readip };
+static FILE *tfp = NULL;
+static int tfd = -1;
+
+static int hex_open(fname)
+char *fname;
+{
+ if (tfp && tfd != -1) {
+ rewind(tfp);
+ return tfd;
+ }
+
+ if (!strcmp(fname, "-")) {
+ tfd = 0;
+ tfp = stdin;
+ } else {
+ tfd = open(fname, O_RDONLY);
+ if (tfd != -1)
+ tfp = fdopen(tfd, "r");
+ }
+ return tfd;
+}
+
+
+static int hex_close()
+{
+ int cfd = tfd;
+
+ tfd = -1;
+ return close(cfd);
+}
+
+
+static int hex_readip(buf, cnt, ifn, dir)
+char *buf, **ifn;
+int cnt, *dir;
+{
+ register char *s;
+ struct ip *ip;
+ char line[513];
+
+ ip = (struct ip *)buf;
+ while (fgets(line, sizeof(line)-1, tfp)) {
+ if ((s = index(line, '\n'))) {
+ if (s == line)
+ return (char *)ip - buf;
+ *s = '\0';
+ }
+ if ((s = index(line, '#')))
+ *s = '\0';
+ if (!*line)
+ continue;
+ if (!(opts & OPT_BRIEF)) {
+ printf("input: %s\n", line);
+ fflush(stdout);
+ }
+ ip = (struct ip *)readhex(line, (char *)ip);
+ }
+ return -1;
+}
+
+
+static char *readhex(src, dst)
+register char *src, *dst;
+{
+ int state = 0;
+ char c;
+
+ while ((c = *src++)) {
+ if (isspace(c)) {
+ if (state) {
+ dst++;
+ state = 0;
+ }
+ continue;
+ } else if ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') ||
+ (c >= 'A' && c <= 'F')) {
+ c = isdigit(c) ? (c - '0') : (toupper(c) - 55);
+ if (state == 0) {
+ *dst = (c << 4);
+ state++;
+ } else {
+ *dst++ |= c;
+ state = 0;
+ }
+ } else
+ break;
+ }
+ return dst;
+}
diff --git a/contrib/ipfilter/ipft_pc.c b/contrib/ipfilter/ipft_pc.c
new file mode 100644
index 000000000000..3d3d8879bd80
--- /dev/null
+++ b/contrib/ipfilter/ipft_pc.c
@@ -0,0 +1,224 @@
+/*
+ * (C)opyright 1993-1996 by Darren Reed.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that this notice is preserved and due credit is given
+ * to the original author and the contributors.
+ */
+#include <stdio.h>
+#include <string.h>
+#if !defined(__SVR4) && !defined(__GNUC__)
+#include <strings.h>
+#endif
+#include <sys/types.h>
+#include <sys/time.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <stddef.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <sys/param.h>
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip_var.h>
+#include <netinet/ip.h>
+#include <netinet/tcp.h>
+#include <netinet/tcpip.h>
+#include <net/if.h>
+#include "ipf.h"
+#include "ipt.h"
+#include "pcap.h"
+
+#if !defined(lint) && defined(LIBC_SCCS)
+static char rcsid[] = "$Id: ipft_pc.c,v 2.0.1.1 1997/01/09 15:14:44 darrenr Exp $";
+#endif
+
+struct llc {
+ int lc_sz; /* LLC header length */
+ int lc_to; /* LLC Type offset */
+ int lc_tl; /* LLC Type length */
+};
+
+/*
+ * While many of these maybe the same, some do have different header formats
+ * which make this useful.
+ */
+#define DLT_MAX 10
+
+static struct llc llcs[DLT_MAX+1] = {
+ { 0, 0, 0 }, /* DLT_NULL */
+ { 14, 12, 2 }, /* DLT_E10MB */
+ { 0, 0, 0 }, /* DLT_EN3MB */
+ { 0, 0, 0 }, /* DLT_AX25 */
+ { 0, 0, 0 }, /* DLT_PRONET */
+ { 0, 0, 0 }, /* DLT_CHAOS */
+ { 0, 0, 0 }, /* DLT_IEEE802 */
+ { 0, 0, 0 }, /* DLT_ARCNET */
+ { 0, 0, 0 }, /* DLT_SLIP */
+ { 0, 0, 0 }, /* DLT_PPP */
+ { 0, 0, 0 } /* DLT_FDDI */
+};
+
+static int pcap_open(), pcap_close(), pcap_readip();
+
+static int pfd = -1, s_type = -1, swapped = 0;
+
+struct ipread pcap = { pcap_open, pcap_close, pcap_readip };
+
+#define SWAPLONG(y) \
+ ((((y)&0xff)<<24) | (((y)&0xff00)<<8) | (((y)&0xff0000)>>8) | (((y)>>24)&0xff))
+#define SWAPSHORT(y) \
+ ( (((y)&0xff)<<8) | (((y)&0xff00)>>8) )
+
+static void swap_hdr(p)
+pcaphdr_t *p;
+{
+ p->pc_v_maj = SWAPSHORT(p->pc_v_maj);
+ p->pc_v_min = SWAPSHORT(p->pc_v_min);
+ p->pc_zone = SWAPLONG(p->pc_zone);
+ p->pc_sigfigs = SWAPLONG(p->pc_sigfigs);
+ p->pc_slen = SWAPLONG(p->pc_slen);
+ p->pc_type = SWAPLONG(p->pc_type);
+}
+
+static int pcap_open(fname)
+char *fname;
+{
+ pcaphdr_t ph;
+ int fd;
+
+ if (pfd != -1)
+ return pfd;
+
+ if (!strcmp(fname, "-"))
+ fd = 0;
+ else if ((fd = open(fname, O_RDONLY)) == -1)
+ return -1;
+
+ if (read(fd, (char *)&ph, sizeof(ph)) != sizeof(ph))
+ return -2;
+
+ if (ph.pc_id != TCPDUMP_MAGIC) {
+ if (SWAPLONG(ph.pc_id) != TCPDUMP_MAGIC) {
+ (void) close(fd);
+ return -2;
+ }
+ swapped = 1;
+ swap_hdr(&ph);
+ }
+
+ if (ph.pc_v_maj != PCAP_VERSION_MAJ || ph.pc_type > DLT_MAX) {
+ (void) close(fd);
+ return -2;
+ }
+
+ pfd = fd;
+ s_type = ph.pc_type;
+ printf("opened pcap file %s:\n", fname);
+ printf("\tid: %08x version: %d.%d type: %d snap %d\n",
+ ph.pc_id, ph.pc_v_maj, ph.pc_v_min, ph.pc_type, ph.pc_slen);
+
+ return fd;
+}
+
+
+static int pcap_close()
+{
+ return close(pfd);
+}
+
+
+/*
+ * read in the header (and validate) which should be the first record
+ * in a pcap file.
+ */
+static int pcap_read_rec(rec)
+struct pcap_pkthdr *rec;
+{
+ int n, p;
+
+ if (read(pfd, (char *)rec, sizeof(*rec)) != sizeof(*rec))
+ return -2;
+
+ if (swapped) {
+ rec->ph_clen = SWAPLONG(rec->ph_clen);
+ rec->ph_len = SWAPLONG(rec->ph_len);
+ rec->ph_ts.tv_sec = SWAPLONG(rec->ph_ts.tv_sec);
+ rec->ph_ts.tv_usec = SWAPLONG(rec->ph_ts.tv_usec);
+ }
+ p = rec->ph_clen;
+ n = MIN(p, rec->ph_len);
+ if (!n || n < 0)
+ return -3;
+
+ return p;
+}
+
+
+#ifdef notyet
+/*
+ * read an entire pcap packet record. only the data part is copied into
+ * the available buffer, with the number of bytes copied returned.
+ */
+static int pcap_read(buf, cnt)
+char *buf;
+int cnt;
+{
+ struct pcap_pkthdr rec;
+ static char *bufp = NULL;
+ int i, n;
+
+ if ((i = pcap_read_rec(&rec)) <= 0)
+ return i;
+
+ if (!bufp)
+ bufp = malloc(i);
+ else
+ bufp = realloc(bufp, i);
+
+ if (read(pfd, bufp, i) != i)
+ return -2;
+
+ n = MIN(i, cnt);
+ bcopy(bufp, buf, n);
+ return n;
+}
+#endif
+
+
+/*
+ * return only an IP packet read into buf
+ */
+static int pcap_readip(buf, cnt, ifn, dir)
+char *buf, **ifn;
+int cnt, *dir;
+{
+ static char *bufp = NULL;
+ struct pcap_pkthdr rec;
+ struct llc *l;
+ char *s, ty[4];
+ int i, n;
+
+ do {
+ if ((i = pcap_read_rec(&rec)) <= 0)
+ return i;
+
+ if (!bufp)
+ bufp = malloc(i);
+ else
+ bufp = realloc(bufp, i);
+ s = bufp;
+
+ if (read(pfd, s, i) != i)
+ return -2;
+
+ l = &llcs[s_type];
+ i -= l->lc_sz;
+ s += l->lc_to;
+ bcopy(s, ty, l->lc_tl);
+ s += l->lc_tl;
+ } while (ty[0] != 0x8 && ty[1] != 0);
+ n = MIN(i, cnt);
+ bcopy(s, buf, n);
+ return n;
+}
diff --git a/contrib/ipfilter/ipft_sn.c b/contrib/ipfilter/ipft_sn.c
new file mode 100644
index 000000000000..3185b56157dc
--- /dev/null
+++ b/contrib/ipfilter/ipft_sn.c
@@ -0,0 +1,206 @@
+/*
+ * (C)opyright 1993,1994,1995 by Darren Reed.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that this notice is preserved and due credit is given
+ * to the original author and the contributors.
+ */
+
+/*
+ * Written to comply with the recent RFC 1761 from Sun.
+ */
+#include <stdio.h>
+#include <string.h>
+#if !defined(__SVR4) && !defined(__GNUC__)
+#include <strings.h>
+#endif
+#include <sys/types.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <stddef.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <sys/param.h>
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip_var.h>
+#include <netinet/ip.h>
+#include <netinet/tcp.h>
+#include <netinet/tcpip.h>
+#include <net/if.h>
+#include "ipf.h"
+#include "ipt.h"
+#include "snoop.h"
+
+#if !defined(lint) && defined(LIBC_SCCS)
+static char rcsid[] = "$Id: ipft_sn.c,v 2.0.1.1 1997/01/09 15:14:44 darrenr Exp $";
+#endif
+
+struct llc {
+ int lc_sz; /* LLC header length */
+ int lc_to; /* LLC Type offset */
+ int lc_tl; /* LLC Type length */
+};
+
+/*
+ * While many of these maybe the same, some do have different header formats
+ * which make this useful.
+ */
+static struct llc llcs[SDL_MAX+1] = {
+ { 0, 0, 0 }, /* SDL_8023 */
+ { 0, 0, 0 }, /* SDL_8024 */
+ { 0, 0, 0 }, /* SDL_8025 */
+ { 0, 0, 0 }, /* SDL_8026 */
+ { 14, 12, 2 }, /* SDL_ETHER */
+ { 0, 0, 0 }, /* SDL_HDLC */
+ { 0, 0, 0 }, /* SDL_CHSYNC */
+ { 0, 0, 0 }, /* SDL_IBMCC */
+ { 0, 0, 0 }, /* SDL_FDDI */
+ { 0, 0, 0 }, /* SDL_OTHER */
+};
+
+static int snoop_open(), snoop_close(), snoop_readip();
+
+static int sfd = -1, s_type = -1;
+
+struct ipread snoop = { snoop_open, snoop_close, snoop_readip };
+
+
+static int snoop_open(fname)
+char *fname;
+{
+ struct snoophdr sh;
+ int fd;
+
+ if (sfd != -1)
+ return sfd;
+
+ if (!strcmp(fname, "-"))
+ fd = 0;
+ else if ((fd = open(fname, O_RDONLY)) == -1)
+ return -1;
+
+ if (read(fd, (char *)&sh, sizeof(sh)) != sizeof(sh))
+ return -2;
+
+ if (sh.s_v != SNOOP_VERSION ||
+ sh.s_type < 0 || sh.s_type > SDL_MAX) {
+ (void) close(fd);
+ return -2;
+ }
+
+ sfd = fd;
+ s_type = sh.s_type;
+ printf("opened snoop file %s:\n", fname);
+ printf("\tid: %8.8s version: %d type: %d\n", sh.s_id, sh.s_v, s_type);
+
+ return fd;
+}
+
+
+static int snoop_close()
+{
+ return close(sfd);
+}
+
+
+/*
+ * read in the header (and validate) which should be the first record
+ * in a snoop file.
+ */
+static int snoop_read_rec(rec)
+struct snooppkt *rec;
+{
+ int n, p;
+
+ if (read(sfd, (char *)rec, sizeof(*rec)) != sizeof(*rec))
+ return -2;
+
+ if (rec->sp_ilen > rec->sp_plen || rec->sp_plen < sizeof(*rec))
+ return -2;
+
+ p = rec->sp_plen - sizeof(*rec);
+ n = MIN(p, rec->sp_ilen);
+ if (!n || n < 0)
+ return -3;
+
+ return p;
+}
+
+
+#ifdef notyet
+/*
+ * read an entire snoop packet record. only the data part is copied into
+ * the available buffer, with the number of bytes copied returned.
+ */
+static int snoop_read(buf, cnt)
+char *buf;
+int cnt;
+{
+ struct snooppkt rec;
+ static char *bufp = NULL;
+ int i, n;
+
+ if ((i = snoop_read_rec(&rec)) <= 0)
+ return i;
+
+ if (!bufp)
+ bufp = malloc(i);
+ else
+ bufp = realloc(bufp, i);
+
+ if (read(sfd, bufp, i) != i)
+ return -2;
+
+ n = MIN(i, cnt);
+ bcopy(bufp, buf, n);
+ return n;
+}
+#endif
+
+
+/*
+ * return only an IP packet read into buf
+ */
+static int snoop_readip(buf, cnt, ifn, dir)
+char *buf, **ifn;
+int cnt, *dir;
+{
+ static char *bufp = NULL;
+ struct snooppkt rec;
+ struct llc *l;
+ char ty[4], *s;
+ int i, n;
+
+ do {
+ if ((i = snoop_read_rec(&rec)) <= 0)
+ return i;
+
+ if (!bufp)
+ bufp = malloc(i);
+ else
+ bufp = realloc(bufp, i);
+ s = bufp;
+
+ if (read(sfd, s, i) != i)
+ return -2;
+
+ l = &llcs[s_type];
+ i -= l->lc_to;
+ s += l->lc_to;
+ /*
+ * XXX - bogus assumption here on the part of the time field
+ * that it won't be greater than 4 bytes and the 1st two will
+ * have the values 8 and 0 for IP. Should be a table of
+ * these too somewhere. Really only works for SDL_ETHER.
+ */
+ bcopy(s, ty, l->lc_tl);
+ } while (ty[0] != 0x8 && ty[1] != 0);
+
+ i -= l->lc_tl;
+ s += l->lc_tl;
+ n = MIN(i, cnt);
+ bcopy(s, buf, n);
+
+ return n;
+}
diff --git a/contrib/ipfilter/ipft_td.c b/contrib/ipfilter/ipft_td.c
new file mode 100644
index 000000000000..ecd2badae454
--- /dev/null
+++ b/contrib/ipfilter/ipft_td.c
@@ -0,0 +1,184 @@
+/*
+ * (C)opyright 1993,1994,1995 by Darren Reed.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that this notice is preserved and due credit is given
+ * to the original author and the contributors.
+ */
+
+/*
+tcpdump -n
+
+00:05:47.816843 128.231.76.76.3291 > 224.2.252.231.36573: udp 36 (encap)
+
+tcpdump -nq
+
+00:33:48.410771 192.73.213.11.1463 > 224.2.248.153.59360: udp 31 (encap)
+
+tcpdump -nqt
+
+128.250.133.13.23 > 128.250.20.20.2419: tcp 27
+
+tcpdump -nqtt
+
+123456789.1234567 128.250.133.13.23 > 128.250.20.20.2419: tcp 27
+
+tcpdump -nqte
+
+8:0:20:f:65:f7 0:0:c:1:8a:c5 81: 128.250.133.13.23 > 128.250.20.20.2419: tcp 27
+
+*/
+#include <stdio.h>
+#include <string.h>
+#if !defined(__SVR4) && !defined(__GNUC__)
+#include <strings.h>
+#endif
+#include <sys/types.h>
+#include <sys/param.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <stddef.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip_var.h>
+#include <netinet/ip.h>
+#include <netinet/tcp.h>
+#include <netinet/udp.h>
+#include <netinet/ip_icmp.h>
+#include <netinet/tcpip.h>
+#include <net/if.h>
+#include <netdb.h>
+#include "ipf.h"
+#include "ipt.h"
+
+#if !defined(lint) && defined(LIBC_SCCS)
+static char sccsid[] = "@(#)ipft_td.c 1.8 2/4/96 (C)1995 Darren Reed";
+static char rcsid[] = "$Id: ipft_td.c,v 2.0.1.1 1997/01/09 15:14:44 darrenr Exp $";
+#endif
+
+static int tcpd_open(), tcpd_close(), tcpd_readip();
+
+struct ipread tcpd = { tcpd_open, tcpd_close, tcpd_readip };
+
+static FILE *tfp = NULL;
+static int tfd = -1;
+
+
+static int tcpd_open(fname)
+char *fname;
+{
+ if (tfd != -1)
+ return tfd;
+
+ if (!strcmp(fname, "-")) {
+ tfd = 0;
+ tfp = stdin;
+ } else {
+ tfd = open(fname, O_RDONLY);
+ tfp = fdopen(tfd, "r");
+ }
+ return tfd;
+}
+
+
+static int tcpd_close()
+{
+ (void) fclose(tfp);
+ return close(tfd);
+}
+
+
+static int count_dots(str)
+char *str;
+{
+ int i = 0;
+
+ while (*str)
+ if (*str++ == '.')
+ i++;
+ return i;
+}
+
+
+static int tcpd_readip(buf, cnt, ifn, dir)
+char *buf, **ifn;
+int cnt, *dir;
+{
+ struct tcpiphdr pkt;
+ struct ip *ip = (struct ip *)&pkt;
+ struct protoent *p;
+ char src[32], dst[32], misc[256], time[32], link1[32], link2[32];
+ char lbuf[160], *s;
+ int n, dots, slen, extra = 0;
+
+ if (!fgets(lbuf, sizeof(lbuf) - 1, tfp))
+ return 0;
+
+ if ((s = strchr(lbuf, '\n')))
+ *s = '\0';
+ lbuf[sizeof(lbuf)-1] = '\0';
+
+ bzero(&pkt, sizeof(pkt));
+
+ if ((n = sscanf(lbuf, "%s > %s: %s", src, dst, misc)) != 3)
+ if ((n = sscanf(lbuf, "%s %s > %s: %s",
+ time, src, dst, misc)) != 4)
+ if ((n = sscanf(lbuf, "%s %s: %s > %s: %s",
+ link1, link2, src, dst, misc)) != 5) {
+ n = sscanf(lbuf, "%s %s %s: %s > %s: %s",
+ time, link1, link2, src, dst, misc);
+ if (n != 6)
+ return -1;
+ }
+
+ if ((dots = count_dots(dst)) == 4) {
+ s = strrchr(src, '.');
+ *s++ = '\0';
+ (void) inet_aton(src, &ip->ip_src);
+ pkt.ti_sport = htons(atoi(s));
+ *--s = '.';
+ s = strrchr(dst, '.');
+
+ *s++ = '\0';
+ (void) inet_aton(src, &ip->ip_dst);
+ pkt.ti_dport = htons(atoi(s));
+ *--s = '.';
+
+ } else {
+ (void) inet_aton(src, &ip->ip_src);
+ (void) inet_aton(src, &ip->ip_dst);
+ }
+ ip->ip_len = ip->ip_hl = sizeof(struct ip);
+
+ s = strtok(misc, " :");
+ if ((p = getprotobyname(s))) {
+ ip->ip_p = p->p_proto;
+
+ switch (p->p_proto) {
+ case IPPROTO_TCP :
+ case IPPROTO_UDP :
+ s = strtok(NULL, " :");
+ ip->ip_len += atoi(s);
+ if (p->p_proto == IPPROTO_TCP)
+ extra = sizeof(struct tcphdr);
+ else if (p->p_proto == IPPROTO_UDP)
+ extra = sizeof(struct udphdr);
+ break;
+#ifdef IGMP
+ case IPPROTO_IGMP :
+ extra = sizeof(struct igmp);
+ break;
+#endif
+ case IPPROTO_ICMP :
+ extra = sizeof(struct icmp);
+ break;
+ default :
+ break;
+ }
+ }
+ slen = ip->ip_hl + extra + ip->ip_len;
+ return slen;
+}
diff --git a/contrib/ipfilter/ipft_tx.c b/contrib/ipfilter/ipft_tx.c
new file mode 100644
index 000000000000..0522f96cfae5
--- /dev/null
+++ b/contrib/ipfilter/ipft_tx.c
@@ -0,0 +1,338 @@
+/*
+ * (C)opyright 1995 by Darren Reed.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that this notice is preserved and due credit is given
+ * to the original author and the contributors.
+ */
+#include <stdio.h>
+#include <ctype.h>
+#include <assert.h>
+#include <string.h>
+#if !defined(__SVR4) && !defined(__svr4__)
+#include <strings.h>
+#else
+#include <sys/byteorder.h>
+#endif
+#include <sys/types.h>
+#include <sys/param.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <stddef.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip_var.h>
+#include <netinet/ip.h>
+#include <netinet/udp.h>
+#include <netinet/tcp.h>
+#include <netinet/ip_icmp.h>
+#include <netinet/tcpip.h>
+#include <arpa/inet.h>
+#include <net/if.h>
+#include <netdb.h>
+#include <arpa/nameser.h>
+#include <resolv.h>
+#include "ip_compat.h"
+#include "ipf.h"
+#include "ipt.h"
+
+#if !defined(lint) && defined(LIBC_SCCS)
+static char sccsid[] = "@(#)ipft_tx.c 1.7 6/5/96 (C) 1993 Darren Reed";
+static char rcsid[] = "$Id: ipft_tx.c,v 2.0.1.2 1997/01/19 04:52:25 darrenr Exp $";
+#endif
+
+extern int opts;
+extern u_long buildopts();
+
+static char *tx_proto = "";
+
+static int text_open(), text_close(), text_readip(), parseline();
+
+static char tcp_flagset[] = "FSRPAU";
+static u_char tcp_flags[] = { TH_FIN, TH_SYN, TH_RST, TH_PUSH,
+ TH_ACK, TH_URG };
+
+struct ipread iptext = { text_open, text_close, text_readip };
+static FILE *tfp = NULL;
+static int tfd = -1;
+
+static u_long tx_hostnum();
+static u_short tx_portnum();
+
+
+/*
+ * returns an ip address as a long var as a result of either a DNS lookup or
+ * straight inet_addr() call
+ */
+static u_long tx_hostnum(host, resolved)
+char *host;
+int *resolved;
+{
+ struct hostent *hp;
+ struct netent *np;
+
+ *resolved = 0;
+ if (!strcasecmp("any",host))
+ return 0L;
+ if (isdigit(*host))
+ return inet_addr(host);
+
+ if (!(hp = gethostbyname(host))) {
+ if (!(np = getnetbyname(host))) {
+ *resolved = -1;
+ fprintf(stderr, "can't resolve hostname: %s\n", host);
+ return 0;
+ }
+ return np->n_net;
+ }
+ return *(u_long *)hp->h_addr;
+}
+
+
+/*
+ * find the port number given by the name, either from getservbyname() or
+ * straight atoi()
+ */
+static u_short tx_portnum(name)
+char *name;
+{
+ struct servent *sp, *sp2;
+ u_short p1 = 0;
+
+ if (isdigit(*name))
+ return (u_short)atoi(name);
+ if (!tx_proto)
+ tx_proto = "tcp/udp";
+ if (strcasecmp(tx_proto, "tcp/udp")) {
+ sp = getservbyname(name, tx_proto);
+ if (sp)
+ return ntohs(sp->s_port);
+ (void) fprintf(stderr, "unknown service \"%s\".\n", name);
+ return 0;
+ }
+ sp = getservbyname(name, "tcp");
+ if (sp)
+ p1 = sp->s_port;
+ sp2 = getservbyname(name, "udp");
+ if (!sp || !sp2) {
+ (void) fprintf(stderr, "unknown tcp/udp service \"%s\".\n",
+ name);
+ return 0;
+ }
+ if (p1 != sp2->s_port) {
+ (void) fprintf(stderr, "%s %d/tcp is a different port to ",
+ name, p1);
+ (void) fprintf(stderr, "%s %d/udp\n", name, sp->s_port);
+ return 0;
+ }
+ return ntohs(p1);
+}
+
+
+char *tx_icmptypes[] = {
+ "echorep", (char *)NULL, (char *)NULL, "unreach", "squench",
+ "redir", (char *)NULL, (char *)NULL, "echo", (char *)NULL,
+ (char *)NULL, "timex", "paramprob", "timest", "timestrep",
+ "inforeq", "inforep", "maskreq", "maskrep", "END"
+};
+
+static int text_open(fname)
+char *fname;
+{
+ if (tfp && tfd != -1) {
+ rewind(tfp);
+ return tfd;
+ }
+
+ if (!strcmp(fname, "-")) {
+ tfd = 0;
+ tfp = stdin;
+ } else {
+ tfd = open(fname, O_RDONLY);
+ if (tfd != -1)
+ tfp = fdopen(tfd, "r");
+ }
+ return tfd;
+}
+
+
+static int text_close()
+{
+ int cfd = tfd;
+
+ tfd = -1;
+ return close(cfd);
+}
+
+
+static int text_readip(buf, cnt, ifn, dir)
+char *buf, **ifn;
+int cnt, *dir;
+{
+ register char *s;
+ struct ip *ip;
+ char line[513];
+
+ ip = (struct ip *)buf;
+ *ifn = NULL;
+ while (fgets(line, sizeof(line)-1, tfp)) {
+ if ((s = index(line, '\n')))
+ *s = '\0';
+ if ((s = index(line, '\r')))
+ *s = '\0';
+ if ((s = index(line, '#')))
+ *s = '\0';
+ if (!*line)
+ continue;
+ if (!(opts & OPT_BRIEF))
+ printf("input: %s\n", line);
+ *ifn = NULL;
+ *dir = 0;
+ if (!parseline(line, buf, ifn, dir))
+#if 0
+ return sizeof(struct tcpiphdr);
+#else
+ return sizeof(struct ip);
+#endif
+ }
+ return -1;
+}
+
+static int parseline(line, ip, ifn, out)
+char *line;
+struct ip *ip;
+char **ifn;
+int *out;
+{
+ tcphdr_t th, *tcp = &th;
+ struct icmp icmp, *ic = &icmp;
+ char *cps[20], **cpp, c, ipopts[68];
+ int i, r;
+
+ bzero((char *)ip, MAX(sizeof(*tcp), sizeof(*ic)) + sizeof(*ip));
+ bzero((char *)tcp, sizeof(*tcp));
+ bzero((char *)ic, sizeof(*ic));
+ bzero(ipopts, sizeof(ipopts));
+ ip->ip_hl = sizeof(*ip) >> 2;
+ ip->ip_v = IPVERSION;
+ for (i = 0, cps[0] = strtok(line, " \b\t\r\n"); cps[i] && i < 19; )
+ cps[++i] = strtok(NULL, " \b\t\r\n");
+ if (i < 2)
+ return 1;
+
+ cpp = cps;
+
+ c = **cpp;
+ if (!isalpha(c) || (tolower(c) != 'o' && tolower(c) != 'i')) {
+ fprintf(stderr, "bad direction \"%s\"\n", *cpp);
+ return 1;
+ }
+ *out = (tolower(c) == 'o') ? 1 : 0;
+ cpp++;
+
+ if (!strcasecmp(*cpp, "on")) {
+ cpp++;
+ if (!*cpp)
+ return 1;
+ *ifn = *cpp++;
+ }
+
+ c = **cpp;
+ ip->ip_len = sizeof(struct ip);
+ if (!strcasecmp(*cpp, "tcp") || !strcasecmp(*cpp, "udp") ||
+ !strcasecmp(*cpp, "icmp")) {
+ if (c == 't') {
+ ip->ip_p = IPPROTO_TCP;
+ ip->ip_len += sizeof(struct tcphdr);
+ tx_proto = "tcp";
+ } else if (c == 'u') {
+ ip->ip_p = IPPROTO_UDP;
+ ip->ip_len += sizeof(struct udphdr);
+ tx_proto = "udp";
+ } else {
+ ip->ip_p = IPPROTO_ICMP;
+ ip->ip_len += sizeof(struct icmp);
+ tx_proto = "icmp";
+ }
+ cpp++;
+ } else
+ ip->ip_p = IPPROTO_IP;
+
+ if (!*cpp)
+ return 1;
+ if (ip->ip_p == IPPROTO_TCP || ip->ip_p == IPPROTO_UDP) {
+ char *last;
+
+ last = index(*cpp, ',');
+ if (!last) {
+ fprintf(stderr, "tcp/udp with no source port\n");
+ return 1;
+ }
+ *last++ = '\0';
+ tcp->th_sport = htons(tx_portnum(last));
+ }
+ ip->ip_src.s_addr = tx_hostnum(*cpp, &r);
+ cpp++;
+ if (!*cpp)
+ return 1;
+
+ if (ip->ip_p == IPPROTO_TCP || ip->ip_p == IPPROTO_UDP) {
+ char *last;
+
+ last = index(*cpp, ',');
+ if (!last) {
+ fprintf(stderr, "tcp/udp with no destination port\n");
+ return 1;
+ }
+ *last++ = '\0';
+ tcp->th_dport = htons(tx_portnum(last));
+ }
+ ip->ip_dst.s_addr = tx_hostnum(*cpp, &r);
+ cpp++;
+ if (*cpp && ip->ip_p == IPPROTO_TCP) {
+ extern char tcp_flagset[];
+ extern u_char tcp_flags[];
+ char *s, *t;
+
+ for (s = *cpp; *s; s++)
+ if ((t = index(tcp_flagset, *s)))
+ tcp->th_flags |= tcp_flags[t - tcp_flagset];
+ if (tcp->th_flags)
+ cpp++;
+ assert(tcp->th_flags != 0);
+ } else if (*cpp && ip->ip_p == IPPROTO_ICMP) {
+ extern char *tx_icmptypes[];
+ char **s, *t;
+ int i;
+
+ for (s = tx_icmptypes, i = 0; !*s || strcmp(*s, "END");
+ s++, i++)
+ if (*s && !strncasecmp(*cpp, *s, strlen(*s))) {
+ ic->icmp_type = i;
+ if ((t = index(*cpp, ',')))
+ ic->icmp_code = atoi(t+1);
+ cpp++;
+ break;
+ }
+ }
+
+ if (*cpp && !strcasecmp(*cpp, "opt")) {
+ u_long olen;
+
+ cpp++;
+ olen = buildopts(*cpp, ipopts);
+ if (olen) {
+ bcopy(ipopts, (char *)(ip + 1), olen);
+ ip->ip_hl += olen >> 2;
+ }
+ }
+ if (ip->ip_p == IPPROTO_TCP || ip->ip_p == IPPROTO_UDP)
+ bcopy((char *)tcp, ((char *)ip) + (ip->ip_hl << 2),
+ sizeof(*tcp));
+ else if (ip->ip_p == IPPROTO_ICMP)
+ bcopy((char *)ic, ((char *)ip) + (ip->ip_hl << 2),
+ sizeof(*ic));
+ return 0;
+}
diff --git a/contrib/ipfilter/ipl.h b/contrib/ipfilter/ipl.h
new file mode 100644
index 000000000000..9a2e43d995d2
--- /dev/null
+++ b/contrib/ipfilter/ipl.h
@@ -0,0 +1,16 @@
+/*
+ * (C)opyright 1993-1996 by Darren Reed.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that this notice is preserved and due credit is given
+ * to the original author and the contributors.
+ *
+ * @(#)ipl.h 1.21 6/5/96
+ */
+
+#ifndef __IPL_H_
+#define __IPL_H__
+
+#define IPL_VERSION "IP Filter v3.1.7 - 8/2/97"
+
+#endif
diff --git a/contrib/ipfilter/ipl_ldev.c b/contrib/ipfilter/ipl_ldev.c
new file mode 100644
index 000000000000..a2893257e72e
--- /dev/null
+++ b/contrib/ipfilter/ipl_ldev.c
@@ -0,0 +1,83 @@
+/*
+ * (C)opyright 1993,1994,1995 by Darren Reed.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that this notice is preserved and due credit is given
+ * to the original author and the contributors.
+ */
+
+/*
+ * routines below for saving IP headers to buffer
+ */
+int iplopen(struct inode * inode, struct file * filp)
+{
+ u_int min = MINOR(inode->i_rdev);
+
+ if (flags & FWRITE)
+ return ENXIO;
+ if (min)
+ return ENXIO;
+ iplbusy++;
+ return 0;
+}
+
+
+int iplclose(struct inode * inode, struct file * filp)
+{
+ u_int min = MINOR(inode->i_rdev);
+
+ if (min)
+ return ENXIO;
+ iplbusy--;
+ return 0;
+}
+
+
+/*
+ * iplread/ipllog
+ * all three of these must operate with at least splnet() lest they be
+ * called during packet processing and cause an inconsistancy to appear in
+ * the filter lists.
+ */
+int iplread(struct inode *inode, struct file *file, char *buf, int count)
+{
+ register int ret, s;
+ register size_t sz, sx;
+ int error;
+
+ if (!uio->uio_resid)
+ return 0;
+ while (!iplused) {
+ error = SLEEP(iplbuf, "ipl sleep");
+ if (error)
+ return error;
+ }
+
+ SPLNET(s);
+
+ ret = sx = sz = MIN(count, iplused);
+ if (iplh < iplt)
+ sz = MIN(sz, LOGSIZE - (iplt - iplbuf));
+ sx -= sz;
+
+ memcpy_tofs(buf, iplt, sz);
+ buf += sz;
+ iplt += sz;
+ iplused -= sz;
+ if ((iplh < iplt) && (iplt == iplbuf + LOGSIZE))
+ iplt = iplbuf;
+
+ if (sx) {
+ memcpy_tofs(buf, iplt, sx);
+ ret += sx;
+ iplt += sx;
+ iplused -= sx;
+ if ((iplh < iplt) && (iplt == iplbuf + LOGSIZE))
+ iplt = iplbuf;
+ }
+ if (!iplused) /* minimise wrapping around the end */
+ iplh = iplt = iplbuf;
+
+ SPLX(s);
+ return ret;
+}
diff --git a/contrib/ipfilter/ipmon.c b/contrib/ipfilter/ipmon.c
new file mode 100644
index 000000000000..2ea34efb1874
--- /dev/null
+++ b/contrib/ipfilter/ipmon.c
@@ -0,0 +1,582 @@
+/*
+ * (C)opyright 1993-1996 by Darren Reed.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that this notice is preserved and due credit is given
+ * to the original author and the contributors.
+ */
+
+#include <stdio.h>
+#include <assert.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <stdlib.h>
+#include <syslog.h>
+#include <sys/errno.h>
+#include <sys/file.h>
+#include <sys/ioctl.h>
+#include <sys/param.h>
+#include <sys/uio.h>
+#if !defined(__SVR4) && !defined(__svr4__)
+#include <sys/dir.h>
+#include <sys/mbuf.h>
+#else
+#include <sys/byteorder.h>
+#endif
+#include <sys/protosw.h>
+#include <sys/socket.h>
+#include <sys/user.h>
+
+#include <net/if.h>
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/ip_var.h>
+#include <netinet/tcp.h>
+#include <netinet/tcpip.h>
+#include <netinet/ip_icmp.h>
+#include <netdb.h>
+#include <arpa/inet.h>
+#include <ctype.h>
+
+#if !defined(lint) && defined(LIBC_SCCS)
+static char rcsid[] = "$Id: ipmon.c,v 2.0.1.2 1997/02/04 14:49:19 darrenr Exp $";
+#endif
+
+#include "ip_fil.h"
+
+
+struct flags {
+ int value;
+ char flag;
+};
+
+struct flags tcpfl[] = {
+ { TH_ACK, 'A' },
+ { TH_RST, 'R' },
+ { TH_SYN, 'S' },
+ { TH_FIN, 'F' },
+ { TH_URG, 'U' },
+ { TH_PUSH,'P' },
+ { 0, '\0' }
+};
+
+
+static char line[2048];
+static void printpacket(), dumphex();
+static int opts = 0;
+
+#define OPT_SYSLOG 0x01
+#define OPT_RESOLVE 0x02
+#define OPT_HEXBODY 0x04
+#define OPT_VERBOSE 0x08
+#define OPT_HEXHDR 0x10
+
+#ifndef LOGFAC
+#define LOGFAC LOG_LOCAL0
+#endif
+
+void printiplci(icp)
+struct ipl_ci *icp;
+{
+ printf("sec %ld usec %ld hlen %d plen %d\n", icp->sec, icp->usec,
+ icp->hlen, icp->plen);
+}
+
+
+void resynclog(fd, iplcp, log)
+int fd;
+struct ipl_ci *iplcp;
+FILE *log;
+{
+ time_t now;
+ char *s = NULL;
+ int len, nr = 0;
+
+ do {
+ if (s) {
+ s = (char *)&iplcp->sec;
+ if (opts & OPT_SYSLOG) {
+ syslog(LOG_INFO, "Sync bytes:");
+ syslog(LOG_INFO, " %02x %02x %02x %02x",
+ *s, *(s+1), *(s+2), *(s+3));
+ syslog(LOG_INFO, " %02x %02x %02x %02x\n",
+ *(s+4), *(s+5), *(s+6), *(s+7));
+ } else {
+ fprintf(log, "Sync bytes:");
+ fprintf(log, " %02x %02x %02x %02x",
+ *s, *(s+1), *(s+2), *(s+3));
+ fprintf(log, " %02x %02x %02x %02x\n",
+ *(s+4), *(s+5), *(s+6), *(s+7));
+ }
+ }
+ do {
+ s = (char *)&iplcp->sec;
+ len = sizeof(iplcp->sec);
+ while (len) {
+ switch ((nr = read(fd, s, len)))
+ {
+ case -1:
+ case 0:
+ return;
+ default :
+ s += nr;
+ len -= nr;
+ now = time(NULL);
+ break;
+ }
+ }
+ } while ((now < iplcp->sec) ||
+ ((iplcp->sec - now) > (86400*5)));
+
+ len = sizeof(iplcp->usec);
+ while (len) {
+ switch ((nr = read(fd, s, len)))
+ {
+ case -1:
+ case 0:
+ return;
+ default :
+ s += nr;
+ len -= nr;
+ break;
+ }
+ }
+ } while (iplcp->usec > 1000000);
+
+ len = sizeof(*iplcp) - sizeof(iplcp->sec) - sizeof(iplcp->usec);
+ while (len) {
+ switch ((nr = read(fd, s, len)))
+ {
+ case -1:
+ case 0:
+ return;
+ default :
+ s += nr;
+ len -= nr;
+ break;
+ }
+ }
+}
+
+
+int readlogentry(fd, lenp, buf, bufsize, log)
+int fd, bufsize, *lenp;
+char *buf;
+FILE *log;
+{
+ struct ipl_ci *icp = (struct ipl_ci *)buf;
+ time_t now;
+ char *s;
+ int len, n = bufsize, tr = sizeof(struct ipl_ci), nr;
+
+ if (bufsize < tr)
+ return 1;
+ for (s = buf; (n > 0) && (tr > 0); s += nr, n -= nr) {
+ nr = read(fd, s, tr);
+ if (nr > 0)
+ tr -= nr;
+ else
+ return -1;
+ }
+
+ now = time(NULL);
+ if ((icp->hlen > 92) || (now < icp->sec) ||
+ ((now - icp->sec) > (86400*5))) {
+ if (opts & OPT_SYSLOG)
+ syslog(LOG_INFO, "Out of sync! (1,%x)\n", now);
+ else
+ fprintf(log, "Out of sync! (1,%x)\n", now);
+ dumphex(log, buf, sizeof(struct ipl_ci));
+ resynclog(fd, icp, log);
+ }
+
+
+ len = (int)((u_int)icp->plen);
+ if (len > 128 || len < 0) {
+ if (opts & OPT_SYSLOG)
+ syslog(LOG_INFO, "Out of sync! (2,%d)\n", len);
+ else
+ fprintf(log, "Out of sync! (2,%d)\n", len);
+ dumphex(log, buf, sizeof(struct ipl_ci));
+ resynclog(fd, icp, log);
+ }
+
+
+ tr = icp->hlen + icp->plen;
+ if (n < tr)
+ return 1;
+
+ for (; (n > 0) && (tr > 0); s += nr, n-= nr) {
+ nr = read(fd, s, tr);
+ if (nr > 0)
+ tr -= nr;
+ else
+ return -1;
+ }
+ *lenp = s - buf;
+ return 0;
+}
+
+
+char *hostname(res, ip)
+int res;
+struct in_addr ip;
+{
+ struct hostent *hp;
+
+ if (!res)
+ return inet_ntoa(ip);
+ hp = gethostbyaddr((char *)&ip, sizeof(ip), AF_INET);
+ if (!hp)
+ return inet_ntoa(ip);
+ return hp->h_name;
+}
+
+
+char *portname(res, proto, port)
+int res;
+char *proto;
+u_short port;
+{
+ static char pname[8];
+ struct servent *serv;
+
+ (void) sprintf(pname, "%hu", htons(port));
+ if (!res)
+ return pname;
+ serv = getservbyport((int)port, proto);
+ if (!serv)
+ return pname;
+ return serv->s_name;
+}
+
+
+static void dumphex(log, buf, len)
+FILE *log;
+u_char *buf;
+int len;
+{
+ char line[80];
+ int i, j, k;
+ u_char *s = buf, *t = (u_char *)line;
+
+ for (i = len, j = 0; i; i--, j++, s++) {
+ if (j && !(j & 0xf)) {
+ *t++ = '\n';
+ *t = '\0';
+ fputs(line, stdout);
+ t = (u_char *)line;
+ *t = '\0';
+ }
+ sprintf(t, "%02x", *s & 0xff);
+ t += 2;
+ if (!((j + 1) & 0xf)) {
+ s -= 15;
+ sprintf(t, " ");
+ t += 8;
+ for (k = 16; k; k--, s++)
+ *t++ = (isprint(*s) ? *s : '.');
+ s--;
+ }
+
+ if ((j + 1) & 0xf)
+ *t++ = ' ';;
+ }
+
+ if (j & 0xf) {
+ for (k = 16 - (j & 0xf); k; k--) {
+ *t++ = ' ';
+ *t++ = ' ';
+ *t++ = ' ';
+ }
+ sprintf(t, " ");
+ t += 7;
+ s -= j & 0xf;
+ for (k = j & 0xf; k; k--, s++)
+ *t++ = (isprint(*s) ? *s : '.');
+ *t++ = '\n';
+ *t = '\0';
+ }
+ fputs(line, stdout);
+ fflush(stdout);
+}
+
+
+static void printpacket(log, buf, blen)
+FILE *log;
+char *buf;
+int blen;
+{
+ struct protoent *pr;
+ struct tcphdr *tp;
+ struct icmp *ic;
+ struct ip *ipc;
+ struct tm *tm;
+ char c[3], pname[8], *t, *proto;
+ u_short hl, p;
+ int i, lvl, res;
+#if !SOLARIS && !(defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199603))
+ int len;
+#endif
+ struct ip *ip;
+ struct ipl_ci *lp;
+
+ lp = (struct ipl_ci *)buf;
+ ip = (struct ip *)(buf + sizeof(*lp));
+ res = (opts & OPT_RESOLVE) ? 1 : 0;
+ t = line;
+ *t = '\0';
+ hl = (ip->ip_hl << 2);
+ p = (u_short)ip->ip_p;
+ tm = localtime((time_t *)&lp->sec);
+ if (!(opts & OPT_SYSLOG)) {
+ (void) sprintf(t, "%2d/%02d/%4d ",
+ tm->tm_mday, tm->tm_mon + 1, tm->tm_year + 1900);
+ t += strlen(t);
+ }
+#if SOLARIS || (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199603))
+ (void) sprintf(t, "%02d:%02d:%02d.%-.6ld %.*s @%hd ",
+ tm->tm_hour, tm->tm_min, tm->tm_sec, lp->usec,
+ (int)sizeof(lp->ifname), lp->ifname, lp->rule);
+#else
+ for (len = 0; len < 3; len++)
+ if (!lp->ifname[len])
+ break;
+ if (lp->ifname[len])
+ len++;
+ (void) sprintf(t, "%02d:%02d:%02d.%-.6ld %*.*s%ld @%hd ",
+ tm->tm_hour, tm->tm_min, tm->tm_sec, lp->usec,
+ len, len, lp->ifname, lp->unit, lp->rule);
+#endif
+ pr = getprotobynumber((int)p);
+ if (!pr) {
+ proto = pname;
+ sprintf(proto, "%d", (u_int)p);
+ } else
+ proto = pr->p_name;
+
+ if (lp->flags & (FI_SHORT << 20)) {
+ c[0] = 'S';
+ lvl = LOG_ERR;
+ } else if (lp->flags & FR_PASS) {
+ if (lp->flags & FR_LOGP)
+ c[0] = 'p';
+ else
+ c[0] = 'P';
+ lvl = LOG_NOTICE;
+ } else if (lp->flags & FR_BLOCK) {
+ if (lp->flags & FR_LOGB)
+ c[0] = 'b';
+ else
+ c[0] = 'B';
+ lvl = LOG_WARNING;
+ } else if (lp->flags & FF_LOGNOMATCH) {
+ c[0] = 'n';
+ lvl = LOG_NOTICE;
+ } else {
+ c[0] = 'L';
+ lvl = LOG_INFO;
+ }
+ c[1] = ' ';
+ c[2] = '\0';
+ (void) strcat(line, c);
+ t = line + strlen(line);
+
+ if ((p == IPPROTO_TCP || p == IPPROTO_UDP) && !(ip->ip_off & 0x1fff)) {
+ tp = (struct tcphdr *)((char *)ip + hl);
+ if (!(lp->flags & (FI_SHORT << 16))) {
+ (void) sprintf(t, "%s,%s -> ",
+ hostname(res, ip->ip_src),
+ portname(res, proto, tp->th_sport));
+ t += strlen(t);
+ (void) sprintf(t, "%s,%s PR %s len %hu %hu ",
+ hostname(res, ip->ip_dst),
+ portname(res, proto, tp->th_dport),
+ proto, hl, ip->ip_len);
+ t += strlen(t);
+
+ if (p == IPPROTO_TCP) {
+ *t++ = '-';
+ for (i = 0; tcpfl[i].value; i++)
+ if (tp->th_flags & tcpfl[i].value)
+ *t++ = tcpfl[i].flag;
+ }
+ if (opts & OPT_VERBOSE) {
+ (void) sprintf(t, " %lu %lu %hu",
+ (u_long)tp->th_seq,
+ (u_long)tp->th_ack, tp->th_win);
+ t += strlen(t);
+ }
+ *t = '\0';
+ } else {
+ (void) sprintf(t, "%s -> ", hostname(res, ip->ip_src));
+ t += strlen(t);
+ (void) sprintf(t, "%s PR %s len %hu %hu",
+ hostname(res, ip->ip_dst), proto,
+ hl, ip->ip_len);
+ }
+ } else if (p == IPPROTO_ICMP) {
+ ic = (struct icmp *)((char *)ip + hl);
+ (void) sprintf(t, "%s -> ", hostname(res, ip->ip_src));
+ t += strlen(t);
+ (void) sprintf(t, "%s PR icmp len %hu (%hu) icmp %d/%d",
+ hostname(res, ip->ip_dst), hl,
+ ip->ip_len, ic->icmp_type, ic->icmp_code);
+ if (ic->icmp_type == ICMP_UNREACH ||
+ ic->icmp_type == ICMP_SOURCEQUENCH ||
+ ic->icmp_type == ICMP_PARAMPROB ||
+ ic->icmp_type == ICMP_REDIRECT ||
+ ic->icmp_type == ICMP_TIMXCEED) {
+ ipc = &ic->icmp_ip;
+ tp = (struct tcphdr *)((char *)ipc + hl);
+
+ p = (u_short)ipc->ip_p;
+ pr = getprotobynumber((int)p);
+ if (!pr) {
+ proto = pname;
+ (void) sprintf(proto, "%d", (int)p);
+ } else
+ proto = pr->p_name;
+
+ t += strlen(t);
+ (void) sprintf(t, " for %s,%s -",
+ hostname(res, ipc->ip_src),
+ portname(res, proto, tp->th_sport));
+ t += strlen(t);
+ (void) sprintf(t, " %s,%s PR %s len %hu %hu",
+ hostname(res, ipc->ip_dst),
+ portname(res, proto, tp->th_dport),
+ proto, ipc->ip_hl << 2, ipc->ip_len);
+ }
+ } else {
+ (void) sprintf(t, "%s -> ", hostname(res, ip->ip_src));
+ t += strlen(t);
+ (void) sprintf(t, "%s PR %s len %hu (%hu)",
+ hostname(res, ip->ip_dst), proto, hl, ip->ip_len);
+ t += strlen(t);
+ if (ip->ip_off & 0x1fff)
+ (void) sprintf(t, " frag %s%s%hu@%hu",
+ ip->ip_off & IP_MF ? "+" : "",
+ ip->ip_off & IP_DF ? "-" : "",
+ ip->ip_len - hl, (ip->ip_off & 0x1fff) << 3);
+ }
+ t += strlen(t);
+
+ if (lp->flags & FR_KEEPSTATE) {
+ (void) strcpy(t, " K-S");
+ t += strlen(t);
+ }
+
+ if (lp->flags & FR_KEEPFRAG) {
+ (void) strcpy(t, " K-F");
+ t += strlen(t);
+ }
+
+ *t++ = '\n';
+ *t++ = '\0';
+ if (opts & OPT_SYSLOG)
+ syslog(lvl, "%s", line);
+ else
+ (void) fprintf(log, "%s", line);
+ if (opts & OPT_HEXHDR)
+ dumphex(log, buf, sizeof(struct ipl_ci));
+ if (opts & OPT_HEXBODY)
+ dumphex(log, ip, lp->plen + lp->hlen);
+ fflush(log);
+}
+
+int main(argc, argv)
+int argc;
+char *argv[];
+{
+ FILE *log = NULL;
+ int fd = -1, flushed = 0, doread, n;
+ char buf[512], c, *iplfile = IPL_NAME;
+ extern int optind;
+ extern char *optarg;
+
+ while ((c = getopt(argc, argv, "Nf:FsvxX")) != -1)
+ switch (c)
+ {
+ case 'f' :
+ iplfile = optarg;
+ break;
+ case 'F' :
+ if ((fd == -1) &&
+ (fd = open(iplfile, O_RDWR)) == -1) {
+ (void) fprintf(stderr, "%s: ", IPL_NAME);
+ perror("open");
+ exit(-1);
+ }
+ if (ioctl(fd, SIOCIPFFB, &flushed) == 0) {
+ printf("%d bytes flushed from log buffer\n",
+ flushed);
+ fflush(stdout);
+ } else
+ perror("SIOCIPFFB");
+ break;
+ case 'N' :
+ opts |= OPT_RESOLVE;
+ break;
+ case 's' :
+ openlog(argv[0], LOG_NDELAY|LOG_PID, LOGFAC);
+ opts |= OPT_SYSLOG;
+ break;
+ case 'v' :
+ opts |= OPT_VERBOSE;
+ break;
+ case 'x' :
+ opts |= OPT_HEXBODY;
+ break;
+ case 'X' :
+ opts |= OPT_HEXHDR;
+ break;
+ }
+
+ if ((fd == -1) && (fd = open(iplfile, O_RDONLY)) == -1) {
+ (void) fprintf(stderr, "%s: ", IPL_NAME);
+ perror("open");
+ exit(-1);
+ }
+
+ if (!(opts & OPT_SYSLOG)) {
+ log = argv[optind] ? fopen(argv[optind], "a") : stdout;
+ setvbuf(log, NULL, _IONBF, 0);
+ }
+
+ if (flushed) {
+ if (opts & OPT_SYSLOG)
+ syslog(LOG_INFO, "%d bytes flushed from log\n",
+ flushed);
+ else
+ fprintf(log, "%d bytes flushed from log\n", flushed);
+ }
+
+ for (doread = 1; doread; )
+ switch (readlogentry(fd, &n, buf, sizeof(buf), log))
+ {
+ case -1 :
+ if (opts & OPT_SYSLOG)
+ syslog(LOG_ERR, "read: %m\n");
+ else
+ perror("read");
+ doread = 0;
+ break;
+ case 1 :
+ if (opts & OPT_SYSLOG)
+ syslog(LOG_ERR, "aborting logging\n");
+ else
+ fprintf(log, "aborting logging\n");
+ doread = 0;
+ break;
+ case 2 :
+ break;
+ case 0 :
+ printpacket(log, buf, n, opts);
+ break;
+ }
+ exit(0);
+ /* NOTREACHED */
+}
diff --git a/contrib/ipfilter/ipnat.c b/contrib/ipfilter/ipnat.c
new file mode 100644
index 000000000000..6458cde86b92
--- /dev/null
+++ b/contrib/ipfilter/ipnat.c
@@ -0,0 +1,692 @@
+/*
+ * (C)opyright 1993,1994,1995 by Darren Reed.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that this notice is preserved and due credit is given
+ * to the original author and the contributors.
+ *
+ * Added redirect stuff and a variety of bug fixes. (mcn@EnGarde.com)
+ *
+ * Broken still:
+ * Displaying the nat with redirect entries is way confusing
+ *
+ * Example redirection line:
+ * rdr le1 0.0.0.0/0 port 79 -> 199.165.219.129 port 9901
+ *
+ * Will redirect all incoming packets on le1 to any machine, port 79 to
+ * host 199.165.219.129, port 9901
+ */
+#include <stdio.h>
+#include <string.h>
+#include <fcntl.h>
+#if !defined(__SVR4) && !defined(__svr4__)
+#include <strings.h>
+#else
+#include <sys/byteorder.h>
+#endif
+#include <sys/types.h>
+#include <sys/param.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <stddef.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#if defined(sun) && (defined(__svr4__) || defined(__SVR4))
+# include <sys/ioccom.h>
+# include <sys/sysmacros.h>
+#endif
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/tcp.h>
+#include <net/if.h>
+#include "ip_compat.h"
+#include <netdb.h>
+#include <arpa/nameser.h>
+#include <arpa/inet.h>
+#include <resolv.h>
+#include "ip_nat.h"
+#include <ctype.h>
+
+
+#if !defined(lint) && defined(LIBC_SCCS)
+static char sccsid[] ="@(#)ipnat.c 1.9 6/5/96 (C) 1993 Darren Reed";
+static char rcsid[] = "$Id: ipnat.c,v 2.0.1.7 1997/01/30 12:02:32 darrenr Exp $";
+#endif
+
+#if SOLARIS
+#define bzero(a,b) memset(a,0,b)
+#endif
+
+extern char *optarg;
+extern int kmemcpy();
+
+void dostats(), printnat(), parsefile(), flushtable();
+
+#define OPT_REM 1
+#define OPT_NODO 2
+#define OPT_STAT 4
+#define OPT_LIST 8
+#define OPT_VERBOSE 16
+#define OPT_FLUSH 32
+#define OPT_CLEAR 64
+
+
+void usage(name)
+char *name;
+{
+ fprintf(stderr, "%s: [-CFlnrsv] [-f filename]\n", name);
+ exit(1);
+}
+
+
+int main(argc, argv)
+int argc;
+char *argv[];
+{
+ char *file = NULL, c;
+ int fd, opts = 1;
+
+ while ((c = getopt(argc, argv, "CFf:lnrsv")) != -1)
+ switch (c)
+ {
+ case 'C' :
+ opts |= OPT_CLEAR;
+ break;
+ case 'f' :
+ file = optarg;
+ break;
+ case 'F' :
+ opts |= OPT_FLUSH;
+ break;
+ case 'l' :
+ opts |= OPT_LIST;
+ break;
+ case 'n' :
+ opts |= OPT_NODO;
+ break;
+ case 'r' :
+ opts &= ~OPT_REM;
+ break;
+ case 's' :
+ opts |= OPT_STAT;
+ break;
+ case 'v' :
+ opts |= OPT_VERBOSE;
+ break;
+ default :
+ usage(argv[0]);
+ }
+
+ if (!(opts & OPT_NODO) && ((fd = open(IPL_NAME, O_RDWR)) == -1) &&
+ ((fd = open(IPL_NAME, O_RDONLY)) == -1)) {
+ perror("open");
+ exit(-1);
+ }
+
+ if (opts & (OPT_FLUSH|OPT_CLEAR))
+ flushtable(fd, opts);
+ if (file)
+ parsefile(fd, file, opts);
+ if (opts & (OPT_LIST|OPT_STAT))
+ dostats(fd, opts);
+ return 0;
+}
+
+
+/*
+ * count consecutive 1's in bit mask. If the mask generated by counting
+ * consecutive 1's is different to that passed, return -1, else return #
+ * of bits.
+ */
+int countbits(ip)
+u_long ip;
+{
+ u_long ipn;
+ int cnt = 0, i, j;
+
+ ip = ipn = ntohl(ip);
+ for (i = 32; i; i--, ipn *= 2)
+ if (ipn & 0x80000000)
+ cnt++;
+ else
+ break;
+ ipn = 0;
+ for (i = 32, j = cnt; i; i--, j--) {
+ ipn *= 2;
+ if (j > 0)
+ ipn++;
+ }
+ if (ipn == ip)
+ return cnt;
+ return -1;
+}
+
+
+void printnat(np, verbose, ptr)
+ipnat_t *np;
+int verbose;
+void *ptr;
+{
+ int bits;
+
+ if (np->in_redir == NAT_REDIRECT) {
+ printf("rdr %s %s", np->in_ifname, inet_ntoa(np->in_out[0]));
+ bits = countbits(np->in_out[1].s_addr);
+ if (bits != -1)
+ printf("/%d ", bits);
+ else
+ printf("/%s ", inet_ntoa(np->in_out[1]));
+ if (np->in_pmin)
+ printf("port %d ", ntohs(np->in_pmin));
+ printf("-> %s", inet_ntoa(np->in_in[0]));
+ if (np->in_pnext)
+ printf(" port %d", ntohs(np->in_pnext));
+ if (np->in_flags & IPN_TCPUDP)
+ printf(" tcp/udp");
+ else if (np->in_flags & IPN_TCP)
+ printf(" tcp");
+ else if (np->in_flags & IPN_UDP)
+ printf(" udp");
+ printf("\n");
+ if (verbose)
+ printf("\t%x %u %x %u %x %d\n", (u_int)np->in_ifp,
+ np->in_space, np->in_flags, np->in_pnext, np,
+ np->in_use);
+ } else {
+ np->in_nextip.s_addr = htonl(np->in_nextip.s_addr);
+ printf("map %s %s/", np->in_ifname, inet_ntoa(np->in_in[0]));
+ bits = countbits(np->in_in[1].s_addr);
+ if (bits != -1)
+ printf("%d ", bits);
+ else
+ printf("%s", inet_ntoa(np->in_in[1]));
+ printf(" -> %s/", inet_ntoa(np->in_out[0]));
+ bits = countbits(ntohl(np->in_out[1].s_addr));
+ if (bits != -1)
+ printf("%d ", bits);
+ else
+ printf("%s", inet_ntoa(np->in_out[1]));
+ if (np->in_pmin || np->in_pmax) {
+ printf(" portmap");
+ if ((np->in_flags & IPN_TCPUDP) == IPN_TCPUDP)
+ printf(" tcp/udp");
+ else if (np->in_flags & IPN_TCP)
+ printf(" tcp");
+ else if (np->in_flags & IPN_UDP)
+ printf(" udp");
+ printf(" %d:%d", ntohs(np->in_pmin),
+ ntohs(np->in_pmax));
+ }
+ printf("\n");
+ if (verbose)
+ printf("\t%x %u %s %d %x\n", (u_int)np->in_ifp,
+ np->in_space, inet_ntoa(np->in_nextip),
+ np->in_pnext, np->in_flags);
+ }
+}
+
+
+/*
+ * Get a nat filter type given its kernel address.
+ */
+char *getnattype(ipnat)
+ipnat_t *ipnat;
+{
+ ipnat_t ipnatbuff;
+
+ if (ipnat && kmemcpy(&ipnatbuff, ipnat, sizeof(ipnatbuff)))
+ return "???";
+
+ return (ipnatbuff.in_redir == NAT_MAP) ? "MAP" : "RDR";
+}
+
+
+void dostats(fd, opts)
+int fd, opts;
+{
+ natstat_t ns;
+ ipnat_t ipn;
+ nat_t **nt[2], *np, nat;
+ int i = 0;
+
+ bzero((char *)&ns, sizeof(ns));
+
+ if (!(opts & OPT_NODO) && ioctl(fd, SIOCGNATS, &ns) == -1) {
+ perror("ioctl(SIOCGNATS)");
+ return;
+ }
+
+ if (opts & OPT_STAT) {
+ printf("mapped\tin\t%lu\tout\t%lu\n",
+ ns.ns_mapped[0], ns.ns_mapped[1]);
+ printf("added\t%lu\texpired\t%lu\n",
+ ns.ns_added, ns.ns_expire);
+ printf("inuse\t%lu\n", ns.ns_inuse);
+ if (opts & OPT_VERBOSE)
+ printf("table %#x list %#x\n",
+ (u_int)ns.ns_table, (u_int)ns.ns_list);
+ }
+ if (opts & OPT_LIST) {
+ printf("List of active MAP/Redirect filters:\n");
+ while (ns.ns_list) {
+ if (kmemcpy(&ipn, ns.ns_list, sizeof(ipn))) {
+ perror("kmemcpy");
+ break;
+ }
+ printnat(&ipn, opts & OPT_VERBOSE, (void *)ns.ns_list);
+ ns.ns_list = ipn.in_next;
+ }
+
+ nt[0] = (nat_t **)malloc(sizeof(*nt) * NAT_SIZE);
+ if (kmemcpy(nt[0], ns.ns_table[0], sizeof(**nt) * NAT_SIZE)) {
+ perror("kmemcpy");
+ return;
+ }
+
+ printf("\nList of active sessions:\n");
+
+ for (i = 0; i < NAT_SIZE; i++)
+ for (np = nt[0][i]; np; np = nat.nat_hnext[0]) {
+ if (kmemcpy(&nat, np, sizeof(nat)))
+ break;
+
+ printf("%s %-15s %-5hu <- ->",
+ getnattype(nat.nat_ptr),
+ inet_ntoa(nat.nat_inip),
+ ntohs(nat.nat_inport));
+ printf(" %-15s %-5hu",
+ inet_ntoa(nat.nat_outip),
+ ntohs(nat.nat_outport));
+ printf(" [%s %hu]", inet_ntoa(nat.nat_oip),
+ ntohs(nat.nat_oport));
+ printf(" %d %hu %lx", nat.nat_age,
+ nat.nat_use, nat.nat_sumd);
+#if SOLARIS
+ printf(" %lx", nat.nat_ipsumd);
+#endif
+ putchar('\n');
+ }
+ free(nt[0]);
+ }
+}
+
+
+u_short portnum(name, proto)
+char *name, *proto;
+{
+ struct servent *sp, *sp2;
+ u_short p1 = 0;
+
+ if (isdigit(*name))
+ return htons((u_short)atoi(name));
+ if (!proto)
+ proto = "tcp/udp";
+ if (strcasecmp(proto, "tcp/udp")) {
+ sp = getservbyname(name, proto);
+ if (sp)
+ return sp->s_port;
+ (void) fprintf(stderr, "unknown service \"%s\".\n", name);
+ return 0;
+ }
+ sp = getservbyname(name, "tcp");
+ if (sp)
+ p1 = sp->s_port;
+ sp2 = getservbyname(name, "udp");
+ if (!sp || !sp2) {
+ (void) fprintf(stderr, "unknown tcp/udp service \"%s\".\n",
+ name);
+ return 0;
+ }
+ if (p1 != sp2->s_port) {
+ (void) fprintf(stderr, "%s %d/tcp is a different port to ",
+ name, p1);
+ (void) fprintf(stderr, "%s %d/udp\n", name, sp->s_port);
+ return 0;
+ }
+ return p1;
+}
+
+
+u_long hostmask(msk)
+char *msk;
+{
+ int bits = -1;
+ u_long mask;
+
+ if (!isdigit(*msk))
+ return (u_long)-1;
+ if (strchr(msk, '.'))
+ return inet_addr(msk);
+ if (strchr(msk, 'x'))
+ return (u_long)strtol(msk, NULL, 0);
+ /*
+ * set x most significant bits
+ */
+ for (mask = 0, bits = atoi(msk); bits; bits--) {
+ mask /= 2;
+ mask |= ntohl(inet_addr("128.0.0.0"));
+ }
+ mask = htonl(mask);
+ return mask;
+}
+
+
+/*
+ * returns an ip address as a long var as a result of either a DNS lookup or
+ * straight inet_addr() call
+ */
+u_long hostnum(host, resolved)
+char *host;
+int *resolved;
+{
+ struct hostent *hp;
+ struct netent *np;
+
+ *resolved = 0;
+ if (!strcasecmp("any",host))
+ return 0L;
+ if (isdigit(*host))
+ return inet_addr(host);
+
+ if (!(hp = gethostbyname(host))) {
+ if (!(np = getnetbyname(host))) {
+ *resolved = -1;
+ fprintf(stderr, "can't resolve hostname: %s\n", host);
+ return 0;
+ }
+ return np->n_net;
+ }
+ return *(u_long *)hp->h_addr;
+}
+
+
+ipnat_t *parse(line)
+char *line;
+{
+ static ipnat_t ipn;
+ char *s, *t;
+ char *shost, *snetm, *dhost, *proto;
+ char *dnetm = NULL, *dport = NULL, *tport = NULL;
+ int resolved;
+
+ bzero((char *)&ipn, sizeof(ipn));
+ if ((s = strchr(line, '\n')))
+ *s = '\0';
+ if ((s = strchr(line, '#')))
+ *s = '\0';
+ if (!*line)
+ return NULL;
+ if (!(s = strtok(line, " \t")))
+ return NULL;
+ if (!strcasecmp(s, "map"))
+ ipn.in_redir = NAT_MAP;
+ else if (!strcasecmp(s, "rdr"))
+ ipn.in_redir = NAT_REDIRECT;
+ else {
+ (void)fprintf(stderr,
+ "expected \"map\" or \"rdr\", got \"%s\"\n", s);
+ return NULL;
+ }
+
+ if (!(s = strtok(NULL, " \t"))) {
+ fprintf(stderr, "missing fields (interface)\n");
+ return NULL;
+ }
+ strncpy(ipn.in_ifname, s, sizeof(ipn.in_ifname) - 1);
+ ipn.in_ifname[sizeof(ipn.in_ifname) - 1] = '\0';
+ if (!(s = strtok(NULL, " \t"))) {
+ fprintf(stderr, "missing fields (%s)\n",
+ ipn.in_redir ? "destination": "source");
+ return NULL;
+ }
+ shost = s;
+
+ if (ipn.in_redir == NAT_REDIRECT) {
+ if (!(s = strtok(NULL, " \t"))) {
+ fprintf(stderr, "missing fields (destination port)\n");
+ return NULL;
+ }
+
+ if (strcasecmp(s, "port")) {
+ fprintf(stderr, "missing fields (port)\n");
+ return NULL;
+ }
+
+ if (!(s = strtok(NULL, " \t"))) {
+ fprintf(stderr, "missing fields (destination port)\n");
+ return NULL;
+ }
+
+ dport = s;
+ }
+
+
+ if (!(s = strtok(NULL, " \t"))) {
+ fprintf(stderr, "missing fields (->)\n");
+ return NULL;
+ }
+ if (!strcmp(s, "->")) {
+ snetm = strrchr(shost, '/');
+ if (!snetm) {
+ fprintf(stderr, "missing fields (%s netmask)\n",
+ ipn.in_redir ? "destination":"source");
+ return NULL;
+ }
+ } else {
+ if (strcasecmp(s, "netmask")) {
+ fprintf(stderr, "missing fields (netmask)\n");
+ return NULL;
+ }
+ if (!(s = strtok(NULL, " \t"))) {
+ fprintf(stderr, "missing fields (%s netmask)\n",
+ ipn.in_redir ? "destination":"source");
+ return NULL;
+ }
+ snetm = s;
+ }
+
+ if (!(s = strtok(NULL, " \t"))) {
+ fprintf(stderr, "missing fields (%s)\n",
+ ipn.in_redir ? "destination":"target");
+ return NULL;
+ }
+ dhost = s;
+
+ if (ipn.in_redir == NAT_MAP) {
+ if (!(s = strtok(NULL, " \t"))) {
+ dnetm = strrchr(dhost, '/');
+ if (!dnetm) {
+ fprintf(stderr,
+ "missing fields (dest netmask)\n");
+ return NULL;
+ }
+ }
+ if (!s || !strcasecmp(s, "portmap")) {
+ dnetm = strrchr(dhost, '/');
+ if (!dnetm) {
+ fprintf(stderr,
+ "missing fields (dest netmask)\n");
+ return NULL;
+ }
+ } else {
+ if (strcasecmp(s, "netmask")) {
+ fprintf(stderr,
+ "missing fields (dest netmask)\n");
+ return NULL;
+ }
+ if (!(s = strtok(NULL, " \t"))) {
+ fprintf(stderr,
+ "missing fields (dest netmask)\n");
+ return NULL;
+ }
+ dnetm = s;
+ }
+ if (*dnetm == '/')
+ *dnetm++ = '\0';
+ } else {
+ /* If it's a in_redir, expect target port */
+ if (!(s = strtok(NULL, " \t"))) {
+ fprintf(stderr, "missing fields (destination port)\n");
+ return NULL;
+ }
+
+ if (strcasecmp(s, "port")) {
+ fprintf(stderr, "missing fields (port)\n");
+ return NULL;
+ }
+
+ if (!(s = strtok(NULL, " \t"))) {
+ fprintf(stderr, "missing fields (destination port)\n");
+ return NULL;
+ }
+ tport = s;
+ }
+
+
+ if (*snetm == '/')
+ *snetm++ = '\0';
+
+ if (ipn.in_redir == NAT_MAP) {
+ ipn.in_inip = hostnum(shost, &resolved);
+ if (resolved == -1)
+ return NULL;
+ ipn.in_inmsk = hostmask(snetm);
+ ipn.in_outip = hostnum(dhost, &resolved);
+ if (resolved == -1)
+ return NULL;
+ ipn.in_outmsk = hostmask(dnetm);
+ } else {
+ ipn.in_inip = hostnum(dhost, &resolved); /* Inside is target */
+ if (resolved == -1)
+ return NULL;
+ ipn.in_inmsk = hostmask("255.255.255.255");
+ ipn.in_outip = hostnum(shost, &resolved);
+ if (resolved == -1)
+ return NULL;
+ ipn.in_outmsk = hostmask(snetm);
+ if (!(s = strtok(NULL, " \t"))) {
+ ipn.in_flags = IPN_TCP; /* XXX- TCP only by default */
+ proto = "tcp";
+ } else {
+ if (!strcasecmp(s, "tcp"))
+ ipn.in_flags = IPN_TCP;
+ else if (!strcasecmp(s, "udp"))
+ ipn.in_flags = IPN_UDP;
+ else if (!strcasecmp(s, "tcp/udp"))
+ ipn.in_flags = IPN_TCPUDP;
+ else if (!strcasecmp(s, "tcpudp"))
+ ipn.in_flags = IPN_TCPUDP;
+ else {
+ fprintf(stderr,
+ "expected protocol - got \"%s\"\n", s);
+ return NULL;
+ }
+ proto = s;
+ if ((s = strtok(NULL, " \t"))) {
+ fprintf(stderr,
+ "extra junk at the end of rdr: %s\n",
+ s);
+ return NULL;
+ }
+ }
+ ipn.in_pmin = portnum(dport, proto); /* dest port */
+ ipn.in_pmax = ipn.in_pmin; /* NECESSARY of removing nats */
+ ipn.in_pnext = portnum(tport, proto); /* target port */
+ s = NULL; /* That's all she wrote! */
+ }
+ if (!s)
+ return &ipn;
+ if (strcasecmp(s, "portmap")) {
+ fprintf(stderr, "expected \"portmap\" - got \"%s\"\n", s);
+ return NULL;
+ }
+ if (!(s = strtok(NULL, " \t")))
+ return NULL;
+ if (!strcasecmp(s, "tcp"))
+ ipn.in_flags = IPN_TCP;
+ else if (!strcasecmp(s, "udp"))
+ ipn.in_flags = IPN_UDP;
+ else if (!strcasecmp(s, "tcpudp"))
+ ipn.in_flags = IPN_TCPUDP;
+ else if (!strcasecmp(s, "tcp/udp"))
+ ipn.in_flags = IPN_TCPUDP;
+ else {
+ fprintf(stderr, "expected protocol name - got \"%s\"\n", s);
+ return NULL;
+ }
+ proto = s;
+ if (!(s = strtok(NULL, " \t"))) {
+ fprintf(stderr, "no port range found\n");
+ return NULL;
+ }
+ if (!(t = strchr(s, ':'))) {
+ fprintf(stderr, "no port range in \"%s\"\n", s);
+ return NULL;
+ }
+ *t++ = '\0';
+ ipn.in_pmin = portnum(s, proto);
+ ipn.in_pmax = portnum(t, proto);
+ return &ipn;
+}
+
+
+void parsefile(fd, file, opts)
+int fd;
+char *file;
+int opts;
+{
+ char line[512], *s;
+ ipnat_t *np;
+ FILE *fp;
+ int linenum = 1;
+
+ if (strcmp(file, "-"))
+ fp = fopen(file, "r");
+ else
+ fp = stdin;
+
+ while (fgets(line, sizeof(line) - 1, fp)) {
+ line[sizeof(line) - 1] = '\0';
+ if ((s = strchr(line, '\n')))
+ *s = '\0';
+ if (!(np = parse(line))) {
+ if (*line)
+ fprintf(stderr, "%d: syntax error in \"%s\"\n",
+ linenum, line);
+ } else if (!(opts & OPT_NODO)) {
+ if ((opts & OPT_VERBOSE) && np)
+ printnat(np, opts & OPT_VERBOSE, NULL);
+ if (opts & OPT_REM) {
+ if (ioctl(fd, SIOCADNAT, np) == -1)
+ perror("ioctl(SIOCADNAT)");
+ } else if (ioctl(fd, SIOCRMNAT, np) == -1)
+ perror("ioctl(SIOCRMNAT)");
+ }
+ linenum++;
+ }
+ fclose(stdin);
+}
+
+
+void flushtable(fd, opts)
+int fd, opts;
+{
+ int n = 0;
+
+ if (opts & OPT_FLUSH) {
+ n = 0;
+ if (!(opts & OPT_NODO) && ioctl(fd, SIOCFLNAT, &n) == -1)
+ perror("ioctl(SIOCFLNAT)");
+ else
+ printf("%d entries flushed from NAT table\n", n);
+ }
+
+ if (opts & OPT_CLEAR) {
+ n = 0;
+ if (!(opts & OPT_NODO) && ioctl(fd, SIOCCNATL, &n) == -1)
+ perror("ioctl(SIOCCNATL)");
+ else
+ printf("%d entries flushed from NAT list\n", n);
+ }
+}
diff --git a/contrib/ipfilter/ipsd/Makefile b/contrib/ipfilter/ipsd/Makefile
new file mode 100644
index 000000000000..eb1986e1c9b2
--- /dev/null
+++ b/contrib/ipfilter/ipsd/Makefile
@@ -0,0 +1,63 @@
+#
+# (C)opyright 1993-1996 by Darren Reed.
+#
+# This code may be freely distributed as long as it retains this notice
+# and is not changed in any way. The author accepts no responsibility
+# for the use of this software. I hate legaleese, don't you ?
+#
+OBJS=ipsd.o
+BINDEST=/usr/local/bin
+SBINDEST=/sbin
+MANDIR=/usr/share/man
+BPF=sbpf.o
+NIT=snit.o
+SUNOS4=
+BSD=
+LINUX=slinux.o
+SUNOS5=dlcommon.o sdlpi.o
+
+CC=gcc
+CFLAGS=-g -I..
+
+all:
+ @echo "Use one of these targets:"
+ @echo " sunos4-nit (standard SunOS 4.1.x)"
+ @echo " sunos4-bpf (SunOS4.1.x with BPF in the kernel)"
+ @echo " bsd-bpf (4.4BSD variant with BPF in the kernel)"
+ @echo " linux (Linux kernels)"
+ @echo " sunos5 (Solaris 2.x)"
+
+.c.o:
+ $(CC) $(CFLAGS) -c $< -o $@
+
+ipsdr: ipsdr.o
+ $(CC) ipsdr.o -o $@ $(LIBS)
+
+bpf sunos4-bpf :
+ make ipsd "OBJS=$(OBJS)" "UNIXOBJS=$(BPF) $(SUNOS4)" "CC=$(CC)" \
+ "CFLAGS=$(CFLAGS)"
+
+nit sunos4 sunos4-nit :
+ make ipsd "OBJS=$(OBJS)" "UNIXOBJS=$(NIT) $(SUNOS4)" "CC=$(CC)" \
+ "CFLAGS=$(CFLAGS)"
+
+sunos5 :
+ make ipsd "OBJS=$(OBJS)" "UNIXOBJS=$(SUNOS5)" "CC=$(CC)" \
+ CFLAGS="$(CFLAGS) -Dsolaris" "LIBS=-lsocket -lnsl"
+
+bsd-bpf :
+ make ipsd "OBJS=$(OBJS)" "UNIXOBJS=$(BPF) $(BSD)" "CC=$(CC)" \
+ "CFLAGS=$(CFLAGS)"
+
+linux :
+ make ipsd "OBJS=$(OBJS)" "UNIXOBJS=$(LINUX)" "CC=$(CC)" \
+ CFLAGS="$(CFLAGS) -I /usr/src/linux"
+
+ipsd: $(OBJS) $(UNIXOBJS)
+ $(CC) $(OBJS) $(UNIXOBJS) -o $@ $(LIBS)
+
+../ipft_sn.o ../ipft_pc.o:
+ (cd ..; make $(@:../%=%))
+
+clean:
+ rm -rf *.o core a.out ipsd ipsdr
diff --git a/contrib/ipfilter/ipsd/README b/contrib/ipfilter/ipsd/README
new file mode 100644
index 000000000000..6746d01d3852
--- /dev/null
+++ b/contrib/ipfilter/ipsd/README
@@ -0,0 +1,32 @@
+
+IP Scan Detetor.
+----------------
+
+This program is designed to be a passive listener for TCP packets sent to
+the host. It does not exercise the promiscous mode of interfaces. For
+routing Unix boxes (and firewalls which route/proxy) this is sufficient to
+detect all packets going to/through them.
+
+Upon compiling, a predefined set of "sensitive" ports are configured into
+the program. Any TCP packets which are seen sent to these ports are counted
+and the IP# of the sending host recorded, along with the time of the first
+packet to that port for that IP#.
+
+After a given number of "hits", it will write the current table of packets
+out to disk. This number defaults to 10,000.
+
+To analyze the information written to disk, a sample program called "ipsdr"
+is used (should but doesn't implement a tree algorithm for storing data)
+which reads all log files it recognises and totals up the number of ports
+each host hit. By default, all ports have the same weighting (1). Another
+group of passes is then made over this table using a netmask of 0xfffffffe,
+grouping all results which fall under the same resulting IP#. This netmask
+is then shrunk back to 0, with a output for each level given. This is aimed
+at detecting port scans done from different hosts on the same subnet (although
+I've not seen this done, if one was trying to do it obscurely...)
+
+Lastly, being passive means that no action is taken to stop port scans being
+done or discourage them.
+
+Darren
+darrenr@cyber.com.au
diff --git a/contrib/ipfilter/ipsd/ip_compat.h b/contrib/ipfilter/ipsd/ip_compat.h
new file mode 100644
index 000000000000..a911fd83c3f3
--- /dev/null
+++ b/contrib/ipfilter/ipsd/ip_compat.h
@@ -0,0 +1,201 @@
+/*
+ * (C)opyright 1995 by Darren Reed.
+ *
+ * This code may be freely distributed as long as it retains this notice
+ * and is not changed in any way. The author accepts no responsibility
+ * for the use of this software. I hate legaleese, don't you ?
+ *
+ * @(#)ip_compat.h 1.1 9/14/95
+ */
+
+/*
+ * These #ifdef's are here mainly for linux, but who knows, they may
+ * not be in other places or maybe one day linux will grow up and some
+ * of these will turn up there too.
+ */
+#ifndef ICMP_UNREACH
+# define ICMP_UNREACH ICMP_DEST_UNREACH
+#endif
+#ifndef ICMP_SOURCEQUENCH
+# define ICMP_SOURCEQUENCH ICMP_SOURCE_QUENCH
+#endif
+#ifndef ICMP_TIMXCEED
+# define ICMP_TIMXCEED ICMP_TIME_EXCEEDED
+#endif
+#ifndef ICMP_PARAMPROB
+# define ICMP_PARAMPROB ICMP_PARAMETERPROB
+#endif
+#ifndef IPVERSION
+# define IPVERSION 4
+#endif
+#ifndef IPOPT_MINOFF
+# define IPOPT_MINOFF 4
+#endif
+#ifndef IPOPT_COPIED
+# define IPOPT_COPIED(x) ((x)&0x80)
+#endif
+#ifndef IPOPT_EOL
+# define IPOPT_EOL 0
+#endif
+#ifndef IPOPT_NOP
+# define IPOPT_NOP 1
+#endif
+#ifndef IP_MF
+# define IP_MF ((u_short)0x2000)
+#endif
+#ifndef ETHERTYPE_IP
+# define ETHERTYPE_IP ((u_short)0x0800)
+#endif
+#ifndef TH_FIN
+# define TH_FIN 0x01
+#endif
+#ifndef TH_SYN
+# define TH_SYN 0x02
+#endif
+#ifndef TH_RST
+# define TH_RST 0x04
+#endif
+#ifndef TH_PUSH
+# define TH_PUSH 0x08
+#endif
+#ifndef TH_ACK
+# define TH_ACK 0x10
+#endif
+#ifndef TH_URG
+# define TH_URG 0x20
+#endif
+#ifndef IPOPT_EOL
+# define IPOPT_EOL 0
+#endif
+#ifndef IPOPT_NOP
+# define IPOPT_NOP 1
+#endif
+#ifndef IPOPT_RR
+# define IPOPT_RR 7
+#endif
+#ifndef IPOPT_TS
+# define IPOPT_TS 68
+#endif
+#ifndef IPOPT_SECURITY
+# define IPOPT_SECURITY 130
+#endif
+#ifndef IPOPT_LSRR
+# define IPOPT_LSRR 131
+#endif
+#ifndef IPOPT_SATID
+# define IPOPT_SATID 136
+#endif
+#ifndef IPOPT_SSRR
+# define IPOPT_SSRR 137
+#endif
+#ifndef IPOPT_SECUR_UNCLASS
+# define IPOPT_SECUR_UNCLASS ((u_short)0x0000)
+#endif
+#ifndef IPOPT_SECUR_CONFID
+# define IPOPT_SECUR_CONFID ((u_short)0xf135)
+#endif
+#ifndef IPOPT_SECUR_EFTO
+# define IPOPT_SECUR_EFTO ((u_short)0x789a)
+#endif
+#ifndef IPOPT_SECUR_MMMM
+# define IPOPT_SECUR_MMMM ((u_short)0xbc4d)
+#endif
+#ifndef IPOPT_SECUR_RESTR
+# define IPOPT_SECUR_RESTR ((u_short)0xaf13)
+#endif
+#ifndef IPOPT_SECUR_SECRET
+# define IPOPT_SECUR_SECRET ((u_short)0xd788)
+#endif
+#ifndef IPOPT_SECUR_TOPSECRET
+# define IPOPT_SECUR_TOPSECRET ((u_short)0x6bc5)
+#endif
+
+#ifdef linux
+# define icmp icmphdr
+# define icmp_type type
+# define icmp_code code
+
+/*
+ * From /usr/include/netinet/ip_var.h
+ * !%@#!$@# linux...
+ */
+struct ipovly {
+ caddr_t ih_next, ih_prev; /* for protocol sequence q's */
+ u_char ih_x1; /* (unused) */
+ u_char ih_pr; /* protocol */
+ short ih_len; /* protocol length */
+ struct in_addr ih_src; /* source internet address */
+ struct in_addr ih_dst; /* destination internet address */
+};
+
+typedef struct {
+ __u16 th_sport;
+ __u16 th_dport;
+ __u32 th_seq;
+ __u32 th_ack;
+# if defined(__i386__) || defined(__MIPSEL__) || defined(__alpha__) ||\
+ defined(vax)
+ __u8 th_res:4;
+ __u8 th_off:4;
+#else
+ __u8 th_off:4;
+ __u8 th_res:4;
+#endif
+ __u8 th_flags;
+ __u16 th_win;
+ __u16 th_sum;
+ __u16 th_urp;
+} tcphdr_t;
+
+typedef struct {
+ __u16 uh_sport;
+ __u16 uh_dport;
+ __s16 uh_ulen;
+ __u16 uh_sum;
+} udphdr_t;
+
+typedef struct {
+# if defined(__i386__) || defined(__MIPSEL__) || defined(__alpha__) ||\
+ defined(vax)
+ __u8 ip_hl:4;
+ __u8 ip_v:4;
+# else
+ __u8 ip_hl:4;
+ __u8 ip_v:4;
+# endif
+ __u8 ip_tos;
+ __u16 ip_len;
+ __u16 ip_id;
+ __u16 ip_off;
+ __u8 ip_ttl;
+ __u8 ip_p;
+ __u16 ip_sum;
+ struct in_addr ip_src;
+ struct in_addr ip_dst;
+} ip_t;
+
+typedef struct {
+ __u8 ether_dhost[6];
+ __u8 ether_shost[6];
+ __u16 ether_type;
+} ether_header_t;
+
+# define bcopy(a,b,c) memmove(b,a,c)
+# define bcmp(a,b,c) memcmp(a,b,c)
+
+# define ifnet device
+
+#else
+
+typedef struct udphdr udphdr_t;
+typedef struct tcphdr tcphdr_t;
+typedef struct ip ip_t;
+typedef struct ether_header ether_header_t;
+
+#endif
+
+#ifdef solaris
+# define bcopy(a,b,c) memmove(b,a,c)
+# define bcmp(a,b,c) memcmp(a,b,c)
+# define bzero(a,b) memset(a,0,b)
+#endif
diff --git a/contrib/ipfilter/ipsd/ipsd.c b/contrib/ipfilter/ipsd/ipsd.c
new file mode 100644
index 000000000000..96364dda483e
--- /dev/null
+++ b/contrib/ipfilter/ipsd/ipsd.c
@@ -0,0 +1,297 @@
+/*
+ * (C)opyright December 1995 Darren Reed.
+ *
+ * This software may be freely distributed as long as it is not altered
+ * in any way and that this messagge always accompanies it.
+ *
+ * The author of this software makes no garuntee about the
+ * performance of this package or its suitability to fulfill any purpose.
+ *
+ */
+#include <stdio.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <netdb.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/tcp.h>
+#include <netinet/udp.h>
+#include <netinet/ip_icmp.h>
+#ifndef linux
+#include <netinet/ip_var.h>
+#include <netinet/tcpip.h>
+#endif
+#include "ip_compat.h"
+#ifdef linux
+#include <linux/sockios.h>
+#include "tcpip.h"
+#endif
+#include "ipsd.h"
+
+#ifndef lint
+static char sccsid[] = "@(#)ipsd.c 1.3 12/3/95 (C)1995 Darren Reed";
+#endif
+
+extern char *optarg;
+extern int optind;
+
+#ifdef linux
+char default_device[] = "eth0";
+#else
+# ifdef sun
+char default_device[] = "le0";
+# else
+# ifdef ultrix
+char default_device[] = "ln0";
+# else
+char default_device[] = "lan0";
+# endif
+# endif
+#endif
+
+#define NPORTS 21
+
+u_short defports[NPORTS] = {
+ 7, 9, 20, 21, 23, 25, 53, 69, 79, 111,
+ 123, 161, 162, 512, 513, 514, 515, 520, 540, 6000, 0
+ };
+
+ipsd_t *iphits[NPORTS];
+int writes = 0;
+
+
+int ipcmp(sh1, sh2)
+sdhit_t *sh1, *sh2;
+{
+ return sh1->sh_ip.s_addr - sh2->sh_ip.s_addr;
+}
+
+
+/*
+ * Check to see if we've already received a packet from this host for this
+ * port.
+ */
+int findhit(ihp, src, dport)
+ipsd_t *ihp;
+struct in_addr src;
+u_short dport;
+{
+ int i, j, k;
+ sdhit_t *sh;
+
+ sh = NULL;
+
+ if (ihp->sd_sz == 4) {
+ for (i = 0, sh = ihp->sd_hit; i < ihp->sd_cnt; i++, sh++)
+ if (src.s_addr == sh->sh_ip.s_addr)
+ return 1;
+ } else {
+ for (i = ihp->sd_cnt / 2, j = (i / 2) - 1; j >= 0; j--) {
+ k = ihp->sd_hit[i].sh_ip.s_addr - src.s_addr;
+ if (!k)
+ return 1;
+ else if (k < 0)
+ i -= j;
+ else
+ i += j;
+ }
+ }
+ return 0;
+}
+
+
+/*
+ * Search for port number amongst the sorted array of targets we're
+ * interested in.
+ */
+int detect(ip, tcp)
+ip_t *ip;
+tcphdr_t *tcp;
+{
+ ipsd_t *ihp;
+ sdhit_t *sh;
+ int i, j, k;
+
+ for (i = 10, j = 4; j >= 0; j--) {
+ k = tcp->th_dport - defports[i];
+ if (!k) {
+ ihp = iphits[i];
+ if (findhit(ihp, ip->ip_src, tcp->th_dport))
+ return 0;
+ sh = ihp->sd_hit + ihp->sd_cnt;
+ sh->sh_date = time(NULL);
+ sh->sh_ip.s_addr = ip->ip_src.s_addr;
+ if (++ihp->sd_cnt == ihp->sd_sz)
+ {
+ ihp->sd_sz += 8;
+ sh = realloc(sh, ihp->sd_sz * sizeof(*sh));
+ ihp->sd_hit = sh;
+ }
+ qsort(sh, ihp->sd_cnt, sizeof(*sh), ipcmp);
+ return 0;
+ }
+ if (k < 0)
+ i -= j;
+ else
+ i += j;
+ }
+ return -1;
+}
+
+
+/*
+ * Allocate initial storage for hosts
+ */
+setuphits()
+{
+ int i;
+
+ for (i = 0; i < NPORTS; i++) {
+ if (iphits[i]) {
+ if (iphits[i]->sd_hit)
+ free(iphits[i]->sd_hit);
+ free(iphits[i]);
+ }
+ iphits[i] = (ipsd_t *)malloc(sizeof(ipsd_t));
+ iphits[i]->sd_port = defports[i];
+ iphits[i]->sd_cnt = 0;
+ iphits[i]->sd_sz = 4;
+ iphits[i]->sd_hit = (sdhit_t *)malloc(sizeof(sdhit_t) * 4);
+ }
+}
+
+
+/*
+ * cleanup exits
+ */
+waiter()
+{
+ wait(0);
+}
+
+
+/*
+ * Write statistics out to a file
+ */
+writestats(nwrites)
+int nwrites;
+{
+ ipsd_t **ipsd, *ips;
+ char fname[32];
+ int i, fd;
+
+ (void) sprintf(fname, "/var/log/ipsd/ipsd-hits.%d", nwrites);
+ fd = open(fname, O_RDWR|O_CREAT|O_TRUNC|O_EXCL, 0644);
+ for (i = 0, ipsd = iphits; i < NPORTS; i++, ipsd++) {
+ ips = *ipsd;
+ if (ips->sd_cnt) {
+ write(fd, ips, sizeof(ipsd_t));
+ write(fd, ips->sd_hit, sizeof(sdhit_t) * ips->sd_sz);
+ }
+ }
+ (void) close(fd);
+ exit(0);
+}
+
+
+void writenow()
+{
+ signal(SIGCHLD, waiter);
+ switch (fork())
+ {
+ case 0 :
+ writestats(writes);
+ exit(0);
+ case -1 :
+ perror("vfork");
+ break;
+ default :
+ writes++;
+ setuphits();
+ break;
+ }
+}
+
+
+void usage(prog)
+char *prog;
+{
+ fprintf(stderr, "Usage: %s [-d device]\n", prog);
+ exit(1);
+}
+
+
+void detecthits(fd, writecount)
+int fd, writecount;
+{
+ struct in_addr ip;
+ int hits = 0;
+
+ while (1) {
+ hits += readloop(fd, ip);
+ if (hits > writecount) {
+ writenow();
+ hits = 0;
+ }
+ }
+}
+
+
+main(argc, argv)
+int argc;
+char *argv[];
+{
+ char c, *name = argv[0], *dev = NULL;
+ int fd, writeafter = 10000, angelic = 0;
+
+ while ((c = getopt(argc, argv, "ad:n:")) != -1)
+ switch (c)
+ {
+ case 'a' :
+ angelic = 1;
+ break;
+ case 'd' :
+ dev = optarg;
+ break;
+ case 'n' :
+ writeafter = atoi(optarg);
+ break;
+ default :
+ fprintf(stderr, "Unknown option \"%c\"\n", c);
+ usage(name);
+ }
+
+ bzero(iphits, sizeof(iphits));
+ setuphits();
+
+ if (!dev)
+ dev = default_device;
+ printf("Device: %s\n", dev);
+ fd = initdevice(dev, 60);
+
+ if (!angelic) {
+ switch (fork())
+ {
+ case 0 :
+ (void) close(0);
+ (void) close(1);
+ (void) close(2);
+ (void) setpgrp(0, getpgrp());
+ (void) setsid();
+ break;
+ case -1:
+ perror("fork");
+ exit(-1);
+ default:
+ exit(0);
+ }
+ }
+ signal(SIGUSR1, writenow);
+ detecthits(fd, writeafter);
+}
diff --git a/contrib/ipfilter/ipsd/ipsd.h b/contrib/ipfilter/ipsd/ipsd.h
new file mode 100644
index 000000000000..a9f3920b4c55
--- /dev/null
+++ b/contrib/ipfilter/ipsd/ipsd.h
@@ -0,0 +1,30 @@
+/*
+ * (C)opyright December 1995 Darren Reed.
+ *
+ * This software may be freely distributed as long as it is not altered
+ * in any way and that this messagge always accompanies it.
+ *
+ * The author of this software makes no garuntee about the
+ * performance of this package or its suitability to fulfill any purpose.
+ *
+ * @(#)ipsd.h 1.3 12/3/95
+ */
+
+typedef struct {
+ time_t sh_date;
+ struct in_addr sh_ip;
+} sdhit_t;
+
+typedef struct {
+ u_int sd_sz;
+ u_int sd_cnt;
+ u_short sd_port;
+ sdhit_t *sd_hit;
+} ipsd_t;
+
+typedef struct {
+ struct in_addr ss_ip;
+ int ss_hits;
+ u_long ss_ports;
+} ipss_t;
+
diff --git a/contrib/ipfilter/ipsd/ipsdr.c b/contrib/ipfilter/ipsd/ipsdr.c
new file mode 100644
index 000000000000..b3bf95765a94
--- /dev/null
+++ b/contrib/ipfilter/ipsd/ipsdr.c
@@ -0,0 +1,315 @@
+/*
+ * (C)opyright December 1995 Darren Reed.
+ *
+ * This software may be freely distributed as long as it is not altered
+ * in any way and that this messagge always accompanies it.
+ *
+ * The author of this software makes no garuntee about the
+ * performance of this package or its suitability to fulfill any purpose.
+ *
+ */
+#include <stdio.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <malloc.h>
+#include <netdb.h>
+#include <string.h>
+#include <sys/dir.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/tcp.h>
+#include <netinet/udp.h>
+#include <netinet/ip_icmp.h>
+#ifndef linux
+#include <netinet/ip_var.h>
+#include <netinet/tcpip.h>
+#endif
+#include "ip_compat.h"
+#ifdef linux
+#include <linux/sockios.h>
+#include "tcpip.h"
+#endif
+#include "ipsd.h"
+
+#ifndef lint
+static char sccsid[] = "@(#)ipsdr.c 1.3 12/3/95 (C)1995 Darren Reed";
+#endif
+
+extern char *optarg;
+extern int optind;
+
+#define NPORTS 21
+
+u_short defports[NPORTS] = {
+ 7, 9, 20, 21, 23, 25, 53, 69, 79, 111,
+ 123, 161, 162, 512, 513, 513, 515, 520, 540, 6000, 0
+ };
+u_short pweights[NPORTS] = {
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+ };
+
+ipsd_t *iphits[NPORTS];
+int pkts;
+
+
+int ipcmp(sh1, sh2)
+sdhit_t *sh1, *sh2;
+{
+ return sh1->sh_ip.s_addr - sh2->sh_ip.s_addr;
+}
+
+
+int ssipcmp(sh1, sh2)
+ipss_t *sh1, *sh2;
+{
+ return sh1->ss_ip.s_addr - sh2->ss_ip.s_addr;
+}
+
+
+int countpbits(num)
+u_long num;
+{
+ int i, j;
+
+ for (i = 1, j = 0; i; i <<= 1)
+ if (num & i)
+ j++;
+ return j;
+}
+
+
+/*
+ * Check to see if we've already received a packet from this host for this
+ * port.
+ */
+int findhit(ihp, src, dport)
+ipsd_t *ihp;
+struct in_addr src;
+u_short dport;
+{
+ int i, j, k;
+ sdhit_t *sh;
+
+ sh = NULL;
+
+ if (ihp->sd_sz == 4) {
+ for (i = 0, sh = ihp->sd_hit; i < ihp->sd_cnt; i++, sh++)
+ if (src.s_addr == sh->sh_ip.s_addr)
+ return 1;
+ } else {
+ for (i = ihp->sd_cnt / 2, j = (i / 2) - 1; j >= 0; j--) {
+ k = ihp->sd_hit[i].sh_ip.s_addr - src.s_addr;
+ if (!k)
+ return 1;
+ else if (k < 0)
+ i -= j;
+ else
+ i += j;
+ }
+ }
+ return 0;
+}
+
+
+/*
+ * Search for port number amongst the sorted array of targets we're
+ * interested in.
+ */
+int detect(srcip, dport, date)
+struct in_addr srcip;
+u_short dport;
+time_t date;
+{
+ ipsd_t *ihp;
+ sdhit_t *sh;
+ int i, j, k;
+
+ for (i = 10, j = 4; j >= 0; j--) {
+ k = dport - defports[i];
+ if (!k) {
+ ihp = iphits[i];
+ if (findhit(ihp, srcip, dport))
+ return 0;
+ sh = ihp->sd_hit + ihp->sd_cnt;
+ sh->sh_date = date;
+ sh->sh_ip = srcip;
+ if (++ihp->sd_cnt == ihp->sd_sz)
+ {
+ ihp->sd_sz += 8;
+ sh = realloc(sh, ihp->sd_sz * sizeof(*sh));
+ ihp->sd_hit = sh;
+ }
+ qsort(sh, ihp->sd_cnt, sizeof(*sh), ipcmp);
+ return 0;
+ }
+ if (k < 0)
+ i -= j;
+ else
+ i += j;
+ }
+ return -1;
+}
+
+
+/*
+ * Allocate initial storage for hosts
+ */
+setuphits()
+{
+ int i;
+
+ for (i = 0; i < NPORTS; i++) {
+ if (iphits[i]) {
+ if (iphits[i]->sd_hit)
+ free(iphits[i]->sd_hit);
+ free(iphits[i]);
+ }
+ iphits[i] = (ipsd_t *)malloc(sizeof(ipsd_t));
+ iphits[i]->sd_port = defports[i];
+ iphits[i]->sd_cnt = 0;
+ iphits[i]->sd_sz = 4;
+ iphits[i]->sd_hit = (sdhit_t *)malloc(sizeof(sdhit_t) * 4);
+ }
+}
+
+
+/*
+ * Write statistics out to a file
+ */
+addfile(file)
+char *file;
+{
+ ipsd_t ipsd, *ips = &ipsd;
+ sdhit_t hit, *hp;
+ char fname[32];
+ int i, fd, sz;
+
+ if ((fd = open(file, O_RDONLY)) == -1) {
+ perror("open");
+ return;
+ }
+
+ printf("opened %s\n", file);
+ do {
+ if (read(fd, ips, sizeof(*ips)) != sizeof(*ips))
+ break;
+ sz = ips->sd_sz * sizeof(*hp);
+ hp = (sdhit_t *)malloc(sz);
+ if (read(fd, hp, sz) != sz)
+ break;
+ for (i = 0; i < ips->sd_cnt; i++)
+ detect(hp[i].sh_ip, ips->sd_port, hp[i].sh_date);
+ } while (1);
+ (void) close(fd);
+}
+
+
+readfiles(dir)
+char *dir;
+{
+ struct direct **d;
+ int i, j;
+
+ d = NULL;
+ i = scandir(dir, &d, NULL, NULL);
+
+ for (j = 0; j < i; j++) {
+ if (strncmp(d[j]->d_name, "ipsd-hits.", 10))
+ continue;
+ addfile(d[j]->d_name);
+ }
+}
+
+
+void printreport(ss, num)
+ipss_t *ss;
+int num;
+{
+ struct in_addr ip;
+ ipss_t *sp;
+ int i, j, mask;
+ u_long ports;
+
+ printf("Hosts detected: %d\n", num);
+ if (!num)
+ return;
+ for (i = 0; i < num; i++)
+ printf("%s %d %d\n", inet_ntoa(ss[i].ss_ip), ss[i].ss_hits,
+ countpbits(ss[i].ss_ports));
+
+ printf("--------------------------\n");
+ for (mask = 0xfffffffe, j = 32; j; j--, mask <<= 1) {
+ ip.s_addr = ss[0].ss_ip.s_addr & mask;
+ ports = ss[0].ss_ports;
+ for (i = 1; i < num; i++) {
+ sp = ss + i;
+ if (ip.s_addr != (sp->ss_ip.s_addr & mask)) {
+ printf("Netmask: 0x%08x\n", mask);
+ printf("%s %d\n", inet_ntoa(ip),
+ countpbits(ports));
+ ip.s_addr = sp->ss_ip.s_addr & mask;
+ ports = 0;
+ }
+ ports |= sp->ss_ports;
+ }
+ if (ports) {
+ printf("Netmask: 0x%08x\n", mask);
+ printf("%s %d\n", inet_ntoa(ip), countpbits(ports));
+ }
+ }
+}
+
+
+collectips()
+{
+ ipsd_t *ips;
+ ipss_t *ss;
+ int i, num, nip, in, j, k;
+
+ for (i = 0; i < NPORTS; i++)
+ nip += iphits[i]->sd_cnt;
+
+ ss = (ipss_t *)malloc(sizeof(ipss_t) * nip);
+
+ for (in = 0, i = 0, num = 0; i < NPORTS; i++) {
+ ips = iphits[i];
+ for (j = 0; j < ips->sd_cnt; j++) {
+ for (k = 0; k < num; k++)
+ if (!bcmp(&ss[k].ss_ip, &ips->sd_hit[j].sh_ip,
+ sizeof(struct in_addr))) {
+ ss[k].ss_hits += pweights[i];
+ ss[k].ss_ports |= (1 << i);
+ break;
+ }
+ if (k == num) {
+ ss[num].ss_ip = ips->sd_hit[j].sh_ip;
+ ss[num].ss_hits = pweights[i];
+ ss[k].ss_ports |= (1 << i);
+ num++;
+ }
+ }
+ }
+
+ qsort(ss, num, sizeof(*ss), ssipcmp);
+
+ printreport(ss, num);
+}
+
+
+main(argc, argv)
+int argc;
+char *argv[];
+{
+ char c, *name = argv[0], *dir = NULL;
+ int fd;
+
+ setuphits();
+ dir = dir ? dir : ".";
+ readfiles(dir);
+ collectips();
+}
diff --git a/contrib/ipfilter/ipsd/linux.h b/contrib/ipfilter/ipsd/linux.h
new file mode 100644
index 000000000000..7eb382b4b7e1
--- /dev/null
+++ b/contrib/ipfilter/ipsd/linux.h
@@ -0,0 +1,17 @@
+/*
+ * (C)opyright 1995 by Darren Reed.
+ *
+ * This code may be freely distributed as long as it retains this notice
+ * and is not changed in any way. The author accepts no responsibility
+ * for the use of this software. I hate legaleese, don't you ?
+ *
+ * @(#)linux.h 1.1 8/19/95
+ */
+
+#include <linux/config.h>
+#ifdef MODULE
+#include <linux/module.h>
+#include <linux/version.h>
+#endif /* MODULE */
+
+#include "ip_compat.h"
diff --git a/contrib/ipfilter/ipsd/sbpf.c b/contrib/ipfilter/ipsd/sbpf.c
new file mode 100644
index 000000000000..d008a5f00d25
--- /dev/null
+++ b/contrib/ipfilter/ipsd/sbpf.c
@@ -0,0 +1,195 @@
+/*
+ * (C)opyright October 1995 Darren Reed. (from tcplog)
+ *
+ * This software may be freely distributed as long as it is not altered
+ * in any way and that this messagge always accompanies it.
+ *
+ */
+#include <stdio.h>
+#include <netdb.h>
+#include <ctype.h>
+#include <signal.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/mbuf.h>
+#include <sys/time.h>
+#include <sys/timeb.h>
+#include <sys/socket.h>
+#include <sys/file.h>
+#include <sys/ioctl.h>
+#if BSD < 199103
+#include <sys/fcntlcom.h>
+#endif
+#include <sys/dir.h>
+#include <net/bpf.h>
+
+#include <net/if.h>
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/if_ether.h>
+#include <netinet/ip_var.h>
+#include <netinet/udp.h>
+#include <netinet/udp_var.h>
+#include <netinet/tcp.h>
+#include <netinet/tcpip.h>
+#include "ip_compat.h"
+
+#ifndef lint
+static char sbpf[] = "@(#)sbpf.c 1.2 12/3/95 (C)1995 Darren Reed";
+#endif
+
+/*
+(000) ldh [12]
+(001) jeq #0x800 jt 2 jf 5
+(002) ldb [23]
+(003) jeq #0x6 jt 4 jf 5
+(004) ret #68
+(005) ret #0
+*/
+struct bpf_insn filter[] = {
+/* 0. */ { BPF_LD|BPF_H|BPF_ABS, 0, 0, 12 },
+/* 1. */ { BPF_JMP|BPF_JEQ, 0, 3, 0x0800 },
+/* 2. */ { BPF_LD|BPF_B|BPF_ABS, 0, 0, 23 },
+/* 3. */ { BPF_JMP|BPF_JEQ, 0, 1, 0x06 },
+/* 4. */ { BPF_RET, 0, 0, 68 },
+/* 5. */ { BPF_RET, 0, 0, 0 }
+};
+/*
+ * the code herein is dervied from libpcap.
+ */
+static u_char *buf = NULL;
+static u_int bufsize = 32768, timeout = 1;
+
+
+int ack_recv(ep)
+char *ep;
+{
+ struct tcpiphdr tip;
+ tcphdr_t *tcp;
+ ip_t *ip;
+
+ ip = (ip_t *)&tip;
+ tcp = (tcphdr_t *)(ip + 1);
+ bcopy(ep + 14, (char *)ip, sizeof(*ip));
+ bcopy(ep + 14 + (ip->ip_hl << 2), (char *)tcp, sizeof(*tcp));
+ if (ip->ip_p != IPPROTO_TCP && ip->ip_p != IPPROTO_UDP)
+ return -1;
+ if (ip->ip_p & 0x1fff != 0)
+ return 0;
+ if (0 == detect(ip, tcp))
+ return 1;
+ return 0;
+}
+
+
+int readloop(fd, port, dst)
+int fd, port;
+struct in_addr dst;
+{
+ register u_char *bp, *cp, *bufend;
+ register struct bpf_hdr *bh;
+ register int cc;
+ time_t in = time(NULL);
+ int done = 0;
+
+ while ((cc = read(fd, buf, bufsize)) >= 0) {
+ if (!cc && (time(NULL) - in) > timeout)
+ return done;
+ bp = buf;
+ bufend = buf + cc;
+ /*
+ * loop through each snapshot in the chunk
+ */
+ while (bp < bufend) {
+ bh = (struct bpf_hdr *)bp;
+ cp = bp + bh->bh_hdrlen;
+ done += ack_recv(cp);
+ bp += BPF_WORDALIGN(bh->bh_caplen + bh->bh_hdrlen);
+ }
+ return done;
+ }
+ perror("read");
+ exit(-1);
+}
+
+int initdevice(device, tout)
+char *device;
+int tout;
+{
+ struct bpf_program prog;
+ struct bpf_version bv;
+ struct timeval to;
+ struct ifreq ifr;
+ char bpfname[16];
+ int fd, i;
+
+ for (i = 0; i < 16; i++)
+ {
+ (void) sprintf(bpfname, "/dev/bpf%d", i);
+ if ((fd = open(bpfname, O_RDWR)) >= 0)
+ break;
+ }
+ if (i == 16)
+ {
+ fprintf(stderr, "no bpf devices available as /dev/bpfxx\n");
+ return -1;
+ }
+
+ if (ioctl(fd, BIOCVERSION, (caddr_t)&bv) < 0)
+ {
+ perror("BIOCVERSION");
+ return -1;
+ }
+ if (bv.bv_major != BPF_MAJOR_VERSION ||
+ bv.bv_minor < BPF_MINOR_VERSION)
+ {
+ fprintf(stderr, "kernel bpf (v%d.%d) filter out of date:\n",
+ bv.bv_major, bv.bv_minor);
+ fprintf(stderr, "current version: %d.%d\n",
+ BPF_MAJOR_VERSION, BPF_MINOR_VERSION);
+ return -1;
+ }
+
+ (void) strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
+ if (ioctl(fd, BIOCSETIF, &ifr) == -1)
+ {
+ fprintf(stderr, "%s(%d):", ifr.ifr_name, fd);
+ perror("BIOCSETIF");
+ exit(1);
+ }
+ /*
+ * set the timeout
+ */
+ timeout = tout;
+ to.tv_sec = 1;
+ to.tv_usec = 0;
+ if (ioctl(fd, BIOCSRTIMEOUT, (caddr_t)&to) == -1)
+ {
+ perror("BIOCSRTIMEOUT");
+ exit(-1);
+ }
+ /*
+ * get kernel buffer size
+ */
+ if (ioctl(fd, BIOCSBLEN, &bufsize) == -1)
+ perror("BIOCSBLEN");
+ if (ioctl(fd, BIOCGBLEN, &bufsize) == -1)
+ {
+ perror("BIOCGBLEN");
+ exit(-1);
+ }
+ printf("BPF buffer size: %d\n", bufsize);
+ buf = (u_char*)malloc(bufsize);
+
+ prog.bf_len = sizeof(filter) / sizeof(struct bpf_insn);
+ prog.bf_insns = filter;
+ if (ioctl(fd, BIOCSETF, (caddr_t)&prog) == -1)
+ {
+ perror("BIOCSETF");
+ exit(-1);
+ }
+ (void) ioctl(fd, BIOCFLUSH, 0);
+ return fd;
+}
diff --git a/contrib/ipfilter/ipsd/sdlpi.c b/contrib/ipfilter/ipsd/sdlpi.c
new file mode 100644
index 000000000000..1d0e41d7f66f
--- /dev/null
+++ b/contrib/ipfilter/ipsd/sdlpi.c
@@ -0,0 +1,263 @@
+/*
+ * (C)opyright October 1992 Darren Reed. (from tcplog)
+ *
+ * This software may be freely distributed as long as it is not altered
+ * in any way and that this messagge always accompanies it.
+ *
+ * The author of this software makes no garuntee about the
+ * performance of this package or its suitability to fulfill any purpose.
+ *
+ */
+
+#include <stdio.h>
+#include <netdb.h>
+#include <ctype.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/timeb.h>
+#include <sys/socket.h>
+#include <sys/file.h>
+#include <sys/ioctl.h>
+#include <sys/stropts.h>
+
+#include <sys/pfmod.h>
+#include <sys/bufmod.h>
+#include <sys/dlpi.h>
+
+#include <net/if.h>
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/if_ether.h>
+#include <netinet/ip_var.h>
+#include <netinet/udp.h>
+#include <netinet/udp_var.h>
+#include <netinet/tcp.h>
+#include <netinet/tcpip.h>
+
+#include "ip_compat.h"
+
+#ifndef lint
+static char snitid[] = "%W% %G% (C)1995 Darren Reed";
+#endif
+
+#define BUFSPACE 32768
+
+static int solfd;
+
+/*
+ * Be careful to only include those defined in the flags option for the
+ * interface are included in the header size.
+ */
+static int timeout;
+
+
+void nullbell()
+{
+ return 0;
+}
+
+
+int ack_recv(ep)
+char *ep;
+{
+ struct tcpiphdr tip;
+ tcphdr_t *tcp;
+ ip_t *ip;
+
+ ip = (ip_t *)&tip;
+ tcp = (tcphdr_t *)(ip + 1);
+ bcopy(ep, (char *)ip, sizeof(*ip));
+ bcopy(ep + (ip->ip_hl << 2), (char *)tcp, sizeof(*tcp));
+
+ if (ip->ip_off & 0x1fff != 0)
+ return 0;
+ if (0 == detect(ip, tcp))
+ return 1;
+ return 0;
+}
+
+
+int readloop(fd, port, dst)
+int fd, port;
+struct in_addr dst;
+{
+ static u_char buf[BUFSPACE];
+ register u_char *bp, *cp, *bufend;
+ register struct sb_hdr *hp;
+ register int cc;
+ struct strbuf dbuf;
+ ether_header_t eh;
+ time_t now = time(NULL);
+ int flags = 0, i, done = 0;
+
+ fd = solfd;
+ dbuf.len = 0;
+ dbuf.buf = buf;
+ dbuf.maxlen = sizeof(buf);
+ /*
+ * no control data buffer...
+ */
+ while (1) {
+ (void) signal(SIGALRM, nullbell);
+ alarm(1);
+ i = getmsg(fd, NULL, &dbuf, &flags);
+ alarm(0);
+ (void) signal(SIGALRM, nullbell);
+
+ cc = dbuf.len;
+ if ((time(NULL) - now) > timeout)
+ return done;
+ if (i == -1)
+ if (errno == EINTR)
+ continue;
+ else
+ break;
+ bp = buf;
+ bufend = buf + cc;
+ /*
+ * loop through each snapshot in the chunk
+ */
+ while (bp < bufend) {
+ /*
+ * get past bufmod header
+ */
+ hp = (struct sb_hdr *)bp;
+ cp = (u_char *)((char *)bp + sizeof(*hp));
+ bcopy(cp, (char *)&eh, sizeof(eh));
+ /*
+ * next snapshot
+ */
+ bp += hp->sbh_totlen;
+ cc -= hp->sbh_totlen;
+
+ if (eh.ether_type != ETHERTYPE_IP)
+ continue;
+
+ cp += sizeof(eh);
+ done += ack_recv(cp);
+ }
+ alarm(1);
+ }
+ perror("getmsg");
+ exit(-1);
+}
+
+int initdevice(device, tout)
+char *device;
+int tout;
+{
+ struct strioctl si;
+ struct timeval to;
+ struct ifreq ifr;
+ struct packetfilt pfil;
+ u_long if_flags;
+ u_short *fwp = pfil.Pf_Filter;
+ char devname[16], *s, buf[256];
+ int i, offset, fd, snaplen= 58, chunksize = BUFSPACE;
+
+ (void) sprintf(devname, "/dev/%s", device);
+
+ s = devname + 5;
+ while (*s && !isdigit(*s))
+ s++;
+ if (!*s)
+ {
+ fprintf(stderr, "bad device name %s\n", devname);
+ exit(-1);
+ }
+ i = atoi(s);
+ *s = '\0';
+ /*
+ * For reading
+ */
+ if ((fd = open(devname, O_RDWR)) < 0)
+ {
+ fprintf(stderr, "O_RDWR(0) ");
+ perror(devname);
+ exit(-1);
+ }
+ if (dlattachreq(fd, i) == -1 || dlokack(fd, buf) == -1)
+ {
+ fprintf(stderr, "DLPI error\n");
+ exit(-1);
+ }
+ dlbindreq(fd, ETHERTYPE_IP, 0, DL_CLDLS, 0, 0);
+ dlbindack(fd, buf);
+ /*
+ * read full headers
+ */
+ if (strioctl(fd, DLIOCRAW, -1, 0, NULL) == -1)
+ {
+ fprintf(stderr, "DLIOCRAW error\n");
+ exit(-1);
+ }
+ /*
+ * Create some filter rules for our TCP watcher. We only want ethernet
+ * pacets which are IP protocol and only the TCP packets from IP.
+ */
+ offset = 6;
+ *fwp++ = ENF_PUSHWORD + offset;
+ *fwp++ = ENF_PUSHLIT | ENF_CAND;
+ *fwp++ = htons(ETHERTYPE_IP);
+ *fwp++ = ENF_PUSHWORD + sizeof(struct ether_header)/sizeof(short)+4;
+ *fwp++ = ENF_PUSHLIT | ENF_AND;
+ *fwp++ = htons(0x00ff);
+ *fwp++ = ENF_PUSHLIT | ENF_COR;
+ *fwp++ = htons(IPPROTO_TCP);
+ *fwp++ = ENF_PUSHWORD + sizeof(struct ether_header)/sizeof(short)+4;
+ *fwp++ = ENF_PUSHLIT | ENF_AND;
+ *fwp++ = htons(0x00ff);
+ *fwp++ = ENF_PUSHLIT | ENF_CAND;
+ *fwp++ = htons(IPPROTO_UDP);
+ pfil.Pf_FilterLen = (fwp - &pfil.Pf_Filter[0]);
+ /*
+ * put filter in place.
+ */
+
+ if (ioctl(fd, I_PUSH, "pfmod") == -1)
+ {
+ perror("ioctl: I_PUSH pf");
+ exit(1);
+ }
+ if (strioctl(fd, PFIOCSETF, -1, sizeof(pfil), (char *)&pfil) == -1)
+ {
+ perror("ioctl: PFIOCSETF");
+ exit(1);
+ }
+
+ /*
+ * arrange to get messages from the NIT STREAM and use NIT_BUF option
+ */
+ if (ioctl(fd, I_PUSH, "bufmod") == -1)
+ {
+ perror("ioctl: I_PUSH bufmod");
+ exit(1);
+ }
+ i = 128;
+ strioctl(fd, SBIOCSSNAP, -1, sizeof(i), (char *)&i);
+ /*
+ * set the timeout
+ */
+ to.tv_sec = 1;
+ to.tv_usec = 0;
+ if (strioctl(fd, SBIOCSTIME, -1, sizeof(to), (char *)&to) == -1)
+ {
+ perror("strioctl(SBIOCSTIME)");
+ exit(-1);
+ }
+ /*
+ * flush read queue
+ */
+ if (ioctl(fd, I_FLUSH, FLUSHR) == -1)
+ {
+ perror("I_FLUSHR");
+ exit(-1);
+ }
+ timeout = tout;
+ solfd = fd;
+ return fd;
+}
diff --git a/contrib/ipfilter/ipsd/slinux.c b/contrib/ipfilter/ipsd/slinux.c
new file mode 100644
index 000000000000..1115b86954ec
--- /dev/null
+++ b/contrib/ipfilter/ipsd/slinux.c
@@ -0,0 +1,120 @@
+/*
+ * (C)opyright October 1992 Darren Reed. (from tcplog)
+ *
+ * This software may be freely distributed as long as it is not altered
+ * in any way and that this messagge always accompanies it.
+ *
+ * The author of this software makes no garuntee about the
+ * performance of this package or its suitability to fulfill any purpose.
+ *
+ */
+
+#include <stdio.h>
+#include <netdb.h>
+#include <ctype.h>
+#include <signal.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/timeb.h>
+#include <sys/socket.h>
+#include <sys/file.h>
+#include <sys/ioctl.h>
+#include <sys/dir.h>
+#include <linux/netdevice.h>
+#include <net/if.h>
+#include <netinet/in.h>
+#include <netinet/ip.h>
+#include <netinet/tcp.h>
+#include "ip_compat.h"
+#include "tcpip.h"
+
+#ifndef lint
+static char sccsid[] = "@(#)slinux.c 1.1 12/3/95 (C) 1995 Darren Reed";
+#endif
+
+#define BUFSPACE 32768
+
+/*
+ * Be careful to only include those defined in the flags option for the
+ * interface are included in the header size.
+ */
+
+static int timeout;
+static char *eth_dev = NULL;
+
+
+int ack_recv(bp)
+char *bp;
+{
+ struct tcpip tip;
+ tcphdr_t *tcp;
+ ip_t *ip;
+
+ ip = (struct ip *)&tip;
+ tcp = (tcphdr_t *)(ip + 1);
+
+ bcopy(bp, (char *)&tip, sizeof(tip));
+ bcopy(bp + (ip.ip_hl << 2), (char *)tcp, sizeof(*tcp));
+ if (0 == detect(ip, tcp))
+ return 1;
+ return 0;
+}
+
+
+void readloop(fd, port, dst)
+int fd, port;
+struct in_addr dst;
+{
+ static u_char buf[BUFSPACE];
+ struct sockaddr dest;
+ register u_char *bp = buf;
+ register int cc;
+ int dlen, done = 0;
+ time_t now = time(NULL);
+
+ do {
+ fflush(stdout);
+ dlen = sizeof(dest);
+ bzero((char *)&dest, dlen);
+ cc = recvfrom(fd, buf, BUFSPACE, 0, &dest, &dlen);
+ if (!cc)
+ if ((time(NULL) - now) > timeout)
+ return done;
+ else
+ continue;
+
+ if (bp[12] != 0x8 || bp[13] != 0)
+ continue; /* not ip */
+
+ /*
+ * get rid of non-tcp or fragmented packets here.
+ */
+ if (cc >= sizeof(struct tcpiphdr))
+ {
+ if (((bp[14+9] != IPPROTO_TCP) &&
+ (bp[14+9] != IPPROTO_UDP)) ||
+ (bp[14+6] & 0x1f) || (bp[14+6] & 0xff))
+ continue;
+ done += ack_recv(bp + 14);
+ }
+ } while (cc >= 0);
+ perror("read");
+ exit(-1);
+}
+
+int initdevice(dev, tout)
+char *dev;
+int tout;
+{
+ int fd;
+
+ eth_dev = strdup(dev);
+ if ((fd = socket(AF_INET, SOCK_PACKET, htons(ETHERTYPE_IP))) == -1)
+ {
+ perror("socket(SOCK_PACKET)");
+ exit(-1);
+ }
+
+ return fd;
+}
diff --git a/contrib/ipfilter/ipsd/snit.c b/contrib/ipfilter/ipsd/snit.c
new file mode 100644
index 000000000000..4b5fd0346b2a
--- /dev/null
+++ b/contrib/ipfilter/ipsd/snit.c
@@ -0,0 +1,230 @@
+/*
+ * (C)opyright October 1992 Darren Reed. (from tcplog)
+ *
+ * This software may be freely distributed as long as it is not altered
+ * in any way and that this messagge always accompanies it.
+ *
+ * The author of this software makes no garuntee about the
+ * performance of this package or its suitability to fulfill any purpose.
+ *
+ */
+
+#include <stdio.h>
+#include <netdb.h>
+#include <ctype.h>
+#include <signal.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/timeb.h>
+#include <sys/socket.h>
+#include <sys/file.h>
+#include <sys/ioctl.h>
+#include <net/nit.h>
+#include <sys/fcntlcom.h>
+#include <sys/dir.h>
+#include <net/nit_if.h>
+#include <net/nit_pf.h>
+#include <net/nit_buf.h>
+#include <net/packetfilt.h>
+#include <sys/stropts.h>
+
+#include <net/if.h>
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/if_ether.h>
+#include <netinet/ip_var.h>
+#include <netinet/udp.h>
+#include <netinet/udp_var.h>
+#include <netinet/tcp.h>
+#include <netinet/tcpip.h>
+
+#ifndef lint
+static char snitid[] = "@(#)snit.c 1.2 12/3/95 (C)1995 Darren Reed";
+#endif
+
+#define BUFSPACE 32768
+
+/*
+ * Be careful to only include those defined in the flags option for the
+ * interface are included in the header size.
+ */
+#define BUFHDR_SIZE (sizeof(struct nit_bufhdr))
+#define NIT_HDRSIZE (BUFHDR_SIZE)
+
+static int timeout;
+
+
+int ack_recv(ep)
+char *ep;
+{
+ struct tcpiphdr tip;
+ struct tcphdr *tcp;
+ struct ip *ip;
+
+ ip = (struct ip *)&tip;
+ tcp = (struct tcphdr *)(ip + 1);
+ bcopy(ep + 14, (char *)ip, sizeof(*ip));
+ bcopy(ep + 14 + (ip->ip_hl << 2), (char *)tcp, sizeof(*tcp));
+ if (ip->ip_off & 0x1fff != 0)
+ return 0;
+ if (0 == detect(ip, tcp))
+ return 1;
+ return 0;
+}
+
+
+int readloop(fd, dst)
+int fd;
+struct in_addr dst;
+{
+ static u_char buf[BUFSPACE];
+ register u_char *bp, *cp, *bufend;
+ register struct nit_bufhdr *hp;
+ register int cc;
+ time_t now = time(NULL);
+ int done = 0;
+
+ while ((cc = read(fd, buf, BUFSPACE-1)) >= 0) {
+ if (!cc)
+ if ((time(NULL) - now) > timeout)
+ return done;
+ else
+ continue;
+ bp = buf;
+ bufend = buf + cc;
+ /*
+ * loop through each snapshot in the chunk
+ */
+ while (bp < bufend) {
+ cp = (u_char *)((char *)bp + NIT_HDRSIZE);
+ /*
+ * get past NIT buffer
+ */
+ hp = (struct nit_bufhdr *)bp;
+ /*
+ * next snapshot
+ */
+ bp += hp->nhb_totlen;
+ done += ack_recv(cp);
+ }
+ return done;
+ }
+ perror("read");
+ exit(-1);
+}
+
+int initdevice(device, tout)
+char *device;
+int tout;
+{
+ struct strioctl si;
+ struct timeval to;
+ struct ifreq ifr;
+ struct packetfilt pfil;
+ u_long if_flags;
+ u_short *fwp = pfil.Pf_Filter;
+ int ret, offset, fd, snaplen= 76, chunksize = BUFSPACE;
+
+ if ((fd = open("/dev/nit", O_RDWR)) < 0)
+ {
+ perror("/dev/nit");
+ exit(-1);
+ }
+
+ /*
+ * Create some filter rules for our TCP watcher. We only want ethernet
+ * pacets which are IP protocol and only the TCP packets from IP.
+ */
+ offset = 6;
+ *fwp++ = ENF_PUSHWORD + offset;
+ *fwp++ = ENF_PUSHLIT | ENF_CAND;
+ *fwp++ = htons(ETHERTYPE_IP);
+ *fwp++ = ENF_PUSHWORD + sizeof(struct ether_header)/sizeof(short)+4;
+ *fwp++ = ENF_PUSHLIT | ENF_AND;
+ *fwp++ = htons(0x00ff);
+ *fwp++ = ENF_PUSHLIT | ENF_COR;
+ *fwp++ = htons(IPPROTO_TCP);
+ *fwp++ = ENF_PUSHWORD + sizeof(struct ether_header)/sizeof(short)+4;
+ *fwp++ = ENF_PUSHLIT | ENF_AND;
+ *fwp++ = htons(0x00ff);
+ *fwp++ = ENF_PUSHLIT | ENF_CAND;
+ *fwp++ = htons(IPPROTO_UDP);
+ pfil.Pf_FilterLen = fwp - &pfil.Pf_Filter[0];
+ /*
+ * put filter in place.
+ */
+ if (ioctl(fd, I_PUSH, "pf") == -1)
+ {
+ perror("ioctl: I_PUSH pf");
+ exit(1);
+ }
+ if (ioctl(fd, NIOCSETF, &pfil) == -1)
+ {
+ perror("ioctl: NIOCSETF");
+ exit(1);
+ }
+ /*
+ * arrange to get messages from the NIT STREAM and use NIT_BUF option
+ */
+ ioctl(fd, I_SRDOPT, (char*)RMSGD);
+ ioctl(fd, I_PUSH, "nbuf");
+ /*
+ * set the timeout
+ */
+ timeout = tout;
+ si.ic_timout = 1;
+ to.tv_sec = 1;
+ to.tv_usec = 0;
+ si.ic_cmd = NIOCSTIME;
+ si.ic_len = sizeof(to);
+ si.ic_dp = (char*)&to;
+ if (ioctl(fd, I_STR, (char*)&si) == -1)
+ {
+ perror("ioctl: NIT timeout");
+ exit(-1);
+ }
+ /*
+ * set the chunksize
+ */
+ si.ic_cmd = NIOCSCHUNK;
+ si.ic_len = sizeof(chunksize);
+ si.ic_dp = (char*)&chunksize;
+ if (ioctl(fd, I_STR, (char*)&si) == -1)
+ perror("ioctl: NIT chunksize");
+ if (ioctl(fd, NIOCGCHUNK, (char*)&chunksize) == -1)
+ {
+ perror("ioctl: NIT chunksize");
+ exit(-1);
+ }
+ printf("NIT buffer size: %d\n", chunksize);
+
+ /*
+ * request the interface
+ */
+ strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
+ ifr.ifr_name[sizeof(ifr.ifr_name) - 1] = ' ';
+ si.ic_cmd = NIOCBIND;
+ si.ic_len = sizeof(ifr);
+ si.ic_dp = (char*)&ifr;
+ if (ioctl(fd, I_STR, (char*)&si) == -1)
+ {
+ perror(ifr.ifr_name);
+ exit(1);
+ }
+
+ /*
+ * set the snapshot length
+ */
+ si.ic_cmd = NIOCSSNAP;
+ si.ic_len = sizeof(snaplen);
+ si.ic_dp = (char*)&snaplen;
+ if (ioctl(fd, I_STR, (char*)&si) == -1)
+ {
+ perror("ioctl: NIT snaplen");
+ exit(1);
+ }
+ (void) ioctl(fd, I_FLUSH, (char*)FLUSHR);
+ return fd;
+}
diff --git a/contrib/ipfilter/ipsend/44arp.c b/contrib/ipfilter/ipsend/44arp.c
new file mode 100644
index 000000000000..621d84c86d5b
--- /dev/null
+++ b/contrib/ipfilter/ipsend/44arp.c
@@ -0,0 +1,95 @@
+/*
+ * Based upon 4.4BSD's /usr/sbin/arp
+ */
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sys/param.h>
+#include <sys/file.h>
+#include <sys/socket.h>
+#include <sys/sysctl.h>
+#include <net/if.h>
+#include <net/if_dl.h>
+#include <net/if_types.h>
+#include <net/route.h>
+#include <netinet/in.h>
+#include <netinet/if_ether.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <errno.h>
+#include <nlist.h>
+#include <stdio.h>
+
+/*
+ * lookup host and return
+ * its IP address in address
+ * (4 bytes)
+ */
+int resolve(host, address)
+char *host, *address;
+{
+ struct hostent *hp;
+ u_long add;
+
+ add = inet_addr(host);
+ if (add == -1)
+ {
+ if (!(hp = gethostbyname(host)))
+ {
+ fprintf(stderr, "unknown host: %s\n", host);
+ return -1;
+ }
+ bcopy((char *)hp->h_addr, (char *)address, 4);
+ return 0;
+ }
+ bcopy((char*)&add, address, 4);
+ return 0;
+}
+
+
+int arp(addr, eaddr)
+char *addr, *eaddr;
+{
+ int mib[6];
+ size_t needed;
+ char *malloc(), *lim, *buf, *next;
+ struct rt_msghdr *rtm;
+ struct sockaddr_inarp *sin;
+ struct sockaddr_dl *sdl;
+
+ mib[0] = CTL_NET;
+ mib[1] = PF_ROUTE;
+ mib[2] = 0;
+ mib[3] = AF_INET;
+ mib[4] = NET_RT_FLAGS;
+ mib[5] = RTF_LLINFO;
+ if (sysctl(mib, 6, NULL, &needed, NULL, 0) == -1)
+ {
+ perror("route-sysctl-estimate");
+ exit(-1);
+ }
+ if ((buf = malloc(needed)) == NULL)
+ {
+ perror("malloc");
+ exit(-1);
+ }
+ if (sysctl(mib, 6, buf, &needed, NULL, 0) == -1)
+ {
+ perror("actual retrieval of routing table");
+ exit(-1);
+ }
+ lim = buf + needed;
+ for (next = buf; next < lim; next += rtm->rtm_msglen)
+ {
+ rtm = (struct rt_msghdr *)next;
+ sin = (struct sockaddr_inarp *)(rtm + 1);
+ sdl = (struct sockaddr_dl *)(sin + 1);
+ if (addr && !bcmp(addr, (char *)&sin->sin_addr,
+ sizeof(struct in_addr)))
+ {
+ bcopy(LLADDR(sdl), eaddr, sdl->sdl_alen);
+ return 0;
+ }
+ }
+ return -1;
+}
diff --git a/contrib/ipfilter/ipsend/Crashable b/contrib/ipfilter/ipsend/Crashable
new file mode 100644
index 000000000000..dbe1b87c1174
--- /dev/null
+++ b/contrib/ipfilter/ipsend/Crashable
@@ -0,0 +1,20 @@
+Test 1:
+ Solaris 2.4 - upto and including 101945-34, > 34 ?
+ Solaris 2.5 - 11/95
+ Linux 1.2.13, < 1.3.45(?)
+ 3com/sonix bridge
+ Instant Internet
+ KA9Q NOS
+ Netblazer 40i, Version 3.2 OS
+ Irix 6.x
+ HP-UX 9.0
+ HP-UX 10.1
+ LivingstonsComOS
+
+Test 6:
+ SunOS 4.1.x
+ ULtrix 4.3
+
+Test 7:
+ SunOS 4.1.x
+ Linux <= 1.3.84
diff --git a/contrib/ipfilter/ipsend/Makefile b/contrib/ipfilter/ipsend/Makefile
new file mode 100644
index 000000000000..1f049125c307
--- /dev/null
+++ b/contrib/ipfilter/ipsend/Makefile
@@ -0,0 +1,91 @@
+#
+# (C)opyright 1993-1996 by Darren Reed.
+#
+# This code may be freely distributed as long as it retains this notice
+# and is not changed in any way. The author accepts no responsibility
+# for the use of this software. I hate legaleese, don't you ?
+#
+OBJS=ipsend.o ip.o ipsopt.o
+ROBJS=ipresend.o ip.o resend.o
+TOBJS=iptest.o iptests.o ip.o
+BPF=sbpf.o
+NIT=snit.o
+SUNOS4=sock.o arp.o
+BSD=sock.o 44arp.o
+LINUX=lsock.o slinux.o larp.o
+LINUXK=
+TOP=..
+SUNOS5=dlcommon.o sdlpi.o arp.o
+
+CC=gcc
+CFLAGS=-g -I.. -DNO_IPF
+
+all:
+ @echo "Use one of these targets:"
+ @echo " sunos4-nit (standard SunOS 4.1.x)"
+ @echo " sunos4-bpf (SunOS4.1.x with BPF in the kernel)"
+ @echo " bsd-bpf (4.4BSD variant with BPF in the kernel)"
+ @echo " linux10 (Linux 1.0 kernels)"
+ @echo " linux20 (Linux 2.0 kernels)"
+ @echo " sunos5 (Solaris 2.x)"
+
+.c.o:
+ $(CC) $(CFLAGS) $(LINUXK) -c $< -o $@
+
+bpf sunos4-bpf :
+ make ipsend "OBJS=$(OBJS)" "UNIXOBJS=$(BPF) $(SUNOS4)" "CC=$(CC)" \
+ "CFLAGS=$(CFLAGS) -DDOSOCKET"
+ make ipresend "ROBJS=$(ROBJS)" "UNIXOBJS=$(BPF) $(SUNOS4)" "CC=$(CC)" \
+ "CFLAGS=$(CFLAGS) -DDOSOCKET"
+ make iptest "TOBJS=$(TOBJS)" "UNIXOBJS=$(BPF) $(SUNOS4)" "CC=$(CC)" \
+ "CFLAGS=$(CFLAGS) -DDOSOCKET"
+
+nit sunos4 sunos4-nit :
+ make ipsend "OBJS=$(OBJS)" "UNIXOBJS=$(NIT) $(SUNOS4)" "CC=$(CC)" \
+ "CFLAGS=$(CFLAGS) -DDOSOCKET"
+ make ipresend "ROBJS=$(ROBJS)" "UNIXOBJS=$(NIT) $(SUNOS4)" "CC=$(CC)" \
+ "CFLAGS=$(CFLAGS) -DDOSOCKET"
+ make iptest "TOBJS=$(TOBJS)" "UNIXOBJS=$(NIT) $(SUNOS4)" "CC=$(CC)" \
+ "CFLAGS=$(CFLAGS) -DDOSOCKET"
+
+dlpi sunos5 :
+ make ipsend "OBJS=$(OBJS)" "UNIXOBJS=$(SUNOS5)" "CC=$(CC)" \
+ CFLAGS="$(CFLAGS) -Dsolaris" "LIBS=-lsocket -lnsl"
+ make ipresend "ROBJS=$(ROBJS)" "UNIXOBJS=$(SUNOS5)" "CC=$(CC)" \
+ CFLAGS="$(CFLAGS) -Dsolaris" "LIBS=-lsocket -lnsl"
+ make iptest "TOBJS=$(TOBJS)" "UNIXOBJS=$(SUNOS5)" "CC=$(CC)" \
+ CFLAGS="$(CFLAGS) -Dsolaris" "LIBS=-lsocket -lnsl"
+
+bsd-bpf :
+ make ipsend "OBJS=$(OBJS)" "UNIXOBJS=$(BPF) $(BSD)" "CC=$(CC)" \
+ "CFLAGS=$(CFLAGS) -DDOSOCKET"
+ make ipresend "ROBJS=$(ROBJS)" "UNIXOBJS=$(BPF) $(BSD)" "CC=$(CC)" \
+ "CFLAGS=$(CFLAGS) -DDOSOCKET"
+ make iptest "TOBJS=$(TOBJS)" "UNIXOBJS=$(BPF) $(BSD)" "CC=$(CC)" \
+ "CFLAGS=$(CFLAGS) -DDOSOCKET"
+
+linuxrev :
+ make ipsend "OBJS=$(OBJS)" "UNIXOBJS=$(LINUX)" "CC=$(CC)" \
+ CFLAGS="$(CFLAGS) -I/usr/src/linux/include -DDOSOCKET" $(LINUXK)
+ make ipresend "ROBJS=$(ROBJS)" "UNIXOBJS=$(LINUX)" "CC=$(CC)" \
+ CFLAGS="$(CFLAGS) -I/usr/src/linux/include -DDOSOCKET" $(LINUXK)
+ make iptest "TOBJS=$(TOBJS)" "UNIXOBJS=$(LINUX)" "CC=$(CC)" \
+ CFLAGS="$(CFLAGS) -I/usr/src/linux/include -DDOSOCKET" $(LINUXK)
+
+linux10:
+ make linuxrev 'LINUXK="LINUXK=-DLINUX=0100"'
+
+linux20:
+ make linuxrev 'LINUXK="LINUXK=-DLINUX=0200"'
+
+ipsend: $(OBJS) $(UNIXOBJS)
+ $(CC) $(OBJS) $(UNIXOBJS) -o $@ $(LIBS)
+
+ipresend: $(ROBJS) $(UNIXOBJS)
+ $(CC) $(ROBJS) $(UNIXOBJS) -o $@ $(LIBS)
+
+iptest: $(TOBJS) $(UNIXOBJS)
+ $(CC) $(TOBJS) $(UNIXOBJS) -o $@ $(LIBS)
+
+clean:
+ rm -rf *.o *core a.out ipsend ipresend iptest
diff --git a/contrib/ipfilter/ipsend/arp.c b/contrib/ipfilter/ipsend/arp.c
new file mode 100644
index 000000000000..47f6fce3e397
--- /dev/null
+++ b/contrib/ipfilter/ipsend/arp.c
@@ -0,0 +1,119 @@
+/*
+ * arp.c (C) 1995 Darren Reed
+ *
+ * The author provides this program as-is, with no gaurantee for its
+ * suitability for any specific purpose. The author takes no responsibility
+ * for the misuse/abuse of this program and provides it for the sole purpose
+ * of testing packet filter policies. This file maybe distributed freely
+ * providing it is not modified and that this notice remains in tact.
+ */
+#if !defined(lint) && defined(LIBC_SCCS)
+static char sccsid[] = "@(#)arp.c 1.4 1/11/96 (C)1995 Darren Reed";
+#endif
+#include <stdio.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/sockio.h>
+#include <sys/ioctl.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#include <net/if.h>
+#include <net/if_arp.h>
+
+#if defined(__SVR4) || defined(__svr4__)
+#define bcopy(a,b,c) memmove(b,a,c)
+#define bzero(a,c) memset(a,0,c)
+#define bcmp(a,b,c) memcmp(a,b,c)
+#endif
+
+/*
+ * lookup host and return
+ * its IP address in address
+ * (4 bytes)
+ */
+int resolve(host, address)
+char *host, *address;
+{
+ struct hostent *hp;
+ u_long add;
+
+ add = inet_addr(host);
+ if (add == -1)
+ {
+ if (!(hp = gethostbyname(host)))
+ {
+ fprintf(stderr, "unknown host: %s\n", host);
+ return -1;
+ }
+ bcopy((char *)hp->h_addr, (char *)address, 4);
+ return 0;
+ }
+ bcopy((char*)&add, address, 4);
+ return 0;
+}
+
+/*
+ * ARP for the MAC address corresponding
+ * to the IP address. This taken from
+ * some BSD program, I cant remember which.
+ */
+int arp(ip, ether)
+char *ip;
+char *ether;
+{
+ static int sfd = -1;
+ static char ethersave[6], ipsave[4];
+ struct arpreq ar;
+ struct sockaddr_in *sin, san;
+ struct hostent *hp;
+ char *inet_ntoa();
+ int fd;
+
+ if (!bcmp(ipsave, ip, 4)) {
+ bcopy(ethersave, ether, 6);
+ return 0;
+ }
+ fd = -1;
+ bzero((char *)&ar, sizeof(ar));
+ sin = (struct sockaddr_in *)&ar.arp_pa;
+ sin->sin_family = AF_INET;
+ bcopy(ip, (char *)&sin->sin_addr.s_addr, 4);
+ if ((hp = gethostbyaddr(ip, 4, AF_INET)))
+ if (!(ether_hostton(hp->h_name, ether)))
+ goto savearp;
+
+ if (sfd == -1)
+ if ((sfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
+ {
+ perror("arp: socket");
+ return -1;
+ }
+tryagain:
+ if (ioctl(sfd, SIOCGARP, (caddr_t)&ar) == -1)
+ {
+ if (fd == -1)
+ {
+ bzero((char *)&san, sizeof(san));
+ san.sin_family = AF_INET;
+ san.sin_port = htons(1);
+ bcopy(ip, &san.sin_addr.s_addr, 4);
+ fd = socket(AF_INET, SOCK_DGRAM, 0);
+ (void) sendto(fd, ip, 4, 0,
+ (struct sockaddr *)&san, sizeof(san));
+ sleep(1);
+ (void) close(fd);
+ goto tryagain;
+ }
+ fprintf(stderr, "(%s):", inet_ntoa(sin->sin_addr));
+ if (errno != ENXIO)
+ perror("SIOCGARP");
+ return -1;
+ }
+
+ bcopy(ar.arp_ha.sa_data, ether, 6);
+savearp:
+ bcopy(ether, ethersave, 6);
+ bcopy(ip, ipsave, 4);
+ return 0;
+}
diff --git a/contrib/ipfilter/ipsend/dlcommon.c b/contrib/ipfilter/ipsend/dlcommon.c
new file mode 100644
index 000000000000..59b283d2b82f
--- /dev/null
+++ b/contrib/ipfilter/ipsend/dlcommon.c
@@ -0,0 +1,1359 @@
+/*
+ * Common (shared) DLPI test routines.
+ * Mostly pretty boring boilerplate sorta stuff.
+ * These can be split into individual library routines later
+ * but it's just convenient to keep them in a single file
+ * while they're being developed.
+ *
+ * Not supported:
+ * Connection Oriented stuff
+ * QOS stuff
+ */
+
+/*
+typedef unsigned long ulong;
+*/
+
+
+#include <sys/types.h>
+#include <sys/stream.h>
+#include <sys/stropts.h>
+#include <sys/dlpi.h>
+#include <sys/signal.h>
+#include <stdio.h>
+#include <string.h>
+#include "dltest.h"
+
+#define CASERET(s) case s: return ("s")
+
+char *dlprim();
+char *dlstate();
+char *dlerrno();
+char *dlpromisclevel();
+char *dlservicemode();
+char *dlstyle();
+char *dlmactype();
+
+
+dlinforeq(fd)
+int fd;
+{
+ dl_info_req_t info_req;
+ struct strbuf ctl;
+ int flags;
+
+ info_req.dl_primitive = DL_INFO_REQ;
+
+ ctl.maxlen = 0;
+ ctl.len = sizeof (info_req);
+ ctl.buf = (char *) &info_req;
+
+ flags = RS_HIPRI;
+
+ if (putmsg(fd, &ctl, (struct strbuf*) NULL, flags) < 0)
+ syserr("dlinforeq: putmsg");
+}
+
+dlinfoack(fd, bufp)
+int fd;
+char *bufp;
+{
+ union DL_primitives *dlp;
+ struct strbuf ctl;
+ int flags;
+
+ ctl.maxlen = MAXDLBUF;
+ ctl.len = 0;
+ ctl.buf = bufp;
+
+ strgetmsg(fd, &ctl, (struct strbuf*)NULL, &flags, "dlinfoack");
+
+ dlp = (union DL_primitives *) ctl.buf;
+
+ expecting(DL_INFO_ACK, dlp);
+
+ if (ctl.len < sizeof (dl_info_ack_t))
+ err("dlinfoack: response ctl.len too short: %d", ctl.len);
+
+ if (flags != RS_HIPRI)
+ err("dlinfoack: DL_INFO_ACK was not M_PCPROTO");
+
+ if (ctl.len < sizeof (dl_info_ack_t))
+ err("dlinfoack: short response ctl.len: %d", ctl.len);
+}
+
+dlattachreq(fd, ppa)
+int fd;
+u_long ppa;
+{
+ dl_attach_req_t attach_req;
+ struct strbuf ctl;
+ int flags;
+
+ attach_req.dl_primitive = DL_ATTACH_REQ;
+ attach_req.dl_ppa = ppa;
+
+ ctl.maxlen = 0;
+ ctl.len = sizeof (attach_req);
+ ctl.buf = (char *) &attach_req;
+
+ flags = 0;
+
+ if (putmsg(fd, &ctl, (struct strbuf*) NULL, flags) < 0)
+ syserr("dlattachreq: putmsg");
+}
+
+dlenabmultireq(fd, addr, length)
+int fd;
+char *addr;
+int length;
+{
+ long buf[MAXDLBUF];
+ union DL_primitives *dlp;
+ struct strbuf ctl;
+ int flags;
+
+ dlp = (union DL_primitives*) buf;
+
+ dlp->enabmulti_req.dl_primitive = DL_ENABMULTI_REQ;
+ dlp->enabmulti_req.dl_addr_length = length;
+ dlp->enabmulti_req.dl_addr_offset = sizeof (dl_enabmulti_req_t);
+
+ (void) memcpy((char*)OFFADDR(buf, sizeof (dl_enabmulti_req_t)), addr, length);
+
+ ctl.maxlen = 0;
+ ctl.len = sizeof (dl_enabmulti_req_t) + length;
+ ctl.buf = (char*) buf;
+
+ flags = 0;
+
+ if (putmsg(fd, &ctl, (struct strbuf*) NULL, flags) < 0)
+ syserr("dlenabmultireq: putmsg");
+}
+
+dldisabmultireq(fd, addr, length)
+int fd;
+char *addr;
+int length;
+{
+ long buf[MAXDLBUF];
+ union DL_primitives *dlp;
+ struct strbuf ctl;
+ int flags;
+
+ dlp = (union DL_primitives*) buf;
+
+ dlp->disabmulti_req.dl_primitive = DL_ENABMULTI_REQ;
+ dlp->disabmulti_req.dl_addr_length = length;
+ dlp->disabmulti_req.dl_addr_offset = sizeof (dl_disabmulti_req_t);
+
+ (void) memcpy((char*)OFFADDR(buf, sizeof (dl_disabmulti_req_t)), addr, length);
+
+ ctl.maxlen = 0;
+ ctl.len = sizeof (dl_disabmulti_req_t) + length;
+ ctl.buf = (char*) buf;
+
+ flags = 0;
+
+ if (putmsg(fd, &ctl, (struct strbuf*) NULL, flags) < 0)
+ syserr("dldisabmultireq: putmsg");
+}
+
+dlpromisconreq(fd, level)
+int fd;
+u_long level;
+{
+ dl_promiscon_req_t promiscon_req;
+ struct strbuf ctl;
+ int flags;
+
+ promiscon_req.dl_primitive = DL_PROMISCON_REQ;
+ promiscon_req.dl_level = level;
+
+ ctl.maxlen = 0;
+ ctl.len = sizeof (promiscon_req);
+ ctl.buf = (char *) &promiscon_req;
+
+ flags = 0;
+
+ if (putmsg(fd, &ctl, (struct strbuf*) NULL, flags) < 0)
+ syserr("dlpromiscon: putmsg");
+
+}
+
+dlpromiscoff(fd, level)
+int fd;
+u_long level;
+{
+ dl_promiscoff_req_t promiscoff_req;
+ struct strbuf ctl;
+ int flags;
+
+ promiscoff_req.dl_primitive = DL_PROMISCOFF_REQ;
+ promiscoff_req.dl_level = level;
+
+ ctl.maxlen = 0;
+ ctl.len = sizeof (promiscoff_req);
+ ctl.buf = (char *) &promiscoff_req;
+
+ flags = 0;
+
+ if (putmsg(fd, &ctl, (struct strbuf*) NULL, flags) < 0)
+ syserr("dlpromiscoff: putmsg");
+}
+
+dlphysaddrreq(fd, addrtype)
+int fd;
+u_long addrtype;
+{
+ dl_phys_addr_req_t phys_addr_req;
+ struct strbuf ctl;
+ int flags;
+
+ phys_addr_req.dl_primitive = DL_PHYS_ADDR_REQ;
+ phys_addr_req.dl_addr_type = addrtype;
+
+ ctl.maxlen = 0;
+ ctl.len = sizeof (phys_addr_req);
+ ctl.buf = (char *) &phys_addr_req;
+
+ flags = 0;
+
+ if (putmsg(fd, &ctl, (struct strbuf*) NULL, flags) < 0)
+ syserr("dlphysaddrreq: putmsg");
+}
+
+dlsetphysaddrreq(fd, addr, length)
+int fd;
+char *addr;
+int length;
+{
+ long buf[MAXDLBUF];
+ union DL_primitives *dlp;
+ struct strbuf ctl;
+ int flags;
+
+ dlp = (union DL_primitives*) buf;
+
+ dlp->set_physaddr_req.dl_primitive = DL_ENABMULTI_REQ;
+ dlp->set_physaddr_req.dl_addr_length = length;
+ dlp->set_physaddr_req.dl_addr_offset = sizeof (dl_set_phys_addr_req_t);
+
+ (void) memcpy((char*)OFFADDR(buf, sizeof (dl_set_phys_addr_req_t)), addr, length);
+
+ ctl.maxlen = 0;
+ ctl.len = sizeof (dl_set_phys_addr_req_t) + length;
+ ctl.buf = (char*) buf;
+
+ flags = 0;
+
+ if (putmsg(fd, &ctl, (struct strbuf*) NULL, flags) < 0)
+ syserr("dlsetphysaddrreq: putmsg");
+}
+
+dldetachreq(fd)
+int fd;
+{
+ dl_detach_req_t detach_req;
+ struct strbuf ctl;
+ int flags;
+
+ detach_req.dl_primitive = DL_DETACH_REQ;
+
+ ctl.maxlen = 0;
+ ctl.len = sizeof (detach_req);
+ ctl.buf = (char *) &detach_req;
+
+ flags = 0;
+
+ if (putmsg(fd, &ctl, (struct strbuf*) NULL, flags) < 0)
+ syserr("dldetachreq: putmsg");
+}
+
+dlbindreq(fd, sap, max_conind, service_mode, conn_mgmt, xidtest)
+int fd;
+u_long sap;
+u_long max_conind;
+u_long service_mode;
+u_long conn_mgmt;
+u_long xidtest;
+{
+ dl_bind_req_t bind_req;
+ struct strbuf ctl;
+ int flags;
+
+ bind_req.dl_primitive = DL_BIND_REQ;
+ bind_req.dl_sap = sap;
+ bind_req.dl_max_conind = max_conind;
+ bind_req.dl_service_mode = service_mode;
+ bind_req.dl_conn_mgmt = conn_mgmt;
+ bind_req.dl_xidtest_flg = xidtest;
+
+ ctl.maxlen = 0;
+ ctl.len = sizeof (bind_req);
+ ctl.buf = (char *) &bind_req;
+
+ flags = 0;
+
+ if (putmsg(fd, &ctl, (struct strbuf*) NULL, flags) < 0)
+ syserr("dlbindreq: putmsg");
+}
+
+dlunitdatareq(fd, addrp, addrlen, minpri, maxpri, datap, datalen)
+int fd;
+u_char *addrp;
+int addrlen;
+u_long minpri, maxpri;
+u_char *datap;
+int datalen;
+{
+ long buf[MAXDLBUF];
+ union DL_primitives *dlp;
+ struct strbuf data, ctl;
+
+ dlp = (union DL_primitives*) buf;
+
+ dlp->unitdata_req.dl_primitive = DL_UNITDATA_REQ;
+ dlp->unitdata_req.dl_dest_addr_length = addrlen;
+ dlp->unitdata_req.dl_dest_addr_offset = sizeof (dl_unitdata_req_t);
+ dlp->unitdata_req.dl_priority.dl_min = minpri;
+ dlp->unitdata_req.dl_priority.dl_max = maxpri;
+
+ (void) memcpy(OFFADDR(dlp, sizeof (dl_unitdata_req_t)), addrp, addrlen);
+
+ ctl.maxlen = 0;
+ ctl.len = sizeof (dl_unitdata_req_t) + addrlen;
+ ctl.buf = (char *) buf;
+
+ data.maxlen = 0;
+ data.len = datalen;
+ data.buf = (char *) datap;
+
+ if (putmsg(fd, &ctl, &data, 0) < 0)
+ syserr("dlunitdatareq: putmsg");
+}
+
+dlunbindreq(fd)
+int fd;
+{
+ dl_unbind_req_t unbind_req;
+ struct strbuf ctl;
+ int flags;
+
+ unbind_req.dl_primitive = DL_UNBIND_REQ;
+
+ ctl.maxlen = 0;
+ ctl.len = sizeof (unbind_req);
+ ctl.buf = (char *) &unbind_req;
+
+ flags = 0;
+
+ if (putmsg(fd, &ctl, (struct strbuf*) NULL, flags) < 0)
+ syserr("dlunbindreq: putmsg");
+}
+
+dlokack(fd, bufp)
+int fd;
+char *bufp;
+{
+ union DL_primitives *dlp;
+ struct strbuf ctl;
+ int flags;
+
+ ctl.maxlen = MAXDLBUF;
+ ctl.len = 0;
+ ctl.buf = bufp;
+
+ strgetmsg(fd, &ctl, (struct strbuf*)NULL, &flags, "dlokack");
+
+ dlp = (union DL_primitives *) ctl.buf;
+
+ expecting(DL_OK_ACK, dlp);
+
+ if (ctl.len < sizeof (dl_ok_ack_t))
+ err("dlokack: response ctl.len too short: %d", ctl.len);
+
+ if (flags != RS_HIPRI)
+ err("dlokack: DL_OK_ACK was not M_PCPROTO");
+
+ if (ctl.len < sizeof (dl_ok_ack_t))
+ err("dlokack: short response ctl.len: %d", ctl.len);
+}
+
+dlerrorack(fd, bufp)
+int fd;
+char *bufp;
+{
+ union DL_primitives *dlp;
+ struct strbuf ctl;
+ int flags;
+
+ ctl.maxlen = MAXDLBUF;
+ ctl.len = 0;
+ ctl.buf = bufp;
+
+ strgetmsg(fd, &ctl, (struct strbuf*)NULL, &flags, "dlerrorack");
+
+ dlp = (union DL_primitives *) ctl.buf;
+
+ expecting(DL_ERROR_ACK, dlp);
+
+ if (ctl.len < sizeof (dl_error_ack_t))
+ err("dlerrorack: response ctl.len too short: %d", ctl.len);
+
+ if (flags != RS_HIPRI)
+ err("dlerrorack: DL_OK_ACK was not M_PCPROTO");
+
+ if (ctl.len < sizeof (dl_error_ack_t))
+ err("dlerrorack: short response ctl.len: %d", ctl.len);
+}
+
+dlbindack(fd, bufp)
+int fd;
+char *bufp;
+{
+ union DL_primitives *dlp;
+ struct strbuf ctl;
+ int flags;
+
+ ctl.maxlen = MAXDLBUF;
+ ctl.len = 0;
+ ctl.buf = bufp;
+
+ strgetmsg(fd, &ctl, (struct strbuf*)NULL, &flags, "dlbindack");
+
+ dlp = (union DL_primitives *) ctl.buf;
+
+ expecting(DL_BIND_ACK, dlp);
+
+ if (flags != RS_HIPRI)
+ err("dlbindack: DL_OK_ACK was not M_PCPROTO");
+
+ if (ctl.len < sizeof (dl_bind_ack_t))
+ err("dlbindack: short response ctl.len: %d", ctl.len);
+}
+
+dlphysaddrack(fd, bufp)
+int fd;
+char *bufp;
+{
+ union DL_primitives *dlp;
+ struct strbuf ctl;
+ int flags;
+
+ ctl.maxlen = MAXDLBUF;
+ ctl.len = 0;
+ ctl.buf = bufp;
+
+ strgetmsg(fd, &ctl, (struct strbuf*)NULL, &flags, "dlphysaddrack");
+
+ dlp = (union DL_primitives *) ctl.buf;
+
+ expecting(DL_PHYS_ADDR_ACK, dlp);
+
+ if (flags != RS_HIPRI)
+ err("dlbindack: DL_OK_ACK was not M_PCPROTO");
+
+ if (ctl.len < sizeof (dl_phys_addr_ack_t))
+ err("dlphysaddrack: short response ctl.len: %d", ctl.len);
+}
+
+void
+sigalrm()
+{
+ (void) err("sigalrm: TIMEOUT");
+}
+
+strgetmsg(fd, ctlp, datap, flagsp, caller)
+int fd;
+struct strbuf *ctlp, *datap;
+int *flagsp;
+char *caller;
+{
+ int rc;
+ static char errmsg[80];
+
+ /*
+ * Start timer.
+ */
+ (void) signal(SIGALRM, sigalrm);
+ if (alarm(MAXWAIT) < 0) {
+ (void) sprintf(errmsg, "%s: alarm", caller);
+ syserr(errmsg);
+ }
+
+ /*
+ * Set flags argument and issue getmsg().
+ */
+ *flagsp = 0;
+ if ((rc = getmsg(fd, ctlp, datap, flagsp)) < 0) {
+ (void) sprintf(errmsg, "%s: getmsg", caller);
+ syserr(errmsg);
+ }
+
+ /*
+ * Stop timer.
+ */
+ if (alarm(0) < 0) {
+ (void) sprintf(errmsg, "%s: alarm", caller);
+ syserr(errmsg);
+ }
+
+ /*
+ * Check for MOREDATA and/or MORECTL.
+ */
+ if ((rc & (MORECTL | MOREDATA)) == (MORECTL | MOREDATA))
+ err("%s: MORECTL|MOREDATA", caller);
+ if (rc & MORECTL)
+ err("%s: MORECTL", caller);
+ if (rc & MOREDATA)
+ err("%s: MOREDATA", caller);
+
+ /*
+ * Check for at least sizeof (long) control data portion.
+ */
+ if (ctlp->len < sizeof (long))
+ err("getmsg: control portion length < sizeof (long): %d", ctlp->len);
+}
+
+expecting(prim, dlp)
+int prim;
+union DL_primitives *dlp;
+{
+ if (dlp->dl_primitive != (u_long)prim) {
+ printdlprim(dlp);
+ err("expected %s got %s", dlprim(prim),
+ dlprim(dlp->dl_primitive));
+ exit(1);
+ }
+}
+
+/*
+ * Print any DLPI msg in human readable format.
+ */
+printdlprim(dlp)
+union DL_primitives *dlp;
+{
+ switch (dlp->dl_primitive) {
+ case DL_INFO_REQ:
+ printdlinforeq(dlp);
+ break;
+
+ case DL_INFO_ACK:
+ printdlinfoack(dlp);
+ break;
+
+ case DL_ATTACH_REQ:
+ printdlattachreq(dlp);
+ break;
+
+ case DL_OK_ACK:
+ printdlokack(dlp);
+ break;
+
+ case DL_ERROR_ACK:
+ printdlerrorack(dlp);
+ break;
+
+ case DL_DETACH_REQ:
+ printdldetachreq(dlp);
+ break;
+
+ case DL_BIND_REQ:
+ printdlbindreq(dlp);
+ break;
+
+ case DL_BIND_ACK:
+ printdlbindack(dlp);
+ break;
+
+ case DL_UNBIND_REQ:
+ printdlunbindreq(dlp);
+ break;
+
+ case DL_SUBS_BIND_REQ:
+ printdlsubsbindreq(dlp);
+ break;
+
+ case DL_SUBS_BIND_ACK:
+ printdlsubsbindack(dlp);
+ break;
+
+ case DL_SUBS_UNBIND_REQ:
+ printdlsubsunbindreq(dlp);
+ break;
+
+ case DL_ENABMULTI_REQ:
+ printdlenabmultireq(dlp);
+ break;
+
+ case DL_DISABMULTI_REQ:
+ printdldisabmultireq(dlp);
+ break;
+
+ case DL_PROMISCON_REQ:
+ printdlpromisconreq(dlp);
+ break;
+
+ case DL_PROMISCOFF_REQ:
+ printdlpromiscoffreq(dlp);
+ break;
+
+ case DL_UNITDATA_REQ:
+ printdlunitdatareq(dlp);
+ break;
+
+ case DL_UNITDATA_IND:
+ printdlunitdataind(dlp);
+ break;
+
+ case DL_UDERROR_IND:
+ printdluderrorind(dlp);
+ break;
+
+ case DL_UDQOS_REQ:
+ printdludqosreq(dlp);
+ break;
+
+ case DL_PHYS_ADDR_REQ:
+ printdlphysaddrreq(dlp);
+ break;
+
+ case DL_PHYS_ADDR_ACK:
+ printdlphysaddrack(dlp);
+ break;
+
+ case DL_SET_PHYS_ADDR_REQ:
+ printdlsetphysaddrreq(dlp);
+ break;
+
+ default:
+ err("printdlprim: unknown primitive type 0x%x",
+ dlp->dl_primitive);
+ break;
+ }
+}
+
+/* ARGSUSED */
+printdlinforeq(dlp)
+union DL_primitives *dlp;
+{
+ (void) printf("DL_INFO_REQ\n");
+}
+
+printdlinfoack(dlp)
+union DL_primitives *dlp;
+{
+ u_char addr[MAXDLADDR];
+ u_char brdcst[MAXDLADDR];
+
+ addrtostring(OFFADDR(dlp, dlp->info_ack.dl_addr_offset),
+ dlp->info_ack.dl_addr_length, addr);
+ addrtostring(OFFADDR(dlp, dlp->info_ack.dl_brdcst_addr_offset),
+ dlp->info_ack.dl_brdcst_addr_length, brdcst);
+
+ (void) printf("DL_INFO_ACK: max_sdu %d min_sdu %d\n",
+ dlp->info_ack.dl_max_sdu,
+ dlp->info_ack.dl_min_sdu);
+ (void) printf("addr_length %d mac_type %s current_state %s\n",
+ dlp->info_ack.dl_addr_length,
+ dlmactype(dlp->info_ack.dl_mac_type),
+ dlstate(dlp->info_ack.dl_current_state));
+ (void) printf("sap_length %d service_mode %s qos_length %d\n",
+ dlp->info_ack.dl_sap_length,
+ dlservicemode(dlp->info_ack.dl_service_mode),
+ dlp->info_ack.dl_qos_length);
+ (void) printf("qos_offset %d qos_range_length %d qos_range_offset %d\n",
+ dlp->info_ack.dl_qos_offset,
+ dlp->info_ack.dl_qos_range_length,
+ dlp->info_ack.dl_qos_range_offset);
+ (void) printf("provider_style %s addr_offset %d version %d\n",
+ dlstyle(dlp->info_ack.dl_provider_style),
+ dlp->info_ack.dl_addr_offset,
+ dlp->info_ack.dl_version);
+ (void) printf("brdcst_addr_length %d brdcst_addr_offset %d\n",
+ dlp->info_ack.dl_brdcst_addr_length,
+ dlp->info_ack.dl_brdcst_addr_offset);
+ (void) printf("addr %s\n", addr);
+ (void) printf("brdcst_addr %s\n", brdcst);
+}
+
+printdlattachreq(dlp)
+union DL_primitives *dlp;
+{
+ (void) printf("DL_ATTACH_REQ: ppa %d\n",
+ dlp->attach_req.dl_ppa);
+}
+
+printdlokack(dlp)
+union DL_primitives *dlp;
+{
+ (void) printf("DL_OK_ACK: correct_primitive %s\n",
+ dlprim(dlp->ok_ack.dl_correct_primitive));
+}
+
+printdlerrorack(dlp)
+union DL_primitives *dlp;
+{
+ (void) printf("DL_ERROR_ACK: error_primitive %s errno %s unix_errno %d\n",
+ dlprim(dlp->error_ack.dl_error_primitive),
+ dlerrno(dlp->error_ack.dl_errno),
+ dlp->error_ack.dl_unix_errno);
+}
+
+printdlenabmultireq(dlp)
+union DL_primitives *dlp;
+{
+ u_char addr[MAXDLADDR];
+
+ addrtostring(OFFADDR(dlp, dlp->enabmulti_req.dl_addr_offset),
+ dlp->enabmulti_req.dl_addr_length, addr);
+
+ (void) printf("DL_ENABMULTI_REQ: addr_length %d addr_offset %d\n",
+ dlp->enabmulti_req.dl_addr_length,
+ dlp->enabmulti_req.dl_addr_offset);
+ (void) printf("addr %s\n", addr);
+}
+
+printdldisabmultireq(dlp)
+union DL_primitives *dlp;
+{
+ u_char addr[MAXDLADDR];
+
+ addrtostring(OFFADDR(dlp, dlp->disabmulti_req.dl_addr_offset),
+ dlp->disabmulti_req.dl_addr_length, addr);
+
+ (void) printf("DL_DISABMULTI_REQ: addr_length %d addr_offset %d\n",
+ dlp->disabmulti_req.dl_addr_length,
+ dlp->disabmulti_req.dl_addr_offset);
+ (void) printf("addr %s\n", addr);
+}
+
+printdlpromisconreq(dlp)
+union DL_primitives *dlp;
+{
+ (void) printf("DL_PROMISCON_REQ: level %s\n",
+ dlpromisclevel(dlp->promiscon_req.dl_level));
+}
+
+printdlpromiscoffreq(dlp)
+union DL_primitives *dlp;
+{
+ (void) printf("DL_PROMISCOFF_REQ: level %s\n",
+ dlpromisclevel(dlp->promiscoff_req.dl_level));
+}
+
+printdlphysaddrreq(dlp)
+union DL_primitives *dlp;
+{
+ (void) printf("DL_PHYS_ADDR_REQ: addr_type 0x%x\n",
+ dlp->physaddr_req.dl_addr_type);
+}
+
+printdlphysaddrack(dlp)
+union DL_primitives *dlp;
+{
+ u_char addr[MAXDLADDR];
+
+ addrtostring(OFFADDR(dlp, dlp->physaddr_ack.dl_addr_offset),
+ dlp->physaddr_ack.dl_addr_length, addr);
+
+ (void) printf("DL_PHYS_ADDR_ACK: addr_length %d addr_offset %d\n",
+ dlp->physaddr_ack.dl_addr_length,
+ dlp->physaddr_ack.dl_addr_offset);
+ (void) printf("addr %s\n", addr);
+}
+
+printdlsetphysaddrreq(dlp)
+union DL_primitives *dlp;
+{
+ u_char addr[MAXDLADDR];
+
+ addrtostring(OFFADDR(dlp, dlp->set_physaddr_req.dl_addr_offset),
+ dlp->set_physaddr_req.dl_addr_length, addr);
+
+ (void) printf("DL_SET_PHYS_ADDR_REQ: addr_length %d addr_offset %d\n",
+ dlp->set_physaddr_req.dl_addr_length,
+ dlp->set_physaddr_req.dl_addr_offset);
+ (void) printf("addr %s\n", addr);
+}
+
+/* ARGSUSED */
+printdldetachreq(dlp)
+union DL_primitives *dlp;
+{
+ (void) printf("DL_DETACH_REQ\n");
+}
+
+printdlbindreq(dlp)
+union DL_primitives *dlp;
+{
+ (void) printf("DL_BIND_REQ: sap %d max_conind %d\n",
+ dlp->bind_req.dl_sap,
+ dlp->bind_req.dl_max_conind);
+ (void) printf("service_mode %s conn_mgmt %d xidtest_flg 0x%x\n",
+ dlservicemode(dlp->bind_req.dl_service_mode),
+ dlp->bind_req.dl_conn_mgmt,
+ dlp->bind_req.dl_xidtest_flg);
+}
+
+printdlbindack(dlp)
+union DL_primitives *dlp;
+{
+ u_char addr[MAXDLADDR];
+
+ addrtostring(OFFADDR(dlp, dlp->bind_ack.dl_addr_offset),
+ dlp->bind_ack.dl_addr_length, addr);
+
+ (void) printf("DL_BIND_ACK: sap %d addr_length %d addr_offset %d\n",
+ dlp->bind_ack.dl_sap,
+ dlp->bind_ack.dl_addr_length,
+ dlp->bind_ack.dl_addr_offset);
+ (void) printf("max_conind %d xidtest_flg 0x%x\n",
+ dlp->bind_ack.dl_max_conind,
+ dlp->bind_ack.dl_xidtest_flg);
+ (void) printf("addr %s\n", addr);
+}
+
+/* ARGSUSED */
+printdlunbindreq(dlp)
+union DL_primitives *dlp;
+{
+ (void) printf("DL_UNBIND_REQ\n");
+}
+
+printdlsubsbindreq(dlp)
+union DL_primitives *dlp;
+{
+ u_char sap[MAXDLADDR];
+
+ addrtostring(OFFADDR(dlp, dlp->subs_bind_req.dl_subs_sap_offset),
+ dlp->subs_bind_req.dl_subs_sap_length, sap);
+
+ (void) printf("DL_SUBS_BIND_REQ: subs_sap_offset %d sub_sap_len %d\n",
+ dlp->subs_bind_req.dl_subs_sap_offset,
+ dlp->subs_bind_req.dl_subs_sap_length);
+ (void) printf("sap %s\n", sap);
+}
+
+printdlsubsbindack(dlp)
+union DL_primitives *dlp;
+{
+ u_char sap[MAXDLADDR];
+
+ addrtostring(OFFADDR(dlp, dlp->subs_bind_ack.dl_subs_sap_offset),
+ dlp->subs_bind_ack.dl_subs_sap_length, sap);
+
+ (void) printf("DL_SUBS_BIND_ACK: subs_sap_offset %d sub_sap_length %d\n",
+ dlp->subs_bind_ack.dl_subs_sap_offset,
+ dlp->subs_bind_ack.dl_subs_sap_length);
+ (void) printf("sap %s\n", sap);
+}
+
+printdlsubsunbindreq(dlp)
+union DL_primitives *dlp;
+{
+ u_char sap[MAXDLADDR];
+
+ addrtostring(OFFADDR(dlp, dlp->subs_unbind_req.dl_subs_sap_offset),
+ dlp->subs_unbind_req.dl_subs_sap_length, sap);
+
+ (void) printf("DL_SUBS_UNBIND_REQ: subs_sap_offset %d sub_sap_length %d\n",
+ dlp->subs_unbind_req.dl_subs_sap_offset,
+ dlp->subs_unbind_req.dl_subs_sap_length);
+ (void) printf("sap %s\n", sap);
+}
+
+printdlunitdatareq(dlp)
+union DL_primitives *dlp;
+{
+ u_char addr[MAXDLADDR];
+
+ addrtostring(OFFADDR(dlp, dlp->unitdata_req.dl_dest_addr_offset),
+ dlp->unitdata_req.dl_dest_addr_length, addr);
+
+ (void) printf("DL_UNITDATA_REQ: dest_addr_length %d dest_addr_offset %d\n",
+ dlp->unitdata_req.dl_dest_addr_length,
+ dlp->unitdata_req.dl_dest_addr_offset);
+ (void) printf("dl_priority.min %d dl_priority.max %d\n",
+ dlp->unitdata_req.dl_priority.dl_min,
+ dlp->unitdata_req.dl_priority.dl_max);
+ (void) printf("addr %s\n", addr);
+}
+
+printdlunitdataind(dlp)
+union DL_primitives *dlp;
+{
+ u_char dest[MAXDLADDR];
+ u_char src[MAXDLADDR];
+
+ addrtostring(OFFADDR(dlp, dlp->unitdata_ind.dl_dest_addr_offset),
+ dlp->unitdata_ind.dl_dest_addr_length, dest);
+ addrtostring(OFFADDR(dlp, dlp->unitdata_ind.dl_src_addr_offset),
+ dlp->unitdata_ind.dl_src_addr_length, src);
+
+ (void) printf("DL_UNITDATA_IND: dest_addr_length %d dest_addr_offset %d\n",
+ dlp->unitdata_ind.dl_dest_addr_length,
+ dlp->unitdata_ind.dl_dest_addr_offset);
+ (void) printf("src_addr_length %d src_addr_offset %d\n",
+ dlp->unitdata_ind.dl_src_addr_length,
+ dlp->unitdata_ind.dl_src_addr_offset);
+ (void) printf("group_address 0x%x\n",
+ dlp->unitdata_ind.dl_group_address);
+ (void) printf("dest %s\n", dest);
+ (void) printf("src %s\n", src);
+}
+
+printdluderrorind(dlp)
+union DL_primitives *dlp;
+{
+ u_char addr[MAXDLADDR];
+
+ addrtostring(OFFADDR(dlp, dlp->uderror_ind.dl_dest_addr_offset),
+ dlp->uderror_ind.dl_dest_addr_length, addr);
+
+ (void) printf("DL_UDERROR_IND: dest_addr_length %d dest_addr_offset %d\n",
+ dlp->uderror_ind.dl_dest_addr_length,
+ dlp->uderror_ind.dl_dest_addr_offset);
+ (void) printf("unix_errno %d errno %s\n",
+ dlp->uderror_ind.dl_unix_errno,
+ dlerrno(dlp->uderror_ind.dl_errno));
+ (void) printf("addr %s\n", addr);
+}
+
+printdltestreq(dlp)
+union DL_primitives *dlp;
+{
+ u_char addr[MAXDLADDR];
+
+ addrtostring(OFFADDR(dlp, dlp->test_req.dl_dest_addr_offset),
+ dlp->test_req.dl_dest_addr_length, addr);
+
+ (void) printf("DL_TEST_REQ: flag 0x%x dest_addr_length %d dest_addr_offset %d\n",
+ dlp->test_req.dl_flag,
+ dlp->test_req.dl_dest_addr_length,
+ dlp->test_req.dl_dest_addr_offset);
+ (void) printf("dest_addr %s\n", addr);
+}
+
+printdltestind(dlp)
+union DL_primitives *dlp;
+{
+ u_char dest[MAXDLADDR];
+ u_char src[MAXDLADDR];
+
+ addrtostring(OFFADDR(dlp, dlp->test_ind.dl_dest_addr_offset),
+ dlp->test_ind.dl_dest_addr_length, dest);
+ addrtostring(OFFADDR(dlp, dlp->test_ind.dl_src_addr_offset),
+ dlp->test_ind.dl_src_addr_length, src);
+
+ (void) printf("DL_TEST_IND: flag 0x%x dest_addr_length %d dest_addr_offset %d\n",
+ dlp->test_ind.dl_flag,
+ dlp->test_ind.dl_dest_addr_length,
+ dlp->test_ind.dl_dest_addr_offset);
+ (void) printf("src_addr_length %d src_addr_offset %d\n",
+ dlp->test_ind.dl_src_addr_length,
+ dlp->test_ind.dl_src_addr_offset);
+ (void) printf("dest_addr %s\n", dest);
+ (void) printf("src_addr %s\n", src);
+}
+
+printdltestres(dlp)
+union DL_primitives *dlp;
+{
+ u_char dest[MAXDLADDR];
+
+ addrtostring(OFFADDR(dlp, dlp->test_res.dl_dest_addr_offset),
+ dlp->test_res.dl_dest_addr_length, dest);
+
+ (void) printf("DL_TEST_RES: flag 0x%x dest_addr_length %d dest_addr_offset %d\n",
+ dlp->test_res.dl_flag,
+ dlp->test_res.dl_dest_addr_length,
+ dlp->test_res.dl_dest_addr_offset);
+ (void) printf("dest_addr %s\n", dest);
+}
+
+printdltestcon(dlp)
+union DL_primitives *dlp;
+{
+ u_char dest[MAXDLADDR];
+ u_char src[MAXDLADDR];
+
+ addrtostring(OFFADDR(dlp, dlp->test_con.dl_dest_addr_offset),
+ dlp->test_con.dl_dest_addr_length, dest);
+ addrtostring(OFFADDR(dlp, dlp->test_con.dl_src_addr_offset),
+ dlp->test_con.dl_src_addr_length, src);
+
+ (void) printf("DL_TEST_CON: flag 0x%x dest_addr_length %d dest_addr_offset %d\n",
+ dlp->test_con.dl_flag,
+ dlp->test_con.dl_dest_addr_length,
+ dlp->test_con.dl_dest_addr_offset);
+ (void) printf("src_addr_length %d src_addr_offset %d\n",
+ dlp->test_con.dl_src_addr_length,
+ dlp->test_con.dl_src_addr_offset);
+ (void) printf("dest_addr %s\n", dest);
+ (void) printf("src_addr %s\n", src);
+}
+
+printdlxidreq(dlp)
+union DL_primitives *dlp;
+{
+ u_char dest[MAXDLADDR];
+
+ addrtostring(OFFADDR(dlp, dlp->xid_req.dl_dest_addr_offset),
+ dlp->xid_req.dl_dest_addr_length, dest);
+
+ (void) printf("DL_XID_REQ: flag 0x%x dest_addr_length %d dest_addr_offset %d\n",
+ dlp->xid_req.dl_flag,
+ dlp->xid_req.dl_dest_addr_length,
+ dlp->xid_req.dl_dest_addr_offset);
+ (void) printf("dest_addr %s\n", dest);
+}
+
+printdlxidind(dlp)
+union DL_primitives *dlp;
+{
+ u_char dest[MAXDLADDR];
+ u_char src[MAXDLADDR];
+
+ addrtostring(OFFADDR(dlp, dlp->xid_ind.dl_dest_addr_offset),
+ dlp->xid_ind.dl_dest_addr_length, dest);
+ addrtostring(OFFADDR(dlp, dlp->xid_ind.dl_src_addr_offset),
+ dlp->xid_ind.dl_src_addr_length, src);
+
+ (void) printf("DL_XID_IND: flag 0x%x dest_addr_length %d dest_addr_offset %d\n",
+ dlp->xid_ind.dl_flag,
+ dlp->xid_ind.dl_dest_addr_length,
+ dlp->xid_ind.dl_dest_addr_offset);
+ (void) printf("src_addr_length %d src_addr_offset %d\n",
+ dlp->xid_ind.dl_src_addr_length,
+ dlp->xid_ind.dl_src_addr_offset);
+ (void) printf("dest_addr %s\n", dest);
+ (void) printf("src_addr %s\n", src);
+}
+
+printdlxidres(dlp)
+union DL_primitives *dlp;
+{
+ u_char dest[MAXDLADDR];
+
+ addrtostring(OFFADDR(dlp, dlp->xid_res.dl_dest_addr_offset),
+ dlp->xid_res.dl_dest_addr_length, dest);
+
+ (void) printf("DL_XID_RES: flag 0x%x dest_addr_length %d dest_addr_offset %d\n",
+ dlp->xid_res.dl_flag,
+ dlp->xid_res.dl_dest_addr_length,
+ dlp->xid_res.dl_dest_addr_offset);
+ (void) printf("dest_addr %s\n", dest);
+}
+
+printdlxidcon(dlp)
+union DL_primitives *dlp;
+{
+ u_char dest[MAXDLADDR];
+ u_char src[MAXDLADDR];
+
+ addrtostring(OFFADDR(dlp, dlp->xid_con.dl_dest_addr_offset),
+ dlp->xid_con.dl_dest_addr_length, dest);
+ addrtostring(OFFADDR(dlp, dlp->xid_con.dl_src_addr_offset),
+ dlp->xid_con.dl_src_addr_length, src);
+
+ (void) printf("DL_XID_CON: flag 0x%x dest_addr_length %d dest_addr_offset %d\n",
+ dlp->xid_con.dl_flag,
+ dlp->xid_con.dl_dest_addr_length,
+ dlp->xid_con.dl_dest_addr_offset);
+ (void) printf("src_addr_length %d src_addr_offset %d\n",
+ dlp->xid_con.dl_src_addr_length,
+ dlp->xid_con.dl_src_addr_offset);
+ (void) printf("dest_addr %s\n", dest);
+ (void) printf("src_addr %s\n", src);
+}
+
+printdludqosreq(dlp)
+union DL_primitives *dlp;
+{
+ (void) printf("DL_UDQOS_REQ: qos_length %d qos_offset %d\n",
+ dlp->udqos_req.dl_qos_length,
+ dlp->udqos_req.dl_qos_offset);
+}
+
+/*
+ * Return string.
+ */
+addrtostring(addr, length, s)
+u_char *addr;
+u_long length;
+u_char *s;
+{
+ int i;
+
+ for (i = 0; i < length; i++) {
+ (void) sprintf((char*) s, "%x:", addr[i] & 0xff);
+ s = s + strlen((char*)s);
+ }
+ if (length)
+ *(--s) = '\0';
+}
+
+/*
+ * Return length
+ */
+stringtoaddr(sp, addr)
+char *sp;
+char *addr;
+{
+ int n = 0;
+ char *p;
+ int val;
+
+ p = sp;
+ while (p = strtok(p, ":")) {
+ if (sscanf(p, "%x", &val) != 1)
+ err("stringtoaddr: invalid input string: %s", sp);
+ if (val > 0xff)
+ err("stringtoaddr: invalid input string: %s", sp);
+ *addr++ = val;
+ n++;
+ p = NULL;
+ }
+
+ return (n);
+}
+
+
+static char
+hexnibble(c)
+char c;
+{
+ static char hextab[] = {
+ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
+ 'a', 'b', 'c', 'd', 'e', 'f'
+ };
+
+ return (hextab[c & 0x0f]);
+}
+
+char*
+dlprim(prim)
+u_long prim;
+{
+ static char primbuf[80];
+
+ switch ((int)prim) {
+ CASERET(DL_INFO_REQ);
+ CASERET(DL_INFO_ACK);
+ CASERET(DL_ATTACH_REQ);
+ CASERET(DL_DETACH_REQ);
+ CASERET(DL_BIND_REQ);
+ CASERET(DL_BIND_ACK);
+ CASERET(DL_UNBIND_REQ);
+ CASERET(DL_OK_ACK);
+ CASERET(DL_ERROR_ACK);
+ CASERET(DL_SUBS_BIND_REQ);
+ CASERET(DL_SUBS_BIND_ACK);
+ CASERET(DL_UNITDATA_REQ);
+ CASERET(DL_UNITDATA_IND);
+ CASERET(DL_UDERROR_IND);
+ CASERET(DL_UDQOS_REQ);
+ CASERET(DL_CONNECT_REQ);
+ CASERET(DL_CONNECT_IND);
+ CASERET(DL_CONNECT_RES);
+ CASERET(DL_CONNECT_CON);
+ CASERET(DL_TOKEN_REQ);
+ CASERET(DL_TOKEN_ACK);
+ CASERET(DL_DISCONNECT_REQ);
+ CASERET(DL_DISCONNECT_IND);
+ CASERET(DL_RESET_REQ);
+ CASERET(DL_RESET_IND);
+ CASERET(DL_RESET_RES);
+ CASERET(DL_RESET_CON);
+ default:
+ (void) sprintf(primbuf, "unknown primitive 0x%x", prim);
+ return (primbuf);
+ }
+}
+
+
+char*
+dlstate(state)
+u_long state;
+{
+ static char statebuf[80];
+
+ switch (state) {
+ CASERET(DL_UNATTACHED);
+ CASERET(DL_ATTACH_PENDING);
+ CASERET(DL_DETACH_PENDING);
+ CASERET(DL_UNBOUND);
+ CASERET(DL_BIND_PENDING);
+ CASERET(DL_UNBIND_PENDING);
+ CASERET(DL_IDLE);
+ CASERET(DL_UDQOS_PENDING);
+ CASERET(DL_OUTCON_PENDING);
+ CASERET(DL_INCON_PENDING);
+ CASERET(DL_CONN_RES_PENDING);
+ CASERET(DL_DATAXFER);
+ CASERET(DL_USER_RESET_PENDING);
+ CASERET(DL_PROV_RESET_PENDING);
+ CASERET(DL_RESET_RES_PENDING);
+ CASERET(DL_DISCON8_PENDING);
+ CASERET(DL_DISCON9_PENDING);
+ CASERET(DL_DISCON11_PENDING);
+ CASERET(DL_DISCON12_PENDING);
+ CASERET(DL_DISCON13_PENDING);
+ CASERET(DL_SUBS_BIND_PND);
+ default:
+ (void) sprintf(statebuf, "unknown state 0x%x", state);
+ return (statebuf);
+ }
+}
+
+char*
+dlerrno(errno)
+u_long errno;
+{
+ static char errnobuf[80];
+
+ switch (errno) {
+ CASERET(DL_ACCESS);
+ CASERET(DL_BADADDR);
+ CASERET(DL_BADCORR);
+ CASERET(DL_BADDATA);
+ CASERET(DL_BADPPA);
+ CASERET(DL_BADPRIM);
+ CASERET(DL_BADQOSPARAM);
+ CASERET(DL_BADQOSTYPE);
+ CASERET(DL_BADSAP);
+ CASERET(DL_BADTOKEN);
+ CASERET(DL_BOUND);
+ CASERET(DL_INITFAILED);
+ CASERET(DL_NOADDR);
+ CASERET(DL_NOTINIT);
+ CASERET(DL_OUTSTATE);
+ CASERET(DL_SYSERR);
+ CASERET(DL_UNSUPPORTED);
+ CASERET(DL_UNDELIVERABLE);
+ CASERET(DL_NOTSUPPORTED);
+ CASERET(DL_TOOMANY);
+ CASERET(DL_NOTENAB);
+ CASERET(DL_BUSY);
+ CASERET(DL_NOAUTO);
+ CASERET(DL_NOXIDAUTO);
+ CASERET(DL_NOTESTAUTO);
+ CASERET(DL_XIDAUTO);
+ CASERET(DL_TESTAUTO);
+ CASERET(DL_PENDING);
+
+ default:
+ (void) sprintf(errnobuf, "unknown dlpi errno 0x%x", errno);
+ return (errnobuf);
+ }
+}
+
+char*
+dlpromisclevel(level)
+u_long level;
+{
+ static char levelbuf[80];
+
+ switch (level) {
+ CASERET(DL_PROMISC_PHYS);
+ CASERET(DL_PROMISC_SAP);
+ CASERET(DL_PROMISC_MULTI);
+ default:
+ (void) sprintf(levelbuf, "unknown promisc level 0x%x", level);
+ return (levelbuf);
+ }
+}
+
+char*
+dlservicemode(servicemode)
+u_long servicemode;
+{
+ static char servicemodebuf[80];
+
+ switch (servicemode) {
+ CASERET(DL_CODLS);
+ CASERET(DL_CLDLS);
+ CASERET(DL_CODLS|DL_CLDLS);
+ default:
+ (void) sprintf(servicemodebuf,
+ "unknown provider service mode 0x%x", servicemode);
+ return (servicemodebuf);
+ }
+}
+
+char*
+dlstyle(style)
+long style;
+{
+ static char stylebuf[80];
+
+ switch (style) {
+ CASERET(DL_STYLE1);
+ CASERET(DL_STYLE2);
+ default:
+ (void) sprintf(stylebuf, "unknown provider style 0x%x", style);
+ return (stylebuf);
+ }
+}
+
+char*
+dlmactype(media)
+u_long media;
+{
+ static char mediabuf[80];
+
+ switch (media) {
+ CASERET(DL_CSMACD);
+ CASERET(DL_TPB);
+ CASERET(DL_TPR);
+ CASERET(DL_METRO);
+ CASERET(DL_ETHER);
+ CASERET(DL_HDLC);
+ CASERET(DL_CHAR);
+ CASERET(DL_CTCA);
+ default:
+ (void) sprintf(mediabuf, "unknown media type 0x%x", media);
+ return (mediabuf);
+ }
+}
+
+/*VARARGS1*/
+err(fmt, a1, a2, a3, a4)
+char *fmt;
+char *a1, *a2, *a3, *a4;
+{
+ (void) fprintf(stderr, fmt, a1, a2, a3, a4);
+ (void) fprintf(stderr, "\n");
+ (void) exit(1);
+}
+
+syserr(s)
+char *s;
+{
+ (void) perror(s);
+ exit(1);
+}
+
+strioctl(fd, cmd, timout, len, dp)
+int fd;
+int cmd;
+int timout;
+int len;
+char *dp;
+{
+ struct strioctl sioc;
+ int rc;
+
+ sioc.ic_cmd = cmd;
+ sioc.ic_timout = timout;
+ sioc.ic_len = len;
+ sioc.ic_dp = dp;
+ rc = ioctl(fd, I_STR, &sioc);
+
+ if (rc < 0)
+ return (rc);
+ else
+ return (sioc.ic_len);
+}
diff --git a/contrib/ipfilter/ipsend/dltest.h b/contrib/ipfilter/ipsend/dltest.h
new file mode 100644
index 000000000000..4c32c30eb1bc
--- /dev/null
+++ b/contrib/ipfilter/ipsend/dltest.h
@@ -0,0 +1,32 @@
+/*
+ * Common DLPI Test Suite header file
+ *
+ */
+
+/*
+ * Maximum control/data buffer size (in long's !!) for getmsg().
+ */
+#define MAXDLBUF 8192
+
+/*
+ * Maximum number of seconds we'll wait for any
+ * particular DLPI acknowledgment from the provider
+ * after issuing a request.
+ */
+#define MAXWAIT 15
+
+/*
+ * Maximum address buffer length.
+ */
+#define MAXDLADDR 1024
+
+
+/*
+ * Handy macro.
+ */
+#define OFFADDR(s, n) (u_char*)((char*)(s) + (int)(n))
+
+/*
+ * externs go here
+ */
+extern void sigalrm();
diff --git a/contrib/ipfilter/ipsend/in_var.h b/contrib/ipfilter/ipsend/in_var.h
new file mode 100644
index 000000000000..63980ef304e3
--- /dev/null
+++ b/contrib/ipfilter/ipsend/in_var.h
@@ -0,0 +1,177 @@
+/* @(#)in_var.h 1.3 88/08/19 SMI; from UCB 7.1 6/5/86 */
+
+/*
+ * Copyright (c) 1985, 1986 Regents of the University of California.
+ * All rights reserved. The Berkeley software License Agreement
+ * specifies the terms and conditions for redistribution.
+ */
+
+/*
+ * Interface address, Internet version. One of these structures
+ * is allocated for each interface with an Internet address.
+ * The ifaddr structure contains the protocol-independent part
+ * of the structure and is assumed to be first.
+ */
+
+#ifndef _netinet_in_var_h
+#define _netinet_in_var_h
+
+struct in_ifaddr {
+ struct ifaddr ia_ifa; /* protocol-independent info */
+#define ia_addr ia_ifa.ifa_addr
+#define ia_broadaddr ia_ifa.ifa_broadaddr
+#define ia_dstaddr ia_ifa.ifa_dstaddr
+#define ia_ifp ia_ifa.ifa_ifp
+ u_long ia_net; /* network number of interface */
+ u_long ia_netmask; /* mask of net part */
+ u_long ia_subnet; /* subnet number, including net */
+ u_long ia_subnetmask; /* mask of net + subnet */
+ struct in_addr ia_netbroadcast; /* broadcast addr for (logical) net */
+ int ia_flags;
+ struct in_ifaddr *ia_next; /* next in list of internet addresses */
+ struct in_multi *ia_multiaddrs;/* list of multicast addresses */
+};
+/*
+ * Given a pointer to an in_ifaddr (ifaddr),
+ * return a pointer to the addr as a sockadd_in.
+ */
+#define IA_SIN(ia) ((struct sockaddr_in *)(&((struct in_ifaddr *)ia)->ia_addr))
+/*
+ * ia_flags
+ */
+#define IFA_ROUTE 0x01 /* routing entry installed */
+
+#ifdef KERNEL
+struct in_ifaddr *in_ifaddr;
+struct in_ifaddr *in_iaonnetof();
+struct ifqueue ipintrq; /* ip packet input queue */
+#endif
+
+#ifdef KERNEL
+/*
+ * Macro for finding the interface (ifnet structure) corresponding to one
+ * of our IP addresses.
+ */
+#define INADDR_TO_IFP(addr, ifp) \
+ /* struct in_addr addr; */ \
+ /* struct ifnet *ifp; */ \
+{ \
+ register struct in_ifaddr *ia; \
+ \
+ for (ia = in_ifaddr; \
+ ia != NULL && IA_SIN(ia)->sin_addr.s_addr != (addr).s_addr; \
+ ia = ia->ia_next); \
+ (ifp) = (ia == NULL) ? NULL : ia->ia_ifp; \
+}
+
+/*
+ * Macro for finding the internet address structure (in_ifaddr) corresponding
+ * to a given interface (ifnet structure).
+ */
+#define IFP_TO_IA(ifp, ia) \
+ /* struct ifnet *ifp; */ \
+ /* struct in_ifaddr *ia; */ \
+{ \
+ for ((ia) = in_ifaddr; \
+ (ia) != NULL && (ia)->ia_ifp != (ifp); \
+ (ia) = (ia)->ia_next); \
+}
+#endif KERNEL
+
+/*
+ * Per-interface router version information is kept in this list.
+ * This information should be part of the ifnet structure but we don't wish
+ * to change that - as it might break a number of things
+ */
+
+struct router_info {
+ struct ifnet *ifp;
+ int type; /* type of router which is querier on this interface */
+ int time; /* # of slow timeouts since last old query */
+ struct router_info *next;
+};
+
+/*
+ * Internet multicast address structure. There is one of these for each IP
+ * multicast group to which this host belongs on a given network interface.
+ * They are kept in a linked list, rooted in the interface's in_ifaddr
+ * structure.
+ */
+
+struct in_multi {
+ struct in_addr inm_addr; /* IP multicast address */
+ struct ifnet *inm_ifp; /* back pointer to ifnet */
+ struct in_ifaddr *inm_ia; /* back pointer to in_ifaddr */
+ u_int inm_refcount;/* no. membership claims by sockets */
+ u_int inm_timer; /* IGMP membership report timer */
+ struct in_multi *inm_next; /* ptr to next multicast address */
+ u_int inm_state; /* state of the membership */
+ struct router_info *inm_rti; /* router info*/
+};
+
+#ifdef KERNEL
+/*
+ * Structure used by macros below to remember position when stepping through
+ * all of the in_multi records.
+ */
+struct in_multistep {
+ struct in_ifaddr *i_ia;
+ struct in_multi *i_inm;
+};
+
+/*
+ * Macro for looking up the in_multi record for a given IP multicast address
+ * on a given interface. If no matching record is found, "inm" returns NULL.
+ */
+#define IN_LOOKUP_MULTI(addr, ifp, inm) \
+ /* struct in_addr addr; */ \
+ /* struct ifnet *ifp; */ \
+ /* struct in_multi *inm; */ \
+{ \
+ register struct in_ifaddr *ia; \
+ \
+ IFP_TO_IA((ifp), ia); \
+ if (ia == NULL) \
+ (inm) = NULL; \
+ else \
+ for ((inm) = ia->ia_multiaddrs; \
+ (inm) != NULL && (inm)->inm_addr.s_addr != (addr).s_addr; \
+ (inm) = inm->inm_next); \
+}
+
+/*
+ * Macro to step through all of the in_multi records, one at a time.
+ * The current position is remembered in "step", which the caller must
+ * provide. IN_FIRST_MULTI(), below, must be called to initialize "step"
+ * and get the first record. Both macros return a NULL "inm" when there
+ * are no remaining records.
+ */
+#define IN_NEXT_MULTI(step, inm) \
+ /* struct in_multistep step; */ \
+ /* struct in_multi *inm; */ \
+{ \
+ if (((inm) = (step).i_inm) != NULL) { \
+ (step).i_inm = (inm)->inm_next; \
+ } \
+ else while ((step).i_ia != NULL) { \
+ (inm) = (step).i_ia->ia_multiaddrs; \
+ (step).i_ia = (step).i_ia->ia_next; \
+ if ((inm) != NULL) { \
+ (step).i_inm = (inm)->inm_next; \
+ break; \
+ } \
+ } \
+}
+
+#define IN_FIRST_MULTI(step, inm) \
+ /* struct in_multistep step; */ \
+ /* struct in_multi *inm; */ \
+{ \
+ (step).i_ia = in_ifaddr; \
+ (step).i_inm = NULL; \
+ IN_NEXT_MULTI((step), (inm)); \
+}
+
+struct in_multi *in_addmulti();
+#endif KERNEL
+#endif /*!_netinet_in_var_h*/
diff --git a/contrib/ipfilter/ipsend/ip.c b/contrib/ipfilter/ipsend/ip.c
new file mode 100644
index 000000000000..2c7f7ff3e019
--- /dev/null
+++ b/contrib/ipfilter/ipsend/ip.c
@@ -0,0 +1,346 @@
+/*
+ * ip.c (C) 1995 Darren Reed
+ *
+ * The author provides this program as-is, with no gaurantee for its
+ * suitability for any specific purpose. The author takes no responsibility
+ * for the misuse/abuse of this program and provides it for the sole purpose
+ * of testing packet filter policies. This file maybe distributed freely
+ * providing it is not modified and that this notice remains in tact.
+ */
+#if !defined(lint) && defined(LIBC_SCCS)
+static char sccsid[] = "%W% %G% (C)1995";
+#endif
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/types.h>
+#include <netinet/in_systm.h>
+#include <sys/socket.h>
+#include <net/if.h>
+#include <netinet/in.h>
+#include <netinet/ip.h>
+#include <netinet/tcp.h>
+#include <netinet/udp.h>
+#include <netinet/ip_icmp.h>
+#ifndef linux
+#include <netinet/if_ether.h>
+#include <netinet/ip_var.h>
+#include <netinet/tcpip.h>
+#endif
+#include "ip_compat.h"
+#ifdef linux
+#include "tcpip.h"
+#endif
+
+
+static char *ipbuf = NULL, *ethbuf = NULL;
+
+extern int arp(), sendip();
+
+u_short chksum(buf,len)
+u_short *buf;
+int len;
+{
+ u_long sum = 0;
+ int nwords = len >> 1;
+
+ for(; nwords > 0; nwords--)
+ sum += *buf++;
+ sum = (sum>>16) + (sum & 0xffff);
+ sum += (sum >>16);
+ return (~sum);
+}
+
+
+int send_ether(nfd, buf, len, gwip)
+int nfd, len;
+char *buf;
+struct in_addr gwip;
+{
+ static struct in_addr last_gw;
+ static char last_arp[6] = { 0, 0, 0, 0, 0, 0};
+ ether_header_t *eh;
+ char *s;
+ int err;
+
+ if (!ethbuf)
+ ethbuf = (char *)calloc(1, 65536+1024);
+ s = ethbuf;
+ eh = (ether_header_t *)s;
+
+ bcopy((char *)buf, s + sizeof(*eh), len);
+ if (gwip.s_addr == last_gw.s_addr)
+ bcopy(last_arp, (char *)&eh->ether_dhost, 6);
+ else if (arp((char *)&gwip, &eh->ether_dhost) == -1)
+ {
+ perror("arp");
+ return -2;
+ }
+ eh->ether_type = ETHERTYPE_IP;
+ last_gw.s_addr = gwip.s_addr;
+ err = sendip(nfd, s, sizeof(*eh) + len);
+ return err;
+}
+
+
+/*
+ */
+int send_ip(nfd, mtu, ip, gwip, frag)
+int nfd, mtu;
+ip_t *ip;
+struct in_addr gwip;
+int frag;
+{
+ static struct in_addr last_gw;
+ static char last_arp[6] = { 0, 0, 0, 0, 0, 0};
+ static u_short id = 0;
+ ether_header_t *eh;
+ ip_t ipsv;
+ int err;
+
+ if (!ipbuf)
+ ipbuf = (char *)malloc(65536);
+ eh = (ether_header_t *)ipbuf;
+
+ bzero((char *)&eh->ether_shost, sizeof(eh->ether_shost));
+ if (last_gw.s_addr && (gwip.s_addr == last_gw.s_addr))
+ bcopy(last_arp, (char *)&eh->ether_dhost, 6);
+ else if (arp((char *)&gwip, &eh->ether_dhost) == -1)
+ {
+ perror("arp");
+ return -2;
+ }
+ bcopy((char *)&eh->ether_dhost, last_arp, sizeof(last_arp));
+ eh->ether_type = ETHERTYPE_IP;
+
+ bcopy((char *)ip, (char *)&ipsv, sizeof(*ip));
+ last_gw.s_addr = gwip.s_addr;
+ ip->ip_len = htons(ip->ip_len);
+ ip->ip_off = htons(ip->ip_off);
+ if (!ip->ip_v)
+ ip->ip_v = IPVERSION;
+ if (!ip->ip_id)
+ ip->ip_id = htons(id++);
+ if (!ip->ip_ttl)
+ ip->ip_ttl = 60;
+
+ if (!frag || (sizeof(*eh) + ntohs(ip->ip_len) < mtu))
+ {
+ ip->ip_sum = 0;
+ ip->ip_sum = chksum(ip, ip->ip_hl << 2);
+
+ bcopy((char *)ip, ipbuf + sizeof(*eh), ntohs(ip->ip_len));
+ err = sendip(nfd, ipbuf, sizeof(*eh) + ntohs(ip->ip_len));
+ }
+ else
+ {
+ /*
+ * Actually, this is bogus because we're putting all IP
+ * options in every packet, which isn't always what should be
+ * done. Will do for now.
+ */
+ ether_header_t eth;
+ char optcpy[48], ol;
+ char *s;
+ int i, iplen, sent = 0, ts, hlen, olen;
+
+ hlen = ip->ip_hl << 2;
+ if (mtu < (hlen + 8)) {
+ fprintf(stderr, "mtu (%d) < ip header size (%d) + 8\n",
+ mtu, hlen);
+ fprintf(stderr, "can't fragment data\n");
+ return -2;
+ }
+ ol = (ip->ip_hl << 2) - sizeof(*ip);
+ for (i = 0, s = (char*)(ip + 1); ol > 0; )
+ if (*s == IPOPT_EOL) {
+ optcpy[i++] = *s;
+ break;
+ } else if (*s == IPOPT_NOP) {
+ s++;
+ ol--;
+ } else
+ {
+ olen = (int)(*(u_char *)(s + 1));
+ ol -= olen;
+ if (IPOPT_COPIED(*s))
+ {
+ bcopy(s, optcpy + i, olen);
+ i += olen;
+ s += olen;
+ }
+ }
+ if (i)
+ {
+ /*
+ * pad out
+ */
+ while ((i & 3) && (i & 3) != 3)
+ optcpy[i++] = IPOPT_NOP;
+ if ((i & 3) == 3)
+ optcpy[i++] = IPOPT_EOL;
+ }
+
+ bcopy((char *)eh, (char *)&eth, sizeof(eth));
+ s = (char *)ip + hlen;
+ iplen = ntohs(ip->ip_len) - hlen;
+ ip->ip_off |= htons(IP_MF);
+
+ while (1)
+ {
+ if ((sent + (mtu - hlen)) >= iplen)
+ {
+ ip->ip_off ^= htons(IP_MF);
+ ts = iplen - sent;
+ }
+ else
+ ts = (mtu - hlen);
+ ip->ip_off &= htons(0xe000);
+ ip->ip_off |= htons(sent >> 3);
+ ts += hlen;
+ ip->ip_len = htons(ts);
+ ip->ip_sum = 0;
+ ip->ip_sum = chksum(ip, hlen);
+ bcopy((char *)ip, ipbuf + sizeof(*eh), hlen);
+ bcopy(s + sent, ipbuf + sizeof(*eh) + hlen, ts - hlen);
+ err = sendip(nfd, ipbuf, sizeof(*eh) + ts);
+
+ bcopy((char *)&eth, ipbuf, sizeof(eth));
+ sent += (ts - hlen);
+ if (!(ntohs(ip->ip_off) & IP_MF))
+ break;
+ else if (!(ip->ip_off & htons(0x1fff)))
+ {
+ hlen = i + sizeof(*ip);
+ ip->ip_hl = (sizeof(*ip) + i) >> 2;
+ bcopy(optcpy, (char *)(ip + 1), i);
+ }
+ }
+ }
+
+ bcopy((char *)&ipsv, (char *)ip, sizeof(*ip));
+ return err;
+}
+
+
+/*
+ * send a tcp packet.
+ */
+int send_tcp(nfd, mtu, ip, gwip)
+int nfd, mtu;
+ip_t *ip;
+struct in_addr gwip;
+{
+ static tcp_seq iss = 2;
+ struct tcpiphdr *ti;
+ int thlen, i;
+ u_long lbuf[20];
+
+ ti = (struct tcpiphdr *)lbuf;
+ bzero((char *)ti, sizeof(*ti));
+ thlen = sizeof(tcphdr_t);
+ ip->ip_p = IPPROTO_TCP;
+ ti->ti_pr = ip->ip_p;
+ ti->ti_src = ip->ip_src;
+ ti->ti_dst = ip->ip_dst;
+ bcopy((char *)ip + (ip->ip_hl << 2),
+ (char *)&ti->ti_sport, sizeof(tcphdr_t));
+
+ if (!ti->ti_win)
+ ti->ti_win = htons(4096);
+ if (!ti->ti_seq)
+ ti->ti_seq = htonl(iss);
+ iss += 64;
+
+ if ((ti->ti_flags == TH_SYN) && !ip->ip_off)
+ {
+ ip = (ip_t *)realloc((char *)ip, ntohs(ip->ip_len) + 4);
+ i = sizeof(struct tcpiphdr) / sizeof(long);
+ lbuf[i] = htonl(0x020405b4);
+ bcopy((char *)(lbuf + i), (char*)ip + ntohs(ip->ip_len),
+ sizeof(u_long));
+ thlen += 4;
+ }
+ if (!ti->ti_off)
+ ti->ti_off = thlen >> 2;
+ ti->ti_len = htons(thlen);
+ ip->ip_len = (ip->ip_hl << 2) + thlen;
+ ti->ti_sum = 0;
+ ti->ti_sum = chksum(ti, thlen + sizeof(ip_t));
+
+ bcopy((char *)&ti->ti_sport,
+ (char *)ip + (ip->ip_hl << 2), thlen);
+ return send_ip(nfd, mtu, ip, gwip, 1);
+}
+
+
+/*
+ * send a udp packet.
+ */
+int send_udp(nfd, mtu, ip, gwip)
+int nfd, mtu;
+ip_t *ip;
+struct in_addr gwip;
+{
+ struct tcpiphdr *ti;
+ int thlen;
+ u_long lbuf[20];
+
+ ti = (struct tcpiphdr *)lbuf;
+ bzero((char *)ti, sizeof(*ti));
+ thlen = sizeof(udphdr_t);
+ ti->ti_pr = ip->ip_p;
+ ti->ti_src = ip->ip_src;
+ ti->ti_dst = ip->ip_dst;
+ bcopy((char *)ip + (ip->ip_hl << 2),
+ (char *)&ti->ti_sport, sizeof(udphdr_t));
+
+ ti->ti_len = htons(thlen);
+ ip->ip_len = (ip->ip_hl << 2) + thlen;
+ ti->ti_sum = 0;
+ ti->ti_sum = chksum(ti, thlen + sizeof(ip_t));
+
+ bcopy((char *)&ti->ti_sport,
+ (char *)ip + (ip->ip_hl << 2), sizeof(udphdr_t));
+ return send_ip(nfd, mtu, ip, gwip, 1);
+}
+
+
+/*
+ * send an icmp packet.
+ */
+int send_icmp(nfd, mtu, ip, gwip)
+int nfd, mtu;
+ip_t *ip;
+struct in_addr gwip;
+{
+ struct icmp *ic;
+
+ ic = (struct icmp *)((char *)ip + (ip->ip_hl << 2));
+
+ ic->icmp_cksum = 0;
+ ic->icmp_cksum = chksum((char *)ic, sizeof(struct icmp));
+
+ return send_ip(nfd, mtu, ip, gwip, 1);
+}
+
+
+int send_packet(nfd, mtu, ip, gwip)
+int nfd, mtu;
+ip_t *ip;
+struct in_addr gwip;
+{
+ switch (ip->ip_p)
+ {
+ case IPPROTO_TCP :
+ return send_tcp(nfd, mtu, ip, gwip);
+ case IPPROTO_UDP :
+ return send_udp(nfd, mtu, ip, gwip);
+ case IPPROTO_ICMP :
+ return send_icmp(nfd, mtu, ip, gwip);
+ default :
+ return send_ip(nfd, mtu, ip, gwip, 1);
+ }
+}
diff --git a/contrib/ipfilter/ipsend/ip_compat.h b/contrib/ipfilter/ipsend/ip_compat.h
new file mode 100644
index 000000000000..c38fa59ed3c7
--- /dev/null
+++ b/contrib/ipfilter/ipsend/ip_compat.h
@@ -0,0 +1,242 @@
+/*
+ * (C)opyright 1995 by Darren Reed.
+ *
+ * This code may be freely distributed as long as it retains this notice
+ * and is not changed in any way. The author accepts no responsibility
+ * for the use of this software. I hate legaleese, don't you ?
+ *
+ * @(#)ip_compat.h 1.2 12/7/95
+ */
+
+/*
+ * These #ifdef's are here mainly for linux, but who knows, they may
+ * not be in other places or maybe one day linux will grow up and some
+ * of these will turn up there too.
+ */
+#ifndef ICMP_UNREACH
+# define ICMP_UNREACH ICMP_DEST_UNREACH
+#endif
+#ifndef ICMP_SOURCEQUENCH
+# define ICMP_SOURCEQUENCH ICMP_SOURCE_QUENCH
+#endif
+#ifndef ICMP_TIMXCEED
+# define ICMP_TIMXCEED ICMP_TIME_EXCEEDED
+#endif
+#ifndef ICMP_PARAMPROB
+# define ICMP_PARAMPROB ICMP_PARAMETERPROB
+#endif
+#ifndef IPVERSION
+# define IPVERSION 4
+#endif
+#ifndef IPOPT_MINOFF
+# define IPOPT_MINOFF 4
+#endif
+#ifndef IPOPT_COPIED
+# define IPOPT_COPIED(x) ((x)&0x80)
+#endif
+#ifndef IPOPT_EOL
+# define IPOPT_EOL 0
+#endif
+#ifndef IPOPT_NOP
+# define IPOPT_NOP 1
+#endif
+#ifndef IP_MF
+# define IP_MF ((u_short)0x2000)
+#endif
+#ifndef ETHERTYPE_IP
+# define ETHERTYPE_IP ((u_short)0x0800)
+#endif
+#ifndef TH_FIN
+# define TH_FIN 0x01
+#endif
+#ifndef TH_SYN
+# define TH_SYN 0x02
+#endif
+#ifndef TH_RST
+# define TH_RST 0x04
+#endif
+#ifndef TH_PUSH
+# define TH_PUSH 0x08
+#endif
+#ifndef TH_ACK
+# define TH_ACK 0x10
+#endif
+#ifndef TH_URG
+# define TH_URG 0x20
+#endif
+#ifndef IPOPT_EOL
+# define IPOPT_EOL 0
+#endif
+#ifndef IPOPT_NOP
+# define IPOPT_NOP 1
+#endif
+#ifndef IPOPT_RR
+# define IPOPT_RR 7
+#endif
+#ifndef IPOPT_TS
+# define IPOPT_TS 68
+#endif
+#ifndef IPOPT_SECURITY
+# define IPOPT_SECURITY 130
+#endif
+#ifndef IPOPT_LSRR
+# define IPOPT_LSRR 131
+#endif
+#ifndef IPOPT_SATID
+# define IPOPT_SATID 136
+#endif
+#ifndef IPOPT_SSRR
+# define IPOPT_SSRR 137
+#endif
+#ifndef IPOPT_SECUR_UNCLASS
+# define IPOPT_SECUR_UNCLASS ((u_short)0x0000)
+#endif
+#ifndef IPOPT_SECUR_CONFID
+# define IPOPT_SECUR_CONFID ((u_short)0xf135)
+#endif
+#ifndef IPOPT_SECUR_EFTO
+# define IPOPT_SECUR_EFTO ((u_short)0x789a)
+#endif
+#ifndef IPOPT_SECUR_MMMM
+# define IPOPT_SECUR_MMMM ((u_short)0xbc4d)
+#endif
+#ifndef IPOPT_SECUR_RESTR
+# define IPOPT_SECUR_RESTR ((u_short)0xaf13)
+#endif
+#ifndef IPOPT_SECUR_SECRET
+# define IPOPT_SECUR_SECRET ((u_short)0xd788)
+#endif
+#ifndef IPOPT_SECUR_TOPSECRET
+# define IPOPT_SECUR_TOPSECRET ((u_short)0x6bc5)
+#endif
+
+#ifdef linux
+# if LINUX < 0200
+# define icmp icmphdr
+# define icmp_type type
+# define icmp_code code
+# endif
+
+/*
+ * From /usr/include/netinet/ip_var.h
+ * !%@#!$@# linux...
+ */
+struct ipovly {
+ caddr_t ih_next, ih_prev; /* for protocol sequence q's */
+ u_char ih_x1; /* (unused) */
+ u_char ih_pr; /* protocol */
+ short ih_len; /* protocol length */
+ struct in_addr ih_src; /* source internet address */
+ struct in_addr ih_dst; /* destination internet address */
+};
+
+typedef struct {
+ __u16 th_sport;
+ __u16 th_dport;
+ __u32 th_seq;
+ __u32 th_ack;
+# if defined(__i386__) || defined(__MIPSEL__) || defined(__alpha__) ||\
+ defined(vax)
+ __u8 th_res:4;
+ __u8 th_off:4;
+#else
+ __u8 th_off:4;
+ __u8 th_res:4;
+#endif
+ __u8 th_flags;
+ __u16 th_win;
+ __u16 th_sum;
+ __u16 th_urp;
+} tcphdr_t;
+
+typedef struct {
+ __u16 uh_sport;
+ __u16 uh_dport;
+ __s16 uh_ulen;
+ __u16 uh_sum;
+} udphdr_t;
+
+typedef struct {
+# if defined(__i386__) || defined(__MIPSEL__) || defined(__alpha__) ||\
+ defined(vax)
+ __u8 ip_hl:4;
+ __u8 ip_v:4;
+# else
+ __u8 ip_hl:4;
+ __u8 ip_v:4;
+# endif
+ __u8 ip_tos;
+ __u16 ip_len;
+ __u16 ip_id;
+ __u16 ip_off;
+ __u8 ip_ttl;
+ __u8 ip_p;
+ __u16 ip_sum;
+ struct in_addr ip_src;
+ struct in_addr ip_dst;
+} ip_t;
+
+typedef struct {
+ __u8 ether_dhost[6];
+ __u8 ether_shost[6];
+ __u16 ether_type;
+} ether_header_t;
+
+typedef struct icmp {
+ u_char icmp_type; /* type of message, see below */
+ u_char icmp_code; /* type sub code */
+ u_short icmp_cksum; /* ones complement cksum of struct */
+ union {
+ u_char ih_pptr; /* ICMP_PARAMPROB */
+ struct in_addr ih_gwaddr; /* ICMP_REDIRECT */
+ struct ih_idseq {
+ n_short icd_id;
+ n_short icd_seq;
+ } ih_idseq;
+ int ih_void;
+ } icmp_hun;
+#define icmp_pptr icmp_hun.ih_pptr
+#define icmp_gwaddr icmp_hun.ih_gwaddr
+#define icmp_id icmp_hun.ih_idseq.icd_id
+#define icmp_seq icmp_hun.ih_idseq.icd_seq
+#define icmp_void icmp_hun.ih_void
+ union {
+ struct id_ts {
+ n_time its_otime;
+ n_time its_rtime;
+ n_time its_ttime;
+ } id_ts;
+ struct id_ip {
+ ip_t idi_ip;
+ /* options and then 64 bits of data */
+ } id_ip;
+ u_long id_mask;
+ char id_data[1];
+ } icmp_dun;
+#define icmp_otime icmp_dun.id_ts.its_otime
+#define icmp_rtime icmp_dun.id_ts.its_rtime
+#define icmp_ttime icmp_dun.id_ts.its_ttime
+#define icmp_ip icmp_dun.id_ip.idi_ip
+#define icmp_mask icmp_dun.id_mask
+#define icmp_data icmp_dun.id_data
+} icmphdr_t;
+
+# define bcopy(a,b,c) memmove(b,a,c)
+# define bcmp(a,b,c) memcmp(a,b,c)
+
+# define ifnet device
+
+#else
+
+typedef struct udphdr udphdr_t;
+typedef struct tcphdr tcphdr_t;
+typedef struct ip ip_t;
+typedef struct ether_header ether_header_t;
+
+#endif
+
+#if defined(__SVR4) || defined(__svr4__)
+# define bcopy(a,b,c) memmove(b,a,c)
+# define bcmp(a,b,c) memcmp(a,b,c)
+# define bzero(a,b) memset(a,0,b)
+#endif
diff --git a/contrib/ipfilter/ipsend/ip_var.h b/contrib/ipfilter/ipsend/ip_var.h
new file mode 100644
index 000000000000..92eb38a0befc
--- /dev/null
+++ b/contrib/ipfilter/ipsend/ip_var.h
@@ -0,0 +1,123 @@
+/* @(#)ip_var.h 1.11 88/08/19 SMI; from UCB 7.1 6/5/86 */
+
+/*
+ * Copyright (c) 1982, 1986 Regents of the University of California.
+ * All rights reserved. The Berkeley software License Agreement
+ * specifies the terms and conditions for redistribution.
+ */
+
+/*
+ * Overlay for ip header used by other protocols (tcp, udp).
+ */
+
+#ifndef _netinet_ip_var_h
+#define _netinet_ip_var_h
+
+struct ipovly {
+ caddr_t ih_next, ih_prev; /* for protocol sequence q's */
+ u_char ih_x1; /* (unused) */
+ u_char ih_pr; /* protocol */
+ short ih_len; /* protocol length */
+ struct in_addr ih_src; /* source internet address */
+ struct in_addr ih_dst; /* destination internet address */
+};
+
+/*
+ * Ip reassembly queue structure. Each fragment
+ * being reassembled is attached to one of these structures.
+ * They are timed out after ipq_ttl drops to 0, and may also
+ * be reclaimed if memory becomes tight.
+ */
+struct ipq {
+ struct ipq *next,*prev; /* to other reass headers */
+ u_char ipq_ttl; /* time for reass q to live */
+ u_char ipq_p; /* protocol of this fragment */
+ u_short ipq_id; /* sequence id for reassembly */
+ struct ipasfrag *ipq_next,*ipq_prev;
+ /* to ip headers of fragments */
+ struct in_addr ipq_src,ipq_dst;
+};
+
+/*
+ * Ip header, when holding a fragment.
+ *
+ * Note: ipf_next must be at same offset as ipq_next above
+ */
+struct ipasfrag {
+#if defined(vax) || defined(i386)
+ u_char ip_hl:4,
+ ip_v:4;
+#endif
+#if defined(mc68000) || defined(sparc)
+ u_char ip_v:4,
+ ip_hl:4;
+#endif
+ u_char ipf_mff; /* copied from (ip_off&IP_MF) */
+ short ip_len;
+ u_short ip_id;
+ short ip_off;
+ u_char ip_ttl;
+ u_char ip_p;
+ u_short ip_sum;
+ struct ipasfrag *ipf_next; /* next fragment */
+ struct ipasfrag *ipf_prev; /* previous fragment */
+};
+
+/*
+ * Structure stored in mbuf in inpcb.ip_options
+ * and passed to ip_output when ip options are in use.
+ * The actual length of the options (including ipopt_dst)
+ * is in m_len.
+ */
+#define MAX_IPOPTLEN 40
+
+struct ipoption {
+ struct in_addr ipopt_dst; /* first-hop dst if source routed */
+ char ipopt_list[MAX_IPOPTLEN]; /* options proper */
+};
+
+/*
+ * Structure stored in an mbuf attached to inpcb.ip_moptions and
+ * passed to ip_output when IP multicast options are in use.
+ */
+struct ip_moptions {
+ struct ifnet *imo_multicast_ifp; /* ifp for outgoing multicasts */
+ u_char imo_multicast_ttl; /* TTL for outgoing multicasts */
+ u_char imo_multicast_loop; /* 1 => hear sends if a member */
+ u_short imo_num_memberships;/* no. memberships this socket */
+ struct in_multi *imo_membership[IP_MAX_MEMBERSHIPS];
+#ifdef RSVP_ISI
+ long imo_multicast_vif; /* vif for outgoing multicasts */
+#endif /* RSVP_ISI */
+};
+
+struct ipstat {
+ long ips_total; /* total packets received */
+ long ips_badsum; /* checksum bad */
+ long ips_tooshort; /* packet too short */
+ long ips_toosmall; /* not enough data */
+ long ips_badhlen; /* ip header length < data size */
+ long ips_badlen; /* ip length < ip header length */
+ long ips_fragments; /* fragments received */
+ long ips_fragdropped; /* frags dropped (dups, out of space) */
+ long ips_fragtimeout; /* fragments timed out */
+ long ips_forward; /* packets forwarded */
+ long ips_cantforward; /* packets rcvd for unreachable dest */
+ long ips_redirectsent; /* packets forwarded on same net */
+};
+
+#ifdef KERNEL
+/* flags passed to ip_output as last parameter */
+#define IP_FORWARDING 0x1 /* most of ip header exists */
+#define IP_MULTICASTOPTS 0x2 /* multicast opts present */
+#define IP_ROUTETOIF SO_DONTROUTE /* bypass routing tables */
+#define IP_ALLOWBROADCAST SO_BROADCAST /* can send broadcast packets */
+
+struct ipstat ipstat;
+struct ipq ipq; /* ip reass. queue */
+u_short ip_id; /* ip packet ctr, for ids */
+
+struct mbuf *ip_srcroute();
+#endif
+
+#endif /*!_netinet_ip_var_h*/
diff --git a/contrib/ipfilter/ipsend/ipresend.c b/contrib/ipfilter/ipsend/ipresend.c
new file mode 100644
index 000000000000..6fd91bf4ff10
--- /dev/null
+++ b/contrib/ipfilter/ipsend/ipresend.c
@@ -0,0 +1,165 @@
+/*
+ * ipsend.c (C) 1995 Darren Reed
+ *
+ * This was written to test what size TCP fragments would get through
+ * various TCP/IP packet filters, as used in IP firewalls. In certain
+ * conditions, enough of the TCP header is missing for unpredictable
+ * results unless the filter is aware that this can happen.
+ *
+ * The author provides this program as-is, with no gaurantee for its
+ * suitability for any specific purpose. The author takes no responsibility
+ * for the misuse/abuse of this program and provides it for the sole purpose
+ * of testing packet filter policies. This file maybe distributed freely
+ * providing it is not modified and that this notice remains in tact.
+ *
+ * This was written and tested (successfully) on SunOS 4.1.x.
+ */
+#if !defined(lint) && defined(LIBC_SCCS)
+static char sccsid[] = "%W% %G% (C)1995 Darren Reed";
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <netdb.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/tcp.h>
+#include <netinet/udp.h>
+#include <netinet/ip_icmp.h>
+#ifndef linux
+#include <netinet/ip_var.h>
+#include <netinet/tcpip.h>
+#endif
+#include "ip_compat.h"
+#ifdef linux
+#include <linux/sockios.h>
+#include "tcpip.h"
+#endif
+#include "ipt.h"
+
+
+extern char *optarg;
+extern int optind;
+#ifndef NO_IPF
+extern struct ipread snoop, pcap, etherf, iphex, tcpd, iptext;
+#endif
+extern int resolve(), ip_resend();
+
+int opts = 0;
+#ifndef DEFAULT_DEVICE
+# ifdef linux
+char default_device[] = "eth0";
+# else
+# ifdef sun
+char default_device[] = "le0";
+# else
+# ifdef ultrix
+char default_device[] = "ln0";
+# else
+# ifdef __bsdi__
+char default_device[] = "ef0";
+# else
+char default_device[] = "lan0";
+# endif
+# endif
+# endif
+# endif
+#else
+char default_device[] = DEFAULT_DEVICE;
+#endif
+
+
+void usage(prog)
+char *prog;
+{
+ fprintf(stderr, "Usage: %s [options] <-r filename|-R filename>\n\
+\t\t-r filename\tsnoop data file to resend\n\
+\t\t-R filename\tlibpcap data file to resend\n\
+\toptions:\n\
+\t\t-d device\tSend out on this device\n\
+\t\t-g gateway\tIP gateway to use if non-local dest.\n\
+\t\t-m mtu\t\tfake MTU to use when sending out\n\
+", prog);
+ exit(1);
+}
+
+
+int main(argc, argv)
+int argc;
+char **argv;
+{
+ struct in_addr gwip;
+ struct ipread *ipr = NULL;
+ char *name = argv[0], *gateway = NULL, *dev = NULL;
+ char c, *resend = NULL;
+ int mtu = 1500;
+
+ while ((c = getopt(argc, argv, "EHPSTXd:g:m:r:")) != -1)
+ switch (c)
+ {
+ case 'd' :
+ dev = optarg;
+ break;
+ case 'g' :
+ gateway = optarg;
+ break;
+ case 'm' :
+ mtu = atoi(optarg);
+ if (mtu < 28)
+ {
+ fprintf(stderr, "mtu must be > 28\n");
+ exit(1);
+ }
+ case 'r' :
+ resend = optarg;
+ break;
+#ifndef NO_IPF
+ case 'E' :
+ ipr = &etherf;
+ break;
+ case 'H' :
+ ipr = &iphex;
+ break;
+ case 'P' :
+ ipr = &pcap;
+ break;
+ case 'S' :
+ ipr = &snoop;
+ break;
+ case 'T' :
+ ipr = &tcpd;
+ break;
+ case 'X' :
+ ipr = &iptext;
+ break;
+#endif
+ default :
+ fprintf(stderr, "Unknown option \"%c\"\n", c);
+ usage(name);
+ }
+
+ if (!ipr || !resend)
+ usage(name);
+
+ gwip.s_addr = 0;
+ if (gateway && resolve(gateway, (char *)&gwip) == -1)
+ {
+ fprintf(stderr,"Cant resolve %s\n", gateway);
+ exit(2);
+ }
+
+ if (!dev)
+ dev = default_device;
+
+ printf("Device: %s\n", dev);
+ printf("Gateway: %s\n", inet_ntoa(gwip));
+ printf("mtu: %d\n", mtu);
+
+ return ip_resend(dev, mtu, ipr, gwip, resend);
+}
diff --git a/contrib/ipfilter/ipsend/ipsend.c b/contrib/ipfilter/ipsend/ipsend.c
new file mode 100644
index 000000000000..e45d3ee73adc
--- /dev/null
+++ b/contrib/ipfilter/ipsend/ipsend.c
@@ -0,0 +1,350 @@
+/*
+ * ipsend.c (C) 1995 Darren Reed
+ *
+ * This was written to test what size TCP fragments would get through
+ * various TCP/IP packet filters, as used in IP firewalls. In certain
+ * conditions, enough of the TCP header is missing for unpredictable
+ * results unless the filter is aware that this can happen.
+ *
+ * The author provides this program as-is, with no gaurantee for its
+ * suitability for any specific purpose. The author takes no responsibility
+ * for the misuse/abuse of this program and provides it for the sole purpose
+ * of testing packet filter policies. This file maybe distributed freely
+ * providing it is not modified and that this notice remains in tact.
+ *
+ * This was written and tested (successfully) on SunOS 4.1.x.
+ */
+#if !defined(lint) && defined(LIBC_SCCS)
+static char sccsid[] = "@(#)ipsend.c 1.5 12/10/95 (C)1995 Darren Reed";
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <netdb.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/tcp.h>
+#include <netinet/udp.h>
+#include <netinet/ip_icmp.h>
+#ifndef linux
+#include <netinet/ip_var.h>
+#include <netinet/tcpip.h>
+#endif
+#include "ip_compat.h"
+#ifdef linux
+#include <linux/sockios.h>
+#include "tcpip.h"
+#endif
+#include "ipt.h"
+
+
+extern char *optarg;
+extern int optind;
+
+extern int resolve(), optname(), initdevice(), send_packet();
+
+char options[68];
+#ifdef linux
+char default_device[] = "eth0";
+#else
+# ifdef sun
+char default_device[] = "le0";
+# else
+# ifdef ultrix
+char default_device[] = "ln0";
+# else
+# ifdef __bsdi__
+char default_device[] = "ef0";
+# else
+char default_device[] = "lan0";
+# endif
+# endif
+# endif
+#endif
+
+
+void usage(prog)
+char *prog;
+{
+ fprintf(stderr, "Usage: %s [options] dest [flags]\n\
+\toptions:\n\
+\t\t-d device\tSend out on this device\n\
+\t\t-f fragflags\tcan set IP_MF or IP_DF\n\
+\t\t-g gateway\tIP gateway to use if non-local dest.\n\
+\t\t-I code,type[,gw[,dst[,src]]]\tSet ICMP protocol\n\
+\t\t-m mtu\t\tfake MTU to use when sending out\n\
+\t\t-P protocol\tSet protocol by name\n\
+\t\t-s src\t\tsource address for IP packet\n\
+\t\t-T\t\tSet TCP protocol\n\
+\t\t-t port\t\tdestination port\n\
+\t\t-U\t\tSet UDP protocol\n\
+", prog);
+ exit(1);
+}
+
+
+void do_icmp(ip, args)
+ip_t *ip;
+char *args;
+{
+ struct icmp *ic;
+ char *s;
+
+ ip->ip_p = IPPROTO_ICMP;
+ ip->ip_len += sizeof(*ic);
+ ic = (struct icmp *)(ip + 1);
+ bzero((char *)ic, sizeof(*ic));
+ if (!(s = strchr(args, ',')))
+ {
+ fprintf(stderr, "ICMP args missing: ,\n");
+ return;
+ }
+ *s++ = '\0';
+ ic->icmp_type = atoi(args);
+ ic->icmp_code = atoi(s);
+ if (ic->icmp_type == ICMP_REDIRECT && strchr(s, ','))
+ {
+ char *t;
+
+ t = strtok(s, ",");
+ t = strtok(NULL, ",");
+ if (resolve(t, (char *)&ic->icmp_gwaddr) == -1)
+ {
+ fprintf(stderr,"Cant resolve %s\n", t);
+ exit(2);
+ }
+ if ((t = strtok(NULL, ",")))
+ {
+ if (resolve(t, (char *)&ic->icmp_ip.ip_dst) == -1)
+ {
+ fprintf(stderr,"Cant resolve %s\n", t);
+ exit(2);
+ }
+ if ((t = strtok(NULL, ",")))
+ {
+ if (resolve(t,
+ (char *)&ic->icmp_ip.ip_src) == -1)
+ {
+ fprintf(stderr,"Cant resolve %s\n", t);
+ exit(2);
+ }
+ }
+ }
+ }
+}
+
+
+int send_packets(dev, mtu, ip, gwip)
+char *dev;
+int mtu;
+ip_t *ip;
+struct in_addr gwip;
+{
+ u_short sport = 0;
+ int wfd;
+
+ if (ip->ip_p == IPPROTO_TCP || ip->ip_p == IPPROTO_UDP)
+ sport = ((struct tcpiphdr *)ip)->ti_sport;
+ wfd = initdevice(dev, sport, 5);
+
+ return send_packet(wfd, mtu, ip, gwip);
+}
+
+
+int main(argc, argv)
+int argc;
+char **argv;
+{
+ struct tcpiphdr *ti;
+ struct in_addr gwip;
+ tcphdr_t *tcp;
+ ip_t *ip;
+ char *name = argv[0], host[64], *gateway = NULL, *dev = NULL;
+ char *src = NULL, *dst, c, *s;
+ int mtu = 1500, olen = 0;
+
+ /*
+ * 65535 is maximum packet size...you never know...
+ */
+ ip = (ip_t *)calloc(1, 65536);
+ ti = (struct tcpiphdr *)ip;
+ tcp = (tcphdr_t *)&ti->ti_sport;
+ ip->ip_len = sizeof(*ip);
+ ip->ip_hl = sizeof(*ip) >> 2;
+
+ while ((c = getopt(argc, argv, "IP:TUd:f:g:m:o:s:t:")) != -1)
+ switch (c)
+ {
+ case 'I' :
+ if (ip->ip_p)
+ {
+ fprintf(stderr, "Protocol already set: %d\n",
+ ip->ip_p);
+ break;
+ }
+ do_icmp(ip, optarg);
+ break;
+ case 'P' :
+ {
+ struct protoent *p;
+
+ if (ip->ip_p)
+ {
+ fprintf(stderr, "Protocol already set: %d\n",
+ ip->ip_p);
+ break;
+ }
+ if ((p = getprotobyname(optarg)))
+ ip->ip_p = p->p_proto;
+ else
+ fprintf(stderr, "Unknown protocol: %s\n",
+ optarg);
+ break;
+ }
+ case 'T' :
+ if (ip->ip_p)
+ {
+ fprintf(stderr, "Protocol already set: %d\n",
+ ip->ip_p);
+ break;
+ }
+ ip->ip_p = IPPROTO_TCP;
+ ip->ip_len += sizeof(tcphdr_t);
+ break;
+ case 'U' :
+ if (ip->ip_p)
+ {
+ fprintf(stderr, "Protocol already set: %d\n",
+ ip->ip_p);
+ break;
+ }
+ ip->ip_p = IPPROTO_UDP;
+ ip->ip_len += sizeof(udphdr_t);
+ break;
+ case 'd' :
+ dev = optarg;
+ break;
+ case 'f' :
+ ip->ip_off = strtol(optarg, NULL, 0);
+ break;
+ case 'g' :
+ gateway = optarg;
+ break;
+ case 'm' :
+ mtu = atoi(optarg);
+ if (mtu < 28)
+ {
+ fprintf(stderr, "mtu must be > 28\n");
+ exit(1);
+ }
+ break;
+ case 'o' :
+ olen = optname(optarg, options);
+ break;
+ case 's' :
+ src = optarg;
+ break;
+ case 't' :
+ if (ip->ip_p == IPPROTO_TCP || ip->ip_p == IPPROTO_UDP)
+ tcp->th_dport = htons(atoi(optarg));
+ break;
+ case 'w' :
+ if (ip->ip_p == IPPROTO_TCP)
+ tcp->th_win = atoi(optarg);
+ else
+ fprintf(stderr, "set protocol to TCP first\n");
+ break;
+ default :
+ fprintf(stderr, "Unknown option \"%c\"\n", c);
+ usage(name);
+ }
+
+ if (argc - optind < 2)
+ usage(name);
+ dst = argv[optind++];
+
+ if (!src)
+ {
+ gethostname(host, sizeof(host));
+ src = host;
+ }
+
+ if (resolve(src, (char *)&ip->ip_src) == -1)
+ {
+ fprintf(stderr,"Cant resolve %s\n", src);
+ exit(2);
+ }
+
+ if (resolve(dst, (char *)&ip->ip_dst) == -1)
+ {
+ fprintf(stderr,"Cant resolve %s\n", dst);
+ exit(2);
+ }
+
+ if (!gateway)
+ gwip = ip->ip_dst;
+ else if (resolve(gateway, (char *)&gwip) == -1)
+ {
+ fprintf(stderr,"Cant resolve %s\n", gateway);
+ exit(2);
+ }
+
+ if (ip->ip_p == IPPROTO_TCP)
+ for (s = argv[optind]; (c = *s); s++)
+ switch(c)
+ {
+ case 'S' : case 's' :
+ tcp->th_flags |= TH_SYN;
+ break;
+ case 'A' : case 'a' :
+ tcp->th_flags |= TH_ACK;
+ break;
+ case 'F' : case 'f' :
+ tcp->th_flags |= TH_FIN;
+ break;
+ case 'R' : case 'r' :
+ tcp->th_flags |= TH_RST;
+ break;
+ case 'P' : case 'p' :
+ tcp->th_flags |= TH_PUSH;
+ break;
+ case 'U' : case 'u' :
+ tcp->th_flags |= TH_URG;
+ break;
+ }
+
+ if (!dev)
+ dev = default_device;
+ printf("Device: %s\n", dev);
+ printf("Source: %s\n", inet_ntoa(ip->ip_src));
+ printf("Dest: %s\n", inet_ntoa(ip->ip_dst));
+ printf("Gateway: %s\n", inet_ntoa(gwip));
+ if (ip->ip_p == IPPROTO_TCP && tcp->th_flags)
+ printf("Flags: %#x\n", tcp->th_flags);
+ printf("mtu: %d\n", mtu);
+
+ if (olen)
+ {
+ printf("Options: %d\n", olen);
+ ti = (struct tcpiphdr *)malloc(olen + ip->ip_len);
+ bcopy((char *)ip, (char *)ti, sizeof(*ip));
+ ip = (ip_t *)ti;
+ ip->ip_hl += (olen >> 2);
+ bcopy(options, (char *)(ip + 1), olen);
+ bcopy((char *)tcp, (char *)(ip + 1) + olen, sizeof(*tcp));
+ tcp = (tcphdr_t *)((char *)(ip + 1) + olen);
+ ip->ip_len += olen;
+ }
+
+#ifdef DOSOCKET
+ if (tcp->th_dport)
+ return do_socket(dev, mtu, ti, gwip);
+#endif
+ return send_packets(dev, mtu, ti, gwip);
+}
diff --git a/contrib/ipfilter/ipsend/ipsopt.c b/contrib/ipfilter/ipsend/ipsopt.c
new file mode 100644
index 000000000000..75c4f1627a8e
--- /dev/null
+++ b/contrib/ipfilter/ipsend/ipsopt.c
@@ -0,0 +1,111 @@
+/*
+ * (C)opyright 1995 by Darren Reed.
+ *
+ * This code may be freely distributed as long as it retains this notice
+ * and is not changed in any way. The author accepts no responsibility
+ * for the use of this software. I hate legaleese, don't you ?
+ */
+#if !defined(lint) && defined(LIBC_SCCS)
+static char sccsid[] = "@(#)ipsopt.c 1.2 1/11/96 (C)1995 Darren Reed";
+#endif
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include "ip_compat.h"
+
+struct ipopt_names {
+ int on_value;
+ int on_bit;
+ int on_siz;
+ char *on_name;
+};
+
+struct ipopt_names ionames[] = {
+ { IPOPT_EOL, 0x01, 1, "eol" },
+ { IPOPT_NOP, 0x02, 1, "nop" },
+ { IPOPT_RR, 0x04, 7, "rr" }, /* 1 route */
+ { IPOPT_TS, 0x08, 8, "ts" }, /* 1 TS */
+ { IPOPT_SECURITY, 0x08, 11, "sec-level" },
+ { IPOPT_LSRR, 0x10, 7, "lsrr" }, /* 1 route */
+ { IPOPT_SATID, 0x20, 4, "satid" },
+ { IPOPT_SSRR, 0x40, 7, "ssrr" }, /* 1 route */
+ { 0, 0, 0, NULL } /* must be last */
+};
+
+struct ipopt_names secnames[] = {
+ { IPOPT_SECUR_UNCLASS, 0x0100, 0, "unclass" },
+ { IPOPT_SECUR_CONFID, 0x0200, 0, "confid" },
+ { IPOPT_SECUR_EFTO, 0x0400, 0, "efto" },
+ { IPOPT_SECUR_MMMM, 0x0800, 0, "mmmm" },
+ { IPOPT_SECUR_RESTR, 0x1000, 0, "restr" },
+ { IPOPT_SECUR_SECRET, 0x2000, 0, "secret" },
+ { IPOPT_SECUR_TOPSECRET, 0x4000,0, "topsecret" },
+ { 0, 0, 0, NULL } /* must be last */
+};
+
+
+u_short seclevel(slevel)
+char *slevel;
+{
+ struct ipopt_names *so;
+
+ for (so = secnames; so->on_name; so++)
+ if (!strcasecmp(slevel, so->on_name))
+ break;
+
+ if (!so->on_name) {
+ fprintf(stderr, "no such security level: %s\n", slevel);
+ return 0;
+ }
+ return so->on_value;
+}
+
+
+u_long optname(cp, op)
+char *cp, *op;
+{
+ struct ipopt_names *io;
+ u_short lvl;
+ u_long msk = 0;
+ char *s, *t;
+ int len = 0;
+
+ for (s = strtok(cp, ","); s; s = strtok(NULL, ",")) {
+ if ((t = strchr(s, '=')))
+ *t++ = '\0';
+ for (io = ionames; io->on_name; io++) {
+ if (strcasecmp(s, io->on_name) || (msk & io->on_bit))
+ continue;
+ if ((len + io->on_siz) > 48) {
+ fprintf(stderr, "options too long\n");
+ return 0;
+ }
+ len += io->on_siz;
+ *op++ = io->on_value;
+ if (io->on_siz > 1) {
+ *op++ = io->on_siz;
+ *op++ = IPOPT_MINOFF;
+
+ if (t && !strcasecmp(s, "sec-level")) {
+ lvl = seclevel(t);
+ bcopy(&lvl, op, sizeof(lvl));
+ }
+ op += io->on_siz - 3;
+ }
+ msk |= io->on_bit;
+ break;
+ }
+ if (!io->on_name) {
+ fprintf(stderr, "unknown IP option name %s\n", s);
+ return 0;
+ }
+ }
+ *op++ = IPOPT_EOL;
+ len++;
+ return len;
+}
diff --git a/contrib/ipfilter/ipsend/iptest.c b/contrib/ipfilter/ipsend/iptest.c
new file mode 100644
index 000000000000..c5d48fa83420
--- /dev/null
+++ b/contrib/ipfilter/ipsend/iptest.c
@@ -0,0 +1,211 @@
+/*
+ * ipsend.c (C) 1995 Darren Reed
+ *
+ * This was written to test what size TCP fragments would get through
+ * various TCP/IP packet filters, as used in IP firewalls. In certain
+ * conditions, enough of the TCP header is missing for unpredictable
+ * results unless the filter is aware that this can happen.
+ *
+ * The author provides this program as-is, with no gaurantee for its
+ * suitability for any specific purpose. The author takes no responsibility
+ * for the misuse/abuse of this program and provides it for the sole purpose
+ * of testing packet filter policies. This file maybe distributed freely
+ * providing it is not modified and that this notice remains in tact.
+ *
+ * This was written and tested (successfully) on SunOS 4.1.x.
+ */
+#if !defined(lint) && defined(LIBC_SCCS)
+static char sccsid[] = "%W% %G% (C)1995 Darren Reed";
+#endif
+#include <stdio.h>
+#include <netdb.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/tcp.h>
+#include <netinet/udp.h>
+#include <netinet/ip_icmp.h>
+#ifndef linux
+#include <netinet/ip_var.h>
+#include <netinet/tcpip.h>
+#endif
+#include "ip_compat.h"
+#ifdef linux
+#include <linux/sockios.h>
+#include "tcpip.h"
+#endif
+#include "ipt.h"
+
+
+extern char *optarg;
+extern int optind;
+
+extern int initdevice(), resolve();
+extern int ip_test1(), ip_test2(), ip_test3(), ip_test4(), ip_test5();
+extern int ip_test6(), ip_test7();
+
+char options[68];
+#ifdef linux
+char default_device[] = "eth0";
+#else
+# ifdef sun
+char default_device[] = "le0";
+# else
+# ifdef ultrix
+char default_device[] = "ln0";
+# else
+# ifdef __bsdi__
+char default_device[] = "ef0";
+# else
+char default_device[] = "lan0";
+# endif
+# endif
+# endif
+#endif
+
+
+void usage(prog)
+char *prog;
+{
+ fprintf(stderr, "Usage: %s [options] dest\n\
+\toptions:\n\
+\t\t-d device\tSend out on this device\n\
+\t\t-g gateway\tIP gateway to use if non-local dest.\n\
+\t\t-m mtu\t\tfake MTU to use when sending out\n\
+\t\t-p pointtest\t\n\
+\t\t-s src\t\tsource address for IP packet\n\
+\t\t-1 \t\tPerform test 1 (IP header)\n\
+\t\t-2 \t\tPerform test 2 (IP options)\n\
+\t\t-3 \t\tPerform test 3 (ICMP)\n\
+\t\t-4 \t\tPerform test 4 (UDP)\n\
+\t\t-5 \t\tPerform test 5 (TCP)\n\
+\t\t-6 \t\tPerform test 6 (overlapping fragments)\n\
+\t\t-7 \t\tPerform test 7 (random packets)\n\
+", prog);
+ exit(1);
+}
+
+
+int main(argc, argv)
+int argc;
+char **argv;
+{
+ struct tcpiphdr *ti;
+ struct in_addr gwip;
+ ip_t *ip;
+ char *name = argv[0], host[64], *gateway = NULL, *dev = NULL;
+ char *src = NULL, *dst, c;
+ int mtu = 1500, tests = 0, pointtest = 0;
+
+ /*
+ * 65535 is maximum packet size...you never know...
+ */
+ ip = (ip_t *)calloc(1, 65536);
+ ti = (struct tcpiphdr *)ip;
+ ip->ip_len = sizeof(*ip);
+ ip->ip_hl = sizeof(*ip) >> 2;
+
+ while ((c = getopt(argc, argv, "1234567IP:TUd:f:g:m:o:p:s:t:")) != -1)
+ switch (c)
+ {
+ case '1' :
+ case '2' :
+ case '3' :
+ case '4' :
+ case '5' :
+ case '6' :
+ case '7' :
+ tests = c - '0';
+ break;
+ case 'd' :
+ dev = optarg;
+ break;
+ case 'g' :
+ gateway = optarg;
+ break;
+ case 'm' :
+ mtu = atoi(optarg);
+ if (mtu < 28)
+ {
+ fprintf(stderr, "mtu must be > 28\n");
+ exit(1);
+ }
+ break;
+ case 'p' :
+ pointtest = atoi(optarg);
+ break;
+ case 's' :
+ src = optarg;
+ break;
+ default :
+ fprintf(stderr, "Unknown option \"%c\"\n", c);
+ usage(name);
+ }
+
+ if (argc - optind < 2 && !tests)
+ usage(name);
+ dst = argv[optind++];
+
+ if (!src)
+ {
+ gethostname(host, sizeof(host));
+ src = host;
+ }
+
+ if (resolve(dst, (char *)&ip->ip_dst) == -1)
+ {
+ fprintf(stderr,"Cant resolve %s\n", dst);
+ exit(2);
+ }
+
+ if (resolve(src, (char *)&ip->ip_src) == -1)
+ {
+ fprintf(stderr,"Cant resolve %s\n", src);
+ exit(2);
+ }
+
+ if (!gateway)
+ gwip = ip->ip_dst;
+ else if (resolve(gateway, (char *)&gwip) == -1)
+ {
+ fprintf(stderr,"Cant resolve %s\n", gateway);
+ exit(2);
+ }
+
+
+ if (!dev)
+ dev = default_device;
+ printf("Device: %s\n", dev);
+ printf("Source: %s\n", inet_ntoa(ip->ip_src));
+ printf("Dest: %s\n", inet_ntoa(ip->ip_dst));
+ printf("Gateway: %s\n", inet_ntoa(gwip));
+ printf("mtu: %d\n", mtu);
+
+ switch (tests)
+ {
+ case 1 :
+ return ip_test1(dev, mtu, ti, gwip, pointtest);
+ case 2 :
+ return ip_test2(dev, mtu, ti, gwip, pointtest);
+ case 3 :
+ return ip_test3(dev, mtu, ti, gwip, pointtest);
+ case 4 :
+ return ip_test4(dev, mtu, ti, gwip, pointtest);
+ case 5 :
+ return ip_test5(dev, mtu, ti, gwip, pointtest);
+ case 6 :
+ return ip_test6(dev, mtu, ti, gwip, pointtest);
+ case 7 :
+ return ip_test7(dev, mtu, ti, gwip, pointtest);
+ default :
+ break;
+ }
+ return 0;
+}
diff --git a/contrib/ipfilter/ipsend/iptests.c b/contrib/ipfilter/ipsend/iptests.c
new file mode 100644
index 000000000000..b9da7b2ba82e
--- /dev/null
+++ b/contrib/ipfilter/ipsend/iptests.c
@@ -0,0 +1,1296 @@
+/*
+ * (C)opyright 1993, 1994, 1995 by Darren Reed.
+ *
+ * This code may be freely distributed as long as it retains this notice
+ * and is not changed in any way. The author accepts no responsibility
+ * for the use of this software. I hate legaleese, don't you ?
+ */
+#if !defined(lint) && defined(LIBC_SCCS)
+static char sccsid[] = "%W% %G% (C)1995 Darren Reed";
+#endif
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/param.h>
+#if !defined(solaris)
+# define _KERNEL
+# define KERNEL
+# include <sys/file.h>
+# undef _KERNEL
+# undef KERNEL
+# include <nlist.h>
+# include <sys/user.h>
+# include <sys/proc.h>
+#endif
+#include <kvm.h>
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+#ifdef sun
+#include <sys/systm.h>
+#include <sys/session.h>
+#endif
+#if BSD >= 199103
+#include <sys/sysctl.h>
+#include <sys/filedesc.h>
+#include <paths.h>
+#endif
+#include <netinet/in_systm.h>
+#include <sys/socket.h>
+#include <net/if.h>
+#include <net/route.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netinet/ip.h>
+#include <netinet/tcp.h>
+#include <netinet/udp.h>
+#include <netinet/ip_icmp.h>
+#include <netinet/if_ether.h>
+#include <netinet/ip_var.h>
+#include <netinet/in_pcb.h>
+#include <netinet/tcp_timer.h>
+#include <netinet/tcp_var.h>
+#include "ip_compat.h"
+#ifdef linux
+#include "tcpip.h"
+#else
+#include <netinet/tcpip.h>
+# if defined(__SVR4) || defined(__svr4__)
+#include <sys/sysmacros.h>
+# endif
+#endif
+
+#define PAUSE() tv.tv_sec = 0; tv.tv_usec = 10000; \
+ (void) select(0, NULL, NULL, NULL, &tv)
+
+extern int send_ip(), send_tcp(), send_udp(), send_icmp(), send_ether();
+extern int initdevice(), kmemcpy();
+extern u_short chksum();
+extern struct tcpcb *find_tcp();
+
+void ip_test1(dev, mtu, ip, gwip, ptest)
+char *dev;
+int mtu;
+ip_t *ip;
+struct in_addr gwip;
+int ptest;
+{
+ struct timeval tv;
+ udphdr_t *u;
+ int nfd, i, len, id = getpid();
+
+ ip->ip_hl = sizeof(*ip) >> 2;
+ ip->ip_v = IPVERSION;
+ ip->ip_tos = 0;
+ ip->ip_off = 0;
+ ip->ip_ttl = 60;
+ ip->ip_p = IPPROTO_UDP;
+ ip->ip_sum = 0;
+ u = (udphdr_t *)(ip + 1);
+ u->uh_sport = 1;
+ u->uh_dport = 9;
+ u->uh_sum = 0;
+ u->uh_ulen = sizeof(*u) + 4;
+ ip->ip_len = sizeof(*ip) + u->uh_ulen;
+ len = ip->ip_len;
+ nfd = initdevice(dev, u->uh_sport, 1);
+
+ u->uh_sport = htons(u->uh_sport);
+ u->uh_dport = htons(u->uh_dport);
+ u->uh_ulen = htons(u->uh_ulen);
+ if (!ptest || (ptest == 1)) {
+ /*
+ * Part1: hl < len
+ */
+ ip->ip_id = 0;
+ printf("1.1. sending packets with ip_hl < ip_len\n");
+ for (i = 0; i < ((sizeof(*ip) + u->uh_ulen) >> 2); i++) {
+ ip->ip_hl = i >> 2;
+ (void) send_ip(nfd, 1500, ip, gwip, 1);
+ printf("%d\r", i);
+ fflush(stdout);
+ PAUSE();
+ }
+ putchar('\n');
+ }
+
+ if (!ptest || (ptest == 2)) {
+ /*
+ * Part2: hl > len
+ */
+ ip->ip_id = 0;
+ printf("1.2. sending packets with ip_hl > ip_len\n");
+ for (; i < ((sizeof(*ip) * 2 + u->uh_ulen) >> 2); i++) {
+ ip->ip_hl = i >> 2;
+ (void) send_ip(nfd, 1500, ip, gwip, 1);
+ printf("%d\r", i);
+ fflush(stdout);
+ PAUSE();
+ }
+ putchar('\n');
+ }
+
+ if (!ptest || (ptest == 3)) {
+ /*
+ * Part3: v < 4
+ */
+ ip->ip_id = 0;
+ printf("1.3. ip_v < 4\n");
+ ip->ip_hl = sizeof(*ip) >> 2;
+ for (i = 0; i < 4; i++) {
+ ip->ip_v = i;
+ (void) send_ip(nfd, 1500, ip, gwip, 1);
+ printf("%d\r", i);
+ fflush(stdout);
+ PAUSE();
+ }
+ putchar('\n');
+ }
+
+ if (!ptest || (ptest == 4)) {
+ /*
+ * Part4: v > 4
+ */
+ ip->ip_id = 0;
+ printf("1.4. ip_v > 4\n");
+ for (i = 5; i < 16; i++) {
+ ip->ip_v = i;
+ (void) send_ip(nfd, 1500, ip, gwip, 1);
+ printf("%d\r", i);
+ fflush(stdout);
+ PAUSE();
+ }
+ putchar('\n');
+ }
+
+ if (!ptest || (ptest == 5)) {
+ /*
+ * Part5: len < packet
+ */
+ ip->ip_id = 0;
+ ip->ip_v = IPVERSION;
+ i = ip->ip_len + 1;
+ ip->ip_len = htons(ip->ip_len);
+ ip->ip_off = htons(ip->ip_off);
+ printf("1.5.0 ip_len < packet size (size++, long packets)\n");
+ for (; i < (ntohs(ip->ip_len) * 2); i++) {
+ ip->ip_id = htons(id++);
+ ip->ip_sum = 0;
+ ip->ip_sum = chksum(ip, ip->ip_hl << 2);
+ (void) send_ether(nfd, ip, i, gwip);
+ printf("%d\r", i);
+ fflush(stdout);
+ PAUSE();
+ }
+ putchar('\n');
+ printf("1.5.1 ip_len < packet size (ip_len-, short packets)\n");
+ for (i = len; i > 0; i--) {
+ ip->ip_id = htons(id++);
+ ip->ip_len = htons(i);
+ ip->ip_sum = 0;
+ ip->ip_sum = chksum(ip, ip->ip_hl << 2);
+ (void) send_ether(nfd, ip, len, gwip);
+ printf("%d\r", i);
+ fflush(stdout);
+ PAUSE();
+ }
+ putchar('\n');
+ }
+
+ if (!ptest || (ptest == 6)) {
+ /*
+ * Part6: len > packet
+ */
+ ip->ip_id = 0;
+ printf("1.6.0 ip_len > packet size (increase ip_len)\n");
+ for (i = len + 1; i < (len * 2); i++) {
+ ip->ip_id = htons(id++);
+ ip->ip_len = htons(i);
+ ip->ip_sum = 0;
+ ip->ip_sum = chksum(ip, ip->ip_hl << 2);
+ (void) send_ether(nfd, ip, len, gwip);
+ printf("%d\r", i);
+ fflush(stdout);
+ PAUSE();
+ }
+ putchar('\n');
+ ip->ip_len = htons(len);
+ printf("1.6.1 ip_len > packet size (size--, short packets)\n");
+ for (i = len; i > 0; i--) {
+ ip->ip_id = htons(id++);
+ ip->ip_sum = 0;
+ ip->ip_sum = chksum(ip, ip->ip_hl << 2);
+ (void) send_ether(nfd, ip, i, gwip);
+ printf("%d\r", i);
+ fflush(stdout);
+ PAUSE();
+ }
+ putchar('\n');
+ }
+
+ if (!ptest || (ptest == 7)) {
+ /*
+ * Part7: 0 length fragment
+ */
+ printf("1.7.0 Zero length fragments (ip_off = 0x2000)\n");
+ ip->ip_id = 0;
+ ip->ip_len = sizeof(*ip);
+ ip->ip_off = htons(IP_MF);
+ (void) send_ip(nfd, mtu, ip, gwip, 1);
+ fflush(stdout);
+ PAUSE();
+
+ printf("1.7.1 Zero length fragments (ip_off = 0x3000)\n");
+ ip->ip_id = 0;
+ ip->ip_len = sizeof(*ip);
+ ip->ip_off = htons(IP_MF);
+ (void) send_ip(nfd, mtu, ip, gwip, 1);
+ fflush(stdout);
+ PAUSE();
+
+ printf("1.7.2 Zero length fragments (ip_off = 0xa000)\n");
+ ip->ip_id = 0;
+ ip->ip_len = sizeof(*ip);
+ ip->ip_off = htons(0xa000);
+ (void) send_ip(nfd, mtu, ip, gwip, 1);
+ fflush(stdout);
+ PAUSE();
+
+ printf("1.7.3 Zero length fragments (ip_off = 0x0100)\n");
+ ip->ip_id = 0;
+ ip->ip_len = sizeof(*ip);
+ ip->ip_off = htons(0x0100);
+ (void) send_ip(nfd, mtu, ip, gwip, 1);
+ fflush(stdout);
+ PAUSE();
+ }
+
+ if (!ptest || (ptest == 8)) {
+ struct timeval tv;
+
+ gettimeofday(&tv, NULL);
+ srand(tv.tv_sec ^ getpid() ^ tv.tv_usec);
+ /*
+ * Part8.1: 63k packet + 1k fragment at offset 0x1ffe
+ * Mark it as being ICMP (so it doesn't get junked), but
+ * don't bother about the ICMP header, we're not worrying
+ * about that here.
+ */
+ ip->ip_p = IPPROTO_ICMP;
+ ip->ip_off = IP_MF;
+ u->uh_dport = htons(9);
+ ip->ip_id = htons(id++);
+ printf("1.8.1 63k packet + 1k fragment at offset 0x1ffe\n");
+ ip->ip_len = 768 + 20 + 8;
+ (void) send_ip(nfd, mtu, ip, gwip, 1);
+ printf("%d\r", i);
+
+ ip->ip_len = MIN(768 + 20, mtu - 68);
+ i = 512;
+ for (; i < (63 * 1024 + 768); i += 768) {
+ ip->ip_off = IP_MF | (i >> 3);
+ (void) send_ip(nfd, mtu, ip, gwip, 1);
+ printf("%d\r", i);
+ fflush(stdout);
+ PAUSE();
+ }
+ ip->ip_len = 896 + 20;
+ ip->ip_off = (i >> 3);
+ (void) send_ip(nfd, mtu, ip, gwip, 1);
+ printf("%d\r", i);
+ putchar('\n');
+ fflush(stdout);
+
+ /*
+ * Part8.2: 63k packet + 1k fragment at offset 0x1ffe
+ * Mark it as being ICMP (so it doesn't get junked), but
+ * don't bother about the ICMP header, we're not worrying
+ * about that here. (Lossage here)
+ */
+ ip->ip_p = IPPROTO_ICMP;
+ ip->ip_off = IP_MF;
+ u->uh_dport = htons(9);
+ ip->ip_id = htons(id++);
+ printf("1.8.2 63k packet + 1k fragment at offset 0x1ffe\n");
+ ip->ip_len = 768 + 20 + 8;
+ if ((rand() & 0x1f) != 0) {
+ (void) send_ip(nfd, mtu, ip, gwip, 1);
+ printf("%d\r", i);
+ } else
+ printf("skip 0\n");
+
+ ip->ip_len = MIN(768 + 20, mtu - 68);
+ i = 512;
+ for (; i < (63 * 1024 + 768); i += 768) {
+ ip->ip_off = IP_MF | (i >> 3);
+ if ((rand() & 0x1f) != 0) {
+ (void) send_ip(nfd, mtu, ip, gwip, 1);
+ printf("%d\r", i);
+ } else
+ printf("skip %d\n", i);
+ fflush(stdout);
+ PAUSE();
+ }
+ ip->ip_len = 896 + 20;
+ ip->ip_off = (i >> 3);
+ if ((rand() & 0x1f) != 0) {
+ (void) send_ip(nfd, mtu, ip, gwip, 1);
+ printf("%d\r", i);
+ } else
+ printf("skip\n");
+ putchar('\n');
+ fflush(stdout);
+
+ /*
+ * Part8.3: 33k packet - test for not dealing with -ve length
+ * Mark it as being ICMP (so it doesn't get junked), but
+ * don't bother about the ICMP header, we're not worrying
+ * about that here.
+ */
+ ip->ip_p = IPPROTO_ICMP;
+ ip->ip_off = IP_MF;
+ u->uh_dport = htons(9);
+ ip->ip_id = htons(id++);
+ printf("1.8.3 33k packet\n");
+ ip->ip_len = 768 + 20 + 8;
+ (void) send_ip(nfd, mtu, ip, gwip, 1);
+ printf("%d\r", i);
+
+ ip->ip_len = MIN(768 + 20, mtu - 68);
+ i = 512;
+ for (; i < (32 * 1024 + 768); i += 768) {
+ ip->ip_off = IP_MF | (i >> 3);
+ (void) send_ip(nfd, mtu, ip, gwip, 1);
+ printf("%d\r", i);
+ fflush(stdout);
+ PAUSE();
+ }
+ ip->ip_len = 896 + 20;
+ ip->ip_off = (i >> 3);
+ (void) send_ip(nfd, mtu, ip, gwip, 1);
+ printf("%d\r", i);
+ putchar('\n');
+ fflush(stdout);
+ }
+
+ ip->ip_len = len;
+ ip->ip_off = 0;
+ if (!ptest || (ptest == 9)) {
+ /*
+ * Part9: off & 0x8000 == 0x8000
+ */
+ ip->ip_id = 0;
+ ip->ip_off = 0x8000;
+ printf("1.9. ip_off & 0x8000 == 0x8000\n");
+ (void) send_ip(nfd, mtu, ip, gwip, 1);
+ fflush(stdout);
+ PAUSE();
+ }
+
+ ip->ip_off = 0;
+
+ if (!ptest || (ptest == 10)) {
+ /*
+ * Part10: ttl = 255
+ */
+ ip->ip_id = 0;
+ ip->ip_ttl = 255;
+ printf("1.10.0 ip_ttl = 255\n");
+ (void) send_ip(nfd, mtu, ip, gwip, 1);
+ fflush(stdout);
+ PAUSE();
+
+ ip->ip_ttl = 128;
+ printf("1.10.1 ip_ttl = 128\n");
+ (void) send_ip(nfd, mtu, ip, gwip, 1);
+ fflush(stdout);
+ PAUSE();
+
+ ip->ip_ttl = 0;
+ printf("1.10.2 ip_ttl = 0\n");
+ (void) send_ip(nfd, mtu, ip, gwip, 1);
+ fflush(stdout);
+ PAUSE();
+ }
+
+ (void) close(nfd);
+}
+
+
+void ip_test2(dev, mtu, ip, gwip, ptest)
+char *dev;
+int mtu;
+ip_t *ip;
+struct in_addr gwip;
+int ptest;
+{
+ struct timeval tv;
+ int nfd;
+ u_char *s;
+
+ s = (u_char *)(ip + 1);
+ nfd = initdevice(dev, 1, 1);
+
+ ip->ip_hl = 6;
+ ip->ip_len = ip->ip_hl << 2;
+ s[IPOPT_OPTVAL] = IPOPT_NOP;
+ s++;
+ if (!ptest || (ptest == 1)) {
+ /*
+ * Test 1: option length > packet length,
+ * header length == packet length
+ */
+ s[IPOPT_OPTVAL] = IPOPT_TS;
+ s[IPOPT_OLEN] = 4;
+ s[IPOPT_OFFSET] = IPOPT_MINOFF;
+ ip->ip_p = IPPROTO_IP;
+ printf("2.1 option length > packet length\n");
+ (void) send_ip(nfd, mtu, ip, gwip, 1);
+ fflush(stdout);
+ PAUSE();
+ }
+
+ ip->ip_hl = 7;
+ ip->ip_len = ip->ip_hl << 2;
+ if (!ptest || (ptest == 1)) {
+ /*
+ * Test 2: options have length = 0
+ */
+ printf("2.2.1 option length = 0, RR\n");
+ s[IPOPT_OPTVAL] = IPOPT_RR;
+ s[IPOPT_OLEN] = 0;
+ (void) send_ip(nfd, mtu, ip, gwip, 1);
+ fflush(stdout);
+ PAUSE();
+
+ printf("2.2.2 option length = 0, TS\n");
+ s[IPOPT_OPTVAL] = IPOPT_TS;
+ s[IPOPT_OLEN] = 0;
+ (void) send_ip(nfd, mtu, ip, gwip, 1);
+ fflush(stdout);
+ PAUSE();
+
+ printf("2.2.3 option length = 0, SECURITY\n");
+ s[IPOPT_OPTVAL] = IPOPT_SECURITY;
+ s[IPOPT_OLEN] = 0;
+ (void) send_ip(nfd, mtu, ip, gwip, 1);
+ fflush(stdout);
+ PAUSE();
+
+ printf("2.2.4 option length = 0, LSRR\n");
+ s[IPOPT_OPTVAL] = IPOPT_LSRR;
+ s[IPOPT_OLEN] = 0;
+ (void) send_ip(nfd, mtu, ip, gwip, 1);
+ fflush(stdout);
+ PAUSE();
+
+ printf("2.2.5 option length = 0, SATID\n");
+ s[IPOPT_OPTVAL] = IPOPT_SATID;
+ s[IPOPT_OLEN] = 0;
+ (void) send_ip(nfd, mtu, ip, gwip, 1);
+ fflush(stdout);
+ PAUSE();
+
+ printf("2.2.6 option length = 0, SSRR\n");
+ s[IPOPT_OPTVAL] = IPOPT_SSRR;
+ s[IPOPT_OLEN] = 0;
+ (void) send_ip(nfd, mtu, ip, gwip, 1);
+ fflush(stdout);
+ PAUSE();
+ }
+
+ (void) close(nfd);
+}
+
+
+/*
+ * test 3 (ICMP)
+ */
+void ip_test3(dev, mtu, ip, gwip, ptest)
+char *dev;
+int mtu;
+ip_t *ip;
+struct in_addr gwip;
+int ptest;
+{
+ static int ict1[10] = { 8, 9, 10, 13, 14, 15, 16, 17, 18, 0 };
+ static int ict2[8] = { 3, 9, 10, 13, 14, 17, 18, 0 };
+ struct timeval tv;
+ struct icmp *icp;
+ int nfd, i;
+
+ ip->ip_hl = sizeof(*ip) >> 2;
+ ip->ip_v = IPVERSION;
+ ip->ip_tos = 0;
+ ip->ip_off = 0;
+ ip->ip_ttl = 60;
+ ip->ip_p = IPPROTO_ICMP;
+ ip->ip_sum = 0;
+ ip->ip_len = sizeof(*ip) + sizeof(*icp);
+ icp = (struct icmp *)((char *)ip + (ip->ip_hl << 2));
+ nfd = initdevice(dev, 1, 1);
+
+ if (!ptest || (ptest == 1)) {
+ /*
+ * Type 0 - 31, 255, code = 0
+ */
+ bzero((char *)icp, sizeof(*icp));
+ for (i = 0; i < 32; i++) {
+ icp->icmp_type = i;
+ (void) send_icmp(nfd, mtu, ip, gwip);
+ PAUSE();
+ printf("3.1.%d ICMP type %d code 0 (all 0's)\r", i, i);
+ }
+ icp->icmp_type = 255;
+ (void) send_icmp(nfd, mtu, ip, gwip);
+ PAUSE();
+ printf("3.1.%d ICMP type %d code 0 (all 0's)\r", i, 255);
+ putchar('\n');
+ }
+
+ if (!ptest || (ptest == 2)) {
+ /*
+ * Type 3, code = 0 - 31
+ */
+ icp->icmp_type = 3;
+ for (i = 0; i < 32; i++) {
+ icp->icmp_code = i;
+ (void) send_icmp(nfd, mtu, ip, gwip);
+ PAUSE();
+ printf("3.2.%d ICMP type 3 code %d (all 0's)\r", i, i);
+ }
+ }
+
+ if (!ptest || (ptest == 3)) {
+ /*
+ * Type 4, code = 0,127,128,255
+ */
+ icp->icmp_type = 4;
+ icp->icmp_code = 0;
+ (void) send_icmp(nfd, mtu, ip, gwip);
+ PAUSE();
+ printf("3.3.1 ICMP type 4 code 0 (all 0's)\r");
+ icp->icmp_code = 127;
+ (void) send_icmp(nfd, mtu, ip, gwip);
+ PAUSE();
+ printf("3.3.2 ICMP type 4 code 127 (all 0's)\r");
+ icp->icmp_code = 128;
+ (void) send_icmp(nfd, mtu, ip, gwip);
+ PAUSE();
+ printf("3.3.3 ICMP type 4 code 128 (all 0's)\r");
+ icp->icmp_code = 255;
+ (void) send_icmp(nfd, mtu, ip, gwip);
+ PAUSE();
+ printf("3.3.4 ICMP type 4 code 255 (all 0's)\r");
+ }
+
+ if (!ptest || (ptest == 4)) {
+ /*
+ * Type 5, code = 0,127,128,255
+ */
+ icp->icmp_type = 5;
+ icp->icmp_code = 0;
+ (void) send_icmp(nfd, mtu, ip, gwip);
+ PAUSE();
+ printf("3.4.1 ICMP type 5 code 0 (all 0's)\r");
+ icp->icmp_code = 127;
+ (void) send_icmp(nfd, mtu, ip, gwip);
+ PAUSE();
+ printf("3.4.2 ICMP type 5 code 127 (all 0's)\r");
+ icp->icmp_code = 128;
+ (void) send_icmp(nfd, mtu, ip, gwip);
+ PAUSE();
+ printf("3.4.3 ICMP type 5 code 128 (all 0's)\r");
+ icp->icmp_code = 255;
+ (void) send_icmp(nfd, mtu, ip, gwip);
+ PAUSE();
+ printf("3.4.4 ICMP type 5 code 255 (all 0's)\r");
+ }
+
+ if (!ptest || (ptest == 5)) {
+ /*
+ * Type 8-10;13-18, code - 0,127,128,255
+ */
+ for (i = 0; ict1[i]; i++) {
+ icp->icmp_type = ict1[i];
+ icp->icmp_code = 0;
+ (void) send_icmp(nfd, mtu, ip, gwip);
+ PAUSE();
+ printf("3.5.%d ICMP type 5 code 0 (all 0's)\r",
+ i * 4);
+ icp->icmp_code = 127;
+ (void) send_icmp(nfd, mtu, ip, gwip);
+ PAUSE();
+ printf("3.5.%d ICMP type 5 code 127 (all 0's)\r",
+ i * 4 + 1);
+ icp->icmp_code = 128;
+ (void) send_icmp(nfd, mtu, ip, gwip);
+ PAUSE();
+ printf("3.5.%d ICMP type 5 code 128 (all 0's)\r",
+ i * 4 + 2);
+ icp->icmp_code = 255;
+ (void) send_icmp(nfd, mtu, ip, gwip);
+ PAUSE();
+ printf("3.5.%d ICMP type 5 code 255 (all 0's)\r",
+ i * 4 + 3);
+ }
+ putchar('\n');
+ }
+
+ if (!ptest || (ptest == 6)) {
+ /*
+ * Type 12, code - 0,127,128,129,255
+ */
+ icp->icmp_type = 12;
+ icp->icmp_code = 0;
+ (void) send_icmp(nfd, mtu, ip, gwip);
+ PAUSE();
+ printf("3.6.1 ICMP type 12 code 0 (all 0's)\r");
+ icp->icmp_code = 127;
+ (void) send_icmp(nfd, mtu, ip, gwip);
+ PAUSE();
+ printf("3.6.2 ICMP type 12 code 127 (all 0's)\r");
+ icp->icmp_code = 128;
+ (void) send_icmp(nfd, mtu, ip, gwip);
+ PAUSE();
+ printf("3.6.3 ICMP type 12 code 128 (all 0's)\r");
+ icp->icmp_code = 129;
+ (void) send_icmp(nfd, mtu, ip, gwip);
+ PAUSE();
+ printf("3.6.4 ICMP type 12 code 129 (all 0's)\r");
+ icp->icmp_code = 255;
+ (void) send_icmp(nfd, mtu, ip, gwip);
+ PAUSE();
+ printf("3.6.5 ICMP type 12 code 255 (all 0's)\r");
+ putchar('\n');
+ }
+
+ if (!ptest || (ptest == 7)) {
+ /*
+ * Type 3;9-10;13-14;17-18 - shorter packets
+ */
+ ip->ip_len = sizeof(*ip) + sizeof(*icp) / 2;
+ for (i = 0; ict2[i]; i++) {
+ icp->icmp_type = ict1[i];
+ icp->icmp_code = 0;
+ (void) send_icmp(nfd, mtu, ip, gwip);
+ PAUSE();
+ printf("3.5.%d ICMP type %d code 0 (all 0's)\r",
+ i * 4, icp->icmp_type);
+ icp->icmp_code = 127;
+ (void) send_icmp(nfd, mtu, ip, gwip);
+ PAUSE();
+ printf("3.5.%d ICMP type %d code 127 (all 0's)\r",
+ i * 4 + 1, icp->icmp_type);
+ icp->icmp_code = 128;
+ (void) send_icmp(nfd, mtu, ip, gwip);
+ PAUSE();
+ printf("3.5.%d ICMP type %d code 128 (all 0's)\r",
+ i * 4 + 2, icp->icmp_type);
+ icp->icmp_code = 255;
+ (void) send_icmp(nfd, mtu, ip, gwip);
+ PAUSE();
+ printf("3.5.%d ICMP type %d code 127 (all 0's)\r",
+ i * 4 + 3, icp->icmp_type);
+ }
+ putchar('\n');
+ }
+}
+
+
+/* Perform test 4 (UDP) */
+
+void ip_test4(dev, mtu, ip, gwip, ptest)
+char *dev;
+int mtu;
+ip_t *ip;
+struct in_addr gwip;
+int ptest;
+{
+ struct timeval tv;
+ struct udphdr *u;
+ int nfd, i;
+
+
+ ip->ip_hl = sizeof(*ip) >> 2;
+ ip->ip_v = IPVERSION;
+ ip->ip_tos = 0;
+ ip->ip_off = 0;
+ ip->ip_ttl = 60;
+ ip->ip_p = IPPROTO_UDP;
+ ip->ip_sum = 0;
+ u = (udphdr_t *)((char *)ip + (ip->ip_hl << 2));
+ u->uh_sport = 1;
+ u->uh_dport = 1;
+ u->uh_ulen = sizeof(*u) + 4;
+ nfd = initdevice(dev, u->uh_sport, 1);
+
+ if (!ptest || (ptest == 1)) {
+ /*
+ * Test 1. ulen > packet
+ */
+ u->uh_ulen = sizeof(*u) + 4;
+ ip->ip_len = (ip->ip_hl << 2) + u->uh_ulen;
+ printf("4.1 UDP uh_ulen > packet size - short packets\n");
+ for (i = u->uh_ulen * 2; i > sizeof(*u) + 4; i--) {
+ u->uh_ulen = i;
+ (void) send_udp(nfd, 1500, ip, gwip);
+ printf("%d\r", i);
+ fflush(stdout);
+ PAUSE();
+ }
+ putchar('\n');
+ }
+
+ if (!ptest || (ptest == 2)) {
+ /*
+ * Test 2. ulen < packet
+ */
+ u->uh_ulen = sizeof(*u) + 4;
+ ip->ip_len = (ip->ip_hl << 2) + u->uh_ulen;
+ printf("4.2 UDP uh_ulen < packet size - short packets\n");
+ for (i = u->uh_ulen * 2; i > sizeof(*u) + 4; i--) {
+ ip->ip_len = i;
+ (void) send_udp(nfd, 1500, ip, gwip);
+ printf("%d\r", i);
+ fflush(stdout);
+ PAUSE();
+ }
+ putchar('\n');
+ }
+
+ if (!ptest || (ptest == 3)) {
+ /*
+ * Test 3: sport = 0, sport = 1, sport = 32767
+ * sport = 32768, sport = 65535
+ */
+ u->uh_ulen = sizeof(*u) + 4;
+ ip->ip_len = (ip->ip_hl << 2) + u->uh_ulen;
+ printf("4.3.1 UDP sport = 0\n");
+ u->uh_sport = 0;
+ (void) send_udp(nfd, 1500, ip, gwip);
+ printf("0\n");
+ fflush(stdout);
+ PAUSE();
+ printf("4.3.2 UDP sport = 1\n");
+ u->uh_sport = 1;
+ (void) send_udp(nfd, 1500, ip, gwip);
+ printf("1\n");
+ fflush(stdout);
+ PAUSE();
+ printf("4.3.3 UDP sport = 32767\n");
+ u->uh_sport = 32767;
+ (void) send_udp(nfd, 1500, ip, gwip);
+ printf("32767\n");
+ fflush(stdout);
+ PAUSE();
+ printf("4.3.4 UDP sport = 32768\n");
+ u->uh_sport = 32768;
+ (void) send_udp(nfd, 1500, ip, gwip);
+ printf("32768\n");
+ putchar('\n');
+ fflush(stdout);
+ PAUSE();
+ printf("4.3.5 UDP sport = 65535\n");
+ u->uh_sport = 65535;
+ (void) send_udp(nfd, 1500, ip, gwip);
+ printf("65535\n");
+ fflush(stdout);
+ PAUSE();
+ }
+
+ if (!ptest || (ptest == 4)) {
+ /*
+ * Test 4: dport = 0, dport = 1, dport = 32767
+ * dport = 32768, dport = 65535
+ */
+ u->uh_ulen = sizeof(*u) + 4;
+ u->uh_sport = 1;
+ ip->ip_len = (ip->ip_hl << 2) + u->uh_ulen;
+ printf("4.4.1 UDP dport = 0\n");
+ u->uh_dport = 0;
+ (void) send_udp(nfd, 1500, ip, gwip);
+ printf("0\n");
+ fflush(stdout);
+ PAUSE();
+ printf("4.4.2 UDP dport = 1\n");
+ u->uh_dport = 1;
+ (void) send_udp(nfd, 1500, ip, gwip);
+ printf("1\n");
+ fflush(stdout);
+ PAUSE();
+ printf("4.4.3 UDP dport = 32767\n");
+ u->uh_dport = 32767;
+ (void) send_udp(nfd, 1500, ip, gwip);
+ printf("32767\n");
+ fflush(stdout);
+ PAUSE();
+ printf("4.4.4 UDP dport = 32768\n");
+ u->uh_dport = 32768;
+ (void) send_udp(nfd, 1500, ip, gwip);
+ printf("32768\n");
+ fflush(stdout);
+ PAUSE();
+ printf("4.4.5 UDP dport = 65535\n");
+ u->uh_dport = 65535;
+ (void) send_udp(nfd, 1500, ip, gwip);
+ printf("65535\n");
+ fflush(stdout);
+ PAUSE();
+ }
+
+ if (!ptest || (ptest == 4)) {
+ /*
+ * Test 5: sizeof(struct ip) <= MTU <= sizeof(struct udphdr) +
+ * sizeof(struct ip)
+ */
+ printf("4.5 UDP 20 <= MTU <= 32\n");
+ for (i = sizeof(*ip); i <= u->uh_ulen; i++) {
+ (void) send_udp(nfd, i, ip, gwip);
+ printf("%d\r", i);
+ fflush(stdout);
+ PAUSE();
+ }
+ putchar('\n');
+ }
+}
+
+
+/* Perform test 5 (TCP) */
+
+void ip_test5(dev, mtu, ip, gwip, ptest)
+char *dev;
+int mtu;
+ip_t *ip;
+struct in_addr gwip;
+int ptest;
+{
+ struct timeval tv;
+ tcphdr_t *t;
+ int nfd, i;
+
+ t = (tcphdr_t *)((char *)ip + (ip->ip_hl << 2));
+ t->th_x2 = 0;
+ t->th_off = 0;
+ t->th_sport = 1;
+ t->th_dport = 1;
+ t->th_win = 4096;
+ t->th_urp = 0;
+ t->th_sum = 0;
+ t->th_seq = 1;
+ t->th_ack = 0;
+ nfd = initdevice(dev, t->th_sport, 1);
+
+ if (!ptest || (ptest == 1)) {
+ /*
+ * Test 1: flags variations, 0 - 3f
+ */
+ t->th_off = sizeof(*t) >> 2;
+ printf("5.1 Test TCP flag combinations\n");
+ for (i = 0; i <= (TH_URG|TH_ACK|TH_PUSH|TH_RST|TH_SYN|TH_FIN);
+ i++) {
+ t->th_flags = i;
+ (void) send_tcp(nfd, mtu, ip, gwip);
+ printf("%d\r", i);
+ fflush(stdout);
+ PAUSE();
+ }
+ putchar('\n');
+ }
+
+ if (!ptest || (ptest == 2)) {
+ t->th_flags = TH_SYN;
+ /*
+ * Test 2: seq = 0, seq = 1, seq = 0x7fffffff, seq=0x80000000,
+ * seq = 0xa000000, seq = 0xffffffff
+ */
+ printf("5.2.1 TCP seq = 0\n");
+ t->th_seq = 0;
+ (void) send_tcp(nfd, mtu, ip, gwip);
+ fflush(stdout);
+ PAUSE();
+
+ printf("5.2.2 TCP seq = 1\n");
+ t->th_seq = 1;
+ (void) send_tcp(nfd, mtu, ip, gwip);
+ fflush(stdout);
+ PAUSE();
+
+ printf("5.2.3 TCP seq = 0x7fffffff\n");
+ t->th_seq = 0x7fffffff;
+ (void) send_tcp(nfd, mtu, ip, gwip);
+ fflush(stdout);
+ PAUSE();
+
+ printf("5.2.4 TCP seq = 0x80000000\n");
+ t->th_seq = 0x80000000;
+ (void) send_tcp(nfd, mtu, ip, gwip);
+ fflush(stdout);
+ PAUSE();
+
+ printf("5.2.5 TCP seq = 0xc0000000\n");
+ t->th_seq = 0xc0000000;
+ (void) send_tcp(nfd, mtu, ip, gwip);
+ fflush(stdout);
+ PAUSE();
+
+ printf("5.2.6 TCP seq = 0xffffffff\n");
+ t->th_seq = 0xffffffff;
+ (void) send_tcp(nfd, mtu, ip, gwip);
+ fflush(stdout);
+ PAUSE();
+ }
+
+ if (!ptest || (ptest == 3)) {
+ t->th_flags = TH_ACK;
+ /*
+ * Test 3: ack = 0, ack = 1, ack = 0x7fffffff, ack = 0x8000000
+ * ack = 0xa000000, ack = 0xffffffff
+ */
+ printf("5.3.1 TCP ack = 0\n");
+ t->th_ack = 0;
+ (void) send_tcp(nfd, mtu, ip, gwip);
+ fflush(stdout);
+ PAUSE();
+
+ printf("5.3.2 TCP ack = 1\n");
+ t->th_ack = 1;
+ (void) send_tcp(nfd, mtu, ip, gwip);
+ fflush(stdout);
+ PAUSE();
+
+ printf("5.3.3 TCP ack = 0x7fffffff\n");
+ t->th_ack = 0x7fffffff;
+ (void) send_tcp(nfd, mtu, ip, gwip);
+ fflush(stdout);
+ PAUSE();
+
+ printf("5.3.4 TCP ack = 0x80000000\n");
+ t->th_ack = 0x80000000;
+ (void) send_tcp(nfd, mtu, ip, gwip);
+ fflush(stdout);
+ PAUSE();
+
+ printf("5.3.5 TCP ack = 0xc0000000\n");
+ t->th_ack = 0xc0000000;
+ (void) send_tcp(nfd, mtu, ip, gwip);
+ fflush(stdout);
+ PAUSE();
+
+ printf("5.3.6 TCP ack = 0xffffffff\n");
+ t->th_ack = 0xffffffff;
+ (void) send_tcp(nfd, mtu, ip, gwip);
+ fflush(stdout);
+ PAUSE();
+ }
+
+ if (!ptest || (ptest == 4)) {
+ t->th_flags = TH_SYN;
+ /*
+ * Test 4: win = 0, win = 32768, win = 65535
+ */
+ printf("5.4.1 TCP win = 0\n");
+ t->th_seq = 0;
+ (void) send_tcp(nfd, mtu, ip, gwip);
+ fflush(stdout);
+ PAUSE();
+
+ printf("5.4.2 TCP win = 32768\n");
+ t->th_seq = 0x7fff;
+ (void) send_tcp(nfd, mtu, ip, gwip);
+ fflush(stdout);
+ PAUSE();
+
+ printf("5.4.3 TCP win = 65535\n");
+ t->th_win = 0xffff;
+ (void) send_tcp(nfd, mtu, ip, gwip);
+ fflush(stdout);
+ PAUSE();
+ }
+
+#if !defined(linux) && !defined(__SVR4) && !defined(__svr4__)
+ {
+ struct tcpcb *t, tcb;
+ struct tcpiphdr ti;
+ struct sockaddr_in sin;
+ int fd, slen;
+
+ bzero((char *)&sin, sizeof(sin));
+
+ for (i = 1; i < 63; i++) {
+ fd = socket(AF_INET, SOCK_STREAM, 0);
+ sin.sin_addr.s_addr = ip->ip_dst.s_addr;
+ sin.sin_port = htons(i);
+ if (!connect(fd, (struct sockaddr *)&sin, sizeof(sin)))
+ break;
+ }
+
+ if (i == 63) {
+ printf("Couldn't open a TCP socket between ports 1 and 63\n");
+ printf("to host %s for test 5 and 6 - skipping.\n",
+ inet_ntoa(ip->ip_dst));
+ goto skip_five_and_six;
+ }
+
+ bcopy((char *)ip, (char *)&ti, sizeof(*ip));
+ ti.ti_dport = i;
+ slen = sizeof(sin);
+ if (!getsockname(fd, (struct sockaddr *)&sin, &slen))
+ ti.ti_sport = sin.sin_port;
+ if (!(t = find_tcp(fd, &ti))) {
+ printf("Can't find PCB\n");
+ goto skip_five_and_six;
+ }
+ kmemcpy((char*)&tcb, (void *)t, sizeof(tcb));
+ ti.ti_win = tcb.rcv_adv;
+ ti.ti_seq = tcb.snd_nxt - 1;
+ ti.ti_ack = tcb.rcv_nxt;
+
+ if (!ptest || (ptest == 5)) {
+ /*
+ * Test 5: urp
+ */
+ printf("5.1 TCP Urgent pointer\n");
+ ti.ti_urp = 1;
+ (void) send_tcp(nfd, mtu, ip, gwip);
+ PAUSE();
+ ti.ti_urp = 0x7fff;
+ (void) send_tcp(nfd, mtu, ip, gwip);
+ PAUSE();
+ ti.ti_urp = 0x8000;
+ (void) send_tcp(nfd, mtu, ip, gwip);
+ PAUSE();
+ ti.ti_urp = 0xffff;
+ (void) send_tcp(nfd, mtu, ip, gwip);
+ PAUSE();
+ }
+
+ if (!ptest || (ptest == 6)) {
+ /*
+ * Test 6: data offset, off = 0, off is inside, off is outside
+ */
+ printf("6.1 TCP off = 0-15, len = 40\n");
+ for (i = 0; i < 16; i++) {
+ ti.ti_off = ntohs(i);
+ (void) send_tcp(nfd, mtu, ip, gwip);
+ printf("%d\r", i);
+ fflush(stdout);
+ PAUSE();
+ }
+ putchar('\n');
+ }
+
+ (void) close(fd);
+ }
+skip_five_and_six:
+#endif
+ t->th_seq = 1;
+ t->th_ack = 1;
+
+ if (!ptest || (ptest == 7)) {
+ t->th_off = 0;
+ t->th_flags = TH_SYN;
+ /*
+ * Test 7: sport = 0, sport = 1, sport = 32767
+ * sport = 32768, sport = 65535
+ */
+ printf("5.7.1 TCP sport = 0\n");
+ t->th_sport = 0;
+ (void) send_tcp(nfd, mtu, ip, gwip);
+ fflush(stdout);
+ PAUSE();
+
+ printf("5.7.2 TCP sport = 1\n");
+ t->th_sport = 1;
+ (void) send_tcp(nfd, mtu, ip, gwip);
+ fflush(stdout);
+ PAUSE();
+
+ printf("5.7.3 TCP sport = 32767\n");
+ t->th_sport = 32767;
+ (void) send_tcp(nfd, mtu, ip, gwip);
+ fflush(stdout);
+ PAUSE();
+
+ printf("5.7.4 TCP sport = 32768\n");
+ t->th_sport = 32768;
+ (void) send_tcp(nfd, mtu, ip, gwip);
+ fflush(stdout);
+ PAUSE();
+
+ printf("5.7.5 TCP sport = 65535\n");
+ t->th_sport = 65535;
+ (void) send_tcp(nfd, mtu, ip, gwip);
+ fflush(stdout);
+ PAUSE();
+ }
+
+ if (!ptest || (ptest == 8)) {
+ t->th_sport = 1;
+ /*
+ * Test 8: dport = 0, dport = 1, dport = 32767
+ * dport = 32768, dport = 65535
+ */
+ printf("5.8.1 TCP dport = 0\n");
+ t->th_dport = 0;
+ (void) send_tcp(nfd, mtu, ip, gwip);
+ fflush(stdout);
+ PAUSE();
+
+ printf("5.8.2 TCP dport = 1\n");
+ t->th_dport = 1;
+ (void) send_tcp(nfd, mtu, ip, gwip);
+ fflush(stdout);
+ PAUSE();
+
+ printf("5.8.3 TCP dport = 32767\n");
+ t->th_dport = 32767;
+ (void) send_tcp(nfd, mtu, ip, gwip);
+ fflush(stdout);
+ PAUSE();
+
+ printf("5.8.4 TCP dport = 32768\n");
+ t->th_dport = 32768;
+ (void) send_tcp(nfd, mtu, ip, gwip);
+ fflush(stdout);
+ PAUSE();
+
+ printf("5.8.5 TCP dport = 65535\n");
+ t->th_dport = 65535;
+ (void) send_tcp(nfd, mtu, ip, gwip);
+ fflush(stdout);
+ PAUSE();
+ }
+ /* TCP options header checking */
+ /* 0 length options, etc */
+}
+
+
+/* Perform test 6 (exhaust mbuf test) */
+
+void ip_test6(dev, mtu, ip, gwip, ptest)
+char *dev;
+int mtu;
+ip_t *ip;
+struct in_addr gwip;
+int ptest;
+{
+ struct timeval tv;
+ udphdr_t *u;
+ int nfd, i, j, k;
+
+ ip->ip_v = IPVERSION;
+ ip->ip_tos = 0;
+ ip->ip_off = 0;
+ ip->ip_ttl = 60;
+ ip->ip_p = IPPROTO_UDP;
+ ip->ip_sum = 0;
+ u = (udphdr_t *)(ip + 1);
+ u->uh_sport = 1;
+ u->uh_dport = 9;
+ u->uh_sum = 0;
+
+ nfd = initdevice(dev, u->uh_sport, 1);
+ u->uh_sport = htons(u->uh_sport);
+ u->uh_dport = htons(u->uh_dport);
+ u->uh_ulen = 7168;
+
+ for (i = 0; i < 128; i++) {
+ /*
+ * First send the entire packet in 768 byte chunks.
+ */
+ ip->ip_len = sizeof(*ip) + 768 + sizeof(*u);
+ ip->ip_hl = sizeof(*ip) >> 2;
+ ip->ip_off = IP_MF;
+ (void) send_ip(nfd, 1500, ip, gwip, 1);
+ printf("%d %d\r", i, 0);
+ fflush(stdout);
+ PAUSE();
+ /*
+ * And again using 128 byte chunks.
+ */
+ ip->ip_len = sizeof(*ip) + 128 + sizeof(*u);
+ ip->ip_off = IP_MF;
+ (void) send_ip(nfd, 1500, ip, gwip, 1);
+ printf("%d %d\r", i, 0);
+ fflush(stdout);
+ PAUSE();
+
+ for (j = 768; j < 3584; j += 768) {
+ ip->ip_len = sizeof(*ip) + 768;
+ ip->ip_off = IP_MF|(j>>3);
+ (void) send_ip(nfd, 1500, ip, gwip, 1);
+ printf("%d %d\r", i, j);
+ fflush(stdout);
+ PAUSE();
+
+ ip->ip_len = sizeof(*ip) + 128;
+ for (k = j - 768; k < j; k += 128) {
+ ip->ip_off = IP_MF|(k>>3);
+ (void) send_ip(nfd, 1500, ip, gwip, 1);
+ printf("%d %d\r", i, k);
+ fflush(stdout);
+ PAUSE();
+ }
+ }
+ }
+ putchar('\n');
+}
+
+
+/* Perform test 7 (random packets) */
+
+static u_long tbuf[64];
+
+void ip_test7(dev, mtu, ip, gwip, ptest)
+char *dev;
+int mtu;
+ip_t *ip;
+struct in_addr gwip;
+int ptest;
+{
+ ip_t *pip;
+ struct timeval tv;
+ int nfd, i, j;
+ u_char *s;
+
+ nfd = initdevice(dev, 0, 1);
+ pip = (ip_t *)tbuf;
+
+ srand(time(NULL) ^ (getpid() * getppid()));
+
+ printf("7. send 1024 random IP packets.\n");
+
+ for (i = 0; i < 512; i++) {
+ for (s = (u_char *)pip, j = 0; j < sizeof(tbuf); j++, s++)
+ *s = (rand() >> 13) & 0xff;
+ pip->ip_v = IPVERSION;
+ bcopy((char *)&ip->ip_dst, (char *)&pip->ip_dst,
+ sizeof(struct in_addr));
+ pip->ip_sum = 0;
+ pip->ip_len &= 0xff;
+ (void) send_ip(nfd, mtu, pip, gwip, 0);
+ printf("%d\r", i);
+ fflush(stdout);
+ PAUSE();
+ }
+ putchar('\n');
+
+ for (i = 0; i < 512; i++) {
+ for (s = (u_char *)pip, j = 0; j < sizeof(tbuf); j++, s++)
+ *s = (rand() >> 13) & 0xff;
+ pip->ip_v = IPVERSION;
+ pip->ip_off &= 0xc000;
+ bcopy((char *)&ip->ip_dst, (char *)&pip->ip_dst,
+ sizeof(struct in_addr));
+ pip->ip_sum = 0;
+ pip->ip_len &= 0xff;
+ (void) send_ip(nfd, mtu, pip, gwip, 0);
+ printf("%d\r", i);
+ fflush(stdout);
+ PAUSE();
+ }
+ putchar('\n');
+}
diff --git a/contrib/ipfilter/ipsend/larp.c b/contrib/ipfilter/ipsend/larp.c
new file mode 100644
index 000000000000..1eb4b2fe3e7a
--- /dev/null
+++ b/contrib/ipfilter/ipsend/larp.c
@@ -0,0 +1,85 @@
+/*
+ * larp.c (C) 1995 Darren Reed
+ *
+ * The author provides this program as-is, with no gaurantee for its
+ * suitability for any specific purpose. The author takes no responsibility
+ * for the misuse/abuse of this program and provides it for the sole purpose
+ * of testing packet filter policies. This file maybe distributed freely
+ * providing it is not modified and that this notice remains in tact.
+ */
+#if !defined(lint) && defined(LIBC_SCCS)
+static char sccsid[] = "@(#)larp.c 1.1 8/19/95 (C)1995 Darren Reed";
+#endif
+#include <stdio.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#include <net/if.h>
+#include <net/if_arp.h>
+
+/*
+ * lookup host and return
+ * its IP address in address
+ * (4 bytes)
+ */
+int resolve(host, address)
+char *host, *address;
+{
+ struct hostent *hp;
+ u_long add;
+
+ add = inet_addr(host);
+ if (add == -1)
+ {
+ if (!(hp = gethostbyname(host)))
+ {
+ fprintf(stderr, "unknown host: %s\n", host);
+ return -1;
+ }
+ bcopy((char *)hp->h_addr, (char *)address, 4);
+ return 0;
+ }
+ bcopy((char*)&add, address, 4);
+ return 0;
+}
+
+/*
+ * ARP for the MAC address corresponding
+ * to the IP address. This taken from
+ * some BSD program, I cant remember which.
+ */
+int arp(ip, ether)
+char *ip;
+char *ether;
+{
+ static int s = -1;
+ struct arpreq ar;
+ struct sockaddr_in *sin;
+ char *inet_ntoa();
+
+ bzero((char *)&ar, sizeof(ar));
+ sin = (struct sockaddr_in *)&ar.arp_pa;
+ sin->sin_family = AF_INET;
+ bcopy(ip, (char *)&sin->sin_addr.s_addr, 4);
+
+ if (s == -1)
+ if ((s = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
+ {
+ perror("arp: socket");
+ return -1;
+ }
+
+ if (ioctl(s, SIOCGARP, (caddr_t)&ar) == -1)
+ {
+ fprintf(stderr, "(%s):", inet_ntoa(sin->sin_addr));
+ if (errno != ENXIO)
+ perror("SIOCGARP");
+ return -1;
+ }
+
+ bcopy(ar.arp_ha.sa_data, ether, 6);
+ return 0;
+}
diff --git a/contrib/ipfilter/ipsend/linux.h b/contrib/ipfilter/ipsend/linux.h
new file mode 100644
index 000000000000..7eb382b4b7e1
--- /dev/null
+++ b/contrib/ipfilter/ipsend/linux.h
@@ -0,0 +1,17 @@
+/*
+ * (C)opyright 1995 by Darren Reed.
+ *
+ * This code may be freely distributed as long as it retains this notice
+ * and is not changed in any way. The author accepts no responsibility
+ * for the use of this software. I hate legaleese, don't you ?
+ *
+ * @(#)linux.h 1.1 8/19/95
+ */
+
+#include <linux/config.h>
+#ifdef MODULE
+#include <linux/module.h>
+#include <linux/version.h>
+#endif /* MODULE */
+
+#include "ip_compat.h"
diff --git a/contrib/ipfilter/ipsend/lsock.c b/contrib/ipfilter/ipsend/lsock.c
new file mode 100644
index 000000000000..89b6ab7e4e32
--- /dev/null
+++ b/contrib/ipfilter/ipsend/lsock.c
@@ -0,0 +1,261 @@
+/*
+ * lsock.c (C) 1995 Darren Reed
+ *
+ * The author provides this program as-is, with no gaurantee for its
+ * suitability for any specific purpose. The author takes no responsibility
+ * for the misuse/abuse of this program and provides it for the sole purpose
+ * of testing packet filter policies. This file maybe distributed freely
+ * providing it is not modified and that this notice remains in tact.
+ */
+#if !defined(lint) && defined(LIBC_SCCS)
+static char sccsid[] = "@(#)lsock.c 1.2 1/11/96 (C)1995 Darren Reed";
+#endif
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <pwd.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <sys/dir.h>
+#define __KERNEL__
+#if LINUX >= 0200
+# undef UINT_MAX
+# undef INT_MAX
+# undef ULONG_MAX
+# undef LONG_MAX
+# include <linux/notifier.h>
+#endif
+#include <linux/fs.h>
+#if LINUX >= 0200
+#include "linux/netdevice.h"
+#include "net/sock.h"
+#endif
+#undef __KERNEL__
+#include <linux/sched.h>
+#include <linux/netdevice.h>
+#include <nlist.h>
+#include <sys/user.h>
+#include <sys/socket.h>
+#include <math.h>
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <net/if.h>
+#if LINUX < 0103
+#include <net/inet/sock.h>
+#endif
+#include "ip_compat.h"
+#include "tcpip.h"
+
+int nproc;
+struct task_struct *proc;
+
+#ifndef KMEM
+# ifdef _PATH_KMEM
+# define KMEM _PATH_KMEM
+# endif
+#endif
+#ifndef KMEM
+# define KMEM "/dev/kmem"
+#endif
+#ifndef KERNEL
+# define KERNEL "/System.map"
+#endif
+
+int kmemcpy(buf, pos, n)
+char *buf;
+void *pos;
+int n;
+{
+ static int kfd = -1;
+
+ if (kfd == -1)
+ kfd = open(KMEM, O_RDONLY);
+
+ if (lseek(kfd, (off_t)pos, SEEK_SET) == -1)
+ {
+ perror("lseek");
+ return -1;
+ }
+ if (read(kfd, buf, n) == -1)
+ {
+ perror("read");
+ return -1;
+ }
+ return n;
+}
+
+struct nlist names[3] = {
+ { "_task" },
+ { "_nr_tasks" },
+ { NULL }
+ };
+
+struct task_struct *getproc()
+{
+ struct task_struct *p, **pp;
+ void *v;
+ pid_t pid = getpid();
+ int siz, n;
+
+ n = nlist(KERNEL, names);
+ if (n != 0)
+ {
+ fprintf(stderr, "nlist(%#x) == %d\n", names, n);
+ return NULL;
+ }
+ if (kmemcpy((char *)&nproc, (void *)names[1].n_value,
+ sizeof(nproc)) == -1)
+ {
+ fprintf(stderr, "read nproc (%#x)\n", names[1].n_value);
+ return NULL;
+ }
+ siz = nproc * sizeof(struct task_struct *);
+ if (kmemcpy((char *)&v, (void *)names[0].n_value, sizeof(v)) == -1)
+ {
+ fprintf(stderr, "read(%#x,%#x,%d) proc\n",
+ names[0].n_value, &v, sizeof(v));
+ return NULL;
+ }
+ pp = (struct task_struct **)malloc(siz);
+ if (kmemcpy((char *)pp, (void *)v, siz) == -1)
+ {
+ fprintf(stderr, "read(%#x,%#x,%d) proc\n",
+ v, pp, siz);
+ return NULL;
+ }
+ proc = (struct task_struct *)malloc(siz);
+ for (n = 0; n < NR_TASKS; n++)
+ {
+ if (kmemcpy((char *)(proc + n), (void *)pp[n],
+ sizeof(*proc)) == -1)
+ {
+ fprintf(stderr, "read(%#x,%#x,%d) proc\n",
+ pp[n], proc + n, sizeof(*proc));
+ return NULL;
+ }
+ }
+
+ p = proc;
+
+ for (n = NR_TASKS; n; n--, p++)
+ if (p->pid == pid)
+ break;
+ if (!n)
+ return NULL;
+
+ return p;
+}
+
+
+struct sock *find_tcp(fd, ti)
+int fd;
+struct tcpiphdr *ti;
+{
+ struct sock *s;
+ struct inode *i;
+ struct files_struct *fs;
+ struct task_struct *p;
+ struct file *f, **o;
+
+ if (!(p = getproc()))
+ return NULL;
+
+ fs = p->files;
+ o = (struct file **)calloc(1, sizeof(*o) * (fs->count + 1));
+ if (kmemcpy((char *)o, (void *)fs->fd,
+ (fs->count + 1) * sizeof(*o)) == -1)
+ {
+ fprintf(stderr, "read(%#x,%#x,%d) - fd - failed\n",
+ fs->fd, o, sizeof(*o));
+ return NULL;
+ }
+ f = (struct file *)calloc(1, sizeof(*f));
+ if (kmemcpy((char *)f, (void *)o[fd], sizeof(*f)) == -1)
+ {
+ fprintf(stderr, "read(%#x,%#x,%d) - o[fd] - failed\n",
+ o[fd], f, sizeof(*f));
+ return NULL;
+ }
+
+ i = (struct inode *)calloc(1, sizeof(*i));
+ if (kmemcpy((char *)i, (void *)f->f_inode, sizeof(*i)) == -1)
+ {
+ fprintf(stderr, "read(%#x,%#x,%d) - f_inode - failed\n",
+ f->f_inode, i, sizeof(*i));
+ return NULL;
+ }
+ return i->u.socket_i.data;
+}
+
+int do_socket(dev, mtu, ti, gwip, flags)
+char *dev;
+int mtu;
+struct tcpiphdr *ti;
+struct in_addr gwip;
+int flags;
+{
+ struct sockaddr_in rsin, lsin;
+ struct sock *s, sk;
+ int fd, nfd, len;
+
+ printf("Dest. Port: %d\n", ti->ti_dport);
+
+ fd = socket(AF_INET, SOCK_STREAM, 0);
+ if (fd == -1)
+ {
+ perror("socket");
+ return -1;
+ }
+
+ if (fcntl(fd, F_SETFL, FNDELAY) == -1)
+ {
+ perror("fcntl");
+ return -1;
+ }
+
+ bzero((char *)&lsin, sizeof(lsin));
+ lsin.sin_family = AF_INET;
+ bcopy((char *)&ti->ti_src, (char *)&lsin.sin_addr,
+ sizeof(struct in_addr));
+ if (bind(fd, (struct sockaddr *)&lsin, sizeof(lsin)) == -1)
+ {
+ perror("bind");
+ return -1;
+ }
+ len = sizeof(lsin);
+ (void) getsockname(fd, (struct sockaddr *)&lsin, &len);
+ ti->ti_sport = lsin.sin_port;
+ printf("sport %d\n", ntohs(lsin.sin_port));
+ nfd = initdevice(dev, ntohs(lsin.sin_port));
+
+ if (!(s = find_tcp(fd, ti)))
+ return -1;
+
+ bzero((char *)&rsin, sizeof(rsin));
+ rsin.sin_family = AF_INET;
+ bcopy((char *)&ti->ti_dst, (char *)&rsin.sin_addr,
+ sizeof(struct in_addr));
+ rsin.sin_port = ti->ti_dport;
+ if (connect(fd, (struct sockaddr *)&rsin, sizeof(rsin)) == -1 &&
+ errno != EINPROGRESS)
+ {
+ perror("connect");
+ return -1;
+ }
+ kmemcpy((char*)&sk, (void *)s, sizeof(sk));
+ ti->ti_win = sk.window;
+ ti->ti_seq = sk.sent_seq - 1;
+ ti->ti_ack = sk.rcv_ack_seq;
+
+ if (send_tcp(nfd, mtu, ti, gwip, TH_SYN) == -1)
+ return -1;
+ (void)write(fd, "Hello World\n", 12);
+ sleep(2);
+ close(fd);
+ return 0;
+}
diff --git a/contrib/ipfilter/ipsend/resend.c b/contrib/ipfilter/ipsend/resend.c
new file mode 100644
index 000000000000..59ed75ef082c
--- /dev/null
+++ b/contrib/ipfilter/ipsend/resend.c
@@ -0,0 +1,130 @@
+/*
+ * resend.c (C) 1995 Darren Reed
+ *
+ * This was written to test what size TCP fragments would get through
+ * various TCP/IP packet filters, as used in IP firewalls. In certain
+ * conditions, enough of the TCP header is missing for unpredictable
+ * results unless the filter is aware that this can happen.
+ *
+ */
+#if !defined(lint) && defined(LIBC_SCCS)
+static char sccsid[] = "@(#)resend.c 1.3 1/11/96 (C)1995 Darren Reed";
+#endif
+#include <stdio.h>
+#include <netdb.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+#include <net/if.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/tcp.h>
+#include <netinet/udp.h>
+#include <netinet/ip_icmp.h>
+#ifndef linux
+#include <netinet/ip_var.h>
+#include <netinet/tcpip.h>
+#include <netinet/if_ether.h>
+#endif
+#include "ip_compat.h"
+#ifdef linux
+#include <linux/sockios.h>
+#include "tcpip.h"
+#endif
+#include "ipt.h"
+
+
+static u_char buf[65536]; /* 1 big packet */
+
+extern int initdevice(), arp(), sendip();
+
+void printpacket(ip)
+ip_t *ip;
+{
+ tcphdr_t *t;
+ int i, j;
+
+ t = (tcphdr_t *)((char *)ip + (ip->ip_hl << 2));
+ if (ip->ip_tos)
+ printf("tos %#x ", ip->ip_tos);
+ if (ip->ip_off & 0x3fff)
+ printf("frag @%#x ", (ip->ip_off & 0x1fff) << 3);
+ printf("len %d id %d ", ip->ip_len, ip->ip_id);
+ printf("ttl %d p %d src %s", ip->ip_ttl, ip->ip_p,
+ inet_ntoa(ip->ip_src));
+ if (ip->ip_p == IPPROTO_TCP || ip->ip_p == IPPROTO_UDP)
+ printf(",%d", t->th_sport);
+ printf(" dst %s", inet_ntoa(ip->ip_dst));
+ if (ip->ip_p == IPPROTO_TCP || ip->ip_p == IPPROTO_UDP)
+ printf(",%d", t->th_dport);
+ if (ip->ip_p == IPPROTO_TCP) {
+ printf(" seq %lu:%lu flags ",
+ (u_long)t->th_seq, (u_long)t->th_ack);
+ for (j = 0, i = 1; i < 256; i *= 2, j++)
+ if (t->th_flags & i)
+ printf("%c", "FSRPAU--"[j]);
+ }
+ putchar('\n');
+}
+
+
+int ip_resend(dev, mtu, r, gwip, datain)
+char *dev;
+int mtu;
+struct in_addr gwip;
+struct ipread *r;
+char *datain;
+{
+ ether_header_t *eh;
+ char dhost[6];
+ ip_t *ip;
+ int fd, wfd = initdevice(dev, 0, 5), len, i;
+
+ if (datain)
+ fd = (*r->r_open)(datain);
+ else
+ fd = (*r->r_open)("-");
+
+ if (fd < 0)
+ exit(-1);
+
+ ip = (struct ip *)buf;
+ eh = (ether_header_t *)malloc(sizeof(*eh));
+
+ bzero(&eh->ether_shost, sizeof(eh->ether_shost));
+ if (gwip.s_addr && (arp((char *)&gwip, dhost) == -1))
+ {
+ perror("arp");
+ return -2;
+ }
+
+ while ((i = (*r->r_readip)(buf, sizeof(buf), NULL, NULL)) > 0)
+ {
+ len = ntohs(ip->ip_len);
+ eh = (ether_header_t *)realloc((char *)eh, sizeof(*eh) + len);
+ eh->ether_type = htons((u_short)ETHERTYPE_IP);
+ if (!gwip.s_addr) {
+ if (arp((char *)&gwip,
+ (char *)&eh->ether_dhost) == -1) {
+ perror("arp");
+ continue;
+ }
+ } else
+ bcopy(dhost, (char *)&eh->ether_dhost, sizeof(dhost));
+ bcopy(ip, (char *)(eh + 1), len);
+ printpacket(ip);
+
+ if (sendip(wfd, eh, sizeof(*eh) + len) == -1)
+ {
+ perror("send_packet");
+ break;
+ }
+ }
+ (*r->r_close)();
+ return 0;
+}
diff --git a/contrib/ipfilter/ipsend/sbpf.c b/contrib/ipfilter/ipsend/sbpf.c
new file mode 100644
index 000000000000..5eb9d9b1f97d
--- /dev/null
+++ b/contrib/ipfilter/ipsend/sbpf.c
@@ -0,0 +1,136 @@
+/*
+ * (C)opyright October 1995 Darren Reed. (from tcplog)
+ *
+ * This software may be freely distributed as long as it is not altered
+ * in any way and that this messagge always accompanies it.
+ *
+ */
+#include <stdio.h>
+#include <netdb.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <signal.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/mbuf.h>
+#include <sys/time.h>
+#include <sys/timeb.h>
+#include <sys/socket.h>
+#include <sys/file.h>
+#include <sys/ioctl.h>
+#if BSD < 199103
+#include <sys/fcntlcom.h>
+#endif
+#include <sys/dir.h>
+#include <net/bpf.h>
+
+#include <net/if.h>
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/if_ether.h>
+#include <netinet/ip_var.h>
+#include <netinet/udp.h>
+#include <netinet/udp_var.h>
+#include <netinet/tcp.h>
+#include <netinet/tcpip.h>
+
+#if !defined(lint) && defined(LIBC_SCCS)
+static char sbpf[] = "@(#)sbpf.c 1.3 8/25/95 (C)1995 Darren Reed";
+#endif
+
+/*
+ * the code herein is dervied from libpcap.
+ */
+static u_char *buf = NULL;
+static int bufsize = 0, timeout = 1;
+
+
+int initdevice(device, sport, tout)
+char *device;
+int sport, tout;
+{
+ struct bpf_version bv;
+ struct timeval to;
+ struct ifreq ifr;
+ char bpfname[16];
+ int fd, i;
+
+ for (i = 0; i < 16; i++)
+ {
+ (void) sprintf(bpfname, "/dev/bpf%d", i);
+ if ((fd = open(bpfname, O_RDWR)) >= 0)
+ break;
+ }
+ if (i == 16)
+ {
+ fprintf(stderr, "no bpf devices available as /dev/bpfxx\n");
+ return -1;
+ }
+
+ if (ioctl(fd, BIOCVERSION, (caddr_t)&bv) < 0)
+ {
+ perror("BIOCVERSION");
+ return -1;
+ }
+ if (bv.bv_major != BPF_MAJOR_VERSION ||
+ bv.bv_minor < BPF_MINOR_VERSION)
+ {
+ fprintf(stderr, "kernel bpf (v%d.%d) filter out of date:\n",
+ bv.bv_major, bv.bv_minor);
+ fprintf(stderr, "current version: %d.%d\n",
+ BPF_MAJOR_VERSION, BPF_MINOR_VERSION);
+ return -1;
+ }
+
+ (void) strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
+ if (ioctl(fd, BIOCSETIF, &ifr) == -1)
+ {
+ fprintf(stderr, "%s(%d):", ifr.ifr_name, fd);
+ perror("BIOCSETIF");
+ exit(1);
+ }
+ /*
+ * get kernel buffer size
+ */
+ if (ioctl(fd, BIOCGBLEN, &bufsize) == -1)
+ {
+ perror("BIOCSBLEN");
+ exit(-1);
+ }
+ buf = (u_char*)malloc(bufsize);
+ /*
+ * set the timeout
+ */
+ timeout = tout;
+ to.tv_sec = 1;
+ to.tv_usec = 0;
+ if (ioctl(fd, BIOCSRTIMEOUT, (caddr_t)&to) == -1)
+ {
+ perror("BIOCSRTIMEOUT");
+ exit(-1);
+ }
+
+ (void) ioctl(fd, BIOCFLUSH, 0);
+ return fd;
+}
+
+
+/*
+ * output an IP packet onto a fd opened for /dev/bpf
+ */
+int sendip(fd, pkt, len)
+int fd, len;
+char *pkt;
+{
+ if (write(fd, pkt, len) == -1)
+ {
+ perror("send");
+ return -1;
+ }
+
+ return len;
+}
diff --git a/contrib/ipfilter/ipsend/sdlpi.c b/contrib/ipfilter/ipsend/sdlpi.c
new file mode 100644
index 000000000000..eabd61eb7344
--- /dev/null
+++ b/contrib/ipfilter/ipsend/sdlpi.c
@@ -0,0 +1,130 @@
+/*
+ * (C)opyright October 1992 Darren Reed. (from tcplog)
+ *
+ * This software may be freely distributed as long as it is not altered
+ * in any way and that this messagge always accompanies it.
+ *
+ * The author of this software makes no garuntee about the
+ * performance of this package or its suitability to fulfill any purpose.
+ *
+ */
+
+#include <stdio.h>
+#include <netdb.h>
+#include <ctype.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/timeb.h>
+#include <sys/socket.h>
+#include <sys/file.h>
+#include <sys/ioctl.h>
+#include <sys/stropts.h>
+
+#include <sys/pfmod.h>
+#include <sys/bufmod.h>
+#include <sys/dlpi.h>
+
+#include <net/if.h>
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/if_ether.h>
+#include <netinet/ip_var.h>
+#include <netinet/udp.h>
+#include <netinet/udp_var.h>
+#include <netinet/tcp.h>
+#include <netinet/tcpip.h>
+
+#include "ip_compat.h"
+
+#if !defined(lint) && defined(LIBC_SCCS)
+static char snitid[] = "@(#)sdlpi.c 1.3 10/30/95 (C)1995 Darren Reed";
+#endif
+
+#define CHUNKSIZE 8192
+#define BUFSPACE (4*CHUNKSIZE)
+
+
+/*
+ * Be careful to only include those defined in the flags option for the
+ * interface are included in the header size.
+ */
+int initdevice(device, sport, tout)
+char *device;
+int sport, tout;
+{
+ char devname[16], *s, buf[256];
+ int i, fd;
+
+ (void) sprintf(devname, "/dev/%s", device);
+
+ s = devname + 5;
+ while (*s && !isdigit(*s))
+ s++;
+ if (!*s)
+ {
+ fprintf(stderr, "bad device name %s\n", devname);
+ exit(-1);
+ }
+ i = atoi(s);
+ *s = '\0';
+ /*
+ * For writing
+ */
+ if ((fd = open(devname, O_RDWR)) < 0)
+ {
+ fprintf(stderr, "O_RDWR(1) ");
+ perror(devname);
+ exit(-1);
+ }
+
+ if (dlattachreq(fd, i) == -1 || dlokack(fd, buf) == -1)
+ {
+ fprintf(stderr, "DLPI error\n");
+ exit(-1);
+ }
+ dlbindreq(fd, ETHERTYPE_IP, 0, DL_CLDLS, 0, 0);
+ dlbindack(fd, buf);
+ /*
+ * write full headers
+ */
+ if (strioctl(fd, DLIOCRAW, -1, 0, NULL) == -1)
+ {
+ fprintf(stderr, "DLIOCRAW error\n");
+ exit(-1);
+ }
+ return fd;
+}
+
+
+/*
+ * output an IP packet onto a fd opened for /dev/nit
+ */
+int sendip(fd, pkt, len)
+int fd, len;
+char *pkt;
+{
+ struct strbuf dbuf, *dp = &dbuf;
+
+ /*
+ * construct NIT STREAMS messages, first control then data.
+ */
+ dp->buf = pkt;
+ dp->len = len;
+ dp->maxlen = dp->len;
+
+ if (putmsg(fd, NULL, dp, 0) == -1)
+ {
+ perror("putmsg");
+ return -1;
+ }
+ if (ioctl(fd, I_FLUSH, FLUSHW) == -1)
+ {
+ perror("I_FLUSHW");
+ return -1;
+ }
+ return len;
+}
diff --git a/contrib/ipfilter/ipsend/slinux.c b/contrib/ipfilter/ipsend/slinux.c
new file mode 100644
index 000000000000..1767dfeb9ba2
--- /dev/null
+++ b/contrib/ipfilter/ipsend/slinux.c
@@ -0,0 +1,94 @@
+/*
+ * (C)opyright October 1992 Darren Reed. (from tcplog)
+ *
+ * This software may be freely distributed as long as it is not altered
+ * in any way and that this messagge always accompanies it.
+ *
+ * The author of this software makes no garuntee about the
+ * performance of this package or its suitability to fulfill any purpose.
+ *
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <netdb.h>
+#include <ctype.h>
+#include <signal.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/timeb.h>
+#include <sys/socket.h>
+#include <sys/file.h>
+#include <sys/ioctl.h>
+#include <sys/dir.h>
+#include <linux/netdevice.h>
+#include <net/if.h>
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/tcp.h>
+#include "ip_compat.h"
+#include "tcpip.h"
+
+#if !defined(lint) && defined(LIBC_SCCS)
+static char sccsid[] = "@(#)slinux.c 1.2 8/25/95";
+#endif
+
+#define CHUNKSIZE 8192
+#define BUFSPACE (4*CHUNKSIZE)
+
+/*
+ * Be careful to only include those defined in the flags option for the
+ * interface are included in the header size.
+ */
+
+static int timeout;
+static char *eth_dev = NULL;
+
+
+int initdevice(dev, sport, tout)
+char *dev;
+int sport, tout;
+{
+ int fd;
+
+ eth_dev = strdup(dev);
+ if ((fd = socket(AF_INET, SOCK_PACKET, htons(ETHERTYPE_IP))) == -1)
+ {
+ perror("socket(SOCK_PACKET)");
+ exit(-1);
+ }
+
+ return fd;
+}
+
+
+/*
+ * output an IP packet onto a fd opened for /dev/nit
+ */
+int sendip(fd, pkt, len)
+int fd, len;
+char *pkt;
+{
+ struct sockaddr s;
+ struct ifreq ifr;
+
+ strncpy(ifr.ifr_name, eth_dev, sizeof(ifr.ifr_name));
+ if (ioctl(fd, SIOCGIFHWADDR, &ifr) == -1)
+ {
+ perror("SIOCGIFHWADDR");
+ return -1;
+ }
+ bcopy(ifr.ifr_hwaddr.sa_data, pkt + 6, 6);
+ s.sa_family = ETHERTYPE_IP;
+ strncpy(s.sa_data, eth_dev, sizeof(s.sa_data));
+
+ if (sendto(fd, pkt, len, 0, &s, sizeof(s)) == -1)
+ {
+ perror("send");
+ return -1;
+ }
+
+ return len;
+}
diff --git a/contrib/ipfilter/ipsend/snit.c b/contrib/ipfilter/ipsend/snit.c
new file mode 100644
index 000000000000..d02219267398
--- /dev/null
+++ b/contrib/ipfilter/ipsend/snit.c
@@ -0,0 +1,160 @@
+/*
+ * (C)opyright October 1992 Darren Reed. (from tcplog)