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