diff options
author | Federico G. Schwindt <fgsch@cvs.openbsd.org> | 2001-01-17 05:01:03 +0000 |
---|---|---|
committer | Federico G. Schwindt <fgsch@cvs.openbsd.org> | 2001-01-17 05:01:03 +0000 |
commit | 563aa13c03d2813c7166caafc538d5e70b2fb34c (patch) | |
tree | 667756531d650ac84b36eee1d5a33c592111139c | |
parent | 88e9db6efe2d8f5ccd5d6e21f96e87b9e167070e (diff) |
1st part of ipf userland code.
-rw-r--r-- | sbin/ipf/HISTORY | 241 | ||||
-rw-r--r-- | sbin/ipf/Makefile | 4 | ||||
-rw-r--r-- | sbin/ipf/common.c | 606 | ||||
-rw-r--r-- | sbin/ipf/facpri.c | 6 | ||||
-rw-r--r-- | sbin/ipf/facpri.h | 6 | ||||
-rw-r--r-- | sbin/ipf/ifaddr.c | 82 | ||||
-rw-r--r-- | sbin/ipf/ifaddr.h | 9 | ||||
-rw-r--r-- | sbin/ipf/ipf.c | 123 | ||||
-rw-r--r-- | sbin/ipf/ipf.h | 34 | ||||
-rw-r--r-- | sbin/ipf/opt.c | 10 | ||||
-rw-r--r-- | sbin/ipf/parse.c | 549 | ||||
-rw-r--r-- | sbin/ipfstat/Makefile | 6 | ||||
-rw-r--r-- | sbin/ipfstat/fils.c | 998 | ||||
-rw-r--r-- | sbin/ipfstat/kmem.c | 18 | ||||
-rw-r--r-- | sbin/ipfstat/kmem.h | 11 | ||||
-rw-r--r-- | sbin/ipnat/Makefile | 4 | ||||
-rw-r--r-- | sbin/ipnat/ipnat.c | 191 | ||||
-rw-r--r-- | sbin/ipnat/natparse.c | 737 | ||||
-rw-r--r-- | usr.sbin/ipmon/ipmon.c | 219 |
19 files changed, 2415 insertions, 1439 deletions
diff --git a/sbin/ipf/HISTORY b/sbin/ipf/HISTORY index 5c81d705dab..0bcb7fb4110 100644 --- a/sbin/ipf/HISTORY +++ b/sbin/ipf/HISTORY @@ -1,4 +1,4 @@ -# $OpenBSD: HISTORY,v 1.9 2000/08/10 05:50:27 kjell Exp $ +# $OpenBSD: HISTORY,v 1.10 2001/01/17 05:00:57 fgsch Exp $ # # NOTE: Quite a few patches and suggestions come from other sources, to whom # I'm greatly indebted, even if no names are mentioned. @@ -7,9 +7,11 @@ # in providing a very available location for the IP Filter home page and # distribution center. # -# Thanks to Tel.Net Media for allowing me to maintain and further develop -# IP Filter as part of my job and supplying Sun equipment for testing the -# move to 64bits and Gigabit Ethernet. +# Thanks to Hewlett Packard for making it possible to port IP Filter to +# HP-UX 11.00. +# +# Thanks to Tel.Net Media for supplying me with equipment to ensure that +# IP Filter continues to work on Solaris/sparc64. # # Thanks to BSDI for providing object files for BSD/OS 3.1 and the means # to further support development of IP Filter under BSDI. @@ -21,52 +23,239 @@ # and especially those who have found the time to port IP Filter to new # platforms. # -3.3.18 08/08/2000 - Released +3.4.15 17/12/2000 - Released + +add minimum ttl filtering (to be replaced later by return-icmp-as-dest +for all ICMP packets matching state entries). + +fix NAT'ing of fragments + +fix sanity checks for ICMPV6 + +fix up compiling on IRIX 6.2 with IDF/IDL installed + +3.4.14 02/11/2000 - Released + +cause flushing NAT table to generate log records the same as state flush +does. + +fix ftp proxy port/pasv + +fix problem where nat_{in,out}lookup() would release a write lock when it +didn't need to. + +add check for ipf6.conf in Solaris ipfboot + +3.4.13 28/10/2000 - Released + +fix introduced bug with ICMP packets being rejected when valid + +fix bug with proxy's that don't set fin_dlen correctly when calling +fr_addstate() + +3.4.12 26/10/2000 - Released + +fix installing into FreeBSD-4.1 + +fix FTP proxy bug where it'd hang and make NAT slightly more efficient + +fix general compiling errors/warnings on various platforms + +don't access ICMP data fields that aren't there + +3.4.11 09/10/2000 - Released + +return NULL for IPv6 access control lists if it is disabled rather than +random garbage. + +fix for getting protocol & packet length for IPv6 packets for pullup. + +update plog script from version 0.8 to version 0.10 + +patch from Frank Volf adding fix_datacksum() to NAT code, enhancing the +capabilities for "fixing" checksums. + +3.4.10 03/09/2000 - Released -fix up command checking in the ftp proxy +merge patch from Frank Volf for ICMP nat handling of TCP/UDP data `errors' -fix getting the version from the kernel for solaris +getline() adjusts linenum now + +add tcphalfclosed timeout + +fill in icmp_nextmtu field if it is defined on the platform + +RST generation fix from guido + +force 32bit compile for gcc on solaris if it can't generate 64bit code + +encase logging when fr_chksrc == 2 in #ifdef IPFILTER_LOG + +fix up line wrap problems in plog script + +fix ICMP packet handling to not drop valid ICMP errors + +freebsd 5.0 compat changes + +3.4.9 08/08/2000 - Released + +implement new aging mechanism in fr_tcp_age() fix icmp state checking bug -print out better information for ICMP packets in ipmon +revamp buildsunos script and build both sparcv7/sparcv9 for Solaris +if on an Ultra with a 64bit system & compiler (Caseper Dik) open ipfilter device read only if we know we can -3.3.17 08/07/2000 - Released +print out better information for ICMP packets in ipmon + +move checking for source spoofed packets to a point where we can generate +logs of them + +return EFAULT from ircopyptr/iwcopyptr + +don't do ioctl(SIOCGETFS) for auth stats + +fix up freeing mbufs for post-4.3BSD + +fix returning of inc from ftp proxy + +fix bugs with ipfs -R/-W (Caseper Dik) + +3.4.8 19/07/2000 - Released + +create fake opt_inet6.h for FreeBSD-4 compile as LKM + +add #ifdef's for KLD_MODULE sanity + +NAT fastroute'd packets which come out of return-* + +fix upper/lower case crap in ftp proxy and get seq# checking fixed up. -increase default state table sizes +3.4.7 08/07/2000 - Released + +make "ipf -y" lookup NAT if's which are unknown + +prepend line numbers to ioctl error messages in ipf/ipnat don't apply patches to FreeBSD twice -fix parsing of icmp code when using words +allow for ip_len to be on an unaligned boundary early on in fr_precheck fix printing of icmp code when it is 0 -add compatibility #ifdef for FreeBSD's CSUM_DELAY_DATA +correct printing of port numbers in map rules with from/to + +don't allow fr_func to be called at securelevel > 0 or rules to be added +if securelevel > 0 if they have a non-zero fr_func. + +3.4.6 11/06/2000 - Released + +add extra regression tests for new nat functionality + +place restrictions on using '!' in map/rdr rules + +fix up solaris compile problems + +3.4.5 10/06/2000 - Released + +mention -sl in ipfstat.8 + +fix/support '!' in from/to rules (rdr) for NAT + +add from/to support to rdr NAT rules + +don't send ICMP errors in response to ICMP errors -3.3.16 23/05/2000 - Released +fix sunos5 compilation for "ipfstat-top" and cleanup ipfboot + +input accounting list used for both outbound and inbound packets + +3.4.4 23/05/2000 - Released don't add TCP state if it is an RST packet and (attempt) to send out RST/ICMP packets in a manner that bypasses IP Filter. add patch to work with 4.0_STABLE delayed checksums -3.3.15 20/05/2000 - Released - -fix destination being 0/32 in NAT map rules +3.4.3 20/05/2000 - Released fix ipmon -F -3.3.14 10/05/2000 - Released +don't truncate IPv6 packets on Solaris + +fix keep state for ICMP ECHO + +add some NAT stats and use def_nat_age rather than DEF_NAT_AGE + +don't make ftp proxy drop packets + +use MCLISREFERENCED() in tandem with M_EXT to check if IP fields need to be +swapped back. + +fix up RST generation for non-Solaris + +get "short" flag right for IPv6 + +3.4.2 - 10/5/2000 - Released Fix bug in dealing with "hlen == 1 and opt > 1" - Itojun ignore previous NAT mappings for 0/0 and 0/32 rules -struct friostat got too big for SunOS4 +bring in a completely new ftp proxy + +allow NAT to cause packets to be dropped. + +add NetBSD callout support for 1.4-current -3.3.13 26/04/2000 - Released +3.4.1 - 30/4/2000 - Released + +add ratoui() and fix parsing of group numbers to allow 0 - UINT_MAX + +don't include opt_inet6.h for FreeBSD if KLD_MODULE is defined + +Solaris must use copyin() for all types of ioctl() args + +fix up screen/tty when leaving "top mode" of ipfstat + +linked list for maptable not setup correctly in nat_hostmap() + +check for maptable rather than nat_table[1] to see if malloc for maptable +succeeded in nat_init + +fix handling of map NAT rules with "from/to" host specs + +fix printout out of source address when using "from/to" with map rules + +convert ip_len back to network byte order, not plen, for solaris as ip_len +may have been changed by NAT and plen won't reflect this + +3.4 - 27/4/2000 - Released + +source address spoofing can be turned on (fr_chksrc) without using +filter rules + +group numbers are now 32bits in size, up from 16bits + +IPv6 filtering available + +add frank volf's state-top patches + +add load splitting and round-robin attribute to redirect rules + +FreeBSD-4.0 support (including KLD) + +add top-style operation mode for ipfstat (-t) + +add save/restore of IP Filter state/NAT information (ipfs) + +further ftp proxy security checks + +support for adding and removing proxies at runtime + +3.3.13 26/04/2000 - Released Fix parsing of "range" with "portmap" @@ -76,7 +265,7 @@ Fix NAT timeouts for ICMP packets SunOS4 patches for ICMP redirects from Jurgen Keil (jk@tools.de) -3.3.12 16/03/2000 - Released +3.3.12 16/03/2000 - Released tighten up ftp proxy behaviour. sigh. yuck. hate. @@ -89,7 +278,7 @@ erroneously. fix bug with the spl level not being reset when returning EIO from iplioctl due to ipfilter not being initialized yet. -3.3.11 04/03/2000 - Released +3.3.11 04/03/2000 - Released make "or-block" work with lines that start with "log" @@ -97,6 +286,7 @@ fix up parsing and printing of rules with syslog levels in them fix from Cy Schubert for calling of apr_fini only if non-null + 3.3.10 24/02/2000 - Released * fix back from guido for state tracking interfaces @@ -105,10 +295,10 @@ fix from Cy Schubert for calling of apr_fini only if non-null * if attaching fails and we can abort, then cleanup when doing so. -Julian Yip (julian@computer.org): +julian@computer.org: * solaris.c (fr_precheck): After calling freemsg on mt, set it point to *mp. * ipf.c (packetlogon): use flag to store the return value from get_flags. -* ipmon.c (init_tabs): Generate cleanup so we do not have to cast +* ipmon.c (init_tabs): General cleanup so we do not have to cast an int s->s_port to u_int port and try to check if the u_int port is less than zero. @@ -200,11 +390,6 @@ fix yet another problem with real audio. 3.3.4 4/12/1999 - Released -patches from Guido: fix panic in ip_state:fr_checkicmpmatchingstate(), fix -byte order problem in ip_id (host order when called from ip_input(), vs -network byte order when called from ip_output()) and fix a problem where the -fragment cache was never timedout early. - fix up the real audio proxy to properly setup state information and NAT entries, thanks to Laine Stump for testing/advice/fixes. diff --git a/sbin/ipf/Makefile b/sbin/ipf/Makefile index d4061995d59..ed7af593210 100644 --- a/sbin/ipf/Makefile +++ b/sbin/ipf/Makefile @@ -1,7 +1,7 @@ -# $OpenBSD: Makefile,v 1.9 2000/04/26 21:03:59 deraadt Exp $ +# $OpenBSD: Makefile,v 1.10 2001/01/17 05:00:57 fgsch Exp $ PROG= ipf MAN= ipf.8 ipf.4 ipf.5 -SRCS= ipf.c parse.c opt.c facpri.c ifaddr.c +SRCS= ipf.c parse.c opt.c facpri.c common.c ifaddr.c .include <bsd.prog.mk> diff --git a/sbin/ipf/common.c b/sbin/ipf/common.c new file mode 100644 index 00000000000..569d6e0427f --- /dev/null +++ b/sbin/ipf/common.c @@ -0,0 +1,606 @@ +/* $OpenBSD: common.c,v 1.1 2001/01/17 05:00:57 fgsch Exp $ */ + +/* + * Copyright (C) 1993-2000 by Darren Reed. + * + * Redistribution and use in source and binary forms are permitted + * provided that this notice is preserved and due credit is given + * to the original author and the contributors. + */ +#include <sys/types.h> +#if !defined(__SVR4) && !defined(__svr4__) +#include <strings.h> +#else +#include <sys/byteorder.h> +#endif +#include <sys/param.h> +#include <sys/time.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <netinet/in_systm.h> +#include <netinet/ip.h> +#include <netinet/tcp.h> +#include <net/if.h> +#if __FreeBSD_version >= 300000 +# include <net/if_var.h> +#endif +#include <stdio.h> +#include <string.h> +#include <limits.h> +#include <stdlib.h> +#include <unistd.h> +#include <stddef.h> +#include <netdb.h> +#include <arpa/nameser.h> +#include <arpa/inet.h> +#include <resolv.h> +#include <ctype.h> +#include <syslog.h> +#include <netinet/ip_compat.h> +#include <netinet/ip_fil.h> +#include "ipf.h" +#include "facpri.h" + +#if defined(__OpenBSD__) +#include "ifaddr.h" +#endif + +#if !defined(lint) +static const char sccsid[] = "@(#)parse.c 1.44 6/5/96 (C) 1993-2000 Darren Reed"; +static const char rcsid[] = "@(#)$IPFilter: parse.c,v 2.8 1999/12/28 10:49:46 darrenr Exp $"; +#endif + +extern struct ipopt_names ionames[], secclass[]; +extern int opts; +#ifdef USE_INET6 +extern int use_inet6; +#endif + + +char *proto = NULL; +char flagset[] = "FSRPAU"; +u_char flags[] = { TH_FIN, TH_SYN, TH_RST, TH_PUSH, TH_ACK, TH_URG }; + +#ifdef USE_INET6 +void fill6bits __P((int, u_32_t *)); +int count6bits __P((u_32_t *)); +#endif + +static char thishost[MAXHOSTNAMELEN]; + + +void initparse() +{ + gethostname(thishost, sizeof(thishost)); + thishost[sizeof(thishost) - 1] = '\0'; +} + + +int genmask(msk, mskp) +char *msk; +u_32_t *mskp; +{ + char *endptr = NULL; +#ifdef USE_INET6 + u_32_t addr; +#endif + int bits; + + if (index(msk, '.') || index(msk, 'x') || index(msk, ':')) { + /* possibly of the form xxx.xxx.xxx.xxx + * or 0xYYYYYYYY */ +#ifdef USE_INET6 + if (use_inet6) { + if (inet_pton(AF_INET6, msk, &addr) != 1) + return -1; + } else +#endif + if (inet_aton(msk, (struct in_addr *)mskp) == 0) + return -1; + } else { + /* + * set x most significant bits + */ + bits = (int)strtol(msk, &endptr, 0); +#ifdef USE_INET6 + if ((*endptr != '\0') || + ((bits > 32) && !use_inet6) || (bits < 0) || + ((bits > 128) && use_inet6)) +#else + if (*endptr != '\0' || bits > 32 || bits < 0) +#endif + return -1; +#ifdef USE_INET6 + if (use_inet6) + fill6bits(bits, mskp); + else +#endif + if (bits == 0) + *mskp = 0; + else + *mskp = htonl(0xffffffff << (32 - bits)); + } + return 0; +} + + + +#ifdef USE_INET6 +void fill6bits(bits, msk) +int bits; +u_32_t *msk; +{ + int i; + + for (i = 0; bits >= 32 && i < 4 ; ++i, bits -= 32) + msk[i] = 0xffffffff; + + if (bits > 0 && i < 4) + msk[i++] = htonl(0xffffffff << (32 - bits)); + + while (i < 4) + msk[i++] = 0; +} +#endif + + +/* + * returns -1 if neither "hostmask/num" or "hostmask mask addr" are + * found in the line segments, there is an error processing this information, + * or there is an error processing ports information. + */ +int hostmask(seg, sa, msk, pp, cp, tp, linenum) +char ***seg; +u_32_t *sa, *msk; +u_short *pp, *tp; +int *cp; +int linenum; +{ + struct in_addr maskaddr; + char *s; + + /* + * is it possibly hostname/num ? + */ + if ((s = index(**seg, '/')) || + ((s = index(**seg, ':')) && !index(s + 1, ':'))) { + *s++ = '\0'; + if (genmask(s, msk) == -1) { + fprintf(stderr, "%d: bad mask (%s)\n", linenum, s); + return -1; + } + if (hostnum(sa, **seg, linenum) == -1) { + fprintf(stderr, "%d: bad host (%s)\n", linenum, **seg); + return -1; + } + *sa &= *msk; + (*seg)++; + return ports(seg, pp, cp, tp, linenum); + } + + /* + * look for extra segments if "mask" found in right spot + */ + if (*(*seg+1) && *(*seg+2) && !strcasecmp(*(*seg+1), "mask")) { + if (hostnum(sa, **seg, linenum) == -1) { + fprintf(stderr, "%d: bad host (%s)\n", linenum, **seg); + return -1; + } + (*seg)++; + (*seg)++; + if (inet_aton(**seg, &maskaddr) == 0) { + fprintf(stderr, "%d: bad mask (%s)\n", linenum, **seg); + return -1; + } + *msk = maskaddr.s_addr; + (*seg)++; + *sa &= *msk; + return ports(seg, pp, cp, tp, linenum); + } + + if (**seg) { + if (hostnum(sa, **seg, linenum) == -1) { + fprintf(stderr, "%d: bad host (%s)\n", linenum, **seg); + return -1; + } + (*seg)++; +#ifdef USE_INET6 + if (use_inet6) { + u_32_t k = 0; + if (sa[0] || sa[1] || sa[2] || sa[3]) + k = 0xffffffff; + msk[0] = msk[1] = msk[2] = msk[3] = k; + } + else +#endif + *msk = *sa ? 0xffffffff : 0; + return ports(seg, pp, cp, tp, linenum); + } + fprintf(stderr, "%d: bad host (%s)\n", linenum, **seg); + return -1; +} + +/* + * returns an ip address as a long var as a result of either a DNS lookup or + * straight inet_addr() call + */ +int hostnum(ipa, host, linenum) +u_32_t *ipa; +char *host; +int linenum; +{ + struct hostent *hp; + struct netent *np; + struct in_addr ip; + + if (!strcasecmp("any", host)) + return 0; +#ifdef USE_INET6 + if (use_inet6) { + if (inet_pton(AF_INET6, host, ipa) == 1) + return 0; + else + return -1; + } +#endif + if (isdigit(*host) && inet_aton(host, &ip)) { + *ipa = ip.s_addr; + return 0; + } + + if (!strcasecmp("<thishost>", host)) + host = thishost; + +#if defined(__OpenBSD__) + if (if_addr(host, &ip)) + return *ipa = ip.s_addr; +#endif + + if (!(hp = gethostbyname(host))) { + if (!(np = getnetbyname(host))) { + fprintf(stderr, "%d: can't resolve hostname: %s\n", + linenum, host); + return -1; + } + *ipa = htonl(np->n_net); + return 0; + } + *ipa = *(u_32_t *)hp->h_addr; + return 0; +} + + +/* + * check for possible presence of the port fields in the line + */ +int ports(seg, pp, cp, tp, linenum) +char ***seg; +u_short *pp, *tp; +int *cp; +int linenum; +{ + int comp = -1; + + if (!*seg || !**seg || !***seg) + return 0; + if (!strcasecmp(**seg, "port") && *(*seg + 1) && *(*seg + 2)) { + (*seg)++; + if (isalnum(***seg) && *(*seg + 2)) { + if (portnum(**seg, pp, linenum) == 0) + return -1; + (*seg)++; + if (!strcmp(**seg, "<>")) + comp = FR_OUTRANGE; + else if (!strcmp(**seg, "><")) + comp = FR_INRANGE; + else { + fprintf(stderr, + "%d: unknown range operator (%s)\n", + linenum, **seg); + return -1; + } + (*seg)++; + if (**seg == NULL) { + fprintf(stderr, "%d: missing 2nd port value\n", + linenum); + return -1; + } + if (portnum(**seg, tp, linenum) == 0) + return -1; + } else if (!strcmp(**seg, "=") || !strcasecmp(**seg, "eq")) + comp = FR_EQUAL; + else if (!strcmp(**seg, "!=") || !strcasecmp(**seg, "ne")) + comp = FR_NEQUAL; + else if (!strcmp(**seg, "<") || !strcasecmp(**seg, "lt")) + comp = FR_LESST; + else if (!strcmp(**seg, ">") || !strcasecmp(**seg, "gt")) + comp = FR_GREATERT; + else if (!strcmp(**seg, "<=") || !strcasecmp(**seg, "le")) + comp = FR_LESSTE; + else if (!strcmp(**seg, ">=") || !strcasecmp(**seg, "ge")) + comp = FR_GREATERTE; + else { + fprintf(stderr, "%d: unknown comparator (%s)\n", + linenum, **seg); + return -1; + } + if (comp != FR_OUTRANGE && comp != FR_INRANGE) { + (*seg)++; + if (portnum(**seg, pp, linenum) == 0) + return -1; + } + *cp = comp; + (*seg)++; + } + return 0; +} + + +/* + * find the port number given by the name, either from getservbyname() or + * straight atoi(). Return 1 on success, 0 on failure + */ +int portnum(name, port, linenum) +char *name; +u_short *port; +int linenum; +{ + struct servent *sp, *sp2; + u_short p1 = 0; + int i; + + if (isdigit(*name)) { + if (ratoi(name, &i, 0, USHRT_MAX)) { + *port = (u_short)i; + return 1; + } + fprintf(stderr, "%d: unknown port \"%s\"\n", linenum, name); + return 0; + } + if (proto != NULL && strcasecmp(proto, "tcp/udp") != 0) { + sp = getservbyname(name, proto); + if (sp) { + *port = ntohs(sp->s_port); + return 1; + } + fprintf(stderr, "%d: unknown service \"%s\".\n", linenum, name); + return 0; + } + sp = getservbyname(name, "tcp"); + if (sp) + p1 = sp->s_port; + sp2 = getservbyname(name, "udp"); + if (!sp || !sp2) { + fprintf(stderr, "%d: unknown tcp/udp service \"%s\".\n", + linenum, name); + return 0; + } + if (p1 != sp2->s_port) { + fprintf(stderr, "%d: %s %d/tcp is a different port to ", + linenum, name, p1); + fprintf(stderr, "%d: %s %d/udp\n", linenum, name, sp->s_port); + return 0; + } + *port = ntohs(p1); + return 1; +} + + +u_char tcp_flags(flgs, mask, linenum) +char *flgs; +u_char *mask; +int linenum; +{ + u_char tcpf = 0, tcpfm = 0, *fp = &tcpf; + char *s, *t; + + if (*flgs == '0') { + s = strchr(flgs, '/'); + if (s) + *s++ = '\0'; + tcpf = strtol(flgs, NULL, 0); + fp = &tcpfm; + } else + s = flgs; + + for (; *s; s++) { + if (*s == '/' && fp == &tcpf) { + fp = &tcpfm; + if (*(s + 1) == '0') + break; + continue; + } + if (!(t = index(flagset, *s))) { + fprintf(stderr, "%d: unknown flag (%c)\n", linenum, *s); + return 0; + } + *fp |= flags[t - flagset]; + } + + if (s && *s == '0') + tcpfm = strtol(s, NULL, 0); + + if (!tcpfm) + tcpfm = 0xff; + *mask = tcpfm; + return tcpf; +} + + +/* + * count consecutive 1's in bit mask. If the mask generated by counting + * consecutive 1's is different to that passed, return -1, else return # + * of bits. + */ +int countbits(ip) +u_32_t ip; +{ + u_32_t ipn; + int cnt = 0, i, j; + + ip = ipn = ntohl(ip); + for (i = 32; i; i--, ipn *= 2) + if (ipn & 0x80000000) + cnt++; + else + break; + ipn = 0; + for (i = 32, j = cnt; i; i--, j--) { + ipn *= 2; + if (j > 0) + ipn++; + } + if (ipn == ip) + return cnt; + return -1; +} + + +#ifdef USE_INET6 +int count6bits(msk) +u_32_t *msk; +{ + int i = 0, k; + u_32_t j; + + for (k = 3; k >= 0; k--) + if (msk[k] == 0xffffffff) + i += 32; + else { + for (j = msk[k]; j; j <<= 1) + if (j & 0x80000000) + i++; + } + return i; +} +#endif + + +char *portname(pr, port) +int pr, port; +{ + static char buf[32]; + struct protoent *p = NULL; + struct servent *sv = NULL, *sv1 = NULL; + + if (pr == -1) { + if ((sv = getservbyport(htons(port), "tcp"))) { + strncpy(buf, sv->s_name, sizeof(buf)-1); + buf[sizeof(buf)-1] = '\0'; + sv1 = getservbyport(htons(port), "udp"); + sv = strncasecmp(buf, sv->s_name, strlen(buf)) ? + NULL : sv1; + } + if (sv) + return buf; + } else if (pr && (p = getprotobynumber(pr))) { + if ((sv = getservbyport(htons(port), p->p_name))) { + strncpy(buf, sv->s_name, sizeof(buf)-1); + buf[sizeof(buf)-1] = '\0'; + return buf; + } + } + + (void) sprintf(buf, "%d", port); + return buf; +} + + +int ratoi(ps, pi, min, max) +char *ps; +int *pi, min, max; +{ + int i; + char *pe; + + i = (int)strtol(ps, &pe, 0); + if (*pe != '\0' || i < min || i > max) + return 0; + *pi = i; + return 1; +} + + +int ratoui(ps, pi, min, max) +char *ps; +u_int *pi, min, max; +{ + u_int i; + char *pe; + + i = (u_int)strtol(ps, &pe, 0); + if (*pe != '\0' || i < min || i > max) + return 0; + *pi = i; + return 1; +} + + +void printhostmask(v, addr, mask) +int v; +u_32_t *addr, *mask; +{ + struct in_addr ipa; + int ones; + +#ifdef USE_INET6 + if (v == 6) { + ones = count6bits(mask); + if (ones == 0 && !addr[0] && !addr[1] && !addr[2] && !addr[3]) + printf("any"); + else { + char ipbuf[64]; + printf("%s/%d", + inet_ntop(AF_INET6, addr, ipbuf, sizeof(ipbuf)), + ones); + } + } + else +#endif + if (!*addr && !*mask) + printf("any"); + else { + ipa.s_addr = *addr; + printf("%s", inet_ntoa(ipa)); + if ((ones = countbits(*mask)) == -1) { + ipa.s_addr = *mask; + printf("/%s", inet_ntoa(ipa)); + } else + printf("/%d", ones); + } +} + + +void printportcmp(pr, frp) +int pr; +frpcmp_t *frp; +{ + static char *pcmp1[] = { "*", "=", "!=", "<", ">", "<=", ">=", + "<>", "><"}; + + if (frp->frp_cmp == FR_INRANGE || frp->frp_cmp == FR_OUTRANGE) + printf(" port %d %s %d", frp->frp_port, + pcmp1[frp->frp_cmp], frp->frp_top); + else + printf(" port %s %s", pcmp1[frp->frp_cmp], + portname(pr, frp->frp_port)); +} + + +void printbuf(buf, len, zend) +char *buf; +int len, zend; +{ + char *s, c; + int i; + + for (s = buf, i = len; i; i--) { + c = *s++; + if (isprint(c)) + putchar(c); + else + printf("\\%03o", c); + if ((c == '\0') && zend) + break; + } +} diff --git a/sbin/ipf/facpri.c b/sbin/ipf/facpri.c index 00434b42a0f..4333b4345fd 100644 --- a/sbin/ipf/facpri.c +++ b/sbin/ipf/facpri.c @@ -1,7 +1,7 @@ -/* $OpenBSD: facpri.c,v 1.4 2000/03/13 23:40:19 kjell Exp $ */ +/* $OpenBSD: facpri.c,v 1.5 2001/01/17 05:00:58 fgsch Exp $ */ /* - * Copyright (C) 1993-1998 by Darren Reed. + * Copyright (C) 1993-2000 by Darren Reed. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and due credit is given @@ -21,7 +21,7 @@ #include "facpri.h" #if !defined(lint) -static const char rcsid[] = "@(#)$IPFilter: facpri.c,v 1.2 1999/08/01 11:10:45 darrenr Exp $"; +static const char rcsid[] = "@(#)$IPFilter: facpri.c,v 1.3 2000/03/13 22:10:18 darrenr Exp $"; #endif typedef struct table { diff --git a/sbin/ipf/facpri.h b/sbin/ipf/facpri.h index 8f819136b34..68621f5b4a2 100644 --- a/sbin/ipf/facpri.h +++ b/sbin/ipf/facpri.h @@ -1,12 +1,12 @@ -/* $OpenBSD: facpri.h,v 1.4 2000/03/13 23:40:19 kjell Exp $ */ +/* $OpenBSD: facpri.h,v 1.5 2001/01/17 05:00:58 fgsch Exp $ */ /* - * Copyright (C) 1999 by Darren Reed. + * Copyright (C) 1999-2000 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. - * $IPFilter: facpri.h,v 1.2 1999/08/01 11:10:46 darrenr Exp $ + * $IPFilter: facpri.h,v 1.3 2000/03/13 22:10:18 darrenr Exp $ */ #ifndef __FACPRI_H__ diff --git a/sbin/ipf/ifaddr.c b/sbin/ipf/ifaddr.c index 3f162c361a3..5e4d46242ef 100644 --- a/sbin/ipf/ifaddr.c +++ b/sbin/ipf/ifaddr.c @@ -1,14 +1,13 @@ -/* $OpenBSD: ifaddr.c,v 1.5 2000/04/05 05:35:28 kjell Exp $ */ +/* $OpenBSD: ifaddr.c,v 1.6 2001/01/17 05:00:58 fgsch Exp $ */ + #include <sys/types.h> -#include <sys/ioctl.h> #include <sys/socket.h> -#include <net/if.h> +#include <sys/ioctl.h> #include <netinet/in.h> +#include <net/if.h> +#include <arpa/inet.h> +#include <string.h> #include <err.h> -#include <stdlib.h> -#include <unistd.h> -#include "ifaddr.h" - /* * if_addr(): @@ -19,58 +18,27 @@ * suggests inclusion into other platforms. The closest alternative is * to define /etc/networks with suitable values. */ -int if_addr(name, ap) -char *name; -struct in_addr *ap; +int if_addr(name, ap) + char *name; + struct in_addr *ap; { - struct ifconf ifc; - struct ifreq ifreq, *ifr; - char *inbuf = NULL; - int s, i, len = 8192; + struct sockaddr_in *sin; + struct ifreq ifr; + int s; + + if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { + warn("socket"); + return (0); + } + + strncpy(ifr.ifr_name, name, IFNAMSIZ); + ifr.ifr_name[IFNAMSIZ - 1] = '\0'; - if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { - warn("socket"); - return 0; - } + if (ioctl(s, SIOCGIFADDR, &ifr) < 0) + return (0); - 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)); - 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; - *ap = sin->sin_addr; - return (1); - } - } + sin = (struct sockaddr_in *)&ifr.ifr_addr; + *ap = sin->sin_addr; -if_addr_lose: - close(s); - free(inbuf); - return 0; + return (1); } diff --git a/sbin/ipf/ifaddr.h b/sbin/ipf/ifaddr.h index bb882dcddf7..34e01f42fc5 100644 --- a/sbin/ipf/ifaddr.h +++ b/sbin/ipf/ifaddr.h @@ -1,8 +1,3 @@ -/* $OpenBSD: ifaddr.h,v 1.5 2000/04/05 05:35:28 kjell Exp $ */ +/* $OpenBSD: ifaddr.h,v 1.6 2001/01/17 05:00:58 fgsch Exp $ */ -#ifndef __IFADDR_H__ -#define __IFADDR_H__ - -int if_addr __P((char *, struct in_addr *)); - -#endif +int if_addr __P((char *, struct in_addr *)); diff --git a/sbin/ipf/ipf.c b/sbin/ipf/ipf.c index 9a978846565..f012e109a8f 100644 --- a/sbin/ipf/ipf.c +++ b/sbin/ipf/ipf.c @@ -1,7 +1,7 @@ -/* $OpenBSD: ipf.c,v 1.24 2000/04/12 21:51:48 kjell Exp $ */ +/* $OpenBSD: ipf.c,v 1.25 2001/01/17 05:00:58 fgsch Exp $ */ /* - * Copyright (C) 1993-1998 by Darren Reed. + * Copyright (C) 1993-2000 by Darren Reed. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and due credit is given @@ -36,15 +36,16 @@ #include <netdb.h> #include <arpa/nameser.h> #include <resolv.h> -#include <netinet/ip_fil_compat.h> +#include <netinet/ip_compat.h> #include <netinet/ip_fil.h> #include <netinet/ip_nat.h> +#include <netinet/ip_state.h> #include "ipf.h" #include <netinet/ipl.h> #if !defined(lint) -static const char sccsid[] = "@(#)ipf.c 1.23 6/5/96 (C) 1993-1995 Darren Reed"; -static const char rcsid[] = "@(#)$IPFilter: ipf.c,v 2.2.2.1 2000/02/16 14:40:39 darrenr Exp $"; +static const char sccsid[] = "@(#)ipf.c 1.23 6/5/96 (C) 1993-2000 Darren Reed"; +static const char rcsid[] = "@(#)$IPFilter: ipf.c,v 2.10.2.5 2000/10/25 10:37:11 darrenr Exp $"; #endif #if SOLARIS @@ -55,14 +56,15 @@ extern char *index __P((const char *, int)); #endif extern char *optarg; -extern int optind; -extern int optreset; void frsync __P((void)); void zerostats __P((void)); int main __P((int, char *[])); int opts = 0; +#ifdef USE_INET6 +int use_inet6 = 0; +#endif static int fd = -1; @@ -71,25 +73,16 @@ 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 *getline __P((char *, size_t, FILE *, int *)); static char *ipfname = IPL_NAME; static void usage __P((void)); static void showversion __P((void)); static int get_flags __P((void)); -#if SOLARIS -#define OPTS "AdDEf:F:Il:noPrsUvVyzZ" -#else -#define OPTS "AdDEf:F:Il:noPrsvVyzZ" -#endif static void usage() { -#if SOLARIS - fprintf(stderr, "usage: ipf [-AdDEInoPrsUvVyzZ] %s %s %s\n", -#else - fprintf(stderr, "usage: ipf [-AdDEInoPrsvVyzZ] %s %s %s\n", -#endif + fprintf(stderr, "usage: ipf [-6AdDEInoPrsUvVyzZ] %s %s %s\n", "[-l block|pass|nomatch]", "[-F i|o|a|s|S]", "[-f filename]"); exit(1); } @@ -101,15 +94,16 @@ char *argv[]; { int c; - while ((c = getopt(argc, argv, OPTS)) != -1) - if (c == '?') - usage(); - - optreset = 1; - optind = 1; - while ((c = getopt(argc, argv, OPTS)) != -1) { + while ((c = getopt(argc, argv, "6AdDEf:F:Il:noPrsUvVyzZ")) != -1) { switch (c) { + case '?' : + usage(); +#ifdef USE_INET6 + case '6' : + use_inet6 = 1; + break; +#endif case 'A' : opts &= ~OPT_INACTIVE; break; @@ -138,7 +132,6 @@ char *argv[]; opts |= OPT_DONOTHING; break; case 'o' : - opts |= OPT_OUTQUE; break; case 'P' : ipfname = IPL_AUTH; @@ -191,7 +184,7 @@ char *ipfdev; if (!(opts & OPT_DONOTHING) && fd == -1) if ((fd = open(ipfdev, O_RDWR)) == -1) - if ((fd = open(ipfname, O_RDONLY)) == -1) + if ((fd = open(ipfdev, O_RDONLY)) == -1) perror("open device"); return fd; } @@ -209,7 +202,7 @@ static int get_flags() int i; if ((opendevice(ipfname) != -2) && (ioctl(fd, SIOCGETFF, &i) == -1)) { - perror("SIOCFRENB"); + perror("SIOCGETFF"); return 0; } return i; @@ -220,8 +213,13 @@ static void set_state(enable) u_int enable; { if (opendevice(ipfname) != -2) - if (ioctl(fd, SIOCFRENB, &enable) == -1) - perror("SIOCFRENB"); + if (ioctl(fd, SIOCFRENB, &enable) == -1) { + if (errno == EBUSY) + fprintf(stderr, + "IP FIlter: already initialized\n"); + else + perror("SIOCFRENB"); + } return; } @@ -256,8 +254,7 @@ char *name, *file; exit(1); } - while (getline(line, sizeof(line), fp)) { - linenum++; + while (getline(line, sizeof(line), fp, &linenum)) { /* * treat CR as EOL. LF is converted to NUL by getline(). */ @@ -299,24 +296,31 @@ char *name, *file; if ((opts & OPT_ZERORULEST) && !(opts & OPT_DONOTHING)) { - if (ioctl(fd, add, fr) == -1) + if (ioctl(fd, add, &fr) == -1) { + fprintf(stderr, "%d:", linenum); perror("ioctl(SIOCZRLST)"); - else { + } else { #ifdef USE_QUAD_T printf("hits %qd bytes %qd ", + (long long)fr->fr_hits, + (long long)fr->fr_bytes); #else printf("hits %ld bytes %ld ", -#endif fr->fr_hits, fr->fr_bytes); +#endif printfr(fr); } } else if ((opts & OPT_REMOVE) && !(opts & OPT_DONOTHING)) { - if (ioctl(fd, del, fr) == -1) - perror("ioctl(SIOCDELFR)"); + if (ioctl(fd, del, &fr) == -1) { + fprintf(stderr, "%d:", linenum); + perror("ioctl(delete rule)"); + } } else if (!(opts & OPT_DONOTHING)) { - if (ioctl(fd, add, fr) == -1) - perror("ioctl(SIOCADDFR)"); + if (ioctl(fd, add, &fr) == -1) { + fprintf(stderr, "%d:", linenum); + perror("ioctl(add/insert rule)"); + } } } } @@ -332,16 +336,17 @@ char *name, *file; * Similar to fgets(3) but can handle '\\' and NL is converted to NUL. * Returns NULL if error occured, EOF encounterd or input line is too long. */ -static char *getline(str, size, file) +static char *getline(str, size, file, linenum) register char *str; size_t size; FILE *file; +int *linenum; { char *p; int s, len; do { - for (p = str, s = size;; p += len, s -= len) { + for (p = str, s = size;; p += (len - 1), s -= (len - 1)) { /* * if an error occured, EOF was encounterd, or there * was no room to put NUL, return NULL. @@ -349,12 +354,22 @@ FILE *file; if (fgets(p, s, file) == NULL) return (NULL); len = strlen(p); + if (p[len - 1] != '\n') { + p[len] = '\0'; + break; + } + (*linenum)++; p[len - 1] = '\0'; - if (p[len - 1] != '\\') + if (len < 2 || p[len - 2] != '\\') break; - size -= len; + else + /* + * Convert '\\' to a space so words don't + * run together + */ + p[len - 2] = ' '; } - } while (*str == '\0' || *str == '\n'); + } while (*str == '\0'); return (str); } @@ -468,13 +483,14 @@ void frsync() void zerostats() { friostat_t fio; + friostat_t *fiop = &fio; if (opendevice(ipfname) != -2) { - if (ioctl(fd, SIOCFRZST, &fio) == -1) { + if (ioctl(fd, SIOCFRZST, &fiop) == -1) { perror("ioctl(SIOCFRZST)"); exit(-1); } - showstats(&fio); + showstats(fiop); } } @@ -542,15 +558,24 @@ static void blockunknown() static void showversion() { struct friostat fio; + struct friostat *fiop=&fio; u_32_t flags; char *s; + int vfd; - printf("ipf: %s (%d)\n", IPL_VERSION, sizeof(frentry_t)); + printf("ipf: %s (%d)\n", IPL_VERSION, (int)sizeof(frentry_t)); + + if ((vfd = open(ipfname, O_RDONLY)) == -1) { + perror("open device"); + return; + } - if (opendevice(ipfname) != -2 && ioctl(fd, SIOCGETFS, &fio)) { - perror("ioctl(SIOCGETFS"); + if (ioctl(vfd, SIOCGETFS, &fiop)) { + perror("ioctl(SIOCGETFS)"); + close(vfd); return; } + close(vfd); flags = get_flags(); printf("Kernel: %-*.*s\n", (int)sizeof(fio.f_version), diff --git a/sbin/ipf/ipf.h b/sbin/ipf/ipf.h index f4f8c5d7d00..164bacda75f 100644 --- a/sbin/ipf/ipf.h +++ b/sbin/ipf/ipf.h @@ -1,14 +1,14 @@ -/* $OpenBSD: ipf.h,v 1.14 2000/03/13 23:40:19 kjell Exp $ */ +/* $OpenBSD: ipf.h,v 1.15 2001/01/17 05:00:59 fgsch Exp $ */ /* - * Copyright (C) 1993-1998 by Darren Reed. + * Copyright (C) 1993-2000 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 - * $IPFilter: ipf.h,v 2.1.2.1 1999/10/05 12:59:25 darrenr Exp $ + * $IPFilter: ipf.h,v 2.9.2.2 2000/05/06 11:20:20 darrenr Exp $ */ #ifndef __IPF_H__ @@ -39,6 +39,14 @@ #define OPT_RAW 0x080000 #define OPT_NAT 0x100000 #define OPT_GROUPS 0x200000 +#define OPT_STATETOP 0x400000 +#define OPT_FLUSH 0x800000 +#define OPT_CLEAR 0x1000000 +#define OPT_NODO 0x80000000 + +#define OPT_STAT OPT_FRSTATES +#define OPT_LIST OPT_SHOWLIST + #ifndef __P # ifdef __STDC__ @@ -48,6 +56,8 @@ # endif #endif +struct frpcmp; + #ifdef ultrix extern char *strdup __P((char *)); #endif @@ -67,10 +77,26 @@ struct ipopt_names { }; +extern char *proto; +extern char flagset[]; +extern u_char flags[]; + +extern u_char tcp_flags __P((char *, u_char *, int)); +extern int countbits __P((u_32_t)); +extern int ratoi __P((char *, int *, int, int)); +extern int ratoui __P((char *, u_int *, u_int, u_int)); +extern int hostmask __P((char ***, u_32_t *, u_32_t *, u_short *, int *, + u_short *, int)); +extern int ports __P((char ***, u_short *, int *, u_short *, int)); +extern char *portname __P((int, int)); extern u_32_t buildopts __P((char *, char *, int)); -extern u_32_t hostnum __P((char *, int *, int)); +extern int genmask __P((char *, u_32_t *)); +extern int hostnum __P((u_32_t *, char *, int)); extern u_32_t optname __P((char ***, u_short *, int)); extern void printpacket __P((ip_t *)); +extern void printportcmp __P((int, struct frpcmp *)); +extern void printhostmask __P((int, u_32_t *, u_32_t *)); +extern void printbuf __P((char *, int, int)); #if SOLARIS extern int inet_aton __P((const char *, struct in_addr *)); extern int gethostname __P((char *, int )); diff --git a/sbin/ipf/opt.c b/sbin/ipf/opt.c index 99fbcda9529..38a414bc5c8 100644 --- a/sbin/ipf/opt.c +++ b/sbin/ipf/opt.c @@ -1,7 +1,7 @@ -/* $OpenBSD: opt.c,v 1.14 2000/03/13 23:40:19 kjell Exp $ */ +/* $OpenBSD: opt.c,v 1.15 2001/01/17 05:00:59 fgsch Exp $ */ /* - * Copyright (C) 1993-1998 by Darren Reed. + * Copyright (C) 1993-2000 by Darren Reed. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and due credit is given @@ -22,14 +22,14 @@ #include <netinet/tcp.h> #include <net/if.h> #include <arpa/inet.h> -#include <netinet/ip_fil_compat.h> +#include <netinet/ip_compat.h> #include <netinet/tcpip.h> #include <netinet/ip_fil.h> #include "ipf.h" #if !defined(lint) -static const char sccsid[] = "@(#)opt.c 1.8 4/10/96 (C) 1993-1995 Darren Reed"; -static const char rcsid[] = "@(#)$IPFilter: opt.c,v 2.1 1999/08/04 17:30:15 darrenr Exp $"; +static const char sccsid[] = "@(#)opt.c 1.8 4/10/96 (C) 1993-2000 Darren Reed"; +static const char rcsid[] = "@(#)$IPFilter: opt.c,v 2.2 2000/03/13 22:10:26 darrenr Exp $"; #endif extern int opts; diff --git a/sbin/ipf/parse.c b/sbin/ipf/parse.c index 9b6b38f10c5..1ff6e70069d 100644 --- a/sbin/ipf/parse.c +++ b/sbin/ipf/parse.c @@ -1,7 +1,7 @@ -/* $OpenBSD: parse.c,v 1.35 2000/08/10 05:50:27 kjell Exp $ */ +/* $OpenBSD: parse.c,v 1.36 2001/01/17 05:00:59 fgsch Exp $ */ /* - * Copyright (C) 1993-1998 by Darren Reed. + * Copyright (C) 1993-2000 by Darren Reed. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and due credit is given @@ -36,56 +36,35 @@ #include <resolv.h> #include <ctype.h> #include <syslog.h> -#include <netinet/ip_fil_compat.h> +#include <netinet/ip_compat.h> #include <netinet/ip_fil.h> #include "ipf.h" #include "facpri.h" #if !defined(lint) -static const char sccsid[] = "@(#)parse.c 1.44 6/5/96 (C) 1993-1996 Darren Reed"; -static const char rcsid[] = "@(#)$IPFilter: parse.c,v 2.1.2.14 2000/06/21 14:50:52 darrenr Exp $"; +static const char sccsid[] = "@(#)parse.c 1.44 6/5/96 (C) 1993-2000 Darren Reed"; +static const char rcsid[] = "@(#)$IPFilter: parse.c,v 2.8 1999/12/28 10:49:46 darrenr Exp $"; #endif extern struct ipopt_names ionames[], secclass[]; extern int opts; +#ifdef USE_INET6 +extern int use_inet6; +#endif -int portnum __P((char *, u_short *, int)); -u_char tcp_flags __P((char *, u_char *, int)); int addicmp __P((char ***, struct frentry *, int)); int extras __P((char ***, struct frentry *, int)); -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)); -int ports __P((char ***, u_short *, u_char *, u_short *, int)); + int icmpcode __P((char *)), addkeep __P((char ***, struct frentry *, int)); int to_interface __P((frdest_t *, char *, int)); void print_toif __P((char *, frdest_t *)); void optprint __P((u_short *, u_long, u_long)); -int countbits __P((u_32_t)); -char *portname __P((int, int)); -int ratoi __P((char *, int *, int, int)); -int loglevel __P((char **, u_short *, int)); +int loglevel __P((char **, u_int *, int)); void printlog __P((frentry_t *)); -#if defined(__OpenBSD__) -extern int if_addr __P((char *, struct in_addr *)); -#endif - -char *proto = NULL; -char flagset[] = "FSRPAU"; -u_char flags[] = { TH_FIN, TH_SYN, TH_RST, TH_PUSH, TH_ACK, TH_URG }; - -static char thishost[MAXHOSTNAMELEN]; - - -void initparse() -{ - gethostname(thishost, sizeof(thishost)); -} +extern char *proto; +extern char flagset[]; +extern u_char flags[]; /* parse() @@ -99,8 +78,8 @@ int linenum; static struct frentry fil; struct protoent *p = NULL; char *cps[31], **cpp, *endptr; - u_char ch; - int i, cnt = 1, j; + int i, cnt = 1, j, ch; + u_int k; while (*line && isspace(*line)) line++; @@ -109,7 +88,11 @@ int linenum; bzero((char *)&fil, sizeof(fil)); fil.fr_mip.fi_v = 0xf; +#ifdef USE_INET6 + fil.fr_ip.fi_v = use_inet6 ? 6 : 4; +#else fil.fr_ip.fi_v = 4; +#endif fil.fr_loglevel = 0xffff; /* @@ -176,8 +159,8 @@ int linenum; fil.fr_flags |= FR_PREAUTH; } else if (!strcasecmp("skip", *cpp)) { cpp++; - if (ratoi(*cpp, &i, 0, USHRT_MAX)) - fil.fr_skip = i; + if (ratoui(*cpp, &k, 0, UINT_MAX)) + fil.fr_skip = k; else { fprintf(stderr, "%d: integer must follow skip\n", linenum); @@ -265,43 +248,6 @@ int linenum; cpp++; } if (*cpp && !strcasecmp(*cpp, "level")) { - int fac, pri; - char *s; - - fac = 0; - pri = 0; - if (!*++cpp) { - fprintf(stderr, "%d: %s\n", linenum, - "missing identifier after level"); - return NULL; - } - s = index(*cpp, '.'); - if (s) { - *s++ = '\0'; - fac = fac_findname(*cpp); - if (fac == -1) { - fprintf(stderr, "%d: %s %s\n", linenum, - "Unknown facility", *cpp); - return NULL; - } - pri = pri_findname(s); - if (pri == -1) { - fprintf(stderr, "%d: %s %s\n", linenum, - "Unknown priority", s); - return NULL; - } - } else { - pri = pri_findname(*cpp); - if (pri == -1) { - fprintf(stderr, "%d: %s %s\n", linenum, - "Unknown priority", *cpp); - return NULL; - } - } - fil.fr_loglevel = fac|pri; - cpp++; - } - if (*cpp && !strcasecmp(*cpp, "level")) { if (loglevel(cpp, &fil.fr_loglevel, linenum) == -1) return NULL; cpp++; @@ -450,16 +396,17 @@ int linenum; linenum); return NULL; } - ch = 0; if (**cpp == '!') { fil.fr_flags |= FR_NOTSRCIP; (*cpp)++; } + ch = 0; if (hostmask(&cpp, (u_32_t *)&fil.fr_src, (u_32_t *)&fil.fr_smsk, &fil.fr_sport, &ch, &fil.fr_stop, linenum)) { return NULL; } + fil.fr_scmp = ch; if (!*cpp) { fprintf(stderr, "%d: missing to fields\n", linenum); @@ -521,7 +468,8 @@ int linenum; /* * extras... */ - if (*cpp && (!strcasecmp(*cpp, "with") || !strcasecmp(*cpp, "and"))) + if ((fil.fr_v == 4) && *cpp && (!strcasecmp(*cpp, "with") || + !strcasecmp(*cpp, "and"))) if (extras(&cpp, &fil, linenum)) return NULL; @@ -556,8 +504,8 @@ int linenum; fprintf(stderr, "%d: head without group #\n", linenum); return NULL; } - if (ratoi(*cpp, &i, 0, USHRT_MAX)) - fil.fr_grhead = i; + if (ratoui(*cpp, &k, 0, UINT_MAX)) + fil.fr_grhead = (u_32_t)k; else { fprintf(stderr, "%d: invalid group (%s)\n", linenum, *cpp); @@ -575,8 +523,8 @@ int linenum; linenum); return NULL; } - if (ratoi(*cpp, &i, 0, USHRT_MAX)) - fil.fr_group = i; + if (ratoui(*cpp, &k, 0, UINT_MAX)) + fil.fr_group = k; else { fprintf(stderr, "%d: invalid group (%s)\n", linenum, *cpp); @@ -630,7 +578,7 @@ int linenum; int loglevel(cpp, facpri, linenum) char **cpp; -u_short *facpri; +u_int *facpri; int linenum; { int fac, pri; @@ -677,15 +625,13 @@ frdest_t *fdp; char *to; int linenum; { - int r = 0; - char *s; + char *s; s = index(to, ':'); fdp->fd_ifp = NULL; if (s) { *s++ = '\0'; - fdp->fd_ip.s_addr = hostnum(s, &r, linenum); - if (r == -1) + if (hostnum((u_32_t *)&fdp->fd_ip, s, linenum) == -1) return -1; } (void) strncpy(fdp->fd_ifname, to, sizeof(fdp->fd_ifname) - 1); @@ -707,279 +653,6 @@ frdest_t *fdp; /* - * returns -1 if neither "hostmask/num" or "hostmask mask addr" are - * found in the line segments, there is an error processing this information, - * or there is an error processing ports information. - */ -int hostmask(seg, sa, msk, pp, cp, tp, linenum) -char ***seg; -u_32_t *sa, *msk; -u_short *pp, *tp; -u_char *cp; -int linenum; -{ - char *s, *endptr; - int bits = -1, resolved; - struct in_addr maskaddr; - - /* - * is it possibly hostname/num ? - */ - if ((s = index(**seg, '/')) || (s = index(**seg, ':'))) { - *s++ = '\0'; - if (index(s, '.') || index(s, 'x')) { - /* possibly of the form xxx.xxx.xxx.xxx - * or 0xYYYYYYYY */ - if (inet_aton(s, &maskaddr) == 0) { - fprintf(stderr, "%d: bad mask (%s)\n", - linenum, s); - return -1; - } - *msk = maskaddr.s_addr; - } else { - /* - * set x most significant bits - */ - bits = (int)strtol(s, &endptr, 0); - if (*endptr != '\0' || bits > 32 || bits < 0) { - fprintf(stderr, "%d: bad mask (/%s)\n", - linenum, s); - return -1; - } - if (bits == 0) - *msk = 0; - else - *msk = htonl(0xffffffff << (32 - bits)); - } - *sa = hostnum(**seg, &resolved, linenum) & *msk; - if (resolved == -1) { - fprintf(stderr, "%d: bad host (%s)\n", linenum, **seg); - return -1; - } - (*seg)++; - return ports(seg, pp, cp, tp, linenum); - } - - /* - * look for extra segments if "mask" found in right spot - */ - if (*(*seg+1) && *(*seg+2) && !strcasecmp(*(*seg+1), "mask")) { - *sa = hostnum(**seg, &resolved, linenum); - if (resolved == -1) { - fprintf(stderr, "%d: bad host (%s)\n", linenum, **seg); - return -1; - } - (*seg)++; - (*seg)++; - if (inet_aton(**seg, &maskaddr) == 0) { - fprintf(stderr, "%d: bad mask (%s)\n", linenum, **seg); - return -1; - } - *msk = maskaddr.s_addr; - (*seg)++; - *sa &= *msk; - return ports(seg, pp, cp, tp, linenum); - } - - if (**seg) { - *sa = hostnum(**seg, &resolved, linenum); - if (resolved == -1) { - fprintf(stderr, "%d: bad host (%s)\n", linenum, **seg); - return -1; - } - (*seg)++; - *msk = (*sa ? inet_addr("255.255.255.255") : 0L); - *sa &= *msk; - return ports(seg, pp, cp, tp, linenum); - } - fprintf(stderr, "%d: bad host (%s)\n", linenum, **seg); - return -1; -} - -/* - * returns an ip address as a long var as a result of either a DNS lookup or - * straight inet_addr() call - */ -u_32_t hostnum(host, resolved, linenum) -char *host; -int *resolved; -int linenum; -{ - struct hostent *hp; - struct netent *np; - struct in_addr ip; -#if defined(__OpenBSD__) - struct in_addr addr; -#endif - - *resolved = 0; - if (!strcasecmp("any", host)) - return 0; - if (isdigit(*host) && inet_aton(host, &ip)) - return ip.s_addr; - - if (!strcasecmp("<thishost>", host)) - host = thishost; - -#if defined(__OpenBSD__) - /* attempt a map from interface name to address */ - if (if_addr(host, &addr)) - return (u_32_t)addr.s_addr; -#endif - - if (!(hp = gethostbyname(host))) { - if (!(np = getnetbyname(host))) { - *resolved = -1; - fprintf(stderr, "%d: can't resolve hostname: %s\n", - linenum, host); - return 0; - } - return htonl(np->n_net); - } - return *(u_32_t *)hp->h_addr; -} - -/* - * check for possible presence of the port fields in the line - */ -int ports(seg, pp, cp, tp, linenum) -char ***seg; -u_short *pp, *tp; -u_char *cp; -int linenum; -{ - int comp = -1; - - if (!*seg || !**seg || !***seg) - return 0; - if (!strcasecmp(**seg, "port") && *(*seg + 1) && *(*seg + 2)) { - (*seg)++; - if (isdigit(***seg) && *(*seg + 2)) { - if (portnum(**seg, pp, linenum) == 0) - return -1; - (*seg)++; - if (!strcmp(**seg, "<>")) - comp = FR_OUTRANGE; - else if (!strcmp(**seg, "><")) - comp = FR_INRANGE; - else { - fprintf(stderr, - "%d: unknown range operator (%s)\n", - linenum, **seg); - return -1; - } - (*seg)++; - if (**seg == NULL) { - fprintf(stderr, "%d: missing 2nd port value\n", - linenum); - return -1; - } - if (portnum(**seg, tp, linenum) == 0) - return -1; - } else if (!strcmp(**seg, "=") || !strcasecmp(**seg, "eq")) - comp = FR_EQUAL; - else if (!strcmp(**seg, "!=") || !strcasecmp(**seg, "ne")) - comp = FR_NEQUAL; - else if (!strcmp(**seg, "<") || !strcasecmp(**seg, "lt")) - comp = FR_LESST; - else if (!strcmp(**seg, ">") || !strcasecmp(**seg, "gt")) - comp = FR_GREATERT; - else if (!strcmp(**seg, "<=") || !strcasecmp(**seg, "le")) - comp = FR_LESSTE; - else if (!strcmp(**seg, ">=") || !strcasecmp(**seg, "ge")) - comp = FR_GREATERTE; - else { - fprintf(stderr, "%d: unknown comparator (%s)\n", - linenum, **seg); - return -1; - } - if (comp != FR_OUTRANGE && comp != FR_INRANGE) { - (*seg)++; - if (portnum(**seg, pp, linenum) == 0) - return -1; - } - *cp = comp; - (*seg)++; - } - return 0; -} - -/* - * find the port number given by the name, either from getservbyname() or - * straight atoi(). Return 1 on success, 0 on failure - */ -int portnum(name, port, linenum) -char *name; -u_short *port; -int linenum; -{ - struct servent *sp, *sp2; - u_short p1 = 0; - int i; - if (isdigit(*name)) { - if (ratoi(name, &i, 0, USHRT_MAX)) { - *port = (u_short)i; - return 1; - } - fprintf(stderr, "%d: unknown port \"%s\"\n", linenum, name); - return 0; - } - if (proto != NULL && strcasecmp(proto, "tcp/udp") != 0) { - sp = getservbyname(name, proto); - if (sp) { - *port = ntohs(sp->s_port); - return 1; - } - fprintf(stderr, "%d: unknown service \"%s\".\n", linenum, name); - return 0; - } - sp = getservbyname(name, "tcp"); - if (sp) - p1 = sp->s_port; - sp2 = getservbyname(name, "udp"); - if (!sp || !sp2) { - fprintf(stderr, "%d: unknown tcp/udp service \"%s\".\n", - linenum, name); - return 0; - } - if (p1 != sp2->s_port) { - fprintf(stderr, "%d: %s %d/tcp is a different port to ", - linenum, name, p1); - fprintf(stderr, "%d: %s %d/udp\n", linenum, name, sp->s_port); - return 0; - } - *port = ntohs(p1); - return 1; -} - - -u_char tcp_flags(flgs, mask, linenum) -char *flgs; -u_char *mask; -int linenum; -{ - u_char tcpf = 0, tcpfm = 0, *fp = &tcpf; - char *s, *t; - - for (s = flgs; *s; s++) { - if (*s == '/' && fp == &tcpf) { - fp = &tcpfm; - continue; - } - if (!(t = index(flagset, *s))) { - fprintf(stderr, "%d: unknown flag (%c)\n", linenum, *s); - return 0; - } - *fp |= flags[t - flagset]; - } - if (!tcpfm) - tcpfm = 0xff; - *mask = tcpfm; - return tcpf; -} - - -/* * deal with extra bits on end of the line */ int extras(cp, fr, linenum) @@ -1000,8 +673,8 @@ int linenum; return -1; while (**cp && (!strncasecmp(**cp, "ipopt", 5) || - !strncasecmp(**cp, "not", 3) || !strncasecmp(**cp, "opt", 4) || - !strncasecmp(**cp, "frag", 3) || !strncasecmp(**cp, "no", 2) || + !strncasecmp(**cp, "not", 3) || !strncasecmp(**cp, "opt", 3) || + !strncasecmp(**cp, "frag", 4) || !strncasecmp(**cp, "no", 2) || !strncasecmp(**cp, "short", 5))) { if (***cp == 'n' || ***cp == 'N') { notopt = 1; @@ -1327,6 +1000,9 @@ struct frentry *fp; int linenum; { if (fp->fr_proto != IPPROTO_TCP && fp->fr_proto != IPPROTO_UDP && +#ifdef USE_INET6 + fp->fr_proto != IPPROTO_ICMPV6 && +#endif fp->fr_proto != IPPROTO_ICMP && !(fp->fr_ip.fi_fl & FI_TCPUDP)) { fprintf(stderr, "%d: Can only use keep with UDP/ICMP/TCP\n", linenum); @@ -1339,8 +1015,7 @@ int linenum; linenum); return -1; } - - if (**cp && strcasecmp(**cp, "state") && strcasecmp(**cp, "frags")) { + if (strcasecmp(**cp, "state") && strcasecmp(**cp, "frags")) { fprintf(stderr, "%d: Unrecognised state keyword \"%s\"\n", linenum, **cp); return -1; @@ -1356,77 +1031,16 @@ int linenum; /* - * count consecutive 1's in bit mask. If the mask generated by counting - * consecutive 1's is different to that passed, return -1, else return # - * of bits. - */ -int countbits(ip) -u_32_t ip; -{ - u_32_t ipn; - int cnt = 0, i, j; - - ip = ipn = ntohl(ip); - for (i = 32; i; i--, ipn *= 2) - if (ipn & 0x80000000) - cnt++; - else - break; - ipn = 0; - for (i = 32, j = cnt; i; i--, j--) { - ipn *= 2; - if (j > 0) - ipn++; - } - if (ipn == ip) - return cnt; - return -1; -} - - -char *portname(pr, port) -int pr, port; -{ - static char buf[32]; - struct protoent *p = NULL; - struct servent *sv = NULL, *sv1 = NULL; - - if (pr == -1) { - if ((sv = getservbyport(htons(port), "tcp"))) { - strncpy(buf, sv->s_name, sizeof(buf)-1); - buf[sizeof(buf)-1] = '\0'; - sv1 = getservbyport(htons(port), "udp"); - sv = strncasecmp(buf, sv->s_name, strlen(buf)) ? - NULL : sv1; - } - if (sv) - return buf; - } else if (pr && (p = getprotobynumber(pr))) { - if ((sv = getservbyport(htons(port), p->p_name))) { - strncpy(buf, sv->s_name, sizeof(buf)-1); - buf[sizeof(buf)-1] = '\0'; - return buf; - } - } - - (void) sprintf(buf, "%d", port); - return buf; -} - - -/* * print the filter structure in a useful way */ void printfr(fp) struct frentry *fp; { - static char *pcmp1[] = { "*", "=", "!=", "<", ">", "<=", ">=", - "<>", "><"}; - struct protoent *p; - int ones = 0, pr; - char *s; - u_char *t; + struct protoent *p; u_short sec[2]; + char *s; + u_char *t; + int pr; if (fp->fr_flags & FR_PASS) printf("pass"); @@ -1467,6 +1081,7 @@ struct frentry *fp; printlog(fp); putchar(' '); } + if (fp->fr_flags & FR_QUICK) printf("quick "); @@ -1496,42 +1111,17 @@ struct frentry *fp; } printf("from %s", fp->fr_flags & FR_NOTSRCIP ? "!" : ""); - if (!fp->fr_src.s_addr && !fp->fr_smsk.s_addr) - printf("any "); - else { - printf("%s", inet_ntoa(fp->fr_src)); - if ((ones = countbits(fp->fr_smsk.s_addr)) == -1) - printf("/%s ", inet_ntoa(fp->fr_smsk)); - else - printf("/%d ", ones); - } - if (fp->fr_scmp) { - if (fp->fr_scmp == FR_INRANGE || fp->fr_scmp == FR_OUTRANGE) - printf("port %d %s %d ", fp->fr_sport, - pcmp1[fp->fr_scmp], fp->fr_stop); - else - printf("port %s %s ", pcmp1[fp->fr_scmp], - portname(pr, fp->fr_sport)); - } + printhostmask(fp->fr_v, (u_32_t *)&fp->fr_src.s_addr, + (u_32_t *)&fp->fr_smsk.s_addr); + if (fp->fr_scmp) + printportcmp(pr, &fp->fr_tuc.ftu_src); + + printf(" to %s", fp->fr_flags & FR_NOTDSTIP ? "!" : ""); + printhostmask(fp->fr_v, (u_32_t *)&fp->fr_dst.s_addr, + (u_32_t *)&fp->fr_dmsk.s_addr); + if (fp->fr_dcmp) + printportcmp(pr, &fp->fr_tuc.ftu_dst); - printf("to %s", fp->fr_flags & FR_NOTDSTIP ? "!" : ""); - if (!fp->fr_dst.s_addr && !fp->fr_dmsk.s_addr) - printf("any"); - else { - printf("%s", inet_ntoa(fp->fr_dst)); - if ((ones = countbits(fp->fr_dmsk.s_addr)) == -1) - printf("/%s", inet_ntoa(fp->fr_dmsk)); - else - printf("/%d", ones); - } - if (fp->fr_dcmp) { - if (fp->fr_dcmp == FR_INRANGE || fp->fr_dcmp == FR_OUTRANGE) - printf(" port %d %s %d", fp->fr_dport, - pcmp1[fp->fr_dcmp], fp->fr_dtop); - else - printf(" port %s %s", pcmp1[fp->fr_dcmp], - portname(pr, fp->fr_dport)); - } if ((fp->fr_ip.fi_fl & ~FI_TCPUDP) || (fp->fr_mip.fi_fl & ~FI_TCPUDP) || fp->fr_ip.fi_optmsk || fp->fr_mip.fi_optmsk || @@ -1575,14 +1165,20 @@ struct frentry *fp; } if (fp->fr_proto == IPPROTO_TCP && (fp->fr_tcpf || fp->fr_tcpfm)) { printf(" flags "); - for (s = flagset, t = flags; *s; s++, t++) - if (fp->fr_tcpf & *t) - (void)putchar(*s); - if (fp->fr_tcpfm) { - (void)putchar('/'); + if (fp->fr_tcpf & ~TCPF_ALL) + printf("0x%x", fp->fr_tcpf); + else for (s = flagset, t = flags; *s; s++, t++) - if (fp->fr_tcpfm & *t) + if (fp->fr_tcpf & *t) (void)putchar(*s); + if (fp->fr_tcpfm) { + (void)putchar('/'); + if (fp->fr_tcpfm & ~TCPF_ALL) + printf("0x%x", fp->fr_tcpfm); + else + for (s = flagset, t = flags; *s; s++, t++) + if (fp->fr_tcpfm & *t) + (void)putchar(*s); } } @@ -1645,18 +1241,3 @@ frentry_t *fp; printf("%s", u); } } - - -int ratoi(ps, pi, min, max) -char *ps; -int *pi, min, max; -{ - int i; - char *pe; - - i = (int)strtol(ps, &pe, 0); - if (*pe != '\0' || i < min || i > max) - return 0; - *pi = i; - return 1; -} diff --git a/sbin/ipfstat/Makefile b/sbin/ipfstat/Makefile index ab29321d47e..60c98824ff7 100644 --- a/sbin/ipfstat/Makefile +++ b/sbin/ipfstat/Makefile @@ -1,11 +1,9 @@ -# $OpenBSD: Makefile,v 1.6 1999/12/16 07:38:45 kjell Exp $ +# $OpenBSD: Makefile,v 1.7 2001/01/17 05:01:00 fgsch Exp $ PROG= ipfstat MAN= ipfstat.8 -SRCS= fils.c parse.c opt.c kmem.c facpri.c ifaddr.c +SRCS= fils.c parse.c opt.c kmem.c facpri.c common.c ifaddr.c .PATH: ${.CURDIR}/../../sbin/ipf CFLAGS+=-I${.CURDIR}/../../sbin/ipf - - .include <bsd.prog.mk> diff --git a/sbin/ipfstat/fils.c b/sbin/ipfstat/fils.c index 9f005ecb62f..cbf412089c3 100644 --- a/sbin/ipfstat/fils.c +++ b/sbin/ipfstat/fils.c @@ -1,7 +1,7 @@ -/* $OpenBSD: fils.c,v 1.22 2000/11/14 18:56:31 aaron Exp $ */ +/* $OpenBSD: fils.c,v 1.23 2001/01/17 05:01:00 fgsch Exp $ */ /* - * Copyright (C) 1993-1998 by Darren Reed. + * Copyright (C) 1993-2000 by Darren Reed. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and due credit is given @@ -19,11 +19,18 @@ #include <sys/time.h> #include <sys/param.h> #include <sys/file.h> +#if defined(STATETOP) && defined(sun) && !defined(__svr4__) && !defined(__SVR4) +#include <sys/select.h> +#endif #include <stdlib.h> #include <unistd.h> #include <fcntl.h> #include <stddef.h> #include <nlist.h> +#ifdef STATETOP +#include <ctype.h> +#include <ncurses.h> +#endif #include <sys/socket.h> #include <sys/ioctl.h> #include <netinet/in.h> @@ -38,7 +45,11 @@ #include <arpa/nameser.h> #include <resolv.h> #include <netinet/tcp.h> -#include <netinet/ip_fil_compat.h> +#if defined(STATETOP) && !defined(linux) +# include <netinet/ip_var.h> +# include <netinet/tcp_fsm.h> +#endif +#include <netinet/ip_compat.h> #include <netinet/ip_fil.h> #include "ipf.h" #include <netinet/ip_proxy.h> @@ -46,16 +57,23 @@ #include <netinet/ip_frag.h> #include <netinet/ip_state.h> #include <netinet/ip_auth.h> +#ifdef STATETOP +#include <netinet/ipl.h> +#endif #include "kmem.h" #if defined(__NetBSD__) || (__OpenBSD__) # include <paths.h> #endif #if !defined(lint) -static const char sccsid[] = "@(#)fils.c 1.21 4/20/96 (C) 1993-1996 Darren Reed"; -static const char rcsid[] = "@(#)$IPFilter: fils.c,v 2.2.2.7 2000/05/24 20:34:56 darrenr Exp $"; +static const char sccsid[] = "@(#)fils.c 1.21 4/20/96 (C) 1993-2000 Darren Reed"; +static const char rcsid[] = "@(#)$IPFilter: fils.c,v 2.21.2.7 2000/12/02 00:13:56 darrenr Exp $"; #endif +extern char *optarg; + +#define PRINTF (void)printf +#define FPRINTF (void)fprintf #define F_IN 0 #define F_OUT 1 #define F_AC 2 @@ -63,8 +81,34 @@ static char *filters[4] = { "ipfilter(in)", "ipfilter(out)", "ipacct(in)", "ipacct(out)" }; int opts = 0; +#ifdef USE_INET6 +int use_inet6 = 0; +#endif + +#ifdef STATETOP +#define STSTRSIZE 80 +#define STGROWSIZE 16 -char *nlistf = NULL, *memf = NULL; +#define STSORT_PR 0 +#define STSORT_PKTS 1 +#define STSORT_BYTES 2 +#define STSORT_TTL 3 +#define STSORT_MAX STSORT_TTL +#define STSORT_DEFAULT STSORT_BYTES + + +typedef struct statetop { + union i6addr st_src; + union i6addr st_dst; + u_short st_sport; + u_short st_dport; + u_char st_p; + u_char st_state[2]; + U_QUAD_T st_pkts; + U_QUAD_T st_bytes; + u_long st_age; +} statetop_t; +#endif extern int main __P((int, char *[])); static void showstats __P((int, friostat_t *)); @@ -76,14 +120,49 @@ static void showgroups __P((friostat_t *)); static void Usage __P((char *)); static void printlist __P((frentry_t *)); static char *get_ifname __P((void *)); +static char *hostname __P((int, void *)); +static void parse_ipportstr __P((const char *, struct in_addr *, int *)); +#ifdef STATETOP +static void topipstates __P((int, struct in_addr, struct in_addr, int, int, int, int, int)); +static char *ttl_to_string __P((long)); +static int sort_p __P((const void *, const void *)); +static int sort_pkts __P((const void *, const void *)); +static int sort_bytes __P((const void *, const void *)); +static int sort_ttl __P((const void *, const void *)); +#endif + +static char *hostname(v, ip) +int v; +void *ip; +{ +#ifdef USE_INET6 + static char hostbuf[MAXHOSTNAMELEN+1]; +#endif + struct in_addr ipa; + + if (v == 4) { + ipa.s_addr = *(u_32_t *)ip; + return inet_ntoa(ipa); + } +#ifdef USE_INET6 + (void) inet_ntop(AF_INET6, ip, hostbuf, sizeof(hostbuf) - 1); + hostbuf[MAXHOSTNAMELEN] = '\0'; + return hostbuf; +#else + return "IPv6"; +#endif +} static void Usage(name) char *name; { - fprintf(stderr, - "usage: %s [-aAfghIinosv] [-d device] [-M core]\n", - name); +#ifdef USE_INET6 + fprintf(stderr, "Usage: %s [-6aAfhIinosv] [-d <device>]\n", name); +#else + fprintf(stderr, "Usage: %s [-aAfhIinosv] [-d <device>]\n", name); +#endif + fprintf(stderr, " %s -t [-S source address] [-D destination address] [-P protocol] [-T refreshtime] [-C] [-d <device>]\n", name); exit(1); } @@ -93,25 +172,57 @@ int argc; char *argv[]; { fr_authstat_t frauthst; + fr_authstat_t *frauthstp = &frauthst; friostat_t fio; + friostat_t *fiop=&fio; ips_stat_t ipsst; + ips_stat_t *ipsstp = &ipsst; ipfrstat_t ifrst; + ipfrstat_t *ifrstp = &ifrst; char *name = NULL, *device = IPL_NAME; int c, fd; + struct protoent *proto; + + int protocol = -1; /* -1 = wild card for any protocol */ + int refreshtime = 1; /* default update time */ + int sport = -1; /* -1 = wild card for any source port */ + int dport = -1; /* -1 = wild card for any dest port */ + int topclosed = 0; /* do not show closed tcp sessions */ + struct in_addr saddr, daddr; + saddr.s_addr = INADDR_ANY; /* default any source addr */ + daddr.s_addr = INADDR_ANY; /* default any dest addr */ + + if (openkmem() == -1) + exit(-1); + + (void)setuid(getuid()); + (void)setgid(getgid()); - while ((c = getopt(argc, argv, "AafhgIinosvd:M:")) != -1) + while ((c = getopt(argc, argv, "6aACfghIilnostvd:D:P:S:T:")) != -1) { switch (c) { +#ifdef USE_INET6 + case '6' : + use_inet6 = 1; + break; +#endif case 'a' : opts |= OPT_ACCNT|OPT_SHOWLIST; break; case 'A' : + device = IPAUTH_NAME; opts |= OPT_AUTHSTATS; break; + case 'C' : + topclosed = 1; + break; case 'd' : device = optarg; break; + case 'D' : + parse_ipportstr(optarg, &daddr, &dport); + break; case 'f' : opts |= OPT_FRSTATES; break; @@ -127,38 +238,59 @@ char *argv[]; case 'I' : opts |= OPT_INACTIVE; break; + case 'l' : + opts |= OPT_SHOWLIST; + break; case 'n' : opts |= OPT_SHOWLINENO; break; case 'o' : opts |= OPT_OUTQUE|OPT_SHOWLIST; break; + case 'P' : + if ((proto = getprotobyname(optarg)) != NULL) { + protocol = proto->p_proto; + } else if (!sscanf(optarg, "%ud", &protocol) || + (protocol < 0)) { + fprintf(stderr, "%s : Invalid protocol: %s\n", + argv[0], optarg); + exit(-2); + } + break; case 's' : opts |= OPT_IPSTATES; break; + case 'S' : + parse_ipportstr(optarg, &saddr, &sport); + break; + case 't' : +#ifdef STATETOP + opts |= OPT_STATETOP; + break; +#else + fprintf(stderr, + "%s : state top facility not compiled in\n", + argv[0]); + exit(-2); +#endif + case 'T' : + if (!sscanf(optarg, "%d", &refreshtime) || + (refreshtime <= 0)) { + fprintf(stderr, + "%s : Invalid refreshtime < 1 : %s\n", + argv[0], optarg); + exit(-2); + } + break; case 'v' : opts |= OPT_VERBOSE; break; - case 'M': - memf = optarg; - break; default : Usage(argv[0]); break; } } - if (nlistf != NULL || memf != NULL) { - (void)setuid(getuid()); - (void)setgid(getgid()); - } - - if (openkmem(nlistf, memf) == -1) - exit(-1); - - (void)setuid(getuid()); - (void)setgid(getgid()); - if ((fd = open(device, O_RDONLY)) < 0) { perror("open"); exit(-1); @@ -168,8 +300,8 @@ char *argv[]; bzero((char *)&ipsst, sizeof(ipsst)); bzero((char *)&ifrst, sizeof(ifrst)); - if (ioctl(fd, SIOCGETFS, &fio) == -1) { - perror("ioctl(SIOCGETFS)"); + if (!(opts & OPT_AUTHSTATS) && ioctl(fd, SIOCGETFS, &fiop) == -1) { + perror("ioctl(ipf:SIOCGETFS)"); exit(-1); } if ((opts & OPT_IPSTATES)) { @@ -179,39 +311,44 @@ char *argv[]; perror("open"); exit(-1); } - if ((ioctl(sfd, SIOCGIPST, &ipsst) == -1)) { - perror("ioctl(SIOCGIPST)"); + if ((ioctl(sfd, SIOCGETFS, &ipsstp) == -1)) { + perror("ioctl(state:SIOCGETFS)"); exit(-1); } close(sfd); } - if ((opts & OPT_FRSTATES) && (ioctl(fd, SIOCGFRST, &ifrst) == -1)) { + if ((opts & OPT_FRSTATES) && (ioctl(fd, SIOCGFRST, &ifrstp) == -1)) { perror("ioctl(SIOCGFRST)"); exit(-1); } if (opts & OPT_VERBOSE) - printf("opts %#x name %s\n", opts, name ? name : "<>"); + PRINTF("opts %#x name %s\n", opts, name ? name : "<>"); if ((opts & OPT_AUTHSTATS) && - (ioctl(fd, SIOCATHST, &frauthst) == -1)) { + (ioctl(fd, SIOCATHST, &frauthstp) == -1)) { perror("ioctl(SIOCATHST)"); exit(-1); } - if (opts & OPT_SHOWLIST) { + if (opts & OPT_IPSTATES) { + showipstates(fd, ipsstp); + } else if (opts & OPT_SHOWLIST) { showlist(&fio); if ((opts & OPT_OUTQUE) && (opts & OPT_INQUE)){ opts &= ~OPT_OUTQUE; showlist(&fio); } } else { - if (opts & OPT_IPSTATES) - showipstates(fd, &ipsst); - else if (opts & OPT_FRSTATES) - showfrstates(fd, &ifrst); + if (opts & OPT_FRSTATES) + showfrstates(fd, ifrstp); +#ifdef STATETOP + else if (opts & OPT_STATETOP) + topipstates(fd, saddr, daddr, sport, dport, + protocol, refreshtime, topclosed); +#endif else if (opts & OPT_AUTHSTATS) - showauthstates(fd, &frauthst); + showauthstates(fd, frauthstp); else if (opts & OPT_GROUPS) showgroups(&fio); else @@ -234,67 +371,72 @@ struct friostat *fp; perror("ioctl(SIOCGETFF)"); #if SOLARIS - printf("dropped packets:\tin %lu\tout %lu\n", + PRINTF("dropped packets:\tin %lu\tout %lu\n", fp->f_st[0].fr_drop, fp->f_st[1].fr_drop); - printf("non-data packets:\tin %lu\tout %lu\n", + PRINTF("non-data packets:\tin %lu\tout %lu\n", fp->f_st[0].fr_notdata, fp->f_st[1].fr_notdata); - printf("no-data packets:\tin %lu\tout %lu\n", + PRINTF("no-data packets:\tin %lu\tout %lu\n", fp->f_st[0].fr_nodata, fp->f_st[1].fr_nodata); - printf("non-ip packets:\t\tin %lu\tout %lu\n", + PRINTF("non-ip packets:\t\tin %lu\tout %lu\n", fp->f_st[0].fr_notip, fp->f_st[1].fr_notip); - printf(" bad packets:\t\tin %lu\tout %lu\n", + PRINTF(" bad packets:\t\tin %lu\tout %lu\n", fp->f_st[0].fr_bad, fp->f_st[1].fr_bad); - printf("copied messages:\tin %lu\tout %lu\n", + PRINTF("copied messages:\tin %lu\tout %lu\n", fp->f_st[0].fr_copy, fp->f_st[1].fr_copy); #endif - printf(" input packets:\t\tblocked %lu passed %lu nomatch %lu", +#ifdef USE_INET6 + PRINTF(" IPv6 packets:\t\tin %lu out %lu\n", + fp->f_st[0].fr_ipv6[0], fp->f_st[0].fr_ipv6[1]); +#endif + PRINTF(" input packets:\t\tblocked %lu passed %lu nomatch %lu", fp->f_st[0].fr_block, fp->f_st[0].fr_pass, fp->f_st[0].fr_nom); - printf(" counted %lu short %lu\n", + PRINTF(" counted %lu short %lu\n", fp->f_st[0].fr_acct, fp->f_st[0].fr_short); - printf("output packets:\t\tblocked %lu passed %lu nomatch %lu", + PRINTF("output packets:\t\tblocked %lu passed %lu nomatch %lu", fp->f_st[1].fr_block, fp->f_st[1].fr_pass, fp->f_st[1].fr_nom); - printf(" counted %lu short %lu\n", + PRINTF(" counted %lu short %lu\n", fp->f_st[1].fr_acct, fp->f_st[1].fr_short); - printf(" input packets logged:\tblocked %lu passed %lu\n", + PRINTF(" input packets logged:\tblocked %lu passed %lu\n", fp->f_st[0].fr_bpkl, fp->f_st[0].fr_ppkl); - printf("output packets logged:\tblocked %lu passed %lu\n", + PRINTF("output packets logged:\tblocked %lu passed %lu\n", fp->f_st[1].fr_bpkl, fp->f_st[1].fr_ppkl); - printf(" packets logged:\tinput %lu output %lu\n", + 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", + 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", + 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", + PRINTF("fragment state(out):\tkept %lu\tlost %lu\n", fp->f_st[1].fr_nfr, fp->f_st[1].fr_bnfr); - printf("packet state(in):\tkept %lu\tlost %lu\n", + PRINTF("packet state(in):\tkept %lu\tlost %lu\n", fp->f_st[0].fr_ads, fp->f_st[0].fr_bads); - printf("packet state(out):\tkept %lu\tlost %lu\n", + PRINTF("packet state(out):\tkept %lu\tlost %lu\n", fp->f_st[1].fr_ads, fp->f_st[1].fr_bads); - printf("ICMP replies:\t%lu\tTCP RSTs sent:\t%lu\n", + PRINTF("ICMP replies:\t%lu\tTCP RSTs sent:\t%lu\n", fp->f_st[0].fr_ret, fp->f_st[1].fr_ret); - printf("Result cache hits(in):\t%lu\t(out):\t%lu\n", + PRINTF("Invalid source(in):\t%lu\n", fp->f_st[0].fr_badsrc); + PRINTF("Result cache hits(in):\t%lu\t(out):\t%lu\n", fp->f_st[0].fr_chit, fp->f_st[1].fr_chit); - printf("IN Pullups succeeded:\t%lu\tfailed:\t%lu\n", + 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", + 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", + 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", + 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); + PRINTF("Packet log flags set: (%#x)\n", frf); if (frf & FF_LOGPASS) - printf("\tpackets passed through filter\n"); + PRINTF("\tpackets passed through filter\n"); if (frf & FF_LOGBLOCK) - printf("\tpackets blocked by filter\n"); + PRINTF("\tpackets blocked by filter\n"); if (frf & FF_LOGNOMATCH) - printf("\tpackets not matched by filter\n"); + PRINTF("\tpackets not matched by filter\n"); if (!frf) - printf("\tnone\n"); + PRINTF("\tnone\n"); } @@ -314,18 +456,18 @@ frentry_t *fp; fp->fr_flags |= FR_OUTQUE; if (opts & (OPT_HITS|OPT_VERBOSE)) #ifdef USE_QUAD_T - printf("%qu ", fp->fr_hits); + PRINTF("%qu ", (unsigned long long) fp->fr_hits); #else - printf("%lu ", fp->fr_hits); + PRINTF("%lu ", fp->fr_hits); #endif if (opts & (OPT_ACCNT|OPT_VERBOSE)) #ifdef USE_QUAD_T - printf("%qu ", fp->fr_bytes); + PRINTF("%qu ", (unsigned long long) fp->fr_bytes); #else - printf("%lu ", fp->fr_bytes); + PRINTF("%lu ", fp->fr_bytes); #endif if (opts & OPT_SHOWLINENO) - printf("@%d ", n); + PRINTF("@%d ", n); printfr(fp); if (opts & OPT_VERBOSE) binprint(fp); @@ -355,24 +497,35 @@ struct friostat *fiop; } else if (opts & OPT_INQUE) fp = (struct frentry *)fiop->f_acctin[set]; else { - fprintf(stderr, "No -i or -o given with -a\n"); + FPRINTF(stderr, "No -i or -o given with -a\n"); return; } - } else if (opts & OPT_OUTQUE) { - i = F_OUT; - fp = (struct frentry *)fiop->f_fout[set]; - } else if (opts & OPT_INQUE) { - i = F_IN; - fp = (struct frentry *)fiop->f_fin[set]; - } else - return; + } else { +#ifdef USE_INET6 + if ((use_inet6) && (opts & OPT_OUTQUE)) { + i = F_OUT; + fp = (struct frentry *)fiop->f_fout6[set]; + } else if ((use_inet6) && (opts & OPT_INQUE)) { + i = F_IN; + fp = (struct frentry *)fiop->f_fin6[set]; + } else +#endif + if (opts & OPT_OUTQUE) { + i = F_OUT; + fp = (struct frentry *)fiop->f_fout[set]; + } else if (opts & OPT_INQUE) { + i = F_IN; + fp = (struct frentry *)fiop->f_fin[set]; + } else + return; + } if (opts & OPT_VERBOSE) - fprintf(stderr, "showlist:opts %#x i %d\n", opts, i); + FPRINTF(stderr, "showlist:opts %#x i %d\n", opts, i); if (opts & OPT_VERBOSE) - printf("fp %p set %d\n", fp, set); + PRINTF("fp %p set %d\n", fp, set); if (!fp) { - fprintf(stderr, "empty list for %s%s\n", + FPRINTF(stderr, "empty list for %s%s\n", (opts & OPT_INACTIVE) ? "inactive " : "", filters[i]); return; } @@ -385,126 +538,433 @@ int fd; ips_stat_t *ipsp; { ipstate_t *istab[IPSTATE_SIZE], ips; - int i; - printf("IP states added:\n\t%lu TCP\n\t%lu UDP\n\t%lu ICMP\n", - ipsp->iss_tcp, ipsp->iss_udp, ipsp->iss_icmp); - printf("\t%lu hits\n\t%lu misses\n", ipsp->iss_hits, ipsp->iss_miss); - printf("\t%lu maximum\n\t%lu no memory\n\tbuckets in use\t%lu\n", - ipsp->iss_max, ipsp->iss_nomem, ipsp->iss_inuse); - printf("\t%lu active\n\t%lu expired\n\t%lu closed\n", - ipsp->iss_active, ipsp->iss_expire, ipsp->iss_fin); + if (!(opts & OPT_SHOWLIST)) { + PRINTF("IP states added:\n\t%lu TCP\n\t%lu UDP\n\t%lu ICMP\n", + ipsp->iss_tcp, ipsp->iss_udp, ipsp->iss_icmp); + PRINTF("\t%lu hits\n\t%lu misses\n", ipsp->iss_hits, + ipsp->iss_miss); + PRINTF("\t%lu maximum\n\t%lu no memory\n\t%lu bkts in use\n", + ipsp->iss_max, ipsp->iss_nomem, ipsp->iss_inuse); + PRINTF("\t%lu active\n\t%lu expired\n\t%lu closed\n", + ipsp->iss_active, ipsp->iss_expire, ipsp->iss_fin); + return; + } + if (kmemcpy((char *)istab, (u_long)ipsp->iss_table, sizeof(istab))) return; - for (i = 0; i < IPSTATE_SIZE; i++) { - while (istab[i]) { - if (kmemcpy((char *)&ips, (u_long)istab[i], - sizeof(ips)) == -1) - break; - printf("%s -> ", inet_ntoa(ips.is_src)); - printf("%s ttl %ld pass %#x 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]); + + while (ipsp->iss_list) { + if (kmemcpy((char *)&ips, (u_long)ipsp->iss_list, sizeof(ips))) + break; + ipsp->iss_list = ips.is_next; + PRINTF("%s -> ", hostname(ips.is_v, &ips.is_src.in4)); + PRINTF("%s ttl %ld pass %#x pr %d state %d/%d\n", + hostname(ips.is_v, &ips.is_dst.in4), + 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); + PRINTF("\tpkts %qu bytes %qu", + (unsigned long long) ips.is_pkts, + (unsigned long long) ips.is_bytes); #else - printf("\tpkts %ld bytes %ld", - ips.is_pkts, ips.is_bytes); + PRINTF("\tpkts %ld bytes %ld", ips.is_pkts, ips.is_bytes); #endif - if (ips.is_p == IPPROTO_TCP) + if (ips.is_p == IPPROTO_TCP) #if defined(NetBSD) && (NetBSD >= 199905) && (NetBSD < 1991011) || \ (__FreeBSD_version >= 220000) || defined(__OpenBSD__) - printf("\t%hu -> %hu %x:%x %hu:%hu", - ntohs(ips.is_sport), - ntohs(ips.is_dport), - ips.is_send, ips.is_dend, - ips.is_maxswin, ips.is_maxdwin); + PRINTF("\t%hu -> %hu %x:%x %hu:%hu", + ntohs(ips.is_sport), ntohs(ips.is_dport), + ips.is_send, ips.is_dend, + ips.is_maxswin, ips.is_maxdwin); #else - printf("\t%hu -> %hu %lx:%lx %hu:%hu", - ntohs(ips.is_sport), - ntohs(ips.is_dport), - ips.is_send, ips.is_dend, - ips.is_maxswin, ips.is_maxdwin); + PRINTF("\t%hu -> %hu %x:%x %hu:%hu", + ntohs(ips.is_sport), ntohs(ips.is_dport), + ips.is_send, ips.is_dend, + ips.is_maxswin, ips.is_maxdwin); #endif - else if (ips.is_p == IPPROTO_UDP) - printf(" %hu -> %hu", ntohs(ips.is_sport), - ntohs(ips.is_dport)); - else if (ips.is_p == IPPROTO_ICMP) - printf(" %hu %hu %d", ips.is_icmp.ics_id, - ips.is_icmp.ics_seq, - ips.is_icmp.ics_type); - - printf("\n\t"); - - if (ips.is_pass & FR_PASS) { - printf("pass"); - } else if (ips.is_pass & FR_BLOCK) { - printf("block"); - switch (ips.is_pass & FR_RETMASK) - { - case FR_RETICMP : - printf(" return-icmp"); - break; - case FR_FAKEICMP : - printf(" return-icmp-as-dest"); - break; - case FR_RETRST : - printf(" return-rst"); - break; - default : - break; - } - } else if ((ips.is_pass & FR_LOGMASK) == FR_LOG) { - printf("log"); - if (ips.is_pass & FR_LOGBODY) - printf(" body"); - if (ips.is_pass & FR_LOGFIRST) - printf(" first"); - } else if (ips.is_pass & FR_ACCOUNT) - printf("count"); - - if (ips.is_pass & FR_OUTQUE) - printf(" out"); - else - printf(" in"); - - if ((ips.is_pass & FR_LOG) != 0) { - printf(" log"); - if (ips.is_pass & FR_LOGBODY) - printf(" body"); - if (ips.is_pass & FR_LOGFIRST) - printf(" first"); - if (ips.is_pass & FR_LOGORBLOCK) - printf(" or-block"); + else if (ips.is_p == IPPROTO_UDP) + PRINTF(" %hu -> %hu", ntohs(ips.is_sport), + ntohs(ips.is_dport)); + else if (ips.is_p == IPPROTO_ICMP +#ifdef USE_INET6 + || ips.is_p == IPPROTO_ICMPV6 +#endif + ) + PRINTF(" %hu %hu %d", ips.is_icmp.ics_id, + ips.is_icmp.ics_seq, ips.is_icmp.ics_type); + + PRINTF("\n\t"); + + if (ips.is_pass & FR_PASS) { + PRINTF("pass"); + } else if (ips.is_pass & FR_BLOCK) { + PRINTF("block"); + switch (ips.is_pass & FR_RETMASK) + { + case FR_RETICMP : + PRINTF(" return-icmp"); + break; + case FR_FAKEICMP : + PRINTF(" return-icmp-as-dest"); + break; + case FR_RETRST : + PRINTF(" return-rst"); + break; + default : + break; } - 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"); - - printf("\tpkt_flags & %x(%x) = %x,\t", - ips.is_flags & 0xf, ips.is_flags, - ips.is_flags >> 4); - printf("\tpkt_options & %x = %x\n", ips.is_optmsk, - ips.is_opt); - printf("\tpkt_security & %x = %x, pkt_auth & %x = %x\n", - ips.is_secmsk, ips.is_sec, ips.is_authmsk, - ips.is_auth); - istab[i] = ips.is_next; - printf("interfaces: in %s[%p] ", - get_ifname(ips.is_ifpin), ips.is_ifpin); - printf("out %s[%p]\n", - get_ifname(ips.is_ifpout), ips.is_ifpout); + } 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_LOG) != 0) { + PRINTF(" log"); + if (ips.is_pass & FR_LOGBODY) + PRINTF(" body"); + if (ips.is_pass & FR_LOGFIRST) + PRINTF(" first"); + if (ips.is_pass & FR_LOGORBLOCK) + PRINTF(" or-block"); } + if (ips.is_pass & FR_QUICK) + PRINTF(" quick"); + if (ips.is_pass & FR_KEEPFRAG) + PRINTF(" keep frags"); + /* a given; no? */ + if (ips.is_pass & FR_KEEPSTATE) + PRINTF(" keep state"); + PRINTF("\tIPv%d", ips.is_v); + PRINTF("\n"); + + PRINTF("\tpkt_flags & %x(%x) = %x,\t", + ips.is_flags & 0xf, ips.is_flags, + ips.is_flags >> 4); + PRINTF("\tpkt_options & %x = %x\n", ips.is_optmsk, + ips.is_opt); + PRINTF("\tpkt_security & %x = %x, pkt_auth & %x = %x\n", + ips.is_secmsk, ips.is_sec, ips.is_authmsk, + ips.is_auth); + PRINTF("interfaces: in %s[%p] ", + get_ifname(ips.is_ifpin), ips.is_ifpin); + PRINTF("out %s[%p]\n", + get_ifname(ips.is_ifpout), ips.is_ifpout); } } +#ifdef STATETOP +static void topipstates(fd, saddr, daddr, sport, dport, protocol, + refreshtime, topclosed) +int fd; +struct in_addr saddr; +struct in_addr daddr; +int sport; +int dport; +int protocol; +int refreshtime; +int topclosed; +{ + char str1[STSTRSIZE], str2[STSTRSIZE], str3[STSTRSIZE], str4[STSTRSIZE]; + int maxtsentries = 0, reverse = 0, sorting = STSORT_DEFAULT; + int i, j, sfd, winx, tsentry, maxx, maxy, redraw = 0; + ipstate_t *istab[IPSTATE_SIZE], ips; + ips_stat_t ipsst, *ipsstp = &ipsst; + statetop_t *tstable = NULL, *tp; + struct timeval selecttimeout; + struct protoent *proto; + fd_set readfd; + char c = '\0'; + time_t t; + + /* open state device */ + if ((sfd = open(IPL_STATE, O_RDONLY)) == -1) { + perror("open"); + exit(-1); + } + + /* init ncurses stuff */ + initscr(); + cbreak(); + noecho(); + nodelay(stdscr, 1); + + /* repeat until user aborts */ + while ( 1 ) { + + /* get state table */ + bzero((char *)&ipsst, sizeof(&ipsst)); + if ((ioctl(sfd, SIOCGETFS, &ipsstp) == -1)) { + perror("ioctl(SIOCGETFS)"); + exit(-1); + } + if (kmemcpy((char *)istab, (u_long)ipsstp->iss_table, + sizeof(ips))) + return; + + /* clear the history */ + tsentry = -1; + + /* read the state table and store in tstable */ + while (ipsstp->iss_list) { + if (kmemcpy((char *)&ips, (u_long)ipsstp->iss_list, + sizeof(ips))) + break; + ipsstp->iss_list = ips.is_next; + + if (((saddr.s_addr == INADDR_ANY) || + (saddr.s_addr == ips.is_saddr)) && + ((daddr.s_addr == INADDR_ANY) || + (daddr.s_addr == ips.is_daddr)) && + ((protocol < 0) || (protocol == ips.is_p)) && + (((ips.is_p != IPPROTO_TCP) && + (ips.is_p != IPPROTO_UDP)) || + (((sport < 0) || + (htons(sport) == ips.is_sport)) && + ((dport < 0) || + (htons(dport) == ips.is_dport)))) && + (topclosed || (ips.is_p != IPPROTO_TCP) || + (ips.is_state[0] < TCPS_CLOSE_WAIT) || + (ips.is_state[1] < TCPS_CLOSE_WAIT))) { + /* + * if necessary make room for this state + * entry + */ + tsentry++; + if (!maxtsentries || + (tsentry == maxtsentries)) { + + maxtsentries += STGROWSIZE; + tstable = realloc(tstable, maxtsentries * sizeof(statetop_t)); + if (!tstable) { + perror("malloc"); + exit(-1); + } + } + + /* fill structure */ + tp = tstable + tsentry; + tp->st_src = ips.is_src; + tp->st_dst = ips.is_dst; + tp->st_p = ips.is_p; + tp->st_state[0] = ips.is_state[0]; + tp->st_state[1] = ips.is_state[1]; + tp->st_pkts = ips.is_pkts; + tp->st_bytes = ips.is_bytes; + tp->st_age = ips.is_age; + if ((ips.is_p == IPPROTO_TCP) || + (ips.is_p == IPPROTO_UDP)) { + tp->st_sport = ips.is_sport; + tp->st_dport = ips.is_dport; + } + + } + } + + + /* sort the array */ + if (tsentry != -1) + switch (sorting) + { + case STSORT_PR: + qsort(tstable, tsentry + 1, + sizeof(statetop_t), sort_p); + break; + case STSORT_PKTS: + qsort(tstable, tsentry + 1, + sizeof(statetop_t), sort_pkts); + break; + case STSORT_BYTES: + qsort(tstable, tsentry + 1, + sizeof(statetop_t), sort_bytes); + break; + case STSORT_TTL: + qsort(tstable, tsentry + 1, + sizeof(statetop_t), sort_ttl); + break; + default: + break; + } + + /* print title */ + erase(); + getmaxyx(stdscr, maxy, maxx); + attron(A_BOLD); + winx = 0; + move(winx,0); + sprintf(str1, "%s - state top", IPL_VERSION); + for(j = 0 ; j < (maxx - 8 - strlen(str1)) / 2; j++) + printw(" "); + printw("%s", str1); + attroff(A_BOLD); + + /* just for fun add a clock */ + move(winx, maxx - 8); + t = time(NULL); + strftime(str1, 80, "%T", localtime(&t)); + printw("%s\n", str1); + + /* + * print the display filters, this is placed in the loop, + * because someday I might add code for changing these + * while the programming is running :-) + */ + if (sport >= 0) + sprintf(str1, "%s,%d", inet_ntoa(saddr), sport); + else + sprintf(str1, "%s", inet_ntoa(saddr)); + + if (dport >= 0) + sprintf(str2, "%s,%d", inet_ntoa(daddr), dport); + else + sprintf(str2, "%s", inet_ntoa(daddr)); + + if (protocol < 0) + strcpy(str3, "any"); + else if ((proto = getprotobynumber(protocol)) != NULL) + sprintf(str3, "%s", proto->p_name); + else + sprintf(str3, "%d", protocol); + + switch (sorting) + { + case STSORT_PR: + sprintf(str4, "proto"); + break; + case STSORT_PKTS: + sprintf(str4, "# pkts"); + break; + case STSORT_BYTES: + sprintf(str4, "# bytes"); + break; + case STSORT_TTL: + sprintf(str4, "ttl"); + break; + default: + sprintf(str4, "unknown"); + break; + } + + if (reverse) + strcat(str4, " (reverse)"); + + winx += 2; + move(winx,0); + printw("Src = %s Dest = %s Proto = %s Sorted by = %s\n\n", + str1, str2, str3, str4); + + /* print column description */ + winx += 2; + move(winx,0); + attron(A_BOLD); + printw("%-21s %-21s %3s %4s %7s %9s %9s\n", "Source IP", + "Destination IP", "ST", "PR", "#pkts", "#bytes", "ttl"); + attroff(A_BOLD); + + /* print all the entries */ + tp = tstable; + if (reverse) + tp += tsentry; + + for(i = 0; i <= tsentry; i++) { + /* print src/dest and port */ + if ((tp->st_p == IPPROTO_TCP) || + (tp->st_p == IPPROTO_UDP)) { + sprintf(str1, "%s,%hu", + inet_ntoa(tp->st_src.in4), + ntohs(tp->st_sport)); + sprintf(str2, "%s,%hu", + inet_ntoa(tp->st_dst.in4), + ntohs(tp->st_dport)); + } else { + sprintf(str1, "%s", inet_ntoa(tp->st_src.in4)); + sprintf(str2, "%s", inet_ntoa(tp->st_dst.in4)); + } + winx++; + move(winx, 0); + printw("%-21s %-21s", str1, str2); + + /* print state */ + sprintf(str1, "%X/%X", tp->st_state[0], + tp->st_state[1]); + printw(" %3s", str1); + + /* print proto */ + proto = getprotobynumber(tp->st_p); + if (proto) { + strncpy(str1, proto->p_name, 4); + str1[4] = '\0'; + } else { + sprintf(str1, "%d", tp->st_p); + } + printw(" %4s", str1); + /* print #pkt/#bytes */ +#ifdef USE_QUAD_T + printw(" %7qu %9qu", (unsigned long long) tp->st_pkts, + (unsigned long long) tp->st_bytes); +#else + printw(" %7lu %9lu", tp->st_pkts, tp->st_bytes); +#endif + printw(" %9s", ttl_to_string(tp->st_age)); + + if (reverse) + tp--; + else + tp++; + } + + /* screen data structure is filled, now update the screen */ + if (redraw) + clearok(stdscr,1); + + refresh(); + if (redraw) { + clearok(stdscr,0); + redraw = 0; + } + + /* wait for key press or a 1 second time out period */ + selecttimeout.tv_sec = refreshtime; + selecttimeout.tv_usec = 0; + FD_ZERO(&readfd); + FD_SET(0, &readfd); + select(1, &readfd, NULL, NULL, &selecttimeout); + + /* if key pressed, read all waiting keys */ + if (FD_ISSET(0, &readfd)) + while ((c = wgetch(stdscr)) != ERR) { + if (tolower(c) == 'l') { + redraw = 1; + } else if (tolower(c) == 'q') { + nocbreak(); + endwin(); + exit(0); + } else if (tolower(c) == 'r') { + reverse = !reverse; + } else if (tolower(c) == 's') { + sorting++; + if (sorting > STSORT_MAX) + sorting = 0; + } + } + } /* while */ + + close(sfd); + + printw("\n"); + nocbreak(); + endwin(); +} +#endif static void showfrstates(fd, ifsp) int fd; @@ -514,11 +974,11 @@ ipfrstat_t *ifsp; frentry_t fr; int i; - printf("IP fragment states:\n\t%lu new\n\t%lu expired\n\t%lu hits\n", + PRINTF("IP fragment states:\n\t%lu new\n\t%lu expired\n\t%lu hits\n", ifsp->ifs_new, ifsp->ifs_expire, ifsp->ifs_hits); - printf("\t%lu no memory\n\t%lu already exist\n", + PRINTF("\t%lu no memory\n\t%lu already exist\n", ifsp->ifs_nomem, ifsp->ifs_exists); - printf("\t%lu inuse\n", ifsp->ifs_inuse); + PRINTF("\t%lu inuse\n", ifsp->ifs_inuse); if (kmemcpy((char *)ipfrtab, (u_long)ifsp->ifs_table, sizeof(ipfrtab))) return; for (i = 0; i < IPFT_SIZE; i++) @@ -526,12 +986,29 @@ ipfrstat_t *ifsp; if (kmemcpy((char *)&ifr, (u_long)ipfrtab[i], sizeof(ifr)) == -1) break; - printf("%s -> ", inet_ntoa(ifr.ipfr_src)); + PRINTF("%s -> ", hostname(4, &ifr.ipfr_src)); + if (kmemcpy((char *)&fr, (u_long)ifr.ipfr_rule, + sizeof(fr)) == -1) + break; + PRINTF("%s %d %d %d %#02x = %#x\n", + hostname(4, &ifr.ipfr_dst), ifr.ipfr_id, + ifr.ipfr_ttl, ifr.ipfr_p, ifr.ipfr_tos, + fr.fr_flags); + ipfrtab[i] = ifr.ipfr_next; + } + if (kmemcpy((char *)ipfrtab, (u_long)ifsp->ifs_nattab,sizeof(ipfrtab))) + return; + for (i = 0; i < IPFT_SIZE; i++) + while (ipfrtab[i]) { + if (kmemcpy((char *)&ifr, (u_long)ipfrtab[i], + sizeof(ifr)) == -1) + break; + PRINTF("NAT: %s -> ", hostname(4, &ifr.ipfr_src)); if (kmemcpy((char *)&fr, (u_long)ifr.ipfr_rule, sizeof(fr)) == -1) break; - printf("%s %d %d %d %#02x = %#x\n", - inet_ntoa(ifr.ipfr_dst), ifr.ipfr_id, + PRINTF("%s %d %d %d %#02x = %#x\n", + hostname(4, &ifr.ipfr_dst), ifr.ipfr_id, ifr.ipfr_ttl, ifr.ipfr_p, ifr.ipfr_tos, fr.fr_flags); ipfrtab[i] = ifr.ipfr_next; @@ -546,8 +1023,9 @@ fr_authstat_t *asp; frauthent_t *frap, fra; #ifdef USE_QUAD_T - printf("Authorisation hits: %qd\tmisses %qd\n", asp->fas_hits, - asp->fas_miss); + printf("Authorisation hits: %qu\tmisses %qu\n", + (unsigned long long) asp->fas_hits, + (unsigned long long) asp->fas_miss); #else printf("Authorisation hits: %ld\tmisses %ld\n", asp->fas_hits, asp->fas_miss); @@ -652,3 +1130,131 @@ struct friostat *fiop; printf("%hu\n", grp.fg_num); } } + +static void parse_ipportstr(argument, ip, port) +const char *argument; +struct in_addr *ip; +int *port; +{ + + char *s, *comma; + + /* make working copy of argument, Theoretically you must be able + * to write to optarg, but that seems very ugly to me.... + */ + if ((s = malloc(strlen(argument) + 1)) == NULL) + perror("malloc"); + strcpy(s, argument); + + /* get port */ + if ((comma = strchr(s, ',')) != NULL) { + if (!strcasecmp(s, "any")) { + *port = -1; + } else if (!sscanf(comma + 1, "%d", port) || + (*port < 0) || (*port > 65535)) { + fprintf(stderr, "Invalid port specfication in %s\n", + argument); + exit(-2); + } + *comma = '\0'; + } + + + /* get ip address */ + if (!strcasecmp(s, "any")) { + ip->s_addr = INADDR_ANY; + } else if (!inet_aton(s, ip)) { + fprintf(stderr, "Invalid IP address: %s\n", s); + exit(-2); + } + + /* free allocated memory */ + free(s); +} + + +#ifdef STATETOP +static char ttlbuf[STSTRSIZE]; + +static char *ttl_to_string(ttl) +long int ttl; +{ + + int hours, minutes, seconds; + + /* ttl is in half seconds */ + ttl /= 2; + + hours = ttl / 3600; + ttl = ttl % 3600; + minutes = ttl / 60; + seconds = ttl % 60; + + if (hours > 0 ) + sprintf(ttlbuf, "%2d:%02d:%02d", hours, minutes, seconds); + else + sprintf(ttlbuf, "%2d:%02d", minutes, seconds); + return ttlbuf; +} + + +static int sort_pkts(a, b) +const void *a; +const void *b; +{ + + register const statetop_t *ap = a; + register const statetop_t *bp = b; + + if (ap->st_pkts == bp->st_pkts) + return 0; + else if (ap->st_pkts < bp->st_pkts) + return 1; + return -1; +} + + +static int sort_bytes(a, b) +const void *a; +const void *b; +{ + register const statetop_t *ap = a; + register const statetop_t *bp = b; + + if (ap->st_bytes == bp->st_bytes) + return 0; + else if (ap->st_bytes < bp->st_bytes) + return 1; + return -1; +} + + +static int sort_p(a, b) +const void *a; +const void *b; +{ + register const statetop_t *ap = a; + register const statetop_t *bp = b; + + if (ap->st_p == bp->st_p) + return 0; + else if (ap->st_p < bp->st_p) + return 1; + return -1; +} + + +static int sort_ttl(a, b) +const void *a; +const void *b; +{ + register const statetop_t *ap = a; + register const statetop_t *bp = b; + + if (ap->st_age == bp->st_age) + return 0; + else if (ap->st_age < bp->st_age) + return 1; + return -1; +} +#endif diff --git a/sbin/ipfstat/kmem.c b/sbin/ipfstat/kmem.c index 0e04df3b9cc..7674d78999d 100644 --- a/sbin/ipfstat/kmem.c +++ b/sbin/ipfstat/kmem.c @@ -1,7 +1,7 @@ -/* $OpenBSD: kmem.c,v 1.15 2000/03/13 23:40:19 kjell Exp $ */ +/* $OpenBSD: kmem.c,v 1.16 2001/01/17 05:01:00 fgsch Exp $ */ /* - * Copyright (C) 1993-1998 by Darren Reed. + * Copyright (C) 1993-2000 by Darren Reed. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and due credit is given @@ -22,18 +22,14 @@ #if !defined(lint) static const char sccsid[] = "@(#)kmem.c 1.4 1/12/96 (C) 1992 Darren Reed"; -static const char rcsid[] = "@(#)$IPFilter: kmem.c,v 2.1 1999/08/04 17:30:09 darrenr Exp $"; +static const char rcsid[] = "@(#)$IPFilter: kmem.c,v 2.2 2000/03/13 22:10:25 darrenr Exp $"; #endif static int kmemfd = -1; -int openkmem(nlistf, memf) -char *nlistf, *memf; +int openkmem() { - if (memf == NULL) - memf = KMEM; - - if ((kmemfd = open(memf,O_RDONLY)) == -1) + if ((kmemfd = open(KMEM,O_RDONLY)) == -1) { perror("kmeminit:open"); return -1; @@ -51,7 +47,7 @@ register int n; if (!n) return 0; if (kmemfd == -1) - if (openkmem(nlistf, memf) == -1) + if (openkmem() == -1) return -1; if (lseek(kmemfd, pos, 0) == -1) { @@ -82,7 +78,7 @@ register int n; if (!n) return 0; if (kmemfd == -1) - if (openkmem(nlistf, memf) == -1) + if (openkmem() == -1) return -1; if (lseek(kmemfd, pos, 0) == -1) { diff --git a/sbin/ipfstat/kmem.h b/sbin/ipfstat/kmem.h index bc01009e090..61b4ad24de4 100644 --- a/sbin/ipfstat/kmem.h +++ b/sbin/ipfstat/kmem.h @@ -1,12 +1,12 @@ -/* $OpenBSD: kmem.h,v 1.12 2000/03/13 23:40:19 kjell Exp $ */ +/* $OpenBSD: kmem.h,v 1.13 2001/01/17 05:01:01 fgsch Exp $ */ /* - * Copyright (C) 1993-1998 by Darren Reed. + * Copyright (C) 1993-2000 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. - * $IPFilter: kmem.h,v 2.1 1999/08/04 17:30:10 darrenr Exp $ + * $IPFilter: kmem.h,v 2.2 2000/03/13 22:10:25 darrenr Exp $ */ #ifndef __KMEM_H__ @@ -19,7 +19,7 @@ # define __P(x) () # endif #endif -extern int openkmem __P((char *, char *)); +extern int openkmem __P((void)); extern int kmemcpy __P((char *, long, int)); extern int kstrncpy __P((char *, long, int)); @@ -27,9 +27,6 @@ extern int kstrncpy __P((char *, long, int)); # include <paths.h> #endif -extern char *nlistf; -extern char *memf; - #ifdef _PATH_KMEM # define KMEM _PATH_KMEM #else diff --git a/sbin/ipnat/Makefile b/sbin/ipnat/Makefile index 10d4bf17f1b..3ed89451018 100644 --- a/sbin/ipnat/Makefile +++ b/sbin/ipnat/Makefile @@ -1,8 +1,8 @@ -# $OpenBSD: Makefile,v 1.9 2000/04/26 21:04:00 deraadt Exp $ +# $OpenBSD: Makefile,v 1.10 2001/01/17 05:01:01 fgsch Exp $ PROG= ipnat MAN= ipnat.8 ipnat.4 ipnat.5 -SRCS= ipnat.c kmem.c natparse.c ifaddr.c +SRCS= ipnat.c kmem.c natparse.c common.c ifaddr.c .PATH: ${.CURDIR}/../ipfstat ${.CURDIR}/../ipf CFLAGS+=-I${.CURDIR}/../../sbin/ipfstat -I${.CURDIR}/../ipf diff --git a/sbin/ipnat/ipnat.c b/sbin/ipnat/ipnat.c index 3cfc24a5892..9a3b9db453b 100644 --- a/sbin/ipnat/ipnat.c +++ b/sbin/ipnat/ipnat.c @@ -1,7 +1,7 @@ -/* $OpenBSD: ipnat.c,v 1.38 2000/08/10 05:50:27 kjell Exp $ */ +/* $OpenBSD: ipnat.c,v 1.39 2001/01/17 05:01:01 fgsch Exp $ */ /* - * Copyright (C) 1993-1998 by Darren Reed. + * Copyright (C) 1993-2000 by Darren Reed. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and due credit is given @@ -43,10 +43,11 @@ #include <arpa/inet.h> #include <resolv.h> #include <ctype.h> -#include <netinet/ip_fil_compat.h> +#include <netinet/ip_compat.h> #include <netinet/ip_fil.h> #include <netinet/ip_proxy.h> #include <netinet/ip_nat.h> +#include "ipf.h" #include "kmem.h" #if defined(sun) && !SOLARIS2 @@ -58,26 +59,25 @@ extern char *sys_errlist[]; #if !defined(lint) static const char sccsid[] ="@(#)ipnat.c 1.9 6/5/96 (C) 1993 Darren Reed"; -static const char rcsid[] = "@(#)$IPFilter: ipnat.c,v 2.1.2.3 2000/07/27 13:07:07 darrenr Exp $"; +static const char rcsid[] = "@(#)$IPFilter: ipnat.c,v 2.16.2.5 2000/12/02 00:15:04 darrenr Exp $"; #endif #if SOLARIS #define bzero(a,b) memset(a,0,b) #endif +#ifdef USE_INET6 +int use_inet6 = 0; +#endif + +static char thishost[MAXHOSTNAMELEN]; + extern char *optarg; -char *nlistf = NULL, *memf = NULL; extern ipnat_t *natparse __P((char *, int)); extern void natparsefile __P((int, char *, int)); extern void printnat __P((ipnat_t *, int, void *)); -#if defined(__OpenBSD__) -extern int if_addr __P((char *, struct in_addr *)); -#endif - -u_32_t hostnum __P((char *, int *, int)); -u_32_t hostmask __P((char *)); void dostats __P((int, int)), flushtable __P((int, int)); void usage __P((char *)); int countbits __P((u_32_t)); @@ -86,15 +86,6 @@ int main __P((int, char*[])); void printaps __P((ap_session_t *, int)); char *getsumd __P((u_32_t)); -#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 -#define OPT_HITS 128 - void usage(name) char *name; @@ -124,12 +115,15 @@ char *argv[]; char *file = NULL; int fd = -1, opts = 0, c, mode = O_RDWR; - while ((c = getopt(argc, argv, "CFf:hlnrsv")) != -1) + while ((c = getopt(argc, argv, "CdFf:hlnrsv")) != -1) switch (c) { case 'C' : opts |= OPT_CLEAR; break; + case 'd' : + opts |= OPT_DEBUG; + break; case 'f' : file = optarg; break; @@ -148,7 +142,7 @@ char *argv[]; mode = O_RDONLY; break; case 'r' : - opts |= OPT_REM; + opts |= OPT_REMOVE; break; case 's' : opts |= OPT_STAT; @@ -161,6 +155,9 @@ char *argv[]; usage(argv[0]); } + gethostname(thishost, sizeof(thishost)); + thishost[sizeof(thishost) - 1] = '\0'; + if (!(opts & OPT_NODO) && ((fd = open(IPL_NAT, mode)) == -1) && ((fd = open(IPL_NAT, O_RDONLY)) == -1)) { (void) fprintf(stderr, "%s: open: %s\n", IPL_NAT, @@ -178,40 +175,12 @@ char *argv[]; } -/* - * count consecutive 1's in bit mask. If the mask generated by counting - * consecutive 1's is different to that passed, return -1, else return # - * of bits. - */ -int countbits(ip) -u_32_t ip; -{ - u_32_t ipn; - int cnt = 0, i, j; - - ip = ipn = ntohl(ip); - for (i = 32; i; i--, ipn *= 2) - if (ipn & 0x80000000) - cnt++; - else - break; - ipn = 0; - for (i = 32, j = cnt; i; i--, j--) { - ipn *= 2; - if (j > 0) - ipn++; - } - if (ipn == ip) - return cnt; - return -1; -} - - void printaps(aps, opts) ap_session_t *aps; int opts; { ap_session_t ap; + ftpinfo_t ftp; aproxy_t apr; raudio_t ra; @@ -223,7 +192,8 @@ int opts; apr.apr_p, apr.apr_ref, apr.apr_flags); printf("\t\tproto %d flags %#x bytes ", ap.aps_p, ap.aps_flags); #ifdef USE_QUAD_T - printf("%qu pkts %qu", ap.aps_bytes, ap.aps_pkts); + printf("%qu pkts %qu", (unsigned long long)ap.aps_bytes, + (unsigned long long)ap.aps_pkts); #else printf("%lu pkts %lu", ap.aps_bytes, ap.aps_pkts); #endif @@ -259,6 +229,29 @@ int opts; printf("\t\tMode: %#x\tSBF: %#x\n", ra.rap_mode, ra.rap_sbf); printf("\t\tPorts:pl %hu, pr %hu, sr %hu\n", ra.rap_plport, ra.rap_prport, ra.rap_srport); + } else if (!strcmp(apr.apr_label, "ftp") && + (ap.aps_psiz == sizeof(ftp))) { + if (kmemcpy((char *)&ftp, (long)ap.aps_data, sizeof(ftp))) + return; + printf("\tFTP Proxy:\n"); + printf("\t\tpassok: %d\n", ftp.ftp_passok); + ftp.ftp_side[0].ftps_buf[FTP_BUFSZ - 1] = '\0'; + ftp.ftp_side[1].ftps_buf[FTP_BUFSZ - 1] = '\0'; + printf("\tClient:\n"); + printf("\t\trptr %p wptr %p seq %x len %d junk %d\n", + ftp.ftp_side[0].ftps_rptr, ftp.ftp_side[0].ftps_wptr, + ftp.ftp_side[0].ftps_seq, ftp.ftp_side[0].ftps_len, + ftp.ftp_side[0].ftps_junk); + printf("\t\tbuf ["); + printbuf(ftp.ftp_side[0].ftps_buf, FTP_BUFSZ, 1); + printf("]\n\tServer:\n"); + printf("\t\trptr %p wptr %p seq %x len %d junk %d\n", + ftp.ftp_side[1].ftps_rptr, ftp.ftp_side[1].ftps_wptr, + ftp.ftp_side[1].ftps_seq, ftp.ftp_side[1].ftps_len, + ftp.ftp_side[1].ftps_junk); + printf("\t\tbuf ["); + printbuf(ftp.ftp_side[1].ftps_buf, FTP_BUFSZ, 1); + printf("]\n"); } } @@ -301,14 +294,13 @@ ipnat_t *ipnat; void dostats(fd, opts) int fd, opts; { - natstat_t ns; + natstat_t ns, *nsp = &ns; + nat_t **nt[2], *np, nat; ipnat_t ipn; - nat_t **nt[2], *np, nat; - int i = 0; bzero((char *)&ns, sizeof(ns)); - if (!(opts & OPT_NODO) && ioctl(fd, SIOCGNATS, &ns) == -1) { + if (!(opts & OPT_NODO) && ioctl(fd, SIOCGNATS, &nsp) == -1) { perror("ioctl(SIOCGNATS)"); return; } @@ -318,7 +310,10 @@ 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("no memory\t%lu\tbad nat\t%lu\n", + ns.ns_memfail, ns.ns_badnat); printf("inuse\t%lu\nrules\t%lu\n", ns.ns_inuse, ns.ns_rules); + printf("wilds\t%u\n", ns.ns_wilds); if (opts & OPT_VERBOSE) printf("table %p list %p\n", ns.ns_table, ns.ns_list); } @@ -332,7 +327,8 @@ int fd, opts; } if (opts & OPT_HITS) printf("%d ", ipn.in_hits); - printnat(&ipn, opts & OPT_VERBOSE, (void *)ns.ns_list); + printnat(&ipn, opts & (OPT_DEBUG|OPT_VERBOSE), + (void *)ns.ns_list); ns.ns_list = ipn.in_next; } @@ -359,12 +355,19 @@ int fd, opts; printf("\n\tage %lu use %hu sumd %s/", nat.nat_age, nat.nat_use, getsumd(nat.nat_sumd[0])); - printf("%s pr %u bkt %d flags %x ", + printf("%s pr %u bkt %d/%d flags %x ", getsumd(nat.nat_sumd[1]), nat.nat_p, - i, nat.nat_flags); + (int)NAT_HASH_FN(nat.nat_inip.s_addr, + nat.nat_inport, + NAT_TABLE_SZ), + (int)NAT_HASH_FN(nat.nat_outip.s_addr, + nat.nat_outport, + NAT_TABLE_SZ), + nat.nat_flags); #ifdef USE_QUAD_T printf("bytes %qu pkts %qu", - nat.nat_bytes, nat.nat_pkts); + (unsigned long long)nat.nat_bytes, + (unsigned long long)nat.nat_pkts); #else printf("bytes %lu pkts %lu", nat.nat_bytes, nat.nat_pkts); @@ -383,68 +386,6 @@ int fd, opts; } -u_32_t hostmask(msk) -char *msk; -{ - int bits = -1; - u_32_t mask; - - if (!isdigit(*msk)) - return (u_32_t)-1; - if (strchr(msk, '.')) - return inet_addr(msk); - if (strchr(msk, 'x')) - return (u_32_t)strtol(msk, NULL, 0); - /* - * set x most significant bits - */ - for (mask = 0, bits = atoi(msk); bits; bits--) { - mask /= 2; - mask |= ntohl(inet_addr("128.0.0.0")); - } - mask = htonl(mask); - return mask; -} - - -/* - * returns an ip address as a long var as a result of either a DNS lookup or - * straight inet_addr() call - */ -u_32_t hostnum(host, resolved, linenum) -char *host; -int *resolved; -int linenum; -{ - struct hostent *hp; - struct netent *np; -#if defined(__OpenBSD__) - struct in_addr addr; -#endif - - *resolved = 0; - if (!strcasecmp("any", host)) - return 0L; - if (isdigit(*host)) - return inet_addr(host); - -#if defined(__OpenBSD__) - /* attempt a map from interface name to address */ - if (if_addr(host, &addr)) - return (u_32_t)addr.s_addr; -#endif - if (!(hp = gethostbyname(host))) { - if (!(np = getnetbyname(host))) { - *resolved = -1; - fprintf(stderr, "Line %d: can't resolve hostname: %s\n", linenum, host); - return 0; - } - return htonl(np->n_net); - } - return *(u_32_t *)hp->h_addr; -} - - void flushtable(fd, opts) int fd, opts; { @@ -452,15 +393,15 @@ int fd, opts; if (opts & OPT_FLUSH) { n = 0; - if (!(opts & OPT_NODO) && ioctl(fd, SIOCFLNAT, &n) == -1) + if (!(opts & OPT_NODO) && ioctl(fd, SIOCIPFFL, &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) + n = 1; + if (!(opts & OPT_NODO) && ioctl(fd, SIOCIPFFL, &n) == -1) perror("ioctl(SIOCCNATL)"); else printf("%d entries flushed from NAT list\n", n); diff --git a/sbin/ipnat/natparse.c b/sbin/ipnat/natparse.c index 62c40794f15..5836f260d03 100644 --- a/sbin/ipnat/natparse.c +++ b/sbin/ipnat/natparse.c @@ -1,7 +1,7 @@ -/* $OpenBSD: natparse.c,v 1.6 2000/08/10 05:50:27 kjell Exp $ */ +/* $OpenBSD: natparse.c,v 1.7 2001/01/17 05:01:01 fgsch Exp $ */ /* - * Copyright (C) 1993-1998 by Darren Reed. + * Copyright (C) 1993-2000 by Darren Reed. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and due credit is given @@ -41,10 +41,11 @@ #include <arpa/inet.h> #include <resolv.h> #include <ctype.h> -#include <netinet/ip_fil_compat.h> +#include <netinet/ip_compat.h> #include <netinet/ip_fil.h> #include <netinet/ip_proxy.h> #include <netinet/ip_nat.h> +#include "ipf.h" #if defined(sun) && !SOLARIS2 # define STRERROR(x) sys_errlist[x] @@ -55,7 +56,7 @@ extern char *sys_errlist[]; #if !defined(lint) static const char sccsid[] ="@(#)ipnat.c 1.9 6/5/96 (C) 1993 Darren Reed"; -static const char rcsid[] = "@(#)$IPFilter: natparse.c,v 1.2.2.3 2000/06/25 07:13:28 darrenr Exp $"; +static const char rcsid[] = "@(#)$IPFilter: natparse.c,v 1.17.2.6 2000/07/08 02:14:40 darrenr Exp $"; #endif @@ -64,27 +65,17 @@ static const char rcsid[] = "@(#)$IPFilter: natparse.c,v 1.2.2.3 2000/06/25 07:1 #endif extern int countbits __P((u_32_t)); -extern u_32_t hostnum __P((char *, int *, int)); +extern char *proto; ipnat_t *natparse __P((char *, int)); void printnat __P((ipnat_t *, int, void *)); void natparsefile __P((int, char *, int)); -u_32_t n_hostmask __P((char *)); -u_short n_portnum __P((char *, char *, int)); void nat_setgroupmap __P((struct ipnat *)); -#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 printnat(np, verbose, ptr) +void printnat(np, opts, ptr) ipnat_t *np; -int verbose; +int opts; void *ptr; { struct protoent *pr; @@ -94,16 +85,16 @@ void *ptr; switch (np->in_redir) { case NAT_REDIRECT : - printf("rdr "); + printf("rdr"); break; case NAT_MAP : - printf("map "); + printf("map"); break; case NAT_MAPBLK : - printf("map-block "); + printf("map-block"); break; case NAT_BIMAP : - printf("bimap "); + printf("bimap"); break; default : fprintf(stderr, "unknown value for in_redir: %#x\n", @@ -111,25 +102,56 @@ void *ptr; break; } + printf(" %s ", np->in_ifname); + + if (np->in_flags & IPN_FILTER) { + if (np->in_flags & IPN_NOTSRC) + printf("! "); + printf("from "); + if (np->in_redir == NAT_REDIRECT) { + printhostmask(4, (u_32_t *)&np->in_srcip, + (u_32_t *)&np->in_srcmsk); + if (np->in_scmp) + printportcmp(np->in_p, &np->in_tuc.ftu_src); + } else { + printhostmask(4, (u_32_t *)&np->in_inip, + (u_32_t *)&np->in_inmsk); + if (np->in_dcmp) + printportcmp(np->in_p, &np->in_tuc.ftu_dst); + } + + if (np->in_flags & IPN_NOTDST) + printf(" !"); + printf(" to "); + if (np->in_redir == NAT_REDIRECT) { + printhostmask(4, (u_32_t *)&np->in_outip, + (u_32_t *)&np->in_outmsk); + if (np->in_dcmp) + printportcmp(np->in_p, &np->in_tuc.ftu_dst); + } else { + printhostmask(4, (u_32_t *)&np->in_srcip, + (u_32_t *)&np->in_srcmsk); + if (np->in_scmp) + printportcmp(np->in_p, &np->in_tuc.ftu_src); + } + } + if (np->in_redir == NAT_REDIRECT) { - printf("%s ", np->in_ifname); - if (np->in_src[0].s_addr || np->in_src[1].s_addr) { - printf("from %s",inet_ntoa(np->in_src[0])); - bits = countbits(np->in_src[1].s_addr); + if (!(np->in_flags & IPN_FILTER)) { + printf("%s", inet_ntoa(np->in_out[0])); + bits = countbits(np->in_out[1].s_addr); if (bits != -1) printf("/%d ", bits); else - printf("/%s ", inet_ntoa(np->in_src[1])); + printf("/%s ", inet_ntoa(np->in_out[1])); + if (np->in_pmin) + printf("port %d", ntohs(np->in_pmin)); + if (np->in_pmax != np->in_pmin) + printf("- %d", ntohs(np->in_pmax)); } - printf("%s",inet_ntoa(np->in_out[0])); - bits = countbits(np->in_out[1].s_addr); - if (bits != -1) - printf("/%d ", bits); - else - printf("/%s ", inet_ntoa(np->in_out[1])); - if (np->in_pmin) - printf("port %d ", ntohs(np->in_pmin)); - printf("-> %s", inet_ntoa(np->in_in[0])); + printf(" -> %s", inet_ntoa(np->in_in[0])); + if (np->in_flags & IPN_SPLIT) + printf(",%s", inet_ntoa(np->in_in[1])); if (np->in_pnext) printf(" port %d", ntohs(np->in_pnext)); if ((np->in_flags & IPN_TCPUDP) == IPN_TCPUDP) @@ -138,21 +160,25 @@ void *ptr; printf(" tcp"); else if ((np->in_flags & IPN_UDP) == IPN_UDP) printf(" udp"); + if (np->in_flags & IPN_ROUNDR) + printf(" round-robin"); printf("\n"); - if (verbose) - printf("\t%p %lu %x %u %p %d\n", np->in_ifp, - np->in_space, np->in_flags, np->in_pnext, np, + if (opts & OPT_DEBUG) + printf("\t%p %lu %#x %u %p %d\n", np->in_ifp, + np->in_space, np->in_flags, np->in_pmax, np, np->in_use); } else { np->in_nextip.s_addr = htonl(np->in_nextip.s_addr); - 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])); + if (!(np->in_flags & IPN_FILTER)) { + printf("%s/", 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(" -> "); - if (np->in_flags & IPN_RANGE) { + if (np->in_flags & IPN_IPRANGE) { printf("range %s-", inet_ntoa(np->in_out[0])); printf("%s", inet_ntoa(np->in_out[1])); } else { @@ -185,13 +211,13 @@ void *ptr; printf("%d", np->in_p); } else if (np->in_redir == NAT_MAPBLK) { printf(" ports %d", np->in_pmin); - if (verbose) + if (opts & OPT_VERBOSE) printf("\n\tip modulous %d", np->in_pmax); } else if (np->in_pmin || np->in_pmax) { printf(" portmap"); if (np->in_flags & IPN_AUTOPORTMAP) { printf(" auto"); - if (verbose) + if (opts & OPT_DEBUG) printf(" [%d:%d %d %d]", ntohs(np->in_pmin), ntohs(np->in_pmax), @@ -208,7 +234,7 @@ void *ptr; } } printf("\n"); - if (verbose) { + if (opts & OPT_DEBUG) { printf("\tifp %p space %lu nextip %s pnext %d", np->in_ifp, np->in_space, inet_ntoa(np->in_nextip), np->in_pnext); @@ -247,161 +273,221 @@ ipnat_t *natparse(line, linenum) char *line; int linenum; { - struct protoent *pr; static ipnat_t ipn; - char *s, *t; - char *shost, *snetm, *dhost, *proto, *srchost, *srcnetm; - char *dnetm = NULL, *dport = NULL, *tport = NULL; - int resolved; + struct protoent *pr; + char *dnetm = NULL, *dport = NULL; + char *s, *t, *cps[31], **cpp; + int i, cnt; - srchost = NULL; - srcnetm = NULL; - bzero((char *)&ipn, sizeof(ipn)); if ((s = strchr(line, '\n'))) *s = '\0'; if ((s = strchr(line, '#'))) *s = '\0'; + while (*line && isspace(*line)) + line++; if (!*line) return NULL; - if (!(s = strtok(line, " \t"))) + + bzero((char *)&ipn, sizeof(ipn)); + cnt = 0; + + for (i = 0, *cps = strtok(line, " \b\t\r\n"); cps[i] && i < 30; cnt++) + cps[++i] = strtok(NULL, " \b\t\r\n"); + + cps[i] = NULL; + + if (cnt < 3) { + fprintf(stderr, "%d: not enough segments in line\n", linenum); return NULL; - if (!strcasecmp(s, "map")) + } + + cpp = cps; + + if (!strcasecmp(*cpp, "map")) ipn.in_redir = NAT_MAP; - else if (!strcasecmp(s, "map-block")) + else if (!strcasecmp(*cpp, "map-block")) ipn.in_redir = NAT_MAPBLK; - else if (!strcasecmp(s, "rdr")) + else if (!strcasecmp(*cpp, "rdr")) ipn.in_redir = NAT_REDIRECT; - else if (!strcasecmp(s, "bimap")) + else if (!strcasecmp(*cpp, "bimap")) ipn.in_redir = NAT_BIMAP; else { fprintf(stderr, "%d: unknown mapping: \"%s\"\n", - linenum, s); + linenum, *cpp); return NULL; } - if (!(s = strtok(NULL, " \t"))) { - fprintf(stderr, "%d: missing fields (interface)\n", - linenum); - return NULL; - } + cpp++; - strncpy(ipn.in_ifname, s, sizeof(ipn.in_ifname) - 1); + strncpy(ipn.in_ifname, *cpp, sizeof(ipn.in_ifname) - 1); ipn.in_ifname[sizeof(ipn.in_ifname) - 1] = '\0'; - if (!(s = strtok(NULL, " \t"))) { - fprintf(stderr, "%d: missing fields (%s)\n", linenum, - ipn.in_redir ? "from source | destination" : "source"); - return NULL; - } + cpp++; - if ((ipn.in_redir == NAT_REDIRECT) && !strcasecmp(s, "from")) { - if (!(s = strtok(NULL, " \t"))) { - fprintf(stderr, - "%d: missing fields (source address)\n", - linenum); + if (!strcasecmp(*cpp, "from") || (**cpp == '!')) { + if (!strcmp(*cpp, "!")) { + cpp++; + if (strcasecmp(*cpp, "from")) { + fprintf(stderr, "Missing from after !\n"); + return NULL; + } + ipn.in_flags |= IPN_NOTSRC; + } else if (**cpp == '!') { + if (strcasecmp(*cpp + 1, "from")) { + fprintf(stderr, "Missing from after !\n"); + return NULL; + } + ipn.in_flags |= IPN_NOTSRC; + } + if ((ipn.in_flags & IPN_NOTSRC) && + (ipn.in_redir & (NAT_MAP|NAT_MAPBLK))) { + fprintf(stderr, "Cannot use '! from' with map\n"); return NULL; } - srchost = s; - srcnetm = strrchr(srchost, '/'); + ipn.in_flags |= IPN_FILTER; + cpp++; + if (ipn.in_redir == NAT_REDIRECT) { + if (hostmask(&cpp, (u_32_t *)&ipn.in_srcip, + (u_32_t *)&ipn.in_srcmsk, + &ipn.in_sport, &ipn.in_scmp, + &ipn.in_stop, linenum)) { + return NULL; + } + } else { + if (hostmask(&cpp, (u_32_t *)&ipn.in_inip, + (u_32_t *)&ipn.in_inmsk, + &ipn.in_sport, &ipn.in_scmp, + &ipn.in_stop, linenum)) { + return NULL; + } + } - if (srcnetm == NULL) { - if (!(s = strtok(NULL, " \t"))) { - fprintf(stderr, - "%d: missing fields (source netmask)\n", - linenum); - return NULL; - } + if (!strcmp(*cpp, "!")) { + cpp++; + ipn.in_flags |= IPN_NOTDST; + } else if (**cpp == '!') { + (*cpp)++; + ipn.in_flags |= IPN_NOTDST; + } - if (strcasecmp(s, "netmask")) { - fprintf(stderr, - "%d: missing fields (netmask)\n", - linenum); + if (strcasecmp(*cpp, "to")) { + fprintf(stderr, "%d: unexpected keyword (%s) - to\n", + linenum, *cpp); + return NULL; + } + if ((ipn.in_flags & IPN_NOTDST) && + (ipn.in_redir & (NAT_REDIRECT))) { + fprintf(stderr, "Cannot use '! to' with rdr\n"); + return NULL; + } + + if (!*++cpp) { + fprintf(stderr, "%d: missing host after to\n", linenum); + return NULL; + } + if (ipn.in_redir == NAT_REDIRECT) { + if (hostmask(&cpp, (u_32_t *)&ipn.in_outip, + (u_32_t *)&ipn.in_outmsk, + &ipn.in_dport, &ipn.in_dcmp, + &ipn.in_dtop, linenum)) { + return NULL; + } + ipn.in_pmin = htons(ipn.in_dport); + } else { + if (hostmask(&cpp, (u_32_t *)&ipn.in_srcip, + (u_32_t *)&ipn.in_srcmsk, + &ipn.in_dport, &ipn.in_dcmp, + &ipn.in_dtop, linenum)) { + return NULL; + } + } + } else { + s = *cpp; + if (!s) + return NULL; + t = strchr(s, '/'); + if (!t) + return NULL; + *t++ = '\0'; + if (ipn.in_redir == NAT_REDIRECT) { + if (hostnum((u_32_t *)&ipn.in_outip, s, linenum) == -1) + return NULL; + if (genmask(t, (u_32_t *)&ipn.in_outmsk) == -1) { return NULL; } - if (!(s = strtok(NULL, " \t"))) { - fprintf(stderr, - "%d: missing fields (source netmask)\n", - linenum); + } else { + if (hostnum((u_32_t *)&ipn.in_inip, s, linenum) == -1) + return NULL; + if (genmask(t, (u_32_t *)&ipn.in_inmsk) == -1) { return NULL; } - srcnetm = s; } - if (*srcnetm == '/') - *srcnetm++ = '\0'; + cpp++; + if (!*cpp) + return NULL; + } - /* re read the next word -- destination */ - if (!(s = strtok(NULL, " \t"))) { - fprintf(stderr, - "%d: missing fields (destination)\n", linenum); + if ((ipn.in_redir == NAT_REDIRECT) && !(ipn.in_flags & IPN_FILTER)) { + if (strcasecmp(*cpp, "port")) { + fprintf(stderr, "%d: missing fields - 1st port\n", + linenum); return NULL; } - } - - shost = s; + cpp++; - if (ipn.in_redir == NAT_REDIRECT) { - if (!(s = strtok(NULL, " \t"))) { + if (!*cpp) { fprintf(stderr, "%d: missing fields (destination port)\n", linenum); return NULL; } - if (strcasecmp(s, "port")) { - fprintf(stderr, "%d: missing fields (port)\n", linenum); - return NULL; - } + if (isdigit(**cpp) && (s = strchr(*cpp, '-'))) + *s++ = '\0'; + else + s = NULL; - if (!(s = strtok(NULL, " \t"))) { - fprintf(stderr, - "%d: missing fields (destination port)\n", - linenum); + if (!portnum(*cpp, &ipn.in_pmin, linenum)) return NULL; + ipn.in_pmin = htons(ipn.in_pmin); + cpp++; + + if (!strcmp(*cpp, "-")) { + cpp++; + s = *cpp++; } - dport = s; + if (s) { + if (!portnum(s, &ipn.in_pmax, linenum)) + return NULL; + ipn.in_pmax = htons(ipn.in_pmax); + } else + ipn.in_pmax = ipn.in_pmin; } - - if (!(s = strtok(NULL, " \t"))) { + if (!*cpp) { fprintf(stderr, "%d: missing fields (->)\n", linenum); return NULL; } - if (!strcmp(s, "->")) { - snetm = strrchr(shost, '/'); - if (!snetm) { - fprintf(stderr, - "%d: missing fields (%s netmask)\n", linenum, - ipn.in_redir ? "destination" : "source"); - return NULL; - } - } else { - if (strcasecmp(s, "netmask")) { - fprintf(stderr, "%d: missing fields (netmask)\n", - linenum); - return NULL; - } - if (!(s = strtok(NULL, " \t"))) { - fprintf(stderr, - "%d: missing fields (%s netmask)\n", linenum, - ipn.in_redir ? "destination" : "source"); - return NULL; - } - snetm = s; + if (strcmp(*cpp, "->")) { + fprintf(stderr, "%d: missing ->\n", linenum); + return NULL; } + cpp++; - if (!(s = strtok(NULL, " \t"))) { + if (!*cpp) { fprintf(stderr, "%d: missing fields (%s)\n", - linenum, ipn.in_redir ? "destination":"target"); + linenum, ipn.in_redir ? "destination" : "target"); return NULL; } if (ipn.in_redir == NAT_MAP) { - if (!strcasecmp(s, "range")) { - ipn.in_flags |= IPN_RANGE; - if (!(s = strtok(NULL, " \t"))) { + if (!strcasecmp(*cpp, "range")) { + cpp++; + ipn.in_flags |= IPN_IPRANGE; + if (!*cpp) { fprintf(stderr, "%d: missing fields (%s)\n", linenum, ipn.in_redir ? "destination":"target"); @@ -409,187 +495,167 @@ int linenum; } } } - dhost = s; - if (ipn.in_redir & (NAT_MAP|NAT_MAPBLK)) { - if (ipn.in_flags & IPN_RANGE) { - dnetm = strrchr(dhost, '-'); - if (dnetm == NULL) { - if (!(s = strtok(NULL, " \t"))) - dnetm = NULL; - else { - if (strcmp(s, "-")) - s = NULL; - else if ((s = strtok(NULL, " \t"))) { - dnetm = s; - } - } - } else - *dnetm++ = '\0'; - if (dnetm == NULL || *dnetm == '\0') { - fprintf(stderr, - "%d: desination range not specified\n", - linenum); - return NULL; - } - } else { - dnetm = strrchr(dhost, '/'); - if (dnetm == NULL) { - if (!(s = strtok(NULL, " \t"))) - dnetm = NULL; - else if (!strcasecmp(s, "netmask")) - if ((s = strtok(NULL, " \t")) != NULL) - dnetm = s; - } - if (dnetm == NULL) { - fprintf(stderr, - "%d: missing fields (dest netmask)\n", - linenum); - return NULL; - } - if (*dnetm == '/') - *dnetm++ = '\0'; + if (ipn.in_flags & IPN_IPRANGE) { + dnetm = strrchr(*cpp, '-'); + if (dnetm == NULL) { + cpp++; + if (*cpp && !strcmp(*cpp, "-") && *(cpp + 1)) + dnetm = *(cpp + 1); + } else + *dnetm++ = '\0'; + if (dnetm == NULL || *dnetm == '\0') { + fprintf(stderr, + "%d: desination range not specified\n", + linenum); + return NULL; + } + } else if (ipn.in_redir != NAT_REDIRECT) { + dnetm = strrchr(*cpp, '/'); + if (dnetm == NULL) { + cpp++; + if (*cpp && !strcasecmp(*cpp, "netmask")) + dnetm = *++cpp; + } + if (dnetm == NULL) { + fprintf(stderr, + "%d: missing fields (dest netmask)\n", + linenum); + return NULL; + } + if (*dnetm == '/') + *dnetm++ = '\0'; + } + + if (ipn.in_redir == NAT_REDIRECT) { + dnetm = strchr(*cpp, ','); + if (dnetm != NULL) { + ipn.in_flags |= IPN_SPLIT; + *dnetm++ = '\0'; } - s = strtok(NULL, " \t"); + if (hostnum((u_32_t *)&ipn.in_inip, *cpp, linenum) == -1) + return NULL; + } else { + if (hostnum((u_32_t *)&ipn.in_outip, *cpp, linenum) == -1) + return NULL; } + cpp++; if (ipn.in_redir & NAT_MAPBLK) { - if (s && strcasecmp(s, "ports")) { + if (*cpp && strcasecmp(*cpp, "ports")) { fprintf(stderr, "%d: expected \"ports\" - got \"%s\"\n", - linenum, s); + linenum, *cpp); return NULL; } - if (s != NULL) { - if ((s = strtok(NULL, " \t")) == NULL) - return NULL; - ipn.in_pmin = atoi(s); - s = strtok(NULL, " \t"); + cpp++; + if (*cpp) { + ipn.in_pmin = atoi(*cpp); + cpp++; } else ipn.in_pmin = 0; } else if ((ipn.in_redir & NAT_BIMAP) == NAT_REDIRECT) { - if (strrchr(dhost, '/') != NULL) { + if (strrchr(*cpp, '/') != NULL) { fprintf(stderr, "%d: No netmask supported in %s\n", linenum, "destination host for redirect"); return NULL; } /* If it's a in_redir, expect target port */ - if (!(s = strtok(NULL, " \t"))) { - fprintf(stderr, - "%d: missing fields (destination port)\n", - linenum); - return NULL; - } - if (strcasecmp(s, "port")) { - fprintf(stderr, "%d: missing fields (port)\n", - linenum); + if (strcasecmp(*cpp, "port")) { + fprintf(stderr, "%d: missing fields - 2nd port (%s)\n", + linenum, *cpp); return NULL; } - - if (!(s = strtok(NULL, " \t"))) { + cpp++; + if (!*cpp) { fprintf(stderr, "%d: missing fields (destination port)\n", linenum); return NULL; } - tport = s; + if (!portnum(*cpp, &ipn.in_pnext, linenum)) + return NULL; + ipn.in_pnext = htons(ipn.in_pnext); + cpp++; } if (dnetm && *dnetm == '/') *dnetm++ = '\0'; - if (snetm && *snetm == '/') - *snetm++ = '\0'; if (ipn.in_redir & (NAT_MAP|NAT_MAPBLK)) { - ipn.in_inip = hostnum(shost, &resolved, linenum); - if (resolved == -1) - return NULL; - ipn.in_inmsk = n_hostmask(snetm); - ipn.in_outip = hostnum(dhost, &resolved, linenum); - if (resolved == -1) - return NULL; - if (ipn.in_flags & IPN_RANGE) { - ipn.in_outmsk = hostnum(dnetm, &resolved, linenum); - if (resolved == -1) - return NULL; - } else - ipn.in_outmsk = n_hostmask(dnetm); - if (srchost) { - ipn.in_srcip = hostnum(srchost, &resolved, linenum); - if (resolved == -1) + if (ipn.in_flags & IPN_IPRANGE) { + if (hostnum((u_32_t *)&ipn.in_outmsk, dnetm, + linenum) == -1) return NULL; - } - if (srcnetm) - ipn.in_srcmsk = n_hostmask(srcnetm); + } else if (genmask(dnetm, (u_32_t *)&ipn.in_outmsk)) + return NULL; } else { - if (srchost) { - ipn.in_srcip = hostnum(srchost, &resolved, linenum); - if (resolved == -1) + if (ipn.in_flags & IPN_SPLIT) { + if (hostnum((u_32_t *)&ipn.in_inmsk, dnetm, + linenum) == -1) return NULL; - } - if (srcnetm) - ipn.in_srcmsk = n_hostmask(srcnetm); - ipn.in_inip = hostnum(dhost, &resolved, linenum); - if (resolved == -1) + } else if (genmask("255.255.255.255", (u_32_t *)&ipn.in_inmsk)) return NULL; - ipn.in_inmsk = n_hostmask("255.255.255.255"); - ipn.in_outip = hostnum(shost, &resolved, linenum); - if (resolved == -1) - return NULL; - ipn.in_outmsk = n_hostmask(snetm); - if (!(s = strtok(NULL, " \t"))) { + if (!*cpp) { ipn.in_flags |= IPN_TCP; /* XXX- TCP only by default */ proto = "tcp"; } else { - if (!strcasecmp(s, "tcp")) + if (!strcasecmp(*cpp, "tcp")) ipn.in_flags |= IPN_TCP; - else if (!strcasecmp(s, "udp")) + else if (!strcasecmp(*cpp, "udp")) ipn.in_flags |= IPN_UDP; - else if (!strcasecmp(s, "tcp/udp")) + else if (!strcasecmp(*cpp, "tcp/udp")) ipn.in_flags |= IPN_TCPUDP; - else if (!strcasecmp(s, "tcpudp")) + else if (!strcasecmp(*cpp, "tcpudp")) ipn.in_flags |= IPN_TCPUDP; - else if (!strcasecmp(s, "ip")) + else if (!strcasecmp(*cpp, "ip")) ipn.in_flags |= IPN_ANY; else { ipn.in_flags |= IPN_ANY; - if ((pr = getprotobyname(s))) + if ((pr = getprotobyname(*cpp))) ipn.in_p = pr->p_proto; else - ipn.in_p = atoi(s); + ipn.in_p = atoi(*cpp); + } + proto = *cpp; + cpp++; + + if (*cpp && !strcasecmp(*cpp, "round-robin")) { + cpp++; + ipn.in_flags |= IPN_ROUNDR; } - proto = s; - if ((s = strtok(NULL, " \t"))) { + + if (*cpp) { fprintf(stderr, "%d: extra junk at the end of rdr: %s\n", - linenum, s); + linenum, *cpp); return NULL; } } - ipn.in_pmin = n_portnum(dport, proto, linenum); - ipn.in_pmax = ipn.in_pmin; - ipn.in_pnext = n_portnum(tport, proto, linenum); - s = NULL; } - ipn.in_inip &= ipn.in_inmsk; - if ((ipn.in_flags & IPN_RANGE) == 0) + + if (!(ipn.in_flags & IPN_SPLIT)) + ipn.in_inip &= ipn.in_inmsk; + if ((ipn.in_flags & IPN_IPRANGE) == 0) ipn.in_outip &= ipn.in_outmsk; ipn.in_srcip &= ipn.in_srcmsk; if ((ipn.in_redir & NAT_MAPBLK) != 0) nat_setgroupmap(&ipn); - if (!s) + if (!*cpp) return &ipn; if (ipn.in_redir == NAT_BIMAP) { fprintf(stderr, "%d: extra words at the end of bimap line: %s\n", - linenum, s); + linenum, *cpp); return NULL; } - if (!strcasecmp(s, "proxy")) { - if (!(s = strtok(NULL, " \t"))) { + + if (!strcasecmp(*cpp, "proxy")) { + cpp++; + if (!*cpp) { fprintf(stderr, "%d: missing parameter for \"proxy\"\n", linenum); @@ -597,17 +663,19 @@ int linenum; } dport = NULL; - if (!strcasecmp(s, "port")) { - if (!(s = strtok(NULL, " \t"))) { + if (!strcasecmp(*cpp, "port")) { + cpp++; + if (!*cpp) { fprintf(stderr, "%d: missing parameter for \"port\"\n", linenum); return NULL; } - dport = s; + dport = *cpp; + cpp++; - if (!(s = strtok(NULL, " \t"))) { + if (!*cpp) { fprintf(stderr, "%d: missing parameter for \"proxy\"\n", linenum); @@ -618,73 +686,86 @@ int linenum; "%d: missing keyword \"port\"\n", linenum); return NULL; } - if ((proto = index(s, '/'))) { + + if ((proto = index(*cpp, '/'))) { *proto++ = '\0'; if ((pr = getprotobyname(proto))) ipn.in_p = pr->p_proto; else ipn.in_p = atoi(proto); - if (dport) - ipn.in_dport = n_portnum(dport, proto, linenum); - } else { + } else ipn.in_p = 0; - if (dport) - ipn.in_dport = n_portnum(dport, NULL, linenum); - } - (void) strncpy(ipn.in_plabel, s, sizeof(ipn.in_plabel)); - if ((s = strtok(NULL, " \t"))) { + if (dport && !portnum(dport, &ipn.in_dport, linenum)) + return NULL; + ipn.in_dport = htons(ipn.in_dport); + + (void) strncpy(ipn.in_plabel, *cpp, sizeof(ipn.in_plabel)); + cpp++; + + if (*cpp) { fprintf(stderr, "%d: too many parameters for \"proxy\"\n", linenum); return NULL; } return &ipn; - } - if (strcasecmp(s, "portmap")) { + if (strcasecmp(*cpp, "portmap")) { fprintf(stderr, - "%d: expected \"portmap\" - got \"%s\"\n", linenum, s); + "%d: expected \"portmap\" - got \"%s\"\n", linenum, + *cpp); return NULL; } - if (!(s = strtok(NULL, " \t"))) + cpp++; + if (!*cpp) { + fprintf(stderr, "%d: missing expression following portmap\n", + linenum); return NULL; - if (!strcasecmp(s, "tcp")) + } + + if (!strcasecmp(*cpp, "tcp")) ipn.in_flags |= IPN_TCP; - else if (!strcasecmp(s, "udp")) + else if (!strcasecmp(*cpp, "udp")) ipn.in_flags |= IPN_UDP; - else if (!strcasecmp(s, "tcpudp")) + else if (!strcasecmp(*cpp, "tcpudp")) ipn.in_flags |= IPN_TCPUDP; - else if (!strcasecmp(s, "tcp/udp")) + else if (!strcasecmp(*cpp, "tcp/udp")) ipn.in_flags |= IPN_TCPUDP; else { fprintf(stderr, "%d: expected protocol name - got \"%s\"\n", - linenum, s); + linenum, *cpp); return NULL; } + proto = *cpp; + cpp++; - if (!(s = strtok(NULL, " \t"))) { + if (!*cpp) { fprintf(stderr, "%d: no port range found\n", linenum); return NULL; } - if (!strcasecmp(s, "auto")) { + if (!strcasecmp(*cpp, "auto")) { ipn.in_flags |= IPN_AUTOPORTMAP; ipn.in_pmin = htons(1024); ipn.in_pmax = htons(65535); nat_setgroupmap(&ipn); return &ipn; } - proto = s; - if (!(t = strchr(s, ':'))) { - fprintf(stderr, "%d: no port range in \"%s\"\n", linenum, s); + + if (!(t = strchr(*cpp, ':'))) { + fprintf(stderr, "%d: no port range in \"%s\"\n", + linenum, *cpp); return NULL; } *t++ = '\0'; - ipn.in_pmin = n_portnum(s, proto, linenum); - ipn.in_pmax = n_portnum(t, proto, linenum); + if (!portnum(*cpp, &ipn.in_pmin, linenum) || + !portnum(t, &ipn.in_pmax, linenum)) + return NULL; + ipn.in_pmin = htons(ipn.in_pmin); + ipn.in_pmax = htons(ipn.in_pmax); return &ipn; } @@ -709,7 +790,7 @@ int opts; fp = stdin; while (fgets(line, sizeof(line) - 1, fp)) { - linenum++; + linenum++; line[sizeof(line) - 1] = '\0'; if ((s = strchr(line, '\n'))) *s = '\0'; @@ -720,81 +801,21 @@ int opts; linenum, line); } else { if ((opts & OPT_VERBOSE) && np) - printnat(np, opts & OPT_VERBOSE, NULL); + printnat(np, opts, NULL); if (!(opts & OPT_NODO)) { - if (!(opts & OPT_REM)) { - if (ioctl(fd, SIOCADNAT, np) == -1) + if (!(opts & OPT_REMOVE)) { + if (ioctl(fd, SIOCADNAT, &np) == -1) { + fprintf(stderr, "%d:", + linenum); perror("ioctl(SIOCADNAT)"); - } else if (ioctl(fd, SIOCRMNAT, np) == -1) + } + } else if (ioctl(fd, SIOCRMNAT, &np) == -1) { + fprintf(stderr, "%d:", linenum); perror("ioctl(SIOCRMNAT)"); + } } } } if (fp != stdin) fclose(fp); } - - -u_32_t n_hostmask(msk) -char *msk; -{ - int bits = -1; - u_32_t mask; - - if (!isdigit(*msk)) - return (u_32_t)-1; - if (strchr(msk, '.')) - return inet_addr(msk); - if (strchr(msk, 'x')) -#if defined(sun) && !defined(__SVR4) && !defined(__svr4__) - return (u_32_t)htonl(strtol(msk, NULL, 0)); -#else - return (u_32_t)htonl(strtoul(msk, NULL, 0)); -#endif - /* - * set x most significant bits - */ - for (mask = 0, bits = atoi(msk); bits; bits--) { - mask /= 2; - mask |= ntohl(inet_addr("128.0.0.0")); - } - mask = htonl(mask); - return mask; -} - - -u_short n_portnum(name, proto, linenum) -char *name, *proto; -int linenum; -{ - struct servent *sp, *sp2; - u_short p1 = 0; - - if (isdigit(*name)) - return htons((u_short)atoi(name)); - if (!proto) - proto = "tcp/udp"; - if (strcasecmp(proto, "tcp/udp")) { - sp = getservbyname(name, proto); - if (sp) - return sp->s_port; - fprintf(stderr, "%d: unknown service \"%s\".\n", linenum, name); - return 0; - } - sp = getservbyname(name, "tcp"); - if (sp) - p1 = sp->s_port; - sp2 = getservbyname(name, "udp"); - if (!sp || !sp2) { - fprintf(stderr, "%d: unknown tcp/udp service \"%s\".\n", - linenum, name); - return 0; - } - if (p1 != sp2->s_port) { - fprintf(stderr, "%d: %s %d/tcp is a different port to ", - linenum, name, p1); - fprintf(stderr, "%d: %s %d/udp\n", linenum, name, sp->s_port); - return 0; - } - return p1; -} diff --git a/usr.sbin/ipmon/ipmon.c b/usr.sbin/ipmon/ipmon.c index 6b38934dbaa..d96d409ab05 100644 --- a/usr.sbin/ipmon/ipmon.c +++ b/usr.sbin/ipmon/ipmon.c @@ -1,15 +1,15 @@ -/* $OpenBSD: ipmon.c,v 1.24 2000/08/10 05:50:27 kjell Exp $ */ +/* $OpenBSD: ipmon.c,v 1.25 2001/01/17 05:01:02 fgsch Exp $ */ /* - * Copyright (C) 1993-1998 by Darren Reed. + * Copyright (C) 1993-2000 by Darren Reed. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and due credit is given * to the original author and the contributors. */ #if !defined(lint) -static const char sccsid[] = "@(#)ipmon.c 1.21 6/5/96 (C)1993-1998 Darren Reed"; -static const char rcsid[] = "@(#)$IPFilter: ipmon.c,v 2.3.2.6 2000/08/07 13:04:51 darrenr Exp $"; +static const char sccsid[] = "@(#)ipmon.c 1.21 6/5/96 (C)1993-2000 Darren Reed"; +static const char rcsid[] = "@(#)$IPFilter: ipmon.c,v 2.12.2.6 2000/10/31 22:17:41 darrenr Exp $"; #endif #ifndef SOLARIS @@ -65,7 +65,7 @@ static const char rcsid[] = "@(#)$IPFilter: ipmon.c,v 2.3.2.6 2000/08/07 13:04:5 #include <ctype.h> #include <syslog.h> -#include <netinet/ip_fil_compat.h> +#include <netinet/ip_compat.h> #include <netinet/tcpip.h> #include <netinet/ip_fil.h> #include <netinet/ip_proxy.h> @@ -106,14 +106,6 @@ static char *pidfile = "/etc/ipmon.pid"; # endif #endif -struct hlist { - struct hlist *next; - struct in_addr addr; - char name[MAXHOSTNAMELEN]; -}; -#define PRIME 367 -static struct hlist htable[PRIME]; - static char line[2048]; static int opts = 0; static FILE *newlog = NULL; @@ -130,7 +122,7 @@ static void dumphex __P((FILE *, u_char *, int)); static int read_log __P((int, int *, char *, int)); static void write_pid __P((char *)); -char *hostname __P((int, struct in_addr)); +char *hostname __P((int, int, u_32_t *)); char *portname __P((int, char *, u_int)); int main __P((int, char *[])); @@ -155,6 +147,8 @@ static char **tcp_ports = NULL; #define OPT_PORTNUM 0x400 #define OPT_LOGALL (OPT_NAT|OPT_STATE|OPT_FILTER) +#define HOSTNAME_V4(a,b) hostname((a), 4, (u_32_t *)&(b)) + #ifndef LOGFAC #define LOGFAC LOG_LOCAL0 #endif @@ -217,11 +211,11 @@ static void init_tabs() if (s->s_proto == NULL) continue; else if (!strcmp(s->s_proto, "tcp")) { - port = s->s_port; + port = ntohs(s->s_port); name = s->s_name; tab = tcp_ports; } else if (!strcmp(s->s_proto, "udp")) { - port = s->s_port; + port = ntohs(s->s_port); name = s->s_name; tab = udp_ports; } else @@ -266,35 +260,33 @@ char *buf; } -char *hostname(res, ip) -int res; -struct in_addr ip; +char *hostname(res, v, ip) +int res, v; +u_32_t *ip; { +#ifdef USE_INET6 + static char hostbuf[MAXHOSTNAMELEN+1]; +#endif struct hostent *hp; - struct hlist *hl; - - if (!res) - return inet_ntoa(ip); + struct in_addr ipa; - hl = &htable[ip.s_addr % PRIME]; - for ( ; hl->next != NULL; hl = hl->next) - if (hl->addr.s_addr == ip.s_addr) - return hl->name; + if (v == 4) { + ipa.s_addr = *ip; + if (!res) + return inet_ntoa(ipa); + hp = gethostbyaddr((char *)ip, sizeof(ip), AF_INET); + if (!hp) + return inet_ntoa(ipa); + return hp->h_name; - hl->addr.s_addr = ip.s_addr; - hl->next = (struct hlist *)calloc(1, sizeof(*hl)); - if (hl->next == NULL) { - perror("calloc"); - exit(1); } - - hp = gethostbyaddr((char *)&ip, sizeof(ip), AF_INET); - if (!hp) - strlcpy(hl->name, inet_ntoa(ip), sizeof hl->name); - else - strlcpy(hl->name, hp->h_name, sizeof hl->name); - - return hl->name; +#ifdef USE_INET6 + (void) inet_ntop(AF_INET6, ip, hostbuf, sizeof(hostbuf) - 1); + hostbuf[MAXHOSTNAMELEN] = '\0'; + return hostbuf; +#else + return "IPv6"; +#endif } @@ -346,7 +338,7 @@ int len; t += 2; if (!((j + 1) & 0xf)) { s -= 15; - sprintf((char *)t, " "); + sprintf((char *)t, " "); t += 8; for (k = 16; k; k--, s++) *t++ = (isprint(*s) ? *s : '.'); @@ -411,28 +403,36 @@ int blen; strcpy(t, "NAT:RDR "); else if (nl->nl_type == NL_EXPIRE) strcpy(t, "NAT:EXPIRE "); + else if (nl->nl_type == NL_FLUSH) + strcpy(t, "NAT:FLUSH "); + else if (nl->nl_type == NL_NEWBIMAP) + strcpy(t, "NAT:BIMAP "); + else if (nl->nl_type == NL_NEWBLOCK) + strcpy(t, "NAT:MAPBLOCK "); else sprintf(t, "Type: %d ", nl->nl_type); t += strlen(t); proto = getproto(nl->nl_p); - (void) sprintf(t, "%s,%s <- -> ", hostname(res, nl->nl_inip), + (void) sprintf(t, "%s,%s <- -> ", HOSTNAME_V4(res, nl->nl_inip), portname(res, proto, (u_int)nl->nl_inport)); t += strlen(t); - (void) sprintf(t, "%s,%s ", hostname(res, nl->nl_outip), + (void) sprintf(t, "%s,%s ", HOSTNAME_V4(res, nl->nl_outip), portname(res, proto, (u_int)nl->nl_outport)); t += strlen(t); - (void) sprintf(t, "[%s,%s]", hostname(res, nl->nl_origip), + (void) sprintf(t, "[%s,%s]", HOSTNAME_V4(res, nl->nl_origip), portname(res, proto, (u_int)nl->nl_origport)); t += strlen(t); if (nl->nl_type == NL_EXPIRE) { #ifdef USE_QUAD_T (void) sprintf(t, " Pkts %qd Bytes %qd", + (long long)nl->nl_pkts, + (long long)nl->nl_bytes); #else (void) sprintf(t, " Pkts %ld Bytes %ld", -#endif nl->nl_pkts, nl->nl_bytes); +#endif t += strlen(t); } @@ -482,6 +482,8 @@ int blen; strcpy(t, "STATE:EXPIRE "); } else if (sl->isl_type == ISL_FLUSH) strcpy(t, "STATE:FLUSH "); + else if (sl->isl_type == ISL_REMOVE) + strcpy(t, "STATE:REMOVE "); else sprintf(t, "Type: %d ", sl->isl_type); t += strlen(t); @@ -490,26 +492,30 @@ int blen; if (sl->isl_p == IPPROTO_TCP || sl->isl_p == IPPROTO_UDP) { (void) sprintf(t, "%s,%s -> ", - hostname(res, sl->isl_src), + hostname(res, sl->isl_v, (u_32_t *)&sl->isl_src), portname(res, proto, (u_int)sl->isl_sport)); t += strlen(t); (void) sprintf(t, "%s,%s PR %s", - hostname(res, sl->isl_dst), + hostname(res, sl->isl_v, (u_32_t *)&sl->isl_dst), portname(res, proto, (u_int)sl->isl_dport), proto); } else if (sl->isl_p == IPPROTO_ICMP) { - (void) sprintf(t, "%s -> ", hostname(res, sl->isl_src)); + (void) sprintf(t, "%s -> ", hostname(res, sl->isl_v, + (u_32_t *)&sl->isl_src)); t += strlen(t); (void) sprintf(t, "%s PR icmp %d", - hostname(res, sl->isl_dst), sl->isl_itype); + hostname(res, sl->isl_v, (u_32_t *)&sl->isl_dst), + sl->isl_itype); } t += strlen(t); if (sl->isl_type != ISL_NEW) { #ifdef USE_QUAD_T (void) sprintf(t, " Pkts %qd Bytes %qd", + (long long)sl->isl_pkts, + (long long)sl->isl_bytes); #else (void) sprintf(t, " Pkts %ld Bytes %ld", -#endif sl->isl_pkts, sl->isl_bytes); +#endif t += strlen(t); } @@ -579,26 +585,30 @@ int blen; { tcphdr_t *tp; struct icmp *ic; - struct icmp *icmphdr; + struct icmp *icmp; struct tm *tm; char *t, *proto; - u_short hl, p; - int i, lvl, res, len, ipoff; + int i, v, lvl, res, len, off, plen, ipoff; ip_t *ipc, *ip; - iplog_t *ipl; + u_short hl, p; ipflog_t *ipf; + iplog_t *ipl; + u_32_t *s, *d; +#ifdef USE_INET6 + ip6_t *ip6; +#endif ipl = (iplog_t *)buf; ipf = (ipflog_t *)((char *)buf + sizeof(*ipl)); ip = (ip_t *)((char *)ipf + sizeof(*ipf)); + v = ip->ip_v; 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 *)&ipl->ipl_sec); #ifdef linux - ip->ip_len = ntohs(ip->ip_len); + if (v == 4) + ip->ip_len = ntohs(ip->ip_len); #endif len = sizeof(line); @@ -637,7 +647,6 @@ int blen; #endif (void) sprintf(t, " @%hu:%hu ", ipf->fl_group, ipf->fl_rule + 1); t += strlen(t); - proto = getproto(p); if (ipf->fl_flags & FF_SHORT) { *t++ = 'S'; @@ -666,18 +675,43 @@ int blen; *t++ = ' '; *t = '\0'; - if ((p == IPPROTO_TCP || p == IPPROTO_UDP) && - !(ip->ip_off & IP_OFFMASK)) { + if (v == 6) { +#ifdef USE_INET6 + off = 0; + ipoff = 0; + hl = sizeof(ip6_t); + ip6 = (ip6_t *)ip; + p = (u_short)ip6->ip6_nxt; + s = (u_32_t *)&ip6->ip6_src; + d = (u_32_t *)&ip6->ip6_dst; + plen = ntohs(ip6->ip6_plen); +#else + sprintf(t, "ipv6"); + goto printipflog; +#endif + } else if (v == 4) { + hl = (ip->ip_hl << 2); + ipoff = ip->ip_off; + off = ipoff & IP_OFFMASK; + p = (u_short)ip->ip_p; + s = (u_32_t *)&ip->ip_src; + d = (u_32_t *)&ip->ip_dst; + plen = ip->ip_len; + } else { + goto printipflog; + } + proto = getproto(p); + + if ((p == IPPROTO_TCP || p == IPPROTO_UDP) && !off) { tp = (tcphdr_t *)((char *)ip + hl); if (!(ipf->fl_flags & (FI_SHORT << 16))) { - (void) sprintf(t, "%s,%s -> ", - hostname(res, ip->ip_src), + (void) sprintf(t, "%s,%s -> ", hostname(res, v, s), portname(res, proto, (u_int)tp->th_sport)); t += strlen(t); (void) sprintf(t, "%s,%s PR %s len %hu %hu ", - hostname(res, ip->ip_dst), + hostname(res, v, d), portname(res, proto, (u_int)tp->th_dport), - proto, hl, ip->ip_len); + proto, hl, plen); t += strlen(t); if (p == IPPROTO_TCP) { @@ -695,18 +729,17 @@ int blen; } *t = '\0'; } else { - (void) sprintf(t, "%s -> ", hostname(res, ip->ip_src)); + (void) sprintf(t, "%s -> ", hostname(res, v, s)); t += strlen(t); (void) sprintf(t, "%s PR %s len %hu %hu", - hostname(res, ip->ip_dst), proto, - hl, ip->ip_len); + hostname(res, v, d), proto, hl, plen); } - } else if ((p == IPPROTO_ICMP) && !(ip->ip_off & IP_OFFMASK)) { + } else if ((p == IPPROTO_ICMP) && !off && (v == 4)) { ic = (struct icmp *)((char *)ip + hl); - (void) sprintf(t, "%s -> ", hostname(res, ip->ip_src)); + (void) sprintf(t, "%s -> ", hostname(res, v, s)); t += strlen(t); (void) sprintf(t, "%s PR icmp len %hu %hu icmp %d/%d", - hostname(res, ip->ip_dst), hl, ip->ip_len, + hostname(res, v, d), hl, plen, ic->icmp_type, ic->icmp_code); if (ic->icmp_type == ICMP_UNREACH || ic->icmp_type == ICMP_SOURCEQUENCH || @@ -722,62 +755,60 @@ int blen; ((ipc->ip_p == IPPROTO_TCP) || (ipc->ip_p == IPPROTO_UDP))) { tp = (tcphdr_t *)((char *)ipc + hl); - t += strlen(t); (void) sprintf(t, " for %s,%s -", - hostname(res, ipc->ip_src), + HOSTNAME_V4(res, ipc->ip_src), portname(res, proto, (u_int)tp->th_sport)); t += strlen(t); (void) sprintf(t, " %s,%s PR %s len %hu %hu", - hostname(res, ipc->ip_dst), + HOSTNAME_V4(res, ipc->ip_dst), portname(res, proto, (u_int)tp->th_dport), - proto, ipc->ip_hl << 2, ipc->ip_len); - } else if ((ipc->ip_p == IPPROTO_ICMP) && - !(ipoff & IP_OFFMASK)) { - icmphdr = (icmphdr_t *)((char *)ipc + hl); + proto, ipc->ip_hl << 2, i); + } else if (!(ipoff & IP_OFFMASK) && + (ipc->ip_p == IPPROTO_ICMP)) { + icmp = (icmphdr_t *)((char *)ipc + hl); t += strlen(t); (void) sprintf(t, " for %s -", - hostname(res, ipc->ip_src)); + HOSTNAME_V4(res, ipc->ip_src)); t += strlen(t); (void) sprintf(t, " %s PR icmp len %hu %hu icmp %d/%d", - hostname(res, ipc->ip_dst), + HOSTNAME_V4(res, ipc->ip_dst), ipc->ip_hl << 2, i, - icmphdr->icmp_type, icmphdr->icmp_code); - } else { + icmp->icmp_type, icmp->icmp_code); + } else { t += strlen(t); (void) sprintf(t, " for %s -", - hostname(res, ipc->ip_src)); + HOSTNAME_V4(res, ipc->ip_src)); t += strlen(t); (void) sprintf(t, " %s PR %s len %hu (%hu)", - hostname(res, ipc->ip_dst), - proto, ipc->ip_hl << 2, ipc->ip_len); + HOSTNAME_V4(res, ipc->ip_dst), proto, + ipc->ip_hl << 2, i); t += strlen(t); - if (ipc->ip_off & IP_OFFMASK) { + if (ipoff & IP_OFFMASK) { (void) sprintf(t, " frag %s%s%hu@%hu", ipoff & IP_MF ? "+" : "", ipoff & IP_DF ? "-" : "", - i - (ipc->ip_hl << 2), + i - (ipc->ip_hl<<2), (ipoff & IP_OFFMASK) << 3); } } } } else { - (void) sprintf(t, "%s -> ", hostname(res, ip->ip_src)); + (void) sprintf(t, "%s -> ", hostname(res, v, s)); t += strlen(t); (void) sprintf(t, "%s PR %s len %hu (%hu)", - hostname(res, ip->ip_dst), proto, hl, ip->ip_len); + hostname(res, v, d), proto, hl, plen); t += strlen(t); - if (ip->ip_off & IP_OFFMASK) + if (off & IP_OFFMASK) (void) sprintf(t, " frag %s%s%hu@%hu", - ip->ip_off & IP_MF ? "+" : "", - ip->ip_off & IP_DF ? "-" : "", - ip->ip_len - hl, - (ip->ip_off & IP_OFFMASK) << 3); + ipoff & IP_MF ? "+" : "", + ipoff & IP_DF ? "-" : "", + plen - hl, (off & IP_OFFMASK) << 3); } t += strlen(t); @@ -796,6 +827,7 @@ int blen; else if (ipf->fl_flags & FR_OUTQUE) strcpy(t, " OUT"); t += strlen(t); +printipflog: *t++ = '\n'; *t++ = '\0'; if (opts & OPT_SYSLOG) @@ -972,7 +1004,6 @@ char *argv[]; openlog(s, LOG_NDELAY|LOG_PID, LOGFAC); s = NULL; opts |= OPT_SYSLOG; - log = NULL; break; case 'S' : opts |= OPT_STATE; |