fil.c revision 59874
1/* 2 * Copyright (C) 1993-1998 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 59874 2000-05-01 20:32:07Z peter $"; 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 1619