fil.c revision 111119
1251881Speter/* 2251881Speter * Copyright (C) 1993-2001 by Darren Reed. 3251881Speter * 4251881Speter * See the IPFILTER.LICENCE file for details on licencing. 5251881Speter */ 6251881Speter#if defined(__sgi) && (IRIX > 602) 7251881Speter# include <sys/ptimers.h> 8251881Speter#endif 9251881Speter#include <sys/errno.h> 10251881Speter#include <sys/types.h> 11251881Speter#include <sys/param.h> 12251881Speter#include <sys/time.h> 13251881Speter#include <sys/file.h> 14251881Speter#if defined(__NetBSD__) && (NetBSD >= 199905) && !defined(IPFILTER_LKM) && \ 15251881Speter defined(_KERNEL) 16251881Speter# include "opt_ipfilter_log.h" 17251881Speter#endif 18251881Speter#if (defined(KERNEL) || defined(_KERNEL)) && defined(__FreeBSD_version) && \ 19251881Speter (__FreeBSD_version >= 220000) 20251881Speter# if (__FreeBSD_version >= 400000) 21251881Speter# ifndef KLD_MODULE 22251881Speter# include "opt_inet6.h" 23251881Speter# endif 24251881Speter# if (__FreeBSD_version == 400019) 25251881Speter# define CSUM_DELAY_DATA 26251881Speter# endif 27251881Speter# endif 28251881Speter# include <sys/filio.h> 29251881Speter# include <sys/fcntl.h> 30251881Speter#else 31251881Speter# include <sys/ioctl.h> 32251881Speter#endif 33251881Speter#if (defined(_KERNEL) || defined(KERNEL)) && !defined(linux) 34251881Speter# include <sys/systm.h> 35251881Speter#else 36251881Speter# include <stdio.h> 37251881Speter# include <string.h> 38251881Speter# include <stdlib.h> 39251881Speter#endif 40251881Speter#if !defined(__SVR4) && !defined(__svr4__) 41251881Speter# ifndef linux 42251881Speter# include <sys/mbuf.h> 43251881Speter# endif 44251881Speter#else 45251881Speter# include <sys/byteorder.h> 46251881Speter# if SOLARIS2 < 5 47251881Speter# include <sys/dditypes.h> 48251881Speter# endif 49251881Speter# include <sys/stream.h> 50251881Speter#endif 51251881Speter#ifndef linux 52251881Speter# include <sys/protosw.h> 53251881Speter# include <sys/socket.h> 54251881Speter#endif 55251881Speter#include <net/if.h> 56251881Speter#ifdef sun 57251881Speter# include <net/af.h> 58251881Speter#endif 59251881Speter#include <net/route.h> 60251881Speter#include <netinet/in.h> 61251881Speter#include <netinet/in_systm.h> 62251881Speter#include <netinet/ip.h> 63251881Speter#ifndef linux 64251881Speter# include <netinet/ip_var.h> 65251881Speter#endif 66251881Speter#if defined(__sgi) && defined(IFF_DRVRLOCK) /* IRIX 6 */ 67251881Speter# include <sys/hashing.h> 68251881Speter# include <netinet/in_var.h> 69251881Speter#endif 70251881Speter#include <netinet/tcp.h> 71251881Speter#include <netinet/udp.h> 72251881Speter#include <netinet/ip_icmp.h> 73251881Speter#include "netinet/ip_compat.h" 74251881Speter#ifdef USE_INET6 75251881Speter# include <netinet/icmp6.h> 76251881Speter# if !SOLARIS && defined(_KERNEL) 77251881Speter# include <netinet6/in6_var.h> 78251881Speter# endif 79251881Speter#endif 80251881Speter#include <netinet/tcpip.h> 81251881Speter#include "netinet/ip_fil.h" 82251881Speter#include "netinet/ip_nat.h" 83251881Speter#include "netinet/ip_frag.h" 84251881Speter#include "netinet/ip_state.h" 85251881Speter#include "netinet/ip_proxy.h" 86251881Speter#include "netinet/ip_auth.h" 87251881Speter# if defined(__FreeBSD_version) && (__FreeBSD_version >= 300000) 88251881Speter# include <sys/malloc.h> 89251881Speter# if defined(_KERNEL) && !defined(IPFILTER_LKM) 90251881Speter# include "opt_ipfilter.h" 91251881Speter# endif 92251881Speter# endif 93251881Speter#ifndef MIN 94251881Speter# define MIN(a,b) (((a)<(b))?(a):(b)) 95251881Speter#endif 96251881Speter#include "netinet/ipl.h" 97251881Speter 98251881Speter#include <machine/in_cksum.h> 99251881Speter 100251881Speter#if !defined(lint) 101251881Speterstatic const char sccsid[] = "@(#)fil.c 1.36 6/5/96 (C) 1993-2000 Darren Reed"; 102251881Speterstatic const char rcsid[] = "@(#)$FreeBSD: head/sys/contrib/ipfilter/netinet/fil.c 111119 2003-02-19 05:47:46Z imp $"; 103251881Speter#endif 104251881Speter 105251881Speter#ifndef _KERNEL 106251881Speter# include "ipf.h" 107251881Speter# include "ipt.h" 108251881Speterextern int opts; 109251881Speter 110251881Speter# define FR_VERBOSE(verb_pr) verbose verb_pr 111251881Speter# define FR_DEBUG(verb_pr) debug verb_pr 112251881Speter# define IPLLOG(a, c, d, e) ipflog(a, c, d, e) 113251881Speter#else /* #ifndef _KERNEL */ 114251881Speter# define FR_VERBOSE(verb_pr) 115251881Speter# define FR_DEBUG(verb_pr) 116251881Speter# define IPLLOG(a, c, d, e) ipflog(a, c, d, e) 117251881Speter# if SOLARIS || defined(__sgi) 118251881Speterextern KRWLOCK_T ipf_mutex, ipf_auth, ipf_nat; 119251881Speterextern kmutex_t ipf_rw; 120251881Speter# endif /* SOLARIS || __sgi */ 121251881Speter#endif /* _KERNEL */ 122251881Speter 123251881Speter 124251881Speterstruct filterstats frstats[2] = {{0,0,0,0,0},{0,0,0,0,0}}; 125251881Speterstruct frentry *ipfilter[2][2] = { { NULL, NULL }, { NULL, NULL } }, 126251881Speter#ifdef USE_INET6 127251881Speter *ipfilter6[2][2] = { { NULL, NULL }, { NULL, NULL } }, 128251881Speter *ipacct6[2][2] = { { NULL, NULL }, { NULL, NULL } }, 129251881Speter#endif 130251881Speter *ipacct[2][2] = { { NULL, NULL }, { NULL, NULL } }; 131251881Speterstruct frgroup *ipfgroups[3][2]; 132251881Speterint fr_flags = IPF_LOGGING; 133251881Speterint fr_active = 0; 134251881Speterint fr_chksrc = 0; 135251881Speterint fr_minttl = 3; 136251881Speterint fr_minttllog = 1; 137251881Speter#if defined(IPFILTER_DEFAULT_BLOCK) 138251881Speterint fr_pass = FR_NOMATCH|FR_BLOCK; 139251881Speter#else 140251881Speterint fr_pass = (IPF_DEFAULT_PASS|FR_NOMATCH); 141251881Speter#endif 142251881Speterchar ipfilter_version[] = IPL_VERSION; 143251881Speter 144251881Speterfr_info_t frcache[2]; 145251881Speter 146251881Speterstatic int frflushlist __P((int, minor_t, int *, frentry_t **)); 147251881Speter#ifdef _KERNEL 148251881Speterstatic void frsynclist __P((frentry_t *)); 149251881Speter#endif 150251881Speter 151251881Speter 152251881Speter/* 153251881Speter * bit values for identifying presence of individual IP options 154251881Speter */ 155251881Speterstruct optlist ipopts[20] = { 156251881Speter { IPOPT_NOP, 0x000001 }, 157251881Speter { IPOPT_RR, 0x000002 }, 158251881Speter { IPOPT_ZSU, 0x000004 }, 159251881Speter { IPOPT_MTUP, 0x000008 }, 160251881Speter { IPOPT_MTUR, 0x000010 }, 161251881Speter { IPOPT_ENCODE, 0x000020 }, 162251881Speter { IPOPT_TS, 0x000040 }, 163251881Speter { IPOPT_TR, 0x000080 }, 164251881Speter { IPOPT_SECURITY, 0x000100 }, 165251881Speter { IPOPT_LSRR, 0x000200 }, 166251881Speter { IPOPT_E_SEC, 0x000400 }, 167251881Speter { IPOPT_CIPSO, 0x000800 }, 168251881Speter { IPOPT_SATID, 0x001000 }, 169251881Speter { IPOPT_SSRR, 0x002000 }, 170251881Speter { IPOPT_ADDEXT, 0x004000 }, 171251881Speter { IPOPT_VISA, 0x008000 }, 172251881Speter { IPOPT_IMITD, 0x010000 }, 173251881Speter { IPOPT_EIP, 0x020000 }, 174251881Speter { IPOPT_FINN, 0x040000 }, 175251881Speter { 0, 0x000000 } 176251881Speter}; 177251881Speter 178251881Speter/* 179251881Speter * bit values for identifying presence of individual IP security options 180251881Speter */ 181251881Speterstruct optlist secopt[8] = { 182251881Speter { IPSO_CLASS_RES4, 0x01 }, 183251881Speter { IPSO_CLASS_TOPS, 0x02 }, 184251881Speter { IPSO_CLASS_SECR, 0x04 }, 185251881Speter { IPSO_CLASS_RES3, 0x08 }, 186251881Speter { IPSO_CLASS_CONF, 0x10 }, 187251881Speter { IPSO_CLASS_UNCL, 0x20 }, 188251881Speter { IPSO_CLASS_RES2, 0x40 }, 189251881Speter { IPSO_CLASS_RES1, 0x80 } 190251881Speter}; 191251881Speter 192251881Speter 193251881Speter/* 194251881Speter * compact the IP header into a structure which contains just the info. 195251881Speter * which is useful for comparing IP headers with. 196251881Speter */ 197251881Spetervoid fr_makefrip(hlen, ip, fin) 198251881Speterint hlen; 199251881Speterip_t *ip; 200251881Speterfr_info_t *fin; 201251881Speter{ 202251881Speter u_short optmsk = 0, secmsk = 0, auth = 0; 203251881Speter int i, mv, ol, off, p, plen, v; 204251881Speter fr_ip_t *fi = &fin->fin_fi; 205251881Speter struct optlist *op; 206251881Speter u_char *s, opt; 207251881Speter tcphdr_t *tcp; 208251881Speter 209251881Speter fin->fin_rev = 0; 210251881Speter fin->fin_fr = NULL; 211251881Speter fin->fin_tcpf = 0; 212251881Speter fin->fin_data[0] = 0; 213251881Speter fin->fin_data[1] = 0; 214251881Speter fin->fin_rule = -1; 215251881Speter fin->fin_group = -1; 216251881Speter fin->fin_icode = ipl_unreach; 217251881Speter v = fin->fin_v; 218251881Speter fi->fi_v = v; 219251881Speter fin->fin_hlen = hlen; 220251881Speter if (v == 4) { 221251881Speter fin->fin_id = ip->ip_id; 222251881Speter fi->fi_tos = ip->ip_tos; 223251881Speter off = (ip->ip_off & IP_OFFMASK); 224251881Speter tcp = (tcphdr_t *)((char *)ip + hlen); 225251881Speter (*(((u_short *)fi) + 1)) = (*(((u_short *)ip) + 4)); 226251881Speter fi->fi_src.i6[1] = 0; 227251881Speter fi->fi_src.i6[2] = 0; 228251881Speter fi->fi_src.i6[3] = 0; 229251881Speter fi->fi_dst.i6[1] = 0; 230251881Speter fi->fi_dst.i6[2] = 0; 231251881Speter fi->fi_dst.i6[3] = 0; 232251881Speter fi->fi_saddr = ip->ip_src.s_addr; 233251881Speter fi->fi_daddr = ip->ip_dst.s_addr; 234251881Speter p = ip->ip_p; 235251881Speter fi->fi_fl = (hlen > sizeof(ip_t)) ? FI_OPTIONS : 0; 236251881Speter if (ip->ip_off & (IP_MF|IP_OFFMASK)) 237251881Speter fi->fi_fl |= FI_FRAG; 238251881Speter plen = ip->ip_len; 239251881Speter fin->fin_dlen = plen - hlen; 240251881Speter } 241251881Speter#ifdef USE_INET6 242251881Speter else if (v == 6) { 243251881Speter ip6_t *ip6 = (ip6_t *)ip; 244251881Speter 245251881Speter off = 0; 246251881Speter p = ip6->ip6_nxt; 247251881Speter fi->fi_p = p; 248251881Speter fi->fi_ttl = ip6->ip6_hlim; 249251881Speter tcp = (tcphdr_t *)(ip6 + 1); 250251881Speter fi->fi_src.in6 = ip6->ip6_src; 251251881Speter fi->fi_dst.in6 = ip6->ip6_dst; 252251881Speter fin->fin_id = (u_short)(ip6->ip6_flow & 0xffff); 253251881Speter fi->fi_tos = 0; 254251881Speter fi->fi_fl = 0; 255251881Speter plen = ntohs(ip6->ip6_plen); 256251881Speter fin->fin_dlen = plen; 257251881Speter plen += sizeof(*ip6); 258251881Speter } 259251881Speter#endif 260251881Speter else 261251881Speter return; 262251881Speter 263251881Speter fin->fin_off = off; 264251881Speter fin->fin_plen = plen; 265251881Speter fin->fin_dp = (char *)tcp; 266251881Speter fin->fin_misc = 0; 267251881Speter off <<= 3; 268251881Speter 269251881Speter switch (p) 270251881Speter { 271251881Speter#ifdef USE_INET6 272251881Speter case IPPROTO_ICMPV6 : 273251881Speter { 274251881Speter int minicmpsz = sizeof(struct icmp6_hdr); 275251881Speter struct icmp6_hdr *icmp6; 276251881Speter 277251881Speter if (fin->fin_dlen > 1) { 278251881Speter fin->fin_data[0] = *(u_short *)tcp; 279251881Speter 280251881Speter icmp6 = (struct icmp6_hdr *)tcp; 281251881Speter 282251881Speter switch (icmp6->icmp6_type) 283251881Speter { 284251881Speter case ICMP6_ECHO_REPLY : 285251881Speter case ICMP6_ECHO_REQUEST : 286251881Speter minicmpsz = ICMP6_MINLEN; 287251881Speter break; 288251881Speter case ICMP6_DST_UNREACH : 289251881Speter case ICMP6_PACKET_TOO_BIG : 290251881Speter case ICMP6_TIME_EXCEEDED : 291251881Speter case ICMP6_PARAM_PROB : 292251881Speter minicmpsz = ICMP6ERR_IPICMPHLEN; 293251881Speter break; 294251881Speter default : 295251881Speter break; 296251881Speter } 297251881Speter } 298251881Speter 299251881Speter if (!(plen >= minicmpsz)) 300251881Speter fi->fi_fl |= FI_SHORT; 301251881Speter 302251881Speter break; 303251881Speter } 304251881Speter#endif 305251881Speter case IPPROTO_ICMP : 306251881Speter { 307251881Speter int minicmpsz = sizeof(struct icmp); 308251881Speter icmphdr_t *icmp; 309251881Speter 310251881Speter if (!off && (fin->fin_dlen > 1)) { 311251881Speter fin->fin_data[0] = *(u_short *)tcp; 312251881Speter 313251881Speter icmp = (icmphdr_t *)tcp; 314251881Speter 315251881Speter switch (icmp->icmp_type) 316251881Speter { 317251881Speter case ICMP_ECHOREPLY : 318251881Speter case ICMP_ECHO : 319251881Speter /* Router discovery messages - RFC 1256 */ 320251881Speter case ICMP_ROUTERADVERT : 321251881Speter case ICMP_ROUTERSOLICIT : 322251881Speter minicmpsz = ICMP_MINLEN; 323251881Speter break; 324251881Speter /* 325251881Speter * type(1) + code(1) + cksum(2) + id(2) seq(2) + 326251881Speter * 3*timestamp(3*4) 327251881Speter */ 328251881Speter case ICMP_TSTAMP : 329251881Speter case ICMP_TSTAMPREPLY : 330251881Speter minicmpsz = 20; 331251881Speter break; 332251881Speter /* 333251881Speter * type(1) + code(1) + cksum(2) + id(2) seq(2) + 334251881Speter * mask(4) 335251881Speter */ 336251881Speter case ICMP_MASKREQ : 337251881Speter case ICMP_MASKREPLY : 338251881Speter minicmpsz = 12; 339251881Speter break; 340251881Speter default : 341251881Speter break; 342251881Speter } 343251881Speter } 344251881Speter 345251881Speter if ((!(plen >= hlen + minicmpsz) && !off) || 346251881Speter (off && off < sizeof(struct icmp))) 347251881Speter fi->fi_fl |= FI_SHORT; 348251881Speter 349251881Speter break; 350251881Speter } 351251881Speter case IPPROTO_TCP : 352251881Speter fi->fi_fl |= FI_TCPUDP; 353251881Speter#ifdef USE_INET6 354251881Speter if (v == 6) { 355251881Speter if (plen < sizeof(struct tcphdr)) 356251881Speter fi->fi_fl |= FI_SHORT; 357251881Speter } else 358251881Speter#endif 359251881Speter if (v == 4) { 360251881Speter if ((!IPMINLEN(ip, tcphdr) && !off) || 361251881Speter (off && off < sizeof(struct tcphdr))) 362251881Speter fi->fi_fl |= FI_SHORT; 363251881Speter } 364251881Speter if (!(fi->fi_fl & FI_SHORT) && !off) 365251881Speter fin->fin_tcpf = tcp->th_flags; 366251881Speter goto getports; 367251881Speter case IPPROTO_UDP : 368251881Speter fi->fi_fl |= FI_TCPUDP; 369251881Speter#ifdef USE_INET6 370251881Speter if (v == 6) { 371251881Speter if (plen < sizeof(struct udphdr)) 372251881Speter fi->fi_fl |= FI_SHORT; 373251881Speter } else 374251881Speter#endif 375251881Speter if (v == 4) { 376251881Speter if ((!IPMINLEN(ip, udphdr) && !off) || 377251881Speter (off && off < sizeof(struct udphdr))) 378251881Speter fi->fi_fl |= FI_SHORT; 379251881Speter } 380251881Spetergetports: 381251881Speter if (!off && (fin->fin_dlen > 3)) { 382251881Speter fin->fin_data[0] = ntohs(tcp->th_sport); 383251881Speter fin->fin_data[1] = ntohs(tcp->th_dport); 384251881Speter } 385251881Speter break; 386251881Speter case IPPROTO_ESP : 387251881Speter#ifdef USE_INET6 388251881Speter if (v == 6) { 389251881Speter if (plen < 8) 390251881Speter fi->fi_fl |= FI_SHORT; 391251881Speter } else 392251881Speter#endif 393251881Speter if (v == 4) { 394251881Speter if (((ip->ip_len < hlen + 8) && !off) || 395251881Speter (off && off < 8)) 396251881Speter fi->fi_fl |= FI_SHORT; 397251881Speter } 398251881Speter break; 399251881Speter default : 400251881Speter break; 401251881Speter } 402251881Speter 403251881Speter#ifdef USE_INET6 404251881Speter if (v == 6) { 405251881Speter fi->fi_optmsk = 0; 406251881Speter fi->fi_secmsk = 0; 407251881Speter fi->fi_auth = 0; 408251881Speter return; 409251881Speter } 410251881Speter#endif 411251881Speter 412251881Speter for (s = (u_char *)(ip + 1), hlen -= (int)sizeof(*ip); hlen > 0; ) { 413251881Speter opt = *s; 414251881Speter if (opt == '\0') 415251881Speter break; 416251881Speter else if (opt == IPOPT_NOP) 417251881Speter ol = 1; 418251881Speter else { 419251881Speter if (hlen < 2) 420251881Speter break; 421251881Speter ol = (int)*(s + 1); 422251881Speter if (ol < 2 || ol > hlen) 423251881Speter break; 424251881Speter } 425251881Speter for (i = 9, mv = 4; mv >= 0; ) { 426251881Speter op = ipopts + i; 427251881Speter if (opt == (u_char)op->ol_val) { 428251881Speter optmsk |= op->ol_bit; 429251881Speter if (opt == IPOPT_SECURITY) { 430251881Speter struct optlist *sp; 431251881Speter u_char sec; 432251881Speter int j, m; 433251881Speter 434251881Speter sec = *(s + 2); /* classification */ 435251881Speter for (j = 3, m = 2; m >= 0; ) { 436251881Speter sp = secopt + j; 437251881Speter if (sec == sp->ol_val) { 438251881Speter secmsk |= sp->ol_bit; 439251881Speter auth = *(s + 3); 440251881Speter auth *= 256; 441251881Speter auth += *(s + 4); 442251881Speter break; 443251881Speter } 444251881Speter if (sec < sp->ol_val) 445251881Speter j -= m--; 446251881Speter else 447251881Speter j += m--; 448251881Speter } 449251881Speter } 450251881Speter break; 451251881Speter } 452251881Speter if (opt < op->ol_val) 453251881Speter i -= mv--; 454251881Speter else 455251881Speter i += mv--; 456251881Speter } 457251881Speter hlen -= ol; 458251881Speter s += ol; 459251881Speter } 460251881Speter if (auth && !(auth & 0x0100)) 461251881Speter auth &= 0xff00; 462251881Speter fi->fi_optmsk = optmsk; 463251881Speter fi->fi_secmsk = secmsk; 464251881Speter fi->fi_auth = auth; 465251881Speter} 466251881Speter 467251881Speter 468251881Speter/* 469251881Speter * check an IP packet for TCP/UDP characteristics such as ports and flags. 470251881Speter */ 471251881Speterint fr_tcpudpchk(ft, fin) 472251881Speterfrtuc_t *ft; 473251881Speterfr_info_t *fin; 474251881Speter{ 475251881Speter register u_short po, tup; 476251881Speter register char i; 477251881Speter register int err = 1; 478251881Speter 479251881Speter /* 480251881Speter * Both ports should *always* be in the first fragment. 481251881Speter * So far, I cannot find any cases where they can not be. 482251881Speter * 483251881Speter * compare destination ports 484251881Speter */ 485251881Speter if ((i = (int)ft->ftu_dcmp)) { 486251881Speter po = ft->ftu_dport; 487251881Speter tup = fin->fin_data[1]; 488251881Speter /* 489251881Speter * Do opposite test to that required and 490251881Speter * continue if that succeeds. 491251881Speter */ 492251881Speter if (!--i && tup != po) /* EQUAL */ 493251881Speter err = 0; 494251881Speter else if (!--i && tup == po) /* NOTEQUAL */ 495251881Speter err = 0; 496251881Speter else if (!--i && tup >= po) /* LESSTHAN */ 497251881Speter err = 0; 498251881Speter else if (!--i && tup <= po) /* GREATERTHAN */ 499251881Speter err = 0; 500251881Speter else if (!--i && tup > po) /* LT or EQ */ 501251881Speter err = 0; 502251881Speter else if (!--i && tup < po) /* GT or EQ */ 503251881Speter err = 0; 504251881Speter else if (!--i && /* Out of range */ 505251881Speter (tup >= po && tup <= ft->ftu_dtop)) 506251881Speter err = 0; 507251881Speter else if (!--i && /* In range */ 508251881Speter (tup <= po || tup >= ft->ftu_dtop)) 509251881Speter err = 0; 510251881Speter } 511251881Speter /* 512251881Speter * compare source ports 513251881Speter */ 514251881Speter if (err && (i = (int)ft->ftu_scmp)) { 515251881Speter po = ft->ftu_sport; 516251881Speter tup = fin->fin_data[0]; 517251881Speter if (!--i && tup != po) 518251881Speter err = 0; 519251881Speter else if (!--i && tup == po) 520251881Speter err = 0; 521251881Speter else if (!--i && tup >= po) 522251881Speter err = 0; 523251881Speter else if (!--i && tup <= po) 524251881Speter err = 0; 525251881Speter else if (!--i && tup > po) 526251881Speter err = 0; 527251881Speter else if (!--i && tup < po) 528251881Speter err = 0; 529251881Speter else if (!--i && /* Out of range */ 530251881Speter (tup >= po && tup <= ft->ftu_stop)) 531251881Speter err = 0; 532251881Speter else if (!--i && /* In range */ 533251881Speter (tup <= po || tup >= ft->ftu_stop)) 534251881Speter err = 0; 535251881Speter } 536251881Speter 537251881Speter /* 538251881Speter * If we don't have all the TCP/UDP header, then how can we 539251881Speter * expect to do any sort of match on it ? If we were looking for 540251881Speter * TCP flags, then NO match. If not, then match (which should 541251881Speter * satisfy the "short" class too). 542251881Speter */ 543251881Speter if (err && (fin->fin_fi.fi_p == IPPROTO_TCP)) { 544251881Speter if (fin->fin_fl & FI_SHORT) 545251881Speter return !(ft->ftu_tcpf | ft->ftu_tcpfm); 546251881Speter /* 547251881Speter * Match the flags ? If not, abort this match. 548251881Speter */ 549251881Speter if (ft->ftu_tcpfm && 550251881Speter ft->ftu_tcpf != (fin->fin_tcpf & ft->ftu_tcpfm)) { 551251881Speter FR_DEBUG(("f. %#x & %#x != %#x\n", fin->fin_tcpf, 552251881Speter ft->ftu_tcpfm, ft->ftu_tcpf)); 553251881Speter err = 0; 554251881Speter } 555251881Speter } 556251881Speter return err; 557251881Speter} 558251881Speter 559251881Speter/* 560251881Speter * Check the input/output list of rules for a match and result. 561251881Speter * Could be per interface, but this gets real nasty when you don't have 562251881Speter * kernel sauce. 563251881Speter */ 564251881Speterint fr_scanlist(passin, ip, fin, m) 565251881Speteru_32_t passin; 566251881Speterip_t *ip; 567251881Speterregister fr_info_t *fin; 568251881Spetervoid *m; 569251881Speter{ 570251881Speter register struct frentry *fr; 571251881Speter register fr_ip_t *fi = &fin->fin_fi; 572251881Speter int rulen, portcmp = 0, off, skip = 0, logged = 0; 573251881Speter u_32_t pass, passt, passl; 574251881Speter frentry_t *frl; 575251881Speter 576251881Speter frl = NULL; 577251881Speter pass = passin; 578251881Speter fr = fin->fin_fr; 579251881Speter fin->fin_fr = NULL; 580251881Speter off = fin->fin_off; 581251881Speter 582251881Speter if ((fi->fi_fl & FI_TCPUDP) && (fin->fin_dlen > 3) && !off) 583251881Speter portcmp = 1; 584251881Speter 585251881Speter for (rulen = 0; fr; fr = fr->fr_next, rulen++) { 586251881Speter if (skip) { 587251881Speter FR_VERBOSE(("%d (%#x)\n", skip, fr->fr_flags)); 588251881Speter skip--; 589251881Speter continue; 590251881Speter } 591251881Speter /* 592251881Speter * In all checks below, a null (zero) value in the 593251881Speter * filter struture is taken to mean a wildcard. 594251881Speter * 595251881Speter * check that we are working for the right interface 596251881Speter */ 597251881Speter#ifdef _KERNEL 598251881Speter# if (BSD >= 199306) 599251881Speter if (fin->fin_out != 0) { 600251881Speter if ((fr->fr_oifa && 601251881Speter (fr->fr_oifa != ((mb_t *)m)->m_pkthdr.rcvif))) 602251881Speter continue; 603251881Speter } 604251881Speter# endif 605251881Speter#else 606251881Speter if (opts & (OPT_VERBOSE|OPT_DEBUG)) 607251881Speter printf("\n"); 608251881Speter#endif 609251881Speter 610251881Speter FR_VERBOSE(("%c", fr->fr_skip ? 's' : 611251881Speter (pass & FR_PASS) ? 'p' : 612251881Speter (pass & FR_AUTH) ? 'a' : 613251881Speter (pass & FR_ACCOUNT) ? 'A' : 614251881Speter (pass & FR_NOMATCH) ? 'n' : 'b')); 615251881Speter 616251881Speter if (fr->fr_ifa && fr->fr_ifa != fin->fin_ifp) 617251881Speter continue; 618251881Speter 619251881Speter FR_VERBOSE((":i")); 620251881Speter { 621251881Speter register u_32_t *ld, *lm, *lip; 622251881Speter register int i; 623251881Speter 624251881Speter lip = (u_32_t *)fi; 625251881Speter lm = (u_32_t *)&fr->fr_mip; 626251881Speter ld = (u_32_t *)&fr->fr_ip; 627251881Speter i = ((*lip & *lm) != *ld); 628251881Speter FR_DEBUG(("0. %#08x & %#08x != %#08x\n", 629251881Speter *lip, *lm, *ld)); 630251881Speter if (i) 631251881Speter continue; 632251881Speter /* 633251881Speter * We now know whether the packet version and the 634251881Speter * rule version match, along with protocol, ttl and 635251881Speter * tos. 636251881Speter */ 637251881Speter lip++, lm++, ld++; 638251881Speter /* 639251881Speter * Unrolled loops (4 each, for 32 bits). 640251881Speter */ 641251881Speter FR_DEBUG(("1a. %#08x & %#08x != %#08x\n", 642251881Speter *lip, *lm, *ld)); 643251881Speter i |= ((*lip++ & *lm++) != *ld++) << 5; 644251881Speter if (fi->fi_v == 6) { 645251881Speter FR_DEBUG(("1b. %#08x & %#08x != %#08x\n", 646251881Speter *lip, *lm, *ld)); 647251881Speter i |= ((*lip++ & *lm++) != *ld++) << 5; 648251881Speter FR_DEBUG(("1c. %#08x & %#08x != %#08x\n", 649251881Speter *lip, *lm, *ld)); 650251881Speter i |= ((*lip++ & *lm++) != *ld++) << 5; 651251881Speter FR_DEBUG(("1d. %#08x & %#08x != %#08x\n", 652251881Speter *lip, *lm, *ld)); 653251881Speter i |= ((*lip++ & *lm++) != *ld++) << 5; 654251881Speter } else { 655251881Speter lip += 3; 656251881Speter lm += 3; 657251881Speter ld += 3; 658251881Speter } 659251881Speter i ^= (fr->fr_flags & FR_NOTSRCIP); 660251881Speter if (i) 661251881Speter continue; 662251881Speter FR_DEBUG(("2a. %#08x & %#08x != %#08x\n", 663251881Speter *lip, *lm, *ld)); 664251881Speter i |= ((*lip++ & *lm++) != *ld++) << 6; 665251881Speter if (fi->fi_v == 6) { 666251881Speter FR_DEBUG(("2b. %#08x & %#08x != %#08x\n", 667251881Speter *lip, *lm, *ld)); 668251881Speter i |= ((*lip++ & *lm++) != *ld++) << 6; 669251881Speter FR_DEBUG(("2c. %#08x & %#08x != %#08x\n", 670251881Speter *lip, *lm, *ld)); 671251881Speter i |= ((*lip++ & *lm++) != *ld++) << 6; 672251881Speter FR_DEBUG(("2d. %#08x & %#08x != %#08x\n", 673251881Speter *lip, *lm, *ld)); 674251881Speter i |= ((*lip++ & *lm++) != *ld++) << 6; 675251881Speter } else { 676251881Speter lip += 3; 677251881Speter lm += 3; 678251881Speter ld += 3; 679251881Speter } 680251881Speter i ^= (fr->fr_flags & FR_NOTDSTIP); 681251881Speter if (i) 682251881Speter continue; 683251881Speter FR_DEBUG(("3. %#08x & %#08x != %#08x\n", 684251881Speter *lip, *lm, *ld)); 685251881Speter i |= ((*lip++ & *lm++) != *ld++); 686251881Speter FR_DEBUG(("4. %#08x & %#08x != %#08x\n", 687251881Speter *lip, *lm, *ld)); 688251881Speter i |= ((*lip & *lm) != *ld); 689251881Speter if (i) 690251881Speter continue; 691251881Speter } 692251881Speter 693251881Speter /* 694251881Speter * If a fragment, then only the first has what we're looking 695251881Speter * for here... 696251881Speter */ 697251881Speter if (!portcmp && (fr->fr_dcmp || fr->fr_scmp || fr->fr_tcpf || 698251881Speter fr->fr_tcpfm)) 699251881Speter continue; 700251881Speter if (fi->fi_fl & FI_TCPUDP) { 701251881Speter if (!fr_tcpudpchk(&fr->fr_tuc, fin)) 702251881Speter continue; 703251881Speter } else if (fr->fr_icmpm || fr->fr_icmp) { 704251881Speter if (((fi->fi_p != IPPROTO_ICMP) && 705251881Speter (fi->fi_p != IPPROTO_ICMPV6)) || off || 706251881Speter (fin->fin_dlen < 2)) 707251881Speter continue; 708251881Speter if ((fin->fin_data[0] & fr->fr_icmpm) != fr->fr_icmp) { 709251881Speter FR_DEBUG(("i. %#x & %#x != %#x\n", 710251881Speter fin->fin_data[0], fr->fr_icmpm, 711251881Speter fr->fr_icmp)); 712251881Speter continue; 713251881Speter } 714251881Speter } 715251881Speter FR_VERBOSE(("*")); 716251881Speter 717251881Speter if (fr->fr_flags & FR_NOMATCH) { 718251881Speter passt = passl; 719251881Speter passl = passin; 720251881Speter fin->fin_fr = frl; 721251881Speter frl = NULL; 722251881Speter if (fr->fr_flags & FR_QUICK) 723251881Speter break; 724251881Speter continue; 725251881Speter } 726251881Speter 727251881Speter passl = passt; 728251881Speter passt = fr->fr_flags; 729251881Speter frl = fin->fin_fr; 730251881Speter fin->fin_fr = fr; 731251881Speter#if (BSD >= 199306) && (defined(_KERNEL) || defined(KERNEL)) 732251881Speter if (securelevel <= 0) 733251881Speter#endif 734251881Speter if ((passt & FR_CALLNOW) && fr->fr_func) 735251881Speter passt = (*fr->fr_func)(passt, ip, fin); 736251881Speter#ifdef IPFILTER_LOG 737251881Speter /* 738251881Speter * Just log this packet... 739251881Speter */ 740251881Speter if ((passt & FR_LOGMASK) == FR_LOG) { 741251881Speter if (!IPLLOG(passt, ip, fin, m)) { 742251881Speter if (passt & FR_LOGORBLOCK) 743251881Speter passt |= FR_BLOCK|FR_QUICK; 744251881Speter ATOMIC_INCL(frstats[fin->fin_out].fr_skip); 745251881Speter } 746251881Speter ATOMIC_INCL(frstats[fin->fin_out].fr_pkl); 747251881Speter logged = 1; 748251881Speter } 749251881Speter#endif /* IPFILTER_LOG */ 750251881Speter ATOMIC_INCL(fr->fr_hits); 751251881Speter if (passt & FR_ACCOUNT) 752251881Speter fr->fr_bytes += (U_QUAD_T)ip->ip_len; 753251881Speter else 754251881Speter fin->fin_icode = fr->fr_icode; 755251881Speter fin->fin_rule = rulen; 756251881Speter fin->fin_group = fr->fr_group; 757251881Speter if (fr->fr_grp != NULL) { 758251881Speter fin->fin_fr = fr->fr_grp; 759251881Speter passt = fr_scanlist(passt, ip, fin, m); 760251881Speter if (fin->fin_fr == NULL) { 761251881Speter fin->fin_rule = rulen; 762251881Speter fin->fin_group = fr->fr_group; 763251881Speter fin->fin_fr = fr; 764251881Speter } 765251881Speter if (passt & FR_DONTCACHE) 766251881Speter logged = 1; 767251881Speter } 768251881Speter if (!(skip = fr->fr_skip) && (passt & FR_LOGMASK) != FR_LOG) 769251881Speter pass = passt; 770251881Speter FR_DEBUG(("pass %#x\n", pass)); 771251881Speter if (passt & FR_QUICK) 772251881Speter break; 773251881Speter } 774251881Speter if (logged) 775251881Speter pass |= FR_DONTCACHE; 776251881Speter pass |= (fi->fi_fl << 24); 777251881Speter return pass; 778251881Speter} 779251881Speter 780251881Speter 781251881Speter/* 782251881Speter * frcheck - filter check 783251881Speter * check using source and destination addresses/ports in a packet whether 784251881Speter * or not to pass it on or not. 785251881Speter */ 786251881Speterint fr_check(ip, hlen, ifp, out 787251881Speter#if defined(_KERNEL) && SOLARIS 788251881Speter, qif, mp) 789251881Speterqif_t *qif; 790251881Speter#else 791251881Speter, mp) 792251881Speter#endif 793251881Spetermb_t **mp; 794251881Speterip_t *ip; 795251881Speterint hlen; 796251881Spetervoid *ifp; 797251881Speterint out; 798251881Speter{ 799251881Speter /* 800251881Speter * The above really sucks, but short of writing a diff 801251881Speter */ 802251881Speter fr_info_t frinfo, *fc; 803251881Speter register fr_info_t *fin = &frinfo; 804251881Speter int changed, error = EHOSTUNREACH, v = ip->ip_v; 805251881Speter frentry_t *fr = NULL, *list; 806251881Speter u_32_t pass, apass; 807251881Speter#if !SOLARIS || !defined(_KERNEL) 808251881Speter register mb_t *m = *mp; 809251881Speter#endif 810251881Speter 811251881Speter#ifdef _KERNEL 812251881Speter int p, len, drop = 0, logit = 0; 813251881Speter mb_t *mc = NULL; 814251881Speter# if !defined(__SVR4) && !defined(__svr4__) 815251881Speter# ifdef __sgi 816251881Speter char hbuf[128]; 817251881Speter# endif 818251881Speter int up; 819251881Speter 820251881Speter# if !SOLARIS && !defined(NETBSD_PF) && \ 821251881Speter ((defined(__FreeBSD__) && (__FreeBSD_version < 500011)) || \ 822251881Speter defined(__OpenBSD__) || defined(_BSDI_VERSION)) 823251881Speter if (fr_checkp != fr_check && fr_running > 0) { 824251881Speter static int counter = 0; 825251881Speter 826251881Speter if (counter == 0) { 827251881Speter printf("WARNING: fr_checkp corrupt: value %lx\n", 828251881Speter (u_long)fr_checkp); 829251881Speter printf("WARNING: fr_checkp should be %lx\n", 830251881Speter (u_long)fr_check); 831251881Speter printf("WARNING: fixing fr_checkp\n"); 832251881Speter } 833251881Speter fr_checkp = fr_check; 834251881Speter counter++; 835251881Speter if (counter == 10000) 836251881Speter counter = 0; 837251881Speter } 838251881Speter# endif 839251881Speter 840251881Speter# ifdef M_CANFASTFWD 841251881Speter /* 842251881Speter * XXX For now, IP Filter and fast-forwarding of cached flows 843251881Speter * XXX are mutually exclusive. Eventually, IP Filter should 844251881Speter * XXX get a "can-fast-forward" filter rule. 845251881Speter */ 846251881Speter m->m_flags &= ~M_CANFASTFWD; 847251881Speter# endif /* M_CANFASTFWD */ 848251881Speter# ifdef CSUM_DELAY_DATA 849251881Speter /* 850251881Speter * disable delayed checksums. 851251881Speter */ 852251881Speter if ((out != 0) && (m->m_pkthdr.csum_flags & CSUM_DELAY_DATA)) { 853251881Speter in_delayed_cksum(m); 854251881Speter m->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA; 855251881Speter } 856251881Speter# endif /* CSUM_DELAY_DATA */ 857251881Speter 858251881Speter# ifdef USE_INET6 859251881Speter if (v == 6) { 860251881Speter len = ntohs(((ip6_t*)ip)->ip6_plen); 861251881Speter if (!len) 862251881Speter return -1; /* potential jumbo gram */ 863251881Speter len += sizeof(ip6_t); 864251881Speter p = ((ip6_t *)ip)->ip6_nxt; 865251881Speter } else 866251881Speter# endif 867251881Speter { 868251881Speter p = ip->ip_p; 869251881Speter len = ip->ip_len; 870251881Speter } 871251881Speter 872251881Speter if ((p == IPPROTO_TCP || p == IPPROTO_UDP || 873251881Speter (v == 4 && p == IPPROTO_ICMP) 874251881Speter# ifdef USE_INET6 875251881Speter || (v == 6 && p == IPPROTO_ICMPV6) 876251881Speter# endif 877251881Speter )) { 878251881Speter int plen = 0; 879251881Speter 880251881Speter if ((v == 6) || (ip->ip_off & IP_OFFMASK) == 0) 881251881Speter switch(p) 882251881Speter { 883251881Speter case IPPROTO_TCP: 884251881Speter plen = sizeof(tcphdr_t); 885251881Speter break; 886251881Speter case IPPROTO_UDP: 887251881Speter plen = sizeof(udphdr_t); 888251881Speter break; 889251881Speter /* 96 - enough for complete ICMP error IP header */ 890251881Speter case IPPROTO_ICMP: 891251881Speter plen = ICMPERR_MAXPKTLEN - sizeof(ip_t); 892251881Speter break; 893251881Speter case IPPROTO_ESP: 894251881Speter plen = 8; 895251881Speter break; 896251881Speter# ifdef USE_INET6 897251881Speter case IPPROTO_ICMPV6 : 898251881Speter /* 899251881Speter * XXX does not take intermediate header 900251881Speter * into account 901251881Speter */ 902251881Speter plen = ICMP6ERR_MINPKTLEN + 8 - sizeof(ip6_t); 903251881Speter break; 904251881Speter# endif 905251881Speter } 906251881Speter up = MIN(hlen + plen, len); 907251881Speter 908251881Speter if (up > m->m_len) { 909251881Speter# ifdef __sgi 910251881Speter /* Under IRIX, avoid m_pullup as it makes ping <hostname> panic */ 911251881Speter if ((up > sizeof(hbuf)) || (m_length(m) < up)) { 912251881Speter ATOMIC_INCL(frstats[out].fr_pull[1]); 913251881Speter return -1; 914251881Speter } 915251881Speter m_copydata(m, 0, up, hbuf); 916251881Speter ATOMIC_INCL(frstats[out].fr_pull[0]); 917251881Speter ip = (ip_t *)hbuf; 918251881Speter# else /* __ sgi */ 919251881Speter# ifndef linux 920251881Speter if ((*mp = m_pullup(m, up)) == 0) { 921251881Speter ATOMIC_INCL(frstats[out].fr_pull[1]); 922251881Speter return -1; 923251881Speter } else { 924251881Speter ATOMIC_INCL(frstats[out].fr_pull[0]); 925251881Speter m = *mp; 926251881Speter ip = mtod(m, ip_t *); 927251881Speter } 928251881Speter# endif /* !linux */ 929251881Speter# endif /* __sgi */ 930251881Speter } else 931251881Speter up = 0; 932251881Speter } else 933251881Speter up = 0; 934251881Speter# endif /* !defined(__SVR4) && !defined(__svr4__) */ 935251881Speter# if SOLARIS 936251881Speter mb_t *m = qif->qf_m; 937251881Speter 938251881Speter if ((u_int)ip & 0x3) 939251881Speter return 2; 940251881Speter fin->fin_qfm = m; 941251881Speter fin->fin_qif = qif; 942251881Speter# endif 943251881Speter#endif /* _KERNEL */ 944251881Speter 945251881Speter#ifndef __FreeBSD__ 946251881Speter /* 947251881Speter * Be careful here: ip_id is in network byte order when called 948251881Speter * from ip_output() 949251881Speter */ 950251881Speter if ((out) && (v == 4)) 951251881Speter ip->ip_id = ntohs(ip->ip_id); 952251881Speter#endif 953251881Speter 954251881Speter changed = 0; 955251881Speter fin->fin_ifp = ifp; 956251881Speter fin->fin_v = v; 957251881Speter fin->fin_out = out; 958251881Speter fin->fin_mp = mp; 959251881Speter fr_makefrip(hlen, ip, fin); 960251881Speter 961251881Speter#ifdef _KERNEL 962251881Speter# ifdef USE_INET6 963251881Speter if (v == 6) { 964251881Speter ATOMIC_INCL(frstats[0].fr_ipv6[out]); 965251881Speter if (((ip6_t *)ip)->ip6_hlim < fr_minttl) { 966251881Speter ATOMIC_INCL(frstats[0].fr_badttl); 967251881Speter if (fr_minttllog & 1) 968251881Speter logit = -3; 969251881Speter if (fr_minttllog & 2) 970251881Speter drop = 1; 971251881Speter } 972251881Speter } else 973251881Speter# endif 974251881Speter if (!out) { 975251881Speter if (fr_chksrc && !fr_verifysrc(ip->ip_src, ifp)) { 976251881Speter ATOMIC_INCL(frstats[0].fr_badsrc); 977251881Speter if (fr_chksrc & 1) 978251881Speter drop = 1; 979251881Speter if (fr_chksrc & 2) 980251881Speter logit = -2; 981251881Speter } else if (ip->ip_ttl < fr_minttl) { 982251881Speter ATOMIC_INCL(frstats[0].fr_badttl); 983251881Speter if (fr_minttllog & 1) 984251881Speter logit = -3; 985251881Speter if (fr_minttllog & 2) 986251881Speter drop = 1; 987251881Speter } 988251881Speter } 989251881Speter if (drop) { 990251881Speter# ifdef IPFILTER_LOG 991251881Speter if (logit) { 992251881Speter fin->fin_group = logit; 993251881Speter pass = FR_INQUE|FR_NOMATCH|FR_LOGB; 994251881Speter (void) IPLLOG(pass, ip, fin, m); 995251881Speter } 996251881Speter# endif 997251881Speter# if !SOLARIS 998251881Speter m_freem(m); 999251881Speter# endif 1000251881Speter return error; 1001251881Speter } 1002251881Speter#endif 1003251881Speter pass = fr_pass; 1004251881Speter if (fin->fin_fl & FI_SHORT) { 1005251881Speter ATOMIC_INCL(frstats[out].fr_short); 1006251881Speter } 1007251881Speter 1008251881Speter READ_ENTER(&ipf_mutex); 1009251881Speter 1010251881Speter /* 1011251881Speter * Check auth now. This, combined with the check below to see if apass 1012251881Speter * is 0 is to ensure that we don't count the packet twice, which can 1013251881Speter * otherwise occur when we reprocess it. As it is, we only count it 1014251881Speter * after it has no auth. table matchup. This also stops NAT from 1015251881Speter * occuring until after the packet has been auth'd. 1016251881Speter */ 1017251881Speter apass = fr_checkauth(ip, fin); 1018251881Speter 1019251881Speter if (!out) { 1020251881Speter#ifdef USE_INET6 1021251881Speter if (v == 6) 1022251881Speter list = ipacct6[0][fr_active]; 1023251881Speter else 1024251881Speter#endif 1025251881Speter list = ipacct[0][fr_active]; 1026251881Speter changed = ip_natin(ip, fin); 1027251881Speter if (!apass && (fin->fin_fr = list) && 1028251881Speter (fr_scanlist(FR_NOMATCH, ip, fin, m) & FR_ACCOUNT)) { 1029251881Speter ATOMIC_INCL(frstats[0].fr_acct); 1030251881Speter } 1031251881Speter } 1032251881Speter 1033251881Speter if (!apass) { 1034251881Speter if ((fin->fin_fl & FI_FRAG) == FI_FRAG) 1035251881Speter fr = ipfr_knownfrag(ip, fin); 1036251881Speter if (!fr && !(fin->fin_fl & FI_SHORT)) 1037251881Speter fr = fr_checkstate(ip, fin); 1038251881Speter if (fr != NULL) 1039251881Speter pass = fr->fr_flags; 1040251881Speter if (fr && (pass & FR_LOGFIRST)) 1041251881Speter pass &= ~(FR_LOGFIRST|FR_LOG); 1042251881Speter } 1043251881Speter 1044251881Speter if (apass || !fr) { 1045251881Speter /* 1046251881Speter * If a packet is found in the auth table, then skip checking 1047251881Speter * the access lists for permission but we do need to consider 1048251881Speter * the result as if it were from the ACL's. 1049251881Speter */ 1050251881Speter if (!apass) { 1051251881Speter fc = frcache + out; 1052251881Speter if (!bcmp((char *)fin, (char *)fc, FI_CSIZE)) { 1053251881Speter /* 1054251881Speter * copy cached data so we can unlock the mutex 1055251881Speter * earlier. 1056251881Speter */ 1057251881Speter bcopy((char *)fc, (char *)fin, FI_COPYSIZE); 1058251881Speter ATOMIC_INCL(frstats[out].fr_chit); 1059251881Speter if ((fr = fin->fin_fr)) { 1060251881Speter ATOMIC_INCL(fr->fr_hits); 1061251881Speter pass = fr->fr_flags; 1062251881Speter } 1063251881Speter } else { 1064251881Speter#ifdef USE_INET6 1065251881Speter if (v == 6) 1066251881Speter list = ipfilter6[out][fr_active]; 1067251881Speter else 1068251881Speter#endif 1069251881Speter list = ipfilter[out][fr_active]; 1070251881Speter if ((fin->fin_fr = list)) 1071251881Speter pass = fr_scanlist(fr_pass, ip, fin, m); 1072251881Speter if (!(pass & (FR_KEEPSTATE|FR_DONTCACHE))) 1073251881Speter bcopy((char *)fin, (char *)fc, 1074251881Speter FI_COPYSIZE); 1075251881Speter if (pass & FR_NOMATCH) { 1076251881Speter ATOMIC_INCL(frstats[out].fr_nom); 1077251881Speter fin->fin_fr = NULL; 1078251881Speter } 1079251881Speter } 1080251881Speter } else 1081251881Speter pass = apass; 1082251881Speter fr = fin->fin_fr; 1083251881Speter 1084251881Speter /* 1085251881Speter * If we fail to add a packet to the authorization queue, 1086251881Speter * then we drop the packet later. However, if it was added 1087251881Speter * then pretend we've dropped it already. 1088251881Speter */ 1089251881Speter if ((pass & FR_AUTH)) { 1090251881Speter if (fr_newauth((mb_t *)m, fin, ip) != 0) { 1091251881Speter m = *mp = NULL; 1092251881Speter error = 0; 1093251881Speter } else 1094251881Speter error = ENOSPC; 1095251881Speter } 1096251881Speter 1097251881Speter if (pass & FR_PREAUTH) { 1098251881Speter READ_ENTER(&ipf_auth); 1099251881Speter if ((fin->fin_fr = ipauth) && 1100251881Speter (pass = fr_scanlist(0, ip, fin, m))) { 1101251881Speter ATOMIC_INCL(fr_authstats.fas_hits); 1102251881Speter } else { 1103251881Speter ATOMIC_INCL(fr_authstats.fas_miss); 1104251881Speter } 1105251881Speter RWLOCK_EXIT(&ipf_auth); 1106251881Speter } 1107251881Speter 1108251881Speter fin->fin_fr = fr; 1109251881Speter if ((pass & (FR_KEEPFRAG|FR_KEEPSTATE)) == FR_KEEPFRAG) { 1110251881Speter if (fin->fin_fl & FI_FRAG) { 1111251881Speter if (ipfr_newfrag(ip, fin) == -1) { 1112251881Speter ATOMIC_INCL(frstats[out].fr_bnfr); 1113251881Speter } else { 1114251881Speter ATOMIC_INCL(frstats[out].fr_nfr); 1115251881Speter } 1116251881Speter } else { 1117251881Speter ATOMIC_INCL(frstats[out].fr_cfr); 1118251881Speter } 1119251881Speter } 1120251881Speter if (pass & FR_KEEPSTATE) { 1121251881Speter if (fr_addstate(ip, fin, NULL, 0) == NULL) { 1122251881Speter ATOMIC_INCL(frstats[out].fr_bads); 1123251881Speter } else { 1124251881Speter ATOMIC_INCL(frstats[out].fr_ads); 1125251881Speter } 1126251881Speter } 1127251881Speter } else if (fr != NULL) { 1128251881Speter pass = fr->fr_flags; 1129251881Speter if (pass & FR_LOGFIRST) 1130251881Speter pass &= ~(FR_LOGFIRST|FR_LOG); 1131251881Speter } 1132251881Speter 1133251881Speter#if (BSD >= 199306) && (defined(_KERNEL) || defined(KERNEL)) 1134251881Speter if (securelevel <= 0) 1135251881Speter#endif 1136251881Speter if (fr && fr->fr_func && !(pass & FR_CALLNOW)) 1137251881Speter pass = (*fr->fr_func)(pass, ip, fin); 1138251881Speter 1139251881Speter /* 1140251881Speter * Only count/translate packets which will be passed on, out the 1141251881Speter * interface. 1142251881Speter */ 1143251881Speter if (out && (pass & FR_PASS)) { 1144251881Speter#ifdef USE_INET6 1145251881Speter if (v == 6) 1146251881Speter list = ipacct6[1][fr_active]; 1147251881Speter else 1148251881Speter#endif 1149251881Speter list = ipacct[1][fr_active]; 1150251881Speter if (list != NULL) { 1151251881Speter u_32_t sg, sr; 1152251881Speter 1153251881Speter fin->fin_fr = list; 1154251881Speter sg = fin->fin_group; 1155251881Speter sr = fin->fin_rule; 1156251881Speter if (fr_scanlist(FR_NOMATCH, ip, fin, m) & FR_ACCOUNT) { 1157251881Speter ATOMIC_INCL(frstats[1].fr_acct); 1158251881Speter } 1159251881Speter fin->fin_group = sg; 1160251881Speter fin->fin_rule = sr; 1161251881Speter fin->fin_fr = fr; 1162251881Speter } 1163251881Speter changed = ip_natout(ip, fin); 1164251881Speter } else 1165251881Speter fin->fin_fr = fr; 1166251881Speter RWLOCK_EXIT(&ipf_mutex); 1167251881Speter 1168251881Speter#ifdef IPFILTER_LOG 1169251881Speter if ((fr_flags & FF_LOGGING) || (pass & FR_LOGMASK)) { 1170251881Speter if ((fr_flags & FF_LOGNOMATCH) && (pass & FR_NOMATCH)) { 1171251881Speter pass |= FF_LOGNOMATCH; 1172251881Speter ATOMIC_INCL(frstats[out].fr_npkl); 1173251881Speter goto logit; 1174251881Speter } else if (((pass & FR_LOGMASK) == FR_LOGP) || 1175251881Speter ((pass & FR_PASS) && (fr_flags & FF_LOGPASS))) { 1176251881Speter if ((pass & FR_LOGMASK) != FR_LOGP) 1177251881Speter pass |= FF_LOGPASS; 1178251881Speter ATOMIC_INCL(frstats[out].fr_ppkl); 1179251881Speter goto logit; 1180251881Speter } else if (((pass & FR_LOGMASK) == FR_LOGB) || 1181251881Speter ((pass & FR_BLOCK) && (fr_flags & FF_LOGBLOCK))) { 1182251881Speter if ((pass & FR_LOGMASK) != FR_LOGB) 1183251881Speter pass |= FF_LOGBLOCK; 1184251881Speter ATOMIC_INCL(frstats[out].fr_bpkl); 1185251881Speterlogit: 1186251881Speter if (!IPLLOG(pass, ip, fin, m)) { 1187251881Speter ATOMIC_INCL(frstats[out].fr_skip); 1188251881Speter if ((pass & (FR_PASS|FR_LOGORBLOCK)) == 1189251881Speter (FR_PASS|FR_LOGORBLOCK)) 1190251881Speter pass ^= FR_PASS|FR_BLOCK; 1191251881Speter } 1192251881Speter } 1193251881Speter } 1194251881Speter#endif /* IPFILTER_LOG */ 1195251881Speter 1196251881Speter#ifndef __FreeBSD__ 1197251881Speter if ((out) && (v == 4)) 1198251881Speter ip->ip_id = htons(ip->ip_id); 1199251881Speter#endif 1200251881Speter 1201251881Speter#ifdef _KERNEL 1202251881Speter /* 1203251881Speter * Only allow FR_DUP to work if a rule matched - it makes no sense to 1204251881Speter * set FR_DUP as a "default" as there are no instructions about where 1205251881Speter * to send the packet. 1206251881Speter */ 1207251881Speter if (fr && (pass & FR_DUP)) 1208251881Speter# if SOLARIS 1209251881Speter mc = dupmsg(m); 1210251881Speter# else 1211251881Speter# if defined(__OpenBSD__) && (OpenBSD >= 199905) 1212251881Speter mc = m_copym2(m, 0, M_COPYALL, M_DONTWAIT); 1213251881Speter# else 1214251881Speter mc = m_copy(m, 0, M_COPYALL); 1215251881Speter# endif 1216251881Speter# endif 1217251881Speter#endif 1218251881Speter if (pass & FR_PASS) { 1219251881Speter ATOMIC_INCL(frstats[out].fr_pass); 1220251881Speter } else if (pass & FR_BLOCK) { 1221251881Speter ATOMIC_INCL(frstats[out].fr_block); 1222251881Speter /* 1223251881Speter * Should we return an ICMP packet to indicate error 1224251881Speter * status passing through the packet filter ? 1225251881Speter * WARNING: ICMP error packets AND TCP RST packets should 1226251881Speter * ONLY be sent in repsonse to incoming packets. Sending them 1227251881Speter * in response to outbound packets can result in a panic on 1228251881Speter * some operating systems. 1229251881Speter */ 1230251881Speter if (!out) { 1231251881Speter if (changed == -1) 1232251881Speter /* 1233251881Speter * If a packet results in a NAT error, do not 1234251881Speter * send a reset or ICMP error as it may disrupt 1235251881Speter * an existing flow. This is the proxy saying 1236251881Speter * the content is bad so just drop the packet 1237251881Speter * silently. 1238251881Speter */ 1239251881Speter ; 1240251881Speter else if (pass & FR_RETICMP) { 1241251881Speter int dst; 1242251881Speter 1243251881Speter if ((pass & FR_RETMASK) == FR_FAKEICMP) 1244251881Speter dst = 1; 1245251881Speter else 1246251881Speter dst = 0; 1247251881Speter send_icmp_err(ip, ICMP_UNREACH, fin, dst); 1248251881Speter ATOMIC_INCL(frstats[0].fr_ret); 1249251881Speter } else if (((pass & FR_RETMASK) == FR_RETRST) && 1250251881Speter !(fin->fin_fl & FI_SHORT)) { 1251251881Speter if (send_reset(ip, fin) == 0) { 1252251881Speter ATOMIC_INCL(frstats[1].fr_ret); 1253251881Speter } 1254251881Speter } 1255251881Speter } else { 1256251881Speter if (pass & FR_RETRST) 1257251881Speter error = ECONNRESET; 1258251881Speter } 1259251881Speter } 1260251881Speter 1261251881Speter /* 1262251881Speter * If we didn't drop off the bottom of the list of rules (and thus 1263251881Speter * the 'current' rule fr is not NULL), then we may have some extra 1264251881Speter * instructions about what to do with a packet. 1265251881Speter * Once we're finished return to our caller, freeing the packet if 1266251881Speter * we are dropping it (* BSD ONLY *). 1267251881Speter */ 1268251881Speter if ((changed == -1) && (pass & FR_PASS)) { 1269251881Speter pass &= ~FR_PASS; 1270251881Speter pass |= FR_BLOCK; 1271251881Speter } 1272251881Speter#if defined(_KERNEL) 1273251881Speter# if !SOLARIS 1274251881Speter# if !defined(linux) 1275251881Speter if (fr) { 1276251881Speter frdest_t *fdp = &fr->fr_tif; 1277251881Speter 1278251881Speter if (((pass & FR_FASTROUTE) && !out) || 1279251881Speter (fdp->fd_ifp && fdp->fd_ifp != (struct ifnet *)-1)) { 1280251881Speter (void) ipfr_fastroute(m, mp, fin, fdp); 1281251881Speter m = *mp; 1282251881Speter } 1283251881Speter 1284251881Speter if (mc != NULL) 1285251881Speter (void) ipfr_fastroute(mc, &mc, fin, &fr->fr_dif); 1286251881Speter } 1287251881Speter 1288251881Speter if (!(pass & FR_PASS) && m) { 1289251881Speter m_freem(m); 1290251881Speter m = *mp = NULL; 1291251881Speter } 1292251881Speter# ifdef __sgi 1293251881Speter else if (changed && up && m) 1294251881Speter m_copyback(m, 0, up, hbuf); 1295251881Speter# endif 1296251881Speter# endif /* !linux */ 1297251881Speter# else /* !SOLARIS */ 1298251881Speter if (fr) { 1299251881Speter frdest_t *fdp = &fr->fr_tif; 1300251881Speter 1301251881Speter if (((pass & FR_FASTROUTE) && !out) || 1302251881Speter (fdp->fd_ifp && fdp->fd_ifp != (struct ifnet *)-1)) 1303251881Speter (void) ipfr_fastroute(ip, m, mp, fin, fdp); 1304251881Speter 1305251881Speter if (mc != NULL) 1306251881Speter (void) ipfr_fastroute(ip, mc, &mc, fin, &fr->fr_dif); 1307251881Speter } 1308251881Speter# endif /* !SOLARIS */ 1309251881Speter return (pass & FR_PASS) ? 0 : error; 1310251881Speter#else /* _KERNEL */ 1311251881Speter if (pass & FR_NOMATCH) 1312251881Speter return 1; 1313251881Speter if (pass & FR_PASS) 1314251881Speter return 0; 1315251881Speter if (pass & FR_AUTH) 1316251881Speter return -2; 1317251881Speter if ((pass & FR_RETMASK) == FR_RETRST) 1318251881Speter return -3; 1319251881Speter if ((pass & FR_RETMASK) == FR_RETICMP) 1320251881Speter return -4; 1321251881Speter if ((pass & FR_RETMASK) == FR_FAKEICMP) 1322251881Speter return -5; 1323251881Speter return -1; 1324251881Speter#endif /* _KERNEL */ 1325251881Speter} 1326251881Speter 1327251881Speter 1328251881Speter/* 1329251881Speter * ipf_cksum 1330251881Speter * addr should be 16bit aligned and len is in bytes. 1331251881Speter * length is in bytes 1332251881Speter */ 1333251881Speteru_short ipf_cksum(addr, len) 1334251881Speterregister u_short *addr; 1335251881Speterregister int len; 1336251881Speter{ 1337251881Speter register u_32_t sum = 0; 1338251881Speter 1339251881Speter for (sum = 0; len > 1; len -= 2) 1340251881Speter sum += *addr++; 1341251881Speter 1342251881Speter /* mop up an odd byte, if necessary */ 1343251881Speter if (len == 1) 1344251881Speter sum += *(u_char *)addr; 1345251881Speter 1346251881Speter /* 1347251881Speter * add back carry outs from top 16 bits to low 16 bits 1348251881Speter */ 1349251881Speter sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */ 1350251881Speter sum += (sum >> 16); /* add carry */ 1351251881Speter return (u_short)(~sum); 1352251881Speter} 1353251881Speter 1354251881Speter 1355251881Speter/* 1356251881Speter * NB: This function assumes we've pullup'd enough for all of the IP header 1357251881Speter * and the TCP header. We also assume that data blocks aren't allocated in 1358251881Speter * odd sizes. 1359251881Speter */ 1360251881Speteru_short fr_tcpsum(m, ip, tcp) 1361251881Spetermb_t *m; 1362251881Speterip_t *ip; 1363251881Spetertcphdr_t *tcp; 1364251881Speter{ 1365251881Speter u_short *sp, slen, ts; 1366251881Speter u_int sum, sum2; 1367251881Speter int hlen; 1368251881Speter 1369251881Speter /* 1370251881Speter * Add up IP Header portion 1371251881Speter */ 1372251881Speter hlen = ip->ip_hl << 2; 1373251881Speter slen = ip->ip_len - hlen; 1374251881Speter sum = htons((u_short)ip->ip_p); 1375251881Speter sum += htons(slen); 1376251881Speter sp = (u_short *)&ip->ip_src; 1377251881Speter sum += *sp++; /* ip_src */ 1378251881Speter sum += *sp++; 1379251881Speter sum += *sp++; /* ip_dst */ 1380251881Speter sum += *sp++; 1381251881Speter ts = tcp->th_sum; 1382251881Speter tcp->th_sum = 0; 1383251881Speter#ifdef KERNEL 1384251881Speter# if SOLARIS 1385251881Speter sum2 = ip_cksum(m, hlen, sum); /* hlen == offset */ 1386251881Speter sum2 = (sum2 & 0xffff) + (sum2 >> 16); 1387251881Speter sum2 = ~sum2 & 0xffff; 1388251881Speter# else /* SOLARIS */ 1389251881Speter# if defined(BSD) || defined(sun) 1390251881Speter# if BSD >= 199306 1391251881Speter m->m_data += hlen; 1392251881Speter# else 1393251881Speter m->m_off += hlen; 1394251881Speter# endif 1395251881Speter m->m_len -= hlen; 1396251881Speter sum2 = in_cksum(m, slen); 1397251881Speter m->m_len += hlen; 1398251881Speter# if BSD >= 199306 1399251881Speter m->m_data -= hlen; 1400251881Speter# else 1401251881Speter m->m_off -= hlen; 1402251881Speter# endif 1403251881Speter /* 1404251881Speter * Both sum and sum2 are partial sums, so combine them together. 1405251881Speter */ 1406251881Speter sum = (sum & 0xffff) + (sum >> 16); 1407251881Speter sum = ~sum & 0xffff; 1408251881Speter sum2 += sum; 1409251881Speter sum2 = (sum2 & 0xffff) + (sum2 >> 16); 1410251881Speter# else /* defined(BSD) || defined(sun) */ 1411251881Speter{ 1412251881Speter union { 1413251881Speter u_char c[2]; 1414251881Speter u_short s; 1415251881Speter } bytes; 1416251881Speter u_short len = ip->ip_len; 1417251881Speter# if defined(__sgi) 1418251881Speter int add; 1419251881Speter# endif 1420251881Speter 1421251881Speter /* 1422251881Speter * Add up IP Header portion 1423251881Speter */ 1424251881Speter sp = (u_short *)&ip->ip_src; 1425251881Speter len -= (ip->ip_hl << 2); 1426251881Speter sum = ntohs(IPPROTO_TCP); 1427251881Speter sum += htons(len); 1428251881Speter sum += *sp++; /* ip_src */ 1429251881Speter sum += *sp++; 1430251881Speter sum += *sp++; /* ip_dst */ 1431251881Speter sum += *sp++; 1432251881Speter if (sp != (u_short *)tcp) 1433251881Speter sp = (u_short *)tcp; 1434251881Speter sum += *sp++; /* sport */ 1435251881Speter sum += *sp++; /* dport */ 1436251881Speter sum += *sp++; /* seq */ 1437251881Speter sum += *sp++; 1438251881Speter sum += *sp++; /* ack */ 1439251881Speter sum += *sp++; 1440251881Speter sum += *sp++; /* off */ 1441251881Speter sum += *sp++; /* win */ 1442251881Speter sum += *sp++; /* Skip over checksum */ 1443251881Speter sum += *sp++; /* urp */ 1444251881Speter 1445251881Speter# ifdef __sgi 1446251881Speter /* 1447251881Speter * In case we had to copy the IP & TCP header out of mbufs, 1448251881Speter * skip over the mbuf bits which are the header 1449251881Speter */ 1450251881Speter if ((caddr_t)ip != mtod(m, caddr_t)) { 1451251881Speter hlen = (caddr_t)sp - (caddr_t)ip; 1452251881Speter while (hlen) { 1453251881Speter add = MIN(hlen, m->m_len); 1454251881Speter sp = (u_short *)(mtod(m, caddr_t) + add); 1455251881Speter hlen -= add; 1456251881Speter if (add == m->m_len) { 1457251881Speter m = m->m_next; 1458251881Speter if (!hlen) { 1459251881Speter if (!m) 1460251881Speter break; 1461251881Speter sp = mtod(m, u_short *); 1462251881Speter } 1463251881Speter PANIC((!m),("fr_tcpsum(1): not enough data")); 1464251881Speter } 1465251881Speter } 1466251881Speter } 1467251881Speter# endif 1468251881Speter 1469251881Speter if (!(len -= sizeof(*tcp))) 1470251881Speter goto nodata; 1471251881Speter while (len > 1) { 1472251881Speter if (((caddr_t)sp - mtod(m, caddr_t)) >= m->m_len) { 1473251881Speter m = m->m_next; 1474251881Speter PANIC((!m),("fr_tcpsum(2): not enough data")); 1475251881Speter sp = mtod(m, u_short *); 1476251881Speter } 1477251881Speter if (((caddr_t)(sp + 1) - mtod(m, caddr_t)) > m->m_len) { 1478251881Speter bytes.c[0] = *(u_char *)sp; 1479251881Speter m = m->m_next; 1480251881Speter PANIC((!m),("fr_tcpsum(3): not enough data")); 1481251881Speter sp = mtod(m, u_short *); 1482251881Speter bytes.c[1] = *(u_char *)sp; 1483251881Speter sum += bytes.s; 1484251881Speter sp = (u_short *)((u_char *)sp + 1); 1485251881Speter } 1486251881Speter if ((u_long)sp & 1) { 1487251881Speter bcopy((char *)sp++, (char *)&bytes.s, sizeof(bytes.s)); 1488251881Speter sum += bytes.s; 1489251881Speter } else 1490251881Speter sum += *sp++; 1491251881Speter len -= 2; 1492251881Speter } 1493251881Speter if (len) 1494251881Speter sum += ntohs(*(u_char *)sp << 8); 1495251881Speternodata: 1496251881Speter while (sum > 0xffff) 1497251881Speter sum = (sum & 0xffff) + (sum >> 16); 1498251881Speter sum2 = (u_short)(~sum & 0xffff); 1499251881Speter} 1500251881Speter# endif /* defined(BSD) || defined(sun) */ 1501251881Speter# endif /* SOLARIS */ 1502251881Speter#else /* KERNEL */ 1503251881Speter for (; slen > 1; slen -= 2) 1504251881Speter sum += *sp++; 1505251881Speter if (slen) 1506251881Speter sum += ntohs(*(u_char *)sp << 8); 1507251881Speter while (sum > 0xffff) 1508251881Speter sum = (sum & 0xffff) + (sum >> 16); 1509251881Speter sum2 = (u_short)(~sum & 0xffff); 1510251881Speter#endif /* KERNEL */ 1511251881Speter tcp->th_sum = ts; 1512251881Speter return sum2; 1513251881Speter} 1514251881Speter 1515251881Speter 1516251881Speter#if defined(_KERNEL) && ( ((BSD < 199306) && !SOLARIS) || defined(__sgi) ) 1517251881Speter/* 1518251881Speter * Copyright (c) 1982, 1986, 1988, 1991, 1993 1519251881Speter * The Regents of the University of California. All rights reserved. 1520251881Speter * 1521251881Speter * Redistribution and use in source and binary forms, with or without 1522251881Speter * modification, are permitted provided that the following conditions 1523251881Speter * are met: 1524251881Speter * 1. Redistributions of source code must retain the above copyright 1525251881Speter * notice, this list of conditions and the following disclaimer. 1526251881Speter * 2. Redistributions in binary form must reproduce the above copyright 1527251881Speter * notice, this list of conditions and the following disclaimer in the 1528251881Speter * documentation and/or other materials provided with the distribution. 1529251881Speter * 3. All advertising materials mentioning features or use of this software 1530251881Speter * must display the following acknowledgement: 1531251881Speter * This product includes software developed by the University of 1532251881Speter * California, Berkeley and its contributors. 1533251881Speter * 4. Neither the name of the University nor the names of its contributors 1534251881Speter * may be used to endorse or promote products derived from this software 1535251881Speter * without specific prior written permission. 1536251881Speter * 1537251881Speter * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 1538251881Speter * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1539251881Speter * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1540251881Speter * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 1541251881Speter * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1542251881Speter * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 1543251881Speter * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 1544251881Speter * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 1545251881Speter * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 1546251881Speter * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 1547251881Speter * SUCH DAMAGE. 1548251881Speter * 1549251881Speter * @(#)uipc_mbuf.c 8.2 (Berkeley) 1/4/94 1550251881Speter * $Id: fil.c,v 2.35.2.67 2002/12/06 13:28:05 darrenr Exp $ 1551251881Speter */ 1552251881Speter/* 1553251881Speter * Copy data from an mbuf chain starting "off" bytes from the beginning, 1554251881Speter * continuing for "len" bytes, into the indicated buffer. 1555251881Speter */ 1556251881Spetervoid 1557251881Speterm_copydata(m, off, len, cp) 1558251881Speter register mb_t *m; 1559251881Speter register int off; 1560251881Speter register int len; 1561251881Speter caddr_t cp; 1562251881Speter{ 1563251881Speter register unsigned count; 1564251881Speter 1565251881Speter if (off < 0 || len < 0) 1566251881Speter panic("m_copydata"); 1567251881Speter while (off > 0) { 1568251881Speter if (m == 0) 1569251881Speter panic("m_copydata"); 1570251881Speter if (off < m->m_len) 1571251881Speter break; 1572251881Speter off -= m->m_len; 1573251881Speter m = m->m_next; 1574251881Speter } 1575251881Speter while (len > 0) { 1576251881Speter if (m == 0) 1577251881Speter panic("m_copydata"); 1578251881Speter count = MIN(m->m_len - off, len); 1579251881Speter bcopy(mtod(m, caddr_t) + off, cp, count); 1580251881Speter len -= count; 1581251881Speter cp += count; 1582251881Speter off = 0; 1583251881Speter m = m->m_next; 1584251881Speter } 1585251881Speter} 1586251881Speter 1587251881Speter 1588251881Speter# ifndef linux 1589251881Speter/* 1590251881Speter * Copy data from a buffer back into the indicated mbuf chain, 1591251881Speter * starting "off" bytes from the beginning, extending the mbuf 1592251881Speter * chain if necessary. 1593251881Speter */ 1594251881Spetervoid 1595251881Speterm_copyback(m0, off, len, cp) 1596251881Speter struct mbuf *m0; 1597251881Speter register int off; 1598251881Speter register int len; 1599251881Speter caddr_t cp; 1600251881Speter{ 1601251881Speter register int mlen; 1602251881Speter register struct mbuf *m = m0, *n; 1603251881Speter int totlen = 0; 1604251881Speter 1605251881Speter if (m0 == 0) 1606251881Speter return; 1607251881Speter while (off > (mlen = m->m_len)) { 1608251881Speter off -= mlen; 1609251881Speter totlen += mlen; 1610251881Speter if (m->m_next == 0) { 1611251881Speter n = m_getclr(M_DONTWAIT, m->m_type); 1612251881Speter if (n == 0) 1613251881Speter goto out; 1614251881Speter n->m_len = min(MLEN, len + off); 1615251881Speter m->m_next = n; 1616251881Speter } 1617251881Speter m = m->m_next; 1618251881Speter } 1619251881Speter while (len > 0) { 1620251881Speter mlen = min (m->m_len - off, len); 1621251881Speter bcopy(cp, off + mtod(m, caddr_t), (unsigned)mlen); 1622251881Speter cp += mlen; 1623251881Speter len -= mlen; 1624251881Speter mlen += off; 1625251881Speter off = 0; 1626251881Speter totlen += mlen; 1627251881Speter if (len == 0) 1628251881Speter break; 1629251881Speter if (m->m_next == 0) { 1630251881Speter n = m_get(M_DONTWAIT, m->m_type); 1631251881Speter if (n == 0) 1632251881Speter break; 1633251881Speter n->m_len = min(MLEN, len); 1634251881Speter m->m_next = n; 1635251881Speter } 1636251881Speter m = m->m_next; 1637251881Speter } 1638251881Speterout: 1639251881Speter#if 0 1640251881Speter if (((m = m0)->m_flags & M_PKTHDR) && (m->m_pkthdr.len < totlen)) 1641251881Speter m->m_pkthdr.len = totlen; 1642251881Speter#endif 1643251881Speter return; 1644251881Speter} 1645251881Speter# endif /* linux */ 1646251881Speter#endif /* (_KERNEL) && ( ((BSD < 199306) && !SOLARIS) || __sgi) */ 1647251881Speter 1648251881Speter 1649251881Speterfrgroup_t *fr_findgroup(num, flags, which, set, fgpp) 1650251881Speteru_32_t num, flags; 1651251881Speterminor_t which; 1652251881Speterint set; 1653251881Speterfrgroup_t ***fgpp; 1654251881Speter{ 1655251881Speter frgroup_t *fg, **fgp; 1656251881Speter 1657251881Speter if (which == IPL_LOGAUTH) 1658251881Speter fgp = &ipfgroups[2][set]; 1659251881Speter else if (flags & FR_ACCOUNT) 1660251881Speter fgp = &ipfgroups[1][set]; 1661251881Speter else if (flags & (FR_OUTQUE|FR_INQUE)) 1662251881Speter fgp = &ipfgroups[0][set]; 1663251881Speter else 1664251881Speter return NULL; 1665251881Speter 1666251881Speter while ((fg = *fgp)) 1667251881Speter if (fg->fg_num == num) 1668251881Speter break; 1669251881Speter else 1670251881Speter fgp = &fg->fg_next; 1671251881Speter if (fgpp) 1672251881Speter *fgpp = fgp; 1673251881Speter return fg; 1674251881Speter} 1675251881Speter 1676251881Speter 1677251881Speterfrgroup_t *fr_addgroup(num, fp, which, set) 1678251881Speteru_32_t num; 1679251881Speterfrentry_t *fp; 1680251881Speterminor_t which; 1681251881Speterint set; 1682251881Speter{ 1683251881Speter frgroup_t *fg, **fgp; 1684251881Speter 1685251881Speter if ((fg = fr_findgroup(num, fp->fr_flags, which, set, &fgp))) 1686251881Speter return fg; 1687251881Speter 1688251881Speter KMALLOC(fg, frgroup_t *); 1689251881Speter if (fg) { 1690251881Speter fg->fg_num = num; 1691251881Speter fg->fg_next = *fgp; 1692251881Speter fg->fg_head = fp; 1693251881Speter fg->fg_start = &fp->fr_grp; 1694251881Speter *fgp = fg; 1695251881Speter } 1696251881Speter return fg; 1697251881Speter} 1698251881Speter 1699251881Speter 1700251881Spetervoid fr_delgroup(num, flags, which, set) 1701251881Speteru_32_t num, flags; 1702251881Speterminor_t which; 1703251881Speterint set; 1704251881Speter{ 1705251881Speter frgroup_t *fg, **fgp; 1706251881Speter 1707251881Speter if (!(fg = fr_findgroup(num, flags, which, set, &fgp))) 1708251881Speter return; 1709251881Speter 1710251881Speter *fgp = fg->fg_next; 1711251881Speter KFREE(fg); 1712251881Speter} 1713251881Speter 1714251881Speter 1715251881Speter 1716251881Speter/* 1717251881Speter * recursively flush rules from the list, descending groups as they are 1718251881Speter * encountered. if a rule is the head of a group and it has lost all its 1719251881Speter * group members, then also delete the group reference. 1720251881Speter */ 1721251881Speterstatic int frflushlist(set, unit, nfreedp, listp) 1722251881Speterint set; 1723251881Speterminor_t unit; 1724251881Speterint *nfreedp; 1725251881Speterfrentry_t **listp; 1726251881Speter{ 1727251881Speter register int freed = 0, i; 1728251881Speter register frentry_t *fp; 1729251881Speter 1730251881Speter while ((fp = *listp)) { 1731251881Speter *listp = fp->fr_next; 1732251881Speter if (fp->fr_grp) { 1733251881Speter i = frflushlist(set, unit, nfreedp, &fp->fr_grp); 1734251881Speter MUTEX_ENTER(&ipf_rw); 1735251881Speter fp->fr_ref -= i; 1736251881Speter MUTEX_EXIT(&ipf_rw); 1737251881Speter } 1738251881Speter 1739251881Speter ATOMIC_DEC32(fp->fr_ref); 1740251881Speter if (fp->fr_grhead) { 1741251881Speter fr_delgroup(fp->fr_grhead, fp->fr_flags, 1742251881Speter unit, set); 1743251881Speter fp->fr_grhead = 0; 1744251881Speter } 1745251881Speter if (fp->fr_ref == 0) { 1746251881Speter KFREE(fp); 1747251881Speter freed++; 1748251881Speter } else 1749251881Speter fp->fr_next = NULL; 1750251881Speter } 1751251881Speter *nfreedp += freed; 1752251881Speter return freed; 1753251881Speter} 1754251881Speter 1755251881Speter 1756251881Speterint frflush(unit, proto, flags) 1757251881Speterminor_t unit; 1758251881Speterint proto, flags; 1759251881Speter{ 1760251881Speter int flushed = 0, set; 1761251881Speter 1762251881Speter if (unit != IPL_LOGIPF) 1763251881Speter return 0; 1764251881Speter WRITE_ENTER(&ipf_mutex); 1765251881Speter bzero((char *)frcache, sizeof(frcache[0]) * 2); 1766251881Speter 1767251881Speter set = fr_active; 1768251881Speter if (flags & FR_INACTIVE) 1769251881Speter set = 1 - set; 1770251881Speter 1771251881Speter if (flags & FR_OUTQUE) { 1772251881Speter#ifdef USE_INET6 1773251881Speter if (proto == 0 || proto == 6) { 1774251881Speter (void) frflushlist(set, unit, 1775251881Speter &flushed, &ipfilter6[1][set]); 1776251881Speter (void) frflushlist(set, unit, 1777251881Speter &flushed, &ipacct6[1][set]); 1778251881Speter } 1779251881Speter#endif 1780251881Speter if (proto == 0 || proto == 4) { 1781251881Speter (void) frflushlist(set, unit, 1782251881Speter &flushed, &ipfilter[1][set]); 1783251881Speter (void) frflushlist(set, unit, 1784251881Speter &flushed, &ipacct[1][set]); 1785251881Speter } 1786251881Speter } 1787251881Speter if (flags & FR_INQUE) { 1788251881Speter#ifdef USE_INET6 1789251881Speter if (proto == 0 || proto == 6) { 1790251881Speter (void) frflushlist(set, unit, 1791251881Speter &flushed, &ipfilter6[0][set]); 1792251881Speter (void) frflushlist(set, unit, 1793251881Speter &flushed, &ipacct6[0][set]); 1794251881Speter } 1795251881Speter#endif 1796251881Speter if (proto == 0 || proto == 4) { 1797251881Speter (void) frflushlist(set, unit, 1798251881Speter &flushed, &ipfilter[0][set]); 1799251881Speter (void) frflushlist(set, unit, 1800251881Speter &flushed, &ipacct[0][set]); 1801251881Speter } 1802251881Speter } 1803251881Speter RWLOCK_EXIT(&ipf_mutex); 1804251881Speter return flushed; 1805251881Speter} 1806251881Speter 1807251881Speter 1808251881Speterchar *memstr(src, dst, slen, dlen) 1809251881Speterchar *src, *dst; 1810251881Speterint slen, dlen; 1811251881Speter{ 1812251881Speter char *s = NULL; 1813251881Speter 1814251881Speter while (dlen >= slen) { 1815251881Speter if (bcmp(src, dst, slen) == 0) { 1816251881Speter s = dst; 1817251881Speter break; 1818251881Speter } 1819251881Speter dst++; 1820251881Speter dlen--; 1821251881Speter } 1822251881Speter return s; 1823251881Speter} 1824251881Speter 1825251881Speter 1826251881Spetervoid fixskip(listp, rp, addremove) 1827251881Speterfrentry_t **listp, *rp; 1828251881Speterint addremove; 1829251881Speter{ 1830251881Speter frentry_t *fp; 1831251881Speter int rules = 0, rn = 0; 1832251881Speter 1833251881Speter for (fp = *listp; fp && (fp != rp); fp = fp->fr_next, rules++) 1834251881Speter ; 1835251881Speter 1836251881Speter if (!fp) 1837251881Speter return; 1838251881Speter 1839251881Speter for (fp = *listp; fp && (fp != rp); fp = fp->fr_next, rn++) 1840251881Speter if (fp->fr_skip && (rn + fp->fr_skip >= rules)) 1841251881Speter fp->fr_skip += addremove; 1842251881Speter} 1843251881Speter 1844251881Speter 1845251881Speter#ifdef _KERNEL 1846251881Speter/* 1847251881Speter * count consecutive 1's in bit mask. If the mask generated by counting 1848251881Speter * consecutive 1's is different to that passed, return -1, else return # 1849251881Speter * of bits. 1850251881Speter */ 1851251881Speterint countbits(ip) 1852251881Speteru_32_t ip; 1853251881Speter{ 1854251881Speter u_32_t ipn; 1855251881Speter int cnt = 0, i, j; 1856251881Speter 1857251881Speter ip = ipn = ntohl(ip); 1858251881Speter for (i = 32; i; i--, ipn *= 2) 1859251881Speter if (ipn & 0x80000000) 1860251881Speter cnt++; 1861251881Speter else 1862251881Speter break; 1863251881Speter ipn = 0; 1864251881Speter for (i = 32, j = cnt; i; i--, j--) { 1865251881Speter ipn *= 2; 1866251881Speter if (j > 0) 1867251881Speter ipn++; 1868251881Speter } 1869251881Speter if (ipn == ip) 1870251881Speter return cnt; 1871251881Speter return -1; 1872251881Speter} 1873251881Speter 1874251881Speter 1875251881Speter/* 1876251881Speter * return the first IP Address associated with an interface 1877251881Speter */ 1878251881Speterint fr_ifpaddr(v, ifptr, inp) 1879251881Speterint v; 1880251881Spetervoid *ifptr; 1881251881Speterstruct in_addr *inp; 1882251881Speter{ 1883251881Speter# ifdef USE_INET6 1884251881Speter struct in6_addr *inp6 = NULL; 1885251881Speter# endif 1886251881Speter# if SOLARIS 1887251881Speter ill_t *ill = ifptr; 1888251881Speter# else 1889251881Speter struct ifnet *ifp = ifptr; 1890251881Speter# endif 1891251881Speter struct in_addr in; 1892251881Speter 1893251881Speter# if SOLARIS 1894251881Speter# ifdef USE_INET6 1895251881Speter if (v == 6) { 1896251881Speter struct in6_addr in6; 1897251881Speter 1898251881Speter /* 1899251881Speter * First is always link local. 1900251881Speter */ 1901251881Speter if (ill->ill_ipif->ipif_next) 1902251881Speter in6 = ill->ill_ipif->ipif_next->ipif_v6lcl_addr; 1903251881Speter else 1904251881Speter bzero((char *)&in6, sizeof(in6)); 1905251881Speter bcopy((char *)&in6, (char *)inp, sizeof(in6)); 1906251881Speter } else 1907251881Speter# endif 1908251881Speter { 1909251881Speter in.s_addr = ill->ill_ipif->ipif_local_addr; 1910251881Speter *inp = in; 1911251881Speter } 1912251881Speter# else /* SOLARIS */ 1913251881Speter# if linux 1914251881Speter ; 1915251881Speter# else /* linux */ 1916251881Speter struct sockaddr_in *sin; 1917251881Speter struct ifaddr *ifa; 1918251881Speter 1919251881Speter# if (__FreeBSD_version >= 300000) 1920251881Speter ifa = TAILQ_FIRST(&ifp->if_addrhead); 1921251881Speter# else 1922251881Speter# if defined(__NetBSD__) || defined(__OpenBSD__) 1923251881Speter ifa = ifp->if_addrlist.tqh_first; 1924251881Speter# else 1925251881Speter# if defined(__sgi) && defined(IFF_DRVRLOCK) /* IRIX 6 */ 1926251881Speter ifa = &((struct in_ifaddr *)ifp->in_ifaddr)->ia_ifa; 1927251881Speter# else 1928251881Speter ifa = ifp->if_addrlist; 1929251881Speter# endif 1930251881Speter# endif /* __NetBSD__ || __OpenBSD__ */ 1931251881Speter# endif /* __FreeBSD_version >= 300000 */ 1932251881Speter# if (BSD < 199306) && !(/*IRIX6*/defined(__sgi) && defined(IFF_DRVRLOCK)) 1933251881Speter sin = (struct sockaddr_in *)&ifa->ifa_addr; 1934251881Speter# else 1935251881Speter sin = (struct sockaddr_in *)ifa->ifa_addr; 1936251881Speter while (sin && ifa) { 1937251881Speter if ((v == 4) && (sin->sin_family == AF_INET)) 1938251881Speter break; 1939251881Speter# ifdef USE_INET6 1940251881Speter if ((v == 6) && (sin->sin_family == AF_INET6)) { 1941251881Speter inp6 = &((struct sockaddr_in6 *)sin)->sin6_addr; 1942251881Speter if (!IN6_IS_ADDR_LINKLOCAL(inp6) && 1943251881Speter !IN6_IS_ADDR_LOOPBACK(inp6)) 1944251881Speter break; 1945251881Speter } 1946251881Speter# endif 1947251881Speter# if (__FreeBSD_version >= 300000) 1948251881Speter ifa = TAILQ_NEXT(ifa, ifa_link); 1949251881Speter# else 1950251881Speter# if defined(__NetBSD__) || defined(__OpenBSD__) 1951251881Speter ifa = ifa->ifa_list.tqe_next; 1952251881Speter# else 1953251881Speter ifa = ifa->ifa_next; 1954251881Speter# endif 1955251881Speter# endif /* __FreeBSD_version >= 300000 */ 1956251881Speter if (ifa) 1957251881Speter sin = (struct sockaddr_in *)ifa->ifa_addr; 1958251881Speter } 1959251881Speter if (ifa == NULL) 1960251881Speter sin = NULL; 1961251881Speter if (sin == NULL) 1962251881Speter return -1; 1963251881Speter# endif /* (BSD < 199306) && (!__sgi && IFF_DRVLOCK) */ 1964251881Speter# ifdef USE_INET6 1965251881Speter if (v == 6) 1966251881Speter bcopy((char *)inp6, (char *)inp, sizeof(*inp6)); 1967251881Speter else 1968251881Speter# endif 1969251881Speter { 1970251881Speter in = sin->sin_addr; 1971251881Speter *inp = in; 1972251881Speter } 1973251881Speter# endif /* linux */ 1974251881Speter# endif /* SOLARIS */ 1975251881Speter return 0; 1976251881Speter} 1977251881Speter 1978251881Speter 1979251881Speterstatic void frsynclist(fr) 1980251881Speterregister frentry_t *fr; 1981251881Speter{ 1982251881Speter for (; fr; fr = fr->fr_next) { 1983251881Speter if (fr->fr_ifa != NULL) { 1984251881Speter fr->fr_ifa = GETUNIT(fr->fr_ifname, fr->fr_ip.fi_v); 1985251881Speter if (fr->fr_ifa == NULL) 1986251881Speter fr->fr_ifa = (void *)-1; 1987251881Speter } 1988251881Speter if (fr->fr_grp) 1989251881Speter frsynclist(fr->fr_grp); 1990251881Speter } 1991251881Speter} 1992251881Speter 1993251881Speter 1994251881Spetervoid frsync() 1995251881Speter{ 1996251881Speter# if !SOLARIS 1997251881Speter register struct ifnet *ifp; 1998251881Speter 1999251881Speter# if defined(__OpenBSD__) || ((NetBSD >= 199511) && (NetBSD < 1991011)) || \ 2000251881Speter (defined(__FreeBSD_version) && (__FreeBSD_version >= 300000)) 2001251881Speter# if (NetBSD >= 199905) || defined(__OpenBSD__) 2002251881Speter for (ifp = ifnet.tqh_first; ifp; ifp = ifp->if_list.tqe_next) 2003251881Speter# elif defined(__FreeBSD_version) && (__FreeBSD_version >= 500043) 2004251881Speter IFNET_RLOCK(); 2005251881Speter TAILQ_FOREACH(ifp, &ifnet, if_link) 2006251881Speter# else 2007251881Speter for (ifp = ifnet.tqh_first; ifp; ifp = ifp->if_link.tqe_next) 2008251881Speter# endif 2009251881Speter# else 2010251881Speter for (ifp = ifnet; ifp; ifp = ifp->if_next) 2011251881Speter# endif 2012251881Speter { 2013251881Speter ip_natsync(ifp); 2014251881Speter ip_statesync(ifp); 2015251881Speter } 2016251881Speter# if defined(__FreeBSD_version) && (__FreeBSD_version >= 500043) 2017251881Speter IFNET_RUNLOCK(); 2018251881Speter# endif 2019251881Speter ip_natsync((struct ifnet *)-1); 2020251881Speter# endif /* !SOLARIS */ 2021251881Speter 2022251881Speter WRITE_ENTER(&ipf_mutex); 2023251881Speter frsynclist(ipacct[0][fr_active]); 2024251881Speter frsynclist(ipacct[1][fr_active]); 2025251881Speter frsynclist(ipfilter[0][fr_active]); 2026251881Speter frsynclist(ipfilter[1][fr_active]); 2027251881Speter#ifdef USE_INET6 2028251881Speter frsynclist(ipacct6[0][fr_active]); 2029251881Speter frsynclist(ipacct6[1][fr_active]); 2030251881Speter frsynclist(ipfilter6[0][fr_active]); 2031251881Speter frsynclist(ipfilter6[1][fr_active]); 2032251881Speter#endif 2033251881Speter RWLOCK_EXIT(&ipf_mutex); 2034251881Speter} 2035251881Speter 2036251881Speter 2037251881Speter/* 2038251881Speter * In the functions below, bcopy() is called because the pointer being 2039251881Speter * copied _from_ in this instance is a pointer to a char buf (which could 2040251881Speter * end up being unaligned) and on the kernel's local stack. 2041251881Speter */ 2042251881Speterint ircopyptr(a, b, c) 2043251881Spetervoid *a, *b; 2044251881Spetersize_t c; 2045251881Speter{ 2046251881Speter caddr_t ca; 2047251881Speter int err; 2048251881Speter 2049251881Speter#if SOLARIS 2050251881Speter if (copyin(a, (char *)&ca, sizeof(ca))) 2051251881Speter return EFAULT; 2052251881Speter#else 2053251881Speter bcopy(a, &ca, sizeof(ca)); 2054251881Speter#endif 2055251881Speter err = copyin(ca, b, c); 2056251881Speter if (err) 2057251881Speter err = EFAULT; 2058251881Speter return err; 2059251881Speter} 2060251881Speter 2061251881Speter 2062251881Speterint iwcopyptr(a, b, c) 2063251881Spetervoid *a, *b; 2064251881Spetersize_t c; 2065251881Speter{ 2066251881Speter caddr_t ca; 2067251881Speter int err; 2068251881Speter 2069251881Speter#if SOLARIS 2070251881Speter if (copyin(b, (char *)&ca, sizeof(ca))) 2071251881Speter return EFAULT; 2072251881Speter#else 2073251881Speter bcopy(b, &ca, sizeof(ca)); 2074251881Speter#endif 2075251881Speter err = copyout(a, ca, c); 2076251881Speter if (err) 2077251881Speter err = EFAULT; 2078251881Speter return err; 2079251881Speter} 2080251881Speter 2081251881Speter#else /* _KERNEL */ 2082251881Speter 2083251881Speter 2084251881Speter/* 2085251881Speter * return the first IP Address associated with an interface 2086251881Speter */ 2087251881Speterint fr_ifpaddr(v, ifptr, inp) 2088251881Speterint v; 2089251881Spetervoid *ifptr; 2090251881Speterstruct in_addr *inp; 2091251881Speter{ 2092251881Speter return 0; 2093251881Speter} 2094251881Speter 2095251881Speter 2096251881Speterint ircopyptr(a, b, c) 2097251881Spetervoid *a, *b; 2098251881Spetersize_t c; 2099251881Speter{ 2100251881Speter caddr_t ca; 2101251881Speter 2102251881Speter bcopy(a, &ca, sizeof(ca)); 2103251881Speter bcopy(ca, b, c); 2104251881Speter return 0; 2105251881Speter} 2106251881Speter 2107251881Speter 2108251881Speterint iwcopyptr(a, b, c) 2109251881Spetervoid *a, *b; 2110251881Spetersize_t c; 2111251881Speter{ 2112251881Speter caddr_t ca; 2113251881Speter 2114251881Speter bcopy(b, &ca, sizeof(ca)); 2115251881Speter bcopy(a, ca, c); 2116251881Speter return 0; 2117251881Speter} 2118251881Speter 2119251881Speter 2120251881Speter#endif 2121251881Speter 2122251881Speter 2123251881Speterint fr_lock(data, lockp) 2124251881Spetercaddr_t data; 2125251881Speterint *lockp; 2126251881Speter{ 2127251881Speter int arg, error; 2128251881Speter 2129251881Speter error = IRCOPY(data, (caddr_t)&arg, sizeof(arg)); 2130251881Speter if (!error) { 2131251881Speter error = IWCOPY((caddr_t)lockp, data, sizeof(*lockp)); 2132251881Speter if (!error) 2133251881Speter *lockp = arg; 2134251881Speter } 2135251881Speter return error; 2136251881Speter} 2137251881Speter 2138251881Speter 2139251881Spetervoid fr_getstat(fiop) 2140251881Speterfriostat_t *fiop; 2141251881Speter{ 2142251881Speter bcopy((char *)frstats, (char *)fiop->f_st, sizeof(filterstats_t) * 2); 2143251881Speter fiop->f_locks[0] = fr_state_lock; 2144251881Speter fiop->f_locks[1] = fr_nat_lock; 2145251881Speter fiop->f_locks[2] = fr_frag_lock; 2146251881Speter fiop->f_locks[3] = fr_auth_lock; 2147251881Speter fiop->f_fin[0] = ipfilter[0][0]; 2148251881Speter fiop->f_fin[1] = ipfilter[0][1]; 2149251881Speter fiop->f_fout[0] = ipfilter[1][0]; 2150251881Speter fiop->f_fout[1] = ipfilter[1][1]; 2151251881Speter fiop->f_acctin[0] = ipacct[0][0]; 2152251881Speter fiop->f_acctin[1] = ipacct[0][1]; 2153251881Speter fiop->f_acctout[0] = ipacct[1][0]; 2154251881Speter fiop->f_acctout[1] = ipacct[1][1]; 2155251881Speter#ifdef USE_INET6 2156251881Speter fiop->f_fin6[0] = ipfilter6[0][0]; 2157251881Speter fiop->f_fin6[1] = ipfilter6[0][1]; 2158251881Speter fiop->f_fout6[0] = ipfilter6[1][0]; 2159251881Speter fiop->f_fout6[1] = ipfilter6[1][1]; 2160251881Speter fiop->f_acctin6[0] = ipacct6[0][0]; 2161251881Speter fiop->f_acctin6[1] = ipacct6[0][1]; 2162251881Speter fiop->f_acctout6[0] = ipacct6[1][0]; 2163251881Speter fiop->f_acctout6[1] = ipacct6[1][1]; 2164251881Speter#else 2165251881Speter fiop->f_fin6[0] = NULL; 2166251881Speter fiop->f_fin6[1] = NULL; 2167251881Speter fiop->f_fout6[0] = NULL; 2168251881Speter fiop->f_fout6[1] = NULL; 2169251881Speter fiop->f_acctin6[0] = NULL; 2170251881Speter fiop->f_acctin6[1] = NULL; 2171251881Speter fiop->f_acctout6[0] = NULL; 2172251881Speter fiop->f_acctout6[1] = NULL; 2173251881Speter#endif 2174251881Speter fiop->f_active = fr_active; 2175251881Speter fiop->f_froute[0] = ipl_frouteok[0]; 2176251881Speter fiop->f_froute[1] = ipl_frouteok[1]; 2177251881Speter 2178251881Speter fiop->f_running = fr_running; 2179251881Speter fiop->f_groups[0][0] = ipfgroups[0][0]; 2180251881Speter fiop->f_groups[0][1] = ipfgroups[0][1]; 2181251881Speter fiop->f_groups[1][0] = ipfgroups[1][0]; 2182251881Speter fiop->f_groups[1][1] = ipfgroups[1][1]; 2183251881Speter fiop->f_groups[2][0] = ipfgroups[2][0]; 2184251881Speter fiop->f_groups[2][1] = ipfgroups[2][1]; 2185251881Speter#ifdef IPFILTER_LOG 2186251881Speter fiop->f_logging = 1; 2187251881Speter#else 2188251881Speter fiop->f_logging = 0; 2189251881Speter#endif 2190251881Speter fiop->f_defpass = fr_pass; 2191251881Speter strncpy(fiop->f_version, ipfilter_version, sizeof(fiop->f_version)); 2192251881Speter} 2193251881Speter 2194251881Speter 2195251881Speter#ifdef USE_INET6 2196251881Speterint icmptoicmp6types[ICMP_MAXTYPE+1] = { 2197251881Speter ICMP6_ECHO_REPLY, /* 0: ICMP_ECHOREPLY */ 2198251881Speter -1, /* 1: UNUSED */ 2199251881Speter -1, /* 2: UNUSED */ 2200251881Speter ICMP6_DST_UNREACH, /* 3: ICMP_UNREACH */ 2201251881Speter -1, /* 4: ICMP_SOURCEQUENCH */ 2202251881Speter ND_REDIRECT, /* 5: ICMP_REDIRECT */ 2203251881Speter -1, /* 6: UNUSED */ 2204251881Speter -1, /* 7: UNUSED */ 2205251881Speter ICMP6_ECHO_REQUEST, /* 8: ICMP_ECHO */ 2206251881Speter -1, /* 9: UNUSED */ 2207251881Speter -1, /* 10: UNUSED */ 2208251881Speter ICMP6_TIME_EXCEEDED, /* 11: ICMP_TIMXCEED */ 2209251881Speter ICMP6_PARAM_PROB, /* 12: ICMP_PARAMPROB */ 2210251881Speter -1, /* 13: ICMP_TSTAMP */ 2211251881Speter -1, /* 14: ICMP_TSTAMPREPLY */ 2212251881Speter -1, /* 15: ICMP_IREQ */ 2213251881Speter -1, /* 16: ICMP_IREQREPLY */ 2214251881Speter -1, /* 17: ICMP_MASKREQ */ 2215251881Speter -1, /* 18: ICMP_MASKREPLY */ 2216251881Speter}; 2217251881Speter 2218251881Speter 2219251881Speterint icmptoicmp6unreach[ICMP_MAX_UNREACH] = { 2220251881Speter ICMP6_DST_UNREACH_ADDR, /* 0: ICMP_UNREACH_NET */ 2221251881Speter ICMP6_DST_UNREACH_ADDR, /* 1: ICMP_UNREACH_HOST */ 2222251881Speter -1, /* 2: ICMP_UNREACH_PROTOCOL */ 2223251881Speter ICMP6_DST_UNREACH_NOPORT, /* 3: ICMP_UNREACH_PORT */ 2224251881Speter -1, /* 4: ICMP_UNREACH_NEEDFRAG */ 2225251881Speter ICMP6_DST_UNREACH_NOTNEIGHBOR, /* 5: ICMP_UNREACH_SRCFAIL */ 2226251881Speter ICMP6_DST_UNREACH_ADDR, /* 6: ICMP_UNREACH_NET_UNKNOWN */ 2227251881Speter ICMP6_DST_UNREACH_ADDR, /* 7: ICMP_UNREACH_HOST_UNKNOWN */ 2228251881Speter -1, /* 8: ICMP_UNREACH_ISOLATED */ 2229251881Speter ICMP6_DST_UNREACH_ADMIN, /* 9: ICMP_UNREACH_NET_PROHIB */ 2230251881Speter ICMP6_DST_UNREACH_ADMIN, /* 10: ICMP_UNREACH_HOST_PROHIB */ 2231251881Speter -1, /* 11: ICMP_UNREACH_TOSNET */ 2232251881Speter -1, /* 12: ICMP_UNREACH_TOSHOST */ 2233251881Speter ICMP6_DST_UNREACH_ADMIN, /* 13: ICMP_UNREACH_ADMIN_PROHIBIT */ 2234251881Speter}; 2235251881Speter#endif 2236251881Speter 2237251881Speter 2238251881Speter#ifndef _KERNEL 2239251881Speterint mbuflen(buf) 2240251881Spetermb_t *buf; 2241251881Speter{ 2242251881Speter ip_t *ip; 2243251881Speter 2244251881Speter ip = (ip_t *)buf; 2245251881Speter return ip->ip_len; 2246251881Speter} 2247251881Speter#endif 2248251881Speter