summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordarrenr <darrenr@FreeBSD.org>2005-04-25 17:31:50 +0000
committerdarrenr <darrenr@FreeBSD.org>2005-04-25 17:31:50 +0000
commit1c27d898b4c751a3eaf3754898bbfefa174dec6a (patch)
tree230d1d527f6b251fd46e2108f5e341c63e59cb39
parent4a018e38da65e3b750e7541d80879f2b98b3ea95 (diff)
parentd438802dcb3e270d6fcc65f075c808c64853a7c2 (diff)
downloadFreeBSD-src-1c27d898b4c751a3eaf3754898bbfefa174dec6a.zip
FreeBSD-src-1c27d898b4c751a3eaf3754898bbfefa174dec6a.tar.gz
This commit was generated by cvs2svn to compensate for changes in r145510,
which included commits to RCS files with non-trunk default branches.
-rw-r--r--contrib/ipfilter/.cvsignore28
-rw-r--r--contrib/ipfilter/BNF27
-rw-r--r--contrib/ipfilter/BSD/.cvsignore22
-rw-r--r--contrib/ipfilter/BSD/Makefile501
-rw-r--r--contrib/ipfilter/BSD/Makefile.ipsend19
-rw-r--r--contrib/ipfilter/BSD/kupgrade226
-rwxr-xr-xcontrib/ipfilter/BSD/make-devices2
-rw-r--r--contrib/ipfilter/FWTK/fwtk_transparent.diff16
-rw-r--r--contrib/ipfilter/FWTK/fwtkp6
-rw-r--r--contrib/ipfilter/FreeBSD-2.2/files.diffs6
-rw-r--r--contrib/ipfilter/FreeBSD-2.2/files.newconf.diffs6
-rwxr-xr-xcontrib/ipfilter/FreeBSD-2.2/kinstall11
-rw-r--r--contrib/ipfilter/FreeBSD-3/INST.FreeBSD-32
-rwxr-xr-xcontrib/ipfilter/FreeBSD-3/kinstall8
-rwxr-xr-xcontrib/ipfilter/FreeBSD-4.0/ipv6-patch-4.02
-rw-r--r--contrib/ipfilter/FreeBSD-4.0/ipv6-patch-4.12
-rw-r--r--contrib/ipfilter/FreeBSD-4.0/ipv6-patch-4.265
-rwxr-xr-xcontrib/ipfilter/FreeBSD-4.0/kinstall26
-rwxr-xr-xcontrib/ipfilter/FreeBSD-4.0/unkinstall2
-rw-r--r--contrib/ipfilter/FreeBSD/files.diffs6
-rw-r--r--contrib/ipfilter/FreeBSD/files.newconf.diffs6
-rw-r--r--contrib/ipfilter/FreeBSD/files.oldconf.diffs6
-rw-r--r--contrib/ipfilter/FreeBSD/filez.diffs12
-rwxr-xr-xcontrib/ipfilter/FreeBSD/kinstall10
-rw-r--r--contrib/ipfilter/HISTORY813
-rw-r--r--contrib/ipfilter/INST.FreeBSD-2.22
-rw-r--r--contrib/ipfilter/INSTALL.FreeBSD55
-rw-r--r--contrib/ipfilter/IPFILTER.LICENCE57
-rw-r--r--contrib/ipfilter/README3
-rw-r--r--contrib/ipfilter/STYLE.TXT57
-rw-r--r--contrib/ipfilter/WhatsNew40.txt90
-rw-r--r--contrib/ipfilter/bpf-ipf.h452
-rw-r--r--contrib/ipfilter/bpf_filter.c517
-rwxr-xr-xcontrib/ipfilter/bsdinstall9
-rw-r--r--contrib/ipfilter/etc/protocols3
-rw-r--r--contrib/ipfilter/etc/services2
-rw-r--r--contrib/ipfilter/ip_fil_freebsd.c1692
-rw-r--r--contrib/ipfilter/ip_htable.c455
-rw-r--r--contrib/ipfilter/ip_htable.h71
-rw-r--r--contrib/ipfilter/ip_irc_pxy.c435
-rw-r--r--contrib/ipfilter/ip_lookup.c530
-rw-r--r--contrib/ipfilter/ip_lookup.h65
-rw-r--r--contrib/ipfilter/ip_msnrpc_pxy.c328
-rw-r--r--contrib/ipfilter/ip_pool.c786
-rw-r--r--contrib/ipfilter/ip_pool.h87
-rw-r--r--contrib/ipfilter/ip_pptp_pxy.c527
-rw-r--r--contrib/ipfilter/ip_rpcb_pxy.c1460
-rw-r--r--contrib/ipfilter/ip_scan.c594
-rw-r--r--contrib/ipfilter/ip_scan.h108
-rw-r--r--contrib/ipfilter/ip_sync.c1001
-rw-r--r--contrib/ipfilter/ip_sync.h117
-rw-r--r--contrib/ipfilter/ipf.h343
-rw-r--r--contrib/ipfilter/iplang/.cvsignore9
-rw-r--r--contrib/ipfilter/iplang/Makefile35
-rw-r--r--contrib/ipfilter/iplang/iplang.h2
-rw-r--r--contrib/ipfilter/iplang/iplang_l.l23
-rw-r--r--contrib/ipfilter/ipmon.h96
-rw-r--r--contrib/ipfilter/ipsd/Celler/ip_compat.h2
-rw-r--r--contrib/ipfilter/ipsd/Makefile4
-rw-r--r--contrib/ipfilter/ipsd/ipsd.c7
-rw-r--r--contrib/ipfilter/ipsd/ipsd.h5
-rw-r--r--contrib/ipfilter/ipsd/ipsdr.c7
-rw-r--r--contrib/ipfilter/ipsd/linux.h2
-rw-r--r--contrib/ipfilter/ipsd/sbpf.c2
-rw-r--r--contrib/ipfilter/ipsd/sdlpi.c4
-rw-r--r--contrib/ipfilter/ipsd/slinux.c5
-rw-r--r--contrib/ipfilter/ipsd/snit.c5
-rw-r--r--contrib/ipfilter/ipsend/.OLD/ip_compat.h2
-rw-r--r--contrib/ipfilter/ipsend/.cvsignore3
-rw-r--r--contrib/ipfilter/ipsend/44arp.c37
-rw-r--r--contrib/ipfilter/ipsend/Makefile12
-rw-r--r--contrib/ipfilter/ipsend/arp.c35
-rw-r--r--contrib/ipfilter/ipsend/dlcommon.c30
-rw-r--r--contrib/ipfilter/ipsend/dltest.h2
-rw-r--r--contrib/ipfilter/ipsend/hpux.c6
-rw-r--r--contrib/ipfilter/ipsend/in_var.h4
-rw-r--r--contrib/ipfilter/ipsend/ip.c98
-rw-r--r--contrib/ipfilter/ipsend/ip_var.h4
-rw-r--r--contrib/ipfilter/ipsend/ipresend.12
-rw-r--r--contrib/ipfilter/ipsend/ipresend.c33
-rw-r--r--contrib/ipfilter/ipsend/ipsend.12
-rw-r--r--contrib/ipfilter/ipsend/ipsend.h24
-rw-r--r--contrib/ipfilter/ipsend/ipsopt.c28
-rw-r--r--contrib/ipfilter/ipsend/iptest.c33
-rw-r--r--contrib/ipfilter/ipsend/larp.c14
-rw-r--r--contrib/ipfilter/ipsend/linux.h6
-rw-r--r--contrib/ipfilter/ipsend/lsock.c10
-rw-r--r--contrib/ipfilter/ipsend/resend.c41
-rw-r--r--contrib/ipfilter/ipsend/sdlpi.c69
-rw-r--r--contrib/ipfilter/ipsend/sirix.c12
-rw-r--r--contrib/ipfilter/ipsend/slinux.c9
-rw-r--r--contrib/ipfilter/ipsend/snit.c9
-rw-r--r--contrib/ipfilter/ipsend/sockraw.c89
-rw-r--r--contrib/ipfilter/ipsend/tcpip.h15
-rw-r--r--contrib/ipfilter/ipt.h8
-rw-r--r--contrib/ipfilter/kmem.h5
-rw-r--r--contrib/ipfilter/l4check/http.ok2
-rw-r--r--contrib/ipfilter/l4check/l4check.c25
-rw-r--r--contrib/ipfilter/lib/Makefile309
-rw-r--r--contrib/ipfilter/lib/addicmp.c94
-rw-r--r--contrib/ipfilter/lib/addipopt.c67
-rw-r--r--contrib/ipfilter/lib/addkeep.c86
-rw-r--r--contrib/ipfilter/lib/bcopywrap.c12
-rw-r--r--contrib/ipfilter/lib/binprint.c31
-rw-r--r--contrib/ipfilter/lib/buildopts.c44
-rw-r--r--contrib/ipfilter/lib/checkrev.c46
-rw-r--r--contrib/ipfilter/lib/count4bits.c40
-rw-r--r--contrib/ipfilter/lib/count6bits.c29
-rw-r--r--contrib/ipfilter/lib/debug.c37
-rw-r--r--contrib/ipfilter/lib/extras.c114
-rw-r--r--contrib/ipfilter/lib/facpri.c153
-rw-r--r--contrib/ipfilter/lib/facpri.h43
-rw-r--r--contrib/ipfilter/lib/fill6bits.c48
-rw-r--r--contrib/ipfilter/lib/flags.c25
-rw-r--r--contrib/ipfilter/lib/genmask.c56
-rw-r--r--contrib/ipfilter/lib/gethost.c36
-rw-r--r--contrib/ipfilter/lib/getifname.c76
-rw-r--r--contrib/ipfilter/lib/getline.c58
-rw-r--r--contrib/ipfilter/lib/getnattype.c54
-rw-r--r--contrib/ipfilter/lib/getport.c46
-rw-r--r--contrib/ipfilter/lib/getportproto.c32
-rw-r--r--contrib/ipfilter/lib/getproto.c21
-rw-r--r--contrib/ipfilter/lib/getsumd.c15
-rw-r--r--contrib/ipfilter/lib/hexdump.c30
-rw-r--r--contrib/ipfilter/lib/hostmask.c95
-rw-r--r--contrib/ipfilter/lib/hostname.c51
-rw-r--r--contrib/ipfilter/lib/hostnum.c49
-rw-r--r--contrib/ipfilter/lib/icmpcode.c49
-rw-r--r--contrib/ipfilter/lib/inet_addr.c210
-rw-r--r--contrib/ipfilter/lib/initparse.c20
-rw-r--r--contrib/ipfilter/lib/ionames.c40
-rw-r--r--contrib/ipfilter/lib/ipf_dotuning.c60
-rw-r--r--contrib/ipfilter/lib/ipft_ef.c130
-rw-r--r--contrib/ipfilter/lib/ipft_hx.c158
-rw-r--r--contrib/ipfilter/lib/ipft_pc.c252
-rw-r--r--contrib/ipfilter/lib/ipft_sn.c197
-rw-r--r--contrib/ipfilter/lib/ipft_td.c174
-rw-r--r--contrib/ipfilter/lib/ipft_tx.c331
-rw-r--r--contrib/ipfilter/lib/ipoptsec.c58
-rw-r--r--contrib/ipfilter/lib/kmem.c203
-rw-r--r--contrib/ipfilter/lib/kmem.h34
-rw-r--r--contrib/ipfilter/lib/kmemcpywrap.c15
-rw-r--r--contrib/ipfilter/lib/kvatoname.c31
-rw-r--r--contrib/ipfilter/lib/load_hash.c112
-rw-r--r--contrib/ipfilter/lib/load_hashnode.c61
-rw-r--r--contrib/ipfilter/lib/load_pool.c69
-rw-r--r--contrib/ipfilter/lib/load_poolnode.c63
-rw-r--r--contrib/ipfilter/lib/loglevel.c55
-rw-r--r--contrib/ipfilter/lib/make_range.c26
-rw-r--r--contrib/ipfilter/lib/mutex_emul.c80
-rw-r--r--contrib/ipfilter/lib/nametokva.c30
-rw-r--r--contrib/ipfilter/lib/nat_setgroupmap.c34
-rw-r--r--contrib/ipfilter/lib/natparse.c730
-rw-r--r--contrib/ipfilter/lib/ntomask.c38
-rw-r--r--contrib/ipfilter/lib/optname.c65
-rw-r--r--contrib/ipfilter/lib/optprint.c79
-rw-r--r--contrib/ipfilter/lib/optprintv6.c47
-rw-r--r--contrib/ipfilter/lib/optvalue.c34
-rw-r--r--contrib/ipfilter/lib/parse.c754
-rw-r--r--contrib/ipfilter/lib/portname.c42
-rw-r--r--contrib/ipfilter/lib/portnum.c64
-rw-r--r--contrib/ipfilter/lib/ports.c81
-rw-r--r--contrib/ipfilter/lib/print_toif.c32
-rw-r--r--contrib/ipfilter/lib/printactivenat.c85
-rw-r--r--contrib/ipfilter/lib/printaps.c112
-rw-r--r--contrib/ipfilter/lib/printbuf.c32
-rw-r--r--contrib/ipfilter/lib/printfr.c445
-rw-r--r--contrib/ipfilter/lib/printfraginfo.c29
-rw-r--r--contrib/ipfilter/lib/printhash.c144
-rw-r--r--contrib/ipfilter/lib/printhashnode.c52
-rw-r--r--contrib/ipfilter/lib/printhostmap.c13
-rw-r--r--contrib/ipfilter/lib/printhostmask.c46
-rw-r--r--contrib/ipfilter/lib/printifname.c20
-rw-r--r--contrib/ipfilter/lib/printip.c24
-rw-r--r--contrib/ipfilter/lib/printlog.c44
-rw-r--r--contrib/ipfilter/lib/printmask.c30
-rw-r--r--contrib/ipfilter/lib/printnat.c247
-rw-r--r--contrib/ipfilter/lib/printpacket.c89
-rw-r--r--contrib/ipfilter/lib/printpacket6.c43
-rw-r--r--contrib/ipfilter/lib/printpool.c108
-rw-r--r--contrib/ipfilter/lib/printpoolnode.c33
-rw-r--r--contrib/ipfilter/lib/printportcmp.c29
-rw-r--r--contrib/ipfilter/lib/printsbuf.c24
-rw-r--r--contrib/ipfilter/lib/printstate.c189
-rw-r--r--contrib/ipfilter/lib/printtunable.c21
-rw-r--r--contrib/ipfilter/lib/ratoi.c26
-rw-r--r--contrib/ipfilter/lib/ratoui.c26
-rw-r--r--contrib/ipfilter/lib/remove_hash.c53
-rw-r--r--contrib/ipfilter/lib/remove_hashnode.c58
-rw-r--r--contrib/ipfilter/lib/remove_pool.c50
-rw-r--r--contrib/ipfilter/lib/remove_poolnode.c57
-rw-r--r--contrib/ipfilter/lib/resetlexer.c17
-rw-r--r--contrib/ipfilter/lib/rwlock_emul.c125
-rw-r--r--contrib/ipfilter/lib/tcp_flags.c50
-rw-r--r--contrib/ipfilter/lib/tcpflags.c45
-rw-r--r--contrib/ipfilter/lib/tcpoptnames.c22
-rw-r--r--contrib/ipfilter/lib/to_interface.c31
-rw-r--r--contrib/ipfilter/lib/v6ionames.c27
-rw-r--r--contrib/ipfilter/lib/v6optvalue.c39
-rw-r--r--contrib/ipfilter/lib/var.c171
-rw-r--r--contrib/ipfilter/lib/verbose.c37
-rw-r--r--contrib/ipfilter/man/Makefile11
-rw-r--r--contrib/ipfilter/man/ipfilter.4241
-rw-r--r--contrib/ipfilter/man/ipfilter.4.mandoc267
-rw-r--r--contrib/ipfilter/man/ipfs.812
-rw-r--r--contrib/ipfilter/man/ipl.46
-rw-r--r--contrib/ipfilter/man/ipmon.569
-rw-r--r--contrib/ipfilter/man/ipnat.5147
-rw-r--r--contrib/ipfilter/man/ipnat.835
-rw-r--r--contrib/ipfilter/man/ippool.5155
-rw-r--r--contrib/ipfilter/man/ippool.8126
-rw-r--r--contrib/ipfilter/man/ipscan.552
-rw-r--r--contrib/ipfilter/man/ipscan.844
-rw-r--r--contrib/ipfilter/man/mkfilters.12
-rw-r--r--contrib/ipfilter/md5.c314
-rw-r--r--contrib/ipfilter/md5.h72
-rw-r--r--contrib/ipfilter/mlf_ipl.c164
-rw-r--r--contrib/ipfilter/mlf_rule.c168
-rw-r--r--contrib/ipfilter/mlfk_rule.c69
-rw-r--r--contrib/ipfilter/mlh_rule.c114
-rw-r--r--contrib/ipfilter/net/.cvsignore1
-rw-r--r--contrib/ipfilter/opts.h67
-rw-r--r--contrib/ipfilter/pcap-ipf.h35
-rw-r--r--contrib/ipfilter/perl/ipf-mrtg.pl2
-rw-r--r--contrib/ipfilter/perl/ipfmeta.pl210
-rw-r--r--contrib/ipfilter/perl/logfilter.pl2
-rw-r--r--contrib/ipfilter/radix.c1202
-rw-r--r--contrib/ipfilter/radix_ipf.h208
-rw-r--r--contrib/ipfilter/rules/.cvsignore1
-rw-r--r--contrib/ipfilter/rules/example.11
-rw-r--r--contrib/ipfilter/rules/example.101
-rw-r--r--contrib/ipfilter/rules/example.111
-rw-r--r--contrib/ipfilter/rules/example.121
-rw-r--r--contrib/ipfilter/rules/example.131
-rw-r--r--contrib/ipfilter/rules/example.21
-rw-r--r--contrib/ipfilter/rules/example.31
-rw-r--r--contrib/ipfilter/rules/example.41
-rw-r--r--contrib/ipfilter/rules/example.51
-rw-r--r--contrib/ipfilter/rules/example.61
-rw-r--r--contrib/ipfilter/rules/example.71
-rw-r--r--contrib/ipfilter/rules/example.81
-rw-r--r--contrib/ipfilter/rules/example.91
-rw-r--r--contrib/ipfilter/rules/example.sr1
-rw-r--r--contrib/ipfilter/rules/ip_rules3
-rw-r--r--contrib/ipfilter/rules/ipmon.conf24
-rw-r--r--contrib/ipfilter/rules/pool.conf4
-rw-r--r--contrib/ipfilter/samples/.cvsignore4
-rw-r--r--contrib/ipfilter/samples/Makefile10
-rw-r--r--contrib/ipfilter/samples/ipfilter-pb.gifbin795 -> 796 bytes
-rw-r--r--contrib/ipfilter/samples/proxy.c33
-rw-r--r--contrib/ipfilter/samples/relay.c196
-rw-r--r--contrib/ipfilter/samples/userauth.c12
-rw-r--r--contrib/ipfilter/snoop.h4
-rw-r--r--contrib/ipfilter/test/.cvsignore87
-rw-r--r--contrib/ipfilter/test/Makefile89
-rw-r--r--contrib/ipfilter/test/bpftest28
-rw-r--r--contrib/ipfilter/test/dotest3
-rwxr-xr-xcontrib/ipfilter/test/dotest64
-rw-r--r--contrib/ipfilter/test/expected/bpf-f120
-rw-r--r--contrib/ipfilter/test/expected/bpf14
-rw-r--r--contrib/ipfilter/test/expected/f174
-rw-r--r--contrib/ipfilter/test/expected/i110
-rw-r--r--contrib/ipfilter/test/expected/i117
-rw-r--r--contrib/ipfilter/test/expected/i1238
-rw-r--r--contrib/ipfilter/test/expected/i132
-rw-r--r--contrib/ipfilter/test/expected/i148
-rw-r--r--contrib/ipfilter/test/expected/i154
-rw-r--r--contrib/ipfilter/test/expected/i21
-rw-r--r--contrib/ipfilter/test/expected/i37
-rw-r--r--contrib/ipfilter/test/expected/i43
-rw-r--r--contrib/ipfilter/test/expected/i52
-rw-r--r--contrib/ipfilter/test/expected/i68
-rw-r--r--contrib/ipfilter/test/expected/i72
-rw-r--r--contrib/ipfilter/test/expected/i96
-rw-r--r--contrib/ipfilter/test/expected/in18
-rw-r--r--contrib/ipfilter/test/expected/in289
-rw-r--r--contrib/ipfilter/test/expected/in522
-rw-r--r--contrib/ipfilter/test/expected/in63
-rw-r--r--contrib/ipfilter/test/expected/ip168
-rw-r--r--contrib/ipfilter/test/expected/l16
-rw-r--r--contrib/ipfilter/test/expected/l1.b6
-rw-r--r--contrib/ipfilter/test/expected/n113
-rw-r--r--contrib/ipfilter/test/expected/n106
-rw-r--r--contrib/ipfilter/test/expected/n1151
-rw-r--r--contrib/ipfilter/test/expected/n124
-rw-r--r--contrib/ipfilter/test/expected/n446
-rw-r--r--contrib/ipfilter/test/expected/n56
-rw-r--r--contrib/ipfilter/test/expected/n710
-rw-r--r--contrib/ipfilter/test/expected/n85
-rw-r--r--contrib/ipfilter/test/expected/n95
-rw-r--r--contrib/ipfilter/test/expected/ni16
-rw-r--r--contrib/ipfilter/test/expected/ni108
-rw-r--r--contrib/ipfilter/test/expected/ni118
-rw-r--r--contrib/ipfilter/test/expected/ni125
-rw-r--r--contrib/ipfilter/test/expected/ni1332
-rw-r--r--contrib/ipfilter/test/expected/ni1432
-rw-r--r--contrib/ipfilter/test/expected/ni1532
-rw-r--r--contrib/ipfilter/test/expected/ni1632
-rw-r--r--contrib/ipfilter/test/expected/ni218
-rw-r--r--contrib/ipfilter/test/expected/ni36
-rw-r--r--contrib/ipfilter/test/expected/ni46
-rw-r--r--contrib/ipfilter/test/expected/ni593
-rw-r--r--contrib/ipfilter/test/expected/ni69
-rw-r--r--contrib/ipfilter/test/expected/ni74
-rw-r--r--contrib/ipfilter/test/expected/ni88
-rw-r--r--contrib/ipfilter/test/expected/ni95
-rw-r--r--contrib/ipfilter/test/expected/p119
-rw-r--r--contrib/ipfilter/test/expected/p220
-rw-r--r--contrib/ipfilter/test/expected/p333
-rw-r--r--contrib/ipfilter/test/hextest2
-rw-r--r--contrib/ipfilter/test/input/f112
-rw-r--r--contrib/ipfilter/test/input/f1241
-rw-r--r--contrib/ipfilter/test/input/f1348
-rw-r--r--contrib/ipfilter/test/input/f1735
-rw-r--r--contrib/ipfilter/test/input/ipv6.12
-rw-r--r--contrib/ipfilter/test/input/l158
-rw-r--r--contrib/ipfilter/test/input/n13
-rw-r--r--contrib/ipfilter/test/input/n106
-rw-r--r--contrib/ipfilter/test/input/n1116
-rw-r--r--contrib/ipfilter/test/input/n1218
-rw-r--r--contrib/ipfilter/test/input/n47
-rw-r--r--contrib/ipfilter/test/input/n830
-rw-r--r--contrib/ipfilter/test/input/n930
-rw-r--r--contrib/ipfilter/test/input/ni19
-rw-r--r--contrib/ipfilter/test/input/ni104
-rw-r--r--contrib/ipfilter/test/input/ni1224
-rw-r--r--contrib/ipfilter/test/input/ni13235
-rw-r--r--contrib/ipfilter/test/input/ni14235
-rw-r--r--contrib/ipfilter/test/input/ni15235
-rw-r--r--contrib/ipfilter/test/input/ni16235
-rw-r--r--contrib/ipfilter/test/input/ni654
-rw-r--r--contrib/ipfilter/test/input/ni74
-rw-r--r--contrib/ipfilter/test/input/ni924
-rw-r--r--contrib/ipfilter/test/input/p18
-rw-r--r--contrib/ipfilter/test/input/p28
-rw-r--r--contrib/ipfilter/test/input/p312
-rwxr-xr-xcontrib/ipfilter/test/intest3
-rw-r--r--contrib/ipfilter/test/iptest22
-rw-r--r--contrib/ipfilter/test/itest3
-rwxr-xr-xcontrib/ipfilter/test/mhtest2
-rwxr-xr-xcontrib/ipfilter/test/mtest4
-rwxr-xr-xcontrib/ipfilter/test/natipftest55
-rwxr-xr-xcontrib/ipfilter/test/nattest10
-rw-r--r--contrib/ipfilter/test/ptest31
-rw-r--r--contrib/ipfilter/test/regress/bpf-f14
-rw-r--r--contrib/ipfilter/test/regress/bpf14
-rw-r--r--contrib/ipfilter/test/regress/i15
-rw-r--r--contrib/ipfilter/test/regress/i117
-rw-r--r--contrib/ipfilter/test/regress/i1213
-rw-r--r--contrib/ipfilter/test/regress/i138
-rw-r--r--contrib/ipfilter/test/regress/i148
-rw-r--r--contrib/ipfilter/test/regress/i155
-rw-r--r--contrib/ipfilter/test/regress/i21
-rw-r--r--contrib/ipfilter/test/regress/i34
-rw-r--r--contrib/ipfilter/test/regress/i43
-rw-r--r--contrib/ipfilter/test/regress/i68
-rw-r--r--contrib/ipfilter/test/regress/i94
-rw-r--r--contrib/ipfilter/test/regress/in12
-rw-r--r--contrib/ipfilter/test/regress/in289
-rw-r--r--contrib/ipfilter/test/regress/in522
-rw-r--r--contrib/ipfilter/test/regress/in63
-rw-r--r--contrib/ipfilter/test/regress/ip178
-rw-r--r--contrib/ipfilter/test/regress/n103
-rw-r--r--contrib/ipfilter/test/regress/n113
-rw-r--r--contrib/ipfilter/test/regress/n121
-rw-r--r--contrib/ipfilter/test/regress/n41
-rw-r--r--contrib/ipfilter/test/regress/n71
-rw-r--r--contrib/ipfilter/test/regress/n81
-rw-r--r--contrib/ipfilter/test/regress/n91
-rw-r--r--contrib/ipfilter/test/regress/ni10.nat2
-rw-r--r--contrib/ipfilter/test/regress/ni11.nat2
-rw-r--r--contrib/ipfilter/test/regress/ni12.ipf4
-rw-r--r--contrib/ipfilter/test/regress/ni12.nat1
-rw-r--r--contrib/ipfilter/test/regress/ni13.ipf3
-rw-r--r--contrib/ipfilter/test/regress/ni13.nat1
-rw-r--r--contrib/ipfilter/test/regress/ni14.ipf3
-rw-r--r--contrib/ipfilter/test/regress/ni14.nat1
-rw-r--r--contrib/ipfilter/test/regress/ni15.ipf3
-rw-r--r--contrib/ipfilter/test/regress/ni15.nat1
-rw-r--r--contrib/ipfilter/test/regress/ni16.ipf3
-rw-r--r--contrib/ipfilter/test/regress/ni16.nat1
-rw-r--r--contrib/ipfilter/test/regress/ni6.ipf9
-rw-r--r--contrib/ipfilter/test/regress/ni6.nat3
-rw-r--r--contrib/ipfilter/test/regress/ni7.nat2
-rw-r--r--contrib/ipfilter/test/regress/ni8.nat2
-rw-r--r--contrib/ipfilter/test/regress/ni9.ipf1
-rw-r--r--contrib/ipfilter/test/regress/ni9.nat1
-rw-r--r--contrib/ipfilter/test/regress/p1.ipf1
-rw-r--r--contrib/ipfilter/test/regress/p1.pool2
-rw-r--r--contrib/ipfilter/test/regress/p2.ipf1
-rw-r--r--contrib/ipfilter/test/regress/p3.ipf6
-rw-r--r--contrib/ipfilter/test/regress/p3.pool4
-rw-r--r--contrib/ipfilter/test/test.format77
-rwxr-xr-xcontrib/ipfilter/test/vfycksum.pl41
-rw-r--r--contrib/ipfilter/todo46
-rw-r--r--contrib/ipfilter/tools/BNF.ipf80
-rw-r--r--contrib/ipfilter/tools/BNF.ipnat28
-rw-r--r--contrib/ipfilter/tools/Makefile103
-rw-r--r--contrib/ipfilter/tools/ipf.c562
-rw-r--r--contrib/ipfilter/tools/ipf_y.y2126
-rw-r--r--contrib/ipfilter/tools/ipfcomp.c1347
-rw-r--r--contrib/ipfilter/tools/ipfs.c855
-rw-r--r--contrib/ipfilter/tools/ipfstat.c1792
-rw-r--r--contrib/ipfilter/tools/ipftest.c776
-rw-r--r--contrib/ipfilter/tools/ipmon.c1663
-rw-r--r--contrib/ipfilter/tools/ipmon_y.y694
-rw-r--r--contrib/ipfilter/tools/ipnat.c400
-rw-r--r--contrib/ipfilter/tools/ipnat_y.y828
-rw-r--r--contrib/ipfilter/tools/ippool.c700
-rw-r--r--contrib/ipfilter/tools/ippool_y.y415
-rw-r--r--contrib/ipfilter/tools/ipscan_y.y565
-rw-r--r--contrib/ipfilter/tools/ipsyncm.c253
-rw-r--r--contrib/ipfilter/tools/ipsyncs.c272
-rw-r--r--contrib/ipfilter/tools/lex_var.h55
-rw-r--r--contrib/ipfilter/tools/lexer.c632
-rw-r--r--contrib/ipfilter/tools/lexer.h37
-rw-r--r--contrib/ipfilter/typescript121
417 files changed, 41248 insertions, 1733 deletions
diff --git a/contrib/ipfilter/.cvsignore b/contrib/ipfilter/.cvsignore
new file mode 100644
index 0000000..616828f
--- /dev/null
+++ b/contrib/ipfilter/.cvsignore
@@ -0,0 +1,28 @@
+ipf
+sparcv7
+sparcv9
+h
+ipf-darren
+bugs
+ipftest
+patches
+state
+cbits
+CVS
+old
+new
+netinet
+import
+bak
+streams
+cvs.diff
+threads
+glibc
+hp
+windows
+ipnat
+opt_inet6.h
+ippool
+ipmon
+ip_rules.c
+ip_rules.h
diff --git a/contrib/ipfilter/BNF b/contrib/ipfilter/BNF
index cf30ab6..404cc28 100644
--- a/contrib/ipfilter/BNF
+++ b/contrib/ipfilter/BNF
@@ -1,25 +1,26 @@
filter-rule = [ insert ] action in-out [ options ] [ tos ] [ ttl ]
- [ proto ] [ ip ] [ group ].
+ [ proto ] [ ip ] [ group ] [ tag ] [ pps ] .
insert = "@" decnumber .
-action = block | "no-match" | "pass" | log | "count" | skip | auth | call .
+action = block | "pass" | log | "count" | auth | call .
in-out = "in" | "out" .
-options = [ log ] [ "quick" ] [ "on" interface-name [ dup ] [ froute ]
- [ via ] ] .
+options = [ log ] [ "quick" ] [ onif [ dup ] [ froute ] ] .
tos = "tos" decnumber | "tos" hexnumber .
ttl = "ttl" decnumber .
proto = "proto" protocol .
ip = srcdst [ flags ] [ with withopt ] [ icmp ] [ keep ] .
group = [ "head" decnumber ] [ "group" decnumber ] .
+pps = "pps" decnumber .
+onif = "on" interface-name [ "out-via" interface-name ] .
block = "block" [ return-icmp[return-code] | "return-rst" ] .
auth = "auth" | "preauth" .
log = "log" [ "body" ] [ "first" ] [ "or-block" ] [ "level" loglevel ] .
-call = "call" [ "now" ] function-name .
-skip = "skip" decnumber .
+tag = "tag" tagid .
+call = "call" [ "now" ] function-name "/" decnumber.
dup = "dup-to" interface-name[":"ipaddr] .
-via = "in-via" interface-name | "out-via" interface-name .
-froute = "fastroute" | "to" interface-name [ ":" ipaddr ] .
+froute = "fastroute" | "to" interface-name .
+replyto = "reply-to" interface-name [ ":" ipaddr ] .
protocol = "tcp/udp" | "udp" | "tcp" | "icmp" | decnumber .
srcdst = "all" | fromto .
fromto = "from" object "to" object .
@@ -34,8 +35,7 @@ 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" | "keep" "state-age" state-age .
-state-age = decnmber [ "/" decnumber ] .
+keep = "keep" "state" [ "limit" number ] | "keep" "frags" .
nummask = host-name [ "/" decnumber ] .
host-name = ipaddr | hostname | "any" .
@@ -43,8 +43,9 @@ 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 .
+withopt = [ "not" | "no" ] opttype [ [ "," ] withopt ] .
+opttype = "ipopts" | "short" | "nat" | "bad-src" | "lowttl" | "frag" |
+ "mbcast" | "opt" ipopts .
optname = ipopts [ "," optname ] .
ipopts = optlist | "sec-class" [ secname ] .
secname = seclvl [ "," secname ] .
@@ -77,4 +78,4 @@ compare = "=" | "!=" | "<" | ">" | "<=" | ">=" | "eq" | "ne" | "lt" | "gt" |
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" .
+flag = "F" | "S" | "R" | "P" | "A" | "U" | "C" | "W" .
diff --git a/contrib/ipfilter/BSD/.cvsignore b/contrib/ipfilter/BSD/.cvsignore
new file mode 100644
index 0000000..c149a00
--- /dev/null
+++ b/contrib/ipfilter/BSD/.cvsignore
@@ -0,0 +1,22 @@
+ipf
+ipfs
+ipfstat
+ipftest
+ipmon
+ipnat
+ipresend
+ipsend
+iptest
+vnode_if.h
+if_ipl
+i386
+amiga
+FreeBSD*
+BSDOS*
+NetBSD*
+OpenBSD*
+*_lex_var.h
+*_y.c
+*_l.c
+*_y.h
+ip_rules.*
diff --git a/contrib/ipfilter/BSD/Makefile b/contrib/ipfilter/BSD/Makefile
index 50a61e8..72086a0 100644
--- a/contrib/ipfilter/BSD/Makefile
+++ b/contrib/ipfilter/BSD/Makefile
@@ -1,16 +1,14 @@
#
# Copyright (C) 1993-1998 by Darren Reed.
#
-# Redistribution and use in source and binary forms are permitted
-# provided that this notice is preserved and due credit is given
-# to the original author and the contributors.
+# See the IPFILTER.LICENCE file for details on licencing.
#
BINDEST=/usr/sbin
SBINDEST=/sbin
-SEARCHDIRS=$(BINDEST) $(SBINDEST) /bin /usr/bin /sbin /usr/sbin \
- /usr/local/bin /usr/local/sbin
MANDIR=/usr/share/man
-CC=cc -Wall -Wstrict-prototypes -Wuninitialized -O
+SEARCHDIRS!=echo $(BINDEST) $(SBINDEST) /bin /usr/bin /sbin /usr/sbin /usr/local/bin /usr/local/sbin | awk '{for(i=1;i<NF;i++){print $$i;}}' - | sort -u
+
+CC=cc -Wall -Wuninitialized -Wstrict-prototypes -O
CFLAGS=-g -I$(TOP)
#
# For NetBSD/FreeBSD
@@ -21,16 +19,19 @@ INC=-I/usr/include -I/sys -I/sys/sys -I/sys/arch
DEF=-D$(CPU) -D__$(CPU)__ -DINET -DKERNEL -D_KERNEL $(INC) $(DEVFS)
IPDEF=$(DEF) -DGATEWAY -DDIRECTED_BROADCAST
VNODESHDIR=/sys/kern
-MLD=$(ML) vnode_if.h
+MLD=$(ML)
ML=mln_ipl.c
-IPFILC=ip_fil.c
LKM=if_ipl.o
+LKMR=ipfrule.o
DLKM=
+OBJ=.
+DEST=$(OBJ)
MFLAGS="BINDEST=$(BINDEST)" "SBINDEST=$(SBINDEST)" "MANDIR=$(MANDIR)" \
'CFLAGS=$(CFLAGS) $(SOLARIS2)' "IPFLKM=$(IPFLKM)" \
"IPFLOG=$(IPFLOG)" "LOGFAC=$(LOGFAC)" "POLICY=$(POLICY)" \
"SOLARIS2=$(SOLARIS2)" "DEBUG=$(DEBUG)" "DCPU=$(CPU)" \
- "CPUDIR=$(CPUDIR)"
+ "CPUDIR=$(CPUDIR)" "LOOKUP=$(LOOKUP)" "SYNC=$(SYNC)"
+LIBS=-L. -lipf $(LIBBPF)
#
########## ########## ########## ########## ########## ########## ##########
#
@@ -39,205 +40,425 @@ RM=/bin/rm
CHMOD=/bin/chmod
INSTALL=install
#
-MODOBJS=ip_fil.o fil_k.o ml_ipl.o ip_nat.o ip_frag.o ip_state.o ip_proxy.o \
- ip_auth.o ip_log.o
-DFLAGS=$(IPFLKM) $(DEF) $(DLKM)
-IPF=ipf.o parse.o common.o opt.o facpri.o
-IPT=ipt.o parse.o common.o fil.o ipft_sn.o ipft_ef.o ipft_td.o ipft_pc.o \
- opt.o ipft_tx.o misc.o ip_frag_u.o ip_state_u.o ip_nat_u.o ip_proxy_u.o \
- ip_auth_u.o ipft_hx.o ip_fil_u.o ip_log_u.o natparse.o facpri.o \
- printnat.o printstate.o
-IPNAT=ipnat.o kmem.o natparse.o common.o printnat.o
-FILS=fils.o parse.o kmem.o opt.o facpri.o common.o printstate.o
-
-build all: ipf ipfs ipfstat ipftest ipmon ipnat $(LKM)
- /bin/rm -f $(TOP)/ipf
- ln -s `pwd`/ipf $(TOP)
- /bin/rm -f $(TOP)/ipftest
- ln -s `pwd`/ipftest $(TOP)
- /bin/rm -f $(TOP)/ipmon
- ln -s `pwd`/ipmon $(TOP)
- /bin/rm -f $(TOP)/ipnat
- ln -s `pwd`/ipnat $(TOP)
-
-ipfstat: $(FILS)
- $(CC) -static $(DEBUG) $(CFLAGS) $(STATETOP_CFLAGS) $(STATETOP_INC) \
- $(FILS) -o $@ $(LIBS) $(STATETOP_LIB) -lkvm
-
-ipf: $(IPF)
- $(CC) -static $(DEBUG) $(CFLAGS) $(IPF) -o $@ $(LIBS)
-
-ipftest: $(IPT)
- $(CC) $(DEBUG) $(CFLAGS) $(IPT) -o $@ $(LIBS)
-
-ipnat: $(IPNAT)
- $(CC) -static $(DEBUG) $(CFLAGS) $(IPNAT) -o $@ $(LIBS) -lkvm
+MODOBJS=ip_fil.o fil.o ml_ipl.o ip_nat.o ip_frag.o ip_state.o ip_proxy.o \
+ ip_auth.o ip_log.o ip_pool.o ip_htable.o ip_lookup.o ip_rules.o \
+ ip_scan.o ip_sync.o
+# ip_trafcon.o
+DFLAGS=$(IPFLKM) $(IPFLOG) $(LOOKUP) $(SYNC) $(DEF) $(DLKM) $(IPFBPF)
+IPF=ipf.o ipfcomp.o ipf_y.o ipf_l.o
+IPT=ipftest.o fil_u.o ip_frag_u.o ip_state_u.o ip_nat_u.o \
+ ip_proxy_u.o ip_auth_u.o ip_htable_u.o ip_lookup_u.o ip_pool_u.o \
+ ip_scan_u.o ip_sync_u.o ip_rules_u.o ip_fil_u.o ip_log_u.o \
+ ippool_y.o ippool_l.o ipf_y.o ipf_l.o ipnat_y.o ipnat_l.o \
+ md5_u.o radix_u.o bpf_filter_u.o
+# ip_syn_u.o
+#ip_trafcon_u.o
+TOOL=$(TOP)/tools
+IPNAT=ipnat.o ipnat_y.o ipnat_l.o
+IPMON=ipmon.o ipmon_y.o ipmon_l.o
+IPPOOL=ippool_y.o ippool_l.o kmem.o ippool.o
+IPTRAFCON=iptrafcon.o
+PROXYLIST=$(TOP)/ip_ftp_pxy.c $(TOP)/ip_ipsec_pxy.c $(TOP)/ip_irc_pxy.c \
+ $(TOP)/ip_netbios_pxy.c $(TOP)/ip_raudio_pxy.c $(TOP)/ip_rcmd_pxy.c \
+ $(TOP)/ip_rpcb_pxy.c $(TOP)/ip_pptp_pxy.c
+FILS=ipfstat.o
+LIBSRC=$(TOP)/lib
+RANLIB=ranlib
+AROPTS=cq
+HERE!=pwd
+CCARGS=-I. $(DEBUG) $(CFLAGS)
+#
+# Extra is option kernel things we always want in user space.
+#
+EXTRA=$(ALLOPTS)
+
+include $(TOP)/lib/Makefile
+
+build all: machine $(OBJ)/libipf.a ipf ipfs ipfstat ipftest ipmon ipnat \
+ ippool ipscan ipsyncm ipsyncs $(LKM) $(LKMR)
+ -sh -c 'for i in ipf ipftest ipmon ippool ipnat ipscan ipsyncm ipsyncs; do /bin/rm -f $(TOP)/$$i; ln -s `pwd`/$$i $(TOP); done'
+
+machine: Makefile.kmod
+ if [ -f Makefile.kmod ] ; then \
+ make -f Makefile.kmod depend MKUPDATE=no; \
+ fi
+
+Makefile.kmod:
+ if [ -f /usr/share/mk/bsd.kmod.mk -a "`uname -s`" = "NetBSD" ] ; then \
+ rm -f Makefile.kmod; \
+ ln -s /usr/share/mk/bsd.kmod.mk Makefile.kmod; \
+ fi
+
+ipfstat: $(FILS) $(OBJ)/libipf.a
+ $(CC) $(CCARGS) $(STATETOP_CFLAGS) $(STATETOP_INC) $(FILS) \
+ -o $@ $(LIBS) $(STATETOP_LIB) -lkvm
+
+ipf: $(IPF) $(OBJ)/libipf.a
+ $(CC) $(CCARGS) $(IPF) -o $@ $(LIBS) -ll $(LIBBPF)
+
+ipftest: $(IPT) $(OBJ)/libipf.a
+ $(CC) $(CCARGS) $(IPT) -o $@ $(LIBS) -ll $(LIBBPF)
+
+ipnat: $(IPNAT) $(OBJ)/libipf.a
+ $(CC) $(CCARGS) $(IPNAT) -o $@ $(LIBS) -lkvm -ll
ipfs: ipfs.o
- $(CC) -static $(DEBUG) $(CFLAGS) ipfs.o -o $@ $(LIBS)
+ $(CC) $(CCARGS) ipfs.o -o $@
-tests:
- (cd test; make )
+ipsyncm: ipsyncm.o $(OBJ)/libipf.a
+ $(CC) $(CCARGS) ipsyncm.o -o $@ $(LIBS)
-fils.o: $(TOP)/fils.c $(TOP)/ip_fil.h $(TOP)/ipf.h $(TOP)/ip_frag.h \
- $(TOP)/ip_compat.h $(TOP)/ip_state.h $(TOP)/ip_nat.h
- $(CC) $(DEBUG) $(CFLAGS) $(STATETOP_CFLAGS) $(STATETOP_INC) \
- -c $(TOP)/fils.c -o $@
+ipsyncs: ipsyncs.o $(OBJ)/libipf.a
+ $(CC) $(CCARGS) ipsyncs.o -o $@ $(LIBS)
-ipfs.o: $(TOP)/ipfs.c $(TOP)/ip_fil.h $(TOP)/ipf.h $(TOP)/ip_state.h \
- $(TOP)/ip_nat.h
- $(CC) $(DEBUG) $(CFLAGS) -c $(TOP)/ipfs.c -o $@
+ipsyncm.o: $(TOOL)/ipsyncm.c $(TOP)/ip_sync.h
+ $(CC) $(CCARGS) -c $(TOOL)/ipsyncm.c -o $@
-fil.o: $(TOP)/fil.c $(TOP)/ip_fil.h $(TOP)/ipf.h $(TOP)/ip_compat.h
- $(CC) $(DEBUG) $(CFLAGS) -c $(TOP)/fil.c -o $@
+ipsyncs.o: $(TOOL)/ipsyncs.c $(TOP)/ip_sync.h
+ $(CC) $(CCARGS) -c $(TOOL)/ipsyncs.c -o $@
-fil_k.o: $(TOP)/fil.c $(TOP)/ip_fil.h $(TOP)/ipf.h $(TOP)/ip_compat.h \
- $(TOP)/ipl.h
- $(CC) $(DEBUG) $(CFLAGS) $(POLICY) $(DFLAGS) -c $(TOP)/fil.c -o $@
+tests:
+ (cd test; make )
-ipf.o: $(TOP)/ipf.c $(TOP)/ip_fil.h $(TOP)/ipf.h
- $(CC) $(DEBUG) $(CFLAGS) -c $(TOP)/ipf.c -o $@
+ipfstat.o: $(TOOL)/ipfstat.c $(TOP)/ip_fil.h $(TOP)/ipf.h $(TOP)/ip_frag.h \
+ $(TOP)/ip_compat.h $(TOP)/ip_state.h $(TOP)/ip_nat.h $(TOP)/opts.h
+ $(CC) $(CCARGS) $(STATETOP_CFLAGS) $(STATETOP_INC) \
+ -c $(TOOL)/ipfstat.c -o $@
-ipt.o: $(TOP)/ipt.c $(TOP)/ip_fil.h $(TOP)/ipt.h $(TOP)/ipf.h
- $(CC) $(DEBUG) $(CFLAGS) -c $(TOP)/ipt.c -o $@
+ipfs.o: $(TOOL)/ipfs.c $(TOP)/ip_fil.h $(TOP)/ipf.h $(TOP)/ip_state.h \
+ $(TOP)/ip_nat.h $(TOP)/opts.h
+ $(CC) $(CCARGS) -c $(TOOL)/ipfs.c -o $@
-misc.o: $(TOP)/misc.c $(TOP)/ip_fil.h $(TOP)/ipt.h $(TOP)/ipf.h
- $(CC) $(DEBUG) $(CFLAGS) -c $(TOP)/misc.c -o $@
+fil_u.o: $(TOP)/fil.c $(TOP)/ip_fil.h $(TOP)/ipf.h $(TOP)/ip_compat.h \
+ $(TOP)/opts.h $(TOP)/ip_rules.h
+ $(CC) $(CCARGS) $(EXTRA) $(IPFBPF) -D_RADIX_H_ -c $(TOP)/fil.c -o $@
-opt.o: $(TOP)/opt.c $(TOP)/ip_fil.h $(TOP)/ipf.h
- $(CC) $(DEBUG) $(CFLAGS) -c $(TOP)/opt.c -o $@
+fil.o: $(TOP)/fil.c $(TOP)/ip_fil.h $(TOP)/ip_compat.h $(TOP)/ipl.h \
+ $(TOP)/ip_rules.h
+ $(CC) $(CCARGS) $(POLICY) $(DFLAGS) $(IPFBPF) $(COMPIPF) \
+ -c $(TOP)/fil.c -o $@
-ipnat.o: $(TOP)/ipnat.c $(TOP)/ip_fil.h $(TOP)/ipf.h $(TOP)/ip_nat.h
- $(CC) $(DEBUG) $(CFLAGS) -c $(TOP)/ipnat.c -o $@
+ipf.o: $(TOOL)/ipf.c $(TOP)/ip_fil.h $(TOP)/ipf.h $(TOP)/opts.h
+ $(CC) $(CCARGS) -c $(TOOL)/ipf.c -o $@
-natparse.o: $(TOP)/natparse.c $(TOP)/ip_fil.h $(TOP)/ipf.h $(TOP)/ip_nat.h \
- $(TOP)/ip_compat.h
- $(CC) $(DEBUG) $(CFLAGS) -c $(TOP)/natparse.c -o $@
+ipfcomp.o: $(TOOL)/ipfcomp.c $(TOP)/ip_fil.h $(TOP)/ipf.h $(TOP)/opts.h
+ $(CC) $(CCARGS) -c $(TOOL)/ipfcomp.c -o $@
-printnat.o: $(TOP)/printnat.c $(TOP)/ip_fil.h $(TOP)/ipf.h $(TOP)/ip_nat.h \
- $(TOP)/ip_compat.h $(TOP)/ip_proxy.h
- $(CC) $(DEBUG) $(CFLAGS) -c $(TOP)/printnat.c -o $@
+ipftest.o: $(TOOL)/ipftest.c $(TOP)/ip_fil.h $(TOP)/ipt.h $(TOP)/ipf.h \
+ $(TOP)/opts.h
+ $(CC) $(CCARGS) -c $(TOOL)/ipftest.c -o $@
-printstate.o: $(TOP)/printstate.c $(TOP)/ip_fil.h $(TOP)/ipf.h \
- $(TOP)/ip_state.h $(TOP)/ip_compat.h
- $(CC) $(DEBUG) $(CFLAGS) -c $(TOP)/printstate.c -o $@
+ipnat.o: $(TOOL)/ipnat.c $(TOP)/ip_fil.h $(TOP)/ipf.h $(TOP)/ip_nat.h \
+ $(TOP)/opts.h
+ $(CC) $(CCARGS) -c $(TOOL)/ipnat.c -o $@
-ipft_sn.o: $(TOP)/ipft_sn.c $(TOP)/ipt.h $(TOP)/ipf.h $(TOP)/ip_fil.h \
- $(TOP)/snoop.h
- $(CC) $(DEBUG) $(CFLAGS) -c $(TOP)/ipft_sn.c -o $@
+ipnat_y.o: ipnat_y.c ipnat_y.h ipnat_l.h
+ $(CC) $(CCARGS) -c ipnat_y.c -o $@
-ipft_ef.o: $(TOP)/ipft_ef.c $(TOP)/ipf.h $(TOP)/ip_fil.h $(TOP)/ipt.h
- $(CC) $(DEBUG) $(CFLAGS) -c $(TOP)/ipft_ef.c -o $@
+ipnat_l.o: ipnat_l.c ipnat_y.h
+ $(CC) $(CCARGS) -I. -c ipnat_l.c -o $@
-ipft_td.o: $(TOP)/ipft_td.c $(TOP)/ipf.h $(TOP)/ip_fil.h $(TOP)/ipt.h
- $(CC) $(DEBUG) $(CFLAGS) -c $(TOP)/ipft_td.c -o $@
+ipnat_y.c: $(TOOL)/ipnat_y.y
+ (cd $(TOOL); make "DEST=$(HERE)" $(HERE)/$@)
-ipft_pc.o: $(TOP)/ipft_pc.c $(TOP)/ipf.h $(TOP)/ip_fil.h $(TOP)/ipt.h
- $(CC) $(DEBUG) $(CFLAGS) -c $(TOP)/ipft_pc.c -o $@
+ipnat_y.h: ipnat_y.c
-ipft_tx.o: $(TOP)/ipft_tx.c $(TOP)/ipf.h $(TOP)/ip_fil.h $(TOP)/ipt.h
- $(CC) $(DEBUG) $(CFLAGS) -c $(TOP)/ipft_tx.c -o $@
+ipnat_l.c: $(TOOL)/lexer.c $(TOP)/ip_nat.h
+ (cd $(TOOL); make "DEST=$(HERE)" $(HERE)/$@)
-ipft_hx.o: $(TOP)/ipft_hx.c $(TOP)/ipf.h $(TOP)/ip_fil.h $(TOP)/ipt.h
- $(CC) $(DEBUG) $(CFLAGS) -c $(TOP)/ipft_hx.c -o $@
+ipnat_l.h: $(TOOL)/lexer.h
+ (cd $(TOOL); make "DEST=$(HERE)" $(HERE)/$@)
ip_nat_u.o: $(TOP)/ip_nat.c $(TOP)/ip_nat.h $(TOP)/ip_compat.h $(TOP)/ip_fil.h
- $(CC) $(DEBUG) $(CFLAGS) -c $(TOP)/ip_nat.c -o $@
+ $(CC) $(CCARGS) $(EXTRA) -c $(TOP)/ip_nat.c -o $@
ip_proxy_u.o: $(TOP)/ip_proxy.c $(TOP)/ip_proxy.h $(TOP)/ip_compat.h \
- $(TOP)/ip_fil.h $(TOP)/ip_ftp_pxy.c $(TOP)/ip_rcmd_pxy.c \
- $(TOP)/ip_raudio_pxy.c $(TOP)/ip_ipsec_pxy.c $(TOP)/ip_nat.h
- $(CC) $(DEBUG) $(CFLAGS) -c $(TOP)/ip_proxy.c -o $@
+ $(TOP)/ip_fil.h $(PROXYLIST) $(TOP)/ip_nat.h
+ $(CC) $(CCARGS) $(EXTRA) -c $(TOP)/ip_proxy.c -o $@
ip_frag_u.o: $(TOP)/ip_frag.c $(TOP)/ip_frag.h $(TOP)/ip_compat.h \
$(TOP)/ip_fil.h
- $(CC) $(DEBUG) $(CFLAGS) -c $(TOP)/ip_frag.c -o $@
+ $(CC) $(CCARGS) $(EXTRA) -c $(TOP)/ip_frag.c -o $@
ip_state_u.o: $(TOP)/ip_state.c $(TOP)/ip_state.h $(TOP)/ip_compat.h \
$(TOP)/ip_fil.h $(TOP)/ip_nat.h
- $(CC) $(DEBUG) $(CFLAGS) -c $(TOP)/ip_state.c -o $@
+ $(CC) $(CCARGS) $(EXTRA) -c $(TOP)/ip_state.c -o $@
ip_auth_u.o: $(TOP)/ip_auth.c $(TOP)/ip_auth.h $(TOP)/ip_compat.h \
$(TOP)/ip_fil.h
- $(CC) $(DEBUG) $(CFLAGS) -c $(TOP)/ip_auth.c -o $@
+ $(CC) $(CCARGS) $(EXTRA) -c $(TOP)/ip_auth.c -o $@
+
+ip_fil_u.o: $(TOP)/ip_fil.c $(TOP)/ip_fil.h $(TOP)/ip_compat.h
+ $(CC) $(CCARGS) $(EXTRA) -c $(TOP)/ip_fil.c -o $@
+
+ip_rules_u.o: ip_rules.c $(TOP)/ip_compat.h $(TOP)/ip_fil.h \
+ $(TOP)/ip_rules.h
+ $(CC) $(CCARGS) $(EXTRA) -c ip_rules.c -o $@
+
+ip_scan_u.o: $(TOP)/ip_scan.c $(TOP)/ip_compat.h $(TOP)/ip_fil.h \
+ $(TOP)/ip_scan.h
+ $(CC) $(CCARGS) $(EXTRA) -c $(TOP)/ip_scan.c -o $@
-ip_fil_u.o: $(TOP)/$(IPFILC) $(TOP)/ip_fil.h $(TOP)/ip_compat.h
- $(CC) $(DEBUG) $(CFLAGS) -c $(TOP)/$(IPFILC) -o $@
+ip_sync_u.o: $(TOP)/ip_sync.c $(TOP)/ip_compat.h $(TOP)/ip_fil.h \
+ $(TOP)/ip_sync.h
+ $(CC) $(CCARGS) $(EXTRA) -c $(TOP)/ip_sync.c -o $@
+
+ip_pool_u.o: $(TOP)/ip_pool.c $(TOP)/ip_compat.h $(TOP)/ip_fil.h \
+ $(TOP)/ip_pool.h
+ $(CC) $(CCARGS) $(EXTRA) -c $(TOP)/ip_pool.c -o $@
+
+ip_htable_u.o: $(TOP)/ip_htable.c $(TOP)/ip_compat.h $(TOP)/ip_fil.h \
+ $(TOP)/ip_htable.h
+ $(CC) $(CCARGS) $(EXTRA) -c $(TOP)/ip_htable.c -o $@
+
+ip_lookup_u.o: $(TOP)/ip_lookup.c $(TOP)/ip_compat.h $(TOP)/ip_fil.h \
+ $(TOP)/ip_lookup.h $(TOP)/ip_pool.h $(TOP)/ip_htable.h
+ $(CC) $(CCARGS) $(EXTRA) -c $(TOP)/ip_lookup.c -o $@
+
+ip_trafcon_u.o: $(TOP)/ip_trafcon.c $(TOP)/ip_compat.h $(TOP)/ip_fil.h \
+ $(TOP)/ip_trafcon.h
+ $(CC) $(CCARGS) -c $(TOP)/ip_trafcon.c -o $@
ip_log_u.o: $(TOP)/ip_log.c $(TOP)/ip_fil.h $(TOP)/ip_compat.h
- $(CC) $(DEBUG) $(CFLAGS) -c $(TOP)/ip_log.c -o $@
+ $(CC) $(CCARGS) $(EXTRA) -c $(TOP)/ip_log.c -o $@
+
+md5_u.o: $(TOP)/md5.c $(TOP)/md5.h
+ $(CC) $(CCARGS) $(EXTRA) -c $(TOP)/md5.c -o $@
+
+radix_u.o: $(TOP)/md5.c $(TOP)/radix_ipf.h
+ $(CC) $(CCARGS) $(EXTRA) -c $(TOP)/radix.c -o $@
+
+bpf_filter_u.o: $(TOP)/bpf_filter.c $(TOP)/pcap-ipf.h
+ $(CC) $(CCARGS) $(EXTRA) -c $(TOP)/bpf_filter.c -o $@
if_ipl.o: $(MODOBJS)
ld -r $(MODOBJS) -o $(LKM)
${RM} -f if_ipl
+ipfrule.ko.5: ip_rulesx.o $(MLR)
+ ld -warn-common -r -d -o $(.TARGET:S/.ko/.kld/) ip_rulesx.o $(MLR)
+ ld -Bshareable -d -warn-common -o $(LKMR:S/.5$//) $(.TARGET:S/.ko/.kld/)
+ipfrule.ko: ip_rulesx.o $(MLR)
+ gensetdefs ip_rulesx.o $(MLR)
+ $(CC) $(CCARGS) -c setdef0.c
+ $(CC) $(CCARGS) -c setdef1.c
+ ld -Bshareable -o $@ setdef0.o ip_rulesx.o $(MLR) setdef1.o
+
+ipf.ko.5 ipl.ko.5: $(MODOBJS)
+ ld -warn-common -r -d -o $(.TARGET:S/.ko/.kld/) $(MODOBJS)
+ ld -Bshareable -d -warn-common -o $(LKM:S/.5$//) $(.TARGET:S/.ko/.kld/)
+
ipf.ko ipl.ko: $(MODOBJS)
gensetdefs $(MODOBJS)
- $(CC) $(DEBUG) $(CFLAGS) -c setdef0.c
- $(CC) $(DEBUG) $(CFLAGS) -c setdef1.c
- ld -Bshareable -o $(LKM) setdef0.o $(MODOBJS) setdef1.o
+ $(CC) $(CCARGS) -c setdef0.c
+ $(CC) $(CCARGS) -c setdef1.c
+ ld -Bshareable -o $@ setdef0.o $(MODOBJS) setdef1.o
ip_nat.o: $(TOP)/ip_nat.c $(TOP)/ip_nat.h $(TOP)/ip_compat.h $(TOP)/ip_fil.h
- $(CC) $(DEBUG) $(CFLAGS) $(DFLAGS) -c $(TOP)/ip_nat.c -o $@
+ $(CC) $(CCARGS) $(DFLAGS) -c $(TOP)/ip_nat.c -o $@
ip_frag.o: $(TOP)/ip_frag.c $(TOP)/ip_frag.h $(TOP)/ip_compat.h $(TOP)/ip_fil.h
- $(CC) $(DEBUG) $(CFLAGS) $(DFLAGS) -c $(TOP)/ip_frag.c -o $@
+ $(CC) $(CCARGS) $(DFLAGS) -c $(TOP)/ip_frag.c -o $@
ip_state.o: $(TOP)/ip_state.c $(TOP)/ip_state.h $(TOP)/ip_compat.h \
$(TOP)/ip_fil.h $(TOP)/ip_nat.h
- $(CC) $(DEBUG) $(CFLAGS) $(DFLAGS) -c $(TOP)/ip_state.c -o $@
+ $(CC) $(CCARGS) $(DFLAGS) -c $(TOP)/ip_state.c -o $@
ip_proxy.o: $(TOP)/ip_proxy.c $(TOP)/ip_proxy.h $(TOP)/ip_compat.h \
- $(TOP)/ip_fil.h $(TOP)/ip_ftp_pxy.c $(TOP)/ip_raudio_pxy.c \
- $(TOP)/ip_rcmd_pxy.c $(TOP)/ip_ipsec_pxy.c $(TOP)/ip_nat.h
- $(CC) $(DEBUG) $(CFLAGS) $(DFLAGS) -c $(TOP)/ip_proxy.c -o $@
+ $(TOP)/ip_fil.h $(PROXYLIST) $(TOP)/ip_nat.h
+ $(CC) $(CCARGS) $(DFLAGS) -c $(TOP)/ip_proxy.c -o $@
ip_auth.o: $(TOP)/ip_auth.c $(TOP)/ip_auth.h $(TOP)/ip_compat.h \
$(TOP)/ip_fil.h
- $(CC) $(DEBUG) $(CFLAGS) $(DFLAGS) -c $(TOP)/ip_auth.c -o $@
+ $(CC) $(CCARGS) $(DFLAGS) -c $(TOP)/ip_auth.c -o $@
+
+ip_fil.c:
+ /bin/rm -f ip_fil.c
+ ln -s $(TOP)/ip_fil_`uname -s|tr A-Z a-z`.c ip_fil.c
-ip_fil.o: $(TOP)/$(IPFILC) $(TOP)/ip_fil.h $(TOP)/ip_compat.h $(TOP)/ip_nat.h
- $(CC) $(DEBUG) $(CFLAGS) $(DFLAGS) -c $(TOP)/$(IPFILC) -o $@
+ip_fil.o: ip_fil.c $(TOP)/ip_fil.h $(TOP)/ip_compat.h $(TOP)/ip_nat.h
+ $(CC) $(CCARGS) $(DFLAGS) $(COMPIPF) -c ip_fil.c -o $@
ip_log.o: $(TOP)/ip_log.c $(TOP)/ip_compat.h $(TOP)/ip_fil.h
- $(CC) $(DEBUG) $(CFLAGS) $(DFLAGS) -c $(TOP)/ip_log.c -o $@
+ $(CC) $(CCARGS) $(DFLAGS) -c $(TOP)/ip_log.c -o $@
-vnode_if.h: $(VNODESHDIR)/vnode_if.sh $(VNODESHDIR)/vnode_if.src
+ip_scan.o: $(TOP)/ip_scan.c $(TOP)/ip_compat.h $(TOP)/ip_fil.h $(TOP)/ip_scan.h
+ $(CC) $(CCARGS) $(DFLAGS) -c $(TOP)/ip_scan.c -o $@
+
+ip_sync.o: $(TOP)/ip_sync.c $(TOP)/ip_compat.h $(TOP)/ip_fil.h $(TOP)/ip_sync.h
+ $(CC) $(CCARGS) $(DFLAGS) -c $(TOP)/ip_sync.c -o $@
+
+ip_pool.o: $(TOP)/ip_pool.c $(TOP)/ip_compat.h $(TOP)/ip_fil.h \
+ $(TOP)/ip_lookup.h $(TOP)/ip_pool.h
+ $(CC) $(CCARGS) $(DFLAGS) -c $(TOP)/ip_pool.c -o $@
+
+ip_htable.o: $(TOP)/ip_htable.c $(TOP)/ip_compat.h $(TOP)/ip_fil.h \
+ $(TOP)/ip_lookup.h $(TOP)/ip_htable.h
+ $(CC) $(CCARGS) $(DFLAGS) -c $(TOP)/ip_htable.c -o $@
+
+ip_lookup.o: $(TOP)/ip_lookup.c $(TOP)/ip_compat.h $(TOP)/ip_fil.h \
+ $(TOP)/ip_pool.h $(TOP)/ip_htable.h $(TOP)/ip_lookup.h
+ $(CC) $(CCARGS) $(DFLAGS) -c $(TOP)/ip_lookup.c -o $@
+
+ip_trafcon.o: $(TOP)/ip_trafcon.c $(TOP)/ip_compat.h $(TOP)/ip_fil.h \
+ $(TOP)/ip_trafcon.h
+ $(CC) $(CCARGS) $(DFLAGS) -c $(TOP)/ip_trafcon.c -o $@
+
+vnode_if.h: $(VNODESHDIR)/vnode_if.src
mkdir -p ../sys
- sh $(VNODESHDIR)/vnode_if.sh $(VNODESHDIR)/vnode_if.src
+ if [ -f $(VNODESHDIR)/vnode_if.sh ] ; then \
+ sh $(VNODESHDIR)/vnode_if.sh $(VNODESHDIR)/vnode_if.src; \
+ fi
+ if [ -f $(VNODESHDIR)/vnode_if.pl ] ; then \
+ perl $(VNODESHDIR)/vnode_if.pl $(VNODESHDIR)/vnode_if.src; \
+ fi
if [ -f ../sys/vnode_if.h ] ; then mv ../sys/vnode_if.h .; fi
rmdir ../sys
-ml_ipl.o: $(TOP)/$(MLD) $(TOP)/ipl.h
+ml_ipl.o: vnode_if.h $(TOP)/$(MLD) $(TOP)/ipl.h
-/bin/rm -f vnode_if.c
$(CC) -I. $(CFLAGS) $(DFLAGS) -c $(TOP)/$(ML) -o $@
-kmem.o: $(TOP)/kmem.c
- $(CC) $(DEBUG) $(CFLAGS) -c $(TOP)/kmem.c -o $@
+ip_rules.o: ip_rules.c $(TOP)/ip_rules.h
+ $(CC) -I. $(CFLAGS) $(DFLAGS) $(COMPIPF) -c ip_rules.c -o $@
+
+ip_rules.c: $(TOP)/rules/ip_rules $(TOP)/tools/ipfcomp.c ipf
+ ./ipf -cc -nf $(TOP)/rules/ip_rules
+
+$(TOP)/ip_rules.h: ip_rules.c
+ if [ ! -f $(TOP)/ip_rules.h ] ; then \
+ /bin/mv -f ip_rules.h $(TOP); \
+ else \
+ touch $(TOP)/ip_rules.h; \
+ fi
+
+ip_rulesx.o: ip_rules.c $(TOP)/ip_rules.h
+ $(CC) -I. $(CFLAGS) $(DFLAGS) -DIPFILTER_COMPILED -c ip_rules.c -o $@
+
+mlf_rule.o: $(TOP)/mlf_rule.c $(TOP)/ip_rules.h
+ $(CC) -I. $(CFLAGS) $(DFLAGS) -c $(TOP)/mlf_rule.c -o $@
+
+mln_rule.o: $(TOP)/mln_rule.c $(TOP)/ip_rules.h
+ $(CC) -I. $(CFLAGS) $(DFLAGS) -c $(TOP)/mln_rule.c -o $@
+
+mlo_rule.o: $(TOP)/mlo_rule.c $(TOP)/ip_rules.h
+ $(CC) -I. $(CFLAGS) $(DFLAGS) -c $(TOP)/mlo_rule.c -o $@
+
+mlfk_rule.o: $(TOP)/mlfk_rule.c $(TOP)/ip_rules.h
+ $(CC) -I. $(CFLAGS) $(DFLAGS) -c $(TOP)/mlfk_rule.c -o $@
+
+ipf_y.o: ipf_y.c ipf_y.h $(TOP)/ipf.h ipf_l.h $(TOP)/opts.h
+ $(CC) $(CCARGS) $(IPFBPF) -c ipf_y.c -o $@
+
+ipf_l.o: ipf_l.c ipf_y.h $(TOP)/ipf.h ipf_l.h $(TOP)/opts.h
+ $(CC) $(CCARGS) -I. -c ipf_l.c -o $@
+
+ipf_y.c: $(TOOL)/ipf_y.y $(TOP)/ipf.h $(TOP)/opts.h
+ (cd $(TOOL); make "DEST=$(HERE)" $(HERE)/$@)
+
+ipf_y.h: ipf_y.c
+
+ipf_l.c: $(TOOL)/lexer.c $(TOP)/ipf.h $(TOP)/opts.h
+ (cd $(TOOL); make "DEST=$(HERE)" $(HERE)/$@)
+
+ipf_l.h: $(TOOL)/lexer.h
+ (cd $(TOOL); make "DEST=$(HERE)" $(HERE)/$@)
+
+ipmon: $(IPMON) $(OBJ)/libipf.a
+ $(CC) $(CCARGS) $(IPMON) -o $@ $(LIBS) -ll
+
+ipmon.o: $(TOOL)/ipmon.c $(TOP)/ipmon.h
+ $(CC) $(CCARGS) $(LOGFAC) -c $(TOOL)/ipmon.c -o $@
+
+ipmon_y.o: ipmon_y.c ipmon_y.h $(TOP)/ipmon.h ipmon_l.h
+ $(CC) $(CCARGS) -c ipmon_y.c -o $@
+
+ipmon_l.o: ipmon_l.c ipmon_y.h $(TOP)/ipmon.h
+ $(CC) $(CCARGS) -I. -c ipmon_l.c -o $@
+
+ipmon_y.c: $(TOOL)/ipmon_y.y $(TOP)/ipmon.h
+ (cd $(TOOL); make "DEST=$(HERE)" $(HERE)/$@)
+
+ipmon_y.h: ipmon_y.c
+
+ipmon_l.c: $(TOOL)/lexer.c $(TOP)/ipmon.h
+ (cd $(TOOL); make "DEST=$(HERE)" $(HERE)/$@)
+
+ipmon_l.h: $(TOOL)/lexer.h
+ (cd $(TOOL); make "DEST=$(HERE)" $(HERE)/$@)
-parse.o: $(TOP)/parse.c $(TOP)/ip_fil.h
- $(CC) $(DEBUG) $(CFLAGS) -c $(TOP)/parse.c -o $@
+ipscan: ipscan_y.o ipscan_l.o
+ $(CC) $(DEBUG) ipscan_y.o ipscan_l.o -o $@ -ll $(LIBS) -lkvm
-common.o: $(TOP)/common.c $(TOP)/ip_fil.h
- $(CC) $(DEBUG) $(CFLAGS) -c $(TOP)/common.c -o $@
+ipscan_y.o: ipscan_y.c ipscan_y.h $(TOP)/ip_scan.h ipscan_l.h
+ $(CC) $(CCARGS) -c ipscan_y.c -o $@
-facpri.o: $(TOP)/facpri.c $(TOP)/facpri.h
- $(CC) $(DEBUG) $(CFLAGS) -c $(TOP)/facpri.c -o $@
+ipscan_l.o: ipscan_l.c ipscan_y.h $(TOP)/ip_scan.h
+ $(CC) $(CCARGS) -I. -c ipscan_l.c -o $@
-ipmon: $(TOP)/ipmon.c
- $(CC) $(DEBUG) $(CFLAGS) $(LOGFAC) $(TOP)/ipmon.c -o $@ $(LIBS)
+ipscan_y.c: $(TOOL)/ipscan_y.y $(TOP)/ip_scan.h
+ (cd $(TOOL); make "DEST=$(HERE)" $(HERE)/$@)
+
+ipscan_y.h: ipscan_y.c
+
+ipscan_l.c ipscan_l.h: $(TOOL)/lexer.c $(TOP)/ip_scan.h
+ (cd $(TOOL); make "DEST=$(HERE)" $(HERE)/$@)
+
+ippool: $(IPPOOL) $(OBJ)/libipf.a
+ $(CC) $(DEBUG) -I. $(CFLAGS) $(IPPOOL) -o $@ -ll -lkvm -L. -lipf
+
+ippool.o: $(TOOL)/ippool.c $(TOP)/ip_pool.h
+ $(CC) $(CCARGS) -c $(TOOL)/ippool.c -o $@
+
+ippool_y.o: ippool_y.c ippool_y.h $(TOP)/ip_pool.h ippool_l.h
+ $(CC) $(CCARGS) -c ippool_y.c -o $@
+
+ippool_l.o: ippool_l.c ippool_y.h $(TOP)/ip_pool.h
+ $(CC) $(CCARGS) -I. -c ippool_l.c -o $@
+
+ippool_y.c: $(TOOL)/ippool_y.y $(TOP)/ip_pool.h ippool_l.h
+ (cd $(TOOL); make "DEST=$(HERE)" $(HERE)/$@)
+
+ippool_y.h: ippool_y.c
+
+ippool_l.c: $(TOOL)/lexer.c $(TOP)/ip_pool.h
+ (cd $(TOOL); make "DEST=$(HERE)" $(HERE)/$@)
+
+ippool_l.h: $(TOOL)/lexer.h
+ (cd $(TOOL); make "DEST=$(HERE)" $(HERE)/$@)
+
+iptrafcon.o: $(TOP)/iptrafcon.c
+ $(CC) $(CCARGS) -c $< -o $@
+
+iptrafcon: $(IPTRAFCON) $(OBJ)/libipf.a
+ $(CC) $(CCARGS) $(IPTRAFCON) -o $@ $(LIBS)
+
+.y.c:
+
+.l.c:
clean:
- ${RM} -f *.core *.o ipt fils ipf ipfstat ipftest ipmon if_ipl ipnat \
- vnode_if.h $(LKM) ioconf.h *.ko setdef1.c setdef0.c setdefs.h \
- y.tab.? lex.yy.c ipfs
- ${RM} -f ../opt_inet6.h ../ipftest ../ipmon ../ipf ../ipnat
+ ${RM} -f ../ipf ../ipnat ../ipmon ../ippool ../ipftest
+ ${RM} -f ../ipscan ../ipsyncm ../ipsyncs
+ ${RM} -f *.core *.o *.a ipt ipfstat ipf ipfstat ipftest ipmon
+ ${RM} -f if_ipl ipnat ipfrule.ko* ipf.kld*
+ ${RM} -f vnode_if.h $(LKM) ioconf.h *.ko setdef1.c setdef0.c setdefs.h
+ ${RM} -f ip_fil.c ipf_l.c ipf_y.c ipf_y.h ipf_l.h
+ ${RM} -f ipscan ipscan_y.c ipscan_y.h ipscan_l.c ipscan_l.h
+ ${RM} -f ippool ippool_y.c ippool_y.h ippool_l.c ippool_l.h
+ ${RM} -f ipnat_y.c ipnat_y.h ipnat_l.c ipnat_l.h
+ ${RM} -f ipmon_y.c ipmon_y.h ipmon_l.c ipmon_l.h
+ ${RM} -f ipsyncm ipsyncs ipfs ip_rules.c ip_rules.h
${MAKE} -f Makefile.ipsend ${MFLAGS} clean
+ if [ -f Makefile.kmod ] ; then \
+ ${MAKE} -f Makefile.kmod ${MFLAGS} clean; \
+ fi
-(for i in *; do \
if [ -d $${i} -a -f $${i}/Makefile ] ; then \
- cd $${i}; (make clean); cd ..; \
- rm $${i}/Makefile $${i}/Makefile.ipsend; \
+ cd $${i}; (make TOP=../.. clean); cd ..; \
+ /bin/rm -f $${i}/Makefile $${i}/Makefile.ipsend; \
+ /bin/rm -f $${i}/Makefile.kmod; \
rmdir $${i}; \
fi \
done)
@@ -254,15 +475,31 @@ install:
-if [ -d /modules -a -f ipf.ko ] ; then \
cp ipf.ko /modules; \
fi
+ -if [ -d /modules -a -f ipfrule.ko ] ; then \
+ cp ipfrule.ko /modules; \
+ fi
+ -if [ -d /boot/kernel -a -f ipf.ko ] ; then \
+ cp ipf.ko /boot/kernel; \
+ fi
+ -if [ -d /boot/kernel -a -f ipfrule.ko ] ; then \
+ cp ipfrule.ko /boot/kernel; \
+ fi
+ -if [ -d /usr/lkm -a -f if_ipl.o ] ; then \
+ cp if_ipl.o /usr/lkm; \
+ fi
+ -$(INSTALL) -cs -g wheel -m 755 -o root ipscan $(SBINDEST)
+ (cd $(TOP)/man; make INSTALL=$(INSTALL) MANDIR=$(MANDIR) install; cd $(TOP))
@for i in ipf:$(SBINDEST) ipfs:$(SBINDEST) ipnat:$(SBINDEST) \
+ ippool:$(BINDEST) ipsyncm:$(BINDEST) ipsyncs:$(BINDEST) \
ipfstat:$(SBINDEST) ipftest:$(SBINDEST) ipmon:$(BINDEST); do \
def="`expr $$i : '[^:]*:\(.*\)'`"; \
p="`expr $$i : '\([^:]*\):.*'`"; \
+ dd=; \
for d in $(SEARCHDIRS); do \
if [ -f $$d/$$p ] ; then \
echo "$(INSTALL) -cs -g wheel -m 755 -o root $$p $$d"; \
$(INSTALL) -cs -g wheel -m 755 -o root $$p $$d; \
- dd=$$d; \
+ dd=XXX; \
fi; \
done; \
if [ -z "$$dd" ] ; then \
diff --git a/contrib/ipfilter/BSD/Makefile.ipsend b/contrib/ipfilter/BSD/Makefile.ipsend
index 94a3c7a..410ea67 100644
--- a/contrib/ipfilter/BSD/Makefile.ipsend
+++ b/contrib/ipfilter/BSD/Makefile.ipsend
@@ -1,16 +1,18 @@
#
-# $Id: Makefile.ipsend,v 2.2 2000/02/28 08:27:51 darrenr Exp $
+# Id: Makefile.ipsend,v 2.8 2002/05/22 16:15:36 darrenr Exp
#
BINDEST=/usr/sbin
SBINDEST=/sbin
MANDIR=/usr/share/man
-OBJS=ipsend.o ip.o ipsopt.o y.tab.o lex.yy.o
+OBJS=ipsend.o ip.o ipsopt.o iplang_y.o iplang_l.o
IPFTO=ipft_ef.o ipft_hx.o ipft_pc.o ipft_sn.o ipft_td.o ipft_tx.o
-ROBJS=ipresend.o ip.o resend.o $(IPFTO) opt.o
+ROBJS=ipresend.o ip.o resend.o
TOBJS=iptest.o iptests.o ip.o
UNIXOBJS=sbpf.o sock.o 44arp.o
+OBJ=.
+LIBS=-L$(OBJ) -lipf
CC=gcc -Wuninitialized -Wstrict-prototypes -O
CFLAGS=-g -I$(TOP)
@@ -19,14 +21,14 @@ MFLAGS="BINDEST=$(BINDEST)" "SBINDEST=$(SBINDEST)" "MANDIR=$(MANDIR)" \
'CFLAGS=$(CFLAGS) $(SOLARIS2)' "IPFLKM=$(IPFLKM)" \
"IPFLOG=$(IPFLOG)" "LOGFAC=$(LOGFAC)" "POLICY=$(POLICY)" \
"SOLARIS2=$(SOLARIS2)" "DEBUG=$(DEBUG)" "DCPU=$(CPU)" \
- "CPUDIR=$(CPUDIR)"
+ "CPUDIR=$(CPUDIR)" "LOOKUP=$(LOOKUP)"
#
all build bsd-bpf : ipsend ipresend iptest
-y.tab.o: $(TOP)/iplang/iplang_y.y
+iplang_y.o: $(TOP)/iplang/iplang_y.y
(cd $(TOP)/iplang; $(MAKE) ../BSD/$(CPUDIR)/$@ $(MFLAGS) 'DESTDIR=../BSD/$(CPUDIR)' )
-lex.yy.o: $(TOP)/iplang/iplang_l.l
+iplang_l.o: $(TOP)/iplang/iplang_l.l
(cd $(TOP)/iplang; $(MAKE) ../BSD/$(CPUDIR)/$@ $(MFLAGS) 'DESTDIR=../BSD/$(CPUDIR)' )
.c.o:
@@ -42,7 +44,7 @@ iptest: $(TOBJS) $(UNIXOBJS)
$(CC) $(DEBUG) $(TOBJS) $(UNIXOBJS) -o $@ $(LIBS)
clean:
- rm -rf *.o core a.out ipsend ipresend iptest
+ rm -rf *.o core a.out ipsend ipresend iptest iplang_y.* iplang_l.*
ipsend.o: $(TOP)/ipsend/ipsend.c
$(CC) $(DEBUG) $(CFLAGS) -c $(TOP)/ipsend/ipsend.c -o $@
@@ -101,9 +103,6 @@ dlcommon.o: $(TOP)/ipsend/dlcommon.c
sdlpi.o: $(TOP)/ipsend/sdlpi.c
$(CC) $(DEBUG) $(CFLAGS) -c $(TOP)/ipsend/sdlpi.c -o $@
-arp.o: $(TOP)/ipsend/arp.c
- $(CC) $(DEBUG) $(CFLAGS) -c $(TOP)/ipsend/arp.c -o $@
-
install:
-$(INSTALL) -cs -g wheel -m 755 -o root ipsend ipresend iptest $(BINDEST)
diff --git a/contrib/ipfilter/BSD/kupgrade b/contrib/ipfilter/BSD/kupgrade
index ae0b71f..91f32da 100644
--- a/contrib/ipfilter/BSD/kupgrade
+++ b/contrib/ipfilter/BSD/kupgrade
@@ -1,41 +1,89 @@
#!/bin/sh
#
PATH=/sbin:/usr/sbin:/bin:/usr/bin; export PATH
+argv0=`basename $0`
+os=`uname -s`
+rev=`uname -r`
+maj=`expr $rev : '\([0-9]*\)\.'`
+min=`expr $rev : '[0-9]*\.\([0-9]*\)'`
+sub=`expr $rev : '[0-9]*\.[0-9]*\.\([0-9]*\)'`
+
# try to bomb out fast if anything fails....
set -e
-
-argv0=`basename $0`
+
+fullrev=`printf '%02d%02d%02d' $maj $min $sub`
dir=`pwd`
karch=`uname -m`
-os=`uname -s`
-if [ $os = FreeBSD ] ; then
- rev=`uname -r`
- rev=`expr $rev : '\([0-9]*\)\..*'`
- if [ $rev = 2 ] ; then
- echo "Copying /usr/include/osreldate.h to /sys/sys"
- cp /usr/include/osreldate.h /sys/sys
- fi
- if [ -f /sys/contrib/ipfilter/netinet/mlfk_ipl.c ] ; then
- /bin/cp mlfk_ipl.c /sys/contrib/ipfilter/netinet/
- fi
-fi
archdir="/sys/arch/$karch"
ipfdir=/sys/netinet
if [ -d /sys/contrib/ipfilter ] ; then
ipfdir=/sys/contrib/ipfilter/netinet
fi
+if [ -d /sys/dist/ipf ] ; then
+ ipfdir=/sys/dist/ipf/netinet
+fi
confdir="$archdir/conf"
+if [ -f /dev/ipnat ] ; then
+ major=`ls -l /dev/ipnat | sed -e 's/.* \([0-9]*\),.*/\1/'`
+ echo "Major number for IP Filter is $major"
+else
+ major=x
+fi
echo -n "Installing "
-for i in ip_fil.[ch] fil.c ip_nat.[ch] ip_frag.[ch] ip_state.[ch] ip_proxy.[ch] ip_auth.[ch] ip_log.c ip_compat.h ipl.h ip_*_pxy.c ; do
- echo -n "$i "
+for j in auth frag nat proxy scan state sync pool htable lookup rules; do
+ for i in ip_$j.[ch]; do
+ if [ -f "$i" ] ; then
+ echo -n " $i"
+ cp $i $ipfdir
+ chmod 644 $ipfdir/$i
+ fi
+ done
+done
+
+case $os in
+SunOS)
+ case `uname -r` in
+ 5.*)
+ filc=ip_fil_solaris.c
+ ;;
+ 4.*)
+ filc=ip_fil_sunos.c
+ ;;
+ esac
+ ;;
+*BSD)
+ filc=ip_fil_`echo $os | tr A-Z a-z`.c
+ case $os in
+ FreeBSD)
+ cp mlfk_ipl.c $ipfdir/
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+esac
+
+if [ -f $ipfdir/$filc ] ; then
+ echo -n "$filc -> $ipfdir/$filc "
+ cp $filc $ipfdir/$filc
+ chmod 644 $ipfdir/$filc
+fi
+if [ -f $ipfdir/ip_fil.c ] ; then
+ echo -n "$filc -> $ipfdir/ip_fil.c "
+ cp $filc $ipfdir/ip_fil.c
+ chmod 644 $ipfdir/ip_fil.c
+fi
+
+for i in ip_fil.h fil.c ip_log.c ip_compat.h ipl.h ip_*_pxy.c; do
+ echo -n " $i"
cp $i $ipfdir
chmod 644 $ipfdir/$i
done
echo ""
echo -n "Installing into /usr/include/netinet"
-for j in auth compat fil frag nat proxy state ; do
+for j in auth compat fil frag nat proxy scan state sync pool htable lookup; do
i=ip_$j.h
if [ -f "$i" ] ; then
echo -n " $i"
@@ -57,4 +105,148 @@ if [ -f /sys/netinet/ip_fil_compat.h ] ; then
rm /sys/netinet/ip_fil_compat.h
ln -s /sys/netinet/ip_compat.h /sys/netinet/ip_fil_compat.h
fi
+
+if [ $major != x ] ; then
+ if [ ! -e /dev/ipsync ] ; then
+ echo "Creating /dev/ipsync"
+ mknod /dev/ipsync c $major 4
+ fi
+
+ if [ ! -e /dev/ipsync ] ; then
+ echo "Creating /dev/ipscan"
+ mknod /dev/ipsync c $major 5
+ fi
+
+ if [ ! -e /dev/iplookup ] ; then
+ echo "Creating /dev/iplookup"
+ mknod /dev/iplookup c $major 6
+ fi
+fi
+
+set +e
+os=`uname -s`
+if [ $os = FreeBSD -a -f /sys/conf/files ] ; then
+ cd /sys/conf
+ if [ -f options ] ; then
+ if [ ! -f options.preipf4 ] ; then
+ mv options options.preipf4
+ cp -p options.preipf4 options
+ fi
+ for i in SCAN SYNC LOOKUP COMPILED; do
+ grep IPFILTER_$i options >/dev/null 2>&1
+ if [ $? -ne 0 ] ; then
+ echo >> options
+ echo "# extra option for IP Filter" >> options
+ echo "IPFILTER_$i opt_ipfilter.h" >> options
+ fi
+ done
+ fi
+ if [ ! -f files.preipf4 ] ; then
+ mv files files.preipf4
+ cp -p files.preipf4 files
+ fi
+ for i in htable pool lookup; do
+ grep ip_$i.c files >/dev/null 2>&1
+ if [ $? -ne 0 ] ; then
+ echo "contrib/ipfilter/netinet/ip_$i.c optional ipfilter inet ipfilter_lookup" >> files
+ fi
+ done
+ grep ip_sync.c files >/dev/null 2>&1
+ if [ $? -ne 0 ] ; then
+ echo 'contrib/ipfilter/netinet/ip_sync.c optional ipfilter inet ipfilter_sync' >> files
+ fi
+ grep ip_scan.c files >/dev/null 2>&1
+ if [ $? -ne 0 ] ; then
+ echo 'contrib/ipfilter/netinet/ip_scan.c optional ipfilter inet ipfilter_scan' >> files
+ fi
+ grep ip_rules.c files >/dev/null 2>&1
+ if [ $? -ne 0 ] ; then
+ echo 'contrib/ipfilter/netinet/ip_rules.c optional ipfilter inet ipfilter_compiled' >> files
+ fi
+fi
+if [ $os = NetBSD -a -f /sys/conf/files ] ; then
+ cd /sys/conf
+ if [ ! -f files.preipf4 ] ; then
+ mv files files.preipf4
+ cp -p files.preipf4 files
+ fi
+ if [ $fullrev -ge 010600 -a $fullrev -lt 020000 ] ; then
+ for i in htable pool lookup; do
+ grep ip_$i.c files >/dev/null 2>&1
+ if [ $? -ne 0 ] ; then
+ echo "file netinet/ip_$i.c ipfilter & ipfilter_lookup" >> files
+ fi
+ done
+ grep ip_sync.c files >/dev/null 2>&1
+ if [ $? -ne 0 ] ; then
+ echo 'file netinet/ip_sync.c ipfilter & ipfilter_sync' >> files
+ fi
+ grep ip_scan.c files >/dev/null 2>&1
+ if [ $? -ne 0 ] ; then
+ echo 'file netinet/ip_scan.c ipfilter & ipfilter_scan' >> files
+ fi
+ grep ip_rules.c files >/dev/null 2>&1
+ if [ $? -ne 0 ] ; then
+ echo 'file netinet/ip_rules.c ipfilter & ipfilter_compiled' >> files
+ fi
+ fi
+fi
+if [ $os = OpenBSD -a -f /sys/conf/files ] ; then
+ cd /sys/conf
+ if [ ! -f files.preipf4 ] ; then
+ mv files files.preipf4
+ cp -p files.preipf4 files
+ fi
+ if [ $fullrev -ge 030400 ] ; then
+ for i in htable pool lookup; do
+ grep ip_$i.c files >/dev/null 2>&1
+ if [ $? -ne 0 ] ; then
+ echo "file netinet/ip_$i.c ipfilter & ipfilter_lookup" >> files
+ fi
+ done
+ grep ip_sync.c files >/dev/null 2>&1
+ if [ $? -ne 0 ] ; then
+ echo 'file netinet/ip_sync.c ipfilter & ipfilter_sync' >> files
+ fi
+ grep ip_scan.c files >/dev/null 2>&1
+ if [ $? -ne 0 ] ; then
+ echo 'file netinet/ip_scan.c ipfilter & ipfilter_scan' >> files
+ fi
+ grep ip_rules.c files >/dev/null 2>&1
+ if [ $? -ne 0 ] ; then
+ echo 'file netinet/ip_rules.c ipfilter & ipfilter_compiled' >> files
+ fi
+ fi
+fi
+
+if [ -f /usr/src/sys/modules/ipfilter/Makefile -a \
+ ! -f /usr/src/sys/modules/ipfilter/Makefile.orig ] ; then
+cat | (cd /usr/src/sys/modules/ipfilter; patch) <<__EOF__
+*** Makefile.orig Mon Mar 28 09:10:11 2005
+--- Makefile Mon Mar 28 09:12:51 2005
+***************
+*** 5,13 ****
+ KMOD= ipl
+ SRCS= mlfk_ipl.c ip_nat.c ip_frag.c ip_state.c ip_proxy.c ip_auth.c \\
+! ip_log.c ip_fil.c fil.c
+
+ .if !defined(NOINET6)
+ CFLAGS+= -DUSE_INET6
+ .endif
+ CFLAGS+= -I$${.CURDIR}/../../contrib/ipfilter
+! CFLAGS+= -DIPFILTER=1 -DIPFILTER_LKM -DIPFILTER_LOG -DPFIL_HOOKS
+--- 5,15 ----
+ KMOD= ipl
+ SRCS= mlfk_ipl.c ip_nat.c ip_frag.c ip_state.c ip_proxy.c ip_auth.c \\
+! ip_log.c ip_fil.c fil.c ip_lookup.c ip_pool.c ip_htable.c \\
+! ip_sync.c ip_scan.c ip_rules.c
+
+ .if !defined(NOINET6)
+ CFLAGS+= -DUSE_INET6
+ .endif
+ CFLAGS+= -I$${.CURDIR}/../../contrib/ipfilter
+! CFLAGS+= -DIPFILTER=1 -DIPFILTER_LKM -DIPFILTER_LOG -DPFIL_HOOKS \\
+! -DIPFILTER_LOOKUP -DIPFILTER_COMPILED
+__EOF__
+fi
exit 0
diff --git a/contrib/ipfilter/BSD/make-devices b/contrib/ipfilter/BSD/make-devices
index 320bd80..d512e1c 100755
--- a/contrib/ipfilter/BSD/make-devices
+++ b/contrib/ipfilter/BSD/make-devices
@@ -26,3 +26,5 @@ mknod /dev/ipl c $major 0
mknod /dev/ipnat c $major 1
mknod /dev/ipstate c $major 2
mknod /dev/ipauth c $major 3
+mknod /dev/ipsync c $major 4
+mknod /dev/ipscan c $major 5
diff --git a/contrib/ipfilter/FWTK/fwtk_transparent.diff b/contrib/ipfilter/FWTK/fwtk_transparent.diff
index 69962b6..a6c21fa 100644
--- a/contrib/ipfilter/FWTK/fwtk_transparent.diff
+++ b/contrib/ipfilter/FWTK/fwtk_transparent.diff
@@ -124,7 +124,7 @@ diff -cr ../TIS.orig/fwtk/Makefile.config.solaris fwtk/Makefile.config.solaris
***************
*** 11,30 ****
#
- # RcsId: "$Header: /devel/CVS/IP-Filter/FWTK/fwtk_transparent.diff,v 2.1 1999/08/04 17:40:48 darrenr Exp $"
+ # RcsId: "$Header: /devel/CVS/IP-Filter/FWTK/fwtk_transparent.diff,v 2.2 2001/02/28 09:36:06 darrenr Exp $"
# Your C compiler (eg, "cc" or "gcc")
@@ -145,7 +145,7 @@ diff -cr ../TIS.orig/fwtk/Makefile.config.solaris fwtk/Makefile.config.solaris
-Dgethostbyaddr=res_gethostbyaddr -Dgetnetbyname=res_getnetbyname \
--- 11,34 ----
#
- # RcsId: "$Header: /devel/CVS/IP-Filter/FWTK/fwtk_transparent.diff,v 2.1 1999/08/04 17:40:48 darrenr Exp $"
+ # RcsId: "$Header: /devel/CVS/IP-Filter/FWTK/fwtk_transparent.diff,v 2.2 2001/02/28 09:36:06 darrenr Exp $"
+ #
+ # Path to sources of ip_filter (ip_nat.h required in lib/hnam.c)
@@ -649,15 +649,15 @@ diff -cr ../TIS.orig/fwtk/lib/hnam.c fwtk/lib/hnam.c
+ 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) {
++ if((natfd=open("/dev/ipnat",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));
++ if(ptr) *ptr=ntohs(natlookup.nl_realport);
++ sprintf(buf,"%s",inet_ntoa(natlookup.nl_realip));
+ #endif
+
+ #if defined(SOLARIS) /* for Solaris */
@@ -679,15 +679,15 @@ diff -cr ../TIS.orig/fwtk/lib/hnam.c fwtk/lib/hnam.c
+ 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) {
++ if( (natfd=open(IPL_NAT,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));
++ if(ptr) *ptr=ntohs(natlookup.nl_realport);
++ sprintf(buf,"%s",inet_ntoa(natlookup.nl_realip));
+ #endif
+
+ /* No transparent proxy support */
diff --git a/contrib/ipfilter/FWTK/fwtkp b/contrib/ipfilter/FWTK/fwtkp
index 8f4819a..aba869d 100644
--- a/contrib/ipfilter/FWTK/fwtkp
+++ b/contrib/ipfilter/FWTK/fwtkp
@@ -482,15 +482,15 @@ diff -c -r ./lib/hnam.c ../../NEW/fwtk/lib/hnam.c
+ 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) {
++ if((natfd=open(IPL_NAT,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));
++ if(ptr) *ptr=ntohs(natlookup.nl_realport);
++ sprintf(buf,"%s",inet_ntoa(natlookup.nl_realip));
+ #endif
+
+ /* No transparent proxy support */
diff --git a/contrib/ipfilter/FreeBSD-2.2/files.diffs b/contrib/ipfilter/FreeBSD-2.2/files.diffs
index 10bce4b..2ada3fa 100644
--- a/contrib/ipfilter/FreeBSD-2.2/files.diffs
+++ b/contrib/ipfilter/FreeBSD-2.2/files.diffs
@@ -2,7 +2,7 @@
--- files Sat Apr 4 10:52:58 1998
***************
*** 222,227 ****
---- 222,236 ----
+--- 222,240 ----
netinet/tcp_timer.c optional inet
netinet/tcp_usrreq.c optional inet
netinet/udp_usrreq.c optional inet
@@ -15,6 +15,10 @@
+ netinet/mlf_ipl.c optional ipfilter inet
+ netinet/ip_auth.c optional ipfilter inet
+ netinet/ip_log.c optional ipfilter inet
++ netinet/ip_scan.c optional ipfilter inet
++ netinet/ip_sync.c optional ipfilter inet
++ netinet/ip_pool.c optional ipfilter_pool inet
++ netinet/ip_rules.c optional ipfilter_compiled ipfilter inet
netipx/ipx.c optional ipx
netipx/ipx_cksum.c optional ipx
netipx/ipx_input.c optional ipx
diff --git a/contrib/ipfilter/FreeBSD-2.2/files.newconf.diffs b/contrib/ipfilter/FreeBSD-2.2/files.newconf.diffs
index 67894d0..82599f1 100644
--- a/contrib/ipfilter/FreeBSD-2.2/files.newconf.diffs
+++ b/contrib/ipfilter/FreeBSD-2.2/files.newconf.diffs
@@ -2,7 +2,7 @@
--- files.newconf Sun Jun 25 02:19:10 1995
***************
*** 161,166 ****
---- 161,175 ----
+--- 161,179 ----
file netinet/ip_input.c inet
file netinet/ip_mroute.c inet
file netinet/ip_output.c inet
@@ -15,6 +15,10 @@
+ file netinet/ip_auth.c ipfilter
+ file netinet/ip_log.c ipfilter
+ file netinet/mlf_ipl.c ipfilter
++ file netinet/ip_scan.c ipfilter
++ file netinet/ip_sync.c ipfilter
++ file netinet/ip_pool.c ipfilter_pool
++ file netinet/ip_rules.c ipfilter_compiled
file netinet/raw_ip.c inet
file netinet/tcp_debug.c inet
file netinet/tcp_input.c inet
diff --git a/contrib/ipfilter/FreeBSD-2.2/kinstall b/contrib/ipfilter/FreeBSD-2.2/kinstall
index 9ecadc4..5a4368e 100755
--- a/contrib/ipfilter/FreeBSD-2.2/kinstall
+++ b/contrib/ipfilter/FreeBSD-2.2/kinstall
@@ -8,18 +8,17 @@ set confdir="$archdir/conf"
if ( $dir =~ */FreeBSD* ) cd ..
echo -n "Installing "
-foreach i (ip_fil.[ch] ip_nat.[ch] ip_frag.[ch] ip_state.[ch] fil.c \
- ip_proxy.[ch] ip_*_pxy.c mlf_ipl.c ipl.h ip_compat.h \
- ip_auth.[ch] ip_log.c)
+foreach i (ip_{auth,fil,frag,nat,pool,proxy,scan,state,sync}.[ch] fil.c \
+ ip_*_pxy.c mlf_ipl.c ipl.h ip_compat.h ip_log.c)
echo -n "$i ";
cp $i /sys/netinet
chmod 644 /sys/netinet/$i
- switch ( $i )
+ switch ($i)
case *.h:
/bin/cp $i /usr/include/netinet/$i
chmod 644 /usr/include/netinet/$i
- breaksw
- endsw
+ breaksw
+ endsw
end
echo ""
echo "Copying /usr/include/osreldate.h to /sys/sys"
diff --git a/contrib/ipfilter/FreeBSD-3/INST.FreeBSD-3 b/contrib/ipfilter/FreeBSD-3/INST.FreeBSD-3
index 6c68dbb..5c30b57 100644
--- a/contrib/ipfilter/FreeBSD-3/INST.FreeBSD-3
+++ b/contrib/ipfilter/FreeBSD-3/INST.FreeBSD-3
@@ -16,6 +16,8 @@ To build a kernel with the IP filter, follow these seven steps:
mknod /dev/ipnat c 79 1
mknod /dev/ipstate c 79 2
mknod /dev/ipauth c 79 3
+ mknod /dev/ipsync c 79 4
+ mknod /dev/ipscan c 79 5
7. reboot
diff --git a/contrib/ipfilter/FreeBSD-3/kinstall b/contrib/ipfilter/FreeBSD-3/kinstall
index 8282de7..20f0369 100755
--- a/contrib/ipfilter/FreeBSD-3/kinstall
+++ b/contrib/ipfilter/FreeBSD-3/kinstall
@@ -9,17 +9,17 @@ set confdir="$archdir/conf"
if ( $dir =~ */FreeBSD* ) cd ..
echo -n "Installing "
foreach i (ip_fil.[ch] ip_nat.[ch] ip_frag.[ch] ip_state.[ch] fil.c \
- ip_proxy.[ch] ip_*_pxy.c mlf_ipl.c ipl.h \
+ ip_proxy.[ch] ip_{ftp,rcmd,raudio}_pxy.c mlf_ipl.c ipl.h \
ip_compat.h ip_auth.[ch] ip_log.c)
echo -n "$i ";
cp $i /sys/netinet
chmod 644 /sys/netinet/$i
- switch ( $i )
+ switch ($i)
case *.h:
/bin/cp $i /usr/include/netinet/$i
chmod 644 /usr/include/netinet/$i
- breaksw
- endsw
+ breaksw
+ endsw
end
echo ""
echo "Linking /usr/include/osreldate.h to /sys/sys/osreldate.h"
diff --git a/contrib/ipfilter/FreeBSD-4.0/ipv6-patch-4.0 b/contrib/ipfilter/FreeBSD-4.0/ipv6-patch-4.0
index c232b2c..8a827cf 100755
--- a/contrib/ipfilter/FreeBSD-4.0/ipv6-patch-4.0
+++ b/contrib/ipfilter/FreeBSD-4.0/ipv6-patch-4.0
@@ -1,3 +1,5 @@
+.\" $NetBSD$
+.\"
*** ip6_input.c.orig Sun Feb 13 14:32:01 2000
--- ip6_input.c Wed Apr 26 22:31:34 2000
***************
diff --git a/contrib/ipfilter/FreeBSD-4.0/ipv6-patch-4.1 b/contrib/ipfilter/FreeBSD-4.0/ipv6-patch-4.1
index 90dac19..a6a4612 100644
--- a/contrib/ipfilter/FreeBSD-4.0/ipv6-patch-4.1
+++ b/contrib/ipfilter/FreeBSD-4.0/ipv6-patch-4.1
@@ -1,3 +1,5 @@
+.\" $NetBSD$
+.\"
*** ip6_input.c.orig Sat Jul 15 07:14:34 2000
--- ip6_input.c Thu Oct 19 17:14:37 2000
***************
diff --git a/contrib/ipfilter/FreeBSD-4.0/ipv6-patch-4.2 b/contrib/ipfilter/FreeBSD-4.0/ipv6-patch-4.2
new file mode 100644
index 0000000..a6a4612
--- /dev/null
+++ b/contrib/ipfilter/FreeBSD-4.0/ipv6-patch-4.2
@@ -0,0 +1,65 @@
+.\" $NetBSD$
+.\"
+*** ip6_input.c.orig Sat Jul 15 07:14:34 2000
+--- ip6_input.c Thu Oct 19 17:14:37 2000
+***************
+*** 120,125 ****
+--- 120,127 ----
+
+ extern struct domain inet6domain;
+ extern struct ip6protosw inet6sw[];
++ extern int (*fr_checkp) __P((struct ip *, int, struct ifnet *, int,
++ struct mbuf **));
+
+ u_char ip6_protox[IPPROTO_MAX];
+ static int ip6qmaxlen = IFQ_MAXLEN;
+***************
+*** 289,294 ****
+--- 291,305 ----
+ ip6stat.ip6s_badvers++;
+ in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_hdrerr);
+ goto bad;
++ }
++
++ if (fr_checkp) {
++ struct mbuf *m1 = m;
++
++ if ((*fr_checkp)(ip6, sizeof(*ip6), m->m_pkthdr.rcvif,
++ 0, &m1) || !m1)
++ return;
++ ip6 = mtod(m = m1, struct ip6_hdr *);
+ }
+
+ ip6stat.ip6s_nxthist[ip6->ip6_nxt]++;
+
+*** ip6_output.c.orig Sat Jul 15 07:14:35 2000
+--- ip6_output.c Thu Oct 19 17:13:53 2000
+***************
+*** 106,111 ****
+--- 106,113 ----
+ #include <netinet6/ip6_fw.h>
+ #endif
+
++ extern int (*fr_checkp) __P((struct ip *, int, struct ifnet *, int, struct mbuf **));
++
+ static MALLOC_DEFINE(M_IPMOPTS, "ip6_moptions", "internet multicast options");
+
+ struct ip6_exthdrs {
+***************
+*** 787,792 ****
+--- 789,803 ----
+ ip6->ip6_src.s6_addr16[1] = 0;
+ if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_dst))
+ ip6->ip6_dst.s6_addr16[1] = 0;
++ }
++
++ if (fr_checkp) {
++ struct mbuf *m1 = m;
++
++ if ((error = (*fr_checkp)(ip6, sizeof(*ip6), ifp, 1, &m1)) ||
++ !m1)
++ goto done;
++ ip6 = mtod(m = m1, struct ip6_hdr *);
+ }
+
+ #ifdef IPV6FIREWALL
diff --git a/contrib/ipfilter/FreeBSD-4.0/kinstall b/contrib/ipfilter/FreeBSD-4.0/kinstall
index 99ec679..ebd6e2e 100755
--- a/contrib/ipfilter/FreeBSD-4.0/kinstall
+++ b/contrib/ipfilter/FreeBSD-4.0/kinstall
@@ -11,31 +11,25 @@ set confdir="$archdir/conf"
if ( $dir =~ */FreeBSD* ) cd ..
echo -n "Installing "
-foreach i (ip_fil.[ch] ip_nat.[ch] ip_frag.[ch] ip_state.[ch] fil.c \
- ip_proxy.[ch] ip_*_pxy.c mlf_ipl.c mlfk_ipl.c \
- ipl.h ip_compat.h ip_auth.[ch] ip_log.c)
+foreach i (ip_{auth,fil,nat,pool,proxy,scan,state,sync}.[ch] fil.c \
+ ip_*_pxy.c mlfk_ipl.c ipl.h ip_compat.h ip_log.c )
echo -n "$i ";
- cp $i $ipfdir
- chmod 644 $ipfdir/$i
- switch ( $i )
+ cp $i /sys/netinet
+ chmod 644 /sys/netinet/$i
+ switch ($i)
case *.h:
/bin/cp $i /usr/include/netinet/$i
chmod 644 /usr/include/netinet/$i
- breaksw
- endsw
+ breaksw
+ endsw
end
echo ""
echo "Linking /usr/include/osreldate.h to /sys/sys/osreldate.h"
ln -s /usr/include/osreldate.h /sys/sys/osreldate.h
-set patchfile=FreeBSD-4.0/ipv6-patch-$krev
-if ( -f $patchfile ) then
- echo ""
- echo "Patching ip6_input.c and ip6_output.c"
- cat $patchfile | (cd /sys/netinet6; patch)
-else
- echo "IPv6 patching not required for your OS version"
-endif
+echo ""
+echo "Patching ip6_input.c and ip6_output.c"
+cat FreeBSD-4.0/ipv6-patch-$krev | (cd /sys/netinet6; patch -N)
set config=`(cd $confdir; /bin/ls -1t [0-9A-Z_]*) | head -1`
echo -n "Kernel configuration to update [$config] "
diff --git a/contrib/ipfilter/FreeBSD-4.0/unkinstall b/contrib/ipfilter/FreeBSD-4.0/unkinstall
index b9c5f029..4e9caaa 100755
--- a/contrib/ipfilter/FreeBSD-4.0/unkinstall
+++ b/contrib/ipfilter/FreeBSD-4.0/unkinstall
@@ -12,7 +12,7 @@ if ( $dir =~ */FreeBSD* ) cd ..
echo -n "Uninstalling "
foreach i (ip_fil.[ch] ip_nat.[ch] ip_frag.[ch] ip_state.[ch] fil.c \
ip_auth.[ch] ip_proxy.[ch] ip_{ftp,rcmd,raudio}_pxy.c ip_compat.h \
- ip_log.c mlf_ipl.c mlfk_ipl.c ipl.h)
+ ip_log.c mlf_ipl.c ipl.h)
echo -n "$i ";
/bin/rm -f /sys/netinet/$i
end
diff --git a/contrib/ipfilter/FreeBSD/files.diffs b/contrib/ipfilter/FreeBSD/files.diffs
index 84893d4..2f028e3 100644
--- a/contrib/ipfilter/FreeBSD/files.diffs
+++ b/contrib/ipfilter/FreeBSD/files.diffs
@@ -2,7 +2,7 @@
--- files Sun Jan 14 14:32:25 1996
***************
*** 208,213 ****
---- 208,221 ----
+--- 208,225 ----
netinet/tcp_timer.c optional inet
netinet/tcp_usrreq.c optional inet
netinet/udp_usrreq.c optional inet
@@ -14,6 +14,10 @@
+ netinet/ip_auth.c optional ipfilter inet
+ netinet/ip_proxy.c optional ipfilter inet
+ netinet/ip_log.c optional ipfilter inet
++ netinet/ip_scan.c optional ipfilter inet
++ netinet/ip_sync.c optional ipfilter inet
++ netinet/ip_pool.c optional ipfilter_pool ipfilter inet
++ netinet/ip_rules.c optional ipfilter_compiled ipfilter inet
netiso/clnp_debug.c optional iso
netiso/clnp_er.c optional iso
netiso/clnp_frag.c optional iso
diff --git a/contrib/ipfilter/FreeBSD/files.newconf.diffs b/contrib/ipfilter/FreeBSD/files.newconf.diffs
index cc7cf41..29aea54 100644
--- a/contrib/ipfilter/FreeBSD/files.newconf.diffs
+++ b/contrib/ipfilter/FreeBSD/files.newconf.diffs
@@ -2,7 +2,7 @@
--- files.newconf Sun Jun 25 02:19:10 1995
***************
*** 161,166 ****
---- 161,174 ----
+--- 161,178 ----
file netinet/ip_input.c inet
file netinet/ip_mroute.c inet
file netinet/ip_output.c inet
@@ -14,6 +14,10 @@
+ file netinet/ip_proxy.c ipfilter
+ file netinet/ip_auth.c ipfilter
+ file netinet/ip_log.c ipfilter
++ file netinet/ip_scan.c ipfilter
++ file netinet/ip_sync.c ipfilter
++ file netinet/ip_pool.c ipfilter_pool
++ file netinet/ip_rules.c ipfilter_compiled
file netinet/raw_ip.c inet
file netinet/tcp_debug.c inet
file netinet/tcp_input.c inet
diff --git a/contrib/ipfilter/FreeBSD/files.oldconf.diffs b/contrib/ipfilter/FreeBSD/files.oldconf.diffs
index 55b526f..ed8aff9 100644
--- a/contrib/ipfilter/FreeBSD/files.oldconf.diffs
+++ b/contrib/ipfilter/FreeBSD/files.oldconf.diffs
@@ -2,7 +2,7 @@
--- files.oldconf Sun Apr 23 17:54:18 1995
***************
*** 180,185 ****
---- 180,193 ----
+--- 180,197 ----
netinet/tcp_timer.c optional inet
netinet/tcp_usrreq.c optional inet
netinet/udp_usrreq.c optional inet
@@ -14,6 +14,10 @@
+ netinet/ip_proxy.c optional ipfilter requires inet
+ netinet/ip_auth.c optional ipfilter requires inet
+ netinet/ip_log.c optional ipfilter requires inet
++ netinet/ip_scan.c optional ipfilter requires inet
++ netinet/ip_sync.c optional ipfilter requires inet
++ netinet/ip_pool.c optional ipfilter_pool requires ipfilter
++ netinet/ip_rules.c optional ipfilter_compiled requires ipfilter
netiso/clnp_debug.c optional iso
netiso/clnp_er.c optional iso
netiso/clnp_frag.c optional iso
diff --git a/contrib/ipfilter/FreeBSD/filez.diffs b/contrib/ipfilter/FreeBSD/filez.diffs
index 52492e8..9656006 100644
--- a/contrib/ipfilter/FreeBSD/filez.diffs
+++ b/contrib/ipfilter/FreeBSD/filez.diffs
@@ -9,11 +9,15 @@
+ file netinet/ip_fil.c ipfilter
+ file netinet/fil.c ipfilter
+ file netinet/ip_nat.c ipfilter
-+ file netinet/ip_frag.c ipfilter
-+ file netinet/ip_state.c ipfilter
-+ file netinet/ip_proxy.c ipfilter
-+ file netinet/ip_auth.c ipfilter
++ file netinet/ip_frag.c ipfilter
++ file netinet/ip_state.c ipfilter
++ file netinet/ip_proxy.c ipfilter
++ file netinet/ip_auth.c ipfilter
+ file netinet/ip_log.c ipfilter
++ file netinet/ip_scan.c ipfilter
++ file netinet/ip_sync.c ipfilter
++ file netinet/ip_pool.c ipfilter_pool
++ file netinet/ip_rules.c ipfilter_compiled
file netiso/clnp_debug.c iso
file netiso/clnp_er.c iso
file netiso/clnp_frag.c iso
diff --git a/contrib/ipfilter/FreeBSD/kinstall b/contrib/ipfilter/FreeBSD/kinstall
index ef2db54..2b67b9a 100755
--- a/contrib/ipfilter/FreeBSD/kinstall
+++ b/contrib/ipfilter/FreeBSD/kinstall
@@ -8,17 +8,17 @@ set confdir="$archdir/conf"
if ( $dir =~ */FreeBSD ) cd ..
echo -n "Installing "
-foreach i (ip_fil.[ch] ip_nat.[ch] ip_frag.[ch] ip_state.[ch] fil.c \
- ip_proxy.[ch] ip_auth.[ch] ip_*_pxy.c ip_compat.h ip_log.c)
+foreach i (ip_{auth,fil,frag,nat,pool,proxy,scan,state,sync}.[ch] fil.c \
+ ip_*_pxy.c ip_compat.h ip_log.c )
echo -n "$i ";
cp $i /sys/netinet
chmod 644 /sys/netinet/$i
- switch ( $i )
+ switch ($i)
case *.h:
/bin/cp $i /usr/include/netinet/$i
chmod 644 /usr/include/netinet/$i
- breaksw
- endsw
+ breaksw
+ endsw
end
echo ""
grep iplopen $archdir/$karch/conf.c >& /dev/null
diff --git a/contrib/ipfilter/HISTORY b/contrib/ipfilter/HISTORY
index 85a8b5f..9b93e83 100644
--- a/contrib/ipfilter/HISTORY
+++ b/contrib/ipfilter/HISTORY
@@ -6,757 +6,394 @@
# in providing a very available location for the IP Filter home page and
# distribution center.
#
-# Thanks to Hewlett Packard for making it possible to port IP Filter to
-# HP-UX 11.00.
-#
-# Thanks to Tel.Net Media for supplying me with equipment to ensure that
-# IP Filter continues to work on Solaris/sparc64.
-#
-# Thanks to BSDI for providing object files for BSD/OS 3.1 and the means
-# to further support development of IP Filter under BSDI.
-#
-# 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.
-#
# Thanks also to all those who have contributed patches and other code,
# and especially those who have found the time to port IP Filter to new
# platforms.
#
-3.4.35 21/6/2004 - Released
-
-some cases of ICMP checksum alteration were wrong
-
-block packets that fail to create state table entries
-
-correctly handle all return values from ip_natout() when fastrouting
-
-ipmon was not correctly calculating the length of the IPv6 packet (excluded
-ipv6 header length)
-
-3.4.34 20/4/2004 - Released
-
-correct the ICMP packet checksum fixing up when processing ICMP errors for NAT
-
-various changes to ipsend for sending packets with ipv4 options
-
-look for ipmon's pidfile in /var/run and /etc/opt/ipf in Solaris' init script
-
-only allow non-fragmented packets to influence whether or not a logged
-packet is the same as the one logged before.
-
-make "ipfstat -f" output more informative
-
-compatibility for openbsd byte order changes to ip_off/ip_len
-
-disallow "freebsd" as a make target (encourages people to do the wrong thing)
-
-3.4.33 15/12/2003 - Released
-
-pass on messages moving through ipfilter when it is unloading itself on Solaris
-
-add disabling of auto-detach when the module attaches on Solaris
-
-compatibility patches for 'struct ifnet' changes on FreeBSD
-
-implement a maximum for the number of entries in the NAT table (NAT_TABLE_MAX
-and ipf_nattable_max)
-
-fix ipfstat -A
-
-frsynclist() wasn't paying attention to all the places where interface
-names are, like it should.
-
-fix where packet header pointers are pointing to after doing an ipf_pullup
-
-fix comparing ICMP packets with established TCP state where only 8 bytes
-of header are returned in the ICMP error.
-
-3.4.32 18/6/2003 - Released
-
-fix up the behaviour of ipfs
-
-make parsing errors in ipf/ipnat return an error rather than return
-indicating success.
-
-window scaling patch
-
-make ipfstat work as a set{g,u}id thing - gave up privs before opening
-/dev/ipl
-
-checksum adjustment corrections for ICMP & NAT
-
-attempt to always get an mbuf full of data through pullup if possible
-
-Fix bug with NAT and fragments causing system to crash
-
-Add patches for OpenBSD 3.3
-
-stop LKM locking up the machine on modern NetBSD(?)
-
-allow timeouts in NAT rules to over-ride fr_defnatage if LARGE_NAT is defined
-
-Locking patches for IRIX 6.5 from SGI.
-
-fix bug in synchronising state sessions where all interfaces were invalidated
-
-fix bug in openbsd 3.2 bridge diffs
-
-fix bug parsing port comparisons in proxy rules
-
-3.4.31 7/12/2002 - Released
-
-Solaris 10 compatibility
-
-fix linking into pfil in NetBSD
-
-fix IRIX 6.2 compatibility
-
-add code to check consistency of fr_checkp/fr_check on non-Solaris
-
-OpenBSD: missing patches for ip6_output.c on OpenBSD 3.2,
- make LKM work for 3.2 (OpenBSD LKMs now match NetBSD)
-
-3.4.30 26/11/2002 - Released
-
-attempt to detect using GNU make and abort if so
-
-OpenBSD 3.2 patches from Stefan Hermes von GMX
-
-add MSS clamping code from NetBSD
-
-correctly display ipv6 output with ipfstat for (accounting) rules
-
-fix problems with ioctl handling for /dev/ipauth
-
-set SYN bit in rcmd fake packet to create back channel
-
-make libpcap reader capable of determining in/out (not in libpcap file)
-and add more DLT types
-
-do not allow redirects to localhost for Solaris in NAT parser
-
-allow return-rst with auth rules
-
-man page corrections
-
-fix for handling ipv6 icmp errors
-
-fix up ipfs command line option processing
-
-only allow processing a ftp 227 response following a PASV command
-
-NetBSD: use poll() and adapt to new cdevsw mechanism
-
-make flushing for just ipv6 things work
-
-3.4.29 28/8/2002 - Released
-
-Make substantial changes to the FTP proxy to improve reliability, security
-and functionality.
-
-don't send ICMP errors/TCP RST's in response to blocked proxy packets
-
-fix potential memory leaks when unloading ipfilter from kernel
-
-fix bug in SIOCGNATL handler that did not preserve the expected
-byte order from earlier versions in the port number
-
-set do not fragment flag in generated packets according to system flags,
-where available.
-
-preserve filter rule number and group number in state structure
-
-fix bug in ipmon printing of p/P/b/B
-
-make some changes to the kmem.c code for IRIX compatibility
-
-add code to specifically handle ip.tun* interfaces on Solaris
-
-3.4.28 6/6/2002 - Released
-
-Fix for H.323 proxy to work on little endian boxes
-
-IRIX: Update installation documentation
- add route lock patch
-
-allow use of groups > 65535
-
-create a new packet info summary for packets going through ipfr_fastroute()
-so that where details are different (RST/ICMP errors), the packet now gets
-correctly NAT'd, etc.
-
-fix the FTP proxy so that checks for TCP sequence numbers outside the
-normal offset due to data changes use absolute numbers
-
-make it possible to remove rules in ipftest
-
-Update installing onto OpenBSD and split into two directories:
-OpenBSD-2 and OpenBSD-3
-
-fix error in printout out the protocol in NAT rules
-
-always unlock ipfilter if locking fails half way through in ipfs
-
-fix problems with TCP window scaling
-
-update of man pages for ipnat(4) and ipftest(1)
-
-3.4.27 28/04/2002 - Released
-
-fix calculation of 2's complmenent 16 bit checksum for user space
-
-add mbuflen() to usespace compiles.
-
-add more #ifdef complexity for platform portability
-
-add OpenBSD 3.1 diffs
-
-3.4.26 25/04/2002 - Released
-
-fix parsing and printing of NAT rules with regression tests.
-
-add code to adjust TCP checksums inside ICMP errors where present and as
-required for NAT.
-
-fix documentation problems in instal documents
-
-fix locking problem with auth code on Solaris
-
-fix use of version macros for FreeBSD and make the use of __FreeBSD_version
-override previous hacks except when not present
-
-fix the macros defined for SIOCAUTHR and SIOCAUTHW
-
-fix the H.323 proxy so it no longer panics (multiple issues: re-entry into
-nat_ioctl with lock held on Solaris, trying to copy data from kernel space
-with copyin, unaligned access to get 32bit & 16bit numbers)
-
-use the ip_ttl ndd parameter on Solaris to fill in ip_ttl for packets
-generated by IPFilter
-
-fix comparing state information to delete state table entries
-
-flag packets as being "bad state" if they're outside the window and prevent
-them from being able to cause new state to be created - except for SYN packets
-
-be stricter about what packets match a TCP state table entry if its creation
-was triggered by a SYN packet.
-
-add patches to handle TCP window scaling
-
-don't update TCP state table entries if the packet is not considered to be
-part of the connection
-
-ipfs wasn't allowing -i command line option in getopt
-
-IRIX: fix kvm interface, fix compile warnings, compile the kernel with -O2
- regardless of user compile, fix the getkflags script to prune down the
- output more so it is acceptable
-
-change building in Makefiles to create links to the application in $(TOP)
-at the end of "build" rather than when each is created.
-
-update BSD/kupgrade for FreeBSD
-
-l4check wasn't properly closing things when a connection fails
-
-man page updates for ipmon(8) and ipnat(5)
-
-more regression tests added.
-
-3.4.25 13/03/2002 - Released
-
-retain rule # in state information
-
-log the direction of a packet so ipmon gets it right rather than incorrectly
-deriving it from the rule flags
-
-add #ifdef for IPFILTER_LOGSIZE (put options IPFILTER_LOGSIZE=16384 in BSD
-kernel config files to increase that buffer size)
-
-recognise return-* rules differently to block in ipftest
-
-fix bug in ipmon output for solaris
-
-add regression testing for skip rules, logging and using head/group
-
-fix output of ipmon: was displaying large unsigned ints rather than -1
-when no rules matched.
-
-make logging code compile into ipftest and add -l command line option to
-dump binary log file (read with ipmon -f) when it finishes.
-
-protect rule # and group # from interference when checking accounting rules
-
-add regression testing for log output (text) from ipmon.
-
-document -b command line option for ipmon
-
-fix double-quick in Solaris startup script
-
-3.4.24 01/03/2002 - Released
-
-fix how files are installed on SunOS5
-
-fix some minor problems in SunOS5 ipfboot script
-
-by default, compile all OpenBSD tools in 3.0 for IPv6
-
-fix NULL-pointer dereference in NAT code
-
-make a better attempt at replacing the appropriate binaries on BSD systems
-
-always print IPv6 icmp-types as a number
-
-impose some rules about what "skip" can be used with
-
-fix parsing problems with "keep state" and "keep state-age"
-
-Try to read as much data as is in the log device in ipmon
-
-remove some redundant checks when searching for rdr/nat rules
-
-fix bug in handling of ACCT with FTP proxy
-
-increase array size for interface names, using LIFNAMSIZ
-
-include H.323 proxy from QNX
-
-3.4.23 16/01/2002 - Released
-
-Include patches to install IPFilter into OpenBSD 3.0, both for just kernel
-compiles and complete system builds.
-
-Fix bug in automatic flushing of state table which would cause it to hang
-in an infinite loop bug introduced in 3.4.20.
-
-Modify the sample proxy (samples/proxy.c) so that it ads a NAT mapping for
-the outgoing connection to make it look like it comes from the real source.
-
-Only support ICMPv6 with IPv6.
-
-Move ipnat.1 to ipnat.8
-
-Enhance ipmon to print textual ICMP[v6] types and subtypes where possible.
-
-Make it possible to do IPv6 regression testing with ipftest.
-
-Use kvm library for kmem access, rather than trying to do it manually with
-open/lseek/read.
-
-Fix diffs for ip_input.c on BSDOS so it doesn't crash with fastroute.
-
-Remove Berkeley advertising licence clause. Reference:
-ftp://ftp.cs.berkeley.edu/pub/4bsd/README.Impt.License.Change
-
-Add more regression tests: ICMPv6 neighbour discovery, ICMP time exceeded
-and fragmentation required.
-
-Fix ipfboot script on Solaris to deal with no nameservers or no route to
-them in a clean manner.
-
-Support per-rule set timeouts for non-TCP NAT and state
-
-Add netbios proxy
-
-Add ICMPv6 stateful checking, including handling multicast destination
-addresses for neighbour discovery.
-
-Fix problems with internals of ICMP messages for MTU discovery and
-unreachables not being correctly adjust on little endian boxes.
-
-Add "in-via" and "out-via" to filtering rules grammar. It is now possible
-to bind a rule to both incoming and outgoing interfaces, in both forward
-and reverse directions (4 directions in total). allows for asymetric flows
-through a firewall.
-
-Fix ipfstat and ipnat for working on crash dumps.
-
-Don't let USE_INET6 stay defined for SunOS4
-
-Count things we see for each interface on solaris.
-
-Include <netinet/icmp6.h> when compiling with USE_INET6 defined and
-also include a whole bunch of #define's to make sure the symbols expected
-can be used.
-
-Fix up fastroute on BSD systems.
-
-Make fastrouting work for IPv6 just a bit better. doesn't split up big
-packets into fragments like the IPv4 one does. You can now do a
-"to <if>:<ipv6_addr>"
-
-Remove some of the differences between user-space and kernel-space code
-that is internal to ipfilter.
-
-Call ipfr_slowtimer() after each packet is processed in ipftest to artificially
-create the illusion of passing time and include the expire functions in the
-code compiled for user-space.
-
-Fix issues with the IPSec proxy not working or leading to a system crash.
-
-Junk all processing of SPIs and special handling for ESP.
-
-Add "no-match" as a filter rule action (resets _LAST_ match)
-
-Add hack to workaround problems with Cassini interface cards on
-Solaris and VLANs
-
-Add some protocols to etc/protocols
-
-3.4.22 03/12/2001 - Released
-
-various openbsd changes
-
-sorting based on IP numbers for ipfstat top output
-
-fix various IPv6 code & compile problems
-
-modify ip_fil.c to be more netbsd friendly
-
-fix fastroute bug where it modified a packet post-sending
-
-fix get_unit() - don't understand why it was broken.
+4.1.8 - Released 29 March 2005
-add FI_IGNOREPKT and don't count so marked packets when doing stats or
-state/nat.
+include path from Phil Dibowitz for sorting ipfstat -t output by source or
+destination port.
-extend the interface name saved to log output
+fix a bug in printing rules where interface names could not be printed,
+even if they're in the rule structure.
-make proxies capable of extending the matching done on a packet with a
-particular nat session
+fix BSD/kupgrade to correctly change ipfilter lkm Makefile for FreeBSD
-change interfaces inside NAT & state code to accomodate redesign to allow
-IPsec proxy to work.
+add 2 new features to SIOCGNATL:
+- if IPN_FINDFORWARD is set, check if the respective MAP is already
+ present in the outbound table
+- if IPN_IN is set, search for a matching MAP entry instead of RDR
+ (Peter Potsma)
-fix bug when free'ing loaded rules that results in a memory leak
-(only an issue with "ipf -rf -", not flush)
+turn off function inlining for freebsd 5.3+
-make ipftest capable of loading > 1 file or rules, making it now possible
-to load both NAT & filter rules
+UDP doesn't pullup enough data which can sometimes cause a panic.
+Fix other protocols, as required, where a similar problem may exist.
-fix hex input for ipftest to allow interface name & direction to work
+overhaul the timeout queue management, especially that for user defined queues
+which are now only freed in an orderly manner.
-show ipsec proxy details in ipnat output
+4.1.7 - Released 13 March 2005
-if OPT_HEX is set in opts, print a packet out as hex
+Using the GRE call field is almost impossible because it is unbalanced and
+both call fields are not present in each v1 header.
-don't modify b_next or preseve it or preserve b_prev for solaris
+Fix a problem where it was possible to load duplicate rules into ipf
-fix up kinstall scripts to install all the files everywhere they need to
+patch from John Wehle to address problems with fastroute on solaris
-fix overflowing of bits in ip_off inside iptest
+Copying data out for ipf -z failed because it tried to copy out to an address
+that is a kernel pointer in user space.
-make userauth and proxy in samples directory compile
+add "ip" timeout for both NAT & state that's for non-TCP/UDP/ICMP
-fix minimum size when doing a pullup for ESP & ICMPv6
+synch up with NetBSD's changes
-3.4.21 24/10/2001 - Released
+fix problems parsing long lines of text in the ftp proxy where they would not
+be parsed properly and stop the session from working
-include ipsec proxy
+enhance the PPTP proxy so that it tries to decode messages in the TCP stream
+so it knows when to create and destroy the state/nat sessions for GRE. There
+are also 4 new regression tests for it, testing map/rdr rules.
-make state work for non-tcp/udp/icmp in a very simple way
+impose some limits on the size of data that can be moved with SIOCSTPUT in
+the NAT code and also prevent a duplicate session entry from being created
+using this method.
-include diffs for ipv6 firewall on openbsd-2.9
+add a new flag (IPN_FINDFORWARD) to NAT code that can be used with SIOCGNATL
+to check if it is possible to create an outgoing transparent NAT mapping to
+compliment the redirect being investigated.
-add compatibility filter wrapper for NetBSD-current
+Linux requires that the checksums in the IP header get adjusted
-fix command line option problems with ipfs
+only resolve unknown interfaces in fr_stinsert, and nuke all interface pointers
+in SIOCSTPUT to prevent bad data being loaded from userspace.
-if we fill the state table and a automated flush doesn't purge any
-expiring entries, remove all entries idle for more than half a day
+make the byte counting for state correct (was counting data from ICMP packet
+twice)
-fix bug with sending resets/icmp errors where the pointer to the data
-section of the packet was not being set (BSD only)
+print out the keyword "frag-body" if the flag is set.
-split out validating ftp commands and responses into different halves,
-one for each of server & client.
+fix ipfs loading/restoring NAT sessions
-do not compile in STATETOP support for specific architectures
+patch from Frank to correctly format IP addresses in ipfstat -t output
-fix INSTALL.FreeBSD to no longer provide directions and properly direct
-people to the right file for the right version of FreeBSD.
+parsing port numbers in ipf/ipnat was confusing as the port number was returned
+in an int that was also overloaded to be the suceess/failure. instead, change
+the port using pass by reference and only use the return value for indicating
+success or failure.
-3.4.20 24/07/2001 - Released
+4.1.6 - Released 19 February 2005
-adjust NAT hashing to give a better spread across the table
+add a new timeout number to NAT (fr_defnatipage) that is used for all
+non-TCP/UDP/ICMP protocols - default 60 seconds.
-show icmp code/type names in output, where known
+buffer leak with bad nat - David Gueluy
-fix bug in altering cached interface names in state when resync'ing
+fix memory leak with state entries created by proxies
-fix bug in real audio proxy that caused crashs
-
-fix compiling using sunos4 cc
+eliminate copying too much data into a scan buffer
-patch from casper to address weird exit problem for ipstat in top mode
+allow a trailing protocol name for map rules as well as rdr ones
-patch from Greg Woods to produce names for icmp types/unreach codes,
-where they are known
+fix bug in parsing of <= and > for NAT rules (two were crossed over)
-fix bug where ipfr_fastroute() would use a mblk and it would also get
-freed later.
+FreeBSD's iplwrite hasn't kept pace with iplread's prototype
-don't match fragments which would cause 64k length to be exceeded
+expand documention on the karma of using "auto" in ipnat map rules
-ftp proxy fix for port numbers being setup for pasv ftp with state/nat
+add matching on IP protocol to ipnat map rules
-change hashing for NAT to include both IP#'s and ports.
+allow ippool definitions to contain no addresses to start with
-Solaris fixes for IPv6
+Linux NAT needs to modify the IP header checksum as it gets called after it
+has been computed by IP.
-fix compiling iplang bits, under Solaris, for ipsend
+UDP was missing a pullup for packet header information before examining
+the header
-3.4.19 29/06/2001 - Released
+4.1.5 - Released 9 January 2005
-fix to support suspend/resume on solaris8 as well as ipv6
+all rules were being converted into "dup-to" rules in the kernel
-include group/group-head in match of filter rules
+fix two ftp proxy problems: 1st, buffer needs to be bigger for fitting in
+complete RETR/CWD commands, 2nd is () use in 227 messages isn't copied
+over correctly.
-fix endian problem reading snoop files
+response to CWDs
+revert ip_off back to network byte order in the ICMP error packet that
+gets generated.
-make all licence comments point to the one place
+4.1.4 - Released 9 January 2005
-fix ftp proxy to only advance state if a reply is received in response to
-a recognised command
+force NAT rules to only match ipv4 NAT rules (which all are, currently,
+by default)
-3.4.18 05/06/2001 - Released
+include state synchronisation fixes from Frank Volf
-fix up parsing of "from ! host" where '!' is separate
+make the maximum log size for internally buffered log entries accessible
+via "ipf -T"
-disable hardware checksums for NetBSD
+redesign start of fr_check() to avoid putting duplicate information in
+ipfilter about how much data needs to be pulled up for a protocol to be
+properly filtered.
-put ipftest temporary files in . rather than /tmp
+tidy up sending ICMP error messages - some bad inputs could result in
+data not being freed and/or no error returned.
-modify ftp proxy to be more intelligent about moving between states
-and recognise new authentication commands
+make the maximum size of the log buffer run-time tunable
-allow state/nat table sizes to be externally influenced
+fix bug in parsing TCP header when looking for MSS option that could make
+the system hang
-print out host mapping table for NAT with ipnat -l
+change pool lookups that fail to find a match to return "no match"
+rather than fail.
-fix handling of hardware checksum'ing on Solaris
+add run-time tunable debugging for proxy support code and FTP proxy.
-fixup makefiles for Solaris
+fix state table updates for entries where the first packet as an ICMPv6
+multicast message
-update regression tests
+fix hang when flushing state for v4/v6 and other (v6/v4) entries are present
+too
-fix surrender of SPL's for failure cases
+attaching filtering to ipv6 pfil hook wasn't present for solaris
-include patches for OpenBSD's new timeout mechanism
+don't allow rules with "keep state" and "with oow"
-default ipl_unreach to ICMP_UNREACH_FILTER_PROHIB if defined, else make it
-ICMP_UNREACH_FILTER
+move a bunch of userland only code from fil.c to ip_fil.c
-fix up handling of packets matching auth rules and interaction with state
+make fr_coalesce() more resiliant to bad input, just returning an error
+instead of crashing, making calling it easier in many places
-add -q command line option to ipfstat on Solaris to list bound interfaces
+When m_pulldown doesn't return NULL, it doesn't necessarily return a pointer
+to the same mbuf passed in as the first arg.
-add command line option to ipfstat/ipnat to select different core image
+remove fr_unreach and use ENETUNREACH by default.
-don't use ncurses on Solaris for STATETOP
+printing out of tag data in ipf rules doesn't match input syntax
-fix includes to get FreeBSD version
+ipftest(1) man page update
-do not byte swap ip_id
+ipfs command line option parsing still rejects some valid syntaxes
-fix handling success for packets matching the auth rule
+SIGHUP handling by ipmon was not as safe as it could be
-don't double-count short packets
+fix various parsing regressions, including "<thishost>", "tcpudp", ordering
+of "keep" options
-add ICMP router discovery message size recognition
+patches from Frank Volk: add udp_acktimeout to sysctl list for FreeBSD,
+ICMP packet length not calculated correctly in send_icmp_err, reply-to
+not printed by ipfstat, keep state with icmp passing (mtrr)
-fix packet length calculation for IPv6
+patches for return-rst and return-icmp from Attila Fueloep
+(lichtscheu@gesindel.org)
-set CPUDIR when for install-sunos5 make target
+4.1.3 - Released 18 July 2004
-SUNWspro -xF causes Solaris 2.5.1 kernel to crash
+do some more fine tuning on NAT checksum adjustments
-3.4.17 06/04/2001 - Released
+correct IP address byte order in proxy setup for ipsec/pptp
-fix fragment#0 handling bug where they could get in via cache information
-created by state table entries
+man page updates
-use ire_walk to look for ire cache entries with link layer headers cached
+fix numerous problems with ipfs operation
-deal with bad SPL assumptions for log reading on BSD
+complete new syntax for ipmon.conf in its parser and update the sample file
-fix ftp proxy to allow logins with passwords
+assign error value consistantly in fastroute code
-some auth rule patches, fixing byte endian problems and returning as an error
+rewrite allocation of mbufs in send_reset/send_icmp_err to better use
+mbuf clusters and size calculations
-support LOG_SECURITY, where available, in ipmon
+resolve problem with linux panic'ing because the wrong flag was being
+passed to skb_clone/skb_alloc
-don't return an error for packets which match auth rules
+enable use of shared/exclusive locks on freebsd5 and above
-introduce fr_icmpacktimeout to timeout entries once an ICMP reply has
-been seen separately to when created
+do not rely on m_pkthdr.len to be valid all the time for mbufs on modern BSD
+and so use mbufchainlen to get the mbuf length instead
-3.4.16 15/01/2001 - Released
+replace lots of COPYIN/COPYOUT with BCOPYIN/BCOPYOUT where the data is
+going to be on the stack and not in userland
-fix race condition in flushing of state entries that are timing out
+packet buffer pointers were not refreshed & used properly in fr_check()
-Add TCP ECN patches
+include extra bits for OpenBSD 3.4 & 3.5.
-log all NAT entries created, not just those via rules
+fix ipf/ipnat parsing regression problems with v3.4
-3.4.15 17/12/2000 - Released
+4.1.2 - RELEASED - 27 May 2004
-add minimum ttl filtering (to be replaced later by return-icmp-as-dest
-for all ICMP packets matching state entries).
+add state top for ipv6
-fix NAT'ing of fragments
+fix numerous parsing regressions
-fix sanity checks for ICMPV6
+change sample proxies to use SIOCGNATL with the new API
-fix up compiling on IRIX 6.2 with IDF/IDL installed
+allow macro names to contain underscores (_)
-3.4.14 02/11/2000 - Released
+split the parser into a collection of dictionaries so that keywords do
+not interfere with resolving hostnames and portnames
-cause flushing NAT table to generate log records the same as state flush
-does.
+fix ipfrule LKM loading on freebsd
-fix ftp proxy port/pasv
+support mapping a fixed range of ports to a single port
-fix problem where nat_{in,out}lookup() would release a write lock when it
-didn't need to.
+fix timeout queue use by proxies with private queues
-add check for ipf6.conf in Solaris ipfboot
+handle space-led ftp server replies properly
-3.4.13 28/10/2000 - Released
+fix timeout queue management
-fix introduced bug with ICMP packets being rejected when valid
+fix fastroute, generation of RST & ICMP packets and operation with to/fastroute
-fix bug with proxy's that don't set fin_dlen correctly when calling
-fr_addstate()
+resolve further linux compatibility problems
-3.4.12 26/10/2000 - Released
+replace the use of COPYIN with BCOPYIN for platforms that provide ioctl
+args on the stack
-fix installing into FreeBSD-4.1
+allow flushing of ipv6 rules independant of ipv4 rules
-fix FTP proxy bug where it'd hang and make NAT slightly more efficient
+correct internal ipv6 checksum calculations
-fix general compiling errors/warnings on various platforms
+if a 'keep state' rule fails to create state, block the packet rather
+than let it through
-don't access ICMP data fields that aren't there
+correct all checksums in regression tests and correct NAT code to adjust
+checksums correctly.
-3.4.11 09/10/2000 - Released
+fix ipfs -R/-W
-return NULL for IPv6 access control lists if it is disabled rather than
-random garbage.
+4.1.1 - RELEASED - 24 March 2004
-fix for getting protocol & packet length for IPv6 packets for pullup.
+allow new connections with the same port numbers as an existing one
+in the state table if the creating packet is a SYN
-update plog script from version 0.8 to version 0.10
+timeout values have drifted, incorrectly, from what they were in 3.4
-patch from Frank Volf adding fix_datacksum() to NAT code, enhancing the
-capabilities for "fixing" checksums.
+FreeBSD - compatibility changes for 5.2
-3.4.10 03/09/2000 - Released
+don't match on sequence number (as well) for ICMO ECHO/REPLY, just the
+ICMP Id. field as otherwise thre is a state/NAT entry per packet pair
+rather than per "flow"
-merge patch from Frank Volf for ICMP nat handling of TCP/UDP data `errors'
+fr_cksum() returned the wrong answer for ICMP
-getline() adjusts linenum now
+Linux:
+- get return-rst and return-icmp working
+- treat the interface name the same as if_xname on BSD
-add tcphalfclosed timeout
+adjust expectations for TCP urgent bits based on observed traffic in the
+wild
-fill in icmp_nextmtu field if it is defined on the platform
+openbsd3.4 has ip_len/ip_off in network byte order when ipfilter is called
-RST generation fix from guido
+fix flushing of hash pool gorups (ippool -F) as well as displaying them
+(ippool -l)
-force 32bit compile for gcc on solaris if it can't generate 64bit code
+passing of pointers to interface structures wrong for HP-UX/Solaris with
+return-* rules.
-encase logging when fr_chksrc == 2 in #ifdef IPFILTER_LOG
+Make the solaris boot script able to run on 2.5.1
-fix up line wrap problems in plog script
+ippool related files missing from Solaris packages
-fix ICMP packet handling to not drop valid ICMP errors
+The name /dev/ippool should be /dev/iplookup
-freebsd 5.0 compat changes
+add regression testing for parsing long interface names in nat rules,
+along with mssclamp and tags. Also add test for mssclamp operation.
-3.4.9 08/08/2000 - Released
+ttl displayed for "ipfstat -t" is wrong because ttl is not computed.
-implement new aging mechanism in fr_tcp_age()
+parse logical interface names (Sun)
-fix icmp state checking bug
+unloading LKMs was only working if they were enabled.
-revamp buildsunos script and build both sparcv7/sparcv9 for Solaris
-if on an Ultra with a 64bit system & compiler (Caseper Dik)
+sync'ing up NAT sessions when NICs change should cause NAT rules to
+re-lookup name->pointer mappings
-open ipfilter device read only if we know we can
+not all of the ippool ioctl's are IOWR and they should be because they
+use the ipfobj_t for passing information in/out of the kernel. leave the
+old values defined and handle them, for compatibility.
-print out better information for ICMP packets in ipmon
+pool stats wrong: ippoolstate used where ipoolstat should be, hash table
+ statistics not reported at all
-move checking for source spoofed packets to a point where we can generate
-logs of them
+fr_running not set correctly for OpenBSD when compiled into the kernel
-return EFAULT from ircopyptr/iwcopyptr
+Allow SIOCGETFF while disabled
-don't do ioctl(SIOCGETFS) for auth stats
+Fix mssclamp with NAT (pasing and printing of the word, plus wrong bytes
+altered. How do you say "untested" ?)
-fix up freeing mbufs for post-4.3BSD
+4.1 - RELEASED - 12 February 2004
-fix returning of inc from ftp proxy
+4.0-BETA1 20 August 2003
-fix bugs with ipfs -R/-W (Caseper Dik)
+support 0/32 and 0/0 on the RHS in redirect rules
-3.4.8 19/07/2000 - Released
+where LHS and RHS netmasks are the same size for redirect, do 1:1 mapping
+for bimap rules.
-create fake opt_inet6.h for FreeBSD-4 compile as LKM
+allow NAT rule to match 'all' interfaces with * as interface name
-add #ifdef's for KLD_MODULE sanity
+do mapping of ICMP sequence id#'s in pings
-NAT fastroute'd packets which come out of return-*
+allow default age for NAT entries to be set per NAT rule
-fix upper/lower case crap in ftp proxy and get seq# checking fixed up.
+provide round robin selection of destination addresses for redirect
-3.4.7 08/07/2000 - Released
+ipmon can load a configuration file with instructions on actions
+to take when a matching log entry is received
-make "ipf -y" lookup NAT if's which are unknown
+now requires pfil to work on Solaris & HP-UX
-prepend line numbers to ioctl error messages in ipf/ipnat
+supports mapping outbound connections to a specific address/port
-don't apply patches to FreeBSD twice
+support toggling of logging per ipfilter 'device'
-allow for ip_len to be on an unaligned boundary early on in fr_precheck
+use queues to expire data rather than lists
-fix printing of icmp code when it is 0
+add MSN RPC proxy
-correct printing of port numbers in map rules with from/to
+add IRC proxy
-don't allow fr_func to be called at securelevel > 0 or rules to be added
-if securelevel > 0 if they have a non-zero fr_func.
+support rules with dynamic ip addresses
-3.4.6 11/06/2000 - Released
+add ability to define a pool of addresses & networks which can then
+be placed in a single rule
-add extra regression tests for new nat functionality
+support passing entire packet back to user program for authentication
-place restrictions on using '!' in map/rdr rules
+support master/slave for state information sharing
-fix up solaris compile problems
+reorganise generic code into a lib directory and make libipf.a
-3.4.5 10/06/2000 - Released
+user programs enforce version matching with the kernel
-mention -sl in ipfstat.8
+supports window scaling if seen at TCP session setup
-fix/support '!' in from/to rules (rdr) for NAT
+generates C code from filter rules to compile in or load as native
+machine code.
-add from/to support to rdr NAT rules
+supports loading rules comprised of BPF bytecode statements
-don't send ICMP errors in response to ICMP errors
+HP-UX 11 port completed
-fix sunos5 compilation for "ipfstat-top" and cleanup ipfboot
+and packets-per-second filtering
-input accounting list used for both outbound and inbound packets
+add numerical tags to rules for filtering and display in ipmon output
-3.4.4 23/05/2000 - Released
+3.4.4 23/05/2000 - Released
don't add TCP state if it is an RST packet and (attempt) to send out
RST/ICMP packets in a manner that bypasses IP Filter.
add patch to work with 4.0_STABLE delayed checksums
-3.4.3 20/05/2000 - Released
+3.4.3 20/05/2000 - Released
fix ipmon -F
diff --git a/contrib/ipfilter/INST.FreeBSD-2.2 b/contrib/ipfilter/INST.FreeBSD-2.2
index 78f7295..0e0ea06 100644
--- a/contrib/ipfilter/INST.FreeBSD-2.2
+++ b/contrib/ipfilter/INST.FreeBSD-2.2
@@ -1,3 +1,5 @@
+.\" $NetBSD$
+.\"
To build a kernel for use with the loadable kernel module, follow these
steps:
diff --git a/contrib/ipfilter/INSTALL.FreeBSD b/contrib/ipfilter/INSTALL.FreeBSD
index c732bac..a4a787a 100644
--- a/contrib/ipfilter/INSTALL.FreeBSD
+++ b/contrib/ipfilter/INSTALL.FreeBSD
@@ -1,7 +1,56 @@
-*** IF you are using FreeBSD 2.2.x, see the file "INST.FreeBSD-2.2" ***
-*** IF you are using FreeBSD 3.x, see the file "FreeBSD-3/INST.FreeBSD-3" ***
-*** IF you are using FreeBSD 4.x, see the file "FreeBSD-4.0/INST.FreeBSD-4" ***
+This file is for use with FreeBSD 4.x and 5.x only.
+
+To build a kernel for use with the loadable kernel module, follow these
+steps:
+ 1. For FreeBSD version:
+ 4.* do make freebsd4
+ 5.* do make freebsd5
+
+ 2. do "make install-bsd"
+ (probably has to be done as root)
+
+ 3. Run "BSD/kupgrade"
+
+ 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. For FreeBSD version:
+ 4.* do make freebsd4
+ 5.* do make freebsd5
+
+ 2. do "make install-bsd"
+ (probably has to be done as root)
+
+ 3. run "FreeBSD/kinstall" as root
+
+ 4. build a new kernel
+
+ 5.
+ b) If you are using FreeBSD-3 or later:
+ create devices for IP Filter as follows (assuming it was
+ installed into the device table as char dev 20):
+ mknod /dev/ipl c 79 0
+ mknod /dev/ipnat c 79 1
+ mknod /dev/ipstate c 79 2
+ mknod /dev/ipauth c 79 3
+ mknod /dev/ipsync c 79 4
+ mknod /dev/ipscan c 79 5
+
+ 6. install and reboot with the new kernel
Darren Reed
darrenr@pobox.com
diff --git a/contrib/ipfilter/IPFILTER.LICENCE b/contrib/ipfilter/IPFILTER.LICENCE
index 2b4b67e..41c151c 100644
--- a/contrib/ipfilter/IPFILTER.LICENCE
+++ b/contrib/ipfilter/IPFILTER.LICENCE
@@ -1,28 +1,29 @@
-Copyright (C) 1993-2002 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, with or without modification, in source and binary
-forms, are permitted provided that this notice is preserved in its entirety
-and due credit is given to the original author and the contributors.
-
-The licence and distribution terms for any publically available version or
-derivative of this code cannot be changed. i.e. this code cannot simply be
-copied, in part or in whole, and put under another distribution licence
-[including the GNU Public Licence.]
-
-THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
-
-I hate legalese, don't you ?
-
+/*
+ * Copyright (C) 1993-2001 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, with or without modification, in source and binary
+ * forms, are permitted provided that this notice is preserved in its entirety
+ * and due credit is given to the original author and the contributors.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied, in part or in whole, and put under another distribution licence
+ * [including the GNU Public Licence.]
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ *
+ * I hate legalese, don't you ?
+ */
diff --git a/contrib/ipfilter/README b/contrib/ipfilter/README
index 80ce748..8464af4 100644
--- a/contrib/ipfilter/README
+++ b/contrib/ipfilter/README
@@ -1,5 +1,7 @@
IP Filter - What's this about ?
============================
+Web site: http://coombs.anu.edu.au/~avalon/ip-filter.html
+How-to: http://www.obfuscation.org/ipf/ipf-howto.txt
The idea behind this package is allow those who use Unix workstations as
routers (a common occurance in Universities it appears) to apply packet
@@ -96,3 +98,4 @@ BNF
Darren Reed
darrenr@pobox.com
+http://coombs.anu.edu.au/~avalon/ip-filter.html
diff --git a/contrib/ipfilter/STYLE.TXT b/contrib/ipfilter/STYLE.TXT
new file mode 100644
index 0000000..384bcec
--- /dev/null
+++ b/contrib/ipfilter/STYLE.TXT
@@ -0,0 +1,57 @@
+
+Over time, I am moving all of the IPFilter code to what I consider a better
+coding style than it had before. If you submit patches, I expect them to
+conform as appropriate.
+
+Function Comments
+=================
+Preceeding each and every function, a comment block like this should
+be present:
+
+/* ------------------------------------------------------------------------ */
+/* Function: function-name */
+/* Returns: return-type */
+/* Parameters: param1(I) - param1 is an input parameter */
+/* p2(O) - p2 is an output parameter passed as an arg */
+/* par3(IO) - par3 is a parameter which is both input and */
+/* output. Pointers to things which are used and */
+/* then get a result stored in them qualify here. */
+/* */
+/* Description about what the function does. This comment should explain */
+/* any gotchas or algorithms that are used which aren't obvious to the */
+/* casual reader. It should not be an excuse to not use comments inside */
+/* the function. */
+/* ------------------------------------------------------------------------ */
+
+
+Tab spacing
+===========
+Tabs are to be at 8 characters.
+
+
+Conditions
+==========
+All expressions which evaluate to a boolean for a test condition, such as
+in an if()/while() statement must involve a boolean operation. Since C
+has no native boolean type, this means that one of <,>,<=,>=,==,!= must
+be present. Implied boolean evaluations are out.
+
+In code, the following is banned:
+
+if (x)
+if (!x)
+while ((a = b))
+
+and should be replaced by:
+
+if (x != 0)
+if (x == 0)
+while ((a = b) != 0)
+
+If pointers are involved, always compare with NULL, ie.:
+
+if (x != NULL)
+if (x == NULL)
+while ((a = b) != NULL)
+
+
diff --git a/contrib/ipfilter/WhatsNew40.txt b/contrib/ipfilter/WhatsNew40.txt
new file mode 100644
index 0000000..e5b8294
--- /dev/null
+++ b/contrib/ipfilter/WhatsNew40.txt
@@ -0,0 +1,90 @@
+What's new in IPFilter 4.1
+==========================
+(Well, compared to 3.*, anyway)
+In no particular order, except headline alphabetical:
+
+Administration:
+ - Run-time support for modifying ipf table size parameters.
+ - Run-time support for tuning other ipfilter parameters.
+
+Content Scanning:
+ - Simple matching of content for TCP session startup.
+
+Firewall Synchronising:
+ - Master/slave programs available.
+
+General:
+ - All input files allow simple 'marco' definitions and expansion,
+ including nesting.
+ - Code has been rototilled to make maintenance and enhancements
+ eaiser for me and you.
+ - More configuration files and binaries.
+ - Takes up more memory.
+ - Probably slower.
+ - Versioned API to support changes in the ABI without breaking
+ existing binaries (4.0 onward only.)
+ - IP-Filter framework in place for handling multiple different
+ types of packet matching for firewalling.
+ - IP Id number rewriting available.
+ - Verification of checksums for recognised packet types.
+ - Optionally enable/disable IP forwarding when enabled/disabled.
+
+IPF:
+ - BPF syntax available for matching packets in ipf rules (1).
+ - Can convert IPv4 ipf rules into C code and either:
+ * load them as an LKM o;
+ * compile them statically into the kernel (where possible.)
+ - Address pools allow for simpler rules covering large numbers of
+ addresses/networks (IPv4 only).
+ - Lookup functions available to map an IPv4 address to a group.
+ - Groups can be referenced by multiple heads for subroutine-like use.
+ - NAT/ipf rules can refer to each other via a tag, creating an implied
+ join that forms part of the packet matching.
+ - Extra packet attributes available for filter rules:
+ * source address/routing interface mismatch;
+ * multicast (3);
+ * broadcast (2,3);
+ * state lookup partially failed;
+ * out of the TCP window for a state connection;
+ * NAT lookup partially failed.
+ - PPS (packets per second) matching available for ipf rules.
+ - Rule collections (cf FreeBSD numbering) supported for ipf rules.
+ - Groups can now be names rather than just numbers
+
+IPV6:
+ - understands extension headers.
+ - can filter on extension headers.
+
+Logging:
+ - ipmon now comes with a configuration file for more advanced logging
+ behaviour.
+ - Can append arbitrary logging tags with ipf rules for easy matching.
+
+NAT:
+ - "sticky" mapping available to ensure an address translation on
+ a per-address basis is always the same (while known) for a set
+ IP address.
+
+Operating System Support:
+ - HP-UX 11 added.
+ - Tru64 5.1a added.
+ - Solaris/HP-UX now use pfil STREAMS module.
+ - Linux 2.4 on the way.
+
+Proxies:
+ - PPTP proxy added.
+ - IRC proxy added.
+ - RPCBIND proxy added.
+ - FTP proxy support for EPSV (IPv4 only.)
+
+Stateful Inspection:
+ - Can insist that all TCP data arrives in order.
+ - Can insist that all fragments pass through in order.
+ - The number of states created per-rule can be set where the total
+ across all rules may exceed the maximum allowed.
+ - Can elect not to automatically match ICMP error packets.
+ - TCP sequence number rewriting supported.
+
+(1) - Requires libpcap for rule parsing
+(2) - On Solaris/HP-UX, broadcast packets are seen as multicast packets.
+(3) - Not supported on SunOS4
diff --git a/contrib/ipfilter/bpf-ipf.h b/contrib/ipfilter/bpf-ipf.h
new file mode 100644
index 0000000..c303152
--- /dev/null
+++ b/contrib/ipfilter/bpf-ipf.h
@@ -0,0 +1,452 @@
+/* $NetBSD$ */
+
+/*-
+ * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from the Stanford/CMU enet packet filter,
+ * (net/enet.c) distributed as part of 4.3BSD, and code contributed
+ * to Berkeley by Steven McCanne and Van Jacobson both of Lawrence
+ * Berkeley Laboratory.
+ *
+ * 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.
+ *
+ * @(#)bpf.h 7.1 (Berkeley) 5/7/91
+ *
+ * @(#) $Header: /devel/CVS/IP-Filter/bpf-ipf.h,v 2.1 2002/10/26 12:14:26 darrenr Exp $ (LBL)
+ */
+
+#ifndef BPF_MAJOR_VERSION
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* BSD style release date */
+#define BPF_RELEASE 199606
+
+typedef int bpf_int32;
+typedef u_int bpf_u_int32;
+
+/*
+ * Alignment macros. BPF_WORDALIGN rounds up to the next
+ * even multiple of BPF_ALIGNMENT.
+ */
+#ifndef __NetBSD__
+#define BPF_ALIGNMENT sizeof(bpf_int32)
+#else
+#define BPF_ALIGNMENT sizeof(long)
+#endif
+#define BPF_WORDALIGN(x) (((x)+(BPF_ALIGNMENT-1))&~(BPF_ALIGNMENT-1))
+
+#define BPF_MAXINSNS 512
+#define BPF_MAXBUFSIZE 0x8000
+#define BPF_MINBUFSIZE 32
+
+/*
+ * Structure for BIOCSETF.
+ */
+struct bpf_program {
+ u_int bf_len;
+ struct bpf_insn *bf_insns;
+};
+
+/*
+ * Struct returned by BIOCGSTATS.
+ */
+struct bpf_stat {
+ u_int bs_recv; /* number of packets received */
+ u_int bs_drop; /* number of packets dropped */
+};
+
+/*
+ * Struct return by BIOCVERSION. This represents the version number of
+ * the filter language described by the instruction encodings below.
+ * bpf understands a program iff kernel_major == filter_major &&
+ * kernel_minor >= filter_minor, that is, if the value returned by the
+ * running kernel has the same major number and a minor number equal
+ * equal to or less than the filter being downloaded. Otherwise, the
+ * results are undefined, meaning an error may be returned or packets
+ * may be accepted haphazardly.
+ * It has nothing to do with the source code version.
+ */
+struct bpf_version {
+ u_short bv_major;
+ u_short bv_minor;
+};
+/* Current version number of filter architecture. */
+#define BPF_MAJOR_VERSION 1
+#define BPF_MINOR_VERSION 1
+
+/*
+ * BPF ioctls
+ *
+ * The first set is for compatibility with Sun's pcc style
+ * header files. If your using gcc, we assume that you
+ * have run fixincludes so the latter set should work.
+ */
+#if (defined(sun) || defined(ibm032)) && !defined(__GNUC__)
+#define BIOCGBLEN _IOR(B,102, u_int)
+#define BIOCSBLEN _IOWR(B,102, u_int)
+#define BIOCSETF _IOW(B,103, struct bpf_program)
+#define BIOCFLUSH _IO(B,104)
+#define BIOCPROMISC _IO(B,105)
+#define BIOCGDLT _IOR(B,106, u_int)
+#define BIOCGETIF _IOR(B,107, struct ifreq)
+#define BIOCSETIF _IOW(B,108, struct ifreq)
+#define BIOCSRTIMEOUT _IOW(B,109, struct timeval)
+#define BIOCGRTIMEOUT _IOR(B,110, struct timeval)
+#define BIOCGSTATS _IOR(B,111, struct bpf_stat)
+#define BIOCIMMEDIATE _IOW(B,112, u_int)
+#define BIOCVERSION _IOR(B,113, struct bpf_version)
+#define BIOCSTCPF _IOW(B,114, struct bpf_program)
+#define BIOCSUDPF _IOW(B,115, struct bpf_program)
+#else
+#define BIOCGBLEN _IOR('B',102, u_int)
+#define BIOCSBLEN _IOWR('B',102, u_int)
+#define BIOCSETF _IOW('B',103, struct bpf_program)
+#define BIOCFLUSH _IO('B',104)
+#define BIOCPROMISC _IO('B',105)
+#define BIOCGDLT _IOR('B',106, u_int)
+#define BIOCGETIF _IOR('B',107, struct ifreq)
+#define BIOCSETIF _IOW('B',108, struct ifreq)
+#define BIOCSRTIMEOUT _IOW('B',109, struct timeval)
+#define BIOCGRTIMEOUT _IOR('B',110, struct timeval)
+#define BIOCGSTATS _IOR('B',111, struct bpf_stat)
+#define BIOCIMMEDIATE _IOW('B',112, u_int)
+#define BIOCVERSION _IOR('B',113, struct bpf_version)
+#define BIOCSTCPF _IOW('B',114, struct bpf_program)
+#define BIOCSUDPF _IOW('B',115, struct bpf_program)
+#endif
+
+/*
+ * Structure prepended to each packet.
+ */
+struct bpf_hdr {
+ struct timeval bh_tstamp; /* time stamp */
+ bpf_u_int32 bh_caplen; /* length of captured portion */
+ bpf_u_int32 bh_datalen; /* original length of packet */
+ u_short bh_hdrlen; /* length of bpf header (this struct
+ plus alignment padding) */
+};
+/*
+ * Because the structure above is not a multiple of 4 bytes, some compilers
+ * will insist on inserting padding; hence, sizeof(struct bpf_hdr) won't work.
+ * Only the kernel needs to know about it; applications use bh_hdrlen.
+ */
+#if defined(KERNEL) || defined(_KERNEL)
+#define SIZEOF_BPF_HDR 18
+#endif
+
+/*
+ * Data-link level type codes.
+ */
+
+/*
+ * These are the types that are the same on all platforms; on other
+ * platforms, a <net/bpf.h> should be supplied that defines the additional
+ * DLT_* codes appropriately for that platform (the BSDs, for example,
+ * should not just pick up this version of "bpf.h"; they should also define
+ * the additional DLT_* codes used by their kernels, as well as the values
+ * defined here - and, if the values they use for particular DLT_ types
+ * differ from those here, they should use their values, not the ones
+ * here).
+ */
+#define DLT_NULL 0 /* no link-layer encapsulation */
+#define DLT_EN10MB 1 /* Ethernet (10Mb) */
+#define DLT_EN3MB 2 /* Experimental Ethernet (3Mb) */
+#define DLT_AX25 3 /* Amateur Radio AX.25 */
+#define DLT_PRONET 4 /* Proteon ProNET Token Ring */
+#define DLT_CHAOS 5 /* Chaos */
+#define DLT_IEEE802 6 /* IEEE 802 Networks */
+#define DLT_ARCNET 7 /* ARCNET */
+#define DLT_SLIP 8 /* Serial Line IP */
+#define DLT_PPP 9 /* Point-to-point Protocol */
+#define DLT_FDDI 10 /* FDDI */
+
+/*
+ * These are values from the traditional libpcap "bpf.h".
+ * Ports of this to particular platforms should replace these definitions
+ * with the ones appropriate to that platform, if the values are
+ * different on that platform.
+ */
+#define DLT_ATM_RFC1483 11 /* LLC/SNAP encapsulated atm */
+#define DLT_RAW 12 /* raw IP */
+
+/*
+ * These are values from BSD/OS's "bpf.h".
+ * These are not the same as the values from the traditional libpcap
+ * "bpf.h"; however, these values shouldn't be generated by any
+ * OS other than BSD/OS, so the correct values to use here are the
+ * BSD/OS values.
+ *
+ * Platforms that have already assigned these values to other
+ * DLT_ codes, however, should give these codes the values
+ * from that platform, so that programs that use these codes will
+ * continue to compile - even though they won't correctly read
+ * files of these types.
+ */
+#ifdef __NetBSD__
+#ifndef DLT_SLIP_BSDOS
+#define DLT_SLIP_BSDOS 13 /* BSD/OS Serial Line IP */
+#define DLT_PPP_BSDOS 14 /* BSD/OS Point-to-point Protocol */
+#endif
+#else
+#define DLT_SLIP_BSDOS 15 /* BSD/OS Serial Line IP */
+#define DLT_PPP_BSDOS 16 /* BSD/OS Point-to-point Protocol */
+#endif
+
+#define DLT_ATM_CLIP 19 /* Linux Classical-IP over ATM */
+
+/*
+ * These values are defined by NetBSD; other platforms should refrain from
+ * using them for other purposes, so that NetBSD savefiles with link
+ * types of 50 or 51 can be read as this type on all platforms.
+ */
+#define DLT_PPP_SERIAL 50 /* PPP over serial with HDLC encapsulation */
+#define DLT_PPP_ETHER 51 /* PPP over Ethernet */
+
+/*
+ * Values between 100 and 103 are used in capture file headers as
+ * link-layer types corresponding to DLT_ types that differ
+ * between platforms; don't use those values for new DLT_ new types.
+ */
+
+/*
+ * This value was defined by libpcap 0.5; platforms that have defined
+ * it with a different value should define it here with that value -
+ * a link type of 104 in a save file will be mapped to DLT_C_HDLC,
+ * whatever value that happens to be, so programs will correctly
+ * handle files with that link type regardless of the value of
+ * DLT_C_HDLC.
+ *
+ * The name DLT_C_HDLC was used by BSD/OS; we use that name for source
+ * compatibility with programs written for BSD/OS.
+ *
+ * libpcap 0.5 defined it as DLT_CHDLC; we define DLT_CHDLC as well,
+ * for source compatibility with programs written for libpcap 0.5.
+ */
+#define DLT_C_HDLC 104 /* Cisco HDLC */
+#define DLT_CHDLC DLT_C_HDLC
+
+#define DLT_IEEE802_11 105 /* IEEE 802.11 wireless */
+
+/*
+ * Values between 106 and 107 are used in capture file headers as
+ * link-layer types corresponding to DLT_ types that might differ
+ * between platforms; don't use those values for new DLT_ new types.
+ */
+
+/*
+ * OpenBSD DLT_LOOP, for loopback devices; it's like DLT_NULL, except
+ * that the AF_ type in the link-layer header is in network byte order.
+ *
+ * OpenBSD defines it as 12, but that collides with DLT_RAW, so we
+ * define it as 108 here. If OpenBSD picks up this file, it should
+ * define DLT_LOOP as 12 in its version, as per the comment above -
+ * and should not use 108 as a DLT_ value.
+ */
+#define DLT_LOOP 108
+
+/*
+ * Values between 109 and 112 are used in capture file headers as
+ * link-layer types corresponding to DLT_ types that might differ
+ * between platforms; don't use those values for new DLT_ types
+ * other than the corresponding DLT_ types.
+ */
+
+/*
+ * This is for Linux cooked sockets.
+ */
+#define DLT_LINUX_SLL 113
+
+/*
+ * Apple LocalTalk hardware.
+ */
+#define DLT_LTALK 114
+
+/*
+ * Acorn Econet.
+ */
+#define DLT_ECONET 115
+
+/*
+ * Reserved for use with OpenBSD ipfilter.
+ */
+#define DLT_IPFILTER 116
+
+/*
+ * Reserved for use in capture-file headers as a link-layer type
+ * corresponding to OpenBSD DLT_PFLOG; DLT_PFLOG is 17 in OpenBSD,
+ * but that's DLT_LANE8023 in SuSE 6.3, so we can't use 17 for it
+ * in capture-file headers.
+ */
+#define DLT_PFLOG 117
+
+/*
+ * Registered for Cisco-internal use.
+ */
+#define DLT_CISCO_IOS 118
+
+/*
+ * Reserved for 802.11 cards using the Prism II chips, with a link-layer
+ * header including Prism monitor mode information plus an 802.11
+ * header.
+ */
+#define DLT_PRISM_HEADER 119
+
+/*
+ * Reserved for Aironet 802.11 cards, with an Aironet link-layer header
+ * (see Doug Ambrisko's FreeBSD patches).
+ */
+#define DLT_AIRONET_HEADER 120
+
+/*
+ * Reserved for Siemens HiPath HDLC.
+ */
+#define DLT_HHDLC 121
+
+/*
+ * Reserved for RFC 2625 IP-over-Fibre Channel, as per a request from
+ * Don Lee <donlee@cray.com>.
+ *
+ * This is not for use with raw Fibre Channel, where the link-layer
+ * header starts with a Fibre Channel frame header; it's for IP-over-FC,
+ * where the link-layer header starts with an RFC 2625 Network_Header
+ * field.
+ */
+#define DLT_IP_OVER_FC 122
+
+/*
+ * The instruction encodings.
+ */
+/* instruction classes */
+#define BPF_CLASS(code) ((code) & 0x07)
+#define BPF_LD 0x00
+#define BPF_LDX 0x01
+#define BPF_ST 0x02
+#define BPF_STX 0x03
+#define BPF_ALU 0x04
+#define BPF_JMP 0x05
+#define BPF_RET 0x06
+#define BPF_MISC 0x07
+
+/* ld/ldx fields */
+#define BPF_SIZE(code) ((code) & 0x18)
+#define BPF_W 0x00
+#define BPF_H 0x08
+#define BPF_B 0x10
+#define BPF_MODE(code) ((code) & 0xe0)
+#define BPF_IMM 0x00
+#define BPF_ABS 0x20
+#define BPF_IND 0x40
+#define BPF_MEM 0x60
+#define BPF_LEN 0x80
+#define BPF_MSH 0xa0
+
+/* alu/jmp fields */
+#define BPF_OP(code) ((code) & 0xf0)
+#define BPF_ADD 0x00
+#define BPF_SUB 0x10
+#define BPF_MUL 0x20
+#define BPF_DIV 0x30
+#define BPF_OR 0x40
+#define BPF_AND 0x50
+#define BPF_LSH 0x60
+#define BPF_RSH 0x70
+#define BPF_NEG 0x80
+#define BPF_JA 0x00
+#define BPF_JEQ 0x10
+#define BPF_JGT 0x20
+#define BPF_JGE 0x30
+#define BPF_JSET 0x40
+#define BPF_SRC(code) ((code) & 0x08)
+#define BPF_K 0x00
+#define BPF_X 0x08
+
+/* ret - BPF_K and BPF_X also apply */
+#define BPF_RVAL(code) ((code) & 0x18)
+#define BPF_A 0x10
+
+/* misc */
+#define BPF_MISCOP(code) ((code) & 0xf8)
+#define BPF_TAX 0x00
+#define BPF_TXA 0x80
+
+/*
+ * The instruction data structure.
+ */
+struct bpf_insn {
+ u_short code;
+ u_char jt;
+ u_char jf;
+ bpf_int32 k;
+};
+
+/*
+ * Macros for insn array initializers.
+ */
+#define BPF_STMT(code, k) { (u_short)(code), 0, 0, k }
+#define BPF_JUMP(code, k, jt, jf) { (u_short)(code), jt, jf, k }
+
+#if defined(BSD) && (defined(KERNEL) || defined(_KERNEL))
+/*
+ * Systems based on non-BSD kernels don't have ifnet's (or they don't mean
+ * anything if it is in <net/if.h>) and won't work like this.
+ */
+# if __STDC__
+extern void bpf_tap(struct ifnet *, u_char *, u_int);
+extern void bpf_mtap(struct ifnet *, struct mbuf *);
+extern void bpfattach(struct ifnet *, u_int, u_int);
+extern void bpfilterattach(int);
+# else
+extern void bpf_tap();
+extern void bpf_mtap();
+extern void bpfattach();
+extern void bpfilterattach();
+# endif /* __STDC__ */
+#endif /* BSD && (_KERNEL || KERNEL) */
+#if __STDC__ || defined(__cplusplus)
+extern int bpf_validate(struct bpf_insn *, int);
+extern u_int bpf_filter(struct bpf_insn *, u_char *, u_int, u_int);
+#else
+extern int bpf_validate();
+extern u_int bpf_filter();
+#endif
+
+/*
+ * Number of scratch memory words (for BPF_LD|BPF_MEM and BPF_ST).
+ */
+#define BPF_MEMWORDS 16
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/contrib/ipfilter/bpf_filter.c b/contrib/ipfilter/bpf_filter.c
new file mode 100644
index 0000000..9876ff3
--- /dev/null
+++ b/contrib/ipfilter/bpf_filter.c
@@ -0,0 +1,517 @@
+/* $NetBSD$ */
+
+/*-
+ * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from the Stanford/CMU enet packet filter,
+ * (net/enet.c) distributed as part of 4.3BSD, and code contributed
+ * to Berkeley by Steven McCanne and Van Jacobson both of Lawrence
+ * Berkeley Laboratory.
+ *
+ * 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.
+ *
+ * @(#)bpf.c 7.5 (Berkeley) 7/15/91
+ */
+
+#if !(defined(lint) || defined(KERNEL) || defined(_KERNEL))
+static const char rcsid[] =
+ "@(#) $Header: /devel/CVS/IP-Filter/bpf_filter.c,v 2.2 2003/08/19 16:49:58 darrenr Exp $ (LBL)";
+#endif
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+#include <net/if.h>
+
+#include "ip_compat.h"
+#include "bpf-ipf.h"
+
+
+#if (defined(__hpux) || SOLARIS) && (defined(_KERNEL) || defined(KERNEL))
+# include <sys/sysmacros.h>
+# include <sys/stream.h>
+#endif
+
+#include "pcap-ipf.h"
+
+#if !defined(KERNEL) && !defined(_KERNEL)
+#include <stdlib.h>
+#endif
+
+#define int32 bpf_int32
+#define u_int32 bpf_u_int32
+
+static int m_xword __P((mb_t *, int, int *));
+static int m_xhalf __P((mb_t *, int, int *));
+
+#ifndef LBL_ALIGN
+/*
+ * XXX - IA-64? If not, this probably won't work on Win64 IA-64
+ * systems, unless LBL_ALIGN is defined elsewhere for them.
+ * XXX - SuperH? If not, this probably won't work on WinCE SuperH
+ * systems, unless LBL_ALIGN is defined elsewhere for them.
+ */
+#if defined(sparc) || defined(__sparc__) || defined(mips) || \
+ defined(ibm032) || defined(__alpha) || defined(__hpux) || \
+ defined(__arm__)
+#define LBL_ALIGN
+#endif
+#endif
+
+#ifndef LBL_ALIGN
+
+#define EXTRACT_SHORT(p) ((u_short)ntohs(*(u_short *)p))
+#define EXTRACT_LONG(p) (ntohl(*(u_int32 *)p))
+#else
+#define EXTRACT_SHORT(p)\
+ ((u_short)\
+ ((u_short)*((u_char *)p+0)<<8|\
+ (u_short)*((u_char *)p+1)<<0))
+#define EXTRACT_LONG(p)\
+ ((u_int32)*((u_char *)p+0)<<24|\
+ (u_int32)*((u_char *)p+1)<<16|\
+ (u_int32)*((u_char *)p+2)<<8|\
+ (u_int32)*((u_char *)p+3)<<0)
+#endif
+
+#define MINDEX(len, _m, _k) \
+{ \
+ len = M_LEN(m); \
+ while ((_k) >= len) { \
+ (_k) -= len; \
+ (_m) = (_m)->m_next; \
+ if ((_m) == 0) \
+ return 0; \
+ len = M_LEN(m); \
+ } \
+}
+
+static int
+m_xword(m, k, err)
+ register mb_t *m;
+ register int k, *err;
+{
+ register int len;
+ register u_char *cp, *np;
+ register mb_t *m0;
+
+ MINDEX(len, m, k);
+ cp = MTOD(m, u_char *) + k;
+ if (len - k >= 4) {
+ *err = 0;
+ return EXTRACT_LONG(cp);
+ }
+ m0 = m->m_next;
+ if (m0 == 0 || M_LEN(m0) + len - k < 4)
+ goto bad;
+ *err = 0;
+ np = MTOD(m0, u_char *);
+ switch (len - k) {
+
+ case 1:
+ return (cp[0] << 24) | (np[0] << 16) | (np[1] << 8) | np[2];
+
+ case 2:
+ return (cp[0] << 24) | (cp[1] << 16) | (np[0] << 8) | np[1];
+
+ default:
+ return (cp[0] << 24) | (cp[1] << 16) | (cp[2] << 8) | np[0];
+ }
+ bad:
+ *err = 1;
+ return 0;
+}
+
+static int
+m_xhalf(m, k, err)
+ register mb_t *m;
+ register int k, *err;
+{
+ register int len;
+ register u_char *cp;
+ register mb_t *m0;
+
+ MINDEX(len, m, k);
+ cp = MTOD(m, u_char *) + k;
+ if (len - k >= 2) {
+ *err = 0;
+ return EXTRACT_SHORT(cp);
+ }
+ m0 = m->m_next;
+ if (m0 == 0)
+ goto bad;
+ *err = 0;
+ return (cp[0] << 8) | MTOD(m0, u_char *)[0];
+ bad:
+ *err = 1;
+ return 0;
+}
+
+/*
+ * Execute the filter program starting at pc on the packet p
+ * wirelen is the length of the original packet
+ * buflen is the amount of data present
+ * For the kernel, p is assumed to be a pointer to an mbuf if buflen is 0,
+ * in all other cases, p is a pointer to a buffer and buflen is its size.
+ */
+u_int
+bpf_filter(pc, p, wirelen, buflen)
+ register struct bpf_insn *pc;
+ register u_char *p;
+ u_int wirelen;
+ register u_int buflen;
+{
+ register u_int32 A, X;
+ register int k;
+ int32 mem[BPF_MEMWORDS];
+ mb_t *m, *n;
+ int merr, len;
+
+ if (buflen == 0) {
+ m = (mb_t *)p;
+ p = MTOD(m, u_char *);
+ buflen = M_LEN(m);
+ } else
+ m = NULL;
+
+ if (pc == 0)
+ /*
+ * No filter means accept all.
+ */
+ return (u_int)-1;
+ A = 0;
+ X = 0;
+ --pc;
+ while (1) {
+ ++pc;
+ switch (pc->code) {
+
+ default:
+ return 0;
+ case BPF_RET|BPF_K:
+ return (u_int)pc->k;
+
+ case BPF_RET|BPF_A:
+ return (u_int)A;
+
+ case BPF_LD|BPF_W|BPF_ABS:
+ k = pc->k;
+ if (k + sizeof(int32) > buflen) {
+ if (m == NULL)
+ return 0;
+ A = m_xword(m, k, &merr);
+ if (merr != 0)
+ return 0;
+ continue;
+ }
+ A = EXTRACT_LONG(&p[k]);
+ continue;
+
+ case BPF_LD|BPF_H|BPF_ABS:
+ k = pc->k;
+ if (k + sizeof(short) > buflen) {
+ if (m == NULL)
+ return 0;
+ A = m_xhalf(m, k, &merr);
+ if (merr != 0)
+ return 0;
+ continue;
+ }
+ A = EXTRACT_SHORT(&p[k]);
+ continue;
+
+ case BPF_LD|BPF_B|BPF_ABS:
+ k = pc->k;
+ if (k >= buflen) {
+ if (m == NULL)
+ return 0;
+ n = m;
+ MINDEX(len, n, k);
+ A = MTOD(n, u_char *)[k];
+ continue;
+ }
+ A = p[k];
+ continue;
+
+ case BPF_LD|BPF_W|BPF_LEN:
+ A = wirelen;
+ continue;
+
+ case BPF_LDX|BPF_W|BPF_LEN:
+ X = wirelen;
+ continue;
+
+ case BPF_LD|BPF_W|BPF_IND:
+ k = X + pc->k;
+ if (k + sizeof(int32) > buflen) {
+ if (m == NULL)
+ return 0;
+ A = m_xword(m, k, &merr);
+ if (merr != 0)
+ return 0;
+ continue;
+ }
+ A = EXTRACT_LONG(&p[k]);
+ continue;
+
+ case BPF_LD|BPF_H|BPF_IND:
+ k = X + pc->k;
+ if (k + sizeof(short) > buflen) {
+ if (m == NULL)
+ return 0;
+ A = m_xhalf(m, k, &merr);
+ if (merr != 0)
+ return 0;
+ continue;
+ }
+ A = EXTRACT_SHORT(&p[k]);
+ continue;
+
+ case BPF_LD|BPF_B|BPF_IND:
+ k = X + pc->k;
+ if (k >= buflen) {
+ if (m == NULL)
+ return 0;
+ n = m;
+ MINDEX(len, n, k);
+ A = MTOD(n, u_char *)[k];
+ continue;
+ }
+ A = p[k];
+ continue;
+
+ case BPF_LDX|BPF_MSH|BPF_B:
+ k = pc->k;
+ if (k >= buflen) {
+ if (m == NULL)
+ return 0;
+ n = m;
+ MINDEX(len, n, k);
+ X = (MTOD(n, char *)[k] & 0xf) << 2;
+ continue;
+ }
+ X = (p[pc->k] & 0xf) << 2;
+ continue;
+
+ case BPF_LD|BPF_IMM:
+ A = pc->k;
+ continue;
+
+ case BPF_LDX|BPF_IMM:
+ X = pc->k;
+ continue;
+
+ case BPF_LD|BPF_MEM:
+ A = mem[pc->k];
+ continue;
+
+ case BPF_LDX|BPF_MEM:
+ X = mem[pc->k];
+ continue;
+
+ case BPF_ST:
+ mem[pc->k] = A;
+ continue;
+
+ case BPF_STX:
+ mem[pc->k] = X;
+ continue;
+
+ case BPF_JMP|BPF_JA:
+ pc += pc->k;
+ continue;
+
+ case BPF_JMP|BPF_JGT|BPF_K:
+ pc += (A > pc->k) ? pc->jt : pc->jf;
+ continue;
+
+ case BPF_JMP|BPF_JGE|BPF_K:
+ pc += (A >= pc->k) ? pc->jt : pc->jf;
+ continue;
+
+ case BPF_JMP|BPF_JEQ|BPF_K:
+ pc += (A == pc->k) ? pc->jt : pc->jf;
+ continue;
+
+ case BPF_JMP|BPF_JSET|BPF_K:
+ pc += (A & pc->k) ? pc->jt : pc->jf;
+ continue;
+
+ case BPF_JMP|BPF_JGT|BPF_X:
+ pc += (A > X) ? pc->jt : pc->jf;
+ continue;
+
+ case BPF_JMP|BPF_JGE|BPF_X:
+ pc += (A >= X) ? pc->jt : pc->jf;
+ continue;
+
+ case BPF_JMP|BPF_JEQ|BPF_X:
+ pc += (A == X) ? pc->jt : pc->jf;
+ continue;
+
+ case BPF_JMP|BPF_JSET|BPF_X:
+ pc += (A & X) ? pc->jt : pc->jf;
+ continue;
+
+ case BPF_ALU|BPF_ADD|BPF_X:
+ A += X;
+ continue;
+
+ case BPF_ALU|BPF_SUB|BPF_X:
+ A -= X;
+ continue;
+
+ case BPF_ALU|BPF_MUL|BPF_X:
+ A *= X;
+ continue;
+
+ case BPF_ALU|BPF_DIV|BPF_X:
+ if (X == 0)
+ return 0;
+ A /= X;
+ continue;
+
+ case BPF_ALU|BPF_AND|BPF_X:
+ A &= X;
+ continue;
+
+ case BPF_ALU|BPF_OR|BPF_X:
+ A |= X;
+ continue;
+
+ case BPF_ALU|BPF_LSH|BPF_X:
+ A <<= X;
+ continue;
+
+ case BPF_ALU|BPF_RSH|BPF_X:
+ A >>= X;
+ continue;
+
+ case BPF_ALU|BPF_ADD|BPF_K:
+ A += pc->k;
+ continue;
+
+ case BPF_ALU|BPF_SUB|BPF_K:
+ A -= pc->k;
+ continue;
+
+ case BPF_ALU|BPF_MUL|BPF_K:
+ A *= pc->k;
+ continue;
+
+ case BPF_ALU|BPF_DIV|BPF_K:
+ A /= pc->k;
+ continue;
+
+ case BPF_ALU|BPF_AND|BPF_K:
+ A &= pc->k;
+ continue;
+
+ case BPF_ALU|BPF_OR|BPF_K:
+ A |= pc->k;
+ continue;
+
+ case BPF_ALU|BPF_LSH|BPF_K:
+ A <<= pc->k;
+ continue;
+
+ case BPF_ALU|BPF_RSH|BPF_K:
+ A >>= pc->k;
+ continue;
+
+ case BPF_ALU|BPF_NEG:
+ A = -A;
+ continue;
+
+ case BPF_MISC|BPF_TAX:
+ X = A;
+ continue;
+
+ case BPF_MISC|BPF_TXA:
+ A = X;
+ continue;
+ }
+ }
+}
+
+
+/*
+ * Return true if the 'fcode' is a valid filter program.
+ * The constraints are that each jump be forward and to a valid
+ * code. The code must terminate with either an accept or reject.
+ * 'valid' is an array for use by the routine (it must be at least
+ * 'len' bytes long).
+ *
+ * The kernel needs to be able to verify an application's filter code.
+ * Otherwise, a bogus program could easily crash the system.
+ */
+int
+bpf_validate(f, len)
+ struct bpf_insn *f;
+ int len;
+{
+ register int i;
+ register struct bpf_insn *p;
+
+ for (i = 0; i < len; ++i) {
+ /*
+ * Check that that jumps are forward, and within
+ * the code block.
+ */
+ p = &f[i];
+ if (BPF_CLASS(p->code) == BPF_JMP) {
+ register int from = i + 1;
+
+ if (BPF_OP(p->code) == BPF_JA) {
+ if (from + p->k >= (unsigned)len)
+ return 0;
+ }
+ else if (from + p->jt >= len || from + p->jf >= len)
+ return 0;
+ }
+ /*
+ * Check that memory operations use valid addresses.
+ */
+ if ((BPF_CLASS(p->code) == BPF_ST ||
+ (BPF_CLASS(p->code) == BPF_LD &&
+ (p->code & 0xe0) == BPF_MEM)) &&
+ (p->k >= BPF_MEMWORDS || p->k < 0))
+ return 0;
+ /*
+ * Check for constant division by 0.
+ */
+ if (p->code == (BPF_ALU|BPF_DIV|BPF_K) && p->k == 0)
+ return 0;
+ }
+ return BPF_CLASS(f[len - 1].code) == BPF_RET;
+}
diff --git a/contrib/ipfilter/bsdinstall b/contrib/ipfilter/bsdinstall
index ce921b6..7689a21 100755
--- a/contrib/ipfilter/bsdinstall
+++ b/contrib/ipfilter/bsdinstall
@@ -5,8 +5,13 @@
cmd=/bin/mv
strip=""
chmod="chmod 755"
-chown="chown -f root"
-chgrp="chgrp -f bin"
+if [ "`uname -s`" = "HP-UX" ] ; then
+ chown="chown root"
+ chgrp="chgrp bin"
+else
+ chown="chown -f root"
+ chgrp="chgrp -f bin"
+fi
while true ; do
case $1 in
-s ) strip="strip"
diff --git a/contrib/ipfilter/etc/protocols b/contrib/ipfilter/etc/protocols
index fd7a1d2..30c5b76 100644
--- a/contrib/ipfilter/etc/protocols
+++ b/contrib/ipfilter/etc/protocols
@@ -38,9 +38,12 @@ 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
+ipv6 41 IPv6 # Internet Protocol, version 6
sip 41 SIP # Simple Internet Protocol
sdrp 42 SDRP # Source Demand Routing Protocol
+ipv6-route 43 IPv6-Route # Routing Header for IPv6
sip-sr 43 SIP-SR # SIP Source Route
+ipv6-frag 44 IPv6-Frag # Fragment Hedaer for IPv6
sip-frag 44 SIP-FRAG # SIP Fragment
idrp 45 IDRP # Inter-Domain Routing Protocol
rsvp 46 RSVP # Reservation Protocol
diff --git a/contrib/ipfilter/etc/services b/contrib/ipfilter/etc/services
index 01c4b782..d8aa0d5 100644
--- a/contrib/ipfilter/etc/services
+++ b/contrib/ipfilter/etc/services
@@ -2359,8 +2359,8 @@ dpserve 7020/tcp # DP Serve
dpserve 7020/udp # DP Serve
dpserveadmin 7021/tcp # DP Serve Admin
dpserveadmin 7021/udp # DP Serve Admin
+raudio 7070/tcp @ Real Audio
arcp 7070/tcp # ARCP
-raudio 7070/tcp # Real Audio
arcp 7070/udp # ARCP
clutild 7174/tcp # Clutild
clutild 7174/udp # Clutild
diff --git a/contrib/ipfilter/ip_fil_freebsd.c b/contrib/ipfilter/ip_fil_freebsd.c
new file mode 100644
index 0000000..3b36b93
--- /dev/null
+++ b/contrib/ipfilter/ip_fil_freebsd.c
@@ -0,0 +1,1692 @@
+/* $NetBSD$ */
+
+/*
+ * Copyright (C) 1993-2003 by Darren Reed.
+ *
+ * See the IPFILTER.LICENCE file for details on licencing.
+ */
+#if !defined(lint)
+static const char sccsid[] = "@(#)ip_fil.c 2.41 6/5/96 (C) 1993-2000 Darren Reed";
+static const char rcsid[] = "@(#)Id: ip_fil_freebsd.c,v 2.53.2.25 2005/02/01 03:15:56 darrenr Exp";
+#endif
+
+#if defined(KERNEL) || defined(_KERNEL)
+# undef KERNEL
+# undef _KERNEL
+# define KERNEL 1
+# define _KERNEL 1
+#endif
+#if defined(__FreeBSD_version) && (__FreeBSD_version >= 400000) && \
+ !defined(KLD_MODULE) && !defined(IPFILTER_LKM)
+# include "opt_inet6.h"
+#endif
+#if defined(__FreeBSD_version) && (__FreeBSD_version >= 440000) && \
+ !defined(KLD_MODULE) && !defined(IPFILTER_LKM)
+# include "opt_random_ip_id.h"
+#endif
+#include <sys/param.h>
+#if defined(__FreeBSD__) && !defined(__FreeBSD_version)
+# if defined(IPFILTER_LKM)
+# ifndef __FreeBSD_cc_version
+# include <osreldate.h>
+# else
+# if __FreeBSD_cc_version < 430000
+# include <osreldate.h>
+# endif
+# endif
+# endif
+#endif
+#include <sys/errno.h>
+#include <sys/types.h>
+#include <sys/file.h>
+#if __FreeBSD_version >= 220000
+# include <sys/fcntl.h>
+# include <sys/filio.h>
+#else
+# include <sys/ioctl.h>
+#endif
+#include <sys/time.h>
+#include <sys/systm.h>
+#if (__FreeBSD_version >= 300000)
+# include <sys/dirent.h>
+#else
+# include <sys/dir.h>
+#endif
+#if !defined(__hpux)
+# include <sys/mbuf.h>
+#endif
+#include <sys/protosw.h>
+#include <sys/socket.h>
+
+#include <net/if.h>
+#if __FreeBSD_version >= 300000
+# include <net/if_var.h>
+# if !defined(IPFILTER_LKM)
+# include "opt_ipfilter.h"
+# endif
+#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>
+#if defined(__osf__)
+# include <netinet/tcp_timer.h>
+#endif
+#include <netinet/udp.h>
+#include <netinet/tcpip.h>
+#include <netinet/ip_icmp.h>
+#ifndef _KERNEL
+# include "netinet/ipf.h"
+#endif
+#include "netinet/ip_compat.h"
+#ifdef USE_INET6
+# include <netinet/icmp6.h>
+#endif
+#include "netinet/ip_fil.h"
+#include "netinet/ip_nat.h"
+#include "netinet/ip_frag.h"
+#include "netinet/ip_state.h"
+#include "netinet/ip_proxy.h"
+#include "netinet/ip_auth.h"
+#ifdef IPFILTER_SYNC
+#include "netinet/ip_sync.h"
+#endif
+#ifdef IPFILTER_SCAN
+#include "netinet/ip_scan.h"
+#endif
+#include "netinet/ip_pool.h"
+#if defined(__FreeBSD_version) && (__FreeBSD_version >= 300000)
+# include <sys/malloc.h>
+#endif
+#include <sys/kernel.h>
+#ifdef CSUM_DATA_VALID
+#include <machine/in_cksum.h>
+#endif
+extern int ip_optcopy __P((struct ip *, struct ip *));
+
+#if (__FreeBSD_version > 460000)
+extern int path_mtu_discovery;
+#endif
+
+# ifdef IPFILTER_M_IPFILTER
+MALLOC_DEFINE(M_IPFILTER, "IP Filter", "IP Filter packet filter data structures");
+# endif
+
+
+#if !defined(__osf__)
+extern struct protosw inetsw[];
+#endif
+
+static int (*fr_savep) __P((ip_t *, int, void *, int, struct mbuf **));
+static int fr_send_ip __P((fr_info_t *, mb_t *, mb_t **));
+# ifdef USE_MUTEXES
+ipfmutex_t ipl_mutex, ipf_authmx, ipf_rw, ipf_stinsert;
+ipfmutex_t ipf_nat_new, ipf_natio, ipf_timeoutlock;
+ipfrwlock_t ipf_mutex, ipf_global, ipf_ipidfrag;
+ipfrwlock_t ipf_frag, ipf_state, ipf_nat, ipf_natfrag, ipf_auth;
+# endif
+int ipf_locks_done = 0;
+
+#if (__FreeBSD_version >= 300000)
+struct callout_handle fr_slowtimer_ch;
+#endif
+
+#if (__FreeBSD_version >= 500011)
+# include <sys/conf.h>
+# if defined(NETBSD_PF)
+# include <net/pfil.h>
+# include <netinet/ipprotosw.h>
+/*
+ * We provide the fr_checkp name just to minimize changes later.
+ */
+int (*fr_checkp) __P((ip_t *ip, int hlen, void *ifp, int out, mb_t **mp));
+# endif /* NETBSD_PF */
+#endif /* __FreeBSD_version >= 500011 */
+
+
+#if (__FreeBSD_version >= 501108) && defined(_KERNEL)
+
+static int
+fr_check_wrapper(void *arg, struct mbuf **mp, struct ifnet *ifp, int dir)
+{
+ struct ip *ip = mtod(*mp, struct ip *);
+ return fr_check(ip, ip->ip_hl << 2, ifp, (dir == PFIL_OUT), mp);
+}
+
+# ifdef USE_INET6
+# include <netinet/ip6.h>
+
+static int
+fr_check_wrapper6(void *arg, struct mbuf **mp, struct ifnet *ifp, int dir)
+{
+ return (fr_check(mtod(*mp, struct ip *), sizeof(struct ip6_hdr),
+ ifp, (dir == PFIL_OUT), mp));
+}
+# endif
+#endif /* __FreeBSD_version >= 501108 */
+#if defined(IPFILTER_LKM)
+int iplidentify(s)
+char *s;
+{
+ if (strcmp(s, "ipl") == 0)
+ return 1;
+ return 0;
+}
+#endif /* IPFILTER_LKM */
+
+
+int iplattach()
+{
+#ifdef USE_SPL
+ int s;
+#endif
+#if defined(NETBSD_PF) && (__FreeBSD_version >= 500011)
+ int error = 0;
+# if __FreeBSD_version >= 501108
+ struct pfil_head *ph_inet;
+# ifdef USE_INET6
+ struct pfil_head *ph_inet6;
+# endif
+# endif
+#endif
+
+ SPL_NET(s);
+ if (fr_running > 0) {
+ SPL_X(s);
+ return EBUSY;
+ }
+
+ MUTEX_INIT(&ipf_rw, "ipf rw mutex");
+ RWLOCK_INIT(&ipf_global, "ipf filter load/unload mutex");
+ MUTEX_INIT(&ipf_timeoutlock, "ipf timeout queue mutex");
+ RWLOCK_INIT(&ipf_mutex, "ipf filter rwlock");
+ RWLOCK_INIT(&ipf_ipidfrag, "ipf IP NAT-Frag rwlock");
+ ipf_locks_done = 1;
+
+ if (fr_initialise() < 0) {
+ SPL_X(s);
+ return EIO;
+ }
+
+
+# ifdef NETBSD_PF
+# if __FreeBSD_version >= 500011
+# if __FreeBSD_version >= 501108
+ ph_inet = pfil_head_get(PFIL_TYPE_AF, AF_INET);
+# ifdef USE_INET6
+ ph_inet6 = pfil_head_get(PFIL_TYPE_AF, AF_INET6);
+# endif
+ if (ph_inet == NULL
+# ifdef USE_INET6
+ && ph_inet6 == NULL
+# endif
+ )
+ return ENODEV;
+
+ if (ph_inet != NULL)
+ error = pfil_add_hook((void *)fr_check_wrapper, NULL,
+ PFIL_IN|PFIL_OUT, ph_inet);
+ else
+ error = 0;
+# else
+ error = pfil_add_hook((void *)fr_check, PFIL_IN|PFIL_OUT,
+ &inetsw[ip_protox[IPPROTO_IP]].pr_pfh);
+# endif
+ if (error) {
+# ifdef USE_INET6
+ goto pfil_error;
+# else
+ fr_deinitialise();
+ SPL_X(s);
+ return error;
+# endif
+ }
+# else
+ pfil_add_hook((void *)fr_check, PFIL_IN|PFIL_OUT);
+# endif
+# ifdef USE_INET6
+# if __FreeBSD_version >= 501108
+ if (ph_inet6 != NULL)
+ error = pfil_add_hook((void *)fr_check_wrapper6, NULL,
+ PFIL_IN|PFIL_OUT, ph_inet6);
+ else
+ error = 0;
+ if (error) {
+ pfil_remove_hook((void *)fr_check_wrapper6, NULL,
+ PFIL_IN|PFIL_OUT, ph_inet6);
+# else
+ error = pfil_add_hook((void *)fr_check, PFIL_IN|PFIL_OUT,
+ &inet6sw[ip6_protox[IPPROTO_IPV6]].pr_pfh);
+ if (error) {
+ pfil_remove_hook((void *)fr_check, PFIL_IN|PFIL_OUT,
+ &inetsw[ip_protox[IPPROTO_IP]].pr_pfh);
+# endif
+pfil_error:
+ fr_deinitialise();
+ SPL_X(s);
+ return error;
+ }
+# endif
+# endif
+ if (fr_checkp != fr_check) {
+ fr_savep = fr_checkp;
+ fr_checkp = fr_check;
+ }
+
+ bzero((char *)frcache, sizeof(frcache));
+ fr_running = 1;
+
+ if (fr_control_forwarding & 1)
+ ipforwarding = 1;
+
+ SPL_X(s);
+#if (__FreeBSD_version >= 300000)
+ fr_slowtimer_ch = timeout(fr_slowtimer, NULL,
+ (hz / IPF_HZ_DIVIDE) * IPF_HZ_MULT);
+#else
+ timeout(fr_slowtimer, NULL, (hz / IPF_HZ_DIVIDE) * IPF_HZ_MULT);
+#endif
+ return 0;
+}
+
+
+/*
+ * Disable the filter by removing the hooks from the IP input/output
+ * stream.
+ */
+int ipldetach()
+{
+#ifdef USE_SPL
+ int s;
+#endif
+#if defined(NETBSD_PF) && (__FreeBSD_version >= 500011)
+ int error = 0;
+# if __FreeBSD_version >= 501108
+ struct pfil_head *ph_inet;
+# ifdef USE_INET6
+ struct pfil_head *ph_inet6;
+# endif
+# endif
+#endif
+
+ if (fr_control_forwarding & 2)
+ ipforwarding = 0;
+
+ SPL_NET(s);
+
+#if (__FreeBSD_version >= 300000)
+ if (fr_slowtimer_ch.callout != NULL)
+ untimeout(fr_slowtimer, NULL, fr_slowtimer_ch);
+ bzero(&fr_slowtimer_ch, sizeof(fr_slowtimer_ch));
+#else
+ untimeout(fr_slowtimer, NULL);
+#endif /* FreeBSD */
+
+#ifndef NETBSD_PF
+ if (fr_checkp != NULL)
+ fr_checkp = fr_savep;
+ fr_savep = NULL;
+#endif
+
+#ifdef NETBSD_PF
+# if (__FreeBSD_version >= 500011)
+# if (__FreeBSD_version >= 501108)
+ ph_inet = pfil_head_get(PFIL_TYPE_AF, AF_INET);
+ if (ph_inet != NULL)
+ error = pfil_remove_hook((void *)fr_check_wrapper, NULL,
+ PFIL_IN|PFIL_OUT, ph_inet);
+ else
+ error = 0;
+# else
+ error = pfil_remove_hook((void *)fr_check, PFIL_IN|PFIL_OUT,
+ &inetsw[ip_protox[IPPROTO_IP]].pr_pfh);
+# endif
+ if (error) {
+ SPL_X(s);
+ return error;
+ }
+# else
+ pfil_remove_hook((void *)fr_check, PFIL_IN|PFIL_OUT);
+# endif
+# ifdef USE_INET6
+# if (__FreeBSD_version >= 501108)
+ ph_inet6 = pfil_head_get(PFIL_TYPE_AF, AF_INET6);
+ if (ph_inet6 != NULL)
+ error = pfil_remove_hook((void *)fr_check_wrapper6, NULL,
+ PFIL_IN|PFIL_OUT, ph_inet6);
+ else
+ error = 0;
+# else
+ error = pfil_remove_hook((void *)fr_check, PFIL_IN|PFIL_OUT,
+ &inet6sw[ip6_protox[IPPROTO_IPV6]].pr_pfh);
+# endif
+ if (error) {
+ SPL_X(s);
+ return error;
+ }
+# endif
+#endif
+ fr_deinitialise();
+
+ fr_running = -2;
+
+ (void) frflush(IPL_LOGIPF, 0, FR_INQUE|FR_OUTQUE|FR_INACTIVE);
+ (void) frflush(IPL_LOGIPF, 0, FR_INQUE|FR_OUTQUE);
+
+ if (ipf_locks_done == 1) {
+ MUTEX_DESTROY(&ipf_timeoutlock);
+ MUTEX_DESTROY(&ipf_rw);
+ RW_DESTROY(&ipf_mutex);
+ RW_DESTROY(&ipf_ipidfrag);
+ RW_DESTROY(&ipf_global);
+ ipf_locks_done = 0;
+ }
+
+ SPL_X(s);
+
+ return 0;
+}
+
+
+/*
+ * Filter ioctl interface.
+ */
+int iplioctl(dev, cmd, data, mode
+# if defined(_KERNEL) && ((BSD >= 199506) || (__FreeBSD_version >= 220000))
+, p)
+# if (__FreeBSD_version >= 500024)
+struct thread *p;
+# else
+struct proc *p;
+# endif /* __FreeBSD_version >= 500024 */
+# else
+)
+# endif
+#if defined(_KERNEL) && (__FreeBSD_version >= 502116)
+struct cdev *dev;
+#else
+dev_t dev;
+#endif
+ioctlcmd_t cmd;
+caddr_t data;
+int mode;
+{
+#ifdef USE_SPL
+ int s;
+#endif
+ int error = 0, unit = 0, tmp;
+ friostat_t fio;
+
+#if (BSD >= 199306) && defined(_KERNEL)
+ if ((securelevel >= 2) && (mode & FWRITE))
+ return EPERM;
+#endif
+
+ unit = GET_MINOR(dev);
+ if ((IPL_LOGMAX < unit) || (unit < 0))
+ return ENXIO;
+
+ if (fr_running <= 0) {
+ if (unit != IPL_LOGIPF)
+ return EIO;
+ if (cmd != SIOCIPFGETNEXT && cmd != SIOCIPFGET &&
+ cmd != SIOCIPFSET && cmd != SIOCFRENB &&
+ cmd != SIOCGETFS && cmd != SIOCGETFF)
+ return EIO;
+ }
+
+ SPL_NET(s);
+
+ error = fr_ioctlswitch(unit, data, cmd, mode);
+ if (error != -1) {
+ SPL_X(s);
+ return error;
+ }
+ error = 0;
+
+ switch (cmd)
+ {
+ case FIONREAD :
+#ifdef IPFILTER_LOG
+ BCOPYOUT(&iplused[IPL_LOGIPF], (caddr_t)data,
+ sizeof(iplused[IPL_LOGIPF]));
+#endif
+ break;
+ case SIOCFRENB :
+ if (!(mode & FWRITE))
+ error = EPERM;
+ else {
+ BCOPYIN(data, &tmp, sizeof(tmp));
+ if (tmp) {
+ if (fr_running > 0)
+ error = 0;
+ else
+ error = iplattach();
+ if (error == 0)
+ fr_running = 1;
+ else
+ (void) ipldetach();
+ } else {
+ error = ipldetach();
+ if (error == 0)
+ fr_running = -1;
+ }
+ }
+ break;
+ case SIOCIPFSET :
+ if (!(mode & FWRITE)) {
+ error = EPERM;
+ break;
+ }
+ case SIOCIPFGETNEXT :
+ case SIOCIPFGET :
+ error = fr_ipftune(cmd, data);
+ break;
+ case SIOCSETFF :
+ if (!(mode & FWRITE))
+ error = EPERM;
+ else
+ BCOPYIN(data, &fr_flags, sizeof(fr_flags));
+ break;
+ case SIOCGETFF :
+ BCOPYOUT(&fr_flags, data, sizeof(fr_flags));
+ break;
+ case SIOCFUNCL :
+ error = fr_resolvefunc(data);
+ break;
+ case SIOCINAFR :
+ case SIOCRMAFR :
+ case SIOCADAFR :
+ case SIOCZRLST :
+ if (!(mode & FWRITE))
+ error = EPERM;
+ else
+ error = frrequest(unit, cmd, data, fr_active, 1);
+ break;
+ case SIOCINIFR :
+ case SIOCRMIFR :
+ case SIOCADIFR :
+ if (!(mode & FWRITE))
+ error = EPERM;
+ else
+ error = frrequest(unit, cmd, data, 1 - fr_active, 1);
+ 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 :
+ fr_getstat(&fio);
+ error = fr_outobj(data, &fio, IPFOBJ_IPFSTAT);
+ break;
+ case SIOCFRZST :
+ if (!(mode & FWRITE))
+ error = EPERM;
+ else
+ error = fr_zerostats(data);
+ break;
+ case SIOCIPFFL :
+ if (!(mode & FWRITE))
+ error = EPERM;
+ else {
+ BCOPYIN(data, &tmp, sizeof(tmp));
+ tmp = frflush(unit, 4, tmp);
+ BCOPYOUT(&tmp, data, sizeof(tmp));
+ }
+ break;
+#ifdef USE_INET6
+ case SIOCIPFL6 :
+ if (!(mode & FWRITE))
+ error = EPERM;
+ else {
+ BCOPYIN(data, &tmp, sizeof(tmp));
+ tmp = frflush(unit, 6, tmp);
+ BCOPYOUT(&tmp, data, sizeof(tmp));
+ }
+ break;
+#endif
+ case SIOCSTLCK :
+ BCOPYIN(data, &tmp, sizeof(tmp));
+ fr_state_lock = tmp;
+ fr_nat_lock = tmp;
+ fr_frag_lock = tmp;
+ fr_auth_lock = tmp;
+ break;
+#ifdef IPFILTER_LOG
+ case SIOCIPFFB :
+ if (!(mode & FWRITE))
+ error = EPERM;
+ else
+ *(int *)data = ipflog_clear(unit);
+ break;
+#endif /* IPFILTER_LOG */
+ case SIOCGFRST :
+ error = fr_outobj(data, fr_fragstats(), IPFOBJ_FRAGSTAT);
+ break;
+ case SIOCFRSYN :
+ if (!(mode & FWRITE))
+ error = EPERM;
+ else {
+ frsync(NULL);
+ }
+ break;
+ default :
+ error = EINVAL;
+ break;
+ }
+ SPL_X(s);
+ return error;
+}
+
+
+#if 0
+void fr_forgetifp(ifp)
+void *ifp;
+{
+ register frentry_t *f;
+
+ WRITE_ENTER(&ipf_mutex);
+ for (f = ipacct[0][fr_active]; (f != NULL); f = f->fr_next)
+ if (f->fr_ifa == ifp)
+ f->fr_ifa = (void *)-1;
+ for (f = ipacct[1][fr_active]; (f != NULL); f = f->fr_next)
+ if (f->fr_ifa == ifp)
+ f->fr_ifa = (void *)-1;
+ for (f = ipfilter[0][fr_active]; (f != NULL); f = f->fr_next)
+ if (f->fr_ifa == ifp)
+ f->fr_ifa = (void *)-1;
+ for (f = ipfilter[1][fr_active]; (f != NULL); f = f->fr_next)
+ if (f->fr_ifa == ifp)
+ f->fr_ifa = (void *)-1;
+#ifdef USE_INET6
+ for (f = ipacct6[0][fr_active]; (f != NULL); f = f->fr_next)
+ if (f->fr_ifa == ifp)
+ f->fr_ifa = (void *)-1;
+ for (f = ipacct6[1][fr_active]; (f != NULL); f = f->fr_next)
+ if (f->fr_ifa == ifp)
+ f->fr_ifa = (void *)-1;
+ for (f = ipfilter6[0][fr_active]; (f != NULL); f = f->fr_next)
+ if (f->fr_ifa == ifp)
+ f->fr_ifa = (void *)-1;
+ for (f = ipfilter6[1][fr_active]; (f != NULL); f = f->fr_next)
+ if (f->fr_ifa == ifp)
+ f->fr_ifa = (void *)-1;
+#endif
+ RWLOCK_EXIT(&ipf_mutex);
+ fr_natsync(ifp);
+}
+#endif
+
+
+/*
+ * routines below for saving IP headers to buffer
+ */
+int iplopen(dev, flags
+#if ((BSD >= 199506) || (__FreeBSD_version >= 220000)) && defined(_KERNEL)
+, devtype, p)
+int devtype;
+# if (__FreeBSD_version >= 500024)
+struct thread *p;
+# else
+struct proc *p;
+# endif /* __FreeBSD_version >= 500024 */
+#else
+)
+#endif
+#if defined(_KERNEL) && (__FreeBSD_version >= 502116)
+struct cdev *dev;
+#else
+dev_t dev;
+#endif
+int flags;
+{
+ u_int min = GET_MINOR(dev);
+
+ if (IPL_LOGMAX < min)
+ min = ENXIO;
+ else
+ min = 0;
+ return min;
+}
+
+
+int iplclose(dev, flags
+#if ((BSD >= 199506) || (__FreeBSD_version >= 220000)) && defined(_KERNEL)
+, devtype, p)
+int devtype;
+# if (__FreeBSD_version >= 500024)
+struct thread *p;
+# else
+struct proc *p;
+# endif /* __FreeBSD_version >= 500024 */
+#else
+)
+#endif
+#if defined(_KERNEL) && (__FreeBSD_version >= 502116)
+struct cdev *dev;
+#else
+dev_t dev;
+#endif
+int flags;
+{
+ u_int min = GET_MINOR(dev);
+
+ if (IPL_LOGMAX < min)
+ min = ENXIO;
+ else
+ min = 0;
+ return min;
+}
+
+/*
+ * 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
+#if defined(_KERNEL) && (__FreeBSD_version >= 502116)
+struct cdev *dev;
+#else
+dev_t dev;
+#endif
+register struct uio *uio;
+{
+
+# ifdef IPFILTER_SYNC
+ if (GET_MINOR(dev) == IPL_LOGSYNC)
+ return ipfsync_read(uio);
+# endif
+
+#ifdef IPFILTER_LOG
+ return ipflog_read(GET_MINOR(dev), uio);
+#else
+ return ENXIO;
+#endif
+}
+
+
+/*
+ * iplwrite
+ * 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 iplwrite(dev, uio, ioflag)
+int ioflag;
+#else
+int iplwrite(dev, uio)
+#endif
+#if defined(_KERNEL) && (__FreeBSD_version >= 502116)
+struct cdev *dev;
+#else
+dev_t dev;
+#endif
+register struct uio *uio;
+{
+
+#ifdef IPFILTER_SYNC
+ if (GET_MINOR(dev) == IPL_LOGSYNC)
+ return ipfsync_write(uio);
+#endif
+ return ENXIO;
+}
+
+
+/*
+ * fr_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 fr_send_reset(fin)
+fr_info_t *fin;
+{
+ struct tcphdr *tcp, *tcp2;
+ int tlen = 0, hlen;
+ struct mbuf *m;
+#ifdef USE_INET6
+ ip6_t *ip6;
+#endif
+ ip_t *ip;
+
+ tcp = fin->fin_dp;
+ if (tcp->th_flags & TH_RST)
+ return -1; /* feedback loop */
+
+#ifndef IPFILTER_CKSUM
+ if (fr_checkl4sum(fin) == -1)
+ return -1;
+#endif
+
+ tlen = fin->fin_dlen - (TCP_OFF(tcp) << 2) +
+ ((tcp->th_flags & TH_SYN) ? 1 : 0) +
+ ((tcp->th_flags & TH_FIN) ? 1 : 0);
+
+#ifdef USE_INET6
+ hlen = (fin->fin_v == 6) ? sizeof(ip6_t) : sizeof(ip_t);
+#else
+ hlen = sizeof(ip_t);
+#endif
+#ifdef MGETHDR
+ MGETHDR(m, M_DONTWAIT, MT_HEADER);
+#else
+ MGET(m, M_DONTWAIT, MT_HEADER);
+#endif
+ if (m == NULL)
+ return -1;
+ if (sizeof(*tcp2) + hlen > MLEN) {
+ MCLGET(m, M_DONTWAIT);
+ if ((m->m_flags & M_EXT) == 0) {
+ FREE_MB_T(m);
+ return -1;
+ }
+ }
+
+ m->m_len = sizeof(*tcp2) + hlen;
+#if (BSD >= 199103)
+ m->m_data += max_linkhdr;
+ m->m_pkthdr.len = m->m_len;
+ m->m_pkthdr.rcvif = (struct ifnet *)0;
+#endif
+ ip = mtod(m, struct ip *);
+ bzero((char *)ip, hlen);
+#ifdef USE_INET6
+ ip6 = (ip6_t *)ip;
+#endif
+ tcp2 = (struct tcphdr *)((char *)ip + hlen);
+ tcp2->th_sport = tcp->th_dport;
+ tcp2->th_dport = tcp->th_sport;
+
+ if (tcp->th_flags & TH_ACK) {
+ tcp2->th_seq = tcp->th_ack;
+ tcp2->th_flags = TH_RST;
+ tcp2->th_ack = 0;
+ } else {
+ tcp2->th_seq = 0;
+ tcp2->th_ack = ntohl(tcp->th_seq);
+ tcp2->th_ack += tlen;
+ tcp2->th_ack = htonl(tcp2->th_ack);
+ tcp2->th_flags = TH_RST|TH_ACK;
+ }
+ TCP_X2_A(tcp2, 0);
+ TCP_OFF_A(tcp2, sizeof(*tcp2) >> 2);
+ tcp2->th_win = tcp->th_win;
+ tcp2->th_sum = 0;
+ tcp2->th_urp = 0;
+
+#ifdef USE_INET6
+ if (fin->fin_v == 6) {
+ ip6->ip6_flow = ((ip6_t *)fin->fin_ip)->ip6_flow;
+ ip6->ip6_plen = htons(sizeof(struct tcphdr));
+ ip6->ip6_nxt = IPPROTO_TCP;
+ ip6->ip6_hlim = 0;
+ ip6->ip6_src = fin->fin_dst6;
+ ip6->ip6_dst = fin->fin_src6;
+ tcp2->th_sum = in6_cksum(m, IPPROTO_TCP,
+ sizeof(*ip6), sizeof(*tcp2));
+ return fr_send_ip(fin, m, &m);
+ }
+#endif
+ ip->ip_p = IPPROTO_TCP;
+ ip->ip_len = htons(sizeof(struct tcphdr));
+ ip->ip_src.s_addr = fin->fin_daddr;
+ ip->ip_dst.s_addr = fin->fin_saddr;
+ tcp2->th_sum = in_cksum(m, hlen + sizeof(*tcp2));
+ ip->ip_len = hlen + sizeof(*tcp2);
+ return fr_send_ip(fin, m, &m);
+}
+
+
+static int fr_send_ip(fin, m, mpp)
+fr_info_t *fin;
+mb_t *m, **mpp;
+{
+ fr_info_t fnew;
+ ip_t *ip, *oip;
+ int hlen;
+
+ ip = mtod(m, ip_t *);
+ bzero((char *)&fnew, sizeof(fnew));
+
+ IP_V_A(ip, fin->fin_v);
+ switch (fin->fin_v)
+ {
+ case 4 :
+ fnew.fin_v = 4;
+ oip = fin->fin_ip;
+ IP_HL_A(ip, sizeof(*oip) >> 2);
+ ip->ip_tos = oip->ip_tos;
+ ip->ip_id = fin->fin_ip->ip_id;
+#if (__FreeBSD_version > 460000)
+ ip->ip_off = path_mtu_discovery ? IP_DF : 0;
+#else
+ ip->ip_off = 0;
+#endif
+ ip->ip_ttl = ip_defttl;
+ ip->ip_sum = 0;
+ hlen = sizeof(*oip);
+ break;
+#ifdef USE_INET6
+ case 6 :
+ {
+ ip6_t *ip6 = (ip6_t *)ip;
+
+ ip6->ip6_vfc = 0x60;
+ ip6->ip6_hlim = IPDEFTTL;
+
+ fnew.fin_v = 6;
+ hlen = sizeof(*ip6);
+ break;
+ }
+#endif
+ default :
+ return EINVAL;
+ }
+#ifdef IPSEC
+ m->m_pkthdr.rcvif = NULL;
+#endif
+
+ fnew.fin_ifp = fin->fin_ifp;
+ fnew.fin_flx = FI_NOCKSUM;
+ fnew.fin_m = m;
+ fnew.fin_ip = ip;
+ fnew.fin_mp = mpp;
+ fnew.fin_hlen = hlen;
+ fnew.fin_dp = (char *)ip + hlen;
+ (void) fr_makefrip(hlen, ip, &fnew);
+
+ return fr_fastroute(m, mpp, &fnew, NULL);
+}
+
+
+int fr_send_icmp_err(type, fin, dst)
+int type;
+fr_info_t *fin;
+int dst;
+{
+ int err, hlen, xtra, iclen, ohlen, avail, code;
+ struct in_addr dst4;
+ struct icmp *icmp;
+ struct mbuf *m;
+ void *ifp;
+#ifdef USE_INET6
+ ip6_t *ip6;
+ struct in6_addr dst6;
+#endif
+ ip_t *ip, *ip2;
+
+ if ((type < 0) || (type > ICMP_MAXTYPE))
+ return -1;
+
+ code = fin->fin_icode;
+#ifdef USE_INET6
+ if ((code < 0) || (code > sizeof(icmptoicmp6unreach)/sizeof(int)))
+ return -1;
+#endif
+
+#ifndef IPFILTER_CKSUM
+ if (fr_checkl4sum(fin) == -1)
+ return -1;
+#endif
+#ifdef MGETHDR
+ MGETHDR(m, M_DONTWAIT, MT_HEADER);
+#else
+ MGET(m, M_DONTWAIT, MT_HEADER);
+#endif
+ if (m == NULL)
+ return -1;
+ avail = MHLEN;
+
+ xtra = 0;
+ hlen = 0;
+ ohlen = 0;
+ ifp = fin->fin_ifp;
+ if (fin->fin_v == 4) {
+ if ((fin->fin_p == IPPROTO_ICMP) &&
+ !(fin->fin_flx & FI_SHORT))
+ switch (ntohs(fin->fin_data[0]) >> 8)
+ {
+ case ICMP_ECHO :
+ case ICMP_TSTAMP :
+ case ICMP_IREQ :
+ case ICMP_MASKREQ :
+ break;
+ default :
+ FREE_MB_T(m);
+ return 0;
+ }
+
+ if (dst == 0) {
+ if (fr_ifpaddr(4, FRI_NORMAL, ifp,
+ &dst4, NULL) == -1) {
+ FREE_MB_T(m);
+ return -1;
+ }
+ } else
+ dst4.s_addr = fin->fin_daddr;
+
+ hlen = sizeof(ip_t);
+ ohlen = fin->fin_hlen;
+ if (fin->fin_hlen < fin->fin_plen)
+ xtra = MIN(fin->fin_dlen, 8);
+ else
+ xtra = 0;
+ }
+
+#ifdef USE_INET6
+ else if (fin->fin_v == 6) {
+ hlen = sizeof(ip6_t);
+ ohlen = sizeof(ip6_t);
+ type = icmptoicmp6types[type];
+ if (type == ICMP6_DST_UNREACH)
+ code = icmptoicmp6unreach[code];
+
+ if (hlen + sizeof(*icmp) + max_linkhdr +
+ fin->fin_plen > avail) {
+ MCLGET(m, M_DONTWAIT);
+ if ((m->m_flags & M_EXT) == 0) {
+ FREE_MB_T(m);
+ return -1;
+ }
+ avail = MCLBYTES;
+ }
+ xtra = MIN(fin->fin_plen,
+ avail - hlen - sizeof(*icmp) - max_linkhdr);
+ if (dst == 0) {
+ if (fr_ifpaddr(6, FRI_NORMAL, ifp,
+ (struct in_addr *)&dst6, NULL) == -1) {
+ FREE_MB_T(m);
+ return -1;
+ }
+ } else
+ dst6 = fin->fin_dst6;
+ }
+#endif
+ else {
+ FREE_MB_T(m);
+ return -1;
+ }
+
+ iclen = hlen + sizeof(*icmp);
+ avail -= (max_linkhdr + iclen);
+ if (avail < 0) {
+ FREE_MB_T(m);
+ return -1;
+ }
+ if (xtra > avail)
+ xtra = avail;
+ iclen += xtra;
+ m->m_data += max_linkhdr;
+ m->m_pkthdr.rcvif = (struct ifnet *)0;
+ m->m_pkthdr.len = iclen;
+ m->m_len = iclen;
+ ip = mtod(m, ip_t *);
+ icmp = (struct icmp *)((char *)ip + hlen);
+ ip2 = (ip_t *)&icmp->icmp_ip;
+
+ icmp->icmp_type = type;
+ icmp->icmp_code = fin->fin_icode;
+ icmp->icmp_cksum = 0;
+#ifdef icmp_nextmtu
+ if (type == ICMP_UNREACH &&
+ fin->fin_icode == ICMP_UNREACH_NEEDFRAG && ifp)
+ icmp->icmp_nextmtu = htons(((struct ifnet *)ifp)->if_mtu);
+#endif
+
+ bcopy((char *)fin->fin_ip, (char *)ip2, ohlen);
+
+#ifdef USE_INET6
+ ip6 = (ip6_t *)ip;
+ if (fin->fin_v == 6) {
+ ip6->ip6_flow = ((ip6_t *)fin->fin_ip)->ip6_flow;
+ ip6->ip6_plen = htons(iclen - hlen);
+ ip6->ip6_nxt = IPPROTO_ICMPV6;
+ ip6->ip6_hlim = 0;
+ ip6->ip6_src = dst6;
+ ip6->ip6_dst = fin->fin_src6;
+ if (xtra > 0)
+ bcopy((char *)fin->fin_ip + ohlen,
+ (char *)&icmp->icmp_ip + ohlen, xtra);
+ icmp->icmp_cksum = in6_cksum(m, IPPROTO_ICMPV6,
+ sizeof(*ip6), iclen - hlen);
+ } else
+#endif
+ {
+ ip2->ip_len = htons(ip2->ip_len);
+ ip2->ip_off = htons(ip2->ip_off);
+ ip->ip_p = IPPROTO_ICMP;
+ ip->ip_src.s_addr = dst4.s_addr;
+ ip->ip_dst.s_addr = fin->fin_saddr;
+
+ if (xtra > 0)
+ bcopy((char *)fin->fin_ip + ohlen,
+ (char *)&icmp->icmp_ip + ohlen, xtra);
+ icmp->icmp_cksum = ipf_cksum((u_short *)icmp,
+ sizeof(*icmp) + 8);
+ ip->ip_len = iclen;
+ ip->ip_p = IPPROTO_ICMP;
+ }
+ err = fr_send_ip(fin, m, &m);
+ return err;
+}
+
+
+#if !defined(IPFILTER_LKM) && (__FreeBSD_version < 300000)
+# if (BSD < 199306)
+int iplinit __P((void));
+
+int
+# else
+void iplinit __P((void));
+
+void
+# endif
+iplinit()
+{
+ if (iplattach() != 0)
+ printf("IP Filter failed to attach\n");
+ ip_init();
+}
+#endif /* __FreeBSD_version < 300000 */
+
+
+int fr_fastroute(m0, mpp, fin, fdp)
+mb_t *m0, **mpp;
+fr_info_t *fin;
+frdest_t *fdp;
+{
+ register struct ip *ip, *mhip;
+ register struct mbuf *m = m0;
+ register struct route *ro;
+ int len, off, error = 0, hlen, code;
+ struct ifnet *ifp, *sifp;
+ struct sockaddr_in *dst;
+ struct route iproute;
+ u_short ip_off;
+ frentry_t *fr;
+
+#ifdef M_WRITABLE
+ /*
+ * HOT FIX/KLUDGE:
+ *
+ * If the mbuf we're about to send is not writable (because of
+ * a cluster reference, for example) we'll need to make a copy
+ * of it since this routine modifies the contents.
+ *
+ * If you have non-crappy network hardware that can transmit data
+ * from the mbuf, rather than making a copy, this is gonna be a
+ * problem.
+ */
+ if (M_WRITABLE(m) == 0) {
+ if ((m0 = m_dup(m, M_DONTWAIT)) != 0) {
+ FREE_MB_T(m);
+ m = m0;
+ *mpp = m;
+ } else {
+ error = ENOBUFS;
+ FREE_MB_T(m);
+ *mpp = NULL;
+ fr_frouteok[1]++;
+ }
+ }
+#endif
+
+#ifdef USE_INET6
+ if (fin->fin_v == 6) {
+ /*
+ * currently "to <if>" and "to <if>:ip#" are not supported
+ * for IPv6
+ */
+#if (__FreeBSD_version >= 490000)
+ return ip6_output(m0, NULL, NULL, 0, NULL, NULL, NULL);
+#else
+ return ip6_output(m0, NULL, NULL, 0, NULL, NULL);
+#endif
+ }
+#endif
+
+ hlen = fin->fin_hlen;
+ 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 = ip->ip_dst;
+
+ fr = fin->fin_fr;
+ if (fdp != NULL)
+ ifp = fdp->fd_ifp;
+ else
+ ifp = fin->fin_ifp;
+
+ if ((ifp == NULL) && (!fr || !(fr->fr_flags & FR_FASTROUTE))) {
+ error = -2;
+ goto bad;
+ }
+
+ /*
+ * In case we're here due to "to <if>" being used with "keep state",
+ * check that we're going in the correct direction.
+ */
+ if ((fr != NULL) && (fin->fin_rev != 0)) {
+ if ((ifp != NULL) && (fdp == &fr->fr_tif))
+ return -1;
+ }
+ if (fdp != NULL) {
+ if (fdp->fd_ip.s_addr != 0)
+ dst->sin_addr = fdp->fd_ip;
+ }
+
+ dst->sin_len = sizeof(*dst);
+ rtalloc(ro);
+
+ if ((ifp == NULL) && (ro->ro_rt != NULL))
+ ifp = ro->ro_rt->rt_ifp;
+
+ if ((ro->ro_rt == NULL) || (ifp == NULL)) {
+ 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;
+ if (ro->ro_rt)
+ 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 and counted.
+ */
+ if (fin->fin_out == 0) {
+ sifp = fin->fin_ifp;
+ fin->fin_ifp = ifp;
+ fin->fin_out = 1;
+ (void) fr_acctpkt(fin, NULL);
+ fin->fin_fr = NULL;
+ if (!fr || !(fr->fr_flags & FR_RETMASK)) {
+ u_32_t pass;
+
+ (void) fr_checkstate(fin, &pass);
+ }
+
+ switch (fr_checknatout(fin, NULL))
+ {
+ case 0 :
+ break;
+ case 1 :
+ ip->ip_sum = 0;
+ break;
+ case -1 :
+ error = -1;
+ goto done;
+ break;
+ }
+
+ fin->fin_ifp = sifp;
+ fin->fin_out = 0;
+ } else
+ ip->ip_sum = 0;
+ /*
+ * If small enough for interface, can just send directly.
+ */
+ if (ip->ip_len <= ifp->if_mtu) {
+ ip->ip_len = htons(ip->ip_len);
+ ip->ip_off = htons(ip->ip_off);
+
+ if (!ip->ip_sum)
+ ip->ip_sum = in_cksum(m, hlen);
+ error = (*ifp->if_output)(ifp, m, (struct sockaddr *)dst,
+ ro->ro_rt);
+ goto done;
+ }
+ /*
+ * Too large for interface; fragment if possible.
+ * Must be able to put at least 8 bytes per fragment.
+ */
+ ip_off = ntohs(ip->ip_off);
+ if (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) {
+#ifdef MGETHDR
+ MGETHDR(m, M_DONTWAIT, MT_HEADER);
+#else
+ MGET(m, M_DONTWAIT, MT_HEADER);
+#endif
+ if (m == 0) {
+ m = m0;
+ error = ENOBUFS;
+ goto bad;
+ }
+ m->m_data += max_linkhdr;
+ 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);
+ IP_HL_A(mhip, mhlen >> 2);
+ }
+ m->m_len = mhlen;
+ mhip->ip_off = ((off - hlen) >> 3) + ip_off;
+ 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;
+ }
+ m->m_pkthdr.len = mhlen + len;
+ m->m_pkthdr.rcvif = NULL;
+ mhip->ip_off = htons((u_short)mhip->ip_off);
+ 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_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)
+ error = (*ifp->if_output)(ifp, m,
+ (struct sockaddr *)dst, ro->ro_rt);
+ else
+ FREE_MB_T(m);
+ }
+ }
+done:
+ if (!error)
+ fr_frouteok[0]++;
+ else
+ fr_frouteok[1]++;
+
+ if (ro->ro_rt) {
+ RTFREE(ro->ro_rt);
+ }
+ *mpp = NULL;
+ return 0;
+bad:
+ if (error == EMSGSIZE) {
+ sifp = fin->fin_ifp;
+ code = fin->fin_icode;
+ fin->fin_icode = ICMP_UNREACH_NEEDFRAG;
+ fin->fin_ifp = ifp;
+ (void) fr_send_icmp_err(ICMP_UNREACH, fin, 1);
+ fin->fin_ifp = sifp;
+ fin->fin_icode = code;
+ }
+ FREE_MB_T(m);
+ goto done;
+}
+
+
+int fr_verifysrc(fin)
+fr_info_t *fin;
+{
+ struct sockaddr_in *dst;
+ struct route iproute;
+
+ bzero((char *)&iproute, sizeof(iproute));
+ dst = (struct sockaddr_in *)&iproute.ro_dst;
+ dst->sin_len = sizeof(*dst);
+ dst->sin_family = AF_INET;
+ dst->sin_addr = fin->fin_src;
+ rtalloc(&iproute);
+ if (iproute.ro_rt == NULL)
+ return 0;
+ return (fin->fin_ifp == iproute.ro_rt->rt_ifp);
+}
+
+
+/*
+ * return the first IP Address associated with an interface
+ */
+int fr_ifpaddr(v, atype, ifptr, inp, inpmask)
+int v, atype;
+void *ifptr;
+struct in_addr *inp, *inpmask;
+{
+#ifdef USE_INET6
+ struct in6_addr *inp6 = NULL;
+#endif
+ struct sockaddr *sock, *mask;
+ struct sockaddr_in *sin;
+ struct ifaddr *ifa;
+ struct ifnet *ifp;
+
+ if ((ifptr == NULL) || (ifptr == (void *)-1))
+ return -1;
+
+ sin = NULL;
+ ifp = ifptr;
+
+ if (v == 4)
+ inp->s_addr = 0;
+#ifdef USE_INET6
+ else if (v == 6)
+ bzero((char *)inp, sizeof(struct in6_addr));
+#endif
+#if (__FreeBSD_version >= 300000)
+ ifa = TAILQ_FIRST(&ifp->if_addrhead);
+#else
+ ifa = ifp->if_addrlist;
+#endif /* __FreeBSD_version >= 300000 */
+
+ sock = ifa->ifa_addr;
+ while (sock != NULL && ifa != NULL) {
+ sin = (struct sockaddr_in *)sock;
+ if ((v == 4) && (sin->sin_family == AF_INET))
+ break;
+#ifdef USE_INET6
+ if ((v == 6) && (sin->sin_family == AF_INET6)) {
+ inp6 = &((struct sockaddr_in6 *)sin)->sin6_addr;
+ if (!IN6_IS_ADDR_LINKLOCAL(inp6) &&
+ !IN6_IS_ADDR_LOOPBACK(inp6))
+ break;
+ }
+#endif
+#if (__FreeBSD_version >= 300000)
+ ifa = TAILQ_NEXT(ifa, ifa_link);
+#else
+ ifa = ifa->ifa_next;
+#endif /* __FreeBSD_version >= 300000 */
+ if (ifa != NULL)
+ sock = ifa->ifa_addr;
+ }
+
+ if (ifa == NULL || sin == NULL)
+ return -1;
+
+ mask = ifa->ifa_netmask;
+ if (atype == FRI_BROADCAST)
+ sock = ifa->ifa_broadaddr;
+ else if (atype == FRI_PEERADDR)
+ sock = ifa->ifa_dstaddr;
+
+#ifdef USE_INET6
+ if (v == 6) {
+ return fr_ifpfillv6addr(atype, (struct sockaddr_in6 *)sock,
+ (struct sockaddr_in6 *)mask,
+ inp, inpmask);
+ }
+#endif
+ return fr_ifpfillv4addr(atype, (struct sockaddr_in *)sock,
+ (struct sockaddr_in *)mask, inp, inpmask);
+}
+
+
+u_32_t fr_newisn(fin)
+fr_info_t *fin;
+{
+ u_32_t newiss;
+#if (__FreeBSD_version >= 400000)
+ newiss = arc4random();
+#else
+ static iss_seq_off = 0;
+ u_char hash[16];
+ MD5_CTX ctx;
+
+ /*
+ * Compute the base value of the ISS. It is a hash
+ * of (saddr, sport, daddr, dport, secret).
+ */
+ MD5Init(&ctx);
+
+ MD5Update(&ctx, (u_char *) &fin->fin_fi.fi_src,
+ sizeof(fin->fin_fi.fi_src));
+ MD5Update(&ctx, (u_char *) &fin->fin_fi.fi_dst,
+ sizeof(fin->fin_fi.fi_dst));
+ MD5Update(&ctx, (u_char *) &fin->fin_dat, sizeof(fin->fin_dat));
+
+ MD5Update(&ctx, ipf_iss_secret, sizeof(ipf_iss_secret));
+
+ MD5Final(hash, &ctx);
+
+ memcpy(&newiss, hash, sizeof(newiss));
+
+ /*
+ * Now increment our "timer", and add it in to
+ * the computed value.
+ *
+ * XXX Use `addin'?
+ * XXX TCP_ISSINCR too large to use?
+ */
+ iss_seq_off += 0x00010000;
+ newiss += iss_seq_off;
+#endif
+ return newiss;
+}
+
+
+/* ------------------------------------------------------------------------ */
+/* Function: fr_nextipid */
+/* Returns: int - 0 == success, -1 == error (packet should be droppped) */
+/* Parameters: fin(I) - pointer to packet information */
+/* */
+/* Returns the next IPv4 ID to use for this packet. */
+/* ------------------------------------------------------------------------ */
+u_short fr_nextipid(fin)
+fr_info_t *fin;
+{
+#ifndef RANDOM_IP_ID
+ static u_short ipid = 0;
+ u_short id;
+
+ MUTEX_ENTER(&ipf_rw);
+ id = ipid++;
+ MUTEX_EXIT(&ipf_rw);
+#else
+ u_short id;
+
+ id = ip_randomid();
+#endif
+
+ return id;
+}
+
+
+INLINE void fr_checkv4sum(fin)
+fr_info_t *fin;
+{
+#ifdef CSUM_DATA_VALID
+ int manual = 0;
+ u_short sum;
+ ip_t *ip;
+ mb_t *m;
+
+ if ((fin->fin_flx & FI_NOCKSUM) != 0)
+ return;
+
+ m = fin->fin_m;
+ if (m == NULL) {
+ manual = 1;
+ goto skipauto;
+ }
+ ip = fin->fin_ip;
+
+ if (m->m_pkthdr.csum_flags & CSUM_DATA_VALID) {
+ if (m->m_pkthdr.csum_flags & CSUM_PSEUDO_HDR)
+ sum = m->m_pkthdr.csum_data;
+ else
+ sum = in_pseudo(ip->ip_src.s_addr, ip->ip_dst.s_addr,
+ htonl(m->m_pkthdr.csum_data +
+ fin->fin_ip->ip_len + fin->fin_p));
+ sum ^= 0xffff;
+ if (sum != 0)
+ fin->fin_flx |= FI_BAD;
+ } else
+ manual = 1;
+skipauto:
+# ifdef IPFILTER_CKSUM
+ if (manual != 0)
+ if (fr_checkl4sum(fin) == -1)
+ fin->fin_flx |= FI_BAD;
+# else
+ ;
+# endif
+#else
+# ifdef IPFILTER_CKSUM
+ if (fr_checkl4sum(fin) == -1)
+ fin->fin_flx |= FI_BAD;
+# endif
+#endif
+}
+
+
+#ifdef USE_INET6
+INLINE void fr_checkv6sum(fin)
+fr_info_t *fin;
+{
+# ifdef IPFILTER_CKSUM
+ if (fr_checkl4sum(fin) == -1)
+ fin->fin_flx |= FI_BAD;
+# endif
+}
+#endif /* USE_INET6 */
+
+
+size_t mbufchainlen(m0)
+struct mbuf *m0;
+{
+ size_t len;
+
+ if ((m0->m_flags & M_PKTHDR) != 0) {
+ len = m0->m_pkthdr.len;
+ } else {
+ struct mbuf *m;
+
+ for (m = m0, len = 0; m != NULL; m = m->m_next)
+ len += m->m_len;
+ }
+ return len;
+}
+
+
+/* ------------------------------------------------------------------------ */
+/* Function: fr_pullup */
+/* Returns: NULL == pullup failed, else pointer to protocol header */
+/* Parameters: m(I) - pointer to buffer where data packet starts */
+/* fin(I) - pointer to packet information */
+/* len(I) - number of bytes to pullup */
+/* */
+/* Attempt to move at least len bytes (from the start of the buffer) into a */
+/* single buffer for ease of access. Operating system native functions are */
+/* used to manage buffers - if necessary. If the entire packet ends up in */
+/* a single buffer, set the FI_COALESCE flag even though fr_coalesce() has */
+/* not been called. Both fin_ip and fin_dp are updated before exiting _IF_ */
+/* and ONLY if the pullup succeeds. */
+/* */
+/* We assume that 'min' is a pointer to a buffer that is part of the chain */
+/* of buffers that starts at *fin->fin_mp. */
+/* ------------------------------------------------------------------------ */
+void *fr_pullup(min, fin, len)
+mb_t *min;
+fr_info_t *fin;
+int len;
+{
+ int out = fin->fin_out, dpoff, ipoff;
+ mb_t *m = min;
+ char *ip;
+
+ if (m == NULL)
+ return NULL;
+
+ ip = (char *)fin->fin_ip;
+ if ((fin->fin_flx & FI_COALESCE) != 0)
+ return ip;
+
+ ipoff = fin->fin_ipoff;
+ if (fin->fin_dp != NULL)
+ dpoff = (char *)fin->fin_dp - (char *)ip;
+ else
+ dpoff = 0;
+
+ if (M_LEN(m) < len) {
+#ifdef MHLEN
+ /*
+ * Assume that M_PKTHDR is set and just work with what is left
+ * rather than check..
+ * Should not make any real difference, anyway.
+ */
+ if (len > MHLEN)
+#else
+ if (len > MLEN)
+#endif
+ {
+#ifdef HAVE_M_PULLDOWN
+ if (m_pulldown(m, 0, len, NULL) == NULL)
+ m = NULL;
+#else
+ FREE_MB_T(*fin->fin_mp);
+ m = NULL;
+#endif
+ } else
+ {
+ m = m_pullup(m, len);
+ }
+ *fin->fin_mp = m;
+ fin->fin_m = m;
+ if (m == NULL) {
+ ATOMIC_INCL(frstats[out].fr_pull[1]);
+ return NULL;
+ }
+ ip = MTOD(m, char *) + ipoff;
+ }
+
+ ATOMIC_INCL(frstats[out].fr_pull[0]);
+ fin->fin_ip = (ip_t *)ip;
+ if (fin->fin_dp != NULL)
+ fin->fin_dp = (char *)fin->fin_ip + dpoff;
+
+ if (len == fin->fin_plen)
+ fin->fin_flx |= FI_COALESCE;
+ return ip;
+}
diff --git a/contrib/ipfilter/ip_htable.c b/contrib/ipfilter/ip_htable.c
new file mode 100644
index 0000000..50aa926
--- /dev/null
+++ b/contrib/ipfilter/ip_htable.c
@@ -0,0 +1,455 @@
+/* $NetBSD$ */
+
+/*
+ * Copyright (C) 1993-2001, 2003 by Darren Reed.
+ *
+ * See the IPFILTER.LICENCE file for details on licencing.
+ */
+#if defined(KERNEL) || defined(_KERNEL)
+# undef KERNEL
+# undef _KERNEL
+# define KERNEL 1
+# define _KERNEL 1
+#endif
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/errno.h>
+#include <sys/time.h>
+#include <sys/file.h>
+#if !defined(_KERNEL)
+# include <stdlib.h>
+# include <string.h>
+# define _KERNEL
+# ifdef __OpenBSD__
+struct file;
+# endif
+# include <sys/uio.h>
+# undef _KERNEL
+#endif
+#include <sys/socket.h>
+#if defined(__FreeBSD_version) && (__FreeBSD_version >= 300000)
+# include <sys/malloc.h>
+#endif
+#if defined(__FreeBSD__)
+# include <sys/cdefs.h>
+# include <sys/proc.h>
+#endif
+#if !defined(__svr4__) && !defined(__SVR4) && !defined(__hpux) && \
+ !defined(linux)
+# include <sys/mbuf.h>
+#endif
+#if defined(_KERNEL)
+# include <sys/systm.h>
+#else
+# include <stdio.h>
+#endif
+#include <netinet/in.h>
+#include <net/if.h>
+
+#include "netinet/ip_compat.h"
+#include "netinet/ip_fil.h"
+#include "netinet/ip_lookup.h"
+#include "netinet/ip_htable.h"
+/* END OF INCLUDES */
+
+#if !defined(lint)
+static const char rcsid[] = "@(#)Id: ip_htable.c,v 2.34.2.2 2004/10/17 15:49:15 darrenr Exp";
+#endif
+
+#ifdef IPFILTER_LOOKUP
+static iphtent_t *fr_iphmfind __P((iphtable_t *, struct in_addr *));
+static u_long ipht_nomem[IPL_LOGSIZE] = { 0, 0, 0, 0, 0, 0, 0, 0 };
+static u_long ipf_nhtables[IPL_LOGSIZE] = { 0, 0, 0, 0, 0, 0, 0, 0 };
+static u_long ipf_nhtnodes[IPL_LOGSIZE] = { 0, 0, 0, 0, 0, 0, 0, 0 };
+
+iphtable_t *ipf_htables[IPL_LOGSIZE] = { NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL };
+
+
+void fr_htable_unload()
+{
+ iplookupflush_t fop;
+
+ fop.iplf_unit = IPL_LOGALL;
+ (void)fr_flushhtable(&fop);
+}
+
+
+int fr_gethtablestat(op)
+iplookupop_t *op;
+{
+ iphtstat_t stats;
+
+ if (op->iplo_size != sizeof(stats))
+ return EINVAL;
+
+ stats.iphs_tables = ipf_htables[op->iplo_unit];
+ stats.iphs_numtables = ipf_nhtables[op->iplo_unit];
+ stats.iphs_numnodes = ipf_nhtnodes[op->iplo_unit];
+ stats.iphs_nomem = ipht_nomem[op->iplo_unit];
+
+ return COPYOUT(&stats, op->iplo_struct, sizeof(stats));
+
+}
+
+
+/*
+ * Create a new hash table using the template passed.
+ */
+int fr_newhtable(op)
+iplookupop_t *op;
+{
+ iphtable_t *iph, *oiph;
+ char name[FR_GROUPLEN];
+ int err, i, unit;
+
+ KMALLOC(iph, iphtable_t *);
+ if (iph == NULL)
+ return ENOMEM;
+
+ err = COPYIN(op->iplo_struct, iph, sizeof(*iph));
+ if (err != 0) {
+ KFREE(iph);
+ return EFAULT;
+ }
+
+ unit = op->iplo_unit;
+ if (iph->iph_unit != unit) {
+ KFREE(iph);
+ return EINVAL;
+ }
+
+ if ((op->iplo_arg & IPHASH_ANON) == 0) {
+ if (fr_findhtable(op->iplo_unit, op->iplo_name) != NULL) {
+ KFREE(iph);
+ return EEXIST;
+ }
+ } else {
+ i = IPHASH_ANON;
+ do {
+ i++;
+#if defined(SNPRINTF) && defined(_KERNEL)
+ SNPRINTF(name, sizeof(name), "%u", i);
+#else
+ (void)sprintf(name, "%u", i);
+#endif
+ for (oiph = ipf_htables[unit]; oiph != NULL;
+ oiph = oiph->iph_next)
+ if (strncmp(oiph->iph_name, name,
+ sizeof(oiph->iph_name)) == 0)
+ break;
+ } while (oiph != NULL);
+ (void)strncpy(iph->iph_name, name, sizeof(iph->iph_name));
+ err = COPYOUT(iph, op->iplo_struct, sizeof(*iph));
+ if (err != 0) {
+ KFREE(iph);
+ return EFAULT;
+ }
+ iph->iph_type |= IPHASH_ANON;
+ }
+
+ KMALLOCS(iph->iph_table, iphtent_t **,
+ iph->iph_size * sizeof(*iph->iph_table));
+ if (iph->iph_table == NULL) {
+ KFREE(iph);
+ ipht_nomem[unit]++;
+ return ENOMEM;
+ }
+
+ bzero((char *)iph->iph_table, iph->iph_size * sizeof(*iph->iph_table));
+ iph->iph_masks = 0;
+
+ iph->iph_next = ipf_htables[unit];
+ iph->iph_pnext = &ipf_htables[unit];
+ if (ipf_htables[unit] != NULL)
+ ipf_htables[unit]->iph_pnext = &iph->iph_next;
+ ipf_htables[unit] = iph;
+
+ ipf_nhtables[unit]++;
+
+ return 0;
+}
+
+
+/*
+ */
+int fr_removehtable(op)
+iplookupop_t *op;
+{
+ iphtable_t *iph;
+
+
+ iph = fr_findhtable(op->iplo_unit, op->iplo_name);
+ if (iph == NULL)
+ return ESRCH;
+
+ if (iph->iph_unit != op->iplo_unit) {
+ return EINVAL;
+ }
+
+ if (iph->iph_ref != 0) {
+ return EBUSY;
+ }
+
+ fr_delhtable(iph);
+
+ return 0;
+}
+
+
+void fr_delhtable(iph)
+iphtable_t *iph;
+{
+ iphtent_t *ipe;
+ int i;
+
+ for (i = 0; i < iph->iph_size; i++)
+ while ((ipe = iph->iph_table[i]) != NULL)
+ if (fr_delhtent(iph, ipe) != 0)
+ return;
+
+ *iph->iph_pnext = iph->iph_next;
+ if (iph->iph_next != NULL)
+ iph->iph_next->iph_pnext = iph->iph_pnext;
+
+ ipf_nhtables[iph->iph_unit]--;
+
+ if (iph->iph_ref == 0) {
+ KFREES(iph->iph_table, iph->iph_size * sizeof(*iph->iph_table));
+ KFREE(iph);
+ }
+}
+
+
+void fr_derefhtable(iph)
+iphtable_t *iph;
+{
+ iph->iph_ref--;
+ if (iph->iph_ref == 0)
+ fr_delhtable(iph);
+}
+
+
+iphtable_t *fr_findhtable(unit, name)
+int unit;
+char *name;
+{
+ iphtable_t *iph;
+
+ for (iph = ipf_htables[unit]; iph != NULL; iph = iph->iph_next)
+ if (strncmp(iph->iph_name, name, sizeof(iph->iph_name)) == 0)
+ break;
+ return iph;
+}
+
+
+size_t fr_flushhtable(op)
+iplookupflush_t *op;
+{
+ iphtable_t *iph;
+ size_t freed;
+ int i;
+
+ freed = 0;
+
+ for (i = 0; i <= IPL_LOGMAX; i++) {
+ if (op->iplf_unit == i || op->iplf_unit == IPL_LOGALL) {
+ while ((iph = ipf_htables[i]) != NULL) {
+ fr_delhtable(iph);
+ freed++;
+ }
+ }
+ }
+
+ return freed;
+}
+
+
+/*
+ * Add an entry to a hash table.
+ */
+int fr_addhtent(iph, ipeo)
+iphtable_t *iph;
+iphtent_t *ipeo;
+{
+ iphtent_t *ipe;
+ u_int hv;
+ int bits;
+
+ KMALLOC(ipe, iphtent_t *);
+ if (ipe == NULL)
+ return -1;
+
+ bcopy((char *)ipeo, (char *)ipe, sizeof(*ipe));
+ ipe->ipe_addr.in4_addr &= ipe->ipe_mask.in4_addr;
+ ipe->ipe_addr.in4_addr = ntohl(ipe->ipe_addr.in4_addr);
+ bits = count4bits(ipe->ipe_mask.in4_addr);
+ ipe->ipe_mask.in4_addr = ntohl(ipe->ipe_mask.in4_addr);
+
+ hv = IPE_HASH_FN(ipe->ipe_addr.in4_addr, ipe->ipe_mask.in4_addr,
+ iph->iph_size);
+ ipe->ipe_ref = 0;
+ ipe->ipe_next = iph->iph_table[hv];
+ ipe->ipe_pnext = iph->iph_table + hv;
+
+ if (iph->iph_table[hv] != NULL)
+ iph->iph_table[hv]->ipe_pnext = &ipe->ipe_next;
+ iph->iph_table[hv] = ipe;
+ if ((bits >= 0) && (bits != 32))
+ iph->iph_masks |= 1 << bits;
+
+ switch (iph->iph_type & ~IPHASH_ANON)
+ {
+ case IPHASH_GROUPMAP :
+ ipe->ipe_ptr = fr_addgroup(ipe->ipe_group, NULL,
+ iph->iph_flags, IPL_LOGIPF,
+ fr_active);
+ break;
+
+ default :
+ ipe->ipe_ptr = NULL;
+ ipe->ipe_value = 0;
+ break;
+ }
+
+ ipf_nhtnodes[iph->iph_unit]++;
+
+ return 0;
+}
+
+
+/*
+ * Delete an entry from a hash table.
+ */
+int fr_delhtent(iph, ipe)
+iphtable_t *iph;
+iphtent_t *ipe;
+{
+
+ if (ipe->ipe_ref != 0)
+ return EBUSY;
+
+
+ *ipe->ipe_pnext = ipe->ipe_next;
+ if (ipe->ipe_next != NULL)
+ ipe->ipe_next->ipe_pnext = ipe->ipe_pnext;
+
+ switch (iph->iph_type & ~IPHASH_ANON)
+ {
+ case IPHASH_GROUPMAP :
+ if (ipe->ipe_group != NULL)
+ fr_delgroup(ipe->ipe_group, IPL_LOGIPF, fr_active);
+ break;
+
+ default :
+ ipe->ipe_ptr = NULL;
+ ipe->ipe_value = 0;
+ break;
+ }
+
+ KFREE(ipe);
+
+ ipf_nhtnodes[iph->iph_unit]--;
+
+ return 0;
+}
+
+
+void *fr_iphmfindgroup(tptr, aptr)
+void *tptr, *aptr;
+{
+ struct in_addr *addr;
+ iphtable_t *iph;
+ iphtent_t *ipe;
+ void *rval;
+
+ READ_ENTER(&ip_poolrw);
+ iph = tptr;
+ addr = aptr;
+
+ ipe = fr_iphmfind(iph, addr);
+ if (ipe != NULL)
+ rval = ipe->ipe_ptr;
+ else
+ rval = NULL;
+ RWLOCK_EXIT(&ip_poolrw);
+ return rval;
+}
+
+
+/* ------------------------------------------------------------------------ */
+/* Function: fr_iphmfindip */
+/* Returns: int - 0 == +ve match, -1 == error, 1 == -ve/no match */
+/* Parameters: tptr(I) - pointer to the pool to search */
+/* version(I) - IP protocol version (4 or 6) */
+/* aptr(I) - pointer to address information */
+/* */
+/* Search the hash table for a given address and return a search result. */
+/* ------------------------------------------------------------------------ */
+int fr_iphmfindip(tptr, version, aptr)
+void *tptr, *aptr;
+int version;
+{
+ struct in_addr *addr;
+ iphtable_t *iph;
+ iphtent_t *ipe;
+ int rval;
+
+ if (version != 4)
+ return -1;
+
+ if (tptr == NULL || aptr == NULL)
+ return -1;
+
+ iph = tptr;
+ addr = aptr;
+
+ READ_ENTER(&ip_poolrw);
+ ipe = fr_iphmfind(iph, addr);
+ if (ipe != NULL)
+ rval = 0;
+ else
+ rval = 1;
+ RWLOCK_EXIT(&ip_poolrw);
+ return rval;
+}
+
+
+/* Locks: ip_poolrw */
+static iphtent_t *fr_iphmfind(iph, addr)
+iphtable_t *iph;
+struct in_addr *addr;
+{
+ u_32_t hmsk, msk, ips;
+ iphtent_t *ipe;
+ u_int hv;
+
+ hmsk = iph->iph_masks;
+ msk = 0xffffffff;
+maskloop:
+ ips = ntohl(addr->s_addr) & msk;
+ hv = IPE_HASH_FN(ips, msk, iph->iph_size);
+ for (ipe = iph->iph_table[hv]; (ipe != NULL); ipe = ipe->ipe_next) {
+ if (ipe->ipe_mask.in4_addr != msk ||
+ ipe->ipe_addr.in4_addr != ips) {
+ continue;
+ }
+ break;
+ }
+
+ if ((ipe == NULL) && (hmsk != 0)) {
+ while (hmsk != 0) {
+ msk <<= 1;
+ if (hmsk & 0x80000000)
+ break;
+ hmsk <<= 1;
+ }
+ if (hmsk != 0) {
+ hmsk <<= 1;
+ goto maskloop;
+ }
+ }
+ return ipe;
+}
+
+#endif /* IPFILTER_LOOKUP */
diff --git a/contrib/ipfilter/ip_htable.h b/contrib/ipfilter/ip_htable.h
new file mode 100644
index 0000000..e138459
--- /dev/null
+++ b/contrib/ipfilter/ip_htable.h
@@ -0,0 +1,71 @@
+/* $NetBSD$ */
+
+#ifndef __IP_HTABLE_H__
+#define __IP_HTABLE_H__
+
+#include "netinet/ip_lookup.h"
+
+typedef struct iphtent_s {
+ struct iphtent_s *ipe_next, **ipe_pnext;
+ void *ipe_ptr;
+ i6addr_t ipe_addr;
+ i6addr_t ipe_mask;
+ int ipe_ref;
+ union {
+ char ipeu_char[16];
+ u_long ipeu_long;
+ u_int ipeu_int;
+ }ipe_un;
+} iphtent_t;
+
+#define ipe_value ipe_un.ipeu_int
+#define ipe_group ipe_un.ipeu_char
+
+#define IPE_HASH_FN(a, m, s) (((a) * (m)) % (s))
+
+
+typedef struct iphtable_s {
+ ipfrwlock_t iph_rwlock;
+ struct iphtable_s *iph_next, **iph_pnext;
+ struct iphtent_s **iph_table;
+ size_t iph_size; /* size of hash table */
+ u_long iph_seed; /* hashing seed */
+ u_32_t iph_flags;
+ u_int iph_unit; /* IPL_LOG* */
+ u_int iph_ref;
+ u_int iph_type; /* lookup or group map - IPHASH_* */
+ u_int iph_masks; /* IPv4 netmasks in use */
+ char iph_name[FR_GROUPLEN]; /* hash table number */
+} iphtable_t;
+
+/* iph_type */
+#define IPHASH_LOOKUP 0
+#define IPHASH_GROUPMAP 1
+#define IPHASH_ANON 0x80000000
+
+
+typedef struct iphtstat_s {
+ iphtable_t *iphs_tables;
+ u_long iphs_numtables;
+ u_long iphs_numnodes;
+ u_long iphs_nomem;
+ u_long iphs_pad[16];
+} iphtstat_t;
+
+
+extern iphtable_t *ipf_htables[IPL_LOGSIZE];
+
+extern void fr_htable_unload __P((void));
+extern int fr_newhtable __P((iplookupop_t *));
+extern iphtable_t *fr_findhtable __P((int, char *));
+extern int fr_removehtable __P((iplookupop_t *));
+extern size_t fr_flushhtable __P((iplookupflush_t *));
+extern int fr_addhtent __P((iphtable_t *, iphtent_t *));
+extern int fr_delhtent __P((iphtable_t *, iphtent_t *));
+extern void fr_derefhtable __P((iphtable_t *));
+extern void fr_delhtable __P((iphtable_t *));
+extern void *fr_iphmfindgroup __P((void *, void *));
+extern int fr_iphmfindip __P((void *, int, void *));
+extern int fr_gethtablestat __P((iplookupop_t *));
+
+#endif /* __IP_HTABLE_H__ */
diff --git a/contrib/ipfilter/ip_irc_pxy.c b/contrib/ipfilter/ip_irc_pxy.c
new file mode 100644
index 0000000..45a120f
--- /dev/null
+++ b/contrib/ipfilter/ip_irc_pxy.c
@@ -0,0 +1,435 @@
+/* $NetBSD$ */
+
+/*
+ * Copyright (C) 2000-2003 Darren Reed
+ *
+ * See the IPFILTER.LICENCE file for details on licencing.
+ *
+ * Id: ip_irc_pxy.c,v 2.39.2.4 2005/02/04 10:22:55 darrenr Exp
+ */
+
+#define IPF_IRC_PROXY
+
+#define IPF_IRCBUFSZ 96 /* This *MUST* be >= 64! */
+
+
+int ippr_irc_init __P((void));
+void ippr_irc_fini __P((void));
+int ippr_irc_new __P((fr_info_t *, ap_session_t *, nat_t *));
+int ippr_irc_out __P((fr_info_t *, ap_session_t *, nat_t *));
+int ippr_irc_send __P((fr_info_t *, nat_t *));
+int ippr_irc_complete __P((ircinfo_t *, char *, size_t));
+u_short ipf_irc_atoi __P((char **));
+
+static frentry_t ircnatfr;
+
+int irc_proxy_init = 0;
+
+
+/*
+ * Initialize local structures.
+ */
+int ippr_irc_init()
+{
+ bzero((char *)&ircnatfr, sizeof(ircnatfr));
+ ircnatfr.fr_ref = 1;
+ ircnatfr.fr_flags = FR_INQUE|FR_PASS|FR_QUICK|FR_KEEPSTATE;
+ MUTEX_INIT(&ircnatfr.fr_lock, "IRC proxy rule lock");
+ irc_proxy_init = 1;
+
+ return 0;
+}
+
+
+void ippr_irc_fini()
+{
+ if (irc_proxy_init == 1) {
+ MUTEX_DESTROY(&ircnatfr.fr_lock);
+ irc_proxy_init = 0;
+ }
+}
+
+
+char *ippr_irc_dcctypes[] = {
+ "CHAT ", /* CHAT chat ipnumber portnumber */
+ "SEND ", /* SEND filename ipnumber portnumber */
+ "MOVE ",
+ "TSEND ",
+ "SCHAT ",
+ NULL,
+};
+
+
+/*
+ * :A PRIVMSG B :^ADCC CHAT chat 0 0^A\r\n
+ * PRIVMSG B ^ADCC CHAT chat 0 0^A\r\n
+ */
+
+
+int ippr_irc_complete(ircp, buf, len)
+ircinfo_t *ircp;
+char *buf;
+size_t len;
+{
+ register char *s, c;
+ register size_t i;
+ u_32_t l;
+ int j, k;
+
+ ircp->irc_ipnum = 0;
+ ircp->irc_port = 0;
+
+ if (len < 31)
+ return 0;
+ s = buf;
+ c = *s++;
+ i = len - 1;
+
+ if ((c != ':') && (c != 'P'))
+ return 0;
+
+ if (c == ':') {
+ /*
+ * Loosely check that the source is a nickname of some sort
+ */
+ s++;
+ c = *s;
+ ircp->irc_snick = s;
+ if (!ISALPHA(c))
+ return 0;
+ i--;
+ for (c = *s; !ISSPACE(c) && (i > 0); i--)
+ c = *s++;
+ if (i < 31)
+ return 0;
+ if (c != 'P')
+ return 0;
+ } else
+ ircp->irc_snick = NULL;
+
+ /*
+ * Check command string
+ */
+ if (strncmp(s, "PRIVMSG ", 8))
+ return 0;
+ i -= 8;
+ s += 8;
+ c = *s;
+ ircp->irc_dnick = s;
+
+ /*
+ * Loosely check that the destination is a nickname of some sort
+ */
+ if (!ISALPHA(c))
+ return 0;
+ for (; !ISSPACE(c) && (i > 0); i--)
+ c = *s++;
+ if (i < 20)
+ return 0;
+ s++,
+ i--;
+
+ /*
+ * Look for a ^A to start the DCC
+ */
+ c = *s;
+ if (c == ':') {
+ s++;
+ c = *s;
+ }
+
+ if (strncmp(s, "\001DCC ", 4))
+ return 0;
+
+ i -= 4;
+ s += 4;
+
+ /*
+ * Check for a recognised DCC command
+ */
+ for (j = 0, k = 0; ippr_irc_dcctypes[j]; j++) {
+ k = MIN(strlen(ippr_irc_dcctypes[j]), i);
+ if (!strncmp(ippr_irc_dcctypes[j], s, k))
+ break;
+ }
+ if (!ippr_irc_dcctypes[j])
+ return 0;
+
+ ircp->irc_type = s;
+ i -= k;
+ s += k;
+
+ if (i < 11)
+ return 0;
+
+ /*
+ * Check for the arg
+ */
+ c = *s;
+ if (ISSPACE(c))
+ return 0;
+ ircp->irc_arg = s;
+ for (; (c != ' ') && (c != '\001') && (i > 0); i--)
+ c = *s++;
+
+ if (c == '\001') /* In reality a ^A can quote another ^A...*/
+ return 0;
+
+ if (i < 5)
+ return 0;
+
+ s++;
+ i--;
+ c = *s;
+ if (!ISDIGIT(c))
+ return 0;
+ ircp->irc_addr = s;
+ /*
+ * Get the IP#
+ */
+ for (l = 0; ISDIGIT(c) && (i > 0); i--) {
+ l *= 10;
+ l += c - '0';
+ c = *s++;
+ }
+
+ if (i < 4)
+ return 0;
+
+ if (c != ' ')
+ return 0;
+
+ ircp->irc_ipnum = l;
+ s++;
+ i--;
+ c = *s;
+ if (!ISDIGIT(c))
+ return 0;
+ /*
+ * Get the port#
+ */
+ for (l = 0; ISDIGIT(c) && (i > 0); i--) {
+ l *= 10;
+ l += c - '0';
+ c = *s++;
+ }
+ if (i < 3)
+ return 0;
+ if (strncmp(s, "\001\r\n", 3))
+ return 0;
+ s += 3;
+ ircp->irc_len = s - buf;
+ ircp->irc_port = l;
+ return 1;
+}
+
+
+int ippr_irc_new(fin, aps, nat)
+fr_info_t *fin;
+ap_session_t *aps;
+nat_t *nat;
+{
+ ircinfo_t *irc;
+
+ KMALLOC(irc, ircinfo_t *);
+ if (irc == NULL)
+ return -1;
+
+ fin = fin; /* LINT */
+ nat = nat; /* LINT */
+
+ aps->aps_data = irc;
+ aps->aps_psiz = sizeof(ircinfo_t);
+
+ bzero((char *)irc, sizeof(*irc));
+ return 0;
+}
+
+
+int ippr_irc_send(fin, nat)
+fr_info_t *fin;
+nat_t *nat;
+{
+ char ctcpbuf[IPF_IRCBUFSZ], newbuf[IPF_IRCBUFSZ];
+ tcphdr_t *tcp, tcph, *tcp2 = &tcph;
+ int off, inc = 0, i, dlen;
+ size_t nlen = 0, olen;
+ struct in_addr swip;
+ u_short a5, sp;
+ ircinfo_t *irc;
+ fr_info_t fi;
+ nat_t *nat2;
+ u_int a1;
+ ip_t *ip;
+ mb_t *m;
+#ifdef MENTAT
+ mb_t *m1;
+#endif
+
+ m = fin->fin_m;
+ ip = fin->fin_ip;
+ tcp = (tcphdr_t *)fin->fin_dp;
+ bzero(ctcpbuf, sizeof(ctcpbuf));
+ off = (char *)tcp - (char *)ip + (TCP_OFF(tcp) << 2) + fin->fin_ipoff;
+
+#ifdef __sgi
+ dlen = fin->fin_plen - off;
+#else
+ dlen = MSGDSIZE(m) - off;
+#endif
+ if (dlen <= 0)
+ return 0;
+ COPYDATA(m, off, MIN(sizeof(ctcpbuf), dlen), ctcpbuf);
+
+ if (dlen <= 0)
+ return 0;
+ ctcpbuf[sizeof(ctcpbuf) - 1] = '\0';
+ *newbuf = '\0';
+
+ irc = nat->nat_aps->aps_data;
+ if (ippr_irc_complete(irc, ctcpbuf, dlen) == 0)
+ return 0;
+
+ /*
+ * check that IP address in the PORT/PASV reply is the same as the
+ * sender of the command - prevents using PORT for port scanning.
+ */
+ if (irc->irc_ipnum != ntohl(nat->nat_inip.s_addr))
+ return 0;
+
+ a5 = irc->irc_port;
+
+ /*
+ * Calculate new address parts for the DCC command
+ */
+ a1 = ntohl(ip->ip_src.s_addr);
+ olen = irc->irc_len;
+ i = irc->irc_addr - ctcpbuf;
+ i++;
+ (void) strncpy(newbuf, ctcpbuf, i);
+ /* DO NOT change these! */
+#if defined(SNPRINTF) && defined(KERNEL)
+ SNPRINTF(newbuf, sizeof(newbuf) - i, "%u %u\001\r\n", a1, a5);
+#else
+ (void) sprintf(newbuf, "%u %u\001\r\n", a1, a5);
+#endif
+
+ nlen = strlen(newbuf);
+ inc = nlen - olen;
+
+ if ((inc + ip->ip_len) > 65535)
+ return 0;
+
+#ifdef MENTAT
+ for (m1 = m; m1->b_cont; m1 = m1->b_cont)
+ ;
+ if ((inc > 0) && (m1->b_datap->db_lim - m1->b_wptr < inc)) {
+ mblk_t *nm;
+
+ /* alloc enough to keep same trailer space for lower driver */
+ nm = allocb(nlen, BPRI_MED);
+ PANIC((!nm),("ippr_irc_out: allocb failed"));
+
+ nm->b_band = m1->b_band;
+ nm->b_wptr += nlen;
+
+ m1->b_wptr -= olen;
+ PANIC((m1->b_wptr < m1->b_rptr),
+ ("ippr_irc_out: cannot handle fragmented data block"));
+
+ linkb(m1, nm);
+ } else {
+# if SOLARIS && defined(ICK_VALID)
+ if (m1->b_datap->db_struiolim == m1->b_wptr)
+ m1->b_datap->db_struiolim += inc;
+ m1->b_datap->db_struioflag &= ~STRUIO_IP;
+# endif
+ m1->b_wptr += inc;
+ }
+#else
+ if (inc < 0)
+ m_adj(m, inc);
+ /* the mbuf chain will be extended if necessary by m_copyback() */
+#endif
+ COPYBACK(m, off, nlen, newbuf);
+
+ if (inc != 0) {
+#if defined(MENTAT) || defined(__sgi)
+ register u_32_t sum1, sum2;
+
+ sum1 = ip->ip_len;
+ sum2 = ip->ip_len + inc;
+
+ /* Because ~1 == -2, We really need ~1 == -1 */
+ if (sum1 > sum2)
+ sum2--;
+ sum2 -= sum1;
+ sum2 = (sum2 & 0xffff) + (sum2 >> 16);
+
+ fix_outcksum(fin, &ip->ip_sum, sum2);
+#endif
+ ip->ip_len += inc;
+ }
+
+ /*
+ * Add skeleton NAT entry for connection which will come back the
+ * other way.
+ */
+ sp = htons(a5);
+ /*
+ * Don't allow the PORT command to specify a port < 1024 due to
+ * security crap.
+ */
+ if (ntohs(sp) < 1024)
+ return 0;
+
+ /*
+ * The server may not make the connection back from port 20, but
+ * it is the most likely so use it here to check for a conflicting
+ * mapping.
+ */
+ bcopy((caddr_t)fin, (caddr_t)&fi, sizeof(fi));
+ fi.fin_data[0] = sp;
+ fi.fin_data[1] = fin->fin_data[1];
+ nat2 = nat_outlookup(fin, IPN_TCP, nat->nat_p, nat->nat_inip,
+ ip->ip_dst);
+ if (nat2 == NULL) {
+ bcopy((caddr_t)fin, (caddr_t)&fi, sizeof(fi));
+ bzero((char *)tcp2, sizeof(*tcp2));
+ tcp2->th_win = htons(8192);
+ tcp2->th_sport = sp;
+ tcp2->th_dport = 0; /* XXX - don't specify remote port */
+ fi.fin_state = NULL;
+ fi.fin_nat = NULL;
+ fi.fin_data[0] = ntohs(sp);
+ fi.fin_data[1] = 0;
+ fi.fin_dp = (char *)tcp2;
+ fi.fin_fr = &ircnatfr;
+ fi.fin_dlen = sizeof(*tcp2);
+ fi.fin_plen = fi.fin_hlen + sizeof(*tcp2);
+ swip = ip->ip_src;
+ ip->ip_src = nat->nat_inip;
+ nat2 = nat_new(&fi, nat->nat_ptr, NULL,
+ NAT_SLAVE|IPN_TCP|SI_W_DPORT, NAT_OUTBOUND);
+ if (nat2 != NULL) {
+ (void) nat_proto(&fi, nat2, 0);
+ nat_update(&fi, nat2, nat2->nat_ptr);
+
+ (void) fr_addstate(&fi, NULL, SI_W_DPORT);
+ if (fi.fin_state != NULL)
+ fr_statederef(&fi, (ipstate_t **)&fi.fin_state);
+ }
+ ip->ip_src = swip;
+ }
+ return inc;
+}
+
+
+int ippr_irc_out(fin, aps, nat)
+fr_info_t *fin;
+ap_session_t *aps;
+nat_t *nat;
+{
+ aps = aps; /* LINT */
+ return ippr_irc_send(fin, nat);
+}
diff --git a/contrib/ipfilter/ip_lookup.c b/contrib/ipfilter/ip_lookup.c
new file mode 100644
index 0000000..b832373
--- /dev/null
+++ b/contrib/ipfilter/ip_lookup.c
@@ -0,0 +1,530 @@
+/* $NetBSD$ */
+
+/*
+ * Copyright (C) 2002-2003 by Darren Reed.
+ *
+ * See the IPFILTER.LICENCE file for details on licencing.
+ */
+#if defined(KERNEL) || defined(_KERNEL)
+# undef KERNEL
+# undef _KERNEL
+# define KERNEL 1
+# define _KERNEL 1
+#endif
+#if defined(__osf__)
+# define _PROTO_NET_H_
+#endif
+#include <sys/param.h>
+#include <sys/errno.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/file.h>
+#if __FreeBSD_version >= 220000 && defined(_KERNEL)
+# include <sys/fcntl.h>
+# include <sys/filio.h>
+#else
+# include <sys/ioctl.h>
+#endif
+#if !defined(_KERNEL)
+# include <string.h>
+# define _KERNEL
+# ifdef __OpenBSD__
+struct file;
+# endif
+# include <sys/uio.h>
+# undef _KERNEL
+#endif
+#include <sys/socket.h>
+#if (defined(__osf__) || defined(__hpux) || defined(__sgi)) && defined(_KERNEL)
+# ifdef __osf__
+# include <net/radix.h>
+# endif
+# include "radix_ipf_local.h"
+# define _RADIX_H_
+#endif
+#include <net/if.h>
+#if defined(__FreeBSD__)
+# include <sys/cdefs.h>
+# include <sys/proc.h>
+#endif
+#if defined(_KERNEL)
+# include <sys/systm.h>
+# if !defined(__SVR4) && !defined(__svr4__)
+# include <sys/mbuf.h>
+# endif
+#endif
+#include <netinet/in.h>
+
+#include "netinet/ip_compat.h"
+#include "netinet/ip_fil.h"
+#include "netinet/ip_pool.h"
+#include "netinet/ip_htable.h"
+#include "netinet/ip_lookup.h"
+/* END OF INCLUDES */
+
+#if !defined(lint)
+static const char rcsid[] = "@(#)Id: ip_lookup.c,v 2.35.2.5 2004/07/06 11:16:25 darrenr Exp";
+#endif
+
+#ifdef IPFILTER_LOOKUP
+int ip_lookup_inited = 0;
+
+static int iplookup_addnode __P((caddr_t));
+static int iplookup_delnode __P((caddr_t data));
+static int iplookup_addtable __P((caddr_t));
+static int iplookup_deltable __P((caddr_t));
+static int iplookup_stats __P((caddr_t));
+static int iplookup_flush __P((caddr_t));
+
+
+/* ------------------------------------------------------------------------ */
+/* Function: iplookup_init */
+/* Returns: int - 0 = success, else error */
+/* Parameters: Nil */
+/* */
+/* Initialise all of the subcomponents of the lookup infrstructure. */
+/* ------------------------------------------------------------------------ */
+int ip_lookup_init()
+{
+
+ if (ip_pool_init() == -1)
+ return -1;
+
+ RWLOCK_INIT(&ip_poolrw, "ip pool rwlock");
+
+ ip_lookup_inited = 1;
+
+ return 0;
+}
+
+
+/* ------------------------------------------------------------------------ */
+/* Function: iplookup_unload */
+/* Returns: int - 0 = success, else error */
+/* Parameters: Nil */
+/* */
+/* Free up all pool related memory that has been allocated whilst IPFilter */
+/* has been running. Also, do any other deinitialisation required such */
+/* ip_lookup_init() can be called again, safely. */
+/* ------------------------------------------------------------------------ */
+void ip_lookup_unload()
+{
+ ip_pool_fini();
+ fr_htable_unload();
+
+ if (ip_lookup_inited == 1) {
+ RW_DESTROY(&ip_poolrw);
+ ip_lookup_inited = 0;
+ }
+}
+
+
+/* ------------------------------------------------------------------------ */
+/* Function: iplookup_ioctl */
+/* Returns: int - 0 = success, else error */
+/* Parameters: data(IO) - pointer to ioctl data to be copied to/from user */
+/* space. */
+/* cmd(I) - ioctl command number */
+/* mode(I) - file mode bits used with open */
+/* */
+/* Handle ioctl commands sent to the ioctl device. For the most part, this */
+/* involves just calling another function to handle the specifics of each */
+/* command. */
+/* ------------------------------------------------------------------------ */
+int ip_lookup_ioctl(data, cmd, mode)
+caddr_t data;
+ioctlcmd_t cmd;
+int mode;
+{
+ int err;
+# if defined(_KERNEL) && !defined(MENTAT) && defined(USE_SPL)
+ int s;
+# endif
+
+ mode = mode; /* LINT */
+
+ SPL_NET(s);
+
+ switch (cmd)
+ {
+ case SIOCLOOKUPADDNODE :
+ case SIOCLOOKUPADDNODEW :
+ WRITE_ENTER(&ip_poolrw);
+ err = iplookup_addnode(data);
+ RWLOCK_EXIT(&ip_poolrw);
+ break;
+
+ case SIOCLOOKUPDELNODE :
+ case SIOCLOOKUPDELNODEW :
+ WRITE_ENTER(&ip_poolrw);
+ err = iplookup_delnode(data);
+ RWLOCK_EXIT(&ip_poolrw);
+ break;
+
+ case SIOCLOOKUPADDTABLE :
+ WRITE_ENTER(&ip_poolrw);
+ err = iplookup_addtable(data);
+ RWLOCK_EXIT(&ip_poolrw);
+ break;
+
+ case SIOCLOOKUPDELTABLE :
+ WRITE_ENTER(&ip_poolrw);
+ err = iplookup_deltable(data);
+ RWLOCK_EXIT(&ip_poolrw);
+ break;
+
+ case SIOCLOOKUPSTAT :
+ case SIOCLOOKUPSTATW :
+ WRITE_ENTER(&ip_poolrw);
+ err = iplookup_stats(data);
+ RWLOCK_EXIT(&ip_poolrw);
+ break;
+
+ case SIOCLOOKUPFLUSH :
+ WRITE_ENTER(&ip_poolrw);
+ err = iplookup_flush(data);
+ RWLOCK_EXIT(&ip_poolrw);
+ break;
+
+ default :
+ err = EINVAL;
+ break;
+ }
+ SPL_X(s);
+ return err;
+}
+
+
+/* ------------------------------------------------------------------------ */
+/* Function: iplookup_addnode */
+/* Returns: int - 0 = success, else error */
+/* Parameters: data(I) - pointer to data from ioctl call */
+/* */
+/* Add a new data node to a lookup structure. First, check to see if the */
+/* parent structure refered to by name exists and if it does, then go on to */
+/* add a node to it. */
+/* ------------------------------------------------------------------------ */
+static int iplookup_addnode(data)
+caddr_t data;
+{
+ ip_pool_node_t node, *m;
+ iplookupop_t op;
+ iphtable_t *iph;
+ iphtent_t hte;
+ ip_pool_t *p;
+ int err;
+
+ err = 0;
+ BCOPYIN(data, &op, sizeof(op));
+ op.iplo_name[sizeof(op.iplo_name) - 1] = '\0';
+
+ switch (op.iplo_type)
+ {
+ case IPLT_POOL :
+ if (op.iplo_size != sizeof(node))
+ return EINVAL;
+
+ err = COPYIN(op.iplo_struct, &node, sizeof(node));
+ if (err != 0)
+ return EFAULT;
+
+ p = ip_pool_find(op.iplo_unit, op.iplo_name);
+ if (p == NULL)
+ return ESRCH;
+
+ /*
+ * add an entry to a pool - return an error if it already
+ * exists remove an entry from a pool - if it exists
+ * - in both cases, the pool *must* exist!
+ */
+ m = ip_pool_findeq(p, &node.ipn_addr, &node.ipn_mask);
+ if (m)
+ return EEXIST;
+ err = ip_pool_insert(p, &node.ipn_addr.adf_addr,
+ &node.ipn_mask.adf_addr, node.ipn_info);
+ break;
+
+ case IPLT_HASH :
+ if (op.iplo_size != sizeof(hte))
+ return EINVAL;
+
+ err = COPYIN(op.iplo_struct, &hte, sizeof(hte));
+ if (err != 0)
+ return EFAULT;
+
+ iph = fr_findhtable(op.iplo_unit, op.iplo_name);
+ if (iph == NULL)
+ return ESRCH;
+ err = fr_addhtent(iph, &hte);
+ break;
+
+ default :
+ err = EINVAL;
+ break;
+ }
+ return err;
+}
+
+
+/* ------------------------------------------------------------------------ */
+/* Function: iplookup_delnode */
+/* Returns: int - 0 = success, else error */
+/* Parameters: data(I) - pointer to data from ioctl call */
+/* */
+/* Delete a node from a lookup table by first looking for the table it is */
+/* in and then deleting the entry that gets found. */
+/* ------------------------------------------------------------------------ */
+static int iplookup_delnode(data)
+caddr_t data;
+{
+ ip_pool_node_t node, *m;
+ iplookupop_t op;
+ iphtable_t *iph;
+ iphtent_t hte;
+ ip_pool_t *p;
+ int err;
+
+ err = 0;
+ BCOPYIN(data, &op, sizeof(op));
+
+ op.iplo_name[sizeof(op.iplo_name) - 1] = '\0';
+
+ switch (op.iplo_type)
+ {
+ case IPLT_POOL :
+ if (op.iplo_size != sizeof(node))
+ return EINVAL;
+
+ err = COPYIN(op.iplo_struct, &node, sizeof(node));
+ if (err != 0)
+ return EFAULT;
+
+ p = ip_pool_find(op.iplo_unit, op.iplo_name);
+ if (!p)
+ return ESRCH;
+
+ m = ip_pool_findeq(p, &node.ipn_addr, &node.ipn_mask);
+ if (m == NULL)
+ return ENOENT;
+ err = ip_pool_remove(p, m);
+ break;
+
+ case IPLT_HASH :
+ if (op.iplo_size != sizeof(hte))
+ return EINVAL;
+
+ err = COPYIN(op.iplo_struct, &hte, sizeof(hte));
+ if (err != 0)
+ return EFAULT;
+
+ iph = fr_findhtable(op.iplo_unit, op.iplo_name);
+ if (iph == NULL)
+ return ESRCH;
+ err = fr_delhtent(iph, &hte);
+ break;
+
+ default :
+ err = EINVAL;
+ break;
+ }
+ return err;
+}
+
+
+/* ------------------------------------------------------------------------ */
+/* Function: iplookup_addtable */
+/* Returns: int - 0 = success, else error */
+/* Parameters: data(I) - pointer to data from ioctl call */
+/* */
+/* Create a new lookup table, if one doesn't already exist using the name */
+/* for this one. */
+/* ------------------------------------------------------------------------ */
+static int iplookup_addtable(data)
+caddr_t data;
+{
+ iplookupop_t op;
+ int err;
+
+ err = 0;
+ BCOPYIN(data, &op, sizeof(op));
+
+ op.iplo_name[sizeof(op.iplo_name) - 1] = '\0';
+
+ switch (op.iplo_type)
+ {
+ case IPLT_POOL :
+ if (ip_pool_find(op.iplo_unit, op.iplo_name) != NULL)
+ err = EEXIST;
+ else
+ err = ip_pool_create(&op);
+ break;
+
+ case IPLT_HASH :
+ if (fr_findhtable(op.iplo_unit, op.iplo_name) != NULL)
+ err = EEXIST;
+ else
+ err = fr_newhtable(&op);
+ break;
+
+ default :
+ err = EINVAL;
+ break;
+ }
+ return err;
+}
+
+
+/* ------------------------------------------------------------------------ */
+/* Function: iplookup_deltable */
+/* Returns: int - 0 = success, else error */
+/* Parameters: data(I) - pointer to data from ioctl call */
+/* */
+/* Decodes ioctl request to remove a particular hash table or pool and */
+/* calls the relevant function to do the cleanup. */
+/* ------------------------------------------------------------------------ */
+static int iplookup_deltable(data)
+caddr_t data;
+{
+ iplookupop_t op;
+ int err;
+
+ BCOPYIN(data, &op, sizeof(op));
+ op.iplo_name[sizeof(op.iplo_name) - 1] = '\0';
+
+ if (op.iplo_arg & IPLT_ANON)
+ op.iplo_arg &= IPLT_ANON;
+
+ /*
+ * create a new pool - fail if one already exists with
+ * the same #
+ */
+ switch (op.iplo_type)
+ {
+ case IPLT_POOL :
+ err = ip_pool_destroy(&op);
+ break;
+
+ case IPLT_HASH :
+ err = fr_removehtable(&op);
+ break;
+
+ default :
+ err = EINVAL;
+ break;
+ }
+ return err;
+}
+
+
+/* ------------------------------------------------------------------------ */
+/* Function: iplookup_stats */
+/* Returns: int - 0 = success, else error */
+/* Parameters: data(I) - pointer to data from ioctl call */
+/* */
+/* Copy statistical information from inside the kernel back to user space. */
+/* ------------------------------------------------------------------------ */
+static int iplookup_stats(data)
+caddr_t data;
+{
+ iplookupop_t op;
+ int err;
+
+ err = 0;
+ BCOPYIN(data, &op, sizeof(op));
+
+ switch (op.iplo_type)
+ {
+ case IPLT_POOL :
+ err = ip_pool_statistics(&op);
+ break;
+
+ case IPLT_HASH :
+ err = fr_gethtablestat(&op);
+ break;
+
+ default :
+ err = EINVAL;
+ break;
+ }
+ return err;
+}
+
+
+/* ------------------------------------------------------------------------ */
+/* Function: iplookup_flush */
+/* Returns: int - 0 = success, else error */
+/* Parameters: data(I) - pointer to data from ioctl call */
+/* */
+/* A flush is called when we want to flush all the nodes from a particular */
+/* entry in the hash table/pool or want to remove all groups from those. */
+/* ------------------------------------------------------------------------ */
+static int iplookup_flush(data)
+caddr_t data;
+{
+ int err, unit, num, type;
+ iplookupflush_t flush;
+
+ err = 0;
+ BCOPYIN(data, &flush, sizeof(flush));
+
+ flush.iplf_name[sizeof(flush.iplf_name) - 1] = '\0';
+
+ unit = flush.iplf_unit;
+ if ((unit < 0 || unit > IPL_LOGMAX) && (unit != IPLT_ALL))
+ return EINVAL;
+
+ type = flush.iplf_type;
+ err = EINVAL;
+ num = 0;
+
+ if (type == IPLT_POOL || type == IPLT_ALL) {
+ err = 0;
+ num = ip_pool_flush(&flush);
+ }
+
+ if (type == IPLT_HASH || type == IPLT_ALL) {
+ err = 0;
+ num += fr_flushhtable(&flush);
+ }
+
+ if (err == 0) {
+ flush.iplf_count = num;
+ err = COPYOUT(&flush, data, sizeof(flush));
+ }
+ return err;
+}
+
+
+void ip_lookup_deref(type, ptr)
+int type;
+void *ptr;
+{
+ if (ptr == NULL)
+ return;
+
+ WRITE_ENTER(&ip_poolrw);
+ switch (type)
+ {
+ case IPLT_POOL :
+ ip_pool_deref(ptr);
+ break;
+
+ case IPLT_HASH :
+ fr_derefhtable(ptr);
+ break;
+ }
+ RWLOCK_EXIT(&ip_poolrw);
+}
+
+
+#else /* IPFILTER_LOOKUP */
+
+/*ARGSUSED*/
+int ip_lookup_ioctl(data, cmd, mode)
+caddr_t data;
+ioctlcmd_t cmd;
+int mode;
+{
+ return EIO;
+}
+#endif /* IPFILTER_LOOKUP */
diff --git a/contrib/ipfilter/ip_lookup.h b/contrib/ipfilter/ip_lookup.h
new file mode 100644
index 0000000..e9f8cb8
--- /dev/null
+++ b/contrib/ipfilter/ip_lookup.h
@@ -0,0 +1,65 @@
+/* $NetBSD$ */
+
+
+#ifndef __IP_LOOKUP_H__
+#define __IP_LOOKUP_H__
+
+#if defined(__STDC__) || defined(__GNUC__)
+# define SIOCLOOKUPADDTABLE _IOWR('r', 60, struct iplookupop)
+# define SIOCLOOKUPDELTABLE _IOWR('r', 61, struct iplookupop)
+# define SIOCLOOKUPSTAT _IOWR('r', 64, struct iplookupop)
+# define SIOCLOOKUPSTATW _IOW('r', 64, struct iplookupop)
+# define SIOCLOOKUPFLUSH _IOWR('r', 65, struct iplookupflush)
+# define SIOCLOOKUPADDNODE _IOWR('r', 67, struct iplookupop)
+# define SIOCLOOKUPADDNODEW _IOW('r', 67, struct iplookupop)
+# define SIOCLOOKUPDELNODE _IOWR('r', 68, struct iplookupop)
+# define SIOCLOOKUPDELNODEW _IOW('r', 68, struct iplookupop)
+#else
+# define SIOCLOOKUPADDTABLE _IOWR(r, 60, struct iplookupop)
+# define SIOCLOOKUPDELTABLE _IOWR(r, 61, struct iplookupop)
+# define SIOCLOOKUPSTAT _IOWR(r, 64, struct iplookupop)
+# define SIOCLOOKUPSTATW _IOW(r, 64, struct iplookupop)
+# define SIOCLOOKUPFLUSH _IOWR(r, 65, struct iplookupflush)
+# define SIOCLOOKUPADDNODE _IOWR(r, 67, struct iplookupop)
+# define SIOCLOOKUPADDNODEW _IOW(r, 67, struct iplookupop)
+# define SIOCLOOKUPDELNODE _IOWR(r, 68, struct iplookupop)
+# define SIOCLOOKUPDELNODEW _IOW(r, 68, struct iplookupop)
+#endif
+
+typedef struct iplookupop {
+ int iplo_type; /* IPLT_* */
+ int iplo_unit; /* IPL_LOG* */
+ u_int iplo_arg;
+ char iplo_name[FR_GROUPLEN];
+ size_t iplo_size; /* sizeof struct at iplo_struct */
+ void *iplo_struct;
+} iplookupop_t;
+
+typedef struct iplookupflush {
+ int iplf_type; /* IPLT_* */
+ int iplf_unit; /* IPL_LOG* */
+ u_int iplf_arg;
+ size_t iplf_count;
+ char iplf_name[FR_GROUPLEN];
+} iplookupflush_t;
+
+typedef struct iplookuplink {
+ int ipll_type; /* IPLT_* */
+ int ipll_unit; /* IPL_LOG* */
+ u_int ipll_num;
+ char ipll_group[FR_GROUPLEN];
+} iplookuplink_t;
+
+#define IPLT_ALL -1
+#define IPLT_NONE 0
+#define IPLT_POOL 1
+#define IPLT_HASH 2
+
+#define IPLT_ANON 0x80000000
+
+extern int ip_lookup_init __P((void));
+extern int ip_lookup_ioctl __P((caddr_t, ioctlcmd_t, int));
+extern void ip_lookup_unload __P((void));
+extern void ip_lookup_deref __P((int, void *));
+
+#endif /* __IP_LOOKUP_H__ */
diff --git a/contrib/ipfilter/ip_msnrpc_pxy.c b/contrib/ipfilter/ip_msnrpc_pxy.c
new file mode 100644
index 0000000..187a964
--- /dev/null
+++ b/contrib/ipfilter/ip_msnrpc_pxy.c
@@ -0,0 +1,328 @@
+/* $NetBSD$ */
+
+/*
+ * Copyright (C) 2000-2003 by Darren Reed
+ *
+ * See the IPFILTER.LICENCE file for details on licencing.
+ *
+ * Simple DCE transparent proxy for MSN RPC.
+ *
+ * ******* NOTE: THIS PROXY DOES NOT DO ADDRESS TRANSLATION ********
+ *
+ * Id: ip_msnrpc_pxy.c,v 2.17.2.1 2005/02/04 10:22:55 darrenr Exp
+ */
+
+#define IPF_MSNRPC_PROXY
+
+#define IPF_MINMSNRPCLEN 24
+#define IPF_MSNRPCSKIP (2 + 19 + 2 + 2 + 2 + 19 + 2 + 2)
+
+
+typedef struct msnrpchdr {
+ u_char mrh_major; /* major # == 5 */
+ u_char mrh_minor; /* minor # == 0 */
+ u_char mrh_type;
+ u_char mrh_flags;
+ u_32_t mrh_endian;
+ u_short mrh_dlen; /* data size */
+ u_short mrh_alen; /* authentication length */
+ u_32_t mrh_cid; /* call identifier */
+ u_32_t mrh_hint; /* allocation hint */
+ u_short mrh_ctxt; /* presentation context hint */
+ u_char mrh_ccnt; /* cancel count */
+ u_char mrh_ans;
+} msnrpchdr_t;
+
+int ippr_msnrpc_init __P((void));
+void ippr_msnrpc_fini __P((void));
+int ippr_msnrpc_new __P((fr_info_t *, ap_session_t *, nat_t *));
+int ippr_msnrpc_out __P((fr_info_t *, ap_session_t *, nat_t *));
+int ippr_msnrpc_in __P((fr_info_t *, ap_session_t *, nat_t *));
+int ippr_msnrpc_check __P((ip_t *, msnrpchdr_t *));
+
+static frentry_t msnfr;
+
+int msn_proxy_init = 0;
+
+/*
+ * Initialize local structures.
+ */
+int ippr_msnrpc_init()
+{
+ bzero((char *)&msnfr, sizeof(msnfr));
+ msnfr.fr_ref = 1;
+ msnfr.fr_flags = FR_INQUE|FR_PASS|FR_QUICK|FR_KEEPSTATE;
+ MUTEX_INIT(&msnfr.fr_lock, "MSN RPC proxy rule lock");
+ msn_proxy_init = 1;
+
+ return 0;
+}
+
+
+void ippr_msnrpc_fini()
+{
+ if (msn_proxy_init == 1) {
+ MUTEX_DESTROY(&msnfr.fr_lock);
+ msn_proxy_init = 0;
+ }
+}
+
+
+int ippr_msnrpc_new(fin, aps, nat)
+fr_info_t *fin;
+ap_session_t *aps;
+nat_t *nat;
+{
+ msnrpcinfo_t *mri;
+
+ KMALLOC(mri, msnrpcinfo_t *);
+ if (mri == NULL)
+ return -1;
+ aps->aps_data = mri;
+ aps->aps_psiz = sizeof(msnrpcinfo_t);
+
+ bzero((char *)mri, sizeof(*mri));
+ mri->mri_cmd[0] = 0xff;
+ mri->mri_cmd[1] = 0xff;
+ return 0;
+}
+
+
+int ippr_msnrpc_check(ip, mrh)
+ip_t *ip;
+msnrpchdr_t *mrh;
+{
+ if (mrh->mrh_major != 5)
+ return -1;
+ if (mrh->mrh_minor != 0)
+ return -1;
+ if (mrh->mrh_alen != 0)
+ return -1;
+ if (mrh->mrh_endian == 0x10) {
+ /* Both gateway and packet match endian */
+ if (mrh->mrh_dlen > ip->ip_len)
+ return -1;
+ if (mrh->mrh_type == 0 || mrh->mrh_type == 2)
+ if (mrh->mrh_hint > ip->ip_len)
+ return -1;
+ } else if (mrh->mrh_endian == 0x10000000) {
+ /* XXX - Endian mismatch - should be swapping! */
+ return -1;
+ } else {
+ return -1;
+ }
+ return 0;
+}
+
+
+int ippr_msnrpc_out(fin, ip, aps, nat)
+fr_info_t *fin;
+ip_t *ip;
+ap_session_t *aps;
+nat_t *nat;
+{
+ msnrpcinfo_t *mri;
+ msnrpchdr_t *mrh;
+ tcphdr_t *tcp;
+ int dlen;
+
+ mri = aps->aps_data;
+ if (mri == NULL)
+ return 0;
+
+ tcp = (tcphdr_t *)fin->fin_dp;
+ dlen = fin->fin_dlen - (TCP_OFF(tcp) << 2);
+ if (dlen < IPF_MINMSNRPCLEN)
+ return 0;
+
+ mrh = (msnrpchdr_t *)((char *)tcp + (TCP_OFF(tcp) << 2));
+ if (ippr_msnrpc_check(ip, mrh))
+ return 0;
+
+ mri->mri_valid++;
+
+ switch (mrh->mrh_type)
+ {
+ case 0x0b : /* BIND */
+ case 0x00 : /* REQUEST */
+ break;
+ case 0x0c : /* BIND ACK */
+ case 0x02 : /* RESPONSE */
+ default:
+ return 0;
+ }
+ mri->mri_cmd[1] = mrh->mrh_type;
+ return 0;
+}
+
+
+int ippr_msnrpc_in(fin, ip, aps, nat)
+fr_info_t *fin;
+ip_t *ip;
+ap_session_t *aps;
+nat_t *nat;
+{
+ tcphdr_t *tcp, tcph, *tcp2 = &tcph;
+ int dlen, sz, sz2, i;
+ msnrpcinfo_t *mri;
+ msnrpchdr_t *mrh;
+ fr_info_t fi;
+ u_short len;
+ char *s;
+
+ mri = aps->aps_data;
+ if (mri == NULL)
+ return 0;
+ tcp = (tcphdr_t *)fin->fin_dp;
+ dlen = fin->fin_dlen - (TCP_OFF(tcp) << 2);
+ if (dlen < IPF_MINMSNRPCLEN)
+ return 0;
+
+ mrh = (msnrpchdr_t *)((char *)tcp + (TCP_OFF(tcp) << 2));
+ if (ippr_msnrpc_check(ip, mrh))
+ return 0;
+
+ mri->mri_valid++;
+
+ switch (mrh->mrh_type)
+ {
+ case 0x0c : /* BIND ACK */
+ if (mri->mri_cmd[1] != 0x0b)
+ return 0;
+ break;
+ case 0x02 : /* RESPONSE */
+ if (mri->mri_cmd[1] != 0x00)
+ return 0;
+ break;
+ case 0x0b : /* BIND */
+ case 0x00 : /* REQUEST */
+ default:
+ return 0;
+ }
+ mri->mri_cmd[0] = mrh->mrh_type;
+ dlen -= sizeof(*mrh);
+
+ /*
+ * Only processes RESPONSE's
+ */
+ if (mrh->mrh_type != 0x02)
+ return 0;
+
+ /*
+ * Skip over some bytes...what are these really ?
+ */
+ if (dlen <= 44)
+ return 0;
+ s = (char *)(mrh + 1) + 20;
+ dlen -= 20;
+ bcopy(s, (char *)&len, sizeof(len));
+ if (len == 1) {
+ s += 20;
+ dlen -= 20;
+ } else if (len == 2) {
+ s += 24;
+ dlen -= 24;
+ } else
+ return 0;
+
+ if (dlen <= 10)
+ return 0;
+ dlen -= 10;
+ bcopy(s, (char *)&sz, sizeof(sz));
+ s += sizeof(sz);
+ bcopy(s, (char *)&sz2, sizeof(sz2));
+ s += sizeof(sz2);
+ if (sz2 != sz)
+ return 0;
+ if (sz > dlen)
+ return 0;
+ if (*s++ != 5)
+ return 0;
+ if (*s++ != 0)
+ return 0;
+ sz -= IPF_MSNRPCSKIP;
+ s += IPF_MSNRPCSKIP;
+ dlen -= IPF_MSNRPCSKIP;
+
+ do {
+ if (sz < 7 || dlen < 7)
+ break;
+ bcopy(s, (char *)&len, sizeof(len));
+ if (dlen < len)
+ break;
+ if (sz < len)
+ break;
+
+ if (len != 1)
+ break;
+ sz -= 3;
+ i = *(s + 2);
+ s += 3;
+ dlen -= 3;
+
+ bcopy(s, (char *)&len, sizeof(len));
+ if (dlen < len)
+ break;
+ if (sz < len)
+ break;
+ s += sizeof(len);
+
+ switch (i)
+ {
+ case 7 :
+ if (len == 2) {
+ bcopy(s, (char *)&mri->mri_rport, 2);
+ mri->mri_flags |= 1;
+ }
+ break;
+ case 9 :
+ if (len == 4) {
+ bcopy(s, (char *)&mri->mri_raddr, 4);
+ mri->mri_flags |= 2;
+ }
+ break;
+ default :
+ break;
+ }
+ sz -= len;
+ s += len;
+ dlen -= len;
+ } while (sz > 0);
+
+ if (mri->mri_flags == 3) {
+ int slen;
+
+ bcopy((char *)fin, (char *)&fi, sizeof(fi));
+ bzero((char *)tcp2, sizeof(*tcp2));
+
+ slen = ip->ip_len;
+ ip->ip_len = fin->fin_hlen + sizeof(*tcp2);
+ bcopy((char *)fin, (char *)&fi, sizeof(fi));
+ bzero((char *)tcp2, sizeof(*tcp2));
+ tcp2->th_win = htons(8192);
+ TCP_OFF_A(tcp2, 5);
+ fi.fin_data[0] = htons(mri->mri_rport);
+ tcp2->th_sport = mri->mri_rport;
+ fi.fin_data[1] = 0;
+ tcp2->th_dport = 0;
+ fi.fin_state = NULL;
+ fi.fin_nat = NULL;
+ fi.fin_dlen = sizeof(*tcp2);
+ fi.fin_plen = fi.fin_hlen + sizeof(*tcp2);
+ fi.fin_dp = (char *)tcp2;
+ fi.fin_fi.fi_daddr = ip->ip_dst.s_addr;
+ fi.fin_fi.fi_saddr = mri->mri_raddr.s_addr;
+ if (!fi.fin_fr)
+ fi.fin_fr = &msnfr;
+ if (fr_stlookup(&fi, NULL, NULL)) {
+ RWLOCK_EXIT(&ipf_state);
+ } else {
+ (void) fr_addstate(&fi, NULL, SI_W_DPORT|SI_CLONE);
+ if (fi.fin_state != NULL)
+ fr_statederef(&fi, (ipstate_t **)&fi.fin_state);
+ }
+ ip->ip_len = slen;
+ }
+ mri->mri_flags = 0;
+ return 0;
+}
diff --git a/contrib/ipfilter/ip_pool.c b/contrib/ipfilter/ip_pool.c
new file mode 100644
index 0000000..b6e111b
--- /dev/null
+++ b/contrib/ipfilter/ip_pool.c
@@ -0,0 +1,786 @@
+/* $NetBSD$ */
+
+/*
+ * Copyright (C) 1993-2001, 2003 by Darren Reed.
+ *
+ * See the IPFILTER.LICENCE file for details on licencing.
+ */
+#if defined(KERNEL) || defined(_KERNEL)
+# undef KERNEL
+# undef _KERNEL
+# define KERNEL 1
+# define _KERNEL 1
+#endif
+#if defined(__osf__)
+# define _PROTO_NET_H_
+#endif
+#include <sys/errno.h>
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/file.h>
+#if !defined(_KERNEL) && !defined(__KERNEL__)
+# include <stdio.h>
+# include <stdlib.h>
+# include <string.h>
+# define _KERNEL
+# ifdef __OpenBSD__
+struct file;
+# endif
+# include <sys/uio.h>
+# undef _KERNEL
+#else
+# include <sys/systm.h>
+# if defined(NetBSD) && (__NetBSD_Version__ >= 104000000)
+# include <sys/proc.h>
+# endif
+#endif
+#include <sys/time.h>
+#if !defined(linux)
+# include <sys/protosw.h>
+#endif
+#include <sys/socket.h>
+#if defined(_KERNEL) && (!defined(__SVR4) && !defined(__svr4__))
+# include <sys/mbuf.h>
+#endif
+#if defined(__SVR4) || defined(__svr4__)
+# include <sys/filio.h>
+# include <sys/byteorder.h>
+# ifdef _KERNEL
+# include <sys/dditypes.h>
+# endif
+# include <sys/stream.h>
+# include <sys/kmem.h>
+#endif
+#if defined(__FreeBSD_version) && (__FreeBSD_version >= 300000)
+# include <sys/malloc.h>
+#endif
+
+#if (defined(__osf__) || defined(__hpux) || defined(__sgi)) && defined(_KERNEL)
+# ifdef __osf__
+# include <net/radix.h>
+# endif
+# include "radix_ipf_local.h"
+# define _RADIX_H_
+#endif
+#include <net/if.h>
+#include <netinet/in.h>
+
+#include "netinet/ip_compat.h"
+#include "netinet/ip_fil.h"
+#include "netinet/ip_pool.h"
+
+#if defined(IPFILTER_LOOKUP) && defined(_KERNEL) && \
+ ((BSD >= 198911) && !defined(__osf__) && \
+ !defined(__hpux) && !defined(__sgi))
+static int rn_freenode __P((struct radix_node *, void *));
+#endif
+
+/* END OF INCLUDES */
+
+#if !defined(lint)
+static const char sccsid[] = "@(#)ip_fil.c 2.41 6/5/96 (C) 1993-2000 Darren Reed";
+static const char rcsid[] = "@(#)Id: ip_pool.c,v 2.55.2.12 2005/02/01 04:04:46 darrenr Exp";
+#endif
+
+#ifdef IPFILTER_LOOKUP
+
+# ifndef RADIX_NODE_HEAD_LOCK
+# define RADIX_NODE_HEAD_LOCK(x) ;
+# endif
+# ifndef RADIX_NODE_HEAD_UNLOCK
+# define RADIX_NODE_HEAD_UNLOCK(x) ;
+# endif
+
+ip_pool_stat_t ipoolstat;
+ipfrwlock_t ip_poolrw;
+
+/*
+ * Binary tree routines from Sedgewick and enhanced to do ranges of addresses.
+ * NOTE: Insertion *MUST* be from greatest range to least for it to work!
+ * These should be replaced, eventually, by something else - most notably a
+ * interval searching method. The important feature is to be able to find
+ * the best match.
+ *
+ * So why not use a radix tree for this? As the first line implies, it
+ * has been written to work with a _range_ of addresses. A range is not
+ * necessarily a match with any given netmask so what we end up dealing
+ * with is an interval tree. Implementations of these are hard to find
+ * and the one herein is far from bug free.
+ *
+ * Sigh, in the end I became convinced that the bugs the code contained did
+ * not make it worthwhile not using radix trees. For now the radix tree from
+ * 4.4 BSD is used, but this is not viewed as a long term solution.
+ */
+ip_pool_t *ip_pool_list[IPL_LOGSIZE] = { NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL };
+
+
+#ifdef TEST_POOL
+void treeprint __P((ip_pool_t *));
+
+int
+main(argc, argv)
+ int argc;
+ char *argv[];
+{
+ addrfamily_t a, b;
+ iplookupop_t op;
+ ip_pool_t *ipo;
+ i6addr_t ip;
+
+ RWLOCK_INIT(&ip_poolrw, "poolrw");
+ ip_pool_init();
+
+ bzero((char *)&a, sizeof(a));
+ bzero((char *)&b, sizeof(b));
+ bzero((char *)&ip, sizeof(ip));
+ bzero((char *)&op, sizeof(op));
+ strcpy(op.iplo_name, "0");
+
+ if (ip_pool_create(&op) == 0)
+ ipo = ip_pool_find(0, "0");
+
+ a.adf_addr.in4.s_addr = 0x0a010203;
+ b.adf_addr.in4.s_addr = 0xffffffff;
+ ip_pool_insert(ipo, &a.adf_addr, &b.adf_addr, 1);
+ ip_pool_insert(ipo, &a.adf_addr, &b.adf_addr, 1);
+
+ a.adf_addr.in4.s_addr = 0x0a000000;
+ b.adf_addr.in4.s_addr = 0xff000000;
+ ip_pool_insert(ipo, &a.adf_addr, &b.adf_addr, 0);
+ ip_pool_insert(ipo, &a.adf_addr, &b.adf_addr, 0);
+
+ a.adf_addr.in4.s_addr = 0x0a010100;
+ b.adf_addr.in4.s_addr = 0xffffff00;
+ ip_pool_insert(ipo, &a.adf_addr, &b.adf_addr, 1);
+ ip_pool_insert(ipo, &a.adf_addr, &b.adf_addr, 1);
+
+ a.adf_addr.in4.s_addr = 0x0a010200;
+ b.adf_addr.in4.s_addr = 0xffffff00;
+ ip_pool_insert(ipo, &a.adf_addr, &b.adf_addr, 0);
+ ip_pool_insert(ipo, &a.adf_addr, &b.adf_addr, 0);
+
+ a.adf_addr.in4.s_addr = 0x0a010000;
+ b.adf_addr.in4.s_addr = 0xffff0000;
+ ip_pool_insert(ipo, &a.adf_addr, &b.adf_addr, 1);
+ ip_pool_insert(ipo, &a.adf_addr, &b.adf_addr, 1);
+
+ a.adf_addr.in4.s_addr = 0x0a01020f;
+ b.adf_addr.in4.s_addr = 0xffffffff;
+ ip_pool_insert(ipo, &a.adf_addr, &b.adf_addr, 1);
+ ip_pool_insert(ipo, &a.adf_addr, &b.adf_addr, 1);
+#ifdef DEBUG_POOL
+treeprint(ipo);
+#endif
+ ip.in4.s_addr = 0x0a00aabb;
+ printf("search(%#x) = %d (0)\n", ip.in4.s_addr,
+ ip_pool_search(ipo, 4, &ip));
+
+ ip.in4.s_addr = 0x0a000001;
+ printf("search(%#x) = %d (0)\n", ip.in4.s_addr,
+ ip_pool_search(ipo, 4, &ip));
+
+ ip.in4.s_addr = 0x0a000101;
+ printf("search(%#x) = %d (0)\n", ip.in4.s_addr,
+ ip_pool_search(ipo, 4, &ip));
+
+ ip.in4.s_addr = 0x0a010001;
+ printf("search(%#x) = %d (1)\n", ip.in4.s_addr,
+ ip_pool_search(ipo, 4, &ip));
+
+ ip.in4.s_addr = 0x0a010101;
+ printf("search(%#x) = %d (1)\n", ip.in4.s_addr,
+ ip_pool_search(ipo, 4, &ip));
+
+ ip.in4.s_addr = 0x0a010201;
+ printf("search(%#x) = %d (0)\n", ip.in4.s_addr,
+ ip_pool_search(ipo, 4, &ip));
+
+ ip.in4.s_addr = 0x0a010203;
+ printf("search(%#x) = %d (1)\n", ip.in4.s_addr,
+ ip_pool_search(ipo, 4, &ip));
+
+ ip.in4.s_addr = 0x0a01020f;
+ printf("search(%#x) = %d (1)\n", ip.in4.s_addr,
+ ip_pool_search(ipo, 4, &ip));
+
+ ip.in4.s_addr = 0x0b00aabb;
+ printf("search(%#x) = %d (-1)\n", ip.in4.s_addr,
+ ip_pool_search(ipo, 4, &ip));
+
+#ifdef DEBUG_POOL
+treeprint(ipo);
+#endif
+
+ ip_pool_fini();
+
+ return 0;
+}
+
+
+void
+treeprint(ipo)
+ip_pool_t *ipo;
+{
+ ip_pool_node_t *c;
+
+ for (c = ipo->ipo_list; c != NULL; c = c->ipn_next)
+ printf("Node %p(%s) (%#x/%#x) = %d hits %lu\n",
+ c, c->ipn_name, c->ipn_addr.adf_addr.in4.s_addr,
+ c->ipn_mask.adf_addr.in4.s_addr,
+ c->ipn_info, c->ipn_hits);
+}
+#endif /* TEST_POOL */
+
+
+/* ------------------------------------------------------------------------ */
+/* Function: ip_pool_init */
+/* Returns: int - 0 = success, else error */
+/* */
+/* Initialise the routing table data structures where required. */
+/* ------------------------------------------------------------------------ */
+int ip_pool_init()
+{
+
+ bzero((char *)&ipoolstat, sizeof(ipoolstat));
+
+#if (!defined(_KERNEL) || (BSD < 199306))
+ rn_init();
+#endif
+ return 0;
+}
+
+
+/* ------------------------------------------------------------------------ */
+/* Function: ip_pool_fini */
+/* Returns: int - 0 = success, else error */
+/* Locks: WRITE(ipf_global) */
+/* */
+/* Clean up all the pool data structures allocated and call the cleanup */
+/* function for the radix tree that supports the pools. ip_pool_destroy() is*/
+/* used to delete the pools one by one to ensure they're properly freed up. */
+/* ------------------------------------------------------------------------ */
+void ip_pool_fini()
+{
+ ip_pool_t *p, *q;
+ iplookupop_t op;
+ int i;
+
+ ASSERT(rw_read_locked(&ipf_global.ipf_lk) == 0);
+
+ for (i = 0; i <= IPL_LOGMAX; i++) {
+ for (q = ip_pool_list[i]; (p = q) != NULL; ) {
+ op.iplo_unit = i;
+ (void)strncpy(op.iplo_name, p->ipo_name,
+ sizeof(op.iplo_name));
+ q = p->ipo_next;
+ (void) ip_pool_destroy(&op);
+ }
+ }
+
+#if (!defined(_KERNEL) || (BSD < 199306))
+ rn_fini();
+#endif
+}
+
+
+/* ------------------------------------------------------------------------ */
+/* Function: ip_pool_statistics */
+/* Returns: int - 0 = success, else error */
+/* Parameters: op(I) - pointer to lookup operation arguments */
+/* */
+/* Copy the current statistics out into user space, collecting pool list */
+/* pointers as appropriate for later use. */
+/* ------------------------------------------------------------------------ */
+int ip_pool_statistics(op)
+iplookupop_t *op;
+{
+ ip_pool_stat_t stats;
+ int unit, i, err = 0;
+
+ if (op->iplo_size != sizeof(ipoolstat))
+ return EINVAL;
+
+ bcopy((char *)&ipoolstat, (char *)&stats, sizeof(stats));
+ unit = op->iplo_unit;
+ if (unit == IPL_LOGALL) {
+ for (i = 0; i < IPL_LOGSIZE; i++)
+ stats.ipls_list[i] = ip_pool_list[i];
+ } else if (unit >= 0 && unit < IPL_LOGSIZE) {
+ if (op->iplo_name[0] != '\0')
+ stats.ipls_list[unit] = ip_pool_find(unit,
+ op->iplo_name);
+ else
+ stats.ipls_list[unit] = ip_pool_list[unit];
+ } else
+ err = EINVAL;
+ if (err == 0)
+ err = COPYOUT(&stats, op->iplo_struct, sizeof(stats));
+ return err;
+}
+
+
+
+/* ------------------------------------------------------------------------ */
+/* Function: ip_pool_find */
+/* Returns: int - 0 = success, else error */
+/* Parameters: ipo(I) - pointer to the pool getting the new node. */
+/* */
+/* Find a matching pool inside the collection of pools for a particular */
+/* device, indicated by the unit number. */
+/* ------------------------------------------------------------------------ */
+void *ip_pool_find(unit, name)
+int unit;
+char *name;
+{
+ ip_pool_t *p;
+
+ for (p = ip_pool_list[unit]; p != NULL; p = p->ipo_next)
+ if (strncmp(p->ipo_name, name, sizeof(p->ipo_name)) == 0)
+ break;
+ return p;
+}
+
+
+/* ------------------------------------------------------------------------ */
+/* Function: ip_pool_findeq */
+/* Returns: int - 0 = success, else error */
+/* Parameters: ipo(I) - pointer to the pool getting the new node. */
+/* addr(I) - pointer to address information to delete */
+/* mask(I) - */
+/* */
+/* Searches for an exact match of an entry in the pool. */
+/* ------------------------------------------------------------------------ */
+ip_pool_node_t *ip_pool_findeq(ipo, addr, mask)
+ip_pool_t *ipo;
+addrfamily_t *addr, *mask;
+{
+ struct radix_node *n;
+#ifdef USE_SPL
+ int s;
+
+ SPL_NET(s);
+#endif
+ RADIX_NODE_HEAD_LOCK(ipo->ipo_head);
+ n = ipo->ipo_head->rnh_lookup(addr, mask, ipo->ipo_head);
+ RADIX_NODE_HEAD_UNLOCK(ipo->ipo_head);
+ SPL_X(s);
+ return (ip_pool_node_t *)n;
+}
+
+
+/* ------------------------------------------------------------------------ */
+/* Function: ip_pool_search */
+/* Returns: int - 0 == +ve match, -1 == error, 1 == -ve/no match */
+/* Parameters: tptr(I) - pointer to the pool to search */
+/* version(I) - IP protocol version (4 or 6) */
+/* dptr(I) - pointer to address information */
+/* */
+/* Search the pool for a given address and return a search result. */
+/* ------------------------------------------------------------------------ */
+int ip_pool_search(tptr, version, dptr)
+void *tptr;
+int version;
+void *dptr;
+{
+ struct radix_node *rn;
+ ip_pool_node_t *m;
+ i6addr_t *addr;
+ addrfamily_t v;
+ ip_pool_t *ipo;
+ int rv;
+
+ ipo = tptr;
+ if (ipo == NULL)
+ return -1;
+
+ rv = 1;
+ m = NULL;
+ addr = (i6addr_t *)dptr;
+ bzero(&v, sizeof(v));
+ v.adf_len = offsetof(addrfamily_t, adf_addr);
+
+ if (version == 4) {
+ v.adf_len += sizeof(addr->in4);
+ v.adf_addr.in4 = addr->in4;
+#ifdef USE_INET6
+ } else if (version == 6) {
+ v.adf_len += sizeof(addr->in6);
+ v.adf_addr.in6 = addr->in6;
+#endif
+ } else
+ return -1;
+
+ READ_ENTER(&ip_poolrw);
+
+ RADIX_NODE_HEAD_LOCK(ipo->ipo_head);
+ rn = ipo->ipo_head->rnh_matchaddr(&v, ipo->ipo_head);
+ RADIX_NODE_HEAD_UNLOCK(ipo->ipo_head);
+
+ if ((rn != NULL) && ((rn->rn_flags & RNF_ROOT) == 0)) {
+ m = (ip_pool_node_t *)rn;
+ ipo->ipo_hits++;
+ m->ipn_hits++;
+ rv = m->ipn_info;
+ }
+ RWLOCK_EXIT(&ip_poolrw);
+ return rv;
+}
+
+
+/* ------------------------------------------------------------------------ */
+/* Function: ip_pool_insert */
+/* Returns: int - 0 = success, else error */
+/* Parameters: ipo(I) - pointer to the pool getting the new node. */
+/* addr(I) - address being added as a node */
+/* mask(I) - netmask to with the node being added */
+/* info(I) - extra information to store in this node. */
+/* Locks: WRITE(ip_poolrw) */
+/* */
+/* Add another node to the pool given by ipo. The three parameters passed */
+/* in (addr, mask, info) shold all be stored in the node. */
+/* ------------------------------------------------------------------------ */
+int ip_pool_insert(ipo, addr, mask, info)
+ip_pool_t *ipo;
+i6addr_t *addr, *mask;
+int info;
+{
+ struct radix_node *rn;
+ ip_pool_node_t *x;
+
+ ASSERT(rw_read_locked(&ip_poolrw.ipf_lk) == 0);
+
+ KMALLOC(x, ip_pool_node_t *);
+ if (x == NULL) {
+ return ENOMEM;
+ }
+
+ bzero(x, sizeof(*x));
+
+ x->ipn_info = info;
+ (void)strncpy(x->ipn_name, ipo->ipo_name, sizeof(x->ipn_name));
+
+ bcopy(addr, &x->ipn_addr.adf_addr, sizeof(*addr));
+ x->ipn_addr.adf_len = sizeof(x->ipn_addr);
+ bcopy(mask, &x->ipn_mask.adf_addr, sizeof(*mask));
+ x->ipn_mask.adf_len = sizeof(x->ipn_mask);
+
+ RADIX_NODE_HEAD_LOCK(ipo->ipo_head);
+ rn = ipo->ipo_head->rnh_addaddr(&x->ipn_addr, &x->ipn_mask,
+ ipo->ipo_head, x->ipn_nodes);
+ RADIX_NODE_HEAD_UNLOCK(ipo->ipo_head);
+#ifdef DEBUG_POOL
+ printf("Added %p at %p\n", x, rn);
+#endif
+
+ if (rn == NULL) {
+ KFREE(x);
+ return ENOMEM;
+ }
+
+ x->ipn_next = ipo->ipo_list;
+ x->ipn_pnext = &ipo->ipo_list;
+ if (ipo->ipo_list != NULL)
+ ipo->ipo_list->ipn_pnext = &x->ipn_next;
+ ipo->ipo_list = x;
+
+ ipoolstat.ipls_nodes++;
+
+ return 0;
+}
+
+
+/* ------------------------------------------------------------------------ */
+/* Function: ip_pool_create */
+/* Returns: int - 0 = success, else error */
+/* Parameters: op(I) - pointer to iplookup struct with call details */
+/* Locks: WRITE(ip_poolrw) */
+/* */
+/* Creates a new group according to the paramters passed in via the */
+/* iplookupop structure. Does not check to see if the group already exists */
+/* when being inserted - assume this has already been done. If the pool is */
+/* marked as being anonymous, give it a new, unique, identifier. Call any */
+/* other functions required to initialise the structure. */
+/* ------------------------------------------------------------------------ */
+int ip_pool_create(op)
+iplookupop_t *op;
+{
+ char name[FR_GROUPLEN];
+ int poolnum, unit;
+ ip_pool_t *h;
+
+ ASSERT(rw_read_locked(&ip_poolrw.ipf_lk) == 0);
+
+ KMALLOC(h, ip_pool_t *);
+ if (h == NULL)
+ return ENOMEM;
+ bzero(h, sizeof(*h));
+
+ if (rn_inithead((void **)&h->ipo_head,
+ offsetof(addrfamily_t, adf_addr) << 3) == 0) {
+ KFREE(h);
+ return ENOMEM;
+ }
+
+ unit = op->iplo_unit;
+
+ if ((op->iplo_arg & IPOOL_ANON) != 0) {
+ ip_pool_t *p;
+
+ poolnum = IPOOL_ANON;
+
+#if defined(SNPRINTF) && defined(_KERNEL)
+ SNPRINTF(name, sizeof(name), "%x", poolnum);
+#else
+ (void)sprintf(name, "%x", poolnum);
+#endif
+
+ for (p = ip_pool_list[unit]; p != NULL; ) {
+ if (strncmp(name, p->ipo_name,
+ sizeof(p->ipo_name)) == 0) {
+ poolnum++;
+#if defined(SNPRINTF) && defined(_KERNEL)
+ SNPRINTF(name, sizeof(name), "%x", poolnum);
+#else
+ (void)sprintf(name, "%x", poolnum);
+#endif
+ p = ip_pool_list[unit];
+ } else
+ p = p->ipo_next;
+ }
+
+ (void)strncpy(h->ipo_name, name, sizeof(h->ipo_name));
+ } else {
+ (void) strncpy(h->ipo_name, op->iplo_name, sizeof(h->ipo_name));
+ }
+
+ h->ipo_ref = 1;
+ h->ipo_list = NULL;
+ h->ipo_unit = unit;
+ h->ipo_next = ip_pool_list[unit];
+ if (ip_pool_list[unit] != NULL)
+ ip_pool_list[unit]->ipo_pnext = &h->ipo_next;
+ h->ipo_pnext = &ip_pool_list[unit];
+ ip_pool_list[unit] = h;
+
+ ipoolstat.ipls_pools++;
+
+ return 0;
+}
+
+
+/* ------------------------------------------------------------------------ */
+/* Function: ip_pool_remove */
+/* Returns: int - 0 = success, else error */
+/* Parameters: ipo(I) - pointer to the pool to remove the node from. */
+/* ipe(I) - address being deleted as a node */
+/* Locks: WRITE(ip_poolrw) */
+/* */
+/* Add another node to the pool given by ipo. The three parameters passed */
+/* in (addr, mask, info) shold all be stored in the node. */
+/* ------------------------------------------------------------------------ */
+int ip_pool_remove(ipo, ipe)
+ip_pool_t *ipo;
+ip_pool_node_t *ipe;
+{
+ ip_pool_node_t **ipp, *n;
+
+ ASSERT(rw_read_locked(&ip_poolrw.ipf_lk) == 0);
+
+ for (ipp = &ipo->ipo_list; (n = *ipp) != NULL; ipp = &n->ipn_next) {
+ if (ipe == n) {
+ *n->ipn_pnext = n->ipn_next;
+ if (n->ipn_next)
+ n->ipn_next->ipn_pnext = n->ipn_pnext;
+ break;
+ }
+ }
+
+ if (n == NULL)
+ return ENOENT;
+
+ RADIX_NODE_HEAD_LOCK(ipo->ipo_head);
+ ipo->ipo_head->rnh_deladdr(&n->ipn_addr, &n->ipn_mask,
+ ipo->ipo_head);
+ RADIX_NODE_HEAD_UNLOCK(ipo->ipo_head);
+ KFREE(n);
+
+ ipoolstat.ipls_nodes--;
+
+ return 0;
+}
+
+
+/* ------------------------------------------------------------------------ */
+/* Function: ip_pool_destroy */
+/* Returns: int - 0 = success, else error */
+/* Parameters: op(I) - information about the pool to remove */
+/* Locks: WRITE(ip_poolrw) or WRITE(ipf_global) */
+/* */
+/* Search for a pool using paramters passed in and if it's not otherwise */
+/* busy, free it. */
+/* */
+/* NOTE: Because this function is called out of ipldetach() where ip_poolrw */
+/* may not be initialised, we can't use an ASSERT to enforce the locking */
+/* assertion that one of the two (ip_poolrw,ipf_global) is held. */
+/* ------------------------------------------------------------------------ */
+int ip_pool_destroy(op)
+iplookupop_t *op;
+{
+ ip_pool_t *ipo;
+
+ ipo = ip_pool_find(op->iplo_unit, op->iplo_name);
+ if (ipo == NULL)
+ return ESRCH;
+
+ if (ipo->ipo_ref != 1)
+ return EBUSY;
+
+ ip_pool_free(ipo);
+ return 0;
+}
+
+
+/* ------------------------------------------------------------------------ */
+/* Function: ip_pool_flush */
+/* Returns: int - number of pools deleted */
+/* Parameters: fp(I) - which pool(s) to flush */
+/* Locks: WRITE(ip_poolrw) or WRITE(ipf_global) */
+/* */
+/* Free all pools associated with the device that matches the unit number */
+/* passed in with operation. */
+/* */
+/* NOTE: Because this function is called out of ipldetach() where ip_poolrw */
+/* may not be initialised, we can't use an ASSERT to enforce the locking */
+/* assertion that one of the two (ip_poolrw,ipf_global) is held. */
+/* ------------------------------------------------------------------------ */
+int ip_pool_flush(fp)
+iplookupflush_t *fp;
+{
+ int i, num = 0, unit, err;
+ ip_pool_t *p, *q;
+ iplookupop_t op;
+
+ unit = fp->iplf_unit;
+
+ for (i = 0; i <= IPL_LOGMAX; i++) {
+ if (unit != IPLT_ALL && i != unit)
+ continue;
+ for (q = ip_pool_list[i]; (p = q) != NULL; ) {
+ op.iplo_unit = i;
+ (void)strncpy(op.iplo_name, p->ipo_name,
+ sizeof(op.iplo_name));
+ q = p->ipo_next;
+ err = ip_pool_destroy(&op);
+ if (err == 0)
+ num++;
+ else
+ break;
+ }
+ }
+ return num;
+}
+
+
+/* ------------------------------------------------------------------------ */
+/* Function: ip_pool_free */
+/* Returns: void */
+/* Parameters: ipo(I) - pointer to pool structure */
+/* Locks: WRITE(ip_poolrw) or WRITE(ipf_global) */
+/* */
+/* Deletes the pool strucutre passed in from the list of pools and deletes */
+/* all of the address information stored in it, including any tree data */
+/* structures also allocated. */
+/* */
+/* NOTE: Because this function is called out of ipldetach() where ip_poolrw */
+/* may not be initialised, we can't use an ASSERT to enforce the locking */
+/* assertion that one of the two (ip_poolrw,ipf_global) is held. */
+/* ------------------------------------------------------------------------ */
+void ip_pool_free(ipo)
+ip_pool_t *ipo;
+{
+ ip_pool_node_t *n;
+
+ RADIX_NODE_HEAD_LOCK(ipo->ipo_head);
+ while ((n = ipo->ipo_list) != NULL) {
+ ipo->ipo_head->rnh_deladdr(&n->ipn_addr, &n->ipn_mask,
+ ipo->ipo_head);
+
+ *n->ipn_pnext = n->ipn_next;
+ if (n->ipn_next)
+ n->ipn_next->ipn_pnext = n->ipn_pnext;
+
+ KFREE(n);
+
+ ipoolstat.ipls_nodes--;
+ }
+ RADIX_NODE_HEAD_UNLOCK(ipo->ipo_head);
+
+ ipo->ipo_list = NULL;
+ if (ipo->ipo_next != NULL)
+ ipo->ipo_next->ipo_pnext = ipo->ipo_pnext;
+ *ipo->ipo_pnext = ipo->ipo_next;
+ rn_freehead(ipo->ipo_head);
+ KFREE(ipo);
+
+ ipoolstat.ipls_pools--;
+}
+
+
+/* ------------------------------------------------------------------------ */
+/* Function: ip_pool_deref */
+/* Returns: void */
+/* Parameters: ipo(I) - pointer to pool structure */
+/* Locks: WRITE(ip_poolrw) */
+/* */
+/* Drop the number of known references to this pool structure by one and if */
+/* we arrive at zero known references, free it. */
+/* ------------------------------------------------------------------------ */
+void ip_pool_deref(ipo)
+ip_pool_t *ipo;
+{
+
+ ASSERT(rw_read_locked(&ip_poolrw.ipf_lk) == 0);
+
+ ipo->ipo_ref--;
+ if (ipo->ipo_ref == 0)
+ ip_pool_free(ipo);
+}
+
+
+# if defined(_KERNEL) && ((BSD >= 198911) && !defined(__osf__) && \
+ !defined(__hpux) && !defined(__sgi))
+static int
+rn_freenode(struct radix_node *n, void *p)
+{
+ struct radix_node_head *rnh = p;
+ struct radix_node *d;
+
+ d = rnh->rnh_deladdr(n->rn_key, NULL, rnh);
+ if (d != NULL) {
+ FreeS(d, max_keylen + 2 * sizeof (*d));
+ }
+ return 0;
+}
+
+
+void
+rn_freehead(rnh)
+ struct radix_node_head *rnh;
+{
+
+ RADIX_NODE_HEAD_LOCK(rnh);
+ (*rnh->rnh_walktree)(rnh, rn_freenode, rnh);
+
+ rnh->rnh_addaddr = NULL;
+ rnh->rnh_deladdr = NULL;
+ rnh->rnh_matchaddr = NULL;
+ rnh->rnh_lookup = NULL;
+ rnh->rnh_walktree = NULL;
+ RADIX_NODE_HEAD_UNLOCK(rnh);
+
+ Free(rnh);
+}
+# endif
+
+#endif /* IPFILTER_LOOKUP */
diff --git a/contrib/ipfilter/ip_pool.h b/contrib/ipfilter/ip_pool.h
new file mode 100644
index 0000000..3e3c073
--- /dev/null
+++ b/contrib/ipfilter/ip_pool.h
@@ -0,0 +1,87 @@
+/* $NetBSD$ */
+
+/*
+ * Copyright (C) 1993-2001, 2003 by Darren Reed.
+ *
+ * See the IPFILTER.LICENCE file for details on licencing.
+ *
+ * Id: ip_pool.h,v 2.26.2.2 2004/03/23 12:44:34 darrenr Exp
+ */
+
+#ifndef __IP_POOL_H__
+#define __IP_POOL_H__
+
+#if defined(_KERNEL) && !defined(__osf__) && !defined(__hpux) && \
+ !defined(linux) && !defined(sun)
+# include <net/radix.h>
+extern void rn_freehead __P((struct radix_node_head *));
+# define FreeS(p, z) KFREES(p, z)
+extern int max_keylen;
+#else
+# if defined(__osf__) || defined(__hpux)
+# include "radix_ipf_local.h"
+# define radix_mask ipf_radix_mask
+# define radix_node ipf_radix_node
+# define radix_node_head ipf_radix_node_head
+# else
+# include "radix_ipf.h"
+# endif
+#endif
+#include "netinet/ip_lookup.h"
+
+#define IP_POOL_NOMATCH 0
+#define IP_POOL_POSITIVE 1
+
+typedef struct ip_pool_node {
+ struct radix_node ipn_nodes[2];
+ addrfamily_t ipn_addr;
+ addrfamily_t ipn_mask;
+ int ipn_info;
+ char ipn_name[FR_GROUPLEN];
+ u_long ipn_hits;
+ struct ip_pool_node *ipn_next, **ipn_pnext;
+} ip_pool_node_t;
+
+
+typedef struct ip_pool_s {
+ struct ip_pool_s *ipo_next;
+ struct ip_pool_s **ipo_pnext;
+ struct radix_node_head *ipo_head;
+ ip_pool_node_t *ipo_list;
+ u_long ipo_hits;
+ int ipo_unit;
+ int ipo_flags;
+ int ipo_ref;
+ char ipo_name[FR_GROUPLEN];
+} ip_pool_t;
+
+#define IPOOL_ANON 0x80000000
+
+
+typedef struct ip_pool_stat {
+ u_long ipls_pools;
+ u_long ipls_tables;
+ u_long ipls_nodes;
+ ip_pool_t *ipls_list[IPL_LOGSIZE];
+} ip_pool_stat_t;
+
+
+extern ip_pool_stat_t ipoolstat;
+extern ip_pool_t *ip_pool_list[IPL_LOGSIZE];
+
+extern int ip_pool_search __P((void *, int, void *));
+extern int ip_pool_init __P((void));
+extern void ip_pool_fini __P((void));
+extern int ip_pool_create __P((iplookupop_t *));
+extern int ip_pool_insert __P((ip_pool_t *, i6addr_t *, i6addr_t *, int));
+extern int ip_pool_remove __P((ip_pool_t *, ip_pool_node_t *));
+extern int ip_pool_destroy __P((iplookupop_t *));
+extern void ip_pool_free __P((ip_pool_t *));
+extern void ip_pool_deref __P((ip_pool_t *));
+extern void *ip_pool_find __P((int, char *));
+extern ip_pool_node_t *ip_pool_findeq __P((ip_pool_t *,
+ addrfamily_t *, addrfamily_t *));
+extern int ip_pool_flush __P((iplookupflush_t *));
+extern int ip_pool_statistics __P((iplookupop_t *));
+
+#endif /* __IP_POOL_H__ */
diff --git a/contrib/ipfilter/ip_pptp_pxy.c b/contrib/ipfilter/ip_pptp_pxy.c
new file mode 100644
index 0000000..2511a17
--- /dev/null
+++ b/contrib/ipfilter/ip_pptp_pxy.c
@@ -0,0 +1,527 @@
+/* $NetBSD$ */
+
+/*
+ * Copyright (C) 2002-2003 by Darren Reed
+ *
+ * Simple PPTP transparent proxy for in-kernel use. For use with the NAT
+ * code.
+ *
+ * Id: ip_pptp_pxy.c,v 2.10.2.9 2005/03/16 18:17:34 darrenr Exp
+ *
+ */
+#define IPF_PPTP_PROXY
+
+typedef struct pptp_hdr {
+ u_short pptph_len;
+ u_short pptph_type;
+ u_32_t pptph_cookie;
+} pptp_hdr_t;
+
+#define PPTP_MSGTYPE_CTL 1
+#define PPTP_MTCTL_STARTREQ 1
+#define PPTP_MTCTL_STARTREP 2
+#define PPTP_MTCTL_STOPREQ 3
+#define PPTP_MTCTL_STOPREP 4
+#define PPTP_MTCTL_ECHOREQ 5
+#define PPTP_MTCTL_ECHOREP 6
+#define PPTP_MTCTL_OUTREQ 7
+#define PPTP_MTCTL_OUTREP 8
+#define PPTP_MTCTL_INREQ 9
+#define PPTP_MTCTL_INREP 10
+#define PPTP_MTCTL_INCONNECT 11
+#define PPTP_MTCTL_CLEAR 12
+#define PPTP_MTCTL_DISCONNECT 13
+#define PPTP_MTCTL_WANERROR 14
+#define PPTP_MTCTL_LINKINFO 15
+
+
+int ippr_pptp_init __P((void));
+void ippr_pptp_fini __P((void));
+int ippr_pptp_new __P((fr_info_t *, ap_session_t *, nat_t *));
+void ippr_pptp_del __P((ap_session_t *));
+int ippr_pptp_inout __P((fr_info_t *, ap_session_t *, nat_t *));
+void ippr_pptp_donatstate __P((fr_info_t *, nat_t *, pptp_pxy_t *));
+int ippr_pptp_message __P((fr_info_t *, nat_t *, pptp_pxy_t *, pptp_side_t *));
+int ippr_pptp_nextmessage __P((fr_info_t *, nat_t *, pptp_pxy_t *, int));
+int ippr_pptp_mctl __P((fr_info_t *, nat_t *, pptp_pxy_t *, pptp_side_t *));
+
+static frentry_t pptpfr;
+
+int pptp_proxy_init = 0;
+int ippr_pptp_debug = 0;
+int ippr_pptp_gretimeout = IPF_TTLVAL(120); /* 2 minutes */
+
+
+/*
+ * PPTP application proxy initialization.
+ */
+int ippr_pptp_init()
+{
+ bzero((char *)&pptpfr, sizeof(pptpfr));
+ pptpfr.fr_ref = 1;
+ pptpfr.fr_age[0] = ippr_pptp_gretimeout;
+ pptpfr.fr_age[1] = ippr_pptp_gretimeout;
+ pptpfr.fr_flags = FR_OUTQUE|FR_PASS|FR_QUICK|FR_KEEPSTATE;
+ MUTEX_INIT(&pptpfr.fr_lock, "PPTP proxy rule lock");
+ pptp_proxy_init = 1;
+
+ return 0;
+}
+
+
+void ippr_pptp_fini()
+{
+ if (pptp_proxy_init == 1) {
+ MUTEX_DESTROY(&pptpfr.fr_lock);
+ pptp_proxy_init = 0;
+ }
+}
+
+
+/*
+ * Setup for a new PPTP proxy.
+ */
+int ippr_pptp_new(fin, aps, nat)
+fr_info_t *fin;
+ap_session_t *aps;
+nat_t *nat;
+{
+ pptp_pxy_t *pptp;
+ ipnat_t *ipn;
+ ip_t *ip;
+ int off;
+
+ ip = fin->fin_ip;
+ off = fin->fin_hlen + sizeof(udphdr_t);
+
+ if (nat_outlookup(fin, 0, IPPROTO_GRE, nat->nat_inip,
+ ip->ip_dst) != NULL) {
+ if (ippr_pptp_debug > 0)
+ printf("ippr_pptp_new: GRE session already exists\n");
+ return -1;
+ }
+
+ aps->aps_psiz = sizeof(*pptp);
+ KMALLOCS(aps->aps_data, pptp_pxy_t *, sizeof(*pptp));
+ if (aps->aps_data == NULL) {
+ if (ippr_pptp_debug > 0)
+ printf("ippr_pptp_new: malloc for aps_data failed\n");
+ return -1;
+ }
+
+ /*
+ * Create NAT rule against which the tunnel/transport mapping is
+ * created. This is required because the current NAT rule does not
+ * describe GRE but TCP instead.
+ */
+ pptp = aps->aps_data;
+ bzero((char *)pptp, sizeof(*pptp));
+ ipn = &pptp->pptp_rule;
+ ipn->in_ifps[0] = fin->fin_ifp;
+ ipn->in_apr = NULL;
+ ipn->in_use = 1;
+ ipn->in_hits = 1;
+ ipn->in_ippip = 1;
+ if (nat->nat_dir == NAT_OUTBOUND) {
+ ipn->in_nip = ntohl(nat->nat_outip.s_addr);
+ ipn->in_outip = fin->fin_saddr;
+ ipn->in_redir = NAT_MAP;
+ } else if (nat->nat_dir == NAT_INBOUND) {
+ ipn->in_nip = 0;
+ ipn->in_outip = nat->nat_outip.s_addr;
+ ipn->in_redir = NAT_REDIRECT;
+ }
+ ipn->in_inip = nat->nat_inip.s_addr;
+ ipn->in_inmsk = 0xffffffff;
+ ipn->in_outmsk = 0xffffffff;
+ ipn->in_srcip = fin->fin_saddr;
+ ipn->in_srcmsk = 0xffffffff;
+ bcopy(nat->nat_ptr->in_ifnames[0], ipn->in_ifnames[0],
+ sizeof(ipn->in_ifnames[0]));
+ ipn->in_p = IPPROTO_GRE;
+
+ pptp->pptp_side[0].pptps_wptr = pptp->pptp_side[0].pptps_buffer;
+ pptp->pptp_side[1].pptps_wptr = pptp->pptp_side[1].pptps_buffer;
+ return 0;
+}
+
+
+void ippr_pptp_donatstate(fin, nat, pptp)
+fr_info_t *fin;
+nat_t *nat;
+pptp_pxy_t *pptp;
+{
+ fr_info_t fi;
+ grehdr_t gre;
+ nat_t *nat2;
+ u_char p;
+ ip_t *ip;
+
+ ip = fin->fin_ip;
+ p = ip->ip_p;
+
+ nat2 = pptp->pptp_nat;
+ if ((nat2 == NULL) || (pptp->pptp_state == NULL)) {
+ bcopy((char *)fin, (char *)&fi, sizeof(fi));
+ bzero((char *)&gre, sizeof(gre));
+ fi.fin_state = NULL;
+ fi.fin_nat = NULL;
+ fi.fin_fi.fi_p = IPPROTO_GRE;
+ fi.fin_fr = &pptpfr;
+ if ((nat->nat_dir == NAT_OUTBOUND && fin->fin_out) ||
+ (nat->nat_dir == NAT_INBOUND && !fin->fin_out)) {
+ fi.fin_data[0] = pptp->pptp_call[0];
+ fi.fin_data[1] = pptp->pptp_call[1];
+ } else {
+ fi.fin_data[0] = pptp->pptp_call[1];
+ fi.fin_data[1] = pptp->pptp_call[0];
+ }
+ ip = fin->fin_ip;
+ ip->ip_p = IPPROTO_GRE;
+ fi.fin_flx &= ~(FI_TCPUDP|FI_STATE|FI_FRAG);
+ fi.fin_flx |= FI_IGNORE;
+ fi.fin_dp = &gre;
+ gre.gr_flags = htons(1 << 13);
+ if (fin->fin_out && nat->nat_dir == NAT_INBOUND) {
+ fi.fin_fi.fi_saddr = fin->fin_fi.fi_daddr;
+ fi.fin_fi.fi_daddr = nat->nat_outip.s_addr;
+ } else if (!fin->fin_out && nat->nat_dir == NAT_OUTBOUND) {
+ fi.fin_fi.fi_saddr = nat->nat_inip.s_addr;
+ fi.fin_fi.fi_daddr = fin->fin_fi.fi_saddr;
+ }
+ }
+
+ /*
+ * Update NAT timeout/create NAT if missing.
+ */
+ if (nat2 != NULL)
+ fr_queueback(&nat2->nat_tqe);
+ else {
+ nat2 = nat_new(&fi, &pptp->pptp_rule, &pptp->pptp_nat,
+ NAT_SLAVE, nat->nat_dir);
+ pptp->pptp_nat = nat2;
+ if (nat2 != NULL) {
+ (void) nat_proto(&fi, nat2, 0);
+ nat_update(&fi, nat2, nat2->nat_ptr);
+ }
+ }
+
+ READ_ENTER(&ipf_state);
+ if (pptp->pptp_state != NULL) {
+ fr_queueback(&pptp->pptp_state->is_sti);
+ RWLOCK_EXIT(&ipf_state);
+ } else {
+ RWLOCK_EXIT(&ipf_state);
+ if (nat->nat_dir == NAT_INBOUND)
+ fi.fin_fi.fi_daddr = nat2->nat_inip.s_addr;
+ else
+ fi.fin_fi.fi_saddr = nat2->nat_inip.s_addr;
+ fi.fin_ifp = NULL;
+ pptp->pptp_state = fr_addstate(&fi, &pptp->pptp_state,
+ 0);
+ if (fi.fin_state != NULL)
+ fr_statederef(&fi, (ipstate_t **)&fi.fin_state);
+ }
+ ip->ip_p = p;
+ return;
+}
+
+
+/*
+ * Try and build up the next PPTP message in the TCP stream and if we can
+ * build it up completely (fits in our buffer) then pass it off to the message
+ * parsing function.
+ */
+int ippr_pptp_nextmessage(fin, nat, pptp, rev)
+fr_info_t *fin;
+nat_t *nat;
+pptp_pxy_t *pptp;
+int rev;
+{
+ static char *funcname = "ippr_pptp_nextmessage";
+ pptp_side_t *pptps;
+ u_32_t start, end;
+ pptp_hdr_t *hdr;
+ tcphdr_t *tcp;
+ int dlen, off;
+ u_short len;
+ char *msg;
+
+ tcp = fin->fin_dp;
+ dlen = fin->fin_dlen - (TCP_OFF(tcp) << 2);
+ start = ntohl(tcp->th_seq);
+ pptps = &pptp->pptp_side[rev];
+ off = (char *)tcp - (char *)fin->fin_ip + (TCP_OFF(tcp) << 2) +
+ fin->fin_ipoff;
+
+ if (dlen <= 0)
+ return 0;
+ /*
+ * If the complete data packet is before what we expect to see
+ * "next", just ignore it as the chances are we've already seen it.
+ * The next if statement following this one really just causes packets
+ * ahead of what we've seen to be dropped, implying that something in
+ * the middle went missing and we want to see that first.
+ */
+ end = start + dlen;
+ if (pptps->pptps_next > end && pptps->pptps_next > start)
+ return 0;
+
+ if (pptps->pptps_next != start) {
+ if (ippr_pptp_debug > 5)
+ printf("%s: next (%x) != start (%x)\n", funcname,
+ pptps->pptps_next, start);
+ return -1;
+ }
+
+ msg = (char *)fin->fin_dp + (TCP_OFF(tcp) << 2);
+
+ while (dlen > 0) {
+ off += pptps->pptps_bytes;
+ if (pptps->pptps_gothdr == 0) {
+ /*
+ * PPTP has an 8 byte header that inclues the cookie.
+ * The start of every message should include one and
+ * it should match 1a2b3c4d. Byte order is ignored,
+ * deliberately, when printing out the error.
+ */
+ len = MIN(8 - pptps->pptps_bytes, dlen);
+ COPYDATA(fin->fin_m, off, len, pptps->pptps_wptr);
+ pptps->pptps_bytes += len;
+ pptps->pptps_wptr += len;
+ hdr = (pptp_hdr_t *)pptps->pptps_buffer;
+ if (pptps->pptps_bytes == 8) {
+ pptps->pptps_next += 8;
+ if (ntohl(hdr->pptph_cookie) != 0x1a2b3c4d) {
+ if (ippr_pptp_debug > 1)
+ printf("%s: bad cookie (%x)\n",
+ funcname,
+ hdr->pptph_cookie);
+ return -1;
+ }
+ }
+ dlen -= len;
+ msg += len;
+ off += len;
+
+ pptps->pptps_gothdr = 1;
+ len = ntohs(hdr->pptph_len);
+ pptps->pptps_len = len;
+ pptps->pptps_nexthdr += len;
+
+ /*
+ * If a message is too big for the buffer, just set
+ * the fields for the next message to come along.
+ * The messages defined in RFC 2637 will not exceed
+ * 512 bytes (in total length) so this is likely a
+ * bad data packet, anyway.
+ */
+ if (len > sizeof(pptps->pptps_buffer)) {
+ if (ippr_pptp_debug > 3)
+ printf("%s: message too big (%d)\n",
+ funcname, len);
+ pptps->pptps_next = pptps->pptps_nexthdr;
+ pptps->pptps_wptr = pptps->pptps_buffer;
+ pptps->pptps_gothdr = 0;
+ pptps->pptps_bytes = 0;
+ pptps->pptps_len = 0;
+ break;
+ }
+ }
+
+ len = MIN(pptps->pptps_len - pptps->pptps_bytes, dlen);
+ COPYDATA(fin->fin_m, off, len, pptps->pptps_wptr);
+ pptps->pptps_bytes += len;
+ pptps->pptps_wptr += len;
+ pptps->pptps_next += len;
+
+ if (pptps->pptps_len > pptps->pptps_bytes)
+ break;
+
+ ippr_pptp_message(fin, nat, pptp, pptps);
+ pptps->pptps_wptr = pptps->pptps_buffer;
+ pptps->pptps_gothdr = 0;
+ pptps->pptps_bytes = 0;
+ pptps->pptps_len = 0;
+
+ start += len;
+ msg += len;
+ dlen -= len;
+ }
+
+ return 0;
+}
+
+
+/*
+ * handle a complete PPTP message
+ */
+int ippr_pptp_message(fin, nat, pptp, pptps)
+fr_info_t *fin;
+nat_t *nat;
+pptp_pxy_t *pptp;
+pptp_side_t *pptps;
+{
+ pptp_hdr_t *hdr = (pptp_hdr_t *)pptps->pptps_buffer;
+
+ switch (ntohs(hdr->pptph_type))
+ {
+ case PPTP_MSGTYPE_CTL :
+ ippr_pptp_mctl(fin, nat, pptp, pptps);
+ break;
+
+ default :
+ break;
+ }
+ return 0;
+}
+
+
+/*
+ * handle a complete PPTP control message
+ */
+int ippr_pptp_mctl(fin, nat, pptp, pptps)
+fr_info_t *fin;
+nat_t *nat;
+pptp_pxy_t *pptp;
+pptp_side_t *pptps;
+{
+ u_short *buffer = (u_short *)(pptps->pptps_buffer);
+ pptp_side_t *pptpo;
+
+ if (pptps == &pptp->pptp_side[0])
+ pptpo = &pptp->pptp_side[1];
+ else
+ pptpo = &pptp->pptp_side[0];
+
+ /*
+ * Breakout to handle all the various messages. Most are just state
+ * transition.
+ */
+ switch (ntohs(buffer[4]))
+ {
+ case PPTP_MTCTL_STARTREQ :
+ pptps->pptps_state = PPTP_MTCTL_STARTREQ;
+ break;
+ case PPTP_MTCTL_STARTREP :
+ if (pptpo->pptps_state == PPTP_MTCTL_STARTREQ)
+ pptps->pptps_state = PPTP_MTCTL_STARTREP;
+ break;
+ case PPTP_MTCTL_STOPREQ :
+ pptps->pptps_state = PPTP_MTCTL_STOPREQ;
+ break;
+ case PPTP_MTCTL_STOPREP :
+ if (pptpo->pptps_state == PPTP_MTCTL_STOPREQ)
+ pptps->pptps_state = PPTP_MTCTL_STOPREP;
+ break;
+ case PPTP_MTCTL_ECHOREQ :
+ pptps->pptps_state = PPTP_MTCTL_ECHOREQ;
+ break;
+ case PPTP_MTCTL_ECHOREP :
+ if (pptpo->pptps_state == PPTP_MTCTL_ECHOREQ)
+ pptps->pptps_state = PPTP_MTCTL_ECHOREP;
+ break;
+ case PPTP_MTCTL_OUTREQ :
+ pptps->pptps_state = PPTP_MTCTL_OUTREQ;
+ break;
+ case PPTP_MTCTL_OUTREP :
+ if (pptpo->pptps_state == PPTP_MTCTL_OUTREQ) {
+ pptps->pptps_state = PPTP_MTCTL_OUTREP;
+ pptp->pptp_call[0] = buffer[7];
+ pptp->pptp_call[1] = buffer[6];
+ ippr_pptp_donatstate(fin, nat, pptp);
+ }
+ break;
+ case PPTP_MTCTL_INREQ :
+ pptps->pptps_state = PPTP_MTCTL_INREQ;
+ break;
+ case PPTP_MTCTL_INREP :
+ if (pptpo->pptps_state == PPTP_MTCTL_INREQ) {
+ pptps->pptps_state = PPTP_MTCTL_INREP;
+ pptp->pptp_call[0] = buffer[7];
+ pptp->pptp_call[1] = buffer[6];
+ ippr_pptp_donatstate(fin, nat, pptp);
+ }
+ break;
+ case PPTP_MTCTL_INCONNECT :
+ pptps->pptps_state = PPTP_MTCTL_INCONNECT;
+ break;
+ case PPTP_MTCTL_CLEAR :
+ pptps->pptps_state = PPTP_MTCTL_CLEAR;
+ break;
+ case PPTP_MTCTL_DISCONNECT :
+ pptps->pptps_state = PPTP_MTCTL_DISCONNECT;
+ break;
+ case PPTP_MTCTL_WANERROR :
+ pptps->pptps_state = PPTP_MTCTL_WANERROR;
+ break;
+ case PPTP_MTCTL_LINKINFO :
+ pptps->pptps_state = PPTP_MTCTL_LINKINFO;
+ break;
+ }
+
+ return 0;
+}
+
+
+/*
+ * For outgoing PPTP packets. refresh timeouts for NAT & state entries, if
+ * we can. If they have disappeared, recreate them.
+ */
+int ippr_pptp_inout(fin, aps, nat)
+fr_info_t *fin;
+ap_session_t *aps;
+nat_t *nat;
+{
+ pptp_pxy_t *pptp;
+ tcphdr_t *tcp;
+ int rev;
+
+ if ((fin->fin_out == 1) && (nat->nat_dir == NAT_INBOUND))
+ rev = 1;
+ else if ((fin->fin_out == 0) && (nat->nat_dir == NAT_OUTBOUND))
+ rev = 1;
+ else
+ rev = 0;
+
+ tcp = (tcphdr_t *)fin->fin_dp;
+ if ((tcp->th_flags & TH_OPENING) == TH_OPENING) {
+ pptp = (pptp_pxy_t *)aps->aps_data;
+ pptp->pptp_side[1 - rev].pptps_next = ntohl(tcp->th_ack);
+ pptp->pptp_side[1 - rev].pptps_nexthdr = ntohl(tcp->th_ack);
+ pptp->pptp_side[rev].pptps_next = ntohl(tcp->th_seq) + 1;
+ pptp->pptp_side[rev].pptps_nexthdr = ntohl(tcp->th_seq) + 1;
+ }
+ return ippr_pptp_nextmessage(fin, nat, (pptp_pxy_t *)aps->aps_data,
+ rev);
+}
+
+
+/*
+ * clean up after ourselves.
+ */
+void ippr_pptp_del(aps)
+ap_session_t *aps;
+{
+ pptp_pxy_t *pptp;
+
+ pptp = aps->aps_data;
+
+ if (pptp != NULL) {
+ /*
+ * Don't bother changing any of the NAT structure details,
+ * *_del() is on a callback from aps_free(), from nat_delete()
+ */
+
+ READ_ENTER(&ipf_state);
+ if (pptp->pptp_state != NULL) {
+ pptp->pptp_state->is_die = fr_ticks + 1;
+ pptp->pptp_state->is_me = NULL;
+ fr_queuefront(&pptp->pptp_state->is_sti);
+ }
+ RWLOCK_EXIT(&ipf_state);
+
+ pptp->pptp_state = NULL;
+ pptp->pptp_nat = NULL;
+ }
+}
diff --git a/contrib/ipfilter/ip_rpcb_pxy.c b/contrib/ipfilter/ip_rpcb_pxy.c
new file mode 100644
index 0000000..5d0a1ee
--- /dev/null
+++ b/contrib/ipfilter/ip_rpcb_pxy.c
@@ -0,0 +1,1460 @@
+/* $NetBSD$ */
+
+/*
+ * Copyright (C) 2002-2003 by Ryan Beasley <ryanb@goddamnbastard.org>
+ *
+ * See the IPFILTER.LICENCE file for details on licencing.
+ */
+/*
+ * Overview:
+ * This is an in-kernel application proxy for Sun's RPCBIND (nee portmap)
+ * protocol as defined in RFC1833. It is far from complete, mostly
+ * lacking in less-likely corner cases, but it's definitely functional.
+ *
+ * Invocation:
+ * rdr <int> <e_ip>/32 port <e_p> -> <i_ip> port <i_p> udp proxy rpcbu
+ *
+ * If the host running IP Filter is the same as the RPC server, it's
+ * perfectly legal for both the internal and external addresses and ports
+ * to match.
+ *
+ * When triggered by appropriate IP NAT rules, this proxy works by
+ * examining data contained in received packets. Requests and replies are
+ * modified, NAT and state table entries created, etc., as necessary.
+ */
+/*
+ * TODO / NOTES
+ *
+ * o Must implement locking to protect proxy session data.
+ * o Fragmentation isn't supported.
+ * o Only supports UDP.
+ * o Doesn't support multiple RPC records in a single request.
+ * o Errors should be more fine-grained. (e.g., malloc failure vs.
+ * illegal RPCB request / reply)
+ * o Even with the limit on the total amount of recorded transactions,
+ * should there be a timeout on transaction removal?
+ * o There is a potential collision between cloning, wildcard NAT and
+ * state entries. There should be an appr_getport routine for
+ * to avoid this.
+ * o The enclosed hack of STREAMS support is pretty sick and most likely
+ * broken.
+ *
+ * Id: ip_rpcb_pxy.c,v 2.25.2.3 2005/02/04 10:22:56 darrenr Exp
+ */
+
+#define IPF_RPCB_PROXY
+
+/*
+ * Function prototypes
+ */
+int ippr_rpcb_init __P((void));
+void ippr_rpcb_fini __P((void));
+int ippr_rpcb_new __P((fr_info_t *, ap_session_t *, nat_t *));
+void ippr_rpcb_del __P((ap_session_t *));
+int ippr_rpcb_in __P((fr_info_t *, ap_session_t *, nat_t *));
+int ippr_rpcb_out __P((fr_info_t *, ap_session_t *, nat_t *));
+
+static void ippr_rpcb_flush __P((rpcb_session_t *));
+static int ippr_rpcb_decodereq __P((fr_info_t *, nat_t *,
+ rpcb_session_t *, rpc_msg_t *));
+static int ippr_rpcb_skipauth __P((rpc_msg_t *, xdr_auth_t *, u_32_t **));
+static int ippr_rpcb_insert __P((rpcb_session_t *, rpcb_xact_t *));
+static int ippr_rpcb_xdrrpcb __P((rpc_msg_t *, u_32_t *, rpcb_args_t *));
+static int ippr_rpcb_getuaddr __P((rpc_msg_t *, xdr_uaddr_t *,
+ u_32_t **));
+static u_int ippr_rpcb_atoi __P((char *));
+static int ippr_rpcb_modreq __P((fr_info_t *, nat_t *, rpc_msg_t *,
+ mb_t *, u_int));
+static int ippr_rpcb_decoderep __P((fr_info_t *, nat_t *,
+ rpcb_session_t *, rpc_msg_t *, rpcb_xact_t **));
+static rpcb_xact_t * ippr_rpcb_lookup __P((rpcb_session_t *, u_32_t));
+static void ippr_rpcb_deref __P((rpcb_session_t *, rpcb_xact_t *));
+static int ippr_rpcb_getproto __P((rpc_msg_t *, xdr_proto_t *,
+ u_32_t **));
+static int ippr_rpcb_getnat __P((fr_info_t *, nat_t *, u_int, u_int));
+static int ippr_rpcb_modv3 __P((fr_info_t *, nat_t *, rpc_msg_t *,
+ mb_t *, u_int));
+static int ippr_rpcb_modv4 __P((fr_info_t *, nat_t *, rpc_msg_t *,
+ mb_t *, u_int));
+static void ippr_rpcb_fixlen __P((fr_info_t *, int));
+
+/*
+ * Global variables
+ */
+static frentry_t rpcbfr; /* Skeleton rule for reference by entities
+ this proxy creates. */
+static int rpcbcnt; /* Upper bound of allocated RPCB sessions. */
+ /* XXX rpcbcnt still requires locking. */
+
+int rpcb_proxy_init = 0;
+
+
+/*
+ * Since rpc_msg contains only pointers, one should use this macro as a
+ * handy way to get to the goods. (In case you're wondering about the name,
+ * this started as BYTEREF -> BREF -> B.)
+ */
+#define B(r) (u_32_t)ntohl(*(r))
+
+/*
+ * Public subroutines
+ */
+
+/* -------------------------------------------------------------------- */
+/* Function: ippr_rpcb_init */
+/* Returns: int - 0 == success */
+/* Parameters: (void) */
+/* */
+/* Initialize the filter rule entry and session limiter. */
+/* -------------------------------------------------------------------- */
+int
+ippr_rpcb_init()
+{
+ rpcbcnt = 0;
+
+ bzero((char *)&rpcbfr, sizeof(rpcbfr));
+ rpcbfr.fr_ref = 1;
+ rpcbfr.fr_flags = FR_PASS|FR_QUICK|FR_KEEPSTATE;
+ MUTEX_INIT(&rpcbfr.fr_lock, "ipf Sun RPCB proxy rule lock");
+ rpcb_proxy_init = 1;
+
+ return(0);
+}
+
+/* -------------------------------------------------------------------- */
+/* Function: ippr_rpcb_fini */
+/* Returns: void */
+/* Parameters: (void) */
+/* */
+/* Destroy rpcbfr's mutex to avoid a lock leak. */
+/* -------------------------------------------------------------------- */
+void
+ippr_rpcb_fini()
+{
+ if (rpcb_proxy_init == 1) {
+ MUTEX_DESTROY(&rpcbfr.fr_lock);
+ rpcb_proxy_init = 0;
+ }
+}
+
+/* -------------------------------------------------------------------- */
+/* Function: ippr_rpcb_new */
+/* Returns: int - -1 == failure, 0 == success */
+/* Parameters: fin(I) - pointer to packet information */
+/* aps(I) - pointer to proxy session structure */
+/* nat(I) - pointer to NAT session structure */
+/* */
+/* Allocate resources for per-session proxy structures. */
+/* -------------------------------------------------------------------- */
+int
+ippr_rpcb_new(fin, aps, nat)
+ fr_info_t *fin;
+ ap_session_t *aps;
+ nat_t *nat;
+{
+ rpcb_session_t *rs;
+
+ fin = fin; /* LINT */
+ nat = nat; /* LINT */
+
+ KMALLOC(rs, rpcb_session_t *);
+ if (rs == NULL)
+ return(-1);
+
+ bzero((char *)rs, sizeof(*rs));
+ MUTEX_INIT(&rs->rs_rxlock, "ipf Sun RPCB proxy session lock");
+
+ aps->aps_data = rs;
+
+ return(0);
+}
+
+/* -------------------------------------------------------------------- */
+/* Function: ippr_rpcb_del */
+/* Returns: void */
+/* Parameters: aps(I) - pointer to proxy session structure */
+/* */
+/* Free up a session's list of RPCB requests. */
+/* -------------------------------------------------------------------- */
+void
+ippr_rpcb_del(aps)
+ ap_session_t *aps;
+{
+ rpcb_session_t *rs;
+ rs = (rpcb_session_t *)aps->aps_data;
+
+ MUTEX_ENTER(&rs->rs_rxlock);
+ ippr_rpcb_flush(rs);
+ MUTEX_EXIT(&rs->rs_rxlock);
+ MUTEX_DESTROY(&rs->rs_rxlock);
+}
+
+/* -------------------------------------------------------------------- */
+/* Function: ippr_rpcb_in */
+/* Returns: int - APR_ERR(1) == drop the packet, */
+/* APR_ERR(2) == kill the proxy session, */
+/* else change in packet length (in bytes) */
+/* Parameters: fin(I) - pointer to packet information */
+/* ip(I) - pointer to packet header */
+/* aps(I) - pointer to proxy session structure */
+/* nat(I) - pointer to NAT session structure */
+/* */
+/* Given a presumed RPCB request, perform some minor tests and pass off */
+/* for decoding. Also pass packet off for a rewrite if necessary. */
+/* -------------------------------------------------------------------- */
+int
+ippr_rpcb_in(fin, aps, nat)
+ fr_info_t *fin;
+ ap_session_t *aps;
+ nat_t *nat;
+{
+ rpc_msg_t rpcmsg, *rm;
+ rpcb_session_t *rs;
+ u_int off, dlen;
+ mb_t *m;
+ int rv;
+
+ /* Disallow fragmented or illegally short packets. */
+ if ((fin->fin_flx & (FI_FRAG|FI_SHORT)) != 0)
+ return(APR_ERR(1));
+
+ /* Perform basic variable initialization. */
+ rs = (rpcb_session_t *)aps->aps_data;
+
+ m = fin->fin_m;
+ off = (char *)fin->fin_dp - (char *)fin->fin_ip;
+ off += sizeof(udphdr_t) + fin->fin_ipoff;
+ dlen = fin->fin_dlen - sizeof(udphdr_t);
+
+ /* Disallow packets outside legal range for supported requests. */
+ if ((dlen < RPCB_REQMIN) || (dlen > RPCB_REQMAX))
+ return(APR_ERR(1));
+
+ /* Copy packet over to convenience buffer. */
+ rm = &rpcmsg;
+ bzero((char *)rm, sizeof(*rm));
+ COPYDATA(m, off, dlen, (caddr_t)&rm->rm_msgbuf);
+ rm->rm_buflen = dlen;
+
+ /* Send off to decode request. */
+ rv = ippr_rpcb_decodereq(fin, nat, rs, rm);
+
+ switch(rv)
+ {
+ case -1:
+ return(APR_ERR(1));
+ /*NOTREACHED*/
+ break;
+ case 0:
+ break;
+ case 1:
+ rv = ippr_rpcb_modreq(fin, nat, rm, m, off);
+ break;
+ default:
+ /*CONSTANTCONDITION*/
+ IPF_PANIC(1, ("illegal rv %d (ippr_rpcb_req)", rv));
+ }
+
+ return(rv);
+}
+
+/* -------------------------------------------------------------------- */
+/* Function: ippr_rpcb_out */
+/* Returns: int - APR_ERR(1) == drop the packet, */
+/* APR_ERR(2) == kill the proxy session, */
+/* else change in packet length (in bytes) */
+/* Parameters: fin(I) - pointer to packet information */
+/* ip(I) - pointer to packet header */
+/* aps(I) - pointer to proxy session structure */
+/* nat(I) - pointer to NAT session structure */
+/* */
+/* Given a presumed RPCB reply, perform some minor tests and pass off */
+/* for decoding. If the message indicates a successful request with */
+/* valid addressing information, create NAT and state structures to */
+/* allow direct communication between RPC client and server. */
+/* -------------------------------------------------------------------- */
+int
+ippr_rpcb_out(fin, aps, nat)
+ fr_info_t *fin;
+ ap_session_t *aps;
+ nat_t *nat;
+{
+ rpc_msg_t rpcmsg, *rm;
+ rpcb_session_t *rs;
+ rpcb_xact_t *rx;
+ u_int off, dlen;
+ int rv, diff;
+ mb_t *m;
+
+ /* Disallow fragmented or illegally short packets. */
+ if ((fin->fin_flx & (FI_FRAG|FI_SHORT)) != 0)
+ return(APR_ERR(1));
+
+ /* Perform basic variable initialization. */
+ rs = (rpcb_session_t *)aps->aps_data;
+
+ m = fin->fin_m;
+ off = (char *)fin->fin_dp - (char *)fin->fin_ip;
+ off += sizeof(udphdr_t) + fin->fin_ipoff;
+ dlen = fin->fin_dlen - sizeof(udphdr_t);
+ diff = 0;
+
+ /* Disallow packets outside legal range for supported requests. */
+ if ((dlen < RPCB_REPMIN) || (dlen > RPCB_REPMAX))
+ return(APR_ERR(1));
+
+ /* Copy packet over to convenience buffer. */
+ rm = &rpcmsg;
+ bzero((char *)rm, sizeof(*rm));
+ COPYDATA(m, off, dlen, (caddr_t)&rm->rm_msgbuf);
+ rm->rm_buflen = dlen;
+
+ /* Send off to decode reply. */
+ rv = ippr_rpcb_decoderep(fin, nat, rs, rm, &rx);
+
+ switch(rv)
+ {
+ case -1: /* Bad packet */
+ if (rx != NULL) {
+ MUTEX_ENTER(&rs->rs_rxlock);
+ ippr_rpcb_deref(rs, rx);
+ MUTEX_EXIT(&rs->rs_rxlock);
+ }
+ return(APR_ERR(1));
+ /*NOTREACHED*/
+ break;
+ case 0: /* Negative reply / request rejected */
+ break;
+ case 1: /* Positive reply */
+ /*
+ * With the IP address embedded in a GETADDR(LIST) reply,
+ * we'll need to rewrite the packet in the very possible
+ * event that the internal & external addresses aren't the
+ * same. (i.e., this box is either a router or rpcbind
+ * only listens on loopback.)
+ */
+ if (nat->nat_inip.s_addr != nat->nat_outip.s_addr) {
+ if (rx->rx_type == RPCB_RES_STRING)
+ diff = ippr_rpcb_modv3(fin, nat, rm, m, off);
+ else if (rx->rx_type == RPCB_RES_LIST)
+ diff = ippr_rpcb_modv4(fin, nat, rm, m, off);
+ }
+ break;
+ default:
+ /*CONSTANTCONDITION*/
+ IPF_PANIC(1, ("illegal rv %d (ippr_rpcb_decoderep)", rv));
+ }
+
+ if (rx != NULL) {
+ MUTEX_ENTER(&rs->rs_rxlock);
+ /* XXX Gross hack - I'm overloading the reference
+ * counter to deal with both threads and retransmitted
+ * requests. One deref signals that this thread is
+ * finished with rx, and the other signals that we've
+ * processed its reply.
+ */
+ ippr_rpcb_deref(rs, rx);
+ ippr_rpcb_deref(rs, rx);
+ MUTEX_EXIT(&rs->rs_rxlock);
+ }
+
+ return(diff);
+}
+
+/*
+ * Private support subroutines
+ */
+
+/* -------------------------------------------------------------------- */
+/* Function: ippr_rpcb_flush */
+/* Returns: void */
+/* Parameters: rs(I) - pointer to RPCB session structure */
+/* */
+/* Simply flushes the list of outstanding transactions, if any. */
+/* -------------------------------------------------------------------- */
+static void
+ippr_rpcb_flush(rs)
+ rpcb_session_t *rs;
+{
+ rpcb_xact_t *r1, *r2;
+
+ r1 = rs->rs_rxlist;
+ if (r1 == NULL)
+ return;
+
+ while (r1 != NULL) {
+ r2 = r1;
+ r1 = r1->rx_next;
+ KFREE(r2);
+ }
+}
+
+/* -------------------------------------------------------------------- */
+/* Function: ippr_rpcb_decodereq */
+/* Returns: int - -1 == bad request or critical failure, */
+/* 0 == request successfully decoded, */
+/* 1 == request successfully decoded; requires */
+/* address rewrite/modification */
+/* Parameters: fin(I) - pointer to packet information */
+/* nat(I) - pointer to NAT session structure */
+/* rs(I) - pointer to RPCB session structure */
+/* rm(I) - pointer to RPC message structure */
+/* */
+/* Take a presumed RPCB request, decode it, and store the results in */
+/* the transaction list. If the internal target address needs to be */
+/* modified, store its location in ptr. */
+/* WARNING: It's the responsibility of the caller to make sure there */
+/* is enough room in rs_buf for the basic RPC message "preamble". */
+/* -------------------------------------------------------------------- */
+static int
+ippr_rpcb_decodereq(fin, nat, rs, rm)
+ fr_info_t *fin;
+ nat_t *nat;
+ rpcb_session_t *rs;
+ rpc_msg_t *rm;
+{
+ rpcb_args_t *ra;
+ u_32_t xdr, *p;
+ rpc_call_t *rc;
+ rpcb_xact_t rx;
+ int mod;
+
+ p = (u_32_t *)rm->rm_msgbuf;
+ mod = 0;
+
+ bzero((char *)&rx, sizeof(rx));
+ rc = &rm->rm_call;
+
+ rm->rm_xid = p;
+ rx.rx_xid = B(p++); /* Record this message's XID. */
+
+ /* Parse out and test the RPC header. */
+ if ((B(p++) != RPCB_CALL) ||
+ (B(p++) != RPCB_MSG_VERSION) ||
+ (B(p++) != RPCB_PROG))
+ return(-1);
+
+ /* Record the RPCB version and procedure. */
+ rc->rc_vers = p++;
+ rc->rc_proc = p++;
+
+ /* Bypass RPC authentication stuff. */
+ if (ippr_rpcb_skipauth(rm, &rc->rc_authcred, &p) != 0)
+ return(-1);
+ if (ippr_rpcb_skipauth(rm, &rc->rc_authverf, &p) != 0)
+ return(-1);
+
+ /* Compare RPCB version and procedure numbers. */
+ switch(B(rc->rc_vers))
+ {
+ case 2:
+ /* This proxy only supports PMAP_GETPORT. */
+ if (B(rc->rc_proc) != RPCB_GETPORT)
+ return(-1);
+
+ /* Portmap requests contain four 4 byte parameters. */
+ if (RPCB_BUF_EQ(rm, p, 16) == 0)
+ return(-1);
+
+ p += 2; /* Skip requested program and version numbers. */
+
+ /* Sanity check the requested protocol. */
+ xdr = B(p);
+ if (!(xdr == IPPROTO_UDP || xdr == IPPROTO_TCP))
+ return(-1);
+
+ rx.rx_type = RPCB_RES_PMAP;
+ rx.rx_proto = xdr;
+ break;
+ case 3:
+ case 4:
+ /* GETADDRLIST is exclusive to v4; GETADDR for v3 & v4 */
+ switch(B(rc->rc_proc))
+ {
+ case RPCB_GETADDR:
+ rx.rx_type = RPCB_RES_STRING;
+ rx.rx_proto = (u_int)fin->fin_p;
+ break;
+ case RPCB_GETADDRLIST:
+ if (B(rc->rc_vers) != 4)
+ return(-1);
+ rx.rx_type = RPCB_RES_LIST;
+ break;
+ default:
+ return(-1);
+ }
+
+ ra = &rc->rc_rpcbargs;
+
+ /* Decode the 'struct rpcb' request. */
+ if (ippr_rpcb_xdrrpcb(rm, p, ra) != 0)
+ return(-1);
+
+ /* Are the target address & port valid? */
+ if ((ra->ra_maddr.xu_ip != nat->nat_outip.s_addr) ||
+ (ra->ra_maddr.xu_port != nat->nat_outport))
+ return(-1);
+
+ /* Do we need to rewrite this packet? */
+ if ((nat->nat_outip.s_addr != nat->nat_inip.s_addr) ||
+ (nat->nat_outport != nat->nat_inport))
+ mod = 1;
+ break;
+ default:
+ return(-1);
+ }
+
+ MUTEX_ENTER(&rs->rs_rxlock);
+ if (ippr_rpcb_insert(rs, &rx) != 0) {
+ MUTEX_EXIT(&rs->rs_rxlock);
+ return(-1);
+ }
+ MUTEX_EXIT(&rs->rs_rxlock);
+
+ return(mod);
+}
+
+/* -------------------------------------------------------------------- */
+/* Function: ippr_rpcb_skipauth */
+/* Returns: int -- -1 == illegal auth parameters (lengths) */
+/* 0 == valid parameters, pointer advanced */
+/* Parameters: rm(I) - pointer to RPC message structure */
+/* auth(I) - pointer to RPC auth structure */
+/* buf(IO) - pointer to location within convenience buffer */
+/* */
+/* Record auth data length & location of auth data, then advance past */
+/* it. */
+/* -------------------------------------------------------------------- */
+static int
+ippr_rpcb_skipauth(rm, auth, buf)
+ rpc_msg_t *rm;
+ xdr_auth_t *auth;
+ u_32_t **buf;
+{
+ u_32_t *p, xdr;
+
+ p = *buf;
+
+ /* Make sure we have enough space for expected fixed auth parms. */
+ if (RPCB_BUF_GEQ(rm, p, 8) == 0)
+ return(-1);
+
+ p++; /* We don't care about auth_flavor. */
+
+ auth->xa_string.xs_len = p;
+ xdr = B(p++); /* Length of auth_data */
+
+ /* Test for absurdity / illegality of auth_data length. */
+ if ((XDRALIGN(xdr) < xdr) || (RPCB_BUF_GEQ(rm, p, XDRALIGN(xdr)) == 0))
+ return(-1);
+
+ auth->xa_string.xs_str = (char *)p;
+
+ p += XDRALIGN(xdr); /* Advance our location. */
+
+ *buf = (u_32_t *)p;
+
+ return(0);
+}
+
+/* -------------------------------------------------------------------- */
+/* Function: ippr_rpcb_insert */
+/* Returns: int -- -1 == list insertion failed, */
+/* 0 == item successfully added */
+/* Parameters: rs(I) - pointer to RPCB session structure */
+/* rx(I) - pointer to RPCB transaction structure */
+/* -------------------------------------------------------------------- */
+static int
+ippr_rpcb_insert(rs, rx)
+ rpcb_session_t *rs;
+ rpcb_xact_t *rx;
+{
+ rpcb_xact_t *rxp;
+
+ rxp = ippr_rpcb_lookup(rs, rx->rx_xid);
+ if (rxp != NULL) {
+ ++rxp->rx_ref;
+ return(0);
+ }
+
+ if (rpcbcnt == RPCB_MAXREQS)
+ return(-1);
+
+ KMALLOC(rxp, rpcb_xact_t *);
+ if (rxp == NULL)
+ return(-1);
+
+ bcopy((char *)rx, (char *)rxp, sizeof(*rx));
+
+ if (rs->rs_rxlist != NULL)
+ rs->rs_rxlist->rx_pnext = &rxp->rx_next;
+
+ rxp->rx_pnext = &rs->rs_rxlist;
+ rxp->rx_next = rs->rs_rxlist;
+ rs->rs_rxlist = rxp;
+
+ rxp->rx_ref = 1;
+
+ ++rpcbcnt;
+
+ return(0);
+}
+
+/* -------------------------------------------------------------------- */
+/* Function: ippr_rpcb_xdrrpcb */
+/* Returns: int -- -1 == failure to properly decode the request */
+/* 0 == rpcb successfully decoded */
+/* Parameters: rs(I) - pointer to RPCB session structure */
+/* p(I) - pointer to location within session buffer */
+/* rpcb(O) - pointer to rpcb (xdr type) structure */
+/* */
+/* Decode a XDR encoded rpcb structure and record its contents in rpcb */
+/* within only the context of TCP/UDP over IP networks. */
+/* -------------------------------------------------------------------- */
+static int
+ippr_rpcb_xdrrpcb(rm, p, ra)
+ rpc_msg_t *rm;
+ u_32_t *p;
+ rpcb_args_t *ra;
+{
+ if (!RPCB_BUF_GEQ(rm, p, 20))
+ return(-1);
+
+ /* Bypass target program & version. */
+ p += 2;
+
+ /* Decode r_netid. Must be "tcp" or "udp". */
+ if (ippr_rpcb_getproto(rm, &ra->ra_netid, &p) != 0)
+ return(-1);
+
+ /* Decode r_maddr. */
+ if (ippr_rpcb_getuaddr(rm, &ra->ra_maddr, &p) != 0)
+ return(-1);
+
+ /* Advance to r_owner and make sure it's empty. */
+ if (!RPCB_BUF_EQ(rm, p, 4) || (B(p) != 0))
+ return(-1);
+
+ return(0);
+}
+
+/* -------------------------------------------------------------------- */
+/* Function: ippr_rpcb_getuaddr */
+/* Returns: int -- -1 == illegal string, */
+/* 0 == string parsed; contents recorded */
+/* Parameters: rm(I) - pointer to RPC message structure */
+/* xu(I) - pointer to universal address structure */
+/* p(IO) - pointer to location within message buffer */
+/* */
+/* Decode the IP address / port at p and record them in xu. */
+/* -------------------------------------------------------------------- */
+static int
+ippr_rpcb_getuaddr(rm, xu, p)
+ rpc_msg_t *rm;
+ xdr_uaddr_t *xu;
+ u_32_t **p;
+{
+ char *c, *i, *b, *pp;
+ u_int d, dd, l, t;
+ char uastr[24];
+
+ /* Test for string length. */
+ if (!RPCB_BUF_GEQ(rm, *p, 4))
+ return(-1);
+
+ xu->xu_xslen = (*p)++;
+ xu->xu_xsstr = (char *)*p;
+
+ /* Length check */
+ l = B(xu->xu_xslen);
+ if (l < 11 || l > 23 || !RPCB_BUF_GEQ(rm, *p, XDRALIGN(l)))
+ return(-1);
+
+ /* Advance p */
+ *(char **)p += XDRALIGN(l);
+
+ /* Copy string to local buffer & terminate C style */
+ bcopy(xu->xu_xsstr, uastr, l);
+ uastr[l] = '\0';
+
+ i = (char *)&xu->xu_ip;
+ pp = (char *)&xu->xu_port;
+
+ /*
+ * Expected format: a.b.c.d.e.f where [a-d] correspond to bytes of
+ * an IP address and [ef] are the bytes of a L4 port.
+ */
+ if (!(ISDIGIT(uastr[0]) && ISDIGIT(uastr[l-1])))
+ return(-1);
+ b = uastr;
+ for (c = &uastr[1], d = 0, dd = 0; c < &uastr[l-1]; c++) {
+ if (ISDIGIT(*c)) {
+ dd = 0;
+ continue;
+ }
+ if (*c == '.') {
+ if (dd != 0)
+ return(-1);
+
+ /* Check for ASCII byte. */
+ *c = '\0';
+ t = ippr_rpcb_atoi(b);
+ if (t > 255)
+ return(-1);
+
+ /* Aim b at beginning of the next byte. */
+ b = c + 1;
+
+ /* Switch off IP addr vs port parsing. */
+ if (d < 4)
+ i[d++] = t & 0xff;
+ else
+ pp[d++ - 4] = t & 0xff;
+
+ dd = 1;
+ continue;
+ }
+ return(-1);
+ }
+ if (d != 5) /* String must contain exactly 5 periods. */
+ return(-1);
+
+ /* Handle the last byte (port low byte) */
+ t = ippr_rpcb_atoi(b);
+ if (t > 255)
+ return(-1);
+ pp[d - 4] = t & 0xff;
+
+ return(0);
+}
+
+/* -------------------------------------------------------------------- */
+/* Function: ippr_rpcb_atoi (XXX should be generic for all proxies) */
+/* Returns: int -- integer representation of supplied string */
+/* Parameters: ptr(I) - input string */
+/* */
+/* Simple version of atoi(3) ripped from ip_rcmd_pxy.c. */
+/* -------------------------------------------------------------------- */
+static u_int
+ippr_rpcb_atoi(ptr)
+ char *ptr;
+{
+ register char *s = ptr, c;
+ register u_int i = 0;
+
+ while (((c = *s++) != '\0') && ISDIGIT(c)) {
+ i *= 10;
+ i += c - '0';
+ }
+ return i;
+}
+
+/* -------------------------------------------------------------------- */
+/* Function: ippr_rpcb_modreq */
+/* Returns: int -- change in datagram length */
+/* APR_ERR(2) - critical failure */
+/* Parameters: fin(I) - pointer to packet information */
+/* nat(I) - pointer to NAT session */
+/* rm(I) - pointer to RPC message structure */
+/* m(I) - pointer to mbuf chain */
+/* off(I) - current offset within mbuf chain */
+/* */
+/* When external and internal addresses differ, we rewrite the former */
+/* with the latter. (This is exclusive to protocol versions 3 & 4). */
+/* -------------------------------------------------------------------- */
+static int
+ippr_rpcb_modreq(fin, nat, rm, m, off)
+ fr_info_t *fin;
+ nat_t *nat;
+ rpc_msg_t *rm;
+ mb_t *m;
+ u_int off;
+{
+ u_int len, xlen, pos, bogo;
+ rpcb_args_t *ra;
+ char uaddr[24];
+ udphdr_t *udp;
+ char *i, *p;
+ int diff;
+
+ ra = &rm->rm_call.rc_rpcbargs;
+ i = (char *)&nat->nat_inip.s_addr;
+ p = (char *)&nat->nat_inport;
+
+ /* Form new string. */
+ bzero(uaddr, sizeof(uaddr)); /* Just in case we need padding. */
+#if defined(SNPRINTF) && defined(_KERNEL)
+ SNPRINTF(uaddr, sizeof(uaddr),
+#else
+ (void) sprintf(uaddr,
+#endif
+ "%u.%u.%u.%u.%u.%u", i[0] & 0xff, i[1] & 0xff,
+ i[2] & 0xff, i[3] & 0xff, p[0] & 0xff, p[1] & 0xff);
+ len = strlen(uaddr);
+ xlen = XDRALIGN(len);
+
+ /* Determine mbuf offset to start writing to. */
+ pos = (char *)ra->ra_maddr.xu_xslen - rm->rm_msgbuf;
+ off += pos;
+
+ /* Write new string length. */
+ bogo = htonl(len);
+ COPYBACK(m, off, 4, (caddr_t)&bogo);
+ off += 4;
+
+ /* Write new string. */
+ COPYBACK(m, off, xlen, uaddr);
+ off += xlen;
+
+ /* Write in zero r_owner. */
+ bogo = 0;
+ COPYBACK(m, off, 4, (caddr_t)&bogo);
+
+ /* Determine difference in data lengths. */
+ diff = xlen - XDRALIGN(B(ra->ra_maddr.xu_xslen));
+
+ /*
+ * If our new string has a different length, make necessary
+ * adjustments.
+ */
+ if (diff != 0) {
+ udp = fin->fin_dp;
+ udp->uh_ulen = htons(ntohs(udp->uh_ulen) + diff);
+ fin->fin_ip->ip_len += diff;
+ fin->fin_dlen += diff;
+ fin->fin_plen += diff;
+ /* XXX Storage lengths. */
+ }
+
+ return(diff);
+}
+
+/* -------------------------------------------------------------------- */
+/* Function: ippr_rpcb_decoderep */
+/* Returns: int - -1 == bad request or critical failure, */
+/* 0 == valid, negative reply */
+/* 1 == vaddlid, positive reply; needs no changes */
+/* Parameters: fin(I) - pointer to packet information */
+/* nat(I) - pointer to NAT session structure */
+/* rs(I) - pointer to RPCB session structure */
+/* rm(I) - pointer to RPC message structure */
+/* rxp(O) - pointer to RPCB transaction structure */
+/* */
+/* Take a presumed RPCB reply, extract the XID, search for the original */
+/* request information, and determine whether the request was accepted */
+/* or rejected. With a valid accepted reply, go ahead and create NAT */
+/* and state entries, and finish up by rewriting the packet as */
+/* required. */
+/* */
+/* WARNING: It's the responsibility of the caller to make sure there */
+/* is enough room in rs_buf for the basic RPC message "preamble". */
+/* -------------------------------------------------------------------- */
+static int
+ippr_rpcb_decoderep(fin, nat, rs, rm, rxp)
+ fr_info_t *fin;
+ nat_t *nat;
+ rpcb_session_t *rs;
+ rpc_msg_t *rm;
+ rpcb_xact_t **rxp;
+{
+ rpcb_listp_t *rl;
+ rpcb_entry_t *re;
+ rpcb_xact_t *rx;
+ u_32_t xdr, *p;
+ rpc_resp_t *rr;
+ int rv, cnt;
+
+ p = (u_32_t *)rm->rm_msgbuf;
+
+ bzero((char *)&rx, sizeof(rx));
+ rr = &rm->rm_resp;
+
+ rm->rm_xid = p;
+ xdr = B(p++); /* Record this message's XID. */
+
+ /* Lookup XID */
+ MUTEX_ENTER(&rs->rs_rxlock);
+ if ((rx = ippr_rpcb_lookup(rs, xdr)) == NULL) {
+ MUTEX_EXIT(&rs->rs_rxlock);
+ return(-1);
+ }
+ ++rx->rx_ref; /* per thread reference */
+ MUTEX_EXIT(&rs->rs_rxlock);
+
+ *rxp = rx;
+
+ /* Test call vs reply */
+ if (B(p++) != RPCB_REPLY)
+ return(-1);
+
+ /* Test reply_stat */
+ switch(B(p++))
+ {
+ case RPCB_MSG_DENIED:
+ return(0);
+ case RPCB_MSG_ACCEPTED:
+ break;
+ default:
+ return(-1);
+ }
+
+ /* Bypass RPC authentication stuff. */
+ if (ippr_rpcb_skipauth(rm, &rr->rr_authverf, &p) != 0)
+ return(-1);
+
+ /* Test accept status */
+ if (!RPCB_BUF_GEQ(rm, p, 4))
+ return(-1);
+ if (B(p++) != 0)
+ return(0);
+
+ /* Parse out the expected reply */
+ switch(rx->rx_type)
+ {
+ case RPCB_RES_PMAP:
+ /* There must be only one 4 byte argument. */
+ if (!RPCB_BUF_EQ(rm, p, 4))
+ return(-1);
+
+ rr->rr_v2 = p;
+ xdr = B(rr->rr_v2);
+
+ /* Reply w/ a 0 port indicates service isn't registered */
+ if (xdr == 0)
+ return(0);
+
+ /* Is the value sane? */
+ if (xdr > 65535)
+ return(-1);
+
+ /* Create NAT & state table entries. */
+ if (ippr_rpcb_getnat(fin, nat, rx->rx_proto, (u_int)xdr) != 0)
+ return(-1);
+ break;
+ case RPCB_RES_STRING:
+ /* Expecting a XDR string; need 4 bytes for length */
+ if (!RPCB_BUF_GEQ(rm, p, 4))
+ return(-1);
+
+ rr->rr_v3.xu_str.xs_len = p++;
+ rr->rr_v3.xu_str.xs_str = (char *)p;
+
+ xdr = B(rr->rr_v3.xu_xslen);
+
+ /* A null string indicates an unregistered service */
+ if ((xdr == 0) && RPCB_BUF_EQ(rm, p, 0))
+ return(0);
+
+ /* Decode the target IP address / port. */
+ if (ippr_rpcb_getuaddr(rm, &rr->rr_v3, &p) != 0)
+ return(-1);
+
+ /* Validate the IP address and port contained. */
+ if (nat->nat_inip.s_addr != rr->rr_v3.xu_ip)
+ return(-1);
+
+ /* Create NAT & state table entries. */
+ if (ippr_rpcb_getnat(fin, nat, rx->rx_proto,
+ (u_int)rr->rr_v3.xu_port) != 0)
+ return(-1);
+ break;
+ case RPCB_RES_LIST:
+ if (!RPCB_BUF_GEQ(rm, p, 4))
+ return(-1);
+ /* rpcb_entry_list_ptr */
+ switch(B(p))
+ {
+ case 0:
+ return(0);
+ /*NOTREACHED*/
+ break;
+ case 1:
+ break;
+ default:
+ return(-1);
+ }
+ rl = &rr->rr_v4;
+ rl->rl_list = p++;
+ cnt = 0;
+
+ for(;;) {
+ re = &rl->rl_entries[rl->rl_cnt];
+ if (ippr_rpcb_getuaddr(rm, &re->re_maddr, &p) != 0)
+ return(-1);
+ if (ippr_rpcb_getproto(rm, &re->re_netid, &p) != 0)
+ return(-1);
+ /* re_semantics & re_pfamily length */
+ if (!RPCB_BUF_GEQ(rm, p, 12))
+ return(-1);
+ p++; /* Skipping re_semantics. */
+ xdr = B(p++);
+ if ((xdr != 4) || strncmp((char *)p, "inet", 4))
+ return(-1);
+ p++;
+ if (ippr_rpcb_getproto(rm, &re->re_proto, &p) != 0)
+ return(-1);
+ if (!RPCB_BUF_GEQ(rm, p, 4))
+ return(-1);
+ re->re_more = p;
+ if (B(re->re_more) > 1) /* 0,1 only legal values */
+ return(-1);
+ ++rl->rl_cnt;
+ ++cnt;
+ if (B(re->re_more) == 0)
+ break;
+ /* Replies in max out at 2; TCP and/or UDP */
+ if (cnt > 2)
+ return(-1);
+ p++;
+ }
+
+ for(rl->rl_cnt = 0; rl->rl_cnt < cnt; rl->rl_cnt++) {
+ re = &rl->rl_entries[rl->rl_cnt];
+ rv = ippr_rpcb_getnat(fin, nat,
+ re->re_proto.xp_proto,
+ (u_int)re->re_maddr.xu_port);
+ if (rv != 0)
+ return(-1);
+ }
+ break;
+ default:
+ /*CONSTANTCONDITION*/
+ IPF_PANIC(1, ("illegal rx_type %d", rx->rx_type));
+ }
+
+ return(1);
+}
+
+/* -------------------------------------------------------------------- */
+/* Function: ippr_rpcb_lookup */
+/* Returns: rpcb_xact_t * - NULL == no matching record, */
+/* else pointer to relevant entry */
+/* Parameters: rs(I) - pointer to RPCB session */
+/* xid(I) - XID to look for */
+/* -------------------------------------------------------------------- */
+static rpcb_xact_t *
+ippr_rpcb_lookup(rs, xid)
+ rpcb_session_t *rs;
+ u_32_t xid;
+{
+ rpcb_xact_t *rx;
+
+ if (rs->rs_rxlist == NULL)
+ return(NULL);
+
+ for (rx = rs->rs_rxlist; rx != NULL; rx = rx->rx_next)
+ if (rx->rx_xid == xid)
+ break;
+
+ return(rx);
+}
+
+/* -------------------------------------------------------------------- */
+/* Function: ippr_rpcb_deref */
+/* Returns: (void) */
+/* Parameters: rs(I) - pointer to RPCB session */
+/* rx(I) - pointer to RPC transaction struct to remove */
+/* force(I) - indicates to delete entry regardless of */
+/* reference count */
+/* Locking: rs->rs_rxlock must be held write only */
+/* */
+/* Free the RPCB transaction record rx from the chain of entries. */
+/* -------------------------------------------------------------------- */
+static void
+ippr_rpcb_deref(rs, rx)
+ rpcb_session_t *rs;
+ rpcb_xact_t *rx;
+{
+ rs = rs; /* LINT */
+
+ if (rx == NULL)
+ return;
+
+ if (--rx->rx_ref != 0)
+ return;
+
+ if (rx->rx_next != NULL)
+ rx->rx_next->rx_pnext = rx->rx_pnext;
+
+ *rx->rx_pnext = rx->rx_next;
+
+ KFREE(rx);
+
+ --rpcbcnt;
+}
+
+/* -------------------------------------------------------------------- */
+/* Function: ippr_rpcb_getproto */
+/* Returns: int - -1 == illegal protocol/netid, */
+/* 0 == legal protocol/netid */
+/* Parameters: rm(I) - pointer to RPC message structure */
+/* xp(I) - pointer to netid structure */
+/* p(IO) - pointer to location within packet buffer */
+/* */
+/* Decode netid/proto stored at p and record its numeric value. */
+/* -------------------------------------------------------------------- */
+static int
+ippr_rpcb_getproto(rm, xp, p)
+ rpc_msg_t *rm;
+ xdr_proto_t *xp;
+ u_32_t **p;
+{
+ u_int len;
+
+ /* Must have 4 bytes for length & 4 bytes for "tcp" or "udp". */
+ if (!RPCB_BUF_GEQ(rm, p, 8))
+ return(-1);
+
+ xp->xp_xslen = (*p)++;
+ xp->xp_xsstr = (char *)*p;
+
+ /* Test the string length. */
+ len = B(xp->xp_xslen);
+ if (len != 3)
+ return(-1);
+
+ /* Test the actual string & record the protocol accordingly. */
+ if (!strncmp((char *)xp->xp_xsstr, "tcp\0", 4))
+ xp->xp_proto = IPPROTO_TCP;
+ else if (!strncmp((char *)xp->xp_xsstr, "udp\0", 4))
+ xp->xp_proto = IPPROTO_UDP;
+ else {
+ return(-1);
+ }
+
+ /* Advance past the string. */
+ (*p)++;
+
+ return(0);
+}
+
+/* -------------------------------------------------------------------- */
+/* Function: ippr_rpcb_getnat */
+/* Returns: int -- -1 == failed to create table entries, */
+/* 0 == success */
+/* Parameters: fin(I) - pointer to packet information */
+/* nat(I) - pointer to NAT table entry */
+/* proto(I) - transport protocol for new entries */
+/* port(I) - new port to use w/ wildcard table entries */
+/* */
+/* Create state and NAT entries to handle an anticipated connection */
+/* attempt between RPC client and server. */
+/* -------------------------------------------------------------------- */
+static int
+ippr_rpcb_getnat(fin, nat, proto, port)
+ fr_info_t *fin;
+ nat_t *nat;
+ u_int proto;
+ u_int port;
+{
+ ipnat_t *ipn, ipnat;
+ tcphdr_t tcp;
+ ipstate_t *is;
+ fr_info_t fi;
+ nat_t *natl;
+ int nflags;
+
+ ipn = nat->nat_ptr;
+
+ /* Generate dummy fr_info */
+ bcopy((char *)fin, (char *)&fi, sizeof(fi));
+ fi.fin_out = 0;
+ fi.fin_src = fin->fin_dst;
+ fi.fin_dst = nat->nat_outip;
+ fi.fin_p = proto;
+ fi.fin_sport = 0;
+ fi.fin_dport = port & 0xffff;
+ fi.fin_flx |= FI_IGNORE;
+
+ bzero((char *)&tcp, sizeof(tcp));
+ tcp.th_dport = htons(port);
+
+ if (proto == IPPROTO_TCP) {
+ tcp.th_win = htons(8192);
+ TCP_OFF_A(&tcp, sizeof(tcphdr_t) >> 2);
+ fi.fin_dlen = sizeof(tcphdr_t);
+ tcp.th_flags = TH_SYN;
+ nflags = NAT_TCP;
+ } else {
+ fi.fin_dlen = sizeof(udphdr_t);
+ nflags = NAT_UDP;
+ }
+
+ nflags |= SI_W_SPORT|NAT_SEARCH;
+ fi.fin_dp = &tcp;
+ fi.fin_plen = fi.fin_hlen + fi.fin_dlen;
+
+ /*
+ * Search for existing NAT & state entries. Pay close attention to
+ * mutexes / locks grabbed from lookup routines, as not doing so could
+ * lead to bad things.
+ *
+ * If successful, fr_stlookup returns with ipf_state locked. We have
+ * no use for this lock, so simply unlock it if necessary.
+ */
+ is = fr_stlookup(&fi, &tcp, NULL);
+ if (is != NULL)
+ RWLOCK_EXIT(&ipf_state);
+
+ RWLOCK_EXIT(&ipf_nat);
+
+ WRITE_ENTER(&ipf_nat);
+ natl = nat_inlookup(&fi, nflags, proto, fi.fin_src, fi.fin_dst);
+
+ if ((natl != NULL) && (is != NULL)) {
+ MUTEX_DOWNGRADE(&ipf_nat);
+ return(0);
+ }
+
+ /* Slightly modify the following structures for actual use in creating
+ * NAT and/or state entries. We're primarily concerned with stripping
+ * flags that may be detrimental to the creation process or simply
+ * shouldn't be associated with a table entry.
+ */
+ fi.fin_fr = &rpcbfr;
+ fi.fin_flx &= ~FI_IGNORE;
+ nflags &= ~NAT_SEARCH;
+
+ if (natl == NULL) {
+ /* XXX Since we're just copying the original ipn contents
+ * back, would we be better off just sending a pointer to
+ * the 'temp' copy off to nat_new instead?
+ */
+ /* Generate template/bogus NAT rule. */
+ bcopy((char *)ipn, (char *)&ipnat, sizeof(ipnat));
+ ipn->in_flags = nflags & IPN_TCPUDP;
+ ipn->in_apr = NULL;
+ ipn->in_p = proto;
+ ipn->in_pmin = htons(fi.fin_dport);
+ ipn->in_pmax = htons(fi.fin_dport);
+ ipn->in_pnext = htons(fi.fin_dport);
+ ipn->in_space = 1;
+ ipn->in_ippip = 1;
+ if (ipn->in_flags & IPN_FILTER) {
+ ipn->in_scmp = 0;
+ ipn->in_dcmp = 0;
+ }
+ *ipn->in_plabel = '\0';
+
+ /* Create NAT entry. return NULL if this fails. */
+ natl = nat_new(&fi, ipn, NULL, nflags|SI_CLONE|NAT_SLAVE,
+ NAT_INBOUND);
+
+ bcopy((char *)&ipnat, (char *)ipn, sizeof(ipnat));
+
+ if (natl == NULL) {
+ MUTEX_DOWNGRADE(&ipf_nat);
+ return(-1);
+ }
+
+ ipn->in_use++;
+ (void) nat_proto(&fi, natl, nflags);
+ nat_update(&fi, natl, natl->nat_ptr);
+ }
+ MUTEX_DOWNGRADE(&ipf_nat);
+
+ if (is == NULL) {
+ /* Create state entry. Return NULL if this fails. */
+ fi.fin_dst = nat->nat_inip;
+ fi.fin_nat = (void *)natl;
+ fi.fin_flx |= FI_NATED;
+ fi.fin_flx &= ~FI_STATE;
+ nflags &= NAT_TCPUDP;
+ nflags |= SI_W_SPORT|SI_CLONE;
+
+ is = fr_addstate(&fi, NULL, nflags);
+ if (is == NULL) {
+ /*
+ * XXX nat_delete is private to ip_nat.c. Should
+ * check w/ Darren about this one.
+ *
+ * nat_delete(natl, NL_EXPIRE);
+ */
+ return(-1);
+ }
+ if (fi.fin_state != NULL)
+ fr_statederef(&fi, (ipstate_t **)&fi.fin_state);
+ }
+
+ return(0);
+}
+
+/* -------------------------------------------------------------------- */
+/* Function: ippr_rpcb_modv3 */
+/* Returns: int -- change in packet length */
+/* Parameters: fin(I) - pointer to packet information */
+/* nat(I) - pointer to NAT session */
+/* rm(I) - pointer to RPC message structure */
+/* m(I) - pointer to mbuf chain */
+/* off(I) - offset within mbuf chain */
+/* */
+/* Write a new universal address string to this packet, adjusting */
+/* lengths as necessary. */
+/* -------------------------------------------------------------------- */
+static int
+ippr_rpcb_modv3(fin, nat, rm, m, off)
+ fr_info_t *fin;
+ nat_t *nat;
+ rpc_msg_t *rm;
+ mb_t *m;
+ u_int off;
+{
+ u_int len, xlen, pos, bogo;
+ rpc_resp_t *rr;
+ char uaddr[24];
+ char *i, *p;
+ int diff;
+
+ rr = &rm->rm_resp;
+ i = (char *)&nat->nat_outip.s_addr;
+ p = (char *)&rr->rr_v3.xu_port;
+
+ /* Form new string. */
+ bzero(uaddr, sizeof(uaddr)); /* Just in case we need padding. */
+#if defined(SNPRINTF) && defined(_KERNEL)
+ SNPRINTF(uaddr, sizeof(uaddr),
+#else
+ (void) sprintf(uaddr,
+#endif
+ "%u.%u.%u.%u.%u.%u", i[0] & 0xff, i[1] & 0xff,
+ i[2] & 0xff, i[3] & 0xff, p[0] & 0xff, p[1] & 0xff);
+ len = strlen(uaddr);
+ xlen = XDRALIGN(len);
+
+ /* Determine mbuf offset to write to. */
+ pos = (char *)rr->rr_v3.xu_xslen - rm->rm_msgbuf;
+ off += pos;
+
+ /* Write new string length. */
+ bogo = htonl(len);
+ COPYBACK(m, off, 4, (caddr_t)&bogo);
+ off += 4;
+
+ /* Write new string. */
+ COPYBACK(m, off, xlen, uaddr);
+
+ /* Determine difference in data lengths. */
+ diff = xlen - XDRALIGN(B(rr->rr_v3.xu_xslen));
+
+ /*
+ * If our new string has a different length, make necessary
+ * adjustments.
+ */
+ if (diff != 0)
+ ippr_rpcb_fixlen(fin, diff);
+
+ return(diff);
+}
+
+/* -------------------------------------------------------------------- */
+/* Function: ippr_rpcb_modv4 */
+/* Returns: int -- change in packet length */
+/* Parameters: fin(I) - pointer to packet information */
+/* nat(I) - pointer to NAT session */
+/* rm(I) - pointer to RPC message structure */
+/* m(I) - pointer to mbuf chain */
+/* off(I) - offset within mbuf chain */
+/* */
+/* Write new rpcb_entry list, adjusting lengths as necessary. */
+/* -------------------------------------------------------------------- */
+static int
+ippr_rpcb_modv4(fin, nat, rm, m, off)
+ fr_info_t *fin;
+ nat_t *nat;
+ rpc_msg_t *rm;
+ mb_t *m;
+ u_int off;
+{
+ u_int len, xlen, pos, bogo;
+ rpcb_listp_t *rl;
+ rpcb_entry_t *re;
+ rpc_resp_t *rr;
+ char uaddr[24];
+ int diff, cnt;
+ char *i, *p;
+
+ diff = 0;
+ rr = &rm->rm_resp;
+ rl = &rr->rr_v4;
+
+ i = (char *)&nat->nat_outip.s_addr;
+
+ /* Determine mbuf offset to write to. */
+ re = &rl->rl_entries[0];
+ pos = (char *)re->re_maddr.xu_xslen - rm->rm_msgbuf;
+ off += pos;
+
+ for (cnt = 0; cnt < rl->rl_cnt; cnt++) {
+ re = &rl->rl_entries[cnt];
+ p = (char *)&re->re_maddr.xu_port;
+
+ /* Form new string. */
+ bzero(uaddr, sizeof(uaddr)); /* Just in case we need
+ padding. */
+#if defined(SNPRINTF) && defined(_KERNEL)
+ SNPRINTF(uaddr, sizeof(uaddr),
+#else
+ (void) sprintf(uaddr,
+#endif
+ "%u.%u.%u.%u.%u.%u", i[0] & 0xff,
+ i[1] & 0xff, i[2] & 0xff, i[3] & 0xff,
+ p[0] & 0xff, p[1] & 0xff);
+ len = strlen(uaddr);
+ xlen = XDRALIGN(len);
+
+ /* Write new string length. */
+ bogo = htonl(len);
+ COPYBACK(m, off, 4, (caddr_t)&bogo);
+ off += 4;
+
+ /* Write new string. */
+ COPYBACK(m, off, xlen, uaddr);
+ off += xlen;
+
+ /* Record any change in length. */
+ diff += xlen - XDRALIGN(B(re->re_maddr.xu_xslen));
+
+ /* If the length changed, copy back the rest of this entry. */
+ len = ((char *)re->re_more + 4) -
+ (char *)re->re_netid.xp_xslen;
+ if (diff != 0) {
+ COPYBACK(m, off, len, (caddr_t)re->re_netid.xp_xslen);
+ }
+ off += len;
+ }
+
+ /*
+ * If our new string has a different length, make necessary
+ * adjustments.
+ */
+ if (diff != 0)
+ ippr_rpcb_fixlen(fin, diff);
+
+ return(diff);
+}
+
+
+/* -------------------------------------------------------------------- */
+/* Function: ippr_rpcb_fixlen */
+/* Returns: (void) */
+/* Parameters: fin(I) - pointer to packet information */
+/* len(I) - change in packet length */
+/* */
+/* Adjust various packet related lengths held in structure and packet */
+/* header fields. */
+/* -------------------------------------------------------------------- */
+static void
+ippr_rpcb_fixlen(fin, len)
+ fr_info_t *fin;
+ int len;
+{
+ udphdr_t *udp;
+
+ udp = fin->fin_dp;
+ udp->uh_ulen = htons(ntohs(udp->uh_ulen) + len);
+ fin->fin_ip->ip_len += len;
+ fin->fin_dlen += len;
+ fin->fin_plen += len;
+}
+
+#undef B
diff --git a/contrib/ipfilter/ip_scan.c b/contrib/ipfilter/ip_scan.c
new file mode 100644
index 0000000..37f6d58
--- /dev/null
+++ b/contrib/ipfilter/ip_scan.c
@@ -0,0 +1,594 @@
+/* $NetBSD$ */
+
+/*
+ * Copyright (C) 1995-2001 by Darren Reed.
+ *
+ * See the IPFILTER.LICENCE file for details on licencing.
+ */
+#if defined(KERNEL) || defined(_KERNEL)
+# undef KERNEL
+# undef _KERNEL
+# define KERNEL 1
+# define _KERNEL 1
+#endif
+#include <sys/param.h>
+#if defined(__hpux) && (HPUXREV >= 1111) && !defined(_KERNEL)
+# include <sys/kern_svcs.h>
+#endif
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/errno.h>
+#if !defined(_KERNEL)
+# include <stdlib.h>
+# include <string.h>
+# define _KERNEL
+# ifdef __OpenBSD__
+struct file;
+# endif
+# include <sys/uio.h>
+# undef _KERNEL
+#else
+# include <sys/systm.h>
+# if !defined(__svr4__) && !defined(__SVR4)
+# include <sys/mbuf.h>
+# endif
+#endif
+#include <sys/socket.h>
+#if !defined(__hpux) && !defined(__osf__) && !defined(linux)
+# include <sys/ioccom.h>
+#endif
+#ifdef __FreeBSD__
+# include <sys/filio.h>
+# include <sys/malloc.h>
+#else
+# include <sys/ioctl.h>
+#endif
+
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/tcp.h>
+
+#include <net/if.h>
+
+
+#include "netinet/ip_compat.h"
+#include "netinet/ip_fil.h"
+#include "netinet/ip_state.h"
+#include "netinet/ip_scan.h"
+/* END OF INCLUDES */
+
+#if !defined(lint)
+static const char sccsid[] = "@(#)ip_state.c 1.8 6/5/96 (C) 1993-2000 Darren Reed";
+static const char rcsid[] = "@(#)Id: ip_scan.c,v 2.40.2.2 2005/01/18 10:13:16 darrenr Exp";
+#endif
+
+#ifdef IPFILTER_SCAN /* endif at bottom of file */
+
+
+ipscan_t *ipsc_list = NULL,
+ *ipsc_tail = NULL;
+ipscanstat_t ipsc_stat;
+# ifdef USE_MUTEXES
+ipfrwlock_t ipsc_rwlock;
+# endif
+
+# ifndef isalpha
+# define isalpha(x) (((x) >= 'A' && 'Z' >= (x)) || \
+ ((x) >= 'a' && 'z' >= (x)))
+# endif
+
+
+int ipsc_add __P((caddr_t));
+int ipsc_delete __P((caddr_t));
+struct ipscan *ipsc_lookup __P((char *));
+int ipsc_matchstr __P((sinfo_t *, char *, int));
+int ipsc_matchisc __P((ipscan_t *, ipstate_t *, int, int, int *));
+int ipsc_match __P((ipstate_t *));
+
+
+
+int ipsc_init()
+{
+ RWLOCK_INIT(&ipsc_rwlock, "ip scan rwlock");
+ return 0;
+}
+
+
+void fr_scanunload()
+{
+ RW_DESTROY(&ipsc_rwlock);
+}
+
+
+int ipsc_add(data)
+caddr_t data;
+{
+ ipscan_t *i, *isc;
+ int err;
+
+ KMALLOC(isc, ipscan_t *);
+ if (!isc)
+ return ENOMEM;
+
+ err = copyinptr(data, isc, sizeof(*isc));
+ if (err)
+ return err;
+
+ WRITE_ENTER(&ipsc_rwlock);
+
+ i = ipsc_lookup(isc->ipsc_tag);
+ if (i) {
+ RWLOCK_EXIT(&ipsc_rwlock);
+ KFREE(isc);
+ return EEXIST;
+ }
+
+ if (ipsc_tail) {
+ ipsc_tail->ipsc_next = isc;
+ isc->ipsc_pnext = &ipsc_tail->ipsc_next;
+ ipsc_tail = isc;
+ } else {
+ ipsc_list = isc;
+ ipsc_tail = isc;
+ isc->ipsc_pnext = &ipsc_list;
+ }
+ isc->ipsc_next = NULL;
+
+ isc->ipsc_hits = 0;
+ isc->ipsc_fref = 0;
+ isc->ipsc_sref = 0;
+ isc->ipsc_active = 0;
+
+ ipsc_stat.iscs_entries++;
+ RWLOCK_EXIT(&ipsc_rwlock);
+ return 0;
+}
+
+
+int ipsc_delete(data)
+caddr_t data;
+{
+ ipscan_t isc, *i;
+ int err;
+
+ err = copyinptr(data, &isc, sizeof(isc));
+ if (err)
+ return err;
+
+ WRITE_ENTER(&ipsc_rwlock);
+
+ i = ipsc_lookup(isc.ipsc_tag);
+ if (i == NULL)
+ err = ENOENT;
+ else {
+ if (i->ipsc_fref) {
+ RWLOCK_EXIT(&ipsc_rwlock);
+ return EBUSY;
+ }
+
+ *i->ipsc_pnext = i->ipsc_next;
+ if (i->ipsc_next)
+ i->ipsc_next->ipsc_pnext = i->ipsc_pnext;
+ else {
+ if (i->ipsc_pnext == &ipsc_list)
+ ipsc_tail = NULL;
+ else
+ ipsc_tail = *(*i->ipsc_pnext)->ipsc_pnext;
+ }
+
+ ipsc_stat.iscs_entries--;
+ KFREE(i);
+ }
+ RWLOCK_EXIT(&ipsc_rwlock);
+ return err;
+}
+
+
+struct ipscan *ipsc_lookup(tag)
+char *tag;
+{
+ ipscan_t *i;
+
+ for (i = ipsc_list; i; i = i->ipsc_next)
+ if (!strcmp(i->ipsc_tag, tag))
+ return i;
+ return NULL;
+}
+
+
+int ipsc_attachfr(fr)
+struct frentry *fr;
+{
+ ipscan_t *i;
+
+ if (fr->fr_isctag[0]) {
+ READ_ENTER(&ipsc_rwlock);
+ i = ipsc_lookup(fr->fr_isctag);
+ if (i != NULL) {
+ ATOMIC_INC32(i->ipsc_fref);
+ }
+ RWLOCK_EXIT(&ipsc_rwlock);
+ if (i == NULL)
+ return ENOENT;
+ fr->fr_isc = i;
+ }
+ return 0;
+}
+
+
+int ipsc_attachis(is)
+struct ipstate *is;
+{
+ frentry_t *fr;
+ ipscan_t *i;
+
+ READ_ENTER(&ipsc_rwlock);
+ fr = is->is_rule;
+ if (fr) {
+ i = fr->fr_isc;
+ if (!i || (i != (ipscan_t *)-1)) {
+ is->is_isc = i;
+ if (i) {
+ ATOMIC_INC32(i->ipsc_sref);
+ if (i->ipsc_clen)
+ is->is_flags |= IS_SC_CLIENT;
+ else
+ is->is_flags |= IS_SC_MATCHC;
+ if (i->ipsc_slen)
+ is->is_flags |= IS_SC_SERVER;
+ else
+ is->is_flags |= IS_SC_MATCHS;
+ } else
+ is->is_flags |= (IS_SC_CLIENT|IS_SC_SERVER);
+ }
+ }
+ RWLOCK_EXIT(&ipsc_rwlock);
+ return 0;
+}
+
+
+int ipsc_detachfr(fr)
+struct frentry *fr;
+{
+ ipscan_t *i;
+
+ i = fr->fr_isc;
+ if (i != NULL) {
+ ATOMIC_DEC32(i->ipsc_fref);
+ }
+ return 0;
+}
+
+
+int ipsc_detachis(is)
+struct ipstate *is;
+{
+ ipscan_t *i;
+
+ READ_ENTER(&ipsc_rwlock);
+ if ((i = is->is_isc) && (i != (ipscan_t *)-1)) {
+ ATOMIC_DEC32(i->ipsc_sref);
+ is->is_isc = NULL;
+ is->is_flags &= ~(IS_SC_CLIENT|IS_SC_SERVER);
+ }
+ RWLOCK_EXIT(&ipsc_rwlock);
+ return 0;
+}
+
+
+/*
+ * 'string' compare for scanning
+ */
+int ipsc_matchstr(sp, str, n)
+sinfo_t *sp;
+char *str;
+int n;
+{
+ char *s, *t, *up;
+ int i = n;
+
+ if (i > sp->s_len)
+ i = sp->s_len;
+ up = str;
+
+ for (s = sp->s_txt, t = sp->s_msk; i; i--, s++, t++, up++)
+ switch ((int)*t)
+ {
+ case '.' :
+ if (*s != *up)
+ return 1;
+ break;
+ case '?' :
+ if (!ISALPHA(*up) || ((*s & 0x5f) != (*up & 0x5f)))
+ return 1;
+ break;
+ case '*' :
+ break;
+ }
+ return 0;
+}
+
+
+/*
+ * Returns 3 if both server and client match, 2 if just server,
+ * 1 if just client
+ */
+int ipsc_matchisc(isc, is, cl, sl, maxm)
+ipscan_t *isc;
+ipstate_t *is;
+int cl, sl, maxm[2];
+{
+ int i, j, k, n, ret = 0, flags;
+
+ flags = is->is_flags;
+
+ /*
+ * If we've already matched more than what is on offer, then
+ * assume we have a better match already and forget this one.
+ */
+ if (maxm != NULL) {
+ if (isc->ipsc_clen < maxm[0])
+ return 0;
+ if (isc->ipsc_slen < maxm[1])
+ return 0;
+ j = maxm[0];
+ k = maxm[1];
+ } else {
+ j = 0;
+ k = 0;
+ }
+
+ if (!isc->ipsc_clen)
+ ret = 1;
+ else if (((flags & (IS_SC_MATCHC|IS_SC_CLIENT)) == IS_SC_CLIENT) &&
+ cl && isc->ipsc_clen) {
+ i = 0;
+ n = MIN(cl, isc->ipsc_clen);
+ if ((n > 0) && (!maxm || (n >= maxm[1]))) {
+ if (!ipsc_matchstr(&isc->ipsc_cl, is->is_sbuf[0], n)) {
+ i++;
+ ret |= 1;
+ if (n > j)
+ j = n;
+ }
+ }
+ }
+
+ if (!isc->ipsc_slen)
+ ret |= 2;
+ else if (((flags & (IS_SC_MATCHS|IS_SC_SERVER)) == IS_SC_SERVER) &&
+ sl && isc->ipsc_slen) {
+ i = 0;
+ n = MIN(cl, isc->ipsc_slen);
+ if ((n > 0) && (!maxm || (n >= maxm[1]))) {
+ if (!ipsc_matchstr(&isc->ipsc_sl, is->is_sbuf[1], n)) {
+ i++;
+ ret |= 2;
+ if (n > k)
+ k = n;
+ }
+ }
+ }
+
+ if (maxm && (ret == 3)) {
+ maxm[0] = j;
+ maxm[1] = k;
+ }
+ return ret;
+}
+
+
+int ipsc_match(is)
+ipstate_t *is;
+{
+ int i, j, k, n, cl, sl, maxm[2];
+ ipscan_t *isc, *lm;
+ tcpdata_t *t;
+
+ for (cl = 0, n = is->is_smsk[0]; n & 1; n >>= 1)
+ cl++;
+ for (sl = 0, n = is->is_smsk[1]; n & 1; n >>= 1)
+ sl++;
+
+ j = 0;
+ isc = is->is_isc;
+ if (isc != NULL) {
+ /*
+ * Known object to scan for.
+ */
+ i = ipsc_matchisc(isc, is, cl, sl, NULL);
+ if (i & 1) {
+ is->is_flags |= IS_SC_MATCHC;
+ is->is_flags &= ~IS_SC_CLIENT;
+ } else if (cl >= isc->ipsc_clen)
+ is->is_flags &= ~IS_SC_CLIENT;
+ if (i & 2) {
+ is->is_flags |= IS_SC_MATCHS;
+ is->is_flags &= ~IS_SC_SERVER;
+ } else if (sl >= isc->ipsc_slen)
+ is->is_flags &= ~IS_SC_SERVER;
+ } else {
+ i = 0;
+ lm = NULL;
+ maxm[0] = 0;
+ maxm[1] = 0;
+ for (k = 0, isc = ipsc_list; isc; isc = isc->ipsc_next) {
+ i = ipsc_matchisc(isc, is, cl, sl, maxm);
+ if (i) {
+ /*
+ * We only want to remember the best match
+ * and the number of times we get a best
+ * match.
+ */
+ if ((j == 3) && (i < 3))
+ continue;
+ if ((i == 3) && (j != 3))
+ k = 1;
+ else
+ k++;
+ j = i;
+ lm = isc;
+ }
+ }
+ if (k == 1)
+ isc = lm;
+
+ /*
+ * No matches or partial matches, so reset the respective
+ * search flag.
+ */
+ if (!(j & 1))
+ is->is_flags &= ~IS_SC_CLIENT;
+
+ if (!(j & 2))
+ is->is_flags &= ~IS_SC_SERVER;
+
+ /*
+ * If we found the best match, then set flags appropriately.
+ */
+ if ((j == 3) && (k == 1)) {
+ is->is_flags &= ~(IS_SC_SERVER|IS_SC_CLIENT);
+ is->is_flags |= (IS_SC_MATCHS|IS_SC_MATCHC);
+ }
+ }
+
+ /*
+ * If the acknowledged side of a connection has moved past the data in
+ * which we are interested, then reset respective flag.
+ */
+ t = &is->is_tcp.ts_data[0];
+ if (t->td_end > is->is_s0[0] + 15)
+ is->is_flags &= ~IS_SC_CLIENT;
+
+ t = &is->is_tcp.ts_data[1];
+ if (t->td_end > is->is_s0[1] + 15)
+ is->is_flags &= ~IS_SC_SERVER;
+
+ /*
+ * Matching complete ?
+ */
+ j = ISC_A_NONE;
+ if ((is->is_flags & IS_SC_MATCHALL) == IS_SC_MATCHALL) {
+ j = isc->ipsc_action;
+ ipsc_stat.iscs_acted++;
+ } else if ((is->is_isc != NULL) &&
+ ((is->is_flags & IS_SC_MATCHALL) != IS_SC_MATCHALL) &&
+ !(is->is_flags & (IS_SC_CLIENT|IS_SC_SERVER))) {
+ /*
+ * Matching failed...
+ */
+ j = isc->ipsc_else;
+ ipsc_stat.iscs_else++;
+ }
+
+ switch (j)
+ {
+ case ISC_A_CLOSE :
+ /*
+ * If as a result of a successful match we are to
+ * close a connection, change the "keep state" info.
+ * to block packets and generate TCP RST's.
+ */
+ is->is_pass &= ~FR_RETICMP;
+ is->is_pass |= FR_RETRST;
+ break;
+ default :
+ break;
+ }
+
+ return i;
+}
+
+
+/*
+ * check if a packet matches what we're scanning for
+ */
+int ipsc_packet(fin, is)
+fr_info_t *fin;
+ipstate_t *is;
+{
+ int i, j, rv, dlen, off, thoff;
+ u_32_t seq, s0;
+ tcphdr_t *tcp;
+
+ rv = !IP6_EQ(&fin->fin_fi.fi_src, &is->is_src);
+ tcp = fin->fin_dp;
+ seq = ntohl(tcp->th_seq);
+
+ if (!is->is_s0[rv])
+ return 1;
+
+ /*
+ * check if this packet has more data that falls within the first
+ * 16 bytes sent in either direction.
+ */
+ s0 = is->is_s0[rv];
+ off = seq - s0;
+ if ((off > 15) || (off < 0))
+ return 1;
+ thoff = TCP_OFF(tcp) << 2;
+ dlen = fin->fin_dlen - thoff;
+ if (dlen <= 0)
+ return 1;
+ if (dlen > 16)
+ dlen = 16;
+ if (off + dlen > 16)
+ dlen = 16 - off;
+
+ j = 0xffff >> (16 - dlen);
+ i = (0xffff & j) << off;
+#ifdef _KERNEL
+ COPYDATA(*(mb_t **)fin->fin_mp, fin->fin_hlen + thoff, dlen,
+ (caddr_t)is->is_sbuf[rv] + off);
+#endif
+ is->is_smsk[rv] |= i;
+ for (j = 0, i = is->is_smsk[rv]; i & 1; i >>= 1)
+ j++;
+ if (j == 0)
+ return 1;
+
+ (void) ipsc_match(is);
+#if 0
+ /*
+ * There is the potential here for plain text passwords to get
+ * buffered and stored for some time...
+ */
+ if (!(is->is_flags & IS_SC_CLIENT))
+ bzero(is->is_sbuf[0], sizeof(is->is_sbuf[0]));
+ if (!(is->is_flags & IS_SC_SERVER))
+ bzero(is->is_sbuf[1], sizeof(is->is_sbuf[1]));
+#endif
+ return 0;
+}
+
+
+int fr_scan_ioctl(data, cmd, mode)
+caddr_t data;
+ioctlcmd_t cmd;
+int mode;
+{
+ ipscanstat_t ipscs;
+ int err = 0;
+
+ switch (cmd)
+ {
+ case SIOCADSCA :
+ err = ipsc_add(data);
+ break;
+ case SIOCRMSCA :
+ err = ipsc_delete(data);
+ break;
+ case SIOCGSCST :
+ bcopy((char *)&ipsc_stat, (char *)&ipscs, sizeof(ipscs));
+ ipscs.iscs_list = ipsc_list;
+ BCOPYOUT(&ipscs, data, sizeof(ipscs));
+ break;
+ default :
+ err = EINVAL;
+ break;
+ }
+
+ return err;
+}
+#endif /* IPFILTER_SCAN */
diff --git a/contrib/ipfilter/ip_scan.h b/contrib/ipfilter/ip_scan.h
new file mode 100644
index 0000000..de98f9c
--- /dev/null
+++ b/contrib/ipfilter/ip_scan.h
@@ -0,0 +1,108 @@
+/* $NetBSD$ */
+
+/*
+ * Copyright (C) 1993-2001 by Darren Reed.
+ *
+ * See the IPFILTER.LICENCE file for details on licencing.
+ *
+ * @(#)ip_fil.h 1.35 6/5/96
+ * Id: ip_scan.h,v 2.9 2003/07/25 22:05:01 darrenr Exp
+ */
+
+#ifndef __IP_SCAN_H__
+#define __IP_SCAN_H__ 1
+
+#ifdef sun
+# include <sys/ioccom.h>
+#endif
+
+#define IPSCAN_NAME "/dev/ipscan"
+#define IPL_SCAN IPSCAN_NAME
+#define ISC_TLEN 16
+
+
+struct fr_info;
+struct frentry;
+struct ip;
+struct ipstate;
+
+
+#if defined(__STDC__) || defined(__GNUC__)
+# define SIOCADSCA _IOWR('r', 60, struct ipscan *)
+# define SIOCRMSCA _IOWR('r', 61, struct ipscan *)
+# define SIOCGSCST _IOWR('r', 62, struct ipscan *)
+#else
+# define SIOCADSCA _IOWR(r, 60, struct ipscan *)
+# define SIOCRMSCA _IOWR(r, 61, struct ipscan *)
+# define SIOCGSCST _IOWR(r, 62, struct ipscan *)
+#endif
+
+struct action {
+ int act_val; /* what to do */
+ struct in_addr act_ip; /* redirect IP# */
+ u_short act_port; /* redirect port number */
+ int act_else; /* what to do */
+ struct in_addr act_eip; /* redirect IP# */
+ u_short act_eport; /* redirect port number */
+};
+
+
+typedef struct sinfo {
+ char s_txt[ISC_TLEN]; /* text to match */
+ char s_msk[ISC_TLEN]; /* mask of the above to check */
+ int s_len; /* length of server text */
+} sinfo_t;
+
+
+typedef struct ipscan {
+ struct ipscan *ipsc_next;
+ struct ipscan **ipsc_pnext;
+ char ipsc_tag[ISC_TLEN]; /* table entry protocol tag */
+ sinfo_t ipsc_si[2]; /* client/server side information */
+ int ipsc_hits; /* times this has been matched */
+ int ipsc_active; /* # of active matches */
+ int ipsc_fref; /* # of references from filter rules */
+ int ipsc_sref; /* # of references from state entries */
+ struct action ipsc_act;
+} ipscan_t;
+
+
+#define ipsc_cl ipsc_si[0]
+#define ipsc_sl ipsc_si[1]
+#define ipsc_ctxt ipsc_cl.s_txt
+#define ipsc_cmsk ipsc_cl.s_msk
+#define ipsc_clen ipsc_cl.s_len
+#define ipsc_stxt ipsc_sl.s_txt
+#define ipsc_smsk ipsc_sl.s_msk
+#define ipsc_slen ipsc_sl.s_len
+#define ipsc_action ipsc_act.act_val
+#define ipsc_ip ipsc_act.act_ip
+#define ipsc_port ipsc_act.act_port
+#define ipsc_else ipsc_act.act_else
+#define ipsc_eip ipsc_act.act_eip
+#define ipsc_eport ipsc_act.act_eport
+
+#define ISC_A_NONE 0
+#define ISC_A_TRACK 1
+#define ISC_A_CLOSE 2
+#define ISC_A_REDIRECT 3
+
+
+typedef struct ipscanstat {
+ struct ipscan *iscs_list;
+ u_long iscs_acted;
+ u_long iscs_else;
+ int iscs_entries;
+} ipscanstat_t;
+
+
+extern int fr_scan_ioctl __P((caddr_t, ioctlcmd_t, int));
+extern int ipsc_init __P((void));
+extern int ipsc_attachis __P((struct ipstate *));
+extern int ipsc_attachfr __P((struct frentry *));
+extern int ipsc_detachis __P((struct ipstate *));
+extern int ipsc_detachfr __P((struct frentry *));
+extern int ipsc_packet __P((struct fr_info *, struct ipstate *));
+extern void fr_scanunload __P((void));
+
+#endif /* __IP_SCAN_H__ */
diff --git a/contrib/ipfilter/ip_sync.c b/contrib/ipfilter/ip_sync.c
new file mode 100644
index 0000000..396bae7
--- /dev/null
+++ b/contrib/ipfilter/ip_sync.c
@@ -0,0 +1,1001 @@
+/* $NetBSD$ */
+
+/*
+ * Copyright (C) 1995-1998 by Darren Reed.
+ *
+ * See the IPFILTER.LICENCE file for details on licencing.
+ */
+#if defined(KERNEL) || defined(_KERNEL)
+# undef KERNEL
+# undef _KERNEL
+# define KERNEL 1
+# define _KERNEL 1
+#endif
+#include <sys/errno.h>
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/file.h>
+#if !defined(_KERNEL) && !defined(__KERNEL__)
+# include <stdio.h>
+# include <stdlib.h>
+# include <string.h>
+# define _KERNEL
+# define KERNEL
+# ifdef __OpenBSD__
+struct file;
+# endif
+# include <sys/uio.h>
+# undef _KERNEL
+# undef KERNEL
+#else
+# include <sys/systm.h>
+# if !defined(__SVR4) && !defined(__svr4__)
+# include <sys/mbuf.h>
+# endif
+#endif
+#if defined(__NetBSD__) && (__NetBSD_Version__ >= 104000000)
+# include <sys/proc.h>
+#endif
+#if defined(_KERNEL) && (__FreeBSD_version >= 220000)
+# include <sys/filio.h>
+# include <sys/fcntl.h>
+# if (__FreeBSD_version >= 300000) && !defined(IPFILTER_LKM)
+# include "opt_ipfilter.h"
+# endif
+#else
+# include <sys/ioctl.h>
+#endif
+#include <sys/time.h>
+#if !defined(linux)
+# include <sys/protosw.h>
+#endif
+#include <sys/socket.h>
+#if defined(__SVR4) || defined(__svr4__)
+# include <sys/filio.h>
+# include <sys/byteorder.h>
+# ifdef _KERNEL
+# include <sys/dditypes.h>
+# endif
+# 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/tcp.h>
+#if !defined(linux)
+# include <netinet/ip_var.h>
+#endif
+#if !defined(__hpux) && !defined(linux)
+# include <netinet/tcp_fsm.h>
+#endif
+#include <netinet/udp.h>
+#include <netinet/ip_icmp.h>
+#include "netinet/ip_compat.h"
+#include <netinet/tcpip.h>
+#include "netinet/ip_fil.h"
+#include "netinet/ip_nat.h"
+#include "netinet/ip_frag.h"
+#include "netinet/ip_state.h"
+#include "netinet/ip_proxy.h"
+#include "netinet/ip_sync.h"
+#ifdef USE_INET6
+#include <netinet/icmp6.h>
+#endif
+#if (__FreeBSD_version >= 300000)
+# include <sys/malloc.h>
+# if defined(_KERNEL) && !defined(IPFILTER_LKM)
+# include <sys/libkern.h>
+# include <sys/systm.h>
+# endif
+#endif
+/* END OF INCLUDES */
+
+#if !defined(lint)
+static const char rcsid[] = "@(#)Id: ip_sync.c,v 2.40.2.3 2005/02/18 13:06:29 darrenr Exp";
+#endif
+
+#define SYNC_STATETABSZ 256
+#define SYNC_NATTABSZ 256
+
+#ifdef IPFILTER_SYNC
+ipfmutex_t ipf_syncadd, ipsl_mutex;
+ipfrwlock_t ipf_syncstate, ipf_syncnat;
+#if SOLARIS && defined(_KERNEL)
+kcondvar_t ipslwait;
+#endif
+synclist_t *syncstatetab[SYNC_STATETABSZ];
+synclist_t *syncnattab[SYNC_NATTABSZ];
+synclogent_t synclog[SYNCLOG_SZ];
+syncupdent_t syncupd[SYNCLOG_SZ];
+u_int ipf_syncnum = 1;
+u_int ipf_syncwrap = 0;
+u_int sl_idx = 0, /* next available sync log entry */
+ su_idx = 0, /* next available sync update entry */
+ sl_tail = 0, /* next sync log entry to read */
+ su_tail = 0; /* next sync update entry to read */
+int ipf_sync_debug = 0;
+
+
+# if !defined(sparc) && !defined(__hppa)
+void ipfsync_tcporder __P((int, struct tcpdata *));
+void ipfsync_natorder __P((int, struct nat *));
+void ipfsync_storder __P((int, struct ipstate *));
+# endif
+
+
+/* ------------------------------------------------------------------------ */
+/* Function: ipfsync_init */
+/* Returns: int - 0 == success, -1 == failure */
+/* Parameters: Nil */
+/* */
+/* Initialise all of the locks required for the sync code and initialise */
+/* any data structures, as required. */
+/* ------------------------------------------------------------------------ */
+int ipfsync_init()
+{
+ RWLOCK_INIT(&ipf_syncstate, "add things to state sync table");
+ RWLOCK_INIT(&ipf_syncnat, "add things to nat sync table");
+ MUTEX_INIT(&ipf_syncadd, "add things to sync table");
+ MUTEX_INIT(&ipsl_mutex, "add things to sync table");
+# if SOLARIS && defined(_KERNEL)
+ cv_init(&ipslwait, "ipsl condvar", CV_DRIVER, NULL);
+# endif
+
+ bzero((char *)syncnattab, sizeof(syncnattab));
+ bzero((char *)syncstatetab, sizeof(syncstatetab));
+
+ return 0;
+}
+
+
+# if !defined(sparc) && !defined(__hppa)
+/* ------------------------------------------------------------------------ */
+/* Function: ipfsync_tcporder */
+/* Returns: Nil */
+/* Parameters: way(I) - direction of byte order conversion. */
+/* td(IO) - pointer to data to be converted. */
+/* */
+/* Do byte swapping on values in the TCP state information structure that */
+/* need to be used at both ends by the host in their native byte order. */
+/* ------------------------------------------------------------------------ */
+void ipfsync_tcporder(way, td)
+int way;
+tcpdata_t *td;
+{
+ if (way) {
+ td->td_maxwin = htons(td->td_maxwin);
+ td->td_end = htonl(td->td_end);
+ td->td_maxend = htonl(td->td_maxend);
+ } else {
+ td->td_maxwin = ntohs(td->td_maxwin);
+ td->td_end = ntohl(td->td_end);
+ td->td_maxend = ntohl(td->td_maxend);
+ }
+}
+
+
+/* ------------------------------------------------------------------------ */
+/* Function: ipfsync_natorder */
+/* Returns: Nil */
+/* Parameters: way(I) - direction of byte order conversion. */
+/* nat(IO) - pointer to data to be converted. */
+/* */
+/* Do byte swapping on values in the NAT data structure that need to be */
+/* used at both ends by the host in their native byte order. */
+/* ------------------------------------------------------------------------ */
+void ipfsync_natorder(way, n)
+int way;
+nat_t *n;
+{
+ if (way) {
+ n->nat_age = htonl(n->nat_age);
+ n->nat_flags = htonl(n->nat_flags);
+ n->nat_ipsumd = htonl(n->nat_ipsumd);
+ n->nat_use = htonl(n->nat_use);
+ n->nat_dir = htonl(n->nat_dir);
+ } else {
+ n->nat_age = ntohl(n->nat_age);
+ n->nat_flags = ntohl(n->nat_flags);
+ n->nat_ipsumd = ntohl(n->nat_ipsumd);
+ n->nat_use = ntohl(n->nat_use);
+ n->nat_dir = ntohl(n->nat_dir);
+ }
+}
+
+
+/* ------------------------------------------------------------------------ */
+/* Function: ipfsync_storder */
+/* Returns: Nil */
+/* Parameters: way(I) - direction of byte order conversion. */
+/* ips(IO) - pointer to data to be converted. */
+/* */
+/* Do byte swapping on values in the IP state data structure that need to */
+/* be used at both ends by the host in their native byte order. */
+/* ------------------------------------------------------------------------ */
+void ipfsync_storder(way, ips)
+int way;
+ipstate_t *ips;
+{
+ ipfsync_tcporder(way, &ips->is_tcp.ts_data[0]);
+ ipfsync_tcporder(way, &ips->is_tcp.ts_data[1]);
+
+ if (way) {
+ ips->is_hv = htonl(ips->is_hv);
+ ips->is_die = htonl(ips->is_die);
+ ips->is_pass = htonl(ips->is_pass);
+ ips->is_flags = htonl(ips->is_flags);
+ ips->is_opt = htonl(ips->is_opt);
+ ips->is_optmsk = htonl(ips->is_optmsk);
+ ips->is_sec = htons(ips->is_sec);
+ ips->is_secmsk = htons(ips->is_secmsk);
+ ips->is_auth = htons(ips->is_auth);
+ ips->is_authmsk = htons(ips->is_authmsk);
+ ips->is_s0[0] = htonl(ips->is_s0[0]);
+ ips->is_s0[1] = htonl(ips->is_s0[1]);
+ ips->is_smsk[0] = htons(ips->is_smsk[0]);
+ ips->is_smsk[1] = htons(ips->is_smsk[1]);
+ } else {
+ ips->is_hv = ntohl(ips->is_hv);
+ ips->is_die = ntohl(ips->is_die);
+ ips->is_pass = ntohl(ips->is_pass);
+ ips->is_flags = ntohl(ips->is_flags);
+ ips->is_opt = ntohl(ips->is_opt);
+ ips->is_optmsk = ntohl(ips->is_optmsk);
+ ips->is_sec = ntohs(ips->is_sec);
+ ips->is_secmsk = ntohs(ips->is_secmsk);
+ ips->is_auth = ntohs(ips->is_auth);
+ ips->is_authmsk = ntohs(ips->is_authmsk);
+ ips->is_s0[0] = ntohl(ips->is_s0[0]);
+ ips->is_s0[1] = ntohl(ips->is_s0[1]);
+ ips->is_smsk[0] = ntohl(ips->is_smsk[0]);
+ ips->is_smsk[1] = ntohl(ips->is_smsk[1]);
+ }
+}
+# else /* !defined(sparc) && !defined(__hppa) */
+# define ipfsync_tcporder(x,y)
+# define ipfsync_natorder(x,y)
+# define ipfsync_storder(x,y)
+# endif /* !defined(sparc) && !defined(__hppa) */
+
+/* enable this for debugging */
+
+# ifdef _KERNEL
+/* ------------------------------------------------------------------------ */
+/* Function: ipfsync_write */
+/* Returns: int - 0 == success, else error value. */
+/* Parameters: uio(I) - pointer to information about data to write */
+/* */
+/* Moves data from user space into the kernel and uses it for updating data */
+/* structures in the state/NAT tables. */
+/* ------------------------------------------------------------------------ */
+int ipfsync_write(uio)
+struct uio *uio;
+{
+ synchdr_t sh;
+
+ /*
+ * THIS MUST BE SUFFICIENT LARGE TO STORE
+ * ANY POSSIBLE DATA TYPE
+ */
+ char data[2048];
+
+ int err = 0;
+
+# if (BSD >= 199306) || defined(__FreeBSD__) || defined(__osf__)
+ uio->uio_rw = UIO_WRITE;
+# endif
+
+ /* Try to get bytes */
+ while (uio->uio_resid > 0) {
+
+ if (uio->uio_resid >= sizeof(sh)) {
+
+ err = UIOMOVE((caddr_t)&sh, sizeof(sh), UIO_WRITE, uio);
+
+ if (err) {
+ if (ipf_sync_debug > 2)
+ printf("uiomove(header) failed: %d\n",
+ err);
+ return err;
+ }
+
+ /* convert to host order */
+ sh.sm_magic = ntohl(sh.sm_magic);
+ sh.sm_len = ntohl(sh.sm_len);
+ sh.sm_num = ntohl(sh.sm_num);
+
+ if (ipf_sync_debug > 8)
+ printf("[%d] Read v:%d p:%d cmd:%d table:%d rev:%d len:%d magic:%x\n",
+ sh.sm_num, sh.sm_v, sh.sm_p, sh.sm_cmd,
+ sh.sm_table, sh.sm_rev, sh.sm_len,
+ sh.sm_magic);
+
+ if (sh.sm_magic != SYNHDRMAGIC) {
+ if (ipf_sync_debug > 2)
+ printf("uiomove(header) invalud %s\n",
+ "magic");
+ return EINVAL;
+ }
+
+ if (sh.sm_v != 4 && sh.sm_v != 6) {
+ if (ipf_sync_debug > 2)
+ printf("uiomove(header) invalid %s\n",
+ "protocol");
+ return EINVAL;
+ }
+
+ if (sh.sm_cmd > SMC_MAXCMD) {
+ if (ipf_sync_debug > 2)
+ printf("uiomove(header) invalid %s\n",
+ "command");
+ return EINVAL;
+ }
+
+
+ if (sh.sm_table > SMC_MAXTBL) {
+ if (ipf_sync_debug > 2)
+ printf("uiomove(header) invalid %s\n",
+ "table");
+ return EINVAL;
+ }
+
+ } else {
+ /* unsufficient data, wait until next call */
+ if (ipf_sync_debug > 2)
+ printf("uiomove(header) insufficient data");
+ return EAGAIN;
+ }
+
+
+ /*
+ * We have a header, so try to read the amount of data
+ * needed for the request
+ */
+
+ /* not supported */
+ if (sh.sm_len == 0) {
+ if (ipf_sync_debug > 2)
+ printf("uiomove(data zero length %s\n",
+ "not supported");
+ return EINVAL;
+ }
+
+ if (uio->uio_resid >= sh.sm_len) {
+
+ err = UIOMOVE((caddr_t)data, sh.sm_len, UIO_WRITE, uio);
+
+ if (err) {
+ if (ipf_sync_debug > 2)
+ printf("uiomove(data) failed: %d\n",
+ err);
+ return err;
+ }
+
+ if (ipf_sync_debug > 7)
+ printf("uiomove(data) %d bytes read\n",
+ sh.sm_len);
+
+ if (sh.sm_table == SMC_STATE)
+ err = ipfsync_state(&sh, data);
+ else if (sh.sm_table == SMC_NAT)
+ err = ipfsync_nat(&sh, data);
+ if (ipf_sync_debug > 7)
+ printf("[%d] Finished with error %d\n",
+ sh.sm_num, err);
+
+ } else {
+ /* insufficient data, wait until next call */
+ if (ipf_sync_debug > 2)
+ printf("uiomove(data) %s %d bytes, got %d\n",
+ "insufficient data, need",
+ sh.sm_len, uio->uio_resid);
+ return EAGAIN;
+ }
+ }
+
+ /* no more data */
+ return 0;
+}
+
+
+/* ------------------------------------------------------------------------ */
+/* Function: ipfsync_read */
+/* Returns: int - 0 == success, else error value. */
+/* Parameters: uio(O) - pointer to information about where to store data */
+/* */
+/* This function is called when a user program wants to read some data */
+/* for pending state/NAT updates. If no data is available, the caller is */
+/* put to sleep, pending a wakeup from the "lower half" of this code. */
+/* ------------------------------------------------------------------------ */
+int ipfsync_read(uio)
+struct uio *uio;
+{
+ syncupdent_t *su;
+ synclogent_t *sl;
+ int err = 0;
+
+ if ((uio->uio_resid & 3) || (uio->uio_resid < 8))
+ return EINVAL;
+
+# if (BSD >= 199306) || defined(__FreeBSD__) || defined(__osf__)
+ uio->uio_rw = UIO_READ;
+# endif
+
+ MUTEX_ENTER(&ipsl_mutex);
+ while ((sl_tail == sl_idx) && (su_tail == su_idx)) {
+# if SOLARIS && defined(_KERNEL)
+ if (!cv_wait_sig(&ipslwait, &ipsl_mutex)) {
+ MUTEX_EXIT(&ipsl_mutex);
+ return EINTR;
+ }
+# else
+# ifdef __hpux
+ {
+ lock_t *l;
+
+ l = get_sleep_lock(&sl_tail);
+ err = sleep(&sl_tail, PZERO+1);
+ spinunlock(l);
+ }
+# else /* __hpux */
+# ifdef __osf__
+ err = mpsleep(&sl_tail, PSUSP|PCATCH, "ipl sleep", 0,
+ &ipsl_mutex, MS_LOCK_SIMPLE);
+# else
+ MUTEX_EXIT(&ipsl_mutex);
+ err = SLEEP(&sl_tail, "ipl sleep");
+# endif /* __osf__ */
+# endif /* __hpux */
+ if (err) {
+ MUTEX_EXIT(&ipsl_mutex);
+ return err;
+ }
+# endif /* SOLARIS */
+ }
+ MUTEX_EXIT(&ipsl_mutex);
+
+ READ_ENTER(&ipf_syncstate);
+ while ((sl_tail < sl_idx) && (uio->uio_resid > sizeof(*sl))) {
+ sl = synclog + sl_tail++;
+ err = UIOMOVE((caddr_t)sl, sizeof(*sl), UIO_READ, uio);
+ if (err != 0)
+ break;
+ }
+
+ while ((su_tail < su_idx) && (uio->uio_resid > sizeof(*su))) {
+ su = syncupd + su_tail;
+ su_tail++;
+ err = UIOMOVE((caddr_t)su, sizeof(*su), UIO_READ, uio);
+ if (err != 0)
+ break;
+ if (su->sup_hdr.sm_sl != NULL)
+ su->sup_hdr.sm_sl->sl_idx = -1;
+ }
+
+ MUTEX_ENTER(&ipf_syncadd);
+ if (su_tail == su_idx)
+ su_tail = su_idx = 0;
+ if (sl_tail == sl_idx)
+ sl_tail = sl_idx = 0;
+ MUTEX_EXIT(&ipf_syncadd);
+ RWLOCK_EXIT(&ipf_syncstate);
+ return err;
+}
+
+
+/* ------------------------------------------------------------------------ */
+/* Function: ipfsync_state */
+/* Returns: int - 0 == success, else error value. */
+/* Parameters: sp(I) - pointer to sync packet data header */
+/* uio(I) - pointer to user data for further information */
+/* */
+/* Updates the state table according to information passed in the sync */
+/* header. As required, more data is fetched from the uio structure but */
+/* varies depending on the contents of the sync header. This function can */
+/* create a new state entry or update one. Deletion is left to the state */
+/* structures being timed out correctly. */
+/* ------------------------------------------------------------------------ */
+int ipfsync_state(sp, data)
+synchdr_t *sp;
+void *data;
+{
+ synctcp_update_t su;
+ ipstate_t *is, sn;
+ synclist_t *sl;
+ frentry_t *fr;
+ u_int hv;
+ int err = 0;
+
+ hv = sp->sm_num & (SYNC_STATETABSZ - 1);
+
+ switch (sp->sm_cmd)
+ {
+ case SMC_CREATE :
+
+ bcopy(data, &sn, sizeof(sn));
+ KMALLOC(is, ipstate_t *);
+ if (is == NULL) {
+ err = ENOMEM;
+ break;
+ }
+
+ KMALLOC(sl, synclist_t *);
+ if (sl == NULL) {
+ err = ENOMEM;
+ KFREE(is);
+ break;
+ }
+
+ bzero((char *)is, offsetof(ipstate_t, is_die));
+ bcopy((char *)&sn.is_die, (char *)&is->is_die,
+ sizeof(*is) - offsetof(ipstate_t, is_die));
+ ipfsync_storder(0, is);
+
+ /*
+ * We need to find the same rule on the slave as was used on
+ * the master to create this state entry.
+ */
+ READ_ENTER(&ipf_mutex);
+ fr = fr_getrulen(IPL_LOGIPF, sn.is_group, sn.is_rulen);
+ if (fr != NULL) {
+ MUTEX_ENTER(&fr->fr_lock);
+ fr->fr_ref++;
+ fr->fr_statecnt++;
+ MUTEX_EXIT(&fr->fr_lock);
+ }
+ RWLOCK_EXIT(&ipf_mutex);
+
+ if (ipf_sync_debug > 4)
+ printf("[%d] Filter rules = %p\n", sp->sm_num, fr);
+
+ is->is_rule = fr;
+ is->is_sync = sl;
+
+ sl->sl_idx = -1;
+ sl->sl_ips = is;
+ bcopy(sp, &sl->sl_hdr, sizeof(struct synchdr));
+
+ WRITE_ENTER(&ipf_syncstate);
+ WRITE_ENTER(&ipf_state);
+
+ sl->sl_pnext = syncstatetab + hv;
+ sl->sl_next = syncstatetab[hv];
+ if (syncstatetab[hv] != NULL)
+ syncstatetab[hv]->sl_pnext = &sl->sl_next;
+ syncstatetab[hv] = sl;
+ MUTEX_DOWNGRADE(&ipf_syncstate);
+ fr_stinsert(is, sp->sm_rev);
+ /*
+ * Do not initialise the interface pointers for the state
+ * entry as the full complement of interface names may not
+ * be present.
+ *
+ * Put this state entry on its timeout queue.
+ */
+ /*fr_setstatequeue(is, sp->sm_rev);*/
+ break;
+
+ case SMC_UPDATE :
+ bcopy(data, &su, sizeof(su));
+
+ if (ipf_sync_debug > 4)
+ printf("[%d] Update age %lu state %d/%d \n",
+ sp->sm_num, su.stu_age, su.stu_state[0],
+ su.stu_state[1]);
+
+ READ_ENTER(&ipf_syncstate);
+ for (sl = syncstatetab[hv]; (sl != NULL); sl = sl->sl_next)
+ if (sl->sl_hdr.sm_num == sp->sm_num)
+ break;
+ if (sl == NULL) {
+ if (ipf_sync_debug > 1)
+ printf("[%d] State not found - can't update\n",
+ sp->sm_num);
+ RWLOCK_EXIT(&ipf_syncstate);
+ err = ENOENT;
+ break;
+ }
+
+ READ_ENTER(&ipf_state);
+
+ if (ipf_sync_debug > 6)
+ printf("[%d] Data from state v:%d p:%d cmd:%d table:%d rev:%d\n",
+ sp->sm_num, sl->sl_hdr.sm_v, sl->sl_hdr.sm_p,
+ sl->sl_hdr.sm_cmd, sl->sl_hdr.sm_table,
+ sl->sl_hdr.sm_rev);
+
+ is = sl->sl_ips;
+
+ MUTEX_ENTER(&is->is_lock);
+ switch (sp->sm_p)
+ {
+ case IPPROTO_TCP :
+ /* XXX FV --- shouldn't we do ntohl/htonl???? XXX */
+ is->is_send = su.stu_data[0].td_end;
+ is->is_maxsend = su.stu_data[0].td_maxend;
+ is->is_maxswin = su.stu_data[0].td_maxwin;
+ is->is_state[0] = su.stu_state[0];
+ is->is_dend = su.stu_data[1].td_end;
+ is->is_maxdend = su.stu_data[1].td_maxend;
+ is->is_maxdwin = su.stu_data[1].td_maxwin;
+ is->is_state[1] = su.stu_state[1];
+ break;
+ default :
+ break;
+ }
+
+ if (ipf_sync_debug > 6)
+ printf("[%d] Setting timers for state\n", sp->sm_num);
+
+ fr_setstatequeue(is, sp->sm_rev);
+
+ MUTEX_EXIT(&is->is_lock);
+ break;
+
+ default :
+ err = EINVAL;
+ break;
+ }
+
+ if (err == 0) {
+ RWLOCK_EXIT(&ipf_state);
+ RWLOCK_EXIT(&ipf_syncstate);
+ }
+
+ if (ipf_sync_debug > 6)
+ printf("[%d] Update completed with error %d\n",
+ sp->sm_num, err);
+
+ return err;
+}
+# endif /* _KERNEL */
+
+
+/* ------------------------------------------------------------------------ */
+/* Function: ipfsync_del */
+/* Returns: Nil */
+/* Parameters: sl(I) - pointer to synclist object to delete */
+/* */
+/* Deletes an object from the synclist table and free's its memory. */
+/* ------------------------------------------------------------------------ */
+void ipfsync_del(sl)
+synclist_t *sl;
+{
+ WRITE_ENTER(&ipf_syncstate);
+ *sl->sl_pnext = sl->sl_next;
+ if (sl->sl_next != NULL)
+ sl->sl_next->sl_pnext = sl->sl_pnext;
+ if (sl->sl_idx != -1)
+ syncupd[sl->sl_idx].sup_hdr.sm_sl = NULL;
+ RWLOCK_EXIT(&ipf_syncstate);
+ KFREE(sl);
+}
+
+
+/* ------------------------------------------------------------------------ */
+/* Function: ipfsync_nat */
+/* Returns: int - 0 == success, else error value. */
+/* Parameters: sp(I) - pointer to sync packet data header */
+/* uio(I) - pointer to user data for further information */
+/* */
+/* Updates the NAT table according to information passed in the sync */
+/* header. As required, more data is fetched from the uio structure but */
+/* varies depending on the contents of the sync header. This function can */
+/* create a new NAT entry or update one. Deletion is left to the NAT */
+/* structures being timed out correctly. */
+/* ------------------------------------------------------------------------ */
+int ipfsync_nat(sp, data)
+synchdr_t *sp;
+void *data;
+{
+ synclogent_t sle;
+ syncupdent_t su;
+ nat_t *n, *nat;
+ synclist_t *sl;
+ u_int hv = 0;
+ int err;
+
+ READ_ENTER(&ipf_syncstate);
+
+ switch (sp->sm_cmd)
+ {
+ case SMC_CREATE :
+ bcopy(data, &sle, sizeof(sle));
+
+ KMALLOC(n, nat_t *);
+ if (n == NULL) {
+ err = ENOMEM;
+ break;
+ }
+
+ KMALLOC(sl, synclist_t *);
+ if (sl == NULL) {
+ err = ENOMEM;
+ KFREE(n);
+ break;
+ }
+
+ WRITE_ENTER(&ipf_nat);
+
+ nat = &sle.sle_un.sleu_ipn;
+ bzero((char *)n, offsetof(nat_t, nat_age));
+ bcopy((char *)&nat->nat_age, (char *)&n->nat_age,
+ sizeof(*n) - offsetof(nat_t, nat_age));
+ ipfsync_natorder(0, n);
+ n->nat_sync = sl;
+
+ sl->sl_idx = -1;
+ sl->sl_ipn = n;
+ sl->sl_num = ntohl(sp->sm_num);
+ sl->sl_pnext = syncstatetab + hv;
+ sl->sl_next = syncstatetab[hv];
+ if (syncstatetab[hv] != NULL)
+ syncstatetab[hv]->sl_pnext = &sl->sl_next;
+ syncstatetab[hv] = sl;
+ nat_insert(n, sl->sl_rev);
+ RWLOCK_EXIT(&ipf_nat);
+ break;
+
+ case SMC_UPDATE :
+ bcopy(data, &su, sizeof(su));
+
+ READ_ENTER(&ipf_syncstate);
+ for (sl = syncstatetab[hv]; (sl != NULL); sl = sl->sl_next)
+ if (sl->sl_hdr.sm_num == sp->sm_num)
+ break;
+ if (sl == NULL) {
+ err = ENOENT;
+ break;
+ }
+
+ READ_ENTER(&ipf_nat);
+
+ nat = sl->sl_ipn;
+
+ MUTEX_ENTER(&nat->nat_lock);
+ fr_setnatqueue(nat, sl->sl_rev);
+ MUTEX_EXIT(&nat->nat_lock);
+
+ RWLOCK_EXIT(&ipf_nat);
+
+ break;
+
+ default :
+ err = EINVAL;
+ break;
+ }
+
+ RWLOCK_EXIT(&ipf_syncstate);
+ return 0;
+}
+
+
+/* ------------------------------------------------------------------------ */
+/* Function: ipfsync_new */
+/* Returns: synclist_t* - NULL == failure, else pointer to new synclist */
+/* data structure. */
+/* Parameters: tab(I) - type of synclist_t to create */
+/* fin(I) - pointer to packet information */
+/* ptr(I) - pointer to owning object */
+/* */
+/* Creates a new sync table entry and notifies any sleepers that it's there */
+/* waiting to be processed. */
+/* ------------------------------------------------------------------------ */
+synclist_t *ipfsync_new(tab, fin, ptr)
+int tab;
+fr_info_t *fin;
+void *ptr;
+{
+ synclist_t *sl, *ss;
+ synclogent_t *sle;
+ u_int hv, sz;
+
+ if (sl_idx == SYNCLOG_SZ)
+ return NULL;
+ KMALLOC(sl, synclist_t *);
+ if (sl == NULL)
+ return NULL;
+
+ MUTEX_ENTER(&ipf_syncadd);
+ /*
+ * Get a unique number for this synclist_t. The number is only meant
+ * to be unique for the lifetime of the structure and may be reused
+ * later.
+ */
+ ipf_syncnum++;
+ if (ipf_syncnum == 0) {
+ ipf_syncnum = 1;
+ ipf_syncwrap = 1;
+ }
+
+ hv = ipf_syncnum & (SYNC_STATETABSZ - 1);
+ while (ipf_syncwrap != 0) {
+ for (ss = syncstatetab[hv]; ss; ss = ss->sl_next)
+ if (ss->sl_hdr.sm_num == ipf_syncnum)
+ break;
+ if (ss == NULL)
+ break;
+ ipf_syncnum++;
+ hv = ipf_syncnum & (SYNC_STATETABSZ - 1);
+ }
+ /*
+ * Use the synch number of the object as the hash key. Should end up
+ * with relatively even distribution over time.
+ * XXX - an attacker could lunch an DoS attack, of sorts, if they are
+ * the only one causing new table entries by only keeping open every
+ * nth connection they make, where n is a value in the interval
+ * [0, SYNC_STATETABSZ-1].
+ */
+ sl->sl_pnext = syncstatetab + hv;
+ sl->sl_next = syncstatetab[hv];
+ syncstatetab[hv] = sl;
+ sl->sl_num = ipf_syncnum;
+ MUTEX_EXIT(&ipf_syncadd);
+
+ sl->sl_magic = htonl(SYNHDRMAGIC);
+ sl->sl_v = fin->fin_v;
+ sl->sl_p = fin->fin_p;
+ sl->sl_cmd = SMC_CREATE;
+ sl->sl_idx = -1;
+ sl->sl_table = tab;
+ sl->sl_rev = fin->fin_rev;
+ if (tab == SMC_STATE) {
+ sl->sl_ips = ptr;
+ sz = sizeof(*sl->sl_ips);
+ } else if (tab == SMC_NAT) {
+ sl->sl_ipn = ptr;
+ sz = sizeof(*sl->sl_ipn);
+ } else {
+ ptr = NULL;
+ sz = 0;
+ }
+ sl->sl_len = sz;
+
+ /*
+ * Create the log entry to be read by a user daemon. When it has been
+ * finished and put on the queue, send a signal to wakeup any waiters.
+ */
+ MUTEX_ENTER(&ipf_syncadd);
+ sle = synclog + sl_idx++;
+ bcopy((char *)&sl->sl_hdr, (char *)&sle->sle_hdr,
+ sizeof(sle->sle_hdr));
+ sle->sle_hdr.sm_num = htonl(sle->sle_hdr.sm_num);
+ sle->sle_hdr.sm_len = htonl(sle->sle_hdr.sm_len);
+ if (ptr != NULL) {
+ bcopy((char *)ptr, (char *)&sle->sle_un, sz);
+ if (tab == SMC_STATE) {
+ ipfsync_storder(1, &sle->sle_un.sleu_ips);
+ } else if (tab == SMC_NAT) {
+ ipfsync_natorder(1, &sle->sle_un.sleu_ipn);
+ }
+ }
+ MUTEX_EXIT(&ipf_syncadd);
+
+ MUTEX_ENTER(&ipsl_mutex);
+# if SOLARIS
+# ifdef _KERNEL
+ cv_signal(&ipslwait);
+# endif
+ MUTEX_EXIT(&ipsl_mutex);
+# else
+ MUTEX_EXIT(&ipsl_mutex);
+# ifdef _KERNEL
+ wakeup(&sl_tail);
+# endif
+# endif
+ return sl;
+}
+
+
+/* ------------------------------------------------------------------------ */
+/* Function: ipfsync_update */
+/* Returns: Nil */
+/* Parameters: tab(I) - type of synclist_t to create */
+/* fin(I) - pointer to packet information */
+/* sl(I) - pointer to synchronisation object */
+/* */
+/* For outbound packets, only, create an sync update record for the user */
+/* process to read. */
+/* ------------------------------------------------------------------------ */
+void ipfsync_update(tab, fin, sl)
+int tab;
+fr_info_t *fin;
+synclist_t *sl;
+{
+ synctcp_update_t *st;
+ syncupdent_t *slu;
+ ipstate_t *ips;
+ nat_t *nat;
+
+ if (fin->fin_out == 0 || sl == NULL)
+ return;
+
+ WRITE_ENTER(&ipf_syncstate);
+ MUTEX_ENTER(&ipf_syncadd);
+ if (sl->sl_idx == -1) {
+ slu = syncupd + su_idx;
+ sl->sl_idx = su_idx++;
+ bcopy((char *)&sl->sl_hdr, (char *)&slu->sup_hdr,
+ sizeof(slu->sup_hdr));
+ slu->sup_hdr.sm_magic = htonl(SYNHDRMAGIC);
+ slu->sup_hdr.sm_sl = sl;
+ slu->sup_hdr.sm_cmd = SMC_UPDATE;
+ slu->sup_hdr.sm_table = tab;
+ slu->sup_hdr.sm_num = htonl(sl->sl_num);
+ slu->sup_hdr.sm_len = htonl(sizeof(struct synctcp_update));
+ slu->sup_hdr.sm_rev = fin->fin_rev;
+# if 0
+ if (fin->fin_p == IPPROTO_TCP) {
+ st->stu_len[0] = 0;
+ st->stu_len[1] = 0;
+ }
+# endif
+ } else
+ slu = syncupd + sl->sl_idx;
+ MUTEX_EXIT(&ipf_syncadd);
+ MUTEX_DOWNGRADE(&ipf_syncstate);
+
+ /*
+ * Only TCP has complex timeouts, others just use default timeouts.
+ * For TCP, we only need to track the connection state and window.
+ */
+ if (fin->fin_p == IPPROTO_TCP) {
+ st = &slu->sup_tcp;
+ if (tab == SMC_STATE) {
+ ips = sl->sl_ips;
+ st->stu_age = htonl(ips->is_die);
+ st->stu_data[0].td_end = ips->is_send;
+ st->stu_data[0].td_maxend = ips->is_maxsend;
+ st->stu_data[0].td_maxwin = ips->is_maxswin;
+ st->stu_state[0] = ips->is_state[0];
+ st->stu_data[1].td_end = ips->is_dend;
+ st->stu_data[1].td_maxend = ips->is_maxdend;
+ st->stu_data[1].td_maxwin = ips->is_maxdwin;
+ st->stu_state[1] = ips->is_state[1];
+ } else if (tab == SMC_NAT) {
+ nat = sl->sl_ipn;
+ st->stu_age = htonl(nat->nat_age);
+ }
+ }
+ RWLOCK_EXIT(&ipf_syncstate);
+
+ MUTEX_ENTER(&ipsl_mutex);
+# if SOLARIS
+# ifdef _KERNEL
+ cv_signal(&ipslwait);
+# endif
+ MUTEX_EXIT(&ipsl_mutex);
+# else
+ MUTEX_EXIT(&ipsl_mutex);
+# ifdef _KERNEL
+ wakeup(&sl_tail);
+# endif
+# endif
+}
+
+
+/* ------------------------------------------------------------------------ */
+/* Function: fr_sync_ioctl */
+/* Returns: int - 0 == success, != 0 == failure */
+/* Parameters: data(I) - pointer to ioctl data */
+/* cmd(I) - ioctl command integer */
+/* mode(I) - file mode bits used with open */
+/* */
+/* This function currently does not handle any ioctls and so just returns */
+/* EINVAL on all occasions. */
+/* ------------------------------------------------------------------------ */
+int fr_sync_ioctl(data, cmd, mode)
+caddr_t data;
+ioctlcmd_t cmd;
+int mode;
+{
+ return EINVAL;
+}
+#endif /* IPFILTER_SYNC */
diff --git a/contrib/ipfilter/ip_sync.h b/contrib/ipfilter/ip_sync.h
new file mode 100644
index 0000000..e319a95
--- /dev/null
+++ b/contrib/ipfilter/ip_sync.h
@@ -0,0 +1,117 @@
+/* $NetBSD$ */
+
+/*
+ * Copyright (C) 1993-2001 by Darren Reed.
+ *
+ * See the IPFILTER.LICENCE file for details on licencing.
+ *
+ * @(#)ip_fil.h 1.35 6/5/96
+ * Id: ip_sync.h,v 2.11.2.2 2004/11/04 19:29:07 darrenr Exp
+ */
+
+#ifndef __IP_SYNC_H__
+#define __IP_SYNC_H__
+
+typedef struct synchdr {
+ u_32_t sm_magic; /* magic */
+ u_char sm_v; /* version: 4,6 */
+ u_char sm_p; /* protocol */
+ u_char sm_cmd; /* command */
+ u_char sm_table; /* NAT, STATE, etc */
+ u_int sm_num; /* table entry number */
+ int sm_rev; /* forward/reverse */
+ int sm_len; /* length of the data section */
+ struct synclist *sm_sl; /* back pointer to parent */
+} synchdr_t;
+
+
+#define SYNHDRMAGIC 0x0FF51DE5
+
+/*
+ * Commands
+ * No delete required as expirey will take care of that!
+ */
+#define SMC_CREATE 0 /* pass ipstate_t after synchdr_t */
+#define SMC_UPDATE 1
+#define SMC_MAXCMD 1
+
+/*
+ * Tables
+ */
+#define SMC_NAT 0
+#define SMC_STATE 1
+#define SMC_MAXTBL 1
+
+
+/*
+ * Only TCP requires "more" information than just a reference to the entry
+ * for which an update is being made.
+ */
+typedef struct synctcp_update {
+ u_long stu_age;
+ tcpdata_t stu_data[2];
+ int stu_state[2];
+} synctcp_update_t;
+
+
+typedef struct synclist {
+ struct synclist *sl_next;
+ struct synclist **sl_pnext;
+ int sl_idx; /* update index */
+ struct synchdr sl_hdr;
+ union {
+ struct ipstate *slu_ips;
+ struct nat *slu_ipn;
+ void *slu_ptr;
+ } sl_un;
+} synclist_t;
+
+#define sl_ptr sl_un.slu_ptr
+#define sl_ips sl_un.slu_ips
+#define sl_ipn sl_un.slu_ipn
+#define sl_magic sl_hdr.sm_magic
+#define sl_v sl_hdr.sm_v
+#define sl_p sl_hdr.sm_p
+#define sl_cmd sl_hdr.sm_cmd
+#define sl_rev sl_hdr.sm_rev
+#define sl_table sl_hdr.sm_table
+#define sl_num sl_hdr.sm_num
+#define sl_len sl_hdr.sm_len
+
+/*
+ * NOTE: SYNCLOG_SZ is defined *low*. It should be the next power of two
+ * up for whatever number of packets per second you expect to see. Be
+ * warned: this index's a table of large elements (upto 272 bytes in size
+ * each), and thus a size of 8192, for example, results in a 2MB table.
+ * The lesson here is not to use small machines for running fast firewalls
+ * (100BaseT) in sync, where you might have upwards of 10k pps.
+ */
+#define SYNCLOG_SZ 256
+
+typedef struct synclogent {
+ struct synchdr sle_hdr;
+ union {
+ struct ipstate sleu_ips;
+ struct nat sleu_ipn;
+ } sle_un;
+} synclogent_t;
+
+typedef struct syncupdent { /* 28 or 32 bytes */
+ struct synchdr sup_hdr;
+ struct synctcp_update sup_tcp;
+} syncupdent_t;
+
+extern synclogent_t synclog[SYNCLOG_SZ];
+
+
+extern int fr_sync_ioctl __P((caddr_t, ioctlcmd_t, int));
+extern synclist_t *ipfsync_new __P((int, fr_info_t *, void *));
+extern void ipfsync_del __P((synclist_t *));
+extern void ipfsync_update __P((int, fr_info_t *, synclist_t *));
+extern int ipfsync_init __P((void));
+extern int ipfsync_nat __P((synchdr_t *sp, void *data));
+extern int ipfsync_state __P((synchdr_t *sp, void *data));
+extern int ipfsync_read __P((struct uio *uio));
+extern int ipfsync_write __P((struct uio *uio));
+
+#endif /* IP_SYNC */
diff --git a/contrib/ipfilter/ipf.h b/contrib/ipfilter/ipf.h
index 9260d03f..1398c05 100644
--- a/contrib/ipfilter/ipf.h
+++ b/contrib/ipfilter/ipf.h
@@ -1,72 +1,124 @@
+/* $NetBSD$ */
+
/*
- * Copyright (C) 1993-2001 by Darren Reed.
+ * Copyright (C) 1993-2001, 2003 by Darren Reed.
*
* See the IPFILTER.LICENCE file for details on licencing.
*
* @(#)ipf.h 1.12 6/5/96
- * $Id: ipf.h,v 2.9.2.7 2003/05/15 17:45:33 darrenr Exp $
+ * Id: ipf.h,v 2.71.2.6 2005/02/21 05:05:29 darrenr Exp
*/
#ifndef __IPF_H__
#define __IPF_H__
-#ifndef SOLARIS
-#define SOLARIS (defined(sun) && (defined(__svr4__) || defined(__SVR4)))
+#if defined(__osf__)
+# define radix_mask ipf_radix_mask
+# define radix_node ipf_radix_node
+# define radix_node_head ipf_radix_node_head
+#endif
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/file.h>
+/*
+ * This is a workaround for <sys/uio.h> troubles on FreeBSD, HPUX, OpenBSD.
+ * Needed here because on some systems <sys/uio.h> gets included by things
+ * like <sys/socket.h>
+ */
+#ifndef _KERNEL
+# define ADD_KERNEL
+# define _KERNEL
+# define KERNEL
+#endif
+#ifdef __OpenBSD__
+struct file;
+#endif
+#include <sys/uio.h>
+#ifdef ADD_KERNEL
+# undef _KERNEL
+# undef KERNEL
+#endif
+#include <sys/time.h>
+#include <sys/socket.h>
+#include <net/if.h>
+#if __FreeBSD_version >= 300000
+# include <net/if_var.h>
+#endif
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/ip_icmp.h>
+#ifndef TCP_PAWS_IDLE /* IRIX */
+# include <netinet/tcp.h>
#endif
-#define OPT_REMOVE 0x000001
-#define OPT_DEBUG 0x000002
-#define OPT_OUTQUE FR_OUTQUE /* 0x00004 */
-#define OPT_INQUE FR_INQUE /* 0x00008 */
-#define OPT_LOG FR_LOG /* 0x00010 */
-#define OPT_SHOWLIST 0x000020
-#define OPT_VERBOSE 0x000040
-#define OPT_DONOTHING 0x000080
-#define OPT_HITS 0x000100
-#define OPT_BRIEF 0x000200
-#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 0x004000
-#define OPT_PRINTFR 0x008000
-#define OPT_ZERORULEST 0x010000
-#define OPT_SAVEOUT 0x020000
-#define OPT_AUTHSTATS 0x040000
-#define OPT_RAW 0x080000
-#define OPT_NAT 0x100000
-#define OPT_GROUPS 0x200000
-#define OPT_STATETOP 0x400000
-#define OPT_FLUSH 0x800000
-#define OPT_CLEAR 0x1000000
-#define OPT_HEX 0x2000000
-#define OPT_NODO 0x80000000
-
-#define OPT_STAT OPT_FRSTATES
-#define OPT_LIST OPT_SHOWLIST
+#include <netinet/udp.h>
+#include <arpa/inet.h>
+
+#include <errno.h>
+#include <limits.h>
+#include <netdb.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <stdio.h>
+#if !defined(__SVR4) && !defined(__svr4__) && defined(sun)
+# include <strings.h>
+#endif
+#include <string.h>
+#include <unistd.h>
+
+#include "netinet/ip_compat.h"
+#include "netinet/ip_fil.h"
+#include "netinet/ip_nat.h"
+#include "netinet/ip_frag.h"
+#include "netinet/ip_state.h"
+#include "netinet/ip_proxy.h"
+#include "netinet/ip_auth.h"
+#include "netinet/ip_lookup.h"
+#include "netinet/ip_pool.h"
+#include "netinet/ip_scan.h"
+#include "netinet/ip_htable.h"
+#include "netinet/ip_sync.h"
+
+#include "opts.h"
#ifndef __P
-# ifdef __STDC__
+# ifdef __STDC__
# define __P(x) x
# else
# define __P(x) ()
# endif
#endif
+#ifndef __STDC__
+# undef const
+# define const
+#endif
-struct ipstate;
-struct frpcmp;
-struct ipnat;
-struct nat;
+#ifndef U_32_T
+# define U_32_T 1
+# if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD__) || \
+ defined(__sgi)
+typedef u_int32_t u_32_t;
+# else
+# if defined(__alpha__) || defined(__alpha) || defined(_LP64)
+typedef unsigned int u_32_t;
+# else
+# if SOLARIS2 >= 6
+typedef uint32_t u_32_t;
+# else
+typedef unsigned int u_32_t;
+# endif
+# endif
+# endif /* __NetBSD__ || __OpenBSD__ || __FreeBSD__ || __sgi */
+#endif /* U_32_T */
-#ifdef ultrix
-extern char *strdup __P((char *));
+#ifndef MAXHOSTNAMELEN
+# define MAXHOSTNAMELEN 256
#endif
-extern struct frentry *parse __P((char *, int, int *));
-
-extern void printfr __P((struct frentry *));
-extern void binprint __P((struct frentry *)), initparse __P((void));
-extern int portnum __P((char *, u_short *, int));
+#define MAX_ICMPCODE 16
+#define MAX_ICMPTYPE 19
struct ipopt_names {
@@ -77,47 +129,178 @@ struct ipopt_names {
};
-extern char *proto;
+typedef struct alist_s {
+ struct alist_s *al_next;
+ int al_not;
+ i6addr_t al_i6addr;
+ i6addr_t al_i6mask;
+} alist_t;
+
+#define al_addr al_i6addr.in4_addr
+#define al_mask al_i6mask.in4_addr
+#define al_1 al_addr
+#define al_2 al_mask
+
+
+typedef struct {
+ u_short fb_c;
+ u_char fb_t;
+ u_char fb_f;
+ u_32_t fb_k;
+} fakebpf_t;
+
+
+#if defined(__NetBSD__) || defined(__OpenBSD__) || \
+ (_BSDI_VERSION >= 199701) || (__FreeBSD_version >= 300000) || \
+ SOLARIS || defined(__sgi) || defined(__osf__) || defined(linux)
+# include <stdarg.h>
+typedef int (* ioctlfunc_t) __P((int, ioctlcmd_t, ...));
+#else
+typedef int (* ioctlfunc_t) __P((dev_t, ioctlcmd_t, void *));
+#endif
+typedef void (* addfunc_t) __P((int, ioctlfunc_t, void *));
+typedef int (* copyfunc_t) __P((void *, void *, size_t));
+
+
+/*
+ * SunOS4
+ */
+#if defined(sun) && !defined(__SVR4) && !defined(__svr4__)
+extern int ioctl __P((int, int, void *));
+#endif
+
+extern char thishost[];
extern char flagset[];
extern u_char flags[];
+extern struct ipopt_names ionames[];
+extern struct ipopt_names secclass[];
+extern char *icmpcodes[MAX_ICMPCODE + 1];
+extern char *icmptypes[MAX_ICMPTYPE + 1];
+extern int use_inet6;
+extern int lineNum;
+extern struct ipopt_names v6ionames[];
-extern u_char tcp_flags __P((char *, u_char *, int));
-extern int countbits __P((u_32_t));
-extern int ratoi __P((char *, int *, int, int));
-extern int ratoui __P((char *, u_int *, u_int, u_int));
-extern int hostmask __P((char ***, u_32_t *, u_32_t *, u_short *, int *,
- u_short *, int));
-extern int ports __P((char ***, u_short *, int *, u_short *, int));
-extern char *portname __P((int, int));
-extern u_32_t buildopts __P((char *, char *, int));
-extern int genmask __P((char *, u_32_t *));
-extern int hostnum __P((u_32_t *, char *, int));
-extern u_32_t optname __P((char ***, u_short *, int));
-extern void printpacket __P((ip_t *));
-extern void printpacket6 __P((ip_t *));
-extern void printportcmp __P((int, struct frpcmp *));
-extern void printhostmask __P((int, u_32_t *, u_32_t *));
-extern void printbuf __P((char *, int, int));
-extern char *hostname __P((int, void *));
-extern struct ipstate *printstate __P((struct ipstate *, int));
-extern void printnat __P((struct ipnat *, int));
-extern void printactivenat __P((struct nat *, int));
-#if SOLARIS
-extern int inet_aton __P((const char *, struct in_addr *));
-extern int gethostname __P((char *, int ));
-extern void sync __P((void));
+extern int addicmp __P((char ***, struct frentry *, int));
+extern int addipopt __P((char *, struct ipopt_names *, int, char *));
+extern int addkeep __P((char ***, struct frentry *, int));
+extern int bcopywrap __P((void *, void *, size_t));
+extern void binprint __P((void *, size_t));
+extern void initparse __P((void));
+extern u_32_t buildopts __P((char *, char *, int));
+extern int checkrev __P((char *));
+extern int count6bits __P((u_32_t *));
+extern int count4bits __P((u_32_t));
+extern int extras __P((char ***, struct frentry *, int));
+extern char *fac_toname __P((int));
+extern int fac_findname __P((char *));
+extern void fill6bits __P((int, u_int *));
+extern int gethost __P((char *, u_32_t *));
+extern int getport __P((struct frentry *, char *, u_short *));
+extern int getportproto __P((char *, int));
+extern int getproto __P((char *));
+extern char *getline __P((char *, size_t, FILE *, int *));
+extern int genmask __P((char *, u_32_t *));
+extern char *getnattype __P((struct ipnat *));
+extern char *getsumd __P((u_32_t));
+extern u_32_t getoptbyname __P((char *));
+extern u_32_t getoptbyvalue __P((int));
+extern u_32_t getv6optbyname __P((char *));
+extern u_32_t getv6optbyvalue __P((int));
+extern void hexdump __P((FILE *, void *, int, int));
+extern int hostmask __P((char ***, char *, char *, u_32_t *, u_32_t *, int));
+extern int hostnum __P((u_32_t *, char *, int, char *));
+extern int icmpcode __P((char *));
+extern int icmpidnum __P((char *, u_short *, int));
+extern void initparse __P((void));
+extern void ipf_dotuning __P((int, char *, ioctlfunc_t));
+extern void ipf_addrule __P((int, ioctlfunc_t, void *));
+extern int ipf_parsefile __P((int, addfunc_t, ioctlfunc_t *, char *));
+extern int ipf_parsesome __P((int, addfunc_t, ioctlfunc_t *, FILE *));
+extern int ipmon_parsefile __P((char *));
+extern int ipmon_parsesome __P((FILE *));
+extern void ipnat_addrule __P((int, ioctlfunc_t, void *));
+extern int ipnat_parsefile __P((int, addfunc_t, ioctlfunc_t, char *));
+extern int ipnat_parsesome __P((int, addfunc_t, ioctlfunc_t, FILE *));
+extern int ippool_parsefile __P((int, char *, ioctlfunc_t));
+extern int ippool_parsesome __P((int, FILE *, ioctlfunc_t));
+extern int kmemcpywrap __P((void *, void *, size_t));
+extern char *kvatoname __P((ipfunc_t, ioctlfunc_t));
+extern int load_hash __P((struct iphtable_s *, struct iphtent_s *,
+ ioctlfunc_t));
+extern int load_hashnode __P((int, char *, struct iphtent_s *, ioctlfunc_t));
+extern int load_pool __P((struct ip_pool_s *list, ioctlfunc_t));
+extern int load_poolnode __P((int, char *, ip_pool_node_t *, ioctlfunc_t));
+extern int loglevel __P((char **, u_int *, int));
+extern alist_t *make_range __P((int, struct in_addr, struct in_addr));
+extern ipfunc_t nametokva __P((char *, ioctlfunc_t));
+extern ipnat_t *natparse __P((char *, int));
+extern void natparsefile __P((int, char *, int));
+extern void nat_setgroupmap __P((struct ipnat *));
+extern int ntomask __P((int, int, u_32_t *));
+extern u_32_t optname __P((char ***, u_short *, int));
+extern struct frentry *parse __P((char *, int));
+extern char *portname __P((int, int));
+extern int portnum __P((char *, char *, u_short *, int));
+extern int ports __P((char ***, char *, u_short *, int *, u_short *, int));
+extern int pri_findname __P((char *));
+extern char *pri_toname __P((int));
+extern void print_toif __P((char *, struct frdest *));
+extern void printaps __P((ap_session_t *, int));
+extern void printbuf __P((char *, int, int));
+extern void printfr __P((struct frentry *, ioctlfunc_t));
+extern void printtunable __P((ipftune_t *));
+extern struct iphtable_s *printhash __P((struct iphtable_s *, copyfunc_t,
+ char *, int));
+extern struct iphtent_s *printhashnode __P((struct iphtable_s *,
+ struct iphtent_s *,
+ copyfunc_t, int));
+extern void printhostmask __P((int, u_32_t *, u_32_t *));
+extern void printip __P((u_32_t *));
+extern void printlog __P((struct frentry *));
+extern void printlookup __P((i6addr_t *addr, i6addr_t *mask));
+extern void printmask __P((u_32_t *));
+extern void printpacket __P((struct ip *));
+extern void printpacket6 __P((struct ip *));
+extern struct ip_pool_s *printpool __P((struct ip_pool_s *, copyfunc_t,
+ char *, int));
+extern struct ip_pool_node *printpoolnode __P((struct ip_pool_node *, int));
+extern void printportcmp __P((int, struct frpcmp *));
+extern void optprint __P((u_short *, u_long, u_long));
+#ifdef USE_INET6
+extern void optprintv6 __P((u_short *, u_long, u_long));
#endif
+extern int ratoi __P((char *, int *, int, int));
+extern int ratoui __P((char *, u_int *, u_int, u_int));
+extern int remove_hash __P((struct iphtable_s *, ioctlfunc_t));
+extern int remove_hashnode __P((int, char *, struct iphtent_s *, ioctlfunc_t));
+extern int remove_pool __P((ip_pool_t *, ioctlfunc_t));
+extern int remove_poolnode __P((int, char *, ip_pool_node_t *, ioctlfunc_t));
+extern u_char tcp_flags __P((char *, u_char *, int));
+extern u_char tcpflags __P((char *));
+extern int to_interface __P((struct frdest *, char *, int));
+extern void printc __P((struct frentry *));
+extern void printC __P((int));
+extern void emit __P((int, int, void *, struct frentry *));
+extern u_char secbit __P((int));
+extern u_char seclevel __P((char *));
+extern void printfraginfo __P((char *, struct ipfr *));
+extern void printifname __P((char *, char *, void *));
+extern char *hostname __P((int, void *));
+extern struct ipstate *printstate __P((struct ipstate *, int, u_long));
+extern void printsbuf __P((char *));
+extern void printnat __P((struct ipnat *, int));
+extern void printactivenat __P((struct nat *, int));
+extern void printhostmap __P((struct hostmap *, u_int));
+extern void printpacket __P((struct ip *));
-#if defined(sun) && !SOLARIS
-# define STRERROR(x) sys_errlist[x]
-extern char *sys_errlist[];
-#else
-# define STRERROR(x) strerror(x)
-#endif
+extern void set_variable __P((char *, char *));
+extern char *get_variable __P((char *, char **, int));
+extern void resetlexer __P((void));
-#ifndef MIN
-#define MIN(a,b) ((a) > (b) ? (b) : (a))
+#if SOLARIS
+extern int gethostname __P((char *, int ));
+extern void sync __P((void));
#endif
#endif /* __IPF_H__ */
diff --git a/contrib/ipfilter/iplang/.cvsignore b/contrib/ipfilter/iplang/.cvsignore
new file mode 100644
index 0000000..68b5b4e
--- /dev/null
+++ b/contrib/ipfilter/iplang/.cvsignore
@@ -0,0 +1,9 @@
+y.tab.h
+y.output
+lex.yy.c
+y.tab.c
+y.tab.o
+lex.yy.o
+iplang_y.output
+iplang_y.tab.c
+iplang_y.tab.h
diff --git a/contrib/ipfilter/iplang/Makefile b/contrib/ipfilter/iplang/Makefile
index f97bf19..5b53e9a 100644
--- a/contrib/ipfilter/iplang/Makefile
+++ b/contrib/ipfilter/iplang/Makefile
@@ -1,36 +1,31 @@
#
-# 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.
+# See the IPFILTER.LICENCE file for details on licencing.
#
#CC=gcc -Wuninitialized -Wstrict-prototypes -Werror -O
CFLAGS=-I..
-all: $(DESTDIR)/y.tab.o $(DESTDIR)/lex.yy.o
+all: $(DESTDIR)/iplang_y.o $(DESTDIR)/iplang_l.o
-$(DESTDIR)/y.tab.o: $(DESTDIR)/y.tab.c
- $(CC) $(DEBUG) -I. -I.. -I$(DESTDIR) -I../ipsend $(CFLAGS) $(LINUX) -c $(DESTDIR)/y.tab.c -o $@
+$(DESTDIR)/iplang_y.o: $(DESTDIR)/iplang_y.c
+ $(CC) $(DEBUG) -I. -I.. -I$(DESTDIR) -I../ipsend $(CFLAGS) $(LINUX) -c $(DESTDIR)/iplang_y.c -o $@
-$(DESTDIR)/$(OBJ)/y.tab.o: $(DESTDIR)/y.tab.c
- $(CC) $(DEBUG) -I. -I.. -I$(DESTDIR) -I../ipsend $(CFLAGS) $(LINUX) -c $(DESTDIR)/y.tab.c -o $@
+$(DESTDIR)/iplang_l.o: $(DESTDIR)/iplang_l.c
+ $(CC) $(DEBUG) -I. -I.. -I$(DESTDIR) -I../ipsend $(CFLAGS) $(LINUX) -c $(DESTDIR)/iplang_l.c -o $@
-$(DESTDIR)/lex.yy.o: $(DESTDIR)/lex.yy.c
- $(CC) $(DEBUG) -I. -I.. -I$(DESTDIR) -I../ipsend $(CFLAGS) $(LINUX) -c $(DESTDIR)/lex.yy.c -o $@
+iplang_y.o: iplang_y.c
+ $(CC) $(DEBUG) -I. -I.. -I../ipsend $(CFLAGS) $(LINUX) -c $< -o $@
-y.tab.o: y.tab.c
- $(CC) $(DEBUG) -I. -I.. -I../ipsend $(CFLAGS) $(LINUX) -c y.tab.c -o $@
+iplang_l.o: iplang_l.c
+ $(CC) $(DEBUG) -I. -I.. -I../ipsend $(CFLAGS) $(LINUX) -c $< -o $@
-lex.yy.o: lex.yy.c
- $(CC) $(DEBUG) -I. -I.. -I../ipsend $(CFLAGS) $(LINUX) -c lex.yy.c -o $@
-
-$(DESTDIR)/lex.yy.c: iplang_l.l $(DESTDIR)/y.tab.h
+$(DESTDIR)/iplang_l.c: iplang_l.l $(DESTDIR)/iplang_y.h
lex iplang_l.l
- mv lex.yy.c $(DESTDIR)
+ mv lex.yy.c $(DESTDIR)/iplang_l.c
-$(DESTDIR)/y.tab.c $(DESTDIR)/y.tab.h: iplang_y.y
+$(DESTDIR)/iplang_y.c $(DESTDIR)/iplang_y.h: iplang_y.y
yacc -d iplang_y.y
- mv y.tab.c $(DESTDIR)
- mv y.tab.h $(DESTDIR)
+ mv y.tab.c $(DESTDIR)/iplang_y.c
+ mv y.tab.h $(DESTDIR)/iplang_y.h
clean:
/bin/rm -f *.o lex.yy.c y.tab.c y.tab.h
diff --git a/contrib/ipfilter/iplang/iplang.h b/contrib/ipfilter/iplang/iplang.h
index f36a384..675897b 100644
--- a/contrib/ipfilter/iplang/iplang.h
+++ b/contrib/ipfilter/iplang/iplang.h
@@ -1,3 +1,5 @@
+/* $NetBSD$ */
+
/*
* Copyright (C) 1997-1998 by Darren Reed.
*
diff --git a/contrib/ipfilter/iplang/iplang_l.l b/contrib/ipfilter/iplang/iplang_l.l
index cc31781..0a97ec9 100644
--- a/contrib/ipfilter/iplang/iplang_l.l
+++ b/contrib/ipfilter/iplang/iplang_l.l
@@ -1,12 +1,12 @@
+/* $NetBSD$ */
+
%{
/*
* Copyright (C) 1997-1998 by Darren Reed.
*
- * Redistribution and use in source and binary forms are permitted
- * provided that this notice is preserved and due credit is given
- * to the original author and the contributors.
+ * See the IPFILTER.LICENCE file for details on licencing.
*
- * $Id: iplang_l.l,v 2.2.2.1 2003/07/28 01:15:59 darrenr Exp $
+ * Id: iplang_l.l,v 2.8 2003/07/28 01:15:31 darrenr Exp
*/
#include <stdio.h>
#include <string.h>
@@ -17,8 +17,7 @@
#include <sys/types.h>
#include <netinet/in_systm.h>
#include <netinet/in.h>
-#include "y.tab.h"
-#include "ip_compat.h"
+#include "iplang_y.h"
#include "ipf.h"
#ifndef __P
@@ -43,13 +42,13 @@ int save_token __P((void));
void swallow __P((void));
int yylex __P((void));
-struct wordtab {
+struct lwordtab {
char *word;
int state;
int next;
};
-struct wordtab words[] = {
+struct lwordtab words[] = {
{ "interface", IL_INTERFACE, -1 },
{ "iface", IL_INTERFACE, -1 },
{ "name", IL_IFNAME, IL_TOKEN },
@@ -217,7 +216,7 @@ void pop_proto()
int save_token()
{
- yylval.str = strdup(yytext);
+ yylval.str = strdup((char *)yytext);
return IL_TOKEN;
}
@@ -225,7 +224,7 @@ int save_token()
int next_item(nstate)
int nstate;
{
- struct wordtab *wt;
+ struct lwordtab *wt;
if (opts & OPT_DEBUG)
printf("text=[%s] id=%d next=%d\n", yytext, nstate, next);
@@ -236,13 +235,13 @@ int nstate;
token++;
for (wt = words; wt->word; wt++)
- if (!strcasecmp(wt->word, yytext))
+ if (!strcasecmp(wt->word, (char *)yytext))
return next_state(wt->state, wt->next);
if (opts & OPT_DEBUG)
printf("unknown keyword=[%s]\n", yytext);
next = -1;
if (nstate == IL_NUMBER)
- yylval.num = atoi(yytext);
+ yylval.num = atoi((char *)yytext);
token++;
return nstate;
}
diff --git a/contrib/ipfilter/ipmon.h b/contrib/ipfilter/ipmon.h
new file mode 100644
index 0000000..a240836
--- /dev/null
+++ b/contrib/ipfilter/ipmon.h
@@ -0,0 +1,96 @@
+/* $NetBSD$ */
+
+/*
+ * Copyright (C) 1993-2001 by Darren Reed.
+ *
+ * See the IPFILTER.LICENCE file for details on licencing.
+ *
+ * @(#)ip_fil.h 1.35 6/5/96
+ * Id: ipmon.h,v 2.8 2003/07/25 22:16:20 darrenr Exp
+ */
+
+
+typedef struct ipmon_action {
+ struct ipmon_action *ac_next;
+ int ac_mflag; /* collection of things to compare */
+ int ac_dflag; /* flags to compliment the doing fields */
+ int ac_syslog; /* = 1 to syslog rules. */
+ char *ac_savefile; /* filename to save log records to */
+ FILE *ac_savefp;
+ int ac_direction;
+ char ac_group[FR_GROUPLEN];
+ char ac_nattag[16];
+ u_32_t ac_logtag;
+ int ac_type; /* nat/state/ipf */
+ int ac_proto;
+ int ac_rule;
+ int ac_packet;
+ int ac_second;
+ int ac_result;
+ u_32_t ac_sip;
+ u_32_t ac_smsk;
+ u_32_t ac_dip;
+ u_32_t ac_dmsk;
+ u_short ac_sport;
+ u_short ac_dport;
+ char *ac_exec; /* execute argument */
+ char *ac_run; /* actual command that gets run */
+ char *ac_iface;
+ /*
+ * used with ac_packet/ac_second
+ */
+ struct timeval ac_last;
+ int ac_pktcnt;
+} ipmon_action_t;
+
+#define ac_lastsec ac_last.tv_sec
+#define ac_lastusec ac_last.tv_usec
+
+/*
+ * Flags indicating what fields to do matching upon (ac_mflag).
+ */
+#define IPMAC_DIRECTION 0x0001
+#define IPMAC_DSTIP 0x0002
+#define IPMAC_DSTPORT 0x0004
+#define IPMAC_EVERY 0x0008
+#define IPMAC_GROUP 0x0010
+#define IPMAC_INTERFACE 0x0020
+#define IPMAC_LOGTAG 0x0040
+#define IPMAC_NATTAG 0x0080
+#define IPMAC_PROTOCOL 0x0100
+#define IPMAC_RESULT 0x0200
+#define IPMAC_RULE 0x0400
+#define IPMAC_SRCIP 0x0800
+#define IPMAC_SRCPORT 0x1000
+#define IPMAC_TYPE 0x2000
+#define IPMAC_WITH 0x4000
+
+#define IPMR_BLOCK 1
+#define IPMR_PASS 2
+#define IPMR_NOMATCH 3
+#define IPMR_LOG 4
+
+#define IPMDO_SAVERAW 0x0001
+
+#define OPT_SYSLOG 0x001
+#define OPT_RESOLVE 0x002
+#define OPT_HEXBODY 0x004
+#define OPT_VERBOSE 0x008
+#define OPT_HEXHDR 0x010
+#define OPT_TAIL 0x020
+#define OPT_NAT 0x080
+#define OPT_STATE 0x100
+#define OPT_FILTER 0x200
+#define OPT_PORTNUM 0x400
+#define OPT_LOGALL (OPT_NAT|OPT_STATE|OPT_FILTER)
+
+#define HOSTNAME_V4(a,b) hostname((a), 4, (u_32_t *)&(b))
+
+#ifndef LOGFAC
+#define LOGFAC LOG_LOCAL0
+#endif
+
+extern int load_config __P((char *));
+extern void dumphex __P((FILE *, int, char *, int));
+extern int check_action __P((char *, char *, int, int));
+extern char *getword __P((int));
diff --git a/contrib/ipfilter/ipsd/Celler/ip_compat.h b/contrib/ipfilter/ipsd/Celler/ip_compat.h
index a911fd8..8b43cb9 100644
--- a/contrib/ipfilter/ipsd/Celler/ip_compat.h
+++ b/contrib/ipfilter/ipsd/Celler/ip_compat.h
@@ -1,3 +1,5 @@
+/* $NetBSD$ */
+
/*
* (C)opyright 1995 by Darren Reed.
*
diff --git a/contrib/ipfilter/ipsd/Makefile b/contrib/ipfilter/ipsd/Makefile
index b9ad044..0f3ce08 100644
--- a/contrib/ipfilter/ipsd/Makefile
+++ b/contrib/ipfilter/ipsd/Makefile
@@ -1,9 +1,7 @@
#
# Copyright (C) 1993-1998 by Darren Reed.
#
-# Redistribution and use in source and binary forms are permitted
-# provided that this notice is preserved and due credit is given
-# to the original author and the contributors.
+# See the IPFILTER.LICENCE file for details on licencing.
#
OBJS=ipsd.o
BINDEST=/usr/local/bin
diff --git a/contrib/ipfilter/ipsd/ipsd.c b/contrib/ipfilter/ipsd/ipsd.c
index 261ad89..3d9ea4c 100644
--- a/contrib/ipfilter/ipsd/ipsd.c
+++ b/contrib/ipfilter/ipsd/ipsd.c
@@ -1,11 +1,10 @@
+/* $NetBSD$ */
+
/*
* (C)opyright 1995-1998 Darren Reed.
*
* See the IPFILTER.LICENCE file for details on licencing.
*
- * 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>
@@ -35,7 +34,7 @@
#ifndef lint
static const char sccsid[] = "@(#)ipsd.c 1.3 12/3/95 (C)1995 Darren Reed";
-static const char rcsid[] = "@(#)$Id: ipsd.c,v 2.1.4.1 2001/06/26 10:43:21 darrenr Exp $";
+static const char rcsid[] = "@(#)Id: ipsd.c,v 2.2 2001/06/09 17:09:25 darrenr Exp";
#endif
extern char *optarg;
diff --git a/contrib/ipfilter/ipsd/ipsd.h b/contrib/ipfilter/ipsd/ipsd.h
index a8f58c3..48f5911 100644
--- a/contrib/ipfilter/ipsd/ipsd.h
+++ b/contrib/ipfilter/ipsd/ipsd.h
@@ -1,11 +1,10 @@
+/* $NetBSD$ */
+
/*
* (C)opyright 1995-1998 Darren Reed.
*
* See the IPFILTER.LICENCE file for details on licencing.
*
- * 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
*/
diff --git a/contrib/ipfilter/ipsd/ipsdr.c b/contrib/ipfilter/ipsd/ipsdr.c
index 298f655..4689cba 100644
--- a/contrib/ipfilter/ipsd/ipsdr.c
+++ b/contrib/ipfilter/ipsd/ipsdr.c
@@ -1,11 +1,10 @@
+/* $NetBSD$ */
+
/*
* (C)opyright 1995-1998 Darren Reed.
*
* See the IPFILTER.LICENCE file for details on licencing.
*
- * 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>
@@ -36,7 +35,7 @@
#ifndef lint
static const char sccsid[] = "@(#)ipsdr.c 1.3 12/3/95 (C)1995 Darren Reed";
-static const char rcsid[] = "@(#)$Id: ipsdr.c,v 2.1.4.1 2001/06/26 10:43:21 darrenr Exp $";
+static const char rcsid[] = "@(#)Id: ipsdr.c,v 2.2 2001/06/09 17:09:25 darrenr Exp";
#endif
extern char *optarg;
diff --git a/contrib/ipfilter/ipsd/linux.h b/contrib/ipfilter/ipsd/linux.h
index d9606cb..2fadfcf 100644
--- a/contrib/ipfilter/ipsd/linux.h
+++ b/contrib/ipfilter/ipsd/linux.h
@@ -1,3 +1,5 @@
+/* $NetBSD$ */
+
/*
* Copyright (C) 1997-1998 by Darren Reed.
*
diff --git a/contrib/ipfilter/ipsd/sbpf.c b/contrib/ipfilter/ipsd/sbpf.c
index 97bb4ce..29a7200 100644
--- a/contrib/ipfilter/ipsd/sbpf.c
+++ b/contrib/ipfilter/ipsd/sbpf.c
@@ -1,3 +1,5 @@
+/* $NetBSD$ */
+
/*
* (C)opyright 1995-1998 Darren Reed. (from tcplog)
*
diff --git a/contrib/ipfilter/ipsd/sdlpi.c b/contrib/ipfilter/ipsd/sdlpi.c
index c08fe69..289ad2f 100644
--- a/contrib/ipfilter/ipsd/sdlpi.c
+++ b/contrib/ipfilter/ipsd/sdlpi.c
@@ -1,3 +1,5 @@
+/* $NetBSD$ */
+
/*
* (C)opyright 1992-1998 Darren Reed. (from tcplog)
*
@@ -158,7 +160,7 @@ int tout;
(void) sprintf(devname, "/dev/%s", device);
s = devname + 5;
- while (*s && !isdigit(*s))
+ while (*s && !ISDIGIT(*s))
s++;
if (!*s)
{
diff --git a/contrib/ipfilter/ipsd/slinux.c b/contrib/ipfilter/ipsd/slinux.c
index 2c5aa97d..3b786b0 100644
--- a/contrib/ipfilter/ipsd/slinux.c
+++ b/contrib/ipfilter/ipsd/slinux.c
@@ -1,11 +1,10 @@
+/* $NetBSD$ */
+
/*
* (C)opyright 1992-1998 Darren Reed. (from tcplog)
*
* See the IPFILTER.LICENCE file for details on licencing.
*
- * The author of this software makes no garuntee about the
- * performance of this package or its suitability to fulfill any purpose.
- *
*/
#include <stdio.h>
diff --git a/contrib/ipfilter/ipsd/snit.c b/contrib/ipfilter/ipsd/snit.c
index ec7178f..8f25026 100644
--- a/contrib/ipfilter/ipsd/snit.c
+++ b/contrib/ipfilter/ipsd/snit.c
@@ -1,11 +1,10 @@
+/* $NetBSD$ */
+
/*
* (C)opyright 1992-1998 Darren Reed. (from tcplog)
*
* See the IPFILTER.LICENCE file for details on licencing.
*
- * The author of this software makes no garuntee about the
- * performance of this package or its suitability to fulfill any purpose.
- *
*/
#include <stdio.h>
diff --git a/contrib/ipfilter/ipsend/.OLD/ip_compat.h b/contrib/ipfilter/ipsend/.OLD/ip_compat.h
index c38fa59..3b62be1 100644
--- a/contrib/ipfilter/ipsend/.OLD/ip_compat.h
+++ b/contrib/ipfilter/ipsend/.OLD/ip_compat.h
@@ -1,3 +1,5 @@
+/* $NetBSD$ */
+
/*
* (C)opyright 1995 by Darren Reed.
*
diff --git a/contrib/ipfilter/ipsend/.cvsignore b/contrib/ipfilter/ipsend/.cvsignore
new file mode 100644
index 0000000..b7aea24
--- /dev/null
+++ b/contrib/ipfilter/ipsend/.cvsignore
@@ -0,0 +1,3 @@
+ipsend
+ipresend
+iptest
diff --git a/contrib/ipfilter/ipsend/44arp.c b/contrib/ipfilter/ipsend/44arp.c
index de9f4d9..4206355 100644
--- a/contrib/ipfilter/ipsend/44arp.c
+++ b/contrib/ipfilter/ipsend/44arp.c
@@ -1,33 +1,37 @@
+/* $NetBSD$ */
+
/*
* Based upon 4.4BSD's /usr/sbin/arp
*/
-#if defined(__sgi) && (IRIX > 602)
-# include <sys/ptimers.h>
-#endif
-#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>
+#if __FreeBSD_version >= 300000
+# include <net/if_var.h>
+#endif
#include <net/if_dl.h>
#include <net/if_types.h>
+#if defined(__FreeBSD__)
+# include "radix_ipf.h"
+#endif
#include <net/route.h>
#include <netinet/in.h>
#include <netinet/if_ether.h>
#include <arpa/inet.h>
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/ip_var.h>
+#include <netinet/tcp.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
#include <netdb.h>
#include <errno.h>
#include <nlist.h>
#include <stdio.h>
-#include <netinet/in.h>
-#include <netinet/ip_var.h>
-#include <netinet/tcp.h>
-#if __FreeBSD_version >= 300000
-# include <net/if_var.h>
-#endif
#include "ipsend.h"
#include "iplang/iplang.h"
@@ -37,7 +41,7 @@
* its IP address in address
* (4 bytes)
*/
-int resolve(host, address)
+int resolve(host, address)
char *host, *address;
{
struct hostent *hp;
@@ -74,6 +78,9 @@ char *addr, *eaddr;
return 0;
#endif
+ if (!addr)
+ return -1;
+
mib[0] = CTL_NET;
mib[1] = PF_ROUTE;
mib[2] = 0;
@@ -101,8 +108,8 @@ char *addr, *eaddr;
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)))
+ if (!bcmp(addr, (char *)&sin->sin_addr,
+ sizeof(struct in_addr)))
{
bcopy(LLADDR(sdl), eaddr, sdl->sdl_alen);
return 0;
diff --git a/contrib/ipfilter/ipsend/Makefile b/contrib/ipfilter/ipsend/Makefile
index bb8000f..ed3a51e 100644
--- a/contrib/ipfilter/ipsend/Makefile
+++ b/contrib/ipfilter/ipsend/Makefile
@@ -1,9 +1,7 @@
#
# Copyright (C) 1993-1998 by Darren Reed.
#
-# Redistribution and use in source and binary forms are permitted
-# provided that this notice is preserved and due credit is given
-# to the original author and the contributors.
+# See the IPFILTER.LICENCE file for details on licencing.
#
IPFT=ipft_ef.o ipft_hx.o ipft_pc.o ipft_sn.o ipft_td.o ipft_tx.o opt.o
OBJS=ipsend.o ip.o ipsopt.o y.tab.o lex.yy.o
@@ -134,6 +132,14 @@ hpux9 :
make iptest "TOBJS=$(TOBJS)" "UNIXOBJS=$(HPUX)" "CC=$(CC)" \
CFLAGS="$(CFLAGS)" "LIBS="
+hpux11 :
+ make ipsend "OBJS=$(OBJS)" "UNIXOBJS=$(HPUX)" "CC=$(CC)" \
+ CFLAGS="$(CFLAGS) -DIPSEND" "LIBS="
+ make ipresend "ROBJS=$(ROBJS)" "UNIXOBJS=$(HPUX)" "CC=$(CC)" \
+ CFLAGS="$(CFLAGS)" "LIBS="
+ make iptest "TOBJS=$(TOBJS)" "UNIXOBJS=$(HPUX)" "CC=$(CC)" \
+ CFLAGS="$(CFLAGS)" "LIBS="
+
ipsend: ipf $(OBJS) $(UNIXOBJS)
$(CC) $(OBJS) $(UNIXOBJS) -o $@ $(LIBS) $(LLIB) $(ELIB)
diff --git a/contrib/ipfilter/ipsend/arp.c b/contrib/ipfilter/ipsend/arp.c
index 8e5f7f4..0e8f556 100644
--- a/contrib/ipfilter/ipsend/arp.c
+++ b/contrib/ipfilter/ipsend/arp.c
@@ -1,20 +1,21 @@
+/* $NetBSD$ */
+
/*
* arp.c (C) 1995-1998 Darren Reed
*
* See the IPFILTER.LICENCE file for details on licencing.
*/
-#if defined(__sgi) && (IRIX > 602)
-# include <sys/ptimers.h>
+#if !defined(lint)
+static const char sccsid[] = "@(#)arp.c 1.4 1/11/96 (C)1995 Darren Reed";
+static const char rcsid[] = "@(#)Id: arp.c,v 2.8 2003/12/01 02:01:15 darrenr Exp";
#endif
-#include <stdio.h>
-#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
-#if !defined(ultrix) && !defined(hpux)
+#if !defined(ultrix) && !defined(hpux) && !defined(__hpux) && !defined(__osf__)
#include <sys/sockio.h>
#endif
#include <sys/ioctl.h>
-#include <netdb.h>
+#include <netinet/in_systm.h>
#include <netinet/in.h>
#include <net/if.h>
#include <netinet/if_ether.h>
@@ -22,23 +23,22 @@
#include <net/if_arp.h>
#endif
#include <netinet/in.h>
+#include <netinet/ip.h>
#include <netinet/ip_var.h>
#include <netinet/tcp.h>
+#include <stdio.h>
+#include <errno.h>
+#include <netdb.h>
#include "ipsend.h"
#include "iplang/iplang.h"
-#if !defined(lint)
-static const char sccsid[] = "@(#)arp.c 1.4 1/11/96 (C)1995 Darren Reed";
-static const char rcsid[] = "@(#)$Id: arp.c,v 2.1.4.4 2002/12/06 11:40:35 darrenr Exp $";
-#endif
-
/*
* lookup host and return
* its IP address in address
* (4 bytes)
*/
-int resolve(host, address)
+int resolve(host, address)
char *host, *address;
{
struct hostent *hp;
@@ -90,7 +90,11 @@ char *ether;
bcopy(ip, (char *)&sin->sin_addr.s_addr, 4);
#ifndef hpux
if ((hp = gethostbyaddr(ip, 4, AF_INET)))
+# if SOLARIS && (SOLARIS2 >= 10)
+ if (!(ether_hostton(hp->h_name, (struct ether_addr *)ether)))
+# else
if (!(ether_hostton(hp->h_name, ether)))
+# endif
goto savearp;
#endif
@@ -122,6 +126,13 @@ tryagain:
return -1;
}
+ if ((ar.arp_ha.sa_data[0] == 0) && (ar.arp_ha.sa_data[1] == 0) &&
+ (ar.arp_ha.sa_data[2] == 0) && (ar.arp_ha.sa_data[3] == 0) &&
+ (ar.arp_ha.sa_data[4] == 0) && (ar.arp_ha.sa_data[5] == 0)) {
+ fprintf(stderr, "(%s):", inet_ntoa(sin->sin_addr));
+ return -1;
+ }
+
bcopy(ar.arp_ha.sa_data, ether, 6);
savearp:
bcopy(ether, ethersave, 6);
diff --git a/contrib/ipfilter/ipsend/dlcommon.c b/contrib/ipfilter/ipsend/dlcommon.c
index 59b283d..6e351f0 100644
--- a/contrib/ipfilter/ipsend/dlcommon.c
+++ b/contrib/ipfilter/ipsend/dlcommon.c
@@ -1,3 +1,5 @@
+/* $NetBSD$ */
+
/*
* Common (shared) DLPI test routines.
* Mostly pretty boring boilerplate sorta stuff.
@@ -18,7 +20,11 @@ typedef unsigned long ulong;
#include <sys/types.h>
#include <sys/stream.h>
#include <sys/stropts.h>
-#include <sys/dlpi.h>
+#ifdef __osf__
+# include <sys/dlpihdr.h>
+#else
+# include <sys/dlpi.h>
+#endif
#include <sys/signal.h>
#include <stdio.h>
#include <string.h>
@@ -35,6 +41,7 @@ char *dlstyle();
char *dlmactype();
+void
dlinforeq(fd)
int fd;
{
@@ -54,6 +61,7 @@ int fd;
syserr("dlinforeq: putmsg");
}
+void
dlinfoack(fd, bufp)
int fd;
char *bufp;
@@ -82,6 +90,7 @@ char *bufp;
err("dlinfoack: short response ctl.len: %d", ctl.len);
}
+void
dlattachreq(fd, ppa)
int fd;
u_long ppa;
@@ -103,6 +112,7 @@ u_long ppa;
syserr("dlattachreq: putmsg");
}
+void
dlenabmultireq(fd, addr, length)
int fd;
char *addr;
@@ -131,6 +141,7 @@ int length;
syserr("dlenabmultireq: putmsg");
}
+void
dldisabmultireq(fd, addr, length)
int fd;
char *addr;
@@ -159,6 +170,7 @@ int length;
syserr("dldisabmultireq: putmsg");
}
+void
dlpromisconreq(fd, level)
int fd;
u_long level;
@@ -181,6 +193,7 @@ u_long level;
}
+void
dlpromiscoff(fd, level)
int fd;
u_long level;
@@ -202,6 +215,7 @@ u_long level;
syserr("dlpromiscoff: putmsg");
}
+void
dlphysaddrreq(fd, addrtype)
int fd;
u_long addrtype;
@@ -223,6 +237,7 @@ u_long addrtype;
syserr("dlphysaddrreq: putmsg");
}
+void
dlsetphysaddrreq(fd, addr, length)
int fd;
char *addr;
@@ -251,6 +266,7 @@ int length;
syserr("dlsetphysaddrreq: putmsg");
}
+void
dldetachreq(fd)
int fd;
{
@@ -270,6 +286,7 @@ int fd;
syserr("dldetachreq: putmsg");
}
+void
dlbindreq(fd, sap, max_conind, service_mode, conn_mgmt, xidtest)
int fd;
u_long sap;
@@ -299,6 +316,7 @@ u_long xidtest;
syserr("dlbindreq: putmsg");
}
+void
dlunitdatareq(fd, addrp, addrlen, minpri, maxpri, datap, datalen)
int fd;
u_char *addrp;
@@ -333,6 +351,7 @@ int datalen;
syserr("dlunitdatareq: putmsg");
}
+void
dlunbindreq(fd)
int fd;
{
@@ -352,6 +371,7 @@ int fd;
syserr("dlunbindreq: putmsg");
}
+void
dlokack(fd, bufp)
int fd;
char *bufp;
@@ -380,6 +400,7 @@ char *bufp;
err("dlokack: short response ctl.len: %d", ctl.len);
}
+void
dlerrorack(fd, bufp)
int fd;
char *bufp;
@@ -408,6 +429,7 @@ char *bufp;
err("dlerrorack: short response ctl.len: %d", ctl.len);
}
+void
dlbindack(fd, bufp)
int fd;
char *bufp;
@@ -433,6 +455,7 @@ char *bufp;
err("dlbindack: short response ctl.len: %d", ctl.len);
}
+void
dlphysaddrack(fd, bufp)
int fd;
char *bufp;
@@ -695,10 +718,11 @@ union DL_primitives *dlp;
printdlerrorack(dlp)
union DL_primitives *dlp;
{
- (void) printf("DL_ERROR_ACK: error_primitive %s errno %s unix_errno %d\n",
+ (void) printf("DL_ERROR_ACK: error_primitive %s errno %s unix_errno %d: %s\n",
dlprim(dlp->error_ack.dl_error_primitive),
dlerrno(dlp->error_ack.dl_errno),
- dlp->error_ack.dl_unix_errno);
+ dlp->error_ack.dl_unix_errno,
+ strerror(dlp->error_ack.dl_unix_errno));
}
printdlenabmultireq(dlp)
diff --git a/contrib/ipfilter/ipsend/dltest.h b/contrib/ipfilter/ipsend/dltest.h
index 4c32c30..9fafd91 100644
--- a/contrib/ipfilter/ipsend/dltest.h
+++ b/contrib/ipfilter/ipsend/dltest.h
@@ -1,3 +1,5 @@
+/* $NetBSD$ */
+
/*
* Common DLPI Test Suite header file
*
diff --git a/contrib/ipfilter/ipsend/hpux.c b/contrib/ipfilter/ipsend/hpux.c
index 463fdbf..69f962c 100644
--- a/contrib/ipfilter/ipsend/hpux.c
+++ b/contrib/ipfilter/ipsend/hpux.c
@@ -1,7 +1,11 @@
+/* $NetBSD$ */
+
/*
* (C)opyright 1997-1998 Darren Reed. (from tcplog)
*
- * See the IPFILTER.LICENCE file for details on licencing.
+ * 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 <strings.h>
diff --git a/contrib/ipfilter/ipsend/in_var.h b/contrib/ipfilter/ipsend/in_var.h
index b935259..f228bbb 100644
--- a/contrib/ipfilter/ipsend/in_var.h
+++ b/contrib/ipfilter/ipsend/in_var.h
@@ -1,3 +1,5 @@
+/* $NetBSD$ */
+
/* @(#)in_var.h 1.3 88/08/19 SMI; from UCB 7.1 6/5/86 */
/*
@@ -173,5 +175,5 @@ struct in_multistep {
}
struct in_multi *in_addmulti();
-#endif KERNEL
+#endif /* KERNEL */
#endif /*!_netinet_in_var_h*/
diff --git a/contrib/ipfilter/ipsend/ip.c b/contrib/ipfilter/ipsend/ip.c
index 8d30bf5..8302806 100644
--- a/contrib/ipfilter/ipsend/ip.c
+++ b/contrib/ipfilter/ipsend/ip.c
@@ -1,25 +1,21 @@
+/* $NetBSD$ */
+
/*
* ip.c (C) 1995-1998 Darren Reed
*
* See the IPFILTER.LICENCE file for details on licencing.
*/
-#if defined(__sgi) && (IRIX > 602)
-# include <sys/ptimers.h>
+#if !defined(lint)
+static const char sccsid[] = "%W% %G% (C)1995";
+static const char rcsid[] = "@(#)Id: ip.c,v 2.8.2.1 2004/10/19 12:31:48 darrenr Exp";
#endif
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <string.h>
+#include <sys/param.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>
#include <sys/param.h>
#ifndef linux
# include <netinet/if_ether.h>
@@ -28,12 +24,13 @@
# include <net/if_var.h>
# endif
#endif
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
#include "ipsend.h"
-#if !defined(lint)
-static const char sccsid[] = "%W% %G% (C)1995";
-static const char rcsid[] = "@(#)$Id: ip.c,v 2.1.4.5 2002/12/06 11:40:35 darrenr Exp $";
-#endif
static char *ipbuf = NULL, *ethbuf = NULL;
@@ -71,7 +68,9 @@ struct in_addr gwip;
bcopy((char *)buf, s + sizeof(*eh), len);
if (gwip.s_addr == last_gw.s_addr)
+ {
bcopy(last_arp, (char *)A_A eh->ether_dhost, 6);
+ }
else if (arp((char *)&gwip, (char *)A_A eh->ether_dhost) == -1)
{
perror("arp");
@@ -92,7 +91,8 @@ ip_t *ip;
struct in_addr gwip;
int frag;
{
- static struct in_addr last_gw;
+ static struct in_addr last_gw, local_ip;
+ static char local_arp[6] = { 0, 0, 0, 0, 0, 0};
static char last_arp[6] = { 0, 0, 0, 0, 0, 0};
static u_short id = 0;
ether_header_t *eh;
@@ -102,7 +102,7 @@ int frag;
if (!ipbuf)
{
ipbuf = (char *)malloc(65536);
- if(!ipbuf)
+ if (!ipbuf)
{
perror("malloc failed");
return -2;
@@ -113,7 +113,9 @@ int frag;
bzero((char *)A_A eh->ether_shost, sizeof(eh->ether_shost));
if (last_gw.s_addr && (gwip.s_addr == last_gw.s_addr))
+ {
bcopy(last_arp, (char *)A_A eh->ether_dhost, 6);
+ }
else if (arp((char *)&gwip, (char *)A_A eh->ether_dhost) == -1)
{
perror("arp");
@@ -127,18 +129,25 @@ int frag;
iplen = ip->ip_len;
ip->ip_len = htons(iplen);
if (!(frag & 2)) {
- if (!ip->ip_v)
- ip->ip_v = IPVERSION;
+ if (!IP_V(ip))
+ IP_V_A(ip, IPVERSION);
if (!ip->ip_id)
ip->ip_id = htons(id++);
if (!ip->ip_ttl)
ip->ip_ttl = 60;
}
+ if (ip->ip_src.s_addr != local_ip.s_addr) {
+ (void) arp((char *)&ip->ip_src, (char *)A_A local_arp);
+ bcopy(local_arp, (char *)A_A eh->ether_shost,sizeof(last_arp));
+ local_ip = ip->ip_src;
+ } else
+ bcopy(local_arp, (char *)A_A eh->ether_shost, 6);
+
if (!frag || (sizeof(*eh) + iplen < mtu))
{
ip->ip_sum = 0;
- ip->ip_sum = chksum((u_short *)ip, ip->ip_hl << 2);
+ ip->ip_sum = chksum((u_short *)ip, IP_HL(ip) << 2);
bcopy((char *)ip, ipbuf + sizeof(*eh), iplen);
err = sendip(nfd, ipbuf, sizeof(*eh) + iplen);
@@ -155,14 +164,14 @@ int frag;
char *s;
int i, sent = 0, ts, hlen, olen;
- hlen = ip->ip_hl << 2;
+ hlen = IP_HL(ip) << 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);
+ ol = (IP_HL(ip) << 2) - sizeof(*ip);
for (i = 0, s = (char*)(ip + 1); ol > 0; )
if (*s == IPOPT_EOL) {
optcpy[i++] = *s;
@@ -223,7 +232,7 @@ int frag;
else if (!(ip->ip_off & htons(0x1fff)))
{
hlen = i + sizeof(*ip);
- ip->ip_hl = (sizeof(*ip) + i) >> 2;
+ IP_HL_A(ip, (sizeof(*ip) + i) >> 2);
bcopy(optcpy, (char *)(ip + 1), i);
}
}
@@ -243,45 +252,46 @@ ip_t *ip;
struct in_addr gwip;
{
static tcp_seq iss = 2;
- struct tcpiphdr *ti;
- tcphdr_t *t;
+ tcphdr_t *t, *t2;
int thlen, i, iplen, hlen;
u_32_t lbuf[20];
+ ip_t *ip2;
iplen = ip->ip_len;
- hlen = ip->ip_hl << 2;
+ hlen = IP_HL(ip) << 2;
t = (tcphdr_t *)((char *)ip + hlen);
- ti = (struct tcpiphdr *)lbuf;
- thlen = t->th_off << 2;
+ ip2 = (struct ip *)lbuf;
+ t2 = (tcphdr_t *)((char *)ip2 + hlen);
+ thlen = TCP_OFF(t) << 2;
if (!thlen)
thlen = sizeof(tcphdr_t);
- bzero((char *)ti, sizeof(*ti));
+ bzero((char *)ip2, sizeof(*ip2) + sizeof(*t2));
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 + hlen, (char *)&ti->ti_sport, thlen);
+ ip2->ip_p = ip->ip_p;
+ ip2->ip_src = ip->ip_src;
+ ip2->ip_dst = ip->ip_dst;
+ bcopy((char *)ip + hlen, (char *)t2, thlen);
- if (!ti->ti_win)
- ti->ti_win = htons(4096);
+ if (!t2->th_win)
+ t2->th_win = htons(4096);
iss += 63;
i = sizeof(struct tcpiphdr) / sizeof(long);
- if ((ti->ti_flags == TH_SYN) && !ntohs(ip->ip_off) &&
+ if ((t2->th_flags == TH_SYN) && !ntohs(ip->ip_off) &&
(lbuf[i] != htonl(0x020405b4))) {
lbuf[i] = htonl(0x020405b4);
bcopy((char *)ip + hlen + thlen, (char *)ip + hlen + thlen + 4,
iplen - thlen - hlen);
thlen += 4;
}
- ti->ti_off = thlen >> 2;
- ti->ti_len = htons(thlen);
+ TCP_OFF_A(t2, thlen >> 2);
+ ip2->ip_len = htons(thlen);
ip->ip_len = hlen + thlen;
- ti->ti_sum = 0;
- ti->ti_sum = chksum((u_short *)ti, thlen + sizeof(ip_t));
+ t2->th_sum = 0;
+ t2->th_sum = chksum((u_short *)ip2, thlen + sizeof(ip_t));
- bcopy((char *)&ti->ti_sport, (char *)ip + hlen, thlen);
+ bcopy((char *)t2, (char *)ip + hlen, thlen);
return send_ip(nfd, mtu, ip, gwip, 1);
}
@@ -304,16 +314,16 @@ struct in_addr gwip;
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),
+ bcopy((char *)ip + (IP_HL(ip) << 2),
(char *)&ti->ti_sport, sizeof(udphdr_t));
ti->ti_len = htons(thlen);
- ip->ip_len = (ip->ip_hl << 2) + thlen;
+ ip->ip_len = (IP_HL(ip) << 2) + thlen;
ti->ti_sum = 0;
ti->ti_sum = chksum((u_short *)ti, thlen + sizeof(ip_t));
bcopy((char *)&ti->ti_sport,
- (char *)ip + (ip->ip_hl << 2), sizeof(udphdr_t));
+ (char *)ip + (IP_HL(ip) << 2), sizeof(udphdr_t));
return send_ip(nfd, mtu, ip, gwip, 1);
}
@@ -328,7 +338,7 @@ struct in_addr gwip;
{
struct icmp *ic;
- ic = (struct icmp *)((char *)ip + (ip->ip_hl << 2));
+ ic = (struct icmp *)((char *)ip + (IP_HL(ip) << 2));
ic->icmp_cksum = 0;
ic->icmp_cksum = chksum((u_short *)ic, sizeof(struct icmp));
diff --git a/contrib/ipfilter/ipsend/ip_var.h b/contrib/ipfilter/ipsend/ip_var.h
index ace9800..b08f4e7 100644
--- a/contrib/ipfilter/ipsend/ip_var.h
+++ b/contrib/ipfilter/ipsend/ip_var.h
@@ -1,3 +1,5 @@
+/* $NetBSD$ */
+
/* @(#)ip_var.h 1.11 88/08/19 SMI; from UCB 7.1 6/5/86 */
/*
@@ -44,7 +46,7 @@ struct ipq {
* Note: ipf_next must be at same offset as ipq_next above
*/
struct ipasfrag {
-#if defined(vax) || defined(i386) || defined(__i386__)
+#if defined(vax) || defined(i386)
u_char ip_hl:4,
ip_v:4;
#endif
diff --git a/contrib/ipfilter/ipsend/ipresend.1 b/contrib/ipfilter/ipsend/ipresend.1
index 6014313..cffc6f3 100644
--- a/contrib/ipfilter/ipsend/ipresend.1
+++ b/contrib/ipfilter/ipsend/ipresend.1
@@ -1,3 +1,5 @@
+.\" $NetBSD$
+.\"
.TH IPRESEND 1
.SH NAME
ipresend \- resend IP packets out to network
diff --git a/contrib/ipfilter/ipsend/ipresend.c b/contrib/ipfilter/ipsend/ipresend.c
index 9252b4b..1db54e1 100644
--- a/contrib/ipfilter/ipsend/ipresend.c
+++ b/contrib/ipfilter/ipsend/ipresend.c
@@ -1,42 +1,33 @@
+/* $NetBSD$ */
+
/*
* ipresend.c (C) 1995-1998 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.
- *
* See the IPFILTER.LICENCE file for details on licencing.
+ *
*/
-#if defined(__sgi) && (IRIX > 602)
-# include <sys/ptimers.h>
+#if !defined(lint)
+static const char sccsid[] = "%W% %G% (C)1995 Darren Reed";
+static const char rcsid[] = "@(#)Id: ipresend.c,v 2.4 2004/01/08 13:34:31 darrenr Exp";
#endif
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <netdb.h>
-#include <string.h>
-#include <sys/types.h>
#include <sys/param.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>
#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <netdb.h>
+#include <string.h>
#include "ipsend.h"
-#if !defined(lint)
-static const char sccsid[] = "%W% %G% (C)1995 Darren Reed";
-static const char rcsid[] = "@(#)$Id: ipresend.c,v 2.1.4.4 2002/12/06 11:40:35 darrenr Exp $";
-#endif
-
extern char *optarg;
extern int optind;
diff --git a/contrib/ipfilter/ipsend/ipsend.1 b/contrib/ipfilter/ipsend/ipsend.1
index f2f8066..33320f3 100644
--- a/contrib/ipfilter/ipsend/ipsend.1
+++ b/contrib/ipfilter/ipsend/ipsend.1
@@ -1,3 +1,5 @@
+.\" $NetBSD$
+.\"
.TH IPSEND 1
.SH NAME
ipsend \- sends IP packets
diff --git a/contrib/ipfilter/ipsend/ipsend.h b/contrib/ipfilter/ipsend/ipsend.h
index 71e5490..be98c1b 100644
--- a/contrib/ipfilter/ipsend/ipsend.h
+++ b/contrib/ipfilter/ipsend/ipsend.h
@@ -1,3 +1,5 @@
+/* $NetBSD$ */
+
/*
* ipsend.h (C) 1997-1998 Darren Reed
*
@@ -6,7 +8,11 @@
* conditions, enough of the TCP header is missing for unpredictable
* results unless the filter is aware that this can happen.
*
- * See the IPFILTER.LICENCE file for details on licencing.
+ * 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.
*
*/
#ifndef __P
@@ -17,13 +23,14 @@
# endif
#endif
-#include "ip_compat.h"
+#include <net/if.h>
+
+#include "ipf.h"
#ifdef linux
#include <linux/sockios.h>
#endif
#include "tcpip.h"
#include "ipt.h"
-#include "ipf.h"
extern int resolve __P((char *, char *));
extern int arp __P((char *, char *));
@@ -35,10 +42,10 @@ extern int send_udp __P((int, int, ip_t *, struct in_addr));
extern int send_icmp __P((int, int, ip_t *, struct in_addr));
extern int send_packet __P((int, int, ip_t *, struct in_addr));
extern int send_packets __P((char *, int, ip_t *, struct in_addr));
-extern u_short seclevel __P((char *));
+extern u_short ipseclevel __P((char *));
extern u_32_t buildopts __P((char *, char *, int));
extern int addipopt __P((char *, struct ipopt_names *, int, char *));
-extern int initdevice __P((char *, int, int));
+extern int initdevice __P((char *, int));
extern int sendip __P((int, char *, int));
#ifdef linux
extern struct sock *find_tcp __P((int, struct tcpiphdr *));
@@ -55,7 +62,6 @@ extern void ip_test5 __P((char *, int, ip_t *, struct in_addr, int));
extern void ip_test6 __P((char *, int, ip_t *, struct in_addr, int));
extern void ip_test7 __P((char *, int, ip_t *, struct in_addr, int));
extern int do_socket __P((char *, int, struct tcpiphdr *, struct in_addr));
-extern int openkmem __P((void));
extern int kmemcpy __P((char *, void *, int));
#define KMCPY(a,b,c) kmemcpy((char *)(a), (void *)(b), (int)(c))
@@ -63,9 +69,3 @@ extern int kmemcpy __P((char *, void *, int));
#ifndef OPT_RAW
#define OPT_RAW 0x80000
#endif
-
-#ifndef __STDC__
-# ifndef const
-# define const
-# endif
-#endif
diff --git a/contrib/ipfilter/ipsend/ipsopt.c b/contrib/ipfilter/ipsend/ipsopt.c
index 144c86f..7f16705 100644
--- a/contrib/ipfilter/ipsend/ipsopt.c
+++ b/contrib/ipfilter/ipsend/ipsopt.c
@@ -1,21 +1,25 @@
+/* $NetBSD$ */
+
/*
* Copyright (C) 1995-1998 by Darren Reed.
*
* See the IPFILTER.LICENCE file for details on licencing.
+ *
*/
-#if defined(__sgi) && (IRIX > 602)
-# include <sys/ptimers.h>
+#if !defined(lint)
+static const char sccsid[] = "@(#)ipsopt.c 1.2 1/11/96 (C)1995 Darren Reed";
+static const char rcsid[] = "@(#)Id: ipsopt.c,v 2.4.4.1 2004/03/23 12:58:05 darrenr Exp";
#endif
#include <sys/param.h>
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.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 <stdio.h>
+#include <string.h>
+#include <stdlib.h>
#ifndef linux
#include <netinet/ip_var.h>
#endif
@@ -23,9 +27,13 @@
#include <arpa/inet.h>
#include "ipsend.h"
-#if !defined(lint)
-static const char sccsid[] = "@(#)ipsopt.c 1.2 1/11/96 (C)1995 Darren Reed";
-static const char rcsid[] = "@(#)$Id: ipsopt.c,v 2.1.4.5 2004/04/10 11:50:52 darrenr Exp $";
+
+#ifndef __P
+# ifdef __STDC__
+# define __P(x) x
+# else
+# define __P(x) ()
+# endif
#endif
@@ -53,7 +61,7 @@ struct ipopt_names secnames[] = {
};
-u_short seclevel(slevel)
+u_short ipseclevel(slevel)
char *slevel;
{
struct ipopt_names *so;
@@ -108,7 +116,7 @@ char *class;
switch (io->on_value)
{
case IPOPT_SECURITY :
- lvl = seclevel(class);
+ lvl = ipseclevel(class);
*(op - 1) = lvl;
break;
case IPOPT_LSRR :
diff --git a/contrib/ipfilter/ipsend/iptest.c b/contrib/ipfilter/ipsend/iptest.c
index 72d0d78..45f8f3a 100644
--- a/contrib/ipfilter/ipsend/iptest.c
+++ b/contrib/ipfilter/ipsend/iptest.c
@@ -1,21 +1,15 @@
+/* $NetBSD$ */
+
/*
* ipsend.c (C) 1995-1998 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.
- *
* See the IPFILTER.LICENCE file for details on licencing.
+ *
*/
-#if defined(__sgi) && (IRIX > 602)
-# include <sys/ptimers.h>
+#if !defined(lint)
+static const char sccsid[] = "%W% %G% (C)1995 Darren Reed";
+static const char rcsid[] = "@(#)Id: iptest.c,v 2.6 2004/01/08 13:34:31 darrenr Exp";
#endif
-#include <stdio.h>
-#include <netdb.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <string.h>
#include <sys/param.h>
#include <sys/types.h>
#include <sys/time.h>
@@ -24,22 +18,19 @@
#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>
#endif
#ifdef linux
#include <linux/sockios.h>
#endif
+#include <stdio.h>
+#include <netdb.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
#include "ipsend.h"
-#if !defined(lint)
-static const char sccsid[] = "%W% %G% (C)1995 Darren Reed";
-static const char rcsid[] = "@(#)$Id: iptest.c,v 2.2.2.4 2002/12/06 11:40:35 darrenr Exp $";
-#endif
-
extern char *optarg;
extern int optind;
@@ -111,7 +102,7 @@ char **argv;
ip = (ip_t *)calloc(1, 65536);
ti = (struct tcpiphdr *)ip;
ip->ip_len = sizeof(*ip);
- ip->ip_hl = sizeof(*ip) >> 2;
+ IP_HL_A(ip, sizeof(*ip) >> 2);
while ((c = getopt(argc, argv, "1234567d:g:m:p:s:")) != -1)
switch (c)
diff --git a/contrib/ipfilter/ipsend/larp.c b/contrib/ipfilter/ipsend/larp.c
index d178d64..a8e782e 100644
--- a/contrib/ipfilter/ipsend/larp.c
+++ b/contrib/ipfilter/ipsend/larp.c
@@ -1,21 +1,25 @@
+/* $NetBSD$ */
+
/*
* larp.c (C) 1995-1998 Darren Reed
*
* See the IPFILTER.LICENCE file for details on licencing.
+ *
*/
#if !defined(lint)
static const char sccsid[] = "@(#)larp.c 1.1 8/19/95 (C)1995 Darren Reed";
-static const char rcsid[] = "@(#)$Id: larp.c,v 2.1.4.1 2001/06/26 10:43:22 darrenr Exp $";
+static const char rcsid[] = "@(#)Id: larp.c,v 2.4 2003/12/01 02:01:16 darrenr Exp";
#endif
-#include <stdio.h>
-#include <errno.h>
+#include <sys/param.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>
+#include <stdio.h>
+#include <netdb.h>
+#include <errno.h>
#include "ip_compat.h"
#include "iplang/iplang.h"
@@ -25,7 +29,7 @@ static const char rcsid[] = "@(#)$Id: larp.c,v 2.1.4.1 2001/06/26 10:43:22 darre
* its IP address in address
* (4 bytes)
*/
-int resolve(host, address)
+int resolve(host, address)
char *host, *address;
{
struct hostent *hp;
diff --git a/contrib/ipfilter/ipsend/linux.h b/contrib/ipfilter/ipsend/linux.h
index 2d2a243..d8296ba 100644
--- a/contrib/ipfilter/ipsend/linux.h
+++ b/contrib/ipfilter/ipsend/linux.h
@@ -1,7 +1,11 @@
+/* $NetBSD$ */
+
/*
* Copyright (C) 1995-1998 by Darren Reed.
*
- * See the IPFILTER.LICENCE file for details on licencing.
+ * 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
*/
diff --git a/contrib/ipfilter/ipsend/lsock.c b/contrib/ipfilter/ipsend/lsock.c
index 23a7621..abe664e 100644
--- a/contrib/ipfilter/ipsend/lsock.c
+++ b/contrib/ipfilter/ipsend/lsock.c
@@ -1,14 +1,14 @@
+/* $NetBSD$ */
+
/*
* lsock.c (C) 1995-1998 Darren Reed
*
* See the IPFILTER.LICENCE file for details on licencing.
+ *
*/
#if !defined(lint)
static const char sccsid[] = "@(#)lsock.c 1.2 1/11/96 (C)1995 Darren Reed";
-static const char rcsid[] = "@(#)$Id: lsock.c,v 2.1.4.3 2002/12/06 11:40:36 darrenr Exp $";
-#endif
-#if defined(__sgi) && (IRIX > 602)
-# include <sys/ptimers.h>
+static const char rcsid[] = "@(#)Id: lsock.c,v 2.3 2001/06/09 17:09:26 darrenr Exp";
#endif
#include <stdio.h>
#include <unistd.h>
@@ -226,7 +226,7 @@ struct in_addr gwip;
(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), 0);
+ nfd = initdevice(dev, 0);
if (!(s = find_tcp(fd, ti)))
return -1;
diff --git a/contrib/ipfilter/ipsend/resend.c b/contrib/ipfilter/ipsend/resend.c
index 646da1a..07220df 100644
--- a/contrib/ipfilter/ipsend/resend.c
+++ b/contrib/ipfilter/ipsend/resend.c
@@ -1,21 +1,16 @@
+/* $NetBSD$ */
+
/*
* resend.c (C) 1995-1998 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.
- *
* See the IPFILTER.LICENCE file for details on licencing.
+ *
*/
-#if defined(__sgi) && (IRIX > 602)
-# include <sys/ptimers.h>
+#if !defined(lint)
+static const char sccsid[] = "@(#)resend.c 1.3 1/11/96 (C)1995 Darren Reed";
+static const char rcsid[] = "@(#)Id: resend.c,v 2.8 2004/01/08 13:34:31 darrenr Exp";
#endif
-#include <stdio.h>
-#include <netdb.h>
-#include <string.h>
-#include <stdlib.h>
-#include <unistd.h>
+#include <sys/param.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/socket.h>
@@ -24,9 +19,6 @@
#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/if_ether.h>
@@ -34,14 +26,13 @@
# include <net/if_var.h>
# endif
#endif
+#include <stdio.h>
+#include <netdb.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
#include "ipsend.h"
-#if !defined(lint)
-static const char sccsid[] = "@(#)resend.c 1.3 1/11/96 (C)1995 Darren Reed";
-static const char rcsid[] = "@(#)$Id: resend.c,v 2.1.4.5 2002/12/06 11:40:36 darrenr Exp $";
-#endif
-
-
extern int opts;
static u_char pbuf[65536]; /* 1 big packet */
@@ -54,7 +45,7 @@ ip_t *ip;
tcphdr_t *t;
int i, j;
- t = (tcphdr_t *)((char *)ip + (ip->ip_hl << 2));
+ t = (tcphdr_t *)((char *)ip + (IP_HL(ip) << 2));
if (ip->ip_tos)
printf("tos %#x ", ip->ip_tos);
if (ip->ip_off & 0x3fff)
@@ -88,13 +79,13 @@ char *datain;
ether_header_t *eh;
char dhost[6];
ip_t *ip;
- int fd, wfd = initdevice(dev, 0, 5), len, i;
+ int fd, wfd = initdevice(dev, 5), len, i;
if (datain)
fd = (*r->r_open)(datain);
else
fd = (*r->r_open)("-");
-
+
if (fd < 0)
exit(-1);
@@ -130,7 +121,7 @@ char *datain;
sizeof(dhost));
if (!ip->ip_sum)
ip->ip_sum = chksum((u_short *)ip,
- ip->ip_hl << 2);
+ IP_HL(ip) << 2);
bcopy(ip, (char *)(eh + 1), len);
len += sizeof(*eh);
printpacket(ip);
diff --git a/contrib/ipfilter/ipsend/sdlpi.c b/contrib/ipfilter/ipsend/sdlpi.c
index dcd8422..215223a 100644
--- a/contrib/ipfilter/ipsend/sdlpi.c
+++ b/contrib/ipfilter/ipsend/sdlpi.c
@@ -1,7 +1,10 @@
+/* $NetBSD$ */
+
/*
* (C)opyright 1992-1998 Darren Reed. (from tcplog)
*
* See the IPFILTER.LICENCE file for details on licencing.
+ *
*/
#include <stdio.h>
@@ -19,10 +22,17 @@
#include <sys/stropts.h>
#ifdef sun
-#include <sys/pfmod.h>
-#include <sys/bufmod.h>
+# include <sys/pfmod.h>
+# include <sys/bufmod.h>
+#endif
+#ifdef __osf__
+# include <sys/dlpihdr.h>
+#else
+# include <sys/dlpi.h>
+#endif
+#ifdef __hpux
+# include <sys/dlpi_ext.h>
#endif
-#include <sys/dlpi.h>
#include <net/if.h>
#include <netinet/in.h>
@@ -38,7 +48,7 @@
#if !defined(lint)
static const char sccsid[] = "@(#)sdlpi.c 1.3 10/30/95 (C)1995 Darren Reed";
-static const char rcsid[] = "@(#)$Id: sdlpi.c,v 2.1.4.2 2001/06/26 10:43:22 darrenr Exp $";
+static const char rcsid[] = "@(#)Id: sdlpi.c,v 2.8.2.1 2004/12/09 19:41:13 darrenr Exp";
#endif
#define CHUNKSIZE 8192
@@ -49,9 +59,9 @@ static const char rcsid[] = "@(#)$Id: sdlpi.c,v 2.1.4.2 2001/06/26 10:43:22 darr
* 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)
+int initdevice(device, tout)
char *device;
-int sport, tout;
+int tout;
{
char devname[16], *s, buf[256];
int i, fd;
@@ -60,7 +70,7 @@ int sport, tout;
(void) strncat(devname, device, sizeof(devname) - strlen(devname));
s = devname + 5;
- while (*s && !isdigit(*s))
+ while (*s && !ISDIGIT(*s))
s++;
if (!*s)
{
@@ -79,24 +89,43 @@ int sport, tout;
exit(-1);
}
- if (dlattachreq(fd, i) == -1 || dlokack(fd, buf) == -1)
+ if (dlattachreq(fd, i) == -1)
+ {
+ fprintf(stderr, "dlattachreq: DLPI error\n");
+ exit(-1);
+ }
+ else if (dlokack(fd, buf) == -1)
+ {
+ fprintf(stderr, "dlokack(attach): DLPI error\n");
+ exit(-1);
+ }
+#ifdef DL_HP_RAWDLS
+ if (dlpromisconreq(fd, DL_PROMISC_SAP) < 0)
{
- fprintf(stderr, "DLPI error\n");
+ fprintf(stderr, "dlpromisconreq: DL_PROMISC_PHYS error\n");
exit(-1);
}
+ else if (dlokack(fd, buf) < 0)
+ {
+ fprintf(stderr, "dlokack(promisc): DLPI error\n");
+ exit(-1);
+ }
+ /* 22 is INSAP as per the HP-UX DLPI Programmer's Guide */
+
+ dlbindreq(fd, 22, 1, DL_HP_RAWDLS, 0, 0);
+#else
dlbindreq(fd, ETHERTYPE_IP, 0, DL_CLDLS, 0, 0);
+#endif
dlbindack(fd, buf);
/*
* write full headers
*/
-#ifdef sun /* we require RAW DLPI mode, which is a Sun extension */
+#ifdef DLIOCRAW /* we require RAW DLPI mode, which is a Sun extension */
if (strioctl(fd, DLIOCRAW, -1, 0, NULL) == -1)
{
fprintf(stderr, "DLIOCRAW error\n");
exit(-1);
}
-#else
-you lose
#endif
return fd;
}
@@ -109,8 +138,19 @@ int sendip(fd, pkt, len)
int fd, len;
char *pkt;
{
- struct strbuf dbuf, *dp = &dbuf;
+ struct strbuf dbuf, *dp = &dbuf, *cp = NULL;
+ int pri = 0;
+#ifdef DL_HP_RAWDLS
+ struct strbuf cbuf;
+ dl_hp_rawdata_req_t raw;
+ cp = &cbuf;
+ raw.dl_primitive = DL_HP_RAWDATA_REQ;
+ cp->len = sizeof(raw);
+ cp->buf = (char *)&raw;
+ cp->maxlen = cp->len;
+ pri = MSG_HIPRI;
+#endif
/*
* construct NIT STREAMS messages, first control then data.
*/
@@ -118,7 +158,7 @@ char *pkt;
dp->len = len;
dp->maxlen = dp->len;
- if (putmsg(fd, NULL, dp, 0) == -1)
+ if (putmsg(fd, cp, dp, pri) == -1)
{
perror("putmsg");
return -1;
@@ -130,3 +170,4 @@ char *pkt;
}
return len;
}
+
diff --git a/contrib/ipfilter/ipsend/sirix.c b/contrib/ipfilter/ipsend/sirix.c
index 8f491f7..39a0992 100644
--- a/contrib/ipfilter/ipsend/sirix.c
+++ b/contrib/ipfilter/ipsend/sirix.c
@@ -1,12 +1,12 @@
+/* $NetBSD$ */
+
/*
* (C)opyright 1992-1998 Darren Reed.
* (C)opyright 1997 Marc Boucher.
*
* See the IPFILTER.LICENCE file for details on licencing.
+ *
*/
-#if defined(__sgi) && (IRIX > 602)
-# include <sys/ptimers.h>
-#endif
#include <stdio.h>
#include <sys/types.h>
#include <string.h>
@@ -23,17 +23,15 @@
#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 "ipsend.h"
+#include <netinet/udp_var.h>
#if !defined(lint) && defined(LIBC_SCCS)
static char sirix[] = "@(#)sirix.c 1.0 10/9/97 (C)1997 Marc Boucher";
#endif
-int initdevice(char *device, int sport, int tout)
+int initdevice(char *device, int tout)
{
int fd;
struct sockaddr_raw sr;
diff --git a/contrib/ipfilter/ipsend/slinux.c b/contrib/ipfilter/ipsend/slinux.c
index 7438d1c..3bc7f09 100644
--- a/contrib/ipfilter/ipsend/slinux.c
+++ b/contrib/ipfilter/ipsend/slinux.c
@@ -1,7 +1,10 @@
+/* $NetBSD$ */
+
/*
* (C)opyright 1992-1998 Darren Reed. (from tcplog)
*
* See the IPFILTER.LICENCE file for details on licencing.
+ *
*/
#include <stdio.h>
@@ -27,7 +30,7 @@
#if !defined(lint)
static const char sccsid[] = "@(#)slinux.c 1.2 8/25/95";
-static const char rcsid[] = "@(#)$Id: slinux.c,v 2.1.4.1 2001/06/26 10:43:22 darrenr Exp $";
+static const char rcsid[] = "@(#)Id: slinux.c,v 2.3 2001/06/09 17:09:26 darrenr Exp";
#endif
#define CHUNKSIZE 8192
@@ -42,9 +45,9 @@ static int timeout;
static char *eth_dev = NULL;
-int initdevice(dev, sport, spare)
+int initdevice(dev, spare)
char *dev;
-int sport, spare;
+int spare;
{
int fd;
diff --git a/contrib/ipfilter/ipsend/snit.c b/contrib/ipfilter/ipsend/snit.c
index 6f2c662..a4b19b9 100644
--- a/contrib/ipfilter/ipsend/snit.c
+++ b/contrib/ipfilter/ipsend/snit.c
@@ -1,7 +1,10 @@
+/* $NetBSD$ */
+
/*
* (C)opyright 1992-1998 Darren Reed. (from tcplog)
*
* See the IPFILTER.LICENCE file for details on licencing.
+ *
*/
#include <stdio.h>
@@ -38,7 +41,7 @@
#if !defined(lint)
static const char sccsid[] = "@(#)snit.c 1.5 1/11/96 (C)1995 Darren Reed";
-static const char rcsid[] = "@(#)$Id: snit.c,v 2.1.4.1 2001/06/26 10:43:22 darrenr Exp $";
+static const char rcsid[] = "@(#)Id: snit.c,v 2.3 2001/06/09 17:09:26 darrenr Exp";
#endif
#define CHUNKSIZE 8192
@@ -54,9 +57,9 @@ static const char rcsid[] = "@(#)$Id: snit.c,v 2.1.4.1 2001/06/26 10:43:22 darre
static int timeout;
-int initdevice(device, sport, tout)
+int initdevice(device, tout)
char *device;
-int sport, tout;
+int tout;
{
struct strioctl si;
struct timeval to;
diff --git a/contrib/ipfilter/ipsend/sockraw.c b/contrib/ipfilter/ipsend/sockraw.c
new file mode 100644
index 0000000..822c146
--- /dev/null
+++ b/contrib/ipfilter/ipsend/sockraw.c
@@ -0,0 +1,89 @@
+/* $NetBSD$ */
+
+/*
+ * (C)opyright 2000 Darren Reed.
+ *
+ * See the IPFILTER.LICENCE file for details on licencing.
+ *
+ * WARNING: Attempting to use this .c file on HP-UX 11.00 will cause the
+ * system to crash.
+ */
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/ioctl.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 <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <errno.h>
+#include "ipsend.h"
+
+#if !defined(lint) && defined(LIBC_SCCS)
+static char sirix[] = "@(#)sirix.c 1.0 10/9/97 (C)1997 Marc Boucher";
+#endif
+
+
+int initdevice(char *device, int tout)
+{
+ struct sockaddr s;
+ struct ifreq ifr;
+ int fd;
+
+ memset(&ifr, 0, sizeof(ifr));
+ strncpy(ifr.ifr_name, device, sizeof ifr.ifr_name);
+
+ if ((fd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0)
+ {
+ perror("socket(AF_INET, SOCK_RAW, IPPROTO_RAW)");
+ return -1;
+ }
+
+ if (ioctl(fd, SIOCGIFADDR, &ifr) == -1)
+ {
+ perror("ioctl SIOCGIFADDR");
+ return -1;
+ }
+
+ bzero((char *)&s, sizeof(s));
+ s.sa_family = AF_INET;
+ bcopy(&ifr.ifr_addr, s.sa_data, 4);
+ if (bind(fd, &s, sizeof(s)) == -1)
+ perror("bind");
+ return fd;
+}
+
+
+/*
+ * output an IP packet
+ */
+int sendip(int fd, char *pkt, int len)
+{
+ struct ether_header *eh;
+ struct sockaddr_in sin;
+
+ eh = (struct ether_header *)pkt;
+ bzero((char *)&sin, sizeof(sin));
+ sin.sin_family = AF_INET;
+ pkt += 14;
+ len -= 14;
+ bcopy(pkt + 12, (char *)&sin.sin_addr, 4);
+
+ if (sendto(fd, pkt, len, 0, &sin, sizeof(sin)) == -1)
+ {
+ perror("send");
+ return -1;
+ }
+
+ return len;
+}
diff --git a/contrib/ipfilter/ipsend/tcpip.h b/contrib/ipfilter/ipsend/tcpip.h
index c735593..0d3e040 100644
--- a/contrib/ipfilter/ipsend/tcpip.h
+++ b/contrib/ipfilter/ipsend/tcpip.h
@@ -1,3 +1,5 @@
+/* $NetBSD$ */
+
/*
* Copyright (c) 1982, 1986, 1993
* The Regents of the University of California. All rights reserved.
@@ -10,11 +12,7 @@
* 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
+ * 3. 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.
*
@@ -31,7 +29,7 @@
* SUCH DAMAGE.
*
* @(#)tcpip.h 8.1 (Berkeley) 6/10/93
- * $Id: tcpip.h,v 2.1 1999/08/04 17:31:16 darrenr Exp $
+ * Id: tcpip.h,v 2.2.2.3 2004/05/26 15:45:48 darrenr Exp
*/
#ifndef _NETINET_TCPIP_H_
@@ -54,12 +52,9 @@ struct ipovly {
*/
struct tcpiphdr {
struct ipovly ti_i; /* overlaid ip structure */
-#ifdef linux
- tcphdr_t ti_t;
-#else
struct tcphdr ti_t; /* tcp header */
-#endif
};
+
#ifdef notyet
/*
* Tcp+ip header, after ip options removed but including TCP options.
diff --git a/contrib/ipfilter/ipt.h b/contrib/ipfilter/ipt.h
index 677c74a..6a14fe5 100644
--- a/contrib/ipfilter/ipt.h
+++ b/contrib/ipfilter/ipt.h
@@ -1,8 +1,11 @@
+/* $NetBSD$ */
+
/*
* Copyright (C) 1993-2001 by Darren Reed.
*
* See the IPFILTER.LICENCE file for details on licencing.
- * $Id: ipt.h,v 2.2.2.1 2001/06/26 10:43:19 darrenr Exp $
+ *
+ * Id: ipt.h,v 2.6 2003/02/16 02:33:09 darrenr Exp
*/
#ifndef __IPT_H__
@@ -24,8 +27,11 @@ struct ipread {
int (*r_open) __P((char *));
int (*r_close) __P((void));
int (*r_readip) __P((char *, int, char **, int *));
+ int r_flags;
};
+#define R_DO_CKSUM 0x01
+
extern void debug __P((char *, ...));
extern void verbose __P((char *, ...));
diff --git a/contrib/ipfilter/kmem.h b/contrib/ipfilter/kmem.h
index f7056c2..7cb6635 100644
--- a/contrib/ipfilter/kmem.h
+++ b/contrib/ipfilter/kmem.h
@@ -1,8 +1,10 @@
+/* $NetBSD$ */
+
/*
* Copyright (C) 1993-2001 by Darren Reed.
*
* See the IPFILTER.LICENCE file for details on licencing.
- * $Id: kmem.h,v 2.2.2.4 2002/01/01 13:43:48 darrenr Exp $
+ * Id: kmem.h,v 2.5 2002/08/21 22:57:36 darrenr Exp
*/
#ifndef __KMEM_H__
@@ -18,7 +20,6 @@
extern int openkmem __P((char *, char *));
extern int kmemcpy __P((char *, long, int));
extern int kstrncpy __P((char *, long, int));
-extern char *getifname __P((void *));
#if defined(__NetBSD__) || defined(__OpenBSD)
# include <paths.h>
diff --git a/contrib/ipfilter/l4check/http.ok b/contrib/ipfilter/l4check/http.ok
index 2b5d2c1..0e7dd90 100644
--- a/contrib/ipfilter/l4check/http.ok
+++ b/contrib/ipfilter/l4check/http.ok
@@ -1 +1 @@
-<HTML> \ No newline at end of file
+<HTML>
diff --git a/contrib/ipfilter/l4check/l4check.c b/contrib/ipfilter/l4check/l4check.c
index 23ac79a..68c41de 100644
--- a/contrib/ipfilter/l4check/l4check.c
+++ b/contrib/ipfilter/l4check/l4check.c
@@ -1,3 +1,5 @@
+/* $NetBSD$ */
+
/*
* (C)Copyright March, 2000 - Darren Reed.
*/
@@ -141,8 +143,7 @@ void closel4(l4, dead)
l4cfg_t *l4;
int dead;
{
- if (l4->l4_fd != -1)
- close(l4->l4_fd);
+ close(l4->l4_fd);
l4->l4_fd = -1;
l4->l4_rw = -1;
if (dead && l4->l4_alive) {
@@ -308,7 +309,7 @@ int runconfig()
if (opts & OPT_VERBOSE)
fprintf(stderr, "failed\n");
perror("connect");
- closel4(l4, 1);
+ close(fd);
fd = -1;
} else {
if (opts & OPT_VERBOSE)
@@ -417,10 +418,10 @@ u_short *portp;
*port++ = '\0';
#ifdef HAVE_INET_ATON
- if (isdigit(*host) && inet_aton(host, &ip))
+ if (ISDIGIT(*host) && inet_aton(host, &ip))
*ipp = ip.s_addr;
#else
- if (isdigit(*host))
+ if (ISDIGIT(*host))
*ipp = inet_addr(host);
#endif
else {
@@ -433,7 +434,7 @@ u_short *portp;
}
if (port) {
- if (isdigit(*port))
+ if (ISDIGIT(*port))
*portp = htons(atoi(port));
else {
sp = getservbyname(port, "tcp");
@@ -526,7 +527,7 @@ char *filename;
/*
* Skip leading whitespace
*/
- for (line = buf; (c = *line) && isspace(c); line++)
+ for (line = buf; (c = *line) && ISSPACE(c); line++)
;
if (!*line)
continue;
@@ -606,14 +607,14 @@ char *filename;
}
bcopy((char *)&template, (char *)l4, sizeof(*l4));
l4->l4_sin.sin_addr = ipn->in_in[0];
- l4->l4_sin.sin_port = ipn->in_pnext;
+ l4->l4_sin.sin_port = ipn->in_pnext;
l4->l4_next = l4list;
l4list = l4;
} else if (!strcasecmp(t, "connect")) {
s = strtok(NULL, " \t");
if (s)
t = strtok(NULL, "\t");
- if (!s || !t) {
+ if (!s || !t) {
errtxt = line;
err = -1;
break;
@@ -635,7 +636,7 @@ char *filename;
}
} else if (!strcasecmp(t, "probe")) {
s = strtok(NULL, " \t");
- if (!s) {
+ if (!s) {
errtxt = line;
err = -1;
break;
@@ -683,13 +684,13 @@ char *filename;
}
} else if (!strcasecmp(t, "response")) {
s = strtok(NULL, " \t");
- if (!s) {
+ if (!s) {
errtxt = line;
err = -1;
break;
} else if (!strcasecmp(s, "timeout")) {
t = strtok(NULL, " \t");
- if (!t) {
+ if (!t) {
errtxt = line;
err = -1;
break;
diff --git a/contrib/ipfilter/lib/Makefile b/contrib/ipfilter/lib/Makefile
new file mode 100644
index 0000000..d448ba0
--- /dev/null
+++ b/contrib/ipfilter/lib/Makefile
@@ -0,0 +1,309 @@
+INCDEP=$(TOP)/ip_compat.h $(TOP)/ip_fil.h $(TOP)/ipf.h
+
+LIBOBJS=$(DEST)/addicmp.o \
+ $(DEST)/addipopt.o \
+ $(DEST)/addkeep.o \
+ $(DEST)/bcopywrap.o \
+ $(DEST)/binprint.o \
+ $(DEST)/buildopts.o \
+ $(DEST)/checkrev.o \
+ $(DEST)/count6bits.o \
+ $(DEST)/count4bits.o \
+ $(DEST)/debug.o \
+ $(DEST)/extras.o \
+ $(DEST)/facpri.o \
+ $(DEST)/flags.o \
+ $(DEST)/fill6bits.o \
+ $(DEST)/genmask.o \
+ $(DEST)/gethost.o \
+ $(DEST)/getifname.o \
+ $(DEST)/getline.o \
+ $(DEST)/getnattype.o \
+ $(DEST)/getport.o \
+ $(DEST)/getportproto.o \
+ $(DEST)/getproto.o \
+ $(DEST)/getsumd.o \
+ $(DEST)/hexdump.o \
+ $(DEST)/hostmask.o \
+ $(DEST)/hostname.o \
+ $(DEST)/hostnum.o \
+ $(DEST)/icmpcode.o \
+ $(DEST)/inet_addr.o \
+ $(DEST)/initparse.o \
+ $(DEST)/ionames.o \
+ $(DEST)/ipoptsec.o \
+ $(DEST)/ipf_dotuning.o \
+ $(DEST)/ipft_ef.o \
+ $(DEST)/ipft_hx.o \
+ $(DEST)/ipft_pc.o \
+ $(DEST)/ipft_sn.o \
+ $(DEST)/ipft_td.o \
+ $(DEST)/ipft_tx.o \
+ $(DEST)/kmem.o \
+ $(DEST)/kmemcpywrap.o \
+ $(DEST)/kvatoname.o \
+ $(DEST)/load_hash.o \
+ $(DEST)/load_hashnode.o \
+ $(DEST)/load_pool.o \
+ $(DEST)/load_poolnode.o \
+ $(DEST)/loglevel.o \
+ $(DEST)/make_range.o \
+ $(DEST)/mutex_emul.o \
+ $(DEST)/nametokva.o \
+ $(DEST)/nat_setgroupmap.o \
+ $(DEST)/ntomask.o \
+ $(DEST)/optname.o \
+ $(DEST)/optprint.o \
+ $(DEST)/optprintv6.o \
+ $(DEST)/optvalue.o \
+ $(DEST)/portname.o \
+ $(DEST)/portnum.o \
+ $(DEST)/ports.o \
+ $(DEST)/print_toif.o \
+ $(DEST)/printactivenat.o \
+ $(DEST)/printaps.o \
+ $(DEST)/printbuf.o \
+ $(DEST)/printhash.o \
+ $(DEST)/printhashnode.o \
+ $(DEST)/printip.o \
+ $(DEST)/printpool.o \
+ $(DEST)/printpoolnode.o \
+ $(DEST)/printfr.o \
+ $(DEST)/printfraginfo.o \
+ $(DEST)/printhostmap.o \
+ $(DEST)/printifname.o \
+ $(DEST)/printhostmask.o \
+ $(DEST)/printlog.o \
+ $(DEST)/printmask.o \
+ $(DEST)/printnat.o \
+ $(DEST)/printportcmp.o \
+ $(DEST)/printpacket.o \
+ $(DEST)/printpacket6.o \
+ $(DEST)/printsbuf.o \
+ $(DEST)/printstate.o \
+ $(DEST)/printtunable.o \
+ $(DEST)/ratoi.o \
+ $(DEST)/ratoui.o \
+ $(DEST)/remove_hash.o \
+ $(DEST)/remove_hashnode.o \
+ $(DEST)/remove_pool.o \
+ $(DEST)/remove_poolnode.o \
+ $(DEST)/resetlexer.o \
+ $(DEST)/rwlock_emul.o \
+ $(DEST)/tcpflags.o \
+ $(DEST)/tcp_flags.o \
+ $(DEST)/to_interface.o \
+ $(DEST)/var.o \
+ $(DEST)/verbose.o \
+ $(DEST)/v6ionames.o \
+ $(DEST)/v6optvalue.o
+
+$(DEST)/libipf.a: $(LIBOBJS)
+ /bin/rm -f $@
+ ar $(AROPTS) $@ $(LIBOBJS)
+ $(RANLIB) $@
+
+$(DEST)/addicmp.o: $(LIBSRC)/addicmp.c $(INCDEP)
+ $(CC) $(CCARGS) -c $(LIBSRC)/addicmp.c -o $@
+$(DEST)/addipopt.o: $(LIBSRC)/addipopt.c $(INCDEP)
+ $(CC) $(CCARGS) -c $(LIBSRC)/addipopt.c -o $@
+$(DEST)/addkeep.o: $(LIBSRC)/addkeep.c $(INCDEP)
+ $(CC) $(CCARGS) -c $(LIBSRC)/addkeep.c -o $@
+$(DEST)/bcopywrap.o: $(LIBSRC)/bcopywrap.c $(INCDEP)
+ $(CC) $(CCARGS) -c $(LIBSRC)/bcopywrap.c -o $@
+$(DEST)/binprint.o: $(LIBSRC)/binprint.c $(INCDEP)
+ $(CC) $(CCARGS) -c $(LIBSRC)/binprint.c -o $@
+$(DEST)/buildopts.o: $(LIBSRC)/buildopts.c $(INCDEP)
+ $(CC) $(CCARGS) -c $(LIBSRC)/buildopts.c -o $@
+$(DEST)/count6bits.o: $(LIBSRC)/count6bits.c $(INCDEP)
+ $(CC) $(CCARGS) -c $(LIBSRC)/count6bits.c -o $@
+$(DEST)/checkrev.o: $(LIBSRC)/checkrev.c $(INCDEP) $(TOP)/ipl.h
+ $(CC) $(CCARGS) -c $(LIBSRC)/checkrev.c -o $@
+$(DEST)/count4bits.o: $(LIBSRC)/count4bits.c $(INCDEP)
+ $(CC) $(CCARGS) -c $(LIBSRC)/count4bits.c -o $@
+$(DEST)/debug.o: $(LIBSRC)/debug.c $(INCDEP)
+ $(CC) $(CCARGS) -c $(LIBSRC)/debug.c -o $@
+$(DEST)/extras.o: $(LIBSRC)/extras.c $(INCDEP)
+ $(CC) $(CCARGS) -c $(LIBSRC)/extras.c -o $@
+$(DEST)/facpri.o: $(LIBSRC)/facpri.c $(INCDEP)
+ $(CC) $(CCARGS) -c $(LIBSRC)/facpri.c -o $@
+$(DEST)/fill6bits.o: $(LIBSRC)/fill6bits.c $(INCDEP)
+ $(CC) $(CCARGS) -c $(LIBSRC)/fill6bits.c -o $@
+$(DEST)/flags.o: $(LIBSRC)/flags.c $(INCDEP)
+ $(CC) $(CCARGS) -c $(LIBSRC)/flags.c -o $@
+$(DEST)/genmask.o: $(LIBSRC)/genmask.c $(INCDEP)
+ $(CC) $(CCARGS) -c $(LIBSRC)/genmask.c -o $@
+$(DEST)/getline.o: $(LIBSRC)/getline.c $(INCDEP)
+ $(CC) $(CCARGS) -c $(LIBSRC)/getline.c -o $@
+$(DEST)/gethost.o: $(LIBSRC)/gethost.c $(INCDEP)
+ $(CC) $(CCARGS) -c $(LIBSRC)/gethost.c -o $@
+$(DEST)/getifname.o: $(LIBSRC)/getifname.c $(INCDEP)
+ $(CC) $(CCARGS) -c $(LIBSRC)/getifname.c -o $@
+$(DEST)/getnattype.o: $(LIBSRC)/getnattype.c $(INCDEP)
+ $(CC) $(CCARGS) -c $(LIBSRC)/getnattype.c -o $@
+$(DEST)/getport.o: $(LIBSRC)/getport.c $(INCDEP)
+ $(CC) $(CCARGS) -c $(LIBSRC)/getport.c -o $@
+$(DEST)/getportproto.o: $(LIBSRC)/getportproto.c $(INCDEP)
+ $(CC) $(CCARGS) -c $(LIBSRC)/getportproto.c -o $@
+$(DEST)/getproto.o: $(LIBSRC)/getproto.c $(INCDEP)
+ $(CC) $(CCARGS) -c $(LIBSRC)/getproto.c -o $@
+$(DEST)/getsumd.o: $(LIBSRC)/getsumd.c $(INCDEP)
+ $(CC) $(CCARGS) -c $(LIBSRC)/getsumd.c -o $@
+$(DEST)/hexdump.o: $(LIBSRC)/hexdump.c $(INCDEP)
+ $(CC) $(CCARGS) -c $(LIBSRC)/hexdump.c -o $@
+$(DEST)/hostmask.o: $(LIBSRC)/hostmask.c $(INCDEP)
+ $(CC) $(CCARGS) -c $(LIBSRC)/hostmask.c -o $@
+$(DEST)/hostname.o: $(LIBSRC)/hostname.c $(INCDEP)
+ $(CC) $(CCARGS) -c $(LIBSRC)/hostname.c -o $@
+$(DEST)/hostnum.o: $(LIBSRC)/hostnum.c $(INCDEP)
+ $(CC) $(CCARGS) -c $(LIBSRC)/hostnum.c -o $@
+$(DEST)/icmpcode.o: $(LIBSRC)/icmpcode.c $(INCDEP)
+ $(CC) $(CCARGS) -c $(LIBSRC)/icmpcode.c -o $@
+$(DEST)/ipoptsec.o: $(LIBSRC)/ipoptsec.c $(INCDEP)
+ $(CC) $(CCARGS) -c $(LIBSRC)/ipoptsec.c -o $@
+$(DEST)/inet_addr.o: $(LIBSRC)/inet_addr.c $(INCDEP)
+ $(CC) $(CCARGS) -c $(LIBSRC)/inet_addr.c -o $@
+$(DEST)/initparse.o: $(LIBSRC)/initparse.c $(INCDEP)
+ $(CC) $(CCARGS) -c $(LIBSRC)/initparse.c -o $@
+$(DEST)/ionames.o: $(LIBSRC)/ionames.c $(INCDEP)
+ $(CC) $(CCARGS) -c $(LIBSRC)/ionames.c -o $@
+$(DEST)/ipf_dotuning.o: $(LIBSRC)/ipf_dotuning.c $(INCDEP)
+ $(CC) $(CCARGS) -c $(LIBSRC)/ipf_dotuning.c -o $@
+$(DEST)/ipft_ef.o: $(LIBSRC)/ipft_ef.c $(INCDEP)
+ $(CC) $(CCARGS) -c $(LIBSRC)/ipft_ef.c -o $@
+$(DEST)/ipft_hx.o: $(LIBSRC)/ipft_hx.c $(INCDEP)
+ $(CC) $(CCARGS) -c $(LIBSRC)/ipft_hx.c -o $@
+$(DEST)/ipft_pc.o: $(LIBSRC)/ipft_pc.c $(INCDEP)
+ $(CC) $(CCARGS) -c $(LIBSRC)/ipft_pc.c -o $@
+$(DEST)/ipft_sn.o: $(LIBSRC)/ipft_sn.c $(TOP)/snoop.h
+ $(CC) $(CCARGS) -c $(LIBSRC)/ipft_sn.c -o $@
+$(DEST)/ipft_td.o: $(LIBSRC)/ipft_td.c $(INCDEP)
+ $(CC) $(CCARGS) -c $(LIBSRC)/ipft_td.c -o $@
+$(DEST)/ipft_tx.o: $(LIBSRC)/ipft_tx.c $(INCDEP)
+ $(CC) $(CCARGS) -c $(LIBSRC)/ipft_tx.c -o $@
+$(DEST)/kmem.o: $(LIBSRC)/kmem.c $(INCDEP)
+ $(CC) $(CCARGS) -c $(LIBSRC)/kmem.c -o $@
+$(DEST)/kmemcpywrap.o: $(LIBSRC)/kmemcpywrap.c $(INCDEP)
+ $(CC) $(CCARGS) -c $(LIBSRC)/kmemcpywrap.c -o $@
+$(DEST)/kvatoname.o: $(LIBSRC)/kvatoname.c $(INCDEP)
+ $(CC) $(CCARGS) -c $(LIBSRC)/kvatoname.c -o $@
+$(DEST)/load_hash.o: $(LIBSRC)/load_hash.c $(INCDEP) $(TOP)/ip_htable.h
+ $(CC) $(CCARGS) -c $(LIBSRC)/load_hash.c -o $@
+$(DEST)/load_hashnode.o: $(LIBSRC)/load_hashnode.c $(INCDEP) $(TOP)/ip_htable.h
+ $(CC) $(CCARGS) -c $(LIBSRC)/load_hashnode.c -o $@
+$(DEST)/load_pool.o: $(LIBSRC)/load_pool.c $(INCDEP) $(TOP)/ip_pool.h
+ $(CC) $(CCARGS) -c $(LIBSRC)/load_pool.c -o $@
+$(DEST)/load_poolnode.o: $(LIBSRC)/load_poolnode.c $(INCDEP) $(TOP)/ip_pool.h
+ $(CC) $(CCARGS) -c $(LIBSRC)/load_poolnode.c -o $@
+$(DEST)/make_range.o: $(LIBSRC)/make_range.c $(INCDEP)
+ $(CC) $(CCARGS) -c $(LIBSRC)/make_range.c -o $@
+$(DEST)/mutex_emul.o: $(LIBSRC)/mutex_emul.c $(INCDEP)
+ $(CC) $(CCARGS) -c $(LIBSRC)/mutex_emul.c -o $@
+$(DEST)/nametokva.o: $(LIBSRC)/nametokva.c $(INCDEP)
+ $(CC) $(CCARGS) -c $(LIBSRC)/nametokva.c -o $@
+$(DEST)/nat_setgroupmap.o: $(LIBSRC)/nat_setgroupmap.c $(TOP)/ip_compat.h \
+ $(TOP)/ipf.h $(TOP)/ip_nat.h
+ $(CC) $(CCARGS) -c $(LIBSRC)/nat_setgroupmap.c -o $@
+$(DEST)/ntomask.o: $(LIBSRC)/ntomask.c $(TOP)/ip_compat.h
+ $(CC) $(CCARGS) -c $(LIBSRC)/ntomask.c -o $@
+$(DEST)/loglevel.o: $(LIBSRC)/loglevel.c $(INCDEP)
+ $(CC) $(CCARGS) -c $(LIBSRC)/loglevel.c -o $@
+$(DEST)/optname.o: $(LIBSRC)/optname.c $(INCDEP)
+ $(CC) $(CCARGS) -c $(LIBSRC)/optname.c -o $@
+$(DEST)/optprint.o: $(LIBSRC)/optprint.c $(INCDEP)
+ $(CC) $(CCARGS) -c $(LIBSRC)/optprint.c -o $@
+$(DEST)/optprintv6.o: $(LIBSRC)/optprintv6.c $(INCDEP)
+ $(CC) $(CCARGS) -c $(LIBSRC)/optprintv6.c -o $@
+$(DEST)/optvalue.o: $(LIBSRC)/optvalue.c $(INCDEP)
+ $(CC) $(CCARGS) -c $(LIBSRC)/optvalue.c -o $@
+$(DEST)/portname.o: $(LIBSRC)/portname.c $(INCDEP)
+ $(CC) $(CCARGS) -c $(LIBSRC)/portname.c -o $@
+$(DEST)/portnum.o: $(LIBSRC)/portnum.c $(INCDEP)
+ $(CC) $(CCARGS) -c $(LIBSRC)/portnum.c -o $@
+$(DEST)/ports.o: $(LIBSRC)/ports.c $(INCDEP)
+ $(CC) $(CCARGS) -c $(LIBSRC)/ports.c -o $@
+$(DEST)/print_toif.o: $(LIBSRC)/print_toif.c $(INCDEP)
+ $(CC) $(CCARGS) -c $(LIBSRC)/print_toif.c -o $@
+$(DEST)/printactivenat.o: $(LIBSRC)/printactivenat.c $(INCDEP)
+ $(CC) $(CCARGS) -c $(LIBSRC)/printactivenat.c -o $@
+$(DEST)/printaps.o: $(LIBSRC)/printaps.c $(INCDEP)
+ $(CC) $(CCARGS) -c $(LIBSRC)/printaps.c -o $@
+$(DEST)/printbuf.o: $(LIBSRC)/printbuf.c $(INCDEP)
+ $(CC) $(CCARGS) -c $(LIBSRC)/printbuf.c -o $@
+$(DEST)/printfr.o: $(LIBSRC)/printfr.c $(TOP)/ip_fil.h
+ $(CC) $(CCARGS) -c $(LIBSRC)/printfr.c -o $@
+$(DEST)/printfraginfo.o: $(LIBSRC)/printfraginfo.c $(TOP)/ip_fil.h
+ $(CC) $(CCARGS) -c $(LIBSRC)/printfraginfo.c -o $@
+$(DEST)/printhash.o: $(LIBSRC)/printhash.c $(TOP)/ip_fil.h $(TOP)/ip_htable.h
+ $(CC) $(CCARGS) -c $(LIBSRC)/printhash.c -o $@
+$(DEST)/printhashnode.o: $(LIBSRC)/printhashnode.c $(TOP)/ip_fil.h \
+ $(TOP)/ip_htable.h $(TOP)/ip_lookup.h
+ $(CC) $(CCARGS) -c $(LIBSRC)/printhashnode.c -o $@
+$(DEST)/printip.o: $(LIBSRC)/printip.c $(TOP)/ip_fil.h
+ $(CC) $(CCARGS) -c $(LIBSRC)/printip.c -o $@
+$(DEST)/printpool.o: $(LIBSRC)/printpool.c $(TOP)/ip_fil.h $(TOP)/ip_pool.h
+ $(CC) $(CCARGS) -c $(LIBSRC)/printpool.c -o $@
+$(DEST)/printpoolnode.o: $(LIBSRC)/printpoolnode.c $(TOP)/ip_fil.h \
+ $(TOP)/ip_pool.h $(TOP)/ip_lookup.h
+ $(CC) $(CCARGS) -c $(LIBSRC)/printpoolnode.c -o $@
+$(DEST)/printhostmap.o: $(LIBSRC)/printhostmap.c $(TOP)/ip_fil.h
+ $(CC) $(CCARGS) -c $(LIBSRC)/printhostmap.c -o $@
+$(DEST)/printifname.o: $(LIBSRC)/printifname.c $(INCDEP)
+ $(CC) $(CCARGS) -c $(LIBSRC)/printifname.c -o $@
+$(DEST)/printmask.o: $(LIBSRC)/printmask.c $(INCDEP)
+ $(CC) $(CCARGS) -c $(LIBSRC)/printmask.c -o $@
+$(DEST)/printnat.o: $(LIBSRC)/printnat.c $(INCDEP)
+ $(CC) $(CCARGS) -c $(LIBSRC)/printnat.c -o $@
+$(DEST)/printhostmask.o: $(LIBSRC)/printhostmask.c $(INCDEP)
+ $(CC) $(CCARGS) -c $(LIBSRC)/printhostmask.c -o $@
+$(DEST)/printlog.o: $(LIBSRC)/printlog.c $(INCDEP)
+ $(CC) $(CCARGS) -c $(LIBSRC)/printlog.c -o $@
+$(DEST)/printpacket.o: $(LIBSRC)/printpacket.c $(INCDEP)
+ $(CC) $(CCARGS) -c $(LIBSRC)/printpacket.c -o $@
+$(DEST)/printpacket6.o: $(LIBSRC)/printpacket6.c $(INCDEP)
+ $(CC) $(CCARGS) -c $(LIBSRC)/printpacket6.c -o $@
+$(DEST)/printportcmp.o: $(LIBSRC)/printportcmp.c $(INCDEP)
+ $(CC) $(CCARGS) -c $(LIBSRC)/printportcmp.c -o $@
+$(DEST)/printsbuf.o: $(LIBSRC)/printsbuf.c $(INCDEP)
+ $(CC) $(CCARGS) -c $(LIBSRC)/printsbuf.c -o $@
+$(DEST)/printstate.o: $(LIBSRC)/printstate.c $(INCDEP) $(TOP)/ip_state.h
+ $(CC) $(CCARGS) -c $(LIBSRC)/printstate.c -o $@
+$(DEST)/printtunable.o: $(LIBSRC)/printtunable.c $(INCDEP)
+ $(CC) $(CCARGS) -c $(LIBSRC)/printtunable.c -o $@
+$(DEST)/ratoi.o: $(LIBSRC)/ratoi.c $(INCDEP)
+ $(CC) $(CCARGS) -c $(LIBSRC)/ratoi.c -o $@
+$(DEST)/ratoui.o: $(LIBSRC)/ratoui.c $(INCDEP)
+ $(CC) $(CCARGS) -c $(LIBSRC)/ratoui.c -o $@
+$(DEST)/remove_hash.o: $(LIBSRC)/remove_hash.c $(INCDEP) \
+ $(TOP)/ip_htable.h
+ $(CC) $(CCARGS) -c $(LIBSRC)/remove_hash.c -o $@
+$(DEST)/remove_hashnode.o: $(LIBSRC)/remove_hashnode.c $(INCDEP) \
+ $(TOP)/ip_htable.h
+ $(CC) $(CCARGS) -c $(LIBSRC)/remove_hashnode.c -o $@
+$(DEST)/remove_pool.o: $(LIBSRC)/remove_pool.c $(INCDEP) \
+ $(TOP)/ip_htable.h
+ $(CC) $(CCARGS) -c $(LIBSRC)/remove_pool.c -o $@
+$(DEST)/remove_poolnode.o: $(LIBSRC)/remove_poolnode.c $(INCDEP) \
+ $(TOP)/ip_htable.h
+ $(CC) $(CCARGS) -c $(LIBSRC)/remove_poolnode.c -o $@
+$(DEST)/resetlexer.o: $(LIBSRC)/resetlexer.c $(INCDEP)
+ $(CC) $(CCARGS) -c $(LIBSRC)/resetlexer.c -o $@
+$(DEST)/rwlock_emul.o: $(LIBSRC)/rwlock_emul.c $(INCDEP)
+ $(CC) $(CCARGS) -c $(LIBSRC)/rwlock_emul.c -o $@
+$(DEST)/to_interface.o: $(LIBSRC)/to_interface.c $(INCDEP)
+ $(CC) $(CCARGS) -c $(LIBSRC)/to_interface.c -o $@
+$(DEST)/tcpflags.o: $(LIBSRC)/tcpflags.c $(INCDEP)
+ $(CC) $(CCARGS) -c $(LIBSRC)/tcpflags.c -o $@
+$(DEST)/tcp_flags.o: $(LIBSRC)/tcp_flags.c $(INCDEP)
+ $(CC) $(CCARGS) -c $(LIBSRC)/tcp_flags.c -o $@
+$(DEST)/var.o: $(LIBSRC)/var.c $(INCDEP)
+ $(CC) $(CCARGS) -c $(LIBSRC)/var.c -o $@
+$(DEST)/verbose.o: $(LIBSRC)/verbose.c $(INCDEP)
+ $(CC) $(CCARGS) -c $(LIBSRC)/verbose.c -o $@
+$(DEST)/v6ionames.o: $(LIBSRC)/v6ionames.c $(INCDEP)
+ $(CC) $(CCARGS) -c $(LIBSRC)/v6ionames.c -o $@
+$(DEST)/v6optvalue.o: $(LIBSRC)/v6optvalue.c $(INCDEP)
+ $(CC) $(CCARGS) -c $(LIBSRC)/v6optvalue.c -o $@
+
+clean-lib:
+ /bin/rm -f ${LIBOBJS} ${LIB}
diff --git a/contrib/ipfilter/lib/addicmp.c b/contrib/ipfilter/lib/addicmp.c
new file mode 100644
index 0000000..a8c1722
--- /dev/null
+++ b/contrib/ipfilter/lib/addicmp.c
@@ -0,0 +1,94 @@
+/* $NetBSD$ */
+
+/*
+ * Copyright (C) 1993-2001 by Darren Reed.
+ *
+ * See the IPFILTER.LICENCE file for details on licencing.
+ *
+ * Id: addicmp.c,v 1.10.2.1 2004/12/09 19:41:16 darrenr Exp
+ */
+
+#include <ctype.h>
+
+#include "ipf.h"
+
+
+char *icmptypes[MAX_ICMPTYPE + 1] = {
+ "echorep", (char *)NULL, (char *)NULL, "unreach", "squench",
+ "redir", (char *)NULL, (char *)NULL, "echo", "routerad",
+ "routersol", "timex", "paramprob", "timest", "timestrep",
+ "inforeq", "inforep", "maskreq", "maskrep", "END"
+};
+
+/*
+ * set the icmp field to the correct type if "icmp" word is found
+ */
+int addicmp(cp, fp, linenum)
+char ***cp;
+struct frentry *fp;
+int linenum;
+{
+ char **t;
+ int i;
+
+ (*cp)++;
+ if (!**cp)
+ return -1;
+ if (!fp->fr_proto) /* to catch lusers */
+ fp->fr_proto = IPPROTO_ICMP;
+ if (ISDIGIT(***cp)) {
+ if (!ratoi(**cp, &i, 0, 255)) {
+ fprintf(stderr,
+ "%d: Invalid icmp-type (%s) specified\n",
+ linenum, **cp);
+ return -1;
+ }
+ } else {
+ for (t = icmptypes, i = 0; ; t++, i++) {
+ if (!*t)
+ continue;
+ if (!strcasecmp("END", *t)) {
+ i = -1;
+ break;
+ }
+ if (!strcasecmp(*t, **cp))
+ break;
+ }
+ if (i == -1) {
+ fprintf(stderr,
+ "%d: Unknown icmp-type (%s) specified\n",
+ linenum, **cp);
+ return -1;
+ }
+ }
+ fp->fr_icmp = (u_short)(i << 8);
+ fp->fr_icmpm = (u_short)0xff00;
+ (*cp)++;
+ if (!**cp)
+ return 0;
+
+ if (**cp && strcasecmp("code", **cp))
+ return 0;
+ (*cp)++;
+ if (ISDIGIT(***cp)) {
+ if (!ratoi(**cp, &i, 0, 255)) {
+ fprintf(stderr,
+ "%d: Invalid icmp code (%s) specified\n",
+ linenum, **cp);
+ return -1;
+ }
+ } else {
+ i = icmpcode(**cp);
+ if (i == -1) {
+ fprintf(stderr,
+ "%d: Unknown icmp code (%s) specified\n",
+ linenum, **cp);
+ return -1;
+ }
+ }
+ i &= 0xff;
+ fp->fr_icmp |= (u_short)i;
+ fp->fr_icmpm = (u_short)0xffff;
+ (*cp)++;
+ return 0;
+}
diff --git a/contrib/ipfilter/lib/addipopt.c b/contrib/ipfilter/lib/addipopt.c
new file mode 100644
index 0000000..23f4427
--- /dev/null
+++ b/contrib/ipfilter/lib/addipopt.c
@@ -0,0 +1,67 @@
+/* $NetBSD$ */
+
+/*
+ * Copyright (C) 1993-2001 by Darren Reed.
+ *
+ * See the IPFILTER.LICENCE file for details on licencing.
+ *
+ * Id: addipopt.c,v 1.7 2002/01/28 06:50:45 darrenr Exp
+ */
+
+#include "ipf.h"
+
+
+int addipopt(op, io, len, class)
+char *op;
+struct ipopt_names *io;
+int len;
+char *class;
+{
+ int olen = len;
+ struct in_addr ipadr;
+ u_short val;
+ u_char lvl;
+ char *s;
+
+ 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) {
+ s = op;
+ *op++ = io->on_siz;
+ *op++ = IPOPT_MINOFF;
+
+ if (class) {
+ switch (io->on_value)
+ {
+ case IPOPT_SECURITY :
+ lvl = seclevel(class);
+ *(op - 1) = lvl;
+ break;
+ case IPOPT_LSRR :
+ case IPOPT_SSRR :
+ ipadr.s_addr = inet_addr(class);
+ s[IPOPT_OLEN] = IPOPT_MINOFF - 1 + 4;
+ bcopy((char *)&ipadr, op, sizeof(ipadr));
+ break;
+ case IPOPT_SATID :
+ val = atoi(class);
+ bcopy((char *)&val, op, 2);
+ break;
+ }
+ }
+
+ op += io->on_siz - 3;
+ if (len & 3) {
+ *op++ = IPOPT_NOP;
+ len++;
+ }
+ }
+ if (opts & OPT_DEBUG)
+ fprintf(stderr, "bo: %s %d %#x: %d\n",
+ io->on_name, io->on_value, io->on_bit, len);
+ return len - olen;
+}
diff --git a/contrib/ipfilter/lib/addkeep.c b/contrib/ipfilter/lib/addkeep.c
new file mode 100644
index 0000000..3f20fb4
--- /dev/null
+++ b/contrib/ipfilter/lib/addkeep.c
@@ -0,0 +1,86 @@
+/* $NetBSD$ */
+
+/*
+ * Copyright (C) 1993-2001 by Darren Reed.
+ *
+ * See the IPFILTER.LICENCE file for details on licencing.
+ *
+ * Id: addkeep.c,v 1.12 2003/12/01 01:59:42 darrenr Exp
+ */
+
+#include "ipf.h"
+
+
+/*
+ * Parses "keep state" and "keep frags" stuff on the end of a line.
+ */
+int addkeep(cp, fp, linenum)
+char ***cp;
+struct frentry *fp;
+int linenum;
+{
+ char *s;
+
+ (*cp)++;
+ if (!**cp) {
+ fprintf(stderr, "%d: Missing state/frag after keep\n",
+ linenum);
+ return -1;
+ }
+
+ if (!strcasecmp(**cp, "state")) {
+ fp->fr_flags |= FR_KEEPSTATE;
+ (*cp)++;
+ if (**cp && !strcasecmp(**cp, "limit")) {
+ (*cp)++;
+ fp->fr_statemax = atoi(**cp);
+ (*cp)++;
+ }
+ if (**cp && !strcasecmp(**cp, "scan")) {
+ (*cp)++;
+ if (!strcmp(**cp, "*")) {
+ fp->fr_isc = NULL;
+ fp->fr_isctag[0] = '\0';
+ } else {
+ strncpy(fp->fr_isctag, **cp,
+ sizeof(fp->fr_isctag));
+ fp->fr_isctag[sizeof(fp->fr_isctag)-1] = '\0';
+ fp->fr_isc = NULL;
+ }
+ (*cp)++;
+ } else
+ fp->fr_isc = (struct ipscan *)-1;
+ } else if (!strncasecmp(**cp, "frag", 4)) {
+ fp->fr_flags |= FR_KEEPFRAG;
+ (*cp)++;
+ } else if (!strcasecmp(**cp, "state-age")) {
+ if (fp->fr_ip.fi_p == IPPROTO_TCP) {
+ fprintf(stderr, "%d: cannot use state-age with tcp\n",
+ linenum);
+ return -1;
+ }
+ if ((fp->fr_flags & FR_KEEPSTATE) == 0) {
+ fprintf(stderr, "%d: state-age with no 'keep state'\n",
+ linenum);
+ return -1;
+ }
+ (*cp)++;
+ if (!**cp) {
+ fprintf(stderr, "%d: state-age with no arg\n",
+ linenum);
+ return -1;
+ }
+ fp->fr_age[0] = atoi(**cp);
+ s = strchr(**cp, '/');
+ if (s != NULL) {
+ s++;
+ fp->fr_age[1] = atoi(s);
+ } else
+ fp->fr_age[1] = fp->fr_age[0];
+ } else {
+ fprintf(stderr, "%d: Unrecognised state keyword \"%s\"\n",
+ linenum, **cp);
+ return -1;
+ }
+ return 0;
+}
diff --git a/contrib/ipfilter/lib/bcopywrap.c b/contrib/ipfilter/lib/bcopywrap.c
new file mode 100644
index 0000000..939137b
--- /dev/null
+++ b/contrib/ipfilter/lib/bcopywrap.c
@@ -0,0 +1,12 @@
+/* $NetBSD$ */
+
+#include "ipf.h"
+
+int bcopywrap(from, to, size)
+void *from, *to;
+size_t size;
+{
+ bcopy((caddr_t)from, (caddr_t)to, size);
+ return 0;
+}
+
diff --git a/contrib/ipfilter/lib/binprint.c b/contrib/ipfilter/lib/binprint.c
new file mode 100644
index 0000000..afa4910
--- /dev/null
+++ b/contrib/ipfilter/lib/binprint.c
@@ -0,0 +1,31 @@
+/* $NetBSD$ */
+
+/*
+ * Copyright (C) 1993-2001 by Darren Reed.
+ *
+ * See the IPFILTER.LICENCE file for details on licencing.
+ *
+ * Id: binprint.c,v 1.8 2002/05/14 15:18:56 darrenr Exp
+ */
+
+#include "ipf.h"
+
+
+void binprint(ptr, size)
+void *ptr;
+size_t size;
+{
+ u_char *s;
+ int i, j;
+
+ for (i = size, j = 0, s = (u_char *)ptr; i; i--, s++) {
+ j++;
+ printf("%02x ", *s);
+ if (j == 16) {
+ printf("\n");
+ j = 0;
+ }
+ }
+ putchar('\n');
+ (void)fflush(stdout);
+}
diff --git a/contrib/ipfilter/lib/buildopts.c b/contrib/ipfilter/lib/buildopts.c
new file mode 100644
index 0000000..a35649b
--- /dev/null
+++ b/contrib/ipfilter/lib/buildopts.c
@@ -0,0 +1,44 @@
+/* $NetBSD$ */
+
+/*
+ * Copyright (C) 1993-2001 by Darren Reed.
+ *
+ * See the IPFILTER.LICENCE file for details on licencing.
+ *
+ * Id: buildopts.c,v 1.6 2002/01/28 06:50:45 darrenr Exp
+ */
+
+#include "ipf.h"
+
+
+u_32_t buildopts(cp, op, len)
+char *cp, *op;
+int len;
+{
+ struct ipopt_names *io;
+ u_32_t msk = 0;
+ char *s, *t;
+ int inc;
+
+ 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 ((inc = addipopt(op, io, len, t))) {
+ op += inc;
+ len += inc;
+ }
+ 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/lib/checkrev.c b/contrib/ipfilter/lib/checkrev.c
new file mode 100644
index 0000000..28032ce
--- /dev/null
+++ b/contrib/ipfilter/lib/checkrev.c
@@ -0,0 +1,46 @@
+/* $NetBSD$ */
+
+/*
+ * Copyright (C) 1993-2001 by Darren Reed.
+ *
+ * See the IPFILTER.LICENCE file for details on licencing.
+ *
+ * Id: checkrev.c,v 1.12.2.1 2004/03/09 14:44:39 darrenr Exp
+ */
+
+#include <sys/ioctl.h>
+#include <fcntl.h>
+
+#include "ipf.h"
+#include "netinet/ipl.h"
+
+int checkrev(ipfname)
+char *ipfname;
+{
+ static int vfd = -1;
+ struct friostat fio, *fiop = &fio;
+ ipfobj_t ipfo;
+
+ bzero((caddr_t)&ipfo, sizeof(ipfo));
+ ipfo.ipfo_rev = IPFILTER_VERSION;
+ ipfo.ipfo_size = sizeof(*fiop);
+ ipfo.ipfo_ptr = (void *)fiop;
+ ipfo.ipfo_type = IPFOBJ_IPFSTAT;
+
+ if ((vfd == -1) && ((vfd = open(ipfname, O_RDONLY)) == -1)) {
+ perror("open device");
+ return -1;
+ }
+
+ if (ioctl(vfd, SIOCGETFS, &ipfo)) {
+ perror("ioctl(SIOCGETFS)");
+ close(vfd);
+ vfd = -1;
+ return -1;
+ }
+
+ if (strncmp(IPL_VERSION, fio.f_version, sizeof(fio.f_version))) {
+ return -1;
+ }
+ return 0;
+}
diff --git a/contrib/ipfilter/lib/count4bits.c b/contrib/ipfilter/lib/count4bits.c
new file mode 100644
index 0000000..0f2187f
--- /dev/null
+++ b/contrib/ipfilter/lib/count4bits.c
@@ -0,0 +1,40 @@
+/* $NetBSD$ */
+
+/*
+ * Copyright (C) 1993-2001 by Darren Reed.
+ *
+ * See the IPFILTER.LICENCE file for details on licencing.
+ *
+ * Id: count4bits.c,v 1.1 2002/06/15 04:46:39 darrenr Exp
+ */
+
+#include "ipf.h"
+
+
+/*
+ * 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 count4bits(ip)
+u_int ip;
+{
+ int cnt = 0, i, j;
+ u_int ipn;
+
+ 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;
+}
diff --git a/contrib/ipfilter/lib/count6bits.c b/contrib/ipfilter/lib/count6bits.c
new file mode 100644
index 0000000..bd4e9f8
--- /dev/null
+++ b/contrib/ipfilter/lib/count6bits.c
@@ -0,0 +1,29 @@
+/* $NetBSD$ */
+
+/*
+ * Copyright (C) 1993-2001 by Darren Reed.
+ *
+ * See the IPFILTER.LICENCE file for details on licencing.
+ *
+ * Id: count6bits.c,v 1.4 2001/06/09 17:09:23 darrenr Exp
+ */
+
+#include "ipf.h"
+
+
+int count6bits(msk)
+u_32_t *msk;
+{
+ int i = 0, k;
+ u_32_t j;
+
+ for (k = 3; k >= 0; k--)
+ if (msk[k] == 0xffffffff)
+ i += 32;
+ else {
+ for (j = msk[k]; j; j <<= 1)
+ if (j & 0x80000000)
+ i++;
+ }
+ return i;
+}
diff --git a/contrib/ipfilter/lib/debug.c b/contrib/ipfilter/lib/debug.c
new file mode 100644
index 0000000..1510222
--- /dev/null
+++ b/contrib/ipfilter/lib/debug.c
@@ -0,0 +1,37 @@
+/* $NetBSD$ */
+
+/*
+ * Copyright (C) 1993-2001 by Darren Reed.
+ *
+ * See the IPFILTER.LICENCE file for details on licencing.
+ *
+ * Id: debug.c,v 1.6 2001/06/09 17:09:24 darrenr Exp
+ */
+
+#if defined(__STDC__)
+# include <stdarg.h>
+#else
+# include <varargs.h>
+#endif
+#include <stdio.h>
+
+#include "ipt.h"
+#include "opts.h"
+
+
+#ifdef __STDC__
+void debug(char *fmt, ...)
+#else
+void debug(fmt, va_alist)
+char *fmt;
+va_dcl
+#endif
+{
+ va_list pvar;
+
+ va_start(pvar, fmt);
+
+ if (opts & OPT_DEBUG)
+ vprintf(fmt, pvar);
+ va_end(pvar);
+}
diff --git a/contrib/ipfilter/lib/extras.c b/contrib/ipfilter/lib/extras.c
new file mode 100644
index 0000000..0f7f39f
--- /dev/null
+++ b/contrib/ipfilter/lib/extras.c
@@ -0,0 +1,114 @@
+/* $NetBSD$ */
+
+/*
+ * Copyright (C) 1993-2001 by Darren Reed.
+ *
+ * See the IPFILTER.LICENCE file for details on licencing.
+ *
+ * Id: extras.c,v 1.12 2002/07/13 12:06:49 darrenr Exp
+ */
+
+#include "ipf.h"
+
+
+/*
+ * deal with extra bits on end of the line
+ */
+int extras(cp, fr, linenum)
+char ***cp;
+struct frentry *fr;
+int linenum;
+{
+ u_short secmsk;
+ u_long opts;
+ int notopt;
+
+ opts = 0;
+ secmsk = 0;
+ notopt = 0;
+ (*cp)++;
+ if (!**cp)
+ return -1;
+
+ while (**cp) {
+ if (!strcasecmp(**cp, "not") || !strcasecmp(**cp, "no")) {
+ notopt = 1;
+ (*cp)++;
+ continue;
+ } else if (!strncasecmp(**cp, "ipopt", 5)) {
+ if (!notopt)
+ fr->fr_flx |= FI_OPTIONS;
+ fr->fr_mflx |= FI_OPTIONS;
+ goto nextopt;
+ } else if (!strcasecmp(**cp, "lowttl")) {
+ if (!notopt)
+ fr->fr_flx |= FI_LOWTTL;
+ fr->fr_mflx |= FI_LOWTTL;
+ goto nextopt;
+ } else if (!strcasecmp(**cp, "bad-src")) {
+ if (!notopt)
+ fr->fr_flx |= FI_BADSRC;
+ fr->fr_mflx |= FI_BADSRC;
+ goto nextopt;
+ } else if (!strncasecmp(**cp, "mbcast", 6)) {
+ if (!notopt)
+ fr->fr_flx |= FI_MBCAST;
+ fr->fr_mflx |= FI_MBCAST;
+ goto nextopt;
+ } else if (!strncasecmp(**cp, "nat", 3)) {
+ if (!notopt)
+ fr->fr_flx |= FI_NATED;
+ fr->fr_mflx |= FI_NATED;
+ goto nextopt;
+ } else if (!strncasecmp(**cp, "frag", 4)) {
+ if (!notopt)
+ fr->fr_flx |= FI_FRAG;
+ fr->fr_mflx |= FI_FRAG;
+ goto nextopt;
+ } else if (!strncasecmp(**cp, "opt", 3)) {
+ if (!*(*cp + 1)) {
+ fprintf(stderr, "%d: opt missing arguements\n",
+ linenum);
+ return -1;
+ }
+ (*cp)++;
+ if (!(opts = optname(cp, &secmsk, linenum)))
+ return -1;
+
+ if (notopt) {
+ if (!secmsk) {
+ fr->fr_optmask |= opts;
+ } else {
+ fr->fr_optmask |= (opts & ~0x0100);
+ fr->fr_secmask |= secmsk;
+ }
+ fr->fr_secbits &= ~secmsk;
+ fr->fr_optbits &= ~opts;
+ } else {
+ fr->fr_optmask |= opts;
+ fr->fr_secmask |= secmsk;
+ fr->fr_optbits |= opts;
+ fr->fr_secbits |= secmsk;
+ }
+ } else if (!strncasecmp(**cp, "short", 5)) {
+ if (fr->fr_tcpf) {
+ fprintf(stderr,
+ "%d: short cannot be used with TCP flags\n",
+ linenum);
+ return -1;
+ }
+
+ if (!notopt)
+ fr->fr_flx |= FI_SHORT;
+ fr->fr_mflx |= FI_SHORT;
+ goto nextopt;
+ } else
+ return -1;
+nextopt:
+ notopt = 0;
+ opts = 0;
+ secmsk = 0;
+ (*cp)++;
+ }
+ return 0;
+}
diff --git a/contrib/ipfilter/lib/facpri.c b/contrib/ipfilter/lib/facpri.c
new file mode 100644
index 0000000..1e35ea9
--- /dev/null
+++ b/contrib/ipfilter/lib/facpri.c
@@ -0,0 +1,153 @@
+/* $NetBSD$ */
+
+/*
+ * Copyright (C) 1993-2001 by Darren Reed.
+ *
+ * See the IPFILTER.LICENCE file for details on licencing.
+ *
+ * Id: facpri.c,v 1.6 2003/12/01 01:59:43 darrenr Exp
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <limits.h>
+#include <sys/types.h>
+#if !defined(__SVR4) && !defined(__svr4__)
+#include <strings.h>
+#endif
+#include <stdlib.h>
+#include <unistd.h>
+#include <stddef.h>
+#include <syslog.h>
+#include "facpri.h"
+
+#if !defined(lint)
+static const char rcsid[] = "@(#)Id: facpri.c,v 1.6 2003/12/01 01:59:43 darrenr Exp";
+#endif
+
+
+typedef struct table {
+ char *name;
+ int value;
+} table_t;
+
+table_t facs[] = {
+ { "kern", LOG_KERN }, { "user", LOG_USER },
+ { "mail", LOG_MAIL }, { "daemon", LOG_DAEMON },
+ { "auth", LOG_AUTH }, { "syslog", LOG_SYSLOG },
+ { "lpr", LOG_LPR }, { "news", LOG_NEWS },
+ { "uucp", LOG_UUCP },
+#if LOG_CRON == LOG_CRON2
+ { "cron2", LOG_CRON1 },
+#else
+ { "cron", LOG_CRON1 },
+#endif
+#ifdef LOG_FTP
+ { "ftp", LOG_FTP },
+#endif
+#ifdef LOG_AUTHPRIV
+ { "authpriv", LOG_AUTHPRIV },
+#endif
+#ifdef LOG_AUDIT
+ { "audit", LOG_AUDIT },
+#endif
+#ifdef LOG_LFMT
+ { "logalert", LOG_LFMT },
+#endif
+#if LOG_CRON == LOG_CRON1
+ { "cron", LOG_CRON2 },
+#else
+ { "cron2", LOG_CRON2 },
+#endif
+#ifdef LOG_SECURITY
+ { "security", LOG_SECURITY },
+#endif
+ { "local0", LOG_LOCAL0 }, { "local1", LOG_LOCAL1 },
+ { "local2", LOG_LOCAL2 }, { "local3", LOG_LOCAL3 },
+ { "local4", LOG_LOCAL4 }, { "local5", LOG_LOCAL5 },
+ { "local6", LOG_LOCAL6 }, { "local7", LOG_LOCAL7 },
+ { NULL, 0 }
+};
+
+
+/*
+ * map a facility number to its name
+ */
+char *
+fac_toname(facpri)
+ int facpri;
+{
+ int i, j, fac;
+
+ fac = facpri & LOG_FACMASK;
+ j = fac >> 3;
+ if (j < 24) {
+ if (facs[j].value == fac)
+ return facs[j].name;
+ for (i = 0; facs[i].name; i++)
+ if (fac == facs[i].value)
+ return facs[i].name;
+ }
+
+ return NULL;
+}
+
+
+/*
+ * map a facility name to its number
+ */
+int
+fac_findname(name)
+ char *name;
+{
+ int i;
+
+ for (i = 0; facs[i].name; i++)
+ if (!strcmp(facs[i].name, name))
+ return facs[i].value;
+ return -1;
+}
+
+
+table_t pris[] = {
+ { "emerg", LOG_EMERG }, { "alert", LOG_ALERT },
+ { "crit", LOG_CRIT }, { "err", LOG_ERR },
+ { "warn", LOG_WARNING }, { "notice", LOG_NOTICE },
+ { "info", LOG_INFO }, { "debug", LOG_DEBUG },
+ { NULL, 0 }
+};
+
+
+/*
+ * map a priority name to its number
+ */
+int
+pri_findname(name)
+ char *name;
+{
+ int i;
+
+ for (i = 0; pris[i].name; i++)
+ if (!strcmp(pris[i].name, name))
+ return pris[i].value;
+ return -1;
+}
+
+
+/*
+ * map a priority number to its name
+ */
+char *
+pri_toname(facpri)
+ int facpri;
+{
+ int i, pri;
+
+ pri = facpri & LOG_PRIMASK;
+ if (pris[pri].value == pri)
+ return pris[pri].name;
+ for (i = 0; pris[i].name; i++)
+ if (pri == pris[i].value)
+ return pris[i].name;
+ return NULL;
+}
diff --git a/contrib/ipfilter/lib/facpri.h b/contrib/ipfilter/lib/facpri.h
new file mode 100644
index 0000000..e8eef2b
--- /dev/null
+++ b/contrib/ipfilter/lib/facpri.h
@@ -0,0 +1,43 @@
+/* $NetBSD$ */
+
+/*
+ * Copyright (C) 1999-2001 by Darren Reed.
+ *
+ * See the IPFILTER.LICENCE file for details on licencing.
+ *
+ * Id: facpri.h,v 1.3 2001/06/09 17:19:50 darrenr Exp
+ */
+
+#ifndef __FACPRI_H__
+#define __FACPRI_H__
+
+#ifndef __P
+# define P_DEF
+# ifdef __STDC__
+# define __P(x) x
+# else
+# define __P(x) ()
+# endif
+#endif
+
+extern char *fac_toname __P((int));
+extern int fac_findname __P((char *));
+
+extern char *pri_toname __P((int));
+extern int pri_findname __P((char *));
+
+#ifdef P_DEF
+# undef __P
+# undef P_DEF
+#endif
+
+#if LOG_CRON == (9<<3)
+# define LOG_CRON1 LOG_CRON
+# define LOG_CRON2 (15<<3)
+#endif
+#if LOG_CRON == (15<<3)
+# define LOG_CRON1 (9<<3)
+# define LOG_CRON2 LOG_CRON
+#endif
+
+#endif /* __FACPRI_H__ */
diff --git a/contrib/ipfilter/lib/fill6bits.c b/contrib/ipfilter/lib/fill6bits.c
new file mode 100644
index 0000000..8f23a6f
--- /dev/null
+++ b/contrib/ipfilter/lib/fill6bits.c
@@ -0,0 +1,48 @@
+/* $NetBSD$ */
+
+/*
+ * Copyright (C) 1993-2001 by Darren Reed.
+ *
+ * See the IPFILTER.LICENCE file for details on licencing.
+ *
+ * Id: fill6bits.c,v 1.5 2002/03/27 15:09:57 darrenr Exp
+ */
+
+#include "ipf.h"
+
+
+void fill6bits(bits, msk)
+int bits;
+u_int *msk;
+{
+ if (bits == 0) {
+ msk[0] = 0;
+ msk[1] = 0;
+ msk[2] = 0;
+ msk[3] = 0;
+ return;
+ }
+
+ msk[0] = 0xffffffff;
+ msk[1] = 0xffffffff;
+ msk[2] = 0xffffffff;
+ msk[3] = 0xffffffff;
+
+ if (bits == 128)
+ return;
+ if (bits > 96) {
+ msk[3] = htonl(msk[3] << (128 - bits));
+ } else if (bits > 64) {
+ msk[3] = 0;
+ msk[2] = htonl(msk[2] << (96 - bits));
+ } else if (bits > 32) {
+ msk[3] = 0;
+ msk[2] = 0;
+ msk[1] = htonl(msk[1] << (64 - bits));
+ } else {
+ msk[3] = 0;
+ msk[2] = 0;
+ msk[1] = 0;
+ msk[0] = htonl(msk[0] << (32 - bits));
+ }
+}
diff --git a/contrib/ipfilter/lib/flags.c b/contrib/ipfilter/lib/flags.c
new file mode 100644
index 0000000..df6645d
--- /dev/null
+++ b/contrib/ipfilter/lib/flags.c
@@ -0,0 +1,25 @@
+/* $NetBSD$ */
+
+/*
+ * Copyright (C) 1993-2001 by Darren Reed.
+ *
+ * See the IPFILTER.LICENCE file for details on licencing.
+ *
+ * Id: flags.c,v 1.4 2002/11/02 07:16:36 darrenr Exp
+ */
+
+#include "ipf.h"
+
+/*
+ * ECN is a new addition to TCP - RFC 2481
+ */
+#ifndef TH_ECN
+# define TH_ECN 0x40
+#endif
+#ifndef TH_CWR
+# define TH_CWR 0x80
+#endif
+
+char flagset[] = "FSRPAUEC";
+u_char flags[] = { TH_FIN, TH_SYN, TH_RST, TH_PUSH, TH_ACK, TH_URG,
+ TH_ECN, TH_CWR };
diff --git a/contrib/ipfilter/lib/genmask.c b/contrib/ipfilter/lib/genmask.c
new file mode 100644
index 0000000..06f6404
--- /dev/null
+++ b/contrib/ipfilter/lib/genmask.c
@@ -0,0 +1,56 @@
+/* $NetBSD$ */
+
+/*
+ * Copyright (C) 1993-2001 by Darren Reed.
+ *
+ * See the IPFILTER.LICENCE file for details on licencing.
+ *
+ * Id: genmask.c,v 1.7 2003/11/11 13:40:15 darrenr Exp
+ */
+
+#include "ipf.h"
+
+
+int genmask(msk, mskp)
+char *msk;
+u_32_t *mskp;
+{
+ char *endptr = 0L;
+ int bits;
+
+ if (strchr(msk, '.') || strchr(msk, 'x') || strchr(msk, ':')) {
+ /* possibly of the form xxx.xxx.xxx.xxx
+ * or 0xYYYYYYYY */
+#ifdef USE_INET6
+ if (use_inet6) {
+ if (inet_pton(AF_INET6, msk, mskp) != 1)
+ return -1;
+ } else
+#endif
+ if (inet_aton(msk, (struct in_addr *)mskp) == 0)
+ return -1;
+ } else {
+ /*
+ * set x most significant bits
+ */
+ bits = (int)strtol(msk, &endptr, 0);
+#ifdef USE_INET6
+ if ((*endptr != '\0') ||
+ ((bits > 32) && !use_inet6) || (bits < 0) ||
+ ((bits > 128) && use_inet6))
+#else
+ if (*endptr != '\0' || bits > 32 || bits < 0)
+#endif
+ return -1;
+#ifdef USE_INET6
+ if (use_inet6)
+ fill6bits(bits, mskp);
+ else
+#endif
+ if (bits == 0)
+ *mskp = 0;
+ else
+ *mskp = htonl(0xffffffff << (32 - bits));
+ }
+ return 0;
+}
diff --git a/contrib/ipfilter/lib/gethost.c b/contrib/ipfilter/lib/gethost.c
new file mode 100644
index 0000000..a03168a
--- /dev/null
+++ b/contrib/ipfilter/lib/gethost.c
@@ -0,0 +1,36 @@
+/* $NetBSD$ */
+
+#include "ipf.h"
+
+int gethost(name, hostp)
+char *name;
+u_32_t *hostp;
+{
+ struct hostent *h;
+ struct netent *n;
+ u_32_t addr;
+
+ if (!strcmp(name, "test.host.dots")) {
+ *hostp = htonl(0xfedcba98);
+ return 0;
+ }
+
+ if (!strcmp(name, "<thishost>"))
+ name = thishost;
+
+ h = gethostbyname(name);
+ if (h != NULL) {
+ if ((h->h_addr != NULL) && (h->h_length == sizeof(addr))) {
+ bcopy(h->h_addr, (char *)&addr, sizeof(addr));
+ *hostp = addr;
+ return 0;
+ }
+ }
+
+ n = getnetbyname(name);
+ if (n != NULL) {
+ *hostp = (u_32_t)htonl(n->n_net & 0xffffffff);
+ return 0;
+ }
+ return -1;
+}
diff --git a/contrib/ipfilter/lib/getifname.c b/contrib/ipfilter/lib/getifname.c
new file mode 100644
index 0000000..94c9c9c
--- /dev/null
+++ b/contrib/ipfilter/lib/getifname.c
@@ -0,0 +1,76 @@
+/* $NetBSD$ */
+
+#include "ipf.h"
+
+#include "kmem.h"
+
+/*
+ * Given a pointer to an interface in the kernel, return a pointer to a
+ * string which is the interface name.
+ */
+char *getifname(ptr)
+struct ifnet *ptr;
+{
+#if SOLARIS || defined(__hpux)
+# if SOLARIS
+# include <sys/mutex.h>
+# include <sys/condvar.h>
+# endif
+# ifdef __hpux
+# include "compat.h"
+# endif
+# include "../pfil/qif.h"
+ char *ifname;
+ qif_t qif;
+
+ if ((void *)ptr == (void *)-1)
+ return "!";
+ if (ptr == NULL)
+ return "-";
+
+ if (kmemcpy((char *)&qif, (u_long)ptr, sizeof(qif)) == -1)
+ return "X";
+ ifname = strdup(qif.qf_name);
+ if ((ifname != NULL) && (*ifname == '\0')) {
+ free(ifname);
+ return "!";
+ }
+ return ifname;
+#else
+# if defined(NetBSD) && (NetBSD >= 199905) && (NetBSD < 1991011) || \
+ defined(__OpenBSD__) || \
+ (defined(__FreeBSD__) && (__FreeBSD_version >= 501113))
+#else
+ char buf[32];
+ int len;
+# endif
+ struct ifnet netif;
+
+ if ((void *)ptr == (void *)-1)
+ return "!";
+ if (ptr == NULL)
+ return "-";
+
+ if (kmemcpy((char *)&netif, (u_long)ptr, sizeof(netif)) == -1)
+ return "X";
+# if defined(NetBSD) && (NetBSD >= 199905) && (NetBSD < 1991011) || \
+ defined(__OpenBSD__) || defined(linux) || \
+ (defined(__FreeBSD__) && (__FreeBSD_version >= 501113))
+ return strdup(netif.if_xname);
+# else
+ if (kstrncpy(buf, (u_long)netif.if_name, sizeof(buf)) == -1)
+ return "X";
+ if (netif.if_unit < 10)
+ len = 2;
+ else if (netif.if_unit < 1000)
+ len = 3;
+ else if (netif.if_unit < 10000)
+ len = 4;
+ else
+ len = 5;
+ buf[sizeof(buf) - len] = '\0';
+ sprintf(buf + strlen(buf), "%d", netif.if_unit % 10000);
+ return strdup(buf);
+# endif
+#endif
+}
diff --git a/contrib/ipfilter/lib/getline.c b/contrib/ipfilter/lib/getline.c
new file mode 100644
index 0000000..61c00ba
--- /dev/null
+++ b/contrib/ipfilter/lib/getline.c
@@ -0,0 +1,58 @@
+/* $NetBSD$ */
+
+/*
+ * Copyright (C) 1993-2001 by Darren Reed.
+ *
+ * See the IPFILTER.LICENCE file for details on licencing.
+ *
+ * Id: getline.c,v 1.3 2001/06/09 17:09:24 darrenr Exp
+ */
+
+#include <stdio.h>
+#if !defined(__SVR4) && !defined(__GNUC__)
+#include <strings.h>
+#endif
+#include <string.h>
+#include "ipf.h"
+
+
+/*
+ * Similar to fgets(3) but can handle '\\' and NL is converted to NUL.
+ * Returns NULL if error occured, EOF encounterd or input line is too long.
+ */
+char *getline(str, size, file, linenum)
+register char *str;
+size_t size;
+FILE *file;
+int *linenum;
+{
+ char *p;
+ int s, len;
+
+ do {
+ for (p = str, s = size;; p += (len - 1), s -= (len - 1)) {
+ /*
+ * if an error occured, EOF was encounterd, or there
+ * was no room to put NUL, return NULL.
+ */
+ if (fgets(p, s, file) == NULL)
+ return (NULL);
+ len = strlen(p);
+ if (p[len - 1] != '\n') {
+ p[len] = '\0';
+ break;
+ }
+ (*linenum)++;
+ p[len - 1] = '\0';
+ if (len < 2 || p[len - 2] != '\\')
+ break;
+ else
+ /*
+ * Convert '\\' to a space so words don't
+ * run together
+ */
+ p[len - 2] = ' ';
+ }
+ } while (*str == '\0');
+ return (str);
+}
diff --git a/contrib/ipfilter/lib/getnattype.c b/contrib/ipfilter/lib/getnattype.c
new file mode 100644
index 0000000..c783d6f
--- /dev/null
+++ b/contrib/ipfilter/lib/getnattype.c
@@ -0,0 +1,54 @@
+/* $NetBSD$ */
+
+/*
+ * Copyright (C) 1993-2001 by Darren Reed.
+ *
+ * See the IPFILTER.LICENCE file for details on licencing.
+ *
+ * Added redirect stuff and a variety of bug fixes. (mcn@EnGarde.com)
+ */
+#include "ipf.h"
+#include "kmem.h"
+
+#if !defined(lint)
+static const char rcsid[] = "@(#)Id: getnattype.c,v 1.3 2004/01/17 17:26:07 darrenr Exp";
+#endif
+
+
+/*
+ * Get a nat filter type given its kernel address.
+ */
+char *getnattype(ipnat)
+ipnat_t *ipnat;
+{
+ static char unknownbuf[20];
+ ipnat_t ipnatbuff;
+ char *which;
+
+ if (!ipnat)
+ return "???";
+ if (kmemcpy((char *)&ipnatbuff, (long)ipnat, sizeof(ipnatbuff)))
+ return "!!!";
+
+ switch (ipnatbuff.in_redir)
+ {
+ case NAT_MAP :
+ which = "MAP";
+ break;
+ case NAT_MAPBLK :
+ which = "MAP-BLOCK";
+ break;
+ case NAT_REDIRECT :
+ which = "RDR";
+ break;
+ case NAT_BIMAP :
+ which = "BIMAP";
+ break;
+ default :
+ sprintf(unknownbuf, "unknown(%04x)",
+ ipnatbuff.in_redir & 0xffffffff);
+ which = unknownbuf;
+ break;
+ }
+ return which;
+}
diff --git a/contrib/ipfilter/lib/getport.c b/contrib/ipfilter/lib/getport.c
new file mode 100644
index 0000000..7cf903d
--- /dev/null
+++ b/contrib/ipfilter/lib/getport.c
@@ -0,0 +1,46 @@
+/* $NetBSD$ */
+
+#include "ipf.h"
+
+int getport(fr, name, port)
+frentry_t *fr;
+char *name;
+u_short *port;
+{
+ struct protoent *p;
+ struct servent *s;
+ u_short p1;
+
+ if (fr == NULL || fr->fr_type != FR_T_IPF) {
+ s = getservbyname(name, NULL);
+ if (s != NULL) {
+ *port = s->s_port;
+ return 0;
+ }
+ return -1;
+ }
+
+ if ((fr->fr_flx & FI_TCPUDP) != 0) {
+ /*
+ * If a rule is "tcp/udp" then check that both TCP and UDP
+ * mappings for this protocol name match ports.
+ */
+ s = getservbyname(name, "tcp");
+ if (s == NULL)
+ return -1;
+ p1 = s->s_port;
+ s = getservbyname(name, "udp");
+ if (s == NULL || s->s_port != p1)
+ return -1;
+ *port = p1;
+ return 0;
+ }
+
+ p = getprotobynumber(fr->fr_proto);
+ s = getservbyname(name, p ? p->p_name : NULL);
+ if (s != NULL) {
+ *port = s->s_port;
+ return 0;
+ }
+ return -1;
+}
diff --git a/contrib/ipfilter/lib/getportproto.c b/contrib/ipfilter/lib/getportproto.c
new file mode 100644
index 0000000..17efa43
--- /dev/null
+++ b/contrib/ipfilter/lib/getportproto.c
@@ -0,0 +1,32 @@
+/* $NetBSD$ */
+
+#include <ctype.h>
+#include "ipf.h"
+
+int getportproto(name, proto)
+char *name;
+int proto;
+{
+ struct servent *s;
+ struct protoent *p;
+
+ if (ISDIGIT(*name)) {
+ int number;
+ char *s;
+
+ for (s = name; *s != '\0'; s++)
+ if (!ISDIGIT(*s))
+ return -1;
+
+ number = atoi(name);
+ if (number < 0 || number > 65535)
+ return -1;
+ return htons(number);
+ }
+
+ p = getprotobynumber(proto);
+ s = getservbyname(name, p ? p->p_name : NULL);
+ if (s != NULL)
+ return s->s_port;
+ return -1;
+}
diff --git a/contrib/ipfilter/lib/getproto.c b/contrib/ipfilter/lib/getproto.c
new file mode 100644
index 0000000..c75f137
--- /dev/null
+++ b/contrib/ipfilter/lib/getproto.c
@@ -0,0 +1,21 @@
+/* $NetBSD$ */
+
+#include "ipf.h"
+
+int getproto(name)
+char *name;
+{
+ struct protoent *p;
+ char *s;
+
+ for (s = name; *s != '\0'; s++)
+ if (!ISDIGIT(*s))
+ break;
+ if (*s == '\0')
+ return atoi(name);
+
+ p = getprotobyname(name);
+ if (p != NULL)
+ return p->p_proto;
+ return -1;
+}
diff --git a/contrib/ipfilter/lib/getsumd.c b/contrib/ipfilter/lib/getsumd.c
new file mode 100644
index 0000000..11ecc57
--- /dev/null
+++ b/contrib/ipfilter/lib/getsumd.c
@@ -0,0 +1,15 @@
+/* $NetBSD$ */
+
+#include "ipf.h"
+
+char *getsumd(sum)
+u_32_t sum;
+{
+ static char sumdbuf[17];
+
+ if (sum & NAT_HW_CKSUM)
+ sprintf(sumdbuf, "hw(%#0x)", sum & 0xffff);
+ else
+ sprintf(sumdbuf, "%#0x", sum);
+ return sumdbuf;
+}
diff --git a/contrib/ipfilter/lib/hexdump.c b/contrib/ipfilter/lib/hexdump.c
new file mode 100644
index 0000000..4eb3b9ad
--- /dev/null
+++ b/contrib/ipfilter/lib/hexdump.c
@@ -0,0 +1,30 @@
+/* $NetBSD$ */
+
+#include <ctype.h>
+
+#include "ipf.h"
+
+void hexdump(out, addr, len, ascii)
+FILE *out;
+void *addr;
+int len, ascii;
+{
+ FILE *fpout;
+ u_char *s, *t;
+ int i;
+
+ fpout = out ? out : stdout;
+ for (i = 0, s = addr; i < len; i++, s++) {
+ fprintf(fpout, "%02x", *s);
+ if (i % 16 == 15) {
+ if (ascii != 0) {
+ fputc('\t', fpout);
+ for (t = s - 15; t<= s; t++)
+ fputc(ISPRINT(*t) ? *t : '.', fpout);
+ }
+ fputc('\n', fpout);
+ } else if (i % 4 == 3) {
+ fputc(' ', fpout);
+ }
+ }
+}
diff --git a/contrib/ipfilter/lib/hostmask.c b/contrib/ipfilter/lib/hostmask.c
new file mode 100644
index 0000000..67755f8
--- /dev/null
+++ b/contrib/ipfilter/lib/hostmask.c
@@ -0,0 +1,95 @@
+/* $NetBSD$ */
+
+/*
+ * Copyright (C) 1993-2001 by Darren Reed.
+ *
+ * See the IPFILTER.LICENCE file for details on licencing.
+ *
+ * Id: hostmask.c,v 1.10 2002/01/28 06:50:46 darrenr Exp
+ */
+
+#include "ipf.h"
+
+
+/*
+ * returns -1 if neither "hostmask/num" or "hostmask mask addr" are
+ * found in the line segments, there is an error processing this information,
+ * or there is an error processing ports information.
+ */
+int hostmask(seg, proto, ifname, sa, msk, linenum)
+char ***seg, *proto, *ifname;
+u_32_t *sa, *msk;
+int linenum;
+{
+ struct in_addr maskaddr;
+ char *s;
+
+ if ((s = strchr(**seg, '='))) {
+ *s++ = '\0';
+ if (!strcmp(**seg, "pool")) {
+ *sa = atoi(s);
+ return 1;
+ }
+ }
+
+ /*
+ * is it possibly hostname/num ?
+ */
+ if ((s = strchr(**seg, '/')) ||
+ ((s = strchr(**seg, ':')) && !strchr(s + 1, ':'))) {
+ *s++ ='\0';
+ if (genmask(s, msk) == -1) {
+ fprintf(stderr, "%d: bad mask (%s)\n", linenum, s);
+ return -1;
+ }
+ if (hostnum(sa, **seg, linenum, ifname) == -1) {
+ fprintf(stderr, "%d: bad host (%s)\n", linenum, **seg);
+ return -1;
+ }
+ *sa &= *msk;
+ (*seg)++;
+ return 0;
+ }
+
+ /*
+ * look for extra segments if "mask" found in right spot
+ */
+ if (*(*seg+1) && *(*seg+2) && !strcasecmp(*(*seg+1), "mask")) {
+ if (hostnum(sa, **seg, linenum, ifname) == -1) {
+ fprintf(stderr, "%d: bad host (%s)\n", linenum, **seg);
+ return -1;
+ }
+ (*seg)++;
+ (*seg)++;
+ if (inet_aton(**seg, &maskaddr) == 0) {
+ fprintf(stderr, "%d: bad mask (%s)\n", linenum, **seg);
+ return -1;
+ }
+ *msk = maskaddr.s_addr;
+ (*seg)++;
+ *sa &= *msk;
+ return 0;
+ }
+
+ if (**seg) {
+ u_32_t k;
+
+ if (hostnum(sa, **seg, linenum, ifname) == -1) {
+ fprintf(stderr, "%d: bad host (%s)\n", linenum, **seg);
+ return -1;
+ }
+ (*seg)++;
+ k = *sa ? 0xffffffff : 0;
+#ifdef USE_INET6
+ if (use_inet6) {
+ msk[1] = k;
+ msk[2] = k;
+ msk[3] = k;
+ }
+#endif
+ *msk = k;
+ return 0;
+ }
+ fprintf(stderr, "%d: bad host (%s)\n", linenum, **seg);
+ return -1;
+}
diff --git a/contrib/ipfilter/lib/hostname.c b/contrib/ipfilter/lib/hostname.c
new file mode 100644
index 0000000..a0109da
--- /dev/null
+++ b/contrib/ipfilter/lib/hostname.c
@@ -0,0 +1,51 @@
+/* $NetBSD$ */
+
+
+#include "ipf.h"
+
+char *hostname(v, ip)
+int v;
+void *ip;
+{
+ static char hostbuf[MAXHOSTNAMELEN+1];
+ struct hostent *hp;
+ struct in_addr ipa;
+ struct netent *np;
+
+ if (v == 4) {
+ ipa.s_addr = *(u_32_t *)ip;
+ if (ipa.s_addr == htonl(0xfedcba98))
+ return "test.host.dots";
+ }
+
+ if ((opts & OPT_NORESOLVE) == 0) {
+ if (v == 4) {
+ hp = gethostbyaddr(ip, 4, AF_INET);
+ if (hp != NULL && hp->h_name != NULL &&
+ *hp->h_name != '\0') {
+ strncpy(hostbuf, hp->h_name, sizeof(hostbuf));
+ hostbuf[sizeof(hostbuf) - 1] = '\0';
+ return hostbuf;
+ }
+
+ np = getnetbyaddr(ipa.s_addr, AF_INET);
+ if (np != NULL && np->n_name != NULL &&
+ *np->n_name != '\0') {
+ strncpy(hostbuf, np->n_name, sizeof(hostbuf));
+ hostbuf[sizeof(hostbuf) - 1] = '\0';
+ return hostbuf;
+ }
+ }
+ }
+
+ if (v == 4) {
+ return inet_ntoa(ipa);
+ }
+#ifdef USE_INET6
+ (void) inet_ntop(AF_INET6, ip, hostbuf, sizeof(hostbuf) - 1);
+ hostbuf[MAXHOSTNAMELEN] = '\0';
+ return hostbuf;
+#else
+ return "IPv6";
+#endif
+}
diff --git a/contrib/ipfilter/lib/hostnum.c b/contrib/ipfilter/lib/hostnum.c
new file mode 100644
index 0000000..c62e4a1
--- /dev/null
+++ b/contrib/ipfilter/lib/hostnum.c
@@ -0,0 +1,49 @@
+/* $NetBSD$ */
+
+/*
+ * Copyright (C) 1993-2001 by Darren Reed.
+ *
+ * See the IPFILTER.LICENCE file for details on licencing.
+ *
+ * Id: hostnum.c,v 1.10.2.1 2004/12/09 19:41:20 darrenr Exp
+ */
+
+#include <ctype.h>
+
+#include "ipf.h"
+
+
+/*
+ * returns an ip address as a long var as a result of either a DNS lookup or
+ * straight inet_addr() call
+ */
+int hostnum(ipa, host, linenum, ifname)
+u_32_t *ipa;
+char *host;
+int linenum;
+char *ifname;
+{
+ struct in_addr ip;
+
+ if (!strcasecmp("any", host) ||
+ (ifname && *ifname && !strcasecmp(ifname, host)))
+ return 0;
+
+#ifdef USE_INET6
+ if (use_inet6) {
+ if (inet_pton(AF_INET6, host, ipa) == 1)
+ return 0;
+ else
+ return -1;
+ }
+#endif
+ if (ISDIGIT(*host) && inet_aton(host, &ip)) {
+ *ipa = ip.s_addr;
+ return 0;
+ }
+
+ if (!strcasecmp("<thishost>", host))
+ host = thishost;
+
+ return gethost(host, ipa);
+}
diff --git a/contrib/ipfilter/lib/icmpcode.c b/contrib/ipfilter/lib/icmpcode.c
new file mode 100644
index 0000000..17e1ba4
--- /dev/null
+++ b/contrib/ipfilter/lib/icmpcode.c
@@ -0,0 +1,49 @@
+/* $NetBSD$ */
+
+/*
+ * Copyright (C) 1993-2001 by Darren Reed.
+ *
+ * See the IPFILTER.LICENCE file for details on licencing.
+ *
+ * Id: icmpcode.c,v 1.7.2.1 2004/12/09 19:41:20 darrenr Exp
+ */
+
+#include <ctype.h>
+
+#include "ipf.h"
+
+#ifndef MIN
+# define MIN(a,b) ((a) > (b) ? (b) : (a))
+#endif
+
+
+char *icmpcodes[MAX_ICMPCODE + 1] = {
+ "net-unr", "host-unr", "proto-unr", "port-unr", "needfrag", "srcfail",
+ "net-unk", "host-unk", "isolate", "net-prohib", "host-prohib",
+ "net-tos", "host-tos", "filter-prohib", "host-preced", "preced-cutoff",
+ NULL };
+
+/*
+ * Return the number for the associated ICMP unreachable code.
+ */
+int icmpcode(str)
+char *str;
+{
+ char *s;
+ int i, len;
+
+ if ((s = strrchr(str, ')')))
+ *s = '\0';
+ if (ISDIGIT(*str)) {
+ if (!ratoi(str, &i, 0, 255))
+ return -1;
+ else
+ return i;
+ }
+ len = strlen(str);
+ for (i = 0; icmpcodes[i]; i++)
+ if (!strncasecmp(str, icmpcodes[i], MIN(len,
+ strlen(icmpcodes[i])) ))
+ return i;
+ return -1;
+}
diff --git a/contrib/ipfilter/lib/inet_addr.c b/contrib/ipfilter/lib/inet_addr.c
new file mode 100644
index 0000000..5ccf6a9
--- /dev/null
+++ b/contrib/ipfilter/lib/inet_addr.c
@@ -0,0 +1,210 @@
+/* $NetBSD$ */
+
+/*
+ * ++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)
+static const char sccsid[] = "@(#)inet_addr.c 8.1 (Berkeley) 6/17/93";
+static const char rcsid[] = "@(#)Id: inet_addr.c,v 1.8.2.3 2004/12/09 19:41:20 darrenr Exp";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/param.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <ctype.h>
+
+#ifndef __P
+# ifdef __STDC__
+# define __P(x) x
+# else
+# define __P(x) ()
+# endif
+#endif
+#ifndef linux
+int inet_aton __P((const char *, struct in_addr *));
+
+/*
+ * Because the ctype(3) posix definition, if used "safely" in code everywhere,
+ * would mean all normal code that walks through strings needed casts. Yuck.
+ */
+#define ISALNUM(x) isalnum((u_char)(x))
+#define ISALPHA(x) isalpha((u_char)(x))
+#define ISASCII(x) isascii((u_char)(x))
+#define ISDIGIT(x) isdigit((u_char)(x))
+#define ISPRINT(x) isprint((u_char)(x))
+#define ISSPACE(x) isspace((u_char)(x))
+#define ISUPPER(x) isupper((u_char)(x))
+#define ISXDIGIT(x) isxdigit((u_char)(x))
+#define ISLOWER(x) islower((u_char)(x))
+
+/*
+ * 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);
+}
+#endif
+
+/* these are compatibility routines, not needed on recent BSD releases */
+
+/*
+ * Ascii internet address interpretation routine.
+ * The value returned is in network order.
+ */
+#if 0
+inet_addr(cp)
+ const char *cp;
+{
+ struct in_addr val;
+
+ if (inet_aton(cp, &val))
+ return (val.s_addr);
+ return (0xffffffff);
+}
+#endif
diff --git a/contrib/ipfilter/lib/initparse.c b/contrib/ipfilter/lib/initparse.c
new file mode 100644
index 0000000..676774c
--- /dev/null
+++ b/contrib/ipfilter/lib/initparse.c
@@ -0,0 +1,20 @@
+/* $NetBSD$ */
+
+/*
+ * Copyright (C) 1993-2001 by Darren Reed.
+ *
+ * See the IPFILTER.LICENCE file for details on licencing.
+ *
+ * Id: initparse.c,v 1.6 2002/01/28 06:50:46 darrenr Exp
+ */
+#include "ipf.h"
+
+
+char thishost[MAXHOSTNAMELEN];
+
+
+void initparse __P((void))
+{
+ gethostname(thishost, sizeof(thishost));
+ thishost[sizeof(thishost) - 1] = '\0';
+}
diff --git a/contrib/ipfilter/lib/ionames.c b/contrib/ipfilter/lib/ionames.c
new file mode 100644
index 0000000..9e4602b
--- /dev/null
+++ b/contrib/ipfilter/lib/ionames.c
@@ -0,0 +1,40 @@
+/* $NetBSD$ */
+
+/*
+ * Copyright (C) 1993-2001 by Darren Reed.
+ *
+ * See the IPFILTER.LICENCE file for details on licencing.
+ *
+ * Id: ionames.c,v 1.7 2002/01/28 06:50:46 darrenr Exp
+ */
+#include "ipf.h"
+
+
+struct ipopt_names ionames[] ={
+ { IPOPT_NOP, 0x000001, 1, "nop" }, /* RFC791 */
+ { IPOPT_RR, 0x000002, 7, "rr" }, /* 1 route */
+ { IPOPT_ZSU, 0x000004, 3, "zsu" }, /* size ?? */
+ { IPOPT_MTUP, 0x000008, 3, "mtup" }, /* RFC1191 */
+ { IPOPT_MTUR, 0x000010, 3, "mtur" }, /* RFC1191 */
+ { IPOPT_ENCODE, 0x000020, 3, "encode" }, /* size ?? */
+ { IPOPT_TS, 0x000040, 8, "ts" }, /* 1 TS */
+ { IPOPT_TR, 0x000080, 3, "tr" }, /* RFC1393 */
+ { IPOPT_SECURITY,0x000100, 11, "sec" }, /* RFC1108 */
+ { IPOPT_SECURITY,0x000100, 11, "sec-class" }, /* RFC1108 */
+ { IPOPT_LSRR, 0x000200, 7, "lsrr" }, /* 1 route */
+ { IPOPT_E_SEC, 0x000400, 3, "e-sec" }, /* RFC1108 */
+ { IPOPT_CIPSO, 0x000800, 3, "cipso" }, /* size ?? */
+ { IPOPT_SATID, 0x001000, 4, "satid" }, /* RFC791 */
+ { IPOPT_SSRR, 0x002000, 7, "ssrr" }, /* 1 route */
+ { IPOPT_ADDEXT, 0x004000, 3, "addext" }, /* IPv7 ?? */
+ { IPOPT_VISA, 0x008000, 3, "visa" }, /* size ?? */
+ { IPOPT_IMITD, 0x010000, 3, "imitd" }, /* size ?? */
+ { IPOPT_EIP, 0x020000, 3, "eip" }, /* RFC1385 */
+ { IPOPT_FINN, 0x040000, 3, "finn" }, /* size ?? */
+ { IPOPT_DPS, 0x080000, 3, "dps" }, /* size ?? */
+ { IPOPT_SDB, 0x100000, 3, "sdb" }, /* size ?? */
+ { IPOPT_NSAPA, 0x200000, 3, "nsapa" }, /* size ?? */
+ { IPOPT_RTRALRT,0x400000, 3, "rtralrt" }, /* RFC2113 */
+ { IPOPT_UMP, 0x800000, 3, "ump" }, /* size ?? */
+ { 0, 0, 0, (char *)NULL } /* must be last */
+};
diff --git a/contrib/ipfilter/lib/ipf_dotuning.c b/contrib/ipfilter/lib/ipf_dotuning.c
new file mode 100644
index 0000000..c9416ff
--- /dev/null
+++ b/contrib/ipfilter/lib/ipf_dotuning.c
@@ -0,0 +1,60 @@
+/* $NetBSD$ */
+
+#include "ipf.h"
+#include "ipl.h"
+#include <sys/ioctl.h>
+
+void ipf_dotuning(fd, tuneargs, iocfn)
+int fd;
+char *tuneargs;
+ioctlfunc_t iocfn;
+{
+ ipfobj_t obj;
+ ipftune_t tu;
+ char *s, *t;
+
+ bzero((char *)&tu, sizeof(tu));
+ obj.ipfo_rev = IPFILTER_VERSION;
+ obj.ipfo_size = sizeof(tu);;
+ obj.ipfo_ptr = (void *)&tu;
+ obj.ipfo_type = IPFOBJ_TUNEABLE;
+
+ for (s = strtok(tuneargs, ","); s != NULL; s = strtok(NULL, ",")) {
+ if (!strcmp(s, "list")) {
+ while (1) {
+ if ((*iocfn)(fd, SIOCIPFGETNEXT, &obj) == -1) {
+ perror("ioctl(SIOCIPFGETNEXT)");
+ break;
+ }
+ if (tu.ipft_cookie == NULL)
+ break;
+
+ tu.ipft_name[sizeof(tu.ipft_name) - 1] = '\0';
+ printtunable(&tu);
+ }
+ } else if ((t = strchr(s, '=')) != NULL) {
+ *t++ = '\0';
+ strncpy(tu.ipft_name, s, sizeof(tu.ipft_name));
+ if (sscanf(t, "%lu", &tu.ipft_vlong) == 1) {
+ if ((*iocfn)(fd, SIOCIPFSET, &obj) == -1) {
+ perror("ioctl(SIOCIPFSET)");
+ return;
+ }
+ } else {
+ fprintf(stderr, "invalid value '%s'\n", s);
+ return;
+ }
+ } else {
+ strncpy(tu.ipft_name, s, sizeof(tu.ipft_name));
+ if ((*iocfn)(fd, SIOCIPFGET, &obj) == -1) {
+ perror("ioctl(SIOCIPFGET)");
+ return;
+ }
+ if (tu.ipft_cookie == NULL)
+ return;
+
+ tu.ipft_name[sizeof(tu.ipft_name) - 1] = '\0';
+ printtunable(&tu);
+ }
+ }
+}
diff --git a/contrib/ipfilter/lib/ipft_ef.c b/contrib/ipfilter/lib/ipft_ef.c
new file mode 100644
index 0000000..eebc417
--- /dev/null
+++ b/contrib/ipfilter/lib/ipft_ef.c
@@ -0,0 +1,130 @@
+/* $NetBSD$ */
+
+/*
+ * Copyright (C) 1993-2001 by Darren Reed.
+ *
+ * See the IPFILTER.LICENCE file for details on licencing.
+ *
+ * Id: ipft_ef.c,v 1.14 2004/01/08 13:34:31 darrenr Exp
+ */
+
+/*
+ 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 "ipf.h"
+#include "ipt.h"
+
+#ifndef linux
+#include <netinet/ip_var.h>
+#endif
+#include <netinet/tcpip.h>
+
+
+#if !defined(lint)
+static const char sccsid[] = "@(#)ipft_ef.c 1.6 2/4/96 (C)1995 Darren Reed";
+static const char rcsid[] = "@(#)Id: ipft_ef.c,v 1.14 2004/01/08 13:34:31 darrenr Exp";
+#endif
+
+static int etherf_open __P((char *));
+static int etherf_close __P((void));
+static int etherf_readip __P((char *, int, char **, int *));
+
+struct ipread etherf = { etherf_open, etherf_close, etherf_readip, 0 };
+
+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;
+ ip_t *ip = (ip_t *)&pkt;
+ char src[16], dst[16], sprt[16], dprt[16];
+ char lbuf[128], len[8], prot[8], time[8], *s;
+ int slen, extra = 0, i;
+
+ 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 (sscanf(lbuf, "%7s %7s %15s %15s %15s %15s", len, prot, src, dst,
+ sprt, dprt) != 6)
+ if (sscanf(lbuf, "%7s %7s %7s %15s %15s %15s %15s", time,
+ len, prot, src, dst, sprt, dprt) != 7)
+ return -1;
+
+ ip->ip_p = getproto(prot);
+
+ switch (ip->ip_p) {
+ case IPPROTO_TCP :
+ case IPPROTO_UDP :
+ s = strtok(NULL, " :");
+ ip->ip_len += atoi(s);
+ if (ip->ip_p == IPPROTO_TCP)
+ extra = sizeof(struct tcphdr);
+ else if (ip->ip_p == 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_HL_A(ip, sizeof(ip_t));
+
+ slen = IP_HL(ip) + extra;
+ i = MIN(cnt, slen);
+ bcopy((char *)&pkt, buf, i);
+ return i;
+}
diff --git a/contrib/ipfilter/lib/ipft_hx.c b/contrib/ipfilter/lib/ipft_hx.c
new file mode 100644
index 0000000..3cc8ec5
--- /dev/null
+++ b/contrib/ipfilter/lib/ipft_hx.c
@@ -0,0 +1,158 @@
+/* $NetBSD$ */
+
+/*
+ * Copyright (C) 1995-2001 by Darren Reed.
+ *
+ * See the IPFILTER.LICENCE file for details on licencing.
+ */
+#if !defined(lint)
+static const char sccsid[] = "@(#)ipft_hx.c 1.1 3/9/96 (C) 1996 Darren Reed";
+static const char rcsid[] = "@(#)Id: ipft_hx.c,v 1.11.4.1 2004/12/09 19:41:20 darrenr Exp";
+#endif
+
+#include <ctype.h>
+
+#include "ipf.h"
+#include "ipt.h"
+
+
+extern int opts;
+
+static int hex_open __P((char *));
+static int hex_close __P((void));
+static int hex_readip __P((char *, int, char **, int *));
+static char *readhex __P((char *, char *));
+
+struct ipread iphex = { hex_open, hex_close, hex_readip, 0 };
+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, *t, *u;
+ char line[513];
+ ip_t *ip;
+
+ /*
+ * interpret start of line as possibly "[ifname]" or
+ * "[in/out,ifname]".
+ */
+ if (ifn)
+ *ifn = NULL;
+ if (dir)
+ *dir = 0;
+ ip = (ip_t *)buf;
+ while (fgets(line, sizeof(line)-1, tfp)) {
+ if ((s = strchr(line, '\n'))) {
+ if (s == line)
+ return (char *)ip - buf;
+ *s = '\0';
+ }
+ if ((s = strchr(line, '#')))
+ *s = '\0';
+ if (!*line)
+ continue;
+ if (!(opts & OPT_BRIEF)) {
+ printf("input: %s", line);
+ }
+
+ if ((*line == '[') && (s = strchr(line, ']'))) {
+ t = line + 1;
+ if (s - t > 0) {
+ *s++ = '\0';
+ if ((u = strchr(t, ',')) && (u < s)) {
+ u++;
+ if (ifn)
+ *ifn = strdup(u);
+ if (dir) {
+ if (*t == 'i')
+ *dir = 0;
+ else if (*t == 'o')
+ *dir = 1;
+ }
+ } else if (ifn)
+ *ifn = t;
+ }
+ } else
+ s = line;
+ t = (char *)ip;
+ ip = (ip_t *)readhex(s, (char *)ip);
+ if (!(opts & OPT_BRIEF)) {
+ if (opts & OPT_ASCII) {
+ if (t < (char *)ip)
+ putchar('\t');
+ while (t < (char *)ip) {
+ if (ISPRINT(*t) && ISASCII(*t))
+ putchar(*t);
+ else
+ putchar('.');
+ t++;
+ }
+ }
+ putchar('\n');
+ fflush(stdout);
+ }
+ }
+ 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/lib/ipft_pc.c b/contrib/ipfilter/lib/ipft_pc.c
new file mode 100644
index 0000000..3678d78
--- /dev/null
+++ b/contrib/ipfilter/lib/ipft_pc.c
@@ -0,0 +1,252 @@
+/* $NetBSD$ */
+
+/*
+ * Copyright (C) 1993-2001 by Darren Reed.
+ *
+ * See the IPFILTER.LICENCE file for details on licencing.
+ *
+ * Id: ipft_pc.c,v 1.10 2004/02/07 18:17:40 darrenr Exp
+ */
+#include "ipf.h"
+#include "pcap-ipf.h"
+#include "bpf-ipf.h"
+#include "ipt.h"
+
+#if !defined(lint)
+static const char rcsid[] = "@(#)Id: ipft_pc.c,v 1.10 2004/02/07 18:17:40 darrenr Exp";
+#endif
+
+struct llc {
+ int lc_type;
+ 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[] = {
+ { DLT_NULL, 0, 0, 0 },
+ { DLT_EN10MB, 14, 12, 2 },
+ { 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, 0, 0, 0 },
+#ifdef DLT_ATMRFC1483
+ { DLT_ATMRFC1483, 0, 0, 0 },
+#endif
+ { DLT_RAW, 0, 0, 0 },
+#ifdef DLT_ENC
+ { DLT_ENC, 0, 0, 0 },
+#endif
+#ifdef DLT_SLIP_BSDOS
+ { DLT_SLIP_BSDOS, 0, 0, 0 },
+#endif
+#ifdef DLT_PPP_BSDOS
+ { DLT_PPP_BSDOS, 0, 0, 0 },
+#endif
+#ifdef DLT_HIPPI
+ { DLT_HIPPI, 0, 0, 0 },
+#endif
+#ifdef DLT_HDLC
+ { DLT_HDLC, 0, 0, 0 },
+#endif
+#ifdef DLT_PPP_SERIAL
+ { DLT_PPP_SERIAL, 4, 4, 0 },
+#endif
+#ifdef DLT_PPP_ETHER
+ { DLT_PPP_ETHER, 8, 8, 0 },
+#endif
+#ifdef DLT_ECONET
+ { DLT_ECONET, 0, 0, 0 },
+#endif
+ { -1, -1, -1, -1 }
+};
+
+static int pcap_open __P((char *));
+static int pcap_close __P((void));
+static int pcap_readip __P((char *, int, char **, int *));
+static void swap_hdr __P((pcaphdr_t *));
+static int pcap_read_rec __P((struct pcap_pkthdr *));
+
+static int pfd = -1, swapped = 0;
+static struct llc *llcp = NULL;
+
+struct ipread pcap = { pcap_open, pcap_close, pcap_readip, 0 };
+
+#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, i;
+
+ 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) {
+ (void) close(fd);
+ return -2;
+ }
+
+ for (i = 0; llcs[i].lc_type != -1; i++)
+ if (llcs[i].lc_type == ph.pc_type) {
+ llcp = llcs + i;
+ break;
+ }
+
+ if (llcp == NULL) {
+ (void) close(fd);
+ return -2;
+ }
+
+ pfd = fd;
+ 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;
+
+ l = llcp;
+
+ /* 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;
+
+ 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/lib/ipft_sn.c b/contrib/ipfilter/lib/ipft_sn.c
new file mode 100644
index 0000000..1458821
--- /dev/null
+++ b/contrib/ipfilter/lib/ipft_sn.c
@@ -0,0 +1,197 @@
+/* $NetBSD$ */
+
+/*
+ * Copyright (C) 1993-2001 by Darren Reed.
+ *
+ * See the IPFILTER.LICENCE file for details on licencing.
+ *
+ * Id: ipft_sn.c,v 1.7 2003/02/16 02:32:36 darrenr Exp
+ */
+
+/*
+ * Written to comply with the recent RFC 1761 from Sun.
+ */
+#include "ipf.h"
+#include "snoop.h"
+#include "ipt.h"
+
+#if !defined(lint)
+static const char rcsid[] = "@(#)Id: ipft_sn.c,v 1.7 2003/02/16 02:32:36 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 __P((char *));
+static int snoop_close __P((void));
+static int snoop_readip __P((char *, int, char **, int *));
+
+static int sfd = -1, s_type = -1;
+static int snoop_read_rec __P((struct snooppkt *));
+
+struct ipread snoop = { snoop_open, snoop_close, snoop_readip, 0 };
+
+
+static int snoop_open(fname)
+char *fname;
+{
+ struct snoophdr sh;
+ int fd;
+ int s_v;
+
+ 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;
+
+ s_v = (int)ntohl(sh.s_v);
+ s_type = (int)ntohl(sh.s_type);
+
+ if (s_v != SNOOP_VERSION ||
+ s_type < 0 || s_type > SDL_MAX) {
+ (void) close(fd);
+ return -2;
+ }
+
+ sfd = fd;
+ printf("opened snoop file %s:\n", fname);
+ printf("\tid: %8.8s version: %d type: %d\n", sh.s_id, 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, plen, ilen;
+
+ if (read(sfd, (char *)rec, sizeof(*rec)) != sizeof(*rec))
+ return -2;
+
+ ilen = (int)ntohl(rec->sp_ilen);
+ plen = (int)ntohl(rec->sp_plen);
+ if (ilen > plen || plen < sizeof(*rec))
+ return -2;
+
+ plen -= sizeof(*rec);
+ n = MIN(plen, ilen);
+ if (!n || n < 0)
+ return -3;
+
+ return plen;
+}
+
+
+#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/lib/ipft_td.c b/contrib/ipfilter/lib/ipft_td.c
new file mode 100644
index 0000000..b278c72
--- /dev/null
+++ b/contrib/ipfilter/lib/ipft_td.c
@@ -0,0 +1,174 @@
+/* $NetBSD$ */
+
+/*
+ * Copyright (C) 1993-2001 by Darren Reed.
+ *
+ * See the IPFILTER.LICENCE file for details on licencing.
+ *
+ * Id: ipft_td.c,v 1.15 2004/01/08 13:34:31 darrenr Exp
+ */
+
+/*
+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 "ipf.h"
+#include "ipt.h"
+
+#ifndef linux
+#include <netinet/ip_var.h>
+#endif
+#include <netinet/tcpip.h>
+
+
+#if !defined(lint)
+static const char sccsid[] = "@(#)ipft_td.c 1.8 2/4/96 (C)1995 Darren Reed";
+static const char rcsid[] = "@(#)Id: ipft_td.c,v 1.15 2004/01/08 13:34:31 darrenr Exp";
+#endif
+
+static int tcpd_open __P((char *));
+static int tcpd_close __P((void));
+static int tcpd_readip __P((char *, int, char **, int *));
+static int count_dots __P((char *));
+
+struct ipread tcpd = { tcpd_open, tcpd_close, tcpd_readip, 0 };
+
+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;
+ ip_t *ip = (ip_t *)&pkt;
+ char src[32], dst[32], misc[256], time[32], link1[32], link2[32];
+ char lbuf[160], *s;
+ int n, 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, "%31s > %31s: %255s", src, dst, misc)) != 3)
+ if ((n = sscanf(lbuf, "%31s %31s > %31s: %255s",
+ time, src, dst, misc)) != 4)
+ if ((n = sscanf(lbuf, "%31s %31s: %31s > %31s: %255s",
+ link1, link2, src, dst, misc)) != 5) {
+ n = sscanf(lbuf,
+ "%31s %31s %31s: %31s > %31s: %255s",
+ time, link1, link2, src, dst, misc);
+ if (n != 6)
+ return -1;
+ }
+
+ if (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 = sizeof(ip_t);
+ IP_HL_A(ip, sizeof(ip_t));
+
+ s = strtok(misc, " :");
+ ip->ip_p = getproto(s);
+
+ switch (ip->ip_p)
+ {
+ case IPPROTO_TCP :
+ case IPPROTO_UDP :
+ s = strtok(NULL, " :");
+ ip->ip_len += atoi(s);
+ if (ip->ip_p == IPPROTO_TCP)
+ extra = sizeof(struct tcphdr);
+ else if (ip->ip_p == 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_HL(ip) + extra + ip->ip_len;
+ return slen;
+}
diff --git a/contrib/ipfilter/lib/ipft_tx.c b/contrib/ipfilter/lib/ipft_tx.c
new file mode 100644
index 0000000..c77fbc4
--- /dev/null
+++ b/contrib/ipfilter/lib/ipft_tx.c
@@ -0,0 +1,331 @@
+/* $NetBSD$ */
+
+/*
+ * Copyright (C) 1995-2001 by Darren Reed.
+ *
+ * See the IPFILTER.LICENCE file for details on licencing.
+ *
+ * Id: ipft_tx.c,v 1.15.2.2 2004/12/09 19:41:21 darrenr Exp
+ */
+#if !defined(lint)
+static const char sccsid[] = "@(#)ipft_tx.c 1.7 6/5/96 (C) 1993 Darren Reed";
+static const char rcsid[] = "@(#)Id: ipft_tx.c,v 1.15.2.2 2004/12/09 19:41:21 darrenr Exp";
+#endif
+
+#include <ctype.h>
+
+#include "ipf.h"
+#include "ipt.h"
+
+#ifndef linux
+#include <netinet/ip_var.h>
+#endif
+#include <netinet/tcpip.h>
+
+
+extern int opts;
+
+static char *tx_proto = "";
+
+static int text_open __P((char *)), text_close __P((void));
+static int text_readip __P((char *, int, char **, int *));
+static int parseline __P((char *, ip_t *, char **, int *));
+
+static char _tcp_flagset[] = "FSRPAUEC";
+static u_char _tcp_flags[] = { TH_FIN, TH_SYN, TH_RST, TH_PUSH,
+ TH_ACK, TH_URG, TH_ECN, TH_CWR };
+
+struct ipread iptext = { text_open, text_close, text_readip, R_DO_CKSUM };
+static FILE *tfp = NULL;
+static int tfd = -1;
+
+static u_32_t tx_hostnum __P((char *, int *));
+static u_short tx_portnum __P((char *));
+
+
+/*
+ * returns an ip address as a long var as a result of either a DNS lookup or
+ * straight inet_addr() call
+ */
+static u_32_t tx_hostnum(host, resolved)
+char *host;
+int *resolved;
+{
+ u_32_t ipa;
+
+ *resolved = 0;
+ if (!strcasecmp("any", host))
+ return 0L;
+ if (ISDIGIT(*host))
+ return inet_addr(host);
+
+ if (gethost(host, &ipa) == -1) {
+ *resolved = -1;
+ fprintf(stderr, "can't resolve hostname: %s\n", host);
+ return 0;
+ }
+ return ipa;
+}
+
+
+/*
+ * 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", "routerad",
+ "routersol", "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;
+ char line[513];
+
+ *ifn = NULL;
+ while (fgets(line, sizeof(line)-1, tfp)) {
+ if ((s = strchr(line, '\n')))
+ *s = '\0';
+ if ((s = strchr(line, '\r')))
+ *s = '\0';
+ if ((s = strchr(line, '#')))
+ *s = '\0';
+ if (!*line)
+ continue;
+ if (!(opts & OPT_BRIEF))
+ printf("input: %s\n", line);
+ *ifn = NULL;
+ *dir = 0;
+ if (!parseline(line, (ip_t *)buf, ifn, dir))
+#if 0
+ return sizeof(ip_t) + sizeof(tcphdr_t);
+#else
+ return sizeof(ip_t);
+#endif
+ }
+ return -1;
+}
+
+static int parseline(line, ip, ifn, out)
+char *line;
+ip_t *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;
+
+ if (*ifn)
+ free(*ifn);
+ 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_HL_A(ip, sizeof(*ip) >> 2);
+ IP_V_A(ip, IPVERSION);
+ for (i = 0, cps[0] = strtok(line, " \b\t\r\n"); cps[i] && i < 19; )
+ cps[++i] = strtok(NULL, " \b\t\r\n");
+
+ cpp = cps;
+ if (!*cpp)
+ return 1;
+
+ 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 (!*cpp)
+ return 1;
+
+ if (!strcasecmp(*cpp, "on")) {
+ cpp++;
+ if (!*cpp)
+ return 1;
+ *ifn = strdup(*cpp++);
+ if (!*cpp)
+ return 1;
+ }
+
+ c = **cpp;
+ ip->ip_len = sizeof(ip_t);
+ 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 += ICMPERR_IPICMPHLEN;
+ tx_proto = "icmp";
+ }
+ cpp++;
+ } else if (ISDIGIT(**cpp) && !index(*cpp, '.')) {
+ ip->ip_p = atoi(*cpp);
+ 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 = strchr(*cpp, ',');
+ if (!last) {
+ fprintf(stderr, "tcp/udp with no source port\n");
+ return 1;
+ }
+ *last++ = '\0';
+ tcp->th_sport = htons(tx_portnum(last));
+ if (ip->ip_p == IPPROTO_TCP) {
+ tcp->th_win = htons(4096);
+ TCP_OFF_A(tcp, sizeof(*tcp) >> 2);
+ }
+ }
+ 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 = strchr(*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;
+
+ tcp->th_flags = 0;
+ for (s = *cpp; *s; s++)
+ if ((t = strchr(_tcp_flagset, *s)))
+ tcp->th_flags |= _tcp_flags[t - _tcp_flagset];
+ if (tcp->th_flags)
+ cpp++;
+ if (tcp->th_flags == 0)
+ abort();
+ if (tcp->th_flags & TH_URG)
+ tcp->th_urp = htons(1);
+ } 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 = strchr(*cpp, ',')))
+ ic->icmp_code = atoi(t+1);
+ cpp++;
+ break;
+ }
+ }
+
+ if (*cpp && !strcasecmp(*cpp, "opt")) {
+ u_long olen;
+
+ cpp++;
+ olen = buildopts(*cpp, ipopts, (IP_HL(ip) - 5) << 2);
+ if (olen) {
+ bcopy(ipopts, (char *)(ip + 1), olen);
+ IP_HL_A(ip, IP_HL(ip) + (olen >> 2));
+ }
+ }
+ if (ip->ip_p == IPPROTO_TCP || ip->ip_p == IPPROTO_UDP)
+ bcopy((char *)tcp, ((char *)ip) + (IP_HL(ip) << 2),
+ sizeof(*tcp));
+ else if (ip->ip_p == IPPROTO_ICMP)
+ bcopy((char *)ic, ((char *)ip) + (IP_HL(ip) << 2),
+ sizeof(*ic));
+ ip->ip_len = htons(ip->ip_len);
+ return 0;
+}
diff --git a/contrib/ipfilter/lib/ipoptsec.c b/contrib/ipfilter/lib/ipoptsec.c
new file mode 100644
index 0000000..95bde9c
--- /dev/null
+++ b/contrib/ipfilter/lib/ipoptsec.c
@@ -0,0 +1,58 @@
+/* $NetBSD$ */
+
+/*
+ * Copyright (C) 1993-2001 by Darren Reed.
+ *
+ * See the IPFILTER.LICENCE file for details on licencing.
+ *
+ * Id: ipoptsec.c,v 1.2 2002/01/28 06:50:46 darrenr Exp
+ */
+
+#include "ipf.h"
+
+
+struct ipopt_names secclass[] = {
+ { IPSO_CLASS_RES4, 0x01, 0, "reserv-4" },
+ { IPSO_CLASS_TOPS, 0x02, 0, "topsecret" },
+ { IPSO_CLASS_SECR, 0x04, 0, "secret" },
+ { IPSO_CLASS_RES3, 0x08, 0, "reserv-3" },
+ { IPSO_CLASS_CONF, 0x10, 0, "confid" },
+ { IPSO_CLASS_UNCL, 0x20, 0, "unclass" },
+ { IPSO_CLASS_RES2, 0x40, 0, "reserv-2" },
+ { IPSO_CLASS_RES1, 0x80, 0, "reserv-1" },
+ { 0, 0, 0, NULL } /* must be last */
+};
+
+
+u_char seclevel(slevel)
+char *slevel;
+{
+ struct ipopt_names *so;
+
+ for (so = secclass; 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 (u_char)so->on_value;
+}
+
+
+u_char secbit(class)
+int class;
+{
+ struct ipopt_names *so;
+
+ for (so = secclass; so->on_name; so++)
+ if (so->on_value == class)
+ break;
+
+ if (!so->on_name) {
+ fprintf(stderr, "no such security class: %d\n", class);
+ return 0;
+ }
+ return (u_char)so->on_bit;
+}
diff --git a/contrib/ipfilter/lib/kmem.c b/contrib/ipfilter/lib/kmem.c
new file mode 100644
index 0000000..3f044bb
--- /dev/null
+++ b/contrib/ipfilter/lib/kmem.c
@@ -0,0 +1,203 @@
+/* $NetBSD$ */
+
+/*
+ * Copyright (C) 1993-2001 by Darren Reed.
+ *
+ * See the IPFILTER.LICENCE file for details on licencing.
+ */
+/*
+ * kmemcpy() - copies n bytes from kernel memory into user buffer.
+ * returns 0 on success, -1 on error.
+ */
+
+#include <stdio.h>
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/uio.h>
+#include <unistd.h>
+#include <string.h>
+#include <fcntl.h>
+#include <sys/file.h>
+#if !defined(__sgi) && !defined(__hpux) && !defined(__osf__) && !defined(linux)
+#include <kvm.h>
+#endif
+#include <fcntl.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>
+#if __FreeBSD_version >= 300000
+# include <net/if_var.h>
+#endif
+#if defined(linux) || defined(__osf__) || defined(__sgi) || defined(__hpux)
+# include <stdlib.h>
+#endif
+
+#include "kmem.h"
+
+#ifndef __STDC__
+# define const
+#endif
+
+#if !defined(lint)
+static const char sccsid[] = "@(#)kmem.c 1.4 1/12/96 (C) 1992 Darren Reed";
+static const char rcsid[] = "@(#)Id: kmem.c,v 1.16.2.1 2004/06/20 10:25:58 darrenr Exp";
+#endif
+
+
+
+#if !defined(__sgi) && !defined(__hpux) && !defined(__osf__) && !defined(linux)
+/*
+ * For all platforms where there is a libkvm and a kvm_t, we use that...
+ */
+static kvm_t *kvm_f = NULL;
+
+#else
+/*
+ *...and for the others (HP-UX, IRIX, Tru64), we have to provide our own.
+ */
+
+typedef int * kvm_t;
+
+static kvm_t kvm_f = NULL;
+static char *kvm_errstr = NULL;
+
+kvm_t kvm_open __P((char *, char *, char *, int, char *));
+int kvm_read __P((kvm_t, u_long, char *, size_t));
+
+kvm_t kvm_open(kernel, core, swap, mode, errstr)
+char *kernel, *core, *swap;
+int mode;
+char *errstr;
+{
+ kvm_t k;
+ int fd;
+
+ kvm_errstr = errstr;
+
+ if (core == NULL)
+ core = "/dev/kmem";
+
+ fd = open(core, mode);
+ if (fd == -1)
+ return NULL;
+ k = malloc(sizeof(*k));
+ if (k == NULL)
+ return NULL;
+ *k = fd;
+ return k;
+}
+
+int kvm_read(kvm, pos, buffer, size)
+kvm_t kvm;
+u_long pos;
+char *buffer;
+size_t size;
+{
+ int r = 0, left;
+ char *bufp;
+
+ if (lseek(*kvm, pos, 0) == -1) {
+ if (kvm_errstr != NULL) {
+ fprintf(stderr, "%s", kvm_errstr);
+ perror("lseek");
+ }
+ return -1;
+ }
+
+ for (bufp = buffer, left = size; left > 0; bufp += r, left -= r) {
+ r = read(*kvm, bufp, left);
+#ifdef __osf__
+ /*
+ * Tru64 returns "0" for successful operation, not the number
+ * of bytes read.
+ */
+ if (r == 0)
+ r = left;
+#endif
+ if (r <= 0)
+ return -1;
+ }
+ return r;
+}
+#endif /* !defined(__sgi) && !defined(__hpux) && !defined(__osf__) */
+
+int openkmem(kern, core)
+char *kern, *core;
+{
+ kvm_f = kvm_open(kern, core, NULL, O_RDONLY, NULL);
+ if (kvm_f == NULL)
+ {
+ perror("openkmem:open");
+ return -1;
+ }
+ return kvm_f != NULL;
+}
+
+int kmemcpy(buf, pos, n)
+register char *buf;
+long pos;
+register int n;
+{
+ register int r;
+
+ if (!n)
+ return 0;
+
+ if (kvm_f == NULL)
+ if (openkmem(NULL, NULL) == -1)
+ return -1;
+
+ while ((r = kvm_read(kvm_f, pos, buf, n)) < n)
+ if (r <= 0)
+ {
+ fprintf(stderr, "pos=0x%lx ", (u_long)pos);
+ perror("kmemcpy:read");
+ return -1;
+ }
+ else
+ {
+ buf += r;
+ pos += r;
+ n -= r;
+ }
+ return 0;
+}
+
+int kstrncpy(buf, pos, n)
+register char *buf;
+long pos;
+register int n;
+{
+ register int r;
+
+ if (!n)
+ return 0;
+
+ if (kvm_f == NULL)
+ if (openkmem(NULL, NULL) == -1)
+ return -1;
+
+ while (n > 0)
+ {
+ r = kvm_read(kvm_f, pos, buf, 1);
+ if (r <= 0)
+ {
+ fprintf(stderr, "pos=0x%lx ", (u_long)pos);
+ perror("kmemcpy:read");
+ return -1;
+ }
+ else
+ {
+ if (*buf == '\0')
+ break;
+ buf++;
+ pos++;
+ n--;
+ }
+ }
+ return 0;
+}
diff --git a/contrib/ipfilter/lib/kmem.h b/contrib/ipfilter/lib/kmem.h
new file mode 100644
index 0000000..07a14f5
--- /dev/null
+++ b/contrib/ipfilter/lib/kmem.h
@@ -0,0 +1,34 @@
+/* $NetBSD$ */
+
+/*
+ * Copyright (C) 1993-2001 by Darren Reed.
+ *
+ * See the IPFILTER.LICENCE file for details on licencing.
+ * Id: kmem.h,v 1.2 2002/08/21 22:57:36 darrenr Exp
+ */
+
+#ifndef __KMEM_H__
+#define __KMEM_H__
+
+#ifndef __P
+# ifdef __STDC__
+# define __P(x) x
+# else
+# define __P(x) ()
+# endif
+#endif
+extern int openkmem __P((char *, char *));
+extern int kmemcpy __P((char *, long, int));
+extern int kstrncpy __P((char *, long, int));
+
+#if defined(__NetBSD__) || defined(__OpenBSD)
+# include <paths.h>
+#endif
+
+#ifdef _PATH_KMEM
+# define KMEM _PATH_KMEM
+#else
+# define KMEM "/dev/kmem"
+#endif
+
+#endif /* __KMEM_H__ */
diff --git a/contrib/ipfilter/lib/kmemcpywrap.c b/contrib/ipfilter/lib/kmemcpywrap.c
new file mode 100644
index 0000000..274bcb1
--- /dev/null
+++ b/contrib/ipfilter/lib/kmemcpywrap.c
@@ -0,0 +1,15 @@
+/* $NetBSD$ */
+
+#include "ipf.h"
+#include "kmem.h"
+
+int kmemcpywrap(from, to, size)
+void *from, *to;
+size_t size;
+{
+ int ret;
+
+ ret = kmemcpy((caddr_t)to, (u_long)from, size);
+ return ret;
+}
+
diff --git a/contrib/ipfilter/lib/kvatoname.c b/contrib/ipfilter/lib/kvatoname.c
new file mode 100644
index 0000000..030c633
--- /dev/null
+++ b/contrib/ipfilter/lib/kvatoname.c
@@ -0,0 +1,31 @@
+/* $NetBSD$ */
+
+#include "ipf.h"
+
+#include <fcntl.h>
+#include <sys/ioctl.h>
+
+char *kvatoname(func, iocfunc)
+ipfunc_t func;
+ioctlfunc_t iocfunc;
+{
+ static char funcname[40];
+ ipfunc_resolve_t res;
+ int fd;
+
+ res.ipfu_addr = func;
+ res.ipfu_name[0] = '\0';
+ fd = -1;
+
+ if ((opts & OPT_DONOTHING) == 0) {
+ fd = open(IPL_NAME, O_RDONLY);
+ if (fd == -1)
+ return NULL;
+ }
+ (void) (*iocfunc)(fd, SIOCFUNCL, &res);
+ if (fd >= 0)
+ close(fd);
+ strncpy(funcname, res.ipfu_name, sizeof(funcname));
+ funcname[sizeof(funcname) - 1] = '\0';
+ return funcname;
+}
diff --git a/contrib/ipfilter/lib/load_hash.c b/contrib/ipfilter/lib/load_hash.c
new file mode 100644
index 0000000..4fc042b
--- /dev/null
+++ b/contrib/ipfilter/lib/load_hash.c
@@ -0,0 +1,112 @@
+/* $NetBSD$ */
+
+/*
+ * Copyright (C) 2002 by Darren Reed.
+ *
+ * See the IPFILTER.LICENCE file for details on licencing.
+ *
+ * Id: load_hash.c,v 1.11.2.2 2005/02/01 02:44:05 darrenr Exp
+ */
+
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include "ipf.h"
+#include "netinet/ip_lookup.h"
+#include "netinet/ip_htable.h"
+
+static int hashfd = -1;
+
+
+int load_hash(iphp, list, iocfunc)
+iphtable_t *iphp;
+iphtent_t *list;
+ioctlfunc_t iocfunc;
+{
+ iplookupop_t op;
+ iphtable_t iph;
+ iphtent_t *a;
+ size_t size;
+ int n;
+
+ if ((hashfd == -1) && ((opts & OPT_DONOTHING) == 0))
+ hashfd = open(IPLOOKUP_NAME, O_RDWR);
+ if ((hashfd == -1) && ((opts & OPT_DONOTHING) == 0))
+ return -1;
+
+ for (n = 0, a = list; a != NULL; a = a->ipe_next)
+ n++;
+
+ op.iplo_arg = 0;
+ op.iplo_type = IPLT_HASH;
+ op.iplo_unit = iphp->iph_unit;
+ strncpy(op.iplo_name, iphp->iph_name, sizeof(op.iplo_name));
+ if (*op.iplo_name == '\0')
+ op.iplo_arg = IPHASH_ANON;
+ op.iplo_size = sizeof(iph);
+ op.iplo_struct = &iph;
+ iph.iph_unit = iphp->iph_unit;
+ iph.iph_type = iphp->iph_type;
+ strncpy(iph.iph_name, iphp->iph_name, sizeof(iph.iph_name));
+ iph.iph_flags = iphp->iph_flags;
+ if (n <= 0)
+ n = 1;
+ if (iphp->iph_size == 0)
+ size = n * 2 - 1;
+ else
+ size = iphp->iph_size;
+ if ((list == NULL) && (size == 1)) {
+ fprintf(stderr,
+ "WARNING: empty hash table %s, recommend setting %s\n",
+ iphp->iph_name, "size to match expected use");
+ }
+ iph.iph_size = size;
+ iph.iph_seed = iphp->iph_seed;
+ iph.iph_table = NULL;
+ iph.iph_ref = 0;
+
+ if ((opts & OPT_REMOVE) == 0) {
+ if ((*iocfunc)(hashfd, SIOCLOOKUPADDTABLE, &op))
+ if ((opts & OPT_DONOTHING) == 0) {
+ perror("load_hash:SIOCLOOKUPADDTABLE");
+ return -1;
+ }
+ }
+
+ strncpy(op.iplo_name, iph.iph_name, sizeof(op.iplo_name));
+ strncpy(iphp->iph_name, iph.iph_name, sizeof(op.iplo_name));
+
+ if (opts & OPT_VERBOSE) {
+ for (a = list; a != NULL; a = a->ipe_next) {
+ a->ipe_addr.in4_addr = ntohl(a->ipe_addr.in4_addr);
+ a->ipe_mask.in4_addr = ntohl(a->ipe_mask.in4_addr);
+ }
+ iph.iph_table = calloc(size, sizeof(*iph.iph_table));
+ if (iph.iph_table == NULL) {
+ perror("calloc(size, sizeof(*iph.iph_table))");
+ return -1;
+ }
+ iph.iph_table[0] = list;
+ printhash(&iph, bcopywrap, iph.iph_name, opts);
+ free(iph.iph_table);
+
+ for (a = list; a != NULL; a = a->ipe_next) {
+ a->ipe_addr.in4_addr = htonl(a->ipe_addr.in4_addr);
+ a->ipe_mask.in4_addr = htonl(a->ipe_mask.in4_addr);
+ }
+ }
+
+ if (opts & OPT_DEBUG)
+ printf("Hash %s:\n", iph.iph_name);
+
+ for (a = list; a != NULL; a = a->ipe_next)
+ load_hashnode(iphp->iph_unit, iph.iph_name, a, iocfunc);
+
+ if ((opts & OPT_REMOVE) != 0) {
+ if ((*iocfunc)(hashfd, SIOCLOOKUPDELTABLE, &op))
+ if ((opts & OPT_DONOTHING) == 0) {
+ perror("load_hash:SIOCLOOKUPDELTABLE");
+ return -1;
+ }
+ }
+ return 0;
+}
diff --git a/contrib/ipfilter/lib/load_hashnode.c b/contrib/ipfilter/lib/load_hashnode.c
new file mode 100644
index 0000000..186ba05
--- /dev/null
+++ b/contrib/ipfilter/lib/load_hashnode.c
@@ -0,0 +1,61 @@
+/* $NetBSD$ */
+
+/*
+ * Copyright (C) 2002 by Darren Reed.
+ *
+ * See the IPFILTER.LICENCE file for details on licencing.
+ *
+ * Id: load_hashnode.c,v 1.2.4.1 2004/03/06 14:33:28 darrenr Exp
+ */
+
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include "ipf.h"
+#include "netinet/ip_lookup.h"
+#include "netinet/ip_htable.h"
+
+static int hashfd = -1;
+
+
+int load_hashnode(unit, name, node, iocfunc)
+int unit;
+char *name;
+iphtent_t *node;
+ioctlfunc_t iocfunc;
+{
+ iplookupop_t op;
+ iphtent_t ipe;
+ int err;
+
+ if ((hashfd == -1) && ((opts & OPT_DONOTHING) == 0))
+ hashfd = open(IPLOOKUP_NAME, O_RDWR);
+ if ((hashfd == -1) && ((opts & OPT_DONOTHING) == 0))
+ return -1;
+
+ op.iplo_type = IPLT_HASH;
+ op.iplo_unit = unit;
+ op.iplo_arg = 0;
+ op.iplo_size = sizeof(ipe);
+ op.iplo_struct = &ipe;
+ strncpy(op.iplo_name, name, sizeof(op.iplo_name));
+
+ bzero((char *)&ipe, sizeof(ipe));
+ bcopy((char *)&node->ipe_addr, (char *)&ipe.ipe_addr,
+ sizeof(ipe.ipe_addr));
+ bcopy((char *)&node->ipe_mask, (char *)&ipe.ipe_mask,
+ sizeof(ipe.ipe_mask));
+ bcopy((char *)&node->ipe_group, (char *)&ipe.ipe_group,
+ sizeof(ipe.ipe_group));
+
+ if ((opts & OPT_REMOVE) == 0)
+ err = (*iocfunc)(hashfd, SIOCLOOKUPADDNODE, &op);
+ else
+ err = (*iocfunc)(hashfd, SIOCLOOKUPDELNODE, &op);
+
+ if (err != 0)
+ if (!(opts & OPT_DONOTHING)) {
+ perror("load_hash:SIOCLOOKUP*NODE");
+ return -1;
+ }
+ return 0;
+}
diff --git a/contrib/ipfilter/lib/load_pool.c b/contrib/ipfilter/lib/load_pool.c
new file mode 100644
index 0000000..5fab311
--- /dev/null
+++ b/contrib/ipfilter/lib/load_pool.c
@@ -0,0 +1,69 @@
+/* $NetBSD$ */
+
+/*
+ * Copyright (C) 2002 by Darren Reed.
+ *
+ * See the IPFILTER.LICENCE file for details on licencing.
+ *
+ * Id: load_pool.c,v 1.14.2.2 2005/02/01 02:44:06 darrenr Exp
+ */
+
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include "ipf.h"
+#include "netinet/ip_lookup.h"
+#include "netinet/ip_pool.h"
+
+static int poolfd = -1;
+
+
+int load_pool(plp, iocfunc)
+ip_pool_t *plp;
+ioctlfunc_t iocfunc;
+{
+ iplookupop_t op;
+ ip_pool_node_t *a;
+ ip_pool_t pool;
+
+ if ((poolfd == -1) && ((opts & OPT_DONOTHING) == 0))
+ poolfd = open(IPLOOKUP_NAME, O_RDWR);
+ if ((poolfd == -1) && ((opts & OPT_DONOTHING) == 0))
+ return -1;
+
+ op.iplo_unit = plp->ipo_unit;
+ op.iplo_type = IPLT_POOL;
+ op.iplo_arg = 0;
+ strncpy(op.iplo_name, plp->ipo_name, sizeof(op.iplo_name));
+ op.iplo_size = sizeof(pool);
+ op.iplo_struct = &pool;
+ bzero((char *)&pool, sizeof(pool));
+ strncpy(pool.ipo_name, plp->ipo_name, sizeof(pool.ipo_name));
+ if (*plp->ipo_name == '\0')
+ op.iplo_arg |= IPOOL_ANON;
+
+ if ((opts & OPT_REMOVE) == 0) {
+ if ((*iocfunc)(poolfd, SIOCLOOKUPADDTABLE, &op))
+ if ((opts & OPT_DONOTHING) == 0) {
+ perror("load_pool:SIOCLOOKUPADDTABLE");
+ return -1;
+ }
+ }
+
+ if ((opts & OPT_VERBOSE) != 0) {
+ pool.ipo_list = plp->ipo_list;
+ printpool(&pool, bcopywrap, pool.ipo_name, opts);
+ pool.ipo_list = NULL;
+ }
+
+ for (a = plp->ipo_list; a != NULL; a = a->ipn_next)
+ load_poolnode(plp->ipo_unit, plp->ipo_name, a, iocfunc);
+
+ if ((opts & OPT_REMOVE) != 0) {
+ if ((*iocfunc)(poolfd, SIOCLOOKUPDELTABLE, &op))
+ if ((opts & OPT_DONOTHING) == 0) {
+ perror("load_pool:SIOCLOOKUPDELTABLE");
+ return -1;
+ }
+ }
+ return 0;
+}
diff --git a/contrib/ipfilter/lib/load_poolnode.c b/contrib/ipfilter/lib/load_poolnode.c
new file mode 100644
index 0000000..e9d233f
--- /dev/null
+++ b/contrib/ipfilter/lib/load_poolnode.c
@@ -0,0 +1,63 @@
+/* $NetBSD$ */
+
+/*
+ * Copyright (C) 2002 by Darren Reed.
+ *
+ * See the IPFILTER.LICENCE file for details on licencing.
+ *
+ * Id: load_poolnode.c,v 1.3.2.1 2004/03/06 14:33:29 darrenr Exp
+ */
+
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include "ipf.h"
+#include "netinet/ip_lookup.h"
+#include "netinet/ip_pool.h"
+
+static int poolfd = -1;
+
+
+int load_poolnode(role, name, node, iocfunc)
+int role;
+char *name;
+ip_pool_node_t *node;
+ioctlfunc_t iocfunc;
+{
+ ip_pool_node_t pn;
+ iplookupop_t op;
+ int err;
+
+ if ((poolfd == -1) && ((opts & OPT_DONOTHING) == 0))
+ poolfd = open(IPLOOKUP_NAME, O_RDWR);
+ if ((poolfd == -1) && ((opts & OPT_DONOTHING) == 0))
+ return -1;
+
+ op.iplo_unit = role;
+ op.iplo_type = IPLT_POOL;
+ op.iplo_arg = 0;
+ op.iplo_struct = &pn;
+ op.iplo_size = sizeof(pn);
+ strncpy(op.iplo_name, name, sizeof(op.iplo_name));
+
+ bzero((char *)&pn, sizeof(pn));
+ bcopy((char *)&node->ipn_addr, (char *)&pn.ipn_addr,
+ sizeof(pn.ipn_addr));
+ bcopy((char *)&node->ipn_mask, (char *)&pn.ipn_mask,
+ sizeof(pn.ipn_mask));
+ pn.ipn_info = node->ipn_info;
+ strncpy(pn.ipn_name, node->ipn_name, sizeof(pn.ipn_name));
+
+ if ((opts & OPT_REMOVE) == 0)
+ err = (*iocfunc)(poolfd, SIOCLOOKUPADDNODE, &op);
+ else
+ err = (*iocfunc)(poolfd, SIOCLOOKUPDELNODE, &op);
+
+ if (err != 0) {
+ if ((opts & OPT_DONOTHING) == 0) {
+ perror("load_pool:SIOCLOOKUP*NODE");
+ return -1;
+ }
+ }
+
+ return 0;
+}
diff --git a/contrib/ipfilter/lib/loglevel.c b/contrib/ipfilter/lib/loglevel.c
new file mode 100644
index 0000000..31b4f17
--- /dev/null
+++ b/contrib/ipfilter/lib/loglevel.c
@@ -0,0 +1,55 @@
+/* $NetBSD$ */
+
+/*
+ * Copyright (C) 1993-2001 by Darren Reed.
+ *
+ * See the IPFILTER.LICENCE file for details on licencing.
+ *
+ * Id: loglevel.c,v 1.5 2001/06/09 17:09:24 darrenr Exp
+ */
+
+#include "ipf.h"
+
+
+int loglevel(cpp, facpri, linenum)
+char **cpp;
+u_int *facpri;
+int linenum;
+{
+ int fac, pri;
+ char *s;
+
+ fac = 0;
+ pri = 0;
+ if (!*++cpp) {
+ fprintf(stderr, "%d: %s\n", linenum,
+ "missing identifier after level");
+ return -1;
+ }
+
+ s = strchr(*cpp, '.');
+ if (s) {
+ *s++ = '\0';
+ fac = fac_findname(*cpp);
+ if (fac == -1) {
+ fprintf(stderr, "%d: %s %s\n", linenum,
+ "Unknown facility", *cpp);
+ return -1;
+ }
+ pri = pri_findname(s);
+ if (pri == -1) {
+ fprintf(stderr, "%d: %s %s\n", linenum,
+ "Unknown priority", s);
+ return -1;
+ }
+ } else {
+ pri = pri_findname(*cpp);
+ if (pri == -1) {
+ fprintf(stderr, "%d: %s %s\n", linenum,
+ "Unknown priority", *cpp);
+ return -1;
+ }
+ }
+ *facpri = fac|pri;
+ return 0;
+}
diff --git a/contrib/ipfilter/lib/make_range.c b/contrib/ipfilter/lib/make_range.c
new file mode 100644
index 0000000..9ec3ca3
--- /dev/null
+++ b/contrib/ipfilter/lib/make_range.c
@@ -0,0 +1,26 @@
+/* $NetBSD$ */
+
+/*
+ * Copyright (C) 2002 by Darren Reed.
+ *
+ * See the IPFILTER.LICENCE file for details on licencing.
+ *
+ * Id: make_range.c,v 1.2 2002/05/18 07:27:52 darrenr Exp
+ */
+#include "ipf.h"
+
+
+alist_t *make_range(not, a1, a2)
+int not;
+struct in_addr a1, a2;
+{
+ alist_t *a;
+
+ a = (alist_t *)calloc(1, sizeof(*a));
+ if (a != NULL) {
+ a->al_1 = a1.s_addr;
+ a->al_2 = a2.s_addr;
+ a->al_not = not;
+ }
+ return a;
+}
diff --git a/contrib/ipfilter/lib/mutex_emul.c b/contrib/ipfilter/lib/mutex_emul.c
new file mode 100644
index 0000000..43b7f76
--- /dev/null
+++ b/contrib/ipfilter/lib/mutex_emul.c
@@ -0,0 +1,80 @@
+/* $NetBSD$ */
+
+#include "ipf.h"
+
+#define EMM_MAGIC 0x9d7adba3
+
+void eMmutex_enter(mtx, file, line)
+eMmutex_t *mtx;
+char *file;
+int line;
+{
+ if (mtx->eMm_magic != EMM_MAGIC) {
+ fprintf(stderr, "%s:eMmutex_enter(%p): bad magic: %#x\n",
+ mtx->eMm_owner, mtx, mtx->eMm_magic);
+ abort();
+ }
+ if (mtx->eMm_held != 0) {
+ fprintf(stderr, "%s:eMmutex_enter(%p): already locked: %d\n",
+ mtx->eMm_owner, mtx, mtx->eMm_held);
+ abort();
+ }
+ mtx->eMm_held++;
+ mtx->eMm_heldin = file;
+ mtx->eMm_heldat = line;
+}
+
+
+void eMmutex_exit(mtx)
+eMmutex_t *mtx;
+{
+ if (mtx->eMm_magic != EMM_MAGIC) {
+ fprintf(stderr, "%s:eMmutex_exit(%p): bad magic: %#x\n",
+ mtx->eMm_owner, mtx, mtx->eMm_magic);
+ abort();
+ }
+ if (mtx->eMm_held != 1) {
+ fprintf(stderr, "%s:eMmutex_exit(%p): not locked: %d\n",
+ mtx->eMm_owner, mtx, mtx->eMm_held);
+ abort();
+ }
+ mtx->eMm_held--;
+ mtx->eMm_heldin = NULL;
+ mtx->eMm_heldat = 0;
+}
+
+
+void eMmutex_init(mtx, who)
+eMmutex_t *mtx;
+char *who;
+{
+ if (mtx->eMm_magic == EMM_MAGIC) { /* safe bet ? */
+ fprintf(stderr,
+ "%s:eMmutex_init(%p): already initialised?: %#x\n",
+ mtx->eMm_owner, mtx, mtx->eMm_magic);
+ abort();
+ }
+ mtx->eMm_magic = EMM_MAGIC;
+ mtx->eMm_held = 0;
+ if (who != NULL)
+ mtx->eMm_owner = strdup(who);
+ else
+ mtx->eMm_owner = NULL;
+}
+
+
+void eMmutex_destroy(mtx)
+eMmutex_t *mtx;
+{
+ if (mtx->eMm_magic != EMM_MAGIC) {
+ fprintf(stderr, "%s:eMmutex_destroy(%p): bad magic: %#x\n",
+ mtx->eMm_owner, mtx, mtx->eMm_magic);
+ abort();
+ }
+ if (mtx->eMm_held != 0) {
+ fprintf(stderr, "%s:eMmutex_enter(%p): still locked: %d\n",
+ mtx->eMm_owner, mtx, mtx->eMm_held);
+ abort();
+ }
+ memset(mtx, 0xa5, sizeof(*mtx));
+}
diff --git a/contrib/ipfilter/lib/nametokva.c b/contrib/ipfilter/lib/nametokva.c
new file mode 100644
index 0000000..50f3077
--- /dev/null
+++ b/contrib/ipfilter/lib/nametokva.c
@@ -0,0 +1,30 @@
+/* $NetBSD$ */
+
+#include "ipf.h"
+
+#include <sys/ioctl.h>
+#include <fcntl.h>
+
+ipfunc_t nametokva(name, iocfunc)
+char *name;
+ioctlfunc_t iocfunc;
+{
+ ipfunc_resolve_t res;
+ int fd;
+
+ strncpy(res.ipfu_name, name, sizeof(res.ipfu_name));
+ res.ipfu_addr = NULL;
+ fd = -1;
+
+ if ((opts & OPT_DONOTHING) == 0) {
+ fd = open(IPL_NAME, O_RDONLY);
+ if (fd == -1)
+ return NULL;
+ }
+ (void) (*iocfunc)(fd, SIOCFUNCL, &res);
+ if (fd >= 0)
+ close(fd);
+ if (res.ipfu_addr == NULL)
+ res.ipfu_addr = (ipfunc_t)-1;
+ return res.ipfu_addr;
+}
diff --git a/contrib/ipfilter/lib/nat_setgroupmap.c b/contrib/ipfilter/lib/nat_setgroupmap.c
new file mode 100644
index 0000000..ce64abb
--- /dev/null
+++ b/contrib/ipfilter/lib/nat_setgroupmap.c
@@ -0,0 +1,34 @@
+/* $NetBSD$ */
+
+/*
+ * Copyright (C) 1993-2001 by Darren Reed.
+ *
+ * See the IPFILTER.LICENCE file for details on licencing.
+ */
+#if !defined(lint)
+static const char rcsid[] = "@(#)Id: nat_setgroupmap.c,v 1.1 2003/04/13 06:40:14 darrenr Exp";
+#endif
+
+#include "ipf.h"
+
+void nat_setgroupmap(n)
+ipnat_t *n;
+{
+ if (n->in_outmsk == n->in_inmsk)
+ n->in_ippip = 1;
+ else if (n->in_flags & IPN_AUTOPORTMAP) {
+ n->in_ippip = ~ntohl(n->in_inmsk);
+ if (n->in_outmsk != 0xffffffff)
+ n->in_ippip /= (~ntohl(n->in_outmsk) + 1);
+ n->in_ippip++;
+ if (n->in_ippip == 0)
+ n->in_ippip = 1;
+ n->in_ppip = USABLE_PORTS / n->in_ippip;
+ } else {
+ n->in_space = USABLE_PORTS * ~ntohl(n->in_outmsk);
+ n->in_nip = 0;
+ if (!(n->in_ppip = n->in_pmin))
+ n->in_ppip = 1;
+ n->in_ippip = USABLE_PORTS / n->in_ppip;
+ }
+}
diff --git a/contrib/ipfilter/lib/natparse.c b/contrib/ipfilter/lib/natparse.c
new file mode 100644
index 0000000..adbbeb9
--- /dev/null
+++ b/contrib/ipfilter/lib/natparse.c
@@ -0,0 +1,730 @@
+/* $NetBSD$ */
+
+/*
+ * Copyright (C) 1993-2001 by Darren Reed.
+ *
+ * See the IPFILTER.LICENCE file for details on licencing.
+ */
+#if !defined(lint)
+static const char sccsid[] ="@(#)ipnat.c 1.9 6/5/96 (C) 1993 Darren Reed";
+static const char rcsid[] = "@(#)Id: natparse.c,v 1.8.2.1 2004/12/09 19:41:21 darrenr Exp";
+#endif
+
+#include <sys/ioctl.h>
+#include <errno.h>
+#include <ctype.h>
+
+#include "ipf.h"
+#include "opts.h"
+
+
+void nat_setgroupmap(n)
+ipnat_t *n;
+{
+ if (n->in_outmsk == n->in_inmsk)
+ n->in_ippip = 1;
+ else if (n->in_flags & IPN_AUTOPORTMAP) {
+ n->in_ippip = ~ntohl(n->in_inmsk);
+ if (n->in_outmsk != 0xffffffff)
+ n->in_ippip /= (~ntohl(n->in_outmsk) + 1);
+ n->in_ippip++;
+ if (n->in_ippip == 0)
+ n->in_ippip = 1;
+ n->in_ppip = USABLE_PORTS / n->in_ippip;
+ } else {
+ n->in_space = USABLE_PORTS * ~ntohl(n->in_outmsk);
+ n->in_nip = 0;
+ if (!(n->in_ppip = n->in_pmin))
+ n->in_ppip = 1;
+ n->in_ippip = USABLE_PORTS / n->in_ppip;
+ }
+}
+
+
+
+ipnat_t *natparse(line, linenum)
+char *line;
+int linenum;
+{
+ static ipnat_t ipn;
+ struct protoent *pr;
+ char *dnetm = NULL, *dport = NULL, *proto = NULL;
+ char *s, *t, *cps[31], **cpp;
+ int i, cnt;
+
+
+ if ((s = strchr(line, '\n')))
+ *s = '\0';
+ if ((s = strchr(line, '#')))
+ *s = '\0';
+ while (*line && ISSPACE(*line))
+ line++;
+ if (!*line)
+ return NULL;
+
+ bzero((char *)&ipn, sizeof(ipn));
+ cnt = 0;
+
+ for (i = 0, *cps = strtok(line, " \b\t\r\n"); cps[i] && i < 30; cnt++)
+ cps[++i] = strtok(NULL, " \b\t\r\n");
+
+ cps[i] = NULL;
+
+ if (cnt < 3) {
+ fprintf(stderr, "%d: not enough segments in line\n", linenum);
+ return NULL;
+ }
+
+ cpp = cps;
+
+ if (!strcasecmp(*cpp, "map"))
+ ipn.in_redir = NAT_MAP;
+ else if (!strcasecmp(*cpp, "map-block"))
+ ipn.in_redir = NAT_MAPBLK;
+ else if (!strcasecmp(*cpp, "rdr"))
+ ipn.in_redir = NAT_REDIRECT;
+ else if (!strcasecmp(*cpp, "bimap"))
+ ipn.in_redir = NAT_BIMAP;
+ else {
+ fprintf(stderr, "%d: unknown mapping: \"%s\"\n",
+ linenum, *cpp);
+ return NULL;
+ }
+
+ cpp++;
+
+ strncpy(ipn.in_ifnames[0], *cpp, sizeof(ipn.in_ifnames[0]) - 1);
+ ipn.in_ifnames[0][sizeof(ipn.in_ifnames[0]) - 1] = '\0';
+ cpp++;
+
+ if (!strcasecmp(*cpp, "from") || (**cpp == '!')) {
+ if (!strcmp(*cpp, "!")) {
+ cpp++;
+ if (strcasecmp(*cpp, "from")) {
+ fprintf(stderr, "Missing from after !\n");
+ return NULL;
+ }
+ ipn.in_flags |= IPN_NOTSRC;
+ } else if (**cpp == '!') {
+ if (strcasecmp(*cpp + 1, "from")) {
+ fprintf(stderr, "Missing from after !\n");
+ return NULL;
+ }
+ ipn.in_flags |= IPN_NOTSRC;
+ }
+ if ((ipn.in_flags & IPN_NOTSRC) &&
+ (ipn.in_redir & (NAT_MAP|NAT_MAPBLK))) {
+ fprintf(stderr, "Cannot use '! from' with map\n");
+ return NULL;
+ }
+
+ ipn.in_flags |= IPN_FILTER;
+ cpp++;
+ if (ipn.in_redir == NAT_REDIRECT) {
+ if (hostmask(&cpp, proto, NULL,
+ (u_32_t *)&ipn.in_srcip,
+ (u_32_t *)&ipn.in_srcmsk, linenum) == -1)
+ return NULL;
+
+ if (ports(&cpp, proto, &ipn.in_sport,
+ &ipn.in_scmp, &ipn.in_stop, linenum))
+ return NULL;
+ } else {
+ if (hostmask(&cpp, proto, NULL,
+ (u_32_t *)&ipn.in_inip,
+ (u_32_t *)&ipn.in_inmsk, linenum) == -1)
+ return NULL;
+
+ if (ports(&cpp, proto, &ipn.in_dport,
+ &ipn.in_dcmp, &ipn.in_dtop, linenum))
+ return NULL;
+ }
+
+ if (!strcmp(*cpp, "!")) {
+ cpp++;
+ ipn.in_flags |= IPN_NOTDST;
+ } else if (**cpp == '!') {
+ (*cpp)++;
+ ipn.in_flags |= IPN_NOTDST;
+ }
+
+ if (strcasecmp(*cpp, "to")) {
+ fprintf(stderr, "%d: unexpected keyword (%s) - to\n",
+ linenum, *cpp);
+ return NULL;
+ }
+ if ((ipn.in_flags & IPN_NOTDST) &&
+ (ipn.in_redir & (NAT_REDIRECT))) {
+ fprintf(stderr, "Cannot use '! to' with rdr\n");
+ return NULL;
+ }
+
+ if (!*++cpp) {
+ fprintf(stderr, "%d: missing host after to\n", linenum);
+ return NULL;
+ }
+ if (ipn.in_redir == NAT_REDIRECT) {
+ if (hostmask(&cpp, proto, NULL,
+ (u_32_t *)&ipn.in_outip,
+ (u_32_t *)&ipn.in_outmsk, linenum))
+ return NULL;
+
+ if (ports(&cpp, proto, &ipn.in_dport,
+ &ipn.in_dcmp, &ipn.in_dtop, linenum))
+ return NULL;
+ ipn.in_pmin = htons(ipn.in_dport);
+ } else {
+ if (hostmask(&cpp, proto, NULL,
+ (u_32_t *)&ipn.in_srcip,
+ (u_32_t *)&ipn.in_srcmsk, linenum))
+ return NULL;
+
+ if (ports(&cpp, proto, &ipn.in_sport,
+ &ipn.in_scmp, &ipn.in_stop, linenum))
+ return NULL;
+ }
+ } else {
+ s = *cpp;
+ if (!s)
+ return NULL;
+ t = strchr(s, '/');
+ if (!t)
+ return NULL;
+ *t++ = '\0';
+ if (ipn.in_redir == NAT_REDIRECT) {
+ if (hostnum((u_32_t *)&ipn.in_outip, s, linenum, NULL))
+ return NULL;
+ if (genmask(t, (u_32_t *)&ipn.in_outmsk) == -1) {
+ return NULL;
+ }
+ } else {
+ if (hostnum((u_32_t *)&ipn.in_inip, s, linenum, NULL))
+ return NULL;
+ if (genmask(t, (u_32_t *)&ipn.in_inmsk) == -1) {
+ return NULL;
+ }
+ }
+ cpp++;
+ if (!*cpp)
+ return NULL;
+ }
+
+ if ((ipn.in_redir == NAT_REDIRECT) && !(ipn.in_flags & IPN_FILTER)) {
+ if (strcasecmp(*cpp, "port")) {
+ fprintf(stderr, "%d: missing fields - 1st port\n",
+ linenum);
+ return NULL;
+ }
+
+ cpp++;
+
+ if (!*cpp) {
+ fprintf(stderr,
+ "%d: missing fields (destination port)\n",
+ linenum);
+ return NULL;
+ }
+
+ if (ISDIGIT(**cpp) && (s = strchr(*cpp, '-')))
+ *s++ = '\0';
+ else
+ s = NULL;
+
+ if (!portnum(*cpp, proto, &ipn.in_pmin, linenum))
+ return NULL;
+ ipn.in_pmin = htons(ipn.in_pmin);
+ cpp++;
+
+ if (!strcmp(*cpp, "-")) {
+ cpp++;
+ s = *cpp++;
+ }
+
+ if (s) {
+ if (!portnum(s, proto, &ipn.in_pmax, linenum))
+ return NULL;
+ ipn.in_pmax = htons(ipn.in_pmax);
+ } else
+ ipn.in_pmax = ipn.in_pmin;
+ }
+
+ if (!*cpp) {
+ fprintf(stderr, "%d: missing fields (->)\n", linenum);
+ return NULL;
+ }
+ if (strcmp(*cpp, "->")) {
+ fprintf(stderr, "%d: missing ->\n", linenum);
+ return NULL;
+ }
+ cpp++;
+
+ if (!*cpp) {
+ fprintf(stderr, "%d: missing fields (%s)\n",
+ linenum, ipn.in_redir ? "destination" : "target");
+ return NULL;
+ }
+
+ if (ipn.in_redir == NAT_MAP) {
+ if (!strcasecmp(*cpp, "range")) {
+ cpp++;
+ ipn.in_flags |= IPN_IPRANGE;
+ if (!*cpp) {
+ fprintf(stderr, "%d: missing fields (%s)\n",
+ linenum,
+ ipn.in_redir ? "destination":"target");
+ return NULL;
+ }
+ }
+ }
+
+ if (ipn.in_flags & IPN_IPRANGE) {
+ dnetm = strrchr(*cpp, '-');
+ if (dnetm == NULL) {
+ cpp++;
+ if (*cpp && !strcmp(*cpp, "-") && *(cpp + 1))
+ dnetm = *(cpp + 1);
+ } else
+ *dnetm++ = '\0';
+ if (dnetm == NULL || *dnetm == '\0') {
+ fprintf(stderr,
+ "%d: desination range not specified\n",
+ linenum);
+ return NULL;
+ }
+ } else if (ipn.in_redir != NAT_REDIRECT) {
+ dnetm = strrchr(*cpp, '/');
+ if (dnetm == NULL) {
+ cpp++;
+ if (*cpp && !strcasecmp(*cpp, "netmask"))
+ dnetm = *++cpp;
+ }
+ if (dnetm == NULL) {
+ fprintf(stderr,
+ "%d: missing fields (dest netmask)\n",
+ linenum);
+ return NULL;
+ }
+ if (*dnetm == '/')
+ *dnetm++ = '\0';
+ }
+
+ if (ipn.in_redir == NAT_REDIRECT) {
+ dnetm = strchr(*cpp, ',');
+ if (dnetm != NULL) {
+ ipn.in_flags |= IPN_SPLIT;
+ *dnetm++ = '\0';
+ }
+ if (hostnum((u_32_t *)&ipn.in_inip, *cpp, linenum, NULL))
+ return NULL;
+ } else {
+ if (hostnum((u_32_t *)&ipn.in_outip, *cpp, linenum, NULL))
+ return NULL;
+ }
+ cpp++;
+
+ if (ipn.in_redir & NAT_MAPBLK) {
+ if (*cpp && strcasecmp(*cpp, "ports")) {
+ fprintf(stderr,
+ "%d: expected \"ports\" - got \"%s\"\n",
+ linenum, *cpp);
+ return NULL;
+ }
+ cpp++;
+ if (*cpp) {
+ ipn.in_pmin = atoi(*cpp);
+ cpp++;
+ } else
+ ipn.in_pmin = 0;
+ } else if ((ipn.in_redir & NAT_BIMAP) == NAT_REDIRECT) {
+ if (*cpp && strrchr(*cpp, '/') != NULL) {
+ fprintf(stderr, "%d: No netmask supported in %s\n",
+ linenum, "destination host for redirect");
+ return NULL;
+ }
+ /* If it's a in_redir, expect target port */
+
+ if (!*cpp || strcasecmp(*cpp, "port")) {
+ fprintf(stderr, "%d: missing fields - 2nd port (%s)\n",
+ linenum, *cpp);
+ return NULL;
+ }
+ cpp++;
+ if (!*cpp) {
+ fprintf(stderr,
+ "%d: missing fields (destination port)\n",
+ linenum);
+ return NULL;
+ }
+ if (!portnum(*cpp, proto, &ipn.in_pnext, linenum))
+ return NULL;
+ ipn.in_pnext = htons(ipn.in_pnext);
+ cpp++;
+ }
+ if (dnetm && *dnetm == '/')
+ *dnetm++ = '\0';
+
+ if (ipn.in_redir & (NAT_MAP|NAT_MAPBLK)) {
+ if (ipn.in_flags & IPN_IPRANGE) {
+ if (hostnum((u_32_t *)&ipn.in_outmsk, dnetm,
+ linenum, NULL) == -1)
+ return NULL;
+ } else if (genmask(dnetm, (u_32_t *)&ipn.in_outmsk))
+ return NULL;
+ } else {
+ if (ipn.in_flags & IPN_SPLIT) {
+ if (hostnum((u_32_t *)&ipn.in_inmsk, dnetm,
+ linenum, NULL) == -1)
+ return NULL;
+ } else if (genmask("255.255.255.255", (u_32_t *)&ipn.in_inmsk))
+ return NULL;
+ if (!*cpp) {
+ ipn.in_flags |= IPN_TCP; /* XXX- TCP only by default */
+ proto = "tcp";
+ } else {
+ if (!strcasecmp(*cpp, "tcp"))
+ ipn.in_flags |= IPN_TCP;
+ else if (!strcasecmp(*cpp, "udp"))
+ ipn.in_flags |= IPN_UDP;
+ else if (!strcasecmp(*cpp, "tcp/udp"))
+ ipn.in_flags |= IPN_TCPUDP;
+ else if (!strcasecmp(*cpp, "tcpudp"))
+ ipn.in_flags |= IPN_TCPUDP;
+ else if (!strcasecmp(*cpp, "ip"))
+ ipn.in_flags |= IPN_ANY;
+ else {
+ ipn.in_flags |= IPN_ANY;
+ ipn.in_p = getproto(*cpp);
+ }
+ proto = *cpp;
+ cpp++;
+
+ if (*cpp && !strcasecmp(*cpp, "round-robin")) {
+ cpp++;
+ ipn.in_flags |= IPN_ROUNDR;
+ }
+
+ if (*cpp && !strcasecmp(*cpp, "frag")) {
+ cpp++;
+ ipn.in_flags |= IPN_FRAG;
+ }
+
+ if (*cpp && !strcasecmp(*cpp, "age")) {
+ cpp++;
+ if (!*cpp) {
+ fprintf(stderr,
+ "%d: age with no parameters\n",
+ linenum);
+ return NULL;
+ }
+
+ ipn.in_age[0] = atoi(*cpp);
+ s = strchr(*cpp, '/');
+ if (s != NULL)
+ ipn.in_age[1] = atoi(s + 1);
+ else
+ ipn.in_age[1] = ipn.in_age[0];
+ cpp++;
+ }
+
+ if (*cpp && !strcasecmp(*cpp, "mssclamp")) {
+ cpp++;
+ if (*cpp) {
+ ipn.in_mssclamp = atoi(*cpp);
+ cpp++;
+ } else {
+ fprintf(stderr,
+ "%d: mssclamp with no parameters\n",
+ linenum);
+ return NULL;
+ }
+ }
+
+ if (*cpp) {
+ fprintf(stderr,
+ "%d: extra junk at the end of rdr: %s\n",
+ linenum, *cpp);
+ return NULL;
+ }
+ }
+ }
+
+ if (!(ipn.in_flags & IPN_SPLIT))
+ ipn.in_inip &= ipn.in_inmsk;
+ if ((ipn.in_flags & IPN_IPRANGE) == 0)
+ ipn.in_outip &= ipn.in_outmsk;
+ ipn.in_srcip &= ipn.in_srcmsk;
+
+ if ((ipn.in_redir & NAT_MAPBLK) != 0)
+ nat_setgroupmap(&ipn);
+
+ if (*cpp && !strcasecmp(*cpp, "frag")) {
+ cpp++;
+ ipn.in_flags |= IPN_ROUNDR;
+ }
+
+ if (!*cpp)
+ return &ipn;
+
+ if (ipn.in_redir != NAT_BIMAP && !strcasecmp(*cpp, "proxy")) {
+ if (ipn.in_redir == NAT_BIMAP) {
+ fprintf(stderr, "%d: cannot use proxy with bimap\n",
+ linenum);
+ return NULL;
+ }
+
+ cpp++;
+ if (!*cpp) {
+ fprintf(stderr,
+ "%d: missing parameter for \"proxy\"\n",
+ linenum);
+ return NULL;
+ }
+ dport = NULL;
+
+ if (!strcasecmp(*cpp, "port")) {
+ cpp++;
+ if (!*cpp) {
+ fprintf(stderr,
+ "%d: missing parameter for \"port\"\n",
+ linenum);
+ return NULL;
+ }
+
+ dport = *cpp;
+ cpp++;
+
+ if (!*cpp) {
+ fprintf(stderr,
+ "%d: missing parameter for \"proxy\"\n",
+ linenum);
+ return NULL;
+ }
+ } else {
+ fprintf(stderr,
+ "%d: missing keyword \"port\"\n", linenum);
+ return NULL;
+ }
+
+ if ((proto = strchr(*cpp, '/'))) {
+ *proto++ = '\0';
+ ipn.in_p = getproto(proto);
+ } else
+ ipn.in_p = 0;
+
+ if (dport && !portnum(dport, proto, &ipn.in_dport, linenum))
+ return NULL;
+ ipn.in_dport = htons(ipn.in_dport);
+
+ (void) strncpy(ipn.in_plabel, *cpp, sizeof(ipn.in_plabel));
+ cpp++;
+
+ if (*cpp) {
+ fprintf(stderr,
+ "%d: too many parameters for \"proxy\"\n",
+ linenum);
+ return NULL;
+ }
+ return &ipn;
+ }
+
+
+ if (!strcasecmp(*cpp, "icmpidmap")) {
+
+ cpp++;
+ if (!*cpp) {
+ fprintf(stderr,
+ "%d: icmpidmap misses protocol and range\n",
+ linenum);
+ return NULL;
+ };
+
+ if (!strcasecmp(*cpp, "icmp"))
+ ipn.in_flags = IPN_ICMPQUERY;
+ else {
+ fprintf(stderr, "%d: icmpidmap only valid for icmp\n",
+ linenum);
+ return NULL;
+ }
+ cpp++;
+
+ if (!*cpp) {
+ fprintf(stderr, "%d: no icmp id argument found\n",
+ linenum);
+ return NULL;
+ }
+
+ if (!(t = strchr(*cpp, ':'))) {
+ fprintf(stderr,
+ "%d: no icmp id range detected in \"%s\"\n",
+ linenum, *cpp);
+ return NULL;
+ }
+ *t++ = '\0';
+
+ if (!icmpidnum(*cpp, &ipn.in_pmin, linenum) ||
+ !icmpidnum(t, &ipn.in_pmax, linenum))
+ return NULL;
+ } else if (!strcasecmp(*cpp, "portmap")) {
+ if (ipn.in_redir == NAT_BIMAP) {
+ fprintf(stderr, "%d: cannot use proxy with bimap\n",
+ linenum);
+ return NULL;
+ }
+ cpp++;
+ if (!*cpp) {
+ fprintf(stderr,
+ "%d: missing expression following portmap\n",
+ linenum);
+ return NULL;
+ }
+
+ if (!strcasecmp(*cpp, "tcp"))
+ ipn.in_flags |= IPN_TCP;
+ else if (!strcasecmp(*cpp, "udp"))
+ ipn.in_flags |= IPN_UDP;
+ else if (!strcasecmp(*cpp, "tcpudp"))
+ ipn.in_flags |= IPN_TCPUDP;
+ else if (!strcasecmp(*cpp, "tcp/udp"))
+ ipn.in_flags |= IPN_TCPUDP;
+ else {
+ fprintf(stderr,
+ "%d: expected protocol name - got \"%s\"\n",
+ linenum, *cpp);
+ return NULL;
+ }
+ proto = *cpp;
+ cpp++;
+
+ if (!*cpp) {
+ fprintf(stderr, "%d: no port range found\n", linenum);
+ return NULL;
+ }
+
+ if (!strcasecmp(*cpp, "auto")) {
+ ipn.in_flags |= IPN_AUTOPORTMAP;
+ ipn.in_pmin = htons(1024);
+ ipn.in_pmax = htons(65535);
+ nat_setgroupmap(&ipn);
+ } else {
+ if (!(t = strchr(*cpp, ':'))) {
+ fprintf(stderr,
+ "%d: no port range in \"%s\"\n",
+ linenum, *cpp);
+ return NULL;
+ }
+ *t++ = '\0';
+ if (!portnum(*cpp, proto, &ipn.in_pmin, linenum) ||
+ !portnum(t, proto, &ipn.in_pmax, linenum))
+ return NULL;
+ }
+ cpp++;
+ }
+
+ if (*cpp && !strcasecmp(*cpp, "round-robin")) {
+ cpp++;
+ ipn.in_flags |= IPN_ROUNDR;
+ }
+
+ if (*cpp && !strcasecmp(*cpp, "age")) {
+ cpp++;
+ if (!*cpp) {
+ fprintf(stderr, "%d: age with no parameters\n",
+ linenum);
+ return NULL;
+ }
+ s = strchr(*cpp, '/');
+ if (s != NULL)
+ ipn.in_age[1] = atoi(s + 1);
+ else
+ ipn.in_age[1] = ipn.in_age[0];
+ cpp++;
+ }
+
+ if (*cpp && !strcasecmp(*cpp, "mssclamp")) {
+ cpp++;
+ if (*cpp) {
+ ipn.in_mssclamp = atoi(*cpp);
+ cpp++;
+ } else {
+ fprintf(stderr, "%d: mssclamp with no parameters\n",
+ linenum);
+ return NULL;
+ }
+ }
+
+ if (*cpp) {
+ fprintf(stderr, "%d: extra junk at the end of the line: %s\n",
+ linenum, *cpp);
+ return NULL;
+ }
+
+ ipn.in_pmin = htons(ipn.in_pmin);
+ ipn.in_pmax = htons(ipn.in_pmax);
+ return &ipn;
+}
+
+
+void natparsefile(fd, file, opts)
+int fd;
+char *file;
+int opts;
+{
+ char line[512], *s;
+ ipnat_t *np;
+ FILE *fp;
+ int linenum = 0;
+
+ if (strcmp(file, "-")) {
+ if (!(fp = fopen(file, "r"))) {
+ fprintf(stderr, "%s: open: %s\n", file,
+ STRERROR(errno));
+ exit(1);
+ }
+ } else
+ fp = stdin;
+
+ while (getline(line, sizeof(line) - 1, fp, &linenum)) {
+ line[sizeof(line) - 1] = '\0';
+ if ((s = strchr(line, '\n')))
+ *s = '\0';
+
+ if (!(np = natparse(line, linenum))) {
+ if (*line)
+ fprintf(stderr, "%d: syntax error in \"%s\"\n",
+ linenum, line);
+ } else {
+ if ((opts & OPT_VERBOSE) && np)
+ printnat(np, opts);
+ if (!(opts & OPT_DONOTHING)) {
+ if (!(opts & OPT_REMOVE)) {
+ if (ioctl(fd, SIOCADNAT, &np) == -1)
+ perror("ioctl(SIOCADNAT)");
+ } else if (ioctl(fd, SIOCRMNAT, &np) == -1)
+ perror("ioctl(SIOCRMNAT)");
+ }
+ }
+ }
+ if (fp != stdin)
+ fclose(fp);
+}
+
+
+int icmpidnum(str, id, linenum)
+char *str;
+u_short *id;
+int linenum;
+{
+ int i;
+
+
+ i = atoi(str);
+
+ if ((i<0) || (i>65535)) {
+ fprintf(stderr, "%d: invalid icmp id\"%s\".\n", linenum, str);
+ return 0;
+ }
+
+ *id = (u_short)i;
+
+ return 1;
+}
diff --git a/contrib/ipfilter/lib/ntomask.c b/contrib/ipfilter/lib/ntomask.c
new file mode 100644
index 0000000..415a5e8
--- /dev/null
+++ b/contrib/ipfilter/lib/ntomask.c
@@ -0,0 +1,38 @@
+/* $NetBSD$ */
+
+#include "ipf.h"
+
+int ntomask(v, nbits, ap)
+int v, nbits;
+u_32_t *ap;
+{
+ u_32_t mask;
+
+ if (nbits < 0)
+ return -1;
+
+ switch (v)
+ {
+ case 4 :
+ if (nbits > 32 || use_inet6 != 0)
+ return -1;
+ if (nbits == 0) {
+ mask = 0;
+ } else {
+ mask = 0xffffffff;
+ mask <<= (32 - nbits);
+ }
+ *ap = htonl(mask);
+ break;
+
+ case 6 :
+ if ((nbits > 128) || (use_inet6 == 0))
+ return -1;
+ fill6bits(nbits, ap);
+ break;
+
+ default :
+ return -1;
+ }
+ return 0;
+}
diff --git a/contrib/ipfilter/lib/optname.c b/contrib/ipfilter/lib/optname.c
new file mode 100644
index 0000000..7fdcc57
--- /dev/null
+++ b/contrib/ipfilter/lib/optname.c
@@ -0,0 +1,65 @@
+/* $NetBSD$ */
+
+/*
+ * Copyright (C) 1993-2001 by Darren Reed.
+ *
+ * See the IPFILTER.LICENCE file for details on licencing.
+ *
+ * Id: optname.c,v 1.3 2001/06/09 17:09:24 darrenr Exp
+ */
+
+#include "ipf.h"
+
+
+u_32_t optname(cp, sp, linenum)
+char ***cp;
+u_short *sp;
+int linenum;
+{
+ struct ipopt_names *io, *so;
+ u_long msk = 0;
+ u_short smsk = 0;
+ char *s;
+ int sec = 0;
+
+ for (s = strtok(**cp, ","); s; s = strtok(NULL, ",")) {
+ for (io = ionames; io->on_name; io++)
+ if (!strcasecmp(s, io->on_name)) {
+ msk |= io->on_bit;
+ break;
+ }
+ if (!io->on_name) {
+ fprintf(stderr, "%d: unknown IP option name %s\n",
+ linenum, s);
+ return 0;
+ }
+ if (!strcasecmp(s, "sec-class"))
+ sec = 1;
+ }
+
+ if (sec && !*(*cp + 1)) {
+ fprintf(stderr, "%d: missing security level after sec-class\n",
+ linenum);
+ return 0;
+ }
+
+ if (sec) {
+ (*cp)++;
+ for (s = strtok(**cp, ","); s; s = strtok(NULL, ",")) {
+ for (so = secclass; so->on_name; so++)
+ if (!strcasecmp(s, so->on_name)) {
+ smsk |= so->on_bit;
+ break;
+ }
+ if (!so->on_name) {
+ fprintf(stderr,
+ "%d: no such security level: %s\n",
+ linenum, s);
+ return 0;
+ }
+ }
+ if (smsk)
+ *sp = smsk;
+ }
+ return msk;
+}
diff --git a/contrib/ipfilter/lib/optprint.c b/contrib/ipfilter/lib/optprint.c
new file mode 100644
index 0000000..261a75c
--- /dev/null
+++ b/contrib/ipfilter/lib/optprint.c
@@ -0,0 +1,79 @@
+/* $NetBSD$ */
+
+/*
+ * Copyright (C) 1993-2001 by Darren Reed.
+ *
+ * See the IPFILTER.LICENCE file for details on licencing.
+ *
+ * Id: optprint.c,v 1.6 2002/07/13 15:59:49 darrenr Exp
+ */
+#include "ipf.h"
+
+
+void optprint(sec, optmsk, optbits)
+u_short *sec;
+u_long optmsk, optbits;
+{
+ u_short secmsk = sec[0], secbits = sec[1];
+ struct ipopt_names *io, *so;
+ char *s;
+
+ s = " opt ";
+ for (io = ionames; io->on_name; io++)
+ if ((io->on_bit & optmsk) &&
+ ((io->on_bit & optmsk) == (io->on_bit & optbits))) {
+ if ((io->on_value != IPOPT_SECURITY) ||
+ (!secmsk && !secbits)) {
+ printf("%s%s", s, io->on_name);
+ if (io->on_value == IPOPT_SECURITY)
+ io++;
+ s = ",";
+ }
+ }
+
+
+ if (secmsk & secbits) {
+ printf("%ssec-class", s);
+ s = " ";
+ for (so = secclass; so->on_name; so++)
+ if ((secmsk & so->on_bit) &&
+ ((so->on_bit & secmsk) == (so->on_bit & secbits))) {
+ printf("%s%s", s, so->on_name);
+ s = ",";
+ }
+ }
+
+ if ((optmsk && (optmsk != optbits)) ||
+ (secmsk && (secmsk != secbits))) {
+ s = " ";
+ printf(" not opt");
+ if (optmsk != optbits) {
+ for (io = ionames; io->on_name; io++)
+ if ((io->on_bit & optmsk) &&
+ ((io->on_bit & optmsk) !=
+ (io->on_bit & optbits))) {
+ if ((io->on_value != IPOPT_SECURITY) ||
+ (!secmsk && !secbits)) {
+ printf("%s%s", s, io->on_name);
+ s = ",";
+ if (io->on_value ==
+ IPOPT_SECURITY)
+ io++;
+ } else
+ io++;
+ }
+ }
+
+ if (secmsk != secbits) {
+ printf("%ssec-class", s);
+ s = " ";
+ for (so = secclass; so->on_name; so++)
+ if ((so->on_bit & secmsk) &&
+ ((so->on_bit & secmsk) !=
+ (so->on_bit & secbits))) {
+ printf("%s%s", s, so->on_name);
+ s = ",";
+ }
+ }
+ }
+}
diff --git a/contrib/ipfilter/lib/optprintv6.c b/contrib/ipfilter/lib/optprintv6.c
new file mode 100644
index 0000000..75e0fd0
--- /dev/null
+++ b/contrib/ipfilter/lib/optprintv6.c
@@ -0,0 +1,47 @@
+/* $NetBSD$ */
+
+/*
+ * Copyright (C) 1993-2001 by Darren Reed.
+ *
+ * See the IPFILTER.LICENCE file for details on licencing.
+ *
+ * Id: optprintv6.c,v 1.2 2003/04/30 00:39:39 darrenr Exp
+ */
+#include "ipf.h"
+
+
+#ifdef USE_INET6
+
+void optprintv6(sec, optmsk, optbits)
+u_short *sec;
+u_long optmsk, optbits;
+{
+ u_short secmsk = sec[0], secbits = sec[1];
+ struct ipopt_names *io;
+ char *s;
+
+ s = " v6hdrs ";
+ for (io = v6ionames; io->on_name; io++)
+ if ((io->on_bit & optmsk) &&
+ ((io->on_bit & optmsk) == (io->on_bit & optbits))) {
+ printf("%s%s", s, io->on_name);
+ s = ",";
+ }
+
+ if ((optmsk && (optmsk != optbits)) ||
+ (secmsk && (secmsk != secbits))) {
+ s = " ";
+ printf(" not v6hdrs");
+ if (optmsk != optbits) {
+ for (io = v6ionames; io->on_name; io++)
+ if ((io->on_bit & optmsk) &&
+ ((io->on_bit & optmsk) !=
+ (io->on_bit & optbits))) {
+ printf("%s%s", s, io->on_name);
+ s = ",";
+ }
+ }
+
+ }
+}
+#endif
diff --git a/contrib/ipfilter/lib/optvalue.c b/contrib/ipfilter/lib/optvalue.c
new file mode 100644
index 0000000..dc9448d
--- /dev/null
+++ b/contrib/ipfilter/lib/optvalue.c
@@ -0,0 +1,34 @@
+/* $NetBSD$ */
+
+/*
+ * Copyright (C) 1993-2001 by Darren Reed.
+ *
+ * See the IPFILTER.LICENCE file for details on licencing.
+ *
+ * Id: optvalue.c,v 1.2 2002/01/28 06:50:47 darrenr Exp
+ */
+#include "ipf.h"
+
+
+u_32_t getoptbyname(optname)
+char *optname;
+{
+ struct ipopt_names *io;
+
+ for (io = ionames; io->on_name; io++)
+ if (!strcasecmp(optname, io->on_name))
+ return io->on_bit;
+ return -1;
+}
+
+
+u_32_t getoptbyvalue(optval)
+int optval;
+{
+ struct ipopt_names *io;
+
+ for (io = ionames; io->on_name; io++)
+ if (io->on_value == optval)
+ return io->on_bit;
+ return -1;
+}
diff --git a/contrib/ipfilter/lib/parse.c b/contrib/ipfilter/lib/parse.c
new file mode 100644
index 0000000..4cf69ab
--- /dev/null
+++ b/contrib/ipfilter/lib/parse.c
@@ -0,0 +1,754 @@
+/* $NetBSD$ */
+
+/*
+ * Copyright (C) 1993-2001 by Darren Reed.
+ *
+ * See the IPFILTER.LICENCE file for details on licencing.
+ *
+ * Id: parse.c,v 1.34.2.1 2004/12/09 19:41:21 darrenr Exp
+ */
+#include <ctype.h>
+#include "ipf.h"
+#include "opts.h"
+
+static frentry_t *fp = NULL;
+
+/* parse()
+ *
+ * parse a line read from the input filter rule file
+ */
+struct frentry *parse(line, linenum)
+char *line;
+int linenum;
+{
+ static fripf_t fip;
+ char *cps[31], **cpp, *endptr, *proto = NULL, *s;
+ struct protoent *p = NULL;
+ int i, cnt = 1, j;
+ u_int k;
+
+ if (fp == NULL) {
+ fp = malloc(sizeof(*fp));
+ if (fp == NULL)
+ return NULL;
+ }
+
+ while (*line && ISSPACE(*line))
+ line++;
+ if (!*line)
+ return NULL;
+
+ bzero((char *)fp, sizeof(*fp));
+ bzero((char *)&fip, sizeof(fip));
+ fp->fr_v = use_inet6 ? 6 : 4;
+ fp->fr_ipf = &fip;
+ fp->fr_dsize = sizeof(fip);
+ fp->fr_ip.fi_v = fp->fr_v;
+ fp->fr_mip.fi_v = 0xf;
+ fp->fr_type = FR_T_NONE;
+ fp->fr_loglevel = 0xffff;
+ fp->fr_isc = (void *)-1;
+ fp->fr_tag = FR_NOTAG;
+
+ /*
+ * break line up into max of 20 segments
+ */
+ if (opts & OPT_DEBUG)
+ fprintf(stderr, "parse [%s]\n", line);
+ for (i = 0, *cps = strtok(line, " \b\t\r\n"); cps[i] && i < 30; cnt++)
+ cps[++i] = strtok(NULL, " \b\t\r\n");
+ cps[i] = NULL;
+
+ if (cnt < 3) {
+ fprintf(stderr, "%d: not enough segments in line\n", linenum);
+ return NULL;
+ }
+
+ cpp = cps;
+ /*
+ * The presence of an '@' followed by a number gives the position in
+ * the current rule list to insert this one.
+ */
+ if (**cpp == '@')
+ fp->fr_hits = (U_QUAD_T)atoi(*cpp++ + 1) + 1;
+
+ /*
+ * Check the first keyword in the rule and any options that are
+ * expected to follow it.
+ */
+ if (!strcasecmp("block", *cpp)) {
+ fp->fr_flags |= FR_BLOCK;
+ if (!strncasecmp(*(cpp+1), "return-icmp-as-dest", 19) &&
+ (i = 19))
+ fp->fr_flags |= FR_FAKEICMP;
+ else if (!strncasecmp(*(cpp+1), "return-icmp", 11) && (i = 11))
+ fp->fr_flags |= FR_RETICMP;
+ if (fp->fr_flags & FR_RETICMP) {
+ cpp++;
+ if (strlen(*cpp) == i) {
+ if (*(cpp + 1) && **(cpp +1) == '(') {
+ cpp++;
+ i = 0;
+ } else
+ i = -1;
+ }
+
+ /*
+ * The ICMP code is not required to follow in ()'s
+ */
+ if ((i >= 0) && (*(*cpp + i) == '(')) {
+ i++;
+ j = icmpcode(*cpp + i);
+ if (j == -1) {
+ fprintf(stderr,
+ "%d: unrecognised icmp code %s\n",
+ linenum, *cpp + 20);
+ return NULL;
+ }
+ fp->fr_icode = j;
+ }
+ } else if (!strncasecmp(*(cpp+1), "return-rst", 10)) {
+ fp->fr_flags |= FR_RETRST;
+ cpp++;
+ }
+ } else if (!strcasecmp("count", *cpp)) {
+ fp->fr_flags |= FR_ACCOUNT;
+ } else if (!strcasecmp("pass", *cpp)) {
+ fp->fr_flags |= FR_PASS;
+ } else if (!strcasecmp("auth", *cpp)) {
+ fp->fr_flags |= FR_AUTH;
+ } else if (fp->fr_arg != 0) {
+ printf("skip %u", fp->fr_arg);
+ } else if (!strcasecmp("preauth", *cpp)) {
+ fp->fr_flags |= FR_PREAUTH;
+ } else if (!strcasecmp("nomatch", *cpp)) {
+ fp->fr_flags |= FR_NOMATCH;
+ } else if (!strcasecmp("skip", *cpp)) {
+ cpp++;
+ if (ratoui(*cpp, &k, 0, UINT_MAX))
+ fp->fr_arg = k;
+ else {
+ fprintf(stderr, "%d: integer must follow skip\n",
+ linenum);
+ return NULL;
+ }
+ } else if (!strcasecmp("log", *cpp)) {
+ fp->fr_flags |= FR_LOG;
+ if (!strcasecmp(*(cpp+1), "body")) {
+ fp->fr_flags |= FR_LOGBODY;
+ cpp++;
+ }
+ if (!strcasecmp(*(cpp+1), "first")) {
+ fp->fr_flags |= FR_LOGFIRST;
+ cpp++;
+ }
+ if (*cpp && !strcasecmp(*(cpp+1), "or-block")) {
+ fp->fr_flags |= FR_LOGORBLOCK;
+ cpp++;
+ }
+ if (!strcasecmp(*(cpp+1), "level")) {
+ cpp++;
+ if (loglevel(cpp, &fp->fr_loglevel, linenum) == -1)
+ return NULL;
+ cpp++;
+ }
+ } else {
+ /*
+ * Doesn't start with one of the action words
+ */
+ fprintf(stderr, "%d: unknown keyword (%s)\n", linenum, *cpp);
+ return NULL;
+ }
+ if (!*++cpp) {
+ fprintf(stderr, "%d: missing 'in'/'out' keyword\n", linenum);
+ return NULL;
+ }
+
+ /*
+ * Get the direction for filtering. Impose restrictions on direction
+ * if blocking with returning ICMP or an RST has been requested.
+ */
+ if (!strcasecmp("in", *cpp))
+ fp->fr_flags |= FR_INQUE;
+ else if (!strcasecmp("out", *cpp)) {
+ fp->fr_flags |= FR_OUTQUE;
+ if (fp->fr_flags & FR_RETICMP) {
+ fprintf(stderr,
+ "%d: Can only use return-icmp with 'in'\n",
+ linenum);
+ return NULL;
+ } else if (fp->fr_flags & FR_RETRST) {
+ fprintf(stderr,
+ "%d: Can only use return-rst with 'in'\n",
+ linenum);
+ return NULL;
+ }
+ }
+ if (!*++cpp) {
+ fprintf(stderr, "%d: missing source specification\n", linenum);
+ return NULL;
+ }
+
+ if (!strcasecmp("log", *cpp)) {
+ if (!*++cpp) {
+ fprintf(stderr, "%d: missing source specification\n",
+ linenum);
+ return NULL;
+ }
+ if (FR_ISPASS(fp->fr_flags))
+ fp->fr_flags |= FR_LOGP;
+ else if (FR_ISBLOCK(fp->fr_flags))
+ fp->fr_flags |= FR_LOGB;
+ if (*cpp && !strcasecmp(*cpp, "body")) {
+ fp->fr_flags |= FR_LOGBODY;
+ cpp++;
+ }
+ if (*cpp && !strcasecmp(*cpp, "first")) {
+ fp->fr_flags |= FR_LOGFIRST;
+ cpp++;
+ }
+ if (*cpp && !strcasecmp(*cpp, "or-block")) {
+ if (!FR_ISPASS(fp->fr_flags)) {
+ fprintf(stderr,
+ "%d: or-block must be used with pass\n",
+ linenum);
+ return NULL;
+ }
+ fp->fr_flags |= FR_LOGORBLOCK;
+ cpp++;
+ }
+ if (*cpp && !strcasecmp(*cpp, "level")) {
+ if (loglevel(cpp, &fp->fr_loglevel, linenum) == -1)
+ return NULL;
+ cpp++;
+ cpp++;
+ }
+ }
+
+ if (*cpp && !strcasecmp("quick", *cpp)) {
+ if (fp->fr_arg != 0) {
+ fprintf(stderr, "%d: cannot use skip with quick\n",
+ linenum);
+ return NULL;
+ }
+ cpp++;
+ fp->fr_flags |= FR_QUICK;
+ }
+
+ /*
+ * Parse rule options that are available if a rule is tied to an
+ * interface.
+ */
+ *fp->fr_ifname = '\0';
+ *fp->fr_oifname = '\0';
+ if (*cpp && !strcasecmp(*cpp, "on")) {
+ if (!*++cpp) {
+ fprintf(stderr, "%d: interface name missing\n",
+ linenum);
+ return NULL;
+ }
+ (void)strncpy(fp->fr_ifname, *cpp, IFNAMSIZ-1);
+ fp->fr_ifname[IFNAMSIZ-1] = '\0';
+ cpp++;
+ if (!*cpp) {
+ if ((fp->fr_flags & FR_RETMASK) == FR_RETRST) {
+ fprintf(stderr,
+ "%d: %s can only be used with TCP\n",
+ linenum, "return-rst");
+ return NULL;
+ }
+ return fp;
+ }
+
+ if (!strcasecmp(*cpp, "out-via")) {
+ if (fp->fr_flags & FR_OUTQUE) {
+ fprintf(stderr,
+ "out-via must be used with in\n");
+ return NULL;
+ }
+ cpp++;
+ (void)strncpy(fp->fr_oifname, *cpp, IFNAMSIZ-1);
+ fp->fr_oifname[IFNAMSIZ-1] = '\0';
+ cpp++;
+ } else if (!strcasecmp(*cpp, "in-via")) {
+ if (fp->fr_flags & FR_INQUE) {
+ fprintf(stderr,
+ "in-via must be used with out\n");
+ return NULL;
+ }
+ cpp++;
+ (void)strncpy(fp->fr_oifname, *cpp, IFNAMSIZ-1);
+ fp->fr_oifname[IFNAMSIZ-1] = '\0';
+ cpp++;
+ }
+
+ if (!strcasecmp(*cpp, "dup-to") && *(cpp + 1)) {
+ cpp++;
+ if (to_interface(&fp->fr_dif, *cpp, linenum))
+ return NULL;
+ cpp++;
+ }
+ if (*cpp && !strcasecmp(*cpp, "to") && *(cpp + 1)) {
+ cpp++;
+ if (to_interface(&fp->fr_tif, *cpp, linenum))
+ return NULL;
+ cpp++;
+ } else if (*cpp && !strcasecmp(*cpp, "fastroute")) {
+ if (!(fp->fr_flags & FR_INQUE)) {
+ fprintf(stderr,
+ "can only use %s with 'in'\n",
+ "fastroute");
+ return NULL;
+ }
+ fp->fr_flags |= FR_FASTROUTE;
+ cpp++;
+ }
+
+ /*
+ * Set the "other" interface name. Lets you specify both
+ * inbound and outbound interfaces for state rules. Do not
+ * prevent both interfaces from being the same.
+ */
+ strcpy(fp->fr_ifnames[3], "*");
+ if ((*cpp != NULL) && (*(cpp + 1) != NULL) &&
+ ((((fp->fr_flags & FR_INQUE) != 0) &&
+ (strcasecmp(*cpp, "out-via") == 0)) ||
+ (((fp->fr_flags & FR_OUTQUE) != 0) &&
+ (strcasecmp(*cpp, "in-via") == 0)))) {
+ cpp++;
+
+ s = strchr(*cpp, ',');
+ if (s != NULL) {
+ *s++ = '\0';
+ (void)strncpy(fp->fr_ifnames[3], s,
+ IFNAMSIZ - 1);
+ fp->fr_ifnames[3][IFNAMSIZ - 1] = '\0';
+ }
+
+ (void)strncpy(fp->fr_ifnames[2], *cpp, IFNAMSIZ - 1);
+ fp->fr_ifnames[2][IFNAMSIZ - 1] = '\0';
+ cpp++;
+ } else
+ strcpy(fp->fr_ifnames[2], "*");
+
+ }
+
+ if (*cpp && !strcasecmp(*cpp, "tos")) {
+ if (!*++cpp) {
+ fprintf(stderr, "%d: tos missing value\n", linenum);
+ return NULL;
+ }
+ fp->fr_tos = strtol(*cpp, NULL, 0);
+ fp->fr_mip.fi_tos = 0xff;
+ cpp++;
+ }
+
+ if (*cpp && !strcasecmp(*cpp, "ttl")) {
+ if (!*++cpp) {
+ fprintf(stderr, "%d: ttl missing hopcount value\n",
+ linenum);
+ return NULL;
+ }
+ if (ratoi(*cpp, &i, 0, 255))
+ fp->fr_ttl = i;
+ else {
+ fprintf(stderr, "%d: invalid ttl (%s)\n",
+ linenum, *cpp);
+ return NULL;
+ }
+ fp->fr_mip.fi_ttl = 0xff;
+ cpp++;
+ }
+
+ /*
+ * check for "proto <protoname>" only decode udp/tcp/icmp as protoname
+ */
+ if (*cpp && !strcasecmp(*cpp, "proto")) {
+ if (!*++cpp) {
+ fprintf(stderr, "%d: protocol name missing\n", linenum);
+ return NULL;
+ }
+ fp->fr_type = FR_T_IPF;
+ proto = *cpp++;
+ if (!strcasecmp(proto, "tcp/udp")) {
+ fp->fr_flx |= FI_TCPUDP;
+ fp->fr_mflx |= FI_TCPUDP;
+ } else if (use_inet6 && !strcasecmp(proto, "icmp")) {
+ fprintf(stderr,
+"%d: use proto ipv6-icmp with IPv6 (or use proto 1 if you really mean icmp)\n",
+ linenum);
+ return NULL;
+ } else {
+ fp->fr_proto = getproto(proto);
+ fp->fr_mip.fi_p = 0xff;
+ }
+ }
+ if ((fp->fr_proto != IPPROTO_TCP) &&
+ ((fp->fr_flags & FR_RETMASK) == FR_RETRST)) {
+ fprintf(stderr, "%d: %s can only be used with TCP\n",
+ linenum, "return-rst");
+ return NULL;
+ }
+
+ /*
+ * get the from host and bit mask to use against packets
+ */
+
+ if (!*cpp) {
+ fprintf(stderr, "%d: missing source specification\n", linenum);
+ return NULL;
+ }
+ if (!strcasecmp(*cpp, "all")) {
+ cpp++;
+ if (!*cpp) {
+ if (fp->fr_type == FR_T_NONE) {
+ fp->fr_dsize = 0;
+ fp->fr_data = NULL;
+ }
+ return fp;
+ }
+ fp->fr_type = FR_T_IPF;
+#ifdef IPFILTER_BPF
+ } else if (!strcmp(*cpp, "{")) {
+ struct bpf_program bpf;
+ struct pcap *p;
+ char **cp;
+ u_32_t l;
+
+ if (fp->fr_type != FR_T_NONE) {
+ fprintf(stderr,
+ "%d: cannot mix BPF/ipf matching\n", linenum);
+ return NULL;
+ }
+ fp->fr_type = FR_T_BPFOPC;
+ cpp++;
+ if (!strncmp(*cpp, "0x", 2)) {
+ fp->fr_data = malloc(4);
+ for (cp = cpp, i = 0; *cp; cp++, i++) {
+ if (!strcmp(*cp, "}"))
+ break;
+ fp->fr_data = realloc(fp->fr_data,
+ (i + 1) * 4);
+ l = strtoul(*cp, NULL, 0);
+ ((u_32_t *)fp->fr_data)[i] = l;
+ }
+ if (!*cp) {
+ fprintf(stderr, "Missing closing '}'\n");
+ return NULL;
+ }
+ fp->fr_dsize = i * sizeof(l);
+ bpf.bf_insns = fp->fr_data;
+ bpf.bf_len = fp->fr_dsize / sizeof(struct bpf_insn);
+ } else {
+ for (cp = cpp; *cp; cp++) {
+ if (!strcmp(*cp, "}"))
+ break;
+ (*cp)[-1] = ' ';
+ }
+ if (!*cp) {
+ fprintf(stderr, "Missing closing '}'\n");
+ return NULL;
+ }
+
+ bzero((char *)&bpf, sizeof(bpf));
+ p = pcap_open_dead(DLT_RAW, 1);
+ if (!p) {
+ fprintf(stderr, "pcap_open_dead failed\n");
+ return NULL;
+ }
+
+ if (pcap_compile(p, &bpf, *cpp, 1, 0xffffffff)) {
+ pcap_perror(p, "ipf");
+ pcap_close(p);
+ fprintf(stderr, "pcap parsing failed\n");
+ return NULL;
+ }
+ pcap_close(p);
+ fp->fr_dsize = bpf.bf_len * sizeof(struct bpf_insn);
+ fp->fr_data = bpf.bf_insns;
+ if (!bpf_validate(fp->fr_data, bpf.bf_len)) {
+ fprintf(stderr, "BPF validation failed\n");
+ return NULL;
+ }
+ if (opts & OPT_DEBUG)
+ bpf_dump(&bpf, 0);
+ }
+ cpp = cp;
+ (*cpp)++;
+#endif
+ } else {
+ fp->fr_type = FR_T_IPF;
+
+ if (strcasecmp(*cpp, "from")) {
+ fprintf(stderr, "%d: unexpected keyword (%s) - from\n",
+ linenum, *cpp);
+ return NULL;
+ }
+ if (!*++cpp) {
+ fprintf(stderr, "%d: missing host after from\n",
+ linenum);
+ return NULL;
+ }
+ if (**cpp == '!') {
+ fp->fr_flags |= FR_NOTSRCIP;
+ (*cpp)++;
+ } else if (!strcmp(*cpp, "!")) {
+ fp->fr_flags |= FR_NOTSRCIP;
+ cpp++;
+ }
+
+ s = *cpp;
+ i = hostmask(&cpp, proto, fp->fr_ifname, (u_32_t *)&fp->fr_src,
+ (u_32_t *)&fp->fr_smsk, linenum);
+ if (i == -1)
+ return NULL;
+ if (*fp->fr_ifname && !strcasecmp(s, fp->fr_ifname))
+ fp->fr_satype = FRI_DYNAMIC;
+ if (i == 1) {
+ if (fp->fr_v == 6) {
+ fprintf(stderr,
+ "can only use pools with ipv4\n");
+ return NULL;
+ }
+ fp->fr_satype = FRI_LOOKUP;
+ }
+
+ if (ports(&cpp, proto, &fp->fr_sport, &fp->fr_scmp,
+ &fp->fr_stop, linenum))
+ return NULL;
+
+ if (!*cpp) {
+ fprintf(stderr, "%d: missing to fields\n", linenum);
+ return NULL;
+ }
+
+ /*
+ * do the same for the to field (destination host)
+ */
+ if (strcasecmp(*cpp, "to")) {
+ fprintf(stderr, "%d: unexpected keyword (%s) - to\n",
+ linenum, *cpp);
+ return NULL;
+ }
+ if (!*++cpp) {
+ fprintf(stderr, "%d: missing host after to\n", linenum);
+ return NULL;
+ }
+
+ if (**cpp == '!') {
+ fp->fr_flags |= FR_NOTDSTIP;
+ (*cpp)++;
+ } else if (!strcmp(*cpp, "!")) {
+ fp->fr_flags |= FR_NOTDSTIP;
+ cpp++;
+ }
+
+ s = *cpp;
+ i = hostmask(&cpp, proto, fp->fr_ifname, (u_32_t *)&fp->fr_dst,
+ (u_32_t *)&fp->fr_dmsk, linenum);
+ if (i == -1)
+ return NULL;
+ if (*fp->fr_ifname && !strcasecmp(s, fp->fr_ifname))
+ fp->fr_datype = FRI_DYNAMIC;
+ if (i == 1) {
+ if (fp->fr_v == 6) {
+ fprintf(stderr,
+ "can only use pools with ipv4\n");
+ return NULL;
+ }
+ fp->fr_datype = FRI_LOOKUP;
+ }
+
+ if (ports(&cpp, proto, &fp->fr_dport, &fp->fr_dcmp,
+ &fp->fr_dtop, linenum))
+ return NULL;
+ }
+
+ if (fp->fr_type == FR_T_IPF) {
+ /*
+ * check some sanity, make sure we don't have icmp checks
+ * with tcp or udp or visa versa.
+ */
+ if (fp->fr_proto && (fp->fr_dcmp || fp->fr_scmp) &&
+ fp->fr_proto != IPPROTO_TCP &&
+ fp->fr_proto != IPPROTO_UDP) {
+ fprintf(stderr,
+ "%d: port operation on non tcp/udp\n",linenum);
+ return NULL;
+ }
+ if (fp->fr_icmp && fp->fr_proto != IPPROTO_ICMP) {
+ fprintf(stderr,
+ "%d: icmp comparisons on wrong protocol\n",
+ linenum);
+ return NULL;
+ }
+
+ if (!*cpp)
+ return fp;
+
+ if (*cpp && (fp->fr_type == FR_T_IPF) &&
+ !strcasecmp(*cpp, "flags")) {
+ if (!*++cpp) {
+ fprintf(stderr, "%d: no flags present\n",
+ linenum);
+ return NULL;
+ }
+ fp->fr_tcpf = tcp_flags(*cpp, &fp->fr_tcpfm, linenum);
+ cpp++;
+ }
+
+ /*
+ * extras...
+ */
+ if ((fp->fr_v == 4) && *cpp && (!strcasecmp(*cpp, "with") ||
+ !strcasecmp(*cpp, "and")))
+ if (extras(&cpp, fp, linenum))
+ return NULL;
+
+ /*
+ * icmp types for use with the icmp protocol
+ */
+ if (*cpp && !strcasecmp(*cpp, "icmp-type")) {
+ if (fp->fr_proto != IPPROTO_ICMP &&
+ fp->fr_proto != IPPROTO_ICMPV6) {
+ fprintf(stderr,
+ "%d: icmp with wrong protocol (%d)\n",
+ linenum, fp->fr_proto);
+ return NULL;
+ }
+ if (addicmp(&cpp, fp, linenum))
+ return NULL;
+ fp->fr_icmp = htons(fp->fr_icmp);
+ fp->fr_icmpm = htons(fp->fr_icmpm);
+ }
+ }
+
+ /*
+ * Keep something...
+ */
+ while (*cpp && !strcasecmp(*cpp, "keep"))
+ if (addkeep(&cpp, fp, linenum))
+ return NULL;
+
+ /*
+ * This is here to enforce the old interface binding behaviour.
+ * That is, "on X" is equivalent to "<dir> on X <!dir>-via -,X"
+ */
+ if (fp->fr_flags & FR_KEEPSTATE) {
+ if (*fp->fr_ifnames[0] && !*fp->fr_ifnames[3]) {
+ bcopy(fp->fr_ifnames[0], fp->fr_ifnames[3],
+ sizeof(fp->fr_ifnames[3]));
+ strncpy(fp->fr_ifnames[2], "*",
+ sizeof(fp->fr_ifnames[3]));
+ }
+ }
+
+ /*
+ * head of a new group ?
+ */
+ if (*cpp && !strcasecmp(*cpp, "head")) {
+ if (fp->fr_arg != 0) {
+ fprintf(stderr, "%d: cannot use skip with head\n",
+ linenum);
+ return NULL;
+ }
+ if (!*++cpp) {
+ fprintf(stderr, "%d: head without group #\n", linenum);
+ return NULL;
+ }
+ if (strlen(*cpp) > FR_GROUPLEN) {
+ fprintf(stderr, "%d: head name too long #\n", linenum);
+ return NULL;
+ }
+ strncpy(fp->fr_grhead, *cpp, FR_GROUPLEN);
+ cpp++;
+ }
+
+ /*
+ * reference to an already existing group ?
+ */
+ if (*cpp && !strcasecmp(*cpp, "group")) {
+ if (!*++cpp) {
+ fprintf(stderr, "%d: group without group #\n",
+ linenum);
+ return NULL;
+ }
+ if (strlen(*cpp) > FR_GROUPLEN) {
+ fprintf(stderr, "%d: group name too long #\n", linenum);
+ return NULL;
+ }
+ strncpy(fp->fr_group, *cpp, FR_GROUPLEN);
+ cpp++;
+ }
+
+ if (*cpp && !strcasecmp(*cpp, "tag")) {
+ if (!*++cpp) {
+ fprintf(stderr, "%d: tag id missing value\n", linenum);
+ return NULL;
+ }
+ fp->fr_tag = strtol(*cpp, NULL, 0);
+ cpp++;
+ }
+
+ /*
+ * pps counter
+ */
+ if (*cpp && !strcasecmp(*cpp, "pps")) {
+ if (!*++cpp) {
+ fprintf(stderr, "%d: pps without rate\n", linenum);
+ return NULL;
+ }
+ if (ratoui(*cpp, &k, 0, INT_MAX))
+ fp->fr_pps = k;
+ else {
+ fprintf(stderr, "%d: invalid pps rate (%s)\n",
+ linenum, *cpp);
+ return NULL;
+ }
+ cpp++;
+ }
+
+ /*
+ * leftovers...yuck
+ */
+ if (*cpp && **cpp) {
+ fprintf(stderr, "%d: unknown words at end: [", linenum);
+ for (; *cpp; cpp++)
+ fprintf(stderr, "%s ", *cpp);
+ fprintf(stderr, "]\n");
+ return NULL;
+ }
+
+ /*
+ * lazy users...
+ */
+ if (fp->fr_type == FR_T_IPF) {
+ if ((fp->fr_tcpf || fp->fr_tcpfm) &&
+ (fp->fr_proto != IPPROTO_TCP)) {
+ fprintf(stderr,
+ "%d: TCP protocol not specified\n", linenum);
+ return NULL;
+ }
+ if (!(fp->fr_flx & FI_TCPUDP) &&
+ (fp->fr_proto != IPPROTO_TCP) &&
+ (fp->fr_proto != IPPROTO_UDP) &&
+ (fp->fr_dcmp || fp->fr_scmp)) {
+ if (!fp->fr_proto) {
+ fp->fr_flx |= FI_TCPUDP;
+ fp->fr_mflx |= FI_TCPUDP;
+ } else {
+ fprintf(stderr,
+ "%d: port check for non-TCP/UDP\n",
+ linenum);
+ return NULL;
+ }
+ }
+ }
+ if (*fp->fr_oifname && strcmp(fp->fr_oifname, "*") &&
+ !(fp->fr_flags & FR_KEEPSTATE)) {
+ fprintf(stderr, "%d: *-via <if> must be used %s\n",
+ linenum, "with keep-state");
+ return NULL;
+ }
+ return fp;
+}
diff --git a/contrib/ipfilter/lib/portname.c b/contrib/ipfilter/lib/portname.c
new file mode 100644
index 0000000..7c0fc87
--- /dev/null
+++ b/contrib/ipfilter/lib/portname.c
@@ -0,0 +1,42 @@
+/* $NetBSD$ */
+
+/*
+ * Copyright (C) 1993-2001 by Darren Reed.
+ *
+ * See the IPFILTER.LICENCE file for details on licencing.
+ *
+ * Id: portname.c,v 1.7 2003/08/14 14:27:43 darrenr Exp
+ */
+#include "ipf.h"
+
+
+char *portname(pr, port)
+int pr, port;
+{
+ static char buf[32];
+ struct protoent *p = NULL;
+ struct servent *sv = NULL, *sv1 = NULL;
+
+ if ((opts & OPT_NORESOLVE) == 0) {
+ if (pr == -1) {
+ if ((sv = getservbyport(htons(port), "tcp"))) {
+ strncpy(buf, sv->s_name, sizeof(buf)-1);
+ buf[sizeof(buf)-1] = '\0';
+ sv1 = getservbyport(htons(port), "udp");
+ sv = strncasecmp(buf, sv->s_name, strlen(buf)) ?
+ NULL : sv1;
+ }
+ if (sv)
+ return buf;
+ } else if ((pr != -2) && (p = getprotobynumber(pr))) {
+ if ((sv = getservbyport(htons(port), p->p_name))) {
+ strncpy(buf, sv->s_name, sizeof(buf)-1);
+ buf[sizeof(buf)-1] = '\0';
+ return buf;
+ }
+ }
+ }
+
+ (void) sprintf(buf, "%d", port);
+ return buf;
+}
diff --git a/contrib/ipfilter/lib/portnum.c b/contrib/ipfilter/lib/portnum.c
new file mode 100644
index 0000000..284bbc9
--- /dev/null
+++ b/contrib/ipfilter/lib/portnum.c
@@ -0,0 +1,64 @@
+/* $NetBSD$ */
+
+/*
+ * Copyright (C) 1993-2001 by Darren Reed.
+ *
+ * See the IPFILTER.LICENCE file for details on licencing.
+ *
+ *
+ * Id: portnum.c,v 1.6.4.1 2004/12/09 19:41:22 darrenr Exp
+ */
+
+#include <ctype.h>
+
+#include "ipf.h"
+
+
+/*
+ * find the port number given by the name, either from getservbyname() or
+ * straight atoi(). Return 1 on success, 0 on failure
+ */
+int portnum(name, proto, port, linenum)
+char *name, *proto;
+u_short *port;
+int linenum;
+{
+ struct servent *sp, *sp2;
+ u_short p1 = 0;
+ int i;
+
+ if (ISDIGIT(*name)) {
+ if (ratoi(name, &i, 0, USHRT_MAX)) {
+ *port = (u_short)i;
+ return 1;
+ }
+ fprintf(stderr, "%d: unknown port \"%s\"\n", linenum, name);
+ return 0;
+ }
+ if (proto != NULL && strcasecmp(proto, "tcp/udp") != 0) {
+ sp = getservbyname(name, proto);
+ if (sp) {
+ *port = ntohs(sp->s_port);
+ return 1;
+ }
+ fprintf(stderr, "%d: unknown service \"%s\".\n", linenum, name);
+ return 0;
+ }
+ sp = getservbyname(name, "tcp");
+ if (sp)
+ p1 = sp->s_port;
+ sp2 = getservbyname(name, "udp");
+ if (!sp || !sp2) {
+ fprintf(stderr, "%d: unknown tcp/udp service \"%s\".\n",
+ linenum, name);
+ return 0;
+ }
+ if (p1 != sp2->s_port) {
+ fprintf(stderr, "%d: %s %d/tcp is a different port to ",
+ linenum, name, p1);
+ fprintf(stderr, "%d: %s %d/udp\n", linenum, name, sp->s_port);
+ return 0;
+ }
+ *port = ntohs(p1);
+ return 1;
+}
diff --git a/contrib/ipfilter/lib/ports.c b/contrib/ipfilter/lib/ports.c
new file mode 100644
index 0000000..634dfeb
--- /dev/null
+++ b/contrib/ipfilter/lib/ports.c
@@ -0,0 +1,81 @@
+/* $NetBSD$ */
+
+/*
+ * Copyright (C) 1993-2001 by Darren Reed.
+ *
+ * See the IPFILTER.LICENCE file for details on licencing.
+ *
+ * Id: ports.c,v 1.9.4.1 2004/12/09 19:41:22 darrenr Exp
+ */
+
+#include <ctype.h>
+
+#include "ipf.h"
+
+
+/*
+ * check for possible presence of the port fields in the line
+ */
+int ports(seg, proto, pp, cp, tp, linenum)
+char ***seg;
+char *proto;
+u_short *pp;
+int *cp;
+u_short *tp;
+int linenum;
+{
+ int comp = -1;
+
+ if (!*seg || !**seg || !***seg)
+ return 0;
+ if (!strcasecmp(**seg, "port") && *(*seg + 1) && *(*seg + 2)) {
+ (*seg)++;
+ if (ISALNUM(***seg) && *(*seg + 2)) {
+ if (portnum(**seg, proto, pp, linenum) == 0)
+ return -1;
+ (*seg)++;
+ if (!strcmp(**seg, "<>"))
+ comp = FR_OUTRANGE;
+ else if (!strcmp(**seg, "><"))
+ comp = FR_INRANGE;
+ else {
+ fprintf(stderr,
+ "%d: unknown range operator (%s)\n",
+ linenum, **seg);
+ return -1;
+ }
+ (*seg)++;
+ if (**seg == NULL) {
+ fprintf(stderr, "%d: missing 2nd port value\n",
+ linenum);
+ return -1;
+ }
+ if (portnum(**seg, proto, tp, linenum) == 0)
+ return -1;
+ } else if (!strcmp(**seg, "=") || !strcasecmp(**seg, "eq"))
+ comp = FR_EQUAL;
+ else if (!strcmp(**seg, "!=") || !strcasecmp(**seg, "ne"))
+ comp = FR_NEQUAL;
+ else if (!strcmp(**seg, "<") || !strcasecmp(**seg, "lt"))
+ comp = FR_LESST;
+ else if (!strcmp(**seg, ">") || !strcasecmp(**seg, "gt"))
+ comp = FR_GREATERT;
+ else if (!strcmp(**seg, "<=") || !strcasecmp(**seg, "le"))
+ comp = FR_LESSTE;
+ else if (!strcmp(**seg, ">=") || !strcasecmp(**seg, "ge"))
+ comp = FR_GREATERTE;
+ else {
+ fprintf(stderr, "%d: unknown comparator (%s)\n",
+ linenum, **seg);
+ return -1;
+ }
+ if (comp != FR_OUTRANGE && comp != FR_INRANGE) {
+ (*seg)++;
+ if (portnum(**seg, proto, pp, linenum) == 0)
+ return -1;
+ }
+ *cp = comp;
+ (*seg)++;
+ }
+ return 0;
+}
diff --git a/contrib/ipfilter/lib/print_toif.c b/contrib/ipfilter/lib/print_toif.c
new file mode 100644
index 0000000..0e230cd
--- /dev/null
+++ b/contrib/ipfilter/lib/print_toif.c
@@ -0,0 +1,32 @@
+/* $NetBSD$ */
+
+/*
+ * Copyright (C) 1993-2001 by Darren Reed.
+ *
+ * See the IPFILTER.LICENCE file for details on licencing.
+ *
+ * Id: print_toif.c,v 1.8 2002/01/28 06:50:47 darrenr Exp
+ */
+
+#include "ipf.h"
+
+
+void print_toif(tag, fdp)
+char *tag;
+frdest_t *fdp;
+{
+ printf("%s %s%s", tag, fdp->fd_ifname,
+ (fdp->fd_ifp || (long)fdp->fd_ifp == -1) ? "" : "(!)");
+#ifdef USE_INET6
+ if (use_inet6 && IP6_NOTZERO(&fdp->fd_ip6.in6)) {
+ char ipv6addr[80];
+
+ inet_ntop(AF_INET6, &fdp->fd_ip6, ipv6addr,
+ sizeof(fdp->fd_ip6));
+ printf(":%s", ipv6addr);
+ } else
+#endif
+ if (fdp->fd_ip.s_addr)
+ printf(":%s", inet_ntoa(fdp->fd_ip));
+ putchar(' ');
+}
diff --git a/contrib/ipfilter/lib/printactivenat.c b/contrib/ipfilter/lib/printactivenat.c
new file mode 100644
index 0000000..3c56b14
--- /dev/null
+++ b/contrib/ipfilter/lib/printactivenat.c
@@ -0,0 +1,85 @@
+/* $NetBSD$ */
+
+/*
+ * Copyright (C) 1993-2001 by Darren Reed.
+ *
+ * See the IPFILTER.LICENCE file for details on licencing.
+ *
+ * Added redirect stuff and a variety of bug fixes. (mcn@EnGarde.com)
+ */
+
+#include "ipf.h"
+
+
+#if !defined(lint)
+static const char rcsid[] = "@(#)Id: printactivenat.c,v 1.3.2.4 2004/05/11 16:07:32 darrenr Exp";
+#endif
+
+
+void printactivenat(nat, opts)
+nat_t *nat;
+int opts;
+{
+
+ printf("%s", getnattype(nat->nat_ptr));
+
+ if (nat->nat_flags & SI_CLONE)
+ printf(" CLONE");
+
+ printf(" %-15s", inet_ntoa(nat->nat_inip));
+
+ if ((nat->nat_flags & IPN_TCPUDP) != 0)
+ printf(" %-5hu", ntohs(nat->nat_inport));
+
+ printf(" <- -> %-15s",inet_ntoa(nat->nat_outip));
+
+ if ((nat->nat_flags & IPN_TCPUDP) != 0)
+ printf(" %-5hu", ntohs(nat->nat_outport));
+
+ printf(" [%s", inet_ntoa(nat->nat_oip));
+ if ((nat->nat_flags & IPN_TCPUDP) != 0)
+ printf(" %hu", ntohs(nat->nat_oport));
+ printf("]");
+
+ if (opts & OPT_VERBOSE) {
+ printf("\n\tage %lu use %hu sumd %s/",
+ nat->nat_age, nat->nat_use, getsumd(nat->nat_sumd[0]));
+ printf("%s pr %u bkt %d/%d flags %x\n",
+ getsumd(nat->nat_sumd[1]), nat->nat_p,
+ nat->nat_hv[0], nat->nat_hv[1], nat->nat_flags);
+ printf("\tifp %s", getifname(nat->nat_ifps[0]));
+ printf(",%s ", getifname(nat->nat_ifps[1]));
+#ifdef USE_QUAD_T
+ printf("bytes %qu/%qu pkts %qu/%qu",
+ (unsigned long long)nat->nat_bytes[0],
+ (unsigned long long)nat->nat_bytes[1],
+ (unsigned long long)nat->nat_pkts[0],
+ (unsigned long long)nat->nat_pkts[1]);
+#else
+ printf("bytes %lu/%lu pkts %lu/%lu", nat->nat_bytes[0],
+ nat->nat_bytes[1], nat->nat_pkts[0], nat->nat_pkts[1]);
+#endif
+ printf(" ipsumd %x", nat->nat_ipsumd);
+ }
+
+ if (opts & OPT_DEBUG) {
+ printf("\n\tnat_next %p _pnext %p _hm %p\n",
+ nat->nat_next, nat->nat_pnext, nat->nat_hm);
+ printf("\t_hnext %p/%p _phnext %p/%p\n",
+ nat->nat_hnext[0], nat->nat_hnext[1],
+ nat->nat_phnext[0], nat->nat_phnext[1]);
+ printf("\t_data %p _me %p _state %p _aps %p\n",
+ nat->nat_data, nat->nat_me, nat->nat_state, nat->nat_aps);
+ printf("\tfr %p ptr %p ifps %p/%p sync %p\n",
+ nat->nat_fr, nat->nat_ptr, nat->nat_ifps[0],
+ nat->nat_ifps[1], nat->nat_sync);
+ printf("\ttqe:pnext %p next %p ifq %p parent %p/%p\n",
+ nat->nat_tqe.tqe_pnext, nat->nat_tqe.tqe_next,
+ nat->nat_tqe.tqe_ifq, nat->nat_tqe.tqe_parent, nat);
+ printf("\ttqe:die %ld touched %ld flags %x state %d/%d\n",
+ nat->nat_tqe.tqe_die, nat->nat_tqe.tqe_touched,
+ nat->nat_tqe.tqe_flags, nat->nat_tqe.tqe_state[0],
+ nat->nat_tqe.tqe_state[1]);
+ }
+ putchar('\n');
+}
diff --git a/contrib/ipfilter/lib/printaps.c b/contrib/ipfilter/lib/printaps.c
new file mode 100644
index 0000000..5c5c3dd
--- /dev/null
+++ b/contrib/ipfilter/lib/printaps.c
@@ -0,0 +1,112 @@
+/* $NetBSD$ */
+
+/*
+ * Copyright (C) 1993-2001 by Darren Reed.
+ *
+ * See the IPFILTER.LICENCE file for details on licencing.
+ *
+ * Added redirect stuff and a variety of bug fixes. (mcn@EnGarde.com)
+ */
+
+#include "ipf.h"
+#include "kmem.h"
+
+
+#if !defined(lint)
+static const char rcsid[] = "@(#)Id: printaps.c,v 1.4 2004/01/08 13:34:32 darrenr Exp";
+#endif
+
+
+void printaps(aps, opts)
+ap_session_t *aps;
+int opts;
+{
+ ipsec_pxy_t ipsec;
+ ap_session_t ap;
+ ftpinfo_t ftp;
+ aproxy_t apr;
+ raudio_t ra;
+
+ if (kmemcpy((char *)&ap, (long)aps, sizeof(ap)))
+ return;
+ if (kmemcpy((char *)&apr, (long)ap.aps_apr, sizeof(apr)))
+ return;
+ printf("\tproxy %s/%d use %d flags %x\n", apr.apr_label,
+ apr.apr_p, apr.apr_ref, apr.apr_flags);
+ printf("\t\tproto %d flags %#x bytes ", ap.aps_p, ap.aps_flags);
+#ifdef USE_QUAD_T
+ printf("%qu pkts %qu", (unsigned long long)ap.aps_bytes,
+ (unsigned long long)ap.aps_pkts);
+#else
+ printf("%lu pkts %lu", ap.aps_bytes, ap.aps_pkts);
+#endif
+ printf(" data %s size %d\n", ap.aps_data ? "YES" : "NO", ap.aps_psiz);
+ if ((ap.aps_p == IPPROTO_TCP) && (opts & OPT_VERBOSE)) {
+ printf("\t\tstate[%u,%u], sel[%d,%d]\n",
+ ap.aps_state[0], ap.aps_state[1],
+ ap.aps_sel[0], ap.aps_sel[1]);
+#if (defined(NetBSD) && (NetBSD >= 199905) && (NetBSD < 1991011)) || \
+ (__FreeBSD_version >= 300000) || defined(OpenBSD)
+ printf("\t\tseq: off %hd/%hd min %x/%x\n",
+ ap.aps_seqoff[0], ap.aps_seqoff[1],
+ ap.aps_seqmin[0], ap.aps_seqmin[1]);
+ printf("\t\tack: off %hd/%hd min %x/%x\n",
+ ap.aps_ackoff[0], ap.aps_ackoff[1],
+ ap.aps_ackmin[0], ap.aps_ackmin[1]);
+#else
+ printf("\t\tseq: off %hd/%hd min %lx/%lx\n",
+ ap.aps_seqoff[0], ap.aps_seqoff[1],
+ ap.aps_seqmin[0], ap.aps_seqmin[1]);
+ printf("\t\tack: off %hd/%hd min %lx/%lx\n",
+ ap.aps_ackoff[0], ap.aps_ackoff[1],
+ ap.aps_ackmin[0], ap.aps_ackmin[1]);
+#endif
+ }
+
+ if (!strcmp(apr.apr_label, "raudio") && ap.aps_psiz == sizeof(ra)) {
+ if (kmemcpy((char *)&ra, (long)ap.aps_data, sizeof(ra)))
+ return;
+ printf("\tReal Audio Proxy:\n");
+ printf("\t\tSeen PNA: %d\tVersion: %d\tEOS: %d\n",
+ ra.rap_seenpna, ra.rap_version, ra.rap_eos);
+ printf("\t\tMode: %#x\tSBF: %#x\n", ra.rap_mode, ra.rap_sbf);
+ printf("\t\tPorts:pl %hu, pr %hu, sr %hu\n",
+ ra.rap_plport, ra.rap_prport, ra.rap_srport);
+ } else if (!strcmp(apr.apr_label, "ftp") &&
+ (ap.aps_psiz == sizeof(ftp))) {
+ if (kmemcpy((char *)&ftp, (long)ap.aps_data, sizeof(ftp)))
+ return;
+ printf("\tFTP Proxy:\n");
+ printf("\t\tpassok: %d\n", ftp.ftp_passok);
+ ftp.ftp_side[0].ftps_buf[FTP_BUFSZ - 1] = '\0';
+ ftp.ftp_side[1].ftps_buf[FTP_BUFSZ - 1] = '\0';
+ printf("\tClient:\n");
+ printf("\t\tseq %x (ack %x) len %d junk %d cmds %d\n",
+ ftp.ftp_side[0].ftps_seq[0],
+ ftp.ftp_side[0].ftps_seq[1],
+ ftp.ftp_side[0].ftps_len, ftp.ftp_side[0].ftps_junk,
+ ftp.ftp_side[0].ftps_cmds);
+ printf("\t\tbuf [");
+ printbuf(ftp.ftp_side[0].ftps_buf, FTP_BUFSZ, 1);
+ printf("]\n\tServer:\n");
+ printf("\t\tseq %x (ack %x) len %d junk %d cmds %d\n",
+ ftp.ftp_side[1].ftps_seq[0],
+ ftp.ftp_side[1].ftps_seq[1],
+ ftp.ftp_side[1].ftps_len, ftp.ftp_side[1].ftps_junk,
+ ftp.ftp_side[1].ftps_cmds);
+ printf("\t\tbuf [");
+ printbuf(ftp.ftp_side[1].ftps_buf, FTP_BUFSZ, 1);
+ printf("]\n");
+ } else if (!strcmp(apr.apr_label, "ipsec") &&
+ (ap.aps_psiz == sizeof(ipsec))) {
+ if (kmemcpy((char *)&ipsec, (long)ap.aps_data, sizeof(ipsec)))
+ return;
+ printf("\tIPSec Proxy:\n");
+ printf("\t\tICookie %08x%08x RCookie %08x%08x %s\n",
+ (u_int)ntohl(ipsec.ipsc_icookie[0]),
+ (u_int)ntohl(ipsec.ipsc_icookie[1]),
+ (u_int)ntohl(ipsec.ipsc_rcookie[0]),
+ (u_int)ntohl(ipsec.ipsc_rcookie[1]),
+ ipsec.ipsc_rckset ? "(Set)" : "(Not set)");
+ }
+}
diff --git a/contrib/ipfilter/lib/printbuf.c b/contrib/ipfilter/lib/printbuf.c
new file mode 100644
index 0000000..f2b7faa
--- /dev/null
+++ b/contrib/ipfilter/lib/printbuf.c
@@ -0,0 +1,32 @@
+/* $NetBSD$ */
+
+/*
+ * Copyright (C) 1993-2001 by Darren Reed.
+ *
+ * See the IPFILTER.LICENCE file for details on licencing.
+ *
+ * Id: printbuf.c,v 1.5.4.1 2004/12/09 19:41:22 darrenr Exp
+ */
+
+#include <ctype.h>
+
+#include "ipf.h"
+
+
+void printbuf(buf, len, zend)
+char *buf;
+int len, zend;
+{
+ char *s, c;
+ int i;
+
+ for (s = buf, i = len; i; i--) {
+ c = *s++;
+ if (ISPRINT(c))
+ putchar(c);
+ else
+ printf("\\%03o", c);
+ if ((c == '\0') && zend)
+ break;
+ }
+}
diff --git a/contrib/ipfilter/lib/printfr.c b/contrib/ipfilter/lib/printfr.c
new file mode 100644
index 0000000..f0f5a0e
--- /dev/null
+++ b/contrib/ipfilter/lib/printfr.c
@@ -0,0 +1,445 @@
+/* $NetBSD$ */
+
+/*
+ * Copyright (C) 1993-2001 by Darren Reed.
+ *
+ * See the IPFILTER.LICENCE file for details on licencing.
+ *
+ * Id: printfr.c,v 1.43.2.10 2005/03/16 15:38:13 darrenr Exp
+ */
+
+#include "ipf.h"
+
+static void printaddr(int, int, char *, u_32_t *, u_32_t *);
+
+static void printaddr(v, type, ifname, addr, mask)
+int v, type;
+char *ifname;
+u_32_t *addr, *mask;
+{
+ char *suffix;
+
+ switch (type)
+ {
+ case FRI_BROADCAST :
+ suffix = "/bcast";
+ break;
+
+ case FRI_DYNAMIC :
+ printf("%s", ifname);
+ printmask(mask);
+ suffix = NULL;
+ break;
+
+ case FRI_NETWORK :
+ suffix = "/net";
+ break;
+
+ case FRI_NETMASKED :
+ suffix = "/netmasked";
+ break;
+
+ case FRI_PEERADDR :
+ suffix = "/peer";
+ break;
+
+ case FRI_LOOKUP :
+ suffix = NULL;
+ printlookup((i6addr_t *)addr, (i6addr_t *)mask);
+ break;
+
+ case FRI_NORMAL :
+ printhostmask(v, addr, mask);
+ suffix = NULL;
+ break;
+ default :
+ printf("<%d>", type);
+ printmask(mask);
+ suffix = NULL;
+ break;
+ }
+
+ if (suffix != NULL) {
+ printf("%s/%s", ifname, suffix);
+ }
+}
+
+
+void printlookup(addr, mask)
+i6addr_t *addr, *mask;
+{
+ switch (addr->iplookuptype)
+ {
+ case IPLT_POOL :
+ printf("pool/");
+ break;
+ case IPLT_HASH :
+ printf("hash/");
+ break;
+ default :
+ printf("lookup(%x)=", addr->iplookuptype);
+ break;
+ }
+
+ printf("%u", addr->iplookupnum);
+ if (mask->iplookupptr == NULL)
+ printf("(!)");
+}
+
+
+/*
+ * print the filter structure in a useful way
+ */
+void printfr(fp, iocfunc)
+struct frentry *fp;
+ioctlfunc_t iocfunc;
+{
+ struct protoent *p;
+ u_short sec[2];
+ u_32_t type;
+ u_char *t;
+ char *s;
+ int pr;
+
+ pr = -2;
+ type = fp->fr_type & ~FR_T_BUILTIN;
+
+ if ((fp->fr_type & FR_T_BUILTIN) != 0)
+ printf("# Builtin: ");
+
+ if (fp->fr_type == FR_T_CALLFUNC) {
+ ;
+ } else if (fp->fr_func != NULL) {
+ printf("call");
+ if ((fp->fr_flags & FR_CALLNOW) != 0)
+ printf(" now");
+ s = kvatoname(fp->fr_func, iocfunc);
+ printf(" %s/%u", s ? s : "?", fp->fr_arg);
+ } else if (FR_ISPASS(fp->fr_flags))
+ printf("pass");
+ else if (FR_ISBLOCK(fp->fr_flags)) {
+ printf("block");
+ if (fp->fr_flags & FR_RETICMP) {
+ if ((fp->fr_flags & FR_RETMASK) == FR_FAKEICMP)
+ printf(" return-icmp-as-dest");
+ else if ((fp->fr_flags & FR_RETMASK) == FR_RETICMP)
+ printf(" return-icmp");
+ if (fp->fr_icode) {
+ if (fp->fr_icode <= MAX_ICMPCODE)
+ printf("(%s)",
+ icmpcodes[(int)fp->fr_icode]);
+ else
+ printf("(%d)", fp->fr_icode);
+ }
+ } else if ((fp->fr_flags & FR_RETMASK) == FR_RETRST)
+ printf(" return-rst");
+ } else if ((fp->fr_flags & FR_LOGMASK) == FR_LOG) {
+ printlog(fp);
+ } else if (FR_ISACCOUNT(fp->fr_flags))
+ printf("count");
+ else if (FR_ISAUTH(fp->fr_flags))
+ printf("auth");
+ else if (FR_ISPREAUTH(fp->fr_flags))
+ printf("preauth");
+ else if (FR_ISNOMATCH(fp->fr_flags))
+ printf("nomatch");
+ else if (FR_ISSKIP(fp->fr_flags))
+ printf("skip %u", fp->fr_arg);
+ else {
+ printf("%x", fp->fr_flags);
+ }
+
+ if (fp->fr_flags & FR_OUTQUE)
+ printf(" out ");
+ else
+ printf(" in ");
+
+ if (((fp->fr_flags & FR_LOGB) == FR_LOGB) ||
+ ((fp->fr_flags & FR_LOGP) == FR_LOGP)) {
+ printlog(fp);
+ putchar(' ');
+ }
+
+ if (fp->fr_flags & FR_QUICK)
+ printf("quick ");
+
+ if (*fp->fr_ifname) {
+ printifname("on ", fp->fr_ifname, fp->fr_ifa);
+ if (*fp->fr_ifnames[1] && strcmp(fp->fr_ifnames[1], "*"))
+ printifname(",", fp->fr_ifnames[1], fp->fr_ifas[1]);
+ putchar(' ');
+ }
+
+ if (*fp->fr_dif.fd_ifname || (fp->fr_flags & FR_DUP))
+ print_toif("dup-to", &fp->fr_dif);
+ if (*fp->fr_tif.fd_ifname)
+ print_toif("to", &fp->fr_tif);
+ if (*fp->fr_rif.fd_ifname)
+ print_toif("reply-to", &fp->fr_rif);
+ if (fp->fr_flags & FR_FASTROUTE)
+ printf("fastroute ");
+
+ if ((*fp->fr_ifnames[2] && strcmp(fp->fr_ifnames[2], "*")) ||
+ (*fp->fr_ifnames[3] && strcmp(fp->fr_ifnames[3], "*"))) {
+ if (fp->fr_flags & FR_OUTQUE)
+ printf("in-via ");
+ else
+ printf("out-via ");
+
+ if (*fp->fr_ifnames[2]) {
+ printifname("", fp->fr_ifnames[2],
+ fp->fr_ifas[2]);
+ putchar(' ');
+
+ if (*fp->fr_ifnames[3]) {
+ printifname(",", fp->fr_ifnames[3],
+ fp->fr_ifas[3]);
+ }
+ }
+ }
+
+ if (type == FR_T_IPF) {
+ if (fp->fr_mip.fi_tos)
+ printf("tos %#x ", fp->fr_tos);
+ if (fp->fr_mip.fi_ttl)
+ printf("ttl %d ", fp->fr_ttl);
+ if (fp->fr_flx & FI_TCPUDP) {
+ printf("proto tcp/udp ");
+ pr = -1;
+ } else if (fp->fr_mip.fi_p) {
+ pr = fp->fr_ip.fi_p;
+ if ((p = getprotobynumber(fp->fr_proto)))
+ printf("proto %s ", p->p_name);
+ else
+ printf("proto %d ", fp->fr_proto);
+ }
+ }
+
+ if (type == FR_T_NONE) {
+ printf("all");
+ } else if (type == FR_T_IPF) {
+ printf("from %s", fp->fr_flags & FR_NOTSRCIP ? "!" : "");
+ printaddr(fp->fr_v, fp->fr_satype, fp->fr_ifname,
+ &fp->fr_src.s_addr, &fp->fr_smsk.s_addr);
+ if (fp->fr_scmp)
+ printportcmp(pr, &fp->fr_tuc.ftu_src);
+
+ printf(" to %s", fp->fr_flags & FR_NOTDSTIP ? "!" : "");
+ printaddr(fp->fr_v, fp->fr_datype, fp->fr_ifname,
+ &fp->fr_dst.s_addr, &fp->fr_dmsk.s_addr);
+ if (fp->fr_dcmp)
+ printportcmp(pr, &fp->fr_tuc.ftu_dst);
+
+ if (fp->fr_proto == IPPROTO_ICMP && fp->fr_icmpm) {
+ int type = fp->fr_icmp, code;
+
+ type = ntohs(fp->fr_icmp);
+ code = type & 0xff;
+ type /= 256;
+ if (type < (sizeof(icmptypes) / sizeof(char *) - 1) &&
+ icmptypes[type])
+ printf(" icmp-type %s", icmptypes[type]);
+ else
+ printf(" icmp-type %d", type);
+ if (ntohs(fp->fr_icmpm) & 0xff)
+ printf(" code %d", code);
+ }
+ if ((fp->fr_proto == IPPROTO_TCP) &&
+ (fp->fr_tcpf || fp->fr_tcpfm)) {
+ printf(" flags ");
+ if (fp->fr_tcpf & ~TCPF_ALL)
+ printf("0x%x", fp->fr_tcpf);
+ else
+ for (s = flagset, t = flags; *s; s++, t++)
+ if (fp->fr_tcpf & *t)
+ (void)putchar(*s);
+ if (fp->fr_tcpfm) {
+ (void)putchar('/');
+ if (fp->fr_tcpfm & ~TCPF_ALL)
+ printf("0x%x", fp->fr_tcpfm);
+ else
+ for (s = flagset, t = flags; *s;
+ s++, t++)
+ if (fp->fr_tcpfm & *t)
+ (void)putchar(*s);
+ }
+ }
+ } else if (type == FR_T_BPFOPC) {
+ fakebpf_t *fb;
+ int i;
+
+ printf("bpf-v%d { \"", fp->fr_v);
+ i = fp->fr_dsize / sizeof(*fb);
+
+ for (fb = fp->fr_data, s = ""; i; i--, fb++, s = " ")
+ printf("%s%#x %#x %#x %#x", s, fb->fb_c, fb->fb_t,
+ fb->fb_f, fb->fb_k);
+
+ printf("\" }");
+ } else if (type == FR_T_COMPIPF) {
+ ;
+ } else if (type == FR_T_CALLFUNC) {
+ printf("call function at %p", fp->fr_data);
+ } else {
+ printf("[unknown filter type %#x]", fp->fr_type);
+ }
+
+ if ((type == FR_T_IPF) &&
+ ((fp->fr_flx & FI_WITH) || (fp->fr_mflx & FI_WITH) ||
+ fp->fr_optbits || fp->fr_optmask ||
+ fp->fr_secbits || fp->fr_secmask)) {
+ char *comma = " ";
+
+ printf(" with");
+ if (fp->fr_optbits || fp->fr_optmask ||
+ fp->fr_secbits || fp->fr_secmask) {
+ sec[0] = fp->fr_secmask;
+ sec[1] = fp->fr_secbits;
+ if (fp->fr_v == 4)
+ optprint(sec, fp->fr_optmask, fp->fr_optbits);
+#ifdef USE_INET6
+ else
+ optprintv6(sec, fp->fr_optmask,
+ fp->fr_optbits);
+#endif
+ } else if (fp->fr_mflx & FI_OPTIONS) {
+ fputs(comma, stdout);
+ if (!(fp->fr_flx & FI_OPTIONS))
+ printf("not ");
+ printf("ipopts");
+ comma = ",";
+ }
+ if (fp->fr_mflx & FI_SHORT) {
+ fputs(comma, stdout);
+ if (!(fp->fr_flx & FI_SHORT))
+ printf("not ");
+ printf("short");
+ comma = ",";
+ }
+ if (fp->fr_mflx & FI_FRAG) {
+ fputs(comma, stdout);
+ if (!(fp->fr_flx & FI_FRAG))
+ printf("not ");
+ printf("frag");
+ comma = ",";
+ }
+ if (fp->fr_mflx & FI_FRAGBODY) {
+ fputs(comma, stdout);
+ if (!(fp->fr_flx & FI_FRAGBODY))
+ printf("not ");
+ printf("frag-body");
+ comma = ",";
+ }
+ if (fp->fr_mflx & FI_NATED) {
+ fputs(comma, stdout);
+ if (!(fp->fr_flx & FI_NATED))
+ printf("not ");
+ printf("nat");
+ comma = ",";
+ }
+ if (fp->fr_mflx & FI_LOWTTL) {
+ fputs(comma, stdout);
+ if (!(fp->fr_flx & FI_LOWTTL))
+ printf("not ");
+ printf("lowttl");
+ comma = ",";
+ }
+ if (fp->fr_mflx & FI_BAD) {
+ fputs(comma, stdout);
+ if (!(fp->fr_flx & FI_BAD))
+ printf("not ");
+ printf("bad");
+ comma = ",";
+ }
+ if (fp->fr_mflx & FI_BADSRC) {
+ fputs(comma, stdout);
+ if (!(fp->fr_flx & FI_BADSRC))
+ printf("not ");
+ printf("bad-src");
+ comma = ",";
+ }
+ if (fp->fr_mflx & FI_BADNAT) {
+ fputs(comma, stdout);
+ if (!(fp->fr_flx & FI_BADNAT))
+ printf("not ");
+ printf("bad-nat");
+ comma = ",";
+ }
+ if (fp->fr_mflx & FI_OOW) {
+ fputs(comma, stdout);
+ if (!(fp->fr_flx & FI_OOW))
+ printf("not ");
+ printf("oow");
+ }
+ }
+
+ if (fp->fr_flags & FR_KEEPSTATE) {
+ printf(" keep state");
+ if ((fp->fr_flags & (FR_STSTRICT|FR_NEWISN|FR_NOICMPERR|FR_STATESYNC)) ||
+ (fp->fr_statemax != 0) || (fp->fr_age[0] != 0)) {
+ char *comma = "";
+ printf(" (");
+ if (fp->fr_statemax != 0) {
+ printf("limit %u", fp->fr_statemax);
+ comma = ",";
+ }
+ if (fp->fr_flags & FR_STSTRICT) {
+ printf("%sstrict", comma);
+ comma = ",";
+ }
+ if (fp->fr_flags & FR_NEWISN) {
+ printf("%snewisn", comma);
+ comma = ",";
+ }
+ if (fp->fr_flags & FR_NOICMPERR) {
+ printf("%sno-icmp-err", comma);
+ comma = ",";
+ }
+ if (fp->fr_flags & FR_STATESYNC) {
+ printf("%ssync", comma);
+ comma = ",";
+ }
+ if (fp->fr_age[0] || fp->fr_age[1])
+ printf("%sage %d/%d", comma, fp->fr_age[0],
+ fp->fr_age[1]);
+ printf(")");
+ }
+ }
+ if (fp->fr_flags & FR_KEEPFRAG) {
+ printf(" keep frags");
+ if (fp->fr_flags & (FR_FRSTRICT)) {
+ printf(" (");
+ if (fp->fr_flags & FR_FRSTRICT)
+ printf(" strict");
+ printf(" )");
+
+ }
+ }
+ if (fp->fr_isc != (struct ipscan *)-1) {
+ if (fp->fr_isctag[0])
+ printf(" scan %s", fp->fr_isctag);
+ else
+ printf(" scan *");
+ }
+ if (*fp->fr_grhead != '\0')
+ printf(" head %s", fp->fr_grhead);
+ if (*fp->fr_group != '\0')
+ printf(" group %s", fp->fr_group);
+ if (fp->fr_logtag != FR_NOLOGTAG || *fp->fr_nattag.ipt_tag) {
+ char *s = "";
+
+ printf(" set-tag(");
+ if (fp->fr_logtag != FR_NOLOGTAG) {
+ printf("log=%u", fp->fr_logtag);
+ s = ", ";
+ }
+ if (*fp->fr_nattag.ipt_tag) {
+ printf("%snat=%-.*s", s, IPFTAG_LEN,
+ fp->fr_nattag.ipt_tag);
+ }
+ printf(")");
+ }
+ if (fp->fr_pps)
+ printf(" pps %d", fp->fr_pps);
+ (void)putchar('\n');
+}
diff --git a/contrib/ipfilter/lib/printfraginfo.c b/contrib/ipfilter/lib/printfraginfo.c
new file mode 100644
index 0000000..b521c83
--- /dev/null
+++ b/contrib/ipfilter/lib/printfraginfo.c
@@ -0,0 +1,29 @@
+/* $NetBSD$ */
+
+/*
+ * Copyright (C) 2004 by Darren Reed.
+ *
+ * See the IPFILTER.LICENCE file for details on licencing.
+ *
+ * Id: printfraginfo.c,v 1.1.2.2 2004/03/23 15:15:45 darrenr Exp
+ */
+#include "ipf.h"
+#include "kmem.h"
+
+void printfraginfo(prefix, ifr)
+char *prefix;
+struct ipfr *ifr;
+{
+ frentry_t fr;
+
+ fr.fr_flags = 0xffffffff;
+
+ printf("%s%s -> ", prefix, hostname(4, &ifr->ipfr_src));
+ if (kmemcpy((char *)&fr, (u_long)ifr->ipfr_rule,
+ sizeof(fr)) == -1)
+ return;
+ printf("%s id %d ttl %d pr %d seen0 %d ifp %p tos %#02x = %#x\n",
+ hostname(4, &ifr->ipfr_dst), ifr->ipfr_id, ifr->ipfr_seen0,
+ ifr->ipfr_ttl, ifr->ipfr_p, ifr->ipfr_ifp, ifr->ipfr_tos,
+ fr.fr_flags);
+}
diff --git a/contrib/ipfilter/lib/printhash.c b/contrib/ipfilter/lib/printhash.c
new file mode 100644
index 0000000..80157bb
--- /dev/null
+++ b/contrib/ipfilter/lib/printhash.c
@@ -0,0 +1,144 @@
+/* $NetBSD$ */
+
+/*
+ * Copyright (C) 2002 by Darren Reed.
+ *
+ * See the IPFILTER.LICENCE file for details on licencing.
+ */
+
+#include "ipf.h"
+
+#define PRINTF (void)printf
+#define FPRINTF (void)fprintf
+
+
+iphtable_t *printhash(hp, copyfunc, name, opts)
+iphtable_t *hp;
+copyfunc_t copyfunc;
+char *name;
+int opts;
+{
+ iphtent_t *ipep, **table;
+ iphtable_t iph;
+ int i, printed;
+ size_t sz;
+
+ if ((*copyfunc)((char *)hp, (char *)&iph, sizeof(iph)))
+ return NULL;
+
+ if ((name != NULL) && strncmp(name, iph.iph_name, FR_GROUPLEN))
+ return iph.iph_next;
+
+ if ((opts & OPT_DEBUG) == 0) {
+ if ((iph.iph_type & IPHASH_ANON) == IPHASH_ANON)
+ PRINTF("# 'anonymous' table\n");
+ switch (iph.iph_type & ~IPHASH_ANON)
+ {
+ case IPHASH_LOOKUP :
+ PRINTF("table");
+ break;
+ case IPHASH_GROUPMAP :
+ PRINTF("group-map");
+ if (iph.iph_flags & FR_INQUE)
+ PRINTF(" in");
+ else if (iph.iph_flags & FR_OUTQUE)
+ PRINTF(" out");
+ else
+ PRINTF(" ???");
+ break;
+ default :
+ PRINTF("%#x", iph.iph_type);
+ break;
+ }
+ PRINTF(" role = ");
+ } else {
+ PRINTF("Hash Table Number: %s", iph.iph_name);
+ if ((iph.iph_type & IPHASH_ANON) == IPHASH_ANON)
+ PRINTF("(anon)");
+ putchar(' ');
+ PRINTF("Role: ");
+ }
+
+ switch (iph.iph_unit)
+ {
+ case IPL_LOGNAT :
+ PRINTF("nat");
+ break;
+ case IPL_LOGIPF :
+ PRINTF("ipf");
+ break;
+ case IPL_LOGAUTH :
+ PRINTF("auth");
+ break;
+ case IPL_LOGCOUNT :
+ PRINTF("count");
+ break;
+ default :
+ PRINTF("#%d", iph.iph_unit);
+ break;
+ }
+
+ if ((opts & OPT_DEBUG) == 0) {
+ if ((iph.iph_type & ~IPHASH_ANON) == IPHASH_LOOKUP)
+ PRINTF(" type = hash");
+ PRINTF(" number = %s size = %lu",
+ iph.iph_name, (u_long)iph.iph_size);
+ if (iph.iph_seed != 0)
+ PRINTF(" seed = %lu", iph.iph_seed);
+ putchar('\n');
+ } else {
+ PRINTF(" Type: ");
+ switch (iph.iph_type & ~IPHASH_ANON)
+ {
+ case IPHASH_LOOKUP :
+ PRINTF("lookup");
+ break;
+ case IPHASH_GROUPMAP :
+ PRINTF("groupmap Group. %s", iph.iph_name);
+ break;
+ default :
+ break;
+ }
+
+ putchar('\n');
+ PRINTF("\t\tSize: %lu\tSeed: %lu",
+ (u_long)iph.iph_size, iph.iph_seed);
+ PRINTF("\tRef. Count: %d\tMasks: %#x\n", iph.iph_ref,
+ iph.iph_masks);
+ }
+
+ if ((opts & OPT_DEBUG) != 0) {
+ struct in_addr m;
+
+ for (i = 0; i < 32; i++) {
+ if ((1 << i) & iph.iph_masks) {
+ ntomask(4, i, &m.s_addr);
+ PRINTF("\t\tMask: %s\n", inet_ntoa(m));
+ }
+ }
+ }
+
+ if ((opts & OPT_DEBUG) == 0)
+ PRINTF("\t{");
+
+ sz = iph.iph_size * sizeof(*table);
+ table = malloc(sz);
+ if ((*copyfunc)((char *)iph.iph_table, (char *)table, sz))
+ return NULL;
+
+ for (i = 0, printed = 0; i < iph.iph_size; i++) {
+ for (ipep = table[i]; ipep != NULL; ) {
+ ipep = printhashnode(&iph, ipep, copyfunc, opts);
+ printed++;
+ }
+ }
+ if (printed == 0)
+ putchar(';');
+
+ free(table);
+
+ if ((opts & OPT_DEBUG) == 0)
+ PRINTF(" };\n");
+
+ return iph.iph_next;
+}
diff --git a/contrib/ipfilter/lib/printhashnode.c b/contrib/ipfilter/lib/printhashnode.c
new file mode 100644
index 0000000..39255e7
--- /dev/null
+++ b/contrib/ipfilter/lib/printhashnode.c
@@ -0,0 +1,52 @@
+/* $NetBSD$ */
+
+/*
+ * Copyright (C) 2002 by Darren Reed.
+ *
+ * See the IPFILTER.LICENCE file for details on licencing.
+ */
+
+#include "ipf.h"
+
+#define PRINTF (void)printf
+#define FPRINTF (void)fprintf
+
+iphtent_t *printhashnode(iph, ipep, copyfunc, opts)
+iphtable_t *iph;
+iphtent_t *ipep;
+copyfunc_t copyfunc;
+int opts;
+{
+ iphtent_t ipe;
+
+ if ((*copyfunc)(ipep, &ipe, sizeof(ipe)))
+ return NULL;
+
+ ipe.ipe_addr.in4_addr = htonl(ipe.ipe_addr.in4_addr);
+ ipe.ipe_mask.in4_addr = htonl(ipe.ipe_mask.in4_addr);
+
+ if ((opts & OPT_DEBUG) != 0) {
+ PRINTF("\tAddress: %s",
+ inet_ntoa(ipe.ipe_addr.in4));
+ printmask((u_32_t *)&ipe.ipe_mask.in4_addr);
+ PRINTF("\tRef. Count: %d\tGroup: %s\n", ipe.ipe_ref,
+ ipe.ipe_group);
+ } else {
+ putchar(' ');
+ printip((u_32_t *)&ipe.ipe_addr.in4_addr);
+ printmask((u_32_t *)&ipe.ipe_mask.in4_addr);
+ if (ipe.ipe_value != 0) {
+ switch (iph->iph_type & ~IPHASH_ANON)
+ {
+ case IPHASH_GROUPMAP :
+ if (strncmp(ipe.ipe_group, iph->iph_name,
+ FR_GROUPLEN))
+ PRINTF(", group = %s", ipe.ipe_group);
+ break;
+ }
+ }
+ putchar(';');
+ }
+ ipep = ipe.ipe_next;
+ return ipep;
+}
diff --git a/contrib/ipfilter/lib/printhostmap.c b/contrib/ipfilter/lib/printhostmap.c
new file mode 100644
index 0000000..bdb6702
--- /dev/null
+++ b/contrib/ipfilter/lib/printhostmap.c
@@ -0,0 +1,13 @@
+/* $NetBSD$ */
+
+#include "ipf.h"
+
+void printhostmap(hmp, hv)
+hostmap_t *hmp;
+u_int hv;
+{
+ printf("%s,", inet_ntoa(hmp->hm_srcip));
+ printf("%s -> ", inet_ntoa(hmp->hm_dstip));
+ printf("%s ", inet_ntoa(hmp->hm_mapip));
+ printf("(use = %d hv = %u)\n", hmp->hm_ref, hv);
+}
diff --git a/contrib/ipfilter/lib/printhostmask.c b/contrib/ipfilter/lib/printhostmask.c
new file mode 100644
index 0000000..c34bc43
--- /dev/null
+++ b/contrib/ipfilter/lib/printhostmask.c
@@ -0,0 +1,46 @@
+/* $NetBSD$ */
+
+/*
+ * Copyright (C) 1993-2001 by Darren Reed.
+ *
+ * See the IPFILTER.LICENCE file for details on licencing.
+ *
+ * Id: printhostmask.c,v 1.8 2002/04/11 15:01:19 darrenr Exp
+ */
+
+#include "ipf.h"
+
+
+void printhostmask(v, addr, mask)
+int v;
+u_32_t *addr, *mask;
+{
+#ifdef USE_INET6
+ char ipbuf[64];
+#else
+ struct in_addr ipa;
+#endif
+
+ if (!*addr && !*mask)
+ printf("any");
+ else {
+#ifdef USE_INET6
+ void *ptr = addr;
+ int af;
+
+ if (v == 4) {
+ ptr = addr;
+ af = AF_INET;
+ } else if (v == 6) {
+ ptr = addr;
+ af = AF_INET6;
+ } else
+ af = 0;
+ printf("%s", inet_ntop(af, ptr, ipbuf, sizeof(ipbuf)));
+#else
+ ipa.s_addr = *addr;
+ printf("%s", inet_ntoa(ipa));
+#endif
+ printmask(mask);
+ }
+}
diff --git a/contrib/ipfilter/lib/printifname.c b/contrib/ipfilter/lib/printifname.c
new file mode 100644
index 0000000..53a7fd7
--- /dev/null
+++ b/contrib/ipfilter/lib/printifname.c
@@ -0,0 +1,20 @@
+/* $NetBSD$ */
+
+/*
+ * Copyright (C) 1993-2001 by Darren Reed.
+ *
+ * See the IPFILTER.LICENCE file for details on licencing.
+ *
+ * Id: printifname.c,v 1.2 2002/01/28 06:50:47 darrenr Exp
+ */
+
+#include "ipf.h"
+
+void printifname(format, name, ifp)
+char *format, *name;
+void *ifp;
+{
+ printf("%s%s", format, name);
+ if ((ifp == NULL) && strcmp(name, "-") && strcmp(name, "*"))
+ printf("(!)");
+}
diff --git a/contrib/ipfilter/lib/printip.c b/contrib/ipfilter/lib/printip.c
new file mode 100644
index 0000000..1a04f1d
--- /dev/null
+++ b/contrib/ipfilter/lib/printip.c
@@ -0,0 +1,24 @@
+/* $NetBSD$ */
+
+/*
+ * Copyright (C) 1993-2001 by Darren Reed.
+ *
+ * See the IPFILTER.LICENCE file for details on licencing.
+ *
+ * Id: printip.c,v 1.3 2002/07/13 12:10:27 darrenr Exp
+ */
+
+#include "ipf.h"
+
+
+void printip(addr)
+u_32_t *addr;
+{
+ struct in_addr ipa;
+
+ ipa.s_addr = *addr;
+ if (ntohl(ipa.s_addr) < 256)
+ printf("%lu", (u_long)ntohl(ipa.s_addr));
+ else
+ printf("%s", inet_ntoa(ipa));
+}
diff --git a/contrib/ipfilter/lib/printlog.c b/contrib/ipfilter/lib/printlog.c
new file mode 100644
index 0000000..d14add4
--- /dev/null
+++ b/contrib/ipfilter/lib/printlog.c
@@ -0,0 +1,44 @@
+/* $NetBSD$ */
+
+/*
+ * Copyright (C) 1993-2001 by Darren Reed.
+ *
+ * See the IPFILTER.LICENCE file for details on licencing.
+ *
+ * Id: printlog.c,v 1.6 2002/01/28 06:50:47 darrenr Exp
+ */
+
+#include "ipf.h"
+
+#include <syslog.h>
+
+
+void printlog(fp)
+frentry_t *fp;
+{
+ char *s, *u;
+
+ printf("log");
+ if (fp->fr_flags & FR_LOGBODY)
+ printf(" body");
+ if (fp->fr_flags & FR_LOGFIRST)
+ printf(" first");
+ if (fp->fr_flags & FR_LOGORBLOCK)
+ printf(" or-block");
+ if (fp->fr_loglevel != 0xffff) {
+ printf(" level ");
+ if (fp->fr_loglevel & LOG_FACMASK) {
+ s = fac_toname(fp->fr_loglevel);
+ if (s == NULL)
+ s = "!!!";
+ } else
+ s = "";
+ u = pri_toname(fp->fr_loglevel);
+ if (u == NULL)
+ u = "!!!";
+ if (*s)
+ printf("%s.%s", s, u);
+ else
+ printf("%s", u);
+ }
+}
diff --git a/contrib/ipfilter/lib/printmask.c b/contrib/ipfilter/lib/printmask.c
new file mode 100644
index 0000000..d3d9a6f
--- /dev/null
+++ b/contrib/ipfilter/lib/printmask.c
@@ -0,0 +1,30 @@
+/* $NetBSD$ */
+
+/*
+ * Copyright (C) 1993-2001 by Darren Reed.
+ *
+ * See the IPFILTER.LICENCE file for details on licencing.
+ *
+ * Id: printmask.c,v 1.5 2002/06/15 04:48:33 darrenr Exp
+ */
+
+#include "ipf.h"
+
+
+void printmask(mask)
+u_32_t *mask;
+{
+ struct in_addr ipa;
+ int ones;
+
+#ifdef USE_INET6
+ if (use_inet6)
+ printf("/%d", count6bits(mask));
+ else
+#endif
+ if ((ones = count4bits(*mask)) == -1) {
+ ipa.s_addr = *mask;
+ printf("/%s", inet_ntoa(ipa));
+ } else
+ printf("/%d", ones);
+}
diff --git a/contrib/ipfilter/lib/printnat.c b/contrib/ipfilter/lib/printnat.c
new file mode 100644
index 0000000..15a6886
--- /dev/null
+++ b/contrib/ipfilter/lib/printnat.c
@@ -0,0 +1,247 @@
+/* $NetBSD$ */
+
+/*
+ * Copyright (C) 1993-2001 by Darren Reed.
+ *
+ * See the IPFILTER.LICENCE file for details on licencing.
+ *
+ * Added redirect stuff and a variety of bug fixes. (mcn@EnGarde.com)
+ */
+
+#include "ipf.h"
+#include "kmem.h"
+
+
+#if !defined(lint)
+static const char rcsid[] = "@(#)Id: printnat.c,v 1.22.2.8 2005/01/12 03:39:04 darrenr Exp";
+#endif
+
+static void printproto __P((ipnat_t *, struct protoent *));
+
+/*
+ * Print out a NAT rule
+ */
+void printnat(np, opts)
+ipnat_t *np;
+int opts;
+{
+ struct protoent *pr;
+ int bits;
+
+ pr = getprotobynumber(np->in_p);
+
+ switch (np->in_redir)
+ {
+ case NAT_REDIRECT :
+ printf("rdr");
+ break;
+ case NAT_MAP :
+ printf("map");
+ break;
+ case NAT_MAPBLK :
+ printf("map-block");
+ break;
+ case NAT_BIMAP :
+ printf("bimap");
+ break;
+ default :
+ fprintf(stderr, "unknown value for in_redir: %#x\n",
+ np->in_redir);
+ break;
+ }
+
+ printf(" %s", np->in_ifnames[0]);
+ if ((np->in_ifnames[1][0] != '\0') &&
+ (strncmp(np->in_ifnames[0], np->in_ifnames[1], LIFNAMSIZ) != 0)) {
+ printf(",%s ", np->in_ifnames[1]);
+ }
+ putchar(' ');
+
+ if (np->in_flags & IPN_FILTER) {
+ if (np->in_flags & IPN_NOTSRC)
+ printf("! ");
+ printf("from ");
+ if (np->in_redir == NAT_REDIRECT) {
+ printhostmask(4, (u_32_t *)&np->in_srcip,
+ (u_32_t *)&np->in_srcmsk);
+ } else {
+ printhostmask(4, (u_32_t *)&np->in_inip,
+ (u_32_t *)&np->in_inmsk);
+ }
+ if (np->in_scmp)
+ printportcmp(np->in_p, &np->in_tuc.ftu_src);
+
+ if (np->in_flags & IPN_NOTDST)
+ printf(" !");
+ printf(" to ");
+ if (np->in_redir == NAT_REDIRECT) {
+ printhostmask(4, (u_32_t *)&np->in_outip,
+ (u_32_t *)&np->in_outmsk);
+ } else {
+ printhostmask(4, (u_32_t *)&np->in_srcip,
+ (u_32_t *)&np->in_srcmsk);
+ }
+ if (np->in_dcmp)
+ printportcmp(np->in_p, &np->in_tuc.ftu_dst);
+ }
+
+ if (np->in_redir == NAT_REDIRECT) {
+ if (!(np->in_flags & IPN_FILTER)) {
+ printf("%s", inet_ntoa(np->in_out[0].in4));
+ bits = count4bits(np->in_outmsk);
+ if (bits != -1)
+ printf("/%d", bits);
+ else
+ printf("/%s", inet_ntoa(np->in_out[1].in4));
+ if (np->in_flags & IPN_TCPUDP) {
+ printf(" port %d", ntohs(np->in_pmin));
+ if (np->in_pmax != np->in_pmin)
+ printf("-%d", ntohs(np->in_pmax));
+ }
+ }
+ printf(" -> %s", inet_ntoa(np->in_in[0].in4));
+ if (np->in_flags & IPN_SPLIT)
+ printf(",%s", inet_ntoa(np->in_in[1].in4));
+ if (np->in_flags & IPN_TCPUDP) {
+ if ((np->in_flags & IPN_FIXEDDPORT) != 0)
+ printf(" port = %d", ntohs(np->in_pnext));
+ else
+ printf(" port %d", ntohs(np->in_pnext));
+ }
+ printproto(np, pr);
+ if (np->in_flags & IPN_ROUNDR)
+ printf(" round-robin");
+ if (np->in_flags & IPN_FRAG)
+ printf(" frag");
+ if (np->in_age[0] != 0 || np->in_age[1] != 0) {
+ printf(" age %d/%d", np->in_age[0], np->in_age[1]);
+ }
+ if (np->in_flags & IPN_STICKY)
+ printf(" sticky");
+ if (np->in_mssclamp != 0)
+ printf(" mssclamp %d", np->in_mssclamp);
+ if (*np->in_plabel != '\0')
+ printf(" proxy %.*s", (int)sizeof(np->in_plabel),
+ np->in_plabel);
+ if (np->in_tag.ipt_tag[0] != '\0')
+ printf(" tag %-.*s", IPFTAG_LEN, np->in_tag.ipt_tag);
+ printf("\n");
+ if (opts & OPT_DEBUG)
+ printf("\tpmax %u\n", np->in_pmax);
+ } else {
+ if (!(np->in_flags & IPN_FILTER)) {
+ printf("%s/", inet_ntoa(np->in_in[0].in4));
+ bits = count4bits(np->in_inmsk);
+ if (bits != -1)
+ printf("%d", bits);
+ else
+ printf("%s", inet_ntoa(np->in_in[1].in4));
+ }
+ printf(" -> ");
+ if (np->in_flags & IPN_IPRANGE) {
+ printf("range %s-", inet_ntoa(np->in_out[0].in4));
+ printf("%s", inet_ntoa(np->in_out[1].in4));
+ } else {
+ printf("%s/", inet_ntoa(np->in_out[0].in4));
+ bits = count4bits(np->in_outmsk);
+ if (bits != -1)
+ printf("%d", bits);
+ else
+ printf("%s", inet_ntoa(np->in_out[1].in4));
+ }
+ if (*np->in_plabel != '\0') {
+ printf(" proxy port ");
+ if (np->in_dcmp != 0)
+ np->in_dport = htons(np->in_dport);
+ if (np->in_dport != 0) {
+ char *s;
+
+ s = portname(np->in_p, ntohs(np->in_dport));
+ if (s != NULL)
+ fputs(s, stdout);
+ else
+ fputs("???", stdout);
+ }
+ printf(" %.*s/", (int)sizeof(np->in_plabel),
+ np->in_plabel);
+ if (pr != NULL)
+ fputs(pr->p_name, stdout);
+ else
+ printf("%d", np->in_p);
+ } else if (np->in_redir == NAT_MAPBLK) {
+ if ((np->in_pmin == 0) &&
+ (np->in_flags & IPN_AUTOPORTMAP))
+ printf(" ports auto");
+ else
+ printf(" ports %d", np->in_pmin);
+ if (opts & OPT_DEBUG)
+ printf("\n\tip modulous %d", np->in_pmax);
+ } else if (np->in_pmin || np->in_pmax) {
+ if (np->in_flags & IPN_ICMPQUERY) {
+ printf(" icmpidmap");
+ } else {
+ printf(" portmap");
+ }
+ printproto(np, pr);
+ if (np->in_flags & IPN_AUTOPORTMAP) {
+ printf(" auto");
+ if (opts & OPT_DEBUG)
+ printf(" [%d:%d %d %d]",
+ ntohs(np->in_pmin),
+ ntohs(np->in_pmax),
+ np->in_ippip, np->in_ppip);
+ } else {
+ printf(" %d:%d", ntohs(np->in_pmin),
+ ntohs(np->in_pmax));
+ }
+ } else if (np->in_flags & IPN_TCPUDP || np->in_p)
+ printproto(np, pr);
+
+ if (np->in_flags & IPN_FRAG)
+ printf(" frag");
+ if (np->in_age[0] != 0 || np->in_age[1] != 0) {
+ printf(" age %d/%d", np->in_age[0], np->in_age[1]);
+ }
+ if (np->in_mssclamp != 0)
+ printf(" mssclamp %d", np->in_mssclamp);
+ if (np->in_tag.ipt_tag[0] != '\0')
+ printf(" tag %s", np->in_tag.ipt_tag);
+ printf("\n");
+ if (opts & OPT_DEBUG) {
+ struct in_addr nip;
+
+ nip.s_addr = htonl(np->in_nextip.s_addr);
+
+ printf("\tnextip %s pnext %d\n",
+ inet_ntoa(nip), np->in_pnext);
+ }
+ }
+
+ if (opts & OPT_DEBUG) {
+ printf("\tspace %lu use %u hits %lu flags %#x proto %d hv %d\n",
+ np->in_space, np->in_use, np->in_hits,
+ np->in_flags, np->in_p, np->in_hv);
+ printf("\tifp[0] %p ifp[1] %p apr %p\n",
+ np->in_ifps[0], np->in_ifps[1], np->in_apr);
+ printf("\ttqehead %p/%p comment %p\n",
+ np->in_tqehead[0], np->in_tqehead[1], np->in_comment);
+ }
+}
+
+static void printproto(np, pr)
+ipnat_t *np;
+struct protoent *pr;
+{
+ 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");
+ else if (np->in_flags & IPN_ICMPQUERY)
+ printf(" icmp");
+ else if (pr != NULL)
+ printf(" %s", pr->p_name);
+ else
+ printf(" %d", np->in_p);
+}
diff --git a/contrib/ipfilter/lib/printpacket.c b/contrib/ipfilter/lib/printpacket.c
new file mode 100644
index 0000000..58460be
--- /dev/null
+++ b/contrib/ipfilter/lib/printpacket.c
@@ -0,0 +1,89 @@
+/* $NetBSD$ */
+
+/*
+ * Copyright (C) 1993-2001 by Darren Reed.
+ *
+ * See the IPFILTER.LICENCE file for details on licencing.
+ *
+ * Id: printpacket.c,v 1.12.4.1 2005/02/21 05:09:24 darrenr Exp
+ */
+
+#include "ipf.h"
+
+#ifndef IP_OFFMASK
+# define IP_OFFMASK 0x3fff
+#endif
+
+
+void printpacket(ip)
+struct ip *ip;
+{
+ struct tcphdr *tcp;
+ u_short len;
+ u_short off;
+
+ if (IP_V(ip) == 6) {
+ off = 0;
+ len = ntohs(((u_short *)ip)[2]) + 40;
+ } else {
+ off = ntohs(ip->ip_off);
+ len = ntohs(ip->ip_len);
+ }
+
+ if ((opts & OPT_HEX) == OPT_HEX) {
+ u_char *s;
+ int i;
+
+ for (s = (u_char *)ip, i = 0; i < len; i++) {
+ printf("%02x", *s++ & 0xff);
+ if (len - i > 1) {
+ i++;
+ printf("%02x", *s++ & 0xff);
+ }
+ putchar(' ');
+ }
+ putchar('\n');
+ return;
+ }
+
+ if (IP_V(ip) == 6) {
+ printpacket6(ip);
+ return;
+ }
+
+ tcp = (struct tcphdr *)((char *)ip + (IP_HL(ip) << 2));
+ printf("ip %d(%d) %d", ntohs(ip->ip_len), IP_HL(ip) << 2, ip->ip_p);
+ if (off & IP_OFFMASK)
+ printf(" @%d", off << 3);
+ printf(" %s", inet_ntoa(ip->ip_src));
+ if (!(off & IP_OFFMASK))
+ if (ip->ip_p == IPPROTO_TCP || ip->ip_p == IPPROTO_UDP)
+ printf(",%d", ntohs(tcp->th_sport));
+ printf(" > ");
+ printf("%s", inet_ntoa(ip->ip_dst));
+ if (!(off & IP_OFFMASK)) {
+ if (ip->ip_p == IPPROTO_TCP || ip->ip_p == IPPROTO_UDP)
+ printf(",%d", ntohs(tcp->th_dport));
+ if ((ip->ip_p == IPPROTO_TCP) && (tcp->th_flags != 0)) {
+ putchar(' ');
+ if (tcp->th_flags & TH_FIN)
+ putchar('F');
+ if (tcp->th_flags & TH_SYN)
+ putchar('S');
+ if (tcp->th_flags & TH_RST)
+ putchar('R');
+ if (tcp->th_flags & TH_PUSH)
+ putchar('P');
+ if (tcp->th_flags & TH_ACK)
+ putchar('A');
+ if (tcp->th_flags & TH_URG)
+ putchar('U');
+ if (tcp->th_flags & TH_ECN)
+ putchar('E');
+ if (tcp->th_flags & TH_CWR)
+ putchar('C');
+ }
+ }
+
+ putchar('\n');
+}
diff --git a/contrib/ipfilter/lib/printpacket6.c b/contrib/ipfilter/lib/printpacket6.c
new file mode 100644
index 0000000..2f9ea1d
--- /dev/null
+++ b/contrib/ipfilter/lib/printpacket6.c
@@ -0,0 +1,43 @@
+/* $NetBSD$ */
+
+#include "ipf.h"
+
+/*
+ * This is meant to work without the IPv6 header files being present or
+ * the inet_ntop() library.
+ */
+void printpacket6(ip)
+struct ip *ip;
+{
+ u_char *buf, p;
+ u_short plen, *addrs;
+ tcphdr_t *tcp;
+ u_32_t flow;
+
+ buf = (u_char *)ip;
+ tcp = (tcphdr_t *)(buf + 40);
+ p = buf[6];
+ flow = ntohl(*(u_32_t *)buf);
+ flow &= 0xfffff;
+ plen = ntohs(*((u_short *)buf +2));
+ addrs = (u_short *)buf + 4;
+
+ printf("ip6/%d %d %#x %d", buf[0] & 0xf, plen, flow, p);
+ printf(" %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
+ ntohs(addrs[0]), ntohs(addrs[1]), ntohs(addrs[2]),
+ ntohs(addrs[3]), ntohs(addrs[4]), ntohs(addrs[5]),
+ ntohs(addrs[6]), ntohs(addrs[7]));
+ if (plen >= 4)
+ if (p == IPPROTO_TCP || p == IPPROTO_UDP)
+ (void)printf(",%d", ntohs(tcp->th_sport));
+ printf(" >");
+ addrs += 8;
+ printf(" %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
+ ntohs(addrs[0]), ntohs(addrs[1]), ntohs(addrs[2]),
+ ntohs(addrs[3]), ntohs(addrs[4]), ntohs(addrs[5]),
+ ntohs(addrs[6]), ntohs(addrs[7]));
+ if (plen >= 4)
+ if (p == IPPROTO_TCP || p == IPPROTO_UDP)
+ (void)printf(",%d", ntohs(tcp->th_dport));
+ putchar('\n');
+}
diff --git a/contrib/ipfilter/lib/printpool.c b/contrib/ipfilter/lib/printpool.c
new file mode 100644
index 0000000..6291306
--- /dev/null
+++ b/contrib/ipfilter/lib/printpool.c
@@ -0,0 +1,108 @@
+/* $NetBSD$ */
+
+/*
+ * Copyright (C) 2002 by Darren Reed.
+ *
+ * See the IPFILTER.LICENCE file for details on licencing.
+ */
+
+#include "ipf.h"
+
+#define PRINTF (void)printf
+#define FPRINTF (void)fprintf
+
+ip_pool_t *printpool(pp, copyfunc, name, opts)
+ip_pool_t *pp;
+copyfunc_t copyfunc;
+char *name;
+int opts;
+{
+ ip_pool_node_t *ipnp, *ipnpn, ipn;
+ ip_pool_t ipp;
+
+ if ((*copyfunc)(pp, &ipp, sizeof(ipp)))
+ return NULL;
+
+ if ((name != NULL) && strncmp(name, ipp.ipo_name, FR_GROUPLEN))
+ return ipp.ipo_next;
+
+ if ((opts & OPT_DEBUG) == 0) {
+ if ((ipp.ipo_flags & IPOOL_ANON) != 0)
+ PRINTF("# 'anonymous' tree %s\n", ipp.ipo_name);
+ PRINTF("table role = ");
+ } else {
+ PRINTF("Name: %s", ipp.ipo_name);
+ if ((ipp.ipo_flags & IPOOL_ANON) == IPOOL_ANON)
+ PRINTF("(anon)");
+ putchar(' ');
+ PRINTF("Role: ");
+ }
+
+ switch (ipp.ipo_unit)
+ {
+ case IPL_LOGIPF :
+ printf("ipf");
+ break;
+ case IPL_LOGNAT :
+ printf("nat");
+ break;
+ case IPL_LOGSTATE :
+ printf("state");
+ break;
+ case IPL_LOGAUTH :
+ printf("auth");
+ break;
+ case IPL_LOGSYNC :
+ printf("sync");
+ break;
+ case IPL_LOGSCAN :
+ printf("scan");
+ break;
+ case IPL_LOGLOOKUP :
+ printf("lookup");
+ break;
+ case IPL_LOGCOUNT :
+ printf("count");
+ break;
+ default :
+ printf("unknown(%d)", ipp.ipo_unit);
+ }
+
+ if ((opts & OPT_DEBUG) == 0) {
+ PRINTF(" type = tree number = %s\n", ipp.ipo_name);
+ PRINTF("\t{");
+ } else {
+ putchar(' ');
+
+ PRINTF("\tReferences: %d\tHits: %lu\n", ipp.ipo_ref,
+ ipp.ipo_hits);
+ PRINTF("\tNodes Starting at %p\n", ipp.ipo_list);
+ }
+
+ ipnpn = ipp.ipo_list;
+ ipp.ipo_list = NULL;
+ while (ipnpn != NULL) {
+ ipnp = (ip_pool_node_t *)malloc(sizeof(*ipnp));
+ (*copyfunc)(ipnpn, ipnp, sizeof(ipn));
+ ipnpn = ipnp->ipn_next;
+ ipnp->ipn_next = ipp.ipo_list;
+ ipp.ipo_list = ipnp;
+ }
+
+ if (ipp.ipo_list == NULL) {
+ putchar(';');
+ } else {
+ for (ipnp = ipp.ipo_list; ipnp != NULL; ) {
+ ipnp = printpoolnode(ipnp, opts);
+
+ if ((opts & OPT_DEBUG) == 0) {
+ putchar(';');
+ }
+ }
+ }
+
+ if ((opts & OPT_DEBUG) == 0)
+ PRINTF(" };\n");
+
+ return ipp.ipo_next;
+}
diff --git a/contrib/ipfilter/lib/printpoolnode.c b/contrib/ipfilter/lib/printpoolnode.c
new file mode 100644
index 0000000..dd0ef97
--- /dev/null
+++ b/contrib/ipfilter/lib/printpoolnode.c
@@ -0,0 +1,33 @@
+/* $NetBSD$ */
+
+/*
+ * Copyright (C) 2002 by Darren Reed.
+ *
+ * See the IPFILTER.LICENCE file for details on licencing.
+ */
+
+#include "ipf.h"
+
+#define PRINTF (void)printf
+#define FPRINTF (void)fprintf
+
+ip_pool_node_t *printpoolnode(np, opts)
+ip_pool_node_t *np;
+int opts;
+{
+
+ if ((opts & OPT_DEBUG) == 0) {
+ putchar(' ');
+ if (np->ipn_info == 1)
+ PRINTF("! ");
+ printip((u_32_t *)&np->ipn_addr.adf_addr.in4);
+ printmask((u_32_t *)&np->ipn_mask.adf_addr);
+ } else {
+ PRINTF("\t\t%s%s", np->ipn_info ? "! " : "",
+ inet_ntoa(np->ipn_addr.adf_addr.in4));
+ printmask((u_32_t *)&np->ipn_mask.adf_addr);
+ PRINTF("\n\t\tHits %lu\tName %s\n",
+ np->ipn_hits, np->ipn_name);
+ }
+ return np->ipn_next;
+}
diff --git a/contrib/ipfilter/lib/printportcmp.c b/contrib/ipfilter/lib/printportcmp.c
new file mode 100644
index 0000000..7ec0116
--- /dev/null
+++ b/contrib/ipfilter/lib/printportcmp.c
@@ -0,0 +1,29 @@
+/* $NetBSD$ */
+
+/*
+ * Copyright (C) 1993-2001 by Darren Reed.
+ *
+ * See the IPFILTER.LICENCE file for details on licencing.
+ *
+ * Id: printportcmp.c,v 1.7 2003/02/16 02:31:05 darrenr Exp
+ */
+
+#include "ipf.h"
+
+
+void printportcmp(pr, frp)
+int pr;
+frpcmp_t *frp;
+{
+ static char *pcmp1[] = { "*", "=", "!=", "<", ">", "<=", ">=",
+ "<>", "><", ":" };
+
+ if (frp->frp_cmp == FR_INRANGE || frp->frp_cmp == FR_OUTRANGE)
+ printf(" port %d %s %d", frp->frp_port,
+ pcmp1[frp->frp_cmp], frp->frp_top);
+ else if (frp->frp_cmp == FR_INCRANGE)
+ printf(" port %d:%d", frp->frp_port, frp->frp_top);
+ else
+ printf(" port %s %s", pcmp1[frp->frp_cmp],
+ portname(pr, frp->frp_port));
+}
diff --git a/contrib/ipfilter/lib/printsbuf.c b/contrib/ipfilter/lib/printsbuf.c
new file mode 100644
index 0000000..805c03b
--- /dev/null
+++ b/contrib/ipfilter/lib/printsbuf.c
@@ -0,0 +1,24 @@
+/* $NetBSD$ */
+
+#ifdef IPFILTER_SCAN
+
+#include <ctype.h>
+#include <stdio.h>
+#include "ipf.h"
+#include "netinet/ip_scan.h"
+
+void printsbuf(buf)
+char *buf;
+{
+ u_char *s;
+ int i;
+
+ for (s = (u_char *)buf, i = ISC_TLEN; i; i--, s++) {
+ if (ISPRINT(*s))
+ putchar(*s);
+ else
+ printf("\\%o", *s);
+ }
+}
+
+#endif
diff --git a/contrib/ipfilter/lib/printstate.c b/contrib/ipfilter/lib/printstate.c
new file mode 100644
index 0000000..9cfdc8a
--- /dev/null
+++ b/contrib/ipfilter/lib/printstate.c
@@ -0,0 +1,189 @@
+/* $NetBSD$ */
+
+/*
+ * Copyright (C) 2002 by Darren Reed.
+ *
+ * See the IPFILTER.LICENCE file for details on licencing.
+ */
+
+#include "ipf.h"
+#include "kmem.h"
+
+#define PRINTF (void)printf
+#define FPRINTF (void)fprintf
+
+ipstate_t *printstate(sp, opts, now)
+ipstate_t *sp;
+int opts;
+u_long now;
+{
+ ipstate_t ips;
+ synclist_t ipsync;
+
+ if (kmemcpy((char *)&ips, (u_long)sp, sizeof(ips)))
+ return NULL;
+
+ PRINTF("%s -> ", hostname(ips.is_v, &ips.is_src.in4));
+ PRINTF("%s pass %#x pr %d state %d/%d bkt %d\n",
+ hostname(ips.is_v, &ips.is_dst.in4), ips.is_pass, ips.is_p,
+ ips.is_state[0], ips.is_state[1], ips.is_hv);
+ PRINTF("\ttag %u ttl %lu", ips.is_tag, ips.is_die - now);
+
+ if (ips.is_p == IPPROTO_TCP) {
+ PRINTF("\n\t%hu -> %hu %x:%x %hu<<%d:%hu<<%d\n",
+ ntohs(ips.is_sport), ntohs(ips.is_dport),
+ ips.is_send, ips.is_dend,
+ ips.is_maxswin, ips.is_swinscale,
+ ips.is_maxdwin, ips.is_dwinscale);
+ PRINTF("\tcmsk %04x smsk %04x isc %p s0 %08x/%08x\n",
+ ips.is_smsk[0], ips.is_smsk[1], ips.is_isc,
+ ips.is_s0[0], ips.is_s0[1]);
+ PRINTF("\tFWD:ISN inc %x sumd %x\n",
+ ips.is_isninc[0], ips.is_sumd[0]);
+ PRINTF("\tREV:ISN inc %x sumd %x\n",
+ ips.is_isninc[1], ips.is_sumd[1]);
+#ifdef IPFILTER_SCAN
+ PRINTF("\tsbuf[0] [");
+ printsbuf(ips.is_sbuf[0]);
+ PRINTF("] sbuf[1] [");
+ printsbuf(ips.is_sbuf[1]);
+ PRINTF("]\n");
+#endif
+ } else if (ips.is_p == IPPROTO_UDP) {
+ PRINTF(" %hu -> %hu\n", ntohs(ips.is_sport),
+ ntohs(ips.is_dport));
+ } else if (ips.is_p == IPPROTO_GRE) {
+ PRINTF(" call %hx/%hx\n", ntohs(ips.is_gre.gs_call[0]),
+ ntohs(ips.is_gre.gs_call[1]));
+ } else if (ips.is_p == IPPROTO_ICMP
+#ifdef USE_INET6
+ || ips.is_p == IPPROTO_ICMPV6
+#endif
+ )
+ PRINTF(" id %hu seq %hu type %d\n", ips.is_icmp.ici_id,
+ ips.is_icmp.ici_seq, ips.is_icmp.ici_type);
+
+#ifdef USE_QUAD_T
+ PRINTF("\tforward: pkts in %qd bytes in %qd pkts out %qd bytes out %qd\n\tbackward: pkts in %qd bytes in %qd pkts out %qd bytes out %qd\n",
+ ips.is_pkts[0], ips.is_bytes[0],
+ ips.is_pkts[1], ips.is_bytes[1],
+ ips.is_pkts[2], ips.is_bytes[2],
+ ips.is_pkts[3], ips.is_bytes[3]);
+#else
+ PRINTF("\tforward: pkts in %ld bytes in %ld pkts out %ld bytes out %ld\n\tbackward: pkts in %ld bytes in %ld pkts out %ld bytes out %ld\n",
+ ips.is_pkts[0], ips.is_bytes[0],
+ ips.is_pkts[1], ips.is_bytes[1],
+ ips.is_pkts[2], ips.is_bytes[2],
+ ips.is_pkts[3], ips.is_bytes[3]);
+#endif
+
+ PRINTF("\t");
+
+ /*
+ * Print out bits set in the result code for the state being
+ * kept as they would for a rule.
+ */
+ if (FR_ISPASS(ips.is_pass)) {
+ PRINTF("pass");
+ } else if (FR_ISBLOCK(ips.is_pass)) {
+ PRINTF("block");
+ switch (ips.is_pass & FR_RETMASK)
+ {
+ case FR_RETICMP :
+ PRINTF(" return-icmp");
+ break;
+ case FR_FAKEICMP :
+ PRINTF(" return-icmp-as-dest");
+ break;
+ case FR_RETRST :
+ PRINTF(" return-rst");
+ break;
+ default :
+ break;
+ }
+ } else if ((ips.is_pass & FR_LOGMASK) == FR_LOG) {
+ PRINTF("log");
+ if (ips.is_pass & FR_LOGBODY)
+ PRINTF(" body");
+ if (ips.is_pass & FR_LOGFIRST)
+ PRINTF(" first");
+ } else if (FR_ISACCOUNT(ips.is_pass)) {
+ PRINTF("count");
+ } else if (FR_ISPREAUTH(ips.is_pass)) {
+ PRINTF("preauth");
+ } else if (FR_ISAUTH(ips.is_pass))
+ PRINTF("auth");
+
+ if (ips.is_pass & FR_OUTQUE)
+ PRINTF(" out");
+ else
+ PRINTF(" in");
+
+ if ((ips.is_pass & FR_LOG) != 0) {
+ PRINTF(" log");
+ if (ips.is_pass & FR_LOGBODY)
+ PRINTF(" body");
+ if (ips.is_pass & FR_LOGFIRST)
+ PRINTF(" first");
+ if (ips.is_pass & FR_LOGORBLOCK)
+ PRINTF(" or-block");
+ }
+ if (ips.is_pass & FR_QUICK)
+ PRINTF(" quick");
+ if (ips.is_pass & FR_KEEPFRAG)
+ PRINTF(" keep frags");
+ /* a given; no? */
+ if (ips.is_pass & FR_KEEPSTATE) {
+ PRINTF(" keep state");
+ if (ips.is_pass & FR_STATESYNC)
+ PRINTF(" ( sync )");
+ }
+ PRINTF("\tIPv%d", ips.is_v);
+ PRINTF("\n");
+
+ PRINTF("\tpkt_flags & %x(%x) = %x,\t",
+ ips.is_flags & 0xf, ips.is_flags,
+ ips.is_flags >> 4);
+ PRINTF("\tpkt_options & %x = %x\n", ips.is_optmsk,
+ ips.is_opt);
+ PRINTF("\tpkt_security & %x = %x, pkt_auth & %x = %x\n",
+ ips.is_secmsk, ips.is_sec, ips.is_authmsk,
+ ips.is_auth);
+ PRINTF("\tis_flx %#x %#x %#x %#x\n", ips.is_flx[0][0], ips.is_flx[0][1],
+ ips.is_flx[1][0], ips.is_flx[1][1]);
+ PRINTF("\tinterfaces: in %s[%s", getifname(ips.is_ifp[0]),
+ ips.is_ifname[0]);
+ if (opts & OPT_DEBUG)
+ PRINTF("/%p", ips.is_ifp[0]);
+ putchar(']');
+ PRINTF(",%s[%s", getifname(ips.is_ifp[1]), ips.is_ifname[1]);
+ if (opts & OPT_DEBUG)
+ PRINTF("/%p", ips.is_ifp[1]);
+ putchar(']');
+ PRINTF(" out %s[%s", getifname(ips.is_ifp[2]), ips.is_ifname[2]);
+ if (opts & OPT_DEBUG)
+ PRINTF("/%p", ips.is_ifp[2]);
+ putchar(']');
+ PRINTF(",%s[%s", getifname(ips.is_ifp[3]), ips.is_ifname[3]);
+ if (opts & OPT_DEBUG)
+ PRINTF("/%p", ips.is_ifp[3]);
+ PRINTF("]\n");
+
+ if (ips.is_sync != NULL) {
+
+ if (kmemcpy((char *)&ipsync, (u_long)ips.is_sync, sizeof(ipsync))) {
+
+ PRINTF("\tSync status: status could not be retrieved\n");
+ return NULL;
+ }
+
+ PRINTF("\tSync status: idx %d num %d v %d pr %d rev %d\n",
+ ipsync.sl_idx, ipsync.sl_num, ipsync.sl_v,
+ ipsync.sl_p, ipsync.sl_rev);
+
+ } else {
+ PRINTF("\tSync status: not synchronized\n");
+ }
+
+ return ips.is_next;
+}
diff --git a/contrib/ipfilter/lib/printtunable.c b/contrib/ipfilter/lib/printtunable.c
new file mode 100644
index 0000000..46e9f80
--- /dev/null
+++ b/contrib/ipfilter/lib/printtunable.c
@@ -0,0 +1,21 @@
+/* $NetBSD$ */
+
+#include "ipf.h"
+
+void printtunable(tup)
+ipftune_t *tup;
+{
+ printf("%s\tmin %#lx\tmax %#lx\tcurrent ",
+ tup->ipft_name, tup->ipft_min, tup->ipft_max);
+ if (tup->ipft_sz == sizeof(u_long))
+ printf("%lu\n", tup->ipft_vlong);
+ else if (tup->ipft_sz == sizeof(u_int))
+ printf("%u\n", tup->ipft_vint);
+ else if (tup->ipft_sz == sizeof(u_short))
+ printf("%hu\n", tup->ipft_vshort);
+ else if (tup->ipft_sz == sizeof(u_char))
+ printf("%u\n", (u_int)tup->ipft_vchar);
+ else {
+ printf("sz = %d\n", tup->ipft_sz);
+ }
+}
diff --git a/contrib/ipfilter/lib/ratoi.c b/contrib/ipfilter/lib/ratoi.c
new file mode 100644
index 0000000..31ee122
--- /dev/null
+++ b/contrib/ipfilter/lib/ratoi.c
@@ -0,0 +1,26 @@
+/* $NetBSD$ */
+
+/*
+ * Copyright (C) 1993-2001 by Darren Reed.
+ *
+ * See the IPFILTER.LICENCE file for details on licencing.
+ *
+ * Id: ratoi.c,v 1.4 2001/06/09 17:09:25 darrenr Exp
+ */
+
+#include "ipf.h"
+
+
+int ratoi(ps, pi, min, max)
+char *ps;
+int *pi, min, max;
+{
+ int i;
+ char *pe;
+
+ i = (int)strtol(ps, &pe, 0);
+ if (*pe != '\0' || i < min || i > max)
+ return 0;
+ *pi = i;
+ return 1;
+}
diff --git a/contrib/ipfilter/lib/ratoui.c b/contrib/ipfilter/lib/ratoui.c
new file mode 100644
index 0000000..e4d0cbf
--- /dev/null
+++ b/contrib/ipfilter/lib/ratoui.c
@@ -0,0 +1,26 @@
+/* $NetBSD$ */
+
+/*
+ * Copyright (C) 1993-2001 by Darren Reed.
+ *
+ * See the IPFILTER.LICENCE file for details on licencing.
+ *
+ * Id: ratoui.c,v 1.4 2001/06/09 17:09:25 darrenr Exp
+ */
+
+#include "ipf.h"
+
+
+int ratoui(ps, pi, min, max)
+char *ps;
+u_int *pi, min, max;
+{
+ u_int i;
+ char *pe;
+
+ i = (u_int)strtol(ps, &pe, 0);
+ if (*pe != '\0' || i < min || i > max)
+ return 0;
+ *pi = i;
+ return 1;
+}
diff --git a/contrib/ipfilter/lib/remove_hash.c b/contrib/ipfilter/lib/remove_hash.c
new file mode 100644
index 0000000..256751f
--- /dev/null
+++ b/contrib/ipfilter/lib/remove_hash.c
@@ -0,0 +1,53 @@
+/* $NetBSD$ */
+
+/*
+ * Copyright (C) 2002 by Darren Reed.
+ *
+ * See the IPFILTER.LICENCE file for details on licencing.
+ *
+ * Id: remove_hash.c,v 1.1 2003/04/13 06:40:14 darrenr Exp
+ */
+
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include "ipf.h"
+#include "netinet/ip_lookup.h"
+#include "netinet/ip_htable.h"
+
+static int hashfd = -1;
+
+
+int remove_hash(iphp, iocfunc)
+iphtable_t *iphp;
+ioctlfunc_t iocfunc;
+{
+ iplookupop_t op;
+ iphtable_t iph;
+
+ if ((hashfd == -1) && ((opts & OPT_DONOTHING) == 0))
+ hashfd = open(IPLOOKUP_NAME, O_RDWR);
+ if ((hashfd == -1) && ((opts & OPT_DONOTHING) == 0))
+ return -1;
+
+ op.iplo_type = IPLT_HASH;
+ op.iplo_unit = iphp->iph_unit;
+ strncpy(op.iplo_name, iphp->iph_name, sizeof(op.iplo_name));
+ if (*op.iplo_name == '\0')
+ op.iplo_arg = IPHASH_ANON;
+ op.iplo_size = sizeof(iph);
+ op.iplo_struct = &iph;
+
+ bzero((char *)&iph, sizeof(iph));
+ iph.iph_unit = iphp->iph_unit;
+ iph.iph_type = iphp->iph_type;
+ strncpy(iph.iph_name, iphp->iph_name, sizeof(iph.iph_name));
+ iph.iph_flags = iphp->iph_flags;
+
+ if ((*iocfunc)(hashfd, SIOCLOOKUPDELTABLE, &op))
+ if ((opts & OPT_DONOTHING) == 0) {
+ perror("remove_hash:SIOCLOOKUPDELTABLE");
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/contrib/ipfilter/lib/remove_hashnode.c b/contrib/ipfilter/lib/remove_hashnode.c
new file mode 100644
index 0000000..5e5b634
--- /dev/null
+++ b/contrib/ipfilter/lib/remove_hashnode.c
@@ -0,0 +1,58 @@
+/* $NetBSD$ */
+
+/*
+ * Copyright (C) 2002 by Darren Reed.
+ *
+ * See the IPFILTER.LICENCE file for details on licencing.
+ *
+ * Id: remove_hashnode.c,v 1.1 2003/04/13 06:40:14 darrenr Exp
+ */
+
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include "ipf.h"
+#include "netinet/ip_lookup.h"
+#include "netinet/ip_htable.h"
+
+static int hashfd = -1;
+
+
+int remove_hashnode(unit, name, node, iocfunc)
+int unit;
+char *name;
+iphtent_t *node;
+ioctlfunc_t iocfunc;
+{
+ iplookupop_t op;
+ iphtent_t ipe;
+
+ if ((hashfd == -1) && ((opts & OPT_DONOTHING) == 0))
+ hashfd = open(IPLOOKUP_NAME, O_RDWR);
+ if ((hashfd == -1) && ((opts & OPT_DONOTHING) == 0))
+ return -1;
+
+ op.iplo_type = IPLT_HASH;
+ op.iplo_unit = unit;
+ op.iplo_size = sizeof(ipe);
+ op.iplo_struct = &ipe;
+ op.iplo_arg = 0;
+ strncpy(op.iplo_name, name, sizeof(op.iplo_name));
+
+ bzero((char *)&ipe, sizeof(ipe));
+ bcopy((char *)&node->ipe_addr, (char *)&ipe.ipe_addr,
+ sizeof(ipe.ipe_addr));
+ bcopy((char *)&node->ipe_mask, (char *)&ipe.ipe_mask,
+ sizeof(ipe.ipe_mask));
+
+ if (opts & OPT_DEBUG) {
+ printf("\t%s - ", inet_ntoa(ipe.ipe_addr.in4));
+ printf("%s\n", inet_ntoa(ipe.ipe_mask.in4));
+ }
+
+ if ((*iocfunc)(hashfd, SIOCLOOKUPDELNODE, &op))
+ if (!(opts & OPT_DONOTHING)) {
+ perror("remove_hash:SIOCLOOKUPDELNODE");
+ return -1;
+ }
+ return 0;
+}
diff --git a/contrib/ipfilter/lib/remove_pool.c b/contrib/ipfilter/lib/remove_pool.c
new file mode 100644
index 0000000..3f5e004
--- /dev/null
+++ b/contrib/ipfilter/lib/remove_pool.c
@@ -0,0 +1,50 @@
+/* $NetBSD$ */
+
+/*
+ * Copyright (C) 2002 by Darren Reed.
+ *
+ * See the IPFILTER.LICENCE file for details on licencing.
+ *
+ * Id: remove_pool.c,v 1.1 2003/04/13 06:40:14 darrenr Exp
+ */
+
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include "ipf.h"
+#include "netinet/ip_lookup.h"
+#include "netinet/ip_htable.h"
+
+static int poolfd = -1;
+
+
+int remove_pool(poolp, iocfunc)
+ip_pool_t *poolp;
+ioctlfunc_t iocfunc;
+{
+ iplookupop_t op;
+ ip_pool_t pool;
+
+ if ((poolfd == -1) && ((opts & OPT_DONOTHING) == 0))
+ poolfd = open(IPLOOKUP_NAME, O_RDWR);
+ if ((poolfd == -1) && ((opts & OPT_DONOTHING) == 0))
+ return -1;
+
+ op.iplo_type = IPLT_POOL;
+ op.iplo_unit = poolp->ipo_unit;
+ strncpy(op.iplo_name, poolp->ipo_name, sizeof(op.iplo_name));
+ op.iplo_size = sizeof(pool);
+ op.iplo_struct = &pool;
+
+ bzero((char *)&pool, sizeof(pool));
+ pool.ipo_unit = poolp->ipo_unit;
+ strncpy(pool.ipo_name, poolp->ipo_name, sizeof(pool.ipo_name));
+ pool.ipo_flags = poolp->ipo_flags;
+
+ if ((*iocfunc)(poolfd, SIOCLOOKUPDELTABLE, &op))
+ if ((opts & OPT_DONOTHING) == 0) {
+ perror("remove_pool:SIOCLOOKUPDELTABLE");
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/contrib/ipfilter/lib/remove_poolnode.c b/contrib/ipfilter/lib/remove_poolnode.c
new file mode 100644
index 0000000..aff4694
--- /dev/null
+++ b/contrib/ipfilter/lib/remove_poolnode.c
@@ -0,0 +1,57 @@
+/* $NetBSD$ */
+
+/*
+ * Copyright (C) 2002 by Darren Reed.
+ *
+ * See the IPFILTER.LICENCE file for details on licencing.
+ *
+ * Id: remove_poolnode.c,v 1.3 2003/11/22 10:14:36 darrenr Exp
+ */
+
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include "ipf.h"
+#include "netinet/ip_lookup.h"
+#include "netinet/ip_pool.h"
+
+static int poolfd = -1;
+
+
+int remove_poolnode(unit, name, node, iocfunc)
+int unit;
+char *name;
+ip_pool_node_t *node;
+ioctlfunc_t iocfunc;
+{
+ ip_pool_node_t pn;
+ iplookupop_t op;
+
+ if ((poolfd == -1) && ((opts & OPT_DONOTHING) == 0))
+ poolfd = open(IPLOOKUP_NAME, O_RDWR);
+ if ((poolfd == -1) && ((opts & OPT_DONOTHING) == 0))
+ return -1;
+
+ op.iplo_unit = unit;
+ op.iplo_type = IPLT_POOL;
+ op.iplo_arg = 0;
+ strncpy(op.iplo_name, name, sizeof(op.iplo_name));
+ op.iplo_struct = &pn;
+ op.iplo_size = sizeof(pn);
+
+ bzero((char *)&pn, sizeof(pn));
+ bcopy((char *)&node->ipn_addr, (char *)&pn.ipn_addr,
+ sizeof(pn.ipn_addr));
+ bcopy((char *)&node->ipn_mask, (char *)&pn.ipn_mask,
+ sizeof(pn.ipn_mask));
+ pn.ipn_info = node->ipn_info;
+ strncpy(pn.ipn_name, node->ipn_name, sizeof(pn.ipn_name));
+
+ if ((*iocfunc)(poolfd, SIOCLOOKUPDELNODE, &op)) {
+ if ((opts & OPT_DONOTHING) == 0) {
+ perror("remove_pool:SIOCLOOKUPDELNODE");
+ return -1;
+ }
+ }
+
+ return 0;
+}
diff --git a/contrib/ipfilter/lib/resetlexer.c b/contrib/ipfilter/lib/resetlexer.c
new file mode 100644
index 0000000..0801242
--- /dev/null
+++ b/contrib/ipfilter/lib/resetlexer.c
@@ -0,0 +1,17 @@
+/* $NetBSD$ */
+
+#include "ipf.h"
+
+long string_start = -1;
+long string_end = -1;
+char *string_val = NULL;
+long pos = 0;
+
+
+void resetlexer()
+{
+ string_start = -1;
+ string_end = -1;
+ string_val = NULL;
+ pos = 0;
+}
diff --git a/contrib/ipfilter/lib/rwlock_emul.c b/contrib/ipfilter/lib/rwlock_emul.c
new file mode 100644
index 0000000..64b807e
--- /dev/null
+++ b/contrib/ipfilter/lib/rwlock_emul.c
@@ -0,0 +1,125 @@
+/* $NetBSD$ */
+
+#include "ipf.h"
+
+#define EMM_MAGIC 0x97dd8b3a
+
+void eMrwlock_read_enter(rw, file, line)
+eMrwlock_t *rw;
+char *file;
+int line;
+{
+ if (rw->eMrw_magic != EMM_MAGIC) {
+ fprintf(stderr, "%s:eMrwlock_read_enter(%p): bad magic: %#x\n",
+ rw->eMrw_owner, rw, rw->eMrw_magic);
+ abort();
+ }
+ if (rw->eMrw_read != 0 || rw->eMrw_write != 0) {
+ fprintf(stderr,
+ "%s:eMrwlock_read_enter(%p): already locked: %d/%d\n",
+ rw->eMrw_owner, rw, rw->eMrw_read, rw->eMrw_write);
+ abort();
+ }
+ rw->eMrw_read++;
+ rw->eMrw_heldin = file;
+ rw->eMrw_heldat = line;
+}
+
+
+void eMrwlock_write_enter(rw, file, line)
+eMrwlock_t *rw;
+char *file;
+int line;
+{
+ if (rw->eMrw_magic != EMM_MAGIC) {
+ fprintf(stderr, "%s:eMrwlock_write_enter(%p): bad magic: %#x\n",
+ rw->eMrw_owner, rw, rw->eMrw_magic);
+ abort();
+ }
+ if (rw->eMrw_read != 0 || rw->eMrw_write != 0) {
+ fprintf(stderr,
+ "%s:eMrwlock_write_enter(%p): already locked: %d/%d\n",
+ rw->eMrw_owner, rw, rw->eMrw_read, rw->eMrw_write);
+ abort();
+ }
+ rw->eMrw_write++;
+ rw->eMrw_heldin = file;
+ rw->eMrw_heldat = line;
+}
+
+
+void eMrwlock_downgrade(rw, file, line)
+eMrwlock_t *rw;
+char *file;
+int line;
+{
+ if (rw->eMrw_magic != EMM_MAGIC) {
+ fprintf(stderr, "%s:eMrwlock_write_enter(%p): bad magic: %#x\n",
+ rw->eMrw_owner, rw, rw->eMrw_magic);
+ abort();
+ }
+ if (rw->eMrw_read != 0 || rw->eMrw_write != 1) {
+ fprintf(stderr,
+ "%s:eMrwlock_write_enter(%p): already locked: %d/%d\n",
+ rw->eMrw_owner, rw, rw->eMrw_read, rw->eMrw_write);
+ abort();
+ }
+ rw->eMrw_write--;
+ rw->eMrw_read++;
+ rw->eMrw_heldin = file;
+ rw->eMrw_heldat = line;
+}
+
+
+void eMrwlock_exit(rw)
+eMrwlock_t *rw;
+{
+ if (rw->eMrw_magic != EMM_MAGIC) {
+ fprintf(stderr, "%s:eMrwlock_exit(%p): bad magic: %#x\n",
+ rw->eMrw_owner, rw, rw->eMrw_magic);
+ abort();
+ }
+ if (rw->eMrw_read != 1 && rw->eMrw_write != 1) {
+ fprintf(stderr, "%s:eMrwlock_exit(%p): not locked: %d/%d\n",
+ rw->eMrw_owner, rw, rw->eMrw_read, rw->eMrw_write);
+ abort();
+ }
+ if (rw->eMrw_read == 1)
+ rw->eMrw_read--;
+ else if (rw->eMrw_write == 1)
+ rw->eMrw_write--;
+ rw->eMrw_heldin = NULL;
+ rw->eMrw_heldat = 0;
+}
+
+
+void eMrwlock_init(rw, who)
+eMrwlock_t *rw;
+char *who;
+{
+ if (rw->eMrw_magic == EMM_MAGIC) { /* safe bet ? */
+ fprintf(stderr,
+ "%s:eMrwlock_init(%p): already initialised?: %#x\n",
+ rw->eMrw_owner, rw, rw->eMrw_magic);
+ abort();
+ }
+ rw->eMrw_magic = EMM_MAGIC;
+ rw->eMrw_read = 0;
+ rw->eMrw_write = 0;
+ if (who != NULL)
+ rw->eMrw_owner = strdup(who);
+ else
+ rw->eMrw_owner = NULL;
+}
+
+
+void eMrwlock_destroy(rw)
+eMrwlock_t *rw;
+{
+ if (rw->eMrw_magic != EMM_MAGIC) {
+ fprintf(stderr, "%s:eMrwlock_destroy(%p): bad magic: %#x\n",
+ rw->eMrw_owner, rw, rw->eMrw_magic);
+ abort();
+ }
+ memset(rw, 0xa5, sizeof(*rw));
+}
diff --git a/contrib/ipfilter/lib/tcp_flags.c b/contrib/ipfilter/lib/tcp_flags.c
new file mode 100644
index 0000000..314b9d2
--- /dev/null
+++ b/contrib/ipfilter/lib/tcp_flags.c
@@ -0,0 +1,50 @@
+/* $NetBSD$ */
+
+/*
+ * Copyright (C) 1993-2001 by Darren Reed.
+ *
+ * See the IPFILTER.LICENCE file for details on licencing.
+ *
+ * Id: tcp_flags.c,v 1.8 2004/02/07 18:15:54 darrenr Exp
+ */
+
+#include "ipf.h"
+
+extern char flagset[];
+extern u_char flags[];
+
+
+u_char tcp_flags(flgs, mask, linenum)
+char *flgs;
+u_char *mask;
+int linenum;
+{
+ u_char tcpf = 0, tcpfm = 0;
+ char *s;
+
+ s = strchr(flgs, '/');
+ if (s)
+ *s++ = '\0';
+
+ if (*flgs == '0') {
+ tcpf = strtol(flgs, NULL, 0);
+ } else {
+ tcpf = tcpflags(flgs);
+ }
+
+ if (s != NULL) {
+ if (*s == '0')
+ tcpfm = strtol(s, NULL, 0);
+ else
+ tcpfm = tcpflags(s);
+ }
+
+ if (!tcpfm) {
+ if (tcpf == TH_SYN)
+ tcpfm = 0xff & ~(TH_ECN|TH_CWR);
+ else
+ tcpfm = 0xff & ~(TH_ECN);
+ }
+ *mask = tcpfm;
+ return tcpf;
+}
diff --git a/contrib/ipfilter/lib/tcpflags.c b/contrib/ipfilter/lib/tcpflags.c
new file mode 100644
index 0000000..b7ea4b8
--- /dev/null
+++ b/contrib/ipfilter/lib/tcpflags.c
@@ -0,0 +1,45 @@
+/* $NetBSD$ */
+
+/*
+ * Copyright (C) 1993-2001 by Darren Reed.
+ *
+ * See the IPFILTER.LICENCE file for details on licencing.
+ *
+ * Id: tcpflags.c,v 1.3 2002/11/02 07:18:01 darrenr Exp
+ */
+
+#include "ipf.h"
+
+
+/*
+ * ECN is a new addition to TCP - RFC 2481
+ */
+#ifndef TH_ECN
+# define TH_ECN 0x40
+#endif
+#ifndef TH_CWR
+# define TH_CWR 0x80
+#endif
+
+extern char flagset[];
+extern u_char flags[];
+
+
+u_char tcpflags(flgs)
+char *flgs;
+{
+ u_char tcpf = 0;
+ char *s, *t;
+
+ for (s = flgs; *s; s++) {
+ if (*s == 'W')
+ tcpf |= TH_CWR;
+ else {
+ if (!(t = strchr(flagset, *s))) {
+ return 0;
+ }
+ tcpf |= flags[t - flagset];
+ }
+ }
+ return tcpf;
+}
diff --git a/contrib/ipfilter/lib/tcpoptnames.c b/contrib/ipfilter/lib/tcpoptnames.c
new file mode 100644
index 0000000..b5e0cc7
--- /dev/null
+++ b/contrib/ipfilter/lib/tcpoptnames.c
@@ -0,0 +1,22 @@
+/* $NetBSD$ */
+
+/*
+ * Copyright (C) 1993-2001 by Darren Reed.
+ *
+ * See the IPFILTER.LICENCE file for details on licencing.
+ *
+ * Id: tcpoptnames.c,v 1.5 2002/01/28 06:50:48 darrenr Exp
+ */
+
+#include "ipf.h"
+
+
+struct ipopt_names tcpoptnames[] ={
+ { TCPOPT_NOP, 0x000001, 1, "nop" },
+ { TCPOPT_MAXSEG, 0x000002, 4, "maxseg" },
+ { TCPOPT_WINDOW, 0x000004, 3, "wscale" },
+ { TCPOPT_SACK_PERMITTED, 0x000008, 2, "sackok" },
+ { TCPOPT_SACK, 0x000010, 3, "sack" },
+ { TCPOPT_TIMESTAMP, 0x000020, 10, "tstamp" },
+ { 0, 0, 0, (char *)NULL } /* must be last */
+};
diff --git a/contrib/ipfilter/lib/to_interface.c b/contrib/ipfilter/lib/to_interface.c
new file mode 100644
index 0000000..50f9a70
--- /dev/null
+++ b/contrib/ipfilter/lib/to_interface.c
@@ -0,0 +1,31 @@
+/* $NetBSD$ */
+
+/*
+ * Copyright (C) 1993-2001 by Darren Reed.
+ *
+ * See the IPFILTER.LICENCE file for details on licencing.
+ *
+ * Id: to_interface.c,v 1.8 2002/01/28 06:50:48 darrenr Exp
+ */
+
+#include "ipf.h"
+
+
+int to_interface(fdp, to, linenum)
+frdest_t *fdp;
+char *to;
+int linenum;
+{
+ char *s;
+
+ s = strchr(to, ':');
+ fdp->fd_ifp = NULL;
+ if (s) {
+ *s++ = '\0';
+ if (hostnum((u_32_t *)&fdp->fd_ip, s, linenum, NULL) == -1)
+ return -1;
+ }
+ (void) strncpy(fdp->fd_ifname, to, sizeof(fdp->fd_ifname) - 1);
+ fdp->fd_ifname[sizeof(fdp->fd_ifname) - 1] = '\0';
+ return 0;
+}
diff --git a/contrib/ipfilter/lib/v6ionames.c b/contrib/ipfilter/lib/v6ionames.c
new file mode 100644
index 0000000..087da5d
--- /dev/null
+++ b/contrib/ipfilter/lib/v6ionames.c
@@ -0,0 +1,27 @@
+/* $NetBSD$ */
+
+/*
+ * Copyright (C) 1993-2001 by Darren Reed.
+ *
+ * See the IPFILTER.LICENCE file for details on licencing.
+ *
+ * Id: v6ionames.c,v 1.1.4.1 2005/01/02 13:08:49 darrenr Exp
+ */
+#include "ipf.h"
+
+
+#ifdef USE_INET6
+
+struct ipopt_names v6ionames[] ={
+ { IPPROTO_HOPOPTS, 0x000001, 0, "hopopts" },
+ { IPPROTO_IPV6, 0x000002, 0, "ipv6" },
+ { IPPROTO_ROUTING, 0x000004, 0, "routing" },
+ { IPPROTO_FRAGMENT, 0x000008, 0, "frag" },
+ { IPPROTO_ESP, 0x000010, 0, "esp" },
+ { IPPROTO_AH, 0x000020, 0, "ah" },
+ { IPPROTO_NONE, 0x000040, 0, "none" },
+ { IPPROTO_DSTOPTS, 0x000080, 0, "dstopts" },
+ { 0, 0, 0, (char *)NULL }
+};
+
+#endif
diff --git a/contrib/ipfilter/lib/v6optvalue.c b/contrib/ipfilter/lib/v6optvalue.c
new file mode 100644
index 0000000..57dc2fb
--- /dev/null
+++ b/contrib/ipfilter/lib/v6optvalue.c
@@ -0,0 +1,39 @@
+/* $NetBSD$ */
+
+/*
+ * Copyright (C) 1993-2001 by Darren Reed.
+ *
+ * See the IPFILTER.LICENCE file for details on licencing.
+ *
+ * Id: v6optvalue.c,v 1.1 2003/04/26 04:55:58 darrenr Exp
+ */
+#include "ipf.h"
+
+
+
+u_32_t getv6optbyname(optname)
+char *optname;
+{
+#ifdef USE_INET6
+ struct ipopt_names *io;
+
+ for (io = v6ionames; io->on_name; io++)
+ if (!strcasecmp(optname, io->on_name))
+ return io->on_bit;
+#endif
+ return -1;
+}
+
+
+u_32_t getv6optbyvalue(optval)
+int optval;
+{
+#ifdef USE_INET6
+ struct ipopt_names *io;
+
+ for (io = v6ionames; io->on_name; io++)
+ if (io->on_value == optval)
+ return io->on_bit;
+#endif
+ return -1;
+}
diff --git a/contrib/ipfilter/lib/var.c b/contrib/ipfilter/lib/var.c
new file mode 100644
index 0000000..79b2517
--- /dev/null
+++ b/contrib/ipfilter/lib/var.c
@@ -0,0 +1,171 @@
+/* $NetBSD$ */
+
+#include <ctype.h>
+
+#include "ipf.h"
+
+typedef struct variable {
+ struct variable *v_next;
+ char *v_name;
+ char *v_value;
+} variable_t;
+
+static variable_t *vtop = NULL;
+
+static variable_t *find_var __P((char *));
+static char *expand_string __P((char *, int));
+
+
+static variable_t *find_var(name)
+char *name;
+{
+ variable_t *v;
+
+ for (v = vtop; v != NULL; v = v->v_next)
+ if (!strcmp(name, v->v_name))
+ return v;
+ return NULL;
+}
+
+
+char *get_variable(string, after, line)
+char *string, **after;
+int line;
+{
+ char c, *s, *t, *value;
+ variable_t *v;
+
+ s = string;
+
+ if (*s == '{') {
+ s++;
+ for (t = s; *t != '\0'; t++)
+ if (*t == '}')
+ break;
+ if (*t == '\0') {
+ fprintf(stderr, "%d: { without }\n", line);
+ return NULL;
+ }
+ } else if (ISALPHA(*s)) {
+ for (t = s + 1; *t != '\0'; t++)
+ if (!ISALPHA(*t) && !ISDIGIT(*t) && (*t != '_'))
+ break;
+ } else {
+ fprintf(stderr, "%d: variables cannot start with '%c'\n",
+ line, *s);
+ return NULL;
+ }
+
+ if (after != NULL)
+ *after = t;
+ c = *t;
+ *t = '\0';
+ v = find_var(s);
+ *t = c;
+ if (v == NULL) {
+ fprintf(stderr, "%d: unknown variable '%s'\n", line, s);
+ return NULL;
+ }
+
+ s = strdup(v->v_value);
+ value = expand_string(s, line);
+ if (value != s)
+ free(s);
+ return value;
+}
+
+
+static char *expand_string(oldstring, line)
+char *oldstring;
+int line;
+{
+ char c, *s, *p1, *p2, *p3, *newstring, *value;
+ int len;
+
+ p3 = NULL;
+ newstring = oldstring;
+
+ for (s = oldstring; *s != '\0'; s++)
+ if (*s == '$') {
+ *s = '\0';
+ s++;
+
+ switch (*s)
+ {
+ case '$' :
+ bcopy(s, s - 1, strlen(s));
+ break;
+ default :
+ c = *s;
+ if (c == '\0')
+ return newstring;
+
+ value = get_variable(s, &p3, line);
+ if (value == NULL)
+ return NULL;
+
+ p2 = expand_string(value, line);
+ if (p2 == NULL)
+ return NULL;
+
+ len = strlen(newstring) + strlen(p2);
+ if (p3 != NULL) {
+ if (c == '{' && *p3 == '}')
+ p3++;
+ len += strlen(p3);
+ }
+ p1 = malloc(len + 1);
+ if (p1 == NULL)
+ return NULL;
+
+ *(s - 1) = '\0';
+ strcpy(p1, newstring);
+ strcat(p1, p2);
+ if (p3 != NULL)
+ strcat(p1, p3);
+
+ s = p1 + len - strlen(p3) - 1;
+ if (newstring != oldstring)
+ free(newstring);
+ newstring = p1;
+ break;
+ }
+ }
+ return newstring;
+}
+
+
+void set_variable(name, value)
+char *name;
+char *value;
+{
+ variable_t *v;
+ int len;
+
+ if (name == NULL || value == NULL || *name == '\0')
+ return;
+
+ v = find_var(name);
+ if (v != NULL) {
+ free(v->v_value);
+ v->v_value = strdup(value);
+ return;
+ }
+
+ len = strlen(value);
+
+ if ((*value == '"' && value[len - 1] == '"') ||
+ (*value == '\'' && value[len - 1] == '\'')) {
+ value[len - 1] = '\0';
+ value++;
+ len -=2;
+ }
+
+ v = (variable_t *)malloc(sizeof(*v));
+ if (v == NULL)
+ return;
+ v->v_name = strdup(name);
+ v->v_value = strdup(value);
+ v->v_next = vtop;
+ vtop = v;
+}
diff --git a/contrib/ipfilter/lib/verbose.c b/contrib/ipfilter/lib/verbose.c
new file mode 100644
index 0000000..d4f3012
--- /dev/null
+++ b/contrib/ipfilter/lib/verbose.c
@@ -0,0 +1,37 @@
+/* $NetBSD$ */
+
+/*
+ * Copyright (C) 1993-2001 by Darren Reed.
+ *
+ * See the IPFILTER.LICENCE file for details on licencing.
+ *
+ * Id: verbose.c,v 1.6 2001/06/09 17:09:25 darrenr Exp
+ */
+
+#if defined(__STDC__)
+# include <stdarg.h>
+#else
+# include <varargs.h>
+#endif
+#include <stdio.h>
+
+#include "ipt.h"
+#include "opts.h"
+
+
+#if defined(__STDC__)
+void verbose(char *fmt, ...)
+#else
+void verbose(fmt, va_alist)
+char *fmt;
+va_dcl
+#endif
+{
+ va_list pvar;
+
+ va_start(pvar, fmt);
+
+ if (opts & OPT_VERBOSE)
+ vprintf(fmt, pvar);
+ va_end(pvar);
+}
diff --git a/contrib/ipfilter/man/Makefile b/contrib/ipfilter/man/Makefile
index 05164d7..3f12ccb 100644
--- a/contrib/ipfilter/man/Makefile
+++ b/contrib/ipfilter/man/Makefile
@@ -1,9 +1,7 @@
#
# Copyright (C) 1993-1998 by Darren Reed.
#
-# Redistribution and use in source and binary forms are permitted
-# provided that this notice is preserved and due credit is given
-# to the original author and the contributors.
+# See the IPFILTER.LICENCE file for details on licencing.
#
all:
@@ -12,12 +10,19 @@ install:
$(INSTALL) -m 0644 -c -o root -g bin ipftest.1 $(MANDIR)/man1
$(INSTALL) -m 0644 -c -o root -g bin ipnat.8 $(MANDIR)/man8
$(INSTALL) -m 0644 -c -o root -g bin ipf.4 $(MANDIR)/man4
+ $(INSTALL) -m 0644 -c -o root -g bin ipfilter.4 $(MANDIR)/man4
$(INSTALL) -m 0644 -c -o root -g bin ipl.4 $(MANDIR)/man4
$(INSTALL) -m 0644 -c -o root -g bin ipnat.4 $(MANDIR)/man4
$(INSTALL) -m 0644 -c -o root -g bin ipf.5 $(MANDIR)/man5
+ $(INSTALL) -m 0644 -c -o root -g bin ipfilter.5 $(MANDIR)/man5
$(INSTALL) -m 0644 -c -o root -g bin ipnat.5 $(MANDIR)/man5
$(INSTALL) -m 0644 -c -o root -g bin ipf.8 $(MANDIR)/man8
$(INSTALL) -m 0644 -c -o root -g bin ipfs.8 $(MANDIR)/man8
$(INSTALL) -m 0644 -c -o root -g bin ipmon.8 $(MANDIR)/man8
+ $(INSTALL) -m 0644 -c -o root -g bin ipmon.5 $(MANDIR)/man5
+ $(INSTALL) -m 0644 -c -o root -g bin ippool.8 $(MANDIR)/man8
+ $(INSTALL) -m 0644 -c -o root -g bin ippool.5 $(MANDIR)/man5
+ $(INSTALL) -m 0644 -c -o root -g bin ipscan.8 $(MANDIR)/man8
+ $(INSTALL) -m 0644 -c -o root -g bin ipscan.5 $(MANDIR)/man5
$(INSTALL) -m 0644 -c -o root -g bin ipfstat.8 $(MANDIR)/man8
@echo "Remember to rebuild the whatis database."
diff --git a/contrib/ipfilter/man/ipfilter.4 b/contrib/ipfilter/man/ipfilter.4
new file mode 100644
index 0000000..cf8ca9f
--- /dev/null
+++ b/contrib/ipfilter/man/ipfilter.4
@@ -0,0 +1,241 @@
+.\" $NetBSD$
+.\"
+.TH IP\ FILTER 4
+.SH NAME
+ipfilter \- Introduction to IP packet filtering
+.SH DESCRIPTION
+IP Filter is a TCP/IP packet filter, suitable for use in a firewall
+environment. To use, it can either be used as a loadable kernel module or
+incorporated into your UNIX kernel; use as a loadable kernel module where
+possible is highly recommended. Scripts are provided to install and patch
+system files, as required.
+.SH FEATURES
+The IP packet filter can:
+.IP
+explicitly deny/permit any packet from passing through
+.IP
+distinguish between various interfaces
+.IP
+filter by IP networks or hosts
+.IP
+selectively filter any IP protocol
+.IP
+selectively filter fragmented IP packets
+.IP
+selectively filter packets with IP options
+.IP
+send back an ICMP error/TCP reset for blocked packets
+.IP
+keep packet state information for TCP, UDP and ICMP packet flows
+.IP
+keep fragment state information for any IP packet, applying the same rule
+to all fragments.
+.IP
+act as a Network Address Translator (NAT)
+.IP
+use redirection to setup true transparent proxy connections
+.IP
+provide packet header details to a user program for authentication
+.IP
+in addition, supports temporary storage of pre-authenticated rules for passing packets through
+.PP
+Special provision is made for the three most common Internet protocols, TCP,
+UDP and ICMP. The IP Packet filter allows filtering of:
+.IP
+Inverted host/net matchingTCP/UDP packets by port number or a port number
+range
+.IP
+ICMP packets by type/code
+.IP
+"established" TCP packets
+.IP
+On any arbitrary combination of TCP flags
+.IP
+"short" (fragmented) IP packets with incomplete headers can be filtered
+.IP
+any of the 19 IP options or 8 registered IP security classes TOS (Type of
+Service) field in packets
+.PP
+To keep track of the performance of the IP packet filter, a logging device
+is used which supports logging of:
+.IP
+the TCP/UDP/ICMP and IP packet headers
+.IP
+the first 128 bytes of the packet (including headers)
+.PP
+A packet can be logged when:
+.IP
+it is successfully passed through
+.IP
+it is blocked from passing through
+.IP
+it matches a rule setup to look for suspicious packets
+.PP
+IP Filter keeps its own set of statistics on:
+.IP
+packets blocked
+.IP
+packets (and bytes!) used for accounting
+.IP
+packets passed
+.lP
+packets logged
+.IP
+attempts to log which failed (buffer full)
+.IP
+and much more, for packets going both in and out.
+
+.SH Tools
+The current implementation provides a small set of tools, which can easily
+be used and integrated with regular unix shells and tools. A brief description
+of the tools provided:
+.PP
+ipf(8)
+reads in a set of rules, from either stdin or a file, and adds them to
+the kernels current list (appending them). It can also be used to flush the
+current filter set or delete individual filter rules. The file format is
+described in ipf(5).
+.PP
+ipfs(8)
+is a utility to temporarily lock the IP Filter kernel tables (state tables
+and NAT mappings) and write them to disk. After that the system can be
+rebooted, and ipfs can be used to read these tables from disk and restore
+them into the kernel. This way the system can be rebooted without the
+connections being terminated.
+.PP
+ipfstat(8)
+interrogates the kernel for statistics on packet filtering, so
+far, and retrieves the list of filters in operation for inbound and outbound
+packets.
+.PP
+ipftest(1)
+reads in a filter rule file and then applies sample IP packets to
+the rule file. This allows for testing of filter list and examination of how
+a packet is passed along through it.
+.PP
+ipmon(8)
+reads buffered data from the logging device (default is /dev/ipl)
+for output to either:
+.IP
+screen (standard output)
+.IP
+file
+.IP
+syslog
+.PP
+ipsend(1)
+generates arbitary IP packets for ethernet connected machines.
+.PP
+ipresend(1)
+reads in a data file of saved IP packets (ie
+snoop/tcpdump/etherfind output) and sends it back across the network.
+.PP
+iptest(1)
+contains a set of test "programs" which send out a series of IP
+packets, aimed at testing the strength of the TCP/IP stack at which it is
+aimed at. WARNING: this may crash machine(s) targeted!
+.PP
+ipnat(8)
+reads in a set of rules, from either stdin or a file and adds them
+to the kernels current list of active NAT rules. NAT rules can also be
+deleted using ipnat. The format of the configuration file to be used
+with ipnat is described in ipnat(5).
+.PP
+For use in your own programs (e.g. for writing of transparent application
+proxies), the programming interface and the associated ioctl's are
+documented in ipf(4).
+
+Documentation on ioctl's and the format of data saved
+to the logging character device is provided in ipl(4)
+so that you may develop your own applications to work with or in place of any
+of the above.
+
+Similar, the interface to the NAT code is documented in ipnat(4).
+
+.SH PACKET PROCESSING FLOW
+The following diagram illustrates the flow of TCP/IP packets through the
+various stages introduced by IP Filter.
+.PP
+.nf
+ IN
+ |
+ V
+ +-------------------------+--------------------------+
+ | | |
+ | V |
+ | Network Address Translation |
+ | | |
+ | authenticated | |
+ | +-------<---------+ |
+ | | | |
+ | | V |
+ | V IP Accounting |
+ | | | |
+ | | V |
+ | | Fragment Cache Check--+ |
+ | | | | |
+ | V V V |
+ | | Packet State Check-->+ |
+ | | | | |
+ | | +->--+ | | |
+ | | | | V | |
+ | V groups IP Filtering V |
+ | | | | | | |
+ | | +--<-+ | | |
+ | | | | |
+ | +---------------->|<-----------+ |
+ | | |
+ | V |
+ | +---<----+ |
+ | | | |
+ | function | |
+ | | V |
+ | +--->----+ |
+ | | |
+ | V |
+ +--|---<--- fast-route ---<--+ |
+ | | | |
+ | | V |
+ | +-------------------------+--------------------------+
+ | |
+ | pass only
+ | |
+ | V
+ V [KERNEL TCP/IP Processing]
+ | |
+ | +-------------------------+--------------------------+
+ | | | |
+ | | V |
+ | | Fragment Cache Check--+ |
+ | | | | |
+ | | V V |
+ | | Packet State Check-->+ |
+ | | | | |
+ | | V | |
+ V | IP Filtering | |
+ | | | V |
+ | | |<-----------+ |
+ | | V |
+ | | IP Accounting |
+ | | | |
+ | | V |
+ | | Network Address Translation |
+ | | | |
+ | | V |
+ | +-------------------------+--------------------------+
+ | |
+ | pass only
+ V |
+ +--------------------------->|
+ V
+ OUT
+.fi
+
+.SH MORE INFORMATION
+More information (including pointers to the FAQ and the mailing list) can be
+obtained from the sofware's official homepage: www.ipfilter.org
+
+.SH SEE ALSO
+ipf(4), ipf(5), ipf(8), ipfilter(5), ipfs(8), ipfstat(8), ipftest(1),
+ipl(4), ipmon(8), ipnat(8), ipnat(4),
+
diff --git a/contrib/ipfilter/man/ipfilter.4.mandoc b/contrib/ipfilter/man/ipfilter.4.mandoc
new file mode 100644
index 0000000..72534a7
--- /dev/null
+++ b/contrib/ipfilter/man/ipfilter.4.mandoc
@@ -0,0 +1,267 @@
+.Dd December 8, 2000
+.Dt IP\ FILTER 4
+.Os
+.Sh NAME
+.Nm IP Filter
+.Nd Introduction to IP packet filtering
+.Sh DESCRIPTION
+IP Filter is a TCP/IP packet filter, suitable for use in a firewall
+environment. To use, it can either be used as a loadable kernel module or
+incorporated into your UNIX kernel; use as a loadable kernel module where
+possible is highly recommended. Scripts are provided to install and patch
+system files, as required.
+.Sh FEATURES
+The IP packet filter can:
+.Bl -bullet -offset indent -compact
+.It
+explicitly deny/permit any packet from passing through
+.It
+distinguish between various interfaces
+.It
+filter by IP networks or hosts
+.It
+selectively filter any IP protocol
+.It
+selectively filter fragmented IP packets
+.It
+selectively filter packets with IP options
+.It
+send back an ICMP error/TCP reset for blocked packets
+.It
+keep packet state information for TCP, UDP and ICMP packet flows
+.It
+keep fragment state information for any IP packet, applying the same rule
+to all fragments.
+.It
+act as a Network Address Translator (NAT)
+.It
+use redirection to setup true transparent proxy connections
+.It
+provide packet header details to a user program for authentication
+.It
+in addition, supports temporary storage of pre-authenticated rules for passing packets through
+.El
+.Pp
+Special provision is made for the three most common Internet protocols, TCP,
+UDP and ICMP. The IP Packet filter allows filtering of:
+.Bl -bullet -offset indent -compact
+.It
+Inverted host/net matchingTCP/UDP packets by port number or a port number
+range
+.It
+ICMP packets by type/code
+.It
+"established" TCP packets
+.It
+On any arbitrary combination of TCP flags
+.It
+"short" (fragmented) IP packets with incomplete headers can be filtered
+.It
+any of the 19 IP options or 8 registered IP security classes TOS (Type of
+Service) field in packets
+.El
+.Pp
+To keep track of the performance of the IP packet filter, a logging device
+is used which supports logging of:
+.Bl -bullet -offset indent -compact
+.It
+the TCP/UDP/ICMP and IP packet headers
+.It
+the first 128 bytes of the packet (including headers)
+.El
+.Pp
+A packet can be logged when:
+.Bl -bullet -offset indent -compact
+.It
+it is successfully passed through
+.It
+it is blocked from passing through
+.It
+it matches a rule setup to look for suspicious packets
+.El
+.Pp
+IP Filter keeps its own set of statistics on:
+.Bl -bullet -offset indent -compact
+.It
+packets blocked
+.It
+packets (and bytes!) used for accounting
+.It
+packets passed
+.li
+packets logged
+.It
+attempts to log which failed (buffer full)
+.El
+and much more, for packets going both in and out.
+
+.Sh Tools
+The current implementation provides a small set of tools, which can easily
+be used and integrated with regular unix shells and tools. A brief description
+of the tools provided:
+.Pp
+.Xr ipf 8
+reads in a set of rules, from either stdin or a file, and adds them to
+the kernels current list (appending them). It can also be used to flush the
+current filter set or delete individual filter rules. The file format is
+described in
+.Xr ipf 5 .
+.Pp
+.Xr ipfs 8
+is a utility to temporarily lock the IP Filter kernel tables (state tables
+and NAT mappings) and write them to disk. After that the system can be
+rebooted, and ipfs can be used to read these tables from disk and restore
+them into the kernel. This way the system can be rebooted without the
+connections being terminated.
+.Pp
+.Xr ipfstat 8
+interrogates the kernel for statistics on packet filtering, so
+far, and retrieves the list of filters in operation for inbound and outbound
+packets.
+.Pp
+.Xr ipftest 1
+reads in a filter rule file and then applies sample IP packets to
+the rule file. This allows for testing of filter list and examination of how
+a packet is passed along through it.
+.Pp
+.Xr ipmon 8
+reads buffered data from the logging device (default is /dev/ipl)
+for output to either:
+.Bl -bullet -offset indent -compact
+.It
+screen (standard output)
+.It
+file
+.It
+syslog
+.El
+.Pp
+.Xr ipsend 1
+generates arbitary IP packets for ethernet connected machines.
+.Pp
+.Xr ipresend 1
+reads in a data file of saved IP packets (ie
+snoop/tcpdump/etherfind output) and sends it back across the network.
+.Pp
+.Xr iptest 1
+contains a set of test "programs" which send out a series of IP
+packets, aimed at testing the strength of the TCP/IP stack at which it is
+aimed at. WARNING: this may crash machine(s) targeted!
+.Pp
+.Xr ipnat 8
+reads in a set of rules, from either stdin or a file and adds them
+to the kernels current list of active NAT rules. NAT rules can also be
+deleted using ipnat. The format of the configuration file to be used
+with ipnat is described in
+.Xr ipnat 5 .
+.Pp
+For use in your own programs (e.g. for writing of transparent application
+proxies), the programming interface and the associated ioctl's are
+documented in
+.Xr ipf 4 .
+
+Documentation on ioctl's and the format of data saved
+to the logging character device is provided in
+.Xr ipl 4
+so that you may develop your own applications to work with or in place of any
+of the above.
+
+Similar, the interface to the NAT code is documented in
+.Xr ipnat 4 .
+
+.Sh PACKET PROCESSING FLOW
+The following diagram illustrates the flow of TCP/IP packets through the
+various stages introduced by IP Filter.
+.Pp
+.nf
+ IN
+ |
+ V
+ +-------------------------+--------------------------+
+ | | |
+ | V |
+ | Network Address Translation |
+ | | |
+ | authenticated | |
+ | +-------<---------+ |
+ | | | |
+ | | V |
+ | V IP Accounting |
+ | | | |
+ | | V |
+ | | Fragment Cache Check--+ |
+ | | | | |
+ | V V V |
+ | | Packet State Check-->+ |
+ | | | | |
+ | | +->--+ | | |
+ | | | | V | |
+ | V groups IP Filtering V |
+ | | | | | | |
+ | | +--<-+ | | |
+ | | | | |
+ | +---------------->|<-----------+ |
+ | | |
+ | V |
+ | +---<----+ |
+ | | | |
+ | function | |
+ | | V |
+ | +--->----+ |
+ | | |
+ | V |
+ +--|---<--- fast-route ---<--+ |
+ | | | |
+ | | V |
+ | +-------------------------+--------------------------+
+ | |
+ | pass only
+ | |
+ | V
+ V [KERNEL TCP/IP Processing]
+ | |
+ | +-------------------------+--------------------------+
+ | | | |
+ | | V |
+ | | Fragment Cache Check--+ |
+ | | | | |
+ | | V V |
+ | | Packet State Check-->+ |
+ | | | | |
+ | | V | |
+ V | IP Filtering | |
+ | | | V |
+ | | |<-----------+ |
+ | | V |
+ | | IP Accounting |
+ | | | |
+ | | V |
+ | | Network Address Translation |
+ | | | |
+ | | V |
+ | +-------------------------+--------------------------+
+ | |
+ | pass only
+ V |
+ +--------------------------->|
+ V
+ OUT
+.fi
+
+.Sh MORE INFORMATION
+More information (including pointers to the FAQ and the mailing list) can be
+obtained from the sofware's official homepage: www.ipfilter.org
+
+.Sh SEE ALSO
+.Xr ipf 4 ,
+.Xr ipf 5 ,
+.Xr ipf 8 ,
+.Xr ipfilter 5 ,
+.Xr ipfs 8 ,
+.Xr ipfstat 8 ,
+.Xr ipftest 1 ,
+.Xr ipl 4 ,
+.Xr ipmon 8 ,
+.Xr ipnat 4 ,
+.Xr ipnat 8 ,
+
diff --git a/contrib/ipfilter/man/ipfs.8 b/contrib/ipfilter/man/ipfs.8
index b07935a..52f6fcb 100644
--- a/contrib/ipfilter/man/ipfs.8
+++ b/contrib/ipfilter/man/ipfs.8
@@ -1,3 +1,5 @@
+.\" $NetBSD$
+.\"
.TH IPFS 8
.SH NAME
ipfs \- saves and restores information for NAT and state tables.
@@ -54,7 +56,7 @@ and
options for saving state information.
.TP
.B \-n
-Don't actually take any action that would effect information stored in
+Don't actually take any action that would affect information stored in
the kernel or on disk.
.TP
.B \-v
@@ -90,17 +92,17 @@ and does not change the lock once complete.
.B \-R
Restores all saved state information, if any, from two files,
\fIipstate.ipf\fP and \fIipnat.ipf\fP, stored in the \fI/var/db/ipf\fP
-directory unless otherwise specified the
+directory unless otherwise specified by the
.B \-d
-option is used. The state tables are locked at the beginning of this
+option. The state tables are locked at the beginning of this
operation and unlocked once complete.
.TP
.B \-W
Saves in-kernel state information, if any, out to two files,
\fIipstate.ipf\fP and \fIipnat.ipf\fP, stored in the \fI/var/db/ipf\fP
-directory unless otherwise specified the
+directory unless otherwise specified by the
.B \-d
-option is used. The state tables are locked at the beginning of this
+option. The state tables are locked at the beginning of this
operation and unlocked once complete.
.DT
.SH FILES
diff --git a/contrib/ipfilter/man/ipl.4 b/contrib/ipfilter/man/ipl.4
index 0368f03..d45749b 100644
--- a/contrib/ipfilter/man/ipl.4
+++ b/contrib/ipfilter/man/ipl.4
@@ -1,3 +1,5 @@
+.\" $NetBSD$
+.\"
.TH IPL 4
.SH NAME
ipl \- IP packet log device
@@ -50,7 +52,7 @@ a buffer big enough to hold at least 1 complete log record - reading of partial
log records is not supported.
.PP
If the packet contents are more than 128 bytes when \fBlog body\fP is used,
-then only 128 bytes of the packet contents is logged.
+then only 128 bytes of the packet contents are logged.
.PP
Although it is only possible to read from the \fBipl\fP device, opening it
for writing is required when using an ioctl which changes any kernel data.
@@ -76,4 +78,4 @@ ipf(4)
.SH BUGS
Packet headers are dropped when the internal buffer (static size) fills.
.SH FILES
-/dev/ipl
+/dev/ipl0
diff --git a/contrib/ipfilter/man/ipmon.5 b/contrib/ipfilter/man/ipmon.5
new file mode 100644
index 0000000..bc48466
--- /dev/null
+++ b/contrib/ipfilter/man/ipmon.5
@@ -0,0 +1,69 @@
+.\" $NetBSD$
+.\"
+.TH IPMON 5
+.SH NAME
+ipmon, ipmon.conf \- ipmon configuration file format
+.SH DESCRIPTION
+The format for files accepted by ipmon is described by the following grammar:
+.LP
+.nf
+"match" "{" matchlist "}" "do" "{" doing "}" ";"
+
+matchlist ::= matching [ "," matching ] .
+matching ::= direction | dstip | dstport | every | group | interface |
+ logtag | nattag | protocol | result | rule | srcip | srcport .
+
+dolist ::= doing [ "," doing ] .
+doing ::= execute | save | syslog .
+
+direction ::= "in" | "out" .
+dstip ::= "dstip" "=" ipv4 "/" number .
+dstport ::= "dstport" "=" number .
+every ::= "every" every-options .
+execute ::= "execute" "=" string .
+group ::= "group" "=" string | "group" "=" number .
+interface ::= "interface" "=" string .
+logtag ::= "logtag" "=" string | "logtag" "=" number .
+nattag ::= "nattag" "=" string .
+protocol ::= "protocol" "=" string | "protocol" "=" number .
+result ::= "result" "=" result-option .
+rule ::= "rule" "=" number .
+srcip ::= "srcip" "=" ipv4 "/" number .
+srcport ::= "srcport" "=" number .
+type ::= "type" "=" ipftype .
+ipv4 ::= number "." number "." number "." number .
+
+every-options ::= "second" | number "seconds" | "packet" | number "packets" .
+result-option ::= "pass" | "block" | "short" | "nomatch" | "log" .
+ipftype ::= "ipf" | "nat" | "state" .
+
+.fi
+.PP
+In addition, lines that start with a # are considered to be comments.
+.TP
+.SH OVERVIEW
+.PP
+The ipmon configuration file is used for defining rules to be executed when
+logging records are read from
+.B /dev/ipl.
+.PP
+At present, only IPv4 matching is available for source/destination address
+matching.
+.SH MATCHING
+.PP
+Each rule for ipmon consists of two primary segments: the first describes how
+the log record is to be matched, the second defines what action to take if
+there is a positive match. All entries of the rules present in the file are
+compared for matches - there is no first or last rule match.
+.SH FILES
+/dev/ipl
+.br
+/dev/ipf
+.br
+/dev/ipnat
+.br
+/dev/ipstate
+.br
+/etc/ipmon.conf
+.SH SEE ALSO
+ipmon(8), ipl(4)
diff --git a/contrib/ipfilter/man/ipnat.5 b/contrib/ipfilter/man/ipnat.5
index 2bedd0c..7db3308 100644
--- a/contrib/ipfilter/man/ipnat.5
+++ b/contrib/ipfilter/man/ipnat.5
@@ -1,3 +1,5 @@
+.\" $NetBSD$
+.\"
.TH IPNAT 5
.SH NAME
ipnat, ipnat.conf \- IP NAT file format
@@ -7,45 +9,47 @@ The format for files accepted by ipnat is described by the following grammar:
.nf
ipmap :: = mapblock | redir | map .
-map ::= mapit ifname ipmask "->" dstipmask [ mapport ] mapoptions.
-map ::= mapit ifname fromto "->" dstipmask [ mapport ] mapoptions.
-mapblock ::= "map-block" ifname ipmask "->" ipmask [ ports ] mapoptions.
+map ::= mapit ifname lhs "->" dstipmask [ mapicmp | mapport | mapproxy ]
+ mapoptions .
+mapblock ::= "map-block" ifname lhs "->" ipmask [ ports ] mapoptions .
redir ::= "rdr" ifname ipmask dport "->" ip [ "," ip ] rdrport rdroptions .
-dport ::= "port" number [ "-" number ] .
-ports ::= "ports" number | "auto" .
-rdrport ::= "port" number .
+lhs ::= ipmask | fromto .
+dport ::= "port" portnum [ "-" portnum ] .
+ports ::= "ports" numports | "auto" .
+rdrport ::= "port" portnum .
mapit ::= "map" | "bimap" .
fromto ::= "from" object "to" object .
ipmask ::= ip "/" bits | ip "/" mask | ip "netmask" mask .
dstipmask ::= ipmask | "range" ip "-" ip .
+mapicmp ::= "icmpidmap" "icmp" number ":" number .
mapport ::= "portmap" tcpudp portspec .
mapoptions ::= [ tcpudp ] [ "frag" ] [ age ] [ clamp ] .
-rdroptions ::= [ tcpudp | protocol ] [ rr ] [ "frag" ] [ age ] [ clamp ] .
+rdroptions ::= rdrproto [ rr ] [ "frag" ] [ age ] [ clamp ] [ rdrproxy ] .
-object :: = addr [ port-comp | port-range ] .
-addr :: = "any" | nummask | host-name [ "mask" ipaddr | "mask" hexnumber ] .
+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 .
+rdrproto ::= tcpudp | protocol .
rr ::= "round-robin" .
age ::= "age" decnumber [ "/" decnumber ] .
clamp ::= "mssclamp" decnumber .
-tcpudp ::= "tcp/udp" | "tcp" | "udp" .
+tcpudp ::= "tcp/udp" | protocol .
+mapproxy ::= "proxy" "port" port proxy-name '/' protocol
+rdrproxy ::= "proxy" proxy-name .
protocol ::= protocol-name | decnumber .
-nummask ::= host-name [ "/" number ] .
-portspec ::= "auto" | number ":" number .
+nummask ::= host-name [ "/" decnumber ] .
+portspec ::= "auto" | portnumber ":" portnumber .
+port ::= portnumber | port-name .
+portnumber ::= number { numbers } .
ifname ::= 'A' - 'Z' { 'A' - 'Z' } numbers .
-number ::= numbers [ number ] .
numbers ::= '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' .
.fi
.PP
-In addition to this, # is used to mark the start of a comment and may
-appear at the end of a line with a NAT rule (as described above) or on its
-own lines. Blank lines are ignored.
-.PP
For standard NAT functionality, a rule should start with \fBmap\fP and then
proceeds to specify the interface for which outgoing packets will have their
source address rewritten.
@@ -101,41 +105,12 @@ or as
map de0 from 10.1.0.0/16 to any -> 201.2.3.4/32
.fi
.LP
-For even greater control, one may negate either of the "from" or "to" clauses
-with a preceding exclamation mark ("!"). Please note that one may not use a
-negated "from" within a \fBmap\fP rule or a negated "to" within a \fBrdr\fP
-rule. Such a rule might look like the following:
-.LP
-.nf
-+map de0 from 10.1.0.0/16 ! to 10.1.0.0/16 -> 201.2.3.4/32
-.fi
-.PP
Only IP address and port numbers can be compared against. This is available
with all NAT rules.
-.SH COMMAND QUALIFIERS
-At the end of each rule, a number of qualifiers can be used to change how
-the rule works. They are as follows:
-.TP
-protocol
-A specific protocol may be given either by its name (as found in
-/etc/protocols) or its number. A special case for supporting both
-TCP and UDP is allowed with the name \fBtcp/udp\fP.
-.TP
-.B round-robin
-Once a rule with this term has been successfully used, it is put at the
-bottom of the list of those available so that each one will get used, in
-turn, in a list of matching left hand sides.
-.TP
-.B frag
-This qualifier is currently has no impact on NAT operation.
-.TP
-.B age
-If more refined timeouts are required than those available globally for
-NAT settings, this allows you to set them for \fBnon-TCP\fP use.
.SH TRANSLATION
.PP
To the right of the "->" is the address and port specification which will be
-written into the packet providing it has already successful matched the
+written into the packet providing it has already successfully matched the
prior constraints. The case of redirections (\fBrdr\fP) is the simplest:
the new destination address is that specified in the rule. For \fBmap\fP
rules, the destination address will be one for which the tuple combining
@@ -149,13 +124,76 @@ the packet will not be translated. The \fBmap-block\fP is more limited in
how it searches for a new, free and unique tuple, in that it will used an
algorithm to determine what the new source address should be, along with the
range of available ports - the IP address is never changed and nor does the
-port number ever exceed its alloted range.
+port number ever exceed its allotted range.
+.SH ICMPIDMAP
+.PP
+ICMP messages can be divided into two groups: "errors" and "queries". ICMP
+errors are generated as a response of another IP packet. IP Filter will take
+care that ICMP errors that are the response of a NAT-ed IP packet are
+handled properly.
+.PP
+For 4 types of ICMP queries (echo request, timestamp request, information
+request and address mask request) IP Filter supports an additional mapping
+called "ICMP id mapping". All these 4 types of ICMP queries use a unique
+identifier called the ICMP id. This id is set by the process sending the
+ICMP query and it is usually equal to the process id. The receiver of the
+ICMP query will use the same id in its response, thus enabling the
+sender to recognize that the incoming ICMP reply is intended for him and is
+an answer to a query that he made. The "ICMP id mapping" feature modifies
+these ICMP id in a way identical to \fBportmap\fP for TCP or UDP.
+.PP
+The reason that you might want this, is that using this feature you don't
+need an IP address per host behind the NAT box, that wants to do ICMP queries.
+The two numbers behind the \fBicmpidmap\fP keyword are the first and the
+last icmp id number that can be used. There is one important caveat: if you
+map to an IP address that belongs to the NAT box itself (notably if you have
+only a single public IP address), then you must ensure that the NAT box does
+not use the \fBicmpidmap\fP range that you specified in the \fBmap\fP rule.
+Since the ICMP id is usually the process id, it is wise to restrict the
+largest permittable process id (PID) on your operating system to e.g. 63999 and
+use the range 64000:65535 for ICMP id mapping. Changing the maximal PID is
+system dependent. For most BSD derived systems can be done by changing
+PID_MAX in /usr/include/sys/proc.h and then rebuild the system.
.SH KERNEL PROXIES
.PP
IP Filter comes with a few, simple, proxies built into the code that is loaded
into the kernel to allow secondary channels to be opened without forcing the
-packets through a user program.
-.SH TRNSPARENT PROXIES
+packets through a user program. The current state of the proxies is listed
+below, as one of three states:
+.HP
+Aging - protocol is roughly understood from
+the time at which the proxy was written but it is not well tested or
+maintained;
+.HP
+Developmental - basic functionality exists, works most of the time but
+may be problematic in extended real use;
+.HP
+Experimental - rough support for the protocol at best, may or may not
+work as testing has been at best sporadic, possible large scale changes
+to the code in order to properly support the protocol.
+.HP
+Mature - well tested, protocol is properly
+understood by the proxy;
+.PP
+The currently compiled in proxy list is as follows:
+.HP
+FTP - Mature
+.HP
+IRC - Experimental
+.HP
+rpcbind - Experimental
+.HP
+H.323 - Experimental
+.HP
+Real Audio (PNA) - Aging
+.HP
+IPsec - Developmental
+.HP
+netbios - Experimental
+.HP
+R-command - Mature
+
+.SH TRANSPARENT PROXIES
.PP
True transparent proxying should be performed using the redirect (\fBrdr\fP)
rules directing ports to localhost (127.0.0.1) with the proxy program doing
@@ -226,7 +264,13 @@ map ppp0 172.192.0.0/16 -> 209.1.2.0/24 portmap tcp/udp auto
.fi
.PP
which would result in each IP address being given a small range of ports to
-use (252). The problem here is that the \fBmap\fP directive tells the NAT
+use (252). In all cases, the new port number that is used is deterministic.
+That is, port X will always map to port Y.
+WARNING: It is not advisable to use the \fBauto\fP feature if you are map'ing
+to a /32 (i.e. 0/32) because the NAT code will try to map multiple hosts to
+the same port number, outgoing and ultimately this will only succeed for one
+of them.
+The problem here is that the \fBmap\fP directive tells the NAT
code to use the next address/port pair available for an outgoing connection,
resulting in no easily discernible relation between external addresses/ports
and internal ones. This is overcome by using \fBmap-block\fP as follows:
@@ -241,7 +285,6 @@ own. As opposed to the above use of \fBmap\fP, if for some reason the user
of (say) 172.192.0.2 wanted 260 simultaneous connections going out, they would
be limited to 252 with \fBmap-block\fP but would just \fImove on\fP to the next
IP address with the \fBmap\fP command.
-.SH FILES
/dev/ipnat
.br
/etc/services
diff --git a/contrib/ipfilter/man/ipnat.8 b/contrib/ipfilter/man/ipnat.8
index 3b365ed..49a09be 100644
--- a/contrib/ipfilter/man/ipnat.8
+++ b/contrib/ipfilter/man/ipnat.8
@@ -1,10 +1,18 @@
+.\" $NetBSD$
+.\"
.TH IPNAT 8
.SH NAME
-ipnat \- user interface to the NAT
+ipnat \- user interface to the NAT subsystem
.SH SYNOPSIS
.B ipnat
[
-.B \-lnrsvCF
+.B \-dhlnrsvCF
+]
+[
+.B \-M core
+]
+[
+.B \-N system
]
.B \-f <\fIfilename\fP>
.SH DESCRIPTION
@@ -16,33 +24,48 @@ Each rule processed by \fBipnat\fP
is added to the kernels internal lists if there are no parsing problems.
Rules are added to the end of the internal lists, matching the order in
which they appear when given to \fBipnat\fP.
+.PP
+Note that if
+\fBipf(8)\fP
+is not enabled when NAT is configured, it will be enabled
+automatically, as the same kernel facilities are used for
+NAT functionality. In addition, packet forwarding must be
+enabled.
.SH OPTIONS
.TP
.B \-C
delete all entries in the current NAT rule listing (NAT rules)
+ .TP
+.B \-d
+Enable printing of some extra debugging information.
.TP
.B \-F
delete all active entries in the current NAT translation table (currently
active NAT mappings)
.TP
+.B \-h
+Print number of hits for each MAP/Redirect filter.
+.TP
.B \-l
Show the list of current NAT table entry mappings.
.TP
.B \-n
-This flag (no-change) prevents \fBipnat\fP from actually making any ioctl
+This flag (no-change) prevents \fBipf\fP from actually making any ioctl
calls or doing anything which would alter the currently running kernel.
.TP
-.B \-s
-Retrieve and display NAT statistics
-.TP
.B \-r
Remove matching NAT rules rather than add them to the internal lists
.TP
+.B \-s
+Retrieve and display NAT statistics
+.TP
.B \-v
Turn verbose mode on. Displays information relating to rule processing
and active rules/table entries.
.DT
.SH FILES
/dev/ipnat
+.br
+/usr/share/examples/ipf Directory with examples.
.SH SEE ALSO
ipnat(5), ipf(8), ipfstat(8)
diff --git a/contrib/ipfilter/man/ippool.5 b/contrib/ipfilter/man/ippool.5
new file mode 100644
index 0000000..c9eaaca
--- /dev/null
+++ b/contrib/ipfilter/man/ippool.5
@@ -0,0 +1,155 @@
+.\" $NetBSD$
+.\"
+.TH IPPOOL 5
+.SH NAME
+ippool, ippool.conf \- IP Pool file format
+.SH DESCRIPTION
+The format for files accepted by ippool is described by the following grammar:
+.LP
+.nf
+line ::= table | groupmap .
+table ::= "table" role tabletype .
+groupmap ::= "group-map" inout role number ipfgroup
+tabletype ::= ipftree | ipfhash .
+
+role ::= "role" "=" "ipf" .
+inout ::= "in" | "out" .
+
+ipftree ::= "type" "=" "tree" number "{" addrlist "}" .
+ipfhash ::= "type" "=" "hash" number hashopts "{" hashlist "}" .
+
+ipfgroup ::= setgroup hashopts "{" grouplist "}" |
+ hashopts "{" setgrouplist "}" .
+setgroup ::= "group" "=" groupname .
+
+hashopts ::= size [ seed ] | seed .
+
+size ::= "size" number .
+seed ::= "seed" number .
+
+addrlist ::= [ "!" ] addrmask ";" [ addrlist ] .
+grouplist ::= groupentry ";" [ grouplist ] | addrmask ";" [ grouplist ] .
+
+setgrouplist ::= groupentry ";" [ setgrouplist ] .
+
+groupentry ::= addrmask "," setgroup .
+
+hashlist ::= hashentry ";" [ hashlist ] .
+hashentry ::= addrmask .
+
+addrmask ::= ipaddr | ipaddr "/" mask .
+
+mask ::= number | ipaddr .
+
+groupname ::= number | name .
+
+number ::= digit { digit } .
+
+ipaddr = host-num "." host-num "." host-num "." host-num .
+host-num = digit [ digit [ digit ] ] .
+
+digit ::= "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" .
+name ::= letter { letter | digit } .
+.fi
+.PP
+The IP pool configuration file is used for defining a single object that
+contains a reference to multiple IP address/netmask pairs. A pool may consist
+of a mixture of netmask sizes, from 0 to 32.
+.PP
+At this point in time, only IPv4 addressing is supported.
+.TP
+.SH OVERVIEW
+.PP
+The IP pool configuration file provides for defining two different mechanisms
+for improving speed in matching IP addresses with rules.
+The first,
+.B table
+, defines a lookup
+.I table
+to provide a single reference in a
+filter rule to multiple targets and the second,
+.B group-map
+, provides a mechanism to target multiple groups from a single filter line.
+.PP
+The
+.B group-map
+command can only be used with filter rules that use the
+.B call
+command to invoke either
+.B fr_srcgrpmap
+or
+.B fr_dstgrpmap
+, to use the source or destination address,
+respectively, for determining which filter group to jump to next for
+continuation of filter packet processing.
+.SH POOL TYPES
+.PP
+Two storage formats are provided: hash tables and tree structure. The hash
+table is intended for use with objects all containing the same netmask or a
+few different sized netmasks of non-overlapping address space and the tree
+is designed for being able to support exceptions to a covering mask, in
+addition to normal searching as you would do with a table. It is not possible
+to use the tree data storage type with
+.B group-map
+configuration entries.
+.SH POOL ROLES
+.PP
+When a pool is defined in the configruation file, it must have an associated
+role. At present the only supported role is
+.B ipf.
+Future development will see futher expansion of their use by other sections
+of IPFilter code.
+.SH EXAMPLES
+The following examples show how the pool configuration file is used with
+the ipf configuration file to enhance the ability for the ipf configuration
+file to be succinct in meaning.
+.TP
+1
+The first example shows how a filter rule makes reference to a specific
+pool for matching of the source address.
+.nf
+pass in from pool/100 to any
+.fi
+.PP
+The pool configuration, which matches IP addresses 1.1.1.1 and any
+in 2.2.0.0/16, except for those in 2.2.2.0/24.
+.PP
+.nf
+table role = ipf type = tree number = 100
+ { 1.1.1.1/32; 2.2.0.0/16; !2.2.2.0/24 };
+.fi
+.TP
+2
+The following ipf.conf extract uses the
+fr_srcgrpmap/fr_dstgrpmap lookups to use the
+.B group-map
+facility to lookup the next group to use for filter processing, providing
+the
+.B call
+filter rule is matched.
+.nf
+call now fr_srcgrpmap/1010 in all
+call now fr_dstgrpmap/2010 out all
+pass in all group 1020
+block in all group 1030
+pass out all group 2020
+block out all group 2040
+.fi
+.PP
+A ippool configuration to work with the above ipf.conf file might
+look like this:
+.PP
+.nf
+group-map in role = ipf number = 1010
+ { 1.1.1.1/32, group = 1020; 3.3.0.0/16, group = 1030; };
+group-map out role = ipf number = 2010 group = 2020
+ { 2.2.2.2/32; 4.4.0.0/16; 5.0.0.0/8, group = 2040; };
+.fi
+.SH FILES
+/dev/iplookup
+.br
+/etc/ippool.conf
+.br
+/etc/hosts
+.SH SEE ALSO
+ippool(8), hosts(5), ipf(5), ipf(8), ipnat(8)
diff --git a/contrib/ipfilter/man/ippool.8 b/contrib/ipfilter/man/ippool.8
new file mode 100644
index 0000000..6ed1e88
--- /dev/null
+++ b/contrib/ipfilter/man/ippool.8
@@ -0,0 +1,126 @@
+.\" $NetBSD$
+.\"
+.TH IPPOOL 8
+.SH NAME
+ippool \- user interface to the IPFilter pools
+.SH SYNOPSIS
+.br
+.B ippool
+-a [-dnv] [-m <name>] [-o <role>] -i <ipaddr>[/<netmask>]
+.br
+.B ippool
+-A [-dnv] [-m <name>] [-o <role>] [-S <seed>] [-t <type>]
+.br
+.B ippool
+-f <file> [-dnuv]
+.br
+.B ippool
+-F [-dv] [-o <role>] [-t <type>]
+.br
+.B ippool
+-l [-dv] [-m <name>] [-t <type>]
+.br
+.B ippool
+-r [-dnv] [-m <name>] [-o <role>] -i <ipaddr>[/<netmask>]
+.br
+.B ippool
+-R [-dnv] [-m <name>] [-o <role>] [-t <type>]
+.br
+.B ippool
+-s [-dtv] [-M <core>] [-N <namelist>]
+.SH DESCRIPTION
+.PP
+.B Ippool
+is used to manage information stored in the IP pools subsystem of IPFilter.
+Configuration file information may be parsed and loaded into the kernel,
+currently configured pools removed or changed as well as inspected.
+.PP
+The command line options used are broken into two sections: the global
+options and the instance specific options.
+.SH GLOBAL OPTIONS
+.TP
+.B \-d
+Toggle debugging of processing the configuration file.
+.TP
+.B \-n
+This flag (no-change) prevents
+.B ippool
+from actually making any ioctl
+calls or doing anything which would alter the currently running kernel.
+.TP
+.B \-v
+Turn verbose mode on.
+.SH COMMAND OPTIONS
+.TP
+.B -a
+Add a new data node to an existing pool in the kernel.
+.TP
+.B -A
+Add a new (empty) pool to the kernel.
+.TP
+.B -f <file>
+Read in IP pool configuration information from the file and load it into
+the kernel.
+.TP
+.B -F
+Flush loaded pools from the kernel.
+.TP
+.B -l
+Display a list of pools currently loaded into the kernel.
+.TP
+.B -r
+Remove an existing data node from a pool in the kernel.
+.TP
+.B -R
+Remove an existing pool from within the kernel.
+.TP
+.B -s
+Display IP pool statistical information.
+.SH OPTIONS
+.TP
+.B -i <ipaddr>[/<netmask>]
+Sets the IP address for the operation being undertaken with an
+all-one's mask or, optionally, a specific netmask given in either
+the dotted-quad notation or a single integer.
+.TP
+.B -m <name>
+Sets the pool name for the current operation.
+.TP
+.B -M <core>
+Specify an alternative path to /dev/kmem to retrieve statistical information
+from.
+.TP
+.B -N <namelist>
+Specify an alternative path to lookup symbol name information from when
+retrieving statistical information.
+.TP
+.B -o <role>
+Sets the role with which this pool is to be used. Currently only
+.B ipf,
+.B auth
+and
+.B count
+are accepted as arguments to this option.
+.TP
+.B -S <seed>
+Sets the hashing seed to the number specified. Only for use with
+.B hash
+type pools.
+.TP
+.B -t <type>
+Sets the type of pool being defined. Myst be one of
+.B tree,
+.B hash,
+.B group-map.
+.TP
+.B -u
+When parsing a configuration file, rather than load new pool data into the
+kernel, unload it.
+.DT
+.SH FILES
+.br
+/dev/iplookup
+.br
+/etc/ippool.conf
+.SH SEE ALSO
+ippool(5), ipf(8), ipfstat(8)
diff --git a/contrib/ipfilter/man/ipscan.5 b/contrib/ipfilter/man/ipscan.5
new file mode 100644
index 0000000..4a00174
--- /dev/null
+++ b/contrib/ipfilter/man/ipscan.5
@@ -0,0 +1,52 @@
+.\" $NetBSD$
+.\"
+.TH IPSCAN 5
+.SH NAME
+ipscan, ipscan.conf \- ipscan file format
+.SH DESCRIPTION
+.PP
+WARNING: This feature is to be considered experimental and may change
+significantly until a final implementation is drawn up.
+.PP
+The format for files accept by ipscan currently follow this rough grammar:
+.LP
+.nf
+line ::= name ":" matchup [ "," matchup ] "=" action .
+matchup ::= "(" ")" | "(" literal ")" | "(" literal "," match ")" .
+action ::= result | result "else" result .
+result ::= "close" | "track" | redirect .
+redirect ::= "redirect" ip-address [ "(" "," port-number ")" ] .
+match ::= { match-char }
+match-char ::= "*" | "?" | "."
+.fi
+.PP
+In this example an ip-address is a dotted-quad IPv4 address and a port-number
+is a number betwee 1 and 65535, inclusive. The match string is must be of
+same length as the literal string that it is matching (literal). The length
+of either string is limited to 16 bytes.
+.PP
+Currently, the redirect option is not yet been implemented.
+.LP
+.nf
+#
+# * = match any character, . = exact match, ? = case insensitive
+#
+# Scan for anything that looks like HTTP and redirect it to the local
+# proxy. One catch - this feature (redirect) is not yet implemented.
+#
+http : ("GET ", "???." ) = redirect(127.0.0.1)
+#
+# Track ssh connections (i.e do nothing)
+#
+ssh : (), ("SSH-") = track
+#
+# Things which look like smtp to be tracked else closed.
+# Client can start with EHLO (ESMTP) or HELO (SMTP).
+#
+smtp : ("HELO ", "**??."), ("220 ", "....") = track else close
+#
+.fi
+.SH FILES
+/etc/ipscan.conf
+.SH SEE ALSO
+ipscan(8)
diff --git a/contrib/ipfilter/man/ipscan.8 b/contrib/ipfilter/man/ipscan.8
new file mode 100644
index 0000000..d3ce952
--- /dev/null
+++ b/contrib/ipfilter/man/ipscan.8
@@ -0,0 +1,44 @@
+.\" $NetBSD$
+.\"
+.TH IPSCAN 8
+.SH NAME
+ipscan \- user interface to the IPFilter content scanning
+.SH SYNOPSIS
+.B ipscan
+[
+.B \-dlnrsv
+] [
+]
+.B \-f <\fIfilename\fP>
+.SH DESCRIPTION
+.PP
+\fBipscan\fP opens the filename given (treating "\-" as stdin) and parses the
+file to build up a content scanning configuration to load into the kernel.
+Currently only the first 16 bytes of a connection can be compared.
+.SH OPTIONS
+.TP
+.B \-d
+Toggle debugging of processing the configuration file.
+.TP
+.B \-l
+Show the list of currently configured content scanning entries.
+.TP
+.B \-n
+This flag (no-change) prevents \fBipscan\fP from actually making any ioctl
+calls or doing anything which would alter the currently running kernel.
+.TP
+.B \-r
+Remove commands from kernel configuration as they are read from the
+configuration file rather than adding new ones.
+.TP
+.B \-s
+Retrieve and display content scanning statistics
+.TP
+.B \-v
+Turn verbose mode on.
+.DT
+.SH FILES
+/dev/ipscan
+/etc/ipscan.conf
+.SH SEE ALSO
+ipscan(5), ipf(8)
diff --git a/contrib/ipfilter/man/mkfilters.1 b/contrib/ipfilter/man/mkfilters.1
index b5fd9dc..3bac7d1 100644
--- a/contrib/ipfilter/man/mkfilters.1
+++ b/contrib/ipfilter/man/mkfilters.1
@@ -1,3 +1,5 @@
+.\" $NetBSD$
+.\"
.TH MKFILTERS 1
.SH NAME
mkfilters \- generate a minimal firewall ruleset for ipfilter
diff --git a/contrib/ipfilter/md5.c b/contrib/ipfilter/md5.c
new file mode 100644
index 0000000..78a0eb7
--- /dev/null
+++ b/contrib/ipfilter/md5.c
@@ -0,0 +1,314 @@
+/* $NetBSD$ */
+
+
+
+/*
+ ***********************************************************************
+ ** md5.c -- the source code for MD5 routines **
+ ** RSA Data Security, Inc. MD5 Message-Digest Algorithm **
+ ** Created: 2/17/90 RLR **
+ ** Revised: 1/91 SRD,AJ,BSK,JT Reference C ver., 7/10 constant corr. **
+ ***********************************************************************
+ */
+
+/*
+ ***********************************************************************
+ ** Copyright (C) 1990, RSA Data Security, Inc. All rights reserved. **
+ ** **
+ ** License to copy and use this software is granted provided that **
+ ** it is identified as the "RSA Data Security, Inc. MD5 Message- **
+ ** Digest Algorithm" in all material mentioning or referencing this **
+ ** software or this function. **
+ ** **
+ ** License is also granted to make and use derivative works **
+ ** provided that such works are identified as "derived from the RSA **
+ ** Data Security, Inc. MD5 Message-Digest Algorithm" in all **
+ ** material mentioning or referencing the derived work. **
+ ** **
+ ** RSA Data Security, Inc. makes no representations concerning **
+ ** either the merchantability of this software or the suitability **
+ ** of this software for any particular purpose. It is provided "as **
+ ** is" without express or implied warranty of any kind. **
+ ** **
+ ** These notices must be retained in any copies of any part of this **
+ ** documentation and/or software. **
+ ***********************************************************************
+ */
+
+#if defined(_KERNEL) && !defined(__sgi)
+# include <sys/systm.h>
+#else
+# include <string.h>
+#endif
+
+#include "md5.h"
+
+/*
+ ***********************************************************************
+ ** Message-digest routines: **
+ ** To form the message digest for a message M **
+ ** (1) Initialize a context buffer mdContext using MD5Init **
+ ** (2) Call MD5Update on mdContext and M **
+ ** (3) Call MD5Final on mdContext **
+ ** The message digest is now in mdContext->digest[0...15] **
+ ***********************************************************************
+ */
+
+/* forward declaration */
+static void Transform __P((UINT4 *, UINT4 *));
+
+static unsigned char PADDING[64] = {
+ 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+/* F, G, H and I are basic MD5 functions */
+#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
+#define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
+#define H(x, y, z) ((x) ^ (y) ^ (z))
+#define I(x, y, z) ((y) ^ ((x) | (~z)))
+
+/* ROTATE_LEFT rotates x left n bits */
+#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
+
+/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4 */
+/* Rotation is separate from addition to prevent recomputation */
+#define FF(a, b, c, d, x, s, ac) \
+ {(a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \
+ (a) = ROTATE_LEFT ((a), (s)); \
+ (a) += (b); \
+ }
+#define GG(a, b, c, d, x, s, ac) \
+ {(a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \
+ (a) = ROTATE_LEFT ((a), (s)); \
+ (a) += (b); \
+ }
+#define HH(a, b, c, d, x, s, ac) \
+ {(a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \
+ (a) = ROTATE_LEFT ((a), (s)); \
+ (a) += (b); \
+ }
+#define II(a, b, c, d, x, s, ac) \
+ {(a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \
+ (a) = ROTATE_LEFT ((a), (s)); \
+ (a) += (b); \
+ }
+
+#ifdef __STDC__
+#define UL(x) x##U
+#else
+#define UL(x) x
+#endif
+
+/* The routine MD5Init initializes the message-digest context
+ mdContext. All fields are set to zero.
+ */
+void MD5Init (mdContext)
+MD5_CTX *mdContext;
+{
+ mdContext->i[0] = mdContext->i[1] = (UINT4)0;
+
+ /* Load magic initialization constants.
+ */
+ mdContext->buf[0] = (UINT4)0x67452301;
+ mdContext->buf[1] = (UINT4)0xefcdab89;
+ mdContext->buf[2] = (UINT4)0x98badcfe;
+ mdContext->buf[3] = (UINT4)0x10325476;
+}
+
+/* The routine MD5Update updates the message-digest context to
+ account for the presence of each of the characters inBuf[0..inLen-1]
+ in the message whose digest is being computed.
+ */
+void MD5Update (mdContext, inBuf, inLen)
+MD5_CTX *mdContext;
+unsigned char *inBuf;
+unsigned int inLen;
+{
+ UINT4 in[16];
+ int mdi;
+ unsigned int i, ii;
+
+ /* compute number of bytes mod 64 */
+ mdi = (int)((mdContext->i[0] >> 3) & 0x3F);
+
+ /* update number of bits */
+ if ((mdContext->i[0] + ((UINT4)inLen << 3)) < mdContext->i[0])
+ mdContext->i[1]++;
+ mdContext->i[0] += ((UINT4)inLen << 3);
+ mdContext->i[1] += ((UINT4)inLen >> 29);
+
+ while (inLen--) {
+ /* add new character to buffer, increment mdi */
+ mdContext->in[mdi++] = *inBuf++;
+
+ /* transform if necessary */
+ if (mdi == 0x40) {
+ for (i = 0, ii = 0; i < 16; i++, ii += 4)
+ in[i] = (((UINT4)mdContext->in[ii+3]) << 24) |
+ (((UINT4)mdContext->in[ii+2]) << 16) |
+ (((UINT4)mdContext->in[ii+1]) << 8) |
+ ((UINT4)mdContext->in[ii]);
+ Transform (mdContext->buf, in);
+ mdi = 0;
+ }
+ }
+}
+
+/* The routine MD5Final terminates the message-digest computation and
+ ends with the desired message digest in mdContext->digest[0...15].
+ */
+void MD5Final (hash, mdContext)
+unsigned char hash[];
+MD5_CTX *mdContext;
+{
+ UINT4 in[16];
+ int mdi;
+ unsigned int i, ii;
+ unsigned int padLen;
+
+ /* save number of bits */
+ in[14] = mdContext->i[0];
+ in[15] = mdContext->i[1];
+
+ /* compute number of bytes mod 64 */
+ mdi = (int)((mdContext->i[0] >> 3) & 0x3F);
+
+ /* pad out to 56 mod 64 */
+ padLen = (mdi < 56) ? (56 - mdi) : (120 - mdi);
+ MD5Update (mdContext, PADDING, padLen);
+
+ /* append length in bits and transform */
+ for (i = 0, ii = 0; i < 14; i++, ii += 4)
+ in[i] = (((UINT4)mdContext->in[ii+3]) << 24) |
+ (((UINT4)mdContext->in[ii+2]) << 16) |
+ (((UINT4)mdContext->in[ii+1]) << 8) |
+ ((UINT4)mdContext->in[ii]);
+ Transform (mdContext->buf, in);
+
+ /* store buffer in digest */
+ for (i = 0, ii = 0; i < 4; i++, ii += 4) {
+ mdContext->digest[ii] = (unsigned char)(mdContext->buf[i] & 0xFF);
+ mdContext->digest[ii+1] =
+ (unsigned char)((mdContext->buf[i] >> 8) & 0xFF);
+ mdContext->digest[ii+2] =
+ (unsigned char)((mdContext->buf[i] >> 16) & 0xFF);
+ mdContext->digest[ii+3] =
+ (unsigned char)((mdContext->buf[i] >> 24) & 0xFF);
+ }
+ bcopy((char *)mdContext->digest, (char *)hash, 16);
+}
+
+/* Basic MD5 step. Transforms buf based on in.
+ */
+static void Transform (buf, in)
+UINT4 *buf;
+UINT4 *in;
+{
+ UINT4 a = buf[0], b = buf[1], c = buf[2], d = buf[3];
+
+ /* Round 1 */
+#define S11 7
+#define S12 12
+#define S13 17
+#define S14 22
+ FF ( a, b, c, d, in[ 0], S11, UL(3614090360)); /* 1 */
+ FF ( d, a, b, c, in[ 1], S12, UL(3905402710)); /* 2 */
+ FF ( c, d, a, b, in[ 2], S13, UL( 606105819)); /* 3 */
+ FF ( b, c, d, a, in[ 3], S14, UL(3250441966)); /* 4 */
+ FF ( a, b, c, d, in[ 4], S11, UL(4118548399)); /* 5 */
+ FF ( d, a, b, c, in[ 5], S12, UL(1200080426)); /* 6 */
+ FF ( c, d, a, b, in[ 6], S13, UL(2821735955)); /* 7 */
+ FF ( b, c, d, a, in[ 7], S14, UL(4249261313)); /* 8 */
+ FF ( a, b, c, d, in[ 8], S11, UL(1770035416)); /* 9 */
+ FF ( d, a, b, c, in[ 9], S12, UL(2336552879)); /* 10 */
+ FF ( c, d, a, b, in[10], S13, UL(4294925233)); /* 11 */
+ FF ( b, c, d, a, in[11], S14, UL(2304563134)); /* 12 */
+ FF ( a, b, c, d, in[12], S11, UL(1804603682)); /* 13 */
+ FF ( d, a, b, c, in[13], S12, UL(4254626195)); /* 14 */
+ FF ( c, d, a, b, in[14], S13, UL(2792965006)); /* 15 */
+ FF ( b, c, d, a, in[15], S14, UL(1236535329)); /* 16 */
+
+ /* Round 2 */
+#define S21 5
+#define S22 9
+#define S23 14
+#define S24 20
+ GG ( a, b, c, d, in[ 1], S21, UL(4129170786)); /* 17 */
+ GG ( d, a, b, c, in[ 6], S22, UL(3225465664)); /* 18 */
+ GG ( c, d, a, b, in[11], S23, UL( 643717713)); /* 19 */
+ GG ( b, c, d, a, in[ 0], S24, UL(3921069994)); /* 20 */
+ GG ( a, b, c, d, in[ 5], S21, UL(3593408605)); /* 21 */
+ GG ( d, a, b, c, in[10], S22, UL( 38016083)); /* 22 */
+ GG ( c, d, a, b, in[15], S23, UL(3634488961)); /* 23 */
+ GG ( b, c, d, a, in[ 4], S24, UL(3889429448)); /* 24 */
+ GG ( a, b, c, d, in[ 9], S21, UL( 568446438)); /* 25 */
+ GG ( d, a, b, c, in[14], S22, UL(3275163606)); /* 26 */
+ GG ( c, d, a, b, in[ 3], S23, UL(4107603335)); /* 27 */
+ GG ( b, c, d, a, in[ 8], S24, UL(1163531501)); /* 28 */
+ GG ( a, b, c, d, in[13], S21, UL(2850285829)); /* 29 */
+ GG ( d, a, b, c, in[ 2], S22, UL(4243563512)); /* 30 */
+ GG ( c, d, a, b, in[ 7], S23, UL(1735328473)); /* 31 */
+ GG ( b, c, d, a, in[12], S24, UL(2368359562)); /* 32 */
+
+ /* Round 3 */
+#define S31 4
+#define S32 11
+#define S33 16
+#define S34 23
+ HH ( a, b, c, d, in[ 5], S31, UL(4294588738)); /* 33 */
+ HH ( d, a, b, c, in[ 8], S32, UL(2272392833)); /* 34 */
+ HH ( c, d, a, b, in[11], S33, UL(1839030562)); /* 35 */
+ HH ( b, c, d, a, in[14], S34, UL(4259657740)); /* 36 */
+ HH ( a, b, c, d, in[ 1], S31, UL(2763975236)); /* 37 */
+ HH ( d, a, b, c, in[ 4], S32, UL(1272893353)); /* 38 */
+ HH ( c, d, a, b, in[ 7], S33, UL(4139469664)); /* 39 */
+ HH ( b, c, d, a, in[10], S34, UL(3200236656)); /* 40 */
+ HH ( a, b, c, d, in[13], S31, UL( 681279174)); /* 41 */
+ HH ( d, a, b, c, in[ 0], S32, UL(3936430074)); /* 42 */
+ HH ( c, d, a, b, in[ 3], S33, UL(3572445317)); /* 43 */
+ HH ( b, c, d, a, in[ 6], S34, UL( 76029189)); /* 44 */
+ HH ( a, b, c, d, in[ 9], S31, UL(3654602809)); /* 45 */
+ HH ( d, a, b, c, in[12], S32, UL(3873151461)); /* 46 */
+ HH ( c, d, a, b, in[15], S33, UL( 530742520)); /* 47 */
+ HH ( b, c, d, a, in[ 2], S34, UL(3299628645)); /* 48 */
+
+ /* Round 4 */
+#define S41 6
+#define S42 10
+#define S43 15
+#define S44 21
+ II ( a, b, c, d, in[ 0], S41, UL(4096336452)); /* 49 */
+ II ( d, a, b, c, in[ 7], S42, UL(1126891415)); /* 50 */
+ II ( c, d, a, b, in[14], S43, UL(2878612391)); /* 51 */
+ II ( b, c, d, a, in[ 5], S44, UL(4237533241)); /* 52 */
+ II ( a, b, c, d, in[12], S41, UL(1700485571)); /* 53 */
+ II ( d, a, b, c, in[ 3], S42, UL(2399980690)); /* 54 */
+ II ( c, d, a, b, in[10], S43, UL(4293915773)); /* 55 */
+ II ( b, c, d, a, in[ 1], S44, UL(2240044497)); /* 56 */
+ II ( a, b, c, d, in[ 8], S41, UL(1873313359)); /* 57 */
+ II ( d, a, b, c, in[15], S42, UL(4264355552)); /* 58 */
+ II ( c, d, a, b, in[ 6], S43, UL(2734768916)); /* 59 */
+ II ( b, c, d, a, in[13], S44, UL(1309151649)); /* 60 */
+ II ( a, b, c, d, in[ 4], S41, UL(4149444226)); /* 61 */
+ II ( d, a, b, c, in[11], S42, UL(3174756917)); /* 62 */
+ II ( c, d, a, b, in[ 2], S43, UL( 718787259)); /* 63 */
+ II ( b, c, d, a, in[ 9], S44, UL(3951481745)); /* 64 */
+
+ buf[0] += a;
+ buf[1] += b;
+ buf[2] += c;
+ buf[3] += d;
+}
+
+/*
+ ***********************************************************************
+ ** End of md5.c **
+ ******************************** (cut) ********************************
+ */
diff --git a/contrib/ipfilter/md5.h b/contrib/ipfilter/md5.h
new file mode 100644
index 0000000..40e8dc6
--- /dev/null
+++ b/contrib/ipfilter/md5.h
@@ -0,0 +1,72 @@
+/* $NetBSD$ */
+
+/*
+ ***********************************************************************
+ ** md5.h -- header file for implementation of MD5 **
+ ** RSA Data Security, Inc. MD5 Message-Digest Algorithm **
+ ** Created: 2/17/90 RLR **
+ ** Revised: 12/27/90 SRD,AJ,BSK,JT Reference C version **
+ ** Revised (for MD5): RLR 4/27/91 **
+ ** -- G modified to have y&~z instead of y&z **
+ ** -- FF, GG, HH modified to add in last register done **
+ ** -- Access pattern: round 2 works mod 5, round 3 works mod 3 **
+ ** -- distinct additive constant for each step **
+ ** -- round 4 added, working mod 7 **
+ ***********************************************************************
+ */
+
+/*
+ ***********************************************************************
+ ** Copyright (C) 1990, RSA Data Security, Inc. All rights reserved. **
+ ** **
+ ** License to copy and use this software is granted provided that **
+ ** it is identified as the "RSA Data Security, Inc. MD5 Message- **
+ ** Digest Algorithm" in all material mentioning or referencing this **
+ ** software or this function. **
+ ** **
+ ** License is also granted to make and use derivative works **
+ ** provided that such works are identified as "derived from the RSA **
+ ** Data Security, Inc. MD5 Message-Digest Algorithm" in all **
+ ** material mentioning or referencing the derived work. **
+ ** **
+ ** RSA Data Security, Inc. makes no representations concerning **
+ ** either the merchantability of this software or the suitability **
+ ** of this software for any particular purpose. It is provided "as **
+ ** is" without express or implied warranty of any kind. **
+ ** **
+ ** These notices must be retained in any copies of any part of this **
+ ** documentation and/or software. **
+ ***********************************************************************
+ */
+
+#ifndef __MD5_INCLUDE__
+
+#ifndef __P
+# ifdef __STDC__
+# define __P(x) x
+# else
+# define __P(x) ()
+# endif
+#endif
+#ifndef __STDC__
+# undef const
+# define const
+#endif
+
+/* typedef a 32-bit type */
+typedef unsigned int UINT4;
+
+/* Data structure for MD5 (Message-Digest) computation */
+typedef struct {
+ UINT4 i[2]; /* number of _bits_ handled mod 2^64 */
+ UINT4 buf[4]; /* scratch buffer */
+ unsigned char in[64]; /* input buffer */
+ unsigned char digest[16]; /* actual digest after MD5Final call */
+} MD5_CTX;
+
+extern void MD5Init __P((MD5_CTX *));
+extern void MD5Update __P((MD5_CTX *, unsigned char *, unsigned int));
+extern void MD5Final __P((unsigned char *, MD5_CTX *));
+
+#define __MD5_INCLUDE__
+#endif /* __MD5_INCLUDE__ */
diff --git a/contrib/ipfilter/mlf_ipl.c b/contrib/ipfilter/mlf_ipl.c
index a165c79..c0cdce8 100644
--- a/contrib/ipfilter/mlf_ipl.c
+++ b/contrib/ipfilter/mlf_ipl.c
@@ -1,3 +1,5 @@
+/* $NetBSD$ */
+
/*
* Copyright (C) 1993-2001 by Darren Reed.
*
@@ -11,16 +13,22 @@
#include <sys/param.h>
-#if defined(__FreeBSD__)
-# ifndef __FreeBSD_version
-# ifdef IPFILTER_LKM
+#ifdef IPFILTER_LKM
+# ifndef __FreeBSD_cc_version
+# include <osreldate.h>
+# else
+# if __FreeBSD_cc_version < 430000
# include <osreldate.h>
-# else
-# include <sys/osreldate.h>
# endif
# endif
-# ifdef IPFILTER_LKM
-# define ACTUALLY_LKM_NOT_KERNEL
+# define ACTUALLY_LKM_NOT_KERNEL
+#else
+# ifndef __FreeBSD_cc_version
+# include <sys/osreldate.h>
+# else
+# if __FreeBSD_cc_version < 430000
+# include <sys/osreldate.h>
+# endif
# endif
#endif
#include <sys/systm.h>
@@ -41,7 +49,6 @@
#endif
#include <sys/stat.h>
#include <sys/proc.h>
-#include <sys/uio.h>
#include <sys/kernel.h>
#include <sys/vnode.h>
#include <sys/namei.h>
@@ -60,7 +67,6 @@
#include <netinet/in.h>
#include <netinet/ip.h>
#include <net/route.h>
-#include <net/if.h>
#include <netinet/ip_var.h>
#include <netinet/tcp.h>
#include <netinet/tcpip.h>
@@ -73,68 +79,65 @@
#include "netinet/ip_nat.h"
#include "netinet/ip_auth.h"
#include "netinet/ip_frag.h"
-#include "netinet/ip_proxy.h"
#if !defined(VOP_LEASE) && defined(LEASE_CHECK)
#define VOP_LEASE LEASE_CHECK
#endif
-#ifndef MIN
-#define MIN(a,b) (((a)<(b))?(a):(b))
-#endif
-
int xxxinit __P((struct lkm_table *, int, int));
-#ifdef SYSCTL_INT
+#ifdef SYSCTL_OID
+int sysctl_ipf_int SYSCTL_HANDLER_ARGS;
+# define SYSCTL_IPF(parent, nbr, name, access, ptr, val, descr) \
+ SYSCTL_OID(parent, nbr, name, CTLTYPE_INT|access, \
+ ptr, val, sysctl_ipf_int, "I", descr);
+# define CTLFLAG_OFF 0x00800000 /* IPFilter must be disabled */
+# define CTLFLAG_RWO (CTLFLAG_RW|CTLFLAG_OFF)
SYSCTL_NODE(_net_inet, OID_AUTO, ipf, CTLFLAG_RW, 0, "IPF");
-SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_flags, CTLFLAG_RW, &fr_flags, 0, "");
-SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_pass, CTLFLAG_RW, &fr_pass, 0, "");
-SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_active, CTLFLAG_RD, &fr_active, 0, "");
-SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_chksrc, CTLFLAG_RW, &fr_chksrc, 0, "");
-SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_minttl, CTLFLAG_RW, &fr_minttl, 0, "");
-SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_minttllog, CTLFLAG_RW,
- &fr_minttllog, 0, "");
-SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_tcpidletimeout, CTLFLAG_RW,
+SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_flags, CTLFLAG_RW, &fr_flags, 0, "");
+SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_pass, CTLFLAG_RW, &fr_pass, 0, "");
+SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_active, CTLFLAG_RD, &fr_active, 0, "");
+SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_chksrc, CTLFLAG_RW, &fr_chksrc, 0, "");
+SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_minttl, CTLFLAG_RW, &fr_minttl, 0, "");
+SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_tcpidletimeout, CTLFLAG_RWO,
&fr_tcpidletimeout, 0, "");
-SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_tcphalfclosed, CTLFLAG_RW,
+SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_tcphalfclosed, CTLFLAG_RWO,
&fr_tcphalfclosed, 0, "");
-SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_tcpclosewait, CTLFLAG_RW,
+SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_tcpclosewait, CTLFLAG_RWO,
&fr_tcpclosewait, 0, "");
-SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_tcplastack, CTLFLAG_RW,
+SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_tcplastack, CTLFLAG_RWO,
&fr_tcplastack, 0, "");
-SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_tcptimeout, CTLFLAG_RW,
+SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_tcptimeout, CTLFLAG_RWO,
&fr_tcptimeout, 0, "");
-SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_tcpclosed, CTLFLAG_RW,
+SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_tcpclosed, CTLFLAG_RWO,
&fr_tcpclosed, 0, "");
-SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_udptimeout, CTLFLAG_RW,
+SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_udptimeout, CTLFLAG_RWO,
&fr_udptimeout, 0, "");
-SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_udpacktimeout, CTLFLAG_RW,
- &fr_udpacktimeout, 0, "");
-SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_icmptimeout, CTLFLAG_RW,
+SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_icmptimeout, CTLFLAG_RWO,
&fr_icmptimeout, 0, "");
-SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_icmpacktimeout, CTLFLAG_RW,
- &fr_icmpacktimeout, 0, "");
-SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_defnatage, CTLFLAG_RW,
+SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_defnatage, CTLFLAG_RWO,
&fr_defnatage, 0, "");
-SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_ipfrttl, CTLFLAG_RW,
+SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_ipfrttl, CTLFLAG_RW,
&fr_ipfrttl, 0, "");
-SYSCTL_INT(_net_inet_ipf, OID_AUTO, ipl_unreach, CTLFLAG_RW,
- &ipl_unreach, 0, "");
-SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_running, CTLFLAG_RD,
+SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_running, CTLFLAG_RD,
&fr_running, 0, "");
-SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_authsize, CTLFLAG_RD,
+SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_statesize, CTLFLAG_RWO,
+ &fr_statesize, 0, "");
+SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_statemax, CTLFLAG_RWO,
+ &fr_statemax, 0, "");
+SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_authsize, CTLFLAG_RWO,
&fr_authsize, 0, "");
-SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_authused, CTLFLAG_RD,
+SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_authused, CTLFLAG_RD,
&fr_authused, 0, "");
-SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_defaultauthage, CTLFLAG_RW,
+SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_defaultauthage, CTLFLAG_RW,
&fr_defaultauthage, 0, "");
-SYSCTL_INT(_net_inet_ipf, OID_AUTO, ippr_ftp_pasvonly, CTLFLAG_RW,
+SYSCTL_IPF(_net_inet_ipf, OID_AUTO, ippr_ftp_pasvonly, CTLFLAG_RW,
&ippr_ftp_pasvonly, 0, "");
#endif
#ifdef DEVFS
-static void *ipf_devfs[IPL_LOGMAX + 1];
+static void *ipf_devfs[IPL_LOGSIZE];
#endif
#if !defined(__FreeBSD_version) || (__FreeBSD_version < 220000)
@@ -142,17 +145,17 @@ int ipl_major = 0;
static struct cdevsw ipldevsw =
{
- iplopen, /* open */
- iplclose, /* close */
- iplread, /* read */
- (void *)nullop, /* write */
- iplioctl, /* ioctl */
- (void *)nullop, /* stop */
- (void *)nullop, /* reset */
- (void *)NULL, /* tty */
- (void *)nullop, /* select */
- (void *)nullop, /* mmap */
- NULL /* strategy */
+ iplopen, /* open */
+ iplclose, /* close */
+ iplread, /* read */
+ (void *)nullop, /* write */
+ iplioctl, /* ioctl */
+ (void *)nullop, /* stop */
+ (void *)nullop, /* reset */
+ (void *)NULL, /* tty */
+ (void *)nullop, /* select */
+ (void *)nullop, /* mmap */
+ NULL /* strategy */
};
MOD_DEV(IPL_VERSION, LM_DT_CHAR, -1, &ipldevsw);
@@ -183,7 +186,8 @@ static int if_ipl_remove __P((void));
static int ipl_major = CDEV_MAJOR;
static int iplaction __P((struct lkm_table *, int));
-static char *ipf_devfiles[] = { IPL_NAME, IPL_NAT, IPL_STATE, IPL_AUTH, NULL };
+static char *ipf_devfiles[] = { IPL_NAME, IPL_NAT, IPL_STATE, IPL_AUTH,
+ IPL_SCAN, IPL_SYNC, IPL_POOL, NULL };
extern int lkmenodev __P((void));
@@ -236,6 +240,12 @@ int cmd;
devfs_remove_dev(ipf_devfs[IPL_LOGSTATE]);
if (ipf_devfs[IPL_LOGAUTH])
devfs_remove_dev(ipf_devfs[IPL_LOGAUTH]);
+ if (ipf_devfs[IPL_LOGSCAN])
+ devfs_remove_dev(ipf_devfs[IPL_LOGSCAN]);
+ if (ipf_devfs[IPL_LOGSYNC])
+ devfs_remove_dev(ipf_devfs[IPL_LOGSYNC]);
+ if (ipf_devfs[IPL_LOGLOOKUP])
+ devfs_remove_dev(ipf_devfs[IPL_LOGLOOKUP]);
#endif
}
return err;
@@ -329,7 +339,7 @@ int cmd;
VOP_LEASE(nd.ni_dvp, curproc, curproc->p_ucred, LEASE_WRITE);
error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr);
#if (__FreeBSD_version >= 300000)
- vput(nd.ni_dvp);
+ vput(nd.ni_dvp);
#endif
if (error)
return error;
@@ -346,11 +356,11 @@ int cmd;
size_t strlen(string)
char *string;
{
- register char *s;
+ register char *s;
- for (s = string; *s; s++)
+ for (s = string; *s; s++)
;
- return (size_t)(s - string);
+ return (size_t)(s - string);
}
@@ -395,7 +405,7 @@ int cmd, ver;
# endif
}
# endif /* IPFILTER_LKM */
-static int ipl_devsw_installed = 0;
+static ipl_devsw_installed = 0;
static void ipl_drvinit __P((void *unused))
{
@@ -415,15 +425,43 @@ static void ipl_drvinit __P((void *unused))
tp[IPL_LOGNAT] = devfs_add_devswf(&ipl_cdevsw, IPL_LOGNAT,
DV_CHR, 0, 0, 0600, "ipnat");
tp[IPL_LOGSTATE] = devfs_add_devswf(&ipl_cdevsw, IPL_LOGSTATE,
- DV_CHR, 0, 0, 0600,
+ DV_CHR, 0, 0, 0600,
"ipstate");
tp[IPL_LOGAUTH] = devfs_add_devswf(&ipl_cdevsw, IPL_LOGAUTH,
- DV_CHR, 0, 0, 0600,
+ DV_CHR, 0, 0, 0600,
"ipauth");
# endif
}
}
+
+#ifdef SYSCTL_IPF
+int
+sysctl_ipf_int SYSCTL_HANDLER_ARGS
+{
+ int error = 0;
+
+ if (arg1)
+ error = SYSCTL_OUT(req, arg1, sizeof(int));
+ else
+ error = SYSCTL_OUT(req, &arg2, sizeof(int));
+
+ if (error || !req->newptr)
+ return (error);
+
+ if (!arg1)
+ error = EPERM;
+ else {
+ if ((oidp->oid_kind & CTLFLAG_OFF) && (fr_running > 0))
+ error = EBUSY;
+ else
+ error = SYSCTL_IN(req, arg1, sizeof(int));
+ }
+ return (error);
+}
+#endif
+
+
# if defined(IPFILTER_LKM) || \
defined(__FreeBSD_version) && (__FreeBSD_version >= 220000)
SYSINIT(ipldev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,ipl_drvinit,NULL)
diff --git a/contrib/ipfilter/mlf_rule.c b/contrib/ipfilter/mlf_rule.c
new file mode 100644
index 0000000..731ef5e
--- /dev/null
+++ b/contrib/ipfilter/mlf_rule.c
@@ -0,0 +1,168 @@
+/* $NetBSD$ */
+
+/*
+ * Copyright (C) 1993-2001 by Darren Reed.
+ *
+ * See the IPFILTER.LICENCE file for details on licencing.
+ */
+/*
+ * 29/12/94 Added code from Marc Huber <huber@fzi.de> to allow it to allocate
+ * its own major char number! Way cool patch!
+ */
+
+
+#include <sys/param.h>
+
+#if defined(__FreeBSD__) && (__FreeBSD__ > 1)
+# ifdef IPFILTER_LKM
+# include <osreldate.h>
+# define ACTUALLY_LKM_NOT_KERNEL
+# else
+# include <sys/osreldate.h>
+# endif
+#endif
+#include <sys/systm.h>
+#if defined(__FreeBSD_version) && (__FreeBSD_version >= 220000)
+# include <sys/conf.h>
+# include <sys/kernel.h>
+# ifdef DEVFS
+# include <sys/devfsext.h>
+# endif /*DEVFS*/
+#endif
+#include <sys/conf.h>
+#include <sys/file.h>
+#if defined(__FreeBSD_version) && (__FreeBSD_version >= 300000)
+# include <sys/lock.h>
+#endif
+#include <sys/stat.h>
+#include <sys/proc.h>
+#include <sys/kernel.h>
+#include <sys/vnode.h>
+#include <sys/namei.h>
+#include <sys/malloc.h>
+#include <sys/mount.h>
+#include <sys/exec.h>
+#include <sys/mbuf.h>
+#if BSD >= 199506
+# include <sys/sysctl.h>
+#endif
+#if (__FreeBSD_version >= 300000)
+# include <sys/socket.h>
+#endif
+#if (__FreeBSD_version >= 199511)
+#include <net/if.h>
+#include <netinet/in_systm.h>
+#include <netinet/in.h>
+#include <netinet/ip.h>
+#include <net/route.h>
+#include <netinet/ip_var.h>
+#include <netinet/tcp.h>
+#include <netinet/tcpip.h>
+#endif
+#if (__FreeBSD__ > 1)
+# include <sys/sysent.h>
+#endif
+#include <sys/lkm.h>
+#include "netinet/ip_compat.h"
+#include "netinet/ip_fil.h"
+#include "netinet/ip_rules.h"
+
+
+int xxxinit __P((struct lkm_table *, int, int));
+
+#if !defined(__FreeBSD_version) || (__FreeBSD_version < 220000)
+MOD_DEV(IPL_VERSION, LM_DT_CHAR, -1, &ipldevsw);
+#endif
+
+static int ipfrule_ioctl __P((struct lkm_table *, int));
+
+#if defined(__FreeBSD_version) && (__FreeBSD_version < 220000)
+
+int xxxinit(lkmtp, cmd, ver)
+struct lkm_table *lkmtp;
+int cmd, ver;
+{
+ DISPATCH(lkmtp, cmd, ver, ipfrule_ioctl, ipfrule_ioctl, ipfrule_ioctl);
+}
+#else /* __FREEBSD_version >= 220000 */
+# ifdef IPFILTER_LKM
+# include <sys/exec.h>
+
+# if (__FreeBSD_version >= 300000)
+MOD_MISC(ipfrule);
+# else
+MOD_DECL(ipfrule);
+
+
+static struct lkm_misc _module = {
+ LM_MISC,
+ LKM_VERSION,
+ "IP Filter rules",
+ 0,
+};
+# endif
+
+
+int ipfrule __P((struct lkm_table *, int, int));
+
+
+int ipfrule(lkmtp, cmd, ver)
+struct lkm_table *lkmtp;
+int cmd, ver;
+{
+# if (__FreeBSD_version >= 300000)
+ MOD_DISPATCH(ipfrule, lkmtp, cmd, ver, ipfrule_ioctl, ipfrule_ioctl,
+ ipfrule_ioctl);
+# else
+ DISPATCH(lkmtp, cmd, ver, ipfrule_ioctl, ipfrule_ioctl, ipfrule_ioctl);
+# endif
+}
+# endif /* IPFILTER_LKM */
+
+
+int ipfrule_load(lkmtp, cmd)
+struct lkm_table *lkmtp;
+int cmd;
+{
+ return ipfrule_add();
+}
+
+
+int ipfrule_unload(lkmtp, cmd)
+struct lkm_table *lkmtp;
+int cmd;
+{
+ return ipfrule_remove();
+}
+
+
+static int ipfrule_ioctl(lkmtp, cmd)
+struct lkm_table *lkmtp;
+int cmd;
+{
+ int err = 0;
+
+ switch (cmd)
+ {
+ case LKM_E_LOAD :
+ if (lkmexists(lkmtp))
+ return EEXIST;
+
+ err = ipfrule_load(lkmtp, cmd);
+ if (!err)
+ fr_refcnt++;
+ break;
+ case LKM_E_UNLOAD :
+ err = ipfrule_unload(lkmtp, cmd);
+ if (!err)
+ fr_refcnt--;
+ break;
+ case LKM_E_STAT :
+ break;
+ default:
+ err = EIO;
+ break;
+ }
+ return err;
+}
+#endif /* _FreeBSD_version */
diff --git a/contrib/ipfilter/mlfk_rule.c b/contrib/ipfilter/mlfk_rule.c
new file mode 100644
index 0000000..a4f3ba7
--- /dev/null
+++ b/contrib/ipfilter/mlfk_rule.c
@@ -0,0 +1,69 @@
+/* $NetBSD$ */
+
+/*
+ * Copyright (C) 2000 by Darren Reed.
+ *
+ * See the IPFILTER.LICENCE file for details on licencing.
+ *
+ * Id: mlfk_rule.c,v 2.4.4.2 2004/04/16 23:32:08 darrenr Exp
+ */
+
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/conf.h>
+#include <sys/socket.h>
+#include <sys/sysctl.h>
+#include <net/if.h>
+#include <netinet/in_systm.h>
+#include <netinet/in.h>
+
+#include <netinet/ipl.h>
+#include <netinet/ip_compat.h>
+#include <netinet/ip_fil.h>
+#include <netinet/ip_state.h>
+#include <netinet/ip_nat.h>
+#include <netinet/ip_auth.h>
+#include <netinet/ip_frag.h>
+
+#include "ip_rules.h"
+
+
+static int
+ipfrule_modevent(module_t mod, int type, void *unused)
+{
+ int error = 0;
+
+ switch (type)
+ {
+ case MOD_LOAD :
+ error = ipfrule_add();
+ if (!error)
+ fr_refcnt++;
+ break;
+ case MOD_UNLOAD :
+ error = ipfrule_remove();
+ if (!error)
+ fr_refcnt--;
+ break;
+ default:
+ error = EINVAL;
+ break;
+ }
+ return error;
+}
+
+static moduledata_t ipfrulemod = {
+ "ipfrule",
+ ipfrule_modevent,
+ 0
+};
+DECLARE_MODULE(ipfrule, ipfrulemod, SI_SUB_PROTO_DOMAIN, SI_ORDER_ANY);
+#ifdef MODULE_DEPEND
+MODULE_DEPEND(ipfrule, ipfilter, 1, 1, 1);
+#endif
+#ifdef MODULE_VERSION
+MODULE_VERSION(ipfrule, 1);
+#endif
diff --git a/contrib/ipfilter/mlh_rule.c b/contrib/ipfilter/mlh_rule.c
new file mode 100644
index 0000000..e71c7be
--- /dev/null
+++ b/contrib/ipfilter/mlh_rule.c
@@ -0,0 +1,114 @@
+/* $NetBSD$ */
+
+/*
+ * Copyright (C) 1993-1998 by Darren Reed.
+ *
+ * See the IPFILTER.LICENCE file for details on licencing.
+ *
+ */
+/* #pragma ident "@(#)solaris.c 1.12 6/5/96 (C) 1995 Darren Reed"*/
+
+/*typedef unsigned int spustate_t;*/
+struct uio;
+
+#include <sys/types.h>
+#include <sys/cmn_err.h>
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/malloc.h>
+#include <sys/conf.h>
+#include <sys/callout.h>
+#include <sys/moddefs.h>
+#include <sys/io.h>
+#include <sys/wsio.h>
+#include <sys/param.h>
+#include <sys/errno.h>
+#include <sys/byteorder.h>
+#include <sys/socket.h>
+#include <sys/stropts.h>
+#include <net/if.h>
+#include <net/af.h>
+#include <net/route.h>
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/if_ether.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_compat.h"
+#include "ip_fil.h"
+#include "ip_rules.h"
+
+
+/*
+ * Driver Header
+ */
+static drv_info_t ipf_drv_info = {
+ "IP Filter Rules", /* type */
+ "pseudo", /* class */
+ DRV_PSEUDO|DRV_SAVE_CONF|DRV_MP_SAFE, /* flags */
+ -1, /* b_major */
+ -1, /* c_major */
+ NULL, /* cdio */
+ NULL, /* gio_private */
+ NULL, /* cdio_private */
+};
+
+
+extern struct mod_operations gio_mod_ops;
+static drv_info_t ipf_drv_info;
+extern struct mod_conf_data ipf_conf_data;
+
+static struct mod_type_data ipf_drv_link = {
+ IPL_VERSION, (void *)NULL
+};
+
+static struct modlink ipf_mod_link[] = {
+ { &gio_mod_ops, (void *)&ipf_drv_link },
+ { NULL, (void *)NULL }
+};
+
+struct modwrapper ipf_wrapper = {
+ MODREV,
+ ipf_load,
+ ipf_unload,
+ (void (*)())NULL,
+ (void *)&ipf_conf_data,
+ ipf_mod_link
+};
+
+
+static int ipf_load(void *arg)
+{
+ int i;
+
+ i = ipfrule_add();
+ if (!i)
+ fr_refcnt--;
+#ifdef IPFDEBUG
+ printf("IP Filter Rules: ipfrule_add() = %d\n", i);
+#endif
+ if (!i)
+ cmn_err(CE_CONT, "IP Filter Rules: Loaded\n");
+ return i;
+}
+
+
+static int ipf_unload(void *arg)
+{
+ int i;
+
+ i = ipfrule_remove();
+ if (!i)
+ fr_refcnt--;
+#ifdef IPFDEBUG
+ printf("IP Filter Rules: ipfrule_remove() = %d\n", i);
+#endif
+ if (!i)
+ cmn_err(CE_CONT, "IP Filter Rules: Unloaded\n");
+ return i;
+}
diff --git a/contrib/ipfilter/net/.cvsignore b/contrib/ipfilter/net/.cvsignore
new file mode 100644
index 0000000..19f86f4
--- /dev/null
+++ b/contrib/ipfilter/net/.cvsignore
@@ -0,0 +1 @@
+done
diff --git a/contrib/ipfilter/opts.h b/contrib/ipfilter/opts.h
new file mode 100644
index 0000000..602c4e3
--- /dev/null
+++ b/contrib/ipfilter/opts.h
@@ -0,0 +1,67 @@
+/* $NetBSD$ */
+
+/*
+ * Copyright (C) 2000 by Darren Reed.
+ *
+ * See the IPFILTER.LICENCE file for details on licencing.
+ *
+ * Id: opts.h,v 2.12 2003/08/14 14:24:27 darrenr Exp
+ */
+
+#ifndef __OPTS_H__
+#define __OPTS_H__
+
+#ifndef SOLARIS
+#define SOLARIS (defined(sun) && (defined(__svr4__) || defined(__SVR4)))
+#endif
+#define OPT_REMOVE 0x000001
+#define OPT_DEBUG 0x000002
+#define OPT_AUTHSTATS 0x000004
+#define OPT_RAW 0x000008
+#define OPT_LOG 0x000010
+#define OPT_SHOWLIST 0x000020
+#define OPT_VERBOSE 0x000040
+#define OPT_DONOTHING 0x000080
+#define OPT_HITS 0x000100
+#define OPT_BRIEF 0x000200
+#define OPT_ACCNT 0x000400
+#define OPT_FRSTATES 0x000800
+#define OPT_SHOWLINENO 0x001000
+#define OPT_PRINTFR 0x002000
+#define OPT_OUTQUE FR_OUTQUE /* 0x4000 */
+#define OPT_INQUE FR_INQUE /* 0x8000 */
+#define OPT_ZERORULEST 0x010000
+#define OPT_SAVEOUT 0x020000
+#define OPT_IPSTATES 0x040000
+#define OPT_INACTIVE 0x080000
+#define OPT_NAT 0x100000
+#define OPT_GROUPS 0x200000
+#define OPT_STATETOP 0x400000
+#define OPT_FLUSH 0x800000
+#define OPT_CLEAR 0x1000000
+#define OPT_HEX 0x2000000
+#define OPT_ASCII 0x4000000
+#define OPT_NORESOLVE 0x8000000
+
+#define OPT_STAT OPT_FRSTATES
+#define OPT_LIST OPT_SHOWLIST
+
+
+#ifndef __P
+# ifdef __STDC__
+# define __P(x) x
+# else
+# define __P(x) ()
+# endif
+#endif
+
+#if defined(sun) && !SOLARIS
+# define STRERROR(x) sys_errlist[x]
+extern char *sys_errlist[];
+#else
+# define STRERROR(x) strerror(x)
+#endif
+
+extern int opts;
+
+#endif /* __OPTS_H__ */
diff --git a/contrib/ipfilter/pcap-ipf.h b/contrib/ipfilter/pcap-ipf.h
new file mode 100644
index 0000000..a6b974c
--- /dev/null
+++ b/contrib/ipfilter/pcap-ipf.h
@@ -0,0 +1,35 @@
+/* $NetBSD$ */
+
+/*
+ * Copyright (C) 1993-2001 by Darren Reed.
+ *
+ * See the IPFILTER.LICENCE file for details on licencing.
+ *
+ */
+/*
+ * This header file is constructed to match the version described by
+ * PCAP_VERSION_MAJ.
+ *
+ * The structure largely derives from libpcap which wouldn't include
+ * nicely without bpf.
+ */
+typedef struct pcap_filehdr {
+ u_int pc_id;
+ u_short pc_v_maj;
+ u_short pc_v_min;
+ u_int pc_zone;
+ u_int pc_sigfigs;
+ u_int pc_slen;
+ u_int pc_type;
+} pcaphdr_t;
+
+#define TCPDUMP_MAGIC 0xa1b2c3d4
+
+#define PCAP_VERSION_MAJ 2
+
+typedef struct pcap_pkthdr {
+ struct timeval ph_ts;
+ u_int ph_clen;
+ u_int ph_len;
+} pcappkt_t;
+
diff --git a/contrib/ipfilter/perl/ipf-mrtg.pl b/contrib/ipfilter/perl/ipf-mrtg.pl
index cce30ab..a96a7cd 100644
--- a/contrib/ipfilter/perl/ipf-mrtg.pl
+++ b/contrib/ipfilter/perl/ipf-mrtg.pl
@@ -19,4 +19,4 @@ print "$in_pkts\n",
my $uptime = `/usr/bin/uptime`;
$uptime =~ /^\s+(\d{1,2}:\d{2}..)\s+up\s+(\d+)\s+(......),/;
print "$2 $3\n",
- "$firewall\n"; \ No newline at end of file
+ "$firewall\n";
diff --git a/contrib/ipfilter/perl/ipfmeta.pl b/contrib/ipfilter/perl/ipfmeta.pl
new file mode 100644
index 0000000..1a7bb3f
--- /dev/null
+++ b/contrib/ipfilter/perl/ipfmeta.pl
@@ -0,0 +1,210 @@
+#!/usr/bin/perl -w
+#
+# Written by Camiel Dobbelaar <cd@sentia.nl>, Aug-2000
+# ipfmeta is in the Public Domain.
+#
+
+use strict;
+use Getopt::Std;
+
+## PROCESS COMMANDLINE
+our($opt_v); $opt_v=1;
+getopts('v:') || die "usage: ipfmeta [-v verboselevel] [objfile]\n";
+my $verbose = $opt_v + 0;
+my $objfile = shift || "ipf.objs";
+my $MAXRECURSION = 10;
+
+## READ OBJECTS
+open(FH, "$objfile") || die "cannot open $objfile: $!\n";
+my @tokens;
+while (<FH>) {
+ chomp;
+ s/#.*$//; # remove comments
+ s/^\s+//; # compress whitespace
+ s/\s+$//;
+ next if m/^$/; # skip empty lines
+ push (@tokens, split);
+}
+close(FH) || die "cannot close $objfile: $!\n";
+# link objects with their values
+my $obj="";
+my %objs;
+while (@tokens) {
+ my $token = shift(@tokens);
+ if ($token =~ m/^\[([^]]*)\]$/) {
+ # new object
+ $obj = $1;
+ } else {
+ # new value
+ push(@{$objs{$obj}}, $token) unless ($obj eq "");
+ }
+}
+
+# sort objects: longest first
+my @objs = sort { length($b) <=> length($a) } keys %objs;
+
+## SUBSTITUTE OBJECTS WITH THEIR VALUES FROM STDIN
+foreach (<STDIN>) {
+ foreach (expand($_, 0)) {
+ print;
+ }
+}
+
+## END
+
+sub expand {
+ my $line = shift;
+ my $level = shift;
+ my @retlines = $line;
+ my $obj;
+ my $val;
+
+ # coarse protection
+ if ($level > $MAXRECURSION) {
+ print STDERR "ERR: recursion exceeds $MAXRECURSION levels\n";
+ return;
+ }
+
+ foreach $obj (@objs) {
+ if ($line =~ m/$obj/) {
+ @retlines = "";
+ if ($level < $verbose) {
+ # add metarule as a comment
+ push(@retlines, "# ".$line);
+ }
+ foreach $val (@{$objs{$obj}}) {
+ my $newline = $line;
+ $newline =~ s/$obj/$val/;
+ push(@retlines, expand($newline, $level+1));
+ }
+ last;
+ }
+ }
+
+ return @retlines;
+}
+
+__END__
+
+=head1 NAME
+
+B<ipfmeta> - use objects in IP filter files
+
+=head1 SYNOPSIS
+
+B<ipfmeta> [F<options>] [F<objfile>]
+
+=head1 DESCRIPTION
+
+B<ipfmeta> is used to simplify the maintenance of your IP filter
+ruleset. It does this through the use of 'objects'. A matching
+object gets replaced by its values at runtime. This is similar to
+what a macro processor like m4 does.
+
+B<ipfmeta> is specifically geared towards IP filter. It is line
+oriented, if an object has multiple values, the line with the object
+is duplicated and substituted for each value. It is also recursive,
+an object may have another object as a value.
+
+Rules to be processed are read from stdin, output goes to stdout.
+
+The verbose option allows for the inclusion of the metarules in the
+output as comments.
+
+Definition of the objects and their values is done in a separate
+file, the filename defaults to F<ipf.objs>. An object is delimited
+by square brackets. A value is delimited by whitespace. Comments
+start with '#' and end with a newline. Empty lines and extraneous
+whitespace are allowed. A value belongs to the first object that
+precedes it.
+
+It is recommended that you use all caps or another distinguishing
+feature for object names. You can use B<ipfmeta> for NAT rules also,
+for instance to keep them in sync with filter rules. Combine
+B<ipfmeta> with a Makefile to save typing.
+
+=head1 OPTIONS
+
+=over 4
+
+=item B<-v> I<verboselevel>
+
+Include metarules in output as comments. Default is 1, the top level
+metarules. Higher levels cause expanded metarules to be included.
+Level 0 does not add comments at all.
+
+=back
+
+=head1 BUGS
+
+A value can not have whitespace in it.
+
+=head1 EXAMPLE
+
+(this does not look good, formatted)
+
+I<ipf.objs>
+
+[PRIVATE] 10.0.0.0/8 127.0.0.0/8 172.16.0.0/12 192.168.0.0/16
+
+[MULTICAST] 224.0.0.0/4
+
+[UNWANTED] PRIVATE MULTICAST
+
+[NOC] xxx.yy.zz.1/32 xxx.yy.zz.2/32
+
+[WEBSERVERS] 192.168.1.1/32 192.168.1.2/32
+
+[MGMT-PORTS] 22 23
+
+I<ipf.metarules>
+
+block in from UNWANTED to any
+
+pass in from NOC to WEBSERVERS port = MGMT-PORTS
+
+pass out all
+
+I<Run>
+
+ipfmeta ipf.objs <ipf.metarules >ipf.rules
+
+I<Output>
+
+# block in from UNWANTED to any
+
+block in from 10.0.0.0/8 to any
+
+block in from 127.0.0.0/8 to any
+
+block in from 172.16.0.0/12 to any
+
+block in from 192.168.0.0/16 to any
+
+block in from 224.0.0.0/4 to any
+
+# pass in from NOC to WEBSERVERS port = MGMT-PORTS
+
+pass in from xxx.yy.zz.1/32 to 192.168.1.1/32 port = 22
+
+pass in from xxx.yy.zz.1/32 to 192.168.1.1/32 port = 23
+
+pass in from xxx.yy.zz.1/32 to 192.168.1.2/32 port = 22
+
+pass in from xxx.yy.zz.1/32 to 192.168.1.2/32 port = 23
+
+pass in from xxx.yy.zz.2/32 to 192.168.1.1/32 port = 22
+
+pass in from xxx.yy.zz.2/32 to 192.168.1.1/32 port = 23
+
+pass in from xxx.yy.zz.2/32 to 192.168.1.2/32 port = 22
+
+pass in from xxx.yy.zz.2/32 to 192.168.1.2/32 port = 23
+
+pass out all
+
+=head1 AUTHOR
+
+Camiel Dobbelaar <cd@sentia.nl>. B<ipfmeta> is in the Public Domain.
+
+=cut
diff --git a/contrib/ipfilter/perl/logfilter.pl b/contrib/ipfilter/perl/logfilter.pl
index 6ebe401..a75eafd 100644
--- a/contrib/ipfilter/perl/logfilter.pl
+++ b/contrib/ipfilter/perl/logfilter.pl
@@ -178,4 +178,4 @@ tcp 6667 irc.log
tcp 7070 realaudio.log
tcp 8080 http.log
tcp 12345 netbus.log
-udp 31337 backorifice.log \ No newline at end of file
+udp 31337 backorifice.log
diff --git a/contrib/ipfilter/radix.c b/contrib/ipfilter/radix.c
new file mode 100644
index 0000000..964c1095
--- /dev/null
+++ b/contrib/ipfilter/radix.c
@@ -0,0 +1,1202 @@
+/* $NetBSD$ */
+
+/*
+ * Copyright (c) 1988, 1989, 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.
+ *
+ * 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.
+ *
+ * @(#)radix.c 8.6 (Berkeley) 10/17/95
+ */
+
+/*
+ * Routines to build and maintain radix trees for routing lookups.
+ */
+#if defined(KERNEL) || defined(_KERNEL)
+# undef KERNEL
+# undef _KERNEL
+# define KERNEL 1
+# define _KERNEL 1
+#endif
+#define __SYS_ATOMIC_OPS_H__
+#if !defined(__svr4__) && !defined(__SVR4) && !defined(__osf__) && \
+ !defined(__hpux) && !defined(__sgi)
+#include <sys/cdefs.h>
+#endif
+#ifndef __P
+# ifdef __STDC__
+# define __P(x) x
+# else
+# define __P(x) ()
+# endif
+#endif
+#ifdef __osf__
+# define CONST
+# define _IPV6_SWTAB_H
+# define _PROTO_NET_H_
+# define _PROTO_IPV6_H
+# include <sys/malloc.h>
+#endif
+
+#include <sys/param.h>
+#ifdef _KERNEL
+#include <sys/systm.h>
+#else
+void panic __P((char *str));
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#endif
+#ifdef __hpux
+#include <syslog.h>
+#else
+#include <sys/syslog.h>
+#endif
+#include <sys/time.h>
+#include <netinet/in.h>
+#include <sys/socket.h>
+#include <net/if.h>
+#include "netinet/ip_compat.h"
+#include "netinet/ip_fil.h"
+/* END OF INCLUDES */
+#include "radix_ipf.h"
+#ifndef min
+# define min MIN
+#endif
+#ifndef max
+# define max MAX
+#endif
+
+int max_keylen = 16;
+static struct radix_mask *rn_mkfreelist;
+static struct radix_node_head *mask_rnhead;
+static char *addmask_key;
+static u_char normal_chars[] = {0, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff};
+static char *rn_zeros = NULL, *rn_ones = NULL;
+
+#define rn_masktop (mask_rnhead->rnh_treetop)
+#undef Bcmp
+#define Bcmp(a, b, l) (l == 0 ? 0 : bcmp((caddr_t)(a), (caddr_t)(b), (u_long)l))
+
+static int rn_satisfies_leaf __P((char *, struct radix_node *, int));
+static int rn_lexobetter __P((void *, void *));
+static struct radix_mask *rn_new_radix_mask __P((struct radix_node *,
+ struct radix_mask *));
+static int rn_freenode __P((struct radix_node *, void *));
+
+/*
+ * The data structure for the keys is a radix tree with one way
+ * branching removed. The index rn_b at an internal node n represents a bit
+ * position to be tested. The tree is arranged so that all descendants
+ * of a node n have keys whose bits all agree up to position rn_b - 1.
+ * (We say the index of n is rn_b.)
+ *
+ * There is at least one descendant which has a one bit at position rn_b,
+ * and at least one with a zero there.
+ *
+ * A route is determined by a pair of key and mask. We require that the
+ * bit-wise logical and of the key and mask to be the key.
+ * We define the index of a route to associated with the mask to be
+ * the first bit number in the mask where 0 occurs (with bit number 0
+ * representing the highest order bit).
+ *
+ * We say a mask is normal if every bit is 0, past the index of the mask.
+ * If a node n has a descendant (k, m) with index(m) == index(n) == rn_b,
+ * and m is a normal mask, then the route applies to every descendant of n.
+ * If the index(m) < rn_b, this implies the trailing last few bits of k
+ * before bit b are all 0, (and hence consequently true of every descendant
+ * of n), so the route applies to all descendants of the node as well.
+ *
+ * Similar logic shows that a non-normal mask m such that
+ * index(m) <= index(n) could potentially apply to many children of n.
+ * Thus, for each non-host route, we attach its mask to a list at an internal
+ * node as high in the tree as we can go.
+ *
+ * The present version of the code makes use of normal routes in short-
+ * circuiting an explict mask and compare operation when testing whether
+ * a key satisfies a normal route, and also in remembering the unique leaf
+ * that governs a subtree.
+ */
+
+struct radix_node *
+rn_search(v_arg, head)
+ void *v_arg;
+ struct radix_node *head;
+{
+ struct radix_node *x;
+ caddr_t v;
+
+ for (x = head, v = v_arg; x->rn_b >= 0;) {
+ if (x->rn_bmask & v[x->rn_off])
+ x = x->rn_r;
+ else
+ x = x->rn_l;
+ }
+ return (x);
+}
+
+struct radix_node *
+rn_search_m(v_arg, head, m_arg)
+ struct radix_node *head;
+ void *v_arg, *m_arg;
+{
+ struct radix_node *x;
+ caddr_t v = v_arg, m = m_arg;
+
+ for (x = head; x->rn_b >= 0;) {
+ if ((x->rn_bmask & m[x->rn_off]) &&
+ (x->rn_bmask & v[x->rn_off]))
+ x = x->rn_r;
+ else
+ x = x->rn_l;
+ }
+ return x;
+}
+
+int
+rn_refines(m_arg, n_arg)
+ void *m_arg, *n_arg;
+{
+ caddr_t m = m_arg, n = n_arg;
+ caddr_t lim, lim2 = lim = n + *(u_char *)n;
+ int longer = (*(u_char *)n++) - (int)(*(u_char *)m++);
+ int masks_are_equal = 1;
+
+ if (longer > 0)
+ lim -= longer;
+ while (n < lim) {
+ if (*n & ~(*m))
+ return 0;
+ if (*n++ != *m++)
+ masks_are_equal = 0;
+ }
+ while (n < lim2)
+ if (*n++)
+ return 0;
+ if (masks_are_equal && (longer < 0))
+ for (lim2 = m - longer; m < lim2; )
+ if (*m++)
+ return 1;
+ return (!masks_are_equal);
+}
+
+struct radix_node *
+rn_lookup(v_arg, m_arg, head)
+ void *v_arg, *m_arg;
+ struct radix_node_head *head;
+{
+ struct radix_node *x;
+ caddr_t netmask = 0;
+
+ if (m_arg) {
+ if ((x = rn_addmask(m_arg, 1, head->rnh_treetop->rn_off)) == 0)
+ return (0);
+ netmask = x->rn_key;
+ }
+ x = rn_match(v_arg, head);
+ if (x && netmask) {
+ while (x && x->rn_mask != netmask)
+ x = x->rn_dupedkey;
+ }
+ return x;
+}
+
+static int
+rn_satisfies_leaf(trial, leaf, skip)
+ char *trial;
+ struct radix_node *leaf;
+ int skip;
+{
+ char *cp = trial, *cp2 = leaf->rn_key, *cp3 = leaf->rn_mask;
+ char *cplim;
+ int length = min(*(u_char *)cp, *(u_char *)cp2);
+
+ if (cp3 == 0)
+ cp3 = rn_ones;
+ else
+ length = min(length, *(u_char *)cp3);
+ cplim = cp + length;
+ cp3 += skip;
+ cp2 += skip;
+ for (cp += skip; cp < cplim; cp++, cp2++, cp3++)
+ if ((*cp ^ *cp2) & *cp3)
+ return 0;
+ return 1;
+}
+
+struct radix_node *
+rn_match(v_arg, head)
+ void *v_arg;
+ struct radix_node_head *head;
+{
+ caddr_t v = v_arg;
+ struct radix_node *t = head->rnh_treetop, *x;
+ caddr_t cp = v, cp2;
+ caddr_t cplim;
+ struct radix_node *saved_t, *top = t;
+ int off = t->rn_off, vlen = *(u_char *)cp, matched_off;
+ int test, b, rn_b;
+
+ /*
+ * Open code rn_search(v, top) to avoid overhead of extra
+ * subroutine call.
+ */
+ for (; t->rn_b >= 0; ) {
+ if (t->rn_bmask & cp[t->rn_off])
+ t = t->rn_r;
+ else
+ t = t->rn_l;
+ }
+ /*
+ * See if we match exactly as a host destination
+ * or at least learn how many bits match, for normal mask finesse.
+ *
+ * It doesn't hurt us to limit how many bytes to check
+ * to the length of the mask, since if it matches we had a genuine
+ * match and the leaf we have is the most specific one anyway;
+ * if it didn't match with a shorter length it would fail
+ * with a long one. This wins big for class B&C netmasks which
+ * are probably the most common case...
+ */
+ if (t->rn_mask)
+ vlen = *(u_char *)t->rn_mask;
+ cp += off;
+ cp2 = t->rn_key + off;
+ cplim = v + vlen;
+ for (; cp < cplim; cp++, cp2++)
+ if (*cp != *cp2)
+ goto on1;
+ /*
+ * This extra grot is in case we are explicitly asked
+ * to look up the default. Ugh!
+ */
+ if ((t->rn_flags & RNF_ROOT) && t->rn_dupedkey)
+ t = t->rn_dupedkey;
+ return t;
+on1:
+ test = (*cp ^ *cp2) & 0xff; /* find first bit that differs */
+ for (b = 7; (test >>= 1) > 0;)
+ b--;
+ matched_off = cp - v;
+ b += matched_off << 3;
+ rn_b = -1 - b;
+ /*
+ * If there is a host route in a duped-key chain, it will be first.
+ */
+ if ((saved_t = t)->rn_mask == 0)
+ t = t->rn_dupedkey;
+ for (; t; t = t->rn_dupedkey)
+ /*
+ * Even if we don't match exactly as a host,
+ * we may match if the leaf we wound up at is
+ * a route to a net.
+ */
+ if (t->rn_flags & RNF_NORMAL) {
+ if (rn_b <= t->rn_b)
+ return t;
+ } else if (rn_satisfies_leaf(v, t, matched_off))
+ return t;
+ t = saved_t;
+ /* start searching up the tree */
+ do {
+ struct radix_mask *m;
+ t = t->rn_p;
+ m = t->rn_mklist;
+ if (m) {
+ /*
+ * If non-contiguous masks ever become important
+ * we can restore the masking and open coding of
+ * the search and satisfaction test and put the
+ * calculation of "off" back before the "do".
+ */
+ do {
+ if (m->rm_flags & RNF_NORMAL) {
+ if (rn_b <= m->rm_b)
+ return (m->rm_leaf);
+ } else {
+ off = min(t->rn_off, matched_off);
+ x = rn_search_m(v, t, m->rm_mask);
+ while (x && x->rn_mask != m->rm_mask)
+ x = x->rn_dupedkey;
+ if (x && rn_satisfies_leaf(v, x, off))
+ return x;
+ }
+ m = m->rm_mklist;
+ } while (m);
+ }
+ } while (t != top);
+ return 0;
+}
+
+#ifdef RN_DEBUG
+int rn_nodenum;
+struct radix_node *rn_clist;
+int rn_saveinfo;
+int rn_debug = 1;
+#endif
+
+struct radix_node *
+rn_newpair(v, b, nodes)
+ void *v;
+ int b;
+ struct radix_node nodes[2];
+{
+ struct radix_node *tt = nodes, *t = tt + 1;
+ t->rn_b = b;
+ t->rn_bmask = 0x80 >> (b & 7);
+ t->rn_l = tt;
+ t->rn_off = b >> 3;
+ tt->rn_b = -1;
+ tt->rn_key = (caddr_t)v;
+ tt->rn_p = t;
+ tt->rn_flags = t->rn_flags = RNF_ACTIVE;
+#ifdef RN_DEBUG
+ tt->rn_info = rn_nodenum++;
+ t->rn_info = rn_nodenum++;
+ tt->rn_twin = t;
+ tt->rn_ybro = rn_clist;
+ rn_clist = tt;
+#endif
+ return t;
+}
+
+struct radix_node *
+rn_insert(v_arg, head, dupentry, nodes)
+ void *v_arg;
+ struct radix_node_head *head;
+ int *dupentry;
+ struct radix_node nodes[2];
+{
+ caddr_t v = v_arg;
+ struct radix_node *top = head->rnh_treetop;
+ int head_off = top->rn_off, vlen = (int)*((u_char *)v);
+ struct radix_node *t = rn_search(v_arg, top);
+ caddr_t cp = v + head_off;
+ int b;
+ struct radix_node *tt;
+
+#ifdef RN_DEBUG
+ if (rn_debug)
+ log(LOG_DEBUG, "rn_insert(%p,%p,%p,%p)\n", v_arg, head, dupentry, nodes);
+#endif
+ /*
+ * Find first bit at which v and t->rn_key differ
+ */
+ {
+ caddr_t cp2 = t->rn_key + head_off;
+ int cmp_res;
+ caddr_t cplim = v + vlen;
+
+ while (cp < cplim)
+ if (*cp2++ != *cp++)
+ goto on1;
+ *dupentry = 1;
+ return t;
+on1:
+ *dupentry = 0;
+ cmp_res = (cp[-1] ^ cp2[-1]) & 0xff;
+ for (b = (cp - v) << 3; cmp_res; b--)
+ cmp_res >>= 1;
+ }
+ {
+ struct radix_node *p, *x = top;
+ cp = v;
+ do {
+ p = x;
+ if (cp[x->rn_off] & x->rn_bmask)
+ x = x->rn_r;
+ else
+ x = x->rn_l;
+ } while (b > (unsigned) x->rn_b); /* x->rn_b < b && x->rn_b >= 0 */
+#ifdef RN_DEBUG
+ if (rn_debug)
+ log(LOG_DEBUG, "rn_insert: Going In:\n"); // traverse(p);
+#endif
+ t = rn_newpair(v_arg, b, nodes);
+ tt = t->rn_l;
+ if ((cp[p->rn_off] & p->rn_bmask) == 0)
+ p->rn_l = t;
+ else
+ p->rn_r = t;
+ x->rn_p = t;
+ t->rn_p = p; /* frees x, p as temp vars below */
+ if ((cp[t->rn_off] & t->rn_bmask) == 0) {
+ t->rn_r = x;
+ } else {
+ t->rn_r = tt;
+ t->rn_l = x;
+ }
+#ifdef RN_DEBUG
+ if (rn_debug)
+ log(LOG_DEBUG, "rn_insert: Coming Out:\n"); // traverse(p);
+#endif
+ }
+ return (tt);
+}
+
+struct radix_node *
+rn_addmask(n_arg, search, skip)
+ int search, skip;
+ void *n_arg;
+{
+ caddr_t netmask = (caddr_t)n_arg;
+ struct radix_node *x;
+ caddr_t cp, cplim;
+ int b = 0, mlen, j;
+ int maskduplicated, m0, isnormal;
+ struct radix_node *saved_x;
+ static int last_zeroed = 0;
+
+#ifdef RN_DEBUG
+ if (rn_debug)
+ log(LOG_DEBUG, "rn_addmask(%p,%d,%d)\n", n_arg, search, skip);
+#endif
+ mlen = *(u_char *)netmask;
+ if ((mlen = *(u_char *)netmask) > max_keylen)
+ mlen = max_keylen;
+ if (skip == 0)
+ skip = 1;
+ if (mlen <= skip)
+ return (mask_rnhead->rnh_nodes);
+ if (skip > 1)
+ Bcopy(rn_ones + 1, addmask_key + 1, skip - 1);
+ if ((m0 = mlen) > skip)
+ Bcopy(netmask + skip, addmask_key + skip, mlen - skip);
+ /*
+ * Trim trailing zeroes.
+ */
+ for (cp = addmask_key + mlen; (cp > addmask_key) && cp[-1] == 0;)
+ cp--;
+ mlen = cp - addmask_key;
+ if (mlen <= skip) {
+ if (m0 >= last_zeroed)
+ last_zeroed = mlen;
+ return (mask_rnhead->rnh_nodes);
+ }
+ if (m0 < last_zeroed)
+ Bzero(addmask_key + m0, last_zeroed - m0);
+ *addmask_key = last_zeroed = mlen;
+ x = rn_search(addmask_key, rn_masktop);
+ if (Bcmp(addmask_key, x->rn_key, mlen) != 0)
+ x = 0;
+ if (x || search)
+ return (x);
+ R_Malloc(x, struct radix_node *, max_keylen + 2 * sizeof (*x));
+ if ((saved_x = x) == 0)
+ return (0);
+ Bzero(x, max_keylen + 2 * sizeof (*x));
+ netmask = cp = (caddr_t)(x + 2);
+ Bcopy(addmask_key, cp, mlen);
+ x = rn_insert(cp, mask_rnhead, &maskduplicated, x);
+ if (maskduplicated) {
+#if 0
+ log(LOG_ERR, "rn_addmask: mask impossibly already in tree\n");
+#endif
+ Free(saved_x);
+ return (x);
+ }
+ /*
+ * Calculate index of mask, and check for normalcy.
+ */
+ cplim = netmask + mlen;
+ isnormal = 1;
+ for (cp = netmask + skip; (cp < cplim) && *(u_char *)cp == 0xff;)
+ cp++;
+ if (cp != cplim) {
+ for (j = 0x80; (j & *cp) != 0; j >>= 1)
+ b++;
+ if (*cp != normal_chars[b] || cp != (cplim - 1))
+ isnormal = 0;
+ }
+ b += (cp - netmask) << 3;
+ x->rn_b = -1 - b;
+ if (isnormal)
+ x->rn_flags |= RNF_NORMAL;
+ return (x);
+}
+
+static int /* XXX: arbitrary ordering for non-contiguous masks */
+rn_lexobetter(m_arg, n_arg)
+ void *m_arg, *n_arg;
+{
+ u_char *mp = m_arg, *np = n_arg, *lim;
+
+ if (*mp > *np)
+ return 1; /* not really, but need to check longer one first */
+ if (*mp == *np)
+ for (lim = mp + *mp; mp < lim;)
+ if (*mp++ > *np++)
+ return 1;
+ return 0;
+}
+
+static struct radix_mask *
+rn_new_radix_mask(tt, next)
+ struct radix_node *tt;
+ struct radix_mask *next;
+{
+ struct radix_mask *m;
+
+ MKGet(m);
+ if (m == 0) {
+#if 0
+ log(LOG_ERR, "Mask for route not entered\n");
+#endif
+ return (0);
+ }
+ Bzero(m, sizeof *m);
+ m->rm_b = tt->rn_b;
+ m->rm_flags = tt->rn_flags;
+ if (tt->rn_flags & RNF_NORMAL)
+ m->rm_leaf = tt;
+ else
+ m->rm_mask = tt->rn_mask;
+ m->rm_mklist = next;
+ tt->rn_mklist = m;
+ return m;
+}
+
+struct radix_node *
+rn_addroute(v_arg, n_arg, head, treenodes)
+ void *v_arg, *n_arg;
+ struct radix_node_head *head;
+ struct radix_node treenodes[2];
+{
+ caddr_t v = (caddr_t)v_arg, netmask = (caddr_t)n_arg;
+ struct radix_node *t, *x = NULL, *tt;
+ struct radix_node *saved_tt, *top = head->rnh_treetop;
+ short b = 0, b_leaf = 0;
+ int keyduplicated;
+ caddr_t mmask;
+ struct radix_mask *m, **mp;
+
+#ifdef RN_DEBUG
+ if (rn_debug)
+ log(LOG_DEBUG, "rn_addroute(%p,%p,%p,%p)\n", v_arg, n_arg, head, treenodes);
+#endif
+ /*
+ * In dealing with non-contiguous masks, there may be
+ * many different routes which have the same mask.
+ * We will find it useful to have a unique pointer to
+ * the mask to speed avoiding duplicate references at
+ * nodes and possibly save time in calculating indices.
+ */
+ if (netmask) {
+ if ((x = rn_addmask(netmask, 0, top->rn_off)) == 0)
+ return (0);
+ b_leaf = x->rn_b;
+ b = -1 - x->rn_b;
+ netmask = x->rn_key;
+ }
+ /*
+ * Deal with duplicated keys: attach node to previous instance
+ */
+ saved_tt = tt = rn_insert(v, head, &keyduplicated, treenodes);
+ if (keyduplicated) {
+ for (t = tt; tt; t = tt, tt = tt->rn_dupedkey) {
+ if (tt->rn_mask == netmask)
+ return (0);
+ if (netmask == 0 ||
+ (tt->rn_mask &&
+ ((b_leaf < tt->rn_b) || /* index(netmask) > node */
+ rn_refines(netmask, tt->rn_mask) ||
+ rn_lexobetter(netmask, tt->rn_mask))))
+ break;
+ }
+ /*
+ * If the mask is not duplicated, we wouldn't
+ * find it among possible duplicate key entries
+ * anyway, so the above test doesn't hurt.
+ *
+ * We sort the masks for a duplicated key the same way as
+ * in a masklist -- most specific to least specific.
+ * This may require the unfortunate nuisance of relocating
+ * the head of the list.
+ *
+ * We also reverse, or doubly link the list through the
+ * parent pointer.
+ */
+ if (tt == saved_tt) {
+ struct radix_node *xx = x;
+ /* link in at head of list */
+ (tt = treenodes)->rn_dupedkey = t;
+ tt->rn_flags = t->rn_flags;
+ tt->rn_p = x = t->rn_p;
+ t->rn_p = tt;
+ if (x->rn_l == t)
+ x->rn_l = tt;
+ else
+ x->rn_r = tt;
+ saved_tt = tt;
+ x = xx;
+ } else {
+ (tt = treenodes)->rn_dupedkey = t->rn_dupedkey;
+ t->rn_dupedkey = tt;
+ tt->rn_p = t;
+ if (tt->rn_dupedkey)
+ tt->rn_dupedkey->rn_p = tt;
+ }
+#ifdef RN_DEBUG
+ t=tt+1;
+ tt->rn_info = rn_nodenum++;
+ t->rn_info = rn_nodenum++;
+ tt->rn_twin = t;
+ tt->rn_ybro = rn_clist;
+ rn_clist = tt;
+#endif
+ tt->rn_key = (caddr_t) v;
+ tt->rn_b = -1;
+ tt->rn_flags = RNF_ACTIVE;
+ }
+ /*
+ * Put mask in tree.
+ */
+ if (netmask) {
+ tt->rn_mask = netmask;
+ tt->rn_b = x->rn_b;
+ tt->rn_flags |= x->rn_flags & RNF_NORMAL;
+ }
+ t = saved_tt->rn_p;
+ if (keyduplicated)
+ goto on2;
+ b_leaf = -1 - t->rn_b;
+ if (t->rn_r == saved_tt)
+ x = t->rn_l;
+ else
+ x = t->rn_r;
+ /* Promote general routes from below */
+ if (x->rn_b < 0) {
+ for (mp = &t->rn_mklist; x; x = x->rn_dupedkey)
+ if (x->rn_mask && (x->rn_b >= b_leaf) && x->rn_mklist == 0) {
+ *mp = m = rn_new_radix_mask(x, 0);
+ if (m)
+ mp = &m->rm_mklist;
+ }
+ } else if (x->rn_mklist) {
+ /*
+ * Skip over masks whose index is > that of new node
+ */
+ for (mp = &x->rn_mklist; (m = *mp) != NULL; mp = &m->rm_mklist)
+ if (m->rm_b >= b_leaf)
+ break;
+ t->rn_mklist = m;
+ *mp = 0;
+ }
+on2:
+ /* Add new route to highest possible ancestor's list */
+ if ((netmask == 0) || (b > t->rn_b ))
+ return tt; /* can't lift at all */
+ b_leaf = tt->rn_b;
+ do {
+ x = t;
+ t = t->rn_p;
+ } while (b <= t->rn_b && x != top);
+ /*
+ * Search through routes associated with node to
+ * insert new route according to index.
+ * Need same criteria as when sorting dupedkeys to avoid
+ * double loop on deletion.
+ */
+ for (mp = &x->rn_mklist; (m = *mp) != NULL; mp = &m->rm_mklist) {
+ if (m->rm_b < b_leaf)
+ continue;
+ if (m->rm_b > b_leaf)
+ break;
+ if (m->rm_flags & RNF_NORMAL) {
+ mmask = m->rm_leaf->rn_mask;
+ if (tt->rn_flags & RNF_NORMAL) {
+#if 0
+ log(LOG_ERR, "Non-unique normal route,"
+ " mask not entered\n");
+#endif
+ return tt;
+ }
+ } else
+ mmask = m->rm_mask;
+ if (mmask == netmask) {
+ m->rm_refs++;
+ tt->rn_mklist = m;
+ return tt;
+ }
+ if (rn_refines(netmask, mmask)
+ || rn_lexobetter(netmask, mmask))
+ break;
+ }
+ *mp = rn_new_radix_mask(tt, *mp);
+ return tt;
+}
+
+struct radix_node *
+rn_delete(v_arg, netmask_arg, head)
+ void *v_arg, *netmask_arg;
+ struct radix_node_head *head;
+{
+ struct radix_node *t, *p, *x, *tt;
+ struct radix_mask *m, *saved_m, **mp;
+ struct radix_node *dupedkey, *saved_tt, *top;
+ caddr_t v, netmask;
+ int b, head_off, vlen;
+
+ v = v_arg;
+ netmask = netmask_arg;
+ x = head->rnh_treetop;
+ tt = rn_search(v, x);
+ head_off = x->rn_off;
+ vlen = *(u_char *)v;
+ saved_tt = tt;
+ top = x;
+ if (tt == 0 ||
+ Bcmp(v + head_off, tt->rn_key + head_off, vlen - head_off))
+ return (0);
+ /*
+ * Delete our route from mask lists.
+ */
+ if (netmask) {
+ if ((x = rn_addmask(netmask, 1, head_off)) == 0)
+ return (0);
+ netmask = x->rn_key;
+ while (tt->rn_mask != netmask)
+ if ((tt = tt->rn_dupedkey) == 0)
+ return (0);
+ }
+ if (tt->rn_mask == 0 || (saved_m = m = tt->rn_mklist) == 0)
+ goto on1;
+ if (tt->rn_flags & RNF_NORMAL) {
+ if (m->rm_leaf != tt || m->rm_refs > 0) {
+#if 0
+ log(LOG_ERR, "rn_delete: inconsistent annotation\n");
+#endif
+ return 0; /* dangling ref could cause disaster */
+ }
+ } else {
+ if (m->rm_mask != tt->rn_mask) {
+#if 0
+ log(LOG_ERR, "rn_delete: inconsistent annotation\n");
+#endif
+ goto on1;
+ }
+ if (--m->rm_refs >= 0)
+ goto on1;
+ }
+ b = -1 - tt->rn_b;
+ t = saved_tt->rn_p;
+ if (b > t->rn_b)
+ goto on1; /* Wasn't lifted at all */
+ do {
+ x = t;
+ t = t->rn_p;
+ } while (b <= t->rn_b && x != top);
+ for (mp = &x->rn_mklist; (m = *mp) != NULL; mp = &m->rm_mklist)
+ if (m == saved_m) {
+ *mp = m->rm_mklist;
+ MKFree(m);
+ break;
+ }
+ if (m == 0) {
+#if 0
+ log(LOG_ERR, "rn_delete: couldn't find our annotation\n");
+#endif
+ if (tt->rn_flags & RNF_NORMAL)
+ return (0); /* Dangling ref to us */
+ }
+on1:
+ /*
+ * Eliminate us from tree
+ */
+ if (tt->rn_flags & RNF_ROOT)
+ return (0);
+#ifdef RN_DEBUG
+ /* Get us out of the creation list */
+ for (t = rn_clist; t && t->rn_ybro != tt; t = t->rn_ybro)
+ ;
+ if (t) t->rn_ybro = tt->rn_ybro;
+#endif
+ t = tt->rn_p;
+ dupedkey = saved_tt->rn_dupedkey;
+ if (dupedkey) {
+ /*
+ * Here, tt is the deletion target and
+ * saved_tt is the head of the dupedkey chain.
+ */
+ if (tt == saved_tt) {
+ x = dupedkey;
+ x->rn_p = t;
+ if (t->rn_l == tt)
+ t->rn_l = x;
+ else
+ t->rn_r = x;
+ } else {
+ /* find node in front of tt on the chain */
+ for (x = p = saved_tt; p && p->rn_dupedkey != tt;)
+ p = p->rn_dupedkey;
+ if (p) {
+ p->rn_dupedkey = tt->rn_dupedkey;
+ if (tt->rn_dupedkey)
+ tt->rn_dupedkey->rn_p = p;
+ }
+#if 0
+ else
+ log(LOG_ERR, "rn_delete: couldn't find us\n");
+#endif
+ }
+ t = tt + 1;
+ if (t->rn_flags & RNF_ACTIVE) {
+#ifndef RN_DEBUG
+ *++x = *t;
+ p = t->rn_p;
+#else
+ b = t->rn_info;
+ *++x = *t;
+ t->rn_info = b;
+ p = t->rn_p;
+#endif
+ if (p->rn_l == t)
+ p->rn_l = x;
+ else
+ p->rn_r = x;
+ x->rn_l->rn_p = x;
+ x->rn_r->rn_p = x;
+ }
+ goto out;
+ }
+ if (t->rn_l == tt)
+ x = t->rn_r;
+ else
+ x = t->rn_l;
+ p = t->rn_p;
+ if (p->rn_r == t)
+ p->rn_r = x;
+ else
+ p->rn_l = x;
+ x->rn_p = p;
+ /*
+ * Demote routes attached to us.
+ */
+ if (t->rn_mklist) {
+ if (x->rn_b >= 0) {
+ for (mp = &x->rn_mklist; (m = *mp) != NULL;)
+ mp = &m->rm_mklist;
+ *mp = t->rn_mklist;
+ } else {
+ /* If there are any key,mask pairs in a sibling
+ duped-key chain, some subset will appear sorted
+ in the same order attached to our mklist */
+ for (m = t->rn_mklist; m && x; x = x->rn_dupedkey)
+ if (m == x->rn_mklist) {
+ struct radix_mask *mm = m->rm_mklist;
+ x->rn_mklist = 0;
+ if (--(m->rm_refs) < 0)
+ MKFree(m);
+ m = mm;
+ }
+#if 0
+ if (m)
+ log(LOG_ERR, "%s %p at %p\n",
+ "rn_delete: Orphaned Mask", m, x);
+#endif
+ }
+ }
+ /*
+ * We may be holding an active internal node in the tree.
+ */
+ x = tt + 1;
+ if (t != x) {
+#ifndef RN_DEBUG
+ *t = *x;
+#else
+ b = t->rn_info;
+ *t = *x;
+ t->rn_info = b;
+#endif
+ t->rn_l->rn_p = t;
+ t->rn_r->rn_p = t;
+ p = x->rn_p;
+ if (p->rn_l == x)
+ p->rn_l = t;
+ else
+ p->rn_r = t;
+ }
+out:
+ tt->rn_flags &= ~RNF_ACTIVE;
+ tt[1].rn_flags &= ~RNF_ACTIVE;
+ return (tt);
+}
+
+int
+rn_walktree(h, f, w)
+ struct radix_node_head *h;
+ int (*f) __P((struct radix_node *, void *));
+ void *w;
+{
+ int error;
+ struct radix_node *base, *next;
+ struct radix_node *rn = h->rnh_treetop;
+ /*
+ * This gets complicated because we may delete the node
+ * while applying the function f to it, so we need to calculate
+ * the successor node in advance.
+ */
+ /* First time through node, go left */
+ while (rn->rn_b >= 0)
+ rn = rn->rn_l;
+ for (;;) {
+ base = rn;
+ /* If at right child go back up, otherwise, go right */
+ while (rn->rn_p->rn_r == rn && (rn->rn_flags & RNF_ROOT) == 0)
+ rn = rn->rn_p;
+ /* Find the next *leaf* since next node might vanish, too */
+ for (rn = rn->rn_p->rn_r; rn->rn_b >= 0;)
+ rn = rn->rn_l;
+ next = rn;
+ /* Process leaves */
+ while ((rn = base) != NULL) {
+ base = rn->rn_dupedkey;
+ if (!(rn->rn_flags & RNF_ROOT)
+ && (error = (*f)(rn, w)))
+ return (error);
+ }
+ rn = next;
+ if (rn->rn_flags & RNF_ROOT)
+ return (0);
+ }
+ /* NOTREACHED */
+}
+
+int
+rn_inithead(head, off)
+ void **head;
+ int off;
+{
+ struct radix_node_head *rnh;
+
+ if (*head)
+ return (1);
+ R_Malloc(rnh, struct radix_node_head *, sizeof (*rnh));
+ if (rnh == 0)
+ return (0);
+ *head = rnh;
+ return rn_inithead0(rnh, off);
+}
+
+int
+rn_inithead0(rnh, off)
+ struct radix_node_head *rnh;
+ int off;
+{
+ struct radix_node *t, *tt, *ttt;
+
+ Bzero(rnh, sizeof (*rnh));
+ t = rn_newpair(rn_zeros, off, rnh->rnh_nodes);
+ ttt = rnh->rnh_nodes + 2;
+ t->rn_r = ttt;
+ t->rn_p = t;
+ tt = t->rn_l;
+ tt->rn_flags = t->rn_flags = RNF_ROOT | RNF_ACTIVE;
+ tt->rn_b = -1 - off;
+ *ttt = *tt;
+ ttt->rn_key = rn_ones;
+ rnh->rnh_addaddr = rn_addroute;
+ rnh->rnh_deladdr = rn_delete;
+ rnh->rnh_matchaddr = rn_match;
+ rnh->rnh_lookup = rn_lookup;
+ rnh->rnh_walktree = rn_walktree;
+ rnh->rnh_treetop = t;
+ return (1);
+}
+
+void
+rn_init()
+{
+ char *cp, *cplim;
+
+ if (max_keylen == 0) {
+#if 0
+ log(LOG_ERR,
+ "rn_init: radix functions require max_keylen be set\n");
+#endif
+ return;
+ }
+ if (rn_zeros == NULL) {
+ R_Malloc(rn_zeros, char *, 3 * max_keylen);
+ }
+ if (rn_zeros == NULL)
+ panic("rn_init");
+ Bzero(rn_zeros, 3 * max_keylen);
+ rn_ones = cp = rn_zeros + max_keylen;
+ addmask_key = cplim = rn_ones + max_keylen;
+ while (cp < cplim)
+ *cp++ = -1;
+ if (rn_inithead((void *)&mask_rnhead, 0) == 0)
+ panic("rn_init 2");
+}
+
+
+static int
+rn_freenode(struct radix_node *n, void *p)
+{
+ struct radix_node_head *rnh = p;
+ struct radix_node *d;
+
+ d = rnh->rnh_deladdr(n->rn_key, NULL, rnh);
+ if (d != NULL) {
+ FreeS(d, max_keylen + 2 * sizeof (*d));
+ }
+ return 0;
+}
+
+
+void
+rn_freehead(rnh)
+ struct radix_node_head *rnh;
+{
+
+ (void)rn_walktree(rnh, rn_freenode, rnh);
+
+ rnh->rnh_addaddr = NULL;
+ rnh->rnh_deladdr = NULL;
+ rnh->rnh_matchaddr = NULL;
+ rnh->rnh_lookup = NULL;
+ rnh->rnh_walktree = NULL;
+
+ Free(rnh);
+}
+
+
+void
+rn_fini()
+{
+ struct radix_mask *m;
+
+ if (rn_zeros != NULL) {
+ FreeS(rn_zeros, 3 * max_keylen);
+ rn_zeros = NULL;
+ }
+
+ if (mask_rnhead != NULL) {
+ rn_freehead(mask_rnhead);
+ mask_rnhead = NULL;
+ }
+
+ while ((m = rn_mkfreelist) != NULL) {
+ rn_mkfreelist = m->rm_mklist;
+ KFREE(m);
+ }
+}
+
+
+#ifdef USE_MAIN
+
+typedef struct myst {
+ addrfamily_t dst;
+ addrfamily_t mask;
+ struct radix_node nodes[2];
+} myst_t;
+
+int
+main(int argc, char *argv[])
+{
+ struct radix_node_head *rnh;
+ struct radix_node *rn;
+ addrfamily_t af, mf;
+ myst_t st1, st2, *stp;
+
+ memset(&st1, 0, sizeof(st1));
+ memset(&st2, 0, sizeof(st2));
+ memset(&af, 0, sizeof(af));
+
+ rn_init();
+
+ rnh = NULL;
+ rn_inithead(&rnh, offsetof(addrfamily_t, adf_addr) << 3);
+
+ st1.dst.adf_len = sizeof(st1);
+ st1.mask.adf_len = sizeof(st1);
+ st1.dst.adf_addr.in4.s_addr = inet_addr("127.0.0.0");
+ st1.mask.adf_addr.in4.s_addr = inet_addr("255.0.0.0");
+ rn = rnh->rnh_addaddr(&st1.dst, &st1.mask, rnh, st1.nodes);
+ printf("add.1 %p\n", rn);
+
+ st2.dst.adf_len = sizeof(st2);
+ st2.mask.adf_len = sizeof(st2);
+ st2.dst.adf_addr.in4.s_addr = inet_addr("127.0.1.0");
+ st2.mask.adf_addr.in4.s_addr = inet_addr("255.255.255.0");
+ rn = rnh->rnh_addaddr(&st2.dst, &st2.mask, rnh, st2.nodes);
+ printf("add.2 %p\n", rn);
+
+ af.adf_len = sizeof(af);
+ af.adf_addr.in4.s_addr = inet_addr("127.0.1.0");
+ rn = rnh->rnh_matchaddr(&af, rnh);
+ if (rn != NULL) {
+ printf("1.lookup = %p key %p mask %p\n", rn, rn->rn_key, rn->rn_mask);
+ stp = rn->rn_key;
+ printf("%s/", inet_ntoa(stp->dst.adf_addr.in4));
+ stp = rn->rn_mask;
+ printf("%s\n", inet_ntoa(stp->dst.adf_addr.in4));
+ }
+
+ mf.adf_len = sizeof(mf);
+ mf.adf_addr.in4.s_addr = inet_addr("255.255.255.0");
+ rn = rnh->rnh_lookup(&af, &mf, rnh);
+ if (rn != NULL) {
+ printf("2.lookup = %p key %p mask %p\n", rn, rn->rn_key, rn->rn_mask);
+ stp = rn->rn_key;
+ printf("%s/", inet_ntoa(stp->dst.adf_addr.in4));
+ stp = rn->rn_mask;
+ printf("%s\n", inet_ntoa(stp->dst.adf_addr.in4));
+ }
+
+ af.adf_len = sizeof(af);
+ af.adf_addr.in4.s_addr = inet_addr("126.0.0.1");
+ rn = rnh->rnh_matchaddr(&af, rnh);
+ if (rn != NULL) {
+ printf("3.lookup = %p key %p mask %p\n", rn, rn->rn_key, rn->rn_mask);
+ stp = rn->rn_key;
+ printf("%s/", inet_ntoa(stp->dst.adf_addr.in4));
+ stp = rn->rn_mask;
+ printf("%s\n", inet_ntoa(stp->dst.adf_addr.in4));
+ }
+
+ return 0;
+}
+
+
+void
+log(int level, char *format, ...)
+{
+ va_list ap;
+
+ va_start(ap, format);
+ vfprintf(stderr, format, ap);
+ va_end(ap);
+}
+#endif
+
+
+#ifndef _KERNEL
+void
+panic(char *str)
+{
+ fputs(str, stderr);
+ abort();
+}
+#endif
diff --git a/contrib/ipfilter/radix_ipf.h b/contrib/ipfilter/radix_ipf.h
new file mode 100644
index 0000000..1dada60
--- /dev/null
+++ b/contrib/ipfilter/radix_ipf.h
@@ -0,0 +1,208 @@
+/* $NetBSD$ */
+
+/*
+ * Copyright (c) 1988, 1989, 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.
+ *
+ * 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.
+ *
+ * @(#)radix.h 8.2 (Berkeley) 10/31/94
+ */
+
+#ifndef _NET_RADIX_H_
+#define _NET_RADIX_H_
+#ifndef _RADIX_H_
+#define _RADIX_H_
+#endif /* _RADIX_H_ */
+
+#ifndef __P
+# ifdef __STDC__
+# define __P(x) x
+# else
+# define __P(x) ()
+# endif
+#endif
+
+#ifdef __sgi
+# define radix_mask ipf_radix_mask
+# define radix_node ipf_radix_node
+# define radix_node_head ipf_radix_node_head
+#endif
+
+/*
+ * Radix search tree node layout.
+ */
+
+struct radix_node {
+ struct radix_mask *rn_mklist; /* list of masks contained in subtree */
+ struct radix_node *rn_p; /* parent */
+ short rn_b; /* bit offset; -1-index(netmask) */
+ char rn_bmask; /* node: mask for bit test*/
+ u_char rn_flags; /* enumerated next */
+#define RNF_NORMAL 1 /* leaf contains normal route */
+#define RNF_ROOT 2 /* leaf is root leaf for tree */
+#define RNF_ACTIVE 4 /* This node is alive (for rtfree) */
+ union {
+ struct { /* leaf only data: */
+ caddr_t rn_Key; /* object of search */
+ caddr_t rn_Mask; /* netmask, if present */
+ struct radix_node *rn_Dupedkey;
+ } rn_leaf;
+ struct { /* node only data: */
+ int rn_Off; /* where to start compare */
+ struct radix_node *rn_L;/* progeny */
+ struct radix_node *rn_R;/* progeny */
+ } rn_node;
+ } rn_u;
+#ifdef RN_DEBUG
+ int rn_info;
+ struct radix_node *rn_twin;
+ struct radix_node *rn_ybro;
+#endif
+};
+
+#define rn_dupedkey rn_u.rn_leaf.rn_Dupedkey
+#define rn_key rn_u.rn_leaf.rn_Key
+#define rn_mask rn_u.rn_leaf.rn_Mask
+#define rn_off rn_u.rn_node.rn_Off
+#define rn_l rn_u.rn_node.rn_L
+#define rn_r rn_u.rn_node.rn_R
+
+/*
+ * Annotations to tree concerning potential routes applying to subtrees.
+ */
+
+struct radix_mask {
+ short rm_b; /* bit offset; -1-index(netmask) */
+ char rm_unused; /* cf. rn_bmask */
+ u_char rm_flags; /* cf. rn_flags */
+ struct radix_mask *rm_mklist; /* more masks to try */
+ union {
+ caddr_t rmu_mask; /* the mask */
+ struct radix_node *rmu_leaf; /* for normal routes */
+ } rm_rmu;
+ int rm_refs; /* # of references to this struct */
+};
+
+#define rm_mask rm_rmu.rmu_mask
+#define rm_leaf rm_rmu.rmu_leaf /* extra field would make 32 bytes */
+
+#define MKGet(m) {\
+ if (rn_mkfreelist) {\
+ m = rn_mkfreelist; \
+ rn_mkfreelist = (m)->rm_mklist; \
+ } else \
+ R_Malloc(m, struct radix_mask *, sizeof (*(m))); }\
+
+#define MKFree(m) { (m)->rm_mklist = rn_mkfreelist; rn_mkfreelist = (m);}
+
+struct radix_node_head {
+ struct radix_node *rnh_treetop;
+ struct radix_node *rnh_leaflist;
+ u_long rnh_hits;
+ u_int rnh_number;
+ u_int rnh_ref;
+ int rnh_addrsize; /* permit, but not require fixed keys */
+ int rnh_pktsize; /* permit, but not require fixed keys */
+ struct radix_node *(*rnh_addaddr) /* add based on sockaddr */
+ __P((void *v, void *mask,
+ struct radix_node_head *head, struct radix_node nodes[]));
+ struct radix_node *(*rnh_addpkt) /* add based on packet hdr */
+ __P((void *v, void *mask,
+ struct radix_node_head *head, struct radix_node nodes[]));
+ struct radix_node *(*rnh_deladdr) /* remove based on sockaddr */
+ __P((void *v, void *mask, struct radix_node_head *head));
+ struct radix_node *(*rnh_delpkt) /* remove based on packet hdr */
+ __P((void *v, void *mask, struct radix_node_head *head));
+ struct radix_node *(*rnh_matchaddr) /* locate based on sockaddr */
+ __P((void *v, struct radix_node_head *head));
+ struct radix_node *(*rnh_lookup) /* locate based on sockaddr */
+ __P((void *v, void *mask, struct radix_node_head *head));
+ struct radix_node *(*rnh_matchpkt) /* locate based on packet hdr */
+ __P((void *v, struct radix_node_head *head));
+ int (*rnh_walktree) /* traverse tree */
+ __P((struct radix_node_head *,
+ int (*)(struct radix_node *, void *), void *));
+ struct radix_node rnh_nodes[3]; /* empty tree for common case */
+};
+
+
+#define Bcmp(a, b, n) bcmp(((caddr_t)(a)), ((caddr_t)(b)), (unsigned)(n))
+#if defined(linux) && defined(_KERNEL)
+# define Bcopy(a, b, n) memmove(((caddr_t)(b)), ((caddr_t)(a)), (unsigned)(n))
+#else
+# define Bcopy(a, b, n) bcopy(((caddr_t)(a)), ((caddr_t)(b)), (unsigned)(n))
+#endif
+#define Bzero(p, n) bzero((caddr_t)(p), (unsigned)(n));
+#define R_Malloc(p, t, n) KMALLOCS(p, t, n)
+#define FreeS(p, z) KFREES(p, z)
+#define Free(p) KFREE(p)
+
+#if (defined(__osf__) || (IRIX >= 60516)) && defined(_KERNEL)
+# define rn_init ipf_rn_init
+# define rn_fini ipf_rn_fini
+# define rn_inithead ipf_rn_inithead
+# define rn_freehead ipf_rn_freehead
+# define rn_inithead0 ipf_rn_inithead0
+# define rn_refines ipf_rn_refines
+# define rn_walktree ipf_rn_walktree
+# define rn_addmask ipf_rn_addmask
+# define rn_addroute ipf_rn_addroute
+# define rn_delete ipf_rn_delete
+# define rn_insert ipf_rn_insert
+# define rn_lookup ipf_rn_lookup
+# define rn_match ipf_rn_match
+# define rn_newpair ipf_rn_newpair
+# define rn_search ipf_rn_search
+# define rn_search_m ipf_rn_search_m
+# define max_keylen ipf_maxkeylen
+# define rn_mkfreelist ipf_rn_mkfreelist
+# define rn_zeros ipf_rn_zeros
+# define rn_ones ipf_rn_ones
+# define rn_satisfies_leaf ipf_rn_satisfies_leaf
+# define rn_lexobetter ipf_rn_lexobetter
+# define rn_new_radix_mask ipf_rn_new_radix_mask
+# define rn_freenode ipf_rn_freenode
+#endif
+
+void rn_init __P((void));
+void rn_fini __P((void));
+int rn_inithead __P((void **, int));
+void rn_freehead __P((struct radix_node_head *));
+int rn_inithead0 __P((struct radix_node_head *, int));
+int rn_refines __P((void *, void *));
+int rn_walktree __P((struct radix_node_head *,
+ int (*)(struct radix_node *, void *), void *));
+struct radix_node
+ *rn_addmask __P((void *, int, int)),
+ *rn_addroute __P((void *, void *, struct radix_node_head *,
+ struct radix_node [2])),
+ *rn_delete __P((void *, void *, struct radix_node_head *)),
+ *rn_insert __P((void *, struct radix_node_head *, int *,
+ struct radix_node [2])),
+ *rn_lookup __P((void *, void *, struct radix_node_head *)),
+ *rn_match __P((void *, struct radix_node_head *)),
+ *rn_newpair __P((void *, int, struct radix_node[2])),
+ *rn_search __P((void *, struct radix_node *)),
+ *rn_search_m __P((void *, struct radix_node *, void *));
+
+#endif /* _NET_RADIX_H_ */
diff --git a/contrib/ipfilter/rules/.cvsignore b/contrib/ipfilter/rules/.cvsignore
new file mode 100644
index 0000000..3e75765
--- /dev/null
+++ b/contrib/ipfilter/rules/.cvsignore
@@ -0,0 +1 @@
+new
diff --git a/contrib/ipfilter/rules/example.1 b/contrib/ipfilter/rules/example.1
index ff93f49..3da9f3c 100644
--- a/contrib/ipfilter/rules/example.1
+++ b/contrib/ipfilter/rules/example.1
@@ -1,3 +1,4 @@
+# $FreeBSD$
#
# block all incoming TCP packets on le0 from host 10.1.1.1 to any destination.
#
diff --git a/contrib/ipfilter/rules/example.10 b/contrib/ipfilter/rules/example.10
index 560d1e6..f7a0b01 100644
--- a/contrib/ipfilter/rules/example.10
+++ b/contrib/ipfilter/rules/example.10
@@ -1,3 +1,4 @@
+# $FreeBSD$
#
# pass ack packets (ie established connection)
#
diff --git a/contrib/ipfilter/rules/example.11 b/contrib/ipfilter/rules/example.11
index c6b4e7f..1cefa9a 100644
--- a/contrib/ipfilter/rules/example.11
+++ b/contrib/ipfilter/rules/example.11
@@ -1,3 +1,4 @@
+# $FreeBSD$
#
# allow any TCP packets from the same subnet as foo is on through to host
# 10.1.1.2 if they are destined for port 6667.
diff --git a/contrib/ipfilter/rules/example.12 b/contrib/ipfilter/rules/example.12
index c0ba1d3..6dbaef5 100644
--- a/contrib/ipfilter/rules/example.12
+++ b/contrib/ipfilter/rules/example.12
@@ -1,3 +1,4 @@
+# $FreeBSD$
#
# get rid of all short IP fragments (too small for valid comparison)
#
diff --git a/contrib/ipfilter/rules/example.13 b/contrib/ipfilter/rules/example.13
index 854f07f..ca74114 100644
--- a/contrib/ipfilter/rules/example.13
+++ b/contrib/ipfilter/rules/example.13
@@ -1,3 +1,4 @@
+# $FreeBSD$
#
# Log all short TCP packets to qe3, with 10.3.3.3 as the intended
# destination for the packet.
diff --git a/contrib/ipfilter/rules/example.2 b/contrib/ipfilter/rules/example.2
index 4f81725..81e7d25 100644
--- a/contrib/ipfilter/rules/example.2
+++ b/contrib/ipfilter/rules/example.2
@@ -1,3 +1,4 @@
+# $FreeBSD$
#
# block all outgoing TCP packets on le0 from any host to port 23 of
# host 10.1.1.2
diff --git a/contrib/ipfilter/rules/example.3 b/contrib/ipfilter/rules/example.3
index cd31f73..c5b4344 100644
--- a/contrib/ipfilter/rules/example.3
+++ b/contrib/ipfilter/rules/example.3
@@ -1,3 +1,4 @@
+# $FreeBSD$
#
# block all inbound packets.
#
diff --git a/contrib/ipfilter/rules/example.4 b/contrib/ipfilter/rules/example.4
index 7918ec2..f18dcdd 100644
--- a/contrib/ipfilter/rules/example.4
+++ b/contrib/ipfilter/rules/example.4
@@ -1,3 +1,4 @@
+# $FreeBSD$
#
# block all ICMP packets.
#
diff --git a/contrib/ipfilter/rules/example.5 b/contrib/ipfilter/rules/example.5
index 6d688b5..959dfb8 100644
--- a/contrib/ipfilter/rules/example.5
+++ b/contrib/ipfilter/rules/example.5
@@ -1,3 +1,4 @@
+# $FreeBSD$
#
# test ruleset
#
diff --git a/contrib/ipfilter/rules/example.6 b/contrib/ipfilter/rules/example.6
index d40f0f3..e9ce23a 100644
--- a/contrib/ipfilter/rules/example.6
+++ b/contrib/ipfilter/rules/example.6
@@ -1,3 +1,4 @@
+# $FreeBSD$
#
# block all TCP packets with only the SYN flag set (this is the first
# packet sent to establish a connection) out of the SYN-ACK pair.
diff --git a/contrib/ipfilter/rules/example.7 b/contrib/ipfilter/rules/example.7
index 062de98..0ddd7f7 100644
--- a/contrib/ipfilter/rules/example.7
+++ b/contrib/ipfilter/rules/example.7
@@ -1,3 +1,4 @@
+# $FreeBSD$
# block all ICMP packets.
#
block in proto icmp all
diff --git a/contrib/ipfilter/rules/example.8 b/contrib/ipfilter/rules/example.8
index baa0258..2276b52 100644
--- a/contrib/ipfilter/rules/example.8
+++ b/contrib/ipfilter/rules/example.8
@@ -1,3 +1,4 @@
+# $FreeBSD$
#
# block all incoming TCP connections but send back a TCP-RST for ones to
# the ident port
diff --git a/contrib/ipfilter/rules/example.9 b/contrib/ipfilter/rules/example.9
index daff203..50bb46a 100644
--- a/contrib/ipfilter/rules/example.9
+++ b/contrib/ipfilter/rules/example.9
@@ -1,3 +1,4 @@
+# $FreeBSD$
#
# drop all packets without IP security options
#
diff --git a/contrib/ipfilter/rules/example.sr b/contrib/ipfilter/rules/example.sr
index c4c1994..46fb6f1 100644
--- a/contrib/ipfilter/rules/example.sr
+++ b/contrib/ipfilter/rules/example.sr
@@ -1,3 +1,4 @@
+# $FreeBSD$
#
# log all inbound packet on le0 which has IP options present
#
diff --git a/contrib/ipfilter/rules/ip_rules b/contrib/ipfilter/rules/ip_rules
new file mode 100644
index 0000000..9850f16
--- /dev/null
+++ b/contrib/ipfilter/rules/ip_rules
@@ -0,0 +1,3 @@
+# Used to generate ../ip_rules.c and ../ip_rules.h
+pass in all
+pass out all
diff --git a/contrib/ipfilter/rules/ipmon.conf b/contrib/ipfilter/rules/ipmon.conf
new file mode 100644
index 0000000..47b0146
--- /dev/null
+++ b/contrib/ipfilter/rules/ipmon.conf
@@ -0,0 +1,24 @@
+#
+#
+#
+#
+match { logtag = 10000 }
+ do { execute "/usr/bin/mail -s 'logtag 10000' root" };
+match { logtag = 2000, every 10 seconds }
+ do { execute "echo 'XXXXXXXX tag 2000 packet XXXXXXXX'" };
+#
+match { protocol = udp, result = block }
+ do { execute "/usr/bin/mail -s 'blocked udp' root"
+};
+#
+match {
+ srcip = 10.1.0.0/16, dstip = 192.168.1.0/24 }
+ do { execute "/usr/bin/mail -s 'from 10.1 to 192.168.1' root"
+};
+#
+match {
+ rule = 12, logtag = 101, direction = in, result = block,
+ protocol = udp, srcip = 10.1.0.0/16, dstip = 192.168.1.0/24 }
+ do { execute "run shell command"
+};
+#
diff --git a/contrib/ipfilter/rules/pool.conf b/contrib/ipfilter/rules/pool.conf
new file mode 100644
index 0000000..285398d
--- /dev/null
+++ b/contrib/ipfilter/rules/pool.conf
@@ -0,0 +1,4 @@
+#
+pool 0 = { !10.0.0.0 - 10.255.255.255, 10.1.0.0 - 10.1.255.255,
+ 10.1.1.0 - 10.1.1.255, !10.1.2.0 - 10.2.2.255,
+ 10.1.2.3 - 10.1.2.3, 10.1.2.15 - 10.1.2.15 };
diff --git a/contrib/ipfilter/samples/.cvsignore b/contrib/ipfilter/samples/.cvsignore
new file mode 100644
index 0000000..4d38251
--- /dev/null
+++ b/contrib/ipfilter/samples/.cvsignore
@@ -0,0 +1,4 @@
+userauth
+proxy
+relay
+trans_relay
diff --git a/contrib/ipfilter/samples/Makefile b/contrib/ipfilter/samples/Makefile
index 1dad079..47ab4a2 100644
--- a/contrib/ipfilter/samples/Makefile
+++ b/contrib/ipfilter/samples/Makefile
@@ -11,14 +11,14 @@ all:
@echo "make sunos5"
sunos5:
- $(CC) -DSOLARIS2=`uname -r | sh -c 'IFS=. read j n x; echo $$n'` \
- -I.. userauth.c -o userauth -lsocket -lnsl
- $(CC) -DSOLARIS2=`uname -r | sh -c 'IFS=. read j n x; echo $$n'` \
- -I.. proxy.c -o proxy -lsocket -lnsl
+ $(CC) -I.. userauth.c -o userauth -lsocket -lnsl
+ $(CC) -I.. proxy.c -o proxy -lsocket -lnsl
+ $(CC) -I.. relay.c -o relay -lsocket -lnsl
freebsd freebsd22 netbsd bsd bsdi sunos4 openbsd:
$(CC) -I.. userauth.c -o userauth
$(CC) -I.. proxy.c -o proxy
+ $(CC) -I.. relay.c -o relay
clean:
- /bin/rm -f userauth proxy
+ /bin/rm -f userauth proxy relay
diff --git a/contrib/ipfilter/samples/ipfilter-pb.gif b/contrib/ipfilter/samples/ipfilter-pb.gif
index afaefa8..f729ab1 100644
--- a/contrib/ipfilter/samples/ipfilter-pb.gif
+++ b/contrib/ipfilter/samples/ipfilter-pb.gif
Binary files differ
diff --git a/contrib/ipfilter/samples/proxy.c b/contrib/ipfilter/samples/proxy.c
index ef9a69c..ccf2ac6 100644
--- a/contrib/ipfilter/samples/proxy.c
+++ b/contrib/ipfilter/samples/proxy.c
@@ -1,3 +1,5 @@
+/* $NetBSD$ */
+
/*
* Sample transparent proxy program.
*
@@ -45,6 +47,7 @@
#include "netinet/ip_state.h"
#include "netinet/ip_proxy.h"
#include "netinet/ip_nat.h"
+#include "netinet/ipl.h"
main(argc, argv)
@@ -52,6 +55,7 @@ int argc;
char *argv[];
{
struct sockaddr_in sin, sloc, sout;
+ ipfobj_t obj;
natlookup_t natlook;
natlookup_t *natlookp = &natlook;
char buffer[512];
@@ -77,21 +81,27 @@ char *argv[];
exit(-1);
}
+ bzero((char *)&obj, sizeof(obj));
+ obj.ipfo_rev = IPFILTER_VERSION;
+ obj.ipfo_size = sizeof(natlook);
+ obj.ipfo_ptr = &natlook;
+ obj.ipfo_type = IPFOBJ_NATLOOKUP;
+
/*
* Build up the NAT natlookup structure.
*/
bzero((char *)&natlook, sizeof(natlook));
natlook.nl_outip = sin.sin_addr;
natlook.nl_inip = sloc.sin_addr;
- natlook.nl_flags = IPN_TCPUDP;
+ natlook.nl_flags = IPN_TCP;
natlook.nl_outport = ntohs(sin.sin_port);
natlook.nl_inport = ntohs(sloc.sin_port);
/*
* Open the NAT device and lookup the mapping pair.
*/
- fd = open(IPL_NAT, O_RDONLY);
- if (ioctl(fd, SIOCGNATL, &natlookp) == -1) {
+ fd = open(IPNAT_NAME, O_RDONLY);
+ if (ioctl(fd, SIOCGNATL, &obj) == -1) {
perror("ioctl(SIOCGNATL)");
exit(-1);
}
@@ -131,6 +141,7 @@ char *extif;
struct sockaddr_in usin;
u_32_t sum1, sum2, sumd;
int onoff, ofd, slen;
+ ipfobj_t obj;
ipnat_t *ipn;
nat_t *nat;
@@ -140,8 +151,12 @@ char *extif;
nat->nat_p = IPPROTO_TCP;
nat->nat_dir = NAT_OUTBOUND;
if ((extif != NULL) && (*extif != '\0')) {
- strncpy(nat->nat_ifname, extif, sizeof(nat->nat_ifname));
- nat->nat_ifname[sizeof(nat->nat_ifname) - 1] = '\0';
+ strncpy(nat->nat_ifnames[0], extif,
+ sizeof(nat->nat_ifnames[0]));
+ strncpy(nat->nat_ifnames[1], extif,
+ sizeof(nat->nat_ifnames[1]));
+ nat->nat_ifnames[0][sizeof(nat->nat_ifnames[0]) - 1] = '\0';
+ nat->nat_ifnames[1][sizeof(nat->nat_ifnames[1]) - 1] = '\0';
}
ofd = socket(AF_INET, SOCK_DGRAM, 0);
@@ -186,9 +201,15 @@ printf("local port# to use: %d\n", ntohs(usin.sin_port));
nat->nat_flags = IPN_TCPUDP;
+ bzero((char *)&obj, sizeof(obj));
+ obj.ipfo_rev = IPFILTER_VERSION;
+ obj.ipfo_size = sizeof(*nsp);
+ obj.ipfo_ptr = nsp;
+ obj.ipfo_type = IPFOBJ_NATSAVE;
+
onoff = 1;
if (ioctl(fd, SIOCSTLCK, &onoff) == 0) {
- if (ioctl(fd, SIOCSTPUT, &nsp) != 0)
+ if (ioctl(fd, SIOCSTPUT, &obj) != 0)
perror("SIOCSTPUT");
onoff = 0;
if (ioctl(fd, SIOCSTLCK, &onoff) != 0)
diff --git a/contrib/ipfilter/samples/relay.c b/contrib/ipfilter/samples/relay.c
new file mode 100644
index 0000000..b91779a
--- /dev/null
+++ b/contrib/ipfilter/samples/relay.c
@@ -0,0 +1,196 @@
+/* $NetBSD$ */
+
+/*
+ * Sample program to be used as a transparent proxy.
+ *
+ * Must be executed with permission enough to do an ioctl on /dev/ipl
+ * or equivalent. This is just a sample and is only alpha quality.
+ * - Darren Reed (8 April 1996)
+ */
+#include <unistd.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/syslog.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <netinet/in.h>
+#include <net/if.h>
+#include "ip_compat.h"
+#include "ip_fil.h"
+#include "ip_nat.h"
+#include "ipl.h"
+
+#define RELAY_BUFSZ 8192
+
+char ibuff[RELAY_BUFSZ];
+char obuff[RELAY_BUFSZ];
+
+int relay(ifd, ofd, rfd)
+int ifd, ofd, rfd;
+{
+ fd_set rfds, wfds;
+ char *irh, *irt, *rrh, *rrt;
+ char *iwh, *iwt, *rwh, *rwt;
+ int nfd, n, rw;
+
+ irh = irt = ibuff;
+ iwh = iwt = obuff;
+ nfd = ifd;
+ if (nfd < ofd)
+ nfd = ofd;
+ if (nfd < rfd)
+ nfd = rfd;
+
+ while (1) {
+ FD_ZERO(&rfds);
+ FD_ZERO(&wfds);
+ if (irh > irt)
+ FD_SET(rfd, &wfds);
+ if (irh < (ibuff + RELAY_BUFSZ))
+ FD_SET(ifd, &rfds);
+ if (iwh > iwt)
+ FD_SET(ofd, &wfds);
+ if (iwh < (obuff + RELAY_BUFSZ))
+ FD_SET(rfd, &rfds);
+
+ switch ((n = select(nfd + 1, &rfds, &wfds, NULL, NULL)))
+ {
+ case -1 :
+ case 0 :
+ return -1;
+ default :
+ if (FD_ISSET(ifd, &rfds)) {
+ rw = read(ifd, irh, ibuff + RELAY_BUFSZ - irh);
+ if (rw == -1)
+ return -1;
+ if (rw == 0)
+ return 0;
+ irh += rw;
+ n--;
+ }
+ if (n && FD_ISSET(ofd, &wfds)) {
+ rw = write(ofd, iwt, iwh - iwt);
+ if (rw == -1)
+ return -1;
+ iwt += rw;
+ n--;
+ }
+ if (n && FD_ISSET(rfd, &rfds)) {
+ rw = read(rfd, iwh, obuff + RELAY_BUFSZ - iwh);
+ if (rw == -1)
+ return -1;
+ if (rw == 0)
+ return 0;
+ iwh += rw;
+ n--;
+ }
+ if (n && FD_ISSET(rfd, &wfds)) {
+ rw = write(rfd, irt, irh - irt);
+ if (rw == -1)
+ return -1;
+ irt += rw;
+ n--;
+ }
+ if (irh == irt)
+ irh = irt = ibuff;
+ if (iwh == iwt)
+ iwh = iwt = obuff;
+ }
+ }
+}
+
+main(argc, argv)
+int argc;
+char *argv[];
+{
+ struct sockaddr_in sin;
+ ipfobj_t obj;
+ natlookup_t nl;
+ natlookup_t *nlp = &nl;
+ int fd, sl = sizeof(sl), se;
+
+ openlog(argv[0], LOG_PID|LOG_NDELAY, LOG_DAEMON);
+ if ((fd = open(IPNAT_NAME, O_RDONLY)) == -1) {
+ se = errno;
+ perror("open");
+ errno = se;
+ syslog(LOG_ERR, "open: %m\n");
+ exit(-1);
+ }
+
+ bzero(&obj, sizeof(obj));
+ obj.ipfo_rev = IPFILTER_VERSION;
+ obj.ipfo_size = sizeof(nl);
+ obj.ipfo_ptr = &nl;
+ obj.ipfo_type = IPFOBJ_NATLOOKUP;
+
+ bzero(&nl, sizeof(nl));
+ nl.nl_flags = IPN_TCP;
+
+ bzero(&sin, sizeof(sin));
+ sin.sin_family = AF_INET;
+ sl = sizeof(sin);
+ if (getsockname(0, (struct sockaddr *)&sin, &sl) == -1) {
+ se = errno;
+ perror("getsockname");
+ errno = se;
+ syslog(LOG_ERR, "getsockname: %m\n");
+ exit(-1);
+ } else {
+ nl.nl_inip.s_addr = sin.sin_addr.s_addr;
+ nl.nl_inport = sin.sin_port;
+ }
+
+ bzero(&sin, sizeof(sin));
+ sin.sin_family = AF_INET;
+ sl = sizeof(sin);
+ if (getpeername(0, (struct sockaddr *)&sin, &sl) == -1) {
+ se = errno;
+ perror("getpeername");
+ errno = se;
+ syslog(LOG_ERR, "getpeername: %m\n");
+ exit(-1);
+ } else {
+ nl.nl_outip.s_addr = sin.sin_addr.s_addr;
+ nl.nl_outport = sin.sin_port;
+ }
+
+ if (ioctl(fd, SIOCGNATL, &obj) == -1) {
+ se = errno;
+ perror("ioctl");
+ errno = se;
+ syslog(LOG_ERR, "ioctl: %m\n");
+ exit(-1);
+ }
+
+ sin.sin_port = nl.nl_realport;
+ sin.sin_addr = nl.nl_realip;
+ sl = sizeof(sin);
+
+ fd = socket(AF_INET, SOCK_STREAM, 0);
+ if (connect(fd, (struct sockaddr *)&sin, sl) == -1) {
+ se = errno;
+ perror("connect");
+ errno = se;
+ syslog(LOG_ERR, "connect: %m\n");
+ exit(-1);
+ }
+
+ (void) ioctl(fd, F_SETFL, ioctl(fd, F_GETFL, 0)|O_NONBLOCK);
+ (void) ioctl(0, F_SETFL, ioctl(fd, F_GETFL, 0)|O_NONBLOCK);
+ (void) ioctl(1, F_SETFL, ioctl(fd, F_GETFL, 0)|O_NONBLOCK);
+
+ syslog(LOG_NOTICE, "connected to %s,%d\n", inet_ntoa(sin.sin_addr),
+ ntohs(sin.sin_port));
+ if (relay(0, 1, fd) == -1) {
+ se = errno;
+ perror("relay");
+ errno = se;
+ syslog(LOG_ERR, "relay: %m\n");
+ exit(-1);
+ }
+ exit(0);
+}
diff --git a/contrib/ipfilter/samples/userauth.c b/contrib/ipfilter/samples/userauth.c
index 5b50a94..ef059ac 100644
--- a/contrib/ipfilter/samples/userauth.c
+++ b/contrib/ipfilter/samples/userauth.c
@@ -1,3 +1,5 @@
+/* $NetBSD$ */
+
#include <sys/types.h>
#include <sys/socket.h>
#include <fcntl.h>
@@ -21,7 +23,9 @@ main()
char yn[16];
int fd;
- fd = open(IPL_AUTH, O_RDWR);
+ fd = open(IPL_NAME, O_RDWR);
+ fra.fra_len = 0;
+ fra.fra_buf = NULL;
while (ioctl(fd, SIOCAUTHW, &frap) == 0) {
if (fra.fra_info.fin_out)
fra.fra_pass = FR_OUTQUE;
@@ -29,10 +33,10 @@ main()
fra.fra_pass = FR_INQUE;
printf("%s ", inet_ntoa(fi->fi_src));
- if (fi->fi_fl & FI_TCPUDP)
+ if (fi->fi_flx & FI_TCPUDP)
printf("port %d ", fin->fin_data[0]);
printf("-> %s ", inet_ntoa(fi->fi_dst));
- if (fi->fi_fl & FI_TCPUDP)
+ if (fi->fi_flx & FI_TCPUDP)
printf("port %d ", fin->fin_data[1]);
printf("\n");
printf("Allow packet through ? [y/n]");
@@ -44,7 +48,7 @@ main()
fra.fra_pass |= FR_BLOCK;
else if (yn[0] == 'y' || yn[0] == 'Y') {
fra.fra_pass |= FR_PASS;
- if (fra.fra_info.fin_fi.fi_fl & FI_TCPUDP)
+ if (fra.fra_info.fin_fi.fi_flx & FI_TCPUDP)
fra.fra_pass |= FR_KEEPSTATE;
} else
fra.fra_pass |= FR_NOMATCH;
diff --git a/contrib/ipfilter/snoop.h b/contrib/ipfilter/snoop.h
index 2f6c305..12dea37 100644
--- a/contrib/ipfilter/snoop.h
+++ b/contrib/ipfilter/snoop.h
@@ -1,3 +1,5 @@
+/* $NetBSD$ */
+
/*
* Copyright (C) 1993-2001 by Darren Reed.
*
@@ -9,7 +11,7 @@
/*
* written to comply with the RFC (1761) from Sun.
- * $Id: snoop.h,v 2.2.2.1 2001/06/26 10:43:20 darrenr Exp $
+ * Id: snoop.h,v 2.3 2001/06/09 17:09:23 darrenr Exp
*/
struct snoophdr {
char s_id[8];
diff --git a/contrib/ipfilter/test/.cvsignore b/contrib/ipfilter/test/.cvsignore
new file mode 100644
index 0000000..5825abc
--- /dev/null
+++ b/contrib/ipfilter/test/.cvsignore
@@ -0,0 +1,87 @@
+results
+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+i1
+i2
+i3
+i4
+i5
+i6
+i7
+i8
+i9
+i10
+i11
+f1
+f2
+f3
+f4
+f5
+f6
+f7
+f8
+f9
+f10
+f11
+f12
+f13
+f14
+n1
+n2
+n3
+n4
+n5
+n6
+n7
+f15
+f16
+ipv6.1
+ipv6.2
+l1
+ni1
+ni2
+ni3
+ni4
+f17
+in1
+in2
+in3
+in4
+p1
+p2
+i12
+ip1
+p3
+i13
+ni5
+ni6
+i14
+in5
+ipv6.3
+n8
+n9
+n10
+n11
+ni7
+ni8
+ni9
+ni10
+ni11
+ni12
+n12
+in6
+i15
+ni13
+ni14
+ni15
+ni16
diff --git a/contrib/ipfilter/test/Makefile b/contrib/ipfilter/test/Makefile
index a7a6c29..7f17241 100644
--- a/contrib/ipfilter/test/Makefile
+++ b/contrib/ipfilter/test/Makefile
@@ -1,15 +1,21 @@
#
# (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.
+# See the IPFILTER.LICENCE file for details on licencing.
#
BINDEST=/usr/local/bin
SBINDEST=/sbin
MANDIR=/usr/share/man
+all: results tests
-tests: first 0 ftests ptests ntests nitests logtests ipv6 intests
+results:
+ mkdir -p results
+
+tests: ipf nat logtests ipv6 pools
+
+ipf: ftests ptests
+
+nat: ntests nitests intests
first:
-mkdir -p results
@@ -18,57 +24,70 @@ first:
ftests: f1 f2 f3 f4 f5 f6 f7 f8 f9 f10 f11 f12 f13 f14 f15 f16 f17
# Rule parsing tests
-ptests: i1 i2 i3 i4 i5 i6 i7 i8 i9 i10 i11 i12
+ptests: i1 i2 i3 i4 i5 i6 i7 i8 i9 i10 i11 i12 i13 i14 i15
-ntests: n1 n2 n3 n4 n5 n6 n7
+ntests: n1 n2 n3 n4 n5 n6 n7 n8 n9 n10 n11 n12
-nitests: ni1 ni2 ni3 ni4 ni5
+nitests: ni1 ni2 ni3 ni4 ni5 ni6 ni7 ni8 ni9 ni10 ni11 ni12 ni13 ni14 ni15 ni16
-intests: in1 in2 in3 in4
+intests: in1 in2 in3 in4 in5 in6
logtests: l1
-ipv6: ipv6.1 ipv6.2 ipv6.3
+pools: p1 p2 p3 ip1
-0:
- @(cd ..; make ipftest; )
+ipv6: ipv6.1 ipv6.2 ipv6.3
-f1 f2 f3 f4 f5 f6 f7 f8 f9 f10 f11 f14:
- @/bin/sh ./dotest $@
+bpf: bpf1 bpf-f1
-f12 f13:
- @/bin/sh ./hextest $@
+f1 f2 f3 f4 f5 f6 f7 f8 f9 f10 f11 f12 f13 f14:
+ @/bin/sh ./dotest `awk "/^$@ / { print; } " test.format`
-f15 f16:
- @/bin/sh ./mtest $@
+f15 f16 f17:
+ @/bin/sh ./mtest `awk "/^$@ / { print; } " test.format`
-f17:
- @/bin/sh ./mhtest $@
+i1 i2 i3 i4 i5 i6 i7 i8 i9 i10 i11 i12 i13 i14 i15 bpf1:
+ @/bin/sh ./itest `awk "/^$@ / { print; } " test.format`
-i1 i2 i3 i4 i5 i6 i7 i8 i9 i10 i11 i12:
- @/bin/sh ./itest $@
+n1 n2 n3 n4 n5 n6 n7 n8 n9 n10 n11 n12:
+ @/bin/sh ./nattest `awk "/^$@ / { print; } " test.format`
-n1 n2 n3 n4 n5 n6 n7:
- @/bin/sh ./nattest $@
+ni1 ni2 ni3 ni4 ni5 ni7 ni8 ni9 ni10 ni11 ni12 ni13 ni14 ni15 ni16:
+ @/bin/sh ./natipftest single `awk "/^$@ / { print; } " test.format`
-ni1 ni2 ni3 ni4 ni5 ni7 ni8 ni10 ni11:
- @/bin/sh ./natipftest $@
+ni6:
+ @/bin/sh ./natipftest multi `awk "/^$@ / { print; } " test.format`
-in1 in2 in3 in4:
- @/bin/sh ./intest $@
+in1 in2 in3 in4 in5 in6:
+ @/bin/sh ./intest `awk "/^$@ / { print; } " test.format`
l1:
- @/bin/sh ./logtest $@
+ @/bin/sh ./logtest `awk "/^$@ / { print; } " test.format`
ipv6.1 ipv6.2 ipv6.3:
- @/bin/sh ./dotest6 $@
+ @/bin/sh ./dotest6 `awk "/^$@ / { print; } " test.format`
+
+p1 p2 p3:
+ @/bin/sh ./ptest `awk "/^$@ / { print; } " test.format`
+
+ip1:
+ @/bin/sh ./iptest `awk "/^$@ / { print; } " test.format`
+
+bpf-f1:
+ /bin/sh ./bpftest `awk "/^$@ / { print; } " test.format`
clean:
- /bin/rm -f f1 f2 f3 f4 f5 f6 f7 f8 f9 f10 f11 f13 f12 f14 f15 f16 f17
- /bin/rm -f i1 i2 i3 i4 i5 i6 i7 i8 i9 i10 i11 i12
- /bin/rm -f n1 n2 n3 n4 n5 n6 n7
- /bin/rm -f ni1 ni2 ni3 ni4 ni5
- /bin/rm -f in1 in2 in3 in4
+ /bin/rm -f f1 f2 f3 f4 f5 f6 f7 f8 f9 f10 f11 f12 f13 f14 f15 f16 f17
+ /bin/rm -f i1 i2 i3 i4 i5 i6 i7 i8 i9 i10 i11 i12 i13 i14 i15
+ /bin/rm -f n1 n2 n3 n4 n5 n6 n7 n8 n9 n10 n11 n12
+ /bin/rm -f ni1 ni2 ni3 ni4 ni5 ni6 ni7 ni8 ni9
+ /bin/rm -f ni10 ni11 ni12 ni13 ni14 ni15 ni16
+ /bin/rm -f in1 in2 in3 in4 in5 in6
+ /bin/rm -f p1 p2 p3 ip1
/bin/rm -f l1
/bin/rm -f ipv6.1 ipv6.2 ipv6.3
- /bin/rm -f results/*
+ /bin/rm -f bpf1 bpf-f1
+ /bin/rm -f results/* logout
+
+diffs:
+ -cd expected; for i in *; do if [ -f $$i -a ! -f ../$$i -a -f ../results/$$i ] ; then diff -c $$i ../results/$$i >> ../diff.out; fi done
diff --git a/contrib/ipfilter/test/bpftest b/contrib/ipfilter/test/bpftest
new file mode 100644
index 0000000..b24c0f1
--- /dev/null
+++ b/contrib/ipfilter/test/bpftest
@@ -0,0 +1,28 @@
+#!/bin/sh
+if [ -f /usr/ucb/touch ] ; then
+ TOUCH=/usr/ucb/touch
+else
+ if [ -f /usr/bin/touch ] ; then
+ TOUCH=/usr/bin/touch
+ else
+ if [ -f /bin/touch ] ; then
+ TOUCH=/bin/touch
+ fi
+ fi
+fi
+echo "$1...";
+input=`expr $1 : 'bpf-\(.*\)'`
+/bin/cp /dev/null results/$1
+( while read rule; do
+ echo "$rule" | ../ipftest -Rbr - -i input/$input >> results/$1;
+ if [ $? -ne 0 ] ; then
+ exit 1;
+ fi
+ echo "--------" >> results/$1
+done ) < regress/$1
+cmp expected/$1 results/$1
+status=$?
+if [ $status = 0 ] ; then
+ $TOUCH $1
+fi
+exit $status
diff --git a/contrib/ipfilter/test/dotest b/contrib/ipfilter/test/dotest
index 5a11605..71c8cce 100644
--- a/contrib/ipfilter/test/dotest
+++ b/contrib/ipfilter/test/dotest
@@ -1,4 +1,5 @@
#!/bin/sh
+format=$2
if [ -f /usr/ucb/touch ] ; then
TOUCH=/usr/ucb/touch
else
@@ -13,7 +14,7 @@ fi
echo "$1...";
/bin/cp /dev/null results/$1
( while read rule; do
- echo "$rule" | ../ipftest -br - -i input/$1 >> results/$1;
+ echo "$rule" | ../ipftest -F $format -Rbr - -i input/$1 >> results/$1;
if [ $? -ne 0 ] ; then
exit 1;
fi
diff --git a/contrib/ipfilter/test/dotest6 b/contrib/ipfilter/test/dotest6
index 297de6f..d6db564 100755
--- a/contrib/ipfilter/test/dotest6
+++ b/contrib/ipfilter/test/dotest6
@@ -1,4 +1,6 @@
#!/bin/sh
+format=$2
+mkdir -p results
if [ -f /usr/ucb/touch ] ; then
TOUCH=/usr/ucb/touch
else
@@ -19,7 +21,7 @@ if [ $? -ne 0 ] ; then
exit 0
fi
( while read rule; do
- echo "$rule" | ../ipftest -6Hbr - -i input/$1 >> results/$1;
+ echo "$rule" | ../ipftest -F $format -6br - -i input/$1 >> results/$1;
if [ $? -ne 0 ] ; then
exit 1;
fi
diff --git a/contrib/ipfilter/test/expected/bpf-f1 b/contrib/ipfilter/test/expected/bpf-f1
new file mode 100644
index 0000000..85ce84c
--- /dev/null
+++ b/contrib/ipfilter/test/expected/bpf-f1
@@ -0,0 +1,20 @@
+nomatch
+pass
+nomatch
+nomatch
+--------
+nomatch
+nomatch
+nomatch
+pass
+--------
+nomatch
+nomatch
+nomatch
+nomatch
+--------
+nomatch
+nomatch
+nomatch
+nomatch
+--------
diff --git a/contrib/ipfilter/test/expected/bpf1 b/contrib/ipfilter/test/expected/bpf1
new file mode 100644
index 0000000..9d0ad1b
--- /dev/null
+++ b/contrib/ipfilter/test/expected/bpf1
@@ -0,0 +1,4 @@
+pass in bpf { "0x20 0 0 0xc 0x15 0 0x1 0x1010101 0x6 0 0 0x60 0x6 0 0 0" }
+pass out bpf { "0x20 0 0 0xc 0x15 0 0x1 0x1010101 0x6 0 0 0x60 0x6 0 0 0" }
+pass in bpf { "0x20 0 0 0x10 0x15 0 0x1 0x1010101 0x6 0 0 0x60 0x6 0 0 0" }
+pass out bpf { "0x20 0 0 0x10 0x15 0 0x1 0x1010101 0x6 0 0 0x60 0x6 0 0 0" }
diff --git a/contrib/ipfilter/test/expected/f17 b/contrib/ipfilter/test/expected/f17
index 99eee84..4fe3acf 100644
--- a/contrib/ipfilter/test/expected/f17
+++ b/contrib/ipfilter/test/expected/f17
@@ -3,8 +3,4 @@ block return-rst
pass
pass
pass
-pass
-pass
-pass
-pass
--------
diff --git a/contrib/ipfilter/test/expected/i1 b/contrib/ipfilter/test/expected/i1
index 3eb14be..93530f9 100644
--- a/contrib/ipfilter/test/expected/i1
+++ b/contrib/ipfilter/test/expected/i1
@@ -1,7 +1,7 @@
-pass in from any to any
-block out from any to any
-log in from any to any
-log body in from any to any
+pass in all
+block out all
+log in all
+log body in all
count in from any to any
pass in from !any to any
block in from any to !any
@@ -11,3 +11,5 @@ pass in log body quick from any to any
block return-rst in quick on le0(!) proto tcp from any to any
block return-icmp in on qe0(!) from any to any
block return-icmp(host-unr) in on qe0(!) from any to any
+block return-icmp-as-dest(port-unr) in on qe0(!) from any to any
+pass out on longNICname0(!) from 254.220.186.152/32 to 254.220.186.152/32
diff --git a/contrib/ipfilter/test/expected/i11 b/contrib/ipfilter/test/expected/i11
index ddf8000..058d03a 100644
--- a/contrib/ipfilter/test/expected/i11
+++ b/contrib/ipfilter/test/expected/i11
@@ -1,5 +1,8 @@
pass in on ed0(!) proto tcp from 127.0.0.1/32 to 127.0.0.1/32 port = 23 keep state
block in log first on lo0(!) proto tcp/udp from any to any keep state
-pass in proto udp from 127.0.0.1/32 to 127.0.0.1/32 port = 2049 keep frags
+pass in proto udp from 127.0.0.1/32 to 127.0.0.1/32 port = 20499 keep frags
pass in proto udp from 127.0.0.1/32 to 127.0.0.1/32 port = 53 keep state keep frags
-pass in proto tcp from any port > 1024 to 127.0.0.1/32 port = 25 keep state
+pass in on ed0(!) out-via vx0(!) proto udp from any to any keep state
+pass out on ppp0(!) in-via le0(!) proto tcp from any to any keep state
+pass in proto tcp from any port > 1024 to 127.0.0.1/32 port = 1024 keep state
+pass in proto tcp from any to any flags S/FSRPAU keep state (limit 101,strict,newisn,no-icmp-err)
diff --git a/contrib/ipfilter/test/expected/i12 b/contrib/ipfilter/test/expected/i12
index 2a904a3..22a3488 100644
--- a/contrib/ipfilter/test/expected/i12
+++ b/contrib/ipfilter/test/expected/i12
@@ -1,4 +1,34 @@
-block in on eri0(!) from any to any head 1
-pass in on eri0(!) proto icmp from any to any group 1
-pass out on ed0(!) from any to any head 1000000
-block out on ed0(!) proto udp from any to any group 1000000
+pass in from 1.1.1.1/32 to 2.2.2.2/32
+pass in from 2.2.2.0/24 to 4.4.4.4/32
+pass in from 3.3.3.3/32 to 4.4.4.4/32
+pass in from 2.2.2.0/24 to 5.5.5.5/32
+pass in from 3.3.3.3/32 to 5.5.5.5/32
+pass in from 2.2.2.0/24 to 6.6.6.6/32
+pass in from 3.3.3.3/32 to 6.6.6.6/32
+pass in from 2.2.2.0/24 to 5.5.5.5/32 port = 22
+pass in from 3.3.3.3/32 to 5.5.5.5/32 port = 22
+pass in from 2.2.2.0/24 to 6.6.6.6/32 port = 22
+pass in from 3.3.3.3/32 to 6.6.6.6/32 port = 22
+pass in from 2.2.2.0/24 to 5.5.5.5/32 port = 25
+pass in from 3.3.3.3/32 to 5.5.5.5/32 port = 25
+pass in from 2.2.2.0/24 to 6.6.6.6/32 port = 25
+pass in from 3.3.3.3/32 to 6.6.6.6/32 port = 25
+pass in proto tcp from 2.2.2.0/24 to 5.5.5.5/32 port = 53
+pass in proto tcp from 3.3.3.3/32 to 5.5.5.5/32 port = 53
+pass in proto tcp from 2.2.2.0/24 to 6.6.6.6/32 port = 53
+pass in proto tcp from 3.3.3.3/32 to 6.6.6.6/32 port = 53
+pass in proto tcp from 2.2.2.0/24 to 5.5.5.5/32 port = 9
+pass in proto tcp from 3.3.3.3/32 to 5.5.5.5/32 port = 9
+pass in proto tcp from 2.2.2.0/24 to 6.6.6.6/32 port = 9
+pass in proto tcp from 3.3.3.3/32 to 6.6.6.6/32 port = 9
+pass in proto udp from 2.2.2.0/24 to 5.5.5.5/32 port = 53
+pass in proto udp from 3.3.3.3/32 to 5.5.5.5/32 port = 53
+pass in proto udp from 2.2.2.0/24 to 6.6.6.6/32 port = 53
+pass in proto udp from 3.3.3.3/32 to 6.6.6.6/32 port = 53
+pass in proto udp from 2.2.2.0/24 to 5.5.5.5/32 port = 9
+pass in proto udp from 3.3.3.3/32 to 5.5.5.5/32 port = 9
+pass in proto udp from 2.2.2.0/24 to 6.6.6.6/32 port = 9
+pass in proto udp from 3.3.3.3/32 to 6.6.6.6/32 port = 9
+pass in from 10.10.10.10/32 to 11.11.11.11/32
+pass in from pool/101(!) to hash/202(!)
+pass in from hash/303(!) to pool/404(!)
diff --git a/contrib/ipfilter/test/expected/i13 b/contrib/ipfilter/test/expected/i13
new file mode 100644
index 0000000..5c8d945
--- /dev/null
+++ b/contrib/ipfilter/test/expected/i13
@@ -0,0 +1,2 @@
+block in from any to any
+pass in from any to any
diff --git a/contrib/ipfilter/test/expected/i14 b/contrib/ipfilter/test/expected/i14
new file mode 100644
index 0000000..5a10155
--- /dev/null
+++ b/contrib/ipfilter/test/expected/i14
@@ -0,0 +1,8 @@
+block in on eri0(!) all head 1
+pass in on eri0(!) proto icmp from any to any group 1
+pass out on ed0(!) all head 1000000
+block out on ed0(!) proto udp from any to any group 1000000
+block in on vm0(!) proto tcp/udp from any to any head 101
+pass in proto tcp/udp from 1.1.1.1/32 to 2.2.2.2/32 group 101
+pass in proto tcp from 1.0.0.1/32 to 2.0.0.2/32 group 101
+pass in proto udp from 2.0.0.2/32 to 3.0.0.3/32 group 101
diff --git a/contrib/ipfilter/test/expected/i15 b/contrib/ipfilter/test/expected/i15
new file mode 100644
index 0000000..4974659
--- /dev/null
+++ b/contrib/ipfilter/test/expected/i15
@@ -0,0 +1,4 @@
+pass out on fxp0(!) all set-tag(log=100)
+pass out on fxp0(!) all set-tag(nat=foo)
+pass out on fxp0(!) all set-tag(log=100, nat=200)
+pass out on fxp0(!) all set-tag(log=2147483648, nat=overtherainbowis)
diff --git a/contrib/ipfilter/test/expected/i2 b/contrib/ipfilter/test/expected/i2
index 9d3398d..37ec9c4 100644
--- a/contrib/ipfilter/test/expected/i2
+++ b/contrib/ipfilter/test/expected/i2
@@ -1,6 +1,7 @@
log in proto tcp from any to any
pass in proto tcp from any to any
pass in proto udp from 127.0.0.1/32 to 127.0.0.1/32
+block in proto ipv6 from any to any
block in proto udp from any to any
block in proto 250 from any to any
pass in proto tcp/udp from any to any
diff --git a/contrib/ipfilter/test/expected/i3 b/contrib/ipfilter/test/expected/i3
index 18d9161..6150c7e 100644
--- a/contrib/ipfilter/test/expected/i3
+++ b/contrib/ipfilter/test/expected/i3
@@ -1,4 +1,5 @@
-log in from any to any
+log in all
+pass in from 128.16.0.0/16 to 129.10.10.0/24
pass in from 128.0.0.0/24 to 128.0.0.0/16
pass in from 128.0.0.0/24 to 128.0.0.0/16
pass in from 128.0.0.0/24 to 128.0.0.0/16
@@ -6,5 +7,5 @@ pass in from 128.0.0.0/24 to 128.0.0.0/16
pass in from 128.0.0.0/24 to 128.0.0.0/16
pass in from 127.0.0.1/32 to 127.0.0.1/32
block in log from any to any
-block in log level auth.info on hme0(!) from any to any
-log level local5.warn out from any to any
+block in log level auth.info on hme0(!) all
+log level local5.warn out all
diff --git a/contrib/ipfilter/test/expected/i4 b/contrib/ipfilter/test/expected/i4
index dfa3674..89c0995 100644
--- a/contrib/ipfilter/test/expected/i4
+++ b/contrib/ipfilter/test/expected/i4
@@ -2,6 +2,7 @@ log in proto tcp from any port > 0 to any
log in proto tcp from any to any port > 0
pass in proto tcp from any port != 0 to any port 0 >< 65535
pass in proto udp from 127.0.0.1/32 port > 32000 to 127.0.0.1/32 port < 29000
-block in proto udp from any port != 123 to any port < 123
+block in proto udp from any port != 123 to any port < 7
block in proto tcp from any port = 25 to any port > 25
pass in proto tcp/udp from any port 1 >< 3 to any port 1 <> 3
+pass in log first quick proto tcp from any port > 1023 to any port = 1723 flags S/FSRPAU keep state
diff --git a/contrib/ipfilter/test/expected/i5 b/contrib/ipfilter/test/expected/i5
index 3bcb10b..6947ad3 100644
--- a/contrib/ipfilter/test/expected/i5
+++ b/contrib/ipfilter/test/expected/i5
@@ -1,4 +1,4 @@
-log in from any to any
+log in all
count in tos 0x80 from any to any
pass in on ed0(!) tos 0x40 from 127.0.0.1/32 to 127.0.0.1/32
block in log on lo0(!) ttl 0 from any to any
diff --git a/contrib/ipfilter/test/expected/i6 b/contrib/ipfilter/test/expected/i6
index 4849626..40fe185 100644
--- a/contrib/ipfilter/test/expected/i6
+++ b/contrib/ipfilter/test/expected/i6
@@ -1,4 +1,10 @@
pass in on lo0(!) fastroute from any to any
+pass in on lo0(!) to qe0(!) from 127.0.0.1/32 to 127.0.0.1/32
+pass in on le0(!) to qe0(!):127.0.0.1 from 127.0.0.1/32 to 127.0.0.1/32
pass in on lo0(!) dup-to qe0(!) from 127.0.0.1/32 to 127.0.0.1/32
-pass in on qe0(!) dup-to qe0(!):127.0.0.1 from 127.0.0.1/32 to 127.0.0.1/32
+pass in on le0(!) dup-to qe0(!):127.0.0.1 from 127.0.0.1/32 to 127.0.0.1/32
+pass in on le0(!) dup-to qe0(!):127.0.0.1 to hme0(!):10.1.1.1 from 127.0.0.1/32 to 127.0.0.1/32
block in quick on qe0(!) to qe1(!) from any to any
+block in quick to qe1(!) from any to any
+pass out quick dup-to hme0(!) from any to any
+pass in quick fastroute all
diff --git a/contrib/ipfilter/test/expected/i7 b/contrib/ipfilter/test/expected/i7
index db9cd01..c46364b 100644
--- a/contrib/ipfilter/test/expected/i7
+++ b/contrib/ipfilter/test/expected/i7
@@ -1,4 +1,4 @@
pass in on ed0(!) proto tcp from 127.0.0.1/32 to 127.0.0.1/32 port = 23 flags S/SA
-block in on lo0(!) proto tcp from any to any flags A/FSRPAUC
+block in on lo0(!) proto tcp from any to any flags A/FSRPAU
pass in on lo0(!) proto tcp from any to any flags /SPA
block in on lo0(!) proto tcp from any to any flags C/A
diff --git a/contrib/ipfilter/test/expected/i9 b/contrib/ipfilter/test/expected/i9
index b36d864..bae7c9b 100644
--- a/contrib/ipfilter/test/expected/i9
+++ b/contrib/ipfilter/test/expected/i9
@@ -1,5 +1,7 @@
-pass in from 127.0.0.1/32 to 127.0.0.1/32 with short
-block in from any to any with ipopt
+pass in from 127.0.0.1/32 to 127.0.0.1/32 with short,frag
+block in from any to any with ipopts
pass in from any to any with opt nop,rr,zsu
pass in from any to any with opt nop,rr,zsu not opt lsrr,ssrr
pass in from 127.0.0.1/32 to 127.0.0.1/32 with not frag
+pass in proto tcp from any to any flags S/FSRPAU with not oow keep state
+pass in proto tcp from any to any flags S/FSRPAU with not bad,bad-src,bad-nat
diff --git a/contrib/ipfilter/test/expected/in1 b/contrib/ipfilter/test/expected/in1
index c507db7..ce5a610 100644
--- a/contrib/ipfilter/test/expected/in1
+++ b/contrib/ipfilter/test/expected/in1
@@ -10,16 +10,18 @@ map ppp0 192.168.0.0/16 -> 0.0.0.0/32 portmap tcp/udp 30000:39999
map ppp0 192.168.0.0/16 -> 0.0.0.0/32 portmap tcp auto
map ppp0 192.168.0.0/16 -> 0.0.0.0/32 portmap udp auto
map ppp0 192.168.0.0/16 -> 0.0.0.0/32 portmap tcp/udp auto
-map ppp0 192.168.0.0/16 -> 0.0.0.0/32 proxy port ftp ftp/tcp
+map ppp0 192.168.0.0/16 -> 0.0.0.0/32 proxy port 21 ftp/tcp
map ppp0 192.168.0.0/16 -> 0.0.0.0/32 proxy port 1010 ftp/tcp
map le0 0.0.0.0/0 -> 0.0.0.0/32 frag
map le0 192.168.0.0/16 -> range 203.1.1.23-203.1.3.45 frag
map ppp0 192.168.0.0/16 -> 0.0.0.0/32 portmap tcp 10000:19999 frag
-map ppp0 192.168.0.0/16 -> 0.0.0.0/32 proxy port ftp ftp/tcp frag
+map ppp0 192.168.0.0/16 -> 0.0.0.0/32 proxy port 21 ftp/tcp frag
map le0 0.0.0.0/0 -> 0.0.0.0/32 age 10/10
map le0 192.168.0.0/16 -> range 203.1.1.23-203.1.3.45 age 10/20
map ppp0 192.168.0.0/16 -> 0.0.0.0/32 portmap tcp 10000:19999 age 30/30
map le0 0.0.0.0/0 -> 0.0.0.0/32 frag age 10/10
map le0 192.168.0.0/16 -> range 203.1.1.23-203.1.3.45 frag age 10/20
map ppp0 192.168.0.0/16 -> 0.0.0.0/32 portmap tcp 10000:19999 frag age 30/30
-map fxp0 from 192.168.0.0/18 to any port = ftp -> 1.2.3.4/32 proxy port ftp ftp/tcp
+map fxp0 from 192.168.0.0/18 to any port = 21 -> 1.2.3.4/32 proxy port 21 ftp/tcp
+map thisisalonginte 0.0.0.0/0 -> 0.0.0.0/32 mssclamp 1452 tag freddyliveshere
+map bar0 0.0.0.0/0 -> 0.0.0.0/32 icmpidmap icmp 1000:2000
diff --git a/contrib/ipfilter/test/expected/in2 b/contrib/ipfilter/test/expected/in2
index ebe747b..61c0d18 100644
--- a/contrib/ipfilter/test/expected/in2
+++ b/contrib/ipfilter/test/expected/in2
@@ -1,22 +1,67 @@
-rdr le0 0.0.0.0/0 port 0 -> 1.1.1.1 port 0 tcp
-rdr le0 0.0.0.0/0 port 0 -> 1.1.1.1 port 0 ip
-rdr le0 0.0.0.0/0 port 80 -> 1.1.1.1 port 80 tcp
-rdr le0 0.0.0.0/0 port 0 -> 1.1.1.1 port 0 ip
-rdr le0 0.0.0.0/0 port 80 -> 1.1.1.1 port 80 tcp
-rdr le0 0.0.0.0/0 port 80 -> 1.1.1.1 port 80 udp
-rdr le0 0.0.0.0/0 port 80 -> 1.1.1.1 port 80 tcp/udp
-rdr le0 0.0.0.0/0 port 0 -> 1.1.1.1 port 0 icmp
-rdr le0 0.0.0.0/0 port 80 -> 1.1.1.1,1.1.1.2 port 80 tcp
-rdr le0 0.0.0.0/0 port 80 -> 1.1.1.1 port 80 tcp round-robin
-rdr le0 0.0.0.0/0 port 80 -> 1.1.1.1,1.1.1.2 port 80 tcp round-robin
-rdr le0 0.0.0.0/0 port 0 -> 1.1.1.1 port 0 ip frag
-rdr le0 0.0.0.0/0 port 0 -> 1.1.1.1 port 0 icmp frag
-rdr le0 0.0.0.0/0 port 80 -> 1.1.1.1,1.1.1.2 port 80 tcp frag
-rdr le0 0.0.0.0/0 port 80 -> 1.1.1.1 port 80 tcp round-robin frag
-rdr le0 0.0.0.0/0 port 80 -> 1.1.1.1,1.1.1.2 port 80 tcp round-robin frag
-rdr le0 0.0.0.0/0 port 0 -> 1.1.1.1 port 0 ip frag age 10/10
-rdr le0 0.0.0.0/0 port 0 -> 1.1.1.1 port 0 ip frag age 10/20
-rdr le0 0.0.0.0/0 port 0 -> 1.1.1.1 port 0 icmp frag age 10/10
-rdr le0 0.0.0.0/0 port 80 -> 1.1.1.1,1.1.1.2 port 80 tcp frag age 20/20
-rdr le0 0.0.0.0/0 port 80 -> 1.1.1.1 port 80 tcp round-robin frag age 30/30
-rdr le0 0.0.0.0/0 port 80 -> 1.1.1.1,1.1.1.2 port 80 tcp round-robin frag age 40/40
+rdr le0 9.8.7.6/32 port 0 -> 1.1.1.1 port 0 tcp
+rdr le0 9.8.7.6/32 -> 1.1.1.1 ip
+rdr le0 9.8.7.6/32 port 80 -> 1.1.1.1 port 80 tcp
+rdr le0 9.8.7.6/32 -> 1.1.1.1 ip
+rdr le0 9.8.7.6/32 port 80 -> 1.1.1.1 port 80 tcp
+rdr le0 9.8.7.6/32 port 80 -> 1.1.1.1 port 80 udp
+rdr le0 9.8.7.6/32 port 80 -> 1.1.1.1 port 80 tcp/udp
+rdr le0 9.8.7.6/32 -> 1.1.1.1 icmp
+rdr le0 9.8.7.6/32 port 80 -> 1.1.1.1,1.1.1.2 port 80 tcp
+rdr le0 9.8.7.6/32 port 80 -> 1.1.1.1 port 80 tcp round-robin
+rdr le0 9.8.7.6/32 port 80 -> 1.1.1.1,1.1.1.2 port 80 tcp round-robin
+rdr le0 9.8.7.6/32 -> 1.1.1.1 ip frag
+rdr le0 9.8.7.6/32 -> 1.1.1.1 icmp frag
+rdr le0 9.8.7.6/32 port 80 -> 1.1.1.1,1.1.1.2 port 80 tcp frag
+rdr le0 9.8.7.6/32 port 80 -> 1.1.1.1 port 80 tcp round-robin frag
+rdr le0 9.8.7.6/32 port 80 -> 1.1.1.1,1.1.1.2 port 80 tcp round-robin frag
+rdr le0 9.8.7.6/32 -> 1.1.1.1 ip frag age 10/10
+rdr le0 9.8.7.6/32 -> 1.1.1.1 ip frag age 10/20
+rdr le0 9.8.7.6/32 -> 1.1.1.1 icmp frag age 10/10
+rdr le0 9.8.7.6/32 port 80 -> 1.1.1.1,1.1.1.2 port 80 tcp frag age 20/20
+rdr le0 9.8.7.6/32 port 80 -> 1.1.1.1 port 80 tcp round-robin frag age 30/30
+rdr le0 9.8.7.6/32 port 80 -> 1.1.1.1,1.1.1.2 port 80 tcp round-robin frag age 40/40
+rdr le0 9.8.7.6/32 -> 1.1.1.1 ip
+rdr le0 9.8.7.6/32 -> 1.1.1.1 ip frag
+rdr le0 9.8.7.6/32 -> 1.1.1.1 icmp frag
+rdr le0 9.8.7.6/32 port 80 -> 1.1.1.1,1.1.1.2 port 80 tcp frag sticky
+rdr le0 9.8.7.6/32 port 80 -> 1.1.1.1 port 80 tcp round-robin frag sticky
+rdr le0 9.8.7.6/32 port 80 -> 1.1.1.1,1.1.1.2 port 80 tcp round-robin frag sticky
+rdr le0 9.8.7.6/32 -> 1.1.1.1 ip frag age 10/10
+rdr le0 9.8.7.6/32 -> 1.1.1.1 ip frag age 10/20
+rdr le0 9.8.7.6/32 -> 1.1.1.1 icmp frag age 10/10
+rdr le0 9.8.7.6/32 port 80 -> 1.1.1.1,1.1.1.2 port 80 tcp frag age 20/20 sticky
+rdr le0 9.8.7.6/32 port 80 -> 1.1.1.1 port 80 tcp round-robin frag age 30/30 sticky
+rdr le0 9.8.7.6/32 port 80 -> 1.1.1.1,1.1.1.2 port 80 tcp round-robin frag age 40/40 sticky
+rdr le0 9.8.7.6/32 -> 1.1.1.1 ip mssclamp 1000
+rdr le0 9.8.7.6/32 -> 1.1.1.1 ip mssclamp 1000
+rdr le0 9.8.7.6/32 -> 1.1.1.1 ip frag mssclamp 1000
+rdr le0 9.8.7.6/32 -> 1.1.1.1 icmp frag mssclamp 1000
+rdr le0 9.8.7.6/32 port 80 -> 1.1.1.1,1.1.1.2 port 80 tcp frag sticky mssclamp 1000
+rdr le0 9.8.7.6/32 port 80 -> 1.1.1.1 port 80 tcp round-robin frag sticky mssclamp 1000
+rdr le0 9.8.7.6/32 port 80 -> 1.1.1.1,1.1.1.2 port 80 tcp round-robin frag sticky mssclamp 1000
+rdr le0 9.8.7.6/32 -> 1.1.1.1 ip frag age 10/10 mssclamp 1000
+rdr le0 9.8.7.6/32 -> 1.1.1.1 ip frag age 10/20 mssclamp 1000
+rdr le0 9.8.7.6/32 -> 1.1.1.1 icmp frag age 10/10 mssclamp 1000
+rdr le0 9.8.7.6/32 port 80 -> 1.1.1.1,1.1.1.2 port 80 tcp frag age 20/20 sticky mssclamp 1000
+rdr le0 9.8.7.6/32 port 80 -> 1.1.1.1 port 80 tcp round-robin frag age 30/30 sticky mssclamp 1000
+rdr le0 9.8.7.6/32 port 80 -> 1.1.1.1,1.1.1.2 port 80 tcp round-robin frag age 40/40 sticky mssclamp 1000
+rdr le0 9.8.7.6/32 -> 1.1.1.1 ip tag nattagcacheline
+rdr le0 9.8.7.6/32 -> 1.1.1.1 ip mssclamp 1000 tag nattagcacheline
+rdr le0 9.8.7.6/32 -> 1.1.1.1 ip mssclamp 1000 tag nattagcacheline
+rdr le0 9.8.7.6/32 -> 1.1.1.1 ip frag mssclamp 1000 tag nattagcacheline
+rdr le0 9.8.7.6/32 -> 1.1.1.1 icmp frag mssclamp 1000 tag nattagcacheline
+rdr le0 9.8.7.6/32 port 80 -> 1.1.1.1,1.1.1.2 port 80 tcp frag sticky mssclamp 1000 tag nattagcacheline
+rdr le0 9.8.7.6/32 port 80 -> 1.1.1.1 port 80 tcp round-robin frag sticky mssclamp 1000 tag nattagcacheline
+rdr le0 9.8.7.6/32 port 80 -> 1.1.1.1,1.1.1.2 port 80 tcp round-robin frag sticky mssclamp 1000 tag nattagcacheline
+rdr le0 9.8.7.6/32 -> 1.1.1.1 ip frag age 10/10 mssclamp 1000 tag nattagcacheline
+rdr le0 9.8.7.6/32 -> 1.1.1.1 ip frag age 10/20 mssclamp 1000 tag nattagcacheline
+rdr le0 9.8.7.6/32 -> 1.1.1.1 icmp frag age 10/10 mssclamp 1000 tag nattagcacheline
+rdr le0 9.8.7.6/32 port 80 -> 1.1.1.1,1.1.1.2 port 80 tcp frag age 20/20 sticky mssclamp 1000 tag nattagcacheline
+rdr le0 9.8.7.6/32 port 80 -> 1.1.1.1 port 80 tcp round-robin frag age 30/30 sticky mssclamp 1000 tag nattagcacheline
+rdr le0 9.8.7.6/32 port 80 -> 1.1.1.1,1.1.1.2 port 80 tcp round-robin frag age 40/40 sticky mssclamp 1000 tag nattagcacheline
+rdr ge0 9.8.7.6/32 port 21 -> 1.1.1.1 port 21 tcp proxy ftp
+rdr ge0 9.8.7.6/32 port 21 -> 1.1.1.1 port 21 tcp proxy ftp
+rdr le0 9.8.7.6/32 port 1000-2000 -> 1.1.1.1 port 5555 tcp
+rdr le0 9.8.7.6/32 port 1000-2000 -> 1.1.1.1 port = 5555 tcp
+rdr le0 0.0.0.0/0 -> 254.220.186.152 ip
+rdr le0 0.0.0.0/0 -> 254.220.186.152,254.220.186.152 ip
diff --git a/contrib/ipfilter/test/expected/in5 b/contrib/ipfilter/test/expected/in5
new file mode 100644
index 0000000..7b3120a
--- /dev/null
+++ b/contrib/ipfilter/test/expected/in5
@@ -0,0 +1,22 @@
+rdr le0 from any to 9.8.7.6/32 port = 0 -> 1.1.1.1 port 0 tcp
+rdr le0 from any to 9.8.7.6/32 -> 1.1.1.1 ip
+rdr le0 from any to 9.8.7.6/32 port = 8888 -> 1.1.1.1 port 888 tcp
+rdr le0 from any to 9.8.7.6/32 -> 1.1.1.1 ip
+rdr le0 from any to 9.8.7.6/32 port = 8888 -> 1.1.1.1 port 888 tcp
+rdr le0 from any to 9.8.7.6/32 port = 8888 -> 1.1.1.1 port 888 udp
+rdr le0 from any to 9.8.7.6/32 port = 8888 -> 1.1.1.1 port 888 tcp/udp
+rdr le0 from any to 9.8.7.6/32 -> 1.1.1.1 icmp
+rdr le0 from any to 9.8.7.6/32 port = 8888 -> 1.1.1.1,1.1.1.2 port 888 tcp
+rdr le0 from any to 9.8.7.6/32 port = 8888 -> 1.1.1.1 port 888 tcp round-robin
+rdr le0 from any to 9.8.7.6/32 port = 8888 -> 1.1.1.1,1.1.1.2 port 888 tcp round-robin
+rdr le0 from any to 9.8.7.6/32 -> 1.1.1.1 ip frag
+rdr le0 from any to 9.8.7.6/32 -> 1.1.1.1 icmp frag
+rdr le0 from any to 9.8.7.6/32 port = 8888 -> 1.1.1.1,1.1.1.2 port 888 tcp frag
+rdr le0 from any to 9.8.7.6/32 port = 8888 -> 1.1.1.1 port 888 tcp round-robin frag
+rdr le0 from any to 9.8.7.6/32 port = 8888 -> 1.1.1.1,1.1.1.2 port 888 tcp round-robin frag
+rdr le0 from any to 9.8.7.6/32 -> 1.1.1.1 ip frag age 10/10
+rdr le0 from any to 9.8.7.6/32 -> 1.1.1.1 ip frag age 10/20
+rdr le0 from any to 9.8.7.6/32 -> 1.1.1.1 icmp frag age 10/10
+rdr le0 from any to 9.8.7.6/32 port = 8888 -> 1.1.1.1,1.1.1.2 port 888 tcp frag age 20/20
+rdr le0 from any to 9.8.7.6/32 port = 8888 -> 1.1.1.1 port 888 tcp round-robin frag age 30/30
+rdr le0 from any to 9.8.7.6/32 port = 8888 -> 1.1.1.1,1.1.1.2 port 888 tcp round-robin frag age 40/40
diff --git a/contrib/ipfilter/test/expected/in6 b/contrib/ipfilter/test/expected/in6
new file mode 100644
index 0000000..08bbff0
--- /dev/null
+++ b/contrib/ipfilter/test/expected/in6
@@ -0,0 +1,3 @@
+map foo0 from any port = 1 to any port != 0 -> 0.0.0.0/32 udp
+map foo0 from any port < 1 to any port > 0 -> 0.0.0.0/32 tcp
+map foo0 from any port <= 1 to any port >= 0 -> 0.0.0.0/32 tcp/udp
diff --git a/contrib/ipfilter/test/expected/ip1 b/contrib/ipfilter/test/expected/ip1
new file mode 100644
index 0000000..b04fa9d
--- /dev/null
+++ b/contrib/ipfilter/test/expected/ip1
@@ -0,0 +1,68 @@
+table role = ipf type = tree number = 1
+ {; };
+table role = ipf type = tree number = 100
+ { 2.2.2.0/24; ! 2.2.0.0/16; 1.2.3.4/32; };
+table role = ipf type = tree number = 110
+ { 2.2.2.0/24; ! 2.2.0.0/16; 1.2.3.4/32; };
+table role = ipf type = tree number = 120
+ { 2.2.2.0/24; ! 2.2.0.0/16; 1.2.3.4/32; };
+table role = ipf type = tree number = 130
+ { 2.2.2.0/24; ! 2.2.0.0/16; 1.2.3.4/32; };
+table role = ipf type = hash number = 2 size = 1
+ {; };
+table role = ipf type = hash number = 200 size = 5
+ { 0/0; 1/32; 1.2.3.4/32; };
+table role = nat type = hash number = 210 size = 5
+ { 0/0; 2/32; 1.2.3.4/32; };
+table role = auth type = hash number = 220 size = 5
+ { 0/0; 3/32; 1.2.3.4/32; };
+table role = count type = hash number = 230 size = 5
+ { 0/0; 4/32; 1.2.3.4/32; };
+table role = ipf type = hash number = 240 size = 5 seed = 101
+ { 0/0; 1/32; 1.2.3.4/32; };
+table role = nat type = hash number = 250 size = 5 seed = 101
+ { 0/0; 2/32; 1.2.3.4/32; };
+table role = auth type = hash number = 260 size = 5 seed = 101
+ { 0/0; 3/32; 1.2.3.4/32; };
+table role = count type = hash number = 270 size = 5 seed = 101
+ { 0/0; 4/32; 1.2.3.4/32; };
+table role = ipf type = hash number = 2000 size = 1001
+ { 0/0; 1/32; 1.2.3.4/32; };
+table role = nat type = hash number = 2000 size = 1001
+ { 0/0; 2/32; 1.2.3.4/32; };
+table role = auth type = hash number = 2000 size = 1001
+ { 0/0; 3/32; 1.2.3.4/32; };
+table role = count type = hash number = 2000 size = 1001
+ { 0/0; 4/32; 1.2.3.4/32; };
+table role = ipf type = hash number = 100 size = 1001 seed = 101
+ { 0/0; 1/32; 1.2.3.4/32; };
+table role = nat type = hash number = 100 size = 1001 seed = 101
+ { 0/0; 2/32; 1.2.3.4/32; };
+table role = auth type = hash number = 100 size = 1001 seed = 101
+ { 0/0; 3/32; 1.2.3.4/32; };
+table role = count type = hash number = 100 size = 1001 seed = 101
+ { 0/0; 4/32; 1.2.3.4/32; };
+group-map in role = ipf number = 300 size = 5
+ { 0/0, group = 303; 5/32, group = 303; 1.2.3.4/32, group = 303; };
+group-map in role = nat number = 300 size = 5
+ { 0/0, group = 303; 6/32, group = 303; 1.2.3.4/32, group = 303; };
+group-map in role = auth number = 300 size = 5
+ { 0/0, group = 303; 7/32, group = 303; 1.2.3.4/32, group = 303; };
+group-map in role = count number = 300 size = 5
+ { 0/0, group = 303; 8/32, group = 303; 1.2.3.4/32, group = 303; };
+group-map out role = ipf number = 400 size = 5
+ { 0/0, group = 303; 5/32, group = 303; 1.2.3.4/32, group = 606; };
+group-map out role = nat number = 400 size = 5
+ { 0/0, group = 303; 6/32, group = 303; 1.2.3.4/32, group = 606; };
+group-map out role = auth number = 400 size = 5
+ { 0/0, group = 303; 7/32, group = 303; 1.2.3.4/32, group = 606; };
+group-map out role = count number = 400 size = 5
+ { 0/0, group = 303; 8/32, group = 303; 1.2.3.4/32, group = 606; };
+group-map in role = ipf number = 500 size = 5
+ { 0/0, group = 10; 5/32, group = 800; 1.2.3.4/32, group = 606; };
+group-map in role = nat number = 500 size = 5
+ { 0/0, group = 10; 6/32, group = 800; 1.2.3.4/32, group = 606; };
+group-map in role = auth number = 500 size = 5
+ { 0/0, group = 10; 7/32, group = 800; 1.2.3.4/32, group = 606; };
+group-map in role = count number = 500 size = 5
+ { 0/0, group = 10; 8/32, group = 800; 1.2.3.4/32, group = 606; };
diff --git a/contrib/ipfilter/test/expected/l1 b/contrib/ipfilter/test/expected/l1
index dbd6b01..ba0de69 100644
--- a/contrib/ipfilter/test/expected/l1
+++ b/contrib/ipfilter/test/expected/l1
@@ -2,7 +2,7 @@ log in all
01/01/1970 00:00:00.000000 anon0 @-1:-1 L 1.1.1.1,1025 -> 2.2.2.2,25 PR tcp len 20 40 -S IN
01/01/1970 00:00:00.000000 anon0 @-1:-1 L 1.1.1.1,1025 -> 2.2.2.2,25 PR tcp len 20 40 -A IN
01/01/1970 00:00:00.000000 anon0 @-1:-1 L 2.2.2.2,25 -> 1.1.1.1,1025 PR tcp len 20 40 -AS IN
-01/01/1970 00:00:00.000000 anon0 @-1:-1 L 1.1.1.1,1025 -> 2.2.2.2,25 PR tcp len 20 40 -F IN
+01/01/1970 00:00:00.000000 anon0 @-1:-1 L 1.1.1.1,1025 -> 2.2.2.2,25 PR tcp len 20 40 -AF IN
01/01/1970 00:00:00.000000 2x anon0 @-1:-1 L 1.1.1.1,1025 -> 2.2.2.2,25 PR tcp len 20 40 -A IN
01/01/1970 00:00:00.000000 anon0 @-1:-1 L 1.1.1.1,1 -> 4.4.4.4,53 PR udp len 20 40 IN
01/01/1970 00:00:00.000000 2x anon0 @-1:-1 L 2.2.2.2,1 -> 4.4.4.4,53 PR udp len 20 40 IN
@@ -24,7 +24,7 @@ pass in log quick proto tcp from 1.1.1.1 to any flags S keep state
01/01/1970 00:00:00.000000 anon0 @0:1 p 1.1.1.1,1025 -> 2.2.2.2,25 PR tcp len 20 40 -A K-S IN
01/01/1970 00:00:00.000000 anon0 @0:1 p 2.2.2.2,25 -> 1.1.1.1,1025 PR tcp len 20 40 -AS K-S IN
01/01/1970 00:00:00.000000 e1 @0:1 p 2.2.2.2,25 -> 1.1.1.1,1025 PR tcp len 20 40 -A K-S OUT
-01/01/1970 00:00:00.000000 anon0 @0:1 p 1.1.1.1,1025 -> 2.2.2.2,25 PR tcp len 20 40 -F K-S IN
+01/01/1970 00:00:00.000000 anon0 @0:1 p 1.1.1.1,1025 -> 2.2.2.2,25 PR tcp len 20 40 -AF K-S IN
--------
pass in log first quick proto tcp from 1.1.1.1 to any flags S keep state
01/01/1970 00:00:00.000000 anon0 @0:1 p 1.1.1.1,1025 -> 2.2.2.2,25 PR tcp len 20 40 -S K-S IN
@@ -34,7 +34,7 @@ pass in log first quick proto tcp from 1.1.1.1 to any flags S keep state
01/01/1970 00:00:00.000000 anon0 @0:4 p 1.1.1.1,1025 -> 2.2.2.2,25 PR tcp len 20 40 -A K-S IN
01/01/1970 00:00:00.000000 anon0 @0:4 p 2.2.2.2,25 -> 1.1.1.1,1025 PR tcp len 20 40 -AS K-S IN
01/01/1970 00:00:00.000000 e1 @0:4 p 2.2.2.2,25 -> 1.1.1.1,1025 PR tcp len 20 40 -A K-S OUT
-01/01/1970 00:00:00.000000 anon0 @0:4 p 1.1.1.1,1025 -> 2.2.2.2,25 PR tcp len 20 40 -F K-S IN
+01/01/1970 00:00:00.000000 anon0 @0:4 p 1.1.1.1,1025 -> 2.2.2.2,25 PR tcp len 20 40 -AF K-S IN
01/01/1970 00:00:00.000000 2x anon0 @-1:-1 L 1.1.1.1,1025 -> 2.2.2.2,25 PR tcp len 20 40 -A IN
01/01/1970 00:00:00.000000 anon0 @-1:-1 L 1.1.1.1,1 -> 4.4.4.4,53 PR udp len 20 40 IN
01/01/1970 00:00:00.000000 anon0 @-1:-1 L 2.2.2.2,1 -> 4.4.4.4,53 PR udp len 20 40 IN
diff --git a/contrib/ipfilter/test/expected/l1.b b/contrib/ipfilter/test/expected/l1.b
index e5c1077..c060086 100644
--- a/contrib/ipfilter/test/expected/l1.b
+++ b/contrib/ipfilter/test/expected/l1.b
@@ -1,7 +1,7 @@
01/01/1970 00:00:00.000000 anon0 @-1:-1 L 1.1.1.1,1025 -> 2.2.2.2,25 PR tcp len 20 40 -S IN
01/01/1970 00:00:00.000000 anon0 @-1:-1 L 1.1.1.1,1025 -> 2.2.2.2,25 PR tcp len 20 40 -A IN
01/01/1970 00:00:00.000000 anon0 @-1:-1 L 2.2.2.2,25 -> 1.1.1.1,1025 PR tcp len 20 40 -AS IN
-01/01/1970 00:00:00.000000 anon0 @-1:-1 L 1.1.1.1,1025 -> 2.2.2.2,25 PR tcp len 20 40 -F IN
+01/01/1970 00:00:00.000000 anon0 @-1:-1 L 1.1.1.1,1025 -> 2.2.2.2,25 PR tcp len 20 40 -AF IN
01/01/1970 00:00:00.000000 2x anon0 @-1:-1 L 1.1.1.1,1025 -> 2.2.2.2,25 PR tcp len 20 40 -A IN
01/01/1970 00:00:00.000000 anon0 @-1:-1 L 1.1.1.1,1 -> 4.4.4.4,53 PR udp len 20 40 IN
01/01/1970 00:00:00.000000 2x anon0 @-1:-1 L 2.2.2.2,1 -> 4.4.4.4,53 PR udp len 20 40 IN
@@ -20,7 +20,7 @@
01/01/1970 00:00:00.000000 anon0 @0:1 p 1.1.1.1,1025 -> 2.2.2.2,25 PR tcp len 20 40 -A K-S IN
01/01/1970 00:00:00.000000 anon0 @0:1 p 2.2.2.2,25 -> 1.1.1.1,1025 PR tcp len 20 40 -AS K-S IN
01/01/1970 00:00:00.000000 e1 @0:1 p 2.2.2.2,25 -> 1.1.1.1,1025 PR tcp len 20 40 -A K-S OUT
-01/01/1970 00:00:00.000000 anon0 @0:1 p 1.1.1.1,1025 -> 2.2.2.2,25 PR tcp len 20 40 -F K-S IN
+01/01/1970 00:00:00.000000 anon0 @0:1 p 1.1.1.1,1025 -> 2.2.2.2,25 PR tcp len 20 40 -AF K-S IN
--------
01/01/1970 00:00:00.000000 anon0 @0:1 p 1.1.1.1,1025 -> 2.2.2.2,25 PR tcp len 20 40 -S K-S IN
--------
@@ -29,7 +29,7 @@
01/01/1970 00:00:00.000000 anon0 @0:4 p 1.1.1.1,1025 -> 2.2.2.2,25 PR tcp len 20 40 -A K-S IN
01/01/1970 00:00:00.000000 anon0 @0:4 p 2.2.2.2,25 -> 1.1.1.1,1025 PR tcp len 20 40 -AS K-S IN
01/01/1970 00:00:00.000000 e1 @0:4 p 2.2.2.2,25 -> 1.1.1.1,1025 PR tcp len 20 40 -A K-S OUT
-01/01/1970 00:00:00.000000 anon0 @0:4 p 1.1.1.1,1025 -> 2.2.2.2,25 PR tcp len 20 40 -F K-S IN
+01/01/1970 00:00:00.000000 anon0 @0:4 p 1.1.1.1,1025 -> 2.2.2.2,25 PR tcp len 20 40 -AF K-S IN
01/01/1970 00:00:00.000000 2x anon0 @-1:-1 L 1.1.1.1,1025 -> 2.2.2.2,25 PR tcp len 20 40 -A IN
01/01/1970 00:00:00.000000 anon0 @-1:-1 L 1.1.1.1,1 -> 4.4.4.4,53 PR udp len 20 40 IN
01/01/1970 00:00:00.000000 anon0 @-1:-1 L 2.2.2.2,1 -> 4.4.4.4,53 PR udp len 20 40 IN
diff --git a/contrib/ipfilter/test/expected/n1 b/contrib/ipfilter/test/expected/n1
index c195f6f..0f87034 100644
--- a/contrib/ipfilter/test/expected/n1
+++ b/contrib/ipfilter/test/expected/n1
@@ -19,7 +19,10 @@ ip 20(20) 255 10.1.1.2 > 10.3.4.5
ip 40(20) 6 10.1.1.1,1025 > 10.3.4.5,1025
ip 48(20) 1 10.2.2.2 > 10.4.3.2
ip 48(20) 1 10.4.3.2 > 10.1.1.1
+ip 48(20) 1 10.4.3.2 > 10.3.4.1
+ip 48(20) 1 10.4.3.2 > 10.3.4.2
ip 48(20) 1 10.4.3.2 > 10.3.4.3
+ip 48(20) 1 10.4.3.2 > 10.3.4.4
ip 48(20) 1 10.4.3.2 > 10.3.4.5
ip 20(20) 34 10.1.1.2 > 10.4.3.2
ip 20(20) 34 10.4.3.2 > 10.3.4.4
@@ -51,7 +54,10 @@ ip 20(20) 255 10.1.1.2 > 10.1.1.0
ip 40(20) 6 10.1.1.1,1025 > 10.1.1.2,1025
ip 48(20) 1 10.3.4.5 > 10.4.3.2
ip 48(20) 1 10.4.3.2 > 10.2.2.2
+ip 48(20) 1 10.4.3.2 > 10.3.4.1
+ip 48(20) 1 10.4.3.2 > 10.3.4.2
ip 48(20) 1 10.4.3.2 > 10.3.4.3
+ip 48(20) 1 10.4.3.2 > 10.3.4.4
ip 48(20) 1 10.4.3.2 > 10.1.1.1
ip 20(20) 34 10.3.4.5 > 10.4.3.2
ip 20(20) 34 10.4.3.2 > 10.3.4.4
@@ -81,9 +87,12 @@ ip 20(20) 255 10.1.1.0 > 10.3.4.5
ip 20(20) 255 10.1.1.1 > 10.3.4.5
ip 20(20) 255 10.1.1.2 > 10.3.4.5
ip 40(20) 6 10.1.1.1,1025 > 10.3.4.5,1025
-ip 48(20) 1 10.3.4.2 > 10.4.3.2
+ip 48(20) 1 10.3.4.3 > 10.4.3.2
ip 48(20) 1 10.4.3.2 > 10.2.2.2
-ip 48(20) 1 10.4.3.2 > 10.3.4.3
+ip 48(20) 1 10.4.3.2 > 10.3.4.1
+ip 48(20) 1 10.4.3.2 > 10.3.4.2
+ip 48(20) 1 10.4.3.2 > 10.1.1.1
+ip 48(20) 1 10.4.3.2 > 10.3.4.4
ip 48(20) 1 10.4.3.2 > 10.3.4.5
ip 20(20) 34 10.3.4.3 > 10.4.3.2
ip 20(20) 34 10.4.3.2 > 10.3.4.4
diff --git a/contrib/ipfilter/test/expected/n10 b/contrib/ipfilter/test/expected/n10
new file mode 100644
index 0000000..f30d757
--- /dev/null
+++ b/contrib/ipfilter/test/expected/n10
@@ -0,0 +1,6 @@
+4500 002c 10c9 4000 ff06 5c9d cbcb cbcb 96cb e002 8032 0015 bd6b c9c8 0000 0000 6002 2238 655d 0000 0204 0064
+-------------------------------
+4500 002c 10c9 4000 ff06 5c9d cbcb cbcb 96cb e002 8032 0015 bd6b c9c8 0000 0000 6002 2238 61d9 0000 0204 03e8
+-------------------------------
+4500 002c 10c9 4000 ff06 5c9d cbcb cbcb 96cb e002 8032 0015 bd6b c9c8 0000 0000 6002 2238 600d 0000 0204 05b4
+-------------------------------
diff --git a/contrib/ipfilter/test/expected/n11 b/contrib/ipfilter/test/expected/n11
new file mode 100644
index 0000000..3732709
--- /dev/null
+++ b/contrib/ipfilter/test/expected/n11
@@ -0,0 +1,51 @@
+ip 20(20) 255 10.1.1.0 > 10.1.1.2
+ip 20(20) 255 1.6.7.8 > 10.1.1.2
+ip 20(20) 255 10.1.1.2 > 10.1.1.1
+ip 20(20) 255 10.2.2.1 > 10.1.2.1
+ip 20(20) 255 10.2.2.2 > 10.1.2.1
+ip 20(20) 255 10.1.1.1 > 10.1.1.2
+ip 20(20) 255 10.1.1.2 > 10.1.1.1
+ip 20(20) 255 10.2.2.1 > 10.2.1.1
+ip 20(20) 255 10.2.2.2 > 10.2.1.1
+ip 20(20) 255 10.2.2.3 > 10.1.1.1
+ip 20(20) 255 10.2.3.4 > 10.2.2.2
+ip 20(20) 255 10.1.1.1 > 10.2.2.2
+ip 20(20) 255 10.1.1.2 > 10.2.2.2
+ip 20(20) 255 10.1.1.0 > 10.3.4.5
+ip 20(20) 255 10.1.1.1 > 10.3.4.5
+ip 20(20) 255 10.1.1.2 > 10.3.4.5
+-------------------------------
+ip 20(20) 255 10.2.2.2 > 10.1.1.2
+ip 20(20) 255 10.1.1.1 > 10.1.1.2
+ip 20(20) 255 10.2.2.2 > 10.1.1.1
+ip 20(20) 255 10.2.2.1 > 10.1.2.1
+ip 20(20) 255 10.2.2.2 > 10.1.2.1
+ip 20(20) 255 10.1.1.1 > 10.1.1.2
+ip 20(20) 255 10.1.1.2 > 10.1.1.1
+ip 20(20) 255 10.2.2.1 > 10.2.1.1
+ip 20(20) 255 10.2.2.2 > 10.2.1.1
+ip 20(20) 255 10.2.2.3 > 10.1.1.1
+ip 20(20) 255 10.2.3.4 > 10.1.1.0
+ip 20(20) 255 10.1.1.1 > 10.1.1.2
+ip 20(20) 255 10.1.1.2 > 10.1.1.0
+ip 20(20) 255 10.1.1.0 > 10.3.4.5
+ip 20(20) 255 10.1.1.1 > 10.3.4.5
+ip 20(20) 255 10.1.1.2 > 10.3.4.5
+-------------------------------
+ip 20(20) 255 10.3.4.0 > 10.1.1.2
+ip 20(20) 255 10.3.4.1 > 10.1.1.2
+ip 20(20) 255 10.3.4.2 > 10.1.1.1
+ip 20(20) 255 10.2.2.1 > 10.1.2.1
+ip 20(20) 255 10.2.2.2 > 10.1.2.1
+ip 20(20) 255 10.1.1.1 > 10.1.1.2
+ip 20(20) 255 10.1.1.2 > 10.1.1.1
+ip 20(20) 255 10.2.2.1 > 10.2.1.1
+ip 20(20) 255 10.2.2.2 > 10.2.1.1
+ip 20(20) 255 10.2.2.3 > 10.1.1.1
+ip 20(20) 255 10.2.3.4 > 10.2.2.2
+ip 20(20) 255 10.1.1.1 > 10.2.2.2
+ip 20(20) 255 10.1.1.2 > 10.2.2.2
+ip 20(20) 255 10.1.1.0 > 10.1.1.5
+ip 20(20) 255 10.1.1.1 > 10.1.1.5
+ip 20(20) 255 10.1.1.2 > 10.1.1.5
+-------------------------------
diff --git a/contrib/ipfilter/test/expected/n12 b/contrib/ipfilter/test/expected/n12
new file mode 100644
index 0000000..010b77b
--- /dev/null
+++ b/contrib/ipfilter/test/expected/n12
@@ -0,0 +1,4 @@
+4510 0040 2020 4000 4006 9478 c0a8 01bc c0a8 0303 2710 0017 4e33 298e 0000 0000 b002 4000 6ff8 0000 0204 05b4 0101 0402 0103 0300 0101 080a 0c72 549e 0000 0000
+4500 003c 00b0 4000 fe06 7964 c0a8 0303 c0a8 7e53 0017 12c2 f674 e02c 4e33 298f a012 2798 7ace 0000 0101 080a 2c05 b797 0c72 549e 0103 0300 0204 05b4
+4510 0034 493b 4000 4006 6b69 c0a8 01bc c0a8 0303 2710 0017 4e33 298f f674 e02d 8010 4000 f673 0000 0101 080a 0c72 549e 2c05 b797
+-------------------------------
diff --git a/contrib/ipfilter/test/expected/n4 b/contrib/ipfilter/test/expected/n4
index c6fb4d4..8cdf78c 100644
--- a/contrib/ipfilter/test/expected/n4
+++ b/contrib/ipfilter/test/expected/n4
@@ -1,30 +1,66 @@
ip 40(20) 6 10.3.3.3,12345 > 10.2.2.1,10023
+ip 40(20) 6 10.1.1.1,23 > 10.3.3.3,12345
ip 40(20) 6 10.3.3.3,12345 > 10.1.1.1,53
-ip 40(20) 6 10.3.3.3,12345 > 10.1.0.0,23
+ip 40(20) 6 10.2.2.1,10053 > 10.3.3.3,12345
+ip 40(20) 6 10.3.3.3,12346 > 10.1.0.0,23
+ip 40(20) 6 10.2.2.1,10023 > 10.3.3.3,12346
ip 28(20) 17 10.3.3.3,12345 > 10.1.1.0,53
+ip 28(20) 17 10.2.2.1,10053 > 10.3.3.3,12345
ip 40(20) 6 10.3.3.3,12345 > 10.1.1.0,53
+ip 40(20) 6 10.2.2.1,53 > 10.3.3.3,12345
-------------------------------
ip 40(20) 6 10.3.3.3,12345 > 10.2.2.1,10023
+ip 40(20) 6 10.1.1.1,23 > 10.3.3.3,12345
ip 40(20) 6 10.3.3.3,12345 > 10.1.1.1,53
-ip 40(20) 6 10.3.3.3,12345 > 10.1.0.0,23
+ip 40(20) 6 10.2.2.1,10053 > 10.3.3.3,12345
+ip 40(20) 6 10.3.3.3,12346 > 10.1.0.0,23
+ip 40(20) 6 10.2.2.1,10023 > 10.3.3.3,12346
ip 28(20) 17 10.3.3.3,12345 > 10.1.1.0,53
+ip 28(20) 17 10.2.2.1,10053 > 10.3.3.3,12345
ip 40(20) 6 10.3.3.3,12345 > 10.1.1.0,53
+ip 40(20) 6 10.2.2.1,53 > 10.3.3.3,12345
-------------------------------
ip 40(20) 6 10.3.3.3,12345 > 10.2.2.1,10023
+ip 40(20) 6 10.1.1.1,23 > 10.3.3.3,12345
ip 40(20) 6 10.3.3.3,12345 > 10.1.1.1,53
-ip 40(20) 6 10.3.3.3,12345 > 10.2.2.1,10023
+ip 40(20) 6 10.2.2.1,10053 > 10.3.3.3,12345
+ip 40(20) 6 10.3.3.3,12346 > 10.2.2.1,10023
+ip 40(20) 6 10.1.0.0,23 > 10.3.3.3,12346
ip 28(20) 17 10.3.3.3,12345 > 10.1.1.0,53
+ip 28(20) 17 10.2.2.1,10053 > 10.3.3.3,12345
ip 40(20) 6 10.3.3.3,12345 > 10.1.1.0,53
+ip 40(20) 6 10.2.2.1,53 > 10.3.3.3,12345
-------------------------------
ip 40(20) 6 10.3.3.3,12345 > 10.1.1.1,23
+ip 40(20) 6 10.2.2.1,10023 > 10.3.3.3,12345
ip 40(20) 6 10.3.3.3,12345 > 10.1.1.1,53
-ip 40(20) 6 10.3.3.3,12345 > 10.1.0.0,23
+ip 40(20) 6 10.2.2.1,10053 > 10.3.3.3,12345
+ip 40(20) 6 10.3.3.3,12346 > 10.1.0.0,23
+ip 40(20) 6 10.2.2.1,10023 > 10.3.3.3,12346
ip 28(20) 17 10.3.3.3,12345 > 10.2.2.1,10053
+ip 28(20) 17 10.1.1.0,53 > 10.3.3.3,12345
ip 40(20) 6 10.3.3.3,12345 > 10.1.1.0,53
+ip 40(20) 6 10.2.2.1,53 > 10.3.3.3,12345
-------------------------------
ip 40(20) 6 10.3.3.3,12345 > 10.2.2.1,23
+ip 40(20) 6 10.2.2.1,10023 > 10.3.3.3,12345
ip 40(20) 6 10.3.3.3,12345 > 10.2.2.1,53
-ip 40(20) 6 10.3.3.3,12345 > 10.1.0.0,23
+ip 40(20) 6 10.2.2.1,10053 > 10.3.3.3,12345
+ip 40(20) 6 10.3.3.3,12346 > 10.1.0.0,23
+ip 40(20) 6 10.2.2.1,10023 > 10.3.3.3,12346
ip 28(20) 17 10.3.3.3,12345 > 10.1.1.0,53
+ip 28(20) 17 10.2.2.1,10053 > 10.3.3.3,12345
+ip 40(20) 6 10.3.3.3,12345 > 10.2.2.1,53
+ip 40(20) 6 10.1.1.0,53 > 10.3.3.3,12345
+-------------------------------
+ip 40(20) 6 10.3.3.3,12345 > 10.2.2.1,23
+ip 40(20) 6 10.2.2.1,10023 > 10.3.3.3,12345
+ip 40(20) 6 10.3.3.3,12345 > 10.2.2.1,53
+ip 40(20) 6 10.2.2.1,10053 > 10.3.3.3,12345
+ip 40(20) 6 10.3.3.3,12346 > 10.1.0.0,23
+ip 40(20) 6 10.2.2.1,10023 > 10.3.3.3,12346
+ip 28(20) 17 10.3.3.3,12345 > 10.2.2.1,53
+ip 28(20) 17 10.2.2.1,10053 > 10.3.3.3,12345
ip 40(20) 6 10.3.3.3,12345 > 10.2.2.1,53
+ip 40(20) 6 10.1.1.0,53 > 10.3.3.3,12345
-------------------------------
diff --git a/contrib/ipfilter/test/expected/n5 b/contrib/ipfilter/test/expected/n5
index 75f174b..521c737 100644
--- a/contrib/ipfilter/test/expected/n5
+++ b/contrib/ipfilter/test/expected/n5
@@ -154,11 +154,11 @@ ip 40(20) 6 10.1.1.3,2003 > 10.1.4.1,80
ip 20(20) 0 10.1.1.1 > 10.1.1.2
ip 40(20) 6 10.1.1.1,1025 > 10.1.1.2,1025
ip 20(20) 0 10.1.1.2 > 10.1.1.1
-ip 40(20) 6 10.3.4.1,1026 > 10.3.4.5,40000
+ip 40(20) 6 10.3.4.3,1026 > 10.3.4.5,40000
ip 40(20) 6 10.1.1.1,1026 > 10.3.4.5,40000
-ip 40(20) 6 10.3.4.1,1025 > 10.3.4.5,40000
+ip 40(20) 6 10.3.4.3,1025 > 10.3.4.5,40000
ip 40(20) 6 10.1.1.1,1025 > 10.3.4.5,40000
-ip 28(20) 17 10.3.4.1,1025 > 10.3.4.5,40001
+ip 28(20) 17 10.3.4.3,1025 > 10.3.4.5,40001
ip 28(20) 17 10.1.1.2,1025 > 10.3.4.5,40001
ip 40(20) 6 10.1.2.1,80 > 10.3.4.5,40001
ip 40(20) 6 10.1.2.1,80 > 10.3.4.5,40001
diff --git a/contrib/ipfilter/test/expected/n7 b/contrib/ipfilter/test/expected/n7
index 51aa987..db8bb50 100644
--- a/contrib/ipfilter/test/expected/n7
+++ b/contrib/ipfilter/test/expected/n7
@@ -9,6 +9,16 @@ ip 40(20) 6 10.2.3.1,1237 > 10.1.1.4,80
ip 40(20) 6 10.2.3.1,1238 > 10.1.1.4,80
-------------------------------
ip 40(20) 6 10.2.3.1,1230 > 10.1.1.1,22
+ip 40(20) 6 10.2.3.1,1231 > 10.2.2.1,10023
+ip 40(20) 6 10.2.3.1,1232 > 10.2.2.1,10023
+ip 40(20) 6 10.2.3.1,1233 > 10.2.2.1,10023
+ip 40(20) 6 10.2.3.1,1234 > 10.1.1.1,80
+ip 40(20) 6 10.2.3.1,1235 > 10.1.1.2,80
+ip 40(20) 6 10.2.3.1,1236 > 10.1.1.3,80
+ip 40(20) 6 10.2.3.1,1237 > 10.1.1.4,80
+ip 40(20) 6 10.2.3.1,1238 > 10.1.1.4,80
+-------------------------------
+ip 40(20) 6 10.2.3.1,1230 > 10.1.1.1,22
ip 40(20) 6 10.2.3.1,1231 > 10.1.1.1,23
ip 40(20) 6 10.2.3.1,1232 > 10.1.1.1,50
ip 40(20) 6 10.2.3.1,1233 > 10.1.1.1,79
diff --git a/contrib/ipfilter/test/expected/n8 b/contrib/ipfilter/test/expected/n8
new file mode 100644
index 0000000..7a26a26
--- /dev/null
+++ b/contrib/ipfilter/test/expected/n8
@@ -0,0 +1,5 @@
+4500 0054 8bc1 0000 ff01 13d5 0a0a 0a01 0404 0404 0800 efdf 6220 0000 3f6f 6e80 000b 0d02 0809 0a0b 0c0d 0e0f 1011 1213 1415 1617 1819 1a1b 1c1d 1e1f 2021 2223 2425 2627 2829 2a2b 2c2d 2e2f 3031 3233 3435 3637
+4500 0054 3fd5 4000 ff01 2fc8 0404 0404 0202 0202 0000 f7df 6220 0000 3f6f 6e80 000b 0d02 0809 0a0b 0c0d 0e0f 1011 1213 1415 1617 1819 1a1b 1c1d 1e1f 2021 2223 2425 2627 2829 2a2b 2c2d 2e2f 3031 3233 3435 3637
+4500 0054 8bc1 0000 ff01 13d5 0a0a 0a01 0404 0404 0800 efde 6220 0001 3f6f 6e80 000b 0d02 0809 0a0b 0c0d 0e0f 1011 1213 1415 1617 1819 1a1b 1c1d 1e1f 2021 2223 2425 2627 2829 2a2b 2c2d 2e2f 3031 3233 3435 3637
+4500 0054 3fd5 4000 ff01 2fc8 0404 0404 0202 0202 0000 f7de 6220 0001 3f6f 6e80 000b 0d02 0809 0a0b 0c0d 0e0f 1011 1213 1415 1617 1819 1a1b 1c1d 1e1f 2021 2223 2425 2627 2829 2a2b 2c2d 2e2f 3031 3233 3435 3637
+-------------------------------
diff --git a/contrib/ipfilter/test/expected/n9 b/contrib/ipfilter/test/expected/n9
new file mode 100644
index 0000000..39979fa
--- /dev/null
+++ b/contrib/ipfilter/test/expected/n9
@@ -0,0 +1,5 @@
+4500 0054 8bc1 0000 ff01 17d9 0202 0202 0a0a 0a01 0800 efdf 6220 0000 3f6f 6e80 000b 0d02 0809 0a0b 0c0d 0e0f 1011 1213 1415 1617 1819 1a1b 1c1d 1e1f 2021 2223 2425 2627 2829 2a2b 2c2d 2e2f 3031 3233 3435 3637
+4500 0054 3fd5 4000 ff01 2fc8 0404 0404 0202 0202 0000 f7df 6220 0000 3f6f 6e80 000b 0d02 0809 0a0b 0c0d 0e0f 1011 1213 1415 1617 1819 1a1b 1c1d 1e1f 2021 2223 2425 2627 2829 2a2b 2c2d 2e2f 3031 3233 3435 3637
+4500 0054 8bc1 0000 ff01 17d9 0202 0202 0a0a 0a01 0800 efde 6220 0001 3f6f 6e80 000b 0d02 0809 0a0b 0c0d 0e0f 1011 1213 1415 1617 1819 1a1b 1c1d 1e1f 2021 2223 2425 2627 2829 2a2b 2c2d 2e2f 3031 3233 3435 3637
+4500 0054 3fd5 4000 ff01 2fc8 0404 0404 0202 0202 0000 f7de 6220 0001 3f6f 6e80 000b 0d02 0809 0a0b 0c0d 0e0f 1011 1213 1415 1617 1819 1a1b 1c1d 1e1f 2021 2223 2425 2627 2829 2a2b 2c2d 2e2f 3031 3233 3435 3637
+-------------------------------
diff --git a/contrib/ipfilter/test/expected/ni1 b/contrib/ipfilter/test/expected/ni1
index 724d38e..be981f1 100644
--- a/contrib/ipfilter/test/expected/ni1
+++ b/contrib/ipfilter/test/expected/ni1
@@ -1,4 +1,4 @@
-4500 0028 4706 4000 0111 1eac 0606 0606 0404 0404 afc9 829e 0014 6308 0402 0000 3be5 468d 000a cfc3
-4500 0038 809a 0000 ff01 3121 0303 0303 0202 0202 0b00 5773 0000 0000 4500 0028 4706 4000 0111 26b4 0202 0202 0404 0404 afc9 829e 0014 6b10
-4500 0044 809a 0000 ff01 3115 0303 0303 0202 0202 0b00 0131 0000 0000 4500 0028 4706 4000 0111 26b4 0202 0202 0404 0404 afc9 829e 0014 6b10 0402 0000 3be5 468d 000a cfc3
+4500 0028 0000 4000 0111 65b2 0606 0606 0404 0404 afc9 829e 0014 6308 0402 0000 3be5 468d 000a cfc3
+4500 0038 809a 0000 ff01 3121 0303 0303 0202 0202 0b00 5773 0000 0000 4500 0028 0000 4000 0111 6dba 0202 0202 0404 0404 afc9 829e 0014 6b10
+4500 0044 809a 0000 ff01 3115 0303 0303 0202 0202 0b00 0131 0000 0000 4500 0028 0000 4000 0111 6dba 0202 0202 0404 0404 afc9 829e 0014 6b10 0402 0000 3be5 468d 000a cfc3
-------------------------------
diff --git a/contrib/ipfilter/test/expected/ni10 b/contrib/ipfilter/test/expected/ni10
index e784581..df7b03f 100644
--- a/contrib/ipfilter/test/expected/ni10
+++ b/contrib/ipfilter/test/expected/ni10
@@ -1,5 +1,5 @@
-4500 003c 4706 4000 ff06 20a2 0404 0404 0606 0606 5000 0050 0000 0001 0000 0000 a002 16d0 d0da 0000 0204 05b4 0402 080a 0047 fbb0 0000 0000 0103 0300
-4500 0038 809a 0000 ff01 2f1f 0202 0202 0404 0404 0303 acab 0000 0000 4500 003c 4706 4000 ff06 28aa 0404 0404 0202 0202 5000 0050 0000 0001
-4500 0058 809a 0000 ff01 2cfd 0303 0303 0404 0404 0303 113f 0000 0000 4500 003c 4706 4000 ff06 20a2 0404 0404 0606 0606 5000 0050 0000 0001 0000 0000 a002 16d0 d0da 0000 0204 05b4 0402 080a 0047 fbb0 0000 0000 0103 0300
-4500 0038 809a 0000 ff01 2b1b 0303 0303 0505 0505 0303 acab 0000 0000 4500 003c 4706 4000 ff06 28ab 0404 0404 0202 0201 5000 0050 0000 0001
+4500 003c 4706 4000 ff06 20a2 0404 0404 0606 0606 5000 0050 0000 0001 0000 0000 a002 16d0 d0da 0000 0204 05b4 0402 080a 0047 fbb0 0000 0000 0103 0300
+4500 0038 0000 0000 ff01 afb9 0202 0202 0404 0404 0303 acab 0000 0000 4500 003c 4706 4000 ff06 28aa 0404 0404 0202 0202 5000 0050 0000 0001
+4500 0058 0001 0000 ff01 af98 0202 0202 0404 0404 0303 0937 0000 0000 4500 003c 4706 4000 ff06 28aa 0404 0404 0202 0202 5000 0050 0000 0001 0000 0000 a002 16d0 d8e2 0000 0204 05b4 0402 080a 0047 fbb0 0000 0000 0103 0300
+4500 0038 809a 0000 ff01 2b1b 0303 0303 0505 0505 0303 acab 0000 0000 4500 003c 4706 4000 ff06 28ab 0404 0404 0202 0201 5000 0050 0000 0001
-------------------------------
diff --git a/contrib/ipfilter/test/expected/ni11 b/contrib/ipfilter/test/expected/ni11
index 8cc37f4..d6db012 100644
--- a/contrib/ipfilter/test/expected/ni11
+++ b/contrib/ipfilter/test/expected/ni11
@@ -1,5 +1,5 @@
-4500 003c 4706 4000 ff06 2aac 0404 0404 0101 0101 5000 9d58 0000 0001 0000 0000 a002 16d0 3ddc 0000 0204 05b4 0402 080a 0047 fbb0 0000 0000 0103 0300
-4500 0038 809a 0000 ff01 271f 0a02 0202 0404 0404 0303 a7fb 0000 0000 4500 003c 4706 4000 ff06 20aa 0404 0404 0a02 0202 5000 0500 0000 0001
-4500 0058 809a 0000 ff01 2cfd 0303 0303 0404 0404 0303 0735 0000 0000 4500 003c 4706 4000 ff06 2aac 0404 0404 0101 0101 5000 9d58 0000 0001 0000 0000 a002 16d0 3ddc 0000 0204 05b4 0402 080a 0047 fbb0 0000 0000 0103 0300
-4500 0038 809a 0000 ff01 2b1b 0303 0303 0505 0505 0303 0fa3 0000 0000 4500 003c 4706 4000 ff06 2aab 0404 0404 0101 0102 5000 9d58 0000 0001
+4500 003c 4706 4000 ff06 2aac 0404 0404 0101 0101 5000 9d58 0000 0001 0000 0000 a002 16d0 3ddc 0000 0204 05b4 0402 080a 0047 fbb0 0000 0000 0103 0300
+4500 0038 0000 0000 ff01 a7b9 0a02 0202 0404 0404 0303 a7fb 0000 0000 4500 003c 4706 4000 ff06 20aa 0404 0404 0a02 0202 5000 0500 0000 0001
+4500 0058 0001 0000 ff01 a798 0a02 0202 0404 0404 0303 1137 0000 0000 4500 003c 4706 4000 ff06 20aa 0404 0404 0a02 0202 5000 0500 0000 0001 0000 0000 a002 16d0 cc32 0000 0204 05b4 0402 080a 0047 fbb0 0000 0000 0103 0300
+4500 0038 809a 0000 ff01 2b1b 0303 0303 0505 0505 0303 0fa3 0000 0000 4500 003c 4706 4000 ff06 2aab 0404 0404 0101 0102 5000 9d58 0000 0001
-------------------------------
diff --git a/contrib/ipfilter/test/expected/ni12 b/contrib/ipfilter/test/expected/ni12
new file mode 100644
index 0000000..70f991b
--- /dev/null
+++ b/contrib/ipfilter/test/expected/ni12
@@ -0,0 +1,5 @@
+4500 003c 4706 4000 ff06 2aac 0404 0404 0101 0101 5000 9c40 0000 0001 0000 0000 a002 16d0 3ef4 0000 0204 05b4 0402 080a 0047 fbb0 0000 0000 0103 0300
+4500 0038 809a 0000 ff01 2d1d 0303 0303 0404 0404 0303 0fa3 0000 0000 4500 003c 4706 4000 ff06 2aac 0404 0404 0101 0101 5000 9d58 0000 0001
+4500 0058 809a 0000 ff01 2cfd 0303 0303 0404 0404 0303 0735 0000 0000 4500 003c 4706 4000 ff06 2aac 0404 0404 0101 0101 5000 9d58 0000 0001 0000 0000 a002 16d0 3ddc 0000 0204 05b4 0402 080a 0047 fbb0 0000 0000 0103 0300
+4500 0038 809a 0000 ff01 2b1b 0303 0303 0505 0505 0303 0fa3 0000 0000 4500 003c 4706 4000 ff06 2aab 0404 0404 0101 0102 5000 9d58 0000 0001
+-------------------------------
diff --git a/contrib/ipfilter/test/expected/ni13 b/contrib/ipfilter/test/expected/ni13
new file mode 100644
index 0000000..3848d39
--- /dev/null
+++ b/contrib/ipfilter/test/expected/ni13
@@ -0,0 +1,32 @@
+4500 0030 5e11 4000 8006 3961 c0a8 7101 c0a8 7103 05e7 06bb abf0 4aa5 0000 0000 7002 faf0 21a1 0000 0204 05b4 0101 0402
+4500 002c 0000 4000 4006 d776 c0a8 7103 c0a8 7101 06bb 05e7 a564 68da abf0 4aa6 6012 8000 a348 0000 0204 05b4
+4500 00c4 5e12 4000 8006 38cc c0a8 7101 c0a8 7103 05e7 06bb abf0 4aa6 a564 68db 5018 faf0 e2a0 0000 009c 0001 1a2b 3c4d 0001 0000 0100 0000 0000 0001 0000 0001 0000 0a28 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 4d69 6372 6f73 6f66 7420 5769 6e64 6f77 7320 4e54 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000
+4500 00c4 0001 4000 4006 d6dd c0a8 7103 c0a8 7101 06bb 05e7 a564 68db abf0 4b42 5018 832c cecf 0000 009c 0001 1a2b 3c4d 0002 0000 0100 0100 0000 0000 0000 0000 0001 0001 6c6f 6361 6c00 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 6c69 6e75 7800 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000
+4500 00d0 5e13 4000 8006 38bf c0a8 7101 c0a8 7103 05e7 06bb abf0 4b42 a564 6977 5018 fa54 ac07 0000 00a8 0001 1a2b 3c4d 0007 0000 4000 1331 0000 012c 05f5 e100 0000 0003 0000 0003 0040 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000
+4500 0048 0002 4000 4006 d758 c0a8 7103 c0a8 7101 06bb 05e7 a564 6977 abf0 4bea 5018 832c 36fa 0000 0020 0001 1a2b 3c4d 0008 0000 0000 4000 0100 0000 05f5 e100 0040 0000 0000 0000
+4500 0040 5e14 4000 8006 394e c0a8 7101 c0a8 7103 05e7 06bb abf0 4bea a564 6997 5018 fa34 e810 0000 0018 0001 1a2b 3c4d 000f 0000 0000 0000 ffff ffff ffff ffff
+4500 0039 5e15 0000 802f 792b c0a8 7101 c0a8 7103 3001 880b 0019 0000 0000 0000 ff03 c021 0100 0015 0104 0578 0506 577f 7c5b 0702 0802 0d03 06
+4500 0020 0003 0000 ff2f 5856 c0a8 7103 c0a8 7101 2081 880b 0000 4000 ffff ffff
+4500 0028 0004 4000 4006 d776 c0a8 7103 c0a8 7101 06bb 05e7 a564 6997 abf0 4c02 5010 832c b5c1 0000
+4500 0038 0005 0000 ff2f 583c c0a8 7103 c0a8 7101 3001 880b 0018 4000 0000 0000 ff03 c021 0101 0014 0206 0000 0000 0506 22d9 0cfa 0702 0802
+4500 002f 0006 0000 ff2f 5844 c0a8 7103 c0a8 7101 3081 880b 000b 4000 0000 0001 0000 0000 ff03 c021 0400 0007 0d03 06
+4500 003c 5e16 0000 802f 7927 c0a8 7101 c0a8 7103 3081 880b 0018 0000 0000 0001 0000 0001 ff03 c021 0201 0014 0206 0000 0000 0506 22d9 0cfa 0702 0802
+4500 0036 5e17 0000 802f 792c c0a8 7101 c0a8 7103 3001 880b 0016 0000 0000 0002 ff03 c021 0101 0012 0104 0578 0506 577f 7c5b 0702 0802
+4500 003a 0007 0000 ff2f 5838 c0a8 7103 c0a8 7101 3081 880b 0016 4000 0000 0002 0000 0002 ff03 c021 0201 0012 0104 0578 0506 577f 7c5b 0702 0802
+4500 0032 0008 0000 ff2f 583f c0a8 7103 c0a8 7101 3001 880b 0012 4000 0000 0003 8021 0101 0010 0306 c0a8 0001 0206 002d 0f01
+4500 0040 5e18 4000 8006 394a c0a8 7101 c0a8 7103 05e7 06bb abf0 4c02 a564 6997 5018 fa34 e7f8 0000 0018 0001 1a2b 3c4d 000f 0000 0000 0000 0000 0000 ffff ffff
+4500 0038 5e19 0000 802f 7928 c0a8 7101 c0a8 7103 3081 880b 0014 0000 0000 0003 0000 0003 c021 0c02 0012 577f 7c5b 4d53 5241 5356 352e 3130
+4500 003e 0009 0000 ff2f 5832 c0a8 7103 c0a8 7101 3081 880b 001a 4000 0000 0004 0000 0003 ff03 c021 0702 0016 0c02 0012 577f 7c5b 4d53 5241 5356 352e 3130
+4500 003e 5e1a 0000 802f 7921 c0a8 7101 c0a8 7103 3081 880b 001a 0000 0000 0004 0000 0004 c021 0c03 0018 577f 7c5b 4d53 5241 532d 302d 434c 4159 4d4f 4f52
+4500 0044 000a 0000 ff2f 582b c0a8 7103 c0a8 7101 3081 880b 0020 4000 0000 0005 0000 0004 ff03 c021 0703 001c 0c03 0018 577f 7c5b 4d53 5241 532d 302d 434c 4159 4d4f 4f52
+4500 0030 5e1b 0000 802f 792e c0a8 7101 c0a8 7103 3081 880b 000c 0000 0000 0005 0000 0005 80fd 0104 000a 1206 0100 0001
+4500 002a 000b 0000 ff2f 5844 c0a8 7103 c0a8 7101 3081 880b 0006 4000 0000 0006 0000 0005 80fd 0101 0004
+4500 002c 000c 0000 ff2f 5841 c0a8 7103 c0a8 7101 3001 880b 000c 4000 0000 0007 80fd 0404 000a 1206 0100 0001
+4500 0048 5e1c 0000 802f 7915 c0a8 7101 c0a8 7103 3081 880b 0024 0000 0000 0006 0000 0007 8021 0105 0022 0306 0000 0000 8106 0000 0000 8206 0000 0000 8306 0000 0000 8406 0000 0000
+4500 0042 000d 0000 ff2f 582a c0a8 7103 c0a8 7101 3081 880b 001e 4000 0000 0008 0000 0006 8021 0405 001c 8106 0000 0000 8206 0000 0000 8306 0000 0000 8406 0000 0000
+4500 0030 5e1d 0000 802f 792c c0a8 7101 c0a8 7103 3081 880b 000c 0000 0000 0007 0000 0008 8021 0401 000a 0206 002d 0f01
+4500 0030 000e 0000 ff2f 583b c0a8 7103 c0a8 7101 3081 880b 000c 4000 0000 0009 0000 0007 8021 0102 000a 0306 c0a8 0001
+4500 002a 5e1e 0000 802f 7933 c0a8 7101 c0a8 7103 3081 880b 0006 0000 0000 0008 0000 0009 80fd 0201 0004
+4500 0032 5e1f 0000 802f 792a c0a8 7101 c0a8 7103 3001 880b 0012 0000 0000 0009 80fd 0506 0010 577f 7c5b 003c cd74 0000 02dc
+4500 002a 000f 0000 ff2f 5840 c0a8 7103 c0a8 7101 3081 880b 0006 4000 0000 000a 0000 0009 80fd 0606 0004
+-------------------------------
diff --git a/contrib/ipfilter/test/expected/ni14 b/contrib/ipfilter/test/expected/ni14
new file mode 100644
index 0000000..8521323
--- /dev/null
+++ b/contrib/ipfilter/test/expected/ni14
@@ -0,0 +1,32 @@
+4500 0030 5e11 4000 8006 ec0b c0a8 7101 7f00 0001 05e7 06bb abf0 4aa5 0000 0000 7002 faf0 d44b 0000 0204 05b4 0101 0402
+4500 002c 0000 4000 4006 d776 c0a8 7103 c0a8 7101 06bb 05e7 a564 68da abf0 4aa6 6012 8000 a348 0000 0204 05b4
+4500 00c4 5e12 4000 8006 eb76 c0a8 7101 7f00 0001 05e7 06bb abf0 4aa6 a564 68db 5018 faf0 954b 0000 009c 0001 1a2b 3c4d 0001 0000 0100 0000 0000 0001 0000 0001 0000 0a28 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 4d69 6372 6f73 6f66 7420 5769 6e64 6f77 7320 4e54 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000
+4500 00c4 0001 4000 4006 d6dd c0a8 7103 c0a8 7101 06bb 05e7 a564 68db abf0 4b42 5018 832c cecf 0000 009c 0001 1a2b 3c4d 0002 0000 0100 0100 0000 0000 0000 0000 0001 0001 6c6f 6361 6c00 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 6c69 6e75 7800 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000
+4500 00d0 5e13 4000 8006 eb69 c0a8 7101 7f00 0001 05e7 06bb abf0 4b42 a564 6977 5018 fa54 5eb2 0000 00a8 0001 1a2b 3c4d 0007 0000 4000 1331 0000 012c 05f5 e100 0000 0003 0000 0003 0040 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000
+4500 0048 0002 4000 4006 d758 c0a8 7103 c0a8 7101 06bb 05e7 a564 6977 abf0 4bea 5018 832c 36fa 0000 0020 0001 1a2b 3c4d 0008 0000 0000 4000 0100 0000 05f5 e100 0040 0000 0000 0000
+4500 0040 5e14 4000 8006 ebf8 c0a8 7101 7f00 0001 05e7 06bb abf0 4bea a564 6997 5018 fa34 9abb 0000 0018 0001 1a2b 3c4d 000f 0000 0000 0000 ffff ffff ffff ffff
+4500 0039 5e15 0000 802f 2bd6 c0a8 7101 7f00 0001 3001 880b 0019 0000 0000 0000 ff03 c021 0100 0015 0104 0578 0506 577f 7c5b 0702 0802 0d03 06
+4500 0020 0003 0000 ff2f 5856 c0a8 7103 c0a8 7101 2081 880b 0000 4000 ffff ffff
+4500 0028 0004 4000 4006 d776 c0a8 7103 c0a8 7101 06bb 05e7 a564 6997 abf0 4c02 5010 832c b5c1 0000
+4500 0038 0005 0000 ff2f 583c c0a8 7103 c0a8 7101 3001 880b 0018 4000 0000 0000 ff03 c021 0101 0014 0206 0000 0000 0506 22d9 0cfa 0702 0802
+4500 002f 0006 0000 ff2f 5844 c0a8 7103 c0a8 7101 3081 880b 000b 4000 0000 0001 0000 0000 ff03 c021 0400 0007 0d03 06
+4500 003c 5e16 0000 802f 2bd2 c0a8 7101 7f00 0001 3081 880b 0018 0000 0000 0001 0000 0001 ff03 c021 0201 0014 0206 0000 0000 0506 22d9 0cfa 0702 0802
+4500 0036 5e17 0000 802f 2bd7 c0a8 7101 7f00 0001 3001 880b 0016 0000 0000 0002 ff03 c021 0101 0012 0104 0578 0506 577f 7c5b 0702 0802
+4500 003a 0007 0000 ff2f 5838 c0a8 7103 c0a8 7101 3081 880b 0016 4000 0000 0002 0000 0002 ff03 c021 0201 0012 0104 0578 0506 577f 7c5b 0702 0802
+4500 0032 0008 0000 ff2f a594 c0a8 7103 c0a8 7101 3001 880b 0012 4000 0000 0003 8021 0101 0010 0306 c0a8 0001 0206 002d 0f01
+4500 0040 5e18 4000 8006 ebf4 c0a8 7101 7f00 0001 05e7 06bb abf0 4c02 a564 6997 5018 fa34 9aa3 0000 0018 0001 1a2b 3c4d 000f 0000 0000 0000 0000 0000 ffff ffff
+4500 0038 5e19 0000 802f 2bd3 c0a8 7101 7f00 0001 3081 880b 0014 0000 0000 0003 0000 0003 c021 0c02 0012 577f 7c5b 4d53 5241 5356 352e 3130
+4500 003e 0009 0000 ff2f a587 c0a8 7103 c0a8 7101 3081 880b 001a 4000 0000 0004 0000 0003 ff03 c021 0702 0016 0c02 0012 577f 7c5b 4d53 5241 5356 352e 3130
+4500 003e 5e1a 0000 802f 2bcc c0a8 7101 7f00 0001 3081 880b 001a 0000 0000 0004 0000 0004 c021 0c03 0018 577f 7c5b 4d53 5241 532d 302d 434c 4159 4d4f 4f52
+4500 0044 000a 0000 ff2f a580 c0a8 7103 c0a8 7101 3081 880b 0020 4000 0000 0005 0000 0004 ff03 c021 0703 001c 0c03 0018 577f 7c5b 4d53 5241 532d 302d 434c 4159 4d4f 4f52
+4500 0030 5e1b 0000 802f 2bd9 c0a8 7101 7f00 0001 3081 880b 000c 0000 0000 0005 0000 0005 80fd 0104 000a 1206 0100 0001
+4500 002a 000b 0000 ff2f a599 c0a8 7103 c0a8 7101 3081 880b 0006 4000 0000 0006 0000 0005 80fd 0101 0004
+4500 002c 000c 0000 ff2f a596 c0a8 7103 c0a8 7101 3001 880b 000c 4000 0000 0007 80fd 0404 000a 1206 0100 0001
+4500 0048 5e1c 0000 802f 2bc0 c0a8 7101 7f00 0001 3081 880b 0024 0000 0000 0006 0000 0007 8021 0105 0022 0306 0000 0000 8106 0000 0000 8206 0000 0000 8306 0000 0000 8406 0000 0000
+4500 0042 000d 0000 ff2f a57f c0a8 7103 c0a8 7101 3081 880b 001e 4000 0000 0008 0000 0006 8021 0405 001c 8106 0000 0000 8206 0000 0000 8306 0000 0000 8406 0000 0000
+4500 0030 5e1d 0000 802f 2bd7 c0a8 7101 7f00 0001 3081 880b 000c 0000 0000 0007 0000 0008 8021 0401 000a 0206 002d 0f01
+4500 0030 000e 0000 ff2f a590 c0a8 7103 c0a8 7101 3081 880b 000c 4000 0000 0009 0000 0007 8021 0102 000a 0306 c0a8 0001
+4500 002a 5e1e 0000 802f 2bdc c0a8 7101 7f00 0001 3081 880b 0006 0000 0000 0008 0000 0009 80fd 0201 0004
+4500 0032 5e1f 0000 802f 2bd3 c0a8 7101 7f00 0001 3001 880b 0012 0000 0000 0009 80fd 0506 0010 577f 7c5b 003c cd74 0000 02dc
+4500 002a 000f 0000 ff2f a595 c0a8 7103 c0a8 7101 3081 880b 0006 4000 0000 000a 0000 0009 80fd 0606 0004
+-------------------------------
diff --git a/contrib/ipfilter/test/expected/ni15 b/contrib/ipfilter/test/expected/ni15
new file mode 100644
index 0000000..1c59de1
--- /dev/null
+++ b/contrib/ipfilter/test/expected/ni15
@@ -0,0 +1,32 @@
+4500 0030 0000 4000 8006 9772 c0a8 7101 c0a8 7103 05e7 06bb abf0 4aa5 0000 0000 7002 faf0 21a1 0000 0204 05b4 0101 0402
+4500 002c 69a6 4000 4006 6dd0 c0a8 7103 c0a8 7101 06bb 05e7 a564 68da abf0 4aa6 6012 8000 a348 0000 0204 05b4
+4500 00c4 0001 4000 8006 96dd c0a8 7101 c0a8 7103 05e7 06bb abf0 4aa6 a564 68db 5018 faf0 e2a0 0000 009c 0001 1a2b 3c4d 0001 0000 0100 0000 0000 0001 0000 0001 0000 0a28 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 4d69 6372 6f73 6f66 7420 5769 6e64 6f77 7320 4e54 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000
+4500 00c4 69a7 4000 4006 6d37 c0a8 7103 c0a8 7101 06bb 05e7 a564 68db abf0 4b42 5018 832c cecf 0000 009c 0001 1a2b 3c4d 0002 0000 0100 0100 0000 0000 0000 0000 0001 0001 6c6f 6361 6c00 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 6c69 6e75 7800 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000
+4500 00d0 0002 4000 8006 96d0 c0a8 7101 c0a8 7103 05e7 06bb abf0 4b42 a564 6977 5018 fa54 ac07 0000 00a8 0001 1a2b 3c4d 0007 0000 4000 1331 0000 012c 05f5 e100 0000 0003 0000 0003 0040 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000
+4500 0048 69a8 4000 4006 6db2 c0a8 7103 c0a8 7101 06bb 05e7 a564 6977 abf0 4bea 5018 832c 36fa 0000 0020 0001 1a2b 3c4d 0008 0000 0000 4000 0100 0000 05f5 e100 0040 0000 0000 0000
+4500 0040 0003 4000 8006 975f c0a8 7101 c0a8 7103 05e7 06bb abf0 4bea a564 6997 5018 fa34 e810 0000 0018 0001 1a2b 3c4d 000f 0000 0000 0000 ffff ffff ffff ffff
+4500 0039 0004 0000 802f d73c c0a8 7101 c0a8 7103 3001 880b 0019 0000 0000 0000 ff03 c021 0100 0015 0104 0578 0506 577f 7c5b 0702 0802 0d03 06
+4500 0020 69a9 0000 ff2f eeaf c0a8 7103 c0a8 7101 2081 880b 0000 4000 ffff ffff
+4500 0028 69aa 4000 4006 6dd0 c0a8 7103 c0a8 7101 06bb 05e7 a564 6997 abf0 4c02 5010 832c b5c1 0000
+4500 0038 69ab 0000 ff2f ee95 c0a8 7103 c0a8 7101 3001 880b 0018 4000 0000 0000 ff03 c021 0101 0014 0206 0000 0000 0506 22d9 0cfa 0702 0802
+4500 002f 69ac 0000 ff2f ee9d c0a8 7103 c0a8 7101 3081 880b 000b 4000 0000 0001 0000 0000 ff03 c021 0400 0007 0d03 06
+4500 003c 0005 0000 802f d738 c0a8 7101 c0a8 7103 3081 880b 0018 0000 0000 0001 0000 0001 ff03 c021 0201 0014 0206 0000 0000 0506 22d9 0cfa 0702 0802
+4500 0036 0006 0000 802f d73d c0a8 7101 c0a8 7103 3001 880b 0016 0000 0000 0002 ff03 c021 0101 0012 0104 0578 0506 577f 7c5b 0702 0802
+4500 003a 69ad 0000 ff2f ee91 c0a8 7103 c0a8 7101 3081 880b 0016 4000 0000 0002 0000 0002 ff03 c021 0201 0012 0104 0578 0506 577f 7c5b 0702 0802
+4500 0032 69ae 0000 ff2f ee98 c0a8 7103 c0a8 7101 3001 880b 0012 4000 0000 0003 8021 0101 0010 0306 c0a8 0001 0206 002d 0f01
+4500 0040 0007 4000 8006 975b c0a8 7101 c0a8 7103 05e7 06bb abf0 4c02 a564 6997 5018 fa34 e7f8 0000 0018 0001 1a2b 3c4d 000f 0000 0000 0000 0000 0000 ffff ffff
+4500 0038 0008 0000 802f d739 c0a8 7101 c0a8 7103 3081 880b 0014 0000 0000 0003 0000 0003 c021 0c02 0012 577f 7c5b 4d53 5241 5356 352e 3130
+4500 003e 69af 0000 ff2f ee8b c0a8 7103 c0a8 7101 3081 880b 001a 4000 0000 0004 0000 0003 ff03 c021 0702 0016 0c02 0012 577f 7c5b 4d53 5241 5356 352e 3130
+4500 003e 0009 0000 802f d732 c0a8 7101 c0a8 7103 3081 880b 001a 0000 0000 0004 0000 0004 c021 0c03 0018 577f 7c5b 4d53 5241 532d 302d 434c 4159 4d4f 4f52
+4500 0044 69b0 0000 ff2f ee84 c0a8 7103 c0a8 7101 3081 880b 0020 4000 0000 0005 0000 0004 ff03 c021 0703 001c 0c03 0018 577f 7c5b 4d53 5241 532d 302d 434c 4159 4d4f 4f52
+4500 0030 000a 0000 802f d73f c0a8 7101 c0a8 7103 3081 880b 000c 0000 0000 0005 0000 0005 80fd 0104 000a 1206 0100 0001
+4500 002a 69b1 0000 ff2f ee9d c0a8 7103 c0a8 7101 3081 880b 0006 4000 0000 0006 0000 0005 80fd 0101 0004
+4500 002c 69b2 0000 ff2f ee9a c0a8 7103 c0a8 7101 3001 880b 000c 4000 0000 0007 80fd 0404 000a 1206 0100 0001
+4500 0048 000b 0000 802f d726 c0a8 7101 c0a8 7103 3081 880b 0024 0000 0000 0006 0000 0007 8021 0105 0022 0306 0000 0000 8106 0000 0000 8206 0000 0000 8306 0000 0000 8406 0000 0000
+4500 0042 69b3 0000 ff2f ee83 c0a8 7103 c0a8 7101 3081 880b 001e 4000 0000 0008 0000 0006 8021 0405 001c 8106 0000 0000 8206 0000 0000 8306 0000 0000 8406 0000 0000
+4500 0030 000c 0000 802f d73d c0a8 7101 c0a8 7103 3081 880b 000c 0000 0000 0007 0000 0008 8021 0401 000a 0206 002d 0f01
+4500 0030 69b4 0000 ff2f ee94 c0a8 7103 c0a8 7101 3081 880b 000c 4000 0000 0009 0000 0007 8021 0102 000a 0306 c0a8 0001
+4500 002a 000d 0000 802f d742 c0a8 7101 c0a8 7103 3081 880b 0006 0000 0000 0008 0000 0009 80fd 0201 0004
+4500 0032 000e 0000 802f d739 c0a8 7101 c0a8 7103 3001 880b 0012 0000 0000 0009 80fd 0506 0010 577f 7c5b 003c cd74 0000 02dc
+4500 002a 69b5 0000 ff2f ee99 c0a8 7103 c0a8 7101 3081 880b 0006 4000 0000 000a 0000 0009 80fd 0606 0004
+-------------------------------
diff --git a/contrib/ipfilter/test/expected/ni16 b/contrib/ipfilter/test/expected/ni16
new file mode 100644
index 0000000..c30b0d2
--- /dev/null
+++ b/contrib/ipfilter/test/expected/ni16
@@ -0,0 +1,32 @@
+4500 0030 0000 4000 8006 9772 c0a8 7101 c0a8 7103 05e7 06bb abf0 4aa5 0000 0000 7002 faf0 21a1 0000 0204 05b4 0101 0402
+4500 002c 69a6 4000 4006 9376 c0a8 7103 0a02 0202 06bb 05e7 a564 68da abf0 4aa6 6012 8000 c8ee 0000 0204 05b4
+4500 00c4 0001 4000 8006 96dd c0a8 7101 c0a8 7103 05e7 06bb abf0 4aa6 a564 68db 5018 faf0 e2a0 0000 009c 0001 1a2b 3c4d 0001 0000 0100 0000 0000 0001 0000 0001 0000 0a28 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 4d69 6372 6f73 6f66 7420 5769 6e64 6f77 7320 4e54 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000
+4500 00c4 69a7 4000 4006 92dd c0a8 7103 0a02 0202 06bb 05e7 a564 68db abf0 4b42 5018 832c f475 0000 009c 0001 1a2b 3c4d 0002 0000 0100 0100 0000 0000 0000 0000 0001 0001 6c6f 6361 6c00 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 6c69 6e75 7800 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000
+4500 00d0 0002 4000 8006 96d0 c0a8 7101 c0a8 7103 05e7 06bb abf0 4b42 a564 6977 5018 fa54 ac07 0000 00a8 0001 1a2b 3c4d 0007 0000 4000 1331 0000 012c 05f5 e100 0000 0003 0000 0003 0040 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000
+4500 0048 69a8 4000 4006 9358 c0a8 7103 0a02 0202 06bb 05e7 a564 6977 abf0 4bea 5018 832c 5ca0 0000 0020 0001 1a2b 3c4d 0008 0000 0000 4000 0100 0000 05f5 e100 0040 0000 0000 0000
+4500 0040 0003 4000 8006 975f c0a8 7101 c0a8 7103 05e7 06bb abf0 4bea a564 6997 5018 fa34 e810 0000 0018 0001 1a2b 3c4d 000f 0000 0000 0000 ffff ffff ffff ffff
+4500 0039 0004 0000 802f d73c c0a8 7101 c0a8 7103 3001 880b 0019 0000 0000 0000 ff03 c021 0100 0015 0104 0578 0506 577f 7c5b 0702 0802 0d03 06
+4500 0020 69a9 0000 ff2f 1456 c0a8 7103 0a02 0202 2081 880b 0000 4000 ffff ffff
+4500 0028 69aa 4000 4006 9376 c0a8 7103 0a02 0202 06bb 05e7 a564 6997 abf0 4c02 5010 832c db67 0000
+4500 0038 69ab 0000 ff2f 143c c0a8 7103 0a02 0202 3001 880b 0018 4000 0000 0000 ff03 c021 0101 0014 0206 0000 0000 0506 22d9 0cfa 0702 0802
+4500 002f 69ac 0000 ff2f 1444 c0a8 7103 0a02 0202 3081 880b 000b 4000 0000 0001 0000 0000 ff03 c021 0400 0007 0d03 06
+4500 003c 0005 0000 802f d738 c0a8 7101 c0a8 7103 3081 880b 0018 0000 0000 0001 0000 0001 ff03 c021 0201 0014 0206 0000 0000 0506 22d9 0cfa 0702 0802
+4500 0036 0006 0000 802f d73d c0a8 7101 c0a8 7103 3001 880b 0016 0000 0000 0002 ff03 c021 0101 0012 0104 0578 0506 577f 7c5b 0702 0802
+4500 003a 69ad 0000 ff2f 1438 c0a8 7103 0a02 0202 3081 880b 0016 4000 0000 0002 0000 0002 ff03 c021 0201 0012 0104 0578 0506 577f 7c5b 0702 0802
+4500 0032 69ae 0000 ff2f 143f c0a8 7103 0a02 0202 3001 880b 0012 4000 0000 0003 8021 0101 0010 0306 c0a8 0001 0206 002d 0f01
+4500 0040 0007 4000 8006 975b c0a8 7101 c0a8 7103 05e7 06bb abf0 4c02 a564 6997 5018 fa34 e7f8 0000 0018 0001 1a2b 3c4d 000f 0000 0000 0000 0000 0000 ffff ffff
+4500 0038 0008 0000 802f d739 c0a8 7101 c0a8 7103 3081 880b 0014 0000 0000 0003 0000 0003 c021 0c02 0012 577f 7c5b 4d53 5241 5356 352e 3130
+4500 003e 69af 0000 ff2f 1432 c0a8 7103 0a02 0202 3081 880b 001a 4000 0000 0004 0000 0003 ff03 c021 0702 0016 0c02 0012 577f 7c5b 4d53 5241 5356 352e 3130
+4500 003e 0009 0000 802f d732 c0a8 7101 c0a8 7103 3081 880b 001a 0000 0000 0004 0000 0004 c021 0c03 0018 577f 7c5b 4d53 5241 532d 302d 434c 4159 4d4f 4f52
+4500 0044 69b0 0000 ff2f 142b c0a8 7103 0a02 0202 3081 880b 0020 4000 0000 0005 0000 0004 ff03 c021 0703 001c 0c03 0018 577f 7c5b 4d53 5241 532d 302d 434c 4159 4d4f 4f52
+4500 0030 000a 0000 802f d73f c0a8 7101 c0a8 7103 3081 880b 000c 0000 0000 0005 0000 0005 80fd 0104 000a 1206 0100 0001
+4500 002a 69b1 0000 ff2f 1444 c0a8 7103 0a02 0202 3081 880b 0006 4000 0000 0006 0000 0005 80fd 0101 0004
+4500 002c 69b2 0000 ff2f 1441 c0a8 7103 0a02 0202 3001 880b 000c 4000 0000 0007 80fd 0404 000a 1206 0100 0001
+4500 0048 000b 0000 802f d726 c0a8 7101 c0a8 7103 3081 880b 0024 0000 0000 0006 0000 0007 8021 0105 0022 0306 0000 0000 8106 0000 0000 8206 0000 0000 8306 0000 0000 8406 0000 0000
+4500 0042 69b3 0000 ff2f 142a c0a8 7103 0a02 0202 3081 880b 001e 4000 0000 0008 0000 0006 8021 0405 001c 8106 0000 0000 8206 0000 0000 8306 0000 0000 8406 0000 0000
+4500 0030 000c 0000 802f d73d c0a8 7101 c0a8 7103 3081 880b 000c 0000 0000 0007 0000 0008 8021 0401 000a 0206 002d 0f01
+4500 0030 69b4 0000 ff2f 143b c0a8 7103 0a02 0202 3081 880b 000c 4000 0000 0009 0000 0007 8021 0102 000a 0306 c0a8 0001
+4500 002a 000d 0000 802f d744 c0a8 7101 c0a8 7103 3081 880b 0006 0000 0000 0008 0000 0009 80fd 0201 0004
+4500 0032 000e 0000 802f d73b c0a8 7101 c0a8 7103 3001 880b 0012 0000 0000 0009 80fd 0506 0010 577f 7c5b 003c cd74 0000 02dc
+4500 002a 69b5 0000 ff2f 1440 c0a8 7103 0a02 0202 3081 880b 0006 4000 0000 000a 0000 0009 80fd 0606 0004
+-------------------------------
diff --git a/contrib/ipfilter/test/expected/ni2 b/contrib/ipfilter/test/expected/ni2
index bf05cf0..6aef39f 100644
--- a/contrib/ipfilter/test/expected/ni2
+++ b/contrib/ipfilter/test/expected/ni2
@@ -1,10 +1,10 @@
-4510 002c bd0d 4000 3e06 bbd1 0101 0101 c0a8 0133 9c40 0077 a664 2485 0000 0000 6002 4000 2ca8 0000 0204 05b4
-4500 002c ce83 4000 7e06 606b c0a8 0133 0a01 0201 0077 05f6 fbdf 1a21 a664 2486 6012 2238 c0a8 0000 0204 05b4
-4510 0028 bd0e 4000 3e06 bbd4 0101 0101 c0a8 0133 9c40 0077 a664 2486 fbdf 1a22 5010 4470 29e3 0000
-4500 005b cf83 4000 7e06 5f3c c0a8 0133 0a01 0201 0077 05f6 fbdf 1a22 a664 2486 5018 2238 ce2a 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0a
-4510 0028 bd18 4000 3e06 bbca 0101 0101 c0a8 0133 9c40 0077 a664 2486 fbdf 1a55 5010 4470 29b0 0000
-4510 002e bd1e 4000 3e06 bbbe 0101 0101 c0a8 0133 9c40 0077 a664 2486 fbdf 1a55 5018 4470 1c98 0000 0000 0000 0d0a
-4500 0048 e383 4000 7e06 4b4f c0a8 0133 0a01 0201 0077 05f6 fbdf 1a55 a664 248c 5018 2232 d80a 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000
-4500 05dc e483 4000 7e06 44bb c0a8 0133 0a01 0201 0077 05f6 fbdf 1a75 a664 248c 5010 2232 9f2d 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 1111 2222 3333 0000 0000 0000 0000 0000 0000 1111 2222 3333 0000 0000 0000 0000 0000 0000 1111 2222 3333 0000 0000 0000 0000 0000 0000 1111 2222 3333 0000 0000 0000 0000 0000 0000 1111 2222 3333 0000 0000 0000 0000 0000 0000 1111 2222 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 1111 2222 3333 0000 0000 0000 0000 0000 0000 1111 2222 3333 0000 0000 0000 0000 0000 0000 1111 2222 3333 0000 0000 0000 0000 0000 0000 1111 2222 3333 0000 0000 0000 0000 0000 0000 1111 2222 3333 0000 0000 0000 0000 0000 0000 1111 2222 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 1111 2222 3333 0000 0000 0000 0000 0000 0000 1111 2222 3333 0000 0000 0000 0000 0000 0000 1111 2222 3333 0000 0000 0000 0000 0000 0000 1111 2222 3333 0000 0000 0000 0000 0000 0000 1111 2222 3333 0000 0000 0000 0000 0000 0000 1111 2222 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 1111 2222 3333 0000 0000 0000 0000 0000 0000 1111 2222 3333 0000 0000 0000 0000 0000 0000 1111 2222 3333 0000 0000 0000 0000 0000 0000 1111 2222 3333 0000 0000 0000 0000 0000 0000 1111 2222 3333 0000 0000 0000 0000 0000 0000 1111 2222 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 1111 2222 3333 0000 0000 0000 0000 0000 0000 1111 2222 3333 0000 0000 0000 0000 0000 0000 1111 2222 3333 0000 0000 0000 0000 0000 0000 1111 2222 3333 0000 0000 0000 0000 0000 0000 1111 2222 3333 0000 0000 0000 0000 0000 0000 1111 2222 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 1111 2222 3333 0000 0000 0000 0000 0000 0000 1111 2222 3333 0000 0000 0000 0000 0000 0000 1111 2222 3333 0000 0000 0000 0000 0000 0000 1111 2222 3333 0000 0000 0000 0000 0000 0000 1111 2222 3333 0000 0000 0000 0000 0000 0000 1111 2222 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 1111 2222 3331 0000 0000 0000 0000 0000 0000 1111 2222 3333 0000 0000 0000 0000 0000 0000 1111 2222 3333 0000 0000 0000 0000 0000 0000 1111 2222 3333 0000 0000 0000 0000 0000 0000 1111 2222 3333 0000 0000 0000 0000 0000 0000 1111 2222 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 1111 2222 3333 0000 0000 0000 0000 0000 0000 1111 2222 3333 0000 0000 0000 0000 0000 0000 1111 2222 3333 0000 0000 0000 0000 0000 0000 1111 2222 3333 0000 0000 0000 0000 0000 0000 1111 2222 3333 0000 0000 0000 0000 0000 0000 1111 2222 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 1111 2222 3333 0000 0000 0000 0000 0000 0000 1111 2222 3333 0000 0000 0000 0000 0000 0000 1111 2222 3333 0000 0000 0000 0000 0000 0000 1111 2222 3333 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000
-4500 0038 d71d 4000 4001 9fca 0101 0101 c0a8 0133 0304 444f 0000 05a0 4500 05dc e483 4000 7e06 4ebb c0a8 0133 0101 0101 0077 9c40 fbdf 1a75
+4510 002c 0000 4000 3e06 78df 0101 0101 c0a8 0133 9c40 0077 a664 2485 0000 0000 6002 4000 2ca8 0000 0204 05b4
+4500 002c ce83 4000 7e06 606b c0a8 0133 0a01 0201 0077 05f6 fbdf 1a21 a664 2486 6012 2238 c0a8 0000 0204 05b4
+4510 0028 0001 4000 3e06 78e2 0101 0101 c0a8 0133 9c40 0077 a664 2486 fbdf 1a22 5010 4470 29e3 0000
+4500 005b cf83 4000 7e06 5f3c c0a8 0133 0a01 0201 0077 05f6 fbdf 1a22 a664 2486 5018 2238 ce2a 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0a
+4510 0028 0002 4000 3e06 78e1 0101 0101 c0a8 0133 9c40 0077 a664 2486 fbdf 1a55 5010 4470 29b0 0000
+4510 002e 0003 4000 3e06 78da 0101 0101 c0a8 0133 9c40 0077 a664 2486 fbdf 1a55 5018 4470 1c98 0000 0000 0000 0d0a
+4500 0048 e383 4000 7e06 4b4f c0a8 0133 0a01 0201 0077 05f6 fbdf 1a55 a664 248c 5018 2232 d80a 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000
+4500 05dc e483 4000 7e06 44bb c0a8 0133 0a01 0201 0077 05f6 fbdf 1a75 a664 248c 5010 2232 9f2d 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 1111 2222 3333 0000 0000 0000 0000 0000 0000 1111 2222 3333 0000 0000 0000 0000 0000 0000 1111 2222 3333 0000 0000 0000 0000 0000 0000 1111 2222 3333 0000 0000 0000 0000 0000 0000 1111 2222 3333 0000 0000 0000 0000 0000 0000 1111 2222 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 1111 2222 3333 0000 0000 0000 0000 0000 0000 1111 2222 3333 0000 0000 0000 0000 0000 0000 1111 2222 3333 0000 0000 0000 0000 0000 0000 1111 2222 3333 0000 0000 0000 0000 0000 0000 1111 2222 3333 0000 0000 0000 0000 0000 0000 1111 2222 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 1111 2222 3333 0000 0000 0000 0000 0000 0000 1111 2222 3333 0000 0000 0000 0000 0000 0000 1111 2222 3333 0000 0000 0000 0000 0000 0000 1111 2222 3333 0000 0000 0000 0000 0000 0000 1111 2222 3333 0000 0000 0000 0000 0000 0000 1111 2222 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 1111 2222 3333 0000 0000 0000 0000 0000 0000 1111 2222 3333 0000 0000 0000 0000 0000 0000 1111 2222 3333 0000 0000 0000 0000 0000 0000 1111 2222 3333 0000 0000 0000 0000 0000 0000 1111 2222 3333 0000 0000 0000 0000 0000 0000 1111 2222 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 1111 2222 3333 0000 0000 0000 0000 0000 0000 1111 2222 3333 0000 0000 0000 0000 0000 0000 1111 2222 3333 0000 0000 0000 0000 0000 0000 1111 2222 3333 0000 0000 0000 0000 0000 0000 1111 2222 3333 0000 0000 0000 0000 0000 0000 1111 2222 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 1111 2222 3333 0000 0000 0000 0000 0000 0000 1111 2222 3333 0000 0000 0000 0000 0000 0000 1111 2222 3333 0000 0000 0000 0000 0000 0000 1111 2222 3333 0000 0000 0000 0000 0000 0000 1111 2222 3333 0000 0000 0000 0000 0000 0000 1111 2222 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 1111 2222 3331 0000 0000 0000 0000 0000 0000 1111 2222 3333 0000 0000 0000 0000 0000 0000 1111 2222 3333 0000 0000 0000 0000 0000 0000 1111 2222 3333 0000 0000 0000 0000 0000 0000 1111 2222 3333 0000 0000 0000 0000 0000 0000 1111 2222 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 1111 2222 3333 0000 0000 0000 0000 0000 0000 1111 2222 3333 0000 0000 0000 0000 0000 0000 1111 2222 3333 0000 0000 0000 0000 0000 0000 1111 2222 3333 0000 0000 0000 0000 0000 0000 1111 2222 3333 0000 0000 0000 0000 0000 0000 1111 2222 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 1111 2222 3333 0000 0000 0000 0000 0000 0000 1111 2222 3333 0000 0000 0000 0000 0000 0000 1111 2222 3333 0000 0000 0000 0000 0000 0000 1111 2222 3333 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000
+4500 0038 0004 4000 4001 76e4 0101 0101 c0a8 0133 0304 444f 0000 05a0 4500 05dc e483 4000 7e06 4ebb c0a8 0133 0101 0101 0077 9c40 fbdf 1a75
-------------------------------
diff --git a/contrib/ipfilter/test/expected/ni3 b/contrib/ipfilter/test/expected/ni3
index cf535f3..600b624 100644
--- a/contrib/ipfilter/test/expected/ni3
+++ b/contrib/ipfilter/test/expected/ni3
@@ -1,4 +1,4 @@
-4500 003c 4706 4000 ff06 20a2 0606 0606 0404 0404 5000 0050 0000 0001 0000 0000 a002 16d0 d0da 0000 0204 05b4 0402 080a 0047 fbb0 0000 0000 0103 0300
-4500 0038 809a 0000 ff01 3121 0303 0303 0202 0202 0303 acab 0000 0000 4500 003c 4706 4000 ff06 28aa 0202 0202 0404 0404 5000 0050 0000 0001
-4500 0058 809a 0000 ff01 3101 0303 0303 0202 0202 0303 0937 0000 0000 4500 003c 4706 4000 ff06 28aa 0202 0202 0404 0404 5000 0050 0000 0001 0000 0000 a002 16d0 d8e2 0000 0204 05b4 0402 080a 0047 fbb0 0000 0000 0103 0300
+4500 003c 0000 4000 ff06 67a8 0606 0606 0404 0404 5000 0050 0000 0001 0000 0000 a002 16d0 d0da 0000 0204 05b4 0402 080a 0047 fbb0 0000 0000 0103 0300
+4500 0038 809a 0000 ff01 3121 0303 0303 0202 0202 0303 acab 0000 0000 4500 003c 4706 4000 ff06 28aa 0202 0202 0404 0404 5000 0050 0000 0001
+4500 0058 809a 0000 ff01 3101 0303 0303 0202 0202 0303 0937 0000 0000 4500 003c 4706 4000 ff06 28aa 0202 0202 0404 0404 5000 0050 0000 0001 0000 0000 a002 16d0 d8e2 0000 0204 05b4 0402 080a 0047 fbb0 0000 0000 0103 0300
-------------------------------
diff --git a/contrib/ipfilter/test/expected/ni4 b/contrib/ipfilter/test/expected/ni4
index 95382cd..cd5ebac 100644
--- a/contrib/ipfilter/test/expected/ni4
+++ b/contrib/ipfilter/test/expected/ni4
@@ -1,4 +1,4 @@
-4500 003c 4706 4000 ff06 20a2 0606 0606 0404 0404 9c40 0050 0000 0001 0000 0000 a002 16d0 849a 0000 0204 05b4 0402 080a 0047 fbb0 0000 0000 0103 0300
-4500 0038 809a 0000 ff01 3121 0303 0303 0202 0202 0303 acab 0000 0000 4500 003c 4706 4000 ff06 28aa 0202 0202 0404 0404 5000 0050 0000 0001
-4500 0058 809a 0000 ff01 3101 0303 0303 0202 0202 0303 0937 0000 0000 4500 003c 4706 4000 ff06 28aa 0202 0202 0404 0404 5000 0050 0000 0001 0000 0000 a002 16d0 d8e2 0000 0204 05b4 0402 080a 0047 fbb0 0000 0000 0103 0300
+4500 003c 0000 4000 ff06 67a8 0606 0606 0404 0404 9c40 0050 0000 0001 0000 0000 a002 16d0 849a 0000 0204 05b4 0402 080a 0047 fbb0 0000 0000 0103 0300
+4500 0038 809a 0000 ff01 3121 0303 0303 0202 0202 0303 acab 0000 0000 4500 003c 4706 4000 ff06 28aa 0202 0202 0404 0404 5000 0050 0000 0001
+4500 0058 809a 0000 ff01 3101 0303 0303 0202 0202 0303 0937 0000 0000 4500 003c 4706 4000 ff06 28aa 0202 0202 0404 0404 5000 0050 0000 0001 0000 0000 a002 16d0 d8e2 0000 0204 05b4 0402 080a 0047 fbb0 0000 0000 0103 0300
-------------------------------
diff --git a/contrib/ipfilter/test/expected/ni5 b/contrib/ipfilter/test/expected/ni5
index 449c2c4..a64d812 100644
--- a/contrib/ipfilter/test/expected/ni5
+++ b/contrib/ipfilter/test/expected/ni5
@@ -1,48 +1,47 @@
-4500 002c 10c9 4000 ff06 f232 0101 0101 96cb e002 8032 0015 bd6b c9c8 0000 0000 6002 2238 f5a2 0000 0204 05b4
-4500 002c ffdd 4000 ef06 5374 96cb e002 c0a8 0103 0015 8032 3786 76c4 bd6b c9c9 6012 269c 8369 0000 0204 0584
-4500 0028 10ca 4000 ff06 f235 0101 0101 96cb e002 8032 0015 bd6b c9c9 3786 76c5 5010 269c 5aa0 0000
-4500 006f ffde 4000 ef06 5330 96cb e002 c0a8 0103 0015 8032 3786 76c5 bd6b c9c9 5018 269c 967e 0000 3232 302d 636f 6f6d 6273 2e61 6e75 2e65 6475 2e61 7520 4e63 4654 5064 2053 6572 7665 7220 2866 7265 6520 6564 7563 6174 696f 6e61 6c20 6c69 6365 6e73 6529 2072 6561 6479 2e0d 0a
-4500 0028 10cb 4000 ff06 f234 0101 0101 96cb e002 8032 0015 bd6b c9c9 3786 770c 5010 269c 5a59 0000
-ippr_ftp_server_valid:junk after cmd[220-Maintained by RSSS and RSPAS IT Staff (previously known as Coombs Comp]
-4500 00c7 ffdf 4000 ef06 52d7 96cb e002 c0a8 0103 0015 8032 3786 770c bd6b c9c9 5018 269c 1087 0000 3232 302d 0d0a 3232 302d 4d61 696e 7461 696e 6564 2062 7920 5253 5353 2061 6e64 2052 5350 4153 2049 5420 5374 6166 6620 2870 7265 7669 6f75 736c 7920 6b6e 6f77 6e20 6173 2043 6f6f 6d62 7320 436f 6d70 7574 696e 6720 556e 6974 290d 0a32 3230 2d41 6e79 2070 726f 626c 656d 7320 636f 6e74 6163 7420 6674 706d 6173 7465 7240 636f 6f6d 6273 2e61 6e75 2e65 6475 2e61 750d 0a32 3230 2d0d 0a32 3230 200d 0a
-4500 0028 10cc 4000 ff06 f233 0101 0101 96cb e002 8032 0015 bd6b c9c9 3786 77ab 5010 269c 59ba 0000
-4500 0038 10cd 4000 ff06 f222 0101 0101 96cb e002 8032 0015 bd6b c9c9 3786 77ab 5018 269c d1c5 0000 5553 4552 2061 6e6f 6e79 6d6f 7573 0d0a
-4500 0028 ffe0 4000 ef06 5375 96cb e002 c0a8 0103 0015 8032 3786 77ab bd6b c9d9 5010 269c 9a00 0000
-4500 006c ffe1 4000 ef06 5330 96cb e002 c0a8 0103 0015 8032 3786 77ab bd6b c9d9 5018 269c b00f 0000 3333 3120 4775 6573 7420 6c6f 6769 6e20 6f6b 2c20 7365 6e64 2079 6f75 7220 636f 6d70 6c65 7465 2065 2d6d 6169 6c20 6164 6472 6573 7320 6173 2070 6173 7377 6f72 642e 0d0a
-4500 0028 10ce 4000 ff06 f231 0101 0101 96cb e002 8032 0015 bd6b c9d9 3786 77ef 5010 269c 5966 0000
-4500 0036 10cf 4000 ff06 f222 0101 0101 96cb e002 8032 0015 bd6b c9d9 3786 77ef 5018 269c 373f 0000 5041 5353 2061 7661 6c6f 6e40 0d0a
-4500 005f ffe2 4000 ef06 533c 96cb e002 c0a8 0103 0015 8032 3786 77ef bd6b c9e7 5018 269c 895e 0000 3233 302d 596f 7520 6172 6520 7573 6572 2023 3420 6f66 2035 3020 7369 6d75 6c74 616e 656f 7573 2075 7365 7273 2061 6c6c 6f77 6564 2e0d 0a
-4500 0028 10d0 4000 ff06 f22f 0101 0101 96cb e002 8032 0015 bd6b c9e7 3786 7826 5010 269c 5921 0000
-4500 0099 ffe3 4000 ef06 5301 96cb e002 c0a8 0103 0015 8032 3786 7826 bd6b c9e7 5018 269c d399 0000 3233 302d 0d0a 3233 302d 0d0a 3233 302d 4869 2e20 2057 6527 7265 2063 6c65 616e 696e 6720 7570 2e20 2041 6e79 2066 6565 6462 6163 6b20 6d6f 7374 2077 656c 636f 6d65 2e20 3130 2041 7567 2030 300d 0a32 3330 2d0d 0a32 3330 204c 6f67 6765 6420 696e 2061 6e6f 6e79 6d6f 7573 6c79 2e0d 0a
-4500 0028 10d1 4000 ff06 f22e 0101 0101 96cb e002 8032 0015 bd6b c9e7 3786 7897 5010 269c 58b0 0000
-4500 0030 10d2 4000 ff06 f225 0101 0101 96cb e002 8032 0015 bd6b c9e7 3786 7897 5018 269c 86ae 0000 5459 5045 2049 0d0a
-4500 0038 ffe4 4000 ef06 5361 96cb e002 c0a8 0103 0015 8032 3786 7897 bd6b c9ef 5018 269c 5fae 0000 3230 3020 5479 7065 206f 6b61 792e 0d0a
-4500 0028 10d3 4000 ff06 f22c 0101 0101 96cb e002 8032 0015 bd6b c9ef 3786 78a7 5010 269c 5898 0000
-4500 003d 10d4 4000 ff06 f216 0101 0101 96cb e002 8032 0015 bd6b c9ef 3786 78a7 5018 269c 4b67 0000 504f 5254 2031 2c31 2c31 2c31 2c31 3238 2c35 310d 0a
-4500 0046 ffe5 4000 ef06 5352 96cb e002 c0a8 0103 0015 8032 3786 78a7 bd6b ca0c 5018 269c dbc3 0000 3230 3020 504f 5254 2063 6f6d 6d61 6e64 2073 7563 6365 7373 6675 6c2e 0d0a
-4500 0030 10d5 4000 ff06 f222 0101 0101 96cb e002 8032 0015 bd6b ca04 3786 78c5 5018 269c 866b 0000 5459 5045 2041 0d0a
-4500 0038 ffe6 4000 ef06 535f 96cb e002 c0a8 0103 0015 8032 3786 78c5 bd6b ca14 5018 269c 5f5b 0000 3230 3020 5479 7065 206f 6b61 792e 0d0a
-4500 002e 10d6 4000 ff06 f223 0101 0101 96cb e002 8032 0015 bd6b ca0c 3786 78d5 5018 269c a994 0000 4e4c 5354 0d0a
-4500 002c ffe7 4000 ef06 536a 96cb e002 c0a8 0103 0014 8033 d9f8 11d4 0000 0000 6002 2238 d190 0000 0204 0584
-4500 002c 10d7 4000 ff06 327b c0a8 0103 96cb e002 8033 0014 bd78 5c12 d9f8 11d5 6012 02f8 d734 0000 0204 0584
-4500 0028 ffe8 4000 ef06 536d 96cb e002 c0a8 0103 0014 8033 d9f8 11d5 bd78 5c13 5010 269c cb1d 0000
-4500 005d ffe9 4000 ef06 5337 96cb e002 c0a8 0103 0015 8032 3786 78d5 bd6b ca1a 5018 269c eed0 0000 3135 3020 4f70 656e 696e 6720 4153 4349 4920 6d6f 6465 2064 6174 6120 636f 6e6e 6563 7469 6f6e 2066 6f72 202f 6269 6e2f 6c73 2e0d 0a
-4500 0028 10d8 4000 ff06 327e c0a8 0103 96cb e002 8033 0014 bd78 5c13 d9f8 11d5 5010 6348 8e71 0000
-4500 0063 ffea 4000 ef06 5330 96cb e002 c0a8 0103 0014 8033 d9f8 11d5 bd78 5c13 5018 269c a315 0000 636f 6f6d 6273 7061 7065 7273 0d0a 6465 7074 730d 0a66 6f75 6e64 2d66 696c 6573 0d0a 696e 636f 6d69 6e67 0d0a 6e6c 632d 7465 7374 0d0a 7075 620d 0a
-4500 0028 10d9 4000 ff06 327d c0a8 0103 96cb e002 8033 0014 bd78 5c13 d9f8 1210 5010 6348 8e36 0000
-4500 0028 ffeb 4000 ef06 536a 96cb e002 c0a8 0103 0014 8033 d9f8 1210 bd78 5c13 5011 269c cae1 0000
-4500 0028 10da 4000 ff06 327c c0a8 0103 96cb e002 8033 0014 bd78 5c13 d9f8 1211 5010 6348 8e35 0000
-4500 0028 10db 4000 ff06 327b c0a8 0103 96cb e002 8033 0014 bd78 5c13 d9f8 1211 5011 6348 8e34 0000
-4500 0028 ffec 4000 ef06 5369 96cb e002 c0a8 0103 0014 8033 d9f8 1211 bd78 5c14 5010 269c cae0 0000
-4500 0028 10dc 4000 ff06 f223 0101 0101 96cb e002 8032 0015 bd6b ca12 3786 790a 5010 269c 5812 0000
-4500 0040 ffed 4000 ef06 5350 96cb e002 c0a8 0103 0015 8032 3786 790a bd6b ca1a 5018 269c 7c9e 0000 3232 3620 4c69 7374 696e 6720 636f 6d70 6c65 7465 642e 0d0a
-4500 0030 10dd 4000 ff06 f21a 0101 0101 96cb e002 8032 0015 bd6b ca12 3786 7922 5018 269c 85f8 0000 5459 5045 2049 0d0a
-4500 0038 ffee 4000 ef06 5357 96cb e002 c0a8 0103 0015 8032 3786 7922 bd6b ca22 5018 269c 5ef0 0000 3230 3020 5479 7065 206f 6b61 792e 0d0a
-4500 0028 10de 4000 ff06 f221 0101 0101 96cb e002 8032 0015 bd6b ca1a 3786 7932 5010 269c 57e2 0000
-4500 002e 10df 4000 ff06 f21a 0101 0101 96cb e002 8032 0015 bd6b ca1a 3786 7932 5018 269c b020 0000 5155 4954 0d0a
-4500 0036 ffef 4000 ef06 5358 96cb e002 c0a8 0103 0015 8032 3786 7932 bd6b ca28 5018 269c a93c 0000 3232 3120 476f 6f64 6279 652e 0d0a
-4500 0028 10e0 4000 ff06 f21f 0101 0101 96cb e002 8032 0015 bd6b ca20 3786 7940 5011 269c 57cd 0000
-4500 0028 fff0 4000 ef06 5365 96cb e002 c0a8 0103 0015 8032 3786 7940 bd6b ca28 5011 269c 981b 0000
-4500 0028 10e1 4000 ff06 3275 c0a8 0103 96cb e002 8032 0015 bd6b ca25 3786 7941 5010 269c 981e 0000
-4500 0028 fff1 4000 ef06 5364 96cb e002 c0a8 0103 0015 8032 3786 7941 bd6b ca29 5010 269c 981a 0000
+4500 002c 0000 4000 ff06 02fc 0101 0101 96cb e002 8032 0015 bd6b c9c8 0000 0000 6002 2238 f5a2 0000 0204 05b4
+4500 002c ffdd 4000 ef06 5374 96cb e002 c0a8 0103 0015 8032 3786 76c4 bd6b c9c9 6012 269c 8369 0000 0204 0584
+4500 0028 0001 4000 ff06 02ff 0101 0101 96cb e002 8032 0015 bd6b c9c9 3786 76c5 5010 269c 5aa0 0000
+4500 006f ffde 4000 ef06 5330 96cb e002 c0a8 0103 0015 8032 3786 76c5 bd6b c9c9 5018 269c 967e 0000 3232 302d 636f 6f6d 6273 2e61 6e75 2e65 6475 2e61 7520 4e63 4654 5064 2053 6572 7665 7220 2866 7265 6520 6564 7563 6174 696f 6e61 6c20 6c69 6365 6e73 6529 2072 6561 6479 2e0d 0a
+4500 0028 0002 4000 ff06 02fe 0101 0101 96cb e002 8032 0015 bd6b c9c9 3786 770c 5010 269c 5a59 0000
+4500 00c7 ffdf 4000 ef06 52d7 96cb e002 c0a8 0103 0015 8032 3786 770c bd6b c9c9 5018 269c 1087 0000 3232 302d 0d0a 3232 302d 4d61 696e 7461 696e 6564 2062 7920 5253 5353 2061 6e64 2052 5350 4153 2049 5420 5374 6166 6620 2870 7265 7669 6f75 736c 7920 6b6e 6f77 6e20 6173 2043 6f6f 6d62 7320 436f 6d70 7574 696e 6720 556e 6974 290d 0a32 3230 2d41 6e79 2070 726f 626c 656d 7320 636f 6e74 6163 7420 6674 706d 6173 7465 7240 636f 6f6d 6273 2e61 6e75 2e65 6475 2e61 750d 0a32 3230 2d0d 0a32 3230 200d 0a
+4500 0028 0003 4000 ff06 02fd 0101 0101 96cb e002 8032 0015 bd6b c9c9 3786 77ab 5010 269c 59ba 0000
+4500 0038 0004 4000 ff06 02ec 0101 0101 96cb e002 8032 0015 bd6b c9c9 3786 77ab 5018 269c d1c5 0000 5553 4552 2061 6e6f 6e79 6d6f 7573 0d0a
+4500 0028 ffe0 4000 ef06 5375 96cb e002 c0a8 0103 0015 8032 3786 77ab bd6b c9d9 5010 269c 9a00 0000
+4500 006c ffe1 4000 ef06 5330 96cb e002 c0a8 0103 0015 8032 3786 77ab bd6b c9d9 5018 269c b00f 0000 3333 3120 4775 6573 7420 6c6f 6769 6e20 6f6b 2c20 7365 6e64 2079 6f75 7220 636f 6d70 6c65 7465 2065 2d6d 6169 6c20 6164 6472 6573 7320 6173 2070 6173 7377 6f72 642e 0d0a
+4500 0028 0005 4000 ff06 02fb 0101 0101 96cb e002 8032 0015 bd6b c9d9 3786 77ef 5010 269c 5966 0000
+4500 0036 0006 4000 ff06 02ec 0101 0101 96cb e002 8032 0015 bd6b c9d9 3786 77ef 5018 269c 373f 0000 5041 5353 2061 7661 6c6f 6e40 0d0a
+4500 005f ffe2 4000 ef06 533c 96cb e002 c0a8 0103 0015 8032 3786 77ef bd6b c9e7 5018 269c 895e 0000 3233 302d 596f 7520 6172 6520 7573 6572 2023 3420 6f66 2035 3020 7369 6d75 6c74 616e 656f 7573 2075 7365 7273 2061 6c6c 6f77 6564 2e0d 0a
+4500 0028 0007 4000 ff06 02f9 0101 0101 96cb e002 8032 0015 bd6b c9e7 3786 7826 5010 269c 5921 0000
+4500 0099 ffe3 4000 ef06 5301 96cb e002 c0a8 0103 0015 8032 3786 7826 bd6b c9e7 5018 269c d399 0000 3233 302d 0d0a 3233 302d 0d0a 3233 302d 4869 2e20 2057 6527 7265 2063 6c65 616e 696e 6720 7570 2e20 2041 6e79 2066 6565 6462 6163 6b20 6d6f 7374 2077 656c 636f 6d65 2e20 3130 2041 7567 2030 300d 0a32 3330 2d0d 0a32 3330 204c 6f67 6765 6420 696e 2061 6e6f 6e79 6d6f 7573 6c79 2e0d 0a
+4500 0028 0008 4000 ff06 02f8 0101 0101 96cb e002 8032 0015 bd6b c9e7 3786 7897 5010 269c 58b0 0000
+4500 0030 0009 4000 ff06 02ef 0101 0101 96cb e002 8032 0015 bd6b c9e7 3786 7897 5018 269c 86ae 0000 5459 5045 2049 0d0a
+4500 0038 ffe4 4000 ef06 5361 96cb e002 c0a8 0103 0015 8032 3786 7897 bd6b c9ef 5018 269c 5fae 0000 3230 3020 5479 7065 206f 6b61 792e 0d0a
+4500 0028 000a 4000 ff06 02f6 0101 0101 96cb e002 8032 0015 bd6b c9ef 3786 78a7 5010 269c 5898 0000
+4500 003d 000b 4000 ff06 02e0 0101 0101 96cb e002 8032 0015 bd6b c9ef 3786 78a7 5018 269c 4b67 0000 504f 5254 2031 2c31 2c31 2c31 2c31 3238 2c35 310d 0a
+4500 0046 ffe5 4000 ef06 5352 96cb e002 c0a8 0103 0015 8032 3786 78a7 bd6b ca0c 5018 269c dbc3 0000 3230 3020 504f 5254 2063 6f6d 6d61 6e64 2073 7563 6365 7373 6675 6c2e 0d0a
+4500 0030 000c 4000 ff06 02ec 0101 0101 96cb e002 8032 0015 bd6b ca04 3786 78c5 5018 269c 866b 0000 5459 5045 2041 0d0a
+4500 0038 ffe6 4000 ef06 535f 96cb e002 c0a8 0103 0015 8032 3786 78c5 bd6b ca14 5018 269c 5f5b 0000 3230 3020 5479 7065 206f 6b61 792e 0d0a
+4500 002e 000d 4000 ff06 02ed 0101 0101 96cb e002 8032 0015 bd6b ca0c 3786 78d5 5018 269c a994 0000 4e4c 5354 0d0a
+4500 002c ffe7 4000 ef06 536a 96cb e002 c0a8 0103 0014 8033 d9f8 11d4 0000 0000 6002 2238 d190 0000 0204 0584
+4500 002c 000e 4000 ff06 02ee 0101 0101 96cb e002 8033 0014 bd78 5c12 d9f8 11d5 6012 02f8 96de 0000 0204 0584
+4500 0028 ffe8 4000 ef06 536d 96cb e002 c0a8 0103 0014 8033 d9f8 11d5 bd78 5c13 5010 269c cb1d 0000
+4500 005d ffe9 4000 ef06 5337 96cb e002 c0a8 0103 0015 8032 3786 78d5 bd6b ca1a 5018 269c eed0 0000 3135 3020 4f70 656e 696e 6720 4153 4349 4920 6d6f 6465 2064 6174 6120 636f 6e6e 6563 7469 6f6e 2066 6f72 202f 6269 6e2f 6c73 2e0d 0a
+4500 0028 000f 4000 ff06 02f1 0101 0101 96cb e002 8033 0014 bd78 5c13 d9f8 11d5 5010 6348 4e1b 0000
+4500 0063 ffea 4000 ef06 5330 96cb e002 c0a8 0103 0014 8033 d9f8 11d5 bd78 5c13 5018 269c a315 0000 636f 6f6d 6273 7061 7065 7273 0d0a 6465 7074 730d 0a66 6f75 6e64 2d66 696c 6573 0d0a 696e 636f 6d69 6e67 0d0a 6e6c 632d 7465 7374 0d0a 7075 620d 0a
+4500 0028 0010 4000 ff06 02f0 0101 0101 96cb e002 8033 0014 bd78 5c13 d9f8 1210 5010 6348 4de0 0000
+4500 0028 ffeb 4000 ef06 536a 96cb e002 c0a8 0103 0014 8033 d9f8 1210 bd78 5c13 5011 269c cae1 0000
+4500 0028 10da 4000 ff06 327c c0a8 0103 96cb e002 8033 0014 bd78 5c13 d9f8 1211 5010 6348 8e35 0000
+4500 0028 10db 4000 ff06 327b c0a8 0103 96cb e002 8033 0014 bd78 5c13 d9f8 1211 5011 6348 8e34 0000
+4500 0028 ffec 4000 ef06 5369 96cb e002 c0a8 0103 0014 8033 d9f8 1211 bd78 5c14 5010 269c cae0 0000
+4500 0028 0011 4000 ff06 02ef 0101 0101 96cb e002 8032 0015 bd6b ca12 3786 790a 5010 269c 5812 0000
+4500 0040 ffed 4000 ef06 5350 96cb e002 c0a8 0103 0015 8032 3786 790a bd6b ca1a 5018 269c 7c9e 0000 3232 3620 4c69 7374 696e 6720 636f 6d70 6c65 7465 642e 0d0a
+4500 0030 0012 4000 ff06 02e6 0101 0101 96cb e002 8032 0015 bd6b ca12 3786 7922 5018 269c 85f8 0000 5459 5045 2049 0d0a
+4500 0038 ffee 4000 ef06 5357 96cb e002 c0a8 0103 0015 8032 3786 7922 bd6b ca22 5018 269c 5ef0 0000 3230 3020 5479 7065 206f 6b61 792e 0d0a
+4500 0028 0013 4000 ff06 02ed 0101 0101 96cb e002 8032 0015 bd6b ca1a 3786 7932 5010 269c 57e2 0000
+4500 002e 0014 4000 ff06 02e6 0101 0101 96cb e002 8032 0015 bd6b ca1a 3786 7932 5018 269c b020 0000 5155 4954 0d0a
+4500 0036 ffef 4000 ef06 5358 96cb e002 c0a8 0103 0015 8032 3786 7932 bd6b ca28 5018 269c a93c 0000 3232 3120 476f 6f64 6279 652e 0d0a
+4500 0028 0015 4000 ff06 02eb 0101 0101 96cb e002 8032 0015 bd6b ca20 3786 7940 5011 269c 57cd 0000
+4500 0028 fff0 4000 ef06 5365 96cb e002 c0a8 0103 0015 8032 3786 7940 bd6b ca28 5011 269c 981b 0000
+4500 0028 10e1 4000 ff06 3275 c0a8 0103 96cb e002 8032 0015 bd6b ca25 3786 7941 5010 269c 981e 0000
+4500 0028 fff1 4000 ef06 5364 96cb e002 c0a8 0103 0015 8032 3786 7941 bd6b ca29 5010 269c 981a 0000
-------------------------------
diff --git a/contrib/ipfilter/test/expected/ni6 b/contrib/ipfilter/test/expected/ni6
new file mode 100644
index 0000000..a4e4ace
--- /dev/null
+++ b/contrib/ipfilter/test/expected/ni6
@@ -0,0 +1,9 @@
+4500 0054 cd8a 4000 ff11 1fbb c0a8 0601 c0a8 0701 8075 006f 0040 d26e 3e1d d249 0000 0000 0000 0002 0001 86a0 0000 0002 0000 0003 0000 0000 0000 0000 0000 0000 0000 0000 0001 86a3 0000 0003 0000 0011 0000 0000
+4500 0054 0000 4000 ff11 ec44 c0a8 0702 c0a8 0701 8075 006f 0040 d16d 3e1d d249 0000 0000 0000 0002 0001 86a0 0000 0002 0000 0003 0000 0000 0000 0000 0000 0000 0000 0000 0001 86a3 0000 0003 0000 0011 0000 0000
+4500 0038 cd83 4000 ff11 1fde c0a8 0701 c0a8 0601 006f 8075 0024 d805 3e1d d249 0000 0001 0000 0000 0000 0000 0000 0000 0000 0000 0000 0801
+4500 0038 0001 4000 ff11 ee5f c0a8 0602 c0a8 0601 006f 8075 0024 d904 3e1d d249 0000 0001 0000 0000 0000 0000 0000 0000 0000 0000 0000 0801
+4500 0044 d5a6 4000 ff11 17af c0a8 0601 c0a8 0701 80df 0801 0030 03f1 3e10 1fb1 0000 0000 0000 0002 0001 86a3 0000 0002 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000
+4500 0044 0002 4000 ff11 ec52 c0a8 0702 c0a8 0701 80df 0801 0030 02f0 3e10 1fb1 0000 0000 0000 0002 0001 86a3 0000 0002 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000
+4500 0034 0000 4000 fe11 ee65 c0a8 0701 c0a8 0601 0801 80df 0020 8ab8 3e10 1fb1 0000 0001 0000 0000 0000 0000 0000 0000 0000 0000
+4500 0034 0003 4000 fe11 ef61 c0a8 0602 c0a8 0601 0801 80df 0020 0000 3e10 1fb1 0000 0001 0000 0000 0000 0000 0000 0000 0000 0000
+-------------------------------
diff --git a/contrib/ipfilter/test/expected/ni7 b/contrib/ipfilter/test/expected/ni7
index d03ec58..f0d0010 100644
--- a/contrib/ipfilter/test/expected/ni7
+++ b/contrib/ipfilter/test/expected/ni7
@@ -1,3 +1,3 @@
-4500 0028 4706 4000 0111 1eac 0404 0404 0606 0606 afc9 829e 0014 6308 0402 0000 3be5 468d 000a cfc3
-4500 0038 809a 0000 ff01 2f1f 0202 0202 0404 0404 0b00 f91c 0000 0000 4500 0028 4706 4000 0111 26b4 0404 0404 0202 0202 afc9 829e 0014 c966
+4500 0028 4706 4000 0111 1eac 0404 0404 0606 0606 afc9 829e 0014 6308 0402 0000 3be5 468d 000a cfc3
+4500 0038 0000 0000 ff01 afb9 0202 0202 0404 0404 0b00 f91c 0000 0000 4500 0028 4706 4000 0111 26b4 0404 0404 0202 0202 afc9 829e 0014 c966
-------------------------------
diff --git a/contrib/ipfilter/test/expected/ni8 b/contrib/ipfilter/test/expected/ni8
index ebee8bc..4741b18 100644
--- a/contrib/ipfilter/test/expected/ni8
+++ b/contrib/ipfilter/test/expected/ni8
@@ -1,5 +1,5 @@
-4500 003c 4706 4000 ff06 2aac 0404 0404 0101 0101 5000 9d58 0000 0001 0000 0000 a002 16d0 3ddc 0000 0204 05b4 0402 080a 0047 fbb0 0000 0000 0103 0300
-4500 0038 809a 0000 ff01 271f 0a02 0202 0404 0404 0303 a7fb 0000 0000 4500 003c 4706 4000 ff06 20aa 0404 0404 0a02 0202 5000 0500 0000 0001
-4500 0058 809a 0000 ff01 26ff 0a02 0202 0404 0404 0303 1137 0000 0000 4500 003c 4706 4000 ff06 20aa 0404 0404 0a02 0202 5000 0500 0000 0001 0000 0000 a002 16d0 cc32 0000 0204 05b4 0402 080a 0047 fbb0 0000 0000 0103 0300
-4500 0038 809a 0000 ff01 2b1b 0303 0303 0505 0505 0303 0fa3 0000 0000 4500 003c 4706 4000 ff06 2aab 0404 0404 0101 0102 5000 9d58 0000 0001
+4500 003c 4706 4000 ff06 2aac 0404 0404 0101 0101 5000 9d58 0000 0001 0000 0000 a002 16d0 3ddc 0000 0204 05b4 0402 080a 0047 fbb0 0000 0000 0103 0300
+4500 0038 0000 0000 ff01 a7b9 0a02 0202 0404 0404 0303 a7fb 0000 0000 4500 003c 4706 4000 ff06 20aa 0404 0404 0a02 0202 5000 0500 0000 0001
+4500 0058 0001 0000 ff01 a798 0a02 0202 0404 0404 0303 1137 0000 0000 4500 003c 4706 4000 ff06 20aa 0404 0404 0a02 0202 5000 0500 0000 0001 0000 0000 a002 16d0 cc32 0000 0204 05b4 0402 080a 0047 fbb0 0000 0000 0103 0300
+4500 0038 0002 0000 ff01 abb3 0303 0303 0505 0505 0303 0fa3 0000 0000 4500 003c 4706 4000 ff06 2aab 0404 0404 0101 0102 5000 9d58 0000 0001
-------------------------------
diff --git a/contrib/ipfilter/test/expected/ni9 b/contrib/ipfilter/test/expected/ni9
new file mode 100644
index 0000000..9effc52
--- /dev/null
+++ b/contrib/ipfilter/test/expected/ni9
@@ -0,0 +1,5 @@
+4500 003c 4706 4000 ff06 2aac 0404 0404 0101 0101 5000 9c40 0000 0001 0000 0000 a002 16d0 3ef4 0000 0204 05b4 0402 080a 0047 fbb0 0000 0000 0103 0300
+4500 0038 0000 0000 ff01 adb7 0303 0303 0404 0404 0303 0fa3 0000 0000 4500 003c 4706 4000 ff06 2aac 0404 0404 0101 0101 5000 9d58 0000 0001
+4500 0058 0001 0000 ff01 ad96 0303 0303 0404 0404 0303 0735 0000 0000 4500 003c 4706 4000 ff06 2aac 0404 0404 0101 0101 5000 9d58 0000 0001 0000 0000 a002 16d0 3ddc 0000 0204 05b4 0402 080a 0047 fbb0 0000 0000 0103 0300
+4500 0038 0002 0000 ff01 abb3 0303 0303 0505 0505 0303 0fa3 0000 0000 4500 003c 4706 4000 ff06 2aab 0404 0404 0101 0102 5000 9d58 0000 0001
+-------------------------------
diff --git a/contrib/ipfilter/test/expected/p1 b/contrib/ipfilter/test/expected/p1
new file mode 100644
index 0000000..c3f7afa
--- /dev/null
+++ b/contrib/ipfilter/test/expected/p1
@@ -0,0 +1,19 @@
+nomatch
+pass
+nomatch
+nomatch
+nomatch
+pass
+nomatch
+nomatch
+List of active MAP/Redirect filters:
+
+List of active sessions:
+List of active state sessions:
+List of configured pools
+table role = ipf type = tree number = 100
+ { 1.1.1.1/32; ! 2.2.0.0/16; 2.2.2.0/24; };
+List of configured hash tables
+List of groups configured (set 0)
+List of groups configured (set 1)
+-------------------------------
diff --git a/contrib/ipfilter/test/expected/p2 b/contrib/ipfilter/test/expected/p2
new file mode 100644
index 0000000..bb15bdf
--- /dev/null
+++ b/contrib/ipfilter/test/expected/p2
@@ -0,0 +1,20 @@
+nomatch
+nomatch
+pass
+nomatch
+nomatch
+nomatch
+nomatch
+pass
+List of active MAP/Redirect filters:
+
+List of active sessions:
+List of active state sessions:
+List of configured pools
+List of configured hash tables
+# 'anonymous' table
+table role = ipf type = hash number = 2147483649 size = 3
+ { 4.4.0.0/16; 127.0.0.1/32; };
+List of groups configured (set 0)
+List of groups configured (set 1)
+-------------------------------
diff --git a/contrib/ipfilter/test/expected/p3 b/contrib/ipfilter/test/expected/p3
new file mode 100644
index 0000000..136543f
--- /dev/null
+++ b/contrib/ipfilter/test/expected/p3
@@ -0,0 +1,33 @@
+pass
+nomatch
+nomatch
+nomatch
+nomatch
+pass
+block
+nomatch
+nomatch
+pass
+nomatch
+block
+List of active MAP/Redirect filters:
+
+List of active sessions:
+List of active state sessions:
+List of configured pools
+List of configured hash tables
+group-map out role = ipf number = 2010 size = 5
+ { 5.0.0.0/8, group = 2040; 4.4.0.0/16, group = 2020; 2.2.2.2/32, group = 2020; };
+group-map in role = ipf number = 1010 size = 3
+ { 3.3.0.0/16, group = 1030; 1.1.1.1/32, group = 1020; };
+List of groups configured (set 0)
+Dev.0. Group 1020 Ref 1 Flags 0x8000
+2 pass in all group 1020
+Dev.0. Group 1030 Ref 1 Flags 0x8000
+2 block in all group 1030
+Dev.0. Group 2020 Ref 2 Flags 0x4000
+4 pass out all group 2020
+Dev.0. Group 2040 Ref 1 Flags 0x4000
+2 block out all group 2040
+List of groups configured (set 1)
+-------------------------------
diff --git a/contrib/ipfilter/test/hextest b/contrib/ipfilter/test/hextest
index c500c6b..b7b0b2c 100644
--- a/contrib/ipfilter/test/hextest
+++ b/contrib/ipfilter/test/hextest
@@ -13,7 +13,7 @@ fi
echo "$1...";
/bin/cp /dev/null results/$1
( while read rule; do
- echo "$rule" | ../ipftest -br - -Hi input/$1 >> results/$1;
+ echo "$rule" | ../ipftest -br - -F hex -i input/$1 >> results/$1;
if [ $? -ne 0 ] ; then
exit 1;
fi
diff --git a/contrib/ipfilter/test/input/f11 b/contrib/ipfilter/test/input/f11
index 25c670d..c54bb80 100644
--- a/contrib/ipfilter/test/input/f11
+++ b/contrib/ipfilter/test/input/f11
@@ -6,7 +6,7 @@ in on e0 tcp 1.1.1.1,1 2.1.2.2,23 A
in on e0 tcp 1.1.1.1,1 2.1.2.2,25 A
in on e1 tcp 2.1.2.2,23 1.1.1.1,1 A
in on e1 tcp 2.1.2.2,25 1.1.1.1,1 A
-in on e0 tcp 1.1.1.1,1 2.1.2.2,23 F
+in on e0 tcp 1.1.1.1,1 2.1.2.2,23 FA
in on e0 tcp 1.1.1.1,1 2.1.2.2,23 A
in on e0 tcp 1.1.1.1,2 2.1.2.2,23 A
in on e1 udp 1.1.1.1,1 4.4.4.4,53
diff --git a/contrib/ipfilter/test/input/f12 b/contrib/ipfilter/test/input/f12
index 682202f..52edde1 100644
--- a/contrib/ipfilter/test/input/f12
+++ b/contrib/ipfilter/test/input/f12
@@ -1,35 +1,44 @@
# 1.1.1.1,1025 -> 2.1.1.1,25 TTL=63 TCP DF SYN
-45 00 0028 0000 4000 3f 06 36cd 01010101 02010101
-0401 0019 00000000 00000000 50 02 2000 0000 0000
+[]
+4500 0028 0000 4000 3f06 36cd 0101 0101 0201 0101
+0401 0019 0000 0000 0000 0000 5002 2000 86c5 0000
# 1.1.1.1,1025 -> 2.1.1.1,25 TTL=63 TCP DF ACK
-45 00 0028 0000 4000 3f 06 36cd 01010101 02010101
-0401 0019 00000000 00000000 50 10 2000 0000 0000
+[]
+4500 0028 0000 4000 3f06 36cd 0101 0101 0201 0101
+0401 0019 0000 0000 0000 0000 5010 2000 86b7 0000
# 1.1.1.1,1025 -> 2.1.1.1,25 TTL=63 TCP DF MF FO=0 ACK
-45 00 0028 0000 6000 3f 06 16cd 01010101 02010101
-0401 0019 00000000 00000000 50 10 2000 0000 0000
+[]
+4500 0028 0000 6000 3f06 16cd 0101 0101 0201 0101
+0401 0019 0000 0000 0000 0000 5010 2000 86b7 0000
# 1.1.1.1,1025 -> 2.1.1.1,25 TTL=63 TCP DF FO=0
-45 00 001c 0000 6000 3f 06 16d9 01010101 02010101
-0401 0019 00000000
+[]
+4500 001c 0000 6000 3f06 16d9 0101 0101 0201 0101
+0401 0019 0000 0000
# 1.1.1.1 -> 2.1.1.1 TTL=63 TCP DF FO=1 ACK
-45 00 001c 0000 6001 3f 06 16d8 01010101 02010101
-00000000 50 10 2000
+[]
+4500 001c 0000 6001 3f06 16d8 0101 0101 0201 0101
+0000 0000 5010 2000
# 1.1.1.1 -> 2.1.1.1 TTL=63 UDP DF MF FO=0
-45 00 0014 0000 6000 3f 11 16d6 01010101 02010101
+[]
+4500 0014 0000 6000 3f11 16d6 0101 0101 0201 0101
# 1.1.1.1,53 -> 2.1.1.1,53 TTL=63 UDP MF FO=0
-45 00 0018 0000 2000 3f 11 56d2 01010101 02010101
+[]
+4500 0018 0000 2000 3f11 56d2 0101 0101 0201 0101
0035 0035
# 1.1.1.1,1 -> 2.1.1.1,1 TTL=63 UDP MF FO=0
-45 00 001c 0000 2000 3f 11 56ce 01010101 02010101
-0001 0001 0004 0000
+[]
+4500 001c 0000 2000 3f11 56ce 0101 0101 0201 0101
+0001 0001 0004 fadc
# 1.1.1.1,53 -> 2.1.1.1,53 TTL=63 UDP MF FO=0
-45 00 001c 0000 2000 3f 11 56ce 01010101 02010101
-0035 0035 0004 0000
+[]
+4500 001c 0000 2000 3f11 56ce 0101 0101 0201 0101
+0035 0035 0004 fa74
diff --git a/contrib/ipfilter/test/input/f13 b/contrib/ipfilter/test/input/f13
index d1c04d8..0ca607e 100644
--- a/contrib/ipfilter/test/input/f13
+++ b/contrib/ipfilter/test/input/f13
@@ -1,51 +1,51 @@
# 1.1.1.1,1025 -> 2.1.1.1,25 TTL=63 TCP DF,MF,FO=0 SYN
-45 00 0028 0001 4000 3f 06 36cc 01010101 02010101
-0401 0019 00000000 00000000 50 02 2000 0000 0000
+4500 0028 0001 4000 3f06 36cc 0101 0101 0201 0101
+0401 0019 0000 0000 0000 0000 50 02 2000 86c5 0000
# 1.1.1.1,1025 -> 2.1.1.1,25 TTL=63 TCP MF ACK
-45 00 0024 0002 2000 3f 06 56cf 01010101 02010101
-0401001900000000 0000000050102000
+4500 0024 0002 2000 3f06 56cf 0101 0101 0201 0101
+0401 0019 0000 0000 0000 0000 5010 2000
# 1.1.1.1,1025 -> 2.1.1.1,25 TTL=63 TCP FO=2 ACK
-45 00 002c 0002 0002 3f 06 76c5 01010101 02010101
-0000000000010203 0405060708090a0b 0c0d0e0f10111213
+4500 002c 0002 0002 3f06 76c5 0101 0101 0201 0101
+0000 0000 0001 0203 0405 0607 0809 0a0b 0c0d 0e0f 1011 1213
# 1.1.1.1,1025 -> 2.1.1.1,25 TTL=63 TCP DF MF FO=0 SYN
-45 00 0028 0003 6000 3f 06 16ca 01010101 02010101
-0401 0019 00000000 00000000 50 10 2000 0000 0000
+4500 0028 0003 6000 3f06 16ca 0101 0101 0201 0101
+0401 0019 0000 0000 0000 0000 5010 2000 0000 0000
# 1.1.1.1,1025 -> 2.1.1.1,25 TTL=63 TCP DF FO=0
-45 00 001c 0004 6000 3f 06 16d5 01010101 02010101
-0401 0019 00000000
+4500 001c 0004 6000 3f06 16d5 0101 0101 0201 0101
+0401 0019 0000 0000
# 1.1.1.1 -> 2.1.1.1 TTL=63 TCP DF FO=1 SYN
-45 00 001c 0005 6001 3f 06 16d3 01010101 02010101
-00000000 50 10 2000
+4500 001c 0005 6001 3f06 16d3 0101 0101 0201 0101
+0000 0000 5010 2000
# 1.1.1.1 -> 2.1.1.1 TTL=63 UDP DF MF FO=0
-45 00 0014 0006 6000 3f 11 16d0 01010101 02010101
+4500 0014 0006 6000 3f11 16d0 0101 0101 0201 0101
# 1.1.1.1,53 -> 2.1.1.1,53 TTL=63 UDP MF FO=0
-45 00 0018 0007 2000 3f 11 56cb 01010101 02010101
+4500 0018 0007 2000 3f11 56cb 0101 0101 0201 0101
0035 0035
# 1.1.1.1,53 -> 2.1.1.1,53 TTL=63 UDP MF FO=0
-45 00 001c 0008 2000 3f 11 56c6 01010101 02010101
-0035003500040000
+4500 001c 0008 2000 3f11 56c6 0101 0101 0201 0101
+0035 0035 0004 0000
# 1.1.1.1,53 -> 2.1.1.1,54 TTL=63 UDP MF FO=0 (short)
-45 00 0018 0008 2000 3f 11 56ca 01010101 02010101
-00350036
+4500 0018 0008 2000 3f11 56ca 0101 0101 0201 0101
+0035 0036
# 1.1.1.1,21 -> 2.1.1.1,54 TTL=63 UDP MF FO=0
-45 00 001c 0008 2000 3f 11 56c6 01010101 02010101
-0015003600040000
+4500 001c 0008 2000 3f11 56c6 0101 0101 0201 0101
+0015 0036 0004 0000
# 1.1.1.1,21 -> 2.1.1.1,54 TTL=63 TCP MF FO=0
-45 00 001c 0008 2000 3f 06 56d1 01010101 02010101
-0015 0036 00000000 00000000 50 02 2000 0000 0000
+4500 001c 0008 2000 3f06 56d1 0101 0101 0201 0101
+0015 0036 0000 0000 0000 0000 50 02 2000 0000 0000
# 1.1.1.1 -> 2.1.1.1 TTL=63 UDP FO=1
-45 00 001c 0008 0001 3f 11 76c5 01010101 02010101
-0000000000000000
+4500 001c 0008 0001 3f11 76c5 0101 0101 0201 0101
+0000 0000 0000 0000
diff --git a/contrib/ipfilter/test/input/f17 b/contrib/ipfilter/test/input/f17
index 1eba7e7..18af566 100644
--- a/contrib/ipfilter/test/input/f17
+++ b/contrib/ipfilter/test/input/f17
@@ -1,61 +1,28 @@
-# (1.1.1.1,54076,seq=0xbfd08989) -> (2.2.2.2,25,seq=0) SYN
[out,ppp0]
4500 003c 8262 0000 4006 f254 0101 0101
0202 0202 d33c 0019 bfd0 8989 0000 0000
a002 4000 cfcd 0000 0204 05b4 0103 0300
0101 080a 008e 17f7 0000 0000
-# (2.2.2.2,25,seq=0x40203436) -> (1.1.1.1,54076,seq=0xbfdfcbc9) ACK
[in,ppp0]
4500 003c 8262 0000 1106 2155 0202 0202
0101 0101 0019 d33c 4020 3436 bfdf cbc9
5010 4000 694a 0000 0204 0584 0103 0300
0101 080a 008e 17f7 0000 0000
-# (1.1.1.1,54076,seq=0xbfd08989) -> (2.2.2.2,25,seq=0x0) SYN
[out,ppp0]
4500 003c 8265 0000 4006 f251 0101 0101
0202 0202 d33c 0019 bfd0 8989 0000 0000
a002 4000 cfc2 0000 0204 05b4 0103 0300
0101 080a 008e 1802 0000 0000
-# (2.2.2.2,25,seq=0xed674d4e) -> (1.1.1.1,54076,seq=0xbfd0898a) SYN-ACK
[in,ppp0]
4500 002c 7442 4000 2906 d784 0202 0202
0101 0101 0019 d33c ed67 4d4e bfd0 898a
6012 2118 19c2 0000 0204 0584
-#
-# (2.2.2.2,25,seq=0xbfd0898a) -> (1.1.1.1,54076,seq=0xed674d4e) ACK
[out,ppp0]
4500 002c 8262 0000 4006 f264 0101 0101
0202 0202 d33c 0019 bfd0 898a ed67 4d4e
-5010 4000 6190 0000 0000
-
-# (1.1.1.1,54076,seq=0xcfd08989) -> (2.2.2.2,25,seq=0x0) SYN
-[out,ppp0]
-4500 003c 8265 0000 4006 f251 0101 0101
-0202 0202 d33c 0019 cfd0 8989 0000 0000
-a002 4000 bfc2 0000 0204 05b4 0103 0300
-0101 080a 008e 1802 0000 0000
-
-# (1.1.1.1,54076,seq=0xcfd08989) -> (2.2.2.2,25,seq=0x0) SYN
-[out,ppp0]
-4500 003c 8266 0000 4006 f250 0101 0101
-0202 0202 d33c 0019 cfd0 8989 0000 0000
-a002 4000 bfc2 0000 0204 05b4 0103 0300
-0101 080a 008e 1802 0000 0000
-
-# (2.2.2.2,25,seq=0xed674d4e) -> (1.1.1.1,54076,seq=0xcfd0898a) SYN-ACK
-[in,ppp0]
-4500 002c 7442 4000 2906 d784 0202 0202
-0101 0101 0019 d33c ed67 4d4e cfd0 898a
-6012 2118 09c2 0000 0204 0584
-
-#
-# (2.2.2.2,25,seq=0xcfd0898a) -> (1.1.1.1,54076,seq=0xed674d4e) ACK
-[out,ppp0]
-4500 002c 8262 0000 4006 f264 0101 0101
-0202 0202 d33c 0019 cfd0 898a ed67 4d4e
-5010 4000 6190 0000 0000
+5010 4000 0ce0 0000 0000
diff --git a/contrib/ipfilter/test/input/ipv6.1 b/contrib/ipfilter/test/input/ipv6.1
index 1d7d546..3920810 100644
--- a/contrib/ipfilter/test/input/ipv6.1
+++ b/contrib/ipfilter/test/input/ipv6.1
@@ -3,7 +3,7 @@ ef00 1001 2002 0001 0000 0000 0000 0070
2001 1002 3333 0001 0000 0000 0000 0001
8083 829a
0018
-f427
+f4c1
0000 0344 0000 0004 f8f1 9d3c ddba 0e00
[in,gif0] 6000 0000 0048 3a40
diff --git a/contrib/ipfilter/test/input/l1 b/contrib/ipfilter/test/input/l1
index afda0db..56d766a 100644
--- a/contrib/ipfilter/test/input/l1
+++ b/contrib/ipfilter/test/input/l1
@@ -1,52 +1,64 @@
# 1.1.1.1,1025 -> 2.2.2.2,25 TTL=63 TCP DF SYN
-45 00 0028 0000 4000 3f 06 0000 01010101 02020202
-0401 0019 00000000 00000000 50 02 2000 0000 0000
+[]
+4500 0028 0000 4000 3f06 35cb 0101 0101 0202 0202
+0401 0019 0000 0000 0000 0000 5002 2000 85c3 0000
#in on e0 tcp 1.1.1.1,1025 2.1.2.2,25 A
-45 00 0028 0000 4000 3f 06 0000 01010101 02020202
-0401 0019 00000000 00000000 50 10 2000 0000 0000
+[]
+4500 0028 0000 4000 3f06 35cb 0101 0101 0202 0202
+0401 0019 0000 0000 0000 0000 5010 2000 85b5 0000
#in on e1 tcp 2.1.2.2,25 1.1.1.1,1025 AS
-45 00 0028 0000 4000 3f 06 0000 02020202 01010101
-0019 0401 00000000 00000000 50 12 2000 0000 0000
+[]
+4500 0028 0000 4000 3f06 35cb 0202 0202 0101 0101
+0019 0401 0000 0000 0000 0000 5012 2000 85b3 0000
#in on e1 tcp 2.1.2.2,25 1.1.1.1,1025 A
-[out,e1] 45 00 0028 0000 4000 3f 06 0000 02020202 01010101
-0019 0401 00000000 00000000 50 10 2000 0000 0000
+[out,e1] 4500 0028 0000 4000 3f06 35cb 0202 0202 0101 0101
+0019 0401 0000 0000 0000 0000 5010 2000 85b5 0000
#in on e0 tcp 1.1.1.1,1025 2.1.2.2,25 F
-45 00 0028 0000 4000 3f 06 0000 01010101 02020202
-0401 0019 00000000 00000000 50 01 2000 0000 0000
+[]
+4500 0028 0000 4000 3f06 35cb 0101 0101 0202 0202
+0401 0019 0000 0000 0000 0000 5011 2000 85b4 0000
#in on e0 tcp 1.1.1.1,1025 2.1.2.2,25 A
-45 00 0028 0000 4000 3f 06 0000 01010101 02020202
-0401 0019 00000000 00000000 50 10 2000 0000 0000
+[]
+4500 0028 0000 4000 3f06 35cb 0101 0101 0202 0202
+0401 0019 0000 0000 0000 0000 5010 2000 85b5 0000
#in on e0 tcp 1.1.1.1,1025 2.1.2.2,25 A
-45 00 0028 0000 4000 3f 06 0000 01010101 02020202
-0401 0019 00000000 00000000 50 10 2000 0000 0000
+[]
+4500 0028 0000 4000 3f06 35cb 0101 0101 0202 0202
+0401 0019 0000 0000 0000 0000 5010 2000 85b5 0000
#in on e1 udp 1.1.1.1,1 4.4.4.4,53
-45 00 0028 0000 4000 3f 11 0000 01010101 04040404
-0001 0035 0000 0000 0102 0304 0506 0708 090a 0b0d
+[]
+4500 0028 0000 4000 3f11 31bc 0101 0101 0404 0404
+0001 0035 0000 d16f 0102 0304 0506 0708 090a 0b0d
#in on e1 udp 2.2.2.2,2 4.4.4.4,53
-45 00 0028 0000 4000 3f 11 0000 02020202 04040404
+[]
+4500 0028 0000 4000 3f11 2fba 0202 0202 0404 0404
0001 0035 0000 0000 0102 0304 0506 0708 090a 0b0d
#in on e1 udp 2.2.2.2,2 4.4.4.4,53
-45 00 0038 0000 4000 3f 11 0000 02020202 04040404
-0001 0035 0000 0000 0102 0304 0506 0708 090a 0b0d
+[]
+4500 0038 0000 4000 3f11 2faa 0202 0202 0404 0404
+0001 0035 0000 d47b 0102 0304 0506 0708 090a 0b0d
0e0f 4061 4263 4465 4667 4869 4a6b 4c6d
#in on e0 ip 4.4.4.4,53 1.1.1.1,1
-45 00 0014 0000 4000 3f 00 0000 02020202 04040404
+[]
+4500 0014 0000 4000 3f00 2fdf 0202 0202 0404 0404
#in on e0 udp 3.3.3.3,1023 1.1.1.1,2049
-45 00 001c 0000 4000 3f 11 0000 03030303 01010101
-03ff 0801 0000 0000
+[]
+4500 001c 0000 4000 3f11 33ca 0303 0303 0101 0101
+03ff 0801 0000 ebde
#in on e0 udp 1.1.1.1,2049 3.3.3.3,1023
-45 00 001c 0000 4000 3f 11 0000 01010101 03030303
+[]
+4500 001c 0000 4000 3f11 33ca 0101 0101 0303 0303
0801 03ff 0000 0000
diff --git a/contrib/ipfilter/test/input/n1 b/contrib/ipfilter/test/input/n1
index a607390..04b24ef 100644
--- a/contrib/ipfilter/test/input/n1
+++ b/contrib/ipfilter/test/input/n1
@@ -19,7 +19,10 @@ in on zx0 255 10.1.1.2 10.3.4.5
in on zx0 tcp 10.1.1.1,1025 10.3.4.5,1025
out on zx0 icmp 10.1.1.1 10.4.3.2
in on zx0 icmp 10.4.3.2 10.2.2.2
+in on zx0 icmp 10.4.3.2 10.3.4.1
+in on zx0 icmp 10.4.3.2 10.3.4.2
in on zx0 icmp 10.4.3.2 10.3.4.3
+in on zx0 icmp 10.4.3.2 10.3.4.4
in on zx0 icmp 10.4.3.2 10.3.4.5
out on zx0 34 10.1.1.2 10.4.3.2
in on zx0 34 10.4.3.2 10.3.4.4
diff --git a/contrib/ipfilter/test/input/n10 b/contrib/ipfilter/test/input/n10
new file mode 100644
index 0000000..321ed0b
--- /dev/null
+++ b/contrib/ipfilter/test/input/n10
@@ -0,0 +1,6 @@
+# TCP SYN packet with an MSS option
+[out,ppp0]
+4500 002c 10c9 4000 ff06 3289 c0a8 0103
+96cb e002 8032 0015 bd6b c9c8 0000 0000
+6002 2238 35f9 0000 0204 05b4
+
diff --git a/contrib/ipfilter/test/input/n11 b/contrib/ipfilter/test/input/n11
new file mode 100644
index 0000000..8712674
--- /dev/null
+++ b/contrib/ipfilter/test/input/n11
@@ -0,0 +1,16 @@
+out on zx0 255 10.1.1.0 10.1.1.2
+out on zx0 255 10.1.1.1 10.1.1.2
+out on zx0 255 10.1.1.2 10.1.1.1
+out on zx0 255 10.2.2.1 10.1.2.1
+out on zx0 255 10.2.2.2 10.1.2.1
+in on zx0 255 10.1.1.1 10.1.1.2
+in on zx0 255 10.1.1.2 10.1.1.1
+in on zx0 255 10.2.2.1 10.2.1.1
+in on zx0 255 10.2.2.2 10.2.1.1
+in on zx0 255 10.2.2.3 10.1.1.1
+in on zx0 255 10.2.3.4 10.2.2.2
+in on zx0 255 10.1.1.1 10.2.2.2
+in on zx0 255 10.1.1.2 10.2.2.2
+in on zx0 255 10.1.1.0 10.3.4.5
+in on zx0 255 10.1.1.1 10.3.4.5
+in on zx0 255 10.1.1.2 10.3.4.5
diff --git a/contrib/ipfilter/test/input/n12 b/contrib/ipfilter/test/input/n12
new file mode 100644
index 0000000..fb4d76d
--- /dev/null
+++ b/contrib/ipfilter/test/input/n12
@@ -0,0 +1,18 @@
+[out,le0=192.168.1.188]
+4510 0040 2020 4000 4006 17e1 c0a8 7e53
+c0a8 0303 12c2 0017 4e33 298e 0000 0000
+b002 4000 07af 0000 0204 05b4 0101 0402
+0103 0300 0101 080a 0c72 549e 0000 0000
+
+[in,le0]
+4500 003c 00b0 4000 fe06 f5fb c0a8 0303
+c0a8 01bc 0017 2710 f674 e02c 4e33 298f
+a012 2798 e317 0000 0101 080a 2c05 b797
+0c72 549e 0103 0300 0204 05b4
+
+[out,le0]
+4510 0034 493b 4000 4006 eed1 c0a8 7e53
+c0a8 0303 12c2 0017 4e33 298f f674 e02d
+8010 4000 8e2a 0000 0101 080a 0c72 549e
+2c05 b797
+
diff --git a/contrib/ipfilter/test/input/n4 b/contrib/ipfilter/test/input/n4
index 52c2d88..1218ef9 100644
--- a/contrib/ipfilter/test/input/n4
+++ b/contrib/ipfilter/test/input/n4
@@ -1,5 +1,10 @@
in on zx0 tcp 10.3.3.3,12345 10.1.1.1,23
+out on zx0 tcp 10.2.2.1,10023 10.3.3.3,12345
in on zx0 tcp 10.3.3.3,12345 10.1.1.1,53
-in on zx0 tcp 10.3.3.3,12345 10.1.0.0,23
+out on zx0 tcp 10.2.2.1,10053 10.3.3.3,12345
+in on zx0 tcp 10.3.3.3,12346 10.1.0.0,23
+out on zx0 tcp 10.2.2.1,10023 10.3.3.3,12346
in on zx0 udp 10.3.3.3,12345 10.1.1.0,53
+out on zx0 udp 10.2.2.1,10053 10.3.3.3,12345
in on zx0 tcp 10.3.3.3,12345 10.1.1.0,53
+out on zx0 tcp 10.2.2.1,53 10.3.3.3,12345
diff --git a/contrib/ipfilter/test/input/n8 b/contrib/ipfilter/test/input/n8
new file mode 100644
index 0000000..1f5b213
--- /dev/null
+++ b/contrib/ipfilter/test/input/n8
@@ -0,0 +1,30 @@
+#v tos len id off ttl p sum src dst
+# ICMP ECHO (ping) exchange
+[out,icmp0] 4500 0054 8bc1 0000 ff01 23dc 0202 0202 0404 0404
+0800 efdf 6220 0000 3f6f 6e80 000b
+0d02 0809 0a0b 0c0d 0e0f 1011 1213 1415
+1617 1819 1a1b 1c1d 1e1f 2021 2223 2425
+2627 2829 2a2b 2c2d 2e2f 3031 3233 3435
+3637
+
+[in,icmp0] 4500 0054 3fd5 4000 ff01 1fc1 0404 0404 0a0a 0a01
+0000 f7df 6220 0000 3f6f 6e80 000b
+0d02 0809 0a0b 0c0d 0e0f 1011 1213 1415
+1617 1819 1a1b 1c1d 1e1f 2021 2223 2425
+2627 2829 2a2b 2c2d 2e2f 3031 3233 3435
+3637
+
+[out,icmp0] 4500 0054 8bc1 0000 ff01 23dc 0202 0202 0404 0404
+0800 efde 6220 0001 3f6f 6e80 000b
+0d02 0809 0a0b 0c0d 0e0f 1011 1213 1415
+1617 1819 1a1b 1c1d 1e1f 2021 2223 2425
+2627 2829 2a2b 2c2d 2e2f 3031 3233 3435
+3637
+
+[in,icmp0] 4500 0054 3fd5 4000 ff01 1fc1 0404 0404 0a0a 0a01
+0000 f7de 6220 0001 3f6f 6e80 000b
+0d02 0809 0a0b 0c0d 0e0f 1011 1213 1415
+1617 1819 1a1b 1c1d 1e1f 2021 2223 2425
+2627 2829 2a2b 2c2d 2e2f 3031 3233 3435
+3637
+
diff --git a/contrib/ipfilter/test/input/n9 b/contrib/ipfilter/test/input/n9
new file mode 100644
index 0000000..c4aada8
--- /dev/null
+++ b/contrib/ipfilter/test/input/n9
@@ -0,0 +1,30 @@
+#v tos len id off ttl p sum src dst
+# ICMP ECHO (ping) exchange
+[in,icmp0] 4500 0054 8bc1 0000 ff01 23dc 0202 0202 0404 0404
+0800 efdf 6220 0000 3f6f 6e80 000b
+0d02 0809 0a0b 0c0d 0e0f 1011 1213 1415
+1617 1819 1a1b 1c1d 1e1f 2021 2223 2425
+2627 2829 2a2b 2c2d 2e2f 3031 3233 3435
+3637
+
+[out,icmp0] 4500 0054 3fd5 4000 ff01 23c5 0a0a 0a01 0202 0202
+0000 f7df 6220 0000 3f6f 6e80 000b
+0d02 0809 0a0b 0c0d 0e0f 1011 1213 1415
+1617 1819 1a1b 1c1d 1e1f 2021 2223 2425
+2627 2829 2a2b 2c2d 2e2f 3031 3233 3435
+3637
+
+[in,icmp0] 4500 0054 8bc1 0000 ff01 23dc 0202 0202 0404 0404
+0800 efde 6220 0001 3f6f 6e80 000b
+0d02 0809 0a0b 0c0d 0e0f 1011 1213 1415
+1617 1819 1a1b 1c1d 1e1f 2021 2223 2425
+2627 2829 2a2b 2c2d 2e2f 3031 3233 3435
+3637
+
+[out,icmp0] 4500 0054 3fd5 4000 ff01 23c5 0a0a 0a01 0202 0202
+0000 f7de 6220 0001 3f6f 6e80 000b
+0d02 0809 0a0b 0c0d 0e0f 1011 1213 1415
+1617 1819 1a1b 1c1d 1e1f 2021 2223 2425
+2627 2829 2a2b 2c2d 2e2f 3031 3233 3435
+3637
+
diff --git a/contrib/ipfilter/test/input/ni1 b/contrib/ipfilter/test/input/ni1
index dc2f05e..8f548d5 100644
--- a/contrib/ipfilter/test/input/ni1
+++ b/contrib/ipfilter/test/input/ni1
@@ -8,12 +8,13 @@
[in,df0]
4500 0038 809a 0000 ff01 2919 0303 0303
0606 0606 0b00 5f7b 0000 0000
-4500 0028 4706 4000 0111 1eac 0606 0606 0404 0404
-afc9 829e 0014 6308
+4500 0028 0000 4000 0111 65b2 0606 0606 0404 0404
+afc9 829e 0014 6308
[in,df0]
4500 0044 809a 0000 ff01 290d 0303 0303
0606 0606 0b00 0939 0000 0000
-4500 0028 4706 4000 0111 1eac 0606 0606 0404 0404
-afc9 829e 0014 6308 0402 0000 3be5 468d 000a cfc3
+4500 0028 0000 4000 0111 65b2 0606 0606 0404 0404
+afc9 829e 0014 6308
+0402 0000 3be5 468d 000a cfc3
diff --git a/contrib/ipfilter/test/input/ni10 b/contrib/ipfilter/test/input/ni10
index 041326f..48ac225 100644
--- a/contrib/ipfilter/test/input/ni10
+++ b/contrib/ipfilter/test/input/ni10
@@ -1,17 +1,21 @@
#v tos len id off ttl p sum src dst
# ICMP dest unreachable with 64 bits in payload (in reply to a TCP packet
# going out)
+# IP 4.4.4.4 2.2.2.2 TCP(20480,80)
[in,df0] 45 00 00 3c 47 06 40 00 ff 06 28 aa 04 04 04 04 02 02 02 02 50 00 00 50 00 00 00 01 00 00 00 00 a0 02 16 d0 d8 e2 00 00 02 04 05 b4 04 02 08 0a 00 47 fb b0 00 00 00 00 01 03 03 00
+# IP 3.3.3.3 -> 4.4.4.4 ICMP (IP(4.4.4.4,6.6.6.6) TCP(20480,80))
[out,df0]
4500 0038 809a 0000 ff01 2d1d 0303 0303 0404 0404
0303 acab 0000 0000
4500 003c 4706 4000 ff06 20a2 0404 0404 0606 0606
5000 0050 0000 0001
+# IP 3.3.3.3 -> 4.4.4.4 ICMP (IP(4.4.4.4,6.6.6.6) TCP(20480,80))
# ICMP dest unreachable with whole packet in payload (40 bytes = 320 bits)
[out,df0] 45 00 00 58 80 9a 00 00 ff 01 2c fd 03 03 03 03 04 04 04 04 03 03 11 3f 00 00 00 00 45 00 00 3c 47 06 40 00 ff 06 20 a2 04 04 04 04 06 06 06 06 50 00 00 50 00 00 00 01 00 00 00 00 a0 02 16 d0 d0 da 00 00 02 04 05 b4 04 02 08 0a 00 47 fb b0 00 00 00 00 01 03 03 00
+# IP 3.3.3.3 -> 4.4.4.4 ICMP (IP(4.4.4.4,6.6.6.6) TCP(20480,80))
[out,df0]
4500 0038 809a 0000 ff01 2b1b 0303 0303 0505 0505
0303 acab 0000 0000
diff --git a/contrib/ipfilter/test/input/ni12 b/contrib/ipfilter/test/input/ni12
new file mode 100644
index 0000000..788e603
--- /dev/null
+++ b/contrib/ipfilter/test/input/ni12
@@ -0,0 +1,24 @@
+#v tos len id off ttl p sum src dst
+# ICMP dest unreachable with 64 bits in payload (in reply to a TCP packet
+# going out)
+[in,df0] 45 00 00 3c 47 06 40 00 ff 06 20 aa 04 04 04 04 0a 02 02 02 50 00 05 00 00 00 00 01 00 00 00 00 a0 02 16 d0 cc 32 00 00 02 04 05 b4 04 02 08 0a 00 47 fb b0 00 00 00 00 01 03 03 00
+
+[out,df0]
+4500 0038 809a 0000 ff01 2d1d 0303 0303 0404 0404
+0303 0fa3 0000 0000
+4500 003c 4706 4000 ff06 2aac 0404 0404 0101 0101
+5000 9d58 0000 0001
+
+# ICMP dest unreachable with whole packet in payload (40 bytes = 320 bits)
+[out,df0]
+4500 0058 809a 0000 ff01 2cfd 0303 0303 0404 0404
+0303 0735 0000 0000
+4500 003c 4706 4000 ff06 2aac 0404 0404 0101 0101
+5000 9d58 0000 0001 0000 0000 a002 16d0 3ddc 0000
+0204 05b4 0402 080a 0047 fbb0 0000 0000 0103 0300
+
+[out,df0]
+4500 0038 809a 0000 ff01 2b1b 0303 0303 0505 0505
+0303 0fa3 0000 0000
+4500 003c 4706 4000 ff06 2aab 0404 0404 0101 0102 5000 9d58 0000 0001
+
diff --git a/contrib/ipfilter/test/input/ni13 b/contrib/ipfilter/test/input/ni13
new file mode 100644
index 0000000..56ddb79
--- /dev/null
+++ b/contrib/ipfilter/test/input/ni13
@@ -0,0 +1,235 @@
+# 23:18:36.130424 192.168.113.1.1511 > 192.168.113.3.1723: S 2884651685:2884651685(0) win 64240 <mss 1460,nop,nop,sackOK> (DF)
+[in,pcn1=192.168.113.3]
+4500 0030 5e11 4000 8006 3961 c0a8 7101
+c0a8 7103 05e7 06bb abf0 4aa5 0000 0000
+7002 faf0 21a1 0000 0204 05b4 0101 0402
+
+# 23:18:36.130778 192.168.113.3.1723 > 192.168.113.1.1511: S 2774821082:2774821082(0) ack 2884651686 win 32768 <mss 1460> (DF)
+[out,pcn1]
+4500 002c 69a6 4000 4006 6dd0 c0a8 7103
+c0a8 7101 06bb 05e7 a564 68da abf0 4aa6
+6012 8000 a348 0000 0204 05b4
+
+# 23:18:36.130784 192.168.113.1.1511 > 192.168.113.3.1723: P 1:157(156) ack 1 win 64240: pptp CTRL_MSGTYPE=SCCRQ PROTO_VER(1.0) FRAME_CAP(A) BEARER_CAP(A) MAX_CHAN(0) FIRM_REV(2600) HOSTNAME() VENDOR(Microsoft Windows NT) (DF)
+[in,pcn1]
+4500 00c4 5e12 4000 8006 38cc c0a8 7101
+c0a8 7103 05e7 06bb abf0 4aa6 a564 68db
+5018 faf0 e2a0 0000 009c 0001 1a2b 3c4d
+0001 0000 0100 0000 0000 0001 0000 0001
+0000 0a28 0000 0000 0000 0000 0000 0000
+0000 0000 0000 0000 0000 0000 0000 0000
+0000 0000 0000 0000 0000 0000 0000 0000
+0000 0000 0000 0000 0000 0000 0000 0000
+0000 0000 4d69 6372 6f73 6f66 7420 5769
+6e64 6f77 7320 4e54 0000 0000 0000 0000
+0000 0000 0000 0000 0000 0000 0000 0000
+0000 0000 0000 0000 0000 0000 0000 0000
+0000 0000
+
+# 23:18:36.260235 192.168.113.3.1723 > 192.168.113.1.1511: P 1:157(156) ack 157 win 33580: pptp CTRL_MSGTYPE=SCCRP PROTO_VER(1.0) RESULT_CODE(1) ERR_CODE(0) FRAME_CAP() BEARER_CAP() MAX_CHAN(1) FIRM_REV(1) HOSTNAME(local) VENDOR(linux) (DF)
+[out,pcn1]
+4500 00c4 69a7 4000 4006 6d37 c0a8 7103
+c0a8 7101 06bb 05e7 a564 68db abf0 4b42
+5018 832c cecf 0000 009c 0001 1a2b 3c4d
+0002 0000 0100 0100 0000 0000 0000 0000
+0001 0001 6c6f 6361 6c00 0000 0000 0000
+0000 0000 0000 0000 0000 0000 0000 0000
+0000 0000 0000 0000 0000 0000 0000 0000
+0000 0000 0000 0000 0000 0000 0000 0000
+0000 0000 6c69 6e75 7800 0000 0000 0000
+0000 0000 0000 0000 0000 0000 0000 0000
+0000 0000 0000 0000 0000 0000 0000 0000
+0000 0000 0000 0000 0000 0000 0000 0000
+0000 0000
+
+# 23:18:36.260252 192.168.113.1.1511 > 192.168.113.3.1723: P 157:325(168) ack 157 win 64084: pptp CTRL_MSGTYPE=OCRQ CALL_ID(16384) CALL_SER_NUM(4913) MIN_BPS(300) MAX_BPS(100000000) BEARER_TYPE(Any) FRAME_TYPE(E) RECV_WIN(64) PROC_DELAY(0) PHONE_NO_LEN(0) PHONE_NO() SUB_ADDR() (DF)
+[in,pcn1]
+4500 00d0 5e13 4000 8006 38bf c0a8 7101
+c0a8 7103 05e7 06bb abf0 4b42 a564 6977
+5018 fa54 ac07 0000 00a8 0001 1a2b 3c4d
+0007 0000 4000 1331 0000 012c 05f5 e100
+0000 0003 0000 0003 0040 0000 0000 0000
+0000 0000 0000 0000 0000 0000 0000 0000
+0000 0000 0000 0000 0000 0000 0000 0000
+0000 0000 0000 0000 0000 0000 0000 0000
+0000 0000 0000 0000 0000 0000 0000 0000
+0000 0000 0000 0000 0000 0000 0000 0000
+0000 0000 0000 0000 0000 0000 0000 0000
+0000 0000 0000 0000 0000 0000 0000 0000
+0000 0000 0000 0000 0000 0000 0000 0000
+
+# 23:18:36.272856 192.168.113.3.1723 > 192.168.113.1.1511: P 157:189(32) ack 325 win 33580: pptp CTRL_MSGTYPE=OCRP CALL_ID(0) PEER_CALL_ID(16384) RESULT_CODE(1) ERR_CODE(0) CAUSE_CODE(0) CONN_SPEED(100000000) RECV_WIN(64) PROC_DELAY(0) PHY_CHAN_ID(0) (DF)
+[out,pcn1]
+4500 0048 69a8 4000 4006 6db2 c0a8 7103
+c0a8 7101 06bb 05e7 a564 6977 abf0 4bea
+5018 832c 36fa 0000 0020 0001 1a2b 3c4d
+0008 0000 0000 4000 0100 0000 05f5 e100
+0040 0000 0000 0000
+
+# 23:18:36.321819 192.168.113.1.1511 > 192.168.113.3.1723: P 325:349(24) ack 189 win 64052: pptp CTRL_MSGTYPE=SLI PEER_CALL_ID(0) SEND_ACCM(0xffffffff) RECV_ACCM(0xffffffff) (DF)
+[in,pcn1]
+4500 0040 5e14 4000 8006 394e c0a8 7101
+c0a8 7103 05e7 06bb abf0 4bea a564 6997
+5018 fa34 e810 0000 0018 0001 1a2b 3c4d
+000f 0000 0000 0000 ffff ffff ffff ffff
+
+# 23:18:36.349759 192.168.113.1 > 192.168.113.3: gre [KSv1] ID:0000 S:0 ppp: LCP 25: Conf-Req(0), MRU=1400, Magic-Num=577f7c5b, PFC, ACFC, Call-Back CBCP
+[in,pcn1]
+4500 0039 5e15 0000 802f 792b c0a8 7101
+c0a8 7103 3001 880b 0019 0000 0000 0000
+ff03 c021 0100 0015 0104 0578 0506 577f
+7c5b 0702 0802 0d03 06
+
+# 23:18:36.389970 192.168.113.3 > 192.168.113.1: gre [KAv1] ID:4000 A:4294967295 [|gre]
+[out,pcn1]
+4500 0020 69a9 0000 ff2f eeaf c0a8 7103
+c0a8 7101 2081 880b 0000 4000 ffff ffff
+
+# 23:18:36.518426 192.168.113.3.1723 > 192.168.113.1.1511: . ack 349 win 33580 (DF)
+[out,pcn1]
+4500 0028 69aa 4000 4006 6dd0 c0a8 7103
+c0a8 7101 06bb 05e7 a564 6997 abf0 4c02
+5010 832c b5c1 0000
+
+# 23:18:36.555363 192.168.113.3 > 192.168.113.1: gre [KSv1] ID:4000 S:0 ppp: LCP 24: Conf-Req(1), ACCM=00000000, Magic-Num=22d90cfa, PFC, ACFC
+[out,pcn1]
+4500 0038 69ab 0000 ff2f ee95 c0a8 7103
+c0a8 7101 3001 880b 0018 4000 0000 0000
+ff03 c021 0101 0014 0206 0000 0000 0506
+22d9 0cfa 0702 0802
+
+# 23:18:36.556030 192.168.113.3 > 192.168.113.1: gre [KSAv1] ID:4000 S:1 A:0 ppp: LCP 11: Conf-Rej(0), Call-Back CBCP
+[out,pcn1]
+4500 002f 69ac 0000 ff2f ee9d c0a8 7103
+c0a8 7101 3081 880b 000b 4000 0000 0001
+0000 0000 ff03 c021 0400 0007 0d03 06
+
+# 23:18:36.557166 192.168.113.1 > 192.168.113.3: gre [KSAv1] ID:0000 S:1 A:1 ppp: LCP 24: Conf-Ack(1), ACCM=00000000, Magic-Num=22d90cfa, PFC, ACFC
+[in,pcn1]
+4500 003c 5e16 0000 802f 7927 c0a8 7101
+c0a8 7103 3081 880b 0018 0000 0000 0001
+0000 0001 ff03 c021 0201 0014 0206 0000
+0000 0506 22d9 0cfa 0702 0802
+
+# 23:18:36.557764 192.168.113.1 > 192.168.113.3: gre [KSv1] ID:0000 S:2 ppp: LCP 22: Conf-Req(1), MRU=1400, Magic-Num=577f7c5b, PFC, ACFC
+[in,pcn1]
+4500 0036 5e17 0000 802f 792c c0a8 7101
+c0a8 7103 3001 880b 0016 0000 0000 0002
+ff03 c021 0101 0012 0104 0578 0506 577f
+7c5b 0702 0802
+
+# 23:18:36.564658 192.168.113.3 > 192.168.113.1: gre [KSAv1] ID:4000 S:2 A:2 ppp: LCP 22: Conf-Ack(1), MRU=1400, Magic-Num=577f7c5b, PFC, ACFC
+[out,pcn1]
+4500 003a 69ad 0000 ff2f ee91 c0a8 7103
+c0a8 7101 3081 880b 0016 4000 0000 0002
+0000 0002 ff03 c021 0201 0012 0104 0578
+0506 577f 7c5b 0702 0802
+
+# 23:18:36.564803 192.168.113.3 > 192.168.113.1: gre [KSv1] ID:4000 S:3 ppp: IPCP 18: Conf-Req(1), IP-Addr=192.168.0.1, IP-Comp VJ-Comp
+[out,pcn1]
+4500 0032 69ae 0000 ff2f ee98 c0a8 7103
+c0a8 7101 3001 880b 0012 4000 0000 0003
+8021 0101 0010 0306 c0a8 0001 0206 002d
+0f01
+
+# 23:18:36.570395 192.168.113.1.1511 > 192.168.113.3.1723: P 349:373(24) ack 189 win 64052: pptp CTRL_MSGTYPE=SLI PEER_CALL_ID(0) SEND_ACCM(0x00000000) RECV_ACCM(0xffffffff) (DF)
+[in,pcn1]
+4500 0040 5e18 4000 8006 394a c0a8 7101
+c0a8 7103 05e7 06bb abf0 4c02 a564 6997
+5018 fa34 e7f8 0000 0018 0001 1a2b 3c4d
+000f 0000 0000 0000 0000 0000 ffff ffff
+
+# 23:18:36.573307 192.168.113.1 > 192.168.113.3: gre [KSAv1] ID:0000 S:3 A:3 ppp: LCP 20: Ident(2), Magic-Num=577f7c5b
+[in,pcn1]
+4500 0038 5e19 0000 802f 7928 c0a8 7101
+c0a8 7103 3081 880b 0014 0000 0000 0003
+0000 0003 c021 0c02 0012 577f 7c5b 4d53
+5241 5356 352e 3130
+
+# 23:18:36.573856 192.168.113.3 > 192.168.113.1: gre [KSAv1] ID:4000 S:4 A:3 ppp: LCP 26: Code-Rej(2)
+[out,pcn1]
+4500 003e 69af 0000 ff2f ee8b c0a8 7103
+c0a8 7101 3081 880b 001a 4000 0000 0004
+0000 0003 ff03 c021 0702 0016 0c02 0012
+577f 7c5b 4d53 5241 5356 352e 3130
+
+# 23:18:36.584936 192.168.113.1 > 192.168.113.3: gre [KSAv1] ID:0000 S:4 A:4 ppp: LCP 26: Ident(3), Magic-Num=577f7c5b
+[in,pcn1]
+4500 003e 5e1a 0000 802f 7921 c0a8 7101
+c0a8 7103 3081 880b 001a 0000 0000 0004
+0000 0004 c021 0c03 0018 577f 7c5b 4d53
+5241 532d 302d 434c 4159 4d4f 4f52
+
+# 23:18:36.585562 192.168.113.3 > 192.168.113.1: gre [KSAv1] ID:4000 S:5 A:4 ppp: LCP 32: Code-Rej(3)
+[out,pcn1]
+4500 0044 69b0 0000 ff2f ee84 c0a8 7103
+c0a8 7101 3081 880b 0020 4000 0000 0005
+0000 0004 ff03 c021 0703 001c 0c03 0018
+577f 7c5b 4d53 5241 532d 302d 434c 4159
+4d4f 4f52
+
+# 23:18:36.588721 192.168.113.1 > 192.168.113.3: gre [KSAv1] ID:0000 S:5 A:5 ppp: CCP 12: Conf-Req(4), MPPC
+[in,pcn1]
+4500 0030 5e1b 0000 802f 792e c0a8 7101
+c0a8 7103 3081 880b 000c 0000 0000 0005
+0000 0005 80fd 0104 000a 1206 0100 0001
+
+# 23:18:36.589445 192.168.113.3 > 192.168.113.1: gre [KSAv1] ID:4000 S:6 A:5 ppp: CCP 6: Conf-Req(1)
+[out,pcn1]
+4500 002a 69b1 0000 ff2f ee9d c0a8 7103
+c0a8 7101 3081 880b 0006 4000 0000 0006
+0000 0005 80fd 0101 0004
+
+# 23:18:36.589540 192.168.113.3 > 192.168.113.1: gre [KSv1] ID:4000 S:7 ppp: CCP 12: Conf-Rej(4), MPPC
+[out,pcn1]
+4500 002c 69b2 0000 ff2f ee9a c0a8 7103
+c0a8 7101 3001 880b 000c 4000 0000 0007
+80fd 0404 000a 1206 0100 0001
+
+# 23:18:36.590023 192.168.113.1 > 192.168.113.3: gre [KSAv1] ID:0000 S:6 A:7 ppp: IPCP 36: Conf-Req(5), IP-Addr=0.0.0.0, Pri-DNS=0.0.0.0, Pri-NBNS=0.0.0.0, Sec-DNS=0.0.0.0, Sec-NBNS=0.0.0.0
+[in,pcn1]
+4500 0048 5e1c 0000 802f 7915 c0a8 7101
+c0a8 7103 3081 880b 0024 0000 0000 0006
+0000 0007 8021 0105 0022 0306 0000 0000
+8106 0000 0000 8206 0000 0000 8306 0000
+0000 8406 0000 0000
+
+# 23:18:36.590489 192.168.113.3 > 192.168.113.1: gre [KSAv1] ID:4000 S:8 A:6 ppp: IPCP 30: Conf-Rej(5), Pri-DNS=0.0.0.0, Pri-NBNS=0.0.0.0, Sec-DNS=0.0.0.0, Sec-NBNS=0.0.0.0
+[out,pcn1]
+4500 0042 69b3 0000 ff2f ee83 c0a8 7103
+c0a8 7101 3081 880b 001e 4000 0000 0008
+0000 0006 8021 0405 001c 8106 0000 0000
+8206 0000 0000 8306 0000 0000 8406 0000
+0000
+
+# 23:18:36.591003 192.168.113.1 > 192.168.113.3: gre [KSAv1] ID:0000 S:7 A:8 ppp: IPCP 12: Conf-Rej(1), IP-Comp VJ-Comp
+[in,pcn1]
+4500 0030 5e1d 0000 802f 792c c0a8 7101
+c0a8 7103 3081 880b 000c 0000 0000 0007
+0000 0008 8021 0401 000a 0206 002d 0f01
+
+# 23:18:36.593819 192.168.113.3 > 192.168.113.1: gre [KSAv1] ID:4000 S:9 A:7 ppp: IPCP 12: Conf-Req(2), IP-Addr=192.168.0.1
+[out,pcn1]
+4500 0030 69b4 0000 ff2f ee94 c0a8 7103
+c0a8 7101 3081 880b 000c 4000 0000 0009
+0000 0007 8021 0102 000a 0306 c0a8 0001
+
+# 23:18:36.594840 192.168.113.1 > 192.168.113.3: gre [KSAv1] ID:0000 S:8 A:9 ppp: CCP 6: Conf-Ack(1)
+[in,pcn1]
+4500 002a 5e1e 0000 802f 7933 c0a8 7101
+c0a8 7103 3081 880b 0006 0000 0000 0008
+0000 0009 80fd 0201 0004 0000 0000
+
+# 23:18:36.595525 192.168.113.1 > 192.168.113.3: gre [KSv1] ID:0000 S:9 ppp: CCP 18: Term-Req(6)
+[in,pcn1]
+4500 0032 5e1f 0000 802f 792a c0a8 7101
+c0a8 7103 3001 880b 0012 0000 0000 0009
+80fd 0506 0010 577f 7c5b 003c cd74 0000
+02dc
+
+# 23:18:36.595937 192.168.113.3 > 192.168.113.1: gre [KSAv1] ID:4000 S:10 A:9 ppp: CCP 6: Term-Ack(6)
+[out,pcn1]
+4500 002a 69b5 0000 ff2f ee99 c0a8 7103
+c0a8 7101 3081 880b 0006 4000 0000 000a
+0000 0009 80fd 0606 0004
+
diff --git a/contrib/ipfilter/test/input/ni14 b/contrib/ipfilter/test/input/ni14
new file mode 100644
index 0000000..00f0290
--- /dev/null
+++ b/contrib/ipfilter/test/input/ni14
@@ -0,0 +1,235 @@
+# 23:18:36.130424 192.168.113.1.1511 > 192.168.113.3.1723: S 2884651685:2884651685(0) win 64240 <mss 1460,nop,nop,sackOK> (DF)
+[in,pcn1=192.168.113.3]
+4500 0030 5e11 4000 8006 3961 c0a8 7101
+c0a8 7103 05e7 06bb abf0 4aa5 0000 0000
+7002 faf0 21a1 0000 0204 05b4 0101 0402
+
+# 23:18:36.130778 192.168.113.3.1723 > 192.168.113.1.1511: S 2774821082:2774821082(0) ack 2884651686 win 32768 <mss 1460> (DF)
+[out,pcn1]
+4500 002c 69a6 4000 4006 207b 7f00 0001
+c0a8 7101 06bb 05e7 a564 68da abf0 4aa6
+6012 8000 55f3 0000 0204 05b4
+
+# 23:18:36.130784 192.168.113.1.1511 > 192.168.113.3.1723: P 1:157(156) ack 1 win 64240: pptp CTRL_MSGTYPE=SCCRQ PROTO_VER(1.0) FRAME_CAP(A) BEARER_CAP(A) MAX_CHAN(0) FIRM_REV(2600) HOSTNAME() VENDOR(Microsoft Windows NT) (DF)
+[in,pcn1]
+4500 00c4 5e12 4000 8006 38cc c0a8 7101
+c0a8 7103 05e7 06bb abf0 4aa6 a564 68db
+5018 faf0 e2a0 0000 009c 0001 1a2b 3c4d
+0001 0000 0100 0000 0000 0001 0000 0001
+0000 0a28 0000 0000 0000 0000 0000 0000
+0000 0000 0000 0000 0000 0000 0000 0000
+0000 0000 0000 0000 0000 0000 0000 0000
+0000 0000 0000 0000 0000 0000 0000 0000
+0000 0000 4d69 6372 6f73 6f66 7420 5769
+6e64 6f77 7320 4e54 0000 0000 0000 0000
+0000 0000 0000 0000 0000 0000 0000 0000
+0000 0000 0000 0000 0000 0000 0000 0000
+0000 0000
+
+# 23:18:36.260235 192.168.113.3.1723 > 192.168.113.1.1511: P 1:157(156) ack 157 win 33580: pptp CTRL_MSGTYPE=SCCRP PROTO_VER(1.0) RESULT_CODE(1) ERR_CODE(0) FRAME_CAP() BEARER_CAP() MAX_CHAN(1) FIRM_REV(1) HOSTNAME(local) VENDOR(linux) (DF)
+[out,pcn1]
+4500 00c4 69a7 4000 4006 1fe2 7f00 0001
+c0a8 7101 06bb 05e7 a564 68db abf0 4b42
+5018 832c 817a 0000 009c 0001 1a2b 3c4d
+0002 0000 0100 0100 0000 0000 0000 0000
+0001 0001 6c6f 6361 6c00 0000 0000 0000
+0000 0000 0000 0000 0000 0000 0000 0000
+0000 0000 0000 0000 0000 0000 0000 0000
+0000 0000 0000 0000 0000 0000 0000 0000
+0000 0000 6c69 6e75 7800 0000 0000 0000
+0000 0000 0000 0000 0000 0000 0000 0000
+0000 0000 0000 0000 0000 0000 0000 0000
+0000 0000 0000 0000 0000 0000 0000 0000
+0000 0000
+
+# 23:18:36.260252 192.168.113.1.1511 > 192.168.113.3.1723: P 157:325(168) ack 157 win 64084: pptp CTRL_MSGTYPE=OCRQ CALL_ID(16384) CALL_SER_NUM(4913) MIN_BPS(300) MAX_BPS(100000000) BEARER_TYPE(Any) FRAME_TYPE(E) RECV_WIN(64) PROC_DELAY(0) PHONE_NO_LEN(0) PHONE_NO() SUB_ADDR() (DF)
+[in,pcn1]
+4500 00d0 5e13 4000 8006 38bf c0a8 7101
+c0a8 7103 05e7 06bb abf0 4b42 a564 6977
+5018 fa54 ac07 0000 00a8 0001 1a2b 3c4d
+0007 0000 4000 1331 0000 012c 05f5 e100
+0000 0003 0000 0003 0040 0000 0000 0000
+0000 0000 0000 0000 0000 0000 0000 0000
+0000 0000 0000 0000 0000 0000 0000 0000
+0000 0000 0000 0000 0000 0000 0000 0000
+0000 0000 0000 0000 0000 0000 0000 0000
+0000 0000 0000 0000 0000 0000 0000 0000
+0000 0000 0000 0000 0000 0000 0000 0000
+0000 0000 0000 0000 0000 0000 0000 0000
+0000 0000 0000 0000 0000 0000 0000 0000
+
+# 23:18:36.272856 192.168.113.3.1723 > 192.168.113.1.1511: P 157:189(32) ack 325 win 33580: pptp CTRL_MSGTYPE=OCRP CALL_ID(0) PEER_CALL_ID(16384) RESULT_CODE(1) ERR_CODE(0) CAUSE_CODE(0) CONN_SPEED(100000000) RECV_WIN(64) PROC_DELAY(0) PHY_CHAN_ID(0) (DF)
+[out,pcn1]
+4500 0048 69a8 4000 4006 205d 7f00 0001
+c0a8 7101 06bb 05e7 a564 6977 abf0 4bea
+5018 832c e9a4 0000 0020 0001 1a2b 3c4d
+0008 0000 0000 4000 0100 0000 05f5 e100
+0040 0000 0000 0000
+
+# 23:18:36.321819 192.168.113.1.1511 > 192.168.113.3.1723: P 325:349(24) ack 189 win 64052: pptp CTRL_MSGTYPE=SLI PEER_CALL_ID(0) SEND_ACCM(0xffffffff) RECV_ACCM(0xffffffff) (DF)
+[in,pcn1]
+4500 0040 5e14 4000 8006 394e c0a8 7101
+c0a8 7103 05e7 06bb abf0 4bea a564 6997
+5018 fa34 e810 0000 0018 0001 1a2b 3c4d
+000f 0000 0000 0000 ffff ffff ffff ffff
+
+# 23:18:36.349759 192.168.113.1 > 192.168.113.3: gre [KSv1] ID:0000 S:0 ppp: LCP 25: Conf-Req(0), MRU=1400, Magic-Num=577f7c5b, PFC, ACFC, Call-Back CBCP
+[in,pcn1]
+4500 0039 5e15 0000 802f 792b c0a8 7101
+c0a8 7103 3001 880b 0019 0000 0000 0000
+ff03 c021 0100 0015 0104 0578 0506 577f
+7c5b 0702 0802 0d03 06
+
+# 23:18:36.389970 192.168.113.3 > 192.168.113.1: gre [KAv1] ID:4000 A:4294967295 [|gre]
+[out,pcn1]
+4500 0020 69a9 0000 ff2f a15a 7f00 0001
+c0a8 7101 2081 880b 0000 4000 ffff ffff
+
+# 23:18:36.518426 192.168.113.3.1723 > 192.168.113.1.1511: . ack 349 win 33580 (DF)
+[out,pcn1]
+4500 0028 69aa 4000 4006 207b 7f00 0001
+c0a8 7101 06bb 05e7 a564 6997 abf0 4c02
+5010 832c 686c 0000
+
+# 23:18:36.555363 192.168.113.3 > 192.168.113.1: gre [KSv1] ID:4000 S:0 ppp: LCP 24: Conf-Req(1), ACCM=00000000, Magic-Num=22d90cfa, PFC, ACFC
+[out,pcn1]
+4500 0038 69ab 0000 ff2f a140 7f00 0001
+c0a8 7101 3001 880b 0018 4000 0000 0000
+ff03 c021 0101 0014 0206 0000 0000 0506
+22d9 0cfa 0702 0802
+
+# 23:18:36.556030 192.168.113.3 > 192.168.113.1: gre [KSAv1] ID:4000 S:1 A:0 ppp: LCP 11: Conf-Rej(0), Call-Back CBCP
+[out,pcn1]
+4500 002f 69ac 0000 ff2f a148 7f00 0001
+c0a8 7101 3081 880b 000b 4000 0000 0001
+0000 0000 ff03 c021 0400 0007 0d03 06
+
+# 23:18:36.557166 192.168.113.1 > 192.168.113.3: gre [KSAv1] ID:0000 S:1 A:1 ppp: LCP 24: Conf-Ack(1), ACCM=00000000, Magic-Num=22d90cfa, PFC, ACFC
+[in,pcn1]
+4500 003c 5e16 0000 802f 7927 c0a8 7101
+c0a8 7103 3081 880b 0018 0000 0000 0001
+0000 0001 ff03 c021 0201 0014 0206 0000
+0000 0506 22d9 0cfa 0702 0802
+
+# 23:18:36.557764 192.168.113.1 > 192.168.113.3: gre [KSv1] ID:0000 S:2 ppp: LCP 22: Conf-Req(1), MRU=1400, Magic-Num=577f7c5b, PFC, ACFC
+[in,pcn1]
+4500 0036 5e17 0000 802f 792c c0a8 7101
+c0a8 7103 3001 880b 0016 0000 0000 0002
+ff03 c021 0101 0012 0104 0578 0506 577f
+7c5b 0702 0802
+
+# 23:18:36.564658 192.168.113.3 > 192.168.113.1: gre [KSAv1] ID:4000 S:2 A:2 ppp: LCP 22: Conf-Ack(1), MRU=1400, Magic-Num=577f7c5b, PFC, ACFC
+[out,pcn1]
+4500 003a 69ad 0000 ff2f a13c 7f00 0001
+c0a8 7101 3081 880b 0016 4000 0000 0002
+0000 0002 ff03 c021 0201 0012 0104 0578
+0506 577f 7c5b 0702 0802
+
+# 23:18:36.564803 192.168.113.3 > 192.168.113.1: gre [KSv1] ID:4000 S:3 ppp: IPCP 18: Conf-Req(1), IP-Addr=192.168.0.1, IP-Comp VJ-Comp
+[out,pcn1]
+4500 0032 69ae 0000 ff2f ee98 7f00 0001
+c0a8 7101 3001 880b 0012 4000 0000 0003
+8021 0101 0010 0306 c0a8 0001 0206 002d
+0f01
+
+# 23:18:36.570395 192.168.113.1.1511 > 192.168.113.3.1723: P 349:373(24) ack 189 win 64052: pptp CTRL_MSGTYPE=SLI PEER_CALL_ID(0) SEND_ACCM(0x00000000) RECV_ACCM(0xffffffff) (DF)
+[in,pcn1]
+4500 0040 5e18 4000 8006 394a c0a8 7101
+c0a8 7103 05e7 06bb abf0 4c02 a564 6997
+5018 fa34 e7f8 0000 0018 0001 1a2b 3c4d
+000f 0000 0000 0000 0000 0000 ffff ffff
+
+# 23:18:36.573307 192.168.113.1 > 192.168.113.3: gre [KSAv1] ID:0000 S:3 A:3 ppp: LCP 20: Ident(2), Magic-Num=577f7c5b
+[in,pcn1]
+4500 0038 5e19 0000 802f 7928 c0a8 7101
+c0a8 7103 3081 880b 0014 0000 0000 0003
+0000 0003 c021 0c02 0012 577f 7c5b 4d53
+5241 5356 352e 3130
+
+# 23:18:36.573856 192.168.113.3 > 192.168.113.1: gre [KSAv1] ID:4000 S:4 A:3 ppp: LCP 26: Code-Rej(2)
+[out,pcn1]
+4500 003e 69af 0000 ff2f ee8b 7f00 0001
+c0a8 7101 3081 880b 001a 4000 0000 0004
+0000 0003 ff03 c021 0702 0016 0c02 0012
+577f 7c5b 4d53 5241 5356 352e 3130
+
+# 23:18:36.584936 192.168.113.1 > 192.168.113.3: gre [KSAv1] ID:0000 S:4 A:4 ppp: LCP 26: Ident(3), Magic-Num=577f7c5b
+[in,pcn1]
+4500 003e 5e1a 0000 802f 7921 c0a8 7101
+c0a8 7103 3081 880b 001a 0000 0000 0004
+0000 0004 c021 0c03 0018 577f 7c5b 4d53
+5241 532d 302d 434c 4159 4d4f 4f52
+
+# 23:18:36.585562 192.168.113.3 > 192.168.113.1: gre [KSAv1] ID:4000 S:5 A:4 ppp: LCP 32: Code-Rej(3)
+[out,pcn1]
+4500 0044 69b0 0000 ff2f ee84 7f00 0001
+c0a8 7101 3081 880b 0020 4000 0000 0005
+0000 0004 ff03 c021 0703 001c 0c03 0018
+577f 7c5b 4d53 5241 532d 302d 434c 4159
+4d4f 4f52
+
+# 23:18:36.588721 192.168.113.1 > 192.168.113.3: gre [KSAv1] ID:0000 S:5 A:5 ppp: CCP 12: Conf-Req(4), MPPC
+[in,pcn1]
+4500 0030 5e1b 0000 802f 792e c0a8 7101
+c0a8 7103 3081 880b 000c 0000 0000 0005
+0000 0005 80fd 0104 000a 1206 0100 0001
+
+# 23:18:36.589445 192.168.113.3 > 192.168.113.1: gre [KSAv1] ID:4000 S:6 A:5 ppp: CCP 6: Conf-Req(1)
+[out,pcn1]
+4500 002a 69b1 0000 ff2f ee9d 7f00 0001
+c0a8 7101 3081 880b 0006 4000 0000 0006
+0000 0005 80fd 0101 0004
+
+# 23:18:36.589540 192.168.113.3 > 192.168.113.1: gre [KSv1] ID:4000 S:7 ppp: CCP 12: Conf-Rej(4), MPPC
+[out,pcn1]
+4500 002c 69b2 0000 ff2f ee9a 7f00 0001
+c0a8 7101 3001 880b 000c 4000 0000 0007
+80fd 0404 000a 1206 0100 0001
+
+# 23:18:36.590023 192.168.113.1 > 192.168.113.3: gre [KSAv1] ID:0000 S:6 A:7 ppp: IPCP 36: Conf-Req(5), IP-Addr=0.0.0.0, Pri-DNS=0.0.0.0, Pri-NBNS=0.0.0.0, Sec-DNS=0.0.0.0, Sec-NBNS=0.0.0.0
+[in,pcn1]
+4500 0048 5e1c 0000 802f 7915 c0a8 7101
+c0a8 7103 3081 880b 0024 0000 0000 0006
+0000 0007 8021 0105 0022 0306 0000 0000
+8106 0000 0000 8206 0000 0000 8306 0000
+0000 8406 0000 0000
+
+# 23:18:36.590489 192.168.113.3 > 192.168.113.1: gre [KSAv1] ID:4000 S:8 A:6 ppp: IPCP 30: Conf-Rej(5), Pri-DNS=0.0.0.0, Pri-NBNS=0.0.0.0, Sec-DNS=0.0.0.0, Sec-NBNS=0.0.0.0
+[out,pcn1]
+4500 0042 69b3 0000 ff2f ee83 7f00 0001
+c0a8 7101 3081 880b 001e 4000 0000 0008
+0000 0006 8021 0405 001c 8106 0000 0000
+8206 0000 0000 8306 0000 0000 8406 0000
+0000
+
+# 23:18:36.591003 192.168.113.1 > 192.168.113.3: gre [KSAv1] ID:0000 S:7 A:8 ppp: IPCP 12: Conf-Rej(1), IP-Comp VJ-Comp
+[in,pcn1]
+4500 0030 5e1d 0000 802f 792c c0a8 7101
+c0a8 7103 3081 880b 000c 0000 0000 0007
+0000 0008 8021 0401 000a 0206 002d 0f01
+
+# 23:18:36.593819 192.168.113.3 > 192.168.113.1: gre [KSAv1] ID:4000 S:9 A:7 ppp: IPCP 12: Conf-Req(2), IP-Addr=192.168.0.1
+[out,pcn1]
+4500 0030 69b4 0000 ff2f ee94 7f00 0001
+c0a8 7101 3081 880b 000c 4000 0000 0009
+0000 0007 8021 0102 000a 0306 c0a8 0001
+
+# 23:18:36.594840 192.168.113.1 > 192.168.113.3: gre [KSAv1] ID:0000 S:8 A:9 ppp: CCP 6: Conf-Ack(1)
+[in,pcn1]
+4500 002a 5e1e 0000 802f 7931 c0a8 7101
+c0a8 7103 3081 880b 0006 0000 0000 0008
+0000 0009 80fd 0201 0004 0000 0000
+
+# 23:18:36.595525 192.168.113.1 > 192.168.113.3: gre [KSv1] ID:0000 S:9 ppp: CCP 18: Term-Req(6)
+[in,pcn1]
+4500 0032 5e1f 0000 802f 7928 c0a8 7101
+c0a8 7103 3001 880b 0012 0000 0000 0009
+80fd 0506 0010 577f 7c5b 003c cd74 0000
+02dc
+
+# 23:18:36.595937 192.168.113.3 > 192.168.113.1: gre [KSAv1] ID:4000 S:10 A:9 ppp: CCP 6: Term-Ack(6)
+[out,pcn1]
+4500 002a 69b5 0000 ff2f ee99 7f00 0001
+c0a8 7101 3081 880b 0006 4000 0000 000a
+0000 0009 80fd 0606 0004
+
diff --git a/contrib/ipfilter/test/input/ni15 b/contrib/ipfilter/test/input/ni15
new file mode 100644
index 0000000..fb445bb
--- /dev/null
+++ b/contrib/ipfilter/test/input/ni15
@@ -0,0 +1,235 @@
+# 23:18:36.130424 192.168.113.1.1511 > 192.168.113.3.1723: S 2884651685:2884651685(0) win 64240 <mss 1460,nop,nop,sackOK> (DF)
+[out,pcn1=192.168.113.3]
+4500 0030 5e11 4000 8006 3961 c0a8 7101
+c0a8 7103 05e7 06bb abf0 4aa5 0000 0000
+7002 faf0 21a1 0000 0204 05b4 0101 0402
+
+# 23:18:36.130778 192.168.113.3.1723 > 192.168.113.1.1511: S 2774821082:2774821082(0) ack 2884651686 win 32768 <mss 1460> (DF)
+[in,pcn1]
+4500 002c 69a6 4000 4006 6dd0 c0a8 7103
+c0a8 7101 06bb 05e7 a564 68da abf0 4aa6
+6012 8000 a348 0000 0204 05b4
+
+# 23:18:36.130784 192.168.113.1.1511 > 192.168.113.3.1723: P 1:157(156) ack 1 win 64240: pptp CTRL_MSGTYPE=SCCRQ PROTO_VER(1.0) FRAME_CAP(A) BEARER_CAP(A) MAX_CHAN(0) FIRM_REV(2600) HOSTNAME() VENDOR(Microsoft Windows NT) (DF)
+[out,pcn1]
+4500 00c4 5e12 4000 8006 38cc c0a8 7101
+c0a8 7103 05e7 06bb abf0 4aa6 a564 68db
+5018 faf0 e2a0 0000 009c 0001 1a2b 3c4d
+0001 0000 0100 0000 0000 0001 0000 0001
+0000 0a28 0000 0000 0000 0000 0000 0000
+0000 0000 0000 0000 0000 0000 0000 0000
+0000 0000 0000 0000 0000 0000 0000 0000
+0000 0000 0000 0000 0000 0000 0000 0000
+0000 0000 4d69 6372 6f73 6f66 7420 5769
+6e64 6f77 7320 4e54 0000 0000 0000 0000
+0000 0000 0000 0000 0000 0000 0000 0000
+0000 0000 0000 0000 0000 0000 0000 0000
+0000 0000
+
+# 23:18:36.260235 192.168.113.3.1723 > 192.168.113.1.1511: P 1:157(156) ack 157 win 33580: pptp CTRL_MSGTYPE=SCCRP PROTO_VER(1.0) RESULT_CODE(1) ERR_CODE(0) FRAME_CAP() BEARER_CAP() MAX_CHAN(1) FIRM_REV(1) HOSTNAME(local) VENDOR(linux) (DF)
+[in,pcn1]
+4500 00c4 69a7 4000 4006 6d37 c0a8 7103
+c0a8 7101 06bb 05e7 a564 68db abf0 4b42
+5018 832c cecf 0000 009c 0001 1a2b 3c4d
+0002 0000 0100 0100 0000 0000 0000 0000
+0001 0001 6c6f 6361 6c00 0000 0000 0000
+0000 0000 0000 0000 0000 0000 0000 0000
+0000 0000 0000 0000 0000 0000 0000 0000
+0000 0000 0000 0000 0000 0000 0000 0000
+0000 0000 6c69 6e75 7800 0000 0000 0000
+0000 0000 0000 0000 0000 0000 0000 0000
+0000 0000 0000 0000 0000 0000 0000 0000
+0000 0000 0000 0000 0000 0000 0000 0000
+0000 0000
+
+# 23:18:36.260252 192.168.113.1.1511 > 192.168.113.3.1723: P 157:325(168) ack 157 win 64084: pptp CTRL_MSGTYPE=OCRQ CALL_ID(16384) CALL_SER_NUM(4913) MIN_BPS(300) MAX_BPS(100000000) BEARER_TYPE(Any) FRAME_TYPE(E) RECV_WIN(64) PROC_DELAY(0) PHONE_NO_LEN(0) PHONE_NO() SUB_ADDR() (DF)
+[out,pcn1]
+4500 00d0 5e13 4000 8006 38bf c0a8 7101
+c0a8 7103 05e7 06bb abf0 4b42 a564 6977
+5018 fa54 ac07 0000 00a8 0001 1a2b 3c4d
+0007 0000 4000 1331 0000 012c 05f5 e100
+0000 0003 0000 0003 0040 0000 0000 0000
+0000 0000 0000 0000 0000 0000 0000 0000
+0000 0000 0000 0000 0000 0000 0000 0000
+0000 0000 0000 0000 0000 0000 0000 0000
+0000 0000 0000 0000 0000 0000 0000 0000
+0000 0000 0000 0000 0000 0000 0000 0000
+0000 0000 0000 0000 0000 0000 0000 0000
+0000 0000 0000 0000 0000 0000 0000 0000
+0000 0000 0000 0000 0000 0000 0000 0000
+
+# 23:18:36.272856 192.168.113.3.1723 > 192.168.113.1.1511: P 157:189(32) ack 325 win 33580: pptp CTRL_MSGTYPE=OCRP CALL_ID(0) PEER_CALL_ID(16384) RESULT_CODE(1) ERR_CODE(0) CAUSE_CODE(0) CONN_SPEED(100000000) RECV_WIN(64) PROC_DELAY(0) PHY_CHAN_ID(0) (DF)
+[in,pcn1]
+4500 0048 69a8 4000 4006 6db2 c0a8 7103
+c0a8 7101 06bb 05e7 a564 6977 abf0 4bea
+5018 832c 36fa 0000 0020 0001 1a2b 3c4d
+0008 0000 0000 4000 0100 0000 05f5 e100
+0040 0000 0000 0000
+
+# 23:18:36.321819 192.168.113.1.1511 > 192.168.113.3.1723: P 325:349(24) ack 189 win 64052: pptp CTRL_MSGTYPE=SLI PEER_CALL_ID(0) SEND_ACCM(0xffffffff) RECV_ACCM(0xffffffff) (DF)
+[out,pcn1]
+4500 0040 5e14 4000 8006 394e c0a8 7101
+c0a8 7103 05e7 06bb abf0 4bea a564 6997
+5018 fa34 e810 0000 0018 0001 1a2b 3c4d
+000f 0000 0000 0000 ffff ffff ffff ffff
+
+# 23:18:36.349759 192.168.113.1 > 192.168.113.3: gre [KSv1] ID:0000 S:0 ppp: LCP 25: Conf-Req(0), MRU=1400, Magic-Num=577f7c5b, PFC, ACFC, Call-Back CBCP
+[out,pcn1]
+4500 0039 5e15 0000 802f 792b c0a8 7101
+c0a8 7103 3001 880b 0019 0000 0000 0000
+ff03 c021 0100 0015 0104 0578 0506 577f
+7c5b 0702 0802 0d03 06
+
+# 23:18:36.389970 192.168.113.3 > 192.168.113.1: gre [KAv1] ID:4000 A:4294967295 [|gre]
+[in,pcn1]
+4500 0020 69a9 0000 ff2f eeaf c0a8 7103
+c0a8 7101 2081 880b 0000 4000 ffff ffff
+
+# 23:18:36.518426 192.168.113.3.1723 > 192.168.113.1.1511: . ack 349 win 33580 (DF)
+[in,pcn1]
+4500 0028 69aa 4000 4006 6dd0 c0a8 7103
+c0a8 7101 06bb 05e7 a564 6997 abf0 4c02
+5010 832c b5c1 0000
+
+# 23:18:36.555363 192.168.113.3 > 192.168.113.1: gre [KSv1] ID:4000 S:0 ppp: LCP 24: Conf-Req(1), ACCM=00000000, Magic-Num=22d90cfa, PFC, ACFC
+[in,pcn1]
+4500 0038 69ab 0000 ff2f ee95 c0a8 7103
+c0a8 7101 3001 880b 0018 4000 0000 0000
+ff03 c021 0101 0014 0206 0000 0000 0506
+22d9 0cfa 0702 0802
+
+# 23:18:36.556030 192.168.113.3 > 192.168.113.1: gre [KSAv1] ID:4000 S:1 A:0 ppp: LCP 11: Conf-Rej(0), Call-Back CBCP
+[in,pcn1]
+4500 002f 69ac 0000 ff2f ee9d c0a8 7103
+c0a8 7101 3081 880b 000b 4000 0000 0001
+0000 0000 ff03 c021 0400 0007 0d03 06
+
+# 23:18:36.557166 192.168.113.1 > 192.168.113.3: gre [KSAv1] ID:0000 S:1 A:1 ppp: LCP 24: Conf-Ack(1), ACCM=00000000, Magic-Num=22d90cfa, PFC, ACFC
+[out,pcn1]
+4500 003c 5e16 0000 802f 7927 c0a8 7101
+c0a8 7103 3081 880b 0018 0000 0000 0001
+0000 0001 ff03 c021 0201 0014 0206 0000
+0000 0506 22d9 0cfa 0702 0802
+
+# 23:18:36.557764 192.168.113.1 > 192.168.113.3: gre [KSv1] ID:0000 S:2 ppp: LCP 22: Conf-Req(1), MRU=1400, Magic-Num=577f7c5b, PFC, ACFC
+[out,pcn1]
+4500 0036 5e17 0000 802f 792c c0a8 7101
+c0a8 7103 3001 880b 0016 0000 0000 0002
+ff03 c021 0101 0012 0104 0578 0506 577f
+7c5b 0702 0802
+
+# 23:18:36.564658 192.168.113.3 > 192.168.113.1: gre [KSAv1] ID:4000 S:2 A:2 ppp: LCP 22: Conf-Ack(1), MRU=1400, Magic-Num=577f7c5b, PFC, ACFC
+[in,pcn1]
+4500 003a 69ad 0000 ff2f ee91 c0a8 7103
+c0a8 7101 3081 880b 0016 4000 0000 0002
+0000 0002 ff03 c021 0201 0012 0104 0578
+0506 577f 7c5b 0702 0802
+
+# 23:18:36.564803 192.168.113.3 > 192.168.113.1: gre [KSv1] ID:4000 S:3 ppp: IPCP 18: Conf-Req(1), IP-Addr=192.168.0.1, IP-Comp VJ-Comp
+[in,pcn1]
+4500 0032 69ae 0000 ff2f ee98 c0a8 7103
+c0a8 7101 3001 880b 0012 4000 0000 0003
+8021 0101 0010 0306 c0a8 0001 0206 002d
+0f01
+
+# 23:18:36.570395 192.168.113.1.1511 > 192.168.113.3.1723: P 349:373(24) ack 189 win 64052: pptp CTRL_MSGTYPE=SLI PEER_CALL_ID(0) SEND_ACCM(0x00000000) RECV_ACCM(0xffffffff) (DF)
+[out,pcn1]
+4500 0040 5e18 4000 8006 394a c0a8 7101
+c0a8 7103 05e7 06bb abf0 4c02 a564 6997
+5018 fa34 e7f8 0000 0018 0001 1a2b 3c4d
+000f 0000 0000 0000 0000 0000 ffff ffff
+
+# 23:18:36.573307 192.168.113.1 > 192.168.113.3: gre [KSAv1] ID:0000 S:3 A:3 ppp: LCP 20: Ident(2), Magic-Num=577f7c5b
+[out,pcn1]
+4500 0038 5e19 0000 802f 7928 c0a8 7101
+c0a8 7103 3081 880b 0014 0000 0000 0003
+0000 0003 c021 0c02 0012 577f 7c5b 4d53
+5241 5356 352e 3130
+
+# 23:18:36.573856 192.168.113.3 > 192.168.113.1: gre [KSAv1] ID:4000 S:4 A:3 ppp: LCP 26: Code-Rej(2)
+[in,pcn1]
+4500 003e 69af 0000 ff2f ee8b c0a8 7103
+c0a8 7101 3081 880b 001a 4000 0000 0004
+0000 0003 ff03 c021 0702 0016 0c02 0012
+577f 7c5b 4d53 5241 5356 352e 3130
+
+# 23:18:36.584936 192.168.113.1 > 192.168.113.3: gre [KSAv1] ID:0000 S:4 A:4 ppp: LCP 26: Ident(3), Magic-Num=577f7c5b
+[out,pcn1]
+4500 003e 5e1a 0000 802f 7921 c0a8 7101
+c0a8 7103 3081 880b 001a 0000 0000 0004
+0000 0004 c021 0c03 0018 577f 7c5b 4d53
+5241 532d 302d 434c 4159 4d4f 4f52
+
+# 23:18:36.585562 192.168.113.3 > 192.168.113.1: gre [KSAv1] ID:4000 S:5 A:4 ppp: LCP 32: Code-Rej(3)
+[in,pcn1]
+4500 0044 69b0 0000 ff2f ee84 c0a8 7103
+c0a8 7101 3081 880b 0020 4000 0000 0005
+0000 0004 ff03 c021 0703 001c 0c03 0018
+577f 7c5b 4d53 5241 532d 302d 434c 4159
+4d4f 4f52
+
+# 23:18:36.588721 192.168.113.1 > 192.168.113.3: gre [KSAv1] ID:0000 S:5 A:5 ppp: CCP 12: Conf-Req(4), MPPC
+[out,pcn1]
+4500 0030 5e1b 0000 802f 792e c0a8 7101
+c0a8 7103 3081 880b 000c 0000 0000 0005
+0000 0005 80fd 0104 000a 1206 0100 0001
+
+# 23:18:36.589445 192.168.113.3 > 192.168.113.1: gre [KSAv1] ID:4000 S:6 A:5 ppp: CCP 6: Conf-Req(1)
+[in,pcn1]
+4500 002a 69b1 0000 ff2f ee9d c0a8 7103
+c0a8 7101 3081 880b 0006 4000 0000 0006
+0000 0005 80fd 0101 0004
+
+# 23:18:36.589540 192.168.113.3 > 192.168.113.1: gre [KSv1] ID:4000 S:7 ppp: CCP 12: Conf-Rej(4), MPPC
+[in,pcn1]
+4500 002c 69b2 0000 ff2f ee9a c0a8 7103
+c0a8 7101 3001 880b 000c 4000 0000 0007
+80fd 0404 000a 1206 0100 0001
+
+# 23:18:36.590023 192.168.113.1 > 192.168.113.3: gre [KSAv1] ID:0000 S:6 A:7 ppp: IPCP 36: Conf-Req(5), IP-Addr=0.0.0.0, Pri-DNS=0.0.0.0, Pri-NBNS=0.0.0.0, Sec-DNS=0.0.0.0, Sec-NBNS=0.0.0.0
+[out,pcn1]
+4500 0048 5e1c 0000 802f 7915 c0a8 7101
+c0a8 7103 3081 880b 0024 0000 0000 0006
+0000 0007 8021 0105 0022 0306 0000 0000
+8106 0000 0000 8206 0000 0000 8306 0000
+0000 8406 0000 0000
+
+# 23:18:36.590489 192.168.113.3 > 192.168.113.1: gre [KSAv1] ID:4000 S:8 A:6 ppp: IPCP 30: Conf-Rej(5), Pri-DNS=0.0.0.0, Pri-NBNS=0.0.0.0, Sec-DNS=0.0.0.0, Sec-NBNS=0.0.0.0
+[in,pcn1]
+4500 0042 69b3 0000 ff2f ee83 c0a8 7103
+c0a8 7101 3081 880b 001e 4000 0000 0008
+0000 0006 8021 0405 001c 8106 0000 0000
+8206 0000 0000 8306 0000 0000 8406 0000
+0000
+
+# 23:18:36.591003 192.168.113.1 > 192.168.113.3: gre [KSAv1] ID:0000 S:7 A:8 ppp: IPCP 12: Conf-Rej(1), IP-Comp VJ-Comp
+[out,pcn1]
+4500 0030 5e1d 0000 802f 792c c0a8 7101
+c0a8 7103 3081 880b 000c 0000 0000 0007
+0000 0008 8021 0401 000a 0206 002d 0f01
+
+# 23:18:36.593819 192.168.113.3 > 192.168.113.1: gre [KSAv1] ID:4000 S:9 A:7 ppp: IPCP 12: Conf-Req(2), IP-Addr=192.168.0.1
+[in,pcn1]
+4500 0030 69b4 0000 ff2f ee94 c0a8 7103
+c0a8 7101 3081 880b 000c 4000 0000 0009
+0000 0007 8021 0102 000a 0306 c0a8 0001
+
+# 23:18:36.594840 192.168.113.1 > 192.168.113.3: gre [KSAv1] ID:0000 S:8 A:9 ppp: CCP 6: Conf-Ack(1)
+[out,pcn1]
+4500 002a 5e1e 0000 802f 7931 c0a8 7101
+c0a8 7103 3081 880b 0006 0000 0000 0008
+0000 0009 80fd 0201 0004 0000 0000
+
+# 23:18:36.595525 192.168.113.1 > 192.168.113.3: gre [KSv1] ID:0000 S:9 ppp: CCP 18: Term-Req(6)
+[out,pcn1]
+4500 0032 5e1f 0000 802f 7928 c0a8 7101
+c0a8 7103 3001 880b 0012 0000 0000 0009
+80fd 0506 0010 577f 7c5b 003c cd74 0000
+02dc
+
+# 23:18:36.595937 192.168.113.3 > 192.168.113.1: gre [KSAv1] ID:4000 S:10 A:9 ppp: CCP 6: Term-Ack(6)
+[in,pcn1]
+4500 002a 69b5 0000 ff2f ee99 c0a8 7103
+c0a8 7101 3081 880b 0006 4000 0000 000a
+0000 0009 80fd 0606 0004
+
diff --git a/contrib/ipfilter/test/input/ni16 b/contrib/ipfilter/test/input/ni16
new file mode 100644
index 0000000..b1cc521
--- /dev/null
+++ b/contrib/ipfilter/test/input/ni16
@@ -0,0 +1,235 @@
+# 23:18:36.130424 192.168.113.1.1511 > 192.168.113.3.1723: S 2884651685:2884651685(0) win 64240 <mss 1460,nop,nop,sackOK> (DF)
+[out,pcn1=192.168.113.1]
+4500 0030 5e11 4000 8006 5f07 0a02 0202
+c0a8 7103 05e7 06bb abf0 4aa5 0000 0000
+7002 faf0 4747 0000 0204 05b4 0101 0402
+
+# 23:18:36.130778 192.168.113.3.1723 > 192.168.113.1.1511: S 2774821082:2774821082(0) ack 2884651686 win 32768 <mss 1460> (DF)
+[in,pcn1]
+4500 002c 69a6 4000 4006 6dd0 c0a8 7103
+c0a8 7101 06bb 05e7 a564 68da abf0 4aa6
+6012 8000 a348 0000 0204 05b4
+
+# 23:18:36.130784 192.168.113.1.1511 > 192.168.113.3.1723: P 1:157(156) ack 1 win 64240: pptp CTRL_MSGTYPE=SCCRQ PROTO_VER(1.0) FRAME_CAP(A) BEARER_CAP(A) MAX_CHAN(0) FIRM_REV(2600) HOSTNAME() VENDOR(Microsoft Windows NT) (DF)
+[out,pcn1]
+4500 00c4 5e12 4000 8006 5e72 0a02 0202
+c0a8 7103 05e7 06bb abf0 4aa6 a564 68db
+5018 faf0 0847 0000 009c 0001 1a2b 3c4d
+0001 0000 0100 0000 0000 0001 0000 0001
+0000 0a28 0000 0000 0000 0000 0000 0000
+0000 0000 0000 0000 0000 0000 0000 0000
+0000 0000 0000 0000 0000 0000 0000 0000
+0000 0000 0000 0000 0000 0000 0000 0000
+0000 0000 4d69 6372 6f73 6f66 7420 5769
+6e64 6f77 7320 4e54 0000 0000 0000 0000
+0000 0000 0000 0000 0000 0000 0000 0000
+0000 0000 0000 0000 0000 0000 0000 0000
+0000 0000
+
+# 23:18:36.260235 192.168.113.3.1723 > 192.168.113.1.1511: P 1:157(156) ack 157 win 33580: pptp CTRL_MSGTYPE=SCCRP PROTO_VER(1.0) RESULT_CODE(1) ERR_CODE(0) FRAME_CAP() BEARER_CAP() MAX_CHAN(1) FIRM_REV(1) HOSTNAME(local) VENDOR(linux) (DF)
+[in,pcn1]
+4500 00c4 69a7 4000 4006 6d37 c0a8 7103
+c0a8 7101 06bb 05e7 a564 68db abf0 4b42
+5018 832c cecf 0000 009c 0001 1a2b 3c4d
+0002 0000 0100 0100 0000 0000 0000 0000
+0001 0001 6c6f 6361 6c00 0000 0000 0000
+0000 0000 0000 0000 0000 0000 0000 0000
+0000 0000 0000 0000 0000 0000 0000 0000
+0000 0000 0000 0000 0000 0000 0000 0000
+0000 0000 6c69 6e75 7800 0000 0000 0000
+0000 0000 0000 0000 0000 0000 0000 0000
+0000 0000 0000 0000 0000 0000 0000 0000
+0000 0000 0000 0000 0000 0000 0000 0000
+0000 0000
+
+# 23:18:36.260252 192.168.113.1.1511 > 192.168.113.3.1723: P 157:325(168) ack 157 win 64084: pptp CTRL_MSGTYPE=OCRQ CALL_ID(16384) CALL_SER_NUM(4913) MIN_BPS(300) MAX_BPS(100000000) BEARER_TYPE(Any) FRAME_TYPE(E) RECV_WIN(64) PROC_DELAY(0) PHONE_NO_LEN(0) PHONE_NO() SUB_ADDR() (DF)
+[out,pcn1]
+4500 00d0 5e13 4000 8006 5e65 0a02 0202
+c0a8 7103 05e7 06bb abf0 4b42 a564 6977
+5018 fa54 d1ad 0000 00a8 0001 1a2b 3c4d
+0007 0000 4000 1331 0000 012c 05f5 e100
+0000 0003 0000 0003 0040 0000 0000 0000
+0000 0000 0000 0000 0000 0000 0000 0000
+0000 0000 0000 0000 0000 0000 0000 0000
+0000 0000 0000 0000 0000 0000 0000 0000
+0000 0000 0000 0000 0000 0000 0000 0000
+0000 0000 0000 0000 0000 0000 0000 0000
+0000 0000 0000 0000 0000 0000 0000 0000
+0000 0000 0000 0000 0000 0000 0000 0000
+0000 0000 0000 0000 0000 0000 0000 0000
+
+# 23:18:36.272856 192.168.113.3.1723 > 192.168.113.1.1511: P 157:189(32) ack 325 win 33580: pptp CTRL_MSGTYPE=OCRP CALL_ID(0) PEER_CALL_ID(16384) RESULT_CODE(1) ERR_CODE(0) CAUSE_CODE(0) CONN_SPEED(100000000) RECV_WIN(64) PROC_DELAY(0) PHY_CHAN_ID(0) (DF)
+[in,pcn1]
+4500 0048 69a8 4000 4006 6db2 c0a8 7103
+c0a8 7101 06bb 05e7 a564 6977 abf0 4bea
+5018 832c 36fa 0000 0020 0001 1a2b 3c4d
+0008 0000 0000 4000 0100 0000 05f5 e100
+0040 0000 0000 0000
+
+# 23:18:36.321819 192.168.113.1.1511 > 192.168.113.3.1723: P 325:349(24) ack 189 win 64052: pptp CTRL_MSGTYPE=SLI PEER_CALL_ID(0) SEND_ACCM(0xffffffff) RECV_ACCM(0xffffffff) (DF)
+[out,pcn1]
+4500 0040 5e14 4000 8006 5ef4 0a02 0202
+c0a8 7103 05e7 06bb abf0 4bea a564 6997
+5018 fa34 0db7 0000 0018 0001 1a2b 3c4d
+000f 0000 0000 0000 ffff ffff ffff ffff
+
+# 23:18:36.349759 192.168.113.1 > 192.168.113.3: gre [KSv1] ID:0000 S:0 ppp: LCP 25: Conf-Req(0), MRU=1400, Magic-Num=577f7c5b, PFC, ACFC, Call-Back CBCP
+[out,pcn1]
+4500 0039 5e15 0000 802f 9ed1 0a02 0202
+c0a8 7103 3001 880b 0019 0000 0000 0000
+ff03 c021 0100 0015 0104 0578 0506 577f
+7c5b 0702 0802 0d03 06
+
+# 23:18:36.389970 192.168.113.3 > 192.168.113.1: gre [KAv1] ID:4000 A:4294967295 [|gre]
+[in,pcn1]
+4500 0020 69a9 0000 ff2f eeaf c0a8 7103
+c0a8 7101 2081 880b 0000 4000 ffff ffff
+
+# 23:18:36.518426 192.168.113.3.1723 > 192.168.113.1.1511: . ack 349 win 33580 (DF)
+[in,pcn1]
+4500 0028 69aa 4000 4006 6dd0 c0a8 7103
+c0a8 7101 06bb 05e7 a564 6997 abf0 4c02
+5010 832c b5c1 0000
+
+# 23:18:36.555363 192.168.113.3 > 192.168.113.1: gre [KSv1] ID:4000 S:0 ppp: LCP 24: Conf-Req(1), ACCM=00000000, Magic-Num=22d90cfa, PFC, ACFC
+[in,pcn1]
+4500 0038 69ab 0000 ff2f ee95 c0a8 7103
+c0a8 7101 3001 880b 0018 4000 0000 0000
+ff03 c021 0101 0014 0206 0000 0000 0506
+22d9 0cfa 0702 0802
+
+# 23:18:36.556030 192.168.113.3 > 192.168.113.1: gre [KSAv1] ID:4000 S:1 A:0 ppp: LCP 11: Conf-Rej(0), Call-Back CBCP
+[in,pcn1]
+4500 002f 69ac 0000 ff2f ee9d c0a8 7103
+c0a8 7101 3081 880b 000b 4000 0000 0001
+0000 0000 ff03 c021 0400 0007 0d03 06
+
+# 23:18:36.557166 192.168.113.1 > 192.168.113.3: gre [KSAv1] ID:0000 S:1 A:1 ppp: LCP 24: Conf-Ack(1), ACCM=00000000, Magic-Num=22d90cfa, PFC, ACFC
+[out,pcn1]
+4500 003c 5e16 0000 802f 9ecd 0a02 0202
+c0a8 7103 3081 880b 0018 0000 0000 0001
+0000 0001 ff03 c021 0201 0014 0206 0000
+0000 0506 22d9 0cfa 0702 0802
+
+# 23:18:36.557764 192.168.113.1 > 192.168.113.3: gre [KSv1] ID:0000 S:2 ppp: LCP 22: Conf-Req(1), MRU=1400, Magic-Num=577f7c5b, PFC, ACFC
+[out,pcn1]
+4500 0036 5e17 0000 802f 9ed2 0a02 0202
+c0a8 7103 3001 880b 0016 0000 0000 0002
+ff03 c021 0101 0012 0104 0578 0506 577f
+7c5b 0702 0802
+
+# 23:18:36.564658 192.168.113.3 > 192.168.113.1: gre [KSAv1] ID:4000 S:2 A:2 ppp: LCP 22: Conf-Ack(1), MRU=1400, Magic-Num=577f7c5b, PFC, ACFC
+[in,pcn1]
+4500 003a 69ad 0000 ff2f ee91 c0a8 7103
+c0a8 7101 3081 880b 0016 4000 0000 0002
+0000 0002 ff03 c021 0201 0012 0104 0578
+0506 577f 7c5b 0702 0802
+
+# 23:18:36.564803 192.168.113.3 > 192.168.113.1: gre [KSv1] ID:4000 S:3 ppp: IPCP 18: Conf-Req(1), IP-Addr=192.168.0.1, IP-Comp VJ-Comp
+[in,pcn1]
+4500 0032 69ae 0000 ff2f ee98 c0a8 7103
+c0a8 7101 3001 880b 0012 4000 0000 0003
+8021 0101 0010 0306 c0a8 0001 0206 002d
+0f01
+
+# 23:18:36.570395 192.168.113.1.1511 > 192.168.113.3.1723: P 349:373(24) ack 189 win 64052: pptp CTRL_MSGTYPE=SLI PEER_CALL_ID(0) SEND_ACCM(0x00000000) RECV_ACCM(0xffffffff) (DF)
+[out,pcn1]
+4500 0040 5e18 4000 8006 5ef0 0a02 0202
+c0a8 7103 05e7 06bb abf0 4c02 a564 6997
+5018 fa34 0d9f 0000 0018 0001 1a2b 3c4d
+000f 0000 0000 0000 0000 0000 ffff ffff
+
+# 23:18:36.573307 192.168.113.1 > 192.168.113.3: gre [KSAv1] ID:0000 S:3 A:3 ppp: LCP 20: Ident(2), Magic-Num=577f7c5b
+[out,pcn1]
+4500 0038 5e19 0000 802f 9ece 0a02 0202
+c0a8 7103 3081 880b 0014 0000 0000 0003
+0000 0003 c021 0c02 0012 577f 7c5b 4d53
+5241 5356 352e 3130
+
+# 23:18:36.573856 192.168.113.3 > 192.168.113.1: gre [KSAv1] ID:4000 S:4 A:3 ppp: LCP 26: Code-Rej(2)
+[in,pcn1]
+4500 003e 69af 0000 ff2f ee8b c0a8 7103
+c0a8 7101 3081 880b 001a 4000 0000 0004
+0000 0003 ff03 c021 0702 0016 0c02 0012
+577f 7c5b 4d53 5241 5356 352e 3130
+
+# 23:18:36.584936 192.168.113.1 > 192.168.113.3: gre [KSAv1] ID:0000 S:4 A:4 ppp: LCP 26: Ident(3), Magic-Num=577f7c5b
+[out,pcn1]
+4500 003e 5e1a 0000 802f 9ec7 0a02 0202
+c0a8 7103 3081 880b 001a 0000 0000 0004
+0000 0004 c021 0c03 0018 577f 7c5b 4d53
+5241 532d 302d 434c 4159 4d4f 4f52
+
+# 23:18:36.585562 192.168.113.3 > 192.168.113.1: gre [KSAv1] ID:4000 S:5 A:4 ppp: LCP 32: Code-Rej(3)
+[in,pcn1]
+4500 0044 69b0 0000 ff2f ee84 c0a8 7103
+c0a8 7101 3081 880b 0020 4000 0000 0005
+0000 0004 ff03 c021 0703 001c 0c03 0018
+577f 7c5b 4d53 5241 532d 302d 434c 4159
+4d4f 4f52
+
+# 23:18:36.588721 192.168.113.1 > 192.168.113.3: gre [KSAv1] ID:0000 S:5 A:5 ppp: CCP 12: Conf-Req(4), MPPC
+[out,pcn1]
+4500 0030 5e1b 0000 802f 9ed4 0a02 0202
+c0a8 7103 3081 880b 000c 0000 0000 0005
+0000 0005 80fd 0104 000a 1206 0100 0001
+
+# 23:18:36.589445 192.168.113.3 > 192.168.113.1: gre [KSAv1] ID:4000 S:6 A:5 ppp: CCP 6: Conf-Req(1)
+[in,pcn1]
+4500 002a 69b1 0000 ff2f ee9d c0a8 7103
+c0a8 7101 3081 880b 0006 4000 0000 0006
+0000 0005 80fd 0101 0004
+
+# 23:18:36.589540 192.168.113.3 > 192.168.113.1: gre [KSv1] ID:4000 S:7 ppp: CCP 12: Conf-Rej(4), MPPC
+[in,pcn1]
+4500 002c 69b2 0000 ff2f ee9a c0a8 7103
+c0a8 7101 3001 880b 000c 4000 0000 0007
+80fd 0404 000a 1206 0100 0001
+
+# 23:18:36.590023 192.168.113.1 > 192.168.113.3: gre [KSAv1] ID:0000 S:6 A:7 ppp: IPCP 36: Conf-Req(5), IP-Addr=0.0.0.0, Pri-DNS=0.0.0.0, Pri-NBNS=0.0.0.0, Sec-DNS=0.0.0.0, Sec-NBNS=0.0.0.0
+[out,pcn1]
+4500 0048 5e1c 0000 802f 9ebb 0a02 0202
+c0a8 7103 3081 880b 0024 0000 0000 0006
+0000 0007 8021 0105 0022 0306 0000 0000
+8106 0000 0000 8206 0000 0000 8306 0000
+0000 8406 0000 0000
+
+# 23:18:36.590489 192.168.113.3 > 192.168.113.1: gre [KSAv1] ID:4000 S:8 A:6 ppp: IPCP 30: Conf-Rej(5), Pri-DNS=0.0.0.0, Pri-NBNS=0.0.0.0, Sec-DNS=0.0.0.0, Sec-NBNS=0.0.0.0
+[in,pcn1]
+4500 0042 69b3 0000 ff2f ee83 c0a8 7103
+c0a8 7101 3081 880b 001e 4000 0000 0008
+0000 0006 8021 0405 001c 8106 0000 0000
+8206 0000 0000 8306 0000 0000 8406 0000
+0000
+
+# 23:18:36.591003 192.168.113.1 > 192.168.113.3: gre [KSAv1] ID:0000 S:7 A:8 ppp: IPCP 12: Conf-Rej(1), IP-Comp VJ-Comp
+[out,pcn1]
+4500 0030 5e1d 0000 802f 9ed2 0a02 0202
+c0a8 7103 3081 880b 000c 0000 0000 0007
+0000 0008 8021 0401 000a 0206 002d 0f01
+
+# 23:18:36.593819 192.168.113.3 > 192.168.113.1: gre [KSAv1] ID:4000 S:9 A:7 ppp: IPCP 12: Conf-Req(2), IP-Addr=192.168.0.1
+[in,pcn1]
+4500 0030 69b4 0000 ff2f ee94 c0a8 7103
+c0a8 7101 3081 880b 000c 4000 0000 0009
+0000 0007 8021 0102 000a 0306 c0a8 0001
+
+# 23:18:36.594840 192.168.113.1 > 192.168.113.3: gre [KSAv1] ID:0000 S:8 A:9 ppp: CCP 6: Conf-Ack(1)
+[out,pcn1]
+4500 002a 5e1e 0000 802f 9ed9 0a02 0202
+c0a8 7103 3081 880b 0006 0000 0000 0008
+0000 0009 80fd 0201 0004 0000 0000
+
+# 23:18:36.595525 192.168.113.1 > 192.168.113.3: gre [KSv1] ID:0000 S:9 ppp: CCP 18: Term-Req(6)
+[out,pcn1]
+4500 0032 5e1f 0000 802f 9ed0 0a02 0202
+c0a8 7103 3001 880b 0012 0000 0000 0009
+80fd 0506 0010 577f 7c5b 003c cd74 0000
+02dc
+
+# 23:18:36.595937 192.168.113.3 > 192.168.113.1: gre [KSAv1] ID:4000 S:10 A:9 ppp: CCP 6: Term-Ack(6)
+[in,pcn1]
+4500 002a 69b5 0000 ff2f ee99 c0a8 7103
+c0a8 7101 3081 880b 0006 4000 0000 000a
+0000 0009 80fd 0606 0004
+
diff --git a/contrib/ipfilter/test/input/ni6 b/contrib/ipfilter/test/input/ni6
new file mode 100644
index 0000000..70e80c0
--- /dev/null
+++ b/contrib/ipfilter/test/input/ni6
@@ -0,0 +1,54 @@
+[in,nf0]
+4500 0054 cd8a 4000 ff11 20ba c0a8 0601
+c0a8 0602 8075 006f 0040 d36d 3e1d d249
+0000 0000 0000 0002 0001 86a0 0000 0002
+0000 0003 0000 0000 0000 0000 0000 0000
+0000 0000 0001 86a3 0000 0003 0000 0011
+0000 0000
+
+[out,qfe0]
+4500 0054 cd8a 4000 ff11 1fbb c0a8 0601
+c0a8 0701 8075 006f 0040 d26e 3e1d d249
+0000 0000 0000 0002 0001 86a0 0000 0002
+0000 0003 0000 0000 0000 0000 0000 0000
+0000 0000 0001 86a3 0000 0003 0000 0011
+0000 0000
+
+[in,qfe0]
+4500 0038 cd83 4000 ff11 1edd c0a8 0701
+c0a8 0702 006f 8075 0024 d704 3e1d d249
+0000 0001 0000 0000 0000 0000 0000 0000
+0000 0000 0000 0801
+
+[out,nf0]
+4500 0038 cd83 4000 ff11 1fde c0a8 0701
+c0a8 0601 006f 8075 0024 d805 3e1d d249
+0000 0001 0000 0000 0000 0000 0000 0000
+0000 0000 0000 0801
+
+[in,nf0]
+4500 0044 d5a6 4000 ff11 18ae c0a8 0601
+c0a8 0602 80df 0801 0030 04f0 3e10 1fb1
+0000 0000 0000 0002 0001 86a3 0000 0002
+0000 0000 0000 0000 0000 0000 0000 0000
+0000 0000
+
+[out,qfe0]
+4500 0044 d5a6 4000 ff11 17af c0a8 0601
+c0a8 0701 80df 0801 0030 03f1 3e10 1fb1
+0000 0000 0000 0002 0001 86a3 0000 0002
+0000 0000 0000 0000 0000 0000 0000 0000
+0000 0000
+
+[in,qfe0]
+4500 0034 0000 4000 fe11 ed64 c0a8 0701
+c0a8 0702 0801 80df 0020 89b7 3e10 1fb1
+0000 0001 0000 0000 0000 0000 0000 0000
+0000 0000
+
+[out,nf0]
+4500 0034 0000 4000 fe11 ee65 c0a8 0701
+c0a8 0601 0801 80df 0020 0000 3e10 1fb1
+0000 0001 0000 0000 0000 0000 0000 0000
+0000 0000
+
diff --git a/contrib/ipfilter/test/input/ni7 b/contrib/ipfilter/test/input/ni7
index 954bb7b..30f247d 100644
--- a/contrib/ipfilter/test/input/ni7
+++ b/contrib/ipfilter/test/input/ni7
@@ -7,7 +7,7 @@
[out,df0]
4500 0038 809a 0000 ff01 2d1d 0303 0303
-0404 0404 0b00 0125 0000 0000
-4500 0028 4706 4000 0111 1eac 0404 0404 0606 0606
+0404 0404 0b00 0125 0000 0000 4500 0028
+4706 4000 0111 1eac 0404 0404 0606 0606
afc9 829e 0014 c15e
diff --git a/contrib/ipfilter/test/input/ni9 b/contrib/ipfilter/test/input/ni9
new file mode 100644
index 0000000..788e603
--- /dev/null
+++ b/contrib/ipfilter/test/input/ni9
@@ -0,0 +1,24 @@
+#v tos len id off ttl p sum src dst
+# ICMP dest unreachable with 64 bits in payload (in reply to a TCP packet
+# going out)
+[in,df0] 45 00 00 3c 47 06 40 00 ff 06 20 aa 04 04 04 04 0a 02 02 02 50 00 05 00 00 00 00 01 00 00 00 00 a0 02 16 d0 cc 32 00 00 02 04 05 b4 04 02 08 0a 00 47 fb b0 00 00 00 00 01 03 03 00
+
+[out,df0]
+4500 0038 809a 0000 ff01 2d1d 0303 0303 0404 0404
+0303 0fa3 0000 0000
+4500 003c 4706 4000 ff06 2aac 0404 0404 0101 0101
+5000 9d58 0000 0001
+
+# ICMP dest unreachable with whole packet in payload (40 bytes = 320 bits)
+[out,df0]
+4500 0058 809a 0000 ff01 2cfd 0303 0303 0404 0404
+0303 0735 0000 0000
+4500 003c 4706 4000 ff06 2aac 0404 0404 0101 0101
+5000 9d58 0000 0001 0000 0000 a002 16d0 3ddc 0000
+0204 05b4 0402 080a 0047 fbb0 0000 0000 0103 0300
+
+[out,df0]
+4500 0038 809a 0000 ff01 2b1b 0303 0303 0505 0505
+0303 0fa3 0000 0000
+4500 003c 4706 4000 ff06 2aab 0404 0404 0101 0102 5000 9d58 0000 0001
+
diff --git a/contrib/ipfilter/test/input/p1 b/contrib/ipfilter/test/input/p1
new file mode 100644
index 0000000..f6753fa
--- /dev/null
+++ b/contrib/ipfilter/test/input/p1
@@ -0,0 +1,8 @@
+in 127.0.0.1 127.0.0.1
+in 1.1.1.1 1.2.1.1
+out 127.0.0.1 127.0.0.1
+out 1.1.1.1 1.2.1.1
+in 2.3.0.1 1.2.1.1
+in 2.2.2.1 1.2.1.1
+in 2.2.0.1 1.2.1.1
+out 4.4.1.1 1.2.1.1
diff --git a/contrib/ipfilter/test/input/p2 b/contrib/ipfilter/test/input/p2
new file mode 100644
index 0000000..f6753fa
--- /dev/null
+++ b/contrib/ipfilter/test/input/p2
@@ -0,0 +1,8 @@
+in 127.0.0.1 127.0.0.1
+in 1.1.1.1 1.2.1.1
+out 127.0.0.1 127.0.0.1
+out 1.1.1.1 1.2.1.1
+in 2.3.0.1 1.2.1.1
+in 2.2.2.1 1.2.1.1
+in 2.2.0.1 1.2.1.1
+out 4.4.1.1 1.2.1.1
diff --git a/contrib/ipfilter/test/input/p3 b/contrib/ipfilter/test/input/p3
new file mode 100644
index 0000000..4a6666b
--- /dev/null
+++ b/contrib/ipfilter/test/input/p3
@@ -0,0 +1,12 @@
+in 1.1.1.1 1.2.1.1
+in 1.2.1.1 1.1.1.1
+out 1.1.1.1 1.2.1.1
+out 1.2.1.1 1.1.1.1
+in 2.2.2.2 2.1.2.1
+out 2.1.2.1 2.2.2.2
+in 3.3.1.1 3.1.3.1
+out 3.1.3.1 3.3.1.1
+in 4.4.1.1 4.1.4.1
+out 4.1.4.1 4.4.1.1
+in 5.5.1.1 5.1.5.1
+out 5.1.5.1 5.5.1.1
diff --git a/contrib/ipfilter/test/intest b/contrib/ipfilter/test/intest
index 98241fc..e94ca08 100755
--- a/contrib/ipfilter/test/intest
+++ b/contrib/ipfilter/test/intest
@@ -1,4 +1,5 @@
#!/bin/sh
+mkdir -p results
if [ -f /usr/ucb/touch ] ; then
TOUCH=/usr/ucb/touch
else
@@ -12,7 +13,7 @@ else
fi
echo "$1...";
/bin/cp /dev/null results/$1
-../ipnat -nvf regress/$1 2>/dev/null > results/$1
+../ipnat -Rnvf regress/$1 2>/dev/null > results/$1
cmp expected/$1 results/$1
status=$?
if [ $status = 0 ] ; then
diff --git a/contrib/ipfilter/test/iptest b/contrib/ipfilter/test/iptest
new file mode 100644
index 0000000..bb3ab5e
--- /dev/null
+++ b/contrib/ipfilter/test/iptest
@@ -0,0 +1,22 @@
+#!/bin/sh
+mkdir -p results
+if [ -f /usr/ucb/touch ] ; then
+ TOUCH=/usr/ucb/touch
+else
+ if [ -f /usr/bin/touch ] ; then
+ TOUCH=/usr/bin/touch
+ else
+ if [ -f /bin/touch ] ; then
+ TOUCH=/bin/touch
+ fi
+ fi
+fi
+echo "$1...";
+/bin/cp /dev/null results/$1
+../ippool -f regress/$1 -nRv 2>/dev/null > results/$1
+cmp expected/$1 results/$1
+status=$?
+if [ $status = 0 ] ; then
+ $TOUCH $1
+fi
+exit $status
diff --git a/contrib/ipfilter/test/itest b/contrib/ipfilter/test/itest
index c1b5f57..333afde 100644
--- a/contrib/ipfilter/test/itest
+++ b/contrib/ipfilter/test/itest
@@ -1,4 +1,5 @@
#!/bin/sh
+mkdir -p results
if [ -f /usr/ucb/touch ] ; then
TOUCH=/usr/ucb/touch
else
@@ -12,7 +13,7 @@ else
fi
echo "$1...";
/bin/cp /dev/null results/$1
-../ipf -nvf regress/$1 2>/dev/null > results/$1
+../ipf -Rnvf regress/$1 2>/dev/null > results/$1
cmp expected/$1 results/$1
status=$?
if [ $status = 0 ] ; then
diff --git a/contrib/ipfilter/test/mhtest b/contrib/ipfilter/test/mhtest
index 52a0027..a4d48d6 100755
--- a/contrib/ipfilter/test/mhtest
+++ b/contrib/ipfilter/test/mhtest
@@ -16,7 +16,7 @@ echo "$1...";
/bin/cp /dev/null results/$1
-../ipftest -br regress/$1 -Hi input/$1 > results/$1
+../ipftest -br regress/$1 -F hex -i input/$1 > results/$1
if [ $? -ne 0 ] ; then
exit 1
fi
diff --git a/contrib/ipfilter/test/mtest b/contrib/ipfilter/test/mtest
index b185abb..2a3ed38 100755
--- a/contrib/ipfilter/test/mtest
+++ b/contrib/ipfilter/test/mtest
@@ -1,4 +1,6 @@
#!/bin/sh
+format=$2
+mkdir -p results
# multiple rules at the same time
if [ -f /usr/ucb/touch ] ; then
@@ -16,7 +18,7 @@ echo "$1...";
/bin/cp /dev/null results/$1
-../ipftest -br regress/$1 -i input/$1 > results/$1
+../ipftest -F $format -Rbr regress/$1 -i input/$1 > results/$1
if [ $? -ne 0 ] ; then
exit 1
fi
diff --git a/contrib/ipfilter/test/natipftest b/contrib/ipfilter/test/natipftest
index 8627168..f5cfdb8 100755
--- a/contrib/ipfilter/test/natipftest
+++ b/contrib/ipfilter/test/natipftest
@@ -1,4 +1,15 @@
#!/bin/sh
+mode=$1
+shift
+if [ $3 = hex ] ; then
+ format="-xF $2"
+else
+ format="-F $2"
+fi
+if [ "$4" != "" ] ; then
+ format="-T $4 $format"
+fi
+mkdir -p results
if [ -f /usr/ucb/touch ] ; then
TOUCH=/usr/ucb/touch
else
@@ -10,19 +21,39 @@ else
fi
fi
fi
-echo "$1...";
-/bin/cp /dev/null results/$1
-( while read rule; do
- echo "$rule" | ../ipftest -bHx -r regress/$1.ipf -Nr - -i input/$1 >> \
- results/$1;
+
+case $mode in
+single)
+ echo "$1...";
+ /bin/cp /dev/null results/$1
+ ( while read rule; do
+ echo "$rule" | ../ipftest -R $format -bx -r regress/$1.ipf -N - -i input/$1 >> \
+ results/$1;
+ if [ $? -ne 0 ] ; then
+ exit 1;
+ fi
+ echo "-------------------------------" >> results/$1
+ done ) < regress/$1.nat
+ cmp expected/$1 results/$1
+ status=$?
+ if [ $status = 0 ] ; then
+ $TOUCH $1
+ fi
+ ;;
+multi)
+ echo "$1...";
+ /bin/cp /dev/null results/$1
+ ../ipftest -R $format -bx -r regress/$1.ipf -N regress/$1.nat \
+ -i input/$1 >> results/$1;
if [ $? -ne 0 ] ; then
- exit 1;
+ exit 2;
fi
echo "-------------------------------" >> results/$1
-done ) < regress/$1.nat
-cmp expected/$1 results/$1
-status=$?
-if [ $status = 0 ] ; then
- $TOUCH $1
-fi
+ cmp expected/$1 results/$1
+ status=$?
+ if [ $status = 0 ] ; then
+ $TOUCH $1
+ fi
+ ;;
+esac
exit $status
diff --git a/contrib/ipfilter/test/nattest b/contrib/ipfilter/test/nattest
index 2b3e931..78b757e 100755
--- a/contrib/ipfilter/test/nattest
+++ b/contrib/ipfilter/test/nattest
@@ -1,4 +1,12 @@
#!/bin/sh
+if [ $3 = hex ] ; then
+ format="-xF $2"
+else
+ format="-F $2"
+fi
+if [ "$4" != "" ] ; then
+ format="-T $4 $format"
+fi
if [ -f /usr/ucb/touch ] ; then
TOUCH=/usr/ucb/touch
else
@@ -13,7 +21,7 @@ fi
echo "$1...";
/bin/cp /dev/null results/$1
( while read rule; do
- echo "$rule" | ../ipftest -Nbr - -i input/$1 >> results/$1;
+ echo "$rule" | ../ipftest $format -RbN - -i input/$1 >> results/$1;
if [ $? -ne 0 ] ; then
exit 1;
fi
diff --git a/contrib/ipfilter/test/ptest b/contrib/ipfilter/test/ptest
new file mode 100644
index 0000000..7deccd3
--- /dev/null
+++ b/contrib/ipfilter/test/ptest
@@ -0,0 +1,31 @@
+#!/bin/sh
+mkdir -p results
+if [ -f /usr/ucb/touch ] ; then
+ TOUCH=/usr/ucb/touch
+else
+ if [ -f /usr/bin/touch ] ; then
+ TOUCH=/usr/bin/touch
+ else
+ if [ -f /bin/touch ] ; then
+ TOUCH=/bin/touch
+ fi
+ fi
+fi
+echo "$1...";
+/bin/cp /dev/null results/$1
+if [ -f regress/$1.pool ] ; then
+ ../ipftest -RD -b -P regress/$1.pool -r regress/$1.ipf -i input/$1 >> \
+ results/$1
+else
+ ../ipftest -RD -b -r regress/$1.ipf -i input/$1 >> results/$1
+fi
+if [ $? -ne 0 ] ; then
+ exit 1;
+fi
+echo "-------------------------------" >> results/$1
+cmp expected/$1 results/$1
+status=$?
+if [ $status = 0 ] ; then
+ $TOUCH $1
+fi
+exit $status
diff --git a/contrib/ipfilter/test/regress/bpf-f1 b/contrib/ipfilter/test/regress/bpf-f1
new file mode 100644
index 0000000..2c80283
--- /dev/null
+++ b/contrib/ipfilter/test/regress/bpf-f1
@@ -0,0 +1,4 @@
+pass in bpf-v4 { "0x20 0 0 0xc 0x15 0 0x1 0x1010101 0x6 0 0 0x60 0x6 0 0 0" }
+pass out bpf-v4 { "0x20 0 0 0xc 0x15 0 0x1 0x1010101 0x6 0 0 0x60 0x6 0 0 0" }
+pass in bpf-v4 { "0x20 0 0 0x10 0x15 0 0x1 0x1010101 0x6 0 0 0x60 0x6 0 0 0" }
+pass out bpf-v4 { "0x20 0 0 0x10 0x15 0 0x1 0x1010101 0x6 0 0 0x60 0x6 0 0 0" }
diff --git a/contrib/ipfilter/test/regress/bpf1 b/contrib/ipfilter/test/regress/bpf1
new file mode 100644
index 0000000..2c80283
--- /dev/null
+++ b/contrib/ipfilter/test/regress/bpf1
@@ -0,0 +1,4 @@
+pass in bpf-v4 { "0x20 0 0 0xc 0x15 0 0x1 0x1010101 0x6 0 0 0x60 0x6 0 0 0" }
+pass out bpf-v4 { "0x20 0 0 0xc 0x15 0 0x1 0x1010101 0x6 0 0 0x60 0x6 0 0 0" }
+pass in bpf-v4 { "0x20 0 0 0x10 0x15 0 0x1 0x1010101 0x6 0 0 0x60 0x6 0 0 0" }
+pass out bpf-v4 { "0x20 0 0 0x10 0x15 0 0x1 0x1010101 0x6 0 0 0x60 0x6 0 0 0" }
diff --git a/contrib/ipfilter/test/regress/i1 b/contrib/ipfilter/test/regress/i1
index 736801e..df60d2b 100644
--- a/contrib/ipfilter/test/regress/i1
+++ b/contrib/ipfilter/test/regress/i1
@@ -1,5 +1,6 @@
pass in all
-block out all
+block out \
+all
log in all
log body in all
count in from any to any
@@ -11,3 +12,5 @@ pass in log body quick from any to any
block return-rst in quick on le0 proto tcp from any to any
block return-icmp in on qe0 from any to any
block return-icmp(1) in on qe0 from any to any
+block return-icmp-as-dest(port-unr) in on qe0 from any to any
+pass out on longNICname0 from test.host.dots to test\.host.dots
diff --git a/contrib/ipfilter/test/regress/i11 b/contrib/ipfilter/test/regress/i11
index 68e9283..2999a85 100644
--- a/contrib/ipfilter/test/regress/i11
+++ b/contrib/ipfilter/test/regress/i11
@@ -1,5 +1,8 @@
pass in on ed0 proto tcp from localhost to localhost port = telnet keep state
block in log first on lo0 proto tcp/udp from any to any keep state
-pass in proto udp from localhost to localhost port = 2049 keep frags
+pass in proto udp from localhost to localhost port = 20499 keep frag
pass in proto udp from localhost to localhost port = 53 keep state keep frags
-pass in proto tcp from any port gt 1024 to localhost port eq 25 keep state
+pass in on ed0 out-via vx0 proto udp from any to any keep state
+pass out on ppp0 in-via le0 proto tcp from any to any keep state
+pass in proto tcp from any port gt 1024 to localhost port eq 1024 keep state
+pass in proto tcp all flags S keep state(strict,newisn,no-icmp-err,limit 101)
diff --git a/contrib/ipfilter/test/regress/i12 b/contrib/ipfilter/test/regress/i12
index d923f08..b8b2f3e 100644
--- a/contrib/ipfilter/test/regress/i12
+++ b/contrib/ipfilter/test/regress/i12
@@ -1,4 +1,9 @@
-block in on eri0 all head 1
-pass in on eri0 proto icmp all group 1
-pass out on ed0 all head 1000000
-block out on ed0 proto udp all group 1000000
+pass in from 1.1.1.1/32 to 2.2.2.2/32
+pass in from (2.2.2.2/24,3.3.3.3/32) to 4.4.4.4/32
+pass in from (2.2.2.2/24,3.3.3.3/32) to (5.5.5.5/32,6.6.6.6/32)
+pass in from (2.2.2.2/24,3.3.3.3/32) to (5.5.5.5/32,6.6.6.6/32) port = (22,25)
+pass in proto tcp from (2.2.2.2/24,3.3.3.3/32) to (5.5.5.5/32,6.6.6.6/32) port = (53,9)
+pass in proto udp from (2.2.2.2/24,3.3.3.3/32) to (5.5.5.5/32,6.6.6.6/32) port = (53,9)
+pass in from 10.10.10.10 to 11.11.11.11
+pass in from pool/101 to hash/202
+pass in from hash/303 to pool/404
diff --git a/contrib/ipfilter/test/regress/i13 b/contrib/ipfilter/test/regress/i13
new file mode 100644
index 0000000..3ba343d
--- /dev/null
+++ b/contrib/ipfilter/test/regress/i13
@@ -0,0 +1,8 @@
+a=any;
+b="from $a";
+c='to $a';
+d=block;
+e="pass in";
+$d in $b $c
+f=" $b $c";
+$e${f}
diff --git a/contrib/ipfilter/test/regress/i14 b/contrib/ipfilter/test/regress/i14
new file mode 100644
index 0000000..3c9d7b8
--- /dev/null
+++ b/contrib/ipfilter/test/regress/i14
@@ -0,0 +1,8 @@
+block in on eri0 all head 1
+pass in on eri0 proto icmp all group 1
+pass out on ed0 all head 1000000
+block out on ed0 proto udp all group 1000000
+block in on vm0 proto tcp/udp all head 101
+pass in from 1.1.1.1 to 2.2.2.2 group 101
+pass in proto tcp from 1.0.0.1 to 2.0.0.2 group 101
+pass in proto udp from 2.0.0.2 to 3.0.0.3 group 101
diff --git a/contrib/ipfilter/test/regress/i15 b/contrib/ipfilter/test/regress/i15
new file mode 100644
index 0000000..5268ec35
--- /dev/null
+++ b/contrib/ipfilter/test/regress/i15
@@ -0,0 +1,5 @@
+pass out on fxp0 all set-tag(log=100)
+pass out on fxp0 all set-tag(nat=foo)
+pass out on fxp0 all set-tag(log=100, nat=200)
+pass out on fxp0 all set-tag(log=2147483648, nat=overtherainbowisapotof)
+
diff --git a/contrib/ipfilter/test/regress/i2 b/contrib/ipfilter/test/regress/i2
index 101deaa..a3b9cd8 100644
--- a/contrib/ipfilter/test/regress/i2
+++ b/contrib/ipfilter/test/regress/i2
@@ -1,6 +1,7 @@
log in proto tcp all
pass in proto 6 from any to any
pass in proto udp from localhost to localhost
+block in proto ipv6 from any to any
block in proto 17 from any to any
block in proto 250 from any to any
pass in proto tcp/udp from any to any
diff --git a/contrib/ipfilter/test/regress/i3 b/contrib/ipfilter/test/regress/i3
index 15e98bf..0d82e8a 100644
--- a/contrib/ipfilter/test/regress/i3
+++ b/contrib/ipfilter/test/regress/i3
@@ -1,5 +1,7 @@
log in all
-pass in from 128.0.0.1/24 to 128.0.0.1/16
+pass in from 128.16/16 to 129.10.10/24
+pass in from 128.0.0.1/24 to 128\
+.0.0.1/16
pass in from 128.0.0.1/0xffffff00 to 128.0.0.1/0xffff0000
pass in from 128.0.0.1/255.255.255.0 to 128.0.0.1/255.255.0.0
pass in from 128.0.0.1 mask 0xffffff00 to 128.0.0.1 mask 0xffff0000
diff --git a/contrib/ipfilter/test/regress/i4 b/contrib/ipfilter/test/regress/i4
index 1095ed9..7170dc2 100644
--- a/contrib/ipfilter/test/regress/i4
+++ b/contrib/ipfilter/test/regress/i4
@@ -2,6 +2,7 @@ log in proto tcp from any port > 0 to any
log in proto tcp from any to any port > 0
pass in proto 6 from any port != 0 to any port 0 >< 65535
pass in proto 17 from localhost port > 32000 to localhost port < 29000
-block in proto udp from any port != ntp to any port < ntp
+block in proto udp from any port != \ntp to any port < echo
block in proto tcp from any port = smtp to any port > 25
pass in proto tcp/udp from any port 1 >< 3 to any port 1 <> 3
+pass in log first quick proto tcp from any port > 1023 to any port = 1723 flags S keep state
diff --git a/contrib/ipfilter/test/regress/i6 b/contrib/ipfilter/test/regress/i6
index a35633b..1a53089 100644
--- a/contrib/ipfilter/test/regress/i6
+++ b/contrib/ipfilter/test/regress/i6
@@ -1,4 +1,10 @@
pass in on lo0 fastroute from any to any
+pass in on lo0 to qe0 from localhost to localhost
+pass in on le0 to qe0:127.0.0.1 from localhost to localhost
pass in on lo0 dup-to qe0 from localhost to localhost
-pass in on qe0 dup-to qe0:127.0.0.1 from localhost to localhost
+pass in on le0 dup-to qe0:127.0.0.1 from localhost to localhost
+pass in on le0 to hme0:10.1.1.1 dup-to qe0:127.0.0.1 from localhost to localhost
block in quick on qe0 to qe1 from any to any
+block in quick to qe1 from any to any
+pass out quick dup-to hme0 from any to any
+pass in quick fastroute all
diff --git a/contrib/ipfilter/test/regress/i9 b/contrib/ipfilter/test/regress/i9
index 327cff4..2b8fb10 100644
--- a/contrib/ipfilter/test/regress/i9
+++ b/contrib/ipfilter/test/regress/i9
@@ -1,5 +1,7 @@
-pass in from localhost to localhost with short
+pass in from localhost to localhost with short,frags
block in from any to any with ipopts
pass in from any to any with opt nop,rr,zsu
pass in from any to any with opt nop,rr,zsu not opt ssrr,lsrr
pass in from localhost to localhost with not frag
+pass in proto tcp all flags S with not oow keep state
+pass in proto tcp all flags S with not bad,bad-src,bad-nat
diff --git a/contrib/ipfilter/test/regress/in1 b/contrib/ipfilter/test/regress/in1
index 59c5754..145e3d0 100644
--- a/contrib/ipfilter/test/regress/in1
+++ b/contrib/ipfilter/test/regress/in1
@@ -23,3 +23,5 @@ map le0 0/0 -> 0/32 frag age 10
map le0 192.168.0.0/16 -> range 203.1.1.23-203.1.3.45 frag age 10/20
map ppp0 192.168.0.0/16 -> 0/32 portmap tcp 10000:19999 frag age 30
map fxp0 from 192.168.0.0/18 to 0/0 port = 21 -> 1.2.3.4/32 proxy port 21 ftp/tcp
+map thisisalonginte 0/0 -> 0/32 mssclamp 1452 tag freddyliveshere
+map bar0 0/0 -> 0/32 icmpidmap icmp 1000:2000
diff --git a/contrib/ipfilter/test/regress/in2 b/contrib/ipfilter/test/regress/in2
index 33151f0..222a28c 100644
--- a/contrib/ipfilter/test/regress/in2
+++ b/contrib/ipfilter/test/regress/in2
@@ -1,22 +1,67 @@
-rdr le0 0/0 port 0 -> 1.1.1.1 port 0
-rdr le0 0/0 port 0 -> 1.1.1.1 port 0 ip
-rdr le0 0/0 port 80 -> 1.1.1.1 port 80
-rdr le0 0/0 port 80 -> 1.1.1.1 port 80 ip
-rdr le0 0/0 port 80 -> 1.1.1.1 port 80 tcp
-rdr le0 0/0 port 80 -> 1.1.1.1 port 80 udp
-rdr le0 0/0 port 80 -> 1.1.1.1 port 80 tcp/udp
-rdr le0 0/0 port 80 -> 1.1.1.1 port 80 icmp
-rdr le0 0/0 port 80 -> 1.1.1.1,1.1.1.2 port 80 tcp
-rdr le0 0/0 port 80 -> 1.1.1.1 port 80 tcp round-robin
-rdr le0 0/0 port 80 -> 1.1.1.1,1.1.1.2 port 80 tcp round-robin
-rdr le0 0/0 port 0 -> 1.1.1.1 port 0 ip frag
-rdr le0 0/0 port 80 -> 1.1.1.1 port 80 icmp frag
-rdr le0 0/0 port 80 -> 1.1.1.1,1.1.1.2 port 80 tcp frag
-rdr le0 0/0 port 80 -> 1.1.1.1 port 80 tcp round-robin frag
-rdr le0 0/0 port 80 -> 1.1.1.1,1.1.1.2 port 80 tcp round-robin frag
-rdr le0 0/0 port 0 -> 1.1.1.1 port 0 ip frag age 10
-rdr le0 0/0 port 0 -> 1.1.1.1 port 0 ip frag age 10/20
-rdr le0 0/0 port 80 -> 1.1.1.1 port 80 icmp frag age 10
-rdr le0 0/0 port 80 -> 1.1.1.1,1.1.1.2 port 80 tcp frag age 20
-rdr le0 0/0 port 80 -> 1.1.1.1 port 80 tcp round-robin frag age 30
-rdr le0 0/0 port 80 -> 1.1.1.1,1.1.1.2 port 80 tcp round-robin frag age 40
+rdr le0 9.8.7.6/32 port 0 -> 1.1.1.1 port 0 tcp
+rdr le0 9.8.7.6/32 port 0 -> 1.1.1.1 port 0 ip
+rdr le0 9.8.7.6/32 port 80 -> 1.1.1.1 port 80 tcp
+rdr le0 9.8.7.6/32 -> 1.1.1.1 ip
+rdr le0 9.8.7.6/32 port 80 -> 1.1.1.1 port 80 tcp
+rdr le0 9.8.7.6/32 port 80 -> 1.1.1.1 port 80 udp
+rdr le0 9.8.7.6/32 port 80 -> 1.1.1.1 port 80 tcp/udp
+rdr le0 9.8.7.6/32 port 80 -> 1.1.1.1 port 80 icmp
+rdr le0 9.8.7.6/32 port 80 -> 1.1.1.1,1.1.1.2 port 80 tcp
+rdr le0 9.8.7.6/32 port 80 -> 1.1.1.1 port 80 tcp round-robin
+rdr le0 9.8.7.6/32 port 80 -> 1.1.1.1,1.1.1.2 port 80 tcp round-robin
+rdr le0 9.8.7.6/32 port 0 -> 1.1.1.1 port 0 ip frag
+rdr le0 9.8.7.6/32 port 80 -> 1.1.1.1 port 80 icmp frag
+rdr le0 9.8.7.6/32 port 80 -> 1.1.1.1,1.1.1.2 port 80 tcp frag
+rdr le0 9.8.7.6/32 port 80 -> 1.1.1.1 port 80 tcp round-robin frag
+rdr le0 9.8.7.6/32 port 80 -> 1.1.1.1,1.1.1.2 port 80 tcp round-robin frag
+rdr le0 9.8.7.6/32 -> 1.1.1.1 ip frag age 10
+rdr le0 9.8.7.6/32 port 0 -> 1.1.1.1 port 0 ip frag age 10/20
+rdr le0 9.8.7.6/32 port 80 -> 1.1.1.1 port 80 icmp frag age 10
+rdr le0 9.8.7.6/32 port 80 -> 1.1.1.1,1.1.1.2 port 80 tcp frag age 20
+rdr le0 9.8.7.6/32 port 80 -> 1.1.1.1 port 80 tcp round-robin frag age 30
+rdr le0 9.8.7.6/32 port 80 -> 1.1.1.1,1.1.1.2 port 80 tcp round-robin frag age 40
+rdr le0 9.8.7.6/32 port 0 -> 1.1.1.1 port 0 ip sticky
+rdr le0 9.8.7.6/32 port 0 -> 1.1.1.1 port 0 ip frag sticky
+rdr le0 9.8.7.6/32 port 80 -> 1.1.1.1 port 80 icmp frag sticky
+rdr le0 9.8.7.6/32 port 80 -> 1.1.1.1,1.1.1.2 port 80 tcp frag sticky
+rdr le0 9.8.7.6/32 port 80 -> 1.1.1.1 port 80 tcp round-robin frag sticky
+rdr le0 9.8.7.6/32 port 80 -> 1.1.1.1,1.1.1.2 port 80 tcp round-robin frag sticky
+rdr le0 9.8.7.6/32 port 0 -> 1.1.1.1 port 0 ip frag age 10 sticky
+rdr le0 9.8.7.6/32 port 0 -> 1.1.1.1 port 0 ip frag age 10/20 sticky
+rdr le0 9.8.7.6/32 port 80 -> 1.1.1.1 port 80 icmp frag age 10 sticky
+rdr le0 9.8.7.6/32 port 80 -> 1.1.1.1,1.1.1.2 port 80 tcp frag age 20 sticky
+rdr le0 9.8.7.6/32 port 80 -> 1.1.1.1 port 80 tcp round-robin frag age 30 sticky
+rdr le0 9.8.7.6/32 port 80 -> 1.1.1.1,1.1.1.2 port 80 tcp round-robin frag age 40 sticky
+rdr le0 9.8.7.6/32 port 0 -> 1.1.1.1 port 0 ip mssclamp 1000
+rdr le0 9.8.7.6/32 port 0 -> 1.1.1.1 port 0 ip sticky mssclamp 1000
+rdr le0 9.8.7.6/32 port 0 -> 1.1.1.1 port 0 ip frag sticky mssclamp 1000
+rdr le0 9.8.7.6/32 port 80 -> 1.1.1.1 port 80 icmp frag sticky mssclamp 1000
+rdr le0 9.8.7.6/32 port 80 -> 1.1.1.1,1.1.1.2 port 80 tcp frag sticky mssclamp 1000
+rdr le0 9.8.7.6/32 port 80 -> 1.1.1.1 port 80 tcp round-robin frag sticky mssclamp 1000
+rdr le0 9.8.7.6/32 port 80 -> 1.1.1.1,1.1.1.2 port 80 tcp round-robin frag sticky mssclamp 1000
+rdr le0 9.8.7.6/32 port 0 -> 1.1.1.1 port 0 ip frag age 10 sticky mssclamp 1000
+rdr le0 9.8.7.6/32 port 0 -> 1.1.1.1 port 0 ip frag age 10/20 sticky mssclamp 1000
+rdr le0 9.8.7.6/32 port 80 -> 1.1.1.1 port 80 icmp frag age 10 sticky mssclamp 1000
+rdr le0 9.8.7.6/32 port 80 -> 1.1.1.1,1.1.1.2 port 80 tcp frag age 20 sticky mssclamp 1000
+rdr le0 9.8.7.6/32 port 80 -> 1.1.1.1 port 80 tcp round-robin frag age 30 sticky mssclamp 1000
+rdr le0 9.8.7.6/32 port 80 -> 1.1.1.1,1.1.1.2 port 80 tcp round-robin frag age 40 sticky mssclamp 1000
+rdr le0 9.8.7.6/32 port 0 -> 1.1.1.1 port 0 ip tag nattagcacheline
+rdr le0 9.8.7.6/32 port 0 -> 1.1.1.1 port 0 ip mssclamp 1000 tag nattagcacheline
+rdr le0 9.8.7.6/32 port 0 -> 1.1.1.1 port 0 ip sticky mssclamp 1000 tag nattagcacheline
+rdr le0 9.8.7.6/32 port 0 -> 1.1.1.1 port 0 ip frag sticky mssclamp 1000 tag nattagcacheline
+rdr le0 9.8.7.6/32 port 80 -> 1.1.1.1 port 80 icmp frag sticky mssclamp 1000 tag nattagcacheline
+rdr le0 9.8.7.6/32 port 80 -> 1.1.1.1,1.1.1.2 port 80 tcp frag sticky mssclamp 1000 tag nattagcacheline
+rdr le0 9.8.7.6/32 port 80 -> 1.1.1.1 port 80 tcp round-robin frag sticky mssclamp 1000 tag nattagcacheline
+rdr le0 9.8.7.6/32 port 80 -> 1.1.1.1,1.1.1.2 port 80 tcp round-robin frag sticky mssclamp 1000 tag nattagcacheline
+rdr le0 9.8.7.6/32 port 0 -> 1.1.1.1 port 0 ip frag age 10 sticky mssclamp 1000 tag nattagcacheline
+rdr le0 9.8.7.6/32 port 0 -> 1.1.1.1 port 0 ip frag age 10/20 sticky mssclamp 1000 tag nattagcacheline
+rdr le0 9.8.7.6/32 port 80 -> 1.1.1.1 port 80 icmp frag age 10 sticky mssclamp 1000 tag nattagcacheline
+rdr le0 9.8.7.6/32 port 80 -> 1.1.1.1,1.1.1.2 port 80 tcp frag age 20 sticky mssclamp 1000 tag nattagcacheline
+rdr le0 9.8.7.6/32 port 80 -> 1.1.1.1 port 80 tcp round-robin frag age 30 sticky mssclamp 1000 tag nattagcacheline
+rdr le0 9.8.7.6/32 port 80 -> 1.1.1.1,1.1.1.2 port 80 tcp round-robin frag age 40 sticky mssclamp 1000 tag nattagcacheline
+rdr ge0 9.8.7.6/32 -> 1.1.1.1 proxy port 21 ftp/tcp
+rdr ge0 9.8.7.6/32 port 21 -> 1.1.1.1 port 21 tcp proxy ftp
+rdr le0 9.8.7.6/32 port 1000-2000 -> 1.1.1.1 port 5555 tcp
+rdr le0 9.8.7.6/32 port 1000-2000 -> 1.1.1.1 port = 5555 tcp
+rdr le0 0/0 -> test.host.dots
+rdr le0 0/0 -> test.host.dots,test.host.dots
diff --git a/contrib/ipfilter/test/regress/in5 b/contrib/ipfilter/test/regress/in5
new file mode 100644
index 0000000..d0a115c
--- /dev/null
+++ b/contrib/ipfilter/test/regress/in5
@@ -0,0 +1,22 @@
+rdr le0 from any to 9.8.7.6/32 port = 0 -> 1.1.1.1 port 0 tcp
+rdr le0 from any to 9.8.7.6/32 port = 0 -> 1.1.1.1 port 0 ip
+rdr le0 from any to 9.8.7.6/32 port = 8888 -> 1.1.1.1 port 888 tcp
+rdr le0 from any to 9.8.7.6/32 port = 8888 -> 1.1.1.1 port 888 ip
+rdr le0 from any to 9.8.7.6/32 port = 8888 -> 1.1.1.1 port 888 tcp
+rdr le0 from any to 9.8.7.6/32 port = 8888 -> 1.1.1.1 port 888 udp
+rdr le0 from any to 9.8.7.6/32 port = 8888 -> 1.1.1.1 port 888 tcp/udp
+rdr le0 from any to 9.8.7.6/32 -> 1.1.1.1 port 888 icmp
+rdr le0 from any to 9.8.7.6/32 port = 8888 -> 1.1.1.1,1.1.1.2 port 888 tcp
+rdr le0 from any to 9.8.7.6/32 port = 8888 -> 1.1.1.1 port 888 tcp round-robin
+rdr le0 from any to 9.8.7.6/32 port = 8888 -> 1.1.1.1,1.1.1.2 port 888 tcp round-robin
+rdr le0 from any to 9.8.7.6/32 -> 1.1.1.1 port 0 ip frag
+rdr le0 from any to 9.8.7.6/32 port = 8888 -> 1.1.1.1 port 888 icmp frag
+rdr le0 from any to 9.8.7.6/32 port = 8888 -> 1.1.1.1,1.1.1.2 port 888 tcp frag
+rdr le0 from any to 9.8.7.6/32 port = 8888 -> 1.1.1.1 port 888 tcp round-robin frag
+rdr le0 from any to 9.8.7.6/32 port = 8888 -> 1.1.1.1,1.1.1.2 port 888 tcp round-robin frag
+rdr le0 from any to 9.8.7.6/32 -> 1.1.1.1 port 0 ip frag age 10
+rdr le0 from any to 9.8.7.6/32 port = 0 -> 1.1.1.1 port 0 ip frag age 10/20
+rdr le0 from any to 9.8.7.6/32 port = 8888 -> 1.1.1.1 port 888 icmp frag age 10
+rdr le0 from any to 9.8.7.6/32 port = 8888 -> 1.1.1.1,1.1.1.2 port 888 tcp frag age 20
+rdr le0 from any to 9.8.7.6/32 port = 8888 -> 1.1.1.1 port 888 tcp round-robin frag age 30
+rdr le0 from any to 9.8.7.6/32 port = 8888 -> 1.1.1.1,1.1.1.2 port 888 tcp round-robin frag age 40
diff --git a/contrib/ipfilter/test/regress/in6 b/contrib/ipfilter/test/regress/in6
new file mode 100644
index 0000000..6948799
--- /dev/null
+++ b/contrib/ipfilter/test/regress/in6
@@ -0,0 +1,3 @@
+map foo0 from any port = 1 to any port != 0 -> 0/32 udp
+map foo0 from any port < 1 to any port > 0 -> 0/32 tcp
+map foo0 from any port <= 1 to any port >= 0 -> 0/32 tcp/udp
diff --git a/contrib/ipfilter/test/regress/ip1 b/contrib/ipfilter/test/regress/ip1
new file mode 100644
index 0000000..c31ba25
--- /dev/null
+++ b/contrib/ipfilter/test/regress/ip1
@@ -0,0 +1,78 @@
+#:%s/ \(number = [0-9]*\) \(type = [a-z]*\)/ \2 \1/g
+
+table role = ipf type = tree number = 1
+ {; };
+table role = ipf type = tree number = 100
+ { 1.2.3.4/32; !2.2.0.0/16; 2.2.2.0/24; };
+table role = nat type = tree number = 110
+ { 1.2.3.4/32; !2.2.0.0/16; 2.2.2.0/24; };
+table role = auth type = tree number = 120
+ { 1.2.3.4/32; !2.2.0.0/16; 2.2.2.0/24; };
+table role = count type = tree number = 130
+ { 1.2.3.4; !2.2.0.0/16; 2.2.2.0/24; };
+
+table role = ipf type = hash number = 2
+ {; };
+table role = ipf type = hash number = 200
+ { 0/0; 1/32; 1.2.3.4/32; };
+table role = nat type = hash number = 210
+ { 0/0; 2/32; 1.2.3.4/32; };
+table role = auth type = hash number = 220
+ { 0/0; 3/32; 1.2.3.4/32; };
+table role = count type = hash number = 230
+ { 0/0; 4/32; 1.2.3.4/32; };
+
+table role = ipf type = hash number = 240 seed = 101
+ { 0/0; 1/32; 1.2.3.4/32; };
+table role = nat type = hash number = 250 seed = 101
+ { 0/0; 2/32; 1.2.3.4/32; };
+table role = auth type = hash number = 260 seed = 101
+ { 0/0; 3/32; 1.2.3.4/32; };
+table role = count type = hash number = 270 seed = 101
+ { 0/0; 4/32; 1.2.3.4/32; };
+
+table role = ipf type = hash number = 2000 size = 1001
+ { 0/0; 1/32; 1.2.3.4/32; };
+table role = nat type = hash number = 2000 size = 1001
+ { 0/0; 2/32; 1.2.3.4/32; };
+table role = auth type = hash number = 2000 size = 1001
+ { 0/0; 3/32; 1.2.3.4/32; };
+table role = count type = hash number = 2000 size = 1001
+ { 0/0; 4/32; 1.2.3.4/32; };
+
+table role = ipf type = hash number = 100 size = 1001 seed = 101
+ { 0/0; 1/32; 1.2.3.4/32; };
+table role = nat type = hash number = 100 size = 1001 seed = 101
+ { 0/0; 2/32; 1.2.3.4/32; };
+table role = auth type = hash number = 100 size = 1001 seed = 101
+ { 0/0; 3/32; 1.2.3.4/32; };
+table role = count type = hash number = 100 size = 1001 seed = 101
+ { 0/0; 4/32; 1.2.3.4/32; };
+
+group-map in role = ipf number = 300 group = 303
+ { 0/0; 5/32; 1.2.3.4/32; };
+group-map in role = nat number = 300 group = 303
+ { 0/0; 6/32; 1.2.3.4/32; };
+group-map in role = auth number = 300 group = 303
+ { 0/0; 7/32; 1.2.3.4/32; };
+group-map in role = count number = 300 group = 303
+ { 0/0; 8/32; 1.2.3.4/32; };
+
+group-map out role = ipf number = 400 group = 303
+ { 0/0; 5/32; 1.2.3.4/32, group = 606; };
+group-map out role = nat number = 400 group = 303
+ { 0/0; 6/32; 1.2.3.4/32, group = 606; };
+group-map out role = auth number = 400 group = 303
+ { 0/0; 7/32; 1.2.3.4/32, group = 606; };
+group-map out role = count number = 400 group = 303
+ { 0/0; 8/32; 1.2.3.4/32, group = 606; };
+
+group-map in role = ipf number = 500
+ { 0/0, group = 10; 5/32, group = 800; 1.2.3.4/32, group = 606; };
+group-map in role = nat number = 500
+ { 0/0, group = 10; 6/32, group = 800; 1.2.3.4/32, group = 606; };
+group-map in role = auth number = 500
+ { 0/0, group = 10; 7/32, group = 800; 1.2.3.4/32, group = 606; };
+group-map in role = count number = 500
+ { 0/0, group = 10; 8/32, group = 800; 1.2.3.4/32, group = 606; };
+
diff --git a/contrib/ipfilter/test/regress/n10 b/contrib/ipfilter/test/regress/n10
new file mode 100644
index 0000000..0f48192
--- /dev/null
+++ b/contrib/ipfilter/test/regress/n10
@@ -0,0 +1,3 @@
+map ppp0 0/0 -> 203.203.203.203/32 mssclamp 100
+map ppp0 0/0 -> 203.203.203.203/32 mssclamp 1000
+map ppp0 0/0 -> 203.203.203.203/32 mssclamp 10000
diff --git a/contrib/ipfilter/test/regress/n11 b/contrib/ipfilter/test/regress/n11
new file mode 100644
index 0000000..8cdf7fc
--- /dev/null
+++ b/contrib/ipfilter/test/regress/n11
@@ -0,0 +1,3 @@
+bimap zx0 10.1.1.1/32 -> 1.6.7.8/32
+bimap zx0 10.1.1.0/24 -> 10.2.2.2/32
+bimap zx0 10.1.1.0/24 -> 10.3.4.5/24
diff --git a/contrib/ipfilter/test/regress/n12 b/contrib/ipfilter/test/regress/n12
new file mode 100644
index 0000000..225675b
--- /dev/null
+++ b/contrib/ipfilter/test/regress/n12
@@ -0,0 +1 @@
+map le0 192.168.126.0/24 -> 0/32 portmap tcp/udp 10000:20000
diff --git a/contrib/ipfilter/test/regress/n4 b/contrib/ipfilter/test/regress/n4
index b066c7a..e7c0314 100644
--- a/contrib/ipfilter/test/regress/n4
+++ b/contrib/ipfilter/test/regress/n4
@@ -3,3 +3,4 @@ rdr zx0 10.1.1.0/24 port 23 -> 10.2.2.1 port 10023 tcp
rdr zx0 0/0 port 23 -> 10.2.2.1 port 10023 tcp
rdr zx0 10.1.1.0/24 port 53 -> 10.2.2.1 port 10053 udp
rdr zx0 10.1.1.0/24 port 0 -> 10.2.2.1 port 0 tcp
+rdr zx0 10.1.1.0/24 port 0 -> 10.2.2.1 port 0 ip
diff --git a/contrib/ipfilter/test/regress/n7 b/contrib/ipfilter/test/regress/n7
index 4abde53..be995c2 100644
--- a/contrib/ipfilter/test/regress/n7
+++ b/contrib/ipfilter/test/regress/n7
@@ -1,2 +1,3 @@
rdr zx0 10.1.1.1/32 port 23-79 -> 10.2.2.1 port 10023 tcp
+rdr zx0 10.1.1.1/32 port 23-79 -> 10.2.2.1 port = 10023 tcp
rdr zx0 10.1.1.0/24 port 80 -> 10.2.2.1,1.2.2.129 port 3128 tcp
diff --git a/contrib/ipfilter/test/regress/n8 b/contrib/ipfilter/test/regress/n8
new file mode 100644
index 0000000..bf0e94f
--- /dev/null
+++ b/contrib/ipfilter/test/regress/n8
@@ -0,0 +1 @@
+map icmp0 2.2.2.0/24 -> 10.10.10.0/24
diff --git a/contrib/ipfilter/test/regress/n9 b/contrib/ipfilter/test/regress/n9
new file mode 100644
index 0000000..81a7ccd
--- /dev/null
+++ b/contrib/ipfilter/test/regress/n9
@@ -0,0 +1 @@
+rdr icmp0 4.4.4.0/24 port 0 -> 10.10.10.1 port 0 ip
diff --git a/contrib/ipfilter/test/regress/ni10.nat b/contrib/ipfilter/test/regress/ni10.nat
index 5257818..2a04ef7 100644
--- a/contrib/ipfilter/test/regress/ni10.nat
+++ b/contrib/ipfilter/test/regress/ni10.nat
@@ -1 +1 @@
-rdr df0 2.2.2.2/32 port 0 -> 6.6.6.6 port 0 ip
+rdr df0 2.2.2.2/32 -> 6.6.6.6
diff --git a/contrib/ipfilter/test/regress/ni11.nat b/contrib/ipfilter/test/regress/ni11.nat
index 87e9673..1d0018c 100644
--- a/contrib/ipfilter/test/regress/ni11.nat
+++ b/contrib/ipfilter/test/regress/ni11.nat
@@ -1 +1 @@
-rdr df0 10.0.0.0/8 port 1000-2000 -> 1.1.1.1 port 40000 tcp/udp
+rdr df0 10.0.0.0/8 port 1000:2000 -> 1.1.1.1 port 40000 tcp/udp
diff --git a/contrib/ipfilter/test/regress/ni12.ipf b/contrib/ipfilter/test/regress/ni12.ipf
new file mode 100644
index 0000000..4151b6e
--- /dev/null
+++ b/contrib/ipfilter/test/regress/ni12.ipf
@@ -0,0 +1,4 @@
+block in all
+block out all
+pass in proto udp from any to any keep state
+pass in proto tcp from any to any flags S keep state
diff --git a/contrib/ipfilter/test/regress/ni12.nat b/contrib/ipfilter/test/regress/ni12.nat
new file mode 100644
index 0000000..8c36bc8
--- /dev/null
+++ b/contrib/ipfilter/test/regress/ni12.nat
@@ -0,0 +1 @@
+rdr df0 10.0.0.0/8 port 1000:2000 -> 1.1.1.1 port = 40000 tcp/udp
diff --git a/contrib/ipfilter/test/regress/ni13.ipf b/contrib/ipfilter/test/regress/ni13.ipf
new file mode 100644
index 0000000..04b6d13
--- /dev/null
+++ b/contrib/ipfilter/test/regress/ni13.ipf
@@ -0,0 +1,3 @@
+pass in quick on pcn1 proto tcp from any to any port = 1723 keep state
+block in all
+block out all
diff --git a/contrib/ipfilter/test/regress/ni13.nat b/contrib/ipfilter/test/regress/ni13.nat
new file mode 100644
index 0000000..7a879d8
--- /dev/null
+++ b/contrib/ipfilter/test/regress/ni13.nat
@@ -0,0 +1 @@
+rdr pcn1 192.168.113.3/32 port 1723 -> 0.0.0.0 port 1723 proxy pptp
diff --git a/contrib/ipfilter/test/regress/ni14.ipf b/contrib/ipfilter/test/regress/ni14.ipf
new file mode 100644
index 0000000..04b6d13
--- /dev/null
+++ b/contrib/ipfilter/test/regress/ni14.ipf
@@ -0,0 +1,3 @@
+pass in quick on pcn1 proto tcp from any to any port = 1723 keep state
+block in all
+block out all
diff --git a/contrib/ipfilter/test/regress/ni14.nat b/contrib/ipfilter/test/regress/ni14.nat
new file mode 100644
index 0000000..c546e99
--- /dev/null
+++ b/contrib/ipfilter/test/regress/ni14.nat
@@ -0,0 +1 @@
+rdr pcn1 192.168.113.3/32 port 1723 -> 127.0.0.1 port 1723 proxy pptp
diff --git a/contrib/ipfilter/test/regress/ni15.ipf b/contrib/ipfilter/test/regress/ni15.ipf
new file mode 100644
index 0000000..1b9a013
--- /dev/null
+++ b/contrib/ipfilter/test/regress/ni15.ipf
@@ -0,0 +1,3 @@
+pass out quick on pcn1 proto tcp from any to any port = 1723 keep state
+block in all
+block out all
diff --git a/contrib/ipfilter/test/regress/ni15.nat b/contrib/ipfilter/test/regress/ni15.nat
new file mode 100644
index 0000000..420c7b7
--- /dev/null
+++ b/contrib/ipfilter/test/regress/ni15.nat
@@ -0,0 +1 @@
+map pcn1 0/0 -> 0/0 proxy port 1723 pptp/tcp
diff --git a/contrib/ipfilter/test/regress/ni16.ipf b/contrib/ipfilter/test/regress/ni16.ipf
new file mode 100644
index 0000000..1b9a013
--- /dev/null
+++ b/contrib/ipfilter/test/regress/ni16.ipf
@@ -0,0 +1,3 @@
+pass out quick on pcn1 proto tcp from any to any port = 1723 keep state
+block in all
+block out all
diff --git a/contrib/ipfilter/test/regress/ni16.nat b/contrib/ipfilter/test/regress/ni16.nat
new file mode 100644
index 0000000..5fad3cd
--- /dev/null
+++ b/contrib/ipfilter/test/regress/ni16.nat
@@ -0,0 +1 @@
+map pcn1 10.2.2.2/32 -> 0/32 proxy port 1723 pptp/tcp
diff --git a/contrib/ipfilter/test/regress/ni6.ipf b/contrib/ipfilter/test/regress/ni6.ipf
new file mode 100644
index 0000000..f5b83b2
--- /dev/null
+++ b/contrib/ipfilter/test/regress/ni6.ipf
@@ -0,0 +1,9 @@
+block out log quick on qfe0 from 192.168.7.0/24 to any
+block out log quick on nf0 from 192.168.6.0/24 to any
+pass in quick on nf0 proto tcp from any to any port = 111 flags S keep state
+pass in quick on nf0 proto udp from any to any port = 111 keep state
+block return-rst in log quick on nf0 proto tcp from any to any
+block in log quick on nf0 from 192.168.7.0/24 to any
+block return-rst in log quick on qfe0 proto tcp from any to any
+block in log quick on qfe0 from 192.168.6.0/24 to any
+
diff --git a/contrib/ipfilter/test/regress/ni6.nat b/contrib/ipfilter/test/regress/ni6.nat
new file mode 100644
index 0000000..00d57d0
--- /dev/null
+++ b/contrib/ipfilter/test/regress/ni6.nat
@@ -0,0 +1,3 @@
+rdr nf0 192.168.6.2 port 111 -> 192.168.7.1 port 111 udp proxy rpcbu
+rdr nf0 192.168.6.2 port 111 -> 192.168.7.1 port 111 tcp proxy rpcbt
+map qfe0 192.168.6.0/24 -> 192.168.7.2/32
diff --git a/contrib/ipfilter/test/regress/ni7.nat b/contrib/ipfilter/test/regress/ni7.nat
index 5257818..2a04ef7 100644
--- a/contrib/ipfilter/test/regress/ni7.nat
+++ b/contrib/ipfilter/test/regress/ni7.nat
@@ -1 +1 @@
-rdr df0 2.2.2.2/32 port 0 -> 6.6.6.6 port 0 ip
+rdr df0 2.2.2.2/32 -> 6.6.6.6
diff --git a/contrib/ipfilter/test/regress/ni8.nat b/contrib/ipfilter/test/regress/ni8.nat
index 87e9673..1d0018c 100644
--- a/contrib/ipfilter/test/regress/ni8.nat
+++ b/contrib/ipfilter/test/regress/ni8.nat
@@ -1 +1 @@
-rdr df0 10.0.0.0/8 port 1000-2000 -> 1.1.1.1 port 40000 tcp/udp
+rdr df0 10.0.0.0/8 port 1000:2000 -> 1.1.1.1 port 40000 tcp/udp
diff --git a/contrib/ipfilter/test/regress/ni9.ipf b/contrib/ipfilter/test/regress/ni9.ipf
new file mode 100644
index 0000000..6666241
--- /dev/null
+++ b/contrib/ipfilter/test/regress/ni9.ipf
@@ -0,0 +1 @@
+pass in quick proto tcp from any to any flags S/SAFR keep state
diff --git a/contrib/ipfilter/test/regress/ni9.nat b/contrib/ipfilter/test/regress/ni9.nat
new file mode 100644
index 0000000..8c36bc8
--- /dev/null
+++ b/contrib/ipfilter/test/regress/ni9.nat
@@ -0,0 +1 @@
+rdr df0 10.0.0.0/8 port 1000:2000 -> 1.1.1.1 port = 40000 tcp/udp
diff --git a/contrib/ipfilter/test/regress/p1.ipf b/contrib/ipfilter/test/regress/p1.ipf
new file mode 100644
index 0000000..acaf639
--- /dev/null
+++ b/contrib/ipfilter/test/regress/p1.ipf
@@ -0,0 +1 @@
+pass in from pool/100 to any
diff --git a/contrib/ipfilter/test/regress/p1.pool b/contrib/ipfilter/test/regress/p1.pool
new file mode 100644
index 0000000..14ae3a3
--- /dev/null
+++ b/contrib/ipfilter/test/regress/p1.pool
@@ -0,0 +1,2 @@
+table role = ipf type = tree number = 100
+ { 1.1.1.1/32; !2.2.0.0/16; 2.2.2.0/24; };
diff --git a/contrib/ipfilter/test/regress/p2.ipf b/contrib/ipfilter/test/regress/p2.ipf
new file mode 100644
index 0000000..5b58647
--- /dev/null
+++ b/contrib/ipfilter/test/regress/p2.ipf
@@ -0,0 +1 @@
+pass out from hash=(127.0.0.1,4.4.0.0/16) to any
diff --git a/contrib/ipfilter/test/regress/p3.ipf b/contrib/ipfilter/test/regress/p3.ipf
new file mode 100644
index 0000000..aad7cb3
--- /dev/null
+++ b/contrib/ipfilter/test/regress/p3.ipf
@@ -0,0 +1,6 @@
+call now fr_srcgrpmap/1010 in all
+call now fr_dstgrpmap/2010 out all
+pass in all group 1020
+block in all group 1030
+pass out all group 2020
+block out all group 2040
diff --git a/contrib/ipfilter/test/regress/p3.pool b/contrib/ipfilter/test/regress/p3.pool
new file mode 100644
index 0000000..3fadd59
--- /dev/null
+++ b/contrib/ipfilter/test/regress/p3.pool
@@ -0,0 +1,4 @@
+group-map in role = ipf number = 1010
+ { 1.1.1.1/32, group = 1020; 3.3.0.0/16, group = 1030; };
+group-map out role = ipf number = 2010 group = 2020
+ { 2.2.2.2/32; 4.4.0.0/16; 5.0.0.0/8, group = 2040; };
diff --git a/contrib/ipfilter/test/test.format b/contrib/ipfilter/test/test.format
new file mode 100644
index 0000000..090c8a9
--- /dev/null
+++ b/contrib/ipfilter/test/test.format
@@ -0,0 +1,77 @@
+#test input-format output-format
+bpf-f1 text text
+bpf1 text text
+f1 text text
+f2 text text
+f3 text text
+f4 text text
+f5 text text
+f6 text text
+f7 text text
+f8 text text
+f9 text text
+f10 text text
+f11 text text
+f12 hex hex
+f13 hex hex
+f14 text text
+f15 text text
+f16 text text
+f17 hex hex
+i1 text text
+i2 text text
+i3 text text
+i4 text text
+i5 text text
+i6 text text
+i7 text text
+i8 text text
+i9 text text
+i10 text text
+i11 text text
+i12 text text
+i13 text text
+i14 text text
+i15 text text
+in1 text text
+in2 text text
+in3 text text
+in4 text text
+in5 text text
+in6 text text
+ip1 text text
+ipv6.1 hex hex
+ipv6.2 hex hex
+ipv6.3 hex hex
+l1 hex hex
+n1 text text
+n2 text text
+n3 text text
+n4 text text
+n5 text text
+n6 text text
+n7 text text
+n8 hex hex fr_update_ipid=0
+n9 hex hex fr_update_ipid=0
+n10 hex hex fr_update_ipid=0
+n11 text text
+n12 hex hex fr_update_ipid=0
+ni1 hex hex fr_update_ipid=1
+ni2 hex hex fr_update_ipid=1
+ni3 hex hex fr_update_ipid=1
+ni4 hex hex fr_update_ipid=1
+ni5 hex hex fr_update_ipid=1
+ni6 hex hex fr_update_ipid=1
+ni7 hex hex fr_update_ipid=1
+ni8 hex hex fr_update_ipid=1
+ni9 hex hex fr_update_ipid=1
+ni10 hex hex fr_update_ipid=1
+ni11 hex hex fr_update_ipid=1
+ni12 hex hex fr_update_ipid=1
+ni13 hex hex fr_update_ipid=1
+ni14 hex hex fr_update_ipid=1
+ni15 hex hex fr_update_ipid=1
+ni16 hex hex fr_update_ipid=1
+p1 text text
+p2 text text
+p3 text text
diff --git a/contrib/ipfilter/test/vfycksum.pl b/contrib/ipfilter/test/vfycksum.pl
index b6a2076..9cb47f6 100755
--- a/contrib/ipfilter/test/vfycksum.pl
+++ b/contrib/ipfilter/test/vfycksum.pl
@@ -62,7 +62,7 @@ sub tcpcheck {
local($base) = $_[0];
local($hl) = $bytes[$base] / 256;
return if (($hl >> 4) != 4);
- return if ($bytes[3] & 0x1fff);
+ return if ($bytes[$base + 3] & 0x1fff);
$hl &= 0xf;
$hl <<= 1;
@@ -79,10 +79,27 @@ sub tcpcheck {
local($thl) = $bytes[$base + $hl + 6] >> 8;
$thl &= 0xf0;
$thl >>= 2;
- if (($bytes[$base + 1] > ($cnt - $base) * 2) ||
- (($cnt - $base) * 2 < $hl + 20) ||
- (($cnt - $base) * 2 < $hl + $thl)) {
- print " TCP: missing data";
+
+ $x = $bytes[$base + 1];
+ $y = ($cnt - $base) * 2;
+ $z = 0;
+ if ($bytes[$base + 1] > ($cnt - $base) * 2) {
+ print "[cnt=$cnt base=$base]";
+ $x = $bytes[$base + 1];
+ $y = ($cnt - $base) * 2;
+ $z = 1;
+ } elsif (($cnt - $base) * 2 < $hl + 20) {
+ $x = ($cnt - $base) * 2;
+ $y = $hl + 20;
+ $z = 2;
+ } elsif (($cnt - $base) * 2 < $hl + $thl) {
+ $x = ($cnt - $base) * 2;
+ $y = $hl + $thl;
+ $z = 3;
+ }
+
+ if ($z) {
+ print " TCP: missing data($x $y $z)";
return;
}
@@ -95,7 +112,7 @@ sub tcpcheck {
$bytes[$tcpat + 8] = $osum;
printf " TCP: (%x) %x != %x", $hs, $osum, $hs2;
} else {
- print " TCP: ok";
+ print " TCP: ok ($x $y)";
}
}
@@ -161,8 +178,15 @@ sub icmpcheck {
local($len) = $bytes[$base + 1] - ($hl << 1);
- if ($len > $cnt * 2) {
- print "missing icmp data\n";
+ if ($bytes[$base + 1] > ($cnt - $base) * 2) {
+ print " ICMP: missing data(1)";
+ return;
+ } elsif ($bytes[$base + 1] < ($hl << 1) + 8) {
+ print " ICMP: missing data(2)";
+ return;
+ } elsif (($cnt - $base) * 2 < ($hl << 1) + 8) {
+ print " ICMP: missing data(3)";
+ return;
}
local($osum) = $bytes[$base + $hl + 1];
@@ -240,6 +264,7 @@ $b=$_;
$y = hex $x;
s/[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F] *(.*)/$1/;
$bytes[$cnt] = $y;
+#print "bytes[$cnt] = $x\n";
$cnt++;
}
diff --git a/contrib/ipfilter/todo b/contrib/ipfilter/todo
index 4c2adf1..5b2c059 100644
--- a/contrib/ipfilter/todo
+++ b/contrib/ipfilter/todo
@@ -7,9 +7,14 @@ fastroute works
GENERAL:
--------
+* support redirection like "rdr tun0 0/32 port 80 ..."
+
* use fr_tcpstate() with NAT code for increased NAT usage security or even
fr_checkstate() - suspect this is not possible.
+* add another alias for <thishost> for interfaces <thisif>? as well as
+ all IP#'s associated with the box <myaddrs>?
+
time permitting:
* load balancing across interfaces
@@ -17,21 +22,13 @@ time permitting:
* record buffering for TCP/UDP
* modular application proxying
-available
+-done
* allow multiple ip addresses in a source route list for ipsend
-* complete Linux port to implement all the IP Filter features
-return-rst done, to/dup-to/fastroute remain - ip_forward() problems :-(
-on hold until rewrite
-
-* add a flag to automate src spoofing
-done
+* port IP Filter to Linux
+Not in this century.
-* ipfsync() should change IP#'s in current mappings as well as what's
- in rules.
-done
-
* document bimap
* document NAT rule order processing
@@ -43,22 +40,23 @@ in progress
XDDD. I agree. Bandwidth Shapping and QoS (Quality of Service, AKA
traffic priorization) should be *TOP* in the TO DO list.
-* irc proxy for dcc
* Bandwidth limiting!!!
+maybe for solaris, otherwise "ALTQ"
* More examples
* More documentation
-* And did I mention bandwidth limiting???
* Load balancing features added to the NAT code, so that I can have
something coming in for 20.20.20.20:80 and it gets shuffled around between
internal addresses 10.10.10.1:8000 and 10.10.10.2:8000. or whatever.
- done, stage 1 (round robin/split)
The one thing that Cisco's PIX has on IPF that I can see is that
rewrites the sequence numbers with semi-random ones.
+- done
I would also love to see a more extensive NAT. It can choose to do
rdr and map based on saddr, daddr, sport and dport. (Does the kernel
module already have functionality for that and it just needs support in
the userland ipnat?)
+-sort of done
* intrusion detection
detection of port scans
@@ -76,23 +74,25 @@ the userland ipnat?)
large packets of garbage or other packets to
otherwise confuse the intruder (ping of death?)
-* I ran into your solaris streams stuff and noticed you are
-playing with mblk's in an unsafe way. You seem to be modifying the
-underlying datab without checking db_ref. If db_ref is greater than one,
-you'll need to copy the mblk,
-- fixed
-
-* fix up where manual pages go for Solaris2
-
-
IPv6:
-----
* NAT is yet not available, either as a null proxy or address translation
BSD:
* "to <if>" and "to <if>:<ip>" are not supported, but "fastroute" is.
-fixed.
Solaris:
* "to <if>:<ip>" is not supported, but "fastroute" is and "to <if>" are.
+Tru64:
+------
+* IPv6 checksum calculation for RST's and ICMP packets is not done (there
+ are routines in the Tru64 kernel to do this but what is the interface?)
+
+does bimap allow equal sized subnets?
+
+make return-icmp 'intelligent' if no type is given about what type to use?
+
+reply-to - enforce packets to pass through interfaces in particular
+combinations - opposite to "to", set reverse path interface
+
diff --git a/contrib/ipfilter/tools/BNF.ipf b/contrib/ipfilter/tools/BNF.ipf
new file mode 100644
index 0000000..0e84332
--- /dev/null
+++ b/contrib/ipfilter/tools/BNF.ipf
@@ -0,0 +1,80 @@
+filter-rule = [ insert ] action in-out [ options ] [ tos ] [ ttl ]
+ [ proto ] [ ip ] [ group ] [ tag ] [ pps ] .
+
+insert = "@" decnumber .
+action = block | "pass" | log | "count" | auth | call .
+in-out = "in" | "out" .
+options = [ log ] [ "quick" ] [ onif [ dup ] [ froute ] ] .
+tos = "tos" decnumber | "tos" hexnumber .
+ttl = "ttl" decnumber .
+proto = "proto" protocol .
+ip = srcdst [ flags ] [ with withopt ] [ icmp ] [ keep ] .
+group = [ "head" decnumber ] [ "group" decnumber ] .
+pps = "pps" decnumber .
+
+onif = "on" interface-name [ "out-via" interface-name ] .
+block = "block" [ return-icmp[return-code] | "return-rst" ] .
+auth = "auth" | "preauth" .
+log = "log" [ "body" ] [ "first" ] [ "or-block" ] [ "level" loglevel ] .
+tag = "tag" tagid .
+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 .
+
+return-icmp = "return-icmp" | "return-icmp-as-dest" .
+loglevel = facility"."priority | priority .
+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" [ "limit" number ] | "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" | "nat" | "bad-src" | "lowttl" | "frag" |
+ "mbcast" | "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" | "routerad" |
+ "routersol" | 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" |
+ "filter-prohib" | "host-preced" | "cutoff-preced" .
+optlist = "nop" | "rr" | "zsu" | "mtup" | "mtur" | "encode" | "ts" | "tr" |
+ "sec" | "lsrr" | "e-sec" | "cipso" | "satid" | "ssrr" | "addext" |
+ "visa" | "imitd" | "eip" | "finn" .
+facility = "kern" | "user" | "mail" | "daemon" | "auth" | "syslog" |
+ "lpr" | "news" | "uucp" | "cron" | "ftp" | "authpriv" |
+ "audit" | "logalert" | "local0" | "local1" | "local2" |
+ "local3" | "local4" | "local5" | "local6" | "local7" .
+priority = "emerg" | "alert" | "crit" | "err" | "warn" | "notice" |
+ "info" | "debug" .
+
+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" | "C" | "W" .
diff --git a/contrib/ipfilter/tools/BNF.ipnat b/contrib/ipfilter/tools/BNF.ipnat
new file mode 100644
index 0000000..69ed8a2
--- /dev/null
+++ b/contrib/ipfilter/tools/BNF.ipnat
@@ -0,0 +1,28 @@
+ipmap :: = mapblock | redir | map .
+
+map ::= mapit ifname ipmask "->" ipmask [ mapport | mapicmpid ] .
+map ::= mapit ifname fromto "->" ipmask [ mapport | mapicmpid ] .
+mapblock ::= "map-block" ifname ipmask "->" ipmask [ ports ] .
+redir ::= "rdr" ifname ipmask dport "->" ip [ "," ip ] [ ports ] options .
+
+dport ::= "port" portnum [ "-" portnum ] .
+ports ::= "ports" numports | "auto" .
+mapit ::= "map" | "bimap" .
+fromto ::= "from" object "to" object .
+ipmask ::= ip "/" bits | ip "/" mask | ip "netmask" mask .
+mapport ::= "portmap" tcpudp portnumber ":" portnumber .
+mapicmpid ::= "icmpidmap" icmp idnumber ":" idnumber .
+options ::= [ tcpudp ] [ rr ] .
+
+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 .
+
+rr ::= "round-robin" .
+tcpudp ::= "tcp" | "udp" | "tcp/udp" .
+portnumber ::= number { numbers } | "auto" .
+idnumber ::= number { numbers } .
+ifname ::= 'A' - 'Z' { 'A' - 'Z' } numbers .
+
+numbers ::= '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' .
diff --git a/contrib/ipfilter/tools/Makefile b/contrib/ipfilter/tools/Makefile
new file mode 100644
index 0000000..49a869c
--- /dev/null
+++ b/contrib/ipfilter/tools/Makefile
@@ -0,0 +1,103 @@
+
+DEST=.
+
+all: $(DEST)/ipf_y.c $(DEST)/ipf_y.h $(DEST)/ipf_l.c \
+ $(DEST)/ipmon_y.c $(DEST)/ipmon_y.h $(DEST)/ipmon_l.c \
+ $(DEST)/ipnat_y.c $(DEST)/ipnat_y.h $(DEST)/ipnat_l.c \
+ $(DEST)/ipscan_y.c $(DEST)/ipscan_y.h $(DEST)/ipscan_l.c \
+ $(DEST)/ippool_y.c $(DEST)/ippool_y.h $(DEST)/ippool_l.c \
+ $(DEST)/ipf_l.h $(DEST)/ipnat_l.h $(DEST)/ipscan_l.h \
+ $(DEST)/ippool_l.h $(DEST)/ipmon_l.h
+
+$(DEST)/ipf_y.h: $(DEST)/ipf_y.c
+
+$(DEST)/ipf_y.c: ipf_y.y
+ yacc -d ipf_y.y
+ sed -e 's/yy/ipf_yy/g' -e 's/y.tab.h/ipf_y.c/' \
+ -e 's/"ipf_y.y"/"..\/tools\/ipf_y.y"/' \
+ y.tab.c > $(DEST)/ipf_y.c
+ sed -e 's/yy/ipf_yy/g' -e 's/y.tab.h/ipf_y.h/' y.tab.h > $(DEST)/ipf_y.h
+ /bin/rm -f y.tab.c y.tab.h
+
+$(DEST)/ipf_l.c: lexer.c
+ sed -e 's/yy/ipf_yy/g' -e 's/y.tab.h/ipf_y.h/' \
+ -e 's/lexer.h/ipf_l.h/' lexer.c > $@
+
+$(DEST)/ipmon_y.n: $(DEST)/ipmon_y.c
+
+$(DEST)/ipmon_y.c $(DEST)/ipmon_y.h: ipmon_y.y
+ yacc -d ipmon_y.y
+ sed -e 's/yy/ipmon_yy/g' -e 's/"ipmon_y.y"/"..\/tools\/ipmon_y.y"/' \
+ y.tab.c > $(DEST)/ipmon_y.c
+ sed -e 's/yy/ipmon_yy/g' y.tab.h > $(DEST)/ipmon_y.h
+ /bin/rm -f y.tab.c y.tab.h
+
+$(DEST)/ipmon_l.c: lexer.c
+ sed -e 's/yy/ipmon_yy/g' -e 's/y.tab.h/ipmon_y.h/' \
+ -e 's/lexer.h/ipmon_l.h/' lexer.c > $@
+
+$(DEST)/ipscan_y.h: $(DEST)/ipscan_y.c
+
+$(DEST)/ipscan_y.c $(DEST)/ipscan_y.h: ipscan_y.y
+ yacc -d ipscan_y.y
+ sed -e 's/yy/ipscan_yy/g' \
+ -e 's/"ipscan_y.y"/"..\/tools\/ipscan_y.y"/' \
+ y.tab.c > $(DEST)/ipscan_y.c
+ sed -e 's/yy/ipscan_yy/g' y.tab.h > $(DEST)/ipscan_y.h
+ /bin/rm -f y.tab.c y.tab.h
+
+$(DEST)/ipscan_l.c: lexer.c
+ sed -e 's/yy/ipscan_yy/g' -e 's/y.tab.h/ipscan_y.h/' \
+ -e 's/lexer.h/ipscan_l.h/' lexer.c > $@
+
+$(DEST)/ippool_y.h: $(DEST)/ippool_y.c
+
+$(DEST)/ippool_y.c $(DEST)/ippool_y.h: ippool_y.y
+ yacc -d ippool_y.y
+ sed -e 's/yy/ippool_yy/g' -e 's/"ippool_y.y"/"..\/tools\/ippool_y.y"/' \
+ y.tab.c > $(DEST)/ippool_y.c
+ sed -e 's/yy/ippool_yy/g' y.tab.h > $(DEST)/ippool_y.h
+ /bin/rm -f y.tab.c y.tab.h
+
+$(DEST)/ippool_l.c: lexer.c
+ sed -e 's/yy/ippool_yy/g' -e 's/y.tab.h/ippool_y.h/' \
+ -e 's/lexer.h/ippool_l.h/' lexer.c > $@
+
+$(DEST)/ipnat_y.h: $(DEST)/ipnat_y.c
+
+$(DEST)/ipnat_y.c $(DEST)/ipnat_y.h: ipnat_y.y
+ yacc -d ipnat_y.y
+ sed -e 's/yy/ipnat_yy/g' -e 's/y.tab.c/ipnat_y.c/' \
+ -e s/\"ipnat_y.y\"/\"..\\/tools\\/ipnat_y.y\"/ \
+ y.tab.c > $(DEST)/ipnat_y.c
+ sed -e 's/yy/ipnat_yy/g' -e 's/y.tab.h/ipnat_y.h/' \
+ y.tab.h > $(DEST)/ipnat_y.h
+ /bin/rm -f y.tab.c y.tab.h
+
+$(DEST)/ipnat_l.c: lexer.c
+ sed -e 's/yy/ipnat_yy/g' -e 's/y.tab.h/ipnat_y.h/' \
+ -e 's/lexer.h/ipnat_l.h/' lexer.c > $@
+
+$(DEST)/ipf_l.h: lexer.h
+ sed -e 's/yy/ipf_yy/g' lexer.h > $@
+
+$(DEST)/ipmon_l.h: lexer.h
+ sed -e 's/yy/ipmon_yy/g' lexer.h > $@
+
+$(DEST)/ipscan_l.h: lexer.h
+ sed -e 's/yy/ipscan_yy/g' lexer.h > $@
+
+$(DEST)/ippool_l.h: lexer.h
+ sed -e 's/yy/ippool_yy/g' lexer.h > $@
+
+$(DEST)/ipnat_l.h: lexer.h
+ sed -e 's/yy/ipnat_yy/g' lexer.h > $@
+
+clean:
+ /bin/rm -f $(DEST)/ipf_y.c $(DEST)/ipf_y.h $(DEST)/ipf_l.c
+ /bin/rm -f $(DEST)/ipmon_y.c $(DEST)/ipmon_y.h $(DEST)/ipmon_l.c
+ /bin/rm -f $(DEST)/ipscan_y.c $(DEST)/ipscan_y.h $(DEST)/ipscan_l.c
+ /bin/rm -f $(DEST)/ippool_y.c $(DEST)/ippool_y.h $(DEST)/ippool_l.c
+ /bin/rm -f $(DEST)/ipnat_y.c $(DEST)/ipnat_y.h $(DEST)/ipnat_l.c
+ /bin/rm -f $(DEST)/ipf_l.h $(DEST)/ipmon_l.h $(DEST)/ippool_l.h
+ /bin/rm -f $(DEST)/ipscan_l.h $(DEST)/ipnat_l.h
diff --git a/contrib/ipfilter/tools/ipf.c b/contrib/ipfilter/tools/ipf.c
new file mode 100644
index 0000000..ea39780
--- /dev/null
+++ b/contrib/ipfilter/tools/ipf.c
@@ -0,0 +1,562 @@
+/* $NetBSD$ */
+
+/*
+ * Copyright (C) 1993-2001 by Darren Reed.
+ *
+ * See the IPFILTER.LICENCE file for details on licencing.
+ */
+#ifdef __FreeBSD__
+# ifndef __FreeBSD_cc_version
+# include <osreldate.h>
+# else
+# if __FreeBSD_cc_version < 430000
+# include <osreldate.h>
+# endif
+# endif
+#endif
+#include "ipf.h"
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include "netinet/ipl.h"
+
+#if !defined(lint)
+static const char sccsid[] = "@(#)ipf.c 1.23 6/5/96 (C) 1993-2000 Darren Reed";
+static const char rcsid[] = "@(#)Id: ipf.c,v 1.35.2.3 2004/12/15 18:27:17 darrenr Exp";
+#endif
+
+#if !defined(__SVR4) && defined(__GNUC__)
+extern char *index __P((const char *, int));
+#endif
+
+extern char *optarg;
+extern int optind;
+extern frentry_t *frtop;
+
+
+void ipf_frsync __P((void));
+void zerostats __P((void));
+int main __P((int, char *[]));
+
+int opts = 0;
+int outputc = 0;
+int use_inet6 = 0;
+
+static void procfile __P((char *, char *)), flushfilter __P((char *));
+static void set_state __P((u_int)), showstats __P((friostat_t *));
+static void packetlogon __P((char *)), swapactive __P((void));
+static int opendevice __P((char *, int));
+static void closedevice __P((void));
+static char *ipfname = IPL_NAME;
+static void usage __P((void));
+static int showversion __P((void));
+static int get_flags __P((void));
+static void ipf_interceptadd __P((int, ioctlfunc_t, void *));
+
+static int fd = -1;
+static ioctlfunc_t iocfunctions[IPL_LOGSIZE] = { ioctl, ioctl, ioctl,
+ ioctl, ioctl, ioctl,
+ ioctl, ioctl };
+
+
+static void usage()
+{
+ fprintf(stderr, "usage: ipf [-6AdDEInoPrRsvVyzZ] %s %s %s\n",
+ "[-l block|pass|nomatch|state|nat]", "[-cc] [-F i|o|a|s|S|u]",
+ "[-f filename] [-T <tuneopts>]");
+ exit(1);
+}
+
+
+int main(argc,argv)
+int argc;
+char *argv[];
+{
+ int c;
+
+ if (argc < 2)
+ usage();
+
+ while ((c = getopt(argc, argv, "6Ac:dDEf:F:Il:noPrRsT:vVyzZ")) != -1) {
+ switch (c)
+ {
+ case '?' :
+ usage();
+ break;
+#ifdef USE_INET6
+ case '6' :
+ use_inet6 = 1;
+ break;
+#endif
+ case 'A' :
+ opts &= ~OPT_INACTIVE;
+ break;
+ case 'c' :
+ if (strcmp(optarg, "c") == 0)
+ outputc = 1;
+ break;
+ case 'E' :
+ set_state((u_int)1);
+ break;
+ case 'D' :
+ set_state((u_int)0);
+ 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' :
+ break;
+ case 'P' :
+ ipfname = IPAUTH_NAME;
+ break;
+ case 'R' :
+ opts ^= OPT_NORESOLVE;
+ break;
+ case 'r' :
+ opts ^= OPT_REMOVE;
+ break;
+ case 's' :
+ swapactive();
+ break;
+ case 'T' :
+ if (opendevice(ipfname, 1) >= 0)
+ ipf_dotuning(fd, optarg, ioctl);
+ break;
+ case 'v' :
+ opts += OPT_VERBOSE;
+ break;
+ case 'V' :
+ if (showversion())
+ exit(1);
+ break;
+ case 'y' :
+ ipf_frsync();
+ break;
+ case 'z' :
+ opts ^= OPT_ZERORULEST;
+ break;
+ case 'Z' :
+ zerostats();
+ break;
+ }
+ }
+
+ if (optind < 2)
+ usage();
+
+ if (fd != -1)
+ (void) close(fd);
+
+ return(0);
+ /* NOTREACHED */
+}
+
+
+static int opendevice(ipfdev, check)
+char *ipfdev;
+int check;
+{
+ if (opts & OPT_DONOTHING)
+ return -2;
+
+ if (check && checkrev(ipfname) == -1) {
+ fprintf(stderr, "User/kernel version check failed\n");
+ return -2;
+ }
+
+ if (!ipfdev)
+ ipfdev = ipfname;
+
+ if (fd == -1)
+ if ((fd = open(ipfdev, O_RDWR)) == -1)
+ if ((fd = open(ipfdev, O_RDONLY)) == -1)
+ perror("open device");
+ return fd;
+}
+
+
+static void closedevice()
+{
+ close(fd);
+ fd = -1;
+}
+
+
+static int get_flags()
+{
+ int i;
+
+ if ((opendevice(ipfname, 1) != -2) &&
+ (ioctl(fd, SIOCGETFF, &i) == -1)) {
+ perror("SIOCGETFF");
+ return 0;
+ }
+ return i;
+}
+
+
+static void set_state(enable)
+u_int enable;
+{
+ if (opendevice(ipfname, 0) != -2)
+ if (ioctl(fd, SIOCFRENB, &enable) == -1) {
+ if (errno == EBUSY)
+ fprintf(stderr,
+ "IP FIlter: already initialized\n");
+ else
+ perror("SIOCFRENB");
+ }
+ return;
+}
+
+
+static void procfile(name, file)
+char *name, *file;
+{
+ (void) opendevice(ipfname, 1);
+
+ initparse();
+
+ ipf_parsefile(fd, ipf_interceptadd, iocfunctions, file);
+
+ if (outputc) {
+ printC(0);
+ printC(1);
+ emit(-1, -1, NULL, NULL);
+ }
+}
+
+
+static void ipf_interceptadd(fd, ioctlfunc, ptr)
+int fd;
+ioctlfunc_t ioctlfunc;
+void *ptr;
+{
+ if (outputc)
+ printc(ptr);
+
+ ipf_addrule(fd, ioctlfunc, ptr);
+}
+
+
+static void packetlogon(opt)
+char *opt;
+{
+ int flag, xfd, logopt, change = 0;
+
+ flag = get_flags();
+ if (flag != 0) {
+ if ((opts & (OPT_DONOTHING|OPT_VERBOSE)) == OPT_VERBOSE)
+ printf("log flag is currently %#x\n", flag);
+ }
+
+ flag &= ~(FF_LOGPASS|FF_LOGNOMATCH|FF_LOGBLOCK);
+
+ if (strstr(opt, "pass")) {
+ flag |= FF_LOGPASS;
+ if (opts & OPT_VERBOSE)
+ printf("set log flag: pass\n");
+ change = 1;
+ }
+ if (strstr(opt, "nomatch")) {
+ flag |= FF_LOGNOMATCH;
+ if (opts & OPT_VERBOSE)
+ printf("set log flag: nomatch\n");
+ change = 1;
+ }
+ if (strstr(opt, "block") || index(opt, 'd')) {
+ flag |= FF_LOGBLOCK;
+ if (opts & OPT_VERBOSE)
+ printf("set log flag: block\n");
+ change = 1;
+ }
+ if (strstr(opt, "none")) {
+ if (opts & OPT_VERBOSE)
+ printf("disable all log flags\n");
+ change = 1;
+ }
+
+ if (change == 1) {
+ if (opendevice(ipfname, 1) != -2 &&
+ (ioctl(fd, SIOCSETFF, &flag) != 0))
+ perror("ioctl(SIOCSETFF)");
+ }
+
+ if ((opts & (OPT_DONOTHING|OPT_VERBOSE)) == OPT_VERBOSE) {
+ flag = get_flags();
+ printf("log flags are now %#x\n", flag);
+ }
+
+ if (strstr(opt, "state")) {
+ if (opts & OPT_VERBOSE)
+ printf("set state log flag\n");
+ xfd = open(IPSTATE_NAME, O_RDWR);
+ if (xfd >= 0) {
+ logopt = 0;
+ if (ioctl(xfd, SIOCGETLG, &logopt))
+ perror("ioctl(SIOCGETLG)");
+ else {
+ logopt = 1 - logopt;
+ if (ioctl(xfd, SIOCSETLG, &logopt))
+ perror("ioctl(SIOCSETLG)");
+ }
+ close(xfd);
+ }
+ }
+
+ if (strstr(opt, "nat")) {
+ if (opts & OPT_VERBOSE)
+ printf("set nat log flag\n");
+ xfd = open(IPNAT_NAME, O_RDWR);
+ if (xfd >= 0) {
+ logopt = 0;
+ if (ioctl(xfd, SIOCGETLG, &logopt))
+ perror("ioctl(SIOCGETLG)");
+ else {
+ logopt = 1 - logopt;
+ if (ioctl(xfd, SIOCSETLG, &logopt))
+ perror("ioctl(SIOCSETLG)");
+ }
+ close(xfd);
+ }
+ }
+}
+
+
+static void flushfilter(arg)
+char *arg;
+{
+ int fl = 0, rem;
+
+ if (!arg || !*arg)
+ return;
+ if (!strcmp(arg, "s") || !strcmp(arg, "S")) {
+ if (*arg == 'S')
+ fl = 0;
+ else
+ fl = 1;
+ rem = fl;
+
+ closedevice();
+ if (opendevice(IPSTATE_NAME, 1) == -2)
+ exit(1);
+
+ if (!(opts & OPT_DONOTHING)) {
+ if (use_inet6) {
+ if (ioctl(fd, SIOCIPFL6, &fl) == -1) {
+ perror("ioctl(SIOCIPFL6)");
+ exit(1);
+ }
+ } else {
+ if (ioctl(fd, SIOCIPFFL, &fl) == -1) {
+ perror("ioctl(SIOCIPFFL)");
+ exit(1);
+ }
+ }
+ }
+ if ((opts & (OPT_DONOTHING|OPT_VERBOSE)) == OPT_VERBOSE) {
+ printf("remove flags %s (%d)\n", arg, rem);
+ printf("removed %d filter rules\n", fl);
+ }
+ closedevice();
+ return;
+ }
+
+#ifdef SIOCIPFFA
+ if (!strcmp(arg, "u")) {
+ closedevice();
+ /*
+ * Flush auth rules and packets
+ */
+ if (opendevice(IPL_AUTH, 1) == -1)
+ perror("open(IPL_AUTH)");
+ else {
+ if (ioctl(fd, SIOCIPFFA, &fl) == -1)
+ perror("ioctl(SIOCIPFFA)");
+ }
+ closedevice();
+ return;
+ }
+#endif
+
+ 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;
+ if (opts & OPT_INACTIVE)
+ fl |= FR_INACTIVE;
+ rem = fl;
+
+ if (opendevice(ipfname, 1) == -2)
+ exit(1);
+
+ if (!(opts & OPT_DONOTHING)) {
+ if (use_inet6) {
+ if (ioctl(fd, SIOCIPFL6, &fl) == -1) {
+ perror("ioctl(SIOCIPFL6)");
+ exit(1);
+ }
+ } else {
+ if (ioctl(fd, SIOCIPFFL, &fl) == -1) {
+ perror("ioctl(SIOCIPFFL)");
+ exit(1);
+ }
+ }
+ }
+
+ 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(ipfname, 1) != -2 && ioctl(fd, SIOCSWAPA, &in) == -1)
+ perror("ioctl(SIOCSWAPA)");
+ else
+ printf("Set %d now inactive\n", in);
+}
+
+
+void ipf_frsync()
+{
+ int frsyn = 0;
+
+ if (opendevice(ipfname, 1) != -2 && ioctl(fd, SIOCFRSYN, &frsyn) == -1)
+ perror("SIOCFRSYN");
+ else
+ printf("filter sync'd\n");
+}
+
+
+void zerostats()
+{
+ friostat_t fio;
+ friostat_t *fiop = &fio;
+
+ if (opendevice(ipfname, 1) != -2) {
+ if (ioctl(fd, SIOCFRZST, &fiop) == -1) {
+ perror("ioctl(SIOCFRZST)");
+ exit(-1);
+ }
+ showstats(fiop);
+ }
+
+}
+
+
+/*
+ * read the kernel stats for packets blocked and passed
+ */
+static void showstats(fp)
+friostat_t *fp;
+{
+ printf("bad packets:\t\tin %lu\tout %lu\n",
+ fp->f_st[0].fr_bad, fp->f_st[1].fr_bad);
+ 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);
+}
+
+
+static int showversion()
+{
+ struct friostat fio;
+ ipfobj_t ipfo;
+ u_32_t flags;
+ char *s;
+ int vfd;
+
+ bzero((caddr_t)&ipfo, sizeof(ipfo));
+ ipfo.ipfo_rev = IPFILTER_VERSION;
+ ipfo.ipfo_size = sizeof(fio);
+ ipfo.ipfo_ptr = (void *)&fio;
+ ipfo.ipfo_type = IPFOBJ_IPFSTAT;
+
+ printf("ipf: %s (%d)\n", IPL_VERSION, (int)sizeof(frentry_t));
+
+ if ((vfd = open(ipfname, O_RDONLY)) == -1) {
+ perror("open device");
+ return 1;
+ }
+
+ if (ioctl(vfd, SIOCGETFS, &ipfo)) {
+ perror("ioctl(SIOCGETFS)");
+ close(vfd);
+ return 1;
+ }
+ close(vfd);
+ flags = get_flags();
+
+ printf("Kernel: %-*.*s\n", (int)sizeof(fio.f_version),
+ (int)sizeof(fio.f_version), fio.f_version);
+ printf("Running: %s\n", (fio.f_running > 0) ? "yes" : "no");
+ printf("Log Flags: %#x = ", flags);
+ s = "";
+ if (flags & FF_LOGPASS) {
+ printf("pass");
+ s = ", ";
+ }
+ if (flags & FF_LOGBLOCK) {
+ printf("%sblock", s);
+ s = ", ";
+ }
+ if (flags & FF_LOGNOMATCH) {
+ printf("%snomatch", s);
+ s = ", ";
+ }
+ if (flags & FF_BLOCKNONIP) {
+ printf("%snonip", s);
+ s = ", ";
+ }
+ if (!*s)
+ printf("none set");
+ putchar('\n');
+
+ printf("Default: ");
+ if (FR_ISPASS(fio.f_defpass))
+ s = "pass";
+ else if (FR_ISBLOCK(fio.f_defpass))
+ s = "block";
+ else
+ s = "nomatch -> block";
+ printf("%s all, Logging: %savailable\n", s, fio.f_logging ? "" : "un");
+ printf("Active list: %d\n", fio.f_active);
+ printf("Feature mask: %#x\n", fio.f_features);
+
+ return 0;
+}
diff --git a/contrib/ipfilter/tools/ipf_y.y b/contrib/ipfilter/tools/ipf_y.y
new file mode 100644
index 0000000..0660d50
--- /dev/null
+++ b/contrib/ipfilter/tools/ipf_y.y
@@ -0,0 +1,2126 @@
+/* $NetBSD$ */
+
+%{
+#include "ipf.h"
+#include <sys/ioctl.h>
+#include <syslog.h>
+#ifdef IPFILTER_BPF
+# include <pcap-bpf.h>
+# include <pcap.h>
+#endif
+#include "netinet/ip_pool.h"
+#include "netinet/ip_htable.h"
+#include "netinet/ipl.h"
+#include "ipf_l.h"
+
+#define YYDEBUG 1
+#define DOALL(x) for (fr = frc; fr != NULL; fr = fr->fr_next) { x }
+#define DOREM(x) for (; fr != NULL; fr = fr->fr_next) { x }
+
+extern void yyerror __P((char *));
+extern int yyparse __P((void));
+extern int yylex __P((void));
+extern int yydebug;
+extern FILE *yyin;
+extern int yylineNum;
+
+static void newrule __P((void));
+static void setipftype __P((void));
+static u_32_t lookuphost __P((char *));
+static void dobpf __P((int, char *));
+static void resetaddr __P((void));
+static struct alist_s *newalist __P((struct alist_s *));
+static u_int makehash __P((struct alist_s *));
+static int makepool __P((struct alist_s *));
+static frentry_t *addrule __P((void));
+static void setsyslog __P((void));
+static void unsetsyslog __P((void));
+static void fillgroup __P((frentry_t *));
+
+frentry_t *fr = NULL, *frc = NULL, *frtop = NULL, *frold = NULL;
+
+static int ifpflag = 0;
+static int nowith = 0;
+static int dynamic = -1;
+static int pooled = 0;
+static int hashed = 0;
+static int nrules = 0;
+static int newlist = 0;
+static int added = 0;
+static int ipffd = -1;
+static int *yycont = 0;
+static ioctlfunc_t ipfioctl[IPL_LOGSIZE];
+static addfunc_t ipfaddfunc = NULL;
+static struct wordtab ipfwords[95];
+static struct wordtab addrwords[4];
+static struct wordtab maskwords[5];
+static struct wordtab icmpcodewords[17];
+static struct wordtab icmptypewords[16];
+static struct wordtab ipv4optwords[25];
+static struct wordtab ipv4secwords[9];
+static struct wordtab ipv6optwords[8];
+static struct wordtab logwords[33];
+
+%}
+%union {
+ char *str;
+ u_32_t num;
+ struct in_addr ipa;
+ frentry_t fr;
+ frtuc_t *frt;
+ struct alist_s *alist;
+ u_short port;
+ struct {
+ u_short p1;
+ u_short p2;
+ int pc;
+ } pc;
+ struct {
+ union i6addr a;
+ union i6addr m;
+ } ipp;
+ union i6addr ip6;
+};
+
+%type <port> portnum
+%type <num> facility priority icmpcode seclevel secname icmptype
+%type <num> opt compare range opttype flagset optlist ipv6hdrlist ipv6hdr
+%type <num> portc porteq
+%type <ipa> hostname ipv4 ipv4mask ipv4_16 ipv4_24
+%type <ip6> ipv6mask
+%type <ipp> addr ipaddr
+%type <str> servicename name interfacename
+%type <pc> portrange portcomp
+%type <alist> addrlist poollist
+
+%token <num> YY_NUMBER YY_HEX
+%token <str> YY_STR
+%token YY_COMMENT
+%token YY_CMP_EQ YY_CMP_NE YY_CMP_LE YY_CMP_GE YY_CMP_LT YY_CMP_GT
+%token YY_RANGE_OUT YY_RANGE_IN
+%token <ip6> YY_IPV6
+
+%token IPFY_PASS IPFY_BLOCK IPFY_COUNT IPFY_CALL
+%token IPFY_RETICMP IPFY_RETRST IPFY_RETICMPASDST
+%token IPFY_IN IPFY_OUT
+%token IPFY_QUICK IPFY_ON IPFY_OUTVIA IPFY_INVIA
+%token IPFY_DUPTO IPFY_TO IPFY_FROUTE IPFY_REPLY_TO IPFY_ROUTETO
+%token IPFY_TOS IPFY_TTL IPFY_PROTO
+%token IPFY_HEAD IPFY_GROUP
+%token IPFY_AUTH IPFY_PREAUTH
+%token IPFY_LOG IPFY_BODY IPFY_FIRST IPFY_LEVEL IPFY_ORBLOCK
+%token IPFY_LOGTAG IPFY_MATCHTAG IPFY_SETTAG IPFY_SKIP
+%token IPFY_FROM IPFY_ALL IPFY_ANY IPFY_BPFV4 IPFY_BPFV6 IPFY_POOL IPFY_HASH
+%token IPFY_PPS
+%token IPFY_ESP IPFY_AH
+%token IPFY_WITH IPFY_AND IPFY_NOT IPFY_NO IPFY_OPT
+%token IPFY_TCPUDP IPFY_TCP IPFY_UDP
+%token IPFY_FLAGS IPFY_MULTICAST
+%token IPFY_MASK IPFY_BROADCAST IPFY_NETWORK IPFY_NETMASKED IPFY_PEER
+%token IPFY_PORT
+%token IPFY_NOW
+%token IPFY_ICMP IPFY_ICMPTYPE IPFY_ICMPCODE
+%token IPFY_IPOPTS IPFY_SHORT IPFY_NAT IPFY_BADSRC IPFY_LOWTTL IPFY_FRAG
+%token IPFY_MBCAST IPFY_BAD IPFY_BADNAT IPFY_OOW IPFY_NEWISN IPFY_NOICMPERR
+%token IPFY_KEEP IPFY_STATE IPFY_FRAGS IPFY_LIMIT IPFY_STRICT IPFY_AGE
+%token IPFY_SYNC IPFY_FRAGBODY
+%token IPFY_IPOPT_NOP IPFY_IPOPT_RR IPFY_IPOPT_ZSU IPFY_IPOPT_MTUP
+%token IPFY_IPOPT_MTUR IPFY_IPOPT_ENCODE IPFY_IPOPT_TS IPFY_IPOPT_TR
+%token IPFY_IPOPT_SEC IPFY_IPOPT_LSRR IPFY_IPOPT_ESEC IPFY_IPOPT_CIPSO
+%token IPFY_IPOPT_SATID IPFY_IPOPT_SSRR IPFY_IPOPT_ADDEXT IPFY_IPOPT_VISA
+%token IPFY_IPOPT_IMITD IPFY_IPOPT_EIP IPFY_IPOPT_FINN IPFY_IPOPT_DPS
+%token IPFY_IPOPT_SDB IPFY_IPOPT_NSAPA IPFY_IPOPT_RTRALRT IPFY_IPOPT_UMP
+%token IPFY_SECCLASS IPFY_SEC_UNC IPFY_SEC_CONF IPFY_SEC_RSV1 IPFY_SEC_RSV2
+%token IPFY_SEC_RSV4 IPFY_SEC_SEC IPFY_SEC_TS IPFY_SEC_RSV3
+
+%token IPF6_V6HDRS IPFY_IPV6OPT IPFY_IPV6OPT_DSTOPTS IPFY_IPV6OPT_HOPOPTS
+%token IPFY_IPV6OPT_IPV6 IPFY_IPV6OPT_NONE IPFY_IPV6OPT_ROUTING
+
+%token IPFY_ICMPT_UNR IPFY_ICMPT_ECHO IPFY_ICMPT_ECHOR IPFY_ICMPT_SQUENCH
+%token IPFY_ICMPT_REDIR IPFY_ICMPT_TIMEX IPFY_ICMPT_PARAMP IPFY_ICMPT_TIMEST
+%token IPFY_ICMPT_TIMESTREP IPFY_ICMPT_INFOREQ IPFY_ICMPT_INFOREP
+%token IPFY_ICMPT_MASKREQ IPFY_ICMPT_MASKREP IPFY_ICMPT_ROUTERAD
+%token IPFY_ICMPT_ROUTERSOL
+
+%token IPFY_ICMPC_NETUNR IPFY_ICMPC_HSTUNR IPFY_ICMPC_PROUNR IPFY_ICMPC_PORUNR
+%token IPFY_ICMPC_NEEDF IPFY_ICMPC_SRCFAIL IPFY_ICMPC_NETUNK IPFY_ICMPC_HSTUNK
+%token IPFY_ICMPC_ISOLATE IPFY_ICMPC_NETPRO IPFY_ICMPC_HSTPRO
+%token IPFY_ICMPC_NETTOS IPFY_ICMPC_HSTTOS IPFY_ICMPC_FLTPRO IPFY_ICMPC_HSTPRE
+%token IPFY_ICMPC_CUTPRE
+
+%token IPFY_FAC_KERN IPFY_FAC_USER IPFY_FAC_MAIL IPFY_FAC_DAEMON IPFY_FAC_AUTH
+%token IPFY_FAC_SYSLOG IPFY_FAC_LPR IPFY_FAC_NEWS IPFY_FAC_UUCP IPFY_FAC_CRON
+%token IPFY_FAC_LOCAL0 IPFY_FAC_LOCAL1 IPFY_FAC_LOCAL2 IPFY_FAC_LOCAL3
+%token IPFY_FAC_LOCAL4 IPFY_FAC_LOCAL5 IPFY_FAC_LOCAL6 IPFY_FAC_LOCAL7
+%token IPFY_FAC_SECURITY IPFY_FAC_FTP IPFY_FAC_AUTHPRIV IPFY_FAC_AUDIT
+%token IPFY_FAC_LFMT IPFY_FAC_CONSOLE
+
+%token IPFY_PRI_EMERG IPFY_PRI_ALERT IPFY_PRI_CRIT IPFY_PRI_ERR IPFY_PRI_WARN
+%token IPFY_PRI_NOTICE IPFY_PRI_INFO IPFY_PRI_DEBUG
+%%
+file: line
+ | assign
+ | file line
+ | file assign
+ ;
+
+line: xx rule { while ((fr = frtop) != NULL) {
+ frtop = fr->fr_next;
+ fr->fr_next = NULL;
+ (*ipfaddfunc)(ipffd, ipfioctl[IPL_LOGIPF], fr);
+ fr->fr_next = frold;
+ frold = fr;
+ }
+ resetlexer();
+ }
+ | YY_COMMENT
+ ;
+
+xx: { newrule(); }
+ ;
+
+assign: YY_STR assigning YY_STR ';' { set_variable($1, $3);
+ resetlexer();
+ free($1);
+ free($3);
+ }
+ ;
+
+assigning:
+ '=' { yyvarnext = 1; }
+ ;
+
+rule: inrule eol
+ | outrule eol
+ ;
+
+eol: | ';'
+ ;
+
+inrule:
+ rulehead markin inopts rulemain ruletail intag ruletail2
+ ;
+
+outrule:
+ rulehead markout outopts rulemain ruletail outtag ruletail2
+ ;
+
+rulehead:
+ collection action
+ | insert collection action
+ ;
+
+markin: IPFY_IN { fr->fr_flags |= FR_INQUE; }
+ ;
+
+markout:
+ IPFY_OUT { fr->fr_flags |= FR_OUTQUE; }
+ ;
+
+rulemain:
+ ipfrule
+ | bpfrule
+ ;
+
+ipfrule:
+ tos ttl proto ip
+ ;
+
+bpfrule:
+ IPFY_BPFV4 '{' YY_STR '}' { dobpf(4, $3); free($3); }
+ | IPFY_BPFV6 '{' YY_STR '}' { dobpf(6, $3); free($3); }
+ ;
+
+ruletail:
+ with keep head group
+ ;
+
+ruletail2:
+ pps age new
+ ;
+
+intag: settagin matchtagin
+ ;
+
+outtag: settagout matchtagout
+ ;
+
+insert:
+ '@' YY_NUMBER { fr->fr_hits = (U_QUAD_T)$2 + 1; }
+ ;
+
+collection:
+ | YY_NUMBER { fr->fr_collect = $1; }
+ ;
+
+action: block
+ | IPFY_PASS { fr->fr_flags |= FR_PASS; }
+ | log
+ | IPFY_COUNT { fr->fr_flags |= FR_ACCOUNT; }
+ | auth
+ | IPFY_SKIP YY_NUMBER { fr->fr_flags |= FR_SKIP;
+ fr->fr_arg = $2; }
+ | IPFY_CALL func
+ | IPFY_CALL IPFY_NOW func { fr->fr_flags |= FR_CALLNOW; }
+ ;
+
+block: blocked
+ | blocked blockreturn
+ ;
+
+blocked:
+ IPFY_BLOCK { fr->fr_flags = FR_BLOCK; }
+ ;
+blockreturn:
+ IPFY_RETICMP { fr->fr_flags |= FR_RETICMP; }
+ | IPFY_RETICMP returncode { fr->fr_flags |= FR_RETICMP; }
+ | IPFY_RETICMPASDST { fr->fr_flags |= FR_FAKEICMP; }
+ | IPFY_RETICMPASDST returncode { fr->fr_flags |= FR_FAKEICMP; }
+ | IPFY_RETRST { fr->fr_flags |= FR_RETRST; }
+ ;
+
+log: IPFY_LOG { fr->fr_flags |= FR_LOG; }
+ | IPFY_LOG logoptions { fr->fr_flags |= FR_LOG; }
+ ;
+
+auth: IPFY_AUTH { fr->fr_flags |= FR_AUTH; }
+ | IPFY_AUTH IPFY_RETRST { fr->fr_flags |= (FR_AUTH|FR_RETRST);}
+ | IPFY_PREAUTH { fr->fr_flags |= FR_PREAUTH; }
+ ;
+
+func: YY_STR '/' YY_NUMBER { fr->fr_func = nametokva($1,
+ ipfioctl[IPL_LOGIPF]);
+ fr->fr_arg = $3;
+ free($1); }
+ ;
+
+inopts:
+ | inopts inopt
+ ;
+
+inopt:
+ logopt
+ | quick
+ | on
+ | dup
+ | froute
+ | proute
+ | replyto
+ ;
+
+outopts:
+ | outopts outopt
+ ;
+
+outopt:
+ logopt
+ | quick
+ | on
+ | dup
+ | proute
+ | replyto
+ ;
+
+tos: | settos YY_NUMBER { DOALL(fr->fr_tos = $2; fr->fr_mtos = 0xff;) }
+ | settos YY_HEX { DOALL(fr->fr_tos = $2; fr->fr_mtos = 0xff;) }
+ | settos lstart toslist lend
+ ;
+
+settos: IPFY_TOS { setipftype(); }
+ ;
+
+toslist:
+ YY_NUMBER { DOALL(fr->fr_tos = $1; fr->fr_mtos = 0xff;) }
+ | YY_HEX { DOREM(fr->fr_tos = $1; fr->fr_mtos = 0xff;) }
+ | toslist lmore YY_NUMBER
+ { DOREM(fr->fr_tos = $3; fr->fr_mtos = 0xff;) }
+ | toslist lmore YY_HEX
+ { DOREM(fr->fr_tos = $3; fr->fr_mtos = 0xff;) }
+ ;
+
+ttl: | setttl YY_NUMBER
+ { DOALL(fr->fr_ttl = $2; fr->fr_mttl = 0xff;) }
+ | setttl lstart ttllist lend
+ ;
+
+lstart: '(' { newlist = 1; fr = frc; added = 0; }
+ ;
+
+lend: ')' { nrules += added; }
+ ;
+
+lmore: lanother { if (newlist == 1) {
+ newlist = 0;
+ }
+ fr = addrule();
+ if (yycont != NULL)
+ *yycont = 1;
+ }
+ ;
+
+lanother:
+ | ','
+ ;
+
+setttl: IPFY_TTL { setipftype(); }
+ ;
+
+ttllist:
+ YY_NUMBER { DOREM(fr->fr_ttl = $1; fr->fr_mttl = 0xff;) }
+ | ttllist lmore YY_NUMBER
+ { DOREM(fr->fr_ttl = $3; fr->fr_mttl = 0xff;) }
+ ;
+
+proto: | protox protocol { yyresetdict(); }
+ ;
+
+protox: IPFY_PROTO { setipftype();
+ fr = frc;
+ yysetdict(NULL); }
+ ;
+
+ip: srcdst flags icmp
+ ;
+
+group: | IPFY_GROUP YY_STR { DOALL(strncpy(fr->fr_group, $2, \
+ FR_GROUPLEN); \
+ fillgroup(fr););
+ free($2); }
+ | IPFY_GROUP YY_NUMBER { DOALL(sprintf(fr->fr_group, "%d", \
+ $2); \
+ fillgroup(fr);) }
+ ;
+
+head: | IPFY_HEAD YY_STR { DOALL(strncpy(fr->fr_grhead, $2, \
+ FR_GROUPLEN););
+ free($2); }
+ | IPFY_HEAD YY_NUMBER { DOALL(sprintf(fr->fr_grhead, "%d", \
+ $2);) }
+ ;
+
+settagin:
+ | IPFY_SETTAG '(' taginlist ')'
+ ;
+
+taginlist:
+ taginspec
+ | taginlist ',' taginspec
+ ;
+
+taginspec:
+ logtag
+ ;
+
+nattag: IPFY_NAT '=' YY_STR { DOALL(strncpy(fr->fr_nattag.ipt_tag,\
+ $3, IPFTAG_LEN););
+ free($3); }
+ | IPFY_NAT '=' YY_NUMBER { DOALL(sprintf(fr->fr_nattag.ipt_tag,\
+ "%d", $3 & 0xffffffff);) }
+ ;
+
+logtag: IPFY_LOG '=' YY_NUMBER { DOALL(fr->fr_logtag = $3;) }
+ ;
+
+settagout:
+ | IPFY_SETTAG '(' tagoutlist ')'
+ ;
+
+tagoutlist:
+ tagoutspec
+ | tagoutlist ',' tagoutspec
+ ;
+
+tagoutspec:
+ logtag
+ | nattag
+ ;
+
+matchtagin:
+ | IPFY_MATCHTAG '(' tagoutlist ')'
+ ;
+
+matchtagout:
+ | IPFY_MATCHTAG '(' taginlist ')'
+ ;
+
+pps: | IPFY_PPS YY_NUMBER { DOALL(fr->fr_pps = $2;) }
+ ;
+
+new: | savegroup file restoregroup
+ ;
+
+savegroup:
+ '{'
+ ;
+
+restoregroup:
+ '}'
+ ;
+
+logopt: log
+ ;
+
+quick:
+ IPFY_QUICK { fr->fr_flags |= FR_QUICK; }
+ ;
+
+on: IPFY_ON onname
+ | IPFY_ON onname IPFY_INVIA vianame
+ | IPFY_ON onname IPFY_OUTVIA vianame
+ ;
+
+onname: interfacename
+ { strncpy(fr->fr_ifnames[0], $1, sizeof(fr->fr_ifnames[0]));
+ free($1);
+ }
+ | interfacename ',' interfacename
+ { strncpy(fr->fr_ifnames[0], $1, sizeof(fr->fr_ifnames[0]));
+ free($1);
+ strncpy(fr->fr_ifnames[1], $3, sizeof(fr->fr_ifnames[1]));
+ free($3);
+ }
+ ;
+
+vianame:
+ name
+ { strncpy(fr->fr_ifnames[2], $1, sizeof(fr->fr_ifnames[2]));
+ free($1);
+ }
+ | name ',' name
+ { strncpy(fr->fr_ifnames[2], $1, sizeof(fr->fr_ifnames[2]));
+ free($1);
+ strncpy(fr->fr_ifnames[3], $3, sizeof(fr->fr_ifnames[3]));
+ free($3);
+ }
+ ;
+
+dup: IPFY_DUPTO name
+ { strncpy(fr->fr_dif.fd_ifname, $2, sizeof(fr->fr_dif.fd_ifname));
+ free($2);
+ }
+ | IPFY_DUPTO name duptoseparator hostname
+ { strncpy(fr->fr_dif.fd_ifname, $2, sizeof(fr->fr_dif.fd_ifname));
+ fr->fr_dif.fd_ip = $4;
+ yyexpectaddr = 0;
+ free($2);
+ }
+ | IPFY_DUPTO name duptoseparator YY_IPV6
+ { strncpy(fr->fr_dif.fd_ifname, $2, sizeof(fr->fr_dif.fd_ifname));
+ bcopy(&$4, &fr->fr_dif.fd_ip6, sizeof(fr->fr_dif.fd_ip6));
+ yyexpectaddr = 0;
+ free($2);
+ }
+ ;
+
+duptoseparator:
+ ':' { yyexpectaddr = 1; yycont = &yyexpectaddr; resetaddr(); }
+ ;
+
+froute: IPFY_FROUTE { fr->fr_flags |= FR_FASTROUTE; }
+ ;
+
+proute: routeto name
+ { strncpy(fr->fr_tif.fd_ifname, $2, sizeof(fr->fr_tif.fd_ifname));
+ free($2);
+ }
+ | routeto name duptoseparator hostname
+ { strncpy(fr->fr_tif.fd_ifname, $2, sizeof(fr->fr_tif.fd_ifname));
+ fr->fr_tif.fd_ip = $4;
+ yyexpectaddr = 0;
+ free($2);
+ }
+ | routeto name duptoseparator YY_IPV6
+ { strncpy(fr->fr_tif.fd_ifname, $2, sizeof(fr->fr_tif.fd_ifname));
+ bcopy(&$4, &fr->fr_tif.fd_ip6, sizeof(fr->fr_tif.fd_ip6));
+ yyexpectaddr = 0;
+ free($2);
+ }
+ ;
+
+routeto:
+ IPFY_TO
+ | IPFY_ROUTETO
+ ;
+
+replyto:
+ IPFY_REPLY_TO name
+ { strncpy(fr->fr_rif.fd_ifname, $2, sizeof(fr->fr_rif.fd_ifname));
+ free($2);
+ }
+ | IPFY_REPLY_TO name duptoseparator hostname
+ { strncpy(fr->fr_rif.fd_ifname, $2, sizeof(fr->fr_rif.fd_ifname));
+ fr->fr_rif.fd_ip = $4;
+ free($2);
+ }
+ ;
+
+logoptions:
+ logoption
+ | logoptions logoption
+ ;
+
+logoption:
+ IPFY_BODY { fr->fr_flags |= FR_LOGBODY; }
+ | IPFY_FIRST { fr->fr_flags |= FR_LOGFIRST; }
+ | IPFY_ORBLOCK { fr->fr_flags |= FR_LOGORBLOCK; }
+ | level loglevel { unsetsyslog(); }
+ ;
+
+returncode:
+ starticmpcode icmpcode ')' { fr->fr_icode = $2; yyresetdict(); }
+ ;
+
+starticmpcode:
+ '(' { yysetdict(icmpcodewords); }
+ ;
+
+srcdst: | IPFY_ALL
+ | fromto
+ ;
+
+protocol:
+ YY_NUMBER { DOREM(fr->fr_proto = $1; \
+ fr->fr_mproto = 0xff;) }
+ | YY_STR { if (!strcmp($1, "tcp-udp")) {
+ DOREM(fr->fr_flx |= FI_TCPUDP; \
+ fr->fr_mflx |= FI_TCPUDP;)
+ } else {
+ int p = getproto($1);
+ if (p == -1)
+ yyerror("protocol unknown");
+ DOREM(fr->fr_proto = p; \
+ fr->fr_mproto = 0xff;)
+ }
+ free($1);
+ }
+ | YY_STR nextstring YY_STR
+ { if (!strcmp($1, "tcp") &&
+ !strcmp($3, "udp")) {
+ DOREM(fr->fr_flx |= FI_TCPUDP; \
+ fr->fr_mflx |= FI_TCPUDP;)
+ } else
+ YYERROR;
+ free($1);
+ free($3);
+ }
+ ;
+
+nextstring:
+ '/' { yysetdict(NULL); }
+ ;
+
+fromto: from srcobject to dstobject { yyexpectaddr = 0; yycont = NULL; }
+ | to dstobject { yyexpectaddr = 0; yycont = NULL; }
+ | from srcobject { yyexpectaddr = 0; yycont = NULL; }
+ ;
+
+from: IPFY_FROM { setipftype();
+ if (fr == NULL)
+ fr = frc;
+ yyexpectaddr = 1;
+ if (yydebug)
+ printf("set yyexpectaddr\n");
+ yycont = &yyexpectaddr;
+ yysetdict(addrwords);
+ resetaddr(); }
+ ;
+
+to: IPFY_TO { if (fr == NULL)
+ fr = frc;
+ yyexpectaddr = 1;
+ if (yydebug)
+ printf("set yyexpectaddr\n");
+ yycont = &yyexpectaddr;
+ yysetdict(addrwords);
+ resetaddr(); }
+ ;
+
+with: | andwith withlist
+ ;
+
+andwith:
+ IPFY_WITH { nowith = 0; setipftype(); }
+ | IPFY_AND { nowith = 0; setipftype(); }
+ ;
+
+flags: | startflags flagset
+ { DOALL(fr->fr_tcpf = $2; fr->fr_tcpfm = FR_TCPFMAX;) }
+ | startflags flagset '/' flagset
+ { DOALL(fr->fr_tcpf = $2; fr->fr_tcpfm = $4;) }
+ | startflags '/' flagset
+ { DOALL(fr->fr_tcpf = 0; fr->fr_tcpfm = $3;) }
+ | startflags YY_NUMBER
+ { DOALL(fr->fr_tcpf = $2; fr->fr_tcpfm = FR_TCPFMAX;) }
+ | startflags '/' YY_NUMBER
+ { DOALL(fr->fr_tcpf = 0; fr->fr_tcpfm = $3;) }
+ | startflags YY_NUMBER '/' YY_NUMBER
+ { DOALL(fr->fr_tcpf = $2; fr->fr_tcpfm = $4;) }
+ | startflags flagset '/' YY_NUMBER
+ { DOALL(fr->fr_tcpf = $2; fr->fr_tcpfm = $4;) }
+ | startflags YY_NUMBER '/' flagset
+ { DOALL(fr->fr_tcpf = $2; fr->fr_tcpfm = $4;) }
+ ;
+
+startflags:
+ IPFY_FLAGS { if (frc->fr_type != FR_T_IPF)
+ yyerror("flags with non-ipf type rule");
+ if (frc->fr_proto != IPPROTO_TCP)
+ yyerror("flags with non-TCP rule");
+ }
+ ;
+
+flagset:
+ YY_STR { $$ = tcpflags($1); free($1); }
+ | YY_HEX { $$ = $1; }
+ ;
+
+srcobject:
+ { yyresetdict(); } fromport
+ | srcaddr srcport
+ | '!' srcaddr srcport
+ { DOALL(fr->fr_flags |= FR_NOTSRCIP;) }
+ ;
+
+srcaddr:
+ addr { DOREM(bcopy(&($1.a), &fr->fr_ip.fi_src, sizeof($1.a)); \
+ bcopy(&($1.m), &fr->fr_mip.fi_src, sizeof($1.m)); \
+ if (dynamic != -1) { \
+ fr->fr_satype = ifpflag; \
+ fr->fr_ipf->fri_sifpidx = dynamic; \
+ } else if (pooled || hashed) \
+ fr->fr_satype = FRI_LOOKUP;)
+ }
+ | lstart srcaddrlist lend
+ ;
+
+srcaddrlist:
+ addr { DOREM(bcopy(&($1.a), &fr->fr_ip.fi_src, sizeof($1.a)); \
+ bcopy(&($1.m), &fr->fr_mip.fi_src, sizeof($1.m)); \
+ if (dynamic != -1) { \
+ fr->fr_satype = ifpflag; \
+ fr->fr_ipf->fri_sifpidx = dynamic; \
+ } else if (pooled || hashed) \
+ fr->fr_satype = FRI_LOOKUP;)
+ }
+ | srcaddrlist lmore addr
+ { DOREM(bcopy(&($3.a), &fr->fr_ip.fi_src, sizeof($3.a)); \
+ bcopy(&($3.m), &fr->fr_mip.fi_src, sizeof($3.m)); \
+ if (dynamic != -1) { \
+ fr->fr_satype = ifpflag; \
+ fr->fr_ipf->fri_sifpidx = dynamic; \
+ } else if (pooled || hashed) \
+ fr->fr_satype = FRI_LOOKUP;)
+ }
+ ;
+
+srcport:
+ | portcomp
+ { DOALL(fr->fr_scmp = $1.pc; fr->fr_sport = $1.p1;) }
+ | portrange
+ { DOALL(fr->fr_scmp = $1.pc; fr->fr_sport = $1.p1; \
+ fr->fr_stop = $1.p2;) }
+ | porteq lstart srcportlist lend
+ { yyresetdict(); }
+ ;
+
+fromport:
+ portcomp
+ { DOALL(fr->fr_scmp = $1.pc; fr->fr_sport = $1.p1;) }
+ | portrange
+ { DOALL(fr->fr_scmp = $1.pc; fr->fr_sport = $1.p1; \
+ fr->fr_stop = $1.p2;) }
+ | porteq lstart srcportlist lend
+ { yyresetdict(); }
+ ;
+
+srcportlist:
+ portnum { DOREM(fr->fr_scmp = FR_EQUAL; fr->fr_sport = $1;) }
+ | srcportlist lmore portnum
+ { DOREM(fr->fr_scmp = FR_EQUAL; fr->fr_sport = $3;) }
+ ;
+
+dstobject:
+ { yyresetdict(); } toport
+ | dstaddr dstport
+ | '!' dstaddr dstport
+ { DOALL(fr->fr_flags |= FR_NOTDSTIP;) }
+ ;
+
+dstaddr:
+ addr { DOREM(bcopy(&($1.a), &fr->fr_ip.fi_dst, sizeof($1.a)); \
+ bcopy(&($1.m), &fr->fr_mip.fi_dst, sizeof($1.m)); \
+ if (dynamic != -1) { \
+ fr->fr_datype = ifpflag; \
+ fr->fr_ipf->fri_difpidx = dynamic; \
+ } else if (pooled || hashed) \
+ fr->fr_datype = FRI_LOOKUP;)
+ }
+ | lstart dstaddrlist lend
+ ;
+
+dstaddrlist:
+ addr { DOREM(bcopy(&($1.a), &fr->fr_ip.fi_dst, sizeof($1.a)); \
+ bcopy(&($1.m), &fr->fr_mip.fi_dst, sizeof($1.m)); \
+ if (dynamic != -1) { \
+ fr->fr_datype = ifpflag; \
+ fr->fr_ipf->fri_difpidx = dynamic; \
+ } else if (pooled || hashed) \
+ fr->fr_datype = FRI_LOOKUP;)
+ }
+ | dstaddrlist lmore addr
+ { DOREM(bcopy(&($3.a), &fr->fr_ip.fi_dst, sizeof($3.a)); \
+ bcopy(&($3.m), &fr->fr_mip.fi_dst, sizeof($3.m)); \
+ if (dynamic != -1) { \
+ fr->fr_datype = ifpflag; \
+ fr->fr_ipf->fri_difpidx = dynamic; \
+ } else if (pooled || hashed) \
+ fr->fr_datype = FRI_LOOKUP;)
+ }
+ ;
+
+
+dstport:
+ | portcomp
+ { DOALL(fr->fr_dcmp = $1.pc; fr->fr_dport = $1.p1;) }
+ | portrange
+ { DOALL(fr->fr_dcmp = $1.pc; fr->fr_dport = $1.p1; \
+ fr->fr_dtop = $1.p2;) }
+ | porteq lstart dstportlist lend
+ { yyresetdict(); }
+ ;
+
+toport:
+ portcomp
+ { DOALL(fr->fr_dcmp = $1.pc; fr->fr_dport = $1.p1;) }
+ | portrange
+ { DOALL(fr->fr_dcmp = $1.pc; fr->fr_dport = $1.p1; \
+ fr->fr_dtop = $1.p2;) }
+ | porteq lstart dstportlist lend
+ { yyresetdict(); }
+ ;
+
+dstportlist:
+ portnum { DOREM(fr->fr_dcmp = FR_EQUAL; fr->fr_dport = $1;) }
+ | dstportlist lmore portnum
+ { DOREM(fr->fr_dcmp = FR_EQUAL; fr->fr_dport = $3;) }
+ ;
+
+addr: pool '/' YY_NUMBER { pooled = 1;
+ yyexpectaddr = 0;
+ $$.a.iplookuptype = IPLT_POOL;
+ $$.a.iplookupnum = $3; }
+ | pool '=' '(' poollist ')' { pooled = 1;
+ yyexpectaddr = 0;
+ $$.a.iplookuptype = IPLT_POOL;
+ $$.a.iplookupnum = makepool($4); }
+ | hash '/' YY_NUMBER { hashed = 1;
+ yyexpectaddr = 0;
+ $$.a.iplookuptype = IPLT_HASH;
+ $$.a.iplookupnum = $3; }
+ | hash '=' '(' addrlist ')' { hashed = 1;
+ yyexpectaddr = 0;
+ $$.a.iplookuptype = IPLT_HASH;
+ $$.a.iplookupnum = makehash($4); }
+ | ipaddr { bcopy(&$1, &$$, sizeof($$));
+ yyexpectaddr = 0; }
+ ;
+
+ipaddr: IPFY_ANY { bzero(&($$), sizeof($$));
+ yyresetdict();
+ yyexpectaddr = 0; }
+ | hostname { $$.a.in4 = $1;
+ $$.m.in4_addr = 0xffffffff;
+ yyexpectaddr = 0; }
+ | hostname { yyresetdict();
+ $$.a.in4_addr = $1.s_addr; }
+ maskspace { yysetdict(maskwords); }
+ ipv4mask { $$.m.in4_addr = $5.s_addr;
+ $$.a.in4_addr &= $5.s_addr;
+ yyresetdict();
+ yyexpectaddr = 0; }
+ | YY_IPV6 { bcopy(&$1, &$$.a, sizeof($$.a));
+ fill6bits(128, (u_32_t *)&$$.m);
+ yyresetdict();
+ yyexpectaddr = 0; }
+ | YY_IPV6 { yyresetdict();
+ bcopy(&$1, &$$.a, sizeof($$.a)); }
+ maskspace { yysetdict(maskwords); }
+ ipv6mask { bcopy(&$5, &$$.m, sizeof($$.m));
+ yyresetdict();
+ yyexpectaddr = 0; }
+ ;
+maskspace:
+ '/'
+ | IPFY_MASK
+ ;
+
+ipv4mask:
+ ipv4 { $$ = $1; }
+ | YY_HEX { $$.s_addr = htonl($1); }
+ | YY_NUMBER { ntomask(4, $1, (u_32_t *)&$$); }
+ | IPFY_BROADCAST { if (ifpflag == FRI_DYNAMIC) {
+ $$.s_addr = 0;
+ ifpflag = FRI_BROADCAST;
+ } else
+ YYERROR;
+ }
+ | IPFY_NETWORK { if (ifpflag == FRI_DYNAMIC) {
+ $$.s_addr = 0;
+ ifpflag = FRI_NETWORK;
+ } else
+ YYERROR;
+ }
+ | IPFY_NETMASKED { if (ifpflag == FRI_DYNAMIC) {
+ $$.s_addr = 0;
+ ifpflag = FRI_NETMASKED;
+ } else
+ YYERROR;
+ }
+ | IPFY_PEER { if (ifpflag == FRI_DYNAMIC) {
+ $$.s_addr = 0;
+ ifpflag = FRI_PEERADDR;
+ } else
+ YYERROR;
+ }
+ ;
+
+ipv6mask:
+ YY_NUMBER { ntomask(6, $1, $$.i6); }
+ | IPFY_BROADCAST { if (ifpflag == FRI_DYNAMIC) {
+ bzero(&$$, sizeof($$));
+ ifpflag = FRI_BROADCAST;
+ } else
+ YYERROR;
+ }
+ | IPFY_NETWORK { if (ifpflag == FRI_DYNAMIC) {
+ bzero(&$$, sizeof($$));
+ ifpflag = FRI_BROADCAST;
+ } else
+ YYERROR;
+ }
+ | IPFY_NETMASKED { if (ifpflag == FRI_DYNAMIC) {
+ bzero(&$$, sizeof($$));
+ ifpflag = FRI_BROADCAST;
+ } else
+ YYERROR;
+ }
+ | IPFY_PEER { if (ifpflag == FRI_DYNAMIC) {
+ bzero(&$$, sizeof($$));
+ ifpflag = FRI_BROADCAST;
+ } else
+ YYERROR;
+ }
+ ;
+
+hostname:
+ ipv4 { $$ = $1; }
+ | YY_NUMBER { $$.s_addr = $1; }
+ | YY_HEX { $$.s_addr = $1; }
+ | YY_STR { $$.s_addr = lookuphost($1);
+ free($1);
+ }
+ ;
+
+addrlist:
+ ipaddr { $$ = newalist(NULL);
+ bcopy(&($1.a), &($$->al_i6addr), sizeof($1.a));
+ bcopy(&($1.m), &($$->al_i6mask), sizeof($1.m)); }
+ | addrlist ',' ipaddr
+ { $$ = newalist($1);
+ bcopy(&($3.a), &($$->al_i6addr), sizeof($3.a));
+ bcopy(&($3.m), &($$->al_i6mask), sizeof($3.m)); }
+ ;
+
+pool: IPFY_POOL { yyexpectaddr = 0; yycont = NULL; yyresetdict(); }
+ ;
+
+hash: IPFY_HASH { yyexpectaddr = 0; yycont = NULL; yyresetdict(); }
+ ;
+
+poollist:
+ ipaddr { $$ = newalist(NULL);
+ bcopy(&($1.a), &($$->al_i6addr), sizeof($1.a));
+ bcopy(&($1.m), &($$->al_i6mask), sizeof($1.m)); }
+ | '!' ipaddr { $$ = newalist(NULL);
+ $$->al_not = 1;
+ bcopy(&($2.a), &($$->al_i6addr), sizeof($2.a));
+ bcopy(&($2.m), &($$->al_i6mask), sizeof($2.m)); }
+ | poollist ',' ipaddr
+ { $$ = newalist($1);
+ bcopy(&($3.a), &($$->al_i6addr), sizeof($3.a));
+ bcopy(&($3.m), &($$->al_i6mask), sizeof($3.m)); }
+ | poollist ',' '!' ipaddr
+ { $$ = newalist($1);
+ $$->al_not = 1;
+ bcopy(&($4.a), &($$->al_i6addr), sizeof($4.a));
+ bcopy(&($4.m), &($$->al_i6mask), sizeof($4.m)); }
+ ;
+
+port: IPFY_PORT { yyexpectaddr = 0;
+ yycont = NULL;
+ }
+ ;
+
+portc: port compare { $$ = $2;
+ yysetdict(NULL); }
+ | porteq { $$ = $1; }
+ ;
+
+porteq: port '=' { $$ = FR_EQUAL;
+ yysetdict(NULL); }
+ ;
+
+portr: IPFY_PORT { yyexpectaddr = 0;
+ yycont = NULL;
+ yysetdict(NULL); }
+ ;
+
+portcomp:
+ portc portnum { $$.pc = $1;
+ $$.p1 = $2;
+ yyresetdict(); }
+ ;
+
+portrange:
+ portr portnum range portnum { $$.p1 = $2;
+ $$.pc = $3;
+ $$.p2 = $4;
+ yyresetdict(); }
+ ;
+
+icmp: | itype icode
+ ;
+
+itype: seticmptype icmptype
+ { DOALL(fr->fr_icmp = htons($2 << 8); fr->fr_icmpm = htons(0xff00););
+ yyresetdict();
+ }
+ | seticmptype lstart typelist lend { yyresetdict(); }
+ ;
+
+seticmptype:
+ IPFY_ICMPTYPE { setipftype();
+ yysetdict(icmptypewords); }
+ ;
+
+icode: | seticmpcode icmpcode
+ { DOALL(fr->fr_icmp |= htons($2); fr->fr_icmpm |= htons(0xff););
+ yyresetdict();
+ }
+ | seticmpcode lstart codelist lend { yyresetdict(); }
+ ;
+
+seticmpcode:
+ IPFY_ICMPCODE { yysetdict(icmpcodewords); }
+ ;
+
+typelist:
+ icmptype
+ { DOREM(fr->fr_icmp = htons($1 << 8); fr->fr_icmpm = htons(0xff00);) }
+ | typelist lmore icmptype
+ { DOREM(fr->fr_icmp = htons($3 << 8); fr->fr_icmpm = htons(0xff00);) }
+ ;
+
+codelist:
+ icmpcode
+ { DOREM(fr->fr_icmp |= htons($1); fr->fr_icmpm |= htons(0xff);) }
+ | codelist lmore icmpcode
+ { DOREM(fr->fr_icmp |= htons($3); fr->fr_icmpm |= htons(0xff);) }
+ ;
+
+age: | IPFY_AGE YY_NUMBER { DOALL(fr->fr_age[0] = $2; \
+ fr->fr_age[1] = $2;) }
+ | IPFY_AGE YY_NUMBER '/' YY_NUMBER
+ { DOALL(fr->fr_age[0] = $2; \
+ fr->fr_age[1] = $4;) }
+ ;
+
+keep: | IPFY_KEEP keepstate keep
+ | IPFY_KEEP keepfrag keep
+ ;
+
+keepstate:
+ IPFY_STATE stateoptlist { DOALL(fr->fr_flags |= FR_KEEPSTATE;)}
+ ;
+
+keepfrag:
+ IPFY_FRAGS fragoptlist { DOALL(fr->fr_flags |= FR_KEEPFRAG;) }
+ | IPFY_FRAG fragoptlist { DOALL(fr->fr_flags |= FR_KEEPFRAG;) }
+ ;
+
+fragoptlist:
+ | '(' fragopts ')'
+ ;
+
+fragopts:
+ fragopt lanother fragopts
+ | fragopt
+ ;
+
+fragopt:
+ IPFY_STRICT { DOALL(fr->fr_flags |= FR_FRSTRICT;) }
+ ;
+
+stateoptlist:
+ | '(' stateopts ')'
+ ;
+
+stateopts:
+ stateopt lanother stateopts
+ | stateopt
+ ;
+
+stateopt:
+ IPFY_LIMIT YY_NUMBER { DOALL(fr->fr_statemax = $2;) }
+ | IPFY_STRICT { DOALL(if (fr->fr_proto != IPPROTO_TCP) { \
+ YYERROR; \
+ } else \
+ fr->fr_flags |= FR_STSTRICT;)
+ }
+ | IPFY_NEWISN { DOALL(if (fr->fr_proto != IPPROTO_TCP) { \
+ YYERROR; \
+ } else \
+ fr->fr_flags |= FR_NEWISN;)
+ }
+ | IPFY_NOICMPERR { DOALL(fr->fr_flags |= FR_NOICMPERR;) }
+
+ | IPFY_SYNC { DOALL(fr->fr_flags |= FR_STATESYNC;) }
+ ;
+
+portnum:
+ servicename { if (getport(frc, $1, &($$)) == -1)
+ yyerror("service unknown");
+ $$ = ntohs($$);
+ free($1);
+ }
+ | YY_NUMBER { if ($1 > 65535) /* Unsigned */
+ yyerror("invalid port number");
+ else
+ $$ = $1;
+ }
+ ;
+
+withlist:
+ withopt
+ | withlist withopt
+ | withlist ',' withopt
+ ;
+
+withopt:
+ opttype { DOALL(fr->fr_flx |= $1; fr->fr_mflx |= $1;) }
+ | notwith opttype
+ { DOALL(fr->fr_mflx |= $2;) }
+ | ipopt ipopts { yyresetdict(); }
+ | notwith ipopt ipopts { yyresetdict(); }
+ | startv6hdrs ipv6hdrs { yyresetdict(); }
+ ;
+
+ipopt: IPFY_OPT { yysetdict(ipv4optwords); }
+ ;
+
+startv6hdrs:
+ IPF6_V6HDRS { if (use_inet6 == 0)
+ yyerror("only available with IPv6");
+ yysetdict(ipv6optwords);
+ }
+ ;
+
+notwith:
+ IPFY_NOT { nowith = 1; }
+ | IPFY_NO { nowith = 1; }
+ ;
+
+opttype:
+ IPFY_IPOPTS { $$ = FI_OPTIONS; }
+ | IPFY_SHORT { $$ = FI_SHORT; }
+ | IPFY_NAT { $$ = FI_NATED; }
+ | IPFY_BAD { $$ = FI_BAD; }
+ | IPFY_BADNAT { $$ = FI_BADNAT; }
+ | IPFY_BADSRC { $$ = FI_BADSRC; }
+ | IPFY_LOWTTL { $$ = FI_LOWTTL; }
+ | IPFY_FRAG { $$ = FI_FRAG; }
+ | IPFY_FRAGBODY { $$ = FI_FRAGBODY; }
+ | IPFY_FRAGS { $$ = FI_FRAG; }
+ | IPFY_MBCAST { $$ = FI_MBCAST; }
+ | IPFY_MULTICAST { $$ = FI_MULTICAST; }
+ | IPFY_BROADCAST { $$ = FI_BROADCAST; }
+ | IPFY_STATE { $$ = FI_STATE; }
+ | IPFY_OOW { $$ = FI_OOW; }
+ ;
+
+ipopts: optlist { DOALL(fr->fr_mip.fi_optmsk |= $1;
+ if (!nowith)
+ fr->fr_ip.fi_optmsk |= $1;)
+ }
+ ;
+
+optlist:
+ opt { $$ |= $1; }
+ | optlist ',' opt { $$ |= $1 | $3; }
+ ;
+
+ipv6hdrs:
+ ipv6hdrlist { DOALL(fr->fr_mip.fi_optmsk |= $1;
+ if (!nowith)
+ fr->fr_ip.fi_optmsk |= $1;)
+ }
+ ;
+
+ipv6hdrlist:
+ ipv6hdr { $$ |= $1; }
+ | ipv6hdrlist ',' ipv6hdr { $$ |= $1 | $3; }
+ ;
+
+secname:
+ seclevel { $$ |= $1; }
+ | secname ',' seclevel { $$ |= $1 | $3; }
+ ;
+
+seclevel:
+ IPFY_SEC_UNC { $$ = secbit(IPSO_CLASS_UNCL); }
+ | IPFY_SEC_CONF { $$ = secbit(IPSO_CLASS_CONF); }
+ | IPFY_SEC_RSV1 { $$ = secbit(IPSO_CLASS_RES1); }
+ | IPFY_SEC_RSV2 { $$ = secbit(IPSO_CLASS_RES2); }
+ | IPFY_SEC_RSV3 { $$ = secbit(IPSO_CLASS_RES3); }
+ | IPFY_SEC_RSV4 { $$ = secbit(IPSO_CLASS_RES4); }
+ | IPFY_SEC_SEC { $$ = secbit(IPSO_CLASS_SECR); }
+ | IPFY_SEC_TS { $$ = secbit(IPSO_CLASS_TOPS); }
+ ;
+
+icmptype:
+ YY_NUMBER { $$ = $1; }
+ | IPFY_ICMPT_UNR { $$ = ICMP_UNREACH; }
+ | IPFY_ICMPT_ECHO { $$ = ICMP_ECHO; }
+ | IPFY_ICMPT_ECHOR { $$ = ICMP_ECHOREPLY; }
+ | IPFY_ICMPT_SQUENCH { $$ = ICMP_SOURCEQUENCH; }
+ | IPFY_ICMPT_REDIR { $$ = ICMP_REDIRECT; }
+ | IPFY_ICMPT_TIMEX { $$ = ICMP_TIMXCEED; }
+ | IPFY_ICMPT_PARAMP { $$ = ICMP_PARAMPROB; }
+ | IPFY_ICMPT_TIMEST { $$ = ICMP_TSTAMP; }
+ | IPFY_ICMPT_TIMESTREP { $$ = ICMP_TSTAMPREPLY; }
+ | IPFY_ICMPT_INFOREQ { $$ = ICMP_IREQ; }
+ | IPFY_ICMPT_INFOREP { $$ = ICMP_IREQREPLY; }
+ | IPFY_ICMPT_MASKREQ { $$ = ICMP_MASKREQ; }
+ | IPFY_ICMPT_MASKREP { $$ = ICMP_MASKREPLY; }
+ | IPFY_ICMPT_ROUTERAD { $$ = ICMP_ROUTERADVERT; }
+ | IPFY_ICMPT_ROUTERSOL { $$ = ICMP_ROUTERSOLICIT; }
+ ;
+
+icmpcode:
+ YY_NUMBER { $$ = $1; }
+ | IPFY_ICMPC_NETUNR { $$ = ICMP_UNREACH_NET; }
+ | IPFY_ICMPC_HSTUNR { $$ = ICMP_UNREACH_HOST; }
+ | IPFY_ICMPC_PROUNR { $$ = ICMP_UNREACH_PROTOCOL; }
+ | IPFY_ICMPC_PORUNR { $$ = ICMP_UNREACH_PORT; }
+ | IPFY_ICMPC_NEEDF { $$ = ICMP_UNREACH_NEEDFRAG; }
+ | IPFY_ICMPC_SRCFAIL { $$ = ICMP_UNREACH_SRCFAIL; }
+ | IPFY_ICMPC_NETUNK { $$ = ICMP_UNREACH_NET_UNKNOWN; }
+ | IPFY_ICMPC_HSTUNK { $$ = ICMP_UNREACH_HOST_UNKNOWN; }
+ | IPFY_ICMPC_ISOLATE { $$ = ICMP_UNREACH_ISOLATED; }
+ | IPFY_ICMPC_NETPRO { $$ = ICMP_UNREACH_NET_PROHIB; }
+ | IPFY_ICMPC_HSTPRO { $$ = ICMP_UNREACH_HOST_PROHIB; }
+ | IPFY_ICMPC_NETTOS { $$ = ICMP_UNREACH_TOSNET; }
+ | IPFY_ICMPC_HSTTOS { $$ = ICMP_UNREACH_TOSHOST; }
+ | IPFY_ICMPC_FLTPRO { $$ = ICMP_UNREACH_ADMIN_PROHIBIT; }
+ | IPFY_ICMPC_HSTPRE { $$ = 14; }
+ | IPFY_ICMPC_CUTPRE { $$ = 15; }
+ ;
+
+opt:
+ IPFY_IPOPT_NOP { $$ = getoptbyvalue(IPOPT_NOP); }
+ | IPFY_IPOPT_RR { $$ = getoptbyvalue(IPOPT_RR); }
+ | IPFY_IPOPT_ZSU { $$ = getoptbyvalue(IPOPT_ZSU); }
+ | IPFY_IPOPT_MTUP { $$ = getoptbyvalue(IPOPT_MTUP); }
+ | IPFY_IPOPT_MTUR { $$ = getoptbyvalue(IPOPT_MTUR); }
+ | IPFY_IPOPT_ENCODE { $$ = getoptbyvalue(IPOPT_ENCODE); }
+ | IPFY_IPOPT_TS { $$ = getoptbyvalue(IPOPT_TS); }
+ | IPFY_IPOPT_TR { $$ = getoptbyvalue(IPOPT_TR); }
+ | IPFY_IPOPT_SEC { $$ = getoptbyvalue(IPOPT_SECURITY); }
+ | IPFY_IPOPT_LSRR { $$ = getoptbyvalue(IPOPT_LSRR); }
+ | IPFY_IPOPT_ESEC { $$ = getoptbyvalue(IPOPT_E_SEC); }
+ | IPFY_IPOPT_CIPSO { $$ = getoptbyvalue(IPOPT_CIPSO); }
+ | IPFY_IPOPT_SATID { $$ = getoptbyvalue(IPOPT_SATID); }
+ | IPFY_IPOPT_SSRR { $$ = getoptbyvalue(IPOPT_SSRR); }
+ | IPFY_IPOPT_ADDEXT { $$ = getoptbyvalue(IPOPT_ADDEXT); }
+ | IPFY_IPOPT_VISA { $$ = getoptbyvalue(IPOPT_VISA); }
+ | IPFY_IPOPT_IMITD { $$ = getoptbyvalue(IPOPT_IMITD); }
+ | IPFY_IPOPT_EIP { $$ = getoptbyvalue(IPOPT_EIP); }
+ | IPFY_IPOPT_FINN { $$ = getoptbyvalue(IPOPT_FINN); }
+ | IPFY_IPOPT_DPS { $$ = getoptbyvalue(IPOPT_DPS); }
+ | IPFY_IPOPT_SDB { $$ = getoptbyvalue(IPOPT_SDB); }
+ | IPFY_IPOPT_NSAPA { $$ = getoptbyvalue(IPOPT_NSAPA); }
+ | IPFY_IPOPT_RTRALRT { $$ = getoptbyvalue(IPOPT_RTRALRT); }
+ | IPFY_IPOPT_UMP { $$ = getoptbyvalue(IPOPT_UMP); }
+ | setsecclass secname
+ { DOALL(fr->fr_mip.fi_secmsk |= $2;
+ if (!nowith)
+ fr->fr_ip.fi_secmsk |= $2;)
+ $$ = 0;
+ yyresetdict();
+ }
+ ;
+
+setsecclass:
+ IPFY_SECCLASS { yysetdict(ipv4secwords); }
+ ;
+
+ipv6hdr:
+ IPFY_AH { $$ = getv6optbyvalue(IPPROTO_AH); }
+ | IPFY_IPV6OPT_DSTOPTS { $$ = getv6optbyvalue(IPPROTO_DSTOPTS); }
+ | IPFY_ESP { $$ = getv6optbyvalue(IPPROTO_ESP); }
+ | IPFY_IPV6OPT_HOPOPTS { $$ = getv6optbyvalue(IPPROTO_HOPOPTS); }
+ | IPFY_IPV6OPT_IPV6 { $$ = getv6optbyvalue(IPPROTO_IPV6); }
+ | IPFY_IPV6OPT_NONE { $$ = getv6optbyvalue(IPPROTO_NONE); }
+ | IPFY_IPV6OPT_ROUTING { $$ = getv6optbyvalue(IPPROTO_ROUTING); }
+ | IPFY_FRAG { $$ = getv6optbyvalue(IPPROTO_FRAGMENT); }
+ ;
+
+level: IPFY_LEVEL { setsyslog(); }
+ ;
+
+loglevel:
+ priority { fr->fr_loglevel = LOG_LOCAL0|$1; }
+ | facility '.' priority { fr->fr_loglevel = $1 | $3; }
+ ;
+
+facility:
+ IPFY_FAC_KERN { $$ = LOG_KERN; }
+ | IPFY_FAC_USER { $$ = LOG_USER; }
+ | IPFY_FAC_MAIL { $$ = LOG_MAIL; }
+ | IPFY_FAC_DAEMON { $$ = LOG_DAEMON; }
+ | IPFY_FAC_AUTH { $$ = LOG_AUTH; }
+ | IPFY_FAC_SYSLOG { $$ = LOG_SYSLOG; }
+ | IPFY_FAC_LPR { $$ = LOG_LPR; }
+ | IPFY_FAC_NEWS { $$ = LOG_NEWS; }
+ | IPFY_FAC_UUCP { $$ = LOG_UUCP; }
+ | IPFY_FAC_CRON { $$ = LOG_CRON; }
+ | IPFY_FAC_FTP { $$ = LOG_FTP; }
+ | IPFY_FAC_AUTHPRIV { $$ = LOG_AUTHPRIV; }
+ | IPFY_FAC_AUDIT { $$ = LOG_AUDIT; }
+ | IPFY_FAC_LFMT { $$ = LOG_LFMT; }
+ | IPFY_FAC_LOCAL0 { $$ = LOG_LOCAL0; }
+ | IPFY_FAC_LOCAL1 { $$ = LOG_LOCAL1; }
+ | IPFY_FAC_LOCAL2 { $$ = LOG_LOCAL2; }
+ | IPFY_FAC_LOCAL3 { $$ = LOG_LOCAL3; }
+ | IPFY_FAC_LOCAL4 { $$ = LOG_LOCAL4; }
+ | IPFY_FAC_LOCAL5 { $$ = LOG_LOCAL5; }
+ | IPFY_FAC_LOCAL6 { $$ = LOG_LOCAL6; }
+ | IPFY_FAC_LOCAL7 { $$ = LOG_LOCAL7; }
+ | IPFY_FAC_SECURITY { $$ = LOG_SECURITY; }
+ ;
+
+priority:
+ IPFY_PRI_EMERG { $$ = LOG_EMERG; }
+ | IPFY_PRI_ALERT { $$ = LOG_ALERT; }
+ | IPFY_PRI_CRIT { $$ = LOG_CRIT; }
+ | IPFY_PRI_ERR { $$ = LOG_ERR; }
+ | IPFY_PRI_WARN { $$ = LOG_WARNING; }
+ | IPFY_PRI_NOTICE { $$ = LOG_NOTICE; }
+ | IPFY_PRI_INFO { $$ = LOG_INFO; }
+ | IPFY_PRI_DEBUG { $$ = LOG_DEBUG; }
+ ;
+
+compare:
+ YY_CMP_EQ { $$ = FR_EQUAL; }
+ | YY_CMP_NE { $$ = FR_NEQUAL; }
+ | YY_CMP_LT { $$ = FR_LESST; }
+ | YY_CMP_LE { $$ = FR_LESSTE; }
+ | YY_CMP_GT { $$ = FR_GREATERT; }
+ | YY_CMP_GE { $$ = FR_GREATERTE; }
+ ;
+
+range: YY_RANGE_IN { $$ = FR_INRANGE; }
+ | YY_RANGE_OUT { $$ = FR_OUTRANGE; }
+ | ':' { $$ = FR_INCRANGE; }
+ ;
+
+servicename:
+ YY_STR { $$ = $1; }
+ ;
+
+interfacename: YY_STR { $$ = $1; }
+ | YY_STR ':' YY_NUMBER
+ { $$ = $1;
+ fprintf(stderr, "%d: Logical interface %s:%d unsupported, "
+ "use the physical interface %s instead.\n",
+ yylineNum, $1, $3, $1);
+ }
+ ;
+
+name: YY_STR { $$ = $1; }
+ ;
+
+ipv4_16:
+ YY_NUMBER '.' YY_NUMBER
+ { if ($1 > 255 || $3 > 255) {
+ yyerror("Invalid octet string for IP address");
+ return 0;
+ }
+ $$.s_addr = ($1 << 24) | ($3 << 16);
+ $$.s_addr = htonl($$.s_addr);
+ }
+ ;
+
+ipv4_24:
+ ipv4_16 '.' YY_NUMBER
+ { if ($3 > 255) {
+ yyerror("Invalid octet string for IP address");
+ return 0;
+ }
+ $$.s_addr |= htonl($3 << 8);
+ }
+ ;
+
+ipv4: ipv4_24 '.' YY_NUMBER
+ { if ($3 > 255) {
+ yyerror("Invalid octet string for IP address");
+ return 0;
+ }
+ $$.s_addr |= htonl($3);
+ }
+ | ipv4_24
+ | ipv4_16
+ ;
+
+%%
+
+
+static struct wordtab ipfwords[95] = {
+ { "age", IPFY_AGE },
+ { "ah", IPFY_AH },
+ { "all", IPFY_ALL },
+ { "and", IPFY_AND },
+ { "auth", IPFY_AUTH },
+ { "bad", IPFY_BAD },
+ { "bad-nat", IPFY_BADNAT },
+ { "bad-src", IPFY_BADSRC },
+ { "bcast", IPFY_BROADCAST },
+ { "block", IPFY_BLOCK },
+ { "body", IPFY_BODY },
+ { "bpf-v4", IPFY_BPFV4 },
+#ifdef USE_INET6
+ { "bpf-v6", IPFY_BPFV6 },
+#endif
+ { "call", IPFY_CALL },
+ { "code", IPFY_ICMPCODE },
+ { "count", IPFY_COUNT },
+ { "dup-to", IPFY_DUPTO },
+ { "eq", YY_CMP_EQ },
+ { "esp", IPFY_ESP },
+ { "fastroute", IPFY_FROUTE },
+ { "first", IPFY_FIRST },
+ { "flags", IPFY_FLAGS },
+ { "frag", IPFY_FRAG },
+ { "frag-body", IPFY_FRAGBODY },
+ { "frags", IPFY_FRAGS },
+ { "from", IPFY_FROM },
+ { "ge", YY_CMP_GE },
+ { "group", IPFY_GROUP },
+ { "gt", YY_CMP_GT },
+ { "head", IPFY_HEAD },
+ { "icmp", IPFY_ICMP },
+ { "icmp-type", IPFY_ICMPTYPE },
+ { "in", IPFY_IN },
+ { "in-via", IPFY_INVIA },
+ { "ipopt", IPFY_IPOPTS },
+ { "ipopts", IPFY_IPOPTS },
+ { "keep", IPFY_KEEP },
+ { "le", YY_CMP_LE },
+ { "level", IPFY_LEVEL },
+ { "limit", IPFY_LIMIT },
+ { "log", IPFY_LOG },
+ { "lowttl", IPFY_LOWTTL },
+ { "lt", YY_CMP_LT },
+ { "mask", IPFY_MASK },
+ { "match-tag", IPFY_MATCHTAG },
+ { "mbcast", IPFY_MBCAST },
+ { "multicast", IPFY_MULTICAST },
+ { "nat", IPFY_NAT },
+ { "ne", YY_CMP_NE },
+ { "net", IPFY_NETWORK },
+ { "newisn", IPFY_NEWISN },
+ { "no", IPFY_NO },
+ { "no-icmp-err", IPFY_NOICMPERR },
+ { "now", IPFY_NOW },
+ { "not", IPFY_NOT },
+ { "oow", IPFY_OOW },
+ { "on", IPFY_ON },
+ { "opt", IPFY_OPT },
+ { "or-block", IPFY_ORBLOCK },
+ { "out", IPFY_OUT },
+ { "out-via", IPFY_OUTVIA },
+ { "pass", IPFY_PASS },
+ { "port", IPFY_PORT },
+ { "pps", IPFY_PPS },
+ { "preauth", IPFY_PREAUTH },
+ { "proto", IPFY_PROTO },
+ { "quick", IPFY_QUICK },
+ { "reply-to", IPFY_REPLY_TO },
+ { "return-icmp", IPFY_RETICMP },
+ { "return-icmp-as-dest", IPFY_RETICMPASDST },
+ { "return-rst", IPFY_RETRST },
+ { "route-to", IPFY_ROUTETO },
+ { "sec-class", IPFY_SECCLASS },
+ { "set-tag", IPFY_SETTAG },
+ { "skip", IPFY_SKIP },
+ { "short", IPFY_SHORT },
+ { "state", IPFY_STATE },
+ { "state-age", IPFY_AGE },
+ { "strict", IPFY_STRICT },
+ { "sync", IPFY_SYNC },
+ { "tcp", IPFY_TCP },
+ { "tcp-udp", IPFY_TCPUDP },
+ { "tos", IPFY_TOS },
+ { "to", IPFY_TO },
+ { "ttl", IPFY_TTL },
+ { "udp", IPFY_UDP },
+ { "v6hdrs", IPF6_V6HDRS },
+ { "with", IPFY_WITH },
+ { NULL, 0 }
+};
+
+static struct wordtab addrwords[4] = {
+ { "any", IPFY_ANY },
+ { "hash", IPFY_HASH },
+ { "pool", IPFY_POOL },
+ { NULL, 0 }
+};
+
+static struct wordtab maskwords[5] = {
+ { "broadcast", IPFY_BROADCAST },
+ { "netmasked", IPFY_NETMASKED },
+ { "network", IPFY_NETWORK },
+ { "peer", IPFY_PEER },
+ { NULL, 0 }
+};
+
+static struct wordtab icmptypewords[16] = {
+ { "echo", IPFY_ICMPT_ECHO },
+ { "echorep", IPFY_ICMPT_ECHOR },
+ { "inforeq", IPFY_ICMPT_INFOREQ },
+ { "inforep", IPFY_ICMPT_INFOREP },
+ { "maskrep", IPFY_ICMPT_MASKREP },
+ { "maskreq", IPFY_ICMPT_MASKREQ },
+ { "paramprob", IPFY_ICMPT_PARAMP },
+ { "redir", IPFY_ICMPT_REDIR },
+ { "unreach", IPFY_ICMPT_UNR },
+ { "routerad", IPFY_ICMPT_ROUTERAD },
+ { "routersol", IPFY_ICMPT_ROUTERSOL },
+ { "squench", IPFY_ICMPT_SQUENCH },
+ { "timest", IPFY_ICMPT_TIMEST },
+ { "timestrep", IPFY_ICMPT_TIMESTREP },
+ { "timex", IPFY_ICMPT_TIMEX },
+ { NULL, 0 },
+};
+
+static struct wordtab icmpcodewords[17] = {
+ { "cutoff-preced", IPFY_ICMPC_CUTPRE },
+ { "filter-prohib", IPFY_ICMPC_FLTPRO },
+ { "isolate", IPFY_ICMPC_ISOLATE },
+ { "needfrag", IPFY_ICMPC_NEEDF },
+ { "net-prohib", IPFY_ICMPC_NETPRO },
+ { "net-tos", IPFY_ICMPC_NETTOS },
+ { "host-preced", IPFY_ICMPC_HSTPRE },
+ { "host-prohib", IPFY_ICMPC_HSTPRO },
+ { "host-tos", IPFY_ICMPC_HSTTOS },
+ { "host-unk", IPFY_ICMPC_HSTUNK },
+ { "host-unr", IPFY_ICMPC_HSTUNR },
+ { "net-unk", IPFY_ICMPC_NETUNK },
+ { "net-unr", IPFY_ICMPC_NETUNR },
+ { "port-unr", IPFY_ICMPC_PORUNR },
+ { "proto-unr", IPFY_ICMPC_PROUNR },
+ { "srcfail", IPFY_ICMPC_SRCFAIL },
+ { NULL, 0 },
+};
+
+static struct wordtab ipv4optwords[25] = {
+ { "addext", IPFY_IPOPT_ADDEXT },
+ { "cipso", IPFY_IPOPT_CIPSO },
+ { "dps", IPFY_IPOPT_DPS },
+ { "e-sec", IPFY_IPOPT_ESEC },
+ { "eip", IPFY_IPOPT_EIP },
+ { "encode", IPFY_IPOPT_ENCODE },
+ { "finn", IPFY_IPOPT_FINN },
+ { "imitd", IPFY_IPOPT_IMITD },
+ { "lsrr", IPFY_IPOPT_LSRR },
+ { "mtup", IPFY_IPOPT_MTUP },
+ { "mtur", IPFY_IPOPT_MTUR },
+ { "nop", IPFY_IPOPT_NOP },
+ { "nsapa", IPFY_IPOPT_NSAPA },
+ { "rr", IPFY_IPOPT_RR },
+ { "rtralrt", IPFY_IPOPT_RTRALRT },
+ { "satid", IPFY_IPOPT_SATID },
+ { "sdb", IPFY_IPOPT_SDB },
+ { "sec", IPFY_IPOPT_SEC },
+ { "ssrr", IPFY_IPOPT_SSRR },
+ { "tr", IPFY_IPOPT_TR },
+ { "ts", IPFY_IPOPT_TS },
+ { "ump", IPFY_IPOPT_UMP },
+ { "visa", IPFY_IPOPT_VISA },
+ { "zsu", IPFY_IPOPT_ZSU },
+ { NULL, 0 },
+};
+
+static struct wordtab ipv4secwords[9] = {
+ { "confid", IPFY_SEC_CONF },
+ { "reserv-1", IPFY_SEC_RSV1 },
+ { "reserv-2", IPFY_SEC_RSV2 },
+ { "reserv-3", IPFY_SEC_RSV3 },
+ { "reserv-4", IPFY_SEC_RSV4 },
+ { "secret", IPFY_SEC_SEC },
+ { "topsecret", IPFY_SEC_TS },
+ { "unclass", IPFY_SEC_UNC },
+ { NULL, 0 },
+};
+
+static struct wordtab ipv6optwords[8] = {
+ { "dstopts", IPFY_IPV6OPT_DSTOPTS },
+ { "esp", IPFY_ESP },
+ { "frag", IPFY_FRAG },
+ { "hopopts", IPFY_IPV6OPT_HOPOPTS },
+ { "ipv6", IPFY_IPV6OPT_IPV6 },
+ { "none", IPFY_IPV6OPT_NONE },
+ { "routing", IPFY_IPV6OPT_ROUTING },
+ { NULL, 0 },
+};
+
+static struct wordtab logwords[33] = {
+ { "kern", IPFY_FAC_KERN },
+ { "user", IPFY_FAC_USER },
+ { "mail", IPFY_FAC_MAIL },
+ { "daemon", IPFY_FAC_DAEMON },
+ { "auth", IPFY_FAC_AUTH },
+ { "syslog", IPFY_FAC_SYSLOG },
+ { "lpr", IPFY_FAC_LPR },
+ { "news", IPFY_FAC_NEWS },
+ { "uucp", IPFY_FAC_UUCP },
+ { "cron", IPFY_FAC_CRON },
+ { "ftp", IPFY_FAC_FTP },
+ { "authpriv", IPFY_FAC_AUTHPRIV },
+ { "audit", IPFY_FAC_AUDIT },
+ { "logalert", IPFY_FAC_LFMT },
+ { "console", IPFY_FAC_CONSOLE },
+ { "security", IPFY_FAC_SECURITY },
+ { "local0", IPFY_FAC_LOCAL0 },
+ { "local1", IPFY_FAC_LOCAL1 },
+ { "local2", IPFY_FAC_LOCAL2 },
+ { "local3", IPFY_FAC_LOCAL3 },
+ { "local4", IPFY_FAC_LOCAL4 },
+ { "local5", IPFY_FAC_LOCAL5 },
+ { "local6", IPFY_FAC_LOCAL6 },
+ { "local7", IPFY_FAC_LOCAL7 },
+ { "emerg", IPFY_PRI_EMERG },
+ { "alert", IPFY_PRI_ALERT },
+ { "crit", IPFY_PRI_CRIT },
+ { "err", IPFY_PRI_ERR },
+ { "warn", IPFY_PRI_WARN },
+ { "notice", IPFY_PRI_NOTICE },
+ { "info", IPFY_PRI_INFO },
+ { "debug", IPFY_PRI_DEBUG },
+ { NULL, 0 },
+};
+
+
+
+
+int ipf_parsefile(fd, addfunc, iocfuncs, filename)
+int fd;
+addfunc_t addfunc;
+ioctlfunc_t *iocfuncs;
+char *filename;
+{
+ FILE *fp = NULL;
+ char *s;
+
+ yylineNum = 1;
+ yysettab(ipfwords);
+
+ s = getenv("YYDEBUG");
+ if (s != NULL)
+ yydebug = atoi(s);
+ else
+ yydebug = 0;
+
+ if (strcmp(filename, "-")) {
+ fp = fopen(filename, "r");
+ if (fp == NULL) {
+ fprintf(stderr, "fopen(%s) failed: %s\n", filename,
+ STRERROR(errno));
+ return -1;
+ }
+ } else
+ fp = stdin;
+
+ while (ipf_parsesome(fd, addfunc, iocfuncs, fp) == 1)
+ ;
+ if (fp != NULL)
+ fclose(fp);
+ return 0;
+}
+
+
+int ipf_parsesome(fd, addfunc, iocfuncs, fp)
+int fd;
+addfunc_t addfunc;
+ioctlfunc_t *iocfuncs;
+FILE *fp;
+{
+ char *s;
+ int i;
+
+ ipffd = fd;
+ for (i = 0; i <= IPL_LOGMAX; i++)
+ ipfioctl[i] = iocfuncs[i];
+ ipfaddfunc = addfunc;
+
+ if (feof(fp))
+ return 0;
+ i = fgetc(fp);
+ if (i == EOF)
+ return 0;
+ if (ungetc(i, fp) == 0)
+ return 0;
+ if (feof(fp))
+ return 0;
+ s = getenv("YYDEBUG");
+ if (s != NULL)
+ yydebug = atoi(s);
+ else
+ yydebug = 0;
+
+ yyin = fp;
+ yyparse();
+ return 1;
+}
+
+
+static void newrule()
+{
+ frentry_t *frn;
+
+ frn = (frentry_t *)calloc(1, sizeof(frentry_t));
+ for (fr = frtop; fr != NULL && fr->fr_next != NULL; fr = fr->fr_next)
+ ;
+ if (fr != NULL)
+ fr->fr_next = frn;
+ if (frtop == NULL)
+ frtop = frn;
+ fr = frn;
+ frc = frn;
+ fr->fr_loglevel = 0xffff;
+ fr->fr_isc = (void *)-1;
+ fr->fr_logtag = FR_NOLOGTAG;
+ fr->fr_type = FR_T_NONE;
+ if (use_inet6 != 0)
+ fr->fr_v = 6;
+ else
+ fr->fr_v = 4;
+
+ nrules = 1;
+}
+
+
+static void setipftype()
+{
+ for (fr = frc; fr != NULL; fr = fr->fr_next) {
+ if (fr->fr_type == FR_T_NONE) {
+ fr->fr_type = FR_T_IPF;
+ fr->fr_data = (void *)calloc(sizeof(fripf_t), 1);
+ fr->fr_dsize = sizeof(fripf_t);
+ fr->fr_ip.fi_v = frc->fr_v;
+ fr->fr_mip.fi_v = 0xf;
+ fr->fr_ipf->fri_sifpidx = -1;
+ fr->fr_ipf->fri_difpidx = -1;
+ }
+ if (fr->fr_type != FR_T_IPF) {
+ fprintf(stderr, "IPF Type not set\n");
+ }
+ }
+}
+
+
+static frentry_t *addrule()
+{
+ frentry_t *f, *f1, *f2;
+ int count;
+
+ for (f2 = frc; f2->fr_next != NULL; f2 = f2->fr_next)
+ ;
+
+ count = nrules;
+ if (count == 0) {
+ f = (frentry_t *)calloc(sizeof(*f), 1);
+ added++;
+ f2->fr_next = f;
+ bcopy(f2, f, sizeof(*f));
+ if (f2->fr_caddr != NULL) {
+ f->fr_caddr = malloc(f->fr_dsize);
+ bcopy(f2->fr_caddr, f->fr_caddr, f->fr_dsize);
+ }
+ f->fr_next = NULL;
+ return f;
+ }
+ f = f2;
+ for (f1 = frc; count > 0; count--, f1 = f1->fr_next) {
+ f->fr_next = (frentry_t *)calloc(sizeof(*f), 1);
+ added++;
+ f = f->fr_next;
+ bcopy(f1, f, sizeof(*f));
+ f->fr_next = NULL;
+ if (f->fr_caddr != NULL) {
+ f->fr_caddr = malloc(f->fr_dsize);
+ bcopy(f1->fr_caddr, f->fr_caddr, f->fr_dsize);
+ }
+ }
+
+ return f2->fr_next;
+}
+
+
+static u_32_t lookuphost(name)
+char *name;
+{
+ u_32_t addr;
+ int i;
+
+ hashed = 0;
+ pooled = 0;
+ dynamic = -1;
+
+ for (i = 0; i < 4; i++) {
+ if (strncmp(name, frc->fr_ifnames[i],
+ sizeof(frc->fr_ifnames[i])) == 0) {
+ ifpflag = FRI_DYNAMIC;
+ dynamic = i;
+ return 0;
+ }
+ }
+
+ if (gethost(name, &addr) == -1) {
+ fprintf(stderr, "unknown name \"%s\"\n", name);
+ return 0;
+ }
+ return addr;
+}
+
+
+static void dobpf(v, phrase)
+int v;
+char *phrase;
+{
+#ifdef IPFILTER_BPF
+ struct bpf_program bpf;
+ struct pcap *p;
+#endif
+ fakebpf_t *fb;
+ u_32_t l;
+ char *s;
+ int i;
+
+ for (fr = frc; fr != NULL; fr = fr->fr_next) {
+ if (fr->fr_type != FR_T_NONE) {
+ fprintf(stderr, "cannot mix IPF and BPF matching\n");
+ return;
+ }
+ fr->fr_v = v;
+ fr->fr_type = FR_T_BPFOPC;
+
+ if (!strncmp(phrase, "\"0x", 2)) {
+ phrase++;
+ fb = malloc(sizeof(fakebpf_t));
+
+ for (i = 0, s = strtok(phrase, " \r\n\t"); s != NULL;
+ s = strtok(NULL, " \r\n\t"), i++) {
+ fb = realloc(fb, (i / 4 + 1) * sizeof(*fb));
+ l = (u_32_t)strtol(s, NULL, 0);
+ switch (i & 3)
+ {
+ case 0 :
+ fb[i / 4].fb_c = l & 0xffff;
+ break;
+ case 1 :
+ fb[i / 4].fb_t = l & 0xff;
+ break;
+ case 2 :
+ fb[i / 4].fb_f = l & 0xff;
+ break;
+ case 3 :
+ fb[i / 4].fb_k = l;
+ break;
+ }
+ }
+ if ((i & 3) != 0) {
+ fprintf(stderr,
+ "Odd number of bytes in BPF code\n");
+ exit(1);
+ }
+ i--;
+ fr->fr_dsize = (i / 4 + 1) * sizeof(*fb);
+ fr->fr_data = fb;
+ return;
+ }
+
+#ifdef IPFILTER_BPF
+ bzero((char *)&bpf, sizeof(bpf));
+ p = pcap_open_dead(DLT_RAW, 1);
+ if (!p) {
+ fprintf(stderr, "pcap_open_dead failed\n");
+ return;
+ }
+
+ if (pcap_compile(p, &bpf, phrase, 1, 0xffffffff)) {
+ pcap_perror(p, "ipf");
+ pcap_close(p);
+ fprintf(stderr, "pcap parsing failed (%s)\n", phrase);
+ return;
+ }
+ pcap_close(p);
+
+ fr->fr_dsize = bpf.bf_len * sizeof(struct bpf_insn);
+ fr->fr_data = malloc(fr->fr_dsize);
+ bcopy((char *)bpf.bf_insns, fr->fr_data, fr->fr_dsize);
+ if (!bpf_validate(fr->fr_data, bpf.bf_len)) {
+ fprintf(stderr, "BPF validation failed\n");
+ return;
+ }
+#endif
+ }
+
+#ifdef IPFILTER_BPF
+ if (opts & OPT_DEBUG)
+ bpf_dump(&bpf, 0);
+#else
+ fprintf(stderr, "BPF filter expressions not supported\n");
+ exit(1);
+#endif
+}
+
+
+static void resetaddr()
+{
+ hashed = 0;
+ pooled = 0;
+ dynamic = -1;
+}
+
+
+static alist_t *newalist(ptr)
+alist_t *ptr;
+{
+ alist_t *al;
+
+ al = malloc(sizeof(*al));
+ if (al == NULL)
+ return NULL;
+ al->al_not = 0;
+ al->al_next = ptr;
+ return al;
+}
+
+
+static int makepool(list)
+alist_t *list;
+{
+ ip_pool_node_t *n, *top;
+ ip_pool_t pool;
+ alist_t *a;
+ int num;
+
+ if (list == NULL)
+ return 0;
+ top = calloc(1, sizeof(*top));
+ if (top == NULL)
+ return 0;
+
+ for (n = top, a = list; (n != NULL) && (a != NULL); a = a->al_next) {
+ n->ipn_addr.adf_addr.in4.s_addr = a->al_1;
+ n->ipn_mask.adf_addr.in4.s_addr = a->al_2;
+ n->ipn_info = a->al_not;
+ if (a->al_next != NULL) {
+ n->ipn_next = calloc(1, sizeof(*n));
+ n = n->ipn_next;
+ }
+ }
+
+ bzero((char *)&pool, sizeof(pool));
+ pool.ipo_unit = IPL_LOGIPF;
+ pool.ipo_list = top;
+ num = load_pool(&pool, ipfioctl[IPL_LOGLOOKUP]);
+
+ while ((n = top) != NULL) {
+ top = n->ipn_next;
+ free(n);
+ }
+ return num;
+}
+
+
+static u_int makehash(list)
+alist_t *list;
+{
+ iphtent_t *n, *top;
+ iphtable_t iph;
+ alist_t *a;
+ int num;
+
+ if (list == NULL)
+ return 0;
+ top = calloc(1, sizeof(*top));
+ if (top == NULL)
+ return 0;
+
+ for (n = top, a = list; (n != NULL) && (a != NULL); a = a->al_next) {
+ n->ipe_addr.in4_addr = a->al_1;
+ n->ipe_mask.in4_addr = a->al_2;
+ n->ipe_value = 0;
+ if (a->al_next != NULL) {
+ n->ipe_next = calloc(1, sizeof(*n));
+ n = n->ipe_next;
+ }
+ }
+
+ bzero((char *)&iph, sizeof(iph));
+ iph.iph_unit = IPL_LOGIPF;
+ iph.iph_type = IPHASH_LOOKUP;
+ *iph.iph_name = '\0';
+
+ if (load_hash(&iph, top, ipfioctl[IPL_LOGLOOKUP]) == 0)
+ sscanf(iph.iph_name, "%u", &num);
+ else
+ num = 0;
+
+ while ((n = top) != NULL) {
+ top = n->ipe_next;
+ free(n);
+ }
+ return num;
+}
+
+
+void ipf_addrule(fd, ioctlfunc, ptr)
+int fd;
+ioctlfunc_t ioctlfunc;
+void *ptr;
+{
+ ioctlcmd_t add, del;
+ frentry_t *fr;
+ ipfobj_t obj;
+
+ fr = ptr;
+ add = 0;
+ del = 0;
+
+ bzero((char *)&obj, sizeof(obj));
+ obj.ipfo_rev = IPFILTER_VERSION;
+ obj.ipfo_size = sizeof(*fr);
+ obj.ipfo_type = IPFOBJ_FRENTRY;
+ obj.ipfo_ptr = ptr;
+
+ if ((opts & OPT_DONOTHING) != 0)
+ fd = -1;
+
+ if (opts & OPT_ZERORULEST) {
+ add = SIOCZRLST;
+ } else if (opts & OPT_INACTIVE) {
+ add = (u_int)fr->fr_hits ? SIOCINIFR :
+ SIOCADIFR;
+ del = SIOCRMIFR;
+ } else {
+ add = (u_int)fr->fr_hits ? SIOCINAFR :
+ SIOCADAFR;
+ del = SIOCRMAFR;
+ }
+
+ if (fr && (opts & OPT_OUTQUE))
+ fr->fr_flags |= FR_OUTQUE;
+ if (fr->fr_hits)
+ fr->fr_hits--;
+ if (fr && (opts & OPT_VERBOSE))
+ printfr(fr, ioctlfunc);
+
+ if (opts & OPT_DEBUG) {
+ binprint(fr, sizeof(*fr));
+ if (fr->fr_data != NULL)
+ binprint(fr->fr_data, fr->fr_dsize);
+ }
+
+ if ((opts & OPT_ZERORULEST) != 0) {
+ if ((*ioctlfunc)(fd, add, (void *)&obj) == -1) {
+ if ((opts & OPT_DONOTHING) == 0) {
+ fprintf(stderr, "%d:", yylineNum);
+ perror("ioctl(SIOCZRLST)");
+ }
+ } else {
+#ifdef USE_QUAD_T
+ printf("hits %qd bytes %qd ",
+ (long long)fr->fr_hits,
+ (long long)fr->fr_bytes);
+#else
+ printf("hits %ld bytes %ld ",
+ fr->fr_hits, fr->fr_bytes);
+#endif
+ printfr(fr, ioctlfunc);
+ }
+ } else if ((opts & OPT_REMOVE) != 0) {
+ if ((*ioctlfunc)(fd, del, (void *)&obj) == -1) {
+ if ((opts & OPT_DONOTHING) != 0) {
+ fprintf(stderr, "%d:", yylineNum);
+ perror("ioctl(delete rule)");
+ }
+ }
+ } else {
+ if ((*ioctlfunc)(fd, add, (void *)&obj) == -1) {
+ if (!(opts & OPT_DONOTHING)) {
+ fprintf(stderr, "%d:", yylineNum);
+ perror("ioctl(add/insert rule)");
+ }
+ }
+ }
+}
+
+static void setsyslog()
+{
+ yysetdict(logwords);
+ yybreakondot = 1;
+}
+
+
+static void unsetsyslog()
+{
+ yyresetdict();
+ yybreakondot = 0;
+}
+
+
+static void fillgroup(fr)
+frentry_t *fr;
+{
+ frentry_t *f;
+
+ for (f = frold; f != NULL; f = f->fr_next)
+ if (strncmp(f->fr_grhead, fr->fr_group, FR_GROUPLEN) == 0)
+ break;
+ if (f == NULL)
+ return;
+
+ /*
+ * Only copy down matching fields if the rules are of the same type
+ * and are of ipf type. The only fields that are copied are those
+ * that impact the rule parsing itself, eg. need for knowing what the
+ * protocol should be for rules with port comparisons in them.
+ */
+ if (f->fr_type != fr->fr_type || f->fr_type != FR_T_IPF)
+ return;
+
+ if (fr->fr_v == 0 && f->fr_v != 0)
+ fr->fr_v = f->fr_v;
+
+ if (fr->fr_mproto == 0 && f->fr_mproto != 0)
+ fr->fr_mproto = f->fr_mproto;
+ if (fr->fr_proto == 0 && f->fr_proto != 0)
+ fr->fr_proto = f->fr_proto;
+
+ if ((fr->fr_mproto == 0) && ((fr->fr_flx & FI_TCPUDP) == 0) &&
+ ((f->fr_flx & FI_TCPUDP) != 0))
+ fr->fr_flx |= FI_TCPUDP;
+}
diff --git a/contrib/ipfilter/tools/ipfcomp.c b/contrib/ipfilter/tools/ipfcomp.c
new file mode 100644
index 0000000..262e909
--- /dev/null
+++ b/contrib/ipfilter/tools/ipfcomp.c
@@ -0,0 +1,1347 @@
+/* $NetBSD$ */
+
+/*
+ * Copyright (C) 1993-2001 by Darren Reed.
+ *
+ * See the IPFILTER.LICENCE file for details on licencing.
+ */
+#if !defined(lint)
+static const char sccsid[] = "@(#)ip_fil.c 2.41 6/5/96 (C) 1993-2000 Darren Reed";
+static const char rcsid[] = "@(#)Id: ipfcomp.c,v 1.24.2.2 2004/04/28 10:34:44 darrenr Exp";
+#endif
+
+#include "ipf.h"
+
+
+typedef struct {
+ int c;
+ int e;
+ int n;
+ int p;
+ int s;
+} mc_t;
+
+
+static char *portcmp[] = { "*", "==", "!=", "<", ">", "<=", ">=", "**", "***" };
+static int count = 0;
+
+int intcmp __P((const void *, const void *));
+static void indent __P((FILE *, int));
+static void printeq __P((FILE *, char *, int, int, int));
+static void printipeq __P((FILE *, char *, int, int, int));
+static void addrule __P((FILE *, frentry_t *));
+static void printhooks __P((FILE *, int, int, frgroup_t *));
+static void emitheader __P((frgroup_t *, u_int, u_int));
+static void emitGroup __P((int, int, void *, frentry_t *, char *,
+ u_int, u_int));
+static void emittail __P((void));
+static void printCgroup __P((int, frentry_t *, mc_t *, char *));
+
+#define FRC_IFN 0
+#define FRC_V 1
+#define FRC_P 2
+#define FRC_FL 3
+#define FRC_TOS 4
+#define FRC_TTL 5
+#define FRC_SRC 6
+#define FRC_DST 7
+#define FRC_TCP 8
+#define FRC_SP 9
+#define FRC_DP 10
+#define FRC_OPT 11
+#define FRC_SEC 12
+#define FRC_ATH 13
+#define FRC_ICT 14
+#define FRC_ICC 15
+#define FRC_MAX 16
+
+
+static FILE *cfile = NULL;
+
+/*
+ * This is called once per filter rule being loaded to emit data structures
+ * required.
+ */
+void printc(fr)
+frentry_t *fr;
+{
+ fripf_t *ipf;
+ u_long *ulp;
+ char *and;
+ FILE *fp;
+ int i;
+
+ if (fr->fr_v != 4)
+ return;
+ if ((fr->fr_type != FR_T_IPF) && (fr->fr_type != FR_T_NONE))
+ return;
+ if ((fr->fr_type == FR_T_IPF) &&
+ ((fr->fr_datype != FRI_NORMAL) || (fr->fr_satype != FRI_NORMAL)))
+ return;
+ ipf = fr->fr_ipf;
+
+ if (cfile == NULL)
+ cfile = fopen("ip_rules.c", "w");
+ if (cfile == NULL)
+ return;
+ fp = cfile;
+ if (count == 0) {
+ fprintf(fp, "/*\n");
+ fprintf(fp, "* Copyright (C) 1993-2000 by Darren Reed.\n");
+ fprintf(fp, "*\n");
+ fprintf(fp, "* Redistribution and use in source and binary forms are permitted\n");
+ fprintf(fp, "* provided that this notice is preserved and due credit is given\n");
+ fprintf(fp, "* to the original author and the contributors.\n");
+ fprintf(fp, "*/\n\n");
+
+ fprintf(fp, "#include <sys/types.h>\n");
+ fprintf(fp, "#include <sys/time.h>\n");
+ fprintf(fp, "#include <sys/socket.h>\n");
+ fprintf(fp, "#if !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__sgi)\n");
+ fprintf(fp, "# include <sys/systm.h>\n");
+ fprintf(fp, "#endif\n");
+ fprintf(fp, "#include <sys/errno.h>\n");
+ fprintf(fp, "#include <sys/param.h>\n");
+ fprintf(fp,
+"#if !defined(__SVR4) && !defined(__svr4__) && !defined(__hpux)\n");
+ fprintf(fp, "# include <sys/mbuf.h>\n");
+ fprintf(fp, "#endif\n");
+ fprintf(fp,
+"#if defined(__FreeBSD__) && (__FreeBSD_version > 220000)\n");
+ fprintf(fp, "# include <sys/sockio.h>\n");
+ fprintf(fp, "#else\n");
+ fprintf(fp, "# include <sys/ioctl.h>\n");
+ fprintf(fp, "#endif /* FreeBSD */\n");
+ fprintf(fp, "#include <net/if.h>\n");
+ fprintf(fp, "#include <netinet/in.h>\n");
+ fprintf(fp, "#include <netinet/in_systm.h>\n");
+ fprintf(fp, "#include <netinet/ip.h>\n");
+ fprintf(fp, "#include <netinet/tcp.h>\n");
+ fprintf(fp, "#include \"netinet/ip_compat.h\"\n");
+ fprintf(fp, "#include \"netinet/ip_fil.h\"\n\n");
+ fprintf(fp, "#include \"netinet/ip_rules.h\"\n\n");
+ fprintf(fp, "#ifndef _KERNEL\n");
+ fprintf(fp, "# include <string.h>\n");
+ fprintf(fp, "#endif /* _KERNEL */\n");
+ fprintf(fp, "\n");
+ fprintf(fp, "#ifdef IPFILTER_COMPILED\n");
+ }
+
+ addrule(fp, fr);
+ fr->fr_type |= FR_T_BUILTIN;
+ and = "";
+ fr->fr_ref = 1;
+ i = sizeof(*fr);
+ if (i & -(1 - sizeof(*ulp)))
+ i += sizeof(u_long);
+ for (i /= sizeof(u_long), ulp = (u_long *)fr; i > 0; i--) {
+ fprintf(fp, "%s%#lx", and, *ulp++);
+ and = ", ";
+ }
+ fprintf(fp, "\n};\n");
+ fr->fr_type &= ~FR_T_BUILTIN;
+
+ count++;
+
+ fflush(fp);
+}
+
+
+static frgroup_t *groups = NULL;
+
+
+static void addrule(fp, fr)
+FILE *fp;
+frentry_t *fr;
+{
+ frentry_t *f, **fpp;
+ frgroup_t *g;
+ u_long *ulp;
+ char *and;
+ int i;
+
+ f = (frentry_t *)malloc(sizeof(*f));
+ bcopy((char *)fr, (char *)f, sizeof(*fr));
+ if (fr->fr_ipf) {
+ f->fr_ipf = (fripf_t *)malloc(sizeof(*f->fr_ipf));
+ bcopy((char *)fr->fr_ipf, (char *)f->fr_ipf,
+ sizeof(*fr->fr_ipf));
+ }
+
+ f->fr_next = NULL;
+ for (g = groups; g != NULL; g = g->fg_next)
+ if ((strncmp(g->fg_name, f->fr_group, FR_GROUPLEN) == 0) &&
+ (g->fg_flags == (f->fr_flags & FR_INOUT)))
+ break;
+
+ if (g == NULL) {
+ g = (frgroup_t *)calloc(1, sizeof(*g));
+ g->fg_next = groups;
+ groups = g;
+ g->fg_head = f;
+ bcopy(f->fr_group, g->fg_name, FR_GROUPLEN);
+ g->fg_ref = 0;
+ g->fg_flags = f->fr_flags & FR_INOUT;
+ }
+
+ for (fpp = &g->fg_start; *fpp != NULL; )
+ fpp = &((*fpp)->fr_next);
+ *fpp = f;
+
+ if (fr->fr_dsize > 0) {
+ fprintf(fp, "\
+static u_long ipf%s_rule_data_%s_%u[] = {\n",
+ f->fr_flags & FR_INQUE ? "in" : "out",
+ g->fg_name, g->fg_ref);
+ and = "";
+ i = fr->fr_dsize;
+ ulp = fr->fr_data;
+ for (i /= sizeof(u_long); i > 0; i--) {
+ fprintf(fp, "%s%#lx", and, *ulp++);
+ and = ", ";
+ }
+ fprintf(fp, "\n};\n");
+ }
+
+ fprintf(fp, "\nstatic u_long %s_rule_%s_%d[] = {\n",
+ f->fr_flags & FR_INQUE ? "in" : "out", g->fg_name, g->fg_ref);
+
+ g->fg_ref++;
+
+ if (f->fr_grhead != 0) {
+ for (g = groups; g != NULL; g = g->fg_next)
+ if ((strncmp(g->fg_name, f->fr_grhead,
+ FR_GROUPLEN) == 0) &&
+ g->fg_flags == (f->fr_flags & FR_INOUT))
+ break;
+ if (g == NULL) {
+ g = (frgroup_t *)calloc(1, sizeof(*g));
+ g->fg_next = groups;
+ groups = g;
+ g->fg_head = f;
+ bcopy(f->fr_grhead, g->fg_name, FR_GROUPLEN);
+ g->fg_ref = 0;
+ g->fg_flags = f->fr_flags & FR_INOUT;
+ }
+ }
+}
+
+
+int intcmp(c1, c2)
+const void *c1, *c2;
+{
+ const mc_t *i1 = (const mc_t *)c1, *i2 = (const mc_t *)c2;
+
+ if (i1->n == i2->n) {
+ return i1->c - i2->c;
+ }
+ return i2->n - i1->n;
+}
+
+
+static void indent(fp, in)
+FILE *fp;
+int in;
+{
+ for (; in; in--)
+ fputc('\t', fp);
+}
+
+static void printeq(fp, var, m, max, v)
+FILE *fp;
+char *var;
+int m, max, v;
+{
+ if (m == max)
+ fprintf(fp, "%s == %#x) {\n", var, v);
+ else
+ fprintf(fp, "(%s & %#x) == %#x) {\n", var, m, v);
+}
+
+/*
+ * Parameters: var - IP# being compared
+ * fl - 0 for positive match, 1 for negative match
+ * m - netmask
+ * v - required address
+ */
+static void printipeq(fp, var, fl, m, v)
+FILE *fp;
+char *var;
+int fl, m, v;
+{
+ if (m == 0xffffffff)
+ fprintf(fp, "%s ", var);
+ else
+ fprintf(fp, "(%s & %#x) ", var, m);
+ fprintf(fp, "%c", fl ? '!' : '=');
+ fprintf(fp, "= %#x) {\n", v);
+}
+
+
+void emit(num, dir, v, fr)
+int num, dir;
+void *v;
+frentry_t *fr;
+{
+ u_int incnt, outcnt;
+ frgroup_t *g;
+ frentry_t *f;
+
+ for (g = groups; g != NULL; g = g->fg_next) {
+ if (dir == 0 || dir == -1) {
+ if ((g->fg_flags & FR_INQUE) == 0)
+ continue;
+ for (incnt = 0, f = g->fg_start; f != NULL;
+ f = f->fr_next)
+ incnt++;
+ emitGroup(num, dir, v, fr, g->fg_name, incnt, 0);
+ }
+ if (dir == 1 || dir == -1) {
+ if ((g->fg_flags & FR_OUTQUE) == 0)
+ continue;
+ for (outcnt = 0, f = g->fg_start; f != NULL;
+ f = f->fr_next)
+ outcnt++;
+ emitGroup(num, dir, v, fr, g->fg_name, 0, outcnt);
+ }
+ }
+
+ if (num == -1 && dir == -1) {
+ for (g = groups; g != NULL; g = g->fg_next) {
+ if ((g->fg_flags & FR_INQUE) != 0) {
+ for (incnt = 0, f = g->fg_start; f != NULL;
+ f = f->fr_next)
+ incnt++;
+ if (incnt > 0)
+ emitheader(g, incnt, 0);
+ }
+ if ((g->fg_flags & FR_OUTQUE) != 0) {
+ for (outcnt = 0, f = g->fg_start; f != NULL;
+ f = f->fr_next)
+ outcnt++;
+ if (outcnt > 0)
+ emitheader(g, 0, outcnt);
+ }
+ }
+ emittail();
+ fprintf(cfile, "#endif /* IPFILTER_COMPILED */\n");
+ }
+
+}
+
+
+static void emitheader(grp, incount, outcount)
+frgroup_t *grp;
+u_int incount, outcount;
+{
+ static FILE *fph = NULL;
+ frgroup_t *g;
+
+ if (fph == NULL) {
+ fph = fopen("ip_rules.h", "w");
+ if (fph == NULL)
+ return;
+
+ fprintf(fph, "extern int ipfrule_add __P((void));\n");
+ fprintf(fph, "extern int ipfrule_remove __P((void));\n");
+ }
+
+ printhooks(cfile, incount, outcount, grp);
+
+ if (incount) {
+ fprintf(fph, "\n\
+extern frentry_t *ipfrule_match_in_%s __P((fr_info_t *, u_32_t *));\n\
+extern frentry_t *ipf_rules_in_%s[%d];\n",
+ grp->fg_name, grp->fg_name, incount);
+
+ for (g = groups; g != grp; g = g->fg_next)
+ if ((strncmp(g->fg_name, grp->fg_name,
+ FR_GROUPLEN) == 0) &&
+ g->fg_flags == grp->fg_flags)
+ break;
+ if (g == grp) {
+ fprintf(fph, "\n\
+extern int ipfrule_add_in_%s __P((void));\n\
+extern int ipfrule_remove_in_%s __P((void));\n", grp->fg_name, grp->fg_name);
+ }
+ }
+ if (outcount) {
+ fprintf(fph, "\n\
+extern frentry_t *ipfrule_match_out_%s __P((fr_info_t *, u_32_t *));\n\
+extern frentry_t *ipf_rules_out_%s[%d];\n",
+ grp->fg_name, grp->fg_name, outcount);
+
+ for (g = groups; g != g; g = g->fg_next)
+ if ((strncmp(g->fg_name, grp->fg_name,
+ FR_GROUPLEN) == 0) &&
+ g->fg_flags == grp->fg_flags)
+ break;
+ if (g == grp) {
+ fprintf(fph, "\n\
+extern int ipfrule_add_out_%s __P((void));\n\
+extern int ipfrule_remove_out_%s __P((void));\n",
+ grp->fg_name, grp->fg_name);
+ }
+ }
+}
+
+static void emittail()
+{
+ frgroup_t *g;
+
+ fprintf(cfile, "\n\
+int ipfrule_add()\n\
+{\n\
+ int err;\n\
+\n");
+ for (g = groups; g != NULL; g = g->fg_next)
+ fprintf(cfile, "\
+ err = ipfrule_add_%s_%s();\n\
+ if (err != 0)\n\
+ return err;\n",
+ (g->fg_flags & FR_INQUE) ? "in" : "out", g->fg_name);
+ fprintf(cfile, "\
+ return 0;\n");
+ fprintf(cfile, "}\n\
+\n");
+
+ fprintf(cfile, "\n\
+int ipfrule_remove()\n\
+{\n\
+ int err;\n\
+\n");
+ for (g = groups; g != NULL; g = g->fg_next)
+ fprintf(cfile, "\
+ err = ipfrule_remove_%s_%s();\n\
+ if (err != 0)\n\
+ return err;\n",
+ (g->fg_flags & FR_INQUE) ? "in" : "out", g->fg_name);
+ fprintf(cfile, "\
+ return 0;\n");
+ fprintf(cfile, "}\n");
+}
+
+
+static void emitGroup(num, dir, v, fr, group, incount, outcount)
+int num, dir;
+void *v;
+frentry_t *fr;
+char *group;
+u_int incount, outcount;
+{
+ static FILE *fp = NULL;
+ static int header[2] = { 0, 0 };
+ static char egroup[FR_GROUPLEN] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+ static int openfunc = 0;
+ static mc_t *n = NULL;
+ static int sin = 0;
+ frentry_t *f;
+ frgroup_t *g;
+ fripf_t *ipf;
+ int i, in, j;
+ mc_t *m = v;
+
+ if (fp == NULL)
+ fp = cfile;
+ if (fp == NULL)
+ return;
+ if (strncmp(egroup, group, FR_GROUPLEN)) {
+ for (sin--; sin > 0; sin--) {
+ indent(fp, sin);
+ fprintf(fp, "}\n");
+ }
+ if (openfunc == 1) {
+ fprintf(fp, "\treturn fr;\n}\n");
+ openfunc = 0;
+ if (n != NULL) {
+ free(n);
+ n = NULL;
+ }
+ }
+ sin = 0;
+ header[0] = 0;
+ header[1] = 0;
+ strncpy(egroup, group, FR_GROUPLEN);
+ } else if (openfunc == 1 && num < 0) {
+ if (n != NULL) {
+ free(n);
+ n = NULL;
+ }
+ for (sin--; sin > 0; sin--) {
+ indent(fp, sin);
+ fprintf(fp, "}\n");
+ }
+ if (openfunc == 1) {
+ fprintf(fp, "\treturn fr;\n}\n");
+ openfunc = 0;
+ }
+ }
+
+ if (dir == -1)
+ return;
+
+ for (g = groups; g != NULL; g = g->fg_next) {
+ if (dir == 0 && (g->fg_flags & FR_INQUE) == 0)
+ continue;
+ else if (dir == 1 && (g->fg_flags & FR_OUTQUE) == 0)
+ continue;
+ if (strncmp(g->fg_name, group, FR_GROUPLEN) != 0)
+ continue;
+ break;
+ }
+
+ /*
+ * Output the array of pointers to rules for this group.
+ */
+ if (num == -2 && dir == 0 && header[0] == 0 && incount != 0) {
+ fprintf(fp, "\nfrentry_t *ipf_rules_in_%s[%d] = {",
+ group, incount);
+ for (f = g->fg_start, i = 0; f != NULL; f = f->fr_next) {
+ if ((f->fr_flags & FR_INQUE) == 0)
+ continue;
+ if ((i & 1) == 0) {
+ fprintf(fp, "\n\t");
+ }
+ fprintf(fp,
+ "(frentry_t *)&in_rule_%s_%d",
+ f->fr_group, i);
+ if (i + 1 < incount)
+ fprintf(fp, ", ");
+ i++;
+ }
+ fprintf(fp, "\n};\n");
+ }
+
+ if (num == -2 && dir == 1 && header[1] == 0 && outcount != 0) {
+ fprintf(fp, "\nfrentry_t *ipf_rules_out_%s[%d] = {",
+ group, outcount);
+ for (f = g->fg_start, i = 0; f != NULL; f = f->fr_next) {
+ if ((f->fr_flags & FR_OUTQUE) == 0)
+ continue;
+ if ((i & 1) == 0) {
+ fprintf(fp, "\n\t");
+ }
+ fprintf(fp,
+ "(frentry_t *)&out_rule_%s_%d",
+ f->fr_group, i);
+ if (i + 1 < outcount)
+ fprintf(fp, ", ");
+ i++;
+ }
+ fprintf(fp, "\n};\n");
+ fp = NULL;
+ }
+
+ if (num < 0)
+ return;
+
+ in = 0;
+ ipf = fr->fr_ipf;
+
+ /*
+ * If the function header has not been printed then print it now.
+ */
+ if (header[dir] == 0) {
+ int pdst = 0, psrc = 0;
+
+ openfunc = 1;
+ fprintf(fp, "\nfrentry_t *ipfrule_match_%s_%s(fin, passp)\n",
+ (dir == 0) ? "in" : "out", group);
+ fprintf(fp, "fr_info_t *fin;\n");
+ fprintf(fp, "u_32_t *passp;\n");
+ fprintf(fp, "{\n");
+ fprintf(fp, "\tfrentry_t *fr = NULL;\n");
+
+ /*
+ * Print out any variables that need to be declared.
+ */
+ for (f = g->fg_start, i = 0; f != NULL; f = f->fr_next) {
+ if (incount + outcount > m[FRC_SRC].e + 1)
+ psrc = 1;
+ if (incount + outcount > m[FRC_DST].e + 1)
+ pdst = 1;
+ }
+ if (psrc == 1)
+ fprintf(fp, "\tu_32_t src = ntohl(%s);\n",
+ "fin->fin_fi.fi_saddr");
+ if (pdst == 1)
+ fprintf(fp, "\tu_32_t dst = ntohl(%s);\n",
+ "fin->fin_fi.fi_daddr");
+ }
+
+ for (i = 0; i < FRC_MAX; i++) {
+ switch(m[i].c)
+ {
+ case FRC_IFN :
+ if (*fr->fr_ifname)
+ m[i].s = 1;
+ break;
+ case FRC_V :
+ if (ipf != NULL && ipf->fri_mip.fi_v != 0)
+ m[i].s = 1;
+ break;
+ case FRC_FL :
+ if (ipf != NULL && ipf->fri_mip.fi_flx != 0)
+ m[i].s = 1;
+ break;
+ case FRC_P :
+ if (ipf != NULL && ipf->fri_mip.fi_p != 0)
+ m[i].s = 1;
+ break;
+ case FRC_TTL :
+ if (ipf != NULL && ipf->fri_mip.fi_ttl != 0)
+ m[i].s = 1;
+ break;
+ case FRC_TOS :
+ if (ipf != NULL && ipf->fri_mip.fi_tos != 0)
+ m[i].s = 1;
+ break;
+ case FRC_TCP :
+ if (ipf == NULL)
+ break;
+ if ((ipf->fri_ip.fi_p == IPPROTO_TCP) &&
+ fr->fr_tcpfm != 0)
+ m[i].s = 1;
+ break;
+ case FRC_SP :
+ if (ipf == NULL)
+ break;
+ if (fr->fr_scmp == FR_INRANGE)
+ m[i].s = 1;
+ else if (fr->fr_scmp == FR_OUTRANGE)
+ m[i].s = 1;
+ else if (fr->fr_scmp != 0)
+ m[i].s = 1;
+ break;
+ case FRC_DP :
+ if (ipf == NULL)
+ break;
+ if (fr->fr_dcmp == FR_INRANGE)
+ m[i].s = 1;
+ else if (fr->fr_dcmp == FR_OUTRANGE)
+ m[i].s = 1;
+ else if (fr->fr_dcmp != 0)
+ m[i].s = 1;
+ break;
+ case FRC_SRC :
+ if (ipf == NULL)
+ break;
+ if (fr->fr_satype == FRI_LOOKUP) {
+ ;
+ } else if ((fr->fr_smask != 0) ||
+ (fr->fr_flags & FR_NOTSRCIP) != 0)
+ m[i].s = 1;
+ break;
+ case FRC_DST :
+ if (ipf == NULL)
+ break;
+ if (fr->fr_datype == FRI_LOOKUP) {
+ ;
+ } else if ((fr->fr_dmask != 0) ||
+ (fr->fr_flags & FR_NOTDSTIP) != 0)
+ m[i].s = 1;
+ break;
+ case FRC_OPT :
+ if (ipf == NULL)
+ break;
+ if (fr->fr_optmask != 0)
+ m[i].s = 1;
+ break;
+ case FRC_SEC :
+ if (ipf == NULL)
+ break;
+ if (fr->fr_secmask != 0)
+ m[i].s = 1;
+ break;
+ case FRC_ATH :
+ if (ipf == NULL)
+ break;
+ if (fr->fr_authmask != 0)
+ m[i].s = 1;
+ break;
+ case FRC_ICT :
+ if (ipf == NULL)
+ break;
+ if ((fr->fr_icmpm & 0xff00) != 0)
+ m[i].s = 1;
+ break;
+ case FRC_ICC :
+ if (ipf == NULL)
+ break;
+ if ((fr->fr_icmpm & 0xff) != 0)
+ m[i].s = 1;
+ break;
+ }
+ }
+
+ if (!header[dir]) {
+ fprintf(fp, "\n");
+ header[dir] = 1;
+ sin = 0;
+ }
+
+ qsort(m, FRC_MAX, sizeof(mc_t), intcmp);
+
+ if (n) {
+ /*
+ * Calculate the indentation interval upto the last common
+ * common comparison being made.
+ */
+ for (i = 0, in = 1; i < FRC_MAX; i++) {
+ if (n[i].c != m[i].c)
+ break;
+ if (n[i].s != m[i].s)
+ break;
+ if (n[i].s) {
+ if (n[i].n && (n[i].n > n[i].e)) {
+ m[i].p++;
+ in += m[i].p;
+ break;
+ }
+ if (n[i].e > 0) {
+ in++;
+ } else
+ break;
+ }
+ }
+ if (sin != in) {
+ for (j = sin - 1; j >= in; j--) {
+ indent(fp, j);
+ fprintf(fp, "}\n");
+ }
+ }
+ } else {
+ in = 1;
+ i = 0;
+ }
+
+ /*
+ * print out C code that implements a filter rule.
+ */
+ for (; i < FRC_MAX; i++) {
+ switch(m[i].c)
+ {
+ case FRC_IFN :
+ if (m[i].s) {
+ indent(fp, in);
+ fprintf(fp, "if (fin->fin_ifp == ");
+ fprintf(fp, "ipf_rules_%s_%s[%d]->fr_ifa) {\n",
+ dir ? "out" : "in", group, num);
+ in++;
+ }
+ break;
+ case FRC_V :
+ if (m[i].s) {
+ indent(fp, in);
+ fprintf(fp, "if (fin->fin_v == %d) {\n",
+ ipf->fri_ip.fi_v);
+ in++;
+ }
+ break;
+ case FRC_FL :
+ if (m[i].s) {
+ indent(fp, in);
+ fprintf(fp, "if (");
+ printeq(fp, "fin->fin_flx",
+ ipf->fri_mip.fi_flx, 0xf,
+ ipf->fri_ip.fi_flx);
+ in++;
+ }
+ break;
+ case FRC_P :
+ if (m[i].s) {
+ indent(fp, in);
+ fprintf(fp, "if (fin->fin_p == %d) {\n",
+ ipf->fri_ip.fi_p);
+ in++;
+ }
+ break;
+ case FRC_TTL :
+ if (m[i].s) {
+ indent(fp, in);
+ fprintf(fp, "if (");
+ printeq(fp, "fin->fin_ttl",
+ ipf->fri_mip.fi_ttl, 0xff,
+ ipf->fri_ip.fi_ttl);
+ in++;
+ }
+ break;
+ case FRC_TOS :
+ if (m[i].s) {
+ indent(fp, in);
+ fprintf(fp, "if (fin->fin_tos");
+ printeq(fp, "fin->fin_tos",
+ ipf->fri_mip.fi_tos, 0xff,
+ ipf->fri_ip.fi_tos);
+ in++;
+ }
+ break;
+ case FRC_TCP :
+ if (m[i].s) {
+ indent(fp, in);
+ fprintf(fp, "if (");
+ printeq(fp, "fin->fin_tcpf", fr->fr_tcpfm,
+ 0xff, fr->fr_tcpf);
+ in++;
+ }
+ break;
+ case FRC_SP :
+ if (!m[i].s)
+ break;
+ if (fr->fr_scmp == FR_INRANGE) {
+ indent(fp, in);
+ fprintf(fp, "if ((fin->fin_data[0] > %d) && ",
+ fr->fr_sport);
+ fprintf(fp, "(fin->fin_data[0] < %d)",
+ fr->fr_stop);
+ fprintf(fp, ") {\n");
+ in++;
+ } else if (fr->fr_scmp == FR_OUTRANGE) {
+ indent(fp, in);
+ fprintf(fp, "if ((fin->fin_data[0] < %d) || ",
+ fr->fr_sport);
+ fprintf(fp, "(fin->fin_data[0] > %d)",
+ fr->fr_stop);
+ fprintf(fp, ") {\n");
+ in++;
+ } else if (fr->fr_scmp) {
+ indent(fp, in);
+ fprintf(fp, "if (fin->fin_data[0] %s %d)",
+ portcmp[fr->fr_scmp], fr->fr_sport);
+ fprintf(fp, " {\n");
+ in++;
+ }
+ break;
+ case FRC_DP :
+ if (!m[i].s)
+ break;
+ if (fr->fr_dcmp == FR_INRANGE) {
+ indent(fp, in);
+ fprintf(fp, "if ((fin->fin_data[1] > %d) && ",
+ fr->fr_dport);
+ fprintf(fp, "(fin->fin_data[1] < %d)",
+ fr->fr_dtop);
+ fprintf(fp, ") {\n");
+ in++;
+ } else if (fr->fr_dcmp == FR_OUTRANGE) {
+ indent(fp, in);
+ fprintf(fp, "if ((fin->fin_data[1] < %d) || ",
+ fr->fr_dport);
+ fprintf(fp, "(fin->fin_data[1] > %d)",
+ fr->fr_dtop);
+ fprintf(fp, ") {\n");
+ in++;
+ } else if (fr->fr_dcmp) {
+ indent(fp, in);
+ fprintf(fp, "if (fin->fin_data[1] %s %d)",
+ portcmp[fr->fr_dcmp], fr->fr_dport);
+ fprintf(fp, " {\n");
+ in++;
+ }
+ break;
+ case FRC_SRC :
+ if (!m[i].s)
+ break;
+ if (fr->fr_satype == FRI_LOOKUP) {
+ ;
+ } else if ((fr->fr_smask != 0) ||
+ (fr->fr_flags & FR_NOTSRCIP) != 0) {
+ indent(fp, in);
+ fprintf(fp, "if (");
+ printipeq(fp, "src",
+ fr->fr_flags & FR_NOTSRCIP,
+ fr->fr_smask, fr->fr_saddr);
+ in++;
+ }
+ break;
+ case FRC_DST :
+ if (!m[i].s)
+ break;
+ if (fr->fr_datype == FRI_LOOKUP) {
+ ;
+ } else if ((fr->fr_dmask != 0) ||
+ (fr->fr_flags & FR_NOTDSTIP) != 0) {
+ indent(fp, in);
+ fprintf(fp, "if (");
+ printipeq(fp, "dst",
+ fr->fr_flags & FR_NOTDSTIP,
+ fr->fr_dmask, fr->fr_daddr);
+ in++;
+ }
+ break;
+ case FRC_OPT :
+ if (m[i].s) {
+ indent(fp, in);
+ fprintf(fp, "if (");
+ printeq(fp, "fin->fin_fi.fi_optmsk",
+ fr->fr_optmask, 0xffffffff,
+ fr->fr_optbits);
+ in++;
+ }
+ break;
+ case FRC_SEC :
+ if (m[i].s) {
+ indent(fp, in);
+ fprintf(fp, "if (");
+ printeq(fp, "fin->fin_fi.fi_secmsk",
+ fr->fr_secmask, 0xffff,
+ fr->fr_secbits);
+ in++;
+ }
+ break;
+ case FRC_ATH :
+ if (m[i].s) {
+ indent(fp, in);
+ fprintf(fp, "if (");
+ printeq(fp, "fin->fin_fi.fi_authmsk",
+ fr->fr_authmask, 0xffff,
+ fr->fr_authbits);
+ in++;
+ }
+ break;
+ case FRC_ICT :
+ if (m[i].s) {
+ indent(fp, in);
+ fprintf(fp, "if (");
+ printeq(fp, "fin->fin_data[0]",
+ fr->fr_icmpm & 0xff00, 0xffff,
+ fr->fr_icmp & 0xff00);
+ in++;
+ }
+ break;
+ case FRC_ICC :
+ if (m[i].s) {
+ indent(fp, in);
+ fprintf(fp, "if (");
+ printeq(fp, "fin->fin_data[0]",
+ fr->fr_icmpm & 0xff, 0xffff,
+ fr->fr_icmp & 0xff);
+ in++;
+ }
+ break;
+ }
+
+ }
+
+ indent(fp, in);
+ if (fr->fr_flags & FR_QUICK) {
+ fprintf(fp, "return (frentry_t *)&%s_rule_%s_%d;\n",
+ fr->fr_flags & FR_INQUE ? "in" : "out",
+ fr->fr_group, num);
+ } else {
+ fprintf(fp, "fr = (frentry_t *)&%s_rule_%s_%d;\n",
+ fr->fr_flags & FR_INQUE ? "in" : "out",
+ fr->fr_group, num);
+ }
+ if (n == NULL)
+ n = (mc_t *)malloc(sizeof(*n) * FRC_MAX);
+ bcopy((char *)m, (char *)n, sizeof(*n) * FRC_MAX);
+ sin = in;
+}
+
+
+void printC(dir)
+int dir;
+{
+ static mc_t *m = NULL;
+ frgroup_t *g;
+
+ if (m == NULL)
+ m = (mc_t *)calloc(1, sizeof(*m) * FRC_MAX);
+
+ for (g = groups; g != NULL; g = g->fg_next) {
+ if ((dir == 0) && ((g->fg_flags & FR_INQUE) != 0))
+ printCgroup(dir, g->fg_start, m, g->fg_name);
+ if ((dir == 1) && ((g->fg_flags & FR_OUTQUE) != 0))
+ printCgroup(dir, g->fg_start, m, g->fg_name);
+ }
+
+ emit(-1, dir, m, NULL);
+}
+
+
+/*
+ * Now print out code to implement all of the rules.
+ */
+static void printCgroup(dir, top, m, group)
+int dir;
+frentry_t *top;
+mc_t *m;
+char *group;
+{
+ frentry_t *fr, *fr1;
+ int i, n, rn;
+ u_int count;
+
+ for (count = 0, fr1 = top; fr1 != NULL; fr1 = fr1->fr_next) {
+ if ((dir == 0) && ((fr1->fr_flags & FR_INQUE) != 0))
+ count++;
+ else if ((dir == 1) && ((fr1->fr_flags & FR_OUTQUE) != 0))
+ count++;
+ }
+
+ if (dir == 0)
+ emitGroup(-2, dir, m, fr1, group, count, 0);
+ else if (dir == 1)
+ emitGroup(-2, dir, m, fr1, group, 0, count);
+
+ /*
+ * Before printing each rule, check to see how many of its fields are
+ * matched by subsequent rules.
+ */
+ for (fr1 = top, rn = 0; fr1 != NULL; fr1 = fr1->fr_next, rn++) {
+ if (!dir && !(fr1->fr_flags & FR_INQUE))
+ continue;
+ if (dir && !(fr1->fr_flags & FR_OUTQUE))
+ continue;
+ n = 0xfffffff;
+
+ for (i = 0; i < FRC_MAX; i++)
+ m[i].e = 0;
+ qsort(m, FRC_MAX, sizeof(mc_t), intcmp);
+
+ for (i = 0; i < FRC_MAX; i++) {
+ m[i].c = i;
+ m[i].e = 0;
+ m[i].n = 0;
+ m[i].s = 0;
+ }
+
+ for (fr = fr1->fr_next; fr; fr = fr->fr_next) {
+ if (!dir && !(fr->fr_flags & FR_INQUE))
+ continue;
+ if (dir && !(fr->fr_flags & FR_OUTQUE))
+ continue;
+
+ if ((n & 0x0001) &&
+ !strcmp(fr1->fr_ifname, fr->fr_ifname)) {
+ m[FRC_IFN].e++;
+ m[FRC_IFN].n++;
+ } else
+ n &= ~0x0001;
+
+ if ((n & 0x0002) && (fr1->fr_v == fr->fr_v)) {
+ m[FRC_V].e++;
+ m[FRC_V].n++;
+ } else
+ n &= ~0x0002;
+
+ if ((n & 0x0004) &&
+ (fr->fr_type == fr1->fr_type) &&
+ (fr->fr_type == FR_T_IPF) &&
+ (fr1->fr_mip.fi_flx == fr->fr_mip.fi_flx) &&
+ (fr1->fr_ip.fi_flx == fr->fr_ip.fi_flx)) {
+ m[FRC_FL].e++;
+ m[FRC_FL].n++;
+ } else
+ n &= ~0x0004;
+
+ if ((n & 0x0008) &&
+ (fr->fr_type == fr1->fr_type) &&
+ (fr->fr_type == FR_T_IPF) &&
+ (fr1->fr_proto == fr->fr_proto)) {
+ m[FRC_P].e++;
+ m[FRC_P].n++;
+ } else
+ n &= ~0x0008;
+
+ if ((n & 0x0010) &&
+ (fr->fr_type == fr1->fr_type) &&
+ (fr->fr_type == FR_T_IPF) &&
+ (fr1->fr_ttl == fr->fr_ttl)) {
+ m[FRC_TTL].e++;
+ m[FRC_TTL].n++;
+ } else
+ n &= ~0x0010;
+
+ if ((n & 0x0020) &&
+ (fr->fr_type == fr1->fr_type) &&
+ (fr->fr_type == FR_T_IPF) &&
+ (fr1->fr_tos == fr->fr_tos)) {
+ m[FRC_TOS].e++;
+ m[FRC_TOS].n++;
+ } else
+ n &= ~0x0020;
+
+ if ((n & 0x0040) &&
+ (fr->fr_type == fr1->fr_type) &&
+ (fr->fr_type == FR_T_IPF) &&
+ ((fr1->fr_tcpfm == fr->fr_tcpfm) &&
+ (fr1->fr_tcpf == fr->fr_tcpf))) {
+ m[FRC_TCP].e++;
+ m[FRC_TCP].n++;
+ } else
+ n &= ~0x0040;
+
+ if ((n & 0x0080) &&
+ (fr->fr_type == fr1->fr_type) &&
+ (fr->fr_type == FR_T_IPF) &&
+ ((fr1->fr_scmp == fr->fr_scmp) &&
+ (fr1->fr_stop == fr->fr_stop) &&
+ (fr1->fr_sport == fr->fr_sport))) {
+ m[FRC_SP].e++;
+ m[FRC_SP].n++;
+ } else
+ n &= ~0x0080;
+
+ if ((n & 0x0100) &&
+ (fr->fr_type == fr1->fr_type) &&
+ (fr->fr_type == FR_T_IPF) &&
+ ((fr1->fr_dcmp == fr->fr_dcmp) &&
+ (fr1->fr_dtop == fr->fr_dtop) &&
+ (fr1->fr_dport == fr->fr_dport))) {
+ m[FRC_DP].e++;
+ m[FRC_DP].n++;
+ } else
+ n &= ~0x0100;
+
+ if ((n & 0x0200) &&
+ (fr->fr_type == fr1->fr_type) &&
+ (fr->fr_type == FR_T_IPF) &&
+ ((fr1->fr_satype == FRI_LOOKUP) &&
+ (fr->fr_satype == FRI_LOOKUP) &&
+ (fr1->fr_srcnum == fr->fr_srcnum))) {
+ m[FRC_SRC].e++;
+ m[FRC_SRC].n++;
+ } else if ((n & 0x0200) &&
+ (fr->fr_type == fr1->fr_type) &&
+ (fr->fr_type == FR_T_IPF) &&
+ (((fr1->fr_flags & FR_NOTSRCIP) ==
+ (fr->fr_flags & FR_NOTSRCIP)))) {
+ if ((fr1->fr_smask == fr->fr_smask) &&
+ (fr1->fr_saddr == fr->fr_saddr))
+ m[FRC_SRC].e++;
+ else
+ n &= ~0x0200;
+ if (fr1->fr_smask &&
+ (fr1->fr_saddr & fr1->fr_smask) ==
+ (fr->fr_saddr & fr1->fr_smask)) {
+ m[FRC_SRC].n++;
+ n |= 0x0200;
+ }
+ } else {
+ n &= ~0x0200;
+ }
+
+ if ((n & 0x0400) &&
+ (fr->fr_type == fr1->fr_type) &&
+ (fr->fr_type == FR_T_IPF) &&
+ ((fr1->fr_datype == FRI_LOOKUP) &&
+ (fr->fr_datype == FRI_LOOKUP) &&
+ (fr1->fr_dstnum == fr->fr_dstnum))) {
+ m[FRC_DST].e++;
+ m[FRC_DST].n++;
+ } else if ((n & 0x0400) &&
+ (fr->fr_type == fr1->fr_type) &&
+ (fr->fr_type == FR_T_IPF) &&
+ (((fr1->fr_flags & FR_NOTDSTIP) ==
+ (fr->fr_flags & FR_NOTDSTIP)))) {
+ if ((fr1->fr_dmask == fr->fr_dmask) &&
+ (fr1->fr_daddr == fr->fr_daddr))
+ m[FRC_DST].e++;
+ else
+ n &= ~0x0400;
+ if (fr1->fr_dmask &&
+ (fr1->fr_daddr & fr1->fr_dmask) ==
+ (fr->fr_daddr & fr1->fr_dmask)) {
+ m[FRC_DST].n++;
+ n |= 0x0400;
+ }
+ } else {
+ n &= ~0x0400;
+ }
+
+ if ((n & 0x0800) &&
+ (fr->fr_type == fr1->fr_type) &&
+ (fr->fr_type == FR_T_IPF) &&
+ (fr1->fr_optmask == fr->fr_optmask) &&
+ (fr1->fr_optbits == fr->fr_optbits)) {
+ m[FRC_OPT].e++;
+ m[FRC_OPT].n++;
+ } else
+ n &= ~0x0800;
+
+ if ((n & 0x1000) &&
+ (fr->fr_type == fr1->fr_type) &&
+ (fr->fr_type == FR_T_IPF) &&
+ (fr1->fr_secmask == fr->fr_secmask) &&
+ (fr1->fr_secbits == fr->fr_secbits)) {
+ m[FRC_SEC].e++;
+ m[FRC_SEC].n++;
+ } else
+ n &= ~0x1000;
+
+ if ((n & 0x10000) &&
+ (fr->fr_type == fr1->fr_type) &&
+ (fr->fr_type == FR_T_IPF) &&
+ (fr1->fr_authmask == fr->fr_authmask) &&
+ (fr1->fr_authbits == fr->fr_authbits)) {
+ m[FRC_ATH].e++;
+ m[FRC_ATH].n++;
+ } else
+ n &= ~0x10000;
+
+ if ((n & 0x20000) &&
+ (fr->fr_type == fr1->fr_type) &&
+ (fr->fr_type == FR_T_IPF) &&
+ ((fr1->fr_icmpm & 0xff00) ==
+ (fr->fr_icmpm & 0xff00)) &&
+ ((fr1->fr_icmp & 0xff00) ==
+ (fr->fr_icmp & 0xff00))) {
+ m[FRC_ICT].e++;
+ m[FRC_ICT].n++;
+ } else
+ n &= ~0x20000;
+
+ if ((n & 0x40000) &&
+ (fr->fr_type == fr1->fr_type) &&
+ (fr->fr_type == FR_T_IPF) &&
+ ((fr1->fr_icmpm & 0xff) == (fr->fr_icmpm & 0xff)) &&
+ ((fr1->fr_icmp & 0xff) == (fr->fr_icmp & 0xff))) {
+ m[FRC_ICC].e++;
+ m[FRC_ICC].n++;
+ } else
+ n &= ~0x40000;
+ }
+ /*msort(m);*/
+
+ if (dir == 0)
+ emitGroup(rn, dir, m, fr1, group, count, 0);
+ else if (dir == 1)
+ emitGroup(rn, dir, m, fr1, group, 0, count);
+ }
+}
+
+static void printhooks(fp, in, out, grp)
+FILE *fp;
+int in;
+int out;
+frgroup_t *grp;
+{
+ frentry_t *fr;
+ char *group;
+ int dogrp, i;
+ char *instr;
+
+ group = grp->fg_name;
+ dogrp = 0;
+
+ if (in && out) {
+ fprintf(stderr,
+ "printhooks called with both in and out set\n");
+ exit(1);
+ }
+
+ if (in) {
+ instr = "in";
+ } else if (out) {
+ instr = "out";
+ } else {
+ instr = "???";
+ }
+ fprintf(fp, "static frentry_t ipfrule_%s_%s;\n", instr, group);
+
+ fprintf(fp, "\
+\n\
+int ipfrule_add_%s_%s()\n", instr, group);
+ fprintf(fp, "\
+{\n\
+ int i, j, err = 0, max;\n\
+ frentry_t *fp;\n");
+
+ if (dogrp)
+ fprintf(fp, "\
+ frgroup_t *fg;\n");
+
+ fprintf(fp, "\n");
+
+ for (i = 0, fr = grp->fg_start; fr != NULL; i++, fr = fr->fr_next)
+ if (fr->fr_dsize > 0) {
+ fprintf(fp, "\
+ ipf_rules_%s_%s[%d]->fr_data = &ipf%s_rule_data_%s_%u;\n",
+ instr, grp->fg_name, i,
+ instr, grp->fg_name, i);
+ }
+ fprintf(fp, "\
+ max = sizeof(ipf_rules_%s_%s)/sizeof(frentry_t *);\n\
+ for (i = 0; i < max; i++) {\n\
+ fp = ipf_rules_%s_%s[i];\n\
+ fp->fr_next = NULL;\n", instr, group, instr, group);
+
+ fprintf(fp, "\
+ for (j = i + 1; j < max; j++)\n\
+ if (strncmp(fp->fr_group,\n\
+ ipf_rules_%s_%s[j]->fr_group,\n\
+ FR_GROUPLEN) == 0) {\n\
+ fp->fr_next = ipf_rules_%s_%s[j];\n\
+ break;\n\
+ }\n", instr, group, instr, group);
+ if (dogrp)
+ fprintf(fp, "\
+\n\
+ if (fp->fr_grhead != 0) {\n\
+ fg = fr_addgroup(fp->fr_grhead, fp, FR_INQUE,\n\
+ IPL_LOGIPF, 0);\n\
+ if (fg != NULL)\n\
+ fp->fr_grp = &fg->fg_start;\n\
+ }\n");
+ fprintf(fp, "\
+ }\n\
+\n\
+ fp = &ipfrule_%s_%s;\n", instr, group);
+ fprintf(fp, "\
+ bzero((char *)fp, sizeof(*fp));\n\
+ fp->fr_type = FR_T_CALLFUNC|FR_T_BUILTIN;\n\
+ fp->fr_flags = FR_%sQUE|FR_NOMATCH;\n\
+ fp->fr_data = (void *)ipf_rules_%s_%s[0];\n",
+ (in != 0) ? "IN" : "OUT", instr, group);
+ fprintf(fp, "\
+ fp->fr_dsize = sizeof(ipf_rules_%s_%s[0]);\n",
+ instr, group);
+
+ fprintf(fp, "\
+ fp->fr_v = 4;\n\
+ fp->fr_func = (ipfunc_t)ipfrule_match_%s_%s;\n\
+ err = frrequest(IPL_LOGIPF, SIOCADDFR, (caddr_t)fp, fr_active, 0);\n",
+ instr, group);
+ fprintf(fp, "\treturn err;\n}\n");
+
+ fprintf(fp, "\n\n\
+int ipfrule_remove_%s_%s()\n", instr, group);
+ fprintf(fp, "\
+{\n\
+ int err = 0, i;\n\
+ frentry_t *fp;\n\
+\n\
+ /*\n\
+ * Try to remove the %sbound rule.\n", instr);
+
+ fprintf(fp, "\
+ */\n\
+ if (ipfrule_%s_%s.fr_ref > 0) {\n", instr, group);
+
+ fprintf(fp, "\
+ err = EBUSY;\n\
+ } else {\n");
+
+ fprintf(fp, "\
+ i = sizeof(ipf_rules_%s_%s)/sizeof(frentry_t *) - 1;\n\
+ for (; i >= 0; i--) {\n\
+ fp = ipf_rules_%s_%s[i];\n\
+ if (fp->fr_ref > 1) {\n\
+ err = EBUSY;\n\
+ break;\n\
+ }\n\
+ }\n\
+ }\n\
+ if (err == 0)\n\
+ err = frrequest(IPL_LOGIPF, SIOCDELFR,\n\
+ (caddr_t)&ipfrule_%s_%s, fr_active, 0);\n",
+ instr, group, instr, group, instr, group);
+ fprintf(fp, "\
+ if (err)\n\
+ return err;\n\
+\n\n");
+
+ fprintf(fp, "\treturn err;\n}\n");
+}
diff --git a/contrib/ipfilter/tools/ipfs.c b/contrib/ipfilter/tools/ipfs.c
new file mode 100644
index 0000000..49e7e52
--- /dev/null
+++ b/contrib/ipfilter/tools/ipfs.c
@@ -0,0 +1,855 @@
+/* $NetBSD$ */
+
+/*
+ * Copyright (C) 1999-2001, 2003 by Darren Reed.
+ *
+ * See the IPFILTER.LICENCE file for details on licencing.
+ */
+#ifdef __FreeBSD__
+# ifndef __FreeBSD_cc_version
+# include <osreldate.h>
+# else
+# if __FreeBSD_cc_version < 430000
+# include <osreldate.h>
+# endif
+# endif
+#endif
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <fcntl.h>
+#include <errno.h>
+#if !defined(__SVR4) && !defined(__GNUC__)
+#include <strings.h>
+#endif
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/file.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <sys/time.h>
+#include <net/if.h>
+#if __FreeBSD_version >= 300000
+# include <net/if_var.h>
+#endif
+#include <netinet/ip.h>
+#include <netdb.h>
+#include <arpa/nameser.h>
+#include <resolv.h>
+#include "ipf.h"
+#include "ipl.h"
+
+#if !defined(lint)
+static const char rcsid[] = "@(#)Id: ipfs.c,v 1.12 2003/12/01 01:56:53 darrenr Exp";
+#endif
+
+#ifndef IPF_SAVEDIR
+# define IPF_SAVEDIR "/var/db/ipf"
+#endif
+#ifndef IPF_NATFILE
+# define IPF_NATFILE "ipnat.ipf"
+#endif
+#ifndef IPF_STATEFILE
+# define IPF_STATEFILE "ipstate.ipf"
+#endif
+
+#if !defined(__SVR4) && defined(__GNUC__)
+extern char *index __P((const char *, int));
+#endif
+
+extern char *optarg;
+extern int optind;
+
+int main __P((int, char *[]));
+void usage __P((void));
+int changestateif __P((char *, char *));
+int changenatif __P((char *, char *));
+int readstate __P((int, char *));
+int readnat __P((int, char *));
+int writestate __P((int, char *));
+int opendevice __P((char *));
+void closedevice __P((int));
+int setlock __P((int, int));
+int writeall __P((char *));
+int readall __P((char *));
+int writenat __P((int, char *));
+
+int opts = 0;
+char *progname;
+
+
+void usage()
+{
+ fprintf(stderr, "usage: %s [-nv] -l\n", progname);
+ fprintf(stderr, "usage: %s [-nv] -u\n", progname);
+ fprintf(stderr, "usage: %s [-nv] [-d <dir>] -R\n", progname);
+ fprintf(stderr, "usage: %s [-nv] [-d <dir>] -W\n", progname);
+ fprintf(stderr, "usage: %s [-nNSv] [-f <file>] -r\n", progname);
+ fprintf(stderr, "usage: %s [-nNSv] [-f <file>] -w\n", progname);
+ fprintf(stderr, "usage: %s [-nNSv] -f <filename> -i <if1>,<if2>\n",
+ progname);
+ exit(1);
+}
+
+
+/*
+ * Change interface names in state information saved out to disk.
+ */
+int changestateif(ifs, fname)
+char *ifs, *fname;
+{
+ int fd, olen, nlen, rw;
+ ipstate_save_t ips;
+ off_t pos;
+ char *s;
+
+ s = strchr(ifs, ',');
+ if (!s)
+ usage();
+ *s++ = '\0';
+ nlen = strlen(s);
+ olen = strlen(ifs);
+ if (nlen >= sizeof(ips.ips_is.is_ifname) ||
+ olen >= sizeof(ips.ips_is.is_ifname))
+ usage();
+
+ fd = open(fname, O_RDWR);
+ if (fd == -1) {
+ perror("open");
+ exit(1);
+ }
+
+ for (pos = 0; read(fd, &ips, sizeof(ips)) == sizeof(ips); ) {
+ rw = 0;
+ if (!strncmp(ips.ips_is.is_ifname[0], ifs, olen + 1)) {
+ strcpy(ips.ips_is.is_ifname[0], s);
+ rw = 1;
+ }
+ if (!strncmp(ips.ips_is.is_ifname[1], ifs, olen + 1)) {
+ strcpy(ips.ips_is.is_ifname[1], s);
+ rw = 1;
+ }
+ if (rw == 1) {
+ if (lseek(fd, pos, SEEK_SET) != pos) {
+ perror("lseek");
+ exit(1);
+ }
+ if (write(fd, &ips, sizeof(ips)) != sizeof(ips)) {
+ perror("write");
+ exit(1);
+ }
+ }
+ pos = lseek(fd, 0, SEEK_CUR);
+ }
+ close(fd);
+
+ return 0;
+}
+
+
+/*
+ * Change interface names in NAT information saved out to disk.
+ */
+int changenatif(ifs, fname)
+char *ifs, *fname;
+{
+ int fd, olen, nlen, rw;
+ nat_save_t ipn;
+ nat_t *nat;
+ off_t pos;
+ char *s;
+
+ s = strchr(ifs, ',');
+ if (!s)
+ usage();
+ *s++ = '\0';
+ nlen = strlen(s);
+ olen = strlen(ifs);
+ nat = &ipn.ipn_nat;
+ if (nlen >= sizeof(nat->nat_ifnames[0]) ||
+ olen >= sizeof(nat->nat_ifnames[0]))
+ usage();
+
+ fd = open(fname, O_RDWR);
+ if (fd == -1) {
+ perror("open");
+ exit(1);
+ }
+
+ for (pos = 0; read(fd, &ipn, sizeof(ipn)) == sizeof(ipn); ) {
+ rw = 0;
+ if (!strncmp(nat->nat_ifnames[0], ifs, olen + 1)) {
+ strcpy(nat->nat_ifnames[0], s);
+ rw = 1;
+ }
+ if (!strncmp(nat->nat_ifnames[1], ifs, olen + 1)) {
+ strcpy(nat->nat_ifnames[1], s);
+ rw = 1;
+ }
+ if (rw == 1) {
+ if (lseek(fd, pos, SEEK_SET) != pos) {
+ perror("lseek");
+ exit(1);
+ }
+ if (write(fd, &ipn, sizeof(ipn)) != sizeof(ipn)) {
+ perror("write");
+ exit(1);
+ }
+ }
+ pos = lseek(fd, 0, SEEK_CUR);
+ }
+ close(fd);
+
+ return 0;
+}
+
+
+int main(argc,argv)
+int argc;
+char *argv[];
+{
+ int c, lock = -1, devfd = -1, err = 0, rw = -1, ns = -1, set = 0;
+ char *dirname = NULL, *filename = NULL, *ifs = NULL;
+
+ progname = argv[0];
+ while ((c = getopt(argc, argv, "d:f:lNnSRruvWw")) != -1)
+ switch (c)
+ {
+ case 'd' :
+ if ((set == 0) && !dirname && !filename)
+ dirname = optarg;
+ else
+ usage();
+ break;
+ case 'f' :
+ if ((set != 0) && !dirname && !filename)
+ filename = optarg;
+ else
+ usage();
+ break;
+ case 'i' :
+ ifs = optarg;
+ set = 1;
+ break;
+ case 'l' :
+ if (filename || dirname || set)
+ usage();
+ lock = 1;
+ set = 1;
+ break;
+ case 'n' :
+ opts |= OPT_DONOTHING;
+ break;
+ case 'N' :
+ if ((ns >= 0) || dirname || (rw != -1) || set)
+ usage();
+ ns = 0;
+ set = 1;
+ break;
+ case 'r' :
+ if (dirname || (rw != -1) || (ns == -1))
+ usage();
+ rw = 0;
+ set = 1;
+ break;
+ case 'R' :
+ rw = 2;
+ set = 1;
+ break;
+ case 'S' :
+ if ((ns >= 0) || dirname || (rw != -1) || set)
+ usage();
+ ns = 1;
+ set = 1;
+ break;
+ case 'u' :
+ if (filename || dirname || set)
+ usage();
+ lock = 0;
+ set = 1;
+ break;
+ case 'v' :
+ opts |= OPT_VERBOSE;
+ break;
+ case 'w' :
+ if (dirname || (rw != -1) || (ns == -1))
+ usage();
+ rw = 1;
+ set = 1;
+ break;
+ case 'W' :
+ rw = 3;
+ set = 1;
+ break;
+ case '?' :
+ default :
+ usage();
+ }
+
+ if (ifs) {
+ if (!filename || ns < 0)
+ usage();
+ if (ns == 0)
+ return changenatif(ifs, filename);
+ else
+ return changestateif(ifs, filename);
+ }
+
+ if ((ns >= 0) || (lock >= 0)) {
+ if (lock >= 0)
+ devfd = opendevice(NULL);
+ else if (ns >= 0) {
+ if (ns == 1)
+ devfd = opendevice(IPSTATE_NAME);
+ else if (ns == 0)
+ devfd = opendevice(IPNAT_NAME);
+ }
+ if (devfd == -1)
+ exit(1);
+ }
+
+ if (lock >= 0)
+ err = setlock(devfd, lock);
+ else if (rw >= 0) {
+ if (rw & 1) { /* WRITE */
+ if (rw & 2)
+ err = writeall(dirname);
+ else {
+ if (ns == 0)
+ err = writenat(devfd, filename);
+ else if (ns == 1)
+ err = writestate(devfd, filename);
+ }
+ } else {
+ if (rw & 2)
+ err = readall(dirname);
+ else {
+ if (ns == 0)
+ err = readnat(devfd, filename);
+ else if (ns == 1)
+ err = readstate(devfd, filename);
+ }
+ }
+ }
+ return err;
+}
+
+
+int opendevice(ipfdev)
+char *ipfdev;
+{
+ int fd = -1;
+
+ if (opts & OPT_DONOTHING)
+ return -2;
+
+ if (!ipfdev)
+ ipfdev = IPL_NAME;
+
+ if ((fd = open(ipfdev, O_RDWR)) == -1)
+ if ((fd = open(ipfdev, O_RDONLY)) == -1)
+ perror("open device");
+ return fd;
+}
+
+
+void closedevice(fd)
+int fd;
+{
+ close(fd);
+}
+
+
+int setlock(fd, lock)
+int fd, lock;
+{
+ if (opts & OPT_VERBOSE)
+ printf("Turn lock %s\n", lock ? "on" : "off");
+ if (!(opts & OPT_DONOTHING)) {
+ if (ioctl(fd, SIOCSTLCK, &lock) == -1) {
+ perror("SIOCSTLCK");
+ return 1;
+ }
+ if (opts & OPT_VERBOSE)
+ printf("Lock now %s\n", lock ? "on" : "off");
+ }
+ return 0;
+}
+
+
+int writestate(fd, file)
+int fd;
+char *file;
+{
+ ipstate_save_t ips, *ipsp;
+ ipfobj_t obj;
+ int wfd = -1;
+
+ if (!file)
+ file = IPF_STATEFILE;
+
+ wfd = open(file, O_WRONLY|O_TRUNC|O_CREAT, 0600);
+ if (wfd == -1) {
+ fprintf(stderr, "%s ", file);
+ perror("state:open");
+ return 1;
+ }
+
+ ipsp = &ips;
+ bzero((char *)&obj, sizeof(obj));
+ bzero((char *)ipsp, sizeof(ips));
+
+ obj.ipfo_rev = IPFILTER_VERSION;
+ obj.ipfo_size = sizeof(*ipsp);
+ obj.ipfo_type = IPFOBJ_STATESAVE;
+ obj.ipfo_ptr = ipsp;
+
+ do {
+
+ if (opts & OPT_VERBOSE)
+ printf("Getting state from addr %p\n", ips.ips_next);
+ if (ioctl(fd, SIOCSTGET, &obj)) {
+ if (errno == ENOENT)
+ break;
+ perror("state:SIOCSTGET");
+ close(wfd);
+ return 1;
+ }
+ if (opts & OPT_VERBOSE)
+ printf("Got state next %p\n", ips.ips_next);
+ if (write(wfd, ipsp, sizeof(ips)) != sizeof(ips)) {
+ perror("state:write");
+ close(wfd);
+ return 1;
+ }
+ } while (ips.ips_next != NULL);
+ close(wfd);
+
+ return 0;
+}
+
+
+int readstate(fd, file)
+int fd;
+char *file;
+{
+ ipstate_save_t ips, *is, *ipshead = NULL, *is1, *ipstail = NULL;
+ int sfd = -1, i;
+ ipfobj_t obj;
+
+ if (!file)
+ file = IPF_STATEFILE;
+
+ sfd = open(file, O_RDONLY, 0600);
+ if (sfd == -1) {
+ fprintf(stderr, "%s ", file);
+ perror("open");
+ return 1;
+ }
+
+ bzero((char *)&ips, sizeof(ips));
+
+ /*
+ * 1. Read all state information in.
+ */
+ do {
+ i = read(sfd, &ips, sizeof(ips));
+ if (i == -1) {
+ perror("read");
+ close(sfd);
+ return 1;
+ }
+ if (i == 0)
+ break;
+ if (i != sizeof(ips)) {
+ fprintf(stderr, "state:incomplete read: %d != %d\n",
+ i, (int)sizeof(ips));
+ close(sfd);
+ return 1;
+ }
+ is = (ipstate_save_t *)malloc(sizeof(*is));
+ if(!is) {
+ fprintf(stderr, "malloc failed\n");
+ return 1;
+ }
+
+ bcopy((char *)&ips, (char *)is, sizeof(ips));
+
+ /*
+ * Check to see if this is the first state entry that will
+ * reference a particular rule and if so, flag it as such
+ * else just adjust the rule pointer to become a pointer to
+ * the other. We do this so we have a means later for tracking
+ * who is referencing us when we get back the real pointer
+ * in is_rule after doing the ioctl.
+ */
+ for (is1 = ipshead; is1 != NULL; is1 = is1->ips_next)
+ if (is1->ips_rule == is->ips_rule)
+ break;
+ if (is1 == NULL)
+ is->ips_is.is_flags |= SI_NEWFR;
+ else
+ is->ips_rule = (void *)&is1->ips_rule;
+
+ /*
+ * Use a tail-queue type list (add things to the end)..
+ */
+ is->ips_next = NULL;
+ if (!ipshead)
+ ipshead = is;
+ if (ipstail)
+ ipstail->ips_next = is;
+ ipstail = is;
+ } while (1);
+
+ close(sfd);
+
+ obj.ipfo_rev = IPFILTER_VERSION;
+ obj.ipfo_size = sizeof(*is);
+ obj.ipfo_type = IPFOBJ_STATESAVE;
+
+ for (is = ipshead; is; is = is->ips_next) {
+ if (opts & OPT_VERBOSE)
+ printf("Loading new state table entry\n");
+ if (is->ips_is.is_flags & SI_NEWFR) {
+ if (opts & OPT_VERBOSE)
+ printf("Loading new filter rule\n");
+ }
+
+ obj.ipfo_ptr = is;
+ if (!(opts & OPT_DONOTHING))
+ if (ioctl(fd, SIOCSTPUT, &obj)) {
+ perror("SIOCSTPUT");
+ return 1;
+ }
+
+ if (is->ips_is.is_flags & SI_NEWFR) {
+ if (opts & OPT_VERBOSE)
+ printf("Real rule addr %p\n", is->ips_rule);
+ for (is1 = is->ips_next; is1; is1 = is1->ips_next)
+ if (is1->ips_rule == (frentry_t *)&is->ips_rule)
+ is1->ips_rule = is->ips_rule;
+ }
+ }
+
+ return 0;
+}
+
+
+int readnat(fd, file)
+int fd;
+char *file;
+{
+ nat_save_t ipn, *in, *ipnhead = NULL, *in1, *ipntail = NULL;
+ ipfobj_t obj;
+ int nfd, i;
+ nat_t *nat;
+ char *s;
+ int n;
+
+ nfd = -1;
+ in = NULL;
+ ipnhead = NULL;
+ ipntail = NULL;
+
+ if (!file)
+ file = IPF_NATFILE;
+
+ nfd = open(file, O_RDONLY);
+ if (nfd == -1) {
+ fprintf(stderr, "%s ", file);
+ perror("nat:open");
+ return 1;
+ }
+
+ bzero((char *)&ipn, sizeof(ipn));
+
+ /*
+ * 1. Read all state information in.
+ */
+ do {
+ i = read(nfd, &ipn, sizeof(ipn));
+ if (i == -1) {
+ perror("read");
+ close(nfd);
+ return 1;
+ }
+ if (i == 0)
+ break;
+ if (i != sizeof(ipn)) {
+ fprintf(stderr, "nat:incomplete read: %d != %d\n",
+ i, (int)sizeof(ipn));
+ close(nfd);
+ return 1;
+ }
+
+ in = (nat_save_t *)malloc(ipn.ipn_dsize);
+ if (!in)
+ break;
+
+ if (ipn.ipn_dsize > sizeof(ipn)) {
+ n = ipn.ipn_dsize - sizeof(ipn);
+ if (n > 0) {
+ s = in->ipn_data + sizeof(in->ipn_data);
+ i = read(nfd, s, n);
+ if (i == 0)
+ break;
+ if (i != n) {
+ fprintf(stderr,
+ "nat:incomplete read: %d != %d\n",
+ i, n);
+ close(nfd);
+ return 1;
+ }
+ }
+ }
+ bcopy((char *)&ipn, (char *)in, sizeof(ipn));
+
+ /*
+ * Check to see if this is the first NAT entry that will
+ * reference a particular rule and if so, flag it as such
+ * else just adjust the rule pointer to become a pointer to
+ * the other. We do this so we have a means later for tracking
+ * who is referencing us when we get back the real pointer
+ * in is_rule after doing the ioctl.
+ */
+ nat = &in->ipn_nat;
+ if (nat->nat_fr != NULL) {
+ for (in1 = ipnhead; in1 != NULL; in1 = in1->ipn_next)
+ if (in1->ipn_rule == nat->nat_fr)
+ break;
+ if (in1 == NULL)
+ nat->nat_flags |= SI_NEWFR;
+ else
+ nat->nat_fr = &in1->ipn_fr;
+ }
+
+ /*
+ * Use a tail-queue type list (add things to the end)..
+ */
+ in->ipn_next = NULL;
+ if (!ipnhead)
+ ipnhead = in;
+ if (ipntail)
+ ipntail->ipn_next = in;
+ ipntail = in;
+ } while (1);
+
+ close(nfd);
+ nfd = -1;
+
+ obj.ipfo_rev = IPFILTER_VERSION;
+ obj.ipfo_type = IPFOBJ_NATSAVE;
+
+ for (in = ipnhead; in; in = in->ipn_next) {
+ if (opts & OPT_VERBOSE)
+ printf("Loading new NAT table entry\n");
+ nat = &in->ipn_nat;
+ if (nat->nat_flags & SI_NEWFR) {
+ if (opts & OPT_VERBOSE)
+ printf("Loading new filter rule\n");
+ }
+
+ obj.ipfo_ptr = in;
+ obj.ipfo_size = in->ipn_dsize;
+ if (!(opts & OPT_DONOTHING))
+ if (ioctl(fd, SIOCSTPUT, &obj)) {
+ fprintf(stderr, "in=%p:", in);
+ perror("SIOCSTPUT");
+ return 1;
+ }
+
+ if (nat->nat_flags & SI_NEWFR) {
+ if (opts & OPT_VERBOSE)
+ printf("Real rule addr %p\n", nat->nat_fr);
+ for (in1 = in->ipn_next; in1; in1 = in1->ipn_next)
+ if (in1->ipn_rule == &in->ipn_fr)
+ in1->ipn_rule = nat->nat_fr;
+ }
+ }
+
+ return 0;
+}
+
+
+int writenat(fd, file)
+int fd;
+char *file;
+{
+ nat_save_t *ipnp = NULL, *next = NULL;
+ ipfobj_t obj;
+ int nfd = -1;
+ natget_t ng;
+
+ if (!file)
+ file = IPF_NATFILE;
+
+ nfd = open(file, O_WRONLY|O_TRUNC|O_CREAT, 0600);
+ if (nfd == -1) {
+ fprintf(stderr, "%s ", file);
+ perror("nat:open");
+ return 1;
+ }
+
+ obj.ipfo_rev = IPFILTER_VERSION;
+ obj.ipfo_type = IPFOBJ_NATSAVE;
+
+ do {
+ if (opts & OPT_VERBOSE)
+ printf("Getting nat from addr %p\n", ipnp);
+ ng.ng_ptr = next;
+ ng.ng_sz = 0;
+ if (ioctl(fd, SIOCSTGSZ, &ng)) {
+ perror("nat:SIOCSTGSZ");
+ close(nfd);
+ if (ipnp != NULL)
+ free(ipnp);
+ return 1;
+ }
+
+ if (opts & OPT_VERBOSE)
+ printf("NAT size %d from %p\n", ng.ng_sz, ng.ng_ptr);
+
+ if (ng.ng_sz == 0)
+ break;
+
+ if (!ipnp)
+ ipnp = malloc(ng.ng_sz);
+ else
+ ipnp = realloc((char *)ipnp, ng.ng_sz);
+ if (!ipnp) {
+ fprintf(stderr,
+ "malloc for %d bytes failed\n", ng.ng_sz);
+ break;
+ }
+
+ bzero((char *)ipnp, ng.ng_sz);
+ obj.ipfo_size = ng.ng_sz;
+ obj.ipfo_ptr = ipnp;
+ ipnp->ipn_dsize = ng.ng_sz;
+ ipnp->ipn_next = next;
+ if (ioctl(fd, SIOCSTGET, &obj)) {
+ if (errno == ENOENT)
+ break;
+ perror("nat:SIOCSTGET");
+ close(nfd);
+ free(ipnp);
+ return 1;
+ }
+
+ if (opts & OPT_VERBOSE)
+ printf("Got nat next %p ipn_dsize %d ng_sz %d\n",
+ ipnp->ipn_next, ipnp->ipn_dsize, ng.ng_sz);
+ if (write(nfd, ipnp, ipnp->ipn_dsize) != ipnp->ipn_dsize) {
+ perror("nat:write");
+ close(nfd);
+ free(ipnp);
+ return 1;
+ }
+ next = ipnp->ipn_next;
+ } while (ipnp && next);
+ if (ipnp != NULL)
+ free(ipnp);
+ close(nfd);
+
+ return 0;
+}
+
+
+int writeall(dirname)
+char *dirname;
+{
+ int fd, devfd;
+
+ if (!dirname)
+ dirname = IPF_SAVEDIR;
+
+ if (chdir(dirname)) {
+ fprintf(stderr, "IPF_SAVEDIR=%s: ", dirname);
+ perror("chdir(IPF_SAVEDIR)");
+ return 1;
+ }
+
+ fd = opendevice(NULL);
+ if (fd == -1)
+ return 1;
+ if (setlock(fd, 1)) {
+ close(fd);
+ return 1;
+ }
+
+ devfd = opendevice(IPSTATE_NAME);
+ if (devfd == -1)
+ goto bad;
+ if (writestate(devfd, NULL))
+ goto bad;
+ close(devfd);
+
+ devfd = opendevice(IPNAT_NAME);
+ if (devfd == -1)
+ goto bad;
+ if (writenat(devfd, NULL))
+ goto bad;
+ close(devfd);
+
+ if (setlock(fd, 0)) {
+ close(fd);
+ return 1;
+ }
+
+ close(fd);
+ return 0;
+
+bad:
+ setlock(fd, 0);
+ close(fd);
+ return 1;
+}
+
+
+int readall(dirname)
+char *dirname;
+{
+ int fd, devfd;
+
+ if (!dirname)
+ dirname = IPF_SAVEDIR;
+
+ if (chdir(dirname)) {
+ perror("chdir(IPF_SAVEDIR)");
+ return 1;
+ }
+
+ fd = opendevice(NULL);
+ if (fd == -1)
+ return 1;
+ if (setlock(fd, 1)) {
+ close(fd);
+ return 1;
+ }
+
+ devfd = opendevice(IPSTATE_NAME);
+ if (devfd == -1)
+ return 1;
+ if (readstate(devfd, NULL))
+ return 1;
+ close(devfd);
+
+ devfd = opendevice(IPNAT_NAME);
+ if (devfd == -1)
+ return 1;
+ if (readnat(devfd, NULL))
+ return 1;
+ close(devfd);
+
+ if (setlock(fd, 0)) {
+ close(fd);
+ return 1;
+ }
+
+ return 0;
+}
diff --git a/contrib/ipfilter/tools/ipfstat.c b/contrib/ipfilter/tools/ipfstat.c
new file mode 100644
index 0000000..fbd6c35
--- /dev/null
+++ b/contrib/ipfilter/tools/ipfstat.c
@@ -0,0 +1,1792 @@
+/* $NetBSD$ */
+
+/*
+ * Copyright (C) 1993-2001, 2003 by Darren Reed.
+ *
+ * See the IPFILTER.LICENCE file for details on licencing.
+ */
+#ifdef __FreeBSD__
+# ifndef __FreeBSD_cc_version
+# include <osreldate.h>
+# else
+# if __FreeBSD_cc_version < 430000
+# include <osreldate.h>
+# endif
+# endif
+#endif
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#ifdef linux
+# include <linux/a.out.h>
+#else
+# include <nlist.h>
+#endif
+#include <ctype.h>
+#if defined(sun) && (defined(__svr4__) || defined(__SVR4))
+# include <stddef.h>
+#endif
+#include "ipf.h"
+#include "netinet/ipl.h"
+#if defined(STATETOP)
+# if defined(_BSDI_VERSION)
+# undef STATETOP
+# endif
+# if defined(__FreeBSD__) && \
+ (!defined(__FreeBSD_version) || (__FreeBSD_version < 430000))
+# undef STATETOP
+# endif
+# if defined(__NetBSD_Version__) && (__NetBSD_Version__ < 105000000)
+# undef STATETOP
+# endif
+# if defined(sun)
+# if defined(__svr4__) || defined(__SVR4)
+# include <sys/select.h>
+# else
+# undef STATETOP /* NOT supported on SunOS4 */
+# endif
+# endif
+#endif
+#if defined(STATETOP) && !defined(linux)
+# include <netinet/ip_var.h>
+# include <netinet/tcp_fsm.h>
+#endif
+#ifdef STATETOP
+# include <ctype.h>
+# include <signal.h>
+# if SOLARIS || defined(__NetBSD__) || defined(_BSDI_VERSION) || \
+ defined(__sgi)
+# ifdef ERR
+# undef ERR
+# endif
+# include <curses.h>
+# else /* SOLARIS */
+# include <ncurses.h>
+# endif /* SOLARIS */
+#endif /* STATETOP */
+#include "kmem.h"
+#if defined(__NetBSD__) || (__OpenBSD__)
+# include <paths.h>
+#endif
+
+#if !defined(lint)
+static const char sccsid[] = "@(#)fils.c 1.21 4/20/96 (C) 1993-2000 Darren Reed";
+static const char rcsid[] = "@(#)Id: ipfstat.c,v 1.44.2.11 2005/03/30 14:09:57 darrenr Exp";
+#endif
+
+#ifdef __hpux
+# define nlist nlist64
+#endif
+
+extern char *optarg;
+extern int optind;
+extern int opterr;
+
+#define PRINTF (void)printf
+#define FPRINTF (void)fprintf
+#define F_IN 0
+#define F_OUT 1
+#define F_ACIN 2
+#define F_ACOUT 3
+static char *filters[4] = { "ipfilter(in)", "ipfilter(out)",
+ "ipacct(in)", "ipacct(out)" };
+static int state_logging = -1;
+
+int opts = 0;
+int use_inet6 = 0;
+int live_kernel = 1;
+int state_fd = -1;
+int ipf_fd = -1;
+
+#ifdef STATETOP
+#define STSTRSIZE 80
+#define STGROWSIZE 16
+#define HOSTNMLEN 40
+
+#define STSORT_PR 0
+#define STSORT_PKTS 1
+#define STSORT_BYTES 2
+#define STSORT_TTL 3
+#define STSORT_SRCIP 4
+#define STSORT_SRCPT 5
+#define STSORT_DSTIP 6
+#define STSORT_DSTPT 7
+#define STSORT_MAX STSORT_DSTPT
+#define STSORT_DEFAULT STSORT_BYTES
+
+
+typedef struct statetop {
+ i6addr_t st_src;
+ i6addr_t st_dst;
+ u_short st_sport;
+ u_short st_dport;
+ u_char st_p;
+ u_char st_v;
+ u_char st_state[2];
+ U_QUAD_T st_pkts;
+ U_QUAD_T st_bytes;
+ u_long st_age;
+} statetop_t;
+#endif
+
+int main __P((int, char *[]));
+
+static void showstats __P((friostat_t *, u_32_t));
+static void showfrstates __P((ipfrstat_t *));
+static void showlist __P((friostat_t *));
+static void showipstates __P((ips_stat_t *));
+static void showauthstates __P((fr_authstat_t *));
+static void showgroups __P((friostat_t *));
+static void usage __P((char *));
+static void printlist __P((frentry_t *, char *));
+static void parse_ipportstr __P((const char *, i6addr_t *, int *));
+static void ipfstate_live __P((char *, friostat_t **, ips_stat_t **,
+ ipfrstat_t **, fr_authstat_t **, u_32_t *));
+static void ipfstate_dead __P((char *, friostat_t **, ips_stat_t **,
+ ipfrstat_t **, fr_authstat_t **, u_32_t *));
+#ifdef STATETOP
+static void topipstates __P((i6addr_t, i6addr_t, int, int, int,
+ int, int, int));
+static void sig_break __P((int));
+static void sig_resize __P((int));
+static char *getip __P((int, i6addr_t *));
+static char *ttl_to_string __P((long));
+static int sort_p __P((const void *, const void *));
+static int sort_pkts __P((const void *, const void *));
+static int sort_bytes __P((const void *, const void *));
+static int sort_ttl __P((const void *, const void *));
+static int sort_srcip __P((const void *, const void *));
+static int sort_srcpt __P((const void *, const void *));
+static int sort_dstip __P((const void *, const void *));
+static int sort_dstpt __P((const void *, const void *));
+#endif
+
+
+static void usage(name)
+char *name;
+{
+#ifdef USE_INET6
+ fprintf(stderr, "Usage: %s [-6aAdfghIilnoRsv]\n", name);
+#else
+ fprintf(stderr, "Usage: %s [-aAdfghIilnoRsv]\n", name);
+#endif
+ fprintf(stderr, " %s [-M corefile] [-N symbol-list]\n", name);
+#ifdef USE_INET6
+ fprintf(stderr, " %s -t [-6C] ", name);
+#else
+ fprintf(stderr, " %s -t [-C] ", name);
+#endif
+ fprintf(stderr, "[-D destination address] [-P protocol] [-S source address] [-T refresh time]\n");
+ exit(1);
+}
+
+
+int main(argc,argv)
+int argc;
+char *argv[];
+{
+ fr_authstat_t frauthst;
+ fr_authstat_t *frauthstp = &frauthst;
+ friostat_t fio;
+ friostat_t *fiop = &fio;
+ ips_stat_t ipsst;
+ ips_stat_t *ipsstp = &ipsst;
+ ipfrstat_t ifrst;
+ ipfrstat_t *ifrstp = &ifrst;
+ char *device = IPL_NAME, *memf = NULL;
+ char *options, *kern = NULL;
+ int c, myoptind;
+
+ int protocol = -1; /* -1 = wild card for any protocol */
+ int refreshtime = 1; /* default update time */
+ int sport = -1; /* -1 = wild card for any source port */
+ int dport = -1; /* -1 = wild card for any dest port */
+ int topclosed = 0; /* do not show closed tcp sessions */
+ i6addr_t saddr, daddr;
+ u_32_t frf;
+
+#ifdef USE_INET6
+ options = "6aACdfghIilnostvD:M:N:P:RS:T:";
+#else
+ options = "aACdfghIilnostvD:M:N:P:RS:T:";
+#endif
+
+ saddr.in4.s_addr = INADDR_ANY; /* default any v4 source addr */
+ daddr.in4.s_addr = INADDR_ANY; /* default any v4 dest addr */
+#ifdef USE_INET6
+ saddr.in6 = in6addr_any; /* default any v6 source addr */
+ daddr.in6 = in6addr_any; /* default any v6 dest addr */
+#endif
+
+ /* Don't warn about invalid flags when we run getopt for the 1st time */
+ opterr = 0;
+
+ /*
+ * Parse these two arguments now lest there be any buffer overflows
+ * in the parsing of the rest.
+ */
+ myoptind = optind;
+ while ((c = getopt(argc, argv, options)) != -1) {
+ switch (c)
+ {
+ case 'M' :
+ memf = optarg;
+ live_kernel = 0;
+ break;
+ case 'N' :
+ kern = optarg;
+ live_kernel = 0;
+ break;
+ }
+ }
+ optind = myoptind;
+
+ if (live_kernel == 1) {
+ if ((state_fd = open(IPSTATE_NAME, O_RDONLY)) == -1) {
+ perror("open(IPSTATE_NAME)");
+ exit(-1);
+ }
+ if ((ipf_fd = open(device, O_RDONLY)) == -1) {
+ fprintf(stderr, "open(%s)", device);
+ perror("");
+ exit(-1);
+ }
+ }
+
+ if (kern != NULL || memf != NULL) {
+ (void)setgid(getgid());
+ (void)setuid(getuid());
+ }
+
+ if (live_kernel == 1)
+ (void) checkrev(device);
+ if (openkmem(kern, memf) == -1)
+ exit(-1);
+
+ (void)setgid(getgid());
+ (void)setuid(getuid());
+
+ opterr = 1;
+
+ while ((c = getopt(argc, argv, options)) != -1)
+ {
+ switch (c)
+ {
+#ifdef USE_INET6
+ case '6' :
+ use_inet6 = 1;
+ break;
+#endif
+ case 'a' :
+ opts |= OPT_ACCNT|OPT_SHOWLIST;
+ break;
+ case 'A' :
+ opts |= OPT_AUTHSTATS;
+ break;
+ case 'C' :
+ topclosed = 1;
+ break;
+ case 'd' :
+ opts |= OPT_DEBUG;
+ break;
+ case 'D' :
+ parse_ipportstr(optarg, &daddr, &dport);
+ break;
+ case 'f' :
+ opts |= OPT_FRSTATES;
+ break;
+ case 'g' :
+ opts |= OPT_GROUPS;
+ break;
+ case 'h' :
+ opts |= OPT_HITS;
+ break;
+ case 'i' :
+ opts |= OPT_INQUE|OPT_SHOWLIST;
+ break;
+ case 'I' :
+ opts |= OPT_INACTIVE;
+ break;
+ case 'l' :
+ opts |= OPT_SHOWLIST;
+ break;
+ case 'M' :
+ break;
+ case 'N' :
+ break;
+ case 'n' :
+ opts |= OPT_SHOWLINENO;
+ break;
+ case 'o' :
+ opts |= OPT_OUTQUE|OPT_SHOWLIST;
+ break;
+ case 'P' :
+ protocol = getproto(optarg);
+ if (protocol == -1) {
+ fprintf(stderr, "%s: Invalid protocol: %s\n",
+ argv[0], optarg);
+ exit(-2);
+ }
+ break;
+ case 'R' :
+ opts |= OPT_NORESOLVE;
+ break;
+ case 's' :
+ opts |= OPT_IPSTATES;
+ break;
+ case 'S' :
+ parse_ipportstr(optarg, &saddr, &sport);
+ break;
+ case 't' :
+#ifdef STATETOP
+ opts |= OPT_STATETOP;
+ break;
+#else
+ fprintf(stderr,
+ "%s: state top facility not compiled in\n",
+ argv[0]);
+ exit(-2);
+#endif
+ case 'T' :
+ if (!sscanf(optarg, "%d", &refreshtime) ||
+ (refreshtime <= 0)) {
+ fprintf(stderr,
+ "%s: Invalid refreshtime < 1 : %s\n",
+ argv[0], optarg);
+ exit(-2);
+ }
+ break;
+ case 'v' :
+ opts |= OPT_VERBOSE;
+ break;
+ default :
+ usage(argv[0]);
+ break;
+ }
+ }
+
+ if (live_kernel == 1) {
+ bzero((char *)&fio, sizeof(fio));
+ bzero((char *)&ipsst, sizeof(ipsst));
+ bzero((char *)&ifrst, sizeof(ifrst));
+
+ ipfstate_live(device, &fiop, &ipsstp, &ifrstp,
+ &frauthstp, &frf);
+ } else
+ ipfstate_dead(kern, &fiop, &ipsstp, &ifrstp, &frauthstp, &frf);
+
+ if (opts & OPT_IPSTATES) {
+ showipstates(ipsstp);
+ } else if (opts & OPT_SHOWLIST) {
+ showlist(fiop);
+ if ((opts & OPT_OUTQUE) && (opts & OPT_INQUE)){
+ opts &= ~OPT_OUTQUE;
+ showlist(fiop);
+ }
+ } else if (opts & OPT_FRSTATES)
+ showfrstates(ifrstp);
+#ifdef STATETOP
+ else if (opts & OPT_STATETOP)
+ topipstates(saddr, daddr, sport, dport, protocol,
+ use_inet6 ? 6 : 4, refreshtime, topclosed);
+#endif
+ else if (opts & OPT_AUTHSTATS)
+ showauthstates(frauthstp);
+ else if (opts & OPT_GROUPS)
+ showgroups(fiop);
+ else
+ showstats(fiop, frf);
+
+ return 0;
+}
+
+
+/*
+ * Fill in the stats structures from the live kernel, using a combination
+ * of ioctl's and copying directly from kernel memory.
+ */
+static void ipfstate_live(device, fiopp, ipsstpp, ifrstpp, frauthstpp, frfp)
+char *device;
+friostat_t **fiopp;
+ips_stat_t **ipsstpp;
+ipfrstat_t **ifrstpp;
+fr_authstat_t **frauthstpp;
+u_32_t *frfp;
+{
+ ipfobj_t ipfo;
+
+ if (checkrev(device) == -1) {
+ fprintf(stderr, "User/kernel version check failed\n");
+ exit(1);
+ }
+
+ if ((opts & OPT_AUTHSTATS) == 0) {
+ bzero((caddr_t)&ipfo, sizeof(ipfo));
+ ipfo.ipfo_rev = IPFILTER_VERSION;
+ ipfo.ipfo_size = sizeof(friostat_t);
+ ipfo.ipfo_ptr = (void *)*fiopp;
+ ipfo.ipfo_type = IPFOBJ_IPFSTAT;
+
+ if (ioctl(ipf_fd, SIOCGETFS, &ipfo) == -1) {
+ perror("ioctl(ipf:SIOCGETFS)");
+ exit(-1);
+ }
+
+ if (ioctl(ipf_fd, SIOCGETFF, frfp) == -1)
+ perror("ioctl(SIOCGETFF)");
+ }
+
+ if ((opts & OPT_IPSTATES) != 0) {
+
+ bzero((caddr_t)&ipfo, sizeof(ipfo));
+ ipfo.ipfo_rev = IPFILTER_VERSION;
+ ipfo.ipfo_size = sizeof(ips_stat_t);
+ ipfo.ipfo_ptr = (void *)*ipsstpp;
+ ipfo.ipfo_type = IPFOBJ_STATESTAT;
+
+ if ((ioctl(state_fd, SIOCGETFS, &ipfo) == -1)) {
+ perror("ioctl(state:SIOCGETFS)");
+ exit(-1);
+ }
+ if (ioctl(state_fd, SIOCGETLG, &state_logging) == -1) {
+ perror("ioctl(state:SIOCGETLG)");
+ exit(-1);
+ }
+ }
+
+ if ((opts & OPT_FRSTATES) != 0) {
+ bzero((caddr_t)&ipfo, sizeof(ipfo));
+ ipfo.ipfo_rev = IPFILTER_VERSION;
+ ipfo.ipfo_size = sizeof(ipfrstat_t);
+ ipfo.ipfo_ptr = (void *)*ifrstpp;
+ ipfo.ipfo_type = IPFOBJ_FRAGSTAT;
+
+ if (ioctl(ipf_fd, SIOCGFRST, &ipfo) == -1) {
+ perror("ioctl(SIOCGFRST)");
+ exit(-1);
+ }
+ }
+
+ if (opts & OPT_VERBOSE)
+ PRINTF("opts %#x name %s\n", opts, device);
+
+ if ((opts & OPT_AUTHSTATS) != 0) {
+ if (ipf_fd >= 0) {
+ close(ipf_fd);
+ ipf_fd = -1;
+ }
+ device = IPAUTH_NAME;
+ if ((ipf_fd = open(device, O_RDONLY)) == -1) {
+ perror("open");
+ exit(-1);
+ }
+
+ bzero((caddr_t)&ipfo, sizeof(ipfo));
+ ipfo.ipfo_rev = IPFILTER_VERSION;
+ ipfo.ipfo_size = sizeof(fr_authstat_t);
+ ipfo.ipfo_ptr = (void *)*frauthstpp;
+ ipfo.ipfo_type = IPFOBJ_AUTHSTAT;
+
+ if (ioctl(ipf_fd, SIOCATHST, &ipfo) == -1) {
+ perror("ioctl(SIOCATHST)");
+ exit(-1);
+ }
+ }
+}
+
+
+/*
+ * Build up the stats structures from data held in the "core" memory.
+ * This is mainly useful when looking at data in crash dumps and ioctl's
+ * just won't work any more.
+ */
+static void ipfstate_dead(kernel, fiopp, ipsstpp, ifrstpp, frauthstpp, frfp)
+char *kernel;
+friostat_t **fiopp;
+ips_stat_t **ipsstpp;
+ipfrstat_t **ifrstpp;
+fr_authstat_t **frauthstpp;
+u_32_t *frfp;
+{
+ static fr_authstat_t frauthst, *frauthstp;
+ static ips_stat_t ipsst, *ipsstp;
+ static ipfrstat_t ifrst, *ifrstp;
+ static friostat_t fio, *fiop;
+ int temp;
+
+ void *rules[2][2];
+ struct nlist deadlist[43] = {
+ { "fr_authstats" }, /* 0 */
+ { "fae_list" },
+ { "ipauth" },
+ { "fr_authlist" },
+ { "fr_authstart" },
+ { "fr_authend" }, /* 5 */
+ { "fr_authnext" },
+ { "fr_auth" },
+ { "fr_authused" },
+ { "fr_authsize" },
+ { "fr_defaultauthage" }, /* 10 */
+ { "fr_authpkts" },
+ { "fr_auth_lock" },
+ { "frstats" },
+ { "ips_stats" },
+ { "ips_num" }, /* 15 */
+ { "ips_wild" },
+ { "ips_list" },
+ { "ips_table" },
+ { "fr_statemax" },
+ { "fr_statesize" }, /* 20 */
+ { "fr_state_doflush" },
+ { "fr_state_lock" },
+ { "ipfr_heads" },
+ { "ipfr_nattab" },
+ { "ipfr_stats" }, /* 25 */
+ { "ipfr_inuse" },
+ { "fr_ipfrttl" },
+ { "fr_frag_lock" },
+ { "ipfr_timer_id" },
+ { "fr_nat_lock" }, /* 30 */
+ { "ipfilter" },
+ { "ipfilter6" },
+ { "ipacct" },
+ { "ipacct6" },
+ { "ipl_frouteok" }, /* 35 */
+ { "fr_running" },
+ { "ipfgroups" },
+ { "fr_active" },
+ { "fr_pass" },
+ { "fr_flags" }, /* 40 */
+ { "ipstate_logging" },
+ { NULL }
+ };
+
+
+ frauthstp = &frauthst;
+ ipsstp = &ipsst;
+ ifrstp = &ifrst;
+ fiop = &fio;
+
+ *frfp = 0;
+ *fiopp = fiop;
+ *ipsstpp = ipsstp;
+ *ifrstpp = ifrstp;
+ *frauthstpp = frauthstp;
+
+ bzero((char *)fiop, sizeof(*fiop));
+ bzero((char *)ipsstp, sizeof(*ipsstp));
+ bzero((char *)ifrstp, sizeof(*ifrstp));
+ bzero((char *)frauthstp, sizeof(*frauthstp));
+
+ if (nlist(kernel, deadlist) == -1) {
+ fprintf(stderr, "nlist error\n");
+ return;
+ }
+
+ /*
+ * This is for SIOCGETFF.
+ */
+ kmemcpy((char *)frfp, (u_long)deadlist[40].n_value, sizeof(*frfp));
+
+ /*
+ * f_locks is a combination of the lock variable from each part of
+ * ipfilter (state, auth, nat, fragments).
+ */
+ kmemcpy((char *)fiop, (u_long)deadlist[13].n_value, sizeof(*fiop));
+ kmemcpy((char *)&fiop->f_locks[0], (u_long)deadlist[22].n_value,
+ sizeof(fiop->f_locks[0]));
+ kmemcpy((char *)&fiop->f_locks[0], (u_long)deadlist[30].n_value,
+ sizeof(fiop->f_locks[1]));
+ kmemcpy((char *)&fiop->f_locks[2], (u_long)deadlist[28].n_value,
+ sizeof(fiop->f_locks[2]));
+ kmemcpy((char *)&fiop->f_locks[3], (u_long)deadlist[12].n_value,
+ sizeof(fiop->f_locks[3]));
+
+ /*
+ * Get pointers to each list of rules (active, inactive, in, out)
+ */
+ kmemcpy((char *)&rules, (u_long)deadlist[31].n_value, sizeof(rules));
+ fiop->f_fin[0] = rules[0][0];
+ fiop->f_fin[1] = rules[0][1];
+ fiop->f_fout[0] = rules[1][0];
+ fiop->f_fout[1] = rules[1][1];
+
+ /*
+ * Same for IPv6, except make them null if support for it is not
+ * being compiled in.
+ */
+#ifdef USE_INET6
+ kmemcpy((char *)&rules, (u_long)deadlist[32].n_value, sizeof(rules));
+ fiop->f_fin6[0] = rules[0][0];
+ fiop->f_fin6[1] = rules[0][1];
+ fiop->f_fout6[0] = rules[1][0];
+ fiop->f_fout6[1] = rules[1][1];
+#else
+ fiop->f_fin6[0] = NULL;
+ fiop->f_fin6[1] = NULL;
+ fiop->f_fout6[0] = NULL;
+ fiop->f_fout6[1] = NULL;
+#endif
+
+ /*
+ * Now get accounting rules pointers.
+ */
+ kmemcpy((char *)&rules, (u_long)deadlist[33].n_value, sizeof(rules));
+ fiop->f_acctin[0] = rules[0][0];
+ fiop->f_acctin[1] = rules[0][1];
+ fiop->f_acctout[0] = rules[1][0];
+ fiop->f_acctout[1] = rules[1][1];
+
+#ifdef USE_INET6
+ kmemcpy((char *)&rules, (u_long)deadlist[34].n_value, sizeof(rules));
+ fiop->f_acctin6[0] = rules[0][0];
+ fiop->f_acctin6[1] = rules[0][1];
+ fiop->f_acctout6[0] = rules[1][0];
+ fiop->f_acctout6[1] = rules[1][1];
+#else
+ fiop->f_acctin6[0] = NULL;
+ fiop->f_acctin6[1] = NULL;
+ fiop->f_acctout6[0] = NULL;
+ fiop->f_acctout6[1] = NULL;
+#endif
+
+ /*
+ * A collection of "global" variables used inside the kernel which
+ * are all collected in friostat_t via ioctl.
+ */
+ kmemcpy((char *)&fiop->f_froute, (u_long)deadlist[35].n_value,
+ sizeof(fiop->f_froute));
+ kmemcpy((char *)&fiop->f_running, (u_long)deadlist[36].n_value,
+ sizeof(fiop->f_running));
+ kmemcpy((char *)&fiop->f_groups, (u_long)deadlist[37].n_value,
+ sizeof(fiop->f_groups));
+ kmemcpy((char *)&fiop->f_active, (u_long)deadlist[38].n_value,
+ sizeof(fiop->f_active));
+ kmemcpy((char *)&fiop->f_defpass, (u_long)deadlist[39].n_value,
+ sizeof(fiop->f_defpass));
+
+ /*
+ * Build up the state information stats structure.
+ */
+ kmemcpy((char *)ipsstp, (u_long)deadlist[14].n_value, sizeof(*ipsstp));
+ kmemcpy((char *)&temp, (u_long)deadlist[15].n_value, sizeof(temp));
+ ipsstp->iss_active = temp;
+ ipsstp->iss_table = (void *)deadlist[18].n_value;
+ ipsstp->iss_list = (void *)deadlist[17].n_value;
+
+ /*
+ * Build up the authentiation information stats structure.
+ */
+ kmemcpy((char *)frauthstp, (u_long)deadlist[0].n_value,
+ sizeof(*frauthstp));
+ frauthstp->fas_faelist = (void *)deadlist[1].n_value;
+
+ /*
+ * Build up the fragment information stats structure.
+ */
+ kmemcpy((char *)ifrstp, (u_long)deadlist[25].n_value,
+ sizeof(*ifrstp));
+ ifrstp->ifs_table = (void *)deadlist[23].n_value;
+ ifrstp->ifs_nattab = (void *)deadlist[24].n_value;
+ kmemcpy((char *)&ifrstp->ifs_inuse, (u_long)deadlist[26].n_value,
+ sizeof(ifrstp->ifs_inuse));
+
+ /*
+ * Get logging on/off switches
+ */
+ kmemcpy((char *)&state_logging, (u_long)deadlist[41].n_value,
+ sizeof(state_logging));
+}
+
+
+/*
+ * Display the kernel stats for packets blocked and passed and other
+ * associated running totals which are kept.
+ */
+static void showstats(fp, frf)
+struct friostat *fp;
+u_32_t frf;
+{
+
+ PRINTF("bad packets:\t\tin %lu\tout %lu\n",
+ fp->f_st[0].fr_bad, fp->f_st[1].fr_bad);
+#ifdef USE_INET6
+ PRINTF(" IPv6 packets:\t\tin %lu out %lu\n",
+ fp->f_st[0].fr_ipv6, fp->f_st[1].fr_ipv6);
+#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 short %lu\n",
+ fp->f_st[0].fr_acct, fp->f_st[0].fr_short);
+ 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 short %lu\n",
+ fp->f_st[1].fr_acct, fp->f_st[1].fr_short);
+ 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\tnot fragmented %lu\n",
+ fp->f_st[0].fr_nfr, fp->f_st[0].fr_bnfr,
+ fp->f_st[0].fr_cfr);
+ PRINTF("fragment state(out):\tkept %lu\tlost %lu\tnot fragmented %lu\n",
+ fp->f_st[1].fr_nfr, fp->f_st[1].fr_bnfr,
+ fp->f_st[0].fr_cfr);
+ 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("Invalid source(in):\t%lu\n", fp->f_st[0].fr_badsrc);
+ 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("Fastroute successes:\t%lu\tfailures:\t%lu\n",
+ fp->f_froute[0], fp->f_froute[1]);
+ PRINTF("TCP cksum fails(in):\t%lu\t(out):\t%lu\n",
+ fp->f_st[0].fr_tcpbad, fp->f_st[1].fr_tcpbad);
+ PRINTF("IPF Ticks:\t%lu\n", fp->f_ticks);
+
+ 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 & FF_LOGNOMATCH)
+ PRINTF("\tpackets not matched by filter\n");
+ if (!frf)
+ PRINTF("\tnone\n");
+}
+
+
+/*
+ * Print out a list of rules from the kernel, starting at the one passed.
+ */
+static void printlist(fp, comment)
+frentry_t *fp;
+char *comment;
+{
+ struct frentry fb, *fg;
+ char *data;
+ u_32_t type;
+ int n;
+
+ for (n = 1; fp; n++) {
+ if (kmemcpy((char *)&fb, (u_long)fp, sizeof(fb)) == -1) {
+ perror("kmemcpy");
+ return;
+ }
+ fp = &fb;
+ if (opts & (OPT_HITS|OPT_VERBOSE))
+#ifdef USE_QUAD_T
+ PRINTF("%qu ", (unsigned long long) fp->fr_hits);
+#else
+ PRINTF("%lu ", fp->fr_hits);
+#endif
+ if (opts & (OPT_ACCNT|OPT_VERBOSE))
+#ifdef USE_QUAD_T
+ PRINTF("%qu ", (unsigned long long) fp->fr_bytes);
+#else
+ PRINTF("%lu ", fp->fr_bytes);
+#endif
+ if (opts & OPT_SHOWLINENO)
+ PRINTF("@%d ", n);
+ data = NULL;
+ type = fp->fr_type & ~FR_T_BUILTIN;
+ if (type == FR_T_IPF || type == FR_T_BPFOPC) {
+ if (fp->fr_dsize) {
+ data = malloc(fp->fr_dsize);
+
+ if (kmemcpy(data, (u_long)fp->fr_data,
+ fp->fr_dsize) == -1) {
+ perror("kmemcpy");
+ return;
+ }
+ fp->fr_data = data;
+ }
+ }
+
+ printfr(fp, ioctl);
+ if (opts & OPT_DEBUG) {
+ binprint(fp, sizeof(*fp));
+ if (fp->fr_data != NULL && fp->fr_dsize > 0)
+ binprint(fp->fr_data, fp->fr_dsize);
+ }
+ if (data != NULL)
+ free(data);
+ if (fp->fr_grp != NULL) {
+ if (!kmemcpy((char *)&fg, (u_long)fp->fr_grp,
+ sizeof(fg)))
+ printlist(fg, comment);
+ }
+ if (type == FR_T_CALLFUNC) {
+ printlist(fp->fr_data, "# callfunc: ");
+ }
+ fp = fp->fr_next;
+ }
+}
+
+/*
+ * print out all of the asked for rule sets, using the stats struct as
+ * the base from which to get the pointers.
+ */
+static void showlist(fiop)
+struct friostat *fiop;
+{
+ struct frentry *fp = NULL;
+ int i, set;
+
+ set = fiop->f_active;
+ if (opts & OPT_INACTIVE)
+ set = 1 - set;
+ if (opts & OPT_ACCNT) {
+#ifdef USE_INET6
+ if ((use_inet6) && (opts & OPT_OUTQUE)) {
+ i = F_ACOUT;
+ fp = (struct frentry *)fiop->f_acctout6[set];
+ } else if ((use_inet6) && (opts & OPT_INQUE)) {
+ i = F_ACIN;
+ fp = (struct frentry *)fiop->f_acctin6[set];
+ } else
+#endif
+ if (opts & OPT_OUTQUE) {
+ i = F_ACOUT;
+ fp = (struct frentry *)fiop->f_acctout[set];
+ } else if (opts & OPT_INQUE) {
+ i = F_ACIN;
+ fp = (struct frentry *)fiop->f_acctin[set];
+ } else {
+ FPRINTF(stderr, "No -i or -o given with -a\n");
+ return;
+ }
+ } else {
+#ifdef USE_INET6
+ if ((use_inet6) && (opts & OPT_OUTQUE)) {
+ i = F_OUT;
+ fp = (struct frentry *)fiop->f_fout6[set];
+ } else if ((use_inet6) && (opts & OPT_INQUE)) {
+ i = F_IN;
+ fp = (struct frentry *)fiop->f_fin6[set];
+ } else
+#endif
+ 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 %p set %d\n", fp, set);
+ if (!fp) {
+ FPRINTF(stderr, "empty list for %s%s\n",
+ (opts & OPT_INACTIVE) ? "inactive " : "", filters[i]);
+ return;
+ }
+ printlist(fp, NULL);
+}
+
+
+/*
+ * Display ipfilter stateful filtering information
+ */
+static void showipstates(ipsp)
+ips_stat_t *ipsp;
+{
+ u_long minlen, maxlen, totallen, *buckets;
+ int i, sz;
+
+ sz = sizeof(*buckets) * ipsp->iss_statesize;
+ buckets = (u_long *)malloc(sz);
+ if (kmemcpy((char *)buckets, (u_long)ipsp->iss_bucketlen, sz)) {
+ free(buckets);
+ return;
+ }
+
+ /*
+ * If a list of states hasn't been asked for, only print out stats
+ */
+ if (!(opts & OPT_SHOWLIST)) {
+ 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\t%lu max bucket\n",
+ ipsp->iss_max, ipsp->iss_nomem, ipsp->iss_bucketfull);
+ PRINTF("\t%lu maximum\n\t%lu no memory\n\t%lu bkts in use\n",
+ ipsp->iss_max, ipsp->iss_nomem, ipsp->iss_inuse);
+ PRINTF("\t%lu active\n\t%lu expired\n\t%lu closed\n",
+ ipsp->iss_active, ipsp->iss_expire, ipsp->iss_fin);
+
+ PRINTF("State logging %sabled\n",
+ state_logging ? "en" : "dis");
+
+ PRINTF("\nState table bucket statistics:\n");
+ PRINTF("\t%lu in use\t\n", ipsp->iss_inuse);
+
+ minlen = ipsp->iss_max;
+ totallen = 0;
+ maxlen = 0;
+
+ for (i = 0; i < ipsp->iss_statesize; i++) {
+ if (buckets[i] > maxlen)
+ maxlen = buckets[i];
+ if (buckets[i] < minlen)
+ minlen = buckets[i];
+ totallen += buckets[i];
+ }
+
+ PRINTF("\t%2.2f%% bucket usage\n\t%lu minimal length\n",
+ ((float)ipsp->iss_inuse / ipsp->iss_statesize) * 100.0,
+ minlen);
+ PRINTF("\t%lu maximal length\n\t%.3f average length\n",
+ maxlen,
+ ipsp->iss_inuse ? (float) totallen/ ipsp->iss_inuse :
+ 0.0);
+
+#define ENTRIES_PER_LINE 5
+
+ if (opts & OPT_VERBOSE) {
+ PRINTF("\nCurrent bucket sizes :\n");
+ for (i = 0; i < ipsp->iss_statesize; i++) {
+ if ((i % ENTRIES_PER_LINE) == 0)
+ PRINTF("\t");
+ PRINTF("%4d -> %4lu", i, buckets[i]);
+ if ((i % ENTRIES_PER_LINE) ==
+ (ENTRIES_PER_LINE - 1))
+ PRINTF("\n");
+ else
+ PRINTF(" ");
+ }
+ PRINTF("\n");
+ }
+ PRINTF("\n");
+
+ free(buckets);
+ return;
+ }
+
+ /*
+ * Print out all the state information currently held in the kernel.
+ */
+ while (ipsp->iss_list != NULL) {
+ ipsp->iss_list = printstate(ipsp->iss_list, opts,
+ ipsp->iss_ticks);
+ }
+
+ free(buckets);
+}
+
+
+#ifdef STATETOP
+static int handle_resize = 0, handle_break = 0;
+
+static void topipstates(saddr, daddr, sport, dport, protocol, ver,
+ refreshtime, topclosed)
+i6addr_t saddr;
+i6addr_t daddr;
+int sport;
+int dport;
+int protocol;
+int ver;
+int refreshtime;
+int topclosed;
+{
+ char str1[STSTRSIZE], str2[STSTRSIZE], str3[STSTRSIZE], str4[STSTRSIZE];
+ int maxtsentries = 0, reverse = 0, sorting = STSORT_DEFAULT;
+ int i, j, winy, tsentry, maxx, maxy, redraw = 0;
+ int len, srclen, dstlen, forward = 1, c = 0;
+ ips_stat_t ipsst, *ipsstp = &ipsst;
+ statetop_t *tstable = NULL, *tp;
+ ipstate_t ips;
+ ipfobj_t ipfo;
+ struct timeval selecttimeout;
+ char hostnm[HOSTNMLEN];
+ struct protoent *proto;
+ fd_set readfd;
+ time_t t;
+
+ /* install signal handlers */
+ signal(SIGINT, sig_break);
+ signal(SIGQUIT, sig_break);
+ signal(SIGTERM, sig_break);
+ signal(SIGWINCH, sig_resize);
+
+ /* init ncurses stuff */
+ initscr();
+ cbreak();
+ noecho();
+ curs_set(0);
+ timeout(0);
+ getmaxyx(stdscr, maxy, maxx);
+
+ /* init hostname */
+ gethostname(hostnm, sizeof(hostnm) - 1);
+ hostnm[sizeof(hostnm) - 1] = '\0';
+
+ /* init ipfobj_t stuff */
+ bzero((caddr_t)&ipfo, sizeof(ipfo));
+ ipfo.ipfo_rev = IPFILTER_VERSION;
+ ipfo.ipfo_size = sizeof(*ipsstp);
+ ipfo.ipfo_ptr = (void *)ipsstp;
+ ipfo.ipfo_type = IPFOBJ_STATESTAT;
+
+ /* repeat until user aborts */
+ while ( 1 ) {
+
+ /* get state table */
+ bzero((char *)&ipsst, sizeof(ipsst));
+ if ((ioctl(state_fd, SIOCGETFS, &ipfo) == -1)) {
+ perror("ioctl(SIOCGETFS)");
+ exit(-1);
+ }
+
+ /* clear the history */
+ tsentry = -1;
+
+ /* reset max str len */
+ srclen = dstlen = 0;
+
+ /* read the state table and store in tstable */
+ for (; ipsstp->iss_list; ipsstp->iss_list = ips.is_next) {
+
+ if (kmemcpy((char *)&ips, (u_long)ipsstp->iss_list,
+ sizeof(ips)))
+ break;
+
+ if (ips.is_v != ver)
+ continue;
+
+ /* check v4 src/dest addresses */
+ if (ips.is_v == 4) {
+ if ((saddr.in4.s_addr != INADDR_ANY &&
+ saddr.in4.s_addr != ips.is_saddr) ||
+ (daddr.in4.s_addr != INADDR_ANY &&
+ daddr.in4.s_addr != ips.is_daddr))
+ continue;
+ }
+#ifdef USE_INET6
+ /* check v6 src/dest addresses */
+ if (ips.is_v == 6) {
+ if ((IP6_NEQ(&saddr, &in6addr_any) &&
+ IP6_NEQ(&saddr, &ips.is_src)) ||
+ (IP6_NEQ(&daddr, &in6addr_any) &&
+ IP6_NEQ(&daddr, &ips.is_dst)))
+ continue;
+ }
+#endif
+ /* check protocol */
+ if (protocol > 0 && protocol != ips.is_p)
+ continue;
+
+ /* check ports if protocol is TCP or UDP */
+ if (((ips.is_p == IPPROTO_TCP) ||
+ (ips.is_p == IPPROTO_UDP)) &&
+ (((sport > 0) && (htons(sport) != ips.is_sport)) ||
+ ((dport > 0) && (htons(dport) != ips.is_dport))))
+ continue;
+
+ /* show closed TCP sessions ? */
+ if ((topclosed == 0) && (ips.is_p == IPPROTO_TCP) &&
+ (ips.is_state[0] >= IPF_TCPS_LAST_ACK) &&
+ (ips.is_state[1] >= IPF_TCPS_LAST_ACK))
+ continue;
+
+ /*
+ * if necessary make room for this state
+ * entry
+ */
+ tsentry++;
+ if (!maxtsentries || tsentry == maxtsentries) {
+ maxtsentries += STGROWSIZE;
+ tstable = realloc(tstable,
+ maxtsentries * sizeof(statetop_t));
+ if (tstable == NULL) {
+ perror("realloc");
+ exit(-1);
+ }
+ }
+
+ /* get max src/dest address string length */
+ len = strlen(getip(ips.is_v, &ips.is_src));
+ if (srclen < len)
+ srclen = len;
+ len = strlen(getip(ips.is_v, &ips.is_dst));
+ if (dstlen < len)
+ dstlen = len;
+
+ /* fill structure */
+ tp = tstable + tsentry;
+ tp->st_src = ips.is_src;
+ tp->st_dst = ips.is_dst;
+ tp->st_p = ips.is_p;
+ tp->st_v = ips.is_v;
+ tp->st_state[0] = ips.is_state[0];
+ tp->st_state[1] = ips.is_state[1];
+ if (forward) {
+ tp->st_pkts = ips.is_pkts[0]+ips.is_pkts[1];
+ tp->st_bytes = ips.is_bytes[0]+ips.is_bytes[1];
+ } else {
+ tp->st_pkts = ips.is_pkts[2]+ips.is_pkts[3];
+ tp->st_bytes = ips.is_bytes[2]+ips.is_bytes[3];
+ }
+ tp->st_age = ips.is_die - ipsstp->iss_ticks;
+ if ((ips.is_p == IPPROTO_TCP) ||
+ (ips.is_p == IPPROTO_UDP)) {
+ tp->st_sport = ips.is_sport;
+ tp->st_dport = ips.is_dport;
+ }
+ }
+
+
+ /* sort the array */
+ if (tsentry != -1) {
+ switch (sorting)
+ {
+ case STSORT_PR:
+ qsort(tstable, tsentry + 1,
+ sizeof(statetop_t), sort_p);
+ break;
+ case STSORT_PKTS:
+ qsort(tstable, tsentry + 1,
+ sizeof(statetop_t), sort_pkts);
+ break;
+ case STSORT_BYTES:
+ qsort(tstable, tsentry + 1,
+ sizeof(statetop_t), sort_bytes);
+ break;
+ case STSORT_TTL:
+ qsort(tstable, tsentry + 1,
+ sizeof(statetop_t), sort_ttl);
+ break;
+ case STSORT_SRCIP:
+ qsort(tstable, tsentry + 1,
+ sizeof(statetop_t), sort_srcip);
+ break;
+ case STSORT_SRCPT:
+ qsort(tstable, tsentry +1,
+ sizeof(statetop_t), sort_srcpt);
+ break;
+ case STSORT_DSTIP:
+ qsort(tstable, tsentry + 1,
+ sizeof(statetop_t), sort_dstip);
+ break;
+ case STSORT_DSTPT:
+ qsort(tstable, tsentry + 1,
+ sizeof(statetop_t), sort_dstpt);
+ break;
+ default:
+ break;
+ }
+ }
+
+ /* handle window resizes */
+ if (handle_resize) {
+ endwin();
+ initscr();
+ cbreak();
+ noecho();
+ curs_set(0);
+ timeout(0);
+ getmaxyx(stdscr, maxy, maxx);
+ redraw = 1;
+ handle_resize = 0;
+ }
+
+ /* stop program? */
+ if (handle_break)
+ break;
+
+ /* print title */
+ erase();
+ attron(A_BOLD);
+ winy = 0;
+ move(winy,0);
+ sprintf(str1, "%s - %s - state top", hostnm, IPL_VERSION);
+ for (j = 0 ; j < (maxx - 8 - strlen(str1)) / 2; j++)
+ printw(" ");
+ printw("%s", str1);
+ attroff(A_BOLD);
+
+ /* just for fun add a clock */
+ move(winy, maxx - 8);
+ t = time(NULL);
+ strftime(str1, 80, "%T", localtime(&t));
+ printw("%s\n", str1);
+
+ /*
+ * print the display filters, this is placed in the loop,
+ * because someday I might add code for changing these
+ * while the programming is running :-)
+ */
+ if (sport >= 0)
+ sprintf(str1, "%s,%d", getip(ver, &saddr), sport);
+ else
+ sprintf(str1, "%s", getip(ver, &saddr));
+
+ if (dport >= 0)
+ sprintf(str2, "%s,%d", getip(ver, &daddr), dport);
+ else
+ sprintf(str2, "%s", getip(ver, &daddr));
+
+ if (protocol < 0)
+ strcpy(str3, "any");
+ else if ((proto = getprotobynumber(protocol)) != NULL)
+ sprintf(str3, "%s", proto->p_name);
+ else
+ sprintf(str3, "%d", protocol);
+
+ switch (sorting)
+ {
+ case STSORT_PR:
+ sprintf(str4, "proto");
+ break;
+ case STSORT_PKTS:
+ sprintf(str4, "# pkts");
+ break;
+ case STSORT_BYTES:
+ sprintf(str4, "# bytes");
+ break;
+ case STSORT_TTL:
+ sprintf(str4, "ttl");
+ break;
+ case STSORT_SRCIP:
+ sprintf(str4, "src ip");
+ break;
+ case STSORT_SRCPT:
+ sprintf(str4, "src port");
+ break;
+ case STSORT_DSTIP:
+ sprintf(str4, "dest ip");
+ break;
+ case STSORT_DSTPT:
+ sprintf(str4, "dest port");
+ break;
+ default:
+ sprintf(str4, "unknown");
+ break;
+ }
+
+ if (reverse)
+ strcat(str4, " (reverse)");
+
+ winy += 2;
+ move(winy,0);
+ printw("Src: %s, Dest: %s, Proto: %s, Sorted by: %s\n\n",
+ str1, str2, str3, str4);
+
+ /*
+ * For an IPv4 IP address we need at most 15 characters,
+ * 4 tuples of 3 digits, separated by 3 dots. Enforce this
+ * length, so the colums do not change positions based
+ * on the size of the IP address. This length makes the
+ * output fit in a 80 column terminal.
+ * We are lacking a good solution for IPv6 addresses (that
+ * can be longer that 15 characters), so we do not enforce
+ * a maximum on the IP field size.
+ */
+ if (srclen < 15)
+ srclen = 15;
+ if (dstlen < 15)
+ dstlen = 15;
+
+ /* print column description */
+ winy += 2;
+ move(winy,0);
+ attron(A_BOLD);
+ printw("%-*s %-*s %3s %4s %7s %9s %9s\n",
+ srclen + 6, "Source IP", dstlen + 6, "Destination IP",
+ "ST", "PR", "#pkts", "#bytes", "ttl");
+ attroff(A_BOLD);
+
+ /* print all the entries */
+ tp = tstable;
+ if (reverse)
+ tp += tsentry;
+
+ if (tsentry > maxy - 6)
+ tsentry = maxy - 6;
+ for (i = 0; i <= tsentry; i++) {
+ /* print src/dest and port */
+ if ((tp->st_p == IPPROTO_TCP) ||
+ (tp->st_p == IPPROTO_UDP)) {
+ sprintf(str1, "%s,%hu",
+ getip(tp->st_v, &tp->st_src),
+ ntohs(tp->st_sport));
+ sprintf(str2, "%s,%hu",
+ getip(tp->st_v, &tp->st_dst),
+ ntohs(tp->st_dport));
+ } else {
+ sprintf(str1, "%s", getip(tp->st_v,
+ &tp->st_src));
+ sprintf(str2, "%s", getip(tp->st_v,
+ &tp->st_dst));
+ }
+ winy++;
+ move(winy, 0);
+ printw("%-*s %-*s", srclen + 6, str1, dstlen + 6, str2);
+
+ /* print state */
+ sprintf(str1, "%X/%X", tp->st_state[0],
+ tp->st_state[1]);
+ printw(" %3s", str1);
+
+ /* print protocol */
+ proto = getprotobynumber(tp->st_p);
+ if (proto) {
+ strncpy(str1, proto->p_name, 4);
+ str1[4] = '\0';
+ } else {
+ sprintf(str1, "%d", tp->st_p);
+ }
+ /* just print icmp for IPv6-ICMP */
+ if (tp->st_p == IPPROTO_ICMPV6)
+ strcpy(str1, "icmp");
+ printw(" %4s", str1);
+
+ /* print #pkt/#bytes */
+#ifdef USE_QUAD_T
+ printw(" %7qu %9qu", (unsigned long long) tp->st_pkts,
+ (unsigned long long) tp->st_bytes);
+#else
+ printw(" %7lu %9lu", tp->st_pkts, tp->st_bytes);
+#endif
+ printw(" %9s", ttl_to_string(tp->st_age));
+
+ if (reverse)
+ tp--;
+ else
+ tp++;
+ }
+
+ /* screen data structure is filled, now update the screen */
+ if (redraw)
+ clearok(stdscr,1);
+
+ if (refresh() == ERR)
+ break;
+ if (redraw) {
+ clearok(stdscr,0);
+ redraw = 0;
+ }
+
+ /* wait for key press or a 1 second time out period */
+ selecttimeout.tv_sec = refreshtime;
+ selecttimeout.tv_usec = 0;
+ FD_ZERO(&readfd);
+ FD_SET(0, &readfd);
+ select(1, &readfd, NULL, NULL, &selecttimeout);
+
+ /* if key pressed, read all waiting keys */
+ if (FD_ISSET(0, &readfd)) {
+ c = wgetch(stdscr);
+ if (c == ERR)
+ continue;
+
+ if (ISALPHA(c) && ISUPPER(c))
+ c = TOLOWER(c);
+ if (c == 'l') {
+ redraw = 1;
+ } else if (c == 'q') {
+ break;
+ } else if (c == 'r') {
+ reverse = !reverse;
+ } else if (c == 'b') {
+ forward = 0;
+ } else if (c == 'f') {
+ forward = 1;
+ } else if (c == 's') {
+ if (++sorting > STSORT_MAX)
+ sorting = 0;
+ }
+ }
+ } /* while */
+
+ printw("\n");
+ curs_set(1);
+ nocbreak();
+ endwin();
+
+ free(tstable);
+}
+#endif
+
+
+/*
+ * Show fragment cache information that's held in the kernel.
+ */
+static void showfrstates(ifsp)
+ipfrstat_t *ifsp;
+{
+ struct ipfr *ipfrtab[IPFT_SIZE], ifr;
+ int i;
+
+ /*
+ * print out the numeric statistics
+ */
+ 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 retrans\n\t%lu too short\n",
+ ifsp->ifs_retrans0, ifsp->ifs_short);
+ 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;
+
+ /*
+ * Print out the contents (if any) of the fragment cache table.
+ */
+ PRINTF("\n");
+ for (i = 0; i < IPFT_SIZE; i++)
+ while (ipfrtab[i] != NULL) {
+ if (kmemcpy((char *)&ifr, (u_long)ipfrtab[i],
+ sizeof(ifr)) == -1)
+ break;
+ printfraginfo("", &ifr);
+ ipfrtab[i] = ifr.ipfr_next;
+ }
+ /*
+ * Print out the contents (if any) of the NAT fragment cache table.
+ */
+ if (kmemcpy((char *)ipfrtab, (u_long)ifsp->ifs_nattab,sizeof(ipfrtab)))
+ return;
+ for (i = 0; i < IPFT_SIZE; i++)
+ while (ipfrtab[i] != NULL) {
+ if (kmemcpy((char *)&ifr, (u_long)ipfrtab[i],
+ sizeof(ifr)) == -1)
+ break;
+ printfraginfo("NAT: ", &ifr);
+ ipfrtab[i] = ifr.ipfr_next;
+ }
+}
+
+
+/*
+ * Show stats on how auth within IPFilter has been used
+ */
+static void showauthstates(asp)
+fr_authstat_t *asp;
+{
+ frauthent_t *frap, fra;
+
+#ifdef USE_QUAD_T
+ printf("Authorisation hits: %qu\tmisses %qu\n",
+ (unsigned long long) asp->fas_hits,
+ (unsigned long long) asp->fas_miss);
+#else
+ printf("Authorisation hits: %ld\tmisses %ld\n", asp->fas_hits,
+ asp->fas_miss);
+#endif
+ printf("nospace %ld\nadded %ld\nsendfail %ld\nsendok %ld\n",
+ asp->fas_nospace, asp->fas_added, asp->fas_sendfail,
+ asp->fas_sendok);
+ printf("queok %ld\nquefail %ld\nexpire %ld\n",
+ asp->fas_queok, asp->fas_quefail, asp->fas_expire);
+
+ frap = asp->fas_faelist;
+ while (frap) {
+ if (kmemcpy((char *)&fra, (u_long)frap, sizeof(fra)) == -1)
+ break;
+
+ printf("age %ld\t", fra.fae_age);
+ printfr(&fra.fae_fr, ioctl);
+ frap = fra.fae_next;
+ }
+}
+
+
+/*
+ * Display groups used for each of filter rules, accounting rules and
+ * authentication, separately.
+ */
+static void showgroups(fiop)
+struct friostat *fiop;
+{
+ static char *gnames[3] = { "Filter", "Accounting", "Authentication" };
+ static int gnums[3] = { IPL_LOGIPF, IPL_LOGCOUNT, IPL_LOGAUTH };
+ frgroup_t *fp, grp;
+ int on, off, i;
+
+ on = fiop->f_active;
+ off = 1 - on;
+
+ for (i = 0; i < 3; i++) {
+ printf("%s groups (active):\n", gnames[i]);
+ for (fp = fiop->f_groups[gnums[i]][on]; fp != NULL;
+ fp = grp.fg_next)
+ if (kmemcpy((char *)&grp, (u_long)fp, sizeof(grp)))
+ break;
+ else
+ printf("%s\n", grp.fg_name);
+ printf("%s groups (inactive):\n", gnames[i]);
+ for (fp = fiop->f_groups[gnums[i]][off]; fp != NULL;
+ fp = grp.fg_next)
+ if (kmemcpy((char *)&grp, (u_long)fp, sizeof(grp)))
+ break;
+ else
+ printf("%s\n", grp.fg_name);
+ }
+}
+
+static void parse_ipportstr(argument, ip, port)
+const char *argument;
+i6addr_t *ip;
+int *port;
+{
+ char *s, *comma;
+ int ok = 0;
+
+ /* make working copy of argument, Theoretically you must be able
+ * to write to optarg, but that seems very ugly to me....
+ */
+ s = strdup(argument);
+ if (s == NULL)
+ return;
+
+ /* get port */
+ if ((comma = strchr(s, ',')) != NULL) {
+ if (!strcasecmp(comma + 1, "any")) {
+ *port = -1;
+ } else if (!sscanf(comma + 1, "%d", port) ||
+ (*port < 0) || (*port > 65535)) {
+ fprintf(stderr, "Invalid port specfication in %s\n",
+ argument);
+ free(s);
+ exit(-2);
+ }
+ *comma = '\0';
+ }
+
+
+ /* get ip address */
+ if (!strcasecmp(s, "any")) {
+ ip->in4.s_addr = INADDR_ANY;
+#ifdef USE_INET6
+ ip->in6 = in6addr_any;
+ } else if (use_inet6 && inet_pton(AF_INET6, s, &ip->in6)) {
+ ok = 1;
+#endif
+ } else if (inet_aton(s, &ip->in4))
+ ok = 1;
+
+ if (ok == 0) {
+ fprintf(stderr, "Invalid IP address: %s\n", s);
+ free(s);
+ exit(-2);
+ }
+
+ /* free allocated memory */
+ free(s);
+}
+
+
+#ifdef STATETOP
+static void sig_resize(s)
+int s;
+{
+ handle_resize = 1;
+}
+
+static void sig_break(s)
+int s;
+{
+ handle_break = 1;
+}
+
+static char *getip(v, addr)
+int v;
+i6addr_t *addr;
+{
+ static char hostbuf[MAXHOSTNAMELEN+1];
+
+ if (v == 4)
+ return inet_ntoa(addr->in4);
+
+#ifdef USE_INET6
+ (void) inet_ntop(AF_INET6, &addr->in6, hostbuf, sizeof(hostbuf) - 1);
+ hostbuf[MAXHOSTNAMELEN] = '\0';
+ return hostbuf;
+#else
+ return "IPv6";
+#endif
+}
+
+
+static char *ttl_to_string(ttl)
+long int ttl;
+{
+ static char ttlbuf[STSTRSIZE];
+ int hours, minutes, seconds;
+
+ /* ttl is in half seconds */
+ ttl /= 2;
+
+ hours = ttl / 3600;
+ ttl = ttl % 3600;
+ minutes = ttl / 60;
+ seconds = ttl % 60;
+
+ if (hours > 0)
+ sprintf(ttlbuf, "%2d:%02d:%02d", hours, minutes, seconds);
+ else
+ sprintf(ttlbuf, "%2d:%02d", minutes, seconds);
+ return ttlbuf;
+}
+
+
+static int sort_pkts(a, b)
+const void *a;
+const void *b;
+{
+
+ register const statetop_t *ap = a;
+ register const statetop_t *bp = b;
+
+ if (ap->st_pkts == bp->st_pkts)
+ return 0;
+ else if (ap->st_pkts < bp->st_pkts)
+ return 1;
+ return -1;
+}
+
+
+static int sort_bytes(a, b)
+const void *a;
+const void *b;
+{
+ register const statetop_t *ap = a;
+ register const statetop_t *bp = b;
+
+ if (ap->st_bytes == bp->st_bytes)
+ return 0;
+ else if (ap->st_bytes < bp->st_bytes)
+ return 1;
+ return -1;
+}
+
+
+static int sort_p(a, b)
+const void *a;
+const void *b;
+{
+ register const statetop_t *ap = a;
+ register const statetop_t *bp = b;
+
+ if (ap->st_p == bp->st_p)
+ return 0;
+ else if (ap->st_p < bp->st_p)
+ return 1;
+ return -1;
+}
+
+
+static int sort_ttl(a, b)
+const void *a;
+const void *b;
+{
+ register const statetop_t *ap = a;
+ register const statetop_t *bp = b;
+
+ if (ap->st_age == bp->st_age)
+ return 0;
+ else if (ap->st_age < bp->st_age)
+ return 1;
+ return -1;
+}
+
+static int sort_srcip(a, b)
+const void *a;
+const void *b;
+{
+ register const statetop_t *ap = a;
+ register const statetop_t *bp = b;
+
+#ifdef USE_INET6
+ if (use_inet6) {
+ if (IP6_EQ(&ap->st_src, &bp->st_src))
+ return 0;
+ else if (IP6_GT(&ap->st_src, &bp->st_src))
+ return 1;
+ } else
+#endif
+ {
+ if (ntohl(ap->st_src.in4.s_addr) ==
+ ntohl(bp->st_src.in4.s_addr))
+ return 0;
+ else if (ntohl(ap->st_src.in4.s_addr) >
+ ntohl(bp->st_src.in4.s_addr))
+ return 1;
+ }
+ return -1;
+}
+
+static int sort_srcpt(a, b)
+const void *a;
+const void *b;
+{
+ register const statetop_t *ap = a;
+ register const statetop_t *bp = b;
+
+ if (htons(ap->st_sport) == htons(bp->st_sport))
+ return 0;
+ else if (htons(ap->st_sport) > htons(bp->st_sport))
+ return 1;
+ return -1;
+}
+
+static int sort_dstip(a, b)
+const void *a;
+const void *b;
+{
+ register const statetop_t *ap = a;
+ register const statetop_t *bp = b;
+
+#ifdef USE_INET6
+ if (use_inet6) {
+ if (IP6_EQ(&ap->st_dst, &bp->st_dst))
+ return 0;
+ else if (IP6_GT(&ap->st_dst, &bp->st_dst))
+ return 1;
+ } else
+#endif
+ {
+ if (ntohl(ap->st_dst.in4.s_addr) ==
+ ntohl(bp->st_dst.in4.s_addr))
+ return 0;
+ else if (ntohl(ap->st_dst.in4.s_addr) >
+ ntohl(bp->st_dst.in4.s_addr))
+ return 1;
+ }
+ return -1;
+}
+
+static int sort_dstpt(a, b)
+const void *a;
+const void *b;
+{
+ register const statetop_t *ap = a;
+ register const statetop_t *bp = b;
+
+ if (htons(ap->st_dport) == htons(bp->st_dport))
+ return 0;
+ else if (htons(ap->st_dport) > htons(bp->st_dport))
+ return 1;
+ return -1;
+}
+
+#endif
diff --git a/contrib/ipfilter/tools/ipftest.c b/contrib/ipfilter/tools/ipftest.c
new file mode 100644
index 0000000..fbc91e5
--- /dev/null
+++ b/contrib/ipfilter/tools/ipftest.c
@@ -0,0 +1,776 @@
+/* $NetBSD$ */
+
+/*
+ * Copyright (C) 1993-2001 by Darren Reed.
+ *
+ * See the IPFILTER.LICENCE file for details on licencing.
+ */
+#include "ipf.h"
+#include "ipt.h"
+#include <sys/ioctl.h>
+#include <sys/file.h>
+
+#if !defined(lint)
+static const char sccsid[] = "@(#)ipt.c 1.19 6/3/96 (C) 1993-2000 Darren Reed";
+static const char rcsid[] = "@(#)Id: ipftest.c,v 1.44.2.3 2005/02/01 02:41:24 darrenr Exp";
+#endif
+
+extern char *optarg;
+extern struct frentry *ipfilter[2][2];
+extern struct ipread snoop, etherf, tcpd, pcap, iptext, iphex;
+extern struct ifnet *get_unit __P((char *, int));
+extern void init_ifp __P((void));
+extern ipnat_t *natparse __P((char *, int));
+extern int fr_running;
+
+ipfmutex_t ipl_mutex, ipf_authmx, ipf_rw, ipf_stinsert;
+ipfmutex_t ipf_nat_new, ipf_natio, ipf_timeoutlock;
+ipfrwlock_t ipf_mutex, ipf_global, ipf_ipidfrag, ip_poolrw;
+ipfrwlock_t ipf_frag, ipf_state, ipf_nat, ipf_natfrag, ipf_auth;
+int opts = OPT_DONOTHING;
+int use_inet6 = 0;
+int pfil_delayed_copy = 0;
+int main __P((int, char *[]));
+int loadrules __P((char *, int));
+int kmemcpy __P((char *, long, int));
+int kstrncpy __P((char *, long, int n));
+void dumpnat __P((void));
+void dumpstate __P((void));
+void dumplookups __P((void));
+void dumpgroups __P((void));
+void drain_log __P((char *));
+void fixv4sums __P((mb_t *, ip_t *));
+
+#if defined(__NetBSD__) || defined(__OpenBSD__) || SOLARIS || \
+ (_BSDI_VERSION >= 199701) || (__FreeBSD_version >= 300000) || \
+ defined(__osf__) || defined(linux)
+int ipftestioctl __P((int, ioctlcmd_t, ...));
+int ipnattestioctl __P((int, ioctlcmd_t, ...));
+int ipstatetestioctl __P((int, ioctlcmd_t, ...));
+int ipauthtestioctl __P((int, ioctlcmd_t, ...));
+int ipscantestioctl __P((int, ioctlcmd_t, ...));
+int ipsynctestioctl __P((int, ioctlcmd_t, ...));
+int ipooltestioctl __P((int, ioctlcmd_t, ...));
+#else
+int ipftestioctl __P((dev_t, ioctlcmd_t, void *));
+int ipnattestioctl __P((dev_t, ioctlcmd_t, void *));
+int ipstatetestioctl __P((dev_t, ioctlcmd_t, void *));
+int ipauthtestioctl __P((dev_t, ioctlcmd_t, void *));
+int ipsynctestioctl __P((dev_t, ioctlcmd_t, void *));
+int ipscantestioctl __P((dev_t, ioctlcmd_t, void *));
+int ipooltestioctl __P((dev_t, ioctlcmd_t, void *));
+#endif
+
+static ioctlfunc_t iocfunctions[IPL_LOGSIZE] = { ipftestioctl,
+ ipnattestioctl,
+ ipstatetestioctl,
+ ipauthtestioctl,
+ ipsynctestioctl,
+ ipscantestioctl,
+ ipooltestioctl,
+ NULL };
+
+
+int main(argc,argv)
+int argc;
+char *argv[];
+{
+ char *datain, *iface, *ifname, *logout;
+ int fd, i, dir, c, loaded, dump, hlen;
+ struct ifnet *ifp;
+ struct ipread *r;
+ mb_t mb, *m;
+ ip_t *ip;
+
+ m = &mb;
+ dir = 0;
+ dump = 0;
+ hlen = 0;
+ loaded = 0;
+ r = &iptext;
+ iface = NULL;
+ logout = NULL;
+ ifname = "anon0";
+ datain = NULL;
+
+ MUTEX_INIT(&ipf_rw, "ipf rw mutex");
+ MUTEX_INIT(&ipf_timeoutlock, "ipf timeout lock");
+ RWLOCK_INIT(&ipf_global, "ipf filter load/unload mutex");
+ RWLOCK_INIT(&ipf_mutex, "ipf filter rwlock");
+ RWLOCK_INIT(&ipf_ipidfrag, "ipf IP NAT-Frag rwlock");
+
+ initparse();
+ if (fr_initialise() == -1)
+ abort();
+ fr_running = 1;
+
+ while ((c = getopt(argc, argv, "6bdDF:i:I:l:N:P:or:RT:vxX")) != -1)
+ switch (c)
+ {
+ case '6' :
+#ifdef USE_INET6
+ use_inet6 = 1;
+#else
+ fprintf(stderr, "IPv6 not supported\n");
+ exit(1);
+#endif
+ break;
+ case 'b' :
+ opts |= OPT_BRIEF;
+ break;
+ case 'd' :
+ opts |= OPT_DEBUG;
+ break;
+ case 'D' :
+ dump = 1;
+ break;
+ case 'F' :
+ if (strcasecmp(optarg, "pcap") == 0)
+ r = &pcap;
+ else if (strcasecmp(optarg, "etherfind") == 0)
+ r = &etherf;
+ else if (strcasecmp(optarg, "snoop") == 0)
+ r = &snoop;
+ else if (strcasecmp(optarg, "tcpdump") == 0)
+ r = &tcpd;
+ else if (strcasecmp(optarg, "hex") == 0)
+ r = &iphex;
+ else if (strcasecmp(optarg, "text") == 0)
+ r = &iptext;
+ break;
+ case 'i' :
+ datain = optarg;
+ break;
+ case 'I' :
+ ifname = optarg;
+ break;
+ case 'l' :
+ logout = optarg;
+ break;
+ case 'o' :
+ opts |= OPT_SAVEOUT;
+ break;
+ case 'r' :
+ if (ipf_parsefile(-1, ipf_addrule, iocfunctions,
+ optarg) == -1)
+ return -1;
+ loaded = 1;
+ break;
+ case 'R' :
+ opts |= OPT_NORESOLVE;
+ break;
+ case 'v' :
+ opts |= OPT_VERBOSE;
+ break;
+ case 'N' :
+ if (ipnat_parsefile(-1, ipnat_addrule, ipnattestioctl,
+ optarg) == -1)
+ return -1;
+ loaded = 1;
+ opts |= OPT_NAT;
+ break;
+ case 'P' :
+ if (ippool_parsefile(-1, optarg, ipooltestioctl) == -1)
+ return -1;
+ loaded = 1;
+ break;
+ case 'T' :
+ ipf_dotuning(-1, optarg, ipftestioctl);
+ break;
+ case 'x' :
+ opts |= OPT_HEX;
+ break;
+ }
+
+ if (loaded == 0) {
+ (void)fprintf(stderr,"no rules loaded\n");
+ exit(-1);
+ }
+
+ if (opts & OPT_SAVEOUT)
+ init_ifp();
+
+ if (datain)
+ fd = (*r->r_open)(datain);
+ else
+ fd = (*r->r_open)("-");
+
+ if (fd < 0)
+ exit(-1);
+
+ ip = MTOD(m, ip_t *);
+ while ((i = (*r->r_readip)(MTOD(m, char *), sizeof(m->mb_buf),
+ &iface, &dir)) > 0) {
+ if (iface == NULL || *iface == '\0')
+ iface = ifname;
+ ifp = get_unit(iface, IP_V(ip));
+ if (!use_inet6) {
+ ip->ip_off = ntohs(ip->ip_off);
+ ip->ip_len = ntohs(ip->ip_len);
+ if (r->r_flags & R_DO_CKSUM)
+ fixv4sums(m, ip);
+ hlen = IP_HL(ip) << 2;
+ }
+#ifdef USE_INET6
+ else
+ hlen = sizeof(ip6_t);
+#endif
+ /* ipfr_slowtimer(); */
+ m = &mb;
+ m->mb_len = i;
+ i = fr_check(ip, hlen, ifp, dir, &m);
+ if ((opts & OPT_NAT) == 0)
+ switch (i)
+ {
+ case -4 :
+ (void)printf("preauth");
+ break;
+ case -3 :
+ (void)printf("account");
+ break;
+ case -2 :
+ (void)printf("auth");
+ break;
+ case -1 :
+ (void)printf("block");
+ break;
+ case 0 :
+ (void)printf("pass");
+ break;
+ case 1 :
+ (void)printf("nomatch");
+ break;
+ case 3 :
+ (void)printf("block return-rst");
+ break;
+ case 4 :
+ (void)printf("block return-icmp");
+ break;
+ case 5 :
+ (void)printf("block return-icmp-as-dest");
+ break;
+ default :
+ (void)printf("recognised return %#x\n", i);
+ break;
+ }
+ if (!use_inet6) {
+ ip->ip_off = htons(ip->ip_off);
+ ip->ip_len = htons(ip->ip_len);
+ }
+
+ if (!(opts & OPT_BRIEF)) {
+ putchar(' ');
+ printpacket(ip);
+ printf("--------------");
+ } else if ((opts & (OPT_BRIEF|OPT_NAT)) == (OPT_NAT|OPT_BRIEF))
+ printpacket(ip);
+ if (dir && (ifp != NULL) && IP_V(ip) && (m != NULL))
+#if defined(__sgi) && (IRIX < 60500)
+ (*ifp->if_output)(ifp, (void *)m, NULL);
+#else
+# if TRU64 >= 1885
+ (*ifp->if_output)(ifp, (void *)m, NULL, 0, 0);
+# else
+ (*ifp->if_output)(ifp, (void *)m, NULL, 0);
+# endif
+#endif
+ if ((opts & (OPT_BRIEF|OPT_NAT)) != (OPT_NAT|OPT_BRIEF))
+ putchar('\n');
+ dir = 0;
+ if (iface != ifname) {
+ free(iface);
+ iface = ifname;
+ }
+ m = &mb;
+ }
+ (*r->r_close)();
+
+ if (logout != NULL) {
+ drain_log(logout);
+ }
+
+ if (dump == 1) {
+ dumpnat();
+ dumpstate();
+ dumplookups();
+ dumpgroups();
+ }
+
+ fr_deinitialise();
+
+ return 0;
+}
+
+
+#if defined(__NetBSD__) || defined(__OpenBSD__) || SOLARIS || \
+ (_BSDI_VERSION >= 199701) || (__FreeBSD_version >= 300000) || \
+ defined(__osf__) || defined(linux)
+int ipftestioctl(int dev, ioctlcmd_t cmd, ...)
+{
+ caddr_t data;
+ va_list ap;
+ int i;
+
+ va_start(ap, cmd);
+ data = va_arg(ap, caddr_t);
+ va_end(ap);
+
+ i = iplioctl(IPL_LOGIPF, cmd, data, FWRITE|FREAD);
+ if (opts & OPT_DEBUG)
+ fprintf(stderr, "iplioctl(IPF,%#x,%p) = %d\n",
+ (u_int)cmd, data, i);
+ if (i != 0) {
+ errno = i;
+ return -1;
+ }
+ return 0;
+}
+
+
+int ipnattestioctl(int dev, ioctlcmd_t cmd, ...)
+{
+ caddr_t data;
+ va_list ap;
+ int i;
+
+ va_start(ap, cmd);
+ data = va_arg(ap, caddr_t);
+ va_end(ap);
+
+ i = iplioctl(IPL_LOGNAT, cmd, data, FWRITE|FREAD);
+ if (opts & OPT_DEBUG)
+ fprintf(stderr, "iplioctl(NAT,%#x,%p) = %d\n",
+ (u_int)cmd, data, i);
+ if (i != 0) {
+ errno = i;
+ return -1;
+ }
+ return 0;
+}
+
+
+int ipstatetestioctl(int dev, ioctlcmd_t cmd, ...)
+{
+ caddr_t data;
+ va_list ap;
+ int i;
+
+ va_start(ap, cmd);
+ data = va_arg(ap, caddr_t);
+ va_end(ap);
+
+ i = iplioctl(IPL_LOGSTATE, cmd, data, FWRITE|FREAD);
+ if ((opts & OPT_DEBUG) || (i != 0))
+ fprintf(stderr, "iplioctl(STATE,%#x,%p) = %d\n",
+ (u_int)cmd, data, i);
+ if (i != 0) {
+ errno = i;
+ return -1;
+ }
+ return 0;
+}
+
+
+int ipauthtestioctl(int dev, ioctlcmd_t cmd, ...)
+{
+ caddr_t data;
+ va_list ap;
+ int i;
+
+ va_start(ap, cmd);
+ data = va_arg(ap, caddr_t);
+ va_end(ap);
+
+ i = iplioctl(IPL_LOGAUTH, cmd, data, FWRITE|FREAD);
+ if ((opts & OPT_DEBUG) || (i != 0))
+ fprintf(stderr, "iplioctl(AUTH,%#x,%p) = %d\n",
+ (u_int)cmd, data, i);
+ if (i != 0) {
+ errno = i;
+ return -1;
+ }
+ return 0;
+}
+
+
+int ipscantestioctl(int dev, ioctlcmd_t cmd, ...)
+{
+ caddr_t data;
+ va_list ap;
+ int i;
+
+ va_start(ap, cmd);
+ data = va_arg(ap, caddr_t);
+ va_end(ap);
+
+ i = iplioctl(IPL_LOGSCAN, cmd, data, FWRITE|FREAD);
+ if ((opts & OPT_DEBUG) || (i != 0))
+ fprintf(stderr, "iplioctl(SCAN,%#x,%p) = %d\n",
+ (u_int)cmd, data, i);
+ if (i != 0) {
+ errno = i;
+ return -1;
+ }
+ return 0;
+}
+
+
+int ipsynctestioctl(int dev, ioctlcmd_t cmd, ...)
+{
+ caddr_t data;
+ va_list ap;
+ int i;
+
+ va_start(ap, cmd);
+ data = va_arg(ap, caddr_t);
+ va_end(ap);
+
+ i = iplioctl(IPL_LOGSYNC, cmd, data, FWRITE|FREAD);
+ if ((opts & OPT_DEBUG) || (i != 0))
+ fprintf(stderr, "iplioctl(SYNC,%#x,%p) = %d\n",
+ (u_int)cmd, data, i);
+ if (i != 0) {
+ errno = i;
+ return -1;
+ }
+ return 0;
+}
+
+
+int ipooltestioctl(int dev, ioctlcmd_t cmd, ...)
+{
+ caddr_t data;
+ va_list ap;
+ int i;
+
+ va_start(ap, cmd);
+ data = va_arg(ap, caddr_t);
+ va_end(ap);
+
+ i = iplioctl(IPL_LOGLOOKUP, cmd, data, FWRITE|FREAD);
+ if ((opts & OPT_DEBUG) || (i != 0))
+ fprintf(stderr, "iplioctl(POOL,%#x,%p) = %d\n",
+ (u_int)cmd, data, i);
+ if (i != 0) {
+ errno = i;
+ return -1;
+ }
+ return 0;
+}
+#else
+int ipftestioctl(dev, cmd, data)
+dev_t dev;
+ioctlcmd_t cmd;
+void *data;
+{
+ int i;
+
+ i = iplioctl(IPL_LOGIPF, cmd, data, FWRITE|FREAD);
+ if ((opts & OPT_DEBUG) || (i != 0))
+ fprintf(stderr, "iplioctl(IPF,%#x,%p) = %d\n", cmd, data, i);
+ if (i != 0) {
+ errno = i;
+ return -1;
+ }
+ return 0;
+}
+
+
+int ipnattestioctl(dev, cmd, data)
+dev_t dev;
+ioctlcmd_t cmd;
+void *data;
+{
+ int i;
+
+ i = iplioctl(IPL_LOGNAT, cmd, data, FWRITE|FREAD);
+ if ((opts & OPT_DEBUG) || (i != 0))
+ fprintf(stderr, "iplioctl(NAT,%#x,%p) = %d\n", cmd, data, i);
+ if (i != 0) {
+ errno = i;
+ return -1;
+ }
+ return 0;
+}
+
+
+int ipstatetestioctl(dev, cmd, data)
+dev_t dev;
+ioctlcmd_t cmd;
+void *data;
+{
+ int i;
+
+ i = iplioctl(IPL_LOGSTATE, cmd, data, FWRITE|FREAD);
+ if ((opts & OPT_DEBUG) || (i != 0))
+ fprintf(stderr, "iplioctl(STATE,%#x,%p) = %d\n", cmd, data, i);
+ if (i != 0) {
+ errno = i;
+ return -1;
+ }
+ return 0;
+}
+
+
+int ipauthtestioctl(dev, cmd, data)
+dev_t dev;
+ioctlcmd_t cmd;
+void *data;
+{
+ int i;
+
+ i = iplioctl(IPL_LOGAUTH, cmd, data, FWRITE|FREAD);
+ if ((opts & OPT_DEBUG) || (i != 0))
+ fprintf(stderr, "iplioctl(AUTH,%#x,%p) = %d\n", cmd, data, i);
+ if (i != 0) {
+ errno = i;
+ return -1;
+ }
+ return 0;
+}
+
+
+int ipsynctestioctl(dev, cmd, data)
+dev_t dev;
+ioctlcmd_t cmd;
+void *data;
+{
+ int i;
+
+ i = iplioctl(IPL_LOGSYNC, cmd, data, FWRITE|FREAD);
+ if ((opts & OPT_DEBUG) || (i != 0))
+ fprintf(stderr, "iplioctl(SYNC,%#x,%p) = %d\n", cmd, data, i);
+ if (i != 0) {
+ errno = i;
+ return -1;
+ }
+ return 0;
+}
+
+
+int ipscantestioctl(dev, cmd, data)
+dev_t dev;
+ioctlcmd_t cmd;
+void *data;
+{
+ int i;
+
+ i = iplioctl(IPL_LOGSCAN, cmd, data, FWRITE|FREAD);
+ if ((opts & OPT_DEBUG) || (i != 0))
+ fprintf(stderr, "iplioctl(SCAN,%#x,%p) = %d\n", cmd, data, i);
+ if (i != 0) {
+ errno = i;
+ return -1;
+ }
+ return 0;
+}
+
+
+int ipooltestioctl(dev, cmd, data)
+dev_t dev;
+ioctlcmd_t cmd;
+void *data;
+{
+ int i;
+
+ i = iplioctl(IPL_LOGLOOKUP, cmd, data, FWRITE|FREAD);
+ if (opts & OPT_DEBUG)
+ fprintf(stderr, "iplioctl(POOL,%#x,%p) = %d\n", cmd, data, i);
+ if (i != 0) {
+ errno = i;
+ return -1;
+ }
+ return 0;
+}
+#endif
+
+
+int kmemcpy(addr, offset, size)
+char *addr;
+long offset;
+int size;
+{
+ bcopy((char *)offset, addr, size);
+ return 0;
+}
+
+
+int kstrncpy(buf, pos, n)
+char *buf;
+long pos;
+int n;
+{
+ char *ptr;
+
+ ptr = (char *)pos;
+
+ while ((n > 0) && (*buf++ = *ptr++))
+ ;
+ return 0;
+}
+
+
+/*
+ * Display the built up NAT table rules and mapping entries.
+ */
+void dumpnat()
+{
+ ipnat_t *ipn;
+ nat_t *nat;
+
+ printf("List of active MAP/Redirect filters:\n");
+ for (ipn = nat_list; ipn != NULL; ipn = ipn->in_next)
+ printnat(ipn, opts & (OPT_DEBUG|OPT_VERBOSE));
+ printf("\nList of active sessions:\n");
+ for (nat = nat_instances; nat; nat = nat->nat_next) {
+ printactivenat(nat, opts);
+ if (nat->nat_aps)
+ printaps(nat->nat_aps, opts);
+ }
+}
+
+
+/*
+ * Display the built up state table rules and mapping entries.
+ */
+void dumpstate()
+{
+ ipstate_t *ips;
+
+ printf("List of active state sessions:\n");
+ for (ips = ips_list; ips != NULL; )
+ ips = printstate(ips, opts & (OPT_DEBUG|OPT_VERBOSE),
+ fr_ticks);
+}
+
+
+void dumplookups()
+{
+ iphtable_t *iph;
+ ip_pool_t *ipl;
+ int i;
+
+ printf("List of configured pools\n");
+ for (i = 0; i < IPL_LOGSIZE; i++)
+ for (ipl = ip_pool_list[i]; ipl != NULL; ipl = ipl->ipo_next)
+ printpool(ipl, bcopywrap, NULL, opts);
+
+ printf("List of configured hash tables\n");
+ for (i = 0; i < IPL_LOGSIZE; i++)
+ for (iph = ipf_htables[i]; iph != NULL; iph = iph->iph_next)
+ printhash(iph, bcopywrap, NULL, opts);
+}
+
+
+void dumpgroups()
+{
+ frgroup_t *fg;
+ frentry_t *fr;
+ int i;
+
+ printf("List of groups configured (set 0)\n");
+ for (i = 0; i < IPL_LOGSIZE; i++)
+ for (fg = ipfgroups[i][0]; fg != NULL; fg = fg->fg_next) {
+ printf("Dev.%d. Group %s Ref %d Flags %#x\n",
+ i, fg->fg_name, fg->fg_ref, fg->fg_flags);
+ for (fr = fg->fg_start; fr != NULL; fr = fr->fr_next) {
+#ifdef USE_QUAD_T
+ printf("%qu ",(unsigned long long)fr->fr_hits);
+#else
+ printf("%ld ", fr->fr_hits);
+#endif
+ printfr(fr, ipftestioctl);
+ }
+ }
+
+ printf("List of groups configured (set 1)\n");
+ for (i = 0; i < IPL_LOGSIZE; i++)
+ for (fg = ipfgroups[i][1]; fg != NULL; fg = fg->fg_next) {
+ printf("Dev.%d. Group %s Ref %d Flags %#x\n",
+ i, fg->fg_name, fg->fg_ref, fg->fg_flags);
+ for (fr = fg->fg_start; fr != NULL; fr = fr->fr_next) {
+#ifdef USE_QUAD_T
+ printf("%qu ",(unsigned long long)fr->fr_hits);
+#else
+ printf("%ld ", fr->fr_hits);
+#endif
+ printfr(fr, ipftestioctl);
+ }
+ }
+}
+
+
+void drain_log(filename)
+char *filename;
+{
+ char buffer[DEFAULT_IPFLOGSIZE];
+ struct iovec iov;
+ struct uio uio;
+ size_t resid;
+ int fd, i;
+
+ fd = open(filename, O_CREAT|O_TRUNC|O_WRONLY, 0644);
+ if (fd == -1) {
+ perror("drain_log:open");
+ return;
+ }
+
+ for (i = 0; i <= IPL_LOGMAX; i++)
+ while (1) {
+ bzero((char *)&iov, sizeof(iov));
+ iov.iov_base = buffer;
+ iov.iov_len = sizeof(buffer);
+
+ bzero((char *)&uio, sizeof(uio));
+ uio.uio_iov = &iov;
+ uio.uio_iovcnt = 1;
+ uio.uio_resid = iov.iov_len;
+ resid = uio.uio_resid;
+
+ if (ipflog_read(i, &uio) == 0) {
+ /*
+ * If nothing was read then break out.
+ */
+ if (uio.uio_resid == resid)
+ break;
+ write(fd, buffer, resid - uio.uio_resid);
+ } else
+ break;
+ }
+
+ close(fd);
+}
+
+
+void fixv4sums(m, ip)
+mb_t *m;
+ip_t *ip;
+{
+ u_char *csump, *hdr;
+
+ ip->ip_sum = 0;
+ ip->ip_sum = ipf_cksum((u_short *)ip, IP_HL(ip) << 2);
+
+ csump = (u_char *)ip;
+ csump += IP_HL(ip) << 2;
+
+ switch (ip->ip_p)
+ {
+ case IPPROTO_TCP :
+ hdr = csump;
+ csump += offsetof(tcphdr_t, th_sum);
+ break;
+ case IPPROTO_UDP :
+ hdr = csump;
+ csump += offsetof(udphdr_t, uh_sum);
+ break;
+ default :
+ csump = NULL;
+ hdr = NULL;
+ break;
+ }
+ if (hdr != NULL) {
+ *csump = 0;
+ *(u_short *)csump = fr_cksum(m, ip, ip->ip_p, hdr);
+ }
+}
diff --git a/contrib/ipfilter/tools/ipmon.c b/contrib/ipfilter/tools/ipmon.c
new file mode 100644
index 0000000..a91eee4
--- /dev/null
+++ b/contrib/ipfilter/tools/ipmon.c
@@ -0,0 +1,1663 @@
+/* $NetBSD$ */
+
+/*
+ * Copyright (C) 1993-2001, 2003 by Darren Reed.
+ *
+ * See the IPFILTER.LICENCE file for details on licencing.
+ */
+#ifndef SOLARIS
+#define SOLARIS (defined(__SVR4) || defined(__svr4__)) && defined(sun)
+#endif
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/param.h>
+#include <sys/file.h>
+#include <sys/time.h>
+#define _KERNEL
+#include <sys/uio.h>
+#undef _KERNEL
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <time.h>
+#if !defined(__SVR4) && !defined(__svr4__)
+# if (__FreeBSD_version >= 300000)
+# include <sys/dirent.h>
+# else
+# include <sys/dir.h>
+# endif
+#else
+# include <sys/filio.h>
+# include <sys/byteorder.h>
+#endif
+#if !defined(__hpux) && (!defined(__SVR4) && !defined(__GNUC__))
+# include <strings.h>
+#endif
+#include <signal.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <net/if.h>
+#include <netinet/ip.h>
+#if !defined(__hpux) && !defined(linux)
+# include <netinet/tcp_fsm.h>
+#endif
+#include <netdb.h>
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+#ifdef __hpux
+# undef NOERROR
+#endif
+#include <resolv.h>
+
+#if !defined(linux)
+# include <sys/protosw.h>
+# include <netinet/ip_var.h>
+#endif
+
+#include <netinet/tcp.h>
+#include <netinet/ip_icmp.h>
+
+#include <ctype.h>
+#include <syslog.h>
+
+#include "netinet/ip_compat.h"
+#include <netinet/tcpip.h>
+#include "netinet/ip_fil.h"
+#include "netinet/ip_nat.h"
+#include "netinet/ip_state.h"
+#include "netinet/ip_proxy.h"
+#include "ipmon.h"
+
+#if !defined(lint)
+static const char sccsid[] = "@(#)ipmon.c 1.21 6/5/96 (C)1993-2000 Darren Reed";
+static const char rcsid[] = "@(#)Id: ipmon.c,v 1.33.2.8 2004/12/09 19:41:26 darrenr Exp";
+#endif
+
+
+#if defined(sun) && !defined(SOLARIS2)
+#define STRERROR(x) sys_errlist[x]
+extern char *sys_errlist[];
+#else
+#define STRERROR(x) strerror(x)
+#endif
+
+
+struct flags {
+ int value;
+ char flag;
+};
+
+
+typedef struct icmp_subtype {
+ int ist_val;
+ char *ist_name;
+} icmp_subtype_t;
+
+typedef struct icmp_type {
+ int it_val;
+ struct icmp_subtype *it_subtable;
+ size_t it_stsize;
+ char *it_name;
+} icmp_type_t;
+
+
+#define IST_SZ(x) (sizeof(x)/sizeof(icmp_subtype_t))
+
+
+struct flags tcpfl[] = {
+ { TH_ACK, 'A' },
+ { TH_RST, 'R' },
+ { TH_SYN, 'S' },
+ { TH_FIN, 'F' },
+ { TH_URG, 'U' },
+ { TH_PUSH,'P' },
+ { TH_ECN, 'E' },
+ { TH_CWR, 'C' },
+ { 0, '\0' }
+};
+
+#ifdef MENTAT
+static char *pidfile = "/etc/opt/ipf/ipmon.pid";
+#else
+# if BSD >= 199306
+static char *pidfile = "/var/run/ipmon.pid";
+# else
+static char *pidfile = "/etc/ipmon.pid";
+# endif
+#endif
+
+static char line[2048];
+static int opts = 0;
+static char *logfile = NULL;
+static FILE *binarylog = NULL;
+static char *binarylogfile = NULL;
+static int donehup = 0;
+static void usage __P((char *));
+static void handlehup __P((int));
+static void flushlogs __P((char *, FILE *));
+static void print_log __P((int, FILE *, char *, int));
+static void print_ipflog __P((FILE *, char *, int));
+static void print_natlog __P((FILE *, char *, int));
+static void print_statelog __P((FILE *, char *, int));
+static int read_log __P((int, int *, char *, int));
+static void write_pid __P((char *));
+static char *icmpname __P((u_int, u_int));
+static char *icmpname6 __P((u_int, u_int));
+static icmp_type_t *find_icmptype __P((int, icmp_type_t *, size_t));
+static icmp_subtype_t *find_icmpsubtype __P((int, icmp_subtype_t *, size_t));
+#ifdef __hpux
+static struct tm *get_tm __P((u_32_t));
+#else
+static struct tm *get_tm __P((time_t));
+#endif
+
+char *hostname __P((int, int, u_32_t *));
+char *portname __P((int, char *, u_int));
+int main __P((int, char *[]));
+
+static void logopts __P((int, char *));
+static void init_tabs __P((void));
+static char *getproto __P((u_int));
+
+static char **protocols = NULL;
+static char **udp_ports = NULL;
+static char **tcp_ports = NULL;
+static char *conf_file = NULL;
+
+
+#define OPT_SYSLOG 0x001
+#define OPT_RESOLVE 0x002
+#define OPT_HEXBODY 0x004
+#define OPT_VERBOSE 0x008
+#define OPT_HEXHDR 0x010
+#define OPT_TAIL 0x020
+#define OPT_NAT 0x080
+#define OPT_STATE 0x100
+#define OPT_FILTER 0x200
+#define OPT_PORTNUM 0x400
+#define OPT_LOGALL (OPT_NAT|OPT_STATE|OPT_FILTER)
+#define OPT_LOGBODY 0x800
+
+#define HOSTNAME_V4(a,b) hostname((a), 4, (u_32_t *)&(b))
+
+#ifndef LOGFAC
+#define LOGFAC LOG_LOCAL0
+#endif
+
+
+static icmp_subtype_t icmpunreachnames[] = {
+ { ICMP_UNREACH_NET, "net" },
+ { ICMP_UNREACH_HOST, "host" },
+ { ICMP_UNREACH_PROTOCOL, "protocol" },
+ { ICMP_UNREACH_PORT, "port" },
+ { ICMP_UNREACH_NEEDFRAG, "needfrag" },
+ { ICMP_UNREACH_SRCFAIL, "srcfail" },
+ { ICMP_UNREACH_NET_UNKNOWN, "net_unknown" },
+ { ICMP_UNREACH_HOST_UNKNOWN, "host_unknown" },
+ { ICMP_UNREACH_NET, "isolated" },
+ { ICMP_UNREACH_NET_PROHIB, "net_prohib" },
+ { ICMP_UNREACH_NET_PROHIB, "host_prohib" },
+ { ICMP_UNREACH_TOSNET, "tosnet" },
+ { ICMP_UNREACH_TOSHOST, "toshost" },
+ { ICMP_UNREACH_ADMIN_PROHIBIT, "admin_prohibit" },
+ { -2, NULL }
+};
+
+static icmp_subtype_t redirectnames[] = {
+ { ICMP_REDIRECT_NET, "net" },
+ { ICMP_REDIRECT_HOST, "host" },
+ { ICMP_REDIRECT_TOSNET, "tosnet" },
+ { ICMP_REDIRECT_TOSHOST, "toshost" },
+ { -2, NULL }
+};
+
+static icmp_subtype_t timxceednames[] = {
+ { ICMP_TIMXCEED_INTRANS, "transit" },
+ { ICMP_TIMXCEED_REASS, "reassem" },
+ { -2, NULL }
+};
+
+static icmp_subtype_t paramnames[] = {
+ { ICMP_PARAMPROB_ERRATPTR, "errata_pointer" },
+ { ICMP_PARAMPROB_OPTABSENT, "optmissing" },
+ { ICMP_PARAMPROB_LENGTH, "length" },
+ { -2, NULL }
+};
+
+static icmp_type_t icmptypes[] = {
+ { ICMP_ECHOREPLY, NULL, 0, "echoreply" },
+ { -1, NULL, 0, NULL },
+ { -1, NULL, 0, NULL },
+ { ICMP_UNREACH, icmpunreachnames,
+ IST_SZ(icmpunreachnames),"unreach" },
+ { ICMP_SOURCEQUENCH, NULL, 0, "sourcequench" },
+ { ICMP_REDIRECT, redirectnames,
+ IST_SZ(redirectnames), "redirect" },
+ { -1, NULL, 0, NULL },
+ { -1, NULL, 0, NULL },
+ { ICMP_ECHO, NULL, 0, "echo" },
+ { ICMP_ROUTERADVERT, NULL, 0, "routeradvert" },
+ { ICMP_ROUTERSOLICIT, NULL, 0, "routersolicit" },
+ { ICMP_TIMXCEED, timxceednames,
+ IST_SZ(timxceednames), "timxceed" },
+ { ICMP_PARAMPROB, paramnames,
+ IST_SZ(paramnames), "paramprob" },
+ { ICMP_TSTAMP, NULL, 0, "timestamp" },
+ { ICMP_TSTAMPREPLY, NULL, 0, "timestampreply" },
+ { ICMP_IREQ, NULL, 0, "inforeq" },
+ { ICMP_IREQREPLY, NULL, 0, "inforeply" },
+ { ICMP_MASKREQ, NULL, 0, "maskreq" },
+ { ICMP_MASKREPLY, NULL, 0, "maskreply" },
+ { -2, NULL, 0, NULL }
+};
+
+static icmp_subtype_t icmpredirect6[] = {
+ { ICMP6_DST_UNREACH_NOROUTE, "noroute" },
+ { ICMP6_DST_UNREACH_ADMIN, "admin" },
+ { ICMP6_DST_UNREACH_NOTNEIGHBOR, "neighbour" },
+ { ICMP6_DST_UNREACH_ADDR, "address" },
+ { ICMP6_DST_UNREACH_NOPORT, "noport" },
+ { -2, NULL }
+};
+
+static icmp_subtype_t icmptimexceed6[] = {
+ { ICMP6_TIME_EXCEED_TRANSIT, "intransit" },
+ { ICMP6_TIME_EXCEED_REASSEMBLY, "reassem" },
+ { -2, NULL }
+};
+
+static icmp_subtype_t icmpparamprob6[] = {
+ { ICMP6_PARAMPROB_HEADER, "header" },
+ { ICMP6_PARAMPROB_NEXTHEADER, "nextheader" },
+ { ICMP6_PARAMPROB_OPTION, "option" },
+ { -2, NULL }
+};
+
+static icmp_subtype_t icmpquerysubject6[] = {
+ { ICMP6_NI_SUBJ_IPV6, "ipv6" },
+ { ICMP6_NI_SUBJ_FQDN, "fqdn" },
+ { ICMP6_NI_SUBJ_IPV4, "ipv4" },
+ { -2, NULL },
+};
+
+static icmp_subtype_t icmpnodeinfo6[] = {
+ { ICMP6_NI_SUCCESS, "success" },
+ { ICMP6_NI_REFUSED, "refused" },
+ { ICMP6_NI_UNKNOWN, "unknown" },
+ { -2, NULL }
+};
+
+static icmp_subtype_t icmprenumber6[] = {
+ { ICMP6_ROUTER_RENUMBERING_COMMAND, "command" },
+ { ICMP6_ROUTER_RENUMBERING_RESULT, "result" },
+ { ICMP6_ROUTER_RENUMBERING_SEQNUM_RESET, "seqnum_reset" },
+ { -2, NULL }
+};
+
+static icmp_type_t icmptypes6[] = {
+ { 0, NULL, 0, NULL },
+ { ICMP6_DST_UNREACH, icmpredirect6,
+ IST_SZ(icmpredirect6), "unreach" },
+ { ICMP6_PACKET_TOO_BIG, NULL, 0, "toobig" },
+ { ICMP6_TIME_EXCEEDED, icmptimexceed6,
+ IST_SZ(icmptimexceed6), "timxceed" },
+ { ICMP6_PARAM_PROB, icmpparamprob6,
+ IST_SZ(icmpparamprob6), "paramprob" },
+ { ICMP6_ECHO_REQUEST, NULL, 0, "echo" },
+ { ICMP6_ECHO_REPLY, NULL, 0, "echoreply" },
+ { ICMP6_MEMBERSHIP_QUERY, icmpquerysubject6,
+ IST_SZ(icmpquerysubject6), "groupmemberquery" },
+ { ICMP6_MEMBERSHIP_REPORT,NULL, 0, "groupmemberreport" },
+ { ICMP6_MEMBERSHIP_REDUCTION,NULL, 0, "groupmemberterm" },
+ { ND_ROUTER_SOLICIT, NULL, 0, "routersolicit" },
+ { ND_ROUTER_ADVERT, NULL, 0, "routeradvert" },
+ { ND_NEIGHBOR_SOLICIT, NULL, 0, "neighborsolicit" },
+ { ND_NEIGHBOR_ADVERT, NULL, 0, "neighboradvert" },
+ { ND_REDIRECT, NULL, 0, "redirect" },
+ { ICMP6_ROUTER_RENUMBERING, icmprenumber6,
+ IST_SZ(icmprenumber6), "routerrenumber" },
+ { ICMP6_WRUREQUEST, NULL, 0, "whoareyourequest" },
+ { ICMP6_WRUREPLY, NULL, 0, "whoareyoureply" },
+ { ICMP6_FQDN_QUERY, NULL, 0, "fqdnquery" },
+ { ICMP6_FQDN_REPLY, NULL, 0, "fqdnreply" },
+ { ICMP6_NI_QUERY, icmpnodeinfo6,
+ IST_SZ(icmpnodeinfo6), "nodeinforequest" },
+ { ICMP6_NI_REPLY, NULL, 0, "nodeinforeply" },
+ { MLD6_MTRACE_RESP, NULL, 0, "mtraceresponse" },
+ { MLD6_MTRACE, NULL, 0, "mtracerequest" },
+ { -2, NULL, 0, NULL }
+};
+
+static icmp_subtype_t *find_icmpsubtype(type, table, tablesz)
+int type;
+icmp_subtype_t *table;
+size_t tablesz;
+{
+ icmp_subtype_t *ist;
+ int i;
+
+ if (tablesz < 2)
+ return NULL;
+
+ if ((type < 0) || (type > table[tablesz - 2].ist_val))
+ return NULL;
+
+ i = type;
+ if (table[type].ist_val == type)
+ return table + type;
+
+ for (i = 0, ist = table; ist->ist_val != -2; i++, ist++)
+ if (ist->ist_val == type)
+ return ist;
+ return NULL;
+}
+
+
+static icmp_type_t *find_icmptype(type, table, tablesz)
+int type;
+icmp_type_t *table;
+size_t tablesz;
+{
+ icmp_type_t *it;
+ int i;
+
+ if (tablesz < 2)
+ return NULL;
+
+ if ((type < 0) || (type > table[tablesz - 2].it_val))
+ return NULL;
+
+ i = type;
+ if (table[type].it_val == type)
+ return table + type;
+
+ for (i = 0, it = table; it->it_val != -2; i++, it++)
+ if (it->it_val == type)
+ return it;
+ return NULL;
+}
+
+
+static void handlehup(sig)
+int sig;
+{
+ signal(SIGHUP, handlehup);
+ donehup = 1;
+}
+
+
+static void init_tabs()
+{
+ struct protoent *p;
+ struct servent *s;
+ char *name, **tab;
+ int port, i;
+
+ if (protocols != NULL) {
+ for (i = 0; i < 256; i++)
+ if (protocols[i] != NULL) {
+ free(protocols[i]);
+ protocols[i] = NULL;
+ }
+ free(protocols);
+ protocols = NULL;
+ }
+ protocols = (char **)malloc(256 * sizeof(*protocols));
+ if (protocols != NULL) {
+ bzero((char *)protocols, 256 * sizeof(*protocols));
+
+ setprotoent(1);
+ while ((p = getprotoent()) != NULL)
+ if (p->p_proto >= 0 && p->p_proto <= 255 &&
+ p->p_name != NULL && protocols[p->p_proto] == NULL)
+ protocols[p->p_proto] = strdup(p->p_name);
+ endprotoent();
+ }
+
+ if (udp_ports != NULL) {
+ for (i = 0; i < 65536; i++)
+ if (udp_ports[i] != NULL) {
+ free(udp_ports[i]);
+ udp_ports[i] = NULL;
+ }
+ free(udp_ports);
+ udp_ports = NULL;
+ }
+ udp_ports = (char **)malloc(65536 * sizeof(*udp_ports));
+ if (udp_ports != NULL)
+ bzero((char *)udp_ports, 65536 * sizeof(*udp_ports));
+
+ if (tcp_ports != NULL) {
+ for (i = 0; i < 65536; i++)
+ if (tcp_ports[i] != NULL) {
+ free(tcp_ports[i]);
+ tcp_ports[i] = NULL;
+ }
+ free(tcp_ports);
+ tcp_ports = NULL;
+ }
+ tcp_ports = (char **)malloc(65536 * sizeof(*tcp_ports));
+ if (tcp_ports != NULL)
+ bzero((char *)tcp_ports, 65536 * sizeof(*tcp_ports));
+
+ setservent(1);
+ while ((s = getservent()) != NULL) {
+ if (s->s_proto == NULL)
+ continue;
+ else if (!strcmp(s->s_proto, "tcp")) {
+ port = ntohs(s->s_port);
+ name = s->s_name;
+ tab = tcp_ports;
+ } else if (!strcmp(s->s_proto, "udp")) {
+ port = ntohs(s->s_port);
+ name = s->s_name;
+ tab = udp_ports;
+ } else
+ continue;
+ if ((port < 0 || port > 65535) || (name == NULL))
+ continue;
+ if (tab != NULL)
+ tab[port] = strdup(name);
+ }
+ endservent();
+}
+
+
+static char *getproto(p)
+u_int p;
+{
+ static char pnum[4];
+ char *s;
+
+ p &= 0xff;
+ s = protocols ? protocols[p] : NULL;
+ if (s == NULL) {
+ sprintf(pnum, "%u", p);
+ s = pnum;
+ }
+ return s;
+}
+
+
+static int read_log(fd, lenp, buf, bufsize)
+int fd, bufsize, *lenp;
+char *buf;
+{
+ int nr;
+
+ nr = read(fd, buf, bufsize);
+ if (!nr)
+ return 2;
+ if ((nr < 0) && (errno != EINTR))
+ return -1;
+ *lenp = nr;
+ return 0;
+}
+
+
+char *hostname(res, v, ip)
+int res, v;
+u_32_t *ip;
+{
+# define MAX_INETA 16
+ static char hname[MAXHOSTNAMELEN + MAX_INETA + 3];
+#ifdef USE_INET6
+ static char hostbuf[MAXHOSTNAMELEN+1];
+#endif
+ struct hostent *hp;
+ struct in_addr ipa;
+
+ if (v == 4) {
+ ipa.s_addr = *ip;
+ if (!res)
+ return inet_ntoa(ipa);
+ hp = gethostbyaddr((char *)ip, sizeof(*ip), AF_INET);
+ if (!hp)
+ return inet_ntoa(ipa);
+ sprintf(hname, "%.*s[%s]", MAXHOSTNAMELEN, hp->h_name,
+ inet_ntoa(ipa));
+ return hname;
+ }
+#ifdef USE_INET6
+ (void) inet_ntop(AF_INET6, ip, hostbuf, sizeof(hostbuf) - 1);
+ hostbuf[MAXHOSTNAMELEN] = '\0';
+ return hostbuf;
+#else
+ return "IPv6";
+#endif
+}
+
+
+char *portname(res, proto, port)
+int res;
+char *proto;
+u_int port;
+{
+ static char pname[8];
+ char *s;
+
+ port = ntohs(port);
+ port &= 0xffff;
+ (void) sprintf(pname, "%u", port);
+ if (!res || (opts & OPT_PORTNUM))
+ return pname;
+ s = NULL;
+ if (!strcmp(proto, "tcp"))
+ s = tcp_ports[port];
+ else if (!strcmp(proto, "udp"))
+ s = udp_ports[port];
+ if (s == NULL)
+ s = pname;
+ return s;
+}
+
+
+static char *icmpname(type, code)
+u_int type;
+u_int code;
+{
+ static char name[80];
+ icmp_subtype_t *ist;
+ icmp_type_t *it;
+ char *s;
+
+ s = NULL;
+ it = find_icmptype(type, icmptypes, sizeof(icmptypes) / sizeof(*it));
+ if (it != NULL)
+ s = it->it_name;
+
+ if (s == NULL)
+ sprintf(name, "icmptype(%d)/", type);
+ else
+ sprintf(name, "%s/", s);
+
+ ist = NULL;
+ if (it != NULL && it->it_subtable != NULL)
+ ist = find_icmpsubtype(code, it->it_subtable, it->it_stsize);
+
+ if (ist != NULL && ist->ist_name != NULL)
+ strcat(name, ist->ist_name);
+ else
+ sprintf(name + strlen(name), "%d", code);
+
+ return name;
+}
+
+static char *icmpname6(type, code)
+u_int type;
+u_int code;
+{
+ static char name[80];
+ icmp_subtype_t *ist;
+ icmp_type_t *it;
+ char *s;
+
+ s = NULL;
+ it = find_icmptype(type, icmptypes6, sizeof(icmptypes6) / sizeof(*it));
+ if (it != NULL)
+ s = it->it_name;
+
+ if (s == NULL)
+ sprintf(name, "icmpv6type(%d)/", type);
+ else
+ sprintf(name, "%s/", s);
+
+ ist = NULL;
+ if (it != NULL && it->it_subtable != NULL)
+ ist = find_icmpsubtype(code, it->it_subtable, it->it_stsize);
+
+ if (ist != NULL && ist->ist_name != NULL)
+ strcat(name, ist->ist_name);
+ else
+ sprintf(name + strlen(name), "%d", code);
+
+ return name;
+}
+
+
+void dumphex(log, dopts, buf, len)
+FILE *log;
+int dopts;
+char *buf;
+int len;
+{
+ char hline[80];
+ int i, j, k;
+ u_char *s = (u_char *)buf, *t = (u_char *)hline;
+
+ if (buf == NULL || len == 0)
+ return;
+
+ *hline = '\0';
+
+ for (i = len, j = 0; i; i--, j++, s++) {
+ if (j && !(j & 0xf)) {
+ *t++ = '\n';
+ *t = '\0';
+ if (!(dopts & OPT_SYSLOG))
+ fputs(hline, log);
+ else
+ syslog(LOG_INFO, "%s", hline);
+ t = (u_char *)hline;
+ *t = '\0';
+ }
+ sprintf((char *)t, "%02x", *s & 0xff);
+ t += 2;
+ if (!((j + 1) & 0xf)) {
+ s -= 15;
+ sprintf((char *)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((char *)t, " ");
+ t += 7;
+ s -= j & 0xf;
+ for (k = j & 0xf; k; k--, s++)
+ *t++ = (ISPRINT(*s) ? *s : '.');
+ *t++ = '\n';
+ *t = '\0';
+ }
+ if (!(dopts & OPT_SYSLOG)) {
+ fputs(hline, log);
+ fflush(log);
+ } else
+ syslog(LOG_INFO, "%s", hline);
+}
+
+
+static struct tm *get_tm(sec)
+#ifdef __hpux
+u_32_t sec;
+#else
+time_t sec;
+#endif
+{
+ struct tm *tm;
+ time_t t;
+
+ t = sec;
+ tm = localtime(&t);
+ return tm;
+}
+
+static void print_natlog(log, buf, blen)
+FILE *log;
+char *buf;
+int blen;
+{
+ struct natlog *nl;
+ iplog_t *ipl = (iplog_t *)buf;
+ char *t = line;
+ struct tm *tm;
+ int res, i, len;
+ char *proto;
+
+ nl = (struct natlog *)((char *)ipl + sizeof(*ipl));
+ res = (opts & OPT_RESOLVE) ? 1 : 0;
+ tm = get_tm(ipl->ipl_sec);
+ len = sizeof(line);
+ if (!(opts & OPT_SYSLOG)) {
+ (void) strftime(t, len, "%d/%m/%Y ", tm);
+ i = strlen(t);
+ len -= i;
+ t += i;
+ }
+ (void) strftime(t, len, "%T", tm);
+ t += strlen(t);
+ (void) sprintf(t, ".%-.6ld @%hd ", ipl->ipl_usec, nl->nl_rule + 1);
+ t += strlen(t);
+
+ if (nl->nl_type == NL_NEWMAP)
+ strcpy(t, "NAT:MAP ");
+ else if (nl->nl_type == NL_NEWRDR)
+ strcpy(t, "NAT:RDR ");
+ else if (nl->nl_type == NL_FLUSH)
+ strcpy(t, "NAT:FLUSH ");
+ else if (nl->nl_type == NL_EXPIRE)
+ strcpy(t, "NAT:EXPIRE ");
+ else if (nl->nl_type == NL_NEWBIMAP)
+ strcpy(t, "NAT:BIMAP ");
+ else if (nl->nl_type == NL_NEWBLOCK)
+ strcpy(t, "NAT:MAPBLOCK ");
+ else if (nl->nl_type == NL_CLONE)
+ strcpy(t, "NAT:CLONE ");
+ else
+ sprintf(t, "Type: %d ", nl->nl_type);
+ t += strlen(t);
+
+ proto = getproto(nl->nl_p);
+
+ (void) sprintf(t, "%s,%s <- -> ", HOSTNAME_V4(res, nl->nl_inip),
+ portname(res, proto, (u_int)nl->nl_inport));
+ t += strlen(t);
+ (void) sprintf(t, "%s,%s ", HOSTNAME_V4(res, nl->nl_outip),
+ portname(res, proto, (u_int)nl->nl_outport));
+ t += strlen(t);
+ (void) sprintf(t, "[%s,%s]", HOSTNAME_V4(res, nl->nl_origip),
+ portname(res, proto, (u_int)nl->nl_origport));
+ t += strlen(t);
+ if (nl->nl_type == NL_EXPIRE) {
+#ifdef USE_QUAD_T
+ (void) sprintf(t, " Pkts %qd/%qd Bytes %qd/%qd",
+ (long long)nl->nl_pkts[0],
+ (long long)nl->nl_pkts[1],
+ (long long)nl->nl_bytes[0],
+ (long long)nl->nl_bytes[1]);
+#else
+ (void) sprintf(t, " Pkts %ld/%ld Bytes %ld/%ld",
+ nl->nl_pkts[0], nl->nl_pkts[1],
+ nl->nl_bytes[0], nl->nl_bytes[1]);
+#endif
+ t += strlen(t);
+ }
+
+ *t++ = '\n';
+ *t++ = '\0';
+ if (opts & OPT_SYSLOG)
+ syslog(LOG_INFO, "%s", line);
+ else
+ (void) fprintf(log, "%s", line);
+}
+
+
+static void print_statelog(log, buf, blen)
+FILE *log;
+char *buf;
+int blen;
+{
+ struct ipslog *sl;
+ iplog_t *ipl = (iplog_t *)buf;
+ char *t = line, *proto;
+ struct tm *tm;
+ int res, i, len;
+
+ sl = (struct ipslog *)((char *)ipl + sizeof(*ipl));
+ res = (opts & OPT_RESOLVE) ? 1 : 0;
+ tm = get_tm(ipl->ipl_sec);
+ len = sizeof(line);
+ if (!(opts & OPT_SYSLOG)) {
+ (void) strftime(t, len, "%d/%m/%Y ", tm);
+ i = strlen(t);
+ len -= i;
+ t += i;
+ }
+ (void) strftime(t, len, "%T", tm);
+ t += strlen(t);
+ (void) sprintf(t, ".%-.6ld ", ipl->ipl_usec);
+ t += strlen(t);
+
+ if (sl->isl_type == ISL_NEW)
+ strcpy(t, "STATE:NEW ");
+ else if (sl->isl_type == ISL_CLONE)
+ strcpy(t, "STATE:CLONED ");
+ else if (sl->isl_type == ISL_EXPIRE) {
+ if ((sl->isl_p == IPPROTO_TCP) &&
+ (sl->isl_state[0] > IPF_TCPS_ESTABLISHED ||
+ sl->isl_state[1] > IPF_TCPS_ESTABLISHED))
+ strcpy(t, "STATE:CLOSE ");
+ else
+ strcpy(t, "STATE:EXPIRE ");
+ } else if (sl->isl_type == ISL_FLUSH)
+ strcpy(t, "STATE:FLUSH ");
+ else if (sl->isl_type == ISL_INTERMEDIATE)
+ strcpy(t, "STATE:INTERMEDIATE ");
+ else if (sl->isl_type == ISL_REMOVE)
+ strcpy(t, "STATE:REMOVE ");
+ else if (sl->isl_type == ISL_KILLED)
+ strcpy(t, "STATE:KILLED ");
+ else
+ sprintf(t, "Type: %d ", sl->isl_type);
+ t += strlen(t);
+
+ proto = getproto(sl->isl_p);
+
+ if (sl->isl_p == IPPROTO_TCP || sl->isl_p == IPPROTO_UDP) {
+ (void) sprintf(t, "%s,%s -> ",
+ hostname(res, sl->isl_v, (u_32_t *)&sl->isl_src),
+ portname(res, proto, (u_int)sl->isl_sport));
+ t += strlen(t);
+ (void) sprintf(t, "%s,%s PR %s",
+ hostname(res, sl->isl_v, (u_32_t *)&sl->isl_dst),
+ portname(res, proto, (u_int)sl->isl_dport), proto);
+ } else if (sl->isl_p == IPPROTO_ICMP) {
+ (void) sprintf(t, "%s -> ", hostname(res, sl->isl_v,
+ (u_32_t *)&sl->isl_src));
+ t += strlen(t);
+ (void) sprintf(t, "%s PR icmp %d",
+ hostname(res, sl->isl_v, (u_32_t *)&sl->isl_dst),
+ sl->isl_itype);
+ } else if (sl->isl_p == IPPROTO_ICMPV6) {
+ (void) sprintf(t, "%s -> ", hostname(res, sl->isl_v,
+ (u_32_t *)&sl->isl_src));
+ t += strlen(t);
+ (void) sprintf(t, "%s PR icmpv6 %d",
+ hostname(res, sl->isl_v, (u_32_t *)&sl->isl_dst),
+ sl->isl_itype);
+ } else {
+ (void) sprintf(t, "%s -> ",
+ hostname(res, sl->isl_v, (u_32_t *)&sl->isl_src));
+ t += strlen(t);
+ (void) sprintf(t, "%s PR %s",
+ hostname(res, sl->isl_v, (u_32_t *)&sl->isl_dst),
+ proto);
+ }
+ t += strlen(t);
+ if (sl->isl_tag != FR_NOLOGTAG) {
+ (void) sprintf(t, " tag %u", sl->isl_tag);
+ t += strlen(t);
+ }
+ if (sl->isl_type != ISL_NEW) {
+ sprintf(t,
+#ifdef USE_QUAD_T
+#ifdef PRId64
+ " Forward: Pkts in %" PRId64 " Bytes in %" PRId64
+ " Pkts out %" PRId64 " Bytes out %" PRId64
+ " Backward: Pkts in %" PRId64 " Bytes in %" PRId64
+ " Pkts out %" PRId64 " Bytes out %" PRId64,
+#else
+ " Forward: Pkts in %qd Bytes in %qd Pkts out %qd Bytes out %qd Backward: Pkts in %qd Bytes in %qd Pkts out %qd Bytes out %qd",
+#endif /* PRId64 */
+#else
+ " Forward: Pkts in %ld Bytes in %ld Pkts out %ld Bytes out %ld Backward: Pkts in %ld Bytes in %ld Pkts out %ld Bytes out %ld",
+#endif
+ sl->isl_pkts[0], sl->isl_bytes[0],
+ sl->isl_pkts[1], sl->isl_bytes[1],
+ sl->isl_pkts[2], sl->isl_bytes[2],
+ sl->isl_pkts[3], sl->isl_bytes[3]);
+
+ t += strlen(t);
+ }
+
+ *t++ = '\n';
+ *t++ = '\0';
+ if (opts & OPT_SYSLOG)
+ syslog(LOG_INFO, "%s", line);
+ else
+ (void) fprintf(log, "%s", line);
+}
+
+
+static void print_log(logtype, log, buf, blen)
+FILE *log;
+char *buf;
+int logtype, blen;
+{
+ iplog_t *ipl;
+ char *bp = NULL, *bpo = NULL;
+ int psize;
+
+ while (blen > 0) {
+ ipl = (iplog_t *)buf;
+ if ((u_long)ipl & (sizeof(long)-1)) {
+ if (bp)
+ bpo = bp;
+ bp = (char *)malloc(blen);
+ bcopy((char *)ipl, bp, blen);
+ if (bpo) {
+ free(bpo);
+ bpo = NULL;
+ }
+ buf = bp;
+ continue;
+ }
+
+ psize = ipl->ipl_dsize;
+ if (psize > blen)
+ break;
+
+ if (binarylog) {
+ fwrite(buf, psize, 1, binarylog);
+ fflush(binarylog);
+ }
+
+ if (logtype == IPL_LOGIPF) {
+ if (ipl->ipl_magic == IPL_MAGIC)
+ print_ipflog(log, buf, psize);
+
+ } else if (logtype == IPL_LOGNAT) {
+ if (ipl->ipl_magic == IPL_MAGIC_NAT)
+ print_natlog(log, buf, psize);
+
+ } else if (logtype == IPL_LOGSTATE) {
+ if (ipl->ipl_magic == IPL_MAGIC_STATE)
+ print_statelog(log, buf, psize);
+ }
+
+ blen -= psize;
+ buf += psize;
+ }
+ if (bp)
+ free(bp);
+ return;
+}
+
+
+static void print_ipflog(log, buf, blen)
+FILE *log;
+char *buf;
+int blen;
+{
+ tcphdr_t *tp;
+ struct icmp *ic;
+ struct icmp *icmp;
+ struct tm *tm;
+ char *t, *proto;
+ int i, v, lvl, res, len, off, plen, ipoff, defaction;
+ ip_t *ipc, *ip;
+ u_32_t *s, *d;
+ u_short hl, p;
+ ipflog_t *ipf;
+ iplog_t *ipl;
+#ifdef USE_INET6
+ ip6_t *ip6;
+#endif
+
+ ipl = (iplog_t *)buf;
+ ipf = (ipflog_t *)((char *)buf + sizeof(*ipl));
+ ip = (ip_t *)((char *)ipf + sizeof(*ipf));
+ v = IP_V(ip);
+ res = (opts & OPT_RESOLVE) ? 1 : 0;
+ t = line;
+ *t = '\0';
+ tm = get_tm(ipl->ipl_sec);
+
+ len = sizeof(line);
+ if (!(opts & OPT_SYSLOG)) {
+ (void) strftime(t, len, "%d/%m/%Y ", tm);
+ i = strlen(t);
+ len -= i;
+ t += i;
+ }
+ (void) strftime(t, len, "%T", tm);
+ t += strlen(t);
+ (void) sprintf(t, ".%-.6ld ", ipl->ipl_usec);
+ t += strlen(t);
+ if (ipl->ipl_count > 1) {
+ (void) sprintf(t, "%dx ", ipl->ipl_count);
+ t += strlen(t);
+ }
+#if (defined(MENTAT) || \
+ (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199603)) || \
+ (defined(__FreeBSD__) && (__FreeBSD_version >= 501113)) || \
+ (defined(OpenBSD) && (OpenBSD >= 199603))) || defined(linux)
+ {
+ char ifname[sizeof(ipf->fl_ifname) + 1];
+
+ strncpy(ifname, ipf->fl_ifname, sizeof(ipf->fl_ifname));
+ ifname[sizeof(ipf->fl_ifname)] = '\0';
+ (void) sprintf(t, "%s", ifname);
+ t += strlen(t);
+# if defined(MENTAT) || defined(linux)
+ if (ISALPHA(*(t - 1))) {
+ sprintf(t, "%d", ipf->fl_unit);
+ t += strlen(t);
+ }
+# endif
+ }
+#else
+ for (len = 0; len < 3; len++)
+ if (ipf->fl_ifname[len] == '\0')
+ break;
+ if (ipf->fl_ifname[len])
+ len++;
+ (void) sprintf(t, "%*.*s%u", len, len, ipf->fl_ifname, ipf->fl_unit);
+ t += strlen(t);
+#endif
+#ifdef __sgi
+ if ((ipf->fl_group[0] == 255) && (ipf->fl_group[1] == '\0'))
+#else
+ if ((ipf->fl_group[0] == -1) && (ipf->fl_group[1] == '\0'))
+#endif
+ strcat(t, " @-1:");
+ else if (ipf->fl_group[0] == '\0')
+ (void) strcpy(t, " @0:");
+ else
+ (void) sprintf(t, " @%s:", ipf->fl_group);
+ t += strlen(t);
+ if (ipf->fl_rule == 0xffffffff)
+ strcat(t, "-1 ");
+ else
+ (void) sprintf(t, "%u ", ipf->fl_rule + 1);
+ t += strlen(t);
+
+ lvl = LOG_NOTICE;
+
+ if (ipf->fl_lflags & FI_SHORT) {
+ *t++ = 'S';
+ lvl = LOG_ERR;
+ }
+
+ if (FR_ISPASS(ipf->fl_flags)) {
+ if (ipf->fl_flags & FR_LOGP)
+ *t++ = 'p';
+ else
+ *t++ = 'P';
+ } else if (FR_ISBLOCK(ipf->fl_flags)) {
+ if (ipf->fl_flags & FR_LOGB)
+ *t++ = 'b';
+ else
+ *t++ = 'B';
+ lvl = LOG_WARNING;
+ } else if ((ipf->fl_flags & FR_LOGMASK) == FR_LOG) {
+ *t++ = 'L';
+ lvl = LOG_INFO;
+ } else if (ipf->fl_flags & FF_LOGNOMATCH) {
+ *t++ = 'n';
+ } else {
+ *t++ = '?';
+ lvl = LOG_EMERG;
+ }
+ if (ipf->fl_loglevel != 0xffff)
+ lvl = ipf->fl_loglevel;
+ *t++ = ' ';
+ *t = '\0';
+
+ if (v == 6) {
+#ifdef USE_INET6
+ off = 0;
+ ipoff = 0;
+ hl = sizeof(ip6_t);
+ ip6 = (ip6_t *)ip;
+ p = (u_short)ip6->ip6_nxt;
+ s = (u_32_t *)&ip6->ip6_src;
+ d = (u_32_t *)&ip6->ip6_dst;
+ plen = hl + ntohs(ip6->ip6_plen);
+#else
+ sprintf(t, "ipv6");
+ goto printipflog;
+#endif
+ } else if (v == 4) {
+ hl = IP_HL(ip) << 2;
+ ipoff = ip->ip_off;
+ off = ipoff & IP_OFFMASK;
+ p = (u_short)ip->ip_p;
+ s = (u_32_t *)&ip->ip_src;
+ d = (u_32_t *)&ip->ip_dst;
+ plen = ip->ip_len;
+ } else {
+ goto printipflog;
+ }
+ proto = getproto(p);
+
+ if ((p == IPPROTO_TCP || p == IPPROTO_UDP) && !off) {
+ tp = (tcphdr_t *)((char *)ip + hl);
+ if (!(ipf->fl_lflags & FI_SHORT)) {
+ (void) sprintf(t, "%s,%s -> ", hostname(res, v, s),
+ portname(res, proto, (u_int)tp->th_sport));
+ t += strlen(t);
+ (void) sprintf(t, "%s,%s PR %s len %hu %hu",
+ hostname(res, v, d),
+ portname(res, proto, (u_int)tp->th_dport),
+ proto, hl, plen);
+ t += strlen(t);
+
+ if (p == IPPROTO_TCP) {
+ *t++ = ' ';
+ *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)(ntohl(tp->th_seq)),
+ (u_long)(ntohl(tp->th_ack)),
+ ntohs(tp->th_win));
+ t += strlen(t);
+ }
+ }
+ *t = '\0';
+ } else {
+ (void) sprintf(t, "%s -> ", hostname(res, v, s));
+ t += strlen(t);
+ (void) sprintf(t, "%s PR %s len %hu %hu",
+ hostname(res, v, d), proto, hl, plen);
+ }
+ } else if ((p == IPPROTO_ICMPV6) && !off && (v == 6)) {
+ ic = (struct icmp *)((char *)ip + hl);
+ (void) sprintf(t, "%s -> ", hostname(res, v, s));
+ t += strlen(t);
+ (void) sprintf(t, "%s PR icmpv6 len %hu %hu icmpv6 %s",
+ hostname(res, v, d), hl, plen,
+ icmpname6(ic->icmp_type, ic->icmp_code));
+ } else if ((p == IPPROTO_ICMP) && !off && (v == 4)) {
+ ic = (struct icmp *)((char *)ip + hl);
+ (void) sprintf(t, "%s -> ", hostname(res, v, s));
+ t += strlen(t);
+ (void) sprintf(t, "%s PR icmp len %hu %hu icmp %s",
+ hostname(res, v, d), hl, plen,
+ icmpname(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;
+ i = ntohs(ipc->ip_len);
+ /*
+ * XXX - try to guess endian of ip_len in ICMP
+ * returned data.
+ */
+ if (i > 1500)
+ i = ipc->ip_len;
+ ipoff = ntohs(ipc->ip_off);
+ proto = getproto(ipc->ip_p);
+
+ if (!(ipoff & IP_OFFMASK) &&
+ ((ipc->ip_p == IPPROTO_TCP) ||
+ (ipc->ip_p == IPPROTO_UDP))) {
+ tp = (tcphdr_t *)((char *)ipc + hl);
+ t += strlen(t);
+ (void) sprintf(t, " for %s,%s -",
+ HOSTNAME_V4(res, ipc->ip_src),
+ portname(res, proto,
+ (u_int)tp->th_sport));
+ t += strlen(t);
+ (void) sprintf(t, " %s,%s PR %s len %hu %hu",
+ HOSTNAME_V4(res, ipc->ip_dst),
+ portname(res, proto,
+ (u_int)tp->th_dport),
+ proto, IP_HL(ipc) << 2, i);
+ } else if (!(ipoff & IP_OFFMASK) &&
+ (ipc->ip_p == IPPROTO_ICMP)) {
+ icmp = (icmphdr_t *)((char *)ipc + hl);
+
+ t += strlen(t);
+ (void) sprintf(t, " for %s -",
+ HOSTNAME_V4(res, ipc->ip_src));
+ t += strlen(t);
+ (void) sprintf(t,
+ " %s PR icmp len %hu %hu icmp %d/%d",
+ HOSTNAME_V4(res, ipc->ip_dst),
+ IP_HL(ipc) << 2, i,
+ icmp->icmp_type, icmp->icmp_code);
+ } else {
+ t += strlen(t);
+ (void) sprintf(t, " for %s -",
+ HOSTNAME_V4(res, ipc->ip_src));
+ t += strlen(t);
+ (void) sprintf(t, " %s PR %s len %hu (%hu)",
+ HOSTNAME_V4(res, ipc->ip_dst), proto,
+ IP_HL(ipc) << 2, i);
+ t += strlen(t);
+ if (ipoff & IP_OFFMASK) {
+ (void) sprintf(t,
+ "(frag %d:%hu@%hu%s%s)",
+ ntohs(ipc->ip_id),
+ i - (IP_HL(ipc) << 2),
+ (ipoff & IP_OFFMASK) << 3,
+ ipoff & IP_MF ? "+" : "",
+ ipoff & IP_DF ? "-" : "");
+ }
+ }
+
+ }
+ } else {
+ (void) sprintf(t, "%s -> ", hostname(res, v, s));
+ t += strlen(t);
+ (void) sprintf(t, "%s PR %s len %hu (%hu)",
+ hostname(res, v, d), proto, hl, plen);
+ t += strlen(t);
+ if (off & IP_OFFMASK)
+ (void) sprintf(t, " (frag %d:%hu@%hu%s%s)",
+ ntohs(ip->ip_id),
+ plen - hl, (off & IP_OFFMASK) << 3,
+ ipoff & IP_MF ? "+" : "",
+ ipoff & IP_DF ? "-" : "");
+ }
+ t += strlen(t);
+
+printipflog:
+ if (ipf->fl_flags & FR_KEEPSTATE) {
+ (void) strcpy(t, " K-S");
+ t += strlen(t);
+ }
+
+ if (ipf->fl_flags & FR_KEEPFRAG) {
+ (void) strcpy(t, " K-F");
+ t += strlen(t);
+ }
+
+ if (ipf->fl_dir == 0)
+ strcpy(t, " IN");
+ else if (ipf->fl_dir == 1)
+ strcpy(t, " OUT");
+ t += strlen(t);
+ if (ipf->fl_logtag != 0) {
+ sprintf(t, " log-tag %d", ipf->fl_logtag);
+ t += strlen(t);
+ }
+ if (ipf->fl_nattag.ipt_num[0] != 0) {
+ strcpy(t, " nat-tag ");
+ t += strlen(t);
+ strncpy(t, ipf->fl_nattag.ipt_tag, sizeof(ipf->fl_nattag));
+ t += strlen(t);
+ }
+ if ((ipf->fl_lflags & FI_LOWTTL) != 0) {
+ strcpy(t, " low-ttl");
+ t += 8;
+ }
+ if ((ipf->fl_lflags & FI_OOW) != 0) {
+ strcpy(t, " OOW");
+ t += 4;
+ }
+ if ((ipf->fl_lflags & FI_BAD) != 0) {
+ strcpy(t, " bad");
+ t += 4;
+ }
+ if ((ipf->fl_lflags & FI_NATED) != 0) {
+ strcpy(t, " NAT");
+ t += 4;
+ }
+ if ((ipf->fl_lflags & FI_BADNAT) != 0) {
+ strcpy(t, " bad-NAT");
+ t += 8;
+ }
+ if ((ipf->fl_lflags & FI_BADSRC) != 0) {
+ strcpy(t, " bad-src");
+ t += 8;
+ }
+ if ((ipf->fl_lflags & FI_MULTICAST) != 0) {
+ strcpy(t, " multicast");
+ t += 10;
+ }
+ if ((ipf->fl_lflags & FI_BROADCAST) != 0) {
+ strcpy(t, " broadcast");
+ t += 10;
+ }
+ if ((ipf->fl_lflags & (FI_MULTICAST|FI_BROADCAST|FI_MBCAST)) ==
+ FI_MBCAST) {
+ strcpy(t, " mbcast");
+ t += 7;
+ }
+ *t++ = '\n';
+ *t++ = '\0';
+ defaction = 0;
+ if (conf_file != NULL)
+ defaction = check_action(buf, line, opts, lvl);
+ if (defaction == 0) {
+ if (opts & OPT_SYSLOG)
+ syslog(lvl, "%s", line);
+ else
+ (void) fprintf(log, "%s", line);
+ if (opts & OPT_HEXHDR)
+ dumphex(log, opts, buf,
+ sizeof(iplog_t) + sizeof(*ipf));
+ if (opts & OPT_HEXBODY)
+ dumphex(log, opts, (char *)ip,
+ ipf->fl_plen + ipf->fl_hlen);
+ else if ((opts & OPT_LOGBODY) && (ipf->fl_flags & FR_LOGBODY))
+ dumphex(log, opts, (char *)ip + ipf->fl_hlen,
+ ipf->fl_plen);
+ }
+}
+
+
+static void usage(prog)
+char *prog;
+{
+ fprintf(stderr, "%s: [-NFhstvxX] [-f <logfile>]\n", prog);
+ exit(1);
+}
+
+
+static void write_pid(file)
+char *file;
+{
+ FILE *fp = NULL;
+ int fd;
+
+ if ((fd = open(file, O_CREAT|O_TRUNC|O_WRONLY, 0644)) >= 0) {
+ fp = fdopen(fd, "w");
+ if (fp == NULL) {
+ close(fd);
+ fprintf(stderr,
+ "unable to open/create pid file: %s\n", file);
+ return;
+ }
+ fprintf(fp, "%d", getpid());
+ fclose(fp);
+ }
+}
+
+
+static void flushlogs(file, log)
+char *file;
+FILE *log;
+{
+ int fd, flushed = 0;
+
+ if ((fd = open(file, O_RDWR)) == -1) {
+ (void) fprintf(stderr, "%s: open: %s\n",
+ file, STRERROR(errno));
+ exit(1);
+ }
+
+ if (ioctl(fd, SIOCIPFFB, &flushed) == 0) {
+ printf("%d bytes flushed from log buffer\n",
+ flushed);
+ fflush(stdout);
+ } else
+ perror("SIOCIPFFB");
+ (void) close(fd);
+
+ if (flushed) {
+ if (opts & OPT_SYSLOG)
+ syslog(LOG_INFO, "%d bytes flushed from log\n",
+ flushed);
+ else if (log != stdout)
+ fprintf(log, "%d bytes flushed from log\n", flushed);
+ }
+}
+
+
+static void logopts(turnon, options)
+int turnon;
+char *options;
+{
+ int flags = 0;
+ char *s;
+
+ for (s = options; *s; s++)
+ {
+ switch (*s)
+ {
+ case 'N' :
+ flags |= OPT_NAT;
+ break;
+ case 'S' :
+ flags |= OPT_STATE;
+ break;
+ case 'I' :
+ flags |= OPT_FILTER;
+ break;
+ default :
+ fprintf(stderr, "Unknown log option %c\n", *s);
+ exit(1);
+ }
+ }
+
+ if (turnon)
+ opts |= flags;
+ else
+ opts &= ~(flags);
+}
+
+
+int main(argc, argv)
+int argc;
+char *argv[];
+{
+ struct stat sb;
+ FILE *log = stdout;
+ FILE *fp;
+ int fd[3], doread, n, i;
+ int tr, nr, regular[3], c;
+ int fdt[3], devices = 0, make_daemon = 0;
+ char buf[DEFAULT_IPFLOGSIZE], *iplfile[3], *s;
+ extern int optind;
+ extern char *optarg;
+
+ fd[0] = fd[1] = fd[2] = -1;
+ fdt[0] = fdt[1] = fdt[2] = -1;
+ iplfile[0] = IPL_NAME;
+ iplfile[1] = IPNAT_NAME;
+ iplfile[2] = IPSTATE_NAME;
+
+ while ((c = getopt(argc, argv, "?abB:C:Df:FhnN:o:O:pP:sS:tvxX")) != -1)
+ switch (c)
+ {
+ case 'a' :
+ opts |= OPT_LOGALL;
+ fdt[0] = IPL_LOGIPF;
+ fdt[1] = IPL_LOGNAT;
+ fdt[2] = IPL_LOGSTATE;
+ break;
+ case 'b' :
+ opts |= OPT_LOGBODY;
+ break;
+ case 'B' :
+ binarylogfile = optarg;
+ binarylog = fopen(optarg, "a");
+ break;
+ case 'C' :
+ conf_file = optarg;
+ break;
+ case 'D' :
+ make_daemon = 1;
+ break;
+ case 'f' : case 'I' :
+ opts |= OPT_FILTER;
+ fdt[0] = IPL_LOGIPF;
+ iplfile[0] = optarg;
+ break;
+ case 'F' :
+ flushlogs(iplfile[0], log);
+ flushlogs(iplfile[1], log);
+ flushlogs(iplfile[2], log);
+ break;
+ case 'n' :
+ opts |= OPT_RESOLVE;
+ break;
+ case 'N' :
+ opts |= OPT_NAT;
+ fdt[1] = IPL_LOGNAT;
+ iplfile[1] = optarg;
+ break;
+ case 'o' : case 'O' :
+ logopts(c == 'o', optarg);
+ fdt[0] = fdt[1] = fdt[2] = -1;
+ if (opts & OPT_FILTER)
+ fdt[0] = IPL_LOGIPF;
+ if (opts & OPT_NAT)
+ fdt[1] = IPL_LOGNAT;
+ if (opts & OPT_STATE)
+ fdt[2] = IPL_LOGSTATE;
+ break;
+ case 'p' :
+ opts |= OPT_PORTNUM;
+ break;
+ case 'P' :
+ pidfile = optarg;
+ break;
+ case 's' :
+ s = strrchr(argv[0], '/');
+ if (s == NULL)
+ s = argv[0];
+ else
+ s++;
+ openlog(s, LOG_NDELAY|LOG_PID, LOGFAC);
+ s = NULL;
+ opts |= OPT_SYSLOG;
+ log = NULL;
+ break;
+ case 'S' :
+ opts |= OPT_STATE;
+ fdt[2] = IPL_LOGSTATE;
+ iplfile[2] = optarg;
+ break;
+ case 't' :
+ opts |= OPT_TAIL;
+ break;
+ case 'v' :
+ opts |= OPT_VERBOSE;
+ break;
+ case 'x' :
+ opts |= OPT_HEXBODY;
+ break;
+ case 'X' :
+ opts |= OPT_HEXHDR;
+ break;
+ default :
+ case 'h' :
+ case '?' :
+ usage(argv[0]);
+ }
+
+ init_tabs();
+ if (conf_file)
+ if (load_config(conf_file) == -1)
+ exit(1);
+
+ /*
+ * Default action is to only open the filter log file.
+ */
+ if ((fdt[0] == -1) && (fdt[1] == -1) && (fdt[2] == -1))
+ fdt[0] = IPL_LOGIPF;
+
+ for (i = 0; i < 3; i++) {
+ if (fdt[i] == -1)
+ continue;
+ if (!strcmp(iplfile[i], "-"))
+ fd[i] = 0;
+ else {
+ if ((fd[i] = open(iplfile[i], O_RDONLY)) == -1) {
+ (void) fprintf(stderr,
+ "%s: open: %s\n", iplfile[i],
+ STRERROR(errno));
+ exit(1);
+ /* NOTREACHED */
+ }
+ if (fstat(fd[i], &sb) == -1) {
+ (void) fprintf(stderr, "%d: fstat: %s\n",
+ fd[i], STRERROR(errno));
+ exit(1);
+ /* NOTREACHED */
+ }
+ if (!(regular[i] = !S_ISCHR(sb.st_mode)))
+ devices++;
+ }
+ }
+
+ if (!(opts & OPT_SYSLOG)) {
+ logfile = argv[optind];
+ log = logfile ? fopen(logfile, "a") : stdout;
+ if (log == NULL) {
+ (void) fprintf(stderr, "%s: fopen: %s\n",
+ argv[optind], STRERROR(errno));
+ exit(1);
+ /* NOTREACHED */
+ }
+ setvbuf(log, NULL, _IONBF, 0);
+ } else
+ log = NULL;
+
+ if (make_daemon && ((log != stdout) || (opts & OPT_SYSLOG))) {
+#if BSD >= 199306
+ daemon(0, !(opts & OPT_SYSLOG));
+#else
+ int pid;
+ if ((pid = fork()) > 0)
+ exit(0);
+ if (pid < 0) {
+ (void) fprintf(stderr, "%s: fork() failed: %s\n",
+ argv[0], STRERROR(errno));
+ exit(1);
+ /* NOTREACHED */
+ }
+ setsid();
+ if ((opts & OPT_SYSLOG))
+ close(2);
+#endif /* !BSD */
+ close(0);
+ close(1);
+ }
+ write_pid(pidfile);
+
+ signal(SIGHUP, handlehup);
+
+ for (doread = 1; doread; ) {
+ nr = 0;
+
+ for (i = 0; i < 3; i++) {
+ tr = 0;
+ if (fdt[i] == -1)
+ continue;
+ if (!regular[i]) {
+ if (ioctl(fd[i], FIONREAD, &tr) == -1) {
+ if (opts & OPT_SYSLOG)
+ syslog(LOG_CRIT,
+ "ioctl(FIONREAD): %m");
+ else
+ perror("ioctl(FIONREAD)");
+ exit(1);
+ /* NOTREACHED */
+ }
+ } else {
+ tr = (lseek(fd[i], 0, SEEK_CUR) < sb.st_size);
+ if (!tr && !(opts & OPT_TAIL))
+ doread = 0;
+ }
+ if (!tr)
+ continue;
+ nr += tr;
+
+ tr = read_log(fd[i], &n, buf, sizeof(buf));
+ if (donehup) {
+ if (logfile && (fp = fopen(logfile, "a"))) {
+ fclose(log);
+ log = fp;
+ }
+ if (binarylogfile && (fp = fopen(binarylogfile, "a"))) {
+ fclose(binarylog);
+ binarylog = fp;
+ }
+ init_tabs();
+ if (conf_file != NULL)
+ load_config(conf_file);
+ donehup = 0;
+ }
+
+ switch (tr)
+ {
+ case -1 :
+ if (opts & OPT_SYSLOG)
+ syslog(LOG_CRIT, "read: %m\n");
+ else
+ perror("read");
+ doread = 0;
+ break;
+ case 1 :
+ if (opts & OPT_SYSLOG)
+ syslog(LOG_CRIT, "aborting logging\n");
+ else
+ fprintf(log, "aborting logging\n");
+ doread = 0;
+ break;
+ case 2 :
+ break;
+ case 0 :
+ if (n > 0) {
+ print_log(fdt[i], log, buf, n);
+ if (!(opts & OPT_SYSLOG))
+ fflush(log);
+ }
+ break;
+ }
+ }
+ if (!nr && ((opts & OPT_TAIL) || devices))
+ sleep(1);
+ }
+ return(0);
+ /* NOTREACHED */
+}
diff --git a/contrib/ipfilter/tools/ipmon_y.y b/contrib/ipfilter/tools/ipmon_y.y
new file mode 100644
index 0000000..8b30028
--- /dev/null
+++ b/contrib/ipfilter/tools/ipmon_y.y
@@ -0,0 +1,694 @@
+/* $NetBSD$ */
+
+%{
+#include "ipf.h"
+#include <syslog.h>
+#undef OPT_NAT
+#undef OPT_VERBOSE
+#include "ipmon_l.h"
+#include "ipmon.h"
+
+#define YYDEBUG 1
+
+extern void yyerror __P((char *));
+extern int yyparse __P((void));
+extern int yylex __P((void));
+extern int yydebug;
+extern FILE *yyin;
+extern int yylineNum;
+
+typedef struct opt {
+ struct opt *o_next;
+ int o_line;
+ int o_type;
+ int o_num;
+ char *o_str;
+ struct in_addr o_ip;
+} opt_t;
+
+static void build_action __P((struct opt *));
+static opt_t *new_opt __P((int));
+static void free_action __P((ipmon_action_t *));
+
+static ipmon_action_t *alist = NULL;
+%}
+
+%union {
+ char *str;
+ u_32_t num;
+ struct in_addr addr;
+ struct opt *opt;
+ union i6addr ip6;
+}
+
+%token <num> YY_NUMBER YY_HEX
+%token <str> YY_STR
+%token <ip6> YY_IPV6
+%token YY_COMMENT
+%token YY_CMP_EQ YY_CMP_NE YY_CMP_LE YY_CMP_GE YY_CMP_LT YY_CMP_GT
+%token YY_RANGE_OUT YY_RANGE_IN
+
+%token IPM_MATCH IPM_BODY IPM_COMMENT IPM_DIRECTION IPM_DSTIP IPM_DSTPORT
+%token IPM_EVERY IPM_EXECUTE IPM_GROUP IPM_INTERFACE IPM_IN IPM_NO IPM_OUT
+%token IPM_PACKET IPM_PACKETS IPM_POOL IPM_PROTOCOL IPM_RESULT IPM_RULE
+%token IPM_SECOND IPM_SECONDS IPM_SRCIP IPM_SRCPORT IPM_LOGTAG IPM_WITH
+%token IPM_DO IPM_SAVE IPM_SYSLOG IPM_NOTHING IPM_RAW IPM_TYPE IPM_NAT
+%token IPM_STATE IPM_NATTAG IPM_IPF
+%type <addr> ipv4
+%type <opt> direction dstip dstport every execute group interface
+%type <opt> protocol result rule srcip srcport logtag matching
+%type <opt> matchopt nattag type doopt doing save syslog nothing
+%type <num> saveopts saveopt typeopt
+
+%%
+file: line
+ | assign
+ | file line
+ | file assign
+ ;
+
+line: IPM_MATCH '{' matching '}' IPM_DO '{' doing '}' ';'
+ { build_action($3); resetlexer(); }
+ | IPM_COMMENT
+ | YY_COMMENT
+ ;
+
+assign: YY_STR assigning YY_STR ';' { set_variable($1, $3);
+ resetlexer();
+ free($1);
+ free($3);
+ }
+ ;
+
+assigning:
+ '=' { yyvarnext = 1; }
+ ;
+
+matching:
+ matchopt { $$ = $1; }
+ | matchopt ',' matching { $1->o_next = $3; $$ = $1; }
+ ;
+
+matchopt:
+ direction { $$ = $1; }
+ | dstip { $$ = $1; }
+ | dstport { $$ = $1; }
+ | every { $$ = $1; }
+ | group { $$ = $1; }
+ | interface { $$ = $1; }
+ | protocol { $$ = $1; }
+ | result { $$ = $1; }
+ | rule { $$ = $1; }
+ | srcip { $$ = $1; }
+ | srcport { $$ = $1; }
+ | logtag { $$ = $1; }
+ | nattag { $$ = $1; }
+ | type { $$ = $1; }
+ ;
+
+doing:
+ doopt { $$ = $1; }
+ | doopt ',' doing { $1->o_next = $3; $$ = $1; }
+ ;
+
+doopt:
+ execute { $$ = $1; }
+ | save { $$ = $1; }
+ | syslog { $$ = $1; }
+ | nothing { $$ = $1; }
+ ;
+
+direction:
+ IPM_DIRECTION '=' IPM_IN { $$ = new_opt(IPM_DIRECTION);
+ $$->o_num = IPM_IN; }
+ | IPM_DIRECTION '=' IPM_OUT { $$ = new_opt(IPM_DIRECTION);
+ $$->o_num = IPM_OUT; }
+ ;
+
+dstip: IPM_DSTIP '=' ipv4 '/' YY_NUMBER { $$ = new_opt(IPM_DSTIP);
+ $$->o_ip = $3;
+ $$->o_num = $5; }
+ ;
+
+dstport:
+ IPM_DSTPORT '=' YY_NUMBER { $$ = new_opt(IPM_DSTPORT);
+ $$->o_num = $3; }
+ | IPM_DSTPORT '=' YY_STR { $$ = new_opt(IPM_DSTPORT);
+ $$->o_str = $3; }
+ ;
+
+every: IPM_EVERY IPM_SECOND { $$ = new_opt(IPM_SECOND);
+ $$->o_num = 1; }
+ | IPM_EVERY YY_NUMBER IPM_SECONDS { $$ = new_opt(IPM_SECOND);
+ $$->o_num = $2; }
+ | IPM_EVERY IPM_PACKET { $$ = new_opt(IPM_PACKET);
+ $$->o_num = 1; }
+ | IPM_EVERY YY_NUMBER IPM_PACKETS { $$ = new_opt(IPM_PACKET);
+ $$->o_num = $2; }
+ ;
+
+group: IPM_GROUP '=' YY_NUMBER { $$ = new_opt(IPM_GROUP);
+ $$->o_num = $3; }
+ | IPM_GROUP '=' YY_STR { $$ = new_opt(IPM_GROUP);
+ $$->o_str = $3; }
+ ;
+
+interface:
+ IPM_INTERFACE '=' YY_STR { $$ = new_opt(IPM_INTERFACE);
+ $$->o_str = $3; }
+ ;
+
+logtag: IPM_LOGTAG '=' YY_NUMBER { $$ = new_opt(IPM_LOGTAG);
+ $$->o_num = $3; }
+ ;
+
+nattag: IPM_NATTAG '=' YY_STR { $$ = new_opt(IPM_NATTAG);
+ $$->o_str = $3; }
+ ;
+
+protocol:
+ IPM_PROTOCOL '=' YY_NUMBER { $$ = new_opt(IPM_PROTOCOL);
+ $$->o_num = $3; }
+ | IPM_PROTOCOL '=' YY_STR { $$ = new_opt(IPM_PROTOCOL);
+ $$->o_num = getproto($3);
+ free($3);
+ }
+ ;
+
+result: IPM_RESULT '=' YY_STR { $$ = new_opt(IPM_RESULT);
+ $$->o_str = $3; }
+ ;
+
+rule: IPM_RULE '=' YY_NUMBER { $$ = new_opt(IPM_RULE);
+ $$->o_num = YY_NUMBER; }
+ ;
+
+srcip: IPM_SRCIP '=' ipv4 '/' YY_NUMBER { $$ = new_opt(IPM_SRCIP);
+ $$->o_ip = $3;
+ $$->o_num = $5; }
+ ;
+
+srcport:
+ IPM_SRCPORT '=' YY_NUMBER { $$ = new_opt(IPM_SRCPORT);
+ $$->o_num = $3; }
+ | IPM_SRCPORT '=' YY_STR { $$ = new_opt(IPM_SRCPORT);
+ $$->o_str = $3; }
+ ;
+
+type: IPM_TYPE '=' typeopt { $$ = new_opt(IPM_TYPE);
+ $$->o_num = $3; }
+ ;
+
+typeopt:
+ IPM_IPF { $$ = IPL_MAGIC; }
+ | IPM_NAT { $$ = IPL_MAGIC_NAT; }
+ | IPM_STATE { $$ = IPL_MAGIC_STATE; }
+ ;
+
+execute:
+ IPM_EXECUTE YY_STR { $$ = new_opt(IPM_EXECUTE);
+ $$->o_str = $2; }
+ ;
+
+save: IPM_SAVE saveopts YY_STR { $$ = new_opt(IPM_SAVE);
+ $$->o_num = $2;
+ $$->o_str = $3; }
+ ;
+
+saveopts: { $$ = 0; }
+ | saveopt { $$ = $1; }
+ | saveopt ',' saveopts { $$ = $1 | $3; }
+ ;
+
+saveopt:
+ IPM_RAW { $$ = IPMDO_SAVERAW; }
+ ;
+
+syslog: IPM_SYSLOG { $$ = new_opt(IPM_SYSLOG); }
+ ;
+
+nothing:
+ IPM_NOTHING { $$ = 0; }
+ ;
+
+ipv4: YY_NUMBER '.' YY_NUMBER '.' YY_NUMBER '.' YY_NUMBER
+ { if ($1 > 255 || $3 > 255 || $5 > 255 || $7 > 255) {
+ yyerror("Invalid octet string for IP address");
+ return 0;
+ }
+ $$.s_addr = ($1 << 24) | ($3 << 16) | ($5 << 8) | $7;
+ $$.s_addr = htonl($$.s_addr);
+ }
+%%
+static struct wordtab yywords[] = {
+ { "body", IPM_BODY },
+ { "direction", IPM_DIRECTION },
+ { "do", IPM_DO },
+ { "dstip", IPM_DSTIP },
+ { "dstport", IPM_DSTPORT },
+ { "every", IPM_EVERY },
+ { "execute", IPM_EXECUTE },
+ { "group", IPM_GROUP },
+ { "in", IPM_IN },
+ { "interface", IPM_INTERFACE },
+ { "ipf", IPM_IPF },
+ { "logtag", IPM_LOGTAG },
+ { "match", IPM_MATCH },
+ { "nat", IPM_NAT },
+ { "nattag", IPM_NATTAG },
+ { "no", IPM_NO },
+ { "nothing", IPM_NOTHING },
+ { "out", IPM_OUT },
+ { "packet", IPM_PACKET },
+ { "packets", IPM_PACKETS },
+ { "protocol", IPM_PROTOCOL },
+ { "result", IPM_RESULT },
+ { "rule", IPM_RULE },
+ { "save", IPM_SAVE },
+ { "second", IPM_SECOND },
+ { "seconds", IPM_SECONDS },
+ { "srcip", IPM_SRCIP },
+ { "srcport", IPM_SRCPORT },
+ { "state", IPM_STATE },
+ { "syslog", IPM_SYSLOG },
+ { "with", IPM_WITH },
+ { NULL, 0 }
+};
+
+static int macflags[17][2] = {
+ { IPM_DIRECTION, IPMAC_DIRECTION },
+ { IPM_DSTIP, IPMAC_DSTIP },
+ { IPM_DSTPORT, IPMAC_DSTPORT },
+ { IPM_GROUP, IPMAC_GROUP },
+ { IPM_INTERFACE, IPMAC_INTERFACE },
+ { IPM_LOGTAG, IPMAC_LOGTAG },
+ { IPM_NATTAG, IPMAC_NATTAG },
+ { IPM_PACKET, IPMAC_EVERY },
+ { IPM_PROTOCOL, IPMAC_PROTOCOL },
+ { IPM_RESULT, IPMAC_RESULT },
+ { IPM_RULE, IPMAC_RULE },
+ { IPM_SECOND, IPMAC_EVERY },
+ { IPM_SRCIP, IPMAC_SRCIP },
+ { IPM_SRCPORT, IPMAC_SRCPORT },
+ { IPM_TYPE, IPMAC_TYPE },
+ { IPM_WITH, IPMAC_WITH },
+ { 0, 0 }
+};
+
+static opt_t *new_opt(type)
+int type;
+{
+ opt_t *o;
+
+ o = (opt_t *)malloc(sizeof(*o));
+ o->o_type = type;
+ o->o_line = yylineNum;
+ o->o_num = 0;
+ o->o_str = (char *)0;
+ o->o_next = NULL;
+ return o;
+}
+
+static void build_action(olist)
+opt_t *olist;
+{
+ ipmon_action_t *a;
+ opt_t *o;
+ char c;
+ int i;
+
+ a = (ipmon_action_t *)calloc(1, sizeof(*a));
+ if (a == NULL)
+ return;
+ while ((o = olist) != NULL) {
+ /*
+ * Check to see if the same comparator is being used more than
+ * once per matching statement.
+ */
+ for (i = 0; macflags[i][0]; i++)
+ if (macflags[i][0] == o->o_type)
+ break;
+ if (macflags[i][1] & a->ac_mflag) {
+ fprintf(stderr, "%s redfined on line %d\n",
+ yykeytostr(o->o_type), yylineNum);
+ if (o->o_str != NULL)
+ free(o->o_str);
+ olist = o->o_next;
+ free(o);
+ continue;
+ }
+
+ a->ac_mflag |= macflags[i][1];
+
+ switch (o->o_type)
+ {
+ case IPM_DIRECTION :
+ a->ac_direction = o->o_num;
+ break;
+ case IPM_DSTIP :
+ a->ac_dip = o->o_ip.s_addr;
+ a->ac_dmsk = htonl(0xffffffff << (32 - o->o_num));
+ break;
+ case IPM_DSTPORT :
+ a->ac_dport = htons(o->o_num);
+ break;
+ case IPM_EXECUTE :
+ a->ac_exec = o->o_str;
+ c = *o->o_str;
+ if (c== '"'|| c == '\'') {
+ if (o->o_str[strlen(o->o_str) - 1] == c) {
+ a->ac_run = strdup(o->o_str + 1);
+ a->ac_run[strlen(a->ac_run) - 1] ='\0';
+ } else
+ a->ac_run = o->o_str;
+ } else
+ a->ac_run = o->o_str;
+ o->o_str = NULL;
+ break;
+ case IPM_INTERFACE :
+ a->ac_iface = o->o_str;
+ o->o_str = NULL;
+ break;
+ case IPM_GROUP :
+ if (o->o_str != NULL)
+ strncpy(a->ac_group, o->o_str, FR_GROUPLEN);
+ else
+ sprintf(a->ac_group, "%d", o->o_num);
+ break;
+ case IPM_LOGTAG :
+ a->ac_logtag = o->o_num;
+ break;
+ case IPM_NATTAG :
+ strncpy(a->ac_nattag, o->o_str, sizeof(a->ac_nattag));
+ break;
+ case IPM_PACKET :
+ a->ac_packet = o->o_num;
+ break;
+ case IPM_PROTOCOL :
+ a->ac_proto = o->o_num;
+ break;
+ case IPM_RULE :
+ a->ac_rule = o->o_num;
+ break;
+ case IPM_RESULT :
+ if (!strcasecmp(o->o_str, "pass"))
+ a->ac_result = IPMR_PASS;
+ else if (!strcasecmp(o->o_str, "block"))
+ a->ac_result = IPMR_BLOCK;
+ else if (!strcasecmp(o->o_str, "nomatch"))
+ a->ac_result = IPMR_NOMATCH;
+ else if (!strcasecmp(o->o_str, "log"))
+ a->ac_result = IPMR_LOG;
+ break;
+ case IPM_SECOND :
+ a->ac_second = o->o_num;
+ break;
+ case IPM_SRCIP :
+ a->ac_sip = o->o_ip.s_addr;
+ a->ac_smsk = htonl(0xffffffff << (32 - o->o_num));
+ break;
+ case IPM_SRCPORT :
+ a->ac_sport = htons(o->o_num);
+ break;
+ case IPM_SAVE :
+ if (a->ac_savefile != NULL) {
+ fprintf(stderr, "%s redfined on line %d\n",
+ yykeytostr(o->o_type), yylineNum);
+ break;
+ }
+ a->ac_savefile = strdup(o->o_str);
+ a->ac_savefp = fopen(o->o_str, "a");
+ a->ac_dflag |= o->o_num & IPMDO_SAVERAW;
+ break;
+ case IPM_SYSLOG :
+ if (a->ac_syslog != 0) {
+ fprintf(stderr, "%s redfined on line %d\n",
+ yykeytostr(o->o_type), yylineNum);
+ break;
+ }
+ a->ac_syslog = 1;
+ break;
+ case IPM_TYPE :
+ a->ac_type = o->o_num;
+ break;
+ case IPM_WITH :
+ break;
+ default :
+ break;
+ }
+
+ olist = o->o_next;
+ if (o->o_str != NULL)
+ free(o->o_str);
+ free(o);
+ }
+ a->ac_next = alist;
+ alist = a;
+}
+
+
+int check_action(buf, log, opts, lvl)
+char *buf, *log;
+int opts, lvl;
+{
+ ipmon_action_t *a;
+ struct timeval tv;
+ ipflog_t *ipf;
+ tcphdr_t *tcp;
+ iplog_t *ipl;
+ int matched;
+ u_long t1;
+ ip_t *ip;
+
+ matched = 0;
+ ipl = (iplog_t *)buf;
+ ipf = (ipflog_t *)(ipl +1);
+ ip = (ip_t *)(ipf + 1);
+ tcp = (tcphdr_t *)((char *)ip + (IP_HL(ip) << 2));
+
+ for (a = alist; a != NULL; a = a->ac_next) {
+ if ((a->ac_mflag & IPMAC_DIRECTION) != 0) {
+ if (a->ac_direction == IPM_IN) {
+ if ((ipf->fl_flags & FR_INQUE) == 0)
+ continue;
+ } else if (a->ac_direction == IPM_OUT) {
+ if ((ipf->fl_flags & FR_OUTQUE) == 0)
+ continue;
+ }
+ }
+
+ if ((a->ac_type != 0) && (a->ac_type != ipl->ipl_magic))
+ continue;
+
+ if ((a->ac_mflag & IPMAC_EVERY) != 0) {
+ gettimeofday(&tv, NULL);
+ t1 = tv.tv_sec - a->ac_lastsec;
+ if (tv.tv_usec <= a->ac_lastusec)
+ t1--;
+ if (a->ac_second != 0) {
+ if (t1 < a->ac_second)
+ continue;
+ a->ac_lastsec = tv.tv_sec;
+ a->ac_lastusec = tv.tv_usec;
+ }
+
+ if (a->ac_packet != 0) {
+ if (a->ac_pktcnt == 0)
+ a->ac_pktcnt++;
+ else if (a->ac_pktcnt == a->ac_packet) {
+ a->ac_pktcnt = 0;
+ continue;
+ } else {
+ a->ac_pktcnt++;
+ continue;
+ }
+ }
+ }
+
+ if ((a->ac_mflag & IPMAC_DSTIP) != 0) {
+ if ((ip->ip_dst.s_addr & a->ac_dmsk) != a->ac_dip)
+ continue;
+ }
+
+ if ((a->ac_mflag & IPMAC_DSTPORT) != 0) {
+ if (ip->ip_p != IPPROTO_UDP && ip->ip_p != IPPROTO_TCP)
+ continue;
+ if (tcp->th_dport != a->ac_dport)
+ continue;
+ }
+
+ if ((a->ac_mflag & IPMAC_GROUP) != 0) {
+ if (strncmp(a->ac_group, ipf->fl_group,
+ FR_GROUPLEN) != 0)
+ continue;
+ }
+
+ if ((a->ac_mflag & IPMAC_INTERFACE) != 0) {
+ if (strcmp(a->ac_iface, ipf->fl_ifname))
+ continue;
+ }
+
+ if ((a->ac_mflag & IPMAC_PROTOCOL) != 0) {
+ if (a->ac_proto != ip->ip_p)
+ continue;
+ }
+
+ if ((a->ac_mflag & IPMAC_RESULT) != 0) {
+ if ((ipf->fl_flags & FF_LOGNOMATCH) != 0) {
+ if (a->ac_result != IPMR_NOMATCH)
+ continue;
+ } else if (FR_ISPASS(ipf->fl_flags)) {
+ if (a->ac_result != IPMR_PASS)
+ continue;
+ } else if (FR_ISBLOCK(ipf->fl_flags)) {
+ if (a->ac_result != IPMR_BLOCK)
+ continue;
+ } else { /* Log only */
+ if (a->ac_result != IPMR_LOG)
+ continue;
+ }
+ }
+
+ if ((a->ac_mflag & IPMAC_RULE) != 0) {
+ if (a->ac_rule != ipf->fl_rule)
+ continue;
+ }
+
+ if ((a->ac_mflag & IPMAC_SRCIP) != 0) {
+ if ((ip->ip_src.s_addr & a->ac_smsk) != a->ac_sip)
+ continue;
+ }
+
+ if ((a->ac_mflag & IPMAC_SRCPORT) != 0) {
+ if (ip->ip_p != IPPROTO_UDP && ip->ip_p != IPPROTO_TCP)
+ continue;
+ if (tcp->th_sport != a->ac_sport)
+ continue;
+ }
+
+ if ((a->ac_mflag & IPMAC_LOGTAG) != 0) {
+ if (a->ac_logtag != ipf->fl_logtag)
+ continue;
+ }
+
+ if ((a->ac_mflag & IPMAC_NATTAG) != 0) {
+ if (strncmp(a->ac_nattag, ipf->fl_nattag.ipt_tag,
+ IPFTAG_LEN) != 0)
+ continue;
+ }
+
+ matched = 1;
+
+ /*
+ * It matched so now execute the command
+ */
+ if (a->ac_syslog != 0) {
+ syslog(lvl, "%s", log);
+ }
+
+ if (a->ac_savefp != NULL) {
+ if (a->ac_dflag & IPMDO_SAVERAW)
+ fwrite(ipl, 1, ipl->ipl_dsize, a->ac_savefp);
+ else
+ fputs(log, a->ac_savefp);
+ }
+
+ if (a->ac_exec != NULL) {
+ switch (fork())
+ {
+ case 0 :
+ {
+ FILE *pi;
+
+ pi = popen(a->ac_run, "w");
+ if (pi != NULL) {
+ fprintf(pi, "%s\n", log);
+ if ((opts & OPT_HEXHDR) != 0) {
+ dumphex(pi, 0, buf,
+ sizeof(*ipl) +
+ sizeof(*ipf));
+ }
+ if ((opts & OPT_HEXBODY) != 0) {
+ dumphex(pi, 0, (char *)ip,
+ ipf->fl_hlen +
+ ipf->fl_plen);
+ }
+ pclose(pi);
+ }
+ exit(1);
+ }
+ case -1 :
+ break;
+ default :
+ break;
+ }
+ }
+ }
+
+ return matched;
+}
+
+
+static void free_action(a)
+ipmon_action_t *a;
+{
+ if (a->ac_savefile != NULL) {
+ free(a->ac_savefile);
+ a->ac_savefile = NULL;
+ }
+ if (a->ac_savefp != NULL) {
+ fclose(a->ac_savefp);
+ a->ac_savefp = NULL;
+ }
+ if (a->ac_exec != NULL) {
+ free(a->ac_exec);
+ if (a->ac_run == a->ac_exec)
+ a->ac_run = NULL;
+ a->ac_exec = NULL;
+ }
+ if (a->ac_run != NULL) {
+ free(a->ac_run);
+ a->ac_run = NULL;
+ }
+ if (a->ac_iface != NULL) {
+ free(a->ac_iface);
+ a->ac_iface = NULL;
+ }
+ a->ac_next = NULL;
+ free(a);
+}
+
+
+int load_config(file)
+char *file;
+{
+ ipmon_action_t *a;
+ FILE *fp;
+ char *s;
+
+ s = getenv("YYDEBUG");
+ if (s != NULL)
+ yydebug = atoi(s);
+ else
+ yydebug = 0;
+
+ while ((a = alist) != NULL) {
+ alist = a->ac_next;
+ free_action(a);
+ }
+
+ yylineNum = 1;
+
+ (void) yysettab(yywords);
+
+ fp = fopen(file, "r");
+ if (!fp) {
+ perror("load_config:fopen:");
+ return -1;
+ }
+ yyin = fp;
+ while (!feof(fp))
+ yyparse();
+ fclose(fp);
+ return 0;
+}
diff --git a/contrib/ipfilter/tools/ipnat.c b/contrib/ipfilter/tools/ipnat.c
new file mode 100644
index 0000000..fc17cea
--- /dev/null
+++ b/contrib/ipfilter/tools/ipnat.c
@@ -0,0 +1,400 @@
+/* $NetBSD$ */
+
+/*
+ * Copyright (C) 1993-2001 by Darren Reed.
+ *
+ * See the IPFILTER.LICENCE file for details on licencing.
+ *
+ * Added redirect stuff and a variety of bug fixes. (mcn@EnGarde.com)
+ */
+#include <stdio.h>
+#include <string.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <sys/types.h>
+#if !defined(__SVR4) && !defined(__svr4__)
+#include <strings.h>
+#else
+#include <sys/byteorder.h>
+#endif
+#include <sys/time.h>
+#include <sys/param.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <stddef.h>
+#include <sys/file.h>
+#define _KERNEL
+#include <sys/uio.h>
+#undef _KERNEL
+#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>
+#if __FreeBSD_version >= 300000
+# include <net/if_var.h>
+#endif
+#include <netdb.h>
+#include <arpa/nameser.h>
+#include <arpa/inet.h>
+#include <resolv.h>
+#include <ctype.h>
+#if defined(linux)
+# include <linux/a.out.h>
+#else
+# include <nlist.h>
+#endif
+#include "ipf.h"
+#include "ipl.h"
+#include "kmem.h"
+
+#ifdef __hpux
+# define nlist nlist64
+#endif
+
+#if defined(sun) && !SOLARIS2
+# define STRERROR(x) sys_errlist[x]
+extern char *sys_errlist[];
+#else
+# define STRERROR(x) strerror(x)
+#endif
+
+#if !defined(lint)
+static const char sccsid[] ="@(#)ipnat.c 1.9 6/5/96 (C) 1993 Darren Reed";
+static const char rcsid[] = "@(#)Id: ipnat.c,v 1.24.2.1 2004/04/28 17:56:22 darrenr Exp";
+#endif
+
+
+#if SOLARIS
+#define bzero(a,b) memset(a,0,b)
+#endif
+int use_inet6 = 0;
+char thishost[MAXHOSTNAMELEN];
+
+extern char *optarg;
+
+void dostats __P((natstat_t *, int)), flushtable __P((int, int));
+void usage __P((char *));
+int main __P((int, char*[]));
+void showhostmap __P((natstat_t *nsp));
+void natstat_dead __P((natstat_t *, char *));
+
+int opts;
+
+void usage(name)
+char *name;
+{
+ fprintf(stderr, "Usage: %s [-CFhlnrRsv] [-f filename]\n", name);
+ exit(1);
+}
+
+
+int main(argc, argv)
+int argc;
+char *argv[];
+{
+ char *file, *core, *kernel;
+ natstat_t ns, *nsp;
+ int fd, c, mode;
+ ipfobj_t obj;
+
+ fd = -1;
+ opts = 0;
+ nsp = &ns;
+ file = NULL;
+ core = NULL;
+ kernel = NULL;
+ mode = O_RDWR;
+
+ while ((c = getopt(argc, argv, "CdFf:hlM:N:nrRsv")) != -1)
+ switch (c)
+ {
+ case 'C' :
+ opts |= OPT_CLEAR;
+ break;
+ case 'd' :
+ opts |= OPT_DEBUG;
+ break;
+ case 'f' :
+ file = optarg;
+ break;
+ case 'F' :
+ opts |= OPT_FLUSH;
+ break;
+ case 'h' :
+ opts |=OPT_HITS;
+ break;
+ case 'l' :
+ opts |= OPT_LIST;
+ mode = O_RDONLY;
+ break;
+ case 'M' :
+ core = optarg;
+ break;
+ case 'N' :
+ kernel = optarg;
+ break;
+ case 'n' :
+ opts |= OPT_DONOTHING;
+ mode = O_RDONLY;
+ break;
+ case 'R' :
+ opts |= OPT_NORESOLVE;
+ break;
+ case 'r' :
+ opts |= OPT_REMOVE;
+ break;
+ case 's' :
+ opts |= OPT_STAT;
+ mode = O_RDONLY;
+ break;
+ case 'v' :
+ opts |= OPT_VERBOSE;
+ break;
+ default :
+ usage(argv[0]);
+ }
+
+ initparse();
+
+ if ((kernel != NULL) || (core != NULL)) {
+ (void) setgid(getgid());
+ (void) setuid(getuid());
+ }
+
+ bzero((char *)&ns, sizeof(ns));
+
+ if ((opts & OPT_DONOTHING) == 0) {
+ if (checkrev(IPL_NAME) == -1) {
+ fprintf(stderr, "User/kernel version check failed\n");
+ exit(1);
+ }
+ }
+
+
+ if (!(opts & OPT_DONOTHING) && (kernel == NULL) && (core == NULL)) {
+ if (openkmem(kernel, core) == -1)
+ exit(1);
+
+ if (((fd = open(IPNAT_NAME, mode)) == -1) &&
+ ((fd = open(IPNAT_NAME, O_RDONLY)) == -1)) {
+ (void) fprintf(stderr, "%s: open: %s\n", IPNAT_NAME,
+ STRERROR(errno));
+ exit(1);
+ }
+
+ bzero((char *)&obj, sizeof(obj));
+ obj.ipfo_rev = IPFILTER_VERSION;
+ obj.ipfo_size = sizeof(*nsp);
+ obj.ipfo_type = IPFOBJ_NATSTAT;
+ obj.ipfo_ptr = (void *)nsp;
+ if (ioctl(fd, SIOCGNATS, &obj) == -1) {
+ perror("ioctl(SIOCGNATS)");
+ exit(1);
+ }
+ (void) setgid(getgid());
+ (void) setuid(getuid());
+ } else if ((kernel != NULL) || (core != NULL)) {
+ if (openkmem(kernel, core) == -1)
+ exit(1);
+
+ natstat_dead(nsp, kernel);
+ if (opts & (OPT_LIST|OPT_STAT))
+ dostats(nsp, opts);
+ exit(0);
+ }
+
+ if (opts & (OPT_FLUSH|OPT_CLEAR))
+ flushtable(fd, opts);
+ if (file) {
+ ipnat_parsefile(fd, ipnat_addrule, ioctl, file);
+ }
+ if (opts & (OPT_LIST|OPT_STAT))
+ dostats(nsp, opts);
+ return 0;
+}
+
+
+/*
+ * Read NAT statistic information in using a symbol table and memory file
+ * rather than doing ioctl's.
+ */
+void natstat_dead(nsp, kernel)
+natstat_t *nsp;
+char *kernel;
+{
+ struct nlist nat_nlist[10] = {
+ { "nat_table" }, /* 0 */
+ { "nat_list" },
+ { "maptable" },
+ { "ipf_nattable_sz" },
+ { "ipf_natrules_sz" },
+ { "ipf_rdrrules_sz" }, /* 5 */
+ { "ipf_hostmap_sz" },
+ { "nat_instances" },
+ { "ap_sess_list" },
+ { NULL }
+ };
+ void *tables[2];
+
+ if (nlist(kernel, nat_nlist) == -1) {
+ fprintf(stderr, "nlist error\n");
+ return;
+ }
+
+ /*
+ * Normally the ioctl copies all of these values into the structure
+ * for us, before returning it to userland, so here we must copy each
+ * one in individually.
+ */
+ kmemcpy((char *)&tables, nat_nlist[0].n_value, sizeof(tables));
+ nsp->ns_table[0] = tables[0];
+ nsp->ns_table[1] = tables[1];
+
+ kmemcpy((char *)&nsp->ns_list, nat_nlist[1].n_value,
+ sizeof(nsp->ns_list));
+ kmemcpy((char *)&nsp->ns_maptable, nat_nlist[2].n_value,
+ sizeof(nsp->ns_maptable));
+ kmemcpy((char *)&nsp->ns_nattab_sz, nat_nlist[3].n_value,
+ sizeof(nsp->ns_nattab_sz));
+ kmemcpy((char *)&nsp->ns_rultab_sz, nat_nlist[4].n_value,
+ sizeof(nsp->ns_rultab_sz));
+ kmemcpy((char *)&nsp->ns_rdrtab_sz, nat_nlist[5].n_value,
+ sizeof(nsp->ns_rdrtab_sz));
+ kmemcpy((char *)&nsp->ns_hostmap_sz, nat_nlist[6].n_value,
+ sizeof(nsp->ns_hostmap_sz));
+ kmemcpy((char *)&nsp->ns_instances, nat_nlist[7].n_value,
+ sizeof(nsp->ns_instances));
+ kmemcpy((char *)&nsp->ns_apslist, nat_nlist[8].n_value,
+ sizeof(nsp->ns_apslist));
+}
+
+
+/*
+ * Display NAT statistics.
+ */
+void dostats(nsp, opts)
+natstat_t *nsp;
+int opts;
+{
+ nat_t *np, nat;
+ ipnat_t ipn;
+
+ /*
+ * Show statistics ?
+ */
+ if (opts & OPT_STAT) {
+ printf("mapped\tin\t%lu\tout\t%lu\n",
+ nsp->ns_mapped[0], nsp->ns_mapped[1]);
+ printf("added\t%lu\texpired\t%lu\n",
+ nsp->ns_added, nsp->ns_expire);
+ printf("no memory\t%lu\tbad nat\t%lu\n",
+ nsp->ns_memfail, nsp->ns_badnat);
+ printf("inuse\t%lu\nrules\t%lu\n",
+ nsp->ns_inuse, nsp->ns_rules);
+ printf("wilds\t%u\n", nsp->ns_wilds);
+ if (opts & OPT_VERBOSE)
+ printf("table %p list %p\n",
+ nsp->ns_table, nsp->ns_list);
+ }
+
+ /*
+ * Show list of NAT rules and NAT sessions ?
+ */
+ if (opts & OPT_LIST) {
+ printf("List of active MAP/Redirect filters:\n");
+ while (nsp->ns_list) {
+ if (kmemcpy((char *)&ipn, (long)nsp->ns_list,
+ sizeof(ipn))) {
+ perror("kmemcpy");
+ break;
+ }
+ if (opts & OPT_HITS)
+ printf("%lu ", ipn.in_hits);
+ printnat(&ipn, opts & (OPT_DEBUG|OPT_VERBOSE));
+ nsp->ns_list = ipn.in_next;
+ }
+
+ printf("\nList of active sessions:\n");
+
+ for (np = nsp->ns_instances; np; np = nat.nat_next) {
+ if (kmemcpy((char *)&nat, (long)np, sizeof(nat)))
+ break;
+ printactivenat(&nat, opts);
+ if (nat.nat_aps)
+ printaps(nat.nat_aps, opts);
+ }
+
+ if (opts & OPT_VERBOSE)
+ showhostmap(nsp);
+ }
+}
+
+
+/*
+ * Display the active host mapping table.
+ */
+void showhostmap(nsp)
+natstat_t *nsp;
+{
+ hostmap_t hm, *hmp, **maptable;
+ u_int hv;
+
+ printf("\nList of active host mappings:\n");
+
+ maptable = (hostmap_t **)malloc(sizeof(hostmap_t *) *
+ nsp->ns_hostmap_sz);
+ if (kmemcpy((char *)maptable, (u_long)nsp->ns_maptable,
+ sizeof(hostmap_t *) * nsp->ns_hostmap_sz)) {
+ perror("kmemcpy (maptable)");
+ return;
+ }
+
+ for (hv = 0; hv < nsp->ns_hostmap_sz; hv++) {
+ hmp = maptable[hv];
+
+ while (hmp) {
+ if (kmemcpy((char *)&hm, (u_long)hmp, sizeof(hm))) {
+ perror("kmemcpy (hostmap)");
+ return;
+ }
+
+ printhostmap(&hm, hv);
+ hmp = hm.hm_next;
+ }
+ }
+ free(maptable);
+}
+
+
+/*
+ * Issue an ioctl to flush either the NAT rules table or the active mapping
+ * table or both.
+ */
+void flushtable(fd, opts)
+int fd, opts;
+{
+ int n = 0;
+
+ if (opts & OPT_FLUSH) {
+ n = 0;
+ if (!(opts & OPT_DONOTHING) && ioctl(fd, SIOCIPFFL, &n) == -1)
+ perror("ioctl(SIOCFLNAT)");
+ else
+ printf("%d entries flushed from NAT table\n", n);
+ }
+
+ if (opts & OPT_CLEAR) {
+ n = 1;
+ if (!(opts & OPT_DONOTHING) && ioctl(fd, SIOCIPFFL, &n) == -1)
+ perror("ioctl(SIOCCNATL)");
+ else
+ printf("%d entries flushed from NAT list\n", n);
+ }
+}
diff --git a/contrib/ipfilter/tools/ipnat_y.y b/contrib/ipfilter/tools/ipnat_y.y
new file mode 100644
index 0000000..d3f18c6
--- /dev/null
+++ b/contrib/ipfilter/tools/ipnat_y.y
@@ -0,0 +1,828 @@
+/* $NetBSD$ */
+
+%{
+#ifdef __FreeBSD__
+# ifndef __FreeBSD_cc_version
+# include <osreldate.h>
+# else
+# if __FreeBSD_cc_version < 430000
+# include <osreldate.h>
+# endif
+# endif
+#endif
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <fcntl.h>
+#include <errno.h>
+#if !defined(__SVR4) && !defined(__GNUC__)
+#include <strings.h>
+#endif
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/file.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <sys/time.h>
+#include <syslog.h>
+#include <net/if.h>
+#if __FreeBSD_version >= 300000
+# include <net/if_var.h>
+#endif
+#include <netdb.h>
+#include <arpa/nameser.h>
+#include <resolv.h>
+#include "ipf.h"
+#include "netinet/ipl.h"
+#include "ipnat_l.h"
+
+#define YYDEBUG 1
+
+extern void yyerror __P((char *));
+extern int yyparse __P((void));
+extern int yylex __P((void));
+extern int yydebug;
+extern FILE *yyin;
+extern int yylineNum;
+
+static ipnat_t *nattop = NULL;
+static ipnat_t *nat = NULL;
+static int natfd = -1;
+static ioctlfunc_t natioctlfunc = NULL;
+static addfunc_t nataddfunc = NULL;
+
+static void newnatrule __P((void));
+static void setnatproto __P((int));
+
+%}
+%union {
+ char *str;
+ u_32_t num;
+ struct in_addr ipa;
+ frentry_t fr;
+ frtuc_t *frt;
+ u_short port;
+ struct {
+ u_short p1;
+ u_short p2;
+ int pc;
+ } pc;
+ struct {
+ struct in_addr a;
+ struct in_addr m;
+ } ipp;
+ union i6addr ip6;
+};
+
+%token <num> YY_NUMBER YY_HEX
+%token <str> YY_STR
+%token YY_COMMENT
+%token YY_CMP_EQ YY_CMP_NE YY_CMP_LE YY_CMP_GE YY_CMP_LT YY_CMP_GT
+%token YY_RANGE_OUT YY_RANGE_IN
+%token <ip6> YY_IPV6
+
+%token IPNY_MAPBLOCK IPNY_RDR IPNY_PORT IPNY_PORTS IPNY_AUTO IPNY_RANGE
+%token IPNY_MAP IPNY_BIMAP IPNY_FROM IPNY_TO IPNY_MASK IPNY_PORTMAP IPNY_ANY
+%token IPNY_ROUNDROBIN IPNY_FRAG IPNY_AGE IPNY_ICMPIDMAP IPNY_PROXY
+%token IPNY_TCP IPNY_UDP IPNY_TCPUDP IPNY_STICKY IPNY_MSSCLAMP IPNY_TAG
+%token IPNY_TLATE
+%type <port> portspec
+%type <num> hexnumber compare range proto
+%type <ipa> hostname ipv4
+%type <ipp> addr nummask rhaddr
+%type <pc> portstuff
+%%
+file: line
+ | assign
+ | file line
+ | file assign
+ ;
+
+line: xx rule { while ((nat = nattop) != NULL) {
+ nattop = nat->in_next;
+ (*nataddfunc)(natfd, natioctlfunc, nat);
+ free(nat);
+ }
+ resetlexer();
+ }
+ | YY_COMMENT
+ ;
+
+assign: YY_STR assigning YY_STR ';' { set_variable($1, $3);
+ resetlexer();
+ free($1);
+ free($3);
+ }
+ ;
+
+assigning:
+ '=' { yyvarnext = 1; }
+ ;
+
+xx: { newnatrule(); }
+ ;
+
+rule: map eol
+ | mapblock eol
+ | redir eol
+ ;
+
+eol: | ';'
+ ;
+
+map: mapit ifnames addr IPNY_TLATE rhaddr proxy mapoptions
+ { nat->in_v = 4;
+ nat->in_inip = $3.a.s_addr;
+ nat->in_inmsk = $3.m.s_addr;
+ nat->in_outip = $5.a.s_addr;
+ nat->in_outmsk = $5.m.s_addr;
+ if (nat->in_ifnames[1][0] == '\0')
+ strncpy(nat->in_ifnames[1],
+ nat->in_ifnames[0],
+ sizeof(nat->in_ifnames[0]));
+ if ((nat->in_flags & IPN_TCPUDP) == 0)
+ setnatproto(nat->in_p);
+ if (((nat->in_redir & NAT_MAPBLK) != 0) ||
+ ((nat->in_flags & IPN_AUTOPORTMAP) != 0))
+ nat_setgroupmap(nat);
+ }
+ | mapit ifnames addr IPNY_TLATE rhaddr mapport mapoptions
+ { nat->in_v = 4;
+ nat->in_inip = $3.a.s_addr;
+ nat->in_inmsk = $3.m.s_addr;
+ nat->in_outip = $5.a.s_addr;
+ nat->in_outmsk = $5.m.s_addr;
+ if (nat->in_ifnames[1][0] == '\0')
+ strncpy(nat->in_ifnames[1],
+ nat->in_ifnames[0],
+ sizeof(nat->in_ifnames[0]));
+ if ((nat->in_flags & IPN_TCPUDPICMPQ) == 0)
+ setnatproto(nat->in_p);
+ if (((nat->in_redir & NAT_MAPBLK) != 0) ||
+ ((nat->in_flags & IPN_AUTOPORTMAP) != 0))
+ nat_setgroupmap(nat);
+ }
+ | mapit ifnames mapfrom IPNY_TLATE rhaddr proxy mapoptions
+ { nat->in_v = 4;
+ nat->in_outip = $5.a.s_addr;
+ nat->in_outmsk = $5.m.s_addr;
+ if (nat->in_ifnames[1][0] == '\0')
+ strncpy(nat->in_ifnames[1],
+ nat->in_ifnames[0],
+ sizeof(nat->in_ifnames[0]));
+ if ((nat->in_flags & IPN_TCPUDP) == 0)
+ setnatproto(nat->in_p);
+ if (((nat->in_redir & NAT_MAPBLK) != 0) ||
+ ((nat->in_flags & IPN_AUTOPORTMAP) != 0))
+ nat_setgroupmap(nat);
+ }
+ | mapit ifnames mapfrom IPNY_TLATE rhaddr mapport mapoptions
+ { nat->in_v = 4;
+ nat->in_outip = $5.a.s_addr;
+ nat->in_outmsk = $5.m.s_addr;
+ if (nat->in_ifnames[1][0] == '\0')
+ strncpy(nat->in_ifnames[1],
+ nat->in_ifnames[0],
+ sizeof(nat->in_ifnames[0]));
+ if ((nat->in_flags & IPN_TCPUDPICMPQ) == 0)
+ setnatproto(nat->in_p);
+ if (((nat->in_redir & NAT_MAPBLK) != 0) ||
+ ((nat->in_flags & IPN_AUTOPORTMAP) != 0))
+ nat_setgroupmap(nat);
+ }
+ ;
+
+mapblock:
+ mapblockit ifnames addr IPNY_TLATE addr ports mapoptions
+ { nat->in_v = 4;
+ nat->in_inip = $3.a.s_addr;
+ nat->in_inmsk = $3.m.s_addr;
+ nat->in_outip = $5.a.s_addr;
+ nat->in_outmsk = $5.m.s_addr;
+ if (nat->in_ifnames[1][0] == '\0')
+ strncpy(nat->in_ifnames[1],
+ nat->in_ifnames[0],
+ sizeof(nat->in_ifnames[0]));
+ if ((nat->in_flags & IPN_TCPUDP) == 0)
+ setnatproto(nat->in_p);
+ if (((nat->in_redir & NAT_MAPBLK) != 0) ||
+ ((nat->in_flags & IPN_AUTOPORTMAP) != 0))
+ nat_setgroupmap(nat);
+ }
+ ;
+
+redir: rdrit ifnames addr dport IPNY_TLATE dip nport setproto rdroptions
+ { nat->in_v = 4;
+ nat->in_outip = $3.a.s_addr;
+ nat->in_outmsk = $3.m.s_addr;
+ if (nat->in_ifnames[1][0] == '\0')
+ strncpy(nat->in_ifnames[1],
+ nat->in_ifnames[0],
+ sizeof(nat->in_ifnames[0]));
+ if ((nat->in_p == 0) &&
+ ((nat->in_flags & IPN_TCPUDP) == 0) &&
+ (nat->in_pmin != 0 ||
+ nat->in_pmax != 0 ||
+ nat->in_pnext != 0))
+ setnatproto(IPPROTO_TCP);
+ }
+ | rdrit ifnames rdrfrom IPNY_TLATE dip nport setproto rdroptions
+ { nat->in_v = 4;
+ if ((nat->in_p == 0) &&
+ ((nat->in_flags & IPN_TCPUDP) == 0) &&
+ (nat->in_pmin != 0 ||
+ nat->in_pmax != 0 ||
+ nat->in_pnext != 0))
+ setnatproto(IPPROTO_TCP);
+ if (nat->in_ifnames[1][0] == '\0')
+ strncpy(nat->in_ifnames[1],
+ nat->in_ifnames[0],
+ sizeof(nat->in_ifnames[0]));
+ }
+ | rdrit ifnames addr IPNY_TLATE dip setproto rdroptions
+ { nat->in_v = 4;
+ nat->in_outip = $3.a.s_addr;
+ nat->in_outmsk = $3.m.s_addr;
+ if (nat->in_ifnames[1][0] == '\0')
+ strncpy(nat->in_ifnames[1],
+ nat->in_ifnames[0],
+ sizeof(nat->in_ifnames[0]));
+ }
+ ;
+
+proxy: | IPNY_PROXY IPNY_PORT portspec YY_STR '/' proto
+ { strncpy(nat->in_plabel, $4, sizeof(nat->in_plabel));
+ if (nat->in_dcmp == 0) {
+ nat->in_dport = htons($3);
+ } else if ($3 != nat->in_dport) {
+ yyerror("proxy port numbers not consistant");
+ }
+ setnatproto($6);
+ free($4);
+ }
+ | IPNY_PROXY IPNY_PORT YY_STR YY_STR '/' proto
+ { int pnum;
+ strncpy(nat->in_plabel, $4, sizeof(nat->in_plabel));
+ pnum = getportproto($3, $6);
+ if (pnum == -1)
+ yyerror("invalid port number");
+ nat->in_dport = pnum;
+ setnatproto($6);
+ free($3);
+ free($4);
+ }
+ ;
+
+setproto:
+ | proto { if (nat->in_p != 0 ||
+ nat->in_flags & IPN_TCPUDP)
+ yyerror("protocol set twice");
+ setnatproto($1);
+ }
+ | IPNY_TCPUDP { if (nat->in_p != 0 ||
+ nat->in_flags & IPN_TCPUDP)
+ yyerror("protocol set twice");
+ nat->in_flags |= IPN_TCPUDP;
+ nat->in_p = 0;
+ }
+ | IPNY_TCP '/' IPNY_UDP { if (nat->in_p != 0 ||
+ nat->in_flags & IPN_TCPUDP)
+ yyerror("protocol set twice");
+ nat->in_flags |= IPN_TCPUDP;
+ nat->in_p = 0;
+ }
+ ;
+
+rhaddr: addr { $$.a = $1.a; $$.m = $1.m; }
+ | IPNY_RANGE ipv4 '-' ipv4
+ { $$.a = $2; $$.m = $4;
+ nat->in_flags |= IPN_IPRANGE; }
+ ;
+
+dip:
+ hostname { nat->in_inip = $1.s_addr;
+ nat->in_inmsk = 0xffffffff; }
+ | hostname ',' hostname { nat->in_flags |= IPN_SPLIT;
+ nat->in_inip = $1.s_addr;
+ nat->in_inmsk = $3.s_addr; }
+ ;
+
+portspec:
+ YY_NUMBER { if ($1 > 65535) /* Unsigned */
+ yyerror("invalid port number");
+ else
+ $$ = $1;
+ }
+ | YY_STR { if (getport(NULL, $1, &($$)) == -1)
+ yyerror("invalid port number");
+ $$ = ntohs($$);
+ }
+ ;
+
+dport: | IPNY_PORT portspec { nat->in_pmin = htons($2);
+ nat->in_pmax = htons($2); }
+ | IPNY_PORT portspec '-' portspec { nat->in_pmin = htons($2);
+ nat->in_pmax = htons($4); }
+ | IPNY_PORT portspec ':' portspec { nat->in_pmin = htons($2);
+ nat->in_pmax = htons($4); }
+ ;
+
+nport: IPNY_PORT portspec { nat->in_pnext = htons($2); }
+ | IPNY_PORT '=' portspec { nat->in_pnext = htons($3);
+ nat->in_flags |= IPN_FIXEDDPORT;
+ }
+ ;
+
+ports: | IPNY_PORTS YY_NUMBER { nat->in_pmin = $2; }
+ | IPNY_PORTS IPNY_AUTO { nat->in_flags |= IPN_AUTOPORTMAP; }
+ ;
+
+mapit: IPNY_MAP { nat->in_redir = NAT_MAP; }
+ | IPNY_BIMAP { nat->in_redir = NAT_BIMAP; }
+ ;
+
+rdrit: IPNY_RDR { nat->in_redir = NAT_REDIRECT; }
+ ;
+
+mapblockit:
+ IPNY_MAPBLOCK { nat->in_redir = NAT_MAPBLK; }
+ ;
+
+mapfrom:
+ from sobject IPNY_TO dobject
+ | from sobject '!' IPNY_TO dobject
+ { nat->in_flags |= IPN_NOTDST; }
+ ;
+
+rdrfrom:
+ from sobject IPNY_TO dobject
+ | '!' from sobject IPNY_TO dobject
+ { nat->in_flags |= IPN_NOTSRC; }
+ ;
+
+from: IPNY_FROM { nat->in_flags |= IPN_FILTER; }
+ ;
+
+ifnames:
+ ifname
+ | ifname ',' otherifname
+ ;
+
+ifname: YY_STR { strncpy(nat->in_ifnames[0], $1,
+ sizeof(nat->in_ifnames[0]));
+ nat->in_ifnames[0][LIFNAMSIZ - 1] = '\0';
+ free($1);
+ }
+ ;
+
+otherifname:
+ YY_STR { strncpy(nat->in_ifnames[1], $1,
+ sizeof(nat->in_ifnames[1]));
+ nat->in_ifnames[1][LIFNAMSIZ - 1] = '\0';
+ free($1);
+ }
+ ;
+
+mapport:
+ IPNY_PORTMAP tcpudp portspec ':' portspec
+ { nat->in_pmin = htons($3);
+ nat->in_pmax = htons($5);
+ }
+ | IPNY_PORTMAP tcpudp IPNY_AUTO
+ { nat->in_flags |= IPN_AUTOPORTMAP;
+ nat->in_pmin = htons(1024);
+ nat->in_pmax = htons(65535);
+ }
+ | IPNY_ICMPIDMAP YY_STR YY_NUMBER ':' YY_NUMBER
+ { if (strcmp($2, "icmp") != 0) {
+ yyerror("icmpidmap not followed by icmp");
+ }
+ free($2);
+ if ($3 < 0 || $3 > 65535)
+ yyerror("invalid ICMP Id number");
+ if ($5 < 0 || $5 > 65535)
+ yyerror("invalid ICMP Id number");
+ nat->in_flags = IPN_ICMPQUERY;
+ nat->in_pmin = htons($3);
+ nat->in_pmax = htons($5);
+ }
+ ;
+
+sobject:
+ saddr
+ | saddr IPNY_PORT portstuff { nat->in_sport = $3.p1;
+ nat->in_stop = $3.p2;
+ nat->in_scmp = $3.pc; }
+ ;
+
+saddr: addr { if (nat->in_redir == NAT_REDIRECT) {
+ nat->in_srcip = $1.a.s_addr;
+ nat->in_srcmsk = $1.m.s_addr;
+ } else {
+ nat->in_inip = $1.a.s_addr;
+ nat->in_inmsk = $1.m.s_addr;
+ }
+ }
+ ;
+
+dobject:
+ daddr
+ | daddr IPNY_PORT portstuff { nat->in_dport = $3.p1;
+ nat->in_dtop = $3.p2;
+ nat->in_dcmp = $3.pc;
+ if (nat->in_redir == NAT_REDIRECT)
+ nat->in_pmin = htons($3.p1);
+ }
+ ;
+
+daddr: addr { if (nat->in_redir == NAT_REDIRECT) {
+ nat->in_outip = $1.a.s_addr;
+ nat->in_outmsk = $1.m.s_addr;
+ } else {
+ nat->in_srcip = $1.a.s_addr;
+ nat->in_srcmsk = $1.m.s_addr;
+ }
+ }
+ ;
+
+addr: IPNY_ANY { $$.a.s_addr = 0; $$.m.s_addr = 0; }
+ | nummask { $$.a = $1.a; $$.m = $1.m;
+ $$.a.s_addr &= $$.m.s_addr; }
+ | hostname '/' ipv4 { $$.a = $1; $$.m = $3;
+ $$.a.s_addr &= $$.m.s_addr; }
+ | hostname '/' hexnumber { $$.a = $1; $$.m.s_addr = $3;
+ $$.a.s_addr &= $$.m.s_addr; }
+ | hostname IPNY_MASK ipv4 { $$.a = $1; $$.m = $3;
+ $$.a.s_addr &= $$.m.s_addr; }
+ | hostname IPNY_MASK hexnumber { $$.a = $1; $$.m.s_addr = $3;
+ $$.a.s_addr &= $$.m.s_addr; }
+ ;
+
+nummask:
+ hostname { $$.a = $1;
+ $$.m.s_addr = 0xffffffff; }
+ | hostname '/' YY_NUMBER { $$.a = $1;
+ ntomask(4, $3, &$$.m.s_addr); }
+ ;
+
+portstuff:
+ compare portspec { $$.pc = $1; $$.p1 = $2; }
+ | portspec range portspec { $$.pc = $2; $$.p1 = $1; $$.p1 = $3; }
+ ;
+
+mapoptions:
+ rr frag age mssclamp nattag setproto
+ ;
+
+rdroptions:
+ rr frag age sticky mssclamp rdrproxy nattag
+ ;
+
+nattag: | IPNY_TAG YY_STR { strncpy(nat->in_tag.ipt_tag, $2,
+ sizeof(nat->in_tag.ipt_tag));
+ }
+rr: | IPNY_ROUNDROBIN { nat->in_flags |= IPN_ROUNDR; }
+ ;
+
+frag: | IPNY_FRAG { nat->in_flags |= IPN_FRAG; }
+ ;
+
+age: | IPNY_AGE YY_NUMBER { nat->in_age[0] = $2;
+ nat->in_age[1] = $2; }
+ | IPNY_AGE YY_NUMBER '/' YY_NUMBER { nat->in_age[0] = $2;
+ nat->in_age[1] = $4; }
+ ;
+
+sticky: | IPNY_STICKY { if (!(nat->in_flags & IPN_ROUNDR) &&
+ !(nat->in_flags & IPN_SPLIT)) {
+ fprintf(stderr,
+ "'sticky' for use with round-robin/IP splitting only\n");
+ } else
+ nat->in_flags |= IPN_STICKY;
+ }
+ ;
+
+mssclamp:
+ | IPNY_MSSCLAMP YY_NUMBER { nat->in_mssclamp = $2; }
+ ;
+
+tcpudp: | IPNY_TCP { setnatproto(IPPROTO_TCP); }
+ | IPNY_UDP { setnatproto(IPPROTO_UDP); }
+ | IPNY_TCPUDP { nat->in_flags |= IPN_TCPUDP;
+ nat->in_p = 0;
+ }
+ | IPNY_TCP '/' IPNY_UDP { nat->in_flags |= IPN_TCPUDP;
+ nat->in_p = 0;
+ }
+ ;
+
+rdrproxy:
+ IPNY_PROXY YY_STR
+ { strncpy(nat->in_plabel, $2,
+ sizeof(nat->in_plabel));
+ nat->in_dport = nat->in_pnext;
+ nat->in_dport = htons(nat->in_dport);
+ free($2);
+ }
+ | proxy { if (nat->in_plabel[0] != '\0') {
+ nat->in_pmin = nat->in_dport;
+ nat->in_pmax = nat->in_pmin;
+ nat->in_pnext = nat->in_pmin;
+ }
+ }
+ ;
+
+proto: YY_NUMBER { $$ = $1; }
+ | IPNY_TCP { $$ = IPPROTO_TCP; }
+ | IPNY_UDP { $$ = IPPROTO_UDP; }
+ | YY_STR { $$ = getproto($1); free($1); }
+ ;
+
+hexnumber:
+ YY_HEX { $$ = $1; }
+ ;
+
+hostname:
+ YY_STR { if (gethost($1, &$$.s_addr) == -1)
+ fprintf(stderr,
+ "Unknown host '%s'\n",
+ $1);
+ free($1);
+ }
+ | YY_NUMBER { $$.s_addr = htonl($1); }
+ | ipv4 { $$.s_addr = $1.s_addr; }
+ ;
+
+compare:
+ '=' { $$ = FR_EQUAL; }
+ | YY_CMP_EQ { $$ = FR_EQUAL; }
+ | YY_CMP_NE { $$ = FR_NEQUAL; }
+ | YY_CMP_LT { $$ = FR_LESST; }
+ | YY_CMP_LE { $$ = FR_LESSTE; }
+ | YY_CMP_GT { $$ = FR_GREATERT; }
+ | YY_CMP_GE { $$ = FR_GREATERTE; }
+
+range:
+ YY_RANGE_OUT { $$ = FR_OUTRANGE; }
+ | YY_RANGE_IN { $$ = FR_INRANGE; }
+ ;
+
+ipv4: YY_NUMBER '.' YY_NUMBER '.' YY_NUMBER '.' YY_NUMBER
+ { if ($1 > 255 || $3 > 255 || $5 > 255 || $7 > 255) {
+ yyerror("Invalid octet string for IP address");
+ return 0;
+ }
+ $$.s_addr = ($1 << 24) | ($3 << 16) | ($5 << 8) | $7;
+ $$.s_addr = htonl($$.s_addr);
+ }
+ ;
+
+%%
+
+
+static wordtab_t yywords[] = {
+ { "age", IPNY_AGE },
+ { "any", IPNY_ANY },
+ { "auto", IPNY_AUTO },
+ { "bimap", IPNY_BIMAP },
+ { "frag", IPNY_FRAG },
+ { "from", IPNY_FROM },
+ { "icmpidmap", IPNY_ICMPIDMAP },
+ { "mask", IPNY_MASK },
+ { "map", IPNY_MAP },
+ { "map-block", IPNY_MAPBLOCK },
+ { "mssclamp", IPNY_MSSCLAMP },
+ { "netmask", IPNY_MASK },
+ { "port", IPNY_PORT },
+ { "portmap", IPNY_PORTMAP },
+ { "ports", IPNY_PORTS },
+ { "proxy", IPNY_PROXY },
+ { "range", IPNY_RANGE },
+ { "rdr", IPNY_RDR },
+ { "round-robin",IPNY_ROUNDROBIN },
+ { "sticky", IPNY_STICKY },
+ { "tag", IPNY_TAG },
+ { "tcp", IPNY_TCP },
+ { "tcpudp", IPNY_TCPUDP },
+ { "to", IPNY_TO },
+ { "udp", IPNY_UDP },
+ { "-", '-' },
+ { "->", IPNY_TLATE },
+ { "eq", YY_CMP_EQ },
+ { "ne", YY_CMP_NE },
+ { "lt", YY_CMP_LT },
+ { "gt", YY_CMP_GT },
+ { "le", YY_CMP_LE },
+ { "ge", YY_CMP_GE },
+ { NULL, 0 }
+};
+
+
+int ipnat_parsefile(fd, addfunc, ioctlfunc, filename)
+int fd;
+addfunc_t addfunc;
+ioctlfunc_t ioctlfunc;
+char *filename;
+{
+ FILE *fp = NULL;
+ char *s;
+
+ (void) yysettab(yywords);
+
+ s = getenv("YYDEBUG");
+ if (s)
+ yydebug = atoi(s);
+ else
+ yydebug = 0;
+
+ if (strcmp(filename, "-")) {
+ fp = fopen(filename, "r");
+ if (!fp) {
+ fprintf(stderr, "fopen(%s) failed: %s\n", filename,
+ STRERROR(errno));
+ return -1;
+ }
+ } else
+ fp = stdin;
+
+ while (ipnat_parsesome(fd, addfunc, ioctlfunc, fp) == 1)
+ ;
+ if (fp != NULL)
+ fclose(fp);
+ return 0;
+}
+
+
+int ipnat_parsesome(fd, addfunc, ioctlfunc, fp)
+int fd;
+addfunc_t addfunc;
+ioctlfunc_t ioctlfunc;
+FILE *fp;
+{
+ char *s;
+ int i;
+
+ yylineNum = 1;
+
+ natfd = fd;
+ nataddfunc = addfunc;
+ natioctlfunc = ioctlfunc;
+
+ if (feof(fp))
+ return 0;
+ i = fgetc(fp);
+ if (i == EOF)
+ return 0;
+ if (ungetc(i, fp) == EOF)
+ return 0;
+ if (feof(fp))
+ return 0;
+ s = getenv("YYDEBUG");
+ if (s)
+ yydebug = atoi(s);
+ else
+ yydebug = 0;
+
+ yyin = fp;
+ yyparse();
+ return 1;
+}
+
+
+static void newnatrule()
+{
+ ipnat_t *n;
+
+ n = calloc(1, sizeof(*n));
+ if (n == NULL)
+ return;
+
+ if (nat == NULL)
+ nattop = nat = n;
+ else {
+ nat->in_next = n;
+ nat = n;
+ }
+}
+
+
+static void setnatproto(p)
+int p;
+{
+ nat->in_p = p;
+
+ switch (p)
+ {
+ case IPPROTO_TCP :
+ nat->in_flags |= IPN_TCP;
+ nat->in_flags &= ~IPN_UDP;
+ break;
+ case IPPROTO_UDP :
+ nat->in_flags |= IPN_UDP;
+ nat->in_flags &= ~IPN_TCP;
+ break;
+ case IPPROTO_ICMP :
+ nat->in_flags &= ~IPN_TCPUDP;
+ if (!(nat->in_flags & IPN_ICMPQUERY)) {
+ nat->in_dcmp = 0;
+ nat->in_scmp = 0;
+ nat->in_pmin = 0;
+ nat->in_pmax = 0;
+ nat->in_pnext = 0;
+ }
+ break;
+ default :
+ if ((nat->in_redir & NAT_MAPBLK) == 0) {
+ nat->in_flags &= ~IPN_TCPUDP;
+ nat->in_dcmp = 0;
+ nat->in_scmp = 0;
+ nat->in_pmin = 0;
+ nat->in_pmax = 0;
+ nat->in_pnext = 0;
+ }
+ break;
+ }
+
+ if ((nat->in_flags & (IPN_TCPUDP|IPN_FIXEDDPORT)) == IPN_FIXEDDPORT)
+ nat->in_flags &= ~IPN_FIXEDDPORT;
+}
+
+
+void ipnat_addrule(fd, ioctlfunc, ptr)
+int fd;
+ioctlfunc_t ioctlfunc;
+void *ptr;
+{
+ ioctlcmd_t add, del;
+ ipfobj_t obj;
+ ipnat_t *ipn;
+
+ ipn = ptr;
+ bzero((char *)&obj, sizeof(obj));
+ obj.ipfo_rev = IPFILTER_VERSION;
+ obj.ipfo_size = sizeof(ipnat_t);
+ obj.ipfo_type = IPFOBJ_IPNAT;
+ obj.ipfo_ptr = ptr;
+ add = 0;
+ del = 0;
+
+ if ((opts & OPT_DONOTHING) != 0)
+ fd = -1;
+
+ if (opts & OPT_ZERORULEST) {
+ add = SIOCZRLST;
+ } else if (opts & OPT_INACTIVE) {
+ add = SIOCADNAT;
+ del = SIOCRMNAT;
+ } else {
+ add = SIOCADNAT;
+ del = SIOCRMNAT;
+ }
+
+ if (ipn && (opts & OPT_VERBOSE))
+ printnat(ipn, opts);
+
+ if (opts & OPT_DEBUG)
+ binprint(ipn, sizeof(*ipn));
+
+ if ((opts & OPT_ZERORULEST) != 0) {
+ if ((*ioctlfunc)(fd, add, (void *)&obj) == -1) {
+ if ((opts & OPT_DONOTHING) == 0) {
+ fprintf(stderr, "%d:", yylineNum);
+ perror("ioctl(SIOCZRLST)");
+ }
+ } else {
+#ifdef USE_QUAD_T
+/*
+ printf("hits %qd bytes %qd ",
+ (long long)fr->fr_hits,
+ (long long)fr->fr_bytes);
+*/
+#else
+/*
+ printf("hits %ld bytes %ld ",
+ fr->fr_hits, fr->fr_bytes);
+*/
+#endif
+ printnat(ipn, opts);
+ }
+ } else if ((opts & OPT_REMOVE) != 0) {
+ if ((*ioctlfunc)(fd, del, (void *)&obj) == -1) {
+ if ((opts & OPT_DONOTHING) == 0) {
+ fprintf(stderr, "%d:", yylineNum);
+ perror("ioctl(delete nat rule)");
+ }
+ }
+ } else {
+ if ((*ioctlfunc)(fd, add, (void *)&obj) == -1) {
+ if ((opts & OPT_DONOTHING) == 0) {
+ fprintf(stderr, "%d:", yylineNum);
+ perror("ioctl(add/insert nat rule)");
+ }
+ }
+ }
+}
diff --git a/contrib/ipfilter/tools/ippool.c b/contrib/ipfilter/tools/ippool.c
new file mode 100644
index 0000000..7122c94
--- /dev/null
+++ b/contrib/ipfilter/tools/ippool.c
@@ -0,0 +1,700 @@
+/* $NetBSD$ */
+
+/*
+ * Copyright (C) 2003 by Darren Reed.
+ *
+ * See the IPFILTER.LICENCE file for details on licencing.
+ */
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+#if defined(BSD) && (BSD >= 199306)
+# include <sys/cdefs.h>
+#endif
+#include <sys/ioctl.h>
+
+#include <net/if.h>
+#if __FreeBSD_version >= 300000
+# include <net/if_var.h>
+#endif
+#include <netinet/in.h>
+
+#include <arpa/inet.h>
+
+#include <stdio.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <netdb.h>
+#include <ctype.h>
+#include <unistd.h>
+
+#include "ipf.h"
+#include "netinet/ip_lookup.h"
+#include "netinet/ip_pool.h"
+#include "netinet/ip_htable.h"
+#include "kmem.h"
+
+
+extern int ippool_yyparse __P((void));
+extern int ippool_yydebug;
+extern FILE *ippool_yyin;
+extern char *optarg;
+extern int lineNum;
+
+void showpools __P((ip_pool_stat_t *));
+void usage __P((char *));
+int main __P((int, char **));
+int poolcommand __P((int, int, char *[]));
+int poolnodecommand __P((int, int, char *[]));
+int loadpoolfile __P((int, char *[], char *));
+int poollist __P((int, char *[]));
+int poolflush __P((int, char *[]));
+int poolstats __P((int, char *[]));
+int gettype __P((char *, u_int *));
+int getrole __P((char *));
+
+int opts = 0;
+int fd = -1;
+int use_inet6 = 0;
+
+
+void usage(prog)
+char *prog;
+{
+ fprintf(stderr, "Usage:\t%s\n", prog);
+ fprintf(stderr, "\t\t\t-a [-dnv] [-m <name>] [-o <role>] -i <ipaddr>[/netmask]\n");
+ fprintf(stderr, "\t\t\t-A [-dnv] [-m <name>] [-o <role>] [-S <seed>] [-t <type>]\n");
+ fprintf(stderr, "\t\t\t-f <file> [-dnuv]\n");
+ fprintf(stderr, "\t\t\t-F [-dv] [-o <role>] [-t <type>]\n");
+ fprintf(stderr, "\t\t\t-l [-dv] [-m <name>] [-t <type>]\n");
+ fprintf(stderr, "\t\t\t-r [-dnv] [-m <name>] [-o <role>] -i <ipaddr>[/netmask]\n");
+ fprintf(stderr, "\t\t\t-R [-dnv] [-m <name>] [-o <role>] [-t <type>]\n");
+ fprintf(stderr, "\t\t\t-s [-dtv] [-M <core>] [-N <namelist>]\n");
+ exit(1);
+}
+
+
+int main(argc, argv)
+int argc;
+char *argv[];
+{
+ int err;
+
+ if (argc < 2)
+ usage(argv[0]);
+
+ switch (getopt(argc, argv, "aAf:FlrRs"))
+ {
+ case 'a' :
+ err = poolnodecommand(0, argc, argv);
+ break;
+ case 'A' :
+ err = poolcommand(0, argc, argv);
+ break;
+ case 'f' :
+ err = loadpoolfile(argc, argv, optarg);
+ break;
+ case 'F' :
+ err = poolflush(argc, argv);
+ break;
+ case 'l' :
+ err = poollist(argc, argv);
+ break;
+ case 'r' :
+ err = poolnodecommand(1, argc, argv);
+ break;
+ case 'R' :
+ err = poolcommand(1, argc, argv);
+ break;
+ case 's' :
+ err = poolstats(argc, argv);
+ break;
+ default :
+ exit(1);
+ }
+
+ return err;
+}
+
+
+int poolnodecommand(remove, argc, argv)
+int remove, argc;
+char *argv[];
+{
+ char *poolname = NULL, *s;
+ int err, c, ipset, role;
+ ip_pool_node_t node;
+ struct in_addr mask;
+
+ ipset = 0;
+ role = IPL_LOGIPF;
+ bzero((char *)&node, sizeof(node));
+
+ while ((c = getopt(argc, argv, "di:m:no:Rv")) != -1)
+ switch (c)
+ {
+ case 'd' :
+ opts |= OPT_DEBUG;
+ ippool_yydebug++;
+ break;
+ case 'i' :
+ s = strchr(optarg, '/');
+ if (s == NULL)
+ mask.s_addr = 0xffffffff;
+ else if (strchr(s, '.') == NULL) {
+ if (ntomask(4, atoi(s + 1), &mask.s_addr) != 0)
+ return -1;
+ } else {
+ mask.s_addr = inet_addr(s + 1);
+ }
+ if (s != NULL)
+ *s = '\0';
+ ipset = 1;
+ node.ipn_addr.adf_len = sizeof(node.ipn_addr);
+ node.ipn_addr.adf_addr.in4.s_addr = inet_addr(optarg);
+ node.ipn_mask.adf_len = sizeof(node.ipn_mask);
+ node.ipn_mask.adf_addr.in4.s_addr = mask.s_addr;
+ break;
+ case 'm' :
+ poolname = optarg;
+ break;
+ case 'n' :
+ opts |= OPT_DONOTHING;
+ break;
+ case 'o' :
+ role = getrole(optarg);
+ if (role == IPL_LOGNONE)
+ return -1;
+ break;
+ case 'R' :
+ opts |= OPT_NORESOLVE;
+ break;
+ case 'v' :
+ opts |= OPT_VERBOSE;
+ break;
+ }
+
+ if (opts & OPT_DEBUG)
+ fprintf(stderr, "poolnodecommand: opts = %#x\n", opts);
+
+ if (ipset == 0)
+ return -1;
+ if (poolname == NULL) {
+ fprintf(stderr, "poolname not given with add/remove node\n");
+ return -1;
+ }
+
+ if (remove == 0)
+ err = load_poolnode(0, poolname, &node, ioctl);
+ else
+ err = remove_poolnode(0, poolname, &node, ioctl);
+ return err;
+}
+
+
+int poolcommand(remove, argc, argv)
+int remove, argc;
+char *argv[];
+{
+ int type, role, c, err;
+ char *poolname;
+ iphtable_t iph;
+ ip_pool_t pool;
+
+ err = 1;
+ role = 0;
+ type = 0;
+ poolname = NULL;
+ role = IPL_LOGIPF;
+ bzero((char *)&iph, sizeof(iph));
+ bzero((char *)&pool, sizeof(pool));
+
+ while ((c = getopt(argc, argv, "dm:no:RSt:v")) != -1)
+ switch (c)
+ {
+ case 'd' :
+ opts |= OPT_DEBUG;
+ ippool_yydebug++;
+ break;
+ case 'm' :
+ poolname = optarg;
+ break;
+ case 'n' :
+ opts |= OPT_DONOTHING;
+ break;
+ case 'o' :
+ role = getrole(optarg);
+ if (role == IPL_LOGNONE) {
+ fprintf(stderr, "unknown role '%s'\n", optarg);
+ return -1;
+ }
+ break;
+ case 'R' :
+ opts |= OPT_NORESOLVE;
+ break;
+ case 'S' :
+ iph.iph_seed = atoi(optarg);
+ break;
+ case 't' :
+ type = gettype(optarg, &iph.iph_type);
+ if (type == IPLT_NONE) {
+ fprintf(stderr, "unknown type '%s'\n", optarg);
+ return -1;
+ }
+ break;
+ case 'v' :
+ opts |= OPT_VERBOSE;
+ break;
+ }
+
+ if (opts & OPT_DEBUG)
+ fprintf(stderr, "poolcommand: opts = %#x\n", opts);
+
+ if (poolname == NULL) {
+ fprintf(stderr, "poolname not given with add/remove pool\n");
+ return -1;
+ }
+
+ if (type == IPLT_HASH) {
+ strncpy(iph.iph_name, poolname, sizeof(iph.iph_name));
+ iph.iph_name[sizeof(iph.iph_name) - 1] = '\0';
+ iph.iph_unit = role;
+ } else if (type == IPLT_POOL) {
+ strncpy(pool.ipo_name, poolname, sizeof(pool.ipo_name));
+ pool.ipo_name[sizeof(pool.ipo_name) - 1] = '\0';
+ pool.ipo_unit = role;
+ }
+
+ if (remove == 0) {
+ switch (type)
+ {
+ case IPLT_HASH :
+ err = load_hash(&iph, NULL, ioctl);
+ break;
+ case IPLT_POOL :
+ err = load_pool(&pool, ioctl);
+ break;
+ }
+ } else {
+ switch (type)
+ {
+ case IPLT_HASH :
+ err = remove_hash(&iph, ioctl);
+ break;
+ case IPLT_POOL :
+ err = remove_pool(&pool, ioctl);
+ break;
+ }
+ }
+ return err;
+}
+
+
+int loadpoolfile(argc, argv, infile)
+int argc;
+char *argv[], *infile;
+{
+ int c;
+
+ infile = optarg;
+
+ while ((c = getopt(argc, argv, "dnRuv")) != -1)
+ switch (c)
+ {
+ case 'd' :
+ opts |= OPT_DEBUG;
+ ippool_yydebug++;
+ break;
+ case 'n' :
+ opts |= OPT_DONOTHING;
+ break;
+ case 'R' :
+ opts |= OPT_NORESOLVE;
+ break;
+ case 'u' :
+ opts |= OPT_REMOVE;
+ break;
+ case 'v' :
+ opts |= OPT_VERBOSE;
+ break;
+ }
+
+ if (opts & OPT_DEBUG)
+ fprintf(stderr, "loadpoolfile: opts = %#x\n", opts);
+
+ if (!(opts & OPT_DONOTHING) && (fd == -1)) {
+ fd = open(IPLOOKUP_NAME, O_RDWR);
+ if (fd == -1) {
+ perror("open(IPLOOKUP_NAME)");
+ exit(1);
+ }
+ }
+
+ if (ippool_parsefile(fd, infile, ioctl) != 0)
+ return -1;
+ return 0;
+}
+
+
+int poollist(argc, argv)
+int argc;
+char *argv[];
+{
+ char *kernel, *core, *poolname;
+ int c, role, type, live_kernel;
+ ip_pool_stat_t *plstp, plstat;
+ iphtstat_t *htstp, htstat;
+ iphtable_t *hptr;
+ iplookupop_t op;
+ ip_pool_t *ptr;
+
+ core = NULL;
+ kernel = NULL;
+ live_kernel = 1;
+ type = IPLT_ALL;
+ poolname = NULL;
+ role = IPL_LOGALL;
+
+ while ((c = getopt(argc, argv, "dm:M:N:o:Rt:v")) != -1)
+ switch (c)
+ {
+ case 'd' :
+ opts |= OPT_DEBUG;
+ break;
+ case 'm' :
+ poolname = optarg;
+ break;
+ case 'M' :
+ live_kernel = 0;
+ core = optarg;
+ break;
+ case 'N' :
+ live_kernel = 0;
+ kernel = optarg;
+ break;
+ case 'o' :
+ role = getrole(optarg);
+ if (role == IPL_LOGNONE) {
+ fprintf(stderr, "unknown role '%s'\n", optarg);
+ return -1;
+ }
+ break;
+ case 'R' :
+ opts |= OPT_NORESOLVE;
+ break;
+ case 't' :
+ type = gettype(optarg, NULL);
+ if (type == IPLT_NONE) {
+ fprintf(stderr, "unknown type '%s'\n", optarg);
+ return -1;
+ }
+ break;
+ case 'v' :
+ opts |= OPT_VERBOSE;
+ break;
+ }
+
+ if (opts & OPT_DEBUG)
+ fprintf(stderr, "poollist: opts = %#x\n", opts);
+
+ if (!(opts & OPT_DONOTHING) && (fd == -1)) {
+ fd = open(IPLOOKUP_NAME, O_RDWR);
+ if (fd == -1) {
+ perror("open(IPLOOKUP_NAME)");
+ exit(1);
+ }
+ }
+
+ bzero((char *)&op, sizeof(op));
+ if (poolname != NULL) {
+ strncpy(op.iplo_name, poolname, sizeof(op.iplo_name));
+ op.iplo_name[sizeof(op.iplo_name) - 1] = '\0';
+ }
+ op.iplo_unit = role;
+
+ if (openkmem(kernel, core) == -1)
+ exit(-1);
+
+ if (type == IPLT_ALL || type == IPLT_POOL) {
+ plstp = &plstat;
+ op.iplo_type = IPLT_POOL;
+ op.iplo_size = sizeof(plstat);
+ op.iplo_struct = &plstat;
+ c = ioctl(fd, SIOCLOOKUPSTAT, &op);
+ if (c == -1) {
+ perror("ioctl(SIOCLOOKUPSTAT)");
+ return -1;
+ }
+
+ if (role != IPL_LOGALL) {
+ ptr = plstp->ipls_list[role];
+ while (ptr != NULL) {
+ ptr = printpool(ptr, kmemcpywrap, poolname,
+ opts);
+ }
+ } else {
+ for (role = 0; role <= IPL_LOGMAX; role++) {
+ ptr = plstp->ipls_list[role];
+ while (ptr != NULL) {
+ ptr = printpool(ptr, kmemcpywrap,
+ poolname, opts);
+ }
+ }
+ role = IPL_LOGALL;
+ }
+ }
+ if (type == IPLT_ALL || type == IPLT_HASH) {
+ htstp = &htstat;
+ op.iplo_type = IPLT_HASH;
+ op.iplo_size = sizeof(htstat);
+ op.iplo_struct = &htstat;
+ c = ioctl(fd, SIOCLOOKUPSTAT, &op);
+ if (c == -1) {
+ perror("ioctl(SIOCLOOKUPSTAT)");
+ return -1;
+ }
+
+ if (role != IPL_LOGALL) {
+ hptr = htstp->iphs_tables;
+ while (hptr != NULL) {
+ hptr = printhash(hptr, kmemcpywrap,
+ poolname, opts);
+ }
+ } else {
+ for (role = 0; role <= IPL_LOGMAX; role++) {
+ hptr = htstp->iphs_tables;
+ while (hptr != NULL) {
+ hptr = printhash(hptr, kmemcpywrap,
+ poolname, opts);
+ }
+
+ op.iplo_unit = role;
+ c = ioctl(fd, SIOCLOOKUPSTAT, &op);
+ if (c == -1) {
+ perror("ioctl(SIOCLOOKUPSTAT)");
+ return -1;
+ }
+ }
+ }
+ }
+ return 0;
+}
+
+
+int poolstats(argc, argv)
+int argc;
+char *argv[];
+{
+ int c, type, role, live_kernel;
+ ip_pool_stat_t plstat;
+ char *kernel, *core;
+ iphtstat_t htstat;
+ iplookupop_t op;
+
+ core = NULL;
+ kernel = NULL;
+ live_kernel = 1;
+ type = IPLT_ALL;
+ role = IPL_LOGALL;
+
+ bzero((char *)&op, sizeof(op));
+
+ while ((c = getopt(argc, argv, "dM:N:o:t:v")) != -1)
+ switch (c)
+ {
+ case 'd' :
+ opts |= OPT_DEBUG;
+ break;
+ case 'M' :
+ live_kernel = 0;
+ core = optarg;
+ break;
+ case 'N' :
+ live_kernel = 0;
+ kernel = optarg;
+ break;
+ case 'o' :
+ role = getrole(optarg);
+ if (role == IPL_LOGNONE) {
+ fprintf(stderr, "unknown role '%s'\n", optarg);
+ return -1;
+ }
+ break;
+ case 't' :
+ type = gettype(optarg, NULL);
+ if (type != IPLT_POOL) {
+ fprintf(stderr,
+ "-s not supported for this type yet\n");
+ return -1;
+ }
+ break;
+ case 'v' :
+ opts |= OPT_VERBOSE;
+ break;
+ }
+
+ if (opts & OPT_DEBUG)
+ fprintf(stderr, "poolstats: opts = %#x\n", opts);
+
+ if (!(opts & OPT_DONOTHING) && (fd == -1)) {
+ fd = open(IPLOOKUP_NAME, O_RDWR);
+ if (fd == -1) {
+ perror("open(IPLOOKUP_NAME)");
+ exit(1);
+ }
+ }
+
+ if (type == IPLT_ALL || type == IPLT_POOL) {
+ op.iplo_type = IPLT_POOL;
+ op.iplo_struct = &plstat;
+ op.iplo_size = sizeof(plstat);
+ if (!(opts & OPT_DONOTHING)) {
+ c = ioctl(fd, SIOCLOOKUPSTAT, &op);
+ if (c == -1) {
+ perror("ioctl(SIOCLOOKUPSTAT)");
+ return -1;
+ }
+ printf("Pools:\t%lu\n", plstat.ipls_pools);
+ printf("Nodes:\t%lu\n", plstat.ipls_nodes);
+ }
+ }
+
+ if (type == IPLT_ALL || type == IPLT_HASH) {
+ op.iplo_type = IPLT_HASH;
+ op.iplo_struct = &htstat;
+ op.iplo_size = sizeof(htstat);
+ if (!(opts & OPT_DONOTHING)) {
+ c = ioctl(fd, SIOCLOOKUPSTAT, &op);
+ if (c == -1) {
+ perror("ioctl(SIOCLOOKUPSTAT)");
+ return -1;
+ }
+ printf("Hash Tables:\t%lu\n", htstat.iphs_numtables);
+ printf("Nodes:\t%lu\n", htstat.iphs_numnodes);
+ printf("Out of Memory:\t%lu\n", htstat.iphs_nomem);
+ }
+ }
+ return 0;
+}
+
+
+int poolflush(argc, argv)
+int argc;
+char *argv[];
+{
+ int c, role, type, arg;
+ iplookupflush_t flush;
+
+ arg = IPLT_ALL;
+ type = IPLT_ALL;
+ role = IPL_LOGALL;
+
+ while ((c = getopt(argc, argv, "do:t:v")) != -1)
+ switch (c)
+ {
+ case 'd' :
+ opts |= OPT_DEBUG;
+ break;
+ case 'o' :
+ role = getrole(optarg);
+ if (role == IPL_LOGNONE) {
+ fprintf(stderr, "unknown role '%s'\n", optarg);
+ return -1;
+ }
+ break;
+ case 't' :
+ type = gettype(optarg, NULL);
+ if (type == IPLT_NONE) {
+ fprintf(stderr, "unknown type '%s'\n", optarg);
+ return -1;
+ }
+ break;
+ case 'v' :
+ opts |= OPT_VERBOSE;
+ break;
+ }
+
+ if (opts & OPT_DEBUG)
+ fprintf(stderr, "poolflush: opts = %#x\n", opts);
+
+ if (!(opts & OPT_DONOTHING) && (fd == -1)) {
+ fd = open(IPLOOKUP_NAME, O_RDWR);
+ if (fd == -1) {
+ perror("open(IPLOOKUP_NAME)");
+ exit(1);
+ }
+ }
+
+ bzero((char *)&flush, sizeof(flush));
+ flush.iplf_type = type;
+ flush.iplf_unit = role;
+ flush.iplf_arg = arg;
+
+ if (!(opts & OPT_DONOTHING)) {
+ if (ioctl(fd, SIOCLOOKUPFLUSH, &flush) == -1) {
+ perror("ioctl(SIOCLOOKUPFLUSH)");
+ exit(1);
+ }
+
+ }
+ printf("%u object%s flushed\n", flush.iplf_count,
+ (flush.iplf_count == 1) ? "" : "s");
+
+ return 0;
+}
+
+
+int getrole(rolename)
+char *rolename;
+{
+ int role;
+
+ if (!strcasecmp(rolename, "ipf")) {
+ role = IPL_LOGIPF;
+#if 0
+ } else if (!strcasecmp(rolename, "nat")) {
+ role = IPL_LOGNAT;
+ } else if (!strcasecmp(rolename, "state")) {
+ role = IPL_LOGSTATE;
+ } else if (!strcasecmp(rolename, "auth")) {
+ role = IPL_LOGAUTH;
+ } else if (!strcasecmp(rolename, "sync")) {
+ role = IPL_LOGSYNC;
+ } else if (!strcasecmp(rolename, "scan")) {
+ role = IPL_LOGSCAN;
+ } else if (!strcasecmp(rolename, "pool")) {
+ role = IPL_LOGLOOKUP;
+ } else if (!strcasecmp(rolename, "count")) {
+ role = IPL_LOGCOUNT;
+#endif
+ } else {
+ role = IPL_LOGNONE;
+ }
+
+ return role;
+}
+
+
+int gettype(typename, minor)
+char *typename;
+u_int *minor;
+{
+ int type;
+
+ if (!strcasecmp(optarg, "tree")) {
+ type = IPLT_POOL;
+ } else if (!strcasecmp(optarg, "hash")) {
+ type = IPLT_HASH;
+ if (minor != NULL)
+ *minor = IPHASH_LOOKUP;
+ } else if (!strcasecmp(optarg, "group-map")) {
+ type = IPLT_HASH;
+ if (minor != NULL)
+ *minor = IPHASH_GROUPMAP;
+ } else {
+ type = IPLT_NONE;
+ }
+ return type;
+}
diff --git a/contrib/ipfilter/tools/ippool_y.y b/contrib/ipfilter/tools/ippool_y.y
new file mode 100644
index 0000000..357745d
--- /dev/null
+++ b/contrib/ipfilter/tools/ippool_y.y
@@ -0,0 +1,415 @@
+/* $NetBSD$ */
+
+%{
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+#if defined(BSD) && (BSD >= 199306)
+# include <sys/cdefs.h>
+#endif
+#include <sys/ioctl.h>
+
+#include <net/if.h>
+#if __FreeBSD_version >= 300000
+# include <net/if_var.h>
+#endif
+#include <netinet/in.h>
+
+#include <arpa/inet.h>
+
+#include <stdio.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <netdb.h>
+#include <ctype.h>
+#include <unistd.h>
+
+#include "ipf.h"
+#include "netinet/ip_lookup.h"
+#include "netinet/ip_pool.h"
+#include "netinet/ip_htable.h"
+#include "ippool_l.h"
+#include "kmem.h"
+
+#define YYDEBUG 1
+
+extern int yyparse __P((void));
+extern int yydebug;
+extern FILE *yyin;
+
+static iphtable_t ipht;
+static iphtent_t iphte;
+static ip_pool_t iplo;
+static ioctlfunc_t poolioctl = NULL;
+static char poolname[FR_GROUPLEN];
+
+%}
+
+%union {
+ char *str;
+ u_32_t num;
+ struct in_addr addr;
+ struct alist_s *alist;
+ struct in_addr adrmsk[2];
+ iphtent_t *ipe;
+ ip_pool_node_t *ipp;
+ union i6addr ip6;
+}
+
+%token <num> YY_NUMBER YY_HEX
+%token <str> YY_STR
+%token YY_COMMENT
+%token YY_CMP_EQ YY_CMP_NE YY_CMP_LE YY_CMP_GE YY_CMP_LT YY_CMP_GT
+%token YY_RANGE_OUT YY_RANGE_IN
+%token <ip6> YY_IPV6
+
+%token IPT_IPF IPT_NAT IPT_COUNT IPT_AUTH IPT_IN IPT_OUT
+%token IPT_TABLE IPT_GROUPMAP IPT_HASH
+%token IPT_ROLE IPT_TYPE IPT_TREE
+%token IPT_GROUP IPT_SIZE IPT_SEED IPT_NUM IPT_NAME
+%type <num> role table inout
+%type <ipp> ipftree range addrlist
+%type <adrmsk> addrmask
+%type <ipe> ipfgroup ipfhash hashlist hashentry
+%type <ipe> groupentry setgrouplist grouplist
+%type <addr> ipaddr mask ipv4
+%type <str> number setgroup
+
+%%
+file: line
+ | assign
+ | file line
+ | file assign
+ ;
+
+line: table role ipftree eol { iplo.ipo_unit = $2;
+ iplo.ipo_list = $3;
+ load_pool(&iplo, poolioctl);
+ resetlexer();
+ }
+ | table role ipfhash eol { ipht.iph_unit = $2;
+ ipht.iph_type = IPHASH_LOOKUP;
+ load_hash(&ipht, $3, poolioctl);
+ resetlexer();
+ }
+ | groupmap role number ipfgroup eol
+ { ipht.iph_unit = $2;
+ strncpy(ipht.iph_name, $3,
+ sizeof(ipht.iph_name));
+ ipht.iph_type = IPHASH_GROUPMAP;
+ load_hash(&ipht, $4, poolioctl);
+ resetlexer();
+ }
+ | YY_COMMENT
+ ;
+
+eol: ';'
+ ;
+
+assign: YY_STR assigning YY_STR ';' { set_variable($1, $3);
+ resetlexer();
+ free($1);
+ free($3);
+ }
+ ;
+
+assigning:
+ '=' { yyvarnext = 1; }
+ ;
+
+table: IPT_TABLE { bzero((char *)&ipht, sizeof(ipht));
+ bzero((char *)&iphte, sizeof(iphte));
+ bzero((char *)&iplo, sizeof(iplo));
+ *ipht.iph_name = '\0';
+ iplo.ipo_flags = IPHASH_ANON;
+ iplo.ipo_name[0] = '\0';
+ }
+ ;
+
+groupmap:
+ IPT_GROUPMAP inout { bzero((char *)&ipht, sizeof(ipht));
+ bzero((char *)&iphte, sizeof(iphte));
+ *ipht.iph_name = '\0';
+ ipht.iph_unit = IPHASH_GROUPMAP;
+ ipht.iph_flags = $2;
+ }
+ ;
+
+inout: IPT_IN { $$ = FR_INQUE; }
+ | IPT_OUT { $$ = FR_OUTQUE; }
+ ;
+role:
+ IPT_ROLE '=' IPT_IPF { $$ = IPL_LOGIPF; }
+ | IPT_ROLE '=' IPT_NAT { $$ = IPL_LOGNAT; }
+ | IPT_ROLE '=' IPT_AUTH { $$ = IPL_LOGAUTH; }
+ | IPT_ROLE '=' IPT_COUNT { $$ = IPL_LOGCOUNT; }
+ ;
+
+ipftree:
+ IPT_TYPE '=' IPT_TREE number start addrlist end
+ { strncpy(iplo.ipo_name, $4,
+ sizeof(iplo.ipo_name));
+ $$ = $6;
+ }
+ ;
+
+ipfhash:
+ IPT_TYPE '=' IPT_HASH number hashopts start hashlist end
+ { strncpy(ipht.iph_name, $4,
+ sizeof(ipht.iph_name));
+ $$ = $7;
+ }
+ ;
+
+ipfgroup:
+ setgroup hashopts start grouplist end
+ { iphtent_t *e;
+ for (e = $4; e != NULL;
+ e = e->ipe_next)
+ if (e->ipe_group[0] == '\0')
+ strncpy(e->ipe_group,
+ $1,
+ FR_GROUPLEN);
+ $$ = $4;
+ }
+ | hashopts start setgrouplist end { $$ = $3; }
+ ;
+
+number: IPT_NUM '=' YY_NUMBER { sprintf(poolname, "%u", $3);
+ $$ = poolname;
+ }
+ | IPT_NAME '=' YY_STR { $$ = $3; }
+ | { $$ = ""; }
+ ;
+
+setgroup:
+ IPT_GROUP '=' YY_STR { char tmp[FR_GROUPLEN+1];
+ strncpy(tmp, $3, FR_GROUPLEN);
+ $$ = strdup(tmp);
+ }
+ | IPT_GROUP '=' YY_NUMBER { char tmp[FR_GROUPLEN+1];
+ sprintf(tmp, "%u", $3);
+ $$ = strdup(tmp);
+ }
+ ;
+
+hashopts:
+ | size
+ | seed
+ | size seed
+ ;
+
+addrlist:
+ next { $$ = NULL; }
+ | range next addrlist { $1->ipn_next = $3; $$ = $1; }
+ | range next { $$ = $1; }
+ ;
+
+grouplist:
+ next { $$ = NULL; }
+ | groupentry next grouplist { $$ = $1; $1->ipe_next = $3; }
+ | addrmask next grouplist { $$ = calloc(1, sizeof(iphtent_t));
+ bcopy((char *)&($1[0]),
+ (char *)&($$->ipe_addr),
+ sizeof($$->ipe_addr));
+ bcopy((char *)&($1[1]),
+ (char *)&($$->ipe_mask),
+ sizeof($$->ipe_mask));
+ $$->ipe_next = $3;
+ }
+ | groupentry next { $$ = $1; }
+ | addrmask next { $$ = calloc(1, sizeof(iphtent_t));
+ bcopy((char *)&($1[0]),
+ (char *)&($$->ipe_addr),
+ sizeof($$->ipe_addr));
+ bcopy((char *)&($1[1]),
+ (char *)&($$->ipe_mask),
+ sizeof($$->ipe_mask));
+ }
+ ;
+
+setgrouplist:
+ next { $$ = NULL; }
+ | groupentry next { $$ = $1; }
+ | groupentry next setgrouplist { $1->ipe_next = $3; $$ = $1; }
+ ;
+
+groupentry:
+ addrmask ',' setgroup { $$ = calloc(1, sizeof(iphtent_t));
+ bcopy((char *)&($1[0]),
+ (char *)&($$->ipe_addr),
+ sizeof($$->ipe_addr));
+ bcopy((char *)&($1[1]),
+ (char *)&($$->ipe_mask),
+ sizeof($$->ipe_mask));
+ strncpy($$->ipe_group, $3,
+ FR_GROUPLEN);
+ free($3);
+ }
+ ;
+
+range: addrmask { $$ = calloc(1, sizeof(*$$));
+ $$->ipn_info = 0;
+ $$->ipn_addr.adf_len = sizeof($$->ipn_addr);
+ $$->ipn_addr.adf_addr.in4.s_addr = $1[0].s_addr;
+ $$->ipn_mask.adf_len = sizeof($$->ipn_mask);
+ $$->ipn_mask.adf_addr.in4.s_addr = $1[1].s_addr;
+ }
+ | '!' addrmask { $$ = calloc(1, sizeof(*$$));
+ $$->ipn_info = 1;
+ $$->ipn_addr.adf_len = sizeof($$->ipn_addr);
+ $$->ipn_addr.adf_addr.in4.s_addr = $2[0].s_addr;
+ $$->ipn_mask.adf_len = sizeof($$->ipn_mask);
+ $$->ipn_mask.adf_addr.in4.s_addr = $2[1].s_addr;
+ }
+
+hashlist:
+ next { $$ = NULL; }
+ | hashentry next { $$ = $1; }
+ | hashentry next hashlist { $1->ipe_next = $3; $$ = $1; }
+ ;
+
+hashentry:
+ addrmask { $$ = calloc(1, sizeof(iphtent_t));
+ bcopy((char *)&($1[0]),
+ (char *)&($$->ipe_addr),
+ sizeof($$->ipe_addr));
+ bcopy((char *)&($1[1]),
+ (char *)&($$->ipe_mask),
+ sizeof($$->ipe_mask));
+ }
+ ;
+
+addrmask:
+ ipaddr '/' mask { $$[0] = $1; $$[1].s_addr = $3.s_addr;
+ yyexpectaddr = 0;
+ }
+ | ipaddr { $$[0] = $1; $$[1].s_addr = 0xffffffff;
+ yyexpectaddr = 0;
+ }
+ ;
+
+ipaddr: ipv4 { $$ = $1; }
+ | YY_NUMBER { $$.s_addr = htonl($1); }
+ | YY_STR { if (gethost($1, &($$.s_addr)) == -1)
+ yyerror("Unknown hostname");
+ }
+ ;
+
+mask: YY_NUMBER { ntomask(4, $1, (u_32_t *)&$$.s_addr); }
+ | ipv4 { $$ = $1; }
+ ;
+
+start: '{' { yyexpectaddr = 1; }
+ ;
+
+end: '}' { yyexpectaddr = 0; }
+ ;
+
+next: ';' { yyexpectaddr = 1; }
+ ;
+
+size: IPT_SIZE '=' YY_NUMBER { ipht.iph_size = $3; }
+ ;
+
+seed: IPT_SEED '=' YY_NUMBER { ipht.iph_seed = $3; }
+ ;
+
+ipv4: YY_NUMBER '.' YY_NUMBER '.' YY_NUMBER '.' YY_NUMBER
+ { if ($1 > 255 || $3 > 255 || $5 > 255 || $7 > 255) {
+ yyerror("Invalid octet string for IP address");
+ return 0;
+ }
+ $$.s_addr = ($1 << 24) | ($3 << 16) | ($5 << 8) | $7;
+ $$.s_addr = htonl($$.s_addr);
+ }
+ ;
+%%
+static wordtab_t yywords[] = {
+ { "auth", IPT_AUTH },
+ { "count", IPT_COUNT },
+ { "group", IPT_GROUP },
+ { "group-map", IPT_GROUPMAP },
+ { "hash", IPT_HASH },
+ { "in", IPT_IN },
+ { "ipf", IPT_IPF },
+ { "name", IPT_NAME },
+ { "nat", IPT_NAT },
+ { "number", IPT_NUM },
+ { "out", IPT_OUT },
+ { "role", IPT_ROLE },
+ { "seed", IPT_SEED },
+ { "size", IPT_SIZE },
+ { "table", IPT_TABLE },
+ { "tree", IPT_TREE },
+ { "type", IPT_TYPE },
+ { NULL, 0 }
+};
+
+
+int ippool_parsefile(fd, filename, iocfunc)
+int fd;
+char *filename;
+ioctlfunc_t iocfunc;
+{
+ FILE *fp = NULL;
+ char *s;
+
+ yylineNum = 1;
+ (void) yysettab(yywords);
+
+ s = getenv("YYDEBUG");
+ if (s)
+ yydebug = atoi(s);
+ else
+ yydebug = 0;
+
+ if (strcmp(filename, "-")) {
+ fp = fopen(filename, "r");
+ if (!fp) {
+ fprintf(stderr, "fopen(%s) failed: %s\n", filename,
+ STRERROR(errno));
+ return -1;
+ }
+ } else
+ fp = stdin;
+
+ while (ippool_parsesome(fd, fp, iocfunc) == 1)
+ ;
+ if (fp != NULL)
+ fclose(fp);
+ return 0;
+}
+
+
+int ippool_parsesome(fd, fp, iocfunc)
+int fd;
+FILE *fp;
+ioctlfunc_t iocfunc;
+{
+ char *s;
+ int i;
+
+ poolioctl = iocfunc;
+
+ if (feof(fp))
+ return 0;
+ i = fgetc(fp);
+ if (i == EOF)
+ return 0;
+ if (ungetc(i, fp) == EOF)
+ return 0;
+ if (feof(fp))
+ return 0;
+ s = getenv("YYDEBUG");
+ if (s)
+ yydebug = atoi(s);
+ else
+ yydebug = 0;
+
+ yyin = fp;
+ yyparse();
+ return 1;
+}
diff --git a/contrib/ipfilter/tools/ipscan_y.y b/contrib/ipfilter/tools/ipscan_y.y
new file mode 100644
index 0000000..64cbb6d
--- /dev/null
+++ b/contrib/ipfilter/tools/ipscan_y.y
@@ -0,0 +1,565 @@
+/* $NetBSD$ */
+
+%{
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include "ipf.h"
+#include "opts.h"
+#include "kmem.h"
+#include "ipscan_l.h"
+#include "netinet/ip_scan.h"
+
+#define YYDEBUG 1
+
+extern char *optarg;
+extern void yyerror __P((char *));
+extern int yyparse __P((void));
+extern int yylex __P((void));
+extern int yydebug;
+extern FILE *yyin;
+extern int yylineNum;
+extern void printbuf __P((char *, int, int));
+
+
+void printent __P((ipscan_t *));
+void showlist __P((void));
+int getportnum __P((char *));
+struct in_addr gethostip __P((char *));
+struct in_addr combine __P((int, int, int, int));
+char **makepair __P((char *, char *));
+void addtag __P((char *, char **, char **, struct action *));
+int cram __P((char *, char *));
+void usage __P((char *));
+int main __P((int, char **));
+
+int opts = 0;
+int fd = -1;
+
+
+%}
+
+%union {
+ char *str;
+ char **astr;
+ u_32_t num;
+ struct in_addr ipa;
+ struct action act;
+ union i6addr ip6;
+}
+
+%type <str> tag
+%type <act> action redirect result
+%type <ipa> ipaddr
+%type <num> portnum
+%type <astr> matchup onehalf twohalves
+
+%token <num> YY_NUMBER YY_HEX
+%token <str> YY_STR
+%token YY_COMMENT
+%token YY_CMP_EQ YY_CMP_NE YY_CMP_LE YY_CMP_GE YY_CMP_LT YY_CMP_GT
+%token YY_RANGE_OUT YY_RANGE_IN
+%token <ip6> YY_IPV6
+%token IPSL_START IPSL_STARTGROUP IPSL_CONTENT
+
+%token IPSL_CLOSE IPSL_TRACK IPSL_EOF IPSL_REDIRECT IPSL_ELSE
+
+%%
+file: line ';'
+ | assign ';'
+ | file line ';'
+ | file assign ';'
+ | YY_COMMENT
+ ;
+
+line: IPSL_START dline
+ | IPSL_STARTGROUP gline
+ | IPSL_CONTENT oline
+ ;
+
+dline: cline { resetlexer(); }
+ | sline { resetlexer(); }
+ | csline { resetlexer(); }
+ ;
+
+gline: YY_STR ':' glist '=' action
+ ;
+
+oline: cline
+ | sline
+ | csline
+ ;
+
+assign: YY_STR assigning YY_STR
+ { set_variable($1, $3);
+ resetlexer();
+ free($1);
+ free($3);
+ }
+ ;
+
+assigning:
+ '=' { yyvarnext = 1; }
+ ;
+
+cline: tag ':' matchup '=' action { addtag($1, $3, NULL, &$5); }
+ ;
+
+sline: tag ':' '(' ')' ',' matchup '=' action { addtag($1, NULL, $6, &$8); }
+ ;
+
+csline: tag ':' matchup ',' matchup '=' action { addtag($1, $3, $5, &$7); }
+ ;
+
+glist: YY_STR
+ | glist ',' YY_STR
+ ;
+
+tag: YY_STR { $$ = $1; }
+ ;
+
+matchup:
+ onehalf { $$ = $1; }
+ | twohalves { $$ = $1; }
+ ;
+
+action: result { $$.act_val = $1.act_val;
+ $$.act_ip = $1.act_ip;
+ $$.act_port = $1.act_port; }
+ | result IPSL_ELSE result { $$.act_val = $1.act_val;
+ $$.act_else = $3.act_val;
+ if ($1.act_val == IPSL_REDIRECT) {
+ $$.act_ip = $1.act_ip;
+ $$.act_port = $1.act_port;
+ }
+ if ($3.act_val == IPSL_REDIRECT) {
+ $$.act_eip = $3.act_eip;
+ $$.act_eport = $3.act_eport;
+ }
+ }
+
+result: IPSL_CLOSE { $$.act_val = IPSL_CLOSE; }
+ | IPSL_TRACK { $$.act_val = IPSL_TRACK; }
+ | redirect { $$.act_val = IPSL_REDIRECT;
+ $$.act_ip = $1.act_ip;
+ $$.act_port = $1.act_port; }
+ ;
+
+onehalf:
+ '(' YY_STR ')' { $$ = makepair($2, NULL); }
+ ;
+
+twohalves:
+ '(' YY_STR ',' YY_STR ')' { $$ = makepair($2, $4); }
+ ;
+
+redirect:
+ IPSL_REDIRECT '(' ipaddr ')' { $$.act_ip = $3;
+ $$.act_port = 0; }
+ | IPSL_REDIRECT '(' ipaddr ',' portnum ')'
+ { $$.act_ip = $3;
+ $$.act_port = $5; }
+ ;
+
+
+ipaddr: YY_NUMBER '.' YY_NUMBER '.' YY_NUMBER '.' YY_NUMBER
+ { $$ = combine($1,$3,$5,$7); }
+ | YY_STR { $$ = gethostip($1);
+ free($1);
+ }
+ ;
+
+portnum:
+ YY_NUMBER { $$ = htons($1); }
+ | YY_STR { $$ = getportnum($1);
+ free($1);
+ }
+ ;
+
+%%
+
+
+static struct wordtab yywords[] = {
+ { "close", IPSL_CLOSE },
+ { "content", IPSL_CONTENT },
+ { "else", IPSL_ELSE },
+ { "start-group", IPSL_STARTGROUP },
+ { "redirect", IPSL_REDIRECT },
+ { "start", IPSL_START },
+ { "track", IPSL_TRACK },
+ { NULL, 0 }
+};
+
+
+int cram(dst, src)
+char *dst;
+char *src;
+{
+ char c, *s, *t, *u;
+ int i, j, k;
+
+ c = *src;
+ s = src + 1;
+ t = strchr(s, c);
+ *t = '\0';
+ for (u = dst, i = 0; (i <= ISC_TLEN) && (s < t); ) {
+ c = *s++;
+ if (c == '\\') {
+ if (s >= t)
+ break;
+ j = k = 0;
+ do {
+ c = *s++;
+ if (j && (!ISDIGIT(c) || (c > '7') ||
+ (k >= 248))) {
+ *u++ = k, i++;
+ j = k = 0;
+ s--;
+ break;
+ }
+ i++;
+
+ if (ISALPHA(c) || (c > '7')) {
+ switch (c)
+ {
+ case 'n' :
+ *u++ = '\n';
+ break;
+ case 'r' :
+ *u++ = '\r';
+ break;
+ case 't' :
+ *u++ = '\t';
+ break;
+ default :
+ *u++ = c;
+ break;
+ }
+ } else if (ISDIGIT(c)) {
+ j = 1;
+ k <<= 3;
+ k |= (c - '0');
+ i--;
+ } else
+ *u++ = c;
+ } while ((i <= ISC_TLEN) && (s <= t) && (j > 0));
+ } else
+ *u++ = c, i++;
+ }
+ return i;
+}
+
+
+void printent(isc)
+ipscan_t *isc;
+{
+ char buf[ISC_TLEN+1];
+ u_char *u;
+ int i, j;
+
+ buf[ISC_TLEN] = '\0';
+ bcopy(isc->ipsc_ctxt, buf, ISC_TLEN);
+ printf("%s : (\"", isc->ipsc_tag);
+ printbuf(isc->ipsc_ctxt, isc->ipsc_clen, 0);
+
+ bcopy(isc->ipsc_cmsk, buf, ISC_TLEN);
+ printf("\", \"%s\"), (\"", buf);
+
+ printbuf(isc->ipsc_stxt, isc->ipsc_slen, 0);
+
+ bcopy(isc->ipsc_smsk, buf, ISC_TLEN);
+ printf("\", \"%s\") = ", buf);
+
+ switch (isc->ipsc_action)
+ {
+ case ISC_A_TRACK :
+ printf("track");
+ break;
+ case ISC_A_REDIRECT :
+ printf("redirect");
+ printf("(%s", inet_ntoa(isc->ipsc_ip));
+ if (isc->ipsc_port)
+ printf(",%d", isc->ipsc_port);
+ printf(")");
+ break;
+ case ISC_A_CLOSE :
+ printf("close");
+ break;
+ default :
+ break;
+ }
+
+ if (isc->ipsc_else != ISC_A_NONE) {
+ printf(" else ");
+ switch (isc->ipsc_else)
+ {
+ case ISC_A_TRACK :
+ printf("track");
+ break;
+ case ISC_A_REDIRECT :
+ printf("redirect");
+ printf("(%s", inet_ntoa(isc->ipsc_eip));
+ if (isc->ipsc_eport)
+ printf(",%d", isc->ipsc_eport);
+ printf(")");
+ break;
+ case ISC_A_CLOSE :
+ printf("close");
+ break;
+ default :
+ break;
+ }
+ }
+ printf("\n");
+
+ if (opts & OPT_DEBUG) {
+ for (u = (u_char *)isc, i = sizeof(*isc); i; ) {
+ printf("#");
+ for (j = 32; (j > 0) && (i > 0); j--, i--)
+ printf("%s%02x", (j & 7) ? "" : " ", *u++);
+ printf("\n");
+ }
+ }
+ if (opts & OPT_VERBOSE) {
+ printf("# hits %d active %d fref %d sref %d\n",
+ isc->ipsc_hits, isc->ipsc_active, isc->ipsc_fref,
+ isc->ipsc_sref);
+ }
+}
+
+
+void addtag(tstr, cp, sp, act)
+char *tstr;
+char **cp, **sp;
+struct action *act;
+{
+ ipscan_t isc, *iscp;
+
+ bzero((char *)&isc, sizeof(isc));
+
+ strncpy(isc.ipsc_tag, tstr, sizeof(isc.ipsc_tag));
+ isc.ipsc_tag[sizeof(isc.ipsc_tag) - 1] = '\0';
+
+ if (cp) {
+ isc.ipsc_clen = cram(isc.ipsc_ctxt, cp[0]);
+ if (cp[1]) {
+ if (cram(isc.ipsc_cmsk, cp[1]) != isc.ipsc_clen) {
+ fprintf(stderr,
+ "client text/mask strings different length\n");
+ return;
+ }
+ }
+ }
+
+ if (sp) {
+ isc.ipsc_slen = cram(isc.ipsc_stxt, sp[0]);
+ if (sp[1]) {
+ if (cram(isc.ipsc_smsk, sp[1]) != isc.ipsc_slen) {
+ fprintf(stderr,
+ "server text/mask strings different length\n");
+ return;
+ }
+ }
+ }
+
+ if (act->act_val == IPSL_CLOSE) {
+ isc.ipsc_action = ISC_A_CLOSE;
+ } else if (act->act_val == IPSL_TRACK) {
+ isc.ipsc_action = ISC_A_TRACK;
+ } else if (act->act_val == IPSL_REDIRECT) {
+ isc.ipsc_action = ISC_A_REDIRECT;
+ isc.ipsc_ip = act->act_ip;
+ isc.ipsc_port = act->act_port;
+ fprintf(stderr, "%d: redirect unsupported\n", yylineNum + 1);
+ }
+
+ if (act->act_else == IPSL_CLOSE) {
+ isc.ipsc_else = ISC_A_CLOSE;
+ } else if (act->act_else == IPSL_TRACK) {
+ isc.ipsc_else = ISC_A_TRACK;
+ } else if (act->act_else == IPSL_REDIRECT) {
+ isc.ipsc_else = ISC_A_REDIRECT;
+ isc.ipsc_eip = act->act_eip;
+ isc.ipsc_eport = act->act_eport;
+ fprintf(stderr, "%d: redirect unsupported\n", yylineNum + 1);
+ }
+
+ if (!(opts & OPT_DONOTHING)) {
+ iscp = &isc;
+ if (opts & OPT_REMOVE) {
+ if (ioctl(fd, SIOCRMSCA, &iscp) == -1)
+ perror("SIOCADSCA");
+ } else {
+ if (ioctl(fd, SIOCADSCA, &iscp) == -1)
+ perror("SIOCADSCA");
+ }
+ }
+
+ if (opts & OPT_VERBOSE)
+ printent(&isc);
+}
+
+
+char **makepair(s1, s2)
+char *s1, *s2;
+{
+ char **a;
+
+ a = malloc(sizeof(char *) * 2);
+ a[0] = s1;
+ a[1] = s2;
+ return a;
+}
+
+
+struct in_addr combine(a1, a2, a3, a4)
+int a1, a2, a3, a4;
+{
+ struct in_addr in;
+
+ a1 &= 0xff;
+ in.s_addr = a1 << 24;
+ a2 &= 0xff;
+ in.s_addr |= (a2 << 16);
+ a3 &= 0xff;
+ in.s_addr |= (a3 << 8);
+ a4 &= 0xff;
+ in.s_addr |= a4;
+ in.s_addr = htonl(in.s_addr);
+ return in;
+}
+
+
+struct in_addr gethostip(host)
+char *host;
+{
+ struct hostent *hp;
+ struct in_addr in;
+
+ in.s_addr = 0;
+
+ hp = gethostbyname(host);
+ if (!hp)
+ return in;
+ bcopy(hp->h_addr, (char *)&in, sizeof(in));
+ return in;
+}
+
+
+int getportnum(port)
+char *port;
+{
+ struct servent *s;
+
+ s = getservbyname(port, "tcp");
+ if (s == NULL)
+ return -1;
+ return s->s_port;
+}
+
+
+void showlist()
+{
+ ipscanstat_t ipsc, *ipscp = &ipsc;
+ ipscan_t isc;
+
+ if (ioctl(fd, SIOCGSCST, &ipscp) == -1)
+ perror("ioctl(SIOCGSCST)");
+ else if (opts & OPT_SHOWLIST) {
+ while (ipsc.iscs_list != NULL) {
+ if (kmemcpy((char *)&isc, (u_long)ipsc.iscs_list,
+ sizeof(isc)) == -1) {
+ perror("kmemcpy");
+ break;
+ } else {
+ printent(&isc);
+ ipsc.iscs_list = isc.ipsc_next;
+ }
+ }
+ } else {
+ printf("scan entries loaded\t%d\n", ipsc.iscs_entries);
+ printf("scan entries matches\t%ld\n", ipsc.iscs_acted);
+ printf("negative matches\t%ld\n", ipsc.iscs_else);
+ }
+}
+
+
+void usage(prog)
+char *prog;
+{
+ fprintf(stderr, "Usage:\t%s [-dnrv] -f <filename>\n", prog);
+ fprintf(stderr, "\t%s [-dlv]\n", prog);
+ exit(1);
+}
+
+
+int main(argc, argv)
+int argc;
+char *argv[];
+{
+ FILE *fp = NULL;
+ int c;
+
+ (void) yysettab(yywords);
+
+ if (argc < 2)
+ usage(argv[0]);
+
+ while ((c = getopt(argc, argv, "df:lnrsv")) != -1)
+ switch (c)
+ {
+ case 'd' :
+ opts |= OPT_DEBUG;
+ yydebug++;
+ break;
+ case 'f' :
+ if (!strcmp(optarg, "-"))
+ fp = stdin;
+ else {
+ fp = fopen(optarg, "r");
+ if (!fp) {
+ perror("open");
+ exit(1);
+ }
+ }
+ yyin = fp;
+ break;
+ case 'l' :
+ opts |= OPT_SHOWLIST;
+ break;
+ case 'n' :
+ opts |= OPT_DONOTHING;
+ break;
+ case 'r' :
+ opts |= OPT_REMOVE;
+ break;
+ case 's' :
+ opts |= OPT_STAT;
+ break;
+ case 'v' :
+ opts |= OPT_VERBOSE;
+ break;
+ }
+
+ if (!(opts & OPT_DONOTHING)) {
+ fd = open(IPL_SCAN, O_RDWR);
+ if (fd == -1) {
+ perror("open(IPL_SCAN)");
+ exit(1);
+ }
+ }
+
+ if (fp != NULL) {
+ yylineNum = 1;
+
+ while (!feof(fp))
+ yyparse();
+ fclose(fp);
+ exit(0);
+ }
+
+ if (opts & (OPT_SHOWLIST|OPT_STAT)) {
+ showlist();
+ exit(0);
+ }
+ exit(1);
+}
diff --git a/contrib/ipfilter/tools/ipsyncm.c b/contrib/ipfilter/tools/ipsyncm.c
new file mode 100644
index 0000000..20cc25e
--- /dev/null
+++ b/contrib/ipfilter/tools/ipsyncm.c
@@ -0,0 +1,253 @@
+/* $NetBSD$ */
+
+/*
+ * Copyright (C) 1993-2001 by Darren Reed.
+ *
+ * See the IPFILTER.LICENCE file for details on licencing.
+ */
+#if !defined(lint)
+static const char sccsid[] = "@(#)ip_fil.c 2.41 6/5/96 (C) 1993-2000 Darren Reed";
+static const char rcsid[] = "@(#)Id: ipsyncm.c,v 1.4.2.2 2005/01/08 14:31:46 darrenr Exp";
+#endif
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+#include <net/if.h>
+
+#include <arpa/inet.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <strings.h>
+#include <syslog.h>
+#include <signal.h>
+
+#include "netinet/ip_compat.h"
+#include "netinet/ip_fil.h"
+#include "netinet/ip_nat.h"
+#include "netinet/ip_state.h"
+#include "netinet/ip_sync.h"
+
+
+int main __P((int, char *[]));
+
+int terminate = 0;
+
+void usage(const char *progname) {
+ fprintf(stderr, "Usage: %s <destination IP> <destination port>\n", progname);
+}
+
+static void handleterm(int sig)
+{
+ terminate = sig;
+}
+
+
+/* should be large enough to hold header + any datatype */
+#define BUFFERLEN 1400
+
+int main(argc, argv)
+int argc;
+char *argv[];
+{
+ struct sockaddr_in sin;
+ char buff[BUFFERLEN];
+ synclogent_t *sl;
+ syncupdent_t *su;
+ int nfd = -1, lfd = -1, n1, n2, n3, len;
+ int inbuf;
+ u_32_t magic;
+ synchdr_t *sh;
+ char *progname;
+
+ progname = strrchr(argv[0], '/');
+ if (progname) {
+ progname++;
+ } else {
+ progname = argv[0];
+ }
+
+
+ if (argc < 2) {
+ usage(progname);
+ exit(1);
+ }
+
+#if 0
+ signal(SIGHUP, handleterm);
+ signal(SIGINT, handleterm);
+ signal(SIGTERM, handleterm);
+#endif
+
+ openlog(progname, LOG_PID, LOG_SECURITY);
+
+ bzero((char *)&sin, sizeof(sin));
+ sin.sin_family = AF_INET;
+ sin.sin_addr.s_addr = inet_addr(argv[1]);
+ if (argc > 2)
+ sin.sin_port = htons(atoi(argv[2]));
+ else
+ sin.sin_port = htons(43434);
+
+ while (1) {
+
+ if (lfd != -1)
+ close(lfd);
+ if (nfd != -1)
+ close(nfd);
+
+ lfd = open(IPSYNC_NAME, O_RDONLY);
+ if (lfd == -1) {
+ syslog(LOG_ERR, "Opening %s :%m", IPSYNC_NAME);
+ goto tryagain;
+ }
+
+ nfd = socket(AF_INET, SOCK_DGRAM, 0);
+ if (nfd == -1) {
+ syslog(LOG_ERR, "Socket :%m");
+ goto tryagain;
+ }
+
+ if (connect(nfd, (struct sockaddr *)&sin, sizeof(sin)) == -1) {
+ syslog(LOG_ERR, "Connect: %m");
+ goto tryagain;
+ }
+
+ syslog(LOG_INFO, "Established connection to %s",
+ inet_ntoa(sin.sin_addr));
+
+ inbuf = 0;
+ while (1) {
+
+ n1 = read(lfd, buff+inbuf, BUFFERLEN-inbuf);
+
+ printf("header : %d bytes read (header = %d bytes)\n",
+ n1, sizeof(*sh));
+
+ if (n1 < 0) {
+ syslog(LOG_ERR, "Read error (header): %m");
+ goto tryagain;
+ }
+
+ if (n1 == 0) {
+ /* XXX can this happen??? */
+ syslog(LOG_ERR,
+ "Read error (header) : No data");
+ sleep(1);
+ continue;
+ }
+
+ inbuf += n1;
+
+moreinbuf:
+ if (inbuf < sizeof(*sh)) {
+ continue; /* need more data */
+ }
+
+ sh = (synchdr_t *)buff;
+ len = ntohl(sh->sm_len);
+ magic = ntohl(sh->sm_magic);
+
+ if (magic != SYNHDRMAGIC) {
+ syslog(LOG_ERR,
+ "Invalid header magic %x", magic);
+ goto tryagain;
+ }
+
+#define IPSYNC_DEBUG
+#ifdef IPSYNC_DEBUG
+ printf("v:%d p:%d len:%d magic:%x", sh->sm_v,
+ sh->sm_p, len, magic);
+
+ if (sh->sm_cmd == SMC_CREATE)
+ printf(" cmd:CREATE");
+ else if (sh->sm_cmd == SMC_UPDATE)
+ printf(" cmd:UPDATE");
+ else
+ printf(" cmd:Unknown(%d)", sh->sm_cmd);
+
+ if (sh->sm_table == SMC_NAT)
+ printf(" table:NAT");
+ else if (sh->sm_table == SMC_STATE)
+ printf(" table:STATE");
+ else
+ printf(" table:Unknown(%d)", sh->sm_table);
+
+ printf(" num:%d\n", (u_32_t)ntohl(sh->sm_num));
+#endif
+
+ if (inbuf < sizeof(*sh) + len) {
+ continue; /* need more data */
+ goto tryagain;
+ }
+
+#ifdef IPSYNC_DEBUG
+ if (sh->sm_cmd == SMC_CREATE) {
+ sl = (synclogent_t *)buff;
+
+ } else if (sh->sm_cmd == SMC_UPDATE) {
+ su = (syncupdent_t *)buff;
+ if (sh->sm_p == IPPROTO_TCP) {
+ printf(" TCP Update: age %lu state %d/%d\n",
+ su->sup_tcp.stu_age,
+ su->sup_tcp.stu_state[0],
+ su->sup_tcp.stu_state[1]);
+ }
+ } else {
+ printf("Unknown command\n");
+ }
+#endif
+
+ n2 = sizeof(*sh) + len;
+ n3 = write(nfd, buff, n2);
+ if (n3 <= 0) {
+ syslog(LOG_ERR, "Write error: %m");
+ goto tryagain;
+ }
+
+
+ if (n3 != n2) {
+ syslog(LOG_ERR, "Incomplete write (%d/%d)",
+ n3, n2);
+ goto tryagain;
+ }
+
+ /* signal received? */
+ if (terminate)
+ break;
+
+ /* move buffer to the front,we might need to make
+ * this more efficient, by using a rolling pointer
+ * over the buffer and only copying it, when
+ * we are reaching the end
+ */
+ inbuf -= n2;
+ if (inbuf) {
+ bcopy(buff+n2, buff, inbuf);
+ printf("More data in buffer\n");
+ goto moreinbuf;
+ }
+ }
+
+ if (terminate)
+ break;
+tryagain:
+ sleep(1);
+ }
+
+
+ /* terminate */
+ if (lfd != -1)
+ close(lfd);
+ if (nfd != -1)
+ close(nfd);
+
+ syslog(LOG_ERR, "signal %d received, exiting...", terminate);
+
+ exit(1);
+}
+
diff --git a/contrib/ipfilter/tools/ipsyncs.c b/contrib/ipfilter/tools/ipsyncs.c
new file mode 100644
index 0000000..a189a9b
--- /dev/null
+++ b/contrib/ipfilter/tools/ipsyncs.c
@@ -0,0 +1,272 @@
+/* $NetBSD$ */
+
+/*
+ * Copyright (C) 1993-2001 by Darren Reed.
+ *
+ * See the IPFILTER.LICENCE file for details on licencing.
+ */
+#if !defined(lint)
+static const char sccsid[] = "@(#)ip_fil.c 2.41 6/5/96 (C) 1993-2000 Darren Reed";
+static const char rcsid[] = "@(#)Id: ipsyncs.c,v 1.5.2.1 2004/10/31 18:46:44 darrenr Exp";
+#endif
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+#include <net/if.h>
+
+#include <arpa/inet.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <strings.h>
+#include <unistd.h>
+#include <syslog.h>
+#include <errno.h>
+#include <signal.h>
+
+#include "netinet/ip_compat.h"
+#include "netinet/ip_fil.h"
+#include "netinet/ip_state.h"
+#include "netinet/ip_nat.h"
+#include "netinet/ip_sync.h"
+
+int main __P((int, char *[]));
+
+int terminate = 0;
+
+void usage(const char *progname) {
+ fprintf(stderr,
+ "Usage: %s <destination IP> <destination port> [remote IP]\n",
+ progname);
+}
+
+static void handleterm(int sig)
+{
+ terminate = sig;
+
+}
+
+#define BUFFERLEN 1400
+
+int main(argc, argv)
+int argc;
+char *argv[];
+{
+ int nfd = -1 , lfd = -1;
+ int n1, n2, n3, magic, len, inbuf;
+ struct sockaddr_in sin;
+ struct sockaddr_in in;
+ char buff[BUFFERLEN];
+ synclogent_t *sl;
+ syncupdent_t *su;
+ synchdr_t *sh;
+ char *progname;
+
+ progname = strrchr(argv[0], '/');
+ if (progname) {
+ progname++;
+ } else {
+ progname = argv[0];
+ }
+
+ if (argc < 2) {
+ usage(progname);
+ exit(1);
+ }
+
+#if 0
+ signal(SIGHUP, handleterm);
+ signal(SIGINT, handleterm);
+ signal(SIGTERM, handleterm);
+#endif
+
+ openlog(progname, LOG_PID, LOG_SECURITY);
+
+ lfd = open(IPSYNC_NAME, O_WRONLY);
+ if (lfd == -1) {
+ syslog(LOG_ERR, "Opening %s :%m", IPSYNC_NAME);
+ exit(1);
+ }
+
+ bzero((char *)&sin, sizeof(sin));
+ sin.sin_family = AF_INET;
+ if (argc > 1)
+ sin.sin_addr.s_addr = inet_addr(argv[1]);
+ if (argc > 2)
+ sin.sin_port = htons(atoi(argv[2]));
+ else
+ sin.sin_port = htons(43434);
+ if (argc > 3)
+ in.sin_addr.s_addr = inet_addr(argv[3]);
+ else
+ in.sin_addr.s_addr = 0;
+ in.sin_port = 0;
+
+ while(1) {
+
+ if (lfd != -1)
+ close(lfd);
+ if (nfd != -1)
+ close(nfd);
+
+ lfd = open(IPSYNC_NAME, O_WRONLY);
+ if (lfd == -1) {
+ syslog(LOG_ERR, "Opening %s :%m", IPSYNC_NAME);
+ goto tryagain;
+ }
+
+ nfd = socket(AF_INET, SOCK_DGRAM, 0);
+ if (nfd == -1) {
+ syslog(LOG_ERR, "Socket :%m");
+ goto tryagain;
+ }
+
+ n1 = 1;
+ setsockopt(nfd, SOL_SOCKET, SO_REUSEADDR, &n1, sizeof(n1));
+
+ if (bind(nfd, (struct sockaddr *)&sin, sizeof(sin)) == -1) {
+ syslog(LOG_ERR, "Bind: %m");
+ goto tryagain;
+ }
+
+ syslog(LOG_INFO, "Established connection to %s",
+ inet_ntoa(sin.sin_addr));
+
+ inbuf = 0;
+ while (1) {
+
+
+ /*
+ * XXX currently we do not check the source address
+ * of a datagram, this can be a security risk
+ */
+ n1 = read(nfd, buff+inbuf, BUFFERLEN-inbuf);
+
+ printf("header : %d bytes read (header = %d bytes)\n",
+ n1, sizeof(*sh));
+
+ if (n1 < 0) {
+ syslog(LOG_ERR, "Read error (header): %m");
+ goto tryagain;
+ }
+
+ if (n1 == 0) {
+ /* XXX can this happen??? */
+ syslog(LOG_ERR,
+ "Read error (header) : No data");
+ sleep(1);
+ continue;
+ }
+
+ inbuf += n1;
+
+moreinbuf:
+ if (inbuf < sizeof(*sh)) {
+ continue; /* need more data */
+ }
+
+ sh = (synchdr_t *)buff;
+ len = ntohl(sh->sm_len);
+ magic = ntohl(sh->sm_magic);
+
+ if (magic != SYNHDRMAGIC) {
+ syslog(LOG_ERR, "Invalid header magic %x",
+ magic);
+ goto tryagain;
+ }
+
+#define IPSYNC_DEBUG
+#ifdef IPSYNC_DEBUG
+ printf("v:%d p:%d len:%d magic:%x", sh->sm_v,
+ sh->sm_p, len, magic);
+
+ if (sh->sm_cmd == SMC_CREATE)
+ printf(" cmd:CREATE");
+ else if (sh->sm_cmd == SMC_UPDATE)
+ printf(" cmd:UPDATE");
+ else
+ printf(" cmd:Unknown(%d)", sh->sm_cmd);
+
+ if (sh->sm_table == SMC_NAT)
+ printf(" table:NAT");
+ else if (sh->sm_table == SMC_STATE)
+ printf(" table:STATE");
+ else
+ printf(" table:Unknown(%d)", sh->sm_table);
+
+ printf(" num:%d\n", (u_32_t)ntohl(sh->sm_num));
+#endif
+
+ if (inbuf < sizeof(*sh) + len) {
+ continue; /* need more data */
+ goto tryagain;
+ }
+
+#ifdef IPSYNC_DEBUG
+ if (sh->sm_cmd == SMC_CREATE) {
+ sl = (synclogent_t *)buff;
+
+ } else if (sh->sm_cmd == SMC_UPDATE) {
+ su = (syncupdent_t *)buff;
+ if (sh->sm_p == IPPROTO_TCP) {
+ printf(" TCP Update: age %lu state %d/%d\n",
+ su->sup_tcp.stu_age,
+ su->sup_tcp.stu_state[0],
+ su->sup_tcp.stu_state[1]);
+ }
+ } else {
+ printf("Unknown command\n");
+ }
+#endif
+
+ n2 = sizeof(*sh) + len;
+ n3 = write(lfd, buff, n2);
+ if (n3 <= 0) {
+ syslog(LOG_ERR, "Write error: %m");
+ goto tryagain;
+ }
+
+
+ if (n3 != n2) {
+ syslog(LOG_ERR, "Incomplete write (%d/%d)",
+ n3, n2);
+ goto tryagain;
+ }
+
+ /* signal received? */
+ if (terminate)
+ break;
+
+ /* move buffer to the front,we might need to make
+ * this more efficient, by using a rolling pointer
+ * over the buffer and only copying it, when
+ * we are reaching the end
+ */
+ inbuf -= n2;
+ if (inbuf) {
+ bcopy(buff+n2, buff, inbuf);
+ printf("More data in buffer\n");
+ goto moreinbuf;
+ }
+ }
+
+ if (terminate)
+ break;
+tryagain:
+ sleep(1);
+ }
+
+
+ /* terminate */
+ if (lfd != -1)
+ close(lfd);
+ if (nfd != -1)
+ close(nfd);
+
+ syslog(LOG_ERR, "signal %d received, exiting...", terminate);
+
+ exit(1);
+}
diff --git a/contrib/ipfilter/tools/lex_var.h b/contrib/ipfilter/tools/lex_var.h
new file mode 100644
index 0000000..33fba25
--- /dev/null
+++ b/contrib/ipfilter/tools/lex_var.h
@@ -0,0 +1,55 @@
+/* $NetBSD$ */
+
+
+extern long string_start;
+extern long string_end;
+extern char *string_val;
+extern long pos;
+
+#define YY_INPUT(buf, result, max_size) \
+ if (pos >= string_start && pos <= string_end) { \
+ buf[0] = string_val[pos - string_start]; \
+ pos++; \
+ result = 1; \
+ } else if ( yy_current_buffer->yy_is_interactive ) \
+ { \
+ int c = '*', n; \
+ for ( n = 0; n < 1 && \
+ (c = getc( yyin )) != EOF && c != '\n'; ++n ) \
+ buf[n] = (char) c; \
+ if ( c == '\n' ) \
+ buf[n++] = (char) c; \
+ if ( c == EOF && ferror( yyin ) ) \
+ YY_FATAL_ERROR( "input in flex scanner failed" ); \
+ result = n; \
+ pos++; \
+ } \
+ else if ( ((result = fread( buf, 1, 1, yyin )) == 0) \
+ && ferror( yyin ) ) \
+ YY_FATAL_ERROR( "input in flex scanner failed" );
+
+#ifdef input
+# undef input
+# define input() (((pos >= string_start) && (pos < string_end)) ? \
+ yysptr = yysbuf, string_val[pos++ - string_start] : \
+ ((yytchar = yysptr > yysbuf ? U(*--yysptr) : \
+ getc(yyin)) == 10 ? (pos++, yylineno++, yytchar) : \
+ yytchar) == EOF ? (pos++, 0) : (pos++, yytchar))
+#endif
+
+#ifdef lex_input
+# undef lex_input
+# define lex_input() (((pos >= string_start) && (pos < string_end)) ? \
+ yysptr = yysbuf, string_val[pos++ - string_start] : \
+ ((yytchar = yysptr > yysbuf ? U(*--yysptr) : \
+ getc(yyin)) == 10 ? (pos++, yylineno++, yytchar) : \
+ yytchar) == EOF ? (pos++, 0) : (pos++, yytchar))
+#endif
+
+#ifdef unput
+# undef unput
+# define unput(c) { if (pos > 0) pos--; \
+ yytchar = (c); if (yytchar == '\n') yylineno--; \
+ *yysptr++ = yytchar; }
+#endif
+
diff --git a/contrib/ipfilter/tools/lexer.c b/contrib/ipfilter/tools/lexer.c
new file mode 100644
index 0000000..f6fccfb
--- /dev/null
+++ b/contrib/ipfilter/tools/lexer.c
@@ -0,0 +1,632 @@
+/* $NetBSD$ */
+
+/*
+ * Copyright (C) 2003 by Darren Reed.
+ *
+ * See the IPFILTER.LICENCE file for details on licencing.
+ */
+#include <ctype.h>
+#include "ipf.h"
+#ifdef IPFILTER_SCAN
+# include "netinet/ip_scan.h"
+#endif
+#include <sys/ioctl.h>
+#include <syslog.h>
+#ifdef TEST_LEXER
+# define NO_YACC
+union {
+ int num;
+ char *str;
+ struct in_addr ipa;
+ i6addr_t ip6;
+} yylval;
+#endif
+#include "lexer.h"
+#include "y.tab.h"
+
+FILE *yyin;
+
+#define ishex(c) (ISDIGIT(c) || ((c) >= 'a' && (c) <= 'f') || \
+ ((c) >= 'A' && (c) <= 'F'))
+#define TOOLONG -3
+
+extern int string_start;
+extern int string_end;
+extern char *string_val;
+extern int pos;
+extern int yydebug;
+
+char *yystr = NULL;
+int yytext[YYBUFSIZ+1];
+int yylineNum = 1;
+int yypos = 0;
+int yylast = -1;
+int yyexpectaddr = 0;
+int yybreakondot = 0;
+int yyvarnext = 0;
+int yytokentype = 0;
+wordtab_t *yywordtab = NULL;
+int yysavedepth = 0;
+wordtab_t *yysavewords[30];
+
+
+static wordtab_t *yyfindkey __P((char *));
+static int yygetc __P((void));
+static void yyunputc __P((int));
+static int yyswallow __P((int));
+static char *yytexttostr __P((int, int));
+static void yystrtotext __P((char *));
+
+static int yygetc()
+{
+ int c;
+
+ if (yypos < yylast) {
+ c = yytext[yypos++];
+ if (c == '\n')
+ yylineNum++;
+ return c;
+ }
+
+ if (yypos == YYBUFSIZ)
+ return TOOLONG;
+
+ if (pos >= string_start && pos <= string_end) {
+ c = string_val[pos - string_start];
+ yypos++;
+ } else {
+ c = fgetc(yyin);
+ }
+ if (c == '\n')
+ yylineNum++;
+ yytext[yypos++] = c;
+ yylast = yypos;
+ yytext[yypos] = '\0';
+
+ return c;
+}
+
+
+static void yyunputc(c)
+int c;
+{
+ if (c == '\n')
+ yylineNum--;
+ yytext[--yypos] = c;
+}
+
+
+static int yyswallow(last)
+int last;
+{
+ int c;
+
+ while (((c = yygetc()) > '\0') && (c != last))
+ ;
+
+ if (c != EOF)
+ yyunputc(c);
+ if (c == last)
+ return 0;
+ return -1;
+}
+
+
+static void yystrtotext(str)
+char *str;
+{
+ int len;
+ char *s;
+
+ len = strlen(str);
+ if (len > YYBUFSIZ)
+ len = YYBUFSIZ;
+
+ for (s = str; *s != '\0' && len > 0; s++, len--)
+ yytext[yylast++] = *s;
+ yytext[yylast] = '\0';
+}
+
+
+static char *yytexttostr(offset, max)
+int offset, max;
+{
+ char *str;
+ int i;
+
+ if ((yytext[offset] == '\'' || yytext[offset] == '"') &&
+ (yytext[offset] == yytext[offset + max - 1])) {
+ offset++;
+ max--;
+ }
+
+ if (max > yylast)
+ max = yylast;
+ str = malloc(max + 1);
+ if (str != NULL) {
+ for (i = offset; i < max; i++)
+ str[i - offset] = (char)(yytext[i] & 0xff);
+ str[i - offset] = '\0';
+ }
+ return str;
+}
+
+
+int yylex()
+{
+ int c, n, isbuilding, rval, lnext, nokey = 0;
+ char *name;
+
+ isbuilding = 0;
+ lnext = 0;
+ rval = 0;
+
+ if (yystr != NULL) {
+ free(yystr);
+ yystr = NULL;
+ }
+
+nextchar:
+ c = yygetc();
+
+ switch (c)
+ {
+ case '\n' :
+ case '\t' :
+ case '\r' :
+ case ' ' :
+ if (isbuilding == 1) {
+ yyunputc(c);
+ goto done;
+ }
+ if (yylast > yypos) {
+ bcopy(yytext + yypos, yytext,
+ sizeof(yytext[0]) * (yylast - yypos + 1));
+ }
+ yylast -= yypos;
+ yypos = 0;
+ lnext = 0;
+ nokey = 0;
+ goto nextchar;
+
+ case '\\' :
+ if (lnext == 0) {
+ lnext = 1;
+ if (yylast == yypos) {
+ yylast--;
+ yypos--;
+ } else
+ yypos--;
+ if (yypos == 0)
+ nokey = 1;
+ goto nextchar;
+ }
+ break;
+ }
+
+ if (lnext == 1) {
+ lnext = 0;
+ if ((isbuilding == 0) && !ISALNUM(c)) {
+ return c;
+ }
+ goto nextchar;
+ }
+
+ switch (c)
+ {
+ case '#' :
+ if (isbuilding == 1) {
+ yyunputc(c);
+ goto done;
+ }
+ yyswallow('\n');
+ rval = YY_COMMENT;
+ goto nextchar;
+
+ case '$' :
+ if (isbuilding == 1) {
+ yyunputc(c);
+ goto done;
+ }
+ n = yygetc();
+ if (n == '{') {
+ if (yyswallow('}') == -1) {
+ rval = -2;
+ goto done;
+ }
+ (void) yygetc();
+ } else {
+ if (!ISALPHA(n)) {
+ yyunputc(n);
+ break;
+ }
+ do {
+ n = yygetc();
+ } while (ISALPHA(n) || ISDIGIT(n) || n == '_');
+ yyunputc(n);
+ }
+
+ name = yytexttostr(1, yypos); /* skip $ */
+
+ if (name != NULL) {
+ string_val = get_variable(name, NULL, yylineNum);
+ free(name);
+ if (string_val != NULL) {
+ name = yytexttostr(yypos, yylast);
+ if (name != NULL) {
+ yypos = 0;
+ yylast = 0;
+ yystrtotext(string_val);
+ yystrtotext(name);
+ free(string_val);
+ free(name);
+ goto nextchar;
+ }
+ free(string_val);
+ }
+ }
+ break;
+
+ case '\'':
+ case '"' :
+ if (isbuilding == 1) {
+ goto done;
+ }
+ do {
+ n = yygetc();
+ if (n == EOF || n == TOOLONG) {
+ rval = -2;
+ goto done;
+ }
+ if (n == '\n') {
+ yyunputc(' ');
+ yypos++;
+ }
+ } while (n != c);
+ yyunputc(n);
+ break;
+
+ case EOF :
+ yylineNum = 1;
+ yypos = 0;
+ yylast = -1;
+ yyexpectaddr = 0;
+ yybreakondot = 0;
+ yyvarnext = 0;
+ yytokentype = 0;
+ return 0;
+ }
+
+ if (strchr("=,/;{}()@", c) != NULL) {
+ if (isbuilding == 1) {
+ yyunputc(c);
+ goto done;
+ }
+ rval = c;
+ goto done;
+ } else if (c == '.') {
+ if (isbuilding == 0) {
+ rval = c;
+ goto done;
+ }
+ if (yybreakondot != 0) {
+ yyunputc(c);
+ goto done;
+ }
+ }
+
+ switch (c)
+ {
+ case '-' :
+ if (yyexpectaddr)
+ break;
+ if (isbuilding == 1)
+ break;
+ n = yygetc();
+ if (n == '>') {
+ isbuilding = 1;
+ goto done;
+ }
+ yyunputc(n);
+ rval = '-';
+ goto done;
+
+ case '!' :
+ if (isbuilding == 1) {
+ yyunputc(c);
+ goto done;
+ }
+ n = yygetc();
+ if (n == '=') {
+ rval = YY_CMP_NE;
+ goto done;
+ }
+ yyunputc(n);
+ rval = '!';
+ goto done;
+
+ case '<' :
+ if (yyexpectaddr)
+ break;
+ if (isbuilding == 1) {
+ yyunputc(c);
+ goto done;
+ }
+ n = yygetc();
+ if (n == '=') {
+ rval = YY_CMP_LE;
+ goto done;
+ }
+ if (n == '>') {
+ rval = YY_RANGE_OUT;
+ goto done;
+ }
+ yyunputc(n);
+ rval = YY_CMP_LT;
+ goto done;
+
+ case '>' :
+ if (yyexpectaddr)
+ break;
+ if (isbuilding == 1) {
+ yyunputc(c);
+ goto done;
+ }
+ n = yygetc();
+ if (n == '=') {
+ rval = YY_CMP_GE;
+ goto done;
+ }
+ if (n == '<') {
+ rval = YY_RANGE_IN;
+ goto done;
+ }
+ yyunputc(n);
+ rval = YY_CMP_GT;
+ goto done;
+ }
+
+ /*
+ * Now for the reason this is here...IPv6 address parsing.
+ * The longest string we can expect is of this form:
+ * 0000:0000:0000:0000:0000:0000:000.000.000.000
+ * not:
+ * 0000:0000:0000:0000:0000:0000:0000:0000
+ */
+#ifdef USE_INET6
+ if (yyexpectaddr == 1 && isbuilding == 0 && (ishex(c) || c == ':')) {
+ char ipv6buf[45 + 1], *s, oc;
+ int start;
+
+ start = yypos;
+ s = ipv6buf;
+ oc = c;
+
+ /*
+ * Perhaps we should implement stricter controls on what we
+ * swallow up here, but surely it would just be duplicating
+ * the code in inet_pton() anyway.
+ */
+ do {
+ *s++ = c;
+ c = yygetc();
+ } while ((ishex(c) || c == ':' || c == '.') &&
+ (s - ipv6buf < 46));
+ yyunputc(c);
+ *s = '\0';
+
+ if (inet_pton(AF_INET6, ipv6buf, &yylval.ip6) == 1) {
+ rval = YY_IPV6;
+ yyexpectaddr = 0;
+ goto done;
+ }
+ yypos = start;
+ c = oc;
+ }
+#endif
+
+ if (c == ':') {
+ if (isbuilding == 1) {
+ yyunputc(c);
+ goto done;
+ }
+ rval = ':';
+ goto done;
+ }
+
+ if (isbuilding == 0 && c == '0') {
+ n = yygetc();
+ if (n == 'x') {
+ do {
+ n = yygetc();
+ } while (ishex(n));
+ yyunputc(n);
+ rval = YY_HEX;
+ goto done;
+ }
+ yyunputc(n);
+ }
+
+ /*
+ * No negative numbers with leading - sign..
+ */
+ if (isbuilding == 0 && ISDIGIT(c)) {
+ do {
+ n = yygetc();
+ } while (ISDIGIT(n));
+ yyunputc(n);
+ rval = YY_NUMBER;
+ goto done;
+ }
+
+ isbuilding = 1;
+ goto nextchar;
+
+done:
+ yystr = yytexttostr(0, yypos);
+
+ if (isbuilding == 1) {
+ wordtab_t *w;
+
+ w = NULL;
+ isbuilding = 0;
+
+ if ((yyvarnext == 0) && (nokey == 0)) {
+ w = yyfindkey(yystr);
+ if (w == NULL && yywordtab != NULL) {
+ yyresetdict();
+ w = yyfindkey(yystr);
+ }
+ } else
+ yyvarnext = 0;
+ if (w != NULL)
+ rval = w->w_value;
+ else
+ rval = YY_STR;
+ }
+
+ if (rval == YY_STR && yysavedepth > 0)
+ yyresetdict();
+
+ yytokentype = rval;
+
+ if (yydebug)
+ printf("lexed(%s) [%d,%d,%d] => %d\n", yystr, string_start,
+ string_end, pos, rval);
+
+ switch (rval)
+ {
+ case YY_NUMBER :
+ sscanf(yystr, "%u", &yylval.num);
+ break;
+
+ case YY_HEX :
+ sscanf(yystr, "0x%x", (u_int *)&yylval.num);
+ break;
+
+ case YY_STR :
+ yylval.str = strdup(yystr);
+ break;
+
+ default :
+ break;
+ }
+
+ if (yylast > 0) {
+ bcopy(yytext + yypos, yytext,
+ sizeof(yytext[0]) * (yylast - yypos + 1));
+ yylast -= yypos;
+ yypos = 0;
+ }
+
+ return rval;
+}
+
+
+static wordtab_t *yyfindkey(key)
+char *key;
+{
+ wordtab_t *w;
+
+ if (yywordtab == NULL)
+ return NULL;
+
+ for (w = yywordtab; w->w_word != 0; w++)
+ if (strcasecmp(key, w->w_word) == 0)
+ return w;
+ return NULL;
+}
+
+
+char *yykeytostr(num)
+int num;
+{
+ wordtab_t *w;
+
+ if (yywordtab == NULL)
+ return "<unknown>";
+
+ for (w = yywordtab; w->w_word; w++)
+ if (w->w_value == num)
+ return w->w_word;
+ return "<unknown>";
+}
+
+
+wordtab_t *yysettab(words)
+wordtab_t *words;
+{
+ wordtab_t *save;
+
+ save = yywordtab;
+ yywordtab = words;
+ return save;
+}
+
+
+void yyerror(msg)
+char *msg;
+{
+ char *txt, letter[2];
+ int freetxt = 0;
+
+ if (yytokentype < 256) {
+ letter[0] = yytokentype;
+ letter[1] = '\0';
+ txt = letter;
+ } else if (yytokentype == YY_STR || yytokentype == YY_HEX ||
+ yytokentype == YY_NUMBER) {
+ if (yystr == NULL) {
+ txt = yytexttostr(yypos, YYBUFSIZ);
+ freetxt = 1;
+ } else
+ txt = yystr;
+ } else {
+ txt = yykeytostr(yytokentype);
+ }
+ fprintf(stderr, "%s error at \"%s\", line %d\n", msg, txt, yylineNum);
+ if (freetxt == 1)
+ free(txt);
+ exit(1);
+}
+
+
+void yysetdict(newdict)
+wordtab_t *newdict;
+{
+ if (yysavedepth == sizeof(yysavewords)/sizeof(yysavewords[0])) {
+ fprintf(stderr, "%d: at maximum dictionary depth\n",
+ yylineNum);
+ return;
+ }
+
+ yysavewords[yysavedepth++] = yysettab(newdict);
+ if (yydebug)
+ printf("yysavedepth++ => %d\n", yysavedepth);
+}
+
+void yyresetdict()
+{
+ if (yysavedepth > 0) {
+ yysettab(yysavewords[--yysavedepth]);
+ if (yydebug)
+ printf("yysavedepth-- => %d\n", yysavedepth);
+ }
+}
+
+
+
+#ifdef TEST_LEXER
+int main(argc, argv)
+int argc;
+char *argv[];
+{
+ int n;
+
+ yyin = stdin;
+
+ while ((n = yylex()) != 0)
+ printf("%d.n = %d [%s] %d %d\n",
+ yylineNum, n, yystr, yypos, yylast);
+}
+#endif
diff --git a/contrib/ipfilter/tools/lexer.h b/contrib/ipfilter/tools/lexer.h
new file mode 100644
index 0000000..4950aa8
--- /dev/null
+++ b/contrib/ipfilter/tools/lexer.h
@@ -0,0 +1,37 @@
+/* $NetBSD$ */
+
+
+typedef struct wordtab {
+ char *w_word;
+ int w_value;
+} wordtab_t;
+
+#ifdef NO_YACC
+#define YY_COMMENT 1000
+#define YY_CMP_NE 1001
+#define YY_CMP_LE 1002
+#define YY_RANGE_OUT 1003
+#define YY_CMP_GE 1004
+#define YY_RANGE_IN 1005
+#define YY_HEX 1006
+#define YY_NUMBER 1007
+#define YY_IPV6 1008
+#define YY_STR 1009
+#define YY_IPADDR 1010
+#endif
+
+#define YYBUFSIZ 8192
+
+extern wordtab_t *yysettab __P((wordtab_t *));
+extern void yysetdict __P((wordtab_t *));
+extern int yylex __P((void));
+extern void yyerror __P((char *));
+extern char *yykeytostr __P((int));
+extern void yyresetdict __P((void));
+
+extern FILE *yyin;
+extern int yylineNum;
+extern int yyexpectaddr;
+extern int yybreakondot;
+extern int yyvarnext;
+
diff --git a/contrib/ipfilter/typescript b/contrib/ipfilter/typescript
new file mode 100644
index 0000000..1446ac4
--- /dev/null
+++ b/contrib/ipfilter/typescript
@@ -0,0 +1,121 @@
+Script started on Mon Apr 25 17:24:29 2005
+/sbin /usr/sbin /bin /usr/bin /etc /usr/sbin
+FreeBSD FreeBSD/i386.6.0 on /dev/ttyp0
+tcsh
+.cshrc
+(.cshrc)
+-done.
+/bin /sbin /etc /usr/bin /usr/sbin /usr/games
+.cshrc done
+TERM = vt100
+/usr/X11R6/man /usr/share/man
+(freebsd6:~) cd /usr/src/sycontrib/ipfilter
+(freebsd6:/usr/src/contrib/ipfilter) l
+./ ip_compat.h ipf.h
+../ ip_fil.c ipl.h
+.cvsignore ip_fil.h iplang/
+BNF ip_fil_freebsd.c ipmon.h
+BSD/ ip_frag.c ipsd/
+BugReport ip_frag.h ipsend/
+CVS/ ip_ftp_pxy.c ipt.h
+FAQ.FreeBSD ip_h323_pxy.c kmem.h
+FWTK/ ip_htable.c l4check/
+FreeBSD/ ip_htable.h lib/
+FreeBSD-2.2/ ip_ipsec_pxy.c man/
+FreeBSD-3/ ip_irc_pxy.c md5.c
+FreeBSD-4.0/ ip_log.c md5.h
+HISTORY ip_lookup.c mkfilters
+IMPORTANT ip_lookup.h mlf_ipl.c
+INST.FreeBSD-2.2 ip_msnrpc_pxy.c mlf_rule.c
+INSTALL.FreeBSD ip_nat.c mlfk_ipl.c
+INSTALL.xBSD ip_nat.h mlfk_rule.c
+IPF.KANJI ip_netbios_pxy.c mlh_rule.c
+IPFILTER.LICENCE ip_pool.c net/
+Makefile ip_pool.h netinet/
+NAT.FreeBSD ip_pptp_pxy.c opts.h
+QNX_OCL.txt ip_proxy.c pcap-ipf.h
+README ip_proxy.h perl/
+STYLE.TXT ip_raudio_pxy.c radix.c
+WhatsNew40.txt ip_rcmd_pxy.c radix_ipf.h
+Y2K ip_rpcb_pxy.c rules/
+bpf-ipf.h ip_rules.c samples/
+bpf_filter.c ip_rules.h snoop.h
+bsdinstall ip_scan.c test/
+buildsunos ip_scan.h todo
+etc/ ip_state.c tools/
+fil.c ip_state.h typescript
+ip_auth.c ip_sync.c
+ip_auth.h ip_sync.h
+(freebsd6:/usr/src/contrib/ipfilter) l CVS
+./ Entries Repository
+../ Entries.Log Root
+(freebsd6:/usr/src/contrib/ipfilter) \rm -rf CVS
+(freebsd6:/usr/src/contrib/ipfilter) l
+./ ip_compat.h ip_sync.h
+../ ip_fil.c ipf.h
+.cvsignore ip_fil.h ipl.h
+BNF ip_fil_freebsd.c iplang/
+BSD/ ip_frag.c ipmon.h
+BugReport ip_frag.h ipsd/
+FAQ.FreeBSD ip_ftp_pxy.c ipsend/
+FWTK/ ip_h323_pxy.c ipt.h
+FreeBSD/ ip_htable.c kmem.h
+FreeBSD-2.2/ ip_htable.h l4check/
+FreeBSD-3/ ip_ipsec_pxy.c lib/
+FreeBSD-4.0/ ip_irc_pxy.c man/
+HISTORY ip_log.c md5.c
+IMPORTANT ip_lookup.c md5.h
+INST.FreeBSD-2.2 ip_lookup.h mkfilters
+INSTALL.FreeBSD ip_msnrpc_pxy.c mlf_ipl.c
+INSTALL.xBSD ip_nat.c mlf_rule.c
+IPF.KANJI ip_nat.h mlfk_ipl.c
+IPFILTER.LICENCE ip_netbios_pxy.c mlfk_rule.c
+Makefile ip_pool.c mlh_rule.c
+NAT.FreeBSD ip_pool.h net/
+QNX_OCL.txt ip_pptp_pxy.c netinet/
+README ip_proxy.c opts.h
+STYLE.TXT ip_proxy.h pcap-ipf.h
+WhatsNew40.txt ip_raudio_pxy.c perl/
+Y2K ip_rcmd_pxy.c radix.c
+bpf-ipf.h ip_rpcb_pxy.c radix_ipf.h
+bpf_filter.c ip_rules.c rules/
+bsdinstall ip_rules.h samples/
+buildsunos ip_scan.c snoop.h
+etc/ ip_scan.h test/
+fil.c ip_state.c todo
+ip_auth.c ip_state.h tools/
+ip_auth.h ip_sync.c typescript
+(freebsd6:/usr/src/contrib/ipfilter) cd ..
+(freebsd6:/usr/src/contrib) mv ipfilter ipfilter.i
+(freebsd6:/usr/src/contrib) cd !$ipfilter.i
+(freebsd6:/usr/src/contrib/ipfilter.i) l */CVS
+/bin/ls: No match.
+(freebsd6:/usr/src/contrib/ipfilter.i) cvs m
+(freebsd6:/usr/src/contrib/ipfilter.i) cvs import
+(freebsd6:/usr/src/contrib/ipfilter.i) ~
+/home/darrenr: Permission denied.
+(freebsd6:/usr/src/contrib/ipfilter.i) ~
+(freebsd6:/usr/src/contrib/ipfilter.i) suspend
+(freebsd6:/usr/src/contrib/ipfilter.i) history
+ 1 17:24 cd /usr/src/contrib/ipfilter
+ 2 17:24 l
+ 3 17:24 l CVS
+ 4 17:24 \rm -rf CVS
+ 5 17:24 l
+ 6 17:24 cd ..
+ 7 17:24 mv ipfilter ipfilter.i
+ 8 17:24 cd ipfilter.i
+ 9 17:24 l */CVS
+ 10 17:25 ~
+ 11 17:25 suspend
+ 12 17:25 history
+(freebsd6:/usr/src/contrib/ipfilter.i)
+(freebsd6:/usr/src/contrib/ipfilter.i) kill -STOP $$
+
+^C
+c
+
+
+(freebsd6:/usr/src/contrib/ipfilter.i)
+(freebsd6:/usr/src/contrib/ipfilter.i) c
+
OpenPOWER on IntegriCloud