diff options
-rw-r--r-- | sbin/ipf/ipf.1 | 24 | ||||
-rw-r--r-- | sbin/ipf/ipf.4 | 91 | ||||
-rw-r--r-- | sbin/ipf/ipf.5 | 131 | ||||
-rw-r--r-- | sbin/ipf/ipf.c | 155 | ||||
-rw-r--r-- | sbin/ipf/ipf.h | 43 | ||||
-rw-r--r-- | sbin/ipf/opt.c | 109 | ||||
-rw-r--r-- | sbin/ipf/parse.c | 174 | ||||
-rw-r--r-- | sbin/ipfstat/fils.c | 233 | ||||
-rw-r--r-- | sbin/ipfstat/ipfstat.8 | 6 | ||||
-rw-r--r-- | sbin/ipfstat/kmem.c | 15 | ||||
-rw-r--r-- | sbin/ipfstat/kmem.h | 22 | ||||
-rw-r--r-- | sbin/ipnat/Makefile | 4 | ||||
-rw-r--r-- | sbin/ipnat/ipnat.1 | 1 | ||||
-rw-r--r-- | sbin/ipnat/ipnat.4 | 6 | ||||
-rw-r--r-- | sbin/ipnat/ipnat.5 | 1 | ||||
-rw-r--r-- | sbin/ipnat/ipnat.c | 270 |
16 files changed, 876 insertions, 409 deletions
diff --git a/sbin/ipf/ipf.1 b/sbin/ipf/ipf.1 index f96a14d0e3c..5efd91b35c6 100644 --- a/sbin/ipf/ipf.1 +++ b/sbin/ipf/ipf.1 @@ -1,4 +1,4 @@ -.\" $OpenBSD: ipf.1,v 1.11 1997/04/09 11:44:25 kstailey Exp $ +.\" $OpenBSD: ipf.1,v 1.12 1998/01/26 04:13:32 dgregor Exp $ .TH IPF 1 .SH NAME ipf \- alters packet filtering lists for IP packet input and output @@ -11,7 +11,7 @@ ipf \- alters packet filtering lists for IP packet input and output <block|pass|nomatch> ] [ .B \-F -<i|o|a> +<i|o|a|s|S> ] .B \-f <\fIfilename\fP> @@ -44,13 +44,21 @@ Disable the filter (if enabled). Not effective for loadable kernel versions. .B \-E Enable the filter (if disabled). Not effective for loadable kernel versions. .TP -.BR \-F \0<param> +.BR \-F \0<i|o|a> 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. .TP +.BR \-F \0<s|S> +To flush entries from the state table, the \fB-F\fP option is used in +conjuction with either "s" (removes state information about any non-fully +established connections) or "S" (deletes the entire state table). Only +one of the two options may be given. A fully established connection +will show up in \fBipfstat -s\fP output as 4/4, with deviations either +way indicating it is not fully established any more. +.TP .BR \-f \0<filename> This option specifies which files \fBipf\fP should use to get input from for modifying the packet filter rule @@ -81,15 +89,15 @@ Remove matching filter rules rather than add them to the internal lists Swap the active filter list in use to be the "other" one. .TP .B \-U -(SOLARIS 2 ONLY) Block packets traveling along the data stream which aren't -recognized as IP packets. They will be printed out on the console. +(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. +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 @@ -102,7 +110,7 @@ affect fragment or state statistics). .SH FILES \fI/usr/share/ipf\fP -- sample configuration files. .SH SEE ALSO -ipfstat(1), ipftest(1), ipf(4), ipf(5) +ipfstat(8), ipftest(1), ipf(5), mkfilters(1) .SH DIAGNOSTICS .PP Needs to be run as root for the packet filtering lists to actually diff --git a/sbin/ipf/ipf.4 b/sbin/ipf/ipf.4 index 48b8787053a..fdec8db3d37 100644 --- a/sbin/ipf/ipf.4 +++ b/sbin/ipf/ipf.4 @@ -1,12 +1,10 @@ -.\" $OpenBSD: ipf.4,v 1.8 1997/04/09 11:44:26 kstailey Exp $ +.\" $OpenBSD: ipf.4,v 1.9 1998/01/26 04:13:33 dgregor Exp $ .TH IPF 4 .SH NAME ipf \- packet filtering kernel interface .SH SYNOPSIS -.nf #include <netinet/ip_fil_compat.h> #include <netinet/ip_fil.h> -.fi .SH IOCTLS .PP To add and delete rules to the filter list, three 'basic' ioctls are provided @@ -45,10 +43,17 @@ which it is inserted is stored in the "fr_hits" field, below. .nf typedef struct frentry { struct frentry *fr_next; + u_short fr_group; /* group to which this rule belongs */ + u_short fr_head; /* group # which this rule starts */ + struct frentry *fr_grp; + int fr_ref; /* reference count - for grouping */ struct ifnet *fr_ifa; - u_long fr_hits; - u_long fr_bytes; /* this is only incremented when a packet */ - /* stops matching on this rule */ + /* + * These are only incremented when a packet matches this rule and + * it is the last match + */ + U_QUAD_T fr_hits; + U_QUAD_T fr_bytes; /* * Fields after this may not change whilst in the kernel. */ @@ -68,6 +73,7 @@ typedef struct frentry { u_short fr_stop; /* top port for <> and >< */ u_short fr_dtop; /* top port for <> and >< */ u_long fr_flags; /* per-rule flags && options (see below) */ + int fr_skip; /* # of rules to skip */ int (*fr_func)(); /* call this function */ char fr_icode; /* return ICMP code */ char fr_ifname[IFNAMSIZ]; @@ -82,30 +88,34 @@ filter list, the number of the rule which it is to be inserted before must be put in the "fr_hits" field (the first rule is number 0). .LP .PP -Flags which are recognized in fr_pass: +Flags which are recognised in fr_pass: .nf - FR_BLOCK 0x00001 /* do not allow packet to pass */ - FR_PASS 0x00002 /* allow packet to pass */ - FR_OUTQUE 0x00004 /* outgoing packets */ - FR_INQUE 0x00008 /* ingoing packets */ - FR_LOG 0x00010 /* Log */ - FR_LOGP 0x00011 /* Log-pass */ - FR_LOGB 0x00012 /* Log-fail */ - FR_LOGBODY 0x00020 /* log the body of packets too */ - FR_LOGFIRST 0x00040 /* log only the first packet to match */ - FR_RETRST 0x00080 /* return a TCP RST packet if blocked */ - FR_RETICMP 0x00100 /* return an ICMP packet if blocked */ - FR_NOMATCH 0x00200 /* no match occurred */ - FR_ACCOUNT 0x00400 /* count packet bytes */ - FR_KEEPFRAG 0x00800 - FR_KEEPSTATE 0x01000 /* keep packet flow state information */ - FR_INACTIVE 0x02000 - FR_QUICK 0x04000 /* quick-match and return */ - FR_FASTROUTE 0x08000 - FR_CALLFUNC 0x10000 - FR_CALLNOW 0x20000 - FR_DUP 0x40000 /* duplicate the packet (not Solaris2) + FR_BLOCK 0x000001 /* do not allow packet to pass */ + FR_PASS 0x000002 /* allow packet to pass */ + FR_OUTQUE 0x000004 /* outgoing packets */ + FR_INQUE 0x000008 /* ingoing packets */ + FR_LOG 0x000010 /* Log */ + FR_LOGP 0x000011 /* Log-pass */ + FR_LOGB 0x000012 /* Log-fail */ + FR_LOGBODY 0x000020 /* log the body of packets too */ + FR_LOGFIRST 0x000040 /* log only the first packet to match */ + FR_RETRST 0x000080 /* return a TCP RST packet if blocked */ + FR__RETICMP 0x000100 /* return an ICMP packet if blocked */ + FR_NOMATCH 0x000200 /* no match occured */ + FR_ACCOUNT 0x000400 /* count packet bytes */ + FR_KEEPFRAG 0x000800 /* keep fragment information */ + FR_KEEPSTATE 0x001000 /* keep `connection' state information */ + FR_INACTIVE 0x002000 + FR_QUICK 0x004000 /* match & stop processing list */ + FR_FASTROUTE 0x008000 /* bypass normal routing */ + FR_CALLNOW 0x010000 /* call another function (fr_func) if matches */ + FR_DUP 0x020000 /* duplicate the packet */ + FR_LOGORBLOCK 0x040000 /* block the packet if it can't be logged */ + FR_NOTSRCIP 0x080000 /* not the src IP# */ + FR_NOTDSTIP 0x100000 /* not the dst IP# */ + FR_AUTH 0x200000 /* use authentication */ + FR_PREAUTH 0x400000 /* require preauthentication */ .fi .PP @@ -126,11 +136,11 @@ comparisons) : .PP The third ioctl, SIOCIPFFL, flushes either the input filter list, the output filter list or both and it returns the number of filters removed -from the list(s). The values which it will take and recognize are FR_INQUE +from the list(s). The values which it will take and recognise are FR_INQUE and FR_OUTQUE (see above). \fBGeneral Logging Flags\fP -There are two flags which can be set to log packets independently of the +There are two flags which can be set to log packets independantly of the rules used. These allow for packets which are either passed or blocked to be logged. To set (and clear)/get these flags, two ioctls are provided: @@ -139,8 +149,10 @@ Takes an unsigned integer as the parameter. The flags are then set to those provided (clearing/setting all in one). .nf - FF_LOGPASS 1 - FF_LOGBLOCK 2 + FF_LOGPASS 0x10000000 + FF_LOGBLOCK 0x20000000 + FF_LOGNOMATCH 0x40000000 + FF_BLOCKNONIP 0x80000000 /* Solaris 2.x only */ .fi .IP SIOCGETFF 16 Takes a pointer to an unsigned integer as the parameter. A copy of the @@ -154,10 +166,14 @@ through the kernel. To retrieve this structure, use this ioctl: ioctl(fd, SIOCGETFS, struct friostat *) -struct friostat { - struct filterstats f_st[2]; - struct frentry *f_fin; - struct frentry *f_fout; +struct friostat { + struct filterstats f_st[2]; + struct frentry *f_fin[2]; + struct frentry *f_fout[2]; + struct frentry *f_acctin[2]; + struct frentry *f_acctout[2]; + struct frentry *f_auth; + int f_active; }; struct filterstats { @@ -177,6 +193,7 @@ 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 */ @@ -185,4 +202,4 @@ struct filterstats { }; .fi .SH SEE ALSO -ipfstat(1), ipf(1), ipf(5) +ipfstat(8), ipf(1), ipf(5) diff --git a/sbin/ipf/ipf.5 b/sbin/ipf/ipf.5 index 6bb78204762..f036affb88b 100644 --- a/sbin/ipf/ipf.5 +++ b/sbin/ipf/ipf.5 @@ -1,11 +1,11 @@ -.\" $OpenBSD: ipf.5,v 1.9 1997/07/14 01:21:41 angelos Exp $ +.\" $OpenBSD: ipf.5,v 1.10 1998/01/26 04:13:34 dgregor Exp $ .TH IPF 5 .SH NAME ipf \- IP packet filter rule syntax .SH DESCRIPTION .PP A rule file for \fBipf\fP may have any name or even be stdin. As -\fBipfstat\fP produces parsable rules as output when displaying the internal +\fBipfstat\fP produces parseable rules as output when displaying the internal kernel filter lists, it is quite plausible to use its output to feed back into \fBipf\fP. Thus, to remove all filters on input packets, the following could be done: @@ -19,27 +19,26 @@ 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 ] [ match ] [ keep ] +filter-rule = [ insert ] action in-out [ options ] [ tos ] [ ttl ] + [ proto ] [ ip ] [ group ]. insert = "@" decnumber . -action = block | "pass" | log | "count" | call . +action = block | "pass" | log | "count" | skip | auth | call . in-out = "in" | "out" . options = [ log ] [ "quick" ] [ "on" interface-name [ dup ] [ froute ] ] . -match = [ tos ] [ ttl ] [ proto ] [ ip ] . -keep = "keep state" | "keep frags" . +tos = "tos" decnumber | "tos" hexnumber . +ttl = "ttl" decnumber . +proto = "proto" protocol . +ip = srcdst [ flags ] [ with withopt ] [ icmp ] [ keep ] . +group = [ "head" decnumber ] [ "group" decnumber ] . 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] . +auth = "auth" | "preauth" . +log = "log" [ "body" ] [ "first" ] [ "or-block" ] . +call = "call" [ "now" ] function-name . +skip = "skip" decnumber . +dup = "dup-to" interface-name[":"ipaddr] . froute = "fastroute" | "to" interface-name . - -tos = "tos" decnumber | "tos" hexnumber . -ttl = "ttl" decnumber . -proto = "proto" protocol . -ip = srcdst [ flags ] [ with withopt ] [ icmp ] [ keep ] . - protocol = "tcp/udp" | "udp" | "tcp" | "icmp" | decnumber . srcdst = "all" | fromto . fromto = "from" object "to" object . @@ -48,11 +47,11 @@ object = addr [ port-comp | port-range ] . addr = "any" | nummask | host-name [ "mask" ipaddr | "mask" hexnumber ] . port-comp = "port" compare port-num . port-range = "port" port-num range port-num . - flags = "flags" flag { flag } [ "/" flag { flag } ] . with = "with" | "and" . icmp = "icmp-type" icmp-type [ "code" decnumber ] . return-code = "("icmp-code")" . +keep = "keep" "state" | "keep" "frags" . nummask = host-name [ "/" decnumber ] . host-name = ipaddr | hostname | "any" . @@ -70,19 +69,19 @@ seclvl = "unclass" | "confid" | "reserv-1" | "reserv-2" | "reserv-3" | icmp-type = "unreach" | "echo" | "echorep" | "squench" | "redir" | "timex" | "paramprob" | "timest" | "timestrep" | "inforeq" | "inforep" | "maskreq" | "maskrep" | decnumber . -icmp-code = decnumber | "net-unr" | "host-unr" | "proto-unr" | "port-unr" | +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" . +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" . +compare = "=" | "!=" | "<" | ">" | "<=" | ">=" | "eq" | "ne" | "lt" | + "gt" | "le" | "ge" . range = "<>" | "><" . hexdigit = digit | "a" | "b" | "c" | "d" | "e" | "f" . digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" . @@ -96,18 +95,9 @@ not make sense (such as tcp \fBflags\fP for non-TCP packets). .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 are supposed to be the same as, but currently differ from: -.\" XXX How, why do they differ?? -.nf block in all - pass in from any to any - log in all + pass in all + log out all count in all .fi .PP @@ -154,6 +144,12 @@ must conform to a specific calling interface. Customized actions and semantics can thus be implemented to supplement those available. This feature is for use by knowledgeable hackers, and is not currently documented. +.TP +.B "skip <n>" +.TP +.B auth +.TP +.B preauth .PP 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 @@ -222,7 +218,6 @@ 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. -.\" XXX TOS mask?? not in grammar! .TP .B ttl packets may also be selected by their Time-To-Live value. The value given in @@ -278,7 +273,10 @@ 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. +port ranges may be specified. When the port appears as part of the +\fBfrom\fP object, it matches the source port number, when it appears +as part of the \fBto\fP object, it matches the destination port number. +See the examples for more information. .PP The \fBall\fP keyword is essentially a synonym for "from any to any" with no other match parameters. @@ -354,8 +352,9 @@ 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 historical information for that packet, and what sort to keep. The following information can be kept: +The second last parameter which can be set for a filter rule is whether on not +to 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 @@ -367,6 +366,23 @@ fragments. .PP allowing packets which match these to flow straight through, rather than going through the access control list. +.SH GROUPS +The last pair of parameters control filter rule "grouping". By default, all +filter rules are placed in group 0 if no other group is specified. To add a +rule to a non-default group, the group must first be started by creating a +group \fIhead\fP. If a packet matches a rule which is the \fIhead\fP of a +group, the filter processing then switches to the group, using that rule as +the default for the group. If \fBquick\fP is used with a \fBhead\fP rule, rule +processing isn't stopped until it has returned from processing the group. +.PP +A rule may be both the head for a new group and a member of a non-default +group (\fBhead\fP and \fBgroup\fP may be used together in a rule). +.TP +.B "head <n>" +indicates that a new group (number n) should be created. +.TP +.B "group <n>" +indicates that the rule should be put in group (number n) rather than group 0. .SH LOGGING .PP When a packet is logged, with either the \fBlog\fP action or option, @@ -425,7 +441,42 @@ rule such as: pass in quick from any to any port < 1024 .fi .PP -would be needed before the first block. +would be needed before the first block. To create a new group for +processing all inbould packets on le0/le1/lo0, with the default being to block +all inbound packets, we would do something like: +.LP +.nf + block in all + block in on le0 quick all head 100 + block in on le1 quick all head 200 + block in on lo0 quick all head 300 +.fi +.PP + +and to then allow ICMP packets in on le0, only, we would do: +.LP +.nf + pass in proto icmp all group 100 +.fi +.PP +Note that because only inbound packets on le0 are used processed by group 100, +there is no need to respecify the interface name. Likewise, we could further +breakup processing of TCP, etc, as follows: +.LP +.nf + block in proto tcp all head 110 group 100 + pass in from any to any port = 23 group 110 +.fi +.PP +and so on. The last line, if written without the groups would be: +.LP +.nf + pass in on le0 proto tcp from any to any port = telnet +.fi +.PP +Note, that if we wanted to say "port = telnet", "proto tcp" would +need to be specified as the parser interprets each rule on its own and +qualifies all service/port names with the protocol specified. .SH FILES \fI/etc/services\fP -- port names .br @@ -433,4 +484,4 @@ would be needed before the first block. .br \fI/usr/share/ipf\fP -- sample configuration files .SH SEE ALSO -ipf(1), ipftest(1), ipf(4), hosts(5), services(5) +ipf(1), ipftest(1), mkfilters(1), ipmon(8), ipf(4), hosts(5), services(5) diff --git a/sbin/ipf/ipf.c b/sbin/ipf/ipf.c index 260fc731a1d..e1fba7a31db 100644 --- a/sbin/ipf/ipf.c +++ b/sbin/ipf/ipf.c @@ -1,11 +1,14 @@ -/* $OpenBSD: ipf.c,v 1.10 1997/02/26 04:35:39 kstailey Exp $ */ +/* $OpenBSD: ipf.c,v 1.11 1998/01/26 04:13:35 dgregor Exp $ */ /* - * (C)opyright 1993,1994,1995 by Darren Reed. + * Copyright (C) 1993-1997 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. */ +#ifdef __FreeBSD__ +# include <osreldate.h> +#endif #include <stdio.h> #include <unistd.h> #include <string.h> @@ -14,65 +17,75 @@ #if !defined(__SVR4) && !defined(__GNUC__) #include <strings.h> #endif -#if !defined(__SVR4) && defined(__GNUC__) && !defined(__OpenBSD__) -extern char *index(); -#endif #include <sys/types.h> #include <sys/param.h> #include <sys/file.h> #include <stdlib.h> -#include <unistd.h> #include <stddef.h> #include <sys/socket.h> #include <sys/ioctl.h> #include <netinet/in.h> #include <netinet/in_systm.h> +#include <sys/time.h> #include <net/if.h> +#if __FreeBSD_version >= 300000 +# include <net/if_var.h> +#endif #include <netinet/ip.h> -#include "ip_fil_compat.h" -#include "ip_fil.h" #include <netdb.h> #include <arpa/nameser.h> #include <resolv.h> +#include "ip_fil_compat.h" +#include "ip_fil.h" #include "ipf.h" -#if !defined(lint) && defined(LIBC_SCCS) -static char sccsid[] = "@(#)ipf.c 1.23 6/5/96 (C) 1993-1995 Darren Reed"; -static char rcsid[] = "$DRId: ipf.c,v 2.0.1.2 1997/02/04 14:37:46 darrenr Exp $"; +#if !defined(lint) +static const char sccsid[] = "@(#)ipf.c 1.23 6/5/96 (C) 1993-1995 Darren Reed"; +static const char rcsid[] = "@(#)$Id: ipf.c,v 1.11 1998/01/26 04:13:35 dgregor Exp $"; #endif +static void frsync __P((void)); #if SOLARIS -void frsync(), blockunknown(); +static void blockunknown __P((void)); +#endif +#if !defined(__SVR4) && defined(__GNUC__) +extern char *index __P((const char *, int)); #endif -void zerostats(); extern char *optarg; +void zerostats __P((void)); +int main __P((int, char *[])); + int opts = 0; static int fd = -1; -static void procfile(), flushfilter(), set_state(); -static void packetlogon(), swapactive(), showstats(); -static char *getline(); +static void procfile __P((char *, char *)), flushfilter __P((char *)); +static void set_state __P((u_int)), showstats __P((friostat_t *)); +static void packetlogon __P((char *)), swapactive __P((void)); +static int opendevice __P((char *)); +static void closedevice __P((void)); +static char *getline __P((char *, size_t, FILE *)); +static char *ipfname = IPL_NAME; int main(argc,argv) int argc; char *argv[]; { - char c; + int c; - while ((c = getopt(argc, argv, "AdDEf:F:Il:noprsUvyzZ")) != -1) { + while ((c = getopt(argc, argv, "AdDEf:F:Il:noPrsUvyzZ")) != -1) { switch (c) { + case 'A' : + opts &= ~OPT_INACTIVE; + break; case 'E' : - set_state(1); + set_state((u_int)1); break; case 'D' : - set_state(0); - break; - case 'A' : - opts &= ~OPT_INACTIVE; + set_state((u_int)0); break; case 'd' : opts |= OPT_DEBUG; @@ -95,8 +108,8 @@ char *argv[]; case 'o' : opts |= OPT_OUTQUE; break; - case 'p' : - opts |= OPT_PRINTFR; + case 'P' : + ipfname = IPL_AUTH; break; case 'r' : opts |= OPT_REMOVE; @@ -112,11 +125,9 @@ char *argv[]; case 'v' : opts |= OPT_VERBOSE; break; -#if SOLARIS case 'y' : frsync(); break; -#endif case 'z' : opts |= OPT_ZERORULEST; break; @@ -134,23 +145,34 @@ char *argv[]; } -static int opendevice() +static int opendevice(ipfdev) +char *ipfdev; { if (opts & OPT_DONOTHING) return -2; + if (!ipfdev) + ipfdev = ipfname; + if (!(opts & OPT_DONOTHING) && fd == -1) - if ((fd = open(IPL_NAME, O_RDWR)) == -1) - if ((fd = open(IPL_NAME, O_RDONLY)) == -1) + if ((fd = open(ipfdev, O_RDWR)) == -1) + if ((fd = open(ipfname, O_RDONLY)) == -1) perror("open device"); return fd; } +static void closedevice() +{ + close(fd); + fd = -1; +} + + static void set_state(enable) u_int enable; { - if (opendevice() != -2) + if (opendevice(ipfname) != -2) if (ioctl(fd, SIOCFRENB, &enable) == -1) perror("SIOCFRENB"); return; @@ -164,7 +186,7 @@ char *name, *file; struct frentry *fr; u_int add = SIOCADAFR, del = SIOCRMAFR; - (void) opendevice(); + (void) opendevice(ipfname); if (opts & OPT_INACTIVE) { add = SIOCADIFR; @@ -187,14 +209,14 @@ char *name, *file; /* * 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) @@ -210,9 +232,11 @@ char *name, *file; if (opts & OPT_ZERORULEST) add = SIOCZRLST; else if (opts & OPT_INACTIVE) - add = fr->fr_hits ? SIOCINIFR : SIOCADIFR; + add = (u_int)fr->fr_hits ? SIOCINIFR : + SIOCADIFR; else - add = fr->fr_hits ? SIOCINAFR : SIOCADAFR; + add = (u_int)fr->fr_hits ? SIOCINAFR : + SIOCADAFR; if (fr->fr_hits) fr->fr_hits--; if (fr && (opts & OPT_VERBOSE)) @@ -228,7 +252,11 @@ char *name, *file; if (ioctl(fd, add, fr) == -1) perror("ioctl(SIOCZRLST)"); else { +#ifdef USE_QUAD_T + printf("hits %qd bytes %qd ", +#else printf("hits %ld bytes %ld ", +#endif fr->fr_hits, fr->fr_bytes); printfr(fr); } @@ -254,14 +282,17 @@ size_t size; FILE *file; { register char *p; + register int len; do { - for (p = str;; p+= strlen(p) - 1) { + for (p = str; ; p += strlen(p) - 1) { if (!fgets(p, size, file)) return(NULL); - p[strlen(p) -1] = '\0'; - if (p[strlen(p) - 1] != '\\') + len = strlen(p); + p[len - 1] = '\0'; + if (p[len - 1] != '\\') break; + size -= len; } } while (*str == '\0' || *str == '\n'); return(str); @@ -282,23 +313,23 @@ char *opt; flag &= ~(FF_LOGPASS|FF_LOGNOMATCH|FF_LOGBLOCK); - if (strchr(opt, 'p')) { + if (index(opt, 'p')) { flag |= FF_LOGPASS; if (opts & OPT_VERBOSE) printf("set log flag: pass\n"); } - if (strchr(opt, 'm') && (*opt == 'n' || *opt == 'N')) { + if (index(opt, 'm') && (*opt == 'n' || *opt == 'N')) { flag |= FF_LOGNOMATCH; if (opts & OPT_VERBOSE) printf("set log flag: nomatch\n"); } - if (strchr(opt, 'b') || strchr(opt, 'd')) { + if (index(opt, 'b') || index(opt, 'd')) { flag |= FF_LOGBLOCK; if (opts & OPT_VERBOSE) printf("set log flag: block\n"); } - if (opendevice() != -2 && (err = ioctl(fd, SIOCSETFF, &flag))) + if (opendevice(ipfname) != -2 && (err = ioctl(fd, SIOCSETFF, &flag))) perror("ioctl(SIOCSETFF)"); if ((opts & (OPT_DONOTHING|OPT_VERBOSE)) == OPT_VERBOSE) { @@ -317,6 +348,24 @@ char *arg; if (!arg || !*arg) return; + if (!strcmp(arg, "s") || !strcmp(arg, "S")) { + if (*arg == 'S') + fl = 0; + else + fl = 1; + rem = fl; + + closedevice(); + if (opendevice(IPL_STATE) != -2 && + ioctl(fd, SIOCIPFFL, &fl) == -1) + perror("ioctl(SIOCIPFFL)"); + if ((opts & (OPT_DONOTHING|OPT_VERBOSE)) == OPT_VERBOSE) { + printf("remove flags %s (%d)\n", arg, rem); + printf("removed %d filter rules\n", fl); + } + closedevice(); + return; + } if (strchr(arg, 'i') || strchr(arg, 'I')) fl = FR_INQUE; if (strchr(arg, 'o') || strchr(arg, 'O')) @@ -326,7 +375,7 @@ char *arg; fl |= (opts & FR_INACTIVE); rem = fl; - if (opendevice() != -2 && ioctl(fd, SIOCIPFFL, &fl) == -1) + if (opendevice(ipfname) != -2 && ioctl(fd, SIOCIPFFL, &fl) == -1) perror("ioctl(SIOCIPFFL)"); if ((opts & (OPT_DONOTHING|OPT_VERBOSE)) == OPT_VERBOSE) { printf("remove flags %s%s (%d)\n", (rem & FR_INQUE) ? "I" : "", @@ -341,29 +390,27 @@ static void swapactive() { int in = 2; - if (opendevice() != -2 && ioctl(fd, SIOCSWAPA, &in) == -1) + if (opendevice(ipfname) != -2 && ioctl(fd, SIOCSWAPA, &in) == -1) perror("ioctl(SIOCSWAPA)"); else printf("Set %d now inactive\n", in); } -#if defined(sun) && (defined(__SVR4) || defined(__svr4__)) -void frsync() +static void frsync() { - if (opendevice() != -2 && ioctl(fd, SIOCFRSYN, 0) == -1) + if (opendevice(ipfname) != -2 && ioctl(fd, SIOCFRSYN, 0) == -1) perror("SIOCFRSYN"); else printf("filter sync'd\n"); } -#endif void zerostats() { friostat_t fio; - if (opendevice() != -2) { + if (opendevice(ipfname) != -2) { if (ioctl(fd, SIOCFRZST, &fio) == -1) { perror("ioctl(SIOCFRZST)"); exit(-1); @@ -407,11 +454,11 @@ friostat_t *fp; #if SOLARIS -void blockunknown() +static void blockunknown() { int flag; - if (opendevice() == -1) + if (opendevice(ipfname) == -1) return; if ((opts & (OPT_DONOTHING|OPT_VERBOSE)) == OPT_VERBOSE) { @@ -423,7 +470,7 @@ void blockunknown() flag ^= FF_BLOCKNONIP; - if (opendevice() != -2 && ioctl(fd, SIOCSETFF, &flag)) + if (opendevice(ipfname) != -2 && ioctl(fd, SIOCSETFF, &flag)) perror("ioctl(SIOCSETFF)"); if ((opts & (OPT_DONOTHING|OPT_VERBOSE)) == OPT_VERBOSE) { diff --git a/sbin/ipf/ipf.h b/sbin/ipf/ipf.h index 7980f227692..afd65120faf 100644 --- a/sbin/ipf/ipf.h +++ b/sbin/ipf/ipf.h @@ -1,14 +1,18 @@ +/* $OpenBSD: ipf.h,v 1.8 1998/01/26 04:13:36 dgregor Exp $ */ /* - * (C)opyright 1993-1996 by Darren Reed. + * Copyright (C) 1993-1997 by Darren Reed. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and due credit is given * to the original author and the contributors. * * @(#)ipf.h 1.12 6/5/96 - * $DRId: ipf.h,v 2.0.1.1 1997/01/09 15:14:43 darrenr Exp $ + * $Id: ipf.h,v 1.8 1998/01/26 04:13:36 dgregor Exp $ */ +#ifndef __IPF_H__ +#define __IPF_H__ + #ifndef SOLARIS #define SOLARIS (defined(sun) && (defined(__svr4__) || defined(__SVR4))) #endif @@ -29,17 +33,29 @@ #define OPT_SHOWLINENO 0x04000 #define OPT_PRINTFR 0x08000 #define OPT_ZERORULEST 0x10000 +#define OPT_SAVEOUT 0x20000 +#define OPT_AUTHSTATS 0x40000 +#define OPT_RAW 0x80000 -extern struct frentry *parse(); - -extern void printfr(), binprint(), initparse(); +#ifndef __P +# ifdef __STDC__ +# define __P(x) x +# else +# define __P(x) () +# endif +#endif -#if defined(__SVR4) || defined(__svr4__) -#define index strchr -#define bzero(a,b) memset(a, 0, b) -#define bcopy(a,b,c) memmove(b,a,c) +#ifdef ultrix +extern char *strdup __P((char *)); #endif +extern struct frentry *parse __P((char *)); + +extern void printfr __P((struct frentry *)); +extern void binprint __P((struct frentry *)), initparse __P((void)); +extern u_short portnum __P((char *)); + + struct ipopt_names { int on_value; int on_bit; @@ -48,10 +64,12 @@ struct ipopt_names { }; -extern u_long hostnum(), optname(); -extern void printpacket(); +extern u_32_t buildopts __P((char *, char *, int)); +extern u_32_t hostnum __P((char *, int *)); +extern u_32_t optname __P((char ***, u_short *)); +extern void printpacket __P((ip_t *)); #if SOLARIS -extern int inet_aton(); +extern int inet_aton __P((const char *, struct in_addr *)); #endif #ifdef sun @@ -65,3 +83,4 @@ extern char *sys_errlist[]; #define MIN(a,b) ((a) > (b) ? (b) : (a)) #endif +#endif /* __IPF_H__ */ diff --git a/sbin/ipf/opt.c b/sbin/ipf/opt.c index 3f0da9f0274..1e65c9bd0e0 100644 --- a/sbin/ipf/opt.c +++ b/sbin/ipf/opt.c @@ -1,6 +1,6 @@ -/* $OpenBSD: opt.c,v 1.7 1997/06/23 17:11:28 kstailey Exp $ */ +/* $OpenBSD: opt.c,v 1.8 1998/01/26 04:13:37 dgregor Exp $ */ /* - * (C)opyright 1993,1994,1995 by Darren Reed. + * Copyright (C) 1993-1997 by Darren Reed. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and due credit is given @@ -8,23 +8,27 @@ */ #include <stdio.h> #include <string.h> +#include <stdlib.h> #include <sys/types.h> #include <sys/time.h> #include <sys/socket.h> #include <netinet/in.h> #include <netinet/in_systm.h> #include <netinet/ip.h> +#ifndef linux #include <netinet/ip_var.h> +#endif #include <netinet/tcp.h> -#include <netinet/tcpip.h> #include <net/if.h> +#include <arpa/inet.h> #include "ip_fil_compat.h" +#include <netinet/tcpip.h> #include "ip_fil.h" #include "ipf.h" -#ifndef lint -static char sccsid[] = "@(#)opt.c 1.8 4/10/96 (C) 1993-1995 Darren Reed"; -static char rcsid[] = "$DRId: opt.c,v 2.0.1.1 1997/01/09 15:14:44 darrenr Exp $"; +#if !defined(lint) +static const char sccsid[] = "@(#)opt.c 1.8 4/10/96 (C) 1993-1995 Darren Reed"; +static const char rcsid[] = "@(#)$Id: opt.c,v 1.8 1998/01/26 04:13:37 dgregor Exp $"; #endif extern int opts; @@ -66,6 +70,9 @@ struct ipopt_names secclass[] = { }; +static u_char seclevel __P((char *)); +int addipopt __P((char *, struct ipopt_names *, int, char *)); + static u_char seclevel(slevel) char *slevel; { @@ -83,14 +90,70 @@ char *slevel; } -u_long buildopts(cp, op) +int addipopt(op, io, len, class) +char *op; +struct ipopt_names *io; +int len; +char *class; +{ + int olen = len; + struct in_addr ipadr; + u_short val; + u_char lvl; + char *s; + + if ((len + io->on_siz) > 48) { + fprintf(stderr, "options too long\n"); + return 0; + } + len += io->on_siz; + *op++ = io->on_value; + if (io->on_siz > 1) { + s = op; + *op++ = io->on_siz; + *op++ = IPOPT_MINOFF; + + if (class) { + switch (io->on_value) + { + case IPOPT_SECURITY : + lvl = seclevel(class); + *(op - 1) = lvl; + break; + case IPOPT_LSRR : + case IPOPT_SSRR : + ipadr.s_addr = inet_addr(class); + s[IPOPT_OLEN] = IPOPT_MINOFF - 1 + 4; + bcopy((char *)&ipadr, op, sizeof(ipadr)); + break; + case IPOPT_SATID : + val = atoi(class); + bcopy((char *)&val, op, 2); + break; + } + } + + op += io->on_siz - 3; + if (len & 3) { + *op++ = IPOPT_NOP; + len++; + } + } + if (opts & OPT_DEBUG) + fprintf(stderr, "bo: %s %d %#x: %d\n", + io->on_name, io->on_value, io->on_bit, len); + return len - olen; +} + + +u_32_t buildopts(cp, op, len) char *cp, *op; +int len; { struct ipopt_names *io; - u_char lvl; - u_long msk = 0; + u_32_t msk = 0; char *s, *t; - int len = 0; + int inc; for (s = strtok(cp, ","); s; s = strtok(NULL, ",")) { if ((t = strchr(s, '='))) @@ -98,30 +161,10 @@ char *cp, *op; for (io = ionames; io->on_name; io++) { if (strcasecmp(s, io->on_name) || (msk & io->on_bit)) continue; - if ((len + io->on_siz) > 48) { - fprintf(stderr, "options too long\n"); - return 0; - } - len += io->on_siz; - *op++ = io->on_value; - if (io->on_siz > 1) { - *op++ = io->on_siz; - *op++ = IPOPT_MINOFF; - - if (t && !strcasecmp(s, "sec-class")) { - lvl = seclevel(t); - *(op - 1) = lvl; - } - op += io->on_siz - 3; - if (len & 3) { - *op++ = IPOPT_NOP; - len++; - } + if ((inc = addipopt(op, io, len, t))) { + op += inc; + len += inc; } - if (opts & OPT_DEBUG) - fprintf(stderr, "bo: %s %d %#x: %d\n", - io->on_name, io->on_value, - io->on_bit, len); msk |= io->on_bit; break; } diff --git a/sbin/ipf/parse.c b/sbin/ipf/parse.c index 1420d5745d1..da8817a4923 100644 --- a/sbin/ipf/parse.c +++ b/sbin/ipf/parse.c @@ -1,6 +1,6 @@ -/* $OpenBSD: parse.c,v 1.17 1997/11/24 03:25:29 deraadt Exp $ */ +/* $OpenBSD: parse.c,v 1.18 1998/01/26 04:13:38 dgregor Exp $ */ /* - * (C)opyright 1993-1996 by Darren Reed. + * Copyright (C) 1993-1997 by Darren Reed. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and due credit is given @@ -8,13 +8,14 @@ */ #include <stdio.h> #include <string.h> +#include <sys/types.h> #if !defined(__SVR4) && !defined(__svr4__) #include <strings.h> #else #include <sys/byteorder.h> #endif -#include <sys/types.h> #include <sys/param.h> +#include <sys/time.h> #include <stdlib.h> #include <unistd.h> #include <stddef.h> @@ -24,31 +25,41 @@ #include <netinet/ip.h> #include <netinet/tcp.h> #include <net/if.h> -#include "ip_fil_compat.h" -#include "ip_fil.h" #include <netdb.h> #include <arpa/nameser.h> #include <arpa/inet.h> #include <resolv.h> -#include "ipf.h" #include <ctype.h> +#include "ip_fil_compat.h" +#include "ip_fil.h" +#include "ipf.h" -#if !defined(lint) && defined(LIBC_SCCS) -static char sccsid[] ="@(#)parse.c 1.44 6/5/96 (C) 1993-1996 Darren Reed"; -static char rcsid[] = "$DRId: parse.c,v 2.0.1.4 1997/03/20 15:49:25 darrenr Exp $"; +#if !defined(lint) +static const char sccsid[] ="@(#)parse.c 1.44 6/5/96 (C) 1993-1996 Darren Reed"; +static const char rcsid[] = "@(#)$Id: parse.c,v 1.18 1998/01/26 04:13:38 dgregor Exp $"; #endif extern struct ipopt_names ionames[], secclass[]; extern int opts; -extern int gethostname(); -u_long hostnum(), optname(); -u_short portnum(); -u_char tcp_flags(); -struct frentry *parse(); -void binprint(), printfr(); -int addicmp(), extras(), hostmask(), ports(), icmpcode(), addkeep(); -int to_interface(); +u_short portnum __P((char *)); +u_char tcp_flags __P((char *, u_char *)); +int addicmp __P((char ***, struct frentry *)); +int extras __P((char ***, struct frentry *)); +char ***seg; +u_long *sa, *msk; +u_short *pp, *tp; +u_char *cp; + +int hostmask __P((char ***, u_32_t *, u_32_t *, u_short *, u_char *, + u_short *)); +int ports __P((char ***, u_short *, u_char *, u_short *)); +int icmpcode __P((char *)), addkeep __P((char ***, struct frentry *)); +int to_interface __P((frdest_t *, char *)); +void print_toif __P((char *, frdest_t *)); +void optprint __P((u_short, u_short, u_long, u_long)); +int countbits __P((u_long)); +char *portname __P((int, int)); char *proto = NULL; @@ -102,32 +113,45 @@ char *line; cpp = cps; if (**cpp == '@') - fil.fr_hits = atoi(*cpp++ + 1) + 1; + fil.fr_hits = (U_QUAD_T)atoi(*cpp++ + 1) + 1; + if (!strcasecmp("block", *cpp)) { - fil.fr_flags = FR_BLOCK; + fil.fr_flags |= FR_BLOCK; if (!strncasecmp(*(cpp+1), "return-icmp", 11)) { fil.fr_flags |= FR_RETICMP; cpp++; if (*(*cpp + 11) == '(') { - fil.fr_icode = icmpcode(*cpp + 12); - if (fil.fr_icode == -1) { + i = icmpcode(*cpp + 12); + if (i == -1) { fprintf(stderr, - "unrecognized icmp code %s\n", + "uncrecognised icmp code %s\n", *cpp + 12); return NULL; } + fil.fr_icode = i; } } else if (!strncasecmp(*(cpp+1), "return-rst", 10)) { fil.fr_flags |= FR_RETRST; cpp++; } } else if (!strcasecmp("count", *cpp)) { - fil.fr_flags = FR_ACCOUNT; + fil.fr_flags |= FR_ACCOUNT; } else if (!strcasecmp("pass", *cpp)) { - fil.fr_flags = FR_PASS; + fil.fr_flags |= FR_PASS; + } else if (!strcasecmp("auth", *cpp)) { + fil.fr_flags |= FR_AUTH; + } else if (!strcasecmp("preauth", *cpp)) { + fil.fr_flags |= FR_PREAUTH; + } else if (!strcasecmp("skip", *cpp)) { + cpp++; + if (!isdigit(**cpp)) { + (void)fprintf(stderr, "integer must follow skip\n"); + return NULL; + } + fil.fr_skip = atoi(*cpp); } else if (!strcasecmp("log", *cpp)) { - fil.fr_flags = FR_LOG; + fil.fr_flags |= FR_LOG; if (!strcasecmp(*(cpp+1), "body")) { fil.fr_flags |= FR_LOGBODY; cpp++; @@ -316,8 +340,13 @@ char *line; return NULL; } ch = 0; - if (hostmask(&cpp, &fil.fr_src, &fil.fr_smsk, - &fil.fr_sport, &ch, &fil.fr_stop)) { + if (**cpp == '!') { + fil.fr_flags |= FR_NOTSRCIP; + (*cpp)++; + } + if (hostmask(&cpp, (u_32_t *)&fil.fr_src, + (u_32_t *)&fil.fr_smsk, &fil.fr_sport, &ch, + &fil.fr_stop)) { (void)fprintf(stderr, "bad host (%s)\n", *cpp); return NULL; } @@ -340,8 +369,13 @@ char *line; return NULL; } ch = 0; - if (hostmask(&cpp, &fil.fr_dst, &fil.fr_dmsk, - &fil.fr_dport, &ch, &fil.fr_dtop)) { + if (**cpp == '!') { + fil.fr_flags |= FR_NOTDSTIP; + (*cpp)++; + } + if (hostmask(&cpp, (u_32_t *)&fil.fr_dst, + (u_32_t *)&fil.fr_dmsk, &fil.fr_dport, &ch, + &fil.fr_dtop)) { (void)fprintf(stderr, "bad host (%s)\n", *cpp); return NULL; } @@ -405,6 +439,30 @@ char *line; return NULL; /* + * head of a new group ? + */ + if (*cpp && !strcasecmp(*cpp, "head")) { + if (!*++cpp) { + (void)fprintf(stderr, "head without group #\n"); + return NULL; + } + fil.fr_grhead = atoi(*cpp); + cpp++; + } + + /* + * head of a new group ? + */ + if (*cpp && !strcasecmp(*cpp, "group")) { + if (!*++cpp) { + (void)fprintf(stderr, "group without group #\n"); + return NULL; + } + fil.fr_group = atoi(*cpp); + cpp++; + } + + /* * leftovers...yuck */ if (*cpp && **cpp) { @@ -418,7 +476,8 @@ char *line; /* * lazy users... */ - if (!fil.fr_proto && (fil.fr_dcmp || fil.fr_scmp || fil.fr_tcpf)) { + if (!fil.fr_proto && !(fil.fr_ip.fi_fl & FI_TCPUDP) && + (fil.fr_dcmp || fil.fr_scmp || fil.fr_tcpf)) { (void)fprintf(stderr, "no protocol given for TCP/UDP comparisons\n"); return NULL; @@ -442,7 +501,7 @@ char *to; int r = 0; char *s; - s = strchr(to, ':'); + s = index(to, ':'); fdp->fd_ifp = NULL; if (s) { *s++ = '\0'; @@ -474,7 +533,7 @@ frdest_t *fdp; */ int hostmask(seg, sa, msk, pp, cp, tp) char ***seg; -u_long *sa, *msk; +u_32_t *sa, *msk; u_short *pp, *tp; u_char *cp; { @@ -484,13 +543,13 @@ u_char *cp; /* * is it possibly hostname/num ? */ - if ((s = strchr(**seg, '/'))) { + if ((s = index(**seg, '/')) || (s = index(**seg, ':'))) { *s++ = '\0'; if (!isdigit(*s)) return -1; - if (strchr(s, '.')) + if (index(s, '.')) *msk = inet_addr(s); - if (!strchr(s, '.') && !strchr(s, 'x')) { + if (!index(s, '.') && !index(s, 'x')) { /* * set x most significant bits */ @@ -542,7 +601,7 @@ u_char *cp; * returns an ip address as a long var as a result of either a DNS lookup or * straight inet_addr() call */ -u_long hostnum(host, resolved) +u_32_t hostnum(host, resolved) char *host; int *resolved; { @@ -565,7 +624,7 @@ int *resolved; } return np->n_net; } - return *(u_int32_t *)hp->h_addr; + return *(u_32_t *)hp->h_addr; } /* @@ -670,7 +729,7 @@ u_char *mask; fp = &tcpfm; continue; } - if (!(t = strchr(flagset, *s))) { + if (!(t = index(flagset, *s))) { (void)fprintf(stderr, "unknown flag (%c)\n", *s); return 0; } @@ -703,8 +762,8 @@ struct frentry *fr; return -1; while (**cp && (!strncasecmp(**cp, "ipopt", 5) || - !strncasecmp(**cp, "not", 3) || !strncasecmp(**cp, "opt", 3) || - !strncasecmp(**cp, "frag", 4) || !strncasecmp(**cp, "no", 2) || + !strncasecmp(**cp, "not", 3) || !strncasecmp(**cp, "opt", 4) || + !strncasecmp(**cp, "frag", 3) || !strncasecmp(**cp, "no", 2) || !strncasecmp(**cp, "short", 5))) { if (***cp == 'n' || ***cp == 'N') { notopt = 1; @@ -775,7 +834,7 @@ nextopt: } -u_long optname(cp, sp) +u_32_t optname(cp, sp) char ***cp; u_short *sp; { @@ -825,9 +884,13 @@ u_short *sp; } +#ifdef __STDC__ +void optprint(u_short secmsk, u_short secbits, u_long optmsk, u_long optbits) +#else void optprint(secmsk, secbits, optmsk, optbits) u_short secmsk, secbits; u_long optmsk, optbits; +#endif { struct ipopt_names *io, *so; char *s; @@ -896,8 +959,8 @@ u_long optmsk, optbits; char *icmptypes[] = { "echorep", (char *)NULL, (char *)NULL, "unreach", "squench", - "redir", (char *)NULL, (char *)NULL, "echo", (char *)NULL, - (char *)NULL, "timex", "paramprob", "timest", "timestrep", + "redir", (char *)NULL, (char *)NULL, "echo", "routerad", + "routersol", "timex", "paramprob", "timest", "timestrep", "inforeq", "inforep", "maskreq", "maskrep", "END" }; @@ -1086,9 +1149,9 @@ struct frentry *fp; char *s; u_char *t; - if (fp->fr_flags & FR_PASS) { + if (fp->fr_flags & FR_PASS) (void)printf("pass"); - } else if (fp->fr_flags & FR_BLOCK) { + else if (fp->fr_flags & FR_BLOCK) { (void)printf("block"); if (fp->fr_flags & FR_RETICMP) { (void)printf(" return-icmp"); @@ -1109,6 +1172,12 @@ struct frentry *fp; (void)printf(" first"); } else if (fp->fr_flags & FR_ACCOUNT) (void)printf("count"); + else if (fp->fr_flags & FR_AUTH) + (void)printf("auth"); + else if (fp->fr_flags & FR_PREAUTH) + (void)printf("preauth"); + else if (fp->fr_skip) + (void)printf("skip %d", fp->fr_skip); if (fp->fr_flags & FR_OUTQUE) (void)printf(" out "); @@ -1153,10 +1222,11 @@ struct frentry *fp; (void)printf("proto %d ", fp->fr_proto); } + printf("from %s", fp->fr_flags & FR_NOTSRCIP ? "!" : ""); if (!fp->fr_src.s_addr & !fp->fr_smsk.s_addr) - (void)printf("from any "); + (void)printf("any "); else { - (void)printf("from %s", inet_ntoa(fp->fr_src)); + (void)printf("%s", inet_ntoa(fp->fr_src)); if ((ones = countbits(fp->fr_smsk.s_addr)) == -1) (void)printf("/%s ", inet_ntoa(fp->fr_smsk)); else @@ -1169,10 +1239,12 @@ struct frentry *fp; else (void)printf("port %s %s ", pcmp1[fp->fr_scmp], portname(pr, fp->fr_sport)); + + printf("to %s", fp->fr_flags & FR_NOTDSTIP ? "!" : ""); if (!fp->fr_dst.s_addr & !fp->fr_dmsk.s_addr) - (void)printf("to any"); + (void)printf("any"); else { - (void)printf("to %s", inet_ntoa(fp->fr_dst)); + (void)printf("%s", inet_ntoa(fp->fr_dst)); if ((ones = countbits(fp->fr_dmsk.s_addr)) == -1) (void)printf("/%s", inet_ntoa(fp->fr_dmsk)); else @@ -1244,6 +1316,10 @@ struct frentry *fp; printf(" keep state"); if (fp->fr_flags & FR_KEEPFRAG) printf(" keep frags"); + if (fp->fr_grhead) + printf(" head %d", fp->fr_grhead); + if (fp->fr_group) + printf(" group %d", fp->fr_group); (void)putchar('\n'); } diff --git a/sbin/ipfstat/fils.c b/sbin/ipfstat/fils.c index dd7211495a5..b28c360be53 100644 --- a/sbin/ipfstat/fils.c +++ b/sbin/ipfstat/fils.c @@ -1,6 +1,6 @@ -/* $OpenBSD: fils.c,v 1.11 1997/06/23 18:57:23 kstailey Exp $ */ +/* $OpenBSD: fils.c,v 1.12 1998/01/26 04:13:41 dgregor Exp $ */ /* - * (C)opyright 1993-1996 by Darren Reed. + * Copyright (C) 1993-1997 by Darren Reed. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and due credit is given @@ -13,6 +13,7 @@ #include <strings.h> #endif #include <sys/types.h> +#include <sys/time.h> #include <sys/param.h> #include <sys/file.h> #include <stdlib.h> @@ -27,23 +28,26 @@ #include <netinet/in_systm.h> #include <netinet/ip.h> #include <net/if.h> +#include <netdb.h> +#include <arpa/nameser.h> +#include <resolv.h> +#include <netinet/tcp.h> #include "ip_fil_compat.h" #include "ip_fil.h" +#include "ipf.h" +#include "ip_proxy.h" #include "ip_nat.h" #include "ip_frag.h" #include "ip_state.h" -#include <netdb.h> -#include <arpa/nameser.h> -#include <resolv.h> -#include "ipf.h" +#include "ip_auth.h" #include "kmem.h" -#if defined(__NetBSD__) || defined(__OpenBSD__) +#if defined(__NetBSD__) || (__OpenBSD__) #include <paths.h> #endif -#if !defined(lint) && defined(LIBC_SCCS) -static char sccsid[] = "@(#)fils.c 1.21 4/20/96 (C) 1993-1996 Darren Reed"; -static char rcsid[] = "$DRId: fils.c,v 2.0.1.3 1997/03/20 15:52:50 darrenr Exp $"; +#if !defined(lint) +static const char sccsid[] = "@(#)fils.c 1.21 4/20/96 (C) 1993-1996 Darren Reed"; +static const char rcsid[] = "@(#)$Id: fils.c,v 1.12 1998/01/26 04:13:41 dgregor Exp $"; #endif #ifdef _PATH_UNIX #define VMUNIX _PATH_UNIX @@ -63,13 +67,20 @@ static char *filters[4] = { "ipfilter(in)", "ipfilter(out)", int opts = 0; -static void showstats(), showfrstates(); -static void showlist(), showipstates(); +extern int main __P((int, char *[])); +static void showstats __P((int, friostat_t *)); +static void showfrstates __P((int, ipfrstat_t *)); +static void showlist __P((friostat_t *)); +static void showipstates __P((int, ips_stat_t *)); +static void showauthstates __P((int, fr_authstat_t *)); +static void Usage __P((char *)); +static void printlist __P((frentry_t *)); + -void Usage(name) +static void Usage(name) char *name; { - fprintf(stderr, "Usage: %s [-afhIiosv] [-d <device>]\n", name); + fprintf(stderr, "Usage: %s [-aAfhIinosv] [-d <device>]\n", name); exit(1); } @@ -78,11 +89,12 @@ int main(argc,argv) int argc; char *argv[]; { + fr_authstat_t frauthst; friostat_t fio; ips_stat_t ipsst; ipfrstat_t ifrst; - char c, *name = NULL, *device = IPL_NAME; - int fd; + char *name = NULL, *device = IPL_NAME; + int c, fd; if (openkmem() == -1) exit(-1); @@ -90,13 +102,16 @@ char *argv[]; (void)setuid(getuid()); (void)setgid(getgid()); - while ((c = getopt(argc, argv, "afhIiosvd:")) != -1) + while ((c = getopt(argc, argv, "aAfhIinosvd:")) != -1) { switch (c) { case 'a' : opts |= OPT_ACCNT|OPT_SHOWLIST; break; + case 'A' : + opts |= OPT_AUTHSTATS; + break; case 'd' : device = optarg; break; @@ -109,12 +124,12 @@ char *argv[]; case 'i' : opts |= OPT_INQUE|OPT_SHOWLIST; break; - case 'n' : - opts |= OPT_SHOWLINENO; - break; case 'I' : opts |= OPT_INACTIVE; break; + case 'n' : + opts |= OPT_SHOWLINENO; + break; case 'o' : opts |= OPT_OUTQUE|OPT_SHOWLIST; break; @@ -143,9 +158,18 @@ char *argv[]; perror("ioctl(SIOCGETFS)"); exit(-1); } - if ((opts & OPT_IPSTATES) && (ioctl(fd, SIOCGIPST, &ipsst) == -1)) { - perror("ioctl(SIOCGIPST)"); - exit(-1); + if ((opts & OPT_IPSTATES)) { + int sfd = open(IPL_STATE, O_RDONLY); + + if (sfd == -1) { + perror("open"); + exit(-1); + } + if ((ioctl(sfd, SIOCGIPST, &ipsst) == -1)) { + perror("ioctl(SIOCGIPST)"); + exit(-1); + } + close(sfd); } if ((opts & OPT_FRSTATES) && (ioctl(fd, SIOCGFRST, &ifrst) == -1)) { perror("ioctl(SIOCGFRST)"); @@ -154,9 +178,16 @@ char *argv[]; if (opts & OPT_VERBOSE) PRINTF("opts %#x name %s\n", opts, name ? name : "<>"); + + if ((opts & OPT_AUTHSTATS) && + (ioctl(fd, SIOCATHST, &frauthst) == -1)) { + perror("ioctl(SIOCATHST)"); + exit(-1); + } + if (opts & OPT_SHOWLIST) { showlist(&fio); - if((opts & OPT_OUTQUE) && (opts & OPT_INQUE)){ + if ((opts & OPT_OUTQUE) && (opts & OPT_INQUE)){ opts &= ~OPT_OUTQUE; showlist(&fio); } @@ -165,6 +196,8 @@ char *argv[]; showipstates(fd, &ipsst); else if (opts & OPT_FRSTATES) showfrstates(fd, &ifrst); + else if (opts & OPT_AUTHSTATS) + showauthstates(fd, &frauthst); else showstats(fd, &fio); } @@ -224,25 +257,68 @@ struct friostat *fp; fp->f_st[0].fr_pull[0], fp->f_st[0].fr_pull[1]); PRINTF("OUT Pullups succeeded:\t%lu\tfailed:\t%lu\n", fp->f_st[1].fr_pull[0], fp->f_st[1].fr_pull[1]); + PRINTF("Fastroute successes:\t%lu\tfailures:\t%lu\n", + fp->f_froute[0], fp->f_froute[1]); + PRINTF("TCP cksum fails(in):\t%lu\t(out):\t%lu\n", + fp->f_st[0].fr_tcpbad, fp->f_st[1].fr_tcpbad); PRINTF("Packet log flags set: (%#x)\n", frf); if (frf & FF_LOGPASS) PRINTF("\tpackets passed through filter\n"); if (frf & FF_LOGBLOCK) PRINTF("\tpackets blocked by filter\n"); + if (frf & FF_LOGNOMATCH) + PRINTF("\tpackets not matched by filter\n"); if (!frf) PRINTF("\tnone\n"); } + +static void printlist(fp) +frentry_t *fp; +{ + struct frentry fb; + int n; + + for (n = 1; fp; n++) { + if (kmemcpy((char *)&fb, (u_long)fp, sizeof(fb)) == -1) { + perror("kmemcpy"); + return; + } + fp = &fb; + if (opts & OPT_OUTQUE) + fp->fr_flags |= FR_OUTQUE; + if (opts & (OPT_HITS|OPT_VERBOSE)) +#ifdef USE_QUAD_T + PRINTF("%qd ", fp->fr_hits); +#else + PRINTF("%ld ", fp->fr_hits); +#endif + if (opts & (OPT_ACCNT|OPT_VERBOSE)) +#ifdef USE_QUAD_T + PRINTF("%qd ", fp->fr_bytes); +#else + PRINTF("%ld ", fp->fr_bytes); +#endif + if (opts & OPT_SHOWLINENO) + PRINTF("@%d ", n); + printfr(fp); + if (opts & OPT_VERBOSE) + binprint(fp); + if (fp->fr_grp) + printlist(fp->fr_grp); + fp = fp->fr_next; + } +} + /* * print out filter rule list */ static void showlist(fiop) struct friostat *fiop; { - struct frentry fb; struct frentry *fp = NULL; - int i, set, n; + int i, set; set = fiop->f_active; if (opts & OPT_INACTIVE) @@ -270,32 +346,13 @@ struct friostat *fiop; FPRINTF(stderr, "showlist:opts %#x i %d\n", opts, i); if (opts & OPT_VERBOSE) - PRINTF("fp %#lx set %d\n", (u_long)fp, set); + PRINTF("fp %p set %d\n", fp, set); if (!fp) { FPRINTF(stderr, "empty list for %s%s\n", (opts & OPT_INACTIVE) ? "inactive " : "", filters[i]); return; } - - for (n = 1; fp; n++) { - if (kmemcpy((char *)&fb, (u_long)fp, sizeof(fb)) == -1) { - perror("kmemcpy"); - return; - } - fp = &fb; - if (opts & OPT_OUTQUE) - fp->fr_flags |= FR_OUTQUE; - if (opts & (OPT_HITS|OPT_VERBOSE)) - PRINTF("%ld ", fp->fr_hits); - if (opts & (OPT_ACCNT|OPT_VERBOSE)) - PRINTF("%ld ", fp->fr_bytes); - if (opts & OPT_SHOWLINENO) - PRINTF("@%d ", n); - printfr(fp); - if (opts & OPT_VERBOSE) - binprint(fp); - fp = fp->fr_next; - } + printlist(fp); } @@ -317,13 +374,21 @@ ips_stat_t *ipsp; return; for (i = 0; i < IPSTATE_SIZE; i++) while (istab[i]) { - if (kmemcpy(&ips, istab[i], sizeof(ips)) == -1) + if (kmemcpy((char *)&ips, (u_long)istab[i], + sizeof(ips)) == -1) break; PRINTF("%s -> ", inet_ntoa(ips.is_src)); - PRINTF("%s age %d pass %d pr %d state %d/%d\n", + PRINTF("%s ttl %ld pass %d pr %d state %d/%d\n", inet_ntoa(ips.is_dst), ips.is_age, ips.is_pass, ips.is_p, ips.is_state[0], ips.is_state[1]); +#ifdef USE_QUAD_T + PRINTF("\tpkts %qd bytes %qd", + ips.is_pkts, ips.is_bytes); +#else + PRINTF("\tpkts %ld bytes %ld", + ips.is_pkts, ips.is_bytes); +#endif if (ips.is_p == IPPROTO_TCP) PRINTF("\t%hu -> %hu %lu:%lu %hu:%hu\n", ntohs(ips.is_sport), @@ -331,12 +396,57 @@ ips_stat_t *ipsp; 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), + PRINTF(" %hu -> %hu\n", ntohs(ips.is_sport), ntohs(ips.is_dport)); else if (ips.is_p == IPPROTO_ICMP) - PRINTF("\t%hu %hu %d\n", ips.is_icmp.ics_id, + PRINTF(" %hu %hu %d\n", ips.is_icmp.ics_id, ips.is_icmp.ics_seq, ips.is_icmp.ics_type); + + /* phil@ultimate.com ... */ + PRINTF("\t"); + /* from "printfr()" */ + if (ips.is_pass & FR_PASS) { + PRINTF("pass"); + } else if (ips.is_pass & FR_BLOCK) { + PRINTF("block"); + if (ips.is_pass & FR_RETICMP) + PRINTF(" return-icmp"); + if (ips.is_pass & FR_RETRST) + PRINTF(" return-rst"); + } else if ((ips.is_pass & FR_LOGMASK) == FR_LOG) { + PRINTF("log"); + if (ips.is_pass & FR_LOGBODY) + PRINTF(" body"); + if (ips.is_pass & FR_LOGFIRST) + PRINTF(" first"); + } else if (ips.is_pass & FR_ACCOUNT) + PRINTF("count"); + + if (ips.is_pass & FR_OUTQUE) + PRINTF(" out"); + else + PRINTF(" in"); + + if ((ips.is_pass & (FR_LOGB|FR_LOGP)) != 0) { + PRINTF(" log"); + if (ips.is_pass & FR_LOGBODY) + PRINTF(" body"); + if (ips.is_pass & FR_LOGFIRST) + PRINTF(" first"); + if (ips.is_pass & FR_LOGORBLOCK) + PRINTF(" or-block"); + } + if (ips.is_pass & FR_QUICK) + PRINTF(" quick"); + if (ips.is_pass & FR_KEEPFRAG) + PRINTF(" keep frags"); + /* a given; no? */ + if (ips.is_pass & FR_KEEPSTATE) + PRINTF(" keep state"); + PRINTF("\n"); + /* ... phil@ultimate.com */ + istab[i] = ips.is_next; } } @@ -358,7 +468,7 @@ ipfrstat_t *ifsp; return; for (i = 0; i < IPFT_SIZE; i++) while (ipfrtab[i]) { - if (kmemcpy(&ifr, (u_long)ipfrtab[i], + if (kmemcpy((char *)&ifr, (u_long)ipfrtab[i], sizeof(ifr)) == -1) break; PRINTF("%s -> ", inet_ntoa(ifr.ipfr_src)); @@ -369,3 +479,22 @@ ipfrstat_t *ifsp; ipfrtab[i] = ifr.ipfr_next; } } + + +static void showauthstates(fd, asp) +int fd; +fr_authstat_t *asp; +{ +#ifdef USE_QUAD_T + printf("Authorisation hits: %qd\tmisses %qd\n", asp->fas_hits, + asp->fas_miss); +#else + printf("Authorisation hits: %ld\tmisses %ld\n", asp->fas_hits, + asp->fas_miss); +#endif + printf("nospace %ld\nadded %ld\nsendfail %ld\nsendok %ld\n", + asp->fas_nospace, asp->fas_added, asp->fas_sendfail, + asp->fas_sendok); + printf("queok %ld\nquefail %ld\nexpire %ld\n", + asp->fas_queok, asp->fas_quefail, asp->fas_expire); +} diff --git a/sbin/ipfstat/ipfstat.8 b/sbin/ipfstat/ipfstat.8 index db23e39eed7..f26d60a216b 100644 --- a/sbin/ipfstat/ipfstat.8 +++ b/sbin/ipfstat/ipfstat.8 @@ -1,10 +1,11 @@ +.\" $OpenBSD: ipfstat.8,v 1.8 1998/01/26 04:13:42 dgregor Exp $ .TH ipfstat 8 .SH NAME ipfstat \- reports on packet filter statistics and filter list .SH SYNOPSIS .B ipfstat [ -.B \-hIinov +.B \-aAfhIinosv ] [ .B \-d <device> @@ -24,6 +25,9 @@ accumulated over time as the kernel has put packets through the filter. .B \-a Display the accounting filter list and show bytes counted against each rule. .TP +.B \-A +Display packet authentication statistics. +.TP .BR \-d \0<device> Use a device other than \fB/dev/ipl\fP for interfacing with the kernel. .TP diff --git a/sbin/ipfstat/kmem.c b/sbin/ipfstat/kmem.c index 06f57f9f1a8..6792855133e 100644 --- a/sbin/ipfstat/kmem.c +++ b/sbin/ipfstat/kmem.c @@ -1,6 +1,6 @@ -/* $OpenBSD: kmem.c,v 1.8 1997/02/12 20:57:44 kstailey Exp $ */ +/* $OpenBSD: kmem.c,v 1.9 1998/01/26 04:13:43 dgregor Exp $ */ /* - * (C)opyright 1993,1994,1995 by Darren Reed. + * Copyright (C) 1993-1997 by Darren Reed. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and due credit is given @@ -17,12 +17,11 @@ #include <unistd.h> #include <fcntl.h> #include <sys/file.h> +#include "kmem.h" -#define KMEM "/dev/kmem" - -#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.8 1997/02/12 20:57:44 kstailey Exp $"; +#if !defined(lint) +static const char sccsid[] = "@(#)kmem.c 1.4 1/12/96 (C) 1992 Darren Reed"; +static const char rcsid[] = "@(#)$Id: kmem.c,v 1.9 1998/01/26 04:13:43 dgregor Exp $"; #endif static int kmemfd = -1; @@ -39,7 +38,7 @@ int openkmem() int kmemcpy(buf, pos, n) register char *buf; -u_long pos; +long pos; register int n; { register int r; diff --git a/sbin/ipfstat/kmem.h b/sbin/ipfstat/kmem.h index f0b4c44f226..28e9a9d643c 100644 --- a/sbin/ipfstat/kmem.h +++ b/sbin/ipfstat/kmem.h @@ -1,12 +1,26 @@ +/* $OpenBSD: kmem.h,v 1.5 1998/01/26 04:13:44 dgregor Exp $ */ /* - * (C)opyright 1993,1994,1995 by Darren Reed. + * Copyright (C) 1993-1997 by Darren Reed. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and due credit is given * to the original author and the contributors. - * $Id: kmem.h,v 1.4 1997/02/11 22:23:46 kstailey Exp $ + * $Id: kmem.h,v 1.5 1998/01/26 04:13:44 dgregor Exp $ */ -extern int openkmem(); -extern int kmemcpy(); +#ifndef __KMEM_H__ +#define __KMEM_H__ +#ifndef __P +# ifdef __STDC__ +# define __P(x) x +# else +# define __P(x) () +# endif +#endif +extern int openkmem __P((void)); +extern int kmemcpy __P((char *, long, int)); + +#define KMEM "/dev/kmem" + +#endif /* __KMEM_H__ */ diff --git a/sbin/ipnat/Makefile b/sbin/ipnat/Makefile index 3cf787dad31..07fdcf86220 100644 --- a/sbin/ipnat/Makefile +++ b/sbin/ipnat/Makefile @@ -1,9 +1,9 @@ -# $OpenBSD: Makefile,v 1.2 1996/06/23 14:30:59 deraadt Exp $ +# $OpenBSD: Makefile,v 1.3 1998/01/26 04:13:45 dgregor Exp $ PROG= ipnat MAN= ipnat.1 ipnat.4 ipnat.5 SRCS= ipnat.c kmem.c .PATH: ${.CURDIR}/../ipfstat -CFLAGS+=-DIPL_NAME=\"/dev/ipl\" -I${.CURDIR}/../../sys/netinet +CFLAGS+=-DIPL_NAME=\"/dev/ipl\" -I${.CURDIR}/../../sys/netinet -I${.CURDIR}/../../sbin/ipfstat .include <bsd.prog.mk> diff --git a/sbin/ipnat/ipnat.1 b/sbin/ipnat/ipnat.1 index 661a7642ecf..203fbe3e905 100644 --- a/sbin/ipnat/ipnat.1 +++ b/sbin/ipnat/ipnat.1 @@ -1,3 +1,4 @@ +.\" $OpenBSD: ipnat.1,v 1.10 1998/01/26 04:13:46 dgregor Exp $ .\" .\" Manual page, using -mandoc macros .\" diff --git a/sbin/ipnat/ipnat.4 b/sbin/ipnat/ipnat.4 index 9bfa6f03158..551dfe4641b 100644 --- a/sbin/ipnat/ipnat.4 +++ b/sbin/ipnat/ipnat.4 @@ -1,8 +1,14 @@ +.\" $OpenBSD: ipnat.4,v 1.7 1998/01/26 04:13:47 dgregor Exp $ .TH IPNAT 4 .SH NAME ipnat \- Network Address Translation kernel interface .SH SYNOPSIS +.nf +#include <sys/ip_fil_compat.h> #include <sys/ip_fil.h> +#include <sys/ip_proxy.h> +#include <sys/ip_nat.h> +.fi .SH IOCTLS .PP To add and delete rules to the NAT list, two 'basic' ioctls are provided diff --git a/sbin/ipnat/ipnat.5 b/sbin/ipnat/ipnat.5 index 80d8054c7cc..04c3bae2c1b 100644 --- a/sbin/ipnat/ipnat.5 +++ b/sbin/ipnat/ipnat.5 @@ -1,3 +1,4 @@ +.\" $OpenBSD: ipnat.5,v 1.5 1998/01/26 04:13:48 dgregor Exp $ .TH IPNAT 5 .SH NAME ipnat \- IP NAT file format diff --git a/sbin/ipnat/ipnat.c b/sbin/ipnat/ipnat.c index 898afe4021f..ae5d7450fdd 100644 --- a/sbin/ipnat/ipnat.c +++ b/sbin/ipnat/ipnat.c @@ -1,6 +1,6 @@ -/* $OpenBSD: ipnat.c,v 1.18 1997/09/22 05:11:43 millert Exp $ */ +/* $OpenBSD: ipnat.c,v 1.19 1998/01/26 04:13:49 dgregor Exp $ */ /* - * (C)opyright 1993,1994,1995 by Darren Reed. + * Copyright (C) 1993-1997 by Darren Reed. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and due credit is given @@ -20,12 +20,13 @@ #include <stdio.h> #include <string.h> #include <fcntl.h> +#include <sys/types.h> #if !defined(__SVR4) && !defined(__svr4__) #include <strings.h> #else #include <sys/byteorder.h> #endif -#include <sys/types.h> +#include <sys/time.h> #include <sys/param.h> #include <stdlib.h> #include <unistd.h> @@ -41,29 +42,40 @@ #include <netinet/ip.h> #include <netinet/tcp.h> #include <net/if.h> -#include "ip_fil_compat.h" -#include "ip_fil.h" /* XXX needed? */ #include <netdb.h> #include <arpa/nameser.h> #include <arpa/inet.h> #include <resolv.h> -#include "ip_nat.h" #include <ctype.h> +#include "ip_fil_compat.h" +#include "ip_fil.h" +#include "ip_proxy.h" +#include "ip_nat.h" +#include "kmem.h" - -#if !defined(lint) && defined(LIBC_SCCS) -static char sccsid[] ="@(#)ipnat.c 1.9 6/5/96 (C) 1993 Darren Reed"; -static char rcsid[] = "$DRId: ipnat.c,v 2.0.1.8 1997/02/16 21:23:40 darrenr Exp $"; +#if !defined(lint) +static const char sccsid[] ="@(#)ipnat.c 1.9 6/5/96 (C) 1993 Darren Reed"; +static const char rcsid[] = "@(#)$Id: ipnat.c,v 1.19 1998/01/26 04:13:49 dgregor Exp $"; #endif + #if SOLARIS #define bzero(a,b) memset(a,0,b) #endif extern char *optarg; -extern int kmemcpy(); -void dostats(), printnat(), parsefile(), flushtable(); +ipnat_t *parse __P((char *)); +u_long hostnum __P((char *, int *)); +u_long hostmask __P((char *)); +u_short portnum __P((char *, char *)); +void dostats __P((int, int)), flushtable __P((int, int)); +void printnat __P((ipnat_t *, int, void *)); +void parsefile __P((int, char *, int)); +void usage __P((char *)); +int countbits __P((u_long)); +char *getnattype __P((ipnat_t *)); +int main __P((int, char*[])); #define OPT_REM 1 #define OPT_NODO 2 @@ -86,8 +98,8 @@ int main(argc, argv) int argc; char *argv[]; { - char *file = NULL, c; - int fd, opts = 1; + char *file = NULL; + int fd = -1, opts = 1, c; while ((c = getopt(argc, argv, "CFf:lnrsv")) != -1) switch (c) @@ -120,8 +132,8 @@ char *argv[]; usage(argv[0]); } - if (!(opts & OPT_NODO) && ((fd = open(IPL_NAME, O_RDWR)) == -1) && - ((fd = open(IPL_NAME, O_RDONLY)) == -1)) { + if (!(opts & OPT_NODO) && ((fd = open(IPL_NAT, O_RDWR)) == -1) && + ((fd = open(IPL_NAT, O_RDONLY)) == -1)) { perror("open"); exit(-1); } @@ -142,9 +154,9 @@ char *argv[]; * of bits. */ int countbits(ip) -u_int ip; +u_long ip; { - u_int ipn; + u_long ipn; int cnt = 0, i, j; ip = ipn = ntohl(ip); @@ -171,9 +183,27 @@ int verbose; void *ptr; { int bits; + struct protoent *pr; + + switch (np->in_redir) + { + case NAT_REDIRECT : + printf("rdr "); + break; + case NAT_MAP : + printf("map "); + break; + case NAT_BIMAP : + printf("bimap "); + break; + default : + fprintf(stderr, "unknown value for in_redir: %#x\n", + np->in_redir); + break; + } if (np->in_redir == NAT_REDIRECT) { - printf("rdr %s %s", np->in_ifname, inet_ntoa(np->in_out[0])); + printf("%s %s", np->in_ifname, inet_ntoa(np->in_out[0])); bits = countbits(np->in_out[1].s_addr); if (bits != -1) printf("/%d ", bits); @@ -184,11 +214,11 @@ void *ptr; 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) + if ((np->in_flags & IPN_TCPUDP) == IPN_TCPUDP) printf(" tcp/udp"); - else if (np->in_flags & IPN_TCP) + else if ((np->in_flags & IPN_TCP) == IPN_TCP) printf(" tcp"); - else if (np->in_flags & IPN_UDP) + else if ((np->in_flags & IPN_UDP) == IPN_UDP) printf(" udp"); printf("\n"); if (verbose) @@ -197,19 +227,29 @@ void *ptr; 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])); + printf("%s %s/", np->in_ifname, inet_ntoa(np->in_in[0])); bits = countbits(np->in_in[1].s_addr); if (bits != -1) printf("%d ", bits); else printf("%s", inet_ntoa(np->in_in[1])); printf(" -> %s/", inet_ntoa(np->in_out[0])); - bits = countbits(np->in_out[1].s_addr); + bits = countbits(ntohl(np->in_out[1].s_addr)); if (bits != -1) printf("%d ", bits); else printf("%s", inet_ntoa(np->in_out[1])); - if (np->in_pmin || np->in_pmax) { + if (*np->in_plabel) { + printf(" proxy port"); + if (np->in_dport) + printf(" %hu", ntohs(np->in_dport)); + printf(" %.*s/", (int)sizeof(np->in_plabel), + np->in_plabel); + if ((pr = getprotobynumber(np->in_p))) + fputs(pr->p_name, stdout); + else + printf("%d", np->in_p); + } else if (np->in_pmin || np->in_pmax) { printf(" portmap"); if ((np->in_flags & IPN_TCPUDP) == IPN_TCPUDP) printf(" tcp/udp"); @@ -235,12 +275,29 @@ void *ptr; char *getnattype(ipnat) ipnat_t *ipnat; { + char *which; ipnat_t ipnatbuff; - if (ipnat && kmemcpy(&ipnatbuff, ipnat, sizeof(ipnatbuff))) + if (ipnat && kmemcpy((char *)&ipnatbuff, (long)ipnat, + sizeof(ipnatbuff))) return "???"; - return (ipnatbuff.in_redir == NAT_MAP) ? "MAP" : "RDR"; + switch (ipnatbuff.in_redir) + { + case NAT_MAP : + which = "MAP"; + break; + case NAT_REDIRECT : + which = "RDR"; + break; + case NAT_BIMAP : + which = "BIMAP"; + break; + default : + which = "unknown"; + break; + } + return which; } @@ -264,14 +321,15 @@ int fd, opts; 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); + printf("inuse\t%lu\nrules\t%lu\n", ns.ns_inuse, ns.ns_rules); if (opts & OPT_VERBOSE) printf("table %p list %p\n", ns.ns_table, ns.ns_list); } if (opts & OPT_LIST) { printf("List of active MAP/Redirect filters:\n"); while (ns.ns_list) { - if (kmemcpy(&ipn, ns.ns_list, sizeof(ipn))) { + if (kmemcpy((char *)&ipn, (long)ns.ns_list, + sizeof(ipn))) { perror("kmemcpy"); break; } @@ -280,7 +338,8 @@ int fd, opts; } nt[0] = (nat_t **)malloc(sizeof(*nt) * NAT_SIZE); - if (kmemcpy(nt[0], ns.ns_table[0], sizeof(**nt) * NAT_SIZE)) { + if (kmemcpy((char *)nt[0], (long)ns.ns_table[0], + sizeof(**nt) * NAT_SIZE)) { perror("kmemcpy"); return; } @@ -289,7 +348,8 @@ int fd, opts; for (i = 0; i < NAT_SIZE; i++) for (np = nt[0][i]; np; np = nat.nat_hnext[0]) { - if (kmemcpy(&nat, np, sizeof(nat))) + if (kmemcpy((char *)&nat, (long)np, + sizeof(nat))) break; printf("%s %-15s %-5hu <- ->", @@ -301,7 +361,7 @@ int fd, opts; ntohs(nat.nat_outport)); printf(" [%s %hu]", inet_ntoa(nat.nat_oip), ntohs(nat.nat_oport)); - printf(" %d %hu %lx", nat.nat_age, + printf(" %ld %hu %lx", nat.nat_age, nat.nat_use, nat.nat_sumd); #if SOLARIS printf(" %lx", nat.nat_ipsumd); @@ -349,18 +409,18 @@ char *name, *proto; } -u_int hostmask(msk) +u_long hostmask(msk) char *msk; { int bits = -1; - u_int mask; + u_long mask; if (!isdigit(*msk)) - return (u_int)-1; + return (u_long)-1; if (strchr(msk, '.')) return inet_addr(msk); if (strchr(msk, 'x')) - return (u_int)strtol(msk, NULL, 0); + return (u_long)strtol(msk, NULL, 0); /* * set x most significant bits */ @@ -372,71 +432,12 @@ char *msk; return mask; } -/* - * get_if_addr(): given a string containing an interface name (e.g. "ppp0") - * return the IP address it represents as an unsigned int - */ -u_int if_addr(name) -char *name; -{ - struct ifconf ifc; - struct ifreq ifreq, *ifr; - char *inbuf = NULL; - int s, i, len = 8192; - - if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { - warn("socket"); - return INADDR_NONE; - } - - while (1) { - ifc.ifc_len = len; - ifc.ifc_buf = inbuf = realloc(inbuf, len); - if (inbuf == NULL) - err(1, "malloc"); - if (ioctl(s, SIOCGIFCONF, &ifc) < 0) { - warn("SIOCGIFCONF"); - goto if_addr_lose; - } - if (ifc.ifc_len + sizeof(ifreq) < len) - break; - len *= 2; - } - ifr = ifc.ifc_req; - ifreq.ifr_name[0] = '\0'; - for (i = 0; i < ifc.ifc_len; ) { - ifr = (struct ifreq *)((caddr_t)ifc.ifc_req + i); - i += sizeof(ifr->ifr_name) + - (ifr->ifr_addr.sa_len > sizeof(struct sockaddr) - ? ifr->ifr_addr.sa_len - : sizeof(struct sockaddr)); - if (!strncmp(ifreq.ifr_name, ifr->ifr_name, - sizeof(ifr->ifr_name))) - continue; - ifreq = *ifr; - if (ioctl(s, SIOCGIFADDR, (caddr_t)ifr) < 0) - continue; - if (ifr->ifr_addr.sa_family != AF_INET) - continue; - if (!strcmp(name, ifr->ifr_name)) { - struct sockaddr_in *sin; - close(s); - free(inbuf); - sin = (struct sockaddr_in *)&ifr->ifr_addr; - return (sin->sin_addr.s_addr); - } - } -if_addr_lose: - close(s); - free(inbuf); - return INADDR_NONE; -} /* - * returns an ip address as an int var as a result of either a DNS lookup or + * returns an ip address as a long var as a result of either a DNS lookup or * straight inet_addr() call */ -u_int hostnum(host, resolved) +u_long hostnum(host, resolved) char *host; int *resolved; { @@ -451,22 +452,20 @@ int *resolved; if (!(hp = gethostbyname(host))) { if (!(np = getnetbyname(host))) { - u_int addr; - if ((addr = if_addr(host)) != INADDR_NONE) - return addr; *resolved = -1; fprintf(stderr, "can't resolve hostname: %s\n", host); return 0; } return np->n_net; } - return *(u_int32_t *)hp->h_addr; + return *(u_32_t *)hp->h_addr; } ipnat_t *parse(line) char *line; { + struct protoent *pr; static ipnat_t ipn; char *s, *t; char *shost, *snetm, *dhost, *proto; @@ -486,9 +485,11 @@ char *line; ipn.in_redir = NAT_MAP; else if (!strcasecmp(s, "rdr")) ipn.in_redir = NAT_REDIRECT; + else if (!strcasecmp(s, "bimap")) + ipn.in_redir = NAT_BIMAP; else { (void)fprintf(stderr, - "expected \"map\" or \"rdr\", got \"%s\"\n", s); + "expected map/rdr/bimap, got \"%s\"\n", s); return NULL; } @@ -556,7 +557,7 @@ char *line; } dhost = s; - if (ipn.in_redir == NAT_MAP) { + if (ipn.in_redir & NAT_MAP) { if (!(s = strtok(NULL, " \t"))) { dnetm = strrchr(dhost, '/'); if (!dnetm) { @@ -565,7 +566,8 @@ char *line; return NULL; } } - if (!s || !strcasecmp(s, "portmap")) { + if (!s || !strcasecmp(s, "portmap") || + !strcasecmp(s, "proxy")) { dnetm = strrchr(dhost, '/'); if (!dnetm) { fprintf(stderr, @@ -610,7 +612,7 @@ char *line; if (*snetm == '/') *snetm++ = '\0'; - if (ipn.in_redir == NAT_MAP) { + if (ipn.in_redir & NAT_MAP) { ipn.in_inip = hostnum(shost, &resolved); if (resolved == -1) return NULL; @@ -664,6 +666,55 @@ char *line; if (!s) return &ipn; + if (ipn.in_redir == NAT_BIMAP) { + fprintf(stderr, "extra words at the end of bimap line: %s\n", + s); + return NULL; + } + if (!strcasecmp(s, "proxy")) { + if (!(s = strtok(NULL, " \t"))) { + fprintf(stderr, "missing parameter for \"proxy\"\n"); + return NULL; + } + dport = NULL; + + if (!strcasecmp(s, "port")) { + if (!(s = strtok(NULL, " \t"))) { + fprintf(stderr, + "missing parameter for \"port\"\n"); + return NULL; + } + + dport = s; + + if (!(s = strtok(NULL, " \t"))) { + fprintf(stderr, + "missing parameter for \"proxy\"\n"); + return NULL; + } + } + if ((proto = index(s, '/'))) { + *proto++ = '\0'; + if ((pr = getprotobyname(proto))) + ipn.in_p = pr->p_proto; + else + ipn.in_p = atoi(proto); + if (dport) + ipn.in_dport = portnum(dport, proto); + } else { + ipn.in_p = 0; + if (dport) + ipn.in_dport = portnum(dport, NULL); + } + + (void) strncpy(ipn.in_plabel, s, sizeof(ipn.in_plabel)); + if ((s = strtok(NULL, " \t"))) { + fprintf(stderr, "too many parameters for \"proxy\"\n"); + return NULL; + } + return &ipn; + + } if (strcasecmp(s, "portmap")) { fprintf(stderr, "expected \"portmap\" - got \"%s\"\n", s); return NULL; @@ -709,9 +760,9 @@ int opts; int linenum = 1; if (strcmp(file, "-")) { - if ((fp = fopen(file, "r")) == NULL) { - perror("fopen"); - exit(-1); + if (!(fp = fopen(file, "r"))) { + perror(file); + exit(1); } } else fp = stdin; @@ -735,7 +786,8 @@ int opts; } linenum++; } - fclose(stdin); + if (fp != stdin) + fclose(fp); } |