diff options
author | yz155240 <none@none> | 2006-07-19 01:15:53 -0700 |
---|---|---|
committer | yz155240 <none@none> | 2006-07-19 01:15:53 -0700 |
commit | ab25eeb551a4be927a4b6ae2cf8aff7ed17decb4 (patch) | |
tree | 8f3a55a94fbaf0fdcbf3d0270606e4528a9dbb37 | |
parent | e32cd585e45b9f19db8e971dfa93046993fced0f (diff) | |
download | illumos-joyent-ab25eeb551a4be927a4b6ae2cf8aff7ed17decb4.tar.gz |
PSARC 2006/082 IP Filter Code Merge on ip_fil4.1.9
4912568 ipftest ipf ipfstat ipnat ippool need a non-name resolution flag
5040248 ipfs -W fails to save kernel state tables
5081834 syntax parser reports wrong error position and line number
5094575 keyword "netmask" is un-supported in ipnat.conf (4)
6181751 ipf parser fails on wrong subnet notations
6181773 ipf parser fails on wrong port ranges
6248745 ipnat drops packets if the IP header is not 32 bit aligned
6340621 RFE: IP Filter code merge on ip_fil4.1.9
6359805 ipf command incorrectly check options in rules and core dumps
6395837 ipnat tcpudp parsing is incomplete
6426469 IPFilter rejects IPv6 neighbour discovery packets
6447872 usr/src/common/ipf/ip_compat.h should not be CDDL
--HG--
rename : usr/src/common/ipf/bpf-ipf.h => usr/src/uts/common/inet/ipf/bpf-ipf.h
rename : usr/src/common/ipf/fil.c => usr/src/uts/common/inet/ipf/fil.c
rename : usr/src/common/ipf/ip_auth.c => usr/src/uts/common/inet/ipf/ip_auth.c
rename : usr/src/common/ipf/ip_fil_solaris.c => usr/src/uts/common/inet/ipf/ip_fil_solaris.c
rename : usr/src/common/ipf/ip_frag.c => usr/src/uts/common/inet/ipf/ip_frag.c
rename : usr/src/common/ipf/ip_htable.c => usr/src/uts/common/inet/ipf/ip_htable.c
rename : usr/src/common/ipf/ip_log.c => usr/src/uts/common/inet/ipf/ip_log.c
rename : usr/src/common/ipf/ip_lookup.c => usr/src/uts/common/inet/ipf/ip_lookup.c
rename : usr/src/common/ipf/ip_nat.c => usr/src/uts/common/inet/ipf/ip_nat.c
rename : usr/src/common/ipf/ip_pool.c => usr/src/uts/common/inet/ipf/ip_pool.c
rename : usr/src/common/ipf/ip_proxy.c => usr/src/uts/common/inet/ipf/ip_proxy.c
rename : usr/src/common/ipf/ip_state.c => usr/src/uts/common/inet/ipf/ip_state.c
rename : usr/src/common/ipf/ipf.h => usr/src/uts/common/inet/ipf/ipf.h
rename : usr/src/common/ipf/ipmon.h => usr/src/uts/common/inet/ipf/ipmon.h
rename : usr/src/common/ipf/ipt.h => usr/src/uts/common/inet/ipf/ipt.h
rename : usr/src/common/ipf/Makefile => usr/src/uts/common/inet/ipf/netinet/Makefile
rename : usr/src/common/ipf/ip_auth.h => usr/src/uts/common/inet/ipf/netinet/ip_auth.h
rename : usr/src/common/ipf/ip_compat.h => usr/src/uts/common/inet/ipf/netinet/ip_compat.h
rename : usr/src/common/ipf/ip_fil.h => usr/src/uts/common/inet/ipf/netinet/ip_fil.h
rename : usr/src/common/ipf/ip_frag.h => usr/src/uts/common/inet/ipf/netinet/ip_frag.h
rename : usr/src/common/ipf/ip_ftp_pxy.c => usr/src/uts/common/inet/ipf/netinet/ip_ftp_pxy.c
rename : usr/src/common/ipf/ip_h323_pxy.c => usr/src/uts/common/inet/ipf/netinet/ip_h323_pxy.c
rename : usr/src/common/ipf/ip_htable.h => usr/src/uts/common/inet/ipf/netinet/ip_htable.h
rename : usr/src/common/ipf/ip_ipsec_pxy.c => usr/src/uts/common/inet/ipf/netinet/ip_ipsec_pxy.c
rename : usr/src/common/ipf/ip_irc_pxy.c => usr/src/uts/common/inet/ipf/netinet/ip_irc_pxy.c
rename : usr/src/common/ipf/ip_lookup.h => usr/src/uts/common/inet/ipf/netinet/ip_lookup.h
rename : usr/src/common/ipf/ip_nat.h => usr/src/uts/common/inet/ipf/netinet/ip_nat.h
rename : usr/src/common/ipf/ip_netbios_pxy.c => usr/src/uts/common/inet/ipf/netinet/ip_netbios_pxy.c
rename : usr/src/common/ipf/ip_pool.h => usr/src/uts/common/inet/ipf/netinet/ip_pool.h
rename : usr/src/common/ipf/ip_proxy.h => usr/src/uts/common/inet/ipf/netinet/ip_proxy.h
rename : usr/src/common/ipf/ip_raudio_pxy.c => usr/src/uts/common/inet/ipf/netinet/ip_raudio_pxy.c
rename : usr/src/common/ipf/ip_rcmd_pxy.c => usr/src/uts/common/inet/ipf/netinet/ip_rcmd_pxy.c
rename : usr/src/common/ipf/ip_rpcb_pxy.c => usr/src/uts/common/inet/ipf/netinet/ip_rpcb_pxy.c
rename : usr/src/common/ipf/ip_state.h => usr/src/uts/common/inet/ipf/netinet/ip_state.h
rename : usr/src/common/ipf/ipl.h => usr/src/uts/common/inet/ipf/netinet/ipl.h
rename : usr/src/common/ipf/opts.h => usr/src/uts/common/inet/ipf/opts.h
rename : usr/src/common/ipf/radix.c => usr/src/uts/common/inet/ipf/radix.c
rename : usr/src/common/ipf/radix.h => usr/src/uts/common/inet/ipf/radix.h
rename : usr/src/common/ipf/solaris.c => usr/src/uts/common/inet/ipf/solaris.c
rename : usr/src/uts/common/inet/ipf/compat.h => usr/src/uts/common/inet/pfil/compat.h
rename : usr/src/uts/common/inet/ipf/misc.c => usr/src/uts/common/inet/pfil/misc.c
rename : usr/src/uts/common/inet/ipf/ndd.c => usr/src/uts/common/inet/pfil/ndd.c
rename : usr/src/uts/common/inet/ipf/os.h => usr/src/uts/common/inet/pfil/os.h
rename : usr/src/uts/common/inet/ipf/pfil.c => usr/src/uts/common/inet/pfil/pfil.c
rename : usr/src/uts/common/inet/ipf/pfil.conf => usr/src/uts/common/inet/pfil/pfil.conf
rename : usr/src/uts/common/inet/ipf/pfil.h => usr/src/uts/common/inet/pfil/pfil.h
rename : usr/src/common/ipf/pfild.h => usr/src/uts/common/inet/pfil/pfild.h
rename : usr/src/uts/common/inet/ipf/pfildrv.c => usr/src/uts/common/inet/pfil/pfildrv.c
rename : usr/src/uts/common/inet/ipf/pfilstream.c => usr/src/uts/common/inet/pfil/pfilstream.c
rename : usr/src/uts/common/inet/ipf/pkt.c => usr/src/uts/common/inet/pfil/pkt.c
rename : usr/src/uts/common/inet/ipf/qif.c => usr/src/uts/common/inet/pfil/qif.c
rename : usr/src/uts/common/inet/ipf/qif.h => usr/src/uts/common/inet/pfil/qif.h
131 files changed, 11184 insertions, 7159 deletions
diff --git a/usr/src/Makefile b/usr/src/Makefile index f04c2c9388..1707c95d75 100644 --- a/usr/src/Makefile +++ b/usr/src/Makefile @@ -180,7 +180,7 @@ cmdheaders: FRC @cd cmd/mdb; pwd; $(MAKE) install_h commonheaders: FRC - @cd common/ipf; pwd; $(MAKE) install_h + @cd uts/common/inet/ipf/netinet; pwd; $(MAKE) install_h # each xmod target depends on a corresponding MACH-specific pseudotarget # before doing common xmod work diff --git a/usr/src/cmd/ipf/Makefile.ipf b/usr/src/cmd/ipf/Makefile.ipf index b4bb4d8620..7a6d8c4c16 100644 --- a/usr/src/cmd/ipf/Makefile.ipf +++ b/usr/src/cmd/ipf/Makefile.ipf @@ -1,5 +1,5 @@ # -# Copyright 2005 Sun Microsystems, Inc. All rights reserved. +# Copyright 2006 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # #ident "%Z%%M% %I% %E% SMI" @@ -11,8 +11,8 @@ LIBIPF= ../../lib/$(MACH)/libipf.a LIBIPF64= ../../lib/$(MACH64)/libipf.a -COMMONIPF= $(SRC)/common/ipf -KERNELIPF= $(SRC)/uts/common/inet/ipf +COMMONIPF= $(SRC)/uts/common/inet/ipf +KERNELIPF= $(SRC)/uts/common/inet/pfil MINOR= echo $(RELEASE) | cut -d. -f2 CPPFLAGS += -I$(COMMONIPF) -I$(KERNELIPF) -DSUNDDI -DUSE_INET6 \ diff --git a/usr/src/cmd/ipf/lib/Makefile.com b/usr/src/cmd/ipf/lib/Makefile.com index c2f50235b5..70f7d0a179 100644 --- a/usr/src/cmd/ipf/lib/Makefile.com +++ b/usr/src/cmd/ipf/lib/Makefile.com @@ -1,5 +1,5 @@ # -# Copyright 2005 Sun Microsystems, Inc. All rights reserved. +# Copyright 2006 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # #ident "%Z%%M% %I% %E% SMI" @@ -17,19 +17,21 @@ OBJECTS= addicmp.o addipopt.o bcopywrap.o \ getline.o getnattype.o getport.o getportproto.o \ getproto.o getsumd.o hostmask.o hostname.o \ hostnum.o icmpcode.o inet_addr.o initparse.o \ - ionames.o ipoptsec.o ipft_ef.o ipft_hx.o \ - ipft_pc.o ipft_sn.o ipft_td.o ipft_tx.o kmem.o \ - kmemcpywrap.o kvatoname.o load_hash.o load_pool.o \ - load_hashnode.o load_poolnode.o loglevel.o \ - mutex_emul.o nametokva.o natparse.o ntomask.o \ - optname.o optprint.o optprintv6.o optvalue.o \ + ionames.o v6ionames.o ipoptsec.o ipf_dotuning.o \ + ipft_ef.o ipft_hx.o ipft_pc.o ipft_sn.o ipft_td.o \ + ipft_tx.o kmem.o kmemcpywrap.o kvatoname.o \ + load_hash.o load_pool.o load_hashnode.o \ + load_poolnode.o loglevel.o mutex_emul.o nametokva.o \ + natparse.o ntomask.o optname.o optprint.o \ + optprintv6.o optvalue.o \ portname.o portnum.o ports.o print_toif.o \ - printaps.o printbuf.o printhash.o printhashnode.o \ - printip.o printpool.o printpoolnode.o printfr.o \ + printactivenat.o printaps.o printbuf.o printhash.o \ + printhashnode.o printip.o printpool.o \ + printpoolnode.o printfr.o printfraginfo.o \ printhostmap.o printifname.o printhostmask.o \ - printlog.o printmask.o printnat.o printportcmp.o \ - printpacket.o printpacket6.o printsbuf.o \ - printstate.o ratoi.o \ + printlog.o printmask.o printnat.o printpacket.o \ + printpacket6.o printportcmp.o printproto.o \ + printsbuf.o printstate.o printtunable.o ratoi.o \ remove_pool.o remove_poolnode.o remove_hash.o \ remove_hashnode.o resetlexer.o rwlock_emul.o \ tcpflags.o to_interface.o var.o verbose.o \ diff --git a/usr/src/cmd/ipf/lib/common/addicmp.c b/usr/src/cmd/ipf/lib/common/addicmp.c index 4892ba09ed..e18a787a0a 100644 --- a/usr/src/cmd/ipf/lib/common/addicmp.c +++ b/usr/src/cmd/ipf/lib/common/addicmp.c @@ -3,7 +3,7 @@ * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: addicmp.c,v 1.8 2002/01/28 06:50:45 darrenr Exp $ + * $Id: addicmp.c,v 1.10.2.1 2004/12/09 19:41:16 darrenr Exp $ */ #include <ctype.h> @@ -34,7 +34,7 @@ int linenum; return -1; if (!fp->fr_proto) /* to catch lusers */ fp->fr_proto = IPPROTO_ICMP; - if (isdigit(***cp)) { + if (ISDIGIT(***cp)) { if (!ratoi(**cp, &i, 0, 255)) { fprintf(stderr, "%d: Invalid icmp-type (%s) specified\n", @@ -68,9 +68,9 @@ int linenum; if (**cp && strcasecmp("code", **cp)) return 0; (*cp)++; - if (isdigit(***cp)) { + if (ISDIGIT(***cp)) { if (!ratoi(**cp, &i, 0, 255)) { - fprintf(stderr, + fprintf(stderr, "%d: Invalid icmp code (%s) specified\n", linenum, **cp); return -1; @@ -78,7 +78,7 @@ int linenum; } else { i = icmpcode(**cp); if (i == -1) { - fprintf(stderr, + fprintf(stderr, "%d: Unknown icmp code (%s) specified\n", linenum, **cp); return -1; diff --git a/usr/src/cmd/ipf/lib/common/checkrev.c b/usr/src/cmd/ipf/lib/common/checkrev.c index c57295385f..f95cc7977a 100644 --- a/usr/src/cmd/ipf/lib/common/checkrev.c +++ b/usr/src/cmd/ipf/lib/common/checkrev.c @@ -3,21 +3,21 @@ * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: checkrev.c,v 1.9 2003/04/27 17:09:46 darrenr Exp $ + * $Id: checkrev.c,v 1.12.2.1 2004/03/09 14:44:39 darrenr Exp $ */ #include <sys/ioctl.h> #include <fcntl.h> #include "ipf.h" -#include "ipl.h" +#include "netinet/ipl.h" int checkrev(ipfname) char *ipfname; { + static int vfd = -1; struct friostat fio, *fiop = &fio; ipfobj_t ipfo; - int vfd; bzero((caddr_t)&ipfo, sizeof(ipfo)); ipfo.ipfo_rev = IPFILTER_VERSION; @@ -25,7 +25,7 @@ char *ipfname; ipfo.ipfo_ptr = (void *)fiop; ipfo.ipfo_type = IPFOBJ_IPFSTAT; - if ((vfd = open(ipfname, O_RDONLY)) == -1) { + if ((vfd == -1) && ((vfd = open(ipfname, O_RDONLY)) == -1)) { perror("open device"); return -1; } @@ -33,9 +33,9 @@ char *ipfname; if (ioctl(vfd, SIOCGETFS, &ipfo)) { perror("ioctl(SIOCGETFS)"); close(vfd); + vfd = -1; return -1; } - close(vfd); if (strncmp(IPL_VERSION, fio.f_version, sizeof(fio.f_version))) { return -1; diff --git a/usr/src/cmd/ipf/lib/common/facpri.c b/usr/src/cmd/ipf/lib/common/facpri.c index eb76ee0f95..9d6faa9055 100644 --- a/usr/src/cmd/ipf/lib/common/facpri.c +++ b/usr/src/cmd/ipf/lib/common/facpri.c @@ -3,7 +3,7 @@ * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: facpri.c,v 1.5 2001/06/09 17:09:24 darrenr Exp $ + * $Id: facpri.c,v 1.6 2003/12/01 01:59:43 darrenr Exp $ */ #include <stdio.h> @@ -20,7 +20,7 @@ #include "facpri.h" #if !defined(lint) -static const char rcsid[] = "@(#)$Id: facpri.c,v 1.5 2001/06/09 17:09:24 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id: facpri.c,v 1.6 2003/12/01 01:59:43 darrenr Exp $"; #endif @@ -35,7 +35,7 @@ table_t facs[] = { { "auth", LOG_AUTH }, { "syslog", LOG_SYSLOG }, { "lpr", LOG_LPR }, { "news", LOG_NEWS }, { "uucp", LOG_UUCP }, -#if LOG_CRON == LOG_CRON2 +#if LOG_CRON == LOG_CRON2 { "cron2", LOG_CRON1 }, #else { "cron", LOG_CRON1 }, diff --git a/usr/src/cmd/ipf/lib/common/genmask.c b/usr/src/cmd/ipf/lib/common/genmask.c index e57a65499b..238e5b62af 100644 --- a/usr/src/cmd/ipf/lib/common/genmask.c +++ b/usr/src/cmd/ipf/lib/common/genmask.c @@ -3,7 +3,7 @@ * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: genmask.c,v 1.6 2002/01/28 06:50:46 darrenr Exp $ + * $Id: genmask.c,v 1.7 2003/11/11 13:40:15 darrenr Exp $ */ #include "ipf.h" diff --git a/usr/src/cmd/ipf/lib/common/gethost.c b/usr/src/cmd/ipf/lib/common/gethost.c index bc5d8975ee..5ecea3adaf 100644 --- a/usr/src/cmd/ipf/lib/common/gethost.c +++ b/usr/src/cmd/ipf/lib/common/gethost.c @@ -1,3 +1,8 @@ +/* + * Copyright (C) 1993-2005 by Darren Reed. + * See the IPFILTER.LICENCE file for details on licencing. + */ + #include "ipf.h" int gethost(name, hostp) @@ -5,8 +10,14 @@ char *name; u_32_t *hostp; { struct hostent *h; + struct netent *n; u_32_t addr; + if (!strcmp(name, "test.host.dots")) { + *hostp = htonl(0xfedcba98); + return 0; + } + if (!strcmp(name, "<thishost>")) name = thishost; @@ -18,5 +29,11 @@ u_32_t *hostp; return 0; } } + + n = getnetbyname(name); + if (n != NULL) { + *hostp = (u_32_t)htonl(n->n_net & 0xffffffff); + return 0; + } return -1; } diff --git a/usr/src/cmd/ipf/lib/common/getifname.c b/usr/src/cmd/ipf/lib/common/getifname.c index 39d193dcc6..a42a4e089b 100644 --- a/usr/src/cmd/ipf/lib/common/getifname.c +++ b/usr/src/cmd/ipf/lib/common/getifname.c @@ -1,6 +1,16 @@ +/* + * Copyright (C) 2003 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + #include "ipf.h" #include "qif.h" - #include "kmem.h" /* @@ -10,24 +20,34 @@ char *getifname(ptr) struct ifnet *ptr; { -#if SOLARIS +#if SOLARIS || defined(__hpux) +# if SOLARIS +# include <sys/mutex.h> +# include <sys/condvar.h> +# endif +# ifdef __hpux +# include "compat.h" +# endif char *ifname; - s_ill_t ill; + qif_t qif; if ((void *)ptr == (void *)-1) return "!"; if (ptr == NULL) return "-"; - if (kmemcpy((char *)&ill, (u_long)ptr, sizeof(ill)) == -1) + if (kmemcpy((char *)&qif, (u_long)ptr, sizeof(qif)) == -1) return "X"; - ifname = malloc(sizeof(ill.ill_name) + 1); - strncpy(ifname, ill.ill_name, sizeof(ill.ill_name)); - ifname[sizeof(ill.ill_name)] = '\0'; + ifname = strdup(qif.qf_name); + if ((ifname != NULL) && (*ifname == '\0')) { + free(ifname); + return "!"; + } return ifname; #else # if defined(NetBSD) && (NetBSD >= 199905) && (NetBSD < 1991011) || \ - defined(__OpenBSD__) + defined(__OpenBSD__) || \ + (defined(__FreeBSD__) && (__FreeBSD_version >= 501113)) #else char buf[32]; int len; @@ -42,7 +62,8 @@ struct ifnet *ptr; if (kmemcpy((char *)&netif, (u_long)ptr, sizeof(netif)) == -1) return "X"; # if defined(NetBSD) && (NetBSD >= 199905) && (NetBSD < 1991011) || \ - defined(__OpenBSD__) + defined(__OpenBSD__) || defined(linux) || \ + (defined(__FreeBSD__) && (__FreeBSD_version >= 501113)) return strdup(netif.if_xname); # else if (kstrncpy(buf, (u_long)netif.if_name, sizeof(buf)) == -1) diff --git a/usr/src/cmd/ipf/lib/common/getnattype.c b/usr/src/cmd/ipf/lib/common/getnattype.c index d3b32d2d77..312a862c3e 100644 --- a/usr/src/cmd/ipf/lib/common/getnattype.c +++ b/usr/src/cmd/ipf/lib/common/getnattype.c @@ -9,7 +9,7 @@ #include "kmem.h" #if !defined(lint) -static const char rcsid[] = "@(#)$Id: getnattype.c,v 1.2 2002/01/28 06:50:46 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id: getnattype.c,v 1.3 2004/01/17 17:26:07 darrenr Exp $"; #endif @@ -23,9 +23,10 @@ ipnat_t *ipnat; ipnat_t ipnatbuff; char *which; - if (!ipnat || (ipnat && kmemcpy((char *)&ipnatbuff, (long)ipnat, - sizeof(ipnatbuff)))) + if (!ipnat) return "???"; + if (kmemcpy((char *)&ipnatbuff, (long)ipnat, sizeof(ipnatbuff))) + return "!!!"; switch (ipnatbuff.in_redir) { diff --git a/usr/src/cmd/ipf/lib/common/getport.c b/usr/src/cmd/ipf/lib/common/getport.c index 9e77c665d3..415522ffc0 100644 --- a/usr/src/cmd/ipf/lib/common/getport.c +++ b/usr/src/cmd/ipf/lib/common/getport.c @@ -1,8 +1,14 @@ +/* + * Copyright (C) 1993-2005 by Darren Reed. + * See the IPFILTER.LICENCE file for details on licencing. + */ + #include "ipf.h" -int getport(fr, name) +int getport(fr, name, port) frentry_t *fr; char *name; +u_short *port; { struct protoent *p; struct servent *s; @@ -10,8 +16,10 @@ char *name; if (fr == NULL || fr->fr_type != FR_T_IPF) { s = getservbyname(name, NULL); - if (s != NULL) - return s->s_port; + if (s != NULL) { + *port = s->s_port; + return 0; + } return -1; } @@ -27,13 +35,15 @@ char *name; s = getservbyname(name, "udp"); if (s == NULL || s->s_port != p1) return -1; - return p1; + *port = p1; + return 0; } p = getprotobynumber(fr->fr_proto); s = getservbyname(name, p ? p->p_name : NULL); - if (s != NULL) - return s->s_port; - + if (s != NULL) { + *port = s->s_port; + return 0; + } return -1; } diff --git a/usr/src/cmd/ipf/lib/common/getportproto.c b/usr/src/cmd/ipf/lib/common/getportproto.c index 6237e39ab9..ae04229c67 100644 --- a/usr/src/cmd/ipf/lib/common/getportproto.c +++ b/usr/src/cmd/ipf/lib/common/getportproto.c @@ -1,3 +1,8 @@ +/* + * Copyright (C) 1993-2005 by Darren Reed. + * See the IPFILTER.LICENCE file for details on licencing. + */ + #include <ctype.h> #include "ipf.h" @@ -8,14 +13,23 @@ int proto; struct servent *s; struct protoent *p; - if (isdigit(*name) && atoi(name) > 0) - return htons(atoi(name) & 65535); + if (ISDIGIT(*name)) { + int number; + char *s; - p = getprotobynumber(proto); - if (p != NULL) { - s = getservbyname(name, p->p_name); - if (s != NULL) - return s->s_port; + for (s = name; *s != '\0'; s++) + if (!ISDIGIT(*s)) + return -1; + + number = atoi(name); + if (number < 0 || number > 65535) + return -1; + return htons(number); } - return 0; + + p = getprotobynumber(proto); + s = getservbyname(name, p ? p->p_name : NULL); + if (s != NULL) + return s->s_port; + return -1; } diff --git a/usr/src/cmd/ipf/lib/common/getproto.c b/usr/src/cmd/ipf/lib/common/getproto.c index 43a3029f47..472fe148ab 100644 --- a/usr/src/cmd/ipf/lib/common/getproto.c +++ b/usr/src/cmd/ipf/lib/common/getproto.c @@ -1,3 +1,8 @@ +/* + * Copyright (C) 1993-2005 by Darren Reed. + * See the IPFILTER.LICENCE file for details on licencing. + */ + #include "ipf.h" int getproto(name) @@ -7,11 +12,19 @@ char *name; char *s; for (s = name; *s != '\0'; s++) - if (!isdigit(*s)) + if (!ISDIGIT(*s)) break; if (*s == '\0') return atoi(name); +#ifdef _AIX51 + /* + * For some bogus reason, "ip" is 252 in /etc/protocols on AIX 5 + */ + if (!strcasecmp(name, "ip")) + return 0; +#endif + p = getprotobyname(name); if (p != NULL) return p->p_proto; diff --git a/usr/src/cmd/ipf/lib/common/hostname.c b/usr/src/cmd/ipf/lib/common/hostname.c index d0c8b490fe..4bca028c16 100644 --- a/usr/src/cmd/ipf/lib/common/hostname.c +++ b/usr/src/cmd/ipf/lib/common/hostname.c @@ -3,7 +3,7 @@ * * See the IPFILTER.LICENCE file for details on licencing. * - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -15,17 +15,43 @@ char *hostname(v, ip) int v; void *ip; { -#ifdef USE_INET6 - static char hostbuf[INET6_ADDRSTRLEN]; -#endif + static char hostbuf[MAXHOSTNAMELEN+1]; + struct hostent *hp; struct in_addr ipa; + struct netent *np; if (v == 4) { ipa.s_addr = *(u_32_t *)ip; + if (ipa.s_addr == htonl(0xfedcba98)) + return "test.host.dots"; + } + + if ((opts & OPT_NORESOLVE) == 0) { + if (v == 4) { + hp = gethostbyaddr(ip, 4, AF_INET); + if (hp != NULL && hp->h_name != NULL && + *hp->h_name != '\0') { + strncpy(hostbuf, hp->h_name, sizeof(hostbuf)); + hostbuf[sizeof(hostbuf) - 1] = '\0'; + return hostbuf; + } + + np = getnetbyaddr(ipa.s_addr, AF_INET); + if (np != NULL && np->n_name != NULL && + *np->n_name != '\0') { + strncpy(hostbuf, np->n_name, sizeof(hostbuf)); + hostbuf[sizeof(hostbuf) - 1] = '\0'; + return hostbuf; + } + } + } + + if (v == 4) { return inet_ntoa(ipa); } #ifdef USE_INET6 - (void) inet_ntop(AF_INET6, ip, hostbuf, sizeof(hostbuf)); + (void) inet_ntop(AF_INET6, ip, hostbuf, sizeof(hostbuf) - 1); + hostbuf[MAXHOSTNAMELEN] = '\0'; return hostbuf; #else return "IPv6"; diff --git a/usr/src/cmd/ipf/lib/common/hostnum.c b/usr/src/cmd/ipf/lib/common/hostnum.c index edef2997dd..2ec0529a29 100644 --- a/usr/src/cmd/ipf/lib/common/hostnum.c +++ b/usr/src/cmd/ipf/lib/common/hostnum.c @@ -3,7 +3,7 @@ * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: hostnum.c,v 1.8 2002/01/28 06:50:46 darrenr Exp $ + * $Id: hostnum.c,v 1.10.2.1 2004/12/09 19:41:20 darrenr Exp $ */ #include <ctype.h> @@ -21,13 +21,12 @@ char *host; int linenum; char *ifname; { - struct hostent *hp; - struct netent *np; struct in_addr ip; if (!strcasecmp("any", host) || (ifname && *ifname && !strcasecmp(ifname, host))) return 0; + #ifdef USE_INET6 if (use_inet6) { if (inet_pton(AF_INET6, host, ipa) == 1) @@ -36,7 +35,7 @@ char *ifname; return -1; } #endif - if (isdigit(*host) && inet_aton(host, &ip)) { + if (ISDIGIT(*host) && inet_aton(host, &ip)) { *ipa = ip.s_addr; return 0; } @@ -44,15 +43,5 @@ char *ifname; if (!strcasecmp("<thishost>", host)) host = thishost; - 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; + return gethost(host, ipa); } diff --git a/usr/src/cmd/ipf/lib/common/icmpcode.c b/usr/src/cmd/ipf/lib/common/icmpcode.c index 1dac556cec..fd1e647687 100644 --- a/usr/src/cmd/ipf/lib/common/icmpcode.c +++ b/usr/src/cmd/ipf/lib/common/icmpcode.c @@ -3,7 +3,7 @@ * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: icmpcode.c,v 1.6 2001/06/09 17:09:24 darrenr Exp $ + * $Id: icmpcode.c,v 1.7.2.1 2004/12/09 19:41:20 darrenr Exp $ */ #include <ctype.h> @@ -18,7 +18,7 @@ char *icmpcodes[MAX_ICMPCODE + 1] = { "net-unr", "host-unr", "proto-unr", "port-unr", "needfrag", "srcfail", "net-unk", "host-unk", "isolate", "net-prohib", "host-prohib", - "net-tos", "host-tos", "filter-prohib", "host-preced", "preced-cutoff", + "net-tos", "host-tos", "filter-prohib", "host-preced", "preced-cutoff", NULL }; /* @@ -32,7 +32,7 @@ char *str; if ((s = strrchr(str, ')'))) *s = '\0'; - if (isdigit(*str)) { + if (ISDIGIT(*str)) { if (!ratoi(str, &i, 0, 255)) return -1; else diff --git a/usr/src/cmd/ipf/lib/common/inet_addr.c b/usr/src/cmd/ipf/lib/common/inet_addr.c index 5c91169141..820b7b58a4 100644 --- a/usr/src/cmd/ipf/lib/common/inet_addr.c +++ b/usr/src/cmd/ipf/lib/common/inet_addr.c @@ -3,7 +3,7 @@ * - * Copyright (c) 1983, 1990, 1993 * The Regents of the University of California. All rights reserved. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -19,7 +19,7 @@ * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE @@ -33,14 +33,14 @@ * SUCH DAMAGE. * - * Portions Copyright (c) 1993 by Digital Equipment Corporation. - * + * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies, and that * the name of Digital Equipment Corporation not be used in advertising or * publicity pertaining to distribution of the document or software without * specific, written prior permission. - * + * * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT @@ -55,7 +55,7 @@ #if !defined(lint) static const char sccsid[] = "@(#)inet_addr.c 8.1 (Berkeley) 6/17/93"; -static const char rcsid[] = "@(#)$Id: inet_addr.c,v 1.4 2002/02/21 09:25:42 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id: inet_addr.c,v 1.8.2.3 2004/12/09 19:41:20 darrenr Exp $"; #endif /* LIBC_SCCS and not lint */ #include <sys/param.h> @@ -70,9 +70,24 @@ static const char rcsid[] = "@(#)$Id: inet_addr.c,v 1.4 2002/02/21 09:25:42 darr # define __P(x) () # endif #endif +#ifndef linux int inet_aton __P((const char *, struct in_addr *)); -/* +/* + * Because the ctype(3) posix definition, if used "safely" in code everywhere, + * would mean all normal code that walks through strings needed casts. Yuck. + */ +#define ISALNUM(x) isalnum((u_char)(x)) +#define ISALPHA(x) isalpha((u_char)(x)) +#define ISASCII(x) isascii((u_char)(x)) +#define ISDIGIT(x) isdigit((u_char)(x)) +#define ISPRINT(x) isprint((u_char)(x)) +#define ISSPACE(x) isspace((u_char)(x)) +#define ISUPPER(x) isupper((u_char)(x)) +#define ISXDIGIT(x) isxdigit((u_char)(x)) +#define ISLOWER(x) islower((u_char)(x)) + +/* * Check whether "cp" is a valid ascii representation * of an Internet address and convert to a binary address. * Returns 1 if the address is valid, 0 if not. @@ -97,7 +112,7 @@ inet_aton(cp, addr) * Values are specified as for C: * 0x=hex, 0=octal, isdigit=decimal. */ - if (!isdigit(c)) + if (!ISDIGIT(c)) return (0); val = 0; base = 10; if (c == '0') { @@ -108,12 +123,12 @@ inet_aton(cp, addr) base = 8; } for (;;) { - if (isascii(c) && isdigit(c)) { + if (ISASCII(c) && ISDIGIT(c)) { val = (val * base) + (c - '0'); c = *++cp; - } else if (base == 16 && isascii(c) && isxdigit(c)) { + } else if (base == 16 && ISASCII(c) && ISXDIGIT(c)) { val = (val << 4) | - (c + 10 - (islower(c) ? 'a' : 'A')); + (c + 10 - (ISLOWER(c) ? 'a' : 'A')); c = *++cp; } else break; @@ -135,7 +150,7 @@ inet_aton(cp, addr) /* * Check for trailing characters. */ - if (c != '\0' && (!isascii(c) || !isspace(c))) + if (c != '\0' && (!ISASCII(c) || !ISSPACE(c))) return (0); /* * Concoct the address according to @@ -172,6 +187,7 @@ inet_aton(cp, addr) addr->s_addr = htonl(val); return (1); } +#endif /* these are compatibility routines, not needed on recent BSD releases */ @@ -179,16 +195,9 @@ inet_aton(cp, addr) * Ascii internet address interpretation routine. * The value returned is in network order. */ -#if (defined(SOLARIS2) && (SOLARIS2 > 5)) || defined(__hpux) || \ - defined(__osf__) || (defined(IRIX) && (IRIX >= 605)) || \ - (defined(__FreeBSD__) && (__FreeBSD__ >= 4)) || \ - defined(__OpenBSD__) -in_addr_t -#else -u_long -#endif +#if 0 inet_addr(cp) - register const char *cp; + const char *cp; { struct in_addr val; @@ -196,3 +205,4 @@ inet_addr(cp) return (val.s_addr); return (0xffffffff); } +#endif diff --git a/usr/src/cmd/ipf/lib/common/ipf_dotuning.c b/usr/src/cmd/ipf/lib/common/ipf_dotuning.c new file mode 100644 index 0000000000..0746bd1e67 --- /dev/null +++ b/usr/src/cmd/ipf/lib/common/ipf_dotuning.c @@ -0,0 +1,67 @@ +/* + * Copyright (C) 1993-2005 by Darren Reed. + * See the IPFILTER.LICENCE file for details on licencing. + */ + +#include "ipf.h" +#include "netinet/ipl.h" +#include <sys/ioctl.h> + +void ipf_dotuning(fd, tuneargs, iocfn) +int fd; +char *tuneargs; +ioctlfunc_t iocfn; +{ + ipfobj_t obj; + ipftune_t tu; + char *s, *t; + + bzero((char *)&tu, sizeof(tu)); + obj.ipfo_rev = IPFILTER_VERSION; + obj.ipfo_size = sizeof(tu);; + obj.ipfo_ptr = (void *)&tu; + obj.ipfo_type = IPFOBJ_TUNEABLE; + + for (s = strtok(tuneargs, ","); s != NULL; s = strtok(NULL, ",")) { + if (!strcmp(s, "list")) { + while (1) { + if ((*iocfn)(fd, SIOCIPFGETNEXT, &obj) == -1) { + perror("ioctl(SIOCIPFGETNEXT)"); + break; + } + if (tu.ipft_cookie == NULL) + break; + + tu.ipft_name[sizeof(tu.ipft_name) - 1] = '\0'; + printtunable(&tu); + } + } else if ((t = strchr(s, '=')) != NULL) { + tu.ipft_cookie = NULL; + *t++ = '\0'; + strncpy(tu.ipft_name, s, sizeof(tu.ipft_name)); + if (sscanf(t, "%lu", &tu.ipft_vlong) == 1) { + if ((*iocfn)(fd, SIOCIPFSET, &obj) == -1) { + perror("ioctl(SIOCIPFSET)"); + return; + } + } else { + fprintf(stderr, "invalid value '%s'\n", s); + return; + } + } else { + tu.ipft_cookie = NULL; + strncpy(tu.ipft_name, s, sizeof(tu.ipft_name)); + if ((*iocfn)(fd, SIOCIPFGET, &obj) == -1) { + perror("ioctl(SIOCIPFGET)"); + return; + } + if (tu.ipft_cookie == NULL) { + fprintf(stderr, "Null cookie for %s\n", s); + return; + } + + tu.ipft_name[sizeof(tu.ipft_name) - 1] = '\0'; + printtunable(&tu); + } + } +} diff --git a/usr/src/cmd/ipf/lib/common/ipft_ef.c b/usr/src/cmd/ipf/lib/common/ipft_ef.c index 411dc51a91..237febcb4b 100644 --- a/usr/src/cmd/ipf/lib/common/ipft_ef.c +++ b/usr/src/cmd/ipf/lib/common/ipft_ef.c @@ -3,7 +3,7 @@ * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: ipft_ef.c,v 1.11 2003/06/02 12:22:49 darrenr Exp $ + * $Id: ipft_ef.c,v 1.14 2004/01/08 13:34:31 darrenr Exp $ */ /* @@ -23,16 +23,15 @@ etherfind -n -t #include "ipf.h" #include "ipt.h" -#undef ICMP_MAXTYPE -#include <netinet/ip_icmp.h> +#ifndef linux #include <netinet/ip_var.h> -#include <netinet/udp.h> +#endif #include <netinet/tcpip.h> #if !defined(lint) static const char sccsid[] = "@(#)ipft_ef.c 1.6 2/4/96 (C)1995 Darren Reed"; -static const char rcsid[] = "@(#)$Id: ipft_ef.c,v 1.11 2003/06/02 12:22:49 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id: ipft_ef.c,v 1.14 2004/01/08 13:34:31 darrenr Exp $"; #endif static int etherf_open __P((char *)); diff --git a/usr/src/cmd/ipf/lib/common/ipft_hx.c b/usr/src/cmd/ipf/lib/common/ipft_hx.c index 3a02700206..fa5923b756 100644 --- a/usr/src/cmd/ipf/lib/common/ipft_hx.c +++ b/usr/src/cmd/ipf/lib/common/ipft_hx.c @@ -5,7 +5,7 @@ */ #if !defined(lint) static const char sccsid[] = "@(#)ipft_hx.c 1.1 3/9/96 (C) 1996 Darren Reed"; -static const char rcsid[] = "@(#)$Id: ipft_hx.c,v 1.11 2003/02/16 02:32:35 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id: ipft_hx.c,v 1.11.4.1 2004/12/09 19:41:20 darrenr Exp $"; #endif #include <ctype.h> @@ -111,7 +111,7 @@ int cnt, *dir; if (t < (char *)ip) putchar('\t'); while (t < (char *)ip) { - if (isprint(*t) && isascii(*t)) + if (ISPRINT(*t) && ISASCII(*t)) putchar(*t); else putchar('.'); @@ -133,7 +133,7 @@ register char *src, *dst; char c; while ((c = *src++)) { - if (isspace(c)) { + if (ISSPACE(c)) { if (state) { dst++; state = 0; @@ -141,7 +141,7 @@ register char *src, *dst; continue; } else if ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F')) { - c = isdigit(c) ? (c - '0') : (toupper(c) - 55); + c = ISDIGIT(c) ? (c - '0') : (TOUPPER(c) - 55); if (state == 0) { *dst = (c << 4); state++; diff --git a/usr/src/cmd/ipf/lib/common/ipft_pc.c b/usr/src/cmd/ipf/lib/common/ipft_pc.c index 92b482bfaa..3042a3976c 100644 --- a/usr/src/cmd/ipf/lib/common/ipft_pc.c +++ b/usr/src/cmd/ipf/lib/common/ipft_pc.c @@ -3,7 +3,7 @@ * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: ipft_pc.c,v 1.9 2003/02/16 02:32:36 darrenr Exp $ + * $Id: ipft_pc.c,v 1.10 2004/02/07 18:17:40 darrenr Exp $ */ #include "ipf.h" #include "pcap-ipf.h" @@ -11,7 +11,7 @@ #include "ipt.h" #if !defined(lint) -static const char rcsid[] = "@(#)$Id: ipft_pc.c,v 1.9 2003/02/16 02:32:36 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id: ipft_pc.c,v 1.10 2004/02/07 18:17:40 darrenr Exp $"; #endif struct llc { @@ -75,7 +75,7 @@ static int pcap_readip __P((char *, int, char **, int *)); static void swap_hdr __P((pcaphdr_t *)); static int pcap_read_rec __P((struct pcap_pkthdr *)); -static int pfd = -1, s_type = -1, swapped = 0; +static int pfd = -1, swapped = 0; static struct llc *llcp = NULL; struct ipread pcap = { pcap_open, pcap_close, pcap_readip, 0 }; @@ -139,7 +139,6 @@ char *fname; } pfd = fd; - s_type = ph.pc_type; printf("opened pcap file %s:\n", fname); printf("\tid: %08x version: %d.%d type: %d snap %d\n", ph.pc_id, ph.pc_v_maj, ph.pc_v_min, ph.pc_type, ph.pc_slen); diff --git a/usr/src/cmd/ipf/lib/common/ipft_td.c b/usr/src/cmd/ipf/lib/common/ipft_td.c index acc3631e46..1aa616670a 100644 --- a/usr/src/cmd/ipf/lib/common/ipft_td.c +++ b/usr/src/cmd/ipf/lib/common/ipft_td.c @@ -3,7 +3,7 @@ * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: ipft_td.c,v 1.11 2003/06/03 16:01:01 darrenr Exp $ + * $Id: ipft_td.c,v 1.15 2004/01/08 13:34:31 darrenr Exp $ */ /* @@ -32,16 +32,15 @@ tcpdump -nqte #include "ipf.h" #include "ipt.h" -#undef ICMP_MAXTYPE -#include <netinet/ip_icmp.h> +#ifndef linux #include <netinet/ip_var.h> -#include <netinet/udp.h> +#endif #include <netinet/tcpip.h> #if !defined(lint) static const char sccsid[] = "@(#)ipft_td.c 1.8 2/4/96 (C)1995 Darren Reed"; -static const char rcsid[] = "@(#)$Id: ipft_td.c,v 1.11 2003/06/03 16:01:01 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id: ipft_td.c,v 1.15 2004/01/08 13:34:31 darrenr Exp $"; #endif static int tcpd_open __P((char *)); @@ -97,7 +96,6 @@ int cnt, *dir; { struct tcpiphdr pkt; ip_t *ip = (ip_t *)&pkt; - struct protoent *p; char src[32], dst[32], misc[256], time[32], link1[32], link2[32]; char lbuf[160], *s; int n, slen, extra = 0; diff --git a/usr/src/cmd/ipf/lib/common/ipft_tx.c b/usr/src/cmd/ipf/lib/common/ipft_tx.c index 3d0f5800ce..82eca169d8 100644 --- a/usr/src/cmd/ipf/lib/common/ipft_tx.c +++ b/usr/src/cmd/ipf/lib/common/ipft_tx.c @@ -3,11 +3,11 @@ * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: ipft_tx.c,v 1.11 2003/02/16 02:32:01 darrenr Exp $ + * $Id: ipft_tx.c,v 1.15.2.3 2005/06/18 02:41:34 darrenr Exp $ */ #if !defined(lint) static const char sccsid[] = "@(#)ipft_tx.c 1.7 6/5/96 (C) 1993 Darren Reed"; -static const char rcsid[] = "@(#)$Id: ipft_tx.c,v 1.11 2003/02/16 02:32:01 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id: ipft_tx.c,v 1.15.2.3 2005/06/18 02:41:34 darrenr Exp $"; #endif #include <ctype.h> @@ -15,10 +15,9 @@ static const char rcsid[] = "@(#)$Id: ipft_tx.c,v 1.11 2003/02/16 02:32:01 darre #include "ipf.h" #include "ipt.h" -#undef ICMP_MAXTYPE -#include <netinet/ip_icmp.h> +#ifndef linux #include <netinet/ip_var.h> -#include <netinet/udp.h> +#endif #include <netinet/tcpip.h> @@ -30,8 +29,8 @@ static int text_open __P((char *)), text_close __P((void)); static int text_readip __P((char *, int, char **, int *)); static int parseline __P((char *, ip_t *, char **, int *)); -static char _tcp_flagset[] = "FSRPAUEC"; -static u_char _tcp_flags[] = { TH_FIN, TH_SYN, TH_RST, TH_PUSH, +static char myflagset[] = "FSRPAUEC"; +static u_char myflags[] = { TH_FIN, TH_SYN, TH_RST, TH_PUSH, TH_ACK, TH_URG, TH_ECN, TH_CWR }; struct ipread iptext = { text_open, text_close, text_readip, R_DO_CKSUM }; @@ -50,24 +49,20 @@ static u_32_t tx_hostnum(host, resolved) char *host; int *resolved; { - struct hostent *hp; - struct netent *np; + u_32_t ipa; *resolved = 0; - if (!strcasecmp("any",host)) + if (!strcasecmp("any", host)) return 0L; - if (isdigit(*host)) + if (ISDIGIT(*host)) return inet_addr(host); - if (!(hp = gethostbyname(host))) { - if (!(np = getnetbyname(host))) { - *resolved = -1; - fprintf(stderr, "can't resolve hostname: %s\n", host); - return 0; - } - return htonl(np->n_net); + if (gethost(host, &ipa) == -1) { + *resolved = -1; + fprintf(stderr, "can't resolve hostname: %s\n", host); + return 0; } - return *(u_32_t *)hp->h_addr; + return ipa; } @@ -81,7 +76,7 @@ char *name; struct servent *sp, *sp2; u_short p1 = 0; - if (isdigit(*name)) + if (ISDIGIT(*name)) return (u_short)atoi(name); if (!tx_proto) tx_proto = "tcp/udp"; @@ -205,11 +200,11 @@ int *out; return 1; c = **cpp; - if (!isalpha(c) || (tolower(c) != 'o' && tolower(c) != 'i')) { + if (!ISALPHA(c) || (TOLOWER(c) != 'o' && TOLOWER(c) != 'i')) { fprintf(stderr, "bad direction \"%s\"\n", *cpp); return 1; } - *out = (tolower(c) == 'o') ? 1 : 0; + *out = (TOLOWER(c) == 'o') ? 1 : 0; cpp++; if (!*cpp) return 1; @@ -241,7 +236,7 @@ int *out; tx_proto = "icmp"; } cpp++; - } else if (isdigit(**cpp) && !index(*cpp, '.')) { + } else if (ISDIGIT(**cpp) && !index(*cpp, '.')) { ip->ip_p = atoi(*cpp); cpp++; } else @@ -259,6 +254,10 @@ int *out; } *last++ = '\0'; tcp->th_sport = htons(tx_portnum(last)); + if (ip->ip_p == IPPROTO_TCP) { + tcp->th_win = htons(4096); + TCP_OFF_A(tcp, sizeof(*tcp) >> 2); + } } ip->ip_src.s_addr = tx_hostnum(*cpp, &r); cpp++; @@ -279,19 +278,18 @@ int *out; ip->ip_dst.s_addr = tx_hostnum(*cpp, &r); cpp++; if (*cpp && ip->ip_p == IPPROTO_TCP) { - extern char _tcp_flagset[]; - extern u_char _tcp_flags[]; char *s, *t; + tcp->th_flags = 0; for (s = *cpp; *s; s++) - if ((t = strchr(_tcp_flagset, *s))) - tcp->th_flags |= _tcp_flags[t - _tcp_flagset]; + if ((t = strchr(myflagset, *s))) + tcp->th_flags |= myflags[t - myflagset]; if (tcp->th_flags) cpp++; if (tcp->th_flags == 0) abort(); - tcp->th_win = htons(4096); - TCP_OFF_A(tcp, sizeof(*tcp) >> 2); + if (tcp->th_flags & TH_URG) + tcp->th_urp = htons(1); } else if (*cpp && ip->ip_p == IPPROTO_ICMP) { extern char *tx_icmptypes[]; char **s, *t; diff --git a/usr/src/cmd/ipf/lib/common/kmem.c b/usr/src/cmd/ipf/lib/common/kmem.c index a90b897cf7..3142d68011 100644 --- a/usr/src/cmd/ipf/lib/common/kmem.c +++ b/usr/src/cmd/ipf/lib/common/kmem.c @@ -9,7 +9,7 @@ */ /* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -23,7 +23,7 @@ #include <string.h> #include <fcntl.h> #include <sys/file.h> -#if !defined(__sgi) && !defined(__hpux) && !defined(__osf__) +#if !defined(__sgi) && !defined(__hpux) && !defined(__osf__) && !defined(linux) && !defined(_AIX51) #include <kvm.h> #endif #include <fcntl.h> @@ -37,6 +37,9 @@ #if __FreeBSD_version >= 300000 # include <net/if_var.h> #endif +#if defined(linux) || defined(__osf__) || defined(__sgi) || defined(__hpux) +# include <stdlib.h> +#endif #include "kmem.h" @@ -46,12 +49,13 @@ #if !defined(lint) static const char sccsid[] = "@(#)kmem.c 1.4 1/12/96 (C) 1992 Darren Reed"; -static const char rcsid[] = "@(#)$Id: kmem.c,v 1.11 2003/06/02 12:22:29 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id: kmem.c,v 1.16.2.2 2005/06/12 07:18:41 darrenr Exp $"; #endif -#if !defined(__sgi) && !defined(__hpux) && !defined(__osf__) +#if !defined(__sgi) && !defined(__hpux) && !defined(__osf__) && \ + !defined(linux) && !defined(_AIX51) /* * For all platforms where there is a libkvm and a kvm_t, we use that... */ @@ -62,17 +66,21 @@ static kvm_t *kvm_f = NULL; *...and for the others (HP-UX, IRIX, Tru64), we have to provide our own. */ -typedef int kvm_t; +typedef int * kvm_t; -static kvm_t kvm_f = -1; +static kvm_t kvm_f = NULL; static char *kvm_errstr = NULL; +kvm_t kvm_open __P((char *, char *, char *, int, char *)); +int kvm_read __P((kvm_t, u_long, char *, size_t)); + kvm_t kvm_open(kernel, core, swap, mode, errstr) char *kernel, *core, *swap; int mode; char *errstr; { - kvm_t fd; + kvm_t k; + int fd; kvm_errstr = errstr; @@ -80,7 +88,15 @@ char *errstr; core = "/dev/kmem"; fd = open(core, mode); - return fd; + if (fd == -1) + return NULL; + k = malloc(sizeof(*k)); + if (k == NULL) { + close(fd); + return NULL; + } + *k = fd; + return k; } int kvm_read(kvm, pos, buffer, size) @@ -89,10 +105,10 @@ u_long pos; char *buffer; size_t size; { - int r, left; + int r = 0, left; char *bufp; - if (lseek(kvm, pos, 0) == -1) { + if (lseek(*kvm, pos, 0) == -1) { if (kvm_errstr != NULL) { fprintf(stderr, "%s", kvm_errstr); perror("lseek"); @@ -101,19 +117,19 @@ size_t size; } for (bufp = buffer, left = size; left > 0; bufp += r, left -= r) { - r = read(kvm, bufp, 1); + r = read(*kvm, bufp, left); #ifdef __osf__ /* * Tru64 returns "0" for successful operation, not the number * of bytes read. */ - return r; -#else + if (r == 0) + r = left; +#endif if (r <= 0) return -1; -#endif } - return 0; + return r; } #endif /* !defined(__sgi) && !defined(__hpux) && !defined(__osf__) */ @@ -126,7 +142,7 @@ char *kern, *core; perror("openkmem:open"); return -1; } - return 0; + return kvm_f != NULL; } int kmemcpy(buf, pos, n) @@ -179,7 +195,7 @@ register int n; if (r <= 0) { fprintf(stderr, "pos=0x%lx ", (u_long)pos); - perror("kstrncpy:read"); + perror("kmemcpy:read"); return -1; } else diff --git a/usr/src/cmd/ipf/lib/common/load_hash.c b/usr/src/cmd/ipf/lib/common/load_hash.c index a86052478e..e43ddf54a3 100644 --- a/usr/src/cmd/ipf/lib/common/load_hash.c +++ b/usr/src/cmd/ipf/lib/common/load_hash.c @@ -3,9 +3,9 @@ * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: load_hash.c,v 1.10 2003/04/26 04:55:11 darrenr Exp $ + * $Id: load_hash.c,v 1.11.2.2 2005/02/01 02:44:05 darrenr Exp $ * - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -14,13 +14,8 @@ #include <fcntl.h> #include <sys/ioctl.h> #include "ipf.h" -#if SOLARIS2 >= 10 -#include "ip_lookup.h" -#include "ip_htable.h" -#else #include "netinet/ip_lookup.h" #include "netinet/ip_htable.h" -#endif static int hashfd = -1; @@ -40,8 +35,6 @@ ioctlfunc_t iocfunc; hashfd = open(IPLOOKUP_NAME, O_RDWR); if ((hashfd == -1) && ((opts & OPT_DONOTHING) == 0)) return -1; - if (list == NULL) - return 0; for (n = 0, a = list; a != NULL; a = a->ipe_next) n++; @@ -58,20 +51,29 @@ ioctlfunc_t iocfunc; iph.iph_type = iphp->iph_type; strncpy(iph.iph_name, iphp->iph_name, sizeof(iph.iph_name)); iph.iph_flags = iphp->iph_flags; + if (n <= 0) + n = 1; if (iphp->iph_size == 0) size = n * 2 - 1; else size = iphp->iph_size; + if ((list == NULL) && (size == 1)) { + fprintf(stderr, + "WARNING: empty hash table %s, recommend setting %s\n", + iphp->iph_name, "size to match expected use"); + } iph.iph_size = size; iph.iph_seed = iphp->iph_seed; iph.iph_table = NULL; iph.iph_ref = 0; - if ((*iocfunc)(hashfd, SIOCLOOKUPADDTABLE, &op)) - if ((opts & OPT_DONOTHING) == 0) { - perror("load_hash:SIOCLOOKUPADDTABLE"); - return -1; - } + if ((opts & OPT_REMOVE) == 0) { + if ((*iocfunc)(hashfd, SIOCLOOKUPADDTABLE, &op)) + if ((opts & OPT_DONOTHING) == 0) { + perror("load_hash:SIOCLOOKUPADDTABLE"); + return -1; + } + } strncpy(op.iplo_name, iph.iph_name, sizeof(op.iplo_name)); strncpy(iphp->iph_name, iph.iph_name, sizeof(op.iplo_name)); @@ -89,7 +91,7 @@ ioctlfunc_t iocfunc; return -1; } iph.iph_table[0] = list; - printhash(&iph, bcopywrap, opts); + printhash(&iph, bcopywrap, iph.iph_name, opts); free(iph.iph_table); for (a = list; a != NULL; a = a->ipe_next) { @@ -106,5 +108,12 @@ ioctlfunc_t iocfunc; for (a = list; a != NULL; a = a->ipe_next) load_hashnode(iphp->iph_unit, iph.iph_name, a, iocfunc); + if ((opts & OPT_REMOVE) != 0) { + if ((*iocfunc)(hashfd, SIOCLOOKUPDELTABLE, &op)) + if ((opts & OPT_DONOTHING) == 0) { + perror("load_hash:SIOCLOOKUPDELTABLE"); + return -1; + } + } return 0; } diff --git a/usr/src/cmd/ipf/lib/common/load_hashnode.c b/usr/src/cmd/ipf/lib/common/load_hashnode.c index c072031abc..8cf1bb2c67 100644 --- a/usr/src/cmd/ipf/lib/common/load_hashnode.c +++ b/usr/src/cmd/ipf/lib/common/load_hashnode.c @@ -3,9 +3,9 @@ * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: load_hashnode.c,v 1.2 2003/04/26 04:55:11 darrenr Exp $ + * $Id: load_hashnode.c,v 1.2.4.1 2004/03/06 14:33:28 darrenr Exp $ * - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -14,14 +14,8 @@ #include <fcntl.h> #include <sys/ioctl.h> #include "ipf.h" - -#if SOLARIS2 >= 10 -#include "ip_lookup.h" -#include "ip_htable.h" -#else #include "netinet/ip_lookup.h" #include "netinet/ip_htable.h" -#endif static int hashfd = -1; @@ -34,6 +28,7 @@ ioctlfunc_t iocfunc; { iplookupop_t op; iphtent_t ipe; + int err; if ((hashfd == -1) && ((opts & OPT_DONOTHING) == 0)) hashfd = open(IPLOOKUP_NAME, O_RDWR); @@ -56,9 +51,14 @@ ioctlfunc_t iocfunc; bcopy((char *)&node->ipe_group, (char *)&ipe.ipe_group, sizeof(ipe.ipe_group)); - if ((*iocfunc)(hashfd, SIOCLOOKUPADDNODE, &op)) + if ((opts & OPT_REMOVE) == 0) + err = (*iocfunc)(hashfd, SIOCLOOKUPADDNODE, &op); + else + err = (*iocfunc)(hashfd, SIOCLOOKUPDELNODE, &op); + + if (err != 0) if (!(opts & OPT_DONOTHING)) { - perror("load_hash:SIOCLOOKUPADDNODE"); + perror("load_hash:SIOCLOOKUP*NODE"); return -1; } return 0; diff --git a/usr/src/cmd/ipf/lib/common/load_pool.c b/usr/src/cmd/ipf/lib/common/load_pool.c index e87db99119..d27b6c381b 100644 --- a/usr/src/cmd/ipf/lib/common/load_pool.c +++ b/usr/src/cmd/ipf/lib/common/load_pool.c @@ -3,19 +3,14 @@ * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: load_pool.c,v 1.12 2003/04/26 04:55:11 darrenr Exp $ + * $Id: load_pool.c,v 1.14.2.2 2005/02/01 02:44:06 darrenr Exp $ */ #include <fcntl.h> #include <sys/ioctl.h> #include "ipf.h" -#if SOLARIS2 >= 10 -#include "ip_lookup.h" -#include "ip_pool.h" -#else #include "netinet/ip_lookup.h" #include "netinet/ip_pool.h" -#endif static int poolfd = -1; @@ -44,20 +39,29 @@ ioctlfunc_t iocfunc; if (*plp->ipo_name == '\0') op.iplo_arg |= IPOOL_ANON; - if ((*iocfunc)(poolfd, SIOCLOOKUPADDTABLE, &op)) - if ((opts & OPT_DONOTHING) == 0) { - perror("load_pool:SIOCLOOKUPADDTABLE"); - return -1; - } + if ((opts & OPT_REMOVE) == 0) { + if ((*iocfunc)(poolfd, SIOCLOOKUPADDTABLE, &op)) + if ((opts & OPT_DONOTHING) == 0) { + perror("load_pool:SIOCLOOKUPADDTABLE"); + return -1; + } + } if ((opts & OPT_VERBOSE) != 0) { pool.ipo_list = plp->ipo_list; - printpool(&pool, bcopywrap, opts); + printpool(&pool, bcopywrap, pool.ipo_name, opts); pool.ipo_list = NULL; } for (a = plp->ipo_list; a != NULL; a = a->ipn_next) load_poolnode(plp->ipo_unit, plp->ipo_name, a, iocfunc); + if ((opts & OPT_REMOVE) != 0) { + if ((*iocfunc)(poolfd, SIOCLOOKUPDELTABLE, &op)) + if ((opts & OPT_DONOTHING) == 0) { + perror("load_pool:SIOCLOOKUPDELTABLE"); + return -1; + } + } return 0; } diff --git a/usr/src/cmd/ipf/lib/common/load_poolnode.c b/usr/src/cmd/ipf/lib/common/load_poolnode.c index 50c06b538d..e992a80281 100644 --- a/usr/src/cmd/ipf/lib/common/load_poolnode.c +++ b/usr/src/cmd/ipf/lib/common/load_poolnode.c @@ -3,20 +3,14 @@ * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: load_poolnode.c,v 1.2 2003/04/26 04:55:11 darrenr Exp $ + * $Id: load_poolnode.c,v 1.3.2.1 2004/03/06 14:33:29 darrenr Exp $ */ #include <fcntl.h> #include <sys/ioctl.h> #include "ipf.h" - -#if SOLARIS2 >= 10 -#include "ip_lookup.h" -#include "ip_pool.h" -#else #include "netinet/ip_lookup.h" #include "netinet/ip_pool.h" -#endif static int poolfd = -1; @@ -29,6 +23,7 @@ ioctlfunc_t iocfunc; { ip_pool_node_t pn; iplookupop_t op; + int err; if ((poolfd == -1) && ((opts & OPT_DONOTHING) == 0)) poolfd = open(IPLOOKUP_NAME, O_RDWR); @@ -50,9 +45,14 @@ ioctlfunc_t iocfunc; pn.ipn_info = node->ipn_info; strncpy(pn.ipn_name, node->ipn_name, sizeof(pn.ipn_name)); - if ((*iocfunc)(poolfd, SIOCLOOKUPADDNODE, &op)) { + if ((opts & OPT_REMOVE) == 0) + err = (*iocfunc)(poolfd, SIOCLOOKUPADDNODE, &op); + else + err = (*iocfunc)(poolfd, SIOCLOOKUPDELNODE, &op); + + if (err != 0) { if ((opts & OPT_DONOTHING) == 0) { - perror("load_pool:SIOCLOOKUPADDNODE"); + perror("load_pool:SIOCLOOKUP*NODE"); return -1; } } diff --git a/usr/src/cmd/ipf/lib/common/natparse.c b/usr/src/cmd/ipf/lib/common/natparse.c index b6dd7318a5..9937380f35 100644 --- a/usr/src/cmd/ipf/lib/common/natparse.c +++ b/usr/src/cmd/ipf/lib/common/natparse.c @@ -5,7 +5,7 @@ */ #if !defined(lint) static const char sccsid[] ="@(#)ipnat.c 1.9 6/5/96 (C) 1993 Darren Reed"; -static const char rcsid[] = "@(#)$Id: natparse.c,v 1.6 2002/11/09 14:08:04 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id: natparse.c,v 1.8.2.1 2004/12/09 19:41:21 darrenr Exp $"; #endif #include <sys/ioctl.h> @@ -55,7 +55,7 @@ int linenum; *s = '\0'; if ((s = strchr(line, '#'))) *s = '\0'; - while (*line && isspace(*line)) + while (*line && ISSPACE(*line)) line++; if (!*line) return NULL; @@ -223,7 +223,7 @@ int linenum; return NULL; } - if (isdigit(**cpp) && (s = strchr(*cpp, '-'))) + if (ISDIGIT(**cpp) && (s = strchr(*cpp, '-'))) *s++ = '\0'; else s = NULL; @@ -357,7 +357,7 @@ int linenum; return NULL; ipn.in_pnext = htons(ipn.in_pnext); cpp++; - } + } if (dnetm && *dnetm == '/') *dnetm++ = '\0'; @@ -559,7 +559,7 @@ int linenum; } *t++ = '\0'; - if (!icmpidnum(*cpp, &ipn.in_pmin, linenum) || + if (!icmpidnum(*cpp, &ipn.in_pmin, linenum) || !icmpidnum(t, &ipn.in_pmax, linenum)) return NULL; } else if (!strcasecmp(*cpp, "portmap")) { diff --git a/usr/src/cmd/ipf/lib/common/portname.c b/usr/src/cmd/ipf/lib/common/portname.c index 7e9586ee47..7136d8c017 100644 --- a/usr/src/cmd/ipf/lib/common/portname.c +++ b/usr/src/cmd/ipf/lib/common/portname.c @@ -3,7 +3,7 @@ * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: portname.c,v 1.6 2002/01/28 06:50:47 darrenr Exp $ + * $Id: portname.c,v 1.7 2003/08/14 14:27:43 darrenr Exp $ */ #include "ipf.h" @@ -15,21 +15,23 @@ int pr, port; 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 != -2) && (p = getprotobynumber(pr))) { - if ((sv = getservbyport(htons(port), p->p_name))) { - strncpy(buf, sv->s_name, sizeof(buf)-1); - buf[sizeof(buf)-1] = '\0'; - return buf; + if ((opts & OPT_NORESOLVE) == 0) { + if (pr == -1) { + if ((sv = getservbyport(htons(port), "tcp"))) { + strncpy(buf, sv->s_name, sizeof(buf)-1); + buf[sizeof(buf)-1] = '\0'; + sv1 = getservbyport(htons(port), "udp"); + sv = strncasecmp(buf, sv->s_name, strlen(buf)) ? + NULL : sv1; + } + if (sv) + return buf; + } else if ((pr != -2) && (p = getprotobynumber(pr))) { + if ((sv = getservbyport(htons(port), p->p_name))) { + strncpy(buf, sv->s_name, sizeof(buf)-1); + buf[sizeof(buf)-1] = '\0'; + return buf; + } } } diff --git a/usr/src/cmd/ipf/lib/common/portnum.c b/usr/src/cmd/ipf/lib/common/portnum.c index 07556337c8..4079f464c2 100644 --- a/usr/src/cmd/ipf/lib/common/portnum.c +++ b/usr/src/cmd/ipf/lib/common/portnum.c @@ -4,7 +4,7 @@ * See the IPFILTER.LICENCE file for details on licencing. * * - * $Id: portnum.c,v 1.6 2001/06/09 17:09:24 darrenr Exp $ + * $Id: portnum.c,v 1.6.4.1 2004/12/09 19:41:22 darrenr Exp $ */ #include <ctype.h> @@ -25,7 +25,7 @@ int linenum; u_short p1 = 0; int i; - if (isdigit(*name)) { + if (ISDIGIT(*name)) { if (ratoi(name, &i, 0, USHRT_MAX)) { *port = (u_short)i; return 1; diff --git a/usr/src/cmd/ipf/lib/common/ports.c b/usr/src/cmd/ipf/lib/common/ports.c index 1c56f6e9ca..9a44e2c06a 100644 --- a/usr/src/cmd/ipf/lib/common/ports.c +++ b/usr/src/cmd/ipf/lib/common/ports.c @@ -3,7 +3,7 @@ * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: ports.c,v 1.9 2002/01/28 06:50:47 darrenr Exp $ + * $Id: ports.c,v 1.9.4.1 2004/12/09 19:41:22 darrenr Exp $ */ #include <ctype.h> @@ -28,7 +28,7 @@ int linenum; return 0; if (!strcasecmp(**seg, "port") && *(*seg + 1) && *(*seg + 2)) { (*seg)++; - if (isalnum(***seg) && *(*seg + 2)) { + if (ISALNUM(***seg) && *(*seg + 2)) { if (portnum(**seg, proto, pp, linenum) == 0) return -1; (*seg)++; diff --git a/usr/src/cmd/ipf/lib/common/print_toif.c b/usr/src/cmd/ipf/lib/common/print_toif.c index 81524396d2..fc57a302e8 100644 --- a/usr/src/cmd/ipf/lib/common/print_toif.c +++ b/usr/src/cmd/ipf/lib/common/print_toif.c @@ -5,7 +5,7 @@ * * $Id: print_toif.c,v 1.8 2002/01/28 06:50:47 darrenr Exp $ * - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -28,7 +28,7 @@ frdest_t *fdp; char ipv6addr[INET6_ADDRSTRLEN]; inet_ntop(AF_INET6, &fdp->fd_ip6, ipv6addr, - sizeof(ipv6addr)); + sizeof(fdp->fd_ip6)); printf(":%s", ipv6addr); } else #endif diff --git a/usr/src/cmd/ipf/lib/common/printactivenat.c b/usr/src/cmd/ipf/lib/common/printactivenat.c new file mode 100644 index 0000000000..389818b67b --- /dev/null +++ b/usr/src/cmd/ipf/lib/common/printactivenat.c @@ -0,0 +1,83 @@ +/* + * Copyright (C) 1993-2001 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * Added redirect stuff and a variety of bug fixes. (mcn@EnGarde.com) + */ + +#include "ipf.h" + + +#if !defined(lint) +static const char rcsid[] = "@(#)$Id: printactivenat.c,v 1.3.2.4 2004/05/11 16:07:32 darrenr Exp $"; +#endif + + +void printactivenat(nat, opts) +nat_t *nat; +int opts; +{ + + printf("%s", getnattype(nat->nat_ptr)); + + if (nat->nat_flags & SI_CLONE) + printf(" CLONE"); + + printf(" %-15s", inet_ntoa(nat->nat_inip)); + + if ((nat->nat_flags & IPN_TCPUDP) != 0) + printf(" %-5hu", ntohs(nat->nat_inport)); + + printf(" <- -> %-15s",inet_ntoa(nat->nat_outip)); + + if ((nat->nat_flags & IPN_TCPUDP) != 0) + printf(" %-5hu", ntohs(nat->nat_outport)); + + printf(" [%s", inet_ntoa(nat->nat_oip)); + if ((nat->nat_flags & IPN_TCPUDP) != 0) + printf(" %hu", ntohs(nat->nat_oport)); + printf("]"); + + if (opts & OPT_VERBOSE) { + printf("\n\tage %lu use %hu sumd %s/", + nat->nat_age, nat->nat_use, getsumd(nat->nat_sumd[0])); + printf("%s pr %u bkt %d/%d flags %x\n", + getsumd(nat->nat_sumd[1]), nat->nat_p, + nat->nat_hv[0], nat->nat_hv[1], nat->nat_flags); + printf("\tifp %s", getifname(nat->nat_ifps[0])); + printf(",%s ", getifname(nat->nat_ifps[1])); +#ifdef USE_QUAD_T + printf("bytes %qu/%qu pkts %qu/%qu", + (unsigned long long)nat->nat_bytes[0], + (unsigned long long)nat->nat_bytes[1], + (unsigned long long)nat->nat_pkts[0], + (unsigned long long)nat->nat_pkts[1]); +#else + printf("bytes %lu/%lu pkts %lu/%lu", nat->nat_bytes[0], + nat->nat_bytes[1], nat->nat_pkts[0], nat->nat_pkts[1]); +#endif + printf(" ipsumd %x", nat->nat_ipsumd); + } + + if (opts & OPT_DEBUG) { + printf("\n\tnat_next %p _pnext %p _hm %p\n", + nat->nat_next, nat->nat_pnext, nat->nat_hm); + printf("\t_hnext %p/%p _phnext %p/%p\n", + nat->nat_hnext[0], nat->nat_hnext[1], + nat->nat_phnext[0], nat->nat_phnext[1]); + printf("\t_data %p _me %p _state %p _aps %p\n", + nat->nat_data, nat->nat_me, nat->nat_state, nat->nat_aps); + printf("\tfr %p ptr %p ifps %p/%p sync %p\n", + nat->nat_fr, nat->nat_ptr, nat->nat_ifps[0], + nat->nat_ifps[1], nat->nat_sync); + printf("\ttqe:pnext %p next %p ifq %p parent %p/%p\n", + nat->nat_tqe.tqe_pnext, nat->nat_tqe.tqe_next, + nat->nat_tqe.tqe_ifq, nat->nat_tqe.tqe_parent, nat); + printf("\ttqe:die %ld touched %ld flags %x state %d/%d\n", + nat->nat_tqe.tqe_die, nat->nat_tqe.tqe_touched, + nat->nat_tqe.tqe_flags, nat->nat_tqe.tqe_state[0], + nat->nat_tqe.tqe_state[1]); + } + putchar('\n'); +} diff --git a/usr/src/cmd/ipf/lib/common/printaps.c b/usr/src/cmd/ipf/lib/common/printaps.c index 437fc03ae9..45b4b2f6ad 100644 --- a/usr/src/cmd/ipf/lib/common/printaps.c +++ b/usr/src/cmd/ipf/lib/common/printaps.c @@ -11,7 +11,7 @@ #if !defined(lint) -static const char rcsid[] = "@(#)$Id"; +static const char rcsid[] = "@(#)$Id: printaps.c,v 1.4 2004/01/08 13:34:32 darrenr Exp $"; #endif diff --git a/usr/src/cmd/ipf/lib/common/printbuf.c b/usr/src/cmd/ipf/lib/common/printbuf.c index dae0e541a0..613293ae19 100644 --- a/usr/src/cmd/ipf/lib/common/printbuf.c +++ b/usr/src/cmd/ipf/lib/common/printbuf.c @@ -3,7 +3,7 @@ * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: printbuf.c,v 1.5 2001/06/09 17:09:24 darrenr Exp $ + * $Id: printbuf.c,v 1.5.4.1 2004/12/09 19:41:22 darrenr Exp $ */ #include <ctype.h> @@ -20,7 +20,7 @@ int len, zend; for (s = buf, i = len; i; i--) { c = *s++; - if (isprint(c)) + if (ISPRINT(c)) putchar(c); else printf("\\%03o", c); diff --git a/usr/src/cmd/ipf/lib/common/printfr.c b/usr/src/cmd/ipf/lib/common/printfr.c index fc7a3a1a8e..d7bd3f2bbf 100644 --- a/usr/src/cmd/ipf/lib/common/printfr.c +++ b/usr/src/cmd/ipf/lib/common/printfr.c @@ -3,9 +3,9 @@ * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: printfr.c,v 1.37 2003/06/03 16:01:12 darrenr Exp $ + * $Id: printfr.c,v 1.43.2.12 2005/06/12 07:18:42 darrenr Exp $ * - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -13,6 +13,60 @@ #include "ipf.h" +static void printaddr(int, int, char *, u_32_t *, u_32_t *); + +static void printaddr(v, type, ifname, addr, mask) +int v, type; +char *ifname; +u_32_t *addr, *mask; +{ + char *suffix; + + switch (type) + { + case FRI_BROADCAST : + suffix = "/bcast"; + break; + + case FRI_DYNAMIC : + printf("%s", ifname); + printmask(v, mask); + suffix = NULL; + break; + + case FRI_NETWORK : + suffix = "/net"; + break; + + case FRI_NETMASKED : + suffix = "/netmasked"; + break; + + case FRI_PEERADDR : + suffix = "/peer"; + break; + + case FRI_LOOKUP : + suffix = NULL; + printlookup((i6addr_t *)addr, (i6addr_t *)mask); + break; + + case FRI_NORMAL : + printhostmask(v, addr, mask); + suffix = NULL; + break; + default : + printf("<%d>", type); + printmask(v, mask); + suffix = NULL; + break; + } + + if (suffix != NULL) { + printf("%s/%s", ifname, suffix); + } +} + void printlookup(addr, mask) i6addr_t *addr, *mask; @@ -59,6 +113,9 @@ ioctlfunc_t iocfunc; if ((fp->fr_type & FR_T_BUILTIN) != 0) printf("# Builtin: "); + if (fp->fr_collect != 0) + printf("%u ", fp->fr_collect); + if (fp->fr_type == FR_T_CALLFUNC) { ; } else if (fp->fr_func != NULL) { @@ -120,30 +177,32 @@ ioctlfunc_t iocfunc; if (*fp->fr_ifnames[1] && strcmp(fp->fr_ifnames[1], "*")) printifname(",", fp->fr_ifnames[1], fp->fr_ifas[1]); putchar(' '); + } - if (*fp->fr_dif.fd_ifname) - print_toif("dup-to", &fp->fr_dif); - if (*fp->fr_tif.fd_ifname) - print_toif("to", &fp->fr_tif); - if (fp->fr_flags & FR_FASTROUTE) - printf("fastroute "); - - if ((*fp->fr_ifnames[2] && strcmp(fp->fr_ifnames[2], "*")) || - (*fp->fr_ifnames[3] && strcmp(fp->fr_ifnames[3], "*"))) { - if (fp->fr_flags & FR_OUTQUE) - printf("in-via "); - else - printf("out-via "); + if (*fp->fr_dif.fd_ifname || (fp->fr_flags & FR_DUP)) + print_toif("dup-to", &fp->fr_dif); + if (*fp->fr_tif.fd_ifname) + print_toif("to", &fp->fr_tif); + if (*fp->fr_rif.fd_ifname) + print_toif("reply-to", &fp->fr_rif); + if (fp->fr_flags & FR_FASTROUTE) + printf("fastroute "); - if (*fp->fr_ifnames[2]) { - printifname("", fp->fr_ifnames[2], - fp->fr_ifas[2]); - putchar(' '); + if ((*fp->fr_ifnames[2] && strcmp(fp->fr_ifnames[2], "*")) || + (*fp->fr_ifnames[3] && strcmp(fp->fr_ifnames[3], "*"))) { + if (fp->fr_flags & FR_OUTQUE) + printf("in-via "); + else + printf("out-via "); + + if (*fp->fr_ifnames[2]) { + printifname("", fp->fr_ifnames[2], + fp->fr_ifas[2]); + putchar(' '); - if (*fp->fr_ifnames[3]) { - printifname(",", fp->fr_ifnames[3], - fp->fr_ifas[3]); - } + if (*fp->fr_ifnames[3]) { + printifname(",", fp->fr_ifnames[3], + fp->fr_ifas[3]); } } } @@ -158,10 +217,10 @@ ioctlfunc_t iocfunc; pr = -1; } else if (fp->fr_mip.fi_p) { pr = fp->fr_ip.fi_p; - if ((p = getprotobynumber(fp->fr_proto))) - printf("proto %s ", p->p_name); - else - printf("proto %d ", fp->fr_proto); + p = getprotobynumber(pr); + printf("proto "); + printproto(p, pr, NULL); + putchar(' '); } } @@ -169,133 +228,17 @@ ioctlfunc_t iocfunc; printf("all"); } else if (type == FR_T_IPF) { printf("from %s", fp->fr_flags & FR_NOTSRCIP ? "!" : ""); - if (fp->fr_satype != FRI_NORMAL) { - printf("%s", fp->fr_ifname); - if (fp->fr_satype == FRI_BROADCAST) - printf("/bcast"); - else if (fp->fr_satype == FRI_NETWORK) - printf("/net"); - else if (fp->fr_satype == FRI_NETMASKED) - printf("/netmasked"); - else if (fp->fr_satype == FRI_PEERADDR) - printf("/peer"); - else if (fp->fr_satype == FRI_LOOKUP) - printlookup(&fp->fr_ip.fi_src, - &fp->fr_mip.fi_src); - else - printmask(fp->fr_v, - (u_32_t *)&fp->fr_smsk.s_addr); - } else - printhostmask(fp->fr_v, (u_32_t *)&fp->fr_src.s_addr, - (u_32_t *)&fp->fr_smsk.s_addr); + printaddr(fp->fr_v, fp->fr_satype, fp->fr_ifname, + &fp->fr_src.s_addr, &fp->fr_smsk.s_addr); if (fp->fr_scmp) printportcmp(pr, &fp->fr_tuc.ftu_src); printf(" to %s", fp->fr_flags & FR_NOTDSTIP ? "!" : ""); - if (fp->fr_datype != FRI_NORMAL) { - printf("%s", fp->fr_ifname); - if (fp->fr_datype == FRI_BROADCAST) - printf("/bcast"); - else if (fp->fr_datype == FRI_NETWORK) - printf("/net"); - else if (fp->fr_datype == FRI_NETMASKED) - printf("/netmasked"); - else if (fp->fr_datype == FRI_PEERADDR) - printf("/peer"); - else if (fp->fr_datype == FRI_LOOKUP) - printlookup(&fp->fr_ip.fi_dst, - &fp->fr_mip.fi_dst); - else - printmask(fp->fr_v, - (u_32_t *)&fp->fr_dmsk.s_addr); - } else - printhostmask(fp->fr_v, (u_32_t *)&fp->fr_dst.s_addr, - (u_32_t *)&fp->fr_dmsk.s_addr); + printaddr(fp->fr_v, fp->fr_datype, fp->fr_ifname, + &fp->fr_dst.s_addr, &fp->fr_dmsk.s_addr); if (fp->fr_dcmp) printportcmp(pr, &fp->fr_tuc.ftu_dst); - if ((fp->fr_flx & FI_WITH) || (fp->fr_mflx & FI_WITH) || - fp->fr_optbits || fp->fr_optmask || - fp->fr_secbits || fp->fr_secmask) { - printf(" with"); - if (fp->fr_optbits || fp->fr_optmask || - fp->fr_secbits || fp->fr_secmask) { - sec[0] = fp->fr_secmask; - sec[1] = fp->fr_secbits; - if (fp->fr_v == 4) - optprint(sec, fp->fr_optmask, - fp->fr_optbits); -#ifdef USE_INET6 - else - optprintv6(sec, fp->fr_optmask, - fp->fr_optbits); -#endif - } else if (fp->fr_mflx & FI_OPTIONS) { - if (!(fp->fr_flx & FI_OPTIONS)) - printf(" not"); - printf(" ipopts"); - } - if (fp->fr_mflx & FI_SHORT) { - if (!(fp->fr_flx & FI_SHORT)) - printf(" not"); - printf(" short"); - } - if (fp->fr_mflx & FI_FRAG) { - if (!(fp->fr_flx & FI_FRAG)) - printf(" not"); - printf(" frag"); - } - if (fp->fr_mflx & FI_NATED) { - if (!(fp->fr_flx & FI_NATED)) - printf(" not"); - printf(" nat"); - } - if (fp->fr_mflx & FI_MULTICAST) { - if (!(fp->fr_flx & FI_MULTICAST)) - printf(" not"); - printf(" multicast"); - } - if (fp->fr_mflx & FI_BROADCAST) { - if (!(fp->fr_flx & FI_BROADCAST)) - printf(" not"); - printf(" bcast"); - } - if (fp->fr_mflx & FI_MBCAST) { - if (!(fp->fr_flx & FI_MBCAST)) - printf(" not"); - printf(" mbcast"); - } - if (fp->fr_mflx & FI_STATE) { - if (!(fp->fr_flx & FI_STATE)) - printf(" not"); - printf(" state"); - } - if (fp->fr_mflx & FI_BADNAT) { - if (!(fp->fr_flx & FI_BADNAT)) - printf(" not"); - printf(" bad-nat"); - } - if (fp->fr_mflx & FI_BAD) { - if (!(fp->fr_flx & FI_BAD)) - printf(" not"); - printf(" bad"); - } - if (fp->fr_mflx & FI_OOW) { - if (!(fp->fr_flx & FI_OOW)) - printf(" not"); - printf(" oow"); - } - if (fp->fr_mflx & FI_LOWTTL) { - if (!(fp->fr_flx & FI_LOWTTL)) - printf(" not"); - printf(" lowttl"); - } - if (fp->fr_mflx & FI_BADSRC) { - if (!(fp->fr_flx & FI_BADSRC)) - printf(" not"); - printf(" bad-src"); - } - } if ((fp->fr_proto == IPPROTO_ICMP #ifdef USE_INET6 || fp->fr_proto == IPPROTO_ICMPV6 @@ -334,19 +277,18 @@ ioctlfunc_t iocfunc; (void)putchar(*s); } } -#ifdef IPFILTER_BPF } else if (type == FR_T_BPFOPC) { - u_32_t *bp; + fakebpf_t *fb; int i; - printf("{"); - i = fp->fr_dsize / sizeof(*bp); + printf("bpf-v%d { \"", fp->fr_v); + i = fp->fr_dsize / sizeof(*fb); - for (bp = fp->fr_data; i; i--, bp++) - printf(" 0x%08x", *bp); + for (fb = fp->fr_data, s = ""; i; i--, fb++, s = " ") + printf("%s%#x %#x %#x %#x", s, fb->fb_c, fb->fb_t, + fb->fb_f, fb->fb_k); - printf(" }"); -#endif + printf("\" }"); } else if (type == FR_T_COMPIPF) { ; } else if (type == FR_T_CALLFUNC) { @@ -355,21 +297,153 @@ ioctlfunc_t iocfunc; printf("[unknown filter type %#x]", fp->fr_type); } + if ((type == FR_T_IPF) && + ((fp->fr_flx & FI_WITH) || (fp->fr_mflx & FI_WITH) || + fp->fr_optbits || fp->fr_optmask || + fp->fr_secbits || fp->fr_secmask)) { + char *comma = " "; + + printf(" with"); + if (fp->fr_optbits || fp->fr_optmask || + fp->fr_secbits || fp->fr_secmask) { + sec[0] = fp->fr_secmask; + sec[1] = fp->fr_secbits; + if (fp->fr_v == 4) + optprint(sec, fp->fr_optmask, fp->fr_optbits); +#ifdef USE_INET6 + else + optprintv6(sec, fp->fr_optmask, + fp->fr_optbits); +#endif + } else if (fp->fr_mflx & FI_OPTIONS) { + fputs(comma, stdout); + if (!(fp->fr_flx & FI_OPTIONS)) + printf("not "); + printf("ipopts"); + comma = ","; + } + if (fp->fr_mflx & FI_SHORT) { + fputs(comma, stdout); + if (!(fp->fr_flx & FI_SHORT)) + printf("not "); + printf("short"); + comma = ","; + } + if (fp->fr_mflx & FI_FRAG) { + fputs(comma, stdout); + if (!(fp->fr_flx & FI_FRAG)) + printf("not "); + printf("frag"); + comma = ","; + } + if (fp->fr_mflx & FI_FRAGBODY) { + fputs(comma, stdout); + if (!(fp->fr_flx & FI_FRAGBODY)) + printf("not "); + printf("frag-body"); + comma = ","; + } + if (fp->fr_mflx & FI_NATED) { + fputs(comma, stdout); + if (!(fp->fr_flx & FI_NATED)) + printf("not "); + printf("nat"); + comma = ","; + } + if (fp->fr_mflx & FI_LOWTTL) { + fputs(comma, stdout); + if (!(fp->fr_flx & FI_LOWTTL)) + printf("not "); + printf("lowttl"); + comma = ","; + } + if (fp->fr_mflx & FI_BAD) { + fputs(comma, stdout); + if (!(fp->fr_flx & FI_BAD)) + printf("not "); + printf("bad"); + comma = ","; + } + if (fp->fr_mflx & FI_BADSRC) { + fputs(comma, stdout); + if (!(fp->fr_flx & FI_BADSRC)) + printf("not "); + printf("bad-src"); + comma = ","; + } + if (fp->fr_mflx & FI_BADNAT) { + fputs(comma, stdout); + if (!(fp->fr_flx & FI_BADNAT)) + printf("not "); + printf("bad-nat"); + comma = ","; + } + if (fp->fr_mflx & FI_OOW) { + fputs(comma, stdout); + if (!(fp->fr_flx & FI_OOW)) + printf("not "); + printf("oow"); + } + if (fp->fr_mflx & FI_MULTICAST) { + fputs(comma, stdout); + if (!(fp->fr_flx & FI_MULTICAST)) + printf("not "); + printf("multicast"); + comma = ","; + } + if (fp->fr_mflx & FI_BROADCAST) { + fputs(comma, stdout); + if (!(fp->fr_flx & FI_BROADCAST)) + printf("not "); + printf("bcast"); + comma = ","; + } + if (fp->fr_mflx & FI_MBCAST) { + fputs(comma, stdout); + if (!(fp->fr_flx & FI_MBCAST)) + printf("not "); + printf("mbcast"); + comma = ","; + } + if (fp->fr_mflx & FI_STATE) { + fputs(comma, stdout); + if (!(fp->fr_flx & FI_STATE)) + printf("not "); + printf("state"); + comma = ","; + } + } + if (fp->fr_flags & FR_KEEPSTATE) { printf(" keep state"); - if ((fp->fr_flags & (FR_STSTRICT|FR_NEWISN)) || + if ((fp->fr_flags & (FR_STSTRICT|FR_NEWISN|FR_NOICMPERR|FR_STATESYNC)) || (fp->fr_statemax != 0) || (fp->fr_age[0] != 0)) { + char *comma = ""; printf(" ("); - if (fp->fr_statemax != 0) - printf(" limit %u", fp->fr_statemax); - if (fp->fr_flags & FR_FRSTRICT) - printf(" strict"); - if (fp->fr_flags & FR_NEWISN) - printf(" newisn"); + if (fp->fr_statemax != 0) { + printf("limit %u", fp->fr_statemax); + comma = ","; + } + if (fp->fr_flags & FR_STSTRICT) { + printf("%sstrict", comma); + comma = ","; + } + if (fp->fr_flags & FR_NEWISN) { + printf("%snewisn", comma); + comma = ","; + } + if (fp->fr_flags & FR_NOICMPERR) { + printf("%sno-icmp-err", comma); + comma = ","; + } + if (fp->fr_flags & FR_STATESYNC) { + printf("%ssync", comma); + comma = ","; + } if (fp->fr_age[0] || fp->fr_age[1]) - printf(" age %d/%d", fp->fr_age[0], + printf("%sage %d/%d", comma, fp->fr_age[0], fp->fr_age[1]); - printf(" )"); + printf(")"); } } if (fp->fr_flags & FR_KEEPFRAG) { @@ -392,8 +466,20 @@ ioctlfunc_t iocfunc; printf(" head %s", fp->fr_grhead); if (*fp->fr_group != '\0') printf(" group %s", fp->fr_group); - if (fp->fr_logtag != FR_NOLOGTAG) - printf(" log-tag %u", fp->fr_logtag); + if (fp->fr_logtag != FR_NOLOGTAG || *fp->fr_nattag.ipt_tag) { + char *s = ""; + + printf(" set-tag("); + if (fp->fr_logtag != FR_NOLOGTAG) { + printf("log=%u", fp->fr_logtag); + s = ", "; + } + if (*fp->fr_nattag.ipt_tag) { + printf("%snat=%-.*s", s, IPFTAG_LEN, + fp->fr_nattag.ipt_tag); + } + printf(")"); + } if (fp->fr_pps) printf(" pps %d", fp->fr_pps); (void)putchar('\n'); diff --git a/usr/src/cmd/ipf/lib/common/printfraginfo.c b/usr/src/cmd/ipf/lib/common/printfraginfo.c new file mode 100644 index 0000000000..557b031a6b --- /dev/null +++ b/usr/src/cmd/ipf/lib/common/printfraginfo.c @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2004 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id: printfraginfo.c,v 1.1.2.2 2004/03/23 15:15:45 darrenr Exp $ + */ +#include "ipf.h" +#include "kmem.h" + +void printfraginfo(prefix, ifr) +char *prefix; +struct ipfr *ifr; +{ + frentry_t fr; + + fr.fr_flags = 0xffffffff; + + printf("%s%s -> ", prefix, hostname(4, &ifr->ipfr_src)); + if (kmemcpy((char *)&fr, (u_long)ifr->ipfr_rule, + sizeof(fr)) == -1) + return; + printf("%s id %d ttl %d pr %d seen0 %d ifp %p tos %#02x = %#x\n", + hostname(4, &ifr->ipfr_dst), ifr->ipfr_id, ifr->ipfr_seen0, + ifr->ipfr_ttl, ifr->ipfr_p, ifr->ipfr_ifp, ifr->ipfr_tos, + fr.fr_flags); +} diff --git a/usr/src/cmd/ipf/lib/common/printhash.c b/usr/src/cmd/ipf/lib/common/printhash.c index f683226026..034c952d6f 100644 --- a/usr/src/cmd/ipf/lib/common/printhash.c +++ b/usr/src/cmd/ipf/lib/common/printhash.c @@ -3,7 +3,7 @@ * * See the IPFILTER.LICENCE file for details on licencing. * - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -14,19 +14,24 @@ #define PRINTF (void)printf #define FPRINTF (void)fprintf -iphtable_t *printhash(hp, copyfunc, opts) + +iphtable_t *printhash(hp, copyfunc, name, opts) iphtable_t *hp; copyfunc_t copyfunc; +char *name; int opts; { iphtent_t *ipep, **table; iphtable_t iph; + int i, printed; size_t sz; - int i; if ((*copyfunc)((char *)hp, (char *)&iph, sizeof(iph))) return NULL; + if ((name != NULL) && strncmp(name, iph.iph_name, FR_GROUPLEN)) + return iph.iph_next; + if ((opts & OPT_DEBUG) == 0) { if ((iph.iph_type & IPHASH_ANON) == IPHASH_ANON) PRINTF("# 'anonymous' table\n"); @@ -124,11 +129,14 @@ int opts; if ((*copyfunc)((char *)iph.iph_table, (char *)table, sz)) return NULL; - for (i = 0; i < iph.iph_size; i++) { + for (i = 0, printed = 0; i < iph.iph_size; i++) { for (ipep = table[i]; ipep != NULL; ) { ipep = printhashnode(&iph, ipep, copyfunc, opts); + printed++; } } + if (printed == 0) + putchar(';'); free(table); diff --git a/usr/src/cmd/ipf/lib/common/printhashnode.c b/usr/src/cmd/ipf/lib/common/printhashnode.c index 83cd57eab1..10f2223f28 100644 --- a/usr/src/cmd/ipf/lib/common/printhashnode.c +++ b/usr/src/cmd/ipf/lib/common/printhashnode.c @@ -3,7 +3,7 @@ * * See the IPFILTER.LICENCE file for details on licencing. * - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -47,8 +47,8 @@ int opts; #endif printmask(4, (u_32_t *)&ipe.ipe_mask.in4_addr); - PRINTF("\tRef. Count: %d\tValue: %d\n", ipe.ipe_ref, - ipe.ipe_value); + PRINTF("\tRef. Count: %d\tGroup: %s\n", ipe.ipe_ref, + ipe.ipe_group); } else { putchar(' '); #ifdef USE_INET6 @@ -65,8 +65,10 @@ int opts; switch (iph->iph_type & ~IPHASH_ANON) { case IPHASH_GROUPMAP : - PRINTF(", group = %s", ipe.ipe_group); - break; + if (strncmp(ipe.ipe_group, iph->iph_name, + FR_GROUPLEN)) + PRINTF(", group = %s", ipe.ipe_group); + break; } } putchar(';'); diff --git a/usr/src/cmd/ipf/lib/common/printnat.c b/usr/src/cmd/ipf/lib/common/printnat.c index 2f6c058bc4..0e228652fa 100644 --- a/usr/src/cmd/ipf/lib/common/printnat.c +++ b/usr/src/cmd/ipf/lib/common/printnat.c @@ -5,7 +5,7 @@ * * Added redirect stuff and a variety of bug fixes. (mcn@EnGarde.com) * - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -16,84 +16,9 @@ #if !defined(lint) -static const char rcsid[] = "@(#)$Id: printnat.c,v 1.14 2003/04/13 06:39:16 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id: printnat.c,v 1.22.2.9 2005/06/12 07:18:43 darrenr Exp $"; #endif - -void printactivenat(nat, opts) -nat_t *nat; -int opts; -{ - u_int hv1, hv2; - - printf("%s", getnattype(nat->nat_ptr)); - - if (nat->nat_flags & SI_CLONE) - printf(" CLONE"); - - printf(" %-15s", inet_ntoa(nat->nat_inip)); - - if ((nat->nat_flags & IPN_TCPUDP) != 0) - printf(" %-5hu", ntohs(nat->nat_inport)); - - printf(" <- -> %-15s",inet_ntoa(nat->nat_outip)); - - if ((nat->nat_flags & IPN_TCPUDP) != 0) - printf(" %-5hu", ntohs(nat->nat_outport)); - - printf(" [%s", inet_ntoa(nat->nat_oip)); - if ((nat->nat_flags & IPN_TCPUDP) != 0) - printf(" %hu", ntohs(nat->nat_oport)); - printf("]"); - - if (opts & OPT_VERBOSE) { - printf("\n\tage %lu use %hu sumd %s/", - nat->nat_age, nat->nat_use, getsumd(nat->nat_sumd[0])); - if ((nat->nat_flags & SI_WILDP) == 0) { - hv1 = NAT_HASH_FN(nat->nat_inip.s_addr, - nat->nat_inport, 0xffffffff); - hv1 = NAT_HASH_FN(nat->nat_oip.s_addr, - hv1 + nat->nat_oport, NAT_TABLE_SZ); - hv2 = NAT_HASH_FN(nat->nat_outip.s_addr, - nat->nat_outport, 0xffffffff); - hv2 = NAT_HASH_FN(nat->nat_oip.s_addr, - hv2 + nat->nat_oport, NAT_TABLE_SZ); - } else { - hv1 = NAT_HASH_FN(nat->nat_inip.s_addr, 0, - 0xffffffff); - hv1 = NAT_HASH_FN(nat->nat_oip.s_addr, hv1, - NAT_TABLE_SZ); - hv2 = NAT_HASH_FN(nat->nat_outip.s_addr, 0, - 0xffffffff); - hv2 = NAT_HASH_FN(nat->nat_oip.s_addr, hv2, - NAT_TABLE_SZ); - } - printf("%s pr %u bkt %d/%d flags %x\n", - getsumd(nat->nat_sumd[1]), nat->nat_p, - hv1, hv2, nat->nat_flags); - printf("\tifp %s", getifname(nat->nat_ifps[0])); - printf(",%s ", getifname(nat->nat_ifps[1])); -#ifdef USE_QUAD_T - printf("bytes %qu/%qu pkts %qu/%qu", - (unsigned long long)nat->nat_bytes[0], - (unsigned long long)nat->nat_bytes[1], - (unsigned long long)nat->nat_pkts[0], - (unsigned long long)nat->nat_pkts[1]); -#else - printf("bytes %lu/%lu pkts %lu/%lu", nat->nat_bytes[0], - nat->nat_bytes[1], nat->nat_pkts[0], nat->nat_pkts[1]); -#endif -#if SOLARIS - printf(" %lx", nat->nat_ipsumd); -#endif - } - - putchar('\n'); - if (nat->nat_aps) - printaps(nat->nat_aps, opts); -} - - /* * Print out a NAT rule */ @@ -102,7 +27,6 @@ ipnat_t *np; int opts; { struct protoent *pr; - struct servent *sv; int bits; pr = getprotobynumber(np->in_p); @@ -167,33 +91,26 @@ int opts; printf("%s", inet_ntoa(np->in_out[0].in4)); bits = count4bits(np->in_outmsk); if (bits != -1) - printf("/%d ", bits); + printf("/%d", bits); else - printf("/%s ", inet_ntoa(np->in_out[1].in4)); - 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[1].in4)); + if (np->in_flags & IPN_TCPUDP) { + printf(" port %d", ntohs(np->in_pmin)); + if (np->in_pmax != np->in_pmin) + printf("-%d", ntohs(np->in_pmax)); + } } printf(" -> %s", inet_ntoa(np->in_in[0].in4)); if (np->in_flags & IPN_SPLIT) printf(",%s", inet_ntoa(np->in_in[1].in4)); - if (np->in_inip == 0) { - bits = count4bits(np->in_inmsk); - printf("/%d", bits); + if (np->in_flags & IPN_TCPUDP) { + if ((np->in_flags & IPN_FIXEDDPORT) != 0) + printf(" port = %d", ntohs(np->in_pnext)); + else + printf(" port %d", ntohs(np->in_pnext)); } - printf(" port %d", ntohs(np->in_pnext)); - if ((np->in_flags & IPN_TCPUDP) == IPN_TCPUDP) - printf(" tcp/udp"); - else if ((np->in_flags & IPN_TCP) == IPN_TCP) - printf(" tcp"); - else if ((np->in_flags & IPN_UDP) == IPN_UDP) - printf(" udp"); - else if (np->in_p == 0) - printf(" ip"); - else if (pr != NULL) - printf(" %s", pr->p_name); - else - printf(" %d", np->in_p); + putchar(' '); + printproto(pr, np->in_p, np); if (np->in_flags & IPN_ROUNDR) printf(" round-robin"); if (np->in_flags & IPN_FRAG) @@ -205,19 +122,14 @@ int opts; printf(" sticky"); if (np->in_mssclamp != 0) printf(" mssclamp %d", np->in_mssclamp); - if (*np->in_plabel != '\0') { - printf(" proxy %.*s/", (int)sizeof(np->in_plabel), + if (*np->in_plabel != '\0') + printf(" proxy %.*s", (int)sizeof(np->in_plabel), np->in_plabel); - if (pr != NULL) - fputs(pr->p_name, stdout); - else - printf("%d", np->in_p); - } + if (np->in_tag.ipt_tag[0] != '\0') + printf(" tag %-.*s", IPFTAG_LEN, np->in_tag.ipt_tag); printf("\n"); if (opts & OPT_DEBUG) - printf("\tspc %lu flg %#x max %u use %d\n", - np->in_space, np->in_flags, - np->in_pmax, np->in_use); + printf("\tpmax %u\n", np->in_pmax); } else { if (!(np->in_flags & IPN_FILTER)) { printf("%s/", inet_ntoa(np->in_in[0].in4)); @@ -240,26 +152,21 @@ int opts; printf("%s", inet_ntoa(np->in_out[1].in4)); } if (*np->in_plabel != '\0') { - printf(" proxy port"); + printf(" proxy port "); if (np->in_dcmp != 0) np->in_dport = htons(np->in_dport); if (np->in_dport != 0) { - if (pr != NULL) - sv = getservbyport(np->in_dport, - pr->p_name); - else - sv = getservbyport(np->in_dport, NULL); - if (sv != NULL) - printf(" %s", sv->s_name); + char *s; + + s = portname(np->in_p, ntohs(np->in_dport)); + if (s != NULL) + fputs(s, stdout); else - printf(" %hu", ntohs(np->in_dport)); + fputs("???", stdout); } printf(" %.*s/", (int)sizeof(np->in_plabel), np->in_plabel); - if (pr != NULL) - fputs(pr->p_name, stdout); - else - printf("%d", np->in_p); + printproto(pr, np->in_p, NULL); } else if (np->in_redir == NAT_MAPBLK) { if ((np->in_pmin == 0) && (np->in_flags & IPN_AUTOPORTMAP)) @@ -269,13 +176,12 @@ int opts; if (opts & OPT_DEBUG) printf("\n\tip modulous %d", np->in_pmax); } else if (np->in_pmin || np->in_pmax) { - printf(" portmap"); - if ((np->in_flags & IPN_TCPUDP) == IPN_TCPUDP) - printf(" tcp/udp"); - else if (np->in_flags & IPN_TCP) - printf(" tcp"); - else if (np->in_flags & IPN_UDP) - printf(" udp"); + if (np->in_flags & IPN_ICMPQUERY) { + printf(" icmpidmap "); + } else { + printf(" portmap "); + } + printproto(pr, np->in_p, np); if (np->in_flags & IPN_AUTOPORTMAP) { printf(" auto"); if (opts & OPT_DEBUG) @@ -287,7 +193,11 @@ int opts; printf(" %d:%d", ntohs(np->in_pmin), ntohs(np->in_pmax)); } + } else if (np->in_flags & IPN_TCPUDP || np->in_p) { + putchar(' '); + printproto(pr, np->in_p, np); } + if (np->in_flags & IPN_FRAG) printf(" frag"); if (np->in_age[0] != 0 || np->in_age[1] != 0) { @@ -295,16 +205,26 @@ int opts; } if (np->in_mssclamp != 0) printf(" mssclamp %d", np->in_mssclamp); + if (np->in_tag.ipt_tag[0] != '\0') + printf(" tag %s", np->in_tag.ipt_tag); printf("\n"); if (opts & OPT_DEBUG) { struct in_addr nip; nip.s_addr = htonl(np->in_nextip.s_addr); - printf("\tspace %lu nextip %s pnext %d", np->in_space, + printf("\tnextip %s pnext %d\n", inet_ntoa(nip), np->in_pnext); - printf(" flags %x use %u\n", - np->in_flags, np->in_use); } } + + if (opts & OPT_DEBUG) { + printf("\tspace %lu use %u hits %lu flags %#x proto %d hv %d\n", + np->in_space, np->in_use, np->in_hits, + np->in_flags, np->in_p, np->in_hv); + printf("\tifp[0] %p ifp[1] %p apr %p\n", + np->in_ifps[0], np->in_ifps[1], np->in_apr); + printf("\ttqehead %p/%p comment %p\n", + np->in_tqehead[0], np->in_tqehead[1], np->in_comment); + } } diff --git a/usr/src/cmd/ipf/lib/common/printpacket.c b/usr/src/cmd/ipf/lib/common/printpacket.c index 6f2194af70..4121e3acd5 100644 --- a/usr/src/cmd/ipf/lib/common/printpacket.c +++ b/usr/src/cmd/ipf/lib/common/printpacket.c @@ -3,7 +3,7 @@ * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: printpacket.c,v 1.12 2002/11/02 13:27:29 darrenr Exp $ + * $Id: printpacket.c,v 1.12.4.1 2005/02/21 05:09:24 darrenr Exp $ */ #include "ipf.h" @@ -18,11 +18,15 @@ struct ip *ip; { struct tcphdr *tcp; u_short len; + u_short off; - if (IP_V(ip) == 6) + if (IP_V(ip) == 6) { + off = 0; len = ntohs(((u_short *)ip)[2]) + 40; - else + } else { + off = ntohs(ip->ip_off); len = ntohs(ip->ip_len); + } if ((opts & OPT_HEX) == OPT_HEX) { u_char *s; @@ -47,15 +51,15 @@ struct ip *ip; tcp = (struct tcphdr *)((char *)ip + (IP_HL(ip) << 2)); printf("ip %d(%d) %d", ntohs(ip->ip_len), IP_HL(ip) << 2, ip->ip_p); - if (ip->ip_off & IP_OFFMASK) - printf(" @%d", ip->ip_off << 3); + if (off & IP_OFFMASK) + printf(" @%d", off << 3); printf(" %s", inet_ntoa(ip->ip_src)); - if (!(ip->ip_off & IP_OFFMASK)) + if (!(off & IP_OFFMASK)) if (ip->ip_p == IPPROTO_TCP || ip->ip_p == IPPROTO_UDP) printf(",%d", ntohs(tcp->th_sport)); printf(" > "); printf("%s", inet_ntoa(ip->ip_dst)); - if (!(ip->ip_off & IP_OFFMASK)) { + if (!(off & IP_OFFMASK)) { if (ip->ip_p == IPPROTO_TCP || ip->ip_p == IPPROTO_UDP) printf(",%d", ntohs(tcp->th_dport)); if ((ip->ip_p == IPPROTO_TCP) && (tcp->th_flags != 0)) { diff --git a/usr/src/cmd/ipf/lib/common/printpool.c b/usr/src/cmd/ipf/lib/common/printpool.c index 59f5d727e7..842086274b 100644 --- a/usr/src/cmd/ipf/lib/common/printpool.c +++ b/usr/src/cmd/ipf/lib/common/printpool.c @@ -3,7 +3,7 @@ * * See the IPFILTER.LICENCE file for details on licencing. * - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -14,17 +14,21 @@ #define PRINTF (void)printf #define FPRINTF (void)fprintf -ip_pool_t *printpool(pp, copyfunc, opts) +ip_pool_t *printpool(pp, copyfunc, name, opts) ip_pool_t *pp; copyfunc_t copyfunc; +char *name; int opts; { - ip_pool_node_t *ipnp, *ipnpn; + ip_pool_node_t *ipnp, *ipnpn, ipn; ip_pool_t ipp; if ((*copyfunc)(pp, &ipp, sizeof(ipp))) return NULL; + if ((name != NULL) && strncmp(name, ipp.ipo_name, FR_GROUPLEN)) + return ipp.ipo_next; + if ((opts & OPT_DEBUG) == 0) { if ((ipp.ipo_flags & IPOOL_ANON) != 0) PRINTF("# 'anonymous' tree %s\n", ipp.ipo_name); @@ -82,17 +86,22 @@ int opts; ipp.ipo_list = NULL; while (ipnpn != NULL) { ipnp = (ip_pool_node_t *)malloc(sizeof(*ipnp)); - (*copyfunc)(ipnpn, ipnp, sizeof(*ipnp)); + (*copyfunc)(ipnpn, ipnp, sizeof(ipn)); ipnpn = ipnp->ipn_next; ipnp->ipn_next = ipp.ipo_list; ipp.ipo_list = ipnp; } - for (ipnp = ipp.ipo_list; ipnp != NULL; ) { - ipnp = printpoolnode(ipnp, opts); + if (ipp.ipo_list == NULL) { + putchar(';'); + } else { + for (ipnp = ipp.ipo_list; ipnp != NULL; ) { + ipnp = printpoolnode(ipnp, opts); - if ((opts & OPT_DEBUG) == 0) - putchar(';'); + if ((opts & OPT_DEBUG) == 0) { + putchar(';'); + } + } } if ((opts & OPT_DEBUG) == 0) diff --git a/usr/src/cmd/ipf/lib/common/printproto.c b/usr/src/cmd/ipf/lib/common/printproto.c new file mode 100644 index 0000000000..dd0ce39ca5 --- /dev/null +++ b/usr/src/cmd/ipf/lib/common/printproto.c @@ -0,0 +1,51 @@ +/* + * Copyright (C) 1993-2005 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + */ + +#include "ipf.h" + + +#if !defined(lint) +static const char rcsid[] = "@(#)$Id: printproto.c,v 1.1.2.1 2005/06/12 07:21:53 darrenr Exp $"; +#endif + + +void printproto(pr, p, np) +struct protoent *pr; +int p; +ipnat_t *np; +{ + if (np != NULL) { + if ((np->in_flags & IPN_TCPUDP) == IPN_TCPUDP) + printf("tcp/udp"); + else if (np->in_flags & IPN_TCP) + printf("tcp"); + else if (np->in_flags & IPN_UDP) + printf("udp"); + else if (np->in_flags & IPN_ICMPQUERY) + printf("icmp"); +#ifdef _AIX51 + /* + * To make up for "ip = 252" and "hopopt = 0" in /etc/protocols + */ + else if (np->in_p == 0) + printf("ip"); +#endif + else if (pr != NULL) + printf("%s", pr->p_name); + else + printf("%d", np->in_p); + } else { +#ifdef _AIX51 + if (p == 0) + printf("ip"); + else +#endif + if (pr != NULL) + printf("%s", pr->p_name); + else + printf("%d", p); + } +} diff --git a/usr/src/cmd/ipf/lib/common/printsbuf.c b/usr/src/cmd/ipf/lib/common/printsbuf.c index 98139cebc9..cc13e19b6b 100644 --- a/usr/src/cmd/ipf/lib/common/printsbuf.c +++ b/usr/src/cmd/ipf/lib/common/printsbuf.c @@ -1,3 +1,8 @@ +/* + * Copyright (C) 1993-2005 by Darren Reed. + * See the IPFILTER.LICENCE file for details on licencing. + */ + #ifdef IPFILTER_SCAN #include <ctype.h> @@ -12,7 +17,7 @@ char *buf; int i; for (s = (u_char *)buf, i = ISC_TLEN; i; i--, s++) { - if (isprint(*s)) + if (ISPRINT(*s)) putchar(*s); else printf("\\%o", *s); diff --git a/usr/src/cmd/ipf/lib/common/printstate.c b/usr/src/cmd/ipf/lib/common/printstate.c index 369c1665bf..b0a58abfd7 100644 --- a/usr/src/cmd/ipf/lib/common/printstate.c +++ b/usr/src/cmd/ipf/lib/common/printstate.c @@ -10,11 +10,15 @@ #define PRINTF (void)printf #define FPRINTF (void)fprintf -ipstate_t *printstate(sp, opts) +ipstate_t *printstate(sp, opts, now) ipstate_t *sp; int opts; +u_long now; { ipstate_t ips; +#ifdef IPFILTER_SYNC + synclist_t ipsync; +#endif if (kmemcpy((char *)&ips, (u_long)sp, sizeof(ips))) return NULL; @@ -23,7 +27,7 @@ int opts; PRINTF("%s pass %#x pr %d state %d/%d bkt %d\n", hostname(ips.is_v, &ips.is_dst.in4), ips.is_pass, ips.is_p, ips.is_state[0], ips.is_state[1], ips.is_hv); - PRINTF("\ttag %u age %lu/%lu", ips.is_tag, ips.is_die, ips.is_touched); + PRINTF("\ttag %u ttl %lu", ips.is_tag, ips.is_die - now); if (ips.is_p == IPPROTO_TCP) { PRINTF("\n\t%hu -> %hu %x:%x %hu<<%d:%hu<<%d\n", @@ -45,10 +49,13 @@ int opts; printsbuf(ips.is_sbuf[1]); PRINTF("]\n"); #endif - } else if (ips.is_p == IPPROTO_UDP) + } else if (ips.is_p == IPPROTO_UDP) { PRINTF(" %hu -> %hu\n", ntohs(ips.is_sport), ntohs(ips.is_dport)); - else if (ips.is_p == IPPROTO_ICMP + } else if (ips.is_p == IPPROTO_GRE) { + PRINTF(" call %hx/%hx\n", ntohs(ips.is_gre.gs_call[0]), + ntohs(ips.is_gre.gs_call[1])); + } else if (ips.is_p == IPPROTO_ICMP #ifdef USE_INET6 || ips.is_p == IPPROTO_ICMPV6 #endif @@ -57,7 +64,7 @@ int opts; ntohs(ips.is_icmp.ici_seq), ips.is_icmp.ici_type); #ifdef USE_QUAD_T - PRINTF("\tforward: pkts in %qd bytes in %qd pkts out %qd bytes out %qd\n\tbackward: pkts in %qd bytes in %qd pkts out %qd bytes out %qd", + PRINTF("\tforward: pkts in %qd bytes in %qd pkts out %qd bytes out %qd\n\tbackward: pkts in %qd bytes in %qd pkts out %qd bytes out %qd\n", ips.is_pkts[0], ips.is_bytes[0], ips.is_pkts[1], ips.is_bytes[1], ips.is_pkts[2], ips.is_bytes[2], @@ -126,16 +133,19 @@ int opts; if (ips.is_pass & FR_KEEPFRAG) PRINTF(" keep frags"); /* a given; no? */ - if (ips.is_pass & FR_KEEPSTATE) + if (ips.is_pass & FR_KEEPSTATE) { PRINTF(" keep state"); + if (ips.is_pass & FR_STATESYNC) + PRINTF(" ( sync )"); + } PRINTF("\tIPv%d", ips.is_v); PRINTF("\n"); PRINTF("\tpkt_flags & %x(%x) = %x,\t", ips.is_flags & 0xf, ips.is_flags, ips.is_flags >> 4); - PRINTF("\tpkt_options & %x = %x\n", ips.is_optmsk, - ips.is_opt); + PRINTF("\tpkt_options & %x = %x, %x = %x \n", ips.is_optmsk[0], + ips.is_opt[0], ips.is_optmsk[1], ips.is_opt[1]); PRINTF("\tpkt_security & %x = %x, pkt_auth & %x = %x\n", ips.is_secmsk, ips.is_sec, ips.is_authmsk, ips.is_auth); @@ -159,5 +169,23 @@ int opts; PRINTF("/%p", ips.is_ifp[3]); PRINTF("]\n"); +#ifdef IPFILTER_SYNC + if (ips.is_sync != NULL) { + + if (kmemcpy((char *)&ipsync, (u_long)ips.is_sync, sizeof(ipsync))) { + + PRINTF("\tSync status: status could not be retrieved\n"); + return NULL; + } + + PRINTF("\tSync status: idx %d num %d v %d pr %d rev %d\n", + ipsync.sl_idx, ipsync.sl_num, ipsync.sl_v, + ipsync.sl_p, ipsync.sl_rev); + + } else { + PRINTF("\tSync status: not synchronized\n"); + } +#endif + return ips.is_next; } diff --git a/usr/src/cmd/ipf/lib/common/printtunable.c b/usr/src/cmd/ipf/lib/common/printtunable.c new file mode 100644 index 0000000000..01ea7e8985 --- /dev/null +++ b/usr/src/cmd/ipf/lib/common/printtunable.c @@ -0,0 +1,24 @@ +/* + * Copyright (C) 1993-2005 by Darren Reed. + * See the IPFILTER.LICENCE file for details on licencing. + */ + +#include "ipf.h" + +void printtunable(tup) +ipftune_t *tup; +{ + printf("%s\tmin %#lx\tmax %#lx\tcurrent ", + tup->ipft_name, tup->ipft_min, tup->ipft_max); + if (tup->ipft_sz == sizeof(u_long)) + printf("%lu\n", tup->ipft_vlong); + else if (tup->ipft_sz == sizeof(u_int)) + printf("%u\n", tup->ipft_vint); + else if (tup->ipft_sz == sizeof(u_short)) + printf("%hu\n", tup->ipft_vshort); + else if (tup->ipft_sz == sizeof(u_char)) + printf("%u\n", (u_int)tup->ipft_vchar); + else { + printf("sz = %d\n", tup->ipft_sz); + } +} diff --git a/usr/src/cmd/ipf/lib/common/remove_hash.c b/usr/src/cmd/ipf/lib/common/remove_hash.c index d939f97b71..d1830ac76a 100644 --- a/usr/src/cmd/ipf/lib/common/remove_hash.c +++ b/usr/src/cmd/ipf/lib/common/remove_hash.c @@ -9,14 +9,8 @@ #include <fcntl.h> #include <sys/ioctl.h> #include "ipf.h" - -#if SOLARIS2 >= 10 -#include "ip_lookup.h" -#include "ip_htable.h" -#else #include "netinet/ip_lookup.h" #include "netinet/ip_htable.h" -#endif static int hashfd = -1; diff --git a/usr/src/cmd/ipf/lib/common/remove_hashnode.c b/usr/src/cmd/ipf/lib/common/remove_hashnode.c index b9c65d5914..afa0dbc554 100644 --- a/usr/src/cmd/ipf/lib/common/remove_hashnode.c +++ b/usr/src/cmd/ipf/lib/common/remove_hashnode.c @@ -9,14 +9,8 @@ #include <fcntl.h> #include <sys/ioctl.h> #include "ipf.h" - -#if SOLARIS2 >= 10 -#include "ip_lookup.h" -#include "ip_htable.h" -#else #include "netinet/ip_lookup.h" #include "netinet/ip_htable.h" -#endif static int hashfd = -1; diff --git a/usr/src/cmd/ipf/lib/common/remove_pool.c b/usr/src/cmd/ipf/lib/common/remove_pool.c index 398ce376ed..d14529ab40 100644 --- a/usr/src/cmd/ipf/lib/common/remove_pool.c +++ b/usr/src/cmd/ipf/lib/common/remove_pool.c @@ -9,14 +9,8 @@ #include <fcntl.h> #include <sys/ioctl.h> #include "ipf.h" - -#if SOLARIS2 >= 10 -#include "ip_lookup.h" -#include "ip_htable.h" -#else #include "netinet/ip_lookup.h" #include "netinet/ip_htable.h" -#endif static int poolfd = -1; diff --git a/usr/src/cmd/ipf/lib/common/remove_poolnode.c b/usr/src/cmd/ipf/lib/common/remove_poolnode.c index 1b5b537913..2c7f9d3028 100644 --- a/usr/src/cmd/ipf/lib/common/remove_poolnode.c +++ b/usr/src/cmd/ipf/lib/common/remove_poolnode.c @@ -3,20 +3,14 @@ * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: remove_poolnode.c,v 1.1 2003/04/13 06:40:14 darrenr Exp $ + * $Id: remove_poolnode.c,v 1.3 2003/11/22 10:14:36 darrenr Exp $ */ #include <fcntl.h> #include <sys/ioctl.h> #include "ipf.h" - -#if SOLARIS2 >= 10 -#include "ip_lookup.h" -#include "ip_htable.h" -#else #include "netinet/ip_lookup.h" -#include "netinet/ip_htable.h" -#endif +#include "netinet/ip_pool.h" static int poolfd = -1; diff --git a/usr/src/cmd/ipf/lib/common/v6ionames.c b/usr/src/cmd/ipf/lib/common/v6ionames.c index 9b47cfd9fd..27affe5e50 100644 --- a/usr/src/cmd/ipf/lib/common/v6ionames.c +++ b/usr/src/cmd/ipf/lib/common/v6ionames.c @@ -3,10 +3,8 @@ * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: v6ionames.c,v 1.1 2003/04/26 04:55:58 darrenr Exp $ + * $Id: v6ionames.c,v 1.1.4.1 2005/01/02 13:08:49 darrenr Exp $ */ - - #include "ipf.h" diff --git a/usr/src/cmd/ipf/lib/common/var.c b/usr/src/cmd/ipf/lib/common/var.c index 994d5bcdb3..706a55ba97 100644 --- a/usr/src/cmd/ipf/lib/common/var.c +++ b/usr/src/cmd/ipf/lib/common/var.c @@ -1,3 +1,8 @@ +/* + * Copyright (C) 1993-2005 by Darren Reed. + * See the IPFILTER.LICENCE file for details on licencing. + */ + #include <ctype.h> #include "ipf.h" @@ -44,9 +49,9 @@ int line; fprintf(stderr, "%d: { without }\n", line); return NULL; } - } else if (isalpha(*s)) { + } else if (ISALPHA(*s)) { for (t = s + 1; *t != '\0'; t++) - if (!isalpha(*t) && !isdigit(*t)) + if (!ISALPHA(*t) && !ISDIGIT(*t) && (*t != '_')) break; } else { fprintf(stderr, "%d: variables cannot start with '%c'\n", @@ -95,6 +100,9 @@ int line; break; default : c = *s; + if (c == '\0') + return newstring; + value = get_variable(s, &p3, line); if (value == NULL) return NULL; @@ -119,7 +127,7 @@ int line; if (p3 != NULL) strcat(p1, p3); - s = p1 + len - strlen(p3); + s = p1 + len - strlen(p3) - 1; if (newstring != oldstring) free(newstring); newstring = p1; diff --git a/usr/src/cmd/ipf/tools/Makefile.tools b/usr/src/cmd/ipf/tools/Makefile.tools index c4cd838a04..17ec18ab93 100644 --- a/usr/src/cmd/ipf/tools/Makefile.tools +++ b/usr/src/cmd/ipf/tools/Makefile.tools @@ -48,7 +48,7 @@ ipftest := LDLIBS += -lsocket -lnsl -lmd ipfstat := LDLIBS += -lsocket -lnsl -lkvm -lelf ipmon := LDLIBS += -lsocket -lnsl ipnat := LDLIBS += -lsocket -lnsl -lkvm -lelf -ippool := LDLIBS += -lnsl -lkvm +ippool := LDLIBS += -lsocket -lnsl -lkvm CLEANFILES += $(OBJS) @@ -90,7 +90,7 @@ ipf: $(IPF_OBJS) $(LIBIPF) $(LINK.c) -o ipf $(IPF_OBJS) $(LDLIBS) $(POST_PROCESS) -ipf_y.o: ../ipf_y.c $(COMMONIPF)/ip_fil.h $(COMMONIPF)/ipf.h \ +ipf_y.o: ../ipf_y.c $(COMMONIPF)/netinet/ip_fil.h $(COMMONIPF)/ipf.h \ ../ipf_y.c ../ipf_l.h ../ipf_y.c ../ipf_y.h: ../ipf_y.y @@ -100,11 +100,11 @@ ipf_y.o: ../ipf_y.c $(COMMONIPF)/ip_fil.h $(COMMONIPF)/ipf.h \ sed -e 's/yy/ipf_yy/g' -e 's/y.tab.h/ipf_y.h/' \ ipf.tab.h > ../ipf_y.h -ipf_l.o: ../ipf_l.c $(COMMONIPF)/ip_fil.h $(COMMONIPF)/ipf.h \ +ipf_l.o: ../ipf_l.c $(COMMONIPF)/netinet/ip_fil.h $(COMMONIPF)/ipf.h \ ../ipf_y.h ../ipf_l.h $(COMPILE.c) ../ipf_l.c -o $@ -../ipf_l.c: ../lexer.c $(COMMONIPF)/ipf.h $(COMMONIPF)/ip_fil.h +../ipf_l.c: ../lexer.c $(COMMONIPF)/ipf.h $(COMMONIPF)/netinet/ip_fil.h sed -e 's/yy/ipf_yy/g' -e 's/y.tab.h/ipf_y.h/' \ -e 's/lexer.h/ipf_l.h/' ../lexer.c > $@ @@ -149,7 +149,7 @@ ipnat: $(IPNAT_OBJS) $(LIBIPF) $(LINK.c) -o ipnat $(IPNAT_OBJS) $(LDLIBS) $(POST_PROCESS) -ipnat_y.o: ../ipnat_y.c $(COMMONIPF)/ip_nat.h \ +ipnat_y.o: ../ipnat_y.c $(COMMONIPF)/netinet/ip_nat.h \ ../ipnat_y.h ../ipnat_l.h ../ipnat_y.c ../ipnat_y.h: ../ipnat_y.y @@ -161,10 +161,10 @@ ipnat_y.o: ../ipnat_y.c $(COMMONIPF)/ip_nat.h \ sed -e 's/yy/ipnat_yy/g' -e 's/y.tab.h/ipnat_y.h/' \ ipnat.tab.h > ../ipnat_y.h -ipnat_l.o: ../ipnat_l.c $(COMMONIPF)/ip_nat.h ../ipnat_l.h +ipnat_l.o: ../ipnat_l.c $(COMMONIPF)/netinet/ip_nat.h ../ipnat_l.h $(COMPILE.c) ../ipnat_l.c -o $@ -../ipnat_l.c: ../lexer.c $(COMMONIPF)/ip_nat.h +../ipnat_l.c: ../lexer.c $(COMMONIPF)/netinet/ip_nat.h sed -e 's/yy/ipnat_yy/g' -e 's/y.tab.h/ipnat_y.h/' \ -e 's/lexer.h/ipnat_l.h/' ../lexer.c > $@ @@ -175,7 +175,7 @@ ippool: $(IPPOOL_OBJS) $(LIBIPF) $(LINK.c) -o ippool $(IPPOOL_OBJS) $(LDLIBS) $(POST_PROCESS) -ippool_y.o: ../ippool_y.c $(COMMONIPF)/ip_pool.h \ +ippool_y.o: ../ippool_y.c $(COMMONIPF)/netinet/ip_pool.h \ ../ippool_y.h ../ippool_l.h ../ippool_y.c ../ippool_y.h: ../ippool_y.y @@ -187,10 +187,10 @@ ippool_y.o: ../ippool_y.c $(COMMONIPF)/ip_pool.h \ sed -e 's/yy/ippool_yy/g' -e 's/y.tab.h/ippool_y.h/' \ ippool.tab.h > ../ippool_y.h -ippool_l.o: ../ippool_l.c $(COMMONIPF)/ip_pool.h ../ippool_l.h +ippool_l.o: ../ippool_l.c $(COMMONIPF)/netinet/ip_pool.h ../ippool_l.h $(COMPILE.c) ../ippool_l.c -o $@ -../ippool_l.c: ../lexer.c $(COMMONIPF)/ip_pool.h +../ippool_l.c: ../lexer.c $(COMMONIPF)/netinet/ip_pool.h sed -e 's/yy/ippool_yy/g' -e 's/y.tab.h/ippool_y.h/' \ -e 's/lexer.h/ippool_l.h/' ../lexer.c > $@ @@ -206,7 +206,7 @@ clean: lint: lint_SRCS -%.o: $(SRC)/common/ipf/%.c +%.o: $(SRC)/uts/common/inet/ipf/%.c $(COMPILE.c) $< %.o: ../%.c diff --git a/usr/src/cmd/ipf/tools/ip_fil.c b/usr/src/cmd/ipf/tools/ip_fil.c index ae11de166e..0011968b9a 100644 --- a/usr/src/cmd/ipf/tools/ip_fil.c +++ b/usr/src/cmd/ipf/tools/ip_fil.c @@ -3,26 +3,21 @@ * * See the IPFILTER.LICENCE file for details on licencing. * - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #pragma ident "%Z%%M% %I% %E% SMI" #if !defined(lint) -static const char rcsid[] = "@(#)$Id: ip_fil.c,v 2.121 2003/06/28 17:01:55 darrenr Exp $"; +static const char sccsid[] = "@(#)ip_fil.c 2.41 6/5/96 (C) 1993-2000 Darren Reed"; +static const char rcsid[] = "@(#)$Id: ip_fil.c,v 2.133.2.9 2005/01/08 14:22:18 darrenr Exp $"; #endif #ifndef SOLARIS #define SOLARIS (defined(sun) && (defined(__svr4__) || defined(__SVR4))) #endif -#if defined(KERNEL) || defined(_KERNEL) -# undef KERNEL -# undef _KERNEL -# define KERNEL 1 -# define _KERNEL 1 -#endif #include <sys/param.h> #if defined(__FreeBSD__) && !defined(__FreeBSD_version) # if defined(IPFILTER_LKM) @@ -36,30 +31,20 @@ static const char rcsid[] = "@(#)$Id: ip_fil.c,v 2.121 2003/06/28 17:01:55 darre # endif #endif #include <sys/errno.h> +#if defined(__hpux) && (HPUXREV >= 1111) && !defined(_KERNEL) +# include <sys/kern_svcs.h> +#endif #include <sys/types.h> - -#ifdef _KERNEL -# include <sys/systm.h> -# include <sys/fcntl.h> -#else -# define _KERNEL -# ifdef __OpenBSD__ +#define _KERNEL +#define KERNEL +#ifdef __OpenBSD__ struct file; -# endif - -# include <sys/uio.h> -# undef _KERNEL #endif - +#include <sys/uio.h> +#undef _KERNEL +#undef KERNEL #include <sys/file.h> #include <sys/ioctl.h> - -#include <stdio.h> -#include <string.h> -#include <stdlib.h> -#include <ctype.h> -#include <fcntl.h> - #ifdef __sgi # include <sys/ptimers.h> #endif @@ -73,7 +58,9 @@ struct file; #else # include <sys/filio.h> #endif -#include <sys/protosw.h> +#ifndef linux +# include <sys/protosw.h> +#endif #include <sys/socket.h> #include <stdio.h> @@ -81,6 +68,7 @@ struct file; #include <stdlib.h> #include <ctype.h> #include <fcntl.h> +#include <arpa/inet.h> #ifdef __hpux # define _NET_ROUTE_INCLUDED @@ -98,19 +86,28 @@ struct file; #include <sys/hashing.h> # endif #endif +#if defined(__FreeBSD__) +# include "radix_ipf.h" +#endif #include <net/route.h> #include <netinet/in.h> #if !(defined(__sgi) && !defined(IFF_DRVRLOCK)) /* IRIX < 6 */ && \ - !defined(__hpux) + !defined(__hpux) && !defined(linux) # include <netinet/in_var.h> #endif #include <netinet/in_systm.h> #include <netinet/ip.h> -#include <netinet/ip_var.h> +#if !defined(linux) +# include <netinet/ip_var.h> +#endif #include <netinet/tcp.h> #if defined(__osf__) # include <netinet/tcp_timer.h> #endif +#if defined(__osf__) || defined(__hpux) || defined(__sgi) +# include "radix_ipf_local.h" +# define _RADIX_H_ +#endif #include <netinet/udp.h> #include <netinet/tcpip.h> #include <netinet/ip_icmp.h> @@ -119,15 +116,6 @@ struct file; #ifdef __hpux # undef _NET_ROUTE_INCLUDED #endif -#if SOLARIS2 >= 10 -#include "ip_compat.h" -#include "ip_fil.h" -#include "ip_nat.h" -#include "ip_frag.h" -#include "ip_state.h" -#include "ip_proxy.h" -#include "ip_auth.h" -#else #include "netinet/ip_compat.h" #include "netinet/ip_fil.h" #include "netinet/ip_nat.h" @@ -135,18 +123,13 @@ struct file; #include "netinet/ip_state.h" #include "netinet/ip_proxy.h" #include "netinet/ip_auth.h" -#endif #ifdef IPFILTER_SYNC #include "netinet/ip_sync.h" #endif #ifdef IPFILTER_SCAN #include "netinet/ip_scan.h" #endif -#if SOLARIS2 >= 10 -#include "ip_pool.h" -#else #include "netinet/ip_pool.h" -#endif #ifdef IPFILTER_COMPILED # include "netinet/ip_rules.h" #endif @@ -156,8 +139,8 @@ struct file; #ifdef __hpux struct rtentry; #endif +#include "md5.h" -#include <sys/md5.h> #if !defined(__osf__) extern struct protosw inetsw[]; @@ -168,8 +151,9 @@ static struct ifnet **ifneta = NULL; static int nifs = 0; static int frzerostats __P((caddr_t)); +static void fr_setifpaddr __P((struct ifnet *, char *)); void init_ifp __P((void)); -#if defined(__sgi) && (IRIX < 605) +#if defined(__sgi) && (IRIX < 60500) static int no_output __P((struct ifnet *, struct mbuf *, struct sockaddr *)); static int write_output __P((struct ifnet *, struct mbuf *, @@ -220,18 +204,12 @@ caddr_t data; } - /* * Filter ioctl interface. */ int iplioctl(dev, cmd, data, mode) int dev; -#if defined(__NetBSD__) || defined(__OpenBSD__) || \ - (_BSDI_VERSION >= 199701) || (__FreeBSD_version >= 300000) -u_long cmd; -#else -int cmd; -#endif +ioctlcmd_t cmd; caddr_t data; int mode; { @@ -260,7 +238,8 @@ int mode; } if (unit == IPL_LOGAUTH) { if (fr_running > 0) { - if ((cmd == SIOCADAFR) || (cmd == SIOCRMAFR)) { + if ((cmd == (ioctlcmd_t)SIOCADAFR) || + (cmd == (ioctlcmd_t)SIOCRMAFR)) { if (!(mode & FWRITE)) { error = EPERM; } else { @@ -325,6 +304,15 @@ int mode; error = ipldetach(); } break; + case SIOCIPFSET : + if (!(mode & FWRITE)) { + error = EPERM; + break; + } + case SIOCIPFGETNEXT : + case SIOCIPFGET : + error = fr_ipftune(cmd, (void *)data); + break; case SIOCSETFF : if (!(mode & FWRITE)) error = EPERM; @@ -422,7 +410,7 @@ int mode; if (!(mode & FWRITE)) error = EPERM; else { - frsync(); + frsync(NULL); } break; default : @@ -471,7 +459,7 @@ void *ifp; } -void fr_resolvdest(fdp, v) +void fr_resolvedest(fdp, v) frdest_t *fdp; int v; { @@ -485,7 +473,7 @@ int v; } -#if defined(__sgi) && (IRIX < 605) +#if defined(__sgi) && (IRIX < 60500) static int no_output(ifp, m, s) #else # if TRU64 >= 1885 @@ -504,7 +492,7 @@ struct sockaddr *s; } -#if defined(__sgi) && (IRIX < 605) +#if defined(__sgi) && (IRIX < 60500) static int write_output(ifp, m, s) #else # if TRU64 >= 1885 @@ -528,7 +516,8 @@ struct sockaddr *s; ip = MTOD(mb, ip_t *); #if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \ - (defined(OpenBSD) && (OpenBSD >= 199603)) + (defined(OpenBSD) && (OpenBSD >= 199603)) || defined(linux) || \ + (defined(__FreeBSD__) && (__FreeBSD_version >= 501113)) sprintf(fname, "/tmp/%s", ifp->if_xname); #else sprintf(fname, "/tmp/%s%d", ifp->if_name, ifp->if_unit); @@ -544,20 +533,75 @@ struct sockaddr *s; } +static void fr_setifpaddr(ifp, addr) +struct ifnet *ifp; +char *addr; +{ +#ifdef __sgi + struct in_ifaddr *ifa; +#else + struct ifaddr *ifa; +#endif + +#if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD__) + if (ifp->if_addrlist.tqh_first != NULL) +#else +# ifdef __sgi + if (ifp->in_ifaddr != NULL) +# else + if (ifp->if_addrlist != NULL) +# endif +#endif + return; + + ifa = (struct ifaddr *)malloc(sizeof(*ifa)); +#if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD__) + ifp->if_addrlist.tqh_first = ifa; +#else +# ifdef __sgi + ifp->in_ifaddr = ifa; +# else + ifp->if_addrlist = ifa; +# endif +#endif + + if (ifa != NULL) { + struct sockaddr_in *sin; + +#ifdef __sgi + sin = (struct sockaddr_in *)&ifa->ia_addr; +#else + sin = (struct sockaddr_in *)&ifa->ifa_addr; +#endif + sin->sin_addr.s_addr = inet_addr(addr); + if (sin->sin_addr.s_addr == 0) + abort(); + } +} + struct ifnet *get_unit(name, v) char *name; int v; { - struct ifnet *ifp, **ifa, **old_ifneta; + struct ifnet *ifp, **ifpp, **old_ifneta; + char *addr; #if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \ - (defined(OpenBSD) && (OpenBSD >= 199603)) + (defined(OpenBSD) && (OpenBSD >= 199603)) || defined(linux) || \ + (defined(__FreeBSD__) && (__FreeBSD_version >= 501113)) if (name == NULL) name = "anon0"; - for (ifa = ifneta; ifa && (ifp = *ifa); ifa++) { - if (!strcmp(name, ifp->if_xname)) + addr = strchr(name, '='); + if (addr != NULL) + *addr++ = '\0'; + + for (ifpp = ifneta; ifpp && (ifp = *ifpp); ifpp++) { + if (!strcmp(name, ifp->if_xname)) { + if (addr != NULL) + fr_setifpaddr(ifp, addr); return ifp; + } } #else char *s, ifname[LIFNAMSIZ+1]; @@ -565,10 +609,17 @@ int v; if (name == NULL) name = "anon0"; - for (ifa = ifneta; ifa && (ifp = *ifa); ifa++) { + addr = strchr(name, '='); + if (addr != NULL) + *addr++ = '\0'; + + for (ifpp = ifneta; ifpp && (ifp = *ifpp); ifpp++) { COPYIFNAME(ifp, ifname); - if (!strcmp(name, ifname)) + if (!strcmp(name, ifname)) { + if (addr != NULL) + fr_setifpaddr(ifp, addr); return ifp; + } } #endif @@ -587,7 +638,7 @@ int v; old_ifneta = ifneta; nifs++; ifneta = (struct ifnet **)realloc(ifneta, - (nifs + 1) * sizeof(*ifa)); + (nifs + 1) * sizeof(ifp)); if (!ifneta) { free(old_ifneta); nifs = 0; @@ -603,12 +654,13 @@ int v; ifp = ifneta[nifs - 1]; #if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \ - (defined(OpenBSD) && (OpenBSD >= 199603)) - strncpy(ifp->if_xname, name, sizeof(ifp->if_xname)); + (defined(OpenBSD) && (OpenBSD >= 199603)) || defined(linux) || \ + (defined(__FreeBSD__) && (__FreeBSD_version >= 501113)) + (void) strncpy(ifp->if_xname, name, sizeof(ifp->if_xname)); #else - for (s = name; *s && !isdigit(*s); s++) + for (s = name; *s && !ISDIGIT(*s); s++) ; - if (*s && isdigit(*s)) { + if (*s && ISDIGIT(*s)) { ifp->if_unit = atoi(s); ifp->if_name = (char *)malloc(s - name + 1); if (ifp->if_name == NULL) { @@ -619,7 +671,7 @@ int v; perror("malloc"); exit(1); } - strncpy(ifp->if_name, name, s - name); + (void) strncpy(ifp->if_name, name, s - name); ifp->if_name[s - name] = '\0'; } else { ifp->if_name = strdup(name); @@ -627,6 +679,11 @@ int v; } #endif ifp->if_output = no_output; + + if (addr != NULL) { + fr_setifpaddr(ifp, addr); + } + return ifp; } @@ -636,7 +693,8 @@ struct ifnet *ifp; { static char ifname[LIFNAMSIZ]; -#if defined(__OpenBSD__) || defined(__NetBSD__) +#if defined(__OpenBSD__) || defined(__NetBSD__) || defined(linux) || \ + (defined(__FreeBSD__) && (__FreeBSD_version >= 501113)) sprintf(ifname, "%s", ifp->if_xname); #else sprintf(ifname, "%s%d", ifp->if_name, ifp->if_unit); @@ -648,13 +706,14 @@ struct ifnet *ifp; void init_ifp() { - struct ifnet *ifp, **ifa; + struct ifnet *ifp, **ifpp; char fname[32]; int fd; #if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \ - (defined(OpenBSD) && (OpenBSD >= 199603)) - for (ifa = ifneta; ifa && (ifp = *ifa); ifa++) { + (defined(OpenBSD) && (OpenBSD >= 199603)) || defined(linux) || \ + (defined(__FreeBSD__) && (__FreeBSD_version >= 501113)) + for (ifpp = ifneta; ifpp && (ifp = *ifpp); ifpp++) { ifp->if_output = write_output; sprintf(fname, "/tmp/%s", ifp->if_xname); fd = open(fname, O_WRONLY|O_CREAT|O_EXCL|O_TRUNC, 0600); @@ -665,7 +724,7 @@ void init_ifp() } #else - for (ifa = ifneta; ifa && (ifp = *ifa); ifa++) { + for (ifpp = ifneta; ifpp && (ifp = *ifpp); ifpp++) { ifp->if_output = write_output; sprintf(fname, "/tmp/%s%d", ifp->if_name, ifp->if_unit); fd = open(fname, O_WRONLY|O_CREAT|O_EXCL|O_TRUNC, 0600); @@ -692,7 +751,7 @@ frdest_t *fdp; ip->ip_len = htons((u_short)ip->ip_len); ip->ip_off = htons((u_short)(ip->ip_off | IP_MF)); ip->ip_sum = 0; -#if defined(__sgi) && (IRIX < 605) +#if defined(__sgi) && (IRIX < 60500) (*ifp->if_output)(ifp, (void *)ip, NULL); # if TRU64 >= 1885 (*ifp->if_output)(ifp, (void *)m, NULL, 0, 0); @@ -717,12 +776,13 @@ int type; fr_info_t *fin; int dst; { - verbose("- TCP RST sent\n"); + verbose("- ICMP unreachable sent\n"); return 0; } -void frsync() +void frsync(ifp) +void *ifp; { return; } @@ -860,3 +920,74 @@ fr_info_t *fin; fin->fin_flx |= FI_BAD; } #endif + + +/* + * See above for description, except that all addressing is in user space. + */ +int copyoutptr(src, dst, size) +void *src, *dst; +size_t size; +{ + caddr_t ca; + + bcopy(dst, (char *)&ca, sizeof(ca)); + bcopy(src, ca, size); + return 0; +} + + +/* + * See above for description, except that all addressing is in user space. + */ +int copyinptr(src, dst, size) +void *src, *dst; +size_t size; +{ + caddr_t ca; + + bcopy(src, (char *)&ca, sizeof(ca)); + bcopy(ca, dst, size); + return 0; +} + + +/* + * return the first IP Address associated with an interface + */ +int fr_ifpaddr(v, atype, ifptr, inp, inpmask) +int v, atype; +void *ifptr; +struct in_addr *inp, *inpmask; +{ + struct ifnet *ifp = ifptr; +#ifdef __sgi + struct in_ifaddr *ifa; +#else + struct ifaddr *ifa; +#endif + +#if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD__) + ifa = ifp->if_addrlist.tqh_first; +#else +# ifdef __sgi + ifa = (struct in_ifaddr *)ifp->in_ifaddr; +# else + ifa = ifp->if_addrlist; +# endif +#endif + if (ifa != NULL) { + struct sockaddr_in *sin, mask; + + mask.sin_addr.s_addr = 0xffffffff; + +#ifdef __sgi + sin = (struct sockaddr_in *)&ifa->ia_addr; +#else + sin = (struct sockaddr_in *)&ifa->ifa_addr; +#endif + + return fr_ifpfillv4addr(atype, sin, &mask, inp, inpmask); + } + return 0; +} diff --git a/usr/src/cmd/ipf/tools/ipf.c b/usr/src/cmd/ipf/tools/ipf.c index 1a06567959..a9621ef7df 100644 --- a/usr/src/cmd/ipf/tools/ipf.c +++ b/usr/src/cmd/ipf/tools/ipf.c @@ -3,7 +3,7 @@ * * See the IPFILTER.LICENCE file for details on licencing. * - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -21,20 +21,13 @@ #include "ipf.h" #include <fcntl.h> #include <sys/ioctl.h> -#if SOLARIS2 >= 10 -#include "ipl.h" -#else #include "netinet/ipl.h" -#endif #if !defined(lint) static const char sccsid[] = "@(#)ipf.c 1.23 6/5/96 (C) 1993-2000 Darren Reed"; -static const char rcsid[] = "@(#)$Id: ipf.c,v 1.24 2003/07/01 16:30:47 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id: ipf.c,v 1.35.2.3 2004/12/15 18:27:17 darrenr Exp $"; #endif -#if SOLARIS -static void blockunknown __P((void)); -#endif #if !defined(__SVR4) && defined(__GNUC__) extern char *index __P((const char *, int)); #endif @@ -44,7 +37,7 @@ extern int optind; extern frentry_t *frtop; -void frsync __P((void)); +void ipf_frsync __P((void)); void zerostats __P((void)); int main __P((int, char *[])); @@ -62,8 +55,6 @@ static void usage __P((void)); static int showversion __P((void)); static int get_flags __P((void)); static void ipf_interceptadd __P((int, ioctlfunc_t, void *)); -static void dotuning __P((char *)); -static void printtunable __P((ipftune_t *)); static int fd = -1; static ioctlfunc_t iocfunctions[IPL_LOGSIZE] = { ioctl, ioctl, ioctl, @@ -73,13 +64,9 @@ static ioctlfunc_t iocfunctions[IPL_LOGSIZE] = { ioctl, ioctl, ioctl, static void usage() { - fprintf(stderr, "usage: ipf [-" -#ifdef USE_INET6 - "6" -#endif - "AdDEInoPrsUvVyzZ] %s %s %s %s\n", - "[-l block|pass|nomatch|state|nat]", "[-T optionlist]", - "[-F i|o|a|s|S|u]", "[-f filename]"); + fprintf(stderr, "usage: ipf [-6AdDEInoPrRsvVyzZ] %s %s %s\n", + "[-l block|pass|nomatch|state|nat]", "[-cc] [-F i|o|a|s|S|u]", + "[-f filename] [-T <tuneopts>]"); exit(1); } @@ -93,7 +80,7 @@ char *argv[]; if (argc < 2) usage(); - while ((c = getopt(argc, argv, "6ACdDEf:F:Il:noPrsT:UvVyzZ")) != -1) { + while ((c = getopt(argc, argv, "6Ac:dDEf:F:Il:noPrRsT:vVyzZ")) != -1) { switch (c) { case '?' : @@ -107,11 +94,10 @@ char *argv[]; case 'A' : opts &= ~OPT_INACTIVE; break; -#ifdef USE_OPTIONC - case 'C' : - outputc = 1; + case 'c' : + if (strcmp(optarg, "c") == 0) + outputc = 1; break; -#endif case 'E' : set_state((u_int)1); break; @@ -141,6 +127,9 @@ char *argv[]; case 'P' : ipfname = IPAUTH_NAME; break; + case 'R' : + opts ^= OPT_NORESOLVE; + break; case 'r' : opts ^= OPT_REMOVE; break; @@ -148,13 +137,9 @@ char *argv[]; swapactive(); break; case 'T' : - dotuning(optarg); - break; -#if SOLARIS - case 'U' : - blockunknown(); + if (opendevice(ipfname, 1) >= 0) + ipf_dotuning(fd, optarg, ioctl); break; -#endif case 'v' : opts += OPT_VERBOSE; break; @@ -163,7 +148,7 @@ char *argv[]; exit(1); break; case 'y' : - frsync(); + ipf_frsync(); break; case 'z' : opts ^= OPT_ZERORULEST; @@ -275,7 +260,7 @@ void *ptr; static void packetlogon(opt) char *opt; { - int flag, xfd, logopt; + int flag, xfd, logopt, change = 0; flag = get_flags(); if (flag != 0) { @@ -289,24 +274,35 @@ char *opt; flag |= FF_LOGPASS; if (opts & OPT_VERBOSE) printf("set log flag: pass\n"); + change = 1; } if (strstr(opt, "nomatch")) { flag |= FF_LOGNOMATCH; if (opts & OPT_VERBOSE) printf("set log flag: nomatch\n"); + change = 1; } if (strstr(opt, "block") || index(opt, 'd')) { flag |= FF_LOGBLOCK; if (opts & OPT_VERBOSE) printf("set log flag: block\n"); + change = 1; + } + if (strstr(opt, "none")) { + if (opts & OPT_VERBOSE) + printf("disable all log flags\n"); + change = 1; } - if (opendevice(ipfname, 1) != -2 && (ioctl(fd, SIOCSETFF, &flag) != 0)) - perror("ioctl(SIOCSETFF)"); + if (change == 1) { + if (opendevice(ipfname, 1) != -2 && + (ioctl(fd, SIOCSETFF, &flag) != 0)) + perror("ioctl(SIOCSETFF)"); + } if ((opts & (OPT_DONOTHING|OPT_VERBOSE)) == OPT_VERBOSE) { flag = get_flags(); - printf("log flag is now %#x\n", flag); + printf("log flags are now %#x\n", flag); } if (strstr(opt, "state")) { @@ -360,19 +356,22 @@ char *arg; rem = fl; closedevice(); + if (opendevice(IPSTATE_NAME, 1) == -2) + exit(1); - if (opendevice(IPSTATE_NAME, 1) != -2) { + if (!(opts & OPT_DONOTHING)) { if (use_inet6) { -#ifdef USE_INET6 - if (ioctl(fd, SIOCIPFL6, &fl) == -1) - perror("SIOCIPFL6"); -#endif + if (ioctl(fd, SIOCIPFL6, &fl) == -1) { + perror("ioctl(SIOCIPFL6)"); + exit(1); + } } else { - if (ioctl(fd, SIOCIPFFL, &fl) == -1) - perror("SIOCIPFFL"); + if (ioctl(fd, SIOCIPFFL, &fl) == -1) { + perror("ioctl(SIOCIPFFL)"); + exit(1); + } } } - if ((opts & (OPT_DONOTHING|OPT_VERBOSE)) == OPT_VERBOSE) { printf("remove flags %s (%d)\n", arg, rem); printf("removed %d filter rules\n", fl); @@ -408,15 +407,20 @@ char *arg; fl |= FR_INACTIVE; rem = fl; - if (opendevice(ipfname, 1) != -2) { + if (opendevice(ipfname, 1) == -2) + exit(1); + + if (!(opts & OPT_DONOTHING)) { if (use_inet6) { -#ifdef USE_INET6 - if (ioctl(fd, SIOCIPFL6, &fl) == -1) - perror("SIOCIPFL6"); -#endif + if (ioctl(fd, SIOCIPFL6, &fl) == -1) { + perror("ioctl(SIOCIPFL6)"); + exit(1); + } } else { - if (ioctl(fd, SIOCIPFFL, &fl) == -1) - perror("SIOCIPFFL"); + if (ioctl(fd, SIOCIPFFL, &fl) == -1) { + perror("ioctl(SIOCIPFFL)"); + exit(1); + } } } @@ -440,7 +444,7 @@ static void swapactive() } -void frsync() +void ipf_frsync() { int frsyn = 0; @@ -493,33 +497,6 @@ friostat_t *fp; } -#if SOLARIS -static void blockunknown() -{ - u_32_t flag; - - if (opendevice(ipfname, 1) == -1) - return; - - flag = get_flags(); - if ((opts & (OPT_DONOTHING|OPT_VERBOSE)) == OPT_VERBOSE) - printf("log flag is currently %#x\n", flag); - - flag ^= FF_BLOCKNONIP; - - if (opendevice(ipfname, 1) != -2 && ioctl(fd, SIOCSETFF, &flag)) - perror("ioctl(SIOCSETFF)"); - - if ((opts & (OPT_DONOTHING|OPT_VERBOSE)) == OPT_VERBOSE) { - if (ioctl(fd, SIOCGETFF, &flag)) - perror("ioctl(SIOCGETFF)"); - - printf("log flag is now %#x\n", flag); - } -} -#endif - - static int showversion() { struct friostat fio; @@ -583,82 +560,7 @@ static int showversion() s = "nomatch -> block"; printf("%s all, Logging: %savailable\n", s, fio.f_logging ? "" : "un"); printf("Active list: %d\n", fio.f_active); + printf("Feature mask: %#x\n", fio.f_features); return 0; } - - -static void dotuning(tuneargs) -char *tuneargs; -{ - ipfobj_t obj; - ipftune_t tu; - char *s, *t; - - if (opendevice(ipfname, 1) < 0) - return; - - bzero((char *)&tu, sizeof(tu)); - obj.ipfo_rev = IPFILTER_VERSION; - obj.ipfo_size = sizeof(tu);; - obj.ipfo_ptr = (void *)&tu; - obj.ipfo_type = IPFOBJ_TUNEABLE; - - for (s = strtok(tuneargs, ","); s != NULL; s = strtok(NULL, ",")) { - if (!strcmp(s, "list")) { - while (1) { - if (ioctl(fd, SIOCIPFGETNEXT, &obj) == -1) { - perror("ioctl(SIOCIPFGETNEXT)"); - break; - } - if (tu.ipft_cookie == NULL) - break; - - tu.ipft_name[sizeof(tu.ipft_name) - 1] = '\0'; - printtunable(&tu); - } - } else if ((t = strchr(s, '=')) != NULL) { - *t++ = '\0'; - strncpy(tu.ipft_name, s, sizeof(tu.ipft_name)); - if (sscanf(t, "%lu", &tu.ipft_vlong) == 1) { - if (ioctl(fd, SIOCIPFSET, &obj) == -1) { - perror("ioctl(SIOCIPFSET)"); - return; - } - } else { - fprintf(stderr, "invalid value '%s'\n", s); - return; - } - } else { - strncpy(tu.ipft_name, s, sizeof(tu.ipft_name)); - if (ioctl(fd, SIOCIPFGET, &obj) == -1) { - perror("ioctl(SIOCIPFGET)"); - return; - } - if (tu.ipft_cookie == NULL) - return; - - tu.ipft_name[sizeof(tu.ipft_name) - 1] = '\0'; - printtunable(&tu); - } - } -} - - -static void printtunable(tup) -ipftune_t *tup; -{ - printf("%s\tmin %#lx\tmax %#lx\tcurrent ", - tup->ipft_name, tup->ipft_min, tup->ipft_max); - if (tup->ipft_sz == sizeof(u_long)) - printf("%lu\n", tup->ipft_vlong); - else if (tup->ipft_sz == sizeof(u_int)) - printf("%u\n", tup->ipft_vint); - else if (tup->ipft_sz == sizeof(u_short)) - printf("%hu\n", tup->ipft_vshort); - else if (tup->ipft_sz == sizeof(u_char)) - printf("%u\n", (u_int)tup->ipft_vchar); - else { - printf("sz = %d\n", tup->ipft_sz); - } -} diff --git a/usr/src/cmd/ipf/tools/ipf_y.y b/usr/src/cmd/ipf/tools/ipf_y.y index f1fc0096f0..31af5ef875 100644 --- a/usr/src/cmd/ipf/tools/ipf_y.y +++ b/usr/src/cmd/ipf/tools/ipf_y.y @@ -4,47 +4,36 @@ * * See the IPFILTER.LICENCE file for details on licencing. * - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #pragma ident "%Z%%M% %I% %E% SMI" #include "ipf.h" -#include <netinet/ip_icmp.h> #include <sys/ioctl.h> #include <syslog.h> #ifdef IPFILTER_BPF -# include <net/bpf.h> -# include <pcap-int.h> +# include "pcap-bpf.h" +# define _NET_BPF_H_ # include <pcap.h> #endif -#if SOLARIS2 >= 10 -#include "ip_pool.h" -#include "ip_htable.h" -#include "ipl.h" -#else #include "netinet/ip_pool.h" #include "netinet/ip_htable.h" #include "netinet/ipl.h" -#endif #include "ipf_l.h" #define YYDEBUG 1 #define DOALL(x) for (fr = frc; fr != NULL; fr = fr->fr_next) { x } #define DOREM(x) for (; fr != NULL; fr = fr->fr_next) { x } -#if SOLARIS2 >= 10 -#define VNI "vni" -#define VNISTRLEN 3 -#endif -#define OPTION_LOG 0x1 -#define OPTION_QUICK 0x2 -#define OPTION_DUP 0x4 -#define OPTION_PROUTE 0x8 -#define OPTION_ON 0x10 -#define OPTION_REPLYTO 0x20 -#define OPTION_FROUTE 0x40 +#define OPTION_LOG 0x1 +#define OPTION_QUICK 0x2 +#define OPTION_DUP 0x4 +#define OPTION_PROUTE 0x8 +#define OPTION_ON 0x10 +#define OPTION_REPLYTO 0x20 +#define OPTION_FROUTE 0x40 extern void yyerror __P((char *)); extern int yyparse __P((void)); @@ -56,7 +45,7 @@ extern int yylineNum; static void newrule __P((void)); static void setipftype __P((void)); static u_32_t lookuphost __P((char *)); -static void dobpf __P((char *)); +static void dobpf __P((int, char *)); static void resetaddr __P((void)); static struct alist_s *newalist __P((struct alist_s *)); static u_int makehash __P((struct alist_s *)); @@ -77,14 +66,20 @@ static int nrules = 0; static int newlist = 0; static int added = 0; static int ipffd = -1; +static int ruleopts = 0; static int *yycont = 0; -static int ruleopts = 0; static ioctlfunc_t ipfioctl[IPL_LOGSIZE]; static addfunc_t ipfaddfunc = NULL; -static wordtab_t addrwords[4]; -static wordtab_t maskwords[5]; -static wordtab_t *savewords; -static int set_ipv6_addr = 0; +static struct wordtab ipfwords[95]; +static struct wordtab addrwords[4]; +static struct wordtab maskwords[5]; +static struct wordtab icmpcodewords[17]; +static struct wordtab icmptypewords[16]; +static struct wordtab ipv4optwords[25]; +static struct wordtab ipv4secwords[9]; +static struct wordtab ipv6optwords[8]; +static struct wordtab logwords[33]; +static int set_ipv6_addr = 0; %} %union { @@ -94,6 +89,7 @@ static int set_ipv6_addr = 0; frentry_t fr; frtuc_t *frt; struct alist_s *alist; + u_short port; struct { u_short p1; u_short p2; @@ -106,10 +102,11 @@ static int set_ipv6_addr = 0; union i6addr ip6; }; -%type <num> portnum facility priority icmpcode seclevel secname icmptype +%type <port> portnum +%type <num> facility priority icmpcode seclevel secname icmptype %type <num> opt compare range opttype flagset optlist ipv6hdrlist ipv6hdr -%type <num> portc porteq -%type <ipa> hostname ipv4 ipv4mask +%type <num> portc porteq +%type <ipa> hostname ipv4 ipv4mask ipv4_16 ipv4_24 %type <ip6> ipv6mask %type <ipp> addr ipaddr %type <str> servicename name interfacename @@ -127,13 +124,13 @@ static int set_ipv6_addr = 0; %token IPFY_RETICMP IPFY_RETRST IPFY_RETICMPASDST %token IPFY_IN IPFY_OUT %token IPFY_QUICK IPFY_ON IPFY_OUTVIA IPFY_INVIA -%token IPFY_DUPTO IPFY_TO IPFY_FROUTE IPFY_REPLY_TO +%token IPFY_DUPTO IPFY_TO IPFY_FROUTE IPFY_REPLY_TO IPFY_ROUTETO %token IPFY_TOS IPFY_TTL IPFY_PROTO %token IPFY_HEAD IPFY_GROUP -%token IPFY_AUTH IPFY_PREAUTH IPFY_DIVERT +%token IPFY_AUTH IPFY_PREAUTH %token IPFY_LOG IPFY_BODY IPFY_FIRST IPFY_LEVEL IPFY_ORBLOCK -%token IPFY_LOGTAG IPFY_TAG IPFY_SKIP -%token IPFY_FROM IPFY_ALL IPFY_ANY IPFY_BPF IPFY_POOL IPFY_HASH +%token IPFY_LOGTAG IPFY_MATCHTAG IPFY_SETTAG IPFY_SKIP +%token IPFY_FROM IPFY_ALL IPFY_ANY IPFY_BPFV4 IPFY_BPFV6 IPFY_POOL IPFY_HASH %token IPFY_PPS %token IPFY_ESP IPFY_AH %token IPFY_WITH IPFY_AND IPFY_NOT IPFY_NO IPFY_OPT @@ -146,6 +143,7 @@ static int set_ipv6_addr = 0; %token IPFY_IPOPTS IPFY_SHORT IPFY_NAT IPFY_BADSRC IPFY_LOWTTL IPFY_FRAG %token IPFY_MBCAST IPFY_BAD IPFY_BADNAT IPFY_OOW IPFY_NEWISN IPFY_NOICMPERR %token IPFY_KEEP IPFY_STATE IPFY_FRAGS IPFY_LIMIT IPFY_STRICT IPFY_AGE +%token IPFY_SYNC IPFY_FRAGBODY %token IPFY_IPOPT_NOP IPFY_IPOPT_RR IPFY_IPOPT_ZSU IPFY_IPOPT_MTUP %token IPFY_IPOPT_MTUR IPFY_IPOPT_ENCODE IPFY_IPOPT_TS IPFY_IPOPT_TR %token IPFY_IPOPT_SEC IPFY_IPOPT_LSRR IPFY_IPOPT_ESEC IPFY_IPOPT_CIPSO @@ -212,16 +210,19 @@ assigning: '=' { yyvarnext = 1; } ; -rule: inrule - | outrule +rule: inrule eol + | outrule eol + ; + +eol: | ';' ; inrule: - rulehead markin { ruleopts = 0; } inopts rulemain ruletail + rulehead markin { ruleopts = 0; } inopts rulemain ruletail intag ruletail2 ; outrule: - rulehead markout { ruleopts = 0; } outopts rulemain ruletail + rulehead markout { ruleopts = 0; } outopts rulemain ruletail outtag ruletail2 ; rulehead: @@ -246,15 +247,26 @@ ipfrule: ; bpfrule: - IPFY_BPF '{' YY_STR '}' { dobpf($3); free($3); } + IPFY_BPFV4 '{' YY_STR '}' { dobpf(4, $3); free($3); } + | IPFY_BPFV6 '{' YY_STR '}' { dobpf(6, $3); free($3); } ; ruletail: - keep head group tag pps age new + with keep head group + ; + +ruletail2: + pps age new + ; + +intag: settagin matchtagin + ; + +outtag: settagout matchtagout ; insert: - '@' YY_NUMBER { fr->fr_hits = (U_QUAD_T)$2; } + '@' YY_NUMBER { fr->fr_hits = (U_QUAD_T)$2 + 1; } ; collection: @@ -263,8 +275,6 @@ collection: action: block | IPFY_PASS { fr->fr_flags |= FR_PASS; } - | IPFY_DIVERT YY_NUMBER { fr->fr_flags |= FR_DIVERT; - fr->fr_arg = $2; } | log | IPFY_COUNT { fr->fr_flags |= FR_ACCOUNT; } | auth @@ -429,7 +439,7 @@ lmore: lanother { if (newlist == 1) { } fr = addrule(); if (yycont != NULL) - *yycont = 1; + *yycont = 1; } ; @@ -454,7 +464,7 @@ protox: IPFY_PROTO { setipftype(); yysetdict(NULL); } ; -ip: srcdst flags with icmp +ip: srcdst flags icmp ; group: | IPFY_GROUP YY_STR { DOALL(strncpy(fr->fr_group, $2, \ @@ -473,21 +483,50 @@ head: | IPFY_HEAD YY_STR { DOALL(strncpy(fr->fr_grhead, $2, \ $2);) } ; -tag: | IPFY_TAG YY_NUMBER { DOALL(fr->fr_logtag = $2;) } - | IPFY_TAG '(' taglist ')' +settagin: + | IPFY_SETTAG '(' taginlist ')' + ; -taglist: - tagspec - | taglist ',' tagspec +taginlist: + taginspec + | taginlist ',' taginspec ; -tagspec: - IPFY_NAT '=' YY_STR { DOALL(strncpy(fr->fr_nattag.ipt_tag,\ - $3, 16);); +taginspec: + logtag + |nattag + ; + +nattag: IPFY_NAT '=' YY_STR { DOALL(strncpy(fr->fr_nattag.ipt_tag,\ + $3, IPFTAG_LEN);); free($3); } | IPFY_NAT '=' YY_NUMBER { DOALL(sprintf(fr->fr_nattag.ipt_tag,\ - "%15d", $3);) } - | IPFY_LOG '=' YY_NUMBER { DOALL(fr->fr_logtag = $3;) } + "%d", $3 & 0xffffffff);) } + ; + +logtag: IPFY_LOG '=' YY_NUMBER { DOALL(fr->fr_logtag = $3;) } + ; + +settagout: + | IPFY_SETTAG '(' tagoutlist ')' + ; + +tagoutlist: + tagoutspec + | tagoutlist ',' tagoutspec + ; + +tagoutspec: + logtag + | nattag + ; + +matchtagin: + | IPFY_MATCHTAG '(' tagoutlist ')' + ; + +matchtagout: + | IPFY_MATCHTAG '(' taginlist ')' ; pps: | IPFY_PPS YY_NUMBER { DOALL(fr->fr_pps = $2;) } @@ -517,114 +556,26 @@ on: IPFY_ON onname ; onname: interfacename - { -#if SOLARIS2 >=10 - char *cp; -#endif - strncpy(fr->fr_ifnames[0], $1, sizeof(fr->fr_ifnames[0])); -#if SOLARIS2 >= 10 - if (strncmp(VNI, $1, VNISTRLEN) == 0) { - cp = $1 + VNISTRLEN; - cp += strspn(cp, "0123456789"); - if (*cp == '\0' || *cp == ':') { - fprintf(stderr, "%d: Warning- %s specified. vni" - " is a virtual interface, use a physical" - " interface instead. See vni(7D)\n", - yylineNum, $1); - } - } -#endif + { strncpy(fr->fr_ifnames[0], $1, sizeof(fr->fr_ifnames[0])); free($1); } - | interfacename ',' name - { -#if SOLARIS2 >= 10 - char *cp; -#endif - strncpy(fr->fr_ifnames[0], $1, sizeof(fr->fr_ifnames[0])); -#if SOLARIS2 >= 10 - if (strncmp(VNI, $1, VNISTRLEN) == 0) { - cp = $1 + VNISTRLEN; - cp += strspn(cp, "0123456789"); - if (*cp == '\0' || *cp == ':') { - fprintf(stderr, "%d: Warning- %s specified. vni" - " is a virtual interface, use a physical" - " interface instead. See vni(7D)\n", - yylineNum, $1); - } - } -#endif + | interfacename ',' interfacename + { strncpy(fr->fr_ifnames[0], $1, sizeof(fr->fr_ifnames[0])); free($1); strncpy(fr->fr_ifnames[1], $3, sizeof(fr->fr_ifnames[1])); -#if SOLARIS2 >= 10 - if (strncmp(VNI, $3, VNISTRLEN) == 0) { - cp = $3 + VNISTRLEN; - cp += strspn(cp, "0123456789"); - if (*cp == '\0' || *cp == ':') { - fprintf(stderr, "%d: Warning- %s specified. vni" - " is a virtual interface, use a physical" - " interface instead. See vni(7D)\n", - yylineNum, $3); - } - } -#endif free($3); } ; vianame: - interfacename - { -#if SOLARIS2 >= 10 - char *cp; -#endif - strncpy(fr->fr_ifnames[2], $1, sizeof(fr->fr_ifnames[2])); -#if SOLARIS2 >= 10 - if (strncmp(VNI, $1, VNISTRLEN) == 0) { - cp = $1 + VNISTRLEN; - cp += strspn(cp, "0123456789"); - if (*cp == '\0' || *cp == ':') { - fprintf(stderr, "%d: Warning- %s specified. vni" - " is a virtual interface, use a physical" - " interface instead. See vni(7D)\n", - yylineNum, $1); - } - } -#endif + name + { strncpy(fr->fr_ifnames[2], $1, sizeof(fr->fr_ifnames[2])); free($1); } - | interfacename ',' name - { -#if SOLARIS2 >= 10 - char *cp; -#endif - strncpy(fr->fr_ifnames[2], $1, sizeof(fr->fr_ifnames[2])); -#if SOLARIS2 >= 10 - if (strncmp(VNI, $1, VNISTRLEN) == 0) { - cp = $1 + VNISTRLEN; - cp += strspn(cp, "0123456789"); - if (*cp == '\0' || *cp == ':') { - fprintf(stderr, "%d: Warning- %s specified. vni" - " is a virtual interface, use a physical" - " interface instead. See vni(7D)\n", - yylineNum, $1); - } - } -#endif + | name ',' name + { strncpy(fr->fr_ifnames[2], $1, sizeof(fr->fr_ifnames[2])); free($1); strncpy(fr->fr_ifnames[3], $3, sizeof(fr->fr_ifnames[3])); -#if SOLARIS2 >= 10 - if (strncmp(VNI, $3, VNISTRLEN) == 0) { - cp = $3 + VNISTRLEN; - cp += strspn(cp, "0123456789"); - if (*cp == '\0' || *cp == ':') { - fprintf(stderr, "%d: Warning- %s specified. vni" - " is a virtual interface, use a physical" - " interface instead. See vni(7D)\n", - yylineNum, $3); - } - } -#endif free($3); } ; @@ -633,33 +584,56 @@ dup: IPFY_DUPTO name { strncpy(fr->fr_dif.fd_ifname, $2, sizeof(fr->fr_dif.fd_ifname)); free($2); } - | IPFY_DUPTO name ':' hostname + | IPFY_DUPTO name duptoseparator hostname { strncpy(fr->fr_dif.fd_ifname, $2, sizeof(fr->fr_dif.fd_ifname)); fr->fr_dif.fd_ip = $4; + yyexpectaddr = 0; + free($2); + } + | IPFY_DUPTO name duptoseparator YY_IPV6 + { strncpy(fr->fr_dif.fd_ifname, $2, sizeof(fr->fr_dif.fd_ifname)); + bcopy(&$4, &fr->fr_dif.fd_ip6, sizeof(fr->fr_dif.fd_ip6)); + yyexpectaddr = 0; free($2); } ; +duptoseparator: + ':' { yyexpectaddr = 1; yycont = &yyexpectaddr; resetaddr(); } + ; + froute: IPFY_FROUTE { fr->fr_flags |= FR_FASTROUTE; } ; -proute: IPFY_TO name +proute: routeto name { strncpy(fr->fr_tif.fd_ifname, $2, sizeof(fr->fr_tif.fd_ifname)); free($2); } - | IPFY_TO name ':' hostname + | routeto name duptoseparator hostname { strncpy(fr->fr_tif.fd_ifname, $2, sizeof(fr->fr_tif.fd_ifname)); fr->fr_tif.fd_ip = $4; + yyexpectaddr = 0; + free($2); + } + | routeto name duptoseparator YY_IPV6 + { strncpy(fr->fr_tif.fd_ifname, $2, sizeof(fr->fr_tif.fd_ifname)); + bcopy(&$4, &fr->fr_tif.fd_ip6, sizeof(fr->fr_tif.fd_ip6)); + yyexpectaddr = 0; free($2); } ; +routeto: + IPFY_TO + | IPFY_ROUTETO + ; + replyto: IPFY_REPLY_TO name { strncpy(fr->fr_rif.fd_ifname, $2, sizeof(fr->fr_rif.fd_ifname)); free($2); } - | IPFY_REPLY_TO name ':' hostname + | IPFY_REPLY_TO name duptoseparator hostname { strncpy(fr->fr_rif.fd_ifname, $2, sizeof(fr->fr_rif.fd_ifname)); fr->fr_rif.fd_ip = $4; free($2); @@ -686,7 +660,7 @@ starticmpcode: '(' { yysetdict(icmpcodewords); } ; -srcdst: IPFY_ALL +srcdst: | IPFY_ALL | fromto ; @@ -699,7 +673,7 @@ protocol: } else { int p = getproto($1); if (p == -1) - fprintf(stderr, "protocol unknown: %s, line %d\n", $1, yylineNum); + yyerror("protocol unknown"); DOREM(fr->fr_proto = p; \ fr->fr_mproto = 0xff;) } @@ -730,6 +704,8 @@ from: IPFY_FROM { setipftype(); if (fr == NULL) fr = frc; yyexpectaddr = 1; + if (yydebug) + printf("set yyexpectaddr\n"); yycont = &yyexpectaddr; yysetdict(addrwords); resetaddr(); } @@ -738,6 +714,8 @@ from: IPFY_FROM { setipftype(); to: IPFY_TO { if (fr == NULL) fr = frc; yyexpectaddr = 1; + if (yydebug) + printf("set yyexpectaddr\n"); yycont = &yyexpectaddr; yysetdict(addrwords); resetaddr(); } @@ -751,34 +729,42 @@ andwith: | IPFY_AND { nowith = 0; setipftype(); } ; -flags: | IPFY_FLAGS flagset +flags: | startflags flagset { DOALL(fr->fr_tcpf = $2; fr->fr_tcpfm = FR_TCPFMAX;) } - | IPFY_FLAGS flagset '/' flagset + | startflags flagset '/' flagset { DOALL(fr->fr_tcpf = $2; fr->fr_tcpfm = $4;) } - | IPFY_FLAGS '/' flagset + | startflags '/' flagset { DOALL(fr->fr_tcpf = 0; fr->fr_tcpfm = $3;) } - | IPFY_FLAGS YY_NUMBER + | startflags YY_NUMBER { DOALL(fr->fr_tcpf = $2; fr->fr_tcpfm = FR_TCPFMAX;) } - | IPFY_FLAGS '/' YY_NUMBER + | startflags '/' YY_NUMBER { DOALL(fr->fr_tcpf = 0; fr->fr_tcpfm = $3;) } - | IPFY_FLAGS YY_NUMBER '/' YY_NUMBER + | startflags YY_NUMBER '/' YY_NUMBER { DOALL(fr->fr_tcpf = $2; fr->fr_tcpfm = $4;) } - | IPFY_FLAGS flagset '/' YY_NUMBER + | startflags flagset '/' YY_NUMBER { DOALL(fr->fr_tcpf = $2; fr->fr_tcpfm = $4;) } - | IPFY_FLAGS YY_NUMBER '/' flagset + | startflags YY_NUMBER '/' flagset { DOALL(fr->fr_tcpf = $2; fr->fr_tcpfm = $4;) } ; +startflags: + IPFY_FLAGS { if (frc->fr_type != FR_T_IPF) + yyerror("flags with non-ipf type rule"); + if (frc->fr_proto != IPPROTO_TCP) + yyerror("flags with non-TCP rule"); + } + ; + flagset: YY_STR { $$ = tcpflags($1); free($1); } | YY_HEX { $$ = $1; } ; srcobject: - srcaddr srcport + { yyresetdict(); } fromport + | srcaddr srcport | '!' srcaddr srcport { DOALL(fr->fr_flags |= FR_NOTSRCIP;) } - | fromport ; srcaddr: @@ -840,7 +826,7 @@ srcportlist: ; dstobject: - toport + { yyresetdict(); } toport | dstaddr dstport | '!' dstaddr dstport { DOALL(fr->fr_flags |= FR_NOTDSTIP;) } @@ -960,7 +946,11 @@ maskspace: ipv4mask: ipv4 { $$ = $1; } | YY_HEX { $$.s_addr = htonl($1); } - | YY_NUMBER { ntomask(4, $1, (u_32_t *)&$$); } + | YY_NUMBER { if (($1 >= 0) && ($1 <= 32)) { + ntomask(4, $1, (u_32_t *)&$$); + } else + yyerror("invalid mask"); + } | IPFY_BROADCAST { if (ifpflag == FRI_DYNAMIC) { $$.s_addr = 0; ifpflag = FRI_BROADCAST; @@ -988,7 +978,11 @@ ipv4mask: ; ipv6mask: - YY_NUMBER { ntomask(6, $1, $$.i6); } + YY_NUMBER { if (($1 >= 0) && ($1 <= 128)) { + ntomask(6, $1, $$.i6); + } else + yyerror("invalid mask"); + } | IPFY_BROADCAST { if (ifpflag == FRI_DYNAMIC) { bzero(&$$, sizeof($$)); ifpflag = FRI_BROADCAST; @@ -1174,6 +1168,7 @@ age: | IPFY_AGE YY_NUMBER { DOALL(fr->fr_age[0] = $2; \ keep: | IPFY_KEEP keepstate | IPFY_KEEP keepfrag | IPFY_KEEP keepstate IPFY_KEEP keepfrag + | IPFY_KEEP keepfrag IPFY_KEEP keepstate ; keepstate: @@ -1182,6 +1177,7 @@ keepstate: keepfrag: IPFY_FRAGS fragoptlist { DOALL(fr->fr_flags |= FR_KEEPFRAG;) } + | IPFY_FRAG fragoptlist { DOALL(fr->fr_flags |= FR_KEEPFRAG;) } ; fragoptlist: @@ -1219,34 +1215,46 @@ stateopt: fr->fr_flags |= FR_NEWISN;) } | IPFY_NOICMPERR { DOALL(fr->fr_flags |= FR_NOICMPERR;) } + + | IPFY_SYNC { DOALL(fr->fr_flags |= FR_STATESYNC;) } ; portnum: - servicename { $$ = ntohs(getport(frc, $1)); - if ($$ == -1) - fprintf(stderr, "service unknown: %s, line %d\n", $1, yylineNum); + servicename { if (getport(frc, $1, &($$)) == -1) + yyerror("service unknown"); + else + $$ = ntohs($$); free($1); } - | YY_NUMBER { $$ = $1; } + | YY_NUMBER { if ($1 > 65535) /* Unsigned */ + yyerror("invalid port number"); + else + $$ = $1; + } ; withlist: withopt | withlist withopt + | withlist ',' withopt ; withopt: opttype { DOALL(fr->fr_flx |= $1; fr->fr_mflx |= $1;) } | notwith opttype - { DOALL(fr->fr_mflx |= $2;) } - | IPFY_OPT ipopts - | notwith IPFY_OPT ipopts - | startv6hdrs ipv6hdrs + { DOALL(fr->fr_mflx |= $2;) } + | ipopt ipopts { yyresetdict(); } + | notwith ipopt ipopts { yyresetdict(); } + | startv6hdrs ipv6hdrs { yyresetdict(); } + ; + +ipopt: IPFY_OPT { yysetdict(ipv4optwords); } ; startv6hdrs: IPF6_V6HDRS { if (use_inet6 == 0) yyerror("only available with IPv6"); + yysetdict(ipv6optwords); } ; @@ -1264,6 +1272,8 @@ opttype: | IPFY_BADSRC { $$ = FI_BADSRC; } | IPFY_LOWTTL { $$ = FI_LOWTTL; } | IPFY_FRAG { $$ = FI_FRAG; } + | IPFY_FRAGBODY { $$ = FI_FRAGBODY; } + | IPFY_FRAGS { $$ = FI_FRAG; } | IPFY_MBCAST { $$ = FI_MBCAST; } | IPFY_MULTICAST { $$ = FI_MULTICAST; } | IPFY_BROADCAST { $$ = FI_BROADCAST; } @@ -1374,14 +1384,19 @@ opt: | IPFY_IPOPT_NSAPA { $$ = getoptbyvalue(IPOPT_NSAPA); } | IPFY_IPOPT_RTRALRT { $$ = getoptbyvalue(IPOPT_RTRALRT); } | IPFY_IPOPT_UMP { $$ = getoptbyvalue(IPOPT_UMP); } - | IPFY_SECCLASS secname + | setsecclass secname { DOALL(fr->fr_mip.fi_secmsk |= $2; if (!nowith) fr->fr_ip.fi_secmsk |= $2;) $$ = 0; + yyresetdict(); } ; +setsecclass: + IPFY_SECCLASS { yysetdict(ipv4secwords); } + ; + ipv6hdr: IPFY_AH { $$ = getv6optbyvalue(IPPROTO_AH); } | IPFY_IPV6OPT_DSTOPTS { $$ = getv6optbyvalue(IPPROTO_DSTOPTS); } @@ -1439,8 +1454,7 @@ priority: ; compare: - '=' { $$ = FR_EQUAL; } - | YY_CMP_EQ { $$ = FR_EQUAL; } + YY_CMP_EQ { $$ = FR_EQUAL; } | YY_CMP_NE { $$ = FR_NEQUAL; } | YY_CMP_LT { $$ = FR_LESST; } | YY_CMP_LE { $$ = FR_LESSTE; } @@ -1460,32 +1474,51 @@ servicename: interfacename: YY_STR { $$ = $1; } | YY_STR ':' YY_NUMBER { $$ = $1; -#if SOLARIS2 >= 10 - if (strncmp(VNI, $1, VNISTRLEN) != 0) -#endif fprintf(stderr, "%d: Logical interface %s:%d unsupported, " - "use the physical interface %s instead.\n", - yylineNum, $1, $3, $1); + "use the physical interface %s instead.\n", + yylineNum, $1, $3, $1); } ; name: YY_STR { $$ = $1; } ; -ipv4: YY_NUMBER '.' YY_NUMBER '.' YY_NUMBER '.' YY_NUMBER - { if ($1 > 255 || $3 > 255 || $5 > 255 || $7 > 255) { +ipv4_16: + YY_NUMBER '.' YY_NUMBER + { if ($1 > 255 || $3 > 255) { yyerror("Invalid octet string for IP address"); return 0; } - $$.s_addr = ($1 << 24) | ($3 << 16) | ($5 << 8) | $7; + $$.s_addr = ($1 << 24) | ($3 << 16); $$.s_addr = htonl($$.s_addr); } ; + +ipv4_24: + ipv4_16 '.' YY_NUMBER + { if ($3 > 255) { + yyerror("Invalid octet string for IP address"); + return 0; + } + $$.s_addr |= htonl($3 << 8); + } + ; + +ipv4: ipv4_24 '.' YY_NUMBER + { if ($3 > 255) { + yyerror("Invalid octet string for IP address"); + return 0; + } + $$.s_addr |= htonl($3); + } + | ipv4_24 + | ipv4_16 + ; + %% -static struct wordtab ipfwords[] = { - { "addext", IPFY_IPOPT_ADDEXT }, +static struct wordtab ipfwords[95] = { { "age", IPFY_AGE }, { "ah", IPFY_AH }, { "all", IPFY_ALL }, @@ -1497,58 +1530,43 @@ static struct wordtab ipfwords[] = { { "bcast", IPFY_BROADCAST }, { "block", IPFY_BLOCK }, { "body", IPFY_BODY }, - { "bpf", IPFY_BPF }, + { "bpf-v4", IPFY_BPFV4 }, +#ifdef USE_INET6 + { "bpf-v6", IPFY_BPFV6 }, +#endif { "call", IPFY_CALL }, - { "cipso", IPFY_IPOPT_CIPSO }, { "code", IPFY_ICMPCODE }, - { "confid", IPFY_SEC_CONF }, { "count", IPFY_COUNT }, - { "divert", IPFY_DIVERT }, - { "dps", IPFY_IPOPT_DPS }, - { "dstopts", IPFY_IPV6OPT_DSTOPTS }, { "dup-to", IPFY_DUPTO }, - { "e-sec", IPFY_IPOPT_ESEC }, - { "eip", IPFY_IPOPT_EIP }, - { "encode", IPFY_IPOPT_ENCODE }, { "eq", YY_CMP_EQ }, { "esp", IPFY_ESP }, { "fastroute", IPFY_FROUTE }, { "first", IPFY_FIRST }, - { "finn", IPFY_IPOPT_FINN }, - { "frag", IPFY_FRAG }, { "flags", IPFY_FLAGS }, + { "frag", IPFY_FRAG }, + { "frag-body", IPFY_FRAGBODY }, { "frags", IPFY_FRAGS }, { "from", IPFY_FROM }, { "ge", YY_CMP_GE }, { "group", IPFY_GROUP }, { "gt", YY_CMP_GT }, { "head", IPFY_HEAD }, - { "hopopts", IPFY_IPV6OPT_HOPOPTS }, - { "host-preced", IPFY_ICMPC_HSTPRE }, - { "host-prohib", IPFY_ICMPC_HSTPRO }, - { "host-tos", IPFY_ICMPC_HSTTOS }, - { "host-unk", IPFY_ICMPC_HSTUNK }, - { "host-unr", IPFY_ICMPC_HSTUNR }, { "icmp", IPFY_ICMP }, { "icmp-type", IPFY_ICMPTYPE }, - { "imitd", IPFY_IPOPT_IMITD }, { "in", IPFY_IN }, { "in-via", IPFY_INVIA }, { "ipopt", IPFY_IPOPTS }, { "ipopts", IPFY_IPOPTS }, - { "ipv6", IPFY_IPV6OPT_IPV6 }, { "keep", IPFY_KEEP }, { "le", YY_CMP_LE }, { "level", IPFY_LEVEL }, { "limit", IPFY_LIMIT }, { "log", IPFY_LOG }, { "lowttl", IPFY_LOWTTL }, - { "lsrr", IPFY_IPOPT_LSRR }, { "lt", YY_CMP_LT }, { "mask", IPFY_MASK }, + { "match-tag", IPFY_MATCHTAG }, { "mbcast", IPFY_MBCAST }, - { "mtup", IPFY_IPOPT_MTUP }, - { "mtur", IPFY_IPOPT_MTUR }, { "multicast", IPFY_MULTICAST }, { "nat", IPFY_NAT }, { "ne", YY_CMP_NE }, @@ -1556,11 +1574,8 @@ static struct wordtab ipfwords[] = { { "newisn", IPFY_NEWISN }, { "no", IPFY_NO }, { "no-icmp-err", IPFY_NOICMPERR }, - { "none", IPFY_IPV6OPT_NONE }, - { "nop", IPFY_IPOPT_NOP }, { "now", IPFY_NOW }, { "not", IPFY_NOT }, - { "nsapa", IPFY_IPOPT_NSAPA }, { "oow", IPFY_OOW }, { "on", IPFY_ON }, { "opt", IPFY_OPT }, @@ -1574,42 +1589,26 @@ static struct wordtab ipfwords[] = { { "proto", IPFY_PROTO }, { "quick", IPFY_QUICK }, { "reply-to", IPFY_REPLY_TO }, - { "reserv-1", IPFY_SEC_RSV1 }, - { "reserv-2", IPFY_SEC_RSV2 }, - { "reserv-3", IPFY_SEC_RSV3 }, - { "reserv-4", IPFY_SEC_RSV4 }, { "return-icmp", IPFY_RETICMP }, { "return-icmp-as-dest", IPFY_RETICMPASDST }, { "return-rst", IPFY_RETRST }, - { "routing", IPFY_IPV6OPT_ROUTING }, - { "rr", IPFY_IPOPT_RR }, - { "rtralrt", IPFY_IPOPT_RTRALRT }, - { "satid", IPFY_IPOPT_SATID }, - { "sdb", IPFY_IPOPT_SDB }, - { "sec", IPFY_IPOPT_SEC }, + { "route-to", IPFY_ROUTETO }, { "sec-class", IPFY_SECCLASS }, - { "secret", IPFY_SEC_SEC }, + { "set-tag", IPFY_SETTAG }, { "skip", IPFY_SKIP }, { "short", IPFY_SHORT }, - { "ssrr", IPFY_IPOPT_SSRR }, { "state", IPFY_STATE }, + { "state-age", IPFY_AGE }, { "strict", IPFY_STRICT }, - { "tag", IPFY_TAG }, + { "sync", IPFY_SYNC }, { "tcp", IPFY_TCP }, { "tcp-udp", IPFY_TCPUDP }, { "tos", IPFY_TOS }, - { "topsecret", IPFY_SEC_TS }, { "to", IPFY_TO }, - { "tr", IPFY_IPOPT_TR }, - { "ts", IPFY_IPOPT_TS }, { "ttl", IPFY_TTL }, { "udp", IPFY_UDP }, - { "ump", IPFY_IPOPT_UMP }, - { "unclass", IPFY_SEC_UNC }, { "v6hdrs", IPF6_V6HDRS }, - { "visa", IPFY_IPOPT_VISA }, { "with", IPFY_WITH }, - { "zsu", IPFY_IPOPT_ZSU }, { NULL, 0 } }; @@ -1667,7 +1666,58 @@ static struct wordtab icmpcodewords[17] = { { NULL, 0 }, }; -static struct wordtab logwords[] = { +static struct wordtab ipv4optwords[25] = { + { "addext", IPFY_IPOPT_ADDEXT }, + { "cipso", IPFY_IPOPT_CIPSO }, + { "dps", IPFY_IPOPT_DPS }, + { "e-sec", IPFY_IPOPT_ESEC }, + { "eip", IPFY_IPOPT_EIP }, + { "encode", IPFY_IPOPT_ENCODE }, + { "finn", IPFY_IPOPT_FINN }, + { "imitd", IPFY_IPOPT_IMITD }, + { "lsrr", IPFY_IPOPT_LSRR }, + { "mtup", IPFY_IPOPT_MTUP }, + { "mtur", IPFY_IPOPT_MTUR }, + { "nop", IPFY_IPOPT_NOP }, + { "nsapa", IPFY_IPOPT_NSAPA }, + { "rr", IPFY_IPOPT_RR }, + { "rtralrt", IPFY_IPOPT_RTRALRT }, + { "satid", IPFY_IPOPT_SATID }, + { "sdb", IPFY_IPOPT_SDB }, + { "sec", IPFY_IPOPT_SEC }, + { "ssrr", IPFY_IPOPT_SSRR }, + { "tr", IPFY_IPOPT_TR }, + { "ts", IPFY_IPOPT_TS }, + { "ump", IPFY_IPOPT_UMP }, + { "visa", IPFY_IPOPT_VISA }, + { "zsu", IPFY_IPOPT_ZSU }, + { NULL, 0 }, +}; + +static struct wordtab ipv4secwords[9] = { + { "confid", IPFY_SEC_CONF }, + { "reserv-1", IPFY_SEC_RSV1 }, + { "reserv-2", IPFY_SEC_RSV2 }, + { "reserv-3", IPFY_SEC_RSV3 }, + { "reserv-4", IPFY_SEC_RSV4 }, + { "secret", IPFY_SEC_SEC }, + { "topsecret", IPFY_SEC_TS }, + { "unclass", IPFY_SEC_UNC }, + { NULL, 0 }, +}; + +static struct wordtab ipv6optwords[8] = { + { "dstopts", IPFY_IPV6OPT_DSTOPTS }, + { "esp", IPFY_ESP }, + { "frag", IPFY_FRAG }, + { "hopopts", IPFY_IPV6OPT_HOPOPTS }, + { "ipv6", IPFY_IPV6OPT_IPV6 }, + { "none", IPFY_IPV6OPT_NONE }, + { "routing", IPFY_IPV6OPT_ROUTING }, + { NULL, 0 }, +}; + +static struct wordtab logwords[33] = { { "kern", IPFY_FAC_KERN }, { "user", IPFY_FAC_USER }, { "mail", IPFY_FAC_MAIL }, @@ -1892,46 +1942,74 @@ char *name; } if (gethost(name, &addr) == -1) { + fprintf(stderr, "unknown name \"%s\"\n", name); return 0; } return addr; } -static void dobpf(phrase) +static void dobpf(v, phrase) +int v; char *phrase; { #ifdef IPFILTER_BPF struct bpf_program bpf; struct pcap *p; +#endif + fakebpf_t *fb; u_32_t l; char *s; int i; for (fr = frc; fr != NULL; fr = fr->fr_next) { if (fr->fr_type != FR_T_NONE) { - fprintf(stderr, "cannoy mix IPF and BPF matching\n"); + fprintf(stderr, "cannot mix IPF and BPF matching\n"); return; } - fr->fr_type = FR_T_IPF; + fr->fr_v = v; + fr->fr_type = FR_T_BPFOPC; if (!strncmp(phrase, "\"0x", 2)) { phrase++; - fr->fr_data = malloc(4); - if (fr->fr_data == NULL) + fb = malloc(sizeof(fakebpf_t)); + if (fb == NULL) yyerror("sorry, out of memory"); - for (i = 0, s = strtok(phrase, " \r\n\t"; s != NULL; + for (i = 0, s = strtok(phrase, " \r\n\t"); s != NULL; s = strtok(NULL, " \r\n\t"), i++) { - fr->fr_data = realloc(fr->fr_data, (i + 1) * 4); - if (fr->fr_data == NULL) + fb = realloc(fb, (i / 4 + 1) * sizeof(*fb)); + if (fb == NULL) yyerror("sorry, out of memory"); l = (u_32_t)strtol(s, NULL, 0); - ((u_32_t *)fr->fr_data)[i] = l; + switch (i & 3) + { + case 0 : + fb[i / 4].fb_c = l & 0xffff; + break; + case 1 : + fb[i / 4].fb_t = l & 0xff; + break; + case 2 : + fb[i / 4].fb_f = l & 0xff; + break; + case 3 : + fb[i / 4].fb_k = l; + break; + } } + if ((i & 3) != 0) { + fprintf(stderr, + "Odd number of bytes in BPF code\n"); + exit(1); + } + i--; + fr->fr_dsize = (i / 4 + 1) * sizeof(*fb); + fr->fr_data = fb; return; } +#ifdef IPFILTER_BPF bzero((char *)&bpf, sizeof(bpf)); p = pcap_open_dead(DLT_RAW, 1); if (!p) { @@ -1939,29 +2017,32 @@ char *phrase; return; } - if (pcap_compile(p, &bpf, phrase, 1, 0xffffffff) { + if (pcap_compile(p, &bpf, phrase, 1, 0xffffffff)) { pcap_perror(p, "ipf"); pcap_close(p); - fprintf(stderr, "pcap parsing failed\n"); + fprintf(stderr, "pcap parsing failed (%s)\n", phrase); return; } pcap_close(p); fr->fr_dsize = bpf.bf_len * sizeof(struct bpf_insn); - fr->fr_data = malloc(bpf.bf_len); + fr->fr_data = malloc(fr->fr_dsize); if (fr->fr_data == NULL) yyerror("sorry, out of memory"); - bcopy((char *)bpf.bf_insns, fr->fr_data, bpf.bf_len); + bcopy((char *)bpf.bf_insns, fr->fr_data, fr->fr_dsize); if (!bpf_validate(fr->fr_data, bpf.bf_len)) { fprintf(stderr, "BPF validation failed\n"); return; } +#endif } +#ifdef IPFILTER_BPF if (opts & OPT_DEBUG) bpf_dump(&bpf, 0); #else - fprintf(stderr, "BPF expressions for matching not supported\n"); + fprintf(stderr, "BPF filter expressions not supported\n"); + exit(1); #endif } @@ -2087,7 +2168,7 @@ int fd; ioctlfunc_t ioctlfunc; void *ptr; { - u_int add, del; + ioctlcmd_t add, del; frentry_t *fr; ipfobj_t obj; @@ -2148,7 +2229,7 @@ void *ptr; } } else if ((opts & OPT_REMOVE) != 0) { if ((*ioctlfunc)(fd, del, (void *)&obj) == -1) { - if ((opts & OPT_DONOTHING) == 0) { + if ((opts & OPT_DONOTHING) != 0) { fprintf(stderr, "%d:", yylineNum); perror("ioctl(delete rule)"); } @@ -2157,23 +2238,22 @@ void *ptr; if ((*ioctlfunc)(fd, add, (void *)&obj) == -1) { if (!(opts & OPT_DONOTHING)) { fprintf(stderr, "%d:", yylineNum); - fprintf(stderr,"ioctl(add/insert rule) failed: rule exists\n"); + perror("ioctl(add/insert rule)"); } } } } - static void setsyslog() { - savewords = yysettab(logwords); + yysetdict(logwords); yybreakondot = 1; } static void unsetsyslog() { - yysettab(savewords); + yyresetdict(); yybreakondot = 0; } @@ -2182,7 +2262,6 @@ static void fillgroup(fr) frentry_t *fr; { frentry_t *f; - int i; for (f = frold; f != NULL; f = f->fr_next) if (strncmp(f->fr_grhead, fr->fr_group, FR_GROUPLEN) == 0) @@ -2192,7 +2271,9 @@ frentry_t *fr; /* * Only copy down matching fields if the rules are of the same type - * and are of ipf type. + * and are of ipf type. The only fields that are copied are those + * that impact the rule parsing itself, eg. need for knowing what the + * protocol should be for rules with port comparisons in them. */ if (f->fr_type != fr->fr_type || f->fr_type != FR_T_IPF) return; @@ -2205,36 +2286,7 @@ frentry_t *fr; if (fr->fr_proto == 0 && f->fr_proto != 0) fr->fr_proto = f->fr_proto; - if (fr->fr_proto == IPPROTO_TCP) { - if (fr->fr_tcpfm == 0 && f->fr_tcpfm != 0) - fr->fr_tcpfm = f->fr_tcpfm; - if (fr->fr_tcpf == 0 && f->fr_tcpf != 0) - fr->fr_tcpf = f->fr_tcpf; - } - - if (fr->fr_proto == IPPROTO_ICMP) { - if (fr->fr_icmpm == 0 && f->fr_icmpm != 0) - fr->fr_icmpm = f->fr_icmpm; - if (fr->fr_icmp == 0 && f->fr_icmp != 0) - fr->fr_icmp = f->fr_icmp; - } - - if (fr->fr_optbits == 0 && f->fr_optbits != 0) - fr->fr_optbits = f->fr_optbits; - if (fr->fr_optmask == 0 && f->fr_optmask != 0) - fr->fr_optmask = f->fr_optmask; - if (fr->fr_secbits == 0 && f->fr_secbits != 0) - fr->fr_secbits = f->fr_secbits; - if (fr->fr_secmask == 0 && f->fr_secmask != 0) - fr->fr_secmask = f->fr_secmask; - if (fr->fr_authbits == 0 && f->fr_authbits != 0) - fr->fr_authbits = f->fr_authbits; - if (fr->fr_authmask == 0 && f->fr_authmask != 0) - fr->fr_authmask = f->fr_authmask; - - for (i = 0; i < 3; i++) { - if (*f->fr_ifnames[i] != '\0' && *fr->fr_ifnames[i] == '\0') - strncpy(fr->fr_ifnames[i], f->fr_ifnames[i], - sizeof(f->fr_ifnames[i])); - } + if ((fr->fr_mproto == 0) && ((fr->fr_flx & FI_TCPUDP) == 0) && + ((f->fr_flx & FI_TCPUDP) != 0)) + fr->fr_flx |= FI_TCPUDP; } diff --git a/usr/src/cmd/ipf/tools/ipfcomp.c b/usr/src/cmd/ipf/tools/ipfcomp.c index 05e0202d73..f09bfd314f 100644 --- a/usr/src/cmd/ipf/tools/ipfcomp.c +++ b/usr/src/cmd/ipf/tools/ipfcomp.c @@ -5,7 +5,7 @@ */ #if !defined(lint) static const char sccsid[] = "@(#)ip_fil.c 2.41 6/5/96 (C) 1993-2000 Darren Reed"; -static const char rcsid[] = "@(#)$Id: ipfcomp.c,v 1.19 2003/04/09 19:04:33 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id: ipfcomp.c,v 1.24.2.2 2004/04/28 10:34:44 darrenr Exp $"; #endif #include "ipf.h" @@ -95,7 +95,9 @@ frentry_t *fr; fprintf(fp, "#include <sys/types.h>\n"); fprintf(fp, "#include <sys/time.h>\n"); fprintf(fp, "#include <sys/socket.h>\n"); - fprintf(fp, "#include <sys/systm.h>\n"); + fprintf(fp, "#if !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__sgi)\n"); + fprintf(fp, "# include <sys/systm.h>\n"); + fprintf(fp, "#endif\n"); fprintf(fp, "#include <sys/errno.h>\n"); fprintf(fp, "#include <sys/param.h>\n"); fprintf(fp, @@ -113,9 +115,14 @@ frentry_t *fr; fprintf(fp, "#include <netinet/in_systm.h>\n"); fprintf(fp, "#include <netinet/ip.h>\n"); fprintf(fp, "#include <netinet/tcp.h>\n"); - fprintf(fp, "#include \"ip_compat.h\"\n"); - fprintf(fp, "#include \"ip_fil.h\"\n\n"); - fprintf(fp, "#include \"ip_rules.h\"\n\n"); + fprintf(fp, "#include \"netinet/ip_compat.h\"\n"); + fprintf(fp, "#include \"netinet/ip_fil.h\"\n\n"); + fprintf(fp, "#include \"netinet/ip_rules.h\"\n\n"); + fprintf(fp, "#ifndef _KERNEL\n"); + fprintf(fp, "# include <string.h>\n"); + fprintf(fp, "#endif /* _KERNEL */\n"); + fprintf(fp, "\n"); + fprintf(fp, "#ifdef IPFILTER_COMPILED\n"); } addrule(fp, fr); @@ -152,18 +159,9 @@ frentry_t *fr; int i; f = (frentry_t *)malloc(sizeof(*f)); - if (f == NULL) { - fprintf(stderr, "out of memory\n"); - exit(1); - } - bcopy((char *)fr, (char *)f, sizeof(*fr)); if (fr->fr_ipf) { f->fr_ipf = (fripf_t *)malloc(sizeof(*f->fr_ipf)); - if (f->fr_ipf == NULL) { - fprintf(stderr, "out of memory\n"); - exit(1); - } bcopy((char *)fr->fr_ipf, (char *)f->fr_ipf, sizeof(*fr->fr_ipf)); } @@ -176,10 +174,6 @@ frentry_t *fr; if (g == NULL) { g = (frgroup_t *)calloc(1, sizeof(*g)); - if (g == NULL) { - fprintf(stderr, "out of memory\n"); - exit(1); - } g->fg_next = groups; groups = g; g->fg_head = f; @@ -220,10 +214,6 @@ static u_long ipf%s_rule_data_%s_%u[] = {\n", break; if (g == NULL) { g = (frgroup_t *)calloc(1, sizeof(*g)); - if (g == NULL) { - fprintf(stderr, "out of memory\n"); - exit(1); - } g->fg_next = groups; groups = g; g->fg_head = f; @@ -332,7 +322,9 @@ frentry_t *fr; } } emittail(); + fprintf(cfile, "#endif /* IPFILTER_COMPILED */\n"); } + } @@ -723,7 +715,7 @@ u_int incount, outcount; /* * print out C code that implements a filter rule. - */ + */ for (; i < FRC_MAX; i++) { switch(m[i].c) { @@ -941,10 +933,6 @@ u_int incount, outcount; } if (n == NULL) n = (mc_t *)malloc(sizeof(*n) * FRC_MAX); - if (n == NULL) { - fprintf(stderr, "out of memory\n"); - exit(1); - } bcopy((char *)m, (char *)n, sizeof(*n) * FRC_MAX); sin = in; } @@ -958,10 +946,6 @@ int dir; if (m == NULL) m = (mc_t *)calloc(1, sizeof(*m) * FRC_MAX); - if (m == NULL) { - fprintf(stderr, "out of memory\n"); - exit(1); - } for (g = groups; g != NULL; g = g->fg_next) { if ((dir == 0) && ((g->fg_flags & FR_INQUE) != 0)) @@ -1309,6 +1293,9 @@ int ipfrule_add_%s_%s()\n", instr, group); fp->fr_flags = FR_%sQUE|FR_NOMATCH;\n\ fp->fr_data = (void *)ipf_rules_%s_%s[0];\n", (in != 0) ? "IN" : "OUT", instr, group); + fprintf(fp, "\ + fp->fr_dsize = sizeof(ipf_rules_%s_%s[0]);\n", + instr, group); fprintf(fp, "\ fp->fr_v = 4;\n\ diff --git a/usr/src/cmd/ipf/tools/ipfs.c b/usr/src/cmd/ipf/tools/ipfs.c index 91ee4498ef..e8a5148143 100644 --- a/usr/src/cmd/ipf/tools/ipfs.c +++ b/usr/src/cmd/ipf/tools/ipfs.c @@ -3,7 +3,7 @@ * * See the IPFILTER.LICENCE file for details on licencing. * - * Copyright 2003 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -45,9 +45,10 @@ #include <arpa/nameser.h> #include <resolv.h> #include "ipf.h" +#include "netinet/ipl.h" #if !defined(lint) -static const char rcsid[] = "@(#)$Id: ipfs.c,v 1.9 2003/05/17 09:47:35 darrenr Exp $"; +static const char rcsid[] = "@(#)Id: ipfs.c,v 1.12 2003/12/01 01:56:53 darrenr Exp"; #endif #ifndef IPF_SAVEDIR @@ -254,7 +255,7 @@ char *argv[]; set = 1; break; case 'r' : - if ((ns >= 0) || dirname || (rw != -1)) + if (dirname || (rw != -1) || (ns == -1)) usage(); rw = 0; set = 1; @@ -389,6 +390,7 @@ int fd; char *file; { ipstate_save_t ips, *ipsp; + ipfobj_t obj; int wfd = -1; if (!file) @@ -402,12 +404,19 @@ char *file; } ipsp = &ips; + bzero((char *)&obj, sizeof(obj)); bzero((char *)ipsp, sizeof(ips)); + obj.ipfo_rev = IPFILTER_VERSION; + obj.ipfo_size = sizeof(*ipsp); + obj.ipfo_type = IPFOBJ_STATESAVE; + obj.ipfo_ptr = ipsp; + do { + if (opts & OPT_VERBOSE) printf("Getting state from addr %p\n", ips.ips_next); - if (ioctl(fd, SIOCSTGET, &ipsp)) { + if (ioctl(fd, SIOCSTGET, &obj)) { if (errno == ENOENT) break; perror("state:SIOCSTGET"); @@ -434,6 +443,7 @@ char *file; { ipstate_save_t ips, *is, *ipshead = NULL, *is1, *ipstail = NULL; int sfd = -1, i; + ipfobj_t obj; if (!file) file = IPF_STATEFILE; @@ -460,8 +470,8 @@ char *file; if (i == 0) break; if (i != sizeof(ips)) { - fprintf(stderr, "incomplete read: %d != %d\n", i, - (int)sizeof(ips)); + fprintf(stderr, "state:incomplete read: %d != %d\n", + i, (int)sizeof(ips)); close(sfd); return 1; } @@ -502,6 +512,10 @@ char *file; close(sfd); + obj.ipfo_rev = IPFILTER_VERSION; + obj.ipfo_size = sizeof(*is); + obj.ipfo_type = IPFOBJ_STATESAVE; + for (is = ipshead; is; is = is->ips_next) { if (opts & OPT_VERBOSE) printf("Loading new state table entry\n"); @@ -509,8 +523,10 @@ char *file; if (opts & OPT_VERBOSE) printf("Loading new filter rule\n"); } + + obj.ipfo_ptr = is; if (!(opts & OPT_DONOTHING)) - if (ioctl(fd, SIOCSTPUT, &is)) { + if (ioctl(fd, SIOCSTPUT, &obj)) { perror("SIOCSTPUT"); return 1; } @@ -532,9 +548,12 @@ int readnat(fd, file) int fd; char *file; { - nat_save_t ipn, *in, *ipnhead, *in1, *ipntail, *ipnp; + nat_save_t ipn, *in, *ipnhead = NULL, *in1, *ipntail = NULL; + ipfobj_t obj; int nfd, i; nat_t *nat; + char *s; + int n; nfd = -1; in = NULL; @@ -552,7 +571,6 @@ char *file; } bzero((char *)&ipn, sizeof(ipn)); - ipnp = &ipn; /* * 1. Read all state information in. @@ -567,42 +585,36 @@ char *file; if (i == 0) break; if (i != sizeof(ipn)) { - fprintf(stderr, "incomplete read: %d != %d\n", i, - (int)sizeof(ipn)); + fprintf(stderr, "nat:incomplete read: %d != %d\n", + i, (int)sizeof(ipn)); close(nfd); return 1; } - if (ipn.ipn_dsize > 0) { - char *s = ipnp->ipn_data; - int n = ipnp->ipn_dsize; - - n -= sizeof(ipnp->ipn_data); - in = malloc(sizeof(*in) + n); - if (!in) - break; + in = (nat_save_t *)malloc(ipn.ipn_dsize); + if (!in) + break; - s += sizeof(ipnp->ipn_data); - i = read(nfd, s, n); - if (i == 0) - break; - if (i != n) { - fprintf(stderr, "incomplete read: %d != %d\n", - i, n); - close(nfd); - free(in); - return 1; + if (ipn.ipn_dsize > sizeof(ipn)) { + n = ipn.ipn_dsize - sizeof(ipn); + if (n > 0) { + s = in->ipn_data + sizeof(in->ipn_data); + i = read(nfd, s, n); + if (i == 0) + break; + if (i != n) { + fprintf(stderr, + "nat:incomplete read: %d != %d\n", + i, n); + close(nfd); + return 1; + } } - } else { - ipn.ipn_dsize = 0; - in = (nat_save_t *)malloc(sizeof(*in)); - if (in == NULL) - break; } - bcopy((char *)ipnp, (char *)in, sizeof(ipn)); + bcopy((char *)&ipn, (char *)in, sizeof(ipn)); /* - * Check to see if this is the first state entry that will + * Check to see if this is the first NAT entry that will * reference a particular rule and if so, flag it as such * else just adjust the rule pointer to become a pointer to * the other. We do this so we have a means later for tracking @@ -632,6 +644,10 @@ char *file; } while (1); close(nfd); + nfd = -1; + + obj.ipfo_rev = IPFILTER_VERSION; + obj.ipfo_type = IPFOBJ_NATSAVE; for (in = ipnhead; in; in = in->ipn_next) { if (opts & OPT_VERBOSE) @@ -641,8 +657,12 @@ char *file; if (opts & OPT_VERBOSE) printf("Loading new filter rule\n"); } + + obj.ipfo_ptr = in; + obj.ipfo_size = in->ipn_dsize; if (!(opts & OPT_DONOTHING)) - if (ioctl(fd, SIOCSTPUT, &in)) { + if (ioctl(fd, SIOCSTPUT, &obj)) { + fprintf(stderr, "in=%p:", in); perror("SIOCSTPUT"); return 1; } @@ -665,6 +685,7 @@ int fd; char *file; { nat_save_t *ipnp = NULL, *next = NULL; + ipfobj_t obj; int nfd = -1; natget_t ng; @@ -678,6 +699,8 @@ char *file; return 1; } + obj.ipfo_rev = IPFILTER_VERSION; + obj.ipfo_type = IPFOBJ_NATSAVE; do { if (opts & OPT_VERBOSE) @@ -709,8 +732,11 @@ char *file; } bzero((char *)ipnp, ng.ng_sz); + obj.ipfo_size = ng.ng_sz; + obj.ipfo_ptr = ipnp; + ipnp->ipn_dsize = ng.ng_sz; ipnp->ipn_next = next; - if (ioctl(fd, SIOCSTGET, &ipnp)) { + if (ioctl(fd, SIOCSTGET, &obj)) { if (errno == ENOENT) break; perror("nat:SIOCSTGET"); @@ -720,8 +746,9 @@ char *file; } if (opts & OPT_VERBOSE) - printf("Got nat next %p\n", ipnp->ipn_next); - if (write(nfd, ipnp, ng.ng_sz) != ng.ng_sz) { + printf("Got nat next %p ipn_dsize %d ng_sz %d\n", + ipnp->ipn_next, ipnp->ipn_dsize, ng.ng_sz); + if (write(nfd, ipnp, ipnp->ipn_dsize) != ipnp->ipn_dsize) { perror("nat:write"); close(nfd); free(ipnp); @@ -746,6 +773,7 @@ char *dirname; dirname = IPF_SAVEDIR; if (chdir(dirname)) { + fprintf(stderr, "IPF_SAVEDIR=%s: ", dirname); perror("chdir(IPF_SAVEDIR)"); return 1; } diff --git a/usr/src/cmd/ipf/tools/ipfstat.c b/usr/src/cmd/ipf/tools/ipfstat.c index e3de41316c..b2f3195a99 100644 --- a/usr/src/cmd/ipf/tools/ipfstat.c +++ b/usr/src/cmd/ipf/tools/ipfstat.c @@ -3,7 +3,7 @@ * * See the IPFILTER.LICENCE file for details on licencing. * - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -20,14 +20,20 @@ #endif #include <sys/ioctl.h> #include <fcntl.h> -#include <nlist.h> +#ifdef linux +# include <linux/a.out.h> +#else +# include <nlist.h> +#endif #include <ctype.h> -#include <stddef.h> +#if defined(sun) && (defined(__svr4__) || defined(__SVR4)) +# include <stddef.h> +#endif #include "ipf.h" -#include "ipl.h" +#include "netinet/ipl.h" #if defined(STATETOP) # if defined(_BSDI_VERSION) -# undef STATETOP) +# undef STATETOP # endif # if defined(__FreeBSD__) && \ (!defined(__FreeBSD_version) || (__FreeBSD_version < 430000)) @@ -49,16 +55,15 @@ # include <netinet/tcp_fsm.h> #endif #ifdef STATETOP -#if SOLARIS2 >= 10 -# include "ipl.h" -#else -# include "netinet/ipl.h" -#endif +# include <ctype.h> +# include <signal.h> # if SOLARIS || defined(__NetBSD__) || defined(_BSDI_VERSION) || \ defined(__sgi) # ifdef ERR # undef ERR # endif +# undef ISASCII +# undef ISPRINT # include <curses.h> # else /* SOLARIS */ # include <ncurses.h> @@ -71,7 +76,7 @@ #if !defined(lint) static const char sccsid[] = "@(#)fils.c 1.21 4/20/96 (C) 1993-2000 Darren Reed"; -static const char rcsid[] = "@(#)$Id: ipfstat.c,v 1.28 2003/07/01 01:03:04 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id: ipfstat.c,v 1.44.2.12 2005/06/12 07:18:46 darrenr Exp $"; #endif #ifdef __hpux @@ -80,6 +85,7 @@ static const char rcsid[] = "@(#)$Id: ipfstat.c,v 1.28 2003/07/01 01:03:04 darre extern char *optarg; extern int optind; +extern int opterr; #define PRINTF (void)printf #define FPRINTF (void)fprintf @@ -107,8 +113,10 @@ int ipf_fd = -1; #define STSORT_BYTES 2 #define STSORT_TTL 3 #define STSORT_SRCIP 4 -#define STSORT_DSTIP 5 -#define STSORT_MAX STSORT_DSTIP +#define STSORT_SRCPT 5 +#define STSORT_DSTIP 6 +#define STSORT_DSTPT 7 +#define STSORT_MAX STSORT_DSTPT #define STSORT_DEFAULT STSORT_BYTES @@ -118,6 +126,7 @@ typedef struct statetop { u_short st_sport; u_short st_dport; u_char st_p; + u_char st_v; u_char st_state[2]; U_QUAD_T st_pkts; U_QUAD_T st_bytes; @@ -125,42 +134,54 @@ typedef struct statetop { } statetop_t; #endif -extern int main __P((int, char *[])); +int main __P((int, char *[])); + static void showstats __P((friostat_t *, u_32_t)); static void showfrstates __P((ipfrstat_t *)); static void showlist __P((friostat_t *)); static void showipstates __P((ips_stat_t *)); static void showauthstates __P((fr_authstat_t *)); static void showgroups __P((friostat_t *)); -static void Usage __P((char *)); +static void usage __P((char *)); static void printlist __P((frentry_t *, char *)); -static void parse_ipportstr __P((const char *, struct in_addr *, int *)); +static void parse_ipportstr __P((const char *, i6addr_t *, int *)); static void ipfstate_live __P((char *, friostat_t **, ips_stat_t **, ipfrstat_t **, fr_authstat_t **, u_32_t *)); static void ipfstate_dead __P((char *, friostat_t **, ips_stat_t **, ipfrstat_t **, fr_authstat_t **, u_32_t *)); #ifdef STATETOP -static void topipstates __P((struct in_addr, struct in_addr, int, int, int, int, int)); +static void topipstates __P((i6addr_t, i6addr_t, int, int, int, + int, int, int)); +static void sig_break __P((int)); +static void sig_resize __P((int)); +static char *getip __P((int, i6addr_t *)); static char *ttl_to_string __P((long)); static int sort_p __P((const void *, const void *)); static int sort_pkts __P((const void *, const void *)); static int sort_bytes __P((const void *, const void *)); static int sort_ttl __P((const void *, const void *)); static int sort_srcip __P((const void *, const void *)); +static int sort_srcpt __P((const void *, const void *)); static int sort_dstip __P((const void *, const void *)); +static int sort_dstpt __P((const void *, const void *)); #endif -static void Usage(name) +static void usage(name) char *name; { #ifdef USE_INET6 - fprintf(stderr, "Usage: %s [-6aAfhIinosv] [-d <device>]\n", name); + fprintf(stderr, "Usage: %s [-6aAdfghIilnoRsv]\n", name); #else - fprintf(stderr, "Usage: %s [-aAfhIinosv] [-d <device>]\n", name); + fprintf(stderr, "Usage: %s [-aAdfghIilnoRsv]\n", name); #endif - fprintf(stderr, "\t\t[-M corefile] [-N symbol-list]\n"); - fprintf(stderr, " %s -t [-S source address] [-D destination address] [-P protocol] [-T refreshtime] [-C] [-d <device>]\n", name); + fprintf(stderr, " %s [-M corefile] [-N symbol-list]\n", name); +#ifdef USE_INET6 + fprintf(stderr, " %s -t [-6C] ", name); +#else + fprintf(stderr, " %s -t [-C] ", name); +#endif + fprintf(stderr, "[-D destination address] [-P protocol] [-S source address] [-T refresh time]\n"); exit(1); } @@ -178,27 +199,39 @@ char *argv[]; ipfrstat_t ifrst; ipfrstat_t *ifrstp = &ifrst; char *device = IPL_NAME, *memf = NULL; - char *kern = NULL; + char *options, *kern = NULL; int c, myoptind; - 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; + i6addr_t saddr, daddr; u_32_t frf; - saddr.s_addr = INADDR_ANY; /* default any source addr */ - daddr.s_addr = INADDR_ANY; /* default any dest addr */ +#ifdef USE_INET6 + options = "6aACdfghIilnostvD:M:N:P:RS:T:"; +#else + options = "aACdfghIilnostvD:M:N:P:RS:T:"; +#endif + + saddr.in4.s_addr = INADDR_ANY; /* default any v4 source addr */ + daddr.in4.s_addr = INADDR_ANY; /* default any v4 dest addr */ +#ifdef USE_INET6 + saddr.in6 = in6addr_any; /* default any v6 source addr */ + daddr.in6 = in6addr_any; /* default any v6 dest addr */ +#endif + + /* Don't warn about invalid flags when we run getopt for the 1st time */ + opterr = 0; /* * Parse these two arguments now lest there be any buffer overflows * in the parsing of the rest. */ myoptind = optind; - while ((c = getopt(argc, argv, "6aACdfghIilnostvD:M:N:P:S:T:")) != -1) + while ((c = getopt(argc, argv, options)) != -1) { switch (c) { case 'M' : @@ -210,32 +243,37 @@ char *argv[]; live_kernel = 0; break; } + } optind = myoptind; if (live_kernel == 1) { if ((state_fd = open(IPSTATE_NAME, O_RDONLY)) == -1) { - perror("open"); + perror("open(IPSTATE_NAME)"); exit(-1); } if ((ipf_fd = open(device, O_RDONLY)) == -1) { - perror("open"); + fprintf(stderr, "open(%s)", device); + perror(""); exit(-1); } } - if (kern != NULL || memf != NULL) - { + if (kern != NULL || memf != NULL) { (void)setgid(getgid()); (void)setreuid(getuid(), getuid()); } + if (live_kernel == 1) + (void) checkrev(device); if (openkmem(kern, memf) == -1) exit(-1); (void)setgid(getgid()); (void)setreuid(getuid(), getuid()); - while ((c = getopt(argc, argv, "6aACdfghIilnostvD:M:N:P:S:T:")) != -1) + opterr = 1; + + while ((c = getopt(argc, argv, options)) != -1) { switch (c) { @@ -288,15 +326,16 @@ char *argv[]; opts |= OPT_OUTQUE|OPT_SHOWLIST; break; case 'P' : - if ((proto = getprotobyname(optarg)) != NULL) { - protocol = proto->p_proto; - } else if (!sscanf(optarg, "%d", &protocol) || - (protocol < 0)) { - fprintf(stderr, "%s : Invalid protocol: %s\n", + protocol = getproto(optarg); + if (protocol == -1) { + fprintf(stderr, "%s: Invalid protocol: %s\n", argv[0], optarg); exit(-2); } break; + case 'R' : + opts |= OPT_NORESOLVE; + break; case 's' : opts |= OPT_IPSTATES; break; @@ -309,7 +348,7 @@ char *argv[]; break; #else fprintf(stderr, - "%s : state top facility not compiled in\n", + "%s: state top facility not compiled in\n", argv[0]); exit(-2); #endif @@ -317,7 +356,7 @@ char *argv[]; if (!sscanf(optarg, "%d", &refreshtime) || (refreshtime <= 0)) { fprintf(stderr, - "%s : Invalid refreshtime < 1 : %s\n", + "%s: Invalid refreshtime < 1 : %s\n", argv[0], optarg); exit(-2); } @@ -327,7 +366,7 @@ char *argv[]; opts |= OPT_UNDEF; break; default : - Usage(argv[0]); + usage(argv[0]); break; } } @@ -350,21 +389,20 @@ char *argv[]; opts &= ~OPT_OUTQUE; showlist(fiop); } - } else { - if (opts & OPT_FRSTATES) - showfrstates(ifrstp); + } else if (opts & OPT_FRSTATES) + showfrstates(ifrstp); #ifdef STATETOP - else if (opts & OPT_STATETOP) - topipstates(saddr, daddr, sport, dport, - protocol, refreshtime, topclosed); + else if (opts & OPT_STATETOP) + topipstates(saddr, daddr, sport, dport, protocol, + use_inet6 ? 6 : 4, refreshtime, topclosed); #endif - else if (opts & OPT_AUTHSTATS) - showauthstates(frauthstp); - else if (opts & OPT_GROUPS) - showgroups(fiop); - else - showstats(fiop, frf); - } + else if (opts & OPT_AUTHSTATS) + showauthstates(frauthstp); + else if (opts & OPT_GROUPS) + showgroups(fiop); + else + showstats(fiop, frf); + return 0; } @@ -685,12 +723,12 @@ u_32_t frf; 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", 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", fp->f_st[0].fr_bpkl, fp->f_st[0].fr_ppkl); @@ -700,10 +738,12 @@ u_32_t frf; fp->f_st[0].fr_pkl, fp->f_st[1].fr_pkl); PRINTF(" log failures:\t\tinput %lu output %lu\n", fp->f_st[0].fr_skip, fp->f_st[1].fr_skip); - PRINTF("fragment state(in):\tkept %lu\tlost %lu\n", - fp->f_st[0].fr_nfr, fp->f_st[0].fr_bnfr); - PRINTF("fragment state(out):\tkept %lu\tlost %lu\n", - fp->f_st[1].fr_nfr, fp->f_st[1].fr_bnfr); + PRINTF("fragment state(in):\tkept %lu\tlost %lu\tnot fragmented %lu\n", + fp->f_st[0].fr_nfr, fp->f_st[0].fr_bnfr, + fp->f_st[0].fr_cfr); + PRINTF("fragment state(out):\tkept %lu\tlost %lu\tnot fragmented %lu\n", + fp->f_st[1].fr_nfr, fp->f_st[1].fr_bnfr, + fp->f_st[0].fr_cfr); PRINTF("packet state(in):\tkept %lu\tlost %lu\n", fp->f_st[0].fr_ads, fp->f_st[0].fr_bads); PRINTF("packet state(out):\tkept %lu\tlost %lu\n", @@ -787,7 +827,7 @@ char *comment; } printfr(fp, ioctl); - if (opts & OPT_VERBOSE) { + if (opts & OPT_DEBUG) { binprint(fp, sizeof(*fp)); if (fp->fr_data != NULL && fp->fr_dsize > 0) binprint(fp->fr_data, fp->fr_dsize); @@ -902,6 +942,8 @@ ips_stat_t *ipsp; ipsp->iss_miss); PRINTF("\t%lu maximum\n\t%lu no memory\n\t%lu max bucket\n", ipsp->iss_max, ipsp->iss_nomem, ipsp->iss_bucketfull); + PRINTF("\t%lu maximum\n\t%lu no memory\n\t%lu bkts in use\n", + ipsp->iss_max, ipsp->iss_nomem, ipsp->iss_inuse); PRINTF("\t%lu active\n\t%lu expired\n\t%lu closed\n", ipsp->iss_active, ipsp->iss_expire, ipsp->iss_fin); @@ -936,13 +978,13 @@ ips_stat_t *ipsp; if (opts & OPT_VERBOSE) { PRINTF("\nCurrent bucket sizes :\n"); for (i = 0; i < ipsp->iss_statesize; i++) { - if ((i % ENTRIES_PER_LINE) == 0) + if ((i % ENTRIES_PER_LINE) == 0) PRINTF("\t"); PRINTF("%4d -> %4lu", i, buckets[i]); if ((i % ENTRIES_PER_LINE) == - (ENTRIES_PER_LINE - 1)) + (ENTRIES_PER_LINE - 1)) PRINTF("\n"); - else + else PRINTF(" "); } PRINTF("\n"); @@ -957,7 +999,8 @@ ips_stat_t *ipsp; * Print out all the state information currently held in the kernel. */ while (ipsp->iss_list != NULL) { - ipsp->iss_list = printstate(ipsp->iss_list, opts); + ipsp->iss_list = printstate(ipsp->iss_list, opts, + ipsp->iss_ticks); } free(buckets); @@ -965,39 +1008,52 @@ ips_stat_t *ipsp; #ifdef STATETOP -static void topipstates(saddr, daddr, sport, dport, protocol, +static int handle_resize = 0, handle_break = 0; + +static void topipstates(saddr, daddr, sport, dport, protocol, ver, refreshtime, topclosed) -struct in_addr saddr; -struct in_addr daddr; +i6addr_t saddr; +i6addr_t daddr; int sport; int dport; int protocol; +int ver; int refreshtime; int topclosed; { char str1[STSTRSIZE], str2[STSTRSIZE], str3[STSTRSIZE], str4[STSTRSIZE]; int maxtsentries = 0, reverse = 0, sorting = STSORT_DEFAULT; - int i, j, winx, tsentry, maxx, maxy, redraw = 0; + int i, j, winy, tsentry, maxx, maxy, redraw = 0, ret = 0; + int len, srclen, dstlen, forward = 1, c = 0; ips_stat_t ipsst, *ipsstp = &ipsst; statetop_t *tstable = NULL, *tp; + const char *errstr = ""; ipstate_t ips; ipfobj_t ipfo; - struct timeval selecttimeout; + struct timeval selecttimeout; char hostnm[HOSTNMLEN]; struct protoent *proto; fd_set readfd; - int c = 0; time_t t; + /* install signal handlers */ + signal(SIGINT, sig_break); + signal(SIGQUIT, sig_break); + signal(SIGTERM, sig_break); + signal(SIGWINCH, sig_resize); + /* init ncurses stuff */ initscr(); cbreak(); noecho(); + curs_set(0); + timeout(0); + getmaxyx(stdscr, maxy, maxx); /* init hostname */ gethostname(hostnm, sizeof(hostnm) - 1); hostnm[sizeof(hostnm) - 1] = '\0'; - + /* init ipfobj_t stuff */ bzero((caddr_t)&ipfo, sizeof(ipfo)); ipfo.ipfo_rev = IPFILTER_VERSION; @@ -1011,73 +1067,111 @@ int topclosed; /* get state table */ bzero((char *)&ipsst, sizeof(ipsst)); if ((ioctl(state_fd, SIOCGETFS, &ipfo) == -1)) { - perror("ioctl(SIOCGETFS)"); - break; + errstr = "ioctl(SIOCGETFS)"; + ret = -1; + goto out; } /* clear the history */ tsentry = -1; + /* reset max str len */ + srclen = dstlen = 0; + /* read the state table and store in tstable */ - while (ipsstp->iss_list) { + for (; ipsstp->iss_list; ipsstp->iss_list = ips.is_next) { + 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_LAST_ACK) || - (ips.is_state[1] < TCPS_LAST_ACK))) { - /* - * 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"); - goto breakout; - } - } - /* 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[0] + ips.is_pkts[1]; - tp->st_bytes = ips.is_bytes[0] + - ips.is_bytes[1]; - tp->st_age = ips.is_die - ipsstp->iss_ticks; - if ((ips.is_p == IPPROTO_TCP) || - (ips.is_p == IPPROTO_UDP)) { - tp->st_sport = ips.is_sport; - tp->st_dport = ips.is_dport; + if (ips.is_v != ver) + continue; + + /* check v4 src/dest addresses */ + if (ips.is_v == 4) { + if ((saddr.in4.s_addr != INADDR_ANY && + saddr.in4.s_addr != ips.is_saddr) || + (daddr.in4.s_addr != INADDR_ANY && + daddr.in4.s_addr != ips.is_daddr)) + continue; + } +#ifdef USE_INET6 + /* check v6 src/dest addresses */ + if (ips.is_v == 6) { + if ((IP6_NEQ(&saddr, &in6addr_any) && + IP6_NEQ(&saddr, &ips.is_src)) || + (IP6_NEQ(&daddr, &in6addr_any) && + IP6_NEQ(&daddr, &ips.is_dst))) + continue; + } +#endif + /* check protocol */ + if (protocol > 0 && protocol != ips.is_p) + continue; + + /* check ports if protocol is TCP or UDP */ + if (((ips.is_p == IPPROTO_TCP) || + (ips.is_p == IPPROTO_UDP)) && + (((sport > 0) && (htons(sport) != ips.is_sport)) || + ((dport > 0) && (htons(dport) != ips.is_dport)))) + continue; + + /* show closed TCP sessions ? */ + if ((topclosed == 0) && (ips.is_p == IPPROTO_TCP) && + (ips.is_state[0] >= IPF_TCPS_LAST_ACK) && + (ips.is_state[1] >= IPF_TCPS_LAST_ACK)) + continue; + + /* + * if necessary make room for this state + * entry + */ + tsentry++; + if (!maxtsentries || tsentry == maxtsentries) { + maxtsentries += STGROWSIZE; + tstable = realloc(tstable, + maxtsentries * sizeof(statetop_t)); + if (tstable == NULL) { + perror("realloc"); + exit(-1); } + } + /* get max src/dest address string length */ + len = strlen(getip(ips.is_v, &ips.is_src)); + if (srclen < len) + srclen = len; + len = strlen(getip(ips.is_v, &ips.is_dst)); + if (dstlen < len) + dstlen = len; + + /* fill structure */ + tp = tstable + tsentry; + tp->st_src = ips.is_src; + tp->st_dst = ips.is_dst; + tp->st_p = ips.is_p; + tp->st_v = ips.is_v; + tp->st_state[0] = ips.is_state[0]; + tp->st_state[1] = ips.is_state[1]; + if (forward) { + tp->st_pkts = ips.is_pkts[0]+ips.is_pkts[1]; + tp->st_bytes = ips.is_bytes[0]+ips.is_bytes[1]; + } else { + tp->st_pkts = ips.is_pkts[2]+ips.is_pkts[3]; + tp->st_bytes = ips.is_bytes[2]+ips.is_bytes[3]; + } + tp->st_age = ips.is_die - ipsstp->iss_ticks; + if ((ips.is_p == IPPROTO_TCP) || + (ips.is_p == IPPROTO_UDP)) { + tp->st_sport = ips.is_sport; + tp->st_dport = ips.is_dport; } } /* sort the array */ - if (tsentry != -1) + if (tsentry != -1) { switch (sorting) { case STSORT_PR: @@ -1100,20 +1194,45 @@ int topclosed; qsort(tstable, tsentry + 1, sizeof(statetop_t), sort_srcip); break; + case STSORT_SRCPT: + qsort(tstable, tsentry +1, + sizeof(statetop_t), sort_srcpt); + break; case STSORT_DSTIP: qsort(tstable, tsentry + 1, sizeof(statetop_t), sort_dstip); break; + case STSORT_DSTPT: + qsort(tstable, tsentry + 1, + sizeof(statetop_t), sort_dstpt); + break; default: break; } + } + + /* handle window resizes */ + if (handle_resize) { + endwin(); + initscr(); + cbreak(); + noecho(); + curs_set(0); + timeout(0); + getmaxyx(stdscr, maxy, maxx); + redraw = 1; + handle_resize = 0; + } + + /* stop program? */ + if (handle_break) + break; /* print title */ erase(); - getmaxyx(stdscr, maxy, maxx); attron(A_BOLD); - winx = 0; - move(winx,0); + winy = 0; + move(winy,0); sprintf(str1, "%s - %s - state top", hostnm, IPL_VERSION); for (j = 0 ; j < (maxx - 8 - strlen(str1)) / 2; j++) printw(" "); @@ -1121,30 +1240,30 @@ int topclosed; attroff(A_BOLD); /* just for fun add a clock */ - move(winx, maxx - 8); + move(winy, maxx - 8); t = time(NULL); strftime(str1, 80, "%T", localtime(&t)); printw("%s\n", str1); /* - * print the display filters, this is placed in the loop, + * 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); + sprintf(str1, "%s,%d", getip(ver, &saddr), sport); else - sprintf(str1, "%s", inet_ntoa(saddr)); + sprintf(str1, "%s", getip(ver, &saddr)); if (dport >= 0) - sprintf(str2, "%s,%d", inet_ntoa(daddr), dport); + sprintf(str2, "%s,%d", getip(ver, &daddr), dport); else - sprintf(str2, "%s", inet_ntoa(daddr)); + sprintf(str2, "%s", getip(ver, &daddr)); if (protocol < 0) strcpy(str3, "any"); else if ((proto = getprotobynumber(protocol)) != NULL) - sprintf(str3, "%s", proto->p_name); + sprintf(str3, "%s", proto->p_name); else sprintf(str3, "%d", protocol); @@ -1163,10 +1282,16 @@ int topclosed; sprintf(str4, "ttl"); break; case STSORT_SRCIP: - sprintf(str4, "srcip"); + sprintf(str4, "src ip"); + break; + case STSORT_SRCPT: + sprintf(str4, "src port"); break; case STSORT_DSTIP: - sprintf(str4, "dstip"); + sprintf(str4, "dest ip"); + break; + case STSORT_DSTPT: + sprintf(str4, "dest port"); break; default: sprintf(str4, "unknown"); @@ -1176,17 +1301,33 @@ int topclosed; if (reverse) strcat(str4, " (reverse)"); - winx += 2; - move(winx,0); - printw("Src = %s Dest = %s Proto = %s Sorted by = %s\n\n", + winy += 2; + move(winy,0); + printw("Src: %s, Dest: %s, Proto: %s, Sorted by: %s\n\n", str1, str2, str3, str4); + /* + * For an IPv4 IP address we need at most 15 characters, + * 4 tuples of 3 digits, separated by 3 dots. Enforce this + * length, so the colums do not change positions based + * on the size of the IP address. This length makes the + * output fit in a 80 column terminal. + * We are lacking a good solution for IPv6 addresses (that + * can be longer that 15 characters), so we do not enforce + * a maximum on the IP field size. + */ + if (srclen < 15) + srclen = 15; + if (dstlen < 15) + dstlen = 15; + /* print column description */ - winx += 2; - move(winx,0); + winy += 2; + move(winy,0); attron(A_BOLD); - printw("%-21s %-21s %3s %4s %7s %9s %9s\n", "Source IP", - "Destination IP", "ST", "PR", "#pkts", "#bytes", "ttl"); + printw("%-*s %-*s %3s %4s %7s %9s %9s\n", + srclen + 6, "Source IP", dstlen + 6, "Destination IP", + "ST", "PR", "#pkts", "#bytes", "ttl"); attroff(A_BOLD); /* print all the entries */ @@ -1201,25 +1342,27 @@ int topclosed; if ((tp->st_p == IPPROTO_TCP) || (tp->st_p == IPPROTO_UDP)) { sprintf(str1, "%s,%hu", - inet_ntoa(tp->st_src.in4), + getip(tp->st_v, &tp->st_src), ntohs(tp->st_sport)); sprintf(str2, "%s,%hu", - inet_ntoa(tp->st_dst.in4), + getip(tp->st_v, &tp->st_dst), ntohs(tp->st_dport)); } else { - sprintf(str1, "%s", inet_ntoa(tp->st_src.in4)); - sprintf(str2, "%s", inet_ntoa(tp->st_dst.in4)); + sprintf(str1, "%s", getip(tp->st_v, + &tp->st_src)); + sprintf(str2, "%s", getip(tp->st_v, + &tp->st_dst)); } - winx++; - move(winx, 0); - printw("%-21s %-21s", str1, str2); + winy++; + move(winy, 0); + printw("%-*s %-*s", srclen + 6, str1, dstlen + 6, str2); /* print state */ sprintf(str1, "%X/%X", tp->st_state[0], tp->st_state[1]); printw(" %3s", str1); - /* print proto */ + /* print protocol */ proto = getprotobynumber(tp->st_p); if (proto) { strncpy(str1, proto->p_name, 4); @@ -1227,8 +1370,12 @@ int topclosed; } else { sprintf(str1, "%d", tp->st_p); } + /* just print icmp for IPv6-ICMP */ + if (tp->st_p == IPPROTO_ICMPV6) + strcpy(str1, "icmp"); printw(" %4s", str1); - /* print #pkt/#bytes */ + + /* print #pkt/#bytes */ #ifdef USE_QUAD_T printw(" %7qu %9qu", (unsigned long long) tp->st_pkts, (unsigned long long) tp->st_bytes); @@ -1247,7 +1394,8 @@ int topclosed; if (redraw) clearok(stdscr,1); - refresh(); + if (refresh() == ERR) + break; if (redraw) { clearok(stdscr,0); redraw = 0; @@ -1266,27 +1414,34 @@ int topclosed; if (c == ERR) continue; - if (tolower(c) == 'l') { + if (ISALPHA(c) && ISUPPER(c)) + c = TOLOWER(c); + if (c == 'l') { redraw = 1; - } else if (tolower(c) == 'q') { + } else if (c == 'q') { break; - } else if (tolower(c) == 'r') { + } else if (c == 'r') { reverse = !reverse; - } else if (tolower(c) == 's') { - sorting++; - if (sorting > STSORT_MAX) + } else if (c == 'b') { + forward = 0; + } else if (c == 'f') { + forward = 1; + } else if (c == 's') { + if (++sorting > STSORT_MAX) sorting = 0; } } } /* while */ -breakout: +out: printw("\n"); + curs_set(1); nocbreak(); endwin(); - if (tstable != NULL) - free(tstable); + free(tstable); + if (ret != 0) + perror(errstr); } #endif @@ -1298,7 +1453,6 @@ static void showfrstates(ifsp) ipfrstat_t *ifsp; { struct ipfr *ipfrtab[IPFT_SIZE], ifr; - frentry_t fr; int i; /* @@ -1306,7 +1460,8 @@ ipfrstat_t *ifsp; */ PRINTF("IP fragment states:\n\t%lu new\n\t%lu expired\n\t%lu hits\n", ifsp->ifs_new, ifsp->ifs_expire, ifsp->ifs_hits); - PRINTF("\t%lu retrans\n\t%lu too short\n", ifsp->ifs_retrans0, ifsp->ifs_short); + PRINTF("\t%lu retrans\n\t%lu too short\n", + ifsp->ifs_retrans0, ifsp->ifs_short); PRINTF("\t%lu no memory\n\t%lu already exist\n", ifsp->ifs_nomem, ifsp->ifs_exists); PRINTF("\t%lu inuse\n", ifsp->ifs_inuse); @@ -1316,36 +1471,26 @@ ipfrstat_t *ifsp; /* * Print out the contents (if any) of the fragment cache table. */ + PRINTF("\n"); for (i = 0; i < IPFT_SIZE; i++) - while (ipfrtab[i]) { + while (ipfrtab[i] != NULL) { if (kmemcpy((char *)&ifr, (u_long)ipfrtab[i], sizeof(ifr)) == -1) break; - 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); + printfraginfo("", &ifr); ipfrtab[i] = ifr.ipfr_next; } + /* + * Print out the contents (if any) of the NAT fragment cache table. + */ if (kmemcpy((char *)ipfrtab, (u_long)ifsp->ifs_nattab,sizeof(ipfrtab))) return; for (i = 0; i < IPFT_SIZE; i++) - while (ipfrtab[i]) { + while (ipfrtab[i] != NULL) { 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", - hostname(4, &ifr.ipfr_dst), ifr.ipfr_id, - ifr.ipfr_ttl, ifr.ipfr_p, ifr.ipfr_tos, - fr.fr_flags); + printfraginfo("NAT: ", &ifr); ipfrtab[i] = ifr.ipfr_next; } } @@ -1393,6 +1538,7 @@ static void showgroups(fiop) struct friostat *fiop; { static char *gnames[3] = { "Filter", "Accounting", "Authentication" }; + static int gnums[3] = { IPL_LOGIPF, IPL_LOGCOUNT, IPL_LOGAUTH }; frgroup_t *fp, grp; int on, off, i; @@ -1401,13 +1547,15 @@ struct friostat *fiop; for (i = 0; i < 3; i++) { printf("%s groups (active):\n", gnames[i]); - for (fp = fiop->f_groups[i][on]; fp; fp = grp.fg_next) + for (fp = fiop->f_groups[gnums[i]][on]; fp != NULL; + fp = grp.fg_next) if (kmemcpy((char *)&grp, (u_long)fp, sizeof(grp))) break; else printf("%s\n", grp.fg_name); printf("%s groups (inactive):\n", gnames[i]); - for (fp = fiop->f_groups[i][off]; fp; fp = grp.fg_next) + for (fp = fiop->f_groups[gnums[i]][off]; fp != NULL; + fp = grp.fg_next) if (kmemcpy((char *)&grp, (u_long)fp, sizeof(grp))) break; else @@ -1417,11 +1565,11 @@ struct friostat *fiop; static void parse_ipportstr(argument, ip, port) const char *argument; -struct in_addr *ip; +i6addr_t *ip; int *port; { - char *s, *comma; + int ok = 0; /* make working copy of argument, Theoretically you must be able * to write to optarg, but that seems very ugly to me.... @@ -1447,8 +1595,16 @@ int *port; /* get ip address */ if (!strcasecmp(s, "any")) { - ip->s_addr = INADDR_ANY; - } else if (!inet_aton(s, ip)) { + ip->in4.s_addr = INADDR_ANY; +#ifdef USE_INET6 + ip->in6 = in6addr_any; + } else if (use_inet6 && inet_pton(AF_INET6, s, &ip->in6)) { + ok = 1; +#endif + } else if (inet_aton(s, &ip->in4)) + ok = 1; + + if (ok == 0) { fprintf(stderr, "Invalid IP address: %s\n", s); free(s); exit(-2); @@ -1460,12 +1616,43 @@ int *port; #ifdef STATETOP -static char ttlbuf[STSTRSIZE]; +static void sig_resize(s) +int s; +{ + handle_resize = 1; +} + +static void sig_break(s) +int s; +{ + handle_break = 1; +} + +static char *getip(v, addr) +int v; +i6addr_t *addr; +{ +#ifdef USE_INET6 + static char hostbuf[MAXHOSTNAMELEN+1]; +#endif + + if (v == 4) + return inet_ntoa(addr->in4); + +#ifdef USE_INET6 + (void) inet_ntop(AF_INET6, &addr->in6, hostbuf, sizeof(hostbuf) - 1); + hostbuf[MAXHOSTNAMELEN] = '\0'; + return hostbuf; +#else + return "IPv6"; +#endif +} + static char *ttl_to_string(ttl) long int ttl; { - + static char ttlbuf[STSTRSIZE]; int hours, minutes, seconds; /* ttl is in half seconds */ @@ -1476,7 +1663,7 @@ long int ttl; minutes = ttl / 60; seconds = ttl % 60; - if (hours > 0 ) + if (hours > 0) sprintf(ttlbuf, "%2d:%02d:%02d", hours, minutes, seconds); else sprintf(ttlbuf, "%2d:%02d", minutes, seconds); @@ -1551,9 +1738,35 @@ const void *b; register const statetop_t *ap = a; register const statetop_t *bp = b; - if (ntohl(ap->st_src.in4.s_addr) == ntohl(bp->st_src.in4.s_addr)) +#ifdef USE_INET6 + if (use_inet6) { + if (IP6_EQ(&ap->st_src, &bp->st_src)) + return 0; + else if (IP6_GT(&ap->st_src, &bp->st_src)) + return 1; + } else +#endif + { + if (ntohl(ap->st_src.in4.s_addr) == + ntohl(bp->st_src.in4.s_addr)) + return 0; + else if (ntohl(ap->st_src.in4.s_addr) > + ntohl(bp->st_src.in4.s_addr)) + return 1; + } + return -1; +} + +static int sort_srcpt(a, b) +const void *a; +const void *b; +{ + register const statetop_t *ap = a; + register const statetop_t *bp = b; + + if (htons(ap->st_sport) == htons(bp->st_sport)) return 0; - else if (ntohl(ap->st_src.in4.s_addr) > ntohl(bp->st_src.in4.s_addr)) + else if (htons(ap->st_sport) > htons(bp->st_sport)) return 1; return -1; } @@ -1565,10 +1778,37 @@ const void *b; register const statetop_t *ap = a; register const statetop_t *bp = b; - if (ntohl(ap->st_dst.in4.s_addr) == ntohl(bp->st_dst.in4.s_addr)) +#ifdef USE_INET6 + if (use_inet6) { + if (IP6_EQ(&ap->st_dst, &bp->st_dst)) + return 0; + else if (IP6_GT(&ap->st_dst, &bp->st_dst)) + return 1; + } else +#endif + { + if (ntohl(ap->st_dst.in4.s_addr) == + ntohl(bp->st_dst.in4.s_addr)) + return 0; + else if (ntohl(ap->st_dst.in4.s_addr) > + ntohl(bp->st_dst.in4.s_addr)) + return 1; + } + return -1; +} + +static int sort_dstpt(a, b) +const void *a; +const void *b; +{ + register const statetop_t *ap = a; + register const statetop_t *bp = b; + + if (htons(ap->st_dport) == htons(bp->st_dport)) return 0; - else if (ntohl(ap->st_dst.in4.s_addr) > ntohl(bp->st_dst.in4.s_addr)) + else if (htons(ap->st_dport) > htons(bp->st_dport)) return 1; return -1; } + #endif diff --git a/usr/src/cmd/ipf/tools/ipftest.c b/usr/src/cmd/ipf/tools/ipftest.c index 3ea511e326..9704597bd9 100644 --- a/usr/src/cmd/ipf/tools/ipftest.c +++ b/usr/src/cmd/ipf/tools/ipftest.c @@ -3,7 +3,7 @@ * * See the IPFILTER.LICENCE file for details on licencing. * - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -16,7 +16,7 @@ #if !defined(lint) static const char sccsid[] = "@(#)ipt.c 1.19 6/3/96 (C) 1993-2000 Darren Reed"; -static const char rcsid[] = "@(#)$Id: ipftest.c,v 1.35 2003/07/01 01:03:04 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id: ipftest.c,v 1.44.2.4 2005/07/16 06:05:28 darrenr Exp $"; #endif extern char *optarg; @@ -29,7 +29,7 @@ extern int fr_running; ipfmutex_t ipl_mutex, ipf_authmx, ipf_rw, ipf_stinsert; ipfmutex_t ipf_nat_new, ipf_natio, ipf_timeoutlock; -ipfrwlock_t ipf_mutex, ipf_global, ipf_ipidfrag, ip_poolrw; +ipfrwlock_t ipf_mutex, ipf_global, ipf_ipidfrag, ip_poolrw, ipf_frcache; ipfrwlock_t ipf_frag, ipf_state, ipf_nat, ipf_natfrag, ipf_auth; int opts = OPT_DONOTHING; int use_inet6 = 0; @@ -47,7 +47,7 @@ void fixv4sums __P((mb_t *, ip_t *)); #if defined(__NetBSD__) || defined(__OpenBSD__) || SOLARIS || \ (_BSDI_VERSION >= 199701) || (__FreeBSD_version >= 300000) || \ - defined(__osf__) + defined(__osf__) || defined(linux) int ipftestioctl __P((int, ioctlcmd_t, ...)); int ipnattestioctl __P((int, ioctlcmd_t, ...)); int ipstatetestioctl __P((int, ioctlcmd_t, ...)); @@ -101,19 +101,15 @@ char *argv[]; MUTEX_INIT(&ipf_timeoutlock, "ipf timeout lock"); RWLOCK_INIT(&ipf_global, "ipf filter load/unload mutex"); RWLOCK_INIT(&ipf_mutex, "ipf filter rwlock"); + RWLOCK_INIT(&ipf_frcache, "ipf cache rwlock"); RWLOCK_INIT(&ipf_ipidfrag, "ipf IP NAT-Frag rwlock"); initparse(); - fr_loginit(); - fr_authinit(); - fr_fraginit(); - fr_stateinit(); - fr_natinit(); - appr_init(); - ip_lookup_init(); + if (fr_initialise() == -1) + abort(); fr_running = 1; - while ((c = getopt(argc, argv, "6bdDF:i:I:l:N:P:or:vxX")) != -1) + while ((c = getopt(argc, argv, "6bdDF:i:I:l:N:P:or:RT:vxX")) != -1) switch (c) { case '6' : @@ -165,6 +161,9 @@ char *argv[]; return -1; loaded = 1; break; + case 'R' : + opts |= OPT_NORESOLVE; + break; case 'v' : opts |= OPT_VERBOSE; break; @@ -180,6 +179,9 @@ char *argv[]; return -1; loaded = 1; break; + case 'T' : + ipf_dotuning(-1, optarg, ipftestioctl); + break; case 'x' : opts |= OPT_HEX; break; @@ -272,7 +274,7 @@ char *argv[]; } else if ((opts & (OPT_BRIEF|OPT_NAT)) == (OPT_NAT|OPT_BRIEF)) printpacket(ip); if (dir && (ifp != NULL) && IP_V(ip) && (m != NULL)) -#if defined(__sgi) && (IRIX < 605) +#if defined(__sgi) && (IRIX < 60500) (*ifp->if_output)(ifp, (void *)m, NULL); #else # if TRU64 >= 1885 @@ -303,19 +305,7 @@ char *argv[]; dumpgroups(); } - for (i = IPL_LOGMAX; i >= 0; i--) - (void) ipflog_clear(i); - - fr_fragunload(); - fr_authunload(); - fr_stateunload(); - fr_natunload(); - appr_unload(); - - i = frflush(IPL_LOGIPF, 0, FR_INQUE|FR_OUTQUE|FR_INACTIVE); - i += frflush(IPL_LOGIPF, 0, FR_INQUE|FR_OUTQUE); - - ip_lookup_unload(); + fr_deinitialise(); return 0; } @@ -323,7 +313,7 @@ char *argv[]; #if defined(__NetBSD__) || defined(__OpenBSD__) || SOLARIS || \ (_BSDI_VERSION >= 199701) || (__FreeBSD_version >= 300000) || \ - defined(__osf__) + defined(__osf__) || defined(linux) int ipftestioctl(int dev, ioctlcmd_t cmd, ...) { caddr_t data; @@ -338,7 +328,11 @@ int ipftestioctl(int dev, ioctlcmd_t cmd, ...) if (opts & OPT_DEBUG) fprintf(stderr, "iplioctl(IPF,%#x,%p) = %d\n", (u_int)cmd, data, i); - return i; + if (i != 0) { + errno = i; + return -1; + } + return 0; } @@ -356,7 +350,11 @@ int ipnattestioctl(int dev, ioctlcmd_t cmd, ...) if (opts & OPT_DEBUG) fprintf(stderr, "iplioctl(NAT,%#x,%p) = %d\n", (u_int)cmd, data, i); - return i; + if (i != 0) { + errno = i; + return -1; + } + return 0; } @@ -374,7 +372,11 @@ int ipstatetestioctl(int dev, ioctlcmd_t cmd, ...) if ((opts & OPT_DEBUG) || (i != 0)) fprintf(stderr, "iplioctl(STATE,%#x,%p) = %d\n", (u_int)cmd, data, i); - return i; + if (i != 0) { + errno = i; + return -1; + } + return 0; } @@ -392,7 +394,11 @@ int ipauthtestioctl(int dev, ioctlcmd_t cmd, ...) if ((opts & OPT_DEBUG) || (i != 0)) fprintf(stderr, "iplioctl(AUTH,%#x,%p) = %d\n", (u_int)cmd, data, i); - return i; + if (i != 0) { + errno = i; + return -1; + } + return 0; } @@ -410,7 +416,11 @@ int ipscantestioctl(int dev, ioctlcmd_t cmd, ...) if ((opts & OPT_DEBUG) || (i != 0)) fprintf(stderr, "iplioctl(SCAN,%#x,%p) = %d\n", (u_int)cmd, data, i); - return i; + if (i != 0) { + errno = i; + return -1; + } + return 0; } @@ -428,7 +438,11 @@ int ipsynctestioctl(int dev, ioctlcmd_t cmd, ...) if ((opts & OPT_DEBUG) || (i != 0)) fprintf(stderr, "iplioctl(SYNC,%#x,%p) = %d\n", (u_int)cmd, data, i); - return i; + if (i != 0) { + errno = i; + return -1; + } + return 0; } @@ -446,7 +460,11 @@ int ipooltestioctl(int dev, ioctlcmd_t cmd, ...) if ((opts & OPT_DEBUG) || (i != 0)) fprintf(stderr, "iplioctl(POOL,%#x,%p) = %d\n", (u_int)cmd, data, i); - return i; + if (i != 0) { + errno = i; + return -1; + } + return 0; } #else int ipftestioctl(dev, cmd, data) @@ -459,7 +477,11 @@ void *data; i = iplioctl(IPL_LOGIPF, cmd, data, FWRITE|FREAD); if ((opts & OPT_DEBUG) || (i != 0)) fprintf(stderr, "iplioctl(IPF,%#x,%p) = %d\n", cmd, data, i); - return i; + if (i != 0) { + errno = i; + return -1; + } + return 0; } @@ -473,7 +495,11 @@ void *data; i = iplioctl(IPL_LOGNAT, cmd, data, FWRITE|FREAD); if ((opts & OPT_DEBUG) || (i != 0)) fprintf(stderr, "iplioctl(NAT,%#x,%p) = %d\n", cmd, data, i); - return i; + if (i != 0) { + errno = i; + return -1; + } + return 0; } @@ -487,7 +513,11 @@ void *data; i = iplioctl(IPL_LOGSTATE, cmd, data, FWRITE|FREAD); if ((opts & OPT_DEBUG) || (i != 0)) fprintf(stderr, "iplioctl(STATE,%#x,%p) = %d\n", cmd, data, i); - return i; + if (i != 0) { + errno = i; + return -1; + } + return 0; } @@ -501,7 +531,11 @@ void *data; i = iplioctl(IPL_LOGAUTH, cmd, data, FWRITE|FREAD); if ((opts & OPT_DEBUG) || (i != 0)) fprintf(stderr, "iplioctl(AUTH,%#x,%p) = %d\n", cmd, data, i); - return i; + if (i != 0) { + errno = i; + return -1; + } + return 0; } @@ -515,7 +549,11 @@ void *data; i = iplioctl(IPL_LOGSYNC, cmd, data, FWRITE|FREAD); if ((opts & OPT_DEBUG) || (i != 0)) fprintf(stderr, "iplioctl(SYNC,%#x,%p) = %d\n", cmd, data, i); - return i; + if (i != 0) { + errno = i; + return -1; + } + return 0; } @@ -529,7 +567,11 @@ void *data; i = iplioctl(IPL_LOGSCAN, cmd, data, FWRITE|FREAD); if ((opts & OPT_DEBUG) || (i != 0)) fprintf(stderr, "iplioctl(SCAN,%#x,%p) = %d\n", cmd, data, i); - return i; + if (i != 0) { + errno = i; + return -1; + } + return 0; } @@ -543,7 +585,11 @@ void *data; i = iplioctl(IPL_LOGLOOKUP, cmd, data, FWRITE|FREAD); if (opts & OPT_DEBUG) fprintf(stderr, "iplioctl(POOL,%#x,%p) = %d\n", cmd, data, i); - return i; + if (i != 0) { + errno = i; + return -1; + } + return 0; } #endif @@ -585,8 +631,11 @@ void dumpnat() for (ipn = nat_list; ipn != NULL; ipn = ipn->in_next) printnat(ipn, opts & (OPT_DEBUG|OPT_VERBOSE)); printf("\nList of active sessions:\n"); - for (nat = nat_instances; nat; nat = nat->nat_next) + for (nat = nat_instances; nat; nat = nat->nat_next) { printactivenat(nat, opts); + if (nat->nat_aps) + printaps(nat->nat_aps, opts); + } } @@ -599,7 +648,8 @@ void dumpstate() printf("List of active state sessions:\n"); for (ips = ips_list; ips != NULL; ) - ips = printstate(ips, opts & (OPT_DEBUG|OPT_VERBOSE)); + ips = printstate(ips, opts & (OPT_DEBUG|OPT_VERBOSE), + fr_ticks); } @@ -612,12 +662,12 @@ void dumplookups() printf("List of configured pools\n"); for (i = 0; i < IPL_LOGSIZE; i++) for (ipl = ip_pool_list[i]; ipl != NULL; ipl = ipl->ipo_next) - printpool(ipl, bcopywrap, opts); + printpool(ipl, bcopywrap, NULL, opts); printf("List of configured hash tables\n"); for (i = 0; i < IPL_LOGSIZE; i++) for (iph = ipf_htables[i]; iph != NULL; iph = iph->iph_next) - printhash(iph, bcopywrap, opts); + printhash(iph, bcopywrap, NULL, opts); } @@ -666,7 +716,7 @@ char *filename; struct iovec iov; struct uio uio; size_t resid; - int fd; + int fd, i; fd = open(filename, O_CREAT|O_TRUNC|O_WRONLY, 0644); if (fd == -1) { @@ -674,26 +724,27 @@ char *filename; return; } - while (1) { - bzero((char *)&iov, sizeof(iov)); - iov.iov_base = buffer; - iov.iov_len = sizeof(buffer); - - bzero((char *)&uio, sizeof(uio)); - uio.uio_iov = &iov; - uio.uio_iovcnt = 1; - uio.uio_resid = iov.iov_len; - resid = uio.uio_resid; - - if (ipflog_read(0, &uio) == 0) { - /* - * If nothing was read then break out. - */ - if (uio.uio_resid == resid) + for (i = 0; i <= IPL_LOGMAX; i++) + while (1) { + bzero((char *)&iov, sizeof(iov)); + iov.iov_base = buffer; + iov.iov_len = sizeof(buffer); + + bzero((char *)&uio, sizeof(uio)); + uio.uio_iov = &iov; + uio.uio_iovcnt = 1; + uio.uio_resid = iov.iov_len; + resid = uio.uio_resid; + + if (ipflog_read(i, &uio) == 0) { + /* + * If nothing was read then break out. + */ + if (uio.uio_resid == resid) + break; + write(fd, buffer, resid - uio.uio_resid); + } else break; - write(fd, buffer, resid - uio.uio_resid); - } else - break; } close(fd); diff --git a/usr/src/cmd/ipf/tools/ipmon.c b/usr/src/cmd/ipf/tools/ipmon.c index 80fbcbe753..0cacc6ce54 100644 --- a/usr/src/cmd/ipf/tools/ipmon.c +++ b/usr/src/cmd/ipf/tools/ipmon.c @@ -29,6 +29,7 @@ #include <string.h> #include <fcntl.h> #include <errno.h> +#include <time.h> #if !defined(__SVR4) && !defined(__svr4__) # if (__FreeBSD_version >= 300000) # include <sys/dirent.h> @@ -49,7 +50,7 @@ #include <netinet/in_systm.h> #include <net/if.h> #include <netinet/ip.h> -#if !defined(__hpux) +#if !defined(__hpux) && !defined(linux) # include <netinet/tcp_fsm.h> #endif #include <netdb.h> @@ -60,8 +61,10 @@ #endif #include <resolv.h> -#include <sys/protosw.h> -#include <netinet/ip_var.h> +#if !defined(linux) +# include <sys/protosw.h> +# include <netinet/ip_var.h> +#endif #include <netinet/tcp.h> #include <netinet/ip_icmp.h> @@ -69,26 +72,17 @@ #include <ctype.h> #include <syslog.h> -#include <netinet/tcpip.h> - -#if SOLARIS2 >= 10 -#include "ip_compat.h" -#include "ip_fil.h" -#include "ip_nat.h" -#include "ip_state.h" -#include "ip_proxy.h" -#else #include "netinet/ip_compat.h" +#include <netinet/tcpip.h> #include "netinet/ip_fil.h" #include "netinet/ip_nat.h" #include "netinet/ip_state.h" #include "netinet/ip_proxy.h" -#endif #include "ipmon.h" #if !defined(lint) static const char sccsid[] = "@(#)ipmon.c 1.21 6/5/96 (C)1993-2000 Darren Reed"; -static const char rcsid[] = "@(#)$Id: ipmon.c,v 1.22 2003/06/14 02:56:57 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id: ipmon.c,v 1.33.2.10 2005/06/18 02:41:35 darrenr Exp $"; #endif @@ -146,10 +140,8 @@ static char *pidfile = "/etc/ipmon.pid"; static char line[2048]; static int opts = 0; -static FILE *newlog = NULL; static char *logfile = NULL; static FILE *binarylog = NULL; -static FILE *newbinarylog = NULL; static char *binarylogfile = NULL; static int donehup = 0; static void usage __P((char *)); @@ -401,17 +393,7 @@ size_t tablesz; static void handlehup(sig) int sig; { - FILE *fp; - signal(SIGHUP, handlehup); - if (logfile && (fp = fopen(logfile, "a"))) - newlog = fp; - if (binarylogfile && (fp = fopen(binarylogfile, "a"))) - newbinarylog = fp; - init_tabs(); - if (conf_file) - if (load_config(conf_file) == -1) - exit(1); donehup = 1; } @@ -442,6 +424,14 @@ static void init_tabs() p->p_name != NULL && protocols[p->p_proto] == NULL) protocols[p->p_proto] = strdup(p->p_name); endprotoent(); +#if defined(_AIX51) + if (protocols[0]) + free(protocols[0]); + if (protocols[252]) + free(protocols[252]); + protocols[0] = "ip"; + protocols[252] = NULL; +#endif } if (udp_ports != NULL) { @@ -678,7 +668,7 @@ int len; sprintf((char *)t, " "); t += 8; for (k = 16; k; k--, s++) - *t++ = (isprint(*s) ? *s : '.'); + *t++ = (ISPRINT(*s) ? *s : '.'); s--; } @@ -696,7 +686,7 @@ int len; t += 7; s -= j & 0xf; for (k = j & 0xf; k; k--, s++) - *t++ = (isprint(*s) ? *s : '.'); + *t++ = (ISPRINT(*s) ? *s : '.'); *t++ = '\n'; *t = '\0'; } @@ -787,7 +777,7 @@ int blen; (long long)nl->nl_bytes[0], (long long)nl->nl_bytes[1]); #else - (void) sprintf(t, " Pkts %ld Bytes %ld", + (void) sprintf(t, " Pkts %ld/%ld Bytes %ld/%ld", nl->nl_pkts[0], nl->nl_pkts[1], nl->nl_bytes[0], nl->nl_bytes[1]); #endif @@ -876,6 +866,13 @@ int blen; (void) sprintf(t, "%s PR icmpv6 %d", hostname(res, sl->isl_v, (u_32_t *)&sl->isl_dst), sl->isl_itype); + } else { + (void) sprintf(t, "%s -> ", + hostname(res, sl->isl_v, (u_32_t *)&sl->isl_src)); + t += strlen(t); + (void) sprintf(t, "%s PR %s", + hostname(res, sl->isl_v, (u_32_t *)&sl->isl_dst), + proto); } t += strlen(t); if (sl->isl_tag != FR_NOLOGTAG) { @@ -885,7 +882,14 @@ int blen; if (sl->isl_type != ISL_NEW) { sprintf(t, #ifdef USE_QUAD_T +#ifdef PRId64 + " Forward: Pkts in %" PRId64 " Bytes in %" PRId64 + " Pkts out %" PRId64 " Bytes out %" PRId64 + " Backward: Pkts in %" PRId64 " Bytes in %" PRId64 + " Pkts out %" PRId64 " Bytes out %" PRId64, +#else " Forward: Pkts in %qd Bytes in %qd Pkts out %qd Bytes out %qd Backward: Pkts in %qd Bytes in %qd Pkts out %qd Bytes out %qd", +#endif /* PRId64 */ #else " Forward: Pkts in %ld Bytes in %ld Pkts out %ld Bytes out %ld Backward: Pkts in %ld Bytes in %ld Pkts out %ld Bytes out %ld", #endif @@ -944,25 +948,16 @@ int logtype, blen; } if (logtype == IPL_LOGIPF) { - if (ipl->ipl_magic != IPL_MAGIC) { - /* invalid data or out of sync */ - break; - } - print_ipflog(log, buf, psize); + if (ipl->ipl_magic == IPL_MAGIC) + print_ipflog(log, buf, psize); } else if (logtype == IPL_LOGNAT) { - if (ipl->ipl_magic != IPL_MAGIC) { - /* invalid data or out of sync */ - break; - } - print_natlog(log, buf, psize); + if (ipl->ipl_magic == IPL_MAGIC_NAT) + print_natlog(log, buf, psize); } else if (logtype == IPL_LOGSTATE) { - if (ipl->ipl_magic != IPL_MAGIC) { - /* invalid data or out of sync */ - break; - } - print_statelog(log, buf, psize); + if (ipl->ipl_magic == IPL_MAGIC_STATE) + print_statelog(log, buf, psize); } blen -= psize; @@ -984,9 +979,9 @@ int blen; struct icmp *icmp; struct tm *tm; char *t, *proto; - int i, v, lvl, res, len, off, plen, ipoff; - u_32_t *s, *d, cmdflags; + int i, v, lvl, res, len, off, plen, ipoff, defaction; ip_t *ipc, *ip; + u_32_t *s, *d; u_short hl, p; ipflog_t *ipf; iplog_t *ipl; @@ -1020,6 +1015,7 @@ int blen; } #if (defined(MENTAT) || \ (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199603)) || \ + (defined(__FreeBSD__) && (__FreeBSD_version >= 501113)) || \ (defined(OpenBSD) && (OpenBSD >= 199603))) || defined(linux) { char ifname[sizeof(ipf->fl_ifname) + 1]; @@ -1028,8 +1024,8 @@ int blen; ifname[sizeof(ipf->fl_ifname)] = '\0'; (void) sprintf(t, "%s", ifname); t += strlen(t); -# if defined(MENTAT) - if (isalpha(*(t - 1))) { +# if defined(MENTAT) || defined(linux) + if (ISALPHA(*(t - 1))) { sprintf(t, "%d", ipf->fl_unit); t += strlen(t); } @@ -1044,7 +1040,12 @@ int blen; (void) sprintf(t, "%*.*s%u", len, len, ipf->fl_ifname, ipf->fl_unit); t += strlen(t); #endif +#if defined(__sgi) || defined(_AIX51) || defined(__powerpc__) || \ + defined(__arm__) + if ((ipf->fl_group[0] == 255) && (ipf->fl_group[1] == '\0')) +#else if ((ipf->fl_group[0] == -1) && (ipf->fl_group[1] == '\0')) +#endif strcat(t, " @-1:"); else if (ipf->fl_group[0] == '\0') (void) strcpy(t, " @0:"); @@ -1064,7 +1065,6 @@ int blen; lvl = LOG_ERR; } - cmdflags = ipf->fl_flags & FR_CMDMASK; if (FR_ISPASS(ipf->fl_flags)) { if (ipf->fl_flags & FR_LOGP) *t++ = 'p'; @@ -1099,7 +1099,7 @@ int blen; 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); + plen = hl + ntohs(ip6->ip6_plen); #else sprintf(t, "ipv6"); goto printipflog; @@ -1218,11 +1218,13 @@ int blen; IP_HL(ipc) << 2, i); t += strlen(t); if (ipoff & IP_OFFMASK) { - (void) sprintf(t, " frag %s%s%hu@%hu", - ipoff & IP_MF ? "+" : "", - ipoff & IP_DF ? "-" : "", + (void) sprintf(t, + "(frag %d:%hu@%hu%s%s)", + ntohs(ipc->ip_id), i - (IP_HL(ipc) << 2), - (ipoff & IP_OFFMASK) << 3); + (ipoff & IP_OFFMASK) << 3, + ipoff & IP_MF ? "+" : "", + ipoff & IP_DF ? "-" : ""); } } @@ -1234,13 +1236,15 @@ int blen; hostname(res, v, d), proto, hl, plen); t += strlen(t); if (off & IP_OFFMASK) - (void) sprintf(t, " frag %s%s%hu@%hu", + (void) sprintf(t, " (frag %d:%hu@%hu%s%s)", + ntohs(ip->ip_id), + plen - hl, (off & IP_OFFMASK) << 3, ipoff & IP_MF ? "+" : "", - ipoff & IP_DF ? "-" : "", - plen - hl, (off & IP_OFFMASK) << 3); + ipoff & IP_DF ? "-" : ""); } t += strlen(t); +printipflog: if (ipf->fl_flags & FR_KEEPSTATE) { (void) strcpy(t, " K-S"); t += strlen(t); @@ -1256,25 +1260,73 @@ int blen; else if (ipf->fl_dir == 1) strcpy(t, " OUT"); t += strlen(t); - if (ipf->fl_tag) { - sprintf(t, " tag %d", ipf->fl_tag); + if (ipf->fl_logtag != 0) { + sprintf(t, " log-tag %d", ipf->fl_logtag); t += strlen(t); } -printipflog: + if (ipf->fl_nattag.ipt_num[0] != 0) { + strcpy(t, " nat-tag "); + t += strlen(t); + strncpy(t, ipf->fl_nattag.ipt_tag, sizeof(ipf->fl_nattag)); + t += strlen(t); + } + if ((ipf->fl_lflags & FI_LOWTTL) != 0) { + strcpy(t, " low-ttl"); + t += 8; + } + if ((ipf->fl_lflags & FI_OOW) != 0) { + strcpy(t, " OOW"); + t += 4; + } + if ((ipf->fl_lflags & FI_BAD) != 0) { + strcpy(t, " bad"); + t += 4; + } + if ((ipf->fl_lflags & FI_NATED) != 0) { + strcpy(t, " NAT"); + t += 4; + } + if ((ipf->fl_lflags & FI_BADNAT) != 0) { + strcpy(t, " bad-NAT"); + t += 8; + } + if ((ipf->fl_lflags & FI_BADSRC) != 0) { + strcpy(t, " bad-src"); + t += 8; + } + if ((ipf->fl_lflags & FI_MULTICAST) != 0) { + strcpy(t, " multicast"); + t += 10; + } + if ((ipf->fl_lflags & FI_BROADCAST) != 0) { + strcpy(t, " broadcast"); + t += 10; + } + if ((ipf->fl_lflags & (FI_MULTICAST|FI_BROADCAST|FI_MBCAST)) == + FI_MBCAST) { + strcpy(t, " mbcast"); + t += 7; + } *t++ = '\n'; *t++ = '\0'; - if (opts & OPT_SYSLOG) - syslog(lvl, "%s", line); - else - (void) fprintf(log, "%s", line); - if (opts & OPT_HEXHDR) - dumphex(log, opts, buf, sizeof(iplog_t) + sizeof(*ipf)); - if (opts & OPT_HEXBODY) - dumphex(log, opts, (char *)ip, ipf->fl_plen + ipf->fl_hlen); - else if ((opts & OPT_LOGBODY) && (ipf->fl_flags & FR_LOGBODY)) - dumphex(log, opts, (char *)ip + ipf->fl_hlen, ipf->fl_plen); - if (conf_file) - check_action(buf, opts, line); + defaction = 0; + if (conf_file != NULL) + defaction = check_action(buf, line, opts, lvl); + if (defaction == 0) { + if (opts & OPT_SYSLOG) + syslog(lvl, "%s", line); + else + (void) fprintf(log, "%s", line); + if (opts & OPT_HEXHDR) + dumphex(log, opts, buf, + sizeof(iplog_t) + sizeof(*ipf)); + if (opts & OPT_HEXBODY) + dumphex(log, opts, (char *)ip, + ipf->fl_plen + ipf->fl_hlen); + else if ((opts & OPT_LOGBODY) && (ipf->fl_flags & FR_LOGBODY)) + dumphex(log, opts, (char *)ip + ipf->fl_hlen, + ipf->fl_plen); + } } @@ -1378,6 +1430,7 @@ char *argv[]; { struct stat sb; FILE *log = stdout; + FILE *fp; int fd[3], doread, n, i; int tr, nr, regular[3], c; int fdt[3], devices = 0, make_daemon = 0; @@ -1581,17 +1634,18 @@ char *argv[]; tr = read_log(fd[i], &n, buf, sizeof(buf)); if (donehup) { - donehup = 0; - if (newlog) { + if (logfile && (fp = fopen(logfile, "a"))) { fclose(log); - log = newlog; - newlog = NULL; + log = fp; } - if (newbinarylog) { + if (binarylogfile && (fp = fopen(binarylogfile, "a"))) { fclose(binarylog); - binarylog = newbinarylog; - newbinarylog = NULL; + binarylog = fp; } + init_tabs(); + if (conf_file != NULL) + load_config(conf_file); + donehup = 0; } switch (tr) diff --git a/usr/src/cmd/ipf/tools/ipmon_y.y b/usr/src/cmd/ipf/tools/ipmon_y.y index b8ddb45de2..e6dda81c35 100644 --- a/usr/src/cmd/ipf/tools/ipmon_y.y +++ b/usr/src/cmd/ipf/tools/ipmon_y.y @@ -1,5 +1,11 @@ +/* + * Copyright (C) 1993-2005 by Darren Reed. + * See the IPFILTER.LICENCE file for details on licencing. + */ + %{ #include "ipf.h" +#include <syslog.h> #undef OPT_NAT #undef OPT_VERBOSE #include "ipmon_l.h" @@ -25,8 +31,9 @@ typedef struct opt { static void build_action __P((struct opt *)); static opt_t *new_opt __P((int)); +static void free_action __P((ipmon_action_t *)); -static action_t *alist = NULL; +static ipmon_action_t *alist = NULL; %} %union { @@ -37,20 +44,24 @@ static action_t *alist = NULL; union i6addr ip6; } -%token <num> YY_NUMBER YY_HEX -%token <str> YY_STR -%token YY_COMMENT -%token YY_CMP_EQ YY_CMP_NE YY_CMP_LE YY_CMP_GE YY_CMP_LT YY_CMP_GT -%token YY_RANGE_OUT YY_RANGE_IN -%token <ip6> YY_IPV6 +%token <num> YY_NUMBER YY_HEX +%token <str> YY_STR +%token <ip6> YY_IPV6 +%token YY_COMMENT +%token YY_CMP_EQ YY_CMP_NE YY_CMP_LE YY_CMP_GE YY_CMP_LT YY_CMP_GT +%token YY_RANGE_OUT YY_RANGE_IN -%token IPM_ACTION IPM_BODY IPM_COMMENT IPM_DIRECTION IPM_DSTIP IPM_DSTPORT +%token IPM_MATCH IPM_BODY IPM_COMMENT IPM_DIRECTION IPM_DSTIP IPM_DSTPORT %token IPM_EVERY IPM_EXECUTE IPM_GROUP IPM_INTERFACE IPM_IN IPM_NO IPM_OUT %token IPM_PACKET IPM_PACKETS IPM_POOL IPM_PROTOCOL IPM_RESULT IPM_RULE -%token IPM_SECOND IPM_SECONDS IPM_SRCIP IPM_SRCPORT IPM_TAG IPM_YES +%token IPM_SECOND IPM_SECONDS IPM_SRCIP IPM_SRCPORT IPM_LOGTAG IPM_WITH +%token IPM_DO IPM_SAVE IPM_SYSLOG IPM_NOTHING IPM_RAW IPM_TYPE IPM_NAT +%token IPM_STATE IPM_NATTAG IPM_IPF %type <addr> ipv4 -%type <opt> direction dstip dstport every execute group interface option -%type <opt> options protocol result rule srcip srcport tag +%type <opt> direction dstip dstport every execute group interface +%type <opt> protocol result rule srcip srcport logtag matching +%type <opt> matchopt nattag type doopt doing save syslog nothing +%type <num> saveopts saveopt typeopt %% file: line @@ -59,8 +70,10 @@ file: line | file assign ; -line: IPM_ACTION '{' options '}' ';' { build_action($3); resetlexer(); } +line: IPM_MATCH '{' matching '}' IPM_DO '{' doing '}' ';' + { build_action($3); resetlexer(); } | IPM_COMMENT + | YY_COMMENT ; assign: YY_STR assigning YY_STR ';' { set_variable($1, $3); @@ -74,16 +87,16 @@ assigning: '=' { yyvarnext = 1; } ; -options: - option { $$ = $1; } - | option ',' options { $1->o_next = $3; $$ = $1; } +matching: + matchopt { $$ = $1; } + | matchopt ',' matching { $1->o_next = $3; $$ = $1; } ; -option: direction { $$ = $1; } +matchopt: + direction { $$ = $1; } | dstip { $$ = $1; } | dstport { $$ = $1; } | every { $$ = $1; } - | execute { $$ = $1; } | group { $$ = $1; } | interface { $$ = $1; } | protocol { $$ = $1; } @@ -91,7 +104,21 @@ option: direction { $$ = $1; } | rule { $$ = $1; } | srcip { $$ = $1; } | srcport { $$ = $1; } - | tag { $$ = $1; } + | logtag { $$ = $1; } + | nattag { $$ = $1; } + | type { $$ = $1; } + ; + +doing: + doopt { $$ = $1; } + | doopt ',' doing { $1->o_next = $3; $$ = $1; } + ; + +doopt: + execute { $$ = $1; } + | save { $$ = $1; } + | syslog { $$ = $1; } + | nothing { $$ = $1; } ; direction: @@ -123,11 +150,6 @@ every: IPM_EVERY IPM_SECOND { $$ = new_opt(IPM_SECOND); $$->o_num = $2; } ; -execute: - IPM_EXECUTE '=' YY_STR { $$ = new_opt(IPM_EXECUTE); - $$->o_str = $3; } - ; - group: IPM_GROUP '=' YY_NUMBER { $$ = new_opt(IPM_GROUP); $$->o_num = $3; } | IPM_GROUP '=' YY_STR { $$ = new_opt(IPM_GROUP); @@ -139,6 +161,14 @@ interface: $$->o_str = $3; } ; +logtag: IPM_LOGTAG '=' YY_NUMBER { $$ = new_opt(IPM_LOGTAG); + $$->o_num = $3; } + ; + +nattag: IPM_NATTAG '=' YY_STR { $$ = new_opt(IPM_NATTAG); + $$->o_str = $3; } + ; + protocol: IPM_PROTOCOL '=' YY_NUMBER { $$ = new_opt(IPM_PROTOCOL); $$->o_num = $3; } @@ -168,10 +198,42 @@ srcport: $$->o_str = $3; } ; -tag: IPM_TAG '=' YY_NUMBER { $$ = new_opt(IPM_TAG); +type: IPM_TYPE '=' typeopt { $$ = new_opt(IPM_TYPE); $$->o_num = $3; } ; +typeopt: + IPM_IPF { $$ = IPL_MAGIC; } + | IPM_NAT { $$ = IPL_MAGIC_NAT; } + | IPM_STATE { $$ = IPL_MAGIC_STATE; } + ; + +execute: + IPM_EXECUTE YY_STR { $$ = new_opt(IPM_EXECUTE); + $$->o_str = $2; } + ; + +save: IPM_SAVE saveopts YY_STR { $$ = new_opt(IPM_SAVE); + $$->o_num = $2; + $$->o_str = $3; } + ; + +saveopts: { $$ = 0; } + | saveopt { $$ = $1; } + | saveopt ',' saveopts { $$ = $1 | $3; } + ; + +saveopt: + IPM_RAW { $$ = IPMDO_SAVERAW; } + ; + +syslog: IPM_SYSLOG { $$ = new_opt(IPM_SYSLOG); } + ; + +nothing: + IPM_NOTHING { $$ = 0; } + ; + ipv4: YY_NUMBER '.' YY_NUMBER '.' YY_NUMBER '.' YY_NUMBER { if ($1 > 255 || $3 > 255 || $5 > 255 || $7 > 255) { yyerror("Invalid octet string for IP address"); @@ -182,9 +244,9 @@ ipv4: YY_NUMBER '.' YY_NUMBER '.' YY_NUMBER '.' YY_NUMBER } %% static struct wordtab yywords[] = { - { "action", IPM_ACTION }, { "body", IPM_BODY }, { "direction", IPM_DIRECTION }, + { "do", IPM_DO }, { "dstip", IPM_DSTIP }, { "dstport", IPM_DSTPORT }, { "every", IPM_EVERY }, @@ -192,29 +254,39 @@ static struct wordtab yywords[] = { { "group", IPM_GROUP }, { "in", IPM_IN }, { "interface", IPM_INTERFACE }, + { "ipf", IPM_IPF }, + { "logtag", IPM_LOGTAG }, + { "match", IPM_MATCH }, + { "nat", IPM_NAT }, + { "nattag", IPM_NATTAG }, { "no", IPM_NO }, + { "nothing", IPM_NOTHING }, { "out", IPM_OUT }, { "packet", IPM_PACKET }, { "packets", IPM_PACKETS }, { "protocol", IPM_PROTOCOL }, { "result", IPM_RESULT }, { "rule", IPM_RULE }, + { "save", IPM_SAVE }, + { "raw", IPM_RAW }, { "second", IPM_SECOND }, { "seconds", IPM_SECONDS }, { "srcip", IPM_SRCIP }, { "srcport", IPM_SRCPORT }, - { "tag", IPM_TAG }, - { "yes", IPM_YES }, + { "state", IPM_STATE }, + { "syslog", IPM_SYSLOG }, + { "with", IPM_WITH }, { NULL, 0 } }; -static int macflags[15][2] = { +static int macflags[17][2] = { { IPM_DIRECTION, IPMAC_DIRECTION }, { IPM_DSTIP, IPMAC_DSTIP }, { IPM_DSTPORT, IPMAC_DSTPORT }, - { IPM_EXECUTE, IPMAC_EXECUTE }, { IPM_GROUP, IPMAC_GROUP }, { IPM_INTERFACE, IPMAC_INTERFACE }, + { IPM_LOGTAG, IPMAC_LOGTAG }, + { IPM_NATTAG, IPMAC_NATTAG }, { IPM_PACKET, IPMAC_EVERY }, { IPM_PROTOCOL, IPMAC_PROTOCOL }, { IPM_RESULT, IPMAC_RESULT }, @@ -222,7 +294,8 @@ static int macflags[15][2] = { { IPM_SECOND, IPMAC_EVERY }, { IPM_SRCIP, IPMAC_SRCIP }, { IPM_SRCPORT, IPMAC_SRCPORT }, - { IPM_TAG, IPMAC_TAG }, + { IPM_TYPE, IPMAC_TYPE }, + { IPM_WITH, IPMAC_WITH }, { 0, 0 } }; @@ -238,22 +311,26 @@ int type; o->o_line = yylineNum; o->o_num = 0; o->o_str = (char *)0; + o->o_next = NULL; return o; } static void build_action(olist) opt_t *olist; { - action_t *a; + ipmon_action_t *a; opt_t *o; - u_32_t m; char c; int i; - a = (action_t *)calloc(1, sizeof(*a)); - if (!a) + a = (ipmon_action_t *)calloc(1, sizeof(*a)); + if (a == NULL) return; - while ((o = olist)) { + while ((o = olist) != NULL) { + /* + * Check to see if the same comparator is being used more than + * once per matching statement. + */ for (i = 0; macflags[i][0]; i++) if (macflags[i][0] == o->o_type) break; @@ -276,11 +353,7 @@ opt_t *olist; break; case IPM_DSTIP : a->ac_dip = o->o_ip.s_addr; - for (i = o->o_num, m = 0; i; i--) { - m >>= 1; - m |= 0x80000000; - } - a->ac_dmsk = htonl(m); + a->ac_dmsk = htonl(0xffffffff << (32 - o->o_num)); break; case IPM_DSTPORT : a->ac_dport = htons(o->o_num); @@ -308,6 +381,12 @@ opt_t *olist; else sprintf(a->ac_group, "%d", o->o_num); break; + case IPM_LOGTAG : + a->ac_logtag = o->o_num; + break; + case IPM_NATTAG : + strncpy(a->ac_nattag, o->o_str, sizeof(a->ac_nattag)); + break; case IPM_PACKET : a->ac_packet = o->o_num; break; @@ -322,8 +401,6 @@ opt_t *olist; a->ac_result = IPMR_PASS; else if (!strcasecmp(o->o_str, "block")) a->ac_result = IPMR_BLOCK; - else if (!strcasecmp(o->o_str, "short")) - a->ac_result = IPMR_SHORT; else if (!strcasecmp(o->o_str, "nomatch")) a->ac_result = IPMR_NOMATCH; else if (!strcasecmp(o->o_str, "log")) @@ -334,17 +411,33 @@ opt_t *olist; break; case IPM_SRCIP : a->ac_sip = o->o_ip.s_addr; - for (i = o->o_num, m = 0; i; i--) { - m >>= 1; - m |= 0x80000000; - } - a->ac_smsk = htonl(m); + a->ac_smsk = htonl(0xffffffff << (32 - o->o_num)); break; case IPM_SRCPORT : a->ac_sport = htons(o->o_num); break; - case IPM_TAG : - a->ac_tag = o->o_num; + case IPM_SAVE : + if (a->ac_savefile != NULL) { + fprintf(stderr, "%s redfined on line %d\n", + yykeytostr(o->o_type), yylineNum); + break; + } + a->ac_savefile = strdup(o->o_str); + a->ac_savefp = fopen(o->o_str, "a"); + a->ac_dflag |= o->o_num & IPMDO_SAVERAW; + break; + case IPM_SYSLOG : + if (a->ac_syslog != 0) { + fprintf(stderr, "%s redfined on line %d\n", + yykeytostr(o->o_type), yylineNum); + break; + } + a->ac_syslog = 1; + break; + case IPM_TYPE : + a->ac_type = o->o_num; + break; + case IPM_WITH : break; default : break; @@ -355,54 +448,58 @@ opt_t *olist; free(o->o_str); free(o); } - a->a_next = alist; + a->ac_next = alist; alist = a; } -void check_action(buf, opts, log) -char *buf; -int opts; -char *log; +int check_action(buf, log, opts, lvl) +char *buf, *log; +int opts, lvl; { + ipmon_action_t *a; struct timeval tv; ipflog_t *ipf; tcphdr_t *tcp; iplog_t *ipl; - action_t *a; + int matched; u_long t1; ip_t *ip; + matched = 0; ipl = (iplog_t *)buf; ipf = (ipflog_t *)(ipl +1); ip = (ip_t *)(ipf + 1); tcp = (tcphdr_t *)((char *)ip + (IP_HL(ip) << 2)); - for (a = alist; a; a = a->a_next) { - if (a->ac_mflag & IPMAC_DIRECTION) { + for (a = alist; a != NULL; a = a->ac_next) { + if ((a->ac_mflag & IPMAC_DIRECTION) != 0) { if (a->ac_direction == IPM_IN) { - if (!(ipf->fl_flags & FR_INQUE)) + if ((ipf->fl_flags & FR_INQUE) == 0) continue; } else if (a->ac_direction == IPM_OUT) { - if (!(ipf->fl_flags & FR_OUTQUE)) + if ((ipf->fl_flags & FR_OUTQUE) == 0) continue; } } - if (a->ac_mflag & IPMAC_EVERY) { + if ((a->ac_type != 0) && (a->ac_type != ipl->ipl_magic)) + continue; + + if ((a->ac_mflag & IPMAC_EVERY) != 0) { gettimeofday(&tv, NULL); t1 = tv.tv_sec - a->ac_lastsec; if (tv.tv_usec <= a->ac_lastusec) t1--; - if (a->ac_second) { + if (a->ac_second != 0) { if (t1 < a->ac_second) continue; a->ac_lastsec = tv.tv_sec; a->ac_lastusec = tv.tv_usec; } - if (a->ac_packet) { - if (!a->ac_pktcnt) + if (a->ac_packet != 0) { + if (a->ac_pktcnt == 0) a->ac_pktcnt++; else if (a->ac_pktcnt == a->ac_packet) { a->ac_pktcnt = 0; @@ -414,37 +511,37 @@ char *log; } } - if (a->ac_mflag & IPMAC_DSTIP) { + if ((a->ac_mflag & IPMAC_DSTIP) != 0) { if ((ip->ip_dst.s_addr & a->ac_dmsk) != a->ac_dip) continue; } - if (a->ac_mflag & IPMAC_DSTPORT) { + if ((a->ac_mflag & IPMAC_DSTPORT) != 0) { if (ip->ip_p != IPPROTO_UDP && ip->ip_p != IPPROTO_TCP) continue; if (tcp->th_dport != a->ac_dport) continue; } - if (a->ac_mflag & IPMAC_GROUP) { + if ((a->ac_mflag & IPMAC_GROUP) != 0) { if (strncmp(a->ac_group, ipf->fl_group, FR_GROUPLEN) != 0) continue; } - if (a->ac_mflag & IPMAC_INTERFACE) { + if ((a->ac_mflag & IPMAC_INTERFACE) != 0) { if (strcmp(a->ac_iface, ipf->fl_ifname)) continue; } - if (a->ac_mflag & IPMAC_PROTOCOL) { + if ((a->ac_mflag & IPMAC_PROTOCOL) != 0) { if (a->ac_proto != ip->ip_p) continue; } - if (a->ac_mflag & IPMAC_RESULT) { - if (ipf->fl_lflags & FI_SHORT) { - if (a->ac_result != IPMR_SHORT) + if ((a->ac_mflag & IPMAC_RESULT) != 0) { + if ((ipf->fl_flags & FF_LOGNOMATCH) != 0) { + if (a->ac_result != IPMR_NOMATCH) continue; } else if (FR_ISPASS(ipf->fl_flags)) { if (a->ac_result != IPMR_PASS) @@ -452,41 +549,57 @@ char *log; } else if (FR_ISBLOCK(ipf->fl_flags)) { if (a->ac_result != IPMR_BLOCK) continue; - } else if (ipf->fl_flags & FF_LOGNOMATCH) { - if (a->ac_result != IPMR_NOMATCH) - continue; } else { /* Log only */ if (a->ac_result != IPMR_LOG) continue; } } - if (a->ac_mflag & IPMAC_RULE) { + if ((a->ac_mflag & IPMAC_RULE) != 0) { if (a->ac_rule != ipf->fl_rule) continue; } - if (a->ac_mflag & IPMAC_SRCIP) { + if ((a->ac_mflag & IPMAC_SRCIP) != 0) { if ((ip->ip_src.s_addr & a->ac_smsk) != a->ac_sip) continue; } - if (a->ac_mflag & IPMAC_SRCPORT) { + if ((a->ac_mflag & IPMAC_SRCPORT) != 0) { if (ip->ip_p != IPPROTO_UDP && ip->ip_p != IPPROTO_TCP) continue; if (tcp->th_sport != a->ac_sport) continue; } - if (a->ac_mflag & IPMAC_TAG) { - if (a->ac_tag != ipf->fl_tag) + if ((a->ac_mflag & IPMAC_LOGTAG) != 0) { + if (a->ac_logtag != ipf->fl_logtag) continue; } + if ((a->ac_mflag & IPMAC_NATTAG) != 0) { + if (strncmp(a->ac_nattag, ipf->fl_nattag.ipt_tag, + IPFTAG_LEN) != 0) + continue; + } + + matched = 1; + /* * It matched so now execute the command */ - if (a->ac_exec) { + if (a->ac_syslog != 0) { + syslog(lvl, "%s", log); + } + + if (a->ac_savefp != NULL) { + if (a->ac_dflag & IPMDO_SAVERAW) + fwrite(ipl, 1, ipl->ipl_dsize, a->ac_savefp); + else + fputs(log, a->ac_savefp); + } + + if (a->ac_exec != NULL) { switch (fork()) { case 0 : @@ -494,14 +607,14 @@ char *log; FILE *pi; pi = popen(a->ac_run, "w"); - if (pi) { + if (pi != NULL) { fprintf(pi, "%s\n", log); - if (opts & OPT_HEXHDR) { + if ((opts & OPT_HEXHDR) != 0) { dumphex(pi, 0, buf, sizeof(*ipl) + sizeof(*ipf)); } - if (opts & OPT_HEXBODY) { + if ((opts & OPT_HEXBODY) != 0) { dumphex(pi, 0, (char *)ip, ipf->fl_hlen + ipf->fl_plen); @@ -517,15 +630,60 @@ char *log; } } } + + return matched; +} + + +static void free_action(a) +ipmon_action_t *a; +{ + if (a->ac_savefile != NULL) { + free(a->ac_savefile); + a->ac_savefile = NULL; + } + if (a->ac_savefp != NULL) { + fclose(a->ac_savefp); + a->ac_savefp = NULL; + } + if (a->ac_exec != NULL) { + free(a->ac_exec); + if (a->ac_run == a->ac_exec) + a->ac_run = NULL; + a->ac_exec = NULL; + } + if (a->ac_run != NULL) { + free(a->ac_run); + a->ac_run = NULL; + } + if (a->ac_iface != NULL) { + free(a->ac_iface); + a->ac_iface = NULL; + } + a->ac_next = NULL; + free(a); } int load_config(file) char *file; { + ipmon_action_t *a; FILE *fp; + char *s; + + s = getenv("YYDEBUG"); + if (s != NULL) + yydebug = atoi(s); + else + yydebug = 0; + + while ((a = alist) != NULL) { + alist = a->ac_next; + free_action(a); + } - yylineNum = 0; + yylineNum = 1; (void) yysettab(yywords); diff --git a/usr/src/cmd/ipf/tools/ipnat.c b/usr/src/cmd/ipf/tools/ipnat.c index e1d93224c6..6989a511f1 100644 --- a/usr/src/cmd/ipf/tools/ipnat.c +++ b/usr/src/cmd/ipf/tools/ipnat.c @@ -5,7 +5,7 @@ * * Added redirect stuff and a variety of bug fixes. (mcn@EnGarde.com) * - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -49,9 +49,13 @@ #include <arpa/inet.h> #include <resolv.h> #include <ctype.h> -#include <nlist.h> +#if defined(linux) +# include <linux/a.out.h> +#else +# include <nlist.h> +#endif #include "ipf.h" -#include "ipl.h" +#include "netinet/ipl.h" #include "kmem.h" #ifdef __hpux @@ -67,7 +71,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[] = "@(#)$Id: ipnat.c,v 1.20 2003/07/01 16:30:27 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id: ipnat.c,v 1.24.2.2 2005/05/10 21:19:30 darrenr Exp $"; #endif @@ -90,7 +94,7 @@ int opts; void usage(name) char *name; { - fprintf(stderr, "Usage: %s [-CdFhlnrsv] [-f filename]\n", name); + fprintf(stderr, "Usage: %s [-CFhlnrRsv] [-f filename]\n", name); exit(1); } @@ -112,7 +116,7 @@ char *argv[]; kernel = NULL; mode = O_RDWR; - while ((c = getopt(argc, argv, "CdFf:hlM:N:nrsv")) != -1) + while ((c = getopt(argc, argv, "CdFf:hlM:N:nrRsv")) != -1) switch (c) { case 'C' : @@ -144,6 +148,9 @@ char *argv[]; opts |= OPT_DONOTHING; mode = O_RDONLY; break; + case 'R' : + opts |= OPT_NORESOLVE; + break; case 'r' : opts |= OPT_REMOVE; break; @@ -313,7 +320,7 @@ int opts; break; } if (opts & OPT_HITS) - printf("%d ", ipn.in_hits); + printf("%lu ", ipn.in_hits); printnat(&ipn, opts & (OPT_DEBUG|OPT_VERBOSE)); nsp->ns_list = ipn.in_next; } @@ -324,6 +331,8 @@ int opts; if (kmemcpy((char *)&nat, (long)np, sizeof(nat))) break; printactivenat(&nat, opts); + if (nat.nat_aps) + printaps(nat.nat_aps, opts); } if (opts & OPT_VERBOSE) diff --git a/usr/src/cmd/ipf/tools/ipnat_y.y b/usr/src/cmd/ipf/tools/ipnat_y.y index 064a6abe35..e382d78afd 100644 --- a/usr/src/cmd/ipf/tools/ipnat_y.y +++ b/usr/src/cmd/ipf/tools/ipnat_y.y @@ -4,7 +4,7 @@ * * See the IPFILTER.LICENCE file for details on licencing. * - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #pragma ident "%Z%%M% %I% %E% SMI" @@ -33,11 +33,6 @@ #include <stddef.h> #include <sys/socket.h> #include <sys/ioctl.h> -#ifdef IPFILTER_BPF -# include <net/bpf.h> -# include <pcap-int.h> -# include <pcap.h> -#endif #include <netinet/in.h> #include <netinet/in_systm.h> #include <sys/time.h> @@ -46,17 +41,11 @@ #if __FreeBSD_version >= 300000 # include <net/if_var.h> #endif -#include <netinet/ip.h> -#include <netinet/ip_icmp.h> #include <netdb.h> #include <arpa/nameser.h> #include <resolv.h> #include "ipf.h" -#if SOLARIS2 >= 10 -#include "ipl.h" -#else #include "netinet/ipl.h" -#endif #include "ipnat_l.h" #define YYDEBUG 1 @@ -84,6 +73,7 @@ static void setnatproto __P((int)); struct in_addr ipa; frentry_t fr; frtuc_t *frt; + u_short port; struct { u_short p1; u_short p2; @@ -108,7 +98,8 @@ static void setnatproto __P((int)); %token IPNY_ROUNDROBIN IPNY_FRAG IPNY_AGE IPNY_ICMPIDMAP IPNY_PROXY %token IPNY_TCP IPNY_UDP IPNY_TCPUDP IPNY_STICKY IPNY_MSSCLAMP IPNY_TAG %token IPNY_TLATE -%type <num> hexnumber numports compare range proto +%type <port> portspec +%type <num> hexnumber compare range proto %type <ipa> hostname ipv4 %type <ipp> addr nummask rhaddr %type <pc> portstuff @@ -143,13 +134,17 @@ assigning: xx: { newnatrule(); } ; -rule: map - | mapblock - | redir +rule: map eol + | mapblock eol + | redir eol + ; + +eol: | ';' ; map: mapit ifnames addr IPNY_TLATE rhaddr proxy mapoptions - { nat->in_inip = $3.a.s_addr; + { nat->in_v = 4; + nat->in_inip = $3.a.s_addr; nat->in_inmsk = $3.m.s_addr; nat->in_outip = $5.a.s_addr; nat->in_outmsk = $5.m.s_addr; @@ -164,7 +159,8 @@ map: mapit ifnames addr IPNY_TLATE rhaddr proxy mapoptions nat_setgroupmap(nat); } | mapit ifnames addr IPNY_TLATE rhaddr mapport mapoptions - { nat->in_inip = $3.a.s_addr; + { nat->in_v = 4; + nat->in_inip = $3.a.s_addr; nat->in_inmsk = $3.m.s_addr; nat->in_outip = $5.a.s_addr; nat->in_outmsk = $5.m.s_addr; @@ -172,14 +168,15 @@ map: mapit ifnames addr IPNY_TLATE rhaddr proxy mapoptions strncpy(nat->in_ifnames[1], nat->in_ifnames[0], sizeof(nat->in_ifnames[0])); - if ((nat->in_flags & IPN_TCPUDP) == 0) + if ((nat->in_flags & IPN_TCPUDPICMPQ) == 0) setnatproto(nat->in_p); if (((nat->in_redir & NAT_MAPBLK) != 0) || ((nat->in_flags & IPN_AUTOPORTMAP) != 0)) nat_setgroupmap(nat); } | mapit ifnames mapfrom IPNY_TLATE rhaddr proxy mapoptions - { nat->in_outip = $5.a.s_addr; + { nat->in_v = 4; + nat->in_outip = $5.a.s_addr; nat->in_outmsk = $5.m.s_addr; if (nat->in_ifnames[1][0] == '\0') strncpy(nat->in_ifnames[1], @@ -192,13 +189,14 @@ map: mapit ifnames addr IPNY_TLATE rhaddr proxy mapoptions nat_setgroupmap(nat); } | mapit ifnames mapfrom IPNY_TLATE rhaddr mapport mapoptions - { nat->in_outip = $5.a.s_addr; + { nat->in_v = 4; + nat->in_outip = $5.a.s_addr; nat->in_outmsk = $5.m.s_addr; if (nat->in_ifnames[1][0] == '\0') strncpy(nat->in_ifnames[1], nat->in_ifnames[0], sizeof(nat->in_ifnames[0])); - if ((nat->in_flags & IPN_TCPUDP) == 0) + if ((nat->in_flags & IPN_TCPUDPICMPQ) == 0) setnatproto(nat->in_p); if (((nat->in_redir & NAT_MAPBLK) != 0) || ((nat->in_flags & IPN_AUTOPORTMAP) != 0)) @@ -208,7 +206,8 @@ map: mapit ifnames addr IPNY_TLATE rhaddr proxy mapoptions mapblock: mapblockit ifnames addr IPNY_TLATE addr ports mapoptions - { nat->in_inip = $3.a.s_addr; + { nat->in_v = 4; + nat->in_inip = $3.a.s_addr; nat->in_inmsk = $3.m.s_addr; nat->in_outip = $5.a.s_addr; nat->in_outmsk = $5.m.s_addr; @@ -224,8 +223,9 @@ mapblock: } ; -redir: rdrit ifnames addr dport IPNY_TLATE dip nport rdrproto rdroptions - { nat->in_outip = $3.a.s_addr; +redir: rdrit ifnames addr dport IPNY_TLATE dip nport setproto rdroptions + { nat->in_v = 4; + nat->in_outip = $3.a.s_addr; nat->in_outmsk = $3.m.s_addr; if (nat->in_ifnames[1][0] == '\0') strncpy(nat->in_ifnames[1], @@ -238,8 +238,9 @@ redir: rdrit ifnames addr dport IPNY_TLATE dip nport rdrproto rdroptions nat->in_pnext != 0)) setnatproto(IPPROTO_TCP); } - | rdrit ifnames rdrfrom IPNY_TLATE dip nport rdrproto rdroptions - { if ((nat->in_p == 0) && + | rdrit ifnames rdrfrom IPNY_TLATE dip nport setproto rdroptions + { nat->in_v = 4; + if ((nat->in_p == 0) && ((nat->in_flags & IPN_TCPUDP) == 0) && (nat->in_pmin != 0 || nat->in_pmax != 0 || @@ -250,8 +251,9 @@ redir: rdrit ifnames addr dport IPNY_TLATE dip nport rdrproto rdroptions nat->in_ifnames[0], sizeof(nat->in_ifnames[0])); } - | rdrit ifnames addr IPNY_TLATE dip rdrproto rdroptions - { nat->in_outip = $3.a.s_addr; + | rdrit ifnames addr IPNY_TLATE dip setproto rdroptions + { nat->in_v = 4; + nat->in_outip = $3.a.s_addr; nat->in_outmsk = $3.m.s_addr; if (nat->in_ifnames[1][0] == '\0') strncpy(nat->in_ifnames[1], @@ -260,7 +262,7 @@ redir: rdrit ifnames addr dport IPNY_TLATE dip nport rdrproto rdroptions } ; -proxy: | IPNY_PROXY IPNY_PORT YY_NUMBER YY_STR '/' proto +proxy: | IPNY_PROXY IPNY_PORT portspec YY_STR '/' proto { strncpy(nat->in_plabel, $4, sizeof(nat->in_plabel)); if (nat->in_dcmp == 0) { nat->in_dport = htons($3); @@ -271,24 +273,35 @@ proxy: | IPNY_PROXY IPNY_PORT YY_NUMBER YY_STR '/' proto free($4); } | IPNY_PROXY IPNY_PORT YY_STR YY_STR '/' proto - { strncpy(nat->in_plabel, $4, sizeof(nat->in_plabel)); - nat->in_dport = getportproto($3, $6); + { int pnum; + strncpy(nat->in_plabel, $4, sizeof(nat->in_plabel)); + pnum = getportproto($3, $6); + if (pnum == -1) + yyerror("invalid port number"); + nat->in_dport = pnum; setnatproto($6); free($3); free($4); } ; -rdrproto: - | IPNY_TCP { setnatproto(IPPROTO_TCP); } - | IPNY_UDP { setnatproto(IPPROTO_UDP); } - | IPNY_TCPUDP { nat->in_flags |= IPN_TCPUDP; - nat->in_p = 0; } - | IPNY_TCP '/' IPNY_UDP { nat->in_flags |= IPN_TCPUDP; - nat->in_p = 0; } - | YY_NUMBER { setnatproto($1); } - | YY_STR { setnatproto(getproto($1)); - free($1); +setproto: + | proto { if (nat->in_p != 0 || + nat->in_flags & IPN_TCPUDP) + yyerror("protocol set twice"); + setnatproto($1); + } + | IPNY_TCPUDP { if (nat->in_p != 0 || + nat->in_flags & IPN_TCPUDP) + yyerror("protocol set twice"); + nat->in_flags |= IPN_TCPUDP; + nat->in_p = 0; + } + | IPNY_TCP '/' IPNY_UDP { if (nat->in_p != 0 || + nat->in_flags & IPN_TCPUDP) + yyerror("protocol set twice"); + nat->in_flags |= IPN_TCPUDP; + nat->in_p = 0; } ; @@ -296,29 +309,43 @@ rhaddr: addr { $$.a = $1.a; $$.m = $1.m; } | IPNY_RANGE ipv4 '-' ipv4 { $$.a = $2; $$.m = $4; nat->in_flags |= IPN_IPRANGE; } + ; + dip: - ipv4 { nat->in_inip = $1.s_addr; + hostname { nat->in_inip = $1.s_addr; nat->in_inmsk = 0xffffffff; } - | ipv4 '/' YY_NUMBER { nat->in_inip = $1.s_addr; - if (nat->in_inip != 0 || - ($3 != 0 && $3 != 32)) - yyerror("Invalid mask for dip"); - ntomask(4, $3, &nat->in_inmsk); } - | ipv4 ',' ipv4 { nat->in_flags |= IPN_SPLIT; + | hostname ',' hostname { nat->in_flags |= IPN_SPLIT; nat->in_inip = $1.s_addr; nat->in_inmsk = $3.s_addr; } ; -dport: | IPNY_PORT YY_NUMBER { nat->in_pmin = htons($2); +portspec: + YY_NUMBER { if ($1 > 65535) /* Unsigned */ + yyerror("invalid port number"); + else + $$ = $1; + } + | YY_STR { if (getport(NULL, $1, &($$)) == -1) + yyerror("invalid port number"); + $$ = ntohs($$); + } + ; + +dport: | IPNY_PORT portspec { nat->in_pmin = htons($2); nat->in_pmax = htons($2); } - | IPNY_PORT YY_NUMBER '-' YY_NUMBER { nat->in_pmin = htons($2); + | IPNY_PORT portspec '-' portspec { nat->in_pmin = htons($2); + nat->in_pmax = htons($4); } + | IPNY_PORT portspec ':' portspec { nat->in_pmin = htons($2); nat->in_pmax = htons($4); } ; -nport: IPNY_PORT YY_NUMBER { nat->in_pnext = htons($2); } +nport: IPNY_PORT portspec { nat->in_pnext = htons($2); } + | IPNY_PORT '=' portspec { nat->in_pnext = htons($3); + nat->in_flags |= IPN_FIXEDDPORT; + } ; -ports: | IPNY_PORTS numports { nat->in_pmin = $2; } +ports: | IPNY_PORTS YY_NUMBER { nat->in_pmin = $2; } | IPNY_PORTS IPNY_AUTO { nat->in_flags |= IPN_AUTOPORTMAP; } ; @@ -353,26 +380,44 @@ ifnames: | ifname ',' otherifname ; -ifname: YY_STR { strncpy(nat->in_ifnames[0], $1, - sizeof(nat->in_ifnames[0])); - free($1); - } +ifname: YY_STR { strncpy(nat->in_ifnames[0], $1, + sizeof(nat->in_ifnames[0])); + nat->in_ifnames[0][LIFNAMSIZ - 1] = '\0'; + free($1); + } ; otherifname: - YY_STR { strncpy(nat->in_ifnames[1], $1, - sizeof(nat->in_ifnames[1])); - free($1); - } + YY_STR { strncpy(nat->in_ifnames[1], $1, + sizeof(nat->in_ifnames[1])); + nat->in_ifnames[1][LIFNAMSIZ - 1] = '\0'; + free($1); + } ; mapport: - IPNY_PORTMAP tcpudp YY_NUMBER ':' YY_NUMBER - { nat->in_pmin = htons($3); - nat->in_pmax = htons($5); } - | IPNY_PORTMAP tcpudp IPNY_AUTO { nat->in_flags |= IPN_AUTOPORTMAP; - nat->in_pmin = htons(1024); - nat->in_pmax = htons(65535); } + IPNY_PORTMAP tcpudp portspec ':' portspec + { nat->in_pmin = htons($3); + nat->in_pmax = htons($5); + } + | IPNY_PORTMAP tcpudp IPNY_AUTO + { nat->in_flags |= IPN_AUTOPORTMAP; + nat->in_pmin = htons(1024); + nat->in_pmax = htons(65535); + } + | IPNY_ICMPIDMAP YY_STR YY_NUMBER ':' YY_NUMBER + { if (strcmp($2, "icmp") != 0) { + yyerror("icmpidmap not followed by icmp"); + } + free($2); + if ($3 < 0 || $3 > 65535) + yyerror("invalid ICMP Id number"); + if ($5 < 0 || $5 > 65535) + yyerror("invalid ICMP Id number"); + nat->in_flags = IPN_ICMPQUERY; + nat->in_pmin = htons($3); + nat->in_pmax = htons($5); + } ; sobject: @@ -433,12 +478,12 @@ nummask: ; portstuff: - compare YY_NUMBER { $$.pc = $1; $$.p1 = $2; } - | YY_NUMBER range YY_NUMBER { $$.pc = $2; $$.p1 = $1; $$.p2 = $3; } + compare portspec { $$.pc = $1; $$.p1 = $2; } + | portspec range portspec { $$.pc = $2; $$.p1 = $1; $$.p1 = $3; } ; mapoptions: - rr frag age mssclamp nattag + rr frag age mssclamp nattag setproto ; rdroptions: @@ -484,10 +529,11 @@ tcpudp: | IPNY_TCP { setnatproto(IPPROTO_TCP); } ; rdrproxy: - | IPNY_PROXY YY_STR + IPNY_PROXY YY_STR { strncpy(nat->in_plabel, $2, sizeof(nat->in_plabel)); nat->in_dport = nat->in_pnext; + nat->in_dport = htons(nat->in_dport); free($2); } | proxy { if (nat->in_plabel[0] != '\0') { @@ -498,10 +544,6 @@ rdrproxy: } ; -numports: - YY_NUMBER { $$ = $1; } - ; - proto: YY_NUMBER { $$ = $1; } | IPNY_TCP { $$ = IPPROTO_TCP; } | IPNY_UDP { $$ = IPPROTO_UDP; } @@ -562,6 +604,7 @@ static wordtab_t yywords[] = { { "map", IPNY_MAP }, { "map-block", IPNY_MAPBLOCK }, { "mssclamp", IPNY_MSSCLAMP }, + { "netmask", IPNY_MASK }, { "port", IPNY_PORT }, { "portmap", IPNY_PORTMAP }, { "ports", IPNY_PORTS }, @@ -572,6 +615,7 @@ static wordtab_t yywords[] = { { "sticky", IPNY_STICKY }, { "tag", IPNY_TAG }, { "tcp", IPNY_TCP }, + { "tcpudp", IPNY_TCPUDP }, { "to", IPNY_TO }, { "udp", IPNY_UDP }, { "-", '-' }, @@ -689,8 +733,23 @@ int p; nat->in_flags |= IPN_UDP; nat->in_flags &= ~IPN_TCP; break; + case IPPROTO_ICMP : + nat->in_flags &= ~IPN_TCPUDP; + if (!(nat->in_flags & IPN_ICMPQUERY)) { + nat->in_dcmp = 0; + nat->in_scmp = 0; + nat->in_pmin = 0; + nat->in_pmax = 0; + nat->in_pnext = 0; + } + break; default : if ((nat->in_redir & NAT_MAPBLK) == 0) { + /* Only reset dcmp/scmp in case dport/sport not set */ + if (0 == nat->in_tuc.ftu_dport) + nat->in_dcmp = 0; + if (0 == nat->in_tuc.ftu_sport) + nat->in_scmp = 0; nat->in_pmin = 0; nat->in_pmax = 0; nat->in_pnext = 0; @@ -698,6 +757,9 @@ int p; } break; } + + if ((nat->in_flags & (IPN_TCPUDP|IPN_FIXEDDPORT)) == IPN_FIXEDDPORT) + nat->in_flags &= ~IPN_FIXEDDPORT; } @@ -706,8 +768,8 @@ int fd; ioctlfunc_t ioctlfunc; void *ptr; { + ioctlcmd_t add, del; ipfobj_t obj; - int add, del; ipnat_t *ipn; ipn = ptr; diff --git a/usr/src/cmd/ipf/tools/ippool.c b/usr/src/cmd/ipf/tools/ippool.c index da6cc9273e..9e7919c757 100644 --- a/usr/src/cmd/ipf/tools/ippool.c +++ b/usr/src/cmd/ipf/tools/ippool.c @@ -3,7 +3,7 @@ * * See the IPFILTER.LICENCE file for details on licencing. * - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -35,15 +35,9 @@ #include <unistd.h> #include "ipf.h" -#if SOLARIS2 >= 10 -#include "ip_lookup.h" -#include "ip_pool.h" -#include "ip_htable.h" -#else #include "netinet/ip_lookup.h" #include "netinet/ip_pool.h" #include "netinet/ip_htable.h" -#endif #include "kmem.h" @@ -142,7 +136,7 @@ char *argv[]; role = IPL_LOGIPF; bzero((char *)&node, sizeof(node)); - while ((c = getopt(argc, argv, "di:m:no:v")) != -1) + while ((c = getopt(argc, argv, "di:m:no:Rv")) != -1) switch (c) { case 'd' : @@ -162,7 +156,9 @@ char *argv[]; if (s != NULL) *s = '\0'; ipset = 1; + node.ipn_addr.adf_len = sizeof(node.ipn_addr); node.ipn_addr.adf_addr.in4.s_addr = inet_addr(optarg); + node.ipn_mask.adf_len = sizeof(node.ipn_mask); node.ipn_mask.adf_addr.in4.s_addr = mask.s_addr; break; case 'm' : @@ -176,11 +172,17 @@ char *argv[]; if (role == IPL_LOGNONE) return -1; break; + case 'R' : + opts |= OPT_NORESOLVE; + break; case 'v' : opts |= OPT_VERBOSE; break; } + if (opts & OPT_DEBUG) + fprintf(stderr, "poolnodecommand: opts = %#x\n", opts); + if (ipset == 0) return -1; if (poolname == NULL) { @@ -213,7 +215,7 @@ char *argv[]; bzero((char *)&iph, sizeof(iph)); bzero((char *)&pool, sizeof(pool)); - while ((c = getopt(argc, argv, "dm:no:S:t:v")) != -1) + while ((c = getopt(argc, argv, "dm:no:RSt:v")) != -1) switch (c) { case 'd' : @@ -233,6 +235,9 @@ char *argv[]; return -1; } break; + case 'R' : + opts |= OPT_NORESOLVE; + break; case 'S' : iph.iph_seed = atoi(optarg); break; @@ -248,6 +253,9 @@ char *argv[]; break; } + if (opts & OPT_DEBUG) + fprintf(stderr, "poolcommand: opts = %#x\n", opts); + if (poolname == NULL) { fprintf(stderr, "poolname not given with add/remove pool\n"); return -1; @@ -296,7 +304,7 @@ char *argv[], *infile; infile = optarg; - while ((c = getopt(argc, argv, "dnrv")) != -1) + while ((c = getopt(argc, argv, "dnRuv")) != -1) switch (c) { case 'd' : @@ -306,7 +314,10 @@ char *argv[], *infile; case 'n' : opts |= OPT_DONOTHING; break; - case 'r' : + case 'R' : + opts |= OPT_NORESOLVE; + break; + case 'u' : opts |= OPT_REMOVE; break; case 'v' : @@ -314,6 +325,9 @@ char *argv[], *infile; break; } + if (opts & OPT_DEBUG) + fprintf(stderr, "loadpoolfile: opts = %#x\n", opts); + if (!(opts & OPT_DONOTHING) && (fd == -1)) { fd = open(IPLOOKUP_NAME, O_RDWR); if (fd == -1) { @@ -347,7 +361,7 @@ char *argv[]; poolname = NULL; role = IPL_LOGALL; - while ((c = getopt(argc, argv, "dm:M:N:o:t:v")) != -1) + while ((c = getopt(argc, argv, "dm:M:N:o:Rt:v")) != -1) switch (c) { case 'd' : @@ -371,6 +385,9 @@ char *argv[]; return -1; } break; + case 'R' : + opts |= OPT_NORESOLVE; + break; case 't' : type = gettype(optarg, NULL); if (type == IPLT_NONE) { @@ -418,14 +435,15 @@ char *argv[]; if (role != IPL_LOGALL) { ptr = plstp->ipls_list[role]; while (ptr != NULL) { - ptr = printpool(ptr, kmemcpywrap, opts); + ptr = printpool(ptr, kmemcpywrap, poolname, + opts); } } else { for (role = 0; role <= IPL_LOGMAX; role++) { ptr = plstp->ipls_list[role]; while (ptr != NULL) { ptr = printpool(ptr, kmemcpywrap, - opts); + poolname, opts); } } role = IPL_LOGALL; @@ -445,14 +463,15 @@ char *argv[]; if (role != IPL_LOGALL) { hptr = htstp->iphs_tables; while (hptr != NULL) { - hptr = printhash(hptr, kmemcpywrap, opts); + hptr = printhash(hptr, kmemcpywrap, + poolname, opts); } } else { for (role = 0; role <= IPL_LOGMAX; role++) { hptr = htstp->iphs_tables; while (hptr != NULL) { hptr = printhash(hptr, kmemcpywrap, - opts); + poolname, opts); } op.iplo_unit = role; @@ -601,6 +620,9 @@ char *argv[]; break; } + if (opts & OPT_DEBUG) + fprintf(stderr, "poolflush: opts = %#x\n", opts); + if (!(opts & OPT_DONOTHING) && (fd == -1)) { fd = open(IPLOOKUP_NAME, O_RDWR); if (fd == -1) { @@ -665,7 +687,7 @@ u_int *minor; { int type; - if (!strcasecmp(optarg, "pool")) { + if (!strcasecmp(optarg, "tree")) { type = IPLT_POOL; } else if (!strcasecmp(optarg, "hash")) { type = IPLT_HASH; diff --git a/usr/src/cmd/ipf/tools/ippool_y.y b/usr/src/cmd/ipf/tools/ippool_y.y index a952538c39..a074dff823 100644 --- a/usr/src/cmd/ipf/tools/ippool_y.y +++ b/usr/src/cmd/ipf/tools/ippool_y.y @@ -4,7 +4,7 @@ * * See the IPFILTER.LICENCE file for details on licencing. * - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -36,15 +36,9 @@ #include <unistd.h> #include "ipf.h" -#if SOLARIS2 >= 10 -#include "ip_lookup.h" -#include "ip_pool.h" -#include "ip_htable.h" -#else #include "netinet/ip_lookup.h" #include "netinet/ip_pool.h" #include "netinet/ip_htable.h" -#endif #include "ippool_l.h" #include "kmem.h" @@ -164,25 +158,23 @@ role: ; ipftree: - IPT_TYPE '=' IPT_TREE number '{' { yyexpectaddr = 1; } - addrlist '}' + IPT_TYPE '=' IPT_TREE number start addrlist end { strncpy(iplo.ipo_name, $4, sizeof(iplo.ipo_name)); - $$ = $7; + $$ = $6; } ; ipfhash: - IPT_TYPE '=' IPT_HASH number hashopts '{' { yyexpectaddr = 1; } - hashlist '}' + IPT_TYPE '=' IPT_HASH number hashopts start hashlist end { strncpy(ipht.iph_name, $4, sizeof(ipht.iph_name)); - $$ = $8; + $$ = $7; } ; ipfgroup: - setgroup hashopts '{' grouplist '}' + setgroup hashopts start grouplist end { iphtent_t *e; for (e = $4; e != NULL; e = e->ipe_next) @@ -192,10 +184,10 @@ ipfgroup: FR_GROUPLEN); $$ = $4; } - | hashopts '{' setgrouplist '}' { $$ = $3; } + | hashopts start setgrouplist end { $$ = $3; } ; -number: IPT_NUM '=' YY_NUMBER { sprintf(poolname, "%u", $3); +number: IPT_NUM '=' YY_NUMBER { snprintf(poolname, FR_GROUPLEN, "%u", $3); $$ = poolname; } | IPT_NAME '=' YY_STR { $$ = $3; } @@ -208,7 +200,7 @@ setgroup: $$ = strdup(tmp); } | IPT_GROUP '=' YY_NUMBER { char tmp[FR_GROUPLEN+1]; - sprintf(tmp, "%u", $3); + snprintf(tmp, FR_GROUPLEN, "%u", $3); $$ = strdup(tmp); } ; @@ -220,14 +212,15 @@ hashopts: ; addrlist: - next { $$ = NULL; } + ';' { $$ = NULL; } | range next addrlist { $1->ipn_next = $3; $$ = $1; } | range next { $$ = $1; } - | range { $$ = $1; } + | range ; grouplist: - groupentry next grouplist { $$ = $1; $1->ipe_next = $3; } + ';' { $$ = NULL; } + | groupentry next grouplist { $$ = $1; $1->ipe_next = $3; } | addrmask next grouplist { $$ = calloc(1, sizeof(iphtent_t)); if ($$ == NULL) yyerror("sorry, out of memory"); @@ -242,7 +235,8 @@ grouplist: (char *)&($$->ipe_mask), sizeof($$->ipe_mask)); set_ipv6_addr = 0; - $$->ipe_next = $3; } + $$->ipe_next = $3; + } | groupentry next { $$ = $1; } | addrmask next { $$ = calloc(1, sizeof(iphtent_t)); if ($$ == NULL) @@ -262,34 +256,38 @@ grouplist: ; setgrouplist: - groupentry next { $$ = $1; } + ';' { $$ = NULL; } + | groupentry next { $$ = $1; } | groupentry next setgrouplist { $1->ipe_next = $3; $$ = $1; } ; groupentry: - addrmask ',' setgroup { $$ = calloc(1, sizeof(iphtent_t)); - if ($$ == NULL) - yyerror("sorry, out of memory"); - if (set_ipv6_addr) - $$->ipe_family = AF_INET6; - else - $$->ipe_family = AF_INET; - bcopy((char *)&($1[0]), - (char *)&($$->ipe_addr), - sizeof($$->ipe_addr)); - bcopy((char *)&($1[1]), - (char *)&($$->ipe_mask), - sizeof($$->ipe_mask)); - set_ipv6_addr = 0; - strncpy($$->ipe_group, $3, FR_GROUPLEN); - free($3); } - + addrmask ',' setgroup { $$ = calloc(1, sizeof(iphtent_t)); + if ($$ == NULL) + yyerror("sorry, out of memory"); + if (set_ipv6_addr) + $$->ipe_family = AF_INET6; + else + $$->ipe_family = AF_INET; + bcopy((char *)&($1[0]), + (char *)&($$->ipe_addr), + sizeof($$->ipe_addr)); + bcopy((char *)&($1[1]), + (char *)&($$->ipe_mask), + sizeof($$->ipe_mask)); + set_ipv6_addr = 0; + strncpy($$->ipe_group, $3, + FR_GROUPLEN); + free($3); + } ; range: addrmask { $$ = calloc(1, sizeof(*$$)); if ($$ == NULL) yyerror("sorry, out of memory"); $$->ipn_info = 0; + $$->ipn_addr.adf_len = sizeof($$->ipn_addr); + $$->ipn_mask.adf_len = sizeof($$->ipn_mask); if (set_ipv6_addr) { $$->ipn_addr.adf_family = AF_INET6; $$->ipn_addr.adf_addr = $1[0]; @@ -306,6 +304,8 @@ range: addrmask { $$ = calloc(1, sizeof(*$$)); if ($$ == NULL) yyerror("sorry, out of memory"); $$->ipn_info = 1; + $$->ipn_addr.adf_len = sizeof($$->ipn_addr); + $$->ipn_mask.adf_len = sizeof($$->ipn_mask); if (set_ipv6_addr) { $$->ipn_addr.adf_family = AF_INET6; $$->ipn_addr.adf_addr = $2[0]; @@ -319,12 +319,13 @@ range: addrmask { $$ = calloc(1, sizeof(*$$)); } hashlist: - hashentry next { $$ = $1; } + ';' { $$ = NULL; } + | hashentry next { $$ = $1; } | hashentry next hashlist { $1->ipe_next = $3; $$ = $1; } ; hashentry: - addrmask { $$ = calloc(1, sizeof(iphtent_t)); + addrmask { $$ = calloc(1, sizeof(iphtent_t)); if ($$ == NULL) yyerror("sorry, out of memory"); if (set_ipv6_addr) @@ -337,34 +338,49 @@ hashentry: bcopy((char *)&($1[1]), (char *)&($$->ipe_mask), sizeof($$->ipe_mask)); - set_ipv6_addr = 0; } ; addrmask: - ipaddr '/' mask { $$[0] = $1; $$[1] = $3; } - | ipaddr { $$[0] = $1; + ipaddr '/' mask { $$[0] = $1; $$[1] = $3; + yyexpectaddr = 0; + } + | ipaddr { $$[0] = $1; + yyexpectaddr = 0; if (set_ipv6_addr) fill6bits(128, (u_32_t *)$$[1].in6.s6_addr); else - $$[1].in4.s_addr = 0xffffffff; } + $$[1].in4.s_addr = 0xffffffff; + } ; ipaddr: ipv4 { $$ = $1; } | YY_NUMBER { $$.in4.s_addr = htonl($1); } - | YY_IPV6 { set_ipv6_addr = 1; + | YY_IPV6 { set_ipv6_addr = 1; bcopy(&$1, &$$, sizeof($$)); yyexpectaddr = 0; } + | YY_STR { if (gethost($1, &($$.in4.s_addr)) == -1) + yyerror("Unknown hostname"); + } ; mask: YY_NUMBER { if (set_ipv6_addr) - ntomask(6, $1, (u_32_t *)$$.in6.s6_addr); + ntomask(6, $1, (u_32_t *)$$.in6.s6_addr); else - ntomask(4, $1, (u_32_t *)&$$.in4.s_addr); - } + ntomask(4, $1, (u_32_t *)&$$.in4.s_addr); } | ipv4 { $$ = $1; } ; +start: '{' { yyexpectaddr = 1; } + ; + +end: '}' { yyexpectaddr = 0; } + ; + +next: ',' { yyexpectaddr = 1; } + | ';' { yyexpectaddr = 1; } + ; + size: IPT_SIZE '=' YY_NUMBER { ipht.iph_size = $3; } ; @@ -380,12 +396,6 @@ ipv4: YY_NUMBER '.' YY_NUMBER '.' YY_NUMBER '.' YY_NUMBER $$.in4.s_addr = htonl($$.in4.s_addr); } ; - -next: ';' { yyexpectaddr = 1; } - | ',' { yyexpectaddr = 1; } - ; - - %% static wordtab_t yywords[] = { { "auth", IPT_AUTH }, diff --git a/usr/src/cmd/ipf/tools/lexer.c b/usr/src/cmd/ipf/tools/lexer.c index 72425e4589..39975a55ce 100644 --- a/usr/src/cmd/ipf/tools/lexer.c +++ b/usr/src/cmd/ipf/tools/lexer.c @@ -3,7 +3,7 @@ * * See the IPFILTER.LICENCE file for details on licencing. * - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -30,7 +30,7 @@ union { FILE *yyin; -#define ishex(c) (isdigit(c) || ((c) >= 'a' && (c) <= 'f') || \ +#define ishex(c) (ISDIGIT(c) || ((c) >= 'a' && (c) <= 'f') || \ ((c) >= 'A' && (c) <= 'F')) #define TOOLONG -3 @@ -61,13 +61,14 @@ static int yyswallow __P((int)); static char *yytexttostr __P((int, int)); static void yystrtotext __P((char *)); - static int yygetc() { int c; if (yypos < yylast) { c = yytext[yypos++]; + if (c == '\n') + yylineNum++; return c; } @@ -79,9 +80,9 @@ static int yygetc() yypos++; } else { c = fgetc(yyin); - if (c == '\n') - yylineNum++; } + if (c == '\n') + yylineNum++; yytext[yypos++] = c; yylast = yypos; yytext[yypos] = '\0'; @@ -93,6 +94,8 @@ static int yygetc() static void yyunputc(c) int c; { + if (c == '\n') + yylineNum--; yytext[--yypos] = c; } @@ -186,6 +189,8 @@ nextchar: } yylast -= yypos; yypos = 0; + lnext = 0; + nokey = 0; goto nextchar; case '\\' : @@ -205,6 +210,9 @@ nextchar: if (lnext == 1) { lnext = 0; + if ((isbuilding == 0) && !ISALNUM(c)) { + return c; + } goto nextchar; } @@ -232,13 +240,13 @@ nextchar: } (void) yygetc(); } else { - if (!isalpha(n)) { + if (!ISALPHA(n)) { yyunputc(n); break; } do { n = yygetc(); - } while (isalpha(n) || isdigit(n) || n == '_'); + } while (ISALPHA(n) || ISDIGIT(n) || n == '_'); yyunputc(n); } @@ -290,7 +298,6 @@ nextchar: yybreakondot = 0; yyvarnext = 0; yytokentype = 0; - yysavedepth = 0; return 0; } @@ -447,10 +454,10 @@ nextchar: /* * No negative numbers with leading - sign.. */ - if (isbuilding == 0 && isdigit(c)) { + if (isbuilding == 0 && ISDIGIT(c)) { do { n = yygetc(); - } while (isdigit(n)); + } while (ISDIGIT(n)); yyunputc(n); rval = YY_NUMBER; goto done; @@ -488,12 +495,13 @@ done: yytokentype = rval; if (yydebug) - printf("lexed(%s) => %d\n", yystr, rval); + printf("lexed(%s) [%d,%d,%d] => %d\n", yystr, string_start, + string_end, pos, rval); switch (rval) { case YY_NUMBER : - yylval.num = atoi(yystr); + sscanf(yystr, "%u", &yylval.num); break; case YY_HEX : diff --git a/usr/src/common/ipf/ipl.h b/usr/src/common/ipf/ipl.h deleted file mode 100644 index 5ae34d6599..0000000000 --- a/usr/src/common/ipf/ipl.h +++ /dev/null @@ -1,18 +0,0 @@ -/* - * Copyright (C) 1999-2001, 2003 by Darren Reed. - * See the IPFILTER.LICENCE file for details on licencing. - * - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifndef __IPL_H__ -#define __IPL_H__ - -#define IPL_VERSION "IP Filter: v4.0.3" - -#define IPFILTER_VERSION 4000300 - -#endif /* __IPL_H__ */ diff --git a/usr/src/common/ipf/solaris.c b/usr/src/common/ipf/solaris.c deleted file mode 100644 index f4ac8ff761..0000000000 --- a/usr/src/common/ipf/solaris.c +++ /dev/null @@ -1,1122 +0,0 @@ -/* - * Copyright (C) 1993-2001, 2003 by Darren Reed. - * See the IPFILTER.LICENCE file for details on licencing. - * - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include <sys/systm.h> -#include <sys/types.h> -#include <sys/param.h> -#include <sys/errno.h> -#include <sys/uio.h> -#include <sys/buf.h> -#include <sys/modctl.h> -#include <sys/open.h> -#include <sys/kmem.h> -#include <sys/conf.h> -#include <sys/cmn_err.h> -#include <sys/stat.h> -#include <sys/cred.h> -#include <sys/dditypes.h> -#include <sys/stream.h> -#include <sys/poll.h> -#include <sys/autoconf.h> -#include <sys/byteorder.h> -#include <sys/socket.h> -#include <sys/dlpi.h> -#include <sys/stropts.h> -#include <sys/kstat.h> -#include <sys/sockio.h> -#include <net/if.h> -#if SOLARIS2 >= 6 -# include <net/if_types.h> -#endif -#include <net/af.h> -#include <net/route.h> -#include <netinet/in.h> -#include <netinet/in_systm.h> -#include <netinet/if_ether.h> -#include <netinet/ip.h> -#include <netinet/ip_var.h> -#include <netinet/tcp.h> -#include <netinet/udp.h> -#include <netinet/tcpip.h> -#include <netinet/ip_icmp.h> -#include <sys/ddi.h> -#include <sys/sunddi.h> -#include "ip_compat.h" -#include "ipl.h" -#include "ip_fil.h" -#include "ip_nat.h" -#include "ip_frag.h" -#include "ip_auth.h" -#include "ip_state.h" -#if SOLARIS2 >= 10 -#include "pfild.h" -#endif - - -extern struct filterstats frstats[]; -extern ipfrwlock_t ipf_mutex, ipf_nat, ipf_global; -extern ipfmutex_t ipf_rw, ipf_timeoutlock; -extern int fr_running; -extern int fr_flags; -#ifdef IPFILTER_SYNC -extern int iplwrite __P((dev_t, struct uio *, cred_t *)); -#endif - -extern ipnat_t *nat_list; - -static int ipf_getinfo __P((dev_info_t *, ddi_info_cmd_t, - void *, void **)); -#if SOLARIS2 < 10 -static int ipf_identify __P((dev_info_t *)); -#endif -static int ipf_attach __P((dev_info_t *, ddi_attach_cmd_t)); -static int ipf_detach __P((dev_info_t *, ddi_detach_cmd_t)); -static int fr_qifsync __P((ip_t *, int, void *, int, qif_t *, mblk_t **)); -static char *ipf_devfiles[] = { IPL_NAME, IPNAT_NAME, IPSTATE_NAME, - IPAUTH_NAME, IPSYNC_NAME, IPSCAN_NAME, - IPLOOKUP_NAME, NULL }; - - -#if SOLARIS2 >= 7 -void fr_slowtimer __P((void *)); -timeout_id_t fr_timer_id; -static timeout_id_t synctimeoutid = 0; -#else -void fr_slowtimer __P((void)); -int fr_timer_id; -static int synctimeoutid = 0; -#endif - -#ifndef IRE_ILL_CN -#ifdef IPFDEBUG -void printire __P((ire_t *)); -#endif -#endif - -static struct cb_ops ipf_cb_ops = { - iplopen, - iplclose, - nodev, /* strategy */ - nodev, /* print */ - nodev, /* dump */ - iplread, -#ifdef IPFILTER_SYNC - iplwrite, /* write */ -#else - nodev, /* write */ -#endif - iplioctl, /* ioctl */ - nodev, /* devmap */ - nodev, /* mmap */ - nodev, /* segmap */ - nochpoll, /* poll */ - ddi_prop_op, - NULL, - D_MTSAFE, -#if SOLARIS2 > 4 - CB_REV, - nodev, /* aread */ - nodev, /* awrite */ -#endif -}; - -static struct dev_ops ipf_ops = { - DEVO_REV, - 0, - ipf_getinfo, -#if SOLARIS2 >= 10 - nulldev, -#else - ipf_identify, -#endif - nulldev, - ipf_attach, - ipf_detach, - nodev, /* reset */ - &ipf_cb_ops, - (struct bus_ops *)0 -}; - -extern struct mod_ops mod_driverops; -static struct modldrv iplmod = { - &mod_driverops, IPL_VERSION, &ipf_ops }; -static struct modlinkage modlink1 = { MODREV_1, &iplmod, NULL }; - -#if SOLARIS2 >= 6 -static size_t hdrsizes[57][2] = { - { 0, 0 }, - { IFT_OTHER, 0 }, - { IFT_1822, 0 }, - { IFT_HDH1822, 0 }, - { IFT_X25DDN, 0 }, - { IFT_X25, 0 }, - { IFT_ETHER, 14 }, - { IFT_ISO88023, 0 }, - { IFT_ISO88024, 0 }, - { IFT_ISO88025, 0 }, - { IFT_ISO88026, 0 }, - { IFT_STARLAN, 0 }, - { IFT_P10, 0 }, - { IFT_P80, 0 }, - { IFT_HY, 0 }, - { IFT_FDDI, 24 }, - { IFT_LAPB, 0 }, - { IFT_SDLC, 0 }, - { IFT_T1, 0 }, - { IFT_CEPT, 0 }, - { IFT_ISDNBASIC, 0 }, - { IFT_ISDNPRIMARY, 0 }, - { IFT_PTPSERIAL, 0 }, - { IFT_PPP, 0 }, - { IFT_LOOP, 0 }, - { IFT_EON, 0 }, - { IFT_XETHER, 0 }, - { IFT_NSIP, 0 }, - { IFT_SLIP, 0 }, - { IFT_ULTRA, 0 }, - { IFT_DS3, 0 }, - { IFT_SIP, 0 }, - { IFT_FRELAY, 0 }, - { IFT_RS232, 0 }, - { IFT_PARA, 0 }, - { IFT_ARCNET, 0 }, - { IFT_ARCNETPLUS, 0 }, - { IFT_ATM, 0 }, - { IFT_MIOX25, 0 }, - { IFT_SONET, 0 }, - { IFT_X25PLE, 0 }, - { IFT_ISO88022LLC, 0 }, - { IFT_LOCALTALK, 0 }, - { IFT_SMDSDXI, 0 }, - { IFT_FRELAYDCE, 0 }, - { IFT_V35, 0 }, - { IFT_HSSI, 0 }, - { IFT_HIPPI, 0 }, - { IFT_MODEM, 0 }, - { IFT_AAL5, 0 }, - { IFT_SONETPATH, 0 }, - { IFT_SONETVT, 0 }, - { IFT_SMDSICIP, 0 }, - { IFT_PROPVIRTUAL, 0 }, - { IFT_PROPMUX, 0 }, -}; -#endif /* SOLARIS2 >= 6 */ - -static dev_info_t *ipf_dev_info = NULL; - -static const filter_kstats_t ipf_kstat_tmp = { - { "pass", KSTAT_DATA_ULONG }, - { "block", KSTAT_DATA_ULONG }, - { "nomatch", KSTAT_DATA_ULONG }, - { "short", KSTAT_DATA_ULONG }, - { "pass, logged", KSTAT_DATA_ULONG }, - { "block, logged", KSTAT_DATA_ULONG }, - { "nomatch, logged", KSTAT_DATA_ULONG }, - { "logged", KSTAT_DATA_ULONG }, - { "skip", KSTAT_DATA_ULONG }, - { "return sent", KSTAT_DATA_ULONG }, - { "acct", KSTAT_DATA_ULONG }, - { "bad frag state alloc", KSTAT_DATA_ULONG }, - { "new frag state kept", KSTAT_DATA_ULONG }, - { "new frag state compl. pkt", KSTAT_DATA_ULONG }, - { "bad pkt state alloc", KSTAT_DATA_ULONG }, - { "new pkt kept state", KSTAT_DATA_ULONG }, - { "cachehit", KSTAT_DATA_ULONG }, - { "tcp cksum bad", KSTAT_DATA_ULONG }, - {{ "pullup ok", KSTAT_DATA_ULONG }, - { "pullup nok", KSTAT_DATA_ULONG }}, - { "src != route", KSTAT_DATA_ULONG }, - { "ttl invalid", KSTAT_DATA_ULONG }, - { "bad ip pkt", KSTAT_DATA_ULONG }, - { "ipv6 pkt", KSTAT_DATA_ULONG }, - { "dropped:pps ceiling", KSTAT_DATA_ULONG }, - { "ip upd. fail", KSTAT_DATA_ULONG } -}; - -kstat_t *ipf_kstatp[2] = {NULL, NULL}; -static int ipf_kstat_update(kstat_t *ksp, int rwflag); - -static void -ipf_kstat_init(void) -{ - int i; - - for (i = 0; i < 2; i++) { - ipf_kstatp[i] = kstat_create("ipf", 0, - (i==0)?"inbound":"outbound", - "net", - KSTAT_TYPE_NAMED, - sizeof (filter_kstats_t) / sizeof (kstat_named_t), - 0); - if (ipf_kstatp[i] != NULL) { - bcopy(&ipf_kstat_tmp, ipf_kstatp[i]->ks_data, - sizeof (filter_kstats_t)); - ipf_kstatp[i]->ks_update = ipf_kstat_update; - ipf_kstatp[i]->ks_private = &frstats[i]; - kstat_install(ipf_kstatp[i]); - } - } - -#ifdef IPFDEBUG - cmn_err(CE_NOTE, "IP Filter: ipf_kstat_init() installed 0x%x, 0x%x", - ipf_kstatp[0], ipf_kstatp[1]); -#endif -} - -static void -ipf_kstat_fini(void) -{ - int i; - for (i = 0; i < 2; i++) { - if (ipf_kstatp[i] != NULL) { - kstat_delete(ipf_kstatp[i]); - ipf_kstatp[i] = NULL; - } - } -} - -static int -ipf_kstat_update(kstat_t *ksp, int rwflag) -{ - filter_kstats_t *fkp; - filterstats_t *fsp; - - if (rwflag == KSTAT_WRITE) - return (EACCES); - - fkp = ksp->ks_data; - fsp = ksp->ks_private; - - fkp->fks_pass.value.ul = fsp->fr_pass; - fkp->fks_block.value.ul = fsp->fr_block; - fkp->fks_nom.value.ul = fsp->fr_nom; - fkp->fks_short.value.ul = fsp->fr_short; - fkp->fks_ppkl.value.ul = fsp->fr_ppkl; - fkp->fks_bpkl.value.ul = fsp->fr_bpkl; - fkp->fks_npkl.value.ul = fsp->fr_npkl; - fkp->fks_pkl.value.ul = fsp->fr_pkl; - fkp->fks_skip.value.ul = fsp->fr_skip; - fkp->fks_ret.value.ul = fsp->fr_ret; - fkp->fks_acct.value.ul = fsp->fr_acct; - fkp->fks_bnfr.value.ul = fsp->fr_bnfr; - fkp->fks_nfr.value.ul = fsp->fr_nfr; - fkp->fks_cfr.value.ul = fsp->fr_cfr; - fkp->fks_bads.value.ul = fsp->fr_bads; - fkp->fks_ads.value.ul = fsp->fr_ads; - fkp->fks_chit.value.ul = fsp->fr_chit; - fkp->fks_tcpbad.value.ul = fsp->fr_tcpbad; - fkp->fks_pull[0].value.ul = fsp->fr_pull[0]; - fkp->fks_pull[1].value.ul = fsp->fr_pull[1]; - fkp->fks_badsrc.value.ul = fsp->fr_badsrc; - fkp->fks_badttl.value.ul = fsp->fr_badttl; - fkp->fks_bad.value.ul = fsp->fr_bad; - fkp->fks_ipv6.value.ul = fsp->fr_ipv6; - fkp->fks_ppshit.value.ul = fsp->fr_ppshit; - fkp->fks_ipud.value.ul = fsp->fr_ipud; - - return (0); -} - -int _init() -{ - int status; - - /* - * Initialize mutex's - */ - RWLOCK_INIT(&ipf_global, "ipf filter load/unload mutex"); - RWLOCK_INIT(&ipf_mutex, "ipf filter rwlock"); - ipf_kstat_init(); - status = mod_install(&modlink1); - if (status != 0) { - RW_DESTROY(&ipf_mutex); - RW_DESTROY(&ipf_global); - ipf_kstat_fini(); - } - - return status; -} - - -int _fini(void) -{ - int status; - - status = mod_remove(&modlink1); - if (status != 0) - return status; - ipf_kstat_fini(); - RW_DESTROY(&ipf_mutex); - RW_DESTROY(&ipf_global); - return status; -} - - -int _info(modinfop) -struct modinfo *modinfop; -{ - int status; - - status = mod_info(&modlink1, modinfop); - return status; -} - - -#if SOLARIS2 < 10 -static int ipf_identify(dip) -dev_info_t *dip; -{ -#ifdef IPFDEBUG - cmn_err(CE_NOTE, "IP Filter: ipf_identify(%x)", dip); -#endif - if (strcmp(ddi_get_name(dip), "ipf") == 0) - return (DDI_IDENTIFIED); - return (DDI_NOT_IDENTIFIED); -} -#endif - - -static int ipf_attach(dip, cmd) -dev_info_t *dip; -ddi_attach_cmd_t cmd; -{ - char *s; - int i; - int instance; - -#ifdef IPFDEBUG - cmn_err(CE_NOTE, "IP Filter: ipf_attach(%x,%x)", dip, cmd); -#endif - - - switch (cmd) - { - case DDI_ATTACH: - instance = ddi_get_instance(dip); - /* Only one instance of ipf (instance 0) can be attached.*/ - if (instance > 0) - return DDI_FAILURE; - if (fr_running != 0) - return DDI_FAILURE; - - if (pfilinterface != PFIL_INTERFACE) { -#ifdef IPFDEBUG - cmn_err(CE_NOTE, "pfilinterface(%d) != %d", - pfilinterface, PFIL_INTERFACE); -#endif - return DDI_FAILURE; - } - - if (ddi_prop_update_int(DDI_DEV_T_NONE, dip, DDI_NO_AUTODETACH, - 1) != DDI_PROP_SUCCESS) { -#ifdef IPFDEBUG - cmn_err(CE_WARN, "!updating %s failed", - DDI_NO_AUTODETACH); -#endif - return DDI_FAILURE; - } - - for (i = 0; ((s = ipf_devfiles[i]) != NULL); i++) { - s = strrchr(s, '/'); - if (s == NULL) - continue; - s++; - if (ddi_create_minor_node(dip, s, S_IFCHR, i, - DDI_PSEUDO, 0) == - DDI_FAILURE) { - ddi_remove_minor_node(dip, NULL); - return DDI_FAILURE; - } - } - - ipf_dev_info = dip; - /* - * Lock people out while we set things up. - */ - WRITE_ENTER(&ipf_global); - if ((fr_running != 0) || (iplattach() == -1)) { - RWLOCK_EXIT(&ipf_global); -#ifdef IPFDEBUG - cmn_err(CE_NOTE, "IP Filter: iplattach() failed"); -#endif - goto attach_failed; - } - - if (pfil_add_hook(fr_check, PFIL_IN|PFIL_OUT, &pfh_inet4)) { - RWLOCK_EXIT(&ipf_global); - goto attach_failed; - } - -#ifdef USE_INET6 - if (pfil_add_hook(fr_check, PFIL_IN|PFIL_OUT, &pfh_inet6)) { - RWLOCK_EXIT(&ipf_global); - goto attach_failed; - } -#endif - - if (pfil_add_hook(fr_qifsync, PFIL_IN|PFIL_OUT, &pfh_sync)) { - RWLOCK_EXIT(&ipf_global); - goto attach_failed; - } - - fr_timer_id = timeout(fr_slowtimer, NULL, - drv_usectohz(500000)); - - fr_running = 1; - - RWLOCK_EXIT(&ipf_global); - - cmn_err(CE_CONT, "!%s, running.\n", ipfilter_version); - - return DDI_SUCCESS; - /* NOTREACHED */ - default: - return DDI_FAILURE; - } - -attach_failed: -#ifdef IPFDEBUG - cmn_err(CE_NOTE, "IP Filter: failed to attach"); -#endif - /* - * Use our own detach routine to toss - * away any stuff we allocated above. - */ - (void) ipf_detach(dip, DDI_DETACH); - return DDI_FAILURE; -} - - -static int ipf_detach(dip, cmd) -dev_info_t *dip; -ddi_detach_cmd_t cmd; -{ - int i; - -#ifdef IPFDEBUG - cmn_err(CE_NOTE, "IP Filter: ipf_detach(%x,%x)", dip, cmd); -#endif - switch (cmd) { - case DDI_DETACH: - if (fr_running == -2 || fr_running == 0) { -#ifdef IPFDEBUG - cmn_err(CE_NOTE, "IP Filter: not yet attached " - "or already detached"); -#endif - break; - } - /* - * Make sure we're the only one's modifying things. With - * this lock others should just fall out of the loop. - */ - WRITE_ENTER(&ipf_global); - if (fr_running <= 0) { - RWLOCK_EXIT(&ipf_global); - return DDI_FAILURE; - } - fr_running = -2; - - (void) pfil_remove_hook(fr_check, PFIL_IN|PFIL_OUT, &pfh_inet4); -#ifdef USE_INET6 - (void) pfil_remove_hook(fr_check, PFIL_IN|PFIL_OUT, &pfh_inet6); -#endif - (void) pfil_remove_hook(fr_qifsync, PFIL_IN|PFIL_OUT, &pfh_sync); - - RWLOCK_EXIT(&ipf_global); - - if (fr_timer_id != 0) { - (void) untimeout(fr_timer_id); - fr_timer_id = 0; - } - - /* - * Undo what we did in ipf_attach, freeing resources - * and removing things we installed. The system - * framework guarantees we are not active with this devinfo - * node in any other entry points at this time. - */ - ddi_prop_remove_all(dip); - i = ddi_get_instance(dip); - ddi_remove_minor_node(dip, NULL); - if (i > 0) { -#ifdef IPFDEBUG - cmn_err(CE_CONT, "IP Filter: still attached (%d)\n", i); -#endif - return DDI_FAILURE; - } - - WRITE_ENTER(&ipf_global); - if (!ipldetach()) { - RWLOCK_EXIT(&ipf_global); -#ifdef IPFDEBUG - cmn_err(CE_CONT, "!%s detached.\n", ipfilter_version); -#endif - return (DDI_SUCCESS); - } - RWLOCK_EXIT(&ipf_global); -#ifdef IPFDEBUG - cmn_err(CE_NOTE, "IP Filter: ipldetach() failed"); -#endif - break; - default: - return DDI_FAILURE; - } -#ifdef IPFDEBUG - cmn_err(CE_NOTE, "IP Filter: failed to detach"); -#endif - return DDI_FAILURE; -} - - -/*ARGSUSED*/ -static int ipf_getinfo(dip, infocmd, arg, result) -dev_info_t *dip; -ddi_info_cmd_t infocmd; -void *arg, **result; -{ - int error; - - if (fr_running <= 0) - return DDI_FAILURE; - error = DDI_FAILURE; -#ifdef IPFDEBUG - cmn_err(CE_NOTE, "IP Filter: ipf_getinfo(%x,%x,%x)", dip, infocmd, arg); -#endif - switch (infocmd) { - case DDI_INFO_DEVT2DEVINFO: - *result = ipf_dev_info; - error = DDI_SUCCESS; - break; - case DDI_INFO_DEVT2INSTANCE: - *result = (void *)0; - error = DDI_SUCCESS; - break; - default: - break; - } - return (error); -} - - -/* - * look for bad consistancies between the list of interfaces the filter knows - * about and those which are currently configured. - */ -/*ARGSUSED*/ -static int fr_qifsync(ip, hlen, il, out, qif, mp) -ip_t *ip; -int hlen; -void *il; -int out; -qif_t *qif; -mblk_t **mp; -{ - - frsync(); - /* - * Resync. any NAT `connections' using this interface and its IP #. - */ - fr_natsync(il); - fr_statesync(il); - return 0; -} - - -/* - * look for bad consistancies between the list of interfaces the filter knows - * about and those which are currently configured. - */ -int ipfsync() -{ - qif_t *qf; - - frsync(); - /* - * Resync. any NAT `connections' using this interface and its IP #. - */ - qf = NULL; - while (qif_walk(&qf)) - (void) fr_qifsync(NULL, 0, (void *)qf->qf_ill, -1, qf, NULL); - return 0; -} - -#ifndef IRE_ILL_CN -#ifdef IPFDEBUG -void printire(ire) -ire_t *ire; -{ - printf("ire: ll_hdr_mp %p rfq %p stq %p src_addr %x max_frag %d\n", -# if SOLARIS2 >= 8 - NULL, -# else - ire->ire_ll_hdr_mp, -# endif - ire->ire_rfq, ire->ire_stq, - ire->ire_src_addr, ire->ire_max_frag); - printf("ire: mask %x addr %x gateway_addr %x type %d\n", - ire->ire_mask, ire->ire_addr, ire->ire_gateway_addr, - ire->ire_type); - printf("ire: ll_hdr_length %d ll_hdr_saved_mp %p\n", - ire->ire_ll_hdr_length, -# if SOLARIS2 >= 8 - NULL -# else - ire->ire_ll_hdr_saved_mp -# endif - ); - -} -#endif -#endif /* IRE_ILL_CN */ - -/* - * Function: fr_fastroute - * Returns: 0: success; - * -1: failed - * Parameters: - * mb: the message block where ip head starts - * mpp: the pointer to the pointer of the orignal - * packet message - * fin: packet information - * fdp: destination interface information - * if it is NULL, no interface information provided. - * - * This function is for fastroute/to/dup-to rules. It calls - * pfil_make_lay2_packet to search route, make lay-2 header - * ,and identify output queue for the IP packet. - * The destination address depends on the following conditions: - * 1: for fastroute rule, fdp is passed in as NULL, so the - * destination address is the IP Packet's destination address - * 2: for to/dup-to rule, if an ip address is specified after - * the interface name, this address is the as destination - * address. Otherwise IP Packet's destination address is used - */ -int fr_fastroute(mb, mpp, fin, fdp) -mblk_t *mb, **mpp; -fr_info_t *fin; -frdest_t *fdp; -{ -#ifndef IRE_ILL_CN - ire_t *ir, *dir; - struct in_addr dst; - ill_t *ifp; - u_char *s; - size_t hlen = 0; - frdest_t fd; -#else - void *target = NULL; - char *ifname = NULL; - s_ill_t *ifp; -#endif - queue_t *q = NULL; - mblk_t *mp = NULL; - frentry_t *fr = fin->fin_fr; - qif_t *qf; - ip_t *ip; -#ifndef sparc - u_short __iplen, __ipoff; -#endif -#ifndef IRE_ILL_CN -#ifdef USE_INET6 - ip6_t *ip6 = (ip6_t *)fin->fin_ip; -#endif -#endif - ip = fin->fin_ip; - qf = fin->fin_qif; - - /* - * If this is a duplicate mblk then we want ip to point at that - * data, not the original, if and only if it is already pointing at - * the current mblk data. - * - * Otherwise, if it's not a duplicate, and we're not already pointing - * at the current mblk data, then we want to ensure that the data - * points at ip. - */ - - if ((ip == (ip_t *)qf->qf_m->b_rptr) && (qf->qf_m != mb)) { - ip = (ip_t *)mb->b_rptr; - } else if ((qf->qf_m == mb) && (ip != (ip_t *)qf->qf_m->b_rptr)) { - qf->qf_m->b_rptr = (uchar_t *)ip; - qf->qf_off = 0; - } - - /* - * If there is another M_PROTO, we don't want it - */ - if (*mpp != mb) { - mp = unlinkb(*mpp); - freeb(*mpp); - *mpp = mp; - } - - - /* - * In case we're here due to "to <if>" being used with - * "keep state", check that we're going in the correct - * direction. - */ - if (fdp != NULL) { - if ((fr != NULL) && (fdp->fd_ifp != NULL) && - (fin->fin_rev != 0) && (fdp == &fr->fr_tif)) - goto bad_fastroute; - } - -#ifndef IRE_ILL_CN - if (!fdp) { - ipif_t *ipif; - - ifp = fin->fin_ifp; - ipif = ifp->ill_ipif; - if (!ipif) - goto bad_fastroute; -#if SOLARIS2 > 5 - ir = ire_ctable_lookup(ipif->ipif_local_addr, 0, IRE_LOCAL, - NULL, NULL, MATCH_IRE_TYPE); -#else - ir = ire_lookup_myaddr(ipif->ipif_local_addr); -#endif - if (!ir) - ir = (ire_t *)-1; - - fd.fd_ifp = (struct ifnet *)ir; - fd.fd_ip = ip->ip_dst; - fdp = &fd; - } - - ir = (ire_t *)fdp->fd_ifp; - - if (fdp->fd_ip.s_addr) - dst = fdp->fd_ip; - else - dst.s_addr = fin->fin_fi.fi_daddr; - -#if SOLARIS2 >= 6 - if (fin->fin_v == 4) { - dir = ire_route_lookup(dst.s_addr, 0xffffffff, 0, 0, NULL, - NULL, NULL, MATCH_IRE_DSTONLY| - MATCH_IRE_DEFAULT|MATCH_IRE_RECURSIVE); - } -#ifdef USE_INET6 - else if (fin->fin_v == 6) { - dir = ire_route_lookup_v6(&ip6->ip6_dst, NULL, 0, 0, - NULL, NULL, NULL, MATCH_IRE_DSTONLY| - MATCH_IRE_DEFAULT|MATCH_IRE_RECURSIVE); - } -#endif -#else - dir = ire_lookup(dst.s_addr); -#endif -#if SOLARIS2 < 8 - if (dir) - if (!dir->ire_ll_hdr_mp || !dir->ire_ll_hdr_length) - dir = NULL; -#else - if (dir) - if (!dir->ire_fp_mp || !dir->ire_dlureq_mp) - dir = NULL; -#endif - - if (!ir) - ir = dir; - - if (!ir || !dir) - goto bad_fastroute; - -#if SOLARIS2 < 8 - mp = dir->ire_ll_hdr_mp; - hlen = dir->ire_ll_hdr_length; -#else - mp = dir->ire_fp_mp; - hlen = mp ? mp->b_wptr - mp->b_rptr : 0; - if (mp == NULL) - mp = dir->ire_dlureq_mp; -#endif - if (mp != NULL) { - s = mb->b_rptr; - if ( -#if SOLARIS2 >= 6 - (dohwcksum && - ifp->ill_ick.ick_magic == ICK_M_CTL_MAGIC) || -#endif - (hlen && (s - mb->b_datap->db_base) >= hlen)) { - s -= hlen; - mb->b_rptr = (u_char *)s; - bcopy((char *)mp->b_rptr, (char *)s, hlen); - } else { - mblk_t *mp2; - - mp2 = copyb(mp); - if (!mp2) - goto bad_fastroute; - linkb(mp2, mb); - mb = mp2; - } - } - - if (ir->ire_stq) - q = ir->ire_stq; - else if (ir->ire_rfq) - q = WR(ir->ire_rfq); - if (q) - q = q->q_next; - if (!q) - goto bad_fastroute; - - ifp = ire_to_ill(ir); - if (ifp == NULL) - goto bad_fastroute; - - fin->fin_ifp = ifp; -#else /* IRE_ILL_CN */ - if (fin->fin_v == 4) { - if (fdp && (fdp->fd_ip.s_addr != 0)) - target = &fdp->fd_ip; - } -#ifdef USE_INET6 - else if (fin->fin_v == 6) { - if (fdp && !IN6_IS_ADDR_UNSPECIFIED(&fdp->fd_ip6.in6)) - target = &fdp->fd_ip6.in6; - } -#endif - else - goto bad_fastroute; - - if (fdp && fdp->fd_ifname[0] != 0) - ifname = fdp->fd_ifname; - - mp = pfil_make_dl_packet(mb, ip, target, ifname, &q); - if (mp == NULL) - { - goto bad_fastroute; - } - mb = mp; - /* - * Determine the s_ill_t we're going out on - */ - ifp = ((qif_t *)(q->q_ptr))->qf_ill; -#endif /* IRE_ILL_CN */ - - mb->b_queue = q; - *mpp = mb; - - if (fin->fin_out == 0) { - void *saveifp; - u_32_t pass; - - saveifp = fin->fin_ifp; - fin->fin_ifp = ifp; - (void)fr_acctpkt(fin, &pass); - fin->fin_fr = NULL; - if (!fr || !(fr->fr_flags & FR_RETMASK)) - (void) fr_checkstate(fin, &pass); - (void) fr_checknatout(fin, NULL); - fin->fin_ifp = saveifp; - } -#ifndef sparc - if (fin->fin_v == 4) { - __iplen = (u_short)ip->ip_len, - __ipoff = (u_short)ip->ip_off; - - ip->ip_len = htons(__iplen); - ip->ip_off = htons(__ipoff); - } -#endif - -#ifndef IRE_ILL_CN -#if SOLARIS2 >= 6 - if ((p == IPPROTO_TCP) && dohwcksum && - (ifp->ill_ick.ick_magic == ICK_M_CTL_MAGIC)) { - tcphdr_t *tcp; - u_32_t t; - - tcp = (tcphdr_t *)((char *)ip + fin->fin_hlen); - t = ip->ip_src.s_addr; - t += ip->ip_dst.s_addr; - t += 30; - t = (t & 0xffff) + (t >> 16); - tcp->th_sum = t & 0xffff; - } -#endif - RWLOCK_EXIT(&ipf_global); - putnext(q, mb); - READ_ENTER(&ipf_global); -#else /* IRE_ILL_CN */ - pfil_send_dl_packet(q, mb); -#endif /* IRE_ILL_CN */ - fr_frouteok[0]++; - return 0; -bad_fastroute: - freemsg(mb); - fr_frouteok[1]++; - return -1; -} - -#if SOLARIS2 >= 10 -/* - * Function: addrset_match_v4 - * Returns: boolean_t - * Parameters: addr - the IP address of interest - * setp - pointer to an address set (generated by pfild) - * - * Support function for fr_verifysrc used on Solaris 10 and later. - * Try to match an IPv4 address against an address set. - * Returns true iff the specified address is a member of the set. - * Note that addr is passed in network byte order; we convert it to host byte - * order for searching the table. - */ -static boolean_t addrset_match_v4(setp, addr) -struct pfil_ifaddrset *setp; -struct in_addr addr; -{ - uint32_t haddr = ntohl(addr.s_addr); - unsigned int low, high, mid; - struct pfil_v4span *spans = (struct pfil_v4span *)(setp + 1); - - /* binary search */ - low = 0; - high = setp->nspans; - while (low < high) { - mid = (high + low) / 2; - if (haddr > spans[mid].last) - low = mid + 1; - else if (haddr < spans[mid].first) - high = mid; - else - return B_TRUE; - } - return B_FALSE; -} - -/* - * Function: addrset_match_v6 - * Returns: boolean_t - * Parameters: addr - the IP address of interest - * setp - pointer to an address set (generated by pfild) - * - * Support function for fr_verifysrc used on Solaris 10 and later. - * Try to match an IPv6 address against an address set. - * Returns true iff the specified address is a member of the set. - */ -static boolean_t addrset_match_v6(setp, addr) -struct pfil_ifaddrset *setp; -struct in6_addr addr; -{ - unsigned int low, high, mid; - struct pfil_v6span *spans = (struct pfil_v6span *)(setp + 1); - - /* binary search */ - low = 0; - high = setp->nspans; - while (low < high) { - mid = (high + low) / 2; - if (IP6_GT(&addr, &spans[mid].last)) - low = mid + 1; - else if (IP6_LT(&addr, &spans[mid].first)) - high = mid; - else - return B_TRUE; - } - return B_FALSE; -} -#endif - -/* - * Function: fr_verifysrc - * Returns: int (really boolean) - * Parameters: fin - packet information - * - * Check whether the packet has a valid source address for the interface on - * which the packet arrived, implementing the "fr_chksrc" feature. - * Returns true iff the packet's source address is valid. - * Pre-Solaris 10, we call into the routing code to make the determination. - * On Solaris 10 and later, we have a valid address set from pfild to check - * against. - */ -int fr_verifysrc(fin) -fr_info_t *fin; -{ -#if SOLARIS2 >= 10 - qif_t *qf = fin->fin_qif; - struct pfil_ifaddrset *setp; - - if (qf->qf_addrset == NULL) { - /* Warn here? pfild might not be running. */ - return 0; - } - - setp = (struct pfil_ifaddrset *)qf->qf_addrset->b_rptr; - if (!setp) - return 0; - - if (fin->fin_v == IPVERSION && setp->af == AF_INET) { - if (qf->qf_addrset->b_wptr - qf->qf_addrset->b_rptr < - sizeof (*setp) + setp->nspans * sizeof (struct pfil_v4span)) - return 0; /* malformed set */ - - return addrset_match_v4(setp, fin->fin_src); - } else if (fin->fin_v == IPV6_VERSION && setp->af == AF_INET6) { - if (qf->qf_addrset->b_wptr - qf->qf_addrset->b_rptr < - sizeof (*setp) + setp->nspans * sizeof (struct pfil_v6span)) - return 0; /* malformed set */ - - return addrset_match_v6(setp, fin->fin_src6); - } else - return 0; - -#else - ire_t *ir, *dir; - -#if SOLARIS2 >= 6 - dir = ire_route_lookup(fin->fin_saddr, 0xffffffff, 0, 0, NULL, - NULL, NULL, MATCH_IRE_DSTONLY|MATCH_IRE_DEFAULT| - MATCH_IRE_RECURSIVE); -#else - dir = ire_lookup(fin->fin_saddr); -#endif - - if (!dir) - return 0; - return (ire_to_ill(dir) == fin->fin_ifp); -#endif /* SOLARIS2 >= 10 */ -} - - -#if (SOLARIS2 < 7) -void fr_slowtimer() -#else -/*ARGSUSED*/ -void fr_slowtimer __P((void *ptr)) -#endif -{ - - WRITE_ENTER(&ipf_global); - if (fr_running <= 0) { - if (fr_running == -1) - fr_timer_id = timeout(fr_slowtimer, NULL, - drv_usectohz(500000)); - else - fr_timer_id = NULL; - RWLOCK_EXIT(&ipf_global); - return; - } - MUTEX_DOWNGRADE(&ipf_global); - - fr_fragexpire(); - fr_timeoutstate(); - fr_natexpire(); - fr_authexpire(); - fr_ticks++; - if (fr_running == -1 || fr_running == 1) - fr_timer_id = timeout(fr_slowtimer, NULL, drv_usectohz(500000)); - else - fr_timer_id = NULL; - RWLOCK_EXIT(&ipf_global); -} diff --git a/usr/src/uts/common/Makefile.rules b/usr/src/uts/common/Makefile.rules index 82fdea4c43..7de4d5f59e 100644 --- a/usr/src/uts/common/Makefile.rules +++ b/usr/src/uts/common/Makefile.rules @@ -362,13 +362,13 @@ $(OBJS_DIR)/%.o: $(UTSBASE)/common/inet/tcp/%.c $(CTFCONVERT_O) -IPFFLAGS=-I $(UTSBASE)/common/inet/ipf -$(OBJS_DIR)/%.o: $(SRC)/common/ipf/%.c +IPFFLAGS=-I $(UTSBASE)/common/inet/pfil +$(OBJS_DIR)/%.o: $(UTSBASE)/common/inet/ipf/%.c $(COMPILE.c) $(IPFFLAGS) -o $@ $< $(CTFCONVERT_O) -IPFFLAG2=-I $(SRC)/common/ipf -$(OBJS_DIR)/%.o: $(UTSBASE)/common/inet/ipf/%.c +IPFFLAG2=-I $(UTSBASE)/common/inet/ipf +$(OBJS_DIR)/%.o: $(UTSBASE)/common/inet/pfil/%.c $(COMPILE.c) $(IPFFLAG2) -o $@ $< $(CTFCONVERT_O) @@ -1103,10 +1103,10 @@ $(LINTS_DIR)/%.ln: $(UTSBASE)/common/inet/arp/%.c $(LINTS_DIR)/%.ln: $(UTSBASE)/common/inet/ip/%.c @($(LHEAD) $(LINT.c) $< $(LTAIL)) -$(LINTS_DIR)/%.ln: $(SRC)/common/ipf/%.c +$(LINTS_DIR)/%.ln: $(UTSBASE)/common/inet/ipf/%.c @($(LHEAD) $(LINT.c) $(IPFFLAGS) $< $(LTAIL)) -$(LINTS_DIR)/%.ln: $(UTSBASE)/common/inet/ipf/%.c +$(LINTS_DIR)/%.ln: $(UTSBASE)/common/inet/pfil/%.c @($(LHEAD) $(LINT.c) $(IPFFLAG2) $< $(LTAIL)) $(LINTS_DIR)/%.ln: $(UTSBASE)/common/inet/kssl/%.c diff --git a/usr/src/common/ipf/bpf-ipf.h b/usr/src/uts/common/inet/ipf/bpf-ipf.h index 544455e5ff..544455e5ff 100644 --- a/usr/src/common/ipf/bpf-ipf.h +++ b/usr/src/uts/common/inet/ipf/bpf-ipf.h diff --git a/usr/src/common/ipf/fil.c b/usr/src/uts/common/inet/ipf/fil.c index 0a53cfb32e..1dd95e9ba5 100644 --- a/usr/src/common/ipf/fil.c +++ b/usr/src/uts/common/inet/ipf/fil.c @@ -2,10 +2,8 @@ * Copyright (C) 1993-2003 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. - */ - -/* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -40,7 +38,9 @@ #else # include <sys/ioctl.h> #endif -#include <sys/fcntl.h> +#if !defined(_AIX51) +# include <sys/fcntl.h> +#endif #if defined(_KERNEL) # include <sys/systm.h> # include <sys/file.h> @@ -48,6 +48,7 @@ # include <stdio.h> # include <string.h> # include <stdlib.h> +# include <stddef.h> # include <sys/file.h> # define _KERNEL # ifdef __OpenBSD__ @@ -56,10 +57,13 @@ struct file; # include <sys/uio.h> # undef _KERNEL #endif -#if !defined(__SVR4) && !defined(__svr4__) && !defined(__hpux) +#if !defined(__SVR4) && !defined(__svr4__) && !defined(__hpux) && \ + !defined(linux) # include <sys/mbuf.h> #else -# include <sys/byteorder.h> +# if !defined(linux) +# include <sys/byteorder.h> +# endif # if (SOLARIS2 < 5) && defined(sun) # include <sys/dditypes.h> # endif @@ -67,65 +71,62 @@ struct file; #ifdef __hpux # define _NET_ROUTE_INCLUDED #endif -#include <sys/protosw.h> +#if !defined(linux) +# include <sys/protosw.h> +#endif #include <sys/socket.h> #include <net/if.h> #ifdef sun # include <net/af.h> #endif +#if !defined(_KERNEL) && defined(__FreeBSD__) +# include "radix_ipf.h" +#endif #include <net/route.h> #include <netinet/in.h> #include <netinet/in_systm.h> #include <netinet/ip.h> -#include <netinet/ip_var.h> +#if !defined(linux) +# include <netinet/ip_var.h> +#endif #if defined(__sgi) && defined(IFF_DRVRLOCK) /* IRIX 6 */ # include <sys/hashing.h> # include <netinet/in_var.h> #endif #include <netinet/tcp.h> -#include <netinet/udp.h> -#include <netinet/ip_icmp.h> +#if (!defined(__sgi) && !defined(AIX)) || defined(_KERNEL) +# include <netinet/udp.h> +# include <netinet/ip_icmp.h> +#endif #ifdef __hpux # undef _NET_ROUTE_INCLUDED #endif -#if SOLARIS2 >= 10 -# include "ip_compat.h" -#else -# include "netinet/ip_compat.h" -#endif +#include "netinet/ip_compat.h" #ifdef USE_INET6 # include <netinet/icmp6.h> -# if !SOLARIS && defined(_KERNEL) && !defined(__osf__) +# if !SOLARIS && defined(_KERNEL) && !defined(__osf__) && !defined(__hpux) # include <netinet6/in6_var.h> # endif #endif #include <netinet/tcpip.h> -#if SOLARIS2 >= 10 -#include "ip_fil.h" -#include "ip_nat.h" -#include "ip_frag.h" -#include "ip_state.h" -#include "ip_proxy.h" -#include "ip_auth.h" -#else #include "netinet/ip_fil.h" #include "netinet/ip_nat.h" #include "netinet/ip_frag.h" #include "netinet/ip_state.h" #include "netinet/ip_proxy.h" #include "netinet/ip_auth.h" -#endif #ifdef IPFILTER_SCAN # include "netinet/ip_scan.h" #endif -#if SOLARIS2 >= 10 -#include "ip_pool.h" -#include "ip_htable.h" -#else +#ifdef IPFILTER_SYNC +# include "netinet/ip_sync.h" +#endif #include "netinet/ip_pool.h" #include "netinet/ip_htable.h" +#ifdef IPFILTER_COMPILED +# include "netinet/ip_rules.h" #endif -#ifdef IPFILTER_BPF +#if defined(IPFILTER_BPF) && defined(_KERNEL) # include <net/bpf.h> #endif #if defined(__FreeBSD_version) && (__FreeBSD_version >= 300000) @@ -134,20 +135,18 @@ struct file; # include "opt_ipfilter.h" # endif #endif -#if SOLARIS2 >= 10 -#include "ipl.h" -#else #include "netinet/ipl.h" -#endif +/* END OF INCLUDES */ #if !defined(lint) static const char sccsid[] = "@(#)fil.c 1.36 6/5/96 (C) 1993-2000 Darren Reed"; -static const char rcsid[] = "@(#)$Id: fil.c,v 2.197 2003/07/01 18:30:18 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id: fil.c,v 2.243.2.64 2005/08/13 05:19:59 darrenr Exp $"; #endif #ifndef _KERNEL # include "ipf.h" # include "ipt.h" +# include "bpf-ipf.h" extern int opts; # define FR_VERBOSE(verb_pr) verbose verb_pr @@ -158,6 +157,7 @@ extern int opts; #endif /* _KERNEL */ +fr_info_t frcache[2][8]; struct filterstats frstats[2] = { { 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0 } }; struct frentry *ipfilter[2][2] = { { NULL, NULL }, { NULL, NULL } }, *ipfilter6[2][2] = { { NULL, NULL }, { NULL, NULL } }, @@ -165,6 +165,7 @@ struct frentry *ipfilter[2][2] = { { NULL, NULL }, { NULL, NULL } }, *ipacct[2][2] = { { NULL, NULL }, { NULL, NULL } }, *ipnatrules[2][2] = { { NULL, NULL }, { NULL, NULL } }; struct frgroup *ipfgroups[IPL_LOGSIZE][2]; +char ipfilter_version[] = IPL_VERSION; int fr_refcnt = 0; /* * For fr_running: @@ -174,31 +175,49 @@ int fr_running = 0; int fr_flags = IPF_LOGGING; int fr_active = 0; int fr_control_forwarding = 0; -#ifdef _KERNEL int fr_update_ipid = 0; -#else -int fr_update_ipid = 1; -#endif u_short fr_ip_id = 0; -int fr_chksrc = 0; +int fr_chksrc = 0; /* causes a system crash if enabled */ int fr_minttl = 4; +int fr_icmpminfragmtu = 68; +u_long fr_frouteok[2] = {0, 0}; +u_long fr_userifqs = 0; +u_long fr_badcoalesces[2] = {0, 0}; +u_char ipf_iss_secret[32]; #if defined(IPFILTER_DEFAULT_BLOCK) int fr_pass = FR_BLOCK|FR_NOMATCH; #else int fr_pass = (IPF_DEFAULT_PASS)|FR_NOMATCH; #endif -u_long fr_frouteok[2] = {0, 0}; -u_long fr_userifqs = 0; -#ifdef ICMP_UNREACH_FILTER_PROHIB -int fr_unreach = ICMP_UNREACH_FILTER_PROHIB; -#else -int fr_unreach = ICMP_UNREACH_FILTER; +int fr_features = 0 +#ifdef IPFILTER_LKM + | IPF_FEAT_LKM #endif -u_char ipf_iss_secret[32]; - -char ipfilter_version[] = IPL_VERSION; - -fr_info_t frcache[2][8]; +#ifdef IPFILTER_LOG + | IPF_FEAT_LOG +#endif +#ifdef IPFILTER_LOOKUP + | IPF_FEAT_LOOKUP +#endif +#ifdef IPFILTER_BPF + | IPF_FEAT_BPF +#endif +#ifdef IPFILTER_COMPILED + | IPF_FEAT_COMPILED +#endif +#ifdef IPFILTER_CKSUM + | IPF_FEAT_CKSUM +#endif +#ifdef IPFILTER_SYNC + | IPF_FEAT_SYNC +#endif +#ifdef IPFILTER_SCAN + | IPF_FEAT_SCAN +#endif +#ifdef USE_INET6 + | IPF_FEAT_IPV6 +#endif + ; static INLINE int fr_ipfcheck __P((fr_info_t *, frentry_t *, int)); static int fr_portcheck __P((frpcmp_t *, u_short *)); @@ -206,6 +225,7 @@ static int frflushlist __P((int, minor_t, int *, frentry_t **)); static ipfunc_t fr_findfunc __P((ipfunc_t)); static frentry_t *fr_firewall __P((fr_info_t *, u_32_t *)); static int fr_funcinit __P((frentry_t *fr)); +static INLINE void frpr_ah __P((fr_info_t *)); static INLINE void frpr_esp __P((fr_info_t *)); static INLINE void frpr_gre __P((fr_info_t *)); static INLINE void frpr_udp __P((fr_info_t *)); @@ -221,13 +241,18 @@ static INLINE int fr_updateipid __P((fr_info_t *)); static int fr_grpmapinit __P((frentry_t *fr)); static INLINE void *fr_resolvelookup __P((u_int, u_int, lookupfunc_t *)); #endif -static void frsynclist __P((frentry_t *)); +static void frsynclist __P((frentry_t *, void *)); +static ipftuneable_t *fr_findtunebyname __P((const char *)); +static ipftuneable_t *fr_findtunebycookie __P((void *, void **)); /* * bit values for identifying presence of individual IP options + * All of these tables should be ordered by increasing key value on the left + * hand side to allow for binary searching of the array and include a trailer + * with a 0 for the bitmask for linear searches to easily find the end with. */ -struct optlist ipopts[20] = { +const struct optlist ipopts[20] = { { IPOPT_NOP, 0x000001 }, { IPOPT_RR, 0x000002 }, { IPOPT_ZSU, 0x000004 }, @@ -277,7 +302,7 @@ struct optlist tcpopts[] = { /* * bit values for identifying presence of individual IP security options */ -struct optlist secopt[8] = { +const struct optlist secopt[8] = { { IPSO_CLASS_RES4, 0x01 }, { IPSO_CLASS_TOPS, 0x02 }, { IPSO_CLASS_SECR, 0x04 }, @@ -311,6 +336,9 @@ static ipfunc_resolve_t fr_availfuncs[] = { * adding more code to a growing switch statement. */ #ifdef USE_INET6 +static INLINE int frpr_ah6 __P((fr_info_t *)); +static INLINE void frpr_esp6 __P((fr_info_t *)); +static INLINE void frpr_gre6 __P((fr_info_t *)); static INLINE void frpr_udp6 __P((fr_info_t *)); static INLINE void frpr_tcp6 __P((fr_info_t *)); static INLINE void frpr_icmp6 __P((fr_info_t *)); @@ -320,6 +348,7 @@ static INLINE int frpr_hopopts6 __P((fr_info_t *)); static INLINE int frpr_routing6 __P((fr_info_t *)); static INLINE int frpr_dstopts6 __P((fr_info_t *)); static INLINE int frpr_fragment6 __P((fr_info_t *)); +static INLINE int frpr_ipv6exthdr __P((fr_info_t *, int, int)); /* ------------------------------------------------------------------------ */ @@ -329,32 +358,16 @@ static INLINE int frpr_fragment6 __P((fr_info_t *)); /* */ /* IPv6 Only */ /* This is function enforces the 'is a packet too short to be legit' rule */ -/* for IPv6 and marks the packet with FI_BAD/FI_SHORT if so. */ -/* See function comment for frpr_short() for more details. */ +/* for IPv6 and marks the packet with FI_SHORT if so. See function comment */ +/* for frpr_short() for more details. */ /* ------------------------------------------------------------------------ */ -static INLINE void frpr_short6(fin, min) +static INLINE void frpr_short6(fin, xmin) fr_info_t *fin; -int min; +int xmin; { - fr_ip_t *fi = &fin->fin_fi; - int off; - off = fin->fin_off; - if (off == 0) { - if (fin->fin_dlen < min) { - if (fin->fin_flx & FI_FRAG) { - fin->fin_p = IPPROTO_FRAGMENT; - fin->fin_flx |= FI_BAD; - } else { - fi->fi_flx |= FI_SHORT; - } - } - } else if (off < min) { - if (fin->fin_flx & FI_FRAG) - fi->fi_flx |= FI_BAD; - else - fi->fi_flx |= FI_SHORT; - } + if (fin->fin_dlen < xmin) + fin->fin_flx |= FI_SHORT; } @@ -370,8 +383,8 @@ int min; static INLINE int frpr_ipv6hdr(fin) fr_info_t *fin; { - int p, go = 1, i, hdrcount, coalesced; ip6_t *ip6 = (ip6_t *)fin->fin_ip; + int p, go = 1, i, hdrcount; fr_ip_t *fi = &fin->fin_fi; fin->fin_off = 0; @@ -381,7 +394,6 @@ fr_info_t *fin; fi->fi_secmsk = 0; fi->fi_auth = 0; - coalesced = (fin->fin_flx & FI_COALESCE) ? 1 : 0; p = ip6->ip6_nxt; fi->fi_ttl = ip6->ip6_hlim; fi->fi_src.in6 = ip6->ip6_src; @@ -408,111 +420,102 @@ fr_info_t *fin; break; case IPPROTO_GRE : - frpr_gre(fin); + frpr_gre6(fin); go = 0; break; case IPPROTO_HOPOPTS : /* - * Actually, hop by hop header is only allowed right - * after IPv6 header! + * hop by hop ext header is only allowed + * right after IPv6 header. */ - if (hdrcount != 0) + if (hdrcount != 0) { fin->fin_flx |= FI_BAD; - - if (coalesced == 0) { - coalesced = fr_coalesce(fin); - if (coalesced != 1) - return 0; + p = IPPROTO_NONE; + } else { + p = frpr_hopopts6(fin); } - p = frpr_hopopts6(fin); break; case IPPROTO_DSTOPTS : - if (coalesced == 0) { - coalesced = fr_coalesce(fin); - if (coalesced != 1) - return 0; - } p = frpr_dstopts6(fin); break; case IPPROTO_ROUTING : - if (coalesced == 0) { - coalesced = fr_coalesce(fin); - if (coalesced != 1) - return 0; - } p = frpr_routing6(fin); break; + case IPPROTO_AH : + p = frpr_ah6(fin); + break; + case IPPROTO_ESP : - frpr_esp(fin); - for (i = 0; ip6exthdr[i].ol_bit != 0; i++) - if (ip6exthdr[i].ol_val == p) { - fin->fin_optmsk |= ip6exthdr[i].ol_bit; - break; - } + frpr_esp6(fin); go = 0; break; - case IPPROTO_AH : - frpr_short6(fin, 16); + case IPPROTO_IPV6 : for (i = 0; ip6exthdr[i].ol_bit != 0; i++) if (ip6exthdr[i].ol_val == p) { - fin->fin_optmsk |= ip6exthdr[i].ol_bit; + fin->fin_flx |= ip6exthdr[i].ol_bit; break; } go = 0; break; - case IPPROTO_IPV6 : - frpr_short6(fin, sizeof(ip6_t)); - for (i = 0; ip6exthdr[i].ol_bit != 0; i++) - if (ip6exthdr[i].ol_val == p) { - fin->fin_optmsk |= ip6exthdr[i].ol_bit; - break; - } + case IPPROTO_NONE : go = 0; break; case IPPROTO_FRAGMENT : - p = frpr_fragment6(fin); - if (fin->fin_off != 0) /* Not the first frag */ + p = frpr_fragment6(fin); + if (fin->fin_off != 0) /* Not the first frag */ go = 0; break; - case IPPROTO_NONE : - go = 0; - break; - default : go = 0; break; } hdrcount++; - } + /* + * It is important to note that at this point, for the + * extension headers (go != 0), the entire header may not have + * been pulled up when the code gets to this point. This is + * only done for "go != 0" because the other header handlers + * will all pullup their complete header. The other indicator + * of an incomplete packet is that this was just an extension + * header. + */ + if ((go != 0) && (p != IPPROTO_NONE) && + (frpr_pullup(fin, 0) == -1)) { + p = IPPROTO_NONE; + go = 0; + } + } fi->fi_p = p; - /* ext hdr error */ - if ((go && hdrcount && (fin->fin_flx & FI_FRAG)) || - (fin->fin_flx & FI_BAD)) - return -1; + if (fin->fin_flx & FI_BAD) + return -1; + return 0; } /* ------------------------------------------------------------------------ */ -/* Function: frpr_hopopts6 */ +/* Function: frpr_ipv6exthdr */ /* Returns: int - value of the next header or IPPROTO_NONE if error */ -/* Parameters: fin(I) - pointer to packet information */ +/* Parameters: fin(I) - pointer to packet information */ +/* multiple(I) - flag indicating yes/no if multiple occurances */ +/* of this extension header are allowed. */ +/* proto(I) - protocol number for this extension header */ /* */ /* IPv6 Only */ -/* This is function checks pending hop by hop options extension header */ /* ------------------------------------------------------------------------ */ -static INLINE int frpr_hopopts6(fin) +static INLINE int frpr_ipv6exthdr(fin, multiple, proto) fr_info_t *fin; +int multiple, proto; { struct ip6_ext *hdr; u_short shift; @@ -520,10 +523,11 @@ fr_info_t *fin; fin->fin_flx |= FI_V6EXTHDR; - /* 8 is default length of extension hdr */ - frpr_short6(fin, 8); - if (fin->fin_flx & (FI_BAD|FI_SHORT)) + /* 8 is default length of extension hdr */ + if ((fin->fin_dlen - 8) < 0) { + fin->fin_flx |= FI_SHORT; return IPPROTO_NONE; + } if (frpr_pullup(fin, 8) == -1) return IPPROTO_NONE; @@ -536,8 +540,15 @@ fr_info_t *fin; } for (i = 0; ip6exthdr[i].ol_bit != 0; i++) - if (ip6exthdr[i].ol_val == IPPROTO_HOPOPTS) { - fin->fin_optmsk |= ip6exthdr[i].ol_bit; + if (ip6exthdr[i].ol_val == proto) { + /* + * Most IPv6 extension headers are only allowed once. + */ + if ((multiple == 0) && + ((fin->fin_optmsk & ip6exthdr[i].ol_bit) != 0)) + fin->fin_flx |= FI_BAD; + else + fin->fin_optmsk |= ip6exthdr[i].ol_bit; break; } @@ -549,6 +560,21 @@ fr_info_t *fin; /* ------------------------------------------------------------------------ */ +/* Function: frpr_hopopts6 */ +/* Returns: int - value of the next header or IPPROTO_NONE if error */ +/* Parameters: fin(I) - pointer to packet information */ +/* */ +/* IPv6 Only */ +/* This is function checks pending hop by hop options extension header */ +/* ------------------------------------------------------------------------ */ +static INLINE int frpr_hopopts6(fin) +fr_info_t *fin; +{ + return frpr_ipv6exthdr(fin, 0, IPPROTO_HOPOPTS); +} + + +/* ------------------------------------------------------------------------ */ /* Function: frpr_routing6 */ /* Returns: int - value of the next header or IPPROTO_NONE if error */ /* Parameters: fin(I) - pointer to packet information */ @@ -560,38 +586,26 @@ static INLINE int frpr_routing6(fin) fr_info_t *fin; { struct ip6_ext *hdr; - u_short shift; - int i; - - fin->fin_flx |= FI_V6EXTHDR; + int shift; - /* 8 is default length of extension hdr */ - frpr_short6(fin, 8); - if (fin->fin_flx & (FI_BAD|FI_SHORT)) - return IPPROTO_NONE; - - if (frpr_pullup(fin, 8) == -1) - return IPPROTO_NONE; hdr = fin->fin_dp; + if (frpr_ipv6exthdr(fin, 0, IPPROTO_ROUTING) == IPPROTO_NONE) + return IPPROTO_NONE; shift = 8 + (hdr->ip6e_len << 3); /* * Nasty extension header length? */ - if ((shift > fin->fin_dlen) || ((hdr->ip6e_len << 3) & 15)) { + if ((hdr->ip6e_len << 3) & 15) { fin->fin_flx |= FI_BAD; + /* + * Compensate for the changes made in frpr_ipv6exthdr() + */ + fin->fin_dlen += shift; + fin->fin_dp = (char *)fin->fin_dp - shift; return IPPROTO_NONE; } - for (i = 0; ip6exthdr[i].ol_bit != 0; i++) - if (ip6exthdr[i].ol_val == IPPROTO_ROUTING) { - fin->fin_optmsk |= ip6exthdr[i].ol_bit; - break; - } - - fin->fin_dp = (char *)fin->fin_dp + shift; - fin->fin_dlen -= shift; - return hdr->ip6e_nxt; } @@ -603,64 +617,63 @@ fr_info_t *fin; /* */ /* IPv6 Only */ /* Examine the IPv6 fragment header and extract fragment offset information.*/ +/* */ +/* We don't know where the transport layer header (or whatever is next is), */ +/* as it could be behind destination options (amongst others). Because */ +/* there is no fragment cache, there is no knowledge about whether or not an*/ +/* upper layer header has been seen (or where it ends) and thus we are not */ +/* able to continue processing beyond this header with any confidence. */ /* ------------------------------------------------------------------------ */ static INLINE int frpr_fragment6(fin) fr_info_t *fin; { struct ip6_frag *frag; - int i; - - fin->fin_flx |= (FI_FRAG|FI_V6EXTHDR); + int dlen; - /* - * Only one frgament header is allowed per IPv6 packet but it need - * not be the first nor last (not possible in some cases.) - */ - for (i = 0; ip6exthdr[i].ol_bit != 0; i++) - if (ip6exthdr[i].ol_val == IPPROTO_FRAGMENT) - break; + fin->fin_flx |= FI_FRAG; - if (fin->fin_optmsk & ip6exthdr[i].ol_bit) { - fin->fin_flx |= FI_BAD; + dlen = fin->fin_dlen; + if (frpr_ipv6exthdr(fin, 0, IPPROTO_FRAGMENT) == IPPROTO_NONE) return IPPROTO_NONE; - } - fin->fin_optmsk |= ip6exthdr[i].ol_bit; - - /* 8 is default length of extension hdr */ - frpr_short6(fin, 8); - if (fin->fin_flx & (FI_BAD|FI_SHORT)) + if (frpr_pullup(fin, sizeof(*frag)) == -1) return IPPROTO_NONE; - if (frpr_pullup(fin, 8) == -1) + frpr_short6(fin, sizeof(*frag)); + + if ((fin->fin_flx & FI_SHORT) != 0) return IPPROTO_NONE; - if ((int)(fin->fin_dlen - sizeof(*frag)) < 0) { - fin->fin_flx |= FI_SHORT; + frag = (struct ip6_frag *)((char *)fin->fin_dp - sizeof(*frag)); + /* + * Fragment but no fragmentation info set? Bad packet... + */ + if (frag->ip6f_offlg == 0) { + fin->fin_flx |= FI_BAD; return IPPROTO_NONE; } - frag = fin->fin_dp; fin->fin_id = frag->ip6f_ident; fin->fin_off = frag->ip6f_offlg & IP6F_OFF_MASK; fin->fin_off = ntohs(fin->fin_off); - if (!(frag->ip6f_offlg & IP6F_MORE_FRAG)) { - fin->fin_flx |= FI_FRAGTAIL; - } else if (fin->fin_dlen % 8) { - /* - * If the frag is not the last one and the payload length - * is not multiple of 8, it must be dropped. - */ - fin->fin_flx |= FI_BAD; - return IPPROTO_NONE; - } + if (fin->fin_off != 0) + fin->fin_flx |= FI_FRAGBODY; - fin->fin_dp = (char *)fin->fin_dp + sizeof(*frag); - fin->fin_dlen -= sizeof(*frag); + fin->fin_dp = (char *)frag + sizeof(*frag); + fin->fin_dlen = dlen - sizeof(*frag); /* length of hdrs(after frag hdr) + data */ fin->fin_flen = fin->fin_dlen; + /* + * If the frag is not the last one and the payload length + * is not multiple of 8, it must be dropped. + */ + if ((frag->ip6f_offlg & IP6F_MORE_FRAG) && (dlen % 8)) { + fin->fin_flx |= FI_BAD; + return IPPROTO_NONE; + } + return frag->ip6f_nxt; } @@ -677,33 +690,7 @@ fr_info_t *fin; static INLINE int frpr_dstopts6(fin) fr_info_t *fin; { - struct ip6_ext *hdr; - u_short shift; - int i; - - /* 8 is default length of extension hdr */ - frpr_short6(fin, 8); - if (fin->fin_flx & (FI_BAD|FI_SHORT)) - return IPPROTO_NONE; - - if (frpr_pullup(fin, 8) == -1) - return IPPROTO_NONE; - hdr = fin->fin_dp; - - shift = 8 + (hdr->ip6e_len << 3); - if (shift > fin->fin_dlen) { /* Nasty extension header length? */ - fin->fin_flx |= FI_BAD; - return IPPROTO_NONE; - } - - for (i = 0; ip6exthdr[i].ol_bit != 0; i++) - if (ip6exthdr[i].ol_val == IPPROTO_DSTOPTS) - break; - fin->fin_optmsk |= ip6exthdr[i].ol_bit; - fin->fin_dp = (char *)fin->fin_dp + shift; - fin->fin_dlen -= shift; - - return hdr->ip6e_nxt; + return frpr_ipv6exthdr(fin, 1, IPPROTO_DSTOPTS); } @@ -722,7 +709,7 @@ fr_info_t *fin; int minicmpsz = sizeof(struct icmp6_hdr); struct icmp6_hdr *icmp6; - if (frpr_pullup(fin, ICMP6ERR_MINPKTLEN + 8 - sizeof(ip6_t)) == -1) + if (frpr_pullup(fin, ICMP6ERR_MINPKTLEN - sizeof(ip6_t)) == -1) return; if (fin->fin_dlen > 1) { @@ -754,7 +741,6 @@ fr_info_t *fin; } frpr_short6(fin, minicmpsz); - fin->fin_flen -= fin->fin_dlen - minicmpsz; } @@ -766,6 +752,7 @@ fr_info_t *fin; /* */ /* IPv6 Only */ /* Analyse the packet for IPv6/UDP properties. */ +/* Is not expected to be called for fragmented packets. */ /* ------------------------------------------------------------------------ */ static INLINE void frpr_udp6(fin) fr_info_t *fin; @@ -790,6 +777,7 @@ fr_info_t *fin; /* */ /* IPv6 Only */ /* Analyse the packet for IPv6/TCP properties. */ +/* Is not expected to be called for fragmented packets. */ /* ------------------------------------------------------------------------ */ static INLINE void frpr_tcp6(fin) fr_info_t *fin; @@ -805,6 +793,94 @@ fr_info_t *fin; frpr_tcpcommon(fin); } + + +/* ------------------------------------------------------------------------ */ +/* Function: frpr_esp6 */ +/* Returns: void */ +/* Parameters: fin(I) - pointer to packet information */ +/* */ +/* IPv6 Only */ +/* Analyse the packet for ESP properties. */ +/* The minimum length is taken to be the SPI (32bits) plus a tail (32bits) */ +/* even though the newer ESP packets must also have a sequence number that */ +/* is 32bits as well, it is not possible(?) to determine the version from a */ +/* simple packet header. */ +/* ------------------------------------------------------------------------ */ +static INLINE void frpr_esp6(fin) +fr_info_t *fin; +{ + int i; + frpr_short6(fin, sizeof(grehdr_t)); + + (void) frpr_pullup(fin, 8); + + for (i = 0; ip6exthdr[i].ol_bit != 0; i++) + if (ip6exthdr[i].ol_val == IPPROTO_ESP) { + fin->fin_optmsk |= ip6exthdr[i].ol_bit; + break; + } +} + + +/* ------------------------------------------------------------------------ */ +/* Function: frpr_ah6 */ +/* Returns: void */ +/* Parameters: fin(I) - pointer to packet information */ +/* */ +/* IPv6 Only */ +/* Analyse the packet for AH properties. */ +/* The minimum length is taken to be the combination of all fields in the */ +/* header being present and no authentication data (null algorithm used.) */ +/* ------------------------------------------------------------------------ */ +static INLINE int frpr_ah6(fin) +fr_info_t *fin; +{ + authhdr_t *ah; + int i, shift; + + frpr_short6(fin, 12); + + if (frpr_pullup(fin, sizeof(*ah)) == -1) + return IPPROTO_NONE; + + for (i = 0; ip6exthdr[i].ol_bit != 0; i++) + if (ip6exthdr[i].ol_val == IPPROTO_AH) { + fin->fin_optmsk |= ip6exthdr[i].ol_bit; + break; + } + + ah = (authhdr_t *)fin->fin_dp; + + shift = (ah->ah_plen + 2) * 4; + fin->fin_dlen -= shift; + fin->fin_dp = (char*)fin->fin_dp + shift; + + return ah->ah_next; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: frpr_gre6 */ +/* Returns: void */ +/* Parameters: fin(I) - pointer to packet information */ +/* */ +/* Analyse the packet for GRE properties. */ +/* ------------------------------------------------------------------------ */ +static INLINE void frpr_gre6(fin) +fr_info_t *fin; +{ + grehdr_t *gre; + + frpr_short6(fin, sizeof(grehdr_t)); + + if (frpr_pullup(fin, sizeof(grehdr_t)) == -1) + return; + + gre = fin->fin_dp; + if (GRE_REV(gre->gr_flags) == 1) + fin->fin_data[0] = gre->gr_call; +} #endif /* USE_INET6 */ @@ -822,7 +898,7 @@ static INLINE int frpr_pullup(fin, plen) fr_info_t *fin; int plen; { -#if defined(_KERNEL) && !defined(__sgi) +#if defined(_KERNEL) if (fin->fin_m != NULL) { if (fin->fin_dp != NULL) plen += (char *)fin->fin_dp - @@ -842,25 +918,25 @@ int plen; /* ------------------------------------------------------------------------ */ /* Function: frpr_short */ /* Returns: void */ -/* Parameters: fin(I) - pointer to packet information */ -/* min(I) - minimum size of packet */ +/* Parameters: fin(I) - pointer to packet information */ +/* xmin(I) - minimum header size */ /* */ -/* Check if a packet is "short" as defined by min. */ +/* Check if a packet is "short" as defined by xmin. The rule we are */ +/* applying here is that the packet must not be fragmented within the layer */ +/* 4 header. That is, it must not be a fragment that has its offset set to */ +/* start within the layer 4 header (hdrmin) or if it is at offset 0, the */ +/* entire layer 4 header must be present (min). */ /* ------------------------------------------------------------------------ */ -/*ARGSUSED*/ -static INLINE void frpr_short(fin, min) +static INLINE void frpr_short(fin, xmin) fr_info_t *fin; -int min; +int xmin; { - fr_ip_t *fi = &fin->fin_fi; - int off; - off = fin->fin_off; - if (off == 0) { - if (fin->fin_plen < fin->fin_hlen + min) - fi->fi_flx |= FI_SHORT; - } else if (off < min) { - fi->fi_flx |= FI_SHORT; + if (fin->fin_off == 0) { + if (fin->fin_dlen < xmin) + fin->fin_flx |= FI_SHORT; + } else if (fin->fin_off < xmin) { + fin->fin_flx |= FI_SHORT; } } @@ -873,7 +949,7 @@ int min; /* IPv4 Only */ /* Do a sanity check on the packet for ICMP (v4). In nearly all cases, */ /* except extrememly bad packets, both type and code will be present. */ -/* The expected minimum size of an ICMP packet is very much dependant on */ +/* The expected minimum size of an ICMP packet is very much dependent on */ /* the type of it. */ /* */ /* XXX - other ICMP sanity checks? */ @@ -883,12 +959,16 @@ fr_info_t *fin; { int minicmpsz = sizeof(struct icmp); icmphdr_t *icmp; + ip_t *oip; if (fin->fin_off != 0) { frpr_short(fin, ICMPERR_ICMPHLEN); return; } + if (frpr_pullup(fin, ICMPERR_ICMPHLEN) == -1) + return; + fr_checkv4sum(fin); if (fin->fin_dlen > 1) { @@ -925,20 +1005,33 @@ fr_info_t *fin; * type(1) + code(1) + cksum(2) + id(2) seq(2) + ip(20+) */ case ICMP_UNREACH : + if (icmp->icmp_code == ICMP_UNREACH_NEEDFRAG) { + if (icmp->icmp_nextmtu < fr_icmpminfragmtu) + fin->fin_flx |= FI_BAD; + } + /* FALLTHRU */ case ICMP_SOURCEQUENCH : case ICMP_REDIRECT : case ICMP_TIMXCEED : case ICMP_PARAMPROB : - if ((fin->fin_m != NULL) && - (M_LEN(fin->fin_m) < fin->fin_plen)) { - if (fr_coalesce(fin) != 1) - return; - } fin->fin_flx |= FI_ICMPERR; + if (fr_coalesce(fin) != 1) + return; + /* + * ICMP error packets should not be generated for IP + * packets that are a fragment that isn't the first + * fragment. + */ + oip = (ip_t *)((char *)fin->fin_dp + ICMPERR_ICMPHLEN); + if ((ntohs(oip->ip_off) & IP_OFFMASK) != 0) + fin->fin_flx |= FI_BAD; break; default : break; } + + if (fin->fin_dlen >= 6) /* ID field */ + fin->fin_data[1] = icmp->icmp_id; } frpr_short(fin, minicmpsz); @@ -965,62 +1058,71 @@ fr_info_t *fin; if (fin->fin_off != 0) return; + if (frpr_pullup(fin, sizeof(*tcp)) == -1) + return; tcp = fin->fin_dp; - tlen = TCP_OFF(tcp) << 2; -#if defined(_KERNEL) && !defined(__sgi) - if ((fin->fin_m != NULL) && - (M_LEN(fin->fin_m) < tlen + fin->fin_hlen)) { - if (fr_pullup(fin->fin_m, fin, tlen + fin->fin_hlen) == NULL) - return; + if (fin->fin_dlen > 3) { + fin->fin_sport = ntohs(tcp->th_sport); + fin->fin_dport = ntohs(tcp->th_dport); } -#endif + + if ((fin->fin_flx & FI_SHORT) != 0) + return; /* * Use of the TCP data offset *must* result in a value that is at * least the same size as the TCP header. */ - if (tlen < sizeof(tcphdr_t)) + tlen = TCP_OFF(tcp) << 2; + if (tlen < sizeof(tcphdr_t)) { fin->fin_flx |= FI_BAD; - if (!(fin->fin_flx & FI_SHORT)) { - flags = tcp->th_flags; - fin->fin_tcpf = tcp->th_flags; + return; + } + flags = tcp->th_flags; + fin->fin_tcpf = tcp->th_flags; + + /* + * If the urgent flag is set, then the urgent pointer must + * also be set and vice versa. Good TCP packets do not have + * just one of these set. + */ + if ((flags & TH_URG) != 0 && (tcp->th_urp == 0)) { + fin->fin_flx |= FI_BAD; + } else if ((flags & TH_URG) == 0 && (tcp->th_urp != 0)) { + /* Ignore this case, it shows up in "real" traffic with */ + /* bogus values in the urgent pointer field. */ + flags = flags; /* LINT */ + } else if (((flags & (TH_SYN|TH_FIN)) != 0) && + ((flags & (TH_RST|TH_ACK)) == TH_RST)) { + /* TH_FIN|TH_RST|TH_ACK seems to appear "naturally" */ + fin->fin_flx |= FI_BAD; + } else if (!(flags & TH_ACK)) { /* - * If the urgent flag is set, then the urgent pointer must - * also be set and vice versa. Good TCP packets do not have - * just one of these set. + * If the ack bit isn't set, then either the SYN or + * RST bit must be set. If the SYN bit is set, then + * we expect the ACK field to be 0. If the ACK is + * not set and if URG, PSH or FIN are set, consdier + * that to indicate a bad TCP packet. */ - if (((flags & TH_URG) != 0 && (tcp->th_urp == 0)) || - ((flags & TH_URG) == 0 && (tcp->th_urp != 0))) { - fin->fin_flx |= FI_BAD; - } else if (((flags & (TH_SYN|TH_FIN)) != 0) && - ((flags & TH_RST) != 0)) { - fin->fin_flx |= FI_BAD; - } else if (!(flags & TH_ACK)) { + if ((flags == TH_SYN) && (tcp->th_ack != 0)) { /* - * If the ack bit isn't set, then either the SYN or - * RST bit must be set. If the SYN bit is set, then - * we expect the ACK field to be 0. If the ACK is - * not set and if URG, PSH or FIN are set, consdier - * that to indicate a bad TCP packet. + * Cisco PIX sets the ACK field to a random value. + * In light of this, do not set FI_BAD until a patch + * is available from Cisco to ensure that + * interoperability between existing systems is + * achieved. */ - if ((flags == TH_SYN) && (tcp->th_ack != 0)) { - fin->fin_flx |= FI_BAD; - } else if (!(flags & (TH_RST|TH_SYN))) { - fin->fin_flx |= FI_BAD; - } else if ((flags & (TH_URG|TH_PUSH|TH_FIN)) != 0) { - fin->fin_flx |= FI_BAD; - } + /*fin->fin_flx |= FI_BAD*/; + flags = flags; /* LINT */ + } else if (!(flags & (TH_RST|TH_SYN))) { + fin->fin_flx |= FI_BAD; + } else if ((flags & (TH_URG|TH_PUSH|TH_FIN)) != 0) { + fin->fin_flx |= FI_BAD; } } - if (fin->fin_dlen > 3) { - fin->fin_sport = ntohs(tcp->th_sport); - fin->fin_dport = ntohs(tcp->th_dport); - } - -#if 0 /* * At this point, it's not exactly clear what is to be gained by * marking up which TCP options are and are not present. The one we @@ -1029,30 +1131,35 @@ fr_info_t *fin; * Now if we were to analyse the header for passive fingerprinting, * then that might add some weight to adding this... */ - s = (u_char *)(tcp + 1); - hlen = TCP_OFF(tcp) << 2; - if (hlen == sizeof(tcphdr_t)) + if (tlen == sizeof(tcphdr_t)) return; + + if (frpr_pullup(fin, tlen) == -1) + return; + +#if 0 + ip = fin->fin_ip; + s = (u_char *)(tcp + 1); off = IP_HL(ip) << 2; # ifdef _KERNEL if (fin->fin_mp != NULL) { mb_t *m = *fin->fin_mp; - if (off + hlen > M_LEN(m)) + if (off + tlen > M_LEN(m)) return; } # endif - for (hlen -= (int)sizeof(*tcp); hlen > 0; ) { + for (tlen -= (int)sizeof(*tcp); tlen > 0; ) { opt = *s; if (opt == '\0') break; else if (opt == TCPOPT_NOP) ol = 1; else { - if (hlen < 2) + if (tlen < 2) break; ol = (int)*(s + 1); - if (ol < 2 || ol > hlen) + if (ol < 2 || ol > tlen) break; } @@ -1063,7 +1170,7 @@ fr_info_t *fin; break; } } - hlen -= ol; + tlen -= ol; s += ol; } #endif /* 0 */ @@ -1087,6 +1194,11 @@ fr_info_t *fin; fin->fin_flx |= FI_TCPUDP; if (!fin->fin_off && (fin->fin_dlen > 3)) { + if (frpr_pullup(fin, sizeof(*udp)) == -1) { + fin->fin_flx |= FI_SHORT; + return; + } + udp = fin->fin_dp; fin->fin_sport = ntohs(udp->uh_sport); @@ -1109,7 +1221,7 @@ fr_info_t *fin; fr_checkv4sum(fin); - frpr_short(fin, sizeof(struct tcphdr)); + frpr_short(fin, sizeof(tcphdr_t)); frpr_tcpcommon(fin); } @@ -1129,7 +1241,7 @@ fr_info_t *fin; fr_checkv4sum(fin); - frpr_short(fin, sizeof(struct udphdr)); + frpr_short(fin, sizeof(udphdr_t)); frpr_udpcommon(fin); } @@ -1149,15 +1261,35 @@ fr_info_t *fin; static INLINE void frpr_esp(fin) fr_info_t *fin; { - if (frpr_pullup(fin, 8) == -1) + if ((fin->fin_off == 0) && (frpr_pullup(fin, 8) == -1)) return; - if (fin->fin_v == 4) - frpr_short(fin, 8); -#ifdef USE_INET6 - else if (fin->fin_v == 6) - frpr_short6(fin, sizeof(grehdr_t)); -#endif + frpr_short(fin, 8); +} + + +/* ------------------------------------------------------------------------ */ +/* Function: frpr_ah */ +/* Returns: void */ +/* Parameters: fin(I) - pointer to packet information */ +/* */ +/* Analyse the packet for AH properties. */ +/* The minimum length is taken to be the combination of all fields in the */ +/* header being present and no authentication data (null algorithm used.) */ +/* ------------------------------------------------------------------------ */ +static INLINE void frpr_ah(fin) +fr_info_t *fin; +{ + authhdr_t *ah; + int len; + + if ((fin->fin_off == 0) && (frpr_pullup(fin, sizeof(*ah)) == -1)) + return; + + ah = (authhdr_t *)fin->fin_dp; + + len = (ah->ah_plen + 2) << 2; + frpr_short(fin, len); } @@ -1171,15 +1303,18 @@ fr_info_t *fin; static INLINE void frpr_gre(fin) fr_info_t *fin; { - if (frpr_pullup(fin, sizeof(grehdr_t)) == -1) + grehdr_t *gre; + + if ((fin->fin_off == 0) && (frpr_pullup(fin, sizeof(grehdr_t)) == -1)) return; - if (fin->fin_v == 4) - frpr_short(fin, sizeof(grehdr_t)); -#ifdef USE_INET6 - else if (fin->fin_v == 6) - frpr_short6(fin, sizeof(grehdr_t)); -#endif + frpr_short(fin, sizeof(grehdr_t)); + + if (fin->fin_off == 0) { + gre = fin->fin_dp; + if (GRE_REV(gre->gr_flags) == 1) + fin->fin_data[0] = gre->gr_call; + } } @@ -1197,7 +1332,7 @@ fr_info_t *fin; { u_short optmsk = 0, secmsk = 0, auth = 0; int hlen, ol, mv, p, i; - struct optlist *op; + const struct optlist *op; u_char *s, opt; u_short off; fr_ip_t *fi; @@ -1235,22 +1370,27 @@ fr_info_t *fin; * set packet attribute flags based on the offset and * calculate the byte offset that it represents. */ - if ((off & IP_MF) != 0) { - fi->fi_flx |= FI_FRAG; - if (fin->fin_dlen == 0) - fi->fi_flx |= FI_BAD; - } - off &= IP_MF|IP_OFFMASK; if (off != 0) { fi->fi_flx |= FI_FRAG; - if ((off & IP_MF) == 0) - fi->fi_flx |= FI_FRAGTAIL; off &= IP_OFFMASK; if (off != 0) { + fin->fin_flx |= FI_FRAGBODY; off <<= 3; - if (off + fin->fin_dlen > 0xffff) + if ((off + fin->fin_dlen > 65535) || + (fin->fin_dlen == 0) || + ((ip->ip_off & IP_MF) && (fin->fin_dlen & 7))) { + /* + * The length of the packet, starting at its + * offset cannot exceed 65535 (0xffff) as the + * length of an IP packet is only 16 bits. + * + * Any fragment that isn't the last fragment + * must have a length greater than 0 and it + * must be an even multiple of 8. + */ fi->fi_flx |= FI_BAD; + } } } fin->fin_off = off; @@ -1269,6 +1409,15 @@ fr_info_t *fin; case IPPROTO_ICMP : frpr_icmp(fin); break; + case IPPROTO_AH : + frpr_ah(fin); + break; + case IPPROTO_ESP : + frpr_esp(fin); + break; + case IPPROTO_GRE : + frpr_gre(fin); + break; } ip = fin->fin_ip; @@ -1313,7 +1462,7 @@ fr_info_t *fin; if ((opt == (u_char)op->ol_val) && (ol > 4)) { optmsk |= op->ol_bit; if (opt == IPOPT_SECURITY) { - struct optlist *sp; + const struct optlist *sp; u_char sec; int j, m; @@ -1347,7 +1496,7 @@ fr_info_t *fin; } /* - * + * */ if (auth && !(auth & 0x0100)) auth &= 0xff00; @@ -1362,7 +1511,7 @@ fr_info_t *fin; /* Returns: int - 1 == hdr checking error, 0 == OK */ /* Parameters: hlen(I) - length of IP packet header */ /* ip(I) - pointer to the IP header */ -/* fin(IO) - pointer to packet information */ +/* fin(IO) - pointer to packet information */ /* */ /* Compact the IP header into a structure which contains just the info. */ /* which is useful for comparing IP headers with and store this information */ @@ -1391,9 +1540,10 @@ fr_info_t *fin; if (v == 4) frpr_ipv4hdr(fin); #ifdef USE_INET6 - else if (v == 6) + else if (v == 6) { if (frpr_ipv6hdr(fin) == -1) return -1; + } #endif if (fin->fin_ip == NULL) return -1; @@ -1726,7 +1876,7 @@ u_32_t pass; { int rulen, portcmp, off, logged, skip; struct frentry *fr, *fnext; - u_32_t passt; + u_32_t passt, passo; /* * Do not allow nesting deeper than 16 levels. @@ -1773,7 +1923,7 @@ u_32_t pass; if (opts & (OPT_VERBOSE|OPT_DEBUG)) printf("\n"); FR_VERBOSE(("%c", FR_ISSKIP(pass) ? 's' : - FR_ISPASS(pass) ? 'p' : + FR_ISPASS(pass) ? 'p' : FR_ISACCOUNT(pass) ? 'A' : FR_ISAUTH(pass) ? 'a' : (pass & FR_NOMATCH) ? 'n' :'b')); @@ -1789,20 +1939,18 @@ u_32_t pass; if (fr_ipfcheck(fin, fr, portcmp)) continue; break; -#if defined(IPFILTER_BPF) && defined(_KERNEL) +#if defined(IPFILTER_BPF) case FR_T_BPFOPC : case FR_T_BPFOPC|FR_T_BUILTIN : { u_char *mc; - int wlen; if (*fin->fin_mp == NULL) continue; if (fin->fin_v != fr->fr_v) continue; mc = (u_char *)fin->fin_m; - wlen = fin->fin_dlen + fin->fin_hlen; - if (!bpf_filter(fr->fr_data, mc, wlen, 0)) + if (!bpf_filter(fr->fr_data, mc, fin->fin_plen, 0)) continue; break; } @@ -1833,13 +1981,22 @@ u_32_t pass; passt = fr->fr_flags; /* + * Allowing a rule with the "keep state" flag set to match + * packets that have been tagged "out of window" by the TCP + * state tracking is foolish as the attempt to add a new + * state entry to the table will fail. + */ + if ((passt & FR_KEEPSTATE) && (fin->fin_flx & FI_OOW)) + continue; + + /* * If the rule is a "call now" rule, then call the function * in the rule, if it exists and use the results from that. * If the function pointer is bad, just make like we ignore * it, except for increasing the hit counter. */ if ((passt & FR_CALLNOW) != 0) { - ATOMIC_INCL(fr->fr_hits); + ATOMIC_INC64(fr->fr_hits); if ((fr->fr_func != NULL) && (fr->fr_func != (ipfunc_t)-1)) { frentry_t *frs; @@ -1875,6 +2032,7 @@ u_32_t pass; } #endif /* IPFILTER_LOG */ fr->fr_bytes += (U_QUAD_T)fin->fin_plen; + passo = pass; if (FR_ISSKIP(passt)) skip = fr->fr_arg; else if ((passt & FR_LOGMASK) != FR_LOG) @@ -1882,7 +2040,7 @@ u_32_t pass; if (passt & (FR_RETICMP|FR_FAKEICMP)) fin->fin_icode = fr->fr_icode; FR_DEBUG(("pass %#x\n", pass)); - ATOMIC_INCL(fr->fr_hits); + ATOMIC_INC64(fr->fr_hits); fin->fin_rule = rulen; (void) strncpy(fin->fin_group, fr->fr_group, FR_GROUPLEN); if (fr->fr_grp != NULL) { @@ -1897,8 +2055,29 @@ u_32_t pass; if (fin->fin_flx & FI_DONTCACHE) logged = 1; } - if (pass & FR_QUICK) + + if (pass & FR_QUICK) { + /* + * Finally, if we've asked to track state for this + * packet, set it up. Add state for "quick" rules + * here so that if the action fails we can consider + * the rule to "not match" and keep on processing + * filter rules. + */ + if ((pass & FR_KEEPSTATE) && + !(fin->fin_flx & FI_STATE)) { + int out = fin->fin_out; + + if (fr_addstate(fin, NULL, 0) != NULL) { + ATOMIC_INCL(frstats[out].fr_ads); + } else { + ATOMIC_INCL(frstats[out].fr_bads); + pass = passo; + continue; + } + } break; + } } if (logged) fin->fin_flx |= FI_DONTCACHE; @@ -1983,18 +2162,22 @@ u_32_t *passp; * the result as if it were from the ACL's. */ fc = &frcache[out][CACHE_HASH(fin)]; + READ_ENTER(&ipf_frcache); if (!bcmp((char *)fin, (char *)fc, FI_CSIZE)) { /* - * copy cached data so we can unlock the mutex - * earlier. + * copy cached data so we can unlock the mutexes earlier. */ bcopy((char *)fc, (char *)fin, FI_COPYSIZE); + RWLOCK_EXIT(&ipf_frcache); ATOMIC_INCL(frstats[out].fr_chit); + if ((fr = fin->fin_fr) != NULL) { - ATOMIC_INCL(fr->fr_hits); + ATOMIC_INC64(fr->fr_hits); pass = fr->fr_flags; } } else { + RWLOCK_EXIT(&ipf_frcache); + #ifdef USE_INET6 if (fin->fin_v == 6) fin->fin_fr = ipfilter6[out][fr_active]; @@ -2003,9 +2186,13 @@ u_32_t *passp; fin->fin_fr = ipfilter[out][fr_active]; if (fin->fin_fr != NULL) pass = fr_scanlist(fin, fr_pass); + if (((pass & FR_KEEPSTATE) == 0) && - ((fin->fin_flx & FI_DONTCACHE) == 0)) + ((fin->fin_flx & FI_DONTCACHE) == 0)) { + WRITE_ENTER(&ipf_frcache); bcopy((char *)fin, (char *)fc, FI_COPYSIZE); + RWLOCK_EXIT(&ipf_frcache); + } if ((pass & FR_NOMATCH)) { ATOMIC_INCL(frstats[out].fr_nom); } @@ -2073,11 +2260,15 @@ u_32_t *passp; /* * Finally, if we've asked to track state for this packet, set it up. */ - if (pass & FR_KEEPSTATE) { + if ((pass & FR_KEEPSTATE) && !(fin->fin_flx & FI_STATE)) { if (fr_addstate(fin, NULL, 0) != NULL) { ATOMIC_INCL(frstats[out].fr_ads); } else { ATOMIC_INCL(frstats[out].fr_bads); + if (FR_ISPASS(pass)) { + pass &= ~FR_CMDMASK; + pass |= FR_BLOCK; + } } } @@ -2096,7 +2287,7 @@ u_32_t *passp; /* User space: */ /* -1 == packet blocked */ /* 1 == packet not matched */ -/* -2 == requires authantication */ +/* -2 == requires authentication */ /* Kernel: */ /* > 0 == filter error # for packet */ /* Parameters: ip(I) - pointer to start of IPv4/6 packet */ @@ -2106,7 +2297,7 @@ u_32_t *passp; /* mp(IO) - pointer to caller's buffer pointer that holds this */ /* IP packet. */ /* Solaris & HP-UX ONLY : */ -/* qif(I) - pointer to STREAMS queue information for this */ +/* qpi(I) - pointer to STREAMS queue information for this */ /* interface & direction. */ /* */ /* fr_check() is the master function for all IPFilter packet processing. */ @@ -2123,7 +2314,7 @@ u_32_t *passp; int fr_check(ip, hlen, ifp, out #if defined(_KERNEL) && defined(MENTAT) , qif, mp) -qif_t *qif; +void *qif; #else , mp) #endif @@ -2138,14 +2329,20 @@ int out; */ fr_info_t frinfo; fr_info_t *fin = &frinfo; - int v = IP_V(ip), len, p; + u_32_t pass = fr_pass; frentry_t *fr = NULL; + int v = IP_V(ip); mb_t *mc = NULL; - u_32_t pass; mb_t *m; #ifdef USE_INET6 ip6_t *ip6; #endif +#ifdef _KERNEL +# ifdef MENTAT + qpktinfo_t *qpi = qif; +#endif +#endif + SPL_INT(s); /* * The first part of fr_check() deals with making sure that what goes @@ -2155,13 +2352,11 @@ int out; * to hold all the required packet headers. */ #ifdef _KERNEL -# ifdef __sgi - char hbuf[MAX_IPV4HDR]; -# endif # ifdef MENTAT - if ((uintptr_t)ip & 0x3) + if (!OK_32PTR(ip)) return 2; # endif + READ_ENTER(&ipf_global); if (fr_running <= 0) { @@ -2172,18 +2367,23 @@ int out; bzero((char *)fin, sizeof(*fin)); # ifdef MENTAT - if (qif->qf_flags & QF_GROUP) + if (qpi->qpi_flags & QF_GROUP) fin->fin_flx |= FI_MBCAST; - m = qif->qf_m; + m = qpi->qpi_m; fin->fin_qfm = m; - fin->fin_qif = qif; + fin->fin_qpi = qpi; # else /* MENTAT */ m = *mp; + # if defined(M_MCAST) if ((m->m_flags & M_MCAST) != 0) fin->fin_flx |= FI_MBCAST|FI_MULTICAST; # endif +# if defined(M_MLOOP) + if ((m->m_flags & M_MLOOP) != 0) + fin->fin_flx |= FI_MBCAST|FI_MULTICAST; +# endif # if defined(M_BCAST) if ((m->m_flags & M_BCAST) != 0) fin->fin_flx |= FI_MBCAST|FI_BROADCAST; @@ -2206,137 +2406,57 @@ int out; } # endif /* CSUM_DELAY_DATA */ # endif /* MENTAT */ -#else /* _KERNEL */ +#else READ_ENTER(&ipf_global); bzero((char *)fin, sizeof(*fin)); m = *mp; #endif /* _KERNEL */ + fin->fin_v = v; + fin->fin_m = m; + fin->fin_ip = ip; + fin->fin_mp = mp; + fin->fin_out = out; + fin->fin_ifp = ifp; + fin->fin_error = ENETUNREACH; + fin->fin_hlen = (u_short)hlen; + fin->fin_dp = (char *)ip + hlen; + + fin->fin_ipoff = (char *)ip - MTOD(m, char *); + + SPL_NET(s); + #ifdef USE_INET6 if (v == 6) { - len = ntohs(((ip6_t*)ip)->ip6_plen); + ATOMIC_INCL(frstats[out].fr_ipv6); /* * Jumbo grams are quite likely too big for internal buffer * structures to handle comfortably, for now, so just drop - * them for now. + * them. */ - if (len == 0) { + ip6 = (ip6_t *)ip; + fin->fin_plen = ntohs(ip6->ip6_plen); + if (fin->fin_plen == 0) { pass = FR_BLOCK|FR_NOMATCH; goto filtered; } - len += sizeof(ip6_t); - p = ((ip6_t *)ip)->ip6_nxt; + fin->fin_plen += sizeof(ip6_t); } else #endif { - p = ip->ip_p; - len = ip->ip_len; - } - - fin->fin_v = v; - fin->fin_m = m; - fin->fin_mp = mp; - fin->fin_out = out; - fin->fin_ifp = ifp; - fin->fin_plen = len; - fin->fin_hlen = (u_short )hlen; - fin->fin_dp = (char *)ip + hlen; - - if (p == IPPROTO_TCP || p == IPPROTO_UDP || - (v == 4 && p == IPPROTO_ICMP) -#ifdef USE_INET6 - || (v == 6 && p == IPPROTO_ICMPV6) +#if (OpenBSD >= 200311) && defined(_KERNEL) + ip->ip_len = ntohs(ip->ip_len); + ip->ip_off = ntohs(ip->ip_off); #endif - ) { -#if defined(_KERNEL) - int plen = 0, up = 0; - - if ((v == 6) || (ip->ip_off & IP_OFFMASK) == 0) - switch(p) - { - case IPPROTO_TCP: - plen = sizeof(tcphdr_t); - break; - case IPPROTO_UDP: - plen = sizeof(udphdr_t); - break; - /* 96 - enough for complete ICMP error IP header */ - case IPPROTO_ICMP: - plen = ICMPERR_MAXPKTLEN - sizeof(ip_t); - break; -# ifdef USE_INET6 - case IPPROTO_ICMPV6 : - /* - * XXX does not take intermediate header - * into account. - */ - plen = ICMP6ERR_MINPKTLEN + 8 - sizeof(ip6_t); - break; -# endif - } - - up = MIN(hlen + plen, len); - if (up > M_LEN(m)) { -# ifdef __sgi - /* Under IRIX, avoid m_pullup as it makes ping <hostname> panic */ - if ((up > sizeof(hbuf)) || (m_length(m) < up)) { - ATOMIC_INCL(frstats[out].fr_pull[1]); - pass = FR_BLOCK|FR_NOMATCH; - goto filtered; - } - m_copydata(m, 0, up, hbuf); - ATOMIC_INCL(frstats[out].fr_pull[0]); - ip = (ip_t *)hbuf; -# else /* __ sgi */ - /* - * Having determined that we need to pullup some data, - * try to bring as much of the packet up into a single - * buffer with the first pullup. This hopefully means - * less need for doing futher pullups. Not needed for - * Solaris because fr_precheck() does it anyway. - * - * The main potential for trouble here is if MLEN/MHLEN - * become quite small, lets say < 64 bytes...but if - * that did happen, BSD networking as a whole would be - * slow/inefficient. - */ -# ifdef MHLEN - /* - * Assume that M_PKTHDR is set and just work with what - * is left rather than check.. Should not make any - * real difference, anyway. - */ - if ((MHLEN > up) && (len > up)) - up = MIN(len, MHLEN); -# else -# ifdef MLEN - if ((MLEN > up) && (len > up)) - up = MIN(len, MLEN); -# endif /* MLEN */ -# endif /* MHLEN */ - fin->fin_ip = ip; - ip = fr_pullup(m, fin, up); - if (ip == NULL) - goto finished; -# endif /* __sgi */ - } -#else - /*EMPTY*/ -#endif /* _KERNEL */ + fin->fin_plen = ip->ip_len; } - fin->fin_error = fr_unreach; if (fr_makefrip(hlen, ip, fin) == -1) { READ_ENTER(&ipf_mutex); pass = FR_BLOCK; goto filtered; } - ip = fin->fin_ip; - - if (v == 6) { - ATOMIC_INCL(frstats[out].fr_ipv6); - } /* * For at least IPv6 packets, if a m_pullup() fails then this pointer @@ -2353,7 +2473,7 @@ int out; fin->fin_flx |= FI_BADSRC; } #endif - if (ip->ip_ttl < fr_minttl) { + if (fin->fin_ip->ip_ttl < fr_minttl) { ATOMIC_INCL(frstats[0].fr_badttl); fin->fin_flx |= FI_LOWTTL; } @@ -2379,8 +2499,6 @@ int out; ATOMIC_INCL(frstats[out].fr_short); } - pass = fr_pass; - READ_ENTER(&ipf_mutex); /* @@ -2391,8 +2509,12 @@ int out; * occuring until after the packet has been auth'd. */ fr = fr_checkauth(fin, &pass); - if (!out) - (void) fr_checknatin(fin, &pass); + if (!out) { + if (fr_checknatin(fin, &pass) == -1) { + RWLOCK_EXIT(&ipf_mutex); + goto finished; + } + } if (!out) (void) fr_acctpkt(fin, NULL); @@ -2413,15 +2535,15 @@ int out; */ if (out && FR_ISPASS(pass)) { (void) fr_acctpkt(fin, NULL); - (void) fr_checknatout(fin, &pass); - if ((fr_update_ipid != 0) && (v == 4)) { + if (fr_checknatout(fin, &pass) == -1) { + RWLOCK_EXIT(&ipf_mutex); + goto finished; + } else if ((fr_update_ipid != 0) && (v == 4)) { if (fr_updateipid(fin) == -1) { ATOMIC_INCL(frstats[1].fr_ipud); pass &= ~FR_CMDMASK; pass |= FR_BLOCK; - FREE_MB_T(*mp); - m = *mp = NULL; } else { ATOMIC_INCL(frstats[0].fr_ipud); } @@ -2429,8 +2551,9 @@ int out; } #ifdef IPFILTER_LOG - if ((fr_flags & FF_LOGGING) || (pass & FR_LOGMASK)) + if ((fr_flags & FF_LOGGING) || (pass & FR_LOGMASK)) { (void) fr_dolog(fin, &pass); + } #endif if (fin->fin_state != NULL) @@ -2442,10 +2565,11 @@ int out; /* * Only allow FR_DUP to work if a rule matched - it makes no sense to * set FR_DUP as a "default" as there are no instructions about where - * to send the packet. + * to send the packet. Use fin_m here because it may have changed + * (without an update of 'm') in prior processing. */ if ((fr != NULL) && (pass & FR_DUP)) { - mc = M_DUPLICATE(m); + mc = M_DUPLICATE(fin->fin_m); } if (pass & (FR_RETRST|FR_RETICMP)) { @@ -2485,15 +2609,10 @@ int out; * instructions about what to do with a packet. * Once we're finished return to our caller, freeing the packet if * we are dropping it (* BSD ONLY *). + * Reassign m from fin_m as we may have a new buffer, now. */ -#if defined(USE_INET6) || (defined(__sgi) && defined(_KERNEL)) filtered: -#endif - if (FR_ISPASS(pass)) { - ATOMIC_INCL(frstats[out].fr_pass); - } else if (FR_ISBLOCK(pass)) { - ATOMIC_INCL(frstats[out].fr_block); - } + m = fin->fin_m; if (fr != NULL) { frdest_t *fdp; @@ -2526,24 +2645,37 @@ filtered: */ RWLOCK_EXIT(&ipf_mutex); +finished: if (!FR_ISPASS(pass)) { - if (m != NULL) { + ATOMIC_INCL(frstats[out].fr_block); + if (*mp != NULL) { FREE_MB_T(*mp); m = *mp = NULL; } - } + } else { + ATOMIC_INCL(frstats[out].fr_pass); #if defined(_KERNEL) && defined(__sgi) - else { - if ((fin->fin_flx & FI_NATED) && up && (m != NULL)) { - COPYBACK(m, 0, up, hbuf); + if ((fin->fin_hbuf != NULL) && + (mtod(fin->fin_m, struct ip *) != fin->fin_ip)) { + COPYBACK(m, 0, fin->fin_plen, fin->fin_hbuf); } - } #endif -finished: + } + + SPL_X(s); RWLOCK_EXIT(&ipf_global); + #ifdef _KERNEL +# if OpenBSD >= 200311 + if (FR_ISPASS(pass) && (v == 4)) { + ip = fin->fin_ip; + ip->ip_len = ntohs(ip->ip_len); + ip->ip_off = ntohs(ip->ip_off); + } +# endif return (FR_ISPASS(pass)) ? 0 : fin->fin_error; #else /* _KERNEL */ + FR_VERBOSE(("fin_flx %#x pass %#x ", fin->fin_flx, pass)); if ((pass & FR_NOMATCH) != 0) return 1; @@ -2668,9 +2800,10 @@ int len; /* ------------------------------------------------------------------------ */ /* Function: fr_cksum */ /* Returns: u_short - layer 4 checksum */ -/* Parameters: m(I ) - pointer to buffer holding packet */ -/* ip(I) - pointer to IP header */ -/* l4hdr(I) - pointer to layer 4 header */ +/* Parameters: m(I ) - pointer to buffer holding packet */ +/* ip(I) - pointer to IP header */ +/* l4proto(I) - protocol to caclulate checksum for */ +/* l4hdr(I) - pointer to layer 4 header */ /* */ /* Calculates the TCP checksum for the packet held in "m", using the data */ /* in the IP header "ip" to seed it. */ @@ -2678,6 +2811,8 @@ int len; /* NB: This function assumes we've pullup'd enough for all of the IP header */ /* and the TCP header. We also assume that data blocks aren't allocated in */ /* odd sizes. */ +/* */ +/* Expects ip_len to be in host byte order when called. */ /* ------------------------------------------------------------------------ */ u_short fr_cksum(m, ip, l4proto, l4hdr) mb_t *m; @@ -2708,7 +2843,7 @@ void *l4hdr; #endif hlen = IP_HL(ip) << 2; slen = ip->ip_len - hlen; - sum = htons((u_short)ip->ip_p); + sum = htons((u_short)l4proto); sum += htons(slen); sp = (u_short *)&ip->ip_src; sum += *sp++; /* ip_src */ @@ -2720,7 +2855,7 @@ void *l4hdr; ip6 = (ip6_t *)ip; hlen = sizeof(*ip6); slen = ntohs(ip6->ip6_plen); - sum = htons((u_short)ip6->ip6_nxt); + sum = htons((u_short)l4proto); sum += htons(slen); sp = (u_short *)&ip6->ip6_src; sum += *sp++; /* ip6_src */ @@ -2756,6 +2891,7 @@ void *l4hdr; case IPPROTO_ICMP : csump = &((icmphdr_t *)l4hdr)->icmp_cksum; l4hlen = 4; + sum = 0; break; default : break; @@ -2777,9 +2913,9 @@ void *l4hdr; m->b_rptr = (u_char *)ip; sum2 = ip_cksum(m, hlen, sum); /* hlen == offset */ m->b_rptr = rp; - } sum2 = (sum2 & 0xffff) + (sum2 >> 16); sum2 = ~sum2 & 0xffff; + } # else /* MENTAT */ # if defined(BSD) || defined(sun) # if BSD >= 199103 @@ -2816,19 +2952,10 @@ void *l4hdr; /* * Add up IP Header portion */ - sp = (u_short *)&ip->ip_src; - len -= (IP_HL(ip) << 2); - sum = ntohs((u_short)ip->ip_p); - sum += htons(len); - sum += *sp++; /* ip_src */ - sum += *sp++; - sum += *sp++; /* ip_dst */ - sum += *sp++; - if (sp != (u_short *)l4hdr) sp = (u_short *)l4hdr; - switch (ip->ip_p) + switch (l4proto) { case IPPROTO_UDP : sum += *sp++; /* sport */ @@ -2849,6 +2976,10 @@ void *l4hdr; sum += *sp++; /* checksum */ sum += *sp++; /* urp */ break; + case IPPROTO_ICMP : + sum = *sp++; /* type/code */ + sum += *sp++; /* checksum */ + break; } # ifdef __sgi @@ -2875,7 +3006,7 @@ void *l4hdr; } # endif - len -= l4hlen; + len -= (l4hlen + hlen); if (len <= 0) goto nodata; @@ -2927,7 +3058,7 @@ nodata: #if defined(_KERNEL) && ( ((BSD < 199103) && !defined(MENTAT)) || \ - defined(__sgi) ) + defined(__sgi) ) && !defined(linux) && !defined(_AIX51) /* * Copyright (c) 1982, 1986, 1988, 1991, 1993 * The Regents of the University of California. All rights reserved. @@ -2957,7 +3088,7 @@ nodata: * SUCH DAMAGE. * * @(#)uipc_mbuf.c 8.2 (Berkeley) 1/4/94 - * $Id: fil.c,v 2.197 2003/07/01 18:30:18 darrenr Exp $ + * $Id: fil.c,v 2.243.2.64 2005/08/13 05:19:59 darrenr Exp $ */ /* * Copy data from an mbuf chain starting "off" bytes from the beginning, @@ -3026,7 +3157,7 @@ m_copyback(m0, off, len, cp) m = m->m_next; } while (len > 0) { - mlen = min (m->m_len - off, len); + mlen = min(m->m_len - off, len); bcopy(cp, off + mtod(m, caddr_t), (unsigned)mlen); cp += mlen; len -= mlen; @@ -3075,7 +3206,7 @@ frgroup_t ***fgpp; frgroup_t *fg, **fgp; /* - * Which list of groups to search in is dependant on which list of + * Which list of groups to search in is dependent on which list of * rules are being operated on. */ fgp = &ipfgroups[unit][set]; @@ -3165,11 +3296,11 @@ minor_t unit; int set; { frgroup_t *fg, **fgp; - + fg = fr_findgroup(group, unit, set, &fgp); if (fg == NULL) return; - + fg->fg_ref--; if (fg->fg_ref == 0) { *fgp = fg->fg_next; @@ -3297,8 +3428,6 @@ frentry_t **listp; /* Function: frflush */ /* Returns: int - >= 0 - number of flushed rules */ /* Parameters: unit(I) - device for which to flush rules */ -/* proto(I) - which proto rules ipv4(4), ipv6(6) */ -/* ipv4 and ipv6(0) to flush */ /* flags(I) - which set of rules to flush */ /* */ /* Calls flushlist() for all filter rules (accounting, firewall - both IPv4 */ @@ -3451,6 +3580,7 @@ u_32_t ip; return -1; } + #ifdef USE_INET6 /* ------------------------------------------------------------------------ */ /* Function: count6bits */ @@ -3476,22 +3606,25 @@ u_32_t *msk; } return i; } -#endif +# endif #endif /* _KERNEL */ /* ------------------------------------------------------------------------ */ /* Function: frsynclist */ /* Returns: void */ -/* Parameters: Nil */ +/* Parameters: fr(I) - start of filter list to sync interface names for */ +/* ifp(I) - interface pointer for limiting sync lookups */ /* Write Locks: ipf_mutex */ /* */ /* Walk through a list of filter rules and resolve any interface names into */ /* pointers. Where dynamic addresses are used, also update the IP address */ -/* used in the rule. */ +/* used in the rule. The interface pointer is used to limit the lookups to */ +/* a specific set of matching names if it is non-NULL. */ /* ------------------------------------------------------------------------ */ -static void frsynclist(fr) +static void frsynclist(fr, ifp) frentry_t *fr; +void *ifp; { frdest_t *fdp; int v, i; @@ -3503,15 +3636,9 @@ frentry_t *fr; * Lookup all the interface names that are part of the rule. */ for (i = 0; i < 4; i++) { - if ((fr->fr_ifnames[i][1] == '\0') && - ((fr->fr_ifnames[i][0] == '-') || - (fr->fr_ifnames[i][0] == '*'))) { - fr->fr_ifas[i] = NULL; - } else if (fr->fr_ifnames[i][0] != '\0') { - fr->fr_ifas[i] = GETIFP(fr->fr_ifnames[i], v); - if (fr->fr_ifas[i] == (void *)NULL) - fr->fr_ifas[i] = (void *)-1; - } + if ((ifp != NULL) && (fr->fr_ifas[i] != ifp)) + continue; + fr->fr_ifas[i] = fr_resolvenic(fr->fr_ifnames[i], v); } if (fr->fr_type == FR_T_IPF) { @@ -3530,26 +3657,20 @@ frentry_t *fr; } fdp = &fr->fr_tifs[0]; - if (fdp->fd_ifname[0] != '\0') { - fdp->fd_ifp = GETIFP(fdp->fd_ifname, v); - if (fdp->fd_ifp == NULL) - fdp->fd_ifp = (void *)-1; - } + if ((ifp == NULL) || (fdp->fd_ifp == ifp)) + fr_resolvedest(fdp, v); fdp = &fr->fr_tifs[1]; - if (fdp->fd_ifname[0] != '\0') { - fdp->fd_ifp = GETIFP(fdp->fd_ifname, v); - if (fdp->fd_ifp == NULL) - fdp->fd_ifp = (void *)-1; - } + if ((ifp == NULL) || (fdp->fd_ifp == ifp)) + fr_resolvedest(fdp, v); fdp = &fr->fr_dif; - if (fdp->fd_ifname[0] != '\0') { + if ((ifp == NULL) || (fdp->fd_ifp == ifp)) { + fr_resolvedest(fdp, v); + fr->fr_flags &= ~FR_DUP; - fdp->fd_ifp = GETIFP(fdp->fd_ifname, v); - if (fdp->fd_ifp == NULL) - fdp->fd_ifp = (void *)-1; - else + if ((fdp->fd_ifp != (void *)-1) && + (fdp->fd_ifp != NULL)) fr->fr_flags |= FR_DUP; } @@ -3582,51 +3703,33 @@ frentry_t *fr; /* filter rules, NAT entries and the state table and check if anything */ /* needs to be changed/updated. */ /* ------------------------------------------------------------------------ */ -void frsync() +void frsync(ifp) +void *ifp; { int i; -# ifndef MENTAT - struct ifnet *ifp; - -# if defined(__OpenBSD__) || ((NetBSD >= 199511) && (NetBSD < 1991011)) || \ - (defined(__FreeBSD_version) && (__FreeBSD_version >= 300000)) -# if (NetBSD >= 199905) || defined(__OpenBSD__) - for (ifp = ifnet.tqh_first; ifp; ifp = ifp->if_list.tqe_next) -# elif defined(__FreeBSD_version) && (__FreeBSD_version >= 500043) - IFNET_RLOCK(); - TAILQ_FOREACH(ifp, &ifnet, if_link); -# else - for (ifp = ifnet.tqh_first; ifp; ifp = ifp->if_link.tqe_next) -# endif -# else - for (ifp = ifnet; ifp; ifp = ifp->if_next) -# endif - { - fr_natsync(ifp); - fr_statesync(ifp); - } -# if defined(__FreeBSD_version) && (__FreeBSD_version >= 500043) - IFNET_RUNLOCK(); -# endif + +# if !SOLARIS + fr_natsync(ifp); + fr_statesync(ifp); # endif WRITE_ENTER(&ipf_mutex); - frsynclist(ipacct[0][fr_active]); - frsynclist(ipacct[1][fr_active]); - frsynclist(ipfilter[0][fr_active]); - frsynclist(ipfilter[1][fr_active]); - frsynclist(ipacct6[0][fr_active]); - frsynclist(ipacct6[1][fr_active]); - frsynclist(ipfilter6[0][fr_active]); - frsynclist(ipfilter6[1][fr_active]); + frsynclist(ipacct[0][fr_active], ifp); + frsynclist(ipacct[1][fr_active], ifp); + frsynclist(ipfilter[0][fr_active], ifp); + frsynclist(ipfilter[1][fr_active], ifp); + frsynclist(ipacct6[0][fr_active], ifp); + frsynclist(ipacct6[1][fr_active], ifp); + frsynclist(ipfilter6[0][fr_active], ifp); + frsynclist(ipfilter6[1][fr_active], ifp); for (i = 0; i < IPL_LOGSIZE; i++) { frgroup_t *g; for (g = ipfgroups[i][0]; g != NULL; g = g->fg_next) - frsynclist(g->fg_start); + frsynclist(g->fg_start, ifp); for (g = ipfgroups[i][1]; g != NULL; g = g->fg_next) - frsynclist(g->fg_start); + frsynclist(g->fg_start, ifp); } RWLOCK_EXIT(&ipf_mutex); } @@ -3655,14 +3758,14 @@ size_t size; caddr_t ca; int err; -#if SOLARIS - err = copyin(src, (caddr_t)&ca, sizeof(ca)); +# if SOLARIS + err = COPYIN(src, (caddr_t)&ca, sizeof(ca)); if (err != 0) return err; -#else +# else bcopy(src, (caddr_t)&ca, sizeof(ca)); -#endif - err = copyin(ca, dst, size); +# endif + err = COPYIN(ca, dst, size); return err; } @@ -3685,86 +3788,37 @@ size_t size; caddr_t ca; int err; -#if SOLARIS - err = copyin(dst, (caddr_t)&ca, sizeof(ca)); +# if SOLARIS + err = COPYIN(dst, (caddr_t)&ca, sizeof(ca)); if (err != 0) return err; -#else +# else bcopy(dst, (caddr_t)&ca, sizeof(ca)); -#endif - err = copyout(src, ca, size); +# endif + err = COPYOUT(src, ca, size); return err; } - -#else /* _KERNEL */ - - -/* - * See above for description, except that all addressing is in user space. - */ -int copyoutptr(src, dst, size) -void *src, *dst; -size_t size; -{ - caddr_t ca; - - bcopy(dst, (char *)&ca, sizeof(ca)); - bcopy(src, ca, size); - return 0; -} - - -/* - * See above for description, except that all addressing is in user space. - */ -int copyinptr(src, dst, size) -void *src, *dst; -size_t size; -{ - caddr_t ca; - - bcopy(src, (char *)&ca, sizeof(ca)); - bcopy(ca, dst, size); - return 0; -} - - -/* - * return the first IP Address associated with an interface - */ -int fr_ifpaddr(v, flags, ifptr, inp, inpmask) -int v, flags; -void *ifptr; -struct in_addr *inp, *inpmask; -{ - return 0; -} - #endif /* ------------------------------------------------------------------------ */ /* Function: fr_lock */ -/* Returns: int - 0 == success, else error */ +/* Returns: (void) */ /* Parameters: data(I) - pointer to lock value to set */ /* lockp(O) - pointer to location to store old lock value */ /* */ /* Get the new value for the lock integer, set it and return the old value */ /* in *lockp. */ /* ------------------------------------------------------------------------ */ -int fr_lock(data, lockp) +void fr_lock(data, lockp) caddr_t data; int *lockp; { - int arg, error; + int arg; - error = COPYIN(data, (caddr_t)&arg, sizeof(arg)); - if (!error) { - error = COPYOUT((caddr_t)lockp, data, sizeof(*lockp)); - if (!error) - *lockp = arg; - } - return error; + BCOPYIN(data, (caddr_t)&arg, sizeof(arg)); + BCOPYOUT((caddr_t)lockp, data, sizeof(*lockp)); + *lockp = arg; } @@ -3811,7 +3865,9 @@ friostat_t *fiop; fiop->f_logging = 0; #endif fiop->f_defpass = fr_pass; - (void) strncpy(fiop->f_version, ipfilter_version, sizeof(fiop->f_version)); + fiop->f_features = fr_features; + (void) strncpy(fiop->f_version, ipfilter_version, + sizeof(fiop->f_version)); } @@ -3892,8 +3948,7 @@ int rev; (rev && (icmpreplytype4[ictype] == icmp->icmp_type))) { if (icmp->icmp_type != ICMP_ECHOREPLY) return 1; - if ((icmp->icmp_id == ic->ici_id) && - (icmp->icmp_seq == ic->ici_seq)) + if (icmp->icmp_id == ic->ici_id) return 1; } } @@ -3903,8 +3958,7 @@ int rev; (rev && (icmpreplytype6[ictype] == icmp->icmp_type))) { if (icmp->icmp_type != ICMP6_ECHO_REPLY) return 1; - if ((icmp->icmp_id == ic->ici_id) && - (icmp->icmp_seq == ic->ici_seq)) + if (icmp->icmp_id == ic->ici_id) return 1; } } @@ -3936,7 +3990,11 @@ lookupfunc_t *funcptr; ip_pool_t *ipo; void *ptr; +#if defined(SNPRINTF) && defined(_KERNEL) + (void) SNPRINTF(name, sizeof(name), "%u", number); +#else (void) sprintf(name, "%u", number); +#endif READ_ENTER(&ip_poolrw); @@ -3994,21 +4052,16 @@ lookupfunc_t *funcptr; /* ------------------------------------------------------------------------ */ int frrequest(unit, req, data, set, makecopy) int unit; -#if defined(__NetBSD__) || defined(__OpenBSD__) || \ - (_BSDI_VERSION >= 199701) || (__FreeBSD_version >= 300003) -u_long req; -#else -int req; -#endif +ioctlcmd_t req; int set, makecopy; caddr_t data; { frentry_t frd, *fp, *f, **fprev, **ftail; int error = 0, in, v; + void *ptr, *uptr; u_int *p, *pp; frgroup_t *fg; char *group; - void *ptr; fg = NULL; fp = &frd; @@ -4032,6 +4085,7 @@ caddr_t data; return EINVAL; v = fp->fr_v; + uptr = fp->fr_data; /* * Only filter rules for IPv4 or IPv6 are accepted. @@ -4064,8 +4118,10 @@ caddr_t data; * Check that the group number does exist and that its use (in/out) * matches what the rule is. */ + if (!strncmp(fp->fr_grhead, "0", FR_GROUPLEN)) + *fp->fr_grhead = '\0'; group = fp->fr_group; - if (!strcmp(group, "0")) + if (!strncmp(group, "0", FR_GROUPLEN)) *group = '\0'; if (FR_ISACCOUNT(fp->fr_flags)) @@ -4110,10 +4166,15 @@ caddr_t data; fprev = &fg->fg_start; } - for (f = *fprev; f != NULL; fprev = &f->fr_next) - if (fp->fr_collect <= f->fr_collect) - break; ftail = fprev; + for (f = *ftail; (f = *ftail) != NULL; ftail = &f->fr_next) { + if (fp->fr_collect <= f->fr_collect) { + ftail = fprev; + f = NULL; + break; + } + fprev = ftail; + } /* * Copy in extra data for the rule. @@ -4123,9 +4184,9 @@ caddr_t data; KMALLOCS(ptr, void *, fp->fr_dsize); if (!ptr) return ENOMEM; - error = COPYIN(fp->fr_data, ptr, fp->fr_dsize); + error = COPYIN(uptr, ptr, fp->fr_dsize); } else { - ptr = fp->fr_data; + ptr = uptr; error = 0; } if (error != 0) { @@ -4141,7 +4202,7 @@ caddr_t data; */ switch (fp->fr_type & ~FR_T_BUILTIN) { -#if defined(IPFILTER_BPF) && defined(_KERNEL) +#if defined(IPFILTER_BPF) case FR_T_BPFOPC : if (fp->fr_dsize == 0) return EINVAL; @@ -4154,8 +4215,17 @@ caddr_t data; break; #endif case FR_T_IPF : - if (fp->fr_dsize == 0) + if (fp->fr_dsize != sizeof(fripf_t)) + return EINVAL; + + /* + * Allowing a rule with both "keep state" and "with oow" is + * pointless because adding a state entry to the table will + * fail with the out of window (oow) flag set. + */ + if ((fp->fr_flags & FR_KEEPSTATE) && (fp->fr_flx & FI_OOW)) return EINVAL; + switch (fp->fr_satype) { case FRI_BROADCAST : @@ -4203,7 +4273,6 @@ caddr_t data; break; #endif default : - break; } break; @@ -4223,7 +4292,7 @@ caddr_t data; /* * Lookup all the interface names that are part of the rule. */ - frsynclist(fp); + frsynclist(fp, NULL); fp->fr_statecnt = 0; /* @@ -4243,26 +4312,46 @@ caddr_t data; WRITE_ENTER(&ipf_mutex); bzero((char *)frcache, sizeof(frcache)); - for (; (f = *ftail) != NULL; ftail = &f->fr_next) - if ((fp->fr_cksum == f->fr_cksum) && - (f->fr_dsize == fp->fr_dsize) && - !bcmp((char *)&f->fr_dsize, - (char *)&fp->fr_dsize, FR_CMPSIZ) && - (!ptr || !f->fr_data || + for (; (f = *ftail) != NULL; ftail = &f->fr_next) { + if ((fp->fr_cksum != f->fr_cksum) || + (f->fr_dsize != fp->fr_dsize)) + continue; + if (bcmp((char *)&f->fr_func, (char *)&fp->fr_func, FR_CMPSIZ)) + continue; + if ((!ptr && !f->fr_data) || + (ptr && f->fr_data && !bcmp((char *)ptr, (char *)f->fr_data, f->fr_dsize))) break; + } /* * If zero'ing statistics, copy current to caller and zero. */ - if (req == (int)SIOCZRLST) { + if (req == (ioctlcmd_t)SIOCZRLST) { if (f == NULL) error = ESRCH; else { - error = fr_outobj(data, f, IPFOBJ_FRENTRY); + /* + * Copy and reduce lock because of impending copyout. + * Well we should, but if we do then the atomicity of + * this call and the correctness of fr_hits and + * fr_bytes cannot be guaranteed. As it is, this code + * only resets them to 0 if they are successfully + * copied out into user space. + */ + bcopy((char *)f, (char *)fp, sizeof(*f)); + /* MUTEX_DOWNGRADE(&ipf_mutex); */ + + /* + * When we copy this rule back out, set the data + * pointer to be what it was in user space. + */ + fp->fr_data = uptr; + error = fr_outobj(data, fp, IPFOBJ_FRENTRY); + if (error == 0) { - if (f->fr_dsize != 0 && f->fr_data != NULL) - error = COPYOUT(f->fr_data, ptr, + if ((f->fr_dsize != 0) && (uptr != NULL)) + error = COPYOUT(f->fr_data, uptr, f->fr_dsize); if (error == 0) { f->fr_hits = 0; @@ -4271,7 +4360,7 @@ caddr_t data; } } - if (ptr != NULL && makecopy != 0) { + if ((ptr != NULL) && (makecopy != 0)) { KFREES(ptr, fp->fr_dsize); } RWLOCK_EXIT(&ipf_mutex); @@ -4279,11 +4368,40 @@ caddr_t data; } if (!f) { - if (req == (int)SIOCINAFR || req == (int)SIOCINIFR) { + /* + * At the end of this, ftail must point to the place where the + * new rule is to be saved/inserted/added. + * For SIOCAD*FR, this should be the last rule in the group of + * rules that have equal fr_collect fields. + * For SIOCIN*FR, ... + */ + if (req == (ioctlcmd_t)SIOCADAFR || + req == (ioctlcmd_t)SIOCADIFR) { + + for (ftail = fprev; (f = *ftail) != NULL; ) { + if (f->fr_collect > fp->fr_collect) + break; + ftail = &f->fr_next; + } + f = NULL; + ptr = NULL; + error = 0; + } else if (req == (ioctlcmd_t)SIOCINAFR || + req == (ioctlcmd_t)SIOCINIFR) { + while ((f = *fprev) != NULL) { + if (f->fr_collect >= fp->fr_collect) + break; + fprev = &f->fr_next; + } ftail = fprev; if (fp->fr_hits != 0) { - while (--fp->fr_hits && (f = *ftail)) + while (fp->fr_hits && (f = *ftail)) { + if (f->fr_collect != fp->fr_collect) + break; + fprev = ftail; ftail = &f->fr_next; + fp->fr_hits--; + } } f = NULL; ptr = NULL; @@ -4294,7 +4412,7 @@ caddr_t data; /* * Request to remove a rule. */ - if (req == (int)SIOCRMAFR || req == (int)SIOCRMIFR) { + if (req == (ioctlcmd_t)SIOCRMAFR || req == (ioctlcmd_t)SIOCRMIFR) { if (!f) error = ESRCH; else { @@ -4318,7 +4436,7 @@ caddr_t data; #ifdef IPFILTER_SCAN if (f->fr_isctag[0] != '\0' && (f->fr_isc != (struct ipscan *)-1)) - isc_detachfr(f); + ipsc_detachfr(f); #endif if ((fg != NULL) && (fg->fg_head != NULL)) fg->fg_head->fr_ref--; @@ -4328,7 +4446,7 @@ caddr_t data; } if (*f->fr_grhead != '\0') fr_delgroup(f->fr_grhead, unit, set); - fr_fixskip(fprev, f, -1); + fr_fixskip(ftail, f, -1); *ftail = f->fr_next; f->fr_next = NULL; (void)fr_derefrule(&f); @@ -4349,7 +4467,7 @@ caddr_t data; } else f = fp; if (f != NULL) { - if (fg != NULL && fg->fg_head!= NULL ) + if (fg != NULL && fg->fg_head != NULL) fg->fg_head->fr_ref++; if (fp != f) bcopy((char *)fp, (char *)f, @@ -4357,7 +4475,8 @@ caddr_t data; MUTEX_NUKE(&f->fr_lock); MUTEX_INIT(&f->fr_lock, "filter rule lock"); #ifdef IPFILTER_SCAN - if (f->fr_isctag[0] != '\0' && isc_attachfr(f)) + if (f->fr_isctag[0] != '\0' && + ipsc_attachfr(f)) f->fr_isc = (struct ipscan *)-1; #endif f->fr_hits = 0; @@ -4365,9 +4484,9 @@ caddr_t data; f->fr_ref = 1; f->fr_next = *ftail; *ftail = f; - if (req == (int)SIOCINIFR || - req == (int)SIOCINAFR) - fr_fixskip(fprev, f, 1); + if (req == (ioctlcmd_t)SIOCINIFR || + req == (ioctlcmd_t)SIOCINAFR) + fr_fixskip(ftail, f, 1); f->fr_grp = NULL; group = f->fr_grhead; if (*group != '\0') { @@ -4442,16 +4561,15 @@ ipfunc_t funcptr; /* */ /* Copy in a ipfunc_resolve_t structure and then fill in the missing field. */ /* This will either be the function name (if the pointer is set) or the */ -/* function pointer if the name is set. When found, fill in the details so */ -/* it can be copied back to user space. */ +/* function pointer if the name is set. When found, fill in the other one */ +/* so that the entire, complete, structure can be copied back to user space.*/ /* ------------------------------------------------------------------------ */ int fr_resolvefunc(data) void *data; { ipfunc_resolve_t res, *ft; - if (COPYIN(data, &res, sizeof(res)) != 0) - return EFAULT; + BCOPYIN(data, &res, sizeof(res)); if (res.ipfu_addr == NULL && res.ipfu_name[0] != '\0') { for (ft = fr_availfuncs; ft->ipfu_addr != NULL; ft++) @@ -4468,7 +4586,7 @@ void *data; for (ft = fr_availfuncs; ft->ipfu_addr != NULL; ft++) if (ft->ipfu_addr == res.ipfu_addr) { (void) strncpy(res.ipfu_name, ft->ipfu_name, - sizeof(res.ipfu_name)); + sizeof(res.ipfu_name)); res.ipfu_init = ft->ipfu_init; if (COPYOUT(&res, data, sizeof(res)) != 0) return EFAULT; @@ -4479,9 +4597,10 @@ void *data; } -#if !defined(_KERNEL) || (!defined(NetBSD) && !defined(OpenBSD)) || \ - ((defined(NetBSD) && (__NetBSD_Version__ < 105000000)) && \ - (defined(OpenBSD) && (OpenBSD < 200006))) +#if !defined(_KERNEL) || (!defined(__NetBSD__) && !defined(__OpenBSD__) && !defined(__FreeBSD__)) || \ + (defined(__FreeBSD__) && (__FreeBSD_version < 490000)) || \ + (defined(__NetBSD__) && (__NetBSD_Version__ < 105000000)) || \ + (defined(__OpenBSD__) && (OpenBSD < 200006)) /* * From: NetBSD * ppsratecheck(): packets (or events) per second limitation. @@ -4589,7 +4708,11 @@ frentry_t *fr; char name[FR_GROUPLEN]; iphtable_t *iph; +#if defined(SNPRINTF) && defined(_KERNEL) + (void) SNPRINTF(name, sizeof(name), "%d", fr->fr_arg); +#else (void) sprintf(name, "%d", fr->fr_arg); +#endif iph = fr_findhtable(IPL_LOGIPF, name); if (iph == NULL) return ESRCH; @@ -4623,7 +4746,7 @@ u_32_t *passp; fg = rval; fin->fin_fr = fg->fg_start; - (void) fr_scanlist(fin, *passp); + (void) fr_scanlist(fin, *passp); return fin->fin_fr; } @@ -4651,11 +4774,21 @@ u_32_t *passp; fg = rval; fin->fin_fr = fg->fg_start; - (void) fr_scanlist(fin, *passp); + (void) fr_scanlist(fin, *passp); return fin->fin_fr; } #endif /* IPFILTER_LOOKUP */ +/* + * Queue functions + * =============== + * These functions manage objects on queues for efficient timeouts. There are + * a number of system defined queues as well as user defined timeouts. It is + * expected that a lock is held in the domain in which the queue belongs + * (i.e. either state or NAT) when calling any of these functions that prevents + * fr_freetimeoutqueue() from being called at the same time as any other. + */ + /* ------------------------------------------------------------------------ */ /* Function: fr_addtimeoutqueue */ @@ -4669,26 +4802,35 @@ u_32_t *passp; /* being requested. If it finds one, increments the reference counter and */ /* returns a pointer to it. If none are found, it allocates a new one and */ /* inserts it at the top of the list. */ +/* */ +/* Locking. */ +/* It is assumed that the caller of this function has an appropriate lock */ +/* held (exclusively) in the domain that encompases 'parent'. */ /* ------------------------------------------------------------------------ */ ipftq_t *fr_addtimeoutqueue(parent, seconds) ipftq_t **parent; u_int seconds; { - u_int period; ipftq_t *ifq; + u_int period; period = seconds * IPF_HZ_DIVIDE; + MUTEX_ENTER(&ipf_timeoutlock); - for (ifq = *parent; ifq != NULL; ifq = ifq->ifq_next) - if (ifq->ifq_ttl == period) - break; + for (ifq = *parent; ifq != NULL; ifq = ifq->ifq_next) { + if (ifq->ifq_ttl == period) { + /* + * Reset the delete flag, if set, so the structure + * gets reused rather than freed and reallocated. + */ + MUTEX_ENTER(&ifq->ifq_lock); + ifq->ifq_flags &= ~IFQF_DELETE; + ifq->ifq_ref++; + MUTEX_EXIT(&ifq->ifq_lock); + MUTEX_EXIT(&ipf_timeoutlock); - if (ifq != NULL) { - MUTEX_ENTER(&ifq->ifq_lock); - ifq->ifq_ref++; - MUTEX_EXIT(&ifq->ifq_lock); - MUTEX_EXIT(&ipf_timeoutlock); - return ifq; + return ifq; + } } KMALLOC(ifq, ipftq_t *); @@ -4712,44 +4854,114 @@ u_int seconds; /* ------------------------------------------------------------------------ */ /* Function: fr_deletetimeoutqueue */ -/* Returns: Nil */ -/* Parameters: difp(I) - timeout queue which is losing a reference. */ +/* Returns: int - new reference count value of the timeout queue */ +/* Parameters: ifq(I) - timeout queue which is losing a reference. */ +/* Locks: ifq->ifq_lock */ /* */ /* This routine must be called when we're discarding a pointer to a timeout */ -/* queue object. It takes care of the reference counter and free's it when */ -/* it reaches 0. */ +/* queue object, taking care of the reference counter. */ +/* */ +/* Now that this just sets a DELETE flag, it requires the expire code to */ +/* check the list of user defined timeout queues and call the free function */ +/* below (currently commented out) to stop memory leaking. It is done this */ +/* way because the locking may not be sufficient to safely do a free when */ +/* this function is called. */ /* ------------------------------------------------------------------------ */ -void fr_deletetimeoutqueue(ifq) +int fr_deletetimeoutqueue(ifq) ipftq_t *ifq; { - MUTEX_ENTER(&ipf_timeoutlock); - MUTEX_ENTER(&ifq->ifq_lock); ifq->ifq_ref--; + if ((ifq->ifq_ref == 0) && ((ifq->ifq_flags & IFQF_USER) != 0)) { + ifq->ifq_flags |= IFQF_DELETE; + } - if ((ifq->ifq_ref == 0) && (ifq->ifq_head == NULL)) { - /* - * Remove from its position in the list. - */ - *ifq->ifq_pnext = ifq->ifq_next; - if (ifq->ifq_next != NULL) - ifq->ifq_next->ifq_pnext = ifq->ifq_pnext; - - MUTEX_EXIT(&ifq->ifq_lock); /* Tru64 */ - MUTEX_DESTROY(&ifq->ifq_lock); - KFREE(ifq); - fr_userifqs--; - } else { - MUTEX_EXIT(&ifq->ifq_lock); + return ifq->ifq_ref; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: fr_freetimeoutqueue */ +/* Parameters: ifq(I) - timeout queue which is losing a reference. */ +/* Returns: Nil */ +/* */ +/* Locking: */ +/* It is assumed that the caller of this function has an appropriate lock */ +/* held (exclusively) in the domain that encompases the callers "domain". */ +/* The ifq_lock for this structure should not be held. */ +/* */ +/* Remove a user definde timeout queue from the list of queues it is in and */ +/* tidy up after this is done. */ +/* ------------------------------------------------------------------------ */ +void fr_freetimeoutqueue(ifq) +ipftq_t *ifq; +{ + + + if (((ifq->ifq_flags & IFQF_DELETE) == 0) || (ifq->ifq_ref != 0) || + ((ifq->ifq_flags & IFQF_USER) == 0)) { + printf("fr_freetimeoutqueue(%lx) flags 0x%x ttl %d ref %d\n", + (u_long)ifq, ifq->ifq_flags, ifq->ifq_ttl, + ifq->ifq_ref); + return; } - MUTEX_EXIT(&ipf_timeoutlock); + + /* + * Remove from its position in the list. + */ + *ifq->ifq_pnext = ifq->ifq_next; + if (ifq->ifq_next != NULL) + ifq->ifq_next->ifq_pnext = ifq->ifq_pnext; + + MUTEX_DESTROY(&ifq->ifq_lock); + fr_userifqs--; + KFREE(ifq); +} + + +/* ------------------------------------------------------------------------ */ +/* Function: fr_deletequeueentry */ +/* Returns: Nil */ +/* Parameters: tqe(I) - timeout queue entry to delete */ +/* ifq(I) - timeout queue to remove entry from */ +/* */ +/* Remove a tail queue entry from its queue and make it an orphan. */ +/* fr_deletetimeoutqueue is called to make sure the reference count on the */ +/* queue is correct. We can't, however, call fr_freetimeoutqueue because */ +/* the correct lock(s) may not be held that would make it safe to do so. */ +/* ------------------------------------------------------------------------ */ +void fr_deletequeueentry(tqe) +ipftqent_t *tqe; +{ + ipftq_t *ifq; + + ifq = tqe->tqe_ifq; + if (ifq == NULL) + return; + + MUTEX_ENTER(&ifq->ifq_lock); + + if (tqe->tqe_pnext != NULL) { + *tqe->tqe_pnext = tqe->tqe_next; + if (tqe->tqe_next != NULL) + tqe->tqe_next->tqe_pnext = tqe->tqe_pnext; + else /* we must be the tail anyway */ + ifq->ifq_tail = tqe->tqe_pnext; + + tqe->tqe_pnext = NULL; + tqe->tqe_ifq = NULL; + } + + (void) fr_deletetimeoutqueue(ifq); + + MUTEX_EXIT(&ifq->ifq_lock); } /* ------------------------------------------------------------------------ */ /* Function: fr_queuefront */ /* Returns: Nil */ -/* Parameters: tq(I) - pointer to timeout queue information */ +/* Parameters: tqe(I) - pointer to timeout queue entry */ /* */ /* Move a queue entry to the front of the queue, if it isn't already there. */ /* ------------------------------------------------------------------------ */ @@ -4759,9 +4971,11 @@ ipftqent_t *tqe; ipftq_t *ifq; ifq = tqe->tqe_ifq; + if (ifq == NULL) + return; + MUTEX_ENTER(&ifq->ifq_lock); if (ifq->ifq_head != tqe) { - MUTEX_ENTER(&ifq->ifq_lock); *tqe->tqe_pnext = tqe->tqe_next; if (tqe->tqe_next) tqe->tqe_next->tqe_pnext = tqe->tqe_pnext; @@ -4772,15 +4986,15 @@ ipftqent_t *tqe; ifq->ifq_head->tqe_pnext = &tqe->tqe_next; ifq->ifq_head = tqe; tqe->tqe_pnext = &ifq->ifq_head; - MUTEX_EXIT(&ifq->ifq_lock); } + MUTEX_EXIT(&ifq->ifq_lock); } /* ------------------------------------------------------------------------ */ /* Function: fr_queueback */ /* Returns: Nil */ -/* Parameters: tq(I) - pointer to timeout queue information */ +/* Parameters: tqe(I) - pointer to timeout queue entry */ /* */ /* Move a queue entry to the back of the queue, if it isn't already there. */ /* ------------------------------------------------------------------------ */ @@ -4792,19 +5006,56 @@ ipftqent_t *tqe; ifq = tqe->tqe_ifq; if (ifq == NULL) return; - if (ifq->ifq_tail != NULL && *ifq->ifq_tail != tqe) { - MUTEX_ENTER(&ifq->ifq_lock); - *tqe->tqe_pnext = tqe->tqe_next; - tqe->tqe_next->tqe_pnext = tqe->tqe_pnext; + tqe->tqe_die = fr_ticks + ifq->ifq_ttl; - tqe->tqe_next = NULL; - tqe->tqe_die = fr_ticks + ifq->ifq_ttl; - tqe->tqe_pnext = ifq->ifq_tail; - *ifq->ifq_tail = tqe; - ifq->ifq_tail = &tqe->tqe_next; - tqe->tqe_die = fr_ticks + ifq->ifq_ttl; + MUTEX_ENTER(&ifq->ifq_lock); + if (tqe->tqe_next == NULL) { /* at the end already ? */ MUTEX_EXIT(&ifq->ifq_lock); + return; } + + /* + * Remove from list + */ + *tqe->tqe_pnext = tqe->tqe_next; + tqe->tqe_next->tqe_pnext = tqe->tqe_pnext; + + /* + * Make it the last entry. + */ + tqe->tqe_next = NULL; + tqe->tqe_pnext = ifq->ifq_tail; + *ifq->ifq_tail = tqe; + ifq->ifq_tail = &tqe->tqe_next; + MUTEX_EXIT(&ifq->ifq_lock); +} + + +/* ------------------------------------------------------------------------ */ +/* Function: fr_queueappend */ +/* Returns: Nil */ +/* Parameters: tqe(I) - pointer to timeout queue entry */ +/* ifq(I) - pointer to timeout queue */ +/* parent(I) - owing object pointer */ +/* */ +/* Add a new item to this queue and put it on the very end. */ +/* ------------------------------------------------------------------------ */ +void fr_queueappend(tqe, ifq, parent) +ipftqent_t *tqe; +ipftq_t *ifq; +void *parent; +{ + + MUTEX_ENTER(&ifq->ifq_lock); + tqe->tqe_parent = parent; + tqe->tqe_pnext = ifq->ifq_tail; + *ifq->ifq_tail = tqe; + ifq->ifq_tail = &tqe->tqe_next; + tqe->tqe_next = NULL; + tqe->tqe_ifq = ifq; + tqe->tqe_die = fr_ticks + ifq->ifq_ttl; + ifq->ifq_ref++; + MUTEX_EXIT(&ifq->ifq_lock); } @@ -4826,13 +5077,15 @@ ipftq_t *oifq, *nifq; /* * Is the operation here going to be a no-op ? */ - if (oifq == nifq && *oifq->ifq_tail == tqe) + MUTEX_ENTER(&oifq->ifq_lock); + if (oifq == nifq && *oifq->ifq_tail == tqe) { + MUTEX_EXIT(&oifq->ifq_lock); return; + } /* * Remove from the old queue */ - MUTEX_ENTER(&oifq->ifq_lock); *tqe->tqe_pnext = tqe->tqe_next; if (tqe->tqe_next) tqe->tqe_next->tqe_pnext = tqe->tqe_pnext; @@ -4847,11 +5100,13 @@ ipftq_t *oifq, *nifq; */ if (oifq != nifq) { tqe->tqe_ifq = NULL; + + (void) fr_deletetimeoutqueue(oifq); + MUTEX_EXIT(&oifq->ifq_lock); - if ((oifq->ifq_flags & IFQF_USER) != 0) - fr_deletetimeoutqueue(oifq); MUTEX_ENTER(&nifq->ifq_lock); + tqe->tqe_ifq = nifq; nifq->ifq_ref++; } @@ -4917,32 +5172,47 @@ fr_info_t *fin; #ifdef NEED_FRGETIFNAME /* ------------------------------------------------------------------------ */ /* Function: fr_getifname */ -/* Returns: char * - pointer to interface name */ -/* Parameters: ifp(I) - pointer to network interface */ +/* Returns: char * - pointer to interface name */ +/* Parameters: ifp(I) - pointer to network interface */ +/* buffer(O) - pointer to where to store interface name */ /* */ -/* Constructs an interface name in the buffer passed. */ +/* Constructs an interface name in the buffer passed. The buffer passed is */ +/* expected to be at least LIFNAMSIZ in bytes big. If buffer is passed in */ +/* as a NULL pointer then return a pointer to a static array. */ /* ------------------------------------------------------------------------ */ char *fr_getifname(ifp, buffer) struct ifnet *ifp; char *buffer; { - static char namebuf[LIFNAMSIZ+1]; + static char namebuf[LIFNAMSIZ]; +# if defined(MENTAT) || defined(__FreeBSD__) || defined(__osf__) || \ + defined(__sgi) || defined(linux) || defined(_AIX51) || \ + (defined(sun) && !defined(__SVR4) && !defined(__svr4__)) int unit, space; char temp[20]; char *s; +# endif if (buffer == NULL) buffer = namebuf; (void) strncpy(buffer, ifp->if_name, LIFNAMSIZ); - namebuf[LIFNAMSIZ] = '\0'; + buffer[LIFNAMSIZ - 1] = '\0'; +# if defined(MENTAT) || defined(__FreeBSD__) || defined(__osf__) || \ + defined(__sgi) || defined(_AIX51) || \ + (defined(sun) && !defined(__SVR4) && !defined(__svr4__)) for (s = buffer; *s; s++) ; unit = ifp->if_unit; space = LIFNAMSIZ - (s - buffer); if (space > 0) { +# if defined(SNPRINTF) && defined(_KERNEL) + (void) SNPRINTF(temp, sizeof(temp), "%d", unit); +# else (void) sprintf(temp, "%d", unit); +# endif (void) strncpy(s, temp, space); } +# endif return buffer; } #endif @@ -4960,13 +5230,9 @@ char *buffer; /* EIO if ipfilter is not running. Also checks if write perms are req'd */ /* for the device in order to execute the ioctl. */ /* ------------------------------------------------------------------------ */ -INLINE int fr_ioctlswitch(unit, data, cmd, mode) +int fr_ioctlswitch(unit, data, cmd, mode) int unit, mode; -# if defined(__NetBSD__) || defined(__OpenBSD__) -u_long cmd; -#else -int cmd; -#endif +ioctlcmd_t cmd; void *data; { int error = 0; @@ -4990,7 +5256,8 @@ void *data; break; case IPL_LOGAUTH : if (fr_running > 0) { - if ((cmd == SIOCADAFR) || (cmd == SIOCRMAFR)) { + if ((cmd == (ioctlcmd_t)SIOCADAFR) || + (cmd == (ioctlcmd_t)SIOCRMAFR)) { if (!(mode & FWRITE)) { error = EPERM; } else { @@ -5040,21 +5307,23 @@ void *data; * This array defines the expected size of objects coming into the kernel * for the various recognised object types. */ -static int fr_objbytes[] = { - 0, /* frentry */ - sizeof(struct friostat), - sizeof(struct fr_info), - sizeof(struct fr_authstat), - sizeof(struct ipfrstat), - sizeof(struct ipnat), - sizeof(struct natstat), - sizeof(struct ipstate_save), - sizeof(struct nat_save), - sizeof(struct natlookup), - 0, /* ipstate */ - sizeof(struct ips_stat), - sizeof(struct frauth), - sizeof(struct ipftune) +#define NUM_OBJ_TYPES 14 + +static int fr_objbytes[NUM_OBJ_TYPES][2] = { + { 1, sizeof(struct frentry) }, /* frentry */ + { 0, sizeof(struct friostat) }, + { 0, sizeof(struct fr_info) }, + { 0, sizeof(struct fr_authstat) }, + { 0, sizeof(struct ipfrstat) }, + { 0, sizeof(struct ipnat) }, + { 0, sizeof(struct natstat) }, + { 0, sizeof(struct ipstate_save) }, + { 1, sizeof(struct nat_save) }, /* nat_save */ + { 0, sizeof(struct natlookup) }, + { 1, sizeof(struct ipstate) }, /* ipstate */ + { 0, sizeof(struct ips_stat) }, + { 0, sizeof(struct frauth) }, + { 0, sizeof(struct ipftune) } }; @@ -5077,32 +5346,138 @@ int type; ipfobj_t obj; int error = 0; - if ((type < 0) || - (type > ((sizeof(fr_objbytes)/sizeof(fr_objbytes[0])) - 1))) + if ((type < 0) || (type > NUM_OBJ_TYPES-1)) return EINVAL; - (void) BCOPYIN((caddr_t)data, (caddr_t)&obj, sizeof(obj)); + BCOPYIN((caddr_t)data, (caddr_t)&obj, sizeof(obj)); if (obj.ipfo_type != type) return EINVAL; #ifndef IPFILTER_COMPAT + if ((fr_objbytes[type][0] & 1) != 0) { + if (obj.ipfo_size < fr_objbytes[type][1]) + return EINVAL; + } else if (obj.ipfo_size != fr_objbytes[type][1]) + return EINVAL; +#else if (obj.ipfo_rev != IPFILTER_VERSION) + /* XXX compatibility hook here */ + ; + if ((fr_objbytes[type][0] & 1) != 0) { + if (obj.ipfo_size < fr_objbytes[type][1]) + /* XXX compatibility hook here */ + return EINVAL; + } else if (obj.ipfo_size != fr_objbytes[type][1]) + /* XXX compatibility hook here */ return EINVAL; - if ((fr_objbytes[type] != 0) && (obj.ipfo_size != fr_objbytes[type])) +#endif + + if ((fr_objbytes[type][0] & 1) != 0) { + error = COPYIN((caddr_t)obj.ipfo_ptr, (caddr_t)ptr, + fr_objbytes[type][1]); + } else { + error = COPYIN((caddr_t)obj.ipfo_ptr, (caddr_t)ptr, + obj.ipfo_size); + } + return error; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: fr_inobjsz */ +/* Returns: int - 0 = success, else failure */ +/* Parameters: data(I) - pointer to ioctl data */ +/* ptr(I) - pointer to store real data in */ +/* type(I) - type of structure being moved */ +/* sz(I) - size of data to copy */ +/* */ +/* As per fr_inobj, except the size of the object to copy in is passed in */ +/* but it must not be smaller than the size defined for the type and the */ +/* type must allow for varied sized objects. The extra requirement here is */ +/* that sz must match the size of the object being passed in - this is not */ +/* not possible nor required in fr_inobj(). */ +/* ------------------------------------------------------------------------ */ +int fr_inobjsz(data, ptr, type, sz) +void *data; +void *ptr; +int type, sz; +{ + ipfobj_t obj; + int error; + + if ((type < 0) || (type > NUM_OBJ_TYPES-1)) + return EINVAL; + if (((fr_objbytes[type][0] & 1) == 0) || (sz < fr_objbytes[type][1])) + return EINVAL; + + BCOPYIN((caddr_t)data, (caddr_t)&obj, sizeof(obj)); + + if (obj.ipfo_type != type) + return EINVAL; + +#ifndef IPFILTER_COMPAT + if (obj.ipfo_size != sz) return EINVAL; #else if (obj.ipfo_rev != IPFILTER_VERSION) /* XXX compatibility hook here */ + ; + if (obj.ipfo_size != sz) + /* XXX compatibility hook here */ + return EINVAL; +#endif + + error = COPYIN((caddr_t)obj.ipfo_ptr, (caddr_t)ptr, sz); + return error; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: fr_outobjsz */ +/* Returns: int - 0 = success, else failure */ +/* Parameters: data(I) - pointer to ioctl data */ +/* ptr(I) - pointer to store real data in */ +/* type(I) - type of structure being moved */ +/* sz(I) - size of data to copy */ +/* */ +/* As per fr_outobj, except the size of the object to copy out is passed in */ +/* but it must not be smaller than the size defined for the type and the */ +/* type must allow for varied sized objects. The extra requirement here is */ +/* that sz must match the size of the object being passed in - this is not */ +/* not possible nor required in fr_outobj(). */ +/* ------------------------------------------------------------------------ */ +int fr_outobjsz(data, ptr, type, sz) +void *data; +void *ptr; +int type, sz; +{ + ipfobj_t obj; + int error; + + if ((type < 0) || (type > NUM_OBJ_TYPES-1) || + ((fr_objbytes[type][0] & 1) == 0) || + (sz < fr_objbytes[type][1])) return EINVAL; - if ((fr_objbytes[type] != 0) && (obj.ipfo_size != fr_objbytes[type])) + BCOPYIN((caddr_t)data, (caddr_t)&obj, sizeof(obj)); + + if (obj.ipfo_type != type) + return EINVAL; + +#ifndef IPFILTER_COMPAT + if (obj.ipfo_size != sz) + return EINVAL; +#else + if (obj.ipfo_rev != IPFILTER_VERSION) + /* XXX compatibility hook here */ + ; + if (obj.ipfo_size != sz) /* XXX compatibility hook here */ return EINVAL; #endif - error = COPYIN((caddr_t)obj.ipfo_ptr, (caddr_t)ptr, obj.ipfo_size); - + error = COPYOUT((caddr_t)ptr, (caddr_t)obj.ipfo_ptr, sz); return error; } @@ -5126,21 +5501,29 @@ int type; ipfobj_t obj; int error; - (void) BCOPYIN((caddr_t)data, (caddr_t)&obj, sizeof(obj)); + if ((type < 0) || (type > NUM_OBJ_TYPES-1)) + return EINVAL; + + BCOPYIN((caddr_t)data, (caddr_t)&obj, sizeof(obj)); if (obj.ipfo_type != type) return EINVAL; #ifndef IPFILTER_COMPAT - if (obj.ipfo_rev != IPFILTER_VERSION) - return EINVAL; - if ((fr_objbytes[type] != 0) && (obj.ipfo_size != fr_objbytes[type])) + if ((fr_objbytes[type][0] & 1) != 0) { + if (obj.ipfo_size < fr_objbytes[type][1]) + return EINVAL; + } else if (obj.ipfo_size != fr_objbytes[type][1]) return EINVAL; #else if (obj.ipfo_rev != IPFILTER_VERSION) /* XXX compatibility hook here */ - return EINVAL; - if ((fr_objbytes[type] != 0) && (obj.ipfo_size != fr_objbytes[type])) + ; + if ((fr_objbytes[type][0] & 1) != 0) { + if (obj.ipfo_size < fr_objbytes[type][1]) + /* XXX compatibility hook here */ + return EINVAL; + } else if (obj.ipfo_size != fr_objbytes[type][1]) /* XXX compatibility hook here */ return EINVAL; #endif @@ -5223,7 +5606,11 @@ fr_info_t *fin; } #endif #if !defined(_KERNEL) - FR_DEBUG(("checkl4sum: %hx == %hx\n", sum, hdrsum)); + if (sum == hdrsum) { + FR_DEBUG(("checkl4sum: %hx == %hx\n", sum, hdrsum)); + } else { + FR_DEBUG(("checkl4sum: %hx != %hx\n", sum, hdrsum)); + } #endif if (hdrsum == sum) return 0; @@ -5331,41 +5718,6 @@ struct in_addr *inp, *inpmask; /* ------------------------------------------------------------------------ */ -/* Function: fr_coalesce */ -/* Returns: 1 == success, -1 == failure, 0 == no change */ -/* Parameters: fin(I) - pointer to packet information */ -/* */ -/* Attempt to get all of the packet data into a single, contiguous buffer. */ -/* If this call returns a failure then the buffers have also been freed. */ -/* ------------------------------------------------------------------------ */ -int fr_coalesce(fin) -fr_info_t *fin; -{ - if ((fin->fin_flx & FI_COALESCE) != 0) - return 1; - - /* - * If the mbuf pointers indicate that there is no mbuf to work with, - * return but do not indicate success or failure. - */ - if (fin->fin_m == NULL || fin->fin_mp == NULL) - return 0; - -#if !defined(__sgi) && defined(_KERNEL) - if (fr_pullup(fin->fin_m, fin, fin->fin_plen) == NULL) { -# ifdef MENTAT - FREE_MB_T(*fin->fin_mp); -# endif - fin->fin_m = NULL; - *fin->fin_mp = NULL; - return -1; - } -#endif - return 1; -} - - -/* ------------------------------------------------------------------------ */ /* Function: fr_matchtag */ /* Returns: 0 == mismatch, 1 == match. */ /* Parameters: tag1(I) - pointer to first tag to compare */ @@ -5397,84 +5749,41 @@ ipftag_t *tag1, *tag2; /* ------------------------------------------------------------------------ */ -/* Function: fr_pullup */ -/* Returns: NULL == pullup failed, else pointer to protocol header */ -/* Parameters: m(I) - pointer to buffer where data packet starts */ -/* fin(I) - pointer to packet information */ -/* len(I) - number of bytes to pullup */ +/* Function: fr_coalesce */ +/* Returns: 1 == success, -1 == failure, 0 == no change */ +/* Parameters: fin(I) - pointer to packet information */ /* */ -/* Attempt to move at least len bytes (from the start of the buffer) into a */ -/* single buffer for ease of access. Operating system native functions are */ -/* used to manage buffers - if necessary. If the entire packet ends up in */ -/* a single buffer, set the FI_COALESCE flag even though fr_coalesce() has */ -/* not been called. Both fin_ip and fin_dp are updated before exiting _IF_ */ -/* and ONLY if the pullup succeeds. */ -/* ------------------------------------------------------------------------ */ -#if defined(_KERNEL) && !defined(__sgi) -void *fr_pullup(min, fin, len) -mb_t *min; +/* Attempt to get all of the packet data into a single, contiguous buffer. */ +/* If this call returns a failure then the buffers have also been freed. */ +/* ------------------------------------------------------------------------ */ +int fr_coalesce(fin) fr_info_t *fin; -int len; { -# ifdef MENTAT - qif_t *qf = fin->fin_qif; -# endif - int out = fin->fin_out, dpoff, ipoff; - mb_t *m = min; - char *ip; - - if (m == NULL) - return NULL; - if ((fin->fin_flx & FI_COALESCE) != 0) - return MTOD(m, void *); + return 1; - ipoff = (char *)fin->fin_ip - MTOD(m, char *); - if (fin->fin_dp != NULL) - dpoff = (char *)fin->fin_dp - (char *)fin->fin_ip; - else - dpoff = 0; + /* + * If the mbuf pointers indicate that there is no mbuf to work with, + * return but do not indicate success or failure. + */ + if (fin->fin_m == NULL || fin->fin_mp == NULL) + return 0; - if (M_LEN(m) < len) { +#if defined(_KERNEL) + if (fr_pullup(fin->fin_m, fin, fin->fin_plen) == NULL) { + ATOMIC_INCL(fr_badcoalesces[fin->fin_out]); # ifdef MENTAT - int inc = 0; - - if (ipoff > 0) { - if ((ipoff & 3) != 0) { - inc = 4 - (ipoff & 3); - if (m->b_rptr - inc >= m->b_datap->db_base) - m->b_rptr -= inc; - else - inc = 0; - } - } - if (!pullupmsg(m, len + ipoff + inc)) { - ATOMIC_INCL(frstats[out].fr_pull[1]); - return NULL; - } - m->b_rptr += inc; - ATOMIC_INCL(frstats[out].fr_pull[0]); - qf->qf_data = MTOD(m, char *) + ipoff; -# else - m = m_pullup(m, len); - *fin->fin_mp = m; - if (m == NULL) { - ATOMIC_INCL(frstats[out].fr_pull[1]); - return NULL; - } - ATOMIC_INCL(frstats[out].fr_pull[0]); -# endif /* MENTAT */ + FREE_MB_T(*fin->fin_mp); +# endif + *fin->fin_mp = NULL; + fin->fin_m = NULL; + return -1; } - ip = MTOD(m, char *) + ipoff; - fin->fin_ip = (ip_t *)ip; - if (fin->fin_dp != NULL) - fin->fin_dp = (char *)fin->fin_ip + dpoff; - - if (len == fin->fin_plen) - fin->fin_flx |= FI_COALESCE; - return ip; +#else + fin = fin; /* LINT */ +#endif + return 1; } -#endif /* _KERNEL && !__sgi */ /* @@ -5502,10 +5811,12 @@ ipftuneable_t ipf_tuneables[] = { sizeof(fr_update_ipid), 0 }, { { &fr_chksrc }, "fr_chksrc", 0, 1, sizeof(fr_chksrc), 0 }, + { { &fr_minttl }, "fr_minttl", 0, 1, + sizeof(fr_minttl), 0 }, + { { &fr_icmpminfragmtu }, "fr_icmpminfragmtu", 0, 1, + sizeof(fr_icmpminfragmtu), 0 }, { { &fr_pass }, "fr_pass", 0, 0xffffffff, sizeof(fr_pass), 0 }, - { { &fr_unreach }, "fr_unreach", 0, 0xff, - sizeof(fr_unreach), 0 }, /* state */ { { &fr_tcpidletimeout }, "fr_tcpidletimeout", 1, 0x7fffffff, sizeof(fr_tcpidletimeout), IPFT_WRDISABLED }, @@ -5527,8 +5838,10 @@ ipftuneable_t ipf_tuneables[] = { sizeof(fr_icmptimeout), IPFT_WRDISABLED }, { { &fr_icmpacktimeout }, "fr_icmpacktimeout", 1, 0x7fffffff, sizeof(fr_icmpacktimeout), IPFT_WRDISABLED }, + { { &fr_iptimeout }, "fr_iptimeout", 1, 0x7fffffff, + sizeof(fr_iptimeout), IPFT_WRDISABLED }, { { &fr_statemax }, "fr_statemax", 1, 0x7fffffff, - sizeof(fr_statemax), IPFT_WRDISABLED }, + sizeof(fr_statemax), 0 }, { { &fr_statesize }, "fr_statesize", 1, 0x7fffffff, sizeof(fr_statesize), IPFT_WRDISABLED }, { { &fr_state_lock }, "fr_state_lock", 0, 1, @@ -5544,6 +5857,8 @@ ipftuneable_t ipf_tuneables[] = { sizeof(fr_nat_lock), IPFT_RDONLY }, { { &ipf_nattable_sz }, "ipf_nattable_sz", 1, 0x7fffffff, sizeof(ipf_nattable_sz), IPFT_WRDISABLED }, + { { &ipf_nattable_max }, "ipf_nattable_max", 1, 0x7fffffff, + sizeof(ipf_nattable_max), 0 }, { { &ipf_natrules_sz }, "ipf_natrules_sz", 1, 0x7fffffff, sizeof(ipf_natrules_sz), IPFT_WRDISABLED }, { { &ipf_rdrrules_sz }, "ipf_rdrrules_sz", 1, 0x7fffffff, @@ -5558,6 +5873,8 @@ ipftuneable_t ipf_tuneables[] = { sizeof(nat_logging), 0 }, { { &fr_defnatage }, "fr_defnatage", 1, 0x7fffffff, sizeof(fr_defnatage), IPFT_WRDISABLED }, + { { &fr_defnatipage }, "fr_defnatipage", 1, 0x7fffffff, + sizeof(fr_defnatipage), IPFT_WRDISABLED }, { { &fr_defnaticmpage }, "fr_defnaticmpage", 1, 0x7fffffff, sizeof(fr_defnaticmpage), IPFT_WRDISABLED }, /* frag */ @@ -5575,10 +5892,144 @@ ipftuneable_t ipf_tuneables[] = { sizeof(ipl_logmax), IPFT_WRDISABLED }, { { &ipl_logall }, "ipl_logall", 0, 1, sizeof(ipl_logall), 0 }, + { { &ipl_logsize }, "ipl_logsize", 0, 0x80000, + sizeof(ipl_logsize), 0 }, #endif { { NULL }, NULL, 0, 0 } }; +static ipftuneable_t *ipf_tunelist = NULL; + + +/* ------------------------------------------------------------------------ */ +/* Function: fr_findtunebycookie */ +/* Returns: NULL = search failed, else pointer to tune struct */ +/* Parameters: cookie(I) - cookie value to search for amongst tuneables */ +/* next(O) - pointer to place to store the cookie for the */ +/* "next" tuneable, if it is desired. */ +/* */ +/* This function is used to walk through all of the existing tunables with */ +/* successive calls. It searches the known tunables for the one which has */ +/* a matching value for "cookie" - ie its address. When returning a match, */ +/* the next one to be found may be returned inside next. */ +/* ------------------------------------------------------------------------ */ +static ipftuneable_t *fr_findtunebycookie(cookie, next) +void *cookie, **next; +{ + ipftuneable_t *ta, **tap; + + for (ta = ipf_tuneables; ta->ipft_name != NULL; ta++) + if (ta == cookie) { + if (next != NULL) { + /* + * If the next entry in the array has a name + * present, then return a pointer to it for + * where to go next, else return a pointer to + * the dynaminc list as a key to search there + * next. This facilitates a weak linking of + * the two "lists" together. + */ + if ((ta + 1)->ipft_name != NULL) + *next = ta + 1; + else + *next = &ipf_tunelist; + } + return ta; + } + + for (tap = &ipf_tunelist; (ta = *tap) != NULL; tap = &ta->ipft_next) + if (tap == cookie) { + if (next != NULL) + *next = &ta->ipft_next; + return ta; + } + + if (next != NULL) + *next = NULL; + return NULL; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: fr_findtunebyname */ +/* Returns: NULL = search failed, else pointer to tune struct */ +/* Parameters: name(I) - name of the tuneable entry to find. */ +/* */ +/* Search the static array of tuneables and the list of dynamic tuneables */ +/* for an entry with a matching name. If we can find one, return a pointer */ +/* to the matching structure. */ +/* ------------------------------------------------------------------------ */ +static ipftuneable_t *fr_findtunebyname(name) +const char *name; +{ + ipftuneable_t *ta; + + for (ta = ipf_tuneables; ta->ipft_name != NULL; ta++) + if (!strcmp(ta->ipft_name, name)) { + return ta; + } + + for (ta = ipf_tunelist; ta != NULL; ta = ta->ipft_next) + if (!strcmp(ta->ipft_name, name)) { + return ta; + } + + return NULL; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: fr_addipftune */ +/* Returns: int - 0 == success, else failure */ +/* Parameters: newtune - pointer to new tune struct to add to tuneables */ +/* */ +/* Appends the tune structure pointer to by "newtune" to the end of the */ +/* current list of "dynamic" tuneable parameters. Once added, the owner */ +/* of the object is not expected to ever change "ipft_next". */ +/* ------------------------------------------------------------------------ */ +int fr_addipftune(newtune) +ipftuneable_t *newtune; +{ + ipftuneable_t *ta, **tap; + + ta = fr_findtunebyname(newtune->ipft_name); + if (ta != NULL) + return EEXIST; + + for (tap = &ipf_tunelist; *tap != NULL; tap = &(*tap)->ipft_next) + ; + + newtune->ipft_next = NULL; + *tap = newtune; + return 0; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: fr_delipftune */ +/* Returns: int - 0 == success, else failure */ +/* Parameters: oldtune - pointer to tune struct to remove from the list of */ +/* current dynamic tuneables */ +/* */ +/* Search for the tune structure, by pointer, in the list of those that are */ +/* dynamically added at run time. If found, adjust the list so that this */ +/* structure is no longer part of it. */ +/* ------------------------------------------------------------------------ */ +int fr_delipftune(oldtune) +ipftuneable_t *oldtune; +{ + ipftuneable_t *ta, **tap; + + for (tap = &ipf_tunelist; (ta = *tap) != NULL; tap = &ta->ipft_next) + if (ta == oldtune) { + *tap = oldtune->ipft_next; + oldtune->ipft_next = NULL; + return 0; + } + + return ESRCH; +} + /* ------------------------------------------------------------------------ */ /* Function: fr_ipftune */ @@ -5594,16 +6045,10 @@ ipftuneable_t ipf_tuneables[] = { /* each responsible for handling their own values being too big. */ /* ------------------------------------------------------------------------ */ int fr_ipftune(cmd, data) -#if defined(__NetBSD__) || defined(__OpenBSD__) || \ - (_BSDI_VERSION >= 199701) || (__FreeBSD_version >= 300003) -u_long cmd; -#else -int cmd; -#endif -char *data; +ioctlcmd_t cmd; +void *data; { ipftuneable_t *ta; - char namebuf[80]; ipftune_t tu; void *cookie; int error; @@ -5613,9 +6058,8 @@ char *data; return error; tu.ipft_name[sizeof(tu.ipft_name) - 1] = '\0'; - ta = ipf_tuneables; cookie = tu.ipft_cookie; - namebuf[sizeof(namebuf) - 1] = '\0'; + ta = NULL; switch (cmd) { @@ -5630,16 +6074,11 @@ char *data; * at the front of the list. */ if (cookie != NULL) { - for (; ta->ipft_name != NULL; ta++) - if (ta == cookie) { - ta++; - break; - } - if (ta->ipft_name == NULL) - ta = NULL; + ta = fr_findtunebycookie(cookie, &tu.ipft_cookie); + } else { + ta = ipf_tuneables; + tu.ipft_cookie = ta + 1; } - cookie = ta; - tu.ipft_cookie = cookie; if (ta != NULL) { /* * Entry found, but does the data pointed to by that @@ -5667,8 +6106,7 @@ char *data; strlen(ta->ipft_name) + 1)); } error = fr_outobj(data, &tu, IPFOBJ_TUNEABLE); - return error; - /*NOTREACHED*/ + break; case SIOCIPFGET : case SIOCIPFSET : @@ -5676,28 +6114,23 @@ char *data; * Search by name or by cookie value for a particular entry * in the tuning paramter table. */ + error = ESRCH; if (cookie != NULL) { - for (; ta->ipft_name != NULL; ta++) - if (ta == cookie) - break; + ta = fr_findtunebycookie(cookie, NULL); + if (ta != NULL) + error = 0; } else if (tu.ipft_name[0] != '\0') { - for (; ta->ipft_name != NULL; ta++) - if (!strncmp(ta->ipft_name, tu.ipft_name, - MIN(sizeof(tu.ipft_name), - strlen(ta->ipft_name) + 1))) - break; - } else - return ESRCH; - if (ta == NULL) - return ESRCH; + ta = fr_findtunebyname(tu.ipft_name); + if (ta != NULL) + error = 0; + } + if (error != 0) + break; - switch (cmd) - { - case SIOCIPFGET : + if (cmd == (ioctlcmd_t)SIOCIPFGET) { /* * Fetch the tuning parameters for a particular value */ - tu.ipft_cookie = ta; tu.ipft_vlong = 0; if (ta->ipft_sz == sizeof(u_long)) tu.ipft_vlong = *ta->ipft_plong; @@ -5707,29 +6140,32 @@ char *data; tu.ipft_vshort = *ta->ipft_pshort; else if (ta->ipft_sz == sizeof(u_char)) tu.ipft_vchar = *ta->ipft_pchar; + tu.ipft_cookie = ta; tu.ipft_sz = ta->ipft_sz; tu.ipft_min = ta->ipft_min; tu.ipft_max = ta->ipft_max; tu.ipft_flags = ta->ipft_flags; error = fr_outobj(data, &tu, IPFOBJ_TUNEABLE); - return error; - /*NOTREACHED*/ - case SIOCIPFSET : + + } else if (cmd == (ioctlcmd_t)SIOCIPFSET) { /* * Set an internal parameter. The hard part here is * getting the new value safely and correctly out of * the kernel (given we only know its size, not type.) */ - { u_long in; if (((ta->ipft_flags & IPFT_WRDISABLED) != 0) && - (fr_running > 0)) - return EBUSY; + (fr_running > 0)) { + error = EBUSY; + break; + } in = tu.ipft_vlong; - if (in < ta->ipft_min || in > ta->ipft_max) - return EINVAL; + if (in < ta->ipft_min || in > ta->ipft_max) { + error = EINVAL; + break; + } if (ta->ipft_sz == sizeof(u_long)) { tu.ipft_vlong = *ta->ipft_plong; @@ -5745,13 +6181,217 @@ char *data; *ta->ipft_pchar = (u_char)(in & 0xff); } error = fr_outobj(data, &tu, IPFOBJ_TUNEABLE); - return error; - } - /*NOTREACHED*/ } + break; + default : + error = EINVAL; break; } - return EINVAL; + return error; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: fr_initialise */ +/* Returns: int - 0 == success, < 0 == failure */ +/* Parameters: None. */ +/* */ +/* Call of the initialise functions for all the various subsystems inside */ +/* of IPFilter. If any of them should fail, return immeadiately a failure */ +/* BUT do not try to recover from the error here. */ +/* ------------------------------------------------------------------------ */ +int fr_initialise() +{ + int i; + +#ifdef IPFILTER_LOG + i = fr_loginit(); + if (i < 0) + return -10 + i; +#endif + i = fr_natinit(); + if (i < 0) + return -20 + i; + + i = fr_stateinit(); + if (i < 0) + return -30 + i; + + i = fr_authinit(); + if (i < 0) + return -40 + i; + + i = fr_fraginit(); + if (i < 0) + return -50 + i; + + i = appr_init(); + if (i < 0) + return -60 + i; + +#ifdef IPFILTER_SYNC + i = ipfsync_init(); + if (i < 0) + return -70 + i; +#endif +#ifdef IPFILTER_SCAN + i = ipsc_init(); + if (i < 0) + return -80 + i; +#endif +#ifdef IPFILTER_LOOKUP + i = ip_lookup_init(); + if (i < 0) + return -90 + i; +#endif +#ifdef IPFILTER_COMPILED + ipfrule_add(); +#endif + return 0; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: fr_deinitialise */ +/* Returns: None. */ +/* Parameters: None. */ +/* */ +/* Call all the various subsystem cleanup routines to deallocate memory or */ +/* destroy locks or whatever they've done that they need to now undo. */ +/* The order here IS important as there are some cross references of */ +/* internal data structures. */ +/* ------------------------------------------------------------------------ */ +void fr_deinitialise() +{ + fr_fragunload(); + fr_authunload(); + fr_natunload(); + fr_stateunload(); +#ifdef IPFILTER_SCAN + fr_scanunload(); +#endif + appr_unload(); + +#ifdef IPFILTER_COMPILED + ipfrule_remove(); +#endif + + (void) frflush(IPL_LOGIPF, 0, FR_INQUE|FR_OUTQUE|FR_INACTIVE); + (void) frflush(IPL_LOGIPF, 0, FR_INQUE|FR_OUTQUE); + (void) frflush(IPL_LOGCOUNT, 0, FR_INQUE|FR_OUTQUE|FR_INACTIVE); + (void) frflush(IPL_LOGCOUNT, 0, FR_INQUE|FR_OUTQUE); + +#ifdef IPFILTER_LOOKUP + ip_lookup_unload(); +#endif + +#ifdef IPFILTER_LOG + fr_logunload(); +#endif +} + + +/* ------------------------------------------------------------------------ */ +/* Function: fr_zerostats */ +/* Returns: int - 0 = success, else failure */ +/* Parameters: data(O) - pointer to pointer for copying data back to */ +/* */ +/* Copies the current statistics out to userspace and then zero's the */ +/* current ones in the kernel. The lock is only held across the bzero() as */ +/* the copyout may result in paging (ie network activity.) */ +/* ------------------------------------------------------------------------ */ +int fr_zerostats(data) +caddr_t data; +{ + friostat_t fio; + int error; + + fr_getstat(&fio); + error = copyoutptr(&fio, data, sizeof(fio)); + if (error) + return EFAULT; + + WRITE_ENTER(&ipf_mutex); + bzero((char *)frstats, sizeof(*frstats) * 2); + RWLOCK_EXIT(&ipf_mutex); + + return 0; +} + + +#ifdef _KERNEL +/* ------------------------------------------------------------------------ */ +/* Function: fr_resolvedest */ +/* Returns: Nil */ +/* Parameters: fdp(IO) - pointer to destination information to resolve */ +/* v(I) - IP protocol version to match */ +/* */ +/* Looks up an interface name in the frdest structure pointed to by fdp and */ +/* if a matching name can be found for the particular IP protocol version */ +/* then store the interface pointer in the frdest struct. If no match is */ +/* found, then set the interface pointer to be -1 as NULL is considered to */ +/* indicate there is no information at all in the structure. */ +/* ------------------------------------------------------------------------ */ +void fr_resolvedest(fdp, v) +frdest_t *fdp; +int v; +{ + void *ifp; + + ifp = NULL; + v = v; /* LINT */ + + if (*fdp->fd_ifname != '\0') { + ifp = GETIFP(fdp->fd_ifname, v); + if (ifp == NULL) + ifp = (void *)-1; + } + fdp->fd_ifp = ifp; +} +#endif /* _KERNEL */ + + +/* ------------------------------------------------------------------------ */ +/* Function: fr_resolvenic */ +/* Returns: void* - NULL = wildcard name, -1 = failed to find NIC, else */ +/* pointer to interface structure for NIC */ +/* Parameters: name(I) - complete interface name */ +/* v(I) - IP protocol version */ +/* */ +/* Look for a network interface structure that firstly has a matching name */ +/* to that passed in and that is also being used for that IP protocol */ +/* version (necessary on some platforms where there are separate listings */ +/* for both IPv4 and IPv6 on the same physical NIC. */ +/* */ +/* One might wonder why name gets terminated with a \0 byte in here. The */ +/* reason is an interface name could get into the kernel structures of ipf */ +/* in any number of ways and so long as they all use the same sized array */ +/* to put the name in, it makes sense to ensure it gets null terminated */ +/* before it is used for its intended purpose - finding its match in the */ +/* kernel's list of configured interfaces. */ +/* */ +/* NOTE: This SHOULD ONLY be used with IPFilter structures that have an */ +/* array for the name that is LIFNAMSIZ bytes (at least) in length. */ +/* ------------------------------------------------------------------------ */ +void *fr_resolvenic(name, v) +char *name; +int v; +{ + void *nic; + + if (name[0] == '\0') + return NULL; + + if ((name[1] == '\0') && ((name[0] == '-') || (name[0] == '*'))) { + return NULL; + } + + name[LIFNAMSIZ - 1] = '\0'; + + nic = GETIFP(name, v); + if (nic == NULL) + nic = (void *)-1; + return nic; } diff --git a/usr/src/common/ipf/ip_auth.c b/usr/src/uts/common/inet/ipf/ip_auth.c index 45de581cc0..b6f0844354 100644 --- a/usr/src/common/ipf/ip_auth.c +++ b/usr/src/uts/common/inet/ipf/ip_auth.c @@ -31,11 +31,13 @@ struct file; #else # include <sys/ioctl.h> #endif -#include <sys/protosw.h> +#if !defined(linux) +# include <sys/protosw.h> +#endif #include <sys/socket.h> #if defined(_KERNEL) # include <sys/systm.h> -# if !defined(__SVR4) && !defined(__svr4__) +# if !defined(__SVR4) && !defined(__svr4__) && !defined(linux) # include <sys/mbuf.h> # endif #endif @@ -65,26 +67,23 @@ struct file; #include <netinet/in.h> #include <netinet/in_systm.h> #include <netinet/ip.h> -#if !defined(_KERNEL) && !defined(__osf__) +#if !defined(_KERNEL) && !defined(__osf__) && !defined(__sgi) # define KERNEL # define _KERNEL # define NOT_KERNEL #endif -#include <netinet/ip_var.h> +#if !defined(linux) +# include <netinet/ip_var.h> +#endif #ifdef NOT_KERNEL # undef _KERNEL # undef KERNEL #endif -#ifdef __sgi -# ifdef IFF_DRVRLOCK /* IRIX6 */ -# include <sys/hashing.h> -# endif -#endif #include <netinet/tcp.h> -#if defined(__sgi) && !defined(IFF_DRVRLOCK) /* IRIX < 6 */ +#if defined(IRIX) && (IRIX < 60516) /* IRIX < 6 */ extern struct ifqueue ipintrq; /* ip packet input queue */ #else -# if !defined(__hpux) +# if !defined(__hpux) && !defined(linux) # if __FreeBSD_version >= 300000 # include <net/if_var.h> # if __FreeBSD_version >= 500042 @@ -98,17 +97,11 @@ extern struct ifqueue ipintrq; /* ip packet input queue */ #endif #include <netinet/udp.h> #include <netinet/ip_icmp.h> -#include <netinet/tcpip.h> -#if SOLARIS2 >= 10 -#include "ip_compat.h" -#include "ip_fil.h" -#include "ip_auth.h" -#else #include "netinet/ip_compat.h" +#include <netinet/tcpip.h> #include "netinet/ip_fil.h" #include "netinet/ip_auth.h" -#endif -#if !defined(MENTAT) +#if !defined(MENTAT) && !defined(linux) # include <net/netisr.h> # ifdef __FreeBSD__ # include <machine/cpufunc.h> @@ -121,19 +114,19 @@ extern struct ifqueue ipintrq; /* ip packet input queue */ # include <sys/systm.h> # endif #endif +/* END OF INCLUDES */ #if !defined(lint) -static const char rcsid[] = "@(#)$Id: ip_auth.c,v 2.56 2003/06/28 17:01:55 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id: ip_auth.c,v 2.73.2.5 2005/06/12 07:18:14 darrenr Exp $"; #endif -#ifdef USE_MUTEXES -extern ipfrwlock_t ipf_auth; -extern ipfmutex_t ipf_authmx; -# if SOLARIS +#if SOLARIS extern kcondvar_t ipfauthwait; -# endif /* SOLARIS */ -#endif /* USE_MUTEXES */ +#endif /* SOLARIS */ +#if defined(linux) && defined(_KERNEL) +wait_queue_head_t fr_authnext_linux; +#endif int fr_authsize = FR_NUMAUTH; int fr_authused = 0; @@ -161,13 +154,16 @@ int fr_authinit() if (fr_authpkts != NULL) bzero((char *)fr_authpkts, fr_authsize * sizeof(*fr_authpkts)); else - return -1; + return -2; MUTEX_INIT(&ipf_authmx, "ipf auth log mutex"); RWLOCK_INIT(&ipf_auth, "ipf IP User-Auth rwlock"); #if SOLARIS && defined(_KERNEL) cv_init(&ipfauthwait, "ipf auth condvar", CV_DRIVER, NULL); #endif +#if defined(linux) && defined(_KERNEL) + init_waitqueue_head(&fr_authnext_linux); +#endif fr_auth_init = 1; @@ -264,7 +260,7 @@ u_32_t *passp; RWLOCK_EXIT(&ipf_auth); if (passp != NULL) *passp = pass; - ATOMIC_INCL(fr_authstats.fas_hits); + ATOMIC_INC64(fr_authstats.fas_hits); return fr; } i++; @@ -273,7 +269,7 @@ u_32_t *passp; } fr_authstats.fas_miss++; RWLOCK_EXIT(&ipf_auth); - ATOMIC_INCL(fr_authstats.fas_miss); + ATOMIC_INC64(fr_authstats.fas_miss); return NULL; } @@ -288,7 +284,7 @@ mb_t *m; fr_info_t *fin; { #if defined(_KERNEL) && defined(MENTAT) - qif_t *qif = fin->fin_qif; + qpktinfo_t *qpi = fin->fin_qpi; #endif frauth_t *fra; #if !defined(sparc) && !defined(m68k) @@ -343,9 +339,9 @@ fr_info_t *fin; } #endif #if SOLARIS && defined(_KERNEL) - m->b_rptr -= qif->qf_off; + m->b_rptr -= qpi->qpi_off; fr_authpkts[i] = *(mblk_t **)fin->fin_mp; - fra->fra_q = qif->qf_q; + fra->fra_q = qpi->qpi_q; /* The queue can disappear! */ cv_signal(&ipfauthwait); #else # if defined(BSD) && !defined(sparc) && (BSD >= 199306) @@ -355,7 +351,7 @@ fr_info_t *fin; } # endif fr_authpkts[i] = m; - WAKEUP(&fr_authnext); + WAKEUP(&fr_authnext,0); #endif return 1; } @@ -363,20 +359,14 @@ fr_info_t *fin; int fr_auth_ioctl(data, cmd, mode) caddr_t data; -#if defined(__NetBSD__) || defined(__OpenBSD__) || \ - (_BSDI_VERSION >= 199701) || (__FreeBSD_version >= 300003) -u_long cmd; -#else -int cmd; -#endif +ioctlcmd_t cmd; int mode; { mb_t *m; -#if defined(_KERNEL) && !defined(MENTAT) +#if defined(_KERNEL) && !defined(MENTAT) && !defined(linux) && \ + (!defined(__FreeBSD_version) || (__FreeBSD_version < 501000)) struct ifqueue *ifq; -# ifdef USE_SPL - int s; -# endif /* USE_SPL */ + SPL_INT(s); #endif frauth_t auth, *au = &auth, *fra; int i, error = 0, len; @@ -389,7 +379,7 @@ int mode; error = EPERM; break; } - error = fr_lock(data, &fr_auth_lock); + fr_lock(data, &fr_auth_lock); break; case SIOCATHST: @@ -513,14 +503,17 @@ fr_authioctlloop: # ifdef MENTAT error = !putq(fra->fra_q, m); # else /* MENTAT */ -# if (_BSDI_VERSION >= 199802) || defined(__OpenBSD__) || \ - (defined(__sgi) && (IRIX >= 605) || \ - (defined(__FreeBSD__) && (__FreeBSD_version >= 500043))) +# if defined(linux) || defined(AIX) +# else +# if (_BSDI_VERSION >= 199802) || defined(__OpenBSD__) || \ + (defined(__sgi) && (IRIX >= 60500) || defined(AIX) || \ + (defined(__FreeBSD__) && (__FreeBSD_version >= 470102))) error = ip_output(m, NULL, NULL, IP_FORWARDING, NULL, NULL); -# else +# else error = ip_output(m, NULL, NULL, IP_FORWARDING, NULL); -# endif +# endif +# endif /* Linux */ # endif /* MENTAT */ if (error != 0) fr_authstats.fas_sendfail++; @@ -530,17 +523,28 @@ fr_authioctlloop: # ifdef MENTAT error = !putq(fra->fra_q, m); # else /* MENTAT */ +# if defined(linux) || defined(AIX) +# else +# if (__FreeBSD_version >= 501000) + netisr_dispatch(NETISR_IP, m); +# else +# if (IRIX >= 60516) + ifq = &((struct ifnet *)fra->fra_info.fin_ifp)->if_snd; +# else ifq = &ipintrq; +# endif if (IF_QFULL(ifq)) { IF_DROP(ifq); - m_freem(m); + FREE_MB_T(m); error = ENOBUFS; } else { IF_ENQUEUE(ifq, m); -# if IRIX < 605 +# if IRIX < 60500 schednetisr(NETISR_IP); -# endif +# endif } +# endif +# endif /* Linux */ # endif /* MENTAT */ if (error != 0) fr_authstats.fas_quefail++; @@ -555,7 +559,7 @@ fr_authioctlloop: /* * If we experience an error which will result in the packet * not being processed, make sure we advance to the next one. - */ + */ if (error == ENOBUFS) { fr_authused--; fra->fra_index = -1; @@ -655,9 +659,7 @@ void fr_authexpire() register frauthent_t *fae, **faep; register frentry_t *fr, **frp; mb_t *m; -# if !defined(MENAT) && defined(_KERNEL) && defined(USE_SPL) - int s; -# endif + SPL_INT(s); if (fr_auth_lock) return; @@ -701,19 +703,12 @@ void fr_authexpire() } int fr_preauthcmd(cmd, fr, frptr) -#if defined(__NetBSD__) || defined(__OpenBSD__) || \ - (_BSDI_VERSION >= 199701) || (__FreeBSD_version >= 300000) -u_long cmd; -#else -int cmd; -#endif +ioctlcmd_t cmd; frentry_t *fr, **frptr; { frauthent_t *fae, **faep; int error = 0; -# if !defined(MENAT) && defined(_KERNEL) && defined(USE_SPL) - int s; -#endif + SPL_INT(s); if ((cmd != SIOCADAFR) && (cmd != SIOCRMAFR)) return EIO; @@ -725,7 +720,7 @@ frentry_t *fr, **frptr; faep = &fae->fae_next; } - if (cmd == SIOCRMAFR) { + if (cmd == (ioctlcmd_t)SIOCRMAFR) { if (fr == NULL || frptr == NULL) error = EINVAL; else if (fae == NULL) @@ -766,9 +761,9 @@ frentry_t *fr, **frptr; /* - * Flush held packets. - * Must already be properly SPL'ed and Locked on &ipf_auth. - * + * Flush held packets. + * Must already be properly SPL'ed and Locked on &ipf_auth. + * */ int fr_authflush() { diff --git a/usr/src/common/ipf/ip_fil_solaris.c b/usr/src/uts/common/inet/ipf/ip_fil_solaris.c index a4dc74c3b1..287cca861e 100644 --- a/usr/src/common/ipf/ip_fil_solaris.c +++ b/usr/src/uts/common/inet/ipf/ip_fil_solaris.c @@ -1,16 +1,17 @@ /* - * Copyright (C) 1999-2001, 2003 by Darren Reed. + * Copyright (C) 1993-2001, 2003 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #pragma ident "%Z%%M% %I% %E% SMI" #if !defined(lint) -static const char rcsid[] = "@(#)$Id: ip_fil_solaris.c,v 2.36 2003/07/01 18:30:20 darrenr Exp $"; +static const char sccsid[] = "%W% %G% (C) 1993-2000 Darren Reed"; +static const char rcsid[] = "@(#)$Id: ip_fil_solaris.c,v 2.62.2.19 2005/07/13 21:40:46 darrenr Exp $"; #endif #include <sys/types.h> @@ -21,6 +22,7 @@ static const char rcsid[] = "@(#)$Id: ip_fil_solaris.c,v 2.36 2003/07/01 18:30:2 #include <sys/ioctl.h> #include <sys/filio.h> #include <sys/systm.h> +#include <sys/strsubr.h> #include <sys/cred.h> #include <sys/ddi.h> #include <sys/sunddi.h> @@ -42,56 +44,54 @@ static const char rcsid[] = "@(#)$Id: ip_fil_solaris.c,v 2.36 2003/07/01 18:30:2 #include <netinet/udp.h> #include <netinet/tcpip.h> #include <netinet/ip_icmp.h> -#include "ip_compat.h" +#include "netinet/ip_compat.h" #ifdef USE_INET6 # include <netinet/icmp6.h> #endif -#include "ip_fil.h" -#include "ip_nat.h" -#include "ip_frag.h" -#include "ip_state.h" -#include "ip_auth.h" -#include "ip_proxy.h" +#include "netinet/ip_fil.h" +#include "netinet/ip_nat.h" +#include "netinet/ip_frag.h" +#include "netinet/ip_state.h" +#include "netinet/ip_auth.h" +#include "netinet/ip_proxy.h" #ifdef IPFILTER_LOOKUP -#include "ip_lookup.h" -#endif -#ifdef IPFILTER_COMPILED -#include "ip_rules.h" +# include "netinet/ip_lookup.h" #endif #include <inet/ip_ire.h> #include <sys/md5.h> -extern int fr_flags, fr_active; +extern int fr_flags, fr_active; #if SOLARIS2 >= 7 -extern timeout_id_t fr_timer_id; +timeout_id_t fr_timer_id; #else -extern int fr_timer_id; +int fr_timer_id; #endif -static int frzerostats __P((caddr_t)); -static int fr_send_ip __P((fr_info_t *fin, mblk_t *m)); +static int fr_send_ip __P((fr_info_t *fin, mblk_t *m, mblk_t **mp)); ipfmutex_t ipl_mutex, ipf_authmx, ipf_rw, ipf_stinsert; ipfmutex_t ipf_nat_new, ipf_natio, ipf_timeoutlock; -ipfrwlock_t ipf_mutex, ipf_global, ipf_ipidfrag; +ipfrwlock_t ipf_mutex, ipf_global, ipf_ipidfrag, ipf_frcache; ipfrwlock_t ipf_frag, ipf_state, ipf_nat, ipf_natfrag, ipf_auth; kcondvar_t iplwait, ipfauthwait; #if SOLARIS2 < 10 #if SOLARIS2 >= 7 -u_int *ip_ttl_ptr; -u_int *ip_mtudisc; +timeout_id_t fr_timer_id; +u_int *ip_ttl_ptr = NULL; +u_int *ip_mtudisc = NULL; # if SOLARIS2 >= 8 -int *ip_forwarding; -u_int *ip6_forwarding; +int *ip_forwarding = NULL; +u_int *ip6_forwarding = NULL; # else -u_int *ip_forwarding; +u_int *ip_forwarding = NULL; # endif #else -u_long *ip_ttl_ptr; -u_long *ip_mtudisc; -u_long *ip_forwarding; +int fr_timer_id; +u_long *ip_ttl_ptr = NULL; +u_long *ip_mtudisc = NULL; +u_long *ip_forwarding = NULL; #endif #endif int ipf_locks_done = 0; @@ -113,14 +113,14 @@ int ipldetach() ASSERT(rw_read_locked(&ipf_global.ipf_lk) == 0); - if (fr_refcnt) - return EBUSY; #if SOLARIS2 < 10 if (fr_control_forwarding & 2) { - *ip_forwarding = 0; + if (ip_forwarding != NULL) + *ip_forwarding = 0; #if SOLARIS2 >= 8 - *ip6_forwarding = 0; + if (ip6_forwarding != NULL) + *ip6_forwarding = 0; #endif } #endif @@ -129,27 +129,11 @@ int ipldetach() cmn_err(CE_CONT, "ipldetach()\n"); #endif - fr_fragunload(); - fr_authunload(); - fr_stateunload(); - fr_natunload(); - appr_unload(); - -#ifdef IPFILTER_COMPILED - ipfrule_remove(); -#endif + fr_deinitialise(); (void) frflush(IPL_LOGIPF, 0, FR_INQUE|FR_OUTQUE|FR_INACTIVE); (void) frflush(IPL_LOGIPF, 0, FR_INQUE|FR_OUTQUE); -#ifdef IPFILTER_LOOKUP - ip_lookup_unload(); -#endif - -#ifdef IPFILTER_LOG - fr_logunload(); -#endif - if (ipf_locks_done == 1) { MUTEX_DESTROY(&ipf_timeoutlock); MUTEX_DESTROY(&ipf_rw); @@ -178,30 +162,8 @@ int iplattach __P((void)) RWLOCK_INIT(&ipf_ipidfrag, "ipf IP NAT-Frag rwlock"); ipf_locks_done = 1; -#ifdef IPFILTER_LOG - if (fr_loginit() == -1) - return -1; -#endif - if (fr_natinit() == -1) - return -1; - if (fr_stateinit() == -1) - return -1; - if (fr_authinit() == -1) - return -1; - if (fr_fraginit() == -1) - return -1; - if (appr_init() == -1) - return -1; -#ifdef IPFILTER_SYNC - ipfsync_init(); -#endif -#ifdef IPFILTER_SCAN - isc_init(); -#endif -#ifdef IPFILTER_LOOKUP - if (ip_lookup_init() == -1) + if (fr_initialise() < 0) return -1; -#endif /* Do not use private interface ip_params_arr[] in Solaris 10 */ #if SOLARIS2 < 10 @@ -215,6 +177,7 @@ int iplattach __P((void)) * of the array. */ +#if SOLARIS2 <= 8 for (i = 0; ; i++) { if (!strcmp(ip_param_arr[i].ip_param_name, "ip_def_ttl")) { ip_ttl_ptr = &ip_param_arr[i].ip_param_value; @@ -241,11 +204,14 @@ int iplattach __P((void)) ip_forwarding != NULL) break; } +#endif if (fr_control_forwarding & 1) { - *ip_forwarding = 1; + if (ip_forwarding != NULL) + *ip_forwarding = 1; #if SOLARIS2 >= 8 - *ip6_forwarding = 1; + if (ip6_forwarding != NULL) + *ip6_forwarding = 1; #endif } @@ -255,23 +221,6 @@ int iplattach __P((void)) } -static int frzerostats(data) -caddr_t data; -{ - friostat_t fio; - int error; - - fr_getstat(&fio); - error = copyoutptr((caddr_t)&fio, data, sizeof(fio)); - if (error) - return error; - - bzero((char *)frstats, sizeof(*frstats) * 2); - - return 0; -} - - /* * Filter ioctl interface. */ @@ -305,7 +254,8 @@ int *rp; if (unit != IPL_LOGIPF) return EIO; if (cmd != SIOCIPFGETNEXT && cmd != SIOCIPFGET && - cmd != SIOCIPFSET && cmd != SIOCFRENB && cmd != SIOCGETFS) + cmd != SIOCIPFSET && cmd != SIOCFRENB && + cmd != SIOCGETFS && cmd != SIOCGETFF) return EIO; } @@ -357,7 +307,7 @@ int *rp; /* FALLTHRU */ case SIOCIPFGETNEXT : case SIOCIPFGET : - error = fr_ipftune(cmd, (char *)data); + error = fr_ipftune(cmd, (void *)data); break; case SIOCSETFF : if (!(mode & FWRITE)) @@ -420,7 +370,7 @@ int *rp; if (!(mode & FWRITE)) error = EPERM; else - error = frzerostats((caddr_t)data); + error = fr_zerostats((caddr_t)data); break; case SIOCIPFFL : if (!(mode & FWRITE)) @@ -502,8 +452,7 @@ int *rp; #endif break; default : - cmn_err(CE_NOTE, "Unknown: cmd 0x%x data %p", - cmd, (void *)data); + cmn_err(CE_NOTE, "Unknown: cmd 0x%x data %p", cmd, (void *)data); error = EINVAL; break; } @@ -511,41 +460,12 @@ int *rp; return error; } -#ifndef IRE_ILL_CN -ill_t *get_unit(name, v) -char *name; -int v; -{ - size_t len = strlen(name) + 1; /* includes \0 */ - ill_t *il; -#if SOLARIS2 >= 10 - ill_walk_context_t ctx; -#endif - int sap; - if (v == 4) - sap = 0x0800; - else if (v == 6) - sap = 0x86dd; - else - return NULL; -#if SOLARIS2 >= 10 - for (il = ILL_START_WALK_ALL(&ctx); il; il = ill_next(&ctx, il)) -#else - for (il = ill_g_head; il; il = il->ill_next) -#endif - if ((len == il->ill_name_length) && (il->ill_sap == sap) && - !strncmp(il->ill_name, name, len)) - return il; - return NULL; -} -#else -s_ill_t *get_unit(name, v) +void *get_unit(name, v) char *name; int v; { - s_ill_t *il; - + qif_t *qf; int sap; if (v == 4) @@ -554,16 +474,11 @@ int v; sap = 0x86dd; else return NULL; - - mutex_enter(&s_ill_g_head_lock); - for (il = s_ill_g_head; il; il = il->ill_next) - if ((il->ill_sap == sap) && - !strncmp(il->ill_name, name, LIFNAMSIZ)) - break; - mutex_exit(&s_ill_g_head_lock); - return il; + rw_enter(&pfil_rw, RW_READER); + qf = qif_iflookup(name, sap); + rw_exit(&pfil_rw); + return qf; } -#endif /* IRE_ILL_CN */ /* @@ -630,7 +545,6 @@ cred_t *cp; #endif /* IPFILTER_LOG */ -#ifdef IPFILTER_SYNC /* * iplread/ipllog * both of these must operate with at least splnet() lest they be @@ -645,11 +559,15 @@ cred_t *cp; #ifdef IPFDEBUG cmn_err(CE_CONT, "iplwrite(%x,%x,%x)\n", dev, uio, cp); #endif - if (getminor(dev) != IPL_LOGSYNC) - return ENXIO; - return ipfsync_write(uio); -} +#ifdef IPFILTER_SYNC + if (getminor(dev) == IPL_LOGSYNC) + return ipfsync_write(uio); #endif /* IPFILTER_SYNC */ + dev = dev; /* LINT */ + uio = uio; /* LINT */ + cp = cp; /* LINT */ + return ENXIO; +} /* @@ -690,7 +608,8 @@ fr_info_t *fin; m->b_rptr += 64; MTYPE(m) = M_DATA; m->b_wptr = m->b_rptr + hlen; - bzero((char *)m->b_rptr, hlen); + ip = (ip_t *)m->b_rptr; + bzero((char *)ip, hlen); tcp2 = (struct tcphdr *)(m->b_rptr + hlen - sizeof(*tcp2)); tcp2->th_dport = tcp->th_sport; tcp2->th_sport = tcp->th_dport; @@ -705,10 +624,7 @@ fr_info_t *fin; } tcp2->th_off = sizeof(struct tcphdr) >> 2; - /* - * This is to get around a bug in the Solaris 2.4/2.5 TCP checksum - * computation that is done by their put routine. - */ + ip->ip_v = fin->fin_v; #ifdef USE_INET6 if (fin->fin_v == 6) { ip6 = (ip6_t *)m->b_rptr; @@ -721,7 +637,6 @@ fr_info_t *fin; } else #endif { - ip = (ip_t *)m->b_rptr; ip->ip_src.s_addr = fin->fin_daddr; ip->ip_dst.s_addr = fin->fin_saddr; ip->ip_id = fr_nextipid(fin); @@ -731,10 +646,9 @@ fr_info_t *fin; ip->ip_tos = fin->fin_ip->ip_tos; tcp2->th_sum = fr_cksum(m, ip, IPPROTO_TCP, tcp2); } - return fr_send_ip(fin, m); + return fr_send_ip(fin, m, &m); } - /* * Function: fr_send_ip * Returns: 0: success @@ -754,40 +668,84 @@ fr_info_t *fin; * * All other portions of the packet must be in on-the-wire format. */ -static int fr_send_ip(fin, m) +/*ARGSUSED*/ +static int fr_send_ip(fin, m, mpp) fr_info_t *fin; -mblk_t *m; +mblk_t *m, **mpp; { - int i; + qpktinfo_t qpi, *qpip; + fr_info_t fnew; + qif_t *qif; + ip_t *ip; + int i, hlen; + + ip = (ip_t *)m->b_rptr; + bzero((char *)&fnew, sizeof(fnew)); #ifdef USE_INET6 if (fin->fin_v == 6) { ip6_t *ip6; - ip6 = (ip6_t *)m->b_rptr; + ip6 = (ip6_t *)ip; ip6->ip6_vfc = 0x60; ip6->ip6_hlim = 127; + fnew.fin_v = 6; + hlen = sizeof(*ip6); } else #endif { - ip_t *ip; - - ip = (ip_t *)m->b_rptr; - ip->ip_v = IPVERSION; - + fnew.fin_v = 4; #if SOLARIS2 >= 10 ip->ip_ttl = 255; - ip->ip_off = IP_DF; + ip->ip_off = htons(IP_DF); #else - ip->ip_ttl = (u_char)(*ip_ttl_ptr); - ip->ip_off = *ip_mtudisc ? IP_DF : 0; + if (ip_ttl_ptr != NULL) + ip->ip_ttl = (u_char)(*ip_ttl_ptr); + else + ip->ip_ttl = 63; + if (ip_mtudisc != NULL) + ip->ip_off = htons(*ip_mtudisc ? IP_DF : 0); + else + ip->ip_off = htons(IP_DF); #endif - + /* + * The dance with byte order and ip_len/ip_off is because in + * fr_fastroute, it expects them to be in host byte order but + * ipf_cksum expects them to be in network byte order. + */ + ip->ip_len = htons(ip->ip_len); ip->ip_sum = ipf_cksum((u_short *)ip, sizeof(*ip)); - + ip->ip_len = ntohs(ip->ip_len); + ip->ip_off = ntohs(ip->ip_off); + hlen = sizeof(*ip); } - i = fr_fastroute(m, &m, fin, NULL); + + qpip = fin->fin_qpi; + qpi.qpi_q = qpip->qpi_q; + qpi.qpi_off = 0; + qpi.qpi_name = qpip->qpi_name; + qif = qpip->qpi_real; + qpi.qpi_real = qif; + qpi.qpi_ill = qif->qf_ill; + qpi.qpi_hl = qif->qf_hl; + qpi.qpi_ppa = qif->qf_ppa; + qpi.qpi_num = qif->qf_num; + qpi.qpi_flags = qif->qf_flags; + qpi.qpi_max_frag = qif->qf_max_frag; + qpi.qpi_m = m; + qpi.qpi_data = ip; + fnew.fin_qpi = &qpi; + fnew.fin_ifp = fin->fin_ifp; + fnew.fin_flx = FI_NOCKSUM; + fnew.fin_m = m; + fnew.fin_ip = ip; + fnew.fin_mp = mpp; + fnew.fin_hlen = hlen; + fnew.fin_dp = (char *)ip + hlen; + (void) fr_makefrip(hlen, ip, &fnew); + + i = fr_fastroute(m, mpp, &fnew, NULL); return i; } @@ -799,31 +757,18 @@ int dst; { struct in_addr dst4; struct icmp *icmp; + qpktinfo_t *qpi; int hlen, code; - qif_t *qif; u_short sz; #ifdef USE_INET6 mblk_t *mb; #endif mblk_t *m; -#ifdef icmp_nextmtu -#ifndef IRE_ILL_CN - ill_t *il; -#else - s_ill_t *il; -#endif /* IRE_ILL_CN */ -#endif #ifdef USE_INET6 ip6_t *ip6; #endif ip_t *ip; -#ifdef icmp_nextmtu - /* lint fodder */ - il = NULL; - il = il; -#endif - if ((type < 0) || (type > ICMP_MAXTYPE)) return -1; @@ -838,7 +783,7 @@ int dst; return -1; #endif - qif = fin->fin_qif; + qpi = fin->fin_qpi; #ifdef USE_INET6 mb = fin->fin_qfm; @@ -878,16 +823,16 @@ int dst; m->b_rptr += 64; m->b_wptr = m->b_rptr + sz; bzero((char *)m->b_rptr, (size_t)sz); + ip = (ip_t *)m->b_rptr; + ip->ip_v = fin->fin_v; icmp = (struct icmp *)(m->b_rptr + hlen); icmp->icmp_type = type & 0xff; icmp->icmp_code = code & 0xff; -#ifndef IRE_ILL_CN #ifdef icmp_nextmtu - if (type == ICMP_UNREACH && ((il = qif->qf_ill) != NULL) && + if (type == ICMP_UNREACH && (qpi->qpi_max_frag != 0) && fin->fin_icode == ICMP_UNREACH_NEEDFRAG) - icmp->icmp_nextmtu = htons(il->ill_max_frag); + icmp->icmp_nextmtu = htons(qpi->qpi_max_frag); #endif -#endif /* IRE_ILL_CN */ #ifdef USE_INET6 if (fin->fin_v == 6) { @@ -895,7 +840,7 @@ int dst; int csz; if (dst == 0) { - if (fr_ifpaddr(6, FRI_NORMAL, qif->qf_ill, + if (fr_ifpaddr(6, FRI_NORMAL, qpi->qpi_real, (struct in_addr *)&dst6, NULL) == -1) { FREE_MB_T(m); return -1; @@ -917,14 +862,13 @@ int dst; } else #endif { - ip = (ip_t *)m->b_rptr; ip->ip_hl = sizeof(*ip) >> 2; ip->ip_p = IPPROTO_ICMP; ip->ip_id = fin->fin_ip->ip_id; ip->ip_tos = fin->fin_ip->ip_tos; ip->ip_len = (u_short)sz; if (dst == 0) { - if (fr_ifpaddr(4, FRI_NORMAL, qif->qf_ill, + if (fr_ifpaddr(4, FRI_NORMAL, qpi->qpi_real, &dst4, NULL) == -1) { FREE_MB_T(m); return -1; @@ -938,6 +882,7 @@ int dst; bcopy((char *)fin->fin_ip + fin->fin_hlen, (char *)&icmp->icmp_ip + sizeof(*fin->fin_ip), 8); icmp->icmp_ip.ip_len = htons(icmp->icmp_ip.ip_len); + icmp->icmp_ip.ip_off = htons(icmp->icmp_ip.ip_off); icmp->icmp_cksum = ipf_cksum((u_short *)icmp, sz - sizeof(ip_t)); } @@ -946,7 +891,7 @@ int dst; * Need to exit out of these so we don't recursively call rw_enter * from fr_qout. */ - return fr_send_ip(fin, m); + return fr_send_ip(fin, m, &m); } #ifdef IRE_ILL_CN @@ -999,30 +944,41 @@ static void rate_limit_message(int rate, const char *message, ...) * return the first IP Address associated with an interface */ /*ARGSUSED*/ -int fr_ifpaddr(v, atype, ifptr, inp, inpmask) +int fr_ifpaddr(v, atype, qifptr, inp, inpmask) int v, atype; -void *ifptr; +void *qifptr; struct in_addr *inp, *inpmask; { #ifdef USE_INET6 struct sockaddr_in6 sin6, mask6; #endif struct sockaddr_in sin, mask; + qif_t *qif; -#ifndef IRE_ILL_CN - ill_t *ill = ifptr; - ipif_t *ipif; -#else - s_ill_t *ill = ifptr; -#endif /* IRE_ILL_CN */ - - if ((ifptr == NULL) || (ifptr == (void *)-1)) +#ifdef USE_INET6 +#ifdef IRE_ILL_CN + s_ill_t *ill; +#endif +#endif + if ((qifptr == NULL) || (qifptr == (void *)-1)) return -1; + qif = qifptr; + +#ifdef USE_INET6 +#ifdef IRE_ILL_CN + ill = qif->qf_ill; +#endif +#endif + #ifdef USE_INET6 if (v == 6) { -#ifndef IRE_ILL_CN +#ifndef IRE_ILL_CN in6_addr_t *inp6; + ipif_t *ipif; + ill_t *ill; + + ill = qif->qf_ill; /* * First is always link local. @@ -1062,24 +1018,22 @@ struct in_addr *inp, *inpmask; return fr_ifpfillv6addr(atype, &sin6, &mask6, inp, inpmask); } #endif -#ifndef IRE_ILL_CN - ipif = ill->ill_ipif; - mask.sin_addr.s_addr = ipif->ipif_net_mask; - if (atype == FRI_BROADCAST) -#if SOLARIS2 < 7 - sin.sin_addr.s_addr = ipif->ipif_broadcast_addr; -#else - sin.sin_addr.s_addr = ipif->ipif_brd_addr; -#endif - else if (atype == FRI_PEERADDR) - sin.sin_addr.s_addr = ipif->ipif_pp_dst_addr; - else -#if SOLARIS2 < 7 - sin.sin_addr.s_addr = ipif->ipif_local_addr; -#else - sin.sin_addr.s_addr = ipif->ipif_lcl_addr; -#endif +#ifndef IRE_ILL_CN + + switch (atype) + { + case FRI_BROADCAST : + sin.sin_addr.s_addr = QF_V4_BROADCAST(qif); + break; + case FRI_PEERADDR : + sin.sin_addr.s_addr = QF_V4_PEERADDR(qif); + break; + default : + sin.sin_addr.s_addr = QF_V4_ADDR(qif); + break; + } + mask.sin_addr.s_addr = QF_V4_NETMASK(qif); #else if (ill->netmask.in.sin_addr.s_addr == 0 || @@ -1101,52 +1055,6 @@ struct in_addr *inp, *inpmask; } - -#ifdef IRE_ILL_CN -/* ARGSUSED */ -#endif -void fr_resolvdest(fdp, v) -frdest_t *fdp; -int v; -{ -#ifndef IRE_ILL_CN - ipif_t *ipif; - ill_t *ill; - ire_t *ire; - - ire = NULL; - - if (*fdp->fd_ifname) { - ill = get_unit(fdp->fd_ifname, v); - if (ill == NULL) - ire = (ire_t *)-1; - else if (((ipif = ill->ill_ipif) != NULL) && (v == 4)) { -#if SOLARIS2 > 5 - ire = ire_ctable_lookup(ipif->ipif_local_addr, 0, - IRE_LOCAL, NULL, NULL, - MATCH_IRE_TYPE); -#else - ire = ire_lookup_myaddr(ipif->ipif_local_addr); -#endif - if (ire == NULL) - ire = (ire_t *)-1; - } -#ifdef USE_INET6 - else if (((ipif = ill->ill_ipif) != NULL) && (v == 6)) { - ire = ire_ctable_lookup_v6(&ipif->ipif_v6lcl_addr, 0, - IRE_LOCAL, NULL, NULL, - MATCH_IRE_TYPE); - if (ire == NULL) - ire = (ire_t *)-1; - } -#endif - } - fdp->fd_ifp = (struct ifnet *)ire; -#else -#endif /*IRE_ILL_CN */ -} - - u_32_t fr_newisn(fin) fr_info_t *fin; { @@ -1193,7 +1101,7 @@ fr_info_t *fin; /* */ /* Returns the next IPv4 ID to use for this packet. */ /* ------------------------------------------------------------------------ */ -INLINE u_short fr_nextipid(fin) +u_short fr_nextipid(fin) fr_info_t *fin; { static u_short ipid = 0; @@ -1230,7 +1138,9 @@ fr_info_t *fin; #ifdef USE_INET6 +# ifndef IPFILTER_CKSUM /* ARGSUSED */ +# endif INLINE void fr_checkv6sum(fin) fr_info_t *fin; { @@ -1240,3 +1150,463 @@ fr_info_t *fin; # endif } #endif /* USE_INET6 */ + + +/* + * Function: fr_verifysrc + * Returns: int (really boolean) + * Parameters: fin - packet information + * + * Check whether the packet has a valid source address for the interface on + * which the packet arrived, implementing the "fr_chksrc" feature. + * Returns true iff the packet's source address is valid. + * Pre-Solaris 10, we call into the routing code to make the determination. + * On Solaris 10 and later, we have a valid address set from pfild to check + * against. + */ +int fr_verifysrc(fin) +fr_info_t *fin; +{ + ire_t *dir; + int result; + +#if SOLARIS2 >= 6 + dir = ire_route_lookup(fin->fin_saddr, 0xffffffff, 0, 0, NULL, + NULL, NULL, NULL, MATCH_IRE_DSTONLY| + MATCH_IRE_DEFAULT|MATCH_IRE_RECURSIVE); +#else + dir = ire_lookup(fin->fin_saddr); +#endif + + if (!dir) + return 0; + result = (ire_to_ill(dir) == fin->fin_ifp); +#if SOLARIS2 >= 8 + ire_refrele(dir); +#endif + return result; +} + + +#if (SOLARIS2 < 7) +void fr_slowtimer() +#else +/*ARGSUSED*/ +void fr_slowtimer __P((void *ptr)) +#endif +{ + + WRITE_ENTER(&ipf_global); + if (fr_running <= 0) { + if (fr_running == -1) + fr_timer_id = timeout(fr_slowtimer, NULL, + drv_usectohz(500000)); + else + fr_timer_id = NULL; + RWLOCK_EXIT(&ipf_global); + return; + } + MUTEX_DOWNGRADE(&ipf_global); + + fr_fragexpire(); + fr_timeoutstate(); + fr_natexpire(); + fr_authexpire(); + fr_ticks++; + if (fr_running == -1 || fr_running == 1) + fr_timer_id = timeout(fr_slowtimer, NULL, drv_usectohz(500000)); + else + fr_timer_id = NULL; + RWLOCK_EXIT(&ipf_global); +} + + +/* + * Function: fr_fastroute + * Returns: 0: success; + * -1: failed + * Parameters: + * mb: the message block where ip head starts + * mpp: the pointer to the pointer of the orignal + * packet message + * fin: packet information + * fdp: destination interface information + * if it is NULL, no interface information provided. + * + * This function is for fastroute/to/dup-to rules. It calls + * pfil_make_lay2_packet to search route, make lay-2 header + * ,and identify output queue for the IP packet. + * The destination address depends on the following conditions: + * 1: for fastroute rule, fdp is passed in as NULL, so the + * destination address is the IP Packet's destination address + * 2: for to/dup-to rule, if an ip address is specified after + * the interface name, this address is the as destination + * address. Otherwise IP Packet's destination address is used + */ +int fr_fastroute(mb, mpp, fin, fdp) +mblk_t *mb, **mpp; +fr_info_t *fin; +frdest_t *fdp; +{ + struct in_addr dst; +#ifndef IRE_ILL_CN + size_t hlen = 0; + ill_t *ifp; + ire_t *dir; + u_char *s; + frdest_t fd; +#ifdef USE_INET6 + ip6_t *ip6 = (ip6_t *)fin->fin_ip; +#endif +#else + void *target = NULL; + char *ifname = NULL; +#endif + queue_t *q = NULL; + mblk_t *mp = NULL; + qpktinfo_t *qpi; + frentry_t *fr; + qif_t *qif; + ip_t *ip; +#ifndef sparc + u_short __iplen, __ipoff; +#endif +#ifdef USE_INET6 + struct in6_addr dst6; +#endif +#ifndef IRE_ILL_CN + dir = NULL; +#endif + fr = fin->fin_fr; + ip = fin->fin_ip; + qpi = fin->fin_qpi; + + /* + * If this is a duplicate mblk then we want ip to point at that + * data, not the original, if and only if it is already pointing at + * the current mblk data. + */ + if (ip == (ip_t *)qpi->qpi_m->b_rptr && qpi->qpi_m != mb) + ip = (ip_t *)mb->b_rptr; + + /* + * If there is another M_PROTO, we don't want it + */ + if (*mpp != mb) { + mp = unlinkb(*mpp); + freeb(*mpp); + *mpp = mp; + } + +#ifdef IRE_ILL_CN + if (fdp != NULL) { +#else + /* + * If the fdp is NULL then there is no set route for this packet. + */ + if (fdp == NULL) { + qif = fin->fin_ifp; + + switch (fin->fin_v) + { + case 4 : + fd.fd_ip = ip->ip_dst; + break; +#ifdef USE_INET6 + case 6 : + fd.fd_ip6.in6 = ip6->ip6_dst; + break; +#endif + } + fdp = &fd; + } else { +#endif + qif = fdp->fd_ifp; + + if (qif == NULL || qif == (void *)-1) + goto bad_fastroute; + } + + /* + * In case we're here due to "to <if>" being used with + * "keep state", check that we're going in the correct + * direction. + */ + if ((fr != NULL) && (fin->fin_rev != 0)) { + if ((qif != NULL) && (fdp == &fr->fr_tif)) + return -1; + dst.s_addr = fin->fin_fi.fi_daddr; + } else { + if (fin->fin_v == 4) { + if (fdp && fdp->fd_ip.s_addr != 0) { + dst = fdp->fd_ip; +#ifdef IRE_ILL_CN + target = &dst; +#endif + } else + dst.s_addr = fin->fin_fi.fi_daddr; + } +#ifdef USE_INET6 + else if (fin->fin_v == 6) { + if (fdp && IP6_NOTZERO(&fdp->fd_ip)) { + dst6 = fdp->fd_ip6.in6; +#ifdef IRE_ILL_CN + target = &dst6; +#endif + } else + dst6 = fin->fin_dst6; + } +#endif + else + goto bad_fastroute; + } + +#ifndef IRE_ILL_CN +#if SOLARIS2 >= 6 + if (fin->fin_v == 4) { + dir = ire_route_lookup(dst.s_addr, 0xffffffff, 0, 0, NULL, + NULL, NULL, MATCH_IRE_DSTONLY| + MATCH_IRE_DEFAULT|MATCH_IRE_RECURSIVE); + } +# ifdef USE_INET6 + else if (fin->fin_v == 6) { + dir = ire_route_lookup_v6(&ip6->ip6_dst, NULL, 0, 0, + NULL, NULL, NULL, MATCH_IRE_DSTONLY| + MATCH_IRE_DEFAULT|MATCH_IRE_RECURSIVE); + } +# endif +#else + dir = ire_lookup(dst.s_addr); +#endif +#if SOLARIS2 < 8 + if (dir != NULL) + if (dir->ire_ll_hdr_mp == NULL || dir->ire_ll_hdr_length == 0) + dir = NULL; +#else + if (dir != NULL) + if (dir->ire_fp_mp == NULL || dir->ire_dlureq_mp == NULL) { + ire_refrele(dir); + dir = NULL; + } +#endif +#else /* IRE_ILL_CN */ + if (fdp && fdp->fd_ifname[0] != 0) + ifname = fdp->fd_ifname; + + DB_CKSUMFLAGS(mb) = 0; /* disable hardware checksum */ + mp = pfil_make_dl_packet(mb, ip, target, ifname, &q); + if (mp == NULL) + { + goto bad_fastroute; + } + mb = mp; +#endif /* IRE_ILL_CN */ + +#ifdef IRE_ILL_CN + if (mp != NULL) { +#else + if (dir != NULL) { +#if SOLARIS2 < 8 + mp = dir->ire_ll_hdr_mp; + hlen = dir->ire_ll_hdr_length; +#else + mp = dir->ire_fp_mp; + hlen = mp ? mp->b_wptr - mp->b_rptr : 0; + if (mp == NULL) + mp = dir->ire_dlureq_mp; +#endif +#endif + if (fin->fin_out == 0) { + void *saveqif; + u_32_t pass; + + saveqif = fin->fin_ifp; + fin->fin_ifp = qif; + fin->fin_out = 1; + (void)fr_acctpkt(fin, &pass); + fin->fin_fr = NULL; + if (!fr || !(fr->fr_flags & FR_RETMASK)) + (void) fr_checkstate(fin, &pass); + + switch (fr_checknatout(fin, NULL)) + { + /* FALLTHROUGH */ + case 0 : + case 1 : + break; + case -1 : + goto bad_fastroute; + } + + fin->fin_out = 0; + fin->fin_ifp = saveqif; + } +#ifndef sparc + if (fin->fin_v == 4) { + __iplen = (u_short)ip->ip_len, + __ipoff = (u_short)ip->ip_off; + + ip->ip_len = htons(__iplen); + ip->ip_off = htons(__ipoff); + } +#endif +#ifndef IRE_ILL_CN + ifp = qif->qf_ill; + + if (mp != NULL) { + s = mb->b_rptr; + if ( +#if (SOLARIS2 >= 6) && defined(ICK_M_CTL_MAGIC) + (dohwcksum && + ifp->ill_ick.ick_magic == ICK_M_CTL_MAGIC) || +#endif + (hlen && (s - mb->b_datap->db_base) >= hlen)) { + s -= hlen; + mb->b_rptr = (u_char *)s; + bcopy((char *)mp->b_rptr, (char *)s, hlen); + } else { + mblk_t *mp2; + + mp2 = copyb(mp); + if (mp2 == NULL) + goto bad_fastroute; + linkb(mp2, mb); + mb = mp2; + } + } + *mpp = mb; + + if (dir->ire_stq != NULL) + q = dir->ire_stq; + else if (dir->ire_rfq != NULL) + q = WR(dir->ire_rfq); + if (q != NULL) + q = q->q_next; + if (q != NULL) { + RWLOCK_EXIT(&ipf_global); +#if (SOLARIS2 >= 6) && defined(ICK_M_CTL_MAGIC) + if ((fin->fin_p == IPPROTO_TCP) && dohwcksum && + (ifp->ill_ick.ick_magic == ICK_M_CTL_MAGIC)) { + tcphdr_t *tcp; + u_32_t t; + + tcp = (tcphdr_t *)((char *)ip + fin->fin_hlen); + t = ip->ip_src.s_addr; + t += ip->ip_dst.s_addr; + t += 30; + t = (t & 0xffff) + (t >> 16); + tcp->th_sum = t & 0xffff; + } +#endif + putnext(q, mb); + ATOMIC_INCL(fr_frouteok[0]); +#if SOLARIS2 >= 8 + ire_refrele(dir); +#endif + READ_ENTER(&ipf_global); + return 0; + } +#else /* IRE_ILL_CN */ + mb->b_queue = q; + *mpp = mb; + pfil_send_dl_packet(q, mb); + ATOMIC_INCL(fr_frouteok[0]); + return 0; +#endif /* IRE_ILL_CN */ + } +bad_fastroute: +#ifndef IRE_ILL_CN +#if SOLARIS2 >= 8 + if (dir != NULL) + ire_refrele(dir); +#endif +#endif + freemsg(mb); + ATOMIC_INCL(fr_frouteok[1]); + return -1; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: fr_pullup */ +/* Returns: NULL == pullup failed, else pointer to protocol header */ +/* Parameters: m(I) - pointer to buffer where data packet starts */ +/* fin(I) - pointer to packet information */ +/* len(I) - number of bytes to pullup */ +/* */ +/* Attempt to move at least len bytes (from the start of the buffer) into a */ +/* single buffer for ease of access. Operating system native functions are */ +/* used to manage buffers - if necessary. If the entire packet ends up in */ +/* a single buffer, set the FI_COALESCE flag even though fr_coalesce() has */ +/* not been called. Both fin_ip and fin_dp are updated before exiting _IF_ */ +/* and ONLY if the pullup succeeds. */ +/* */ +/* We assume that 'min' is a pointer to a buffer that is part of the chain */ +/* of buffers that starts at *fin->fin_mp. */ +/* ------------------------------------------------------------------------ */ +void *fr_pullup(min, fin, len) +mb_t *min; +fr_info_t *fin; +int len; +{ + qpktinfo_t *qpi = fin->fin_qpi; + int out = fin->fin_out, dpoff, ipoff; + mb_t *m = min; + char *ip; + + if (m == NULL) + return NULL; + + ip = (char *)fin->fin_ip; + if ((fin->fin_flx & FI_COALESCE) != 0) + return ip; + + ipoff = fin->fin_ipoff; + if (fin->fin_dp != NULL) + dpoff = (char *)fin->fin_dp - (char *)ip; + else + dpoff = 0; + + if (M_LEN(m) < len) { + + /* + * pfil_precheck ensures the IP header is on a 32bit + * aligned address so simply fail if that isn't currently + * the case (should never happen). + */ + int inc = 0; + + if (ipoff > 0) { + if ((ipoff & 3) != 0) { + inc = 4 - (ipoff & 3); + if (m->b_rptr - inc >= m->b_datap->db_base) + m->b_rptr -= inc; + else + inc = 0; + } + } + if (pullupmsg(m, len + ipoff + inc) == 0) { + ATOMIC_INCL(frstats[out].fr_pull[1]); + FREE_MB_T(*fin->fin_mp); + *fin->fin_mp = NULL; + fin->fin_m = NULL; + fin->fin_ip = NULL; + fin->fin_dp = NULL; + qpi->qpi_data = NULL; + return NULL; + } + m->b_rptr += inc; + fin->fin_m = m; + ip = MTOD(m, char *) + ipoff; + qpi->qpi_data = ip; + } + + ATOMIC_INCL(frstats[out].fr_pull[0]); + fin->fin_ip = (ip_t *)ip; + if (fin->fin_dp != NULL) + fin->fin_dp = (char *)fin->fin_ip + dpoff; + + if (len == fin->fin_plen) + fin->fin_flx |= FI_COALESCE; + return ip; +} diff --git a/usr/src/common/ipf/ip_frag.c b/usr/src/uts/common/inet/ipf/ip_frag.c index 5d5cf0ada4..29362c8a83 100644 --- a/usr/src/common/ipf/ip_frag.c +++ b/usr/src/uts/common/inet/ipf/ip_frag.c @@ -2,10 +2,8 @@ * Copyright (C) 1993-2003 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. - */ - -/* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -42,7 +40,9 @@ struct file; #else # include <sys/ioctl.h> #endif -#include <sys/protosw.h> +#if !defined(linux) +# include <sys/protosw.h> +#endif #include <sys/socket.h> #if defined(_KERNEL) # include <sys/systm.h> @@ -51,7 +51,7 @@ struct file; # endif #endif #if !defined(__SVR4) && !defined(__svr4__) -# if defined(_KERNEL) && !defined(__sgi) +# if defined(_KERNEL) && !defined(__sgi) && !defined(AIX) # include <sys/kernel.h> # endif #else @@ -70,28 +70,20 @@ struct file; #include <netinet/in.h> #include <netinet/in_systm.h> #include <netinet/ip.h> -#include <netinet/ip_var.h> +#if !defined(linux) +# include <netinet/ip_var.h> +#endif #include <netinet/tcp.h> #include <netinet/udp.h> #include <netinet/ip_icmp.h> -#include <netinet/tcpip.h> -#if SOLARIS2 >= 10 -#include "ip_compat.h" -#include "ip_fil.h" -#include "ip_nat.h" -#include "ip_frag.h" -#include "ip_state.h" -#include "ip_auth.h" -#include "ip_proxy.h" -#else #include "netinet/ip_compat.h" +#include <netinet/tcpip.h> #include "netinet/ip_fil.h" #include "netinet/ip_nat.h" #include "netinet/ip_frag.h" #include "netinet/ip_state.h" #include "netinet/ip_auth.h" #include "netinet/ip_proxy.h" -#endif #if (__FreeBSD_version >= 300000) # include <sys/malloc.h> # if defined(_KERNEL) @@ -110,10 +102,11 @@ extern struct callout fr_slowtimer_ch; # include <sys/timeout.h> extern struct timeout fr_slowtimer_ch; #endif +/* END OF INCLUDES */ #if !defined(lint) static const char sccsid[] = "@(#)ip_frag.c 1.11 3/24/96 (C) 1993-2000 Darren Reed"; -static const char rcsid[] = "@(#)$Id: ip_frag.c,v 2.67 2003/06/28 17:01:57 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id: ip_frag.c,v 2.77.2.5 2005/08/11 14:33:10 darrenr Exp $"; #endif @@ -138,12 +131,6 @@ int fr_frag_lock = 0; int fr_frag_init = 0; u_long fr_ticks = 0; -#ifdef USE_MUTEXES -extern ipfrwlock_t ipf_frag, ipf_natfrag, ipf_nat, ipf_mutex, ipf_global; -extern ipfrwlock_t ipf_ipidfrag; -extern ipfmutex_t ipf_rw; -#endif - static ipfr_t *ipfr_newfrag __P((fr_info_t *, u_32_t, ipfr_t **)); static ipfr_t *fr_fraglookup __P((fr_info_t *, ipfr_t **)); @@ -220,7 +207,7 @@ void fr_fragunload() /* ------------------------------------------------------------------------ */ /* Function: fr_fragstats */ -/* Returns: ipfrstat_t* - pointer to struct with current frag stats */ +/* Returns: ipfrstat_t* - pointer to struct with current frag stats */ /* Parameters: Nil */ /* */ /* Updates ipfr_stats with current information and returns a pointer to it */ @@ -297,8 +284,15 @@ ipfr_t *table[]; return NULL; } - if ((fra->ipfr_rule = fin->fin_fr) != NULL) { - ATOMIC_INC(fin->fin_fr->fr_ref); + fra->ipfr_rule = fin->fin_fr; + if (fra->ipfr_rule != NULL) { + + frentry_t *fr; + + fr = fin->fin_fr; + MUTEX_ENTER(&fr->fr_lock); + fr->fr_ref++; + MUTEX_EXIT(&fr->fr_lock); } /* @@ -317,7 +311,7 @@ ipfr_t *table[]; /* * Compute the offset of the expected start of the next packet. */ - off = fin->fin_off >> 3; + off = fin->fin_off; if (off == 0) { fra->ipfr_seen0 = 1; fra->ipfr_firstend = fin->fin_flen; @@ -325,7 +319,7 @@ ipfr_t *table[]; fra->ipfr_seen0 = 0; fra->ipfr_firstend = 0; } - fra->ipfr_off = off + (fin->fin_dlen >> 3); + fra->ipfr_off = off + fin->fin_dlen; fra->ipfr_pass = pass; ipfr_stats.ifs_new++; ipfr_inuse++; @@ -347,7 +341,7 @@ fr_info_t *fin; ipfr_t *fra; if (fr_frag_lock != 0) - return NULL; + return -1; WRITE_ENTER(&ipf_frag); fra = ipfr_newfrag(fin, pass, ipfr_heads); @@ -464,7 +458,6 @@ ipfr_t *table[]; idx += frag.ipfr_src.s_addr; frag.ipfr_dest = fin->fin_fi.fi_dst; idx += frag.ipfr_dst.s_addr; - frag.ipfr_ifp = fin->fin_ifp; idx *= 127; idx %= IPFT_SIZE; @@ -502,7 +495,7 @@ ipfr_t *table[]; * because a fragmented packet is never resent with * the same IP ID# (or shouldn't). */ - off = fin->fin_off >> 3; + off = fin->fin_off; /* same as in ipfr_newfrag() */ if (f->ipfr_seen0) { if (off == 0) { ATOMIC_INCL(ipfr_stats.ifs_retrans0); @@ -534,7 +527,7 @@ ipfr_t *table[]; } if (fin->fin_v == 6) { - if (f->ipfr_seen0 && (off * 8 < f->ipfr_firstend)) + if (f->ipfr_seen0 && (off < f->ipfr_firstend)) fin->fin_flx |= FI_BAD; } /* @@ -542,10 +535,9 @@ ipfr_t *table[]; * last (in order), shrink expiration time. */ if (off == f->ipfr_off) { -/* if (!(ip->ip_off & IP_MF)) + if (!(fin->fin_ip->ip_off & IP_MF)) f->ipfr_ttl = fr_ticks + 1; -*/ - f->ipfr_off = (fin->fin_dlen >> 3) + off; + f->ipfr_off = fin->fin_dlen + off; } else if (f->ipfr_pass & FR_FRSTRICT) continue; ATOMIC_INCL(ipfr_stats.ifs_hits); @@ -783,9 +775,7 @@ void fr_fragexpire() { ipfr_t **fp, *fra; nat_t *nat; -#if defined(_KERNEL) && !defined(MENTAT) && defined(USE_SPL) - int s; -#endif + SPL_INT(s); if (fr_frag_lock) return; @@ -851,7 +841,7 @@ void fr_fragexpire() /* expectation of this being called twice per second. */ /* ------------------------------------------------------------------------ */ #if !defined(_KERNEL) || (!SOLARIS && !defined(__hpux) && !defined(__sgi) && \ - !defined(__osf__)) + !defined(__osf__) && !defined(linux)) # if defined(_KERNEL) && ((BSD >= 199103) || defined(__sgi)) void fr_slowtimer __P((void *ptr)) # else @@ -877,7 +867,11 @@ int fr_slowtimer() # if (__FreeBSD_version >= 300000) fr_slowtimer_ch = timeout(fr_slowtimer, NULL, hz/2); # else +# ifdef linux + ; +# else timeout(fr_slowtimer, NULL, hz/2); +# endif # endif /* FreeBSD */ # endif /* OpenBSD */ # endif /* NetBSD */ diff --git a/usr/src/common/ipf/ip_htable.c b/usr/src/uts/common/inet/ipf/ip_htable.c index 37c65cc398..4ce3cc411e 100644 --- a/usr/src/common/ipf/ip_htable.c +++ b/usr/src/uts/common/inet/ipf/ip_htable.c @@ -3,7 +3,7 @@ * * See the IPFILTER.LICENCE file for details on licencing. * - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -38,7 +38,8 @@ struct file; # include <sys/cdefs.h> # include <sys/proc.h> #endif -#if !defined(__svr4__) && !defined(__SVR4) && !defined(__hpux) +#if !defined(__svr4__) && !defined(__SVR4) && !defined(__hpux) && \ + !defined(linux) # include <sys/mbuf.h> #endif #if defined(_KERNEL) @@ -49,20 +50,14 @@ struct file; #include <netinet/in.h> #include <net/if.h> -#if SOLARIS2 >= 10 -#include "ip_compat.h" -#include "ip_fil.h" -#include "ip_lookup.h" -#include "ip_htable.h" -#else #include "netinet/ip_compat.h" #include "netinet/ip_fil.h" #include "netinet/ip_lookup.h" #include "netinet/ip_htable.h" -#endif +/* END OF INCLUDES */ #if !defined(lint) -static const char rcsid[] = "@(#)$Id: ip_htable.c,v 2.24 2003/05/12 13:49:17 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id: ip_htable.c,v 2.34.2.3 2005/05/14 05:11:38 darrenr Exp $"; #endif #ifdef IPFILTER_LOOKUP @@ -80,22 +75,16 @@ static u_long ipf_nhtnodes[IPL_LOGSIZE] = { 0, 0, 0, 0, 0, 0, 0, 0 }; iphtable_t *ipf_htables[IPL_LOGSIZE] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; + void fr_htable_unload() { iplookupflush_t fop; - iphtable_t *iph; - int unit; - - for (unit = 0; unit < IPL_LOGMAX; unit++) { - fop.iplf_unit = unit; - while ((iph = ipf_htables[unit]) != NULL) { - (void)strncpy(fop.iplf_name, iph->iph_name, - sizeof(fop.iplf_name)); - (void)fr_flushhtable(&fop); - } - } + + fop.iplf_unit = IPL_LOGALL; + (void)fr_flushhtable(&fop); } + int fr_gethtablestat(op) iplookupop_t *op; { @@ -125,8 +114,10 @@ iplookupop_t *op; int err, i, unit; KMALLOC(iph, iphtable_t *); - if (iph == NULL) - return ENOMEM; + if (iph == NULL) { + ipht_nomem[op->iplo_unit]++; + return ENOMEM; + } err = COPYIN(op->iplo_struct, iph, sizeof(*iph)); if (err != 0) { @@ -149,7 +140,11 @@ iplookupop_t *op; i = IPHASH_ANON; do { i++; +#if defined(SNPRINTF) && defined(_KERNEL) + (void)SNPRINTF(name, sizeof(name), "%u", i); +#else (void)sprintf(name, "%u", i); +#endif for (oiph = ipf_htables[unit]; oiph != NULL; oiph = oiph->iph_next) if (strncmp(oiph->iph_name, name, @@ -220,15 +215,24 @@ iplookupop_t *op; void fr_delhtable(iph) iphtable_t *iph; { + iphtent_t *ipe; + int i; + + for (i = 0; i < iph->iph_size; i++) + while ((ipe = iph->iph_table[i]) != NULL) + if (fr_delhtent(iph, ipe) != 0) + return; *iph->iph_pnext = iph->iph_next; if (iph->iph_next != NULL) iph->iph_next->iph_pnext = iph->iph_pnext; ipf_nhtables[iph->iph_unit]--; - - KFREES(iph->iph_table, iph->iph_size * sizeof(*iph->iph_table)); - KFREE(iph); + + if (iph->iph_ref == 0) { + KFREES(iph->iph_table, iph->iph_size * sizeof(*iph->iph_table)); + KFREE(iph); + } } @@ -258,40 +262,19 @@ size_t fr_flushhtable(op) iplookupflush_t *op; { iphtable_t *iph; - size_t i, freed; - iphtent_t *ipe; - - iph = fr_findhtable(op->iplf_unit, op->iplf_name); - if (iph == NULL) { - return 0; - } + size_t freed; + int i; freed = 0; - *iph->iph_pnext = iph->iph_next; - if (iph->iph_next != NULL) - iph->iph_next->iph_pnext = iph->iph_pnext; - for (i = 0; i < iph->iph_size; i++) - while ((ipe = iph->iph_table[i]) != NULL) { - *ipe->ipe_pnext = ipe->ipe_next; - if (ipe->ipe_next != NULL) - ipe->ipe_next->ipe_pnext = ipe->ipe_pnext; - - switch (iph->iph_type & ~IPHASH_ANON) - { - case IPHASH_GROUPMAP : - if (ipe->ipe_ptr != NULL) - fr_delgroup(ipe->ipe_group, - IPL_LOGIPF, fr_active); - break; + for (i = 0; i <= IPL_LOGMAX; i++) { + if (op->iplf_unit == i || op->iplf_unit == IPL_LOGALL) { + while ((iph = ipf_htables[i]) != NULL) { + fr_delhtable(iph); + freed++; } - /* ipe_ref */ - KFREE(ipe); - freed++; } - - KFREES(iph->iph_table, iph->iph_size * sizeof(*iph->iph_table)); - KFREE(iph); + } return freed; } @@ -411,14 +394,15 @@ iphtent_t *ipe; KFREE(ipe); ipf_nhtnodes[iph->iph_unit]--; - + return 0; } void *fr_iphmfindgroup(tptr, version, aptr) -void *tptr, *aptr; +void *tptr; int version; +void *aptr; { i6addr_t *addr; iphtable_t *iph; @@ -454,6 +438,15 @@ int version; } +/* ------------------------------------------------------------------------ */ +/* Function: fr_iphmfindip */ +/* Returns: int - 0 == +ve match, -1 == error, 1 == -ve/no match */ +/* Parameters: tptr(I) - pointer to the pool to search */ +/* version(I) - IP protocol version (4 or 6) */ +/* aptr(I) - pointer to address information */ +/* */ +/* Search the hash table for a given address and return a search result. */ +/* ------------------------------------------------------------------------ */ int fr_iphmfindip(tptr, version, aptr) void *tptr, *aptr; int version; @@ -463,8 +456,15 @@ int version; iphtent_t *ipe; int rval; + if ((version != 4) +#ifdef USE_INET6 + && (version != 6) +#endif + ) + return -1; + if (tptr == NULL || aptr == NULL) - return 1; + return -1; iph = tptr; addr = aptr; @@ -498,7 +498,6 @@ struct in_addr *addr; u_int hv; hmsk = iph->iph_masks[3]; - msk = 0xffffffff; maskloop: ips = ntohl(addr->s_addr) & msk; @@ -523,7 +522,6 @@ maskloop: goto maskloop; } } - return ipe; } @@ -580,7 +578,6 @@ maskloop: goto maskloop; } } - return ipe; } diff --git a/usr/src/common/ipf/ip_log.c b/usr/src/uts/common/inet/ipf/ip_log.c index a7728cb7b8..364b2e08e5 100644 --- a/usr/src/common/ipf/ip_log.c +++ b/usr/src/uts/common/inet/ipf/ip_log.c @@ -3,9 +3,9 @@ * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: ip_log.c,v 2.54 2003/06/28 17:01:57 darrenr Exp $ + * $Id: ip_log.c,v 2.75.2.7 2005/06/11 07:47:44 darrenr Exp $ * - * Copyright 2003 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -22,144 +22,135 @@ defined(_KERNEL) # include "opt_ipfilter_log.h" #endif -#ifdef __FreeBSD__ -# if !defined(IPFILTER_LKM) -# if defined(_KERNEL) -# if defined(__FreeBSD_version) && (__FreeBSD_version >= 300000) -# include "opt_ipfilter.h" -# endif -# else -# include <osreldate.h> +#if defined(__FreeBSD__) && !defined(IPFILTER_LKM) +# if defined(_KERNEL) +# if defined(__FreeBSD_version) && (__FreeBSD_version >= 300000) +# include "opt_ipfilter.h" # endif +# else +# include <osreldate.h> # endif #endif -#ifdef IPFILTER_LOG -# ifndef SOLARIS -# define SOLARIS (defined(sun) && (defined(__svr4__) || defined(__SVR4))) -# endif -# include <sys/errno.h> -# include <sys/types.h> -# include <sys/file.h> -# ifndef _KERNEL -# include <stdio.h> -# include <string.h> -# include <stdlib.h> -# include <ctype.h> -# define _KERNEL +#ifndef SOLARIS +# define SOLARIS (defined(sun) && (defined(__svr4__) || defined(__SVR4))) +#endif +#include <sys/errno.h> +#include <sys/types.h> +#include <sys/file.h> +#ifndef _KERNEL +# include <stdio.h> +# include <string.h> +# include <stdlib.h> +# include <ctype.h> +# define _KERNEL +# define KERNEL # ifdef __OpenBSD__ struct file; # endif -# include <sys/uio.h> -# undef _KERNEL +# include <sys/uio.h> +# undef _KERNEL +# undef KERNEL +#endif +#if __FreeBSD_version >= 220000 && defined(_KERNEL) +# include <sys/fcntl.h> +# include <sys/filio.h> +#else +# include <sys/ioctl.h> +#endif +#include <sys/time.h> +#if defined(_KERNEL) +# include <sys/systm.h> +# if defined(NetBSD) && (__NetBSD_Version__ >= 104000000) +# include <sys/proc.h> # endif -# if __FreeBSD_version >= 220000 && defined(_KERNEL) -# include <sys/fcntl.h> -# include <sys/filio.h> +#endif /* _KERNEL */ +#if !SOLARIS && !defined(__hpux) && !defined(linux) +# if (NetBSD > 199609) || (OpenBSD > 199603) || (__FreeBSD_version >= 300000) +# include <sys/dirent.h> # else -# include <sys/ioctl.h> +# include <sys/dir.h> # endif -# include <sys/time.h> -# if defined(_KERNEL) -# include <sys/systm.h> -# if defined(NetBSD) && (__NetBSD_Version__ >= 104000000) -# include <sys/proc.h> -# endif -# endif /* _KERNEL */ -# if !SOLARIS && !defined(__hpux) -# if (NetBSD > 199609) || (OpenBSD > 199603) || (__FreeBSD_version >= 300000) -# include <sys/dirent.h> -# else -# include <sys/dir.h> -# endif -# include <sys/mbuf.h> -# else -# if !defined(__hpux) && defined(_KERNEL) -# include <sys/filio.h> -# include <sys/cred.h> -# include <sys/ddi.h> -# include <sys/sunddi.h> -# include <sys/ksynch.h> -# include <sys/kmem.h> -# include <sys/mkdev.h> -# include <sys/dditypes.h> -# include <sys/cmn_err.h> -# endif /* !__hpux */ -# endif /* !SOLARIS && !__hpux */ +# include <sys/mbuf.h> +#else +# if !defined(__hpux) && defined(_KERNEL) +# include <sys/filio.h> +# include <sys/cred.h> +# include <sys/ddi.h> +# include <sys/sunddi.h> +# include <sys/ksynch.h> +# include <sys/kmem.h> +# include <sys/mkdev.h> +# include <sys/dditypes.h> +# include <sys/cmn_err.h> +# endif /* !__hpux */ +#endif /* !SOLARIS && !__hpux */ +#if !defined(linux) # include <sys/protosw.h> -# include <sys/socket.h> +#endif +#include <sys/socket.h> -# include <net/if.h> -# ifdef sun -# include <net/af.h> -# endif -# if __FreeBSD_version >= 300000 -# include <net/if_var.h> -# endif -# include <net/route.h> -# include <netinet/in.h> -# ifdef __sgi -# include <sys/ddi.h> -# ifdef IFF_DRVRLOCK /* IRIX6 */ -# include <sys/hashing.h> -# endif -# endif -# if !defined(__hpux) && !(defined(__sgi) && !defined(IFF_DRVRLOCK)) /*IRIX<6*/ -# include <netinet/in_var.h> -# endif -# include <netinet/in_systm.h> -# include <netinet/ip.h> -# include <netinet/tcp.h> -# include <netinet/udp.h> -# include <netinet/ip_icmp.h> -# ifdef USE_INET6 -# include <netinet/icmp6.h> +#include <net/if.h> +#ifdef sun +# include <net/af.h> +#endif +#if __FreeBSD_version >= 300000 +# include <net/if_var.h> +#endif +#include <net/route.h> +#include <netinet/in.h> +#ifdef __sgi +# include <sys/ddi.h> +# ifdef IFF_DRVRLOCK /* IRIX6 */ +# include <sys/hashing.h> # endif +#endif +#if !defined(__hpux) && !defined(linux) && \ + !(defined(__sgi) && !defined(IFF_DRVRLOCK)) /*IRIX<6*/ +# include <netinet/in_var.h> +#endif +#include <netinet/in_systm.h> +#include <netinet/ip.h> +#include <netinet/tcp.h> +#include <netinet/udp.h> +#include <netinet/ip_icmp.h> +#ifdef USE_INET6 +# include <netinet/icmp6.h> +#endif +#if !defined(linux) # include <netinet/ip_var.h> -# ifndef _KERNEL -# include <syslog.h> -# endif -# include <netinet/tcpip.h> -#if SOLARIS2 >= 10 -# include "ip_compat.h" -# include "ip_fil.h" -# include "ip_nat.h" -# include "ip_frag.h" -# include "ip_state.h" -# include "ip_auth.h" -#else -# include "netinet/ip_compat.h" -# include "netinet/ip_fil.h" -# include "netinet/ip_nat.h" -# include "netinet/ip_frag.h" -# include "netinet/ip_state.h" -# include "netinet/ip_auth.h" #endif -# if (__FreeBSD_version >= 300000) || defined(__NetBSD__) -# include <sys/malloc.h> -# endif +#ifndef _KERNEL +# include <syslog.h> +#endif +#include "netinet/ip_compat.h" +#include <netinet/tcpip.h> +#include "netinet/ip_fil.h" +#include "netinet/ip_nat.h" +#include "netinet/ip_frag.h" +#include "netinet/ip_state.h" +#include "netinet/ip_auth.h" +#if (__FreeBSD_version >= 300000) || defined(__NetBSD__) +# include <sys/malloc.h> +#endif +/* END OF INCLUDES */ -# if defined(__hpux) && defined(_KERNEL) && (HPUXREV >= 1111) -# define IPL_SELECT -# endif +#ifdef IPFILTER_LOG # if defined(IPL_SELECT) -# include <machine/sys/user.h> -# include <sys/kthread_iface.h> -# define READ_COLLISION 0x001 +# include <machine/sys/user.h> +# include <sys/kthread_iface.h> +# define READ_COLLISION 0x001 -struct { - kthread *read_waiter; - int state; -} iplog_ss[IPL_LOGMAX+1]; +iplog_select_t iplog_ss[IPL_LOGMAX+1]; extern int selwait; # endif /* IPL_SELECT */ -# ifdef USE_MUTEXES -extern ipfmutex_t ipl_mutex; -# if SOLARIS +# if defined(linux) && defined(_KERNEL) +wait_queue_head_t iplh_linux[IPL_LOGSIZE]; +# endif +# if SOLARIS extern kcondvar_t iplwait; -# endif # endif iplog_t **iplh[IPL_LOGSIZE], *iplt[IPL_LOGSIZE], *ipll[IPL_LOGSIZE]; @@ -170,6 +161,10 @@ int ipl_buffer_sz; int ipl_logmax = IPL_LOGMAX; int ipl_logall = 0; int ipl_log_init = 0; +int ipl_logsize = IPFILTER_LOGSIZE; +int ipl_magic[IPL_LOGSIZE] = { IPL_MAGIC, IPL_MAGIC_NAT, IPL_MAGIC_STATE, + IPL_MAGIC, IPL_MAGIC, IPL_MAGIC, + IPL_MAGIC, IPL_MAGIC }; /* ------------------------------------------------------------------------ */ @@ -194,6 +189,9 @@ int fr_loginit() iplog_ss[i].read_waiter = 0; iplog_ss[i].state = 0; # endif +# if defined(linux) && defined(_KERNEL) + init_waitqueue_head(iplh_linux + i); +# endif } # if SOLARIS && defined(_KERNEL) @@ -256,20 +254,17 @@ u_int flags; ipflog_t ipfl; u_char p; mb_t *m; -# if SOLARIS && defined(_KERNEL) +# if (SOLARIS || defined(__hpux)) && defined(_KERNEL) # ifndef IRE_ILL_CN - ill_t *ifp; + qif_t *ifp; # else s_ill_t *ifp; # endif /* IRE_ILL_CN */ # else -# if defined(__hpux) && defined(_KERNEL) - ifinfo_t *ifp; -# else struct ifnet *ifp; -# endif -# endif /* SOLARIS */ +# endif /* SOLARIS || __hpux */ + ipfl.fl_nattag.ipt_num[0] = 0; m = fin->fin_m; ifp = fin->fin_ifp; hlen = fin->fin_hlen; @@ -286,7 +281,7 @@ u_int flags; struct icmp *icmp; icmp = (struct icmp *)fin->fin_dp; - + /* * For ICMP, if the packet is an error packet, also * include the information about the packet which @@ -333,32 +328,27 @@ u_int flags; * Get the interface number and name to which this packet is * currently associated. */ -# if SOLARIS && defined(_KERNEL) - ipfl.fl_unit = (u_char)0; +# if (SOLARIS || defined(__hpux)) && defined(_KERNEL) + ipfl.fl_unit = (u_int)0; (void) strncpy(ipfl.fl_ifname, IFNAME(ifp), sizeof(ipfl.fl_ifname)); # else -# if defined(__hpux) && defined(_KERNEL) - ipfl.fl_unit = (u_char)ifp->ifi_ppa; - bcopy(IFNAME(ifp), ipfl.fl_ifname, - MIN(ifp->ifi_name_length, sizeof(ipfl.fl_ifname))); +# if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199603)) || \ + (defined(OpenBSD) && (OpenBSD >= 199603)) || defined(linux) || \ + (defined(__FreeBSD__) && (__FreeBSD_version >= 501113)) + COPYIFNAME(ifp, ipfl.fl_ifname); # else -# if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199603)) || \ - (defined(OpenBSD) && (OpenBSD >= 199603)) - (void) strncpy(ipfl.fl_ifname, ifp->if_xname, sizeof(ipfl.fl_ifname)); -# else - ipfl.fl_unit = (u_char)ifp->if_unit; -# if defined(_KERNEL) + ipfl.fl_unit = (u_int)ifp->if_unit; +# if defined(_KERNEL) if ((ipfl.fl_ifname[0] = ifp->if_name[0])) if ((ipfl.fl_ifname[1] = ifp->if_name[1])) if ((ipfl.fl_ifname[2] = ifp->if_name[2])) ipfl.fl_ifname[3] = ifp->if_name[3]; -# else - (void) strncpy(ipfl.fl_ifname, ifp->if_name, LIFNAMSIZ); - ipfl.fl_ifname[LIFNAMSIZ - 1] = '\0'; -# endif +# else + (void) strncpy(ipfl.fl_ifname, IFNAME(ifp), sizeof(ipfl.fl_ifname)); + ipfl.fl_ifname[sizeof(ipfl.fl_ifname) - 1] = '\0'; # endif -# endif /* __hpux */ -# endif /* SOLARIS */ +# endif +# endif /* __hpux || SOLARIS */ mlen = fin->fin_plen - hlen; if (!ipl_logall) { mlen = (flags & FR_LOGBODY) ? MIN(mlen, 128) : 0; @@ -373,11 +363,14 @@ u_int flags; (void) strncpy(ipfl.fl_group, fin->fin_group, FR_GROUPLEN); if (fin->fin_fr != NULL) { ipfl.fl_loglevel = fin->fin_fr->fr_loglevel; - ipfl.fl_tag = fin->fin_fr->fr_logtag; + ipfl.fl_logtag = fin->fin_fr->fr_logtag; } else { ipfl.fl_loglevel = 0xffff; - ipfl.fl_tag = FR_NOLOGTAG; + ipfl.fl_logtag = FR_NOLOGTAG; } + if (fin->fin_nattag != NULL) + bcopy(fin->fin_nattag, (void *)&ipfl.fl_nattag, + sizeof(ipfl.fl_nattag)); ipfl.fl_flags = flags; ipfl.fl_dir = fin->fin_out; ipfl.fl_lflags = fin->fin_flx; @@ -427,11 +420,12 @@ void **items; size_t *itemsz; int *types, cnt; { - caddr_t buf, s; + caddr_t buf, ptr; iplog_t *ipl; size_t len; int i; - + SPL_INT(s); + /* * Check to see if this log record has a CRC which matches the last * record logged. If it does, just up the count on the previous one @@ -439,7 +433,7 @@ int *types, cnt; */ if (ipl_suppress) { MUTEX_ENTER(&ipl_mutex); - if (fin != NULL) { + if ((fin != NULL) && (fin->fin_off == 0)) { if ((ipll[dev] != NULL) && bcmp((char *)fin, (char *)&iplcrc[dev], FI_LCSIZE) == 0) { @@ -463,24 +457,27 @@ int *types, cnt; * check that we have space to record this information and can * allocate that much. */ + KMALLOCS(buf, caddr_t, len); + if (buf == NULL) + return -1; + SPL_NET(s); MUTEX_ENTER(&ipl_mutex); - if ((iplused[dev] + len) > IPFILTER_LOGSIZE) { + if ((iplused[dev] + len) > ipl_logsize) { MUTEX_EXIT(&ipl_mutex); - return 0; + SPL_X(s); + KFREES(buf, len); + return -1; } iplused[dev] += len; MUTEX_EXIT(&ipl_mutex); - - KMALLOCS(buf, caddr_t, len); - if (!buf) - return 0; + SPL_X(s); /* * advance the log pointer to the next empty record and deduct the * amount of space we're going to use. */ ipl = (iplog_t *)buf; - ipl->ipl_magic = IPL_MAGIC; + ipl->ipl_magic = ipl_magic[dev]; ipl->ipl_count = 1; ipl->ipl_next = NULL; ipl->ipl_dsize = len; @@ -495,14 +492,15 @@ int *types, cnt; * Loop through all the items to be logged, copying each one to the * buffer. Use bcopy for normal data or the mb_t copyout routine. */ - for (i = 0, s = buf + sizeof(*ipl); i < cnt; i++) { + for (i = 0, ptr = buf + sizeof(*ipl); i < cnt; i++) { if (types[i] == 0) { - bcopy(items[i], s, itemsz[i]); + bcopy(items[i], ptr, itemsz[i]); } else if (types[i] == 1) { - COPYDATA(items[i], 0, itemsz[i], s); + COPYDATA(items[i], 0, itemsz[i], ptr); } - s += itemsz[i]; + ptr += itemsz[i]; } + SPL_NET(s); MUTEX_ENTER(&ipl_mutex); ipll[dev] = ipl; *iplh[dev] = ipl; @@ -517,12 +515,13 @@ int *types, cnt; MUTEX_EXIT(&ipl_mutex); # else MUTEX_EXIT(&ipl_mutex); - WAKEUP(&iplh[dev]); + WAKEUP(iplh,dev); # endif + SPL_X(s); # ifdef IPL_SELECT iplog_input_ready(dev); # endif - return 1; + return 0; } @@ -545,9 +544,7 @@ struct uio *uio; size_t dlen, copied; int error = 0; iplog_t *ipl; -# if defined(_KERNEL) && !defined(MENTAT) && defined(USE_SPL) - int s; -# endif + SPL_INT(s); /* * Sanity checks. Make sure the minor # is valid and we're copying @@ -558,9 +555,9 @@ struct uio *uio; if (uio->uio_resid == 0) return 0; if ((uio->uio_resid < sizeof(iplog_t)) || - (uio->uio_resid > IPFILTER_LOGSIZE)) + (uio->uio_resid > ipl_logsize)) return EINVAL; - + /* * Lock the log so we can snapshot the variables. Wait for a signal * if the log is empty. @@ -597,7 +594,7 @@ struct uio *uio; # else MUTEX_EXIT(&ipl_mutex); SPL_X(s); - error = SLEEP(&iplh[unit], "ipl sleep"); + error = SLEEP(unit + iplh, "ipl sleep"); # endif /* __osf__ */ # endif /* __hpux */ if (error) @@ -611,7 +608,7 @@ struct uio *uio; uio->uio_rw = UIO_READ; # endif - for (copied = 0; ((ipl = iplt[unit]) != NULL); copied += dlen) { + for (copied = 0; (ipl = iplt[unit]) != NULL; copied += dlen) { dlen = ipl->ipl_dsize; if (dlen > uio->uio_resid) break; @@ -620,30 +617,27 @@ struct uio *uio; */ iplt[unit] = ipl->ipl_next; iplused[unit] -= dlen; - if (iplt[unit] == NULL) { - iplh[unit] = &iplt[unit]; - ipll[unit] = NULL; - } MUTEX_EXIT(&ipl_mutex); SPL_X(s); error = UIOMOVE((caddr_t)ipl, dlen, UIO_READ, uio); if (error) { SPL_NET(s); MUTEX_ENTER(&ipl_mutex); - iplused[unit] += dlen; ipl->ipl_next = iplt[unit]; iplt[unit] = ipl; - ipll[unit] = ipl; - if (iplh[unit] == &iplt[unit]) { - *iplh[unit] = ipl; - iplh[unit] = &ipl->ipl_next; - } + iplused[unit] += dlen; break; } + MUTEX_ENTER(&ipl_mutex); KFREES((caddr_t)ipl, dlen); SPL_NET(s); - MUTEX_ENTER(&ipl_mutex); } + if (!iplt[unit]) { + iplused[unit] = 0; + iplh[unit] = &iplt[unit]; + ipll[unit] = NULL; + } + MUTEX_EXIT(&ipl_mutex); SPL_X(s); return error; @@ -662,7 +656,9 @@ minor_t unit; { iplog_t *ipl; int used; + SPL_INT(s); + SPL_NET(s); MUTEX_ENTER(&ipl_mutex); while ((ipl = iplt[unit]) != NULL) { iplt[unit] = ipl->ipl_next; @@ -674,6 +670,7 @@ minor_t unit; iplused[unit] = 0; bzero((char *)&iplcrc[unit], FI_CSIZE); MUTEX_EXIT(&ipl_mutex); + SPL_X(s); return used; } #endif /* IPFILTER_LOG */ diff --git a/usr/src/common/ipf/ip_lookup.c b/usr/src/uts/common/inet/ipf/ip_lookup.c index dcbe0a4e8a..299dadf0bb 100644 --- a/usr/src/common/ipf/ip_lookup.c +++ b/usr/src/uts/common/inet/ipf/ip_lookup.c @@ -3,7 +3,7 @@ * * See the IPFILTER.LICENCE file for details on licencing. * - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -15,6 +15,9 @@ # define KERNEL 1 # define _KERNEL 1 #endif +#if defined(__osf__) +# define _PROTO_NET_H_ +#endif #include <sys/param.h> #include <sys/errno.h> #include <sys/types.h> @@ -36,6 +39,13 @@ struct file; # undef _KERNEL #endif #include <sys/socket.h> +#if (defined(__osf__) || defined(AIX) || defined(__hpux) || defined(__sgi)) && defined(_KERNEL) +# ifdef __osf__ +# include <net/radix.h> +# endif +# include "radix_ipf_local.h" +# define _RADIX_H_ +#endif #include <net/if.h> #if defined(__FreeBSD__) # include <sys/cdefs.h> @@ -49,28 +59,18 @@ struct file; #endif #include <netinet/in.h> -#if SOLARIS2 >= 10 -#include "ip_compat.h" -#include "ip_fil.h" -#include "ip_pool.h" -#include "ip_htable.h" -#include "ip_lookup.h" -#else #include "netinet/ip_compat.h" #include "netinet/ip_fil.h" #include "netinet/ip_pool.h" #include "netinet/ip_htable.h" #include "netinet/ip_lookup.h" -#endif +/* END OF INCLUDES */ #if !defined(lint) -static const char rcsid[] = "@(#)$Id: ip_lookup.c,v 2.21 2003/06/28 17:01:57 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id: ip_lookup.c,v 2.35.2.7 2005/06/12 07:18:20 darrenr Exp $"; #endif #ifdef IPFILTER_LOOKUP -# ifdef USE_MUTEXES -ipfrwlock_t ip_poolrw; -# endif int ip_lookup_inited = 0; static int iplookup_addnode __P((caddr_t)); @@ -81,8 +81,16 @@ static int iplookup_stats __P((caddr_t)); static int iplookup_flush __P((caddr_t)); +/* ------------------------------------------------------------------------ */ +/* Function: iplookup_init */ +/* Returns: int - 0 = success, else error */ +/* Parameters: Nil */ +/* */ +/* Initialise all of the subcomponents of the lookup infrstructure. */ +/* ------------------------------------------------------------------------ */ int ip_lookup_init() { + if (ip_pool_init() == -1) return -1; @@ -94,6 +102,15 @@ int ip_lookup_init() } +/* ------------------------------------------------------------------------ */ +/* Function: iplookup_unload */ +/* Returns: int - 0 = success, else error */ +/* Parameters: Nil */ +/* */ +/* Free up all pool related memory that has been allocated whilst IPFilter */ +/* has been running. Also, do any other deinitialisation required such */ +/* ip_lookup_init() can be called again, safely. */ +/* ------------------------------------------------------------------------ */ void ip_lookup_unload() { ip_pool_fini(); @@ -106,19 +123,25 @@ void ip_lookup_unload() } +/* ------------------------------------------------------------------------ */ +/* Function: iplookup_ioctl */ +/* Returns: int - 0 = success, else error */ +/* Parameters: data(IO) - pointer to ioctl data to be copied to/from user */ +/* space. */ +/* cmd(I) - ioctl command number */ +/* mode(I) - file mode bits used with open */ +/* */ +/* Handle ioctl commands sent to the ioctl device. For the most part, this */ +/* involves just calling another function to handle the specifics of each */ +/* command. */ +/* ------------------------------------------------------------------------ */ int ip_lookup_ioctl(data, cmd, mode) caddr_t data; -# if defined(__NetBSD__) || defined(__OpenBSD__) -u_long cmd; -# else -int cmd; -# endif +ioctlcmd_t cmd; int mode; { int err; -# if defined(_KERNEL) && !defined(MENTAT) && defined(USE_SPL) - int s; -# endif + SPL_INT(s); mode = mode; /* LINT */ @@ -127,12 +150,14 @@ int mode; switch (cmd) { case SIOCLOOKUPADDNODE : + case SIOCLOOKUPADDNODEW : WRITE_ENTER(&ip_poolrw); err = iplookup_addnode(data); RWLOCK_EXIT(&ip_poolrw); break; case SIOCLOOKUPDELNODE : + case SIOCLOOKUPDELNODEW : WRITE_ENTER(&ip_poolrw); err = iplookup_delnode(data); RWLOCK_EXIT(&ip_poolrw); @@ -151,6 +176,7 @@ int mode; break; case SIOCLOOKUPSTAT : + case SIOCLOOKUPSTATW : WRITE_ENTER(&ip_poolrw); err = iplookup_stats(data); RWLOCK_EXIT(&ip_poolrw); @@ -171,6 +197,15 @@ int mode; } +/* ------------------------------------------------------------------------ */ +/* Function: iplookup_addnode */ +/* Returns: int - 0 = success, else error */ +/* Parameters: data(I) - pointer to data from ioctl call */ +/* */ +/* Add a new data node to a lookup structure. First, check to see if the */ +/* parent structure refered to by name exists and if it does, then go on to */ +/* add a node to it. */ +/* ------------------------------------------------------------------------ */ static int iplookup_addnode(data) caddr_t data; { @@ -181,17 +216,13 @@ caddr_t data; ip_pool_t *p; int err; - err = COPYIN(data, &op, sizeof(op)); - if (err != 0) - return EFAULT; + err = 0; + BCOPYIN(data, &op, sizeof(op)); op.iplo_name[sizeof(op.iplo_name) - 1] = '\0'; switch (op.iplo_type) { case IPLT_POOL : -# if defined(_KERNEL) && defined(__osf__) - return ENOTSUP; -# else if (op.iplo_size != sizeof(node)) return EINVAL; @@ -213,7 +244,6 @@ caddr_t data; return EEXIST; err = ip_pool_insert(p, &node.ipn_addr, &node.ipn_mask, node.ipn_info); -# endif break; case IPLT_HASH : @@ -238,6 +268,14 @@ caddr_t data; } +/* ------------------------------------------------------------------------ */ +/* Function: iplookup_delnode */ +/* Returns: int - 0 = success, else error */ +/* Parameters: data(I) - pointer to data from ioctl call */ +/* */ +/* Delete a node from a lookup table by first looking for the table it is */ +/* in and then deleting the entry that gets found. */ +/* ------------------------------------------------------------------------ */ static int iplookup_delnode(data) caddr_t data; { @@ -248,17 +286,14 @@ caddr_t data; ip_pool_t *p; int err; - err = COPYIN(data, &op, sizeof(op)); - if (err != 0) - return EFAULT; + err = 0; + BCOPYIN(data, &op, sizeof(op)); + op.iplo_name[sizeof(op.iplo_name) - 1] = '\0'; switch (op.iplo_type) { case IPLT_POOL : -# if defined(_KERNEL) && defined(__osf__) - return ENOTSUP; -# else if (op.iplo_size != sizeof(node)) return EINVAL; @@ -270,17 +305,11 @@ caddr_t data; if (!p) return ESRCH; - /* - * add an entry to a pool - return an error if it already - * exists remove an entry from a pool - if it exists - * - in both cases, the pool *must* exist! - */ m = ip_pool_findeq(p, &node.ipn_addr, &node.ipn_mask); if (m == NULL) return ENOENT; err = ip_pool_remove(p, m); break; -# endif case IPLT_HASH : if (op.iplo_size != sizeof(hte)) @@ -304,33 +333,33 @@ caddr_t data; } +/* ------------------------------------------------------------------------ */ +/* Function: iplookup_addtable */ +/* Returns: int - 0 = success, else error */ +/* Parameters: data(I) - pointer to data from ioctl call */ +/* */ +/* Create a new lookup table, if one doesn't already exist using the name */ +/* for this one. */ +/* ------------------------------------------------------------------------ */ static int iplookup_addtable(data) caddr_t data; { iplookupop_t op; int err; - err = COPYIN(data, &op, sizeof(op)); - if (err != 0) - return EFAULT; + err = 0; + BCOPYIN(data, &op, sizeof(op)); + op.iplo_name[sizeof(op.iplo_name) - 1] = '\0'; - /* - * create a new pool - fail if one already exists with - * the same # - */ switch (op.iplo_type) { case IPLT_POOL : -# if defined(_KERNEL) && defined(__osf__) - return ENOTSUP; -# else if (ip_pool_find(op.iplo_unit, op.iplo_name) != NULL) err = EEXIST; else err = ip_pool_create(&op); break; -# endif case IPLT_HASH : if (fr_findhtable(op.iplo_unit, op.iplo_name) != NULL) @@ -361,9 +390,7 @@ caddr_t data; iplookupop_t op; int err; - err = COPYIN(data, &op, sizeof(op)); - if (err != 0) - return EFAULT; + BCOPYIN(data, &op, sizeof(op)); op.iplo_name[sizeof(op.iplo_name) - 1] = '\0'; if (op.iplo_arg & IPLT_ANON) @@ -376,12 +403,8 @@ caddr_t data; switch (op.iplo_type) { case IPLT_POOL : -# if defined(_KERNEL) && defined(__osf__) - return ENOTSUP; -# else err = ip_pool_destroy(&op); break; -# endif case IPLT_HASH : err = fr_removehtable(&op); @@ -409,7 +432,7 @@ caddr_t data; int err; err = 0; - (void)BCOPYIN(data, &op, sizeof(op)); + BCOPYIN(data, &op, sizeof(op)); switch (op.iplo_type) { @@ -440,16 +463,11 @@ caddr_t data; static int iplookup_flush(data) caddr_t data; { - iphtable_t *iph, *iphn; - int err, unit, type, i; - iplookupflush_t flush, opf; - ip_pool_t *p, *q; - iplookupop_t op; - size_t num; + int err, unit, num, type; + iplookupflush_t flush; - err = COPYIN(data, &flush, sizeof(flush)); - if (err != 0) - return EFAULT; + err = 0; + BCOPYIN(data, &flush, sizeof(flush)); flush.iplf_name[sizeof(flush.iplf_name) - 1] = '\0'; @@ -457,69 +475,18 @@ caddr_t data; if ((unit < 0 || unit > IPL_LOGMAX) && (unit != IPLT_ALL)) return EINVAL; - /* - * Flush all ? - * Or flush n except where n == -1 (all pools) - */ type = flush.iplf_type; err = EINVAL; num = 0; if (type == IPLT_POOL || type == IPLT_ALL) { -# if defined(_KERNEL) && defined(__osf__) - err = ENOTSUP; -# else err = 0; - if (flush.iplf_arg != IPLT_ALL) { - op.iplo_unit = unit; - (void)strncpy(op.iplo_name, flush.iplf_name, - sizeof(op.iplo_name)); - err = ip_pool_destroy(&op); - if (err == 0) - num++; - } else { - for (i = 0; i <= IPL_LOGMAX; i++) { - if (unit != IPLT_ALL && i != unit) - continue; - for (q = ip_pool_list[i]; (p = q) != NULL; ) { - op.iplo_unit = i; - (void)strncpy(op.iplo_name, p->ipo_name, - sizeof(op.iplo_name)); - q = p->ipo_next; - err = ip_pool_destroy(&op); - if (err == 0) - num++; - else - break; - } - } - } -# endif + num = ip_pool_flush(&flush); } if (type == IPLT_HASH || type == IPLT_ALL) { err = 0; - if (flush.iplf_arg != IPLT_ALL) { - opf.iplf_unit = unit; - (void)strncpy(opf.iplf_name, flush.iplf_name, - sizeof(opf.iplf_name)); - num += fr_flushhtable(&opf); - } - else { - for (i = 0; i <= IPL_LOGMAX; i++) { - if (unit != IPLT_ALL && i != unit) - continue; - for (iphn = ipf_htables[i]; - (iph = iphn) != NULL; ) { - opf.iplf_unit = i; - (void)strncpy(opf.iplf_name, - iph->iph_name, - sizeof(opf.iplf_name)); - iphn = iph->iph_next; - num += fr_flushhtable(&opf); - } - } - } + num += fr_flushhtable(&flush); } if (err == 0) { @@ -543,6 +510,7 @@ void *ptr; case IPLT_POOL : ip_pool_deref(ptr); break; + case IPLT_HASH : fr_derefhtable(ptr); break; @@ -556,11 +524,7 @@ void *ptr; /*ARGSUSED*/ int ip_lookup_ioctl(data, cmd, mode) caddr_t data; -# if defined(__NetBSD__) || defined(__OpenBSD__) -u_long cmd; -# else -int cmd; -# endif +ioctlcmd_t cmd; int mode; { return EIO; diff --git a/usr/src/common/ipf/ip_nat.c b/usr/src/uts/common/inet/ipf/ip_nat.c index 2df59b40a2..8814553e20 100644 --- a/usr/src/common/ipf/ip_nat.c +++ b/usr/src/uts/common/inet/ipf/ip_nat.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1995-2004 by Darren Reed. + * Copyright (C) 1995-2003 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * @@ -41,8 +41,12 @@ struct file; #else # include <sys/ioctl.h> #endif -#include <sys/fcntl.h> -#include <sys/protosw.h> +#if !defined(AIX) +# include <sys/fcntl.h> +#endif +#if !defined(linux) +# include <sys/protosw.h> +#endif #include <sys/socket.h> #if defined(_KERNEL) # include <sys/systm.h> @@ -77,52 +81,39 @@ struct file; #include <netinet/in_systm.h> #include <netinet/ip.h> -#ifdef __sgi -# ifdef IFF_DRVRLOCK /* IRIX6 */ -#include <sys/hashing.h> -#include <netinet/in_var.h> -# endif -#endif - #ifdef RFC1825 # include <vpn/md5.h> # include <vpn/ipsec.h> extern struct ifnet vpnif; #endif -#include <netinet/ip_var.h> +#if !defined(linux) +# include <netinet/ip_var.h> +#endif #include <netinet/tcp.h> #include <netinet/udp.h> #include <netinet/ip_icmp.h> -#include <netinet/tcpip.h> - -#if SOLARIS2 >= 10 -#include "ip_compat.h" -#include "ip_fil.h" -#include "ip_nat.h" -#include "ip_frag.h" -#include "ip_state.h" -#include "ip_proxy.h" -#else #include "netinet/ip_compat.h" +#include <netinet/tcpip.h> #include "netinet/ip_fil.h" #include "netinet/ip_nat.h" #include "netinet/ip_frag.h" #include "netinet/ip_state.h" #include "netinet/ip_proxy.h" -#endif #ifdef IPFILTER_SYNC #include "netinet/ip_sync.h" #endif #if (__FreeBSD_version >= 300000) # include <sys/malloc.h> #endif +/* END OF INCLUDES */ + #undef SOCKADDR_IN #define SOCKADDR_IN struct sockaddr_in #if !defined(lint) static const char sccsid[] = "@(#)ip_nat.c 1.11 6/5/96 (C) 1995 Darren Reed"; -static const char rcsid[] = "@(#)$Id: ip_nat.c,v 2.162 2003/07/01 18:30:20 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id: ip_nat.c,v 2.195.2.42 2005/08/11 19:51:36 darrenr Exp $"; #endif @@ -151,6 +142,7 @@ static const char rcsid[] = "@(#)$Id: ip_nat.c,v 2.162 2003/07/01 18:30:20 darre nat_t **nat_table[2] = { NULL, NULL }, *nat_instances = NULL; ipnat_t *nat_list = NULL; +u_int ipf_nattable_max = NAT_TABLE_MAX; u_int ipf_nattable_sz = NAT_TABLE_SZ; u_int ipf_natrules_sz = NAT_SIZE; u_int ipf_rdrrules_sz = RDR_SIZE; @@ -174,13 +166,14 @@ int nat_logging = 0; #endif u_long fr_defnatage = DEF_NAT_AGE, + fr_defnatipage = 120, /* 60 seconds */ fr_defnaticmpage = 6; /* 3 seconds */ natstat_t nat_stats; int fr_nat_lock = 0; int fr_nat_init = 0; -extern ipfmutex_t ipf_rw, ipf_natio, ipf_nat_new; -extern ipfrwlock_t ipf_nat; +#if SOLARIS extern int pfil_delayed_copy; +#endif static int nat_flushtable __P((void)); static int nat_clearlist __P((void)); @@ -202,10 +195,9 @@ static void nat_hostmapdel __P((struct hostmap *)); static INLINE int nat_icmpquerytype4 __P((int)); static int nat_siocaddnat __P((ipnat_t *, ipnat_t **, int)); static void nat_siocdelnat __P((ipnat_t *, ipnat_t **, int)); -static INLINE int nat_icmperrortype4 __P((int)); static INLINE int nat_finalise __P((fr_info_t *, nat_t *, natinfo_t *, tcphdr_t *, nat_t **, int)); -static INLINE void nat_resolverule __P((ipnat_t *)); +static void nat_resolverule __P((ipnat_t *)); static nat_t *fr_natclone __P((fr_info_t *, nat_t *)); static void nat_mssclamp __P((tcphdr_t *, u_32_t, fr_info_t *, u_short *)); static INLINE int nat_wildok __P((nat_t *, int, int, int, int)); @@ -232,37 +224,38 @@ int fr_natinit() if (nat_table[1] != NULL) bzero((char *)nat_table[1], ipf_nattable_sz * sizeof(nat_t *)); else - return -1; + return -2; KMALLOCS(nat_rules, ipnat_t **, sizeof(ipnat_t *) * ipf_natrules_sz); if (nat_rules != NULL) bzero((char *)nat_rules, ipf_natrules_sz * sizeof(ipnat_t *)); else - return -1; + return -3; KMALLOCS(rdr_rules, ipnat_t **, sizeof(ipnat_t *) * ipf_rdrrules_sz); if (rdr_rules != NULL) bzero((char *)rdr_rules, ipf_rdrrules_sz * sizeof(ipnat_t *)); else - return -1; + return -4; KMALLOCS(maptable, hostmap_t **, sizeof(hostmap_t *) * ipf_hostmap_sz); if (maptable != NULL) bzero((char *)maptable, sizeof(hostmap_t *) * ipf_hostmap_sz); else - return -1; + return -5; KMALLOCS(nat_stats.ns_bucketlen[0], u_long *, ipf_nattable_sz * sizeof(u_long)); if (nat_stats.ns_bucketlen[0] == NULL) - return -1; + return -6; bzero((char *)nat_stats.ns_bucketlen[0], ipf_nattable_sz * sizeof(u_long)); KMALLOCS(nat_stats.ns_bucketlen[1], u_long *, ipf_nattable_sz * sizeof(u_long)); if (nat_stats.ns_bucketlen[1] == NULL) - return -1; + return -7; + bzero((char *)nat_stats.ns_bucketlen[1], ipf_nattable_sz * sizeof(u_long)); @@ -280,16 +273,19 @@ int fr_natinit() nat_tqb[IPF_TCPS_CLOSED].ifq_ttl = fr_tcplastack; nat_tqb[IPF_TCP_NSTATES - 1].ifq_next = &nat_udptq; nat_udptq.ifq_ttl = fr_defnatage; + nat_udptq.ifq_ref = 1; nat_udptq.ifq_head = NULL; nat_udptq.ifq_tail = &nat_udptq.ifq_head; MUTEX_INIT(&nat_udptq.ifq_lock, "nat ipftq udp tab"); nat_udptq.ifq_next = &nat_icmptq; nat_icmptq.ifq_ttl = fr_defnaticmpage; + nat_icmptq.ifq_ref = 1; nat_icmptq.ifq_head = NULL; nat_icmptq.ifq_tail = &nat_icmptq.ifq_head; MUTEX_INIT(&nat_icmptq.ifq_lock, "nat icmp ipftq tab"); nat_icmptq.ifq_next = &nat_iptq; - nat_iptq.ifq_ttl = fr_defnaticmpage; + nat_iptq.ifq_ttl = fr_defnatipage; + nat_iptq.ifq_ref = 1; nat_iptq.ifq_head = NULL; nat_iptq.ifq_tail = &nat_iptq.ifq_head; MUTEX_INIT(&nat_iptq.ifq_lock, "nat ip ipftq tab"); @@ -349,6 +345,7 @@ ipnat_t *n; np = &(*np)->in_rnext; n->in_rnext = NULL; n->in_prnext = np; + n->in_hv = hv; *np = n; } @@ -380,6 +377,7 @@ ipnat_t *n; np = &(*np)->in_mnext; n->in_mnext = NULL; n->in_pmnext = np; + n->in_hv = hv; *np = n; } @@ -428,7 +426,7 @@ ipnat_t *n; /* */ /* Check if an ip address has already been allocated for a given mapping */ /* that is not doing port based translation. If is not yet allocated, then */ -/* create a new entry. */ +/* create a new entry if a non-NULL NAT rule pointer has been supplied. */ /* ------------------------------------------------------------------------ */ static struct hostmap *nat_hostmap(np, src, dst, map, port) ipnat_t *np; @@ -618,11 +616,7 @@ u_32_t n; /* Processes an ioctl call made to operate on the IP Filter NAT device. */ /* ------------------------------------------------------------------------ */ int fr_nat_ioctl(data, cmd, mode) -#if defined(__NetBSD__) || defined(__OpenBSD__) || (__FreeBSD_version >= 300003) -u_long cmd; -#else -int cmd; -#endif +ioctlcmd_t cmd; caddr_t data; int mode; { @@ -642,13 +636,13 @@ int mode; #endif nat = NULL; /* XXX gcc -Wuninitialized */ - if (cmd == (int)SIOCADNAT) { + if (cmd == (ioctlcmd_t)SIOCADNAT) { KMALLOC(nt, ipnat_t *); } else { nt = NULL; } - if ((cmd == (int)SIOCADNAT) || (cmd == (int)SIOCRMNAT)) { + if ((cmd == (ioctlcmd_t)SIOCADNAT) || (cmd == (ioctlcmd_t)SIOCRMNAT)) { if (mode & NAT_SYSSPACE) { bcopy(data, (char *)&natd, sizeof(natd)); error = 0; @@ -656,8 +650,8 @@ int mode; error = fr_inobj(data, &natd, IPFOBJ_IPNAT); } - } else if (cmd == (int)SIOCIPFFL) { /* SIOCFLNAT & SIOCCNATL */ - (void) BCOPYIN(data, &arg, sizeof(arg)); + } else if (cmd == (ioctlcmd_t)SIOCIPFFL) { /* SIOCFLNAT & SIOCCNATL */ + BCOPYIN(data, &arg, sizeof(arg)); } if (error != 0) @@ -666,8 +660,10 @@ int mode; /* * For add/delete, look to see if the NAT entry is already present */ - if ((cmd == (int)SIOCADNAT) || (cmd == (int)SIOCRMNAT)) { + if ((cmd == (ioctlcmd_t)SIOCADNAT) || (cmd == (ioctlcmd_t)SIOCRMNAT)) { nat = &natd; + if (nat->in_v == 0) /* For backward compat. */ + nat->in_v = 4; nat->in_flags &= IPN_USERFLAGS; if ((nat->in_redir & NAT_MAPBLK) == 0) { if ((nat->in_flags & IPN_SPLIT) == 0) @@ -693,7 +689,7 @@ int mode; error = EPERM; else { tmp = ipflog_clear(IPL_LOGNAT); - (void) BCOPYOUT((char *)&tmp, (char *)data, sizeof(tmp)); + BCOPYOUT((char *)&tmp, (char *)data, sizeof(tmp)); } break; } @@ -701,17 +697,17 @@ int mode; if (!(mode & FWRITE)) error = EPERM; else { - (void) BCOPYIN((char *)data, (char *)&nat_logging, + BCOPYIN((char *)data, (char *)&nat_logging, sizeof(nat_logging)); } break; case SIOCGETLG : - (void) BCOPYOUT((char *)&nat_logging, (char *)data, - sizeof(nat_logging)); + BCOPYOUT((char *)&nat_logging, (char *)data, + sizeof(nat_logging)); break; case FIONREAD : arg = iplused[IPL_LOGNAT]; - (void) BCOPYOUT(&arg, data, sizeof(arg)); + BCOPYOUT(&arg, data, sizeof(arg)); break; #endif case SIOCADNAT : @@ -755,6 +751,7 @@ int mode; nat_stats.ns_list = nat_list; nat_stats.ns_maptable = maptable; nat_stats.ns_nattab_sz = ipf_nattable_sz; + nat_stats.ns_nattab_max = ipf_nattable_max; nat_stats.ns_rultab_sz = ipf_natrules_sz; nat_stats.ns_rdrtab_sz = ipf_rdrrules_sz; nat_stats.ns_hostmap_sz = ipf_hostmap_sz; @@ -771,10 +768,11 @@ int mode; } error = fr_inobj(data, &nl, IPFOBJ_NATLOOKUP); if (error == 0) { - if (nat_lookupredir(&nl)) { + if (nat_lookupredir(&nl) != NULL) { error = fr_outobj(data, &nl, IPFOBJ_NATLOOKUP); - } else + } else { error = ESRCH; + } } if (getlock) { RWLOCK_EXIT(&ipf_nat); @@ -797,23 +795,24 @@ int mode; else error = EINVAL; if (getlock) { - MUTEX_DOWNGRADE(&ipf_nat); + RWLOCK_EXIT(&ipf_nat); } if (error == 0) { - (void) BCOPYOUT(&ret, data, sizeof(ret)); - } - if (getlock) { - RWLOCK_EXIT(&ipf_nat); + BCOPYOUT(&ret, data, sizeof(ret)); } break; case SIOCPROXY : error = appr_ioctl(data, cmd, mode); break; case SIOCSTLCK : - error = fr_lock(data, &fr_nat_lock); + if (!(mode & FWRITE)) { + error = EPERM; + } else { + fr_lock(data, &fr_nat_lock); + } break; case SIOCSTPUT : - if ((mode & FWRITE) != 0) { + if (fr_nat_lock && (mode & FWRITE)) { error = fr_natputent(data, getlock); } else { error = EACCES; @@ -878,6 +877,9 @@ int getlock; return ENOENT; } + if ((n->in_age[0] == 0) && (n->in_age[1] != 0)) + return EINVAL; + n->in_use = 0; if (n->in_redir & NAT_MAPBLK) n->in_space = USABLE_PORTS * ~ntohl(n->in_outmsk); @@ -887,8 +889,11 @@ int getlock; n->in_space = ntohl(n->in_outmsk) - ntohl(n->in_outip); else if (n->in_flags & IPN_SPLIT) n->in_space = 2; - else + else if (n->in_outmsk != 0) n->in_space = ~ntohl(n->in_outmsk); + else + n->in_space = 1; + /* * Calculate the number of valid IP addresses in the output * mapping range. In all cases, the range is inclusive of @@ -905,6 +910,7 @@ int getlock; n->in_space -= 1; } else n->in_space = 1; + if ((n->in_outmsk != 0xffffffff) && (n->in_outmsk != 0) && ((n->in_flags & (IPN_IPRANGE|IPN_SPLIT)) == 0)) n->in_nip = ntohl(n->in_outip) + 1; @@ -949,6 +955,7 @@ int getlock; n->in_space = 0xffffffff; } } + /* Otherwise, these fields are preset */ if (getlock) { @@ -973,7 +980,9 @@ int getlock; } n = NULL; nat_stats.ns_rules++; +#if SOLARIS pfil_delayed_copy = 0; +#endif if (getlock) { RWLOCK_EXIT(&ipf_nat); /* WRITE */ } @@ -991,31 +1000,18 @@ int getlock; /* from information passed to the kernel, then add it to the appropriate */ /* NAT rule table(s). */ /* ------------------------------------------------------------------------ */ -static INLINE void nat_resolverule(n) +static void nat_resolverule(n) ipnat_t *n; { - if (!strncmp(n->in_ifnames[0], "*", LIFNAMSIZ)) { - n->in_ifps[0] = NULL; - } else if (!strncmp(n->in_ifnames[0], "-", LIFNAMSIZ)) { - n->in_ifps[0] = (void *)-1; - } else { - n->in_ifps[0] = (void *)GETIFP(n->in_ifnames[0], 4); - if (n->in_ifps[0] == NULL) - n->in_ifps[0] = (void *)-1; - } + n->in_ifnames[0][LIFNAMSIZ - 1] = '\0'; + n->in_ifps[0] = fr_resolvenic(n->in_ifnames[0], 4); + + n->in_ifnames[1][LIFNAMSIZ - 1] = '\0'; if (n->in_ifnames[1][0] == '\0') { (void) strncpy(n->in_ifnames[1], n->in_ifnames[0], LIFNAMSIZ); n->in_ifps[1] = n->in_ifps[0]; } else { - if (!strncmp(n->in_ifnames[1], "*", LIFNAMSIZ)) { - n->in_ifps[1] = NULL; - } else if (!strncmp(n->in_ifnames[1], "-", LIFNAMSIZ)) { - n->in_ifps[1] = (void *)-1; - } else { - n->in_ifps[1] = (void *)GETIFP(n->in_ifnames[1], 4); - if (n->in_ifps[1] == NULL) - n->in_ifps[1] = (void *)-1; - } + n->in_ifps[1] = fr_resolvenic(n->in_ifnames[0], 4); } if (n->in_plabel[0] != '\0') { @@ -1052,11 +1048,17 @@ int getlock; rdr_masks = 0; } - if (n->in_tqehead[0] != NULL) - fr_deletetimeoutqueue(n->in_tqehead[0]); + if (n->in_tqehead[0] != NULL) { + if (fr_deletetimeoutqueue(n->in_tqehead[0]) == 0) { + fr_freetimeoutqueue(n->in_tqehead[1]); + } + } - if (n->in_tqehead[1] != NULL) - fr_deletetimeoutqueue(n->in_tqehead[1]); + if (n->in_tqehead[1] != NULL) { + if (fr_deletetimeoutqueue(n->in_tqehead[1]) == 0) { + fr_freetimeoutqueue(n->in_tqehead[1]); + } + } *np = n->in_next; @@ -1065,8 +1067,10 @@ int getlock; appr_free(n->in_apr); KFREE(n); nat_stats.ns_rules--; +#if SOLARIS if (nat_stats.ns_rules == 0) pfil_delayed_copy = 1; +#endif } else { n->in_flags |= IPN_DELETE; n->in_next = NULL; @@ -1095,7 +1099,7 @@ caddr_t data; nat_t *nat, *n; natget_t ng; - (void) BCOPYIN(data, &ng, sizeof(ng)); + BCOPYIN(data, &ng, sizeof(ng)); nat = ng.ng_ptr; if (!nat) { @@ -1105,7 +1109,7 @@ caddr_t data; * Empty list so the size returned is 0. Simple. */ if (nat == NULL) { - (void) BCOPYOUT(&ng, data, sizeof(ng)); + BCOPYOUT(&ng, data, sizeof(ng)); return 0; } } else { @@ -1126,14 +1130,13 @@ caddr_t data; */ ng.ng_sz = sizeof(nat_save_t); aps = nat->nat_aps; - if ((aps != NULL) && (aps->aps_data != 0)) { - ng.ng_sz += sizeof(ap_session_t); - ng.ng_sz += aps->aps_psiz; - if (ng.ng_sz > 4) - ng.ng_sz -= 4; /* XXX - sizeof(ipn_data) */ + if (aps != NULL) { + ng.ng_sz += sizeof(ap_session_t) - 4; + if (aps->aps_data != 0) + ng.ng_sz += aps->aps_psiz; } - (void) BCOPYOUT(&ng, data, sizeof(ng)); + BCOPYOUT(&ng, data, sizeof(ng)); return 0; } @@ -1151,22 +1154,30 @@ caddr_t data; static int fr_natgetent(data) caddr_t data; { + int error, outsize; ap_session_t *aps; - nat_save_t ipn; + nat_save_t *ipn, ipns; nat_t *n, *nat; - int error; - error = fr_inobj(data, &ipn, IPFOBJ_NATSAVE); + error = fr_inobj(data, &ipns, IPFOBJ_NATSAVE); if (error != 0) return error; - nat = ipn.ipn_next; + if ((ipns.ipn_dsize < sizeof(ipns)) || (ipns.ipn_dsize > 81920)) + return EINVAL; + + KMALLOCS(ipn, nat_save_t *, ipns.ipn_dsize); + if (ipn == NULL) + return ENOMEM; + + ipn->ipn_dsize = ipns.ipn_dsize; + nat = ipns.ipn_next; if (nat == NULL) { nat = nat_instances; if (nat == NULL) { if (nat_instances == NULL) - return ENOENT; - return 0; + error = ENOENT; + goto finished; } } else { /* @@ -1177,43 +1188,32 @@ caddr_t data; for (n = nat_instances; n; n = n->nat_next) if (n == nat) break; - if (n == NULL) - return ESRCH; + if (n == NULL) { + error = ESRCH; + goto finished; + } } + ipn->ipn_next = nat->nat_next; /* - * Copy out the NAT structure. + * Copy the NAT structure. */ - error = copyoutptr((char *)nat, - (char *)data + offsetof(struct nat_save, ipn_nat), - sizeof(struct nat)); - if (error != 0) - return error; + bcopy((char *)nat, &ipn->ipn_nat, sizeof(*nat)); /* * If we have a pointer to the NAT rule it belongs to, save that too. */ - if (nat->nat_ptr != NULL) { - error = copyoutptr((char *)nat->nat_ptr, - (char *)data + - offsetof(struct nat_save, ipn_ipnat), - sizeof(struct ipnat)); - if (error != 0) - return error; - } + if (nat->nat_ptr != NULL) + bcopy((char *)nat->nat_ptr, (char *)&ipn->ipn_ipnat, + sizeof(ipn->ipn_ipnat)); /* * If we also know the NAT entry has an associated filter rule, * save that too. */ - if (nat->nat_fr != NULL) { - error = copyoutptr((char *)nat->nat_fr, - (char *)data + - offsetof(struct nat_save, ipn_rule), - sizeof(struct frentry)); - if (error != 0) - return error; - } + if (nat->nat_fr != NULL) + bcopy((char *)nat->nat_fr, (char *)&ipn->ipn_fr, + sizeof(ipn->ipn_fr)); /* * Last but not least, if there is an application proxy session set @@ -1221,31 +1221,31 @@ caddr_t data; * private data saved along side it by the proxy. */ aps = nat->nat_aps; + outsize = ipn->ipn_dsize - sizeof(*ipn) + sizeof(ipn->ipn_data); if (aps != NULL) { - ipn.ipn_dsize = sizeof(*aps); - if (aps->aps_data) - ipn.ipn_dsize += aps->aps_psiz; - error = copyoutptr((char *)&ipn.ipn_dsize, - (char *)data + - offsetof(struct nat_save, ipn_dsize), - sizeof(ipn.ipn_dsize)); - if (error != 0) - return error; - - error = copyoutptr((char *)aps, (char *)data + - offsetof(struct nat_save, ipn_data), - sizeof(*aps)); - if (error != 0) - return error; - - if (aps->aps_psiz > 0) { - error = copyoutptr((char *)aps->aps_data, - (char *)data + sizeof(*aps) + - offsetof(struct nat_save, ipn_data), - aps->aps_psiz); - if (error != 0) - return error; + char *s; + + if (outsize < sizeof(*aps)) { + error = ENOBUFS; + goto finished; } + + s = ipn->ipn_data; + bcopy((char *)aps, s, sizeof(*aps)); + s += sizeof(*aps); + outsize -= sizeof(*aps); + if ((aps->aps_data != NULL) && (outsize >= aps->aps_psiz)) + bcopy(aps->aps_data, s, aps->aps_psiz); + else + error = ENOBUFS; + } + if (error == 0) { + error = fr_outobjsz(data, ipn, IPFOBJ_NATSAVE, ipns.ipn_dsize); + } + +finished: + if (ipn != NULL) { + KFREES(ipn, ipns.ipn_dsize); } return error; } @@ -1254,8 +1254,10 @@ caddr_t data; /* ------------------------------------------------------------------------ */ /* Function: fr_natputent */ /* Returns: int - 0 == success, != 0 is the error value. */ -/* Parameters: data(I) - pointer to natget structure with NAT structure */ -/* information to load into the kernel. */ +/* Parameters: data(I) - pointer to natget structure with NAT */ +/* structure information to load into the kernel */ +/* getlock(I) - flag indicating whether or not a write lock */ +/* on ipf_nat is already held. */ /* */ /* Handle SIOCSTPUT. */ /* Loads a NAT table entry from user space, including a NAT rule, proxy and */ @@ -1277,22 +1279,36 @@ int getlock; if (error != 0) return error; + /* + * Initialise early because of code at junkput label. + */ + in = NULL; + aps = NULL; nat = NULL; - if (ipn.ipn_dsize != 0) { - KMALLOCS(ipnn, nat_save_t *, sizeof(ipn) + ipn.ipn_dsize - - sizeof(ipn.ipn_data)); + ipnn = NULL; + + /* + * New entry, copy in the rest of the NAT entry if it's size is more + * than just the nat_t structure. + */ + fr = NULL; + if (ipn.ipn_dsize > sizeof(ipn)) { + if (ipn.ipn_dsize > 81920) { + error = ENOMEM; + goto junkput; + } + + KMALLOCS(ipnn, nat_save_t *, ipn.ipn_dsize); if (ipnn == NULL) return ENOMEM; - /* XXX should use fr_inobj */ - error = copyinptr(data, ipnn, sizeof(ipn) + ipn.ipn_dsize - - sizeof(ipn.ipn_data)); + error = fr_inobjsz(data, ipnn, IPFOBJ_NATSAVE, ipn.ipn_dsize); if (error != 0) { error = EFAULT; goto junkput; } } else - ipnn = NULL; + ipnn = &ipn; KMALLOC(nat, nat_t *); if (nat == NULL) { @@ -1300,40 +1316,33 @@ int getlock; goto junkput; } - bcopy((char *)&ipn.ipn_nat, (char *)nat, sizeof(*nat)); + bcopy((char *)&ipnn->ipn_nat, (char *)nat, sizeof(*nat)); /* * Initialize all these so that nat_delete() doesn't cause a crash. */ - MUTEX_NUKE(&nat->nat_lock); - nat->nat_phnext[0] = NULL; - nat->nat_phnext[1] = NULL; - fr = nat->nat_fr; - nat->nat_fr = NULL; - aps = nat->nat_aps; - nat->nat_aps = NULL; - in = nat->nat_ptr; - nat->nat_ptr = NULL; - nat->nat_hm = NULL; - nat->nat_data = NULL; + bzero((char *)nat, offsetof(struct nat, nat_tqe)); + nat->nat_tqe.tqe_pnext = NULL; + nat->nat_tqe.tqe_next = NULL; + nat->nat_tqe.tqe_ifq = NULL; + nat->nat_tqe.tqe_parent = nat; /* * Restore the rule associated with this nat session */ + in = ipnn->ipn_nat.nat_ptr; if (in != NULL) { KMALLOC(in, ipnat_t *); + nat->nat_ptr = in; if (in == NULL) { error = ENOMEM; goto junkput; } - nat->nat_ptr = in; - bcopy((char *)&ipn.ipn_ipnat, (char *)in, sizeof(*in)); + bzero((char *)in, offsetof(struct ipnat, in_next6)); + bcopy((char *)&ipnn->ipn_ipnat, (char *)in, sizeof(*in)); in->in_use = 1; in->in_flags |= IPN_DELETE; - in->in_next = NULL; - in->in_rnext = NULL; - in->in_prnext = NULL; - in->in_mnext = NULL; - in->in_pmnext = NULL; + + ATOMIC_INC(nat_stats.ns_rules); nat_resolverule(in); } @@ -1346,7 +1355,7 @@ int getlock; if (nat->nat_dir == NAT_OUTBOUND) { fin.fin_data[0] = ntohs(nat->nat_oport); fin.fin_data[1] = ntohs(nat->nat_outport); - fin.fin_ifp = nat->nat_ifps[0]; + fin.fin_ifp = nat->nat_ifps[1]; if (getlock) { READ_ENTER(&ipf_nat); } @@ -1362,12 +1371,12 @@ int getlock; } else if (nat->nat_dir == NAT_INBOUND) { fin.fin_data[0] = ntohs(nat->nat_inport); fin.fin_data[1] = ntohs(nat->nat_oport); - fin.fin_ifp = nat->nat_ifps[1]; + fin.fin_ifp = nat->nat_ifps[0]; if (getlock) { READ_ENTER(&ipf_nat); } n = nat_outlookup(&fin, nat->nat_flags, fin.fin_p, - nat->nat_inip, nat->nat_oip); + nat->nat_outip, nat->nat_oip); if (getlock) { RWLOCK_EXIT(&ipf_nat); } @@ -1384,19 +1393,24 @@ int getlock; * Restore ap_session_t structure. Include the private data allocated * if it was there. */ + aps = nat->nat_aps; if (aps != NULL) { KMALLOC(aps, ap_session_t *); + nat->nat_aps = aps; if (aps == NULL) { error = ENOMEM; goto junkput; } - nat->nat_aps = aps; - aps->aps_next = ap_sess_list; - ap_sess_list = aps; bcopy(ipnn->ipn_data, (char *)aps, sizeof(*aps)); - if (in) + if (in != NULL) aps->aps_apr = in->in_apr; + else + aps->aps_apr = NULL; if (aps->aps_psiz != 0) { + if (aps->aps_psiz > 81920) { + error = ENOMEM; + goto junkput; + } KMALLOCS(aps->aps_data, void *, aps->aps_psiz); if (aps->aps_data == NULL) { error = ENOMEM; @@ -1414,34 +1428,34 @@ int getlock; * If there was a filtering rule associated with this entry then * build up a new one. */ + fr = nat->nat_fr; if (fr != NULL) { - if (nat->nat_flags & SI_NEWFR) { + if ((nat->nat_flags & SI_NEWFR) != 0) { KMALLOC(fr, frentry_t *); nat->nat_fr = fr; if (fr == NULL) { error = ENOMEM; goto junkput; } - bcopy((char *)&ipn.ipn_fr, (char *)fr, sizeof(*fr)); + ipnn->ipn_nat.nat_fr = fr; + fr->fr_ref = 1; + (void) fr_outobj(data, ipnn, IPFOBJ_NATSAVE); + bcopy((char *)&ipnn->ipn_fr, (char *)fr, sizeof(*fr)); MUTEX_NUKE(&fr->fr_lock); MUTEX_INIT(&fr->fr_lock, "nat-filter rule lock"); - ipn.ipn_nat.nat_fr = fr; - (void) fr_outobj(&ipn, data, IPFOBJ_NATSAVE); } else { - if (getlock) { - READ_ENTER(&ipf_nat); - } + READ_ENTER(&ipf_nat); for (n = nat_instances; n; n = n->nat_next) if (n->nat_fr == fr) break; + if (n != NULL) { MUTEX_ENTER(&fr->fr_lock); fr->fr_ref++; MUTEX_EXIT(&fr->fr_lock); } - if (getlock) { - RWLOCK_EXIT(&ipf_nat); - } + RWLOCK_EXIT(&ipf_nat); + if (!n) { error = ESRCH; goto junkput; @@ -1449,24 +1463,34 @@ int getlock; } } + if (ipnn != &ipn) { + KFREES(ipnn, ipn.ipn_dsize); + ipnn = NULL; + } + if (getlock) { WRITE_ENTER(&ipf_nat); } - error = nat_insert(nat); + error = nat_insert(nat, nat->nat_rev); + if ((error == 0) && (aps != NULL)) { + aps->aps_next = ap_sess_list; + ap_sess_list = aps; + } if (getlock) { RWLOCK_EXIT(&ipf_nat); } - if (error == 0) { - if (ipnn != NULL) { - KFREES(ipnn, sizeof (ipn) + ipn.ipn_dsize); - } - return (0); - } + + if (error == 0) + return 0; + error = ENOMEM; junkput: - if (ipnn != NULL) { - KFREES(ipnn, sizeof (ipn) + ipn.ipn_dsize); + if (fr != NULL) + (void) fr_derefrule(&fr); + + if ((ipnn != NULL) && (ipnn != &ipn)) { + KFREES(ipnn, ipn.ipn_dsize); } if (nat != NULL) { if (aps != NULL) { @@ -1482,7 +1506,7 @@ junkput: } KFREE(nat); } - return (error); + return error; } @@ -1500,9 +1524,7 @@ static void nat_delete(nat, logtype) struct nat *nat; int logtype; { - ipftqent_t *tqe; struct ipnat *ipn; - ipftq_t *ifq; if (logtype != 0 && nat_logging != 0) nat_log(nat, logtype); @@ -1547,18 +1569,7 @@ int logtype; nat->nat_me = NULL; } - tqe = &nat->nat_tqe; - ifq = tqe->tqe_ifq; - if (ifq != NULL) { - *tqe->tqe_pnext = tqe->tqe_next; - if (tqe->tqe_next) - tqe->tqe_next->tqe_pnext = tqe->tqe_pnext; - else - ifq->ifq_tail = tqe->tqe_pnext; - tqe->tqe_ifq = NULL; - if ((ifq->ifq_flags & IFQF_USER) != 0) - fr_deletetimeoutqueue(ifq); - } + fr_deletequeueentry(&nat->nat_tqe); nat->nat_ref--; if (nat->nat_ref > 0) { @@ -1591,8 +1602,10 @@ int logtype; appr_free(ipn->in_apr); KFREE(ipn); nat_stats.ns_rules--; +#if SOLARIS if (nat_stats.ns_rules == 0) pfil_delayed_copy = 1; +#endif } } @@ -1682,7 +1695,9 @@ static int nat_clearlist() } i++; } +#if SOLARIS pfil_delayed_copy = 1; +#endif nat_masks = 0; rdr_masks = 0; return i; @@ -1699,6 +1714,8 @@ static int nat_clearlist() /* */ /* Given an empty NAT structure, populate it with new information about a */ /* new NAT session, as defined by the matching NAT rule. */ +/* ni.nai_ip is passed in uninitialised and must be set, in host byte order,*/ +/* to the new IP address for the translation. */ /* ------------------------------------------------------------------------ */ static INLINE int nat_newmap(fin, nat, ni) fr_info_t *fin; @@ -1910,9 +1927,9 @@ natinfo_t *ni; nat->nat_hm = nat_hostmap(np, fin->fin_src, fin->fin_dst, nat->nat_outip, 0); - /* + /* * The ICMP checksum does not have a pseudo header containing - * the IP addresses + * the IP addresses */ ni->nai_sum1 = LONG_SUM(ntohl(fin->fin_saddr)); ni->nai_sum2 = LONG_SUM(in.s_addr); @@ -1921,15 +1938,18 @@ natinfo_t *ni; ni->nai_sum2 += ntohs(port); } - if (flags & IPN_TCPUDPICMP) { + if (flags & IPN_TCPUDP) { nat->nat_inport = sport; nat->nat_outport = port; /* sport */ nat->nat_oport = dport; ((tcphdr_t *)fin->fin_dp)->th_sport = port; - } if (flags & IPN_ICMPQUERY) { + } else if (flags & IPN_ICMPQUERY) { ((icmphdr_t *)fin->fin_dp)->icmp_id = port; + nat->nat_inport = port; + nat->nat_outport = port; } - ni->nai_ip.s_addr = htonl(in.s_addr); + + ni->nai_ip.s_addr = in.s_addr; ni->nai_port = port; ni->nai_nport = dport; return 0; @@ -1945,6 +1965,8 @@ natinfo_t *ni; /* ni(I) - pointer to structure with misc. information needed */ /* to create new NAT entry. */ /* */ +/* ni.nai_ip is passed in uninitialised and must be set, in host byte order,*/ +/* to the new IP address for the translation. */ /* ------------------------------------------------------------------------ */ static INLINE int nat_newrdr(fin, nat, ni) fr_info_t *fin; @@ -1960,7 +1982,7 @@ natinfo_t *ni; move = 1; hm = NULL; - in = ni->nai_ip; + in.s_addr = 0; np = ni->nai_np; flags = ni->nai_flags; sport = ni->nai_sport; @@ -1978,7 +2000,7 @@ natinfo_t *ni; hm = nat_hostmap(NULL, fin->fin_src, fin->fin_dst, in, (u_32_t)dport); if (hm != NULL) { - ni->nai_ip.s_addr = hm->hm_mapip.s_addr; + in.s_addr = ntohl(hm->hm_mapip.s_addr); np = hm->hm_ipnat; ni->nai_np = np; move = 0; @@ -2031,8 +2053,9 @@ natinfo_t *ni; /* * map the address block in a 1:1 fashion */ - in.s_addr |= ntohl(fin->fin_daddr & ~np->in_inmsk); - + in.s_addr = np->in_inip; + in.s_addr |= fin->fin_daddr & ~np->in_inmsk; + in.s_addr = ntohl(in.s_addr); } else { in.s_addr = ntohl(np->in_inip); } @@ -2044,7 +2067,8 @@ natinfo_t *ni; * Whilst not optimized for the case where * pmin == pmax, the gain is not significant. */ - if (np->in_pmin != np->in_pmax) { + if (((np->in_flags & IPN_FIXEDDPORT) == 0) && + (np->in_pmin != np->in_pmax)) { nport = ntohs(dport) - ntohs(np->in_pmin) + ntohs(np->in_pnext); nport = htons(nport); @@ -2070,7 +2094,7 @@ natinfo_t *ni; ni->nai_sum1 = LONG_SUM(ntohl(fin->fin_daddr)) + ntohs(dport); ni->nai_sum2 = LONG_SUM(in.s_addr) + ntohs(nport); - ni->nai_ip.s_addr = htonl(in.s_addr); + ni->nai_ip.s_addr = in.s_addr; ni->nai_nport = nport; ni->nai_port = sport; @@ -2081,6 +2105,8 @@ natinfo_t *ni; ((tcphdr_t *)fin->fin_dp)->th_dport = nport; } else if (flags & IPN_ICMPQUERY) { ((icmphdr_t *)fin->fin_dp)->icmp_id = nport; + nat->nat_inport = nport; + nat->nat_outport = nport; } return move; @@ -2122,9 +2148,14 @@ int direction; u_32_t sumd; int move; #if SOLARIS && defined(_KERNEL) && (SOLARIS2 >= 6) && defined(ICK_M_CTL_MAGIC) - qif_t *qf = fin->fin_qif; + qpktinfo_t *qpi = fin->fin_qpi; #endif + if (nat_stats.ns_inuse >= ipf_nattable_max) { + nat_stats.ns_memfail++; + return NULL; + } + move = 1; nflags = np->in_flags & flags; nflags &= NAT_FROMRULE; @@ -2137,6 +2168,17 @@ int direction; KMALLOC(nat, nat_t *); if (nat == NULL) { nat_stats.ns_memfail++; + /* + * Try to automatically tune the max # of entries in the + * table allowed to be less than what will cause kmem_alloc() + * to fail and try to eliminate panics due to out of memory + * conditions arising. + */ + if (ipf_nattable_max > ipf_nattable_sz) { + ipf_nattable_max = nat_stats.ns_inuse - 100; + printf("ipf_nattable_max reduced to %d\n", + ipf_nattable_max); + } return NULL; } @@ -2147,15 +2189,15 @@ int direction; } else if (flags & IPN_ICMPQUERY) { /* * In the ICMP query NAT code, we translate the ICMP id fields - * to make them unique. This is indepedent of the ICMP type - * (e.g. in the unlikely event that a host sends an echo and - * an tstamp request with the same id, both packets will have + * to make them unique. This is indepedent of the ICMP type + * (e.g. in the unlikely event that a host sends an echo and + * an tstamp request with the same id, both packets will have * their ip address/id field changed in the same way). */ /* The icmp_id field is used by the sender to identify the - * process making the icmp request. (the receiver justs - * copies it back in its response). So, it closely matches - * the concept of source port. We overlay sport, so we can + * process making the icmp request. (the receiver justs + * copies it back in its response). So, it closely matches + * the concept of source port. We overlay sport, so we can * maximally reuse the existing code. */ ni.nai_sport = ((icmphdr_t *)fin->fin_dp)->icmp_id; @@ -2165,7 +2207,9 @@ int direction; bzero((char *)nat, sizeof(*nat)); nat->nat_flags = flags; - MUTEX_ENTER(&ipf_nat_new); + if ((flags & NAT_SLAVE) == 0) { + MUTEX_ENTER(&ipf_nat_new); + } /* * Search the current table for a match. @@ -2179,34 +2223,30 @@ int direction; natl = nat_outlookup(fin, nflags, (u_int)fin->fin_p, fin->fin_src, fin->fin_dst); if (natl != NULL) { - MUTEX_EXIT(&ipf_nat_new); - return natl; + nat = natl; + goto done; } move = nat_newmap(fin, nat, &ni); - if (move == -1) { - MUTEX_EXIT(&ipf_nat_new); + if (move == -1) goto badnat; - } np = ni.nai_np; in = ni.nai_ip; } else { - /* + /* * NAT_INBOUND is used only for redirects rules */ natl = nat_inlookup(fin, nflags, (u_int)fin->fin_p, fin->fin_src, fin->fin_dst); if (natl != NULL) { - MUTEX_EXIT(&ipf_nat_new); - return natl; + nat = natl; + goto done; } move = nat_newrdr(fin, nat, &ni); - if (move == -1) { - MUTEX_EXIT(&ipf_nat_new); + if (move == -1) goto badnat; - } np = ni.nai_np; in = ni.nai_ip; @@ -2235,14 +2275,14 @@ int direction; CALC_SUMD(ni.nai_sum1, ni.nai_sum2, sumd); nat->nat_sumd[0] = (sumd & 0xffff) + (sumd >> 16); #if SOLARIS && defined(_KERNEL) && (SOLARIS2 >= 6) && defined(ICK_M_CTL_MAGIC) - if ((flags & IPN_TCPUDP) && dohwcksum && + if ((flags & IPN_TCP) && dohwcksum && #ifndef IRE_ILL_CN - (((ill_t *)qf->qf_ill)->ill_ick.ick_magic == ICK_M_CTL_MAGIC)) { -#else - (((s_ill_t *)qf->qf_ill)->ill_ick.ick_magic == ICK_M_CTL_MAGIC)) { + (((ill_t *)qpi->qpi_ill)->ill_ick.ick_magic == ICK_M_CTL_MAGIC)) { +#else + (((s_ill_t *)qpi->qpi_ill)->ill_ick.ick_magic == ICK_M_CTL_MAGIC)) { #endif /* IRE_ILL_CN */ if (direction == NAT_OUTBOUND) - ni.nai_sum1 = LONG_SUM(ntohl(in.s_addr)); + ni.nai_sum1 = LONG_SUM(in.s_addr); else ni.nai_sum1 = LONG_SUM(ntohl(fin->fin_saddr)); ni.nai_sum1 += LONG_SUM(ntohl(fin->fin_daddr)); @@ -2259,7 +2299,7 @@ int direction; else ni.nai_sum1 = LONG_SUM(ntohl(fin->fin_daddr)); - ni.nai_sum2 = LONG_SUM(ntohl(in.s_addr)); + ni.nai_sum2 = LONG_SUM(in.s_addr); CALC_SUMD(ni.nai_sum1, ni.nai_sum2, sumd); nat->nat_ipsumd = (sumd & 0xffff) + (sumd >> 16); @@ -2272,22 +2312,22 @@ int direction; } if (nat_finalise(fin, nat, &ni, tcp, natsave, direction) == -1) { - if ((hm = nat->nat_hm) != NULL) - nat_hostmapdel(hm); - MUTEX_EXIT(&ipf_nat_new); - KFREE(nat); - return NULL; + goto badnat; } if (flags & SI_WILDP) nat_stats.ns_wilds++; - MUTEX_EXIT(&ipf_nat_new); - return nat; + goto done; badnat: nat_stats.ns_badnat++; if ((hm = nat->nat_hm) != NULL) nat_hostmapdel(hm); KFREE(nat); - return NULL; + nat = NULL; +done: + if ((flags & NAT_SLAVE) == 0) { + MUTEX_EXIT(&ipf_nat_new); + } + return nat; } @@ -2317,12 +2357,7 @@ int direction; np = ni->nai_np; - if (np->in_ifps[0] != NULL) { - (void) COPYIFNAME(np->in_ifps[0], nat->nat_ifnames[0]); - } - if (np->in_ifps[1] != NULL) { - (void) COPYIFNAME(np->in_ifps[1], nat->nat_ifnames[1]); - } + COPYIFNAME(fin->fin_ifp, nat->nat_ifnames[0]); #ifdef IPFILTER_SYNC if ((nat->nat_flags & SI_CLONE) == 0) nat->nat_sync = ipfsync_new(SMC_NAT, fin, nat); @@ -2330,8 +2365,7 @@ int direction; nat->nat_me = natsave; nat->nat_dir = direction; - nat->nat_ifps[0] = np->in_ifps[0]; - nat->nat_ifps[1] = np->in_ifps[1]; + nat->nat_ifps[0] = fin->fin_ifp; nat->nat_ptr = np; nat->nat_p = fin->fin_p; nat->nat_mssclamp = np->in_mssclamp; @@ -2342,9 +2376,9 @@ int direction; if (appr_new(fin, nat) == -1) return -1; - if (nat_logging) - nat_log(nat, (u_int)np->in_redir); - if (nat_insert(nat) == 0) { + if (nat_insert(nat, fin->fin_rev) == 0) { + if (nat_logging) + nat_log(nat, (u_int)np->in_redir); np->in_use++; if (fr != NULL) { MUTEX_ENTER(&fr->fr_lock); @@ -2362,20 +2396,20 @@ int direction; /* ------------------------------------------------------------------------ */ -/* Function: nat_insert */ -/* Returns: int - 0 == sucess, -1 == failure */ -/* Parameters: nat(I) - pointer to NAT structure */ -/* Write Lock: ipf_nat */ +/* Function: nat_insert */ +/* Returns: int - 0 == sucess, -1 == failure */ +/* Parameters: nat(I) - pointer to NAT structure */ +/* rev(I) - flag indicating forward/reverse direction of packet */ +/* Write Lock: ipf_nat */ /* */ /* Insert a NAT entry into the hash tables for searching and add it to the */ /* list of active NAT entries. Adjust global counters when complete. */ /* ------------------------------------------------------------------------ */ -int nat_insert(nat) +int nat_insert(nat, rev) nat_t *nat; +int rev; { - ipftqent_t *tqe; u_int hv1, hv2; - ipftq_t *ifq; nat_t **natp; /* @@ -2399,49 +2433,32 @@ nat_t *nat; } if (nat_stats.ns_bucketlen[0][hv1] >= fr_nat_maxbucket || - nat_stats.ns_bucketlen[1][hv2] >= fr_nat_maxbucket) + nat_stats.ns_bucketlen[1][hv2] >= fr_nat_maxbucket) { return -1; + } nat->nat_hv[0] = hv1; nat->nat_hv[1] = hv2; MUTEX_INIT(&nat->nat_lock, "nat entry lock"); + nat->nat_rev = rev; nat->nat_ref = 1; nat->nat_bytes[0] = 0; nat->nat_pkts[0] = 0; nat->nat_bytes[1] = 0; nat->nat_pkts[1] = 0; - if (nat->nat_ptr != NULL) - ifq = nat->nat_ptr->in_tqehead[0]; - else - ifq = NULL; - if (ifq == NULL) { - if (nat->nat_p == IPPROTO_UDP) - ifq = &nat_udptq; - else if (nat->nat_p == IPPROTO_ICMP) - ifq = &nat_icmptq; - else if (nat->nat_p == IPPROTO_TCP) - ifq = nat_tqb; - else - ifq = &nat_iptq; - } - tqe = &nat->nat_tqe; - tqe->tqe_die = fr_ticks + ifq->ifq_ttl; - tqe->tqe_ifq = ifq; - tqe->tqe_parent = nat; - tqe->tqe_next = NULL; - - nat->nat_ifnames[0][sizeof(nat->nat_ifnames[0]) - 1] = '\0'; - if (nat->nat_ifnames[0][0] != '\0') { - nat->nat_ifps[0] = GETIFP(nat->nat_ifnames[0], 4); - } - nat->nat_ifnames[1][sizeof(nat->nat_ifnames[1]) - 1] = '\0'; - if (nat->nat_ifnames[1][0] != '\0') { - nat->nat_ifps[1] = GETIFP(nat->nat_ifnames[1], 4); + + nat->nat_ifnames[0][LIFNAMSIZ - 1] = '\0'; + nat->nat_ifps[0] = fr_resolvenic(nat->nat_ifnames[0], 4); + + if (nat->nat_ifnames[1][0] !='\0') { + nat->nat_ifnames[1][LIFNAMSIZ - 1] = '\0'; + nat->nat_ifps[1] = fr_resolvenic(nat->nat_ifnames[1], 4); } else { (void) strncpy(nat->nat_ifnames[1], nat->nat_ifnames[0], - sizeof(nat->nat_ifnames[1])); + LIFNAMSIZ); + nat->nat_ifnames[1][LIFNAMSIZ - 1] = '\0'; nat->nat_ifps[1] = nat->nat_ifps[0]; } @@ -2467,11 +2484,7 @@ nat_t *nat; *natp = nat; nat_stats.ns_bucketlen[1][hv2]++; - MUTEX_ENTER(&ifq->ifq_lock); - tqe->tqe_pnext = ifq->ifq_tail; - *ifq->ifq_tail = tqe; - ifq->ifq_tail = &tqe->tqe_next; - MUTEX_EXIT(&ifq->ifq_lock); + fr_setnatqueue(nat, rev); nat_stats.ns_added++; nat_stats.ns_inuse++; @@ -2486,44 +2499,36 @@ nat_t *nat; /* dir(I) - direction of packet (in/out) */ /* */ /* Check if the ICMP error message is related to an existing TCP, UDP or */ -/* ICMP query nat entry. */ +/* ICMP query nat entry. It is assumed that the packet is already of the */ +/* the required length. */ /* ------------------------------------------------------------------------ */ nat_t *nat_icmperrorlookup(fin, dir) fr_info_t *fin; int dir; { - int flags = 0, type, minlen; - icmphdr_t *icmp, *orgicmp; + int flags = 0, minlen; + icmphdr_t *orgicmp; tcphdr_t *tcp = NULL; + u_short data[2]; + nat_t *nat; ip_t *oip; u_int p; - icmp = fin->fin_dp; /* * Does it at least have the return (basic) IP header ? * Only a basic IP header (no options) should be with an ICMP error - * header. - */ - if (fin->fin_hlen != sizeof(ip_t) || - (fin->fin_plen < ICMPERR_MINPKTLEN)) - return NULL; - - type = icmp->icmp_type; - - /* - * If it's not an error type, then return. + * header. Also, if it's not an error type, then return. */ - if (!nat_icmperrortype4(type)) + if ((fin->fin_hlen != sizeof(ip_t)) || !(fin->fin_flx & FI_ICMPERR)) return NULL; /* - * Check packet size + * Check packet size */ oip = (ip_t *)((char *)fin->fin_dp + 8); minlen = IP_HL(oip) << 2; - if (minlen < sizeof(ip_t)) - return NULL; - if (fin->fin_plen < ICMPERR_IPICMPHLEN + minlen) + if ((minlen < sizeof(ip_t)) || + (fin->fin_plen < ICMPERR_IPICMPHLEN + minlen)) return NULL; /* * Is the buffer big enough for all of it ? It's the size of the IP @@ -2542,13 +2547,17 @@ int dir; # if defined(MENTAT) if ((char *)oip + fin->fin_dlen - ICMPERR_ICMPHLEN > (char *)m->b_wptr) return NULL; -# else +# else if ((char *)oip + fin->fin_dlen - ICMPERR_ICMPHLEN > (char *)fin->fin_ip + M_LEN(m)) - return NULL; -# endif - } + return NULL; +# endif + } #endif + + if (fin->fin_daddr != oip->ip_src.s_addr) + return NULL; + p = oip->ip_p; if (p == IPPROTO_TCP) flags = IPN_TCP; @@ -2559,25 +2568,30 @@ int dir; /* see if this is related to an ICMP query */ if (nat_icmpquerytype4(orgicmp->icmp_type)) { - flags = IPN_ICMPQUERY; + data[0] = fin->fin_data[0]; + data[1] = fin->fin_data[1]; + fin->fin_data[0] = 0; + fin->fin_data[1] = orgicmp->icmp_id; + + flags = IPN_ICMPERR|IPN_ICMPQUERY; /* * NOTE : dir refers to the direction of the original * ip packet. By definition the icmp error * message flows in the opposite direction. */ if (dir == NAT_INBOUND) - return nat_inlookup(fin, flags, p, oip->ip_dst, - oip->ip_src); + nat = nat_inlookup(fin, flags, p, oip->ip_dst, + oip->ip_src); else - return nat_outlookup(fin, flags, p, oip->ip_dst, - oip->ip_src); + nat = nat_outlookup(fin, flags, p, oip->ip_dst, + oip->ip_src); + fin->fin_data[0] = data[0]; + fin->fin_data[1] = data[1]; + return nat; } } if (flags & IPN_TCPUDP) { - u_short data[2]; - nat_t *nat; - minlen += 8; /* + 64bits of data to get ports */ if (fin->fin_plen < ICMPERR_IPICMPHLEN + minlen) return NULL; @@ -2628,12 +2642,13 @@ int dir; struct in_addr in; icmphdr_t *icmp; int flags, dlen; - udphdr_t *udp; + u_short *csump; tcphdr_t *tcp; nat_t *nat; ip_t *oip; + void *dp; - if ((fin->fin_flx & (FI_SHORT|FI_FRAGTAIL))) + if ((fin->fin_flx & (FI_SHORT|FI_FRAGBODY))) return NULL; /* * nat_icmperrorlookup() will return NULL for `defective' packets. @@ -2641,20 +2656,28 @@ int dir; if ((fin->fin_v != 4) || !(nat = nat_icmperrorlookup(fin, dir))) return NULL; + tcp = NULL; + csump = NULL; flags = 0; sumd2 = 0; *nflags = IPN_ICMPERR; icmp = fin->fin_dp; oip = (ip_t *)&icmp->icmp_ip; - if (oip->ip_p == IPPROTO_TCP) + dp = (((char *)oip) + (IP_HL(oip) << 2)); + if (oip->ip_p == IPPROTO_TCP) { + tcp = (tcphdr_t *)dp; + csump = (u_short *)&tcp->th_sum; flags = IPN_TCP; - else if (oip->ip_p == IPPROTO_UDP) + } else if (oip->ip_p == IPPROTO_UDP) { + udphdr_t *udp; + + udp = (udphdr_t *)dp; + tcp = (tcphdr_t *)dp; + csump = (u_short *)&udp->uh_sum; flags = IPN_UDP; - else if (oip->ip_p == IPPROTO_ICMP) + } else if (oip->ip_p == IPPROTO_ICMP) flags = IPN_ICMPQUERY; - udp = (udphdr_t *)((((char *)oip) + (IP_HL(oip) << 2))); - tcp = (tcphdr_t *)udp; - dlen = fin->fin_plen - ((char *)udp - (char *)fin->fin_ip); + dlen = fin->fin_plen - ((char *)dp - (char *)fin->fin_ip); /* * Need to adjust ICMP header to include the real IP#'s and @@ -2693,140 +2716,78 @@ int dir; CALC_SUMD(sum1, sum2, sumd); - if (nat->nat_dir == NAT_OUTBOUND) { - /* - * Fix IP checksum of the offending IP packet to adjust for - * the change in the IP address. - * - * Normally, you would expect that the ICMP checksum of the - * ICMP error message needs to be adjusted as well for the - * IP address change in oip. - * However, this is a NOP, because the ICMP checksum is - * calculated over the complete ICMP packet, which includes the - * changed oip IP addresses and oip->ip_sum. However, these - * two changes cancel each other out (if the delta for - * the IP address is x, then the delta for ip_sum is minus x), - * so no change in the icmp_cksum is necessary. - * - * Be careful that nat_dir refers to the direction of the - * offending IP packet (oip), not to its ICMP response (icmp) - */ - fix_datacksum(&oip->ip_sum, sumd); - /* Fix icmp cksum : IP Addr + Cksum */ - sumd2 = (sumd << 1); + /* + * Fix IP checksum of the offending IP packet to adjust for + * the change in the IP address. + * + * Normally, you would expect that the ICMP checksum of the + * ICMP error message needs to be adjusted as well for the + * IP address change in oip. + * However, this is a NOP, because the ICMP checksum is + * calculated over the complete ICMP packet, which includes the + * changed oip IP addresses and oip->ip_sum. However, these + * two changes cancel each other out (if the delta for + * the IP address is x, then the delta for ip_sum is minus x), + * so no change in the icmp_cksum is necessary. + * + * Be careful that nat_dir refers to the direction of the + * offending IP packet (oip), not to its ICMP response (icmp) + */ + fix_datacksum(&oip->ip_sum, sumd); + /* Fix icmp cksum : IP Addr + Cksum */ + sumd2 = (sumd >> 16); + /* + * Fix UDP pseudo header checksum to compensate for the + * IP address change. + */ + if ((oip->ip_p == IPPROTO_UDP) && (dlen >= 8) && (*csump != 0)) { /* - * Fix UDP pseudo header checksum to compensate for the - * IP address change. + * The UDP checksum is optional, only adjust it + * if it has been set. */ - if ((oip->ip_p == IPPROTO_UDP) && (udp->uh_sum != 0)) { - /* - * The UDP checksum is optional, only adjust it - * if it has been set. - */ - sum1 = ntohs(udp->uh_sum); - fix_datacksum(&udp->uh_sum, sumd); - sum2 = ntohs(udp->uh_sum); - - /* - * Fix ICMP checksum to compensate the UDP - * checksum adjustment. - */ - CALC_SUMD(sum1, sum2, sumd); - sumd2 += sumd; - } + sum1 = ntohs(*csump); + fix_datacksum(csump, sumd); + sum2 = ntohs(*csump); /* - * Fix TCP pseudo header checksum to compensate for the - * IP address change. Before we can do the change, we - * must make sure that oip is sufficient large to hold - * the TCP checksum (normally it does not!). + * Fix ICMP checksum to compensate the UDP + * checksum adjustment. */ - if (oip->ip_p == IPPROTO_TCP && dlen >= 18) { + sumd2 = sumd << 1; + CALC_SUMD(sum1, sum2, sumd); + sumd2 += sumd; + } - sum1 = ntohs(tcp->th_sum); - fix_datacksum(&tcp->th_sum, sumd); - sum2 = ntohs(tcp->th_sum); + /* + * Fix TCP pseudo header checksum to compensate for the + * IP address change. Before we can do the change, we + * must make sure that oip is sufficient large to hold + * the TCP checksum (normally it does not!). + * 18 = offsetof(tcphdr_t, th_sum) + 2 + */ + else if (oip->ip_p == IPPROTO_TCP && dlen >= 18) { + sum1 = ntohs(*csump); + fix_datacksum(csump, sumd); + sum2 = ntohs(*csump); - /* - * Fix ICMP checksum to compensate the TCP checksum - * adjustment. - */ - CALC_SUMD(sum1, sum2, sumd); - sumd2 += sumd; - } - } else { - /* - * Fix IP checksum of the offending IP packet to adjust for - * the change in the IP address. - * - * Normally, you would expect that the ICMP checksum of the - * ICMP error message needs to be adjusted as well for the - * IP address change in oip. - * However, this is a NOP, because the ICMP checksum is - * calculated over the complete ICMP packet, which includes the - * changed oip IP addresses and oip->ip_sum. However, these - * two changes cancel each other out (if the delta for - * the IP address is x, then the delta for ip_sum is minus x), - * so no change in the icmp_cksum is necessary. - * - * Be careful that nat_dir refers to the direction of the - * offending IP packet (oip), not to its ICMP response (icmp) - */ - fix_datacksum(&oip->ip_sum, sumd); - /* Fix icmp cksum : IP Addr + Cksum */ - sumd2 = (sumd << 1); - -/* XXX FV : without having looked at Solaris source code, it seems unlikely - * that SOLARIS would compensate this in the kernel (a body of an IP packet - * in the data section of an ICMP packet). I have the feeling that this should - * be unconditional, but I'm not in a position to check. - */ -#if !SOLARIS && !defined(__sgi) /* - * Fix UDP pseudo header checksum to compensate for the - * IP address change. - */ - if ((oip->ip_p == IPPROTO_UDP) && (udp->uh_sum != 0)) { - /* - * The UDP checksum is optional, only adjust it - * if it has been set - */ - sum1 = ntohs(udp->uh_sum); - fix_datacksum(&udp->uh_sum, sumd); - sum2 = ntohs(udp->uh_sum); - - /* - * Fix ICMP checksum to compensate the UDP - * checksum adjustment. - */ - CALC_SUMD(sum1, sum2, sumd); - sumd2 += sumd; - } - - /* - * Fix TCP pseudo header checksum to compensate for the - * IP address change. Before we can do the change, we - * must make sure that oip is sufficient large to hold - * the TCP checksum (normally it does not!). + * Fix ICMP checksum to compensate the TCP + * checksum adjustment. */ - if (oip->ip_p == IPPROTO_TCP && dlen >= 18) { - - sum1 = ntohs(tcp->th_sum); - fix_datacksum(&tcp->th_sum, sumd); - sum2 = ntohs(tcp->th_sum); - - /* - * Fix ICMP checksum to compensate the TCP checksum - * adjustment. - */ - CALC_SUMD(sum1, sum2, sumd); - sumd2 += sumd; - } -#endif + sumd2 = sumd << 1; + CALC_SUMD(sum1, sum2, sumd); + sumd2 += sumd; + } else { + if (nat->nat_dir == NAT_OUTBOUND) + sumd2 = ~sumd2; + else + sumd2 = ~sumd2 + 1; } - if ((flags & IPN_TCPUDP) != 0) { + if (((flags & IPN_TCPUDP) != 0) && (dlen >= 4)) { + int mode = 0; + /* * Step 2 : * For offending TCP/UDP IP packets, translate the ports as @@ -2842,58 +2803,67 @@ int dir; * * To further complicate: the TCP checksum is not in the first * 8 bytes of the offending ip packet, so it most likely is not - * available. OSses like Solaris return enough bytes to + * available. Some OSses like Solaris return enough bytes to * include the TCP checksum. So we have to check if the * ip->ip_len actually holds the TCP checksum of the oip! */ - if (nat->nat_oport == tcp->th_dport) { + if (nat->nat_oport == tcp->th_dport) { if (tcp->th_sport != nat->nat_inport) { - /* - * Fix ICMP checksum to compensate port - * adjustment. - */ - sum1 = ntohs(tcp->th_sport); - sum2 = ntohs(nat->nat_inport); - CALC_SUMD(sum1, sum2, sumd); - sumd2 += sumd; - tcp->th_sport = nat->nat_inport; + mode = 1; + sum1 = ntohs(nat->nat_inport); + sum2 = ntohs(tcp->th_sport); + } + } else if (tcp->th_sport == nat->nat_oport) { + mode = 2; + sum1 = ntohs(nat->nat_outport); + sum2 = ntohs(tcp->th_dport); + } - /* - * Fix udp checksum to compensate port - * adjustment. NOTE : the offending IP packet - * flows the other direction compared to the - * ICMP message. - * - * The UDP checksum is optional, only adjust - * it if it has been set. - */ - if ((oip->ip_p == IPPROTO_UDP) && - (udp->uh_sum != 0)) { + if (mode == 1) { + /* + * Fix ICMP checksum to compensate port adjustment. + */ + tcp->th_sport = htons(sum1); - sum1 = ntohs(udp->uh_sum); - fix_datacksum(&udp->uh_sum, sumd); - sum2 = ntohs(udp->uh_sum); + /* + * Fix udp checksum to compensate port adjustment. + * NOTE : the offending IP packet flows the other + * direction compared to the ICMP message. + * + * The UDP checksum is optional, only adjust it if + * it has been set. + */ + if ((oip->ip_p == IPPROTO_UDP) && + (dlen >= 8) && (*csump != 0)) { + sumd = sum1 - sum2; + sumd2 += sumd; - /* - * Fix ICMP checksum to compenstate - * UDP checksum adjustment. - */ - CALC_SUMD(sum1, sum2, sumd); - sumd2 += sumd; - } + sum1 = ntohs(*csump); + fix_datacksum(csump, sumd); + sum2 = ntohs(*csump); /* - * Fix TCP checksum (if present) to compensate - * port adjustment. NOTE : the offending IP - * packet flows the other direction compared to - * the ICMP message. + * Fix ICMP checksum to compenstate + * UDP checksum adjustment. */ - if (oip->ip_p == IPPROTO_TCP && dlen >= 18) { + CALC_SUMD(sum1, sum2, sumd); + sumd2 += sumd; + } + + /* + * Fix TCP checksum (if present) to compensate port + * adjustment. NOTE : the offending IP packet flows + * the other direction compared to the ICMP message. + */ + if (oip->ip_p == IPPROTO_TCP) { + if (dlen >= 18) { + sumd = sum1 - sum2; + sumd2 += sumd; - sum1 = ntohs(tcp->th_sum); - fix_datacksum(&tcp->th_sum, sumd); - sum2 = ntohs(tcp->th_sum); + sum1 = ntohs(*csump); + fix_datacksum(csump, sumd); + sum2 = ntohs(*csump); /* * Fix ICMP checksum to compensate @@ -2901,57 +2871,55 @@ int dir; */ CALC_SUMD(sum1, sum2, sumd); sumd2 += sumd; + } else { + sumd = sum2 - sum1 + 1; + sumd2 += sumd; } } - } else { - if (tcp->th_dport != nat->nat_outport) { - udphdr_t *udp = (udphdr_t *)tcp; + } else if (mode == 2) { + /* + * Fix ICMP checksum to compensate port adjustment. + */ + tcp->th_dport = htons(sum1); - /* - * Fix ICMP checksum to compensate port - * adjustment. - */ - sum1 = ntohs(tcp->th_dport); - sum2 = ntohs(nat->nat_outport); - CALC_SUMD(sum1, sum2, sumd); + /* + * Fix UDP checksum to compensate port adjustment. + * NOTE : the offending IP packet flows the other + * direction compared to the ICMP message. + * + * The UDP checksum is optional, only adjust + * it if it has been set. + */ + if ((oip->ip_p == IPPROTO_UDP) && + (dlen >= 8) && (*csump != 0)) { + sumd = sum1 - sum2; sumd2 += sumd; - tcp->th_dport = nat->nat_outport; - - /* - * Fix UDP checksum to compensate port - * adjustment. NOTE : the offending IP - * packet flows the other direction compared - * to the ICMP message. - * - * The UDP checksum is optional, only adjust - * it if it has been set. - */ - if ((oip->ip_p == IPPROTO_UDP) && - (udp->uh_sum != 0)) { - sum1 = ntohs(udp->uh_sum); - fix_datacksum(&udp->uh_sum, sumd); - sum2 = ntohs(udp->uh_sum); - - /* - * Fix ICMP checksum to compensate - * UDP checksum adjustment. - */ - CALC_SUMD(sum1, sum2, sumd); - sumd2 += sumd2; - } + sum1 = ntohs(*csump); + fix_datacksum(csump, sumd); + sum2 = ntohs(*csump); /* - * Fix TCP checksum (if present) to compensate - * port adjustment. NOTE : the offending IP - * packet flows the other direction compared to - * the ICMP message. + * Fix ICMP checksum to compensate + * UDP checksum adjustment. */ - if (oip->ip_p == IPPROTO_TCP && dlen >= 18) { + CALC_SUMD(sum1, sum2, sumd); + sumd2 += sumd; + } + + /* + * Fix TCP checksum (if present) to compensate port + * adjustment. NOTE : the offending IP packet flows + * the other direction compared to the ICMP message. + */ + if (oip->ip_p == IPPROTO_TCP) { + if (dlen >= 18) { + sumd = sum1 - sum2; + sumd2 += sumd; - sum1 = ntohs(tcp->th_sum); - fix_datacksum(&tcp->th_sum, sumd); - sum2 = ntohs(tcp->th_sum); + sum1 = ntohs(*csump); + fix_datacksum(csump, sumd); + sum2 = ntohs(*csump); /* * Fix ICMP checksum to compensate @@ -2959,31 +2927,33 @@ int dir; */ CALC_SUMD(sum1, sum2, sumd); sumd2 += sumd; + } else { + if (nat->nat_dir == NAT_INBOUND) + sumd = sum2 - sum1; + else + sumd = sum2 - sum1 + 1; + sumd2 += sumd; } } } if (sumd2 != 0) { sumd2 = (sumd2 & 0xffff) + (sumd2 >> 16); sumd2 = (sumd2 & 0xffff) + (sumd2 >> 16); - if (nat->nat_dir == NAT_OUTBOUND) { - fix_outcksum(fin, &icmp->icmp_cksum, sumd2); - } else { - fix_incksum(fin, &icmp->icmp_cksum, sumd2); - } + fix_incksum(fin, &icmp->icmp_cksum, sumd2); } - } else if ((flags & IPN_ICMPQUERY) != 0) { + } else if (((flags & IPN_ICMPQUERY) != 0) && (dlen >= 8)) { icmphdr_t *orgicmp; /* * XXX - what if this is bogus hl and we go off the end ? * In this case, nat_icmperrorlookup() will have returned NULL. */ - orgicmp = (icmphdr_t *)udp; + orgicmp = (icmphdr_t *)dp; if (nat->nat_dir == NAT_OUTBOUND) { if (orgicmp->icmp_id != nat->nat_inport) { - /* + /* * Fix ICMP checksum (of the offening ICMP * query packet) to compensate the change * in the ICMP id of the offending ICMP @@ -2993,7 +2963,7 @@ int dir; * a delta (say x) and you compensate that * in origicmp->icmp_cksum with a delta * minus x, you don't have to adjust the - * overall icmp->icmp_cksum + * overall icmp->icmp_cksum */ sum1 = ntohs(orgicmp->icmp_id); sum2 = ntohs(nat->nat_inport); @@ -3040,7 +3010,6 @@ u_int flags, p; struct in_addr src , mapdst; { u_short sport, dport; - grehdr_t *gre; ipnat_t *ipn; u_int sflags; nat_t *nat; @@ -3053,17 +3022,29 @@ struct in_addr src , mapdst; ifp = fin->fin_ifp; else ifp = NULL; + sport = 0; + dport = 0; dst = mapdst.s_addr; sflags = flags & NAT_TCPUDPICMP; - if ((flags & IPN_TCPUDP) != 0) { + + switch (p) + { + case IPPROTO_TCP : + case IPPROTO_UDP : sport = htons(fin->fin_data[0]); dport = htons(fin->fin_data[1]); - gre = NULL; - } else { - gre = (p == IPPROTO_GRE) ? fin->fin_dp : NULL; - sport = 0; - dport = 0; + break; + case IPPROTO_ICMP : + if (flags & IPN_ICMPERR) + sport = fin->fin_data[1]; + else + dport = fin->fin_data[1]; + break; + default : + break; } + + if ((flags & SI_WILDP) != 0) goto find_in_wild_ports; @@ -3071,24 +3052,40 @@ struct in_addr src , mapdst; hv = NAT_HASH_FN(src.s_addr, hv + sport, ipf_nattable_sz); nat = nat_table[1][hv]; for (; nat; nat = nat->nat_hnext[1]) { - if (nat->nat_ifps[0] != NULL) { - if ((ifp != NULL) && (ifp != nat->nat_ifps[0])) - continue; - } else if (ifp != NULL) - nat->nat_ifps[0] = ifp; - nflags = nat->nat_flags; + if (ifp != NULL) { + if (nat->nat_dir == NAT_REDIRECT) { + if (ifp != nat->nat_ifps[0]) + continue; + } else { + if (ifp != nat->nat_ifps[1]) + continue; + } + } + if (nat->nat_oip.s_addr == src.s_addr && nat->nat_outip.s_addr == dst && - (((p == 0) && (sflags == (nat->nat_flags & IPN_TCPUDPICMP))) + (((p == 0) && + (sflags == (nat->nat_flags & IPN_TCPUDPICMP))) || (p == nat->nat_p))) { switch (p) { +#if 0 case IPPROTO_GRE : - if (gre->gr_call != nat->nat_gre.gs_call) + if (nat->nat_call[1] != fin->fin_data[0]) continue; break; +#endif + case IPPROTO_ICMP : + if ((flags & IPN_ICMPERR) != 0) { + if (nat->nat_outport != sport) + continue; + } else { + if (nat->nat_outport != dport) + continue; + } + break; case IPPROTO_TCP : case IPPROTO_UDP : if (nat->nat_oport != sport) @@ -3130,11 +3127,15 @@ find_in_wild_ports: nat = nat_table[1][hv]; for (; nat; nat = nat->nat_hnext[1]) { - if (nat->nat_ifps[0] != NULL) { - if ((ifp != NULL) && (ifp != nat->nat_ifps[0])) - continue; - } else if (ifp != NULL) - nat->nat_ifps[0] = ifp; + if (ifp != NULL) { + if (nat->nat_dir == NAT_REDIRECT) { + if (ifp != nat->nat_ifps[0]) + continue; + } else { + if (ifp != nat->nat_ifps[1]) + continue; + } + } if (nat->nat_p != fin->fin_p) continue; @@ -3270,25 +3271,30 @@ struct in_addr src , dst; int nflags; void *ifp; u_int hv; - frentry_t *fr; - - fr = fin->fin_fr; - - if ((fr != NULL) && !(fr->fr_flags & FR_DUP) && - fr->fr_tif.fd_ifp && fr->fr_tif.fd_ifp != (void *)-1) - ifp = fr->fr_tif.fd_ifp; - else - ifp = fin->fin_ifp; + ifp = fin->fin_ifp; srcip = src.s_addr; sflags = flags & IPN_TCPUDPICMP; - if ((flags & IPN_TCPUDP) != 0) { - sport = ntohs(fin->fin_data[0]); - dport = ntohs(fin->fin_data[1]); - } else { - sport = 0; - dport = 0; + sport = 0; + dport = 0; + + switch (p) + { + case IPPROTO_TCP : + case IPPROTO_UDP : + sport = htons(fin->fin_data[0]); + dport = htons(fin->fin_data[1]); + break; + case IPPROTO_ICMP : + if (flags & IPN_ICMPERR) + sport = fin->fin_data[1]; + else + dport = fin->fin_data[1]; + break; + default : + break; } + if ((flags & SI_WILDP) != 0) goto find_out_wild_ports; @@ -3296,22 +3302,30 @@ struct in_addr src , dst; hv = NAT_HASH_FN(dst.s_addr, hv + dport, ipf_nattable_sz); nat = nat_table[0][hv]; for (; nat; nat = nat->nat_hnext[0]) { - if (nat->nat_ifps[1] != NULL) { - if ((ifp != NULL) && (ifp != nat->nat_ifps[1])) - continue; - } else if (ifp != NULL) - nat->nat_ifps[1] = ifp; - nflags = nat->nat_flags; + if (ifp != NULL) { + if (nat->nat_dir == NAT_REDIRECT) { + if (ifp != nat->nat_ifps[1]) + continue; + } else { + if (ifp != nat->nat_ifps[0]) + continue; + } + } + if (nat->nat_inip.s_addr == srcip && nat->nat_oip.s_addr == dst.s_addr && (((p == 0) && (sflags == (nflags & NAT_TCPUDPICMP))) || (p == nat->nat_p))) { switch (p) { +#if 0 case IPPROTO_GRE : + if (nat->nat_call[1] != fin->fin_data[0]) + continue; break; +#endif case IPPROTO_TCP : case IPPROTO_UDP : if (nat->nat_oport != dport) @@ -3353,11 +3367,15 @@ find_out_wild_ports: nat = nat_table[0][hv]; for (; nat; nat = nat->nat_hnext[0]) { - if (nat->nat_ifps[1] != NULL) { - if ((ifp != NULL) && (ifp != nat->nat_ifps[1])) - continue; - } else if (ifp != NULL) - nat->nat_ifps[1] = ifp; + if (ifp != NULL) { + if (nat->nat_dir == NAT_REDIRECT) { + if (ifp != nat->nat_ifps[1]) + continue; + } else { + if (ifp != nat->nat_ifps[0]) + continue; + } + } if (nat->nat_p != fin->fin_p) continue; @@ -3414,8 +3432,13 @@ natlookup_t *np; nat_t *nat; bzero((char *)&fi, sizeof(fi)); - fi.fin_data[0] = ntohs(np->nl_inport); - fi.fin_data[1] = ntohs(np->nl_outport); + if (np->nl_flags & IPN_IN) { + fi.fin_data[0] = ntohs(np->nl_realport); + fi.fin_data[1] = ntohs(np->nl_outport); + } else { + fi.fin_data[0] = ntohs(np->nl_inport); + fi.fin_data[1] = ntohs(np->nl_outport); + } if (np->nl_flags & IPN_TCP) fi.fin_p = IPPROTO_TCP; else if (np->nl_flags & IPN_UDP) @@ -3424,28 +3447,41 @@ natlookup_t *np; fi.fin_p = IPPROTO_ICMP; /* - * If nl_inip is non null, this is a lookup based on the real - * ip address. Else, we use the fake. + * We can do two sorts of lookups: + * - IPN_IN: we have the `real' and `out' address, look for `in'. + * - default: we have the `in' and `out' address, look for `real'. */ - if ((nat = nat_outlookup(&fi, np->nl_flags, fi.fin_p, - np->nl_inip, np->nl_outip))) { - - if ((np->nl_flags & IPN_FINDFORWARD) != 0) { - fr_info_t fin; - bzero((char *)&fin, sizeof(fin)); - fin.fin_p = nat->nat_p; - fin.fin_data[0] = ntohs(nat->nat_outport); - fin.fin_data[1] = ntohs(nat->nat_oport); - if (nat_inlookup(&fin, np->nl_flags, fin.fin_p, - nat->nat_outip, - nat->nat_oip) != NULL) { - np->nl_flags &= ~IPN_FINDFORWARD; - } + if (np->nl_flags & IPN_IN) { + if ((nat = nat_inlookup(&fi, np->nl_flags, fi.fin_p, + np->nl_realip, np->nl_outip))) { + np->nl_inip = nat->nat_inip; + np->nl_inport = nat->nat_inport; } + } else { + /* + * If nl_inip is non null, this is a lookup based on the real + * ip address. Else, we use the fake. + */ + if ((nat = nat_outlookup(&fi, np->nl_flags, fi.fin_p, + np->nl_inip, np->nl_outip))) { + + if ((np->nl_flags & IPN_FINDFORWARD) != 0) { + fr_info_t fin; + bzero((char *)&fin, sizeof(fin)); + fin.fin_p = nat->nat_p; + fin.fin_data[0] = ntohs(nat->nat_outport); + fin.fin_data[1] = ntohs(nat->nat_oport); + if (nat_inlookup(&fin, np->nl_flags, fin.fin_p, + nat->nat_outip, + nat->nat_oip) != NULL) { + np->nl_flags &= ~IPN_FINDFORWARD; + } + } - np->nl_realip = nat->nat_outip; - np->nl_realport = nat->nat_outport; - } + np->nl_realip = nat->nat_outip; + np->nl_realport = nat->nat_outport; + } + } return nat; } @@ -3494,7 +3530,7 @@ ipnat_t *np; ft = &np->in_tuc; if (!(fin->fin_flx & FI_TCPUDP) || - (fin->fin_flx & (FI_SHORT|FI_FRAGTAIL))) { + (fin->fin_flx & (FI_SHORT|FI_FRAGBODY))) { if (ft->ftu_scmp || ft->ftu_dcmp) return 0; return 1; @@ -3572,20 +3608,21 @@ int fr_checknatout(fin, passp) fr_info_t *fin; u_32_t *passp; { + struct ifnet *ifp, *sifp; icmphdr_t *icmp = NULL; tcphdr_t *tcp = NULL; + int rval, natfailed; ipnat_t *np = NULL; - struct ifnet *ifp, *sifp; u_int nflags = 0; u_32_t ipa, iph; int natadd = 1; frentry_t *fr; nat_t *nat; - int rval; - if (nat_list == NULL || fr_nat_lock != 0) + if (nat_stats.ns_rules == 0 || fr_nat_lock != 0) return 0; + natfailed = 0; fr = fin->fin_fr; sifp = fin->fin_ifp; if ((fr != NULL) && !(fr->fr_flags & FR_DUP) && @@ -3648,7 +3685,11 @@ maskloop: hv = NAT_HASH_FN(iph, 0, ipf_natrules_sz); for (np = nat_rules[hv]; np; np = np->in_mnext) { - if ((np->in_ifps[1] && (np->in_ifps[1] != ifp))) + if ((np->in_ifps[0] && (np->in_ifps[0] != ifp))) + continue; + if (np->in_v != fin->fin_v) + continue; + if (np->in_p && (np->in_p != fin->fin_p)) continue; if ((np->in_flags & IPN_RF) && !(np->in_flags & nflags)) continue; @@ -3674,7 +3715,8 @@ maskloop: NAT_OUTBOUND))) { np->in_hits++; break; - } + } else + natfailed = -1; } if ((np == NULL) && (nmsk != 0)) { while (nmsk) { @@ -3700,7 +3742,7 @@ maskloop: fin->fin_nat = nat; } } else - rval = 0; + rval = natfailed; RWLOCK_EXIT(&ipf_nat); if (rval == -1) { @@ -3751,32 +3793,39 @@ u_32_t nflags; /* * Fix up checksums, not by recalculating them, but * simply computing adjustments. + * This is only done for STREAMS based IP implementations where the + * checksum has already been calculated by IP. In all other cases, + * IPFilter is called before the checksum needs calculating so there + * is no call to modify whatever is in the header now. */ - if (nflags == IPN_ICMPERR) { - u_32_t s1, s2, sumd; - - s1 = LONG_SUM(ntohl(fin->fin_saddr)); - s2 = LONG_SUM(ntohl(nat->nat_outip.s_addr)); - CALC_SUMD(s1, s2, sumd); - - if (fin->fin_v == 4) { + if (fin->fin_v == 4) { + if (nflags == IPN_ICMPERR) { + u_32_t s1, s2, sumd; + + s1 = LONG_SUM(ntohl(fin->fin_saddr)); + s2 = LONG_SUM(ntohl(nat->nat_outip.s_addr)); + CALC_SUMD(s1, s2, sumd); + fix_outcksum(fin, &fin->fin_ip->ip_sum, sumd); + } +#if !defined(_KERNEL) || defined(MENTAT) || defined(__sgi) || \ + defined(linux) || defined(BRIDGE_IPF) + else { + /* + * Strictly speaking, this isn't necessary on BSD + * kernels because they do checksum calculation after + * this code has run BUT if ipfilter is being used + * to do NAT as a bridge, that code doesn't exist. + */ if (nat->nat_dir == NAT_OUTBOUND) - fix_outcksum(fin, &fin->fin_ip->ip_sum, sumd); + fix_outcksum(fin, &fin->fin_ip->ip_sum, + nat->nat_ipsumd); else - fix_incksum(fin, &fin->fin_ip->ip_sum, sumd); + fix_incksum(fin, &fin->fin_ip->ip_sum, + nat->nat_ipsumd); } - } -#if !defined(_KERNEL) || (defined(MENTAT) || defined(__sgi)) - else if (fin->fin_v == 4) { - if (nat->nat_dir == NAT_OUTBOUND) - fix_outcksum(fin, &fin->fin_ip->ip_sum, - nat->nat_ipsumd); - else - fix_incksum(fin, &fin->fin_ip->ip_sum, - nat->nat_ipsumd); - } #endif - fin->fin_ip->ip_src = nat->nat_outip; + } + if (!(fin->fin_flx & FI_SHORT) && (fin->fin_off == 0)) { if ((nat->nat_outport != 0) && (nflags & IPN_TCPUDP)) { tcp = fin->fin_dp; @@ -3793,8 +3842,13 @@ u_32_t nflags; csump = nat_proto(fin, nat, nflags); } + fin->fin_ip->ip_src = nat->nat_outip; + nat_update(fin, nat, np); + /* + * The above comments do not hold for layer 4 (or higher) checksums... + */ if (csump != NULL) { if (nat->nat_dir == NAT_OUTBOUND) fix_outcksum(fin, csump, nat->nat_sumd[1]); @@ -3818,7 +3872,7 @@ u_32_t nflags; i = appr_check(fin, nat); if (i == 0) i = 1; - } else + } else i = 1; ATOMIC_INCL(nat_stats.ns_mapped[1]); fin->fin_flx |= FI_NATED; @@ -3846,6 +3900,7 @@ fr_info_t *fin; u_32_t *passp; { u_int nflags, natadd; + int rval, natfailed; struct ifnet *ifp; struct in_addr in; icmphdr_t *icmp; @@ -3854,9 +3909,8 @@ u_32_t *passp; ipnat_t *np; nat_t *nat; u_32_t iph; - int rval; - if (nat_list == NULL || fr_nat_lock != 0) + if (nat_stats.ns_rules == 0 || fr_nat_lock != 0) return 0; tcp = NULL; @@ -3864,6 +3918,7 @@ u_32_t *passp; dport = 0; natadd = 1; nflags = 0; + natfailed = 0; ifp = fin->fin_ifp; if (!(fin->fin_flx & FI_SHORT) && (fin->fin_off == 0)) { @@ -3925,6 +3980,8 @@ maskloop: for (np = rdr_rules[hv]; np; np = np->in_rnext) { if (np->in_ifps[0] && (np->in_ifps[0] != ifp)) continue; + if (np->in_v != fin->fin_v) + continue; if (np->in_p && (np->in_p != fin->fin_p)) continue; if ((np->in_flags & IPN_RF) && !(np->in_flags & nflags)) @@ -3951,7 +4008,8 @@ maskloop: if (nat != NULL) { np->in_hits++; break; - } + } else + natfailed = -1; } if ((np == NULL) && (rmsk != 0)) { @@ -3978,7 +4036,7 @@ maskloop: fin->fin_state = nat->nat_state; } } else - rval = 0; + rval = natfailed; RWLOCK_EXIT(&ipf_nat); if (rval == -1) { @@ -4058,8 +4116,15 @@ u_32_t nflags; /* * Fix up checksums, not by recalculating them, but * simply computing adjustments. + * Why only do this for some platforms on inbound packets ? + * Because for those that it is done, IP processing is yet to happen + * and so the IPv4 header checksum has not yet been evaluated. + * Perhaps it should always be done for the benefit of things like + * fast forwarding (so that it doesn't need to be recomputed) but with + * header checksum offloading, perhaps it is a moot point. */ -#if !defined(_KERNEL) || (defined(MENTAT) || defined(__sgi) || defined(__osf__)) +#if !defined(_KERNEL) || defined(MENTAT) || defined(__sgi) || \ + defined(__osf__) || defined(linux) if (nat->nat_dir == NAT_OUTBOUND) fix_incksum(fin, &fin->fin_ip->ip_sum, nat->nat_ipsumd); else @@ -4084,6 +4149,9 @@ u_32_t nflags; nat_update(fin, nat, np); + /* + * The above comments do not hold for layer 4 (or higher) checksums... + */ if (csump != NULL) { if (nat->nat_dir == NAT_OUTBOUND) fix_incksum(fin, csump, nat->nat_sumd[0]); @@ -4107,8 +4175,10 @@ u_32_t nflags; /* nat(I) - pointer to NAT structure */ /* nflags(I) - NAT flags set for this packet */ /* */ -/* Make special protocol timeout adjustments and return a pointer to the */ -/* checksum location for updating. */ +/* Return the pointer to the checksum field for each protocol so understood.*/ +/* If support for making other changes to a protocol header is required, */ +/* that is not strictly 'address' translation, such as clamping the MSS in */ +/* TCP down to a specific value, then do it from here. */ /* ------------------------------------------------------------------------ */ u_short *nat_proto(fin, nat, nflags) fr_info_t *fin; @@ -4172,9 +4242,25 @@ u_int nflags; /* ------------------------------------------------------------------------ */ void fr_natunload() { + ipftq_t *ifq, *ifqnext; + (void) nat_clearlist(); (void) nat_flushtable(); + /* + * Proxy timeout queues are not cleaned here because although they + * exist on the NAT list, appr_unload is called after fr_natunload + * and the proxies actually are responsible for them being created. + * Should the proxy timeouts have their own list? There's no real + * justification as this is the only complication. + */ + for (ifq = nat_utqe; ifq != NULL; ifq = ifqnext) { + ifqnext = ifq->ifq_next; + if (((ifq->ifq_flags & IFQF_PROXY) == 0) && + (fr_deletetimeoutqueue(ifq) == 0)) + fr_freetimeoutqueue(ifq); + } + if (nat_table[0] != NULL) { KFREES(nat_table[0], sizeof(nat_t *) * ipf_nattable_sz); nat_table[0] = NULL; @@ -4238,10 +4324,8 @@ void fr_natexpire() { ipftq_t *ifq, *ifqnext; ipftqent_t *tqe, *tqn; -#if defined(_KERNEL) && !defined(MENTAT) && defined(USE_SPL) - int s; -#endif int i; + SPL_INT(s); SPL_NET(s); WRITE_ENTER(&ipf_nat); @@ -4265,6 +4349,15 @@ void fr_natexpire() } } + for (ifq = nat_utqe; ifq != NULL; ifq = ifqnext) { + ifqnext = ifq->ifq_next; + + if (((ifq->ifq_flags & IFQF_DELETE) != 0) && + (ifq->ifq_ref == 0)) { + fr_freetimeoutqueue(ifq); + } + } + RWLOCK_EXIT(&ipf_nat); SPL_X(s); } @@ -4283,13 +4376,10 @@ void *ifp; { u_32_t sum1, sum2, sumd; struct in_addr in; - ipnat_t *np; ipnat_t *n; nat_t *nat; void *ifp2; -#if defined(_KERNEL) && !defined(MENTAT) && defined(USE_SPL) - int s; -#endif + SPL_INT(s); if (fr_running <= 0) return; @@ -4311,12 +4401,12 @@ void *ifp; for (nat = nat_instances; nat; nat = nat->nat_next) { if ((nat->nat_flags & IPN_TCP) != 0) continue; - np = nat->nat_ptr; - if ((np == NULL) || - (np->in_outip != 0) || (np->in_outmsk != 0xffffffff)) + n = nat->nat_ptr; + if ((n == NULL) || + (n->in_outip != 0) || (n->in_outmsk != 0xffffffff)) continue; if (((ifp == NULL) || (ifp == nat->nat_ifps[0]) || - (ifp == nat->nat_ifps[1]))) { + (ifp == nat->nat_ifps[1]))) { nat->nat_ifps[0] = GETIFP(nat->nat_ifnames[0], 4); if (nat->nat_ifnames[1][0] != '\0') { nat->nat_ifps[1] = GETIFP(nat->nat_ifnames[1], @@ -4326,6 +4416,7 @@ void *ifp; ifp2 = nat->nat_ifps[0]; if (ifp2 == NULL) continue; + /* * Change the map-to address to be the same as the * new one. @@ -4349,25 +4440,18 @@ void *ifp; nat->nat_sumd[0] = (sumd & 0xffff) + (sumd >> 16); nat->nat_sumd[1] = nat->nat_sumd[0]; } - } for (n = nat_list; (n != NULL); n = n->in_next) { - if ((ifp == NULL) || (n->in_ifps[0] == ifp)) { - n->in_ifps[0] = (void *)GETIFP(n->in_ifnames[0], 4); - if (n->in_ifps[0] == NULL) - n->in_ifps[0] = (void *)-1; - } - if ((ifp == NULL) || (n->in_ifps[1] == ifp)) { - n->in_ifps[1] = (void *)GETIFP(n->in_ifnames[1], 4); - if (n->in_ifps[1] == NULL) - n->in_ifps[1] = (void *)-1; - } + if ((ifp == NULL) || (n->in_ifps[0] == ifp)) + n->in_ifps[0] = fr_resolvenic(n->in_ifnames[0], 4); + if ((ifp == NULL) || (n->in_ifps[1] == ifp)) + n->in_ifps[1] = fr_resolvenic(n->in_ifnames[1], 4); } RWLOCK_EXIT(&ipf_nat); SPL_X(s); } - + /* ------------------------------------------------------------------------ */ /* Function: nat_icmpquerytype4 */ @@ -4390,9 +4474,9 @@ int icmptype; * altough it seems silly to call a reply a query, this is exactly * as it is defined in the IPv4 specification */ - + switch (icmptype) - { + { case ICMP_ECHOREPLY: case ICMP_ECHO: @@ -4405,32 +4489,7 @@ int icmptype; case ICMP_MASKREQ: case ICMP_MASKREPLY: return 1; - default: - return 0; - } -} - - -/* ------------------------------------------------------------------------ */ -/* Function: nat_icmperrortype4 */ -/* Returns: int - 1 == success, 0 == failure */ -/* Parameters: icmptype(I) - ICMP type number */ -/* */ -/* Tests to see if the ICMP type number passed is an error type or not. */ -/* ------------------------------------------------------------------------ */ -static INLINE int nat_icmperrortype4(icmptype) -int icmptype; -{ - - switch (icmptype) - { - case ICMP_SOURCEQUENCH : - case ICMP_PARAMPROB : - case ICMP_REDIRECT : - case ICMP_TIMXCEED : - case ICMP_UNREACH : - return 1; - default: + default: return 0; } } @@ -4449,11 +4508,14 @@ struct nat *nat; u_int type; { #ifdef IPFILTER_LOG +# ifndef LARGE_NAT struct ipnat *np; + int rulen; +# endif struct natlog natl; void *items[1]; size_t sizes[1]; - int rulen, types[1]; + int types[1]; natl.nl_inip = nat->nat_inip; natl.nl_outip = nat->nat_outip; @@ -4498,7 +4560,7 @@ u_int type; void nat_ifdetach(ifp) void *ifp; { - frsync(); + frsync(ifp); return; } #endif @@ -4552,13 +4614,31 @@ nat_t *nat; MUTEX_NUKE(&clone->nat_lock); + clone->nat_aps = NULL; + /* + * Initialize all these so that nat_delete() doesn't cause a crash. + */ + clone->nat_tqe.tqe_pnext = NULL; + clone->nat_tqe.tqe_next = NULL; + clone->nat_tqe.tqe_ifq = NULL; + clone->nat_tqe.tqe_parent = clone; + + clone->nat_flags &= ~SI_CLONE; + clone->nat_flags |= SI_CLONED; + + if (clone->nat_hm) + clone->nat_hm->hm_ref++; + + if (nat_insert(clone, fin->fin_rev) == -1) { + KFREE(clone); + return NULL; + } np = clone->nat_ptr; if (np != NULL) { + if (nat_logging) + nat_log(clone, (u_int)np->in_redir); np->in_use++; } - clone->nat_flags &= ~SI_CLONE; - clone->nat_flags |= SI_CLONED; - fr = clone->nat_fr; if (fr != NULL) { MUTEX_ENTER(&fr->fr_lock); @@ -4566,33 +4646,37 @@ nat_t *nat; MUTEX_EXIT(&fr->fr_lock); } - if (nat_insert(clone) == -1) { - KFREE(clone); - return NULL; - } - + /* + * Because the clone is created outside the normal loop of things and + * TCP has special needs in terms of state, initialise the timeout + * state of the new NAT from here. + */ if (clone->nat_p == IPPROTO_TCP) { - (void) fr_tcp_age(&clone->nat_tqe, fin, nat_tqb, clone->nat_flags); + (void) fr_tcp_age(&clone->nat_tqe, fin, nat_tqb, + clone->nat_flags); } +#ifdef IPFILTER_SYNC + clone->nat_sync = ipfsync_new(SMC_NAT, fin, clone); +#endif if (nat_logging) nat_log(clone, NL_CLONE); return clone; } -/* -------------------------------------------------------------------- */ -/* Function: nat_wildok */ -/* Returns: int - 1 == packet's ports match wildcards */ -/* 0 == packet's ports don't match wildcards */ -/* Parameters: nat(I) - NAT entry */ -/* sport(I) - source port */ -/* dport(I) - destination port */ -/* flags(I) - wildcard flags */ -/* dir(I) - packet direction */ -/* */ -/* Use NAT entry and packet direction to determine which combination of */ -/* wildcard flags should be used. */ -/* -------------------------------------------------------------------- */ +/* ------------------------------------------------------------------------ */ +/* Function: nat_wildok */ +/* Returns: int - 1 == packet's ports match wildcards */ +/* 0 == packet's ports don't match wildcards */ +/* Parameters: nat(I) - NAT entry */ +/* sport(I) - source port */ +/* dport(I) - destination port */ +/* flags(I) - wildcard flags */ +/* dir(I) - packet direction */ +/* */ +/* Use NAT entry and packet direction to determine which combination of */ +/* wildcard flags should be used. */ +/* ------------------------------------------------------------------------ */ static INLINE int nat_wildok(nat, sport, dport, flags, dir) nat_t *nat; int sport; @@ -4687,17 +4771,17 @@ u_short *csump; if (cp + 1 >= ep) break; advance = cp[1]; - if (cp + advance > ep) + if ((cp + advance > ep) || (advance <= 0)) break; switch (opt) { case TCPOPT_MAXSEG: if (advance != 4) break; - mss = cp[0] * 256 + cp[1]; + mss = cp[2] * 256 + cp[3]; if (mss > maxmss) { - cp[0] = maxmss / 256; - cp[1] = maxmss & 0xff; + cp[2] = maxmss / 256; + cp[3] = maxmss & 0xff; CALC_SUMD(mss, maxmss, sumd); fix_outcksum(fin, csump, sumd); } @@ -4711,3 +4795,55 @@ u_short *csump; } } } + + +/* ------------------------------------------------------------------------ */ +/* Function: fr_setnatqueue */ +/* Returns: Nil */ +/* Parameters: nat(I)- pointer to NAT structure */ +/* rev(I) - forward(0) or reverse(1) direction */ +/* Locks: ipf_nat (read or write) */ +/* */ +/* Put the NAT entry on its default queue entry, using rev as a helped in */ +/* determining which queue it should be placed on. */ +/* ------------------------------------------------------------------------ */ +void fr_setnatqueue(nat, rev) +nat_t *nat; +int rev; +{ + ipftq_t *oifq, *nifq; + + if (nat->nat_ptr != NULL) + nifq = nat->nat_ptr->in_tqehead[rev]; + else + nifq = NULL; + + if (nifq == NULL) { + switch (nat->nat_p) + { + case IPPROTO_UDP : + nifq = &nat_udptq; + break; + case IPPROTO_ICMP : + nifq = &nat_icmptq; + break; + case IPPROTO_TCP : + nifq = nat_tqb + nat->nat_tqe.tqe_state[rev]; + break; + default : + nifq = &nat_iptq; + break; + } + } + + oifq = nat->nat_tqe.tqe_ifq; + /* + * If it's currently on a timeout queue, move it from one queue to + * another, else put it on the end of the newly determined queue. + */ + if (oifq != NULL) + fr_movequeue(&nat->nat_tqe, oifq, nifq); + else + fr_queueappend(&nat->nat_tqe, nifq, nat); + return; +} diff --git a/usr/src/common/ipf/ip_pool.c b/usr/src/uts/common/inet/ipf/ip_pool.c index a9b42cd0fe..e3aace93df 100644 --- a/usr/src/common/ipf/ip_pool.c +++ b/usr/src/uts/common/inet/ipf/ip_pool.c @@ -3,7 +3,7 @@ * * See the IPFILTER.LICENCE file for details on licencing. * - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -15,6 +15,9 @@ # define KERNEL 1 # define _KERNEL 1 #endif +#if defined(__osf__) +# define _PROTO_NET_H_ +#endif #include <sys/errno.h> #include <sys/types.h> #include <sys/param.h> @@ -56,28 +59,45 @@ struct file; # include <sys/malloc.h> #endif +#if defined(_KERNEL) && (defined(__osf__) || defined(AIX) || \ + defined(__hpux) || defined(__sgi)) +# ifdef __osf__ +# include <net/radix.h> +# endif +# include "radix_ipf_local.h" +# define _RADIX_H_ +#endif #include <net/if.h> #include <netinet/in.h> -#if SOLARIS2 >= 10 -#include "ip_compat.h" -#include "ip_fil.h" -#include "ip_pool.h" -#else #include "netinet/ip_compat.h" #include "netinet/ip_fil.h" #include "netinet/ip_pool.h" + +#if defined(IPFILTER_LOOKUP) && defined(_KERNEL) && \ + ((BSD >= 198911) && !defined(__osf__) && \ + !defined(__hpux) && !defined(__sgi)) +static int rn_freenode __P((struct radix_node *, void *)); #endif + /* END OF INCLUDES */ #if !defined(lint) static const char sccsid[] = "@(#)ip_fil.c 2.41 6/5/96 (C) 1993-2000 Darren Reed"; -static const char rcsid[] = "@(#)$Id: ip_pool.c,v 2.45 2003/11/12 09:34:31 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id: ip_pool.c,v 2.55.2.14 2005/06/12 07:18:26 darrenr Exp $"; #endif #ifdef IPFILTER_LOOKUP +# ifndef RADIX_NODE_HEAD_LOCK +# define RADIX_NODE_HEAD_LOCK(x) ; +# endif +# ifndef RADIX_NODE_HEAD_UNLOCK +# define RADIX_NODE_HEAD_UNLOCK(x) ; +# endif + ip_pool_stat_t ipoolstat; +ipfrwlock_t ip_poolrw; /* * Binary tree routines from Sedgewick and enhanced to do ranges of addresses. @@ -101,7 +121,6 @@ ip_pool_t *ip_pool_list[IPL_LOGSIZE] = { NULL, NULL, NULL, NULL, #ifdef TEST_POOL -ipfrwlock_t ip_poolrw; void treeprint __P((ip_pool_t *)); int @@ -227,9 +246,10 @@ ip_pool_t *ipo; /* ------------------------------------------------------------------------ */ int ip_pool_init() { + bzero((char *)&ipoolstat, sizeof(ipoolstat)); -#if !defined(_KERNEL) || (BSD < 199306) +#if (!defined(_KERNEL) || (BSD < 199306)) rn_init(); #endif return 0; @@ -263,11 +283,12 @@ void ip_pool_fini() } } -#if !defined(_KERNEL) || (BSD < 199306) +#if (!defined(_KERNEL) || (BSD < 199306)) rn_fini(); #endif } + /* ------------------------------------------------------------------------ */ /* Function: ip_pool_statistics */ /* Returns: int - 0 = success, else error */ @@ -291,7 +312,11 @@ iplookupop_t *op; for (i = 0; i < IPL_LOGSIZE; i++) stats.ipls_list[i] = ip_pool_list[i]; } else if (unit >= 0 && unit < IPL_LOGSIZE) { - stats.ipls_list[unit] = ip_pool_list[unit]; + if (op->iplo_name[0] != '\0') + stats.ipls_list[unit] = ip_pool_find(unit, + op->iplo_name); + else + stats.ipls_list[unit] = ip_pool_list[unit]; } else err = EINVAL; if (err == 0) @@ -300,6 +325,7 @@ iplookupop_t *op; } + /* ------------------------------------------------------------------------ */ /* Function: ip_pool_find */ /* Returns: int - 0 = success, else error */ @@ -315,7 +341,7 @@ char *name; ip_pool_t *p; for (p = ip_pool_list[unit]; p != NULL; p = p->ipo_next) - if (strcmp(p->ipo_name, name) == 0) + if (strncmp(p->ipo_name, name, sizeof(p->ipo_name)) == 0) break; return p; } @@ -325,7 +351,7 @@ char *name; /* Function: ip_pool_findeq */ /* Returns: int - 0 = success, else error */ /* Parameters: ipo(I) - pointer to the pool getting the new node. */ -/* addr(I) - */ +/* addr(I) - pointer to address information to delete */ /* mask(I) - */ /* */ /* Searches for an exact match of an entry in the pool. */ @@ -335,15 +361,20 @@ ip_pool_t *ipo; addrfamily_t *addr, *mask; { struct radix_node *n; + SPL_INT(s); + SPL_NET(s); + RADIX_NODE_HEAD_LOCK(ipo->ipo_head); n = ipo->ipo_head->rnh_lookup(addr, mask, ipo->ipo_head); + RADIX_NODE_HEAD_UNLOCK(ipo->ipo_head); + SPL_X(s); return (ip_pool_node_t *)n; } /* ------------------------------------------------------------------------ */ /* Function: ip_pool_search */ -/* Returns: int - 0 == +ve match, -1 == error, 1 == -ve match */ +/* Returns: int - 0 == +ve match, -1 == error, 1 == -ve/no match */ /* Parameters: tptr(I) - pointer to the pool to search */ /* version(I) - IP protocol version (4 or 6) */ /* dptr(I) - pointer to address information */ @@ -385,7 +416,9 @@ void *dptr; READ_ENTER(&ip_poolrw); + RADIX_NODE_HEAD_LOCK(ipo->ipo_head); rn = ipo->ipo_head->rnh_matchaddr(&v, ipo->ipo_head); + RADIX_NODE_HEAD_UNLOCK(ipo->ipo_head); if ((rn != NULL) && ((rn->rn_flags & RNF_ROOT) == 0)) { m = (ip_pool_node_t *)rn; @@ -435,8 +468,10 @@ int info; bcopy(mask, &x->ipn_mask, sizeof(*mask)); x->ipn_mask.adf_len = sizeof(x->ipn_mask); + RADIX_NODE_HEAD_LOCK(ipo->ipo_head); rn = ipo->ipo_head->rnh_addaddr(&x->ipn_addr, &x->ipn_mask, ipo->ipo_head, x->ipn_nodes); + RADIX_NODE_HEAD_UNLOCK(ipo->ipo_head); #ifdef DEBUG_POOL printf("Added %p at %p\n", x, rn); #endif @@ -496,11 +531,22 @@ iplookupop_t *op; ip_pool_t *p; poolnum = IPOOL_ANON; + +#if defined(SNPRINTF) && defined(_KERNEL) + (void)SNPRINTF(name, sizeof(name), "%x", poolnum); +#else (void)sprintf(name, "%x", poolnum); +#endif + for (p = ip_pool_list[unit]; p != NULL; ) { - if (strcmp(name, p->ipo_name) == 0) { + if (strncmp(name, p->ipo_name, + sizeof(p->ipo_name)) == 0) { poolnum++; +#if defined(SNPRINTF) && defined(_KERNEL) + (void)SNPRINTF(name, sizeof(name), "%x", poolnum); +#else (void)sprintf(name, "%x", poolnum); +#endif p = ip_pool_list[unit]; } else p = p->ipo_next; @@ -556,11 +602,13 @@ ip_pool_node_t *ipe; if (n == NULL) return ENOENT; + RADIX_NODE_HEAD_LOCK(ipo->ipo_head); ipo->ipo_head->rnh_deladdr(&n->ipn_addr, &n->ipn_mask, ipo->ipo_head); + RADIX_NODE_HEAD_UNLOCK(ipo->ipo_head); KFREE(n); - ipoolstat.ipls_nodes--; + ipoolstat.ipls_nodes--; return 0; } @@ -597,6 +645,47 @@ iplookupop_t *op; /* ------------------------------------------------------------------------ */ +/* Function: ip_pool_flush */ +/* Returns: int - number of pools deleted */ +/* Parameters: fp(I) - which pool(s) to flush */ +/* Locks: WRITE(ip_poolrw) or WRITE(ipf_global) */ +/* */ +/* Free all pools associated with the device that matches the unit number */ +/* passed in with operation. */ +/* */ +/* NOTE: Because this function is called out of ipldetach() where ip_poolrw */ +/* may not be initialised, we can't use an ASSERT to enforce the locking */ +/* assertion that one of the two (ip_poolrw,ipf_global) is held. */ +/* ------------------------------------------------------------------------ */ +int ip_pool_flush(fp) +iplookupflush_t *fp; +{ + int i, num = 0, unit, err; + ip_pool_t *p, *q; + iplookupop_t op; + + unit = fp->iplf_unit; + + for (i = 0; i <= IPL_LOGMAX; i++) { + if (unit != IPLT_ALL && i != unit) + continue; + for (q = ip_pool_list[i]; (p = q) != NULL; ) { + op.iplo_unit = i; + (void)strncpy(op.iplo_name, p->ipo_name, + sizeof(op.iplo_name)); + q = p->ipo_next; + err = ip_pool_destroy(&op); + if (err == 0) + num++; + else + break; + } + } + return num; +} + + +/* ------------------------------------------------------------------------ */ /* Function: ip_pool_free */ /* Returns: void */ /* Parameters: ipo(I) - pointer to pool structure */ @@ -615,16 +704,20 @@ ip_pool_t *ipo; { ip_pool_node_t *n; + RADIX_NODE_HEAD_LOCK(ipo->ipo_head); while ((n = ipo->ipo_list) != NULL) { ipo->ipo_head->rnh_deladdr(&n->ipn_addr, &n->ipn_mask, ipo->ipo_head); + *n->ipn_pnext = n->ipn_next; if (n->ipn_next) n->ipn_next->ipn_pnext = n->ipn_pnext; + KFREE(n); ipoolstat.ipls_nodes--; } + RADIX_NODE_HEAD_UNLOCK(ipo->ipo_head); ipo->ipo_list = NULL; if (ipo->ipo_next != NULL) @@ -658,7 +751,8 @@ ip_pool_t *ipo; } -# if defined(_KERNEL) && (BSD > 199306) +# if defined(_KERNEL) && ((BSD >= 198911) && !defined(__osf__) && \ + !defined(__hpux) && !defined(__sgi)) static int rn_freenode(struct radix_node *n, void *p) { @@ -678,13 +772,15 @@ rn_freehead(rnh) struct radix_node_head *rnh; { - (void)rn_walktree(rnh, rn_freenode, rnh); + RADIX_NODE_HEAD_LOCK(rnh); + (*rnh->rnh_walktree)(rnh, rn_freenode, rnh); rnh->rnh_addaddr = NULL; rnh->rnh_deladdr = NULL; rnh->rnh_matchaddr = NULL; rnh->rnh_lookup = NULL; rnh->rnh_walktree = NULL; + RADIX_NODE_HEAD_UNLOCK(rnh); Free(rnh); } diff --git a/usr/src/common/ipf/ip_proxy.c b/usr/src/uts/common/inet/ipf/ip_proxy.c index 3d31d6a2b2..99f8a14b88 100644 --- a/usr/src/common/ipf/ip_proxy.c +++ b/usr/src/uts/common/inet/ipf/ip_proxy.c @@ -3,7 +3,7 @@ * * See the IPFILTER.LICENCE file for details on licencing. * - * Copyright 2003 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -20,7 +20,9 @@ #include <sys/param.h> #include <sys/time.h> #include <sys/file.h> -#include <sys/fcntl.h> +#if !defined(AIX) +# include <sys/fcntl.h> +#endif #if !defined(_KERNEL) && !defined(__KERNEL__) # include <stdio.h> # include <string.h> @@ -33,11 +35,14 @@ struct file; # include <sys/uio.h> # undef _KERNEL #endif -#include <sys/protosw.h> +#if !defined(linux) +# include <sys/protosw.h> +#endif #include <sys/socket.h> #if defined(_KERNEL) # if !defined(__NetBSD__) && !defined(sun) && !defined(__osf__) && \ - !defined(__OpenBSD__) && !defined(__hpux) + !defined(__OpenBSD__) && !defined(__hpux) && !defined(__sgi) && \ + !defined(AIX) # include <sys/ctype.h> # endif # include <sys/systm.h> @@ -73,70 +78,49 @@ struct file; #include <netinet/in.h> #include <netinet/in_systm.h> #include <netinet/ip.h> -#include <netinet/ip_var.h> +#ifndef linux +# include <netinet/ip_var.h> +#endif #include <netinet/tcp.h> #include <netinet/udp.h> #include <netinet/ip_icmp.h> -#include <netinet/tcpip.h> - -#if SOLARIS2 >= 10 -#include "ip_compat.h" -#include "ip_fil.h" -#include "ip_nat.h" -#include "ip_state.h" -#include "ip_proxy.h" -#else #include "netinet/ip_compat.h" +#include <netinet/tcpip.h> #include "netinet/ip_fil.h" #include "netinet/ip_nat.h" #include "netinet/ip_state.h" #include "netinet/ip_proxy.h" -#endif - #if (__FreeBSD_version >= 300000) # include <sys/malloc.h> #endif -#if !defined(lint) -static const char rcsid[] = "@(#)$Id: ip_proxy.c,v 2.49 2003/06/14 02:56:40 darrenr Exp $"; +#include "netinet/ip_ftp_pxy.c" +#include "netinet/ip_rcmd_pxy.c" +# include "netinet/ip_pptp_pxy.c" +#if defined(_KERNEL) +# include "netinet/ip_irc_pxy.c" +# include "netinet/ip_raudio_pxy.c" +# include "netinet/ip_h323_pxy.c" +# include "netinet/ip_netbios_pxy.c" #endif +#include "netinet/ip_ipsec_pxy.c" +#include "netinet/ip_rpcb_pxy.c" +/* END OF INCLUDES */ -static int appr_fixseqack __P((fr_info_t *, ip_t *, ap_session_t *, int )); +#if !defined(lint) +static const char rcsid[] = "@(#)$Id: ip_proxy.c,v 2.62.2.14 2005/06/18 02:41:33 darrenr Exp $"; +#endif +static int appr_fixseqack __P((fr_info_t *, ip_t *, ap_session_t *, int )); #define AP_SESS_SIZE 53 -#if SOLARIS2 >= 10 -#include "ip_ftp_pxy.c" #if defined(_KERNEL) -#include "ip_irc_pxy.c" -#include "ip_rcmd_pxy.c" -#include "ip_raudio_pxy.c" -#include "ip_h323_pxy.c" -#ifdef IPFILTER_PRO -#include "ip_msnrpc_pxy.c" -#endif -#include "ip_netbios_pxy.c" -#endif -#include "ip_ipsec_pxy.c" -#include "ip_rpcb_pxy.c" +int ipf_proxy_debug = 0; #else -#include "netinet/ip_ftp_pxy.c" -#if defined(_KERNEL) -#include "netinet/ip_irc_pxy.c" -#include "netinet/ip_rcmd_pxy.c" -#include "netinet/ip_raudio_pxy.c" -#include "netinet/ip_h323_pxy.c" -#ifdef IPFILTER_PRO -#include "netinet/ip_msnrpc_pxy.c" -#endif -#include "netinet/ip_netbios_pxy.c" -#endif -#include "netinet/ip_ipsec_pxy.c" -#include "netinet/ip_rpcb_pxy.c" +int ipf_proxy_debug = 2; #endif - ap_session_t *ap_sess_tab[AP_SESS_SIZE]; ap_session_t *ap_sess_list = NULL; aproxy_t *ap_proxylist = NULL; @@ -168,7 +152,12 @@ aproxy_t ap_proxies[] = { #ifdef IPF_IPSEC_PROXY { NULL, "ipsec", (char)IPPROTO_UDP, 0, 0, ippr_ipsec_init, ippr_ipsec_fini, ippr_ipsec_new, ippr_ipsec_del, - NULL, ippr_ipsec_out, NULL, NULL }, + ippr_ipsec_inout, ippr_ipsec_inout, ippr_ipsec_match, NULL }, +#endif +#ifdef IPF_PPTP_PROXY + { NULL, "pptp", (char)IPPROTO_TCP, 0, 0, + ippr_pptp_init, ippr_pptp_fini, ippr_pptp_new, ippr_pptp_del, + ippr_pptp_inout, ippr_pptp_inout, NULL, NULL }, #endif #ifdef IPF_H323_PROXY { NULL, "h323", (char)IPPROTO_TCP, 0, 0, ippr_h323_init, ippr_h323_fini, @@ -201,14 +190,22 @@ aproxy_t *ap; for (a = ap_proxies; a->apr_p; a++) if ((a->apr_p == ap->apr_p) && !strncmp(a->apr_label, ap->apr_label, - sizeof(ap->apr_label))) + sizeof(ap->apr_label))) { + if (ipf_proxy_debug > 1) + printf("appr_add: %s/%d already present (B)\n", + a->apr_label, a->apr_p); return -1; + } for (a = ap_proxylist; a->apr_p; a = a->apr_next) if ((a->apr_p == ap->apr_p) && !strncmp(a->apr_label, ap->apr_label, - sizeof(ap->apr_label))) + sizeof(ap->apr_label))) { + if (ipf_proxy_debug > 1) + printf("appr_add: %s/%d already present (D)\n", + a->apr_label, a->apr_p); return -1; + } ap->apr_next = ap_proxylist; ap_proxylist = ap; if (ap->apr_init != NULL) @@ -229,12 +226,22 @@ ap_ctl_t *ctl; int error; a = appr_lookup(ctl->apc_p, ctl->apc_label); - if (a == NULL) + if (a == NULL) { + if (ipf_proxy_debug > 1) + printf("appr_ctl: can't find %s/%d\n", + ctl->apc_label, ctl->apc_p); error = ESRCH; - else if (a->apr_ctl == NULL) + } else if (a->apr_ctl == NULL) { + if (ipf_proxy_debug > 1) + printf("appr_ctl: no ctl function for %s/%d\n", + ctl->apc_label, ctl->apc_p); error = ENXIO; - else + } else { error = (*a->apr_ctl)(a, ctl); + if ((error != 0) && (ipf_proxy_debug > 1)) + printf("appr_ctl: %s/%d ctl error %d\n", + a->apr_label, a->apr_p, error); + } return error; } @@ -253,10 +260,16 @@ aproxy_t *ap; if (a == ap) { a->apr_flags |= APR_DELETE; *app = a->apr_next; - if (ap->apr_ref != 0) + if (ap->apr_ref != 0) { + if (ipf_proxy_debug > 2) + printf("appr_del: orphaning %s/%d\n", + ap->apr_label, ap->apr_p); return 1; + } return 0; } + if (ipf_proxy_debug > 1) + printf("appr_del: proxy %lx not found\n", (u_long)ap); return -1; } @@ -283,12 +296,8 @@ ipnat_t *nat; int appr_ioctl(data, cmd, mode) caddr_t data; +ioctlcmd_t cmd; int mode; -#if defined(__NetBSD__) || defined(__OpenBSD__) || (__FreeBSD_version >= 300003) -u_long cmd; -#else -int cmd; -#endif { ap_ctl_t ctl; caddr_t ptr; @@ -320,7 +329,8 @@ int cmd; if (error == 0) error = appr_ctl(&ctl); - if (ctl.apc_dsize > 0 && ptr != NULL && ctl.apc_data == ptr) { + if ((ctl.apc_dsize > 0) && (ptr != NULL) && + (ctl.apc_data == ptr)) { KFREES(ptr, ctl.apc_dsize); } break; @@ -342,17 +352,37 @@ nat_t *nat; { aproxy_t *apr; ipnat_t *ipn; + int result; ipn = nat->nat_ptr; - if (ipn == NULL) + if (ipf_proxy_debug > 8) + printf("appr_match(%lx,%lx) aps %lx ptr %lx\n", + (u_long)fin, (u_long)nat, (u_long)nat->nat_aps, + (u_long)ipn); + + if ((fin->fin_flx & (FI_SHORT|FI_BAD)) != 0) { + if (ipf_proxy_debug > 0) + printf("appr_match: flx 0x%x (BAD|SHORT)\n", + fin->fin_flx); return -1; + } + apr = ipn->in_apr; - if ((apr == NULL) || (apr->apr_flags & APR_DELETE) || - (nat->nat_aps == NULL)) + if ((apr == NULL) || (apr->apr_flags & APR_DELETE)) { + if (ipf_proxy_debug > 0) + printf("appr_match:apr %lx apr_flags 0x%x\n", + (u_long)apr, apr ? apr->apr_flags : 0); return -1; - if (apr->apr_match != NULL) - if ((*apr->apr_match)(fin, nat->nat_aps, nat) != 0) + } + + if (apr->apr_match != NULL) { + result = (*apr->apr_match)(fin, nat->nat_aps, nat); + if (result != 0) { + if (ipf_proxy_debug > 4) + printf("appr_match: result %d\n", result); return -1; + } + } return 0; } @@ -369,18 +399,34 @@ nat_t *nat; register ap_session_t *aps; aproxy_t *apr; - if ((nat->nat_ptr == NULL) || (nat->nat_aps != NULL)) + if (ipf_proxy_debug > 8) + printf("appr_new(%lx,%lx) \n", (u_long)fin, (u_long)nat); + + if ((nat->nat_ptr == NULL) || (nat->nat_aps != NULL)) { + if (ipf_proxy_debug > 0) + printf("appr_new: nat_ptr %lx nat_aps %lx\n", + (u_long)nat->nat_ptr, (u_long)nat->nat_aps); return -1; + } apr = nat->nat_ptr->in_apr; - if (!apr || (apr->apr_flags & APR_DELETE) || - (fin->fin_p != apr->apr_p)) + if ((apr->apr_flags & APR_DELETE) || + (fin->fin_p != apr->apr_p)) { + if (ipf_proxy_debug > 2) + printf("appr_new: apr_flags 0x%x p %d/%d\n", + apr->apr_flags, fin->fin_p, apr->apr_p); return -1; + } KMALLOC(aps, ap_session_t *); - if (!aps) + if (!aps) { + if (ipf_proxy_debug > 0) + printf("appr_new: malloc failed (%lu)\n", + (u_long)sizeof(ap_session_t)); return -1; + } + bzero((char *)aps, sizeof(*aps)); aps->aps_p = fin->fin_p; aps->aps_data = NULL; @@ -392,6 +438,9 @@ nat_t *nat; KFREES(aps->aps_data, aps->aps_psiz); } KFREE(aps); + if (ipf_proxy_debug > 2) + printf("appr_new: new(%lx) failed\n", + (u_long)apr->apr_new); return -1; } aps->aps_nat = nat; @@ -413,10 +462,10 @@ int appr_check(fin, nat) fr_info_t *fin; nat_t *nat; { -#if SOLARIS && defined(_KERNEL) && (SOLARIS2 >= 6) -#if defined(ICK_VALID) +#if SOLARIS && defined(_KERNEL) && (SOLARIS2 >= 6) +# if defined(ICK_VALID) mb_t *m; -#endif +# endif int dosum = 1; #endif tcphdr_t *tcp = NULL; @@ -430,14 +479,17 @@ nat_t *nat; u_32_t s1, s2, sd; #endif - if (fin->fin_flx & FI_BAD) + if (fin->fin_flx & FI_BAD) { + if (ipf_proxy_debug > 0) + printf("appr_check: flx 0x%x (BAD)\n", fin->fin_flx); return -1; + } #ifndef IPFILTER_CKSUM if ((fin->fin_out == 0) && (fr_checkl4sum(fin) == -1)) { -# if PROXY_DEBUG || !defined(_KERNEL) - printf("proxy l4 checksum failure\n"); -# endif + if (ipf_proxy_debug > 0) + printf("appr_check: l4 checksum failure %d\n", + fin->fin_p); if (fin->fin_p == IPPROTO_TCP) frstats[fin->fin_out].fr_tcpbad++; return -1; @@ -450,9 +502,14 @@ nat_t *nat; * If there is data in this packet to be proxied then try and * get it all into the one buffer, else drop it. */ +#if defined(MENTAT) || defined(HAVE_M_PULLDOWN) if ((fin->fin_dlen > 0) && !(fin->fin_flx & FI_COALESCE)) - if (fr_coalesce(fin) == -1) + if (fr_coalesce(fin) == -1) { + if (ipf_proxy_debug > 0) + printf("appr_check: fr_coalesce failed %x\n", fin->fin_flx); return -1; + } +#endif ip = fin->fin_ip; switch (fin->fin_p) @@ -490,16 +547,14 @@ nat_t *nat; } rv = APR_EXIT(err); - if (rv == 1) { -#if PROXY_DEBUG || !defined(_KERNEL) - printf("proxy says bad packet received\n"); -#endif + if (((ipf_proxy_debug > 0) && (rv != 0)) || + (ipf_proxy_debug > 8)) + printf("appr_check: out %d err %x rv %d\n", + fin->fin_out, err, rv); + if (rv == 1) return -1; - } + if (rv == 2) { -#if PROXY_DEBUG || !defined(_KERNEL) - printf("proxy says free app proxy data\n"); -#endif appr_free(apr); nat->nat_aps = NULL; return -1; @@ -567,6 +622,9 @@ char *name; { aproxy_t *ap; + if (ipf_proxy_debug > 8) + printf("appr_lookup(%d,%s)\n", pr, name); + for (ap = ap_proxies; ap->apr_p; ap++) if ((ap->apr_p == pr) && !strncmp(name, ap->apr_label, sizeof(ap->apr_label))) { @@ -580,6 +638,8 @@ char *name; ap->apr_ref++; return ap; } + if (ipf_proxy_debug > 2) + printf("appr_lookup: failed for %d/%s\n", pr, name); return NULL; } @@ -648,10 +708,10 @@ int inc; /* switch to other set ? */ if ((aps->aps_seqmin[!sel] > aps->aps_seqmin[sel]) && (seq1 > aps->aps_seqmin[!sel])) { -#if PROXY_DEBUG - printf("proxy out switch set seq %d -> %d %x > %x\n", - sel, !sel, seq1, aps->aps_seqmin[!sel]); -#endif + if (ipf_proxy_debug > 7) + printf("proxy out switch set seq %d -> %d %x > %x\n", + sel, !sel, seq1, + aps->aps_seqmin[!sel]); sel = aps->aps_sel[out] = !sel; } @@ -668,11 +728,10 @@ int inc; if (inc && (seq1 > aps->aps_seqmin[!sel])) { aps->aps_seqmin[sel] = seq1 + nlen - 1; aps->aps_seqoff[sel] = aps->aps_seqoff[sel] + inc; -#if PROXY_DEBUG - printf("proxy seq set %d at %x to %d + %d\n", sel, - aps->aps_seqmin[sel], aps->aps_seqoff[sel], - inc); -#endif + if (ipf_proxy_debug > 7) + printf("proxy seq set %d at %x to %d + %d\n", + sel, aps->aps_seqmin[sel], + aps->aps_seqoff[sel], inc); } /***/ @@ -683,10 +742,10 @@ int inc; /* switch to other set ? */ if ((aps->aps_ackmin[!sel] > aps->aps_ackmin[sel]) && (seq1 > aps->aps_ackmin[!sel])) { -#if PROXY_DEBUG - printf("proxy out switch set ack %d -> %d %x > %x\n", - sel, !sel, seq1, aps->aps_ackmin[!sel]); -#endif + if (ipf_proxy_debug > 7) + printf("proxy out switch set ack %d -> %d %x > %x\n", + sel, !sel, seq1, + aps->aps_ackmin[!sel]); sel = aps->aps_sel[1 - out] = !sel; } @@ -702,10 +761,9 @@ int inc; /* switch to other set ? */ if ((aps->aps_ackmin[!sel] > aps->aps_ackmin[sel]) && (seq1 > aps->aps_ackmin[!sel])) { -#if PROXY_DEBUG - printf("proxy in switch set ack %d -> %d %x > %x\n", - sel, !sel, seq1, aps->aps_ackmin[!sel]); -#endif + if (ipf_proxy_debug > 7) + printf("proxy in switch set ack %d -> %d %x > %x\n", + sel, !sel, seq1, aps->aps_ackmin[!sel]); sel = aps->aps_sel[out] = !sel; } @@ -722,11 +780,11 @@ int inc; if (inc && (seq1 > aps->aps_ackmin[!sel])) { aps->aps_ackmin[!sel] = seq1 + nlen - 1; aps->aps_ackoff[!sel] = aps->aps_ackoff[sel] + inc; -#if PROXY_DEBUG - printf("proxy ack set %d at %x to %d + %d\n", !sel, - aps->aps_seqmin[!sel], aps->aps_seqoff[sel], - inc); -#endif + + if (ipf_proxy_debug > 7) + printf("proxy ack set %d at %x to %d + %d\n", + !sel, aps->aps_seqmin[!sel], + aps->aps_seqoff[sel], inc); } /***/ @@ -737,19 +795,17 @@ int inc; /* switch to other set ? */ if ((aps->aps_seqmin[!sel] > aps->aps_seqmin[sel]) && (seq1 > aps->aps_seqmin[!sel])) { -#if PROXY_DEBUG - printf("proxy in switch set seq %d -> %d %x > %x\n", - sel, !sel, seq1, aps->aps_seqmin[!sel]); -#endif + if (ipf_proxy_debug > 7) + printf("proxy in switch set seq %d -> %d %x > %x\n", + sel, !sel, seq1, aps->aps_seqmin[!sel]); sel = aps->aps_sel[1 - out] = !sel; } if (aps->aps_seqoff[sel] != 0) { -#if PROXY_DEBUG - printf("sel %d seqoff %d seq1 %x seqmin %x\n", sel, - aps->aps_seqoff[sel], seq1, - aps->aps_seqmin[sel]); -#endif + if (ipf_proxy_debug > 7) + printf("sel %d seqoff %d seq1 %x seqmin %x\n", + sel, aps->aps_seqoff[sel], seq1, + aps->aps_seqmin[sel]); if (seq1 > aps->aps_seqmin[sel]) { seq2 = aps->aps_seqoff[sel]; tcp->th_ack = htonl(seq1 - seq2); @@ -757,10 +813,10 @@ int inc; } } } -#if PROXY_DEBUG - printf("appr_fixseqack: seq %lx ack %lx\n", ntohl(tcp->th_seq), - ntohl(tcp->th_ack)); -#endif + + if (ipf_proxy_debug > 8) + printf("appr_fixseqack: seq %x ack %x\n", + ntohl(tcp->th_seq), ntohl(tcp->th_ack)); return ch ? 2 : 0; } diff --git a/usr/src/common/ipf/ip_state.c b/usr/src/uts/common/inet/ipf/ip_state.c index d4e59521ed..9a5586a208 100644 --- a/usr/src/common/ipf/ip_state.c +++ b/usr/src/uts/common/inet/ipf/ip_state.c @@ -3,7 +3,7 @@ * * See the IPFILTER.LICENCE file for details on licencing. * - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -48,11 +48,12 @@ struct file; # include <sys/ioctl.h> #endif #include <sys/time.h> -#include <sys/protosw.h> +#if !defined(linux) +# include <sys/protosw.h> +#endif #include <sys/socket.h> #if defined(_KERNEL) # include <sys/systm.h> -# include <sys/cmn_err.h> # if !defined(__SVR4) && !defined(__svr4__) # include <sys/mbuf.h> # endif @@ -76,31 +77,21 @@ struct file; #include <netinet/in_systm.h> #include <netinet/ip.h> #include <netinet/tcp.h> -#include <netinet/ip_var.h> -#if !defined(__hpux) +#if !defined(linux) +# include <netinet/ip_var.h> +#endif +#if !defined(__hpux) && !defined(linux) # include <netinet/tcp_fsm.h> #endif #include <netinet/udp.h> #include <netinet/ip_icmp.h> -#if SOLARIS2 >= 10 -#include "ip_compat.h" -#else #include "netinet/ip_compat.h" -#endif #include <netinet/tcpip.h> -#if SOLARIS2 >= 10 -#include "ip_fil.h" -#include "ip_nat.h" -#include "ip_frag.h" -#include "ip_state.h" -#include "ip_proxy.h" -#else #include "netinet/ip_fil.h" #include "netinet/ip_nat.h" #include "netinet/ip_frag.h" #include "netinet/ip_state.h" #include "netinet/ip_proxy.h" -#endif #ifdef IPFILTER_SYNC #include "netinet/ip_sync.h" #endif @@ -117,10 +108,12 @@ struct file; # include <sys/systm.h> # endif #endif +/* END OF INCLUDES */ + #if !defined(lint) static const char sccsid[] = "@(#)ip_state.c 1.8 6/5/96 (C) 1993-2000 Darren Reed"; -static const char rcsid[] = "@(#)$Id: ip_state.c,v 2.157 2003/07/01 18:30:21 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id: ip_state.c,v 2.186.2.36 2005/08/11 19:58:03 darrenr Exp $"; #endif static ipstate_t **ips_table = NULL; @@ -128,16 +121,12 @@ static u_long *ips_seed = NULL; static int ips_num = 0; static u_long ips_last_force_flush = 0; ips_stat_t ips_stats; -#ifdef USE_MUTEXES -extern ipfrwlock_t ipf_state, ipf_mutex; -extern ipfmutex_t ipf_rw, ipf_stinsert; -#endif #ifdef USE_INET6 static ipstate_t *fr_checkicmp6matchingstate __P((fr_info_t *)); #endif static ipstate_t *fr_matchsrcdst __P((fr_info_t *, ipstate_t *, i6addr_t *, - i6addr_t *, tcphdr_t *)); + i6addr_t *, tcphdr_t *, u_32_t)); static ipstate_t *fr_checkicmpmatchingstate __P((fr_info_t *)); static int fr_state_flush __P((int, int)); static ips_stat_t *fr_statetstats __P((void)); @@ -159,15 +148,16 @@ int fr_stgetent __P((caddr_t)); #define DOUBLE_HASH(x) (((x) + ips_seed[(x) % fr_statesize]) % fr_statesize) u_long fr_tcpidletimeout = FIVE_DAYS, - fr_tcpclosewait = IPF_TTLVAL(TCP_MSL), - fr_tcplastack = IPF_TTLVAL(TCP_MSL), - fr_tcptimeout = IPF_TTLVAL(TCP_MSL), + fr_tcpclosewait = IPF_TTLVAL(2 * TCP_MSL), + fr_tcplastack = IPF_TTLVAL(2 * TCP_MSL), + fr_tcptimeout = IPF_TTLVAL(2 * TCP_MSL), fr_tcpclosed = IPF_TTLVAL(60), fr_tcphalfclosed = IPF_TTLVAL(2 * 3600), /* 2 hours */ fr_udptimeout = IPF_TTLVAL(120), fr_udpacktimeout = IPF_TTLVAL(12), fr_icmptimeout = IPF_TTLVAL(60), - fr_icmpacktimeout = IPF_TTLVAL(6); + fr_icmpacktimeout = IPF_TTLVAL(6), + fr_iptimeout = IPF_TTLVAL(60); int fr_statemax = IPSTATE_MAX, fr_statesize = IPSTATE_SIZE; int fr_state_doflush = 0, @@ -178,6 +168,7 @@ int fr_state_doflush = 0, ipftq_t ips_tqtqb[IPF_TCP_NSTATES], ips_udptq, ips_udpacktq, + ips_iptq, ips_icmptq, ips_icmpacktq, *ips_utqe = NULL; @@ -208,7 +199,7 @@ int fr_stateinit() KMALLOCS(ips_seed, u_long *, fr_statesize * sizeof(*ips_seed)); if (ips_seed == NULL) - return -1; + return -2; for (i = 0; i < fr_statesize; i++) { /* * XXX - ips_seed[X] should be a random number of sorts. @@ -257,28 +248,38 @@ int fr_stateinit() fr_sttab_init(ips_tqtqb); ips_tqtqb[IPF_TCP_NSTATES - 1].ifq_next = &ips_udptq; ips_udptq.ifq_ttl = (u_long)fr_udptimeout; + ips_udptq.ifq_ref = 1; ips_udptq.ifq_head = NULL; ips_udptq.ifq_tail = &ips_udptq.ifq_head; MUTEX_INIT(&ips_udptq.ifq_lock, "ipftq udp tab"); ips_udptq.ifq_next = &ips_udpacktq; ips_udpacktq.ifq_ttl = (u_long)fr_udpacktimeout; + ips_udpacktq.ifq_ref = 1; ips_udpacktq.ifq_head = NULL; ips_udpacktq.ifq_tail = &ips_udpacktq.ifq_head; MUTEX_INIT(&ips_udpacktq.ifq_lock, "ipftq udpack tab"); ips_udpacktq.ifq_next = &ips_icmptq; ips_icmptq.ifq_ttl = (u_long)fr_icmptimeout; + ips_icmptq.ifq_ref = 1; ips_icmptq.ifq_head = NULL; ips_icmptq.ifq_tail = &ips_icmptq.ifq_head; MUTEX_INIT(&ips_icmptq.ifq_lock, "ipftq icmp tab"); ips_icmptq.ifq_next = &ips_icmpacktq; ips_icmpacktq.ifq_ttl = (u_long)fr_icmpacktimeout; + ips_icmpacktq.ifq_ref = 1; ips_icmpacktq.ifq_head = NULL; ips_icmpacktq.ifq_tail = &ips_icmpacktq.ifq_head; MUTEX_INIT(&ips_icmpacktq.ifq_lock, "ipftq icmpack tab"); - ips_icmpacktq.ifq_next = NULL; + ips_icmpacktq.ifq_next = &ips_iptq; + ips_iptq.ifq_ttl = (u_long)fr_iptimeout; + ips_iptq.ifq_ref = 1; + ips_iptq.ifq_head = NULL; + ips_iptq.ifq_tail = &ips_iptq.ifq_head; + MUTEX_INIT(&ips_iptq.ifq_lock, "ipftq ip tab"); + ips_iptq.ifq_next = NULL; RWLOCK_INIT(&ipf_state, "ipf IP state rwlock"); - MUTEX_INIT(&ipf_stinsert, "ipf stat insert mutex"); + MUTEX_INIT(&ipf_stinsert, "ipf state insert mutex"); fr_state_init = 1; ips_last_force_flush = fr_ticks; @@ -296,11 +297,27 @@ int fr_stateinit() /* ------------------------------------------------------------------------ */ void fr_stateunload() { + ipftq_t *ifq, *ifqnext; ipstate_t *is; WRITE_ENTER(&ipf_state); while ((is = ips_list) != NULL) fr_delstate(is, 0); + + /* + * Proxy timeout queues are not cleaned here because although they + * exist on the state list, appr_unload is called after fr_stateunload + * and the proxies actually are responsible for them being created. + * Should the proxy timeouts have their own list? There's no real + * justification as this is the only complicationA + */ + for (ifq = ips_utqe; ifq != NULL; ifq = ifqnext) { + ifqnext = ifq->ifq_next; + if (((ifq->ifq_flags & IFQF_PROXY) == 0) && + (fr_deletetimeoutqueue(ifq) == 0)) + fr_freetimeoutqueue(ifq); + } + ips_stats.iss_inuse = 0; ips_num = 0; @@ -310,7 +327,7 @@ void fr_stateunload() MUTEX_DESTROY(&ips_icmptq.ifq_lock); MUTEX_DESTROY(&ips_udpacktq.ifq_lock); MUTEX_DESTROY(&ips_icmpacktq.ifq_lock); - fr_state_init = 0; + MUTEX_DESTROY(&ips_iptq.ifq_lock); } if (ips_table != NULL) { @@ -335,8 +352,8 @@ void fr_stateunload() if (fr_state_init == 1) { fr_state_init = 0; + RW_DESTROY(&ipf_state); MUTEX_DESTROY(&ipf_stinsert); - MUTEX_INIT(&ipf_stinsert, "ipf stat insert mutex"); } } @@ -408,11 +425,7 @@ caddr_t data; /* ------------------------------------------------------------------------ */ int fr_state_ioctl(data, cmd, mode) caddr_t data; -#if defined(__NetBSD__) || defined(__OpenBSD__) -u_long cmd; -#else -int cmd; -#endif +ioctlcmd_t cmd; int mode; { int arg, ret, error = 0; @@ -429,23 +442,23 @@ int mode; * Flush the state table */ case SIOCIPFFL : - (void) BCOPYIN(data, (char *)&arg, sizeof(arg)); + BCOPYIN(data, (char *)&arg, sizeof(arg)); if (arg == 0 || arg == 1) { WRITE_ENTER(&ipf_state); ret = fr_state_flush(arg, 4); RWLOCK_EXIT(&ipf_state); - (void) BCOPYOUT((char *)&ret, data, sizeof(ret)); + BCOPYOUT((char *)&ret, data, sizeof(ret)); } else error = EINVAL; break; #ifdef USE_INET6 case SIOCIPFL6 : - (void) BCOPYIN(data, (char *)&arg, sizeof(arg)); + BCOPYIN(data, (char *)&arg, sizeof(arg)); if (arg == 0 || arg == 1) { WRITE_ENTER(&ipf_state); ret = fr_state_flush(arg, 6); RWLOCK_EXIT(&ipf_state); - (void) BCOPYOUT((char *)&ret, data, sizeof(ret)); + BCOPYOUT((char *)&ret, data, sizeof(ret)); } else error = EINVAL; break; @@ -461,7 +474,7 @@ int mode; int tmp; tmp = ipflog_clear(IPL_LOGSTATE); - (void) BCOPYOUT((char *)&tmp, data, sizeof(tmp)); + BCOPYOUT((char *)&tmp, data, sizeof(tmp)); } break; /* @@ -471,7 +484,7 @@ int mode; if (!(mode & FWRITE)) error = EPERM; else { - (void) BCOPYIN((char *)data, (char *)&ipstate_logging, + BCOPYIN((char *)data, (char *)&ipstate_logging, sizeof(ipstate_logging)); } break; @@ -479,15 +492,15 @@ int mode; * Return the current state of logging. */ case SIOCGETLG : - (void) BCOPYOUT((char *)&ipstate_logging, (char *)data, - sizeof(ipstate_logging)); + BCOPYOUT((char *)&ipstate_logging, (char *)data, + sizeof(ipstate_logging)); break; /* * Return the number of bytes currently waiting to be read. */ case FIONREAD : arg = iplused[IPL_LOGSTATE]; /* returned in an int */ - (void) BCOPYOUT((char *)&arg, data, sizeof(arg)); + BCOPYOUT((char *)&arg, data, sizeof(arg)); break; #endif /* @@ -501,13 +514,17 @@ int mode; * means no packets match). */ case SIOCSTLCK : - error = fr_lock(data, &fr_state_lock); + if (!(mode & FWRITE)) { + error = EPERM; + } else { + fr_lock(data, &fr_state_lock); + } break; /* * Add an entry to the current state table. */ case SIOCSTPUT : - if (!fr_state_lock) { + if (!fr_state_lock || !(mode &FWRITE)) { error = EACCES; break; } @@ -575,7 +592,8 @@ caddr_t data; } ips.ips_next = isn->is_next; bcopy((char *)isn, (char *)&ips.ips_is, sizeof(ips.ips_is)); - if (isn->is_rule) + ips.ips_rule = isn->is_rule; + if (isn->is_rule != NULL) bcopy((char *)isn->is_rule, (char *)&ips.ips_fr, sizeof(ips.ips_fr)); error = fr_outobj(data, &ips, IPFOBJ_STATESAVE); @@ -600,7 +618,7 @@ caddr_t data; { ipstate_t *is, *isn; ipstate_save_t ips; - int error, out, i; + int error, i; frentry_t *fr; char *name; @@ -613,12 +631,23 @@ caddr_t data; return ENOMEM; bcopy((char *)&ips.ips_is, (char *)isn, sizeof(*isn)); - MUTEX_NUKE(&isn->is_lock); + bzero((char *)isn, offsetof(struct ipstate, is_pkts)); + isn->is_sti.tqe_pnext = NULL; + isn->is_sti.tqe_next = NULL; + isn->is_sti.tqe_ifq = NULL; + isn->is_sti.tqe_parent = isn; + isn->is_ifp[0] = NULL; + isn->is_ifp[1] = NULL; + isn->is_ifp[2] = NULL; + isn->is_ifp[3] = NULL; isn->is_sync = NULL; - fr = isn->is_rule; + fr = ips.ips_rule; + if (fr == NULL) { - fr_stinsert(isn); + READ_ENTER(&ipf_state); + fr_stinsert(isn, 0); MUTEX_EXIT(&isn->is_lock); + RWLOCK_EXIT(&ipf_state); return 0; } @@ -629,7 +658,6 @@ caddr_t data; return ENOMEM; } bcopy((char *)&ips.ips_fr, (char *)fr, sizeof(*fr)); - out = fr->fr_flags & FR_OUTQUE ? 1 : 0; isn->is_rule = fr; ips.ips_is.is_rule = fr; MUTEX_NUKE(&fr->fr_lock); @@ -640,26 +668,17 @@ caddr_t data; */ for (i = 0; i < 4; i++) { name = fr->fr_ifnames[i]; - if ((name[1] == '\0') && - ((name[0] == '-') || (name[0] == '*'))) { - fr->fr_ifas[i] = NULL; - } else if (*name != '\0') { - fr->fr_ifas[i] = GETIFP(name, fr->fr_v); - if (fr->fr_ifas[i] == NULL) - fr->fr_ifas[i] = (void *)-1; - else { - (void) COPYIFNAME(fr->fr_ifas[i], - isn->is_ifname[i]); - } - } - isn->is_ifp[out] = fr->fr_ifas[i]; + fr->fr_ifas[i] = fr_resolvenic(name, fr->fr_v); + name = isn->is_ifname[i]; + isn->is_ifp[i] = fr_resolvenic(name, isn->is_v); } + fr->fr_ref = 0; fr->fr_dsize = 0; fr->fr_data = NULL; - fr_resolvdest(&fr->fr_tif, fr->fr_v); - fr_resolvdest(&fr->fr_dif, fr->fr_v); + fr_resolvedest(&fr->fr_tif, fr->fr_v); + fr_resolvedest(&fr->fr_dif, fr->fr_v); /* * send a copy back to userland of what we ended up @@ -672,58 +691,71 @@ caddr_t data; KFREE(fr); return EFAULT; } + READ_ENTER(&ipf_state); + fr_stinsert(isn, 0); + MUTEX_EXIT(&isn->is_lock); + RWLOCK_EXIT(&ipf_state); + } else { + READ_ENTER(&ipf_state); for (is = ips_list; is; is = is->is_next) - if (is->is_rule == fr) + if (is->is_rule == fr) { + fr_stinsert(isn, 0); + MUTEX_EXIT(&isn->is_lock); break; - if (!is) { + } + + if (is == NULL) { KFREE(isn); - return ESRCH; + isn = NULL; } + RWLOCK_EXIT(&ipf_state); + + return (isn == NULL) ? ESRCH : 0; } - fr_stinsert(isn); - MUTEX_EXIT(&isn->is_lock); + return 0; } /* ------------------------------------------------------------------------ */ -/* Function: fr_stinsert */ -/* Returns: Nil */ -/* Parameters: is(I) - pointer to state structure */ +/* Function: fr_stinsert */ +/* Returns: Nil */ +/* Parameters: is(I) - pointer to state structure */ +/* rev(I) - flag indicating forward/reverse direction of packet */ /* */ /* Inserts a state structure into the hash table (for lookups) and the list */ /* of state entries (for enumeration). Resolves all of the interface names */ /* to pointers and adjusts running stats for the hash table as appropriate. */ -/* */ -/* NOTE: Holds a lock for is_lock mutex upon return. */ -/* */ +/* */ +/* Locking: it is assumed that some kind of lock on ipf_state is held. */ +/* Exits with is_lock initialised and held. */ /* ------------------------------------------------------------------------ */ -void fr_stinsert(is) +void fr_stinsert(is, rev) ipstate_t *is; +int rev; { + frentry_t *fr; u_int hv; - char *name; int i; - is->is_sti.tqe_parent = is; - MUTEX_INIT(&is->is_lock, "ipf state entry"); - MUTEX_ENTER(&is->is_lock); + + fr = is->is_rule; + if (fr != NULL) { + MUTEX_ENTER(&fr->fr_lock); + fr->fr_ref++; + fr->fr_statecnt++; + MUTEX_EXIT(&fr->fr_lock); + } /* * Look up all the interface names in the state entry. */ for (i = 0; i < 4; i++) { - name = is->is_ifname[i]; - if ((name[1] == '\0') && - ((name[0] == '-') || (name[0] == '*'))) { - is->is_ifp[0] = NULL; - } else if (*name != '\0') { - is->is_ifp[i] = GETIFP(name, is->is_v); - if (is->is_ifp[i] == NULL) - is->is_ifp[i] = (void *)-1; - } + if (is->is_ifp[i] != NULL) + continue; + is->is_ifp[i] = fr_resolvenic(is->is_ifname[i], is->is_v); } /* @@ -733,6 +765,12 @@ ipstate_t *is; hv = is->is_hv % fr_statesize; is->is_hv = hv; + /* + * We need to get both of these locks...the first because it is + * possible that once the insert is complete another packet might + * come along, match the entry and want to update it. + */ + MUTEX_ENTER(&is->is_lock); MUTEX_ENTER(&ipf_stinsert); /* @@ -754,6 +792,8 @@ ipstate_t *is; ips_stats.iss_bucketlen[hv]++; ips_num++; MUTEX_EXIT(&ipf_stinsert); + + fr_setstatequeue(is, rev); } @@ -781,12 +821,14 @@ u_int flags; frentry_t *fr; tcphdr_t *tcp; grehdr_t *gre; - ipftq_t *ifq; void *ifp; int out; if (fr_state_lock || - (fin->fin_flx & (FI_SHORT|FI_STATE|FI_FRAGTAIL|FI_BAD|FI_OOW))) + (fin->fin_flx & (FI_SHORT|FI_STATE|FI_FRAGBODY|FI_BAD))) + return NULL; + + if ((fin->fin_flx & FI_OOW) && !(fin->fin_tcpf & TH_SYN)) return NULL; fr = fin->fin_fr; @@ -813,12 +855,10 @@ u_int flags; ic = NULL; tcp = NULL; - ifq = NULL; out = fin->fin_out; is = &ips; bzero((char *)is, sizeof(*is)); is->is_die = 1 + fr_ticks; - is->is_flags = flags & IS_INHERITED; /* * Copy and calculate... @@ -864,15 +904,11 @@ u_int flags; case IPPROTO_ICMPV6 : ic = fin->fin_dp; - if ((ic->icmp_type & ICMP6_INFOMSG_MASK) == 0) - return NULL; - switch (ic->icmp_type) { case ICMP6_ECHO_REQUEST : is->is_icmp.ici_type = ic->icmp_type; hv += (is->is_icmp.ici_id = ic->icmp_id); - hv += (is->is_icmp.ici_seq = ic->icmp_seq); break; case ICMP6_MEMBERSHIP_QUERY : case ND_ROUTER_SOLICIT : @@ -884,7 +920,6 @@ u_int flags; return NULL; } ATOMIC_INCL(ips_stats.iss_icmp); - ifq = &ips_icmptq; break; #endif case IPPROTO_ICMP : @@ -898,13 +933,11 @@ u_int flags; case ICMP_MASKREQ : is->is_icmp.ici_type = ic->icmp_type; hv += (is->is_icmp.ici_id = ic->icmp_id); - hv += (is->is_icmp.ici_seq = ic->icmp_seq); break; default : return NULL; } ATOMIC_INCL(ips_stats.iss_icmp); - ifq = &ips_icmptq; break; case IPPROTO_GRE : @@ -912,9 +945,10 @@ u_int flags; is->is_gre.gs_flags = gre->gr_flags; is->is_gre.gs_ptype = gre->gr_ptype; - is->is_gre.gs_call = gre->gr_call; - hv += is->is_gre.gs_call; - ifq = &ips_udptq; + if (GRE_REV(is->is_gre.gs_flags) == 1) { + is->is_call[0] = fin->fin_data[0]; + is->is_call[1] = fin->fin_data[1]; + } break; case IPPROTO_TCP : @@ -937,6 +971,12 @@ u_int flags; * If this is a real packet then initialise fields in the * state information structure from the TCP header information. */ + + is->is_maxdwin = 1; + is->is_maxswin = ntohs(tcp->th_win); + if (is->is_maxswin == 0) + is->is_maxswin = 1; + if ((fin->fin_flx & FI_IGNORE) == 0) { is->is_send = ntohl(tcp->th_seq) + fin->fin_dlen - (TCP_OFF(tcp) << 2) + @@ -963,15 +1003,15 @@ u_int flags; } if ((tcp->th_flags & TH_OPENING) == TH_SYN) - is->is_flags |= IS_TCPFSM; + flags |= IS_TCPFSM; + else { + is->is_maxdwin = is->is_maxswin * 2; + is->is_dend = ntohl(tcp->th_ack); + is->is_maxdend = ntohl(tcp->th_ack); + is->is_maxdwin *= 2; + } } - is->is_maxdwin = 1; - is->is_maxswin = ntohs(tcp->th_win); - if (is->is_maxswin == 0) - is->is_maxswin = 1; - - ifq = ips_tqtqb; /* * If we're creating state for a starting connection, start the * timer on it as we'll never see an error if it fails to @@ -990,16 +1030,15 @@ u_int flags; hv += tcp->th_sport; } ATOMIC_INCL(ips_stats.iss_udp); - ifq = &ips_udptq; break; default : - ifq = &ips_udptq; break; } hv = DOUBLE_HASH(hv); is->is_hv = hv; is->is_rule = fr; + is->is_flags = flags & IS_INHERITED; /* * Look for identical state. @@ -1029,19 +1068,17 @@ u_int flags; */ if (fr != NULL) { (void) strncpy(is->is_group, fr->fr_group, FR_GROUPLEN); - MUTEX_ENTER(&fr->fr_lock); - fr->fr_ref++; - fr->fr_statecnt++; - MUTEX_EXIT(&fr->fr_lock); if (fr->fr_age[0] != 0) { is->is_tqehead[0] = fr_addtimeoutqueue(&ips_utqe, fr->fr_age[0]); - is->is_tqehead[1] = is->is_tqehead[0]; is->is_sti.tqe_flags |= TQE_RULEBASED; } - if (fr->fr_age[0] != 0 && fr->fr_age[1] != fr->fr_age[0]) + if (fr->fr_age[1] != 0) { is->is_tqehead[1] = fr_addtimeoutqueue(&ips_utqe, fr->fr_age[1]); + is->is_sti.tqe_flags |= TQE_RULEBASED; + } + is->is_tag = fr->fr_logtag; is->is_ifp[(out << 1) + 1] = fr->fr_ifas[1]; @@ -1050,15 +1087,15 @@ u_int flags; if (((ifp = fr->fr_ifas[1]) != NULL) && (ifp != (void *)-1)) { - (void) COPYIFNAME(ifp, is->is_ifname[(out << 1) + 1]); + COPYIFNAME(ifp, is->is_ifname[(out << 1) + 1]); } if (((ifp = fr->fr_ifas[2]) != NULL) && (ifp != (void *)-1)) { - (void) COPYIFNAME(ifp, is->is_ifname[(1 - out) << 1]); + COPYIFNAME(ifp, is->is_ifname[(1 - out) << 1]); } if (((ifp = fr->fr_ifas[3]) != NULL) && (ifp != (void *)-1)) { - (void) COPYIFNAME(ifp, is->is_ifname[((1 - out) << 1) + 1]); + COPYIFNAME(ifp, is->is_ifname[((1 - out) << 1) + 1]); } } else { pass = fr_flags; @@ -1067,10 +1104,15 @@ u_int flags; is->is_ifp[out << 1] = fin->fin_ifp; if (fin->fin_ifp != NULL) { - (void) COPYIFNAME(fin->fin_ifp, is->is_ifname[out << 1]); + COPYIFNAME(fin->fin_ifp, is->is_ifname[out << 1]); } - is->is_ref = 1; + /* + * It may seem strange to set is_ref to 2, but fr_check() will call + * fr_statederef() after calling fr_addstate() and the idea is to + * have it exist at the end of fr_check() with is_ref == 1. + */ + is->is_ref = 2; is->is_pass = pass; is->is_pkts[0] = 0, is->is_bytes[0] = 0; is->is_pkts[1] = 0, is->is_bytes[1] = 0; @@ -1078,33 +1120,31 @@ u_int flags; is->is_pkts[3] = 0, is->is_bytes[3] = 0; if ((fin->fin_flx & FI_IGNORE) == 0) { is->is_pkts[out] = 1; - is->is_bytes[out] = fin->fin_dlen + fin->fin_hlen; + is->is_bytes[out] = fin->fin_plen; is->is_flx[out][0] = fin->fin_flx & FI_CMP; + is->is_flx[out][0] &= ~FI_OOW; } if (pass & FR_STSTRICT) is->is_flags |= IS_STRICT; + if (pass & FR_STATESYNC) + is->is_flags |= IS_STATESYNC; + /* * We want to check everything that is a property of this packet, * but we don't (automatically) care about it's fragment status as * this may change. */ is->is_v = fin->fin_v; - if (is->is_v == 6) { /* Only IPv6 has fragment options */ - /* - * XXX - This magic value 0x08 comes from ip6exthdr[]. In time - * the flag values for IPv6 extension headers should be given a - * symbolic name rather than used like this. - */ - is->is_opt[0] = fin->fin_optmsk & ~(0x08); - is->is_optmsk[0] = 0xffffffff & ~(0x08); - } else { - is->is_opt[0] = fin->fin_optmsk; - is->is_optmsk[0] = 0xffffffff; + is->is_opt[0] = fin->fin_optmsk; + is->is_optmsk[0] = 0xffffffff; + is->is_optmsk[1] = 0xffffffff; + if (is->is_v == 6) { + is->is_opt[0] &= ~0x8; + is->is_optmsk[0] &= ~0x8; + is->is_optmsk[1] &= ~0x8; } - is->is_opt[1] = 0; - is->is_optmsk[1] = 0; is->is_sec = fin->fin_secmsk; is->is_secmsk = 0xffff; is->is_auth = fin->fin_auth; @@ -1120,19 +1160,8 @@ u_int flags; READ_ENTER(&ipf_state); is->is_me = stsave; - fr_stinsert(is); - /* - * Add the state entry to the end of this timeout queue. - */ - MUTEX_ENTER(&ifq->ifq_lock); - is->is_sti.tqe_pnext = ifq->ifq_tail; - *ifq->ifq_tail = &is->is_sti; - ifq->ifq_tail = &is->is_sti.tqe_next; - is->is_sti.tqe_next = NULL; - is->is_sti.tqe_ifq = ifq; - is->is_sti.tqe_die = fr_ticks + ifq->ifq_ttl; - MUTEX_EXIT(&ifq->ifq_lock); + fr_stinsert(is, fin->fin_rev); if (fin->fin_p == IPPROTO_TCP) { /* @@ -1141,19 +1170,25 @@ u_int flags; * connect. */ (void) fr_tcp_age(&is->is_sti, fin, ips_tqtqb, is->is_flags); + MUTEX_EXIT(&is->is_lock); #ifdef IPFILTER_SCAN - (void) isc_attachis(is); + if ((is->is_flags & SI_CLONE) == 0) + (void) ipsc_attachis(is); #endif + } else { + MUTEX_EXIT(&is->is_lock); } #ifdef IPFILTER_SYNC - is->is_sync = ipfsync_new(SMC_STATE, fin, is); + if ((is->is_flags & IS_STATESYNC) && ((is->is_flags & SI_CLONE) == 0)) + is->is_sync = ipfsync_new(SMC_STATE, fin, is); #endif if (ipstate_logging) ipstate_log(is, ISL_NEW); - MUTEX_EXIT(&is->is_lock); RWLOCK_EXIT(&ipf_state); + fin->fin_state = is; fin->fin_rev = IP6_NEQ(&is->is_dst, &fin->fin_daddr); + fin->fin_flx |= FI_STATE; if (fin->fin_flx & FI_FRAG) (void) fr_newfrag(fin, pass ^ FR_KEEPSTATE); @@ -1180,13 +1215,14 @@ tcpdata_t *td; char buf[64], *s, opt; mb_t *m = NULL; - off = fin->fin_hlen + sizeof(*tcp); - len = (TCP_OFF(tcp) << 2) - sizeof(*tcp); - if (fin->fin_plen < off + len) + len = (TCP_OFF(tcp) << 2); + if (fin->fin_dlen < len) return 0; + len -= sizeof(*tcp); + + off = fin->fin_plen - fin->fin_dlen + sizeof(*tcp) + fin->fin_ipoff; m = fin->fin_m; - off += (char *)fin->fin_ip - MTOD(m, char *); mlen = MSGDSIZE(m) - off; if (len > mlen) { len = mlen; @@ -1267,7 +1303,8 @@ ipstate_t *is; tcpdata_t *fdata, *tdata; source = !fin->fin_rev; - if (source && (ntohs(is->is_sport) != fin->fin_data[0])) + if (((is->is_flags & IS_TCPFSM) != 0) && (source == 1) && + (ntohs(is->is_sport) != fin->fin_data[0])) source = 0; fdata = &is->is_tcp.ts_data[!source]; tdata = &is->is_tcp.ts_data[source]; @@ -1276,7 +1313,7 @@ ipstate_t *is; if (fr_tcpinwindow(fin, fdata, tdata, tcp, is->is_flags)) { #ifdef IPFILTER_SCAN if (is->is_flags & (IS_SC_CLIENT|IS_SC_SERVER)) { - isc_packet(fin, is); + ipsc_packet(fin, is); if (FR_ISBLOCK(is->is_pass)) { MUTEX_EXIT(&is->is_lock); return 1; @@ -1329,6 +1366,7 @@ ipstate_t *is; fr_checknewisn(fin, is); } + ret = 1; } else fin->fin_flx |= FI_OOW; MUTEX_EXIT(&is->is_lock); @@ -1361,7 +1399,7 @@ ipstate_t *is; if (((i == 0) && !(is->is_flags & IS_ISNSYN)) || ((i == 1) && !(is->is_flags & IS_ISNACK))) { - old = tcp->th_seq; + old = ntohl(tcp->th_seq); new = fr_newisn(fin); is->is_isninc[i] = new - old; CALC_SUMD(old, new, sumd); @@ -1376,8 +1414,8 @@ ipstate_t *is; /* Function: fr_tcpinwindow */ /* Returns: int - 1 == packet inside TCP "window", 0 == not inside. */ /* Parameters: fin(I) - pointer to packet information */ -/* fdata(I) - pointer to tcp state informatio (reverse) */ -/* tdata(I) - pointer to tcp state informatio (forward) */ +/* fdata(I) - pointer to tcp state informatio (forward) */ +/* tdata(I) - pointer to tcp state informatio (reverse) */ /* tcp(I) - pointer to TCP packet header */ /* */ /* Given a packet has matched addresses and ports, check to see if it is */ @@ -1428,8 +1466,8 @@ int flags; tdata->td_winscale = 0; tdata->td_winflags = 0; } - } - + } + end = seq + fin->fin_dlen - (TCP_OFF(tcp) << 2) + ((tcpflags & TH_SYN) ? 1 : 0) + ((tcpflags & TH_FIN) ? 1 : 0); @@ -1525,7 +1563,6 @@ tcphdr_t *tcp; ipstate_t *is; { ipstate_t *clone; - frentry_t *fr; u_32_t send; if (ips_num == fr_statemax) { @@ -1565,21 +1602,22 @@ ipstate_t *is; clone->is_maxswin = 1; } - fr = clone->is_rule; - if (fr != NULL) { - MUTEX_ENTER(&fr->fr_lock); - fr->fr_ref++; - fr->fr_statecnt++; - MUTEX_EXIT(&fr->fr_lock); - } clone->is_flags &= ~SI_CLONE; clone->is_flags |= SI_CLONED; - fr_stinsert(clone); - clone->is_ref = 1; + fr_stinsert(clone, fin->fin_rev); + clone->is_ref = 2; if (clone->is_p == IPPROTO_TCP) { - (void) fr_tcp_age(&clone->is_sti, fin, ips_tqtqb, clone->is_flags); + (void) fr_tcp_age(&clone->is_sti, fin, ips_tqtqb, + clone->is_flags); } MUTEX_EXIT(&clone->is_lock); +#ifdef IPFILTER_SCAN + (void) ipsc_attachis(is); +#endif +#ifdef IPFILTER_SYNC + if (is->is_flags & IS_STATESYNC) + clone->is_sync = ipfsync_new(SMC_STATE, fin, clone); +#endif return clone; } @@ -1597,28 +1635,31 @@ ipstate_t *is; /* ret gets set to one if the match succeeds, else remains 0. If it is */ /* still 0 after the test. no match. */ /* ------------------------------------------------------------------------ */ -static ipstate_t *fr_matchsrcdst(fin, is, src, dst, tcp) +static ipstate_t *fr_matchsrcdst(fin, is, src, dst, tcp, cmask) fr_info_t *fin; ipstate_t *is; i6addr_t *src, *dst; tcphdr_t *tcp; +u_32_t cmask; { int ret = 0, rev, out, flags, flx = 0, idx; u_short sp, dp; + u_32_t cflx; void *ifp; rev = IP6_NEQ(&is->is_dst, dst); ifp = fin->fin_ifp; out = fin->fin_out; - flags = is->is_flags & (SI_WILDA); + flags = is->is_flags; sp = 0; dp = 0; if (tcp != NULL) { - flags = is->is_flags; - sp = tcp->th_sport; - dp = tcp->th_dport; - if (!rev) { + sp = htons(fin->fin_sport); + dp = ntohs(fin->fin_dport); + } + if (!rev) { + if (tcp != NULL) { if (!(flags & SI_W_SPORT) && (sp != is->is_sport)) rev = 1; else if (!(flags & SI_W_DPORT) && (dp != is->is_dport)) @@ -1646,19 +1687,28 @@ tcphdr_t *tcp; */ if (rev == 0) { if ((IP6_EQ(&is->is_dst, dst) || (flags & SI_W_DADDR)) && - (IP6_EQ(&is->is_src, src) || (flags & SI_W_SADDR)) && - (!tcp || ((sp == is->is_sport || flags & SI_W_SPORT) && - (dp == is->is_dport || flags & SI_W_DPORT)))) { - ret = 1; + (IP6_EQ(&is->is_src, src) || (flags & SI_W_SADDR))) { + if (tcp) { + if ((sp == is->is_sport || flags & SI_W_SPORT)&& + (dp == is->is_dport || flags & SI_W_DPORT)) + ret = 1; + } else { + ret = 1; + } } } else { if ((IP6_EQ(&is->is_dst, src) || (flags & SI_W_DADDR)) && - (IP6_EQ(&is->is_src, dst) || (flags & SI_W_SADDR)) && - (!tcp || ((sp == is->is_dport || flags & SI_W_DPORT) && - (dp == is->is_sport || flags & SI_W_SPORT)))) { - ret = 1; + (IP6_EQ(&is->is_src, dst) || (flags & SI_W_SADDR))) { + if (tcp) { + if ((dp == is->is_sport || flags & SI_W_SPORT)&& + (sp == is->is_dport || flags & SI_W_DPORT)) + ret = 1; + } else { + ret = 1; + } } } + if (ret == 0) return NULL; @@ -1733,12 +1783,13 @@ tcphdr_t *tcp; } } - flx = fin->fin_flx & FI_CMP; + flx = fin->fin_flx & cmask; + cflx = is->is_flx[out][rev]; /* * Match up any flags set from IP options. */ - if ((is->is_flx[out][rev] && (flx != is->is_flx[out][rev])) || + if ((cflx && (flx != (cflx & cmask))) || ((fin->fin_optmsk & is->is_optmsk[rev]) != is->is_opt[rev]) || ((fin->fin_secmsk & is->is_secmsk) != is->is_sec) || ((fin->fin_auth & is->is_authmsk) != is->is_auth)) @@ -1756,9 +1807,12 @@ tcphdr_t *tcp; if ((flags & (SI_W_SPORT|SI_W_DPORT))) { if ((flags & SI_CLONE) != 0) { - is = fr_stclone(fin, tcp, is); - if (is == NULL) + ipstate_t *clone; + + clone = fr_stclone(fin, tcp, is); + if (clone == NULL) return NULL; + is = clone; } else { ATOMIC_DECL(ips_stats.iss_wild); } @@ -1766,19 +1820,19 @@ tcphdr_t *tcp; if ((flags & SI_W_SPORT) != 0) { if (rev == 0) { is->is_sport = sp; - is->is_send = htonl(tcp->th_seq); + is->is_send = ntohl(tcp->th_seq); } else { is->is_sport = dp; - is->is_send = htonl(tcp->th_ack); + is->is_send = ntohl(tcp->th_ack); } is->is_maxsend = is->is_send + 1; } else if ((flags & SI_W_DPORT) != 0) { if (rev == 0) { is->is_dport = dp; - is->is_dend = htonl(tcp->th_ack); + is->is_dend = ntohl(tcp->th_ack); } else { is->is_dport = sp; - is->is_dend = htonl(tcp->th_seq); + is->is_dend = ntohl(tcp->th_seq); } is->is_maxdend = is->is_dend + 1; } @@ -1791,12 +1845,10 @@ tcphdr_t *tcp; if (is->is_flx[out][rev] == 0) { is->is_flx[out][rev] = flx; - if (is->is_v == 6) { /* Only IPv6 has fragment options */ - is->is_opt[rev] = fin->fin_optmsk & ~(0x08); - is->is_optmsk[rev] = 0xffffffff & ~(0x08); - } else { - is->is_opt[rev] = fin->fin_optmsk; - is->is_optmsk[rev] = 0xffffffff; + is->is_opt[rev] = fin->fin_optmsk; + if (is->is_v == 6) { + is->is_opt[rev] &= ~0x8; + is->is_optmsk[rev] &= ~0x8; } } @@ -1807,7 +1859,7 @@ tcphdr_t *tcp; if (is->is_ifp[idx] == NULL && (*is->is_ifname[idx] == '\0' || *is->is_ifname[idx] == '*')) { is->is_ifp[idx] = ifp; - (void) COPYIFNAME(fin->fin_ifp, is->is_ifname[idx]); + COPYIFNAME(ifp, is->is_ifname[idx]); } fin->fin_rev = rev; return is; @@ -1831,34 +1883,28 @@ fr_info_t *fin; ipstate_t *is, **isp; u_short sport, dport; u_char pr; + int backward, i, oi; i6addr_t dst, src; struct icmp *ic; u_short savelen; icmphdr_t *icmp; - int backward, i; fr_info_t ofin; tcphdr_t *tcp; - int type, len; + int len; ip_t *oip; u_int hv; /* * Does it at least have the return (basic) IP header ? + * Is it an actual recognised ICMP error type? * Only a basic IP header (no options) should be with * an ICMP error header. */ if ((fin->fin_v != 4) || (fin->fin_hlen != sizeof(ip_t)) || - (fin->fin_plen < ICMPERR_MINPKTLEN)) + (fin->fin_plen < ICMPERR_MINPKTLEN) || + !(fin->fin_flx & FI_ICMPERR)) return NULL; ic = fin->fin_dp; - type = ic->icmp_type; - /* - * If it's not an error type, then return - */ - if ((type != ICMP_UNREACH) && (type != ICMP_SOURCEQUENCH) && - (type != ICMP_REDIRECT) && (type != ICMP_TIMXCEED) && - (type != ICMP_PARAMPROB)) - return NULL; oip = (ip_t *)((char *)ic + ICMPERR_ICMPHLEN); /* @@ -1921,7 +1967,7 @@ fr_info_t *fin; */ savelen = oip->ip_len; oip->ip_len = len; - oip->ip_off = htons(oip->ip_off); + oip->ip_off = ntohs(oip->ip_off); ofin.fin_flx = FI_NOCKSUM; ofin.fin_v = 4; @@ -1949,8 +1995,6 @@ fr_info_t *fin; switch (oip->ip_p) { case IPPROTO_ICMP : - icmp = (icmphdr_t *)((char *)oip + (IP_HL(oip) << 2)); - /* * an ICMP error can only be generated as a result of an * ICMP query, not as the response on an ICMP error @@ -1958,39 +2002,52 @@ fr_info_t *fin; * XXX theoretically ICMP_ECHOREP and the other reply's are * ICMP query's as well, but adding them here seems strange XXX */ - if ((icmp->icmp_type != ICMP_ECHO) && - (icmp->icmp_type != ICMP_TSTAMP) && - (icmp->icmp_type != ICMP_IREQ) && - (icmp->icmp_type != ICMP_MASKREQ)) + if ((ofin.fin_flx & FI_ICMPERR) != 0) return NULL; /* * perform a lookup of the ICMP packet in the state table */ + icmp = (icmphdr_t *)((char *)oip + (IP_HL(oip) << 2)); hv = (pr = oip->ip_p); src.in4 = oip->ip_src; hv += src.in4.s_addr; dst.in4 = oip->ip_dst; hv += dst.in4.s_addr; hv += icmp->icmp_id; - hv += icmp->icmp_seq; hv = DOUBLE_HASH(hv); READ_ENTER(&ipf_state); for (isp = &ips_table[hv]; ((is = *isp) != NULL); ) { isp = &is->is_hnext; - if ((is->is_p != pr) || (is->is_v != 4) || - (is->is_pass & FR_NOICMPERR)) + if ((is->is_p != pr) || (is->is_v != 4)) continue; - is = fr_matchsrcdst(&ofin, is, &src, &dst, NULL); - if (is != NULL && - fr_matchicmpqueryreply(is->is_v, &is->is_icmp, - icmp, fin->fin_rev)) { - backward = IP6_NEQ(&is->is_src, &dst); - i = (backward << 1) + fin->fin_out; + if (is->is_pass & FR_NOICMPERR) + continue; + is = fr_matchsrcdst(&ofin, is, &src, &dst, + NULL, FI_ICMPCMP); + if (is != NULL) { + if ((is->is_pass & FR_NOICMPERR) != 0) { + RWLOCK_EXIT(&ipf_state); + return NULL; + } + /* + * i : the index of this packet (the icmp + * unreachable) + * oi : the index of the original packet found + * in the icmp header (i.e. the packet + * causing this icmp) + * backward : original packet was backward + * compared to the state + */ + backward = IP6_NEQ(&is->is_src, &src); + fin->fin_rev = !backward; + i = (!backward << 1) + fin->fin_out; + oi = (backward << 1) + ofin.fin_out; + if (is->is_icmppkts[i] > is->is_pkts[oi]) + continue; ips_stats.iss_hits++; - is->is_pkts[i]++; - is->is_bytes[i] += fin->fin_plen; + is->is_icmppkts[i]++; return is; } } @@ -2029,13 +2086,25 @@ fr_info_t *fin; * short flag is set. */ if ((is->is_p == pr) && (is->is_v == 4) && - !(is->is_pass & FR_NOICMPERR) && - (is = fr_matchsrcdst(&ofin, is, &src, &dst, tcp))) { - backward = IP6_NEQ(&is->is_dst, &src); - i = (backward << 1) + fin->fin_out; + (is = fr_matchsrcdst(&ofin, is, &src, &dst, + tcp, FI_ICMPCMP))) { + /* + * i : the index of this packet (the icmp unreachable) + * oi : the index of the original packet found in the + * icmp header (i.e. the packet causing this icmp) + * backward : original packet was backward compared to + * the state + */ + backward = IP6_NEQ(&is->is_src, &src); + fin->fin_rev = !backward; + i = (!backward << 1) + fin->fin_out; + oi = (backward << 1) + ofin.fin_out; + + if (((is->is_pass & FR_NOICMPERR) != 0) || + (is->is_icmppkts[i] > is->is_pkts[oi])) + break; ips_stats.iss_hits++; - is->is_pkts[i]++; - is->is_bytes[i] += fin->fin_plen; + is->is_icmppkts[i]++; /* * we deliberately do not touch the timeouts * for the accompanying state table entry. @@ -2119,8 +2188,8 @@ ipftq_t **ifqp; u_short dport, sport; i6addr_t src, dst; struct icmp *ic; - grehdr_t *gre; ipftq_t *ifq; + int oow; is = NULL; ifq = NULL; @@ -2157,13 +2226,11 @@ ipftq_t **ifqp; { #ifdef USE_INET6 case IPPROTO_ICMPV6 : - tcp = NULL; tryagain = 0; if (v == 6) { if ((ic->icmp_type == ICMP6_ECHO_REQUEST) || (ic->icmp_type == ICMP6_ECHO_REPLY)) { hv += ic->icmp_id; - hv += ic->icmp_seq; } } READ_ENTER(&ipf_state); @@ -2173,16 +2240,14 @@ icmp6again: isp = &is->is_hnext; if ((is->is_p != pr) || (is->is_v != v)) continue; - is = fr_matchsrcdst(fin, is, &src, &dst, NULL); + is = fr_matchsrcdst(fin, is, &src, &dst, NULL, FI_CMP); if (is != NULL && fr_matchicmpqueryreply(v, &is->is_icmp, ic, fin->fin_rev)) { - if (!(is->is_sti.tqe_flags & TQE_RULEBASED)) { - if (fin->fin_rev) - ifq = &ips_icmpacktq; - else - ifq = &ips_icmptq; - } + if (fin->fin_rev) + ifq = &ips_icmpacktq; + else + ifq = &ips_icmptq; break; } } @@ -2203,6 +2268,12 @@ icmp6again: /* * No matching icmp state entry. Perhaps this is a * response to another state entry. + * + * XXX With some ICMP6 packets, the "other" address is already + * in the packet, after the ICMP6 header, and this could be + * used in place of the multicast address. However, taking + * advantage of this requires some significant code changes + * to handle the specific types where that is the case. */ if ((ips_stats.iss_wild != 0) && (v == 6) && (tryagain == 0) && !IN6_IS_ADDR_MULTICAST(&fin->fin_fi.fi_src.in6)) { @@ -2224,7 +2295,6 @@ icmp6again: case IPPROTO_ICMP : if (v == 4) { hv += ic->icmp_id; - hv += ic->icmp_seq; } hv = DOUBLE_HASH(hv); READ_ENTER(&ipf_state); @@ -2232,16 +2302,14 @@ icmp6again: isp = &is->is_hnext; if ((is->is_p != pr) || (is->is_v != v)) continue; - is = fr_matchsrcdst(fin, is, &src, &dst, NULL); + is = fr_matchsrcdst(fin, is, &src, &dst, NULL, FI_CMP); if (is != NULL && fr_matchicmpqueryreply(v, &is->is_icmp, ic, fin->fin_rev)) { - if (!(is->is_sti.tqe_flags & TQE_RULEBASED)) { - if (fin->fin_rev) - ifq = &ips_icmpacktq; - else - ifq = &ips_icmptq; - } + if (fin->fin_rev) + ifq = &ips_icmpacktq; + else + ifq = &ips_icmptq; break; } } @@ -2250,27 +2318,6 @@ icmp6again: } break; - case IPPROTO_GRE : - gre = fin->fin_dp; - hv += gre->gr_call; - tcp = NULL; - ifqp = NULL; - hv = DOUBLE_HASH(hv); - READ_ENTER(&ipf_state); - for (isp = &ips_table[hv]; ((is = *isp) != NULL); ) { - isp = &is->is_hnext; - if ((is->is_p != IPPROTO_GRE) || (is->is_v != v) || - (is->is_gre.gs_call != gre->gr_call)) - continue; - is = fr_matchsrcdst(fin, is, &src, &dst, NULL); - if (is != NULL) - break; - } - if (is == NULL) { - RWLOCK_EXIT(&ipf_state); - } - break; - case IPPROTO_TCP : case IPPROTO_UDP : ifqp = NULL; @@ -2278,6 +2325,7 @@ icmp6again: hv += sport; dport = htons(fin->fin_data[1]); hv += dport; + oow = 0; tryagain = 0; READ_ENTER(&ipf_state); retry_tcpudp: @@ -2286,9 +2334,17 @@ retry_tcpudp: isp = &is->is_hnext; if ((is->is_p != pr) || (is->is_v != v)) continue; - is = fr_matchsrcdst(fin, is, &src, &dst, tcp); - if (is != NULL) + fin->fin_flx &= ~FI_OOW; + is = fr_matchsrcdst(fin, is, &src, &dst, tcp, FI_CMP); + if (is != NULL) { + if (pr == IPPROTO_TCP) { + if (!fr_tcpstate(fin, tcp, is)) { + oow |= fin->fin_flx & FI_OOW; + continue; + } + } break; + } } if (is != NULL) { if (tryagain && @@ -2309,20 +2365,30 @@ retry_tcpudp: WRITE_ENTER(&ipf_state); goto retry_tcpudp; } + fin->fin_flx |= oow; break; +#if 0 + case IPPROTO_GRE : + gre = fin->fin_dp; + if (GRE_REV(gre->gr_flags) == 1) { + hv += gre->gr_call; + } + /* FALLTHROUGH */ +#endif default : - tcp = NULL; ifqp = NULL; - hv = DOUBLE_HASH(hv); + hvm = DOUBLE_HASH(hv); READ_ENTER(&ipf_state); - for (isp = &ips_table[hv]; ((is = *isp) != NULL); ) { + for (isp = &ips_table[hvm]; ((is = *isp) != NULL); ) { isp = &is->is_hnext; if ((is->is_p != pr) || (is->is_v != v)) continue; - is = fr_matchsrcdst(fin, is, &src, &dst, NULL); - if (is != NULL) + is = fr_matchsrcdst(fin, is, &src, &dst, NULL, FI_CMP); + if (is != NULL) { + ifq = &ips_iptq; break; + } } if (is == NULL) { RWLOCK_EXIT(&ipf_state); @@ -2330,6 +2396,9 @@ retry_tcpudp: break; } + if ((is != NULL) && ((is->is_sti.tqe_flags & TQE_RULEBASED) != 0) && + (is->is_tqehead[fin->fin_rev] != NULL)) + ifq = is->is_tqehead[fin->fin_rev]; if (ifq != NULL && ifqp != NULL) *ifqp = ifq; return is; @@ -2351,7 +2420,7 @@ fr_info_t *fin; ipstate_t *is; ipftq_t *ifq; { - ipftqent_t *tqe; + ipftqent_t *tqe; int i, pass; i = (fin->fin_rev << 1) + fin->fin_out; @@ -2360,22 +2429,21 @@ ipftq_t *ifq; * For TCP packets, ifq == NULL. For all others, check if this new * queue is different to the last one it was on and move it if so. */ - MUTEX_ENTER(&is->is_lock); tqe = &is->is_sti; + MUTEX_ENTER(&is->is_lock); if ((tqe->tqe_flags & TQE_RULEBASED) != 0) ifq = is->is_tqehead[fin->fin_rev]; - if (ifq != NULL) { + if (ifq != NULL) fr_movequeue(tqe, tqe->tqe_ifq, ifq); - is->is_die = ifq->ifq_ttl + fr_ticks; - } is->is_pkts[i]++; is->is_bytes[i] += fin->fin_plen; MUTEX_EXIT(&is->is_lock); #ifdef IPFILTER_SYNC - ipfsync_update(SMC_STATE, fin, is->is_sync); + if (is->is_flags & IS_STATESYNC) + ipfsync_update(SMC_STATE, fin, is->is_sync); #endif ATOMIC_INCL(ips_stats.iss_hits); @@ -2412,7 +2480,7 @@ u_32_t *passp; u_int pass; if (fr_state_lock || (ips_list == NULL) || - (fin->fin_flx & (FI_SHORT|FI_STATE|FI_FRAGTAIL|FI_BAD))) + (fin->fin_flx & (FI_SHORT|FI_STATE|FI_FRAGBODY|FI_BAD))) return NULL; is = NULL; @@ -2460,14 +2528,11 @@ u_32_t *passp; case IPPROTO_TCP : if (is == NULL) break; - if ((fin->fin_out == 0) && (is->is_pass & FR_NEWISN)) - fr_fixinisn(fin, is); - if (!fr_tcpstate(fin, tcp, is)) { - RWLOCK_EXIT(&ipf_state); - is = NULL; - } else { - if ((fin->fin_out == 1) && (is->is_pass & FR_NEWISN)) + if (is->is_pass & FR_NEWISN) { + if (fin->fin_out == 0) + fr_fixinisn(fin, is); + else if (fin->fin_out == 1) fr_fixoutisn(fin, is); } break; @@ -2485,18 +2550,18 @@ u_32_t *passp; matched: fr = is->is_rule; - if ((fin->fin_out == 0) && (fr->fr_nattag.ipt_num[0] != 0)) { - if (fin->fin_nattag == NULL) - return NULL; - if (fr_matchtag(&fr->fr_nattag, fin->fin_nattag) != 0) - return NULL; - } - - fin->fin_rule = is->is_rulen; if (fr != NULL) { + if ((fin->fin_out == 0) && (fr->fr_nattag.ipt_num[0] != 0)) { + if (fin->fin_nattag == NULL) + return NULL; + if (fr_matchtag(&fr->fr_nattag, fin->fin_nattag) != 0) + return NULL; + } (void) strncpy(fin->fin_group, fr->fr_group, FR_GROUPLEN); fin->fin_icode = fr->fr_icode; } + + fin->fin_rule = is->is_rulen; pass = is->is_pass; fr_updatestate(fin, is, ifq); if (fin->fin_out == 1) @@ -2531,18 +2596,23 @@ ipstate_t *is; { tcphdr_t *tcp; int rev; + u_32_t seq; tcp = fin->fin_dp; rev = fin->fin_rev; if ((is->is_flags & IS_ISNSYN) != 0) { if (rev == 0) { - tcp->th_seq += is->is_isninc[0]; + seq = ntohl(tcp->th_seq); + seq += is->is_isninc[0]; + tcp->th_seq = htonl(seq); fix_outcksum(fin, &tcp->th_sum, is->is_sumd[0]); } } if ((is->is_flags & IS_ISNACK) != 0) { if (rev == 1) { - tcp->th_seq += is->is_isninc[1]; + seq = ntohl(tcp->th_seq); + seq += is->is_isninc[1]; + tcp->th_seq = htonl(seq); fix_outcksum(fin, &tcp->th_sum, is->is_sumd[1]); } } @@ -2564,18 +2634,23 @@ ipstate_t *is; { tcphdr_t *tcp; int rev; + u_32_t ack; tcp = fin->fin_dp; rev = fin->fin_rev; if ((is->is_flags & IS_ISNSYN) != 0) { if (rev == 1) { - tcp->th_ack -= is->is_isninc[0]; + ack = ntohl(tcp->th_ack); + ack -= is->is_isninc[0]; + tcp->th_ack = htonl(ack); fix_incksum(fin, &tcp->th_sum, is->is_sumd[0]); } } if ((is->is_flags & IS_ISNACK) != 0) { if (rev == 0) { - tcp->th_ack -= is->is_isninc[1]; + ack = ntohl(tcp->th_ack); + ack -= is->is_isninc[1]; + tcp->th_ack = htonl(ack); fix_incksum(fin, &tcp->th_sum, is->is_sumd[1]); } } @@ -2590,6 +2665,9 @@ ipstate_t *is; /* Walk through all state entries and if an interface pointer match is */ /* found then look it up again, based on its name in case the pointer has */ /* changed since last time. */ +/* */ +/* If ifp is passed in as being non-null then we are only doing updates for */ +/* existing, matching, uses of it. */ /* ------------------------------------------------------------------------ */ void fr_statesync(ifp) void *ifp; @@ -2612,12 +2690,9 @@ void *ifp; * Look up all the interface names in the state entry. */ for (i = 0; i < 4; i++) { - if (is->is_ifp[i] == ifp) { - is->is_ifp[i] = GETIFP(is->is_ifname[i], - is->is_v); - if (is->is_ifp[i] == NULL) - is->is_ifp[i] = (void *)-1; - } + if (ifp == NULL || ifp == is->is_ifp[i]) + is->is_ifp[i] = fr_resolvenic(is->is_ifname[i], + is->is_v); } } RWLOCK_EXIT(&ipf_state); @@ -2639,8 +2714,6 @@ static void fr_delstate(is, why) ipstate_t *is; int why; { - ipftqent_t *tqe; - ipftq_t *ifq; ASSERT(rw_read_locked(&ipf_state.ipf_lk) == 0); @@ -2648,24 +2721,27 @@ int why; * Since we want to delete this, remove it from the state table, * where it can be found & used, first. */ - *is->is_pnext = is->is_next; - - if (is->is_next != NULL) - is->is_next->is_pnext = is->is_pnext; + if (is->is_pnext != NULL) { + *is->is_pnext = is->is_next; + if (is->is_next != NULL) + is->is_next->is_pnext = is->is_pnext; - is->is_pnext = NULL; - is->is_next = NULL; + is->is_pnext = NULL; + is->is_next = NULL; + } - *is->is_phnext = is->is_hnext; - if (is->is_hnext != NULL) - is->is_hnext->is_phnext = is->is_phnext; - if (ips_table[is->is_hv] == NULL) - ips_stats.iss_inuse--; - ips_stats.iss_bucketlen[is->is_hv]--; + if (is->is_phnext != NULL) { + *is->is_phnext = is->is_hnext; + if (is->is_hnext != NULL) + is->is_hnext->is_phnext = is->is_phnext; + if (ips_table[is->is_hv] == NULL) + ips_stats.iss_inuse--; + ips_stats.iss_bucketlen[is->is_hv]--; - is->is_phnext = NULL; - is->is_hnext = NULL; + is->is_phnext = NULL; + is->is_hnext = NULL; + } /* * Because ips_stats.iss_wild is a count of entries in the state @@ -2676,26 +2752,15 @@ int why; if (!(is->is_flags & SI_CLONED)) { ATOMIC_DECL(ips_stats.iss_wild); } + is->is_flags &= ~(SI_WILDP|SI_WILDA); } - /* * Next, remove it from the timeout queue it is in. */ - tqe = &is->is_sti; - ifq = tqe->tqe_ifq; - if (tqe->tqe_pnext != NULL) { - *tqe->tqe_pnext = tqe->tqe_next; - if (tqe->tqe_next != NULL) - tqe->tqe_next->tqe_pnext = tqe->tqe_pnext; - else /* we must be the tail anyway */ - ifq->ifq_tail = tqe->tqe_pnext; - tqe->tqe_pnext = NULL; - tqe->tqe_ifq = NULL; - } + fr_deletequeueentry(&is->is_sti); - if ((ifq->ifq_flags & IFQF_USER) != 0) - fr_deletetimeoutqueue(ifq); + is->is_me = NULL; /* * If it is still in use by something else, do not go any further, @@ -2705,12 +2770,21 @@ int why; if (is->is_ref > 0) return; + if (is->is_tqehead[0] != NULL) { + if (fr_deletetimeoutqueue(is->is_tqehead[0]) == 0) + fr_freetimeoutqueue(is->is_tqehead[0]); + } + if (is->is_tqehead[1] != NULL) { + if (fr_deletetimeoutqueue(is->is_tqehead[1]) == 0) + fr_freetimeoutqueue(is->is_tqehead[1]); + } + #ifdef IPFILTER_SYNC if (is->is_sync) ipfsync_del(is->is_sync); #endif #ifdef IPFILTER_SCAN - (void) isc_detachis(is); + (void) ipsc_detachis(is); #endif if (ipstate_logging != 0 && why != 0) @@ -2742,9 +2816,7 @@ void fr_timeoutstate() ipftq_t *ifq, *ifqnext; ipftqent_t *tqe, *tqn; ipstate_t *is; -#if defined(USE_SPL) && defined(_KERNEL) - int s; -#endif + SPL_INT(s); SPL_NET(s); WRITE_ENTER(&ipf_state); @@ -2768,10 +2840,21 @@ void fr_timeoutstate() fr_delstate(is, ISL_EXPIRE); } } + + for (ifq = ips_utqe; ifq != NULL; ifq = ifqnext) { + ifqnext = ifq->ifq_next; + + if (((ifq->ifq_flags & IFQF_DELETE) != 0) && + (ifq->ifq_ref == 0)) { + fr_freetimeoutqueue(ifq); + } + } + if (fr_state_doflush) { (void) fr_state_flush(2, 0); fr_state_doflush = 0; } + RWLOCK_EXIT(&ipf_state); SPL_X(s); } @@ -2803,9 +2886,7 @@ int which, proto; int delete, removed; long try, maxtick; u_long interval; -#if defined(_KERNEL) && !defined(MENTAT) && defined(USE_SPL) - int s; -#endif + SPL_INT(s); removed = 0; @@ -2955,6 +3036,8 @@ force_flush_skipped: /* */ /* dir == 0 : a packet from source to dest */ /* dir == 1 : a packet from dest to source */ +/* */ +/* Locking: it is assumed that the parent of the tqe structure is locked. */ /* ------------------------------------------------------------------------ */ int fr_tcp_age(tqe, fin, tqtab, flags) ipftqent_t *tqe; @@ -2971,7 +3054,7 @@ int flags; rval = 0; dir = fin->fin_rev; tcpflags = tcp->th_flags; - dlen = fin->fin_plen - fin->fin_hlen - (TCP_OFF(tcp) << 2); + dlen = fin->fin_dlen - (TCP_OFF(tcp) << 2); if (tcpflags & TH_RST) { if (!(tcpflags & TH_PUSH) && !dlen) @@ -3011,13 +3094,20 @@ int flags; * we saw an A, guess 'dir' is in ESTABLISHED * mode */ - if (ostate == IPF_TCPS_CLOSED) { + switch (ostate) + { + case IPF_TCPS_CLOSED : + case IPF_TCPS_SYN_RECEIVED : nstate = IPF_TCPS_HALF_ESTAB; rval = 1; - } else if (ostate == IPF_TCPS_ESTABLISHED || - ostate == IPF_TCPS_HALF_ESTAB) { + break; + case IPF_TCPS_HALF_ESTAB : + case IPF_TCPS_ESTABLISHED : nstate = IPF_TCPS_ESTABLISHED; rval = 1; + break; + default : + break; } } /* @@ -3038,9 +3128,10 @@ int flags; * the timeout here to fr_tcptimeout because a * connection connect timeout does not renew * after every packet that is sent. We need to - * set newage to something to indicate the - * packet has passed the check for its flags - * being valid in the TCP FSM. + * set rval so as to indicate the packet has + * passed the check for its flags being valid + * in the TCP FSM. Setting rval to 2 has the + * result of not resetting the timeout. */ rval = 2; } else if ((tcpflags & (TH_SYN|TH_FIN|TH_ACK)) == @@ -3237,9 +3328,6 @@ int flags; (u_long)tcp, tcpflags, (u_long)tqe, nstate, ostate); # endif -# ifdef DIAGNOSTIC - panic("invalid TCP state"); -# endif #else abort(); #endif @@ -3288,10 +3376,14 @@ u_int type; * structure used for logging. */ ipsl.isl_type = type; - ipsl.isl_pkts[0] = is->is_pkts[0], ipsl.isl_bytes[0] = is->is_bytes[0]; - ipsl.isl_pkts[1] = is->is_pkts[1], ipsl.isl_bytes[1] = is->is_bytes[1]; - ipsl.isl_pkts[2] = is->is_pkts[2], ipsl.isl_bytes[2] = is->is_bytes[2]; - ipsl.isl_pkts[3] = is->is_pkts[3], ipsl.isl_bytes[3] = is->is_bytes[3]; + ipsl.isl_pkts[0] = is->is_pkts[0] + is->is_icmppkts[0]; + ipsl.isl_bytes[0] = is->is_bytes[0]; + ipsl.isl_pkts[1] = is->is_pkts[1] + is->is_icmppkts[1]; + ipsl.isl_bytes[1] = is->is_bytes[1]; + ipsl.isl_pkts[2] = is->is_pkts[2] + is->is_icmppkts[2]; + ipsl.isl_bytes[2] = is->is_bytes[2]; + ipsl.isl_pkts[3] = is->is_pkts[3] + is->is_icmppkts[3]; + ipsl.isl_bytes[3] = is->is_bytes[3]; ipsl.isl_src = is->is_src; ipsl.isl_dst = is->is_dst; ipsl.isl_p = is->is_p; @@ -3321,7 +3413,11 @@ u_int type; sizes[0] = sizeof(ipsl); types[0] = 0; - (void) ipllog(IPL_LOGSTATE, NULL, items, sizes, types, 1); + if (ipllog(IPL_LOGSTATE, NULL, items, sizes, types, 1)) { + ATOMIC_INCL(ips_stats.iss_logged); + } else { + ATOMIC_INCL(ips_stats.iss_logfail); + } #endif } @@ -3341,7 +3437,7 @@ static ipstate_t *fr_checkicmp6matchingstate(fin) fr_info_t *fin; { struct icmp6_hdr *ic6, *oic; - int type, backward, i; + int backward, i; ipstate_t *is, **isp; u_short sport, dport; i6addr_t dst, src; @@ -3355,20 +3451,15 @@ fr_info_t *fin; /* * Does it at least have the return (basic) IP header ? + * Is it an actual recognised ICMP error type? * Only a basic IP header (no options) should be with * an ICMP error header. */ - if ((fin->fin_v != 6) || (fin->fin_plen < ICMP6ERR_MINPKTLEN)) + if ((fin->fin_v != 6) || (fin->fin_plen < ICMP6ERR_MINPKTLEN) || + !(fin->fin_flx & FI_ICMPERR)) return NULL; ic6 = fin->fin_dp; - type = ic6->icmp6_type; - /* - * If it's not an error type, then return - */ - if ((type != ICMP6_DST_UNREACH) && (type != ICMP6_PACKET_TOO_BIG) && - (type != ICMP6_TIME_EXCEEDED) && (type != ICMP6_PARAM_PROB)) - return NULL; oip6 = (ip6_t *)((char *)ic6 + ICMPERR_ICMPHLEN); if (fin->fin_plen < sizeof(*oip6)) @@ -3433,7 +3524,7 @@ fr_info_t *fin; (oic->icmp6_id == ic->ici_id) && (oic->icmp6_seq == ic->ici_seq) && (is = fr_matchsrcdst(&ofin, is, &src, - &dst, NULL))) { + &dst, NULL, FI_ICMPCMP))) { /* * in the state table ICMP query's are stored * with the type of the corresponding ICMP @@ -3444,9 +3535,9 @@ fr_info_t *fin; (ic->ici_type - 1 == oic->icmp6_type )) { ips_stats.iss_hits++; backward = IP6_NEQ(&is->is_dst, &src); + fin->fin_rev = !backward; i = (backward << 1) + fin->fin_out; - is->is_pkts[i]++; - is->is_bytes[i] += fin->fin_plen; + is->is_icmppkts[i]++; return is; } } @@ -3490,13 +3581,13 @@ fr_info_t *fin; if ((is->is_p != pr) || (is->is_v != 6) || (is->is_pass & FR_NOICMPERR)) continue; - is = fr_matchsrcdst(&ofin, is, &src, &dst, tcp); + is = fr_matchsrcdst(&ofin, is, &src, &dst, tcp, FI_ICMPCMP); if (is != NULL) { ips_stats.iss_hits++; backward = IP6_NEQ(&is->is_dst, &src); + fin->fin_rev = !backward; i = (backward << 1) + fin->fin_out; - is->is_pkts[i]++; - is->is_bytes[i] += fin->fin_plen; + is->is_icmppkts[i]++; /* * we deliberately do not touch the timeouts * for the accompanying state table entry. @@ -3525,6 +3616,7 @@ ipftq_t *tqp; for (i = IPF_TCP_NSTATES - 1; i >= 0; i--) { tqp[i].ifq_ttl = 0; + tqp[i].ifq_ref = 1; tqp[i].ifq_head = NULL; tqp[i].ifq_tail = &tqp[i].ifq_head; tqp[i].ifq_next = tqp + i + 1; @@ -3536,14 +3628,14 @@ ipftq_t *tqp; tqp[IPF_TCPS_SYN_SENT].ifq_ttl = fr_tcptimeout; tqp[IPF_TCPS_SYN_RECEIVED].ifq_ttl = fr_tcptimeout; tqp[IPF_TCPS_ESTABLISHED].ifq_ttl = fr_tcpidletimeout; - tqp[IPF_TCPS_CLOSE_WAIT].ifq_ttl = fr_tcpclosewait; + tqp[IPF_TCPS_CLOSE_WAIT].ifq_ttl = fr_tcphalfclosed; tqp[IPF_TCPS_FIN_WAIT_1].ifq_ttl = fr_tcphalfclosed; tqp[IPF_TCPS_CLOSING].ifq_ttl = fr_tcptimeout; tqp[IPF_TCPS_LAST_ACK].ifq_ttl = fr_tcplastack; tqp[IPF_TCPS_FIN_WAIT_2].ifq_ttl = fr_tcpclosewait; tqp[IPF_TCPS_TIME_WAIT].ifq_ttl = fr_tcptimeout; tqp[IPF_TCPS_HALF_ESTAB].ifq_ttl = fr_tcptimeout; -} +} /* ------------------------------------------------------------------------ */ @@ -3556,9 +3648,9 @@ ipftq_t *tqp; /* ------------------------------------------------------------------------ */ void fr_sttab_destroy(tqp) ipftq_t *tqp; -{ +{ int i; - + for (i = IPF_TCP_NSTATES - 1; i >= 0; i--) MUTEX_DESTROY(&tqp[i].ifq_lock); } @@ -3623,28 +3715,92 @@ ipstate_t **isp; fin = fin; /* LINT */ is = *isp; *isp = NULL; - MUTEX_ENTER(&is->is_lock); + WRITE_ENTER(&ipf_state); is->is_ref--; if (is->is_ref == 0) { - MUTEX_EXIT(&is->is_lock); - WRITE_ENTER(&ipf_state); + is->is_ref++; /* To counter ref-- in fr_delstate() */ fr_delstate(is, ISL_EXPIRE); - RWLOCK_EXIT(&ipf_state); #ifndef _KERNEL #if 0 } else if (((fin->fin_out == 1) || (eol == 1)) && ((ostate == IPF_TCPS_LAST_ACK) && (nstate == IPF_TCPS_TIME_WAIT))) { + ; #else } else if ((is->is_sti.tqe_state[0] > IPF_TCPS_ESTABLISHED) || (is->is_sti.tqe_state[1] > IPF_TCPS_ESTABLISHED)) { #endif - MUTEX_EXIT(&is->is_lock); - WRITE_ENTER(&ipf_state); fr_delstate(is, ISL_ORPHAN); - RWLOCK_EXIT(&ipf_state); #endif - } else { - MUTEX_EXIT(&is->is_lock); } + RWLOCK_EXIT(&ipf_state); +} + + +/* ------------------------------------------------------------------------ */ +/* Function: fr_setstatequeue */ +/* Returns: Nil */ +/* Parameters: is(I) - pointer to state structure */ +/* rev(I) - forward(0) or reverse(1) direction */ +/* Locks: ipf_state (read or write) */ +/* */ +/* Put the state entry on its default queue entry, using rev as a helped in */ +/* determining which queue it should be placed on. */ +/* ------------------------------------------------------------------------ */ +void fr_setstatequeue(is, rev) +ipstate_t *is; +int rev; +{ + ipftq_t *oifq, *nifq; + + + if ((is->is_sti.tqe_flags & TQE_RULEBASED) != 0) + nifq = is->is_tqehead[rev]; + else + nifq = NULL; + + if (nifq == NULL) { + switch (is->is_p) + { +#ifdef USE_INET6 + case IPPROTO_ICMPV6 : + if (rev == 1) + nifq = &ips_icmpacktq; + else + nifq = &ips_icmptq; + break; +#endif + case IPPROTO_ICMP : + if (rev == 1) + nifq = &ips_icmpacktq; + else + nifq = &ips_icmptq; + break; + case IPPROTO_TCP : + nifq = ips_tqtqb + is->is_state[rev]; + break; + + case IPPROTO_UDP : + if (rev == 1) + nifq = &ips_udpacktq; + else + nifq = &ips_udptq; + break; + + default : + nifq = &ips_iptq; + break; + } + } + + oifq = is->is_sti.tqe_ifq; + /* + * If it's currently on a timeout queue, move it from one queue to + * another, else put it on the end of the newly determined queue. + */ + if (oifq != NULL) + fr_movequeue(&is->is_sti, oifq, nifq); + else + fr_queueappend(&is->is_sti, nifq, is); + return; } diff --git a/usr/src/common/ipf/ipf.h b/usr/src/uts/common/inet/ipf/ipf.h index c912a298d8..8ae3352883 100644 --- a/usr/src/common/ipf/ipf.h +++ b/usr/src/uts/common/inet/ipf/ipf.h @@ -1,8 +1,12 @@ /* - * Copyright (C) 1993-2001, 2003, 2004 by Darren Reed. + * Copyright (C) 1993-2001, 2003 by Darren Reed. + * * See the IPFILTER.LICENCE file for details on licencing. * - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * @(#)ipf.h 1.12 6/5/96 + * $Id: ipf.h,v 2.71.2.7 2005/06/12 07:18:31 darrenr Exp $ + * + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -11,6 +15,12 @@ #pragma ident "%Z%%M% %I% %E% SMI" +#if defined(__osf__) +# define radix_mask ipf_radix_mask +# define radix_node ipf_radix_node +# define radix_node_head ipf_radix_node_head +#endif + #include <sys/param.h> #include <sys/types.h> #include <sys/file.h> @@ -41,38 +51,26 @@ struct file; #include <netinet/in.h> #include <netinet/in_systm.h> #include <netinet/ip.h> +#include <netinet/ip_icmp.h> #ifndef TCP_PAWS_IDLE /* IRIX */ # include <netinet/tcp.h> #endif #include <netinet/udp.h> -#ifndef _KERNEL #include <arpa/inet.h> #include <errno.h> #include <limits.h> #include <netdb.h> #include <stdlib.h> +#include <stddef.h> #include <stdio.h> #if !defined(__SVR4) && !defined(__svr4__) && defined(sun) # include <strings.h> #endif #include <string.h> #include <unistd.h> -#endif -#if SOLARIS2 >= 10 -#include "ip_compat.h" -#include "ip_fil.h" -#include "ip_nat.h" -#include "ip_frag.h" -#include "ip_state.h" -#include "ip_proxy.h" -#include "ip_auth.h" -#include "ip_lookup.h" -#include "ip_pool.h" -#include "ip_htable.h" -#else #include "netinet/ip_compat.h" #include "netinet/ip_fil.h" #include "netinet/ip_nat.h" @@ -82,7 +80,12 @@ struct file; #include "netinet/ip_auth.h" #include "netinet/ip_lookup.h" #include "netinet/ip_pool.h" +#ifdef IPFILTER_SCAN +#include "netinet/ip_scan.h" +#endif #include "netinet/ip_htable.h" +#ifdef IPFILTER_SYNC +#include "netinet/ip_sync.h" #endif #include "opts.h" @@ -146,22 +149,22 @@ typedef struct alist_s { #define al_1 al_addr #define al_2 al_mask + +typedef struct { + u_short fb_c; + u_char fb_t; + u_char fb_f; + u_32_t fb_k; +} fakebpf_t; + + #if defined(__NetBSD__) || defined(__OpenBSD__) || \ - (_BSDI_VERSION >= 199701) || (__FreeBSD_version >= 300000) + (_BSDI_VERSION >= 199701) || (__FreeBSD_version >= 300000) || \ + SOLARIS || defined(__sgi) || defined(__osf__) || defined(linux) # include <stdarg.h> -typedef u_long ioctlcmd_t; typedef int (* ioctlfunc_t) __P((int, ioctlcmd_t, ...)); #else -# if SOLARIS || defined(__sgi) || defined(__osf__) -#ifndef _KERNEL -# include <stdarg.h> -#endif -typedef int ioctlcmd_t; -typedef int (* ioctlfunc_t) __P((int, ioctlcmd_t, ...)); -# else -typedef int ioctlcmd_t; typedef int (* ioctlfunc_t) __P((dev_t, ioctlcmd_t, void *)); -# endif #endif typedef void (* addfunc_t) __P((int, ioctlfunc_t, void *)); typedef int (* copyfunc_t) __P((void *, void *, size_t)); @@ -183,9 +186,7 @@ extern char *icmpcodes[MAX_ICMPCODE + 1]; extern char *icmptypes[MAX_ICMPTYPE + 1]; extern int use_inet6; extern int lineNum; -#ifdef USE_INET6 extern struct ipopt_names v6ionames[]; -#endif extern int addicmp __P((char ***, struct frentry *, int)); @@ -196,21 +197,17 @@ extern void binprint __P((void *, size_t)); extern void initparse __P((void)); extern u_32_t buildopts __P((char *, char *, int)); extern int checkrev __P((char *)); -#ifdef USE_INET6 extern int count6bits __P((u_32_t *)); -#endif extern int count4bits __P((u_32_t)); extern int extras __P((char ***, struct frentry *, int)); extern char *fac_toname __P((int)); extern int fac_findname __P((char *)); extern void fill6bits __P((int, u_int *)); extern int gethost __P((char *, u_32_t *)); -extern int getport __P((struct frentry *, char *)); +extern int getport __P((struct frentry *, char *, u_short *)); extern int getportproto __P((char *, int)); extern int getproto __P((char *)); -#ifndef _KERNEL extern char *getline __P((char *, size_t, FILE *, int *)); -#endif extern int genmask __P((char *, u_32_t *)); extern char *getnattype __P((struct ipnat *)); extern char *getsumd __P((u_32_t)); @@ -218,23 +215,23 @@ extern u_32_t getoptbyname __P((char *)); extern u_32_t getoptbyvalue __P((int)); extern u_32_t getv6optbyname __P((char *)); extern u_32_t getv6optbyvalue __P((int)); +extern void hexdump __P((FILE *, void *, int, int)); extern int hostmask __P((char ***, char *, char *, u_32_t *, u_32_t *, int)); extern int hostnum __P((u_32_t *, char *, int, char *)); extern int icmpcode __P((char *)); extern int icmpidnum __P((char *, u_short *, int)); extern void initparse __P((void)); +extern void ipf_dotuning __P((int, char *, ioctlfunc_t)); extern void ipf_addrule __P((int, ioctlfunc_t, void *)); extern int ipf_parsefile __P((int, addfunc_t, ioctlfunc_t *, char *)); -#ifndef _KERNEL extern int ipf_parsesome __P((int, addfunc_t, ioctlfunc_t *, FILE *)); -extern int ipmon_parsesome __P((FILE *)); -extern int ipnat_parsesome __P((int, addfunc_t, ioctlfunc_t, FILE *)); -extern int ippool_parsesome __P((int, FILE *, ioctlfunc_t)); -#endif extern int ipmon_parsefile __P((char *)); +extern int ipmon_parsesome __P((FILE *)); extern void ipnat_addrule __P((int, ioctlfunc_t, void *)); extern int ipnat_parsefile __P((int, addfunc_t, ioctlfunc_t, char *)); +extern int ipnat_parsesome __P((int, addfunc_t, ioctlfunc_t, FILE *)); extern int ippool_parsefile __P((int, char *, ioctlfunc_t)); +extern int ippool_parsesome __P((int, FILE *, ioctlfunc_t)); extern int kmemcpywrap __P((void *, void *, size_t)); extern char *kvatoname __P((ipfunc_t, ioctlfunc_t)); extern int load_hash __P((struct iphtable_s *, struct iphtent_s *, @@ -260,8 +257,9 @@ extern void print_toif __P((char *, struct frdest *)); extern void printaps __P((ap_session_t *, int)); extern void printbuf __P((char *, int, int)); extern void printfr __P((struct frentry *, ioctlfunc_t)); -extern struct iphtable_s *printhash __P((struct iphtable_s *, - copyfunc_t, int)); +extern void printtunable __P((ipftune_t *)); +extern struct iphtable_s *printhash __P((struct iphtable_s *, copyfunc_t, + char *, int)); extern struct iphtent_s *printhashnode __P((struct iphtable_s *, struct iphtent_s *, copyfunc_t, int)); @@ -272,8 +270,10 @@ extern void printlookup __P((i6addr_t *addr, i6addr_t *mask)); extern void printmask __P((int, u_32_t *)); extern void printpacket __P((struct ip *)); extern void printpacket6 __P((struct ip *)); -extern struct ip_pool_s *printpool __P((struct ip_pool_s *, copyfunc_t, int)); +extern struct ip_pool_s *printpool __P((struct ip_pool_s *, copyfunc_t, + char *, int)); extern struct ip_pool_node *printpoolnode __P((struct ip_pool_node *, int)); +extern void printproto __P((struct protoent *, int, struct ipnat *)); extern void printportcmp __P((int, struct frpcmp *)); extern void optprint __P((u_short *, u_long, u_long)); #ifdef USE_INET6 @@ -293,9 +293,10 @@ extern void printC __P((int)); extern void emit __P((int, int, void *, struct frentry *)); extern u_char secbit __P((int)); extern u_char seclevel __P((char *)); +extern void printfraginfo __P((char *, struct ipfr *)); extern void printifname __P((char *, char *, void *)); extern char *hostname __P((int, void *)); -extern struct ipstate *printstate __P((struct ipstate *, int)); +extern struct ipstate *printstate __P((struct ipstate *, int, u_long)); extern void printsbuf __P((char *)); extern void printnat __P((struct ipnat *, int)); extern void printactivenat __P((struct nat *, int)); diff --git a/usr/src/common/ipf/ipmon.h b/usr/src/uts/common/inet/ipf/ipmon.h index b523aef2e9..765a646954 100644 --- a/usr/src/common/ipf/ipmon.h +++ b/usr/src/uts/common/inet/ipf/ipmon.h @@ -4,59 +4,71 @@ * See the IPFILTER.LICENCE file for details on licencing. * * @(#)ip_fil.h 1.35 6/5/96 - * $Id: ipmon.h,v 2.6 2002/12/27 16:07:15 darrenr Exp $ + * $Id: ipmon.h,v 2.8 2003/07/25 22:16:20 darrenr Exp $ */ -typedef struct action { - struct action *a_next; +typedef struct ipmon_action { + struct ipmon_action *ac_next; int ac_mflag; /* collection of things to compare */ + int ac_dflag; /* flags to compliment the doing fields */ + int ac_syslog; /* = 1 to syslog rules. */ + char *ac_savefile; /* filename to save log records to */ + FILE *ac_savefp; int ac_direction; char ac_group[FR_GROUPLEN]; + char ac_nattag[16]; + u_32_t ac_logtag; + int ac_type; /* nat/state/ipf */ int ac_proto; int ac_rule; int ac_packet; int ac_second; int ac_result; - int ac_tag; u_32_t ac_sip; u_32_t ac_smsk; u_32_t ac_dip; u_32_t ac_dmsk; u_short ac_sport; u_short ac_dport; - char *ac_exec; - char *ac_run; + char *ac_exec; /* execute argument */ + char *ac_run; /* actual command that gets run */ char *ac_iface; /* * used with ac_packet/ac_second */ struct timeval ac_last; int ac_pktcnt; -} action_t; +} ipmon_action_t; #define ac_lastsec ac_last.tv_sec #define ac_lastusec ac_last.tv_usec +/* + * Flags indicating what fields to do matching upon (ac_mflag). + */ #define IPMAC_DIRECTION 0x0001 #define IPMAC_DSTIP 0x0002 #define IPMAC_DSTPORT 0x0004 #define IPMAC_EVERY 0x0008 -#define IPMAC_EXECUTE 0x0010 -#define IPMAC_GROUP 0x0020 -#define IPMAC_INTERFACE 0x0040 -#define IPMAC_PROTOCOL 0x0080 -#define IPMAC_RESULT 0x0100 -#define IPMAC_RULE 0x0200 -#define IPMAC_SRCIP 0x0400 -#define IPMAC_SRCPORT 0x0800 -#define IPMAC_TAG 0x1000 +#define IPMAC_GROUP 0x0010 +#define IPMAC_INTERFACE 0x0020 +#define IPMAC_LOGTAG 0x0040 +#define IPMAC_NATTAG 0x0080 +#define IPMAC_PROTOCOL 0x0100 +#define IPMAC_RESULT 0x0200 +#define IPMAC_RULE 0x0400 +#define IPMAC_SRCIP 0x0800 +#define IPMAC_SRCPORT 0x1000 +#define IPMAC_TYPE 0x2000 +#define IPMAC_WITH 0x4000 #define IPMR_BLOCK 1 #define IPMR_PASS 2 #define IPMR_NOMATCH 3 -#define IPMR_SHORT 4 -#define IPMR_LOG 5 +#define IPMR_LOG 4 + +#define IPMDO_SAVERAW 0x0001 #define OPT_SYSLOG 0x001 #define OPT_RESOLVE 0x002 @@ -78,5 +90,5 @@ typedef struct action { extern int load_config __P((char *)); extern void dumphex __P((FILE *, int, char *, int)); -extern void check_action __P((char *, int, char *)); +extern int check_action __P((char *, char *, int, int)); extern char *getword __P((int)); diff --git a/usr/src/common/ipf/ipt.h b/usr/src/uts/common/inet/ipf/ipt.h index 938e40041e..938e40041e 100644 --- a/usr/src/common/ipf/ipt.h +++ b/usr/src/uts/common/inet/ipf/ipt.h diff --git a/usr/src/common/ipf/Makefile b/usr/src/uts/common/inet/ipf/netinet/Makefile index ed15db9165..e64d612f4c 100644 --- a/usr/src/common/ipf/Makefile +++ b/usr/src/uts/common/inet/ipf/netinet/Makefile @@ -1,13 +1,13 @@ # #ident "%Z%%M% %I% %E% SMI" # -# Copyright 2005 Sun Microsystems, Inc. All rights reserved. +# Copyright 2006 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # -# uts/common/netinet/Makefile +# uts/common/inet/ipf/netinet/Makefile # # include global definitions -include ../../Makefile.master +include ../../../../../Makefile.master HDRS= ipl.h ip_compat.h ip_fil.h ip_icmp.h ip_nat.h ip_proxy.h ip_state.h diff --git a/usr/src/common/ipf/ip_auth.h b/usr/src/uts/common/inet/ipf/netinet/ip_auth.h index 45e1055b1e..3892778270 100644 --- a/usr/src/common/ipf/ip_auth.h +++ b/usr/src/uts/common/inet/ipf/netinet/ip_auth.h @@ -3,7 +3,7 @@ * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: ip_auth.h,v 2.15 2002/11/02 15:42:21 darrenr Exp $ + * $Id: ip_auth.h,v 2.16 2003/07/25 12:29:56 darrenr Exp $ * */ #ifndef __IP_AUTH_H__ @@ -58,13 +58,7 @@ extern void fr_authunload __P((void)); extern int fr_authflush __P((void)); extern mb_t **fr_authpkts; extern int fr_newauth __P((mb_t *, fr_info_t *)); -#if defined(__NetBSD__) || defined(__OpenBSD__) || \ - (_BSDI_VERSION >= 199701) || (__FreeBSD_version >= 300000) -extern int fr_preauthcmd __P((u_long, frentry_t *, frentry_t **)); -extern int fr_auth_ioctl __P((caddr_t, u_long, int)); -#else -extern int fr_preauthcmd __P((int, frentry_t *, frentry_t **)); -extern int fr_auth_ioctl __P((caddr_t, int, int)); -#endif +extern int fr_preauthcmd __P((ioctlcmd_t, frentry_t *, frentry_t **)); +extern int fr_auth_ioctl __P((caddr_t, ioctlcmd_t, int)); #endif /* __IP_AUTH_H__ */ diff --git a/usr/src/common/ipf/ip_compat.h b/usr/src/uts/common/inet/ipf/netinet/ip_compat.h index 56262aff10..43368d9937 100644 --- a/usr/src/common/ipf/ip_compat.h +++ b/usr/src/uts/common/inet/ipf/netinet/ip_compat.h @@ -1,34 +1,18 @@ /* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright (C) 1999-2001, 2003 by Darren Reed. + * Copyright (C) 1993-2001, 2003 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * + * @(#)ip_compat.h 1.8 1/14/96 + * $Id: ip_compat.h,v 2.142.2.30 2005/08/11 15:13:49 darrenr Exp $ + * * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #pragma ident "%Z%%M% %I% %E% SMI" + #ifndef __IP_COMPAT_H__ #define __IP_COMPAT_H__ @@ -56,25 +40,33 @@ #ifndef SOLARIS #define SOLARIS (defined(sun) && (defined(__svr4__) || defined(__SVR4))) #endif -#if (SOLARIS2 >= 8) && (SOLARIS2 < 10) +#if SOLARIS2 >= 8 # ifndef USE_INET6 # define USE_INET6 # endif #endif #if defined(__FreeBSD_version) && (__FreeBSD_version >= 400000) && \ - !defined(_KERNEL) + !defined(_KERNEL) && !defined(USE_INET6) && !defined(NOINET6) # define USE_INET6 #endif #if defined(__NetBSD_Version__) && (__NetBSD_Version__ >= 105000000) && \ - !defined(_KERNEL) + !defined(_KERNEL) && !defined(USE_INET6) # define USE_INET6 +# define IPFILTER_M_IPFILTER #endif -#if defined(OpenBSD) && (OpenBSD >= 200206) && !defined(_KERNEL) +#if defined(OpenBSD) && (OpenBSD >= 200206) && \ + !defined(_KERNEL) && !defined(USE_INET6) # define USE_INET6 #endif #if defined(__osf__) # define USE_INET6 #endif +#if defined(linux) && (!defined(_KERNEL) || defined(CONFIG_IPV6)) +# define USE_INET6 +#endif +#if defined(HPUXREV) && (HPUXREV >= 1111) +# define USE_INET6 +#endif #if defined(BSD) && (BSD < 199103) && defined(__osf__) # undef BSD @@ -125,18 +117,20 @@ struct ether_addr { /* * This is a workaround for <sys/uio.h> troubles on FreeBSD and OpenBSD. */ -#ifndef _KERNEL -# define ADD_KERNEL -# define _KERNEL -# define KERNEL -#endif -#ifdef __OpenBSD__ +#ifndef linux +# ifndef _KERNEL +# define ADD_KERNEL +# define _KERNEL +# define KERNEL +# endif +# ifdef __OpenBSD__ struct file; -#endif -#include <sys/uio.h> -#ifdef ADD_KERNEL -# undef _KERNEL -# undef KERNEL +# endif +# include <sys/uio.h> +# ifdef ADD_KERNEL +# undef _KERNEL +# undef KERNEL +# endif #endif @@ -177,6 +171,9 @@ struct file; # undef IPOPT_LSRR # undef IPOPT_RR # undef IPOPT_SSRR +# ifdef i386 +# define _SYS_PROMIF_H +# endif # include <inet/ip.h> # undef COPYOUT # include <inet/ip_ire.h> @@ -184,8 +181,9 @@ struct file; # undef _KERNEL # endif # if SOLARIS2 >= 8 +# define SNPRINTF snprintf + # include <inet/ip_if.h> -# include <inet/ip6.h> # define ipif_local_addr ipif_lcl_addr /* Only defined in private include file */ # ifndef V4_PART_OF_V6 @@ -208,8 +206,8 @@ typedef unsigned int u_32_t; # ifdef _KERNEL # define KRWLOCK_T krwlock_t # define KMUTEX_T kmutex_t -# include "pfil.h" # include "qif.h" +# include "pfil.h" # if SOLARIS2 >= 6 # if SOLARIS2 == 6 # define ATOMIC_INCL(x) atomic_add_long((uint32_t*)&(x), 1) @@ -235,31 +233,19 @@ typedef unsigned int u_32_t; # define READ_ENTER(x) rw_enter(&(x)->ipf_lk, RW_READER) # define WRITE_ENTER(x) rw_enter(&(x)->ipf_lk, RW_WRITER) # define MUTEX_DOWNGRADE(x) rw_downgrade(&(x)->ipf_lk) -# if SOLARIS2 >= 6 -# define RWLOCK_INIT(x, y) rw_init(&(x)->ipf_lk, NULL, \ - RW_DRIVER, NULL) -# else # define RWLOCK_INIT(x, y) rw_init(&(x)->ipf_lk, (y), \ RW_DRIVER, NULL) -# endif /* SOLARIS2 >= 6 */ - # define RWLOCK_EXIT(x) rw_exit(&(x)->ipf_lk) # define RW_DESTROY(x) rw_destroy(&(x)->ipf_lk) - -# if SOLARIS2 >= 6 -# define MUTEX_INIT(x, y) mutex_init(&(x)->ipf_lk, NULL, \ - MUTEX_DRIVER, NULL) -# else # define MUTEX_INIT(x, y) mutex_init(&(x)->ipf_lk, (y), \ MUTEX_DRIVER, NULL) -# endif /* SOLARIS2 >= 6 */ # define MUTEX_DESTROY(x) mutex_destroy(&(x)->ipf_lk) # define MUTEX_NUKE(x) bzero((x), sizeof(*(x))) # define MUTEX_EXIT(x) mutex_exit(&(x)->ipf_lk) # define COPYIN(a,b,c) copyin((caddr_t)(a), (caddr_t)(b), (c)) # define COPYOUT(a,b,c) copyout((caddr_t)(a), (caddr_t)(b), (c)) -# define BCOPYIN(a,b,c) copyin((caddr_t)(a), (caddr_t)(b), (c)) -# define BCOPYOUT(a,b,c) copyout((caddr_t)(a), (caddr_t)(b), (c)) +# define BCOPYIN(a,b,c) (void) copyin((caddr_t)(a), (caddr_t)(b), (c)) +# define BCOPYOUT(a,b,c) (void) copyout((caddr_t)(a), (caddr_t)(b), (c)) # define UIOMOVE(a,b,c,d) uiomove((caddr_t)a,b,c,d) # define KFREE(x) kmem_free((char *)(x), sizeof(*(x))) # define KFREES(x,s) kmem_free((char *)(x), (s)) @@ -276,29 +262,25 @@ typedef unsigned int u_32_t; # define KMALLOC(a,b) (a) = (b)kmem_alloc(sizeof(*(a)), KM_NOSLEEP) # define KMALLOCS(a,b,c) (a) = (b)kmem_alloc((c), KM_NOSLEEP) # define GET_MINOR(x) getminor(x) -#ifndef IRE_ILL_CN -extern ill_t *get_unit __P((char *, int)); +extern void *get_unit __P((char *, int)); # define GETIFP(n, v) get_unit(n, v) -# define IFNAME(x) ((ill_t *)x)->ill_name +# define IFNAME(x) ((qif_t *)x)->qf_name # define COPYIFNAME(x, b) \ - strncpy(b, ((ill_t *)x)->ill_name, LIFNAMSIZ) -#else + (void) strncpy(b, ((qif_t *)x)->qf_name, \ + LIFNAMSIZ) +#ifdef IRE_ILL_CN extern kmutex_t s_ill_g_head_lock; extern struct s_ill_s *s_ill_g_head; /* ILL List Head */ -extern s_ill_t *get_unit __P((char *, int)); -# define GETIFP(n, v) get_unit(n, v) -# define IFNAME(x) ((s_ill_t *)x)->ill_name -# define COPYIFNAME(x, b) \ - strncpy(b, ((s_ill_t *)x)->ill_name, LIFNAMSIZ) #endif /* IRE_ILL_CN */ # define GETKTIME(x) uniqtime((struct timeval *)x) # define MSGDSIZE(x) msgdsize(x) # define M_LEN(x) ((x)->b_wptr - (x)->b_rptr) # define M_DUPLICATE(x) dupmsg((x)) -# define MTOD(m,t) (t)((m)->b_rptr) +# define MTOD(m,t) ((t)((m)->b_rptr)) # define MTYPE(m) ((m)->b_datap->db_type) # define FREE_MB_T(m) freemsg(m) -# define CACHE_HASH(x) (((qif_t *)(x)->fin_qif)->qf_num & 7) +# define m_next b_cont +# define CACHE_HASH(x) (((qpktinfo_t *)(x)->fin_qpi)->qpi_num & 7) # define IPF_PANIC(x,y) if (x) { printf y; cmn_err(CE_PANIC, "ipf_panic"); } typedef mblk_t mb_t; # endif /* _KERNEL */ @@ -313,6 +295,10 @@ typedef mblk_t mb_t; # endif # endif +# if SOLARIS2 < 6 +typedef struct uio uio_t; +# endif +typedef int ioctlcmd_t; # define OS_RECOGNISED 1 @@ -327,8 +313,28 @@ typedef mblk_t mb_t; # include <sys/spinlock.h> # include <sys/lock.h> # include <sys/stream.h> +# ifdef USE_INET6 +# include <netinet/if_ether.h> +# include <netinet/ip6.h> +# include <netinet/icmp6.h> +typedef struct ip6_hdr ip6_t; +# endif # ifdef _KERNEL +# define SNPRINTF sprintf +# if (HPUXREV >= 1111) +# define IPL_SELECT +# ifdef IPL_SELECT +# include <machine/sys/user.h> +# include <sys/kthread_iface.h> +# define READ_COLLISION 0x01 + +typedef struct iplog_select_s { + kthread_t *read_waiter; + int state; +} iplog_select_t; +# endif +# endif # define GETKTIME(x) uniqtime((struct timeval *)x) @@ -346,63 +352,82 @@ typedef mblk_t mb_t; * According to /usr/include/sys/spinlock.h on HP-UX 11.00, these functions * are available. Attempting to use them actually results in unresolved * symbols when it comes time to load the module. + * This has been fixed! Yipee! */ -# if 0 +# if 1 # ifdef __LP64__ -# define ATOMIC_INCL(x) lock_and_incr_int64(&ipf_rw, x, 1) -# define ATOMIC_DECL(x) lock_and_incr_int64(&ipf_rw, x, -1) +# define ATOMIC_INCL(x) lock_and_incr_int64(&ipf_rw.ipf_lk, &(x), 1) +# define ATOMIC_DECL(x) lock_and_incr_int64(&ipf_rw.ipf_lk, &(x), -1) # else -# define ATOMIC_INCL(x) lock_and_incr_int32(&ipf_rw, x, 1) -# define ATOMIC_DECL(x) lock_and_incr_int32(&ipf_rw, x, -1) +# define ATOMIC_INCL(x) lock_and_incr_int32(&ipf_rw.ipf_lk, &(x), 1) +# define ATOMIC_DECL(x) lock_and_incr_int32(&ipf_rw.ipf_lk, &(x), -1) # endif -# define ATOMIC_INC64(x) lock_and_incr_int64(&ipf_rw, x, 1) -# define ATOMIC_INC32(x) lock_and_incr_int32(&ipf_rw, x, 1) -# define ATOMIC_INC16(x) lock_and_incr_int16(&ipf_rw, x, 1) -# define ATOMIC_DEC64(x) lock_and_incr_int64(&ipf_rw, x, -1) -# define ATOMIC_DEC32(x) lock_and_incr_int32(&ipf_rw, x, -1) -# define ATOMIC_DEC16(x) lock_and_incr_int16(&ipf_rw, x, -1) +# define ATOMIC_INC64(x) lock_and_incr_int64(&ipf_rw.ipf_lk, &(x), 1) +# define ATOMIC_INC32(x) lock_and_incr_int32(&ipf_rw.ipf_lk, &(x), 1) +# define ATOMIC_INC16(x) lock_and_incr_int16(&ipf_rw.ipf_lk, &(x), 1) +# define ATOMIC_DEC64(x) lock_and_incr_int64(&ipf_rw.ipf_lk, &(x), -1) +# define ATOMIC_DEC32(x) lock_and_incr_int32(&ipf_rw.ipf_lk, &(x), -1) +# define ATOMIC_DEC16(x) lock_and_incr_int16(&ipf_rw.ipf_lk, &(x), -1) # else /* 0 */ -# define ATOMIC_INC(x) { spinlock(&ipf_rw); (x)++; \ - spinunlock(&ipf_rw); } -# define ATOMIC_DEC(x) { spinlock(&ipf_rw); (x)--; \ - spinunlock(&ipf_rw); } +# define ATOMIC_INC64(x) { MUTEX_ENTER(&ipf_rw); (x)++; \ + MUTEX_EXIT(&ipf_rw); } +# define ATOMIC_DEC64(x) { MUTEX_ENTER(&ipf_rw); (x)--; \ + MUTEX_EXIT(&ipf_rw); } +# define ATOMIC_INC32(x) { MUTEX_ENTER(&ipf_rw); (x)++; \ + MUTEX_EXIT(&ipf_rw); } +# define ATOMIC_DEC32(x) { MUTEX_ENTER(&ipf_rw); (x)--; \ + MUTEX_EXIT(&ipf_rw); } +# define ATOMIC_INCL(x) { MUTEX_ENTER(&ipf_rw); (x)++; \ + MUTEX_EXIT(&ipf_rw); } +# define ATOMIC_DECL(x) { MUTEX_ENTER(&ipf_rw); (x)--; \ + MUTEX_EXIT(&ipf_rw); } +# define ATOMIC_INC(x) { MUTEX_ENTER(&ipf_rw); (x)++; \ + MUTEX_EXIT(&ipf_rw); } +# define ATOMIC_DEC(x) { MUTEX_ENTER(&ipf_rw); (x)--; \ + MUTEX_EXIT(&ipf_rw); } # endif # define ip_cksum ip_csuma # define memcpy(a,b,c) bcopy((caddr_t)b, (caddr_t)a, c) # define USE_MUTEXES # define MUTEX_INIT(x, y) initlock(&(x)->ipf_lk, 0, 0, (y)) # define MUTEX_ENTER(x) spinlock(&(x)->ipf_lk) -# define MUTEX_EXIT(x) spinunlock(&(x)->ipf_lk) +# define MUTEX_EXIT(x) spinunlock(&(x)->ipf_lk); # define MUTEX_DESTROY(x) -# define MUTEX_NUKE(x) bzero((x), sizeof(*(x))) +# define MUTEX_NUKE(x) bzero((char *)(x), sizeof(*(x))) +# define KMUTEX_T lock_t +# define kmutex_t lock_t /* for pfil.h */ +# define krwlock_t lock_t /* for pfil.h */ /* * The read-write lock implementation in HP-UX 11.0 is crippled - it can * only be used by threads working in a user context! + * This has been fixed! Yipee! (Or at least it does in 11.00, not 11.11..) */ -# if 0 +# if HPUXREV < 1111 # define MUTEX_DOWNGRADE(x) lock_write_to_read(x) -# define KRWLOCK_T struct rwlock +# define KRWLOCK_T struct rw_lock # define READ_ENTER(x) lock_read(&(x)->ipf_lk) # define WRITE_ENTER(x) lock_write(&(x)->ipf_lk) -# define RWLOCK_INIT(x, y) lock_init3(&(x)->ipf_lk, 0, 1, 0, y) +# if HPUXREV >= 1111 +# define RWLOCK_INIT(x, y) rwlock_init4(&(x)->ipf_lk, 0, RWLCK_CANSLEEP, 0, y) +# else +# define RWLOCK_INIT(x, y) lock_init3(&(x)->ipf_lk, 0, 1, 0, 0, y) +# endif # define RWLOCK_EXIT(x) lock_done(&(x)->ipf_lk) # else # define KRWLOCK_T lock_t # define KMUTEX_T lock_t -# define kmutex_t lock_t /* for pfil.h */ -# define krwlock_t lock_t /* for pfil.h */ -# define READ_ENTER(x) MUTEX_ENTER(&(x)->ipf_lk) -# define WRITE_ENTER(x) MUTEX_ENTER(&(x)->ipf_lk) +# define READ_ENTER(x) MUTEX_ENTER(x) +# define WRITE_ENTER(x) MUTEX_ENTER(x) # define MUTEX_DOWNGRADE(x) # define RWLOCK_INIT(x, y) initlock(&(x)->ipf_lk, 0, 0, y) -# define RWLOCK_EXIT(x) spinunlock(&(x)->ipf_lk) +# define RWLOCK_EXIT(x) MUTEX_EXIT(x) # endif # define RW_DESTROY(x) # define COPYIN(a,b,c) copyin((caddr_t)(a), (caddr_t)(b), (c)) # define COPYOUT(a,b,c) copyout((caddr_t)(a), (caddr_t)(b), (c)) -# if HPUXREV > 1100 -# define BCOPYIN(a,b,c) memcpy((caddr_t)(a), (caddr_t)(b), (c)) -# define BCOPYOUT(a,b,c) memcpy((caddr_t)(a), (caddr_t)(b), (c)) +# if HPUXREV >= 1111 +# define BCOPYIN(a,b,c) 0; bcopy((caddr_t)(a), (caddr_t)(b), (c)) +# define BCOPYOUT(a,b,c) 0; bcopy((caddr_t)(a), (caddr_t)(b), (c)) # else # define BCOPYIN(a,b,c) bcopy((caddr_t)(a), (caddr_t)(b), (c)) # define BCOPYOUT(a,b,c) bcopy((caddr_t)(a), (caddr_t)(b), (c)) @@ -411,19 +436,19 @@ typedef mblk_t mb_t; # define SPL_IMP(x) ; # undef SPL_X # define SPL_X(x) ; -extern ifinfo_t *get_unit __P((char *, int)); +extern void *get_unit __P((char *, int)); # define GETIFP(n, v) get_unit(n, v) -# define IFNAME(x, b) ((ifinfo_t *)x)->ifi_name +# define IFNAME(x, b) ((ill_t *)x)->ill_name # define COPYIFNAME(x, b) \ - strncpy(b, ((ifinfo_t *)x)->ifi_name, \ - LIFNAMSIZ) + (void) strncpy(b, ((qif_t *)x)->qf_name, \ + LIFNAMSIZ) # define UIOMOVE(a,b,c,d) uiomove((caddr_t)a,b,c,d) # define SLEEP(id, n) { lock_t *_l = get_sleep_lock((caddr_t)id); \ sleep(id, PZERO+1); \ spinunlock(_l); \ } -# define WAKEUP(id) { lock_t *_l = get_sleep_lock((caddr_t)id); \ - wakeup(id); \ +# define WAKEUP(id,x) { lock_t *_l = get_sleep_lock((caddr_t)id); \ + wakeup(id + x); \ spinunlock(_l); \ } # define KMALLOC(a, b) MALLOC((a), b, sizeof(*(a)), M_IOSYS, M_NOWAIT) @@ -433,16 +458,17 @@ extern ifinfo_t *get_unit __P((char *, int)); # define MSGDSIZE(x) msgdsize(x) # define M_LEN(x) ((x)->b_wptr - (x)->b_rptr) # define M_DUPLICATE(x) dupmsg((x)) -# define MTOD(m,t) (t)((m)->b_rptr) +# define MTOD(m,t) ((t)((m)->b_rptr)) # define MTYPE(m) ((m)->b_datap->db_type) # define FREE_MB_T(m) freemsg(m) +# define m_next b_cont # define IPF_PANIC(x,y) if (x) { printf y; panic("ipf_panic"); } typedef mblk_t mb_t; -# define CACHE_HASH(x) (((qif_t *)(x)->fin_qif)->qf_num & 7) +# define CACHE_HASH(x) (((qpktinfo_t *)(x)->fin_qpi)->qpi_num & 7) -# include "pfil.h" # include "qif.h" +# include "pfil.h" # else /* _KERNEL */ @@ -465,6 +491,8 @@ typedef u_long ulong; # define ALIGN16(ptr) (ptr) # endif +typedef struct uio uio_t; +typedef int ioctlcmd_t; typedef int minor_t; typedef unsigned int u_32_t; # define U_32_T 1 @@ -478,6 +506,10 @@ typedef unsigned int u_32_t; /* ----------------------------------------------------------------------- */ #ifdef __sgi # undef MENTAT +# if IRIX < 60500 +typedef struct uio uio_t; +# endif +typedef int ioctlcmd_t; typedef u_int32_t u_32_t; # define U_32_T 1 @@ -519,7 +551,7 @@ typedef struct { # define ATOMIC_DEC32(x) atomicAddUint(&(x), -1) # define ATOMIC_DEC16 ATOMIC_DEC # undef MUTEX_INIT -# define MUTEX_INIT(x, y) mutex_init(&(x)->ipf_lk, +# define MUTEX_INIT(x, y) mutex_init(&(x)->ipf_lk, \ MUTEX_DEFAULT, y) # undef MUTEX_ENTER # define MUTEX_ENTER(x) mutex_lock(&(x)->ipf_lk, 0) @@ -555,7 +587,7 @@ typedef struct { # define BCOPYOUT(a,b,c) (bcopy((caddr_t)(a), (caddr_t)(b), (c)), 0) # define UIOMOVE(a,b,c,d) uiomove((caddr_t)a,b,c,d) # define SLEEP(id, n) sleep((id), PZERO+1) -# define WAKEUP(id) wakeup(id) +# define WAKEUP(id,x) wakeup(id+x) # define KFREE(x) kmem_free((char *)(x), sizeof(*(x))) # define KFREES(x,s) kmem_free((char *)(x), (s)) # define GETIFP(n,v) ifunit(n) @@ -564,6 +596,7 @@ typedef struct { # define KMALLOC(a,b) (a) = (b)kmem_alloc(sizeof(*(a)), KM_NOSLEEP) # define KMALLOCS(a,b,c) (a) = (b)kmem_alloc((c), KM_NOSLEEP) # define GET_MINOR(x) getminor(x) +# define USE_SPL 1 # define SPL_IMP(x) (x) = splimp() # define SPL_NET(x) (x) = splnet() # define SPL_X(x) (void) splx(x) @@ -577,6 +610,10 @@ extern void m_copyback __P((struct mbuf *, int, int, caddr_t)); ((struct ifnet *)fin->fin_ifp)->if_unit) & 7) # define IPF_PANIC(x,y) if (x) { printf y; panic("ipf_panic"); } typedef struct mbuf mb_t; +# else +# undef RW_DESTROY +# undef MUTEX_INIT +# undef MUTEX_DESTROY # endif /* _KERNEL */ # define OS_RECOGNISED 1 @@ -588,11 +625,6 @@ typedef struct mbuf mb_t; /* ----------------------------------------------------------------------- */ #ifdef __osf__ # undef MENTAT -/* - * Really, any arch where sizeof(long) != sizeof(int). - */ -typedef unsigned int u_32_t; -# define U_32_T 1 # include <kern/lock.h> # include <sys/sysmacros.h> @@ -636,16 +668,17 @@ typedef unsigned int u_32_t; # define MTOD(m,t) mtod(m,t) # define GETIFP(n, v) ifunit(n) # define GET_MINOR getminor -# define WAKEUP wakeup +# define WAKEUP(id,x) wakeup(id + x) # define COPYIN(a,b,c) copyin((caddr_t)(a), (caddr_t)(b), (c)) # define COPYOUT(a,b,c) copyout((caddr_t)(a), (caddr_t)(b), (c)) # define BCOPYIN(a,b,c) bcopy((caddr_t)(a), (caddr_t)(b), (c)) # define BCOPYOUT(a,b,c) bcopy((caddr_t)(a), (caddr_t)(b), (c)) # define KMALLOC(a, b) MALLOC((a), b, sizeof(*(a)), M_PFILT, M_NOWAIT) -# define KMALLOCS(a, b, c) MALLOC((a), b, (c), M_PFILT, M_NOWAIT) +# define KMALLOCS(a, b, c) MALLOC((a), b, (c), M_PFILT, \ + ((c) > 4096) ? M_WAITOK : M_NOWAIT) # define KFREE(x) FREE((x), M_PFILT) # define KFREES(x,s) FREE((x), M_PFILT) -# define MSGDSIZE(x) (x)->m_pkthdr.len +# define MSGDSIZE(x) mbufchainlen(x) # define M_LEN(x) (x)->m_len # define M_DUPLICATE(x) m_copy((x), 0, M_COPYALL) # define GETKTIME(x) microtime((struct timeval *)x) @@ -660,8 +693,10 @@ typedef struct mbuf mb_t; # define IP_HL(x) ((x)->ip_vhl & 0xf) # define IP_V_A(x,y) (x)->ip_vhl |= (((y) << 4) & 0xf0) # define IP_HL_A(x,y) (x)->ip_vhl |= ((y) & 0xf) +# define TCP_X2(x) ((x)->th_xoff & 0xf) +# define TCP_X2_A(x,y) (x)->th_xoff |= ((y) & 0xf) # define TCP_OFF(x) ((x)->th_xoff >> 4) -# define TCP_OFF_A(x,y) (x)->th_xoff = ((y) << 4) +# define TCP_OFF_A(x,y) (x)->th_xoff |= (((y) << 4) & 0xf0) # endif /* @@ -676,6 +711,13 @@ struct ip6_ext { u_char ip6e_len; }; +typedef int ioctlcmd_t; +/* + * Really, any arch where sizeof(long) != sizeof(int). + */ +typedef unsigned int u_32_t; +# define U_32_T 1 + # define OS_RECOGNISED 1 #endif /* __osf__ */ @@ -684,38 +726,48 @@ struct ip6_ext { /* ----------------------------------------------------------------------- */ #ifdef __NetBSD__ # if defined(_KERNEL) && !defined(IPFILTER_LKM) +# include "bpfilter.h" # if defined(__NetBSD_Version__) && (__NetBSD_Version__ >= 104110000) # include "opt_inet.h" # endif # ifdef INET6 # define USE_INET6 # endif +# if (__NetBSD_Version__ >= 105000000) +# define HAVE_M_PULLDOWN 1 +# endif # endif # ifdef _KERNEL -# define MSGDSIZE(x) (x)->m_pkthdr.len +# define MSGDSIZE(x) mbufchainlen(x) # define M_LEN(x) (x)->m_len # define M_DUPLICATE(x) m_copy((x), 0, M_COPYALL) # define GETKTIME(x) microtime((struct timeval *)x) # define IPF_PANIC(x,y) if (x) { printf y; panic("ipf_panic"); } +# define COPYIN(a,b,c) copyin((caddr_t)(a), (caddr_t)(b), (c)) +# define COPYOUT(a,b,c) copyout((caddr_t)(a), (caddr_t)(b), (c)) +# define BCOPYIN(a,b,c) bcopy((caddr_t)(a), (caddr_t)(b), (c)) +# define BCOPYOUT(a,b,c) bcopy((caddr_t)(a), (caddr_t)(b), (c)) typedef struct mbuf mb_t; # endif /* _KERNEL */ # if (NetBSD <= 1991011) && (NetBSD >= 199606) # define IFNAME(x) ((struct ifnet *)x)->if_xname # define COPYIFNAME(x, b) \ - strncpy(b, ((struct ifnet *)x)->if_xname, \ - LIFNAMSIZ) + (void) strncpy(b, \ + ((struct ifnet *)x)->if_xname, \ + LIFNAMSIZ) # define CACHE_HASH(x) ((((struct ifnet *)fin->fin_ifp)->if_index)&7) # else # define CACHE_HASH(x) ((IFNAME(fin->fin_ifp)[0] + \ ((struct ifnet *)fin->fin_ifp)->if_unit) & 7) # endif +typedef struct uio uio_t; +typedef u_long ioctlcmd_t; typedef int minor_t; typedef u_int32_t u_32_t; # define U_32_T 1 - # define OS_RECOGNISED 1 #endif /* __NetBSD__ */ @@ -724,29 +776,70 @@ typedef u_int32_t u_32_t; /* F R E E B S D */ /* ----------------------------------------------------------------------- */ #ifdef __FreeBSD__ -# if defined(_KERNEL) && !defined(IPFILTER_LKM) && !defined(KLD_MODULE) +# if defined(_KERNEL) +# if (__FreeBSD_version >= 500000) +# include "opt_bpf.h" +# else +# include "bpf.h" +# endif # if defined(__FreeBSD_version) && (__FreeBSD_version >= 400000) # include "opt_inet6.h" # endif -# ifdef INET6 -#error foo +# if defined(INET6) && !defined(USE_INET6) # define USE_INET6 # endif # endif -# if defined(_KERNEL) /* XXX When *isn't* this defined? */ +# if defined(_KERNEL) +# if (__FreeBSD_version >= 400000) +/* + * When #define'd, the 5.2.1 kernel panics when used with the ftp proxy. + * There may be other, safe, kernels but this is not extensively tested yet. + */ +# define HAVE_M_PULLDOWN +# endif +# if !defined(IPFILTER_LKM) && (__FreeBSD_version >= 300000) +# include "opt_ipfilter.h" +# endif +# define COPYIN(a,b,c) copyin((caddr_t)(a), (caddr_t)(b), (c)) +# define COPYOUT(a,b,c) copyout((caddr_t)(a), (caddr_t)(b), (c)) +# define BCOPYIN(a,b,c) bcopy((caddr_t)(a), (caddr_t)(b), (c)) +# define BCOPYOUT(a,b,c) bcopy((caddr_t)(a), (caddr_t)(b), (c)) + # if (__FreeBSD_version >= 500043) -# include "opt_pfil.h" -# endif /* __FreeBSD_version */ -# ifdef PFIL_HOOKS # define NETBSD_PF -# endif /* PFIL_HOOKS */ +# endif # endif /* _KERNEL */ # if (__FreeBSD_version >= 500043) # include <sys/mutex.h> +# include <sys/sx.h> +/* + * Whilst the sx(9) locks on FreeBSD have the right semantics and interface + * for what we want to use them for, despite testing showing they work - + * with a WITNESS kernel, it generates LOR messages. + */ # define KMUTEX_T struct mtx -# define KRWLOCK_T struct mtx +# if 1 +# define KRWLOCK_T struct mtx +# else +# define KRWLOCK_T struct sx +# endif +# endif + +# if (__FreeBSD_version >= 501113) +# include <net/if_var.h> +# define IFNAME(x) ((struct ifnet *)x)->if_xname +# define COPYIFNAME(x, b) \ + (void) strncpy(b, \ + ((struct ifnet *)x)->if_xname, \ + LIFNAMSIZ) +# endif +# if (__FreeBSD_version >= 500043) +# define CACHE_HASH(x) ((((struct ifnet *)fin->fin_ifp)->if_index) & 7) +# else +# define CACHE_HASH(x) ((IFNAME(fin->fin_ifp)[0] + \ + ((struct ifnet *)fin->fin_ifp)->if_unit) & 7) # endif # ifdef _KERNEL @@ -761,47 +854,62 @@ typedef u_int32_t u_32_t; # if (__FreeBSD_version >= 500043) # define USE_MUTEXES # define MUTEX_ENTER(x) mtx_lock(&(x)->ipf_lk) -# define READ_ENTER(x) mtx_lock(&(x)->ipf_lk) -# define WRITE_ENTER(x) mtx_lock(&(x)->ipf_lk) -# define MUTEX_DOWNGRADE(x) ; -# define RWLOCK_INIT(x, y) mtx_init(&(x)->ipf_lk, (y), NULL, \ - MTX_DEF) -# define RW_DESTROY(x) mtx_destroy(&(x)->ipf_lk) -# define RWLOCK_EXIT(x) mtx_unlock(&(x)->ipf_lk) # define MUTEX_EXIT(x) mtx_unlock(&(x)->ipf_lk) # define MUTEX_INIT(x,y) mtx_init(&(x)->ipf_lk, (y), NULL,\ MTX_DEF) # define MUTEX_DESTROY(x) mtx_destroy(&(x)->ipf_lk) -# define MUTEX_NUKE(x) bzero((x), sizeof(*(x))) +# define MUTEX_NUKE(x) bzero((x), sizeof(*(x))) +/* + * Whilst the sx(9) locks on FreeBSD have the right semantics and interface + * for what we want to use them for, despite testing showing they work - + * with a WITNESS kernel, it generates LOR messages. + */ +# if 1 +# define READ_ENTER(x) mtx_lock(&(x)->ipf_lk) +# define WRITE_ENTER(x) mtx_lock(&(x)->ipf_lk) +# define RWLOCK_EXIT(x) mtx_unlock(&(x)->ipf_lk) +# define MUTEX_DOWNGRADE(x) ; +# define RWLOCK_INIT(x,y) mtx_init(&(x)->ipf_lk, (y), NULL,\ + MTX_DEF) +# define RW_DESTROY(x) mtx_destroy(&(x)->ipf_lk) +# else +# define READ_ENTER(x) sx_slock(&(x)->ipf_lk) +# define WRITE_ENTER(x) sx_xlock(&(x)->ipf_lk) +# define MUTEX_DOWNGRADE(x) sx_downgrade(&(x)->ipf_lk) +# define RWLOCK_INIT(x, y) sx_init(&(x)->ipf_lk, (y)) +# define RW_DESTROY(x) sx_destroy(&(x)->ipf_lk) +# ifdef sx_unlock +# define RWLOCK_EXIT(x) sx_unlock(x) +# else +# define RWLOCK_EXIT(x) do { \ + if ((x)->ipf_lk.sx_cnt < 0) \ + sx_xunlock(&(x)->ipf_lk); \ + else \ + sx_sunlock(&(x)->ipf_lk); \ + } while (0) +# endif +# endif # include <machine/atomic.h> # define ATOMIC_INC(x) { mtx_lock(&ipf_rw.ipf_lk); (x)++; \ mtx_unlock(&ipf_rw.ipf_lk); } # define ATOMIC_DEC(x) { mtx_lock(&ipf_rw.ipf_lk); (x)--; \ mtx_unlock(&ipf_rw.ipf_lk); } -# if 0 -# define ATOMIC_INCL(x) atomic_add_long(x, 1) -# define ATOMIC_INC64(x) atomic_add_(x, 1) -# define ATOMIC_INC32(x) atomic_add_(x, 1) -# define ATOMIC_INC16(x) atomic_add_short(x, 1) -# define ATOMIC_DECL(x) atomic_subtrct_long(x, -1) -# define ATOMIC_DEC64(x) atomic_subtrct_(x, -1) -# define ATOMIC_DEC32(x) atomic_subtrct_(x, -1) -# define ATOMIC_DEC16(x) atomic_subtrct_short(x, -1) -# endif +# define ATOMIC_INCL(x) atomic_add_long(&(x), 1) +# define ATOMIC_INC64(x) ATOMIC_INC(x) +# define ATOMIC_INC32(x) atomic_add_32(&(x), 1) +# define ATOMIC_INC16(x) atomic_add_16(&(x), 1) +# define ATOMIC_DECL(x) atomic_add_long(&(x), -1) +# define ATOMIC_DEC64(x) ATOMIC_DEC(x) +# define ATOMIC_DEC32(x) atomic_add_32(&(x), -1) +# define ATOMIC_DEC16(x) atomic_add_16(&(x), -1) # define SPL_X(x) ; # define SPL_NET(x) ; # define SPL_IMP(x) ; extern int in_cksum __P((struct mbuf *, int)); # endif /* __FreeBSD_version >= 500043 */ -# define MSGDSIZE(x) (x)->m_pkthdr.len +# define MSGDSIZE(x) mbufchainlen(x) # define M_LEN(x) (x)->m_len # define M_DUPLICATE(x) m_copy((x), 0, M_COPYALL) -# if (__FreeBSD_version >= 500043) -# define CACHE_HASH(x) ((((struct ifnet *)fin->fin_ifp)->if_index) & 7) -# else -# define CACHE_HASH(x) ((IFNAME(fin->fin_ifp)[0] + \ - ((struct ifnet *)fin->fin_ifp)->if_unit) & 7) -# endif # define IPF_PANIC(x,y) if (x) { printf y; panic("ipf_panic"); } typedef struct mbuf mb_t; # endif /* _KERNEL */ @@ -816,6 +924,12 @@ typedef struct mbuf mb_t; # endif # endif +# if (__FreeBSD_version >= 300000) +typedef u_long ioctlcmd_t; +# else +typedef int ioctlcmd_t; +# endif +typedef struct uio uio_t; typedef int minor_t; typedef u_int32_t u_32_t; # define U_32_T 1 @@ -833,8 +947,25 @@ typedef u_int32_t u_32_t; # endif # ifdef _KERNEL +# if !defined(IPFILTER_LKM) +# include "bpfilter.h" +# endif +# if (OpenBSD >= 200311) +# define SNPRINTF snprintf +# if defined(USE_INET6) +# include "netinet6/in6_var.h" +# include "netinet6/nd6.h" +# endif +# endif +# if (OpenBSD >= 200012) +# define HAVE_M_PULLDOWN 1 +# endif +# define COPYIN(a,b,c) copyin((caddr_t)(a), (caddr_t)(b), (c)) +# define COPYOUT(a,b,c) copyout((caddr_t)(a), (caddr_t)(b), (c)) +# define BCOPYIN(a,b,c) bcopy((caddr_t)(a), (caddr_t)(b), (c)) +# define BCOPYOUT(a,b,c) bcopy((caddr_t)(a), (caddr_t)(b), (c)) # define GETKTIME(x) microtime((struct timeval *)x) -# define MSGDSIZE(x) (x)->m_pkthdr.len +# define MSGDSIZE(x) mbufchainlen(x) # define M_LEN(x) (x)->m_len # define M_DUPLICATE(x) m_copy((x), 0, M_COPYALL) # define IPF_PANIC(x,y) if (x) { printf y; panic("ipf_panic"); } @@ -843,14 +974,17 @@ typedef struct mbuf mb_t; # if (OpenBSD >= 199603) # define IFNAME(x, b) ((struct ifnet *)x)->if_xname # define COPYIFNAME(x, b) \ - strncpy(b, ((struct ifnet *)x)->if_xname, \ - LIFNAMSIZ) + (void) strncpy(b, \ + ((struct ifnet *)x)->if_xname, \ + LIFNAMSIZ) # define CACHE_HASH(x) ((((struct ifnet *)fin->fin_ifp)->if_index)&7) # else # define CACHE_HASH(x) ((IFNAME(fin->fin_ifp)[0] + \ ((struct ifnet *)fin->fin_ifp)->if_unit) & 7) # endif +typedef struct uio uio_t; +typedef u_long ioctlcmd_t; typedef int minor_t; typedef u_int32_t u_32_t; # define U_32_T 1 @@ -869,7 +1003,7 @@ typedef u_int32_t u_32_t; # ifdef _KERNEL # define GETKTIME(x) microtime((struct timeval *)x) -# define MSGDSIZE(x) (x)->m_pkthdr.len +# define MSGDSIZE(x) mbufchainlen(x) # define M_LEN(x) (x)->m_len # define M_DUPLICATE(x) m_copy((x), 0, M_COPYALL) # define CACHE_HASH(x) ((IFNAME(fin->fin_ifp)[0] + \ @@ -877,6 +1011,11 @@ typedef u_int32_t u_32_t; typedef struct mbuf mb_t; # endif /* _KERNEL */ +# if (_BSDI_VERSION >= 199701) +typedef u_long ioctlcmd_t; +# else +typedef int ioctlcmd_t; +# endif typedef u_int32_t u_32_t; # define U_32_T 1 @@ -899,7 +1038,7 @@ typedef u_int32_t u_32_t; # define KFREE(x) kmem_free((char *)(x), sizeof(*(x))) # define KFREES(x,s) kmem_free((char *)(x), (s)) # define SLEEP(id, n) sleep((id), PZERO+1) -# define WAKEUP(id) wakeup(id) +# define WAKEUP(id,x) wakeup(id + x) # define UIOMOVE(a,b,c,d) uiomove((caddr_t)a,b,c,d) # define IPF_PANIC(x,y) if (x) { printf y; panic("ipf_panic"); } @@ -909,6 +1048,8 @@ extern void m_copyback __P((struct mbuf *, int, int, caddr_t)); typedef struct mbuf mb_t; # endif +typedef struct uio uio_t; +typedef int ioctlcmd_t; typedef int minor_t; typedef unsigned int u_32_t; # define U_32_T 1 @@ -917,11 +1058,276 @@ typedef unsigned int u_32_t; #endif /* SunOS 4 */ +/* ----------------------------------------------------------------------- */ +/* L I N U X */ +/* ----------------------------------------------------------------------- */ +#if defined(linux) && !defined(OS_RECOGNISED) +#include <linux/config.h> +#include <linux/version.h> +# if LINUX >= 20600 +# define HDR_T_PRIVATE 1 +# endif +# undef USE_INET6 +# ifdef USE_INET6 +struct ip6_ext { + u_char ip6e_nxt; + u_char ip6e_len; +}; +# endif + +# ifdef _KERNEL +# define IPF_PANIC(x,y) if (x) { printf y; panic("ipf_panic"); } +# define BCOPYIN(a,b,c) bcopy((caddr_t)(a), (caddr_t)(b), (c)) +# define BCOPYOUT(a,b,c) bcopy((caddr_t)(a), (caddr_t)(b), (c)) +# define COPYIN(a,b,c) copy_from_user((caddr_t)(b), (caddr_t)(a), (c)) +# define COPYOUT(a,b,c) copy_to_user((caddr_t)(b), (caddr_t)(a), (c)) +# define FREE_MB_T(m) kfree_skb(m) +# define GETKTIME(x) do_gettimeofday((struct timeval *)x) +# define SLEEP(x,s) 0, interruptible_sleep_on(x##_linux) +# define WAKEUP(x,y) wake_up(x##_linux + y) +# define UIOMOVE(a,b,c,d) uiomove(a,b,c,d) +# define USE_MUTEXES +# define KRWLOCK_T rwlock_t +# define KMUTEX_T spinlock_t +# define MUTEX_INIT(x,y) spin_lock_init(&(x)->ipf_lk) +# define MUTEX_ENTER(x) spin_lock(&(x)->ipf_lk) +# define MUTEX_EXIT(x) spin_unlock(&(x)->ipf_lk) +# define MUTEX_DESTROY(x) do { } while (0) +# define MUTEX_NUKE(x) bzero(&(x)->ipf_lk, sizeof((x)->ipf_lk)) +# define READ_ENTER(x) ipf_read_enter(x) +# define WRITE_ENTER(x) ipf_write_enter(x) +# define RWLOCK_INIT(x,y) rwlock_init(&(x)->ipf_lk) +# define RW_DESTROY(x) do { } while (0) +# define RWLOCK_EXIT(x) ipf_rw_exit(x) +# define MUTEX_DOWNGRADE(x) ipf_rw_downgrade(x) +# define ATOMIC_INCL(x) MUTEX_ENTER(&ipf_rw); (x)++; \ + MUTEX_EXIT(&ipf_rw) +# define ATOMIC_DECL(x) MUTEX_ENTER(&ipf_rw); (x)--; \ + MUTEX_EXIT(&ipf_rw) +# define ATOMIC_INC64(x) MUTEX_ENTER(&ipf_rw); (x)++; \ + MUTEX_EXIT(&ipf_rw) +# define ATOMIC_INC32(x) MUTEX_ENTER(&ipf_rw); (x)++; \ + MUTEX_EXIT(&ipf_rw) +# define ATOMIC_INC16(x) MUTEX_ENTER(&ipf_rw); (x)++; \ + MUTEX_EXIT(&ipf_rw) +# define ATOMIC_DEC64(x) MUTEX_ENTER(&ipf_rw); (x)--; \ + MUTEX_EXIT(&ipf_rw) +# define ATOMIC_DEC32(x) MUTEX_ENTER(&ipf_rw); (x)--; \ + MUTEX_EXIT(&ipf_rw) +# define ATOMIC_DEC16(x) MUTEX_ENTER(&ipf_rw); (x)--; \ + MUTEX_EXIT(&ipf_rw) +# define SPL_IMP(x) do { } while (0) +# define SPL_NET(x) do { } while (0) +# define SPL_X(x) do { } while (0) +# define IFNAME(x) ((struct net_device*)x)->name +# define CACHE_HASH(x) ((IFNAME(fin->fin_ifp)[0] + \ + ((struct net_device *)fin->fin_ifp)->ifindex) & 7) +typedef struct sk_buff mb_t; +extern void m_copydata __P((mb_t *, int, int, caddr_t)); +extern void m_copyback __P((mb_t *, int, int, caddr_t)); +extern void m_adj __P((mb_t *, int)); +extern mb_t *m_pullup __P((mb_t *, int)); +# define mbuf sk_buff + +# define mtod(m, t) ((t)(m)->data) +# define m_len len +# define m_next next +# define M_DUPLICATE(m) skb_clone((m), in_interrupt() ? GFP_ATOMIC : \ + GFP_KERNEL) +# define MSGDSIZE(m) (m)->len +# define M_LEN(m) (m)->len + +# define splnet(x) ; +# define printf printk +# define bcopy(s,d,z) memmove(d, s, z) +# define bzero(s,z) memset(s, 0, z) +# define bcmp(a,b,z) memcmp(a, b, z) + +# define ifnet net_device +# define if_xname name +# define if_unit ifindex + +# define KMALLOC(x,t) (x) = (t)kmalloc(sizeof(*(x)), \ + in_interrupt() ? GFP_ATOMIC : GFP_KERNEL) +# define KFREE(x) kfree(x) +# define KMALLOCS(x,t,s) (x) = (t)kmalloc((s), \ + in_interrupt() ? GFP_ATOMIC : GFP_KERNEL) +# define KFREES(x,s) kfree(x) + +# define GETIFP(n,v) dev_get_by_name(n) + +# else +# include <net/ethernet.h> + +struct mbuf { +}; + +# ifndef _NET_ROUTE_H +struct rtentry { +}; +# endif + +struct ifnet { + char if_xname[IFNAMSIZ]; + int if_unit; + int (* if_output) __P((struct ifnet *, struct mbuf *, struct sockaddr *, struct rtentry *)); + struct ifaddr *if_addrlist; +}; +# define IFNAME(x) ((struct ifnet *)x)->if_xname + +# endif /* _KERNEL */ + +# define COPYIFNAME(x, b) \ + (void) strncpy(b, \ + ((struct ifnet *)x)->if_xname, \ + LIFNAMSIZ) + +# include <linux/fs.h> +# define FWRITE FMODE_WRITE +# define FREAD FMODE_READ + +# define __USE_MISC 1 +# define __FAVOR_BSD 1 + +typedef struct uio { + struct iovec *uio_iov; + void *uio_file; + char *uio_buf; + int uio_iovcnt; + int uio_offset; + size_t uio_resid; + int uio_rw; +} uio_t; + +extern int uiomove __P((caddr_t, size_t, int, struct uio *)); + +# define UIO_READ 1 +# define UIO_WRITE 2 + +typedef u_long ioctlcmd_t; +typedef int minor_t; +typedef u_int32_t u_32_t; +# define U_32_T 1 + +# define OS_RECOGNISED 1 + +#endif + + +/* ----------------------------------------------------------------------- */ +/* A I X */ +/* ----------------------------------------------------------------------- */ +#if defined(_AIX51) +# undef MENTAT + +# include <sys/lock.h> +# include <sys/sysmacros.h> + +# ifdef _KERNEL +# define rw_read_locked(x) 0 +# include <net/net_globals.h> +# include <net/net_malloc.h> +# define KMUTEX_T simple_lock_t +# define KRWLOCK_T complex_lock_t +# define USE_MUTEXES 1 +# define USE_SPL 1 +# define READ_ENTER(x) lock_read((x)->ipf_lk) +# define WRITE_ENTER(x) lock_write((x)->ipf_lk) +# define MUTEX_DOWNGRADE(x) lock_write_to_read((x)->ipf_lk) +# define RWLOCK_INIT(x, y) lock_alloc(&(x)->ipf_lk, \ + LOCK_ALLOC_PIN, \ + (u_short)y, 0); \ + lock_init((x)->ipf_lk, TRUE) +# define RWLOCK_EXIT(x) lock_done((x)->ipf_lk) +# define RW_DESTROY(x) lock_free(&(x)->ipf_lk) +# define MUTEX_ENTER(x) simple_lock((x)->ipf_lk) +# define MUTEX_INIT(x, y) lock_alloc(&(x)->ipf_lk, \ + LOCK_ALLOC_PIN, \ + (u_short)y, 0); \ + simple_lock_init((x)->ipf_lk) +# define MUTEX_DESTROY(x) lock_free(&(x)->ipf_lk) +# define MUTEX_EXIT(x) simple_unlock((x)->ipf_lk) +# define MUTEX_NUKE(x) bzero(&(x)->ipf_lk, sizeof((x)->ipf_lk)) +# define ATOMIC_INC64(x) { MUTEX_ENTER(&ipf_rw); (x)++; \ + MUTEX_EXIT(&ipf_rw); } +# define ATOMIC_DEC64(x) { MUTEX_ENTER(&ipf_rw); (x)--; \ + MUTEX_EXIT(&ipf_rw); } +# define ATOMIC_INC32(x) { MUTEX_ENTER(&ipf_rw); (x)++; \ + MUTEX_EXIT(&ipf_rw); } +# define ATOMIC_DEC32(x) { MUTEX_ENTER(&ipf_rw); (x)--; \ + MUTEX_EXIT(&ipf_rw); } +# define ATOMIC_INCL(x) { MUTEX_ENTER(&ipf_rw); (x)++; \ + MUTEX_EXIT(&ipf_rw); } +# define ATOMIC_DECL(x) { MUTEX_ENTER(&ipf_rw); (x)--; \ + MUTEX_EXIT(&ipf_rw); } +# define ATOMIC_INC(x) { MUTEX_ENTER(&ipf_rw); (x)++; \ + MUTEX_EXIT(&ipf_rw); } +# define ATOMIC_DEC(x) { MUTEX_ENTER(&ipf_rw); (x)--; \ + MUTEX_EXIT(&ipf_rw); } +# define SPL_NET(x) x = splnet() +# define SPL_IMP(x) x = splimp() +# undef SPL_X +# define SPL_X(x) splx(x) +# define UIOMOVE(a,b,c,d) uiomove((caddr_t)a,b,c,d) +extern void* getifp __P((char *, int)); +# define GETIFP(n, v) getifp(n, v) +# define GET_MINOR minor +# define SLEEP(id, n) sleepx((id), PZERO+1, 0) +# define WAKEUP(id,x) wakeup(id) +# define COPYIN(a,b,c) copyin((caddr_t)(a), (caddr_t)(b), (c)) +# define COPYOUT(a,b,c) copyout((caddr_t)(a), (caddr_t)(b), (c)) +# define BCOPYIN(a,b,c) bcopy((caddr_t)(a), (caddr_t)(b), (c)) +# define BCOPYOUT(a,b,c) bcopy((caddr_t)(a), (caddr_t)(b), (c)) +# define KMALLOC(a, b) MALLOC((a), b, sizeof(*(a)), M_TEMP, M_NOWAIT) +# define KMALLOCS(a, b, c) MALLOC((a), b, (c), M_TEMP, \ + ((c) > 4096) ? M_WAITOK : M_NOWAIT) +# define KFREE(x) FREE((x), M_TEMP) +# define KFREES(x,s) FREE((x), M_TEMP) +# define MSGDSIZE(x) mbufchainlen(x) +# define M_LEN(x) (x)->m_len +# define M_DUPLICATE(x) m_copy((x), 0, M_COPYALL) +# define GETKTIME(x) +# define CACHE_HASH(x) ((IFNAME(fin->fin_ifp)[0] + \ + ((struct ifnet *)fin->fin_ifp)->if_unit) & 7) +# define IPF_PANIC(x,y) +typedef struct mbuf mb_t; +# endif /* _KERNEL */ + +/* + * These are from's Solaris' #defines for little endian. + */ +#if !defined(IP6F_MORE_FRAG) +# define IP6F_MORE_FRAG 0x0100 +#endif +#if !defined(IP6F_RESERVED_MASK) +# define IP6F_RESERVED_MASK 0x0600 +#endif +#if !defined(IP6F_OFF_MASK) +# define IP6F_OFF_MASK 0xf8ff +#endif + +struct ip6_ext { + u_char ip6e_nxt; + u_char ip6e_len; +}; + +typedef int ioctlcmd_t; +typedef int minor_t; +/* + * Really, any arch where sizeof(long) != sizeof(int). + */ +typedef unsigned int u_32_t; +# define U_32_T 1 + +# define OS_RECOGNISED 1 +#endif /* _AIX51 */ + #ifndef OS_RECOGNISED #error ip_compat.h does not recognise this platform/OS. #endif + /* ----------------------------------------------------------------------- */ /* G E N E R I C */ /* ----------------------------------------------------------------------- */ @@ -929,59 +1335,133 @@ typedef unsigned int u_32_t; #endif /* + * For BSD kernels, if bpf is in the kernel, enable ipfilter to use bpf in + * filter rules. + */ +#if !defined(IPFILTER_BPF) && ((NBPF > 0) || (NBPFILTER > 0) || (DEV_BPF > 0)) +# define IPFILTER_BPF +#endif + +/* * Userland locking primitives */ typedef struct { + char *eMm_owner; + char *eMm_heldin; u_int eMm_magic; int eMm_held; - char *eMm_owner; int eMm_heldat; - char *eMm_heldin; +#ifdef __hpux + char eMm_fill[8]; +#endif } eMmutex_t; typedef struct { - u_int eMrw_magic; - int eMrw_read; - int eMrw_write; char *eMrw_owner; - int eMrw_heldat; char *eMrw_heldin; + u_int eMrw_magic; + short eMrw_read; + short eMrw_write; + int eMrw_heldat; +#ifdef __hpux + char eMm_fill[24]; +#endif } eMrwlock_t; typedef union { #ifdef KMUTEX_T - KMUTEX_T ipf_lk; + struct { + KMUTEX_T ipf_slk; + char *ipf_lname; + } ipf_lkun_s; #endif eMmutex_t ipf_emu; } ipfmutex_t; typedef union { #ifdef KRWLOCK_T - KRWLOCK_T ipf_lk; + struct { + KRWLOCK_T ipf_slk; + char *ipf_lname; + int ipf_sr; + int ipf_sw; + u_int ipf_magic; + } ipf_lkun_s; #endif eMrwlock_t ipf_emu; } ipfrwlock_t; +#define ipf_lk ipf_lkun_s.ipf_slk +#define ipf_lname ipf_lkun_s.ipf_lname +#define ipf_isr ipf_lkun_s.ipf_sr +#define ipf_isw ipf_lkun_s.ipf_sw +#define ipf_magic ipf_lkun_s.ipf_magic + +#if !defined(__GNUC__) || \ + (defined(__FreeBSD_version) && (__FreeBSD_version >= 503000)) +# ifndef INLINE +# define INLINE +# endif +#else +# define INLINE __inline__ +#endif + +#if defined(linux) && defined(_KERNEL) +extern INLINE void ipf_read_enter __P((ipfrwlock_t *)); +extern INLINE void ipf_write_enter __P((ipfrwlock_t *)); +extern INLINE void ipf_rw_exit __P((ipfrwlock_t *)); +extern INLINE void ipf_rw_downgrade __P((ipfrwlock_t *)); +#endif + +/* + * In a non-kernel environment, there are a lot of macros that need to be + * filled in to be null-ops or to point to some compatibility function, + * somewhere in userland. + */ #ifndef _KERNEL typedef struct mb_s { struct mb_s *mb_next; int mb_len; u_long mb_buf[2048]; } mb_t; +# undef m_next +# define m_next mb_next # define MSGDSIZE(x) (x)->mb_len /* XXX - from ipt.c */ # define M_LEN(x) (x)->mb_len # define M_DUPLICATE(x) (x) # define GETKTIME(x) gettimeofday((struct timeval *)(x), NULL) -# define MTOD(m, t) (t)((m)->mb_buf) +# undef MTOD +# define MTOD(m, t) ((t)(m)->mb_buf) # define FREE_MB_T(x) +# define SLEEP(x,y) 1; +# define WAKEUP(x,y) ; +# define IPF_PANIC(x,y) ; +# define PANIC(x,y) ; +# define SPL_NET(x) ; +# define SPL_IMP(x) ; +# define SPL_X(x) ; +# define KMALLOC(a,b) (a) = (b)malloc(sizeof(*a)) +# define KMALLOCS(a,b,c) (a) = (b)malloc(c) +# define KFREE(x) free(x) +# define KFREES(x,s) free(x) +# define GETIFP(x, v) get_unit(x,v) +# define COPYIN(a,b,c) (bcopy((a), (b), (c)), 0) +# define COPYOUT(a,b,c) (bcopy((a), (b), (c)), 0) +# define BCOPYIN(a,b,c) (bcopy((a), (b), (c)), 0) +# define BCOPYOUT(a,b,c) (bcopy((a), (b), (c)), 0) +# define COPYDATA(m, o, l, b) bcopy(MTOD((mb_t *)m, char *) + (o), \ + (b), (l)) +# define COPYBACK(m, o, l, b) bcopy((b), \ + MTOD((mb_t *)m, char *) + (o), \ + (l)) +# define UIOMOVE(a,b,c,d) ipfuiomove(a,b,c,d) +extern void m_copydata __P((mb_t *, int, int, caddr_t)); +extern int ipfuiomove __P((caddr_t, int, int, struct uio *)); # ifndef CACHE_HASH # define CACHE_HASH(x) ((IFNAME(fin->fin_ifp)[0] + \ ((struct ifnet *)fin->fin_ifp)->if_unit) & 7) # endif -# if 0 -# define KMUTEX_T eMmutex_t -# endif # define MUTEX_DESTROY(x) eMmutex_destroy(&(x)->ipf_emu) # define MUTEX_ENTER(x) eMmutex_enter(&(x)->ipf_emu, \ __FILE__, __LINE__) @@ -989,9 +1469,6 @@ typedef struct mb_s { # define MUTEX_INIT(x,y) eMmutex_init(&(x)->ipf_emu, y) # define MUTEX_NUKE(x) bzero((x), sizeof(*(x))) -# if 0 -# define KRWLOCK_T eMrwlock_t -# endif # define MUTEX_DOWNGRADE(x) eMrwlock_downgrade(&(x)->ipf_emu, \ __FILE__, __LINE__) # define READ_ENTER(x) eMrwlock_read_enter(&(x)->ipf_emu, \ @@ -1020,10 +1497,15 @@ extern void eMrwlock_downgrade __P((eMrwlock_t *, char *, int)); #define MAX_IPV4HDR ((0xf << 2) + sizeof(struct icmp) + sizeof(ip_t) + 8) -# ifndef IP_OFFMASK -# define IP_OFFMASK 0x1fff -# endif +#ifndef IP_OFFMASK +# define IP_OFFMASK 0x1fff +#endif + +/* + * On BSD's use quad_t as a guarantee for getting at least a 64bit sized + * object. + */ #if BSD > 199306 # define USE_QUAD_T # define U_QUAD_T u_quad_t @@ -1036,11 +1518,13 @@ extern void eMrwlock_downgrade __P((eMrwlock_t *, char *, int)); #ifdef USE_INET6 # if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD__) || \ - defined(__osf__) + defined(__osf__) || defined(linux) # include <netinet/ip6.h> # include <netinet/icmp6.h> -# if defined(_KERNEL) && !defined(__osf__) -# include <netinet6/ip6_var.h> +# if !defined(linux) +# if defined(_KERNEL) && !defined(__osf__) +# include <netinet6/ip6_var.h> +# endif # endif typedef struct ip6_hdr ip6_t; # endif @@ -1058,15 +1542,6 @@ typedef struct ip6_hdr ip6_t; # define COPYDATA m_copydata # define COPYBACK m_copyback # endif -#else -# define COPYDATA(m, o, l, b) bcopy(MTOD((mb_t *)m, char *) + (o), \ - (b), (l)) -# define COPYBACK(m, o, l, b) bcopy((b), \ - MTOD((mb_t *)m, char *) + (o), \ - (l)) -#endif - -#ifdef _KERNEL # if (BSD >= 199306) || defined(__FreeBSD__) # if (defined(__NetBSD_Version__) && (__NetBSD_Version__ < 105180000)) || \ defined(__FreeBSD__) || (defined(OpenBSD) && (OpenBSD < 200206)) || \ @@ -1090,32 +1565,29 @@ extern vm_map_t kmem_map; # ifdef IPFILTER_M_IPFILTER # include <sys/malloc.h> MALLOC_DECLARE(M_IPFILTER); -# define KMALLOC(a, b) MALLOC((a), b, sizeof(*(a)), M_IPFILTER, \ - M_NOWAIT) -# define KMALLOCS(a, b, c) MALLOC((a), b, (c), M_IPFILTER, \ - M_NOWAIT) -# define KFREE(x) FREE((x), M_IPFILTER) -# define KFREES(x,s) FREE((x), M_IPFILTER) +# define _M_IPF M_IPFILTER # else /* IPFILTER_M_IPFILTER */ # ifdef M_PFIL -# define KMALLOC(a, b) MALLOC((a), b, sizeof(*(a)), M_PFIL, M_NOWAIT) -# define KMALLOCS(a, b, c) MALLOC((a), b, (c), M_PFIL, M_NOWAIT) -# define KFREE(x) FREE((x), M_PFIL) -# define KFREES(x,s) FREE((x), M_PFIL) -# else /* M_PFIL */ -# define KMALLOC(a, b) MALLOC((a), b, sizeof(*(a)), M_TEMP, M_NOWAIT) -# define KMALLOCS(a, b, c) MALLOC((a), b, (c), M_TEMP, M_NOWAIT) -# define KFREE(x) FREE((x), M_TEMP) -# define KFREES(x,s) FREE((x), M_TEMP) +# define _M_IPF M_PFIL +# else +# ifdef M_IPFILTER +# define _M_IPF M_IPFILTER +# else +# define _M_IPF M_TEMP +# endif /* M_IPFILTER */ # endif /* M_PFIL */ # endif /* IPFILTER_M_IPFILTER */ +# define KMALLOC(a, b) MALLOC((a), b, sizeof(*(a)), _M_IPF, M_NOWAIT) +# define KMALLOCS(a, b, c) MALLOC((a), b, (c), _M_IPF, M_NOWAIT) +# define KFREE(x) FREE((x), _M_IPF) +# define KFREES(x,s) FREE((x), _M_IPF) # define UIOMOVE(a,b,c,d) uiomove(a,b,d) # define SLEEP(id, n) tsleep((id), PPAUSE|PCATCH, n, 0) -# define WAKEUP(id) wakeup(id) +# define WAKEUP(id,x) wakeup(id+x) # define GETIFP(n, v) ifunit(n) # endif /* (Free)BSD */ -# if !defined(USE_MUTEXES) +# if !defined(USE_MUTEXES) && !defined(SPL_NET) # if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199407)) || \ (defined(OpenBSD) && (OpenBSD >= 200006)) # define SPL_NET(x) x = splsoftnet() @@ -1150,27 +1622,7 @@ MALLOC_DECLARE(M_IPFILTER); # ifndef GET_MINOR # define GET_MINOR(x) minor(x) # endif -# define PANIC(x,y) /* if (x) panic y */ -#else /* _KERNEL */ -# define SLEEP(x,y) 1; -# define WAKEUP(x) ; -# define IPF_PANIC(x,y) ; -# define PANIC(x,y) ; -# define SPL_NET(x) ; -# define SPL_IMP(x) ; -# define SPL_X(x) ; -# define KMALLOC(a,b) (a) = (b)malloc(sizeof(*a)) -# define KMALLOCS(a,b,c) (a) = (b)malloc(c) -# define KFREE(x) free(x) -# define KFREES(x,s) free(x) -# define GETIFP(x, v) get_unit(x,v) -# define COPYIN(a,b,c) (bcopy((a), (b), (c)), 0) -# define COPYOUT(a,b,c) (bcopy((a), (b), (c)), 0) -# define BCOPYIN(a,b,c) (bcopy((a), (b), (c)), 0) -# define BCOPYOUT(a,b,c) (bcopy((a), (b), (c)), 0) -# define UIOMOVE(a,b,c,d) ipfuiomove(a,b,c,d) -extern void m_copydata __P((mb_t *, int, int, caddr_t)); -extern int ipfuiomove __P((caddr_t, int, int, struct uio *)); +# define PANIC(x,y) if (x) panic y #endif /* _KERNEL */ #ifndef IFNAME @@ -1183,7 +1635,29 @@ extern char *fr_getifname __P((struct ifnet *, char *)); fr_getifname((struct ifnet *)x, b) #endif +#ifndef ASSERT +# define ASSERT(x) +#endif +/* + * Because the ctype(3) posix definition, if used "safely" in code everywhere, + * would mean all normal code that walks through strings needed casts. Yuck. + */ +#define ISALNUM(x) isalnum((u_char)(x)) +#define ISALPHA(x) isalpha((u_char)(x)) +#define ISASCII(x) isascii((u_char)(x)) +#define ISDIGIT(x) isdigit((u_char)(x)) +#define ISPRINT(x) isprint((u_char)(x)) +#define ISSPACE(x) isspace((u_char)(x)) +#define ISUPPER(x) isupper((u_char)(x)) +#define ISXDIGIT(x) isxdigit((u_char)(x)) +#define ISLOWER(x) islower((u_char)(x)) +#define TOUPPER(x) toupper((u_char)(x)) +#define TOLOWER(x) tolower((u_char)(x)) + +/* + * If mutexes aren't being used, turn all the mutex functions into null-ops. + */ #if !defined(USE_MUTEXES) # define USE_SPL 1 # undef RW_DESTROY @@ -1207,9 +1681,15 @@ extern char *fr_getifname __P((struct ifnet *, char *)); # define ATOMIC_DEC(x) (x)-- #endif +#if defined(USE_SPL) && defined(_KERNEL) +# define SPL_INT(x) int x +#else +# define SPL_INT(x) +#endif + /* - * Build some macros and #defines to enable the same code to compile anywhere - * Well, that's the idea, anyway :-) + * If there are no atomic operations for bit sizes defined, define them to all + * use a generic one that works for all sizes. */ #ifndef ATOMIC_INCL # define ATOMIC_INCL ATOMIC_INC @@ -1222,8 +1702,10 @@ extern char *fr_getifname __P((struct ifnet *, char *)); # define ATOMIC_DEC16 ATOMIC_DEC #endif +#ifndef HDR_T_PRIVATE typedef struct tcphdr tcphdr_t; typedef struct udphdr udphdr_t; +#endif typedef struct icmp icmphdr_t; typedef struct ip ip_t; typedef struct ether_header ether_header_t; @@ -1240,6 +1722,11 @@ typedef struct tcpiphdr tcpiphdr_t; # define offsetof(t,m) (int)((&((t *)0L)->m)) #endif +/* + * This set of macros has been brought about because on Tru64 it is not + * possible to easily assign or examine values in a structure that are + * bit fields. + */ #ifndef IP_V # define IP_V(x) (x)->ip_v #endif @@ -1252,6 +1739,12 @@ typedef struct tcpiphdr tcpiphdr_t; #ifndef IP_HL_A # define IP_HL_A(x,y) (x)->ip_hl = (y) #endif +#ifndef TCP_X2 +# define TCP_X2(x) (x)->th_x2 +#endif +#ifndef TCP_X2_A +# define TCP_X2_A(x,y) (x)->th_x2 = (y) +#endif #ifndef TCP_OFF # define TCP_OFF(x) (x)->th_off #endif @@ -1313,17 +1806,23 @@ typedef struct tcpiphdr tcpiphdr_t; */ #undef IPOPT_RR #define IPOPT_RR 7 +#undef IPOPT_ZSU #define IPOPT_ZSU 10 /* ZSU */ +#undef IPOPT_MTUP #define IPOPT_MTUP 11 /* MTUP */ +#undef IPOPT_MTUR #define IPOPT_MTUR 12 /* MTUR */ +#undef IPOPT_ENCODE #define IPOPT_ENCODE 15 /* ENCODE */ #undef IPOPT_TS #define IPOPT_TS 68 +#undef IPOPT_TR #define IPOPT_TR 82 /* TR */ #undef IPOPT_SECURITY #define IPOPT_SECURITY 130 #undef IPOPT_LSRR #define IPOPT_LSRR 131 +#undef IPOPT_E_SEC #define IPOPT_E_SEC 133 /* E-SEC */ #undef IPOPT_CIPSO #define IPOPT_CIPSO 134 /* CIPSO */ @@ -1334,15 +1833,25 @@ typedef struct tcpiphdr tcpiphdr_t; #endif #undef IPOPT_SSRR #define IPOPT_SSRR 137 +#undef IPOPT_ADDEXT #define IPOPT_ADDEXT 147 /* ADDEXT */ +#undef IPOPT_VISA #define IPOPT_VISA 142 /* VISA */ +#undef IPOPT_IMITD #define IPOPT_IMITD 144 /* IMITD */ +#undef IPOPT_EIP #define IPOPT_EIP 145 /* EIP */ +#undef IPOPT_RTRALRT #define IPOPT_RTRALRT 148 /* RTRALRT */ +#undef IPOPT_SDB #define IPOPT_SDB 149 +#undef IPOPT_NSAPA #define IPOPT_NSAPA 150 +#undef IPOPT_DPS #define IPOPT_DPS 151 +#undef IPOPT_UMP #define IPOPT_UMP 152 +#undef IPOPT_FINN #define IPOPT_FINN 205 /* FINN */ #ifndef TCPOPT_EOL @@ -1888,7 +2397,7 @@ typedef struct tcpiphdr tcpiphdr_t; /* * ICMP error replies have an IP header (20 bytes), 8 bytes of ICMP data, * another IP header and then 64 bits of data, totalling 56. Of course, - * the last 64 bits is dependant on that being available. + * the last 64 bits is dependent on that being available. */ #define ICMPERR_ICMPHLEN 8 #define ICMPERR_IPICMPHLEN (20 + 8) @@ -1897,16 +2406,18 @@ typedef struct tcpiphdr tcpiphdr_t; #define ICMP6ERR_MINPKTLEN (40 + 8) #define ICMP6ERR_IPICMPHLEN (40 + 8 + 40) -#ifdef __GNUC__ -# define INLINE __inline__ +#ifndef MIN +# define MIN(a,b) (((a)<(b))?(a):(b)) +#endif + +#ifdef IPF_DEBUG +# define DPRINT(x) printf x #else -# ifndef INLINE -# define INLINE -# endif +# define DPRINT(x) #endif -#ifndef MIN -# define MIN(a,b) (((a)<(b))?(a):(b)) +#ifdef RESCUE +# undef IPFILTER_BPF #endif #endif /* __IP_COMPAT_H__ */ diff --git a/usr/src/common/ipf/ip_fil.h b/usr/src/uts/common/inet/ipf/netinet/ip_fil.h index e853b697bd..e7ec154f4f 100644 --- a/usr/src/common/ipf/ip_fil.h +++ b/usr/src/uts/common/inet/ipf/netinet/ip_fil.h @@ -3,7 +3,8 @@ * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: ip_fil.h,v 2.146 2003/07/01 18:30:19 darrenr Exp $ + * @(#)ip_fil.h 1.35 6/5/96 + * $Id: ip_fil.h,v 2.170.2.22 2005/07/16 05:55:35 darrenr Exp $ * * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. @@ -14,6 +15,8 @@ #ifndef __IP_FIL_H__ #define __IP_FIL_H__ +#include "netinet/ip_compat.h" + #ifndef SOLARIS # define SOLARIS (defined(sun) && (defined(__svr4__) || defined(__SVR4))) #endif @@ -26,7 +29,7 @@ # endif #endif -#if defined(__STDC__) || defined(__GNUC__) +#if defined(__STDC__) || defined(__GNUC__) || defined(_AIX51) # define SIOCADAFR _IOW('r', 60, struct ipfobj) # define SIOCRMAFR _IOW('r', 61, struct ipfobj) # define SIOCSETFF _IOW('r', 62, u_int) @@ -123,6 +126,7 @@ typedef union i6addr { lookupfunc_t lptr[2]; } i6addr_t; #endif + #define in4_addr in4.s_addr #define iplookupnum i6[0] #define iplookuptype i6[1] @@ -235,10 +239,11 @@ typedef struct fr_ip { #define FI_BAD 0x0400 #define FI_OOW 0x0800 /* Out of state window, else match */ #define FI_ICMPERR 0x1000 -#define FI_FRAGTAIL 0x2000 +#define FI_FRAGBODY 0x2000 #define FI_BADSRC 0x4000 #define FI_LOWTTL 0x8000 -#define FI_CMP 0xcff3 /* Not FI_FRAG,FI_FRAGTAIL */ +#define FI_CMP 0xcfe3 /* Not FI_FRAG,FI_NATED,FI_FRAGTAIL */ +#define FI_ICMPCMP 0x0003 /* Flags we can check for ICMP error packets */ #define FI_WITH 0xeffe /* Not FI_TCPUDP */ #define FI_V6EXTHDR 0x10000 #define FI_COALESCE 0x20000 @@ -276,7 +281,7 @@ typedef struct fr_ip { typedef struct fr_info { void *fin_ifp; /* interface packet is `on' */ - struct fr_ip fin_fi; /* IP Packet summary */ + fr_ip_t fin_fi; /* IP Packet summary */ union { u_short fid_16[2]; /* TCP/UDP ports, ICMP code/type */ u_32_t fid_32; @@ -292,8 +297,9 @@ typedef struct fr_info { void *fin_dp; /* start of data past IP header */ int fin_dlen; /* length of data portion of packet */ int fin_plen; - int fin_flen; /* length of layer 4 hdr and + int fin_flen; /* length of layer 4 hdr and ipv6 ext hdr after fragment hdr */ + int fin_ipoff; /* # bytes from buffer start to hdr */ u_32_t fin_id; /* IP packet id field */ u_short fin_off; int fin_depth; /* Group nesting depth */ @@ -306,7 +312,10 @@ typedef struct fr_info { mb_t *fin_m; /* pointer to mbuf */ #ifdef MENTAT mb_t *fin_qfm; /* pointer to mblk where pkt starts */ - void *fin_qif; + void *fin_qpi; +#endif +#ifdef __sgi + void *fin_hbuf; #endif } fr_info_t; @@ -351,12 +360,13 @@ typedef struct ipfunc_resolve { #define FI_COPYSIZE offsetof(fr_info_t, fin_dp) /* - * + * Structure for holding IPFilter's tag information */ +#define IPFTAG_LEN 16 typedef struct { union { u_32_t iptu_num[4]; - char iptu_tag[16]; + char iptu_tag[IPFTAG_LEN]; } ipt_un; int ipt_not; } ipftag_t; @@ -424,8 +434,8 @@ typedef struct frtuc { * used to define the result which are in frentry_t and not here. */ typedef struct fripf { - struct fr_ip fri_ip; - struct fr_ip fri_mip; /* mask structure */ + fr_ip_t fri_ip; + fr_ip_t fri_mip; /* mask structure */ u_short fri_icmpm; /* data for ICMP packets (mask) */ u_short fri_icmp; @@ -503,11 +513,11 @@ typedef struct frentry { u_char fr_icode; /* return ICMP code */ char fr_group[FR_GROUPLEN]; /* group to which this rule belongs */ char fr_grhead[FR_GROUPLEN]; /* group # which this rule starts */ - ipftag_t fr_nattag; + ipftag_t fr_nattag; char fr_ifnames[4][LIFNAMSIZ]; char fr_isctag[16]; - struct frdest fr_tifs[2]; /* "to"/"reply-to" interface */ - struct frdest fr_dif; /* duplicate packet interface */ + frdest_t fr_tifs[2]; /* "to"/"reply-to" interface */ + frdest_t fr_dif; /* duplicate packet interface */ /* * This must be last and will change after loaded into the kernel. */ @@ -578,7 +588,7 @@ typedef struct frentry { #define offsetof(t,m) (int)((&((t *)0L)->m)) #endif #define FR_CMPSIZ (sizeof(struct frentry) - \ - offsetof(struct frentry, fr_dsize)) + offsetof(struct frentry, fr_func)) /* * fr_type @@ -626,6 +636,7 @@ typedef struct frentry { #define FR_STSTRICT 0x200000 /* strict keep state */ #define FR_NEWISN 0x400000 /* new ISN for outgoing TCP */ #define FR_NOICMPERR 0x800000 /* do not match ICMP errors in state */ +#define FR_STATESYNC 0x1000000 /* synchronize state to slave */ #define FR_NOMATCH 0x8000000 /* no match occured */ /* 0x10000000 FF_LOGPASS */ /* 0x20000000 FF_LOGBLOCK */ @@ -757,15 +768,17 @@ typedef struct filter_kstats { typedef struct iplog { u_32_t ipl_magic; u_int ipl_count; - struct timeval ipl_tv; + struct timeval ipl_time; size_t ipl_dsize; struct iplog *ipl_next; } iplog_t; -#define ipl_sec ipl_tv.tv_sec -#define ipl_usec ipl_tv.tv_usec +#define ipl_sec ipl_time.tv_sec +#define ipl_usec ipl_time.tv_usec #define IPL_MAGIC 0x49504c4d /* 'IPLM' */ +#define IPL_MAGIC_NAT 0x49504c4e /* 'IPLN' */ +#define IPL_MAGIC_STATE 0x49504c53 /* 'IPLS' */ #define IPLOG_SIZE sizeof(iplog_t) typedef struct ipflog { @@ -777,13 +790,14 @@ typedef struct ipflog { u_32_t fl_rule; u_32_t fl_flags; u_32_t fl_lflags; - u_32_t fl_tag; + u_32_t fl_logtag; + ipftag_t fl_nattag; u_short fl_plen; /* extra data after hlen */ u_short fl_loglevel; /* syslog log level */ char fl_group[FR_GROUPLEN]; u_char fl_hlen; /* length of IP headers saved */ u_char fl_dir; - u_char fl_xxx[6]; /* pad */ + u_char fl_xxx[2]; /* pad */ char fl_ifname[LIFNAMSIZ]; } ipflog_t; @@ -798,8 +812,8 @@ typedef struct ipflog { #ifndef IPFILTER_LOGSIZE # define IPFILTER_LOGSIZE DEFAULT_IPFLOGSIZE #else -# if IPF_LOGSIZE < DEFAULT_IPFLOGSIZE -# error IPFILTER_LOGSISZE too small. Must be >= DEFAULT_IPFLOGSIZE +# if IPFILTER_LOGSIZE < DEFAULT_IPFLOGSIZE +# error IPFILTER_LOGSIZE too small. Must be >= DEFAULT_IPFLOGSIZE # endif #endif @@ -857,9 +871,10 @@ typedef struct friostat { size_t f_kmutex_sz; size_t f_krwlock_sz; int f_defpass; /* default pass - from fr_pass */ - char f_active; /* 1 or 0 - active rule set */ - char f_running; /* 1 if running, else 0 */ - char f_logging; /* 1 if enabled, else 0 */ + int f_active; /* 1 or 0 - active rule set */ + int f_running; /* 1 if running, else 0 */ + int f_logging; /* 1 if enabled, else 0 */ + int f_features; char f_version[32]; /* version string */ } friostat_t; @@ -872,6 +887,15 @@ typedef struct friostat { #define f_acctout f_acct[1] #define f_acctout6 f_acct6[1] +#define IPF_FEAT_LKM 0x001 +#define IPF_FEAT_LOG 0x002 +#define IPF_FEAT_LOOKUP 0x004 +#define IPF_FEAT_BPF 0x008 +#define IPF_FEAT_COMPILED 0x010 +#define IPF_FEAT_CKSUM 0x020 +#define IPF_FEAT_SYNC 0x040 +#define IPF_FEAT_SCAN 0x080 +#define IPF_FEAT_IPV6 0x100 typedef struct optlist { u_short ol_val; @@ -930,43 +954,68 @@ typedef struct tcpinfo { tcpdata_t ts_data[2]; } tcpinfo_t; -typedef struct greinfo { - u_short gs_flags; - u_short gs_ptype; - u_short gs_call; -} greinfo_t; + +/* + * Structures to define a GRE header as seen in a packet. + */ +struct grebits { + u_32_t grb_C:1; + u_32_t grb_R:1; + u_32_t grb_K:1; + u_32_t grb_S:1; + u_32_t grb_s:1; + u_32_t grb_recur:1; + u_32_t grb_A:1; + u_32_t grb_flags:3; + u_32_t grb_ver:3; + u_short grb_ptype; +}; typedef struct grehdr { union { - struct grebits { - u_32_t grub_C:1; - u_32_t grub_R:1; - u_32_t grub_K:1; - u_32_t grub_S:1; - u_32_t grub_s:1; - u_32_t grub_recur:1; - u_32_t grub_A:1; - u_32_t grub_flags:3; - u_32_t grub_ver:3; - u_short grub_ptype; - } gru_bits; + struct grebits gru_bits; u_short gru_flags; } gr_un; u_short gr_len; u_short gr_call; } grehdr_t; +#define gr_flags gr_un.gru_flags #define gr_bits gr_un.gru_bits -#define gr_ptype gr_un.gru_bits.grub_ptype -#define gr_C gr_bits.grub_C -#define gr_R gr_bits.grub_R -#define gr_K gr_bits.grub_K -#define gr_S gr_bits.grub_S -#define gr_s gr_bits.grub_s -#define gr_recur gr_bits.grub_recur -#define gr_A gr_bits.grub_A -#define gr_flags gr_bits.grub_flags -#define gr_ver gr_bits.grub_ver +#define gr_ptype gr_bits.grb_ptype +#define gr_C gr_bits.grb_C +#define gr_R gr_bits.grb_R +#define gr_K gr_bits.grb_K +#define gr_S gr_bits.grb_S +#define gr_s gr_bits.grb_s +#define gr_recur gr_bits.grb_recur +#define gr_A gr_bits.grb_A +#define gr_ver gr_bits.grb_ver + +/* + * GRE information tracked by "keep state" + */ +typedef struct greinfo { + u_short gs_call[2]; + u_short gs_flags; + u_short gs_ptype; +} greinfo_t; + +#define GRE_REV(x) ((ntohs(x) >> 13) & 7) + + +/* + * Format of an Authentication header + */ +typedef struct authhdr { + u_char ah_next; + u_char ah_plen; + u_short ah_reserved; + u_32_t ah_spi; + u_32_t ah_seq; + /* Following the sequence number field is 0 or more bytes of */ + /* authentication data, as specified by ah_plen - RFC 2402. */ +} authhdr_t; /* @@ -1001,6 +1050,8 @@ typedef struct ipftq { } ipftq_t; #define IFQF_USER 0x01 /* User defined aging */ +#define IFQF_DELETE 0x02 /* Marked for deletion */ +#define IFQF_PROXY 0x04 /* Timeout queue in use by a proxy */ #define IPF_HZ_MULT 1 #define IPF_HZ_DIVIDE 2 /* How many times a second ipfilter */ @@ -1060,6 +1111,7 @@ typedef struct ipftuneable { u_long ipft_max; int ipft_sz; int ipft_flags; + struct ipftuneable *ipft_next; } ipftuneable_t; #define ipft_addr ipft_una.ipftp_void @@ -1131,63 +1183,54 @@ extern struct ifnet *get_unit __P((char *, int)); extern char *get_ifname __P((struct ifnet *)); # if defined(__NetBSD__) || defined(__OpenBSD__) || \ (_BSDI_VERSION >= 199701) || (__FreeBSD_version >= 300000) -extern int frrequest __P((int, u_long, caddr_t, int, int)); -extern int iplioctl __P((int, u_long, caddr_t, int)); -extern int fr_ipftune __P((u_long, char *)); +extern int iplioctl __P((int, ioctlcmd_t, caddr_t, int)); # else -extern int frrequest __P((int, int, caddr_t, int, int)); -extern int iplioctl __P((int, int, caddr_t, int)); -extern int fr_ipftune __P((int, char *)); +extern int iplioctl __P((int, ioctlcmd_t, caddr_t, int)); # endif extern int iplopen __P((dev_t, int)); extern int iplclose __P((dev_t, int)); extern void m_freem __P((mb_t *)); #else /* #ifndef _KERNEL */ -extern void *fr_pullup __P((mb_t *, fr_info_t *, int)); # if defined(__NetBSD__) && defined(PFIL_HOOKS) extern void ipfilterattach __P((int)); # endif extern int ipl_enable __P((void)); extern int ipl_disable __P((void)); # ifdef MENTAT -extern int frrequest __P((int, int, caddr_t, int, int)); -extern int fr_check __P((struct ip *, int, void *, int, struct qif *, +extern int fr_check __P((struct ip *, int, void *, int, void *, mblk_t **)); # if SOLARIS # if SOLARIS2 >= 7 extern int iplioctl __P((dev_t, int, intptr_t, int, cred_t *, int *)); -extern int fr_ipftune __P((int, char *)); # else extern int iplioctl __P((dev_t, int, int *, int, cred_t *, int *)); -extern int fr_ipftune __P((int, char *)); # endif extern int iplopen __P((dev_t *, int, int, cred_t *)); extern int iplclose __P((dev_t, int, int, cred_t *)); -extern int iplread __P((dev_t, struct uio *, cred_t *)); +extern int iplread __P((dev_t, uio_t *, cred_t *)); +extern int iplwrite __P((dev_t, uio_t *, cred_t *)); # endif # ifdef __hpux extern int iplopen __P((dev_t, int, intptr_t, int)); extern int iplclose __P((dev_t, int, int)); extern int iplioctl __P((dev_t, int, caddr_t, int)); -extern int fr_ipftune __P((int, char *)); -extern int iplread __P((dev_t, struct uio *)); +extern int iplread __P((dev_t, uio_t *)); +extern int iplwrite __P((dev_t, uio_t *)); extern int iplselect __P((dev_t, int)); # endif extern int ipfsync __P((void)); extern int fr_qout __P((queue_t *, mblk_t *)); -extern void copyin_mblk __P((mblk_t *, size_t, size_t, char *)); # else /* MENTAT */ extern int fr_check __P((struct ip *, int, void *, int, mb_t **)); extern int (*fr_checkp) __P((ip_t *, int, void *, int, mb_t **)); extern size_t mbufchainlen __P((mb_t *)); # ifdef __sgi # include <sys/cred.h> -extern int frrequest __P((int, int, caddr_t, int, int)); extern int iplioctl __P((dev_t, int, caddr_t, int, cred_t *, int *)); -extern int fr_ipftune __P((int, char *)); extern int iplopen __P((dev_t *, int, int, cred_t *)); extern int iplclose __P((dev_t, int, int, cred_t *)); -extern int iplread __P((dev_t, struct uio *, cred_t *)); +extern int iplread __P((dev_t, uio_t *, cred_t *)); +extern int iplwrite __P((dev_t, uio_t *, cred_t *)); extern int ipfsync __P((void)); extern int ipfilter_sgi_attach __P((void)); extern void ipfilter_sgi_detach __P((void)); @@ -1200,37 +1243,52 @@ extern int iplidentify __P((char *)); (NetBSD >= 199511) || defined(__OpenBSD__) # if defined(__NetBSD__) || (_BSDI_VERSION >= 199701) || \ defined(__OpenBSD__) || (__FreeBSD_version >= 300000) -extern int frrequest __P((int, u_long, caddr_t, int, int)); # if (__FreeBSD_version >= 500024) +# if (__FreeBSD_version >= 502116) +extern int iplioctl __P((struct cdev*, u_long, caddr_t, int, struct thread *)); +# else extern int iplioctl __P((dev_t, u_long, caddr_t, int, struct thread *)); -extern int fr_ipftune __P((u_long, char *)); +# endif /* __FreeBSD_version >= 502116 */ # else extern int iplioctl __P((dev_t, u_long, caddr_t, int, struct proc *)); -extern int fr_ipftune __P((u_long, char *)); # endif /* __FreeBSD_version >= 500024 */ # else -extern int frrequest __P((int, int, caddr_t, int, int)); extern int iplioctl __P((dev_t, int, caddr_t, int, struct proc *)); -extern int fr_ipftune __P((int, char *)); # endif # if (__FreeBSD_version >= 500024) +# if (__FreeBSD_version >= 502116) +extern int iplopen __P((struct cdev*, int, int, struct thread *)); +extern int iplclose __P((struct cdev*, int, int, struct thread *)); +# else extern int iplopen __P((dev_t, int, int, struct thread *)); extern int iplclose __P((dev_t, int, int, struct thread *)); +# endif /* __FreeBSD_version >= 502116 */ # else extern int iplopen __P((dev_t, int, int, struct proc *)); extern int iplclose __P((dev_t, int, int, struct proc *)); # endif /* __FreeBSD_version >= 500024 */ # else +# ifdef linux +extern int iplioctl __P((struct inode *, struct file *, u_int, u_long)); +# else extern int iplopen __P((dev_t, int)); extern int iplclose __P((dev_t, int)); -extern int frrequest __P((int, int, caddr_t, int, int)); extern int iplioctl __P((dev_t, int, caddr_t, int)); -extern int fr_ipftune __P((int, char *)); +# endif # endif /* (_BSDI_VERSION >= 199510) */ # if BSD >= 199306 +# if (__FreeBSD_version >= 502116) +extern int iplread __P((struct cdev*, struct uio *, int)); +extern int iplwrite __P((struct cdev*, struct uio *, int)); +# else extern int iplread __P((dev_t, struct uio *, int)); +extern int iplwrite __P((dev_t, struct uio *, int)); +# endif /* __FreeBSD_version >= 502116 */ # else +# ifndef linux extern int iplread __P((dev_t, struct uio *)); +extern int iplwrite __P((dev_t, struct uio *)); +# endif # endif /* BSD >= 199306 */ # endif /* __ sgi */ # endif /* MENTAT */ @@ -1238,39 +1296,45 @@ extern int iplread __P((dev_t, struct uio *)); #endif /* #ifndef _KERNEL */ extern ipfmutex_t ipl_mutex, ipf_authmx, ipf_rw, ipf_hostmap; -extern ipfmutex_t ipf_timeoutlock; -extern ipfrwlock_t ipf_mutex, ipf_global, ip_poolrw; +extern ipfmutex_t ipf_timeoutlock, ipf_stinsert, ipf_natio, ipf_nat_new; +extern ipfrwlock_t ipf_mutex, ipf_global, ip_poolrw, ipf_ipidfrag; extern ipfrwlock_t ipf_frag, ipf_state, ipf_nat, ipf_natfrag, ipf_auth; +extern ipfrwlock_t ipf_frcache; extern char *memstr __P((char *, char *, int, int)); extern int count4bits __P((u_32_t)); -#ifdef USE_INET6 extern int count6bits __P((u_32_t *)); -#endif +extern int frrequest __P((int, ioctlcmd_t, caddr_t, int, int)); extern char *getifname __P((struct ifnet *)); extern int iplattach __P((void)); extern int ipldetach __P((void)); -# if defined(__NetBSD__) || defined(__OpenBSD__) -extern INLINE int fr_ioctlswitch __P((int, void *, u_long, int)); -#else -extern INLINE int fr_ioctlswitch __P((int, void *, int, int)); -#endif extern u_short ipf_cksum __P((u_short *, int)); extern int copyinptr __P((void *, void *, size_t)); extern int copyoutptr __P((void *, void *, size_t)); +extern int fr_fastroute __P((mb_t *, mb_t **, fr_info_t *, frdest_t *)); extern int fr_inobj __P((void *, void *, int)); +extern int fr_inobjsz __P((void *, void *, int, int)); +extern int fr_ioctlswitch __P((int, void *, ioctlcmd_t, int)); +extern int fr_ipftune __P((ioctlcmd_t, void *)); extern int fr_outobj __P((void *, void *, int)); -extern int fr_send_reset __P((fr_info_t *)); -extern int fr_send_icmp_err __P((int, fr_info_t *, int)); -extern void fr_resolvdest __P((struct frdest *, int)); +extern int fr_outobjsz __P((void *, void *, int, int)); +extern void *fr_pullup __P((mb_t *, fr_info_t *, int)); +extern void fr_resolvedest __P((struct frdest *, int)); extern int fr_resolvefunc __P((void *)); -extern int fr_fastroute __P((mb_t *, mb_t **, fr_info_t *, frdest_t *)); +extern void *fr_resolvenic __P((char *, int)); +extern int fr_send_icmp_err __P((int, fr_info_t *, int)); +extern int fr_send_reset __P((fr_info_t *)); +#if (__FreeBSD_version < 490000) || !defined(_KERNEL) extern int ppsratecheck __P((struct timeval *, int *, int)); +#endif extern ipftq_t *fr_addtimeoutqueue __P((ipftq_t **, u_int)); -extern void fr_deletetimeoutqueue __P((ipftq_t *)); +extern void fr_deletequeueentry __P((ipftqent_t *)); +extern int fr_deletetimeoutqueue __P((ipftq_t *)); +extern void fr_freetimeoutqueue __P((ipftq_t *)); extern void fr_movequeue __P((ipftqent_t *, ipftq_t *, ipftq_t *)); -extern void fr_queuefront __P((ipftqent_t *)); +extern void fr_queueappend __P((ipftqent_t *, ipftq_t *, void *)); extern void fr_queueback __P((ipftqent_t *)); +extern void fr_queuefront __P((ipftqent_t *)); extern void fr_checkv4sum __P((fr_info_t *)); extern int fr_checkl4sum __P((fr_info_t *)); extern int fr_ifpfillv4addr __P((int, struct sockaddr_in *, @@ -1284,8 +1348,11 @@ extern int fr_ifpfillv6addr __P((int, struct sockaddr_in6 *, struct in_addr *)); #endif +extern int fr_addipftune __P((ipftuneable_t *)); +extern int fr_delipftune __P((ipftuneable_t *)); + extern int frflush __P((minor_t, int, int)); -extern void frsync __P((void)); +extern void frsync __P((void *)); extern frgroup_t *fr_addgroup __P((char *, void *, u_32_t, minor_t, int)); extern int fr_derefrule __P((frentry_t **)); extern void fr_delgroup __P((char *, minor_t, int)); @@ -1293,7 +1360,7 @@ extern frgroup_t *fr_findgroup __P((char *, minor_t, int, frgroup_t ***)); extern int fr_loginit __P((void)); extern int ipflog_clear __P((minor_t)); -extern int ipflog_read __P((minor_t, struct uio *)); +extern int ipflog_read __P((minor_t, uio_t *)); extern int ipflog __P((fr_info_t *, u_int)); extern int ipllog __P((int, fr_info_t *, void **, size_t *, int *, int)); extern void fr_logunload __P((void)); @@ -1301,6 +1368,7 @@ extern void fr_logunload __P((void)); extern frentry_t *fr_acctpkt __P((fr_info_t *, u_32_t *)); extern int fr_copytolog __P((int, char *, int)); extern u_short fr_cksum __P((mb_t *, ip_t *, int, void *)); +extern void fr_deinitialise __P((void)); extern frentry_t *fr_dolog __P((fr_info_t *, u_32_t *)); extern frentry_t *fr_dstgrpmap __P((fr_info_t *, u_32_t *)); extern void fr_fixskip __P((frentry_t **, frentry_t *, int)); @@ -1309,20 +1377,21 @@ extern frentry_t *fr_getrulen __P((int, char *, u_32_t)); extern void fr_getstat __P((struct friostat *)); extern int fr_ifpaddr __P((int, int, void *, struct in_addr *, struct in_addr *)); -extern int fr_lock __P((caddr_t, int *)); +extern int fr_initialise __P((void)); +extern void fr_lock __P((caddr_t, int *)); extern int fr_makefrip __P((int, ip_t *, fr_info_t *)); extern int fr_matchtag __P((ipftag_t *, ipftag_t *)); extern int fr_matchicmpqueryreply __P((int, icmpinfo_t *, struct icmp *, int)); extern u_32_t fr_newisn __P((fr_info_t *)); -extern INLINE u_short fr_nextipid __P((fr_info_t *)); +extern u_short fr_nextipid __P((fr_info_t *)); extern int fr_rulen __P((int, frentry_t *)); extern int fr_scanlist __P((fr_info_t *, u_32_t)); extern frentry_t *fr_srcgrpmap __P((fr_info_t *, u_32_t *)); extern int fr_tcpudpchk __P((fr_info_t *, frtuc_t *)); extern int fr_verifysrc __P((fr_info_t *fin)); +extern int fr_zerostats __P((char *)); -extern int fr_unreach; extern int fr_running; extern u_long fr_frouteok[2]; extern int fr_pass; @@ -1339,6 +1408,7 @@ extern int ipl_suppress; extern int ipl_buffer_sz; extern int ipl_logmax; extern int ipl_logall; +extern int ipl_logsize; extern u_long fr_ticks; extern fr_info_t frcache[2][8]; extern char ipfilter_version[]; @@ -1354,11 +1424,8 @@ extern int icmpreplytype6[ICMP6_MAXTYPE + 1]; extern int icmpreplytype4[ICMP_MAXTYPE + 1]; extern struct frgroup *ipfgroups[IPL_LOGSIZE][2]; extern struct filterstats frstats[]; -extern int icmpreplytype4[ICMP_MAXTYPE + 1]; -extern struct frgroup *ipfgroups[IPL_LOGSIZE][2]; -extern struct filterstats frstats[]; extern frentry_t *ipfrule_match __P((fr_info_t *)); extern u_char ipf_iss_secret[32]; - +extern ipftuneable_t ipf_tuneables[]; #endif /* __IP_FIL_H__ */ diff --git a/usr/src/common/ipf/ip_frag.h b/usr/src/uts/common/inet/ipf/netinet/ip_frag.h index a7fa4eed71..7eb7399010 100644 --- a/usr/src/common/ipf/ip_frag.h +++ b/usr/src/uts/common/inet/ipf/netinet/ip_frag.h @@ -4,9 +4,9 @@ * See the IPFILTER.LICENCE file for details on licencing. * * @(#)ip_frag.h 1.5 3/24/96 - * $Id: ip_frag.h,v 2.22 2003/06/24 11:13:53 darrenr Exp $ + * $Id: ip_frag.h,v 2.23.2.2 2005/06/10 18:02:37 darrenr Exp $ * - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -38,8 +38,8 @@ typedef struct ipfr { frentry_t *ipfr_rule; } ipfr_t; -#define ipfr_src ipfr_source.in4 -#define ipfr_dst ipfr_dest.in4 +#define ipfr_src ipfr_source.in4 +#define ipfr_dst ipfr_dest.in4 typedef struct ipfrstat { u_long ifs_exists; /* add & already exists */ @@ -79,16 +79,18 @@ extern void fr_fragclear __P((void)); extern void fr_fragexpire __P((void)); #if defined(_KERNEL) && ((BSD >= 199306) || SOLARIS || defined(__sgi) \ - || defined(__osf__) || (defined(__sgi) && (IRIX >= 605))) + || defined(__osf__) || (defined(__sgi) && (IRIX >= 60500))) # if defined(SOLARIS2) && (SOLARIS2 < 7) extern void fr_slowtimer __P((void)); # else -#ifndef _KERNEL extern void fr_slowtimer __P((void *)); -#endif # endif #else +# if defined(linux) && defined(_KERNEL) +extern void fr_slowtimer __P((long)); +# else extern int fr_slowtimer __P((void)); +# endif #endif #endif /* __IP_FRAG_H__ */ diff --git a/usr/src/common/ipf/ip_ftp_pxy.c b/usr/src/uts/common/inet/ipf/netinet/ip_ftp_pxy.c index 6428ebf6c0..7d1ed33c96 100644 --- a/usr/src/common/ipf/ip_ftp_pxy.c +++ b/usr/src/uts/common/inet/ipf/netinet/ip_ftp_pxy.c @@ -3,21 +3,18 @@ * * See the IPFILTER.LICENCE file for details on licencing. * - * Copyright 2003 Sun Microsystems, Inc. All rights reserved. + * $Id: ip_ftp_pxy.c,v 2.88.2.15 2005/03/19 19:38:10 darrenr Exp $ + * + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. * * Simple FTP transparent proxy for in-kernel use. For use with the NAT * code. - * - */ +*/ #pragma ident "%Z%%M% %I% %E% SMI" -#ifdef USE_MUTEXES -extern ipfmutex_t ipf_rw; -#endif -#define IPF_FTP_DEBUG #define IPF_FTP_PROXY #define IPF_MINPORTLEN 18 @@ -26,7 +23,6 @@ extern ipfmutex_t ipf_rw; #define IPF_MAX227LEN 51 #define IPF_MIN229LEN 47 #define IPF_MAX229LEN 51 -#define IPF_FTPBUFSZ 96 /* This *MUST* be >= 53! */ #define FTPXY_GO 0 #define FTPXY_INIT 1 @@ -69,13 +65,36 @@ u_short ippr_ftp_atoi __P((char **)); int ippr_ftp_pasvreply __P((fr_info_t *, ip_t *, nat_t *, ftpside_t *, u_int, char *, char *, u_int)); -static frentry_t ftppxyfr; int ftp_proxy_init = 0; int ippr_ftp_pasvonly = 0; int ippr_ftp_insecure = 0; /* Do not require logins before transfers */ int ippr_ftp_pasvrdr = 0; int ippr_ftp_forcepasv = 0; /* PASV must be last command prior to 227 */ +#if defined(_KERNEL) +int ippr_ftp_debug = 0; +#else +int ippr_ftp_debug = 2; +#endif +/* + * 1 - security + * 2 - errors + * 3 - error debugging + * 4 - parsing errors + * 5 - parsing info + * 6 - parsing debug + */ + +static frentry_t ftppxyfr; +static ipftuneable_t ftptune = { + { &ippr_ftp_debug }, + "ippr_ftp_debug", + 0, + 10, + sizeof(ippr_ftp_debug), + 0, + NULL +}; /* @@ -88,6 +107,7 @@ int ippr_ftp_init() ftppxyfr.fr_flags = FR_INQUE|FR_PASS|FR_QUICK|FR_KEEPSTATE; MUTEX_INIT(&ftppxyfr.fr_lock, "FTP Proxy Mutex"); ftp_proxy_init = 1; + (void) fr_addipftune(&ftptune); return 0; } @@ -95,6 +115,8 @@ int ippr_ftp_init() void ippr_ftp_fini() { + (void) fr_delipftune(&ftptune); + if (ftp_proxy_init == 1) { MUTEX_DESTROY(&ftppxyfr.fr_lock); ftp_proxy_init = 0; @@ -143,8 +165,8 @@ int dlen; tcphdr_t *tcp, tcph, *tcp2 = &tcph; char newbuf[IPF_FTPBUFSZ], *s; struct in_addr swip, swip2; - int inc, off = 0, flags; u_int a1, a2, a3, a4; + int inc, off, flags; u_short a5, a6, sp; size_t nlen, olen; fr_info_t fi; @@ -153,15 +175,15 @@ int dlen; m = fin->fin_m; tcp = (tcphdr_t *)fin->fin_dp; - off = (char *)tcp - MTOD(m, char *) + (TCP_OFF(tcp) << 2); + off = (char *)tcp - (char *)ip + (TCP_OFF(tcp) << 2) + fin->fin_ipoff; /* * Check for client sending out PORT message. */ if (dlen < IPF_MINPORTLEN) { -#if !defined(_KERNEL) || defined(IPF_FTP_DEBUG) - printf("ippr_ftp_port:dlen(%d) < IPF_MINPORTLEN\n", dlen); -#endif + if (ippr_ftp_debug > 1) + printf("ippr_ftp_port:dlen(%d) < IPF_MINPORTLEN\n", + dlen); return 0; } /* @@ -173,18 +195,17 @@ int dlen; */ a1 = ippr_ftp_atoi(&s); if (s == NULL) { -#if !defined(_KERNEL) || defined(IPF_FTP_DEBUG) - printf("ippr_ftp_port:ippr_ftp_atoi(1) failed\n"); -#endif + if (ippr_ftp_debug > 1) + printf("ippr_ftp_port:ippr_ftp_atoi(%d) failed\n", 1); return 0; } a2 = ippr_ftp_atoi(&s); if (s == NULL) { -#if !defined(_KERNEL) || defined(IPF_FTP_DEBUG) - printf("ippr_ftp_port:ippr_ftp_atoi(2) failed\n"); -#endif + if (ippr_ftp_debug > 1) + printf("ippr_ftp_port:ippr_ftp_atoi(%d) failed\n", 2); return 0; } + /* * Check that IP address in the PORT/PASV reply is the same as the * sender of the command - prevents using PORT for port scanning. @@ -195,17 +216,15 @@ int dlen; (a1 != ntohl(nat->nat_inip.s_addr))) || ((nat->nat_dir == NAT_INBOUND) && (a1 != ntohl(nat->nat_oip.s_addr)))) { -#if !defined(_KERNEL) || defined(IPF_FTP_DEBUG) - printf("ippr_ftp_port:a1 != nat->nat_inip\n"); -#endif + if (ippr_ftp_debug > 0) + printf("ippr_ftp_port:%s != nat->nat_inip\n", "a1"); return APR_ERR(1); } a5 = ippr_ftp_atoi(&s); if (s == NULL) { -#if !defined(_KERNEL) || defined(IPF_FTP_DEBUG) - printf("ippr_ftp_port:ippr_ftp_atoi(3) failed\n"); -#endif + if (ippr_ftp_debug > 1) + printf("ippr_ftp_port:ippr_ftp_atoi(%d) failed\n", 3); return 0; } if (*s == ')') @@ -220,13 +239,23 @@ int dlen; s += 2; a6 = a5 & 0xff; } else { -#if !defined(_KERNEL) || defined(IPF_FTP_DEBUG) - printf("ippr_ftp_port:missing cr-lf\n"); -#endif + if (ippr_ftp_debug > 1) + printf("ippr_ftp_port:missing %s\n", "cr-lf"); return 0; } + a5 >>= 8; a5 &= 0xff; + sp = a5 << 8 | a6; + /* + * Don't allow the PORT command to specify a port < 1024 due to + * security crap. + */ + if (sp < 1024) { + if (ippr_ftp_debug > 0) + printf("ippr_ftp_port:sp(%d) < 1024\n", sp); + return 0; + } /* * Calculate new address parts for PORT command */ @@ -240,9 +269,9 @@ int dlen; a1 >>= 24; olen = s - f->ftps_rptr; /* DO NOT change this to snprintf! */ -#if defined(__hpux) && defined(_KERNEL) - (void) sprintf(newbuf, sizeof(newbuf), "%s %u,%u,%u,%u,%u,%u\r\n", - "PORT", a1, a2, a3, a4, a5, a6); +#if defined(SNPRINTF) && defined(_KERNEL) + (void) SNPRINTF(newbuf, sizeof(newbuf), "%s %u,%u,%u,%u,%u,%u\r\n", + "PORT", a1, a2, a3, a4, a5, a6); #else (void) sprintf(newbuf, "%s %u,%u,%u,%u,%u,%u\r\n", "PORT", a1, a2, a3, a4, a5, a6); @@ -251,9 +280,9 @@ int dlen; nlen = strlen(newbuf); inc = nlen - olen; if ((inc + ip->ip_len) > 65535) { -#if !defined(_KERNEL) || defined(IPF_FTP_DEBUG) - printf("ippr_ftp_port:inc(%d) + ip->ip_len > 65535\n", inc); -#endif + if (ippr_ftp_debug > 0) + printf("ippr_ftp_port:inc(%d) + ip->ip_len > 65535\n", + inc); return 0; } @@ -263,16 +292,16 @@ int dlen; # if defined(MENTAT) if (inc < 0) (void)adjmsg(m, inc); -# else +# else /* defined(MENTAT) */ + /* + * m_adj takes care of pkthdr.len, if required and treats inc<0 to + * mean remove -len bytes from the end of the packet. + * The mbuf chain will be extended if necessary by m_copyback(). + */ if (inc < 0) m_adj(m, inc); -# ifdef M_PKTHDR - if (!(m->m_flags & M_PKTHDR)) - m->m_pkthdr.len += inc; -# endif -# endif -#endif - /* the mbuf chain will be extended if necessary by m_copyback() */ +# endif /* defined(MENTAT) */ +#endif /* !defined(_KERNEL) */ COPYBACK(m, off, nlen, newbuf); if (inc != 0) { @@ -282,29 +311,20 @@ int dlen; } /* - * Add skeleton NAT entry for connection which will come back the - * other way. - */ - sp = a5 << 8 | a6; - /* - * Don't allow the PORT command to specify a port < 1024 due to - * security crap. - */ - if (sp < 1024) { -#if !defined(_KERNEL) || defined(IPF_FTP_DEBUG) - printf("ippr_ftp_port:sp(%d) < 1024\n", sp); -#endif - return 0; - } - /* * The server may not make the connection back from port 20, but * it is the most likely so use it here to check for a conflicting * mapping. */ bcopy((char *)fin, (char *)&fi, sizeof(fi)); + fi.fin_state = NULL; + fi.fin_nat = NULL; fi.fin_flx |= FI_IGNORE; fi.fin_data[0] = sp; fi.fin_data[1] = fin->fin_data[1] - 1; + /* + * Add skeleton NAT entry for connection which will come back the + * other way. + */ if (nat->nat_dir == NAT_OUTBOUND) nat2 = nat_outlookup(&fi, NAT_SEARCH|IPN_TCP, nat->nat_p, nat->nat_inip, nat->nat_oip); @@ -353,6 +373,8 @@ int dlen; ip->ip_dst = nat->nat_inip; } (void) fr_addstate(&fi, &nat2->nat_state, SI_W_DPORT); + if (fi.fin_state != NULL) + fr_statederef(&fi, (ipstate_t **)&fi.fin_state); } ip->ip_len = slen; ip->ip_src = swip; @@ -365,8 +387,8 @@ int dlen; is = nat2->nat_state; if (is != NULL) { MUTEX_ENTER(&is->is_lock); - (void)fr_tcp_age(&is->is_sti, &fi, ips_tqtqb, - is->is_flags); + (void)fr_tcp_age(&is->is_sti, &fi, ips_tqtqb, + is->is_flags); MUTEX_EXIT(&is->is_lock); } RWLOCK_EXIT(&ipf_state); @@ -393,8 +415,8 @@ int dlen; for (i = 0; (i < 5) && (i < dlen); i++) { c = rptr[i]; - if (isalpha(c)) { - cmd[i] = toupper(c); + if (ISALPHA(c)) { + cmd[i] = TOUPPER(c); } else { cmd[i] = c; } @@ -455,16 +477,15 @@ int dlen; { u_int a1, a2, a3, a4, data_ip; char newbuf[IPF_FTPBUFSZ]; + char *s, *brackets[2]; u_short a5, a6; ftpside_t *f; - char *s; if (ippr_ftp_forcepasv != 0 && ftp->ftp_side[0].ftps_cmds != FTPXY_C_PASV) { -#if !defined(_KERNEL) || defined(IPF_FTP_DEBUG) - printf("ippr_ftp_pasv:ftps_cmds(%d) != FTPXY_C_PASV\n", - ftp->ftp_side[0].ftps_cmds); -#endif + if (ippr_ftp_debug > 0) + printf("ippr_ftp_pasv:ftps_cmds(%d) != FTPXY_C_PASV\n", + ftp->ftp_side[0].ftps_cmds); return 0; } @@ -475,39 +496,44 @@ int dlen; * Check for PASV reply message. */ if (dlen < IPF_MIN227LEN) { -#if !defined(_KERNEL) || defined(IPF_FTP_DEBUG) - printf("ippr_ftp_pasv:dlen(%d) < IPF_MIN227LEN\n", dlen); -#endif + if (ippr_ftp_debug > 1) + printf("ippr_ftp_pasv:dlen(%d) < IPF_MIN227LEN\n", + dlen); return 0; } else if (strncmp(f->ftps_rptr, "227 Entering Passive Mod", PASV_REPLEN)) { -#if !defined(_KERNEL) || defined(IPF_FTP_DEBUG) - printf("ippr_ftp_pasv:227 reply wrong\n"); -#endif + if (ippr_ftp_debug > 0) + printf("ippr_ftp_pasv:%d reply wrong\n", 227); return 0; } + brackets[0] = ""; + brackets[1] = ""; /* * Skip the PASV reply + space */ s = f->ftps_rptr + PASV_REPLEN; - while (*s && !isdigit(*s)) + while (*s && !ISDIGIT(*s)) { + if (*s == '(') { + brackets[0] = "("; + brackets[1] = ")"; + } s++; + } + /* * Pick out the address components, two at a time. */ a1 = ippr_ftp_atoi(&s); if (s == NULL) { -#if !defined(_KERNEL) || defined(IPF_FTP_DEBUG) - printf("ippr_ftp_pasv:ippr_ftp_atoi(1) failed\n"); -#endif + if (ippr_ftp_debug > 1) + printf("ippr_ftp_pasv:ippr_ftp_atoi(%d) failed\n", 1); return 0; } a2 = ippr_ftp_atoi(&s); if (s == NULL) { -#if !defined(_KERNEL) || defined(IPF_FTP_DEBUG) - printf("ippr_ftp_pasv:ippr_ftp_atoi(2) failed\n"); -#endif + if (ippr_ftp_debug > 1) + printf("ippr_ftp_pasv:ippr_ftp_atoi(%d) failed\n", 2); return 0; } @@ -522,17 +548,15 @@ int dlen; (a1 != ntohl(nat->nat_inip.s_addr))) || ((nat->nat_dir == NAT_OUTBOUND) && (a1 != ntohl(nat->nat_oip.s_addr)))) { -#if !defined(_KERNEL) || defined(IPF_FTP_DEBUG) - printf("ippr_ftp_pasv:a1 != nat->nat_oip\n"); -#endif + if (ippr_ftp_debug > 0) + printf("ippr_ftp_pasv:%s != nat->nat_oip\n", "a1"); return 0; } a5 = ippr_ftp_atoi(&s); if (s == NULL) { -#if !defined(_KERNEL) || defined(IPF_FTP_DEBUG) - printf("ippr_ftp_pasv:ippr_ftp_atoi(3) failed\n"); -#endif + if (ippr_ftp_debug > 1) + printf("ippr_ftp_pasv:ippr_ftp_atoi(%d) failed\n", 3); return 0; } @@ -548,9 +572,8 @@ int dlen; if ((*s == '\r') && (*(s + 1) == '\n')) { s += 2; } else { -#if !defined(_KERNEL) || defined(IPF_FTP_DEBUG) - printf("ippr_ftp_pasv:missing cr-lf\n"); -#endif + if (ippr_ftp_debug > 1) + printf("ippr_ftp_pasv:missing %s", "cr-lf\n"); return 0; } @@ -570,12 +593,14 @@ int dlen; a4 = a1 & 0xff; a1 >>= 24; -#if defined(__hpux) && defined(_KERNEL) - (void) sprintf(newbuf, sizeof(newbuf), "%s %u,%u,%u,%u,%u,%u\r\n", - "227 Entering Passive Mode", a1, a2, a3, a4, a5, a6); +#if defined(SNPRINTF) && defined(_KERNEL) + (void) SNPRINTF(newbuf, sizeof(newbuf), "%s %s%u,%u,%u,%u,%u,%u%s\r\n", + "227 Entering Passive Mode", brackets[0], a1, a2, a3, a4, + a5, a6, brackets[1]); #else - (void) sprintf(newbuf, "%s %u,%u,%u,%u,%u,%u\r\n", - "227 Entering Passive Mode", a1, a2, a3, a4, a5, a6); + (void) sprintf(newbuf, "%s %s%u,%u,%u,%u,%u,%u%s\r\n", + "227 Entering Passive Mode", brackets[0], a1, a2, a3, a4, + a5, a6, brackets[1]); #endif return ippr_ftp_pasvreply(fin, ip, nat, f, (a5 << 8 | a6), newbuf, s, data_ip); @@ -602,7 +627,7 @@ u_int data_ip; m = fin->fin_m; tcp = (tcphdr_t *)fin->fin_dp; - off = (char *)tcp - MTOD(m, char *) + (TCP_OFF(tcp) << 2); + off = (char *)tcp - (char *)ip + (TCP_OFF(tcp) << 2) + fin->fin_ipoff; data_addr.s_addr = data_ip; tcp2 = &tcph; @@ -613,22 +638,26 @@ u_int data_ip; nlen = strlen(newmsg); inc = nlen - olen; if ((inc + ip->ip_len) > 65535) { -#if !defined(_KERNEL) || defined(IPF_FTP_DEBUG) - printf("ippr_ftp_pasv:inc(%d) + ip->ip_len > 65535\n", inc); -#endif + if (ippr_ftp_debug > 0) + printf("ippr_ftp_pasv:inc(%d) + ip->ip_len > 65535\n", + inc); return 0; } #if !defined(_KERNEL) - bcopy(newmsg, (char *)m + off, nlen); + bcopy(newmsg, MTOD(m, char *) + off, nlen); #else # if defined(MENTAT) if (inc < 0) (void)adjmsg(m, inc); # else /* defined(MENTAT) */ + /* + * m_adj takes care of pkthdr.len, if required and treats inc<0 to + * mean remove -len bytes from the end of the packet. + * The mbuf chain will be extended if necessary by m_copyback(). + */ if (inc < 0) m_adj(m, inc); - /* the mbuf chain will be extended if necessary by m_copyback() */ # endif /* defined(MENTAT) */ #endif /* !defined(_KERNEL) */ COPYBACK(m, off, nlen, newmsg); @@ -644,6 +673,8 @@ u_int data_ip; * other way. */ bcopy((char *)fin, (char *)&fi, sizeof(fi)); + fi.fin_state = NULL; + fi.fin_nat = NULL; fi.fin_flx |= FI_IGNORE; fi.fin_data[0] = 0; fi.fin_data[1] = port; @@ -703,6 +734,8 @@ u_int data_ip; ip->ip_dst = nat->nat_inip; } (void) fr_addstate(&fi, &nat2->nat_state, sflags); + if (fi.fin_state != NULL) + fr_statederef(&fi, (ipstate_t **)&fi.fin_state); } ip->ip_len = slen; @@ -716,8 +749,8 @@ u_int data_ip; is = nat2->nat_state; if (is != NULL) { MUTEX_ENTER(&is->is_lock); - (void) fr_tcp_age(&is->is_sti, &fi, ips_tqtqb, - is->is_flags); + (void)fr_tcp_age(&is->is_sti, &fi, ips_tqtqb, + is->is_flags); MUTEX_EXIT(&is->is_lock); } RWLOCK_EXIT(&ipf_state); @@ -742,7 +775,9 @@ int dlen; rptr = f->ftps_rptr; wptr = f->ftps_wptr; - if (!isdigit(*rptr) || !isdigit(*(rptr + 1)) || !isdigit(*(rptr + 2))) + if (*rptr == ' ') + goto server_cmd_ok; + if (!ISDIGIT(*rptr) || !ISDIGIT(*(rptr + 1)) || !ISDIGIT(*(rptr + 2))) return 0; if (ftp->ftp_passok == FTPXY_GO) { if (!strncmp(rptr, "227 ", 4)) @@ -777,6 +812,7 @@ int dlen; } } } +server_cmd_ok: ftp->ftp_incok = 0; while ((*rptr++ != '\n') && (rptr < wptr)) @@ -795,34 +831,38 @@ ftpside_t *ftps; char *buf; size_t len; { - register char *s, c; + register char *s, c, pc; register size_t i = len; char cmd[5]; + s = buf; + + if (ftps->ftps_junk == 1) + return 1; + if (i < 5) { -#if !defined(_KERNEL) || defined(IPF_FTP_DEBUG) - printf("ippr_ftp_client_valid:i(%d) < 5\n", (int)i); -#endif + if (ippr_ftp_debug > 3) + printf("ippr_ftp_client_valid:i(%d) < 5\n", (int)i); return 2; } - s = buf; - c = *s++; + i--; + c = *s++; - if (isalpha(c)) { - cmd[0] = toupper(c); + if (ISALPHA(c)) { + cmd[0] = TOUPPER(c); c = *s++; i--; - if (isalpha(c)) { - cmd[1] = toupper(c); + if (ISALPHA(c)) { + cmd[1] = TOUPPER(c); c = *s++; i--; - if (isalpha(c)) { - cmd[2] = toupper(c); + if (ISALPHA(c)) { + cmd[2] = TOUPPER(c); c = *s++; i--; - if (isalpha(c)) { - cmd[3] = toupper(c); + if (ISALPHA(c)) { + cmd[3] = TOUPPER(c); c = *s++; i--; if ((c != ' ') && (c != '\r')) @@ -835,16 +875,18 @@ size_t len; goto bad_client_command; } else { bad_client_command: -#if !defined(_KERNEL) || defined(IPF_FTP_DEBUG) - printf("ippr_ftp_client_valid:bad cmd:len %d i %d c 0x%x\n", - (int)i, (int)len, c); -#endif + if (ippr_ftp_debug > 3) + printf("%s:bad:junk %d len %d/%d c 0x%x buf [%*s]\n", + "ippr_ftp_client_valid", + ftps->ftps_junk, (int)len, (int)i, c, + (int)len, buf); return 1; } for (; i; i--) { + pc = c; c = *s++; - if (c == '\n') { + if ((pc == '\r') && (c == '\n')) { cmd[4] = '\0'; if (!strcmp(cmd, "PASV")) ftps->ftps_cmds = FTPXY_C_PASV; @@ -854,7 +896,8 @@ bad_client_command: } } #if !defined(_KERNEL) - printf("ippr_ftp_client_valid:junk after cmd[%s]\n", buf); + printf("ippr_ftp_client_valid:junk after cmd[%*.*s]\n", + (int)len, (int)len, buf); #endif return 2; } @@ -865,26 +908,36 @@ ftpside_t *ftps; char *buf; size_t len; { - register char *s, c; + register char *s, c, pc; register size_t i = len; int cmd; - if (i < 5) - return 2; s = buf; - c = *s++; cmd = 0; + + if (ftps->ftps_junk == 1) + return 1; + + if (i < 5) { + if (ippr_ftp_debug > 3) + printf("ippr_ftp_servert_valid:i(%d) < 5\n", (int)i); + return 2; + } + + c = *s++; i--; + if (c == ' ') + goto search_eol; - if (isdigit(c)) { + if (ISDIGIT(c)) { cmd = (c - '0') * 100; c = *s++; i--; - if (isdigit(c)) { + if (ISDIGIT(c)) { cmd += (c - '0') * 10; c = *s++; i--; - if (isdigit(c)) { + if (ISDIGIT(c)) { cmd += (c - '0'); c = *s++; i--; @@ -896,23 +949,25 @@ size_t len; goto bad_server_command; } else { bad_server_command: -#if !defined(_KERNEL) || defined(IPF_FTP_DEBUG) - printf("ippr_ftp_server_valid:bad cmd:len %d i %d c 0x%x\n", - (int)i, (int)len, c); -#endif + if (ippr_ftp_debug > 3) + printf("%s:bad:junk %d len %d/%d c 0x%x buf [%*s]\n", + "ippr_ftp_server_valid", + ftps->ftps_junk, (int)len, (int)i, + c, (int)len, buf); return 1; } - +search_eol: for (; i; i--) { + pc = c; c = *s++; - if (c == '\n') { + if ((pc == '\r') && (c == '\n')) { ftps->ftps_cmds = cmd; return 0; } } -#if !defined(_KERNEL) - printf("ippr_ftp_server_valid:junk after cmd[%s]\n", buf); -#endif + if (ippr_ftp_debug > 3) + printf("ippr_ftp_server_valid:junk after cmd[%*s]\n", + (int)len, buf); return 2; } @@ -951,8 +1006,8 @@ ftpinfo_t *ftp; int rv; { int mlen, len, off, inc, i, sel, sel2, ok, ackoff, seqoff; + char *rptr, *wptr, *s; u_32_t thseq, thack; - char *rptr, *wptr; ap_session_t *aps; ftpside_t *f, *t; tcphdr_t *tcp; @@ -962,14 +1017,21 @@ int rv; m = fin->fin_m; ip = fin->fin_ip; tcp = (tcphdr_t *)fin->fin_dp; - off = (char *)tcp - MTOD(m, char *) + (TCP_OFF(tcp) << 2); + off = (char *)tcp - (char *)ip + (TCP_OFF(tcp) << 2) + fin->fin_ipoff; f = &ftp->ftp_side[rv]; t = &ftp->ftp_side[1 - rv]; thseq = ntohl(tcp->th_seq); thack = ntohl(tcp->th_ack); +#ifdef __sgi + mlen = fin->fin_plen - off; +#else mlen = MSGDSIZE(m) - off; +#endif + if (ippr_ftp_debug > 4) + printf("ippr_ftp_process: mlen %d\n", mlen); + if (mlen <= 0) { if ((tcp->th_flags & TH_OPENING) == TH_OPENING) { f->ftps_seq[0] = thseq + 1; @@ -989,19 +1051,17 @@ int rv; if (aps->aps_ackmin[sel2] > ackoff + thack) ackoff = aps->aps_ackoff[!sel2]; } else { -#if PROXY_DEBUG - printf("seqoff %d thseq %x ackmin %x\n", seqoff, thseq, - aps->aps_ackmin[sel]); -#endif seqoff = aps->aps_ackoff[sel]; + if (ippr_ftp_debug > 2) + printf("seqoff %d thseq %x ackmin %x\n", seqoff, thseq, + aps->aps_ackmin[sel]); if (aps->aps_ackmin[sel] > seqoff + thseq) seqoff = aps->aps_ackoff[!sel]; -#if PROXY_DEBUG - printf("ackoff %d thack %x seqmin %x\n", ackoff, thack, - aps->aps_seqmin[sel2]); -#endif ackoff = aps->aps_seqoff[sel2]; + if (ippr_ftp_debug > 2) + printf("ackoff %d thack %x seqmin %x\n", ackoff, thack, + aps->aps_seqmin[sel2]); if (ackoff > 0) { if (aps->aps_seqmin[sel2] > ackoff + thack) ackoff = aps->aps_seqoff[!sel2]; @@ -1010,26 +1070,27 @@ int rv; ackoff = aps->aps_seqoff[!sel2]; } } -#if PROXY_DEBUG - printf("%s: %x seq %x/%d ack %x/%d len %d\n", rv ? "IN" : "OUT", - tcp->th_flags, thseq, seqoff, thack, ackoff, mlen); - printf("sel %d seqmin %x/%x offset %d/%d\n", sel, - aps->aps_seqmin[sel], aps->aps_seqmin[sel2], - aps->aps_seqoff[sel], aps->aps_seqoff[sel2]); - printf("sel %d ackmin %x/%x offset %d/%d\n", sel2, - aps->aps_ackmin[sel], aps->aps_ackmin[sel2], - aps->aps_ackoff[sel], aps->aps_ackoff[sel2]); -#endif + if (ippr_ftp_debug > 2) { + printf("%s: %x seq %x/%d ack %x/%d len %d/%d off %d\n", + rv ? "IN" : "OUT", tcp->th_flags, thseq, seqoff, + thack, ackoff, mlen, fin->fin_plen, off); + printf("sel %d seqmin %x/%x offset %d/%d\n", sel, + aps->aps_seqmin[sel], aps->aps_seqmin[sel2], + aps->aps_seqoff[sel], aps->aps_seqoff[sel2]); + printf("sel %d ackmin %x/%x offset %d/%d\n", sel2, + aps->aps_ackmin[sel], aps->aps_ackmin[sel2], + aps->aps_ackoff[sel], aps->aps_ackoff[sel2]); + } /* * XXX - Ideally, this packet should get dropped because we now know * that it is out of order (and there is no real danger in doing so * apart from causing packets to go through here ordered). */ -#if PROXY_DEBUG - printf("rv %d t:seq[0] %x seq[1] %x %d/%d\n", - rv, t->ftps_seq[0], t->ftps_seq[1], seqoff, ackoff); -#endif + if (ippr_ftp_debug > 2) { + printf("rv %d t:seq[0] %x seq[1] %x %d/%d\n", + rv, t->ftps_seq[0], t->ftps_seq[1], seqoff, ackoff); + } ok = 0; if (t->ftps_seq[0] == 0) { @@ -1058,33 +1119,35 @@ int rv; } } -#if PROXY_DEBUG - if (!ok) - printf("not ok\n"); -#endif + if (ippr_ftp_debug > 2) { + if (!ok) + printf("%s ok\n", "not"); + } if (!mlen) { if (t->ftps_seq[0] + ackoff != thack) { -#if !defined(_KERNEL) || defined(IPF_FTP_DEBUG) - printf( - "ippr_ftp_process:seq[0](%x) + ackoff(%x) != thack(%x)\n", - t->ftps_seq[0], ackoff, thack); -#endif + if (ippr_ftp_debug > 1) { + printf("%s:seq[0](%x) + (%x) != (%x)\n", + "ippr_ftp_process", t->ftps_seq[0], + ackoff, thack); + } return APR_ERR(1); } -#if PROXY_DEBUG - printf("f:seq[0] %x seq[1] %x\n", f->ftps_seq[0], f->ftps_seq[1]); -#endif + if (ippr_ftp_debug > 2) { + printf("ippr_ftp_process:f:seq[0] %x seq[1] %x\n", + f->ftps_seq[0], f->ftps_seq[1]); + } + if (tcp->th_flags & TH_FIN) { if (thseq == f->ftps_seq[1]) { f->ftps_seq[0] = f->ftps_seq[1] - seqoff; f->ftps_seq[1] = thseq + 1 - seqoff; } else { -#if PROXY_DEBUG || !defined(_KERNEL) || defined(IPF_FTP_DEBUG) - printf("FIN: thseq %x seqoff %d ftps_seq %x\n", - thseq, seqoff, f->ftps_seq[0]); -#endif + if (ippr_ftp_debug > 1) { + printf("FIN: thseq %x seqoff %d ftps_seq %x\n", + thseq, seqoff, f->ftps_seq[0]); + } return APR_ERR(1); } } @@ -1105,15 +1168,15 @@ int rv; if (ok == 0) { inc = thseq - f->ftps_seq[0]; -#if PROXY_DEBUG || !defined(_KERNEL) - printf("inc %d sel %d rv %d\n", inc, sel, rv); - printf("th_seq %x ftps_seq %x/%x\n", thseq, f->ftps_seq[0], - f->ftps_seq[1]); - printf("ackmin %x ackoff %d\n", aps->aps_ackmin[sel], - aps->aps_ackoff[sel]); - printf("seqmin %x seqoff %d\n", aps->aps_seqmin[sel], - aps->aps_seqoff[sel]); -#endif + if (ippr_ftp_debug > 1) { + printf("inc %d sel %d rv %d\n", inc, sel, rv); + printf("th_seq %x ftps_seq %x/%x\n", + thseq, f->ftps_seq[0], f->ftps_seq[1]); + printf("ackmin %x ackoff %d\n", aps->aps_ackmin[sel], + aps->aps_ackoff[sel]); + printf("seqmin %x seqoff %d\n", aps->aps_seqmin[sel], + aps->aps_seqoff[sel]); + } return APR_ERR(1); } @@ -1126,22 +1189,62 @@ int rv; f->ftps_len = mlen; while (mlen > 0) { - len = MIN(mlen, FTP_BUFSZ / 2); + len = MIN(mlen, sizeof(f->ftps_buf) - (wptr - rptr)); COPYDATA(m, off, len, wptr); mlen -= len; off += len; wptr += len; + + if (ippr_ftp_debug > 3) + printf("%s:len %d/%d off %d wptr %lx junk %d [%*s]\n", + "ippr_ftp_process", + len, mlen, off, (u_long)wptr, f->ftps_junk, + len, rptr); + f->ftps_wptr = wptr; - if (f->ftps_junk == 2) + if (f->ftps_junk != 0) { + i = f->ftps_junk; f->ftps_junk = ippr_ftp_valid(ftp, rv, rptr, wptr - rptr); + if (ippr_ftp_debug > 5) + printf("%s:junk %d -> %d\n", + "ippr_ftp_process", i, f->ftps_junk); + + if (f->ftps_junk != 0) { + if (wptr - rptr == sizeof(f->ftps_buf)) { + if (ippr_ftp_debug > 4) + printf("%s:full buffer\n", + "ippr_ftp_process"); + f->ftps_rptr = f->ftps_buf; + f->ftps_wptr = f->ftps_buf; + rptr = f->ftps_rptr; + wptr = f->ftps_wptr; + /* + * Because we throw away data here that + * we would otherwise parse, set the + * junk flag to indicate just ignore + * any data upto the next CRLF. + */ + f->ftps_junk = 1; + continue; + } + } + } + while ((f->ftps_junk == 0) && (wptr > rptr)) { - f->ftps_junk = ippr_ftp_valid(ftp, rv, rptr, - wptr - rptr); + len = wptr - rptr; + f->ftps_junk = ippr_ftp_valid(ftp, rv, rptr, len); + + if (ippr_ftp_debug > 3) { + printf("%s=%d len %d rv %d ptr %lx/%lx ", + "ippr_ftp_valid", + f->ftps_junk, len, rv, (u_long)rptr, + (u_long)wptr); + printf("buf [%*s]\n", len, rptr); + } + if (f->ftps_junk == 0) { - f->ftps_cmds++; - len = wptr - rptr; f->ftps_rptr = rptr; if (rv) inc += ippr_ftp_server(fin, ip, nat, @@ -1160,57 +1263,56 @@ int rv; */ if ((f->ftps_cmds == 0) && (f->ftps_junk == 1)) { /* f->ftps_seq[1] += inc; */ -#if !defined(_KERNEL) || defined(IPF_FTP_DEBUG) - printf("ippr_ftp_process:cmds == 0 junk == 1\n"); -#endif + + if (ippr_ftp_debug > 1) + printf("%s:cmds == 0 junk == 1\n", + "ippr_ftp_process"); return APR_ERR(2); } - while ((f->ftps_junk == 1) && (rptr < wptr)) { - while ((rptr < wptr) && (*rptr != '\r')) - rptr++; - - if (*rptr == '\r') { - if (rptr + 1 < wptr) { - if (*(rptr + 1) == '\n') { - rptr += 2; - f->ftps_junk = 0; - } else - rptr++; - } else + if ((f->ftps_junk != 0) && (rptr < wptr)) { + for (s = rptr; s < wptr; s++) { + if ((*s == '\r') && (s + 1 < wptr) && + (*(s + 1) == '\n')) { + rptr = s + 2; + f->ftps_junk = 0; break; + } } } - f->ftps_rptr = rptr; if (rptr == wptr) { rptr = wptr = f->ftps_buf; } else { - if ((wptr > f->ftps_buf + FTP_BUFSZ / 2)) { - i = wptr - rptr; - if ((rptr == f->ftps_buf) || - (wptr - rptr > FTP_BUFSZ / 2)) { - f->ftps_junk = 1; - rptr = wptr = f->ftps_buf; - } else { - bcopy(rptr, f->ftps_buf, i); - wptr = f->ftps_buf + i; - rptr = f->ftps_buf; - } + /* + * Compact the buffer back to the start. The junk + * flag should already be set and because we're not + * throwing away any data, it is preserved from its + * current state. + */ + if (rptr > f->ftps_buf) { + bcopy(rptr, f->ftps_buf, len); + wptr -= rptr - f->ftps_buf; + rptr = f->ftps_buf; } - f->ftps_rptr = rptr; - f->ftps_wptr = wptr; } + f->ftps_rptr = rptr; + f->ftps_wptr = wptr; } /* f->ftps_seq[1] += inc; */ if (tcp->th_flags & TH_FIN) f->ftps_seq[1]++; -#if PROXY_DEBUG - mlen = MSGDSIZE(m); - mlen -= off; - printf("ftps_seq[1] = %x inc %d len %d\n", f->ftps_seq[1], inc, mlen); + if (ippr_ftp_debug > 3) { +#ifdef __sgi + mlen = fin->fin_plen; +#else + mlen = MSGDSIZE(m); #endif + mlen -= off; + printf("ftps_seq[1] = %x inc %d len %d\n", + f->ftps_seq[1], inc, mlen); + } f->ftps_rptr = rptr; f->ftps_wptr = wptr; @@ -1270,7 +1372,7 @@ char **ptr; register char *s = *ptr, c; register u_char i = 0, j = 0; - while (((c = *s++) != '\0') && isdigit(c)) { + while (((c = *s++) != '\0') && ISDIGIT(c)) { i *= 10; i += c - '0'; } @@ -1278,7 +1380,7 @@ char **ptr; *ptr = NULL; return 0; } - while (((c = *s++) != '\0') && isdigit(c)) { + while (((c = *s++) != '\0') && ISDIGIT(c)) { j *= 10; j += c - '0'; } @@ -1314,14 +1416,14 @@ int dlen; * Skip the EPSV command + space */ s = f->ftps_rptr + 33; - while (*s && !isdigit(*s)) + while (*s && !ISDIGIT(*s)) s++; /* * As per RFC 2428, there are no addres components in the EPSV * response. So we'll go straight to getting the port. */ - while (*s && isdigit(*s)) { + while (*s && ISDIGIT(*s)) { ap *= 10; ap += *s++ - '0'; } @@ -1343,9 +1445,9 @@ int dlen; } else return 0; -#if defined(__hpux) && defined(_KERNEL) - (void) sprintf(newbuf, sizeof(newbuf), "%s (|||%u|)\r\n", - "229 Entering Extended Passive Mode", ap); +#if defined(SNPRINTF) && defined(_KERNEL) + (void) SNPRINTF(newbuf, sizeof(newbuf), "%s (|||%u|)\r\n", + "229 Entering Extended Passive Mode", ap); #else (void) sprintf(newbuf, "%s (|||%u|)\r\n", "229 Entering Extended Passive Mode", ap); @@ -1354,36 +1456,3 @@ int dlen; return ippr_ftp_pasvreply(fin, ip, nat, f, (u_int)ap, newbuf, s, ip->ip_src.s_addr); } - - -#if 0 -ippr_ftp_parse(str, len) -{ - char *s, c; - - if (len < 5) - return -1; - s = str; - if (*s++ != '|') - return -1; - c = *s++; - if (c != '|') { - if (*s++ != '|') - return -1; - } else - c = '1'; - - if (c == '1') { - /* - * IPv4 dotted quad. - */ - return 0; - } else if (c == '2') { - /* - * IPv6 hex string - */ - return 0; - } - return -1; -} -#endif diff --git a/usr/src/common/ipf/ip_h323_pxy.c b/usr/src/uts/common/inet/ipf/netinet/ip_h323_pxy.c index 2a2e1738f4..7fc62276c5 100644 --- a/usr/src/common/ipf/ip_h323_pxy.c +++ b/usr/src/uts/common/inet/ipf/netinet/ip_h323_pxy.c @@ -1,6 +1,6 @@ /* * Copyright 2001, QNX Software Systems Ltd. All Rights Reserved - * + * * This source code has been published by QNX Software Systems Ltd. (QSSL). * However, any use, reproduction, modification, distribution or transfer of * this software, or any software which includes or is based upon any of this @@ -14,7 +14,7 @@ /* * Simple H.323 proxy - * + * * by xtang@canada.com * ported to ipfilter 3.4.20 by Michael Grant mg-ipf@grant.org */ @@ -23,7 +23,9 @@ # include <sys/fcntl.h> # include <sys/filio.h> #else -# include <sys/ioctl.h> +# ifndef linux +# include <sys/ioctl.h> +# endif #endif #define IPF_H323_PROXY @@ -40,9 +42,6 @@ int ippr_h245_out __P((fr_info_t *, ap_session_t *, nat_t *)); int ippr_h245_in __P((fr_info_t *, ap_session_t *, nat_t *)); static frentry_t h323_fr; -#ifdef USE_MUTEXES -extern ipfrwlock_t ipf_nat; -#endif int h323_proxy_init = 0; @@ -126,10 +125,10 @@ ap_session_t *aps; if (aps->aps_data) { for (i = 0, ipn = aps->aps_data; - i < (aps->aps_psiz / sizeof(ipnat_t)); + i < (aps->aps_psiz / sizeof(ipnat_t)); i++, ipn = (ipnat_t *)((char *)ipn + sizeof(*ipn))) { - /* + /* * Check the comment in ippr_h323_in() function, * just above fr_nat_ioctl() call. * We are lucky here because this function is not @@ -186,13 +185,13 @@ nat_t *nat; ipn->in_inip = nat->nat_inip.s_addr; ipn->in_inmsk = 0xffffffff; ipn->in_dport = htons(port); - /* + /* * we got a problem here. we need to call fr_nat_ioctl() to add * the h245 proxy rule, but since we already hold (READ locked) * the nat table rwlock (ipf_nat), if we go into fr_nat_ioctl(), * it will try to WRITE lock it. This will causing dead lock * on RTP. - * + * * The quick & dirty solution here is release the read lock, * call fr_nat_ioctl() and re-lock it. * A (maybe better) solution is do a UPGRADE(), and instead @@ -247,7 +246,7 @@ nat_t *nat; tcp = (tcphdr_t *)fin->fin_dp; ipaddr = nat->nat_inip.s_addr; data = (caddr_t)tcp + (TCP_OFF(tcp) << 2); - datlen = ip->ip_len - fin->fin_hlen - (TCP_OFF(tcp) << 2); + datlen = fin->fin_dlen - (TCP_OFF(tcp) << 2); if (find_port(ipaddr, data, datlen, &off, &port) == 0) { fr_info_t fi; nat_t *nat2; diff --git a/usr/src/common/ipf/ip_htable.h b/usr/src/uts/common/inet/ipf/netinet/ip_htable.h index 269688ce68..082959a9c5 100644 --- a/usr/src/common/ipf/ip_htable.h +++ b/usr/src/uts/common/inet/ipf/netinet/ip_htable.h @@ -3,7 +3,7 @@ * * See the IPFILTER.LICENCE file for details on licencing. * - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -12,11 +12,7 @@ #ifndef __IP_HTABLE_H__ #define __IP_HTABLE_H__ -#if SOLARIS2 >= 10 -#include "ip_lookup.h" -#else #include "netinet/ip_lookup.h" -#endif typedef struct iphtent_s { struct iphtent_s *ipe_next, **ipe_pnext; diff --git a/usr/src/common/ipf/ip_ipsec_pxy.c b/usr/src/uts/common/inet/ipf/netinet/ip_ipsec_pxy.c index dd9298d7f4..aa7e1afd4d 100644 --- a/usr/src/common/ipf/ip_ipsec_pxy.c +++ b/usr/src/uts/common/inet/ipf/netinet/ip_ipsec_pxy.c @@ -3,13 +3,13 @@ * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: ip_ipsec_pxy.c,v 2.16 2003/06/25 12:08:21 darrenr Exp $ - * - * Copyright 2003 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - * * Simple ISAKMP transparent proxy for in-kernel use. For use with the NAT * code. + * + * $Id: ip_ipsec_pxy.c,v 2.20.2.7 2005/07/15 21:56:50 darrenr Exp $ + * + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. */ #pragma ident "%Z%%M% %I% %E% SMI" @@ -21,7 +21,7 @@ int ippr_ipsec_init __P((void)); void ippr_ipsec_fini __P((void)); int ippr_ipsec_new __P((fr_info_t *, ap_session_t *, nat_t *)); void ippr_ipsec_del __P((ap_session_t *)); -int ippr_ipsec_out __P((fr_info_t *, ap_session_t *, nat_t *)); +int ippr_ipsec_inout __P((fr_info_t *, ap_session_t *, nat_t *)); int ippr_ipsec_match __P((fr_info_t *, ap_session_t *, nat_t *)); static frentry_t ipsecfr; @@ -30,6 +30,7 @@ static ipftq_t *ipsecstatetqe; static char ipsec_buffer[1500]; int ipsec_proxy_init = 0; +int ipsec_proxy_ttl = 60; /* * IPSec application proxy initialization. @@ -42,28 +43,37 @@ int ippr_ipsec_init() MUTEX_INIT(&ipsecfr.fr_lock, "IPsec proxy rule lock"); ipsec_proxy_init = 1; - ipsecnattqe = fr_addtimeoutqueue(&nat_utqe, 60); + ipsecnattqe = fr_addtimeoutqueue(&nat_utqe, ipsec_proxy_ttl); if (ipsecnattqe == NULL) return -1; - ipsecstatetqe = fr_addtimeoutqueue(&ips_utqe, 60); + ipsecstatetqe = fr_addtimeoutqueue(&ips_utqe, ipsec_proxy_ttl); if (ipsecstatetqe == NULL) { - fr_deletetimeoutqueue(ipsecnattqe); + if (fr_deletetimeoutqueue(ipsecnattqe) == 0) + fr_freetimeoutqueue(ipsecnattqe); ipsecnattqe = NULL; return -1; } - ipsecfr.fr_age[0] = 60; - ipsecfr.fr_age[1] = 60; + + ipsecnattqe->ifq_flags |= IFQF_PROXY; + ipsecstatetqe->ifq_flags |= IFQF_PROXY; + + ipsecfr.fr_age[0] = ipsec_proxy_ttl; + ipsecfr.fr_age[1] = ipsec_proxy_ttl; return 0; } void ippr_ipsec_fini() { - if (ipsecnattqe != NULL) - fr_deletetimeoutqueue(ipsecnattqe); + if (ipsecnattqe != NULL) { + if (fr_deletetimeoutqueue(ipsecnattqe) == 0) + fr_freetimeoutqueue(ipsecnattqe); + } ipsecnattqe = NULL; - if (ipsecstatetqe != NULL) - fr_deletetimeoutqueue(ipsecstatetqe); + if (ipsecstatetqe != NULL) { + if (fr_deletetimeoutqueue(ipsecstatetqe) == 0) + fr_freetimeoutqueue(ipsecstatetqe); + } ipsecstatetqe = NULL; if (ipsec_proxy_init == 1) { @@ -85,12 +95,12 @@ nat_t *nat; fr_info_t fi; ipnat_t *ipn; char *ptr; - int p, off, dlen; + int p, off, dlen, ttl; mb_t *m; ip_t *ip; + off = fin->fin_plen - fin->fin_dlen + fin->fin_ipoff; bzero(ipsec_buffer, sizeof(ipsec_buffer)); - off = fin->fin_hlen + sizeof(udphdr_t); ip = fin->fin_ip; m = fin->fin_m; @@ -117,13 +127,14 @@ nat_t *nat; * describe ESP but UDP instead. */ ipn = &ipsec->ipsc_rule; - ipn->in_tqehead[0] = ipsecnattqe; - ipn->in_tqehead[1] = ipsecnattqe; + ttl = IPF_TTLVAL(ipsecnattqe->ifq_ttl); + ipn->in_tqehead[0] = fr_addtimeoutqueue(&nat_utqe, ttl); + ipn->in_tqehead[1] = fr_addtimeoutqueue(&nat_utqe, ttl); ipn->in_ifps[0] = fin->fin_ifp; ipn->in_apr = NULL; ipn->in_use = 1; ipn->in_hits = 1; - ipn->in_nip = nat->nat_outip.s_addr; + ipn->in_nip = ntohl(nat->nat_outip.s_addr); ipn->in_ippip = 1; ipn->in_inip = nat->nat_inip.s_addr; ipn->in_inmsk = 0xffffffff; @@ -137,13 +148,15 @@ nat_t *nat; ipn->in_p = IPPROTO_ESP; bcopy((char *)fin, (char *)&fi, sizeof(fi)); + fi.fin_state = NULL; + fi.fin_nat = NULL; fi.fin_fi.fi_p = IPPROTO_ESP; fi.fin_fr = &ipsecfr; fi.fin_data[0] = 0; fi.fin_data[1] = 0; p = ip->ip_p; ip->ip_p = IPPROTO_ESP; - fi.fin_flx &= ~FI_TCPUDP; + fi.fin_flx &= ~(FI_TCPUDP|FI_STATE|FI_FRAG); fi.fin_flx |= FI_IGNORE; ptr = ipsec_buffer; @@ -168,6 +181,8 @@ nat_t *nat; fi.fin_data[1] = 0; ipsec->ipsc_state = fr_addstate(&fi, &ipsec->ipsc_state, SI_WILDP); + if (fi.fin_state != NULL) + fr_statederef(&fi, (ipstate_t **)&fi.fin_state); } ip->ip_p = p & 0xff; return 0; @@ -178,7 +193,7 @@ nat_t *nat; * For outgoing IKE packets. refresh timeouts for NAT & state entries, if * we can. If they have disappeared, recreate them. */ -int ippr_ipsec_out(fin, aps, nat) +int ippr_ipsec_inout(fin, aps, nat) fr_info_t *fin; ap_session_t *aps; nat_t *nat; @@ -188,19 +203,31 @@ nat_t *nat; ip_t *ip; int p; - ip = fin->fin_ip; - bcopy((char *)fin, (char *)&fi, sizeof(fi)); - fi.fin_fi.fi_p = IPPROTO_ESP; - fi.fin_fr = &ipsecfr; - fi.fin_data[0] = 0; - fi.fin_data[1] = 0; - p = ip->ip_p; - ip->ip_p = IPPROTO_ESP; - fi.fin_flx &= ~FI_TCPUDP; - fi.fin_flx |= FI_IGNORE; + if ((fin->fin_out == 1) && (nat->nat_dir == NAT_INBOUND)) + return 0; + + if ((fin->fin_out == 0) && (nat->nat_dir == NAT_OUTBOUND)) + return 0; ipsec = aps->aps_data; + if (ipsec != NULL) { + ip = fin->fin_ip; + p = ip->ip_p; + + if ((ipsec->ipsc_nat == NULL) || (ipsec->ipsc_state == NULL)) { + bcopy((char *)fin, (char *)&fi, sizeof(fi)); + fi.fin_state = NULL; + fi.fin_nat = NULL; + fi.fin_fi.fi_p = IPPROTO_ESP; + fi.fin_fr = &ipsecfr; + fi.fin_data[0] = 0; + fi.fin_data[1] = 0; + ip->ip_p = IPPROTO_ESP; + fi.fin_flx &= ~(FI_TCPUDP|FI_STATE|FI_FRAG); + fi.fin_flx |= FI_IGNORE; + } + /* * Update NAT timeout/create NAT if missing. */ @@ -210,7 +237,7 @@ nat_t *nat; ipsec->ipsc_nat = nat_new(&fi, &ipsec->ipsc_rule, &ipsec->ipsc_nat, NAT_SLAVE|SI_WILDP, - NAT_OUTBOUND); + nat->nat_dir); if (ipsec->ipsc_nat != NULL) { (void) nat_proto(&fi, ipsec->ipsc_nat, 0); nat_update(&fi, ipsec->ipsc_nat, @@ -233,9 +260,11 @@ nat_t *nat; ipsec->ipsc_state = fr_addstate(&fi, &ipsec->ipsc_state, SI_WILDP); + if (fi.fin_state != NULL) + fr_statederef(&fi, (ipstate_t **)&fi.fin_state); } + ip->ip_p = p; } - ip->ip_p = p & 0xff; return 0; } @@ -261,8 +290,8 @@ nat_t *nat; if ((fin->fin_dlen < sizeof(cookies)) || (fin->fin_flx & FI_FRAG)) return -1; + off = fin->fin_plen - fin->fin_dlen + fin->fin_ipoff; ipsec = aps->aps_data; - off = fin->fin_hlen + sizeof(udphdr_t); m = fin->fin_m; COPYDATA(m, off, sizeof(cookies), (char *)cookies); @@ -299,18 +328,14 @@ ap_session_t *aps; if (ipsec != NULL) { /* - * Don't delete it from here, just schedule it to be - * deleted ASAP. + * Don't bother changing any of the NAT structure details, + * *_del() is on a callback from aps_free(), from nat_delete() */ - if (ipsec->ipsc_nat != NULL) { - ipsec->ipsc_nat->nat_age = fr_ticks + 1; - ipsec->ipsc_nat->nat_ptr = NULL; - fr_queuefront(&ipsec->ipsc_nat->nat_tqe); - } READ_ENTER(&ipf_state); if (ipsec->ipsc_state != NULL) { ipsec->ipsc_state->is_die = fr_ticks + 1; + ipsec->ipsc_state->is_me = NULL; fr_queuefront(&ipsec->ipsc_state->is_sti); } RWLOCK_EXIT(&ipf_state); diff --git a/usr/src/common/ipf/ip_irc_pxy.c b/usr/src/uts/common/inet/ipf/netinet/ip_irc_pxy.c index 95d3d64fc2..4b7a139048 100644 --- a/usr/src/common/ipf/ip_irc_pxy.c +++ b/usr/src/uts/common/inet/ipf/netinet/ip_irc_pxy.c @@ -3,21 +3,14 @@ * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: ip_irc_pxy.c,v 2.30 2003/06/28 17:01:57 darrenr Exp $ + * $Id: ip_irc_pxy.c,v 2.39.2.4 2005/02/04 10:22:55 darrenr Exp $ * - * Copyright 2003 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. - * - * Simple FTP transparent proxy for in-kernel use. For use with the NAT - * code. */ #pragma ident "%Z%%M% %I% %E% SMI" -#ifdef USE_MUTEXES -extern ipfmutex_t ipf_rw; -#endif - #define IPF_IRC_PROXY #define IPF_IRCBUFSZ 96 /* This *MUST* be >= 64! */ @@ -105,10 +98,10 @@ size_t len; s++; c = *s; ircp->irc_snick = s; - if (!isalpha(c)) + if (!ISALPHA(c)) return 0; i--; - for (c = *s; !isspace(c) && (i > 0); i--) + for (c = *s; !ISSPACE(c) && (i > 0); i--) c = *s++; if (i < 31) return 0; @@ -130,9 +123,9 @@ size_t len; /* * Loosely check that the destination is a nickname of some sort */ - if (!isalpha(c)) + if (!ISALPHA(c)) return 0; - for (; !isspace(c) && (i > 0); i--) + for (; !ISSPACE(c) && (i > 0); i--) c = *s++; if (i < 20) return 0; @@ -176,7 +169,7 @@ size_t len; * Check for the arg */ c = *s; - if (isspace(c)) + if (ISSPACE(c)) return 0; ircp->irc_arg = s; for (; (c != ' ') && (c != '\001') && (i > 0); i--) @@ -191,13 +184,13 @@ size_t len; s++; i--; c = *s; - if (!isdigit(c)) + if (!ISDIGIT(c)) return 0; ircp->irc_addr = s; /* * Get the IP# */ - for (l = 0; isdigit(c) && (i > 0); i--) { + for (l = 0; ISDIGIT(c) && (i > 0); i--) { l *= 10; l += c - '0'; c = *s++; @@ -213,12 +206,12 @@ size_t len; s++; i--; c = *s; - if (!isdigit(c)) + if (!ISDIGIT(c)) return 0; /* * Get the port# */ - for (l = 0; isdigit(c) && (i > 0); i--) { + for (l = 0; ISDIGIT(c) && (i > 0); i--) { l *= 10; l += c - '0'; c = *s++; @@ -276,13 +269,17 @@ nat_t *nat; mb_t *m1; #endif + m = fin->fin_m; ip = fin->fin_ip; tcp = (tcphdr_t *)fin->fin_dp; bzero(ctcpbuf, sizeof(ctcpbuf)); - m = fin->fin_m; - off = (char *)tcp - MTOD(m, char *) + (TCP_OFF(tcp) << 2); + off = (char *)tcp - (char *)ip + (TCP_OFF(tcp) << 2) + fin->fin_ipoff; +#ifdef __sgi + dlen = fin->fin_plen - off; +#else dlen = MSGDSIZE(m) - off; +#endif if (dlen <= 0) return 0; COPYDATA(m, off, MIN(sizeof(ctcpbuf), dlen), ctcpbuf); @@ -314,8 +311,8 @@ nat_t *nat; i++; (void) strncpy(newbuf, ctcpbuf, i); /* DO NOT change these! */ -#if defined(__hpux) && defined(KERNEL) - (void) sprintf(newbuf, sizeof(newbuf) - i, "%u %u\001\r\n", a1, a5); +#if defined(SNPRINTF) && defined(KERNEL) + (void) SNPRINTF(newbuf, sizeof(newbuf) - i, "%u %u\001\r\n", a1, a5); #else (void) sprintf(newbuf, "%u %u\001\r\n", a1, a5); #endif @@ -405,6 +402,8 @@ nat_t *nat; tcp2->th_win = htons(8192); tcp2->th_sport = sp; tcp2->th_dport = 0; /* XXX - don't specify remote port */ + fi.fin_state = NULL; + fi.fin_nat = NULL; fi.fin_data[0] = ntohs(sp); fi.fin_data[1] = 0; fi.fin_dp = (char *)tcp2; @@ -420,6 +419,8 @@ nat_t *nat; nat_update(&fi, nat2, nat2->nat_ptr); (void) fr_addstate(&fi, NULL, SI_W_DPORT); + if (fi.fin_state != NULL) + fr_statederef(&fi, (ipstate_t **)&fi.fin_state); } ip->ip_src = swip; } diff --git a/usr/src/common/ipf/ip_lookup.h b/usr/src/uts/common/inet/ipf/netinet/ip_lookup.h index 355658d234..76cdd8fd0a 100644 --- a/usr/src/common/ipf/ip_lookup.h +++ b/usr/src/uts/common/inet/ipf/netinet/ip_lookup.h @@ -1,21 +1,31 @@ +/* + * Copyright (C) 1993-2005 by Darren Reed. + * See the IPFILTER.LICENCE file for details on licencing. + */ #ifndef __IP_LOOKUP_H__ #define __IP_LOOKUP_H__ -#if defined(__STDC__) || defined(__GNUC__) +#if defined(__STDC__) || defined(__GNUC__) || defined(_AIX51) # define SIOCLOOKUPADDTABLE _IOWR('r', 60, struct iplookupop) # define SIOCLOOKUPDELTABLE _IOWR('r', 61, struct iplookupop) -# define SIOCLOOKUPSTAT _IOR('r', 64, struct iplookupop) +# define SIOCLOOKUPSTAT _IOWR('r', 64, struct iplookupop) +# define SIOCLOOKUPSTATW _IOW('r', 64, struct iplookupop) # define SIOCLOOKUPFLUSH _IOWR('r', 65, struct iplookupflush) -# define SIOCLOOKUPADDNODE _IOW('r', 67, struct iplookupop) -# define SIOCLOOKUPDELNODE _IOW('r', 68, struct iplookupop) +# define SIOCLOOKUPADDNODE _IOWR('r', 67, struct iplookupop) +# define SIOCLOOKUPADDNODEW _IOW('r', 67, struct iplookupop) +# define SIOCLOOKUPDELNODE _IOWR('r', 68, struct iplookupop) +# define SIOCLOOKUPDELNODEW _IOW('r', 68, struct iplookupop) #else # define SIOCLOOKUPADDTABLE _IOWR(r, 60, struct iplookupop) # define SIOCLOOKUPDELTABLE _IOWR(r, 61, struct iplookupop) -# define SIOCLOOKUPSTAT _IOR(r, 64, struct iplookupop) +# define SIOCLOOKUPSTAT _IOWR(r, 64, struct iplookupop) +# define SIOCLOOKUPSTATW _IOW(r, 64, struct iplookupop) # define SIOCLOOKUPFLUSH _IOWR(r, 65, struct iplookupflush) -# define SIOCLOOKUPADDNODE _IOW(r, 67, struct iplookupop) -# define SIOCLOOKUPDELNODE _IOW(r, 68, struct iplookupop) +# define SIOCLOOKUPADDNODE _IOWR(r, 67, struct iplookupop) +# define SIOCLOOKUPADDNODEW _IOW(r, 67, struct iplookupop) +# define SIOCLOOKUPDELNODE _IOWR(r, 68, struct iplookupop) +# define SIOCLOOKUPDELNODEW _IOW(r, 68, struct iplookupop) #endif typedef struct iplookupop { @@ -50,12 +60,8 @@ typedef struct iplookuplink { #define IPLT_ANON 0x80000000 extern int ip_lookup_init __P((void)); +extern int ip_lookup_ioctl __P((caddr_t, ioctlcmd_t, int)); extern void ip_lookup_unload __P((void)); extern void ip_lookup_deref __P((int, void *)); -#if defined(__NetBSD__) || defined(__OpenBSD__) -extern int ip_lookup_ioctl __P((caddr_t, u_long, int)); -#else -extern int ip_lookup_ioctl __P((caddr_t, int, int)); -#endif #endif /* __IP_LOOKUP_H__ */ diff --git a/usr/src/common/ipf/ip_nat.h b/usr/src/uts/common/inet/ipf/netinet/ip_nat.h index a27ac35783..930e8aa103 100644 --- a/usr/src/common/ipf/ip_nat.h +++ b/usr/src/uts/common/inet/ipf/netinet/ip_nat.h @@ -1,12 +1,12 @@ /* - * Copyright (C) 1995-2001 by Darren Reed. + * Copyright (C) 1995-2001, 2003 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * * @(#)ip_nat.h 1.5 2/4/96 - * $Id: ip_nat.h,v 2.83 2003/08/14 15:22:58 darrenr Exp $ - * - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * $Id: ip_nat.h,v 2.90.2.11 2005/06/18 02:41:32 darrenr Exp $ +* + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #pragma ident "%Z%%M% %I% %E% SMI" @@ -18,18 +18,16 @@ #define SOLARIS (defined(sun) && (defined(__svr4__) || defined(__SVR4))) #endif -#if defined(__STDC__) || defined(__GNUC__) +#if defined(__STDC__) || defined(__GNUC__) || defined(_AIX51) #define SIOCADNAT _IOW('r', 60, struct ipfobj) #define SIOCRMNAT _IOW('r', 61, struct ipfobj) #define SIOCGNATS _IOWR('r', 62, struct ipfobj) #define SIOCGNATL _IOWR('r', 63, struct ipfobj) -#define SIOCPROXY _IOWR('r', 64, struct ap_control) #else #define SIOCADNAT _IOW(r, 60, struct ipfobj) #define SIOCRMNAT _IOW(r, 61, struct ipfobj) #define SIOCGNATS _IOWR(r, 62, struct ipfobj) #define SIOCGNATL _IOWR(r, 63, struct ipfobj) -#define SIOCPROXY _IOWR(r, 64, struct ap_control) #endif #undef LARGE_NAT /* define this if you're setting up a system to NAT @@ -55,16 +53,27 @@ #endif #ifndef HOSTMAP_SIZE # ifdef LARGE_NAT +# define HOSTMAP_SIZE 8191 +# else # define HOSTMAP_SIZE 2047 +# endif +#endif +#ifndef NAT_TABLE_MAX +/* + * This is newly introduced and for the sake of "least surprise", the numbers + * present aren't what we'd normally use for creating a proper hash table. + */ +# ifdef LARGE_NAT +# define NAT_TABLE_MAX 180000 # else -# define HOSTMAP_SIZE 8191 +# define NAT_TABLE_MAX 30000 # endif #endif #ifndef NAT_TABLE_SZ # ifdef LARGE_NAT -# define NAT_TABLE_SZ 2047 -# else # define NAT_TABLE_SZ 16383 +# else +# define NAT_TABLE_SZ 2047 # endif #endif #ifndef APR_LABELLEN @@ -115,6 +124,7 @@ typedef struct nat { int nat_ref; /* reference count */ int nat_hv[2]; char nat_ifnames[2][LIFNAMSIZ]; + int nat_rev; /* 0 = forward, 1 = reverse */ } nat_t; #define nat_inip nat_inip6.in4 @@ -127,7 +137,6 @@ typedef struct nat { #define nat_seq nat_un.nat_uni.ici_seq #define nat_id nat_un.nat_uni.ici_id #define nat_tcpstate nat_tqe.tqe_state -#define nat_gre nat_un.nat_ugre /* * Values for nat_dir @@ -148,6 +157,7 @@ typedef struct nat { #define NAT_TCPUDP (NAT_TCP|NAT_UDP) #define NAT_TCPUDPICMP (NAT_TCP|NAT_UDP|NAT_ICMPERR) +#define NAT_TCPUDPICMPQ (NAT_TCP|NAT_UDP|NAT_ICMPQUERY) #define NAT_FROMRULE (NAT_TCP|NAT_UDP) /* 0x0100 reserved for FI_W_SPORT */ @@ -178,7 +188,8 @@ typedef struct ipnat { u_int in_hv; int in_flineno; /* conf. file line number */ u_short in_pnext; - u_char in_xxx1[2]; + u_char in_v; + u_char in_xxx; /* From here to the end is covered by IPN_CMPSIZ */ u_32_t in_flags; u_32_t in_mssclamp; /* if != 0 clamp MSS to this */ @@ -224,6 +235,7 @@ typedef struct ipnat { #define IPN_ICMPERR 0x00004 #define IPN_TCPUDPICMP (IPN_TCP|IPN_UDP|IPN_ICMPERR) #define IPN_ICMPQUERY 0x00008 +#define IPN_TCPUDPICMPQ (IPN_TCP|IPN_UDP|IPN_ICMPQUERY) #define IPN_RF (IPN_TCPUDP|IPN_DELETE|IPN_ICMPERR) #define IPN_AUTOPORTMAP 0x00010 #define IPN_IPRANGE 0x00020 @@ -237,10 +249,12 @@ typedef struct ipnat { #define IPN_DELETE 0x40000 #define IPN_STICKY 0x80000 #define IPN_FRAG 0x100000 +#define IPN_FIXEDDPORT 0x200000 #define IPN_FINDFORWARD 0x400000 +#define IPN_IN 0x800000 #define IPN_USERFLAGS (IPN_TCPUDP|IPN_AUTOPORTMAP|IPN_IPRANGE|IPN_SPLIT|\ IPN_ROUNDR|IPN_FILTER|IPN_NOTSRC|IPN_NOTDST|\ - IPN_FRAG|IPN_STICKY) + IPN_FRAG|IPN_STICKY|IPN_FIXEDDPORT|IPN_ICMPQUERY) /* * Values for in_redir @@ -283,6 +297,7 @@ typedef struct natget { } natget_t; +#undef tr_flags typedef struct nattrpnt { struct in_addr tr_dstip; /* real destination IP# */ struct in_addr tr_srcip; /* real source IP# */ @@ -353,6 +368,7 @@ typedef struct natstat { void *ns_apslist; u_int ns_wilds; u_int ns_nattab_sz; + u_int ns_nattab_max; u_int ns_rultab_sz; u_int ns_rdrtab_sz; u_int ns_trpntab_sz; @@ -405,6 +421,7 @@ typedef struct natlog { extern u_int ipf_nattable_sz; +extern u_int ipf_nattable_max; extern u_int ipf_natrules_sz; extern u_int ipf_rdrrules_sz; extern u_int ipf_hostmap_sz; @@ -414,6 +431,7 @@ extern int fr_nat_lock; extern void fr_natsync __P((void *)); extern u_long fr_defnatage; extern u_long fr_defnaticmpage; +extern u_long fr_defnatipage; /* nat_table[0] -> hashed list sorted by inside (ip, port) */ /* nat_table[1] -> hashed list sorted by outside (ip, port) */ extern nat_t **nat_table[2]; @@ -427,11 +445,7 @@ extern natstat_t nat_stats; #if defined(__OpenBSD__) extern void nat_ifdetach __P((void *)); #endif -#if defined(__NetBSD__) || defined(__OpenBSD__) || (__FreeBSD_version >= 300003) -extern int fr_nat_ioctl __P((caddr_t, u_long, int)); -#else -extern int fr_nat_ioctl __P((caddr_t, int, int)); -#endif +extern int fr_nat_ioctl __P((caddr_t, ioctlcmd_t, int)); extern int fr_natinit __P((void)); extern nat_t *nat_new __P((fr_info_t *, ipnat_t *, nat_t **, u_int, int)); extern nat_t *nat_outlookup __P((fr_info_t *, u_int, u_int, struct in_addr, @@ -445,7 +459,7 @@ extern nat_t *nat_maplookup __P((void *, u_int, struct in_addr, extern nat_t *nat_lookupredir __P((natlookup_t *)); extern nat_t *nat_icmperrorlookup __P((fr_info_t *, int)); extern nat_t *nat_icmperror __P((fr_info_t *, u_int *, int)); -extern int nat_insert __P((nat_t *)); +extern int nat_insert __P((nat_t *, int)); extern int fr_checknatout __P((fr_info_t *, u_32_t *)); extern int fr_natout __P((fr_info_t *, nat_t *, int, u_32_t)); diff --git a/usr/src/common/ipf/ip_netbios_pxy.c b/usr/src/uts/common/inet/ipf/netinet/ip_netbios_pxy.c index 70d40a2587..8bfa8fac47 100644 --- a/usr/src/common/ipf/ip_netbios_pxy.c +++ b/usr/src/uts/common/inet/ipf/netinet/ip_netbios_pxy.c @@ -1,7 +1,7 @@ /* * Simple netbios-dgm transparent proxy for in-kernel use. * For use with the NAT code. - * $Id: ip_netbios_pxy.c,v 2.7 2003/06/25 12:08:21 darrenr Exp $ + * $Id: ip_netbios_pxy.c,v 2.8.2.1 2005/07/15 21:56:51 darrenr Exp $ */ /*- @@ -29,7 +29,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: ip_netbios_pxy.c,v 2.7 2003/06/25 12:08:21 darrenr Exp $ + * $Id: ip_netbios_pxy.c,v 2.8.2.1 2005/07/15 21:56:51 darrenr Exp $ */ #define IPF_NETBIOS_PROXY @@ -80,25 +80,23 @@ nat_t *nat; aps = aps; /* LINT */ nat = nat; /* LINT */ - ip = fin->fin_ip; - m = *(mb_t **)fin->fin_mp; - off = fin->fin_hlen + sizeof(udphdr_t); - dlen = M_LEN(m); - dlen -= off; - + m = fin->fin_m; + dlen = fin->fin_dlen - sizeof(*udp); /* * no net bios datagram could possibly be shorter than this */ - if (dlen < 11) + if (dlen < 11) return 0; + ip = fin->fin_ip; udp = (udphdr_t *)fin->fin_dp; + off = (char *)udp - (char *)ip + sizeof(*udp) + fin->fin_ipoff; - /* + /* * move past the * ip header; * udp header; - * 4 bytes into the net bios dgm header. + * 4 bytes into the net bios dgm header. * According to rfc1002, this should be the exact location of * the source address/port */ diff --git a/usr/src/common/ipf/ip_pool.h b/usr/src/uts/common/inet/ipf/netinet/ip_pool.h index 1df2ea4675..b40ba2b0fb 100644 --- a/usr/src/common/ipf/ip_pool.h +++ b/usr/src/uts/common/inet/ipf/netinet/ip_pool.h @@ -1,11 +1,11 @@ /* - * Copyright (C) 1993-2001 by Darren Reed. + * Copyright (C) 1993-2001, 2003 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: ip_pool.h,v 2.19 2003/11/08 23:01:26 darrenr Exp $ + * $Id: ip_pool.h,v 2.26.2.3 2005/06/12 07:18:27 darrenr Exp $ * - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -14,17 +14,23 @@ #ifndef __IP_POOL_H__ #define __IP_POOL_H__ -#if defined(_KERNEL) && \ - !(defined(sun) && (defined(__svr4__) || defined(__SVR4))) +#if defined(_KERNEL) && !defined(__osf__) && !defined(__hpux) && \ + !defined(linux) && !defined(sun) && !defined(AIX) # include <net/radix.h> +extern void rn_freehead __P((struct radix_node_head *)); +# define FreeS(p, z) KFREES(p, z) +extern int max_keylen; #else -# include "radix.h" +# if defined(__osf__) || defined(__hpux) +# include "radix_ipf_local.h" +# define radix_mask ipf_radix_mask +# define radix_node ipf_radix_node +# define radix_node_head ipf_radix_node_head +# else +# include "radix_ipf.h" +# endif #endif -#if SOLARIS2 >= 10 -#include "ip_lookup.h" -#else #include "netinet/ip_lookup.h" -#endif #define IP_POOL_NOMATCH 0 #define IP_POOL_POSITIVE 1 @@ -57,6 +63,7 @@ typedef struct ip_pool_s { typedef struct ip_pool_stat { u_long ipls_pools; + u_long ipls_tables; u_long ipls_nodes; ip_pool_t *ipls_list[IPL_LOGSIZE]; } ip_pool_stat_t; @@ -77,7 +84,8 @@ extern void ip_pool_free __P((ip_pool_t *)); extern void ip_pool_deref __P((ip_pool_t *)); extern void *ip_pool_find __P((int, char *)); extern ip_pool_node_t *ip_pool_findeq __P((ip_pool_t *, - addrfamily_t *, addrfamily_t *)); + addrfamily_t *, addrfamily_t *)); +extern int ip_pool_flush __P((iplookupflush_t *)); extern int ip_pool_statistics __P((iplookupop_t *)); #endif /* __IP_POOL_H__ */ diff --git a/usr/src/uts/common/inet/ipf/netinet/ip_pptp_pxy.c b/usr/src/uts/common/inet/ipf/netinet/ip_pptp_pxy.c new file mode 100644 index 0000000000..480edf1a00 --- /dev/null +++ b/usr/src/uts/common/inet/ipf/netinet/ip_pptp_pxy.c @@ -0,0 +1,528 @@ +/* + * Copyright (C) 2002-2003 by Darren Reed + * + * Simple PPTP transparent proxy for in-kernel use. For use with the NAT + * code. + * + * $Id: ip_pptp_pxy.c,v 2.10.2.10 2005/07/15 21:56:52 darrenr Exp $ + * + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#define IPF_PPTP_PROXY + +typedef struct pptp_hdr { + u_short pptph_len; + u_short pptph_type; + u_32_t pptph_cookie; +} pptp_hdr_t; + +#define PPTP_MSGTYPE_CTL 1 +#define PPTP_MTCTL_STARTREQ 1 +#define PPTP_MTCTL_STARTREP 2 +#define PPTP_MTCTL_STOPREQ 3 +#define PPTP_MTCTL_STOPREP 4 +#define PPTP_MTCTL_ECHOREQ 5 +#define PPTP_MTCTL_ECHOREP 6 +#define PPTP_MTCTL_OUTREQ 7 +#define PPTP_MTCTL_OUTREP 8 +#define PPTP_MTCTL_INREQ 9 +#define PPTP_MTCTL_INREP 10 +#define PPTP_MTCTL_INCONNECT 11 +#define PPTP_MTCTL_CLEAR 12 +#define PPTP_MTCTL_DISCONNECT 13 +#define PPTP_MTCTL_WANERROR 14 +#define PPTP_MTCTL_LINKINFO 15 + + +int ippr_pptp_init __P((void)); +void ippr_pptp_fini __P((void)); +int ippr_pptp_new __P((fr_info_t *, ap_session_t *, nat_t *)); +void ippr_pptp_del __P((ap_session_t *)); +int ippr_pptp_inout __P((fr_info_t *, ap_session_t *, nat_t *)); +void ippr_pptp_donatstate __P((fr_info_t *, nat_t *, pptp_pxy_t *)); +int ippr_pptp_message __P((fr_info_t *, nat_t *, pptp_pxy_t *, pptp_side_t *)); +int ippr_pptp_nextmessage __P((fr_info_t *, nat_t *, pptp_pxy_t *, int)); +int ippr_pptp_mctl __P((fr_info_t *, nat_t *, pptp_pxy_t *, pptp_side_t *)); + +static frentry_t pptpfr; + +int pptp_proxy_init = 0; +int ippr_pptp_debug = 0; +int ippr_pptp_gretimeout = IPF_TTLVAL(120); /* 2 minutes */ + + +/* + * PPTP application proxy initialization. + */ +int ippr_pptp_init() +{ + bzero((char *)&pptpfr, sizeof(pptpfr)); + pptpfr.fr_ref = 1; + pptpfr.fr_age[0] = ippr_pptp_gretimeout; + pptpfr.fr_age[1] = ippr_pptp_gretimeout; + pptpfr.fr_flags = FR_OUTQUE|FR_PASS|FR_QUICK|FR_KEEPSTATE; + MUTEX_INIT(&pptpfr.fr_lock, "PPTP proxy rule lock"); + pptp_proxy_init = 1; + + return 0; +} + + +void ippr_pptp_fini() +{ + if (pptp_proxy_init == 1) { + MUTEX_DESTROY(&pptpfr.fr_lock); + pptp_proxy_init = 0; + } +} + + +/* + * Setup for a new PPTP proxy. + */ +int ippr_pptp_new(fin, aps, nat) +fr_info_t *fin; +ap_session_t *aps; +nat_t *nat; +{ + pptp_pxy_t *pptp; + ipnat_t *ipn; + ip_t *ip; + + ip = fin->fin_ip; + + if (nat_outlookup(fin, 0, IPPROTO_GRE, nat->nat_inip, + ip->ip_dst) != NULL) { + if (ippr_pptp_debug > 0) + printf("ippr_pptp_new: GRE session already exists\n"); + return -1; + } + + aps->aps_psiz = sizeof(*pptp); + KMALLOCS(aps->aps_data, pptp_pxy_t *, sizeof(*pptp)); + if (aps->aps_data == NULL) { + if (ippr_pptp_debug > 0) + printf("ippr_pptp_new: malloc for aps_data failed\n"); + return -1; + } + + /* + * Create NAT rule against which the tunnel/transport mapping is + * created. This is required because the current NAT rule does not + * describe GRE but TCP instead. + */ + pptp = aps->aps_data; + bzero((char *)pptp, sizeof(*pptp)); + ipn = &pptp->pptp_rule; + ipn->in_ifps[0] = fin->fin_ifp; + ipn->in_apr = NULL; + ipn->in_use = 1; + ipn->in_hits = 1; + ipn->in_ippip = 1; + if (nat->nat_dir == NAT_OUTBOUND) { + ipn->in_nip = ntohl(nat->nat_outip.s_addr); + ipn->in_outip = fin->fin_saddr; + ipn->in_redir = NAT_MAP; + } else if (nat->nat_dir == NAT_INBOUND) { + ipn->in_nip = 0; + ipn->in_outip = nat->nat_outip.s_addr; + ipn->in_redir = NAT_REDIRECT; + } + ipn->in_inip = nat->nat_inip.s_addr; + ipn->in_inmsk = 0xffffffff; + ipn->in_outmsk = 0xffffffff; + ipn->in_srcip = fin->fin_saddr; + ipn->in_srcmsk = 0xffffffff; + bcopy(nat->nat_ptr->in_ifnames[0], ipn->in_ifnames[0], + sizeof(ipn->in_ifnames[0])); + ipn->in_p = IPPROTO_GRE; + + pptp->pptp_side[0].pptps_wptr = pptp->pptp_side[0].pptps_buffer; + pptp->pptp_side[1].pptps_wptr = pptp->pptp_side[1].pptps_buffer; + return 0; +} + + +void ippr_pptp_donatstate(fin, nat, pptp) +fr_info_t *fin; +nat_t *nat; +pptp_pxy_t *pptp; +{ + fr_info_t fi; + grehdr_t gre; + nat_t *nat2; + u_char p; + ip_t *ip; + + ip = fin->fin_ip; + p = ip->ip_p; + + nat2 = pptp->pptp_nat; + if ((nat2 == NULL) || (pptp->pptp_state == NULL)) { + bcopy((char *)fin, (char *)&fi, sizeof(fi)); + bzero((char *)&gre, sizeof(gre)); + fi.fin_state = NULL; + fi.fin_nat = NULL; + fi.fin_fi.fi_p = IPPROTO_GRE; + fi.fin_fr = &pptpfr; + if ((nat->nat_dir == NAT_OUTBOUND && fin->fin_out) || + (nat->nat_dir == NAT_INBOUND && !fin->fin_out)) { + fi.fin_data[0] = pptp->pptp_call[0]; + fi.fin_data[1] = pptp->pptp_call[1]; + } else { + fi.fin_data[0] = pptp->pptp_call[1]; + fi.fin_data[1] = pptp->pptp_call[0]; + } + ip = fin->fin_ip; + ip->ip_p = IPPROTO_GRE; + fi.fin_flx &= ~(FI_TCPUDP|FI_STATE|FI_FRAG); + fi.fin_flx |= FI_IGNORE; + fi.fin_dp = &gre; + gre.gr_flags = htons(1 << 13); + if (fin->fin_out && nat->nat_dir == NAT_INBOUND) { + fi.fin_fi.fi_saddr = fin->fin_fi.fi_daddr; + fi.fin_fi.fi_daddr = nat->nat_outip.s_addr; + } else if (!fin->fin_out && nat->nat_dir == NAT_OUTBOUND) { + fi.fin_fi.fi_saddr = nat->nat_inip.s_addr; + fi.fin_fi.fi_daddr = fin->fin_fi.fi_saddr; + } + } + + /* + * Update NAT timeout/create NAT if missing. + */ + if (nat2 != NULL) + fr_queueback(&nat2->nat_tqe); + else { + nat2 = nat_new(&fi, &pptp->pptp_rule, &pptp->pptp_nat, + NAT_SLAVE, nat->nat_dir); + pptp->pptp_nat = nat2; + if (nat2 != NULL) { + (void) nat_proto(&fi, nat2, 0); + nat_update(&fi, nat2, nat2->nat_ptr); + } + } + + READ_ENTER(&ipf_state); + if (pptp->pptp_state != NULL) { + fr_queueback(&pptp->pptp_state->is_sti); + RWLOCK_EXIT(&ipf_state); + } else { + RWLOCK_EXIT(&ipf_state); + if (nat->nat_dir == NAT_INBOUND) + fi.fin_fi.fi_daddr = nat2->nat_inip.s_addr; + else + fi.fin_fi.fi_saddr = nat2->nat_inip.s_addr; + fi.fin_ifp = NULL; + pptp->pptp_state = fr_addstate(&fi, &pptp->pptp_state, + 0); + if (fi.fin_state != NULL) + fr_statederef(&fi, (ipstate_t **)&fi.fin_state); + } + ip->ip_p = p; + return; +} + + +/* + * Try and build up the next PPTP message in the TCP stream and if we can + * build it up completely (fits in our buffer) then pass it off to the message + * parsing function. + */ +int ippr_pptp_nextmessage(fin, nat, pptp, rev) +fr_info_t *fin; +nat_t *nat; +pptp_pxy_t *pptp; +int rev; +{ + static char *funcname = "ippr_pptp_nextmessage"; + pptp_side_t *pptps; + u_32_t start, end; + pptp_hdr_t *hdr; + tcphdr_t *tcp; + int dlen, off; + u_short len; + char *msg; + + tcp = fin->fin_dp; + dlen = fin->fin_dlen - (TCP_OFF(tcp) << 2); + start = ntohl(tcp->th_seq); + pptps = &pptp->pptp_side[rev]; + off = (char *)tcp - (char *)fin->fin_ip + (TCP_OFF(tcp) << 2) + + fin->fin_ipoff; + + if (dlen <= 0) + return 0; + /* + * If the complete data packet is before what we expect to see + * "next", just ignore it as the chances are we've already seen it. + * The next if statement following this one really just causes packets + * ahead of what we've seen to be dropped, implying that something in + * the middle went missing and we want to see that first. + */ + end = start + dlen; + if (pptps->pptps_next > end && pptps->pptps_next > start) + return 0; + + if (pptps->pptps_next != start) { + if (ippr_pptp_debug > 5) + printf("%s: next (%x) != start (%x)\n", funcname, + pptps->pptps_next, start); + return -1; + } + + msg = (char *)fin->fin_dp + (TCP_OFF(tcp) << 2); + + while (dlen > 0) { + off += pptps->pptps_bytes; + if (pptps->pptps_gothdr == 0) { + /* + * PPTP has an 8 byte header that inclues the cookie. + * The start of every message should include one and + * it should match 1a2b3c4d. Byte order is ignored, + * deliberately, when printing out the error. + */ + len = MIN(8 - pptps->pptps_bytes, dlen); + COPYDATA(fin->fin_m, off, len, pptps->pptps_wptr); + pptps->pptps_bytes += len; + pptps->pptps_wptr += len; + hdr = (pptp_hdr_t *)pptps->pptps_buffer; + if (pptps->pptps_bytes == 8) { + pptps->pptps_next += 8; + if (ntohl(hdr->pptph_cookie) != 0x1a2b3c4d) { + if (ippr_pptp_debug > 1) + printf("%s: bad cookie (%x)\n", + funcname, + hdr->pptph_cookie); + return -1; + } + } + dlen -= len; + msg += len; + off += len; + + pptps->pptps_gothdr = 1; + len = ntohs(hdr->pptph_len); + pptps->pptps_len = len; + pptps->pptps_nexthdr += len; + + /* + * If a message is too big for the buffer, just set + * the fields for the next message to come along. + * The messages defined in RFC 2637 will not exceed + * 512 bytes (in total length) so this is likely a + * bad data packet, anyway. + */ + if (len > sizeof(pptps->pptps_buffer)) { + if (ippr_pptp_debug > 3) + printf("%s: message too big (%d)\n", + funcname, len); + pptps->pptps_next = pptps->pptps_nexthdr; + pptps->pptps_wptr = pptps->pptps_buffer; + pptps->pptps_gothdr = 0; + pptps->pptps_bytes = 0; + pptps->pptps_len = 0; + break; + } + } + + len = MIN(pptps->pptps_len - pptps->pptps_bytes, dlen); + COPYDATA(fin->fin_m, off, len, pptps->pptps_wptr); + pptps->pptps_bytes += len; + pptps->pptps_wptr += len; + pptps->pptps_next += len; + + if (pptps->pptps_len > pptps->pptps_bytes) + break; + + (void) ippr_pptp_message(fin, nat, pptp, pptps); + pptps->pptps_wptr = pptps->pptps_buffer; + pptps->pptps_gothdr = 0; + pptps->pptps_bytes = 0; + pptps->pptps_len = 0; + + start += len; + msg += len; + dlen -= len; + } + + return 0; +} + + +/* + * handle a complete PPTP message + */ +int ippr_pptp_message(fin, nat, pptp, pptps) +fr_info_t *fin; +nat_t *nat; +pptp_pxy_t *pptp; +pptp_side_t *pptps; +{ + pptp_hdr_t *hdr = (pptp_hdr_t *)pptps->pptps_buffer; + + switch (ntohs(hdr->pptph_type)) + { + case PPTP_MSGTYPE_CTL : + (void) ippr_pptp_mctl(fin, nat, pptp, pptps); + break; + + default : + break; + } + return 0; +} + + +/* + * handle a complete PPTP control message + */ +int ippr_pptp_mctl(fin, nat, pptp, pptps) +fr_info_t *fin; +nat_t *nat; +pptp_pxy_t *pptp; +pptp_side_t *pptps; +{ + u_short *buffer = (u_short *)(pptps->pptps_buffer); + pptp_side_t *pptpo; + + if (pptps == &pptp->pptp_side[0]) + pptpo = &pptp->pptp_side[1]; + else + pptpo = &pptp->pptp_side[0]; + + /* + * Breakout to handle all the various messages. Most are just state + * transition. + */ + switch (ntohs(buffer[4])) + { + case PPTP_MTCTL_STARTREQ : + pptps->pptps_state = PPTP_MTCTL_STARTREQ; + break; + case PPTP_MTCTL_STARTREP : + if (pptpo->pptps_state == PPTP_MTCTL_STARTREQ) + pptps->pptps_state = PPTP_MTCTL_STARTREP; + break; + case PPTP_MTCTL_STOPREQ : + pptps->pptps_state = PPTP_MTCTL_STOPREQ; + break; + case PPTP_MTCTL_STOPREP : + if (pptpo->pptps_state == PPTP_MTCTL_STOPREQ) + pptps->pptps_state = PPTP_MTCTL_STOPREP; + break; + case PPTP_MTCTL_ECHOREQ : + pptps->pptps_state = PPTP_MTCTL_ECHOREQ; + break; + case PPTP_MTCTL_ECHOREP : + if (pptpo->pptps_state == PPTP_MTCTL_ECHOREQ) + pptps->pptps_state = PPTP_MTCTL_ECHOREP; + break; + case PPTP_MTCTL_OUTREQ : + pptps->pptps_state = PPTP_MTCTL_OUTREQ; + break; + case PPTP_MTCTL_OUTREP : + if (pptpo->pptps_state == PPTP_MTCTL_OUTREQ) { + pptps->pptps_state = PPTP_MTCTL_OUTREP; + pptp->pptp_call[0] = buffer[7]; + pptp->pptp_call[1] = buffer[6]; + ippr_pptp_donatstate(fin, nat, pptp); + } + break; + case PPTP_MTCTL_INREQ : + pptps->pptps_state = PPTP_MTCTL_INREQ; + break; + case PPTP_MTCTL_INREP : + if (pptpo->pptps_state == PPTP_MTCTL_INREQ) { + pptps->pptps_state = PPTP_MTCTL_INREP; + pptp->pptp_call[0] = buffer[7]; + pptp->pptp_call[1] = buffer[6]; + ippr_pptp_donatstate(fin, nat, pptp); + } + break; + case PPTP_MTCTL_INCONNECT : + pptps->pptps_state = PPTP_MTCTL_INCONNECT; + break; + case PPTP_MTCTL_CLEAR : + pptps->pptps_state = PPTP_MTCTL_CLEAR; + break; + case PPTP_MTCTL_DISCONNECT : + pptps->pptps_state = PPTP_MTCTL_DISCONNECT; + break; + case PPTP_MTCTL_WANERROR : + pptps->pptps_state = PPTP_MTCTL_WANERROR; + break; + case PPTP_MTCTL_LINKINFO : + pptps->pptps_state = PPTP_MTCTL_LINKINFO; + break; + } + + return 0; +} + + +/* + * For outgoing PPTP packets. refresh timeouts for NAT & state entries, if + * we can. If they have disappeared, recreate them. + */ +int ippr_pptp_inout(fin, aps, nat) +fr_info_t *fin; +ap_session_t *aps; +nat_t *nat; +{ + pptp_pxy_t *pptp; + tcphdr_t *tcp; + int rev; + + if ((fin->fin_out == 1) && (nat->nat_dir == NAT_INBOUND)) + rev = 1; + else if ((fin->fin_out == 0) && (nat->nat_dir == NAT_OUTBOUND)) + rev = 1; + else + rev = 0; + + tcp = (tcphdr_t *)fin->fin_dp; + if ((tcp->th_flags & TH_OPENING) == TH_OPENING) { + pptp = (pptp_pxy_t *)aps->aps_data; + pptp->pptp_side[1 - rev].pptps_next = ntohl(tcp->th_ack); + pptp->pptp_side[1 - rev].pptps_nexthdr = ntohl(tcp->th_ack); + pptp->pptp_side[rev].pptps_next = ntohl(tcp->th_seq) + 1; + pptp->pptp_side[rev].pptps_nexthdr = ntohl(tcp->th_seq) + 1; + } + return ippr_pptp_nextmessage(fin, nat, (pptp_pxy_t *)aps->aps_data, + rev); +} + + +/* + * clean up after ourselves. + */ +void ippr_pptp_del(aps) +ap_session_t *aps; +{ + pptp_pxy_t *pptp; + + pptp = aps->aps_data; + + if (pptp != NULL) { + /* + * Don't bother changing any of the NAT structure details, + * *_del() is on a callback from aps_free(), from nat_delete() + */ + + READ_ENTER(&ipf_state); + if (pptp->pptp_state != NULL) { + pptp->pptp_state->is_die = fr_ticks + 1; + pptp->pptp_state->is_me = NULL; + fr_queuefront(&pptp->pptp_state->is_sti); + } + RWLOCK_EXIT(&ipf_state); + + pptp->pptp_state = NULL; + pptp->pptp_nat = NULL; + } +} diff --git a/usr/src/common/ipf/ip_proxy.h b/usr/src/uts/common/inet/ipf/netinet/ip_proxy.h index 73fa62ed3c..1e0bedef64 100644 --- a/usr/src/common/ipf/ip_proxy.h +++ b/usr/src/uts/common/inet/ipf/netinet/ip_proxy.h @@ -3,7 +3,7 @@ * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: ip_proxy.h,v 2.30 2003/07/01 01:01:29 darrenr Exp $ + * $Id: ip_proxy.h,v 2.31.2.3 2005/06/18 02:41:33 darrenr Exp $ */ #ifndef __IP_PROXY_H__ @@ -13,6 +13,12 @@ #define SOLARIS (defined(sun) && (defined(__svr4__) || defined(__SVR4))) #endif +#if defined(__STDC__) || defined(__GNUC__) || defined(_AIX51) +#define SIOCPROXY _IOWR('r', 64, struct ap_control) +#else +#define SIOCPROXY _IOWR(r, 64, struct ap_control) +#endif + #ifndef APR_LABELLEN #define APR_LABELLEN 16 #endif @@ -20,15 +26,16 @@ struct nat; struct ipnat; +struct ipstate; typedef struct ap_tcp { u_short apt_sport; /* source port */ u_short apt_dport; /* destination port */ short apt_sel[2]; /* {seq,ack}{off,min} set selector */ short apt_seqoff[2]; /* sequence # difference */ - tcp_seq apt_seqmin[2]; /* don't change seq-off until after this */ + u_32_t apt_seqmin[2]; /* don't change seq-off until after this */ short apt_ackoff[2]; /* sequence # difference */ - tcp_seq apt_ackmin[2]; /* don't change seq-off until after this */ + u_32_t apt_ackmin[2]; /* don't change seq-off until after this */ u_char apt_state[2]; /* connection state */ } ap_tcp_t; @@ -130,9 +137,18 @@ typedef struct aproxy { #endif /* - * For the ftp proxy. + * This is the scratch buffer size used to hold strings from the TCP stream + * that we may want to parse. It's an arbitrary size, really, but it must + * be at least as large as IPF_FTPBUFSZ. + */ +#define FTP_BUFSZ 120 + +/* + * This buffer, however, doesn't need to be nearly so big. It just needs to + * be able to squeeze in the largest command it needs to rewrite, Which ones + * does it rewrite? EPRT, PORT, 227 replies. */ -#define FTP_BUFSZ 160 +#define IPF_FTPBUFSZ 80 /* This *MUST* be >= 53! */ typedef struct ftpside { char *ftps_rptr; @@ -140,7 +156,7 @@ typedef struct ftpside { void *ftps_ifp; u_32_t ftps_seq[2]; u_32_t ftps_len; - int ftps_junk; + int ftps_junk; /* 2 = no cr/lf yet, 1 = cannot parse */ int ftps_cmds; char ftps_buf[FTP_BUFSZ]; } ftpside_t; @@ -186,7 +202,7 @@ typedef struct raudio_s { u_32_t rap_sbf; /* flag to indicate which of the 19 bytes have * been filled */ - tcp_seq rap_sseq; + u_32_t rap_sseq; } raudio_t; #define RA_ID_END 0 @@ -199,6 +215,9 @@ typedef struct raudio_s { #define RAP_M_UDP_ROBUST (RAP_M_UDP|RAP_M_ROBUST) +/* + * MSN RPC proxy + */ typedef struct msnrpcinfo { u_int mri_flags; int mri_cmd[2]; @@ -219,10 +238,33 @@ typedef struct ipsec_pxy { int ipsc_rckset; ipnat_t ipsc_rule; nat_t *ipsc_nat; - ipstate_t *ipsc_state; + struct ipstate *ipsc_state; } ipsec_pxy_t; /* + * PPTP proxy + */ +typedef struct pptp_side { + u_32_t pptps_nexthdr; + u_32_t pptps_next; + int pptps_state; + int pptps_gothdr; + int pptps_len; + int pptps_bytes; + char *pptps_wptr; + char pptps_buffer[512]; +} pptp_side_t; + +typedef struct pptp_pxy { + ipnat_t pptp_rule; + nat_t *pptp_nat; + struct ipstate *pptp_state; + u_short pptp_call[2]; + pptp_side_t pptp_side[2]; +} pptp_pxy_t; + + +/* * Sun RPCBIND proxy */ #define RPCB_MAXMSG 888 @@ -411,10 +453,6 @@ extern void aps_free __P((ap_session_t *)); extern int appr_check __P((fr_info_t *, struct nat *)); extern aproxy_t *appr_lookup __P((u_int, char *)); extern int appr_new __P((fr_info_t *, struct nat *)); -#if defined(__NetBSD__) || defined(__OpenBSD__) || (__FreeBSD_version >= 300003) -extern int appr_ioctl __P((caddr_t, u_long, int)); -#else -extern int appr_ioctl __P((caddr_t, int, int)); -#endif +extern int appr_ioctl __P((caddr_t, ioctlcmd_t, int)); #endif /* __IP_PROXY_H__ */ diff --git a/usr/src/common/ipf/ip_raudio_pxy.c b/usr/src/uts/common/inet/ipf/netinet/ip_raudio_pxy.c index 70254575b8..a9abc5809b 100644 --- a/usr/src/common/ipf/ip_raudio_pxy.c +++ b/usr/src/uts/common/inet/ipf/netinet/ip_raudio_pxy.c @@ -3,18 +3,14 @@ * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: ip_raudio_pxy.c,v 1.35 2003/06/28 17:01:58 darrenr Exp $ + * $Id: ip_raudio_pxy.c,v 1.40.2.3 2005/02/04 10:22:55 darrenr Exp $ * - * Copyright 2003 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #pragma ident "%Z%%M% %I% %E% SMI" -#ifdef USE_MUTEXES -extern ipfmutex_t ipf_rw; -#endif - #define IPF_RAUDIO_PROXY @@ -103,16 +99,21 @@ nat_t *nat; m = fin->fin_m; tcp = (tcphdr_t *)fin->fin_dp; - off = (char *)tcp - MTOD(m, char *) + (TCP_OFF(tcp) << 2); - bzero((char *)membuf, sizeof(membuf)); + off = (char *)tcp - (char *)fin->fin_ip; + off += (TCP_OFF(tcp) << 2) + fin->fin_ipoff; +#ifdef __sgi + dlen = fin->fin_plen - off; +#else dlen = MSGDSIZE(m) - off; +#endif if (dlen <= 0) return 0; if (dlen > sizeof(membuf)) dlen = sizeof(membuf); + bzero((char *)membuf, sizeof(membuf)); COPYDATA(m, off, dlen, (char *)membuf); /* * In all the startup parsing, ensure that we don't go outside @@ -188,8 +189,8 @@ nat_t *nat; unsigned char membuf[IPF_MAXPORTLEN + 1], *s; tcphdr_t *tcp, tcph, *tcp2 = &tcph; raudio_t *rap = aps->aps_data; - int off, dlen, slen, clen; struct in_addr swa, swb; + int off, dlen, slen; int a1, a2, a3, a4; u_short sp, dp; fr_info_t fi; @@ -208,11 +209,15 @@ nat_t *nat; return 0; m = fin->fin_m; - ip = fin->fin_ip; tcp = (tcphdr_t *)fin->fin_dp; - off = (char *)tcp - MTOD(m, char *) + (TCP_OFF(tcp) << 2); + off = (char *)tcp - (char *)fin->fin_ip; + off += (TCP_OFF(tcp) << 2) + fin->fin_ipoff; +#ifdef __sgi + dlen = fin->fin_plen - off; +#else dlen = MSGDSIZE(m) - off; +#endif if (dlen <= 0) return 0; @@ -220,8 +225,7 @@ nat_t *nat; dlen = sizeof(membuf); bzero((char *)membuf, sizeof(membuf)); - clen = MIN(sizeof(membuf), dlen); - COPYDATA(m, off, clen, (char *)membuf); + COPYDATA(m, off, dlen, (char *)membuf); seq = ntohl(tcp->th_seq); /* @@ -229,7 +233,7 @@ nat_t *nat; * We only care for the first 19 bytes coming back from the server. */ if (rap->rap_sseq == 0) { - s = (u_char *)memstr("PNA", (char *)membuf, 3, clen); + s = (u_char *)memstr("PNA", (char *)membuf, 3, dlen); if (s == NULL) return 0; a1 = s - membuf; @@ -264,6 +268,7 @@ nat_t *nat; rap->rap_srport = (*s << 8) | *(s + 1); } + ip = fin->fin_ip; swp = ip->ip_p; swa = ip->ip_src; swb = ip->ip_dst; @@ -275,6 +280,8 @@ nat_t *nat; bcopy((char *)fin, (char *)&fi, sizeof(fi)); bzero((char *)tcp2, sizeof(*tcp2)); TCP_OFF_A(tcp2, 5); + fi.fin_state = NULL; + fi.fin_nat = NULL; fi.fin_flx |= FI_IGNORE; fi.fin_dp = (char *)tcp2; fi.fin_fr = &raudiofr; @@ -301,6 +308,8 @@ nat_t *nat; nat_update(&fi, nat2, nat2->nat_ptr); (void) fr_addstate(&fi, NULL, (sp ? 0 : SI_W_SPORT)); + if (fi.fin_state != NULL) + fr_statederef(&fi, (ipstate_t **)&fi.fin_state); } } @@ -319,6 +328,8 @@ nat_t *nat; nat_update(&fi, nat2, nat2->nat_ptr); (void) fr_addstate(&fi, NULL, SI_W_DPORT); + if (fi.fin_state != NULL) + fr_statederef(&fi, (ipstate_t **)&fi.fin_state); } } diff --git a/usr/src/common/ipf/ip_rcmd_pxy.c b/usr/src/uts/common/inet/ipf/netinet/ip_rcmd_pxy.c index f6a52f8e43..919c47cb90 100644 --- a/usr/src/common/ipf/ip_rcmd_pxy.c +++ b/usr/src/uts/common/inet/ipf/netinet/ip_rcmd_pxy.c @@ -3,9 +3,9 @@ * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: ip_rcmd_pxy.c,v 1.32 2003/06/28 17:01:58 darrenr Exp $ + * $Id: ip_rcmd_pxy.c,v 1.41.2.4 2005/02/04 10:22:55 darrenr Exp $ * - * Copyright 2003 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. * * Simple RCMD transparent proxy for in-kernel use. For use with the NAT @@ -14,24 +14,14 @@ #pragma ident "%Z%%M% %I% %E% SMI" -#if 0 -#if SOLARIS && defined(_KERNEL) -extern kmutex_t ipf_rw; -#endif -#else -# ifdef USE_MUTEXES -extern ipfmutex_t ipf_rw; -# endif -#endif - #define IPF_RCMD_PROXY int ippr_rcmd_init __P((void)); void ippr_rcmd_fini __P((void)); int ippr_rcmd_new __P((fr_info_t *, ap_session_t *, nat_t *)); -int ippr_rcmd_in __P((fr_info_t *, ap_session_t *, nat_t *)); int ippr_rcmd_out __P((fr_info_t *, ap_session_t *, nat_t *)); +int ippr_rcmd_in __P((fr_info_t *, ap_session_t *, nat_t *)); u_short ipf_rcmd_atoi __P((char *)); int ippr_rcmd_portmsg __P((fr_info_t *, ap_session_t *, nat_t *)); @@ -101,7 +91,7 @@ char *ptr; register char *s = ptr, c; register u_short i = 0; - while (((c = *s++) != '\0') && isdigit(c)) { + while (((c = *s++) != '\0') && ISDIGIT(c)) { i *= 10; i += c - '0'; } @@ -137,9 +127,13 @@ nat_t *nat; m = fin->fin_m; ip = fin->fin_ip; - off = (char *)tcp - MTOD(m, char *) + (TCP_OFF(tcp) << 2); - + off = (char *)tcp - (char *)ip + (TCP_OFF(tcp) << 2) + fin->fin_ipoff; + +#ifdef __sgi + dlen = fin->fin_plen - off; +#else dlen = MSGDSIZE(m) - off; +#endif if (dlen <= 0) return 0; @@ -164,7 +158,7 @@ nat_t *nat; bcopy((char *)fin, (char *)&fi, sizeof(fi)); fi.fin_flx |= FI_IGNORE; fi.fin_data[0] = sp; - fi.fin_data[1] = fin->fin_data[1]; + fi.fin_data[1] = 0; if (nat->nat_dir == NAT_OUTBOUND) nat2 = nat_outlookup(&fi, NAT_SEARCH|IPN_TCP, nat->nat_p, nat->nat_inip, nat->nat_oip); @@ -182,7 +176,6 @@ nat_t *nat; tcp2->th_dport = 0; /* XXX - don't specify remote port */ TCP_OFF_A(tcp2, 5); tcp2->th_flags = TH_SYN; - fi.fin_data[1] = 0; fi.fin_dp = (char *)tcp2; fi.fin_fr = &rcmdfr; fi.fin_dlen = sizeof(*tcp2); @@ -213,6 +206,8 @@ nat_t *nat; ip->ip_dst = nat->nat_inip; } (void) fr_addstate(&fi, &nat2->nat_state, SI_W_DPORT); + if (fi.fin_state != NULL) + fr_statederef(&fi, (ipstate_t **)&fi.fin_state); } ip->ip_len = slen; ip->ip_src = swip; diff --git a/usr/src/common/ipf/ip_rpcb_pxy.c b/usr/src/uts/common/inet/ipf/netinet/ip_rpcb_pxy.c index fa1a230721..f67c01a232 100644 --- a/usr/src/common/ipf/ip_rpcb_pxy.c +++ b/usr/src/uts/common/inet/ipf/netinet/ip_rpcb_pxy.c @@ -37,7 +37,7 @@ * o The enclosed hack of STREAMS support is pretty sick and most likely * broken. * - * $Id: ip_rpcb_pxy.c,v 2.17 2003/07/01 18:30:21 darrenr Exp $ + * $Id: ip_rpcb_pxy.c,v 2.25.2.3 2005/02/04 10:22:56 darrenr Exp $ */ #define IPF_RPCB_PROXY @@ -75,7 +75,7 @@ static int ippr_rpcb_modv3 __P((fr_info_t *, nat_t *, rpc_msg_t *, static int ippr_rpcb_modv4 __P((fr_info_t *, nat_t *, rpc_msg_t *, mb_t *, u_int)); static void ippr_rpcb_fixlen __P((fr_info_t *, int)); - + /* * Global variables */ @@ -220,7 +220,8 @@ ippr_rpcb_in(fin, aps, nat) rs = (rpcb_session_t *)aps->aps_data; m = fin->fin_m; - off = (char *)fin->fin_dp - MTOD(m, char *) + sizeof(udphdr_t); + off = (char *)fin->fin_dp - (char *)fin->fin_ip; + off += sizeof(udphdr_t) + fin->fin_ipoff; dlen = fin->fin_dlen - sizeof(udphdr_t); /* Disallow packets outside legal range for supported requests. */ @@ -289,7 +290,8 @@ ippr_rpcb_out(fin, aps, nat) rs = (rpcb_session_t *)aps->aps_data; m = fin->fin_m; - off = (char *)fin->fin_dp - MTOD(m, char *) + sizeof(udphdr_t); + off = (char *)fin->fin_dp - (char *)fin->fin_ip; + off += sizeof(udphdr_t) + fin->fin_ipoff; dlen = fin->fin_dlen - sizeof(udphdr_t); diff = 0; @@ -676,11 +678,11 @@ ippr_rpcb_getuaddr(rm, xu, p) * Expected format: a.b.c.d.e.f where [a-d] correspond to bytes of * an IP address and [ef] are the bytes of a L4 port. */ - if (!(isdigit(uastr[0]) && isdigit(uastr[l-1]))) + if (!(ISDIGIT(uastr[0]) && ISDIGIT(uastr[l-1]))) return(-1); b = uastr; for (c = &uastr[1], d = 0, dd = 0; c < &uastr[l-1]; c++) { - if (isdigit(*c)) { + if (ISDIGIT(*c)) { dd = 0; continue; } @@ -734,7 +736,7 @@ ippr_rpcb_atoi(ptr) register char *s = ptr, c; register u_int i = 0; - while (((c = *s++) != '\0') && isdigit(c)) { + while (((c = *s++) != '\0') && ISDIGIT(c)) { i *= 10; i += c - '0'; } @@ -775,8 +777,13 @@ ippr_rpcb_modreq(fin, nat, rm, m, off) /* Form new string. */ bzero(uaddr, sizeof(uaddr)); /* Just in case we need padding. */ - (void) sprintf(uaddr, "%u.%u.%u.%u.%u.%u", i[0] & 0xff, i[1] & 0xff, - i[2] & 0xff, i[3] & 0xff, p[0] & 0xff, p[1] & 0xff); +#if defined(SNPRINTF) && defined(_KERNEL) + (void) SNPRINTF(uaddr, sizeof(uaddr), +#else + (void) sprintf(uaddr, +#endif + "%u.%u.%u.%u.%u.%u", i[0] & 0xff, i[1] & 0xff, + i[2] & 0xff, i[3] & 0xff, p[0] & 0xff, p[1] & 0xff); len = strlen(uaddr); xlen = XDRALIGN(len); @@ -996,7 +1003,7 @@ ippr_rpcb_decoderep(fin, nat, rs, rm, rxp) for(rl->rl_cnt = 0; rl->rl_cnt < cnt; rl->rl_cnt++) { re = &rl->rl_entries[rl->rl_cnt]; rv = ippr_rpcb_getnat(fin, nat, - re->re_proto.xp_proto, + re->re_proto.xp_proto, (u_int)re->re_maddr.xu_port); if (rv != 0) return(-1); @@ -1169,7 +1176,7 @@ ippr_rpcb_getnat(fin, nat, proto, port) fi.fin_dp = &tcp; fi.fin_plen = fi.fin_hlen + fi.fin_dlen; - /* + /* * Search for existing NAT & state entries. Pay close attention to * mutexes / locks grabbed from lookup routines, as not doing so could * lead to bad things. @@ -1257,6 +1264,8 @@ ippr_rpcb_getnat(fin, nat, proto, port) */ return(-1); } + if (fi.fin_state != NULL) + fr_statederef(&fi, (ipstate_t **)&fi.fin_state); } return(0); @@ -1294,8 +1303,13 @@ ippr_rpcb_modv3(fin, nat, rm, m, off) /* Form new string. */ bzero(uaddr, sizeof(uaddr)); /* Just in case we need padding. */ - (void) sprintf(uaddr, "%u.%u.%u.%u.%u.%u", i[0] & 0xff, i[1] & 0xff, - i[2] & 0xff, i[3] & 0xff, p[0] & 0xff, p[1] & 0xff); +#if defined(SNPRINTF) && defined(_KERNEL) + (void) SNPRINTF(uaddr, sizeof(uaddr), +#else + (void) sprintf(uaddr, +#endif + "%u.%u.%u.%u.%u.%u", i[0] & 0xff, i[1] & 0xff, + i[2] & 0xff, i[3] & 0xff, p[0] & 0xff, p[1] & 0xff); len = strlen(uaddr); xlen = XDRALIGN(len); @@ -1369,8 +1383,14 @@ ippr_rpcb_modv4(fin, nat, rm, m, off) /* Form new string. */ bzero(uaddr, sizeof(uaddr)); /* Just in case we need padding. */ - (void) sprintf(uaddr, "%u.%u.%u.%u.%u.%u", i[0] & 0xff, i[1] & 0xff, - i[2] & 0xff, i[3] & 0xff, p[0] & 0xff, p[1] & 0xff); +#if defined(SNPRINTF) && defined(_KERNEL) + (void) SNPRINTF(uaddr, sizeof(uaddr), +#else + (void) sprintf(uaddr, +#endif + "%u.%u.%u.%u.%u.%u", i[0] & 0xff, + i[1] & 0xff, i[2] & 0xff, i[3] & 0xff, + p[0] & 0xff, p[1] & 0xff); len = strlen(uaddr); xlen = XDRALIGN(len); diff --git a/usr/src/common/ipf/ip_state.h b/usr/src/uts/common/inet/ipf/netinet/ip_state.h index ce293cd350..7b5891d86d 100644 --- a/usr/src/common/ipf/ip_state.h +++ b/usr/src/uts/common/inet/ipf/netinet/ip_state.h @@ -4,9 +4,9 @@ * See the IPFILTER.LICENCE file for details on licencing. * * @(#)ip_state.h 1.3 1/12/96 (C) 1995 Darren Reed - * $Id: ip_state.h,v 2.63 2003/06/28 17:02:00 darrenr Exp $ + * $Id: ip_state.h,v 2.68.2.5 2005/08/11 19:58:04 darrenr Exp $ * - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -15,7 +15,7 @@ #ifndef __IP_STATE_H__ #define __IP_STATE_H__ -#if defined(__STDC__) || defined(__GNUC__) +#if defined(__STDC__) || defined(__GNUC__) || defined(_AIX51) # define SIOCDELST _IOW('r', 61, struct ipfobj) #else # define SIOCDELST _IOW(r, 61, struct ipfobj) @@ -48,8 +48,10 @@ typedef struct ipstate { struct nat *is_nat[2]; frentry_t *is_rule; struct ipftq *is_tqehead[2]; + struct ipscan *is_isc; U_QUAD_T is_pkts[4]; U_QUAD_T is_bytes[4]; + U_QUAD_T is_icmppkts[4]; struct ipftqent is_sti; u_int is_frage[2]; int is_ref; /* reference count */ @@ -81,7 +83,6 @@ typedef struct ipstate { u_32_t is_rulen; /* rule number when created */ u_32_t is_s0[2]; u_short is_smsk[2]; - struct ipscan *is_isc; char is_group[FR_GROUPLEN]; char is_sbuf[2][16]; char is_ifname[4][LIFNAMSIZ]; @@ -112,6 +113,7 @@ typedef struct ipstate { #define is_ifpin is_ifp[0] #define is_ifpout is_ifp[2] #define is_gre is_ps.is_ug +#define is_call is_gre.gs_call #define IS_WSPORT SI_W_SPORT /* 0x00100 */ #define IS_WDPORT SI_W_DPORT /* 0x00200 */ @@ -124,6 +126,7 @@ typedef struct ipstate { #define IS_STRICT 0x20000 #define IS_ISNSYN 0x40000 #define IS_ISNACK 0x80000 +#define IS_STATESYNC 0x100000 /* * IS_SC flags are for scan-operations that need to be recognised in state. */ @@ -231,6 +234,7 @@ extern u_long fr_udptimeout; extern u_long fr_udpacktimeout; extern u_long fr_icmptimeout; extern u_long fr_icmpacktimeout; +extern u_long fr_iptimeout; extern int fr_statemax; extern int fr_statesize; extern int fr_state_lock; @@ -249,18 +253,15 @@ extern void fr_timeoutstate __P((void)); extern int fr_tcp_age __P((struct ipftqent *, struct fr_info *, struct ipftq *, int)); extern int fr_tcpinwindow __P((struct fr_info *, struct tcpdata *, - struct tcpdata *, struct tcphdr *, int)); + struct tcpdata *, tcphdr_t *, int)); extern void fr_stateunload __P((void)); extern void ipstate_log __P((struct ipstate *, u_int)); -#if defined(__NetBSD__) || defined(__OpenBSD__) -extern int fr_state_ioctl __P((caddr_t, u_long, int)); -#else -extern int fr_state_ioctl __P((caddr_t, int, int)); -#endif -extern void fr_stinsert __P((struct ipstate *)); +extern int fr_state_ioctl __P((caddr_t, ioctlcmd_t, int)); +extern void fr_stinsert __P((struct ipstate *, int)); extern void fr_sttab_init __P((struct ipftq *)); extern void fr_sttab_destroy __P((struct ipftq *)); extern void fr_updatestate __P((fr_info_t *, ipstate_t *, ipftq_t *)); extern void fr_statederef __P((fr_info_t *, ipstate_t **)); +extern void fr_setstatequeue __P((ipstate_t *, int)); #endif /* __IP_STATE_H__ */ diff --git a/usr/src/uts/common/inet/ipf/netinet/ipl.h b/usr/src/uts/common/inet/ipf/netinet/ipl.h new file mode 100644 index 0000000000..df2c0b4f3b --- /dev/null +++ b/usr/src/uts/common/inet/ipf/netinet/ipl.h @@ -0,0 +1,23 @@ +/* + * Copyright (C) 1993-2001, 2003 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * @(#)ipl.h 1.21 6/5/96 + * $Id: ipl.h,v 2.52.2.10 2005/08/13 05:42:49 darrenr Exp $ + * + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + + +#ifndef __IPL_H__ +#define __IPL_H__ + +#define IPL_VERSION "IP Filter: v4.1.9" + +#define IPFILTER_VERSION 4010900 + +#endif diff --git a/usr/src/common/ipf/opts.h b/usr/src/uts/common/inet/ipf/opts.h index 6850e6b52f..d944df6242 100644 --- a/usr/src/common/ipf/opts.h +++ b/usr/src/uts/common/inet/ipf/opts.h @@ -3,9 +3,9 @@ * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: opts.h,v 2.11 2003/06/14 02:05:21 darrenr Exp $ + * $Id: opts.h,v 2.12 2003/08/14 14:24:27 darrenr Exp $ * - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -44,7 +44,8 @@ #define OPT_CLEAR 0x1000000 #define OPT_HEX 0x2000000 #define OPT_ASCII 0x4000000 -#define OPT_UNDEF 0x8000000 +#define OPT_NORESOLVE 0x8000000 +#define OPT_UNDEF 0x10000000 #define OPT_STAT OPT_FRSTATES #define OPT_LIST OPT_SHOWLIST diff --git a/usr/src/uts/common/inet/ipf/pfil.conf b/usr/src/uts/common/inet/ipf/pfil.conf deleted file mode 100644 index 018946143b..0000000000 --- a/usr/src/uts/common/inet/ipf/pfil.conf +++ /dev/null @@ -1,2 +0,0 @@ -name="pfil" parent="pseudo" instance=0; - diff --git a/usr/src/common/ipf/radix.c b/usr/src/uts/common/inet/ipf/radix.c index f3dd0a6170..69b50c062a 100644 --- a/usr/src/common/ipf/radix.c +++ b/usr/src/uts/common/inet/ipf/radix.c @@ -29,8 +29,15 @@ /* * Routines to build and maintain radix trees for routing lookups. */ - -#if !defined(__svr4__) && !defined(__SVR4) && !defined(__osf__) +#if defined(KERNEL) || defined(_KERNEL) +# undef KERNEL +# undef _KERNEL +# define KERNEL 1 +# define _KERNEL 1 +#endif +#define __SYS_ATOMIC_OPS_H__ +#if !defined(__svr4__) && !defined(__SVR4) && !defined(__osf__) && \ + !defined(__hpux) && !defined(__sgi) #include <sys/cdefs.h> #endif #ifndef __P @@ -40,31 +47,47 @@ # define __P(x) () # endif #endif +#ifdef __osf__ +# define CONST +# define _IPV6_SWTAB_H +# define _PROTO_NET_H_ +# define _PROTO_IPV6_H +# include <sys/malloc.h> +#endif #include <sys/param.h> #ifdef _KERNEL #include <sys/systm.h> #else -void panic(char *str); +void panic __P((char *str)); #include <stdlib.h> #include <stdio.h> #include <stdarg.h> #include <string.h> #endif +#ifdef __hpux +#include <syslog.h> +#else #include <sys/syslog.h> +#endif #include <sys/time.h> #include <netinet/in.h> #include <sys/socket.h> #include <net/if.h> -#include "ip_compat.h" -#include "ip_fil.h" -#include "radix.h" -#define min MIN -#define max MAX +#include "netinet/ip_compat.h" +#include "netinet/ip_fil.h" +/* END OF INCLUDES */ +#include "radix_ipf.h" +#ifndef min +# define min MIN +#endif +#ifndef max +# define max MAX +#endif int max_keylen = 16; -struct radix_mask *rn_mkfreelist; -struct radix_node_head *mask_rnhead; +static struct radix_mask *rn_mkfreelist; +static struct radix_node_head *mask_rnhead; static char *addmask_key; static u_char normal_chars[] = {0, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff}; static char *rn_zeros = NULL, *rn_ones = NULL; @@ -75,9 +98,15 @@ static char *rn_zeros = NULL, *rn_ones = NULL; static int rn_satisfies_leaf __P((char *, struct radix_node *, int)); static int rn_lexobetter __P((void *, void *)); -static int rn_freenode __P((struct radix_node *, void *)); static struct radix_mask *rn_new_radix_mask __P((struct radix_node *, struct radix_mask *)); +static int rn_freenode __P((struct radix_node *, void *)); +#if defined(AIX) && !defined(_KERNEL) +struct radix_node *rn_match __P((void *, struct radix_node_head *)); +struct radix_node *rn_addmask __P((int, int, void *)); +#define FreeS(x, y) KFREES(x, y) +#define Bcopy(x, y, z) bcopy(x, y, z) +#endif /* * The data structure for the keys is a radix tree with one way @@ -94,18 +123,18 @@ static struct radix_mask *rn_new_radix_mask __P((struct radix_node *, * We define the index of a route to associated with the mask to be * the first bit number in the mask where 0 occurs (with bit number 0 * representing the highest order bit). - * + * * We say a mask is normal if every bit is 0, past the index of the mask. * If a node n has a descendant (k, m) with index(m) == index(n) == rn_b, * and m is a normal mask, then the route applies to every descendant of n. * If the index(m) < rn_b, this implies the trailing last few bits of k * before bit b are all 0, (and hence consequently true of every descendant * of n), so the route applies to all descendants of the node as well. - * + * * Similar logic shows that a non-normal mask m such that * index(m) <= index(n) could potentially apply to many children of n. * Thus, for each non-host route, we attach its mask to a list at an internal - * node as high in the tree as we can go. + * node as high in the tree as we can go. * * The present version of the code makes use of normal routes in short- * circuiting an explict mask and compare operation when testing whether @@ -159,7 +188,7 @@ rn_refines(m_arg, n_arg) if (longer > 0) lim -= longer; - while (n < lim) { + while (n < lim) { if (*n & ~(*m)) return 0; if (*n++ != *m++) @@ -210,7 +239,9 @@ rn_satisfies_leaf(trial, leaf, skip) cp3 = rn_ones; else length = min(length, *(u_char *)cp3); - cplim = cp + length; cp3 += skip; cp2 += skip; + cplim = cp + length; + cp3 += skip; + cp2 += skip; for (cp += skip; cp < cplim; cp++, cp2++, cp3++) if ((*cp ^ *cp2) & *cp3) return 0; @@ -253,7 +284,9 @@ rn_match(v_arg, head) */ if (t->rn_mask) vlen = *(u_char *)t->rn_mask; - cp += off; cp2 = t->rn_key + off; cplim = v + vlen; + cp += off; + cp2 = t->rn_key + off; + cplim = v + vlen; for (; cp < cplim; cp++, cp2++) if (*cp != *cp2) goto on1; @@ -318,7 +351,7 @@ on1: } while (t != top); return 0; } - + #ifdef RN_DEBUG int rn_nodenum; struct radix_node *rn_clist; @@ -333,13 +366,20 @@ rn_newpair(v, b, nodes) struct radix_node nodes[2]; { struct radix_node *tt = nodes, *t = tt + 1; - t->rn_b = b; t->rn_bmask = 0x80 >> (b & 7); - t->rn_l = tt; t->rn_off = b >> 3; - tt->rn_b = -1; tt->rn_key = (caddr_t)v; tt->rn_p = t; + t->rn_b = b; + t->rn_bmask = 0x80 >> (b & 7); + t->rn_l = tt; + t->rn_off = b >> 3; + tt->rn_b = -1; + tt->rn_key = (caddr_t)v; + tt->rn_p = t; tt->rn_flags = t->rn_flags = RNF_ACTIVE; #ifdef RN_DEBUG - tt->rn_info = rn_nodenum++; t->rn_info = rn_nodenum++; - tt->rn_twin = t; tt->rn_ybro = rn_clist; rn_clist = tt; + tt->rn_info = rn_nodenum++; + t->rn_info = rn_nodenum++; + tt->rn_twin = t; + tt->rn_ybro = rn_clist; + rn_clist = tt; #endif return t; } @@ -387,24 +427,28 @@ on1: cp = v; do { p = x; - if (cp[x->rn_off] & x->rn_bmask) + if (cp[x->rn_off] & x->rn_bmask) x = x->rn_r; - else x = x->rn_l; + else + x = x->rn_l; } while (b > (unsigned) x->rn_b); /* x->rn_b < b && x->rn_b >= 0 */ #ifdef RN_DEBUG if (rn_debug) log(LOG_DEBUG, "rn_insert: Going In:\n"); // traverse(p); #endif - t = rn_newpair(v_arg, b, nodes); tt = t->rn_l; + t = rn_newpair(v_arg, b, nodes); + tt = t->rn_l; if ((cp[p->rn_off] & p->rn_bmask) == 0) p->rn_l = t; else p->rn_r = t; - x->rn_p = t; t->rn_p = p; /* frees x, p as temp vars below */ + x->rn_p = t; + t->rn_p = p; /* frees x, p as temp vars below */ if ((cp[t->rn_off] & t->rn_bmask) == 0) { t->rn_r = x; } else { - t->rn_r = tt; t->rn_l = x; + t->rn_r = tt; + t->rn_l = x; } #ifdef RN_DEBUG if (rn_debug) @@ -478,11 +522,12 @@ rn_addmask(n_arg, search, skip) /* * Calculate index of mask, and check for normalcy. */ - cplim = netmask + mlen; isnormal = 1; + cplim = netmask + mlen; + isnormal = 1; for (cp = netmask + skip; (cp < cplim) && *(u_char *)cp == 0xff;) cp++; if (cp != cplim) { - for (j = 0x80; (j & *cp) != 0; j >>= 1) + for (j = 0x80; (j & *cp) != 0; j >>= 1) b++; if (*cp != normal_chars[b] || cp != (cplim - 1)) isnormal = 0; @@ -502,7 +547,7 @@ rn_lexobetter(m_arg, n_arg) if (*mp > *np) return 1; /* not really, but need to check longer one first */ - if (*mp == *np) + if (*mp == *np) for (lim = mp + *mp; mp < lim;) if (*mp++ > *np++) return 1; @@ -542,7 +587,7 @@ rn_addroute(v_arg, n_arg, head, treenodes) struct radix_node treenodes[2]; { caddr_t v = (caddr_t)v_arg, netmask = (caddr_t)n_arg; - struct radix_node *t, *x = 0, *tt; + struct radix_node *t, *x = NULL, *tt; struct radix_node *saved_tt, *top = head->rnh_treetop; short b = 0, b_leaf = 0; int keyduplicated; @@ -560,7 +605,7 @@ rn_addroute(v_arg, n_arg, head, treenodes) * the mask to speed avoiding duplicate references at * nodes and possibly save time in calculating indices. */ - if (netmask) { + if (netmask) { if ((x = rn_addmask(netmask, 0, top->rn_off)) == 0) return (0); b_leaf = x->rn_b; @@ -602,8 +647,12 @@ rn_addroute(v_arg, n_arg, head, treenodes) tt->rn_flags = t->rn_flags; tt->rn_p = x = t->rn_p; t->rn_p = tt; - if (x->rn_l == t) x->rn_l = tt; else x->rn_r = tt; - saved_tt = tt; x = xx; + if (x->rn_l == t) + x->rn_l = tt; + else + x->rn_r = tt; + saved_tt = tt; + x = xx; } else { (tt = treenodes)->rn_dupedkey = t->rn_dupedkey; t->rn_dupedkey = tt; @@ -612,8 +661,12 @@ rn_addroute(v_arg, n_arg, head, treenodes) tt->rn_dupedkey->rn_p = tt; } #ifdef RN_DEBUG - t=tt+1; tt->rn_info = rn_nodenum++; t->rn_info = rn_nodenum++; - tt->rn_twin = t; tt->rn_ybro = rn_clist; rn_clist = tt; + t=tt+1; + tt->rn_info = rn_nodenum++; + t->rn_info = rn_nodenum++; + tt->rn_twin = t; + tt->rn_ybro = rn_clist; + rn_clist = tt; #endif tt->rn_key = (caddr_t) v; tt->rn_b = -1; @@ -631,9 +684,12 @@ rn_addroute(v_arg, n_arg, head, treenodes) if (keyduplicated) goto on2; b_leaf = -1 - t->rn_b; - if (t->rn_r == saved_tt) x = t->rn_l; else x = t->rn_r; + if (t->rn_r == saved_tt) + x = t->rn_l; + else + x = t->rn_r; /* Promote general routes from below */ - if (x->rn_b < 0) { + if (x->rn_b < 0) { for (mp = &t->rn_mklist; x; x = x->rn_dupedkey) if (x->rn_mask && (x->rn_b >= b_leaf) && x->rn_mklist == 0) { *mp = m = rn_new_radix_mask(x, 0); @@ -644,10 +700,11 @@ rn_addroute(v_arg, n_arg, head, treenodes) /* * Skip over masks whose index is > that of new node */ - for (mp = &x->rn_mklist; ((m = *mp) != NULL); mp = &m->rm_mklist) + for (mp = &x->rn_mklist; (m = *mp) != NULL; mp = &m->rm_mklist) if (m->rm_b >= b_leaf) break; - t->rn_mklist = m; *mp = 0; + t->rn_mklist = m; + *mp = 0; } on2: /* Add new route to highest possible ancestor's list */ @@ -664,7 +721,7 @@ on2: * Need same criteria as when sorting dupedkeys to avoid * double loop on deletion. */ - for (mp = &x->rn_mklist; ((m = *mp) != NULL); mp = &m->rm_mklist) { + for (mp = &x->rn_mklist; (m = *mp) != NULL; mp = &m->rm_mklist) { if (m->rm_b < b_leaf) continue; if (m->rm_b > b_leaf) @@ -685,7 +742,8 @@ on2: tt->rn_mklist = m; return tt; } - if (rn_refines(netmask, mmask) || rn_lexobetter(netmask, mmask)) + if (rn_refines(netmask, mmask) + || rn_lexobetter(netmask, mmask)) break; } *mp = rn_new_radix_mask(tt, *mp); @@ -734,7 +792,7 @@ rn_delete(v_arg, netmask_arg, head) #endif return 0; /* dangling ref could cause disaster */ } - } else { + } else { if (m->rm_mask != tt->rn_mask) { #if 0 log(LOG_ERR, "rn_delete: inconsistent annotation\n"); @@ -752,7 +810,7 @@ rn_delete(v_arg, netmask_arg, head) x = t; t = t->rn_p; } while (b <= t->rn_b && x != top); - for (mp = &x->rn_mklist; ((m = *mp) != NULL); mp = &m->rm_mklist) + for (mp = &x->rn_mklist; (m = *mp) != NULL; mp = &m->rm_mklist) if (m == saved_m) { *mp = m->rm_mklist; MKFree(m); @@ -773,19 +831,24 @@ on1: return (0); #ifdef RN_DEBUG /* Get us out of the creation list */ - for (t = rn_clist; t && t->rn_ybro != tt; t = t->rn_ybro) {} + for (t = rn_clist; t && t->rn_ybro != tt; t = t->rn_ybro) + ; if (t) t->rn_ybro = tt->rn_ybro; #endif t = tt->rn_p; dupedkey = saved_tt->rn_dupedkey; if (dupedkey) { /* - * Here, tt is the deletion target, and + * Here, tt is the deletion target and * saved_tt is the head of the dupedkey chain. */ if (tt == saved_tt) { - x = dupedkey; x->rn_p = t; - if (t->rn_l == tt) t->rn_l = x; else t->rn_r = x; + x = dupedkey; + x->rn_p = t; + if (t->rn_l == tt) + t->rn_l = x; + else + t->rn_r = x; } else { /* find node in front of tt on the chain */ for (x = p = saved_tt; p && p->rn_dupedkey != tt;) @@ -803,25 +866,39 @@ on1: t = tt + 1; if (t->rn_flags & RNF_ACTIVE) { #ifndef RN_DEBUG - *++x = *t; p = t->rn_p; + *++x = *t; + p = t->rn_p; #else - b = t->rn_info; *++x = *t; t->rn_info = b; p = t->rn_p; + b = t->rn_info; + *++x = *t; + t->rn_info = b; + p = t->rn_p; #endif - if (p->rn_l == t) p->rn_l = x; else p->rn_r = x; - x->rn_l->rn_p = x; x->rn_r->rn_p = x; + if (p->rn_l == t) + p->rn_l = x; + else + p->rn_r = x; + x->rn_l->rn_p = x; + x->rn_r->rn_p = x; } goto out; } - if (t->rn_l == tt) x = t->rn_r; else x = t->rn_l; + if (t->rn_l == tt) + x = t->rn_r; + else + x = t->rn_l; p = t->rn_p; - if (p->rn_r == t) p->rn_r = x; else p->rn_l = x; + if (p->rn_r == t) + p->rn_r = x; + else + p->rn_l = x; x->rn_p = p; /* * Demote routes attached to us. */ if (t->rn_mklist) { if (x->rn_b >= 0) { - for (mp = &x->rn_mklist; ((m = *mp) != NULL);) + for (mp = &x->rn_mklist; (m = *mp) != NULL;) mp = &m->rm_mklist; *mp = t->rn_mklist; } else { @@ -851,11 +928,17 @@ on1: #ifndef RN_DEBUG *t = *x; #else - b = t->rn_info; *t = *x; t->rn_info = b; + b = t->rn_info; + *t = *x; + t->rn_info = b; #endif - t->rn_l->rn_p = t; t->rn_r->rn_p = t; + t->rn_l->rn_p = t; + t->rn_r->rn_p = t; p = x->rn_p; - if (p->rn_l == x) p->rn_l = t; else p->rn_r = t; + if (p->rn_l == x) + p->rn_l = t; + else + p->rn_r = t; } out: tt->rn_flags &= ~RNF_ACTIVE; @@ -892,7 +975,8 @@ rn_walktree(h, f, w) /* Process leaves */ while ((rn = base) != NULL) { base = rn->rn_dupedkey; - if (!(rn->rn_flags & RNF_ROOT) && (error = (*f)(rn, w))) + if (!(rn->rn_flags & RNF_ROOT) + && (error = (*f)(rn, w))) return (error); } rn = next; @@ -902,7 +986,6 @@ rn_walktree(h, f, w) /* NOTREACHED */ } - int rn_inithead(head, off) void **head; @@ -967,7 +1050,7 @@ rn_init() addmask_key = cplim = rn_ones + max_keylen; while (cp < cplim) *cp++ = -1; - if (rn_inithead((void **)&mask_rnhead, 0) == 0) + if (rn_inithead((void *)&mask_rnhead, 0) == 0) panic("rn_init 2"); } @@ -988,7 +1071,7 @@ rn_freenode(struct radix_node *n, void *p) void rn_freehead(rnh) - struct radix_node_head *rnh; + struct radix_node_head *rnh; { (void)rn_walktree(rnh, rn_freenode, rnh); @@ -1013,7 +1096,6 @@ rn_fini() rn_zeros = NULL; } - if (mask_rnhead != NULL) { rn_freehead(mask_rnhead); mask_rnhead = NULL; @@ -1039,7 +1121,7 @@ main(int argc, char *argv[]) { struct radix_node_head *rnh; struct radix_node *rn; - addrfamily_t af; + addrfamily_t af, mf; myst_t st1, st2, *stp; memset(&st1, 0, sizeof(st1)); @@ -1069,7 +1151,18 @@ main(int argc, char *argv[]) af.adf_addr.in4.s_addr = inet_addr("127.0.1.0"); rn = rnh->rnh_matchaddr(&af, rnh); if (rn != NULL) { - printf("lookup = %p key %p mask %p\n", rn, rn->rn_key, rn->rn_mask); + printf("1.lookup = %p key %p mask %p\n", rn, rn->rn_key, rn->rn_mask); + stp = rn->rn_key; + printf("%s/", inet_ntoa(stp->dst.adf_addr.in4)); + stp = rn->rn_mask; + printf("%s\n", inet_ntoa(stp->dst.adf_addr.in4)); + } + + mf.adf_len = sizeof(mf); + mf.adf_addr.in4.s_addr = inet_addr("255.255.255.0"); + rn = rnh->rnh_lookup(&af, &mf, rnh); + if (rn != NULL) { + printf("2.lookup = %p key %p mask %p\n", rn, rn->rn_key, rn->rn_mask); stp = rn->rn_key; printf("%s/", inet_ntoa(stp->dst.adf_addr.in4)); stp = rn->rn_mask; @@ -1080,7 +1173,7 @@ main(int argc, char *argv[]) af.adf_addr.in4.s_addr = inet_addr("126.0.0.1"); rn = rnh->rnh_matchaddr(&af, rnh); if (rn != NULL) { - printf("lookup = %p key %p mask %p\n", rn, rn->rn_key, rn->rn_mask); + printf("3.lookup = %p key %p mask %p\n", rn, rn->rn_key, rn->rn_mask); stp = rn->rn_key; printf("%s/", inet_ntoa(stp->dst.adf_addr.in4)); stp = rn->rn_mask; diff --git a/usr/src/common/ipf/radix.h b/usr/src/uts/common/inet/ipf/radix.h index 0b55412605..0b55412605 100644 --- a/usr/src/common/ipf/radix.h +++ b/usr/src/uts/common/inet/ipf/radix.h diff --git a/usr/src/uts/common/inet/ipf/radix_ipf.h b/usr/src/uts/common/inet/ipf/radix_ipf.h new file mode 100644 index 0000000000..357b9c40dc --- /dev/null +++ b/usr/src/uts/common/inet/ipf/radix_ipf.h @@ -0,0 +1,212 @@ +/* + * Copyright (c) 1988, 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)radix.h 8.2 (Berkeley) 10/31/94 + */ + +#if !defined(_NET_RADIX_H_) && !defined(_RADIX_H_) +#define _NET_RADIX_H_ +#ifndef _RADIX_H_ +#define _RADIX_H_ +#endif /* _RADIX_H_ */ + +#ifndef __P +# ifdef __STDC__ +# define __P(x) x +# else +# define __P(x) () +# endif +#endif + +#if defined(__sgi) +# define radix_mask ipf_radix_mask +# define radix_node ipf_radix_node +# define radix_node_head ipf_radix_node_head +#endif + +/* + * Radix search tree node layout. + */ + +struct radix_node { + struct radix_mask *rn_mklist; /* list of masks contained in subtree */ + struct radix_node *rn_p; /* parent */ + short rn_b; /* bit offset; -1-index(netmask) */ + char rn_bmask; /* node: mask for bit test*/ + u_char rn_flags; /* enumerated next */ +#define RNF_NORMAL 1 /* leaf contains normal route */ +#define RNF_ROOT 2 /* leaf is root leaf for tree */ +#define RNF_ACTIVE 4 /* This node is alive (for rtfree) */ + union { + struct { /* leaf only data: */ + caddr_t rn_Key; /* object of search */ + caddr_t rn_Mask; /* netmask, if present */ + struct radix_node *rn_Dupedkey; + } rn_leaf; + struct { /* node only data: */ + int rn_Off; /* where to start compare */ + struct radix_node *rn_L;/* progeny */ + struct radix_node *rn_R;/* progeny */ + } rn_node; + } rn_u; +#ifdef RN_DEBUG + int rn_info; + struct radix_node *rn_twin; + struct radix_node *rn_ybro; +#endif +}; + +#define rn_dupedkey rn_u.rn_leaf.rn_Dupedkey +#define rn_key rn_u.rn_leaf.rn_Key +#define rn_mask rn_u.rn_leaf.rn_Mask +#define rn_off rn_u.rn_node.rn_Off +#define rn_l rn_u.rn_node.rn_L +#define rn_r rn_u.rn_node.rn_R + +/* + * Annotations to tree concerning potential routes applying to subtrees. + */ + +struct radix_mask { + short rm_b; /* bit offset; -1-index(netmask) */ + char rm_unused; /* cf. rn_bmask */ + u_char rm_flags; /* cf. rn_flags */ + struct radix_mask *rm_mklist; /* more masks to try */ + union { + caddr_t rmu_mask; /* the mask */ + struct radix_node *rmu_leaf; /* for normal routes */ + } rm_rmu; + int rm_refs; /* # of references to this struct */ +}; + +#define rm_mask rm_rmu.rmu_mask +#define rm_leaf rm_rmu.rmu_leaf /* extra field would make 32 bytes */ + +#define MKGet(m) {\ + if (rn_mkfreelist) {\ + m = rn_mkfreelist; \ + rn_mkfreelist = (m)->rm_mklist; \ + } else \ + R_Malloc(m, struct radix_mask *, sizeof (*(m))); }\ + +#define MKFree(m) { (m)->rm_mklist = rn_mkfreelist; rn_mkfreelist = (m);} + +struct radix_node_head { + struct radix_node *rnh_treetop; + struct radix_node *rnh_leaflist; + u_long rnh_hits; + u_int rnh_number; + u_int rnh_ref; + int rnh_addrsize; /* permit, but not require fixed keys */ + int rnh_pktsize; /* permit, but not require fixed keys */ + struct radix_node *(*rnh_addaddr) /* add based on sockaddr */ + __P((void *v, void *mask, + struct radix_node_head *head, struct radix_node nodes[])); + struct radix_node *(*rnh_addpkt) /* add based on packet hdr */ + __P((void *v, void *mask, + struct radix_node_head *head, struct radix_node nodes[])); + struct radix_node *(*rnh_deladdr) /* remove based on sockaddr */ + __P((void *v, void *mask, struct radix_node_head *head)); + struct radix_node *(*rnh_delpkt) /* remove based on packet hdr */ + __P((void *v, void *mask, struct radix_node_head *head)); + struct radix_node *(*rnh_matchaddr) /* locate based on sockaddr */ + __P((void *v, struct radix_node_head *head)); + struct radix_node *(*rnh_lookup) /* locate based on sockaddr */ + __P((void *v, void *mask, struct radix_node_head *head)); + struct radix_node *(*rnh_matchpkt) /* locate based on packet hdr */ + __P((void *v, struct radix_node_head *head)); + int (*rnh_walktree) /* traverse tree */ + __P((struct radix_node_head *, + int (*)(struct radix_node *, void *), void *)); + struct radix_node rnh_nodes[3]; /* empty tree for common case */ +}; + + +#if defined(AIX) +# undef Bcmp +# undef Bzero +# undef R_Malloc +# undef Free +#endif +#define Bcmp(a, b, n) bcmp(((caddr_t)(a)), ((caddr_t)(b)), (unsigned)(n)) +#if defined(linux) && defined(_KERNEL) +# define Bcopy(a, b, n) memmove(((caddr_t)(b)), ((caddr_t)(a)), (unsigned)(n)) +#else +# define Bcopy(a, b, n) bcopy(((caddr_t)(a)), ((caddr_t)(b)), (unsigned)(n)) +#endif +#define Bzero(p, n) bzero((caddr_t)(p), (unsigned)(n)); +#define R_Malloc(p, t, n) KMALLOCS(p, t, n) +#define FreeS(p, z) KFREES(p, z) +#define Free(p) KFREE(p) + +#if (defined(__osf__) || defined(AIX) || (IRIX >= 60516)) && defined(_KERNEL) +# define rn_init ipf_rn_init +# define rn_fini ipf_rn_fini +# define rn_inithead ipf_rn_inithead +# define rn_freehead ipf_rn_freehead +# define rn_inithead0 ipf_rn_inithead0 +# define rn_refines ipf_rn_refines +# define rn_walktree ipf_rn_walktree +# define rn_addmask ipf_rn_addmask +# define rn_addroute ipf_rn_addroute +# define rn_delete ipf_rn_delete +# define rn_insert ipf_rn_insert +# define rn_lookup ipf_rn_lookup +# define rn_match ipf_rn_match +# define rn_newpair ipf_rn_newpair +# define rn_search ipf_rn_search +# define rn_search_m ipf_rn_search_m +# define max_keylen ipf_maxkeylen +# define rn_mkfreelist ipf_rn_mkfreelist +# define rn_zeros ipf_rn_zeros +# define rn_ones ipf_rn_ones +# define rn_satisfies_leaf ipf_rn_satisfies_leaf +# define rn_lexobetter ipf_rn_lexobetter +# define rn_new_radix_mask ipf_rn_new_radix_mask +# define rn_freenode ipf_rn_freenode +#endif + +void rn_init __P((void)); +void rn_fini __P((void)); +int rn_inithead __P((void **, int)); +void rn_freehead __P((struct radix_node_head *)); +int rn_inithead0 __P((struct radix_node_head *, int)); +int rn_refines __P((void *, void *)); +int rn_walktree __P((struct radix_node_head *, + int (*)(struct radix_node *, void *), void *)); +struct radix_node + *rn_addmask __P((void *, int, int)), + *rn_addroute __P((void *, void *, struct radix_node_head *, + struct radix_node [2])), + *rn_delete __P((void *, void *, struct radix_node_head *)), + *rn_insert __P((void *, struct radix_node_head *, int *, + struct radix_node [2])), + *rn_lookup __P((void *, void *, struct radix_node_head *)), + *rn_match __P((void *, struct radix_node_head *)), + *rn_newpair __P((void *, int, struct radix_node[2])), + *rn_search __P((void *, struct radix_node *)), + *rn_search_m __P((void *, struct radix_node *, void *)); + +#endif /* _NET_RADIX_H_ */ diff --git a/usr/src/uts/common/inet/ipf/solaris.c b/usr/src/uts/common/inet/ipf/solaris.c new file mode 100644 index 0000000000..0c21d1f15f --- /dev/null +++ b/usr/src/uts/common/inet/ipf/solaris.c @@ -0,0 +1,696 @@ +/* + * Copyright (C) 1993-2001, 2003 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ +/* #pragma ident "@(#)solaris.c 1.12 6/5/96 (C) 1995 Darren Reed"*/ +#pragma ident "@(#)$Id: solaris.c,v 2.73.2.6 2005/07/13 21:40:47 darrenr Exp $" + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <sys/systm.h> +#include <sys/types.h> +#include <sys/param.h> +#include <sys/errno.h> +#include <sys/uio.h> +#include <sys/buf.h> +#include <sys/modctl.h> +#include <sys/open.h> +#include <sys/kmem.h> +#include <sys/conf.h> +#include <sys/cmn_err.h> +#include <sys/stat.h> +#include <sys/cred.h> +#include <sys/dditypes.h> +#include <sys/stream.h> +#include <sys/poll.h> +#include <sys/autoconf.h> +#include <sys/byteorder.h> +#include <sys/socket.h> +#include <sys/dlpi.h> +#include <sys/stropts.h> +#include <sys/kstat.h> +#include <sys/sockio.h> +#include <net/if.h> +#if SOLARIS2 >= 6 +# include <net/if_types.h> +#endif +#include <net/af.h> +#include <net/route.h> +#include <netinet/in.h> +#include <netinet/in_systm.h> +#include <netinet/if_ether.h> +#include <netinet/ip.h> +#include <netinet/ip_var.h> +#include <netinet/tcp.h> +#include <netinet/udp.h> +#include <netinet/tcpip.h> +#include <netinet/ip_icmp.h> +#include <sys/ddi.h> +#include <sys/sunddi.h> +#include "netinet/ip_compat.h" +#include "netinet/ipl.h" +#include "netinet/ip_fil.h" +#include "netinet/ip_nat.h" +#include "netinet/ip_frag.h" +#include "netinet/ip_auth.h" +#include "netinet/ip_state.h" + + +extern struct filterstats frstats[]; +extern int fr_running; +extern int fr_flags; +extern int iplwrite __P((dev_t, struct uio *, cred_t *)); + +extern ipnat_t *nat_list; + +static int ipf_getinfo __P((dev_info_t *, ddi_info_cmd_t, + void *, void **)); +#if SOLARIS2 < 10 +static int ipf_identify __P((dev_info_t *)); +#endif +static int ipf_attach __P((dev_info_t *, ddi_attach_cmd_t)); +static int ipf_detach __P((dev_info_t *, ddi_detach_cmd_t)); +static int fr_qifsync __P((ip_t *, int, void *, int, void *, mblk_t **)); +static int ipf_property_update __P((dev_info_t *)); +static char *ipf_devfiles[] = { IPL_NAME, IPNAT_NAME, IPSTATE_NAME, + IPAUTH_NAME, IPSYNC_NAME, IPSCAN_NAME, + IPLOOKUP_NAME, NULL }; + + +#if SOLARIS2 >= 7 +extern timeout_id_t fr_timer_id; +#else +extern int fr_timer_id; +#endif + +static struct cb_ops ipf_cb_ops = { + iplopen, + iplclose, + nodev, /* strategy */ + nodev, /* print */ + nodev, /* dump */ + iplread, + iplwrite, /* write */ + iplioctl, /* ioctl */ + nodev, /* devmap */ + nodev, /* mmap */ + nodev, /* segmap */ + nochpoll, /* poll */ + ddi_prop_op, + NULL, + D_MTSAFE, +#if SOLARIS2 > 4 + CB_REV, + nodev, /* aread */ + nodev, /* awrite */ +#endif +}; + +static struct dev_ops ipf_ops = { + DEVO_REV, + 0, + ipf_getinfo, +#if SOLARIS2 >= 10 + nulldev, +#else + ipf_identify, +#endif + nulldev, + ipf_attach, + ipf_detach, + nodev, /* reset */ + &ipf_cb_ops, + (struct bus_ops *)0 +}; + +extern struct mod_ops mod_driverops; +static struct modldrv iplmod = { + &mod_driverops, IPL_VERSION, &ipf_ops }; +static struct modlinkage modlink1 = { MODREV_1, &iplmod, NULL }; + +#if SOLARIS2 >= 6 +static size_t hdrsizes[57][2] = { + { 0, 0 }, + { IFT_OTHER, 0 }, + { IFT_1822, 0 }, + { IFT_HDH1822, 0 }, + { IFT_X25DDN, 0 }, + { IFT_X25, 0 }, + { IFT_ETHER, 14 }, + { IFT_ISO88023, 0 }, + { IFT_ISO88024, 0 }, + { IFT_ISO88025, 0 }, + { IFT_ISO88026, 0 }, + { IFT_STARLAN, 0 }, + { IFT_P10, 0 }, + { IFT_P80, 0 }, + { IFT_HY, 0 }, + { IFT_FDDI, 24 }, + { IFT_LAPB, 0 }, + { IFT_SDLC, 0 }, + { IFT_T1, 0 }, + { IFT_CEPT, 0 }, + { IFT_ISDNBASIC, 0 }, + { IFT_ISDNPRIMARY, 0 }, + { IFT_PTPSERIAL, 0 }, + { IFT_PPP, 0 }, + { IFT_LOOP, 0 }, + { IFT_EON, 0 }, + { IFT_XETHER, 0 }, + { IFT_NSIP, 0 }, + { IFT_SLIP, 0 }, + { IFT_ULTRA, 0 }, + { IFT_DS3, 0 }, + { IFT_SIP, 0 }, + { IFT_FRELAY, 0 }, + { IFT_RS232, 0 }, + { IFT_PARA, 0 }, + { IFT_ARCNET, 0 }, + { IFT_ARCNETPLUS, 0 }, + { IFT_ATM, 0 }, + { IFT_MIOX25, 0 }, + { IFT_SONET, 0 }, + { IFT_X25PLE, 0 }, + { IFT_ISO88022LLC, 0 }, + { IFT_LOCALTALK, 0 }, + { IFT_SMDSDXI, 0 }, + { IFT_FRELAYDCE, 0 }, + { IFT_V35, 0 }, + { IFT_HSSI, 0 }, + { IFT_HIPPI, 0 }, + { IFT_MODEM, 0 }, + { IFT_AAL5, 0 }, + { IFT_SONETPATH, 0 }, + { IFT_SONETVT, 0 }, + { IFT_SMDSICIP, 0 }, + { IFT_PROPVIRTUAL, 0 }, + { IFT_PROPMUX, 0 }, +}; +#endif /* SOLARIS2 >= 6 */ + +static dev_info_t *ipf_dev_info = NULL; + +static const filter_kstats_t ipf_kstat_tmp = { + { "pass", KSTAT_DATA_ULONG }, + { "block", KSTAT_DATA_ULONG }, + { "nomatch", KSTAT_DATA_ULONG }, + { "short", KSTAT_DATA_ULONG }, + { "pass, logged", KSTAT_DATA_ULONG }, + { "block, logged", KSTAT_DATA_ULONG }, + { "nomatch, logged", KSTAT_DATA_ULONG }, + { "logged", KSTAT_DATA_ULONG }, + { "skip", KSTAT_DATA_ULONG }, + { "return sent", KSTAT_DATA_ULONG }, + { "acct", KSTAT_DATA_ULONG }, + { "bad frag state alloc", KSTAT_DATA_ULONG }, + { "new frag state kept", KSTAT_DATA_ULONG }, + { "new frag state compl. pkt", KSTAT_DATA_ULONG }, + { "bad pkt state alloc", KSTAT_DATA_ULONG }, + { "new pkt kept state", KSTAT_DATA_ULONG }, + { "cachehit", KSTAT_DATA_ULONG }, + { "tcp cksum bad", KSTAT_DATA_ULONG }, + {{ "pullup ok", KSTAT_DATA_ULONG }, + { "pullup nok", KSTAT_DATA_ULONG }}, + { "src != route", KSTAT_DATA_ULONG }, + { "ttl invalid", KSTAT_DATA_ULONG }, + { "bad ip pkt", KSTAT_DATA_ULONG }, + { "ipv6 pkt", KSTAT_DATA_ULONG }, + { "dropped:pps ceiling", KSTAT_DATA_ULONG }, + { "ip upd. fail", KSTAT_DATA_ULONG } +}; + +kstat_t *ipf_kstatp[2] = {NULL, NULL}; +static int ipf_kstat_update(kstat_t *ksp, int rwflag); + +static void +ipf_kstat_init(void) +{ + int i; + + for (i = 0; i < 2; i++) { + ipf_kstatp[i] = kstat_create("ipf", 0, + (i==0)?"inbound":"outbound", + "net", + KSTAT_TYPE_NAMED, + sizeof (filter_kstats_t) / sizeof (kstat_named_t), + 0); + if (ipf_kstatp[i] != NULL) { + bcopy(&ipf_kstat_tmp, ipf_kstatp[i]->ks_data, + sizeof (filter_kstats_t)); + ipf_kstatp[i]->ks_update = ipf_kstat_update; + ipf_kstatp[i]->ks_private = &frstats[i]; + kstat_install(ipf_kstatp[i]); + } + } + +#ifdef IPFDEBUG + cmn_err(CE_NOTE, "IP Filter: ipf_kstat_init() installed 0x%x, 0x%x", + ipf_kstatp[0], ipf_kstatp[1]); +#endif +} + +static void +ipf_kstat_fini(void) +{ + int i; + for (i = 0; i < 2; i++) { + if (ipf_kstatp[i] != NULL) { + kstat_delete(ipf_kstatp[i]); + ipf_kstatp[i] = NULL; + } + } +} + +static int +ipf_kstat_update(kstat_t *ksp, int rwflag) +{ + filter_kstats_t *fkp; + filterstats_t *fsp; + + if (rwflag == KSTAT_WRITE) + return (EACCES); + + fkp = ksp->ks_data; + fsp = ksp->ks_private; + + fkp->fks_pass.value.ul = fsp->fr_pass; + fkp->fks_block.value.ul = fsp->fr_block; + fkp->fks_nom.value.ul = fsp->fr_nom; + fkp->fks_short.value.ul = fsp->fr_short; + fkp->fks_ppkl.value.ul = fsp->fr_ppkl; + fkp->fks_bpkl.value.ul = fsp->fr_bpkl; + fkp->fks_npkl.value.ul = fsp->fr_npkl; + fkp->fks_pkl.value.ul = fsp->fr_pkl; + fkp->fks_skip.value.ul = fsp->fr_skip; + fkp->fks_ret.value.ul = fsp->fr_ret; + fkp->fks_acct.value.ul = fsp->fr_acct; + fkp->fks_bnfr.value.ul = fsp->fr_bnfr; + fkp->fks_nfr.value.ul = fsp->fr_nfr; + fkp->fks_cfr.value.ul = fsp->fr_cfr; + fkp->fks_bads.value.ul = fsp->fr_bads; + fkp->fks_ads.value.ul = fsp->fr_ads; + fkp->fks_chit.value.ul = fsp->fr_chit; + fkp->fks_tcpbad.value.ul = fsp->fr_tcpbad; + fkp->fks_pull[0].value.ul = fsp->fr_pull[0]; + fkp->fks_pull[1].value.ul = fsp->fr_pull[1]; + fkp->fks_badsrc.value.ul = fsp->fr_badsrc; + fkp->fks_badttl.value.ul = fsp->fr_badttl; + fkp->fks_bad.value.ul = fsp->fr_bad; + fkp->fks_ipv6.value.ul = fsp->fr_ipv6; + fkp->fks_ppshit.value.ul = fsp->fr_ppshit; + fkp->fks_ipud.value.ul = fsp->fr_ipud; + + return (0); +} + +int _init() +{ + int ipfinst; + + ipf_kstat_init(); + ipfinst = mod_install(&modlink1); + if (ipfinst != 0) + ipf_kstat_fini(); +#ifdef IPFDEBUG + cmn_err(CE_NOTE, "IP Filter: _init() = %d", ipfinst); +#endif + return ipfinst; +} + + +int _fini(void) +{ + int ipfinst; + + ipfinst = mod_remove(&modlink1); +#ifdef IPFDEBUG + cmn_err(CE_NOTE, "IP Filter: _fini() = %d", ipfinst); +#endif + if (ipfinst == 0) + ipf_kstat_fini(); + return ipfinst; +} + + +int _info(modinfop) +struct modinfo *modinfop; +{ + int ipfinst; + + ipfinst = mod_info(&modlink1, modinfop); +#ifdef IPFDEBUG + cmn_err(CE_NOTE, "IP Filter: _info(%x) = %x", modinfop, ipfinst); +#endif + return ipfinst; +} + + +#if SOLARIS2 < 10 +static int ipf_identify(dip) +dev_info_t *dip; +{ +# ifdef IPFDEBUG + cmn_err(CE_NOTE, "IP Filter: ipf_identify(%x)", dip); +# endif + if (strcmp(ddi_get_name(dip), "ipf") == 0) + return (DDI_IDENTIFIED); + return (DDI_NOT_IDENTIFIED); +} +#endif + + +static int ipf_attach(dip, cmd) +dev_info_t *dip; +ddi_attach_cmd_t cmd; +{ + char *s; + int i; + int instance; + +#ifdef IPFDEBUG + cmn_err(CE_NOTE, "IP Filter: ipf_attach(%x,%x)", dip, cmd); +#endif + + if ((pfilinterface != PFIL_INTERFACE) || (PFIL_INTERFACE < 2000000)) { + cmn_err(CE_NOTE, "pfilinterface(%d) != %d\n", pfilinterface, + PFIL_INTERFACE); + return EINVAL; + } + + switch (cmd) + { + case DDI_ATTACH: + instance = ddi_get_instance(dip); + /* Only one instance of ipf (instance 0) can be attached. */ + if (instance > 0) + return DDI_FAILURE; + if (fr_running != 0) + return DDI_FAILURE; + +#ifdef IPFDEBUG + cmn_err(CE_NOTE, "IP Filter: attach ipf instance %d", instance); +#endif + + (void) ipf_property_update(dip); + + for (i = 0; ((s = ipf_devfiles[i]) != NULL); i++) { + s = strrchr(s, '/'); + if (s == NULL) + continue; + s++; + if (ddi_create_minor_node(dip, s, S_IFCHR, i, + DDI_PSEUDO, 0) == + DDI_FAILURE) { + ddi_remove_minor_node(dip, NULL); + goto attach_failed; + } + } + + ipf_dev_info = dip; + /* + * Initialize mutex's + */ + RWLOCK_INIT(&ipf_global, "ipf filter load/unload mutex"); + RWLOCK_INIT(&ipf_mutex, "ipf filter rwlock"); + RWLOCK_INIT(&ipf_frcache, "ipf cache rwlock"); + + /* + * Lock people out while we set things up. + */ + WRITE_ENTER(&ipf_global); + if ((fr_running != 0) || (iplattach() == -1)) { + RWLOCK_EXIT(&ipf_global); + goto attach_failed; + } + + if (pfil_add_hook(fr_check, PFIL_IN|PFIL_OUT, &pfh_inet4)) + cmn_err(CE_WARN, "IP Filter: %s(pfh_inet4) failed", + "pfil_add_hook"); +#ifdef USE_INET6 + if (pfil_add_hook(fr_check, PFIL_IN|PFIL_OUT, &pfh_inet6)) + cmn_err(CE_WARN, "IP Filter: %s(pfh_inet6) failed", + "pfil_add_hook"); +#endif + if (pfil_add_hook(fr_qifsync, PFIL_IN|PFIL_OUT, &pfh_sync)) + cmn_err(CE_WARN, "IP Filter: %s(pfh_sync) failed", + "pfil_add_hook"); + + fr_timer_id = timeout(fr_slowtimer, NULL, + drv_usectohz(500000)); + + fr_running = 1; + + RWLOCK_EXIT(&ipf_global); + + cmn_err(CE_CONT, "!%s, running.\n", ipfilter_version); + + return DDI_SUCCESS; + /* NOTREACHED */ + default: + break; + } + +attach_failed: +#ifdef IPFDEBUG + cmn_err(CE_NOTE, "IP Filter: failed to attach\n"); +#endif + /* + * Use our own detach routine to toss + * away any stuff we allocated above. + */ + (void) ipf_detach(dip, DDI_DETACH); + return DDI_FAILURE; +} + + +static int ipf_detach(dip, cmd) +dev_info_t *dip; +ddi_detach_cmd_t cmd; +{ + int i; + +#ifdef IPFDEBUG + cmn_err(CE_NOTE, "IP Filter: ipf_detach(%x,%x)", dip, cmd); +#endif + switch (cmd) { + case DDI_DETACH: + if (fr_refcnt != 0) + return DDI_FAILURE; + + if (fr_running == -2 || fr_running == 0) + break; + /* + * Make sure we're the only one's modifying things. With + * this lock others should just fall out of the loop. + */ + WRITE_ENTER(&ipf_global); + if (fr_running <= 0) { + RWLOCK_EXIT(&ipf_global); + return DDI_FAILURE; + } + fr_running = -2; + + if (pfil_remove_hook(fr_check, PFIL_IN|PFIL_OUT, &pfh_inet4)) + cmn_err(CE_WARN, "IP Filter: %s(pfh_inet4) failed", + "pfil_remove_hook"); +#ifdef USE_INET6 + if (pfil_remove_hook(fr_check, PFIL_IN|PFIL_OUT, &pfh_inet6)) + cmn_err(CE_WARN, "IP Filter: %s(pfh_inet6) failed", + "pfil_add_hook"); +#endif + if (pfil_remove_hook(fr_qifsync, PFIL_IN|PFIL_OUT, &pfh_sync)) + cmn_err(CE_WARN, "IP Filter: %s(pfh_sync) failed", + "pfil_remove_hook"); + + RWLOCK_EXIT(&ipf_global); + + if (fr_timer_id != 0) { + (void) untimeout(fr_timer_id); + fr_timer_id = 0; + } + + /* + * Undo what we did in ipf_attach, freeing resources + * and removing things we installed. The system + * framework guarantees we are not active with this devinfo + * node in any other entry points at this time. + */ + ddi_prop_remove_all(dip); + i = ddi_get_instance(dip); + ddi_remove_minor_node(dip, NULL); + if (i > 0) { + cmn_err(CE_CONT, "IP Filter: still attached (%d)\n", i); + return DDI_FAILURE; + } + + WRITE_ENTER(&ipf_global); + if (!ipldetach()) { + RWLOCK_EXIT(&ipf_global); + RW_DESTROY(&ipf_mutex); + RW_DESTROY(&ipf_frcache); + RW_DESTROY(&ipf_global); + cmn_err(CE_CONT, "!%s detached.\n", ipfilter_version); + return (DDI_SUCCESS); + } + RWLOCK_EXIT(&ipf_global); + break; + default: + break; + } + cmn_err(CE_NOTE, "IP Filter: failed to detach\n"); + return DDI_FAILURE; +} + + +/*ARGSUSED*/ +static int ipf_getinfo(dip, infocmd, arg, result) +dev_info_t *dip; +ddi_info_cmd_t infocmd; +void *arg, **result; +{ + int error; + + if (fr_running <= 0) + return DDI_FAILURE; + error = DDI_FAILURE; +#ifdef IPFDEBUG + cmn_err(CE_NOTE, "IP Filter: ipf_getinfo(%x,%x,%x)", dip, infocmd, arg); +#endif + switch (infocmd) { + case DDI_INFO_DEVT2DEVINFO: + *result = ipf_dev_info; + error = DDI_SUCCESS; + break; + case DDI_INFO_DEVT2INSTANCE: + *result = (void *)0; + error = DDI_SUCCESS; + break; + default: + break; + } + return (error); +} + + +/* + * look for bad consistancies between the list of interfaces the filter knows + * about and those which are currently configured. + */ +/*ARGSUSED*/ +static int fr_qifsync(ip, hlen, il, out, qif, mp) +ip_t *ip; +int hlen; +void *il; +int out; +void *qif; +mblk_t **mp; +{ + + frsync(qif); + /* + * Resync. any NAT `connections' using this interface and its IP #. + */ + fr_natsync(qif); + fr_statesync(qif); + return 0; +} + + +/* + * look for bad consistancies between the list of interfaces the filter knows + * about and those which are currently configured. + */ +int ipfsync() +{ + frsync(NULL); + return 0; +} + + +/* + * Fetch configuration file values that have been entered into the ipf.conf + * driver file. + */ +static int ipf_property_update(dip) +dev_info_t *dip; +{ + ipftuneable_t *ipft; + int64_t *i64p; + char *name; + u_int one; + int *i32p; + int err; + +#ifdef DDI_NO_AUTODETACH + if (ddi_prop_update_int(DDI_DEV_T_NONE, dip, + DDI_NO_AUTODETACH, 1) != DDI_PROP_SUCCESS) { + cmn_err(CE_WARN, "!updating DDI_NO_AUTODETACH failed"); + return DDI_FAILURE; + } +#else + if (ddi_prop_update_int(DDI_DEV_T_NONE, dip, + "ddi-no-autodetach", 1) != DDI_PROP_SUCCESS) { + cmn_err(CE_WARN, "!updating ddi-no-autodetach failed"); + return DDI_FAILURE; + } +#endif + + err = DDI_SUCCESS; + ipft = ipf_tuneables; + for (ipft = ipf_tuneables; (name = ipft->ipft_name) != NULL; ipft++) { + one = 1; + switch (ipft->ipft_sz) + { + case 4 : + i32p = NULL; + err = ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip, + 0, name, &i32p, &one); + if (err == DDI_PROP_NOT_FOUND) + continue; +#ifdef IPFDEBUG + cmn_err(CE_CONT, "IP Filter: lookup_int(%s) = %d\n", + name, err); +#endif + if (err != DDI_PROP_SUCCESS) + return err; + if (*i32p >= ipft->ipft_min && *i32p <= ipft->ipft_max) + *ipft->ipft_pint = *i32p; + else + err = DDI_PROP_CANNOT_DECODE; + ddi_prop_free(i32p); + break; + +#if SOLARIS2 > 8 + case 8 : + i64p = NULL; + err = ddi_prop_lookup_int64_array(DDI_DEV_T_ANY, dip, + 0, name, &i64p, &one); + if (err == DDI_PROP_NOT_FOUND) + continue; +# ifdef IPFDEBUG + cmn_err(CE_CONT, "IP Filter: lookup_int64(%s) = %d\n", + name, err); +# endif + if (err != DDI_PROP_SUCCESS) + return err; + if (*i64p >= ipft->ipft_min && *i64p <= ipft->ipft_max) + *ipft->ipft_pint = *i64p; + else + err = DDI_PROP_CANNOT_DECODE; + ddi_prop_free(i64p); + break; +#endif + + default : + break; + } + if (err != DDI_SUCCESS) + break; + } + + return err; +} diff --git a/usr/src/uts/common/inet/ipf/compat.h b/usr/src/uts/common/inet/pfil/compat.h index 776dd8d0c6..ddaa3354e2 100644 --- a/usr/src/uts/common/inet/ipf/compat.h +++ b/usr/src/uts/common/inet/pfil/compat.h @@ -3,7 +3,6 @@ * * See the IPFILTER.LICENCE file for details on licencing. */ - #ifdef DEBUG # define PFILDEBUG #endif @@ -42,3 +41,38 @@ # define ASSERT(x) #endif +/* + * The list of SAPs below all come from Sun's <atm/iftypes.h> file. It's not + * yet clear whether pfil should deal with any of these or not. + */ +#ifndef IFMP_SAP +# define IFMP_SAP 0x0065 +#endif + +#ifndef LANER_SAP +# define LANER_SAP 0x9999 +#endif + +#ifndef SNMP_SAP +# define SNMP_SAP 0x999a +#endif + +#ifndef ILMI_SAP +# define ILMI_SAP 0x999b +#endif + +#ifndef SIG_SAP +# define SIG_SAP 0x999c +#endif + +#ifndef Q93B_MGMT_SAP +# define Q93B_MGMT_SAP 0x999d +#endif + +#ifndef UTIL_SAP +# define UTIL_SAP 0x999e +#endif + +#ifndef ERROR_SAP +# define ERROR_SAP 0x999f +#endif diff --git a/usr/src/uts/common/inet/ipf/misc.c b/usr/src/uts/common/inet/pfil/misc.c index b65ca63837..2a8c84dd4c 100644 --- a/usr/src/uts/common/inet/ipf/misc.c +++ b/usr/src/uts/common/inet/pfil/misc.c @@ -1,8 +1,10 @@ /* - * Copyright (C) 2000 by Darren Reed. + * Copyright (C) 2003 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. */ #ifndef __hpux -#pragma ident "@(#)$Id: misc.c,v 1.9 2003/07/20 15:36:27 darrenr Exp $" +#pragma ident "@(#)$Id: misc.c,v 1.12 2003/11/29 07:11:03 darrenr Exp $" #else struct uio; #endif diff --git a/usr/src/uts/common/inet/ipf/ndd.c b/usr/src/uts/common/inet/pfil/ndd.c index c733a1d162..ce85cc0091 100644 --- a/usr/src/uts/common/inet/ipf/ndd.c +++ b/usr/src/uts/common/inet/pfil/ndd.c @@ -3,7 +3,7 @@ * * See the IPFILTER.LICENCE file for details on licencing. * - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -30,13 +30,15 @@ static int qif_report(queue_t *, mblk_t *, caddr_t); static int sill_report(queue_t *, mblk_t *, caddr_t); static int qif_ipmp_report(queue_t *, mblk_t *, caddr_t); static int qif_ipmp_set(queue_t *, mblk_t *, char *, caddr_t); +static int pfil_hl_set(queue_t *, mblk_t *, char *, caddr_t); extern int pfil_report(queue_t *, mblk_t *, caddr_t); #else static int qif_report(queue_t *, mblk_t *, caddr_t, cred_t *); static int sill_report(queue_t *, mblk_t *, caddr_t, cred_t *); static int qif_ipmp_report(queue_t *, mblk_t *, caddr_t, cred_t *); -static int qif_ipmp_set(queue_t *, mblk_t *, char *, caddr_t, cred_t *); +static int qif_ipmp_set(queue_t *, mblk_t *, char *, caddr_t , cred_t *); +static int pfil_hl_set(queue_t *, mblk_t *, char *, caddr_t , cred_t *); extern int pfil_report(queue_t *, mblk_t *, caddr_t, cred_t *); #endif @@ -101,16 +103,24 @@ int pfil_nd_set(queue_t *q, mblk_t *mp, char *str, caddr_t ptr, cred_t *cred) (void *)q, (void *)mp, str, (void *)str, (void *)ptr)); +#if (SOLARIS2 >= 10) if (ddi_strtol(str, &end, 10, &i) != 0) return (EINVAL); - +#else + i = mi_strtol(str, &end, 10); +#endif + if (ptr == (caddr_t)&pfildebug) { #ifdef PFILDEBUG +#if (SOLARIS2 >= 10) if ((end == str) || (i < 0) || (i > 100)) +#else + if (i < 0 || i > 1) +#endif #endif return EINVAL; } else if (ptr == (caddr_t)&qif_verbose) { - if (i < 0 || i > 1) + if ((end == str) || (i < 0) || (i > 1)) return EINVAL; } *((int *)ptr) = i; @@ -122,7 +132,7 @@ int pfil_nd_set(queue_t *q, mblk_t *mp, char *str, caddr_t ptr, cred_t *cred) /* ------------------------------------------------------------------------ */ /* Function: pfil_ioctl_nd */ -/* Returns: int - B_TRUE == success, B_FALSE == getset error */ +/* Returns: int - B_TRUE == success, B_FALSE == getset error */ /* Parameters: q(I) - pointer to queue */ /* mp(I) - pointer to mblk */ /* */ @@ -146,11 +156,13 @@ int pfil_ioctl_nd(queue_t *q, mblk_t *mp) int pfil_nd_init() { +#ifdef PFILDEBUG if (!nd_load(&pfil_nd, "pfildebug", pfil_nd_get, pfil_nd_set, (caddr_t)&pfildebug)) { nd_free(&pfil_nd); return -1; } +#endif if (!nd_load(&pfil_nd, "pfil_delayed_copy", pfil_nd_get, pfil_nd_set, (caddr_t)&pfil_delayed_copy)) { @@ -209,6 +221,11 @@ int pfil_nd_init() return -1; } + if (!nd_load(&pfil_nd, "pfil_hl", NULL, pfil_hl_set, NULL)) { + nd_free(&pfil_nd); + return -1; + } + return 0; } @@ -267,6 +284,7 @@ static int qif_report(queue_t *q, mblk_t *mp, caddr_t arg, cred_t *cred) } + /* ------------------------------------------------------------------------ */ /* Function: sill_report */ /* Returns: int */ @@ -303,6 +321,7 @@ static int sill_report(queue_t *q, mblk_t *mp, caddr_t arg, cred_t *cred) return 0; } + /* ------------------------------------------------------------------------ */ /* Function: qif_ipmp_report */ /* Returns: int */ @@ -378,3 +397,46 @@ static int qif_ipmp_set(queue_t *q, mblk_t *mp, char *str, caddr_t ptr, return 0; } + +/* ------------------------------------------------------------------------ */ +/* Function: pfil_hl_set */ +/* Returns: int - 0 == success, > 0 error occurred */ +/* Parameters: q(I) - pointer to queue */ +/* mp(I) - pointer to mblk */ +/* str(I) - pointer to new value as a string */ +/* ptr(I) - pointer to value to be stored */ +/* cred(I) - pointer to credential information */ +/* */ +/* Explicitly set the header length (hl) field of the qif structure. This */ +/* is used in situations where pfil cannot, for some reason, automatically */ +/* determine it via either ioctl snooping or looking at passing messages. */ +/* ndd -set /dev/pfil pfil_hl ipmp0=14 or v4:ipmp0=14 */ +/* ------------------------------------------------------------------------ */ +#if !defined(sun) || SOLARIS2 <= 8 +/*ARGSUSED*/ +static int pfil_hl_set(queue_t *q, mblk_t *mp, char *str, caddr_t ptr) +#else +/*ARGSUSED*/ +static int pfil_hl_set(queue_t *q, mblk_t *mp, char *str, caddr_t ptr, + cred_t *cred) +#endif +{ + char *s, *t; + + /* LINTED: E_CONSTANT_CONDITION */ + PRINT(2, (CE_CONT, "pfil_hl_set(0x%lx,0x%lx,0x%lx[%s],0x%lx)\n", + (u_long)q, (u_long)mp, (u_long)str, str, (u_long)ptr)); + + t = NULL; + s = str; + do { + if (t != NULL) + s = t + 1; + t = strchr(s, ';'); + if (t != NULL) + *t = '\0'; + qif_hl_set(s); + } while (t != NULL); + + return 0; +} diff --git a/usr/src/uts/common/inet/ipf/os.h b/usr/src/uts/common/inet/pfil/os.h index f0c8e7502a..b7a77e130e 100644 --- a/usr/src/uts/common/inet/ipf/os.h +++ b/usr/src/uts/common/inet/pfil/os.h @@ -1,3 +1,8 @@ +/* + * Copyright (C) 2003 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + */ #include <sys/sunddi.h> #include <sys/ddi.h> #if SOLARIS2 >= 6 @@ -28,3 +33,8 @@ #define KMFREE(v, z) kmem_free(v, z) extern caddr_t pfil_nd; + +#if defined(atomic_add_long) && (SOLARIS2 < 7) +# undef atomic_add_long +# define atomic_add_long(x,y) atomic_add_32((uint32_t *)x, y) +#endif diff --git a/usr/src/uts/common/inet/ipf/pfil.c b/usr/src/uts/common/inet/pfil/pfil.c index a42055d693..d44f1ac5bc 100644 --- a/usr/src/uts/common/inet/ipf/pfil.c +++ b/usr/src/uts/common/inet/pfil/pfil.c @@ -3,12 +3,11 @@ * * See the IPFILTER.LICENCE file for details on licencing. * - * ident "@(#)$Id: pfil.c,v 1.22 2003/08/18 22:13:59 darrenr Exp $" + * ident "@(#)$Id: pfil.c,v 1.27 2003/11/30 09:45:57 darrenr Exp $" * - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ - #ifndef __hpux #pragma ident "%Z%%M% %I% %E% SMI" #else @@ -80,11 +79,11 @@ struct pfil_head pfh_sync; static int pfil_list_add(pfil_list_t *, int (*) __P((struct ip *, int, void *, int, - struct qif *, mblk_t **)), + void *, mblk_t **)), int); static int pfil_list_remove(pfil_list_t *, int (*) __P((struct ip *, int, void *, int, - struct qif *, mblk_t **))); + void *, mblk_t **))); /* ------------------------------------------------------------------------ */ @@ -116,14 +115,14 @@ int pfil_report(queue_t *q, mblk_t *mp, caddr_t arg, cred_t *cred) (void) mi_mpprintf(mp, "in"); (void) mi_mpprintf(mp, "function\tflags"); for (p = ph->ph_in.pfl_top; p; p = p->pfil_next) - (void)mi_mpprintf(mp,"%p\t%x", - (void *)p->pfil_func, p->pfil_flags); + (void) mi_mpprintf(mp,"%p\t%x", + (void *)p->pfil_func, p->pfil_flags); (void) mi_mpprintf(mp, "out"); (void) mi_mpprintf(mp, "function\tflags"); for (p = ph->ph_out.pfl_top; p; p = p->pfil_next) - (void)mi_mpprintf(mp,"%p\t%x", - (void *)p->pfil_func, p->pfil_flags); + (void) mi_mpprintf(mp,"%p\t%x", + (void *)p->pfil_func, p->pfil_flags); RW_EXIT(&ph->ph_lock); @@ -176,7 +175,7 @@ pfil_init(ph) int pfil_add_hook(func, flags, ph) int (*func) __P((struct ip *, int, void *, int, - struct qif *, mblk_t **)); + void *, mblk_t **)); int flags; struct pfil_head *ph; { @@ -216,7 +215,7 @@ static int pfil_list_add(list, func, flags) pfil_list_t *list; int (*func) __P((struct ip *, int, void *, int, - struct qif *, mblk_t **)); + void *, mblk_t **)); int flags; { struct packet_filter_hook *pfh; @@ -270,7 +269,7 @@ pfil_list_add(list, func, flags) int pfil_remove_hook(func, flags, ph) int (*func) __P((struct ip *, int, void *, int, - struct qif *, mblk_t **)); + void *, mblk_t **)); int flags; struct pfil_head *ph; { @@ -309,7 +308,7 @@ static int pfil_list_remove(list, func) pfil_list_t *list; int (*func) __P((struct ip *, int, void *, int, - struct qif *, mblk_t **)); + void *, mblk_t **)); { struct packet_filter_hook *pfh; diff --git a/usr/src/uts/common/inet/pfil/pfil.conf b/usr/src/uts/common/inet/pfil/pfil.conf new file mode 100644 index 0000000000..1cf479a0d6 --- /dev/null +++ b/usr/src/uts/common/inet/pfil/pfil.conf @@ -0,0 +1,28 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" + +name="pfil" parent="pseudo" instance=0; + diff --git a/usr/src/uts/common/inet/ipf/pfil.h b/usr/src/uts/common/inet/pfil/pfil.h index 9c3da19714..97f926da8b 100644 --- a/usr/src/uts/common/inet/ipf/pfil.h +++ b/usr/src/uts/common/inet/pfil/pfil.h @@ -3,7 +3,7 @@ * * See the IPFILTER.LICENCE file for details on licencing. * - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -12,8 +12,8 @@ #ifndef _NET_PFIL_H_ #define _NET_PFIL_H_ -#define PFIL_RELEASE "2.1.4" -#define PFIL_VERSION 2010400 +#define PFIL_RELEASE "2.1.6" +#define PFIL_VERSION 2010600 #define PFIL_INTERFACE 2000000 #ifndef __P @@ -24,6 +24,7 @@ # endif #endif +#ifdef sun # include <inet/ip.h> # if SOLARIS2 < 9 # include <netinet/in_systm.h> @@ -34,15 +35,19 @@ # undef IPOPT_SSRR # include <netinet/ip.h> # endif +#endif +#ifdef __hpux +# include <netinet/in_systm.h> +# include <netinet/in.h> +# include <netinet/ip.h> +#endif -struct qif; -struct ip; typedef struct packet_filter_hook { struct packet_filter_hook *pfil_next; struct packet_filter_hook **pfil_pnext; - int (*pfil_func) __P((struct ip *, int, void *, int, struct qif *, - mblk_t **)); + int (*pfil_func) __P((struct ip *, int, void *, int, + void *, mblk_t **)); int pfil_flags; } packet_filter_hook_t; @@ -82,12 +87,12 @@ typedef struct pfil_head { void pfil_init __P((struct pfil_head *)); struct packet_filter_hook *pfil_hook_get __P((int, struct pfil_head *)); int pfil_add_hook __P((int (*func) __P((struct ip *, int, void *, int, - struct qif *, mblk_t **)), int, + void *, mblk_t **)), int, struct pfil_head *)); int pfil_remove_hook __P((int (*func) __P((struct ip *, int, void *, int, - struct qif *, mblk_t **)), int, + void *, mblk_t **)), int, struct pfil_head *)); -int pfil_sendbuf __P((mblk_t *)); +int pfil_sendbuf(mblk_t *); mblk_t *pfil_make_dl_packet __P((mblk_t *, struct ip *, void *, char *, queue_t **)); void pfil_send_dl_packet __P((queue_t *, mblk_t *)); @@ -103,8 +108,6 @@ extern struct pfil_head pfh_sync; /* Notification of interface */ extern krwlock_t qif_rwlock; extern krwlock_t pfil_rw; -extern u_int pfil_ip_csum_hdr __P((u_char *)); - /* * NOTE: On Solaris, even though pfilwput(), etc, are prototyped as returning * an int, the return value is never checked and much code ignores it, anyway, diff --git a/usr/src/common/ipf/pfild.h b/usr/src/uts/common/inet/pfil/pfild.h index e866e514ae..e866e514ae 100644 --- a/usr/src/common/ipf/pfild.h +++ b/usr/src/uts/common/inet/pfil/pfild.h diff --git a/usr/src/uts/common/inet/ipf/pfildrv.c b/usr/src/uts/common/inet/pfil/pfildrv.c index e787b5338e..45d694d304 100644 --- a/usr/src/uts/common/inet/ipf/pfildrv.c +++ b/usr/src/uts/common/inet/pfil/pfildrv.c @@ -3,7 +3,7 @@ * * See the IPFILTER.LICENCE file for details on licencing. * - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -11,6 +11,7 @@ #include <sys/conf.h> #include <sys/debug.h> +#include <sys/atomic.h> #include <sys/ethernet.h> #include <sys/stream.h> #include <sys/errno.h> @@ -97,6 +98,9 @@ struct streamtab pfil_dev_strtab = { &pfil_rinit, &pfil_winit }; +extern int nulldev(); +extern int nodev(); + void pfil_donotip(int, qif_t *, queue_t *, mblk_t *, mblk_t *, struct ip *, size_t); static int pfil_info(dev_info_t *, ddi_info_cmd_t , void *, void **); static int pfil_attach(dev_info_t *, ddi_attach_cmd_t); @@ -105,9 +109,48 @@ static int pfil_identify(dev_info_t *); #endif static int pfil_detach(dev_info_t *, ddi_detach_cmd_t); +#ifdef DDI_DEFINE_STREAM_OPS DDI_DEFINE_STREAM_OPS(pfil_devops, nulldev, nulldev, pfil_attach, pfil_detach, nulldev, pfil_info, D_MP, &pfil_dev_strtab); +#else +static struct cb_ops pfil_ops = { + nodev, /* cb_open */ + nodev, /* cb_close */ + nodev, /* cb_strategy */ + nodev, /* cb_print */ + nodev, /* cb_dump */ + nodev, /* cb_read */ + nodev, /* cb_write */ + nodev, /* cb_ioctl */ + nodev, /* cb_devmap */ + nodev, /* cb_mmap */ + nodev, /* cb_segmap */ + nochpoll, /* cb_chpoll */ + ddi_prop_op, /* cb_prop_op */ + &pfilinfo, /* cb_stream */ + D_MP /* cb_flag */ +}; + +static struct dev_ops pfil_devops = +{ + DEVO_REV, /* devo_rev */ + 0, /* devo_refcnt */ + pfil_info, /* devo_getinfo */ +#if SOLARIS2 >= 10 + nulldev, +#else + pfil_identify, /* devo_identify */ +#endif + nulldev, /* devo_probe */ + pfil_attach, /* devo_attach */ + pfil_detach, /* devo_detach */ + nodev, /* devo_reset */ + &pfil_ops, /* devo_cb_ops */ + NULL /* devo_bus_ops */ +}; +#endif + static struct modldrv modldrv = { &mod_driverops, "pfil Streams driver "/**/PFIL_RELEASE, &pfil_devops }; @@ -115,9 +158,8 @@ static struct modldrv modldrv = { /************************************************************************ * STREAMS module information */ -static int pfilmodopen(queue_t *q, dev_t *devp, int flag, int sflag, - cred_t *crp); -static int pfilmodclose(queue_t *q, int flag, cred_t *crp); +static int pfilmodopen(queue_t *, dev_t *, int, int, cred_t *); +static int pfilmodclose(queue_t *, int, cred_t *); static struct qinit pfilmod_rinit = { (pfi_t)pfilmodrput, NULL, pfilmodopen, pfilmodclose, @@ -174,7 +216,11 @@ static int pfil_attach(dev_info_t *devi, ddi_attach_cmd_t cmd) pfil_dev_info = devi; +#if SOLARIS2 >= 8 return (ddi_create_minor_node(devi, "pfil", S_IFCHR, 0, DDI_PSEUDO, 0)); +#else + return (ddi_create_minor_node(devi, "pfil", S_IFCHR, 0, NULL, 0)); +#endif } @@ -324,7 +370,6 @@ static int pfildevclose(queue_t *q, int flag, cred_t *crp) return 0; } - /************************************************************************ * STREAMS module functions */ @@ -394,8 +439,11 @@ static int pfilmodclose(queue_t *q, int flag, cred_t *crp) /* ------------------------------------------------------------------------ */ /* Function: pfil_precheck */ -/* Returns: int - < 0 is error in this function, 0 == pass packet, else */ -/* (> 0) indicates passing prohibited */ +/* Returns: int - < 0 pass packet because it's not a type subject to */ +/* firewall rules (i.e. internal STREAMS messages), */ +/* 0 == pass packet, else > 0 indicates passing */ +/* prohibited (possibly due to an error occuring in */ +/* this function.) */ /* Parameters: q(I) - pointer to STREAMS queue */ /* mp(I) - pointer to STREAMS message */ /* qif(I) - pointer to per-queue interface information */ @@ -413,23 +461,32 @@ int pfil_precheck(queue_t *q, mblk_t **mp, int flags, qif_t *qif) { register struct ip *ip; size_t hlen, len, off, mlen, iphlen, plen; - int err, out, sap, realigned = 0; packet_filter_hook_t *pfh; + qpktinfo_t qpkt, *qpi; struct pfil_head *ph; mblk_t *m, *mt = *mp; - u_char *bp, *s; - qif_t qf, *qp; + int err, out, sap; + u_char *bp; #if SOLARIS2 >= 8 ip6_t *ip6; #endif #ifndef sparc u_short __ipoff, __iplen; #endif - qf = *qif; - qp = qif; - qif = &qf; - qif->qf_next = NULL; - qif->qf_flags = 0; + + qpi = &qpkt; + qpi->qpi_q = q; + qpi->qpi_off = 0; + qpi->qpi_name = qif->qf_name; + qpi->qpi_real = qif; + qpi->qpi_ill = qif->qf_ill; + qpi->qpi_hl = qif->qf_hl; + qpi->qpi_ppa = qif->qf_ppa; + qpi->qpi_num = qif->qf_num; + qpi->qpi_flags = qif->qf_flags; + qpi->qpi_max_frag = qif->qf_max_frag; + if ((flags & PFIL_GROUP) != 0) + qpi->qpi_flags |= QF_GROUP; /* * If there is only M_DATA for a packet going out, then any header @@ -437,10 +494,9 @@ int pfil_precheck(queue_t *q, mblk_t **mp, int flags, qif_t *qif) * the M_DATA) is prepended before the IP header. We need to set the * offset to account for this. */ - qif->qf_off = 0; out = (flags & PFIL_OUT) ? 1 : 0; - off = (out) ? qif->qf_hl : 0; -tryagain: + off = (out) ? qpi->qpi_hl : 0; + ip = NULL; m = NULL; #if SOLARIS2 >= 8 @@ -468,13 +524,13 @@ tryagain: off = 0; m = mt; } else { - atomic_add_long(&qp->qf_notdata, 1); + atomic_add_long(&qif->qf_notdata, 1); return -1; } } else { m = mt->b_cont; if (m == NULL) { - atomic_add_long(&qp->qf_nodata, 1); + atomic_add_long(&qif->qf_nodata, 1); return -3; /* No data blocks */ } } @@ -484,7 +540,7 @@ tryagain: m = mt; break; default : - atomic_add_long(&qp->qf_notdata, 1); + atomic_add_long(&qif->qf_notdata, 1); return -2; } @@ -497,7 +553,7 @@ tryagain: off = 0; /* Any non-M_DATA cancels the offset */ if (m == NULL) { - atomic_add_long(&qp->qf_nodata, 1); + atomic_add_long(&qif->qf_nodata, 1); return -3; /* No data blocks */ } @@ -510,7 +566,7 @@ tryagain: if ((dl->dl_primitive == DL_UNITDATA_IND) && (dl->dl_group_address == 1)) { - qif->qf_flags |= QF_GROUP; + qpi->qpi_flags |= QF_GROUP; if (((*((u_char *)m->b_rptr) == 0x0) && ((*((u_char *)m->b_rptr + 2) == 0x45)))) off += 2; @@ -519,52 +575,21 @@ tryagain: } /* - * If there is more than one copy of this message traversing the - * STREAMS stack (ie packet is being used for snoop data) then make a - * copy of it for our use so we become the sole owner of the new - * message and do a freemsg() on the one passed in as we're no longer - * using it or passing it up. - */ - if ((pfil_delayed_copy == 0) && (m->b_datap->db_ref > 1)) { - mblk_t *new; - -forced_copy: - new = copymsg(m); - if (new == NULL) { - atomic_add_long(&qp->qf_copyfail, 1); - return -3; - } - atomic_add_long(&qp->qf_copy, 1); - - if (mt != m) - mt->b_cont = new; - else { - *mp = new; - mt = new; - } - freemsg(m); - m = new; - } - - ip = (struct ip *)(m->b_rptr + off); - - /* * We might have a 1st data block which is really M_PROTO, i.e. it is * only big enough for the link layer header */ - while ((u_char *)ip >= m->b_wptr) { - len = (u_char *)ip - m->b_wptr; + while ((len = m->b_wptr - m->b_rptr) <= off) { + off -= len; m = m->b_cont; if (m == NULL) { - atomic_add_long(&qp->qf_nodata, 1); + atomic_add_long(&qif->qf_nodata, 1); return -4; /* not enough data for IP */ } - ip = (struct ip *)(m->b_rptr + len); } - off = (u_char *)ip - m->b_rptr; - mlen = msgdsize(m) - off; - if (mlen == 0) - mlen = mt->b_wptr - mt->b_rptr; + + ip = (struct ip *)(m->b_rptr + off); + len = m->b_wptr - m->b_rptr - off; + mlen = msgdsize(m); #ifdef IRE_ILL_CN sap = ((s_ill_t *)qif->qf_ill)->ill_sap; @@ -572,7 +597,105 @@ forced_copy: sap = ((ill_t *)qif->qf_ill)->ill_sap; #endif - if (sap == ETHERTYPE_IP) { + if (mlen == 0) + mlen = m->b_wptr - m->b_rptr; + mlen -= off; + +#ifdef PFILDEBUG + /*LINTED: E_CONSTANT_CONDITION*/ + PRINT(10,(CE_CONT, + "!IP Filter[%s]: out %d len %ld/%ld sap %d ip %p b_rptr %p off %ld m %p/%d/%d/%p mt %p/%d/%d/%p\n", + qif->qf_name, out, len, mlen, sap, + (void *)ip, (void *)m->b_rptr, off, + (void *)m, MTYPE(m), (int)MLEN(m), (void *)m->b_cont, + (void *)mt, MTYPE(mt), (int)MLEN(mt), (void *)mt->b_cont)); +#endif + + /* + * If there is more than one copy of this message traversing the + * STREAMS stack (ie the packet is being used for snoop data), the + * IP header isn't on a 32bit aligned address, or the IP header + * isn't contain within a single block, then make a copy which + * meets our requirements and do a freemsg on the one passed in + * since we're no longer using it or passing it up. + */ + + if ((pfil_delayed_copy == 0 && m->b_datap->db_ref > 1) + || ((uintptr_t)ip & 0x3) || len < sizeof(*ip) + || (sap != IP_DL_SAP +#if SOLARIS2 >= 8 + && sap != IP6_DL_SAP +#endif + )) { + mblk_t *b; + mblk_t *nm; + mblk_t *nmt; + mblk_t *previous_nm; + +forced_copy: + nmt = NULL; + previous_nm = NULL; + + /* + * Duplicate the message block descriptors up to (and + * including if the offset is non-zero) the block where + * IP begins. + */ + for (b = mt; b != m || off; b = b->b_cont) { + nm = dupb(b); + if (nm == NULL) { + atomic_add_long(&qif->qf_copyfail, 1); + if (nmt) + freemsg(nmt); + return ENOBUFS; + } + + nm->b_cont = NULL; + if (nmt) + linkb(previous_nm, nm); + else + nmt = nm; + previous_nm = nm; + + /* + * Set the length so the block only contains what + * appears before IP. + */ + if (b == m) { + nm->b_wptr = nm->b_rptr + off; + break; + } + } + + m->b_rptr += off; + nm = msgpullup(m, -1); + m->b_rptr -= off; + + if (nm == NULL) { + atomic_add_long(&qif->qf_copyfail, 1); + if (nmt) + freemsg(nmt); + return ENOBUFS; + } + + if (nmt) + linkb(previous_nm, nm); + else + nmt = nm; + + freemsg(mt); + + *mp = nmt; + mt = nmt; + m = nm; + + ip = (struct ip *)m->b_rptr; + len = m->b_wptr - m->b_rptr; + mlen = len; + off = 0; + } + + if (sap == IP_DL_SAP) { u_short tlen; hlen = sizeof(*ip); @@ -582,7 +705,6 @@ forced_copy: ((char *)&tlen)[1] = ((char *)&ip->ip_len)[1]; plen = ntohs(tlen); - sap = 0; ph = &pfh_inet4; } #if SOLARIS2 >= 8 @@ -599,165 +721,43 @@ forced_copy: if (plen == 0) return EMSGSIZE; /* Jumbo gram */ - sap = IP6_DL_SAP; ph = &pfh_inet6; } #endif else { - hlen = 0; sap = -1; } - - len = m->b_wptr - m->b_rptr - off; -#ifdef PFILDEBUG - /*LINTED: E_CONSTANT_CONDITION*/ - PRINT(10,(CE_CONT, - "!IP Filter[%s]: out %d len %ld/%ld sap %d ip %p b_rptr %p off %ld m %p/%d/%d/%p mt %p/%d/%d/%p\n", - qif->qf_name, out, len, mlen, sap, - (void *)ip, (void *)m->b_rptr, off, - (void *)m, MTYPE(m), (int)MLEN(m), (void *)m->b_cont, - (void *)mt, MTYPE(mt), (int)MLEN(mt), (void *)mt->b_cont)); -#endif - - /* - * Ok, the IP header isn't on a 32bit aligned address so fix this. - */ - if (((uintptr_t)ip & 0x3) || (len < sizeof(*ip)) || (sap == -1)) { - mblk_t *m2, *m1; - int off2; - - if (m->b_datap->db_ref > 1) - goto forced_copy; - /* - * If we have already tried to realign the IP header and we - * are back here, then the attempt has failed, so stop now - * rather than try again (could keep on retrying with no - * benefit.) - */ - if (realigned) { - atomic_add_long(&qp->qf_drop, 1); - return EINVAL; - } - realigned = 1; - - len = msgdsize(m); - if (len < sizeof(*ip)) { - atomic_add_long(&qp->qf_bad, 1); - return EINVAL; - } - - /* - * XXX - Now I understand how pullupmsg() & STREAMS messages - * work better, this can possibly be junked in favour of using - * pullupmsg() which will preserve all the dblk bits correctly, - * as is done in fr_pullup in the ipf code. - */ - - /* - * Junk using pullupmsg() - */ - off2 = (uintptr_t)ip & 0x3; - if (off2) - off2 = 4 - off2; - m2 = allocb(len + off2, BPRI_HI); - if (m2 == NULL) { - atomic_add_long(&qp->qf_drop, 1); - return ENOBUFS; - } - - MTYPE(m2) = M_DATA; - if (m->b_rptr != (u_char *)ip) - m2->b_rptr += off2; - m2->b_wptr = m2->b_rptr + len; - m1 = m; - s = (u_char *)m->b_rptr; - for (bp = m2->b_rptr; m1 && (bp < m2->b_wptr); bp += len) { - len = MIN(m1->b_wptr - s, m2->b_wptr - bp); - bcopy(s, bp, len); - m1 = m1->b_cont; - if (m1 != NULL) - s = m1->b_rptr; - } - - if ((mt != m) && (mt->b_cont == m) && (off == 0)) { - /* - * check if the buffer we're changing is chained in- - * between other buffers and unlink/relink as required. - */ - (void) unlinkb(mt); /* should return 'm' */ - m1 = unlinkb(m); - if (m1 != NULL) - linkb(m2, m1); - freemsg(m); - linkb(mt, m2); - } else { - if (m == mt) { - m1 = unlinkb(mt); - if (m1) - linkb(m2, m1); - } - freemsg(mt); - *mp = m2; - mt = m2; - } - - off = 0; - goto tryagain; - } - - if (((sap == 0) && (ip->ip_v != IPVERSION)) + if (((sap == IP_DL_SAP) && (ip->ip_v != IPVERSION)) #if SOLARIS2 >= 8 || ((sap == IP6_DL_SAP) && (((ip6->ip6_vfc) & 0xf0) != 0x60)) #endif + || sap == -1 ) { - atomic_add_long(&qp->qf_notip, 1); + atomic_add_long(&qif->qf_notip, 1); #ifdef PFILDEBUG pfil_donotip(out, qif, q, m, mt, ip, off); #endif return EINVAL; } - /* - * The code in IPFilter assumes that both the ip_off and ip_len - * fields are in host byte order, so convert them here to fulfill - * that expectation. - * - * If the target compile host is non-SPARC, assume it is a little - * endian machine, requiring the conversion of offset/length fields - * to both be host byte ordered. - */ -#ifndef sparc - if (sap == 0) { - __ipoff = (u_short)ip->ip_off; - ip->ip_len = plen; - ip->ip_off = ntohs(__ipoff); - } -#endif - if (sap == 0) + if (sap == IP_DL_SAP) iphlen = ip->ip_hl << 2; #if SOLARIS2 >= 8 else if (sap == IP6_DL_SAP) iphlen = sizeof(ip6_t); #endif + if (( #if SOLARIS2 >= 8 - (sap == IP6_DL_SAP) && (mlen < iphlen + plen)) || - ((sap == 0) && + (sap == IP6_DL_SAP) && (mlen < plen)) || + ((sap == IP_DL_SAP) && #endif ((iphlen < hlen) || (iphlen > plen) || (mlen < plen)))) { /* * Bad IP packet or not enough data/data length mismatches */ -#ifndef sparc - if (sap == 0) { - __ipoff = (u_short)ip->ip_off; - - ip->ip_len = htons(plen); - ip->ip_off = htons(__ipoff); - } -#endif - atomic_add_long(&qp->qf_bad, 1); + atomic_add_long(&qif->qf_bad, 1); return EINVAL; } @@ -769,28 +769,43 @@ forced_copy: if (m->b_datap->db_ref > 1) goto forced_copy; if (!pullupmsg(m, (int)iphlen + off)) { - atomic_add_long(&qp->qf_nodata, 1); - return -5; + atomic_add_long(&qif->qf_nodata, 1); + return ENOBUFS; } ip = (struct ip *)ALIGN32(m->b_rptr + off); } - if (sap == IP6_DL_SAP) { - if ((len > iphlen + plen) && (off == 0)) - m->b_wptr -= len - (iphlen + plen); - } else { - if ((len > plen) && (off == 0)) - m->b_wptr -= len - plen; + /* + * Discard any excess data. + */ + if (sap == IP6_DL_SAP && len > iphlen + plen) + m->b_wptr = m->b_rptr + off + plen + iphlen; + else if (sap == IP_DL_SAP && len > plen) + m->b_wptr = m->b_rptr + off + plen; + + /* + * The code in IPFilter assumes that both the ip_off and ip_len + * fields are in host byte order, so convert them here to fulfill + * that expectation. + * + * If the target compile host is non-SPARC, assume it is a little + * endian machine, requiring the conversion of offset/length fields + * to both be host byte ordered. + */ +#ifndef sparc + if (sap == IP_DL_SAP) { + __ipoff = (u_short)ip->ip_off; + ip->ip_len = plen; + ip->ip_off = ntohs(__ipoff); } +#endif - qif->qf_m = m; - qif->qf_q = q; - qif->qf_data = ip; - qif->qf_oq = OTHERQ(q); - qif->qf_off = off; + qpi->qpi_m = m; + qpi->qpi_off = off; + qpi->qpi_data = ip; - if (qp->qf_ipmp != NULL) - qp = qp->qf_ipmp; + if (qif->qf_ipmp != NULL) + qif = qif->qf_ipmp; READ_ENTER(&ph->ph_lock); @@ -802,15 +817,24 @@ forced_copy: flags, (void *)ph, (void *)pfh)); for (; pfh; pfh = pfh->pfil_next) if (pfh->pfil_func) { - err = (*pfh->pfil_func)(ip, iphlen, qif->qf_ill, out, - qif, mp); + err = (*pfh->pfil_func)(ip, iphlen, qif, out, qpi, mp); if (err || !*mp) break; - ip = qif->qf_data; + /* + * fr_pullup may have allocated a new buffer. + */ + ip = qpi->qpi_data; } RW_EXIT(&ph->ph_lock); /* + * Functions called via pfil_func should only return values >= 0, so + * convert any that are < 0 to be > 0 and preserve the absolute value. + */ + if (err < 0) + err = -err; + + /* * If we still have a STREAMS message after calling the filtering * hooks, return the byte order of the fields changed above on * platforms where this is required. They are refetched from the @@ -818,8 +842,8 @@ forced_copy: * them in some way. */ #ifndef sparc - if (*mp != NULL) { - if (sap == 0) { + if ((err == 0) && (*mp != NULL)) { + if (sap == IP_DL_SAP) { __iplen = (u_short)ip->ip_len; __ipoff = (u_short)ip->ip_off; ip->ip_len = htons(__iplen); @@ -827,7 +851,6 @@ forced_copy: } } #endif - return err; } @@ -1015,6 +1038,9 @@ static void pfil_remif(queue_t *rq) #endif /* IRE_ILL_CN */ +/************************************************************************ + * + */ #ifdef PFILDEBUG /* ------------------------------------------------------------------------ */ /* Function: pfil_donotip */ @@ -1090,6 +1116,51 @@ void pfil_donotip(int out, qif_t *qif, queue_t *q, mblk_t *m, mblk_t *mt, struct #endif +/* ------------------------------------------------------------------------ */ +/* Function: pfil_property_update */ +/* Returns: int - DDI_SUCCESS == success, else failure */ +/* Parameters: modinfop(I) - pointer to module informatio buffer */ +/* */ +/* Fetch configuration file values that have been entered into the */ +/* pfil.conf driver file. */ +/* ------------------------------------------------------------------------ */ +static int pfil_property_update(dev_info_t *dip) +{ + char *list, *s, *t; + int err; + + if (ddi_prop_update_int(DDI_DEV_T_ANY, dip, + "ddi-no-autodetach", 1) == -1) { + cmn_err(CE_WARN, "!updating ddi-no-authdetach failed"); + return DDI_FAILURE; + } + + list = NULL; + err = ddi_prop_lookup_string(DDI_DEV_T_ANY, dip, + 0, "qif_ipmp_set", &list); +#ifdef IPFDEBUG + cmn_err(CE_CONT, "IP Filter: lookup_string(pfil_ipmp_list) = %d\n", + err); +#endif + if (err == DDI_SUCCESS) { + t = NULL; + s = list; + do { + if (t != NULL) + s = t + 1; + t = strchr(s, ';'); + if (t != NULL) + *t = '\0'; + qif_ipmp_update(s); + } while (t != NULL); + + ddi_prop_free(list); + } + + return DDI_SUCCESS; +} + + #if SOLARIS2 == 8 int miocpullup(mblk_t *m, size_t len) { @@ -1098,4 +1169,3 @@ int miocpullup(mblk_t *m, size_t len) return pullupmsg(m->b_cont, len); } #endif - diff --git a/usr/src/uts/common/inet/ipf/pfilstream.c b/usr/src/uts/common/inet/pfil/pfilstream.c index 580f60d95a..51d1b30d5a 100644 --- a/usr/src/uts/common/inet/ipf/pfilstream.c +++ b/usr/src/uts/common/inet/pfil/pfilstream.c @@ -3,7 +3,7 @@ * * See the IPFILTER.LICENCE file for details on licencing. * - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -20,6 +20,7 @@ struct uio; #include <sys/dlpi.h> #include <sys/cmn_err.h> #ifdef sun +# include <sys/atomic.h> # include <sys/sockio.h> # include <sys/ksynch.h> # include <sys/strsubr.h> @@ -27,6 +28,7 @@ struct uio; #endif #ifdef __hpux # include <sys/dlpi_ext.h> +# include <net/mtcp.h> #endif #include <netinet/in.h> #include <netinet/in_systm.h> @@ -37,6 +39,8 @@ struct uio; # include <inet/common.h> # if SOLARIS2 >= 8 # include <netinet/ip6.h> +# else +# include <net/if_dl.h> # endif # if SOLARIS2 >= 10 # include <sys/policy.h> @@ -50,17 +54,10 @@ struct uio; # include <inet/ip_if.h> #endif -#ifdef sun -# include <inet/ipf/compat.h> -# include <inet/ipf/pfil.h> -# include <inet/ipf/qif.h> -# include <pfild.h> -#else -# include "compat.h" -# include "pfil.h" -# include "qif.h" -# include "pfild.h" -#endif +#include "compat.h" +#include "qif.h" +#include "pfil.h" +#include "pfild.h" #if SOLARIS2 >= 10 extern queue_t *pfildq; @@ -85,6 +82,7 @@ extern queue_t *pfildq; static int pfil_drv_priv __P((cred_t *)); + #ifdef PFILDEBUG /* ------------------------------------------------------------------------ */ /* Function: pfil_printmchain */ @@ -209,6 +207,7 @@ static void pfil_printioctl(mblk_t *mp) } #endif /* PFILDEBUG */ + /* ------------------------------------------------------------------------ */ /* Function: pfilbind */ /* Returns: int - 0 == success, else error */ @@ -234,7 +233,7 @@ int pfilbind(queue_t *q) /* ------------------------------------------------------------------------ */ /* Function: pfilwput_ioctl */ -/* Returns: void */ +/* Returns: void */ /* Parameters: q(I) - pointer to queue */ /* mp(I) - pointer to STREAMS message */ /* */ @@ -318,7 +317,21 @@ void pfilwput_ioctl(queue_t *q, mblk_t *mp) break; #endif #endif /* pre-S10 */ - default: +#ifdef __hpux + case ND_SET : + case ND_GET : + if (pfil_ioctl_nd(q, mp)) { + if (iocp->ioc_error) + iocp->ioc_count = 0; + mp->b_datap->db_type = M_IOCACK; + qreply(q, mp); + } else { + miocnak(q, mp, 0, EINVAL); + } + return; + break; +#endif + default : break; } @@ -408,7 +421,7 @@ static void pfil_update_ifaddrset(mblk_t *mp) */ /* ------------------------------------------------------------------------ */ /* Function: pfilwput */ -/* Returns: void */ +/* Returns: void */ /* Parameters: q(I) - pointer to queue */ /* mp(I) - pointer to STREAMS message */ /* */ @@ -416,19 +429,21 @@ static void pfil_update_ifaddrset(mblk_t *mp) /* /dev/pfil, not the STREAMS module pushed on another queue. As it does */ /* not do any IO, this should never be called except to handle ioctl's and */ /* so all other messages are free'd and no reply sent back. */ -/* The only ioctls handled by the driver are ND_GET/ND_SET. */ -/* pfilwput also handles PFILCMD_IFADDRS and PFILCMD_IFADDRSET messages */ +/* The only ioctls handled by the driver are ND_GET/ND_SET. */ +/* pfilwput also handles PFILCMD_IFADDRS and PFILCMD_IFADDRSET messages. */ +/* NOTE: HP-UX does not need or have pfil implemented as a STREAMS device. */ /* ------------------------------------------------------------------------ */ +#ifdef sun void pfilwput(queue_t *q, mblk_t *mp) { struct iocblk *iocp; uint32_t cmd; -#ifdef PFILDEBUG +# ifdef PFILDEBUG /* LINTED: E_CONSTANT_CONDITION */ PRINT(9,(CE_CONT, "!pfilwput(%p,%p) [%s] qif %p\n", (void *)q, (void *)mp, QTONM(q), (void *)q->q_ptr)); -#endif +# endif switch (MTYPE(mp)) { @@ -463,7 +478,8 @@ void pfilwput(queue_t *q, mblk_t *mp) #endif case M_IOCTL: iocp = (struct iocblk *)mp->b_rptr; - switch (iocp->ioc_cmd) { + switch (iocp->ioc_cmd) + { case ND_SET : case ND_GET : if (pfil_ioctl_nd(q, mp)) { @@ -475,17 +491,20 @@ void pfilwput(queue_t *q, mblk_t *mp) miocnak(q, mp, 0, EINVAL); } break; - default: + + default : miocnak(q, mp, 0, EINVAL); break; } return; - default: + default : break; } + freemsg(mp); } +#endif /************************************************************************ @@ -493,7 +512,7 @@ void pfilwput(queue_t *q, mblk_t *mp) */ /* ------------------------------------------------------------------------ */ /* Function: pfilmodwput */ -/* Returns: Void. */ +/* Returns: void */ /* Parameters: q(I) - pointer to queue */ /* mp(I) - pointer to STREAMS message */ /* */ @@ -527,7 +546,7 @@ void pfilmodwput(queue_t *q, mblk_t *mp) break; } - /*FALLTHROUGH*/ + /*FALLTHROUGH*/ case M_DATA : atomic_add_long(&qif->qf_nw, 1); @@ -535,6 +554,7 @@ void pfilmodwput(queue_t *q, mblk_t *mp) int i; i = pfil_precheck(q, &mp, PFIL_OUT, qif); + /* LINTED: E_CONSTANT_CONDITION */ PRINT(9, (CE_CONT, "!%s: pfil_precheck=%d mp %p\n", "pfilmodwput", i, (void *)mp)); @@ -547,9 +567,10 @@ void pfilmodwput(queue_t *q, mblk_t *mp) } break; - case M_IOCTL: + case M_IOCTL : pfilwput_ioctl(q, mp); return; + default : break; } @@ -572,9 +593,10 @@ void pfilmodrput(queue_t *q, mblk_t *mp) { union DL_primitives *dl; dl_bind_ack_t *b; - int i; + int i, flags; qif_t *qif; + flags = 0; qif = q->q_ptr; /* LINTED: E_CONSTANT_CONDITION */ @@ -582,7 +604,9 @@ void pfilmodrput(queue_t *q, mblk_t *mp) (void *)q, (void *)mp, mp->b_datap->db_type, QTONM(q), QTONM(OTHERQ(q)), (void *)qif, (void *)qif->qf_ill)); - switch (MTYPE(mp)) { + + switch (MTYPE(mp)) + { #ifdef DL_IOC_HDR_INFO case M_IOCACK : { @@ -602,6 +626,7 @@ void pfilmodrput(queue_t *q, mblk_t *mp) pfil_printioctl(mp); #endif break; + case M_PROTO : case M_PCPROTO : @@ -616,7 +641,7 @@ void pfilmodrput(queue_t *q, mblk_t *mp) case DL_UNITDATA_IND : if ((MLEN(mp) >= sizeof(dl_unitdata_ind_t)) && (dl->unitdata_ind.dl_group_address)) - qif->qf_flags |= QF_GROUP; + flags |= PFIL_GROUP; break; case DL_SUBS_BIND_ACK : @@ -625,7 +650,6 @@ void pfilmodrput(queue_t *q, mblk_t *mp) c = (dl_subs_bind_ack_t *)dl; if (qif->qf_sap == 0) { -/* XXX: What is this message? */ #if 0 qif->qf_sap = c->dl_sap; if (qif->qf_sap < 0) @@ -655,7 +679,9 @@ void pfilmodrput(queue_t *q, mblk_t *mp) qif->qf_waitack++; break; } - if (!b->dl_sap || b->dl_sap == IP_DL_SAP || b->dl_sap == IP6_DL_SAP) + + if (!b->dl_sap || b->dl_sap == IP_DL_SAP || + b->dl_sap == IP6_DL_SAP) (void) pfilbind(q); break; @@ -672,7 +698,8 @@ void pfilmodrput(queue_t *q, mblk_t *mp) atomic_add_long(&qif->qf_nr, 1); if (qif->qf_ill != NULL) { - i = pfil_precheck(q, &mp, PFIL_IN, qif); + flags |= PFIL_IN; + i = pfil_precheck(q, &mp, flags, qif); /* LINTED: E_CONSTANT_CONDITION */ PRINT(9, (CE_CONT, @@ -686,9 +713,11 @@ void pfilmodrput(queue_t *q, mblk_t *mp) } } break; + default : break; } + putnext(q, mp); } @@ -730,4 +759,3 @@ void pfil_startup() pfil_init(&pfh_inet6); pfil_init(&pfh_sync); } - diff --git a/usr/src/uts/common/inet/ipf/pkt.c b/usr/src/uts/common/inet/pfil/pkt.c index 0b4653b5d4..6a9c74b139 100644 --- a/usr/src/uts/common/inet/ipf/pkt.c +++ b/usr/src/uts/common/inet/pfil/pkt.c @@ -3,8 +3,6 @@ * * See the IPFILTER.LICENCE file for details on licencing. * - * ident "@(#)$Id: pkt.c,v 1.8 2003/07/28 05:13:58 darrenr Exp $" - * * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -25,7 +23,9 @@ #include <netinet/in.h> #include <netinet/ip.h> #if SOLARIS2 >= 8 -#include <netinet/ip6.h> +# include <netinet/ip6.h> +#else +# include <net/if_dl.h> #endif #undef IPOPT_EOL @@ -253,7 +253,6 @@ mblk_t *mb; /* Function: pfil_sendbuf */ /* Returns: int - 0 == success, 1 == failure */ /* Parameters: m(I) - pointer to streams message */ -/* v - indicated v4 or v6 */ /* */ /* Output an IPv4 packet to whichever interface has the correct route. */ /* ------------------------------------------------------------------------ */ diff --git a/usr/src/uts/common/inet/ipf/qif.c b/usr/src/uts/common/inet/pfil/qif.c index 7715098c0f..fc74ca00fc 100644 --- a/usr/src/uts/common/inet/ipf/qif.c +++ b/usr/src/uts/common/inet/pfil/qif.c @@ -3,7 +3,7 @@ * * See the IPFILTER.LICENCE file for details on licencing. * - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -42,10 +42,10 @@ # endif # include <net/if_dl.h> #endif -#include <inet/common.h> #include <netinet/in.h> #include <netinet/in_systm.h> #include <netinet/ip.h> +#include <inet/common.h> #undef IPOPT_EOL #undef IPOPT_NOP #undef IPOPT_LSRR @@ -326,7 +326,7 @@ qif_attach(rq) (hdrsizes[ill->ill_type][0] == ill->ill_type)) qif->qf_hl = hdrsizes[ill->ill_type][1]; - if (qif->qf_hl == 0) { + if (qif->qf_hl == 0 && ill->ill_type != IFT_OTHER) { cmn_err(CE_WARN, "!Unknown layer 2 header size for %s type %d sap %x\n", qif->qf_name, ill->ill_type, ill->ill_sap); @@ -364,7 +364,7 @@ qif_attach(rq) pfh = pfil_hook_get(PFIL_IN, &pfh_sync); for (; pfh; pfh = pfh->pfil_next) if (pfh->pfil_func) - (void) (*pfh->pfil_func)(NULL, 0, ill, 0, qif, NULL); + (void) (*pfh->pfil_func)(NULL, 0, qif, 0, qif, NULL); RW_EXIT(&pfh_sync.ph_lock); @@ -420,6 +420,7 @@ qif_new(q, mflags) return qif; } + /* ------------------------------------------------------------------------ */ /* Function: qif_delete */ /* Returns: void */ @@ -470,7 +471,7 @@ queue_t *q; pfh = pfil_hook_get(PFIL_OUT, &pfh_sync); for (; pfh; pfh = pfh->pfil_next) if (pfh->pfil_func) - (void) (*pfh->pfil_func)(NULL, 0, qif->qf_ill, + (void) (*pfh->pfil_func)(NULL, 0, qif, 1, qif, NULL); RW_EXIT(&pfh_sync.ph_lock); } @@ -480,9 +481,10 @@ queue_t *q; freeb(qif->qf_addrset); mutex_destroy(&qif->qf_ptl.pt_lock); cv_destroy(&qif->qf_ptl.pt_cv); - if (qif->qf_qifsz == sizeof(*qif)) { + + if (qif->qf_qifsz == sizeof(*qif)) kmem_cache_free(qif_cache, qif); - } else { + else { KMFREE(qif, qif->qf_qifsz); } } @@ -604,6 +606,7 @@ qif_t *qif_walk(qif_t **qfp) return *qfp; } + /* ------------------------------------------------------------------------ */ /* Function: qif_ipmp_update */ /* Returns: void */ @@ -710,7 +713,7 @@ void qif_ipmp_delete(char *qifname) pfh = pfil_hook_get(PFIL_OUT, &pfh_sync); for (; pfh; pfh = pfh->pfil_next) if (pfh->pfil_func) - (void) (*pfh->pfil_func)(NULL, 0, qif->qf_ill, 1, + (void) (*pfh->pfil_func)(NULL, 0, qif, 1, qif, NULL); KMFREE(qif, qif->qf_qifsz); @@ -796,3 +799,59 @@ void qif_ipmp_syncslave(qif_t *target, const int sap) } } + +/* ------------------------------------------------------------------------ */ +/* Function: qif_hl_set */ +/* Returns: void */ +/* Parameters: ipmpconf(I) - string with header length setting for NIC */ +/* */ +/* For NICs that we cannot automatically determine the MAC header length of */ +/* we provide a manual crook to achieve that with. The input syntax for */ +/* the string is "[v4:|v6:]<ifname>=<length>" */ +/* ------------------------------------------------------------------------ */ +void qif_hl_set(char *ipmpconf) +{ + qif_t *qf; + char *s; + + if (!strncmp(ipmpconf, "v4:", 3)) { + ipmpconf += 3; + } else if (!strncmp(ipmpconf, "v6:", 3)) { +#if SOLARIS2 >= 8 + ipmpconf += 3; +#else + return; +#endif + } + + s = strchr(ipmpconf, '='); + if (s != NULL) { + if (*(s + 1) == '\0') + *s = '\0'; + else + *s++ = '\0'; + } + if (s == NULL || *s == NULL) + return; + + READ_ENTER(&pfil_rw); + for (qf = qif_head; qf; qf = qf->qf_next) + if (strcmp(qf->qf_name, ipmpconf) == 0) + break; + + if (qf != NULL) { + int hl = 0; + + for (; *s != '\0'; s++) { + char c = *s; + + if (c < '0' || c > '9') + return; + hl *= 10; + hl += c - '0'; + } + qf->qf_hl = hl; + } + + RW_EXIT(&pfil_rw); +} diff --git a/usr/src/uts/common/inet/ipf/qif.h b/usr/src/uts/common/inet/pfil/qif.h index 2e3c7cc886..7371ab420a 100644 --- a/usr/src/uts/common/inet/ipf/qif.h +++ b/usr/src/uts/common/inet/pfil/qif.h @@ -3,14 +3,17 @@ * * See the IPFILTER.LICENCE file for details on licencing. * - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #pragma ident "%Z%%M% %I% %E% SMI" -#include "pfil.h" -#include <sys/ptms.h> +#ifdef sun +# include <sys/dditypes.h> +# include <sys/ptms.h> +#endif + #ifdef IRE_ILL_CN typedef union { @@ -63,7 +66,6 @@ typedef struct s_ill_s { uint_t mtu; } s_ill_t; - typedef struct qif { /* for alignment reasons, the lock is first. */ kmutex_t qf_lock; @@ -103,7 +105,7 @@ typedef struct qif { char qf_name[LIFNAMSIZ]; char *qf_members; - /* ON10 specific */ + /* ON(10, NV) specific */ mblk_t *qf_addrset; size_t qf_off; mblk_t *qf_m; @@ -155,7 +157,15 @@ typedef struct qpktinfo { #endif #ifdef __hpux -# define QF_V4_ADDR(x) ((ifinfot_t *)(x)->qf_ill)->ifi_addr[0] +# define QF_V4_ADDR(x) ((ifinfo_t *)(x)->qf_ill)->ifi_addr[0] +# define QF_V4_BROADCAST(x) 0 +# define QF_V4_NETMASK(x) 0xffffffff +# define QF_V4_PEERADDR(x) 0 +# ifdef USE_INET6 +# define QF_V6_BROADCAST(x) 0 +# define QF_V6_NETMASK(x) 0 +# define QF_V6_PEERADDR(x) 0 +# endif #endif @@ -170,14 +180,16 @@ extern int qif_startup(void); extern void qif_stop(void); extern void *qif_iflookup(char *, int); +#ifdef __hpux struct irinfo_s; extern void *ir_to_ill(struct irinfo_s *ir); - +#endif extern struct qif *qif_walk(struct qif **); extern struct qif *qif_head; extern int qif_verbose; extern void qif_update(struct qif *, mblk_t *); extern void qif_nd_init(void); +extern void qif_hl_set(char *); extern void qif_ipmp_delete(char *); extern void qif_ipmp_update(char *); extern void qif_ipmp_syncmaster(struct qif *, const int); diff --git a/usr/src/uts/intel/ipf/Makefile b/usr/src/uts/intel/ipf/Makefile index 79067cfbce..84d447a2cc 100644 --- a/usr/src/uts/intel/ipf/Makefile +++ b/usr/src/uts/intel/ipf/Makefile @@ -1,5 +1,5 @@ # -# Copyright 2005 Sun Microsystems, Inc. All rights reserved. +# Copyright 2006 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # #ident "%Z%%M% %I% %E% SMI" @@ -43,6 +43,8 @@ CPPFLAGS += -DIPFILTER_LKM -DIPFILTER_LOG -DIPFILTER_LOOKUP -DUSE_INET6 CPPFLAGS += -DSUNDDI -DSOLARIS2=$(MINOR:sh) -DIRE_ILL_CN LDFLAGS += -dy -Ndrv/ip -Ndrv/pfil -Nmisc/md5 +INC_PATH += -I$(UTSBASE)/common/inet/ipf + # # Default build targets. # diff --git a/usr/src/uts/intel/pfil/Makefile b/usr/src/uts/intel/pfil/Makefile index c88648e53f..14556577bf 100644 --- a/usr/src/uts/intel/pfil/Makefile +++ b/usr/src/uts/intel/pfil/Makefile @@ -2,9 +2,8 @@ # CDDL HEADER START # # The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ # CDDL HEADER END # # -# Copyright 2005 Sun Microsystems, Inc. All rights reserved. +# Copyright 2006 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # #ident "%Z%%M% %I% %E% SMI" @@ -46,7 +45,7 @@ OBJECTS = $(PFIL_OBJS:%=$(OBJS_DIR)/%) LINTS = $(PFIL_OBJS:%.o=$(LINTS_DIR)/%.ln) ROOTMODULE = $(ROOT_DRV_DIR)/$(MODULE) ROOTLINK = $(ROOT_STRMOD_DIR)/$(MODULE) -CONF_SRCDIR = $(UTSBASE)/common/inet/ipf +CONF_SRCDIR = $(UTSBASE)/common/inet/pfil # # Include common rules. diff --git a/usr/src/uts/req.flg b/usr/src/uts/req.flg index 36f48f01be..64495a7f73 100644 --- a/usr/src/uts/req.flg +++ b/usr/src/uts/req.flg @@ -45,7 +45,6 @@ find_files "s.*" usr/src/common/avl # For full builds (open and closed), we want both etc/certs and # etc/keys. For an open source build, there's no etc/keys directory. find_files "s.*" usr/src/cmd/cmd-crypto/etc -find_files "s.*" usr/src/common/ipf find_files "s.*" usr/src/common/mdesc find_files "s.*" usr/src/common/fs find_files "s.*" usr/src/common/acl diff --git a/usr/src/uts/sparc/ipf/Makefile b/usr/src/uts/sparc/ipf/Makefile index 22756183a1..c0400bb4c4 100644 --- a/usr/src/uts/sparc/ipf/Makefile +++ b/usr/src/uts/sparc/ipf/Makefile @@ -1,5 +1,5 @@ # -# Copyright 2005 Sun Microsystems, Inc. All rights reserved. +# Copyright 2006 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # #ident "%Z%%M% %I% %E% SMI" @@ -48,6 +48,8 @@ CPPFLAGS += -DIPFILTER_LKM -DIPFILTER_LOG -DIPFILTER_LOOKUP CPPFLAGS += -DSUNDDI -DSOLARIS2=$(MINOR:sh) -DIRE_ILL_CN -DUSE_INET6 LDFLAGS += -dy -Ndrv/ip -Ndrv/pfil -Nmisc/md5 +INC_PATH += -I$(UTSBASE)/common/inet/ipf + # # Default build targets. # diff --git a/usr/src/uts/sparc/pfil/Makefile b/usr/src/uts/sparc/pfil/Makefile index 2de916bb35..fae0500ce1 100644 --- a/usr/src/uts/sparc/pfil/Makefile +++ b/usr/src/uts/sparc/pfil/Makefile @@ -2,9 +2,8 @@ # CDDL HEADER START # # The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ # CDDL HEADER END # # -# Copyright 2005 Sun Microsystems, Inc. All rights reserved. +# Copyright 2006 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # #ident "%Z%%M% %I% %E% SMI" @@ -46,7 +45,7 @@ OBJECTS = $(PFIL_OBJS:%=$(OBJS_DIR)/%) LINTS = $(PFIL_OBJS:%.o=$(LINTS_DIR)/%.ln) ROOTMODULE = $(ROOT_DRV_DIR)/$(MODULE) ROOTLINK = $(ROOT_STRMOD_DIR)/$(MODULE) -CONF_SRCDIR = $(UTSBASE)/common/inet/ipf +CONF_SRCDIR = $(UTSBASE)/common/inet/pfil # # Include common rules. |