|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. ! 3: * ! 4: * @APPLE_LICENSE_HEADER_START@ ! 5: * ! 6: * The contents of this file constitute Original Code as defined in and ! 7: * are subject to the Apple Public Source License Version 1.1 (the ! 8: * "License"). You may not use this file except in compliance with the ! 9: * License. Please obtain a copy of the License at ! 10: * http://www.apple.com/publicsource and read it before using this file. ! 11: * ! 12: * This Original Code and all software distributed under the License are ! 13: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER ! 14: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, ! 15: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, ! 16: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the ! 17: * License for the specific language governing rights and limitations ! 18: * under the License. ! 19: * ! 20: * @APPLE_LICENSE_HEADER_END@ ! 21: */ ! 22: /* ! 23: * Copyright (C) 1997 by Darren Reed. ! 24: * ! 25: * Redistribution and use in source and binary forms are permitted ! 26: * provided that this notice is preserved and due credit is given ! 27: * to the original author and the contributors. ! 28: * ! 29: */ ! 30: #include "opt_ipfilter.h" ! 31: ! 32: #if IPFILTER_LOG ! 33: # ifndef SOLARIS ! 34: # define SOLARIS (defined(sun) && (defined(__svr4__) || defined(__SVR4))) ! 35: # endif ! 36: ! 37: # if defined(KERNEL) && !defined(_KERNEL) ! 38: # define _KERNEL ! 39: # endif ! 40: # ifdef __FreeBSD__ ! 41: # if defined(_KERNEL) && !defined(IPFILTER_LKM) ! 42: # define __FreeBSD_version 300000 /* this will do as a hack */ ! 43: # else ! 44: # include <osreldate.h> ! 45: # endif ! 46: # endif ! 47: # ifndef _KERNEL ! 48: # include <stdio.h> ! 49: # include <string.h> ! 50: # include <stdlib.h> ! 51: # include <ctype.h> ! 52: # endif ! 53: # include <sys/errno.h> ! 54: # include <sys/types.h> ! 55: # include <sys/param.h> ! 56: # include <sys/file.h> ! 57: # if __FreeBSD_version >= 220000 && defined(_KERNEL) ! 58: # include <sys/fcntl.h> ! 59: # include <sys/filio.h> ! 60: # else ! 61: # include <sys/ioctl.h> ! 62: # endif ! 63: # include <sys/time.h> ! 64: # if defined(_KERNEL) && !defined(linux) ! 65: # include <sys/systm.h> ! 66: # endif ! 67: # include <sys/uio.h> ! 68: # if !SOLARIS ! 69: # if (NetBSD > 199609) || (OpenBSD > 199603) || defined(__FreeBSD__) ! 70: # include <sys/dirent.h> ! 71: # else ! 72: # include <sys/dir.h> ! 73: # endif ! 74: # ifndef linux ! 75: # include <sys/mbuf.h> ! 76: # endif ! 77: # else ! 78: # include <sys/filio.h> ! 79: # include <sys/cred.h> ! 80: # include <sys/ddi.h> ! 81: # include <sys/sunddi.h> ! 82: # include <sys/ksynch.h> ! 83: # include <sys/kmem.h> ! 84: # include <sys/mkdev.h> ! 85: # include <sys/dditypes.h> ! 86: # include <sys/cmn_err.h> ! 87: # endif ! 88: # ifndef linux ! 89: # include <sys/protosw.h> ! 90: # endif ! 91: # include <sys/socket.h> ! 92: ! 93: # include <net/if.h> ! 94: # ifdef sun ! 95: # include <net/af.h> ! 96: # endif ! 97: # if __FreeBSD_version >= 300000 ! 98: # include <sys/malloc.h> ! 99: # include <machine/random.h> ! 100: # endif ! 101: # include <net/route.h> ! 102: # include <netinet/in.h> ! 103: # ifdef __sgi ! 104: # include <sys/ddi.h> ! 105: # ifdef IFF_DRVRLOCK /* IRIX6 */ ! 106: # include <sys/hashing.h> ! 107: # endif ! 108: # endif ! 109: # if !defined(linux) && !(defined(__sgi) && !defined(IFF_DRVRLOCK)) /*IRIX<6*/ ! 110: # include <netinet/in_var.h> ! 111: # endif ! 112: # include <netinet/in_systm.h> ! 113: # include <netinet/ip.h> ! 114: # include <netinet/tcp.h> ! 115: # include <netinet/udp.h> ! 116: # include <netinet/ip_icmp.h> ! 117: # ifndef linux ! 118: # include <netinet/ip_var.h> ! 119: # endif ! 120: # ifndef _KERNEL ! 121: # include <syslog.h> ! 122: # endif ! 123: # include "netinet/ip_compat.h" ! 124: # include <netinet/tcpip.h> ! 125: # include "netinet/ip_fil.h" ! 126: # include "netinet/ip_proxy.h" ! 127: # include "netinet/ip_nat.h" ! 128: # include "netinet/ip_frag.h" ! 129: # include "netinet/ip_state.h" ! 130: # include "netinet/ip_auth.h" ! 131: # ifndef MIN ! 132: # define MIN(a,b) (((a)<(b))?(a):(b)) ! 133: # endif ! 134: ! 135: ! 136: # if SOLARIS || defined(__sgi) ! 137: extern kmutex_t ipl_mutex; ! 138: # if SOLARIS ! 139: extern kcondvar_t iplwait; ! 140: # endif ! 141: # endif ! 142: ! 143: iplog_t **iplh[IPL_LOGMAX+1], *iplt[IPL_LOGMAX+1]; ! 144: int iplused[IPL_LOGMAX+1]; ! 145: static u_long iplcrc[IPL_LOGMAX+1]; ! 146: static u_long iplcrcinit; ! 147: #ifdef linux ! 148: static struct wait_queue *iplwait[IPL_LOGMAX+1]; ! 149: #endif ! 150: ! 151: ! 152: /* ! 153: * Initialise log buffers & pointers. Also iniialised the CRC to a local ! 154: * secret for use in calculating the "last log checksum". ! 155: */ ! 156: void ipflog_init() ! 157: { ! 158: int i; ! 159: ! 160: for (i = IPL_LOGMAX; i >= 0; i--) { ! 161: iplt[i] = NULL; ! 162: iplh[i] = &iplt[i]; ! 163: iplused[i] = 0; ! 164: } ! 165: # if defined(__FreeBSD__) && __FreeBSD_version >= 300000 ! 166: read_random(&iplcrcinit, sizeof iplcrcinit); ! 167: # else ! 168: { ! 169: struct timeval tv; ! 170: ! 171: #if BSD >= 199306 || defined(__FreeBSD__) || defined(__sgi) ! 172: microtime(&tv); ! 173: # else ! 174: uniqtime(&tv); ! 175: # endif ! 176: iplcrcinit = tv.tv_sec ^ (tv.tv_usec << 8) ^ tv.tv_usec; ! 177: } ! 178: # endif ! 179: } ! 180: ! 181: ! 182: /* ! 183: * ipflog ! 184: * Create a log record for a packet given that it has been triggered by a ! 185: * rule (or the default setting). Calculate the transport protocol header ! 186: * size using predetermined size of a couple of popular protocols and thus ! 187: * how much data to copy into the log, including part of the data body if ! 188: * requested. ! 189: */ ! 190: int ipflog(flags, ip, fin, m) ! 191: u_int flags; ! 192: ip_t *ip; ! 193: fr_info_t *fin; ! 194: mb_t *m; ! 195: { ! 196: ipflog_t ipfl; ! 197: register int mlen, hlen; ! 198: u_long crc; ! 199: size_t sizes[2]; ! 200: void *ptrs[2]; ! 201: int types[2]; ! 202: # if SOLARIS ! 203: ill_t *ifp = fin->fin_ifp; ! 204: # else ! 205: struct ifnet *ifp = fin->fin_ifp; ! 206: # endif ! 207: ! 208: /* ! 209: * calculate header size. ! 210: */ ! 211: hlen = fin->fin_hlen; ! 212: if (ip->ip_p == IPPROTO_TCP) ! 213: hlen += MIN(sizeof(tcphdr_t), fin->fin_dlen); ! 214: else if (ip->ip_p == IPPROTO_UDP) ! 215: hlen += MIN(sizeof(udphdr_t), fin->fin_dlen); ! 216: else if (ip->ip_p == IPPROTO_ICMP) { ! 217: struct icmp *icmp = (struct icmp *)((char *)ip + hlen); ! 218: ! 219: /* ! 220: * For ICMP, if the packet is an error packet, also include ! 221: * the information about the packet which caused the error. ! 222: */ ! 223: switch (icmp->icmp_type) ! 224: { ! 225: case ICMP_UNREACH : ! 226: case ICMP_SOURCEQUENCH : ! 227: case ICMP_REDIRECT : ! 228: case ICMP_TIMXCEED : ! 229: case ICMP_PARAMPROB : ! 230: hlen += MIN(sizeof(struct icmp) + 8, fin->fin_dlen); ! 231: break; ! 232: default : ! 233: hlen += MIN(sizeof(struct icmp), fin->fin_dlen); ! 234: break; ! 235: } ! 236: } ! 237: /* ! 238: * Get the interface number and name to which this packet is ! 239: * currently associated. ! 240: */ ! 241: # if SOLARIS ! 242: ipfl.fl_unit = (u_char)ifp->ill_ppa; ! 243: bcopy(ifp->ill_name, ipfl.fl_ifname, MIN(ifp->ill_name_length, 4)); ! 244: mlen = (flags & FR_LOGBODY) ? MIN(msgdsize(m) - hlen, 128) : 0; ! 245: # else ! 246: # if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199603)) || \ ! 247: (defined(OpenBSD) && (OpenBSD >= 199603)) ! 248: strncpy(ipfl.fl_ifname, ifp->if_xname, IFNAMSIZ); ! 249: # else ! 250: # ifndef linux ! 251: ipfl.fl_unit = (u_char)ifp->if_unit; ! 252: # endif ! 253: if ((ipfl.fl_ifname[0] = ifp->if_name[0])) ! 254: if ((ipfl.fl_ifname[1] = ifp->if_name[1])) ! 255: if ((ipfl.fl_ifname[2] = ifp->if_name[2])) ! 256: ipfl.fl_ifname[3] = ifp->if_name[3]; ! 257: # endif ! 258: mlen = (flags & FR_LOGBODY) ? MIN(ip->ip_len - hlen, 128) : 0; ! 259: # endif ! 260: ipfl.fl_plen = (u_char)mlen; ! 261: ipfl.fl_hlen = (u_char)hlen; ! 262: ipfl.fl_rule = fin->fin_rule; ! 263: ipfl.fl_group = fin->fin_group; ! 264: ipfl.fl_flags = flags; ! 265: ptrs[0] = (void *)&ipfl; ! 266: sizes[0] = sizeof(ipfl); ! 267: types[0] = 0; ! 268: #if SOLARIS ! 269: /* ! 270: * Are we copied from the mblk or an aligned array ? ! 271: */ ! 272: if (ip == (ip_t *)m->b_rptr) { ! 273: ptrs[1] = m; ! 274: sizes[1] = hlen + mlen; ! 275: types[1] = 1; ! 276: } else { ! 277: ptrs[1] = ip; ! 278: sizes[1] = hlen + mlen; ! 279: types[1] = 0; ! 280: } ! 281: #else ! 282: ptrs[1] = m; ! 283: sizes[1] = hlen + mlen; ! 284: types[1] = 1; ! 285: #endif ! 286: crc = (ipf_cksum((u_short *)fin, FI_CSIZE) << 8) + iplcrcinit; ! 287: return ipllog(IPL_LOGIPF, crc, ptrs, sizes, types, 2); ! 288: } ! 289: ! 290: ! 291: /* ! 292: * ipllog ! 293: */ ! 294: int ipllog(dev, crc, items, itemsz, types, cnt) ! 295: int dev; ! 296: u_long crc; ! 297: void **items; ! 298: size_t *itemsz; ! 299: int *types, cnt; ! 300: { ! 301: iplog_t *ipl; ! 302: caddr_t buf, s; ! 303: int len, i; ! 304: ! 305: /* ! 306: * Check to see if this log record has a CRC which matches the last ! 307: * record logged. If it does, just up the count on the previous one ! 308: * rather than create a new one. ! 309: */ ! 310: if (crc) { ! 311: MUTEX_ENTER(&ipl_mutex); ! 312: if ((iplcrc[dev] == crc) && *iplh[dev]) { ! 313: (*iplh[dev])->ipl_count++; ! 314: MUTEX_EXIT(&ipl_mutex); ! 315: return 1; ! 316: } ! 317: iplcrc[dev] = crc; ! 318: MUTEX_EXIT(&ipl_mutex); ! 319: } ! 320: ! 321: /* ! 322: * Get the total amount of data to be logged. ! 323: */ ! 324: for (i = 0, len = sizeof(iplog_t); i < cnt; i++) ! 325: len += itemsz[i]; ! 326: ! 327: /* ! 328: * check that we have space to record this information and can ! 329: * allocate that much. ! 330: */ ! 331: KMALLOC(buf, caddr_t, len); ! 332: if (!buf) ! 333: return 0; ! 334: MUTEX_ENTER(&ipl_mutex); ! 335: if ((iplused[dev] + len) > IPLLOGSIZE) { ! 336: MUTEX_EXIT(&ipl_mutex); ! 337: KFREES(buf, len); ! 338: return 0; ! 339: } ! 340: iplused[dev] += len; ! 341: MUTEX_EXIT(&ipl_mutex); ! 342: ! 343: /* ! 344: * advance the log pointer to the next empty record and deduct the ! 345: * amount of space we're going to use. ! 346: */ ! 347: ipl = (iplog_t *)buf; ! 348: ipl->ipl_magic = IPL_MAGIC; ! 349: ipl->ipl_count = 1; ! 350: ipl->ipl_next = NULL; ! 351: ipl->ipl_dsize = len; ! 352: # if SOLARIS || defined(sun) || defined(linux) ! 353: uniqtime((struct timeval *)&ipl->ipl_sec); ! 354: # else ! 355: # if BSD >= 199306 || defined(__FreeBSD__) || defined(__sgi) ! 356: microtime((struct timeval *)&ipl->ipl_sec); ! 357: # endif ! 358: # endif ! 359: ! 360: /* ! 361: * Loop through all the items to be logged, copying each one to the ! 362: * buffer. Use bcopy for normal data or the mb_t copyout routine. ! 363: */ ! 364: for (i = 0, s = buf + sizeof(*ipl); i < cnt; i++) { ! 365: if (types[i] == 0) ! 366: bcopy(items[i], s, itemsz[i]); ! 367: else if (types[i] == 1) { ! 368: # if SOLARIS ! 369: copyout_mblk(items[i], 0, itemsz[i], s); ! 370: # else ! 371: m_copydata(items[i], 0, itemsz[i], s); ! 372: # endif ! 373: } ! 374: s += itemsz[i]; ! 375: } ! 376: MUTEX_ENTER(&ipl_mutex); ! 377: *iplh[dev] = ipl; ! 378: iplh[dev] = &ipl->ipl_next; ! 379: # if SOLARIS ! 380: cv_signal(&iplwait); ! 381: mutex_exit(&ipl_mutex); ! 382: # else ! 383: MUTEX_EXIT(&ipl_mutex); ! 384: # ifdef linux ! 385: wake_up_interruptible(&iplwait[dev]); ! 386: # else ! 387: wakeup(&iplh[dev]); ! 388: # endif ! 389: # endif ! 390: return 1; ! 391: } ! 392: ! 393: ! 394: int ipflog_read(unit, uio) ! 395: int unit; ! 396: struct uio *uio; ! 397: { ! 398: iplog_t *ipl; ! 399: int error = 0, dlen, copied; ! 400: # if defined(_KERNEL) && !SOLARIS ! 401: int s; ! 402: # endif ! 403: ! 404: /* ! 405: * Sanity checks. Make sure the minor # is valid and we're copying ! 406: * a valid chunk of data. ! 407: */ ! 408: if ((IPL_LOGMAX < unit) || (unit < 0)) ! 409: return ENXIO; ! 410: if (!uio->uio_resid) ! 411: return 0; ! 412: if ((uio->uio_resid < sizeof(iplog_t)) || ! 413: (uio->uio_resid > IPLLOGSIZE)) ! 414: return EINVAL; ! 415: ! 416: /* ! 417: * Lock the log so we can snapshot the variables. Wait for a signal ! 418: * if the log is empty. ! 419: */ ! 420: SPL_NET(s); ! 421: MUTEX_ENTER(&ipl_mutex); ! 422: ! 423: while (!iplused[unit] || !iplt[unit]) { ! 424: # if SOLARIS && defined(_KERNEL) ! 425: if (!cv_wait_sig(&iplwait, &ipl_mutex)) { ! 426: MUTEX_EXIT(&ipl_mutex); ! 427: return EINTR; ! 428: } ! 429: # else ! 430: # ifdef linux ! 431: interruptible_sleep_on(&iplwait[unit]); ! 432: if (current->signal & ~current->blocked) ! 433: return -EINTR; ! 434: # else ! 435: MUTEX_EXIT(&ipl_mutex); ! 436: SPL_X(s); ! 437: error = SLEEP(&iplh[unit], "ipl sleep"); ! 438: if (error) ! 439: return error; ! 440: SPL_NET(s); ! 441: MUTEX_ENTER(&ipl_mutex); ! 442: # endif /* linux */ ! 443: # endif /* SOLARIS */ ! 444: } ! 445: ! 446: # if BSD >= 199306 || defined(__FreeBSD__) ! 447: uio->uio_rw = UIO_READ; ! 448: # endif ! 449: ! 450: for (copied = 0; (ipl = iplt[unit]); copied += dlen) { ! 451: dlen = ipl->ipl_dsize; ! 452: if (dlen + sizeof(iplog_t) > uio->uio_resid) ! 453: break; ! 454: /* ! 455: * Don't hold the mutex over the uiomove call. ! 456: */ ! 457: iplt[unit] = ipl->ipl_next; ! 458: MUTEX_EXIT(&ipl_mutex); ! 459: SPL_X(s); ! 460: error = UIOMOVE((caddr_t)ipl, ipl->ipl_dsize, UIO_READ, uio); ! 461: KFREES((caddr_t)ipl, ipl->ipl_dsize); ! 462: if (error) ! 463: break; ! 464: SPL_NET(s); ! 465: MUTEX_ENTER(&ipl_mutex); ! 466: iplused[unit] -= dlen; ! 467: } ! 468: if (!ipl) { ! 469: iplused[unit] = 0; ! 470: iplh[unit] = &iplt[unit]; ! 471: } ! 472: ! 473: if (!error) { ! 474: MUTEX_EXIT(&ipl_mutex); ! 475: SPL_X(s); ! 476: } ! 477: #ifdef linux ! 478: if (!error) ! 479: return copied; ! 480: return -error; ! 481: #else ! 482: return error; ! 483: #endif ! 484: } ! 485: ! 486: ! 487: int ipflog_clear(unit) ! 488: int unit; ! 489: { ! 490: iplog_t *ipl; ! 491: int used; ! 492: ! 493: while ((ipl = iplt[unit])) { ! 494: iplt[unit] = ipl->ipl_next; ! 495: KFREES((caddr_t)ipl, ipl->ipl_dsize); ! 496: } ! 497: iplh[unit] = &iplt[unit]; ! 498: used = iplused[unit]; ! 499: iplused[unit] = 0; ! 500: iplcrc[unit] = 0; ! 501: return used; ! 502: } ! 503: #endif /* IPFILTER_LOG */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.