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