17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * Copyright (C) 1993-2003 by Darren Reed. 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * See the IPFILTER.LICENCE file for details on licencing. 5ab25eeb5Syz * 6ab25eeb5Syz * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 77c478bd9Sstevel@tonic-gate * Use is subject to license terms. 87c478bd9Sstevel@tonic-gate */ 97c478bd9Sstevel@tonic-gate 107c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 117c478bd9Sstevel@tonic-gate 127c478bd9Sstevel@tonic-gate #if defined(KERNEL) || defined(_KERNEL) 137c478bd9Sstevel@tonic-gate # undef KERNEL 147c478bd9Sstevel@tonic-gate # undef _KERNEL 157c478bd9Sstevel@tonic-gate # define KERNEL 1 167c478bd9Sstevel@tonic-gate # define _KERNEL 1 177c478bd9Sstevel@tonic-gate #endif 187c478bd9Sstevel@tonic-gate #include <sys/errno.h> 197c478bd9Sstevel@tonic-gate #include <sys/types.h> 207c478bd9Sstevel@tonic-gate #include <sys/param.h> 217c478bd9Sstevel@tonic-gate #include <sys/time.h> 227c478bd9Sstevel@tonic-gate #if defined(__NetBSD__) 237c478bd9Sstevel@tonic-gate # if (NetBSD >= 199905) && !defined(IPFILTER_LKM) && defined(_KERNEL) 247c478bd9Sstevel@tonic-gate # include "opt_ipfilter_log.h" 257c478bd9Sstevel@tonic-gate # endif 267c478bd9Sstevel@tonic-gate #endif 277c478bd9Sstevel@tonic-gate #if defined(_KERNEL) && defined(__FreeBSD_version) && \ 287c478bd9Sstevel@tonic-gate (__FreeBSD_version >= 220000) 297c478bd9Sstevel@tonic-gate # if (__FreeBSD_version >= 400000) 307c478bd9Sstevel@tonic-gate # if !defined(IPFILTER_LKM) 317c478bd9Sstevel@tonic-gate # include "opt_inet6.h" 327c478bd9Sstevel@tonic-gate # endif 337c478bd9Sstevel@tonic-gate # if (__FreeBSD_version == 400019) 347c478bd9Sstevel@tonic-gate # define CSUM_DELAY_DATA 357c478bd9Sstevel@tonic-gate # endif 367c478bd9Sstevel@tonic-gate # endif 377c478bd9Sstevel@tonic-gate # include <sys/filio.h> 387c478bd9Sstevel@tonic-gate #else 397c478bd9Sstevel@tonic-gate # include <sys/ioctl.h> 407c478bd9Sstevel@tonic-gate #endif 41ab25eeb5Syz #if !defined(_AIX51) 42ab25eeb5Syz # include <sys/fcntl.h> 43ab25eeb5Syz #endif 447c478bd9Sstevel@tonic-gate #if defined(_KERNEL) 457c478bd9Sstevel@tonic-gate # include <sys/systm.h> 467c478bd9Sstevel@tonic-gate # include <sys/file.h> 477c478bd9Sstevel@tonic-gate #else 487c478bd9Sstevel@tonic-gate # include <stdio.h> 497c478bd9Sstevel@tonic-gate # include <string.h> 507c478bd9Sstevel@tonic-gate # include <stdlib.h> 51ab25eeb5Syz # include <stddef.h> 527c478bd9Sstevel@tonic-gate # include <sys/file.h> 537c478bd9Sstevel@tonic-gate # define _KERNEL 547c478bd9Sstevel@tonic-gate # ifdef __OpenBSD__ 557c478bd9Sstevel@tonic-gate struct file; 567c478bd9Sstevel@tonic-gate # endif 577c478bd9Sstevel@tonic-gate # include <sys/uio.h> 587c478bd9Sstevel@tonic-gate # undef _KERNEL 597c478bd9Sstevel@tonic-gate #endif 60ab25eeb5Syz #if !defined(__SVR4) && !defined(__svr4__) && !defined(__hpux) && \ 61ab25eeb5Syz !defined(linux) 627c478bd9Sstevel@tonic-gate # include <sys/mbuf.h> 637c478bd9Sstevel@tonic-gate #else 64ab25eeb5Syz # if !defined(linux) 65ab25eeb5Syz # include <sys/byteorder.h> 66ab25eeb5Syz # endif 677c478bd9Sstevel@tonic-gate # if (SOLARIS2 < 5) && defined(sun) 687c478bd9Sstevel@tonic-gate # include <sys/dditypes.h> 697c478bd9Sstevel@tonic-gate # endif 707c478bd9Sstevel@tonic-gate #endif 717c478bd9Sstevel@tonic-gate #ifdef __hpux 727c478bd9Sstevel@tonic-gate # define _NET_ROUTE_INCLUDED 737c478bd9Sstevel@tonic-gate #endif 74ab25eeb5Syz #if !defined(linux) 75ab25eeb5Syz # include <sys/protosw.h> 76ab25eeb5Syz #endif 777c478bd9Sstevel@tonic-gate #include <sys/socket.h> 787c478bd9Sstevel@tonic-gate #include <net/if.h> 797c478bd9Sstevel@tonic-gate #ifdef sun 807c478bd9Sstevel@tonic-gate # include <net/af.h> 817c478bd9Sstevel@tonic-gate #endif 82ab25eeb5Syz #if !defined(_KERNEL) && defined(__FreeBSD__) 83ab25eeb5Syz # include "radix_ipf.h" 84ab25eeb5Syz #endif 857c478bd9Sstevel@tonic-gate #include <net/route.h> 867c478bd9Sstevel@tonic-gate #include <netinet/in.h> 877c478bd9Sstevel@tonic-gate #include <netinet/in_systm.h> 887c478bd9Sstevel@tonic-gate #include <netinet/ip.h> 89ab25eeb5Syz #if !defined(linux) 90ab25eeb5Syz # include <netinet/ip_var.h> 91ab25eeb5Syz #endif 927c478bd9Sstevel@tonic-gate #if defined(__sgi) && defined(IFF_DRVRLOCK) /* IRIX 6 */ 937c478bd9Sstevel@tonic-gate # include <sys/hashing.h> 947c478bd9Sstevel@tonic-gate # include <netinet/in_var.h> 957c478bd9Sstevel@tonic-gate #endif 967c478bd9Sstevel@tonic-gate #include <netinet/tcp.h> 97ab25eeb5Syz #if (!defined(__sgi) && !defined(AIX)) || defined(_KERNEL) 98ab25eeb5Syz # include <netinet/udp.h> 99ab25eeb5Syz # include <netinet/ip_icmp.h> 100ab25eeb5Syz #endif 1017c478bd9Sstevel@tonic-gate #ifdef __hpux 1027c478bd9Sstevel@tonic-gate # undef _NET_ROUTE_INCLUDED 1037c478bd9Sstevel@tonic-gate #endif 104ab25eeb5Syz #include "netinet/ip_compat.h" 1057c478bd9Sstevel@tonic-gate #ifdef USE_INET6 1067c478bd9Sstevel@tonic-gate # include <netinet/icmp6.h> 107ab25eeb5Syz # if !SOLARIS && defined(_KERNEL) && !defined(__osf__) && !defined(__hpux) 1087c478bd9Sstevel@tonic-gate # include <netinet6/in6_var.h> 1097c478bd9Sstevel@tonic-gate # endif 1107c478bd9Sstevel@tonic-gate #endif 1117c478bd9Sstevel@tonic-gate #include <netinet/tcpip.h> 1127c478bd9Sstevel@tonic-gate #include "netinet/ip_fil.h" 1137c478bd9Sstevel@tonic-gate #include "netinet/ip_nat.h" 1147c478bd9Sstevel@tonic-gate #include "netinet/ip_frag.h" 1157c478bd9Sstevel@tonic-gate #include "netinet/ip_state.h" 1167c478bd9Sstevel@tonic-gate #include "netinet/ip_proxy.h" 1177c478bd9Sstevel@tonic-gate #include "netinet/ip_auth.h" 1187c478bd9Sstevel@tonic-gate #ifdef IPFILTER_SCAN 1197c478bd9Sstevel@tonic-gate # include "netinet/ip_scan.h" 1207c478bd9Sstevel@tonic-gate #endif 121ab25eeb5Syz #ifdef IPFILTER_SYNC 122ab25eeb5Syz # include "netinet/ip_sync.h" 123ab25eeb5Syz #endif 1247c478bd9Sstevel@tonic-gate #include "netinet/ip_pool.h" 1257c478bd9Sstevel@tonic-gate #include "netinet/ip_htable.h" 126ab25eeb5Syz #ifdef IPFILTER_COMPILED 127ab25eeb5Syz # include "netinet/ip_rules.h" 1287c478bd9Sstevel@tonic-gate #endif 129ab25eeb5Syz #if defined(IPFILTER_BPF) && defined(_KERNEL) 1307c478bd9Sstevel@tonic-gate # include <net/bpf.h> 1317c478bd9Sstevel@tonic-gate #endif 1327c478bd9Sstevel@tonic-gate #if defined(__FreeBSD_version) && (__FreeBSD_version >= 300000) 1337c478bd9Sstevel@tonic-gate # include <sys/malloc.h> 1347c478bd9Sstevel@tonic-gate # if defined(_KERNEL) && !defined(IPFILTER_LKM) 1357c478bd9Sstevel@tonic-gate # include "opt_ipfilter.h" 1367c478bd9Sstevel@tonic-gate # endif 1377c478bd9Sstevel@tonic-gate #endif 1387c478bd9Sstevel@tonic-gate #include "netinet/ipl.h" 139ab25eeb5Syz /* END OF INCLUDES */ 1407c478bd9Sstevel@tonic-gate 1417c478bd9Sstevel@tonic-gate #if !defined(lint) 1427c478bd9Sstevel@tonic-gate static const char sccsid[] = "@(#)fil.c 1.36 6/5/96 (C) 1993-2000 Darren Reed"; 143ab25eeb5Syz static const char rcsid[] = "@(#)$Id: fil.c,v 2.243.2.64 2005/08/13 05:19:59 darrenr Exp $"; 1447c478bd9Sstevel@tonic-gate #endif 1457c478bd9Sstevel@tonic-gate 1467c478bd9Sstevel@tonic-gate #ifndef _KERNEL 1477c478bd9Sstevel@tonic-gate # include "ipf.h" 1487c478bd9Sstevel@tonic-gate # include "ipt.h" 149ab25eeb5Syz # include "bpf-ipf.h" 1507c478bd9Sstevel@tonic-gate extern int opts; 1517c478bd9Sstevel@tonic-gate 1527c478bd9Sstevel@tonic-gate # define FR_VERBOSE(verb_pr) verbose verb_pr 1537c478bd9Sstevel@tonic-gate # define FR_DEBUG(verb_pr) debug verb_pr 1547c478bd9Sstevel@tonic-gate #else /* #ifndef _KERNEL */ 1557c478bd9Sstevel@tonic-gate # define FR_VERBOSE(verb_pr) 1567c478bd9Sstevel@tonic-gate # define FR_DEBUG(verb_pr) 1577c478bd9Sstevel@tonic-gate #endif /* _KERNEL */ 1587c478bd9Sstevel@tonic-gate 1597c478bd9Sstevel@tonic-gate 160ab25eeb5Syz fr_info_t frcache[2][8]; 1617c478bd9Sstevel@tonic-gate struct filterstats frstats[2] = { { 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0 } }; 1627c478bd9Sstevel@tonic-gate struct frentry *ipfilter[2][2] = { { NULL, NULL }, { NULL, NULL } }, 1637c478bd9Sstevel@tonic-gate *ipfilter6[2][2] = { { NULL, NULL }, { NULL, NULL } }, 1647c478bd9Sstevel@tonic-gate *ipacct6[2][2] = { { NULL, NULL }, { NULL, NULL } }, 1657c478bd9Sstevel@tonic-gate *ipacct[2][2] = { { NULL, NULL }, { NULL, NULL } }, 1667c478bd9Sstevel@tonic-gate *ipnatrules[2][2] = { { NULL, NULL }, { NULL, NULL } }; 1677c478bd9Sstevel@tonic-gate struct frgroup *ipfgroups[IPL_LOGSIZE][2]; 168ab25eeb5Syz char ipfilter_version[] = IPL_VERSION; 1697c478bd9Sstevel@tonic-gate int fr_refcnt = 0; 1707c478bd9Sstevel@tonic-gate /* 1717c478bd9Sstevel@tonic-gate * For fr_running: 1727c478bd9Sstevel@tonic-gate * 0 == loading, 1 = running, -1 = disabled, -2 = unloading 1737c478bd9Sstevel@tonic-gate */ 1747c478bd9Sstevel@tonic-gate int fr_running = 0; 1757c478bd9Sstevel@tonic-gate int fr_flags = IPF_LOGGING; 1767c478bd9Sstevel@tonic-gate int fr_active = 0; 1777c478bd9Sstevel@tonic-gate int fr_control_forwarding = 0; 1787c478bd9Sstevel@tonic-gate int fr_update_ipid = 0; 1797c478bd9Sstevel@tonic-gate u_short fr_ip_id = 0; 180ab25eeb5Syz int fr_chksrc = 0; /* causes a system crash if enabled */ 1817c478bd9Sstevel@tonic-gate int fr_minttl = 4; 182ab25eeb5Syz int fr_icmpminfragmtu = 68; 183ab25eeb5Syz u_long fr_frouteok[2] = {0, 0}; 184ab25eeb5Syz u_long fr_userifqs = 0; 185ab25eeb5Syz u_long fr_badcoalesces[2] = {0, 0}; 186ab25eeb5Syz u_char ipf_iss_secret[32]; 187*381a2a9aSdr #if SOLARIS2 >= 10 188*381a2a9aSdr int ipf_loopback = 0; 189*381a2a9aSdr #endif 1907c478bd9Sstevel@tonic-gate #if defined(IPFILTER_DEFAULT_BLOCK) 1917c478bd9Sstevel@tonic-gate int fr_pass = FR_BLOCK|FR_NOMATCH; 1927c478bd9Sstevel@tonic-gate #else 1937c478bd9Sstevel@tonic-gate int fr_pass = (IPF_DEFAULT_PASS)|FR_NOMATCH; 1947c478bd9Sstevel@tonic-gate #endif 195ab25eeb5Syz int fr_features = 0 196ab25eeb5Syz #ifdef IPFILTER_LKM 197ab25eeb5Syz | IPF_FEAT_LKM 1987c478bd9Sstevel@tonic-gate #endif 199ab25eeb5Syz #ifdef IPFILTER_LOG 200ab25eeb5Syz | IPF_FEAT_LOG 201ab25eeb5Syz #endif 202ab25eeb5Syz #ifdef IPFILTER_LOOKUP 203ab25eeb5Syz | IPF_FEAT_LOOKUP 204ab25eeb5Syz #endif 205ab25eeb5Syz #ifdef IPFILTER_BPF 206ab25eeb5Syz | IPF_FEAT_BPF 207ab25eeb5Syz #endif 208ab25eeb5Syz #ifdef IPFILTER_COMPILED 209ab25eeb5Syz | IPF_FEAT_COMPILED 210ab25eeb5Syz #endif 211ab25eeb5Syz #ifdef IPFILTER_CKSUM 212ab25eeb5Syz | IPF_FEAT_CKSUM 213ab25eeb5Syz #endif 214ab25eeb5Syz #ifdef IPFILTER_SYNC 215ab25eeb5Syz | IPF_FEAT_SYNC 216ab25eeb5Syz #endif 217ab25eeb5Syz #ifdef IPFILTER_SCAN 218ab25eeb5Syz | IPF_FEAT_SCAN 219ab25eeb5Syz #endif 220ab25eeb5Syz #ifdef USE_INET6 221ab25eeb5Syz | IPF_FEAT_IPV6 222ab25eeb5Syz #endif 223ab25eeb5Syz ; 2247c478bd9Sstevel@tonic-gate 2257c478bd9Sstevel@tonic-gate static INLINE int fr_ipfcheck __P((fr_info_t *, frentry_t *, int)); 2267c478bd9Sstevel@tonic-gate static int fr_portcheck __P((frpcmp_t *, u_short *)); 2277c478bd9Sstevel@tonic-gate static int frflushlist __P((int, minor_t, int *, frentry_t **)); 2287c478bd9Sstevel@tonic-gate static ipfunc_t fr_findfunc __P((ipfunc_t)); 2297c478bd9Sstevel@tonic-gate static frentry_t *fr_firewall __P((fr_info_t *, u_32_t *)); 2307c478bd9Sstevel@tonic-gate static int fr_funcinit __P((frentry_t *fr)); 231ab25eeb5Syz static INLINE void frpr_ah __P((fr_info_t *)); 2327663b816Sml static INLINE void frpr_esp __P((fr_info_t *)); 2337663b816Sml static INLINE void frpr_gre __P((fr_info_t *)); 2347c478bd9Sstevel@tonic-gate static INLINE void frpr_udp __P((fr_info_t *)); 2357c478bd9Sstevel@tonic-gate static INLINE void frpr_tcp __P((fr_info_t *)); 2367c478bd9Sstevel@tonic-gate static INLINE void frpr_icmp __P((fr_info_t *)); 2377c478bd9Sstevel@tonic-gate static INLINE void frpr_ipv4hdr __P((fr_info_t *)); 2387663b816Sml static INLINE int frpr_pullup __P((fr_info_t *, int)); 2397663b816Sml static INLINE void frpr_short __P((fr_info_t *, int)); 2407c478bd9Sstevel@tonic-gate static INLINE void frpr_tcpcommon __P((fr_info_t *)); 2417c478bd9Sstevel@tonic-gate static INLINE void frpr_udpcommon __P((fr_info_t *)); 2427c478bd9Sstevel@tonic-gate static INLINE int fr_updateipid __P((fr_info_t *)); 2437c478bd9Sstevel@tonic-gate #ifdef IPFILTER_LOOKUP 2447c478bd9Sstevel@tonic-gate static int fr_grpmapinit __P((frentry_t *fr)); 2457c478bd9Sstevel@tonic-gate static INLINE void *fr_resolvelookup __P((u_int, u_int, lookupfunc_t *)); 2467c478bd9Sstevel@tonic-gate #endif 247*381a2a9aSdr static void frsynclist __P((int, int, void *, char *, frentry_t *)); 248*381a2a9aSdr static void *fr_ifsync __P((int, int, char *, char *, 249*381a2a9aSdr void *, void *)); 250ab25eeb5Syz static ipftuneable_t *fr_findtunebyname __P((const char *)); 251ab25eeb5Syz static ipftuneable_t *fr_findtunebycookie __P((void *, void **)); 2527c478bd9Sstevel@tonic-gate 2537c478bd9Sstevel@tonic-gate 2547c478bd9Sstevel@tonic-gate /* 2557c478bd9Sstevel@tonic-gate * bit values for identifying presence of individual IP options 256ab25eeb5Syz * All of these tables should be ordered by increasing key value on the left 257ab25eeb5Syz * hand side to allow for binary searching of the array and include a trailer 258ab25eeb5Syz * with a 0 for the bitmask for linear searches to easily find the end with. 2597c478bd9Sstevel@tonic-gate */ 260ab25eeb5Syz const struct optlist ipopts[20] = { 2617c478bd9Sstevel@tonic-gate { IPOPT_NOP, 0x000001 }, 2627c478bd9Sstevel@tonic-gate { IPOPT_RR, 0x000002 }, 2637c478bd9Sstevel@tonic-gate { IPOPT_ZSU, 0x000004 }, 2647c478bd9Sstevel@tonic-gate { IPOPT_MTUP, 0x000008 }, 2657c478bd9Sstevel@tonic-gate { IPOPT_MTUR, 0x000010 }, 2667c478bd9Sstevel@tonic-gate { IPOPT_ENCODE, 0x000020 }, 2677c478bd9Sstevel@tonic-gate { IPOPT_TS, 0x000040 }, 2687c478bd9Sstevel@tonic-gate { IPOPT_TR, 0x000080 }, 2697c478bd9Sstevel@tonic-gate { IPOPT_SECURITY, 0x000100 }, 2707c478bd9Sstevel@tonic-gate { IPOPT_LSRR, 0x000200 }, 2717c478bd9Sstevel@tonic-gate { IPOPT_E_SEC, 0x000400 }, 2727c478bd9Sstevel@tonic-gate { IPOPT_CIPSO, 0x000800 }, 2737c478bd9Sstevel@tonic-gate { IPOPT_SATID, 0x001000 }, 2747c478bd9Sstevel@tonic-gate { IPOPT_SSRR, 0x002000 }, 2757c478bd9Sstevel@tonic-gate { IPOPT_ADDEXT, 0x004000 }, 2767c478bd9Sstevel@tonic-gate { IPOPT_VISA, 0x008000 }, 2777c478bd9Sstevel@tonic-gate { IPOPT_IMITD, 0x010000 }, 2787c478bd9Sstevel@tonic-gate { IPOPT_EIP, 0x020000 }, 2797c478bd9Sstevel@tonic-gate { IPOPT_FINN, 0x040000 }, 2807c478bd9Sstevel@tonic-gate { 0, 0x000000 } 2817c478bd9Sstevel@tonic-gate }; 2827c478bd9Sstevel@tonic-gate 2837c478bd9Sstevel@tonic-gate #ifdef USE_INET6 2847c478bd9Sstevel@tonic-gate struct optlist ip6exthdr[] = { 2857c478bd9Sstevel@tonic-gate { IPPROTO_HOPOPTS, 0x000001 }, 2867663b816Sml { IPPROTO_IPV6, 0x000002 }, 2877663b816Sml { IPPROTO_ROUTING, 0x000004 }, 2887663b816Sml { IPPROTO_FRAGMENT, 0x000008 }, 2897663b816Sml { IPPROTO_ESP, 0x000010 }, 2907663b816Sml { IPPROTO_AH, 0x000020 }, 2917663b816Sml { IPPROTO_NONE, 0x000040 }, 2927663b816Sml { IPPROTO_DSTOPTS, 0x000080 }, 2937663b816Sml { 0, 0 } 2947c478bd9Sstevel@tonic-gate }; 2957c478bd9Sstevel@tonic-gate #endif 2967c478bd9Sstevel@tonic-gate 2977c478bd9Sstevel@tonic-gate struct optlist tcpopts[] = { 2987c478bd9Sstevel@tonic-gate { TCPOPT_NOP, 0x000001 }, 2997c478bd9Sstevel@tonic-gate { TCPOPT_MAXSEG, 0x000002 }, 3007c478bd9Sstevel@tonic-gate { TCPOPT_WINDOW, 0x000004 }, 3017c478bd9Sstevel@tonic-gate { TCPOPT_SACK_PERMITTED, 0x000008 }, 3027c478bd9Sstevel@tonic-gate { TCPOPT_SACK, 0x000010 }, 3037c478bd9Sstevel@tonic-gate { TCPOPT_TIMESTAMP, 0x000020 }, 3047c478bd9Sstevel@tonic-gate { 0, 0x000000 } 3057c478bd9Sstevel@tonic-gate }; 3067c478bd9Sstevel@tonic-gate 3077c478bd9Sstevel@tonic-gate /* 3087c478bd9Sstevel@tonic-gate * bit values for identifying presence of individual IP security options 3097c478bd9Sstevel@tonic-gate */ 310ab25eeb5Syz const struct optlist secopt[8] = { 3117c478bd9Sstevel@tonic-gate { IPSO_CLASS_RES4, 0x01 }, 3127c478bd9Sstevel@tonic-gate { IPSO_CLASS_TOPS, 0x02 }, 3137c478bd9Sstevel@tonic-gate { IPSO_CLASS_SECR, 0x04 }, 3147c478bd9Sstevel@tonic-gate { IPSO_CLASS_RES3, 0x08 }, 3157c478bd9Sstevel@tonic-gate { IPSO_CLASS_CONF, 0x10 }, 3167c478bd9Sstevel@tonic-gate { IPSO_CLASS_UNCL, 0x20 }, 3177c478bd9Sstevel@tonic-gate { IPSO_CLASS_RES2, 0x40 }, 3187c478bd9Sstevel@tonic-gate { IPSO_CLASS_RES1, 0x80 } 3197c478bd9Sstevel@tonic-gate }; 3207c478bd9Sstevel@tonic-gate 3217c478bd9Sstevel@tonic-gate 3227c478bd9Sstevel@tonic-gate /* 3237c478bd9Sstevel@tonic-gate * Table of functions available for use with call rules. 3247c478bd9Sstevel@tonic-gate */ 3257c478bd9Sstevel@tonic-gate static ipfunc_resolve_t fr_availfuncs[] = { 3267c478bd9Sstevel@tonic-gate #ifdef IPFILTER_LOOKUP 3277c478bd9Sstevel@tonic-gate { "fr_srcgrpmap", fr_srcgrpmap, fr_grpmapinit }, 3287c478bd9Sstevel@tonic-gate { "fr_dstgrpmap", fr_dstgrpmap, fr_grpmapinit }, 3297c478bd9Sstevel@tonic-gate #endif 3307c478bd9Sstevel@tonic-gate { "", NULL } 3317c478bd9Sstevel@tonic-gate }; 3327c478bd9Sstevel@tonic-gate 3337c478bd9Sstevel@tonic-gate 3347c478bd9Sstevel@tonic-gate /* 3357c478bd9Sstevel@tonic-gate * The next section of code is a a collection of small routines that set 3367c478bd9Sstevel@tonic-gate * fields in the fr_info_t structure passed based on properties of the 3377c478bd9Sstevel@tonic-gate * current packet. There are different routines for the same protocol 3387c478bd9Sstevel@tonic-gate * for each of IPv4 and IPv6. Adding a new protocol, for which there 3397c478bd9Sstevel@tonic-gate * will "special" inspection for setup, is now more easily done by adding 3407c478bd9Sstevel@tonic-gate * a new routine and expanding the frpr_ipinit*() function rather than by 3417c478bd9Sstevel@tonic-gate * adding more code to a growing switch statement. 3427c478bd9Sstevel@tonic-gate */ 3437c478bd9Sstevel@tonic-gate #ifdef USE_INET6 344ab25eeb5Syz static INLINE int frpr_ah6 __P((fr_info_t *)); 345ab25eeb5Syz static INLINE void frpr_esp6 __P((fr_info_t *)); 346ab25eeb5Syz static INLINE void frpr_gre6 __P((fr_info_t *)); 3477c478bd9Sstevel@tonic-gate static INLINE void frpr_udp6 __P((fr_info_t *)); 3487c478bd9Sstevel@tonic-gate static INLINE void frpr_tcp6 __P((fr_info_t *)); 3497c478bd9Sstevel@tonic-gate static INLINE void frpr_icmp6 __P((fr_info_t *)); 3507663b816Sml static INLINE int frpr_ipv6hdr __P((fr_info_t *)); 3517c478bd9Sstevel@tonic-gate static INLINE void frpr_short6 __P((fr_info_t *, int)); 3527663b816Sml static INLINE int frpr_hopopts6 __P((fr_info_t *)); 3537663b816Sml static INLINE int frpr_routing6 __P((fr_info_t *)); 3547663b816Sml static INLINE int frpr_dstopts6 __P((fr_info_t *)); 3557663b816Sml static INLINE int frpr_fragment6 __P((fr_info_t *)); 356ab25eeb5Syz static INLINE int frpr_ipv6exthdr __P((fr_info_t *, int, int)); 3577c478bd9Sstevel@tonic-gate 3587c478bd9Sstevel@tonic-gate 3597c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 3607c478bd9Sstevel@tonic-gate /* Function: frpr_short6 */ 3617c478bd9Sstevel@tonic-gate /* Returns: void */ 3627c478bd9Sstevel@tonic-gate /* Parameters: fin(I) - pointer to packet information */ 3637c478bd9Sstevel@tonic-gate /* */ 3647c478bd9Sstevel@tonic-gate /* IPv6 Only */ 3657c478bd9Sstevel@tonic-gate /* This is function enforces the 'is a packet too short to be legit' rule */ 366ab25eeb5Syz /* for IPv6 and marks the packet with FI_SHORT if so. See function comment */ 367ab25eeb5Syz /* for frpr_short() for more details. */ 3687c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 369ab25eeb5Syz static INLINE void frpr_short6(fin, xmin) 3707c478bd9Sstevel@tonic-gate fr_info_t *fin; 371ab25eeb5Syz int xmin; 3727c478bd9Sstevel@tonic-gate { 3737c478bd9Sstevel@tonic-gate 374ab25eeb5Syz if (fin->fin_dlen < xmin) 375ab25eeb5Syz fin->fin_flx |= FI_SHORT; 3767c478bd9Sstevel@tonic-gate } 3777c478bd9Sstevel@tonic-gate 3787c478bd9Sstevel@tonic-gate 3797c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 3807c478bd9Sstevel@tonic-gate /* Function: frpr_ipv6hdr */ 3817663b816Sml /* Returns: int */ 3827c478bd9Sstevel@tonic-gate /* Parameters: fin(I) - pointer to packet information */ 3837c478bd9Sstevel@tonic-gate /* */ 3847c478bd9Sstevel@tonic-gate /* IPv6 Only */ 3857c478bd9Sstevel@tonic-gate /* Copy values from the IPv6 header into the fr_info_t struct and call the */ 3867c478bd9Sstevel@tonic-gate /* per-protocol analyzer if it exists. */ 3877c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 3887663b816Sml static INLINE int frpr_ipv6hdr(fin) 3897c478bd9Sstevel@tonic-gate fr_info_t *fin; 3907c478bd9Sstevel@tonic-gate { 3917c478bd9Sstevel@tonic-gate ip6_t *ip6 = (ip6_t *)fin->fin_ip; 392ab25eeb5Syz int p, go = 1, i, hdrcount; 3937c478bd9Sstevel@tonic-gate fr_ip_t *fi = &fin->fin_fi; 3947c478bd9Sstevel@tonic-gate 3957c478bd9Sstevel@tonic-gate fin->fin_off = 0; 3967c478bd9Sstevel@tonic-gate 3977c478bd9Sstevel@tonic-gate fi->fi_tos = 0; 3987c478bd9Sstevel@tonic-gate fi->fi_optmsk = 0; 3997c478bd9Sstevel@tonic-gate fi->fi_secmsk = 0; 4007c478bd9Sstevel@tonic-gate fi->fi_auth = 0; 4017c478bd9Sstevel@tonic-gate 4027c478bd9Sstevel@tonic-gate p = ip6->ip6_nxt; 4037c478bd9Sstevel@tonic-gate fi->fi_ttl = ip6->ip6_hlim; 4047c478bd9Sstevel@tonic-gate fi->fi_src.in6 = ip6->ip6_src; 4057c478bd9Sstevel@tonic-gate fi->fi_dst.in6 = ip6->ip6_dst; 4067663b816Sml fin->fin_id = 0; 4077c478bd9Sstevel@tonic-gate 4087c478bd9Sstevel@tonic-gate hdrcount = 0; 4097663b816Sml while (go && !(fin->fin_flx & (FI_BAD|FI_SHORT))) { 4107c478bd9Sstevel@tonic-gate switch (p) 4117c478bd9Sstevel@tonic-gate { 4127c478bd9Sstevel@tonic-gate case IPPROTO_UDP : 4137c478bd9Sstevel@tonic-gate frpr_udp6(fin); 4147c478bd9Sstevel@tonic-gate go = 0; 4157c478bd9Sstevel@tonic-gate break; 4167663b816Sml 4177c478bd9Sstevel@tonic-gate case IPPROTO_TCP : 4187c478bd9Sstevel@tonic-gate frpr_tcp6(fin); 4197c478bd9Sstevel@tonic-gate go = 0; 4207c478bd9Sstevel@tonic-gate break; 4217663b816Sml 4227c478bd9Sstevel@tonic-gate case IPPROTO_ICMPV6 : 4237c478bd9Sstevel@tonic-gate frpr_icmp6(fin); 4247c478bd9Sstevel@tonic-gate go = 0; 4257c478bd9Sstevel@tonic-gate break; 4267663b816Sml 4277663b816Sml case IPPROTO_GRE : 428ab25eeb5Syz frpr_gre6(fin); 4297663b816Sml go = 0; 4307663b816Sml break; 4317663b816Sml 4327c478bd9Sstevel@tonic-gate case IPPROTO_HOPOPTS : 4337c478bd9Sstevel@tonic-gate /* 434ab25eeb5Syz * hop by hop ext header is only allowed 435ab25eeb5Syz * right after IPv6 header. 4367c478bd9Sstevel@tonic-gate */ 437ab25eeb5Syz if (hdrcount != 0) { 4387663b816Sml fin->fin_flx |= FI_BAD; 439ab25eeb5Syz p = IPPROTO_NONE; 440ab25eeb5Syz } else { 441ab25eeb5Syz p = frpr_hopopts6(fin); 4427c478bd9Sstevel@tonic-gate } 4437c478bd9Sstevel@tonic-gate break; 4447663b816Sml 4457c478bd9Sstevel@tonic-gate case IPPROTO_DSTOPTS : 4467663b816Sml p = frpr_dstopts6(fin); 4477c478bd9Sstevel@tonic-gate break; 4487663b816Sml 4497c478bd9Sstevel@tonic-gate case IPPROTO_ROUTING : 4507663b816Sml p = frpr_routing6(fin); 4517c478bd9Sstevel@tonic-gate break; 4527663b816Sml 453ab25eeb5Syz case IPPROTO_AH : 454ab25eeb5Syz p = frpr_ah6(fin); 455ab25eeb5Syz break; 456ab25eeb5Syz 4577c478bd9Sstevel@tonic-gate case IPPROTO_ESP : 458ab25eeb5Syz frpr_esp6(fin); 4597663b816Sml go = 0; 4607663b816Sml break; 4617663b816Sml 462ab25eeb5Syz case IPPROTO_IPV6 : 4637663b816Sml for (i = 0; ip6exthdr[i].ol_bit != 0; i++) 4647663b816Sml if (ip6exthdr[i].ol_val == p) { 465ab25eeb5Syz fin->fin_flx |= ip6exthdr[i].ol_bit; 4667c478bd9Sstevel@tonic-gate break; 4677663b816Sml } 4687c478bd9Sstevel@tonic-gate go = 0; 4697c478bd9Sstevel@tonic-gate break; 4707663b816Sml 471ab25eeb5Syz case IPPROTO_NONE : 4727c478bd9Sstevel@tonic-gate go = 0; 4737c478bd9Sstevel@tonic-gate break; 4747663b816Sml 4757c478bd9Sstevel@tonic-gate case IPPROTO_FRAGMENT : 476ab25eeb5Syz p = frpr_fragment6(fin); 477ab25eeb5Syz if (fin->fin_off != 0) /* Not the first frag */ 4787663b816Sml go = 0; 4797663b816Sml break; 4807663b816Sml 4817c478bd9Sstevel@tonic-gate default : 4827c478bd9Sstevel@tonic-gate go = 0; 4837c478bd9Sstevel@tonic-gate break; 4847c478bd9Sstevel@tonic-gate } 4857c478bd9Sstevel@tonic-gate hdrcount++; 4867663b816Sml 487ab25eeb5Syz /* 488ab25eeb5Syz * It is important to note that at this point, for the 489ab25eeb5Syz * extension headers (go != 0), the entire header may not have 490ab25eeb5Syz * been pulled up when the code gets to this point. This is 491ab25eeb5Syz * only done for "go != 0" because the other header handlers 492ab25eeb5Syz * will all pullup their complete header. The other indicator 493ab25eeb5Syz * of an incomplete packet is that this was just an extension 494ab25eeb5Syz * header. 495ab25eeb5Syz */ 496ab25eeb5Syz if ((go != 0) && (p != IPPROTO_NONE) && 497ab25eeb5Syz (frpr_pullup(fin, 0) == -1)) { 498ab25eeb5Syz p = IPPROTO_NONE; 499ab25eeb5Syz go = 0; 500ab25eeb5Syz } 501ab25eeb5Syz } 5027663b816Sml fi->fi_p = p; 5037663b816Sml 504ab25eeb5Syz if (fin->fin_flx & FI_BAD) 505ab25eeb5Syz return -1; 506ab25eeb5Syz 5077663b816Sml return 0; 5087c478bd9Sstevel@tonic-gate } 5097c478bd9Sstevel@tonic-gate 5107c478bd9Sstevel@tonic-gate 5117c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 512ab25eeb5Syz /* Function: frpr_ipv6exthdr */ 5137663b816Sml /* Returns: int - value of the next header or IPPROTO_NONE if error */ 514ab25eeb5Syz /* Parameters: fin(I) - pointer to packet information */ 515ab25eeb5Syz /* multiple(I) - flag indicating yes/no if multiple occurances */ 516ab25eeb5Syz /* of this extension header are allowed. */ 517ab25eeb5Syz /* proto(I) - protocol number for this extension header */ 5187c478bd9Sstevel@tonic-gate /* */ 5197c478bd9Sstevel@tonic-gate /* IPv6 Only */ 5207c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 521ab25eeb5Syz static INLINE int frpr_ipv6exthdr(fin, multiple, proto) 5227c478bd9Sstevel@tonic-gate fr_info_t *fin; 523ab25eeb5Syz int multiple, proto; 5247c478bd9Sstevel@tonic-gate { 5257c478bd9Sstevel@tonic-gate struct ip6_ext *hdr; 5267c478bd9Sstevel@tonic-gate u_short shift; 5277c478bd9Sstevel@tonic-gate int i; 5287c478bd9Sstevel@tonic-gate 5297c478bd9Sstevel@tonic-gate fin->fin_flx |= FI_V6EXTHDR; 5307c478bd9Sstevel@tonic-gate 531ab25eeb5Syz /* 8 is default length of extension hdr */ 532ab25eeb5Syz if ((fin->fin_dlen - 8) < 0) { 533ab25eeb5Syz fin->fin_flx |= FI_SHORT; 5347663b816Sml return IPPROTO_NONE; 535ab25eeb5Syz } 5367663b816Sml 5377663b816Sml if (frpr_pullup(fin, 8) == -1) 5387663b816Sml return IPPROTO_NONE; 5397c478bd9Sstevel@tonic-gate 5407c478bd9Sstevel@tonic-gate hdr = fin->fin_dp; 5417c478bd9Sstevel@tonic-gate shift = 8 + (hdr->ip6e_len << 3); 5427c478bd9Sstevel@tonic-gate if (shift > fin->fin_dlen) { /* Nasty extension header length? */ 5437c478bd9Sstevel@tonic-gate fin->fin_flx |= FI_BAD; 5447663b816Sml return IPPROTO_NONE; 5457c478bd9Sstevel@tonic-gate } 5467c478bd9Sstevel@tonic-gate 5477663b816Sml for (i = 0; ip6exthdr[i].ol_bit != 0; i++) 548ab25eeb5Syz if (ip6exthdr[i].ol_val == proto) { 549ab25eeb5Syz /* 550ab25eeb5Syz * Most IPv6 extension headers are only allowed once. 551ab25eeb5Syz */ 552ab25eeb5Syz if ((multiple == 0) && 553ab25eeb5Syz ((fin->fin_optmsk & ip6exthdr[i].ol_bit) != 0)) 554ab25eeb5Syz fin->fin_flx |= FI_BAD; 555ab25eeb5Syz else 556ab25eeb5Syz fin->fin_optmsk |= ip6exthdr[i].ol_bit; 5577c478bd9Sstevel@tonic-gate break; 5587663b816Sml } 5597c478bd9Sstevel@tonic-gate 5607c478bd9Sstevel@tonic-gate fin->fin_dp = (char *)fin->fin_dp + shift; 5617c478bd9Sstevel@tonic-gate fin->fin_dlen -= shift; 5627c478bd9Sstevel@tonic-gate 5637663b816Sml return hdr->ip6e_nxt; 5647c478bd9Sstevel@tonic-gate } 5657c478bd9Sstevel@tonic-gate 5667c478bd9Sstevel@tonic-gate 567ab25eeb5Syz /* ------------------------------------------------------------------------ */ 568ab25eeb5Syz /* Function: frpr_hopopts6 */ 569ab25eeb5Syz /* Returns: int - value of the next header or IPPROTO_NONE if error */ 570ab25eeb5Syz /* Parameters: fin(I) - pointer to packet information */ 571ab25eeb5Syz /* */ 572ab25eeb5Syz /* IPv6 Only */ 573ab25eeb5Syz /* This is function checks pending hop by hop options extension header */ 574ab25eeb5Syz /* ------------------------------------------------------------------------ */ 575ab25eeb5Syz static INLINE int frpr_hopopts6(fin) 576ab25eeb5Syz fr_info_t *fin; 577ab25eeb5Syz { 578ab25eeb5Syz return frpr_ipv6exthdr(fin, 0, IPPROTO_HOPOPTS); 579ab25eeb5Syz } 580ab25eeb5Syz 581ab25eeb5Syz 5827c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 5837c478bd9Sstevel@tonic-gate /* Function: frpr_routing6 */ 5847663b816Sml /* Returns: int - value of the next header or IPPROTO_NONE if error */ 5857c478bd9Sstevel@tonic-gate /* Parameters: fin(I) - pointer to packet information */ 5867c478bd9Sstevel@tonic-gate /* */ 5877c478bd9Sstevel@tonic-gate /* IPv6 Only */ 5887c478bd9Sstevel@tonic-gate /* This is function checks pending routing extension header */ 5897c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 5907663b816Sml static INLINE int frpr_routing6(fin) 5917c478bd9Sstevel@tonic-gate fr_info_t *fin; 5927c478bd9Sstevel@tonic-gate { 5937c478bd9Sstevel@tonic-gate struct ip6_ext *hdr; 594ab25eeb5Syz int shift; 5957c478bd9Sstevel@tonic-gate 5967c478bd9Sstevel@tonic-gate hdr = fin->fin_dp; 597ab25eeb5Syz if (frpr_ipv6exthdr(fin, 0, IPPROTO_ROUTING) == IPPROTO_NONE) 598ab25eeb5Syz return IPPROTO_NONE; 5997663b816Sml 6007c478bd9Sstevel@tonic-gate shift = 8 + (hdr->ip6e_len << 3); 6017c478bd9Sstevel@tonic-gate /* 6027c478bd9Sstevel@tonic-gate * Nasty extension header length? 6037c478bd9Sstevel@tonic-gate */ 604ab25eeb5Syz if ((hdr->ip6e_len << 3) & 15) { 6057c478bd9Sstevel@tonic-gate fin->fin_flx |= FI_BAD; 606ab25eeb5Syz /* 607ab25eeb5Syz * Compensate for the changes made in frpr_ipv6exthdr() 608ab25eeb5Syz */ 609ab25eeb5Syz fin->fin_dlen += shift; 610ab25eeb5Syz fin->fin_dp = (char *)fin->fin_dp - shift; 6117663b816Sml return IPPROTO_NONE; 6127c478bd9Sstevel@tonic-gate } 6137c478bd9Sstevel@tonic-gate 6147663b816Sml return hdr->ip6e_nxt; 6157c478bd9Sstevel@tonic-gate } 6167c478bd9Sstevel@tonic-gate 6177c478bd9Sstevel@tonic-gate 6187c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 6197c478bd9Sstevel@tonic-gate /* Function: frpr_fragment6 */ 6207663b816Sml /* Returns: int - value of the next header or IPPROTO_NONE if error */ 6217c478bd9Sstevel@tonic-gate /* Parameters: fin(I) - pointer to packet information */ 6227c478bd9Sstevel@tonic-gate /* */ 6237c478bd9Sstevel@tonic-gate /* IPv6 Only */ 6247c478bd9Sstevel@tonic-gate /* Examine the IPv6 fragment header and extract fragment offset information.*/ 625ab25eeb5Syz /* */ 626ab25eeb5Syz /* We don't know where the transport layer header (or whatever is next is), */ 627ab25eeb5Syz /* as it could be behind destination options (amongst others). Because */ 628ab25eeb5Syz /* there is no fragment cache, there is no knowledge about whether or not an*/ 629ab25eeb5Syz /* upper layer header has been seen (or where it ends) and thus we are not */ 630ab25eeb5Syz /* able to continue processing beyond this header with any confidence. */ 6317c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 6327663b816Sml static INLINE int frpr_fragment6(fin) 6337c478bd9Sstevel@tonic-gate fr_info_t *fin; 6347c478bd9Sstevel@tonic-gate { 6357c478bd9Sstevel@tonic-gate struct ip6_frag *frag; 636ab25eeb5Syz int dlen; 6377663b816Sml 638ab25eeb5Syz fin->fin_flx |= FI_FRAG; 6397c478bd9Sstevel@tonic-gate 640ab25eeb5Syz dlen = fin->fin_dlen; 641ab25eeb5Syz if (frpr_ipv6exthdr(fin, 0, IPPROTO_FRAGMENT) == IPPROTO_NONE) 6427663b816Sml return IPPROTO_NONE; 6437663b816Sml 644ab25eeb5Syz if (frpr_pullup(fin, sizeof(*frag)) == -1) 6457663b816Sml return IPPROTO_NONE; 6467c478bd9Sstevel@tonic-gate 647ab25eeb5Syz frpr_short6(fin, sizeof(*frag)); 648ab25eeb5Syz 649ab25eeb5Syz if ((fin->fin_flx & FI_SHORT) != 0) 6507663b816Sml return IPPROTO_NONE; 6517c478bd9Sstevel@tonic-gate 652ab25eeb5Syz frag = (struct ip6_frag *)((char *)fin->fin_dp - sizeof(*frag)); 653ab25eeb5Syz /* 654ab25eeb5Syz * Fragment but no fragmentation info set? Bad packet... 655ab25eeb5Syz */ 656ab25eeb5Syz if (frag->ip6f_offlg == 0) { 657ab25eeb5Syz fin->fin_flx |= FI_BAD; 6587663b816Sml return IPPROTO_NONE; 6597c478bd9Sstevel@tonic-gate } 6607c478bd9Sstevel@tonic-gate 6617663b816Sml fin->fin_id = frag->ip6f_ident; 6627c478bd9Sstevel@tonic-gate fin->fin_off = frag->ip6f_offlg & IP6F_OFF_MASK; 6637663b816Sml fin->fin_off = ntohs(fin->fin_off); 664ab25eeb5Syz if (fin->fin_off != 0) 665ab25eeb5Syz fin->fin_flx |= FI_FRAGBODY; 6667c478bd9Sstevel@tonic-gate 667ab25eeb5Syz fin->fin_dp = (char *)frag + sizeof(*frag); 668ab25eeb5Syz fin->fin_dlen = dlen - sizeof(*frag); 6697c478bd9Sstevel@tonic-gate 6707663b816Sml /* length of hdrs(after frag hdr) + data */ 6717663b816Sml fin->fin_flen = fin->fin_dlen; 6727663b816Sml 673ab25eeb5Syz /* 674ab25eeb5Syz * If the frag is not the last one and the payload length 675ab25eeb5Syz * is not multiple of 8, it must be dropped. 676ab25eeb5Syz */ 677ab25eeb5Syz if ((frag->ip6f_offlg & IP6F_MORE_FRAG) && (dlen % 8)) { 678ab25eeb5Syz fin->fin_flx |= FI_BAD; 679ab25eeb5Syz return IPPROTO_NONE; 680ab25eeb5Syz } 681ab25eeb5Syz 6827663b816Sml return frag->ip6f_nxt; 6837c478bd9Sstevel@tonic-gate } 6847c478bd9Sstevel@tonic-gate 6857c478bd9Sstevel@tonic-gate 6867c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 6877c478bd9Sstevel@tonic-gate /* Function: frpr_dstopts6 */ 6887663b816Sml /* Returns: int - value of the next header or IPPROTO_NONE if error */ 6897c478bd9Sstevel@tonic-gate /* Parameters: fin(I) - pointer to packet information */ 6907c478bd9Sstevel@tonic-gate /* nextheader(I) - stores next header value */ 6917c478bd9Sstevel@tonic-gate /* */ 6927c478bd9Sstevel@tonic-gate /* IPv6 Only */ 6937c478bd9Sstevel@tonic-gate /* This is function checks pending destination options extension header */ 6947c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 6957663b816Sml static INLINE int frpr_dstopts6(fin) 6967c478bd9Sstevel@tonic-gate fr_info_t *fin; 6977c478bd9Sstevel@tonic-gate { 698ab25eeb5Syz return frpr_ipv6exthdr(fin, 1, IPPROTO_DSTOPTS); 6997c478bd9Sstevel@tonic-gate } 7007c478bd9Sstevel@tonic-gate 7017c478bd9Sstevel@tonic-gate 7027c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 7037c478bd9Sstevel@tonic-gate /* Function: frpr_icmp6 */ 7047c478bd9Sstevel@tonic-gate /* Returns: void */ 7057c478bd9Sstevel@tonic-gate /* Parameters: fin(I) - pointer to packet information */ 7067c478bd9Sstevel@tonic-gate /* */ 7077c478bd9Sstevel@tonic-gate /* IPv6 Only */ 7087c478bd9Sstevel@tonic-gate /* This routine is mainly concerned with determining the minimum valid size */ 7097c478bd9Sstevel@tonic-gate /* for an ICMPv6 packet. */ 7107c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 7117c478bd9Sstevel@tonic-gate static INLINE void frpr_icmp6(fin) 7127c478bd9Sstevel@tonic-gate fr_info_t *fin; 7137c478bd9Sstevel@tonic-gate { 7147c478bd9Sstevel@tonic-gate int minicmpsz = sizeof(struct icmp6_hdr); 7157c478bd9Sstevel@tonic-gate struct icmp6_hdr *icmp6; 7167c478bd9Sstevel@tonic-gate 717ab25eeb5Syz if (frpr_pullup(fin, ICMP6ERR_MINPKTLEN - sizeof(ip6_t)) == -1) 7187663b816Sml return; 7197663b816Sml 7207c478bd9Sstevel@tonic-gate if (fin->fin_dlen > 1) { 7217c478bd9Sstevel@tonic-gate icmp6 = fin->fin_dp; 7227c478bd9Sstevel@tonic-gate 7237c478bd9Sstevel@tonic-gate fin->fin_data[0] = *(u_short *)icmp6; 7247c478bd9Sstevel@tonic-gate 7257c478bd9Sstevel@tonic-gate switch (icmp6->icmp6_type) 7267c478bd9Sstevel@tonic-gate { 7277c478bd9Sstevel@tonic-gate case ICMP6_ECHO_REPLY : 7287c478bd9Sstevel@tonic-gate case ICMP6_ECHO_REQUEST : 7297c478bd9Sstevel@tonic-gate minicmpsz = ICMP6ERR_MINPKTLEN - sizeof(ip6_t); 7307c478bd9Sstevel@tonic-gate break; 7317c478bd9Sstevel@tonic-gate case ICMP6_DST_UNREACH : 7327c478bd9Sstevel@tonic-gate case ICMP6_PACKET_TOO_BIG : 7337c478bd9Sstevel@tonic-gate case ICMP6_TIME_EXCEEDED : 7347c478bd9Sstevel@tonic-gate case ICMP6_PARAM_PROB : 7357c478bd9Sstevel@tonic-gate if ((fin->fin_m != NULL) && 7367c478bd9Sstevel@tonic-gate (M_LEN(fin->fin_m) < fin->fin_plen)) { 7377663b816Sml if (fr_coalesce(fin) != 1) 7387c478bd9Sstevel@tonic-gate return; 7397c478bd9Sstevel@tonic-gate } 7407c478bd9Sstevel@tonic-gate fin->fin_flx |= FI_ICMPERR; 7417c478bd9Sstevel@tonic-gate minicmpsz = ICMP6ERR_IPICMPHLEN - sizeof(ip6_t); 7427c478bd9Sstevel@tonic-gate break; 7437c478bd9Sstevel@tonic-gate default : 7447c478bd9Sstevel@tonic-gate break; 7457c478bd9Sstevel@tonic-gate } 7467c478bd9Sstevel@tonic-gate } 7477c478bd9Sstevel@tonic-gate 7487c478bd9Sstevel@tonic-gate frpr_short6(fin, minicmpsz); 7497663b816Sml fin->fin_flen -= fin->fin_dlen - minicmpsz; 7507c478bd9Sstevel@tonic-gate } 7517c478bd9Sstevel@tonic-gate 7527c478bd9Sstevel@tonic-gate 7537c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 7547c478bd9Sstevel@tonic-gate /* Function: frpr_udp6 */ 7557c478bd9Sstevel@tonic-gate /* Returns: void */ 7567c478bd9Sstevel@tonic-gate /* Parameters: fin(I) - pointer to packet information */ 7577c478bd9Sstevel@tonic-gate /* */ 7587c478bd9Sstevel@tonic-gate /* IPv6 Only */ 7597c478bd9Sstevel@tonic-gate /* Analyse the packet for IPv6/UDP properties. */ 760ab25eeb5Syz /* Is not expected to be called for fragmented packets. */ 7617c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 7627c478bd9Sstevel@tonic-gate static INLINE void frpr_udp6(fin) 7637c478bd9Sstevel@tonic-gate fr_info_t *fin; 7647c478bd9Sstevel@tonic-gate { 7657c478bd9Sstevel@tonic-gate 7667c478bd9Sstevel@tonic-gate fr_checkv6sum(fin); 7677c478bd9Sstevel@tonic-gate 7687c478bd9Sstevel@tonic-gate frpr_short6(fin, sizeof(struct udphdr)); 76908254dd3Syz if (frpr_pullup(fin, sizeof(struct udphdr)) == -1) 77008254dd3Syz return; 7717c478bd9Sstevel@tonic-gate 7727663b816Sml fin->fin_flen -= fin->fin_dlen - sizeof(struct udphdr); 7737663b816Sml 7747c478bd9Sstevel@tonic-gate frpr_udpcommon(fin); 7757c478bd9Sstevel@tonic-gate } 7767c478bd9Sstevel@tonic-gate 7777c478bd9Sstevel@tonic-gate 7787c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 7797c478bd9Sstevel@tonic-gate /* Function: frpr_tcp6 */ 7807c478bd9Sstevel@tonic-gate /* Returns: void */ 7817c478bd9Sstevel@tonic-gate /* Parameters: fin(I) - pointer to packet information */ 7827c478bd9Sstevel@tonic-gate /* */ 7837c478bd9Sstevel@tonic-gate /* IPv6 Only */ 7847c478bd9Sstevel@tonic-gate /* Analyse the packet for IPv6/TCP properties. */ 785ab25eeb5Syz /* Is not expected to be called for fragmented packets. */ 7867c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 7877c478bd9Sstevel@tonic-gate static INLINE void frpr_tcp6(fin) 7887c478bd9Sstevel@tonic-gate fr_info_t *fin; 7897c478bd9Sstevel@tonic-gate { 7907c478bd9Sstevel@tonic-gate 7917c478bd9Sstevel@tonic-gate fr_checkv6sum(fin); 7927c478bd9Sstevel@tonic-gate 7937c478bd9Sstevel@tonic-gate frpr_short6(fin, sizeof(struct tcphdr)); 79408254dd3Syz if (frpr_pullup(fin, sizeof(struct tcphdr)) == -1) 79508254dd3Syz return; 7967c478bd9Sstevel@tonic-gate 7977663b816Sml fin->fin_flen -= fin->fin_dlen - sizeof(struct tcphdr); 7987663b816Sml 7997c478bd9Sstevel@tonic-gate frpr_tcpcommon(fin); 8007c478bd9Sstevel@tonic-gate } 801ab25eeb5Syz 802ab25eeb5Syz 803ab25eeb5Syz /* ------------------------------------------------------------------------ */ 804ab25eeb5Syz /* Function: frpr_esp6 */ 805ab25eeb5Syz /* Returns: void */ 806ab25eeb5Syz /* Parameters: fin(I) - pointer to packet information */ 807ab25eeb5Syz /* */ 808ab25eeb5Syz /* IPv6 Only */ 809ab25eeb5Syz /* Analyse the packet for ESP properties. */ 810ab25eeb5Syz /* The minimum length is taken to be the SPI (32bits) plus a tail (32bits) */ 811ab25eeb5Syz /* even though the newer ESP packets must also have a sequence number that */ 812ab25eeb5Syz /* is 32bits as well, it is not possible(?) to determine the version from a */ 813ab25eeb5Syz /* simple packet header. */ 814ab25eeb5Syz /* ------------------------------------------------------------------------ */ 815ab25eeb5Syz static INLINE void frpr_esp6(fin) 816ab25eeb5Syz fr_info_t *fin; 817ab25eeb5Syz { 818ab25eeb5Syz int i; 819ab25eeb5Syz frpr_short6(fin, sizeof(grehdr_t)); 820ab25eeb5Syz 821ab25eeb5Syz (void) frpr_pullup(fin, 8); 822ab25eeb5Syz 823ab25eeb5Syz for (i = 0; ip6exthdr[i].ol_bit != 0; i++) 824ab25eeb5Syz if (ip6exthdr[i].ol_val == IPPROTO_ESP) { 825ab25eeb5Syz fin->fin_optmsk |= ip6exthdr[i].ol_bit; 826ab25eeb5Syz break; 827ab25eeb5Syz } 828ab25eeb5Syz } 829ab25eeb5Syz 830ab25eeb5Syz 831ab25eeb5Syz /* ------------------------------------------------------------------------ */ 832ab25eeb5Syz /* Function: frpr_ah6 */ 833ab25eeb5Syz /* Returns: void */ 834ab25eeb5Syz /* Parameters: fin(I) - pointer to packet information */ 835ab25eeb5Syz /* */ 836ab25eeb5Syz /* IPv6 Only */ 837ab25eeb5Syz /* Analyse the packet for AH properties. */ 838ab25eeb5Syz /* The minimum length is taken to be the combination of all fields in the */ 839ab25eeb5Syz /* header being present and no authentication data (null algorithm used.) */ 840ab25eeb5Syz /* ------------------------------------------------------------------------ */ 841ab25eeb5Syz static INLINE int frpr_ah6(fin) 842ab25eeb5Syz fr_info_t *fin; 843ab25eeb5Syz { 844ab25eeb5Syz authhdr_t *ah; 845ab25eeb5Syz int i, shift; 846ab25eeb5Syz 847ab25eeb5Syz frpr_short6(fin, 12); 848ab25eeb5Syz 849ab25eeb5Syz if (frpr_pullup(fin, sizeof(*ah)) == -1) 850ab25eeb5Syz return IPPROTO_NONE; 851ab25eeb5Syz 852ab25eeb5Syz for (i = 0; ip6exthdr[i].ol_bit != 0; i++) 853ab25eeb5Syz if (ip6exthdr[i].ol_val == IPPROTO_AH) { 854ab25eeb5Syz fin->fin_optmsk |= ip6exthdr[i].ol_bit; 855ab25eeb5Syz break; 856ab25eeb5Syz } 857ab25eeb5Syz 858ab25eeb5Syz ah = (authhdr_t *)fin->fin_dp; 859ab25eeb5Syz 860ab25eeb5Syz shift = (ah->ah_plen + 2) * 4; 861ab25eeb5Syz fin->fin_dlen -= shift; 862ab25eeb5Syz fin->fin_dp = (char*)fin->fin_dp + shift; 863ab25eeb5Syz 864ab25eeb5Syz return ah->ah_next; 865ab25eeb5Syz } 866ab25eeb5Syz 867ab25eeb5Syz 868ab25eeb5Syz /* ------------------------------------------------------------------------ */ 869ab25eeb5Syz /* Function: frpr_gre6 */ 870ab25eeb5Syz /* Returns: void */ 871ab25eeb5Syz /* Parameters: fin(I) - pointer to packet information */ 872ab25eeb5Syz /* */ 873ab25eeb5Syz /* Analyse the packet for GRE properties. */ 874ab25eeb5Syz /* ------------------------------------------------------------------------ */ 875ab25eeb5Syz static INLINE void frpr_gre6(fin) 876ab25eeb5Syz fr_info_t *fin; 877ab25eeb5Syz { 878ab25eeb5Syz grehdr_t *gre; 879ab25eeb5Syz 880ab25eeb5Syz frpr_short6(fin, sizeof(grehdr_t)); 881ab25eeb5Syz 882ab25eeb5Syz if (frpr_pullup(fin, sizeof(grehdr_t)) == -1) 883ab25eeb5Syz return; 884ab25eeb5Syz 885ab25eeb5Syz gre = fin->fin_dp; 886ab25eeb5Syz if (GRE_REV(gre->gr_flags) == 1) 887ab25eeb5Syz fin->fin_data[0] = gre->gr_call; 888ab25eeb5Syz } 8897c478bd9Sstevel@tonic-gate #endif /* USE_INET6 */ 8907c478bd9Sstevel@tonic-gate 8917c478bd9Sstevel@tonic-gate 8927663b816Sml /* ------------------------------------------------------------------------ */ 8937663b816Sml /* Function: frpr_pullup */ 8947663b816Sml /* Returns: int - 0 == pullup succeeded, -1 == failure */ 8957663b816Sml /* Parameters: fin(I) - pointer to packet information */ 8967663b816Sml /* plen(I) - length (excluding L3 header) to pullup */ 8977663b816Sml /* */ 8987663b816Sml /* Short inline function to cut down on code duplication to perform a call */ 8997663b816Sml /* to fr_pullup to ensure there is the required amount of data, */ 9007663b816Sml /* consecutively in the packet buffer. */ 9017663b816Sml /* ------------------------------------------------------------------------ */ 9027663b816Sml static INLINE int frpr_pullup(fin, plen) 9037663b816Sml fr_info_t *fin; 9047663b816Sml int plen; 9057663b816Sml { 906ab25eeb5Syz #if defined(_KERNEL) 9077663b816Sml if (fin->fin_m != NULL) { 9087663b816Sml if (fin->fin_dp != NULL) 9097663b816Sml plen += (char *)fin->fin_dp - 9107663b816Sml ((char *)fin->fin_ip + fin->fin_hlen); 91108254dd3Syz plen += ((char *)fin->fin_ip - MTOD(fin->fin_m, char *)) + 91208254dd3Syz fin->fin_hlen; 9137663b816Sml if (M_LEN(fin->fin_m) < plen) { 9147663b816Sml if (fr_pullup(fin->fin_m, fin, plen) == NULL) 9157663b816Sml return -1; 9167663b816Sml } 9177663b816Sml } 9187663b816Sml #endif 9197663b816Sml return 0; 9207663b816Sml } 9217663b816Sml 9227663b816Sml 9237c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 9247c478bd9Sstevel@tonic-gate /* Function: frpr_short */ 9257c478bd9Sstevel@tonic-gate /* Returns: void */ 926ab25eeb5Syz /* Parameters: fin(I) - pointer to packet information */ 927ab25eeb5Syz /* xmin(I) - minimum header size */ 9287c478bd9Sstevel@tonic-gate /* */ 929ab25eeb5Syz /* Check if a packet is "short" as defined by xmin. The rule we are */ 930ab25eeb5Syz /* applying here is that the packet must not be fragmented within the layer */ 931ab25eeb5Syz /* 4 header. That is, it must not be a fragment that has its offset set to */ 932ab25eeb5Syz /* start within the layer 4 header (hdrmin) or if it is at offset 0, the */ 933ab25eeb5Syz /* entire layer 4 header must be present (min). */ 9347c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 935ab25eeb5Syz static INLINE void frpr_short(fin, xmin) 9367c478bd9Sstevel@tonic-gate fr_info_t *fin; 937ab25eeb5Syz int xmin; 9387c478bd9Sstevel@tonic-gate { 9397c478bd9Sstevel@tonic-gate 940ab25eeb5Syz if (fin->fin_off == 0) { 941ab25eeb5Syz if (fin->fin_dlen < xmin) 942ab25eeb5Syz fin->fin_flx |= FI_SHORT; 943ab25eeb5Syz } else if (fin->fin_off < xmin) { 944ab25eeb5Syz fin->fin_flx |= FI_SHORT; 9457c478bd9Sstevel@tonic-gate } 9467c478bd9Sstevel@tonic-gate } 9477c478bd9Sstevel@tonic-gate 9487c478bd9Sstevel@tonic-gate 9497c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 9507c478bd9Sstevel@tonic-gate /* Function: frpr_icmp */ 9517c478bd9Sstevel@tonic-gate /* Returns: void */ 9527c478bd9Sstevel@tonic-gate /* Parameters: fin(I) - pointer to packet information */ 9537c478bd9Sstevel@tonic-gate /* */ 9547c478bd9Sstevel@tonic-gate /* IPv4 Only */ 9557c478bd9Sstevel@tonic-gate /* Do a sanity check on the packet for ICMP (v4). In nearly all cases, */ 9567c478bd9Sstevel@tonic-gate /* except extrememly bad packets, both type and code will be present. */ 957ab25eeb5Syz /* The expected minimum size of an ICMP packet is very much dependent on */ 9587c478bd9Sstevel@tonic-gate /* the type of it. */ 9597c478bd9Sstevel@tonic-gate /* */ 9607c478bd9Sstevel@tonic-gate /* XXX - other ICMP sanity checks? */ 9617c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 9627c478bd9Sstevel@tonic-gate static INLINE void frpr_icmp(fin) 9637c478bd9Sstevel@tonic-gate fr_info_t *fin; 9647c478bd9Sstevel@tonic-gate { 9657c478bd9Sstevel@tonic-gate int minicmpsz = sizeof(struct icmp); 9667c478bd9Sstevel@tonic-gate icmphdr_t *icmp; 967ab25eeb5Syz ip_t *oip; 9687c478bd9Sstevel@tonic-gate 96962685e53Sml if (fin->fin_off != 0) { 97062685e53Sml frpr_short(fin, ICMPERR_ICMPHLEN); 97162685e53Sml return; 97262685e53Sml } 97362685e53Sml 974ab25eeb5Syz if (frpr_pullup(fin, ICMPERR_ICMPHLEN) == -1) 975ab25eeb5Syz return; 976ab25eeb5Syz 9777c478bd9Sstevel@tonic-gate fr_checkv4sum(fin); 9787c478bd9Sstevel@tonic-gate 97962685e53Sml if (fin->fin_dlen > 1) { 9807c478bd9Sstevel@tonic-gate icmp = fin->fin_dp; 9817c478bd9Sstevel@tonic-gate 9827c478bd9Sstevel@tonic-gate fin->fin_data[0] = *(u_short *)icmp; 9837c478bd9Sstevel@tonic-gate 9847c478bd9Sstevel@tonic-gate switch (icmp->icmp_type) 9857c478bd9Sstevel@tonic-gate { 9867c478bd9Sstevel@tonic-gate case ICMP_ECHOREPLY : 9877c478bd9Sstevel@tonic-gate case ICMP_ECHO : 9887c478bd9Sstevel@tonic-gate /* Router discovery messaes - RFC 1256 */ 9897c478bd9Sstevel@tonic-gate case ICMP_ROUTERADVERT : 9907c478bd9Sstevel@tonic-gate case ICMP_ROUTERSOLICIT : 9917c478bd9Sstevel@tonic-gate minicmpsz = ICMP_MINLEN; 9927c478bd9Sstevel@tonic-gate break; 9937c478bd9Sstevel@tonic-gate /* 9947c478bd9Sstevel@tonic-gate * type(1) + code(1) + cksum(2) + id(2) seq(2) + 9957c478bd9Sstevel@tonic-gate * 3 * timestamp(3 * 4) 9967c478bd9Sstevel@tonic-gate */ 9977c478bd9Sstevel@tonic-gate case ICMP_TSTAMP : 9987c478bd9Sstevel@tonic-gate case ICMP_TSTAMPREPLY : 9997c478bd9Sstevel@tonic-gate minicmpsz = 20; 10007c478bd9Sstevel@tonic-gate break; 10017c478bd9Sstevel@tonic-gate /* 10027c478bd9Sstevel@tonic-gate * type(1) + code(1) + cksum(2) + id(2) seq(2) + 10037c478bd9Sstevel@tonic-gate * mask(4) 10047c478bd9Sstevel@tonic-gate */ 10057c478bd9Sstevel@tonic-gate case ICMP_MASKREQ : 10067c478bd9Sstevel@tonic-gate case ICMP_MASKREPLY : 10077c478bd9Sstevel@tonic-gate minicmpsz = 12; 10087c478bd9Sstevel@tonic-gate break; 10097c478bd9Sstevel@tonic-gate /* 10107c478bd9Sstevel@tonic-gate * type(1) + code(1) + cksum(2) + id(2) seq(2) + ip(20+) 10117c478bd9Sstevel@tonic-gate */ 10127c478bd9Sstevel@tonic-gate case ICMP_UNREACH : 1013ab25eeb5Syz if (icmp->icmp_code == ICMP_UNREACH_NEEDFRAG) { 1014ab25eeb5Syz if (icmp->icmp_nextmtu < fr_icmpminfragmtu) 1015ab25eeb5Syz fin->fin_flx |= FI_BAD; 1016ab25eeb5Syz } 1017ab25eeb5Syz /* FALLTHRU */ 10187c478bd9Sstevel@tonic-gate case ICMP_SOURCEQUENCH : 10197c478bd9Sstevel@tonic-gate case ICMP_REDIRECT : 10207c478bd9Sstevel@tonic-gate case ICMP_TIMXCEED : 10217c478bd9Sstevel@tonic-gate case ICMP_PARAMPROB : 10227c478bd9Sstevel@tonic-gate fin->fin_flx |= FI_ICMPERR; 1023ab25eeb5Syz if (fr_coalesce(fin) != 1) 1024ab25eeb5Syz return; 1025ab25eeb5Syz /* 1026ab25eeb5Syz * ICMP error packets should not be generated for IP 1027ab25eeb5Syz * packets that are a fragment that isn't the first 1028ab25eeb5Syz * fragment. 1029ab25eeb5Syz */ 1030ab25eeb5Syz oip = (ip_t *)((char *)fin->fin_dp + ICMPERR_ICMPHLEN); 1031ab25eeb5Syz if ((ntohs(oip->ip_off) & IP_OFFMASK) != 0) 1032ab25eeb5Syz fin->fin_flx |= FI_BAD; 10337c478bd9Sstevel@tonic-gate break; 10347c478bd9Sstevel@tonic-gate default : 10357c478bd9Sstevel@tonic-gate break; 10367c478bd9Sstevel@tonic-gate } 1037ab25eeb5Syz 1038ab25eeb5Syz if (fin->fin_dlen >= 6) /* ID field */ 1039ab25eeb5Syz fin->fin_data[1] = icmp->icmp_id; 10407c478bd9Sstevel@tonic-gate } 10417c478bd9Sstevel@tonic-gate 10427663b816Sml frpr_short(fin, minicmpsz); 10437c478bd9Sstevel@tonic-gate } 10447c478bd9Sstevel@tonic-gate 10457c478bd9Sstevel@tonic-gate 10467c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 10477c478bd9Sstevel@tonic-gate /* Function: frpr_tcpcommon */ 10487c478bd9Sstevel@tonic-gate /* Returns: void */ 10497c478bd9Sstevel@tonic-gate /* Parameters: fin(I) - pointer to packet information */ 10507c478bd9Sstevel@tonic-gate /* */ 10517c478bd9Sstevel@tonic-gate /* TCP header sanity checking. Look for bad combinations of TCP flags, */ 10527c478bd9Sstevel@tonic-gate /* and make some checks with how they interact with other fields. */ 10537c478bd9Sstevel@tonic-gate /* If compiled with IPFILTER_CKSUM, check to see if the TCP checksum is */ 10547c478bd9Sstevel@tonic-gate /* valid and mark the packet as bad if not. */ 10557c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 10567c478bd9Sstevel@tonic-gate static INLINE void frpr_tcpcommon(fin) 10577c478bd9Sstevel@tonic-gate fr_info_t *fin; 10587c478bd9Sstevel@tonic-gate { 10597c478bd9Sstevel@tonic-gate int flags, tlen; 10607c478bd9Sstevel@tonic-gate tcphdr_t *tcp; 10617c478bd9Sstevel@tonic-gate 106262685e53Sml fin->fin_flx |= FI_TCPUDP; 106362685e53Sml if (fin->fin_off != 0) 106462685e53Sml return; 106562685e53Sml 1066ab25eeb5Syz if (frpr_pullup(fin, sizeof(*tcp)) == -1) 1067ab25eeb5Syz return; 10687c478bd9Sstevel@tonic-gate tcp = fin->fin_dp; 10697c478bd9Sstevel@tonic-gate 1070ab25eeb5Syz if (fin->fin_dlen > 3) { 1071ab25eeb5Syz fin->fin_sport = ntohs(tcp->th_sport); 1072ab25eeb5Syz fin->fin_dport = ntohs(tcp->th_dport); 10737c478bd9Sstevel@tonic-gate } 1074ab25eeb5Syz 1075ab25eeb5Syz if ((fin->fin_flx & FI_SHORT) != 0) 1076ab25eeb5Syz return; 10777c478bd9Sstevel@tonic-gate 10787c478bd9Sstevel@tonic-gate /* 10797c478bd9Sstevel@tonic-gate * Use of the TCP data offset *must* result in a value that is at 10807c478bd9Sstevel@tonic-gate * least the same size as the TCP header. 10817c478bd9Sstevel@tonic-gate */ 1082ab25eeb5Syz tlen = TCP_OFF(tcp) << 2; 1083ab25eeb5Syz if (tlen < sizeof(tcphdr_t)) { 10847c478bd9Sstevel@tonic-gate fin->fin_flx |= FI_BAD; 1085ab25eeb5Syz return; 1086ab25eeb5Syz } 1087ab25eeb5Syz 1088ab25eeb5Syz flags = tcp->th_flags; 1089ab25eeb5Syz fin->fin_tcpf = tcp->th_flags; 10907c478bd9Sstevel@tonic-gate 1091ab25eeb5Syz /* 1092ab25eeb5Syz * If the urgent flag is set, then the urgent pointer must 1093ab25eeb5Syz * also be set and vice versa. Good TCP packets do not have 1094ab25eeb5Syz * just one of these set. 1095ab25eeb5Syz */ 1096ab25eeb5Syz if ((flags & TH_URG) != 0 && (tcp->th_urp == 0)) { 1097ab25eeb5Syz fin->fin_flx |= FI_BAD; 1098ab25eeb5Syz } else if ((flags & TH_URG) == 0 && (tcp->th_urp != 0)) { 1099ab25eeb5Syz /* Ignore this case, it shows up in "real" traffic with */ 1100ab25eeb5Syz /* bogus values in the urgent pointer field. */ 1101ab25eeb5Syz flags = flags; /* LINT */ 1102ab25eeb5Syz } else if (((flags & (TH_SYN|TH_FIN)) != 0) && 1103ab25eeb5Syz ((flags & (TH_RST|TH_ACK)) == TH_RST)) { 1104ab25eeb5Syz /* TH_FIN|TH_RST|TH_ACK seems to appear "naturally" */ 1105ab25eeb5Syz fin->fin_flx |= FI_BAD; 1106ab25eeb5Syz } else if (!(flags & TH_ACK)) { 11077c478bd9Sstevel@tonic-gate /* 1108ab25eeb5Syz * If the ack bit isn't set, then either the SYN or 1109ab25eeb5Syz * RST bit must be set. If the SYN bit is set, then 1110ab25eeb5Syz * we expect the ACK field to be 0. If the ACK is 1111ab25eeb5Syz * not set and if URG, PSH or FIN are set, consdier 1112ab25eeb5Syz * that to indicate a bad TCP packet. 11137c478bd9Sstevel@tonic-gate */ 1114ab25eeb5Syz if ((flags == TH_SYN) && (tcp->th_ack != 0)) { 11157c478bd9Sstevel@tonic-gate /* 1116ab25eeb5Syz * Cisco PIX sets the ACK field to a random value. 1117ab25eeb5Syz * In light of this, do not set FI_BAD until a patch 1118ab25eeb5Syz * is available from Cisco to ensure that 1119ab25eeb5Syz * interoperability between existing systems is 1120ab25eeb5Syz * achieved. 11217c478bd9Sstevel@tonic-gate */ 1122ab25eeb5Syz /*fin->fin_flx |= FI_BAD*/; 1123ab25eeb5Syz flags = flags; /* LINT */ 1124ab25eeb5Syz } else if (!(flags & (TH_RST|TH_SYN))) { 1125ab25eeb5Syz fin->fin_flx |= FI_BAD; 1126ab25eeb5Syz } else if ((flags & (TH_URG|TH_PUSH|TH_FIN)) != 0) { 1127ab25eeb5Syz fin->fin_flx |= FI_BAD; 11287c478bd9Sstevel@tonic-gate } 11297c478bd9Sstevel@tonic-gate } 11307c478bd9Sstevel@tonic-gate 11317c478bd9Sstevel@tonic-gate /* 11327c478bd9Sstevel@tonic-gate * At this point, it's not exactly clear what is to be gained by 11337c478bd9Sstevel@tonic-gate * marking up which TCP options are and are not present. The one we 11347c478bd9Sstevel@tonic-gate * are most interested in is the TCP window scale. This is only in 11357c478bd9Sstevel@tonic-gate * a SYN packet [RFC1323] so we don't need this here...? 11367c478bd9Sstevel@tonic-gate * Now if we were to analyse the header for passive fingerprinting, 11377c478bd9Sstevel@tonic-gate * then that might add some weight to adding this... 11387c478bd9Sstevel@tonic-gate */ 1139ab25eeb5Syz if (tlen == sizeof(tcphdr_t)) 1140ab25eeb5Syz return; 1141ab25eeb5Syz 1142ab25eeb5Syz if (frpr_pullup(fin, tlen) == -1) 11437c478bd9Sstevel@tonic-gate return; 1144ab25eeb5Syz 1145ab25eeb5Syz #if 0 1146ab25eeb5Syz ip = fin->fin_ip; 1147ab25eeb5Syz s = (u_char *)(tcp + 1); 11487c478bd9Sstevel@tonic-gate off = IP_HL(ip) << 2; 11497c478bd9Sstevel@tonic-gate # ifdef _KERNEL 11507c478bd9Sstevel@tonic-gate if (fin->fin_mp != NULL) { 11517c478bd9Sstevel@tonic-gate mb_t *m = *fin->fin_mp; 11527c478bd9Sstevel@tonic-gate 1153ab25eeb5Syz if (off + tlen > M_LEN(m)) 11547c478bd9Sstevel@tonic-gate return; 11557c478bd9Sstevel@tonic-gate } 11567c478bd9Sstevel@tonic-gate # endif 1157ab25eeb5Syz for (tlen -= (int)sizeof(*tcp); tlen > 0; ) { 11587c478bd9Sstevel@tonic-gate opt = *s; 11597c478bd9Sstevel@tonic-gate if (opt == '\0') 11607c478bd9Sstevel@tonic-gate break; 11617c478bd9Sstevel@tonic-gate else if (opt == TCPOPT_NOP) 11627c478bd9Sstevel@tonic-gate ol = 1; 11637c478bd9Sstevel@tonic-gate else { 1164ab25eeb5Syz if (tlen < 2) 11657c478bd9Sstevel@tonic-gate break; 11667c478bd9Sstevel@tonic-gate ol = (int)*(s + 1); 1167ab25eeb5Syz if (ol < 2 || ol > tlen) 11687c478bd9Sstevel@tonic-gate break; 11697c478bd9Sstevel@tonic-gate } 11707c478bd9Sstevel@tonic-gate 11717c478bd9Sstevel@tonic-gate for (i = 9, mv = 4; mv >= 0; ) { 11727c478bd9Sstevel@tonic-gate op = ipopts + i; 11737c478bd9Sstevel@tonic-gate if (opt == (u_char)op->ol_val) { 11747c478bd9Sstevel@tonic-gate optmsk |= op->ol_bit; 11757c478bd9Sstevel@tonic-gate break; 11767c478bd9Sstevel@tonic-gate } 11777c478bd9Sstevel@tonic-gate } 1178ab25eeb5Syz tlen -= ol; 11797c478bd9Sstevel@tonic-gate s += ol; 11807c478bd9Sstevel@tonic-gate } 11817c478bd9Sstevel@tonic-gate #endif /* 0 */ 11827c478bd9Sstevel@tonic-gate } 11837c478bd9Sstevel@tonic-gate 11847c478bd9Sstevel@tonic-gate 11857c478bd9Sstevel@tonic-gate 11867c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 11877c478bd9Sstevel@tonic-gate /* Function: frpr_udpcommon */ 11887c478bd9Sstevel@tonic-gate /* Returns: void */ 11897c478bd9Sstevel@tonic-gate /* Parameters: fin(I) - pointer to packet information */ 11907c478bd9Sstevel@tonic-gate /* */ 11917c478bd9Sstevel@tonic-gate /* Extract the UDP source and destination ports, if present. If compiled */ 11927c478bd9Sstevel@tonic-gate /* with IPFILTER_CKSUM, check to see if the UDP checksum is valid. */ 11937c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 11947c478bd9Sstevel@tonic-gate static INLINE void frpr_udpcommon(fin) 11957c478bd9Sstevel@tonic-gate fr_info_t *fin; 11967c478bd9Sstevel@tonic-gate { 11977c478bd9Sstevel@tonic-gate udphdr_t *udp; 11987c478bd9Sstevel@tonic-gate 119962685e53Sml fin->fin_flx |= FI_TCPUDP; 12007c478bd9Sstevel@tonic-gate 12017c478bd9Sstevel@tonic-gate if (!fin->fin_off && (fin->fin_dlen > 3)) { 1202ab25eeb5Syz if (frpr_pullup(fin, sizeof(*udp)) == -1) { 1203ab25eeb5Syz fin->fin_flx |= FI_SHORT; 1204ab25eeb5Syz return; 1205ab25eeb5Syz } 1206ab25eeb5Syz 120762685e53Sml udp = fin->fin_dp; 120862685e53Sml 12097c478bd9Sstevel@tonic-gate fin->fin_sport = ntohs(udp->uh_sport); 12107c478bd9Sstevel@tonic-gate fin->fin_dport = ntohs(udp->uh_dport); 12117c478bd9Sstevel@tonic-gate } 12127c478bd9Sstevel@tonic-gate } 12137c478bd9Sstevel@tonic-gate 12147c478bd9Sstevel@tonic-gate 12157c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 12167c478bd9Sstevel@tonic-gate /* Function: frpr_tcp */ 12177c478bd9Sstevel@tonic-gate /* Returns: void */ 12187c478bd9Sstevel@tonic-gate /* Parameters: fin(I) - pointer to packet information */ 12197c478bd9Sstevel@tonic-gate /* */ 12207c478bd9Sstevel@tonic-gate /* IPv4 Only */ 12217c478bd9Sstevel@tonic-gate /* Analyse the packet for IPv4/TCP properties. */ 12227c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 12237c478bd9Sstevel@tonic-gate static INLINE void frpr_tcp(fin) 12247c478bd9Sstevel@tonic-gate fr_info_t *fin; 12257c478bd9Sstevel@tonic-gate { 12267c478bd9Sstevel@tonic-gate 12277c478bd9Sstevel@tonic-gate fr_checkv4sum(fin); 12287c478bd9Sstevel@tonic-gate 1229ab25eeb5Syz frpr_short(fin, sizeof(tcphdr_t)); 12307c478bd9Sstevel@tonic-gate 12317c478bd9Sstevel@tonic-gate frpr_tcpcommon(fin); 12327c478bd9Sstevel@tonic-gate } 12337c478bd9Sstevel@tonic-gate 12347c478bd9Sstevel@tonic-gate 12357c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 12367c478bd9Sstevel@tonic-gate /* Function: frpr_udp */ 12377c478bd9Sstevel@tonic-gate /* Returns: void */ 12387c478bd9Sstevel@tonic-gate /* Parameters: fin(I) - pointer to packet information */ 12397c478bd9Sstevel@tonic-gate /* */ 12407c478bd9Sstevel@tonic-gate /* IPv4 Only */ 12417c478bd9Sstevel@tonic-gate /* Analyse the packet for IPv4/UDP properties. */ 12427c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 12437c478bd9Sstevel@tonic-gate static INLINE void frpr_udp(fin) 12447c478bd9Sstevel@tonic-gate fr_info_t *fin; 12457c478bd9Sstevel@tonic-gate { 12467c478bd9Sstevel@tonic-gate 12477c478bd9Sstevel@tonic-gate fr_checkv4sum(fin); 12487c478bd9Sstevel@tonic-gate 1249ab25eeb5Syz frpr_short(fin, sizeof(udphdr_t)); 12507c478bd9Sstevel@tonic-gate 12517c478bd9Sstevel@tonic-gate frpr_udpcommon(fin); 12527c478bd9Sstevel@tonic-gate } 12537c478bd9Sstevel@tonic-gate 12547c478bd9Sstevel@tonic-gate 12557663b816Sml /* ------------------------------------------------------------------------ */ 12567663b816Sml /* Function: frpr_esp */ 12577663b816Sml /* Returns: void */ 12587663b816Sml /* Parameters: fin(I) - pointer to packet information */ 12597663b816Sml /* */ 12607663b816Sml /* Analyse the packet for ESP properties. */ 12617663b816Sml /* The minimum length is taken to be the SPI (32bits) plus a tail (32bits) */ 12627663b816Sml /* even though the newer ESP packets must also have a sequence number that */ 12637663b816Sml /* is 32bits as well, it is not possible(?) to determine the version from a */ 12647663b816Sml /* simple packet header. */ 12657663b816Sml /* ------------------------------------------------------------------------ */ 12667663b816Sml static INLINE void frpr_esp(fin) 12677663b816Sml fr_info_t *fin; 12687663b816Sml { 1269ab25eeb5Syz if ((fin->fin_off == 0) && (frpr_pullup(fin, 8) == -1)) 12707663b816Sml return; 12717663b816Sml 1272ab25eeb5Syz frpr_short(fin, 8); 1273ab25eeb5Syz } 1274ab25eeb5Syz 1275ab25eeb5Syz 1276ab25eeb5Syz /* ------------------------------------------------------------------------ */ 1277ab25eeb5Syz /* Function: frpr_ah */ 1278ab25eeb5Syz /* Returns: void */ 1279ab25eeb5Syz /* Parameters: fin(I) - pointer to packet information */ 1280ab25eeb5Syz /* */ 1281ab25eeb5Syz /* Analyse the packet for AH properties. */ 1282ab25eeb5Syz /* The minimum length is taken to be the combination of all fields in the */ 1283ab25eeb5Syz /* header being present and no authentication data (null algorithm used.) */ 1284ab25eeb5Syz /* ------------------------------------------------------------------------ */ 1285ab25eeb5Syz static INLINE void frpr_ah(fin) 1286ab25eeb5Syz fr_info_t *fin; 1287ab25eeb5Syz { 1288ab25eeb5Syz authhdr_t *ah; 1289ab25eeb5Syz int len; 1290ab25eeb5Syz 1291ab25eeb5Syz if ((fin->fin_off == 0) && (frpr_pullup(fin, sizeof(*ah)) == -1)) 1292ab25eeb5Syz return; 1293ab25eeb5Syz 1294ab25eeb5Syz ah = (authhdr_t *)fin->fin_dp; 1295ab25eeb5Syz 1296ab25eeb5Syz len = (ah->ah_plen + 2) << 2; 1297ab25eeb5Syz frpr_short(fin, len); 12987663b816Sml } 12997663b816Sml 13007663b816Sml 13017663b816Sml /* ------------------------------------------------------------------------ */ 13027663b816Sml /* Function: frpr_gre */ 13037663b816Sml /* Returns: void */ 13047663b816Sml /* Parameters: fin(I) - pointer to packet information */ 13057663b816Sml /* */ 13067663b816Sml /* Analyse the packet for GRE properties. */ 13077663b816Sml /* ------------------------------------------------------------------------ */ 13087663b816Sml static INLINE void frpr_gre(fin) 13097663b816Sml fr_info_t *fin; 13107663b816Sml { 1311ab25eeb5Syz grehdr_t *gre; 1312ab25eeb5Syz 1313ab25eeb5Syz if ((fin->fin_off == 0) && (frpr_pullup(fin, sizeof(grehdr_t)) == -1)) 13147663b816Sml return; 13157663b816Sml 1316ab25eeb5Syz frpr_short(fin, sizeof(grehdr_t)); 1317ab25eeb5Syz 1318ab25eeb5Syz if (fin->fin_off == 0) { 1319ab25eeb5Syz gre = fin->fin_dp; 1320ab25eeb5Syz if (GRE_REV(gre->gr_flags) == 1) 1321ab25eeb5Syz fin->fin_data[0] = gre->gr_call; 1322ab25eeb5Syz } 13237663b816Sml } 13247663b816Sml 13257663b816Sml 13267c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 13277c478bd9Sstevel@tonic-gate /* Function: frpr_ipv4hdr */ 13287c478bd9Sstevel@tonic-gate /* Returns: void */ 13297c478bd9Sstevel@tonic-gate /* Parameters: fin(I) - pointer to packet information */ 13307c478bd9Sstevel@tonic-gate /* */ 13317c478bd9Sstevel@tonic-gate /* IPv4 Only */ 13327c478bd9Sstevel@tonic-gate /* Analyze the IPv4 header and set fields in the fr_info_t structure. */ 13337c478bd9Sstevel@tonic-gate /* Check all options present and flag their presence if any exist. */ 13347c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 13357c478bd9Sstevel@tonic-gate static INLINE void frpr_ipv4hdr(fin) 13367c478bd9Sstevel@tonic-gate fr_info_t *fin; 13377c478bd9Sstevel@tonic-gate { 13387c478bd9Sstevel@tonic-gate u_short optmsk = 0, secmsk = 0, auth = 0; 13397c478bd9Sstevel@tonic-gate int hlen, ol, mv, p, i; 1340ab25eeb5Syz const struct optlist *op; 13417c478bd9Sstevel@tonic-gate u_char *s, opt; 13427c478bd9Sstevel@tonic-gate u_short off; 13437c478bd9Sstevel@tonic-gate fr_ip_t *fi; 13447c478bd9Sstevel@tonic-gate ip_t *ip; 13457c478bd9Sstevel@tonic-gate 13467c478bd9Sstevel@tonic-gate fi = &fin->fin_fi; 13477c478bd9Sstevel@tonic-gate hlen = fin->fin_hlen; 13487c478bd9Sstevel@tonic-gate 13497c478bd9Sstevel@tonic-gate ip = fin->fin_ip; 13507c478bd9Sstevel@tonic-gate p = ip->ip_p; 13517c478bd9Sstevel@tonic-gate fi->fi_p = p; 13527c478bd9Sstevel@tonic-gate fi->fi_tos = ip->ip_tos; 13537c478bd9Sstevel@tonic-gate fin->fin_id = ip->ip_id; 13547c478bd9Sstevel@tonic-gate off = ip->ip_off; 13557c478bd9Sstevel@tonic-gate 13567c478bd9Sstevel@tonic-gate /* Get both TTL and protocol */ 13577c478bd9Sstevel@tonic-gate fi->fi_p = ip->ip_p; 13587c478bd9Sstevel@tonic-gate fi->fi_ttl = ip->ip_ttl; 13597c478bd9Sstevel@tonic-gate #if 0 13607c478bd9Sstevel@tonic-gate (*(((u_short *)fi) + 1)) = (*(((u_short *)ip) + 4)); 13617c478bd9Sstevel@tonic-gate #endif 13627c478bd9Sstevel@tonic-gate 13637c478bd9Sstevel@tonic-gate /* Zero out bits not used in IPv6 address */ 13647c478bd9Sstevel@tonic-gate fi->fi_src.i6[1] = 0; 13657c478bd9Sstevel@tonic-gate fi->fi_src.i6[2] = 0; 13667c478bd9Sstevel@tonic-gate fi->fi_src.i6[3] = 0; 13677c478bd9Sstevel@tonic-gate fi->fi_dst.i6[1] = 0; 13687c478bd9Sstevel@tonic-gate fi->fi_dst.i6[2] = 0; 13697c478bd9Sstevel@tonic-gate fi->fi_dst.i6[3] = 0; 13707c478bd9Sstevel@tonic-gate 13717c478bd9Sstevel@tonic-gate fi->fi_saddr = ip->ip_src.s_addr; 13727c478bd9Sstevel@tonic-gate fi->fi_daddr = ip->ip_dst.s_addr; 13737c478bd9Sstevel@tonic-gate 13747c478bd9Sstevel@tonic-gate /* 13757c478bd9Sstevel@tonic-gate * set packet attribute flags based on the offset and 13767c478bd9Sstevel@tonic-gate * calculate the byte offset that it represents. 13777c478bd9Sstevel@tonic-gate */ 13787c478bd9Sstevel@tonic-gate off &= IP_MF|IP_OFFMASK; 13797c478bd9Sstevel@tonic-gate if (off != 0) { 13807c478bd9Sstevel@tonic-gate fi->fi_flx |= FI_FRAG; 13817c478bd9Sstevel@tonic-gate off &= IP_OFFMASK; 13827c478bd9Sstevel@tonic-gate if (off != 0) { 1383ab25eeb5Syz fin->fin_flx |= FI_FRAGBODY; 13847c478bd9Sstevel@tonic-gate off <<= 3; 1385ab25eeb5Syz if ((off + fin->fin_dlen > 65535) || 1386ab25eeb5Syz (fin->fin_dlen == 0) || 1387ab25eeb5Syz ((ip->ip_off & IP_MF) && (fin->fin_dlen & 7))) { 1388ab25eeb5Syz /* 1389ab25eeb5Syz * The length of the packet, starting at its 1390ab25eeb5Syz * offset cannot exceed 65535 (0xffff) as the 1391ab25eeb5Syz * length of an IP packet is only 16 bits. 1392ab25eeb5Syz * 1393ab25eeb5Syz * Any fragment that isn't the last fragment 1394ab25eeb5Syz * must have a length greater than 0 and it 1395ab25eeb5Syz * must be an even multiple of 8. 1396ab25eeb5Syz */ 13977c478bd9Sstevel@tonic-gate fi->fi_flx |= FI_BAD; 1398ab25eeb5Syz } 13997c478bd9Sstevel@tonic-gate } 14007c478bd9Sstevel@tonic-gate } 14017c478bd9Sstevel@tonic-gate fin->fin_off = off; 14027c478bd9Sstevel@tonic-gate 14037c478bd9Sstevel@tonic-gate /* 14047c478bd9Sstevel@tonic-gate * Call per-protocol setup and checking 14057c478bd9Sstevel@tonic-gate */ 14067c478bd9Sstevel@tonic-gate switch (p) 14077c478bd9Sstevel@tonic-gate { 14087c478bd9Sstevel@tonic-gate case IPPROTO_UDP : 14097c478bd9Sstevel@tonic-gate frpr_udp(fin); 14107c478bd9Sstevel@tonic-gate break; 14117c478bd9Sstevel@tonic-gate case IPPROTO_TCP : 14127c478bd9Sstevel@tonic-gate frpr_tcp(fin); 14137c478bd9Sstevel@tonic-gate break; 14147c478bd9Sstevel@tonic-gate case IPPROTO_ICMP : 14157c478bd9Sstevel@tonic-gate frpr_icmp(fin); 14167c478bd9Sstevel@tonic-gate break; 1417ab25eeb5Syz case IPPROTO_AH : 1418ab25eeb5Syz frpr_ah(fin); 1419ab25eeb5Syz break; 1420ab25eeb5Syz case IPPROTO_ESP : 1421ab25eeb5Syz frpr_esp(fin); 1422ab25eeb5Syz break; 1423ab25eeb5Syz case IPPROTO_GRE : 1424ab25eeb5Syz frpr_gre(fin); 1425ab25eeb5Syz break; 14267c478bd9Sstevel@tonic-gate } 14277c478bd9Sstevel@tonic-gate 14287c478bd9Sstevel@tonic-gate ip = fin->fin_ip; 14297c478bd9Sstevel@tonic-gate if (ip == NULL) 14307c478bd9Sstevel@tonic-gate return; 14317c478bd9Sstevel@tonic-gate 14327c478bd9Sstevel@tonic-gate /* 14337c478bd9Sstevel@tonic-gate * If it is a standard IP header (no options), set the flag fields 14347c478bd9Sstevel@tonic-gate * which relate to options to 0. 14357c478bd9Sstevel@tonic-gate */ 14367c478bd9Sstevel@tonic-gate if (hlen == sizeof(*ip)) { 14377c478bd9Sstevel@tonic-gate fi->fi_optmsk = 0; 14387c478bd9Sstevel@tonic-gate fi->fi_secmsk = 0; 14397c478bd9Sstevel@tonic-gate fi->fi_auth = 0; 14407c478bd9Sstevel@tonic-gate return; 14417c478bd9Sstevel@tonic-gate } 14427c478bd9Sstevel@tonic-gate 14437c478bd9Sstevel@tonic-gate /* 14447c478bd9Sstevel@tonic-gate * So the IP header has some IP options attached. Walk the entire 14457c478bd9Sstevel@tonic-gate * list of options present with this packet and set flags to indicate 14467c478bd9Sstevel@tonic-gate * which ones are here and which ones are not. For the somewhat out 14477c478bd9Sstevel@tonic-gate * of date and obscure security classification options, set a flag to 14487c478bd9Sstevel@tonic-gate * represent which classification is present. 14497c478bd9Sstevel@tonic-gate */ 14507c478bd9Sstevel@tonic-gate fi->fi_flx |= FI_OPTIONS; 14517c478bd9Sstevel@tonic-gate 14527c478bd9Sstevel@tonic-gate for (s = (u_char *)(ip + 1), hlen -= (int)sizeof(*ip); hlen > 0; ) { 14537c478bd9Sstevel@tonic-gate opt = *s; 14547c478bd9Sstevel@tonic-gate if (opt == '\0') 14557c478bd9Sstevel@tonic-gate break; 14567c478bd9Sstevel@tonic-gate else if (opt == IPOPT_NOP) 14577c478bd9Sstevel@tonic-gate ol = 1; 14587c478bd9Sstevel@tonic-gate else { 14597c478bd9Sstevel@tonic-gate if (hlen < 2) 14607c478bd9Sstevel@tonic-gate break; 14617c478bd9Sstevel@tonic-gate ol = (int)*(s + 1); 14627c478bd9Sstevel@tonic-gate if (ol < 2 || ol > hlen) 14637c478bd9Sstevel@tonic-gate break; 14647c478bd9Sstevel@tonic-gate } 14657c478bd9Sstevel@tonic-gate for (i = 9, mv = 4; mv >= 0; ) { 14667c478bd9Sstevel@tonic-gate op = ipopts + i; 14677c478bd9Sstevel@tonic-gate if ((opt == (u_char)op->ol_val) && (ol > 4)) { 14687c478bd9Sstevel@tonic-gate optmsk |= op->ol_bit; 14697c478bd9Sstevel@tonic-gate if (opt == IPOPT_SECURITY) { 1470ab25eeb5Syz const struct optlist *sp; 14717c478bd9Sstevel@tonic-gate u_char sec; 14727c478bd9Sstevel@tonic-gate int j, m; 14737c478bd9Sstevel@tonic-gate 14747c478bd9Sstevel@tonic-gate sec = *(s + 2); /* classification */ 14757c478bd9Sstevel@tonic-gate for (j = 3, m = 2; m >= 0; ) { 14767c478bd9Sstevel@tonic-gate sp = secopt + j; 14777c478bd9Sstevel@tonic-gate if (sec == sp->ol_val) { 14787c478bd9Sstevel@tonic-gate secmsk |= sp->ol_bit; 14797c478bd9Sstevel@tonic-gate auth = *(s + 3); 14807c478bd9Sstevel@tonic-gate auth *= 256; 14817c478bd9Sstevel@tonic-gate auth += *(s + 4); 14827c478bd9Sstevel@tonic-gate break; 14837c478bd9Sstevel@tonic-gate } 14847c478bd9Sstevel@tonic-gate if (sec < sp->ol_val) 14857c478bd9Sstevel@tonic-gate j -= m; 14867c478bd9Sstevel@tonic-gate else 14877c478bd9Sstevel@tonic-gate j += m; 14887c478bd9Sstevel@tonic-gate m--; 14897c478bd9Sstevel@tonic-gate } 14907c478bd9Sstevel@tonic-gate } 14917c478bd9Sstevel@tonic-gate break; 14927c478bd9Sstevel@tonic-gate } 14937c478bd9Sstevel@tonic-gate if (opt < op->ol_val) 14947c478bd9Sstevel@tonic-gate i -= mv; 14957c478bd9Sstevel@tonic-gate else 14967c478bd9Sstevel@tonic-gate i += mv; 14977c478bd9Sstevel@tonic-gate mv--; 14987c478bd9Sstevel@tonic-gate } 14997c478bd9Sstevel@tonic-gate hlen -= ol; 15007c478bd9Sstevel@tonic-gate s += ol; 15017c478bd9Sstevel@tonic-gate } 15027c478bd9Sstevel@tonic-gate 15037c478bd9Sstevel@tonic-gate /* 1504ab25eeb5Syz * 15057c478bd9Sstevel@tonic-gate */ 15067c478bd9Sstevel@tonic-gate if (auth && !(auth & 0x0100)) 15077c478bd9Sstevel@tonic-gate auth &= 0xff00; 15087c478bd9Sstevel@tonic-gate fi->fi_optmsk = optmsk; 15097c478bd9Sstevel@tonic-gate fi->fi_secmsk = secmsk; 15107c478bd9Sstevel@tonic-gate fi->fi_auth = auth; 15117c478bd9Sstevel@tonic-gate } 15127c478bd9Sstevel@tonic-gate 15137c478bd9Sstevel@tonic-gate 15147c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 15157c478bd9Sstevel@tonic-gate /* Function: fr_makefrip */ 151608254dd3Syz /* Returns: int - 1 == hdr checking error, 0 == OK */ 15177c478bd9Sstevel@tonic-gate /* Parameters: hlen(I) - length of IP packet header */ 15187c478bd9Sstevel@tonic-gate /* ip(I) - pointer to the IP header */ 1519ab25eeb5Syz /* fin(IO) - pointer to packet information */ 15207c478bd9Sstevel@tonic-gate /* */ 15217c478bd9Sstevel@tonic-gate /* Compact the IP header into a structure which contains just the info. */ 15227c478bd9Sstevel@tonic-gate /* which is useful for comparing IP headers with and store this information */ 15237c478bd9Sstevel@tonic-gate /* in the fr_info_t structure pointer to by fin. At present, it is assumed */ 15247c478bd9Sstevel@tonic-gate /* this function will be called with either an IPv4 or IPv6 packet. */ 15257c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 15267c478bd9Sstevel@tonic-gate int fr_makefrip(hlen, ip, fin) 15277c478bd9Sstevel@tonic-gate int hlen; 15287c478bd9Sstevel@tonic-gate ip_t *ip; 15297c478bd9Sstevel@tonic-gate fr_info_t *fin; 15307c478bd9Sstevel@tonic-gate { 15317c478bd9Sstevel@tonic-gate int v; 15327c478bd9Sstevel@tonic-gate 15337c478bd9Sstevel@tonic-gate fin->fin_nat = NULL; 15347c478bd9Sstevel@tonic-gate fin->fin_state = NULL; 15357c478bd9Sstevel@tonic-gate fin->fin_depth = 0; 15367c478bd9Sstevel@tonic-gate fin->fin_hlen = (u_short)hlen; 15377c478bd9Sstevel@tonic-gate fin->fin_ip = ip; 15387c478bd9Sstevel@tonic-gate fin->fin_rule = 0xffffffff; 15397c478bd9Sstevel@tonic-gate fin->fin_group[0] = -1; 15407c478bd9Sstevel@tonic-gate fin->fin_group[1] = '\0'; 15417c478bd9Sstevel@tonic-gate fin->fin_dlen = fin->fin_plen - hlen; 15427c478bd9Sstevel@tonic-gate fin->fin_dp = (char *)ip + hlen; 15437c478bd9Sstevel@tonic-gate 15447c478bd9Sstevel@tonic-gate v = fin->fin_v; 15457c478bd9Sstevel@tonic-gate if (v == 4) 15467c478bd9Sstevel@tonic-gate frpr_ipv4hdr(fin); 15477c478bd9Sstevel@tonic-gate #ifdef USE_INET6 1548ab25eeb5Syz else if (v == 6) { 15497663b816Sml if (frpr_ipv6hdr(fin) == -1) 15507663b816Sml return -1; 1551ab25eeb5Syz } 15527c478bd9Sstevel@tonic-gate #endif 15537c478bd9Sstevel@tonic-gate if (fin->fin_ip == NULL) 15547c478bd9Sstevel@tonic-gate return -1; 15557c478bd9Sstevel@tonic-gate return 0; 15567c478bd9Sstevel@tonic-gate } 15577c478bd9Sstevel@tonic-gate 15587c478bd9Sstevel@tonic-gate 15597c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 15607c478bd9Sstevel@tonic-gate /* Function: fr_portcheck */ 15617c478bd9Sstevel@tonic-gate /* Returns: int - 1 == port matched, 0 == port match failed */ 15627c478bd9Sstevel@tonic-gate /* Parameters: frp(I) - pointer to port check `expression' */ 15637c478bd9Sstevel@tonic-gate /* pop(I) - pointer to port number to evaluate */ 15647c478bd9Sstevel@tonic-gate /* */ 15657c478bd9Sstevel@tonic-gate /* Perform a comparison of a port number against some other(s), using a */ 15667c478bd9Sstevel@tonic-gate /* structure with compare information stored in it. */ 15677c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 15687c478bd9Sstevel@tonic-gate static INLINE int fr_portcheck(frp, pop) 15697c478bd9Sstevel@tonic-gate frpcmp_t *frp; 15707c478bd9Sstevel@tonic-gate u_short *pop; 15717c478bd9Sstevel@tonic-gate { 15727c478bd9Sstevel@tonic-gate u_short tup, po; 15737c478bd9Sstevel@tonic-gate int err = 1; 15747c478bd9Sstevel@tonic-gate 15757c478bd9Sstevel@tonic-gate tup = *pop; 15767c478bd9Sstevel@tonic-gate po = frp->frp_port; 15777c478bd9Sstevel@tonic-gate 15787c478bd9Sstevel@tonic-gate /* 15797c478bd9Sstevel@tonic-gate * Do opposite test to that required and continue if that succeeds. 15807c478bd9Sstevel@tonic-gate */ 15817c478bd9Sstevel@tonic-gate switch (frp->frp_cmp) 15827c478bd9Sstevel@tonic-gate { 15837c478bd9Sstevel@tonic-gate case FR_EQUAL : 15847c478bd9Sstevel@tonic-gate if (tup != po) /* EQUAL */ 15857c478bd9Sstevel@tonic-gate err = 0; 15867c478bd9Sstevel@tonic-gate break; 15877c478bd9Sstevel@tonic-gate case FR_NEQUAL : 15887c478bd9Sstevel@tonic-gate if (tup == po) /* NOTEQUAL */ 15897c478bd9Sstevel@tonic-gate err = 0; 15907c478bd9Sstevel@tonic-gate break; 15917c478bd9Sstevel@tonic-gate case FR_LESST : 15927c478bd9Sstevel@tonic-gate if (tup >= po) /* LESSTHAN */ 15937c478bd9Sstevel@tonic-gate err = 0; 15947c478bd9Sstevel@tonic-gate break; 15957c478bd9Sstevel@tonic-gate case FR_GREATERT : 15967c478bd9Sstevel@tonic-gate if (tup <= po) /* GREATERTHAN */ 15977c478bd9Sstevel@tonic-gate err = 0; 15987c478bd9Sstevel@tonic-gate break; 15997c478bd9Sstevel@tonic-gate case FR_LESSTE : 16007c478bd9Sstevel@tonic-gate if (tup > po) /* LT or EQ */ 16017c478bd9Sstevel@tonic-gate err = 0; 16027c478bd9Sstevel@tonic-gate break; 16037c478bd9Sstevel@tonic-gate case FR_GREATERTE : 16047c478bd9Sstevel@tonic-gate if (tup < po) /* GT or EQ */ 16057c478bd9Sstevel@tonic-gate err = 0; 16067c478bd9Sstevel@tonic-gate break; 16077c478bd9Sstevel@tonic-gate case FR_OUTRANGE : 16087c478bd9Sstevel@tonic-gate if (tup >= po && tup <= frp->frp_top) /* Out of range */ 16097c478bd9Sstevel@tonic-gate err = 0; 16107c478bd9Sstevel@tonic-gate break; 16117c478bd9Sstevel@tonic-gate case FR_INRANGE : 16127c478bd9Sstevel@tonic-gate if (tup <= po || tup >= frp->frp_top) /* In range */ 16137c478bd9Sstevel@tonic-gate err = 0; 16147c478bd9Sstevel@tonic-gate break; 16157c478bd9Sstevel@tonic-gate case FR_INCRANGE : 16167c478bd9Sstevel@tonic-gate if (tup < po || tup > frp->frp_top) /* Inclusive range */ 16177c478bd9Sstevel@tonic-gate err = 0; 16187c478bd9Sstevel@tonic-gate break; 16197c478bd9Sstevel@tonic-gate default : 16207c478bd9Sstevel@tonic-gate break; 16217c478bd9Sstevel@tonic-gate } 16227c478bd9Sstevel@tonic-gate return err; 16237c478bd9Sstevel@tonic-gate } 16247c478bd9Sstevel@tonic-gate 16257c478bd9Sstevel@tonic-gate 16267c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 16277c478bd9Sstevel@tonic-gate /* Function: fr_tcpudpchk */ 16287c478bd9Sstevel@tonic-gate /* Returns: int - 1 == protocol matched, 0 == check failed */ 16297c478bd9Sstevel@tonic-gate /* Parameters: fin(I) - pointer to packet information */ 16307c478bd9Sstevel@tonic-gate /* ft(I) - pointer to structure with comparison data */ 16317c478bd9Sstevel@tonic-gate /* */ 16327c478bd9Sstevel@tonic-gate /* Compares the current pcket (assuming it is TCP/UDP) information with a */ 16337c478bd9Sstevel@tonic-gate /* structure containing information that we want to match against. */ 16347c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 16357c478bd9Sstevel@tonic-gate int fr_tcpudpchk(fin, ft) 16367c478bd9Sstevel@tonic-gate fr_info_t *fin; 16377c478bd9Sstevel@tonic-gate frtuc_t *ft; 16387c478bd9Sstevel@tonic-gate { 16397c478bd9Sstevel@tonic-gate int err = 1; 16407c478bd9Sstevel@tonic-gate 16417c478bd9Sstevel@tonic-gate /* 16427c478bd9Sstevel@tonic-gate * Both ports should *always* be in the first fragment. 16437c478bd9Sstevel@tonic-gate * So far, I cannot find any cases where they can not be. 16447c478bd9Sstevel@tonic-gate * 16457c478bd9Sstevel@tonic-gate * compare destination ports 16467c478bd9Sstevel@tonic-gate */ 16477c478bd9Sstevel@tonic-gate if (ft->ftu_dcmp) 16487c478bd9Sstevel@tonic-gate err = fr_portcheck(&ft->ftu_dst, &fin->fin_dport); 16497c478bd9Sstevel@tonic-gate 16507c478bd9Sstevel@tonic-gate /* 16517c478bd9Sstevel@tonic-gate * compare source ports 16527c478bd9Sstevel@tonic-gate */ 16537c478bd9Sstevel@tonic-gate if (err && ft->ftu_scmp) 16547c478bd9Sstevel@tonic-gate err = fr_portcheck(&ft->ftu_src, &fin->fin_sport); 16557c478bd9Sstevel@tonic-gate 16567c478bd9Sstevel@tonic-gate /* 16577c478bd9Sstevel@tonic-gate * If we don't have all the TCP/UDP header, then how can we 16587c478bd9Sstevel@tonic-gate * expect to do any sort of match on it ? If we were looking for 16597c478bd9Sstevel@tonic-gate * TCP flags, then NO match. If not, then match (which should 16607c478bd9Sstevel@tonic-gate * satisfy the "short" class too). 16617c478bd9Sstevel@tonic-gate */ 16627c478bd9Sstevel@tonic-gate if (err && (fin->fin_p == IPPROTO_TCP)) { 16637c478bd9Sstevel@tonic-gate if (fin->fin_flx & FI_SHORT) 16647c478bd9Sstevel@tonic-gate return !(ft->ftu_tcpf | ft->ftu_tcpfm); 16657c478bd9Sstevel@tonic-gate /* 16667c478bd9Sstevel@tonic-gate * Match the flags ? If not, abort this match. 16677c478bd9Sstevel@tonic-gate */ 16687c478bd9Sstevel@tonic-gate if (ft->ftu_tcpfm && 16697c478bd9Sstevel@tonic-gate ft->ftu_tcpf != (fin->fin_tcpf & ft->ftu_tcpfm)) { 16707c478bd9Sstevel@tonic-gate FR_DEBUG(("f. %#x & %#x != %#x\n", fin->fin_tcpf, 16717c478bd9Sstevel@tonic-gate ft->ftu_tcpfm, ft->ftu_tcpf)); 16727c478bd9Sstevel@tonic-gate err = 0; 16737c478bd9Sstevel@tonic-gate } 16747c478bd9Sstevel@tonic-gate } 16757c478bd9Sstevel@tonic-gate return err; 16767c478bd9Sstevel@tonic-gate } 16777c478bd9Sstevel@tonic-gate 16787c478bd9Sstevel@tonic-gate 16797c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 16807c478bd9Sstevel@tonic-gate /* Function: fr_ipfcheck */ 16817c478bd9Sstevel@tonic-gate /* Returns: int - 0 == match, 1 == no match */ 16827c478bd9Sstevel@tonic-gate /* Parameters: fin(I) - pointer to packet information */ 16837c478bd9Sstevel@tonic-gate /* fr(I) - pointer to filter rule */ 16847c478bd9Sstevel@tonic-gate /* portcmp(I) - flag indicating whether to attempt matching on */ 16857c478bd9Sstevel@tonic-gate /* TCP/UDP port data. */ 16867c478bd9Sstevel@tonic-gate /* */ 16877c478bd9Sstevel@tonic-gate /* Check to see if a packet matches an IPFilter rule. Checks of addresses, */ 16887c478bd9Sstevel@tonic-gate /* port numbers, etc, for "standard" IPFilter rules are all orchestrated in */ 16897c478bd9Sstevel@tonic-gate /* this function. */ 16907c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 16917c478bd9Sstevel@tonic-gate static INLINE int fr_ipfcheck(fin, fr, portcmp) 16927c478bd9Sstevel@tonic-gate fr_info_t *fin; 16937c478bd9Sstevel@tonic-gate frentry_t *fr; 16947c478bd9Sstevel@tonic-gate int portcmp; 16957c478bd9Sstevel@tonic-gate { 16967c478bd9Sstevel@tonic-gate u_32_t *ld, *lm, *lip; 16977c478bd9Sstevel@tonic-gate fripf_t *fri; 16987c478bd9Sstevel@tonic-gate fr_ip_t *fi; 16997c478bd9Sstevel@tonic-gate int i; 17007c478bd9Sstevel@tonic-gate 17017c478bd9Sstevel@tonic-gate fi = &fin->fin_fi; 17027c478bd9Sstevel@tonic-gate fri = fr->fr_ipf; 17037c478bd9Sstevel@tonic-gate lip = (u_32_t *)fi; 17047c478bd9Sstevel@tonic-gate lm = (u_32_t *)&fri->fri_mip; 17057c478bd9Sstevel@tonic-gate ld = (u_32_t *)&fri->fri_ip; 17067c478bd9Sstevel@tonic-gate 17077c478bd9Sstevel@tonic-gate /* 17087c478bd9Sstevel@tonic-gate * first 32 bits to check coversion: 17097c478bd9Sstevel@tonic-gate * IP version, TOS, TTL, protocol 17107c478bd9Sstevel@tonic-gate */ 17117c478bd9Sstevel@tonic-gate i = ((*lip & *lm) != *ld); 17127c478bd9Sstevel@tonic-gate FR_DEBUG(("0. %#08x & %#08x != %#08x\n", 17137c478bd9Sstevel@tonic-gate *lip, *lm, *ld)); 17147c478bd9Sstevel@tonic-gate if (i) 17157c478bd9Sstevel@tonic-gate return 1; 17167c478bd9Sstevel@tonic-gate 17177c478bd9Sstevel@tonic-gate /* 17187c478bd9Sstevel@tonic-gate * Next 32 bits is a constructed bitmask indicating which IP options 17197c478bd9Sstevel@tonic-gate * are present (if any) in this packet. 17207c478bd9Sstevel@tonic-gate */ 17217c478bd9Sstevel@tonic-gate lip++, lm++, ld++; 17227c478bd9Sstevel@tonic-gate i |= ((*lip & *lm) != *ld); 17237c478bd9Sstevel@tonic-gate FR_DEBUG(("1. %#08x & %#08x != %#08x\n", 17247c478bd9Sstevel@tonic-gate *lip, *lm, *ld)); 17257c478bd9Sstevel@tonic-gate if (i) 17267c478bd9Sstevel@tonic-gate return 1; 17277c478bd9Sstevel@tonic-gate 17287c478bd9Sstevel@tonic-gate lip++, lm++, ld++; 17297c478bd9Sstevel@tonic-gate /* 17307c478bd9Sstevel@tonic-gate * Unrolled loops (4 each, for 32 bits) for address checks. 17317c478bd9Sstevel@tonic-gate */ 17327c478bd9Sstevel@tonic-gate /* 17337c478bd9Sstevel@tonic-gate * Check the source address. 17347c478bd9Sstevel@tonic-gate */ 17357c478bd9Sstevel@tonic-gate #ifdef IPFILTER_LOOKUP 17367c478bd9Sstevel@tonic-gate if (fr->fr_satype == FRI_LOOKUP) { 17377c478bd9Sstevel@tonic-gate i = (*fr->fr_srcfunc)(fr->fr_srcptr, fi->fi_v, lip); 17387c478bd9Sstevel@tonic-gate if (i == -1) 17397c478bd9Sstevel@tonic-gate return 1; 17407c478bd9Sstevel@tonic-gate lip += 3; 17417c478bd9Sstevel@tonic-gate lm += 3; 17427c478bd9Sstevel@tonic-gate ld += 3; 17437c478bd9Sstevel@tonic-gate } else { 17447c478bd9Sstevel@tonic-gate #endif 17457c478bd9Sstevel@tonic-gate i = ((*lip & *lm) != *ld); 17467c478bd9Sstevel@tonic-gate FR_DEBUG(("2a. %#08x & %#08x != %#08x\n", 17477c478bd9Sstevel@tonic-gate *lip, *lm, *ld)); 17487c478bd9Sstevel@tonic-gate if (fi->fi_v == 6) { 17497c478bd9Sstevel@tonic-gate lip++, lm++, ld++; 17507c478bd9Sstevel@tonic-gate i |= ((*lip & *lm) != *ld); 17517c478bd9Sstevel@tonic-gate FR_DEBUG(("2b. %#08x & %#08x != %#08x\n", 17527c478bd9Sstevel@tonic-gate *lip, *lm, *ld)); 17537c478bd9Sstevel@tonic-gate lip++, lm++, ld++; 17547c478bd9Sstevel@tonic-gate i |= ((*lip & *lm) != *ld); 17557c478bd9Sstevel@tonic-gate FR_DEBUG(("2c. %#08x & %#08x != %#08x\n", 17567c478bd9Sstevel@tonic-gate *lip, *lm, *ld)); 17577c478bd9Sstevel@tonic-gate lip++, lm++, ld++; 17587c478bd9Sstevel@tonic-gate i |= ((*lip & *lm) != *ld); 17597c478bd9Sstevel@tonic-gate FR_DEBUG(("2d. %#08x & %#08x != %#08x\n", 17607c478bd9Sstevel@tonic-gate *lip, *lm, *ld)); 17617c478bd9Sstevel@tonic-gate } else { 17627c478bd9Sstevel@tonic-gate lip += 3; 17637c478bd9Sstevel@tonic-gate lm += 3; 17647c478bd9Sstevel@tonic-gate ld += 3; 17657c478bd9Sstevel@tonic-gate } 17667c478bd9Sstevel@tonic-gate #ifdef IPFILTER_LOOKUP 17677c478bd9Sstevel@tonic-gate } 17687c478bd9Sstevel@tonic-gate #endif 17697c478bd9Sstevel@tonic-gate i ^= (fr->fr_flags & FR_NOTSRCIP) >> 6; 17707c478bd9Sstevel@tonic-gate if (i) 17717c478bd9Sstevel@tonic-gate return 1; 17727c478bd9Sstevel@tonic-gate 17737c478bd9Sstevel@tonic-gate /* 17747c478bd9Sstevel@tonic-gate * Check the destination address. 17757c478bd9Sstevel@tonic-gate */ 17767c478bd9Sstevel@tonic-gate lip++, lm++, ld++; 17777c478bd9Sstevel@tonic-gate #ifdef IPFILTER_LOOKUP 17787c478bd9Sstevel@tonic-gate if (fr->fr_datype == FRI_LOOKUP) { 17797c478bd9Sstevel@tonic-gate i = (*fr->fr_dstfunc)(fr->fr_dstptr, fi->fi_v, lip); 17807c478bd9Sstevel@tonic-gate if (i == -1) 17817c478bd9Sstevel@tonic-gate return 1; 17827c478bd9Sstevel@tonic-gate lip += 3; 17837c478bd9Sstevel@tonic-gate lm += 3; 17847c478bd9Sstevel@tonic-gate ld += 3; 17857c478bd9Sstevel@tonic-gate } else { 17867c478bd9Sstevel@tonic-gate #endif 17877c478bd9Sstevel@tonic-gate i = ((*lip & *lm) != *ld); 17887c478bd9Sstevel@tonic-gate FR_DEBUG(("3a. %#08x & %#08x != %#08x\n", 17897c478bd9Sstevel@tonic-gate *lip, *lm, *ld)); 17907c478bd9Sstevel@tonic-gate if (fi->fi_v == 6) { 17917c478bd9Sstevel@tonic-gate lip++, lm++, ld++; 17927c478bd9Sstevel@tonic-gate i |= ((*lip & *lm) != *ld); 17937c478bd9Sstevel@tonic-gate FR_DEBUG(("3b. %#08x & %#08x != %#08x\n", 17947c478bd9Sstevel@tonic-gate *lip, *lm, *ld)); 17957c478bd9Sstevel@tonic-gate lip++, lm++, ld++; 17967c478bd9Sstevel@tonic-gate i |= ((*lip & *lm) != *ld); 17977c478bd9Sstevel@tonic-gate FR_DEBUG(("3c. %#08x & %#08x != %#08x\n", 17987c478bd9Sstevel@tonic-gate *lip, *lm, *ld)); 17997c478bd9Sstevel@tonic-gate lip++, lm++, ld++; 18007c478bd9Sstevel@tonic-gate i |= ((*lip & *lm) != *ld); 18017c478bd9Sstevel@tonic-gate FR_DEBUG(("3d. %#08x & %#08x != %#08x\n", 18027c478bd9Sstevel@tonic-gate *lip, *lm, *ld)); 18037c478bd9Sstevel@tonic-gate } else { 18047c478bd9Sstevel@tonic-gate lip += 3; 18057c478bd9Sstevel@tonic-gate lm += 3; 18067c478bd9Sstevel@tonic-gate ld += 3; 18077c478bd9Sstevel@tonic-gate } 18087c478bd9Sstevel@tonic-gate #ifdef IPFILTER_LOOKUP 18097c478bd9Sstevel@tonic-gate } 18107c478bd9Sstevel@tonic-gate #endif 18117c478bd9Sstevel@tonic-gate i ^= (fr->fr_flags & FR_NOTDSTIP) >> 7; 18127c478bd9Sstevel@tonic-gate if (i) 18137c478bd9Sstevel@tonic-gate return 1; 18147c478bd9Sstevel@tonic-gate /* 18157c478bd9Sstevel@tonic-gate * IP addresses matched. The next 32bits contains: 18167c478bd9Sstevel@tonic-gate * mast of old IP header security & authentication bits. 18177c478bd9Sstevel@tonic-gate */ 18187c478bd9Sstevel@tonic-gate lip++, lm++, ld++; 18197c478bd9Sstevel@tonic-gate i |= ((*lip & *lm) != *ld); 18207c478bd9Sstevel@tonic-gate FR_DEBUG(("4. %#08x & %#08x != %#08x\n", 18217c478bd9Sstevel@tonic-gate *lip, *lm, *ld)); 18227c478bd9Sstevel@tonic-gate 18237c478bd9Sstevel@tonic-gate /* 18247c478bd9Sstevel@tonic-gate * Next we have 32 bits of packet flags. 18257c478bd9Sstevel@tonic-gate */ 18267c478bd9Sstevel@tonic-gate lip++, lm++, ld++; 18277c478bd9Sstevel@tonic-gate i |= ((*lip & *lm) != *ld); 18287c478bd9Sstevel@tonic-gate FR_DEBUG(("5. %#08x & %#08x != %#08x\n", 18297c478bd9Sstevel@tonic-gate *lip, *lm, *ld)); 18307c478bd9Sstevel@tonic-gate 18317c478bd9Sstevel@tonic-gate if (i == 0) { 18327c478bd9Sstevel@tonic-gate /* 18337c478bd9Sstevel@tonic-gate * If a fragment, then only the first has what we're 18347c478bd9Sstevel@tonic-gate * looking for here... 18357c478bd9Sstevel@tonic-gate */ 18367c478bd9Sstevel@tonic-gate if (portcmp) { 18377c478bd9Sstevel@tonic-gate if (!fr_tcpudpchk(fin, &fr->fr_tuc)) 18387c478bd9Sstevel@tonic-gate i = 1; 18397c478bd9Sstevel@tonic-gate } else { 18407c478bd9Sstevel@tonic-gate if (fr->fr_dcmp || fr->fr_scmp || 18417c478bd9Sstevel@tonic-gate fr->fr_tcpf || fr->fr_tcpfm) 18427c478bd9Sstevel@tonic-gate i = 1; 18437c478bd9Sstevel@tonic-gate if (fr->fr_icmpm || fr->fr_icmp) { 18447c478bd9Sstevel@tonic-gate if (((fi->fi_p != IPPROTO_ICMP) && 18457c478bd9Sstevel@tonic-gate (fi->fi_p != IPPROTO_ICMPV6)) || 18467c478bd9Sstevel@tonic-gate fin->fin_off || (fin->fin_dlen < 2)) 18477c478bd9Sstevel@tonic-gate i = 1; 18487c478bd9Sstevel@tonic-gate else if ((fin->fin_data[0] & fr->fr_icmpm) != 18497c478bd9Sstevel@tonic-gate fr->fr_icmp) { 18507c478bd9Sstevel@tonic-gate FR_DEBUG(("i. %#x & %#x != %#x\n", 18517c478bd9Sstevel@tonic-gate fin->fin_data[0], 18527c478bd9Sstevel@tonic-gate fr->fr_icmpm, fr->fr_icmp)); 18537c478bd9Sstevel@tonic-gate i = 1; 18547c478bd9Sstevel@tonic-gate } 18557c478bd9Sstevel@tonic-gate } 18567c478bd9Sstevel@tonic-gate } 18577c478bd9Sstevel@tonic-gate } 18587c478bd9Sstevel@tonic-gate return i; 18597c478bd9Sstevel@tonic-gate } 18607c478bd9Sstevel@tonic-gate 18617c478bd9Sstevel@tonic-gate 18627c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 18637c478bd9Sstevel@tonic-gate /* Function: fr_scanlist */ 18647c478bd9Sstevel@tonic-gate /* Returns: int - result flags of scanning filter list */ 18657c478bd9Sstevel@tonic-gate /* Parameters: fin(I) - pointer to packet information */ 18667c478bd9Sstevel@tonic-gate /* pass(I) - default result to return for filtering */ 18677c478bd9Sstevel@tonic-gate /* */ 18687c478bd9Sstevel@tonic-gate /* Check the input/output list of rules for a match to the current packet. */ 18697c478bd9Sstevel@tonic-gate /* If a match is found, the value of fr_flags from the rule becomes the */ 18707c478bd9Sstevel@tonic-gate /* return value and fin->fin_fr points to the matched rule. */ 18717c478bd9Sstevel@tonic-gate /* */ 18727c478bd9Sstevel@tonic-gate /* This function may be called recusively upto 16 times (limit inbuilt.) */ 18737c478bd9Sstevel@tonic-gate /* When unwinding, it should finish up with fin_depth as 0. */ 18747c478bd9Sstevel@tonic-gate /* */ 18757c478bd9Sstevel@tonic-gate /* Could be per interface, but this gets real nasty when you don't have, */ 18767c478bd9Sstevel@tonic-gate /* or can't easily change, the kernel source code to . */ 18777c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 18787c478bd9Sstevel@tonic-gate int fr_scanlist(fin, pass) 18797c478bd9Sstevel@tonic-gate fr_info_t *fin; 18807c478bd9Sstevel@tonic-gate u_32_t pass; 18817c478bd9Sstevel@tonic-gate { 18827c478bd9Sstevel@tonic-gate int rulen, portcmp, off, logged, skip; 18837c478bd9Sstevel@tonic-gate struct frentry *fr, *fnext; 1884ab25eeb5Syz u_32_t passt, passo; 18857c478bd9Sstevel@tonic-gate 18867c478bd9Sstevel@tonic-gate /* 18877c478bd9Sstevel@tonic-gate * Do not allow nesting deeper than 16 levels. 18887c478bd9Sstevel@tonic-gate */ 18897c478bd9Sstevel@tonic-gate if (fin->fin_depth >= 16) 18907c478bd9Sstevel@tonic-gate return pass; 18917c478bd9Sstevel@tonic-gate 18927c478bd9Sstevel@tonic-gate fr = fin->fin_fr; 18937c478bd9Sstevel@tonic-gate 18947c478bd9Sstevel@tonic-gate /* 18957c478bd9Sstevel@tonic-gate * If there are no rules in this list, return now. 18967c478bd9Sstevel@tonic-gate */ 18977c478bd9Sstevel@tonic-gate if (fr == NULL) 18987c478bd9Sstevel@tonic-gate return pass; 18997c478bd9Sstevel@tonic-gate 19007c478bd9Sstevel@tonic-gate skip = 0; 19017c478bd9Sstevel@tonic-gate logged = 0; 19027c478bd9Sstevel@tonic-gate portcmp = 0; 19037c478bd9Sstevel@tonic-gate fin->fin_depth++; 19047c478bd9Sstevel@tonic-gate fin->fin_fr = NULL; 19057c478bd9Sstevel@tonic-gate off = fin->fin_off; 19067c478bd9Sstevel@tonic-gate 19077c478bd9Sstevel@tonic-gate if ((fin->fin_flx & FI_TCPUDP) && (fin->fin_dlen > 3) && !off) 19087c478bd9Sstevel@tonic-gate portcmp = 1; 19097c478bd9Sstevel@tonic-gate 19107c478bd9Sstevel@tonic-gate for (rulen = 0; fr; fr = fnext, rulen++) { 19117c478bd9Sstevel@tonic-gate fnext = fr->fr_next; 19127c478bd9Sstevel@tonic-gate if (skip != 0) { 19137c478bd9Sstevel@tonic-gate FR_VERBOSE(("%d (%#x)\n", skip, fr->fr_flags)); 19147c478bd9Sstevel@tonic-gate skip--; 19157c478bd9Sstevel@tonic-gate continue; 19167c478bd9Sstevel@tonic-gate } 19177c478bd9Sstevel@tonic-gate 19187c478bd9Sstevel@tonic-gate /* 19197c478bd9Sstevel@tonic-gate * In all checks below, a null (zero) value in the 19207c478bd9Sstevel@tonic-gate * filter struture is taken to mean a wildcard. 19217c478bd9Sstevel@tonic-gate * 19227c478bd9Sstevel@tonic-gate * check that we are working for the right interface 19237c478bd9Sstevel@tonic-gate */ 19247c478bd9Sstevel@tonic-gate #ifdef _KERNEL 19257c478bd9Sstevel@tonic-gate if (fr->fr_ifa && fr->fr_ifa != fin->fin_ifp) 19267c478bd9Sstevel@tonic-gate continue; 19277c478bd9Sstevel@tonic-gate #else 19287c478bd9Sstevel@tonic-gate if (opts & (OPT_VERBOSE|OPT_DEBUG)) 19297c478bd9Sstevel@tonic-gate printf("\n"); 19307c478bd9Sstevel@tonic-gate FR_VERBOSE(("%c", FR_ISSKIP(pass) ? 's' : 1931ab25eeb5Syz FR_ISPASS(pass) ? 'p' : 19327c478bd9Sstevel@tonic-gate FR_ISACCOUNT(pass) ? 'A' : 19337c478bd9Sstevel@tonic-gate FR_ISAUTH(pass) ? 'a' : 19347c478bd9Sstevel@tonic-gate (pass & FR_NOMATCH) ? 'n' :'b')); 19357c478bd9Sstevel@tonic-gate if (fr->fr_ifa && fr->fr_ifa != fin->fin_ifp) 19367c478bd9Sstevel@tonic-gate continue; 19377c478bd9Sstevel@tonic-gate FR_VERBOSE((":i")); 19387c478bd9Sstevel@tonic-gate #endif 19397c478bd9Sstevel@tonic-gate 19407c478bd9Sstevel@tonic-gate switch (fr->fr_type) 19417c478bd9Sstevel@tonic-gate { 19427c478bd9Sstevel@tonic-gate case FR_T_IPF : 19437c478bd9Sstevel@tonic-gate case FR_T_IPF|FR_T_BUILTIN : 19447c478bd9Sstevel@tonic-gate if (fr_ipfcheck(fin, fr, portcmp)) 19457c478bd9Sstevel@tonic-gate continue; 19467c478bd9Sstevel@tonic-gate break; 1947ab25eeb5Syz #if defined(IPFILTER_BPF) 19487c478bd9Sstevel@tonic-gate case FR_T_BPFOPC : 19497c478bd9Sstevel@tonic-gate case FR_T_BPFOPC|FR_T_BUILTIN : 19507c478bd9Sstevel@tonic-gate { 19517c478bd9Sstevel@tonic-gate u_char *mc; 19527c478bd9Sstevel@tonic-gate 19537c478bd9Sstevel@tonic-gate if (*fin->fin_mp == NULL) 19547c478bd9Sstevel@tonic-gate continue; 19557c478bd9Sstevel@tonic-gate if (fin->fin_v != fr->fr_v) 19567c478bd9Sstevel@tonic-gate continue; 19577c478bd9Sstevel@tonic-gate mc = (u_char *)fin->fin_m; 1958ab25eeb5Syz if (!bpf_filter(fr->fr_data, mc, fin->fin_plen, 0)) 19597c478bd9Sstevel@tonic-gate continue; 19607c478bd9Sstevel@tonic-gate break; 19617c478bd9Sstevel@tonic-gate } 19627c478bd9Sstevel@tonic-gate #endif 19637c478bd9Sstevel@tonic-gate case FR_T_CALLFUNC|FR_T_BUILTIN : 19647c478bd9Sstevel@tonic-gate { 19657c478bd9Sstevel@tonic-gate frentry_t *f; 19667c478bd9Sstevel@tonic-gate 19677c478bd9Sstevel@tonic-gate f = (*fr->fr_func)(fin, &pass); 19687c478bd9Sstevel@tonic-gate if (f != NULL) 19697c478bd9Sstevel@tonic-gate fr = f; 19707c478bd9Sstevel@tonic-gate else 19717c478bd9Sstevel@tonic-gate continue; 19727c478bd9Sstevel@tonic-gate break; 19737c478bd9Sstevel@tonic-gate } 19747c478bd9Sstevel@tonic-gate default : 19757c478bd9Sstevel@tonic-gate break; 19767c478bd9Sstevel@tonic-gate } 19777c478bd9Sstevel@tonic-gate 19787c478bd9Sstevel@tonic-gate if ((fin->fin_out == 0) && (fr->fr_nattag.ipt_num[0] != 0)) { 19797c478bd9Sstevel@tonic-gate if (fin->fin_nattag == NULL) 19807c478bd9Sstevel@tonic-gate continue; 19817c478bd9Sstevel@tonic-gate if (fr_matchtag(&fr->fr_nattag, fin->fin_nattag) == 0) 19827c478bd9Sstevel@tonic-gate continue; 19837c478bd9Sstevel@tonic-gate } 19847c478bd9Sstevel@tonic-gate FR_VERBOSE(("=%s.%d *", fr->fr_group, rulen)); 19857c478bd9Sstevel@tonic-gate 19867c478bd9Sstevel@tonic-gate passt = fr->fr_flags; 19877c478bd9Sstevel@tonic-gate 1988ab25eeb5Syz /* 1989ab25eeb5Syz * Allowing a rule with the "keep state" flag set to match 1990ab25eeb5Syz * packets that have been tagged "out of window" by the TCP 1991ab25eeb5Syz * state tracking is foolish as the attempt to add a new 1992ab25eeb5Syz * state entry to the table will fail. 1993ab25eeb5Syz */ 1994ab25eeb5Syz if ((passt & FR_KEEPSTATE) && (fin->fin_flx & FI_OOW)) 1995ab25eeb5Syz continue; 1996ab25eeb5Syz 19977c478bd9Sstevel@tonic-gate /* 19987c478bd9Sstevel@tonic-gate * If the rule is a "call now" rule, then call the function 19997c478bd9Sstevel@tonic-gate * in the rule, if it exists and use the results from that. 20007c478bd9Sstevel@tonic-gate * If the function pointer is bad, just make like we ignore 20017c478bd9Sstevel@tonic-gate * it, except for increasing the hit counter. 20027c478bd9Sstevel@tonic-gate */ 20037c478bd9Sstevel@tonic-gate if ((passt & FR_CALLNOW) != 0) { 2004ab25eeb5Syz ATOMIC_INC64(fr->fr_hits); 20057c478bd9Sstevel@tonic-gate if ((fr->fr_func != NULL) && 20067c478bd9Sstevel@tonic-gate (fr->fr_func != (ipfunc_t)-1)) { 20077c478bd9Sstevel@tonic-gate frentry_t *frs; 20087c478bd9Sstevel@tonic-gate 20097c478bd9Sstevel@tonic-gate frs = fin->fin_fr; 20107c478bd9Sstevel@tonic-gate fin->fin_fr = fr; 20117c478bd9Sstevel@tonic-gate fr = (*fr->fr_func)(fin, &passt); 20127c478bd9Sstevel@tonic-gate if (fr == NULL) { 20137c478bd9Sstevel@tonic-gate fin->fin_fr = frs; 20147c478bd9Sstevel@tonic-gate continue; 20157c478bd9Sstevel@tonic-gate } 20167c478bd9Sstevel@tonic-gate passt = fr->fr_flags; 20177c478bd9Sstevel@tonic-gate fin->fin_fr = fr; 20187c478bd9Sstevel@tonic-gate } 20197c478bd9Sstevel@tonic-gate } else { 20207c478bd9Sstevel@tonic-gate fin->fin_fr = fr; 20217c478bd9Sstevel@tonic-gate } 20227c478bd9Sstevel@tonic-gate 20237c478bd9Sstevel@tonic-gate #ifdef IPFILTER_LOG 20247c478bd9Sstevel@tonic-gate /* 20257c478bd9Sstevel@tonic-gate * Just log this packet... 20267c478bd9Sstevel@tonic-gate */ 20277c478bd9Sstevel@tonic-gate if ((passt & FR_LOGMASK) == FR_LOG) { 20287c478bd9Sstevel@tonic-gate if (ipflog(fin, passt) == -1) { 20297c478bd9Sstevel@tonic-gate if (passt & FR_LOGORBLOCK) { 20307c478bd9Sstevel@tonic-gate passt &= ~FR_CMDMASK; 20317c478bd9Sstevel@tonic-gate passt |= FR_BLOCK|FR_QUICK; 20327c478bd9Sstevel@tonic-gate } 20337c478bd9Sstevel@tonic-gate ATOMIC_INCL(frstats[fin->fin_out].fr_skip); 20347c478bd9Sstevel@tonic-gate } 20357c478bd9Sstevel@tonic-gate ATOMIC_INCL(frstats[fin->fin_out].fr_pkl); 20367c478bd9Sstevel@tonic-gate logged = 1; 20377c478bd9Sstevel@tonic-gate } 20387c478bd9Sstevel@tonic-gate #endif /* IPFILTER_LOG */ 20397c478bd9Sstevel@tonic-gate fr->fr_bytes += (U_QUAD_T)fin->fin_plen; 2040ab25eeb5Syz passo = pass; 20417c478bd9Sstevel@tonic-gate if (FR_ISSKIP(passt)) 20427c478bd9Sstevel@tonic-gate skip = fr->fr_arg; 20437c478bd9Sstevel@tonic-gate else if ((passt & FR_LOGMASK) != FR_LOG) 20447c478bd9Sstevel@tonic-gate pass = passt; 20457c478bd9Sstevel@tonic-gate if (passt & (FR_RETICMP|FR_FAKEICMP)) 20467c478bd9Sstevel@tonic-gate fin->fin_icode = fr->fr_icode; 20477c478bd9Sstevel@tonic-gate FR_DEBUG(("pass %#x\n", pass)); 2048ab25eeb5Syz ATOMIC_INC64(fr->fr_hits); 20497c478bd9Sstevel@tonic-gate fin->fin_rule = rulen; 20507c478bd9Sstevel@tonic-gate (void) strncpy(fin->fin_group, fr->fr_group, FR_GROUPLEN); 20517c478bd9Sstevel@tonic-gate if (fr->fr_grp != NULL) { 20527c478bd9Sstevel@tonic-gate fin->fin_fr = *fr->fr_grp; 20537c478bd9Sstevel@tonic-gate pass = fr_scanlist(fin, pass); 20547c478bd9Sstevel@tonic-gate if (fin->fin_fr == NULL) { 20557c478bd9Sstevel@tonic-gate fin->fin_rule = rulen; 20567c478bd9Sstevel@tonic-gate (void) strncpy(fin->fin_group, fr->fr_group, 20577c478bd9Sstevel@tonic-gate FR_GROUPLEN); 20587c478bd9Sstevel@tonic-gate fin->fin_fr = fr; 20597c478bd9Sstevel@tonic-gate } 20607c478bd9Sstevel@tonic-gate if (fin->fin_flx & FI_DONTCACHE) 20617c478bd9Sstevel@tonic-gate logged = 1; 20627c478bd9Sstevel@tonic-gate } 2063ab25eeb5Syz 2064ab25eeb5Syz if (pass & FR_QUICK) { 2065ab25eeb5Syz /* 2066ab25eeb5Syz * Finally, if we've asked to track state for this 2067ab25eeb5Syz * packet, set it up. Add state for "quick" rules 2068ab25eeb5Syz * here so that if the action fails we can consider 2069ab25eeb5Syz * the rule to "not match" and keep on processing 2070ab25eeb5Syz * filter rules. 2071ab25eeb5Syz */ 2072ab25eeb5Syz if ((pass & FR_KEEPSTATE) && 2073ab25eeb5Syz !(fin->fin_flx & FI_STATE)) { 2074ab25eeb5Syz int out = fin->fin_out; 2075ab25eeb5Syz 2076ab25eeb5Syz if (fr_addstate(fin, NULL, 0) != NULL) { 2077ab25eeb5Syz ATOMIC_INCL(frstats[out].fr_ads); 2078ab25eeb5Syz } else { 2079ab25eeb5Syz ATOMIC_INCL(frstats[out].fr_bads); 2080ab25eeb5Syz pass = passo; 2081ab25eeb5Syz continue; 2082ab25eeb5Syz } 2083ab25eeb5Syz } 20847c478bd9Sstevel@tonic-gate break; 2085ab25eeb5Syz } 20867c478bd9Sstevel@tonic-gate } 20877c478bd9Sstevel@tonic-gate if (logged) 20887c478bd9Sstevel@tonic-gate fin->fin_flx |= FI_DONTCACHE; 20897c478bd9Sstevel@tonic-gate fin->fin_depth--; 20907c478bd9Sstevel@tonic-gate return pass; 20917c478bd9Sstevel@tonic-gate } 20927c478bd9Sstevel@tonic-gate 20937c478bd9Sstevel@tonic-gate 20947c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 20957c478bd9Sstevel@tonic-gate /* Function: fr_acctpkt */ 20967c478bd9Sstevel@tonic-gate /* Returns: frentry_t* - always returns NULL */ 20977c478bd9Sstevel@tonic-gate /* Parameters: fin(I) - pointer to packet information */ 20987c478bd9Sstevel@tonic-gate /* passp(IO) - pointer to current/new filter decision (unused) */ 20997c478bd9Sstevel@tonic-gate /* */ 21007c478bd9Sstevel@tonic-gate /* Checks a packet against accounting rules, if there are any for the given */ 21017c478bd9Sstevel@tonic-gate /* IP protocol version. */ 21027c478bd9Sstevel@tonic-gate /* */ 21037c478bd9Sstevel@tonic-gate /* N.B.: this function returns NULL to match the prototype used by other */ 21047c478bd9Sstevel@tonic-gate /* functions called from the IPFilter "mainline" in fr_check(). */ 21057c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 21067c478bd9Sstevel@tonic-gate frentry_t *fr_acctpkt(fin, passp) 21077c478bd9Sstevel@tonic-gate fr_info_t *fin; 21087c478bd9Sstevel@tonic-gate u_32_t *passp; 21097c478bd9Sstevel@tonic-gate { 21107c478bd9Sstevel@tonic-gate char group[FR_GROUPLEN]; 21117c478bd9Sstevel@tonic-gate frentry_t *fr, *frsave; 21127c478bd9Sstevel@tonic-gate u_32_t pass, rulen; 21137c478bd9Sstevel@tonic-gate 21147c478bd9Sstevel@tonic-gate passp = passp; 21157c478bd9Sstevel@tonic-gate #ifdef USE_INET6 21167c478bd9Sstevel@tonic-gate if (fin->fin_v == 6) 21177c478bd9Sstevel@tonic-gate fr = ipacct6[fin->fin_out][fr_active]; 21187c478bd9Sstevel@tonic-gate else 21197c478bd9Sstevel@tonic-gate #endif 21207c478bd9Sstevel@tonic-gate fr = ipacct[fin->fin_out][fr_active]; 21217c478bd9Sstevel@tonic-gate 21227c478bd9Sstevel@tonic-gate if (fr != NULL) { 21237c478bd9Sstevel@tonic-gate frsave = fin->fin_fr; 21247c478bd9Sstevel@tonic-gate bcopy(fin->fin_group, group, FR_GROUPLEN); 21257c478bd9Sstevel@tonic-gate rulen = fin->fin_rule; 21267c478bd9Sstevel@tonic-gate fin->fin_fr = fr; 21277c478bd9Sstevel@tonic-gate pass = fr_scanlist(fin, FR_NOMATCH); 21287c478bd9Sstevel@tonic-gate if (FR_ISACCOUNT(pass)) { 21297c478bd9Sstevel@tonic-gate ATOMIC_INCL(frstats[0].fr_acct); 21307c478bd9Sstevel@tonic-gate } 21317c478bd9Sstevel@tonic-gate fin->fin_fr = frsave; 21327c478bd9Sstevel@tonic-gate bcopy(group, fin->fin_group, FR_GROUPLEN); 21337c478bd9Sstevel@tonic-gate fin->fin_rule = rulen; 21347c478bd9Sstevel@tonic-gate } 21357c478bd9Sstevel@tonic-gate return NULL; 21367c478bd9Sstevel@tonic-gate } 21377c478bd9Sstevel@tonic-gate 21387c478bd9Sstevel@tonic-gate 21397c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 21407c478bd9Sstevel@tonic-gate /* Function: fr_firewall */ 21417c478bd9Sstevel@tonic-gate /* Returns: frentry_t* - returns pointer to matched rule, if no matches */ 21427c478bd9Sstevel@tonic-gate /* were found, returns NULL. */ 21437c478bd9Sstevel@tonic-gate /* Parameters: fin(I) - pointer to packet information */ 21447c478bd9Sstevel@tonic-gate /* passp(IO) - pointer to current/new filter decision (unused) */ 21457c478bd9Sstevel@tonic-gate /* */ 21467c478bd9Sstevel@tonic-gate /* Applies an appropriate set of firewall rules to the packet, to see if */ 21477c478bd9Sstevel@tonic-gate /* there are any matches. The first check is to see if a match can be seen */ 21487c478bd9Sstevel@tonic-gate /* in the cache. If not, then search an appropriate list of rules. Once a */ 21497c478bd9Sstevel@tonic-gate /* matching rule is found, take any appropriate actions as defined by the */ 21507c478bd9Sstevel@tonic-gate /* rule - except logging. */ 21517c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 21527c478bd9Sstevel@tonic-gate static frentry_t *fr_firewall(fin, passp) 21537c478bd9Sstevel@tonic-gate fr_info_t *fin; 21547c478bd9Sstevel@tonic-gate u_32_t *passp; 21557c478bd9Sstevel@tonic-gate { 21567c478bd9Sstevel@tonic-gate frentry_t *fr; 21577c478bd9Sstevel@tonic-gate fr_info_t *fc; 21587c478bd9Sstevel@tonic-gate u_32_t pass; 21597c478bd9Sstevel@tonic-gate int out; 21607c478bd9Sstevel@tonic-gate 21617c478bd9Sstevel@tonic-gate out = fin->fin_out; 21627c478bd9Sstevel@tonic-gate pass = *passp; 21637c478bd9Sstevel@tonic-gate 21647c478bd9Sstevel@tonic-gate /* 21657c478bd9Sstevel@tonic-gate * If a packet is found in the auth table, then skip checking 21667c478bd9Sstevel@tonic-gate * the access lists for permission but we do need to consider 21677c478bd9Sstevel@tonic-gate * the result as if it were from the ACL's. 21687c478bd9Sstevel@tonic-gate */ 21697c478bd9Sstevel@tonic-gate fc = &frcache[out][CACHE_HASH(fin)]; 2170ab25eeb5Syz READ_ENTER(&ipf_frcache); 21717c478bd9Sstevel@tonic-gate if (!bcmp((char *)fin, (char *)fc, FI_CSIZE)) { 21727c478bd9Sstevel@tonic-gate /* 2173ab25eeb5Syz * copy cached data so we can unlock the mutexes earlier. 21747c478bd9Sstevel@tonic-gate */ 21757c478bd9Sstevel@tonic-gate bcopy((char *)fc, (char *)fin, FI_COPYSIZE); 2176ab25eeb5Syz RWLOCK_EXIT(&ipf_frcache); 21777c478bd9Sstevel@tonic-gate ATOMIC_INCL(frstats[out].fr_chit); 2178ab25eeb5Syz 21797c478bd9Sstevel@tonic-gate if ((fr = fin->fin_fr) != NULL) { 2180ab25eeb5Syz ATOMIC_INC64(fr->fr_hits); 21817c478bd9Sstevel@tonic-gate pass = fr->fr_flags; 21827c478bd9Sstevel@tonic-gate } 21837c478bd9Sstevel@tonic-gate } else { 2184ab25eeb5Syz RWLOCK_EXIT(&ipf_frcache); 2185ab25eeb5Syz 21867c478bd9Sstevel@tonic-gate #ifdef USE_INET6 21877c478bd9Sstevel@tonic-gate if (fin->fin_v == 6) 21887c478bd9Sstevel@tonic-gate fin->fin_fr = ipfilter6[out][fr_active]; 21897c478bd9Sstevel@tonic-gate else 21907c478bd9Sstevel@tonic-gate #endif 21917c478bd9Sstevel@tonic-gate fin->fin_fr = ipfilter[out][fr_active]; 21927c478bd9Sstevel@tonic-gate if (fin->fin_fr != NULL) 21937c478bd9Sstevel@tonic-gate pass = fr_scanlist(fin, fr_pass); 2194ab25eeb5Syz 21957c478bd9Sstevel@tonic-gate if (((pass & FR_KEEPSTATE) == 0) && 2196ab25eeb5Syz ((fin->fin_flx & FI_DONTCACHE) == 0)) { 2197ab25eeb5Syz WRITE_ENTER(&ipf_frcache); 21987c478bd9Sstevel@tonic-gate bcopy((char *)fin, (char *)fc, FI_COPYSIZE); 2199ab25eeb5Syz RWLOCK_EXIT(&ipf_frcache); 2200ab25eeb5Syz } 22017c478bd9Sstevel@tonic-gate if ((pass & FR_NOMATCH)) { 22027c478bd9Sstevel@tonic-gate ATOMIC_INCL(frstats[out].fr_nom); 22037c478bd9Sstevel@tonic-gate } 22047c478bd9Sstevel@tonic-gate fr = fin->fin_fr; 22057c478bd9Sstevel@tonic-gate } 22067c478bd9Sstevel@tonic-gate 22077c478bd9Sstevel@tonic-gate /* 22087c478bd9Sstevel@tonic-gate * Apply packets per second rate-limiting to a rule as required. 22097c478bd9Sstevel@tonic-gate */ 22107c478bd9Sstevel@tonic-gate if ((fr != NULL) && (fr->fr_pps != 0) && 22117c478bd9Sstevel@tonic-gate !ppsratecheck(&fr->fr_lastpkt, &fr->fr_curpps, fr->fr_pps)) { 22127c478bd9Sstevel@tonic-gate pass &= ~(FR_CMDMASK|FR_DUP|FR_RETICMP|FR_RETRST); 22137c478bd9Sstevel@tonic-gate pass |= FR_BLOCK; 22147c478bd9Sstevel@tonic-gate ATOMIC_INCL(frstats[out].fr_ppshit); 22157c478bd9Sstevel@tonic-gate } 22167c478bd9Sstevel@tonic-gate 22177c478bd9Sstevel@tonic-gate /* 22187c478bd9Sstevel@tonic-gate * If we fail to add a packet to the authorization queue, then we 22197c478bd9Sstevel@tonic-gate * drop the packet later. However, if it was added then pretend 22207c478bd9Sstevel@tonic-gate * we've dropped it already. 22217c478bd9Sstevel@tonic-gate */ 22227c478bd9Sstevel@tonic-gate if (FR_ISAUTH(pass)) { 22237c478bd9Sstevel@tonic-gate if (fr_newauth(fin->fin_m, fin) != 0) { 22247c478bd9Sstevel@tonic-gate #ifdef _KERNEL 22257c478bd9Sstevel@tonic-gate fin->fin_m = *fin->fin_mp = NULL; 22267c478bd9Sstevel@tonic-gate #else 22277c478bd9Sstevel@tonic-gate ; 22287c478bd9Sstevel@tonic-gate #endif 22297c478bd9Sstevel@tonic-gate fin->fin_error = 0; 22307c478bd9Sstevel@tonic-gate } else 22317c478bd9Sstevel@tonic-gate fin->fin_error = ENOSPC; 22327c478bd9Sstevel@tonic-gate } 22337c478bd9Sstevel@tonic-gate 22347c478bd9Sstevel@tonic-gate if ((fr != NULL) && (fr->fr_func != NULL) && 22357c478bd9Sstevel@tonic-gate (fr->fr_func != (ipfunc_t)-1) && !(pass & FR_CALLNOW)) 22367c478bd9Sstevel@tonic-gate (void) (*fr->fr_func)(fin, &pass); 22377c478bd9Sstevel@tonic-gate 22387c478bd9Sstevel@tonic-gate /* 22397c478bd9Sstevel@tonic-gate * If a rule is a pre-auth rule, check again in the list of rules 22407c478bd9Sstevel@tonic-gate * loaded for authenticated use. It does not particulary matter 22417c478bd9Sstevel@tonic-gate * if this search fails because a "preauth" result, from a rule, 22427c478bd9Sstevel@tonic-gate * is treated as "not a pass", hence the packet is blocked. 22437c478bd9Sstevel@tonic-gate */ 22447c478bd9Sstevel@tonic-gate if (FR_ISPREAUTH(pass)) { 22457c478bd9Sstevel@tonic-gate if ((fin->fin_fr = ipauth) != NULL) 22467c478bd9Sstevel@tonic-gate pass = fr_scanlist(fin, fr_pass); 22477c478bd9Sstevel@tonic-gate } 22487c478bd9Sstevel@tonic-gate 22497c478bd9Sstevel@tonic-gate /* 22507c478bd9Sstevel@tonic-gate * If the rule has "keep frag" and the packet is actually a fragment, 22517c478bd9Sstevel@tonic-gate * then create a fragment state entry. 22527c478bd9Sstevel@tonic-gate */ 22537c478bd9Sstevel@tonic-gate if ((pass & (FR_KEEPFRAG|FR_KEEPSTATE)) == FR_KEEPFRAG) { 22547c478bd9Sstevel@tonic-gate if (fin->fin_flx & FI_FRAG) { 22557c478bd9Sstevel@tonic-gate if (fr_newfrag(fin, pass) == -1) { 22567c478bd9Sstevel@tonic-gate ATOMIC_INCL(frstats[out].fr_bnfr); 22577c478bd9Sstevel@tonic-gate } else { 22587c478bd9Sstevel@tonic-gate ATOMIC_INCL(frstats[out].fr_nfr); 22597c478bd9Sstevel@tonic-gate } 22607c478bd9Sstevel@tonic-gate } else { 22617c478bd9Sstevel@tonic-gate ATOMIC_INCL(frstats[out].fr_cfr); 22627c478bd9Sstevel@tonic-gate } 22637c478bd9Sstevel@tonic-gate } 22647c478bd9Sstevel@tonic-gate 22657c478bd9Sstevel@tonic-gate /* 22667c478bd9Sstevel@tonic-gate * Finally, if we've asked to track state for this packet, set it up. 22677c478bd9Sstevel@tonic-gate */ 2268ab25eeb5Syz if ((pass & FR_KEEPSTATE) && !(fin->fin_flx & FI_STATE)) { 22697c478bd9Sstevel@tonic-gate if (fr_addstate(fin, NULL, 0) != NULL) { 22707c478bd9Sstevel@tonic-gate ATOMIC_INCL(frstats[out].fr_ads); 22717c478bd9Sstevel@tonic-gate } else { 22727c478bd9Sstevel@tonic-gate ATOMIC_INCL(frstats[out].fr_bads); 2273ab25eeb5Syz if (FR_ISPASS(pass)) { 2274ab25eeb5Syz pass &= ~FR_CMDMASK; 2275ab25eeb5Syz pass |= FR_BLOCK; 2276ab25eeb5Syz } 22777c478bd9Sstevel@tonic-gate } 22787c478bd9Sstevel@tonic-gate } 22797c478bd9Sstevel@tonic-gate 22807c478bd9Sstevel@tonic-gate fr = fin->fin_fr; 22817c478bd9Sstevel@tonic-gate 22827c478bd9Sstevel@tonic-gate if (passp != NULL) 22837c478bd9Sstevel@tonic-gate *passp = pass; 22847c478bd9Sstevel@tonic-gate 22857c478bd9Sstevel@tonic-gate return fr; 22867c478bd9Sstevel@tonic-gate } 22877c478bd9Sstevel@tonic-gate 22887c478bd9Sstevel@tonic-gate 22897c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 22907c478bd9Sstevel@tonic-gate /* Function: fr_check */ 22917c478bd9Sstevel@tonic-gate /* Returns: int - 0 == packet allowed through, */ 22927c478bd9Sstevel@tonic-gate /* User space: */ 22937c478bd9Sstevel@tonic-gate /* -1 == packet blocked */ 22947c478bd9Sstevel@tonic-gate /* 1 == packet not matched */ 2295ab25eeb5Syz /* -2 == requires authentication */ 22967c478bd9Sstevel@tonic-gate /* Kernel: */ 22977c478bd9Sstevel@tonic-gate /* > 0 == filter error # for packet */ 22987c478bd9Sstevel@tonic-gate /* Parameters: ip(I) - pointer to start of IPv4/6 packet */ 22997c478bd9Sstevel@tonic-gate /* hlen(I) - length of header */ 23007c478bd9Sstevel@tonic-gate /* ifp(I) - pointer to interface this packet is on */ 23017c478bd9Sstevel@tonic-gate /* out(I) - 0 == packet going in, 1 == packet going out */ 23027c478bd9Sstevel@tonic-gate /* mp(IO) - pointer to caller's buffer pointer that holds this */ 23037c478bd9Sstevel@tonic-gate /* IP packet. */ 23047c478bd9Sstevel@tonic-gate /* Solaris & HP-UX ONLY : */ 2305ab25eeb5Syz /* qpi(I) - pointer to STREAMS queue information for this */ 23067c478bd9Sstevel@tonic-gate /* interface & direction. */ 23077c478bd9Sstevel@tonic-gate /* */ 23087c478bd9Sstevel@tonic-gate /* fr_check() is the master function for all IPFilter packet processing. */ 23097c478bd9Sstevel@tonic-gate /* It orchestrates: Network Address Translation (NAT), checking for packet */ 23107c478bd9Sstevel@tonic-gate /* authorisation (or pre-authorisation), presence of related state info., */ 23117c478bd9Sstevel@tonic-gate /* generating log entries, IP packet accounting, routing of packets as */ 23127c478bd9Sstevel@tonic-gate /* directed by firewall rules and of course whether or not to allow the */ 23137c478bd9Sstevel@tonic-gate /* packet to be further processed by the kernel. */ 23147c478bd9Sstevel@tonic-gate /* */ 23157c478bd9Sstevel@tonic-gate /* For packets blocked, the contents of "mp" will be NULL'd and the buffer */ 23167c478bd9Sstevel@tonic-gate /* freed. Packets passed may be returned with the pointer pointed to by */ 23177c478bd9Sstevel@tonic-gate /* by "mp" changed to a new buffer. */ 23187c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 23197c478bd9Sstevel@tonic-gate int fr_check(ip, hlen, ifp, out 23207c478bd9Sstevel@tonic-gate #if defined(_KERNEL) && defined(MENTAT) 23217c478bd9Sstevel@tonic-gate , qif, mp) 2322ab25eeb5Syz void *qif; 23237c478bd9Sstevel@tonic-gate #else 23247c478bd9Sstevel@tonic-gate , mp) 23257c478bd9Sstevel@tonic-gate #endif 23267c478bd9Sstevel@tonic-gate mb_t **mp; 23277c478bd9Sstevel@tonic-gate ip_t *ip; 23287c478bd9Sstevel@tonic-gate int hlen; 23297c478bd9Sstevel@tonic-gate void *ifp; 23307c478bd9Sstevel@tonic-gate int out; 23317c478bd9Sstevel@tonic-gate { 23327c478bd9Sstevel@tonic-gate /* 23337c478bd9Sstevel@tonic-gate * The above really sucks, but short of writing a diff 23347c478bd9Sstevel@tonic-gate */ 23357c478bd9Sstevel@tonic-gate fr_info_t frinfo; 23367c478bd9Sstevel@tonic-gate fr_info_t *fin = &frinfo; 2337ab25eeb5Syz u_32_t pass = fr_pass; 23387c478bd9Sstevel@tonic-gate frentry_t *fr = NULL; 2339ab25eeb5Syz int v = IP_V(ip); 23407c478bd9Sstevel@tonic-gate mb_t *mc = NULL; 23417c478bd9Sstevel@tonic-gate mb_t *m; 23427663b816Sml #ifdef USE_INET6 23437663b816Sml ip6_t *ip6; 23447663b816Sml #endif 2345ab25eeb5Syz #ifdef _KERNEL 2346ab25eeb5Syz # ifdef MENTAT 2347ab25eeb5Syz qpktinfo_t *qpi = qif; 2348ab25eeb5Syz #endif 2349ab25eeb5Syz #endif 2350ab25eeb5Syz SPL_INT(s); 23517c478bd9Sstevel@tonic-gate 23527c478bd9Sstevel@tonic-gate /* 23537c478bd9Sstevel@tonic-gate * The first part of fr_check() deals with making sure that what goes 23547c478bd9Sstevel@tonic-gate * into the filtering engine makes some sense. Information about the 23557c478bd9Sstevel@tonic-gate * the packet is distilled, collected into a fr_info_t structure and 23567c478bd9Sstevel@tonic-gate * the an attempt to ensure the buffer the packet is in is big enough 23577c478bd9Sstevel@tonic-gate * to hold all the required packet headers. 23587c478bd9Sstevel@tonic-gate */ 23597c478bd9Sstevel@tonic-gate #ifdef _KERNEL 23607c478bd9Sstevel@tonic-gate # ifdef MENTAT 2361ab25eeb5Syz if (!OK_32PTR(ip)) 23627c478bd9Sstevel@tonic-gate return 2; 23637c478bd9Sstevel@tonic-gate # endif 2364ab25eeb5Syz 23657c478bd9Sstevel@tonic-gate READ_ENTER(&ipf_global); 23667c478bd9Sstevel@tonic-gate 23677c478bd9Sstevel@tonic-gate if (fr_running <= 0) { 23687c478bd9Sstevel@tonic-gate RWLOCK_EXIT(&ipf_global); 23697c478bd9Sstevel@tonic-gate return 0; 23707c478bd9Sstevel@tonic-gate } 23717c478bd9Sstevel@tonic-gate 23727c478bd9Sstevel@tonic-gate bzero((char *)fin, sizeof(*fin)); 23737c478bd9Sstevel@tonic-gate 23747c478bd9Sstevel@tonic-gate # ifdef MENTAT 2375*381a2a9aSdr if (qpi->qpi_flags & QPI_NOCKSUM) 2376*381a2a9aSdr fin->fin_flx |= FI_NOCKSUM; 2377ab25eeb5Syz m = qpi->qpi_m; 23787c478bd9Sstevel@tonic-gate fin->fin_qfm = m; 2379ab25eeb5Syz fin->fin_qpi = qpi; 23807c478bd9Sstevel@tonic-gate # else /* MENTAT */ 23817c478bd9Sstevel@tonic-gate 23827c478bd9Sstevel@tonic-gate m = *mp; 2383ab25eeb5Syz 23847c478bd9Sstevel@tonic-gate # if defined(M_MCAST) 23857c478bd9Sstevel@tonic-gate if ((m->m_flags & M_MCAST) != 0) 23867c478bd9Sstevel@tonic-gate fin->fin_flx |= FI_MBCAST|FI_MULTICAST; 23877c478bd9Sstevel@tonic-gate # endif 2388ab25eeb5Syz # if defined(M_MLOOP) 2389ab25eeb5Syz if ((m->m_flags & M_MLOOP) != 0) 2390ab25eeb5Syz fin->fin_flx |= FI_MBCAST|FI_MULTICAST; 2391ab25eeb5Syz # endif 23927c478bd9Sstevel@tonic-gate # if defined(M_BCAST) 23937c478bd9Sstevel@tonic-gate if ((m->m_flags & M_BCAST) != 0) 23947c478bd9Sstevel@tonic-gate fin->fin_flx |= FI_MBCAST|FI_BROADCAST; 23957c478bd9Sstevel@tonic-gate # endif 23967c478bd9Sstevel@tonic-gate # ifdef M_CANFASTFWD 23977c478bd9Sstevel@tonic-gate /* 23987c478bd9Sstevel@tonic-gate * XXX For now, IP Filter and fast-forwarding of cached flows 23997c478bd9Sstevel@tonic-gate * XXX are mutually exclusive. Eventually, IP Filter should 24007c478bd9Sstevel@tonic-gate * XXX get a "can-fast-forward" filter rule. 24017c478bd9Sstevel@tonic-gate */ 24027c478bd9Sstevel@tonic-gate m->m_flags &= ~M_CANFASTFWD; 24037c478bd9Sstevel@tonic-gate # endif /* M_CANFASTFWD */ 24047c478bd9Sstevel@tonic-gate # ifdef CSUM_DELAY_DATA 24057c478bd9Sstevel@tonic-gate /* 24067c478bd9Sstevel@tonic-gate * disable delayed checksums. 24077c478bd9Sstevel@tonic-gate */ 24087c478bd9Sstevel@tonic-gate if (m->m_pkthdr.csum_flags & CSUM_DELAY_DATA) { 24097c478bd9Sstevel@tonic-gate in_delayed_cksum(m); 24107c478bd9Sstevel@tonic-gate m->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA; 24117c478bd9Sstevel@tonic-gate } 24127c478bd9Sstevel@tonic-gate # endif /* CSUM_DELAY_DATA */ 24137c478bd9Sstevel@tonic-gate # endif /* MENTAT */ 2414ab25eeb5Syz #else 24157c478bd9Sstevel@tonic-gate READ_ENTER(&ipf_global); 24167c478bd9Sstevel@tonic-gate 24177c478bd9Sstevel@tonic-gate bzero((char *)fin, sizeof(*fin)); 24187c478bd9Sstevel@tonic-gate m = *mp; 24197c478bd9Sstevel@tonic-gate #endif /* _KERNEL */ 24207c478bd9Sstevel@tonic-gate 2421ab25eeb5Syz fin->fin_v = v; 2422ab25eeb5Syz fin->fin_m = m; 2423ab25eeb5Syz fin->fin_ip = ip; 2424ab25eeb5Syz fin->fin_mp = mp; 2425ab25eeb5Syz fin->fin_out = out; 2426ab25eeb5Syz fin->fin_ifp = ifp; 2427ab25eeb5Syz fin->fin_error = ENETUNREACH; 2428ab25eeb5Syz fin->fin_hlen = (u_short)hlen; 2429ab25eeb5Syz fin->fin_dp = (char *)ip + hlen; 2430ab25eeb5Syz 2431ab25eeb5Syz fin->fin_ipoff = (char *)ip - MTOD(m, char *); 2432ab25eeb5Syz 2433ab25eeb5Syz SPL_NET(s); 2434ab25eeb5Syz 24357c478bd9Sstevel@tonic-gate #ifdef USE_INET6 24367c478bd9Sstevel@tonic-gate if (v == 6) { 2437ab25eeb5Syz ATOMIC_INCL(frstats[out].fr_ipv6); 24387c478bd9Sstevel@tonic-gate /* 24397c478bd9Sstevel@tonic-gate * Jumbo grams are quite likely too big for internal buffer 24407c478bd9Sstevel@tonic-gate * structures to handle comfortably, for now, so just drop 2441ab25eeb5Syz * them. 24427c478bd9Sstevel@tonic-gate */ 2443ab25eeb5Syz ip6 = (ip6_t *)ip; 2444ab25eeb5Syz fin->fin_plen = ntohs(ip6->ip6_plen); 2445ab25eeb5Syz if (fin->fin_plen == 0) { 24467c478bd9Sstevel@tonic-gate pass = FR_BLOCK|FR_NOMATCH; 24477c478bd9Sstevel@tonic-gate goto filtered; 24487c478bd9Sstevel@tonic-gate } 2449ab25eeb5Syz fin->fin_plen += sizeof(ip6_t); 24507c478bd9Sstevel@tonic-gate } else 24517c478bd9Sstevel@tonic-gate #endif 24527c478bd9Sstevel@tonic-gate { 2453ab25eeb5Syz #if (OpenBSD >= 200311) && defined(_KERNEL) 2454ab25eeb5Syz ip->ip_len = ntohs(ip->ip_len); 2455ab25eeb5Syz ip->ip_off = ntohs(ip->ip_off); 24567c478bd9Sstevel@tonic-gate #endif 2457ab25eeb5Syz fin->fin_plen = ip->ip_len; 24587c478bd9Sstevel@tonic-gate } 24597c478bd9Sstevel@tonic-gate 24607663b816Sml if (fr_makefrip(hlen, ip, fin) == -1) { 24617663b816Sml READ_ENTER(&ipf_mutex); 24627663b816Sml pass = FR_BLOCK; 24637663b816Sml goto filtered; 24647663b816Sml } 24657c478bd9Sstevel@tonic-gate 24667c478bd9Sstevel@tonic-gate /* 24677c478bd9Sstevel@tonic-gate * For at least IPv6 packets, if a m_pullup() fails then this pointer 24687c478bd9Sstevel@tonic-gate * becomes NULL and so we have no packet to free. 24697c478bd9Sstevel@tonic-gate */ 24707c478bd9Sstevel@tonic-gate if (*fin->fin_mp == NULL) 24717c478bd9Sstevel@tonic-gate goto finished; 24727c478bd9Sstevel@tonic-gate 24737c478bd9Sstevel@tonic-gate if (!out) { 24747c478bd9Sstevel@tonic-gate if (v == 4) { 24757c478bd9Sstevel@tonic-gate #ifdef _KERNEL 24767c478bd9Sstevel@tonic-gate if (fr_chksrc && !fr_verifysrc(fin)) { 24777c478bd9Sstevel@tonic-gate ATOMIC_INCL(frstats[0].fr_badsrc); 24787c478bd9Sstevel@tonic-gate fin->fin_flx |= FI_BADSRC; 24797c478bd9Sstevel@tonic-gate } 24807c478bd9Sstevel@tonic-gate #endif 2481ab25eeb5Syz if (fin->fin_ip->ip_ttl < fr_minttl) { 24827c478bd9Sstevel@tonic-gate ATOMIC_INCL(frstats[0].fr_badttl); 24837c478bd9Sstevel@tonic-gate fin->fin_flx |= FI_LOWTTL; 24847c478bd9Sstevel@tonic-gate } 24857c478bd9Sstevel@tonic-gate } 24867c478bd9Sstevel@tonic-gate #ifdef USE_INET6 24877c478bd9Sstevel@tonic-gate else if (v == 6) { 24887663b816Sml ip6 = (ip6_t *)ip; 24897663b816Sml #ifdef _KERNEL 24907663b816Sml if (fr_chksrc && !fr_verifysrc(fin)) { 24917663b816Sml ATOMIC_INCL(frstats[0].fr_badsrc); 24927663b816Sml fin->fin_flx |= FI_BADSRC; 24937663b816Sml } 24947663b816Sml #endif 24957663b816Sml if (ip6->ip6_hlim < fr_minttl) { 24967c478bd9Sstevel@tonic-gate ATOMIC_INCL(frstats[0].fr_badttl); 24977c478bd9Sstevel@tonic-gate fin->fin_flx |= FI_LOWTTL; 24987c478bd9Sstevel@tonic-gate } 24997c478bd9Sstevel@tonic-gate } 25007c478bd9Sstevel@tonic-gate #endif 25017c478bd9Sstevel@tonic-gate } 25027c478bd9Sstevel@tonic-gate 25037c478bd9Sstevel@tonic-gate if (fin->fin_flx & FI_SHORT) { 25047c478bd9Sstevel@tonic-gate ATOMIC_INCL(frstats[out].fr_short); 25057c478bd9Sstevel@tonic-gate } 25067c478bd9Sstevel@tonic-gate 25077c478bd9Sstevel@tonic-gate READ_ENTER(&ipf_mutex); 25087c478bd9Sstevel@tonic-gate 25097c478bd9Sstevel@tonic-gate /* 25107c478bd9Sstevel@tonic-gate * Check auth now. This, combined with the check below to see if apass 25117c478bd9Sstevel@tonic-gate * is 0 is to ensure that we don't count the packet twice, which can 25127c478bd9Sstevel@tonic-gate * otherwise occur when we reprocess it. As it is, we only count it 25137c478bd9Sstevel@tonic-gate * after it has no auth. table matchup. This also stops NAT from 25147c478bd9Sstevel@tonic-gate * occuring until after the packet has been auth'd. 25157c478bd9Sstevel@tonic-gate */ 25167c478bd9Sstevel@tonic-gate fr = fr_checkauth(fin, &pass); 2517ab25eeb5Syz if (!out) { 2518ab25eeb5Syz if (fr_checknatin(fin, &pass) == -1) { 2519ab25eeb5Syz RWLOCK_EXIT(&ipf_mutex); 2520ab25eeb5Syz goto finished; 2521ab25eeb5Syz } 2522ab25eeb5Syz } 25237c478bd9Sstevel@tonic-gate if (!out) 25247c478bd9Sstevel@tonic-gate (void) fr_acctpkt(fin, NULL); 25257c478bd9Sstevel@tonic-gate 25267c478bd9Sstevel@tonic-gate if (fr == NULL) 25277c478bd9Sstevel@tonic-gate if ((fin->fin_flx & (FI_FRAG|FI_BAD)) == FI_FRAG) 25287c478bd9Sstevel@tonic-gate fr = fr_knownfrag(fin, &pass); 25297c478bd9Sstevel@tonic-gate if (fr == NULL) 25307c478bd9Sstevel@tonic-gate fr = fr_checkstate(fin, &pass); 25317c478bd9Sstevel@tonic-gate 25327c478bd9Sstevel@tonic-gate if ((pass & FR_NOMATCH) || (fr == NULL)) 25337c478bd9Sstevel@tonic-gate fr = fr_firewall(fin, &pass); 25347c478bd9Sstevel@tonic-gate 25357c478bd9Sstevel@tonic-gate fin->fin_fr = fr; 25367c478bd9Sstevel@tonic-gate 25377c478bd9Sstevel@tonic-gate /* 25387c478bd9Sstevel@tonic-gate * Only count/translate packets which will be passed on, out the 25397c478bd9Sstevel@tonic-gate * interface. 25407c478bd9Sstevel@tonic-gate */ 25417c478bd9Sstevel@tonic-gate if (out && FR_ISPASS(pass)) { 25427c478bd9Sstevel@tonic-gate (void) fr_acctpkt(fin, NULL); 25437c478bd9Sstevel@tonic-gate 2544ab25eeb5Syz if (fr_checknatout(fin, &pass) == -1) { 2545ab25eeb5Syz RWLOCK_EXIT(&ipf_mutex); 2546ab25eeb5Syz goto finished; 2547ab25eeb5Syz } else if ((fr_update_ipid != 0) && (v == 4)) { 25487c478bd9Sstevel@tonic-gate if (fr_updateipid(fin) == -1) { 25497c478bd9Sstevel@tonic-gate ATOMIC_INCL(frstats[1].fr_ipud); 25507c478bd9Sstevel@tonic-gate pass &= ~FR_CMDMASK; 25517c478bd9Sstevel@tonic-gate pass |= FR_BLOCK; 25527c478bd9Sstevel@tonic-gate } else { 25537c478bd9Sstevel@tonic-gate ATOMIC_INCL(frstats[0].fr_ipud); 25547c478bd9Sstevel@tonic-gate } 25557c478bd9Sstevel@tonic-gate } 25567c478bd9Sstevel@tonic-gate } 25577c478bd9Sstevel@tonic-gate 25587c478bd9Sstevel@tonic-gate #ifdef IPFILTER_LOG 2559ab25eeb5Syz if ((fr_flags & FF_LOGGING) || (pass & FR_LOGMASK)) { 25607c478bd9Sstevel@tonic-gate (void) fr_dolog(fin, &pass); 2561ab25eeb5Syz } 25627c478bd9Sstevel@tonic-gate #endif 25637c478bd9Sstevel@tonic-gate 25647c478bd9Sstevel@tonic-gate if (fin->fin_state != NULL) 25657c478bd9Sstevel@tonic-gate fr_statederef(fin, (ipstate_t **)&fin->fin_state); 25667c478bd9Sstevel@tonic-gate 25677c478bd9Sstevel@tonic-gate if (fin->fin_nat != NULL) 25687c478bd9Sstevel@tonic-gate fr_natderef((nat_t **)&fin->fin_nat); 25697c478bd9Sstevel@tonic-gate 25707c478bd9Sstevel@tonic-gate /* 25717c478bd9Sstevel@tonic-gate * Only allow FR_DUP to work if a rule matched - it makes no sense to 25727c478bd9Sstevel@tonic-gate * set FR_DUP as a "default" as there are no instructions about where 2573ab25eeb5Syz * to send the packet. Use fin_m here because it may have changed 2574ab25eeb5Syz * (without an update of 'm') in prior processing. 25757c478bd9Sstevel@tonic-gate */ 25767c478bd9Sstevel@tonic-gate if ((fr != NULL) && (pass & FR_DUP)) { 2577ab25eeb5Syz mc = M_DUPLICATE(fin->fin_m); 25787c478bd9Sstevel@tonic-gate } 25797c478bd9Sstevel@tonic-gate 25807c478bd9Sstevel@tonic-gate if (pass & (FR_RETRST|FR_RETICMP)) { 25817c478bd9Sstevel@tonic-gate /* 25827c478bd9Sstevel@tonic-gate * Should we return an ICMP packet to indicate error 25837c478bd9Sstevel@tonic-gate * status passing through the packet filter ? 25847c478bd9Sstevel@tonic-gate * WARNING: ICMP error packets AND TCP RST packets should 25857c478bd9Sstevel@tonic-gate * ONLY be sent in repsonse to incoming packets. Sending them 25867c478bd9Sstevel@tonic-gate * in response to outbound packets can result in a panic on 25877c478bd9Sstevel@tonic-gate * some operating systems. 25887c478bd9Sstevel@tonic-gate */ 25897c478bd9Sstevel@tonic-gate if (!out) { 25907c478bd9Sstevel@tonic-gate if (pass & FR_RETICMP) { 25917c478bd9Sstevel@tonic-gate int dst; 25927c478bd9Sstevel@tonic-gate 25937c478bd9Sstevel@tonic-gate if ((pass & FR_RETMASK) == FR_FAKEICMP) 25947c478bd9Sstevel@tonic-gate dst = 1; 25957c478bd9Sstevel@tonic-gate else 25967c478bd9Sstevel@tonic-gate dst = 0; 25977c478bd9Sstevel@tonic-gate (void) fr_send_icmp_err(ICMP_UNREACH, fin, dst); 25987c478bd9Sstevel@tonic-gate ATOMIC_INCL(frstats[0].fr_ret); 25997c478bd9Sstevel@tonic-gate } else if (((pass & FR_RETMASK) == FR_RETRST) && 26007c478bd9Sstevel@tonic-gate !(fin->fin_flx & FI_SHORT)) { 26017c478bd9Sstevel@tonic-gate if (fr_send_reset(fin) == 0) { 26027c478bd9Sstevel@tonic-gate ATOMIC_INCL(frstats[1].fr_ret); 26037c478bd9Sstevel@tonic-gate } 26047c478bd9Sstevel@tonic-gate } 26057c478bd9Sstevel@tonic-gate } else { 26067c478bd9Sstevel@tonic-gate if (pass & FR_RETRST) 26077c478bd9Sstevel@tonic-gate fin->fin_error = ECONNRESET; 26087c478bd9Sstevel@tonic-gate } 26097c478bd9Sstevel@tonic-gate } 26107c478bd9Sstevel@tonic-gate 26117c478bd9Sstevel@tonic-gate /* 26127c478bd9Sstevel@tonic-gate * If we didn't drop off the bottom of the list of rules (and thus 26137c478bd9Sstevel@tonic-gate * the 'current' rule fr is not NULL), then we may have some extra 26147c478bd9Sstevel@tonic-gate * instructions about what to do with a packet. 26157c478bd9Sstevel@tonic-gate * Once we're finished return to our caller, freeing the packet if 26167c478bd9Sstevel@tonic-gate * we are dropping it (* BSD ONLY *). 2617ab25eeb5Syz * Reassign m from fin_m as we may have a new buffer, now. 26187c478bd9Sstevel@tonic-gate */ 26197c478bd9Sstevel@tonic-gate filtered: 2620ab25eeb5Syz m = fin->fin_m; 26217c478bd9Sstevel@tonic-gate 26227c478bd9Sstevel@tonic-gate if (fr != NULL) { 26237c478bd9Sstevel@tonic-gate frdest_t *fdp; 26247c478bd9Sstevel@tonic-gate 26257c478bd9Sstevel@tonic-gate fdp = &fr->fr_tifs[fin->fin_rev]; 26267c478bd9Sstevel@tonic-gate 26277c478bd9Sstevel@tonic-gate if (!out && (pass & FR_FASTROUTE)) { 26287c478bd9Sstevel@tonic-gate /* 26297c478bd9Sstevel@tonic-gate * For fastroute rule, no destioation interface defined 26307c478bd9Sstevel@tonic-gate * so pass NULL as the frdest_t parameter 26317c478bd9Sstevel@tonic-gate */ 26327c478bd9Sstevel@tonic-gate (void) fr_fastroute(m, mp, fin, NULL); 26337c478bd9Sstevel@tonic-gate m = *mp = NULL; 26347c478bd9Sstevel@tonic-gate } else if ((fdp->fd_ifp != NULL) && 26357c478bd9Sstevel@tonic-gate (fdp->fd_ifp != (struct ifnet *)-1)) { 26367c478bd9Sstevel@tonic-gate /* this is for to rules: */ 26377c478bd9Sstevel@tonic-gate (void) fr_fastroute(m, mp, fin, fdp); 26387c478bd9Sstevel@tonic-gate m = *mp = NULL; 26397c478bd9Sstevel@tonic-gate } 26407c478bd9Sstevel@tonic-gate 26417c478bd9Sstevel@tonic-gate /* 26427c478bd9Sstevel@tonic-gate * Generate a duplicated packet. 26437c478bd9Sstevel@tonic-gate */ 26447c478bd9Sstevel@tonic-gate if (mc != NULL) 26457c478bd9Sstevel@tonic-gate (void) fr_fastroute(mc, &mc, fin, &fr->fr_dif); 26467c478bd9Sstevel@tonic-gate } 26477c478bd9Sstevel@tonic-gate 26487c478bd9Sstevel@tonic-gate /* 26497c478bd9Sstevel@tonic-gate * This late because the likes of fr_fastroute() use fin_fr. 26507c478bd9Sstevel@tonic-gate */ 26517c478bd9Sstevel@tonic-gate RWLOCK_EXIT(&ipf_mutex); 26527c478bd9Sstevel@tonic-gate 2653ab25eeb5Syz finished: 26547c478bd9Sstevel@tonic-gate if (!FR_ISPASS(pass)) { 2655ab25eeb5Syz ATOMIC_INCL(frstats[out].fr_block); 2656ab25eeb5Syz if (*mp != NULL) { 26577c478bd9Sstevel@tonic-gate FREE_MB_T(*mp); 26587c478bd9Sstevel@tonic-gate m = *mp = NULL; 26597c478bd9Sstevel@tonic-gate } 2660ab25eeb5Syz } else { 2661ab25eeb5Syz ATOMIC_INCL(frstats[out].fr_pass); 26627c478bd9Sstevel@tonic-gate #if defined(_KERNEL) && defined(__sgi) 2663ab25eeb5Syz if ((fin->fin_hbuf != NULL) && 2664ab25eeb5Syz (mtod(fin->fin_m, struct ip *) != fin->fin_ip)) { 2665ab25eeb5Syz COPYBACK(m, 0, fin->fin_plen, fin->fin_hbuf); 26667c478bd9Sstevel@tonic-gate } 26677c478bd9Sstevel@tonic-gate #endif 2668ab25eeb5Syz } 2669ab25eeb5Syz 2670ab25eeb5Syz SPL_X(s); 26717c478bd9Sstevel@tonic-gate RWLOCK_EXIT(&ipf_global); 2672ab25eeb5Syz 26737c478bd9Sstevel@tonic-gate #ifdef _KERNEL 2674ab25eeb5Syz # if OpenBSD >= 200311 2675ab25eeb5Syz if (FR_ISPASS(pass) && (v == 4)) { 2676ab25eeb5Syz ip = fin->fin_ip; 2677ab25eeb5Syz ip->ip_len = ntohs(ip->ip_len); 2678ab25eeb5Syz ip->ip_off = ntohs(ip->ip_off); 2679ab25eeb5Syz } 2680ab25eeb5Syz # endif 26817c478bd9Sstevel@tonic-gate return (FR_ISPASS(pass)) ? 0 : fin->fin_error; 26827c478bd9Sstevel@tonic-gate #else /* _KERNEL */ 2683ab25eeb5Syz FR_VERBOSE(("fin_flx %#x pass %#x ", fin->fin_flx, pass)); 26847c478bd9Sstevel@tonic-gate if ((pass & FR_NOMATCH) != 0) 26857c478bd9Sstevel@tonic-gate return 1; 26867c478bd9Sstevel@tonic-gate 26877c478bd9Sstevel@tonic-gate if ((pass & FR_RETMASK) != 0) 26887c478bd9Sstevel@tonic-gate switch (pass & FR_RETMASK) 26897c478bd9Sstevel@tonic-gate { 26907c478bd9Sstevel@tonic-gate case FR_RETRST : 26917c478bd9Sstevel@tonic-gate return 3; 26927c478bd9Sstevel@tonic-gate case FR_RETICMP : 26937c478bd9Sstevel@tonic-gate return 4; 26947c478bd9Sstevel@tonic-gate case FR_FAKEICMP : 26957c478bd9Sstevel@tonic-gate return 5; 26967c478bd9Sstevel@tonic-gate } 26977c478bd9Sstevel@tonic-gate 26987c478bd9Sstevel@tonic-gate switch (pass & FR_CMDMASK) 26997c478bd9Sstevel@tonic-gate { 27007c478bd9Sstevel@tonic-gate case FR_PASS : 27017c478bd9Sstevel@tonic-gate return 0; 27027c478bd9Sstevel@tonic-gate case FR_BLOCK : 27037c478bd9Sstevel@tonic-gate return -1; 27047c478bd9Sstevel@tonic-gate case FR_AUTH : 27057c478bd9Sstevel@tonic-gate return -2; 27067c478bd9Sstevel@tonic-gate case FR_ACCOUNT : 27077c478bd9Sstevel@tonic-gate return -3; 27087c478bd9Sstevel@tonic-gate case FR_PREAUTH : 27097c478bd9Sstevel@tonic-gate return -4; 27107c478bd9Sstevel@tonic-gate } 27117c478bd9Sstevel@tonic-gate return 2; 27127c478bd9Sstevel@tonic-gate #endif /* _KERNEL */ 27137c478bd9Sstevel@tonic-gate } 27147c478bd9Sstevel@tonic-gate 27157c478bd9Sstevel@tonic-gate 27167c478bd9Sstevel@tonic-gate #ifdef IPFILTER_LOG 27177c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 27187c478bd9Sstevel@tonic-gate /* Function: fr_dolog */ 27197c478bd9Sstevel@tonic-gate /* Returns: frentry_t* - returns contents of fin_fr (no change made) */ 27207c478bd9Sstevel@tonic-gate /* Parameters: fin(I) - pointer to packet information */ 27217c478bd9Sstevel@tonic-gate /* passp(IO) - pointer to current/new filter decision (unused) */ 27227c478bd9Sstevel@tonic-gate /* */ 27237c478bd9Sstevel@tonic-gate /* Checks flags set to see how a packet should be logged, if it is to be */ 27247c478bd9Sstevel@tonic-gate /* logged. Adjust statistics based on its success or not. */ 27257c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 27267c478bd9Sstevel@tonic-gate frentry_t *fr_dolog(fin, passp) 27277c478bd9Sstevel@tonic-gate fr_info_t *fin; 27287c478bd9Sstevel@tonic-gate u_32_t *passp; 27297c478bd9Sstevel@tonic-gate { 27307c478bd9Sstevel@tonic-gate u_32_t pass; 27317c478bd9Sstevel@tonic-gate int out; 27327c478bd9Sstevel@tonic-gate 27337c478bd9Sstevel@tonic-gate out = fin->fin_out; 27347c478bd9Sstevel@tonic-gate pass = *passp; 27357c478bd9Sstevel@tonic-gate 27367c478bd9Sstevel@tonic-gate if ((fr_flags & FF_LOGNOMATCH) && (pass & FR_NOMATCH)) { 27377c478bd9Sstevel@tonic-gate pass |= FF_LOGNOMATCH; 27387c478bd9Sstevel@tonic-gate ATOMIC_INCL(frstats[out].fr_npkl); 27397c478bd9Sstevel@tonic-gate goto logit; 27407c478bd9Sstevel@tonic-gate } else if (((pass & FR_LOGMASK) == FR_LOGP) || 27417c478bd9Sstevel@tonic-gate (FR_ISPASS(pass) && (fr_flags & FF_LOGPASS))) { 27427c478bd9Sstevel@tonic-gate if ((pass & FR_LOGMASK) != FR_LOGP) 27437c478bd9Sstevel@tonic-gate pass |= FF_LOGPASS; 27447c478bd9Sstevel@tonic-gate ATOMIC_INCL(frstats[out].fr_ppkl); 27457c478bd9Sstevel@tonic-gate goto logit; 27467c478bd9Sstevel@tonic-gate } else if (((pass & FR_LOGMASK) == FR_LOGB) || 27477c478bd9Sstevel@tonic-gate (FR_ISBLOCK(pass) && (fr_flags & FF_LOGBLOCK))) { 27487c478bd9Sstevel@tonic-gate if ((pass & FR_LOGMASK) != FR_LOGB) 27497c478bd9Sstevel@tonic-gate pass |= FF_LOGBLOCK; 27507c478bd9Sstevel@tonic-gate ATOMIC_INCL(frstats[out].fr_bpkl); 27517c478bd9Sstevel@tonic-gate logit: 27527c478bd9Sstevel@tonic-gate if (ipflog(fin, pass) == -1) { 27537c478bd9Sstevel@tonic-gate ATOMIC_INCL(frstats[out].fr_skip); 27547c478bd9Sstevel@tonic-gate 27557c478bd9Sstevel@tonic-gate /* 27567c478bd9Sstevel@tonic-gate * If the "or-block" option has been used then 27577c478bd9Sstevel@tonic-gate * block the packet if we failed to log it. 27587c478bd9Sstevel@tonic-gate */ 27597c478bd9Sstevel@tonic-gate if ((pass & FR_LOGORBLOCK) && 27607c478bd9Sstevel@tonic-gate FR_ISPASS(pass)) { 27617c478bd9Sstevel@tonic-gate pass &= ~FR_CMDMASK; 27627c478bd9Sstevel@tonic-gate pass |= FR_BLOCK; 27637c478bd9Sstevel@tonic-gate } 27647c478bd9Sstevel@tonic-gate } 27657c478bd9Sstevel@tonic-gate *passp = pass; 27667c478bd9Sstevel@tonic-gate } 27677c478bd9Sstevel@tonic-gate 27687c478bd9Sstevel@tonic-gate return fin->fin_fr; 27697c478bd9Sstevel@tonic-gate } 27707c478bd9Sstevel@tonic-gate #endif /* IPFILTER_LOG */ 27717c478bd9Sstevel@tonic-gate 27727c478bd9Sstevel@tonic-gate 27737c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 27747c478bd9Sstevel@tonic-gate /* Function: ipf_cksum */ 27757c478bd9Sstevel@tonic-gate /* Returns: u_short - IP header checksum */ 27767c478bd9Sstevel@tonic-gate /* Parameters: addr(I) - pointer to start of buffer to checksum */ 27777c478bd9Sstevel@tonic-gate /* len(I) - length of buffer in bytes */ 27787c478bd9Sstevel@tonic-gate /* */ 27797c478bd9Sstevel@tonic-gate /* Calculate the two's complement 16 bit checksum of the buffer passed. */ 27807c478bd9Sstevel@tonic-gate /* */ 27817c478bd9Sstevel@tonic-gate /* N.B.: addr should be 16bit aligned. */ 27827c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 27837c478bd9Sstevel@tonic-gate u_short ipf_cksum(addr, len) 27847c478bd9Sstevel@tonic-gate u_short *addr; 27857c478bd9Sstevel@tonic-gate int len; 27867c478bd9Sstevel@tonic-gate { 27877c478bd9Sstevel@tonic-gate u_32_t sum = 0; 27887c478bd9Sstevel@tonic-gate 27897c478bd9Sstevel@tonic-gate for (sum = 0; len > 1; len -= 2) 27907c478bd9Sstevel@tonic-gate sum += *addr++; 27917c478bd9Sstevel@tonic-gate 27927c478bd9Sstevel@tonic-gate /* mop up an odd byte, if necessary */ 27937c478bd9Sstevel@tonic-gate if (len == 1) 27947c478bd9Sstevel@tonic-gate sum += *(u_char *)addr; 27957c478bd9Sstevel@tonic-gate 27967c478bd9Sstevel@tonic-gate /* 27977c478bd9Sstevel@tonic-gate * add back carry outs from top 16 bits to low 16 bits 27987c478bd9Sstevel@tonic-gate */ 27997c478bd9Sstevel@tonic-gate sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */ 28007c478bd9Sstevel@tonic-gate sum += (sum >> 16); /* add carry */ 28017c478bd9Sstevel@tonic-gate return (u_short)(~sum); 28027c478bd9Sstevel@tonic-gate } 28037c478bd9Sstevel@tonic-gate 28047c478bd9Sstevel@tonic-gate 28057c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 28067c478bd9Sstevel@tonic-gate /* Function: fr_cksum */ 28077c478bd9Sstevel@tonic-gate /* Returns: u_short - layer 4 checksum */ 2808ab25eeb5Syz /* Parameters: m(I ) - pointer to buffer holding packet */ 2809ab25eeb5Syz /* ip(I) - pointer to IP header */ 2810ab25eeb5Syz /* l4proto(I) - protocol to caclulate checksum for */ 2811ab25eeb5Syz /* l4hdr(I) - pointer to layer 4 header */ 28127c478bd9Sstevel@tonic-gate /* */ 28137c478bd9Sstevel@tonic-gate /* Calculates the TCP checksum for the packet held in "m", using the data */ 28147c478bd9Sstevel@tonic-gate /* in the IP header "ip" to seed it. */ 28157c478bd9Sstevel@tonic-gate /* */ 28167c478bd9Sstevel@tonic-gate /* NB: This function assumes we've pullup'd enough for all of the IP header */ 28177c478bd9Sstevel@tonic-gate /* and the TCP header. We also assume that data blocks aren't allocated in */ 28187c478bd9Sstevel@tonic-gate /* odd sizes. */ 2819ab25eeb5Syz /* */ 2820ab25eeb5Syz /* Expects ip_len to be in host byte order when called. */ 28217c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 28227c478bd9Sstevel@tonic-gate u_short fr_cksum(m, ip, l4proto, l4hdr) 28237c478bd9Sstevel@tonic-gate mb_t *m; 28247c478bd9Sstevel@tonic-gate ip_t *ip; 28257c478bd9Sstevel@tonic-gate int l4proto; 28267c478bd9Sstevel@tonic-gate void *l4hdr; 28277c478bd9Sstevel@tonic-gate { 28287c478bd9Sstevel@tonic-gate u_short *sp, slen, sumsave, l4hlen, *csump; 28297c478bd9Sstevel@tonic-gate u_int sum, sum2; 28307c478bd9Sstevel@tonic-gate int hlen; 28317c478bd9Sstevel@tonic-gate #ifdef USE_INET6 28327c478bd9Sstevel@tonic-gate ip6_t *ip6; 28337c478bd9Sstevel@tonic-gate #endif 28347c478bd9Sstevel@tonic-gate 28357c478bd9Sstevel@tonic-gate csump = NULL; 28367c478bd9Sstevel@tonic-gate sumsave = 0; 28377c478bd9Sstevel@tonic-gate l4hlen = 0; 28387c478bd9Sstevel@tonic-gate sp = NULL; 28397c478bd9Sstevel@tonic-gate slen = 0; 28407c478bd9Sstevel@tonic-gate hlen = 0; 28417c478bd9Sstevel@tonic-gate sum = 0; 28427c478bd9Sstevel@tonic-gate 28437c478bd9Sstevel@tonic-gate /* 28447c478bd9Sstevel@tonic-gate * Add up IP Header portion 28457c478bd9Sstevel@tonic-gate */ 28467c478bd9Sstevel@tonic-gate #ifdef USE_INET6 28477c478bd9Sstevel@tonic-gate if (IP_V(ip) == 4) { 28487c478bd9Sstevel@tonic-gate #endif 28497c478bd9Sstevel@tonic-gate hlen = IP_HL(ip) << 2; 28507c478bd9Sstevel@tonic-gate slen = ip->ip_len - hlen; 2851ab25eeb5Syz sum = htons((u_short)l4proto); 28527c478bd9Sstevel@tonic-gate sum += htons(slen); 28537c478bd9Sstevel@tonic-gate sp = (u_short *)&ip->ip_src; 28547c478bd9Sstevel@tonic-gate sum += *sp++; /* ip_src */ 28557c478bd9Sstevel@tonic-gate sum += *sp++; 28567c478bd9Sstevel@tonic-gate sum += *sp++; /* ip_dst */ 28577c478bd9Sstevel@tonic-gate sum += *sp++; 28587c478bd9Sstevel@tonic-gate #ifdef USE_INET6 28597c478bd9Sstevel@tonic-gate } else if (IP_V(ip) == 6) { 28607c478bd9Sstevel@tonic-gate ip6 = (ip6_t *)ip; 28617c478bd9Sstevel@tonic-gate hlen = sizeof(*ip6); 28627c478bd9Sstevel@tonic-gate slen = ntohs(ip6->ip6_plen); 2863ab25eeb5Syz sum = htons((u_short)l4proto); 28647c478bd9Sstevel@tonic-gate sum += htons(slen); 28657c478bd9Sstevel@tonic-gate sp = (u_short *)&ip6->ip6_src; 28667c478bd9Sstevel@tonic-gate sum += *sp++; /* ip6_src */ 28677c478bd9Sstevel@tonic-gate sum += *sp++; 28687c478bd9Sstevel@tonic-gate sum += *sp++; 28697c478bd9Sstevel@tonic-gate sum += *sp++; 28707c478bd9Sstevel@tonic-gate sum += *sp++; 28717c478bd9Sstevel@tonic-gate sum += *sp++; 28727c478bd9Sstevel@tonic-gate sum += *sp++; 28737c478bd9Sstevel@tonic-gate sum += *sp++; 28747c478bd9Sstevel@tonic-gate sum += *sp++; /* ip6_dst */ 28757c478bd9Sstevel@tonic-gate sum += *sp++; 28767c478bd9Sstevel@tonic-gate sum += *sp++; 28777c478bd9Sstevel@tonic-gate sum += *sp++; 28787c478bd9Sstevel@tonic-gate sum += *sp++; 28797c478bd9Sstevel@tonic-gate sum += *sp++; 28807c478bd9Sstevel@tonic-gate sum += *sp++; 28817663b816Sml sum += *sp++; 28827c478bd9Sstevel@tonic-gate } 28837c478bd9Sstevel@tonic-gate #endif 28847c478bd9Sstevel@tonic-gate 28857c478bd9Sstevel@tonic-gate switch (l4proto) 28867c478bd9Sstevel@tonic-gate { 28877c478bd9Sstevel@tonic-gate case IPPROTO_UDP : 28887c478bd9Sstevel@tonic-gate csump = &((udphdr_t *)l4hdr)->uh_sum; 28897c478bd9Sstevel@tonic-gate l4hlen = sizeof(udphdr_t); 28907c478bd9Sstevel@tonic-gate break; 28917c478bd9Sstevel@tonic-gate 28927c478bd9Sstevel@tonic-gate case IPPROTO_TCP : 28937c478bd9Sstevel@tonic-gate csump = &((tcphdr_t *)l4hdr)->th_sum; 28947c478bd9Sstevel@tonic-gate l4hlen = sizeof(tcphdr_t); 28957c478bd9Sstevel@tonic-gate break; 28967c478bd9Sstevel@tonic-gate case IPPROTO_ICMP : 28977c478bd9Sstevel@tonic-gate csump = &((icmphdr_t *)l4hdr)->icmp_cksum; 28987c478bd9Sstevel@tonic-gate l4hlen = 4; 2899ab25eeb5Syz sum = 0; 29007c478bd9Sstevel@tonic-gate break; 29017c478bd9Sstevel@tonic-gate default : 29027c478bd9Sstevel@tonic-gate break; 29037c478bd9Sstevel@tonic-gate } 29047c478bd9Sstevel@tonic-gate 29057c478bd9Sstevel@tonic-gate if (csump != NULL) { 29067c478bd9Sstevel@tonic-gate sumsave = *csump; 29077c478bd9Sstevel@tonic-gate *csump = 0; 29087c478bd9Sstevel@tonic-gate } 29097c478bd9Sstevel@tonic-gate 29107c478bd9Sstevel@tonic-gate l4hlen = l4hlen; /* LINT */ 29117c478bd9Sstevel@tonic-gate 29127c478bd9Sstevel@tonic-gate #ifdef _KERNEL 29137c478bd9Sstevel@tonic-gate # ifdef MENTAT 29147c478bd9Sstevel@tonic-gate { 29157c478bd9Sstevel@tonic-gate void *rp = m->b_rptr; 29167c478bd9Sstevel@tonic-gate 29177c478bd9Sstevel@tonic-gate if ((unsigned char *)ip > m->b_rptr && (unsigned char *)ip < m->b_wptr) 29187c478bd9Sstevel@tonic-gate m->b_rptr = (u_char *)ip; 29197c478bd9Sstevel@tonic-gate sum2 = ip_cksum(m, hlen, sum); /* hlen == offset */ 29207c478bd9Sstevel@tonic-gate m->b_rptr = rp; 29217c478bd9Sstevel@tonic-gate sum2 = (sum2 & 0xffff) + (sum2 >> 16); 29227c478bd9Sstevel@tonic-gate sum2 = ~sum2 & 0xffff; 2923ab25eeb5Syz } 29247c478bd9Sstevel@tonic-gate # else /* MENTAT */ 29257c478bd9Sstevel@tonic-gate # if defined(BSD) || defined(sun) 29267c478bd9Sstevel@tonic-gate # if BSD >= 199103 29277c478bd9Sstevel@tonic-gate m->m_data += hlen; 29287c478bd9Sstevel@tonic-gate # else 29297c478bd9Sstevel@tonic-gate m->m_off += hlen; 29307c478bd9Sstevel@tonic-gate # endif 29317c478bd9Sstevel@tonic-gate m->m_len -= hlen; 29327c478bd9Sstevel@tonic-gate sum2 = in_cksum(m, slen); 29337c478bd9Sstevel@tonic-gate m->m_len += hlen; 29347c478bd9Sstevel@tonic-gate # if BSD >= 199103 29357c478bd9Sstevel@tonic-gate m->m_data -= hlen; 29367c478bd9Sstevel@tonic-gate # else 29377c478bd9Sstevel@tonic-gate m->m_off -= hlen; 29387c478bd9Sstevel@tonic-gate # endif 29397c478bd9Sstevel@tonic-gate /* 29407c478bd9Sstevel@tonic-gate * Both sum and sum2 are partial sums, so combine them together. 29417c478bd9Sstevel@tonic-gate */ 29427c478bd9Sstevel@tonic-gate sum += ~sum2 & 0xffff; 29437c478bd9Sstevel@tonic-gate while (sum > 0xffff) 29447c478bd9Sstevel@tonic-gate sum = (sum & 0xffff) + (sum >> 16); 29457c478bd9Sstevel@tonic-gate sum2 = ~sum & 0xffff; 29467c478bd9Sstevel@tonic-gate # else /* defined(BSD) || defined(sun) */ 29477c478bd9Sstevel@tonic-gate { 29487c478bd9Sstevel@tonic-gate union { 29497c478bd9Sstevel@tonic-gate u_char c[2]; 29507c478bd9Sstevel@tonic-gate u_short s; 29517c478bd9Sstevel@tonic-gate } bytes; 29527c478bd9Sstevel@tonic-gate u_short len = ip->ip_len; 29537c478bd9Sstevel@tonic-gate # if defined(__sgi) 29547c478bd9Sstevel@tonic-gate int add; 29557c478bd9Sstevel@tonic-gate # endif 29567c478bd9Sstevel@tonic-gate 29577c478bd9Sstevel@tonic-gate /* 29587c478bd9Sstevel@tonic-gate * Add up IP Header portion 29597c478bd9Sstevel@tonic-gate */ 29607c478bd9Sstevel@tonic-gate if (sp != (u_short *)l4hdr) 29617c478bd9Sstevel@tonic-gate sp = (u_short *)l4hdr; 29627c478bd9Sstevel@tonic-gate 2963ab25eeb5Syz switch (l4proto) 29647c478bd9Sstevel@tonic-gate { 29657c478bd9Sstevel@tonic-gate case IPPROTO_UDP : 29667c478bd9Sstevel@tonic-gate sum += *sp++; /* sport */ 29677c478bd9Sstevel@tonic-gate sum += *sp++; /* dport */ 29687c478bd9Sstevel@tonic-gate sum += *sp++; /* udp length */ 29697c478bd9Sstevel@tonic-gate sum += *sp++; /* checksum */ 29707c478bd9Sstevel@tonic-gate break; 29717c478bd9Sstevel@tonic-gate 29727c478bd9Sstevel@tonic-gate case IPPROTO_TCP : 29737c478bd9Sstevel@tonic-gate sum += *sp++; /* sport */ 29747c478bd9Sstevel@tonic-gate sum += *sp++; /* dport */ 29757c478bd9Sstevel@tonic-gate sum += *sp++; /* seq */ 29767c478bd9Sstevel@tonic-gate sum += *sp++; 29777c478bd9Sstevel@tonic-gate sum += *sp++; /* ack */ 29787c478bd9Sstevel@tonic-gate sum += *sp++; 29797c478bd9Sstevel@tonic-gate sum += *sp++; /* off */ 29807c478bd9Sstevel@tonic-gate sum += *sp++; /* win */ 29817c478bd9Sstevel@tonic-gate sum += *sp++; /* checksum */ 29827c478bd9Sstevel@tonic-gate sum += *sp++; /* urp */ 29837c478bd9Sstevel@tonic-gate break; 2984ab25eeb5Syz case IPPROTO_ICMP : 2985ab25eeb5Syz sum = *sp++; /* type/code */ 2986ab25eeb5Syz sum += *sp++; /* checksum */ 2987ab25eeb5Syz break; 29887c478bd9Sstevel@tonic-gate } 29897c478bd9Sstevel@tonic-gate 29907c478bd9Sstevel@tonic-gate # ifdef __sgi 29917c478bd9Sstevel@tonic-gate /* 29927c478bd9Sstevel@tonic-gate * In case we had to copy the IP & TCP header out of mbufs, 29937c478bd9Sstevel@tonic-gate * skip over the mbuf bits which are the header 29947c478bd9Sstevel@tonic-gate */ 29957c478bd9Sstevel@tonic-gate if ((caddr_t)ip != mtod(m, caddr_t)) { 29967c478bd9Sstevel@tonic-gate hlen = (caddr_t)sp - (caddr_t)ip; 29977c478bd9Sstevel@tonic-gate while (hlen) { 29987c478bd9Sstevel@tonic-gate add = MIN(hlen, m->m_len); 29997c478bd9Sstevel@tonic-gate sp = (u_short *)(mtod(m, caddr_t) + add); 30007c478bd9Sstevel@tonic-gate hlen -= add; 30017c478bd9Sstevel@tonic-gate if (add == m->m_len) { 30027c478bd9Sstevel@tonic-gate m = m->m_next; 30037c478bd9Sstevel@tonic-gate if (!hlen) { 30047c478bd9Sstevel@tonic-gate if (!m) 30057c478bd9Sstevel@tonic-gate break; 30067c478bd9Sstevel@tonic-gate sp = mtod(m, u_short *); 30077c478bd9Sstevel@tonic-gate } 30087c478bd9Sstevel@tonic-gate PANIC((!m),("fr_cksum(1): not enough data")); 30097c478bd9Sstevel@tonic-gate } 30107c478bd9Sstevel@tonic-gate } 30117c478bd9Sstevel@tonic-gate } 30127c478bd9Sstevel@tonic-gate # endif 30137c478bd9Sstevel@tonic-gate 3014ab25eeb5Syz len -= (l4hlen + hlen); 30157c478bd9Sstevel@tonic-gate if (len <= 0) 30167c478bd9Sstevel@tonic-gate goto nodata; 30177c478bd9Sstevel@tonic-gate 30187c478bd9Sstevel@tonic-gate while (len > 1) { 30197c478bd9Sstevel@tonic-gate if (((caddr_t)sp - mtod(m, caddr_t)) >= m->m_len) { 30207c478bd9Sstevel@tonic-gate m = m->m_next; 30217c478bd9Sstevel@tonic-gate PANIC((!m),("fr_cksum(2): not enough data")); 30227c478bd9Sstevel@tonic-gate sp = mtod(m, u_short *); 30237c478bd9Sstevel@tonic-gate } 30247c478bd9Sstevel@tonic-gate if (((caddr_t)(sp + 1) - mtod(m, caddr_t)) > m->m_len) { 30257c478bd9Sstevel@tonic-gate bytes.c[0] = *(u_char *)sp; 30267c478bd9Sstevel@tonic-gate m = m->m_next; 30277c478bd9Sstevel@tonic-gate PANIC((!m),("fr_cksum(3): not enough data")); 30287c478bd9Sstevel@tonic-gate sp = mtod(m, u_short *); 30297c478bd9Sstevel@tonic-gate bytes.c[1] = *(u_char *)sp; 30307c478bd9Sstevel@tonic-gate sum += bytes.s; 30317c478bd9Sstevel@tonic-gate sp = (u_short *)((u_char *)sp + 1); 30327c478bd9Sstevel@tonic-gate } 30337c478bd9Sstevel@tonic-gate if ((u_long)sp & 1) { 30347c478bd9Sstevel@tonic-gate bcopy((char *)sp++, (char *)&bytes.s, sizeof(bytes.s)); 30357c478bd9Sstevel@tonic-gate sum += bytes.s; 30367c478bd9Sstevel@tonic-gate } else 30377c478bd9Sstevel@tonic-gate sum += *sp++; 30387c478bd9Sstevel@tonic-gate len -= 2; 30397c478bd9Sstevel@tonic-gate } 30407c478bd9Sstevel@tonic-gate 30417c478bd9Sstevel@tonic-gate if (len != 0) 30427c478bd9Sstevel@tonic-gate sum += ntohs(*(u_char *)sp << 8); 30437c478bd9Sstevel@tonic-gate nodata: 30447c478bd9Sstevel@tonic-gate while (sum > 0xffff) 30457c478bd9Sstevel@tonic-gate sum = (sum & 0xffff) + (sum >> 16); 30467c478bd9Sstevel@tonic-gate sum2 = (u_short)(~sum & 0xffff); 30477c478bd9Sstevel@tonic-gate } 30487c478bd9Sstevel@tonic-gate # endif /* defined(BSD) || defined(sun) */ 30497c478bd9Sstevel@tonic-gate # endif /* MENTAT */ 30507c478bd9Sstevel@tonic-gate #else /* _KERNEL */ 30517c478bd9Sstevel@tonic-gate for (; slen > 1; slen -= 2) 30527c478bd9Sstevel@tonic-gate sum += *sp++; 30537c478bd9Sstevel@tonic-gate if (slen) 30547c478bd9Sstevel@tonic-gate sum += ntohs(*(u_char *)sp << 8); 30557c478bd9Sstevel@tonic-gate while (sum > 0xffff) 30567c478bd9Sstevel@tonic-gate sum = (sum & 0xffff) + (sum >> 16); 30577c478bd9Sstevel@tonic-gate sum2 = (u_short)(~sum & 0xffff); 30587c478bd9Sstevel@tonic-gate #endif /* _KERNEL */ 30597c478bd9Sstevel@tonic-gate if (csump != NULL) 30607c478bd9Sstevel@tonic-gate *csump = sumsave; 30617c478bd9Sstevel@tonic-gate return sum2; 30627c478bd9Sstevel@tonic-gate } 30637c478bd9Sstevel@tonic-gate 30647c478bd9Sstevel@tonic-gate 30657c478bd9Sstevel@tonic-gate #if defined(_KERNEL) && ( ((BSD < 199103) && !defined(MENTAT)) || \ 3066ab25eeb5Syz defined(__sgi) ) && !defined(linux) && !defined(_AIX51) 30677c478bd9Sstevel@tonic-gate /* 30687c478bd9Sstevel@tonic-gate * Copyright (c) 1982, 1986, 1988, 1991, 1993 30697c478bd9Sstevel@tonic-gate * The Regents of the University of California. All rights reserved. 30707c478bd9Sstevel@tonic-gate * 30717c478bd9Sstevel@tonic-gate * Redistribution and use in source and binary forms, with or without 30727c478bd9Sstevel@tonic-gate * modification, are permitted provided that the following conditions 30737c478bd9Sstevel@tonic-gate * are met: 30747c478bd9Sstevel@tonic-gate * 1. Redistributions of source code must retain the above copyright 30757c478bd9Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer. 30767c478bd9Sstevel@tonic-gate * 2. Redistributions in binary form must reproduce the above copyright 30777c478bd9Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer in the 30787c478bd9Sstevel@tonic-gate * documentation and/or other materials provided with the distribution. 30797c478bd9Sstevel@tonic-gate * 3. Neither the name of the University nor the names of its contributors 30807c478bd9Sstevel@tonic-gate * may be used to endorse or promote products derived from this software 30817c478bd9Sstevel@tonic-gate * without specific prior written permission. 30827c478bd9Sstevel@tonic-gate * 30837c478bd9Sstevel@tonic-gate * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 30847c478bd9Sstevel@tonic-gate * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 30857c478bd9Sstevel@tonic-gate * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 30867c478bd9Sstevel@tonic-gate * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 30877c478bd9Sstevel@tonic-gate * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 30887c478bd9Sstevel@tonic-gate * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30897c478bd9Sstevel@tonic-gate * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30907c478bd9Sstevel@tonic-gate * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30917c478bd9Sstevel@tonic-gate * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30927c478bd9Sstevel@tonic-gate * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30937c478bd9Sstevel@tonic-gate * SUCH DAMAGE. 30947c478bd9Sstevel@tonic-gate * 30957c478bd9Sstevel@tonic-gate * @(#)uipc_mbuf.c 8.2 (Berkeley) 1/4/94 3096ab25eeb5Syz * $Id: fil.c,v 2.243.2.64 2005/08/13 05:19:59 darrenr Exp $ 30977c478bd9Sstevel@tonic-gate */ 30987c478bd9Sstevel@tonic-gate /* 30997c478bd9Sstevel@tonic-gate * Copy data from an mbuf chain starting "off" bytes from the beginning, 31007c478bd9Sstevel@tonic-gate * continuing for "len" bytes, into the indicated buffer. 31017c478bd9Sstevel@tonic-gate */ 31027c478bd9Sstevel@tonic-gate void 31037c478bd9Sstevel@tonic-gate m_copydata(m, off, len, cp) 31047c478bd9Sstevel@tonic-gate mb_t *m; 31057c478bd9Sstevel@tonic-gate int off; 31067c478bd9Sstevel@tonic-gate int len; 31077c478bd9Sstevel@tonic-gate caddr_t cp; 31087c478bd9Sstevel@tonic-gate { 31097c478bd9Sstevel@tonic-gate unsigned count; 31107c478bd9Sstevel@tonic-gate 31117c478bd9Sstevel@tonic-gate if (off < 0 || len < 0) 31127c478bd9Sstevel@tonic-gate panic("m_copydata"); 31137c478bd9Sstevel@tonic-gate while (off > 0) { 31147c478bd9Sstevel@tonic-gate if (m == 0) 31157c478bd9Sstevel@tonic-gate panic("m_copydata"); 31167c478bd9Sstevel@tonic-gate if (off < m->m_len) 31177c478bd9Sstevel@tonic-gate break; 31187c478bd9Sstevel@tonic-gate off -= m->m_len; 31197c478bd9Sstevel@tonic-gate m = m->m_next; 31207c478bd9Sstevel@tonic-gate } 31217c478bd9Sstevel@tonic-gate while (len > 0) { 31227c478bd9Sstevel@tonic-gate if (m == 0) 31237c478bd9Sstevel@tonic-gate panic("m_copydata"); 31247c478bd9Sstevel@tonic-gate count = MIN(m->m_len - off, len); 31257c478bd9Sstevel@tonic-gate bcopy(mtod(m, caddr_t) + off, cp, count); 31267c478bd9Sstevel@tonic-gate len -= count; 31277c478bd9Sstevel@tonic-gate cp += count; 31287c478bd9Sstevel@tonic-gate off = 0; 31297c478bd9Sstevel@tonic-gate m = m->m_next; 31307c478bd9Sstevel@tonic-gate } 31317c478bd9Sstevel@tonic-gate } 31327c478bd9Sstevel@tonic-gate 31337c478bd9Sstevel@tonic-gate 31347c478bd9Sstevel@tonic-gate /* 31357c478bd9Sstevel@tonic-gate * Copy data from a buffer back into the indicated mbuf chain, 31367c478bd9Sstevel@tonic-gate * starting "off" bytes from the beginning, extending the mbuf 31377c478bd9Sstevel@tonic-gate * chain if necessary. 31387c478bd9Sstevel@tonic-gate */ 31397c478bd9Sstevel@tonic-gate void 31407c478bd9Sstevel@tonic-gate m_copyback(m0, off, len, cp) 31417c478bd9Sstevel@tonic-gate struct mbuf *m0; 31427c478bd9Sstevel@tonic-gate int off; 31437c478bd9Sstevel@tonic-gate int len; 31447c478bd9Sstevel@tonic-gate caddr_t cp; 31457c478bd9Sstevel@tonic-gate { 31467c478bd9Sstevel@tonic-gate int mlen; 31477c478bd9Sstevel@tonic-gate struct mbuf *m = m0, *n; 31487c478bd9Sstevel@tonic-gate int totlen = 0; 31497c478bd9Sstevel@tonic-gate 31507c478bd9Sstevel@tonic-gate if (m0 == 0) 31517c478bd9Sstevel@tonic-gate return; 31527c478bd9Sstevel@tonic-gate while (off > (mlen = m->m_len)) { 31537c478bd9Sstevel@tonic-gate off -= mlen; 31547c478bd9Sstevel@tonic-gate totlen += mlen; 31557c478bd9Sstevel@tonic-gate if (m->m_next == 0) { 31567c478bd9Sstevel@tonic-gate n = m_getclr(M_DONTWAIT, m->m_type); 31577c478bd9Sstevel@tonic-gate if (n == 0) 31587c478bd9Sstevel@tonic-gate goto out; 31597c478bd9Sstevel@tonic-gate n->m_len = min(MLEN, len + off); 31607c478bd9Sstevel@tonic-gate m->m_next = n; 31617c478bd9Sstevel@tonic-gate } 31627c478bd9Sstevel@tonic-gate m = m->m_next; 31637c478bd9Sstevel@tonic-gate } 31647c478bd9Sstevel@tonic-gate while (len > 0) { 3165ab25eeb5Syz mlen = min(m->m_len - off, len); 31667c478bd9Sstevel@tonic-gate bcopy(cp, off + mtod(m, caddr_t), (unsigned)mlen); 31677c478bd9Sstevel@tonic-gate cp += mlen; 31687c478bd9Sstevel@tonic-gate len -= mlen; 31697c478bd9Sstevel@tonic-gate mlen += off; 31707c478bd9Sstevel@tonic-gate off = 0; 31717c478bd9Sstevel@tonic-gate totlen += mlen; 31727c478bd9Sstevel@tonic-gate if (len == 0) 31737c478bd9Sstevel@tonic-gate break; 31747c478bd9Sstevel@tonic-gate if (m->m_next == 0) { 31757c478bd9Sstevel@tonic-gate n = m_get(M_DONTWAIT, m->m_type); 31767c478bd9Sstevel@tonic-gate if (n == 0) 31777c478bd9Sstevel@tonic-gate break; 31787c478bd9Sstevel@tonic-gate n->m_len = min(MLEN, len); 31797c478bd9Sstevel@tonic-gate m->m_next = n; 31807c478bd9Sstevel@tonic-gate } 31817c478bd9Sstevel@tonic-gate m = m->m_next; 31827c478bd9Sstevel@tonic-gate } 31837c478bd9Sstevel@tonic-gate out: 31847c478bd9Sstevel@tonic-gate #if 0 31857c478bd9Sstevel@tonic-gate if (((m = m0)->m_flags & M_PKTHDR) && (m->m_pkthdr.len < totlen)) 31867c478bd9Sstevel@tonic-gate m->m_pkthdr.len = totlen; 31877c478bd9Sstevel@tonic-gate #endif 31887c478bd9Sstevel@tonic-gate return; 31897c478bd9Sstevel@tonic-gate } 31907c478bd9Sstevel@tonic-gate #endif /* (_KERNEL) && ( ((BSD < 199103) && !MENTAT) || __sgi) */ 31917c478bd9Sstevel@tonic-gate 31927c478bd9Sstevel@tonic-gate 31937c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 31947c478bd9Sstevel@tonic-gate /* Function: fr_findgroup */ 31957c478bd9Sstevel@tonic-gate /* Returns: frgroup_t * - NULL = group not found, else pointer to group */ 31967c478bd9Sstevel@tonic-gate /* Parameters: group(I) - group name to search for */ 31977c478bd9Sstevel@tonic-gate /* unit(I) - device to which this group belongs */ 31987c478bd9Sstevel@tonic-gate /* set(I) - which set of rules (inactive/inactive) this is */ 31997c478bd9Sstevel@tonic-gate /* fgpp(O) - pointer to place to store pointer to the pointer */ 32007c478bd9Sstevel@tonic-gate /* to where to add the next (last) group or where */ 32017c478bd9Sstevel@tonic-gate /* to delete group from. */ 32027c478bd9Sstevel@tonic-gate /* */ 32037c478bd9Sstevel@tonic-gate /* Search amongst the defined groups for a particular group number. */ 32047c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 32057c478bd9Sstevel@tonic-gate frgroup_t *fr_findgroup(group, unit, set, fgpp) 32067c478bd9Sstevel@tonic-gate char *group; 32077c478bd9Sstevel@tonic-gate minor_t unit; 32087c478bd9Sstevel@tonic-gate int set; 32097c478bd9Sstevel@tonic-gate frgroup_t ***fgpp; 32107c478bd9Sstevel@tonic-gate { 32117c478bd9Sstevel@tonic-gate frgroup_t *fg, **fgp; 32127c478bd9Sstevel@tonic-gate 32137c478bd9Sstevel@tonic-gate /* 3214ab25eeb5Syz * Which list of groups to search in is dependent on which list of 32157c478bd9Sstevel@tonic-gate * rules are being operated on. 32167c478bd9Sstevel@tonic-gate */ 32177c478bd9Sstevel@tonic-gate fgp = &ipfgroups[unit][set]; 32187c478bd9Sstevel@tonic-gate 32197c478bd9Sstevel@tonic-gate while ((fg = *fgp) != NULL) { 32207c478bd9Sstevel@tonic-gate if (strncmp(group, fg->fg_name, FR_GROUPLEN) == 0) 32217c478bd9Sstevel@tonic-gate break; 32227c478bd9Sstevel@tonic-gate else 32237c478bd9Sstevel@tonic-gate fgp = &fg->fg_next; 32247c478bd9Sstevel@tonic-gate } 32257c478bd9Sstevel@tonic-gate if (fgpp != NULL) 32267c478bd9Sstevel@tonic-gate *fgpp = fgp; 32277c478bd9Sstevel@tonic-gate return fg; 32287c478bd9Sstevel@tonic-gate } 32297c478bd9Sstevel@tonic-gate 32307c478bd9Sstevel@tonic-gate 32317c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 32327c478bd9Sstevel@tonic-gate /* Function: fr_addgroup */ 32337c478bd9Sstevel@tonic-gate /* Returns: frgroup_t * - NULL == did not create group, */ 32347c478bd9Sstevel@tonic-gate /* != NULL == pointer to the group */ 32357c478bd9Sstevel@tonic-gate /* Parameters: num(I) - group number to add */ 32367c478bd9Sstevel@tonic-gate /* head(I) - rule pointer that is using this as the head */ 32377c478bd9Sstevel@tonic-gate /* flags(I) - rule flags which describe the type of rule it is */ 32387c478bd9Sstevel@tonic-gate /* unit(I) - device to which this group will belong to */ 32397c478bd9Sstevel@tonic-gate /* set(I) - which set of rules (inactive/inactive) this is */ 32407c478bd9Sstevel@tonic-gate /* Write Locks: ipf_mutex */ 32417c478bd9Sstevel@tonic-gate /* */ 32427c478bd9Sstevel@tonic-gate /* Add a new group head, or if it already exists, increase the reference */ 32437c478bd9Sstevel@tonic-gate /* count to it. */ 32447c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 32457c478bd9Sstevel@tonic-gate frgroup_t *fr_addgroup(group, head, flags, unit, set) 32467c478bd9Sstevel@tonic-gate char *group; 32477c478bd9Sstevel@tonic-gate void *head; 32487c478bd9Sstevel@tonic-gate u_32_t flags; 32497c478bd9Sstevel@tonic-gate minor_t unit; 32507c478bd9Sstevel@tonic-gate int set; 32517c478bd9Sstevel@tonic-gate { 32527c478bd9Sstevel@tonic-gate frgroup_t *fg, **fgp; 32537c478bd9Sstevel@tonic-gate u_32_t gflags; 32547c478bd9Sstevel@tonic-gate 32557c478bd9Sstevel@tonic-gate if (group == NULL) 32567c478bd9Sstevel@tonic-gate return NULL; 32577c478bd9Sstevel@tonic-gate 32587c478bd9Sstevel@tonic-gate if (unit == IPL_LOGIPF && *group == '\0') 32597c478bd9Sstevel@tonic-gate return NULL; 32607c478bd9Sstevel@tonic-gate 32617c478bd9Sstevel@tonic-gate fgp = NULL; 32627c478bd9Sstevel@tonic-gate gflags = flags & FR_INOUT; 32637c478bd9Sstevel@tonic-gate 32647c478bd9Sstevel@tonic-gate fg = fr_findgroup(group, unit, set, &fgp); 32657c478bd9Sstevel@tonic-gate if (fg != NULL) { 32667c478bd9Sstevel@tonic-gate if (fg->fg_flags == 0) 32677c478bd9Sstevel@tonic-gate fg->fg_flags = gflags; 32687c478bd9Sstevel@tonic-gate else if (gflags != fg->fg_flags) 32697c478bd9Sstevel@tonic-gate return NULL; 32707c478bd9Sstevel@tonic-gate fg->fg_ref++; 32717c478bd9Sstevel@tonic-gate return fg; 32727c478bd9Sstevel@tonic-gate } 32737c478bd9Sstevel@tonic-gate KMALLOC(fg, frgroup_t *); 32747c478bd9Sstevel@tonic-gate if (fg != NULL) { 32757c478bd9Sstevel@tonic-gate fg->fg_head = head; 32767c478bd9Sstevel@tonic-gate fg->fg_start = NULL; 32777c478bd9Sstevel@tonic-gate fg->fg_next = *fgp; 32787c478bd9Sstevel@tonic-gate bcopy(group, fg->fg_name, FR_GROUPLEN); 32797c478bd9Sstevel@tonic-gate fg->fg_flags = gflags; 32807c478bd9Sstevel@tonic-gate fg->fg_ref = 1; 32817c478bd9Sstevel@tonic-gate *fgp = fg; 32827c478bd9Sstevel@tonic-gate } 32837c478bd9Sstevel@tonic-gate return fg; 32847c478bd9Sstevel@tonic-gate } 32857c478bd9Sstevel@tonic-gate 32867c478bd9Sstevel@tonic-gate 32877c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 32887c478bd9Sstevel@tonic-gate /* Function: fr_delgroup */ 32897c478bd9Sstevel@tonic-gate /* Returns: Nil */ 32907c478bd9Sstevel@tonic-gate /* Parameters: group(I) - group name to delete */ 32917c478bd9Sstevel@tonic-gate /* unit(I) - device to which this group belongs */ 32927c478bd9Sstevel@tonic-gate /* set(I) - which set of rules (inactive/inactive) this is */ 32937c478bd9Sstevel@tonic-gate /* Write Locks: ipf_mutex */ 32947c478bd9Sstevel@tonic-gate /* */ 32957c478bd9Sstevel@tonic-gate /* Attempt to delete a group head. */ 32967c478bd9Sstevel@tonic-gate /* Only do this when its reference count reaches 0. */ 32977c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 32987c478bd9Sstevel@tonic-gate void fr_delgroup(group, unit, set) 32997c478bd9Sstevel@tonic-gate char *group; 33007c478bd9Sstevel@tonic-gate minor_t unit; 33017c478bd9Sstevel@tonic-gate int set; 33027c478bd9Sstevel@tonic-gate { 33037c478bd9Sstevel@tonic-gate frgroup_t *fg, **fgp; 3304ab25eeb5Syz 33057c478bd9Sstevel@tonic-gate fg = fr_findgroup(group, unit, set, &fgp); 33067c478bd9Sstevel@tonic-gate if (fg == NULL) 33077c478bd9Sstevel@tonic-gate return; 3308ab25eeb5Syz 33097c478bd9Sstevel@tonic-gate fg->fg_ref--; 33107c478bd9Sstevel@tonic-gate if (fg->fg_ref == 0) { 33117c478bd9Sstevel@tonic-gate *fgp = fg->fg_next; 33127c478bd9Sstevel@tonic-gate KFREE(fg); 33137c478bd9Sstevel@tonic-gate } 33147c478bd9Sstevel@tonic-gate } 33157c478bd9Sstevel@tonic-gate 33167c478bd9Sstevel@tonic-gate 33177c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 33187c478bd9Sstevel@tonic-gate /* Function: fr_getrulen */ 33197c478bd9Sstevel@tonic-gate /* Returns: frentry_t * - NULL == not found, else pointer to rule n */ 33207c478bd9Sstevel@tonic-gate /* Parameters: unit(I) - device for which to count the rule's number */ 33217c478bd9Sstevel@tonic-gate /* flags(I) - which set of rules to find the rule in */ 33227c478bd9Sstevel@tonic-gate /* group(I) - group name */ 33237c478bd9Sstevel@tonic-gate /* n(I) - rule number to find */ 33247c478bd9Sstevel@tonic-gate /* */ 33257c478bd9Sstevel@tonic-gate /* Find rule # n in group # g and return a pointer to it. Return NULl if */ 33267c478bd9Sstevel@tonic-gate /* group # g doesn't exist or there are less than n rules in the group. */ 33277c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 33287c478bd9Sstevel@tonic-gate frentry_t *fr_getrulen(unit, group, n) 33297c478bd9Sstevel@tonic-gate int unit; 33307c478bd9Sstevel@tonic-gate char *group; 33317c478bd9Sstevel@tonic-gate u_32_t n; 33327c478bd9Sstevel@tonic-gate { 33337c478bd9Sstevel@tonic-gate frentry_t *fr; 33347c478bd9Sstevel@tonic-gate frgroup_t *fg; 33357c478bd9Sstevel@tonic-gate 33367c478bd9Sstevel@tonic-gate fg = fr_findgroup(group, unit, fr_active, NULL); 33377c478bd9Sstevel@tonic-gate if (fg == NULL) 33387c478bd9Sstevel@tonic-gate return NULL; 33397c478bd9Sstevel@tonic-gate for (fr = fg->fg_head; fr && n; fr = fr->fr_next, n--) 33407c478bd9Sstevel@tonic-gate ; 33417c478bd9Sstevel@tonic-gate if (n != 0) 33427c478bd9Sstevel@tonic-gate return NULL; 33437c478bd9Sstevel@tonic-gate return fr; 33447c478bd9Sstevel@tonic-gate } 33457c478bd9Sstevel@tonic-gate 33467c478bd9Sstevel@tonic-gate 33477c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 33487c478bd9Sstevel@tonic-gate /* Function: fr_rulen */ 33497c478bd9Sstevel@tonic-gate /* Returns: int - >= 0 - rule number, -1 == search failed */ 33507c478bd9Sstevel@tonic-gate /* Parameters: unit(I) - device for which to count the rule's number */ 33517c478bd9Sstevel@tonic-gate /* fr(I) - pointer to rule to match */ 33527c478bd9Sstevel@tonic-gate /* */ 33537c478bd9Sstevel@tonic-gate /* Return the number for a rule on a specific filtering device. */ 33547c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 33557c478bd9Sstevel@tonic-gate int fr_rulen(unit, fr) 33567c478bd9Sstevel@tonic-gate int unit; 33577c478bd9Sstevel@tonic-gate frentry_t *fr; 33587c478bd9Sstevel@tonic-gate { 33597c478bd9Sstevel@tonic-gate frentry_t *fh; 33607c478bd9Sstevel@tonic-gate frgroup_t *fg; 33617c478bd9Sstevel@tonic-gate u_32_t n = 0; 33627c478bd9Sstevel@tonic-gate 33637c478bd9Sstevel@tonic-gate if (fr == NULL) 33647c478bd9Sstevel@tonic-gate return -1; 33657c478bd9Sstevel@tonic-gate fg = fr_findgroup(fr->fr_group, unit, fr_active, NULL); 33667c478bd9Sstevel@tonic-gate if (fg == NULL) 33677c478bd9Sstevel@tonic-gate return -1; 33687c478bd9Sstevel@tonic-gate for (fh = fg->fg_head; fh; n++, fh = fh->fr_next) 33697c478bd9Sstevel@tonic-gate if (fh == fr) 33707c478bd9Sstevel@tonic-gate break; 33717c478bd9Sstevel@tonic-gate if (fh == NULL) 33727c478bd9Sstevel@tonic-gate return -1; 33737c478bd9Sstevel@tonic-gate return n; 33747c478bd9Sstevel@tonic-gate } 33757c478bd9Sstevel@tonic-gate 33767c478bd9Sstevel@tonic-gate 33777c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 33787c478bd9Sstevel@tonic-gate /* Function: frflushlist */ 33797c478bd9Sstevel@tonic-gate /* Returns: int - >= 0 - number of flushed rules */ 33807c478bd9Sstevel@tonic-gate /* Parameters: set(I) - which set of rules (inactive/inactive) this is */ 33817c478bd9Sstevel@tonic-gate /* unit(I) - device for which to flush rules */ 33827c478bd9Sstevel@tonic-gate /* flags(I) - which set of rules to flush */ 33837c478bd9Sstevel@tonic-gate /* nfreedp(O) - pointer to int where flush count is stored */ 33847c478bd9Sstevel@tonic-gate /* listp(I) - pointer to list to flush pointer */ 33857c478bd9Sstevel@tonic-gate /* Write Locks: ipf_mutex */ 33867c478bd9Sstevel@tonic-gate /* */ 33877c478bd9Sstevel@tonic-gate /* Recursively flush rules from the list, descending groups as they are */ 33887c478bd9Sstevel@tonic-gate /* encountered. if a rule is the head of a group and it has lost all its */ 33897c478bd9Sstevel@tonic-gate /* group members, then also delete the group reference. nfreedp is needed */ 33907c478bd9Sstevel@tonic-gate /* to store the accumulating count of rules removed, whereas the returned */ 33917c478bd9Sstevel@tonic-gate /* value is just the number removed from the current list. The latter is */ 33927c478bd9Sstevel@tonic-gate /* needed to correctly adjust reference counts on rules that define groups. */ 33937c478bd9Sstevel@tonic-gate /* */ 33947c478bd9Sstevel@tonic-gate /* NOTE: Rules not loaded from user space cannot be flushed. */ 33957c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 33967c478bd9Sstevel@tonic-gate static int frflushlist(set, unit, nfreedp, listp) 33977c478bd9Sstevel@tonic-gate int set; 33987c478bd9Sstevel@tonic-gate minor_t unit; 33997c478bd9Sstevel@tonic-gate int *nfreedp; 34007c478bd9Sstevel@tonic-gate frentry_t **listp; 34017c478bd9Sstevel@tonic-gate { 34027c478bd9Sstevel@tonic-gate int freed = 0, i; 34037c478bd9Sstevel@tonic-gate frentry_t *fp; 34047c478bd9Sstevel@tonic-gate 34057c478bd9Sstevel@tonic-gate while ((fp = *listp) != NULL) { 34067c478bd9Sstevel@tonic-gate if ((fp->fr_type & FR_T_BUILTIN) || 34077c478bd9Sstevel@tonic-gate !(fp->fr_flags & FR_COPIED)) { 34087c478bd9Sstevel@tonic-gate listp = &fp->fr_next; 34097c478bd9Sstevel@tonic-gate continue; 34107c478bd9Sstevel@tonic-gate } 34117c478bd9Sstevel@tonic-gate *listp = fp->fr_next; 34127c478bd9Sstevel@tonic-gate if (fp->fr_grp != NULL) { 34137c478bd9Sstevel@tonic-gate i = frflushlist(set, unit, nfreedp, fp->fr_grp); 34147c478bd9Sstevel@tonic-gate fp->fr_ref -= i; 34157c478bd9Sstevel@tonic-gate } 34167c478bd9Sstevel@tonic-gate 34177c478bd9Sstevel@tonic-gate if (fp->fr_grhead != NULL) { 34187c478bd9Sstevel@tonic-gate fr_delgroup(fp->fr_grhead, unit, set); 34197c478bd9Sstevel@tonic-gate *fp->fr_grhead = '\0'; 34207c478bd9Sstevel@tonic-gate } 34217c478bd9Sstevel@tonic-gate 34227c478bd9Sstevel@tonic-gate ASSERT(fp->fr_ref > 0); 34237c478bd9Sstevel@tonic-gate fp->fr_next = NULL; 34247c478bd9Sstevel@tonic-gate if (fr_derefrule(&fp) == 0) 34257c478bd9Sstevel@tonic-gate freed++; 34267c478bd9Sstevel@tonic-gate } 34277c478bd9Sstevel@tonic-gate *nfreedp += freed; 34287c478bd9Sstevel@tonic-gate return freed; 34297c478bd9Sstevel@tonic-gate } 34307c478bd9Sstevel@tonic-gate 34317c478bd9Sstevel@tonic-gate 34327c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 34337c478bd9Sstevel@tonic-gate /* Function: frflush */ 34347c478bd9Sstevel@tonic-gate /* Returns: int - >= 0 - number of flushed rules */ 34357c478bd9Sstevel@tonic-gate /* Parameters: unit(I) - device for which to flush rules */ 34367c478bd9Sstevel@tonic-gate /* flags(I) - which set of rules to flush */ 34377c478bd9Sstevel@tonic-gate /* */ 34387c478bd9Sstevel@tonic-gate /* Calls flushlist() for all filter rules (accounting, firewall - both IPv4 */ 34397c478bd9Sstevel@tonic-gate /* and IPv6) as defined by the value of flags. */ 34407c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 34417663b816Sml int frflush(unit, proto, flags) 34427c478bd9Sstevel@tonic-gate minor_t unit; 34437663b816Sml int proto, flags; 34447c478bd9Sstevel@tonic-gate { 34457c478bd9Sstevel@tonic-gate int flushed = 0, set; 34467c478bd9Sstevel@tonic-gate 34477c478bd9Sstevel@tonic-gate WRITE_ENTER(&ipf_mutex); 34487c478bd9Sstevel@tonic-gate bzero((char *)frcache, sizeof(frcache)); 34497c478bd9Sstevel@tonic-gate 34507c478bd9Sstevel@tonic-gate set = fr_active; 34517c478bd9Sstevel@tonic-gate if ((flags & FR_INACTIVE) == FR_INACTIVE) 34527c478bd9Sstevel@tonic-gate set = 1 - set; 34537c478bd9Sstevel@tonic-gate 34547c478bd9Sstevel@tonic-gate if (flags & FR_OUTQUE) { 34557663b816Sml if (proto == 0 || proto == 6) { 34567663b816Sml (void) frflushlist(set, unit, 34577663b816Sml &flushed, &ipfilter6[1][set]); 34587663b816Sml (void) frflushlist(set, unit, 34597663b816Sml &flushed, &ipacct6[1][set]); 34607663b816Sml } 34617663b816Sml if (proto == 0 || proto == 4) { 34627663b816Sml (void) frflushlist(set, unit, 34637663b816Sml &flushed, &ipfilter[1][set]); 34647663b816Sml (void) frflushlist(set, unit, 34657663b816Sml &flushed, &ipacct[1][set]); 34667663b816Sml } 34677c478bd9Sstevel@tonic-gate } 34687c478bd9Sstevel@tonic-gate if (flags & FR_INQUE) { 34697663b816Sml if (proto == 0 || proto == 6) { 34707663b816Sml (void) frflushlist(set, unit, 34717663b816Sml &flushed, &ipfilter6[0][set]); 34727663b816Sml (void) frflushlist(set, unit, 34737663b816Sml &flushed, &ipacct6[0][set]); 34747663b816Sml } 34757663b816Sml if (proto == 0 || proto == 4) { 34767663b816Sml (void) frflushlist(set, unit, 34777663b816Sml &flushed, &ipfilter[0][set]); 34787663b816Sml (void) frflushlist(set, unit, 34797663b816Sml &flushed, &ipacct[0][set]); 34807663b816Sml } 34817c478bd9Sstevel@tonic-gate } 34827c478bd9Sstevel@tonic-gate RWLOCK_EXIT(&ipf_mutex); 34837663b816Sml 34847663b816Sml if (unit == IPL_LOGIPF) { 34857663b816Sml int tmp; 34867663b816Sml 34877663b816Sml tmp = frflush(IPL_LOGCOUNT, proto, flags); 34887663b816Sml if (tmp >= 0) 34897663b816Sml flushed += tmp; 34907663b816Sml } 34917c478bd9Sstevel@tonic-gate return flushed; 34927c478bd9Sstevel@tonic-gate } 34937c478bd9Sstevel@tonic-gate 34947c478bd9Sstevel@tonic-gate 34957c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 34967c478bd9Sstevel@tonic-gate /* Function: memstr */ 34977c478bd9Sstevel@tonic-gate /* Returns: char * - NULL if failed, != NULL pointer to matching bytes */ 34987c478bd9Sstevel@tonic-gate /* Parameters: src(I) - pointer to byte sequence to match */ 34997c478bd9Sstevel@tonic-gate /* dst(I) - pointer to byte sequence to search */ 35007c478bd9Sstevel@tonic-gate /* slen(I) - match length */ 35017c478bd9Sstevel@tonic-gate /* dlen(I) - length available to search in */ 35027c478bd9Sstevel@tonic-gate /* */ 35037c478bd9Sstevel@tonic-gate /* Search dst for a sequence of bytes matching those at src and extend for */ 35047c478bd9Sstevel@tonic-gate /* slen bytes. */ 35057c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 35067c478bd9Sstevel@tonic-gate char *memstr(src, dst, slen, dlen) 35077c478bd9Sstevel@tonic-gate char *src, *dst; 35087c478bd9Sstevel@tonic-gate int slen, dlen; 35097c478bd9Sstevel@tonic-gate { 35107c478bd9Sstevel@tonic-gate char *s = NULL; 35117c478bd9Sstevel@tonic-gate 35127c478bd9Sstevel@tonic-gate while (dlen >= slen) { 35137c478bd9Sstevel@tonic-gate if (bcmp(src, dst, slen) == 0) { 35147c478bd9Sstevel@tonic-gate s = dst; 35157c478bd9Sstevel@tonic-gate break; 35167c478bd9Sstevel@tonic-gate } 35177c478bd9Sstevel@tonic-gate dst++; 35187c478bd9Sstevel@tonic-gate dlen--; 35197c478bd9Sstevel@tonic-gate } 35207c478bd9Sstevel@tonic-gate return s; 35217c478bd9Sstevel@tonic-gate } 35227c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 35237c478bd9Sstevel@tonic-gate /* Function: fr_fixskip */ 35247c478bd9Sstevel@tonic-gate /* Returns: Nil */ 35257c478bd9Sstevel@tonic-gate /* Parameters: listp(IO) - pointer to start of list with skip rule */ 35267c478bd9Sstevel@tonic-gate /* rp(I) - rule added/removed with skip in it. */ 35277c478bd9Sstevel@tonic-gate /* addremove(I) - adjustment (-1/+1) to make to skip count, */ 35287c478bd9Sstevel@tonic-gate /* depending on whether a rule was just added */ 35297c478bd9Sstevel@tonic-gate /* or removed. */ 35307c478bd9Sstevel@tonic-gate /* */ 35317c478bd9Sstevel@tonic-gate /* Adjust all the rules in a list which would have skip'd past the position */ 35327c478bd9Sstevel@tonic-gate /* where we are inserting to skip to the right place given the change. */ 35337c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 35347c478bd9Sstevel@tonic-gate void fr_fixskip(listp, rp, addremove) 35357c478bd9Sstevel@tonic-gate frentry_t **listp, *rp; 35367c478bd9Sstevel@tonic-gate int addremove; 35377c478bd9Sstevel@tonic-gate { 35387c478bd9Sstevel@tonic-gate int rules, rn; 35397c478bd9Sstevel@tonic-gate frentry_t *fp; 35407c478bd9Sstevel@tonic-gate 35417c478bd9Sstevel@tonic-gate rules = 0; 35427c478bd9Sstevel@tonic-gate for (fp = *listp; (fp != NULL) && (fp != rp); fp = fp->fr_next) 35437c478bd9Sstevel@tonic-gate rules++; 35447c478bd9Sstevel@tonic-gate 35457c478bd9Sstevel@tonic-gate if (!fp) 35467c478bd9Sstevel@tonic-gate return; 35477c478bd9Sstevel@tonic-gate 35487c478bd9Sstevel@tonic-gate for (rn = 0, fp = *listp; fp && (fp != rp); fp = fp->fr_next, rn++) 35497c478bd9Sstevel@tonic-gate if (FR_ISSKIP(fp->fr_flags) && (rn + fp->fr_arg >= rules)) 35507c478bd9Sstevel@tonic-gate fp->fr_arg += addremove; 35517c478bd9Sstevel@tonic-gate } 35527c478bd9Sstevel@tonic-gate 35537c478bd9Sstevel@tonic-gate 35547c478bd9Sstevel@tonic-gate #ifdef _KERNEL 35557c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 35567c478bd9Sstevel@tonic-gate /* Function: count4bits */ 35577c478bd9Sstevel@tonic-gate /* Returns: int - >= 0 - number of consecutive bits in input */ 35587c478bd9Sstevel@tonic-gate /* Parameters: ip(I) - 32bit IP address */ 35597c478bd9Sstevel@tonic-gate /* */ 35607c478bd9Sstevel@tonic-gate /* IPv4 ONLY */ 35617c478bd9Sstevel@tonic-gate /* count consecutive 1's in bit mask. If the mask generated by counting */ 35627c478bd9Sstevel@tonic-gate /* consecutive 1's is different to that passed, return -1, else return # */ 35637c478bd9Sstevel@tonic-gate /* of bits. */ 35647c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 35657c478bd9Sstevel@tonic-gate int count4bits(ip) 35667c478bd9Sstevel@tonic-gate u_32_t ip; 35677c478bd9Sstevel@tonic-gate { 35687c478bd9Sstevel@tonic-gate u_32_t ipn; 35697c478bd9Sstevel@tonic-gate int cnt = 0, i, j; 35707c478bd9Sstevel@tonic-gate 35717c478bd9Sstevel@tonic-gate ip = ipn = ntohl(ip); 35727c478bd9Sstevel@tonic-gate for (i = 32; i; i--, ipn *= 2) 35737c478bd9Sstevel@tonic-gate if (ipn & 0x80000000) 35747c478bd9Sstevel@tonic-gate cnt++; 35757c478bd9Sstevel@tonic-gate else 35767c478bd9Sstevel@tonic-gate break; 35777c478bd9Sstevel@tonic-gate ipn = 0; 35787c478bd9Sstevel@tonic-gate for (i = 32, j = cnt; i; i--, j--) { 35797c478bd9Sstevel@tonic-gate ipn *= 2; 35807c478bd9Sstevel@tonic-gate if (j > 0) 35817c478bd9Sstevel@tonic-gate ipn++; 35827c478bd9Sstevel@tonic-gate } 35837c478bd9Sstevel@tonic-gate if (ipn == ip) 35847c478bd9Sstevel@tonic-gate return cnt; 35857c478bd9Sstevel@tonic-gate return -1; 35867c478bd9Sstevel@tonic-gate } 35877c478bd9Sstevel@tonic-gate 3588ab25eeb5Syz 35897663b816Sml #ifdef USE_INET6 35907c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 35917c478bd9Sstevel@tonic-gate /* Function: count6bits */ 35927c478bd9Sstevel@tonic-gate /* Returns: int - >= 0 - number of consecutive bits in input */ 35937c478bd9Sstevel@tonic-gate /* Parameters: msk(I) - pointer to start of IPv6 bitmask */ 35947c478bd9Sstevel@tonic-gate /* */ 35957c478bd9Sstevel@tonic-gate /* IPv6 ONLY */ 35967c478bd9Sstevel@tonic-gate /* count consecutive 1's in bit mask. */ 35977c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 35987c478bd9Sstevel@tonic-gate int count6bits(msk) 35997c478bd9Sstevel@tonic-gate u_32_t *msk; 36007c478bd9Sstevel@tonic-gate { 36017c478bd9Sstevel@tonic-gate int i = 0, k; 36027c478bd9Sstevel@tonic-gate u_32_t j; 36037c478bd9Sstevel@tonic-gate 36047c478bd9Sstevel@tonic-gate for (k = 3; k >= 0; k--) 36057c478bd9Sstevel@tonic-gate if (msk[k] == 0xffffffff) 36067c478bd9Sstevel@tonic-gate i += 32; 36077c478bd9Sstevel@tonic-gate else { 36087c478bd9Sstevel@tonic-gate for (j = msk[k]; j; j <<= 1) 36097c478bd9Sstevel@tonic-gate if (j & 0x80000000) 36107c478bd9Sstevel@tonic-gate i++; 36117c478bd9Sstevel@tonic-gate } 36127c478bd9Sstevel@tonic-gate return i; 36137c478bd9Sstevel@tonic-gate } 3614ab25eeb5Syz # endif 36157c478bd9Sstevel@tonic-gate #endif /* _KERNEL */ 36167c478bd9Sstevel@tonic-gate 36177c478bd9Sstevel@tonic-gate 3618*381a2a9aSdr /* ------------------------------------------------------------------------ */ 3619*381a2a9aSdr /* Function: fr_ifsync */ 3620*381a2a9aSdr /* Returns: void * - new interface identifier */ 3621*381a2a9aSdr /* Parameters: action(I) - type of synchronisation to do */ 3622*381a2a9aSdr /* v(I) - IP version being sync'd (v4 or v6) */ 3623*381a2a9aSdr /* newifp(I) - interface identifier being introduced/removed */ 3624*381a2a9aSdr /* oldifp(I) - interface identifier in a filter rule */ 3625*381a2a9aSdr /* newname(I) - name associated with oldifp interface */ 3626*381a2a9aSdr /* oldname(I) - name associated with newifp interface */ 3627*381a2a9aSdr /* */ 3628*381a2a9aSdr /* This function returns what the new value for "oldifp" should be for its */ 3629*381a2a9aSdr /* caller. In some cases it will not change, in some it will. */ 3630*381a2a9aSdr /* action == IPFSYNC_RESYNC */ 3631*381a2a9aSdr /* a new value for oldifp will always be looked up, according to oldname, */ 3632*381a2a9aSdr /* the values of newname and newifp are ignored. */ 3633*381a2a9aSdr /* action == IPFSYNC_NEWIFP */ 3634*381a2a9aSdr /* if oldname matches newname then we are doing a sync for the matching */ 3635*381a2a9aSdr /* interface, so we return newifp to be used in place of oldifp. If the */ 3636*381a2a9aSdr /* the names don't match, just return oldifp. */ 3637*381a2a9aSdr /* action == IPFSYNC_OLDIFP */ 3638*381a2a9aSdr /* if oldifp matches newifp then we are are doing a sync to remove any */ 3639*381a2a9aSdr /* references to oldifp, so we return "-1". */ 3640*381a2a9aSdr /* ------------------------------------------------------------------------ */ 3641*381a2a9aSdr static void *fr_ifsync(action, v, newname, oldname, newifp, oldifp) 3642*381a2a9aSdr int action, v; 3643*381a2a9aSdr char *newname, *oldname; 3644*381a2a9aSdr void *newifp, *oldifp; 3645*381a2a9aSdr { 3646*381a2a9aSdr void *rval = oldifp; 3647*381a2a9aSdr 3648*381a2a9aSdr switch (action) 3649*381a2a9aSdr { 3650*381a2a9aSdr case IPFSYNC_RESYNC : 3651*381a2a9aSdr if (oldname[0] != '\0') { 3652*381a2a9aSdr rval = fr_resolvenic(oldname, v); 3653*381a2a9aSdr } 3654*381a2a9aSdr break; 3655*381a2a9aSdr case IPFSYNC_NEWIFP : 3656*381a2a9aSdr if (!strncmp(newname, oldname, LIFNAMSIZ)) 3657*381a2a9aSdr rval = newifp; 3658*381a2a9aSdr break; 3659*381a2a9aSdr case IPFSYNC_OLDIFP : 3660*381a2a9aSdr if (newifp == oldifp) 3661*381a2a9aSdr rval = (void *)-1; 3662*381a2a9aSdr break; 3663*381a2a9aSdr } 3664*381a2a9aSdr 3665*381a2a9aSdr return rval; 3666*381a2a9aSdr } 3667*381a2a9aSdr 3668*381a2a9aSdr 36697c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 36707c478bd9Sstevel@tonic-gate /* Function: frsynclist */ 36717c478bd9Sstevel@tonic-gate /* Returns: void */ 3672*381a2a9aSdr /* Parameters: action(I) - type of synchronisation to do */ 3673*381a2a9aSdr /* v(I) - IP version being sync'd (v4 or v6) */ 3674*381a2a9aSdr /* ifp(I) - interface identifier associated with action */ 3675*381a2a9aSdr /* name(I) - name associated with ifp parameter */ 36767c478bd9Sstevel@tonic-gate /* Write Locks: ipf_mutex */ 36777c478bd9Sstevel@tonic-gate /* */ 36787c478bd9Sstevel@tonic-gate /* Walk through a list of filter rules and resolve any interface names into */ 36797c478bd9Sstevel@tonic-gate /* pointers. Where dynamic addresses are used, also update the IP address */ 3680ab25eeb5Syz /* used in the rule. The interface pointer is used to limit the lookups to */ 3681ab25eeb5Syz /* a specific set of matching names if it is non-NULL. */ 36827c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 3683*381a2a9aSdr static void frsynclist(action, v, ifp, ifname, fr) 3684*381a2a9aSdr int action, v; 3685ab25eeb5Syz void *ifp; 3686*381a2a9aSdr char *ifname; 3687*381a2a9aSdr frentry_t *fr; 36887c478bd9Sstevel@tonic-gate { 36897c478bd9Sstevel@tonic-gate frdest_t *fdp; 3690*381a2a9aSdr int rv, i; 36917c478bd9Sstevel@tonic-gate 36927c478bd9Sstevel@tonic-gate for (; fr; fr = fr->fr_next) { 3693*381a2a9aSdr rv = fr->fr_v; 3694*381a2a9aSdr if (v != 0 && v != rv) 3695*381a2a9aSdr continue; 36967c478bd9Sstevel@tonic-gate 36977c478bd9Sstevel@tonic-gate /* 36987c478bd9Sstevel@tonic-gate * Lookup all the interface names that are part of the rule. 36997c478bd9Sstevel@tonic-gate */ 37007c478bd9Sstevel@tonic-gate for (i = 0; i < 4; i++) { 3701ab25eeb5Syz if ((ifp != NULL) && (fr->fr_ifas[i] != ifp)) 3702ab25eeb5Syz continue; 3703*381a2a9aSdr fr->fr_ifas[i] = fr_ifsync(action, rv, ifname, 3704*381a2a9aSdr fr->fr_ifnames[i], 3705*381a2a9aSdr ifp, fr->fr_ifas[i]); 37067c478bd9Sstevel@tonic-gate } 37077c478bd9Sstevel@tonic-gate 3708*381a2a9aSdr fdp = &fr->fr_tifs[0]; 3709*381a2a9aSdr fdp->fd_ifp = fr_ifsync(action, rv, ifname, fdp->fd_ifname, 3710*381a2a9aSdr ifp, fdp->fd_ifp); 3711*381a2a9aSdr 3712*381a2a9aSdr fdp = &fr->fr_tifs[1]; 3713*381a2a9aSdr fdp->fd_ifp = fr_ifsync(action, rv, ifname, fdp->fd_ifname, 3714*381a2a9aSdr ifp, fdp->fd_ifp); 3715*381a2a9aSdr 3716*381a2a9aSdr fdp = &fr->fr_dif; 3717*381a2a9aSdr fdp->fd_ifp = fr_ifsync(action, rv, ifname, fdp->fd_ifname, 3718*381a2a9aSdr ifp, fdp->fd_ifp); 3719*381a2a9aSdr 3720*381a2a9aSdr if (action != IPFSYNC_RESYNC) 3721*381a2a9aSdr return; 3722*381a2a9aSdr 37237c478bd9Sstevel@tonic-gate if (fr->fr_type == FR_T_IPF) { 37247c478bd9Sstevel@tonic-gate if (fr->fr_satype != FRI_NORMAL && 37257c478bd9Sstevel@tonic-gate fr->fr_satype != FRI_LOOKUP) { 3726*381a2a9aSdr (void)fr_ifpaddr(rv, fr->fr_satype, 37277c478bd9Sstevel@tonic-gate fr->fr_ifas[fr->fr_sifpidx], 37287c478bd9Sstevel@tonic-gate &fr->fr_src, &fr->fr_smsk); 37297c478bd9Sstevel@tonic-gate } 37307c478bd9Sstevel@tonic-gate if (fr->fr_datype != FRI_NORMAL && 37317c478bd9Sstevel@tonic-gate fr->fr_datype != FRI_LOOKUP) { 3732*381a2a9aSdr (void)fr_ifpaddr(rv, fr->fr_datype, 37337c478bd9Sstevel@tonic-gate fr->fr_ifas[fr->fr_difpidx], 37347c478bd9Sstevel@tonic-gate &fr->fr_dst, &fr->fr_dmsk); 37357c478bd9Sstevel@tonic-gate } 37367c478bd9Sstevel@tonic-gate } 37377c478bd9Sstevel@tonic-gate 37387c478bd9Sstevel@tonic-gate #ifdef IPFILTER_LOOKUP 37397c478bd9Sstevel@tonic-gate if (fr->fr_type == FR_T_IPF && fr->fr_satype == FRI_LOOKUP && 37407c478bd9Sstevel@tonic-gate fr->fr_srcptr == NULL) { 37417c478bd9Sstevel@tonic-gate fr->fr_srcptr = fr_resolvelookup(fr->fr_srctype, 37427c478bd9Sstevel@tonic-gate fr->fr_srcnum, 37437c478bd9Sstevel@tonic-gate &fr->fr_srcfunc); 37447c478bd9Sstevel@tonic-gate } 37457c478bd9Sstevel@tonic-gate if (fr->fr_type == FR_T_IPF && fr->fr_datype == FRI_LOOKUP && 37467c478bd9Sstevel@tonic-gate fr->fr_dstptr == NULL) { 37477c478bd9Sstevel@tonic-gate fr->fr_dstptr = fr_resolvelookup(fr->fr_dsttype, 37487c478bd9Sstevel@tonic-gate fr->fr_dstnum, 37497c478bd9Sstevel@tonic-gate &fr->fr_dstfunc); 37507c478bd9Sstevel@tonic-gate } 37517c478bd9Sstevel@tonic-gate #endif 37527c478bd9Sstevel@tonic-gate } 37537c478bd9Sstevel@tonic-gate } 37547c478bd9Sstevel@tonic-gate 37557c478bd9Sstevel@tonic-gate 37567c478bd9Sstevel@tonic-gate #ifdef _KERNEL 37577c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 37587c478bd9Sstevel@tonic-gate /* Function: frsync */ 37597c478bd9Sstevel@tonic-gate /* Returns: void */ 3760*381a2a9aSdr /* Parameters: action(I) - type of synchronisation to do */ 3761*381a2a9aSdr /* v(I) - IP version being sync'd (v4 or v6) */ 3762*381a2a9aSdr /* ifp(I) - interface identifier associated with action */ 3763*381a2a9aSdr /* name(I) - name associated with ifp parameter */ 37647c478bd9Sstevel@tonic-gate /* */ 37657c478bd9Sstevel@tonic-gate /* frsync() is called when we suspect that the interface list or */ 37667c478bd9Sstevel@tonic-gate /* information about interfaces (like IP#) has changed. Go through all */ 37677c478bd9Sstevel@tonic-gate /* filter rules, NAT entries and the state table and check if anything */ 37687c478bd9Sstevel@tonic-gate /* needs to be changed/updated. */ 3769*381a2a9aSdr /* With the filtering hooks added to Solaris, we needed to change the manner*/ 3770*381a2a9aSdr /* in which this was done to support three different types of sync: */ 3771*381a2a9aSdr /* - complete resync of all interface name/identifiers */ 3772*381a2a9aSdr /* - new interface being announced with its name and identifier */ 3773*381a2a9aSdr /* - interface removal being announced by only its identifier */ 3774*381a2a9aSdr /* ------------------------------------------------------------------------ */ 3775*381a2a9aSdr void frsync(action, v, ifp, name) 3776*381a2a9aSdr int action, v; 3777ab25eeb5Syz void *ifp; 3778*381a2a9aSdr char *name; 37797c478bd9Sstevel@tonic-gate { 37807c478bd9Sstevel@tonic-gate int i; 3781ab25eeb5Syz 37827c478bd9Sstevel@tonic-gate WRITE_ENTER(&ipf_mutex); 3783*381a2a9aSdr frsynclist(action, v, ifp, name, ipacct[0][fr_active]); 3784*381a2a9aSdr frsynclist(action, v, ifp, name, ipacct[1][fr_active]); 3785*381a2a9aSdr frsynclist(action, v, ifp, name, ipfilter[0][fr_active]); 3786*381a2a9aSdr frsynclist(action, v, ifp, name, ipfilter[1][fr_active]); 3787*381a2a9aSdr frsynclist(action, v, ifp, name, ipacct6[0][fr_active]); 3788*381a2a9aSdr frsynclist(action, v, ifp, name, ipacct6[1][fr_active]); 3789*381a2a9aSdr frsynclist(action, v, ifp, name, ipfilter6[0][fr_active]); 3790*381a2a9aSdr frsynclist(action, v, ifp, name, ipfilter6[1][fr_active]); 37917c478bd9Sstevel@tonic-gate 37927c478bd9Sstevel@tonic-gate for (i = 0; i < IPL_LOGSIZE; i++) { 37937c478bd9Sstevel@tonic-gate frgroup_t *g; 37947c478bd9Sstevel@tonic-gate 37957c478bd9Sstevel@tonic-gate for (g = ipfgroups[i][0]; g != NULL; g = g->fg_next) 3796*381a2a9aSdr frsynclist(action, v, ifp, name, g->fg_start); 37977c478bd9Sstevel@tonic-gate for (g = ipfgroups[i][1]; g != NULL; g = g->fg_next) 3798*381a2a9aSdr frsynclist(action, v, ifp, name, g->fg_start); 37997c478bd9Sstevel@tonic-gate } 38007c478bd9Sstevel@tonic-gate RWLOCK_EXIT(&ipf_mutex); 38017c478bd9Sstevel@tonic-gate } 38027c478bd9Sstevel@tonic-gate 38037c478bd9Sstevel@tonic-gate 38047c478bd9Sstevel@tonic-gate /* 38057c478bd9Sstevel@tonic-gate * In the functions below, bcopy() is called because the pointer being 38067c478bd9Sstevel@tonic-gate * copied _from_ in this instance is a pointer to a char buf (which could 38077c478bd9Sstevel@tonic-gate * end up being unaligned) and on the kernel's local stack. 38087c478bd9Sstevel@tonic-gate */ 38097c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 38107c478bd9Sstevel@tonic-gate /* Function: copyinptr */ 38117c478bd9Sstevel@tonic-gate /* Returns: int - 0 = success, else failure */ 38127c478bd9Sstevel@tonic-gate /* Parameters: src(I) - pointer to the source address */ 38137c478bd9Sstevel@tonic-gate /* dst(I) - destination address */ 38147c478bd9Sstevel@tonic-gate /* size(I) - number of bytes to copy */ 38157c478bd9Sstevel@tonic-gate /* */ 38167c478bd9Sstevel@tonic-gate /* Copy a block of data in from user space, given a pointer to the pointer */ 38177c478bd9Sstevel@tonic-gate /* to start copying from (src) and a pointer to where to store it (dst). */ 38187c478bd9Sstevel@tonic-gate /* NB: src - pointer to user space pointer, dst - kernel space pointer */ 38197c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 38207c478bd9Sstevel@tonic-gate int copyinptr(src, dst, size) 38217c478bd9Sstevel@tonic-gate void *src, *dst; 38227c478bd9Sstevel@tonic-gate size_t size; 38237c478bd9Sstevel@tonic-gate { 38247c478bd9Sstevel@tonic-gate caddr_t ca; 38257c478bd9Sstevel@tonic-gate int err; 38267c478bd9Sstevel@tonic-gate 3827ab25eeb5Syz # if SOLARIS 3828ab25eeb5Syz err = COPYIN(src, (caddr_t)&ca, sizeof(ca)); 38297c478bd9Sstevel@tonic-gate if (err != 0) 38307c478bd9Sstevel@tonic-gate return err; 3831ab25eeb5Syz # else 38327c478bd9Sstevel@tonic-gate bcopy(src, (caddr_t)&ca, sizeof(ca)); 3833ab25eeb5Syz # endif 3834ab25eeb5Syz err = COPYIN(ca, dst, size); 38357c478bd9Sstevel@tonic-gate return err; 38367c478bd9Sstevel@tonic-gate } 38377c478bd9Sstevel@tonic-gate 38387c478bd9Sstevel@tonic-gate 38397c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 38407c478bd9Sstevel@tonic-gate /* Function: copyoutptr */ 38417c478bd9Sstevel@tonic-gate /* Returns: int - 0 = success, else failure */ 38427c478bd9Sstevel@tonic-gate /* Parameters: src(I) - pointer to the source address */ 38437c478bd9Sstevel@tonic-gate /* dst(I) - destination address */ 38447c478bd9Sstevel@tonic-gate /* size(I) - number of bytes to copy */ 38457c478bd9Sstevel@tonic-gate /* */ 38467c478bd9Sstevel@tonic-gate /* Copy a block of data out to user space, given a pointer to the pointer */ 38477c478bd9Sstevel@tonic-gate /* to start copying from (src) and a pointer to where to store it (dst). */ 38487c478bd9Sstevel@tonic-gate /* NB: src - kernel space pointer, dst - pointer to user space pointer. */ 38497c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 38507c478bd9Sstevel@tonic-gate int copyoutptr(src, dst, size) 38517c478bd9Sstevel@tonic-gate void *src, *dst; 38527c478bd9Sstevel@tonic-gate size_t size; 38537c478bd9Sstevel@tonic-gate { 38547c478bd9Sstevel@tonic-gate caddr_t ca; 38557c478bd9Sstevel@tonic-gate int err; 38567c478bd9Sstevel@tonic-gate 3857ab25eeb5Syz # if SOLARIS 3858ab25eeb5Syz err = COPYIN(dst, (caddr_t)&ca, sizeof(ca)); 38597c478bd9Sstevel@tonic-gate if (err != 0) 38607c478bd9Sstevel@tonic-gate return err; 3861ab25eeb5Syz # else 38627c478bd9Sstevel@tonic-gate bcopy(dst, (caddr_t)&ca, sizeof(ca)); 3863ab25eeb5Syz # endif 3864ab25eeb5Syz err = COPYOUT(src, ca, size); 38657c478bd9Sstevel@tonic-gate return err; 38667c478bd9Sstevel@tonic-gate } 3867ab25eeb5Syz #endif 38687c478bd9Sstevel@tonic-gate 38697c478bd9Sstevel@tonic-gate 3870ab25eeb5Syz /* ------------------------------------------------------------------------ */ 3871ab25eeb5Syz /* Function: fr_lock */ 3872ab25eeb5Syz /* Returns: (void) */ 3873ab25eeb5Syz /* Parameters: data(I) - pointer to lock value to set */ 3874ab25eeb5Syz /* lockp(O) - pointer to location to store old lock value */ 3875ab25eeb5Syz /* */ 3876ab25eeb5Syz /* Get the new value for the lock integer, set it and return the old value */ 3877ab25eeb5Syz /* in *lockp. */ 3878ab25eeb5Syz /* ------------------------------------------------------------------------ */ 3879ab25eeb5Syz void fr_lock(data, lockp) 3880ab25eeb5Syz caddr_t data; 3881ab25eeb5Syz int *lockp; 38827c478bd9Sstevel@tonic-gate { 3883ab25eeb5Syz int arg; 38847c478bd9Sstevel@tonic-gate 3885ab25eeb5Syz BCOPYIN(data, (caddr_t)&arg, sizeof(arg)); 3886ab25eeb5Syz BCOPYOUT((caddr_t)lockp, data, sizeof(*lockp)); 3887ab25eeb5Syz *lockp = arg; 38887c478bd9Sstevel@tonic-gate } 38897c478bd9Sstevel@tonic-gate 38907c478bd9Sstevel@tonic-gate 38917c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 38927c478bd9Sstevel@tonic-gate /* Function: fr_getstat */ 38937c478bd9Sstevel@tonic-gate /* Returns: Nil */ 38947c478bd9Sstevel@tonic-gate /* Parameters: fiop(I) - pointer to ipfilter stats structure */ 38957c478bd9Sstevel@tonic-gate /* */ 38967c478bd9Sstevel@tonic-gate /* Stores a copy of current pointers, counters, etc, in the friostat */ 38977c478bd9Sstevel@tonic-gate /* structure. */ 38987c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 38997c478bd9Sstevel@tonic-gate void fr_getstat(fiop) 39007c478bd9Sstevel@tonic-gate friostat_t *fiop; 39017c478bd9Sstevel@tonic-gate { 39027c478bd9Sstevel@tonic-gate int i, j; 39037c478bd9Sstevel@tonic-gate 39047c478bd9Sstevel@tonic-gate bcopy((char *)frstats, (char *)fiop->f_st, sizeof(filterstats_t) * 2); 39057c478bd9Sstevel@tonic-gate fiop->f_locks[IPL_LOGSTATE] = fr_state_lock; 39067c478bd9Sstevel@tonic-gate fiop->f_locks[IPL_LOGNAT] = fr_nat_lock; 39077c478bd9Sstevel@tonic-gate fiop->f_locks[IPL_LOGIPF] = fr_frag_lock; 39087c478bd9Sstevel@tonic-gate fiop->f_locks[IPL_LOGAUTH] = fr_auth_lock; 39097c478bd9Sstevel@tonic-gate 39107c478bd9Sstevel@tonic-gate for (i = 0; i < 2; i++) 39117c478bd9Sstevel@tonic-gate for (j = 0; j < 2; j++) { 39127c478bd9Sstevel@tonic-gate fiop->f_ipf[i][j] = ipfilter[i][j]; 39137c478bd9Sstevel@tonic-gate fiop->f_acct[i][j] = ipacct[i][j]; 39147c478bd9Sstevel@tonic-gate fiop->f_ipf6[i][j] = ipfilter6[i][j]; 39157c478bd9Sstevel@tonic-gate fiop->f_acct6[i][j] = ipacct6[i][j]; 39167c478bd9Sstevel@tonic-gate } 39177c478bd9Sstevel@tonic-gate 39187c478bd9Sstevel@tonic-gate fiop->f_ticks = fr_ticks; 39197c478bd9Sstevel@tonic-gate fiop->f_active = fr_active; 39207c478bd9Sstevel@tonic-gate fiop->f_froute[0] = fr_frouteok[0]; 39217c478bd9Sstevel@tonic-gate fiop->f_froute[1] = fr_frouteok[1]; 39227c478bd9Sstevel@tonic-gate 39237c478bd9Sstevel@tonic-gate fiop->f_running = fr_running; 39247c478bd9Sstevel@tonic-gate for (i = 0; i < IPL_LOGSIZE; i++) { 39257c478bd9Sstevel@tonic-gate fiop->f_groups[i][0] = ipfgroups[i][0]; 39267c478bd9Sstevel@tonic-gate fiop->f_groups[i][1] = ipfgroups[i][1]; 39277c478bd9Sstevel@tonic-gate } 39287c478bd9Sstevel@tonic-gate #ifdef IPFILTER_LOG 39297c478bd9Sstevel@tonic-gate fiop->f_logging = 1; 39307c478bd9Sstevel@tonic-gate #else 39317c478bd9Sstevel@tonic-gate fiop->f_logging = 0; 39327c478bd9Sstevel@tonic-gate #endif 39337c478bd9Sstevel@tonic-gate fiop->f_defpass = fr_pass; 3934ab25eeb5Syz fiop->f_features = fr_features; 3935ab25eeb5Syz (void) strncpy(fiop->f_version, ipfilter_version, 3936ab25eeb5Syz sizeof(fiop->f_version)); 39377c478bd9Sstevel@tonic-gate } 39387c478bd9Sstevel@tonic-gate 39397c478bd9Sstevel@tonic-gate 39407c478bd9Sstevel@tonic-gate #ifdef USE_INET6 39417c478bd9Sstevel@tonic-gate int icmptoicmp6types[ICMP_MAXTYPE+1] = { 39427c478bd9Sstevel@tonic-gate ICMP6_ECHO_REPLY, /* 0: ICMP_ECHOREPLY */ 39437c478bd9Sstevel@tonic-gate -1, /* 1: UNUSED */ 39447c478bd9Sstevel@tonic-gate -1, /* 2: UNUSED */ 39457c478bd9Sstevel@tonic-gate ICMP6_DST_UNREACH, /* 3: ICMP_UNREACH */ 39467c478bd9Sstevel@tonic-gate -1, /* 4: ICMP_SOURCEQUENCH */ 39477c478bd9Sstevel@tonic-gate ND_REDIRECT, /* 5: ICMP_REDIRECT */ 39487c478bd9Sstevel@tonic-gate -1, /* 6: UNUSED */ 39497c478bd9Sstevel@tonic-gate -1, /* 7: UNUSED */ 39507c478bd9Sstevel@tonic-gate ICMP6_ECHO_REQUEST, /* 8: ICMP_ECHO */ 39517c478bd9Sstevel@tonic-gate -1, /* 9: UNUSED */ 39527c478bd9Sstevel@tonic-gate -1, /* 10: UNUSED */ 39537c478bd9Sstevel@tonic-gate ICMP6_TIME_EXCEEDED, /* 11: ICMP_TIMXCEED */ 39547c478bd9Sstevel@tonic-gate ICMP6_PARAM_PROB, /* 12: ICMP_PARAMPROB */ 39557c478bd9Sstevel@tonic-gate -1, /* 13: ICMP_TSTAMP */ 39567c478bd9Sstevel@tonic-gate -1, /* 14: ICMP_TSTAMPREPLY */ 39577c478bd9Sstevel@tonic-gate -1, /* 15: ICMP_IREQ */ 39587c478bd9Sstevel@tonic-gate -1, /* 16: ICMP_IREQREPLY */ 39597c478bd9Sstevel@tonic-gate -1, /* 17: ICMP_MASKREQ */ 39607c478bd9Sstevel@tonic-gate -1, /* 18: ICMP_MASKREPLY */ 39617c478bd9Sstevel@tonic-gate }; 39627c478bd9Sstevel@tonic-gate 39637c478bd9Sstevel@tonic-gate 39647c478bd9Sstevel@tonic-gate int icmptoicmp6unreach[ICMP_MAX_UNREACH] = { 39657c478bd9Sstevel@tonic-gate ICMP6_DST_UNREACH_ADDR, /* 0: ICMP_UNREACH_NET */ 39667c478bd9Sstevel@tonic-gate ICMP6_DST_UNREACH_ADDR, /* 1: ICMP_UNREACH_HOST */ 39677c478bd9Sstevel@tonic-gate -1, /* 2: ICMP_UNREACH_PROTOCOL */ 39687c478bd9Sstevel@tonic-gate ICMP6_DST_UNREACH_NOPORT, /* 3: ICMP_UNREACH_PORT */ 39697c478bd9Sstevel@tonic-gate -1, /* 4: ICMP_UNREACH_NEEDFRAG */ 39707c478bd9Sstevel@tonic-gate ICMP6_DST_UNREACH_NOTNEIGHBOR, /* 5: ICMP_UNREACH_SRCFAIL */ 39717c478bd9Sstevel@tonic-gate ICMP6_DST_UNREACH_ADDR, /* 6: ICMP_UNREACH_NET_UNKNOWN */ 39727c478bd9Sstevel@tonic-gate ICMP6_DST_UNREACH_ADDR, /* 7: ICMP_UNREACH_HOST_UNKNOWN */ 39737c478bd9Sstevel@tonic-gate -1, /* 8: ICMP_UNREACH_ISOLATED */ 39747c478bd9Sstevel@tonic-gate ICMP6_DST_UNREACH_ADMIN, /* 9: ICMP_UNREACH_NET_PROHIB */ 39757c478bd9Sstevel@tonic-gate ICMP6_DST_UNREACH_ADMIN, /* 10: ICMP_UNREACH_HOST_PROHIB */ 39767c478bd9Sstevel@tonic-gate -1, /* 11: ICMP_UNREACH_TOSNET */ 39777c478bd9Sstevel@tonic-gate -1, /* 12: ICMP_UNREACH_TOSHOST */ 39787c478bd9Sstevel@tonic-gate ICMP6_DST_UNREACH_ADMIN, /* 13: ICMP_UNREACH_ADMIN_PROHIBIT */ 39797c478bd9Sstevel@tonic-gate }; 39807c478bd9Sstevel@tonic-gate int icmpreplytype6[ICMP6_MAXTYPE + 1]; 39817c478bd9Sstevel@tonic-gate #endif 39827c478bd9Sstevel@tonic-gate 39837c478bd9Sstevel@tonic-gate int icmpreplytype4[ICMP_MAXTYPE + 1]; 39847c478bd9Sstevel@tonic-gate 39857c478bd9Sstevel@tonic-gate 39867c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 39877c478bd9Sstevel@tonic-gate /* Function: fr_matchicmpqueryreply */ 39887c478bd9Sstevel@tonic-gate /* Returns: int - 1 if "icmp" is a valid reply to "ic" else 0. */ 39897c478bd9Sstevel@tonic-gate /* Parameters: v(I) - IP protocol version (4 or 6) */ 39907c478bd9Sstevel@tonic-gate /* ic(I) - ICMP information */ 39917c478bd9Sstevel@tonic-gate /* icmp(I) - ICMP packet header */ 39927c478bd9Sstevel@tonic-gate /* rev(I) - direction (0 = forward/1 = reverse) of packet */ 39937c478bd9Sstevel@tonic-gate /* */ 39947c478bd9Sstevel@tonic-gate /* Check if the ICMP packet defined by the header pointed to by icmp is a */ 39957c478bd9Sstevel@tonic-gate /* reply to one as described by what's in ic. If it is a match, return 1, */ 39967c478bd9Sstevel@tonic-gate /* else return 0 for no match. */ 39977c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 39987c478bd9Sstevel@tonic-gate int fr_matchicmpqueryreply(v, ic, icmp, rev) 39997c478bd9Sstevel@tonic-gate int v; 40007c478bd9Sstevel@tonic-gate icmpinfo_t *ic; 40017c478bd9Sstevel@tonic-gate icmphdr_t *icmp; 40027c478bd9Sstevel@tonic-gate int rev; 40037c478bd9Sstevel@tonic-gate { 40047c478bd9Sstevel@tonic-gate int ictype; 40057c478bd9Sstevel@tonic-gate 40067c478bd9Sstevel@tonic-gate ictype = ic->ici_type; 40077c478bd9Sstevel@tonic-gate 40087c478bd9Sstevel@tonic-gate if (v == 4) { 40097c478bd9Sstevel@tonic-gate /* 40107c478bd9Sstevel@tonic-gate * If we matched its type on the way in, then when going out 40117c478bd9Sstevel@tonic-gate * it will still be the same type. 40127c478bd9Sstevel@tonic-gate */ 40137c478bd9Sstevel@tonic-gate if ((!rev && (icmp->icmp_type == ictype)) || 40147c478bd9Sstevel@tonic-gate (rev && (icmpreplytype4[ictype] == icmp->icmp_type))) { 40157c478bd9Sstevel@tonic-gate if (icmp->icmp_type != ICMP_ECHOREPLY) 40167c478bd9Sstevel@tonic-gate return 1; 4017ab25eeb5Syz if (icmp->icmp_id == ic->ici_id) 40187c478bd9Sstevel@tonic-gate return 1; 40197c478bd9Sstevel@tonic-gate } 40207c478bd9Sstevel@tonic-gate } 40217c478bd9Sstevel@tonic-gate #ifdef USE_INET6 40227c478bd9Sstevel@tonic-gate else if (v == 6) { 40237c478bd9Sstevel@tonic-gate if ((!rev && (icmp->icmp_type == ictype)) || 40247c478bd9Sstevel@tonic-gate (rev && (icmpreplytype6[ictype] == icmp->icmp_type))) { 40257c478bd9Sstevel@tonic-gate if (icmp->icmp_type != ICMP6_ECHO_REPLY) 40267c478bd9Sstevel@tonic-gate return 1; 4027ab25eeb5Syz if (icmp->icmp_id == ic->ici_id) 40287c478bd9Sstevel@tonic-gate return 1; 40297c478bd9Sstevel@tonic-gate } 40307c478bd9Sstevel@tonic-gate } 40317c478bd9Sstevel@tonic-gate #endif 40327c478bd9Sstevel@tonic-gate return 0; 40337c478bd9Sstevel@tonic-gate } 40347c478bd9Sstevel@tonic-gate 40357c478bd9Sstevel@tonic-gate 40367c478bd9Sstevel@tonic-gate #ifdef IPFILTER_LOOKUP 40377c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 40387c478bd9Sstevel@tonic-gate /* Function: fr_resolvelookup */ 40397c478bd9Sstevel@tonic-gate /* Returns: void * - NULL = failure, else success. */ 40407c478bd9Sstevel@tonic-gate /* Parameters: type(I) - type of lookup these parameters are for. */ 40417c478bd9Sstevel@tonic-gate /* number(I) - table number to use when searching */ 40427c478bd9Sstevel@tonic-gate /* funcptr(IO) - pointer to pointer for storing IP address */ 40437c478bd9Sstevel@tonic-gate /* searching function. */ 40447c478bd9Sstevel@tonic-gate /* */ 40457c478bd9Sstevel@tonic-gate /* Search for the "table" number passed in amongst those configured for */ 40467c478bd9Sstevel@tonic-gate /* that particular type. If the type is recognised then the function to */ 40477c478bd9Sstevel@tonic-gate /* call to do the IP address search will be change, regardless of whether */ 40487c478bd9Sstevel@tonic-gate /* or not the "table" number exists. */ 40497c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 40507c478bd9Sstevel@tonic-gate static void *fr_resolvelookup(type, number, funcptr) 40517c478bd9Sstevel@tonic-gate u_int type, number; 40527c478bd9Sstevel@tonic-gate lookupfunc_t *funcptr; 40537c478bd9Sstevel@tonic-gate { 40547c478bd9Sstevel@tonic-gate char name[FR_GROUPLEN]; 40557c478bd9Sstevel@tonic-gate iphtable_t *iph; 40567c478bd9Sstevel@tonic-gate ip_pool_t *ipo; 40577c478bd9Sstevel@tonic-gate void *ptr; 40587c478bd9Sstevel@tonic-gate 4059ab25eeb5Syz #if defined(SNPRINTF) && defined(_KERNEL) 4060ab25eeb5Syz (void) SNPRINTF(name, sizeof(name), "%u", number); 4061ab25eeb5Syz #else 40627c478bd9Sstevel@tonic-gate (void) sprintf(name, "%u", number); 4063ab25eeb5Syz #endif 40647c478bd9Sstevel@tonic-gate 40657c478bd9Sstevel@tonic-gate READ_ENTER(&ip_poolrw); 40667c478bd9Sstevel@tonic-gate 40677c478bd9Sstevel@tonic-gate switch (type) 40687c478bd9Sstevel@tonic-gate { 40697c478bd9Sstevel@tonic-gate case IPLT_POOL : 40707c478bd9Sstevel@tonic-gate # if (defined(__osf__) && defined(_KERNEL)) 40717c478bd9Sstevel@tonic-gate ptr = NULL; 40727c478bd9Sstevel@tonic-gate *funcptr = NULL; 40737c478bd9Sstevel@tonic-gate # else 40747c478bd9Sstevel@tonic-gate ipo = ip_pool_find(IPL_LOGIPF, name); 40757c478bd9Sstevel@tonic-gate ptr = ipo; 40767c478bd9Sstevel@tonic-gate if (ipo != NULL) { 40777c478bd9Sstevel@tonic-gate ATOMIC_INC32(ipo->ipo_ref); 40787c478bd9Sstevel@tonic-gate } 40797c478bd9Sstevel@tonic-gate *funcptr = ip_pool_search; 40807c478bd9Sstevel@tonic-gate # endif 40817c478bd9Sstevel@tonic-gate break; 40827c478bd9Sstevel@tonic-gate case IPLT_HASH : 40837c478bd9Sstevel@tonic-gate iph = fr_findhtable(IPL_LOGIPF, name); 40847c478bd9Sstevel@tonic-gate ptr = iph; 40857c478bd9Sstevel@tonic-gate if (iph != NULL) { 40867c478bd9Sstevel@tonic-gate ATOMIC_INC32(iph->iph_ref); 40877c478bd9Sstevel@tonic-gate } 40887c478bd9Sstevel@tonic-gate *funcptr = fr_iphmfindip; 40897c478bd9Sstevel@tonic-gate break; 40907c478bd9Sstevel@tonic-gate default: 40917c478bd9Sstevel@tonic-gate ptr = NULL; 40927c478bd9Sstevel@tonic-gate *funcptr = NULL; 40937c478bd9Sstevel@tonic-gate break; 40947c478bd9Sstevel@tonic-gate } 40957c478bd9Sstevel@tonic-gate RWLOCK_EXIT(&ip_poolrw); 40967c478bd9Sstevel@tonic-gate 40977c478bd9Sstevel@tonic-gate return ptr; 40987c478bd9Sstevel@tonic-gate } 40997c478bd9Sstevel@tonic-gate #endif 41007c478bd9Sstevel@tonic-gate 41017c478bd9Sstevel@tonic-gate 41027c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 41037c478bd9Sstevel@tonic-gate /* Function: frrequest */ 41047c478bd9Sstevel@tonic-gate /* Returns: int - 0 == success, > 0 == errno value */ 41057c478bd9Sstevel@tonic-gate /* Parameters: unit(I) - device for which this is for */ 41067c478bd9Sstevel@tonic-gate /* req(I) - ioctl command (SIOC*) */ 41077c478bd9Sstevel@tonic-gate /* data(I) - pointr to ioctl data */ 41087c478bd9Sstevel@tonic-gate /* set(I) - 1 or 0 (filter set) */ 41097c478bd9Sstevel@tonic-gate /* makecopy(I) - flag indicating whether data points to a rule */ 41107c478bd9Sstevel@tonic-gate /* in kernel space & hence doesn't need copying. */ 41117c478bd9Sstevel@tonic-gate /* */ 41127c478bd9Sstevel@tonic-gate /* This function handles all the requests which operate on the list of */ 41137c478bd9Sstevel@tonic-gate /* filter rules. This includes adding, deleting, insertion. It is also */ 41147c478bd9Sstevel@tonic-gate /* responsible for creating groups when a "head" rule is loaded. Interface */ 41157c478bd9Sstevel@tonic-gate /* names are resolved here and other sanity checks are made on the content */ 41167c478bd9Sstevel@tonic-gate /* of the rule structure being loaded. If a rule has user defined timeouts */ 41177c478bd9Sstevel@tonic-gate /* then make sure they are created and initialised before exiting. */ 41187c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 41197c478bd9Sstevel@tonic-gate int frrequest(unit, req, data, set, makecopy) 41207c478bd9Sstevel@tonic-gate int unit; 4121ab25eeb5Syz ioctlcmd_t req; 41227c478bd9Sstevel@tonic-gate int set, makecopy; 41237c478bd9Sstevel@tonic-gate caddr_t data; 41247c478bd9Sstevel@tonic-gate { 41257c478bd9Sstevel@tonic-gate frentry_t frd, *fp, *f, **fprev, **ftail; 41267c478bd9Sstevel@tonic-gate int error = 0, in, v; 4127ab25eeb5Syz void *ptr, *uptr; 41287c478bd9Sstevel@tonic-gate u_int *p, *pp; 41297c478bd9Sstevel@tonic-gate frgroup_t *fg; 41307c478bd9Sstevel@tonic-gate char *group; 41317c478bd9Sstevel@tonic-gate 41327c478bd9Sstevel@tonic-gate fg = NULL; 41337c478bd9Sstevel@tonic-gate fp = &frd; 41347c478bd9Sstevel@tonic-gate if (makecopy != 0) { 41357c478bd9Sstevel@tonic-gate error = fr_inobj(data, fp, IPFOBJ_FRENTRY); 41367c478bd9Sstevel@tonic-gate if (error) 41377c478bd9Sstevel@tonic-gate return EFAULT; 41387c478bd9Sstevel@tonic-gate if ((fp->fr_flags & FR_T_BUILTIN) != 0) 41397c478bd9Sstevel@tonic-gate return EINVAL; 41407c478bd9Sstevel@tonic-gate fp->fr_ref = 0; 41417c478bd9Sstevel@tonic-gate fp->fr_flags |= FR_COPIED; 41427c478bd9Sstevel@tonic-gate } else { 41437c478bd9Sstevel@tonic-gate fp = (frentry_t *)data; 41447c478bd9Sstevel@tonic-gate if ((fp->fr_type & FR_T_BUILTIN) == 0) 41457c478bd9Sstevel@tonic-gate return EINVAL; 41467c478bd9Sstevel@tonic-gate fp->fr_flags &= ~FR_COPIED; 41477c478bd9Sstevel@tonic-gate } 41487c478bd9Sstevel@tonic-gate 41497c478bd9Sstevel@tonic-gate if (((fp->fr_dsize == 0) && (fp->fr_data != NULL)) || 41507c478bd9Sstevel@tonic-gate ((fp->fr_dsize != 0) && (fp->fr_data == NULL))) 41517c478bd9Sstevel@tonic-gate return EINVAL; 41527c478bd9Sstevel@tonic-gate 41537c478bd9Sstevel@tonic-gate v = fp->fr_v; 4154ab25eeb5Syz uptr = fp->fr_data; 41557c478bd9Sstevel@tonic-gate 41567c478bd9Sstevel@tonic-gate /* 41577c478bd9Sstevel@tonic-gate * Only filter rules for IPv4 or IPv6 are accepted. 41587c478bd9Sstevel@tonic-gate */ 41597c478bd9Sstevel@tonic-gate if (v == 4) 41607c478bd9Sstevel@tonic-gate /*EMPTY*/; 41617c478bd9Sstevel@tonic-gate #ifdef USE_INET6 41627c478bd9Sstevel@tonic-gate else if (v == 6) 41637c478bd9Sstevel@tonic-gate /*EMPTY*/; 41647c478bd9Sstevel@tonic-gate #endif 41657c478bd9Sstevel@tonic-gate else { 41667c478bd9Sstevel@tonic-gate return EINVAL; 41677c478bd9Sstevel@tonic-gate } 41687c478bd9Sstevel@tonic-gate 41697c478bd9Sstevel@tonic-gate /* 41707c478bd9Sstevel@tonic-gate * If the rule is being loaded from user space, i.e. we had to copy it 41717c478bd9Sstevel@tonic-gate * into kernel space, then do not trust the function pointer in the 41727c478bd9Sstevel@tonic-gate * rule. 41737c478bd9Sstevel@tonic-gate */ 41747c478bd9Sstevel@tonic-gate if ((makecopy == 1) && (fp->fr_func != NULL)) { 41757c478bd9Sstevel@tonic-gate if (fr_findfunc(fp->fr_func) == NULL) 41767c478bd9Sstevel@tonic-gate return ESRCH; 41777c478bd9Sstevel@tonic-gate error = fr_funcinit(fp); 41787c478bd9Sstevel@tonic-gate if (error != 0) 41797c478bd9Sstevel@tonic-gate return error; 41807c478bd9Sstevel@tonic-gate } 41817c478bd9Sstevel@tonic-gate 41827c478bd9Sstevel@tonic-gate ptr = NULL; 41837c478bd9Sstevel@tonic-gate /* 41847c478bd9Sstevel@tonic-gate * Check that the group number does exist and that its use (in/out) 41857c478bd9Sstevel@tonic-gate * matches what the rule is. 41867c478bd9Sstevel@tonic-gate */ 4187ab25eeb5Syz if (!strncmp(fp->fr_grhead, "0", FR_GROUPLEN)) 4188ab25eeb5Syz *fp->fr_grhead = '\0'; 41897c478bd9Sstevel@tonic-gate group = fp->fr_group; 4190ab25eeb5Syz if (!strncmp(group, "0", FR_GROUPLEN)) 41917c478bd9Sstevel@tonic-gate *group = '\0'; 41926d512983Sdr 41936d512983Sdr if (FR_ISACCOUNT(fp->fr_flags)) 41946d512983Sdr unit = IPL_LOGCOUNT; 41956d512983Sdr 41967c478bd9Sstevel@tonic-gate if ((req != (int)SIOCZRLST) && (*group != '\0')) { 41977c478bd9Sstevel@tonic-gate fg = fr_findgroup(group, unit, set, NULL); 41987c478bd9Sstevel@tonic-gate if (fg == NULL) 41997c478bd9Sstevel@tonic-gate return ESRCH; 42007c478bd9Sstevel@tonic-gate if (fg->fg_flags == 0) 42017c478bd9Sstevel@tonic-gate fg->fg_flags = fp->fr_flags & FR_INOUT; 42027c478bd9Sstevel@tonic-gate else if (fg->fg_flags != (fp->fr_flags & FR_INOUT)) 42037c478bd9Sstevel@tonic-gate return ESRCH; 42047c478bd9Sstevel@tonic-gate } 42057c478bd9Sstevel@tonic-gate 42067c478bd9Sstevel@tonic-gate in = (fp->fr_flags & FR_INQUE) ? 0 : 1; 42077c478bd9Sstevel@tonic-gate 42087c478bd9Sstevel@tonic-gate /* 42097c478bd9Sstevel@tonic-gate * Work out which rule list this change is being applied to. 42107c478bd9Sstevel@tonic-gate */ 42117c478bd9Sstevel@tonic-gate ftail = NULL; 42127c478bd9Sstevel@tonic-gate fprev = NULL; 42137c478bd9Sstevel@tonic-gate if (unit == IPL_LOGAUTH) 42147c478bd9Sstevel@tonic-gate fprev = &ipauth; 42157c478bd9Sstevel@tonic-gate else if (v == 4) { 42167c478bd9Sstevel@tonic-gate if (FR_ISACCOUNT(fp->fr_flags)) 42177c478bd9Sstevel@tonic-gate fprev = &ipacct[in][set]; 42186d512983Sdr else if ((fp->fr_flags & (FR_OUTQUE|FR_INQUE)) != 0) 42197c478bd9Sstevel@tonic-gate fprev = &ipfilter[in][set]; 42207c478bd9Sstevel@tonic-gate } else if (v == 6) { 42217c478bd9Sstevel@tonic-gate if (FR_ISACCOUNT(fp->fr_flags)) 42227c478bd9Sstevel@tonic-gate fprev = &ipacct6[in][set]; 42236d512983Sdr else if ((fp->fr_flags & (FR_OUTQUE|FR_INQUE)) != 0) 42247c478bd9Sstevel@tonic-gate fprev = &ipfilter6[in][set]; 42257c478bd9Sstevel@tonic-gate } 42267c478bd9Sstevel@tonic-gate if (fprev == NULL) 42277c478bd9Sstevel@tonic-gate return ESRCH; 42287c478bd9Sstevel@tonic-gate 42297c478bd9Sstevel@tonic-gate if (*group != '\0') { 42307c478bd9Sstevel@tonic-gate if (!fg && !(fg = fr_findgroup(group, unit, set, NULL))) 42317c478bd9Sstevel@tonic-gate return ESRCH; 42327c478bd9Sstevel@tonic-gate fprev = &fg->fg_start; 42337c478bd9Sstevel@tonic-gate } 42347c478bd9Sstevel@tonic-gate 42357c478bd9Sstevel@tonic-gate ftail = fprev; 4236ab25eeb5Syz for (f = *ftail; (f = *ftail) != NULL; ftail = &f->fr_next) { 4237ab25eeb5Syz if (fp->fr_collect <= f->fr_collect) { 4238ab25eeb5Syz ftail = fprev; 4239ab25eeb5Syz f = NULL; 4240ab25eeb5Syz break; 4241ab25eeb5Syz } 4242ab25eeb5Syz fprev = ftail; 4243ab25eeb5Syz } 42447c478bd9Sstevel@tonic-gate 42457c478bd9Sstevel@tonic-gate /* 42467c478bd9Sstevel@tonic-gate * Copy in extra data for the rule. 42477c478bd9Sstevel@tonic-gate */ 42487c478bd9Sstevel@tonic-gate if (fp->fr_dsize != 0) { 42497c478bd9Sstevel@tonic-gate if (makecopy != 0) { 42507c478bd9Sstevel@tonic-gate KMALLOCS(ptr, void *, fp->fr_dsize); 42517c478bd9Sstevel@tonic-gate if (!ptr) 42527c478bd9Sstevel@tonic-gate return ENOMEM; 4253ab25eeb5Syz error = COPYIN(uptr, ptr, fp->fr_dsize); 42547c478bd9Sstevel@tonic-gate } else { 4255ab25eeb5Syz ptr = uptr; 42567c478bd9Sstevel@tonic-gate error = 0; 42577c478bd9Sstevel@tonic-gate } 42587c478bd9Sstevel@tonic-gate if (error != 0) { 42597c478bd9Sstevel@tonic-gate KFREES(ptr, fp->fr_dsize); 42607c478bd9Sstevel@tonic-gate return ENOMEM; 42617c478bd9Sstevel@tonic-gate } 42627c478bd9Sstevel@tonic-gate fp->fr_data = ptr; 42637c478bd9Sstevel@tonic-gate } else 42647c478bd9Sstevel@tonic-gate fp->fr_data = NULL; 42657c478bd9Sstevel@tonic-gate 42667c478bd9Sstevel@tonic-gate /* 42677c478bd9Sstevel@tonic-gate * Perform per-rule type sanity checks of their members. 42687c478bd9Sstevel@tonic-gate */ 42697c478bd9Sstevel@tonic-gate switch (fp->fr_type & ~FR_T_BUILTIN) 42707c478bd9Sstevel@tonic-gate { 4271ab25eeb5Syz #if defined(IPFILTER_BPF) 42727c478bd9Sstevel@tonic-gate case FR_T_BPFOPC : 42737c478bd9Sstevel@tonic-gate if (fp->fr_dsize == 0) 42747c478bd9Sstevel@tonic-gate return EINVAL; 42757c478bd9Sstevel@tonic-gate if (!bpf_validate(ptr, fp->fr_dsize/sizeof(struct bpf_insn))) { 42767c478bd9Sstevel@tonic-gate if (makecopy && fp->fr_data != NULL) { 42777c478bd9Sstevel@tonic-gate KFREES(fp->fr_data, fp->fr_dsize); 42787c478bd9Sstevel@tonic-gate } 42797c478bd9Sstevel@tonic-gate return EINVAL; 42807c478bd9Sstevel@tonic-gate } 42817c478bd9Sstevel@tonic-gate break; 42827c478bd9Sstevel@tonic-gate #endif 42837c478bd9Sstevel@tonic-gate case FR_T_IPF : 4284ab25eeb5Syz if (fp->fr_dsize != sizeof(fripf_t)) 4285ab25eeb5Syz return EINVAL; 4286ab25eeb5Syz 4287ab25eeb5Syz /* 4288ab25eeb5Syz * Allowing a rule with both "keep state" and "with oow" is 4289ab25eeb5Syz * pointless because adding a state entry to the table will 4290ab25eeb5Syz * fail with the out of window (oow) flag set. 4291ab25eeb5Syz */ 4292ab25eeb5Syz if ((fp->fr_flags & FR_KEEPSTATE) && (fp->fr_flx & FI_OOW)) 42937c478bd9Sstevel@tonic-gate return EINVAL; 4294ab25eeb5Syz 42957c478bd9Sstevel@tonic-gate switch (fp->fr_satype) 42967c478bd9Sstevel@tonic-gate { 42977c478bd9Sstevel@tonic-gate case FRI_BROADCAST : 42987c478bd9Sstevel@tonic-gate case FRI_DYNAMIC : 42997c478bd9Sstevel@tonic-gate case FRI_NETWORK : 43007c478bd9Sstevel@tonic-gate case FRI_NETMASKED : 43017c478bd9Sstevel@tonic-gate case FRI_PEERADDR : 43027c478bd9Sstevel@tonic-gate if (fp->fr_sifpidx < 0 || fp->fr_sifpidx > 3) { 43037c478bd9Sstevel@tonic-gate if (makecopy && fp->fr_data != NULL) { 43047c478bd9Sstevel@tonic-gate KFREES(fp->fr_data, fp->fr_dsize); 43057c478bd9Sstevel@tonic-gate } 43067c478bd9Sstevel@tonic-gate return EINVAL; 43077c478bd9Sstevel@tonic-gate } 43087c478bd9Sstevel@tonic-gate break; 43097c478bd9Sstevel@tonic-gate #ifdef IPFILTER_LOOKUP 43107c478bd9Sstevel@tonic-gate case FRI_LOOKUP : 43117c478bd9Sstevel@tonic-gate fp->fr_srcptr = fr_resolvelookup(fp->fr_srctype, 43127c478bd9Sstevel@tonic-gate fp->fr_srcnum, 43137c478bd9Sstevel@tonic-gate &fp->fr_srcfunc); 43147c478bd9Sstevel@tonic-gate break; 43157c478bd9Sstevel@tonic-gate #endif 43167c478bd9Sstevel@tonic-gate default : 43177c478bd9Sstevel@tonic-gate break; 43187c478bd9Sstevel@tonic-gate } 43197c478bd9Sstevel@tonic-gate 43207c478bd9Sstevel@tonic-gate switch (fp->fr_datype) 43217c478bd9Sstevel@tonic-gate { 43227c478bd9Sstevel@tonic-gate case FRI_BROADCAST : 43237c478bd9Sstevel@tonic-gate case FRI_DYNAMIC : 43247c478bd9Sstevel@tonic-gate case FRI_NETWORK : 43257c478bd9Sstevel@tonic-gate case FRI_NETMASKED : 43267c478bd9Sstevel@tonic-gate case FRI_PEERADDR : 43277c478bd9Sstevel@tonic-gate if (fp->fr_difpidx < 0 || fp->fr_difpidx > 3) { 43287c478bd9Sstevel@tonic-gate if (makecopy && fp->fr_data != NULL) { 43297c478bd9Sstevel@tonic-gate KFREES(fp->fr_data, fp->fr_dsize); 43307c478bd9Sstevel@tonic-gate } 43317c478bd9Sstevel@tonic-gate return EINVAL; 43327c478bd9Sstevel@tonic-gate } 43337c478bd9Sstevel@tonic-gate break; 43347c478bd9Sstevel@tonic-gate #ifdef IPFILTER_LOOKUP 43357c478bd9Sstevel@tonic-gate case FRI_LOOKUP : 43367c478bd9Sstevel@tonic-gate fp->fr_dstptr = fr_resolvelookup(fp->fr_dsttype, 43377c478bd9Sstevel@tonic-gate fp->fr_dstnum, 43387c478bd9Sstevel@tonic-gate &fp->fr_dstfunc); 43397c478bd9Sstevel@tonic-gate break; 43407c478bd9Sstevel@tonic-gate #endif 43417c478bd9Sstevel@tonic-gate default : 43427c478bd9Sstevel@tonic-gate break; 43437c478bd9Sstevel@tonic-gate } 43447c478bd9Sstevel@tonic-gate break; 43457c478bd9Sstevel@tonic-gate case FR_T_NONE : 43467c478bd9Sstevel@tonic-gate break; 43477c478bd9Sstevel@tonic-gate case FR_T_CALLFUNC : 43487c478bd9Sstevel@tonic-gate break; 43497c478bd9Sstevel@tonic-gate case FR_T_COMPIPF : 43507c478bd9Sstevel@tonic-gate break; 43517c478bd9Sstevel@tonic-gate default : 43527c478bd9Sstevel@tonic-gate if (makecopy && fp->fr_data != NULL) { 43537c478bd9Sstevel@tonic-gate KFREES(fp->fr_data, fp->fr_dsize); 43547c478bd9Sstevel@tonic-gate } 43557c478bd9Sstevel@tonic-gate return EINVAL; 43567c478bd9Sstevel@tonic-gate } 43577c478bd9Sstevel@tonic-gate 43587c478bd9Sstevel@tonic-gate /* 43597c478bd9Sstevel@tonic-gate * Lookup all the interface names that are part of the rule. 43607c478bd9Sstevel@tonic-gate */ 4361*381a2a9aSdr frsynclist(0, 0, NULL, NULL, fp); 43627c478bd9Sstevel@tonic-gate fp->fr_statecnt = 0; 43637c478bd9Sstevel@tonic-gate 43647c478bd9Sstevel@tonic-gate /* 43657c478bd9Sstevel@tonic-gate * Look for an existing matching filter rule, but don't include the 43667c478bd9Sstevel@tonic-gate * next or interface pointer in the comparison (fr_next, fr_ifa). 43677c478bd9Sstevel@tonic-gate * This elminates rules which are indentical being loaded. Checksum 43687c478bd9Sstevel@tonic-gate * the constant part of the filter rule to make comparisons quicker 43697c478bd9Sstevel@tonic-gate * (this meaning no pointers are included). 43707c478bd9Sstevel@tonic-gate */ 43717c478bd9Sstevel@tonic-gate for (fp->fr_cksum = 0, p = (u_int *)&fp->fr_func, pp = &fp->fr_cksum; 43727c478bd9Sstevel@tonic-gate p < pp; p++) 43737c478bd9Sstevel@tonic-gate fp->fr_cksum += *p; 43747c478bd9Sstevel@tonic-gate pp = (u_int *)(fp->fr_caddr + fp->fr_dsize); 43757c478bd9Sstevel@tonic-gate for (p = (u_int *)fp->fr_data; p < pp; p++) 43767c478bd9Sstevel@tonic-gate fp->fr_cksum += *p; 43777c478bd9Sstevel@tonic-gate 43787c478bd9Sstevel@tonic-gate WRITE_ENTER(&ipf_mutex); 43797c478bd9Sstevel@tonic-gate bzero((char *)frcache, sizeof(frcache)); 43807c478bd9Sstevel@tonic-gate 4381ab25eeb5Syz for (; (f = *ftail) != NULL; ftail = &f->fr_next) { 4382ab25eeb5Syz if ((fp->fr_cksum != f->fr_cksum) || 4383ab25eeb5Syz (f->fr_dsize != fp->fr_dsize)) 4384ab25eeb5Syz continue; 4385ab25eeb5Syz if (bcmp((char *)&f->fr_func, (char *)&fp->fr_func, FR_CMPSIZ)) 4386ab25eeb5Syz continue; 4387ab25eeb5Syz if ((!ptr && !f->fr_data) || 4388ab25eeb5Syz (ptr && f->fr_data && 43897c478bd9Sstevel@tonic-gate !bcmp((char *)ptr, (char *)f->fr_data, f->fr_dsize))) 43907c478bd9Sstevel@tonic-gate break; 4391ab25eeb5Syz } 43927c478bd9Sstevel@tonic-gate 43937c478bd9Sstevel@tonic-gate /* 43947c478bd9Sstevel@tonic-gate * If zero'ing statistics, copy current to caller and zero. 43957c478bd9Sstevel@tonic-gate */ 4396ab25eeb5Syz if (req == (ioctlcmd_t)SIOCZRLST) { 43977c478bd9Sstevel@tonic-gate if (f == NULL) 43987c478bd9Sstevel@tonic-gate error = ESRCH; 43997c478bd9Sstevel@tonic-gate else { 4400ab25eeb5Syz /* 4401ab25eeb5Syz * Copy and reduce lock because of impending copyout. 4402ab25eeb5Syz * Well we should, but if we do then the atomicity of 4403ab25eeb5Syz * this call and the correctness of fr_hits and 4404ab25eeb5Syz * fr_bytes cannot be guaranteed. As it is, this code 4405ab25eeb5Syz * only resets them to 0 if they are successfully 4406ab25eeb5Syz * copied out into user space. 4407ab25eeb5Syz */ 4408ab25eeb5Syz bcopy((char *)f, (char *)fp, sizeof(*f)); 4409ab25eeb5Syz /* MUTEX_DOWNGRADE(&ipf_mutex); */ 4410ab25eeb5Syz 4411ab25eeb5Syz /* 4412ab25eeb5Syz * When we copy this rule back out, set the data 4413ab25eeb5Syz * pointer to be what it was in user space. 4414ab25eeb5Syz */ 4415ab25eeb5Syz fp->fr_data = uptr; 4416ab25eeb5Syz error = fr_outobj(data, fp, IPFOBJ_FRENTRY); 4417ab25eeb5Syz 44187c478bd9Sstevel@tonic-gate if (error == 0) { 4419ab25eeb5Syz if ((f->fr_dsize != 0) && (uptr != NULL)) 4420ab25eeb5Syz error = COPYOUT(f->fr_data, uptr, 44217c478bd9Sstevel@tonic-gate f->fr_dsize); 44227c478bd9Sstevel@tonic-gate if (error == 0) { 44237c478bd9Sstevel@tonic-gate f->fr_hits = 0; 44247c478bd9Sstevel@tonic-gate f->fr_bytes = 0; 44257c478bd9Sstevel@tonic-gate } 44267c478bd9Sstevel@tonic-gate } 44277c478bd9Sstevel@tonic-gate } 44287c478bd9Sstevel@tonic-gate 4429ab25eeb5Syz if ((ptr != NULL) && (makecopy != 0)) { 44307c478bd9Sstevel@tonic-gate KFREES(ptr, fp->fr_dsize); 44317c478bd9Sstevel@tonic-gate } 44327c478bd9Sstevel@tonic-gate RWLOCK_EXIT(&ipf_mutex); 44337c478bd9Sstevel@tonic-gate return error; 44347c478bd9Sstevel@tonic-gate } 44357c478bd9Sstevel@tonic-gate 44367c478bd9Sstevel@tonic-gate if (!f) { 4437ab25eeb5Syz /* 4438ab25eeb5Syz * At the end of this, ftail must point to the place where the 4439ab25eeb5Syz * new rule is to be saved/inserted/added. 4440ab25eeb5Syz * For SIOCAD*FR, this should be the last rule in the group of 4441ab25eeb5Syz * rules that have equal fr_collect fields. 4442ab25eeb5Syz * For SIOCIN*FR, ... 4443ab25eeb5Syz */ 4444ab25eeb5Syz if (req == (ioctlcmd_t)SIOCADAFR || 4445ab25eeb5Syz req == (ioctlcmd_t)SIOCADIFR) { 4446ab25eeb5Syz 4447ab25eeb5Syz for (ftail = fprev; (f = *ftail) != NULL; ) { 4448ab25eeb5Syz if (f->fr_collect > fp->fr_collect) 4449ab25eeb5Syz break; 4450ab25eeb5Syz ftail = &f->fr_next; 4451ab25eeb5Syz } 4452ab25eeb5Syz f = NULL; 4453ab25eeb5Syz ptr = NULL; 4454ab25eeb5Syz error = 0; 4455ab25eeb5Syz } else if (req == (ioctlcmd_t)SIOCINAFR || 4456ab25eeb5Syz req == (ioctlcmd_t)SIOCINIFR) { 4457ab25eeb5Syz while ((f = *fprev) != NULL) { 4458ab25eeb5Syz if (f->fr_collect >= fp->fr_collect) 4459ab25eeb5Syz break; 4460ab25eeb5Syz fprev = &f->fr_next; 4461ab25eeb5Syz } 44627c478bd9Sstevel@tonic-gate ftail = fprev; 44637c478bd9Sstevel@tonic-gate if (fp->fr_hits != 0) { 4464ab25eeb5Syz while (fp->fr_hits && (f = *ftail)) { 4465ab25eeb5Syz if (f->fr_collect != fp->fr_collect) 4466ab25eeb5Syz break; 4467ab25eeb5Syz fprev = ftail; 44687c478bd9Sstevel@tonic-gate ftail = &f->fr_next; 4469ab25eeb5Syz fp->fr_hits--; 4470ab25eeb5Syz } 44717c478bd9Sstevel@tonic-gate } 44727c478bd9Sstevel@tonic-gate f = NULL; 44737c478bd9Sstevel@tonic-gate ptr = NULL; 44747c478bd9Sstevel@tonic-gate error = 0; 44757c478bd9Sstevel@tonic-gate } 44767c478bd9Sstevel@tonic-gate } 44777c478bd9Sstevel@tonic-gate 44787c478bd9Sstevel@tonic-gate /* 44797c478bd9Sstevel@tonic-gate * Request to remove a rule. 44807c478bd9Sstevel@tonic-gate */ 4481ab25eeb5Syz if (req == (ioctlcmd_t)SIOCRMAFR || req == (ioctlcmd_t)SIOCRMIFR) { 44827c478bd9Sstevel@tonic-gate if (!f) 44837c478bd9Sstevel@tonic-gate error = ESRCH; 44847c478bd9Sstevel@tonic-gate else { 44857c478bd9Sstevel@tonic-gate /* 44867c478bd9Sstevel@tonic-gate * Do not allow activity from user space to interfere 44877c478bd9Sstevel@tonic-gate * with rules not loaded that way. 44887c478bd9Sstevel@tonic-gate */ 44897c478bd9Sstevel@tonic-gate if ((makecopy == 1) && !(f->fr_flags & FR_COPIED)) { 44907c478bd9Sstevel@tonic-gate error = EPERM; 44917c478bd9Sstevel@tonic-gate goto done; 44927c478bd9Sstevel@tonic-gate } 44937c478bd9Sstevel@tonic-gate 44947c478bd9Sstevel@tonic-gate /* 44957c478bd9Sstevel@tonic-gate * Return EBUSY if the rule is being reference by 44967c478bd9Sstevel@tonic-gate * something else (eg state information. 44977c478bd9Sstevel@tonic-gate */ 44987c478bd9Sstevel@tonic-gate if (f->fr_ref > 1) { 44997c478bd9Sstevel@tonic-gate error = EBUSY; 45007c478bd9Sstevel@tonic-gate goto done; 45017c478bd9Sstevel@tonic-gate } 45027c478bd9Sstevel@tonic-gate #ifdef IPFILTER_SCAN 45037c478bd9Sstevel@tonic-gate if (f->fr_isctag[0] != '\0' && 45047c478bd9Sstevel@tonic-gate (f->fr_isc != (struct ipscan *)-1)) 4505ab25eeb5Syz ipsc_detachfr(f); 45067c478bd9Sstevel@tonic-gate #endif 45077c478bd9Sstevel@tonic-gate if ((fg != NULL) && (fg->fg_head != NULL)) 45087c478bd9Sstevel@tonic-gate fg->fg_head->fr_ref--; 45097c478bd9Sstevel@tonic-gate if (unit == IPL_LOGAUTH) { 45107c478bd9Sstevel@tonic-gate error = fr_preauthcmd(req, f, ftail); 45117c478bd9Sstevel@tonic-gate goto done; 45127c478bd9Sstevel@tonic-gate } 45137c478bd9Sstevel@tonic-gate if (*f->fr_grhead != '\0') 45147c478bd9Sstevel@tonic-gate fr_delgroup(f->fr_grhead, unit, set); 4515ab25eeb5Syz fr_fixskip(ftail, f, -1); 45167c478bd9Sstevel@tonic-gate *ftail = f->fr_next; 45177c478bd9Sstevel@tonic-gate f->fr_next = NULL; 45187c478bd9Sstevel@tonic-gate (void)fr_derefrule(&f); 45197c478bd9Sstevel@tonic-gate } 45207c478bd9Sstevel@tonic-gate } else { 45217c478bd9Sstevel@tonic-gate /* 45227c478bd9Sstevel@tonic-gate * Not removing, so we must be adding/inserting a rule. 45237c478bd9Sstevel@tonic-gate */ 45247c478bd9Sstevel@tonic-gate if (f) 45257c478bd9Sstevel@tonic-gate error = EEXIST; 45267c478bd9Sstevel@tonic-gate else { 45277c478bd9Sstevel@tonic-gate if (unit == IPL_LOGAUTH) { 45287c478bd9Sstevel@tonic-gate error = fr_preauthcmd(req, fp, ftail); 45297c478bd9Sstevel@tonic-gate goto done; 45307c478bd9Sstevel@tonic-gate } 45317c478bd9Sstevel@tonic-gate if (makecopy) { 45327c478bd9Sstevel@tonic-gate KMALLOC(f, frentry_t *); 45337c478bd9Sstevel@tonic-gate } else 45347c478bd9Sstevel@tonic-gate f = fp; 45357c478bd9Sstevel@tonic-gate if (f != NULL) { 4536ab25eeb5Syz if (fg != NULL && fg->fg_head != NULL) 45377c478bd9Sstevel@tonic-gate fg->fg_head->fr_ref++; 45387c478bd9Sstevel@tonic-gate if (fp != f) 45397c478bd9Sstevel@tonic-gate bcopy((char *)fp, (char *)f, 45407c478bd9Sstevel@tonic-gate sizeof(*f)); 45417c478bd9Sstevel@tonic-gate MUTEX_NUKE(&f->fr_lock); 45427c478bd9Sstevel@tonic-gate MUTEX_INIT(&f->fr_lock, "filter rule lock"); 45437c478bd9Sstevel@tonic-gate #ifdef IPFILTER_SCAN 4544ab25eeb5Syz if (f->fr_isctag[0] != '\0' && 4545ab25eeb5Syz ipsc_attachfr(f)) 45467c478bd9Sstevel@tonic-gate f->fr_isc = (struct ipscan *)-1; 45477c478bd9Sstevel@tonic-gate #endif 45487c478bd9Sstevel@tonic-gate f->fr_hits = 0; 45497c478bd9Sstevel@tonic-gate if (makecopy != 0) 45507c478bd9Sstevel@tonic-gate f->fr_ref = 1; 45517c478bd9Sstevel@tonic-gate f->fr_next = *ftail; 45527c478bd9Sstevel@tonic-gate *ftail = f; 4553ab25eeb5Syz if (req == (ioctlcmd_t)SIOCINIFR || 4554ab25eeb5Syz req == (ioctlcmd_t)SIOCINAFR) 4555ab25eeb5Syz fr_fixskip(ftail, f, 1); 45567c478bd9Sstevel@tonic-gate f->fr_grp = NULL; 45577c478bd9Sstevel@tonic-gate group = f->fr_grhead; 45587c478bd9Sstevel@tonic-gate if (*group != '\0') { 45597c478bd9Sstevel@tonic-gate fg = fr_addgroup(group, f, f->fr_flags, 45607c478bd9Sstevel@tonic-gate unit, set); 45617c478bd9Sstevel@tonic-gate if (fg != NULL) 45627c478bd9Sstevel@tonic-gate f->fr_grp = &fg->fg_start; 45637c478bd9Sstevel@tonic-gate } 45647c478bd9Sstevel@tonic-gate } else 45657c478bd9Sstevel@tonic-gate error = ENOMEM; 45667c478bd9Sstevel@tonic-gate } 45677c478bd9Sstevel@tonic-gate } 45687c478bd9Sstevel@tonic-gate done: 45697c478bd9Sstevel@tonic-gate RWLOCK_EXIT(&ipf_mutex); 45707c478bd9Sstevel@tonic-gate if ((ptr != NULL) && (error != 0) && (makecopy != 0)) { 45717c478bd9Sstevel@tonic-gate KFREES(ptr, fp->fr_dsize); 45727c478bd9Sstevel@tonic-gate } 45737c478bd9Sstevel@tonic-gate return (error); 45747c478bd9Sstevel@tonic-gate } 45757c478bd9Sstevel@tonic-gate 45767c478bd9Sstevel@tonic-gate 45777c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 45787c478bd9Sstevel@tonic-gate /* Function: fr_funcinit */ 45797c478bd9Sstevel@tonic-gate /* Returns: int - 0 == success, else ESRCH: cannot resolve rule details */ 45807c478bd9Sstevel@tonic-gate /* Parameters: fr(I) - pointer to filter rule */ 45817c478bd9Sstevel@tonic-gate /* */ 45827c478bd9Sstevel@tonic-gate /* If a rule is a call rule, then check if the function it points to needs */ 45837c478bd9Sstevel@tonic-gate /* an init function to be called now the rule has been loaded. */ 45847c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 45857c478bd9Sstevel@tonic-gate static int fr_funcinit(fr) 45867c478bd9Sstevel@tonic-gate frentry_t *fr; 45877c478bd9Sstevel@tonic-gate { 45887c478bd9Sstevel@tonic-gate ipfunc_resolve_t *ft; 45897c478bd9Sstevel@tonic-gate int err; 45907c478bd9Sstevel@tonic-gate 45917c478bd9Sstevel@tonic-gate err = ESRCH; 45927c478bd9Sstevel@tonic-gate 45937c478bd9Sstevel@tonic-gate for (ft = fr_availfuncs; ft->ipfu_addr != NULL; ft++) 45947c478bd9Sstevel@tonic-gate if (ft->ipfu_addr == fr->fr_func) { 45957c478bd9Sstevel@tonic-gate err = 0; 45967c478bd9Sstevel@tonic-gate if (ft->ipfu_init != NULL) 45977c478bd9Sstevel@tonic-gate err = (*ft->ipfu_init)(fr); 45987c478bd9Sstevel@tonic-gate break; 45997c478bd9Sstevel@tonic-gate } 46007c478bd9Sstevel@tonic-gate return err; 46017c478bd9Sstevel@tonic-gate } 46027c478bd9Sstevel@tonic-gate 46037c478bd9Sstevel@tonic-gate 46047c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 46057c478bd9Sstevel@tonic-gate /* Function: fr_findfunc */ 46067c478bd9Sstevel@tonic-gate /* Returns: ipfunc_t - pointer to function if found, else NULL */ 46077c478bd9Sstevel@tonic-gate /* Parameters: funcptr(I) - function pointer to lookup */ 46087c478bd9Sstevel@tonic-gate /* */ 46097c478bd9Sstevel@tonic-gate /* Look for a function in the table of known functions. */ 46107c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 46117c478bd9Sstevel@tonic-gate static ipfunc_t fr_findfunc(funcptr) 46127c478bd9Sstevel@tonic-gate ipfunc_t funcptr; 46137c478bd9Sstevel@tonic-gate { 46147c478bd9Sstevel@tonic-gate ipfunc_resolve_t *ft; 46157c478bd9Sstevel@tonic-gate 46167c478bd9Sstevel@tonic-gate for (ft = fr_availfuncs; ft->ipfu_addr != NULL; ft++) 46177c478bd9Sstevel@tonic-gate if (ft->ipfu_addr == funcptr) 46187c478bd9Sstevel@tonic-gate return funcptr; 46197c478bd9Sstevel@tonic-gate return NULL; 46207c478bd9Sstevel@tonic-gate } 46217c478bd9Sstevel@tonic-gate 46227c478bd9Sstevel@tonic-gate 46237c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 46247c478bd9Sstevel@tonic-gate /* Function: fr_resolvefunc */ 46257c478bd9Sstevel@tonic-gate /* Returns: int - 0 == success, else error */ 46267c478bd9Sstevel@tonic-gate /* Parameters: data(IO) - ioctl data pointer to ipfunc_resolve_t struct */ 46277c478bd9Sstevel@tonic-gate /* */ 46287c478bd9Sstevel@tonic-gate /* Copy in a ipfunc_resolve_t structure and then fill in the missing field. */ 46297c478bd9Sstevel@tonic-gate /* This will either be the function name (if the pointer is set) or the */ 4630ab25eeb5Syz /* function pointer if the name is set. When found, fill in the other one */ 4631ab25eeb5Syz /* so that the entire, complete, structure can be copied back to user space.*/ 46327c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 46337c478bd9Sstevel@tonic-gate int fr_resolvefunc(data) 46347c478bd9Sstevel@tonic-gate void *data; 46357c478bd9Sstevel@tonic-gate { 46367c478bd9Sstevel@tonic-gate ipfunc_resolve_t res, *ft; 46377c478bd9Sstevel@tonic-gate 4638ab25eeb5Syz BCOPYIN(data, &res, sizeof(res)); 46397c478bd9Sstevel@tonic-gate 46407c478bd9Sstevel@tonic-gate if (res.ipfu_addr == NULL && res.ipfu_name[0] != '\0') { 46417c478bd9Sstevel@tonic-gate for (ft = fr_availfuncs; ft->ipfu_addr != NULL; ft++) 46427c478bd9Sstevel@tonic-gate if (strncmp(res.ipfu_name, ft->ipfu_name, 46437c478bd9Sstevel@tonic-gate sizeof(res.ipfu_name)) == 0) { 46447c478bd9Sstevel@tonic-gate res.ipfu_addr = ft->ipfu_addr; 46457c478bd9Sstevel@tonic-gate res.ipfu_init = ft->ipfu_init; 46467c478bd9Sstevel@tonic-gate if (COPYOUT(&res, data, sizeof(res)) != 0) 46477c478bd9Sstevel@tonic-gate return EFAULT; 46487c478bd9Sstevel@tonic-gate return 0; 46497c478bd9Sstevel@tonic-gate } 46507c478bd9Sstevel@tonic-gate } 46517c478bd9Sstevel@tonic-gate if (res.ipfu_addr != NULL && res.ipfu_name[0] == '\0') { 46527c478bd9Sstevel@tonic-gate for (ft = fr_availfuncs; ft->ipfu_addr != NULL; ft++) 46537c478bd9Sstevel@tonic-gate if (ft->ipfu_addr == res.ipfu_addr) { 46547c478bd9Sstevel@tonic-gate (void) strncpy(res.ipfu_name, ft->ipfu_name, 4655ab25eeb5Syz sizeof(res.ipfu_name)); 46567c478bd9Sstevel@tonic-gate res.ipfu_init = ft->ipfu_init; 46577c478bd9Sstevel@tonic-gate if (COPYOUT(&res, data, sizeof(res)) != 0) 46587c478bd9Sstevel@tonic-gate return EFAULT; 46597c478bd9Sstevel@tonic-gate return 0; 46607c478bd9Sstevel@tonic-gate } 46617c478bd9Sstevel@tonic-gate } 46627c478bd9Sstevel@tonic-gate return ESRCH; 46637c478bd9Sstevel@tonic-gate } 46647c478bd9Sstevel@tonic-gate 46657c478bd9Sstevel@tonic-gate 4666ab25eeb5Syz #if !defined(_KERNEL) || (!defined(__NetBSD__) && !defined(__OpenBSD__) && !defined(__FreeBSD__)) || \ 4667ab25eeb5Syz (defined(__FreeBSD__) && (__FreeBSD_version < 490000)) || \ 4668ab25eeb5Syz (defined(__NetBSD__) && (__NetBSD_Version__ < 105000000)) || \ 4669ab25eeb5Syz (defined(__OpenBSD__) && (OpenBSD < 200006)) 46707c478bd9Sstevel@tonic-gate /* 46717c478bd9Sstevel@tonic-gate * From: NetBSD 46727c478bd9Sstevel@tonic-gate * ppsratecheck(): packets (or events) per second limitation. 46737c478bd9Sstevel@tonic-gate */ 46747c478bd9Sstevel@tonic-gate int 46757c478bd9Sstevel@tonic-gate ppsratecheck(lasttime, curpps, maxpps) 46767c478bd9Sstevel@tonic-gate struct timeval *lasttime; 46777c478bd9Sstevel@tonic-gate int *curpps; 46787c478bd9Sstevel@tonic-gate int maxpps; /* maximum pps allowed */ 46797c478bd9Sstevel@tonic-gate { 46807c478bd9Sstevel@tonic-gate struct timeval tv, delta; 46817c478bd9Sstevel@tonic-gate int rv; 46827c478bd9Sstevel@tonic-gate 46837c478bd9Sstevel@tonic-gate GETKTIME(&tv); 46847c478bd9Sstevel@tonic-gate 46857c478bd9Sstevel@tonic-gate delta.tv_sec = tv.tv_sec - lasttime->tv_sec; 46867c478bd9Sstevel@tonic-gate delta.tv_usec = tv.tv_usec - lasttime->tv_usec; 46877c478bd9Sstevel@tonic-gate if (delta.tv_usec < 0) { 46887c478bd9Sstevel@tonic-gate delta.tv_sec--; 46897c478bd9Sstevel@tonic-gate delta.tv_usec += 1000000; 46907c478bd9Sstevel@tonic-gate } 46917c478bd9Sstevel@tonic-gate 46927c478bd9Sstevel@tonic-gate /* 46937c478bd9Sstevel@tonic-gate * check for 0,0 is so that the message will be seen at least once. 46947c478bd9Sstevel@tonic-gate * if more than one second have passed since the last update of 46957c478bd9Sstevel@tonic-gate * lasttime, reset the counter. 46967c478bd9Sstevel@tonic-gate * 46977c478bd9Sstevel@tonic-gate * we do increment *curpps even in *curpps < maxpps case, as some may 46987c478bd9Sstevel@tonic-gate * try to use *curpps for stat purposes as well. 46997c478bd9Sstevel@tonic-gate */ 47007c478bd9Sstevel@tonic-gate if ((lasttime->tv_sec == 0 && lasttime->tv_usec == 0) || 47017c478bd9Sstevel@tonic-gate delta.tv_sec >= 1) { 47027c478bd9Sstevel@tonic-gate *lasttime = tv; 47037c478bd9Sstevel@tonic-gate *curpps = 0; 47047c478bd9Sstevel@tonic-gate rv = 1; 47057c478bd9Sstevel@tonic-gate } else if (maxpps < 0) 47067c478bd9Sstevel@tonic-gate rv = 1; 47077c478bd9Sstevel@tonic-gate else if (*curpps < maxpps) 47087c478bd9Sstevel@tonic-gate rv = 1; 47097c478bd9Sstevel@tonic-gate else 47107c478bd9Sstevel@tonic-gate rv = 0; 47117c478bd9Sstevel@tonic-gate *curpps = *curpps + 1; 47127c478bd9Sstevel@tonic-gate 47137c478bd9Sstevel@tonic-gate return (rv); 47147c478bd9Sstevel@tonic-gate } 47157c478bd9Sstevel@tonic-gate #endif 47167c478bd9Sstevel@tonic-gate 47177c478bd9Sstevel@tonic-gate 47187c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 47197c478bd9Sstevel@tonic-gate /* Function: fr_derefrule */ 47207c478bd9Sstevel@tonic-gate /* Returns: int - 0 == rule freed up, else rule not freed */ 47217c478bd9Sstevel@tonic-gate /* Parameters: fr(I) - pointer to filter rule */ 47227c478bd9Sstevel@tonic-gate /* */ 47237c478bd9Sstevel@tonic-gate /* Decrement the reference counter to a rule by one. If it reaches zero, */ 47247c478bd9Sstevel@tonic-gate /* free it and any associated storage space being used by it. */ 47257c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 47267c478bd9Sstevel@tonic-gate int fr_derefrule(frp) 47277c478bd9Sstevel@tonic-gate frentry_t **frp; 47287c478bd9Sstevel@tonic-gate { 47297c478bd9Sstevel@tonic-gate frentry_t *fr; 47307c478bd9Sstevel@tonic-gate 47317c478bd9Sstevel@tonic-gate fr = *frp; 47327c478bd9Sstevel@tonic-gate 47337c478bd9Sstevel@tonic-gate MUTEX_ENTER(&fr->fr_lock); 47347c478bd9Sstevel@tonic-gate fr->fr_ref--; 47357c478bd9Sstevel@tonic-gate if (fr->fr_ref == 0) { 47367c478bd9Sstevel@tonic-gate MUTEX_EXIT(&fr->fr_lock); 47377c478bd9Sstevel@tonic-gate MUTEX_DESTROY(&fr->fr_lock); 47387c478bd9Sstevel@tonic-gate 47397c478bd9Sstevel@tonic-gate #ifdef IPFILTER_LOOKUP 47407c478bd9Sstevel@tonic-gate if (fr->fr_type == FR_T_IPF && fr->fr_satype == FRI_LOOKUP) 47417c478bd9Sstevel@tonic-gate ip_lookup_deref(fr->fr_srctype, fr->fr_srcptr); 47427c478bd9Sstevel@tonic-gate if (fr->fr_type == FR_T_IPF && fr->fr_datype == FRI_LOOKUP) 47437c478bd9Sstevel@tonic-gate ip_lookup_deref(fr->fr_dsttype, fr->fr_dstptr); 47447c478bd9Sstevel@tonic-gate #endif 47457c478bd9Sstevel@tonic-gate 47467c478bd9Sstevel@tonic-gate if (fr->fr_dsize) { 47477c478bd9Sstevel@tonic-gate KFREES(fr->fr_data, fr->fr_dsize); 47487c478bd9Sstevel@tonic-gate } 47497c478bd9Sstevel@tonic-gate if ((fr->fr_flags & FR_COPIED) != 0) { 47507c478bd9Sstevel@tonic-gate KFREE(fr); 47517c478bd9Sstevel@tonic-gate return 0; 47527c478bd9Sstevel@tonic-gate } 47537c478bd9Sstevel@tonic-gate return 1; 47547c478bd9Sstevel@tonic-gate } else { 47557c478bd9Sstevel@tonic-gate MUTEX_EXIT(&fr->fr_lock); 47567c478bd9Sstevel@tonic-gate } 47577c478bd9Sstevel@tonic-gate *frp = NULL; 47587c478bd9Sstevel@tonic-gate return -1; 47597c478bd9Sstevel@tonic-gate } 47607c478bd9Sstevel@tonic-gate 47617c478bd9Sstevel@tonic-gate 47627c478bd9Sstevel@tonic-gate #ifdef IPFILTER_LOOKUP 47637c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 47647c478bd9Sstevel@tonic-gate /* Function: fr_grpmapinit */ 47657c478bd9Sstevel@tonic-gate /* Returns: int - 0 == success, else ESRCH because table entry not found*/ 47667c478bd9Sstevel@tonic-gate /* Parameters: fr(I) - pointer to rule to find hash table for */ 47677c478bd9Sstevel@tonic-gate /* */ 47687c478bd9Sstevel@tonic-gate /* Looks for group hash table fr_arg and stores a pointer to it in fr_ptr. */ 47697c478bd9Sstevel@tonic-gate /* fr_ptr is later used by fr_srcgrpmap and fr_dstgrpmap. */ 47707c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 47717c478bd9Sstevel@tonic-gate static int fr_grpmapinit(fr) 47727c478bd9Sstevel@tonic-gate frentry_t *fr; 47737c478bd9Sstevel@tonic-gate { 47747c478bd9Sstevel@tonic-gate char name[FR_GROUPLEN]; 47757c478bd9Sstevel@tonic-gate iphtable_t *iph; 47767c478bd9Sstevel@tonic-gate 4777ab25eeb5Syz #if defined(SNPRINTF) && defined(_KERNEL) 4778ab25eeb5Syz (void) SNPRINTF(name, sizeof(name), "%d", fr->fr_arg); 4779ab25eeb5Syz #else 47807c478bd9Sstevel@tonic-gate (void) sprintf(name, "%d", fr->fr_arg); 4781ab25eeb5Syz #endif 47827c478bd9Sstevel@tonic-gate iph = fr_findhtable(IPL_LOGIPF, name); 47837c478bd9Sstevel@tonic-gate if (iph == NULL) 47847c478bd9Sstevel@tonic-gate return ESRCH; 47857c478bd9Sstevel@tonic-gate if ((iph->iph_flags & FR_INOUT) != (fr->fr_flags & FR_INOUT)) 47867c478bd9Sstevel@tonic-gate return ESRCH; 47877c478bd9Sstevel@tonic-gate fr->fr_ptr = iph; 47887c478bd9Sstevel@tonic-gate return 0; 47897c478bd9Sstevel@tonic-gate } 47907c478bd9Sstevel@tonic-gate 47917c478bd9Sstevel@tonic-gate 47927c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 47937c478bd9Sstevel@tonic-gate /* Function: fr_srcgrpmap */ 47947c478bd9Sstevel@tonic-gate /* Returns: frentry_t * - pointer to "new last matching" rule or NULL */ 47957c478bd9Sstevel@tonic-gate /* Parameters: fin(I) - pointer to packet information */ 47967c478bd9Sstevel@tonic-gate /* passp(IO) - pointer to current/new filter decision (unused) */ 47977c478bd9Sstevel@tonic-gate /* */ 47987c478bd9Sstevel@tonic-gate /* Look for a rule group head in a hash table, using the source address as */ 47997c478bd9Sstevel@tonic-gate /* the key, and descend into that group and continue matching rules against */ 48007c478bd9Sstevel@tonic-gate /* the packet. */ 48017c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 48027c478bd9Sstevel@tonic-gate frentry_t *fr_srcgrpmap(fin, passp) 48037c478bd9Sstevel@tonic-gate fr_info_t *fin; 48047c478bd9Sstevel@tonic-gate u_32_t *passp; 48057c478bd9Sstevel@tonic-gate { 48067c478bd9Sstevel@tonic-gate frgroup_t *fg; 48077c478bd9Sstevel@tonic-gate void *rval; 48087c478bd9Sstevel@tonic-gate 48097663b816Sml rval = fr_iphmfindgroup(fin->fin_fr->fr_ptr, fin->fin_v, &fin->fin_src); 48107c478bd9Sstevel@tonic-gate if (rval == NULL) 48117c478bd9Sstevel@tonic-gate return NULL; 48127c478bd9Sstevel@tonic-gate 48137c478bd9Sstevel@tonic-gate fg = rval; 48147c478bd9Sstevel@tonic-gate fin->fin_fr = fg->fg_start; 4815ab25eeb5Syz (void) fr_scanlist(fin, *passp); 48167c478bd9Sstevel@tonic-gate return fin->fin_fr; 48177c478bd9Sstevel@tonic-gate } 48187c478bd9Sstevel@tonic-gate 48197c478bd9Sstevel@tonic-gate 48207c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 48217c478bd9Sstevel@tonic-gate /* Function: fr_dstgrpmap */ 48227c478bd9Sstevel@tonic-gate /* Returns: frentry_t * - pointer to "new last matching" rule or NULL */ 48237c478bd9Sstevel@tonic-gate /* Parameters: fin(I) - pointer to packet information */ 48247c478bd9Sstevel@tonic-gate /* passp(IO) - pointer to current/new filter decision (unused) */ 48257c478bd9Sstevel@tonic-gate /* */ 48267c478bd9Sstevel@tonic-gate /* Look for a rule group head in a hash table, using the destination */ 48277c478bd9Sstevel@tonic-gate /* address as the key, and descend into that group and continue matching */ 48287c478bd9Sstevel@tonic-gate /* rules against the packet. */ 48297c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 48307c478bd9Sstevel@tonic-gate frentry_t *fr_dstgrpmap(fin, passp) 48317c478bd9Sstevel@tonic-gate fr_info_t *fin; 48327c478bd9Sstevel@tonic-gate u_32_t *passp; 48337c478bd9Sstevel@tonic-gate { 48347c478bd9Sstevel@tonic-gate frgroup_t *fg; 48357c478bd9Sstevel@tonic-gate void *rval; 48367c478bd9Sstevel@tonic-gate 48377663b816Sml rval = fr_iphmfindgroup(fin->fin_fr->fr_ptr, fin->fin_v, &fin->fin_dst); 48387c478bd9Sstevel@tonic-gate if (rval == NULL) 48397c478bd9Sstevel@tonic-gate return NULL; 48407c478bd9Sstevel@tonic-gate 48417c478bd9Sstevel@tonic-gate fg = rval; 48427c478bd9Sstevel@tonic-gate fin->fin_fr = fg->fg_start; 4843ab25eeb5Syz (void) fr_scanlist(fin, *passp); 48447c478bd9Sstevel@tonic-gate return fin->fin_fr; 48457c478bd9Sstevel@tonic-gate } 48467c478bd9Sstevel@tonic-gate #endif /* IPFILTER_LOOKUP */ 48477c478bd9Sstevel@tonic-gate 4848ab25eeb5Syz /* 4849ab25eeb5Syz * Queue functions 4850ab25eeb5Syz * =============== 4851ab25eeb5Syz * These functions manage objects on queues for efficient timeouts. There are 4852ab25eeb5Syz * a number of system defined queues as well as user defined timeouts. It is 4853ab25eeb5Syz * expected that a lock is held in the domain in which the queue belongs 4854ab25eeb5Syz * (i.e. either state or NAT) when calling any of these functions that prevents 4855ab25eeb5Syz * fr_freetimeoutqueue() from being called at the same time as any other. 4856ab25eeb5Syz */ 4857ab25eeb5Syz 48587c478bd9Sstevel@tonic-gate 48597c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 48607c478bd9Sstevel@tonic-gate /* Function: fr_addtimeoutqueue */ 48617c478bd9Sstevel@tonic-gate /* Returns: struct ifqtq * - NULL if malloc fails, else pointer to */ 48627c478bd9Sstevel@tonic-gate /* timeout queue with given interval. */ 48637c478bd9Sstevel@tonic-gate /* Parameters: parent(I) - pointer to pointer to parent node of this list */ 48647c478bd9Sstevel@tonic-gate /* of interface queues. */ 48657c478bd9Sstevel@tonic-gate /* seconds(I) - timeout value in seconds for this queue. */ 48667c478bd9Sstevel@tonic-gate /* */ 48677c478bd9Sstevel@tonic-gate /* This routine first looks for a timeout queue that matches the interval */ 48687c478bd9Sstevel@tonic-gate /* being requested. If it finds one, increments the reference counter and */ 48697c478bd9Sstevel@tonic-gate /* returns a pointer to it. If none are found, it allocates a new one and */ 48707c478bd9Sstevel@tonic-gate /* inserts it at the top of the list. */ 4871ab25eeb5Syz /* */ 4872ab25eeb5Syz /* Locking. */ 4873ab25eeb5Syz /* It is assumed that the caller of this function has an appropriate lock */ 4874ab25eeb5Syz /* held (exclusively) in the domain that encompases 'parent'. */ 48757c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 48767c478bd9Sstevel@tonic-gate ipftq_t *fr_addtimeoutqueue(parent, seconds) 48777c478bd9Sstevel@tonic-gate ipftq_t **parent; 48787c478bd9Sstevel@tonic-gate u_int seconds; 48797c478bd9Sstevel@tonic-gate { 48807c478bd9Sstevel@tonic-gate ipftq_t *ifq; 4881ab25eeb5Syz u_int period; 48827c478bd9Sstevel@tonic-gate 48837c478bd9Sstevel@tonic-gate period = seconds * IPF_HZ_DIVIDE; 4884ab25eeb5Syz 48857c478bd9Sstevel@tonic-gate MUTEX_ENTER(&ipf_timeoutlock); 4886ab25eeb5Syz for (ifq = *parent; ifq != NULL; ifq = ifq->ifq_next) { 4887ab25eeb5Syz if (ifq->ifq_ttl == period) { 4888ab25eeb5Syz /* 4889ab25eeb5Syz * Reset the delete flag, if set, so the structure 4890ab25eeb5Syz * gets reused rather than freed and reallocated. 4891ab25eeb5Syz */ 4892ab25eeb5Syz MUTEX_ENTER(&ifq->ifq_lock); 4893ab25eeb5Syz ifq->ifq_flags &= ~IFQF_DELETE; 4894ab25eeb5Syz ifq->ifq_ref++; 4895ab25eeb5Syz MUTEX_EXIT(&ifq->ifq_lock); 4896ab25eeb5Syz MUTEX_EXIT(&ipf_timeoutlock); 48977c478bd9Sstevel@tonic-gate 4898ab25eeb5Syz return ifq; 4899ab25eeb5Syz } 49007c478bd9Sstevel@tonic-gate } 49017c478bd9Sstevel@tonic-gate 49027c478bd9Sstevel@tonic-gate KMALLOC(ifq, ipftq_t *); 49037c478bd9Sstevel@tonic-gate if (ifq != NULL) { 49047c478bd9Sstevel@tonic-gate ifq->ifq_ttl = period; 49057c478bd9Sstevel@tonic-gate ifq->ifq_head = NULL; 49067c478bd9Sstevel@tonic-gate ifq->ifq_tail = &ifq->ifq_head; 49077c478bd9Sstevel@tonic-gate ifq->ifq_next = *parent; 49087c478bd9Sstevel@tonic-gate ifq->ifq_pnext = parent; 49097c478bd9Sstevel@tonic-gate ifq->ifq_ref = 1; 49107c478bd9Sstevel@tonic-gate ifq->ifq_flags = IFQF_USER; 49117c478bd9Sstevel@tonic-gate *parent = ifq; 49127c478bd9Sstevel@tonic-gate fr_userifqs++; 49137c478bd9Sstevel@tonic-gate MUTEX_NUKE(&ifq->ifq_lock); 49147c478bd9Sstevel@tonic-gate MUTEX_INIT(&ifq->ifq_lock, "ipftq mutex"); 49157c478bd9Sstevel@tonic-gate } 49167c478bd9Sstevel@tonic-gate MUTEX_EXIT(&ipf_timeoutlock); 49177c478bd9Sstevel@tonic-gate return ifq; 49187c478bd9Sstevel@tonic-gate } 49197c478bd9Sstevel@tonic-gate 49207c478bd9Sstevel@tonic-gate 49217c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 49227c478bd9Sstevel@tonic-gate /* Function: fr_deletetimeoutqueue */ 4923ab25eeb5Syz /* Returns: int - new reference count value of the timeout queue */ 4924ab25eeb5Syz /* Parameters: ifq(I) - timeout queue which is losing a reference. */ 4925ab25eeb5Syz /* Locks: ifq->ifq_lock */ 49267c478bd9Sstevel@tonic-gate /* */ 49277c478bd9Sstevel@tonic-gate /* This routine must be called when we're discarding a pointer to a timeout */ 4928ab25eeb5Syz /* queue object, taking care of the reference counter. */ 4929ab25eeb5Syz /* */ 4930ab25eeb5Syz /* Now that this just sets a DELETE flag, it requires the expire code to */ 4931ab25eeb5Syz /* check the list of user defined timeout queues and call the free function */ 4932ab25eeb5Syz /* below (currently commented out) to stop memory leaking. It is done this */ 4933ab25eeb5Syz /* way because the locking may not be sufficient to safely do a free when */ 4934ab25eeb5Syz /* this function is called. */ 49357c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 4936ab25eeb5Syz int fr_deletetimeoutqueue(ifq) 49377c478bd9Sstevel@tonic-gate ipftq_t *ifq; 49387c478bd9Sstevel@tonic-gate { 49397c478bd9Sstevel@tonic-gate 49407c478bd9Sstevel@tonic-gate ifq->ifq_ref--; 4941ab25eeb5Syz if ((ifq->ifq_ref == 0) && ((ifq->ifq_flags & IFQF_USER) != 0)) { 4942ab25eeb5Syz ifq->ifq_flags |= IFQF_DELETE; 4943ab25eeb5Syz } 49447c478bd9Sstevel@tonic-gate 4945ab25eeb5Syz return ifq->ifq_ref; 4946ab25eeb5Syz } 4947ab25eeb5Syz 4948ab25eeb5Syz 4949ab25eeb5Syz /* ------------------------------------------------------------------------ */ 4950ab25eeb5Syz /* Function: fr_freetimeoutqueue */ 4951ab25eeb5Syz /* Parameters: ifq(I) - timeout queue which is losing a reference. */ 4952ab25eeb5Syz /* Returns: Nil */ 4953ab25eeb5Syz /* */ 4954ab25eeb5Syz /* Locking: */ 4955ab25eeb5Syz /* It is assumed that the caller of this function has an appropriate lock */ 4956ab25eeb5Syz /* held (exclusively) in the domain that encompases the callers "domain". */ 4957ab25eeb5Syz /* The ifq_lock for this structure should not be held. */ 4958ab25eeb5Syz /* */ 4959ab25eeb5Syz /* Remove a user definde timeout queue from the list of queues it is in and */ 4960ab25eeb5Syz /* tidy up after this is done. */ 4961ab25eeb5Syz /* ------------------------------------------------------------------------ */ 4962ab25eeb5Syz void fr_freetimeoutqueue(ifq) 4963ab25eeb5Syz ipftq_t *ifq; 4964ab25eeb5Syz { 4965ab25eeb5Syz 4966ab25eeb5Syz 4967ab25eeb5Syz if (((ifq->ifq_flags & IFQF_DELETE) == 0) || (ifq->ifq_ref != 0) || 4968ab25eeb5Syz ((ifq->ifq_flags & IFQF_USER) == 0)) { 4969ab25eeb5Syz printf("fr_freetimeoutqueue(%lx) flags 0x%x ttl %d ref %d\n", 4970ab25eeb5Syz (u_long)ifq, ifq->ifq_flags, ifq->ifq_ttl, 4971ab25eeb5Syz ifq->ifq_ref); 4972ab25eeb5Syz return; 49737c478bd9Sstevel@tonic-gate } 4974ab25eeb5Syz 4975ab25eeb5Syz /* 4976ab25eeb5Syz * Remove from its position in the list. 4977ab25eeb5Syz */ 4978ab25eeb5Syz *ifq->ifq_pnext = ifq->ifq_next; 4979ab25eeb5Syz if (ifq->ifq_next != NULL) 4980ab25eeb5Syz ifq->ifq_next->ifq_pnext = ifq->ifq_pnext; 4981ab25eeb5Syz 4982ab25eeb5Syz MUTEX_DESTROY(&ifq->ifq_lock); 4983ab25eeb5Syz fr_userifqs--; 4984ab25eeb5Syz KFREE(ifq); 4985ab25eeb5Syz } 4986ab25eeb5Syz 4987ab25eeb5Syz 4988ab25eeb5Syz /* ------------------------------------------------------------------------ */ 4989ab25eeb5Syz /* Function: fr_deletequeueentry */ 4990ab25eeb5Syz /* Returns: Nil */ 4991ab25eeb5Syz /* Parameters: tqe(I) - timeout queue entry to delete */ 4992ab25eeb5Syz /* ifq(I) - timeout queue to remove entry from */ 4993ab25eeb5Syz /* */ 4994ab25eeb5Syz /* Remove a tail queue entry from its queue and make it an orphan. */ 4995ab25eeb5Syz /* fr_deletetimeoutqueue is called to make sure the reference count on the */ 4996ab25eeb5Syz /* queue is correct. We can't, however, call fr_freetimeoutqueue because */ 4997ab25eeb5Syz /* the correct lock(s) may not be held that would make it safe to do so. */ 4998ab25eeb5Syz /* ------------------------------------------------------------------------ */ 4999ab25eeb5Syz void fr_deletequeueentry(tqe) 5000ab25eeb5Syz ipftqent_t *tqe; 5001ab25eeb5Syz { 5002ab25eeb5Syz ipftq_t *ifq; 5003ab25eeb5Syz 5004ab25eeb5Syz ifq = tqe->tqe_ifq; 5005ab25eeb5Syz if (ifq == NULL) 5006ab25eeb5Syz return; 5007ab25eeb5Syz 5008ab25eeb5Syz MUTEX_ENTER(&ifq->ifq_lock); 5009ab25eeb5Syz 5010ab25eeb5Syz if (tqe->tqe_pnext != NULL) { 5011ab25eeb5Syz *tqe->tqe_pnext = tqe->tqe_next; 5012ab25eeb5Syz if (tqe->tqe_next != NULL) 5013ab25eeb5Syz tqe->tqe_next->tqe_pnext = tqe->tqe_pnext; 5014ab25eeb5Syz else /* we must be the tail anyway */ 5015ab25eeb5Syz ifq->ifq_tail = tqe->tqe_pnext; 5016ab25eeb5Syz 5017ab25eeb5Syz tqe->tqe_pnext = NULL; 5018ab25eeb5Syz tqe->tqe_ifq = NULL; 5019ab25eeb5Syz } 5020ab25eeb5Syz 5021ab25eeb5Syz (void) fr_deletetimeoutqueue(ifq); 5022ab25eeb5Syz 5023ab25eeb5Syz MUTEX_EXIT(&ifq->ifq_lock); 50247c478bd9Sstevel@tonic-gate } 50257c478bd9Sstevel@tonic-gate 50267c478bd9Sstevel@tonic-gate 50277c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 50287c478bd9Sstevel@tonic-gate /* Function: fr_queuefront */ 50297c478bd9Sstevel@tonic-gate /* Returns: Nil */ 5030ab25eeb5Syz /* Parameters: tqe(I) - pointer to timeout queue entry */ 50317c478bd9Sstevel@tonic-gate /* */ 50327c478bd9Sstevel@tonic-gate /* Move a queue entry to the front of the queue, if it isn't already there. */ 50337c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 50347c478bd9Sstevel@tonic-gate void fr_queuefront(tqe) 50357c478bd9Sstevel@tonic-gate ipftqent_t *tqe; 50367c478bd9Sstevel@tonic-gate { 50377c478bd9Sstevel@tonic-gate ipftq_t *ifq; 50387c478bd9Sstevel@tonic-gate 50397c478bd9Sstevel@tonic-gate ifq = tqe->tqe_ifq; 5040ab25eeb5Syz if (ifq == NULL) 5041ab25eeb5Syz return; 50427c478bd9Sstevel@tonic-gate 5043ab25eeb5Syz MUTEX_ENTER(&ifq->ifq_lock); 50447c478bd9Sstevel@tonic-gate if (ifq->ifq_head != tqe) { 50457c478bd9Sstevel@tonic-gate *tqe->tqe_pnext = tqe->tqe_next; 50467c478bd9Sstevel@tonic-gate if (tqe->tqe_next) 50477c478bd9Sstevel@tonic-gate tqe->tqe_next->tqe_pnext = tqe->tqe_pnext; 50487c478bd9Sstevel@tonic-gate else 50497c478bd9Sstevel@tonic-gate ifq->ifq_tail = tqe->tqe_pnext; 50507c478bd9Sstevel@tonic-gate 50517c478bd9Sstevel@tonic-gate tqe->tqe_next = ifq->ifq_head; 50527c478bd9Sstevel@tonic-gate ifq->ifq_head->tqe_pnext = &tqe->tqe_next; 50537c478bd9Sstevel@tonic-gate ifq->ifq_head = tqe; 50547c478bd9Sstevel@tonic-gate tqe->tqe_pnext = &ifq->ifq_head; 50557c478bd9Sstevel@tonic-gate } 5056ab25eeb5Syz MUTEX_EXIT(&ifq->ifq_lock); 50577c478bd9Sstevel@tonic-gate } 50587c478bd9Sstevel@tonic-gate 50597c478bd9Sstevel@tonic-gate 50607c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 50617c478bd9Sstevel@tonic-gate /* Function: fr_queueback */ 50627c478bd9Sstevel@tonic-gate /* Returns: Nil */ 5063ab25eeb5Syz /* Parameters: tqe(I) - pointer to timeout queue entry */ 50647c478bd9Sstevel@tonic-gate /* */ 50657c478bd9Sstevel@tonic-gate /* Move a queue entry to the back of the queue, if it isn't already there. */ 50667c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 50677c478bd9Sstevel@tonic-gate void fr_queueback(tqe) 50687c478bd9Sstevel@tonic-gate ipftqent_t *tqe; 50697c478bd9Sstevel@tonic-gate { 50707c478bd9Sstevel@tonic-gate ipftq_t *ifq; 50717c478bd9Sstevel@tonic-gate 50727c478bd9Sstevel@tonic-gate ifq = tqe->tqe_ifq; 50737663b816Sml if (ifq == NULL) 50747663b816Sml return; 5075ab25eeb5Syz tqe->tqe_die = fr_ticks + ifq->ifq_ttl; 50767c478bd9Sstevel@tonic-gate 5077ab25eeb5Syz MUTEX_ENTER(&ifq->ifq_lock); 5078ab25eeb5Syz if (tqe->tqe_next == NULL) { /* at the end already ? */ 50797c478bd9Sstevel@tonic-gate MUTEX_EXIT(&ifq->ifq_lock); 5080ab25eeb5Syz return; 50817c478bd9Sstevel@tonic-gate } 5082ab25eeb5Syz 5083ab25eeb5Syz /* 5084ab25eeb5Syz * Remove from list 5085ab25eeb5Syz */ 5086ab25eeb5Syz *tqe->tqe_pnext = tqe->tqe_next; 5087ab25eeb5Syz tqe->tqe_next->tqe_pnext = tqe->tqe_pnext; 5088ab25eeb5Syz 5089ab25eeb5Syz /* 5090ab25eeb5Syz * Make it the last entry. 5091ab25eeb5Syz */ 5092ab25eeb5Syz tqe->tqe_next = NULL; 5093ab25eeb5Syz tqe->tqe_pnext = ifq->ifq_tail; 5094ab25eeb5Syz *ifq->ifq_tail = tqe; 5095ab25eeb5Syz ifq->ifq_tail = &tqe->tqe_next; 5096ab25eeb5Syz MUTEX_EXIT(&ifq->ifq_lock); 5097ab25eeb5Syz } 5098ab25eeb5Syz 5099ab25eeb5Syz 5100ab25eeb5Syz /* ------------------------------------------------------------------------ */ 5101ab25eeb5Syz /* Function: fr_queueappend */ 5102ab25eeb5Syz /* Returns: Nil */ 5103ab25eeb5Syz /* Parameters: tqe(I) - pointer to timeout queue entry */ 5104ab25eeb5Syz /* ifq(I) - pointer to timeout queue */ 5105ab25eeb5Syz /* parent(I) - owing object pointer */ 5106ab25eeb5Syz /* */ 5107ab25eeb5Syz /* Add a new item to this queue and put it on the very end. */ 5108ab25eeb5Syz /* ------------------------------------------------------------------------ */ 5109ab25eeb5Syz void fr_queueappend(tqe, ifq, parent) 5110ab25eeb5Syz ipftqent_t *tqe; 5111ab25eeb5Syz ipftq_t *ifq; 5112ab25eeb5Syz void *parent; 5113ab25eeb5Syz { 5114ab25eeb5Syz 5115ab25eeb5Syz MUTEX_ENTER(&ifq->ifq_lock); 5116ab25eeb5Syz tqe->tqe_parent = parent; 5117ab25eeb5Syz tqe->tqe_pnext = ifq->ifq_tail; 5118ab25eeb5Syz *ifq->ifq_tail = tqe; 5119ab25eeb5Syz ifq->ifq_tail = &tqe->tqe_next; 5120ab25eeb5Syz tqe->tqe_next = NULL; 5121ab25eeb5Syz tqe->tqe_ifq = ifq; 5122ab25eeb5Syz tqe->tqe_die = fr_ticks + ifq->ifq_ttl; 5123ab25eeb5Syz ifq->ifq_ref++; 5124ab25eeb5Syz MUTEX_EXIT(&ifq->ifq_lock); 51257c478bd9Sstevel@tonic-gate } 51267c478bd9Sstevel@tonic-gate 51277c478bd9Sstevel@tonic-gate 51287c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 51297c478bd9Sstevel@tonic-gate /* Function: fr_movequeue */ 51307c478bd9Sstevel@tonic-gate /* Returns: Nil */ 51317c478bd9Sstevel@tonic-gate /* Parameters: tq(I) - pointer to timeout queue information */ 51327c478bd9Sstevel@tonic-gate /* oifp(I) - old timeout queue entry was on */ 51337c478bd9Sstevel@tonic-gate /* nifp(I) - new timeout queue to put entry on */ 51347c478bd9Sstevel@tonic-gate /* */ 51357c478bd9Sstevel@tonic-gate /* Move a queue entry from one timeout queue to another timeout queue. */ 51367c478bd9Sstevel@tonic-gate /* If it notices that the current entry is already last and does not need */ 51377c478bd9Sstevel@tonic-gate /* to move queue, the return. */ 51387c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 51397c478bd9Sstevel@tonic-gate void fr_movequeue(tqe, oifq, nifq) 51407c478bd9Sstevel@tonic-gate ipftqent_t *tqe; 51417c478bd9Sstevel@tonic-gate ipftq_t *oifq, *nifq; 51427c478bd9Sstevel@tonic-gate { 51437c478bd9Sstevel@tonic-gate /* 51447c478bd9Sstevel@tonic-gate * Is the operation here going to be a no-op ? 51457c478bd9Sstevel@tonic-gate */ 5146ab25eeb5Syz MUTEX_ENTER(&oifq->ifq_lock); 5147ab25eeb5Syz if (oifq == nifq && *oifq->ifq_tail == tqe) { 5148ab25eeb5Syz MUTEX_EXIT(&oifq->ifq_lock); 51497c478bd9Sstevel@tonic-gate return; 5150ab25eeb5Syz } 51517c478bd9Sstevel@tonic-gate 51527c478bd9Sstevel@tonic-gate /* 51537c478bd9Sstevel@tonic-gate * Remove from the old queue 51547c478bd9Sstevel@tonic-gate */ 51557c478bd9Sstevel@tonic-gate *tqe->tqe_pnext = tqe->tqe_next; 51567c478bd9Sstevel@tonic-gate if (tqe->tqe_next) 51577c478bd9Sstevel@tonic-gate tqe->tqe_next->tqe_pnext = tqe->tqe_pnext; 51587c478bd9Sstevel@tonic-gate else 51597c478bd9Sstevel@tonic-gate oifq->ifq_tail = tqe->tqe_pnext; 51607c478bd9Sstevel@tonic-gate tqe->tqe_next = NULL; 51617c478bd9Sstevel@tonic-gate 51627c478bd9Sstevel@tonic-gate /* 51637c478bd9Sstevel@tonic-gate * If we're moving from one queue to another, release the lock on the 51647c478bd9Sstevel@tonic-gate * old queue and get a lock on the new queue. For user defined queues, 51657c478bd9Sstevel@tonic-gate * if we're moving off it, call delete in case it can now be freed. 51667c478bd9Sstevel@tonic-gate */ 51677c478bd9Sstevel@tonic-gate if (oifq != nifq) { 51687c478bd9Sstevel@tonic-gate tqe->tqe_ifq = NULL; 5169ab25eeb5Syz 5170ab25eeb5Syz (void) fr_deletetimeoutqueue(oifq); 5171ab25eeb5Syz 51727c478bd9Sstevel@tonic-gate MUTEX_EXIT(&oifq->ifq_lock); 51737c478bd9Sstevel@tonic-gate 51747c478bd9Sstevel@tonic-gate MUTEX_ENTER(&nifq->ifq_lock); 5175ab25eeb5Syz 51767c478bd9Sstevel@tonic-gate tqe->tqe_ifq = nifq; 51777c478bd9Sstevel@tonic-gate nifq->ifq_ref++; 51787c478bd9Sstevel@tonic-gate } 51797c478bd9Sstevel@tonic-gate 51807c478bd9Sstevel@tonic-gate /* 51817c478bd9Sstevel@tonic-gate * Add to the bottom of the new queue 51827c478bd9Sstevel@tonic-gate */ 51837c478bd9Sstevel@tonic-gate tqe->tqe_die = fr_ticks + nifq->ifq_ttl; 51847c478bd9Sstevel@tonic-gate tqe->tqe_pnext = nifq->ifq_tail; 51857c478bd9Sstevel@tonic-gate *nifq->ifq_tail = tqe; 51867c478bd9Sstevel@tonic-gate nifq->ifq_tail = &tqe->tqe_next; 51877c478bd9Sstevel@tonic-gate MUTEX_EXIT(&nifq->ifq_lock); 51887c478bd9Sstevel@tonic-gate } 51897c478bd9Sstevel@tonic-gate 51907c478bd9Sstevel@tonic-gate 51917c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 51927c478bd9Sstevel@tonic-gate /* Function: fr_updateipid */ 51937c478bd9Sstevel@tonic-gate /* Returns: int - 0 == success, -1 == error (packet should be droppped) */ 51947c478bd9Sstevel@tonic-gate /* Parameters: fin(I) - pointer to packet information */ 51957c478bd9Sstevel@tonic-gate /* */ 51967c478bd9Sstevel@tonic-gate /* When we are doing NAT, change the IP of every packet to represent a */ 51977c478bd9Sstevel@tonic-gate /* single sequence of packets coming from the host, hiding any host */ 51987c478bd9Sstevel@tonic-gate /* specific sequencing that might otherwise be revealed. If the packet is */ 51997c478bd9Sstevel@tonic-gate /* a fragment, then store the 'new' IPid in the fragment cache and look up */ 52007c478bd9Sstevel@tonic-gate /* the fragment cache for non-leading fragments. If a non-leading fragment */ 52017c478bd9Sstevel@tonic-gate /* has no match in the cache, return an error. */ 52027c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 52037c478bd9Sstevel@tonic-gate static INLINE int fr_updateipid(fin) 52047c478bd9Sstevel@tonic-gate fr_info_t *fin; 52057c478bd9Sstevel@tonic-gate { 52067c478bd9Sstevel@tonic-gate u_short id, ido, sums; 52077c478bd9Sstevel@tonic-gate u_32_t sumd, sum; 52087c478bd9Sstevel@tonic-gate ip_t *ip; 52097c478bd9Sstevel@tonic-gate 52107c478bd9Sstevel@tonic-gate if (fin->fin_off != 0) { 52117c478bd9Sstevel@tonic-gate sum = fr_ipid_knownfrag(fin); 52127c478bd9Sstevel@tonic-gate if (sum == 0xffffffff) 52137c478bd9Sstevel@tonic-gate return -1; 52147c478bd9Sstevel@tonic-gate sum &= 0xffff; 52157c478bd9Sstevel@tonic-gate id = (u_short)sum; 52167c478bd9Sstevel@tonic-gate } else { 52177c478bd9Sstevel@tonic-gate id = fr_nextipid(fin); 52187c478bd9Sstevel@tonic-gate if (fin->fin_off == 0 && (fin->fin_flx & FI_FRAG) != 0) 52197c478bd9Sstevel@tonic-gate (void) fr_ipid_newfrag(fin, (u_32_t)id); 52207c478bd9Sstevel@tonic-gate } 52217c478bd9Sstevel@tonic-gate 52227c478bd9Sstevel@tonic-gate ip = fin->fin_ip; 52237c478bd9Sstevel@tonic-gate ido = ntohs(ip->ip_id); 52247c478bd9Sstevel@tonic-gate if (id == ido) 52257c478bd9Sstevel@tonic-gate return 0; 52267c478bd9Sstevel@tonic-gate ip->ip_id = htons(id); 52277c478bd9Sstevel@tonic-gate CALC_SUMD(ido, id, sumd); /* DESTRUCTIVE MACRO! id,ido change */ 52287c478bd9Sstevel@tonic-gate sum = (~ntohs(ip->ip_sum)) & 0xffff; 52297c478bd9Sstevel@tonic-gate sum += sumd; 52307c478bd9Sstevel@tonic-gate sum = (sum >> 16) + (sum & 0xffff); 52317c478bd9Sstevel@tonic-gate sum = (sum >> 16) + (sum & 0xffff); 52327c478bd9Sstevel@tonic-gate sums = ~(u_short)sum; 52337c478bd9Sstevel@tonic-gate ip->ip_sum = htons(sums); 52347c478bd9Sstevel@tonic-gate return 0; 52357c478bd9Sstevel@tonic-gate } 52367c478bd9Sstevel@tonic-gate 52377c478bd9Sstevel@tonic-gate 52387c478bd9Sstevel@tonic-gate #ifdef NEED_FRGETIFNAME 52397c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 52407c478bd9Sstevel@tonic-gate /* Function: fr_getifname */ 5241ab25eeb5Syz /* Returns: char * - pointer to interface name */ 5242ab25eeb5Syz /* Parameters: ifp(I) - pointer to network interface */ 5243ab25eeb5Syz /* buffer(O) - pointer to where to store interface name */ 52447c478bd9Sstevel@tonic-gate /* */ 5245ab25eeb5Syz /* Constructs an interface name in the buffer passed. The buffer passed is */ 5246ab25eeb5Syz /* expected to be at least LIFNAMSIZ in bytes big. If buffer is passed in */ 5247ab25eeb5Syz /* as a NULL pointer then return a pointer to a static array. */ 52487c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 52497c478bd9Sstevel@tonic-gate char *fr_getifname(ifp, buffer) 52507c478bd9Sstevel@tonic-gate struct ifnet *ifp; 52517c478bd9Sstevel@tonic-gate char *buffer; 52527c478bd9Sstevel@tonic-gate { 5253ab25eeb5Syz static char namebuf[LIFNAMSIZ]; 5254ab25eeb5Syz # if defined(MENTAT) || defined(__FreeBSD__) || defined(__osf__) || \ 5255ab25eeb5Syz defined(__sgi) || defined(linux) || defined(_AIX51) || \ 5256ab25eeb5Syz (defined(sun) && !defined(__SVR4) && !defined(__svr4__)) 52577c478bd9Sstevel@tonic-gate int unit, space; 52587c478bd9Sstevel@tonic-gate char temp[20]; 52597c478bd9Sstevel@tonic-gate char *s; 5260ab25eeb5Syz # endif 52617c478bd9Sstevel@tonic-gate 52627c478bd9Sstevel@tonic-gate if (buffer == NULL) 52637c478bd9Sstevel@tonic-gate buffer = namebuf; 52647c478bd9Sstevel@tonic-gate (void) strncpy(buffer, ifp->if_name, LIFNAMSIZ); 5265ab25eeb5Syz buffer[LIFNAMSIZ - 1] = '\0'; 5266ab25eeb5Syz # if defined(MENTAT) || defined(__FreeBSD__) || defined(__osf__) || \ 5267ab25eeb5Syz defined(__sgi) || defined(_AIX51) || \ 5268ab25eeb5Syz (defined(sun) && !defined(__SVR4) && !defined(__svr4__)) 52697c478bd9Sstevel@tonic-gate for (s = buffer; *s; s++) 52707c478bd9Sstevel@tonic-gate ; 52717c478bd9Sstevel@tonic-gate unit = ifp->if_unit; 52727c478bd9Sstevel@tonic-gate space = LIFNAMSIZ - (s - buffer); 52737c478bd9Sstevel@tonic-gate if (space > 0) { 5274ab25eeb5Syz # if defined(SNPRINTF) && defined(_KERNEL) 5275ab25eeb5Syz (void) SNPRINTF(temp, sizeof(temp), "%d", unit); 5276ab25eeb5Syz # else 52777c478bd9Sstevel@tonic-gate (void) sprintf(temp, "%d", unit); 5278ab25eeb5Syz # endif 52797c478bd9Sstevel@tonic-gate (void) strncpy(s, temp, space); 52807c478bd9Sstevel@tonic-gate } 5281ab25eeb5Syz # endif 52827c478bd9Sstevel@tonic-gate return buffer; 52837c478bd9Sstevel@tonic-gate } 52847c478bd9Sstevel@tonic-gate #endif 52857c478bd9Sstevel@tonic-gate 52867c478bd9Sstevel@tonic-gate 52877c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 52887c478bd9Sstevel@tonic-gate /* Function: fr_ioctlswitch */ 52897c478bd9Sstevel@tonic-gate /* Returns: int - -1 continue processing, else ioctl return value */ 52907c478bd9Sstevel@tonic-gate /* Parameters: unit(I) - device unit opened */ 52917c478bd9Sstevel@tonic-gate /* data(I) - pointer to ioctl data */ 52927c478bd9Sstevel@tonic-gate /* cmd(I) - ioctl command */ 52937c478bd9Sstevel@tonic-gate /* mode(I) - mode value */ 52947c478bd9Sstevel@tonic-gate /* */ 52957c478bd9Sstevel@tonic-gate /* Based on the value of unit, call the appropriate ioctl handler or return */ 52967c478bd9Sstevel@tonic-gate /* EIO if ipfilter is not running. Also checks if write perms are req'd */ 52977c478bd9Sstevel@tonic-gate /* for the device in order to execute the ioctl. */ 52987c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 5299ab25eeb5Syz int fr_ioctlswitch(unit, data, cmd, mode) 53007c478bd9Sstevel@tonic-gate int unit, mode; 5301ab25eeb5Syz ioctlcmd_t cmd; 53027c478bd9Sstevel@tonic-gate void *data; 53037c478bd9Sstevel@tonic-gate { 53047c478bd9Sstevel@tonic-gate int error = 0; 53057c478bd9Sstevel@tonic-gate 53067c478bd9Sstevel@tonic-gate switch (unit) 53077c478bd9Sstevel@tonic-gate { 53087c478bd9Sstevel@tonic-gate case IPL_LOGIPF : 53097c478bd9Sstevel@tonic-gate error = -1; 53107c478bd9Sstevel@tonic-gate break; 53117c478bd9Sstevel@tonic-gate case IPL_LOGNAT : 53127c478bd9Sstevel@tonic-gate if (fr_running > 0) 53137c478bd9Sstevel@tonic-gate error = fr_nat_ioctl(data, cmd, mode); 53147c478bd9Sstevel@tonic-gate else 53157c478bd9Sstevel@tonic-gate error = EIO; 53167c478bd9Sstevel@tonic-gate break; 53177c478bd9Sstevel@tonic-gate case IPL_LOGSTATE : 53187c478bd9Sstevel@tonic-gate if (fr_running > 0) 53197c478bd9Sstevel@tonic-gate error = fr_state_ioctl(data, cmd, mode); 53207c478bd9Sstevel@tonic-gate else 53217c478bd9Sstevel@tonic-gate error = EIO; 53227c478bd9Sstevel@tonic-gate break; 53237c478bd9Sstevel@tonic-gate case IPL_LOGAUTH : 53247c478bd9Sstevel@tonic-gate if (fr_running > 0) { 5325ab25eeb5Syz if ((cmd == (ioctlcmd_t)SIOCADAFR) || 5326ab25eeb5Syz (cmd == (ioctlcmd_t)SIOCRMAFR)) { 53277c478bd9Sstevel@tonic-gate if (!(mode & FWRITE)) { 53287c478bd9Sstevel@tonic-gate error = EPERM; 53297c478bd9Sstevel@tonic-gate } else { 53307c478bd9Sstevel@tonic-gate error = frrequest(unit, cmd, data, 53317c478bd9Sstevel@tonic-gate fr_active, 1); 53327c478bd9Sstevel@tonic-gate } 53337c478bd9Sstevel@tonic-gate } else { 53347c478bd9Sstevel@tonic-gate error = fr_auth_ioctl(data, cmd, mode); 53357c478bd9Sstevel@tonic-gate } 53367c478bd9Sstevel@tonic-gate } else 53377c478bd9Sstevel@tonic-gate error = EIO; 53387c478bd9Sstevel@tonic-gate break; 53397c478bd9Sstevel@tonic-gate case IPL_LOGSYNC : 53407c478bd9Sstevel@tonic-gate #ifdef IPFILTER_SYNC 53417c478bd9Sstevel@tonic-gate if (fr_running > 0) 53427c478bd9Sstevel@tonic-gate error = fr_sync_ioctl(data, cmd, mode); 53437c478bd9Sstevel@tonic-gate else 53447c478bd9Sstevel@tonic-gate #endif 53457c478bd9Sstevel@tonic-gate error = EIO; 53467c478bd9Sstevel@tonic-gate break; 53477c478bd9Sstevel@tonic-gate case IPL_LOGSCAN : 53487c478bd9Sstevel@tonic-gate #ifdef IPFILTER_SCAN 53497c478bd9Sstevel@tonic-gate if (fr_running > 0) 53507c478bd9Sstevel@tonic-gate error = fr_scan_ioctl(data, cmd, mode); 53517c478bd9Sstevel@tonic-gate else 53527c478bd9Sstevel@tonic-gate #endif 53537c478bd9Sstevel@tonic-gate error = EIO; 53547c478bd9Sstevel@tonic-gate break; 53557c478bd9Sstevel@tonic-gate case IPL_LOGLOOKUP : 53567c478bd9Sstevel@tonic-gate #ifdef IPFILTER_LOOKUP 53577c478bd9Sstevel@tonic-gate if (fr_running > 0) 53587c478bd9Sstevel@tonic-gate error = ip_lookup_ioctl(data, cmd, mode); 53597c478bd9Sstevel@tonic-gate else 53607c478bd9Sstevel@tonic-gate #endif 53617c478bd9Sstevel@tonic-gate error = EIO; 53627c478bd9Sstevel@tonic-gate break; 53637c478bd9Sstevel@tonic-gate default : 53647c478bd9Sstevel@tonic-gate error = EIO; 53657c478bd9Sstevel@tonic-gate break; 53667c478bd9Sstevel@tonic-gate } 53677c478bd9Sstevel@tonic-gate 53687c478bd9Sstevel@tonic-gate return error; 53697c478bd9Sstevel@tonic-gate } 53707c478bd9Sstevel@tonic-gate 53717c478bd9Sstevel@tonic-gate 53727c478bd9Sstevel@tonic-gate /* 53737c478bd9Sstevel@tonic-gate * This array defines the expected size of objects coming into the kernel 53747c478bd9Sstevel@tonic-gate * for the various recognised object types. 53757c478bd9Sstevel@tonic-gate */ 5376ab25eeb5Syz #define NUM_OBJ_TYPES 14 5377ab25eeb5Syz 5378ab25eeb5Syz static int fr_objbytes[NUM_OBJ_TYPES][2] = { 5379ab25eeb5Syz { 1, sizeof(struct frentry) }, /* frentry */ 5380ab25eeb5Syz { 0, sizeof(struct friostat) }, 5381ab25eeb5Syz { 0, sizeof(struct fr_info) }, 5382ab25eeb5Syz { 0, sizeof(struct fr_authstat) }, 5383ab25eeb5Syz { 0, sizeof(struct ipfrstat) }, 5384ab25eeb5Syz { 0, sizeof(struct ipnat) }, 5385ab25eeb5Syz { 0, sizeof(struct natstat) }, 5386ab25eeb5Syz { 0, sizeof(struct ipstate_save) }, 5387ab25eeb5Syz { 1, sizeof(struct nat_save) }, /* nat_save */ 5388ab25eeb5Syz { 0, sizeof(struct natlookup) }, 5389ab25eeb5Syz { 1, sizeof(struct ipstate) }, /* ipstate */ 5390ab25eeb5Syz { 0, sizeof(struct ips_stat) }, 5391ab25eeb5Syz { 0, sizeof(struct frauth) }, 5392ab25eeb5Syz { 0, sizeof(struct ipftune) } 53937c478bd9Sstevel@tonic-gate }; 53947c478bd9Sstevel@tonic-gate 53957c478bd9Sstevel@tonic-gate 53967c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 53977c478bd9Sstevel@tonic-gate /* Function: fr_inobj */ 53987c478bd9Sstevel@tonic-gate /* Returns: int - 0 = success, else failure */ 53997c478bd9Sstevel@tonic-gate /* Parameters: data(I) - pointer to ioctl data */ 54007c478bd9Sstevel@tonic-gate /* ptr(I) - pointer to store real data in */ 54017c478bd9Sstevel@tonic-gate /* type(I) - type of structure being moved */ 54027c478bd9Sstevel@tonic-gate /* */ 54037c478bd9Sstevel@tonic-gate /* Copy in the contents of what the ipfobj_t points to. In future, we */ 54047c478bd9Sstevel@tonic-gate /* add things to check for version numbers, sizes, etc, to make it backward */ 54057c478bd9Sstevel@tonic-gate /* compatible at the ABI for user land. */ 54067c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 54077c478bd9Sstevel@tonic-gate int fr_inobj(data, ptr, type) 54087c478bd9Sstevel@tonic-gate void *data; 54097c478bd9Sstevel@tonic-gate void *ptr; 54107c478bd9Sstevel@tonic-gate int type; 54117c478bd9Sstevel@tonic-gate { 54127c478bd9Sstevel@tonic-gate ipfobj_t obj; 54137c478bd9Sstevel@tonic-gate int error = 0; 54147c478bd9Sstevel@tonic-gate 5415ab25eeb5Syz if ((type < 0) || (type > NUM_OBJ_TYPES-1)) 54167c478bd9Sstevel@tonic-gate return EINVAL; 54177c478bd9Sstevel@tonic-gate 5418ab25eeb5Syz BCOPYIN((caddr_t)data, (caddr_t)&obj, sizeof(obj)); 54197c478bd9Sstevel@tonic-gate 54207c478bd9Sstevel@tonic-gate if (obj.ipfo_type != type) 54217c478bd9Sstevel@tonic-gate return EINVAL; 54227c478bd9Sstevel@tonic-gate 54237c478bd9Sstevel@tonic-gate #ifndef IPFILTER_COMPAT 5424ab25eeb5Syz if ((fr_objbytes[type][0] & 1) != 0) { 5425ab25eeb5Syz if (obj.ipfo_size < fr_objbytes[type][1]) 5426ab25eeb5Syz return EINVAL; 5427ab25eeb5Syz } else if (obj.ipfo_size != fr_objbytes[type][1]) 54287c478bd9Sstevel@tonic-gate return EINVAL; 54297c478bd9Sstevel@tonic-gate #else 54307c478bd9Sstevel@tonic-gate if (obj.ipfo_rev != IPFILTER_VERSION) 54317c478bd9Sstevel@tonic-gate /* XXX compatibility hook here */ 5432ab25eeb5Syz ; 5433ab25eeb5Syz if ((fr_objbytes[type][0] & 1) != 0) { 5434ab25eeb5Syz if (obj.ipfo_size < fr_objbytes[type][1]) 5435ab25eeb5Syz /* XXX compatibility hook here */ 5436ab25eeb5Syz return EINVAL; 5437ab25eeb5Syz } else if (obj.ipfo_size != fr_objbytes[type][1]) 54387c478bd9Sstevel@tonic-gate /* XXX compatibility hook here */ 54397c478bd9Sstevel@tonic-gate return EINVAL; 54407c478bd9Sstevel@tonic-gate #endif 54417c478bd9Sstevel@tonic-gate 5442ab25eeb5Syz if ((fr_objbytes[type][0] & 1) != 0) { 5443ab25eeb5Syz error = COPYIN((caddr_t)obj.ipfo_ptr, (caddr_t)ptr, 5444ab25eeb5Syz fr_objbytes[type][1]); 5445ab25eeb5Syz } else { 5446ab25eeb5Syz error = COPYIN((caddr_t)obj.ipfo_ptr, (caddr_t)ptr, 5447ab25eeb5Syz obj.ipfo_size); 5448ab25eeb5Syz } 54497c478bd9Sstevel@tonic-gate return error; 54507c478bd9Sstevel@tonic-gate } 54517c478bd9Sstevel@tonic-gate 54527c478bd9Sstevel@tonic-gate 54537c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 5454ab25eeb5Syz /* Function: fr_inobjsz */ 54557c478bd9Sstevel@tonic-gate /* Returns: int - 0 = success, else failure */ 54567c478bd9Sstevel@tonic-gate /* Parameters: data(I) - pointer to ioctl data */ 54577c478bd9Sstevel@tonic-gate /* ptr(I) - pointer to store real data in */ 54587c478bd9Sstevel@tonic-gate /* type(I) - type of structure being moved */ 5459ab25eeb5Syz /* sz(I) - size of data to copy */ 54607c478bd9Sstevel@tonic-gate /* */ 5461ab25eeb5Syz /* As per fr_inobj, except the size of the object to copy in is passed in */ 5462ab25eeb5Syz /* but it must not be smaller than the size defined for the type and the */ 5463ab25eeb5Syz /* type must allow for varied sized objects. The extra requirement here is */ 5464ab25eeb5Syz /* that sz must match the size of the object being passed in - this is not */ 5465ab25eeb5Syz /* not possible nor required in fr_inobj(). */ 54667c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 5467ab25eeb5Syz int fr_inobjsz(data, ptr, type, sz) 54687c478bd9Sstevel@tonic-gate void *data; 54697c478bd9Sstevel@tonic-gate void *ptr; 5470ab25eeb5Syz int type, sz; 54717c478bd9Sstevel@tonic-gate { 54727c478bd9Sstevel@tonic-gate ipfobj_t obj; 54737c478bd9Sstevel@tonic-gate int error; 54747c478bd9Sstevel@tonic-gate 5475ab25eeb5Syz if ((type < 0) || (type > NUM_OBJ_TYPES-1)) 5476ab25eeb5Syz return EINVAL; 5477ab25eeb5Syz if (((fr_objbytes[type][0] & 1) == 0) || (sz < fr_objbytes[type][1])) 5478ab25eeb5Syz return EINVAL; 5479ab25eeb5Syz 5480ab25eeb5Syz BCOPYIN((caddr_t)data, (caddr_t)&obj, sizeof(obj)); 54817c478bd9Sstevel@tonic-gate 54827c478bd9Sstevel@tonic-gate if (obj.ipfo_type != type) 54837c478bd9Sstevel@tonic-gate return EINVAL; 54847c478bd9Sstevel@tonic-gate 54857c478bd9Sstevel@tonic-gate #ifndef IPFILTER_COMPAT 5486ab25eeb5Syz if (obj.ipfo_size != sz) 54877c478bd9Sstevel@tonic-gate return EINVAL; 54887c478bd9Sstevel@tonic-gate #else 54897c478bd9Sstevel@tonic-gate if (obj.ipfo_rev != IPFILTER_VERSION) 54907c478bd9Sstevel@tonic-gate /* XXX compatibility hook here */ 5491ab25eeb5Syz ; 5492ab25eeb5Syz if (obj.ipfo_size != sz) 54937c478bd9Sstevel@tonic-gate /* XXX compatibility hook here */ 54947c478bd9Sstevel@tonic-gate return EINVAL; 54957c478bd9Sstevel@tonic-gate #endif 54967c478bd9Sstevel@tonic-gate 5497ab25eeb5Syz error = COPYIN((caddr_t)obj.ipfo_ptr, (caddr_t)ptr, sz); 54987c478bd9Sstevel@tonic-gate return error; 54997c478bd9Sstevel@tonic-gate } 55007c478bd9Sstevel@tonic-gate 55017c478bd9Sstevel@tonic-gate 55027c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 5503ab25eeb5Syz /* Function: fr_outobjsz */ 5504ab25eeb5Syz /* Returns: int - 0 = success, else failure */ 5505ab25eeb5Syz /* Parameters: data(I) - pointer to ioctl data */ 5506ab25eeb5Syz /* ptr(I) - pointer to store real data in */ 5507ab25eeb5Syz /* type(I) - type of structure being moved */ 5508ab25eeb5Syz /* sz(I) - size of data to copy */ 55097c478bd9Sstevel@tonic-gate /* */ 5510ab25eeb5Syz /* As per fr_outobj, except the size of the object to copy out is passed in */ 5511ab25eeb5Syz /* but it must not be smaller than the size defined for the type and the */ 5512ab25eeb5Syz /* type must allow for varied sized objects. The extra requirement here is */ 5513ab25eeb5Syz /* that sz must match the size of the object being passed in - this is not */ 5514ab25eeb5Syz /* not possible nor required in fr_outobj(). */ 55157c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 5516ab25eeb5Syz int fr_outobjsz(data, ptr, type, sz) 5517ab25eeb5Syz void *data; 5518ab25eeb5Syz void *ptr; 5519ab25eeb5Syz int type, sz; 55207c478bd9Sstevel@tonic-gate { 5521ab25eeb5Syz ipfobj_t obj; 5522ab25eeb5Syz int error; 55237c478bd9Sstevel@tonic-gate 5524ab25eeb5Syz if ((type < 0) || (type > NUM_OBJ_TYPES-1) || 5525ab25eeb5Syz ((fr_objbytes[type][0] & 1) == 0) || 5526ab25eeb5Syz (sz < fr_objbytes[type][1])) 5527ab25eeb5Syz return EINVAL; 55287c478bd9Sstevel@tonic-gate 5529ab25eeb5Syz BCOPYIN((caddr_t)data, (caddr_t)&obj, sizeof(obj)); 55307c478bd9Sstevel@tonic-gate 5531ab25eeb5Syz if (obj.ipfo_type != type) 5532ab25eeb5Syz return EINVAL; 55337c478bd9Sstevel@tonic-gate 5534ab25eeb5Syz #ifndef IPFILTER_COMPAT 5535ab25eeb5Syz if (obj.ipfo_size != sz) 5536ab25eeb5Syz return EINVAL; 5537ab25eeb5Syz #else 5538ab25eeb5Syz if (obj.ipfo_rev != IPFILTER_VERSION) 5539ab25eeb5Syz /* XXX compatibility hook here */ 5540ab25eeb5Syz ; 5541ab25eeb5Syz if (obj.ipfo_size != sz) 5542ab25eeb5Syz /* XXX compatibility hook here */ 5543ab25eeb5Syz return EINVAL; 55447c478bd9Sstevel@tonic-gate #endif 5545ab25eeb5Syz 5546ab25eeb5Syz error = COPYOUT((caddr_t)ptr, (caddr_t)obj.ipfo_ptr, sz); 5547ab25eeb5Syz return error; 5548ab25eeb5Syz } 5549ab25eeb5Syz 5550ab25eeb5Syz 5551ab25eeb5Syz /* ------------------------------------------------------------------------ */ 5552ab25eeb5Syz /* Function: fr_outobj */ 5553ab25eeb5Syz /* Returns: int - 0 = success, else failure */ 5554ab25eeb5Syz /* Parameters: data(I) - pointer to ioctl data */ 5555ab25eeb5Syz /* ptr(I) - pointer to store real data in */ 5556ab25eeb5Syz /* type(I) - type of structure being moved */ 5557ab25eeb5Syz /* */ 5558ab25eeb5Syz /* Copy out the contents of what ptr is to where ipfobj points to. In */ 5559ab25eeb5Syz /* future, we add things to check for version numbers, sizes, etc, to make */ 5560ab25eeb5Syz /* it backward compatible at the ABI for user land. */ 5561ab25eeb5Syz /* ------------------------------------------------------------------------ */ 5562ab25eeb5Syz int fr_outobj(data, ptr, type) 5563ab25eeb5Syz void *data; 5564ab25eeb5Syz void *ptr; 5565ab25eeb5Syz int type; 5566ab25eeb5Syz { 5567ab25eeb5Syz ipfobj_t obj; 5568ab25eeb5Syz int error; 5569ab25eeb5Syz 5570ab25eeb5Syz if ((type < 0) || (type > NUM_OBJ_TYPES-1)) 5571ab25eeb5Syz return EINVAL; 5572ab25eeb5Syz 5573ab25eeb5Syz BCOPYIN((caddr_t)data, (caddr_t)&obj, sizeof(obj)); 5574ab25eeb5Syz 5575ab25eeb5Syz if (obj.ipfo_type != type) 5576ab25eeb5Syz return EINVAL; 5577ab25eeb5Syz 5578ab25eeb5Syz #ifndef IPFILTER_COMPAT 5579ab25eeb5Syz if ((fr_objbytes[type][0] & 1) != 0) { 5580ab25eeb5Syz if (obj.ipfo_size < fr_objbytes[type][1]) 5581ab25eeb5Syz return EINVAL; 5582ab25eeb5Syz } else if (obj.ipfo_size != fr_objbytes[type][1]) 5583ab25eeb5Syz return EINVAL; 5584ab25eeb5Syz #else 5585ab25eeb5Syz if (obj.ipfo_rev != IPFILTER_VERSION) 5586ab25eeb5Syz /* XXX compatibility hook here */ 5587ab25eeb5Syz ; 5588ab25eeb5Syz if ((fr_objbytes[type][0] & 1) != 0) { 5589ab25eeb5Syz if (obj.ipfo_size < fr_objbytes[type][1]) 5590ab25eeb5Syz /* XXX compatibility hook here */ 5591ab25eeb5Syz return EINVAL; 5592ab25eeb5Syz } else if (obj.ipfo_size != fr_objbytes[type][1]) 5593ab25eeb5Syz /* XXX compatibility hook here */ 5594ab25eeb5Syz return EINVAL; 5595ab25eeb5Syz #endif 5596ab25eeb5Syz 5597ab25eeb5Syz error = COPYOUT((caddr_t)ptr, (caddr_t)obj.ipfo_ptr, obj.ipfo_size); 5598ab25eeb5Syz return error; 5599ab25eeb5Syz } 5600ab25eeb5Syz 5601ab25eeb5Syz 5602ab25eeb5Syz /* ------------------------------------------------------------------------ */ 5603ab25eeb5Syz /* Function: fr_checkl4sum */ 5604ab25eeb5Syz /* Returns: int - 0 = good, -1 = bad, 1 = cannot check */ 5605ab25eeb5Syz /* Parameters: fin(I) - pointer to packet information */ 5606ab25eeb5Syz /* */ 5607ab25eeb5Syz /* If possible, calculate the layer 4 checksum for the packet. If this is */ 5608ab25eeb5Syz /* not possible, return without indicating a failure or success but in a */ 5609ab25eeb5Syz /* way that is ditinguishable. */ 5610ab25eeb5Syz /* ------------------------------------------------------------------------ */ 5611ab25eeb5Syz int fr_checkl4sum(fin) 5612ab25eeb5Syz fr_info_t *fin; 5613ab25eeb5Syz { 5614ab25eeb5Syz u_short sum, hdrsum, *csump; 5615ab25eeb5Syz udphdr_t *udp; 5616ab25eeb5Syz int dosum; 5617ab25eeb5Syz 5618*381a2a9aSdr #if SOLARIS && defined(_KERNEL) && (SOLARIS2 >= 6) 5619*381a2a9aSdr net_data_t net_data_p; 5620*381a2a9aSdr if (fin->fin_v == 4) 5621*381a2a9aSdr net_data_p = ipf_ipv4; 5622*381a2a9aSdr else 5623*381a2a9aSdr net_data_p = ipf_ipv6; 5624*381a2a9aSdr #endif 5625*381a2a9aSdr 5626ab25eeb5Syz if ((fin->fin_flx & FI_NOCKSUM) != 0) 5627ab25eeb5Syz return 0; 5628ab25eeb5Syz 5629ab25eeb5Syz /* 5630ab25eeb5Syz * If the TCP packet isn't a fragment, isn't too short and otherwise 5631ab25eeb5Syz * isn't already considered "bad", then validate the checksum. If 5632ab25eeb5Syz * this check fails then considered the packet to be "bad". 5633ab25eeb5Syz */ 5634ab25eeb5Syz if ((fin->fin_flx & (FI_FRAG|FI_SHORT|FI_BAD)) != 0) 5635ab25eeb5Syz return 1; 5636ab25eeb5Syz 5637ab25eeb5Syz csump = NULL; 5638ab25eeb5Syz hdrsum = 0; 5639ab25eeb5Syz dosum = 0; 5640ab25eeb5Syz sum = 0; 5641ab25eeb5Syz 5642*381a2a9aSdr #if SOLARIS && defined(_KERNEL) && (SOLARIS2 >= 6) 5643*381a2a9aSdr ASSERT(fin->fin_m != NULL); 5644*381a2a9aSdr if (NET_IS_HCK_L4_FULL(net_data_p, fin->fin_m) || 5645*381a2a9aSdr NET_IS_HCK_L4_PART(net_data_p, fin->fin_m)) { 5646*381a2a9aSdr hdrsum = 0; 5647*381a2a9aSdr sum = 0; 5648ab25eeb5Syz } else { 5649ab25eeb5Syz #endif 5650ab25eeb5Syz switch (fin->fin_p) 5651ab25eeb5Syz { 56527c478bd9Sstevel@tonic-gate case IPPROTO_TCP : 56537c478bd9Sstevel@tonic-gate csump = &((tcphdr_t *)fin->fin_dp)->th_sum; 56547c478bd9Sstevel@tonic-gate dosum = 1; 56557c478bd9Sstevel@tonic-gate break; 56567c478bd9Sstevel@tonic-gate 56577c478bd9Sstevel@tonic-gate case IPPROTO_UDP : 56587c478bd9Sstevel@tonic-gate udp = fin->fin_dp; 56597c478bd9Sstevel@tonic-gate if (udp->uh_sum != 0) { 56607c478bd9Sstevel@tonic-gate csump = &udp->uh_sum; 56617c478bd9Sstevel@tonic-gate dosum = 1; 56627c478bd9Sstevel@tonic-gate } 56637c478bd9Sstevel@tonic-gate break; 56647c478bd9Sstevel@tonic-gate 56657c478bd9Sstevel@tonic-gate case IPPROTO_ICMP : 56667c478bd9Sstevel@tonic-gate csump = &((struct icmp *)fin->fin_dp)->icmp_cksum; 56677c478bd9Sstevel@tonic-gate dosum = 1; 56687c478bd9Sstevel@tonic-gate break; 56697c478bd9Sstevel@tonic-gate 56707c478bd9Sstevel@tonic-gate default : 56717c478bd9Sstevel@tonic-gate return 1; 56727c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 56737c478bd9Sstevel@tonic-gate } 56747c478bd9Sstevel@tonic-gate 56757c478bd9Sstevel@tonic-gate if (csump != NULL) 56767c478bd9Sstevel@tonic-gate hdrsum = *csump; 56777c478bd9Sstevel@tonic-gate 56787c478bd9Sstevel@tonic-gate if (dosum) 56797c478bd9Sstevel@tonic-gate sum = fr_cksum(fin->fin_m, fin->fin_ip, 56807c478bd9Sstevel@tonic-gate fin->fin_p, fin->fin_dp); 5681*381a2a9aSdr #if SOLARIS && defined(_KERNEL) && (SOLARIS2 >= 6) 56827c478bd9Sstevel@tonic-gate } 56837c478bd9Sstevel@tonic-gate #endif 56847c478bd9Sstevel@tonic-gate #if !defined(_KERNEL) 5685ab25eeb5Syz if (sum == hdrsum) { 5686ab25eeb5Syz FR_DEBUG(("checkl4sum: %hx == %hx\n", sum, hdrsum)); 5687ab25eeb5Syz } else { 5688ab25eeb5Syz FR_DEBUG(("checkl4sum: %hx != %hx\n", sum, hdrsum)); 5689ab25eeb5Syz } 56907c478bd9Sstevel@tonic-gate #endif 56917c478bd9Sstevel@tonic-gate if (hdrsum == sum) 56927c478bd9Sstevel@tonic-gate return 0; 56937c478bd9Sstevel@tonic-gate return -1; 56947c478bd9Sstevel@tonic-gate } 56957c478bd9Sstevel@tonic-gate 56967c478bd9Sstevel@tonic-gate 56977c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 56987c478bd9Sstevel@tonic-gate /* Function: fr_ifpfillv4addr */ 56997c478bd9Sstevel@tonic-gate /* Returns: int - 0 = address update, -1 = address not updated */ 57007c478bd9Sstevel@tonic-gate /* Parameters: atype(I) - type of network address update to perform */ 57017c478bd9Sstevel@tonic-gate /* sin(I) - pointer to source of address information */ 57027c478bd9Sstevel@tonic-gate /* mask(I) - pointer to source of netmask information */ 57037c478bd9Sstevel@tonic-gate /* inp(I) - pointer to destination address store */ 57047c478bd9Sstevel@tonic-gate /* inpmask(I) - pointer to destination netmask store */ 57057c478bd9Sstevel@tonic-gate /* */ 57067c478bd9Sstevel@tonic-gate /* Given a type of network address update (atype) to perform, copy */ 57077c478bd9Sstevel@tonic-gate /* information from sin/mask into inp/inpmask. If ipnmask is NULL then no */ 57087c478bd9Sstevel@tonic-gate /* netmask update is performed unless FRI_NETMASKED is passed as atype, in */ 57097c478bd9Sstevel@tonic-gate /* which case the operation fails. For all values of atype other than */ 57107c478bd9Sstevel@tonic-gate /* FRI_NETMASKED, if inpmask is non-NULL then the mask is set to an all 1s */ 57117c478bd9Sstevel@tonic-gate /* value. */ 57127c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 57137c478bd9Sstevel@tonic-gate int fr_ifpfillv4addr(atype, sin, mask, inp, inpmask) 57147c478bd9Sstevel@tonic-gate int atype; 57157c478bd9Sstevel@tonic-gate struct sockaddr_in *sin, *mask; 57167c478bd9Sstevel@tonic-gate struct in_addr *inp, *inpmask; 57177c478bd9Sstevel@tonic-gate { 57187c478bd9Sstevel@tonic-gate if (inpmask != NULL && atype != FRI_NETMASKED) 57197c478bd9Sstevel@tonic-gate inpmask->s_addr = 0xffffffff; 57207c478bd9Sstevel@tonic-gate 57217c478bd9Sstevel@tonic-gate if (atype == FRI_NETWORK || atype == FRI_NETMASKED) { 57227c478bd9Sstevel@tonic-gate if (atype == FRI_NETMASKED) { 57237c478bd9Sstevel@tonic-gate if (inpmask == NULL) 57247c478bd9Sstevel@tonic-gate return -1; 57257c478bd9Sstevel@tonic-gate inpmask->s_addr = mask->sin_addr.s_addr; 57267c478bd9Sstevel@tonic-gate } 57277c478bd9Sstevel@tonic-gate inp->s_addr = sin->sin_addr.s_addr & mask->sin_addr.s_addr; 57287c478bd9Sstevel@tonic-gate } else { 57297c478bd9Sstevel@tonic-gate inp->s_addr = sin->sin_addr.s_addr; 57307c478bd9Sstevel@tonic-gate } 57317c478bd9Sstevel@tonic-gate return 0; 57327c478bd9Sstevel@tonic-gate } 57337c478bd9Sstevel@tonic-gate 57347c478bd9Sstevel@tonic-gate 57357c478bd9Sstevel@tonic-gate #ifdef USE_INET6 57367c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 57377c478bd9Sstevel@tonic-gate /* Function: fr_ifpfillv6addr */ 57387c478bd9Sstevel@tonic-gate /* Returns: int - 0 = address update, -1 = address not updated */ 57397c478bd9Sstevel@tonic-gate /* Parameters: atype(I) - type of network address update to perform */ 57407c478bd9Sstevel@tonic-gate /* sin(I) - pointer to source of address information */ 57417c478bd9Sstevel@tonic-gate /* mask(I) - pointer to source of netmask information */ 57427c478bd9Sstevel@tonic-gate /* inp(I) - pointer to destination address store */ 57437c478bd9Sstevel@tonic-gate /* inpmask(I) - pointer to destination netmask store */ 57447c478bd9Sstevel@tonic-gate /* */ 57457c478bd9Sstevel@tonic-gate /* Given a type of network address update (atype) to perform, copy */ 57467c478bd9Sstevel@tonic-gate /* information from sin/mask into inp/inpmask. If ipnmask is NULL then no */ 57477c478bd9Sstevel@tonic-gate /* netmask update is performed unless FRI_NETMASKED is passed as atype, in */ 57487c478bd9Sstevel@tonic-gate /* which case the operation fails. For all values of atype other than */ 57497c478bd9Sstevel@tonic-gate /* FRI_NETMASKED, if inpmask is non-NULL then the mask is set to an all 1s */ 57507c478bd9Sstevel@tonic-gate /* value. */ 57517c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 57527c478bd9Sstevel@tonic-gate int fr_ifpfillv6addr(atype, sin, mask, inp, inpmask) 57537c478bd9Sstevel@tonic-gate int atype; 57547c478bd9Sstevel@tonic-gate struct sockaddr_in6 *sin, *mask; 57557c478bd9Sstevel@tonic-gate struct in_addr *inp, *inpmask; 57567c478bd9Sstevel@tonic-gate { 57577c478bd9Sstevel@tonic-gate i6addr_t *src, *dst, *and, *dmask; 57587c478bd9Sstevel@tonic-gate 57597c478bd9Sstevel@tonic-gate src = (i6addr_t *)&sin->sin6_addr; 57607c478bd9Sstevel@tonic-gate and = (i6addr_t *)&mask->sin6_addr; 57617c478bd9Sstevel@tonic-gate dst = (i6addr_t *)inp; 57627c478bd9Sstevel@tonic-gate dmask = (i6addr_t *)inpmask; 57637c478bd9Sstevel@tonic-gate 57647c478bd9Sstevel@tonic-gate if (inpmask != NULL && atype != FRI_NETMASKED) { 57657c478bd9Sstevel@tonic-gate dmask->i6[0] = 0xffffffff; 57667c478bd9Sstevel@tonic-gate dmask->i6[1] = 0xffffffff; 57677c478bd9Sstevel@tonic-gate dmask->i6[2] = 0xffffffff; 57687c478bd9Sstevel@tonic-gate dmask->i6[3] = 0xffffffff; 57697c478bd9Sstevel@tonic-gate } 57707c478bd9Sstevel@tonic-gate 57717c478bd9Sstevel@tonic-gate if (atype == FRI_NETWORK || atype == FRI_NETMASKED) { 57727c478bd9Sstevel@tonic-gate if (atype == FRI_NETMASKED) { 57737c478bd9Sstevel@tonic-gate if (inpmask == NULL) 57747c478bd9Sstevel@tonic-gate return -1; 57757c478bd9Sstevel@tonic-gate dmask->i6[0] = and->i6[0]; 57767c478bd9Sstevel@tonic-gate dmask->i6[1] = and->i6[1]; 57777c478bd9Sstevel@tonic-gate dmask->i6[2] = and->i6[2]; 57787c478bd9Sstevel@tonic-gate dmask->i6[3] = and->i6[3]; 57797c478bd9Sstevel@tonic-gate } 57807c478bd9Sstevel@tonic-gate 57817c478bd9Sstevel@tonic-gate dst->i6[0] = src->i6[0] & and->i6[0]; 57827c478bd9Sstevel@tonic-gate dst->i6[1] = src->i6[1] & and->i6[1]; 57837c478bd9Sstevel@tonic-gate dst->i6[2] = src->i6[2] & and->i6[2]; 57847c478bd9Sstevel@tonic-gate dst->i6[3] = src->i6[3] & and->i6[3]; 57857c478bd9Sstevel@tonic-gate } else { 57867c478bd9Sstevel@tonic-gate dst->i6[0] = src->i6[0]; 57877c478bd9Sstevel@tonic-gate dst->i6[1] = src->i6[1]; 57887c478bd9Sstevel@tonic-gate dst->i6[2] = src->i6[2]; 57897c478bd9Sstevel@tonic-gate dst->i6[3] = src->i6[3]; 57907c478bd9Sstevel@tonic-gate } 57917c478bd9Sstevel@tonic-gate return 0; 57927c478bd9Sstevel@tonic-gate } 57937c478bd9Sstevel@tonic-gate #endif 57947c478bd9Sstevel@tonic-gate 57957c478bd9Sstevel@tonic-gate 57967c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 57977c478bd9Sstevel@tonic-gate /* Function: fr_matchtag */ 57987c478bd9Sstevel@tonic-gate /* Returns: 0 == mismatch, 1 == match. */ 57997c478bd9Sstevel@tonic-gate /* Parameters: tag1(I) - pointer to first tag to compare */ 58007c478bd9Sstevel@tonic-gate /* tag2(I) - pointer to second tag to compare */ 58017c478bd9Sstevel@tonic-gate /* */ 58027c478bd9Sstevel@tonic-gate /* Returns true (non-zero) or false(0) if the two tag structures can be */ 58037c478bd9Sstevel@tonic-gate /* considered to be a match or not match, respectively. The tag is 16 */ 58047c478bd9Sstevel@tonic-gate /* bytes long (16 characters) but that is overlayed with 4 32bit ints so */ 58057c478bd9Sstevel@tonic-gate /* compare the ints instead, for speed. tag1 is the master of the */ 58067c478bd9Sstevel@tonic-gate /* comparison. This function should only be called with both tag1 and tag2 */ 58077c478bd9Sstevel@tonic-gate /* as non-NULL pointers. */ 58087c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 58097c478bd9Sstevel@tonic-gate int fr_matchtag(tag1, tag2) 58107c478bd9Sstevel@tonic-gate ipftag_t *tag1, *tag2; 58117c478bd9Sstevel@tonic-gate { 58127c478bd9Sstevel@tonic-gate if (tag1 == tag2) 58137c478bd9Sstevel@tonic-gate return 1; 58147c478bd9Sstevel@tonic-gate 58157c478bd9Sstevel@tonic-gate if ((tag1->ipt_num[0] == 0) && (tag2->ipt_num[0] == 0)) 58167c478bd9Sstevel@tonic-gate return 1; 58177c478bd9Sstevel@tonic-gate 58187c478bd9Sstevel@tonic-gate if ((tag1->ipt_num[0] == tag2->ipt_num[0]) && 58197c478bd9Sstevel@tonic-gate (tag1->ipt_num[1] == tag2->ipt_num[1]) && 58207c478bd9Sstevel@tonic-gate (tag1->ipt_num[2] == tag2->ipt_num[2]) && 58217c478bd9Sstevel@tonic-gate (tag1->ipt_num[3] == tag2->ipt_num[3])) 58227c478bd9Sstevel@tonic-gate return 1; 58237c478bd9Sstevel@tonic-gate return 0; 58247c478bd9Sstevel@tonic-gate } 58257c478bd9Sstevel@tonic-gate 58267c478bd9Sstevel@tonic-gate 58277c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 5828ab25eeb5Syz /* Function: fr_coalesce */ 5829ab25eeb5Syz /* Returns: 1 == success, -1 == failure, 0 == no change */ 5830ab25eeb5Syz /* Parameters: fin(I) - pointer to packet information */ 58317c478bd9Sstevel@tonic-gate /* */ 5832ab25eeb5Syz /* Attempt to get all of the packet data into a single, contiguous buffer. */ 5833ab25eeb5Syz /* If this call returns a failure then the buffers have also been freed. */ 5834ab25eeb5Syz /* ------------------------------------------------------------------------ */ 5835ab25eeb5Syz int fr_coalesce(fin) 58367c478bd9Sstevel@tonic-gate fr_info_t *fin; 58377c478bd9Sstevel@tonic-gate { 58387c478bd9Sstevel@tonic-gate if ((fin->fin_flx & FI_COALESCE) != 0) 5839ab25eeb5Syz return 1; 58407c478bd9Sstevel@tonic-gate 5841ab25eeb5Syz /* 5842ab25eeb5Syz * If the mbuf pointers indicate that there is no mbuf to work with, 5843ab25eeb5Syz * return but do not indicate success or failure. 5844ab25eeb5Syz */ 5845ab25eeb5Syz if (fin->fin_m == NULL || fin->fin_mp == NULL) 5846ab25eeb5Syz return 0; 58477c478bd9Sstevel@tonic-gate 5848ab25eeb5Syz #if defined(_KERNEL) 5849ab25eeb5Syz if (fr_pullup(fin->fin_m, fin, fin->fin_plen) == NULL) { 5850ab25eeb5Syz ATOMIC_INCL(fr_badcoalesces[fin->fin_out]); 58517c478bd9Sstevel@tonic-gate # ifdef MENTAT 5852ab25eeb5Syz FREE_MB_T(*fin->fin_mp); 5853ab25eeb5Syz # endif 5854ab25eeb5Syz *fin->fin_mp = NULL; 5855ab25eeb5Syz fin->fin_m = NULL; 5856ab25eeb5Syz return -1; 58577c478bd9Sstevel@tonic-gate } 5858ab25eeb5Syz #else 5859ab25eeb5Syz fin = fin; /* LINT */ 5860ab25eeb5Syz #endif 5861ab25eeb5Syz return 1; 58627c478bd9Sstevel@tonic-gate } 58637c478bd9Sstevel@tonic-gate 58647c478bd9Sstevel@tonic-gate 58657c478bd9Sstevel@tonic-gate /* 58667c478bd9Sstevel@tonic-gate * The following table lists all of the tunable variables that can be 58677c478bd9Sstevel@tonic-gate * accessed via SIOCIPFGET/SIOCIPFSET/SIOCIPFGETNEXt. The format of each row 58687c478bd9Sstevel@tonic-gate * in the table below is as follows: 58697c478bd9Sstevel@tonic-gate * 58707c478bd9Sstevel@tonic-gate * pointer to value, name of value, minimum, maximum, size of the value's 58717c478bd9Sstevel@tonic-gate * container, value attribute flags 58727c478bd9Sstevel@tonic-gate * 58737c478bd9Sstevel@tonic-gate * For convienience, IPFT_RDONLY means the value is read-only, IPFT_WRDISABLED 58747c478bd9Sstevel@tonic-gate * means the value can only be written to when IPFilter is loaded but disabled. 58757c478bd9Sstevel@tonic-gate * The obvious implication is if neither of these are set then the value can be 58767c478bd9Sstevel@tonic-gate * changed at any time without harm. 58777c478bd9Sstevel@tonic-gate */ 58787c478bd9Sstevel@tonic-gate ipftuneable_t ipf_tuneables[] = { 58797c478bd9Sstevel@tonic-gate /* filtering */ 58807c478bd9Sstevel@tonic-gate { { &fr_flags }, "fr_flags", 0, 0xffffffff, 58817c478bd9Sstevel@tonic-gate sizeof(fr_flags), 0 }, 58827c478bd9Sstevel@tonic-gate { { &fr_active }, "fr_active", 0, 0, 58837c478bd9Sstevel@tonic-gate sizeof(fr_active), IPFT_RDONLY }, 58847c478bd9Sstevel@tonic-gate { { &fr_control_forwarding }, "fr_control_forwarding", 0, 1, 58857c478bd9Sstevel@tonic-gate sizeof(fr_control_forwarding), 0 }, 58867c478bd9Sstevel@tonic-gate { { &fr_update_ipid }, "fr_update_ipid", 0, 1, 58877c478bd9Sstevel@tonic-gate sizeof(fr_update_ipid), 0 }, 58887c478bd9Sstevel@tonic-gate { { &fr_chksrc }, "fr_chksrc", 0, 1, 58897c478bd9Sstevel@tonic-gate sizeof(fr_chksrc), 0 }, 5890ab25eeb5Syz { { &fr_minttl }, "fr_minttl", 0, 1, 5891ab25eeb5Syz sizeof(fr_minttl), 0 }, 5892ab25eeb5Syz { { &fr_icmpminfragmtu }, "fr_icmpminfragmtu", 0, 1, 5893ab25eeb5Syz sizeof(fr_icmpminfragmtu), 0 }, 58947c478bd9Sstevel@tonic-gate { { &fr_pass }, "fr_pass", 0, 0xffffffff, 58957c478bd9Sstevel@tonic-gate sizeof(fr_pass), 0 }, 5896*381a2a9aSdr #if SOLARIS2 >= 10 5897*381a2a9aSdr { { &ipf_loopback}, "ipf_loopback", 0, 1, 5898*381a2a9aSdr sizeof(ipf_loopback), IPFT_WRDISABLED }, 5899*381a2a9aSdr #endif 59007c478bd9Sstevel@tonic-gate /* state */ 59017c478bd9Sstevel@tonic-gate { { &fr_tcpidletimeout }, "fr_tcpidletimeout", 1, 0x7fffffff, 59027c478bd9Sstevel@tonic-gate sizeof(fr_tcpidletimeout), IPFT_WRDISABLED }, 59037c478bd9Sstevel@tonic-gate { { &fr_tcpclosewait }, "fr_tcpclosewait", 1, 0x7fffffff, 59047c478bd9Sstevel@tonic-gate sizeof(fr_tcpclosewait), IPFT_WRDISABLED }, 59057c478bd9Sstevel@tonic-gate { { &fr_tcplastack }, "fr_tcplastack", 1, 0x7fffffff, 59067c478bd9Sstevel@tonic-gate sizeof(fr_tcplastack), IPFT_WRDISABLED }, 59077c478bd9Sstevel@tonic-gate { { &fr_tcptimeout }, "fr_tcptimeout", 1, 0x7fffffff, 59087c478bd9Sstevel@tonic-gate sizeof(fr_tcptimeout), IPFT_WRDISABLED }, 59097c478bd9Sstevel@tonic-gate { { &fr_tcpclosed }, "fr_tcpclosed", 1, 0x7fffffff, 59107c478bd9Sstevel@tonic-gate sizeof(fr_tcpclosed), IPFT_WRDISABLED }, 59117c478bd9Sstevel@tonic-gate { { &fr_tcphalfclosed }, "fr_tcphalfclosed", 1, 0x7fffffff, 59127c478bd9Sstevel@tonic-gate sizeof(fr_tcphalfclosed), IPFT_WRDISABLED }, 59137c478bd9Sstevel@tonic-gate { { &fr_udptimeout }, "fr_udptimeout", 1, 0x7fffffff, 59147c478bd9Sstevel@tonic-gate sizeof(fr_udptimeout), IPFT_WRDISABLED }, 59157c478bd9Sstevel@tonic-gate { { &fr_udpacktimeout }, "fr_udpacktimeout", 1, 0x7fffffff, 59167c478bd9Sstevel@tonic-gate sizeof(fr_udpacktimeout), IPFT_WRDISABLED }, 59177c478bd9Sstevel@tonic-gate { { &fr_icmptimeout }, "fr_icmptimeout", 1, 0x7fffffff, 59187c478bd9Sstevel@tonic-gate sizeof(fr_icmptimeout), IPFT_WRDISABLED }, 59197c478bd9Sstevel@tonic-gate { { &fr_icmpacktimeout }, "fr_icmpacktimeout", 1, 0x7fffffff, 59207c478bd9Sstevel@tonic-gate sizeof(fr_icmpacktimeout), IPFT_WRDISABLED }, 5921ab25eeb5Syz { { &fr_iptimeout }, "fr_iptimeout", 1, 0x7fffffff, 5922ab25eeb5Syz sizeof(fr_iptimeout), IPFT_WRDISABLED }, 59237c478bd9Sstevel@tonic-gate { { &fr_statemax }, "fr_statemax", 1, 0x7fffffff, 5924ab25eeb5Syz sizeof(fr_statemax), 0 }, 59257c478bd9Sstevel@tonic-gate { { &fr_statesize }, "fr_statesize", 1, 0x7fffffff, 59267c478bd9Sstevel@tonic-gate sizeof(fr_statesize), IPFT_WRDISABLED }, 59277c478bd9Sstevel@tonic-gate { { &fr_state_lock }, "fr_state_lock", 0, 1, 59287c478bd9Sstevel@tonic-gate sizeof(fr_state_lock), IPFT_RDONLY }, 59297c478bd9Sstevel@tonic-gate { { &fr_state_maxbucket }, "fr_state_maxbucket", 1, 0x7fffffff, 59307c478bd9Sstevel@tonic-gate sizeof(fr_state_maxbucket), IPFT_WRDISABLED }, 59317c478bd9Sstevel@tonic-gate { { &fr_state_maxbucket_reset }, "fr_state_maxbucket_reset", 0, 1, 59327c478bd9Sstevel@tonic-gate sizeof(fr_state_maxbucket_reset), IPFT_WRDISABLED }, 59337c478bd9Sstevel@tonic-gate { { &ipstate_logging }, "ipstate_logging", 0, 1, 59347c478bd9Sstevel@tonic-gate sizeof(ipstate_logging), 0 }, 59357c478bd9Sstevel@tonic-gate /* nat */ 59367c478bd9Sstevel@tonic-gate { { &fr_nat_lock }, "fr_nat_lock", 0, 1, 59377c478bd9Sstevel@tonic-gate sizeof(fr_nat_lock), IPFT_RDONLY }, 59387c478bd9Sstevel@tonic-gate { { &ipf_nattable_sz }, "ipf_nattable_sz", 1, 0x7fffffff, 59397c478bd9Sstevel@tonic-gate sizeof(ipf_nattable_sz), IPFT_WRDISABLED }, 5940ab25eeb5Syz { { &ipf_nattable_max }, "ipf_nattable_max", 1, 0x7fffffff, 5941ab25eeb5Syz sizeof(ipf_nattable_max), 0 }, 59427c478bd9Sstevel@tonic-gate { { &ipf_natrules_sz }, "ipf_natrules_sz", 1, 0x7fffffff, 59437c478bd9Sstevel@tonic-gate sizeof(ipf_natrules_sz), IPFT_WRDISABLED }, 59447c478bd9Sstevel@tonic-gate { { &ipf_rdrrules_sz }, "ipf_rdrrules_sz", 1, 0x7fffffff, 59457c478bd9Sstevel@tonic-gate sizeof(ipf_rdrrules_sz), IPFT_WRDISABLED }, 59467c478bd9Sstevel@tonic-gate { { &ipf_hostmap_sz }, "ipf_hostmap_sz", 1, 0x7fffffff, 59477c478bd9Sstevel@tonic-gate sizeof(ipf_hostmap_sz), IPFT_WRDISABLED }, 59487c478bd9Sstevel@tonic-gate { { &fr_nat_maxbucket }, "fr_nat_maxbucket", 1, 0x7fffffff, 59497c478bd9Sstevel@tonic-gate sizeof(fr_nat_maxbucket), IPFT_WRDISABLED }, 59507c478bd9Sstevel@tonic-gate { { &fr_nat_maxbucket_reset }, "fr_nat_maxbucket_reset", 0, 1, 59517c478bd9Sstevel@tonic-gate sizeof(fr_nat_maxbucket_reset), IPFT_WRDISABLED }, 59527c478bd9Sstevel@tonic-gate { { &nat_logging }, "nat_logging", 0, 1, 59537c478bd9Sstevel@tonic-gate sizeof(nat_logging), 0 }, 59547c478bd9Sstevel@tonic-gate { { &fr_defnatage }, "fr_defnatage", 1, 0x7fffffff, 59557c478bd9Sstevel@tonic-gate sizeof(fr_defnatage), IPFT_WRDISABLED }, 5956ab25eeb5Syz { { &fr_defnatipage }, "fr_defnatipage", 1, 0x7fffffff, 5957ab25eeb5Syz sizeof(fr_defnatipage), IPFT_WRDISABLED }, 59587c478bd9Sstevel@tonic-gate { { &fr_defnaticmpage }, "fr_defnaticmpage", 1, 0x7fffffff, 59597c478bd9Sstevel@tonic-gate sizeof(fr_defnaticmpage), IPFT_WRDISABLED }, 59607c478bd9Sstevel@tonic-gate /* frag */ 59617c478bd9Sstevel@tonic-gate { { &ipfr_size }, "ipfr_size", 1, 0x7fffffff, 59627c478bd9Sstevel@tonic-gate sizeof(ipfr_size), IPFT_WRDISABLED }, 59637c478bd9Sstevel@tonic-gate { { &fr_ipfrttl }, "fr_ipfrttl", 1, 0x7fffffff, 59647c478bd9Sstevel@tonic-gate sizeof(fr_ipfrttl), IPFT_WRDISABLED }, 59657c478bd9Sstevel@tonic-gate #ifdef IPFILTER_LOG 59667c478bd9Sstevel@tonic-gate /* log */ 59677c478bd9Sstevel@tonic-gate { { &ipl_suppress }, "ipl_suppress", 0, 1, 59687c478bd9Sstevel@tonic-gate sizeof(ipl_suppress), 0 }, 59697c478bd9Sstevel@tonic-gate { { &ipl_buffer_sz }, "ipl_buffer_sz", 0, 0, 59707c478bd9Sstevel@tonic-gate sizeof(ipl_buffer_sz), IPFT_RDONLY }, 59717c478bd9Sstevel@tonic-gate { { &ipl_logmax }, "ipl_logmax", 0, 0x7fffffff, 59727c478bd9Sstevel@tonic-gate sizeof(ipl_logmax), IPFT_WRDISABLED }, 59737c478bd9Sstevel@tonic-gate { { &ipl_logall }, "ipl_logall", 0, 1, 59747c478bd9Sstevel@tonic-gate sizeof(ipl_logall), 0 }, 5975ab25eeb5Syz { { &ipl_logsize }, "ipl_logsize", 0, 0x80000, 5976ab25eeb5Syz sizeof(ipl_logsize), 0 }, 59777c478bd9Sstevel@tonic-gate #endif 59787c478bd9Sstevel@tonic-gate { { NULL }, NULL, 0, 0 } 59797c478bd9Sstevel@tonic-gate }; 59807c478bd9Sstevel@tonic-gate 5981ab25eeb5Syz static ipftuneable_t *ipf_tunelist = NULL; 5982ab25eeb5Syz 5983ab25eeb5Syz 5984ab25eeb5Syz /* ------------------------------------------------------------------------ */ 5985ab25eeb5Syz /* Function: fr_findtunebycookie */ 5986ab25eeb5Syz /* Returns: NULL = search failed, else pointer to tune struct */ 5987ab25eeb5Syz /* Parameters: cookie(I) - cookie value to search for amongst tuneables */ 5988ab25eeb5Syz /* next(O) - pointer to place to store the cookie for the */ 5989ab25eeb5Syz /* "next" tuneable, if it is desired. */ 5990ab25eeb5Syz /* */ 5991ab25eeb5Syz /* This function is used to walk through all of the existing tunables with */ 5992ab25eeb5Syz /* successive calls. It searches the known tunables for the one which has */ 5993ab25eeb5Syz /* a matching value for "cookie" - ie its address. When returning a match, */ 5994ab25eeb5Syz /* the next one to be found may be returned inside next. */ 5995ab25eeb5Syz /* ------------------------------------------------------------------------ */ 5996ab25eeb5Syz static ipftuneable_t *fr_findtunebycookie(cookie, next) 5997ab25eeb5Syz void *cookie, **next; 5998ab25eeb5Syz { 5999ab25eeb5Syz ipftuneable_t *ta, **tap; 6000ab25eeb5Syz 6001ab25eeb5Syz for (ta = ipf_tuneables; ta->ipft_name != NULL; ta++) 6002ab25eeb5Syz if (ta == cookie) { 6003ab25eeb5Syz if (next != NULL) { 6004ab25eeb5Syz /* 6005ab25eeb5Syz * If the next entry in the array has a name 6006ab25eeb5Syz * present, then return a pointer to it for 6007ab25eeb5Syz * where to go next, else return a pointer to 6008ab25eeb5Syz * the dynaminc list as a key to search there 6009ab25eeb5Syz * next. This facilitates a weak linking of 6010ab25eeb5Syz * the two "lists" together. 6011ab25eeb5Syz */ 6012ab25eeb5Syz if ((ta + 1)->ipft_name != NULL) 6013ab25eeb5Syz *next = ta + 1; 6014ab25eeb5Syz else 6015ab25eeb5Syz *next = &ipf_tunelist; 6016ab25eeb5Syz } 6017ab25eeb5Syz return ta; 6018ab25eeb5Syz } 6019ab25eeb5Syz 6020ab25eeb5Syz for (tap = &ipf_tunelist; (ta = *tap) != NULL; tap = &ta->ipft_next) 6021ab25eeb5Syz if (tap == cookie) { 6022ab25eeb5Syz if (next != NULL) 6023ab25eeb5Syz *next = &ta->ipft_next; 6024ab25eeb5Syz return ta; 6025ab25eeb5Syz } 6026ab25eeb5Syz 6027ab25eeb5Syz if (next != NULL) 6028ab25eeb5Syz *next = NULL; 6029ab25eeb5Syz return NULL; 6030ab25eeb5Syz } 6031ab25eeb5Syz 6032ab25eeb5Syz 6033ab25eeb5Syz /* ------------------------------------------------------------------------ */ 6034ab25eeb5Syz /* Function: fr_findtunebyname */ 6035ab25eeb5Syz /* Returns: NULL = search failed, else pointer to tune struct */ 6036ab25eeb5Syz /* Parameters: name(I) - name of the tuneable entry to find. */ 6037ab25eeb5Syz /* */ 6038ab25eeb5Syz /* Search the static array of tuneables and the list of dynamic tuneables */ 6039ab25eeb5Syz /* for an entry with a matching name. If we can find one, return a pointer */ 6040ab25eeb5Syz /* to the matching structure. */ 6041ab25eeb5Syz /* ------------------------------------------------------------------------ */ 6042ab25eeb5Syz static ipftuneable_t *fr_findtunebyname(name) 6043ab25eeb5Syz const char *name; 6044ab25eeb5Syz { 6045ab25eeb5Syz ipftuneable_t *ta; 6046ab25eeb5Syz 6047ab25eeb5Syz for (ta = ipf_tuneables; ta->ipft_name != NULL; ta++) 6048ab25eeb5Syz if (!strcmp(ta->ipft_name, name)) { 6049ab25eeb5Syz return ta; 6050ab25eeb5Syz } 6051ab25eeb5Syz 6052ab25eeb5Syz for (ta = ipf_tunelist; ta != NULL; ta = ta->ipft_next) 6053ab25eeb5Syz if (!strcmp(ta->ipft_name, name)) { 6054ab25eeb5Syz return ta; 6055ab25eeb5Syz } 6056ab25eeb5Syz 6057ab25eeb5Syz return NULL; 6058ab25eeb5Syz } 6059ab25eeb5Syz 6060ab25eeb5Syz 6061ab25eeb5Syz /* ------------------------------------------------------------------------ */ 6062ab25eeb5Syz /* Function: fr_addipftune */ 6063ab25eeb5Syz /* Returns: int - 0 == success, else failure */ 6064ab25eeb5Syz /* Parameters: newtune - pointer to new tune struct to add to tuneables */ 6065ab25eeb5Syz /* */ 6066ab25eeb5Syz /* Appends the tune structure pointer to by "newtune" to the end of the */ 6067ab25eeb5Syz /* current list of "dynamic" tuneable parameters. Once added, the owner */ 6068ab25eeb5Syz /* of the object is not expected to ever change "ipft_next". */ 6069ab25eeb5Syz /* ------------------------------------------------------------------------ */ 6070ab25eeb5Syz int fr_addipftune(newtune) 6071ab25eeb5Syz ipftuneable_t *newtune; 6072ab25eeb5Syz { 6073ab25eeb5Syz ipftuneable_t *ta, **tap; 6074ab25eeb5Syz 6075ab25eeb5Syz ta = fr_findtunebyname(newtune->ipft_name); 6076ab25eeb5Syz if (ta != NULL) 6077ab25eeb5Syz return EEXIST; 6078ab25eeb5Syz 6079ab25eeb5Syz for (tap = &ipf_tunelist; *tap != NULL; tap = &(*tap)->ipft_next) 6080ab25eeb5Syz ; 6081ab25eeb5Syz 6082ab25eeb5Syz newtune->ipft_next = NULL; 6083ab25eeb5Syz *tap = newtune; 6084ab25eeb5Syz return 0; 6085ab25eeb5Syz } 6086ab25eeb5Syz 6087ab25eeb5Syz 6088ab25eeb5Syz /* ------------------------------------------------------------------------ */ 6089ab25eeb5Syz /* Function: fr_delipftune */ 6090ab25eeb5Syz /* Returns: int - 0 == success, else failure */ 6091ab25eeb5Syz /* Parameters: oldtune - pointer to tune struct to remove from the list of */ 6092ab25eeb5Syz /* current dynamic tuneables */ 6093ab25eeb5Syz /* */ 6094ab25eeb5Syz /* Search for the tune structure, by pointer, in the list of those that are */ 6095ab25eeb5Syz /* dynamically added at run time. If found, adjust the list so that this */ 6096ab25eeb5Syz /* structure is no longer part of it. */ 6097ab25eeb5Syz /* ------------------------------------------------------------------------ */ 6098ab25eeb5Syz int fr_delipftune(oldtune) 6099ab25eeb5Syz ipftuneable_t *oldtune; 6100ab25eeb5Syz { 6101ab25eeb5Syz ipftuneable_t *ta, **tap; 6102ab25eeb5Syz 6103ab25eeb5Syz for (tap = &ipf_tunelist; (ta = *tap) != NULL; tap = &ta->ipft_next) 6104ab25eeb5Syz if (ta == oldtune) { 6105ab25eeb5Syz *tap = oldtune->ipft_next; 6106ab25eeb5Syz oldtune->ipft_next = NULL; 6107ab25eeb5Syz return 0; 6108ab25eeb5Syz } 6109ab25eeb5Syz 6110ab25eeb5Syz return ESRCH; 6111ab25eeb5Syz } 6112ab25eeb5Syz 61137c478bd9Sstevel@tonic-gate 61147c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 61157c478bd9Sstevel@tonic-gate /* Function: fr_ipftune */ 61167c478bd9Sstevel@tonic-gate /* Returns: int - 0 == success, else failure */ 61177c478bd9Sstevel@tonic-gate /* Parameters: cmd(I) - ioctl command number */ 61187c478bd9Sstevel@tonic-gate /* data(I) - pointer to ioctl data structure */ 61197c478bd9Sstevel@tonic-gate /* */ 61207c478bd9Sstevel@tonic-gate /* Implement handling of SIOCIPFGETNEXT, SIOCIPFGET and SIOCIPFSET. These */ 61217c478bd9Sstevel@tonic-gate /* three ioctls provide the means to access and control global variables */ 61227c478bd9Sstevel@tonic-gate /* within IPFilter, allowing (for example) timeouts and table sizes to be */ 61237c478bd9Sstevel@tonic-gate /* changed without rebooting, reloading or recompiling. The initialisation */ 61247c478bd9Sstevel@tonic-gate /* and 'destruction' routines of the various components of ipfilter are all */ 61257c478bd9Sstevel@tonic-gate /* each responsible for handling their own values being too big. */ 61267c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */ 61277c478bd9Sstevel@tonic-gate int fr_ipftune(cmd, data) 6128ab25eeb5Syz ioctlcmd_t cmd; 6129ab25eeb5Syz void *data; 61307c478bd9Sstevel@tonic-gate { 61317c478bd9Sstevel@tonic-gate ipftuneable_t *ta; 61327c478bd9Sstevel@tonic-gate ipftune_t tu; 61337c478bd9Sstevel@tonic-gate void *cookie; 61347c478bd9Sstevel@tonic-gate int error; 61357c478bd9Sstevel@tonic-gate 61367c478bd9Sstevel@tonic-gate error = fr_inobj(data, &tu, IPFOBJ_TUNEABLE); 61377c478bd9Sstevel@tonic-gate if (error != 0) 61387c478bd9Sstevel@tonic-gate return error; 61397c478bd9Sstevel@tonic-gate 61407c478bd9Sstevel@tonic-gate tu.ipft_name[sizeof(tu.ipft_name) - 1] = '\0'; 61417c478bd9Sstevel@tonic-gate cookie = tu.ipft_cookie; 6142ab25eeb5Syz ta = NULL; 61437c478bd9Sstevel@tonic-gate 61447c478bd9Sstevel@tonic-gate switch (cmd) 61457c478bd9Sstevel@tonic-gate { 61467c478bd9Sstevel@tonic-gate case SIOCIPFGETNEXT : 61477c478bd9Sstevel@tonic-gate /* 61487c478bd9Sstevel@tonic-gate * If cookie is non-NULL, assume it to be a pointer to the last 61497c478bd9Sstevel@tonic-gate * entry we looked at, so find it (if possible) and return a 61507c478bd9Sstevel@tonic-gate * pointer to the next one after it. The last entry in the 61517c478bd9Sstevel@tonic-gate * the table is a NULL entry, so when we get to it, set cookie 61527c478bd9Sstevel@tonic-gate * to NULL and return that, indicating end of list, erstwhile 61537c478bd9Sstevel@tonic-gate * if we come in with cookie set to NULL, we are starting anew 61547c478bd9Sstevel@tonic-gate * at the front of the list. 61557c478bd9Sstevel@tonic-gate */ 61567c478bd9Sstevel@tonic-gate if (cookie != NULL) { 6157ab25eeb5Syz ta = fr_findtunebycookie(cookie, &tu.ipft_cookie); 6158ab25eeb5Syz } else { 6159ab25eeb5Syz ta = ipf_tuneables; 6160ab25eeb5Syz tu.ipft_cookie = ta + 1; 61617c478bd9Sstevel@tonic-gate } 61627c478bd9Sstevel@tonic-gate if (ta != NULL) { 61637c478bd9Sstevel@tonic-gate /* 61647c478bd9Sstevel@tonic-gate * Entry found, but does the data pointed to by that 61657c478bd9Sstevel@tonic-gate * row fit in what we can return? 61667c478bd9Sstevel@tonic-gate */ 61677c478bd9Sstevel@tonic-gate if (ta->ipft_sz > sizeof(tu.ipft_un)) 61687c478bd9Sstevel@tonic-gate return EINVAL; 61697c478bd9Sstevel@tonic-gate 61707c478bd9Sstevel@tonic-gate tu.ipft_vlong = 0; 61717c478bd9Sstevel@tonic-gate if (ta->ipft_sz == sizeof(u_long)) 61727c478bd9Sstevel@tonic-gate tu.ipft_vlong = *ta->ipft_plong; 61737c478bd9Sstevel@tonic-gate else if (ta->ipft_sz == sizeof(u_int)) 61747c478bd9Sstevel@tonic-gate tu.ipft_vint = *ta->ipft_pint; 61757c478bd9Sstevel@tonic-gate else if (ta->ipft_sz == sizeof(u_short)) 61767c478bd9Sstevel@tonic-gate tu.ipft_vshort = *ta->ipft_pshort; 61777c478bd9Sstevel@tonic-gate else if (ta->ipft_sz == sizeof(u_char)) 61787c478bd9Sstevel@tonic-gate tu.ipft_vchar = *ta->ipft_pchar; 61797c478bd9Sstevel@tonic-gate 61807c478bd9Sstevel@tonic-gate tu.ipft_sz = ta->ipft_sz; 61817c478bd9Sstevel@tonic-gate tu.ipft_min = ta->ipft_min; 61827c478bd9Sstevel@tonic-gate tu.ipft_max = ta->ipft_max; 61837c478bd9Sstevel@tonic-gate tu.ipft_flags = ta->ipft_flags; 61847c478bd9Sstevel@tonic-gate bcopy(ta->ipft_name, tu.ipft_name, 61857c478bd9Sstevel@tonic-gate MIN(sizeof(tu.ipft_name), 61867c478bd9Sstevel@tonic-gate strlen(ta->ipft_name) + 1)); 61877c478bd9Sstevel@tonic-gate } 61887c478bd9Sstevel@tonic-gate error = fr_outobj(data, &tu, IPFOBJ_TUNEABLE); 6189ab25eeb5Syz break; 61907c478bd9Sstevel@tonic-gate 61917c478bd9Sstevel@tonic-gate case SIOCIPFGET : 61927c478bd9Sstevel@tonic-gate case SIOCIPFSET : 61937c478bd9Sstevel@tonic-gate /* 61947c478bd9Sstevel@tonic-gate * Search by name or by cookie value for a particular entry 61957c478bd9Sstevel@tonic-gate * in the tuning paramter table. 61967c478bd9Sstevel@tonic-gate */ 6197ab25eeb5Syz error = ESRCH; 61987c478bd9Sstevel@tonic-gate if (cookie != NULL) { 6199ab25eeb5Syz ta = fr_findtunebycookie(cookie, NULL); 6200ab25eeb5Syz if (ta != NULL) 6201ab25eeb5Syz error = 0; 62027c478bd9Sstevel@tonic-gate } else if (tu.ipft_name[0] != '\0') { 6203ab25eeb5Syz ta = fr_findtunebyname(tu.ipft_name); 6204ab25eeb5Syz if (ta != NULL) 6205ab25eeb5Syz error = 0; 6206ab25eeb5Syz } 6207ab25eeb5Syz if (error != 0) 6208ab25eeb5Syz break; 62097c478bd9Sstevel@tonic-gate 6210ab25eeb5Syz if (cmd == (ioctlcmd_t)SIOCIPFGET) { 62117c478bd9Sstevel@tonic-gate /* 62127c478bd9Sstevel@tonic-gate * Fetch the tuning parameters for a particular value 62137c478bd9Sstevel@tonic-gate */ 62147c478bd9Sstevel@tonic-gate tu.ipft_vlong = 0; 62157c478bd9Sstevel@tonic-gate if (ta->ipft_sz == sizeof(u_long)) 62167c478bd9Sstevel@tonic-gate tu.ipft_vlong = *ta->ipft_plong; 62177c478bd9Sstevel@tonic-gate else if (ta->ipft_sz == sizeof(u_int)) 62187c478bd9Sstevel@tonic-gate tu.ipft_vint = *ta->ipft_pint; 62197c478bd9Sstevel@tonic-gate else if (ta->ipft_sz == sizeof(u_short)) 62207c478bd9Sstevel@tonic-gate tu.ipft_vshort = *ta->ipft_pshort; 62217c478bd9Sstevel@tonic-gate else if (ta->ipft_sz == sizeof(u_char)) 62227c478bd9Sstevel@tonic-gate tu.ipft_vchar = *ta->ipft_pchar; 6223ab25eeb5Syz tu.ipft_cookie = ta; 62247c478bd9Sstevel@tonic-gate tu.ipft_sz = ta->ipft_sz; 62257c478bd9Sstevel@tonic-gate tu.ipft_min = ta->ipft_min; 62267c478bd9Sstevel@tonic-gate tu.ipft_max = ta->ipft_max; 62277c478bd9Sstevel@tonic-gate tu.ipft_flags = ta->ipft_flags; 62287c478bd9Sstevel@tonic-gate error = fr_outobj(data, &tu, IPFOBJ_TUNEABLE); 6229ab25eeb5Syz 6230ab25eeb5Syz } else if (cmd == (ioctlcmd_t)SIOCIPFSET) { 62317c478bd9Sstevel@tonic-gate /* 62327c478bd9Sstevel@tonic-gate * Set an internal parameter. The hard part here is 62337c478bd9Sstevel@tonic-gate * getting the new value safely and correctly out of 62347c478bd9Sstevel@tonic-gate * the kernel (given we only know its size, not type.) 62357c478bd9Sstevel@tonic-gate */ 62367c478bd9Sstevel@tonic-gate u_long in; 62377c478bd9Sstevel@tonic-gate 62387c478bd9Sstevel@tonic-gate if (((ta->ipft_flags & IPFT_WRDISABLED) != 0) && 6239ab25eeb5Syz (fr_running > 0)) { 6240ab25eeb5Syz error = EBUSY; 6241ab25eeb5Syz break; 6242ab25eeb5Syz } 62437c478bd9Sstevel@tonic-gate 62447c478bd9Sstevel@tonic-gate in = tu.ipft_vlong; 6245ab25eeb5Syz if (in < ta->ipft_min || in > ta->ipft_max) { 6246ab25eeb5Syz error = EINVAL; 6247ab25eeb5Syz break; 6248ab25eeb5Syz } 62497c478bd9Sstevel@tonic-gate 62507c478bd9Sstevel@tonic-gate if (ta->ipft_sz == sizeof(u_long)) { 62517c478bd9Sstevel@tonic-gate tu.ipft_vlong = *ta->ipft_plong; 62527c478bd9Sstevel@tonic-gate *ta->ipft_plong = in; 62537c478bd9Sstevel@tonic-gate } else if (ta->ipft_sz == sizeof(u_int)) { 62547c478bd9Sstevel@tonic-gate tu.ipft_vint = *ta->ipft_pint; 62557c478bd9Sstevel@tonic-gate *ta->ipft_pint = (u_int)(in & 0xffffffff); 62567c478bd9Sstevel@tonic-gate } else if (ta->ipft_sz == sizeof(u_short)) { 62577c478bd9Sstevel@tonic-gate tu.ipft_vshort = *ta->ipft_pshort; 62587c478bd9Sstevel@tonic-gate *ta->ipft_pshort = (u_short)(in & 0xffff); 62597c478bd9Sstevel@tonic-gate } else if (ta->ipft_sz == sizeof(u_char)) { 62607c478bd9Sstevel@tonic-gate tu.ipft_vchar = *ta->ipft_pchar; 62617c478bd9Sstevel@tonic-gate *ta->ipft_pchar = (u_char)(in & 0xff); 62627c478bd9Sstevel@tonic-gate } 62637c478bd9Sstevel@tonic-gate error = fr_outobj(data, &tu, IPFOBJ_TUNEABLE); 62647c478bd9Sstevel@tonic-gate } 6265ab25eeb5Syz break; 6266ab25eeb5Syz 62677c478bd9Sstevel@tonic-gate default : 6268ab25eeb5Syz error = EINVAL; 62697c478bd9Sstevel@tonic-gate break; 62707c478bd9Sstevel@tonic-gate } 62717c478bd9Sstevel@tonic-gate 6272ab25eeb5Syz return error; 6273ab25eeb5Syz } 6274ab25eeb5Syz 6275ab25eeb5Syz 6276ab25eeb5Syz /* ------------------------------------------------------------------------ */ 6277ab25eeb5Syz /* Function: fr_initialise */ 6278ab25eeb5Syz /* Returns: int - 0 == success, < 0 == failure */ 6279ab25eeb5Syz /* Parameters: None. */ 6280ab25eeb5Syz /* */ 6281ab25eeb5Syz /* Call of the initialise functions for all the various subsystems inside */ 6282ab25eeb5Syz /* of IPFilter. If any of them should fail, return immeadiately a failure */ 6283ab25eeb5Syz /* BUT do not try to recover from the error here. */ 6284ab25eeb5Syz /* ------------------------------------------------------------------------ */ 6285ab25eeb5Syz int fr_initialise() 6286ab25eeb5Syz { 6287ab25eeb5Syz int i; 6288ab25eeb5Syz 6289ab25eeb5Syz #ifdef IPFILTER_LOG 6290ab25eeb5Syz i = fr_loginit(); 6291ab25eeb5Syz if (i < 0) 6292ab25eeb5Syz return -10 + i; 6293ab25eeb5Syz #endif 6294ab25eeb5Syz i = fr_natinit(); 6295ab25eeb5Syz if (i < 0) 6296ab25eeb5Syz return -20 + i; 6297ab25eeb5Syz 6298ab25eeb5Syz i = fr_stateinit(); 6299ab25eeb5Syz if (i < 0) 6300ab25eeb5Syz return -30 + i; 6301ab25eeb5Syz 6302ab25eeb5Syz i = fr_authinit(); 6303ab25eeb5Syz if (i < 0) 6304ab25eeb5Syz return -40 + i; 6305ab25eeb5Syz 6306ab25eeb5Syz i = fr_fraginit(); 6307ab25eeb5Syz if (i < 0) 6308ab25eeb5Syz return -50 + i; 6309ab25eeb5Syz 6310ab25eeb5Syz i = appr_init(); 6311ab25eeb5Syz if (i < 0) 6312ab25eeb5Syz return -60 + i; 6313ab25eeb5Syz 6314ab25eeb5Syz #ifdef IPFILTER_SYNC 6315ab25eeb5Syz i = ipfsync_init(); 6316ab25eeb5Syz if (i < 0) 6317ab25eeb5Syz return -70 + i; 6318ab25eeb5Syz #endif 6319ab25eeb5Syz #ifdef IPFILTER_SCAN 6320ab25eeb5Syz i = ipsc_init(); 6321ab25eeb5Syz if (i < 0) 6322ab25eeb5Syz return -80 + i; 6323ab25eeb5Syz #endif 6324ab25eeb5Syz #ifdef IPFILTER_LOOKUP 6325ab25eeb5Syz i = ip_lookup_init(); 6326ab25eeb5Syz if (i < 0) 6327ab25eeb5Syz return -90 + i; 6328ab25eeb5Syz #endif 6329ab25eeb5Syz #ifdef IPFILTER_COMPILED 6330ab25eeb5Syz ipfrule_add(); 6331ab25eeb5Syz #endif 6332ab25eeb5Syz return 0; 6333ab25eeb5Syz } 6334ab25eeb5Syz 6335ab25eeb5Syz 6336ab25eeb5Syz /* ------------------------------------------------------------------------ */ 6337ab25eeb5Syz /* Function: fr_deinitialise */ 6338ab25eeb5Syz /* Returns: None. */ 6339ab25eeb5Syz /* Parameters: None. */ 6340ab25eeb5Syz /* */ 6341ab25eeb5Syz /* Call all the various subsystem cleanup routines to deallocate memory or */ 6342ab25eeb5Syz /* destroy locks or whatever they've done that they need to now undo. */ 6343ab25eeb5Syz /* The order here IS important as there are some cross references of */ 6344ab25eeb5Syz /* internal data structures. */ 6345ab25eeb5Syz /* ------------------------------------------------------------------------ */ 6346ab25eeb5Syz void fr_deinitialise() 6347ab25eeb5Syz { 6348ab25eeb5Syz fr_fragunload(); 6349ab25eeb5Syz fr_authunload(); 6350ab25eeb5Syz fr_natunload(); 6351ab25eeb5Syz fr_stateunload(); 6352ab25eeb5Syz #ifdef IPFILTER_SCAN 6353ab25eeb5Syz fr_scanunload(); 6354ab25eeb5Syz #endif 6355ab25eeb5Syz appr_unload(); 6356ab25eeb5Syz 6357ab25eeb5Syz #ifdef IPFILTER_COMPILED 6358ab25eeb5Syz ipfrule_remove(); 6359ab25eeb5Syz #endif 6360ab25eeb5Syz 6361ab25eeb5Syz (void) frflush(IPL_LOGIPF, 0, FR_INQUE|FR_OUTQUE|FR_INACTIVE); 6362ab25eeb5Syz (void) frflush(IPL_LOGIPF, 0, FR_INQUE|FR_OUTQUE); 6363ab25eeb5Syz (void) frflush(IPL_LOGCOUNT, 0, FR_INQUE|FR_OUTQUE|FR_INACTIVE); 6364ab25eeb5Syz (void) frflush(IPL_LOGCOUNT, 0, FR_INQUE|FR_OUTQUE); 6365ab25eeb5Syz 6366ab25eeb5Syz #ifdef IPFILTER_LOOKUP 6367ab25eeb5Syz ip_lookup_unload(); 6368ab25eeb5Syz #endif 6369ab25eeb5Syz 6370ab25eeb5Syz #ifdef IPFILTER_LOG 6371ab25eeb5Syz fr_logunload(); 6372ab25eeb5Syz #endif 6373ab25eeb5Syz } 6374ab25eeb5Syz 6375ab25eeb5Syz 6376ab25eeb5Syz /* ------------------------------------------------------------------------ */ 6377ab25eeb5Syz /* Function: fr_zerostats */ 6378ab25eeb5Syz /* Returns: int - 0 = success, else failure */ 6379ab25eeb5Syz /* Parameters: data(O) - pointer to pointer for copying data back to */ 6380ab25eeb5Syz /* */ 6381ab25eeb5Syz /* Copies the current statistics out to userspace and then zero's the */ 6382ab25eeb5Syz /* current ones in the kernel. The lock is only held across the bzero() as */ 6383ab25eeb5Syz /* the copyout may result in paging (ie network activity.) */ 6384ab25eeb5Syz /* ------------------------------------------------------------------------ */ 6385ab25eeb5Syz int fr_zerostats(data) 6386ab25eeb5Syz caddr_t data; 6387ab25eeb5Syz { 6388ab25eeb5Syz friostat_t fio; 6389ab25eeb5Syz int error; 6390ab25eeb5Syz 6391ab25eeb5Syz fr_getstat(&fio); 6392ab25eeb5Syz error = copyoutptr(&fio, data, sizeof(fio)); 6393ab25eeb5Syz if (error) 6394ab25eeb5Syz return EFAULT; 6395ab25eeb5Syz 6396ab25eeb5Syz WRITE_ENTER(&ipf_mutex); 6397ab25eeb5Syz bzero((char *)frstats, sizeof(*frstats) * 2); 6398ab25eeb5Syz RWLOCK_EXIT(&ipf_mutex); 6399ab25eeb5Syz 6400ab25eeb5Syz return 0; 6401ab25eeb5Syz } 6402ab25eeb5Syz 6403ab25eeb5Syz 6404ab25eeb5Syz #ifdef _KERNEL 6405ab25eeb5Syz /* ------------------------------------------------------------------------ */ 6406ab25eeb5Syz /* Function: fr_resolvedest */ 6407ab25eeb5Syz /* Returns: Nil */ 6408ab25eeb5Syz /* Parameters: fdp(IO) - pointer to destination information to resolve */ 6409ab25eeb5Syz /* v(I) - IP protocol version to match */ 6410ab25eeb5Syz /* */ 6411ab25eeb5Syz /* Looks up an interface name in the frdest structure pointed to by fdp and */ 6412ab25eeb5Syz /* if a matching name can be found for the particular IP protocol version */ 6413ab25eeb5Syz /* then store the interface pointer in the frdest struct. If no match is */ 6414ab25eeb5Syz /* found, then set the interface pointer to be -1 as NULL is considered to */ 6415ab25eeb5Syz /* indicate there is no information at all in the structure. */ 6416ab25eeb5Syz /* ------------------------------------------------------------------------ */ 6417ab25eeb5Syz void fr_resolvedest(fdp, v) 6418ab25eeb5Syz frdest_t *fdp; 6419ab25eeb5Syz int v; 6420ab25eeb5Syz { 6421*381a2a9aSdr fdp->fd_ifp = NULL; 6422ab25eeb5Syz 6423*381a2a9aSdr if (*fdp->fd_ifname != '\0') { 6424*381a2a9aSdr fdp->fd_ifp = GETIFP(fdp->fd_ifname, v); 6425*381a2a9aSdr if (fdp->fd_ifp == NULL) 6426*381a2a9aSdr fdp->fd_ifp = (void *)-1; 6427ab25eeb5Syz } 6428ab25eeb5Syz } 6429ab25eeb5Syz #endif /* _KERNEL */ 6430ab25eeb5Syz 6431ab25eeb5Syz 6432ab25eeb5Syz /* ------------------------------------------------------------------------ */ 6433ab25eeb5Syz /* Function: fr_resolvenic */ 6434ab25eeb5Syz /* Returns: void* - NULL = wildcard name, -1 = failed to find NIC, else */ 6435ab25eeb5Syz /* pointer to interface structure for NIC */ 6436ab25eeb5Syz /* Parameters: name(I) - complete interface name */ 6437ab25eeb5Syz /* v(I) - IP protocol version */ 6438ab25eeb5Syz /* */ 6439ab25eeb5Syz /* Look for a network interface structure that firstly has a matching name */ 6440ab25eeb5Syz /* to that passed in and that is also being used for that IP protocol */ 6441ab25eeb5Syz /* version (necessary on some platforms where there are separate listings */ 6442ab25eeb5Syz /* for both IPv4 and IPv6 on the same physical NIC. */ 6443ab25eeb5Syz /* */ 6444ab25eeb5Syz /* One might wonder why name gets terminated with a \0 byte in here. The */ 6445ab25eeb5Syz /* reason is an interface name could get into the kernel structures of ipf */ 6446ab25eeb5Syz /* in any number of ways and so long as they all use the same sized array */ 6447ab25eeb5Syz /* to put the name in, it makes sense to ensure it gets null terminated */ 6448ab25eeb5Syz /* before it is used for its intended purpose - finding its match in the */ 6449ab25eeb5Syz /* kernel's list of configured interfaces. */ 6450ab25eeb5Syz /* */ 6451ab25eeb5Syz /* NOTE: This SHOULD ONLY be used with IPFilter structures that have an */ 6452ab25eeb5Syz /* array for the name that is LIFNAMSIZ bytes (at least) in length. */ 6453ab25eeb5Syz /* ------------------------------------------------------------------------ */ 6454ab25eeb5Syz void *fr_resolvenic(name, v) 6455ab25eeb5Syz char *name; 6456ab25eeb5Syz int v; 6457ab25eeb5Syz { 6458ab25eeb5Syz void *nic; 6459ab25eeb5Syz 6460ab25eeb5Syz if (name[0] == '\0') 6461ab25eeb5Syz return NULL; 6462ab25eeb5Syz 6463ab25eeb5Syz if ((name[1] == '\0') && ((name[0] == '-') || (name[0] == '*'))) { 6464ab25eeb5Syz return NULL; 6465ab25eeb5Syz } 6466ab25eeb5Syz 6467ab25eeb5Syz name[LIFNAMSIZ - 1] = '\0'; 6468ab25eeb5Syz 6469ab25eeb5Syz nic = GETIFP(name, v); 6470ab25eeb5Syz if (nic == NULL) 6471ab25eeb5Syz nic = (void *)-1; 6472ab25eeb5Syz return nic; 64737c478bd9Sstevel@tonic-gate } 6474