IPF 1.3.7
authorkstailey <kstailey@openbsd.org>
Tue, 11 Feb 1997 22:23:08 +0000 (22:23 +0000)
committerkstailey <kstailey@openbsd.org>
Tue, 11 Feb 1997 22:23:08 +0000 (22:23 +0000)
38 files changed:
sbin/ipf/ipf.1
sbin/ipf/ipf.4
sbin/ipf/ipf.5
sbin/ipf/ipf.h
sbin/ipfstat/fils.c
sbin/ipfstat/ipfstat.8
sbin/ipfstat/kmem.c
sbin/ipfstat/kmem.h
sbin/ipnat/ipnat.1
sbin/ipnat/ipnat.4
sbin/ipnat/ipnat.5
sbin/ipnat/ipnat.c
sys/netinet/fil.c
sys/netinet/if_ether.c
sys/netinet/ip_fil.c
sys/netinet/ip_fil.h
sys/netinet/ip_fil_compat.h
sys/netinet/ip_frag.c
sys/netinet/ip_frag.h
sys/netinet/ip_icmp.c
sys/netinet/ip_nat.c
sys/netinet/ip_nat.h
sys/netinet/ip_state.c
sys/netinet/ip_state.h
usr.sbin/ipftest/ipft_ef.c
usr.sbin/ipftest/ipft_hx.c
usr.sbin/ipftest/ipft_pc.c
usr.sbin/ipftest/ipft_sn.c
usr.sbin/ipftest/ipft_td.c
usr.sbin/ipftest/ipft_tx.c
usr.sbin/ipftest/ipftest.1
usr.sbin/ipftest/ipt.c
usr.sbin/ipftest/ipt.h
usr.sbin/ipftest/misc.c
usr.sbin/ipftest/pcap.h
usr.sbin/ipftest/snoop.h
usr.sbin/ipmon/ipmon.8
usr.sbin/ipmon/ipmon.c

index 642d129..912d7ef 100644 (file)
 .TH IPF 1
 .SH NAME
-ipf - alters packet filtering lists for IP packet input and ouput
+ipf \- alters packet filtering lists for IP packet input and ouput
 .SH SYNOPSIS
-ipf [-AEDIsnovdrzZ] [-l <block|pass|nomatch>] [-F <i|o|a>]
--f <\fIfilename\fP> [ -f <\fIfilename\fP> [...]]
+.B ipf
+[
+.B \-AdDEInorsUvyzZ
+] [
+.B \-l
+<block|pass|nomatch>
+] [
+.B \-F
+<i|o|a>
+]
+.B \-f
+<\fIfilename\fP>
+[
+.B \-f
+<\fIfilename\fP>
+[...]]
 .SH DESCRIPTION
 .PP
-\fBipf\fP opens the filenames listed (treating "-" as stdin) and parses the
+\fBipf\fP opens the filenames listed (treating "\-" as stdin) and parses the
 file for a set of rules which are to be added or removed from the packet
 filter rule set.
 .PP
 Each rule processed by \fBipf\fP
-is added to the kernels internal lists if there are no parsing problems.
+is added to the kernel's 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 \fBipf\fP.
 .SH OPTIONS
-.IP -A
-set the list to make changes to the active list (default).
-.IP -E
-Enable the filter (if disabled).  Not effective for loadable kernel versions.
-.IP -D
+.TP
+.B \-A
+Set the list to make changes to the active list (default).
+.TP
+.B \-d
+Turn debug mode on.  Causes a hexdump of filter rules to be generated as
+it processes each one.
+.TP
+.B \-D
 Disable the filter (if enabled).  Not effective for loadable kernel versions.
-.IP -F
-this option specifies which filter list to flush.  The parameter should
+.TP
+.B \-E
+Enable the filter (if disabled).  Not effective for loadable kernel versions.
+.TP
+.BR \-F \0<param>
+This option specifies which filter list to flush.  The parameter should
 either be "i" (input), "o" (output) or "a" (remove all filter rules).
 Either a single letter or an entire word starting with the appropriate
 letter maybe used.  This option maybe before, or after, any other with
 the order on the command line being that used to execute options.
-.IP -d
-turn debug mode on.  Causes a hexdump of filter rules to be generated as
-it processes each one.
-.IP -f
-this option specifies which files
-\fBipf\fP should use to get input from for modifying the pack filter rule
+.TP
+.BR \-f \0<filename>
+This option specifies which files
+\fBipf\fP should use to get input from for modifying the packet filter rule
 lists.
-.IP -I
-set the list to make changes to the inactive list.
-.IP -l
+.TP
+.B \-I
+Set the list to make changes to the inactive list.
+.TP
+.B \-l \0<param>
 Use of the \fB-l\fP flag toggles default logging of packets.  Valid
 arguments to this option are \fBpass\fP, \fBblock\fP and \fBnomatch\fP.
 When an option is set, any packet which exits filtering and matches the
 set category is logged.  This is most useful for causing all packets
 which don't match any of the loaded rules to be logged.
-.IP -n
+.TP
+.B \-n
 This flag (no-change) prevents \fBipf\fP from actually making any ioctl
 calls or doing anything which would alter the currently running kernel.
-.IP -o
+.TP
+.B \-o
 Force rules by default to be added/deleted to/from the output list, rather
 than the (default) input list.
-.IP -s
-swap the active filter list in use to be the "other" one.
-.IP -r
-remove matching filter rules rather than add them to the internal lists
-.IP -v
-turn verbose mode on.  Displays information relating to rule processing.
-.IP -z
-for each rule in the input file, reset the statistics for it to zero and
+.TP
+.B \-r
+Remove matching filter rules rather than add them to the internal lists
+.TP
+.B \-s
+Swap the active filter list in use to be the "other" one.
+.TP
+.B \-U
+(SOLARIS 2 ONLY) Block packets travelling along the data stream which aren't
+recognised as IP packets.  They will be printed out on the console.
+.TP
+.B \-v
+Turn verbose mode on.  Displays information relating to rule processing.
+.TP
+.B \-y
+(SOLARIS 2 ONLY) Manually resync the in-kernel interface list maintained
+by IP Filter with the current interface status list.
+.TP
+.B \-z
+For each rule in the input file, reset the statistics for it to zero and
 display the statistics prior to them being zero'd.
