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