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