-.IP -Z
-zero global statistics held in the kernel for filtering only (this doesn't
+.TP
+.B \-Z
+Zero global statistics held in the kernel for filtering only (this doesn't
 affect fragment or state statistics).
 .DT
 .SH SEE ALSO
index 5cbfbd0..ff17f4f 100644 (file)
@@ -1,6 +1,6 @@
 .TH IPF 4
 .SH NAME
-ipf - packet filtering kernel interface
+ipf \- packet filtering kernel interface
 .SH SYNOPSIS
 #include <sys/ip_fil.h>
 .SH IOCTLS
@@ -26,11 +26,11 @@ However, the full complement is as follows:
        ioctl(fd, SIOCIPFFL, int *)
 .fi
 .PP
-The variations, SIOCADAFR vs SIOCADIFR, allow operation on the two lists,
+The variations, SIOCADAFR vs. SIOCADIFR, allow operation on the two lists,
 active and inactive, respectively.  All of these ioctl's are implemented
 as being routing ioctls and thus the same rules for the various routing
 ioctls and the file descriptor are employed, mainly being that the fd must
-be that of the device associated with the module (ie /dev/ipl).
+be that of the device associated with the module (i.e., /dev/ipl).
 .LP
 .PP
 The three groups of ioctls above perform adding rules to the end of the
index fc8cbd8..417a0ea 100644 (file)
@@ -1,7 +1,6 @@
-.LP
 .TH IPF 5
 .SH NAME
-ipf - IP packet filtering format.
+ipf \- IP packet filter rule syntax
 .SH DESCRIPTION
 .PP
 A rule file for \fBipf\fP may have any name or even be stdin.  As
@@ -11,220 +10,304 @@ into \fBipf\fP.  Thus, to remove all filters on input packets, the following
 could be done:
 .nf
 
-\fC# ipfstat -i | ipf -rf -\fP
+\fC# ipfstat \-i | ipf \-rf \-\fP
 .fi
+.SH GRAMMAR
 .PP
 The format used by \fBipf\fP for construction of filtering rules can be
 described using the following grammar in BNF:
 \fC
 .nf
-filter-rule = [ insert ] action in-out [ options ] [ tos ] [ ttl ]
-              [ proto ] [ ip ] .
+filter-rule = [ insert ] action in-out [ options ] [ match ] [ keep ]
+
+insert = "@" decnumber .
+action = block | "pass" | log | "count" | call .
+in-out = "in" | "out" .
+options        = [ log ] [ "quick" ] [ "on" interface-name [ dup ] [ froute ] ] .
+match  = [ tos ] [ ttl ] [ proto ] [ ip ] .
+keep   = "keep state" | "keep frags" .
+
+block  = "block" [ "return-icmp"[return-code] | "return-rst" ] .
+log    = "log" [ "body" ] [ "first" ] [ "or-block" ] .
+call   = "call" [ "now" ] function-name .
+
+dup    = "dup-to" interface-name[":"ipaddr] .
+froute = "fastroute" | "to" interface-name .
 
-insert  = "@" decnumber .
-action  = block | "pass" | log | "count" | call .
-in-out  = "in" | "out" .
-options = [ log ] [ "quick" ] [ "on" interface-name [ dup ] [ froute ] ] .
-tos     = "tos" decnumber | "tos" hexnumber .
-ttl     = "ttl" decnumber .
-proto   = "proto" protocol .
-ip      = srcdst [ flags ] [ with withopt ] [ icmp ] [ keep ] .
+tos    = "tos" decnumber | "tos" hexnumber .
+ttl    = "ttl" decnumber .
+proto  = "proto" protocol .
+ip     = srcdst [ flags ] [ with withopt ] [ icmp ] [ keep ] .
 
-block   = "block" [ "return-icmp"[return-code] | "return-rst" ] .
-log     = "log" [ "body" ] [ "first" ] .
-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 .
+srcdst = "all" | fromto .
+fromto = "from" object "to" object .
 
-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 .
-flags   = "flags" flag { flag } [ "/" flag { flag } ] .
-with    = "with" | "and" .
-icmp    = "icmp-type" icmp-type [ "code" decnumber ] .
+
+flags  = "flags" flag { flag } [ "/" flag { flag } ] .
+with   = "with" | "and" .
+icmp   = "icmp-type" icmp-type [ "code" decnumber ] .
 return-code = "("icmp-code")" .
-keep    = "keep" "state" | "keep" "frags" .
 
-nummask = host-name [ "/" decnumber ] .
+nummask        = host-name [ "/" decnumber ] .
 host-name = ipaddr | hostname | "any" .
-ipaddr  = host-num "." host-num "." host-num "." host-num .
+ipaddr = host-num "." host-num "." host-num "." host-num .
 host-num = digit [ digit [ digit ] ] .
 port-num = service-name | decnumber .
 
 withopt = [ "not" | "no" ] opttype [ withopt ] .
 opttype = "ipopts" | "short" | "frag" | "opt" ipopts  .
-optname = ipopts [ "," optname ] .
+optname        = ipopts [ "," optname ] .
 ipopts  = optlist | "sec-class" [ secname ] .
-secname = seclvl [ "," secname ] .
+secname        = seclvl [ "," secname ] .
 seclvl  = "unclass" | "confid" | "reserv-1" | "reserv-2" | "reserv-3" |
-          "reserv-4" | "secret" | "topsecret" .
+         "reserv-4" | "secret" | "topsecret" .
 icmp-type = "unreach" | "echo" | "echorep" | "squench" | "redir" |
-            "timex" | "paramprob" | "timest" | "timestrep" | "inforeq" |
-            "inforep" | "maskreq" | "maskrep"  | decnumber .
+           "timex" | "paramprob" | "timest" | "timestrep" | "inforeq" |
+           "inforep" | "maskreq" | "maskrep"  | decnumber .
 icmp-code = decumber | "net-unr" | "host-unr" | "proto-unr" | "port-unr" |
-            "needfrag" | "srcfail" | "net-unk" | "host-unk" | "isolate" |
-            "net-prohib" | "host-prohib" | "net-tos" | "host-tos" .
-optlist = "nop" | "rr" | "zsu" | "mtup" | "mtur" | "encode" | "ts" | "tr" |
-          "sec" | "lsrr" | "e-sec" | "cipso" | "satid" | "ssrr" | "addext" |
-          "visa" | "imitd" | "eip" | "finn" .
+           "needfrag" | "srcfail" | "net-unk" | "host-unk" | "isolate" |
+           "net-prohib" | "host-prohib" | "net-tos" | "host-tos" .
+optlist        = "nop" | "rr" | "zsu" | "mtup" | "mtur" | "encode" | "ts" | "tr" |
+         "sec" | "lsrr" | "e-sec" | "cipso" | "satid" | "ssrr" | "addext" |
+         "visa" | "imitd" | "eip" | "finn" .
 
 hexnumber = "0" "x" hexstring .
 hexstring = hexdigit [ hexstring ] .
 decnumber = digit [ decnumber ] .
 
 compare = "=" | "!=" | "<" | ">" | "<=" | ">=" | "eq" | "ne" | "lt" | "gt" |
-          "le" | "ge" .
-range   = "<>" | "><" .
+         "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" .
+digit  = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" .
+flag   = "F" | "S" | "R" | "P" | "A" | "U" .
 .fi
 .PP
-The "briefest" valid rule is of the form:
+This syntax is somewhat simplified for readability, some combinations
+that match this grammar are disallowed by the software because they do
+not make sense (such as tcp \fBflags\fP for non-TCP packets).
+.SH FILTER RULES
+.PP
+The "briefest" valid rules are (currently) no-ops and are of the form:
 .nf
-
        block in
        pass in
        log in
+       count in
 .fi
 .PP
-These can also be written like:
-.nf
-       block in all pass in from any to any
-.fi
-.PP
-The action, one of either block, log or pass, indicates what to do with
-the packet if it matches the rest of the filter rule.  Block indicates that
-the packet should be dropped here and not let through, log write the packet
-header to the \fBipl\fP packet logging psuedo-device (and has no further
-effect on validity of packet to be allowed through the filter) and pass which
-will allow the packet through.  Each rule MUST have one of these three
-keywords.
-.PP
-In response to blocking a packet, the filter may be instructed to send a
-reply packet, either an ICMP unreachable (\fBreturn-icmp\fP)or a TCP
-"reset" (\fBreturn-rst\fP).  An ICMP packet may be generated in response
-to any IP packet but a TCP reset may only be used with a rule which is
-being applied to TCP packets.
-.PP
-When a packet header is logged with the \fBlog\fP keyword, the optional
-\fBbody\fP keyword indicates that the first 128 bytes of the packet contents
-will be logged to the \fBipl\fP packet logging psuedo-device after the
-headers.
-.PP
-The next word must be either \fBin\fP or \fBout\fP.  As each packet moving
-through the kernel is either an inbound packet or outbound, there is a
-requirement that each filter rule be explicitly stated as to which side of
-the IO it is to be used on.
-.PP
-The list of options is brief, and indeed all are optional.  The presence
-of the \fBlog\fP option indicates, that should this be the last matching
-rule, the packet header will be written to the \fBipl\fP log. The \fBquick\fP
-option allows "short-cut" rules in order to speed up the filter.  If a
-packet header matches a filter rule which is marked as \fBquick\fP, it will
-result in a quick-match and stop processing at this point.  This is good for
-rules such as "block in quick from any to any with ipopts" which will match
-any packet with a non-standard header length (IP options present) and abort
-further processing, recording a match and also that the packet should be
-blocked.  If this command is missing, the rule is taken to be a
-"fall-through" rule, meaning that the result of the match is used
-(block/pass) and that it will continue processing to see if there are any
-more matches.  This allows for effects such as this:
-.LP
-.nf
-        block in from any to any port < 6000
-        pass in from any to any port >= 6000
-        block in from any to port > 6003
-.fi
-.PP
-which sets up the range 6000-6003 as being permitted and all others being
-denied.  Another (easier) way to do the same is:
-.LP
+These are supposed to be the same as, but currently differ from:
+.\" XXX How, why do they differ??
 .nf
-        block in from any to any port 6000 <> 6003
-        pass in from any to any port 5999 >< 6004
+       block in all
+       pass in from any to any
+       log in all
+       count in all
 .fi
 .PP
-Note that both the "block" and "pass" are needed here to affect a result
-as a failed "block" does not imply a pass, only that the rule hasn't taken
-effect.  To then allow ports < 1024, a rule such as:
-.LP
-.nf
-        pass in quick from any to any port < 1024
-.fi
+Filter rules are checked in order, with the last matching rule
+determining the fate of the packet (but see the \fBquick\fP option,
+below).
 .PP
-would be needed before the first block.  Expect to see a "between" operator
-as soon as I can work out how to fit in in.
+Filters are installed by default at the end of the kernel's filter
+lists, prepending the rule with \fB@n\fP will cause it to be inserted
+as the n'th entry in the current list. This is especially useful when
+modifying and testing active filter rulesets. See ipf(1) for more
+information.
+.SH ACTIONS
 .PP
-The \fBon\fP command allows an interface name to be incorporated into the
-matching procedure.  That it is a match and not actually associated with
-the interface itself is a result of the way this was implemented.  Indeed,
-there is nothing to stop you using this with every rule if you so wish.
-If it is absent, the rule is taken to be applied to a packet regardless of
-the interface it is present on.
+The action indicates what to do with the packet if it matches the rest
+of the filter rule. Each rule MUST have an action. The following
+actions are recognised:
+.TP
+.B block
+indicates that the packet should be flagged to be dropped. In response
+to blocking a packet, the filter may be instructed to send a reply
+packet, either an ICMP packet (\fBreturn-icmp\fP) or a TCP "reset"
+(\fBreturn-rst\fP).  An ICMP packet may be generated in response to
+any IP packet, and its type may optionally be specified, but a TCP
+reset may only be used with a rule which is being applied to TCP
+packets.
+.TP
+.B pass
+will flag the packet to be let through the filter.  
+.TP
+.B log
+causes the packet to be logged (as described in the LOGGING section
+below) and has no effect on whether the packet will be allowed through
+the filter.
+.TP
+.B count
+causes the packet to be included in the accounting statistics kept by
+the filter, and has no effect on whether the packet will be allowed through
+the filter. These statistics are viewable with ipfstat(8).
+.TP
+.B call
+this action is used to invoke the named function in the kernel, which
+must conform to a specific calling interface. Customised actions and
+semantics can thus be implemented to supplement those available. This
+feature is for use by knowledgeable hackers, and is not currently
+documented.
 .PP
-The \fBall\fP command is essentially an alias for "from any to any" with
-no other commands.
+The next word must be either \fBin\fP or \fBout\fP.  Each packet
+moving through the kernel is either inbound (just been received on an
+interface, and moving towards the kernel's protocol processing) or
+outbound (transmitted or forwarded by the stack, and on its way to an
+interface). There is a requirement that each filter rule explicitly
+state which side of the I/O it is to be used on.
+.SH OPTIONS
 .PP
-Using \fBtos\fP, packets with different service capabilities can be filtered
-upon.  Individual service levels or combinations can be filtered upon.  The
+The list of options is brief, and all are indeed optional. Where
+options are used, they must be present in the order shown here. These
+are the currently supported options:
+.TP
+.B log
+indicates that, should this be the last matching rule, the packet
+header will be written to the \fBipl\fP log (as described in the
+LOGGING section below).
+.TP
+.B quick
+allows "short-cut" rules in order to speed up the filter or override
+later rules.  If a packet matches a filter rule which is marked as
+\fBquick\fP, this rule will be the last rule checked, allowing a
+"short-circuit" path to avoid processing later rules for this
+packet. The current status of the packet (after any effects of the
+current rule) will determine whether it is passed or blocked.
+.IP
+If this option is missing, the rule is taken to be a "fall-through"
+rule, meaning that the result of the match (block/pass) is saved and
+that processing will continue to see if there are any more matches.
+.TP
+.B on
+allows an interface name to be incorporated into the matching
+procedure. Interface names are as printed by "netstat \-i". If this
+option is used, the rule will only match if the packet is going
+through that interface in the specified direction (in/out). If this
+option is absent, the rule is taken to be applied to a packet
+regardless of the interface it is present on (i.e. on all interfaces).
+Filter rulesets are common to all interfaces, rather than having a
+filter list for each interface.
+.IP
+This option is especially useful for simple IP-spoofing protection:
+packets should only be allowed to pass inbound on the interface from
+which the specified source address would be expected, others may be
+logged and/or dropped.
+.TP
+.B dup-to
+causes the packet to be copied, and the duplicate packet to be sent outbound on the specified interface, optionally with the destination IP address changed to that specified. This is useful for off-host logging, using a network sniffer.
+.TP
+.B to
+causes the packet to be moved to the outbound queue on the
+specified interface. This can be used to circumvent kernel routing
+decisions, and even to bypass the rest of the kernel processing of the
+packet (if applied to an inbound rule). It is thus possible to
+construct a firewall that behaves transparently, like a filtering hub
+or switch, rather than a router. The \fBfastroute\fP keyword is a
+synonym for this option.
+.SH MATCHING PARAMETERS
+.PP 
+The keywords described in this section are used to describe attributes
+of the packet to be used when determining whether rules match or don't
+match. The following general-purpose attributes are provided for
+matching, and must be used in this order:
+.TP
+.B tos
+packets with different Type-Of-Service values can be filtered.
+Individual service levels or combinations can be filtered upon.  The
 value for the TOS mask can either be represented as a hex number or a
 decimal integer value.
-.PP
-Packets may also be selected by their \fBttl\fP value.  The value given in
+.\" XXX TOS mask??  not in grammar!
+.TP
+.B ttl
+packets may also be selected by their Time-To-Live value.  The value given in
 the filter rule must exactly match that in the packet for a match to occur.
 This value can only be given as a decimal integer value.
+.TP
+.B proto
+allows a specific protocol to be matched against.  All protocol names
+found in \fB/etc/protocols\fP are recognised and may be used.
+However, the protocol may also be given as a DECIMAL number, allowing
+for rules to match your own protocols, or new ones which would
+out-date any attempted listing.
+.IP
+The special protocol keyword \fBtcp/udp\fP may be used to match either
+a TCP or a UDP packet, and has been added as a convenience to save
+duplication of otherwise-identical rules.
+.\" XXX grammar should reflect this (/etc/protocols)
 .PP
-The \fBproto\fP command allows a specific protocol to be matched against.
-All protocol names found in \fB/etc/protocols\fP are recognised and maybe
-used.  However, the protocol may also be given as a DECIMAL number, allowing
-for rules to match your own protocols, or new ones which would out-date any
-attempted listing.
-.PP
-To match against BOTH source and destination addresses, the \fBfrom\fP and
-\fBto\fP commands are used.  They both support a large variety of valid
-syntaxes, including the "x/y" format.  There is a special case for the
-hostname \fBany\fP which is taken to be 0.0.0.0/0 and matches all IP numbers.
-If a \fBport\fP match is included, then it is only applied to TCP/UDP
-packets.  If the \fBproto\fP command is left out, packets from both protocols
-are compared.  The hostname may either be a valid hostname, from either the
-hosts file or DNS (depending on your configuration and library) or of the
-dotted numeric form.  There is no special designation for networks but
-network names are recognised.
-.PP
-"x/y" indicates that a mask of y consecutive bits set is generated, starting
-with the MSB, so a value of 16 would give 0xffff0000.
+The \fBfrom\fP and \fBto\fP keywords are used to match against IP
+addresses (and optionally port numbers). Rules must specify BOTH
+source and destination parameters.
+.PP 
+IP addresses may be specified in one of two ways: as a numerical
+address\fB/\fPmask, or as a hostname \fBmask\fP netmask.  The hostname
+may either be a valid hostname, from either the hosts file or DNS
+(depending on your configuration and library) or of the dotted numeric
+form.  There is no special designation for networks but network names
+are recognised.  Note that having your filter rules depend on DNS
+results can introduce an avenue of attack, and is discouraged.
 .PP
-"x mask y" indicates that the mask y is in dotted IP notation or a hexadecimal
-number of the form 0x12345678.
+There is a special case for the hostname \fBany\fP which is taken to
+be 0.0.0.0/0 (see below for mask syntax) and matches all IP addresses.
+Only the presence of "any" has an implied mask, in all other
+situations, a hostname MUST be accompanied by a mask.  It is possible
+to give "any" a hostmask, but in the context of this language, it is
+non-sensical.
 .PP
-Only the presence of "any" has an implied mask, in all other situations,
-a hostname MUST be accompanied by a mask.  It is possible to give "any" a
-hostmask, but in the context of this language, it is non-sensical.
+The numerical format "x\fB/\fPy" indicates that a mask of y
+consecutive 1 bits set is generated, starting with the MSB, so a y value
+of 16 would give 0xffff0000. The symbolic "x \fBmask\fP y" indicates
+that the mask y is in dotted IP notation or a hexadecimal number of
+the form 0x12345678.  Note that all the bits of the IP address
+indicated by the bitmask must match the address on the packet exactly;
+there isn't currently a way to invert the sense of the match, or to
+match ranges of IP addresses which do not express themselves easily as
+bitmasks (anthropomorphization; it's not just for breakfast anymore).
 .PP
-When composing
-\fBport\fP comparisons, either the service name may be used or an integer
-port number.
+If a \fBport\fP match is included, for either or both of source and
+destination, then it is only applied to
+.\" XXX - "may only be" ? how does this apply to other protocols? will it not match, or will it be ignored?
+TCP and UDP packets. If there is no \fBproto\fP match parameter,
+packets from both protocols are compared. This is equivalent to "proto
+tcp/udp".  When composing \fBport\fP comparisons, either the service
+name or an integer port number may be used. Port comparisons may be
+done in a number of forms, with a number of comparison operators, or
+port ranges may be specified. See the examples for more information.
 .PP
-The \fBwith\fP command is used to nominate irregular attributes that some
-packets ma have associated with them.  Alternatively, the keyword \fBand\fP
-maybe used in place of \fBwith\fP.  This is provided to make the rules more
-readable and serves no other purpose.  To filter IP options, in general,
-use \fBipopts\fP.  For more specific filtering on IP options, individual
-options can be listed.  When listed, all those listed must be found in a
-packet to cause a match.
+The \fBall\fP keyword is essentially a synonym for "from any to any"
+with no other match parameters.
 .PP
-Before any option used after the \fBwith\fP keyword, the word \fBnot\fp
-maybe inserted to cause the filter rule to only match if the option(s) is
-not present.
-.PP
-The \fBflags\fP command is only effective for TCP filtering.  Each of the
-letters possible represents one of the possible flags that can be set in the
-TCP header.  The association is as follows:
+Following the source and destination matching parameters, the
+following additional parameters may be used:
+.TP
+.B with
+is used to match irregular attributes that some packets may have
+associated with them.  To match the presence of IP options in general,
+use \fBwith ipopts\fP. To match packets that are too short to contain
+a complete header, use \fBwith short\fP. To match fragmented packets,
+use \fBwith frag\fP.  For more specific filtering on IP options,
+individual options can be listed.
+.IP
+Before any parameter used after the \fBwith\fP keyword, the word
+\fBnot\fP or \fBno\fP may be inserted to cause the filter rule to only
+match if the option(s) is not present.
+.IP
+Multiple consecutive \fBwith\fP clauses are allowed.  Alternatively,
+the keyword \fBand\fP may be used in place of \fBwith\fP, this is
+provided purely to make the rules more readable ("with ... and ...").
+When multiple clauses are listed, all those must match to cause a
+match of the rule.
+.\" XXX describe the options more specifically in a separate section
+.TP
+.B flags
+is only effective for TCP filtering.  Each of the letters possible
+represents one of the possible flags that can be set in the TCP
+header.  The association is as follows:
 .LP
 .nf
         F - FIN
@@ -234,19 +317,22 @@ TCP header.  The association is as follows:
         A - ACK
         U - URG
 .fi
-.PP
-The various flag symbols maybe used in combination, so that "SA" would
-represent a SYN-ACK combination present in a packet.  There is nothing
-preventing combinations, such as "SFR".  However, to guard against weird
-abberations, it is necessary to state which flags you are filtering against.
-To allow this, it is possible to set a mask indicating which TCP flags you
-wich to compare (ie those you deem significant).  This is done by appending
-"/<flags>" to the set of TCP flags you wish to match against. eg:
+.IP
+The various flag symbols may be used in combination, so that "SA"
+would represent a SYN-ACK combination present in a packet.  There is
+nothing preventing the specification of combinations, such as "SFR",
+that would not normally be generated by law-abiding TCP
+implementations.  However, to guard against weird aberrations, it is
+necessary to state which flags you are filtering against.  To allow
+this, it is possible to set a mask indicating which TCP flags you wish
+to compare (i.e., those you deem significant).  This is done by
+appending "/<flags>" to the set of TCP flags you wish to match
+against, e.g.:
 .LP
 .nf
        ... flags S
-                       # becomes "flags S/AUPRFS" and will match a
-                       # packet with ONLY the SYN flag set.
+                       # becomes "flags S/AUPRFS" and will match
+                       # packets with ONLY the SYN flag set.
 
        ... flags SA
                        # becomes "flags SA/AUPRFS" and will match any
@@ -258,20 +344,90 @@ wich to compare (ie those you deem significant).  This is done by appending
                        # keyword action.  "S/SA" will NOT match a packet
                        # with BOTH SYN and ACK set, but WILL match "SFP".
 .fi
-.PP
-The next parameter set for the filter rule is the optional \fBicmp-type\fP.
-It is only effective when used with \fB"proto icmp"\fP and must NOT be used
-in conjuction with \fBflags\fP.  There are a number of types which can be
-refered to by an abbreviation recognised by this language or the numbers
-with which they are associated can be used.
+.TP
+.B icmp-type
+is only effective when used with \fBproto icmp\fP and must NOT be used
+in conjuction with \fBflags\fP.  There are a number of types, which can be
+referred to by an abbreviation recognised by this language, or the numbers
+with which they are associated can be used.  The most important from
+a security point of view is the ICMP redirect.
+.SH KEEP HISTORY
 .PP
 The last parameter which can be set for a filter rule is whether on not to
-record state information for that packet, and what sort to keep.  Either
-information relating to the packet's `flow' or if fragment details can be
-kept, allowing packets which match these to flow straight through, rather
+record historical information for that packet, and what sort to keep. The following information can be kept:
+.TP
+.B state
+keeps information about the flow of a communication session. State can
+be kept for TCP, UDP, and ICMP packets.
+.TP
+.B frags
+keeps information on fragmented packets, to be applied to later
+fragments.
+.PP
+allowing packets which match these to flow straight through, rather
 than going through the access control list.
+.SH LOGGING
+.PP
+When a packet is logged, with either the \fBlog\fP action or option,
+the headers of the packet are written to the \fBipl\fP packet logging
+psuedo-device. Immediately following the \fBlog\fP keyword, the
+following qualifiers may be used (in order):
+.TP
+.B body
+indicates that the first 128 bytes of the packet contents will be
+logged after the headers. 
+.TP
+.B first
+??
+.TP
+.B or-block
+indicates that, if for some reason the filter is unable to log the packet (such as the log reader being too slow) then the rule should be interpreted as if the action was \fBblock\fP for this packet.
+.PP
+See ipl(4) for the format of records written
+to this device. The ipmon(8) program can be used to read and format
+this log.
+.SH EXAMPLES
+.PP
+The \fBquick\fP option is good for rules such as:
+\fC
+.nf
+block in quick from any to any with ipopts
+.fi
+.PP
+which will match any packet with a non-standard header length (IP
+options present) and abort further processing of later rules,
+recording a match and also that the packet should be blocked.
+.PP
+The "fall-through" rule parsing allows for effects such as this:
+.LP
+.nf
+        block in from any to any port < 6000
+        pass in from any to any port >= 6000
+        block in from any to port > 6003
+.fi
+.PP
+which sets up the range 6000-6003 as being permitted and all others being
+denied.  Note that the effect of the first rule is overridden by subsequent
+rules.  Another (easier) way to do the same is:
+.LP
+.nf
+        block in from any to any port 6000 <> 6003
+        pass in from any to any port 5999 >< 6004
+.fi
+.PP
+Note that both the "block" and "pass" are needed here to effect a
+result as a failed match on the "block" action does not imply a pass,
+only that the rule hasn't taken effect.  To then allow ports < 1024, a
+rule such as:
+.LP
+.nf
+        pass in quick from any to any port < 1024
+.fi
+.PP
+would be needed before the first block.  
 .SH FILES
 /etc/services
+.br
 /etc/hosts
 .SH SEE ALSO
 ipf(1), ipftest(1)
index 86a60fa..c287389 100644 (file)
@@ -6,9 +6,12 @@
  * to the original author and the contributors.
  *
  * @(#)ipf.h   1.12 6/5/96
- * $Id: ipf.h,v 1.5 1996/07/18 05:11:02 dm Exp $
+ * $Id: ipf.h,v 1.6 1997/02/11 22:23:39 kstailey Exp $
  */
 
+#ifndef        SOLARIS
+#define        SOLARIS (defined(sun) && (defined(__svr4__) || defined(__SVR4)))
+#endif
 #define        OPT_REMOVE      0x00001
 #define        OPT_DEBUG       0x00002
 #define        OPT_OUTQUE      FR_OUTQUE       /* 0x0004 */
@@ -47,6 +50,9 @@ struct        ipopt_names     {
 
 extern u_long  hostnum(), optname();
 extern void    printpacket();
+#if SOLARIS
+extern int     inet_aton();
+#endif
 
 #ifdef sun
 #define        STRERROR(x)     sys_errlist[x]
@@ -55,3 +61,7 @@ extern        char    *sys_errlist[];
 #define        STRERROR(x)     strerror(x)
 #endif
 
+#ifndef        MIN
+#define        MIN(a,b)        ((a) > (b) ? (b) : (a))
+#endif
+
index aaece1b..076f0fe 100644 (file)
@@ -40,9 +40,9 @@
 #include <paths.h>
 #endif
 
-#ifndef        lint
+#if !defined(lint) && defined(LIBC_SCCS)
 static char    sccsid[] = "@(#)fils.c  1.21 4/20/96 (C) 1993-1996 Darren Reed";
-static char    rcsid[] = "$Id: fils.c,v 1.7 1996/10/08 07:33:33 niklas Exp $";
+static char    rcsid[] = "$Id: fils.c,v 1.8 1997/02/11 22:23:41 kstailey Exp $";
 #endif
 #ifdef _PATH_UNIX
 #define        VMUNIX  _PATH_UNIX
@@ -124,7 +124,7 @@ char *argv[];
                        opts |= OPT_VERBOSE;
                        break;
                default :
-                       Usage();
+                       Usage(argv[0]);
                        break;
                }
        }
@@ -203,9 +203,10 @@ struct     friostat        *fp;
                        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);
+       PRINTF(" packets logged:\tinput %lu output %lu\n",
+                       fp->f_st[0].fr_pkl, fp->f_st[1].fr_pkl);
+       PRINTF(" log failures:\t\tinput %lu output %lu\n",
+                       fp->f_st[0].fr_skip, fp->f_st[1].fr_skip);
        PRINTF("fragment state(in):\tkept %lu\tlost %lu\n",
                        fp->f_st[0].fr_nfr, fp->f_st[0].fr_bnfr);
        PRINTF("fragment state(out):\tkept %lu\tlost %lu\n",
@@ -218,6 +219,10 @@ struct     friostat        *fp;
                        fp->f_st[0].fr_ret, fp->f_st[1].fr_ret);
        PRINTF("Result cache hits(in):\t%lu\t(out):\t%lu\n",
                        fp->f_st[0].fr_chit, fp->f_st[1].fr_chit);
+       PRINTF("IN Pullups succeeded:\t%lu\tfailed:\t%lu\n",
+                       fp->f_st[0].fr_pull[0], fp->f_st[0].fr_pull[1]);
+       PRINTF("OUT Pullups succeeded:\t%lu\tfailed:\t%lu\n",
+                       fp->f_st[1].fr_pull[0], fp->f_st[1].fr_pull[1]);
 
        PRINTF("Packet log flags set: (%#x)\n", frf);
        if (frf & FF_LOGPASS)
@@ -243,12 +248,11 @@ struct    friostat        *fiop;
                set = 1 - set;
        if (opts & OPT_ACCNT) {
                i = F_AC;
-               if (opts & OPT_INQUE)
-                       fp = (struct frentry *)fiop->f_acctin[set];
-               else {
+               if (opts & OPT_OUTQUE) {
                        fp = (struct frentry *)fiop->f_acctout[set];
                        i++;
-               }
+               } else if (opts & OPT_INQUE)
+                       fp = (struct frentry *)fiop->f_acctin[set];
        } else if (opts & OPT_OUTQUE) {
                i = F_OUT;
                fp = (struct frentry *)fiop->f_fout[set];
@@ -311,14 +315,16 @@ ips_stat_t *ipsp;
                        if (kmemcpy(&ips, istab[i], sizeof(ips)) == -1)
                                break;
                        PRINTF("%s -> ", inet_ntoa(ips.is_src));
-                       PRINTF("%s age %d pass %d pr %d\n",
+                       PRINTF("%s age %d pass %d pr %d state %d/%d\n",
                                inet_ntoa(ips.is_dst), ips.is_age,
-                               ips.is_pass, ips.is_p);
+                               ips.is_pass, ips.is_p, ips.is_state[0],
+                               ips.is_state[1]);
                        if (ips.is_p == IPPROTO_TCP)
-                               PRINTF("\t%hu -> %hu %lu:%lu %hu\n",
+                               PRINTF("\t%hu -> %hu %lu:%lu %hu:%hu\n",
                                        ntohs(ips.is_sport),
                                        ntohs(ips.is_dport),
-                                       ips.is_seq, ips.is_ack, ips.is_win);
+                                       ips.is_seq, ips.is_ack,
+                                       ips.is_swin, ips.is_dwin);
                        else if (ips.is_p == IPPROTO_UDP)
                                PRINTF("\t%hu -> %hu\n", ntohs(ips.is_sport),
                                        ntohs(ips.is_dport));
index 1b37854..db23e39 100644 (file)
@@ -1,13 +1,17 @@
-.LP
 .TH ipfstat 8
 .SH NAME
-ipfstat - reports on packet filter statistics and filter list
+ipfstat \- reports on packet filter statistics and filter list
 .SH SYNOPSIS
-ipfstat [-hIiovd:]
+.B ipfstat
+[
+.B \-hIinov
+] [
+.B \-d
+<device>
+]
 .SH DESCRIPTION
-.LP
 .PP
-\fBipfstat examines /dev/kmem using the symbols \fB_fr_flags\fP,
+\fBipfstat\fP examines /dev/kmem using the symbols \fB_fr_flags\fP,
 \fB_frstats\fP, \fB_filterin\fP, and \fB_filterout\fP.
 To run and work, it needs to be able to read both /dev/kmem and the
 kernel itself.  The kernel name defaults to \fB/vmunix\fP.
@@ -16,39 +20,52 @@ The default behaviour of \fBipfstat\fP
 is to retrieve and display the accumulated statistics which have been
 accumulated over time as the kernel has put packets through the filter.
 .SH OPTIONS
-.IP -a
-display the accounting filter list and show bytes counted against each rule.
-.IP -d <device>
-use a device other than \fB/dev/ipl\fP for interfacing with the kernel.
-.IP -f
-show fragment state information (statistics) and held state information (in
+.TP
+.B \-a
+Display the accounting filter list and show bytes counted against each rule.
+.TP
+.BR \-d \0<device>
+Use a device other than \fB/dev/ipl\fP for interfacing with the kernel.
+.TP
+.B \-f
+Show fragment state information (statistics) and held state information (in
 the kernel) if any is present.
-.IP -h
-show per-rule the number of times each one scores a "hit".  For use in
-combination with \fB-i\fP.
-.IP -i
-display the filter list used for the input side of the kernel IP processing.
-.IP -I
-swap between retrieving "inactive"/"active" filter list details.  For use
-in combination with \fB-i\fP.
-.IP -o
-display the filter list used for the output side of the kernel IP processing.
-.IP -s
-show packet/flow state information (statistics) and held state information (in
+.TP
+.B \-h
+Show per-rule the number of times each one scores a "hit".  For use in
+combination with \fB\-i\fP.
+.TP
+.B \-i
+Display the filter list used for the input side of the kernel IP processing.
+.TP
+.B \-I
+Swap between retrieving "inactive"/"active" filter list details.  For use
+in combination with \fB\-i\fP.
+.TP
+.B \-n
+Show the "rule number" for each rule as it is printed.
+.TP
+.B \-o
+Display the filter list used for the output side of the kernel IP processing.
+.TP
+.B \-s
+Show packet/flow state information (statistics) and held state information (in
 the kernel) if any is present.
-.IP -v
-turn verbose mode on.  Displays more debugging information.
+.TP
+.B \-v
+Turn verbose mode on.  Displays more debugging information.
 .SH SYNOPSIS
 The role of \fBipfstat\fP is to display current kernel statistics gathered
 as a result of applying the filters in place (if any) to packets going in and
 out of the kernel.  This is the default operation when no command line
 parameters are present.
 .PP
-When supplied with either \fB-i\fP or \fB-o\fP, it will retrieve and display
+When supplied with either \fB\-i\fP or \fB\-o\fP, it will retrieve and display
 the appropriate list of filter rules currently installed and in use by the
 kernel.
 .SH FILES
 /dev/kmem
+.br
 /vmunix
 .SH SEE ALSO
 ipf(1), ipfstat(1)
index d11cee4..638fa1c 100644 (file)
@@ -19,9 +19,9 @@
 
 #define KMEM "/dev/kmem"
 
-#ifndef lint
+#if !defined(lint) && defined(LIBC_SCCS)
 static  char    sccsid[] = "@(#)kmem.c 1.4 1/12/96 (C) 1992 Darren Reed";
-static char    rcsid[] = "$Id: kmem.c,v 1.5 1996/12/17 23:50:51 niklas Exp $";
+static char    rcsid[] = "$Id: kmem.c,v 1.6 1997/02/11 22:23:44 kstailey Exp $";
 #endif
 
 static int     kmemfd = -1;
@@ -38,7 +38,7 @@ int   openkmem()
 
 int    kmemcpy(buf, pos, n)
 register char  *buf;
-u_long pos;
+long   pos;
 register int   n;
 {
        register int    r;
index fad02f3..f0b4c44 100644 (file)
@@ -4,7 +4,7 @@
  * Redistribution and use in source and binary forms are permitted
  * provided that this notice is preserved and due credit is given
  * to the original author and the contributors.
- * $Id: kmem.h,v 1.3 1996/07/18 05:08:10 dm Exp $
+ * $Id: kmem.h,v 1.4 1997/02/11 22:23:46 kstailey Exp $
  */
 
 extern int     openkmem();
index 3721e65..f3221a7 100644 (file)
@@ -1,11 +1,15 @@
-.TH IPFNAT 1
+.TH IPNAT 1
 .SH NAME
-ipnat - user interface to the NAT
+ipnat \- user interface to the NAT
 .SH SYNOPSIS
-ipnat [-lnrsv] -f <\fIfilename\fP>
+.B ipnat
+[
+.B \-lnrsvCF
+]
+.B \-f <\fIfilename\fP>
 .SH DESCRIPTION
 .PP
-\fBipnat\fP opens the filename given (treating "-" as stdin) and parses the
+\fBipnat\fP opens the filename given (treating "\-" as stdin) and parses the
 file for a set of rules which are to be added or removed from the IP NAT.
 .PP
 Each rule processed by \fBipnat\fP
@@ -13,17 +17,29 @@ 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.
 .SH OPTIONS
-.IP -l
+.TP
+.B \-C
+delete all entries in the current NAT listing (NAT rules)
+.TP
+.B \-F
+delete all active entries in the current NAT table (currently active
+NAT mappings)
+.TP
+.B \-l
 Show the list of current NAT table entry mappings.
-.IP -n
+.TP
+.B \-n
 This flag (no-change) prevents \fBipf\fP from actually making any ioctl
 calls or doing anything which would alter the currently running kernel.
-.IP -s
-retrieve and display NAT statistics
-.IP -r
-remove matching NAT rules rather than add them to the internal lists
-.IP -v
-turn verbose mode on.  Displays information relating to rule processing.
+.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 \-v
+Turn verbose mode on.  Displays information relating to rule processing.
 .DT
 .SH SEE ALSO
 ipfstat(1), ipftest(1), ipf(1), ipnat(4), ipnat(5)
index 2b1723d..79ab09b 100644 (file)
@@ -1,6 +1,6 @@
 .TH IPNAT 4
 .SH NAME
-ipnat - Network Address Translation kernel interface
+ipnat \- Network Address Translation kernel interface
 .SH SYNOPSIS
 #include <sys/ip_fil.h>
 .SH IOCTLS
@@ -20,7 +20,7 @@ supported.
 These ioctl's are implemented as being routing ioctls and thus the same rules
 for the various routing ioctls and the file descriptor are employed, mainly
 being that the fd must be that of the device associated with the module
-(ie /dev/ipl).
+(i.e., /dev/ipl).
 .LP
 .PP
 The strcture used with the NAT interface is described below:
@@ -85,4 +85,4 @@ typedef struct  natstat {
 It would be nice if there were more flexibility when adding and deleting
 filter rules.
 .SH SEE ALSO
-ipnat(1), ipfstat(1), ipf(1), ipf(4), ipnat(5)
+ipfstat(1), ipf(1), ipnat(1), ipf(4), ipnat(5)
index 51fdbee..80d8054 100644 (file)
@@ -1,7 +1,6 @@
-.LP
 .TH IPNAT 5
 .SH NAME
-ipnat - IP NAT file format
+ipnat \- IP NAT file format
 .SH DESCRIPTION
 The format for files accepted by ipnat is described by the following grammar:
 .LP
@@ -65,6 +64,7 @@ so that all TCP/UDP packets were port mapped and only other protocols, such as
 ICMP, only have their IP# changed.
 .SH FILES
 /etc/services
+.br
 /etc/hosts
 .SH SEE ALSO
-ipnat(1), ipf(5), ipnat(4)
+ipnat(1), ipf(5), ipnat(4), ipnat(5)
index 80c1f98..afc2230 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: ipnat.c,v 1.9 1997/02/07 20:06:44 kstailey Exp $      */
+/*     $OpenBSD: ipnat.c,v 1.10 1997/02/11 22:24:20 kstailey Exp $     */
 /*
  * (C)opyright 1993,1994,1995 by Darren Reed.
  *
@@ -42,7 +42,7 @@
 #include <netinet/tcp.h>
 #include <net/if.h>
 #include "ip_fil_compat.h"
-#include "ip_fil.h"
+#include "ip_fil.h"            /* XXX needed? */
 #include <netdb.h>
 #include <arpa/nameser.h>
 #include <arpa/inet.h>
 #include "ip_nat.h"
 #include <ctype.h>
 
-#if 0
-#ifndef lint
+
+#if !defined(lint) && defined(LIBC_SCCS)
 static  char    sccsid[] ="@(#)ipnat.c 1.9 6/5/96 (C) 1993 Darren Reed";
-#endif
+static char    rcsid[] = "Id: ipnat.c,v 2.0.1.7 1997/01/30 12:02:32 darrenr Exp";
 #endif
 
 #if    SOLARIS
@@ -63,13 +63,21 @@ static  char    sccsid[] ="@(#)ipnat.c      1.9 6/5/96 (C) 1993 Darren Reed";
 extern char    *optarg;
 extern int     kmemcpy();
 
-void   dostats(), printnat(), parsefile();
+void   dostats(), printnat(), parsefile(), flushtable();
+
+#define        OPT_REM         1
+#define        OPT_NODO        2
+#define        OPT_STAT        4
+#define        OPT_LIST        8
+#define        OPT_VERBOSE     16
+#define        OPT_FLUSH       32
+#define        OPT_CLEAR       64
 
 
 void usage(name)
 char *name;
 {
-       fprintf(stderr, "%s: [-lnrsv] [-f filename]\n", name);
+       fprintf(stderr, "%s: [-CFlnrsv] [-f filename]\n", name);
        exit(1);
 }
 
@@ -81,40 +89,48 @@ char *argv[];
        char    *file = NULL, c;
        int     fd, opts = 1;
 
-       while ((c = getopt(argc, argv, "f:lnrsv")) != -1)
+       while ((c = getopt(argc, argv, "CFf:lnrsv")) != -1)
                switch (c)
                {
+               case 'C' :
+                       opts |= OPT_CLEAR;
+                       break;
                case 'f' :
                        file = optarg;
                        break;
+               case 'F' :
+                       opts |= OPT_FLUSH;
+                       break;
                case 'l' :
-                       opts |= 8;
+                       opts |= OPT_LIST;
                        break;
                case 'n' :
-                       opts |= 2;
+                       opts |= OPT_NODO;
                        break;
                case 'r' :
-                       opts &= ~1;
+                       opts &= ~OPT_REM;
                        break;
                case 's' :
-                       opts |= 4;
+                       opts |= OPT_STAT;
                        break;
                case 'v' :
-                       opts |= 16;
+                       opts |= OPT_VERBOSE;
                        break;
                default :
                        usage(argv[0]);
                }
 
-       if (((fd = open(IPL_NAME, O_RDWR)) == -1) &&
+       if (!(opts & OPT_NODO) && ((fd = open(IPL_NAME, O_RDWR)) == -1) &&
            ((fd = open(IPL_NAME, O_RDONLY)) == -1)) {
                perror("open");
                exit(-1);
        }
 
+       if (opts & (OPT_FLUSH|OPT_CLEAR))
+               flushtable(fd, opts);
        if (file)
                parsefile(fd, file, opts);
-       if (opts & 12)
+       if (opts & (OPT_LIST|OPT_STAT))
                dostats(fd, opts);
        return 0;
 }
@@ -149,9 +165,10 @@ u_long     ip;
 }
 
 
-void printnat(np, verbose)
+void printnat(np, verbose, ptr)
 ipnat_t *np;
 int verbose;
+void *ptr;
 {
        int     bits;
 
@@ -164,14 +181,20 @@ int verbose;
                        printf("/%s ", inet_ntoa(np->in_out[1]));
                if (np->in_pmin)
                        printf("port %d ", ntohs(np->in_pmin));
-               printf("-> %s", inet_ntoa(np->in_in[0]),
-                      ntohs(np->in_pnext));
-               if (np->in_pmax)
-                       printf(" port %d", ntohs(np->in_pmax));
+               printf("-> %s", inet_ntoa(np->in_in[0]));
+               if (np->in_pnext)
+                       printf(" port %d", ntohs(np->in_pnext));
+               if (np->in_flags & IPN_TCPUDP)
+                       printf(" tcp/udp");
+               else if (np->in_flags & IPN_TCP)
+                       printf(" tcp");
+               else if (np->in_flags & IPN_UDP)
+                       printf(" udp");
                printf("\n");
                if (verbose)
-                       printf("\t%x %u %x %u", (u_int)np->in_ifp,
-                              np->in_space, np->in_flags, np->in_pnext);
+                       printf("\t%x %u %x %u %x %d\n", (u_int)np->in_ifp,
+                              np->in_space, np->in_flags, np->in_pnext, np,
+                              np->in_use);
        } else {
                np->in_nextip.s_addr = htonl(np->in_nextip.s_addr);
                printf("map %s %s/", np->in_ifname, inet_ntoa(np->in_in[0]));
@@ -186,16 +209,16 @@ int verbose;
                        printf("%d ", bits);
                else
                        printf("%s", inet_ntoa(np->in_out[1]));
-               if (np->in_port[0] || np->in_port[1]) {
+               if (np->in_pmin || np->in_pmax) {
                        printf(" portmap");
-                       if (np->in_flags & IPN_TCPUDP)
+                       if ((np->in_flags & IPN_TCPUDP) == IPN_TCPUDP)
                                printf(" tcp/udp");
                        else if (np->in_flags & IPN_TCP)
                                printf(" tcp");
                        else if (np->in_flags & IPN_UDP)
                                printf(" udp");
-                       printf(" %d:%d", ntohs(np->in_port[0]),
-                              ntohs(np->in_port[1]));
+                       printf(" %d:%d", ntohs(np->in_pmin),
+                              ntohs(np->in_pmax));
                }
                printf("\n");
                if (verbose)
@@ -206,58 +229,87 @@ int verbose;
 }
 
 
+/*
+ * Get a nat filter type given its kernel address.
+ */
+char *getnattype(ipnat)
+ipnat_t *ipnat;
+{
+       ipnat_t ipnatbuff;
+
+       if (ipnat && kmemcpy(&ipnatbuff, ipnat, sizeof(ipnatbuff)))
+               return "???";
+
+       return (ipnatbuff.in_redir == NAT_MAP) ? "MAP" : "RDR";
+}
+
+
 void dostats(fd, opts)
 int fd, opts;
 {
        natstat_t ns;
        ipnat_t ipn;
-       nat_t   **nt, *np, nat;
-       int     i;
+       nat_t   **nt[2], *np, nat;
+       int     i = 0;
 
-       if (ioctl(fd, SIOCGNATS, &ns) == -1) {
+       bzero((char *)&ns, sizeof(ns));
+
+       if (!(opts & OPT_NODO) && ioctl(fd, SIOCGNATS, &ns) == -1) {
                perror("ioctl(SIOCGNATS)");
                return;
        }
-       if (opts & 4) {
+
+       if (opts & OPT_STAT) {
                printf("mapped\tin\t%lu\tout\t%lu\n",
                        ns.ns_mapped[0], ns.ns_mapped[1]);
                printf("added\t%lu\texpired\t%lu\n",
                        ns.ns_added, ns.ns_expire);
                printf("inuse\t%lu\n", ns.ns_inuse);
-               if (opts & 16)
+               if (opts & OPT_VERBOSE)
                        printf("table %#x list %#x\n",
                                (u_int)ns.ns_table, (u_int)ns.ns_list);
        }
-       if (opts & 8) {
+       if (opts & OPT_LIST) {
+               printf("List of active MAP/Redirect filters:\n");
                while (ns.ns_list) {
                        if (kmemcpy(&ipn, ns.ns_list, sizeof(ipn))) {
                                perror("kmemcpy");
                                break;
                        }
-                       printnat(&ipn, opts & 16);
+                       printnat(&ipn, opts & OPT_VERBOSE, (void *)ns.ns_list);
                        ns.ns_list = ipn.in_next;
                }
 
-               nt = (nat_t **)malloc(sizeof(*nt) * NAT_SIZE);
-               if (kmemcpy(nt, ns.ns_table, sizeof(*nt) * NAT_SIZE)) {
+               nt[0] = (nat_t **)malloc(sizeof(*nt) * NAT_SIZE);
+               if (kmemcpy(nt[0], ns.ns_table[0], sizeof(**nt) * NAT_SIZE)) {
                        perror("kmemcpy");
                        return;
                }
+
+               printf("\nList of active sessions:\n");
+
                for (i = 0; i < NAT_SIZE; i++)
-                       for (np = nt[i]; np; np = nat.nat_next) {
+                       for (np = nt[0][i]; np; np = nat.nat_hnext[0]) {
                                if (kmemcpy(&nat, np, sizeof(nat)))
                                        break;
-                               printf("%s %hu <- -> ",
+
+                               printf("%s %-15s %-5hu <- ->",
+                                       getnattype(nat.nat_ptr),
                                        inet_ntoa(nat.nat_inip),
                                        ntohs(nat.nat_inport));
-                               printf("%s %hu %hu %hu %lx [",
+                               printf(" %-15s %-5hu",
                                        inet_ntoa(nat.nat_outip),
-                                       ntohs(nat.nat_outport),
-                                       nat.nat_age, nat.nat_use,
-                                       nat.nat_sumd);
-                               printf("%s %hu]\n", inet_ntoa(nat.nat_oip),
+                                       ntohs(nat.nat_outport));
+                               printf(" [%s %hu]", inet_ntoa(nat.nat_oip),
                                        ntohs(nat.nat_oport));
+                               printf(" %d %hu %lx", nat.nat_age,
+                                       nat.nat_use, nat.nat_sumd);
+#if SOLARIS
+                               printf(" %lx", nat.nat_ipsumd);
+#endif
+                               putchar('\n');
                        }
+               free(nt[0]);
        }
 }
 
@@ -356,7 +408,8 @@ char *line;
 {
        static ipnat_t ipn;
        char *s, *t;
-       char *shost, *snetm, *dhost, *dnetm, *proto, *dport, *tport;
+       char *shost, *snetm, *dhost, *proto;
+       char *dnetm = NULL, *dport = NULL, *tport = NULL;
        int resolved;
 
        bzero((char *)&ipn, sizeof(ipn));
@@ -498,13 +551,21 @@ char *line;
 
        if (ipn.in_redir == NAT_MAP) {
                ipn.in_inip = hostnum(shost, &resolved);
+               if (resolved == -1)
+                       return NULL;
                ipn.in_inmsk = hostmask(snetm);
                ipn.in_outip = hostnum(dhost, &resolved);
+               if (resolved == -1)
+                       return NULL;
                ipn.in_outmsk = hostmask(dnetm);
        } else {
                ipn.in_inip = hostnum(dhost, &resolved); /* Inside is target */
+               if (resolved == -1)
+                       return NULL;
                ipn.in_inmsk = hostmask("255.255.255.255");
                ipn.in_outip = hostnum(shost, &resolved);
+               if (resolved == -1)
+                       return NULL;
                ipn.in_outmsk = hostmask(snetm);
                if (!(s = strtok(NULL, " \t"))) {
                        ipn.in_flags = IPN_TCP; /* XXX- TCP only by default */
@@ -516,12 +577,20 @@ char *line;
                                ipn.in_flags = IPN_UDP;
                        else if (!strcasecmp(s, "tcp/udp"))
                                ipn.in_flags = IPN_TCPUDP;
+                       else if (!strcasecmp(s, "tcpudp"))
+                               ipn.in_flags = IPN_TCPUDP;
                        else {
                                fprintf(stderr,
                                        "expected protocol - got \"%s\"\n", s);
                                return NULL;
                        }
                        proto = s;
+                       if ((s = strtok(NULL, " \t"))) {
+                               fprintf(stderr,
+                                       "extra junk at the end of rdr: %s\n",
+                                       s);
+                               return NULL;
+                       }
                }
                ipn.in_pmin = portnum(dport, proto); /* dest port */
                ipn.in_pmax = ipn.in_pmin; /* NECESSARY of removing nats */
@@ -540,6 +609,8 @@ char *line;
                ipn.in_flags = IPN_TCP;
        else if (!strcasecmp(s, "udp"))
                ipn.in_flags = IPN_UDP;
+       else if (!strcasecmp(s, "tcpudp"))
+               ipn.in_flags = IPN_TCPUDP;
        else if (!strcasecmp(s, "tcp/udp"))
                ipn.in_flags = IPN_TCPUDP;
        else {
@@ -585,10 +656,10 @@ int opts;
                        if (*line)
                                fprintf(stderr, "%d: syntax error in \"%s\"\n",
                                        linenum, line);
-               } else if (!(opts & 2)) {
-                       if ((opts &16) && np)
-                               printnat(np, opts & 16);
-                       if (opts & 1) {
+               } else if (!(opts & OPT_NODO)) {
+                       if ((opts & OPT_VERBOSE) && np)
+                               printnat(np, opts &  OPT_VERBOSE, NULL);
+                       if (opts & OPT_REM) {
                                if (ioctl(fd, SIOCADNAT, np) == -1)
                                        perror("ioctl(SIOCADNAT)");
                        } else if (ioctl(fd, SIOCRMNAT, np) == -1)
@@ -598,3 +669,26 @@ int opts;
        }
        fclose(stdin);
 }
+
+
+void flushtable(fd, opts)
+int fd, opts;
+{
+       int n = 0;
+
+       if (opts & OPT_FLUSH) {
+               n = 0;
+               if (!(opts & OPT_NODO) && ioctl(fd, SIOCFLNAT, &n) == -1)
+                       perror("ioctl(SIOCFLNAT)");
+               else
+                       printf("%d entries flushed from NAT table\n", n);
+       }
+
+       if (opts & OPT_CLEAR) {
+               n = 0;
+               if (!(opts & OPT_NODO) && ioctl(fd, SIOCCNATL, &n) == -1)
+                       perror("ioctl(SIOCCNATL)");
+               else
+                       printf("%d entries flushed from NAT list\n", n);
+       }
+}
index 279e583..cec61eb 100644 (file)
@@ -1,3 +1,4 @@
+/*     $OpenBSD: fil.c,v 1.8 1997/02/11 22:23:08 kstailey Exp $        */
 /*
  * (C)opyright 1993-1996 by Darren Reed.
  *
@@ -6,9 +7,9 @@
  * to the original author and the contributors.
  */
 #if 0
-#ifndef        lint
+#if !defined(lint) && defined(LIBC_SCCS)
 static char    sccsid[] = "@(#)fil.c   1.36 6/5/96 (C) 1993-1996 Darren Reed";
-static char    rcsid[] = "$OpenBSD: fil.c,v 1.7 1996/10/24 17:56:20 tholo Exp $";
+static char    rcsid[] = "Id: fil.c,v 2.0.1.3 1997/01/29 13:38:54 darrenr Exp";
 #endif
 #endif
 
@@ -25,11 +26,6 @@ static       char    rcsid[] = "$OpenBSD: fil.c,v 1.7 1996/10/24 17:56:20 tholo Exp $";
 #endif
 #include <sys/uio.h>
 #if !defined(__SVR4) && !defined(__svr4__)
-# if defined(__OpenBSD__)
-#  include <sys/dirent.h>
-# else
-#  include <sys/dir.h>
-# endif
 # include <sys/mbuf.h>
 #else
 # include <sys/byteorder.h>
@@ -69,7 +65,7 @@ extern        void    debug(), verbose();
 #define        FR_IFDEBUG(ex,second,verb_pr)   if (ex) { debug verb_pr; second; }
 #define        FR_VERBOSE(verb_pr)     verbose verb_pr
 #define        FR_DEBUG(verb_pr)       debug verb_pr
-#define        FR_SCANLIST(p, ip, fi, m)       fr_scanlist(p, ip, fi)
+#define        FR_SCANLIST(p, ip, fi, m)       fr_scanlist(p, ip, fi, NULL)
 # if SOLARIS
 #  define      bcmp    memcmp
 # endif
@@ -78,23 +74,24 @@ extern      void    debug(), verbose();
 #define        FR_IFDEBUG(ex,second,verb_pr)   ;
 #define        FR_VERBOSE(verb_pr)
 #define        FR_DEBUG(verb_pr)
+#define        FR_SCANLIST(p, ip, fi, m)       fr_scanlist(p, ip, fi, m)
+extern int     send_reset __P((struct tcpiphdr *));
 # if SOLARIS
-extern int     icmp_error();
-extern kmutex_t        ipf_mutex;
-# define       FR_SCANLIST(p, ip, fi, m)       fr_scanlist(p, ip, fi)
+extern int     icmp_error(), ipfr_fastroute();
+extern kmutex_t        ipf_mutex, ipl_mutex;
 # else
-# define       FR_SCANLIST(p, ip, fi, m)       fr_scanlist(p, ip, fi, m)
+extern void    ipfr_fastroute __P((struct mbuf *, fr_info_t *, frdest_t *));
 # endif
 extern int     ipl_unreach;
+extern int     ipllog __P((u_int, ip_t *, register fr_info_t *,
+                           struct mbuf *));
 #endif
 
 #if SOLARIS
-# define       IPLLOG(fl, ip, fi, m)           ipllog(fl, ip, fi)
 # define       SEND_RESET(ip, if, q)           send_reset(ip, qif, q)
 # define       ICMP_ERROR(b, ip, t, c, if, src) \
                        icmp_error(b, ip, t, c, if, src)
 #else
-# define       IPLLOG(fl, ip, fi, m)           ipllog(fl, ip, fi, m)
 # define       SEND_RESET(ip, if, q)           send_reset( \
                                                    (struct tcpiphdr *)ip)
 # if BSD < 199103
@@ -112,14 +109,10 @@ struct    frentry *ipfilter[2][2] = { { NULL, NULL }, { NULL, NULL } },
 int    fr_flags = 0, fr_active = 0;
 
 fr_info_t      frcache[2];
+
 void   fr_makefrip __P((int, ip_t *, fr_info_t *));
 int    fr_tcpudpchk __P((frentry_t *, fr_info_t *));
-#if (defined(_KERNEL) || defined(KERNEL)) && !SOLARIS
-int    fr_scanlist __P((int, ip_t *, fr_info_t *, void *));
-#else
-int    fr_scanlist __P((int, ip_t *, fr_info_t *));
-#endif
+int    fr_scanlist __P((int, ip_t *, fr_info_t *, void *m));
 
 /*
  * bit values for identifying presence of individual IP options
@@ -168,9 +161,9 @@ struct      optlist secopt[8] = {
  */
 void
 fr_makefrip(hlen, ip, fin)
-       int hlen;
-       ip_t *ip;
-       fr_info_t *fin;
+     int hlen;
+     ip_t *ip;
+     fr_info_t *fin;
 {
        struct optlist *op;
        tcphdr_t *tcp;
@@ -288,8 +281,8 @@ getports:
  */
 int
 fr_tcpudpchk(fr, fin)
-       frentry_t *fr;
-       fr_info_t *fin;
+     frentry_t *fr;
+     fr_info_t *fin;
 {
        register u_short po, tup;
        register char i;
@@ -381,21 +374,18 @@ fr_tcpudpchk(fr, fin)
  * kernel sauce.
  */
 int
-fr_scanlist(pass, ip, fin
-#if (defined(_KERNEL) || defined(KERNEL)) && !SOLARIS
-    , m)
-       void *m;
-#else
-    )
-#endif
-       int pass;
-       ip_t *ip;
-       register fr_info_t *fin;
+fr_scanlist(pass, ip, fin, m)
+     int pass;
+     ip_t *ip;
+     register fr_info_t *fin;
+     void *m;
 {
        register struct frentry *fr;
        register fr_ip_t *fi = &fin->fin_fi;
        int rulen, portcmp = 0, off;
 
+       fr = fin->fin_fr;
+       fin->fin_fr = NULL;
        fin->fin_rule = 0;
        off = ip->ip_off & 0x1fff;
        pass |= (fi->fi_fl << 20);
@@ -403,7 +393,7 @@ fr_scanlist(pass, ip, fin
        if ((fi->fi_fl & FI_TCPUDP) && (fin->fin_dlen > 3) && !off)
                portcmp = 1;
 
-       for (rulen = 0, fr = fin->fin_fr; fr; fr = fr->fr_next, rulen++) {
+       for (rulen = 0; fr; fr = fr->fr_next, rulen++) {
                /*
                 * In all checks below, a null (zero) value in the
                 * filter struture is taken to mean a wildcard.
@@ -456,7 +446,8 @@ fr_scanlist(pass, ip, fin
                        if (portcmp) {
                                if (!fr_tcpudpchk(fr, fin))
                                        continue;
-                       } else if (fr->fr_dcmp || fr->fr_scmp)
+                       } else if (fr->fr_dcmp || fr->fr_scmp || fr->fr_tcpf ||
+                                  fr->fr_tcpfm)
                                continue;
                } else if (fi->fi_p == IPPROTO_ICMP) {
                        if (!off && (fin->fin_dlen > 1)) {
@@ -467,19 +458,19 @@ fr_scanlist(pass, ip, fin
                                                 fr->fr_icmpm, fr->fr_icmp));
                                        continue;
                                }
-                       } else if (fr->fr_icmpm || fr->fr_tcpfm)
+                       } else if (fr->fr_icmpm || fr->fr_icmp)
                                continue;
                }
                FR_VERBOSE(("*"));
-                /*
-                 * Just log this packet...
-                 */
+               /*
+                * Just log this packet...
+                */
                pass = fr->fr_flags;
                if ((pass & FR_CALLNOW) && fr->fr_func)
                        pass = (*fr->fr_func)(pass, ip, fin);
 #ifdef  IPFILTER_LOG
                if ((pass & FR_LOGMASK) == FR_LOG) {
-                       if (!IPLLOG(fr->fr_flags, ip, fin, m))
+                       if (!ipllog(fr->fr_flags, ip, fin, m))
                                frstats[fin->fin_out].fr_skip++;
                        frstats[fin->fin_out].fr_pkl++;
                }
@@ -490,28 +481,28 @@ fr_scanlist(pass, ip, fin
                        fr->fr_bytes += ip->ip_len;
                else
                        fin->fin_icode = fr->fr_icode;
+               fin->fin_rule = rulen;
+               fin->fin_fr = fr;
                if (pass & FR_QUICK)
                        break;
        }
-       fin->fin_rule = rulen;
-       fin->fin_fr = fr;
        return pass;
 }
 
 
 /*
  * frcheck - filter check
- * check using source and destination addresses/pors in a packet whether
+ * check using source and destination addresses/ports in a packet whether
  * or not to pass it on or not.
  */
 int
 fr_check(ip, hlen, ifp, out
 #ifdef _KERNEL
 # if SOLARIS
-    , qif, q, mb)
+    , qif, q, mp)
        qif_t *qif;
        queue_t *q;
-       mblk_t *mb;
+       mblk_t **mp;
 # else
     , mp)
        struct mbuf **mp;
@@ -519,18 +510,18 @@ fr_check(ip, hlen, ifp, out
 #else
     )
 #endif
-       ip_t *ip;
-       int hlen;
-       struct ifnet *ifp;
-       int out;
+     ip_t *ip;
+     int hlen;
+     struct ifnet *ifp;
+     int out;
 {
        /*
         * The above really sucks, but short of writing a diff
         */
        fr_info_t frinfo, *fc;
        register fr_info_t *fin = &frinfo;
-       frentry_t *fr;
-       int pass;
+       frentry_t *fr = NULL;
+       int pass, changed;
 
 #if !defined(__SVR4) && !defined(__svr4__) && defined(_KERNEL)
        register struct mbuf *m = *mp;
@@ -541,17 +532,19 @@ fr_check(ip, hlen, ifp, out
                register int up = MIN(hlen + 8, ip->ip_len);
 
                if (up > m->m_len) {
-                       if ((*mp = m_pullup(m, up)) == 0)
+                       if ((*mp = m_pullup(m, up)) == 0) {
+                               frstats[out].fr_pull[1]++;
                                return -1;
-                       else {
+                       } else {
+                               frstats[out].fr_pull[0]++;
                                m = *mp;
                                ip = mtod(m, struct ip *);
                        }
                }
        }
 #endif
-#if SOLARIS
-       mblk_t *mc = NULL;
+#if SOLARIS && defined(_KERNEL)
+       mblk_t *mc = NULL, *m = qif->qf_m;
 #endif
        fr_makefrip(hlen, ip, fin);
        fin->fin_ifp = ifp;
@@ -559,7 +552,7 @@ fr_check(ip, hlen, ifp, out
 
        MUTEX_ENTER(&ipf_mutex);
        if (!out) {
-               ip_natin(ip, hlen, fin);
+               changed = ip_natin(ip, hlen, fin);
                if ((fin->fin_fr = ipacct[0][fr_active]) &&
                    (FR_SCANLIST(FR_NOMATCH, ip, fin, m) & FR_ACCOUNT))
                        frstats[0].fr_acct++;
@@ -567,13 +560,6 @@ fr_check(ip, hlen, ifp, out
 
        if ((pass = ipfr_knownfrag(ip, fin))) {
                if ((pass & FR_KEEPSTATE)) {
-                       /*
-                        * XXX I don't know if changing hlen to fin is right,
-                        * but at least that is typesafe.  //niklas@appli.se
-                        *
-                        * old code was:
-                        * if (fr_addstate(ip, hlen, pass) == -1)
-                        */
                        if (fr_addstate(ip, fin, pass) == -1)
                                frstats[out].fr_bads++;
                        else
@@ -611,6 +597,7 @@ fr_check(ip, hlen, ifp, out
 #endif
                        }
                }
+               fr = fin->fin_fr;
 
                if ((pass & FR_KEEPFRAG)) {
                        if (fin->fin_fi.fi_fl & FI_FRAG) {
@@ -629,8 +616,6 @@ fr_check(ip, hlen, ifp, out
                }
        }
 
-       fr = fin->fin_fr;
-
        if (fr && fr->fr_func)
                pass = (*fr->fr_func)(pass, ip, fin);
 
@@ -638,8 +623,10 @@ fr_check(ip, hlen, ifp, out
                if ((fin->fin_fr = ipacct[1][fr_active]) &&
                    (FR_SCANLIST(FR_NOMATCH, ip, fin, m) & FR_ACCOUNT))
                        frstats[1].fr_acct++;
-               ip_natout(ip, hlen, fin);
+               fin->fin_fr = NULL;
+               changed = ip_natout(ip, hlen, fin);
        }
+       fin->fin_fr = fr;
        MUTEX_EXIT(&ipf_mutex);
 
 #ifdef IPFILTER_LOG
@@ -660,8 +647,12 @@ fr_check(ip, hlen, ifp, out
                                pass |= FF_LOGBLOCK;
                        frstats[out].fr_bpkl++;
 logit:
-                       if (!IPLLOG(pass, ip, fin, m))
+                       if (!ipllog(pass, ip, fin, m)) {
                                frstats[out].fr_skip++;
+                               if ((pass & (FR_PASS|FR_LOGORBLOCK)) ==
+                                   (FR_PASS|FR_LOGORBLOCK))
+                                       pass ^= FR_PASS|FR_BLOCK;
+                       }
                }
        }
 #endif /* IPFILTER_LOG */
@@ -710,29 +701,33 @@ logit:
                frdest_t *fdp = &fr->fr_tif;
 
                if ((pass & FR_FASTROUTE) ||
-                   (fdp->fd_ifp && fdp->fd_ifp != (struct ifnet *)-1))
+                   (fdp->fd_ifp && fdp->fd_ifp != (struct ifnet *)-1)) {
                        ipfr_fastroute(m, fin, fdp);
+                       m = *mp = NULL;
+                       pass = 0;
+               }
                if (mc)
                        ipfr_fastroute(mc, fin, &fr->fr_dif);
        }
        if (!(pass & FR_PASS) && m)
                m_freem(m);
+       return (pass & FR_PASS) ? 0 : -1;
 # else
-       /*
        if (pass & FR_DUP)
-               mc = dupmsg(mb);
+               mc = dupmsg(m);
        if (fr) {
                frdest_t *fdp = &fr->fr_tif;
 
                if ((pass & FR_FASTROUTE) ||
-                   (fdp->fd_ifp && fdp->fd_ifp != (struct ifnet *)-1))
-                       ipfr_fastroute(mb, fin, fdp);
+                   (fdp->fd_ifp && fdp->fd_ifp != (struct ifnet *)-1)) {
+                       ipfr_fastroute(qif, ip, m, mp, fin, fdp);
+                       m = *mp = NULL;
+               }
                if (mc)
-                       ipfr_fastroute(mc, fin, &fr->fr_dif);
+                       ipfr_fastroute(qif, ip, mc, mp, fin, &fr->fr_dif);
        }
-       */
+       return (pass & FR_PASS) ? changed : -1;
 # endif
-       return (pass & FR_PASS) ? 0 : -1;
 #else
        if (pass & FR_NOMATCH)
                return 1;
@@ -743,9 +738,38 @@ logit:
 }
 
 
-#ifndef        _KERNEL
+#ifdef IPFILTER_LOG
+# if !(defined(_KERNEL))
 static void ipllog()
 {
        verbose("l");
 }
+# endif
+
+
+int fr_copytolog(buf, len)
+char *buf;
+int len;
+{
+       int     clen, tail;
+
+       tail = (iplh >= iplt) ? (iplbuf + IPLLOGSIZE - iplh) : (iplt - iplh);
+       clen = MIN(tail, len);
+       bcopy(buf, iplh, clen);
+       len -= clen;
+       tail -= clen;
+       iplh += clen;
+       buf += clen;
+       if (iplh == iplbuf + IPLLOGSIZE) {
+               iplh = iplbuf;
+               tail = iplt - iplh;
+       }
+       if (len && tail) {
+               clen = MIN(tail, len);
+               bcopy(buf, iplh, clen);
+               len -= clen;
+               iplh += clen;
+       }
+       return len;
+}
 #endif
index 142d98d..cacaf1c 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: if_ether.c,v 1.7 1996/05/22 11:48:45 deraadt Exp $    */
+/*     $OpenBSD: if_ether.c,v 1.8 1997/02/11 22:23:14 kstailey Exp $   */
 /*     $NetBSD: if_ether.c,v 1.31 1996/05/11 12:59:58 mycroft Exp $    */
 
 /*
index 2c367af..f47c090 100644 (file)
@@ -1,3 +1,4 @@
+/*     $OpenBSD: ip_fil.c,v 1.10 1997/02/11 22:23:12 kstailey Exp $    */
 /*
  * (C)opyright 1993,1994,1995 by Darren Reed.
  *
@@ -5,29 +6,21 @@
  * provided that this notice is preserved and due credit is given
  * to the original author and the contributors.
  */
-#if 0
-#ifndef        lint
+#if !defined(lint) && defined(LIBC_SCCS)
 static char    sccsid[] = "@(#)ip_fil.c        2.41 6/5/96 (C) 1993-1995 Darren Reed";
-static char    rcsid[] = "$OpenBSD: ip_fil.c,v 1.9 1997/02/05 00:53:11 kstailey Exp $";
-#endif
+static char    rcsid[] = "Id: ip_fil.c,v 2.0.1.5 1997/01/29 13:41:45 darrenr Exp ";
 #endif
 
-#ifndef        linux
-#include <sys/errno.h>
-#include <sys/types.h>
 #include <sys/param.h>
+#include <sys/errno.h>
 #include <sys/file.h>
-#if defined(__OpenBSD__)
-# include <sys/dirent.h>
-#else
-# include <sys/dir.h>
-#endif
 #include <sys/ioctl.h>
-#include <sys/systm.h>
-#include <sys/uio.h>
 #include <sys/mbuf.h>
 #include <sys/protosw.h>
 #include <sys/socket.h>
+#include <sys/syslog.h>
+#include <sys/systm.h>
+#include <sys/uio.h>
 
 #include <net/if.h>
 #ifdef sun
@@ -43,8 +36,7 @@ static        char    rcsid[] = "$OpenBSD: ip_fil.c,v 1.9 1997/02/05 00:53:11 kstailey Exp
 #include <netinet/udp.h>
 #include <netinet/tcpip.h>
 #include <netinet/ip_icmp.h>
-#include <sys/syslog.h>
-#endif
+
 #include "ip_fil_compat.h"
 #include "ip_fil.h"
 #include "ip_frag.h"
@@ -57,7 +49,7 @@ static        char    rcsid[] = "$OpenBSD: ip_fil.c,v 1.9 1997/02/05 00:53:11 kstailey Exp
 extern fr_flags, fr_active;
 extern struct  protosw inetsw[];
 extern int     (*fr_checkp) __P((ip_t *, int, struct ifnet *, int,
-    struct mbuf **));
+                                struct mbuf **));
 #if    BSD < 199306
 extern int     ipfr_slowtimer __P((void));
 static int     (*fr_saveslowtimo) __P((void));
@@ -67,26 +59,36 @@ extern      void    ipfr_slowtimer __P((void));
 static void    (*fr_saveslowtimo) __P((void));
 #endif
 
+static void    frzerostats __P((caddr_t));
+
 int    ipl_inited = 0;
 int    ipl_unreach = ICMP_UNREACH_FILTER_PROHIB;
+int    send_reset __P((struct tcpiphdr *));
 
 #ifdef IPFILTER_LOG
 # define LOGSIZE       8192
-static char    iplbuf[LOGSIZE];
-static caddr_t iplh = iplbuf, iplt = iplbuf;
+int    ipllog __P((u_int, ip_t *, register fr_info_t *, struct mbuf *));
+char   iplbuf[LOGSIZE];
+caddr_t        iplh = iplbuf, iplt = iplbuf;
 static int     iplused = 0;
 #endif /* IPFILTER_LOG */
-static int     iplbusy = 0;
 static int     (*fr_savep) __P((ip_t *, int, struct ifnet *, int,
-    struct mbuf **));
+                               struct mbuf **));
+static void    frflush __P((caddr_t));
+static int     frrequest __P((int, caddr_t, int));
 
-#if _BSDI_VERSION >= 199510
+#if _BSDI_VERSION >= 199501
 # include <sys/device.h>
 # include <sys/conf.h>
 
 int    iplioctl __P((dev_t, int, caddr_t, int, struct proc *));
-int    iplclose __P((dev_t, int, int, struct proc *));
 int    iplopen __P((dev_t, int, int, struct proc *));
+int    iplclose __P((dev_t, int, int, struct proc *));
+# ifdef IPFILTER_LOG
+int    iplread __P((dev_t, struct uio *, int));
+# else
+#  define iplread      noread
+# endif
 
 struct cfdriver iplcd = {
        NULL, "ipl", NULL, NULL, DV_DULL, 0
@@ -98,48 +100,41 @@ struct devsw iplsw = {
        nostrat, nodump, nopsize, 0,
        nostop
 };
-#else /* _BSDI_VERSION >= 199510 */
+#else /* _BSDI_VERSION >= 199501 */
 
-# ifndef linux
-#  ifdef IPFILTER_LOG
-#   if BSD >= 199306
+# ifdef IPFILTER_LOG
+#  if BSD >= 199306
 int    iplread __P((dev_t, struct uio *, int));
-#   else
-int    iplread __P((dev_t, struct uio *));
-#   endif
 #  else
-#   define iplread     noread
+int    iplread __P((dev_t, struct uio *));
 #  endif
-int    iplclose __P((dev_t, int));
-int    iplopen __P((dev_t, int));
-# endif /* linux */
+# else
+#  define iplread      noread
+# endif
 int    iplioctl __P((dev_t, int, caddr_t, int));
-
-#endif /* _BSDI_VERSION >= 199510 */
+int    iplopen __P((dev_t, int));
+int    iplclose __P((dev_t, int));
+#endif /* _BSDI_VERSION >= 199501 */
 
 int    iplattach __P((void));
 int    ipldetach __P((void));
-void   frzerostats __P((caddr_t));
-void   frflush __P((caddr_t));
-int    frrequest __P((int, caddr_t, int));
-
-#ifndef        IPFILTER_LKM
-void   iplinit __P((void));
-#endif /* !IPFILTER_LKM */
 
 #ifdef IPFILTER_LKM
 int    iplidentify __P((char *));
 
 int
 iplidentify(s)
-       char *s;
+     char *s;
 {
        if (strcmp(s, "ipl") == 0)
                return 1;
        return 0;
 }
+#else
+void   iplinit __P((void));
 #endif /* IPFILTER_LKM */
 
+void   ipfr_fastroute __P((struct mbuf *, fr_info_t *, frdest_t *));
 
 int
 iplattach()
@@ -148,11 +143,12 @@ iplattach()
 
        SPLNET(s);
        if (ipl_inited || (fr_checkp == fr_check)) {
-               printf("ipl: already initialized (%d)\n", iplbusy);
+               printf("IP Filter: already initialized\n");
                SPLX(s);
                return EBUSY;
        }
        ipl_inited = 1;
+       bzero((char *)nat_table, sizeof(nat_t *) * NAT_SIZE * 2);
        fr_savep = fr_checkp;
        fr_checkp = fr_check;
        fr_saveslowtimo = inetsw[0].pr_slowtimo;
@@ -167,14 +163,10 @@ ipldetach()
 {
        int s, i = FR_INQUE|FR_OUTQUE;
 
-       if (iplbusy > 1) {
-               printf("iplbusy: %d\n", iplbusy);
-               return EBUSY;
-       }
        SPLNET(s);
        if (!ipl_inited)
        {
-               printf("ipl: not initialized\n");
+               printf("IP Filter: not initialized\n");
                SPLX(s);
                return EBUSY;
        }
@@ -193,9 +185,9 @@ ipldetach()
 }
 
 
-void
+static void
 frzerostats(data)
-       caddr_t data;
+     caddr_t   data;
 {
        struct  friostat        fio;
 
@@ -211,13 +203,13 @@ frzerostats(data)
        fio.f_acctout[1] = ipacct[1][1];
        fio.f_active = fr_active;
        IWCOPY((caddr_t)&fio, data, sizeof(fio));
-       bzero((char *)frstats, sizeof(*frstats));
+       bzero((char *)frstats, sizeof(*frstats) * 2);
 }
 
 
-void
+static void
 frflush(data)
-       caddr_t data;
+     caddr_t data;
 {
        struct frentry *f, **fp;
        int flags = *(int *)data, flushed = 0, set = fr_active;
@@ -259,16 +251,16 @@ frflush(data)
  */
 int
 iplioctl(dev, cmd, data, mode
-#if _BSDI_VERSION >= 199510
-    , p)
+#if _BSDI_VERSION >= 199501
+   , p)
        struct proc *p;
 #else
-    )
+   )
 #endif
-       dev_t dev;
-       int cmd;
-       caddr_t data;
-       int mode;
+     dev_t dev;
+     int cmd;
+     caddr_t data;
+     int mode;
 {
        int error = 0, s, unit;
 
@@ -399,10 +391,10 @@ iplioctl(dev, cmd, data, mode
 }
 
 
-int
+static int
 frrequest(req, data, set)
-       int req, set;
-       caddr_t data;
+     int req, set;
+     caddr_t data;
 {
        register frentry_t *fp, *f, **fprev;
        register frentry_t **ftail;
@@ -511,15 +503,15 @@ frrequest(req, data, set)
  */
 int
 iplopen(dev, flags
-#if _BSDI_VERSION >= 199510
+#if _BSDI_VERSION >= 199501
     , devtype, p)
        int devtype;
        struct proc *p;
 #else
     )
 #endif
-       dev_t dev;
-       int flags;
+     dev_t dev;
+     int flags;
 {
        u_int min = minor(dev);
 
@@ -531,15 +523,15 @@ iplopen(dev, flags
 
 int
 iplclose(dev, flags
-#if _BSDI_VERSION >= 199510
+#if _BSDI_VERSION >= 199501
     , devtype, p)
        int devtype;
        struct proc *p;
 #else
     )
 #endif
-       dev_t dev;
-       int flags;
+     dev_t dev;
+     int flags;
 {
        u_int   min = minor(dev);
 
@@ -558,13 +550,13 @@ iplclose(dev, flags
 #  if BSD >= 199306
 int
 iplread(dev, uio, ioflag)
-       int ioflag;
+     int ioflag;
 #  else
 int
 iplread(dev, uio)
 #  endif
-       dev_t dev;
-       register struct uio *uio;
+     dev_t dev;
+     register struct uio *uio;
 {
        register int ret, s;
        register size_t sz, sx;
@@ -572,13 +564,10 @@ iplread(dev, uio)
 
        if (!uio->uio_resid)
                return 0;
-       iplbusy++;
        while (!iplused) {
                error = SLEEP(iplbuf, "ipl sleep");
-               if (error) {
-                       iplbusy--;
+               if (error)
                        return error;
-               }
        }
        SPLNET(s);
 
@@ -606,7 +595,6 @@ iplread(dev, uio)
                        iplh = iplt = iplbuf;
        }
        SPLX(s);
-       iplbusy--;
        return ret;
 }
 # endif /* IPFILTER_LOG */
@@ -616,13 +604,12 @@ iplread(dev, uio)
 #ifdef IPFILTER_LOG
 int
 ipllog(flags, ip, fin, m)
-       u_int flags;
-       ip_t *ip;
-       register fr_info_t *fin;
-       struct mbuf *m;
+     u_int flags;
+     ip_t *ip;
+     register fr_info_t *fin;
+     struct mbuf *m;
 {
        struct ipl_ci iplci;
-       register size_t tail = 0;
        register int len, mlen, hlen;
        struct ifnet *ifp = fin->fin_ifp;
 
@@ -646,7 +633,7 @@ ipllog(flags, ip, fin, m)
                }
        }
 
-       mlen = (flags & FR_LOGBODY) ? (MIN(m->m_len, 128) & 0xfa) : 0;
+       mlen = (flags & FR_LOGBODY) ? MIN(ip->ip_len - hlen, 128) : 0;
        len = hlen + sizeof(iplci) + mlen;
        if (iplused + len > LOGSIZE)
                return 0;
@@ -660,11 +647,11 @@ ipllog(flags, ip, fin, m)
 # endif
        iplci.flags = flags;
        iplci.hlen = (u_char)hlen;
-       iplci.plen = (flags & FR_LOGBODY) ? (u_char)mlen : 0 ;
+       iplci.plen = (u_char)mlen;
        iplci.rule = fin->fin_rule;
-# if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \
-    (defined(OpenBSD) && (OpenBSD >= 199606))
-       strcpy(iplci.ifname, ifp->if_xname);
+# if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199603)) || \
+       (defined(OpenBSD) && (OpenBSD >= 199603))
+       strncpy(iplci.ifname, ifp->if_xname, IFNAMSIZ);
 # else
        iplci.unit = (u_char)ifp->if_unit;
        if ((iplci.ifname[0] = ifp->if_name[0]))
@@ -672,56 +659,17 @@ ipllog(flags, ip, fin, m)
                        if ((iplci.ifname[2] = ifp->if_name[2]))
                                iplci.ifname[3] = ifp->if_name[3];
 # endif
-       if (iplh == iplbuf + LOGSIZE)
-               iplh = iplbuf;
-       tail = (iplh >= iplt) ? (iplbuf + LOGSIZE - iplh) : (iplt - iplh);
-
-       len = MIN(tail, sizeof(iplci));
-
-       /*
-        * check in both cases where we add stuff to the buffer to see if we
-        * are going to wrap around at the end.
-        */
-       bcopy((char *)&iplci, iplh, len);
-       iplh += len;
-       if (len < sizeof(iplci)) {
-               bcopy((char *)&iplci + len, iplbuf, sizeof(iplci) - len);
-               iplh = iplbuf + sizeof(iplci) - len;
-               tail = iplt - iplh;
-       } else
-               tail -= len;
-
-       len = MIN(tail, hlen);
-       bcopy((char *)ip, iplh, len);
-       iplh += len;
-       if (len < hlen) {
-               iplh = iplbuf;
-               bcopy((char *)ip + len, iplh, hlen - len);
-               iplh += hlen - len;
-               tail = iplt - iplh;
-       } else
-               tail -= len;
-
-       if (mlen) {
-               len = MIN(tail, mlen);
-#if BSD < 199103
-               bcopy((char *)m->m_un.mun_dat, iplh, len);
-#else
-               bcopy((char *)m->M_dat.M_databuf, iplh, len);
-#endif
-               iplh += len;
-               if (len < mlen) {
-                       iplh = iplbuf;
-#if BSD < 199103
-                       bcopy((char *)m->m_un.mun_dat + len, iplh,
-                               mlen - len);
-#else
-                       bcopy((char *)m->M_dat.M_databuf + len, iplh,
-                               mlen - len);
-#endif
-                       iplh += mlen - len;
-               }
+       /*      
+        * Guaranteed to succeed from above
+        */     
+       (void) fr_copytolog((char *)&iplci, sizeof(iplci));
+
+       for (len -= sizeof(iplci); m && len > 0; m = m->m_next, len -= hlen) {
+               hlen = MIN(len, m->m_len);
+               if (fr_copytolog(mtod(m, char *), hlen))
+                       break;
        }
+
        wakeup(iplbuf);
        return 1;
 }
@@ -733,7 +681,7 @@ ipllog(flags, ip, fin, m)
  */
 int
 send_reset(ti)
-       struct tcpiphdr *ti;
+     struct tcpiphdr *ti;
 {
        struct tcpiphdr *tp;
        struct ip *ip;
@@ -796,17 +744,18 @@ send_reset(ti)
 void
 iplinit()
 {
-       /* (void) iplattach(); */
+       (void) iplattach();
        ip_init();
+       (void) ipldetach();     /* XXX */
 }
 #endif
 
 
 void
 ipfr_fastroute(m0, fin, fdp)
-       struct mbuf *m0;
-       fr_info_t *fin;
-       frdest_t *fdp;
+     struct mbuf *m0;
+     fr_info_t *fin;
+     frdest_t *fdp;
 {
        register struct ip *ip, *mhip;
        register struct mbuf *m = m0;
@@ -826,7 +775,8 @@ ipfr_fastroute(m0, fin, fdp)
        dst = (struct sockaddr_in *)&ro->ro_dst;
        dst->sin_family = AF_INET;
        dst->sin_addr = fdp->fd_ip.s_addr ? fdp->fd_ip : ip->ip_dst;
-#if    BSD >= 199306 && !(defined(__NetBSD__) || defined(__OpenBSD__))
+#if    (BSD >= 199306) && !defined(__NetBSD__) && !defined(__bsdi__) \
+       && !defined(__OpenBSD__)
 # ifdef        RTF_CLONING
        rtalloc_ign(ro, RTF_CLONING);
 # else
@@ -852,7 +802,15 @@ ipfr_fastroute(m0, fin, fdp)
        }
        ro->ro_rt->rt_use++;
 
-       /*      
+       /*
+        * For input packets which are being "fastrouted", they won't
+        * go back through output filtering and miss their chance to get
+        * NAT'd.
+        */
+       (void) ip_natout(ip, hlen, fin);
+       if (fin->fin_out)
+               ip->ip_sum = 0;
+       /*
         * If small enough for interface, can just send directly.
         */
        if (ip->ip_len <= ifp->if_mtu) {
index 0c06696..e9ec125 100644 (file)
@@ -1,3 +1,4 @@
+/*     $OpenBSD: ip_fil.h,v 1.8 1997/02/11 22:23:16 kstailey Exp $     */
 /*
  * (C)opyright 1993-1996 by Darren Reed.
  *
@@ -6,16 +7,12 @@
  * to the original author and the contributors.
  *
  * @(#)ip_fil.h        1.35 6/5/96
- * $OpenBSD: ip_fil.h,v 1.7 1997/02/05 00:53:12 kstailey Exp $
+ * Id: ip_fil.h,v 2.0.1.2 1997/01/10 00:28:15 darrenr Exp 
  */
 
 #ifndef        __IP_FIL_H__
 #define        __IP_FIL_H__
 
-#ifdef _KERNEL
-#define IPFILTER_LOG
-#endif /* _KERNEL */
-
 #ifndef        SOLARIS
 #define        SOLARIS (defined(sun) && (defined(__svr4__) || defined(__SVR4)))
 #endif
@@ -56,9 +53,7 @@
 #define        SIOCFRENB       _IOW('r', 72, u_int)
 #define        SIOCFRSYN       _IOW('r', 73, u_int)
 #define        SIOCFRZST       _IOWR('r', 74, struct friostat)
-#define        SIOCFLNAT       _IOWR('r', 75, int)
-#define        SIOCCNATL       _IOWR('r', 76, int)
-#define        SIOCZRLST       _IOWR('r', 77, struct frentry)
+#define        SIOCZRLST       _IOWR('r', 75, struct frentry)
 #else
 #define        SIOCADAFR       _IOW(r, 60, struct frentry)
 #define        SIOCRMAFR       _IOW(r, 61, struct frentry)
 #define SIOCFRENB      _IOW(r, 72, u_int)
 #define        SIOCFRSYN       _IOW(r, 73, u_int)
 #define        SIOCFRZST       _IOWR(r, 74, struct friostat)
-#define        SIOCFLNAT       _IOWR(r, 75, int)
-#define        SIOCCNATL       _IOWR(r, 76, int)
-#define        SIOCZRLST       _IOWR(r, 77, struct frentry)
+#define        SIOCZRLST       _IOWR(r, 75, struct frentry)
 #endif
 #define        SIOCADDFR       SIOCADAFR
 #define        SIOCDELFR       SIOCRMAFR
 #define        SIOCINSFR       SIOCINAFR
 
 typedef        struct  fr_ip   {
-       u_char  fi_v:4;
-       u_char  fi_fl:4;
+       u_char  fi_v:4;         /* IP version */
+       u_char  fi_fl:4;        /* packet flags */
        u_char  fi_tos;
        u_char  fi_ttl;
        u_char  fi_p;
        struct  in_addr fi_src;
        struct  in_addr fi_dst;
-       u_long  fi_optmsk;
-       u_short fi_secmsk;
+       u_long  fi_optmsk;      /* bitmask composed from IP options */
+       u_short fi_secmsk;      /* bitmask composed from IP security options */
        u_short fi_auth;
 } fr_ip_t;
 
@@ -111,7 +104,7 @@ typedef     struct  fr_info {
        u_short fin_rule;
        u_short fin_hlen;
        u_short fin_dlen;
-       char    *fin_dp;
+       char    *fin_dp;                /* start of data past IP header */
        struct  frentry *fin_fr;
 } fr_info_t;
 
@@ -128,12 +121,12 @@ typedef   struct  frentry {
        struct  ifnet   *fr_ifa;
        u_long  fr_hits;
        u_long  fr_bytes;       /* this is only incremented when a packet */
-                               /* stops matching on this rule */
+                               /* matches this rule and it is the last match*/
        /*
         * Fields after this may not change whilst in the kernel.
         */
        struct  fr_ip   fr_ip;
-       struct  fr_ip   fr_mip;
+       struct  fr_ip   fr_mip; /* mask structure */
 
        u_char  fr_tcpfm;       /* tcp flags mask */
        u_char  fr_tcpf;        /* tcp flags */
@@ -180,18 +173,19 @@ typedef   struct  frentry {
 #define        FR_LOGB         0x00011 /* Log-fail */
 #define        FR_LOGP         0x00012 /* Log-pass */
 #define        FR_LOGBODY      0x00020 /* Log the body */
-#define        FR_LOGFIRST     0x00040
-#define        FR_RETRST       0x00080
-#define        FR_RETICMP      0x00100
+#define        FR_LOGFIRST     0x00040 /* Log the first byte if state held */
+#define        FR_RETRST       0x00080 /* Return TCP RST packet - reset connection */
+#define        FR_RETICMP      0x00100 /* Return ICMP unreachable packet */
 #define        FR_NOMATCH      0x00200
 #define        FR_ACCOUNT      0x00400 /* count packet bytes */
-#define        FR_KEEPFRAG     0x00800
-#define        FR_KEEPSTATE    0x01000
+#define        FR_KEEPFRAG     0x00800 /* keep fragment information */
+#define        FR_KEEPSTATE    0x01000 /* keep `connection' state information */
 #define        FR_INACTIVE     0x02000
-#define        FR_QUICK        0x04000
-#define        FR_FASTROUTE    0x08000
-#define        FR_CALLNOW      0x10000
-#define        FR_DUP          0x20000
+#define        FR_QUICK        0x04000 /* match & stop processing list */
+#define        FR_FASTROUTE    0x08000 /* bypass normal routing */
+#define        FR_CALLNOW      0x10000 /* call another function (fr_func) if matches */
+#define        FR_DUP          0x20000 /* duplicate packet */
+#define        FR_LOGORBLOCK   0x40000 /* block the packet if it can't be logged */
 
 #define        FR_LOGMASK      (FR_LOG|FR_LOGP|FR_LOGB)
 /*
@@ -201,6 +195,7 @@ typedef     struct  frentry {
 #define        FF_LOGBLOCK     0x200000
 #define        FF_LOGNOMATCH   0x400000
 #define        FF_LOGGING      (FF_LOGPASS|FF_LOGBLOCK|FF_LOGNOMATCH)
+#define        FF_BLOCKNONIP   0x800000        /* Solaris2 Only */
 
 #define        FR_NONE 0
 #define        FR_EQUAL 1
@@ -229,6 +224,7 @@ typedef     struct  filterstats {
        u_long  fr_bads;        /* bad attempts to allocate packet state */
        u_long  fr_ads;         /* new packet state kept */
        u_long  fr_chit;        /* cached hit */
+       u_long  fr_pull[2];     /* good and bad pullup attempts */
 #if SOLARIS
        u_long  fr_bad;         /* bad IP packets to the filter */
        u_long  fr_notip;       /* packets passed through no on ip queue */
@@ -253,20 +249,25 @@ typedef struct  optlist {
        int     ol_bit;
 } optlist_t;
 
+/*
+ * Log structure.  Each packet header logged is prepended by one of these,
+ * minimize size to make most effective use of log space which should
+ * (ideally) be a muliple of the most common log entry size.
+ */
 typedef        struct ipl_ci   {
        u_long  sec;
        u_long  usec;
        u_char  hlen;
        u_char  plen;
-       u_short rule;
-       u_long  flags:24;                       /* XXX FIXME do we care about the extra bytes? */
-#if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \
-    (defined(OpenBSD) && (OpenBSD >= 199606))
-       u_long  filler:8;                       /* XXX FIXME do we care? */
-       u_char  ifname[IFNAMSIZ];
+       u_short rule;           /* assume never more than 64k rules, total */
+#if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199603)) || \
+    (defined(OpenBSD) && (OpenBSD >= 199603))
+       u_long  flags;
+       u_char  ifname[IFNAMSIZ];       /* = 32 bytes */
 #else
+       u_long  flags:24;
        u_long  unit:8;
-       u_char  ifname[4];
+       u_char  ifname[4];      /* = 20 bytes */
 #endif
 } ipl_ci_t;
 
@@ -274,81 +275,27 @@ typedef   struct ipl_ci   {
 #ifndef        ICMP_UNREACH_FILTER_PROHIB
 #define        ICMP_UNREACH_FILTER_PROHIB      13
 #endif
-/*
- * Security Options for Intenet Protocol (IPSO) as defined in RFC 1108.
- *
- * Basic Option
- *
- * 00000001   -   (Reserved 4)
- * 00111101   -   Top Secret
- * 01011010   -   Secret
- * 10010110   -   Confidential
- * 01100110   -   (Reserved 3)
- * 11001100   -   (Reserved 2)
- * 10101011   -   Unclassified
- * 11110001   -   (Reserved 1)
- */
-#define        IPSO_CLASS_RES4         0x01
-#define        IPSO_CLASS_TOPS         0x3d
-#define        IPSO_CLASS_SECR         0x5a
-#define        IPSO_CLASS_CONF         0x96
-#define        IPSO_CLASS_RES3         0x66
-#define        IPSO_CLASS_RES2         0xcc
-#define        IPSO_CLASS_UNCL         0xab
-#define        IPSO_CLASS_RES1         0xf1
-
-#define        IPSO_AUTH_GENSER        0x80
-#define        IPSO_AUTH_ESI           0x40
-#define        IPSO_AUTH_SCI           0x20
-#define        IPSO_AUTH_NSA           0x10
-#define        IPSO_AUTH_DOE           0x08
-#define        IPSO_AUTH_UN            0x06
-#define        IPSO_AUTH_FTE           0x01
-
-/*#define      IPOPT_RR        7 */
-#define        IPOPT_ZSU       10      /* ZSU */
-#define        IPOPT_MTUP      11      /* MTUP */
-#define        IPOPT_MTUR      12      /* MTUR */
-#define        IPOPT_ENCODE    15      /* ENCODE */
-/*#define      IPOPT_TS        68 */
-#define        IPOPT_TR        82      /* TR */
-/*#define      IPOPT_SECURITY  130 */
-/*#define      IPOPT_LSRR      131 */
-#define        IPOPT_E_SEC     133     /* E-SEC */
-#define        IPOPT_CIPSO     134     /* CIPSO */
-/*#define      IPOPT_SATID     136 */
-#ifndef        IPOPT_SID
-# define       IPOPT_SID       IPOPT_SATID
-#endif
-/*#define      IPOPT_SSRR      137 */
-#define        IPOPT_ADDEXT    147     /* ADDEXT */
-#define        IPOPT_VISA      142     /* VISA */
-#define        IPOPT_IMITD     144     /* IMITD */
-#define        IPOPT_EIP       145     /* EIP */
-#define        IPOPT_FINN      205     /* FINN */
 
 #define        IPMINLEN(i, h)  ((i)->ip_len >= ((i)->ip_hl * 4 + sizeof(struct h)))
+#define        IPLLOGSIZE      8192
 
+#ifdef _KERNEL
+extern int     fr_check __P((ip_t *, int, struct ifnet *, int,
+                             struct mbuf **));
+#else
+extern int     fr_check __P((ip_t *, int, struct ifnet *, int));
+#endif
+extern int     fr_copytolog(char *, int);
 extern fr_info_t       frcache[];
+extern char    *iplh, *iplt;
+extern char    iplbuf[IPLLOGSIZE];
 
 #ifdef _KERNEL
 
 extern struct frentry *ipfilter[2][2], *ipacct[2][2];
 extern struct filterstats frstats[];
-
-#ifdef IPFILTER_LOG
-extern int     ipllog __P((u_int, ip_t *, fr_info_t *, struct mbuf *));
-#endif
-extern int     send_reset __P((struct tcpiphdr *));
-extern void    ipfr_fastroute __P((struct mbuf *, fr_info_t *, frdest_t *));
 # if   SOLARIS
-extern int     fr_check();
 extern int     ipfsync();
-# else /* SOLARIS */
-extern int     fr_check __P((ip_t *, int, struct ifnet *, int,
-    struct mbuf **));
-# endif /* SOLARIS */
-#else /* _KERNEL */
-extern int     fr_check __P((ip_t *, int, struct ifnet *, int));
+# endif
 #endif /* _KERNEL */
 #endif /* __IP_FIL_H__ */
index 68caa30..0440b5d 100644 (file)
@@ -1,3 +1,4 @@
+/*     $OpenBSD: ip_fil_compat.h,v 1.3 1997/02/11 22:23:18 kstailey Exp $      */
 /*
  * (C)opyright 1993, 1994, 1995 by Darren Reed.
  *
@@ -5,16 +6,23 @@
  * provided that this notice is preserved and due credit is given
  * to the original author and the contributors.
  *
- * @(#)ip_fil_compat.h 1.8 1/14/96
- * $OpenBSD: ip_fil_compat.h,v 1.2 1996/10/08 07:33:26 niklas Exp $
+ * @(#)ip_compat.h     1.8 1/14/96
+ * Id: ip_compat.h,v 2.0.1.4 1997/02/04 14:24:25 darrenr Exp
  */
 
-#ifndef        __IP_COMPAT_H_
-#define        __IP_COMPAT_H__
+#ifndef        __IP_FIL_COMPAT_H_
+#define        __IP_FIL_COMPAT_H__
+
+#ifdef _KERNEL                 /* XXX */
+#define IPFILTER_LOG
+#endif /* _KERNEL */
 
 #ifndef        SOLARIS
 #define        SOLARIS (defined(sun) && (defined(__svr4__) || defined(__SVR4)))
 #endif
+#if    SOLARIS
+#define        MTYPE(m)        ((m)->b_datap->db_type)
+#endif
 #define        IPMINLEN(i, h)  ((i)->ip_len >= ((i)->ip_hl * 4 + sizeof(struct h)))
 
 #ifndef        IP_OFFMASK
 #define        MAX(a,b)        (((a) > (b)) ? (a) : (b))
 #endif
 
+/*
+ * Security Options for Intenet Protocol (IPSO) as defined in RFC 1108.
+ *
+ * Basic Option
+ *
+ * 00000001   -   (Reserved 4)
+ * 00111101   -   Top Secret
+ * 01011010   -   Secret
+ * 10010110   -   Confidential
+ * 01100110   -   (Reserved 3)
+ * 11001100   -   (Reserved 2)
+ * 10101011   -   Unclassified
+ * 11110001   -   (Reserved 1)
+ */
+#define        IPSO_CLASS_RES4         0x01
+#define        IPSO_CLASS_TOPS         0x3d
+#define        IPSO_CLASS_SECR         0x5a
+#define        IPSO_CLASS_CONF         0x96
+#define        IPSO_CLASS_RES3         0x66
+#define        IPSO_CLASS_RES2         0xcc
+#define        IPSO_CLASS_UNCL         0xab
+#define        IPSO_CLASS_RES1         0xf1
+
+#define        IPSO_AUTH_GENSER        0x80
+#define        IPSO_AUTH_ESI           0x40
+#define        IPSO_AUTH_SCI           0x20
+#define        IPSO_AUTH_NSA           0x10
+#define        IPSO_AUTH_DOE           0x08
+#define        IPSO_AUTH_UN            0x06
+#define        IPSO_AUTH_FTE           0x01
+
+/*
+ * IP option #defines
+ */
+/*#define      IPOPT_RR        7 */
+#define        IPOPT_ZSU       10      /* ZSU */
+#define        IPOPT_MTUP      11      /* MTUP */
+#define        IPOPT_MTUR      12      /* MTUR */
+#define        IPOPT_ENCODE    15      /* ENCODE */
+/*#define      IPOPT_TS        68 */
+#define        IPOPT_TR        82      /* TR */
+/*#define      IPOPT_SECURITY  130 */
+/*#define      IPOPT_LSRR      131 */
+#define        IPOPT_E_SEC     133     /* E-SEC */
+#define        IPOPT_CIPSO     134     /* CIPSO */
+/*#define      IPOPT_SATID     136 */
+#ifndef        IPOPT_SID
+# define       IPOPT_SID       IPOPT_SATID
+#endif
+/*#define      IPOPT_SSRR      137 */
+#define        IPOPT_ADDEXT    147     /* ADDEXT */
+#define        IPOPT_VISA      142     /* VISA */
+#define        IPOPT_IMITD     144     /* IMITD */
+#define        IPOPT_EIP       145     /* EIP */
+#define        IPOPT_FINN      205     /* FINN */
+
+
+/*
+ * Build some macros and #defines to enable the same code to compile anywhere
+ * Well, that's the idea, anyway :-)
+ */
 #ifdef _KERNEL
 # if SOLARIS
 #  define      MUTEX_ENTER(x)  mutex_enter(x)
@@ -68,9 +137,11 @@ typedef     struct  qif     {
        queue_t *qf_out;
        void    *qf_wqinfo;
        void    *qf_rqinfo;
-       char    qf_name[8];
        int     (*qf_inp)();
        int     (*qf_outp)();
+       mblk_t  *qf_m;
+       int     qf_len;
+       char    qf_name[8];
        /*
         * in case the ILL has disappeared...
         */
@@ -85,10 +156,10 @@ typedef    struct  qif     {
 #    define    htons(x)        (x)
 #    define    htonl(x)        (x)
 #   endif
-#   define     KMALLOC(x)      kmem_alloc((x), KM_SLEEP)
+#   define     KMALLOC(x)      kmem_alloc((x), KM_NOSLEEP)
 #   define     GET_MINOR(x)    getminor(x)
 #  else
-#   define     KMALLOC(x)      new_kmem_alloc((x), KMEM_SLEEP)
+#   define     KMALLOC(x)      new_kmem_alloc((x), KMEM_NOSLEEP)
 #  endif /* __svr4__ */
 # endif /* sun && !linux */
 # ifndef       GET_MINOR
@@ -103,9 +174,18 @@ extern     vm_map_t        kmem_map;
 #  else
 #   include <vm/vm_kern.h>
 #  endif /* __FreeBSD__ */
-#  define      KMALLOC(x)      kmem_alloc(kmem_map, (x))
-#  define      KFREE(x)        kmem_free(kmem_map, (vm_offset_t)(x), \
+/*
+** #  define   KMALLOC(x)      kmem_alloc(kmem_map, (x))
+** #  define   KFREE(x)        kmem_free(kmem_map, (vm_offset_t)(x), \
                                          sizeof(*(x)))
+*/
+#  ifdef       M_PFIL
+#   define     KMALLOC(x)      malloc((x), M_PFIL, M_NOWAIT)
+#   define     KFREE(x)        FREE((x), M_PFIL)
+#  else
+#   define     KMALLOC(x)      malloc((x), M_TEMP, M_NOWAIT)
+#   define     KFREE(x)        FREE((x), M_TEMP)
+#  endif
 #  define      UIOMOVE(a,b,c,d)        uiomove(a,b,d)
 #  define      SLEEP(id, n)    tsleep((id), PPAUSE|PCATCH, n, 0)
 # endif /* BSD */
@@ -118,15 +198,17 @@ extern    vm_map_t        kmem_map;
 #  endif
 # endif
 #else
-# define       MUTEX_ENTER(x)  ;
-# define       MUTEX_EXIT(x)   ;
-# define       SPLNET(x)       ;
-# define       SPLX(x)         ;
-# define       KMALLOC(x)      malloc(x)
-# define       KFREE(x)        free(x)
-# define       GETUNIT(x)      (x)
-# define       IRCOPY(a,b,c)   bcopy((a), (b), (c))
-# define       IWCOPY(a,b,c)   bcopy((a), (b), (c))
+# ifndef       linux
+#  define      MUTEX_ENTER(x)  ;
+#  define      MUTEX_EXIT(x)   ;
+#  define      SPLNET(x)       ;
+#  define      SPLX(x)         ;
+#  define      KMALLOC(x)      malloc(x)
+#  define      KFREE(x)        free(x)
+#  define      GETUNIT(x)      (x)
+#  define      IRCOPY(a,b,c)   bcopy((a), (b), (c))
+#  define      IWCOPY(a,b,c)   bcopy((a), (b), (c))
+# endif
 #endif /* KERNEL */
 
 #ifdef linux
@@ -134,9 +216,6 @@ extern      vm_map_t        kmem_map;
 # define       ICMP_SOURCEQUENCH       ICMP_SOURCE_QUENCH
 # define       ICMP_TIMXCEED   ICMP_TIME_EXCEEDED
 # define       ICMP_PARAMPROB  ICMP_PARAMETERPROB
-# define       icmp    icmphdr
-# define       icmp_type       type
-# define       icmp_code       code
 
 # define       TH_FIN  0x01
 # define       TH_SYN  0x02
@@ -180,10 +259,61 @@ typedef   struct  {
        __u8    ip_ttl;
        __u8    ip_p;
        __u16   ip_sum;
-       __u32   ip_src;
-       __u32   ip_dst;
+       struct  in_addr ip_src;
+       struct  in_addr ip_dst;
 } ip_t;
 
+/*
+ * Structure of an icmp header.
+ */
+struct icmp {
+       u_char  icmp_type;              /* type of message, see below */
+       u_char  icmp_code;              /* type sub code */
+       u_short icmp_cksum;             /* ones complement cksum of struct */
+       union {
+               u_char ih_pptr;                 /* ICMP_PARAMPROB */
+               struct in_addr ih_gwaddr;       /* ICMP_REDIRECT */
+               struct ih_idseq {
+                       n_short icd_id;
+                       n_short icd_seq;
+               } ih_idseq;
+               int ih_void;
+       } icmp_hun;
+# define       icmp_pptr       icmp_hun.ih_pptr
+# define       icmp_gwaddr     icmp_hun.ih_gwaddr
+# define       icmp_id         icmp_hun.ih_idseq.icd_id
+# define       icmp_seq        icmp_hun.ih_idseq.icd_seq
+# define       icmp_void       icmp_hun.ih_void
+       union {
+               struct id_ts {
+                       n_time its_otime;
+                       n_time its_rtime;
+                       n_time its_ttime;
+               } id_ts;
+               struct id_ip  {
+                       ip_t idi_ip;
+                       /* options and then 64 bits of data */
+               } id_ip;
+               u_long  id_mask;
+               char    id_data[1];
+       } icmp_dun;
+# define       icmp_otime      icmp_dun.id_ts.its_otime
+# define       icmp_rtime      icmp_dun.id_ts.its_rtime
+# define       icmp_ttime      icmp_dun.id_ts.its_ttime
+# define       icmp_ip         icmp_dun.id_ip.idi_ip
+# define       icmp_mask       icmp_dun.id_mask
+# define       icmp_data       icmp_dun.id_data
+};
+
+struct ipovly {
+       caddr_t ih_next, ih_prev;       /* for protocol sequence q's */
+       u_char  ih_x1;                  /* (unused) */
+       u_char  ih_pr;                  /* protocol */
+       short   ih_len;                 /* protocol length */
+       struct  in_addr ih_src;         /* source internet address */
+       struct  in_addr ih_dst;         /* destination internet address */
+};
+
 # define       SPLX(x)         (void)
 # define       SPLNET(x)       (void)
 
@@ -210,7 +340,8 @@ typedef     struct  {
 #else
 typedef        struct  tcphdr  tcphdr_t;
 typedef        struct  udphdr  udphdr_t;
+typedef        struct  icmp    icmphdr_t;
 typedef        struct  ip      ip_t;
 #endif /* linux */
 
-#endif /* __IP_COMPAT_H__ */
+#endif /* __IP__FIL_COMPAT_H__ */
index 77cfa93..accda5e 100644 (file)
@@ -1,3 +1,4 @@
+/*     $OpenBSD: ip_frag.c,v 1.7 1997/02/11 22:23:20 kstailey Exp $    */
 /*
  * (C)opyright 1993,1994,1995 by Darren Reed.
  *
@@ -6,9 +7,9 @@
  * to the original author and the contributors.
  */
 #if 0
-#ifndef        lint
+#if !defined(lint) && defined(LIBC_SCCS)
 static char    sccsid[] = "@(#)ip_frag.c       1.11 3/24/96 (C) 1993-1995 Darren Reed";
-static char    rcsid[] = "$OpenBSD: ip_frag.c,v 1.6 1997/01/18 08:29:20 downsj Exp $";
+static char    rcsid[] = "Id: ip_frag.c,v 2.0.1.1 1997/01/09 15:14:43 darrenr Exp";
 #endif
 #endif
 
@@ -18,21 +19,16 @@ static      char    rcsid[] = "$OpenBSD: ip_frag.c,v 1.6 1997/01/18 08:29:20 downsj Exp
 #endif
 #include <sys/errno.h>
 #include <sys/types.h>
-#if defined(_KERNEL) || defined(KERNEL)
-#include <sys/systm.h>
-#endif
 #include <sys/param.h>
 #include <sys/file.h>
 #include <sys/ioctl.h>
 #include <sys/uio.h>
 #include <sys/protosw.h>
 #include <sys/socket.h>
+#ifdef _KERNEL
+# include <sys/systm.h>
+#endif
 #if !defined(__SVR4) && !defined(__svr4__)
-# if defined(__OpenBSD__)
-#  include <sys/dirent.h>
-# else
-#  include <sys/dir.h>
-# endif
 # include <sys/mbuf.h>
 #else
 # include <sys/byteorder.h>
@@ -54,7 +50,6 @@ static        char    rcsid[] = "$OpenBSD: ip_frag.c,v 1.6 1997/01/18 08:29:20 downsj Exp
 #include <netinet/udp.h>
 #include <netinet/tcpip.h>
 #include <netinet/ip_icmp.h>
-#include <sys/syslog.h>
 #include "ip_fil_compat.h"
 #include "ip_fil.h"
 #include "ip_frag.h"
@@ -64,6 +59,7 @@ static        char    rcsid[] = "$OpenBSD: ip_frag.c,v 1.6 1997/01/18 08:29:20 downsj Exp
 ipfr_t *ipfr_heads[IPFT_SIZE];
 ipfrstat_t ipfr_stats;
 u_long ipfr_inuse = 0;
+u_long fr_ipfrttl = 120;       /* 60 seconds */
 #ifdef _KERNEL
 extern int     ipfr_timer_id;
 #endif
@@ -138,7 +134,7 @@ ipfr_newfrag(ip, fin, pass)
        fr->ipfr_prev = NULL;
        ipfr_heads[idx] = fr;
        bcopy((char *)&frag.ipfr_src, (char *)&fr->ipfr_src, IPFR_CMPSZ);
-       fr->ipfr_ttl = 120;     /* 60 seconds */
+       fr->ipfr_ttl = fr_ipfrttl;
        fr->ipfr_pass = pass & ~(FR_LOGFIRST|FR_LOG);
        fr->ipfr_off = (ip->ip_off & 0x1fff) + (fin->fin_dlen >> 3);
        *fp = fr;
@@ -235,7 +231,7 @@ ipfr_unload()
        for (idx = IPFT_SIZE - 1; idx >= 0; idx--)
                for (fp = &ipfr_heads[idx]; (fr = *fp); ) {
                        *fp = fr->ipfr_next;
-                       KFREE(fp);
+                       KFREE(fr);
                }
        SPLX(s);
        MUTEX_EXIT(&ipf_frag);
@@ -249,9 +245,9 @@ ipfr_unload()
  */
 # if BSD < 199306
 int
-#else
+# else
 void
-#endif
+# endif
 ipfr_slowtimer()
 {
        ipfr_t  **fp, *fr;
@@ -273,23 +269,23 @@ ipfr_slowtimer()
                                *fp = fr->ipfr_next;
                                ipfr_stats.ifs_expire++;
                                ipfr_inuse--;
-                               KFREE(fp);
+                               KFREE(fr);
                        } else
                                fp = &fr->ipfr_next;
                }
        SPLX(s);
-#if    SOLARIS
+# if   SOLARIS
        MUTEX_EXIT(&ipf_frag);
        fr_timeoutstate();
        ip_natexpire();
        ipfr_timer_id = timeout(ipfr_slowtimer, NULL, HZ/2);
-#else
+# else
        fr_timeoutstate();
        ip_natexpire();
        ip_slowtimo();
-#endif
-# if BSD < 199306
+#  if BSD < 199306
        return 0;
+#  endif
 # endif
 }
 #endif /* defined(_KERNEL) */
index 8ee30e6..e0b108a 100644 (file)
@@ -1,3 +1,4 @@
+/*     $OpenBSD: ip_frag.h,v 1.5 1997/02/11 22:23:22 kstailey Exp $    */
 /*
  * (C)opyright 1993, 1994, 1995 by Darren Reed.
  *
@@ -6,7 +7,7 @@
  * to the original author and the contributors.
  *
  * @(#)ip_frag.h       1.5 3/24/96
- * $OpenBSD: ip_frag.h,v 1.4 1996/10/08 07:33:27 niklas Exp $
+ * Id: ip_frag.h,v 2.0.1.1 1997/01/09 15:14:43 darrenr Exp
  */
 
 #ifndef        __IP_FRAG_H_
index 8245206..80604ee 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: ip_icmp.c,v 1.5 1996/05/09 14:33:32 mickey Exp $      */
+/*     $OpenBSD: ip_icmp.c,v 1.6 1997/02/11 22:23:23 kstailey Exp $    */
 /*     $NetBSD: ip_icmp.c,v 1.19 1996/02/13 23:42:22 christos Exp $    */
 
 /*
@@ -274,6 +274,9 @@ icmp_input(m, va_alist)
                        case ICMP_UNREACH_ISOLATED:
                        case ICMP_UNREACH_HOST_PROHIB:
                        case ICMP_UNREACH_TOSHOST:
+                       case ICMP_UNREACH_FILTER_PROHIB:
+                       case ICMP_UNREACH_HOST_PRECEDENCE:
+                       case ICMP_UNREACH_PRECEDENCE_CUTOFF:
                                code = PRC_UNREACH_HOST;
                                break;
 
index a3a9165..17416db 100644 (file)
@@ -1,30 +1,18 @@
+/*     $OpenBSD: ip_nat.c,v 1.8 1997/02/11 22:23:25 kstailey Exp $     */
 /*
- * (C)opyright 1995 by Darren Reed.
+ * (C)opyright 1995-1996 by Darren Reed.
  *
  * Redistribution and use in source and binary forms are permitted
  * provided that this notice is preserved and due credit is given
  * to the original author and the contributors.
  *
- *  Added redirect stuff and a LOT of bug fixes. (mcn@EnGarde.com)
- *
- * Things still screwed:
- *  1) You can't specify a mapping to a class D address. By default, it
- *     always adds 1 to that address. As a result, when a packet comes back,
- *     the rule won't be matched. (e.g. outgoing address = 199.165.219.2,
- *     whereas the rule says outgoing address = 199.165.219.1/32. Because
- *     ADNATS always adds one, and there really isn't any provision for
- *     only using 1 address (the in_space stuff is broke), there isn't any
- *     easy solution)
- *  2) There needs to be a way to flush the NATs table completely. Either
- *     an ioctl, or an easy way of doing it from ipnat.c.
- *
- * Missing from RFC 1631: ICMP header checksum recalculations.
+ * Added redirect stuff and a LOT of bug fixes. (mcn@EnGarde.com)
  *
  */
 #if 0
-#ifndef        lint
+#if !defined(lint) && defined(LIBC_SCCS)
 static char    sccsid[] = "@(#)ip_nat.c        1.11 6/5/96 (C) 1995 Darren Reed";
-static char    rcsid[] = "$OpenBSD: ip_nat.c,v 1.7 1997/01/18 08:29:21 downsj Exp $";
+static char    rcsid[] = "Id: ip_nat.c,v 2.0.1.10 1997/02/08 06:38:49 darrenr Exp";
 #endif
 #endif
 
@@ -36,20 +24,15 @@ static      char    rcsid[] = "$OpenBSD: ip_nat.c,v 1.7 1997/01/18 08:29:21 downsj Exp $
 #include <sys/errno.h>
 #include <sys/types.h>
 #include <sys/param.h>
-#if defined(_KERNEL) || defined(KERNEL)
-#include <sys/systm.h>
-#endif
 #include <sys/file.h>
 #include <sys/ioctl.h>
 #include <sys/uio.h>
 #include <sys/protosw.h>
 #include <sys/socket.h>
+#ifdef _KERNEL
+# include <sys/systm.h>
+#endif
 #if !defined(__SVR4) && !defined(__svr4__)
-# if defined(__OpenBSD__)
-#  include <sys/dirent.h>
-# else
-#  include <sys/dir.h>
-# endif
 # include <sys/mbuf.h>
 #else
 # include <sys/byteorder.h>
@@ -66,25 +49,34 @@ static      char    rcsid[] = "$OpenBSD: ip_nat.c,v 1.7 1997/01/18 08:29:21 downsj Exp $
 #include <netinet/in.h>
 #include <netinet/in_systm.h>
 #include <netinet/ip.h>
+
+#ifdef RFC1825
+#include <vpn/md5.h>
+#include <vpn/ipsec.h>
+extern struct ifnet vpnif;
+#endif
+
 #include <netinet/ip_var.h>
 #include <netinet/tcp.h>
 #include <netinet/udp.h>
 #include <netinet/tcpip.h>
 #include <netinet/ip_icmp.h>
-#include <sys/syslog.h>
 #include "ip_fil_compat.h"
 #include "ip_fil.h"
 #include "ip_nat.h"
+#include "ip_state.h"
 #ifndef        MIN
 #define        MIN(a,b)        (((a)<(b))?(a):(b))
 #endif
 
-nat_t  *nat_table[2][NAT_SIZE];
+nat_t  *nat_table[2][NAT_SIZE], *nat_instances = NULL;
 ipnat_t        *nat_list = NULL;
-u_long nat_inuse = 0;
+u_long nat_inuse = 0,
+       fr_defnatage = 1200;
 natstat_t nat_stats;
 #if    SOLARIS
 # ifndef       _KERNEL
+#define        bzero(a,b)      memset(a,0,b)
 #define        bcmp(a,b,c)     memcpy(a,b,c)
 #define        bcopy(a,b,c)    memmove(b,a,c)
 # else
@@ -92,9 +84,57 @@ extern       kmutex_t        ipf_nat;
 # endif
 #endif
 
-int    flush_nattable __P((void));
-int    clear_natlist __P((void));
-nat_t  *nat_new __P((ipnat_t *, ip_t *, int, u_short, int));
+static int     flush_nattable __P((void)), clear_natlist __P((void));
+static void    nattable_sync __P((void)), nat_delete __P((struct nat *));
+void           fix_incksum __P((u_short *, u_long));
+void           fix_outcksum __P((u_short *, u_long));
+nat_t          *nat_new __P((ipnat_t *, ip_t *, fr_info_t *, u_short, int));
+nat_t          *nat_lookupmapip __P((register int, struct in_addr, u_short,
+                       struct in_addr, u_short));
+
+void
+fix_outcksum(sp, n)
+       u_short *sp;
+       u_long n;
+{
+       register u_short sumshort;
+       register u_long sum1;
+
+#ifdef sparc
+       sum1 = (~(*sp)) & 0xffff;
+#else
+       sum1 = (~ntohs(*sp)) & 0xffff;
+#endif
+       sum1 += (n);
+       sum1 = (sum1 >> 16) + (sum1 & 0xffff);
+       /* Again */
+       sum1 = (sum1 >> 16) + (sum1 & 0xffff);
+       sumshort = ~(u_short)sum1;
+       *(sp) = htons(sumshort);
+}
+
+
+void
+fix_incksum(sp, n)
+       u_short *sp;
+       u_long n;
+{
+       register u_short sumshort;
+       register u_long sum1;
+
+#ifdef sparc
+       sum1 = (~(*sp)) & 0xffff;
+#else
+       sum1 = (~ntohs(*sp)) & 0xffff;
+#endif
+       sum1 += ~(n) & 0xffff;
+       sum1 = (sum1 >> 16) + (sum1 & 0xffff);
+       /* Again */
+       sum1 = (sum1 >> 16) + (sum1 & 0xffff);
+       sumshort = ~(u_short)sum1;
+       *(sp) = htons(sumshort);
+}
+
 
 /*
  * How the NAT is organised and works.
@@ -125,7 +165,7 @@ nat_ioctl(data, cmd, mode)
        caddr_t data;
        int cmd, mode;
 {
-       register ipnat_t *nat, *n, **np;
+       register ipnat_t *nat, *n = NULL, **np = NULL;
        ipnat_t natd;
        int error = 0, ret;
 
@@ -134,10 +174,10 @@ nat_ioctl(data, cmd, mode)
         */
        MUTEX_ENTER(&ipf_nat);
        if ((cmd == SIOCADNAT) || (cmd == SIOCRMNAT)) {
-               IRCOPY(data, &natd, sizeof(natd));
+               IRCOPY(data, (char *)&natd, sizeof(natd));
                nat = &natd;
                for (np = &nat_list; (n = *np); np = &n->in_next)
-                       if (!bcmp((char *)&nat->in_port, (char *)&n->in_port,
+                       if (!bcmp((char *)&nat->in_flags, (char *)&n->in_flags,
                                        IPN_CMPSIZ))
                                break;
        }
@@ -160,14 +200,25 @@ nat_ioctl(data, cmd, mode)
                IRCOPY((char *)data, (char *)n, sizeof(*n));
                n->in_ifp = (void *)GETUNIT(n->in_ifname);
                n->in_next = *np;
+               n->in_use = 0;
                n->in_space = ~(0xffffffff & ntohl(n->in_outmsk));
-               n->in_space -= 2; /* lose 2: broadcast + network address */
-               if (n->in_inmsk != 0xffffffff)
+               if (n->in_space) /* lose 2: broadcast + network address */
+                       n->in_space -= 2;
+               else
+                       n->in_space = 1;        /* single IP# mapping */
+               if (n->in_outmsk != 0xffffffff)
                        n->in_nip = ntohl(n->in_outip) + 1;
                else
                        n->in_nip = ntohl(n->in_outip);
-               if (n->in_redir == NAT_MAP)
+               if (n->in_redir == NAT_MAP) {
                        n->in_pnext = ntohs(n->in_pmin);
+                       /*
+                        * Multiply by the number of ports made available.
+                        */
+                       if (ntohs(n->in_pmax) > ntohs(n->in_pmin))
+                               n->in_space *= (ntohs(n->in_pmax) -
+                                               ntohs(n->in_pmin));
+               }
                /* Otherwise, these fields are preset */
                *np = n;
                break;
@@ -181,10 +232,13 @@ nat_ioctl(data, cmd, mode)
                        break;
                }
                *np = n->in_next;
+
                KFREE(n);
+               nattable_sync();
                break;
        case SIOCGNATS :
-               nat_stats.ns_table = (nat_t ***)nat_table;
+               nat_stats.ns_table[0] = nat_table[0];
+               nat_stats.ns_table[1] = nat_table[1];
                nat_stats.ns_list = nat_list;
                nat_stats.ns_inuse = nat_inuse;
                IWCOPY((char *)&nat_stats, (char *)data, sizeof(nat_stats));
@@ -192,14 +246,12 @@ nat_ioctl(data, cmd, mode)
        case SIOCGNATL :
            {
                natlookup_t nl;
-               nat_t   *na;
 
                IRCOPY((char *)data, (char *)&nl, sizeof(nl));
-               if ((na = nat_lookupredir(&nl))) {
-                       nl.nl_inip = na->nat_outip;
-                       nl.nl_inport = na->nat_outport;
+
+               if (nat_lookupredir(&nl))
                        IWCOPY((char *)&nl, (char *)data, sizeof(nl));
-               else
+               else
                        error = ESRCH;
                break;
            }
@@ -225,36 +277,90 @@ nat_ioctl(data, cmd, mode)
 }
 
 
+static void
+nat_delete(natd)
+       struct nat *natd;
+{
+       register struct nat **natp, *nat;
+
+       for (natp = natd->nat_hstart[0]; (nat = *natp);
+            natp = &nat->nat_hnext[0])
+               if (nat == natd) {
+                       *natp = nat->nat_hnext[0];
+                       break;
+               }
+
+       for (natp = natd->nat_hstart[1]; (nat = *natp);
+            natp = &nat->nat_hnext[1])
+               if (nat == natd) {
+                       *natp = nat->nat_hnext[1];
+                       break;
+               }
+
+       if (natd->nat_ptr) {
+               natd->nat_ptr->in_space++;
+               natd->nat_ptr->in_use--;
+       }
+       KFREE(natd);
+       nat_inuse--;
+}
+
+
 /*
  * flush_nattable - clear the NAT table of all mapping entries.
  */
-int
+static int
 flush_nattable()
 {
-       nat_t *nat, **natp;
-       int i, j = 0;
+       register nat_t *nat, **natp;
+       register int j = 0;
+  
+       /*
+        * Everything will be deleted, so lets just make it the deletions
+        * quicker.
+        */
+       bzero((char *)nat_table[0], sizeof(nat_table[0]));
+       bzero((char *)nat_table[1], sizeof(nat_table[1]));
 
-       for (natp = &nat_table[0][0], i = NAT_SIZE - 1; i >= 0; i--, natp++)
-               while ((nat = *natp)) {
-                       *natp = nat->nat_next;
-                       KFREE((caddr_t)nat);
-                       j++;
-               }
+       for (natp = &nat_instances; (nat = *natp); ) {
+               *natp = nat->nat_next;
+               nat_delete(nat);
+               j++;
+       }
 
-       for (natp = &nat_table[1][0], i = NAT_SIZE - 1; i >= 0; i--, natp++)
-               while ((nat = *natp)) {
-                       *natp = nat->nat_next;
-                       KFREE((caddr_t)nat);
-                       j++;
-               }
        return j;
 }
 
 
+/*
+ * I know this is O(N*M), but it can't be avoided.
+ */
+static void
+nattable_sync()
+{
+       register nat_t *nat;
+       register ipnat_t *np;
+       int i;
+
+       for (i = NAT_SIZE - 1; i >= 0; i--)
+               for (nat = nat_instances; nat; nat = nat->nat_next) {
+                       for (np = nat_list; np; np = np->in_next)
+                               if (nat->nat_ptr == np)
+                                       break;
+                       /*
+                        * XXX - is it better to remove this if ? works the
+                        * same if it is just "nat->nat_ptr = np".
+                        */
+                       if (!np)
+                               nat->nat_ptr = NULL;
+               }
+}
+
+
 /*
  * clear_natlist - delete all entries in the active NAT mapping list.
  */
-int
+static int
 clear_natlist()
 {
        register ipnat_t *n, **np;
@@ -264,6 +370,8 @@ clear_natlist()
                *np = n->in_next;
                KFREE(n);
        }
+
+       nattable_sync();
        return i;
 }
 
@@ -272,21 +380,23 @@ clear_natlist()
  * Create a new NAT table entry.
  */
 nat_t *
-nat_new(np, ip, hlen, flags, direction)
+nat_new(np, ip, fin, flags, direction)
        ipnat_t *np;
        ip_t *ip;
-       int hlen;
+       fr_info_t *fin;
        u_short flags;
        int direction;
 {
        register u_long sum1, sum2, sumd;
        u_short port = 0, sport = 0, dport = 0, nport = 0;
        struct in_addr in;
-       tcphdr_t *tcp;
+       tcphdr_t *tcp = NULL;
        nat_t *nat, **natp;
+       u_short nflags;
 
-       if (flags) {
-               tcp = (tcphdr_t *)((char *)ip + hlen);
+       nflags = flags & np->in_flags;
+       if (flags & IPN_TCPUDP) {
+               tcp = (tcphdr_t *)fin->fin_dp;
                sport = tcp->th_sport;
                dport = tcp->th_dport;
        }
@@ -295,6 +405,8 @@ nat_new(np, ip, hlen, flags, direction)
        if (!(nat = (nat_t *)KMALLOC(sizeof(*nat))))
                return NULL;
 
+       bzero((char *)nat, sizeof(*nat));
+
        /*
         * Search the current table for a match.
         */
@@ -304,8 +416,9 @@ nat_new(np, ip, hlen, flags, direction)
                 * record, then create a new port
                 */
                do {
+                       port = 0;
                        in.s_addr = np->in_nip;
-                       if (np->in_flags & IPN_TCPUDP) {
+                       if (nflags & IPN_TCPUDP) {
                                port = htons(np->in_pnext++);
                                if (np->in_pnext >= ntohs(np->in_pmax)) {
                                        np->in_pnext = ntohs(np->in_pmin);
@@ -313,46 +426,32 @@ nat_new(np, ip, hlen, flags, direction)
                                        if (np->in_outmsk != 0xffffffff)
                                                np->in_nip++;
                                }
-                       } else {
+                       } else if (np->in_outmsk != 0xffffffff) {
                                np->in_space--;
-                               if (np->in_outmsk != 0xffffffff)
-                                       np->in_nip++;
+                               np->in_nip++;
                        }
+
+                       if (!port && (flags & IPN_TCPUDP))
+                               port = sport;
                        if ((np->in_nip & ntohl(np->in_outmsk)) >
-                                       ntohl(np->in_outip))
+                           ntohl(np->in_outip))
                                np->in_nip = ntohl(np->in_outip) + 1;
-               } while (nat_lookupinip(in, sport));
+               } while (nat_inlookup(flags, ip->ip_dst, dport, in, port));
 
                /* Setup the NAT table */
-               nat->nat_use = 0;
                nat->nat_inip = ip->ip_src;
                nat->nat_outip.s_addr = htonl(in.s_addr);
+               nat->nat_oip = ip->ip_dst;
 
                sum1 = (ntohl(ip->ip_src.s_addr) & 0xffff) +
                        (ntohl(ip->ip_src.s_addr) >> 16) + ntohs(sport);
 
-               /* Do it twice */
-               sum1 = (sum1 & 0xffff) + (sum1 >> 16);
-               sum1 = (sum1 & 0xffff) + (sum1 >> 16);
-
                sum2 = (in.s_addr & 0xffff) + (in.s_addr >> 16) + ntohs(port);
 
-               /* Do it twice */
-               sum2 = (sum2 & 0xffff) + (sum2 >> 16);
-               sum2 = (sum2 & 0xffff) + (sum2 >> 16);
-
-               if (sum1 > sum2)
-                       sum2--; /* Because ~1 == -2, We really need ~1 == -1 */
-               sumd = sum2 - sum1;
-               sumd = (sumd & 0xffff) + (sumd >> 16);
-               nat->nat_sumd = (sumd & 0xffff) + (sumd >> 16);
-
-               if (sport) {
+               if (flags & IPN_TCPUDP) {
                        nat->nat_inport = sport;
                        nat->nat_outport = port;
-               } else {
-                       nat->nat_inport = 0;
-                       nat->nat_outport = 0;
+                       nat->nat_oport = dport;
                }
        } else {
 
@@ -363,9 +462,9 @@ nat_new(np, ip, hlen, flags, direction)
                 * internal port.
                 */
                in.s_addr = ntohl(np->in_inip);
-               nport = np->in_pnext;
+               if (!(nport = np->in_pnext))
+                       nport = dport;
 
-               nat->nat_use = 0;
                nat->nat_inip.s_addr = htonl(in.s_addr);
                nat->nat_outip = ip->ip_dst;
                nat->nat_oip = ip->ip_src;
@@ -373,51 +472,75 @@ nat_new(np, ip, hlen, flags, direction)
                sum1 = (ntohl(ip->ip_dst.s_addr) & 0xffff) +
                        (ntohl(ip->ip_dst.s_addr) >> 16) + ntohs(dport);
 
+               sum2 = (in.s_addr & 0xffff) + (in.s_addr >> 16) + ntohs(nport);
+
+               if (flags & IPN_TCPUDP) {
+                       nat->nat_inport = nport;
+                       nat->nat_outport = dport;
+                       nat->nat_oport = sport;
+               }
+       }
+
+       /* Do it twice */
+       sum1 = (sum1 & 0xffff) + (sum1 >> 16);
+       sum1 = (sum1 & 0xffff) + (sum1 >> 16);
+
+       /* Do it twice */
+       sum2 = (sum2 & 0xffff) + (sum2 >> 16);
+       sum2 = (sum2 & 0xffff) + (sum2 >> 16);
+
+       if (sum1 > sum2)
+               sum2--; /* Because ~1 == -2, We really need ~1 == -1 */
+       sumd = sum2 - sum1;
+       sumd = (sumd & 0xffff) + (sumd >> 16);
+       nat->nat_sumd = (sumd & 0xffff) + (sumd >> 16);
+
+       if ((flags & IPN_TCPUDP) && ((sport != port) || (dport != nport))) {
+               if (direction == NAT_OUTBOUND)
+                       sum1 = (ntohl(ip->ip_src.s_addr) & 0xffff) +
+                               (ntohl(ip->ip_src.s_addr) >> 16);
+               else
+                       sum1 = (ntohl(ip->ip_dst.s_addr) & 0xffff) +
+                               (ntohl(ip->ip_dst.s_addr) >> 16);
+
+               sum2 = (in.s_addr & 0xffff) + (in.s_addr >> 16);
+
                /* Do it twice */
                sum1 = (sum1 & 0xffff) + (sum1 >> 16);
                sum1 = (sum1 & 0xffff) + (sum1 >> 16);
 
-               sum2 = (in.s_addr & 0xffff) + (in.s_addr >> 16) + ntohs(nport);
-
                /* Do it twice */
                sum2 = (sum2 & 0xffff) + (sum2 >> 16);
                sum2 = (sum2 & 0xffff) + (sum2 >> 16);
 
-               if (sum2 > sum1)
-                       sum1--; /* Because ~1 == -2, We really need ~1 == -1 */
-               sumd = (sum1 - sum2);
+               if (sum1 > sum2)
+                       sum2--; /* Because ~1 == -2, We really need ~1 == -1 */
+               sumd = sum2 - sum1;
                sumd = (sumd & 0xffff) + (sumd >> 16);
-               nat->nat_sumd = (sumd & 0xffff) + (sumd >> 16);
-
-               if (dport) {
-                       nat->nat_inport = nport;
-                       nat->nat_outport = dport;
-                       nat->nat_oport = sport;
-               } else {
-                       nat->nat_inport = 0;
-                       nat->nat_outport = 0;
-               }
-       }
+               nat->nat_ipsumd = (sumd & 0xffff) + (sumd >> 16);
+       } else
+               nat->nat_ipsumd = nat->nat_sumd;
 
        in.s_addr = htonl(in.s_addr);
+       nat->nat_next = nat_instances;
+       nat_instances = nat;
        natp = &nat_table[0][nat->nat_inip.s_addr % NAT_SIZE];
-       nat->nat_next = *natp;
+       nat->nat_hstart[0] = natp;
+       nat->nat_hnext[0] = *natp;
        *natp = nat;
-       nat->nat_use++;
        natp = &nat_table[1][nat->nat_outip.s_addr % NAT_SIZE];
-       nat->nat_next = *natp;
+       nat->nat_hstart[1] = natp;
+       nat->nat_hnext[1] = *natp;
        *natp = nat;
-       nat->nat_use++;
-       if (direction == NAT_REDIRECT) {
-               ip->ip_src = in;
-               if (flags)
+       nat->nat_ptr = np;
+       np->in_use++;
+       if (direction == NAT_OUTBOUND) {
+               if (flags & IPN_TCPUDP)
                        tcp->th_sport = htons(port);
        } else {
-               ip->ip_dst = in;
-               if (flags)
+               if (flags & IPN_TCPUDP)
                        tcp->th_dport = htons(nport);
        }
-
        nat_stats.ns_added++;
        nat_inuse++;
        return nat;
@@ -428,76 +551,113 @@ nat_new(np, ip, hlen, flags, direction)
  * NB: these lookups don't lock access to the list, it assume it has already
  * been done!
  */
+/*
+ * Lookup a nat entry based on the mapped destination ip address/port and
+ * real source address/port.  We use this lookup when receiving a packet,
+ * we're looking for a table entry, based on the destination address.
+ * NOTE: THE PACKET BEING CHECKED (IF FOUND) HAS A MAPPING ALREADY.
+ */
 nat_t *
-nat_lookupredir(np)
-       natlookup_t *np;
+nat_inlookup(flags, src, sport, mapdst, mapdport)
+       register int flags;
+       struct in_addr src, mapdst;
+       u_short sport, mapdport;
 {
-       nat_t *nat;
+       register nat_t *nat;
 
-       nat = nat_table[0][np->nl_inip.s_addr % NAT_SIZE];
-       for (; nat; nat = nat->nat_next)
-               if ((nat->nat_inip.s_addr == np->nl_inip.s_addr) &&
-                   (nat->nat_oip.s_addr == np->nl_outip.s_addr) &&
-                   (np->nl_inport == nat->nat_inport) &&
-                   (np->nl_outport == nat->nat_oport))
+       flags &= IPN_TCPUDP;
+
+       nat = nat_table[1][mapdst.s_addr % NAT_SIZE];
+       for (; nat; nat = nat->nat_hnext[1])
+               if (nat->nat_oip.s_addr == src.s_addr &&
+                   nat->nat_outip.s_addr == mapdst.s_addr &&
+                   (!flags || (nat->nat_oport == sport &&
+                    nat->nat_outport == mapdport)))
                        return nat;
        return NULL;
 }
 
 
+/*
+ * Lookup a nat entry based on the source 'real' ip address/port and
+ * destination address/port.  We use this lookup when sending a packet out,
+ * we're looking for a table entry, based on the source address.
+ * NOTE: THE PACKET BEING CHECKED (IF FOUND) HAS A MAPPING ALREADY.
+ */
 nat_t *
-nat_lookupinip(ipaddr, sport)
-       struct in_addr ipaddr;
-       u_short sport;
+nat_outlookup(flags, src, sport, dst, dport)
+       register int flags;
+       struct in_addr src, dst;
+       u_short sport, dport;
 {
-       nat_t *nat;
+       register nat_t *nat;
 
-       nat = nat_table[0][ipaddr.s_addr % NAT_SIZE];
+       flags &= IPN_TCPUDP;
 
-       for (; nat; nat = nat->nat_next)
-               if (nat->nat_inip.s_addr == ipaddr.s_addr) {
-                       if (nat->nat_inport && (sport != nat->nat_inport))
-                               continue;
+       nat = nat_table[0][src.s_addr % NAT_SIZE];
+       for (; nat; nat = nat->nat_hnext[0])
+               if (nat->nat_inip.s_addr == src.s_addr &&
+                   nat->nat_oip.s_addr == dst.s_addr &&
+                   (!flags || (nat->nat_inport == sport &&
+                    nat->nat_oport == dport)))
                        return nat;
-               }
        return NULL;
 }
 
 
+/*
+ * Lookup a nat entry based on the mapped source ip address/port and
+ * real destination address/port.  We use this lookup when sending a packet
+ * out, we're looking for a table entry, based on the source address.
+ */
 nat_t *
-nat_lookupoutip(np, ip, tcp)
-       register ipnat_t *np;
-       ip_t *ip;
-       tcphdr_t *tcp;
+nat_lookupmapip(flags, mapsrc, mapsport, dst, dport)
+       register int flags;
+       struct in_addr mapsrc, dst;
+       u_short mapsport, dport;
 {
-       struct in_addr ipaddr;
-       u_short port = tcp->th_dport;
-       nat_t *nat;
+       register nat_t *nat;
 
-       ipaddr.s_addr = ip->ip_dst.s_addr;
-       nat = nat_table[1][ipaddr.s_addr % NAT_SIZE];
+       flags &= IPN_TCPUDP;
 
-       if (np->in_redir == NAT_MAP) {
-               for (; nat; nat = nat->nat_next)
-                       if (nat->nat_outip.s_addr == ipaddr.s_addr &&
-                           (!nat->nat_outport || (port == nat->nat_outport)))
-                               return nat;
-       } else
-               for (; nat; nat = nat->nat_next)
-                       if (nat->nat_outip.s_addr == ipaddr.s_addr &&
-                           nat->nat_oip.s_addr == ip->ip_src.s_addr &&
-                           port == nat->nat_outport &&
-                           tcp->th_sport == nat->nat_oport)
-                               return nat;
+       nat = nat_table[1][mapsrc.s_addr % NAT_SIZE];
+       for (; nat; nat = nat->nat_hnext[0])
+               if (nat->nat_outip.s_addr == mapsrc.s_addr &&
+                   nat->nat_oip.s_addr == dst.s_addr &&
+                   (!flags || (nat->nat_outport == mapsport &&
+                    nat->nat_oport == dport)))
+                       return nat;
        return NULL;
 }
 
 
+/*
+ * Lookup the NAT tables to search for a matching redirect
+ */
+nat_t *
+nat_lookupredir(np)
+       register natlookup_t *np;
+{
+       nat_t *nat;
+
+       /*
+        * If nl_inip is non null, this is a lookup based on the real
+        * ip address. Else, we use the fake.
+        */
+       if ((nat = nat_outlookup(IPN_TCPUDP, np->nl_inip, np->nl_inport,
+                                np->nl_outip, np->nl_outport))) {
+               np->nl_inip = nat->nat_outip;
+               np->nl_inport = nat->nat_outport;
+       }
+       return nat;
+}
+
+
 /*
  * Packets going out on the external interface go through this.
  * Here, the source address requires alteration, if anything.
  */
-void
+int
 ip_natout(ip, hlen, fin)
        ip_t *ip;
        int hlen;
@@ -505,21 +665,28 @@ ip_natout(ip, hlen, fin)
 {
        register ipnat_t *np;
        register u_long ipa;
-       register u_long sum1;
-       tcphdr_t *tcp;
+       tcphdr_t *tcp = NULL;
        nat_t *nat;
-       u_short nflags = 0, sport = 0;
-       struct ifnet *ifp = fin->fin_ifp;
+       u_short nflags = 0, sport = 0, dport = 0, *csump = NULL;
+       struct ifnet *ifp;
+       frentry_t *fr;
+
+       if ((fr = fin->fin_fr) && !(fr->fr_flags & FR_DUP) &&
+           fr->fr_tif.fd_ifp && fr->fr_tif.fd_ifp != (void *)-1)
+               ifp = fr->fr_tif.fd_ifp;
+       else
+               ifp = fin->fin_ifp;
 
        if (!(ip->ip_off & 0x1fff) && !(fin->fin_fi.fi_fl & FI_SHORT)) {
                if (ip->ip_p == IPPROTO_TCP)
                        nflags = IPN_TCP;
                else if (ip->ip_p == IPPROTO_UDP)
                        nflags = IPN_UDP;
-       }
-       if (nflags) {
-               tcp = (tcphdr_t *)fin->fin_dp;
-               sport = tcp->th_sport;
+               if (nflags) {
+                       tcp = (tcphdr_t *)fin->fin_dp;
+                       sport = tcp->th_sport;
+                       dport = tcp->th_dport;
+               }
        }
 
        ipa = ip->ip_src.s_addr;
@@ -529,13 +696,14 @@ ip_natout(ip, hlen, fin)
                if ((np->in_ifp == ifp) && np->in_space &&
                    (!np->in_flags || (np->in_flags & nflags)) &&
                    ((ipa & np->in_inmsk) == np->in_inip) &&
-                   (np->in_redir == NAT_MAP ||
-                    np->in_pnext == sport)) {
+                   ((np->in_redir == NAT_MAP) ||
+                    (np->in_pnext == sport))) {
                        /*
                         * If there is no current entry in the nat table for
                         * this IP#, create one for it.
                         */
-                       if (!(nat = nat_lookupinip(ip->ip_src, sport))) {
+                       if (!(nat = nat_outlookup(nflags, ip->ip_src, sport,
+                                                 ip->ip_dst, dport))) {
                                if (np->in_redir == NAT_REDIRECT)
                                        continue;
                                /*
@@ -544,64 +712,60 @@ ip_natout(ip, hlen, fin)
                                 * Redirections are only for incoming
                                 * connections.
                                 */
-                               if (!(nat = nat_new(np, ip, hlen,
-                                                   nflags & np->in_flags,
+                               if (!(nat = nat_new(np, ip, fin, nflags,
                                                    NAT_OUTBOUND)))
                                        break;
-                       } else
-                               ip->ip_src = nat->nat_outip;
+                       }
+                       ip->ip_src = nat->nat_outip;
 
-                       nat->nat_age = 1200;    /* 5 mins */
+                       nat->nat_age = fr_defnatage;    /* 5 mins */
 
                        /*
                         * Fix up checksums, not by recalculating them, but
                         * simply computing adjustments.
                         */
+#if SOLARIS
+                       if (np->in_redir == NAT_MAP)
+                               fix_outcksum(&ip->ip_sum, nat->nat_ipsumd);
+                       else
+                               fix_incksum(&ip->ip_sum, nat->nat_ipsumd);
+#endif
+
                        if (nflags && !(ip->ip_off & 0x1fff) &&
                            !(fin->fin_fi.fi_fl & FI_SHORT)) {
-                               u_short *sp;
-                               u_short sumshort;
 
                                if (nat->nat_outport)
                                        tcp->th_sport = nat->nat_outport;
 
                                if (ip->ip_p == IPPROTO_TCP) {
-                                       sp = &tcp->th_sum;
-
-                                       sum1 = (~ntohs(*sp)) & 0xffff;
-
-                                       sum1 += nat->nat_sumd;
-
-                                       sum1 = (sum1 >> 16) + (sum1 & 0xffff);
-                                       /* Again */
-                                       sum1 = (sum1 >> 16) + (sum1 & 0xffff);
-                                       sumshort = ~(u_short)sum1;
-                                       *sp = htons(sumshort);
-
+                                       csump = &tcp->th_sum;
+                                       set_tcp_age(&nat->nat_age,
+                                                   nat->nat_state, ip, fin,1);
                                } else if (ip->ip_p == IPPROTO_UDP) {
                                        udphdr_t *udp = (udphdr_t *)tcp;
 
-                                       sp = &udp->uh_sum;
-
-                                       if (udp->uh_sum) {
-                                               sum1 = (~ntohs(*sp)) & 0xffff;
-                                               sum1 += nat->nat_sumd;
-                                               sum1 = (sum1 >> 16) +
-                                                      (sum1 & 0xffff);
-                                               /* Again */
-                                               sum1 = (sum1 >> 16) +
-                                                      (sum1 & 0xffff);
-                                               sumshort = ~(u_short)sum1;
-                                               *sp = htons(sumshort);
-                                       }
+                                       if (udp->uh_sum)
+                                               csump = &udp->uh_sum;
+                               } else if (ip->ip_p == IPPROTO_ICMP) {
+                                       icmphdr_t *ic = (icmphdr_t *)tcp;
+
+                                       csump = &ic->icmp_cksum;
+                               }
+                               if (csump) {
+                                       if (np->in_redir == NAT_MAP)
+                                               fix_outcksum(csump,
+                                                            nat->nat_sumd);
+                                       else
+                                               fix_incksum(csump,
+                                                           nat->nat_sumd);
                                }
                        }
                        nat_stats.ns_mapped[1]++;
                        MUTEX_EXIT(&ipf_nat);
-                       return;
+                       return 1;
                }
        MUTEX_EXIT(&ipf_nat);
-       return;
+       return 0;
 }
 
 
@@ -609,7 +773,7 @@ ip_natout(ip, hlen, fin)
  * Packets coming in from the external interface go through this.
  * Here, the destination address requires alteration, if anything.
  */
-void
+int
 ip_natin(ip, hlen, fin)
        ip_t *ip;
        int hlen;
@@ -617,10 +781,9 @@ ip_natin(ip, hlen, fin)
 {
        register ipnat_t *np;
        register struct in_addr in;
-       register u_long sum1;
        struct ifnet *ifp = fin->fin_ifp;
-       tcphdr_t *tcp;
-       u_short port = 0, nflags;
+       tcphdr_t *tcp = NULL;
+       u_short sport = 0, dport = 0, nflags = 0, *csump = NULL;
        nat_t *nat;
 
        if (!(ip->ip_off & 0x1fff) && !(fin->fin_fi.fi_fl & FI_SHORT)) {
@@ -628,10 +791,11 @@ ip_natin(ip, hlen, fin)
                        nflags = IPN_TCP;
                else if (ip->ip_p == IPPROTO_UDP)
                        nflags = IPN_UDP;
-       }
-       if (nflags) {
-               tcp = (tcphdr_t *)((char *)ip + hlen);
-               port = tcp->th_dport;
+               if (nflags) {
+                       tcp = (tcphdr_t *)((char *)ip + hlen);
+                       dport = tcp->th_dport;
+                       sport = tcp->th_sport;
+               }
        }
 
        in = ip->ip_dst;
@@ -641,8 +805,9 @@ ip_natin(ip, hlen, fin)
                if ((np->in_ifp == ifp) &&
                    (!np->in_flags || (nflags & np->in_flags)) &&
                    ((in.s_addr & np->in_outmsk) == np->in_outip) &&
-                   (np->in_redir == NAT_MAP || np->in_pmin == port)) {
-                       if (!(nat = nat_lookupoutip(np, ip, tcp))) {
+                   (np->in_redir == NAT_MAP || np->in_pmin == dport)) {
+                       if (!(nat = nat_inlookup(nflags, ip->ip_src, sport,
+                                                ip->ip_dst, dport))) {
                                if (np->in_redir == NAT_MAP)
                                        continue;
                                else {
@@ -652,63 +817,61 @@ ip_natin(ip, hlen, fin)
                                         * nat_new. Otherwise, if it's just a
                                         * mapping, do a continue;
                                         */
-                                       nflags &= np->in_flags;
-                                       if (!(nat = nat_new(np, ip, hlen,
+                                       if (!(nat = nat_new(np, ip, fin,
                                                            nflags,
                                                            NAT_INBOUND)))
                                                break;
                                }
                        }
-                       nat->nat_age = 1200;
-
                        ip->ip_dst = nat->nat_inip;
 
+                       nat->nat_age = fr_defnatage;
+
                        /*
                         * Fix up checksums, not by recalculating them, but
                         * simply computing adjustments.
                         */
+#if SOLARIS
+                       if (np->in_redir == NAT_MAP)
+                               fix_incksum(&ip->ip_sum, nat->nat_ipsumd);
+                       else
+                               fix_outcksum(&ip->ip_sum, nat->nat_ipsumd);
+#endif
                        if (nflags && !(ip->ip_off & 0x1fff) &&
                            !(fin->fin_fi.fi_fl & FI_SHORT)) {
-                               u_short *sp;
-                               u_short sumshort;
 
                                if (nat->nat_inport)
                                        tcp->th_dport = nat->nat_inport;
 
                                if (ip->ip_p == IPPROTO_TCP) {
-                                       sp = &tcp->th_sum;
-
-                                       sum1 = (~ntohs(*sp)) & 0xffff;
-                                       sum1 += ~nat->nat_sumd & 0xffff;
-                                       sum1 = (sum1 >> 16) + (sum1 & 0xffff);
-                                       /* Again */
-                                       sum1 = (sum1 >> 16) + (sum1 & 0xffff);
-                                       sumshort = ~(u_short)sum1;
-                                       *sp = htons(sumshort);
+                                       csump = &tcp->th_sum;
+                                       set_tcp_age(&nat->nat_age,
+                                                   nat->nat_state, ip, fin,0);
                                } else if (ip->ip_p == IPPROTO_UDP) {
                                        udphdr_t *udp = (udphdr_t *)tcp;
 
-                                       sp = &udp->uh_sum;
-
-                                       if (udp->uh_sum) {
-                                               sum1 = (~ntohs(*sp)) & 0xffff;
-                                               sum1+= ~nat->nat_sumd & 0xffff;
-                                               sum1 = (sum1 >> 16) +
-                                                      (sum1 & 0xffff);
-                                               /* Again */
-                                               sum1 = (sum1 >> 16) +
-                                                      (sum1 & 0xffff);
-                                               sumshort = ~(u_short)sum1;
-                                               *sp = htons(sumshort);
-                                       }
+                                       if (udp->uh_sum)
+                                               csump = &udp->uh_sum;
+                               } else if (ip->ip_p == IPPROTO_ICMP) {
+                                       icmphdr_t *ic = (icmphdr_t *)tcp;
+
+                                       csump = &ic->icmp_cksum;
+                               }
+                               if (csump) {
+                                       if (np->in_redir == NAT_MAP)
+                                               fix_incksum(csump,
+                                                           nat->nat_sumd);
+                                       else
+                                               fix_outcksum(csump,
+                                                            nat->nat_sumd);
                                }
                        }
                        nat_stats.ns_mapped[0]++;
                        MUTEX_EXIT(&ipf_nat);
-                       return;
+                       return 1;
                }
        MUTEX_EXIT(&ipf_nat);
-       return;
+       return 0;
 }
 
 
@@ -718,28 +881,12 @@ ip_natin(ip, hlen, fin)
 void
 ip_natunload()
 {
-       register struct nat *nat, **natp;
-       register struct ipnat *ipn, **ipnp;
-       register int i;
 
        MUTEX_ENTER(&ipf_nat);
-       for (i = 0; i < NAT_SIZE; i++)
-               for (natp = &nat_table[0][i]; (nat = *natp); ) {
-                       *natp = nat->nat_next;
-                       if (!--nat->nat_use)
-                               KFREE(nat);
-               }
-       for (i = 0; i < NAT_SIZE; i++)
-               for (natp = &nat_table[1][i]; (nat = *natp); ) {
-                       *natp = nat->nat_next;
-                       if (!--nat->nat_use)
-                               KFREE(nat);
-               }
 
-       for (ipnp = &nat_list; (ipn = *ipnp); ) {
-               *ipnp = ipn->in_next;
-               KFREE(ipn);
-       }
+       (void) clear_natlist();
+       (void) flush_nattable();
+
        MUTEX_EXIT(&ipf_nat);
 }
 
@@ -752,41 +899,14 @@ void
 ip_natexpire()
 {
        register struct nat *nat, **natp;
-       register int i;
 
        MUTEX_ENTER(&ipf_nat);
-       for (i = 0; i < NAT_SIZE; i++)
-               for (natp = &nat_table[0][i]; (nat = *natp); ) {
-                       if (nat->nat_age > 0)
-                               nat->nat_age--;
-                       if (!nat->nat_use || !nat->nat_age) {
-                               *natp = nat->nat_next;
-                               if (nat->nat_use)
-                                       nat->nat_use--;
-                               if (!nat->nat_use) {
-                                       KFREE(nat);
-                                       nat_stats.ns_expire++;
-                                       nat_inuse--;
-                               }
-                       } else
-                               natp = &nat->nat_next;
-               }
-
-       for (i = 0; i < NAT_SIZE; i++)
-               for (natp = &nat_table[1][i]; (nat = *natp); ) {
-                       if (nat->nat_age > 0)
-                               nat->nat_age--;
-                       if (!nat->nat_use || !nat->nat_age) {
-                               *natp = nat->nat_next;
-                               if (nat->nat_use)
-                                       nat->nat_use--;
-                               if (!nat->nat_use) {
-                                       KFREE(nat);
-                                       nat_stats.ns_expire++;
-                                       nat_inuse--;
-                               }
-                       } else
-                               natp = &nat->nat_next;
-               }
+       for (natp = &nat_instances; (nat = *natp); natp = &nat->nat_next) {
+               if (--nat->nat_age)
+                       continue;
+               *natp = nat->nat_next;
+               nat_delete(nat);
+               nat_stats.ns_expire++;
+       }
        MUTEX_EXIT(&ipf_nat);
 }
index fe5181e..47b6432 100644 (file)
@@ -1,3 +1,4 @@
+/*     $OpenBSD: ip_nat.h,v 1.5 1997/02/11 22:23:27 kstailey Exp $     */
 /*
  * (C)opyright 1995 by Darren Reed.
  *
@@ -6,7 +7,7 @@
  * to the original author and the contributors.
  *
  * @(#)ip_nat.h        1.5 2/4/96
- * $Id: ip_nat.h,v 1.4 1996/10/08 07:33:29 niklas Exp $
+ * Id: ip_nat.h,v 2.0.1.7 1997/01/30 12:39:41 darrenr Exp
  */
 
 #ifndef        __IP_NAT_H_
@@ -23,6 +24,9 @@
 #define        SIOCGNATL       _IOWR('r', 83, struct natlookup)
 #define SIOCGFRST      _IOR('r', 84, struct ipfrstat)
 #define SIOCGIPST      _IOR('r', 85, struct ips_stat)
+#define        SIOCFLNAT       _IOWR('r', 86, int)
+#define        SIOCCNATL       _IOWR('r', 87, int)
+
 #else
 #define        SIOCADNAT       _IOW(r, 80, struct ipnat)
 #define        SIOCRMNAT       _IOW(r, 81, struct ipnat)
 #define        SIOCGNATL       _IOWR(r, 83, struct natlookup)
 #define SIOCGFRST      _IOR(r, 84, struct ipfrstat)
 #define SIOCGIPST      _IOR(r, 85, struct ips_stat)
+#define        SIOCFLNAT       _IOWR(r, 86, int)
+#define        SIOCCNATL       _IOWR(r, 87, int)
 #endif
 
 #define        NAT_SIZE        367
 
 typedef        struct  nat     {
-       struct  nat     *nat_next;
-       u_short nat_use;
-       short   nat_age;
+       int     nat_age;
        u_long  nat_sumd;
+       u_long  nat_ipsumd;
        struct  in_addr nat_inip;
        struct  in_addr nat_outip;
        struct  in_addr nat_oip;        /* other ip */
        u_short nat_oport;      /* other port */
        u_short nat_inport;
        u_short nat_outport;
+       u_short nat_use;
+       u_char  nat_state[2];
+       struct  ipnat   *nat_ptr;
+       struct  nat     *nat_next;
+       struct  nat     *nat_hnext[2];
+       struct  nat     **nat_hstart[2];
 } nat_t;
 
 typedef        struct  ipnat   {
        struct  ipnat   *in_next;
        void    *in_ifp;
-       u_short in_flags;
+       u_int   in_space;
+       u_int   in_use;
+       struct  in_addr in_nextip;
        u_short in_pnext;
+       u_short in_flags;
        u_short in_port[2];
        struct  in_addr in_in[2];
        struct  in_addr in_out[2];
-       struct  in_addr in_nextip;
-       int     in_space;
        int     in_redir; /* 0 if it's a mapping, 1 if it's a hard redir */
        char    in_ifname[IFNAMSIZ];
 } ipnat_t;
@@ -75,7 +87,8 @@ typedef       struct  ipnat   {
 #define        NAT_MAP         0
 #define        NAT_REDIRECT    1
 
-#define        IPN_CMPSIZ      (sizeof(struct in_addr) * 4 + sizeof(u_short) * 2)
+#define        IPN_CMPSIZ      (sizeof(struct in_addr) * 4 + sizeof(u_short) * 3 + \
+                        sizeof(int))
 
 typedef        struct  natlookup {
        struct  in_addr nl_inip;
@@ -89,7 +102,7 @@ typedef      struct  natstat {
        u_long  ns_added;
        u_long  ns_expire;
        u_long  ns_inuse;
-       nat_t   ***ns_table;
+       nat_t   **ns_table[2];
        ipnat_t *ns_list;
 } natstat_t;
 
@@ -98,12 +111,15 @@ typedef    struct  natstat {
 #define        IPN_UDP         2
 #define        IPN_TCPUDP      3
 
+extern nat_t *nat_table[2][NAT_SIZE];
 extern int nat_ioctl __P((caddr_t, int, int));
-extern nat_t *nat_lookupoutip __P((ipnat_t *, ip_t *, tcphdr_t *));
-extern nat_t *nat_lookupinip __P((struct in_addr, u_short));
+extern nat_t *nat_outlookup __P((int, struct in_addr, u_short, struct in_addr,
+                                u_short));
+extern nat_t *nat_inlookup __P((int, struct in_addr, u_short, struct in_addr,
+                                u_short));
 extern nat_t *nat_lookupredir __P((natlookup_t *));
-extern void ip_natout __P((ip_t *, int, fr_info_t *));
-extern void ip_natin __P((ip_t *, int, fr_info_t *));
+extern int ip_natout __P((ip_t *, int, fr_info_t *));
+extern int ip_natin __P((ip_t *, int, fr_info_t *));
 extern void ip_natunload __P((void));
 extern void ip_natexpire __P((void));
 #endif /* __IP_NAT_H__ */
index c6c04d5..71af2c2 100644 (file)
@@ -1,3 +1,4 @@
+/*     $OpenBSD: ip_state.c,v 1.7 1997/02/11 22:23:28 kstailey Exp $   */
 /*
  * (C)opyright 1995 by Darren Reed.
  *
@@ -6,9 +7,9 @@
  * to the original author and the contributors.
  */
 #if 0
-#ifndef        lint
+#if !defined(lint) && defined(LIBC_SCCS)
 static char    sccsid[] = "@(#)ip_state.c      1.8 6/5/96 (C) 1993-1995 Darren Reed";
-static char    rcsid[] = "$OpenBSD: ip_state.c,v 1.6 1997/01/18 08:29:21 downsj Exp $";
+static char    rcsid[] = "Id: ip_state.c,v 2.0.1.2 1997/01/09 15:22:45 darrenr Exp ";
 #endif
 #endif
 
@@ -16,24 +17,18 @@ static      char    rcsid[] = "$OpenBSD: ip_state.c,v 1.6 1997/01/18 08:29:21 downsj Exp
 # include <stdlib.h>
 # include <string.h>
 #endif
-#ifndef        linux
 #include <sys/errno.h>
 #include <sys/types.h>
-#if defined(_KERNEL) || defined(KERNEL)
-#include <sys/systm.h>
-#endif
 #include <sys/param.h>
 #include <sys/file.h>
 #include <sys/ioctl.h>
 #include <sys/uio.h>
 #include <sys/protosw.h>
 #include <sys/socket.h>
+#ifdef _KERNEL
+# include <sys/systm.h>
+#endif
 #if !defined(__SVR4) && !defined(__svr4__)
-# if defined(__OpenBSD__)
-#  include <sys/dirent.h>
-# else
-#  include <sys/dir.h>
-# endif
 # include <sys/mbuf.h>
 #else
 # include <sys/byteorder.h>
@@ -52,11 +47,10 @@ static      char    rcsid[] = "$OpenBSD: ip_state.c,v 1.6 1997/01/18 08:29:21 downsj Exp
 #include <netinet/ip.h>
 #include <netinet/ip_var.h>
 #include <netinet/tcp.h>
+#include <netinet/tcp_fsm.h>
 #include <netinet/udp.h>
 #include <netinet/tcpip.h>
 #include <netinet/ip_icmp.h>
-#include <sys/syslog.h>
-#endif
 #include "ip_fil_compat.h"
 #include "ip_fil.h"
 #include "ip_state.h"
@@ -64,6 +58,15 @@ static       char    rcsid[] = "$OpenBSD: ip_state.c,v 1.6 1997/01/18 08:29:21 downsj Exp
 #define        MIN(a,b)        (((a)<(b))?(a):(b))
 #endif
 
+void set_tcp_age __P((int *, u_char *, ip_t *, fr_info_t *, int));
+#ifndef _KERNEL
+int fr_tcpstate __P((register ipstate_t *, fr_info_t *, ip_t *, tcphdr_t *,
+                    u_short, ipstate_t **));
+#else
+int fr_tcpstate __P((register ipstate_t *,  fr_info_t *, ip_t *, tcphdr_t *,
+                    u_short));
+#endif
+
 #define        TCP_CLOSE       (TH_FIN|TH_RST)
 
 ipstate_t *ips_table[IPSTATE_SIZE];
@@ -77,6 +80,17 @@ extern       kmutex_t        ipf_state;
 #endif
 
 
+#define        FIVE_DAYS       (2 * 5 * 86400) /* 5 days: half closed session */
+
+u_long fr_tcpidletimeout = FIVE_DAYS,
+       fr_tcpclosewait = 60,
+       fr_tcplastack = 20,
+       fr_tcptimeout = 120,
+       fr_tcpclosed = 1,
+       fr_udptimeout = 120,
+       fr_icmptimeout = 120;
+
+
 ips_stat_t *
 fr_statetstats()
 {
@@ -104,10 +118,15 @@ fr_addstate(ip, fin, pass)
        register ipstate_t *is = &ips;
        register u_int hv;
 
+       if ((ip->ip_off & 0x1fff) || (fin->fin_fi.fi_fl & FI_SHORT))
+               return -1;
        if (ips_num == IPSTATE_MAX) {
                ips_stats.iss_max++;
                return -1;
        }
+       ips.is_age = 1;
+       ips.is_state[0] = 0;
+       ips.is_state[1] = 0;
        /*
         * Copy and calculate...
         */
@@ -137,7 +156,7 @@ fr_addstate(ip, fin, pass)
                        return -1;
                }
                ips_stats.iss_icmp++;
-               is->is_age = 120;
+               is->is_age = fr_icmptimeout;
                break;
            }
        case IPPROTO_TCP :
@@ -152,7 +171,8 @@ fr_addstate(ip, fin, pass)
                hv += (is->is_sport = tcp->th_sport);
                is->is_seq = ntohl(tcp->th_seq);
                is->is_ack = ntohl(tcp->th_ack);
-               is->is_win = ntohs(tcp->th_win);
+               is->is_swin = ntohs(tcp->th_win);
+               is->is_dwin = is->is_swin;      /* start them the same */
                ips_stats.iss_tcp++;
                /*
                 * If we're creating state for a starting connectoin, start the
@@ -160,9 +180,9 @@ fr_addstate(ip, fin, pass)
                 * connect.
                 */
                if ((tcp->th_flags & (TH_SYN|TH_ACK)) == TH_SYN)
-                       is->is_age = 120;
-               else
-                       is->is_age = 0;
+                       is->is_ack = 0; /* Trumpet WinSock 'ism */
+               set_tcp_age(&is->is_age, is->is_state, ip, fin,
+                           tcp->th_sport == is->is_sport);
                break;
            }
        case IPPROTO_UDP :
@@ -172,7 +192,7 @@ fr_addstate(ip, fin, pass)
                hv += (is->is_dport = tcp->th_dport);
                hv += (is->is_sport = tcp->th_sport);
                ips_stats.iss_udp++;
-               is->is_age = 120;
+               is->is_age = fr_udptimeout;
                break;
            }
        default :
@@ -197,6 +217,91 @@ fr_addstate(ip, fin, pass)
 }
 
 
+/*
+ * check to see if a packet with TCP headers fits within the TCP window.
+ * change timeout depending on whether new packet is a SYN-ACK returning for a
+ * SYN or a RST or FIN which indicate time to close up shop.
+ */
+int
+fr_tcpstate(is, fin, ip, tcp, sport
+#ifndef        _KERNEL
+     ,isp)
+       ipstate_t **isp;
+#else
+       )
+#endif
+       register ipstate_t *is;
+       fr_info_t *fin;
+       ip_t *ip;
+       tcphdr_t *tcp;
+       u_short sport;
+{
+       register int seqskew, ackskew;
+       register u_short swin, dwin;
+       register tcp_seq seq, ack;
+       int source;
+
+       /*
+        * Find difference between last checked packet and this packet.
+        */
+       seq = ntohl(tcp->th_seq);
+       ack = ntohl(tcp->th_ack);
+       if (sport == is->is_sport) {
+               seqskew = seq - is->is_seq;
+               ackskew = ack - is->is_ack;
+       } else {
+               seqskew = ack - is->is_seq;
+               if (!is->is_ack)
+                       /*
+                        * Must be a SYN-ACK in reply to a SYN.
+                        */
+                       is->is_ack = seq;
+               ackskew = seq - is->is_ack;
+       }
+
+       /*
+        * Make skew values absolute
+        */
+       if (seqskew < 0)
+               seqskew = -seqskew;
+       if (ackskew < 0)
+               ackskew = -ackskew;
+
+       /*
+        * If the difference in sequence and ack numbers is within the
+        * window size of the connection, store these values and match
+        * the packet.
+        */
+       if ((source = (sport == is->is_sport))) {
+               swin = is->is_swin;
+               dwin = is->is_dwin;
+       } else {
+               dwin = is->is_swin;
+               swin = is->is_dwin;
+       }
+
+       if ((seqskew <= swin) && (ackskew <= dwin)) {
+               if (source) {
+                       is->is_seq = seq;
+                       is->is_ack = ack;
+                       is->is_swin = ntohs(tcp->th_win);
+               } else {
+                       is->is_seq = ack;
+                       is->is_ack = seq;
+                       is->is_dwin = ntohs(tcp->th_win);
+               }
+               ips_stats.iss_hits++;
+               /*
+                * Nearing end of connection, start timeout.
+                */
+               set_tcp_age(&is->is_age, is->is_state, ip, fin,
+                           tcp->th_sport == is->is_sport);
+               return 1;
+       }
+       return 0;
+}
+
+
 /*
  * Check if a packet has a registered state.
  */
@@ -212,7 +317,7 @@ fr_checkstate(ip, fin)
        tcphdr_t *tcp;
        u_int hv, hlen;
 
-       if ((ip->ip_off & 0x1fff) && !(fin->fin_fi.fi_fl & FI_SHORT))
+       if ((ip->ip_off & 0x1fff) || (fin->fin_fi.fi_fl & FI_SHORT))
                return 0;
 
        hlen = fin->fin_hlen;
@@ -244,7 +349,7 @@ fr_checkstate(ip, fin)
                                if (is->is_icmp.ics_type &&
                                    is->is_icmp.ics_type != ic->icmp_type)
                                        continue;
-                               is->is_age = 120;
+                               is->is_age = fr_icmptimeout;
                                ips_stats.iss_hits++;
                                MUTEX_EXIT(&ipf_state);
                                return is->is_pass;
@@ -254,92 +359,34 @@ fr_checkstate(ip, fin)
        case IPPROTO_TCP :
            {
                register u_short dport = tcp->th_dport, sport = tcp->th_sport;
-               register u_short win = ntohs(tcp->th_win);
-               tcp_seq seq, ack;
 
                hv += dport;
                hv += sport;
                hv %= IPSTATE_SIZE;
                MUTEX_ENTER(&ipf_state);
                for (isp = &ips_table[hv]; (is = *isp); isp = &is->is_next) {
-                       register int dl, seqskew, ackskew;
-
                        if ((is->is_p == pr) &&
                            PAIRS(sport, dport, is->is_sport, is->is_dport) &&
-                           IPPAIR(src, dst, is->is_src, is->is_dst)) {
-                               dl = ip->ip_len - hlen - sizeof(tcphdr_t);
-                               /*
-                                * Find difference between last checked packet
-                                * and this packet.
-                                */
-                               seq = ntohl(tcp->th_seq);
-                               ack = ntohl(tcp->th_ack);
-                               if (sport == is->is_sport) {
-                                       seqskew = seq - is->is_seq;
-                                       ackskew = ack - is->is_ack;
-                               } else {
-                                       seqskew = ack - is->is_seq;
-                                       if (!is->is_ack) {
-                                               /*
-                                                * Must be a SYN-ACK in reply
-                                                * to a SYN.  Set age timeout
-                                                * to 0 to stop deletion.
-                                                */
-                                               is->is_ack = seq;
-                                               is->is_age = 0;
-                                       }
-                                       ackskew = seq - is->is_ack;
-                               }
-
-                               /*
-                                * Make skew values absolute
-                                */
-                               if (seqskew < 0)
-                                       seqskew = -seqskew;
-                               if (ackskew < 0)
-                                       ackskew = -ackskew;
-                               /*
-                                * If the difference in sequence and ack
-                                * numbers is within the window size of the
-                                * connection, store these values and match
-                                * the packet.
-                                */
-                               if ((seqskew <= win) && (ackskew <= win)) {
-                                       is->is_win = win;
-                                       if (sport == is->is_sport) {
-                                               is->is_seq = seq;
-                                               is->is_ack = ack;
-                                       } else {
-                                               is->is_seq = ack;
-                                               is->is_ack = seq;
-                                       }
-                                       ips_stats.iss_hits++;
-                                       /*
-                                        * Nearing end of connection, start
-                                        * timeout.
-                                        */
+                           IPPAIR(src, dst, is->is_src, is->is_dst))
+                               if (fr_tcpstate(is, fin, ip, tcp, sport
+#ifndef _KERNEL
+                                               , NULL
+#endif
+                                               )) {
 #ifdef _KERNEL
-                                       if (!is->is_age) {
-                                               if (tcp->th_flags & TH_FIN)
-                                                       is->is_age = 120;
-                                               if (tcp->th_flags & TH_RST)
-                                                       is->is_age = 1;
-                                       }
                                        MUTEX_EXIT(&ipf_state);
                                        return is->is_pass;
 #else
-                                       if (tcp->th_flags & TCP_CLOSE) {
-                                               int pass = is->is_pass;
+                                       int pass = is->is_pass;
 
+                                       if (tcp->th_flags & TCP_CLOSE) {
                                                *isp = is->is_next;
                                                isp = &ips_table[hv];
                                                KFREE(is);
-                                               return pass;
                                        }
-                                       return is->is_pass;
+                                       return pass;
 #endif
                                }
-                       }
                }
                MUTEX_EXIT(&ipf_state);
                break;
@@ -360,7 +407,7 @@ fr_checkstate(ip, fin)
                            PAIRS(sport, dport, is->is_sport, is->is_dport) &&
                            IPPAIR(src, dst, is->is_src, is->is_dst)) {
                                ips_stats.iss_hits++;
-                               is->is_age = 120;
+                               is->is_age = fr_udptimeout;
                                MUTEX_EXIT(&ipf_state);
                                return is->is_pass;
                        }
@@ -395,7 +442,7 @@ fr_stateunload()
 
 
 /*
- * Slowly expire held state for thingslike UDP and ICMP.  Timeouts are set
+ * Slowly expire held state for things like UDP and ICMP.  Timeouts are set
  * in expectation of this being called twice per second.
  */
 void
@@ -419,3 +466,92 @@ fr_timeoutstate()
                                isp = &is->is_next;
        MUTEX_EXIT(&ipf_state);
 }
+
+
+/*
+ * Original idea freom Pradeep Krishnan for use primarily with NAT code.
+ * (pkrishna@netcom.com)
+ */
+void
+set_tcp_age(age, state, ip, fin, dir)
+       int *age;
+       u_char *state;
+       ip_t *ip;
+       fr_info_t *fin;
+       int dir;
+{
+       tcphdr_t *tcp = (tcphdr_t *)fin->fin_dp;
+       u_char flags = tcp->th_flags;
+       int dlen, ostate;
+
+       ostate = state[1 - dir];
+
+       dlen = ip->ip_len - fin->fin_hlen - (tcp->th_off << 2);
+
+       if (flags & TH_RST) {
+               if (!(tcp->th_flags & TH_PUSH) && !dlen) {
+                       *age = fr_tcpclosed;
+                       state[dir] = TCPS_CLOSED;
+               } else {
+                       *age = fr_tcpclosewait;
+                       state[dir] = TCPS_CLOSE_WAIT;
+               }
+               return;
+       }
+
+       *age = fr_tcptimeout; /* 1 min */
+
+       switch(state[dir])
+       {
+       case TCPS_FIN_WAIT_2:
+       case TCPS_CLOSED:
+               if ((flags & TH_OPENING) == TH_OPENING)
+                       state[dir] = TCPS_SYN_RECEIVED;
+               else if (flags & TH_SYN)
+                       state[dir] = TCPS_SYN_SENT;
+               break;
+       case TCPS_SYN_RECEIVED:
+               if ((flags & (TH_FIN|TH_ACK)) == TH_ACK) {
+                       state[dir] = TCPS_ESTABLISHED;
+                       *age = fr_tcpidletimeout;
+               }
+               break;
+       case TCPS_SYN_SENT:
+               if ((flags & (TH_FIN|TH_ACK)) == TH_ACK) {
+                       state[dir] = TCPS_ESTABLISHED;
+                       *age = fr_tcpidletimeout;
+               }
+               break;
+       case TCPS_ESTABLISHED:
+               if (flags & TH_FIN) {
+                       state[dir] = TCPS_CLOSE_WAIT;
+                       if (!(flags & TH_PUSH) && !dlen &&
+                           ostate > TCPS_ESTABLISHED)
+                               *age  = fr_tcplastack;
+                       else
+                               *age  = fr_tcpclosewait;
+               } else
+                       *age = fr_tcpidletimeout;
+               break;
+       case TCPS_CLOSE_WAIT:
+               if ((flags & TH_FIN) && !(flags & TH_PUSH) && !dlen &&
+                   ostate > TCPS_ESTABLISHED) {
+                       *age  = fr_tcplastack;
+                       state[dir] = TCPS_LAST_ACK;
+               } else
+                       *age  = fr_tcpclosewait;
+               break;
+       case TCPS_LAST_ACK:
+               if (flags & TH_ACK) {
+                       state[dir] = TCPS_FIN_WAIT_2;
+                       if (!(flags & TH_PUSH) && !dlen &&
+                           ostate > TCPS_ESTABLISHED)
+                               *age  = fr_tcplastack;
+                       else {
+                               *age  = fr_tcpclosewait;
+                               state[dir] = TCPS_CLOSE_WAIT;
+                       }
+               }
+               break;
+       }
+}
index 5e0b34d..f51dc51 100644 (file)
@@ -1,3 +1,4 @@
+/*     $OpenBSD: ip_state.h,v 1.4 1997/02/11 22:23:30 kstailey Exp $   */
 /*
  * (C)opyright 1995 by Darren Reed.
  *
@@ -6,7 +7,7 @@
  * to the original author and the contributors.
  *
  * @(#)ip_state.h      1.3 1/12/96 (C) 1995 Darren Reed
- * $OpenBSD: ip_state.h,v 1.3 1996/10/08 07:33:30 niklas Exp $
+ * Id: ip_state.h,v 2.0.1.1 1997/01/09 15:14:43 darrenr Exp
  */
 #ifndef        __IP_STATE_H__
 #define        __IP_STATE_H__
@@ -30,7 +31,9 @@ typedef       struct tcpstate {
        u_short ts_dport;
        u_long  ts_seq;
        u_long  ts_ack;
-       u_short ts_win;
+       u_short ts_swin;
+       u_short ts_dwin;
+       u_char  ts_state[2];
 } tcpstate_t;
 
 typedef struct ipstate {
@@ -40,6 +43,7 @@ typedef struct ipstate {
        struct  in_addr is_src;
        struct  in_addr is_dst;
        u_char  is_p;
+       u_char  is_flags;
        union {
                icmpstate_t     is_ics;
                tcpstate_t      is_ts;
@@ -52,10 +56,13 @@ typedef struct ipstate {
 #define        is_udp  is_ps.is_us
 #define        is_seq  is_tcp.ts_seq
 #define        is_ack  is_tcp.ts_ack
-#define        is_win  is_tcp.ts_win
+#define        is_dwin is_tcp.ts_dwin
+#define        is_swin is_tcp.ts_swin
 #define        is_sport        is_tcp.ts_sport
 #define        is_dport        is_tcp.ts_dport
+#define        is_state        is_tcp.ts_state
 
+#define        TH_OPENING      (TH_SYN|TH_ACK)
 
 typedef        struct  ips_stat {
        u_long  iss_hits;
@@ -72,10 +79,11 @@ typedef     struct  ips_stat {
 } ips_stat_t;
 
 extern ips_stat_t *fr_statetstats __P((void));
-extern int     fr_addstate __P((ip_t *, fr_info_t *, u_int));
-extern int     fr_checkstate __P((ip_t *, fr_info_t *));
-extern void    fr_timeoutstate __P((void));
+extern int fr_addstate __P((ip_t *, fr_info_t *, u_int));
+extern int fr_checkstate __P((ip_t *, fr_info_t *));
+extern void fr_timeoutstate __P((void));
+extern void set_tcp_age __P((int *, u_char *, ip_t *, fr_info_t *, int));
 # ifdef        _KERNEL
-extern void    fr_stateunload __P((void));
+extern void fr_stateunload __P((void));
 # endif
 #endif /* __IP_STATE_H__ */
index edc7f57..408558b 100644 (file)
@@ -32,6 +32,7 @@ etherfind -n -t
 #include <sys/ioctl.h>
 #include <sys/param.h>
 #include <netinet/in.h>
+#include <arpa/inet.h>
 #include <netinet/in_systm.h>
 #include <netinet/ip_var.h>
 #include <netinet/ip.h>
@@ -41,14 +42,12 @@ etherfind -n -t
 #include <netinet/tcpip.h>
 #include <net/if.h>
 #include <netdb.h>
-#include "ip_fil_compat.h"
-#include "ip_fil.h"
 #include "ipf.h"
 #include "ipt.h"
 
-#ifndef lint
+#if !defined(lint) && defined(LIBC_SCCS)
 static char sccsid[] = "@(#)ipft_ef.c  1.6 2/4/96 (C)1995 Darren Reed";
-static char    rcsid[] = "$Id: ipft_ef.c,v 1.5 1996/10/08 07:33:34 niklas Exp $";
+static char    rcsid[] = "$Id: ipft_ef.c,v 1.6 1997/02/11 22:23:48 kstailey Exp $";
 #endif
 
 static int     etherf_open(), etherf_close(), etherf_readip();
@@ -58,11 +57,6 @@ struct       ipread  etherf = { etherf_open, etherf_close, etherf_readip };
 static FILE    *efp = NULL;
 static int     efd = -1;
 
-#ifdef NEED_INET_ATON
-extern u_long  inet_aton();
-#else
-#include <arpa/inet.h>
-#endif
 
 static int     etherf_open(fname)
 char   *fname;
index 454a8f9..916c554 100644 (file)
 #include <netinet/ip_icmp.h>
 #include <netinet/tcpip.h>
 #include <net/if.h>
-#include "ip_fil_compat.h"
 #include <netdb.h>
 #include <arpa/nameser.h>
 #include <resolv.h>
 #include "ipf.h"
 #include "ipt.h"
 
-#ifndef        lint
+#if !defined(lint) && defined(LIBC_SCCS)
 static char    sccsid[] = "@(#)ipft_hx.c       1.1 3/9/96 (C) 1996 Darren Reed";
-static char    rcsid[] = "$Id: ipft_hx.c,v 1.3 1997/01/17 07:14:06 millert Exp $";
+static char    rcsid[] = "$Id: ipft_hx.c,v 1.4 1997/02/11 22:23:50 kstailey Exp $";
 #endif
 
 extern int     opts;
@@ -91,16 +90,13 @@ int cnt, *dir;
        char    line[513];
 
        ip = (struct ip *)buf;
-       *ifn = NULL;
        while (fgets(line, sizeof(line)-1, tfp)) {
-               if ((s = strchr(line, '\n'))) {
+               if ((s = index(line, '\n'))) {
                        if (s == line)
                                return (char *)ip - buf;
                        *s = '\0';
                }
-               if ((s = strchr(line, '\r')))
-                       *s = '\0';
-               if ((s = strchr(line, '#')))
+               if ((s = index(line, '#')))
                        *s = '\0';
                if (!*line)
                        continue;
@@ -108,8 +104,6 @@ int cnt, *dir;
                        printf("input: %s\n", line);
                        fflush(stdout);
                }
-               *ifn = NULL;
-               *dir = 0;
                ip = (struct ip *)readhex(line, (char *)ip);
        }
        return -1;
index 5c7056e..84a6b1b 100644 (file)
 #include <netinet/tcp.h>
 #include <netinet/tcpip.h>
 #include <net/if.h>
-#include "ip_fil_compat.h"
-#include "ip_fil.h"
 #include "ipf.h"
 #include "ipt.h"
 #include "pcap.h"
 
-#ifndef        lint
-static char    rcsid[] = "$Id: ipft_pc.c,v 1.5 1996/10/08 07:33:35 niklas Exp $";
+#if !defined(lint) && defined(LIBC_SCCS)
+static char    rcsid[] = "$Id: ipft_pc.c,v 1.6 1997/02/11 22:23:51 kstailey Exp $";
 #endif
 
 struct llc     {
index dbb0b54..a8e8baf 100644 (file)
 #include <netinet/tcp.h>
 #include <netinet/tcpip.h>
 #include <net/if.h>
-#include "ip_fil_compat.h"
-#include "ip_fil.h"
 #include "ipf.h"
 #include "ipt.h"
 #include "snoop.h"
 
-#ifndef        lint
-static char    rcsid[] = "$Id: ipft_sn.c,v 1.4 1996/10/08 07:33:35 niklas Exp $";
+#if !defined(lint) && defined(LIBC_SCCS)
+static char    rcsid[] = "$Id: ipft_sn.c,v 1.5 1997/02/11 22:23:52 kstailey Exp $";
 #endif
 
 struct llc     {
index be6a84b..fb9dcb6 100644 (file)
@@ -41,6 +41,7 @@ tcpdump -nqte
 #include <sys/socket.h>
 #include <sys/ioctl.h>
 #include <netinet/in.h>
+#include <arpa/inet.h>
 #include <netinet/in_systm.h>
 #include <netinet/ip_var.h>
 #include <netinet/ip.h>
@@ -50,22 +51,15 @@ tcpdump -nqte
 #include <netinet/tcpip.h>
 #include <net/if.h>
 #include <netdb.h>
-#include "ip_fil_compat.h"
-#include "ip_fil.h"
 #include "ipf.h"
 #include "ipt.h"
 
-#ifndef lint
+#if !defined(lint) && defined(LIBC_SCCS)
 static char sccsid[] = "@(#)ipft_td.c  1.8 2/4/96 (C)1995 Darren Reed";
-static char    rcsid[] = "$Id: ipft_td.c,v 1.5 1996/10/08 07:33:36 niklas Exp $";
+static char    rcsid[] = "$Id: ipft_td.c,v 1.6 1997/02/11 22:23:54 kstailey Exp $";
 #endif
 
 static int     tcpd_open(), tcpd_close(), tcpd_readip();
-#ifdef NEED_INET_ATON
-extern u_long  inet_aton();
-#else
-#include <arpa/inet.h>
-#endif
 
 struct ipread  tcpd = { tcpd_open, tcpd_close, tcpd_readip };
 
index 39c53c4..4d1186b 100644 (file)
 #include <netinet/tcp.h>
 #include <netinet/ip_icmp.h>
 #include <netinet/tcpip.h>
+#include <arpa/inet.h>
 #include <net/if.h>
-#include "ip_fil_compat.h"
 #include <netdb.h>
 #include <arpa/nameser.h>
 #include <resolv.h>
+#include "ip_fil_compat.h"
 #include "ipf.h"
 #include "ipt.h"
 
-#ifndef        lint
+#if !defined(lint) && defined(LIBC_SCCS)
 static char    sccsid[] = "@(#)ipft_tx.c       1.7 6/5/96 (C) 1993 Darren Reed";
-static char    rcsid[] = "$Id: ipft_tx.c,v 1.5 1997/01/17 07:14:07 millert Exp $";
+static char    rcsid[] = "$Id: ipft_tx.c,v 1.6 1997/02/11 22:23:55 kstailey Exp $";
 #endif
 
 extern int     opts;
@@ -65,7 +66,7 @@ static        u_short tx_portnum();
  * returns an ip address as a long var as a result of either a DNS lookup or
  * straight inet_addr() call
  */
-u_long tx_hostnum(host, resolved)
+static u_long  tx_hostnum(host, resolved)
 char   *host;
 int    *resolved;
 {
@@ -94,7 +95,7 @@ int   *resolved;
  * find the port number given by the name, either from getservbyname() or
  * straight atoi()
  */
-u_short        tx_portnum(name)
+static u_short tx_portnum(name)
 char   *name;
 {
        struct  servent *sp, *sp2;
@@ -177,11 +178,11 @@ int       cnt, *dir;
        ip = (struct ip *)buf;
        *ifn = NULL;
        while (fgets(line, sizeof(line)-1, tfp)) {
-               if ((s = strchr(line, '\n')))
+               if ((s = index(line, '\n')))
                        *s = '\0';
-               if ((s = strchr(line, '\r')))
+               if ((s = index(line, '\r')))
                        *s = '\0';
-               if ((s = strchr(line, '#')))
+               if ((s = index(line, '#')))
                        *s = '\0';
                if (!*line)
                        continue;
@@ -264,7 +265,7 @@ int *out;
        if (ip->ip_p == IPPROTO_TCP || ip->ip_p == IPPROTO_UDP) {
                char    *last;
 
-               last = strchr(*cpp, ',');
+               last = index(*cpp, ',');
                if (!last) {
                        fprintf(stderr, "tcp/udp with no source port\n");
                        return 1;
@@ -280,7 +281,7 @@ int *out;
        if (ip->ip_p == IPPROTO_TCP || ip->ip_p == IPPROTO_UDP) {
                char    *last;
 
-               last = strchr(*cpp, ',');
+               last = index(*cpp, ',');
                if (!last) {
                        fprintf(stderr, "tcp/udp with no destination port\n");
                        return 1;
@@ -296,7 +297,7 @@ int *out;
                char    *s, *t;
 
                for (s = *cpp; *s; s++)
-                       if ((t  = strchr(tcp_flagset, *s)))
+                       if ((t  = index(tcp_flagset, *s)))
                                tcp->th_flags |= tcp_flags[t - tcp_flagset];
                if (tcp->th_flags)
                        cpp++;
@@ -310,7 +311,7 @@ int *out;
                     s++, i++)
                        if (*s && !strncasecmp(*cpp, *s, strlen(*s))) {
                                ic->icmp_type = i;
-                               if ((t = strchr(*cpp, ',')))
+                               if ((t = index(*cpp, ',')))
                                        ic->icmp_code = atoi(t+1);
                                cpp++;
                                break;
index 7259140..912b3a3 100644 (file)
@@ -1,14 +1,24 @@
-.LP
 .TH ipftest 8
 .SH NAME
-ipftest - test packet filter rules with arbitary input.
+ipftest \- test packet filter rules with arbitary input.
 .SH SYNOPSIS
-ipftest [-vbdPSTEHX] [-I interface] -r <filename> [-i <filename>]
+.B ipftest
+[
+.B \-vbdPSTEHX
+] [
+.B \-I
+interface
+]
+.B \-r
+<filename>
+[
+.B \-i
+<filename>
+]
 .SH DESCRIPTION
-.LP
 .PP
 \fBipftest\fP is provided for the purpose of being able to test a set of
-filter rules without having to put them in place, in operation and procede
+filter rules without having to put them in place, in operation and proceed
 to test their effectiveness.  The hope is that this minimises disruptions
 in providing a secure IP environment.
 .PP
@@ -19,7 +29,7 @@ pass, block or nomatch.  This is intended to give the operator a better
 idea of what is happening with packets passing through their filter
 ruleset.
 .PP
-When used without eiether of \fB-S\fP, \fB-T\fP or \fB-E\fP,
+When used without either of \fB\-S\fP, \fB\-T\fP or \fB\-E\fP,
 \fBipftest\fP uses its own text input format to generate "fake" IP packets.
 The format used is as follows:
 .nf
@@ -41,30 +51,37 @@ are:
                out on le0 tcp 10.4.12.1,2245 10.1.1.1,23 S
 .fi
 .SH OPTIONS
-.IP -v
+.TP
+.B \-v
 Verbose mode.  This provides more information about which parts of rule
 matching the input packet passes and fails.
-.IP -d
+.TP
+.B \-d
 Turn on filter rule debugging.  Currently, this only shows you what caused
 the rule to not match in the IP header checking (addresses/netmasks, etc).
-.IP -b
+.TP
+.B \-b
 Cause the output to be a brief summary (one-word) of the result of passing
 the packet through the filter; either "pass", "block" or "nomatch".
 This is used in the regression testing.
-.IP -I <interface>
+.TP
+.BR \-I \0<interface>
 Set the interface name (used in rule matching) to be the name supplied.
-This is useful with the \fB-P, -S, -T\fP and \fB-E\fP options, where it is
+This is useful with the \fB\-P, \-S, \-T\fP and \fB\-E\fP options, where it is
 not otherwise possible to associate a packet with an interface.  Normal
 "text packets" can override this setting.
-.IP -P
-The input file specified by \fB-i\fP is a binary file produced using libpcap
-(ie tcpdump version 3).  Packets are read from this file as being input
-(for rule purposes).  An interface maybe specified using \fB-I\fP.
-.IP -S
+.TP
+.B \-P
+The input file specified by \fB\-i\fP is a binary file produced using libpcap
+(i.e., tcpdump version 3).  Packets are read from this file as being input
+(for rule purposes).  An interface maybe specified using \fB\-I\fP.
+.TP
+.B \-S
 The input file is to be in "snoop" format (see RFC 1761).  Packets are read
 from this file and used as input from any interface.  This is perhaps the
 most useful input type, currently.
-.IP -T
+.TP
+.B \-T
 The input file is to be text output from tcpdump.  The text formats which
 are currently supported are those which result from the following tcpdump
 option combinations:
@@ -77,13 +94,16 @@ option combinations:
                tcpdump -nqte
 .fi
 .LP
-.IP -H
+.TP
+.B \-H
 The input file is to be hex digits, representing the binary makeup of the
 packet.  No length correction is made, if an incorrect length is put in
 the IP header.
-.IP -X
+.TP
+.B \-X
 The input file is composed of text descriptions of IP packets.
-.IP -E
+.TP
+.B \-E
 The input file is to be text output from etherfind.  The text formats which
 are currently supported are those which result from the following etherfind
 option combinations:
@@ -93,9 +113,11 @@ option combinations:
                etherfind -n -t
 .fi
 .LP
-.IP -i <filename>
-Specify the filename to take input from.  Default is stdin.
-.IP -r <filename>
+.TP
+.BR \-i \0<filename>
+Specify the filename from which to take input.  Default is stdin.
+.TP
+.BR \-r \0<filename>
 Specify the filename from which to read filter rules.
 .SH FILES
 .SH SEE ALSO
index 4fc23c0..f5a2fec 100644 (file)
@@ -39,9 +39,9 @@
 #include "ipt.h"
 #include <ctype.h>
 
-#ifndef        lint
+#if !defined(lint) && defined(LIBC_SCCS)
 static char    sccsid[] = "@(#)ipt.c   1.19 6/3/96 (C) 1993-1996 Darren Reed";
-static char    rcsid[] = "$Id: ipt.c,v 1.7 1997/01/17 07:14:08 millert Exp $";
+static char    rcsid[] = "$Id: ipt.c,v 1.8 1997/02/11 22:23:58 kstailey Exp $";
 #endif
 
 extern int     fr_check();
@@ -131,14 +131,14 @@ char *argv[];
                        /*
                         * treat both CR and LF as EOL
                         */
-                       if ((s = strchr(line, '\n')))
+                       if ((s = index(line, '\n')))
                                *s = '\0';
-                       if ((s = strchr(line, '\r')))
+                       if ((s = index(line, '\r')))
                                *s = '\0';
                        /*
                         * # is comment marker, everything after is a ignored
                         */
-                       if ((s = strchr(line, '#')))
+                       if ((s = index(line, '#')))
                                *s = '\0';
 
                        if (!*line)
@@ -175,7 +175,7 @@ char *argv[];
        while ((i = (*r->r_readip)(buf, sizeof(buf), &iface, &dir)) > 0) {
                ip->ip_off = ntohs(ip->ip_off);
                ip->ip_len = ntohs(ip->ip_len);
-               switch (fr_check(ip, ip->ip_hl << 2, iface, dir))
+               switch (fr_check(ip, ip->ip_hl << 2, iface, dir)) /* XXX */
                {
                case -1 :
                        (void)printf("block");
index 4545e1b..77d12de 100644 (file)
@@ -4,7 +4,7 @@
  * Redistribution and use in source and binary forms are permitted
  * provided that this notice is preserved and due credit is given
  * to the original author and the contributors.
- * $Id: ipt.h,v 1.2 1996/07/18 04:59:25 dm Exp $
+ * $Id: ipt.h,v 1.3 1997/02/11 22:24:00 kstailey Exp $
  */
 
 #include <fcntl.h>
index 8000582..44f2bae 100644 (file)
@@ -38,8 +38,9 @@
 #include "ipf.h"
 #include "ipt.h"
 
-#ifndef        lint
+#if !defined(lint) && defined(LIBC_SCCS)
 static char    sccsid[] = "@(#)misc.c  1.3 2/4/96 (C) 1995 Darren Reed";
+static char    rcsid[] = "$Id: misc.c,v 1.5 1997/02/11 22:24:01 kstailey Exp $";
 #endif
 
 void   debug(), verbose();
index 5ffb01c..daf5efe 100644 (file)
@@ -4,7 +4,7 @@
  * Redistribution and use in source and binary forms are permitted
  * provided that this notice is preserved and due credit is given
  * to the original author and the contributors.
- * $Id: pcap.h,v 1.3 1996/07/18 04:59:26 dm Exp $
+ * $Id: pcap.h,v 1.4 1997/02/11 22:24:03 kstailey Exp $
  */
 /*
  * This header file is constructed to match the version described by
index e351a1f..ce92eb9 100644 (file)
@@ -8,7 +8,7 @@
 
 /*
  * written to comply with the RFC (1761) from Sun.
- * $Id: snoop.h,v 1.2 1996/07/18 04:59:26 dm Exp $
+ * $Id: snoop.h,v 1.3 1997/02/11 22:24:04 kstailey Exp $
  */
 struct snoophdr        {
        char    s_id[8];
index b6398c6..11ac23a 100644 (file)
@@ -1,43 +1,48 @@
-.LP
 .TH ipmon 8
 .SH NAME
-ipmon - monitors /dev/ipl for logged packets
+ipmon \- monitors /dev/ipl for logged packets
 .SH SYNOPSIS
-ipmon [-sfN] [<filename>]
+.B ipmon
+[
+.B \-sfN
+] [
+<filename>
+]
 .SH DESCRIPTION
 .LP
 \fBipmon\fP opens \fB/dev/ipl\fP for reading and awaits data to be saved from
 the packet filter.  The binary data read from the device is reprinted in
 human readable for, however, IP#'s are not mapped back to hostnames, nor are
 ports mapped back to service names.  The output goes to standard output by
-default or a filename, if given on the command line.  Should the \fB-s\fP
+default or a filename, if given on the command line.  Should the \fB\-s\fP
 option be used, output is instead sent to \fBsyslogd(8)\fP.  Messages sent
 via syslog have the day, month and year removed from the message, but the
 time (including microseconds), as recorded in the log, is still included.
 .SH OPTIONS
 .TP
-.B -s
+.B \-s
 Packet information read in will be sent through syslogd rather than
 saved to a file.  The following levels are used:
-.TP
 .IP
-.RS
-.B LOG_INFO - packets logged using the "log" keyword as the action rather
+.B LOG_INFO
+\- packets logged using the "log" keyword as the action rather
 than pass or block.
-.TP 3
-.B LOG_NOTICE - packets logged which are also passed
-.TP 3
-.B LOG_WARNING - packets logged which are also blocked
-.TP 3
-.B LOG_ERR - packets which have been logged and which can be considered
+.IP
+.B LOG_NOTICE
+\- packets logged which are also passed
+.IP
+.B LOG_WARNING
+\- packets logged which are also blocked
+.IP
+.B LOG_ERR
+\- packets which have been logged and which can be considered
 "short".
-.RE
 .TP
-.B -f
+.B \-f
 Flush the current packet log buffer.  The number of bytes flushed is displayed,
 even should the result be zero.
 .TP
-.B -N
+.B \-N
 IP addresses and port numbers will be mapped, where possible, back into
 hostnames and service names.
 .SH DIAGNOSTICS
index ba827ce..e7a488b 100644 (file)
@@ -11,7 +11,8 @@
 #include <unistd.h>
 #include <fcntl.h>
 #include <string.h>
-#include <sys/syslog.h>
+#include <stdlib.h>
+#include <syslog.h>
 #include <sys/errno.h>
 #include <sys/file.h>
 #include <sys/ioctl.h>
 #include <netinet/ip_icmp.h>
 #include <netdb.h>
 #include <arpa/inet.h>
+#include <ctype.h>
 
-#ifndef        lint
-static char    sccsid[] = "@(#)ipmon.c 1.21 6/5/96 (C)1993-1996 Darren Reed";
-static char    rcsid[] = "$Id: ipmon.c,v 1.6 1996/10/08 07:33:38 niklas Exp $";
+#if !defined(lint) && defined(LIBC_SCCS)
+static char    rcsid[] = "$Id: ipmon.c,v 1.7 1997/02/11 22:24:10 kstailey Exp $";
 #endif
 
 #include "ip_fil_compat.h"
 #include "ip_fil.h"
 
+
 struct flags {
        int     value;
        char    flag;
@@ -61,8 +63,162 @@ struct      flags   tcpfl[] = {
        { 0, '\0' }
 };
 
+
 static char    line[2048];
-static void    printpacket();
+static void    printpacket(), dumphex();
+static int     opts = 0;
+
+#define        OPT_SYSLOG      0x01
+#define        OPT_RESOLVE     0x02
+#define        OPT_HEXBODY     0x04
+#define        OPT_VERBOSE     0x08
+#define        OPT_HEXHDR      0x10
+
+#ifndef        LOGFAC
+#define        LOGFAC  LOG_LOCAL0
+#endif
+
+void printiplci(icp)
+struct ipl_ci *icp;
+{
+       printf("sec %ld usec %ld hlen %d plen %d\n", icp->sec, icp->usec,
+               icp->hlen, icp->plen);
+}
+
+
+void resynclog(fd, iplcp, log)
+int fd;
+struct ipl_ci *iplcp;
+FILE *log;
+{
+       time_t  now;
+       char    *s = NULL;
+       int     len, nr = 0;
+
+       do {
+               if (s) {
+                       s = (char *)&iplcp->sec;
+                       if (opts & OPT_SYSLOG) {
+                               syslog(LOG_INFO, "Sync bytes:");
+                               syslog(LOG_INFO, " %02x %02x %02x %02x",
+                                       *s, *(s+1), *(s+2), *(s+3));
+                               syslog(LOG_INFO, " %02x %02x %02x %02x\n",
+                                       *(s+4), *(s+5), *(s+6), *(s+7));
+                       } else {
+                               fprintf(log, "Sync bytes:");
+                               fprintf(log, " %02x %02x %02x %02x",
+                                       *s, *(s+1), *(s+2), *(s+3));
+                               fprintf(log, " %02x %02x %02x %02x\n",
+                                       *(s+4), *(s+5), *(s+6), *(s+7));
+                       }
+               }
+               do {
+                       s = (char *)&iplcp->sec;
+                       len = sizeof(iplcp->sec);
+                       while (len) {
+                               switch ((nr = read(fd, s, len)))
+                               {
+                               case -1:
+                               case 0:
+                                       return;
+                               default :
+                                       s += nr;
+                                       len -= nr;
+                                       now = time(NULL);
+                                       break;
+                               }
+                       }
+               } while ((now < iplcp->sec) ||
+                        ((iplcp->sec - now) > (86400*5)));
+
+               len = sizeof(iplcp->usec);
+               while (len) {
+                       switch ((nr = read(fd, s, len)))
+                       {
+                       case -1:
+                       case 0:
+                               return;
+                       default :
+                               s += nr;
+                               len -= nr;
+                               break;
+                       }
+               }
+       } while (iplcp->usec > 1000000);
+
+       len = sizeof(*iplcp) - sizeof(iplcp->sec) - sizeof(iplcp->usec);
+       while (len) {
+               switch ((nr = read(fd, s, len)))
+               {
+               case -1:
+               case 0:
+                       return;
+               default :
+                       s += nr;
+                       len -= nr;
+                       break;
+               }
+       }
+}
+
+
+int readlogentry(fd, lenp, buf, bufsize, log)
+int fd, bufsize, *lenp;
+char *buf;
+FILE *log;
+{
+       struct  ipl_ci  *icp = (struct ipl_ci *)buf;
+       time_t  now;
+       char    *s;
+       int     len, n = bufsize, tr = sizeof(struct ipl_ci), nr;
+
+       if (bufsize < tr)
+               return 1;
+       for (s = buf; (n > 0) && (tr > 0); s += nr, n -= nr) {
+               nr = read(fd, s, tr);
+               if (nr > 0)
+                       tr -= nr;
+               else
+                       return -1;
+       }
+
+       now = time(NULL);
+       if ((icp->hlen > 92) || (now < icp->sec) ||
+           ((now - icp->sec) > (86400*5))) {
+               if (opts & OPT_SYSLOG)
+                       syslog(LOG_INFO, "Out of sync! (1,%x)\n", now);
+               else
+                       fprintf(log, "Out of sync! (1,%x)\n", now);
+               dumphex(log, buf, sizeof(struct ipl_ci));
+               resynclog(fd, icp, log);
+       }
+
+
+       len = (int)((u_int)icp->plen);
+       if (len > 128 || len < 0) {
+               if (opts & OPT_SYSLOG)
+                       syslog(LOG_INFO, "Out of sync! (2,%d)\n", len);
+               else
+                       fprintf(log, "Out of sync! (2,%d)\n", len);
+               dumphex(log, buf, sizeof(struct ipl_ci));
+               resynclog(fd, icp, log);
+       }
+
+
+       tr = icp->hlen + icp->plen;
+       if (n < tr)
+               return 1;
+
+       for (; (n > 0) && (tr > 0); s += nr, n-= nr) {
+               nr = read(fd, s, tr);
+               if (nr > 0)
+                       tr -= nr;
+               else
+                       return -1;
+       }
+       *lenp = s - buf;
+       return 0;
+}
 
 
 char   *hostname(res, ip)
@@ -98,39 +254,61 @@ u_short    port;
 }
 
 
-static void    dumphex(log, ip, lp)
+static void    dumphex(log, buf, len)
 FILE   *log;
-struct ip      *ip;
-struct ipl_ci  *lp;
+u_char *buf;
+int    len;
 {
+       char    line[80];
        int     i, j, k;
-       u_char  *s = (u_char *)ip;
+       u_char  *s = buf, *t = (u_char *)line;
 
-       for (i = lp->plen + lp->hlen, j = 0; i; i--, j++, s++) {
-               if (j && !(j & 0xf))
-                       putchar('\n');
-               printf("%02x", *s);
+       for (i = len, j = 0; i; i--, j++, s++) {
+               if (j && !(j & 0xf)) {
+                       *t++ = '\n';
+                       *t = '\0';
+                       fputs(line, stdout);
+                       t = (u_char *)line;
+                       *t = '\0';
+               }
+               sprintf(t, "%02x", *s & 0xff);
+               t += 2;
                if (!((j + 1) & 0xf)) {
-                       s -= 16;
-                       printf("        ");
+                       s -= 15;
+                       sprintf(t, "        ");
+                       t += 8;
                        for (k = 16; k; k--, s++)
-                               putchar(isprint(*s) ? *s : '.');
+                               *t++ = (isprint(*s) ? *s : '.');
+                       s--;
                }
                        
                if ((j + 1) & 0xf)
-                       putchar(' ');
+                       *t++ = ' ';;
        }
 
-       if ((j - 1) & 0xf)
-               putchar('\n');
+       if (j & 0xf) {
+               for (k = 16 - (j & 0xf); k; k--) {
+                       *t++ = ' ';
+                       *t++ = ' ';
+                       *t++ = ' ';
+               }
+               sprintf(t, "       ");
+               t += 7;
+               s -= j & 0xf;
+               for (k = j & 0xf; k; k--, s++)
+                       *t++ = (isprint(*s) ? *s : '.');
+               *t++ = '\n';
+               *t = '\0';
+       }
+       fputs(line, stdout);
+       fflush(stdout);
 }
 
 
-static void    printpacket(log, ip, lp, opts)
+static void    printpacket(log, buf, blen)
 FILE   *log;
-struct ip      *ip;
-struct ipl_ci  *lp;
-int    opts;
+char   *buf;
+int    blen;
 {
        struct  protoent *pr;
        struct  tcphdr  *tp;
@@ -139,24 +317,32 @@ int       opts;
        struct  tm      *tm;
        char    c[3], pname[8], *t, *proto;
        u_short hl, p;
-       int     i, lvl, res, len;
+       int     i, lvl, res;
+#if !SOLARIS && !(defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199603))\
+       && !(defined(OpenBSD) && (OpenBSD <= 1991011) && (OpenBSD >= 199603))
+       int     len;
+#endif
+       struct  ip      *ip;
+       struct  ipl_ci  *lp;
 
-       res = (opts & 2) ? 1 : 0;
+       lp = (struct ipl_ci *)buf;
+       ip = (struct ip *)(buf + sizeof(*lp));
+       res = (opts & OPT_RESOLVE) ? 1 : 0;
        t = line;
        *t = '\0';
        hl = (ip->ip_hl << 2);
        p = (u_short)ip->ip_p;
        tm = localtime((time_t *)&lp->sec);
-       if (!(opts & 1)) {
+       if (!(opts & OPT_SYSLOG)) {
                (void) sprintf(t, "%2d/%02d/%4d ",
                        tm->tm_mday, tm->tm_mon + 1, tm->tm_year + 1900);
                t += strlen(t);
        }
-#if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \
-    (defined(OpenBSD) && (OpenBSD >= 199606))
-       (void) sprintf(t, "%02d:%02d:%02d.%-.6ld %s @%hd ",
+#if SOLARIS || (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199603)) \
+       || (defined(OpenBSD) && (OpenBSD <= 1991011) && (OpenBSD >= 199603))
+       (void) sprintf(t, "%02d:%02d:%02d.%-.6ld %.*s @%hd ",
                tm->tm_hour, tm->tm_min, tm->tm_sec, lp->usec,
-               lp->ifname, lp->rule);
+               (int)sizeof(lp->ifname), lp->ifname, lp->rule);
 #else
        for (len = 0; len < 3; len++)
                if (!lp->ifname[len])
@@ -220,6 +406,12 @@ int        opts;
                                        if (tp->th_flags & tcpfl[i].value)
                                                *t++ = tcpfl[i].flag;
                        }
+                       if (opts & OPT_VERBOSE) {
+                               (void) sprintf(t, " %lu %lu %hu",
+                                       (u_long)tp->th_seq,
+                                       (u_long)tp->th_ack, tp->th_win);
+                               t += strlen(t);
+                       }
                        *t = '\0';
                } else {
                        (void) sprintf(t, "%s -> ", hostname(res, ip->ip_src));
@@ -287,70 +479,107 @@ int      opts;
 
        *t++ = '\n';
        *t++ = '\0';
-       if (opts & 1)
+       if (opts & OPT_SYSLOG)
                syslog(lvl, "%s", line);
        else
                (void) fprintf(log, "%s", line);
+       if (opts & OPT_HEXHDR)
+               dumphex(log, buf, sizeof(struct ipl_ci));
+       if (opts & OPT_HEXBODY)
+               dumphex(log, ip, lp->plen + lp->hlen);
        fflush(log);
-       if (opts & 4)
-               dumphex(log, ip, lp);
 }
 
 int main(argc, argv)
 int argc;
 char *argv[];
 {
-       FILE            *log;
-       int             fd, flushed = 0, opts = 0;
-       u_int           len;
-       char            buf[512], c;
-       struct ipl_ci   iplci;
+       FILE    *log = NULL;
+       int     fd = -1, flushed = 0, doread, n;
+       char    buf[512], c, *iplfile = IPL_NAME;
        extern  int     optind;
+       extern  char    *optarg;
 
-       if ((fd = open(IPL_NAME, O_RDONLY)) == -1) {
-               (void) fprintf(stderr, "%s: ", IPL_NAME);
-               perror("open");
-               exit(-1);
-       }
-
-       while ((c = getopt(argc, argv, "Nfsx")) != -1)
+       while ((c = getopt(argc, argv, "Nf:FsvxX")) != -1)
                switch (c)
                {
                case 'f' :
+                       iplfile = optarg;
+                       break;
+               case 'F' :
+                       if ((fd == -1) &&
+                           (fd = open(iplfile, O_RDWR)) == -1) {
+                               (void) fprintf(stderr, "%s: ", IPL_NAME);
+                               perror("open");
+                               exit(-1);
+                       }
                        if (ioctl(fd, SIOCIPFFB, &flushed) == 0) {
                                printf("%d bytes flushed from log buffer\n",
                                        flushed);
                                fflush(stdout);
-                       }
+                       } else
+                               perror("SIOCIPFFB");
                        break;
                case 'N' :
-                       opts |= 2;
-                       break;
-               case 'x' :
-                       opts |= 4;
+                       opts |= OPT_RESOLVE;
                        break;
                case 's' :
                        openlog(argv[0], LOG_NDELAY|LOG_PID, LOGFAC);
-                       opts |= 1;
+                       opts |= OPT_SYSLOG;
+                       break;
+               case 'v' :
+                       opts |= OPT_VERBOSE;
+                       break;
+               case 'x' :
+                       opts |= OPT_HEXBODY;
+                       break;
+               case 'X' :
+                       opts |= OPT_HEXHDR;
                        break;
                }
 
-       log = argv[optind] ? fopen(argv[1], "a") : stdout;
-       setvbuf(log, NULL, _IONBF, 0);
-       if (flushed)
-               fprintf(log, "%d bytes flushed from log\n", flushed);
-
-       while (1) {
-               assert(read(fd, &iplci, sizeof(struct ipl_ci)) ==
-                       sizeof(struct ipl_ci));
-               assert(iplci.hlen > 0 && iplci.hlen <= 92);
-               len = (u_int)iplci.plen;
-               assert(len <= 128);
-               assert(read(fd, buf, iplci.hlen + iplci.plen) ==
-                       (iplci.hlen + iplci.plen));
-               printpacket(log, buf, &iplci, opts);
+       if ((fd == -1) && (fd = open(iplfile, O_RDONLY)) == -1) {
+               (void) fprintf(stderr, "%s: ", IPL_NAME);
+               perror("open");
+               exit(-1);
+       }
+
+       if (!(opts & OPT_SYSLOG)) {
+               log = argv[optind] ? fopen(argv[optind], "a") : stdout;
+               setvbuf(log, NULL, _IONBF, 0);
        }
-       /* NOTREACHED */
+
+       if (flushed) {
+               if (opts & OPT_SYSLOG)
+                       syslog(LOG_INFO, "%d bytes flushed from log\n",
+                               flushed);
+               else
+                       fprintf(log, "%d bytes flushed from log\n", flushed);
+       }
+
+       for (doread = 1; doread; )
+               switch (readlogentry(fd, &n, buf, sizeof(buf), log))
+               {
+               case -1 :
+                       if (opts & OPT_SYSLOG)
+                               syslog(LOG_ERR, "read: %m\n");
+                       else
+                               perror("read");
+                       doread = 0;
+                       break;
+               case 1 :
+                       if (opts & OPT_SYSLOG)
+                               syslog(LOG_ERR, "aborting logging\n");
+                       else
+                               fprintf(log, "aborting logging\n");
+                       doread = 0;
+                       break;
+               case 2 :
+                       break;
+               case 0 :
+                       printpacket(log, buf, n, opts);
+                       break;
+               }
        exit(0);
        /* NOTREACHED */
 }