fil.c revision 92685
1/* 2 * Copyright (C) 1993-2001 by Darren Reed. 3 * 4 * See the IPFILTER.LICENCE file for details on licencing. 5 */ 6#ifdef __sgi 7# include <sys/ptimers.h> 8#endif 9#include <sys/errno.h> 10#include <sys/types.h> 11#include <sys/param.h> 12#include <sys/time.h> 13#include <sys/file.h> 14#if defined(__NetBSD__) && (NetBSD >= 199905) && !defined(IPFILTER_LKM) && \ 15 defined(_KERNEL) 16# include "opt_ipfilter_log.h" 17#endif 18#if (defined(KERNEL) || defined(_KERNEL)) && defined(__FreeBSD_version) && \ 19 (__FreeBSD_version >= 220000) 20# if (__FreeBSD_version >= 400000) 21# ifndef KLD_MODULE 22# include "opt_inet6.h" 23# endif 24# if (__FreeBSD_version == 400019) 25# define CSUM_DELAY_DATA 26# endif 27# endif 28# include <sys/filio.h> 29# include <sys/fcntl.h> 30#else 31# include <sys/ioctl.h> 32#endif 33#if (defined(_KERNEL) || defined(KERNEL)) && !defined(linux) 34# include <sys/systm.h> 35#else 36# include <stdio.h> 37# include <string.h> 38# include <stdlib.h> 39#endif 40#if !defined(__SVR4) && !defined(__svr4__) 41# ifndef linux 42# include <sys/mbuf.h> 43# endif 44#else 45# include <sys/byteorder.h> 46# if SOLARIS2 < 5 47# include <sys/dditypes.h> 48# endif 49# include <sys/stream.h> 50#endif 51#ifndef linux 52# include <sys/protosw.h> 53# include <sys/socket.h> 54#endif 55#include <net/if.h> 56#ifdef sun 57# include <net/af.h> 58#endif 59#include <net/route.h> 60#include <netinet/in.h> 61#include <netinet/in_systm.h> 62#include <netinet/ip.h> 63#ifndef linux 64# include <netinet/ip_var.h> 65#endif 66#if defined(__sgi) && defined(IFF_DRVRLOCK) /* IRIX 6 */ 67# include <sys/hashing.h> 68# include <netinet/in_var.h> 69#endif 70#include <netinet/tcp.h> 71#include <netinet/udp.h> 72#include <netinet/ip_icmp.h> 73#include "netinet/ip_compat.h" 74#ifdef USE_INET6 75# include <netinet/icmp6.h> 76# if !SOLARIS && defined(_KERNEL) 77# include <netinet6/in6_var.h> 78# endif 79#endif 80#include <netinet/tcpip.h> 81#include "netinet/ip_fil.h" 82#include "netinet/ip_nat.h" 83#include "netinet/ip_frag.h" 84#include "netinet/ip_state.h" 85#include "netinet/ip_proxy.h" 86#include "netinet/ip_auth.h" 87# if defined(__FreeBSD_version) && (__FreeBSD_version >= 300000) 88# include <sys/malloc.h> 89# if defined(_KERNEL) && !defined(IPFILTER_LKM) 90# include "opt_ipfilter.h" 91# endif 92# endif 93#ifndef MIN 94# define MIN(a,b) (((a)<(b))?(a):(b)) 95#endif 96#include "netinet/ipl.h" 97 98#include <machine/in_cksum.h> 99 100#if !defined(lint) 101static const char sccsid[] = "@(#)fil.c 1.36 6/5/96 (C) 1993-2000 Darren Reed"; 102static const char rcsid[] = "@(#)$FreeBSD: head/sys/contrib/ipfilter/netinet/fil.c 92685 2002-03-19 11:44:16Z darrenr $"; 103#endif 104 105#ifndef _KERNEL 106# include "ipf.h" 107# include "ipt.h" 108extern int opts; 109 110# define FR_VERBOSE(verb_pr) verbose verb_pr 111# define FR_DEBUG(verb_pr) debug verb_pr 112# define IPLLOG(a, c, d, e) ipflog(a, c, d, e) 113#else /* #ifndef _KERNEL */ 114# define FR_VERBOSE(verb_pr) 115# define FR_DEBUG(verb_pr) 116# define IPLLOG(a, c, d, e) ipflog(a, c, d, e) 117# if SOLARIS || defined(__sgi) 118extern KRWLOCK_T ipf_mutex, ipf_auth, ipf_nat; 119extern kmutex_t ipf_rw; 120# endif /* SOLARIS || __sgi */ 121#endif /* _KERNEL */ 122 123 124struct filterstats frstats[2] = {{0,0,0,0,0},{0,0,0,0,0}}; 125struct frentry *ipfilter[2][2] = { { NULL, NULL }, { NULL, NULL } }, 126#ifdef USE_INET6 127 *ipfilter6[2][2] = { { NULL, NULL }, { NULL, NULL } }, 128 *ipacct6[2][2] = { { NULL, NULL }, { NULL, NULL } }, 129#endif 130 *ipacct[2][2] = { { NULL, NULL }, { NULL, NULL } }; 131struct frgroup *ipfgroups[3][2]; 132int fr_flags = IPF_LOGGING; 133int fr_active = 0; 134int fr_chksrc = 0; 135int fr_minttl = 3; 136int fr_minttllog = 1; 137#if defined(IPFILTER_DEFAULT_BLOCK) 138int fr_pass = FR_NOMATCH|FR_BLOCK; 139#else 140int fr_pass = (IPF_DEFAULT_PASS|FR_NOMATCH); 141#endif 142char ipfilter_version[] = IPL_VERSION; 143 144fr_info_t frcache[2]; 145 146static int frflushlist __P((int, minor_t, int *, frentry_t **)); 147#ifdef _KERNEL 148static void frsynclist __P((frentry_t *)); 149#endif 150 151 152/* 153 * bit values for identifying presence of individual IP options 154 */ 155struct optlist ipopts[20] = { 156 { IPOPT_NOP, 0x000001 }, 157 { IPOPT_RR, 0x000002 }, 158 { IPOPT_ZSU, 0x000004 }, 159 { IPOPT_MTUP, 0x000008 }, 160 { IPOPT_MTUR, 0x000010 }, 161 { IPOPT_ENCODE, 0x000020 }, 162 { IPOPT_TS, 0x000040 }, 163 { IPOPT_TR, 0x000080 }, 164 { IPOPT_SECURITY, 0x000100 }, 165 { IPOPT_LSRR, 0x000200 }, 166 { IPOPT_E_SEC, 0x000400 }, 167 { IPOPT_CIPSO, 0x000800 }, 168 { IPOPT_SATID, 0x001000 }, 169 { IPOPT_SSRR, 0x002000 }, 170 { IPOPT_ADDEXT, 0x004000 }, 171 { IPOPT_VISA, 0x008000 }, 172 { IPOPT_IMITD, 0x010000 }, 173 { IPOPT_EIP, 0x020000 }, 174 { IPOPT_FINN, 0x040000 }, 175 { 0, 0x000000 } 176}; 177 178/* 179 * bit values for identifying presence of individual IP security options 180 */ 181struct optlist secopt[8] = { 182 { IPSO_CLASS_RES4, 0x01 }, 183 { IPSO_CLASS_TOPS, 0x02 }, 184 { IPSO_CLASS_SECR, 0x04 }, 185 { IPSO_CLASS_RES3, 0x08 }, 186 { IPSO_CLASS_CONF, 0x10 }, 187 { IPSO_CLASS_UNCL, 0x20 }, 188 { IPSO_CLASS_RES2, 0x40 }, 189 { IPSO_CLASS_RES1, 0x80 } 190}; 191 192 193/* 194 * compact the IP header into a structure which contains just the info. 195 * which is useful for comparing IP headers with. 196 */ 197void fr_makefrip(hlen, ip, fin) 198int hlen; 199ip_t *ip; 200fr_info_t *fin; 201{ 202 u_short optmsk = 0, secmsk = 0, auth = 0; 203 int i, mv, ol, off, p, plen, v; 204 fr_ip_t *fi = &fin->fin_fi; 205 struct optlist *op; 206 u_char *s, opt; 207 tcphdr_t *tcp; 208 209 fin->fin_rev = 0; 210 fin->fin_fr = NULL; 211 fin->fin_tcpf = 0; 212 fin->fin_data[0] = 0; 213 fin->fin_data[1] = 0; 214 fin->fin_rule = -1; 215 fin->fin_group = -1; 216#ifdef _KERNEL 217 fin->fin_icode = ipl_unreach; 218#endif 219 v = fin->fin_v; 220 fi->fi_v = v; 221 fin->fin_hlen = hlen; 222 if (v == 4) { 223 fin->fin_id = ip->ip_id; 224 fi->fi_tos = ip->ip_tos; 225 off = (ip->ip_off & IP_OFFMASK); 226 tcp = (tcphdr_t *)((char *)ip + hlen); 227 (*(((u_short *)fi) + 1)) = (*(((u_short *)ip) + 4)); 228 fi->fi_src.i6[1] = 0; 229 fi->fi_src.i6[2] = 0; 230 fi->fi_src.i6[3] = 0; 231 fi->fi_dst.i6[1] = 0; 232 fi->fi_dst.i6[2] = 0; 233 fi->fi_dst.i6[3] = 0; 234 fi->fi_saddr = ip->ip_src.s_addr; 235 fi->fi_daddr = ip->ip_dst.s_addr; 236 p = ip->ip_p; 237 fi->fi_fl = (hlen > sizeof(ip_t)) ? FI_OPTIONS : 0; 238 if (ip->ip_off & (IP_MF|IP_OFFMASK)) 239 fi->fi_fl |= FI_FRAG; 240 plen = ip->ip_len; 241 fin->fin_dlen = plen - hlen; 242 } 243#ifdef USE_INET6 244 else if (v == 6) { 245 ip6_t *ip6 = (ip6_t *)ip; 246 247 off = 0; 248 p = ip6->ip6_nxt; 249 fi->fi_p = p; 250 fi->fi_ttl = ip6->ip6_hlim; 251 tcp = (tcphdr_t *)(ip6 + 1); 252 fi->fi_src.in6 = ip6->ip6_src; 253 fi->fi_dst.in6 = ip6->ip6_dst; 254 fin->fin_id = (u_short)(ip6->ip6_flow & 0xffff); 255 fi->fi_tos = 0; 256 fi->fi_fl = 0; 257 plen = ntohs(ip6->ip6_plen); 258 fin->fin_dlen = plen; 259 plen += sizeof(*ip6); 260 } 261#endif 262 else 263 return; 264 265 fin->fin_off = off; 266 fin->fin_plen = plen; 267 fin->fin_dp = (char *)tcp; 268 off <<= 3; 269 270 switch (p) 271 { 272#ifdef USE_INET6 273 case IPPROTO_ICMPV6 : 274 { 275 int minicmpsz = sizeof(struct icmp6_hdr); 276 struct icmp6_hdr *icmp6; 277 278 if (fin->fin_dlen > 1) { 279 fin->fin_data[0] = *(u_short *)tcp; 280 281 icmp6 = (struct icmp6_hdr *)tcp; 282 283 switch (icmp6->icmp6_type) 284 { 285 case ICMP6_ECHO_REPLY : 286 case ICMP6_ECHO_REQUEST : 287 minicmpsz = ICMP6_MINLEN; 288 break; 289 case ICMP6_DST_UNREACH : 290 case ICMP6_PACKET_TOO_BIG : 291 case ICMP6_TIME_EXCEEDED : 292 case ICMP6_PARAM_PROB : 293 minicmpsz = ICMP6ERR_IPICMPHLEN; 294 break; 295 default : 296 break; 297 } 298 } 299 300 if (!(plen >= hlen + minicmpsz)) 301 fi->fi_fl |= FI_SHORT; 302 303 break; 304 } 305#endif 306 case IPPROTO_ICMP : 307 { 308 int minicmpsz = sizeof(struct icmp); 309 icmphdr_t *icmp; 310 311 if (!off && (fin->fin_dlen > 1)) { 312 fin->fin_data[0] = *(u_short *)tcp; 313 314 icmp = (icmphdr_t *)tcp; 315 316 switch (icmp->icmp_type) 317 { 318 case ICMP_ECHOREPLY : 319 case ICMP_ECHO : 320 /* Router discovery messages - RFC 1256 */ 321 case ICMP_ROUTERADVERT : 322 case ICMP_ROUTERSOLICIT : 323 minicmpsz = ICMP_MINLEN; 324 break; 325 /* 326 * type(1) + code(1) + cksum(2) + id(2) seq(2) + 327 * 3*timestamp(3*4) 328 */ 329 case ICMP_TSTAMP : 330 case ICMP_TSTAMPREPLY : 331 minicmpsz = 20; 332 break; 333 /* 334 * type(1) + code(1) + cksum(2) + id(2) seq(2) + 335 * mask(4) 336 */ 337 case ICMP_MASKREQ : 338 case ICMP_MASKREPLY : 339 minicmpsz = 12; 340 break; 341 default : 342 break; 343 } 344 } 345 346 if ((!(plen >= hlen + minicmpsz) && !off) || 347 (off && off < sizeof(struct icmp))) 348 fi->fi_fl |= FI_SHORT; 349 350 break; 351 } 352 case IPPROTO_TCP : 353 fi->fi_fl |= FI_TCPUDP; 354#ifdef USE_INET6 355 if (v == 6) { 356 if (plen < sizeof(struct tcphdr)) 357 fi->fi_fl |= FI_SHORT; 358 } else 359#endif 360 if (v == 4) { 361 if ((!IPMINLEN(ip, tcphdr) && !off) || 362 (off && off < sizeof(struct tcphdr))) 363 fi->fi_fl |= FI_SHORT; 364 } 365 if (!(fi->fi_fl & FI_SHORT) && !off) 366 fin->fin_tcpf = tcp->th_flags; 367 goto getports; 368 case IPPROTO_UDP : 369 fi->fi_fl |= FI_TCPUDP; 370#ifdef USE_INET6 371 if (v == 6) { 372 if (plen < sizeof(struct udphdr)) 373 fi->fi_fl |= FI_SHORT; 374 } else 375#endif 376 if (v == 4) { 377 if ((!IPMINLEN(ip, udphdr) && !off) || 378 (off && off < sizeof(struct udphdr))) 379 fi->fi_fl |= FI_SHORT; 380 } 381getports: 382 if (!off && (fin->fin_dlen > 3)) { 383 fin->fin_data[0] = ntohs(tcp->th_sport); 384 fin->fin_data[1] = ntohs(tcp->th_dport); 385 } 386 break; 387 case IPPROTO_ESP : 388#ifdef USE_INET6 389 if (v == 6) { 390 if (plen < 8) 391 fi->fi_fl |= FI_SHORT; 392 } else 393#endif 394 if (v == 4) { 395 if (((ip->ip_len < hlen + 8) && !off) || 396 (off && off < 8)) 397 fi->fi_fl |= FI_SHORT; 398 } 399 break; 400 default : 401 break; 402 } 403 404#ifdef USE_INET6 405 if (v == 6) { 406 fi->fi_optmsk = 0; 407 fi->fi_secmsk = 0; 408 fi->fi_auth = 0; 409 return; 410 } 411#endif 412 413 for (s = (u_char *)(ip + 1), hlen -= (int)sizeof(*ip); hlen > 0; ) { 414 opt = *s; 415 if (opt == '\0') 416 break; 417 else if (opt == IPOPT_NOP) 418 ol = 1; 419 else { 420 if (hlen < 2) 421 break; 422 ol = (int)*(s + 1); 423 if (ol < 2 || ol > hlen) 424 break; 425 } 426 for (i = 9, mv = 4; mv >= 0; ) { 427 op = ipopts + i; 428 if (opt == (u_char)op->ol_val) { 429 optmsk |= op->ol_bit; 430 if (opt == IPOPT_SECURITY) { 431 struct optlist *sp; 432 u_char sec; 433 int j, m; 434 435 sec = *(s + 2); /* classification */ 436 for (j = 3, m = 2; m >= 0; ) { 437 sp = secopt + j; 438 if (sec == sp->ol_val) { 439 secmsk |= sp->ol_bit; 440 auth = *(s + 3); 441 auth *= 256; 442 auth += *(s + 4); 443 break; 444 } 445 if (sec < sp->ol_val) 446 j -= m--; 447 else 448 j += m--; 449 } 450 } 451 break; 452 } 453 if (opt < op->ol_val) 454 i -= mv--; 455 else 456 i += mv--; 457 } 458 hlen -= ol; 459 s += ol; 460 } 461 if (auth && !(auth & 0x0100)) 462 auth &= 0xff00; 463 fi->fi_optmsk = optmsk; 464 fi->fi_secmsk = secmsk; 465 fi->fi_auth = auth; 466} 467 468 469/* 470 * check an IP packet for TCP/UDP characteristics such as ports and flags. 471 */ 472int fr_tcpudpchk(ft, fin) 473frtuc_t *ft; 474fr_info_t *fin; 475{ 476 register u_short po, tup; 477 register char i; 478 register int err = 1; 479 480 /* 481 * Both ports should *always* be in the first fragment. 482 * So far, I cannot find any cases where they can not be. 483 * 484 * compare destination ports 485 */ 486 if ((i = (int)ft->ftu_dcmp)) { 487 po = ft->ftu_dport; 488 tup = fin->fin_data[1]; 489 /* 490 * Do opposite test to that required and 491 * continue if that succeeds. 492 */ 493 if (!--i && tup != po) /* EQUAL */ 494 err = 0; 495 else if (!--i && tup == po) /* NOTEQUAL */ 496 err = 0; 497 else if (!--i && tup >= po) /* LESSTHAN */ 498 err = 0; 499 else if (!--i && tup <= po) /* GREATERTHAN */ 500 err = 0; 501 else if (!--i && tup > po) /* LT or EQ */ 502 err = 0; 503 else if (!--i && tup < po) /* GT or EQ */ 504 err = 0; 505 else if (!--i && /* Out of range */ 506 (tup >= po && tup <= ft->ftu_dtop)) 507 err = 0; 508 else if (!--i && /* In range */ 509 (tup <= po || tup >= ft->ftu_dtop)) 510 err = 0; 511 } 512 /* 513 * compare source ports 514 */ 515 if (err && (i = (int)ft->ftu_scmp)) { 516 po = ft->ftu_sport; 517 tup = fin->fin_data[0]; 518 if (!--i && tup != po) 519 err = 0; 520 else if (!--i && tup == po) 521 err = 0; 522 else if (!--i && tup >= po) 523 err = 0; 524 else if (!--i && tup <= po) 525 err = 0; 526 else if (!--i && tup > po) 527 err = 0; 528 else if (!--i && tup < po) 529 err = 0; 530 else if (!--i && /* Out of range */ 531 (tup >= po && tup <= ft->ftu_stop)) 532 err = 0; 533 else if (!--i && /* In range */ 534 (tup <= po || tup >= ft->ftu_stop)) 535 err = 0; 536 } 537 538 /* 539 * If we don't have all the TCP/UDP header, then how can we 540 * expect to do any sort of match on it ? If we were looking for 541 * TCP flags, then NO match. If not, then match (which should 542 * satisfy the "short" class too). 543 */ 544 if (err && (fin->fin_fi.fi_p == IPPROTO_TCP)) { 545 if (fin->fin_fl & FI_SHORT) 546 return !(ft->ftu_tcpf | ft->ftu_tcpfm); 547 /* 548 * Match the flags ? If not, abort this match. 549 */ 550 if (ft->ftu_tcpfm && 551 ft->ftu_tcpf != (fin->fin_tcpf & ft->ftu_tcpfm)) { 552 FR_DEBUG(("f. %#x & %#x != %#x\n", fin->fin_tcpf, 553 ft->ftu_tcpfm, ft->ftu_tcpf)); 554 err = 0; 555 } 556 } 557 return err; 558} 559 560/* 561 * Check the input/output list of rules for a match and result. 562 * Could be per interface, but this gets real nasty when you don't have 563 * kernel sauce. 564 */ 565int fr_scanlist(passin, ip, fin, m) 566u_32_t passin; 567ip_t *ip; 568register fr_info_t *fin; 569void *m; 570{ 571 register struct frentry *fr; 572 register fr_ip_t *fi = &fin->fin_fi; 573 int rulen, portcmp = 0, off, skip = 0, logged = 0; 574 u_32_t pass, passt, passl; 575 frentry_t *frl; 576 577 frl = NULL; 578 pass = passin; 579 fr = fin->fin_fr; 580 fin->fin_fr = NULL; 581 off = fin->fin_off; 582 583 if ((fi->fi_fl & FI_TCPUDP) && (fin->fin_dlen > 3) && !off) 584 portcmp = 1; 585 586 for (rulen = 0; fr; fr = fr->fr_next, rulen++) { 587 if (skip) { 588 FR_VERBOSE(("%d (%#x)\n", skip, fr->fr_flags)); 589 skip--; 590 continue; 591 } 592 /* 593 * In all checks below, a null (zero) value in the 594 * filter struture is taken to mean a wildcard. 595 * 596 * check that we are working for the right interface 597 */ 598#ifdef _KERNEL 599# if (BSD >= 199306) 600 if (fin->fin_out != 0) { 601 if ((fr->fr_oifa && 602 (fr->fr_oifa != ((mb_t *)m)->m_pkthdr.rcvif))) 603 continue; 604 } 605# endif 606#else 607 if (opts & (OPT_VERBOSE|OPT_DEBUG)) 608 printf("\n"); 609#endif 610 611 FR_VERBOSE(("%c", fr->fr_skip ? 's' : 612 (pass & FR_PASS) ? 'p' : 613 (pass & FR_AUTH) ? 'a' : 614 (pass & FR_ACCOUNT) ? 'A' : 615 (pass & FR_NOMATCH) ? 'n' : 'b')); 616 617 if (fr->fr_ifa && fr->fr_ifa != fin->fin_ifp) 618 continue; 619 620 FR_VERBOSE((":i")); 621 { 622 register u_32_t *ld, *lm, *lip; 623 register int i; 624 625 lip = (u_32_t *)fi; 626 lm = (u_32_t *)&fr->fr_mip; 627 ld = (u_32_t *)&fr->fr_ip; 628 i = ((*lip & *lm) != *ld); 629 FR_DEBUG(("0. %#08x & %#08x != %#08x\n", 630 *lip, *lm, *ld)); 631 if (i) 632 continue; 633 /* 634 * We now know whether the packet version and the 635 * rule version match, along with protocol, ttl and 636 * tos. 637 */ 638 lip++, lm++, ld++; 639 /* 640 * Unrolled loops (4 each, for 32 bits). 641 */ 642 FR_DEBUG(("1a. %#08x & %#08x != %#08x\n", 643 *lip, *lm, *ld)); 644 i |= ((*lip++ & *lm++) != *ld++) << 5; 645 if (fi->fi_v == 6) { 646 FR_DEBUG(("1b. %#08x & %#08x != %#08x\n", 647 *lip, *lm, *ld)); 648 i |= ((*lip++ & *lm++) != *ld++) << 5; 649 FR_DEBUG(("1c. %#08x & %#08x != %#08x\n", 650 *lip, *lm, *ld)); 651 i |= ((*lip++ & *lm++) != *ld++) << 5; 652 FR_DEBUG(("1d. %#08x & %#08x != %#08x\n", 653 *lip, *lm, *ld)); 654 i |= ((*lip++ & *lm++) != *ld++) << 5; 655 } else { 656 lip += 3; 657 lm += 3; 658 ld += 3; 659 } 660 i ^= (fr->fr_flags & FR_NOTSRCIP); 661 if (i) 662 continue; 663 FR_DEBUG(("2a. %#08x & %#08x != %#08x\n", 664 *lip, *lm, *ld)); 665 i |= ((*lip++ & *lm++) != *ld++) << 6; 666 if (fi->fi_v == 6) { 667 FR_DEBUG(("2b. %#08x & %#08x != %#08x\n", 668 *lip, *lm, *ld)); 669 i |= ((*lip++ & *lm++) != *ld++) << 6; 670 FR_DEBUG(("2c. %#08x & %#08x != %#08x\n", 671 *lip, *lm, *ld)); 672 i |= ((*lip++ & *lm++) != *ld++) << 6; 673 FR_DEBUG(("2d. %#08x & %#08x != %#08x\n", 674 *lip, *lm, *ld)); 675 i |= ((*lip++ & *lm++) != *ld++) << 6; 676 } else { 677 lip += 3; 678 lm += 3; 679 ld += 3; 680 } 681 i ^= (fr->fr_flags & FR_NOTDSTIP); 682 if (i) 683 continue; 684 FR_DEBUG(("3. %#08x & %#08x != %#08x\n", 685 *lip, *lm, *ld)); 686 i |= ((*lip++ & *lm++) != *ld++); 687 FR_DEBUG(("4. %#08x & %#08x != %#08x\n", 688 *lip, *lm, *ld)); 689 i |= ((*lip & *lm) != *ld); 690 if (i) 691 continue; 692 } 693 694 /* 695 * If a fragment, then only the first has what we're looking 696 * for here... 697 */ 698 if (!portcmp && (fr->fr_dcmp || fr->fr_scmp || fr->fr_tcpf || 699 fr->fr_tcpfm)) 700 continue; 701 if (fi->fi_fl & FI_TCPUDP) { 702 if (!fr_tcpudpchk(&fr->fr_tuc, fin)) 703 continue; 704 } else if (fr->fr_icmpm || fr->fr_icmp) { 705 if ((fi->fi_p != IPPROTO_ICMP) || off || 706 (fin->fin_dlen < 2)) 707 continue; 708 if ((fin->fin_data[0] & fr->fr_icmpm) != fr->fr_icmp) { 709 FR_DEBUG(("i. %#x & %#x != %#x\n", 710 fin->fin_data[0], fr->fr_icmpm, 711 fr->fr_icmp)); 712 continue; 713 } 714 } 715 FR_VERBOSE(("*")); 716 717 if (fr->fr_flags & FR_NOMATCH) { 718 passt = passl; 719 passl = passin; 720 fin->fin_fr = frl; 721 frl = NULL; 722 if (fr->fr_flags & FR_QUICK) 723 break; 724 continue; 725 } 726 727 passl = passt; 728 passt = fr->fr_flags; 729 frl = fin->fin_fr; 730 fin->fin_fr = fr; 731#if (BSD >= 199306) && (defined(_KERNEL) || defined(KERNEL)) 732 if (securelevel <= 0) 733#endif 734 if ((passt & FR_CALLNOW) && fr->fr_func) 735 passt = (*fr->fr_func)(passt, ip, fin); 736#ifdef IPFILTER_LOG 737 /* 738 * Just log this packet... 739 */ 740 if ((passt & FR_LOGMASK) == FR_LOG) { 741 if (!IPLLOG(passt, ip, fin, m)) { 742 if (passt & FR_LOGORBLOCK) 743 passt |= FR_BLOCK|FR_QUICK; 744 ATOMIC_INCL(frstats[fin->fin_out].fr_skip); 745 } 746 ATOMIC_INCL(frstats[fin->fin_out].fr_pkl); 747 logged = 1; 748 } 749#endif /* IPFILTER_LOG */ 750 ATOMIC_INCL(fr->fr_hits); 751 if (passt & FR_ACCOUNT) 752 fr->fr_bytes += (U_QUAD_T)ip->ip_len; 753 else 754 fin->fin_icode = fr->fr_icode; 755 fin->fin_rule = rulen; 756 fin->fin_group = fr->fr_group; 757 if (fr->fr_grp != NULL) { 758 fin->fin_fr = fr->fr_grp; 759 passt = fr_scanlist(passt, ip, fin, m); 760 if (fin->fin_fr == NULL) { 761 fin->fin_rule = rulen; 762 fin->fin_group = fr->fr_group; 763 fin->fin_fr = fr; 764 } 765 if (passt & FR_DONTCACHE) 766 logged = 1; 767 } 768 if (!(skip = fr->fr_skip) && (passt & FR_LOGMASK) != FR_LOG) 769 pass = passt; 770 FR_DEBUG(("pass %#x\n", pass)); 771 if (passt & FR_QUICK) 772 break; 773 } 774 if (logged) 775 pass |= FR_DONTCACHE; 776 pass |= (fi->fi_fl << 24); 777 return pass; 778} 779 780 781/* 782 * frcheck - filter check 783 * check using source and destination addresses/ports in a packet whether 784 * or not to pass it on or not. 785 */ 786int fr_check(ip, hlen, ifp, out 787#if defined(_KERNEL) && SOLARIS 788, qif, mp) 789qif_t *qif; 790#else 791, mp) 792#endif 793mb_t **mp; 794ip_t *ip; 795int hlen; 796void *ifp; 797int out; 798{ 799 /* 800 * The above really sucks, but short of writing a diff 801 */ 802 fr_info_t frinfo, *fc; 803 register fr_info_t *fin = &frinfo; 804 int changed, error = EHOSTUNREACH, v = ip->ip_v; 805 frentry_t *fr = NULL, *list; 806 u_32_t pass, apass; 807#if !SOLARIS || !defined(_KERNEL) 808 register mb_t *m = *mp; 809#endif 810 811#ifdef _KERNEL 812 int p, len, drop = 0, logit = 0; 813 mb_t *mc = NULL; 814# if !defined(__SVR4) && !defined(__svr4__) 815# ifdef __sgi 816 char hbuf[128]; 817# endif 818 int up; 819 820# ifdef M_CANFASTFWD 821 /* 822 * XXX For now, IP Filter and fast-forwarding of cached flows 823 * XXX are mutually exclusive. Eventually, IP Filter should 824 * XXX get a "can-fast-forward" filter rule. 825 */ 826 m->m_flags &= ~M_CANFASTFWD; 827# endif /* M_CANFASTFWD */ 828# ifdef CSUM_DELAY_DATA 829 /* 830 * disable delayed checksums. 831 */ 832 if ((out != 0) && (m->m_pkthdr.csum_flags & CSUM_DELAY_DATA)) { 833 in_delayed_cksum(m); 834 m->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA; 835 } 836# endif /* CSUM_DELAY_DATA */ 837 838# ifdef USE_INET6 839 if (v == 6) { 840 len = ntohs(((ip6_t*)ip)->ip6_plen); 841 if (!len) 842 return -1; /* potential jumbo gram */ 843 len += sizeof(ip6_t); 844 p = ((ip6_t *)ip)->ip6_nxt; 845 } else 846# endif 847 { 848 p = ip->ip_p; 849 len = ip->ip_len; 850 } 851 852 if ((p == IPPROTO_TCP || p == IPPROTO_UDP || 853 (v == 4 && p == IPPROTO_ICMP) 854# ifdef USE_INET6 855 || (v == 6 && p == IPPROTO_ICMPV6) 856# endif 857 )) { 858 int plen = 0; 859 860 if ((v == 6) || (ip->ip_off & IP_OFFMASK) == 0) 861 switch(p) 862 { 863 case IPPROTO_TCP: 864 plen = sizeof(tcphdr_t); 865 break; 866 case IPPROTO_UDP: 867 plen = sizeof(udphdr_t); 868 break; 869 /* 96 - enough for complete ICMP error IP header */ 870 case IPPROTO_ICMP: 871 plen = ICMPERR_MAXPKTLEN - sizeof(ip_t); 872 break; 873 case IPPROTO_ESP: 874 plen = 8; 875 break; 876# ifdef USE_INET6 877 case IPPROTO_ICMPV6 : 878 /* 879 * XXX does not take intermediate header 880 * into account 881 */ 882 plen = ICMP6ERR_MINPKTLEN + 8 - sizeof(ip6_t); 883 break; 884# endif 885 } 886 up = MIN(hlen + plen, len); 887 888 if (up > m->m_len) { 889# ifdef __sgi 890 /* Under IRIX, avoid m_pullup as it makes ping <hostname> panic */ 891 if ((up > sizeof(hbuf)) || (m_length(m) < up)) { 892 ATOMIC_INCL(frstats[out].fr_pull[1]); 893 return -1; 894 } 895 m_copydata(m, 0, up, hbuf); 896 ATOMIC_INCL(frstats[out].fr_pull[0]); 897 ip = (ip_t *)hbuf; 898# else /* __ sgi */ 899# ifndef linux 900 if ((*mp = m_pullup(m, up)) == 0) { 901 ATOMIC_INCL(frstats[out].fr_pull[1]); 902 return -1; 903 } else { 904 ATOMIC_INCL(frstats[out].fr_pull[0]); 905 m = *mp; 906 ip = mtod(m, ip_t *); 907 } 908# endif /* !linux */ 909# endif /* __sgi */ 910 } else 911 up = 0; 912 } else 913 up = 0; 914# endif /* !defined(__SVR4) && !defined(__svr4__) */ 915# if SOLARIS 916 mb_t *m = qif->qf_m; 917 918 if ((u_int)ip & 0x3) 919 return 2; 920 fin->fin_qfm = m; 921 fin->fin_qif = qif; 922# endif 923#endif /* _KERNEL */ 924 925#ifndef __FreeBSD__ 926 /* 927 * Be careful here: ip_id is in network byte order when called 928 * from ip_output() 929 */ 930 if ((out) && (v == 4)) 931 ip->ip_id = ntohs(ip->ip_id); 932#endif 933 934 changed = 0; 935 fin->fin_ifp = ifp; 936 fin->fin_v = v; 937 fin->fin_out = out; 938 fin->fin_mp = mp; 939 fr_makefrip(hlen, ip, fin); 940 941#ifdef _KERNEL 942# ifdef USE_INET6 943 if (v == 6) { 944 ATOMIC_INCL(frstats[0].fr_ipv6[out]); 945 if (((ip6_t *)ip)->ip6_hlim < fr_minttl) { 946 ATOMIC_INCL(frstats[0].fr_badttl); 947 if (fr_minttllog & 1) 948 logit = -3; 949 if (fr_minttllog & 2) 950 drop = 1; 951 } 952 } else 953# endif 954 if (!out) { 955 if (fr_chksrc && !fr_verifysrc(ip->ip_src, ifp)) { 956 ATOMIC_INCL(frstats[0].fr_badsrc); 957 if (fr_chksrc & 1) 958 drop = 1; 959 if (fr_chksrc & 2) 960 logit = -2; 961 } else if (ip->ip_ttl < fr_minttl) { 962 ATOMIC_INCL(frstats[0].fr_badttl); 963 if (fr_minttllog & 1) 964 logit = -3; 965 if (fr_minttllog & 2) 966 drop = 1; 967 } 968 } 969 if (drop) { 970# ifdef IPFILTER_LOG 971 if (logit) { 972 fin->fin_group = logit; 973 pass = FR_INQUE|FR_NOMATCH|FR_LOGB; 974 (void) IPLLOG(pass, ip, fin, m); 975 } 976# endif 977# if !SOLARIS 978 m_freem(m); 979# endif 980 return error; 981 } 982#endif 983 pass = fr_pass; 984 if (fin->fin_fl & FI_SHORT) { 985 ATOMIC_INCL(frstats[out].fr_short); 986 } 987 988 READ_ENTER(&ipf_mutex); 989 990 /* 991 * Check auth now. This, combined with the check below to see if apass 992 * is 0 is to ensure that we don't count the packet twice, which can 993 * otherwise occur when we reprocess it. As it is, we only count it 994 * after it has no auth. table matchup. This also stops NAT from 995 * occuring until after the packet has been auth'd. 996 */ 997 apass = fr_checkauth(ip, fin); 998 999 if (!out) { 1000#ifdef USE_INET6 1001 if (v == 6) 1002 list = ipacct6[0][fr_active]; 1003 else 1004#endif 1005 list = ipacct[0][fr_active]; 1006 changed = ip_natin(ip, fin); 1007 if (!apass && (fin->fin_fr = list) && 1008 (fr_scanlist(FR_NOMATCH, ip, fin, m) & FR_ACCOUNT)) { 1009 ATOMIC_INCL(frstats[0].fr_acct); 1010 } 1011 } 1012 1013 if (!apass) { 1014 if ((fin->fin_fl & FI_FRAG) == FI_FRAG) 1015 fr = ipfr_knownfrag(ip, fin); 1016 if (!fr && !(fin->fin_fl & FI_SHORT)) 1017 fr = fr_checkstate(ip, fin); 1018 if (fr != NULL) 1019 pass = fr->fr_flags; 1020 if (fr && (pass & FR_LOGFIRST)) 1021 pass &= ~(FR_LOGFIRST|FR_LOG); 1022 } 1023 1024 if (apass || !fr) { 1025 /* 1026 * If a packet is found in the auth table, then skip checking 1027 * the access lists for permission but we do need to consider 1028 * the result as if it were from the ACL's. 1029 */ 1030 if (!apass) { 1031 fc = frcache + out; 1032 if (!bcmp((char *)fin, (char *)fc, FI_CSIZE)) { 1033 /* 1034 * copy cached data so we can unlock the mutex 1035 * earlier. 1036 */ 1037 bcopy((char *)fc, (char *)fin, FI_COPYSIZE); 1038 ATOMIC_INCL(frstats[out].fr_chit); 1039 if ((fr = fin->fin_fr)) { 1040 ATOMIC_INCL(fr->fr_hits); 1041 pass = fr->fr_flags; 1042 } 1043 } else { 1044#ifdef USE_INET6 1045 if (v == 6) 1046 list = ipfilter6[out][fr_active]; 1047 else 1048#endif 1049 list = ipfilter[out][fr_active]; 1050 if ((fin->fin_fr = list)) 1051 pass = fr_scanlist(fr_pass, ip, fin, m); 1052 if (!(pass & (FR_KEEPSTATE|FR_DONTCACHE))) 1053 bcopy((char *)fin, (char *)fc, 1054 FI_COPYSIZE); 1055 if (pass & FR_NOMATCH) { 1056 ATOMIC_INCL(frstats[out].fr_nom); 1057 fin->fin_fr = NULL; 1058 } 1059 } 1060 } else 1061 pass = apass; 1062 fr = fin->fin_fr; 1063 1064 /* 1065 * If we fail to add a packet to the authorization queue, 1066 * then we drop the packet later. However, if it was added 1067 * then pretend we've dropped it already. 1068 */ 1069 if ((pass & FR_AUTH)) { 1070 if (fr_newauth((mb_t *)m, fin, ip) != 0) { 1071 m = *mp = NULL; 1072 error = 0; 1073 } else 1074 error = ENOSPC; 1075 } 1076 1077 if (pass & FR_PREAUTH) { 1078 READ_ENTER(&ipf_auth); 1079 if ((fin->fin_fr = ipauth) && 1080 (pass = fr_scanlist(0, ip, fin, m))) { 1081 ATOMIC_INCL(fr_authstats.fas_hits); 1082 } else { 1083 ATOMIC_INCL(fr_authstats.fas_miss); 1084 } 1085 RWLOCK_EXIT(&ipf_auth); 1086 } 1087 1088 fin->fin_fr = fr; 1089 if ((pass & (FR_KEEPFRAG|FR_KEEPSTATE)) == FR_KEEPFRAG) { 1090 if (fin->fin_fl & FI_FRAG) { 1091 if (ipfr_newfrag(ip, fin, pass) == -1) { 1092 ATOMIC_INCL(frstats[out].fr_bnfr); 1093 } else { 1094 ATOMIC_INCL(frstats[out].fr_nfr); 1095 } 1096 } else { 1097 ATOMIC_INCL(frstats[out].fr_cfr); 1098 } 1099 } 1100 if (pass & FR_KEEPSTATE) { 1101 if (fr_addstate(ip, fin, NULL, 0) == NULL) { 1102 ATOMIC_INCL(frstats[out].fr_bads); 1103 } else { 1104 ATOMIC_INCL(frstats[out].fr_ads); 1105 } 1106 } 1107 } else if (fr != NULL) { 1108 pass = fr->fr_flags; 1109 if (pass & FR_LOGFIRST) 1110 pass &= ~(FR_LOGFIRST|FR_LOG); 1111 } 1112 1113#if (BSD >= 199306) && (defined(_KERNEL) || defined(KERNEL)) 1114 if (securelevel <= 0) 1115#endif 1116 if (fr && fr->fr_func && !(pass & FR_CALLNOW)) 1117 pass = (*fr->fr_func)(pass, ip, fin); 1118 1119 /* 1120 * Only count/translate packets which will be passed on, out the 1121 * interface. 1122 */ 1123 if (out && (pass & FR_PASS)) { 1124#ifdef USE_INET6 1125 if (v == 6) 1126 list = ipacct6[1][fr_active]; 1127 else 1128#endif 1129 list = ipacct[1][fr_active]; 1130 if (list != NULL) { 1131 u_32_t sg, sr; 1132 1133 fin->fin_fr = list; 1134 sg = fin->fin_group; 1135 sr = fin->fin_rule; 1136 if (fr_scanlist(FR_NOMATCH, ip, fin, m) & FR_ACCOUNT) { 1137 ATOMIC_INCL(frstats[1].fr_acct); 1138 } 1139 fin->fin_group = sg; 1140 fin->fin_rule = sr; 1141 fin->fin_fr = fr; 1142 } 1143 changed = ip_natout(ip, fin); 1144 } else 1145 fin->fin_fr = fr; 1146 RWLOCK_EXIT(&ipf_mutex); 1147 1148#ifdef IPFILTER_LOG 1149 if ((fr_flags & FF_LOGGING) || (pass & FR_LOGMASK)) { 1150 if ((fr_flags & FF_LOGNOMATCH) && (pass & FR_NOMATCH)) { 1151 pass |= FF_LOGNOMATCH; 1152 ATOMIC_INCL(frstats[out].fr_npkl); 1153 goto logit; 1154 } else if (((pass & FR_LOGMASK) == FR_LOGP) || 1155 ((pass & FR_PASS) && (fr_flags & FF_LOGPASS))) { 1156 if ((pass & FR_LOGMASK) != FR_LOGP) 1157 pass |= FF_LOGPASS; 1158 ATOMIC_INCL(frstats[out].fr_ppkl); 1159 goto logit; 1160 } else if (((pass & FR_LOGMASK) == FR_LOGB) || 1161 ((pass & FR_BLOCK) && (fr_flags & FF_LOGBLOCK))) { 1162 if ((pass & FR_LOGMASK) != FR_LOGB) 1163 pass |= FF_LOGBLOCK; 1164 ATOMIC_INCL(frstats[out].fr_bpkl); 1165logit: 1166 if (!IPLLOG(pass, ip, fin, m)) { 1167 ATOMIC_INCL(frstats[out].fr_skip); 1168 if ((pass & (FR_PASS|FR_LOGORBLOCK)) == 1169 (FR_PASS|FR_LOGORBLOCK)) 1170 pass ^= FR_PASS|FR_BLOCK; 1171 } 1172 } 1173 } 1174#endif /* IPFILTER_LOG */ 1175 1176#ifndef __FreeBSD__ 1177 if ((out) && (v == 4)) 1178 ip->ip_id = htons(ip->ip_id); 1179#endif 1180 1181#ifdef _KERNEL 1182 /* 1183 * Only allow FR_DUP to work if a rule matched - it makes no sense to 1184 * set FR_DUP as a "default" as there are no instructions about where 1185 * to send the packet. 1186 */ 1187 if (fr && (pass & FR_DUP)) 1188# if SOLARIS 1189 mc = dupmsg(m); 1190# else 1191# if defined(__OpenBSD__) && (OpenBSD >= 199905) 1192 mc = m_copym2(m, 0, M_COPYALL, M_DONTWAIT); 1193# else 1194 mc = m_copy(m, 0, M_COPYALL); 1195# endif 1196# endif 1197#endif 1198 if (pass & FR_PASS) { 1199 ATOMIC_INCL(frstats[out].fr_pass); 1200 } else if (pass & FR_BLOCK) { 1201 ATOMIC_INCL(frstats[out].fr_block); 1202 /* 1203 * Should we return an ICMP packet to indicate error 1204 * status passing through the packet filter ? 1205 * WARNING: ICMP error packets AND TCP RST packets should 1206 * ONLY be sent in repsonse to incoming packets. Sending them 1207 * in response to outbound packets can result in a panic on 1208 * some operating systems. 1209 */ 1210 if (!out) { 1211 if (pass & FR_RETICMP) { 1212 int dst; 1213 1214 if ((pass & FR_RETMASK) == FR_FAKEICMP) 1215 dst = 1; 1216 else 1217 dst = 0; 1218 send_icmp_err(ip, ICMP_UNREACH, fin, dst); 1219 ATOMIC_INCL(frstats[0].fr_ret); 1220 } else if (((pass & FR_RETMASK) == FR_RETRST) && 1221 !(fin->fin_fl & FI_SHORT)) { 1222 if (send_reset(ip, fin) == 0) { 1223 ATOMIC_INCL(frstats[1].fr_ret); 1224 } 1225 } 1226 } else { 1227 if (pass & FR_RETRST) 1228 error = ECONNRESET; 1229 } 1230 } 1231 1232 /* 1233 * If we didn't drop off the bottom of the list of rules (and thus 1234 * the 'current' rule fr is not NULL), then we may have some extra 1235 * instructions about what to do with a packet. 1236 * Once we're finished return to our caller, freeing the packet if 1237 * we are dropping it (* BSD ONLY *). 1238 */ 1239 if ((changed == -1) && (pass & FR_PASS)) { 1240 pass &= ~FR_PASS; 1241 pass |= FR_BLOCK; 1242 } 1243#if defined(_KERNEL) 1244# if !SOLARIS 1245# if !defined(linux) 1246 if (fr) { 1247 frdest_t *fdp = &fr->fr_tif; 1248 1249 if (((pass & FR_FASTROUTE) && !out) || 1250 (fdp->fd_ifp && fdp->fd_ifp != (struct ifnet *)-1)) { 1251 (void) ipfr_fastroute(m, mp, fin, fdp); 1252 m = *mp; 1253 } 1254 1255 if (mc != NULL) 1256 (void) ipfr_fastroute(mc, &mc, fin, &fr->fr_dif); 1257 } 1258 1259 if (!(pass & FR_PASS) && m) { 1260 m_freem(m); 1261 m = *mp = NULL; 1262 } 1263# ifdef __sgi 1264 else if (changed && up && m) 1265 m_copyback(m, 0, up, hbuf); 1266# endif 1267# endif /* !linux */ 1268# else /* !SOLARIS */ 1269 if (fr) { 1270 frdest_t *fdp = &fr->fr_tif; 1271 1272 if (((pass & FR_FASTROUTE) && !out) || 1273 (fdp->fd_ifp && fdp->fd_ifp != (struct ifnet *)-1)) 1274 (void) ipfr_fastroute(ip, m, mp, fin, fdp); 1275 1276 if (mc != NULL) 1277 (void) ipfr_fastroute(ip, mc, &mc, fin, &fr->fr_dif); 1278 } 1279# endif /* !SOLARIS */ 1280 return (pass & FR_PASS) ? 0 : error; 1281#else /* _KERNEL */ 1282 if (pass & FR_NOMATCH) 1283 return 1; 1284 if (pass & FR_PASS) 1285 return 0; 1286 if (pass & FR_AUTH) 1287 return -2; 1288 if ((pass & FR_RETMASK) == FR_RETRST) 1289 return -3; 1290 if ((pass & FR_RETMASK) == FR_RETICMP) 1291 return -4; 1292 if ((pass & FR_RETMASK) == FR_FAKEICMP) 1293 return -5; 1294 return -1; 1295#endif /* _KERNEL */ 1296} 1297 1298 1299/* 1300 * ipf_cksum 1301 * addr should be 16bit aligned and len is in bytes. 1302 * length is in bytes 1303 */ 1304u_short ipf_cksum(addr, len) 1305register u_short *addr; 1306register int len; 1307{ 1308 register u_32_t sum = 0; 1309 1310 for (sum = 0; len > 1; len -= 2) 1311 sum += *addr++; 1312 1313 /* mop up an odd byte, if necessary */ 1314 if (len == 1) 1315 sum += *(u_char *)addr; 1316 1317 /* 1318 * add back carry outs from top 16 bits to low 16 bits 1319 */ 1320 sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */ 1321 sum += (sum >> 16); /* add carry */ 1322 return (u_short)(~sum); 1323} 1324 1325 1326/* 1327 * NB: This function assumes we've pullup'd enough for all of the IP header 1328 * and the TCP header. We also assume that data blocks aren't allocated in 1329 * odd sizes. 1330 */ 1331u_short fr_tcpsum(m, ip, tcp) 1332mb_t *m; 1333ip_t *ip; 1334tcphdr_t *tcp; 1335{ 1336 u_short *sp, slen, ts; 1337 u_int sum, sum2; 1338 int hlen; 1339 1340 /* 1341 * Add up IP Header portion 1342 */ 1343 hlen = ip->ip_hl << 2; 1344 slen = ip->ip_len - hlen; 1345 sum = htons((u_short)ip->ip_p); 1346 sum += htons(slen); 1347 sp = (u_short *)&ip->ip_src; 1348 sum += *sp++; /* ip_src */ 1349 sum += *sp++; 1350 sum += *sp++; /* ip_dst */ 1351 sum += *sp++; 1352 ts = tcp->th_sum; 1353 tcp->th_sum = 0; 1354#ifdef KERNEL 1355# if SOLARIS 1356 sum2 = ip_cksum(m, hlen, sum); /* hlen == offset */ 1357 sum2 = (sum2 & 0xffff) + (sum2 >> 16); 1358 sum2 = ~sum2 & 0xffff; 1359# else /* SOLARIS */ 1360# if defined(BSD) || defined(sun) 1361# if BSD >= 199306 1362 m->m_data += hlen; 1363# else 1364 m->m_off += hlen; 1365# endif 1366 m->m_len -= hlen; 1367 sum2 = in_cksum(m, slen); 1368 m->m_len += hlen; 1369# if BSD >= 199306 1370 m->m_data -= hlen; 1371# else 1372 m->m_off -= hlen; 1373# endif 1374 /* 1375 * Both sum and sum2 are partial sums, so combine them together. 1376 */ 1377 sum = (sum & 0xffff) + (sum >> 16); 1378 sum = ~sum & 0xffff; 1379 sum2 += sum; 1380 sum2 = (sum2 & 0xffff) + (sum2 >> 16); 1381# else /* defined(BSD) || defined(sun) */ 1382{ 1383 union { 1384 u_char c[2]; 1385 u_short s; 1386 } bytes; 1387 u_short len = ip->ip_len; 1388# if defined(__sgi) 1389 int add; 1390# endif 1391 1392 /* 1393 * Add up IP Header portion 1394 */ 1395 sp = (u_short *)&ip->ip_src; 1396 len -= (ip->ip_hl << 2); 1397 sum = ntohs(IPPROTO_TCP); 1398 sum += htons(len); 1399 sum += *sp++; /* ip_src */ 1400 sum += *sp++; 1401 sum += *sp++; /* ip_dst */ 1402 sum += *sp++; 1403 if (sp != (u_short *)tcp) 1404 sp = (u_short *)tcp; 1405 sum += *sp++; /* sport */ 1406 sum += *sp++; /* dport */ 1407 sum += *sp++; /* seq */ 1408 sum += *sp++; 1409 sum += *sp++; /* ack */ 1410 sum += *sp++; 1411 sum += *sp++; /* off */ 1412 sum += *sp++; /* win */ 1413 sum += *sp++; /* Skip over checksum */ 1414 sum += *sp++; /* urp */ 1415 1416# ifdef __sgi 1417 /* 1418 * In case we had to copy the IP & TCP header out of mbufs, 1419 * skip over the mbuf bits which are the header 1420 */ 1421 if ((caddr_t)ip != mtod(m, caddr_t)) { 1422 hlen = (caddr_t)sp - (caddr_t)ip; 1423 while (hlen) { 1424 add = MIN(hlen, m->m_len); 1425 sp = (u_short *)(mtod(m, caddr_t) + add); 1426 hlen -= add; 1427 if (add == m->m_len) { 1428 m = m->m_next; 1429 if (!hlen) { 1430 if (!m) 1431 break; 1432 sp = mtod(m, u_short *); 1433 } 1434 PANIC((!m),("fr_tcpsum(1): not enough data")); 1435 } 1436 } 1437 } 1438# endif 1439 1440 if (!(len -= sizeof(*tcp))) 1441 goto nodata; 1442 while (len > 1) { 1443 if (((caddr_t)sp - mtod(m, caddr_t)) >= m->m_len) { 1444 m = m->m_next; 1445 PANIC((!m),("fr_tcpsum(2): not enough data")); 1446 sp = mtod(m, u_short *); 1447 } 1448 if (((caddr_t)(sp + 1) - mtod(m, caddr_t)) > m->m_len) { 1449 bytes.c[0] = *(u_char *)sp; 1450 m = m->m_next; 1451 PANIC((!m),("fr_tcpsum(3): not enough data")); 1452 sp = mtod(m, u_short *); 1453 bytes.c[1] = *(u_char *)sp; 1454 sum += bytes.s; 1455 sp = (u_short *)((u_char *)sp + 1); 1456 } 1457 if ((u_long)sp & 1) { 1458 bcopy((char *)sp++, (char *)&bytes.s, sizeof(bytes.s)); 1459 sum += bytes.s; 1460 } else 1461 sum += *sp++; 1462 len -= 2; 1463 } 1464 if (len) 1465 sum += ntohs(*(u_char *)sp << 8); 1466nodata: 1467 while (sum > 0xffff) 1468 sum = (sum & 0xffff) + (sum >> 16); 1469 sum2 = (u_short)(~sum & 0xffff); 1470} 1471# endif /* defined(BSD) || defined(sun) */ 1472# endif /* SOLARIS */ 1473#else /* KERNEL */ 1474 sum2 = 0; 1475#endif /* KERNEL */ 1476 tcp->th_sum = ts; 1477 return sum2; 1478} 1479 1480 1481#if defined(_KERNEL) && ( ((BSD < 199306) && !SOLARIS) || defined(__sgi) ) 1482/* 1483 * Copyright (c) 1982, 1986, 1988, 1991, 1993 1484 * The Regents of the University of California. All rights reserved. 1485 * 1486 * Redistribution and use in source and binary forms, with or without 1487 * modification, are permitted provided that the following conditions 1488 * are met: 1489 * 1. Redistributions of source code must retain the above copyright 1490 * notice, this list of conditions and the following disclaimer. 1491 * 2. Redistributions in binary form must reproduce the above copyright 1492 * notice, this list of conditions and the following disclaimer in the 1493 * documentation and/or other materials provided with the distribution. 1494 * 3. All advertising materials mentioning features or use of this software 1495 * must display the following acknowledgement: 1496 * This product includes software developed by the University of 1497 * California, Berkeley and its contributors. 1498 * 4. Neither the name of the University nor the names of its contributors 1499 * may be used to endorse or promote products derived from this software 1500 * without specific prior written permission. 1501 * 1502 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 1503 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1504 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1505 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 1506 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1507 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 1508 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 1509 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 1510 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 1511 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 1512 * SUCH DAMAGE. 1513 * 1514 * @(#)uipc_mbuf.c 8.2 (Berkeley) 1/4/94 1515 * $Id: fil.c,v 2.35.2.58 2002/03/13 02:23:13 darrenr Exp $ 1516 */ 1517/* 1518 * Copy data from an mbuf chain starting "off" bytes from the beginning, 1519 * continuing for "len" bytes, into the indicated buffer. 1520 */ 1521void 1522m_copydata(m, off, len, cp) 1523 register mb_t *m; 1524 register int off; 1525 register int len; 1526 caddr_t cp; 1527{ 1528 register unsigned count; 1529 1530 if (off < 0 || len < 0) 1531 panic("m_copydata"); 1532 while (off > 0) { 1533 if (m == 0) 1534 panic("m_copydata"); 1535 if (off < m->m_len) 1536 break; 1537 off -= m->m_len; 1538 m = m->m_next; 1539 } 1540 while (len > 0) { 1541 if (m == 0) 1542 panic("m_copydata"); 1543 count = MIN(m->m_len - off, len); 1544 bcopy(mtod(m, caddr_t) + off, cp, count); 1545 len -= count; 1546 cp += count; 1547 off = 0; 1548 m = m->m_next; 1549 } 1550} 1551 1552 1553# ifndef linux 1554/* 1555 * Copy data from a buffer back into the indicated mbuf chain, 1556 * starting "off" bytes from the beginning, extending the mbuf 1557 * chain if necessary. 1558 */ 1559void 1560m_copyback(m0, off, len, cp) 1561 struct mbuf *m0; 1562 register int off; 1563 register int len; 1564 caddr_t cp; 1565{ 1566 register int mlen; 1567 register struct mbuf *m = m0, *n; 1568 int totlen = 0; 1569 1570 if (m0 == 0) 1571 return; 1572 while (off > (mlen = m->m_len)) { 1573 off -= mlen; 1574 totlen += mlen; 1575 if (m->m_next == 0) { 1576 n = m_getclr(M_DONTWAIT, m->m_type); 1577 if (n == 0) 1578 goto out; 1579 n->m_len = min(MLEN, len + off); 1580 m->m_next = n; 1581 } 1582 m = m->m_next; 1583 } 1584 while (len > 0) { 1585 mlen = min (m->m_len - off, len); 1586 bcopy(cp, off + mtod(m, caddr_t), (unsigned)mlen); 1587 cp += mlen; 1588 len -= mlen; 1589 mlen += off; 1590 off = 0; 1591 totlen += mlen; 1592 if (len == 0) 1593 break; 1594 if (m->m_next == 0) { 1595 n = m_get(M_DONTWAIT, m->m_type); 1596 if (n == 0) 1597 break; 1598 n->m_len = min(MLEN, len); 1599 m->m_next = n; 1600 } 1601 m = m->m_next; 1602 } 1603out: 1604#if 0 1605 if (((m = m0)->m_flags & M_PKTHDR) && (m->m_pkthdr.len < totlen)) 1606 m->m_pkthdr.len = totlen; 1607#endif 1608 return; 1609} 1610# endif /* linux */ 1611#endif /* (_KERNEL) && ( ((BSD < 199306) && !SOLARIS) || __sgi) */ 1612 1613 1614frgroup_t *fr_findgroup(num, flags, which, set, fgpp) 1615u_32_t num, flags; 1616minor_t which; 1617int set; 1618frgroup_t ***fgpp; 1619{ 1620 frgroup_t *fg, **fgp; 1621 1622 if (which == IPL_LOGAUTH) 1623 fgp = &ipfgroups[2][set]; 1624 else if (flags & FR_ACCOUNT) 1625 fgp = &ipfgroups[1][set]; 1626 else if (flags & (FR_OUTQUE|FR_INQUE)) 1627 fgp = &ipfgroups[0][set]; 1628 else 1629 return NULL; 1630 num &= 0xffff; 1631 1632 while ((fg = *fgp)) 1633 if (fg->fg_num == num) 1634 break; 1635 else 1636 fgp = &fg->fg_next; 1637 if (fgpp) 1638 *fgpp = fgp; 1639 return fg; 1640} 1641 1642 1643frgroup_t *fr_addgroup(num, fp, which, set) 1644u_32_t num; 1645frentry_t *fp; 1646minor_t which; 1647int set; 1648{ 1649 frgroup_t *fg, **fgp; 1650 1651 if ((fg = fr_findgroup(num, fp->fr_flags, which, set, &fgp))) 1652 return fg; 1653 1654 KMALLOC(fg, frgroup_t *); 1655 if (fg) { 1656 fg->fg_num = num; 1657 fg->fg_next = *fgp; 1658 fg->fg_head = fp; 1659 fg->fg_start = &fp->fr_grp; 1660 *fgp = fg; 1661 } 1662 return fg; 1663} 1664 1665 1666void fr_delgroup(num, flags, which, set) 1667u_32_t num, flags; 1668minor_t which; 1669int set; 1670{ 1671 frgroup_t *fg, **fgp; 1672 1673 if (!(fg = fr_findgroup(num, flags, which, set, &fgp))) 1674 return; 1675 1676 *fgp = fg->fg_next; 1677 KFREE(fg); 1678} 1679 1680 1681 1682/* 1683 * recursively flush rules from the list, descending groups as they are 1684 * encountered. if a rule is the head of a group and it has lost all its 1685 * group members, then also delete the group reference. 1686 */ 1687static int frflushlist(set, unit, nfreedp, listp) 1688int set; 1689minor_t unit; 1690int *nfreedp; 1691frentry_t **listp; 1692{ 1693 register int freed = 0, i; 1694 register frentry_t *fp; 1695 1696 while ((fp = *listp)) { 1697 *listp = fp->fr_next; 1698 if (fp->fr_grp) { 1699 i = frflushlist(set, unit, nfreedp, &fp->fr_grp); 1700 MUTEX_ENTER(&ipf_rw); 1701 fp->fr_ref -= i; 1702 MUTEX_EXIT(&ipf_rw); 1703 } 1704 1705 ATOMIC_DEC32(fp->fr_ref); 1706 if (fp->fr_grhead) { 1707 fr_delgroup(fp->fr_grhead, fp->fr_flags, 1708 unit, set); 1709 fp->fr_grhead = 0; 1710 } 1711 if (fp->fr_ref == 0) { 1712 KFREE(fp); 1713 freed++; 1714 } else 1715 fp->fr_next = NULL; 1716 } 1717 *nfreedp += freed; 1718 return freed; 1719} 1720 1721 1722int frflush(unit, flags) 1723minor_t unit; 1724int flags; 1725{ 1726 int flushed = 0, set; 1727 1728 if (unit != IPL_LOGIPF) 1729 return 0; 1730 WRITE_ENTER(&ipf_mutex); 1731 bzero((char *)frcache, sizeof(frcache[0]) * 2); 1732 1733 set = fr_active; 1734 if (flags & FR_INACTIVE) 1735 set = 1 - set; 1736 1737 if (flags & FR_OUTQUE) { 1738#ifdef USE_INET6 1739 (void) frflushlist(set, unit, &flushed, &ipfilter6[1][set]); 1740 (void) frflushlist(set, unit, &flushed, &ipacct6[1][set]); 1741#endif 1742 (void) frflushlist(set, unit, &flushed, &ipfilter[1][set]); 1743 (void) frflushlist(set, unit, &flushed, &ipacct[1][set]); 1744 } 1745 if (flags & FR_INQUE) { 1746#ifdef USE_INET6 1747 (void) frflushlist(set, unit, &flushed, &ipfilter6[0][set]); 1748 (void) frflushlist(set, unit, &flushed, &ipacct6[0][set]); 1749#endif 1750 (void) frflushlist(set, unit, &flushed, &ipfilter[0][set]); 1751 (void) frflushlist(set, unit, &flushed, &ipacct[0][set]); 1752 } 1753 RWLOCK_EXIT(&ipf_mutex); 1754 return flushed; 1755} 1756 1757 1758char *memstr(src, dst, slen, dlen) 1759char *src, *dst; 1760int slen, dlen; 1761{ 1762 char *s = NULL; 1763 1764 while (dlen >= slen) { 1765 if (bcmp(src, dst, slen) == 0) { 1766 s = dst; 1767 break; 1768 } 1769 dst++; 1770 dlen--; 1771 } 1772 return s; 1773} 1774 1775 1776void fixskip(listp, rp, addremove) 1777frentry_t **listp, *rp; 1778int addremove; 1779{ 1780 frentry_t *fp; 1781 int rules = 0, rn = 0; 1782 1783 for (fp = *listp; fp && (fp != rp); fp = fp->fr_next, rules++) 1784 ; 1785 1786 if (!fp) 1787 return; 1788 1789 for (fp = *listp; fp && (fp != rp); fp = fp->fr_next, rn++) 1790 if (fp->fr_skip && (rn + fp->fr_skip >= rules)) 1791 fp->fr_skip += addremove; 1792} 1793 1794 1795#ifdef _KERNEL 1796/* 1797 * count consecutive 1's in bit mask. If the mask generated by counting 1798 * consecutive 1's is different to that passed, return -1, else return # 1799 * of bits. 1800 */ 1801int countbits(ip) 1802u_32_t ip; 1803{ 1804 u_32_t ipn; 1805 int cnt = 0, i, j; 1806 1807 ip = ipn = ntohl(ip); 1808 for (i = 32; i; i--, ipn *= 2) 1809 if (ipn & 0x80000000) 1810 cnt++; 1811 else 1812 break; 1813 ipn = 0; 1814 for (i = 32, j = cnt; i; i--, j--) { 1815 ipn *= 2; 1816 if (j > 0) 1817 ipn++; 1818 } 1819 if (ipn == ip) 1820 return cnt; 1821 return -1; 1822} 1823 1824 1825/* 1826 * return the first IP Address associated with an interface 1827 */ 1828int fr_ifpaddr(v, ifptr, inp) 1829int v; 1830void *ifptr; 1831struct in_addr *inp; 1832{ 1833# ifdef USE_INET6 1834 struct in6_addr *inp6 = NULL; 1835# endif 1836# if SOLARIS 1837 ill_t *ill = ifptr; 1838# else 1839 struct ifnet *ifp = ifptr; 1840# endif 1841 struct in_addr in; 1842 1843# if SOLARIS 1844# ifdef USE_INET6 1845 if (v == 6) { 1846 struct in6_addr in6; 1847 1848 /* 1849 * First is always link local. 1850 */ 1851 if (ill->ill_ipif->ipif_next) 1852 in6 = ill->ill_ipif->ipif_next->ipif_v6lcl_addr; 1853 else 1854 bzero((char *)&in6, sizeof(in6)); 1855 bcopy((char *)&in6, (char *)inp, sizeof(in6)); 1856 } else 1857# endif 1858 { 1859 in.s_addr = ill->ill_ipif->ipif_local_addr; 1860 *inp = in; 1861 } 1862# else /* SOLARIS */ 1863# if linux 1864 ; 1865# else /* linux */ 1866 struct sockaddr_in *sin; 1867 struct ifaddr *ifa; 1868 1869# if (__FreeBSD_version >= 300000) 1870 ifa = TAILQ_FIRST(&ifp->if_addrhead); 1871# else 1872# if defined(__NetBSD__) || defined(__OpenBSD__) 1873 ifa = ifp->if_addrlist.tqh_first; 1874# else 1875# if defined(__sgi) && defined(IFF_DRVRLOCK) /* IRIX 6 */ 1876 ifa = &((struct in_ifaddr *)ifp->in_ifaddr)->ia_ifa; 1877# else 1878 ifa = ifp->if_addrlist; 1879# endif 1880# endif /* __NetBSD__ || __OpenBSD__ */ 1881# endif /* __FreeBSD_version >= 300000 */ 1882# if (BSD < 199306) && !(/*IRIX6*/defined(__sgi) && defined(IFF_DRVRLOCK)) 1883 sin = (struct sockaddr_in *)&ifa->ifa_addr; 1884# else 1885 sin = (struct sockaddr_in *)ifa->ifa_addr; 1886 while (sin && ifa) { 1887 if ((v == 4) && (sin->sin_family == AF_INET)) 1888 break; 1889# ifdef USE_INET6 1890 if ((v == 6) && (sin->sin_family == AF_INET6)) { 1891 inp6 = &((struct sockaddr_in6 *)sin)->sin6_addr; 1892 if (!IN6_IS_ADDR_LINKLOCAL(inp6) && 1893 !IN6_IS_ADDR_LOOPBACK(inp6)) 1894 break; 1895 } 1896# endif 1897# if (__FreeBSD_version >= 300000) 1898 ifa = TAILQ_NEXT(ifa, ifa_link); 1899# else 1900# if defined(__NetBSD__) || defined(__OpenBSD__) 1901 ifa = ifa->ifa_list.tqe_next; 1902# else 1903 ifa = ifa->ifa_next; 1904# endif 1905# endif /* __FreeBSD_version >= 300000 */ 1906 if (ifa) 1907 sin = (struct sockaddr_in *)ifa->ifa_addr; 1908 } 1909 if (ifa == NULL) 1910 sin = NULL; 1911 if (sin == NULL) 1912 return -1; 1913# endif /* (BSD < 199306) && (!__sgi && IFF_DRVLOCK) */ 1914# ifdef USE_INET6 1915 if (v == 6) 1916 bcopy((char *)inp6, (char *)inp, sizeof(*inp6)); 1917 else 1918# endif 1919 { 1920 in = sin->sin_addr; 1921 *inp = in; 1922 } 1923# endif /* linux */ 1924# endif /* SOLARIS */ 1925 return 0; 1926} 1927 1928 1929static void frsynclist(fr) 1930register frentry_t *fr; 1931{ 1932 for (; fr; fr = fr->fr_next) { 1933 if (fr->fr_ifa != NULL) { 1934 fr->fr_ifa = GETUNIT(fr->fr_ifname, fr->fr_ip.fi_v); 1935 if (fr->fr_ifa == NULL) 1936 fr->fr_ifa = (void *)-1; 1937 } 1938 if (fr->fr_grp) 1939 frsynclist(fr->fr_grp); 1940 } 1941} 1942 1943 1944void frsync() 1945{ 1946# if !SOLARIS 1947 register struct ifnet *ifp; 1948 1949# if defined(__OpenBSD__) || ((NetBSD >= 199511) && (NetBSD < 1991011)) || \ 1950 (defined(__FreeBSD_version) && (__FreeBSD_version >= 300000)) 1951# if (NetBSD >= 199905) || defined(__OpenBSD__) 1952 for (ifp = ifnet.tqh_first; ifp; ifp = ifp->if_list.tqe_next) 1953# else 1954 for (ifp = ifnet.tqh_first; ifp; ifp = ifp->if_link.tqe_next) 1955# endif 1956# else 1957 for (ifp = ifnet; ifp; ifp = ifp->if_next) 1958# endif 1959 { 1960 ip_natsync(ifp); 1961 ip_statesync(ifp); 1962 } 1963 ip_natsync((struct ifnet *)-1); 1964# endif /* !SOLARIS */ 1965 1966 WRITE_ENTER(&ipf_mutex); 1967 frsynclist(ipacct[0][fr_active]); 1968 frsynclist(ipacct[1][fr_active]); 1969 frsynclist(ipfilter[0][fr_active]); 1970 frsynclist(ipfilter[1][fr_active]); 1971#ifdef USE_INET6 1972 frsynclist(ipacct6[0][fr_active]); 1973 frsynclist(ipacct6[1][fr_active]); 1974 frsynclist(ipfilter6[0][fr_active]); 1975 frsynclist(ipfilter6[1][fr_active]); 1976#endif 1977 RWLOCK_EXIT(&ipf_mutex); 1978} 1979 1980 1981/* 1982 * In the functions below, bcopy() is called because the pointer being 1983 * copied _from_ in this instance is a pointer to a char buf (which could 1984 * end up being unaligned) and on the kernel's local stack. 1985 */ 1986int ircopyptr(a, b, c) 1987void *a, *b; 1988size_t c; 1989{ 1990 caddr_t ca; 1991 int err; 1992 1993#if SOLARIS 1994 if (copyin(a, (char *)&ca, sizeof(ca))) 1995 return EFAULT; 1996#else 1997 bcopy(a, &ca, sizeof(ca)); 1998#endif 1999 err = copyin(ca, b, c); 2000 if (err) 2001 err = EFAULT; 2002 return err; 2003} 2004 2005 2006int iwcopyptr(a, b, c) 2007void *a, *b; 2008size_t c; 2009{ 2010 caddr_t ca; 2011 int err; 2012 2013#if SOLARIS 2014 if (copyin(b, (char *)&ca, sizeof(ca))) 2015 return EFAULT; 2016#else 2017 bcopy(b, &ca, sizeof(ca)); 2018#endif 2019 err = copyout(a, ca, c); 2020 if (err) 2021 err = EFAULT; 2022 return err; 2023} 2024 2025#else /* _KERNEL */ 2026 2027 2028/* 2029 * return the first IP Address associated with an interface 2030 */ 2031int fr_ifpaddr(v, ifptr, inp) 2032int v; 2033void *ifptr; 2034struct in_addr *inp; 2035{ 2036 return 0; 2037} 2038 2039 2040int ircopyptr(a, b, c) 2041void *a, *b; 2042size_t c; 2043{ 2044 caddr_t ca; 2045 2046 bcopy(a, &ca, sizeof(ca)); 2047 bcopy(ca, b, c); 2048 return 0; 2049} 2050 2051 2052int iwcopyptr(a, b, c) 2053void *a, *b; 2054size_t c; 2055{ 2056 caddr_t ca; 2057 2058 bcopy(b, &ca, sizeof(ca)); 2059 bcopy(a, ca, c); 2060 return 0; 2061} 2062 2063 2064#endif 2065 2066 2067int fr_lock(data, lockp) 2068caddr_t data; 2069int *lockp; 2070{ 2071 int arg, error; 2072 2073 error = IRCOPY(data, (caddr_t)&arg, sizeof(arg)); 2074 if (!error) { 2075 error = IWCOPY((caddr_t)lockp, data, sizeof(*lockp)); 2076 if (!error) 2077 *lockp = arg; 2078 } 2079 return error; 2080} 2081 2082 2083void fr_getstat(fiop) 2084friostat_t *fiop; 2085{ 2086 bcopy((char *)frstats, (char *)fiop->f_st, sizeof(filterstats_t) * 2); 2087 fiop->f_locks[0] = fr_state_lock; 2088 fiop->f_locks[1] = fr_nat_lock; 2089 fiop->f_locks[2] = fr_frag_lock; 2090 fiop->f_locks[3] = fr_auth_lock; 2091 fiop->f_fin[0] = ipfilter[0][0]; 2092 fiop->f_fin[1] = ipfilter[0][1]; 2093 fiop->f_fout[0] = ipfilter[1][0]; 2094 fiop->f_fout[1] = ipfilter[1][1]; 2095 fiop->f_acctin[0] = ipacct[0][0]; 2096 fiop->f_acctin[1] = ipacct[0][1]; 2097 fiop->f_acctout[0] = ipacct[1][0]; 2098 fiop->f_acctout[1] = ipacct[1][1]; 2099#ifdef USE_INET6 2100 fiop->f_fin6[0] = ipfilter6[0][0]; 2101 fiop->f_fin6[1] = ipfilter6[0][1]; 2102 fiop->f_fout6[0] = ipfilter6[1][0]; 2103 fiop->f_fout6[1] = ipfilter6[1][1]; 2104 fiop->f_acctin6[0] = ipacct6[0][0]; 2105 fiop->f_acctin6[1] = ipacct6[0][1]; 2106 fiop->f_acctout6[0] = ipacct6[1][0]; 2107 fiop->f_acctout6[1] = ipacct6[1][1]; 2108#else 2109 fiop->f_fin6[0] = NULL; 2110 fiop->f_fin6[1] = NULL; 2111 fiop->f_fout6[0] = NULL; 2112 fiop->f_fout6[1] = NULL; 2113 fiop->f_acctin6[0] = NULL; 2114 fiop->f_acctin6[1] = NULL; 2115 fiop->f_acctout6[0] = NULL; 2116 fiop->f_acctout6[1] = NULL; 2117#endif 2118 fiop->f_active = fr_active; 2119 fiop->f_froute[0] = ipl_frouteok[0]; 2120 fiop->f_froute[1] = ipl_frouteok[1]; 2121 2122 fiop->f_running = fr_running; 2123 fiop->f_groups[0][0] = ipfgroups[0][0]; 2124 fiop->f_groups[0][1] = ipfgroups[0][1]; 2125 fiop->f_groups[1][0] = ipfgroups[1][0]; 2126 fiop->f_groups[1][1] = ipfgroups[1][1]; 2127 fiop->f_groups[2][0] = ipfgroups[2][0]; 2128 fiop->f_groups[2][1] = ipfgroups[2][1]; 2129#ifdef IPFILTER_LOG 2130 fiop->f_logging = 1; 2131#else 2132 fiop->f_logging = 0; 2133#endif 2134 fiop->f_defpass = fr_pass; 2135 strncpy(fiop->f_version, ipfilter_version, sizeof(fiop->f_version)); 2136} 2137 2138 2139#ifdef USE_INET6 2140int icmptoicmp6types[ICMP_MAXTYPE+1] = { 2141 ICMP6_ECHO_REPLY, /* 0: ICMP_ECHOREPLY */ 2142 -1, /* 1: UNUSED */ 2143 -1, /* 2: UNUSED */ 2144 ICMP6_DST_UNREACH, /* 3: ICMP_UNREACH */ 2145 -1, /* 4: ICMP_SOURCEQUENCH */ 2146 ND_REDIRECT, /* 5: ICMP_REDIRECT */ 2147 -1, /* 6: UNUSED */ 2148 -1, /* 7: UNUSED */ 2149 ICMP6_ECHO_REQUEST, /* 8: ICMP_ECHO */ 2150 -1, /* 9: UNUSED */ 2151 -1, /* 10: UNUSED */ 2152 ICMP6_TIME_EXCEEDED, /* 11: ICMP_TIMXCEED */ 2153 ICMP6_PARAM_PROB, /* 12: ICMP_PARAMPROB */ 2154 -1, /* 13: ICMP_TSTAMP */ 2155 -1, /* 14: ICMP_TSTAMPREPLY */ 2156 -1, /* 15: ICMP_IREQ */ 2157 -1, /* 16: ICMP_IREQREPLY */ 2158 -1, /* 17: ICMP_MASKREQ */ 2159 -1, /* 18: ICMP_MASKREPLY */ 2160}; 2161 2162 2163int icmptoicmp6unreach[ICMP_MAX_UNREACH] = { 2164 ICMP6_DST_UNREACH_ADDR, /* 0: ICMP_UNREACH_NET */ 2165 ICMP6_DST_UNREACH_ADDR, /* 1: ICMP_UNREACH_HOST */ 2166 -1, /* 2: ICMP_UNREACH_PROTOCOL */ 2167 ICMP6_DST_UNREACH_NOPORT, /* 3: ICMP_UNREACH_PORT */ 2168 -1, /* 4: ICMP_UNREACH_NEEDFRAG */ 2169 ICMP6_DST_UNREACH_NOTNEIGHBOR, /* 5: ICMP_UNREACH_SRCFAIL */ 2170 ICMP6_DST_UNREACH_ADDR, /* 6: ICMP_UNREACH_NET_UNKNOWN */ 2171 ICMP6_DST_UNREACH_ADDR, /* 7: ICMP_UNREACH_HOST_UNKNOWN */ 2172 -1, /* 8: ICMP_UNREACH_ISOLATED */ 2173 ICMP6_DST_UNREACH_ADMIN, /* 9: ICMP_UNREACH_NET_PROHIB */ 2174 ICMP6_DST_UNREACH_ADMIN, /* 10: ICMP_UNREACH_HOST_PROHIB */ 2175 -1, /* 11: ICMP_UNREACH_TOSNET */ 2176 -1, /* 12: ICMP_UNREACH_TOSHOST */ 2177 ICMP6_DST_UNREACH_ADMIN, /* 13: ICMP_UNREACH_ADMIN_PROHIBIT */ 2178}; 2179#endif 2180