fil.c revision 67853
1339631Sphilip/* 2270725Spluknet * Copyright (C) 1993-2000 by Darren Reed. 3270725Spluknet * 4270725Spluknet * Redistribution and use in source and binary forms are permitted 5339631Sphilip * provided that this notice is preserved and due credit is given 6339631Sphilip * to the original author and the contributors. 7339631Sphilip */ 8270725Spluknet#if !defined(lint) 9270725Spluknetstatic const char sccsid[] = "@(#)fil.c 1.36 6/5/96 (C) 1993-1996 Darren Reed"; 10270725Spluknet/* static const char rcsid[] = "@(#)$Id: fil.c,v 2.3.2.16 2000/01/27 08:49:37 darrenr Exp $"; */ 11339631Sphilipstatic const char rcsid[] = "@(#)$FreeBSD: head/sys/contrib/ipfilter/netinet/fil.c 67853 2000-10-29 07:53:05Z darrenr $"; 12270728Spluknet#endif 13270728Spluknet 14339631Sphilip#include <sys/errno.h> 15270725Spluknet#include <sys/types.h> 16331663Sphilip#include <sys/param.h> 17270725Spluknet#include <sys/time.h> 18339631Sphilip#include <sys/file.h> 19339631Sphilip#if defined(__NetBSD__) && (NetBSD >= 199905) && !defined(IPFILTER_LKM) && \ 20339631Sphilip defined(_KERNEL) 21270725Spluknet# include "opt_ipfilter_log.h" 22339631Sphilip#endif 23270725Spluknet#if (defined(KERNEL) || defined(_KERNEL)) && defined(__FreeBSD_version) && \ 24339631Sphilip (__FreeBSD_version >= 220000) 25270725Spluknet# if (__FreeBSD_version >= 400000) 26270725Spluknet# ifndef KLD_MODULE 27270725Spluknet# include "opt_inet6.h" 28270725Spluknet# endif 29339631Sphilip# if (__FreeBSD_version == 400019) 30270725Spluknet# define CSUM_DELAY_DATA 31339631Sphilip# endif 32339631Sphilip# endif 33339631Sphilip# include <sys/filio.h> 34270725Spluknet# include <sys/fcntl.h> 35270725Spluknet#else 36270725Spluknet# include <sys/ioctl.h> 37270725Spluknet#endif 38270725Spluknet#if (defined(_KERNEL) || defined(KERNEL)) && !defined(linux) 39270725Spluknet# include <sys/systm.h> 40270725Spluknet#else 41270725Spluknet# include <stdio.h> 42307362Sbapt# include <string.h> 43307362Sbapt# include <stdlib.h> 44307362Sbapt#endif 45307362Sbapt#include <sys/uio.h> 46307362Sbapt#if !defined(__SVR4) && !defined(__svr4__) 47307362Sbapt# ifndef linux 48307362Sbapt# include <sys/mbuf.h> 49307362Sbapt# endif 50307362Sbapt#else 51270725Spluknet# include <sys/byteorder.h> 52307362Sbapt# if SOLARIS2 < 5 53307362Sbapt# include <sys/dditypes.h> 54270725Spluknet# endif 55270725Spluknet# include <sys/stream.h> 56307362Sbapt#endif 57270725Spluknet#ifndef linux 58270725Spluknet# include <sys/protosw.h> 59270725Spluknet# include <sys/socket.h> 60270725Spluknet#endif 61270725Spluknet#include <net/if.h> 62270725Spluknet#ifdef sun 63270725Spluknet# include <net/af.h> 64270725Spluknet#endif 65270725Spluknet#include <net/route.h> 66270725Spluknet#include <netinet/in.h> 67307362Sbapt#include <netinet/in_systm.h> 68307362Sbapt#include <netinet/ip.h> 69270725Spluknet#ifndef linux 70307362Sbapt# include <netinet/ip_var.h> 71307362Sbapt#endif 72307362Sbapt#if defined(__sgi) && defined(IFF_DRVRLOCK) /* IRIX 6 */ 73307362Sbapt# include <sys/hashing.h> 74270725Spluknet# include <netinet/in_var.h> 75270725Spluknet#endif 76307362Sbapt#include <netinet/tcp.h> 77307362Sbapt#include <netinet/udp.h> 78270725Spluknet#include <netinet/ip_icmp.h> 79270725Spluknet#include "netinet/ip_compat.h" 80270725Spluknet#ifdef USE_INET6 81270725Spluknet# include <netinet/icmp6.h> 82270725Spluknet# if !SOLARIS && defined(_KERNEL) 83270725Spluknet# include <netinet6/in6_var.h> 84270725Spluknet# endif 85270725Spluknet#endif 86270725Spluknet#include <netinet/tcpip.h> 87307362Sbapt#include "netinet/ip_fil.h" 88307362Sbapt#include "netinet/ip_proxy.h" 89270725Spluknet#include "netinet/ip_nat.h" 90270725Spluknet#include "netinet/ip_frag.h" 91270725Spluknet#include "netinet/ip_state.h" 92270725Spluknet#include "netinet/ip_auth.h" 93307362Sbapt# if defined(__FreeBSD_version) && (__FreeBSD_version >= 300000) 94270725Spluknet# include <sys/malloc.h> 95270725Spluknet# if defined(_KERNEL) && !defined(IPFILTER_LKM) 96307362Sbapt# include "opt_ipfilter.h" 97270725Spluknet# endif 98270725Spluknet# endif 99307362Sbapt#ifndef MIN 100307362Sbapt# define MIN(a,b) (((a)<(b))?(a):(b)) 101270725Spluknet#endif 102270725Spluknet#include "netinet/ipl.h" 103270725Spluknet 104270725Spluknet#include <machine/in_cksum.h> 105270725Spluknet 106307362Sbapt#ifndef _KERNEL 107307362Sbapt# include "ipf.h" 108307362Sbapt# include "ipt.h" 109307362Sbaptextern int opts; 110307362Sbapt 111307362Sbapt# define FR_VERBOSE(verb_pr) verbose verb_pr 112307362Sbapt# define FR_DEBUG(verb_pr) debug verb_pr 113307362Sbapt# define IPLLOG(a, c, d, e) ipllog() 114307362Sbapt#else /* #ifndef _KERNEL */ 115307362Sbapt# define FR_VERBOSE(verb_pr) 116307362Sbapt# define FR_DEBUG(verb_pr) 117307362Sbapt# define IPLLOG(a, c, d, e) ipflog(a, c, d, e) 118307362Sbapt# if SOLARIS || defined(__sgi) 119307362Sbaptextern KRWLOCK_T ipf_mutex, ipf_auth, ipf_nat; 120307362Sbaptextern kmutex_t ipf_rw; 121307362Sbapt# endif 122307362Sbapt# if SOLARIS 123307362Sbapt# define FR_NEWAUTH(m, fi, ip, qif) fr_newauth((mb_t *)m, fi, \ 124307362Sbapt ip, qif) 125307362Sbapt# else /* SOLARIS */ 126307362Sbapt# define FR_NEWAUTH(m, fi, ip, qif) fr_newauth((mb_t *)m, fi, ip) 127307362Sbapt# endif /* SOLARIS || __sgi */ 128307362Sbapt#endif /* _KERNEL */ 129307362Sbapt 130307362Sbapt 131307362Sbaptstruct filterstats frstats[2] = {{0,0,0,0,0},{0,0,0,0,0}}; 132307362Sbaptstruct frentry *ipfilter[2][2] = { { NULL, NULL }, { NULL, NULL } }, 133307362Sbapt#ifdef USE_INET6 134270725Spluknet *ipfilter6[2][2] = { { NULL, NULL }, { NULL, NULL } }, 135270725Spluknet *ipacct6[2][2] = { { NULL, NULL }, { NULL, NULL } }, 136328476Sphilip#endif 137270725Spluknet *ipacct[2][2] = { { NULL, NULL }, { NULL, NULL } }; 138307362Sbaptstruct frgroup *ipfgroups[3][2]; 139316350Sbaptint fr_flags = IPF_LOGGING; 140270725Spluknetint fr_active = 0; 141270725Spluknetint fr_chksrc = 0; 142270725Spluknet#if defined(IPFILTER_DEFAULT_BLOCK) 143270725Spluknetint fr_pass = FR_NOMATCH|FR_BLOCK; 144270725Spluknet#else 145270725Spluknetint fr_pass = (IPF_DEFAULT_PASS|FR_NOMATCH); 146270725Spluknet#endif 147270725Spluknetchar ipfilter_version[] = IPL_VERSION; 148270725Spluknet 149308302Sgjbfr_info_t frcache[2]; 150308302Sgjb 151270725Spluknetstatic int frflushlist __P((int, minor_t, int *, frentry_t **)); 152307362Sbapt#ifdef _KERNEL 153270725Spluknetstatic void frsynclist __P((frentry_t *)); 154270725Spluknet#endif 155270725Spluknet 156307362Sbapt 157270725Spluknet/* 158270725Spluknet * bit values for identifying presence of individual IP options 159270725Spluknet */ 160270725Spluknetstruct optlist ipopts[20] = { 161307362Sbapt { IPOPT_NOP, 0x000001 }, 162307362Sbapt { IPOPT_RR, 0x000002 }, 163270725Spluknet { IPOPT_ZSU, 0x000004 }, 164270725Spluknet { IPOPT_MTUP, 0x000008 }, 165270725Spluknet { IPOPT_MTUR, 0x000010 }, 166270725Spluknet { IPOPT_ENCODE, 0x000020 }, 167307362Sbapt { IPOPT_TS, 0x000040 }, 168307362Sbapt { IPOPT_TR, 0x000080 }, 169270725Spluknet { IPOPT_SECURITY, 0x000100 }, 170270725Spluknet { IPOPT_LSRR, 0x000200 }, 171270725Spluknet { IPOPT_E_SEC, 0x000400 }, 172270725Spluknet { IPOPT_CIPSO, 0x000800 }, 173270725Spluknet { IPOPT_SATID, 0x001000 }, 174270725Spluknet { IPOPT_SSRR, 0x002000 }, 175270725Spluknet { IPOPT_ADDEXT, 0x004000 }, 176270725Spluknet { IPOPT_VISA, 0x008000 }, 177307362Sbapt { IPOPT_IMITD, 0x010000 }, 178307362Sbapt { IPOPT_EIP, 0x020000 }, 179307362Sbapt { IPOPT_FINN, 0x040000 }, 180307362Sbapt { 0, 0x000000 } 181270725Spluknet}; 182270725Spluknet 183270725Spluknet/* 184270725Spluknet * bit values for identifying presence of individual IP security options 185270725Spluknet */ 186270725Spluknetstruct optlist secopt[8] = { 187270725Spluknet { IPSO_CLASS_RES4, 0x01 }, 188270725Spluknet { IPSO_CLASS_TOPS, 0x02 }, 189270725Spluknet { IPSO_CLASS_SECR, 0x04 }, 190270725Spluknet { IPSO_CLASS_RES3, 0x08 }, 191307362Sbapt { IPSO_CLASS_CONF, 0x10 }, 192307362Sbapt { IPSO_CLASS_UNCL, 0x20 }, 193307362Sbapt { IPSO_CLASS_RES2, 0x40 }, 194307362Sbapt { IPSO_CLASS_RES1, 0x80 } 195270725Spluknet}; 196270725Spluknet 197270725Spluknet 198270725Spluknet/* 199270725Spluknet * compact the IP header into a structure which contains just the info. 200270725Spluknet * which is useful for comparing IP headers with. 201270725Spluknet */ 202270725Spluknetvoid fr_makefrip(hlen, ip, fin) 203270725Spluknetint hlen; 204270725Spluknetip_t *ip; 205270725Spluknetfr_info_t *fin; 206270725Spluknet{ 207270725Spluknet u_short optmsk = 0, secmsk = 0, auth = 0; 208270725Spluknet int i, mv, ol, off, p, plen, v; 209270725Spluknet fr_ip_t *fi = &fin->fin_fi; 210270725Spluknet struct optlist *op; 211270725Spluknet u_char *s, opt; 212270725Spluknet tcphdr_t *tcp; 213307362Sbapt 214307362Sbapt fin->fin_rev = 0; 215342669Sphilip fin->fin_fr = NULL; 216309793Sbapt fin->fin_tcpf = 0; 217309793Sbapt fin->fin_data[0] = 0; 218309793Sbapt fin->fin_data[1] = 0; 219270725Spluknet fin->fin_rule = -1; 220270725Spluknet fin->fin_group = -1; 221270725Spluknet#ifdef _KERNEL 222270725Spluknet fin->fin_icode = ipl_unreach; 223270725Spluknet#endif 224270725Spluknet v = fin->fin_v; 225270725Spluknet fi->fi_v = v; 226270725Spluknet fin->fin_hlen = hlen; 227270725Spluknet if (v == 4) { 228270725Spluknet fin->fin_id = ip->ip_id; 229270725Spluknet fi->fi_tos = ip->ip_tos; 230307362Sbapt off = (ip->ip_off & IP_OFFMASK) << 3; 231270725Spluknet tcp = (tcphdr_t *)((char *)ip + hlen); 232307362Sbapt (*(((u_short *)fi) + 1)) = (*(((u_short *)ip) + 4)); 233307362Sbapt fi->fi_src.i6[1] = 0; 234270725Spluknet fi->fi_src.i6[2] = 0; 235270725Spluknet fi->fi_src.i6[3] = 0; 236339631Sphilip fi->fi_dst.i6[1] = 0; 237270725Spluknet fi->fi_dst.i6[2] = 0; 238270725Spluknet fi->fi_dst.i6[3] = 0; 239270725Spluknet fi->fi_saddr = ip->ip_src.s_addr; 240270725Spluknet fi->fi_daddr = ip->ip_dst.s_addr; 241307362Sbapt p = ip->ip_p; 242279707Sedwin fi->fi_fl = (hlen > sizeof(ip_t)) ? FI_OPTIONS : 0; 243270725Spluknet if (ip->ip_off & 0x3fff) 244307362Sbapt fi->fi_fl |= FI_FRAG; 245307362Sbapt plen = ip->ip_len; 246307362Sbapt fin->fin_dlen = plen - hlen; 247307362Sbapt } 248307362Sbapt#ifdef USE_INET6 249270725Spluknet else if (v == 6) { 250307362Sbapt ip6_t *ip6 = (ip6_t *)ip; 251307362Sbapt 252307362Sbapt off = 0; 253307362Sbapt p = ip6->ip6_nxt; 254307362Sbapt fi->fi_p = p; 255270725Spluknet fi->fi_ttl = ip6->ip6_hlim; 256270725Spluknet tcp = (tcphdr_t *)(ip6 + 1); 257270725Spluknet fi->fi_src.in6 = ip6->ip6_src; 258307362Sbapt fi->fi_dst.in6 = ip6->ip6_dst; 259270725Spluknet fin->fin_id = (u_short)(ip6->ip6_flow & 0xffff); 260270725Spluknet fi->fi_tos = 0; 261270725Spluknet fi->fi_fl = 0; 262270725Spluknet plen = ntohs(ip6->ip6_plen); 263270725Spluknet fin->fin_dlen = plen; 264270725Spluknet } 265270725Spluknet#endif 266270725Spluknet else 267307362Sbapt return; 268270725Spluknet 269270725Spluknet fin->fin_off = off; 270270725Spluknet fin->fin_plen = plen; 271270725Spluknet fin->fin_dp = (void *)tcp; 272307362Sbapt 273273719Sedwin switch (p) 274270725Spluknet { 275270725Spluknet case IPPROTO_ICMP : 276270725Spluknet { 277270725Spluknet int minicmpsz = sizeof(struct icmp); 278270725Spluknet icmphdr_t *icmp; 279270725Spluknet 280270725Spluknet if (!off && (fin->fin_dlen > 1)) { 281270725Spluknet fin->fin_data[0] = *(u_short *)tcp; 282307362Sbapt 283270725Spluknet icmp = (icmphdr_t *)tcp; 284270725Spluknet 285270725Spluknet if (icmp->icmp_type == ICMP_ECHOREPLY || 286270725Spluknet icmp->icmp_type == ICMP_ECHO) 287270725Spluknet minicmpsz = ICMP_MINLEN; 288307362Sbapt 289270725Spluknet /* 290270725Spluknet * type(1) + code(1) + cksum(2) + id(2) seq(2) + 291307362Sbapt * 3*timestamp(3*4) 292307362Sbapt */ 293307362Sbapt else if (icmp->icmp_type == ICMP_TSTAMP || 294307362Sbapt icmp->icmp_type == ICMP_TSTAMPREPLY) 295307362Sbapt minicmpsz = 20; 296342669Sphilip 297309793Sbapt /* 298309793Sbapt * type(1) + code(1) + cksum(2) + id(2) seq(2) + 299307362Sbapt * mask(4) 300307362Sbapt */ 301307362Sbapt else if (icmp->icmp_type == ICMP_MASKREQ || 302309793Sbapt icmp->icmp_type == ICMP_MASKREPLY) 303307362Sbapt minicmpsz = 12; 304307362Sbapt } 305307362Sbapt 306307362Sbapt if ((!(plen >= hlen + minicmpsz) && !off) || 307307362Sbapt (off && off < sizeof(struct icmp))) 308307362Sbapt fi->fi_fl |= FI_SHORT; 309307362Sbapt 310307362Sbapt break; 311307362Sbapt } 312307362Sbapt case IPPROTO_TCP : 313307362Sbapt fi->fi_fl |= FI_TCPUDP; 314307362Sbapt#ifdef USE_INET6 315307362Sbapt if (v == 6) { 316307362Sbapt if (plen < sizeof(struct tcphdr)) 317307362Sbapt fi->fi_fl |= FI_SHORT; 318270725Spluknet } else 319270725Spluknet#endif 320270725Spluknet if (v == 4) { 321325160Sphilip if ((!IPMINLEN(ip, tcphdr) && !off) || 322270725Spluknet (off && off < sizeof(struct tcphdr))) 323270725Spluknet fi->fi_fl |= FI_SHORT; 324270725Spluknet } 325325160Sphilip if (!(fi->fi_fl & FI_SHORT) && !off) 326328476Sphilip fin->fin_tcpf = tcp->th_flags; 327270725Spluknet goto getports; 328270725Spluknet case IPPROTO_UDP : 329270725Spluknet fi->fi_fl |= FI_TCPUDP; 330270725Spluknet#ifdef USE_INET6 331307362Sbapt if (v == 6) { 332307362Sbapt if (plen < sizeof(struct udphdr)) 333270725Spluknet fi->fi_fl |= FI_SHORT; 334270725Spluknet } else 335270725Spluknet#endif 336270725Spluknet if (v == 4) { 337270725Spluknet if ((!IPMINLEN(ip, udphdr) && !off) || 338270725Spluknet (off && off < sizeof(struct udphdr))) 339270725Spluknet fi->fi_fl |= FI_SHORT; 340273719Sedwin } 341270725Spluknetgetports: 342270725Spluknet if (!off && (fin->fin_dlen > 3)) { 343307362Sbapt fin->fin_data[0] = ntohs(tcp->th_sport); 344270725Spluknet fin->fin_data[1] = ntohs(tcp->th_dport); 345307362Sbapt } 346270725Spluknet break; 347307362Sbapt default : 348307362Sbapt break; 349307362Sbapt } 350307362Sbapt 351307362Sbapt#ifdef USE_INET6 352307362Sbapt if (v == 6) { 353307362Sbapt fi->fi_optmsk = 0; 354307362Sbapt fi->fi_secmsk = 0; 355307362Sbapt fi->fi_auth = 0; 356307362Sbapt return; 357307362Sbapt } 358307362Sbapt#endif 359307362Sbapt 360307362Sbapt for (s = (u_char *)(ip + 1), hlen -= (int)sizeof(*ip); hlen > 0; ) { 361307362Sbapt opt = *s; 362307362Sbapt if (opt == '\0') 363307362Sbapt break; 364307362Sbapt else if (opt == IPOPT_NOP) 365307362Sbapt ol = 1; 366307362Sbapt else { 367307362Sbapt if (hlen < 2) 368307362Sbapt break; 369307362Sbapt ol = (int)*(s + 1); 370307362Sbapt if (ol < 2 || ol > hlen) 371307362Sbapt break; 372307362Sbapt } 373307362Sbapt for (i = 9, mv = 4; mv >= 0; ) { 374270725Spluknet op = ipopts + i; 375307362Sbapt if (opt == (u_char)op->ol_val) { 376331663Sphilip optmsk |= op->ol_bit; 377307362Sbapt if (opt == IPOPT_SECURITY) { 378307362Sbapt struct optlist *sp; 379270725Spluknet u_char sec; 380307362Sbapt int j, m; 381270725Spluknet 382270725Spluknet sec = *(s + 2); /* classification */ 383270725Spluknet for (j = 3, m = 2; m >= 0; ) { 384270725Spluknet sp = secopt + j; 385 if (sec == sp->ol_val) { 386 secmsk |= sp->ol_bit; 387 auth = *(s + 3); 388 auth *= 256; 389 auth += *(s + 4); 390 break; 391 } 392 if (sec < sp->ol_val) 393 j -= m--; 394 else 395 j += m--; 396 } 397 } 398 break; 399 } 400 if (opt < op->ol_val) 401 i -= mv--; 402 else 403 i += mv--; 404 } 405 hlen -= ol; 406 s += ol; 407 } 408 if (auth && !(auth & 0x0100)) 409 auth &= 0xff00; 410 fi->fi_optmsk = optmsk; 411 fi->fi_secmsk = secmsk; 412 fi->fi_auth = auth; 413} 414 415 416/* 417 * check an IP packet for TCP/UDP characteristics such as ports and flags. 418 */ 419int fr_tcpudpchk(ft, fin) 420frtuc_t *ft; 421fr_info_t *fin; 422{ 423 register u_short po, tup; 424 register char i; 425 register int err = 1; 426 427 /* 428 * Both ports should *always* be in the first fragment. 429 * So far, I cannot find any cases where they can not be. 430 * 431 * compare destination ports 432 */ 433 if ((i = (int)ft->ftu_dcmp)) { 434 po = ft->ftu_dport; 435 tup = fin->fin_data[1]; 436 /* 437 * Do opposite test to that required and 438 * continue if that succeeds. 439 */ 440 if (!--i && tup != po) /* EQUAL */ 441 err = 0; 442 else if (!--i && tup == po) /* NOTEQUAL */ 443 err = 0; 444 else if (!--i && tup >= po) /* LESSTHAN */ 445 err = 0; 446 else if (!--i && tup <= po) /* GREATERTHAN */ 447 err = 0; 448 else if (!--i && tup > po) /* LT or EQ */ 449 err = 0; 450 else if (!--i && tup < po) /* GT or EQ */ 451 err = 0; 452 else if (!--i && /* Out of range */ 453 (tup >= po && tup <= ft->ftu_dtop)) 454 err = 0; 455 else if (!--i && /* In range */ 456 (tup <= po || tup >= ft->ftu_dtop)) 457 err = 0; 458 } 459 /* 460 * compare source ports 461 */ 462 if (err && (i = (int)ft->ftu_scmp)) { 463 po = ft->ftu_sport; 464 tup = fin->fin_data[0]; 465 if (!--i && tup != po) 466 err = 0; 467 else if (!--i && tup == po) 468 err = 0; 469 else if (!--i && tup >= po) 470 err = 0; 471 else if (!--i && tup <= po) 472 err = 0; 473 else if (!--i && tup > po) 474 err = 0; 475 else if (!--i && tup < po) 476 err = 0; 477 else if (!--i && /* Out of range */ 478 (tup >= po && tup <= ft->ftu_stop)) 479 err = 0; 480 else if (!--i && /* In range */ 481 (tup <= po || tup >= ft->ftu_stop)) 482 err = 0; 483 } 484 485 /* 486 * If we don't have all the TCP/UDP header, then how can we 487 * expect to do any sort of match on it ? If we were looking for 488 * TCP flags, then NO match. If not, then match (which should 489 * satisfy the "short" class too). 490 */ 491 if (err && (fin->fin_fi.fi_p == IPPROTO_TCP)) { 492 if (fin->fin_fi.fi_fl & FI_SHORT) 493 return !(ft->ftu_tcpf | ft->ftu_tcpfm); 494 /* 495 * Match the flags ? If not, abort this match. 496 */ 497 if (ft->ftu_tcpfm && 498 ft->ftu_tcpf != (fin->fin_tcpf & ft->ftu_tcpfm)) { 499 FR_DEBUG(("f. %#x & %#x != %#x\n", fin->fin_tcpf, 500 ft->ftu_tcpfm, ft->ftu_tcpf)); 501 err = 0; 502 } 503 } 504 return err; 505} 506 507/* 508 * Check the input/output list of rules for a match and result. 509 * Could be per interface, but this gets real nasty when you don't have 510 * kernel sauce. 511 */ 512int fr_scanlist(pass, ip, fin, m) 513u_32_t pass; 514ip_t *ip; 515register fr_info_t *fin; 516void *m; 517{ 518 register struct frentry *fr; 519 register fr_ip_t *fi = &fin->fin_fi; 520 int rulen, portcmp = 0, off, skip = 0, logged = 0; 521 u_32_t passt; 522 523 fr = fin->fin_fr; 524 fin->fin_fr = NULL; 525 fin->fin_rule = 0; 526 fin->fin_group = 0; 527 if (fin->fin_v == 4) 528 off = ip->ip_off & IP_OFFMASK; 529 else 530 off = 0; 531 pass |= (fi->fi_fl << 24); 532 533 if ((fi->fi_fl & FI_TCPUDP) && (fin->fin_dlen > 3) && !off) 534 portcmp = 1; 535 536 for (rulen = 0; fr; fr = fr->fr_next, rulen++) { 537 if (skip) { 538 skip--; 539 continue; 540 } 541 /* 542 * In all checks below, a null (zero) value in the 543 * filter struture is taken to mean a wildcard. 544 * 545 * check that we are working for the right interface 546 */ 547#ifdef _KERNEL 548# if BSD >= 199306 549 if (fin->fin_out != 0) { 550 if ((fr->fr_oifa && 551 fr->fr_oifa != ((mb_t *)m)->m_pkthdr.rcvif) || 552 (fr->fr_ifa && fr->fr_ifa != fin->fin_ifp)) 553 continue; 554 } else 555# endif 556 if (fr->fr_ifa && fr->fr_ifa != fin->fin_ifp) 557 continue; 558#else 559 if (opts & (OPT_VERBOSE|OPT_DEBUG)) 560 printf("\n"); 561 FR_VERBOSE(("%c", (pass & FR_PASS) ? 'p' : 562 (pass & FR_AUTH) ? 'a' : 'b')); 563 if (fr->fr_ifa && fr->fr_ifa != fin->fin_ifp) 564 continue; 565 FR_VERBOSE((":i")); 566#endif 567 { 568 register u_32_t *ld, *lm, *lip; 569 register int i; 570 571 lip = (u_32_t *)fi; 572 lm = (u_32_t *)&fr->fr_mip; 573 ld = (u_32_t *)&fr->fr_ip; 574 i = ((*lip & *lm) != *ld); 575 FR_DEBUG(("0. %#08x & %#08x != %#08x\n", 576 *lip, *lm, *ld)); 577 if (i) 578 continue; 579 /* 580 * We now know whether the packet version and the 581 * rule version match, along with protocol, ttl and 582 * tos. 583 */ 584 lip++, lm++, ld++; 585 /* 586 * Unrolled loops (4 each, for 32 bits). 587 */ 588 i |= ((*lip & *lm) != *ld) << 19; 589 FR_DEBUG(("1a. %#08x & %#08x != %#08x\n", 590 *lip, *lm, *ld)); 591 if (fi->fi_v == 6) { 592 lip++, lm++, ld++; 593 i |= ((*lip & *lm) != *ld) << 19; 594 FR_DEBUG(("1b. %#08x & %#08x != %#08x\n", 595 *lip, *lm, *ld)); 596 lip++, lm++, ld++; 597 i |= ((*lip & *lm) != *ld) << 19; 598 FR_DEBUG(("1c. %#08x & %#08x != %#08x\n", 599 *lip, *lm, *ld)); 600 lip++, lm++, ld++; 601 i |= ((*lip & *lm) != *ld) << 19; 602 FR_DEBUG(("1d. %#08x & %#08x != %#08x\n", 603 *lip, *lm, *ld)); 604 } else { 605 lip += 3; 606 lm += 3; 607 ld += 3; 608 } 609 i ^= (fr->fr_flags & FR_NOTSRCIP); 610 if (i) 611 continue; 612 lip++, lm++, ld++; 613 i |= ((*lip & *lm) != *ld) << 20; 614 FR_DEBUG(("2a. %#08x & %#08x != %#08x\n", 615 *lip, *lm, *ld)); 616 if (fi->fi_v == 6) { 617 lip++, lm++, ld++; 618 i |= ((*lip & *lm) != *ld) << 20; 619 FR_DEBUG(("2b. %#08x & %#08x != %#08x\n", 620 *lip, *lm, *ld)); 621 lip++, lm++, ld++; 622 i |= ((*lip & *lm) != *ld) << 20; 623 FR_DEBUG(("2c. %#08x & %#08x != %#08x\n", 624 *lip, *lm, *ld)); 625 lip++, lm++, ld++; 626 i |= ((*lip & *lm) != *ld) << 20; 627 FR_DEBUG(("2d. %#08x & %#08x != %#08x\n", 628 *lip, *lm, *ld)); 629 } else { 630 lip += 3; 631 lm += 3; 632 ld += 3; 633 } 634 i ^= (fr->fr_flags & FR_NOTDSTIP); 635 if (i) 636 continue; 637 lip++, lm++, ld++; 638 i |= ((*lip & *lm) != *ld); 639 FR_DEBUG(("3. %#08x & %#08x != %#08x\n", 640 *lip, *lm, *ld)); 641 lip++, lm++, ld++; 642 i |= ((*lip & *lm) != *ld); 643 FR_DEBUG(("4. %#08x & %#08x != %#08x\n", 644 *lip, *lm, *ld)); 645 if (i) 646 continue; 647 } 648 649 /* 650 * If a fragment, then only the first has what we're looking 651 * for here... 652 */ 653 if (!portcmp && (fr->fr_dcmp || fr->fr_scmp || fr->fr_tcpf || 654 fr->fr_tcpfm)) 655 continue; 656 if (fi->fi_fl & FI_TCPUDP) { 657 if (!fr_tcpudpchk(&fr->fr_tuc, fin)) 658 continue; 659 } else if (fr->fr_icmpm || fr->fr_icmp) { 660 if ((fi->fi_p != IPPROTO_ICMP) || off || 661 (fin->fin_dlen < 2)) 662 continue; 663 if ((fin->fin_data[0] & fr->fr_icmpm) != fr->fr_icmp) { 664 FR_DEBUG(("i. %#x & %#x != %#x\n", 665 fin->fin_data[0], fr->fr_icmpm, 666 fr->fr_icmp)); 667 continue; 668 } 669 } 670 FR_VERBOSE(("*")); 671 /* 672 * Just log this packet... 673 */ 674 passt = fr->fr_flags; 675#if (BSD >= 199306) && (defined(_KERNEL) || defined(KERNEL)) 676 if (securelevel <= 0) 677#endif 678 if ((passt & FR_CALLNOW) && fr->fr_func) 679 passt = (*fr->fr_func)(passt, ip, fin); 680 fin->fin_fr = fr; 681#ifdef IPFILTER_LOG 682 if ((passt & FR_LOGMASK) == FR_LOG) { 683 if (!IPLLOG(passt, ip, fin, m)) { 684 if (passt & FR_LOGORBLOCK) 685 passt |= FR_BLOCK|FR_QUICK; 686 ATOMIC_INCL(frstats[fin->fin_out].fr_skip); 687 } 688 ATOMIC_INCL(frstats[fin->fin_out].fr_pkl); 689 logged = 1; 690 } 691#endif /* IPFILTER_LOG */ 692 if (!(skip = fr->fr_skip) && (passt & FR_LOGMASK) != FR_LOG) 693 pass = passt; 694 FR_DEBUG(("pass %#x\n", pass)); 695 ATOMIC_INCL(fr->fr_hits); 696 if (pass & FR_ACCOUNT) 697 fr->fr_bytes += (U_QUAD_T)ip->ip_len; 698 else 699 fin->fin_icode = fr->fr_icode; 700 fin->fin_rule = rulen; 701 fin->fin_group = fr->fr_group; 702 if (fr->fr_grp) { 703 fin->fin_fr = fr->fr_grp; 704 pass = fr_scanlist(pass, ip, fin, m); 705 if (fin->fin_fr == NULL) { 706 fin->fin_rule = rulen; 707 fin->fin_group = fr->fr_group; 708 fin->fin_fr = fr; 709 } 710 if (pass & FR_DONTCACHE) 711 logged = 1; 712 } 713 if (pass & FR_QUICK) 714 break; 715 } 716 if (logged) 717 pass |= FR_DONTCACHE; 718 return pass; 719} 720 721 722/* 723 * frcheck - filter check 724 * check using source and destination addresses/ports in a packet whether 725 * or not to pass it on or not. 726 */ 727int fr_check(ip, hlen, ifp, out 728#if defined(_KERNEL) && SOLARIS 729, qif, mp) 730qif_t *qif; 731#else 732, mp) 733#endif 734mb_t **mp; 735ip_t *ip; 736int hlen; 737void *ifp; 738int out; 739{ 740 /* 741 * The above really sucks, but short of writing a diff 742 */ 743 fr_info_t frinfo, *fc; 744 register fr_info_t *fin = &frinfo; 745 int changed, error = EHOSTUNREACH, v = ip->ip_v; 746 frentry_t *fr = NULL, *list; 747 u_32_t pass, apass; 748#if !SOLARIS || !defined(_KERNEL) 749 register mb_t *m = *mp; 750#endif 751 752#ifdef _KERNEL 753 mb_t *mc = NULL; 754 int p, len; 755# if !defined(__SVR4) && !defined(__svr4__) 756# ifdef __sgi 757 char hbuf[(0xf << 2) + sizeof(struct icmp) + sizeof(ip_t) + 8]; 758# endif 759 int up; 760 761# ifdef M_CANFASTFWD 762 /* 763 * XXX For now, IP Filter and fast-forwarding of cached flows 764 * XXX are mutually exclusive. Eventually, IP Filter should 765 * XXX get a "can-fast-forward" filter rule. 766 */ 767 m->m_flags &= ~M_CANFASTFWD; 768# endif /* M_CANFASTFWD */ 769# ifdef CSUM_DELAY_DATA 770 /* 771 * disable delayed checksums. 772 */ 773 if (m->m_pkthdr.csum_flags & CSUM_DELAY_DATA) { 774 in_delayed_cksum(m); 775 m->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA; 776 } 777# endif /* CSUM_DELAY_DATA */ 778 779# ifdef USE_INET6 780 if (v == 6) { 781 len = ntohs(((ip6_t*)ip)->ip6_plen); 782 p = ((ip6_t *)ip)->ip6_nxt; 783 } else 784# endif 785 { 786 p = ip->ip_p; 787 len = ip->ip_len; 788 } 789 790 if ((p == IPPROTO_TCP || p == IPPROTO_UDP || p == IPPROTO_ICMP 791# ifdef USE_INET6 792 || (v == 6 && p == IPPROTO_ICMPV6) 793# endif 794 )) { 795 int plen = 0; 796 797 if ((v == 6) || (ip->ip_off & IP_OFFMASK) == 0) 798 switch(p) 799 { 800 case IPPROTO_TCP: 801 plen = sizeof(tcphdr_t); 802 break; 803 case IPPROTO_UDP: 804 plen = sizeof(udphdr_t); 805 break; 806 /* 96 - enough for complete ICMP error IP header */ 807 case IPPROTO_ICMP: 808# ifdef USE_INET6 809 case IPPROTO_ICMPV6 : 810# endif 811 plen = ICMPERR_MAXPKTLEN - sizeof(ip_t); 812 break; 813 } 814 up = MIN(hlen + plen, len); 815 816 if (up > m->m_len) { 817# ifdef __sgi 818 /* Under IRIX, avoid m_pullup as it makes ping <hostname> panic */ 819 if ((up > sizeof(hbuf)) || (m_length(m) < up)) { 820 ATOMIC_INCL(frstats[out].fr_pull[1]); 821 return -1; 822 } 823 m_copydata(m, 0, up, hbuf); 824 ATOMIC_INCL(frstats[out].fr_pull[0]); 825 ip = (ip_t *)hbuf; 826# else /* __ sgi */ 827# ifndef linux 828 if ((*mp = m_pullup(m, up)) == 0) { 829 ATOMIC_INCL(frstats[out].fr_pull[1]); 830 return -1; 831 } else { 832 ATOMIC_INCL(frstats[out].fr_pull[0]); 833 m = *mp; 834 ip = mtod(m, ip_t *); 835 } 836# endif /* !linux */ 837# endif /* __sgi */ 838 } else 839 up = 0; 840 } else 841 up = 0; 842# endif /* !defined(__SVR4) && !defined(__svr4__) */ 843# if SOLARIS 844 mb_t *m = qif->qf_m; 845 846 if ((u_int)ip & 0x3) 847 return 2; 848 fin->fin_qfm = m; 849 fin->fin_qif = qif; 850# endif 851#endif /* _KERNEL */ 852 853#ifndef __FreeBSD__ 854 /* 855 * Be careful here: ip_id is in network byte order when called 856 * from ip_output() 857 */ 858 if ((out) && (v == 4)) 859 ip->ip_id = ntohs(ip->ip_id); 860#endif 861 862 changed = 0; 863 fin->fin_ifp = ifp; 864 fin->fin_v = v; 865 fin->fin_out = out; 866 fin->fin_mp = mp; 867 fr_makefrip(hlen, ip, fin); 868 869#ifdef _KERNEL 870# ifdef USE_INET6 871 if (v == 6) { 872 ATOMIC_INCL(frstats[0].fr_ipv6[out]); 873 } else 874# endif 875 if (!out && fr_chksrc && !fr_verifysrc(ip->ip_src, ifp)) { 876 ATOMIC_INCL(frstats[0].fr_badsrc); 877# ifdef IPFILTER_LOG 878 if (fr_chksrc == 2) { 879 fin->fin_group = -2; 880 pass = FR_INQUE|FR_NOMATCH|FR_LOGB; 881 (void) IPLLOG(pass, ip, fin, m); 882 } 883# endif 884# if !SOLARIS 885 m_freem(m); 886# endif 887 return error; 888 } 889#endif 890 pass = fr_pass; 891 if (fin->fin_fi.fi_fl & FI_SHORT) { 892 ATOMIC_INCL(frstats[out].fr_short); 893 } 894 895 READ_ENTER(&ipf_mutex); 896 897 if (fin->fin_fi.fi_fl & FI_SHORT) 898 ATOMIC_INCL(frstats[out].fr_short); 899 900 /* 901 * Check auth now. This, combined with the check below to see if apass 902 * is 0 is to ensure that we don't count the packet twice, which can 903 * otherwise occur when we reprocess it. As it is, we only count it 904 * after it has no auth. table matchup. This also stops NAT from 905 * occuring until after the packet has been auth'd. 906 */ 907 apass = fr_checkauth(ip, fin); 908 909 if (!out) { 910#ifdef USE_INET6 911 if (v == 6) 912 list = ipacct6[0][fr_active]; 913 else 914#endif 915 list = ipacct[0][fr_active]; 916 changed = ip_natin(ip, fin); 917 if (!apass && (fin->fin_fr = list) && 918 (fr_scanlist(FR_NOMATCH, ip, fin, m) & FR_ACCOUNT)) { 919 ATOMIC_INCL(frstats[0].fr_acct); 920 } 921 } 922 923 if (apass || (!(fr = ipfr_knownfrag(ip, fin)) && 924 !(fr = fr_checkstate(ip, fin)))) { 925 /* 926 * If a packet is found in the auth table, then skip checking 927 * the access lists for permission but we do need to consider 928 * the result as if it were from the ACL's. 929 */ 930 if (!apass) { 931 fc = frcache + out; 932 if (!bcmp((char *)fin, (char *)fc, FI_CSIZE)) { 933 /* 934 * copy cached data so we can unlock the mutex 935 * earlier. 936 */ 937 bcopy((char *)fc, (char *)fin, FI_COPYSIZE); 938 ATOMIC_INCL(frstats[out].fr_chit); 939 if ((fr = fin->fin_fr)) { 940 ATOMIC_INCL(fr->fr_hits); 941 pass = fr->fr_flags; 942 } 943 } else { 944#ifdef USE_INET6 945 if (v == 6) 946 list = ipfilter6[out][fr_active]; 947 else 948#endif 949 list = ipfilter[out][fr_active]; 950 if ((fin->fin_fr = list)) 951 pass = fr_scanlist(fr_pass, ip, fin, m); 952 if (!(pass & (FR_KEEPSTATE|FR_DONTCACHE))) 953 bcopy((char *)fin, (char *)fc, 954 FI_COPYSIZE); 955 if (pass & FR_NOMATCH) { 956 ATOMIC_INCL(frstats[out].fr_nom); 957 } 958 } 959 fr = fin->fin_fr; 960 } else 961 pass = apass; 962 963 /* 964 * If we fail to add a packet to the authorization queue, 965 * then we drop the packet later. However, if it was added 966 * then pretend we've dropped it already. 967 */ 968 if ((pass & FR_AUTH)) 969 if (fr_newauth((mb_t *)m, fin, ip) != 0) 970#ifdef _KERNEL 971 m = *mp = NULL; 972#else 973 ; 974#endif 975 976 if (pass & FR_PREAUTH) { 977 READ_ENTER(&ipf_auth); 978 if ((fin->fin_fr = ipauth) && 979 (pass = fr_scanlist(0, ip, fin, m))) { 980 ATOMIC_INCL(fr_authstats.fas_hits); 981 } else { 982 ATOMIC_INCL(fr_authstats.fas_miss); 983 } 984 RWLOCK_EXIT(&ipf_auth); 985 } 986 987 fin->fin_fr = fr; 988 if ((pass & (FR_KEEPFRAG|FR_KEEPSTATE)) == FR_KEEPFRAG) { 989 if (fin->fin_fi.fi_fl & FI_FRAG) { 990 if (ipfr_newfrag(ip, fin, pass) == -1) { 991 ATOMIC_INCL(frstats[out].fr_bnfr); 992 } else { 993 ATOMIC_INCL(frstats[out].fr_nfr); 994 } 995 } else { 996 ATOMIC_INCL(frstats[out].fr_cfr); 997 } 998 } 999 if (pass & FR_KEEPSTATE) { 1000 if (fr_addstate(ip, fin, 0) == NULL) { 1001 ATOMIC_INCL(frstats[out].fr_bads); 1002 } else { 1003 ATOMIC_INCL(frstats[out].fr_ads); 1004 } 1005 } 1006 } else if (fr != NULL) { 1007 pass = fr->fr_flags; 1008 if (pass & FR_LOGFIRST) 1009 pass &= ~(FR_LOGFIRST|FR_LOG); 1010 } 1011 1012#if (BSD >= 199306) && (defined(_KERNEL) || defined(KERNEL)) 1013 if (securelevel <= 0) 1014#endif 1015 if (fr && fr->fr_func && !(pass & FR_CALLNOW)) 1016 pass = (*fr->fr_func)(pass, ip, fin); 1017 1018 /* 1019 * Only count/translate packets which will be passed on, out the 1020 * interface. 1021 */ 1022 if (out && (pass & FR_PASS)) { 1023#ifdef USE_INET6 1024 if (v == 6) 1025 list = ipacct6[1][fr_active]; 1026 else 1027#endif 1028 list = ipacct[1][fr_active]; 1029 if ((fin->fin_fr = list) && 1030 (fr_scanlist(FR_NOMATCH, ip, fin, m) & FR_ACCOUNT)) { 1031 ATOMIC_INCL(frstats[1].fr_acct); 1032 } 1033 fin->fin_fr = fr; 1034 changed = ip_natout(ip, fin); 1035 } else 1036 fin->fin_fr = fr; 1037 RWLOCK_EXIT(&ipf_mutex); 1038 1039#ifdef IPFILTER_LOG 1040 if ((fr_flags & FF_LOGGING) || (pass & FR_LOGMASK)) { 1041 if ((fr_flags & FF_LOGNOMATCH) && (pass & FR_NOMATCH)) { 1042 pass |= FF_LOGNOMATCH; 1043 ATOMIC_INCL(frstats[out].fr_npkl); 1044 goto logit; 1045 } else if (((pass & FR_LOGMASK) == FR_LOGP) || 1046 ((pass & FR_PASS) && (fr_flags & FF_LOGPASS))) { 1047 if ((pass & FR_LOGMASK) != FR_LOGP) 1048 pass |= FF_LOGPASS; 1049 ATOMIC_INCL(frstats[out].fr_ppkl); 1050 goto logit; 1051 } else if (((pass & FR_LOGMASK) == FR_LOGB) || 1052 ((pass & FR_BLOCK) && (fr_flags & FF_LOGBLOCK))) { 1053 if ((pass & FR_LOGMASK) != FR_LOGB) 1054 pass |= FF_LOGBLOCK; 1055 ATOMIC_INCL(frstats[out].fr_bpkl); 1056logit: 1057 if (!IPLLOG(pass, ip, fin, m)) { 1058 ATOMIC_INCL(frstats[out].fr_skip); 1059 if ((pass & (FR_PASS|FR_LOGORBLOCK)) == 1060 (FR_PASS|FR_LOGORBLOCK)) 1061 pass ^= FR_PASS|FR_BLOCK; 1062 } 1063 } 1064 } 1065#endif /* IPFILTER_LOG */ 1066 1067#ifndef __FreeBSD__ 1068 if ((out) && (v == 4)) 1069 ip->ip_id = htons(ip->ip_id); 1070#endif 1071 1072#ifdef _KERNEL 1073 /* 1074 * Only allow FR_DUP to work if a rule matched - it makes no sense to 1075 * set FR_DUP as a "default" as there are no instructions about where 1076 * to send the packet. 1077 */ 1078 if (fr && (pass & FR_DUP)) 1079# if SOLARIS 1080 mc = dupmsg(m); 1081# else 1082# ifndef linux 1083 mc = m_copy(m, 0, M_COPYALL); 1084# else 1085 ; 1086# endif 1087# endif 1088#endif 1089 if (pass & FR_PASS) { 1090 ATOMIC_INCL(frstats[out].fr_pass); 1091 } else if (pass & FR_BLOCK) { 1092 ATOMIC_INCL(frstats[out].fr_block); 1093 /* 1094 * Should we return an ICMP packet to indicate error 1095 * status passing through the packet filter ? 1096 * WARNING: ICMP error packets AND TCP RST packets should 1097 * ONLY be sent in repsonse to incoming packets. Sending them 1098 * in response to outbound packets can result in a panic on 1099 * some operating systems. 1100 */ 1101 if (!out) { 1102#ifdef _KERNEL 1103 if (pass & FR_RETICMP) { 1104 int dst; 1105 1106 if ((pass & FR_RETMASK) == FR_FAKEICMP) 1107 dst = 1; 1108 else 1109 dst = 0; 1110 send_icmp_err(ip, ICMP_UNREACH, fin, dst); 1111 ATOMIC_INCL(frstats[0].fr_ret); 1112 } else if (((pass & FR_RETMASK) == FR_RETRST) && 1113 !(fin->fin_fi.fi_fl & FI_SHORT)) { 1114 if (send_reset(ip, fin) == 0) { 1115 ATOMIC_INCL(frstats[1].fr_ret); 1116 } 1117 } 1118#else 1119 if ((pass & FR_RETMASK) == FR_RETICMP) { 1120 verbose("- ICMP unreachable sent\n"); 1121 ATOMIC_INCL(frstats[0].fr_ret); 1122 } else if ((pass & FR_RETMASK) == FR_FAKEICMP) { 1123 verbose("- forged ICMP unreachable sent\n"); 1124 ATOMIC_INCL(frstats[0].fr_ret); 1125 } else if (((pass & FR_RETMASK) == FR_RETRST) && 1126 !(fin->fin_fi.fi_fl & FI_SHORT)) { 1127 verbose("- TCP RST sent\n"); 1128 ATOMIC_INCL(frstats[1].fr_ret); 1129 } 1130#endif 1131 } else { 1132 if (pass & FR_RETRST) 1133 error = ECONNRESET; 1134 } 1135 } 1136 1137 /* 1138 * If we didn't drop off the bottom of the list of rules (and thus 1139 * the 'current' rule fr is not NULL), then we may have some extra 1140 * instructions about what to do with a packet. 1141 * Once we're finished return to our caller, freeing the packet if 1142 * we are dropping it (* BSD ONLY *). 1143 */ 1144 if ((changed == -1) && (pass & FR_PASS)) { 1145 pass &= ~FR_PASS; 1146 pass |= FR_BLOCK; 1147 } 1148#if defined(_KERNEL) 1149# if !SOLARIS 1150# if !defined(linux) 1151 if (fr) { 1152 frdest_t *fdp = &fr->fr_tif; 1153 1154 if (((pass & FR_FASTROUTE) && !out) || 1155 (fdp->fd_ifp && fdp->fd_ifp != (struct ifnet *)-1)) { 1156 if (ipfr_fastroute(m, fin, fdp) == 0) 1157 m = *mp = NULL; 1158 } 1159 if (mc) 1160 ipfr_fastroute(mc, fin, &fr->fr_dif); 1161 } 1162 if (!(pass & FR_PASS) && m) 1163 m_freem(m); 1164# ifdef __sgi 1165 else if (changed && up && m) 1166 m_copyback(m, 0, up, hbuf); 1167# endif 1168# endif /* !linux */ 1169# else /* !SOLARIS */ 1170 if (fr) { 1171 frdest_t *fdp = &fr->fr_tif; 1172 1173 if (((pass & FR_FASTROUTE) && !out) || 1174 (fdp->fd_ifp && fdp->fd_ifp != (struct ifnet *)-1)) { 1175 if (ipfr_fastroute(ip, m, mp, fin, fdp) == 0) 1176 m = *mp = NULL; 1177 } 1178 if (mc) 1179 ipfr_fastroute(ip, mc, mp, fin, &fr->fr_dif); 1180 } 1181# endif /* !SOLARIS */ 1182 return (pass & FR_PASS) ? 0 : error; 1183#else /* _KERNEL */ 1184 if (pass & FR_NOMATCH) 1185 return 1; 1186 if (pass & FR_PASS) 1187 return 0; 1188 if (pass & FR_AUTH) 1189 return -2; 1190 return -1; 1191#endif /* _KERNEL */ 1192} 1193 1194 1195/* 1196 * ipf_cksum 1197 * addr should be 16bit aligned and len is in bytes. 1198 * length is in bytes 1199 */ 1200u_short ipf_cksum(addr, len) 1201register u_short *addr; 1202register int len; 1203{ 1204 register u_32_t sum = 0; 1205 1206 for (sum = 0; len > 1; len -= 2) 1207 sum += *addr++; 1208 1209 /* mop up an odd byte, if necessary */ 1210 if (len == 1) 1211 sum += *(u_char *)addr; 1212 1213 /* 1214 * add back carry outs from top 16 bits to low 16 bits 1215 */ 1216 sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */ 1217 sum += (sum >> 16); /* add carry */ 1218 return (u_short)(~sum); 1219} 1220 1221 1222/* 1223 * NB: This function assumes we've pullup'd enough for all of the IP header 1224 * and the TCP header. We also assume that data blocks aren't allocated in 1225 * odd sizes. 1226 */ 1227u_short fr_tcpsum(m, ip, tcp) 1228mb_t *m; 1229ip_t *ip; 1230tcphdr_t *tcp; 1231{ 1232 u_short *sp, slen, ts; 1233 u_int sum, sum2; 1234 int hlen; 1235 1236 /* 1237 * Add up IP Header portion 1238 */ 1239 hlen = ip->ip_hl << 2; 1240 slen = ip->ip_len - hlen; 1241 sum = htons((u_short)ip->ip_p); 1242 sum += htons(slen); 1243 sp = (u_short *)&ip->ip_src; 1244 sum += *sp++; /* ip_src */ 1245 sum += *sp++; 1246 sum += *sp++; /* ip_dst */ 1247 sum += *sp++; 1248 ts = tcp->th_sum; 1249 tcp->th_sum = 0; 1250#ifdef KERNEL 1251# if SOLARIS 1252 sum2 = ip_cksum(m, hlen, sum); /* hlen == offset */ 1253 sum2 = (sum2 & 0xffff) + (sum2 >> 16); 1254 sum2 = ~sum2 & 0xffff; 1255# else /* SOLARIS */ 1256# if defined(BSD) || defined(sun) 1257# if BSD >= 199306 1258 m->m_data += hlen; 1259# else 1260 m->m_off += hlen; 1261# endif 1262 m->m_len -= hlen; 1263 sum2 = in_cksum(m, slen); 1264 m->m_len += hlen; 1265# if BSD >= 199306 1266 m->m_data -= hlen; 1267# else 1268 m->m_off -= hlen; 1269# endif 1270 /* 1271 * Both sum and sum2 are partial sums, so combine them together. 1272 */ 1273 sum = (sum & 0xffff) + (sum >> 16); 1274 sum = ~sum & 0xffff; 1275 sum2 += sum; 1276 sum2 = (sum2 & 0xffff) + (sum2 >> 16); 1277# else /* defined(BSD) || defined(sun) */ 1278{ 1279 union { 1280 u_char c[2]; 1281 u_short s; 1282 } bytes; 1283 u_short len = ip->ip_len; 1284# if defined(__sgi) 1285 int add; 1286# endif 1287 1288 /* 1289 * Add up IP Header portion 1290 */ 1291 sp = (u_short *)&ip->ip_src; 1292 len -= (ip->ip_hl << 2); 1293 sum = ntohs(IPPROTO_TCP); 1294 sum += htons(len); 1295 sum += *sp++; /* ip_src */ 1296 sum += *sp++; 1297 sum += *sp++; /* ip_dst */ 1298 sum += *sp++; 1299 if (sp != (u_short *)tcp) 1300 sp = (u_short *)tcp; 1301 sum += *sp++; /* sport */ 1302 sum += *sp++; /* dport */ 1303 sum += *sp++; /* seq */ 1304 sum += *sp++; 1305 sum += *sp++; /* ack */ 1306 sum += *sp++; 1307 sum += *sp++; /* off */ 1308 sum += *sp++; /* win */ 1309 sum += *sp++; /* Skip over checksum */ 1310 sum += *sp++; /* urp */ 1311 1312# ifdef __sgi 1313 /* 1314 * In case we had to copy the IP & TCP header out of mbufs, 1315 * skip over the mbuf bits which are the header 1316 */ 1317 if ((caddr_t)ip != mtod(m, caddr_t)) { 1318 hlen = (caddr_t)sp - (caddr_t)ip; 1319 while (hlen) { 1320 add = MIN(hlen, m->m_len); 1321 sp = (u_short *)(mtod(m, caddr_t) + add); 1322 hlen -= add; 1323 if (add == m->m_len) { 1324 m = m->m_next; 1325 if (!hlen) { 1326 if (!m) 1327 break; 1328 sp = mtod(m, u_short *); 1329 } 1330 PANIC((!m),("fr_tcpsum(1): not enough data")); 1331 } 1332 } 1333 } 1334# endif 1335 1336 if (!(len -= sizeof(*tcp))) 1337 goto nodata; 1338 while (len > 1) { 1339 if (((caddr_t)sp - mtod(m, caddr_t)) >= m->m_len) { 1340 m = m->m_next; 1341 PANIC((!m),("fr_tcpsum(2): not enough data")); 1342 sp = mtod(m, u_short *); 1343 } 1344 if (((caddr_t)(sp + 1) - mtod(m, caddr_t)) > m->m_len) { 1345 bytes.c[0] = *(u_char *)sp; 1346 m = m->m_next; 1347 PANIC((!m),("fr_tcpsum(3): not enough data")); 1348 sp = mtod(m, u_short *); 1349 bytes.c[1] = *(u_char *)sp; 1350 sum += bytes.s; 1351 sp = (u_short *)((u_char *)sp + 1); 1352 } 1353 if ((u_long)sp & 1) { 1354 bcopy((char *)sp++, (char *)&bytes.s, sizeof(bytes.s)); 1355 sum += bytes.s; 1356 } else 1357 sum += *sp++; 1358 len -= 2; 1359 } 1360 if (len) 1361 sum += ntohs(*(u_char *)sp << 8); 1362nodata: 1363 while (sum > 0xffff) 1364 sum = (sum & 0xffff) + (sum >> 16); 1365 sum2 = (u_short)(~sum & 0xffff); 1366} 1367# endif /* defined(BSD) || defined(sun) */ 1368# endif /* SOLARIS */ 1369#else /* KERNEL */ 1370 sum2 = 0; 1371#endif /* KERNEL */ 1372 tcp->th_sum = ts; 1373 return sum2; 1374} 1375 1376 1377#if defined(_KERNEL) && ( ((BSD < 199306) && !SOLARIS) || defined(__sgi) ) 1378/* 1379 * Copyright (c) 1982, 1986, 1988, 1991, 1993 1380 * The Regents of the University of California. All rights reserved. 1381 * 1382 * Redistribution and use in source and binary forms, with or without 1383 * modification, are permitted provided that the following conditions 1384 * are met: 1385 * 1. Redistributions of source code must retain the above copyright 1386 * notice, this list of conditions and the following disclaimer. 1387 * 2. Redistributions in binary form must reproduce the above copyright 1388 * notice, this list of conditions and the following disclaimer in the 1389 * documentation and/or other materials provided with the distribution. 1390 * 3. All advertising materials mentioning features or use of this software 1391 * must display the following acknowledgement: 1392 * This product includes software developed by the University of 1393 * California, Berkeley and its contributors. 1394 * 4. Neither the name of the University nor the names of its contributors 1395 * may be used to endorse or promote products derived from this software 1396 * without specific prior written permission. 1397 * 1398 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 1399 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1400 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1401 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 1402 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1403 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 1404 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 1405 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 1406 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 1407 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 1408 * SUCH DAMAGE. 1409 * 1410 * @(#)uipc_mbuf.c 8.2 (Berkeley) 1/4/94 1411 * $Id: fil.c,v 2.35.2.27 2000/10/26 21:20:54 darrenr Exp $ 1412 */ 1413/* 1414 * Copy data from an mbuf chain starting "off" bytes from the beginning, 1415 * continuing for "len" bytes, into the indicated buffer. 1416 */ 1417void 1418m_copydata(m, off, len, cp) 1419 register mb_t *m; 1420 register int off; 1421 register int len; 1422 caddr_t cp; 1423{ 1424 register unsigned count; 1425 1426 if (off < 0 || len < 0) 1427 panic("m_copydata"); 1428 while (off > 0) { 1429 if (m == 0) 1430 panic("m_copydata"); 1431 if (off < m->m_len) 1432 break; 1433 off -= m->m_len; 1434 m = m->m_next; 1435 } 1436 while (len > 0) { 1437 if (m == 0) 1438 panic("m_copydata"); 1439 count = MIN(m->m_len - off, len); 1440 bcopy(mtod(m, caddr_t) + off, cp, count); 1441 len -= count; 1442 cp += count; 1443 off = 0; 1444 m = m->m_next; 1445 } 1446} 1447 1448 1449# ifndef linux 1450/* 1451 * Copy data from a buffer back into the indicated mbuf chain, 1452 * starting "off" bytes from the beginning, extending the mbuf 1453 * chain if necessary. 1454 */ 1455void 1456m_copyback(m0, off, len, cp) 1457 struct mbuf *m0; 1458 register int off; 1459 register int len; 1460 caddr_t cp; 1461{ 1462 register int mlen; 1463 register struct mbuf *m = m0, *n; 1464 int totlen = 0; 1465 1466 if (m0 == 0) 1467 return; 1468 while (off > (mlen = m->m_len)) { 1469 off -= mlen; 1470 totlen += mlen; 1471 if (m->m_next == 0) { 1472 n = m_getclr(M_DONTWAIT, m->m_type); 1473 if (n == 0) 1474 goto out; 1475 n->m_len = min(MLEN, len + off); 1476 m->m_next = n; 1477 } 1478 m = m->m_next; 1479 } 1480 while (len > 0) { 1481 mlen = min (m->m_len - off, len); 1482 bcopy(cp, off + mtod(m, caddr_t), (unsigned)mlen); 1483 cp += mlen; 1484 len -= mlen; 1485 mlen += off; 1486 off = 0; 1487 totlen += mlen; 1488 if (len == 0) 1489 break; 1490 if (m->m_next == 0) { 1491 n = m_get(M_DONTWAIT, m->m_type); 1492 if (n == 0) 1493 break; 1494 n->m_len = min(MLEN, len); 1495 m->m_next = n; 1496 } 1497 m = m->m_next; 1498 } 1499out: 1500#if 0 1501 if (((m = m0)->m_flags & M_PKTHDR) && (m->m_pkthdr.len < totlen)) 1502 m->m_pkthdr.len = totlen; 1503#endif 1504 return; 1505} 1506# endif /* linux */ 1507#endif /* (_KERNEL) && ( ((BSD < 199306) && !SOLARIS) || __sgi) */ 1508 1509 1510frgroup_t *fr_findgroup(num, flags, which, set, fgpp) 1511u_32_t num, flags; 1512minor_t which; 1513int set; 1514frgroup_t ***fgpp; 1515{ 1516 frgroup_t *fg, **fgp; 1517 1518 if (which == IPL_LOGAUTH) 1519 fgp = &ipfgroups[2][set]; 1520 else if (flags & FR_ACCOUNT) 1521 fgp = &ipfgroups[1][set]; 1522 else if (flags & (FR_OUTQUE|FR_INQUE)) 1523 fgp = &ipfgroups[0][set]; 1524 else 1525 return NULL; 1526 num &= 0xffff; 1527 1528 while ((fg = *fgp)) 1529 if (fg->fg_num == num) 1530 break; 1531 else 1532 fgp = &fg->fg_next; 1533 if (fgpp) 1534 *fgpp = fgp; 1535 return fg; 1536} 1537 1538 1539frgroup_t *fr_addgroup(num, fp, which, set) 1540u_32_t num; 1541frentry_t *fp; 1542minor_t which; 1543int set; 1544{ 1545 frgroup_t *fg, **fgp; 1546 1547 if ((fg = fr_findgroup(num, fp->fr_flags, which, set, &fgp))) 1548 return fg; 1549 1550 KMALLOC(fg, frgroup_t *); 1551 if (fg) { 1552 fg->fg_num = num; 1553 fg->fg_next = *fgp; 1554 fg->fg_head = fp; 1555 fg->fg_start = &fp->fr_grp; 1556 *fgp = fg; 1557 } 1558 return fg; 1559} 1560 1561 1562void fr_delgroup(num, flags, which, set) 1563u_32_t num, flags; 1564minor_t which; 1565int set; 1566{ 1567 frgroup_t *fg, **fgp; 1568 1569 if (!(fg = fr_findgroup(num, flags, which, set, &fgp))) 1570 return; 1571 1572 *fgp = fg->fg_next; 1573 KFREE(fg); 1574} 1575 1576 1577 1578/* 1579 * recursively flush rules from the list, descending groups as they are 1580 * encountered. if a rule is the head of a group and it has lost all its 1581 * group members, then also delete the group reference. 1582 */ 1583static int frflushlist(set, unit, nfreedp, listp) 1584int set; 1585minor_t unit; 1586int *nfreedp; 1587frentry_t **listp; 1588{ 1589 register int freed = 0, i; 1590 register frentry_t *fp; 1591 1592 while ((fp = *listp)) { 1593 *listp = fp->fr_next; 1594 if (fp->fr_grp) { 1595 i = frflushlist(set, unit, nfreedp, &fp->fr_grp); 1596 MUTEX_ENTER(&ipf_rw); 1597 fp->fr_ref -= i; 1598 MUTEX_EXIT(&ipf_rw); 1599 } 1600 1601 ATOMIC_DEC32(fp->fr_ref); 1602 if (fp->fr_grhead) { 1603 fr_delgroup(fp->fr_grhead, fp->fr_flags, 1604 unit, set); 1605 fp->fr_grhead = 0; 1606 } 1607 if (fp->fr_ref == 0) { 1608 KFREE(fp); 1609 freed++; 1610 } else 1611 fp->fr_next = NULL; 1612 } 1613 *nfreedp += freed; 1614 return freed; 1615} 1616 1617 1618int frflush(unit, flags) 1619minor_t unit; 1620int flags; 1621{ 1622 int flushed = 0, set; 1623 1624 if (unit != IPL_LOGIPF) 1625 return 0; 1626 WRITE_ENTER(&ipf_mutex); 1627 bzero((char *)frcache, sizeof(frcache[0]) * 2); 1628 1629 set = fr_active; 1630 if (flags & FR_INACTIVE) 1631 set = 1 - set; 1632 1633 if (flags & FR_OUTQUE) { 1634#ifdef USE_INET6 1635 (void) frflushlist(set, unit, &flushed, &ipfilter6[1][set]); 1636 (void) frflushlist(set, unit, &flushed, &ipacct6[1][set]); 1637#endif 1638 (void) frflushlist(set, unit, &flushed, &ipfilter[1][set]); 1639 (void) frflushlist(set, unit, &flushed, &ipacct[1][set]); 1640 } 1641 if (flags & FR_INQUE) { 1642#ifdef USE_INET6 1643 (void) frflushlist(set, unit, &flushed, &ipfilter6[0][set]); 1644 (void) frflushlist(set, unit, &flushed, &ipacct6[0][set]); 1645#endif 1646 (void) frflushlist(set, unit, &flushed, &ipfilter[0][set]); 1647 (void) frflushlist(set, unit, &flushed, &ipacct[0][set]); 1648 } 1649 RWLOCK_EXIT(&ipf_mutex); 1650 return flushed; 1651} 1652 1653 1654char *memstr(src, dst, slen, dlen) 1655char *src, *dst; 1656int slen, dlen; 1657{ 1658 char *s = NULL; 1659 1660 while (dlen >= slen) { 1661 if (bcmp(src, dst, slen) == 0) { 1662 s = dst; 1663 break; 1664 } 1665 dst++; 1666 dlen--; 1667 } 1668 return s; 1669} 1670 1671 1672void fixskip(listp, rp, addremove) 1673frentry_t **listp, *rp; 1674int addremove; 1675{ 1676 frentry_t *fp; 1677 int rules = 0, rn = 0; 1678 1679 for (fp = *listp; fp && (fp != rp); fp = fp->fr_next, rules++) 1680 ; 1681 1682 if (!fp) 1683 return; 1684 1685 for (fp = *listp; fp && (fp != rp); fp = fp->fr_next, rn++) 1686 if (fp->fr_skip && (rn + fp->fr_skip >= rules)) 1687 fp->fr_skip += addremove; 1688} 1689 1690 1691#ifdef _KERNEL 1692/* 1693 * count consecutive 1's in bit mask. If the mask generated by counting 1694 * consecutive 1's is different to that passed, return -1, else return # 1695 * of bits. 1696 */ 1697int countbits(ip) 1698u_32_t ip; 1699{ 1700 u_32_t ipn; 1701 int cnt = 0, i, j; 1702 1703 ip = ipn = ntohl(ip); 1704 for (i = 32; i; i--, ipn *= 2) 1705 if (ipn & 0x80000000) 1706 cnt++; 1707 else 1708 break; 1709 ipn = 0; 1710 for (i = 32, j = cnt; i; i--, j--) { 1711 ipn *= 2; 1712 if (j > 0) 1713 ipn++; 1714 } 1715 if (ipn == ip) 1716 return cnt; 1717 return -1; 1718} 1719 1720 1721/* 1722 * return the first IP Address associated with an interface 1723 */ 1724int fr_ifpaddr(v, ifptr, inp) 1725int v; 1726void *ifptr; 1727struct in_addr *inp; 1728{ 1729# ifdef USE_INET6 1730 struct in6_addr *inp6 = NULL; 1731# endif 1732# if SOLARIS 1733 ill_t *ill = ifptr; 1734# else 1735 struct ifnet *ifp = ifptr; 1736# endif 1737 struct in_addr in; 1738 1739# if SOLARIS 1740# ifdef USE_INET6 1741 if (v == 6) { 1742 struct in6_addr in6; 1743 1744 /* 1745 * First is always link local. 1746 */ 1747 if (ill->ill_ipif->ipif_next) 1748 in6 = ill->ill_ipif->ipif_next->ipif_v6lcl_addr; 1749 else 1750 bzero((char *)&in6, sizeof(in6)); 1751 bcopy((char *)&in6, (char *)inp, sizeof(in6)); 1752 } else 1753# endif 1754 { 1755 in.s_addr = ill->ill_ipif->ipif_local_addr; 1756 *inp = in; 1757 } 1758# else /* SOLARIS */ 1759# if linux 1760 ; 1761# else /* linux */ 1762 struct sockaddr_in *sin; 1763 struct ifaddr *ifa; 1764 1765# if (__FreeBSD_version >= 300000) 1766 ifa = TAILQ_FIRST(&ifp->if_addrhead); 1767# else 1768# if defined(__NetBSD__) || defined(__OpenBSD__) 1769 ifa = ifp->if_addrlist.tqh_first; 1770# else 1771# if defined(__sgi) && defined(IFF_DRVRLOCK) /* IRIX 6 */ 1772 ifa = &((struct in_ifaddr *)ifp->in_ifaddr)->ia_ifa; 1773# else 1774 ifa = ifp->if_addrlist; 1775# endif 1776# endif /* __NetBSD__ || __OpenBSD__ */ 1777# endif /* __FreeBSD_version >= 300000 */ 1778# if (BSD < 199306) && !(/*IRIX6*/defined(__sgi) && defined(IFF_DRVRLOCK)) 1779 sin = (struct sockaddr_in *)&ifa->ifa_addr; 1780# else 1781 sin = (struct sockaddr_in *)ifa->ifa_addr; 1782 while (sin && ifa) { 1783 if ((v == 4) && (sin->sin_family == AF_INET)) 1784 break; 1785# ifdef USE_INET6 1786 if ((v == 6) && (sin->sin_family == AF_INET6)) { 1787 inp6 = &((struct sockaddr_in6 *)sin)->sin6_addr; 1788 if (!IN6_IS_ADDR_LINKLOCAL(inp6) && 1789 !IN6_IS_ADDR_LOOPBACK(inp6)) 1790 break; 1791 } 1792# endif 1793# if (__FreeBSD_version >= 300000) 1794 ifa = TAILQ_NEXT(ifa, ifa_link); 1795# else 1796# if defined(__NetBSD__) || defined(__OpenBSD__) 1797 ifa = ifa->ifa_list.tqe_next; 1798# else 1799 ifa = ifa->ifa_next; 1800# endif 1801# endif /* __FreeBSD_version >= 300000 */ 1802 if (ifa) 1803 sin = (struct sockaddr_in *)ifa->ifa_addr; 1804 } 1805 if (ifa == NULL) 1806 sin = NULL; 1807 if (sin == NULL) 1808 return -1; 1809# endif /* (BSD < 199306) && (!__sgi && IFF_DRVLOCK) */ 1810# ifdef USE_INET6 1811 if (v == 6) 1812 bcopy((char *)inp6, (char *)inp, sizeof(*inp6)); 1813 else 1814# endif 1815 { 1816 in = sin->sin_addr; 1817 *inp = in; 1818 } 1819# endif /* linux */ 1820# endif /* SOLARIS */ 1821 return 0; 1822} 1823 1824 1825static void frsynclist(fr) 1826register frentry_t *fr; 1827{ 1828 for (; fr; fr = fr->fr_next) { 1829 if (fr->fr_ifa != NULL) { 1830 fr->fr_ifa = GETUNIT(fr->fr_ifname, fr->fr_ip.fi_v); 1831 if (fr->fr_ifa == NULL) 1832 fr->fr_ifa = (void *)-1; 1833 } 1834 if (fr->fr_grp) 1835 frsynclist(fr->fr_grp); 1836 } 1837} 1838 1839 1840void frsync() 1841{ 1842# if !SOLARIS 1843 register struct ifnet *ifp; 1844 1845# if defined(__OpenBSD__) || ((NetBSD >= 199511) && (NetBSD < 1991011)) || \ 1846 (defined(__FreeBSD_version) && (__FreeBSD_version >= 300000)) 1847# if (NetBSD >= 199905) || defined(__OpenBSD__) 1848 for (ifp = ifnet.tqh_first; ifp; ifp = ifp->if_list.tqe_next) 1849# else 1850 for (ifp = ifnet.tqh_first; ifp; ifp = ifp->if_link.tqe_next) 1851# endif 1852# else 1853 for (ifp = ifnet; ifp; ifp = ifp->if_next) 1854# endif 1855 { 1856 ip_natsync(ifp); 1857 ip_statesync(ifp); 1858 } 1859 ip_natsync((struct ifnet *)-1); 1860# endif 1861 1862 WRITE_ENTER(&ipf_mutex); 1863 frsynclist(ipacct[0][fr_active]); 1864 frsynclist(ipacct[1][fr_active]); 1865 frsynclist(ipfilter[0][fr_active]); 1866 frsynclist(ipfilter[1][fr_active]); 1867#ifdef USE_INET6 1868 frsynclist(ipacct6[0][fr_active]); 1869 frsynclist(ipacct6[1][fr_active]); 1870 frsynclist(ipfilter6[0][fr_active]); 1871 frsynclist(ipfilter6[1][fr_active]); 1872#endif 1873 RWLOCK_EXIT(&ipf_mutex); 1874} 1875 1876 1877/* 1878 * In the functions below, bcopy() is called because the pointer being 1879 * copied _from_ in this instance is a pointer to a char buf (which could 1880 * end up being unaligned) and on the kernel's local stack. 1881 */ 1882int ircopyptr(a, b, c) 1883void *a, *b; 1884size_t c; 1885{ 1886 caddr_t ca; 1887 int err; 1888 1889#if SOLARIS 1890 if (copyin(a, (char *)&ca, sizeof(ca))) 1891 return EFAULT; 1892#else 1893 bcopy(a, &ca, sizeof(ca)); 1894#endif 1895 err = copyin(ca, b, c); 1896 if (err) 1897 err = EFAULT; 1898 return err; 1899} 1900 1901 1902int iwcopyptr(a, b, c) 1903void *a, *b; 1904size_t c; 1905{ 1906 caddr_t ca; 1907 int err; 1908 1909#if SOLARIS 1910 if (copyin(b, (char *)&ca, sizeof(ca))) 1911 return EFAULT; 1912#else 1913 bcopy(b, &ca, sizeof(ca)); 1914#endif 1915 err = copyout(a, ca, c); 1916 if (err) 1917 err = EFAULT; 1918 return err; 1919} 1920 1921#else /* _KERNEL */ 1922 1923 1924/* 1925 * return the first IP Address associated with an interface 1926 */ 1927int fr_ifpaddr(v, ifptr, inp) 1928int v; 1929void *ifptr; 1930struct in_addr *inp; 1931{ 1932 return 0; 1933} 1934 1935 1936int ircopyptr(a, b, c) 1937void *a, *b; 1938size_t c; 1939{ 1940 caddr_t ca; 1941 1942 bcopy(a, &ca, sizeof(ca)); 1943 bcopy(ca, b, c); 1944 return 0; 1945} 1946 1947 1948int iwcopyptr(a, b, c) 1949void *a, *b; 1950size_t c; 1951{ 1952 caddr_t ca; 1953 1954 bcopy(b, &ca, sizeof(ca)); 1955 bcopy(a, ca, c); 1956 return 0; 1957} 1958 1959 1960#endif 1961 1962 1963int fr_lock(data, lockp) 1964caddr_t data; 1965int *lockp; 1966{ 1967 int arg, error; 1968 1969 error = IRCOPY(data, (caddr_t)&arg, sizeof(arg)); 1970 if (!error) { 1971 error = IWCOPY((caddr_t)lockp, data, sizeof(*lockp)); 1972 if (!error) 1973 *lockp = arg; 1974 } 1975 return error; 1976} 1977 1978 1979void fr_getstat(fiop) 1980friostat_t *fiop; 1981{ 1982 bcopy((char *)frstats, (char *)fiop->f_st, sizeof(filterstats_t) * 2); 1983 fiop->f_locks[0] = fr_state_lock; 1984 fiop->f_locks[1] = fr_nat_lock; 1985 fiop->f_locks[2] = fr_frag_lock; 1986 fiop->f_locks[3] = fr_auth_lock; 1987 fiop->f_fin[0] = ipfilter[0][0]; 1988 fiop->f_fin[1] = ipfilter[0][1]; 1989 fiop->f_fout[0] = ipfilter[1][0]; 1990 fiop->f_fout[1] = ipfilter[1][1]; 1991 fiop->f_acctin[0] = ipacct[0][0]; 1992 fiop->f_acctin[1] = ipacct[0][1]; 1993 fiop->f_acctout[0] = ipacct[1][0]; 1994 fiop->f_acctout[1] = ipacct[1][1]; 1995#ifdef USE_INET6 1996 fiop->f_fin6[0] = ipfilter6[0][0]; 1997 fiop->f_fin6[1] = ipfilter6[0][1]; 1998 fiop->f_fout6[0] = ipfilter6[1][0]; 1999 fiop->f_fout6[1] = ipfilter6[1][1]; 2000 fiop->f_acctin6[0] = ipacct6[0][0]; 2001 fiop->f_acctin6[1] = ipacct6[0][1]; 2002 fiop->f_acctout6[0] = ipacct6[1][0]; 2003 fiop->f_acctout6[1] = ipacct6[1][1]; 2004#else 2005 fiop->f_fin6[0] = NULL; 2006 fiop->f_fin6[1] = NULL; 2007 fiop->f_fout6[0] = NULL; 2008 fiop->f_fout6[1] = NULL; 2009 fiop->f_acctin6[0] = NULL; 2010 fiop->f_acctin6[1] = NULL; 2011 fiop->f_acctout6[0] = NULL; 2012 fiop->f_acctout6[1] = NULL; 2013#endif 2014 fiop->f_active = fr_active; 2015 fiop->f_froute[0] = ipl_frouteok[0]; 2016 fiop->f_froute[1] = ipl_frouteok[1]; 2017 2018 fiop->f_running = fr_running; 2019 fiop->f_groups[0][0] = ipfgroups[0][0]; 2020 fiop->f_groups[0][1] = ipfgroups[0][1]; 2021 fiop->f_groups[1][0] = ipfgroups[1][0]; 2022 fiop->f_groups[1][1] = ipfgroups[1][1]; 2023 fiop->f_groups[2][0] = ipfgroups[2][0]; 2024 fiop->f_groups[2][1] = ipfgroups[2][1]; 2025#ifdef IPFILTER_LOG 2026 fiop->f_logging = 1; 2027#else 2028 fiop->f_logging = 0; 2029#endif 2030 fiop->f_defpass = fr_pass; 2031 strncpy(fiop->f_version, ipfilter_version, sizeof(fiop->f_version)); 2032} 2033 2034 2035#ifdef USE_INET6 2036int icmptoicmp6types[ICMP_MAXTYPE+1] = { 2037 ICMP6_ECHO_REPLY, /* 0: ICMP_ECHOREPLY */ 2038 -1, /* 1: UNUSED */ 2039 -1, /* 2: UNUSED */ 2040 ICMP6_DST_UNREACH, /* 3: ICMP_UNREACH */ 2041 -1, /* 4: ICMP_SOURCEQUENCH */ 2042 ND_REDIRECT, /* 5: ICMP_REDIRECT */ 2043 -1, /* 6: UNUSED */ 2044 -1, /* 7: UNUSED */ 2045 ICMP6_ECHO_REQUEST, /* 8: ICMP_ECHO */ 2046 -1, /* 9: UNUSED */ 2047 -1, /* 10: UNUSED */ 2048 ICMP6_TIME_EXCEEDED, /* 11: ICMP_TIMXCEED */ 2049 ICMP6_PARAM_PROB, /* 12: ICMP_PARAMPROB */ 2050 -1, /* 13: ICMP_TSTAMP */ 2051 -1, /* 14: ICMP_TSTAMPREPLY */ 2052 -1, /* 15: ICMP_IREQ */ 2053 -1, /* 16: ICMP_IREQREPLY */ 2054 -1, /* 17: ICMP_MASKREQ */ 2055 -1, /* 18: ICMP_MASKREPLY */ 2056}; 2057 2058 2059int icmptoicmp6unreach[ICMP_MAX_UNREACH] = { 2060 ICMP6_DST_UNREACH_ADDR, /* 0: ICMP_UNREACH_NET */ 2061 ICMP6_DST_UNREACH_ADDR, /* 1: ICMP_UNREACH_HOST */ 2062 -1, /* 2: ICMP_UNREACH_PROTOCOL */ 2063 ICMP6_DST_UNREACH_NOPORT, /* 3: ICMP_UNREACH_PORT */ 2064 -1, /* 4: ICMP_UNREACH_NEEDFRAG */ 2065 ICMP6_DST_UNREACH_NOTNEIGHBOR, /* 5: ICMP_UNREACH_SRCFAIL */ 2066 ICMP6_DST_UNREACH_ADDR, /* 6: ICMP_UNREACH_NET_UNKNOWN */ 2067 ICMP6_DST_UNREACH_ADDR, /* 7: ICMP_UNREACH_HOST_UNKNOWN */ 2068 -1, /* 8: ICMP_UNREACH_ISOLATED */ 2069 ICMP6_DST_UNREACH_ADMIN, /* 9: ICMP_UNREACH_NET_PROHIB */ 2070 ICMP6_DST_UNREACH_ADMIN, /* 10: ICMP_UNREACH_HOST_PROHIB */ 2071 -1, /* 11: ICMP_UNREACH_TOSNET */ 2072 -1, /* 12: ICMP_UNREACH_TOSHOST */ 2073 ICMP6_DST_UNREACH_ADMIN, /* 13: ICMP_UNREACH_ADMIN_PROHIBIT */ 2074}; 2075#endif 2076