fil.c revision 109623
1122397Sharti/* 2122397Sharti * Copyright (C) 1993-2001 by Darren Reed. 3122397Sharti * 4122397Sharti * See the IPFILTER.LICENCE file for details on licencing. 5122397Sharti */ 6122397Sharti#ifdef __sgi 7122397Sharti# include <sys/ptimers.h> 8122397Sharti#endif 9122397Sharti#include <sys/errno.h> 10122397Sharti#include <sys/types.h> 11122397Sharti#include <sys/param.h> 12122397Sharti#include <sys/time.h> 13122397Sharti#include <sys/file.h> 14122397Sharti#if defined(__NetBSD__) && (NetBSD >= 199905) && !defined(IPFILTER_LKM) && \ 15122397Sharti defined(_KERNEL) 16122397Sharti# include "opt_ipfilter_log.h" 17122397Sharti#endif 18122397Sharti#if (defined(KERNEL) || defined(_KERNEL)) && defined(__FreeBSD_version) && \ 19122397Sharti (__FreeBSD_version >= 220000) 20125012Sharti# if (__FreeBSD_version >= 400000) 21122397Sharti# ifndef KLD_MODULE 22122397Sharti# 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 109623 2003-01-21 08:56:16Z alfred $"; 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) == -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_NOWAIT); 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 (changed == -1) 1211 /* 1212 * If a packet results in a NAT error, do not 1213 * send a reset or ICMP error as it may disrupt 1214 * an existing flow. This is the proxy saying 1215 * the content is bad so just drop the packet 1216 * silently. 1217 */ 1218 ; 1219 else if (pass & FR_RETICMP) { 1220 int dst; 1221 1222 if ((pass & FR_RETMASK) == FR_FAKEICMP) 1223 dst = 1; 1224 else 1225 dst = 0; 1226 send_icmp_err(ip, ICMP_UNREACH, fin, dst); 1227 ATOMIC_INCL(frstats[0].fr_ret); 1228 } else if (((pass & FR_RETMASK) == FR_RETRST) && 1229 !(fin->fin_fl & FI_SHORT)) { 1230 if (send_reset(ip, fin) == 0) { 1231 ATOMIC_INCL(frstats[1].fr_ret); 1232 } 1233 } 1234 } else { 1235 if (pass & FR_RETRST) 1236 error = ECONNRESET; 1237 } 1238 } 1239 1240 /* 1241 * If we didn't drop off the bottom of the list of rules (and thus 1242 * the 'current' rule fr is not NULL), then we may have some extra 1243 * instructions about what to do with a packet. 1244 * Once we're finished return to our caller, freeing the packet if 1245 * we are dropping it (* BSD ONLY *). 1246 */ 1247 if ((changed == -1) && (pass & FR_PASS)) { 1248 pass &= ~FR_PASS; 1249 pass |= FR_BLOCK; 1250 } 1251#if defined(_KERNEL) 1252# if !SOLARIS 1253# if !defined(linux) 1254 if (fr) { 1255 frdest_t *fdp = &fr->fr_tif; 1256 1257 if (((pass & FR_FASTROUTE) && !out) || 1258 (fdp->fd_ifp && fdp->fd_ifp != (struct ifnet *)-1)) { 1259 (void) ipfr_fastroute(m, mp, fin, fdp); 1260 m = *mp; 1261 } 1262 1263 if (mc != NULL) 1264 (void) ipfr_fastroute(mc, &mc, fin, &fr->fr_dif); 1265 } 1266 1267 if (!(pass & FR_PASS) && m) { 1268 m_freem(m); 1269 m = *mp = NULL; 1270 } 1271# ifdef __sgi 1272 else if (changed && up && m) 1273 m_copyback(m, 0, up, hbuf); 1274# endif 1275# endif /* !linux */ 1276# else /* !SOLARIS */ 1277 if (fr) { 1278 frdest_t *fdp = &fr->fr_tif; 1279 1280 if (((pass & FR_FASTROUTE) && !out) || 1281 (fdp->fd_ifp && fdp->fd_ifp != (struct ifnet *)-1)) 1282 (void) ipfr_fastroute(ip, m, mp, fin, fdp); 1283 1284 if (mc != NULL) 1285 (void) ipfr_fastroute(ip, mc, &mc, fin, &fr->fr_dif); 1286 } 1287# endif /* !SOLARIS */ 1288 return (pass & FR_PASS) ? 0 : error; 1289#else /* _KERNEL */ 1290 if (pass & FR_NOMATCH) 1291 return 1; 1292 if (pass & FR_PASS) 1293 return 0; 1294 if (pass & FR_AUTH) 1295 return -2; 1296 if ((pass & FR_RETMASK) == FR_RETRST) 1297 return -3; 1298 if ((pass & FR_RETMASK) == FR_RETICMP) 1299 return -4; 1300 if ((pass & FR_RETMASK) == FR_FAKEICMP) 1301 return -5; 1302 return -1; 1303#endif /* _KERNEL */ 1304} 1305 1306 1307/* 1308 * ipf_cksum 1309 * addr should be 16bit aligned and len is in bytes. 1310 * length is in bytes 1311 */ 1312u_short ipf_cksum(addr, len) 1313register u_short *addr; 1314register int len; 1315{ 1316 register u_32_t sum = 0; 1317 1318 for (sum = 0; len > 1; len -= 2) 1319 sum += *addr++; 1320 1321 /* mop up an odd byte, if necessary */ 1322 if (len == 1) 1323 sum += *(u_char *)addr; 1324 1325 /* 1326 * add back carry outs from top 16 bits to low 16 bits 1327 */ 1328 sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */ 1329 sum += (sum >> 16); /* add carry */ 1330 return (u_short)(~sum); 1331} 1332 1333 1334/* 1335 * NB: This function assumes we've pullup'd enough for all of the IP header 1336 * and the TCP header. We also assume that data blocks aren't allocated in 1337 * odd sizes. 1338 */ 1339u_short fr_tcpsum(m, ip, tcp) 1340mb_t *m; 1341ip_t *ip; 1342tcphdr_t *tcp; 1343{ 1344 u_short *sp, slen, ts; 1345 u_int sum, sum2; 1346 int hlen; 1347 1348 /* 1349 * Add up IP Header portion 1350 */ 1351 hlen = ip->ip_hl << 2; 1352 slen = ip->ip_len - hlen; 1353 sum = htons((u_short)ip->ip_p); 1354 sum += htons(slen); 1355 sp = (u_short *)&ip->ip_src; 1356 sum += *sp++; /* ip_src */ 1357 sum += *sp++; 1358 sum += *sp++; /* ip_dst */ 1359 sum += *sp++; 1360 ts = tcp->th_sum; 1361 tcp->th_sum = 0; 1362#ifdef KERNEL 1363# if SOLARIS 1364 sum2 = ip_cksum(m, hlen, sum); /* hlen == offset */ 1365 sum2 = (sum2 & 0xffff) + (sum2 >> 16); 1366 sum2 = ~sum2 & 0xffff; 1367# else /* SOLARIS */ 1368# if defined(BSD) || defined(sun) 1369# if BSD >= 199306 1370 m->m_data += hlen; 1371# else 1372 m->m_off += hlen; 1373# endif 1374 m->m_len -= hlen; 1375 sum2 = in_cksum(m, slen); 1376 m->m_len += hlen; 1377# if BSD >= 199306 1378 m->m_data -= hlen; 1379# else 1380 m->m_off -= hlen; 1381# endif 1382 /* 1383 * Both sum and sum2 are partial sums, so combine them together. 1384 */ 1385 sum = (sum & 0xffff) + (sum >> 16); 1386 sum = ~sum & 0xffff; 1387 sum2 += sum; 1388 sum2 = (sum2 & 0xffff) + (sum2 >> 16); 1389# else /* defined(BSD) || defined(sun) */ 1390{ 1391 union { 1392 u_char c[2]; 1393 u_short s; 1394 } bytes; 1395 u_short len = ip->ip_len; 1396# if defined(__sgi) 1397 int add; 1398# endif 1399 1400 /* 1401 * Add up IP Header portion 1402 */ 1403 sp = (u_short *)&ip->ip_src; 1404 len -= (ip->ip_hl << 2); 1405 sum = ntohs(IPPROTO_TCP); 1406 sum += htons(len); 1407 sum += *sp++; /* ip_src */ 1408 sum += *sp++; 1409 sum += *sp++; /* ip_dst */ 1410 sum += *sp++; 1411 if (sp != (u_short *)tcp) 1412 sp = (u_short *)tcp; 1413 sum += *sp++; /* sport */ 1414 sum += *sp++; /* dport */ 1415 sum += *sp++; /* seq */ 1416 sum += *sp++; 1417 sum += *sp++; /* ack */ 1418 sum += *sp++; 1419 sum += *sp++; /* off */ 1420 sum += *sp++; /* win */ 1421 sum += *sp++; /* Skip over checksum */ 1422 sum += *sp++; /* urp */ 1423 1424# ifdef __sgi 1425 /* 1426 * In case we had to copy the IP & TCP header out of mbufs, 1427 * skip over the mbuf bits which are the header 1428 */ 1429 if ((caddr_t)ip != mtod(m, caddr_t)) { 1430 hlen = (caddr_t)sp - (caddr_t)ip; 1431 while (hlen) { 1432 add = MIN(hlen, m->m_len); 1433 sp = (u_short *)(mtod(m, caddr_t) + add); 1434 hlen -= add; 1435 if (add == m->m_len) { 1436 m = m->m_next; 1437 if (!hlen) { 1438 if (!m) 1439 break; 1440 sp = mtod(m, u_short *); 1441 } 1442 PANIC((!m),("fr_tcpsum(1): not enough data")); 1443 } 1444 } 1445 } 1446# endif 1447 1448 if (!(len -= sizeof(*tcp))) 1449 goto nodata; 1450 while (len > 1) { 1451 if (((caddr_t)sp - mtod(m, caddr_t)) >= m->m_len) { 1452 m = m->m_next; 1453 PANIC((!m),("fr_tcpsum(2): not enough data")); 1454 sp = mtod(m, u_short *); 1455 } 1456 if (((caddr_t)(sp + 1) - mtod(m, caddr_t)) > m->m_len) { 1457 bytes.c[0] = *(u_char *)sp; 1458 m = m->m_next; 1459 PANIC((!m),("fr_tcpsum(3): not enough data")); 1460 sp = mtod(m, u_short *); 1461 bytes.c[1] = *(u_char *)sp; 1462 sum += bytes.s; 1463 sp = (u_short *)((u_char *)sp + 1); 1464 } 1465 if ((u_long)sp & 1) { 1466 bcopy((char *)sp++, (char *)&bytes.s, sizeof(bytes.s)); 1467 sum += bytes.s; 1468 } else 1469 sum += *sp++; 1470 len -= 2; 1471 } 1472 if (len) 1473 sum += ntohs(*(u_char *)sp << 8); 1474nodata: 1475 while (sum > 0xffff) 1476 sum = (sum & 0xffff) + (sum >> 16); 1477 sum2 = (u_short)(~sum & 0xffff); 1478} 1479# endif /* defined(BSD) || defined(sun) */ 1480# endif /* SOLARIS */ 1481#else /* KERNEL */ 1482 for (; slen > 1; slen -= 2) 1483 sum += *sp++; 1484 if (slen) 1485 sum += ntohs(*(u_char *)sp << 8); 1486 while (sum > 0xffff) 1487 sum = (sum & 0xffff) + (sum >> 16); 1488 sum2 = (u_short)(~sum & 0xffff); 1489#endif /* KERNEL */ 1490 tcp->th_sum = ts; 1491 return sum2; 1492} 1493 1494 1495#if defined(_KERNEL) && ( ((BSD < 199306) && !SOLARIS) || defined(__sgi) ) 1496/* 1497 * Copyright (c) 1982, 1986, 1988, 1991, 1993 1498 * The Regents of the University of California. All rights reserved. 1499 * 1500 * Redistribution and use in source and binary forms, with or without 1501 * modification, are permitted provided that the following conditions 1502 * are met: 1503 * 1. Redistributions of source code must retain the above copyright 1504 * notice, this list of conditions and the following disclaimer. 1505 * 2. Redistributions in binary form must reproduce the above copyright 1506 * notice, this list of conditions and the following disclaimer in the 1507 * documentation and/or other materials provided with the distribution. 1508 * 3. All advertising materials mentioning features or use of this software 1509 * must display the following acknowledgement: 1510 * This product includes software developed by the University of 1511 * California, Berkeley and its contributors. 1512 * 4. Neither the name of the University nor the names of its contributors 1513 * may be used to endorse or promote products derived from this software 1514 * without specific prior written permission. 1515 * 1516 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 1517 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1518 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1519 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 1520 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1521 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 1522 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 1523 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 1524 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 1525 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 1526 * SUCH DAMAGE. 1527 * 1528 * @(#)uipc_mbuf.c 8.2 (Berkeley) 1/4/94 1529 * $Id: fil.c,v 2.35.2.63 2002/08/28 12:40:08 darrenr Exp $ 1530 */ 1531/* 1532 * Copy data from an mbuf chain starting "off" bytes from the beginning, 1533 * continuing for "len" bytes, into the indicated buffer. 1534 */ 1535void 1536m_copydata(m, off, len, cp) 1537 register mb_t *m; 1538 register int off; 1539 register int len; 1540 caddr_t cp; 1541{ 1542 register unsigned count; 1543 1544 if (off < 0 || len < 0) 1545 panic("m_copydata"); 1546 while (off > 0) { 1547 if (m == 0) 1548 panic("m_copydata"); 1549 if (off < m->m_len) 1550 break; 1551 off -= m->m_len; 1552 m = m->m_next; 1553 } 1554 while (len > 0) { 1555 if (m == 0) 1556 panic("m_copydata"); 1557 count = MIN(m->m_len - off, len); 1558 bcopy(mtod(m, caddr_t) + off, cp, count); 1559 len -= count; 1560 cp += count; 1561 off = 0; 1562 m = m->m_next; 1563 } 1564} 1565 1566 1567# ifndef linux 1568/* 1569 * Copy data from a buffer back into the indicated mbuf chain, 1570 * starting "off" bytes from the beginning, extending the mbuf 1571 * chain if necessary. 1572 */ 1573void 1574m_copyback(m0, off, len, cp) 1575 struct mbuf *m0; 1576 register int off; 1577 register int len; 1578 caddr_t cp; 1579{ 1580 register int mlen; 1581 register struct mbuf *m = m0, *n; 1582 int totlen = 0; 1583 1584 if (m0 == 0) 1585 return; 1586 while (off > (mlen = m->m_len)) { 1587 off -= mlen; 1588 totlen += mlen; 1589 if (m->m_next == 0) { 1590 n = m_getclr(M_NOWAIT, m->m_type); 1591 if (n == 0) 1592 goto out; 1593 n->m_len = min(MLEN, len + off); 1594 m->m_next = n; 1595 } 1596 m = m->m_next; 1597 } 1598 while (len > 0) { 1599 mlen = min (m->m_len - off, len); 1600 bcopy(cp, off + mtod(m, caddr_t), (unsigned)mlen); 1601 cp += mlen; 1602 len -= mlen; 1603 mlen += off; 1604 off = 0; 1605 totlen += mlen; 1606 if (len == 0) 1607 break; 1608 if (m->m_next == 0) { 1609 n = m_get(M_NOWAIT, m->m_type); 1610 if (n == 0) 1611 break; 1612 n->m_len = min(MLEN, len); 1613 m->m_next = n; 1614 } 1615 m = m->m_next; 1616 } 1617out: 1618#if 0 1619 if (((m = m0)->m_flags & M_PKTHDR) && (m->m_pkthdr.len < totlen)) 1620 m->m_pkthdr.len = totlen; 1621#endif 1622 return; 1623} 1624# endif /* linux */ 1625#endif /* (_KERNEL) && ( ((BSD < 199306) && !SOLARIS) || __sgi) */ 1626 1627 1628frgroup_t *fr_findgroup(num, flags, which, set, fgpp) 1629u_32_t num, flags; 1630minor_t which; 1631int set; 1632frgroup_t ***fgpp; 1633{ 1634 frgroup_t *fg, **fgp; 1635 1636 if (which == IPL_LOGAUTH) 1637 fgp = &ipfgroups[2][set]; 1638 else if (flags & FR_ACCOUNT) 1639 fgp = &ipfgroups[1][set]; 1640 else if (flags & (FR_OUTQUE|FR_INQUE)) 1641 fgp = &ipfgroups[0][set]; 1642 else 1643 return NULL; 1644 1645 while ((fg = *fgp)) 1646 if (fg->fg_num == num) 1647 break; 1648 else 1649 fgp = &fg->fg_next; 1650 if (fgpp) 1651 *fgpp = fgp; 1652 return fg; 1653} 1654 1655 1656frgroup_t *fr_addgroup(num, fp, which, set) 1657u_32_t num; 1658frentry_t *fp; 1659minor_t which; 1660int set; 1661{ 1662 frgroup_t *fg, **fgp; 1663 1664 if ((fg = fr_findgroup(num, fp->fr_flags, which, set, &fgp))) 1665 return fg; 1666 1667 KMALLOC(fg, frgroup_t *); 1668 if (fg) { 1669 fg->fg_num = num; 1670 fg->fg_next = *fgp; 1671 fg->fg_head = fp; 1672 fg->fg_start = &fp->fr_grp; 1673 *fgp = fg; 1674 } 1675 return fg; 1676} 1677 1678 1679void fr_delgroup(num, flags, which, set) 1680u_32_t num, flags; 1681minor_t which; 1682int set; 1683{ 1684 frgroup_t *fg, **fgp; 1685 1686 if (!(fg = fr_findgroup(num, flags, which, set, &fgp))) 1687 return; 1688 1689 *fgp = fg->fg_next; 1690 KFREE(fg); 1691} 1692 1693 1694 1695/* 1696 * recursively flush rules from the list, descending groups as they are 1697 * encountered. if a rule is the head of a group and it has lost all its 1698 * group members, then also delete the group reference. 1699 */ 1700static int frflushlist(set, unit, nfreedp, listp) 1701int set; 1702minor_t unit; 1703int *nfreedp; 1704frentry_t **listp; 1705{ 1706 register int freed = 0, i; 1707 register frentry_t *fp; 1708 1709 while ((fp = *listp)) { 1710 *listp = fp->fr_next; 1711 if (fp->fr_grp) { 1712 i = frflushlist(set, unit, nfreedp, &fp->fr_grp); 1713 MUTEX_ENTER(&ipf_rw); 1714 fp->fr_ref -= i; 1715 MUTEX_EXIT(&ipf_rw); 1716 } 1717 1718 ATOMIC_DEC32(fp->fr_ref); 1719 if (fp->fr_grhead) { 1720 fr_delgroup(fp->fr_grhead, fp->fr_flags, 1721 unit, set); 1722 fp->fr_grhead = 0; 1723 } 1724 if (fp->fr_ref == 0) { 1725 KFREE(fp); 1726 freed++; 1727 } else 1728 fp->fr_next = NULL; 1729 } 1730 *nfreedp += freed; 1731 return freed; 1732} 1733 1734 1735int frflush(unit, flags) 1736minor_t unit; 1737int flags; 1738{ 1739 int flushed = 0, set; 1740 1741 if (unit != IPL_LOGIPF) 1742 return 0; 1743 WRITE_ENTER(&ipf_mutex); 1744 bzero((char *)frcache, sizeof(frcache[0]) * 2); 1745 1746 set = fr_active; 1747 if (flags & FR_INACTIVE) 1748 set = 1 - set; 1749 1750 if (flags & FR_OUTQUE) { 1751#ifdef USE_INET6 1752 (void) frflushlist(set, unit, &flushed, &ipfilter6[1][set]); 1753 (void) frflushlist(set, unit, &flushed, &ipacct6[1][set]); 1754#endif 1755 (void) frflushlist(set, unit, &flushed, &ipfilter[1][set]); 1756 (void) frflushlist(set, unit, &flushed, &ipacct[1][set]); 1757 } 1758 if (flags & FR_INQUE) { 1759#ifdef USE_INET6 1760 (void) frflushlist(set, unit, &flushed, &ipfilter6[0][set]); 1761 (void) frflushlist(set, unit, &flushed, &ipacct6[0][set]); 1762#endif 1763 (void) frflushlist(set, unit, &flushed, &ipfilter[0][set]); 1764 (void) frflushlist(set, unit, &flushed, &ipacct[0][set]); 1765 } 1766 RWLOCK_EXIT(&ipf_mutex); 1767 return flushed; 1768} 1769 1770 1771char *memstr(src, dst, slen, dlen) 1772char *src, *dst; 1773int slen, dlen; 1774{ 1775 char *s = NULL; 1776 1777 while (dlen >= slen) { 1778 if (bcmp(src, dst, slen) == 0) { 1779 s = dst; 1780 break; 1781 } 1782 dst++; 1783 dlen--; 1784 } 1785 return s; 1786} 1787 1788 1789void fixskip(listp, rp, addremove) 1790frentry_t **listp, *rp; 1791int addremove; 1792{ 1793 frentry_t *fp; 1794 int rules = 0, rn = 0; 1795 1796 for (fp = *listp; fp && (fp != rp); fp = fp->fr_next, rules++) 1797 ; 1798 1799 if (!fp) 1800 return; 1801 1802 for (fp = *listp; fp && (fp != rp); fp = fp->fr_next, rn++) 1803 if (fp->fr_skip && (rn + fp->fr_skip >= rules)) 1804 fp->fr_skip += addremove; 1805} 1806 1807 1808#ifdef _KERNEL 1809/* 1810 * count consecutive 1's in bit mask. If the mask generated by counting 1811 * consecutive 1's is different to that passed, return -1, else return # 1812 * of bits. 1813 */ 1814int countbits(ip) 1815u_32_t ip; 1816{ 1817 u_32_t ipn; 1818 int cnt = 0, i, j; 1819 1820 ip = ipn = ntohl(ip); 1821 for (i = 32; i; i--, ipn *= 2) 1822 if (ipn & 0x80000000) 1823 cnt++; 1824 else 1825 break; 1826 ipn = 0; 1827 for (i = 32, j = cnt; i; i--, j--) { 1828 ipn *= 2; 1829 if (j > 0) 1830 ipn++; 1831 } 1832 if (ipn == ip) 1833 return cnt; 1834 return -1; 1835} 1836 1837 1838/* 1839 * return the first IP Address associated with an interface 1840 */ 1841int fr_ifpaddr(v, ifptr, inp) 1842int v; 1843void *ifptr; 1844struct in_addr *inp; 1845{ 1846# ifdef USE_INET6 1847 struct in6_addr *inp6 = NULL; 1848# endif 1849# if SOLARIS 1850 ill_t *ill = ifptr; 1851# else 1852 struct ifnet *ifp = ifptr; 1853# endif 1854 struct in_addr in; 1855 1856# if SOLARIS 1857# ifdef USE_INET6 1858 if (v == 6) { 1859 struct in6_addr in6; 1860 1861 /* 1862 * First is always link local. 1863 */ 1864 if (ill->ill_ipif->ipif_next) 1865 in6 = ill->ill_ipif->ipif_next->ipif_v6lcl_addr; 1866 else 1867 bzero((char *)&in6, sizeof(in6)); 1868 bcopy((char *)&in6, (char *)inp, sizeof(in6)); 1869 } else 1870# endif 1871 { 1872 in.s_addr = ill->ill_ipif->ipif_local_addr; 1873 *inp = in; 1874 } 1875# else /* SOLARIS */ 1876# if linux 1877 ; 1878# else /* linux */ 1879 struct sockaddr_in *sin; 1880 struct ifaddr *ifa; 1881 1882# if (__FreeBSD_version >= 300000) 1883 ifa = TAILQ_FIRST(&ifp->if_addrhead); 1884# else 1885# if defined(__NetBSD__) || defined(__OpenBSD__) 1886 ifa = ifp->if_addrlist.tqh_first; 1887# else 1888# if defined(__sgi) && defined(IFF_DRVRLOCK) /* IRIX 6 */ 1889 ifa = &((struct in_ifaddr *)ifp->in_ifaddr)->ia_ifa; 1890# else 1891 ifa = ifp->if_addrlist; 1892# endif 1893# endif /* __NetBSD__ || __OpenBSD__ */ 1894# endif /* __FreeBSD_version >= 300000 */ 1895# if (BSD < 199306) && !(/*IRIX6*/defined(__sgi) && defined(IFF_DRVRLOCK)) 1896 sin = (struct sockaddr_in *)&ifa->ifa_addr; 1897# else 1898 sin = (struct sockaddr_in *)ifa->ifa_addr; 1899 while (sin && ifa) { 1900 if ((v == 4) && (sin->sin_family == AF_INET)) 1901 break; 1902# ifdef USE_INET6 1903 if ((v == 6) && (sin->sin_family == AF_INET6)) { 1904 inp6 = &((struct sockaddr_in6 *)sin)->sin6_addr; 1905 if (!IN6_IS_ADDR_LINKLOCAL(inp6) && 1906 !IN6_IS_ADDR_LOOPBACK(inp6)) 1907 break; 1908 } 1909# endif 1910# if (__FreeBSD_version >= 300000) 1911 ifa = TAILQ_NEXT(ifa, ifa_link); 1912# else 1913# if defined(__NetBSD__) || defined(__OpenBSD__) 1914 ifa = ifa->ifa_list.tqe_next; 1915# else 1916 ifa = ifa->ifa_next; 1917# endif 1918# endif /* __FreeBSD_version >= 300000 */ 1919 if (ifa) 1920 sin = (struct sockaddr_in *)ifa->ifa_addr; 1921 } 1922 if (ifa == NULL) 1923 sin = NULL; 1924 if (sin == NULL) 1925 return -1; 1926# endif /* (BSD < 199306) && (!__sgi && IFF_DRVLOCK) */ 1927# ifdef USE_INET6 1928 if (v == 6) 1929 bcopy((char *)inp6, (char *)inp, sizeof(*inp6)); 1930 else 1931# endif 1932 { 1933 in = sin->sin_addr; 1934 *inp = in; 1935 } 1936# endif /* linux */ 1937# endif /* SOLARIS */ 1938 return 0; 1939} 1940 1941 1942static void frsynclist(fr) 1943register frentry_t *fr; 1944{ 1945 for (; fr; fr = fr->fr_next) { 1946 if (fr->fr_ifa != NULL) { 1947 fr->fr_ifa = GETUNIT(fr->fr_ifname, fr->fr_ip.fi_v); 1948 if (fr->fr_ifa == NULL) 1949 fr->fr_ifa = (void *)-1; 1950 } 1951 if (fr->fr_grp) 1952 frsynclist(fr->fr_grp); 1953 } 1954} 1955 1956 1957void frsync() 1958{ 1959# if !SOLARIS 1960 register struct ifnet *ifp; 1961 1962# if defined(__OpenBSD__) || ((NetBSD >= 199511) && (NetBSD < 1991011)) || \ 1963 (defined(__FreeBSD_version) && (__FreeBSD_version >= 300000)) 1964# if (NetBSD >= 199905) || defined(__OpenBSD__) 1965 for (ifp = ifnet.tqh_first; ifp; ifp = ifp->if_list.tqe_next) 1966# elif defined(__FreeBSD_version) && (__FreeBSD_version >= 500043) 1967 IFNET_RLOCK(); 1968 TAILQ_FOREACH(ifp, &ifnet, if_link) 1969# else 1970 for (ifp = ifnet.tqh_first; ifp; ifp = ifp->if_link.tqe_next) 1971# endif 1972# else 1973 for (ifp = ifnet; ifp; ifp = ifp->if_next) 1974# endif 1975 { 1976 ip_natsync(ifp); 1977 ip_statesync(ifp); 1978 } 1979# if defined(__FreeBSD_version) && (__FreeBSD_version >= 500043) 1980 IFNET_RUNLOCK(); 1981# endif 1982 ip_natsync((struct ifnet *)-1); 1983# endif /* !SOLARIS */ 1984 1985 WRITE_ENTER(&ipf_mutex); 1986 frsynclist(ipacct[0][fr_active]); 1987 frsynclist(ipacct[1][fr_active]); 1988 frsynclist(ipfilter[0][fr_active]); 1989 frsynclist(ipfilter[1][fr_active]); 1990#ifdef USE_INET6 1991 frsynclist(ipacct6[0][fr_active]); 1992 frsynclist(ipacct6[1][fr_active]); 1993 frsynclist(ipfilter6[0][fr_active]); 1994 frsynclist(ipfilter6[1][fr_active]); 1995#endif 1996 RWLOCK_EXIT(&ipf_mutex); 1997} 1998 1999 2000/* 2001 * In the functions below, bcopy() is called because the pointer being 2002 * copied _from_ in this instance is a pointer to a char buf (which could 2003 * end up being unaligned) and on the kernel's local stack. 2004 */ 2005int ircopyptr(a, b, c) 2006void *a, *b; 2007size_t c; 2008{ 2009 caddr_t ca; 2010 int err; 2011 2012#if SOLARIS 2013 if (copyin(a, (char *)&ca, sizeof(ca))) 2014 return EFAULT; 2015#else 2016 bcopy(a, &ca, sizeof(ca)); 2017#endif 2018 err = copyin(ca, b, c); 2019 if (err) 2020 err = EFAULT; 2021 return err; 2022} 2023 2024 2025int iwcopyptr(a, b, c) 2026void *a, *b; 2027size_t c; 2028{ 2029 caddr_t ca; 2030 int err; 2031 2032#if SOLARIS 2033 if (copyin(b, (char *)&ca, sizeof(ca))) 2034 return EFAULT; 2035#else 2036 bcopy(b, &ca, sizeof(ca)); 2037#endif 2038 err = copyout(a, ca, c); 2039 if (err) 2040 err = EFAULT; 2041 return err; 2042} 2043 2044#else /* _KERNEL */ 2045 2046 2047/* 2048 * return the first IP Address associated with an interface 2049 */ 2050int fr_ifpaddr(v, ifptr, inp) 2051int v; 2052void *ifptr; 2053struct in_addr *inp; 2054{ 2055 return 0; 2056} 2057 2058 2059int ircopyptr(a, b, c) 2060void *a, *b; 2061size_t c; 2062{ 2063 caddr_t ca; 2064 2065 bcopy(a, &ca, sizeof(ca)); 2066 bcopy(ca, b, c); 2067 return 0; 2068} 2069 2070 2071int iwcopyptr(a, b, c) 2072void *a, *b; 2073size_t c; 2074{ 2075 caddr_t ca; 2076 2077 bcopy(b, &ca, sizeof(ca)); 2078 bcopy(a, ca, c); 2079 return 0; 2080} 2081 2082 2083#endif 2084 2085 2086int fr_lock(data, lockp) 2087caddr_t data; 2088int *lockp; 2089{ 2090 int arg, error; 2091 2092 error = IRCOPY(data, (caddr_t)&arg, sizeof(arg)); 2093 if (!error) { 2094 error = IWCOPY((caddr_t)lockp, data, sizeof(*lockp)); 2095 if (!error) 2096 *lockp = arg; 2097 } 2098 return error; 2099} 2100 2101 2102void fr_getstat(fiop) 2103friostat_t *fiop; 2104{ 2105 bcopy((char *)frstats, (char *)fiop->f_st, sizeof(filterstats_t) * 2); 2106 fiop->f_locks[0] = fr_state_lock; 2107 fiop->f_locks[1] = fr_nat_lock; 2108 fiop->f_locks[2] = fr_frag_lock; 2109 fiop->f_locks[3] = fr_auth_lock; 2110 fiop->f_fin[0] = ipfilter[0][0]; 2111 fiop->f_fin[1] = ipfilter[0][1]; 2112 fiop->f_fout[0] = ipfilter[1][0]; 2113 fiop->f_fout[1] = ipfilter[1][1]; 2114 fiop->f_acctin[0] = ipacct[0][0]; 2115 fiop->f_acctin[1] = ipacct[0][1]; 2116 fiop->f_acctout[0] = ipacct[1][0]; 2117 fiop->f_acctout[1] = ipacct[1][1]; 2118#ifdef USE_INET6 2119 fiop->f_fin6[0] = ipfilter6[0][0]; 2120 fiop->f_fin6[1] = ipfilter6[0][1]; 2121 fiop->f_fout6[0] = ipfilter6[1][0]; 2122 fiop->f_fout6[1] = ipfilter6[1][1]; 2123 fiop->f_acctin6[0] = ipacct6[0][0]; 2124 fiop->f_acctin6[1] = ipacct6[0][1]; 2125 fiop->f_acctout6[0] = ipacct6[1][0]; 2126 fiop->f_acctout6[1] = ipacct6[1][1]; 2127#else 2128 fiop->f_fin6[0] = NULL; 2129 fiop->f_fin6[1] = NULL; 2130 fiop->f_fout6[0] = NULL; 2131 fiop->f_fout6[1] = NULL; 2132 fiop->f_acctin6[0] = NULL; 2133 fiop->f_acctin6[1] = NULL; 2134 fiop->f_acctout6[0] = NULL; 2135 fiop->f_acctout6[1] = NULL; 2136#endif 2137 fiop->f_active = fr_active; 2138 fiop->f_froute[0] = ipl_frouteok[0]; 2139 fiop->f_froute[1] = ipl_frouteok[1]; 2140 2141 fiop->f_running = fr_running; 2142 fiop->f_groups[0][0] = ipfgroups[0][0]; 2143 fiop->f_groups[0][1] = ipfgroups[0][1]; 2144 fiop->f_groups[1][0] = ipfgroups[1][0]; 2145 fiop->f_groups[1][1] = ipfgroups[1][1]; 2146 fiop->f_groups[2][0] = ipfgroups[2][0]; 2147 fiop->f_groups[2][1] = ipfgroups[2][1]; 2148#ifdef IPFILTER_LOG 2149 fiop->f_logging = 1; 2150#else 2151 fiop->f_logging = 0; 2152#endif 2153 fiop->f_defpass = fr_pass; 2154 strncpy(fiop->f_version, ipfilter_version, sizeof(fiop->f_version)); 2155} 2156 2157 2158#ifdef USE_INET6 2159int icmptoicmp6types[ICMP_MAXTYPE+1] = { 2160 ICMP6_ECHO_REPLY, /* 0: ICMP_ECHOREPLY */ 2161 -1, /* 1: UNUSED */ 2162 -1, /* 2: UNUSED */ 2163 ICMP6_DST_UNREACH, /* 3: ICMP_UNREACH */ 2164 -1, /* 4: ICMP_SOURCEQUENCH */ 2165 ND_REDIRECT, /* 5: ICMP_REDIRECT */ 2166 -1, /* 6: UNUSED */ 2167 -1, /* 7: UNUSED */ 2168 ICMP6_ECHO_REQUEST, /* 8: ICMP_ECHO */ 2169 -1, /* 9: UNUSED */ 2170 -1, /* 10: UNUSED */ 2171 ICMP6_TIME_EXCEEDED, /* 11: ICMP_TIMXCEED */ 2172 ICMP6_PARAM_PROB, /* 12: ICMP_PARAMPROB */ 2173 -1, /* 13: ICMP_TSTAMP */ 2174 -1, /* 14: ICMP_TSTAMPREPLY */ 2175 -1, /* 15: ICMP_IREQ */ 2176 -1, /* 16: ICMP_IREQREPLY */ 2177 -1, /* 17: ICMP_MASKREQ */ 2178 -1, /* 18: ICMP_MASKREPLY */ 2179}; 2180 2181 2182int icmptoicmp6unreach[ICMP_MAX_UNREACH] = { 2183 ICMP6_DST_UNREACH_ADDR, /* 0: ICMP_UNREACH_NET */ 2184 ICMP6_DST_UNREACH_ADDR, /* 1: ICMP_UNREACH_HOST */ 2185 -1, /* 2: ICMP_UNREACH_PROTOCOL */ 2186 ICMP6_DST_UNREACH_NOPORT, /* 3: ICMP_UNREACH_PORT */ 2187 -1, /* 4: ICMP_UNREACH_NEEDFRAG */ 2188 ICMP6_DST_UNREACH_NOTNEIGHBOR, /* 5: ICMP_UNREACH_SRCFAIL */ 2189 ICMP6_DST_UNREACH_ADDR, /* 6: ICMP_UNREACH_NET_UNKNOWN */ 2190 ICMP6_DST_UNREACH_ADDR, /* 7: ICMP_UNREACH_HOST_UNKNOWN */ 2191 -1, /* 8: ICMP_UNREACH_ISOLATED */ 2192 ICMP6_DST_UNREACH_ADMIN, /* 9: ICMP_UNREACH_NET_PROHIB */ 2193 ICMP6_DST_UNREACH_ADMIN, /* 10: ICMP_UNREACH_HOST_PROHIB */ 2194 -1, /* 11: ICMP_UNREACH_TOSNET */ 2195 -1, /* 12: ICMP_UNREACH_TOSHOST */ 2196 ICMP6_DST_UNREACH_ADMIN, /* 13: ICMP_UNREACH_ADMIN_PROHIBIT */ 2197}; 2198#endif 2199 2200 2201#ifndef _KERNEL 2202int mbuflen(buf) 2203mb_t *buf; 2204{ 2205 ip_t *ip; 2206 2207 ip = (ip_t *)buf; 2208 return ip->ip_len; 2209} 2210#endif 2211