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