diff options
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. |
