1 /* 2 * Copyright (C) 1997-2003 by Darren Reed. 3 * 4 * See the IPFILTER.LICENCE file for details on licencing. 5 * 6 * $Id: ip_log.c,v 2.75.2.7 2005/06/11 07:47:44 darrenr Exp $ 7 * 8 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 9 * Use is subject to license terms. 10 */ 11 12 #include <sys/param.h> 13 #if defined(KERNEL) || defined(_KERNEL) 14 # undef KERNEL 15 # undef _KERNEL 16 # define KERNEL 1 17 # define _KERNEL 1 18 #endif 19 #if defined(__NetBSD__) && (NetBSD >= 199905) && !defined(IPFILTER_LKM) && \ 20 defined(_KERNEL) 21 # include "opt_ipfilter_log.h" 22 #endif 23 #if defined(__FreeBSD__) && !defined(IPFILTER_LKM) 24 # if defined(_KERNEL) 25 # if defined(__FreeBSD_version) && (__FreeBSD_version >= 300000) 26 # include "opt_ipfilter.h" 27 # endif 28 # else 29 # include <osreldate.h> 30 # endif 31 #endif 32 #ifndef SOLARIS 33 # define SOLARIS (defined(sun) && (defined(__svr4__) || defined(__SVR4))) 34 #endif 35 #include <sys/errno.h> 36 #include <sys/types.h> 37 #include <sys/file.h> 38 #ifndef _KERNEL 39 # include <stdio.h> 40 # include <string.h> 41 # include <stdlib.h> 42 # include <ctype.h> 43 # define _KERNEL 44 # define KERNEL 45 # ifdef __OpenBSD__ 46 struct file; 47 # endif 48 # include <sys/uio.h> 49 # undef _KERNEL 50 # undef KERNEL 51 #endif 52 #if __FreeBSD_version >= 220000 && defined(_KERNEL) 53 # include <sys/fcntl.h> 54 # include <sys/filio.h> 55 #else 56 # include <sys/ioctl.h> 57 #endif 58 #include <sys/time.h> 59 #if defined(_KERNEL) 60 # include <sys/systm.h> 61 # if defined(NetBSD) && (__NetBSD_Version__ >= 104000000) 62 # include <sys/proc.h> 63 # endif 64 #endif /* _KERNEL */ 65 #if !SOLARIS && !defined(__hpux) && !defined(linux) 66 # if (NetBSD > 199609) || (OpenBSD > 199603) || (__FreeBSD_version >= 300000) 67 # include <sys/dirent.h> 68 # else 69 # include <sys/dir.h> 70 # endif 71 # include <sys/mbuf.h> 72 #else 73 # if !defined(__hpux) && defined(_KERNEL) 74 # include <sys/filio.h> 75 # include <sys/cred.h> 76 # include <sys/ddi.h> 77 # include <sys/sunddi.h> 78 # include <sys/ksynch.h> 79 # include <sys/kmem.h> 80 # include <sys/mkdev.h> 81 # include <sys/dditypes.h> 82 # include <sys/cmn_err.h> 83 # endif /* !__hpux */ 84 #endif /* !SOLARIS && !__hpux */ 85 #if !defined(linux) 86 # include <sys/protosw.h> 87 #endif 88 #include <sys/socket.h> 89 90 #include <net/if.h> 91 #ifdef sun 92 # include <net/af.h> 93 #endif 94 #if __FreeBSD_version >= 300000 95 # include <net/if_var.h> 96 #endif 97 #include <net/route.h> 98 #include <netinet/in.h> 99 #ifdef __sgi 100 # include <sys/ddi.h> 101 # ifdef IFF_DRVRLOCK /* IRIX6 */ 102 # include <sys/hashing.h> 103 # endif 104 #endif 105 #if !defined(__hpux) && !defined(linux) && \ 106 !(defined(__sgi) && !defined(IFF_DRVRLOCK)) /*IRIX<6*/ 107 # include <netinet/in_var.h> 108 #endif 109 #include <netinet/in_systm.h> 110 #include <netinet/ip.h> 111 #include <netinet/tcp.h> 112 #include <netinet/udp.h> 113 #include <netinet/ip_icmp.h> 114 #ifdef USE_INET6 115 # include <netinet/icmp6.h> 116 #endif 117 #if !defined(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_nat.h" 127 #include "netinet/ip_frag.h" 128 #include "netinet/ip_state.h" 129 #include "netinet/ip_auth.h" 130 #include "netinet/ipf_stack.h" 131 #if (__FreeBSD_version >= 300000) || defined(__NetBSD__) 132 # include <sys/malloc.h> 133 #endif 134 /* END OF INCLUDES */ 135 136 #ifdef IPFILTER_LOG 137 138 # if defined(IPL_SELECT) 139 # include <machine/sys/user.h> 140 # include <sys/kthread_iface.h> 141 # define READ_COLLISION 0x001 142 143 iplog_select_t iplog_ss[IPL_LOGMAX+1]; 144 145 extern int selwait; 146 # endif /* IPL_SELECT */ 147 148 /* ipl_magic never changes */ 149 int ipl_magic[IPL_LOGSIZE] = { IPL_MAGIC, IPL_MAGIC_NAT, IPL_MAGIC_STATE, 150 IPL_MAGIC, IPL_MAGIC, IPL_MAGIC, 151 IPL_MAGIC, IPL_MAGIC }; 152 153 /* ------------------------------------------------------------------------ */ 154 /* Function: fr_loginit */ 155 /* Returns: int - 0 == success (always returned) */ 156 /* Parameters: Nil */ 157 /* */ 158 /* Initialise log buffers & pointers. Also iniialised the CRC to a local */ 159 /* secret for use in calculating the "last log checksum". */ 160 /* ------------------------------------------------------------------------ */ 161 int fr_loginit(ifs) 162 ipf_stack_t *ifs; 163 { 164 int i; 165 166 for (i = IPL_LOGMAX; i >= 0; i--) { 167 ifs->ifs_iplt[i] = NULL; 168 ifs->ifs_ipll[i] = NULL; 169 ifs->ifs_iplh[i] = &ifs->ifs_iplt[i]; 170 ifs->ifs_iplused[i] = 0; 171 bzero((char *)&ifs->ifs_iplcrc[i], sizeof(ifs->ifs_iplcrc[i])); 172 # ifdef IPL_SELECT 173 iplog_ss[i].read_waiter = 0; 174 iplog_ss[i].state = 0; 175 # endif 176 # if defined(linux) && defined(_KERNEL) 177 init_waitqueue_head(iplh_linux + i); 178 # endif 179 } 180 181 # if SOLARIS && defined(_KERNEL) 182 cv_init(&ifs->ifs_iplwait, "ipl condvar", CV_DRIVER, NULL); 183 # endif 184 MUTEX_INIT(&ifs->ifs_ipl_mutex, "ipf log mutex"); 185 186 ifs->ifs_ipl_log_init = 1; 187 188 return 0; 189 } 190 191 192 /* ------------------------------------------------------------------------ */ 193 /* Function: fr_logunload */ 194 /* Returns: Nil */ 195 /* Parameters: Nil */ 196 /* */ 197 /* Clean up any log data that has accumulated without being read. */ 198 /* ------------------------------------------------------------------------ */ 199 void fr_logunload(ifs) 200 ipf_stack_t *ifs; 201 { 202 int i; 203 204 if (ifs->ifs_ipl_log_init == 0) 205 return; 206 207 for (i = IPL_LOGMAX; i >= 0; i--) 208 (void) ipflog_clear(i, ifs); 209 210 # if SOLARIS && defined(_KERNEL) 211 cv_destroy(&ifs->ifs_iplwait); 212 # endif 213 MUTEX_DESTROY(&ifs->ifs_ipl_mutex); 214 215 ifs->ifs_ipl_log_init = 0; 216 } 217 218 219 /* ------------------------------------------------------------------------ */ 220 /* Function: ipflog */ 221 /* Returns: int - 0 == success, -1 == failure */ 222 /* Parameters: fin(I) - pointer to packet information */ 223 /* flags(I) - flags from filter rules */ 224 /* */ 225 /* Create a log record for a packet given that it has been triggered by a */ 226 /* rule (or the default setting). Calculate the transport protocol header */ 227 /* size using predetermined size of a couple of popular protocols and thus */ 228 /* how much data to copy into the log, including part of the data body if */ 229 /* requested. */ 230 /* ------------------------------------------------------------------------ */ 231 int ipflog(fin, flags) 232 fr_info_t *fin; 233 u_int flags; 234 { 235 register size_t hlen; 236 int types[2], mlen; 237 size_t sizes[2]; 238 void *ptrs[2]; 239 ipflog_t ipfl; 240 u_char p; 241 mb_t *m; 242 # if SOLARIS && defined(_KERNEL) 243 net_handle_t nif; 244 void *ifp; 245 # else 246 # if defined(__hpux) && defined(_KERNEL) 247 qif_t *ifp; 248 # else 249 struct ifnet *ifp; 250 # endif 251 # endif /* SOLARIS */ 252 ipf_stack_t *ifs = fin->fin_ifs; 253 254 ipfl.fl_nattag.ipt_num[0] = 0; 255 m = fin->fin_m; 256 ifp = fin->fin_ifp; 257 hlen = fin->fin_hlen; 258 /* 259 * calculate header size. 260 */ 261 if (fin->fin_off == 0) { 262 p = fin->fin_fi.fi_p; 263 if (p == IPPROTO_TCP) 264 hlen += MIN(sizeof(tcphdr_t), fin->fin_dlen); 265 else if (p == IPPROTO_UDP) 266 hlen += MIN(sizeof(udphdr_t), fin->fin_dlen); 267 else if (p == IPPROTO_ICMP) { 268 struct icmp *icmp; 269 270 icmp = (struct icmp *)fin->fin_dp; 271 272 /* 273 * For ICMP, if the packet is an error packet, also 274 * include the information about the packet which 275 * caused the error. 276 */ 277 switch (icmp->icmp_type) 278 { 279 case ICMP_UNREACH : 280 case ICMP_SOURCEQUENCH : 281 case ICMP_REDIRECT : 282 case ICMP_TIMXCEED : 283 case ICMP_PARAMPROB : 284 hlen += MIN(sizeof(struct icmp) + 8, 285 fin->fin_dlen); 286 break; 287 default : 288 hlen += MIN(sizeof(struct icmp), 289 fin->fin_dlen); 290 break; 291 } 292 } 293 # ifdef USE_INET6 294 else if (p == IPPROTO_ICMPV6) { 295 struct icmp6_hdr *icmp; 296 297 icmp = (struct icmp6_hdr *)fin->fin_dp; 298 299 /* 300 * For ICMPV6, if the packet is an error packet, also 301 * include the information about the packet which 302 * caused the error. 303 */ 304 if (icmp->icmp6_type < 128) { 305 hlen += MIN(sizeof(struct icmp6_hdr) + 8, 306 fin->fin_dlen); 307 } else { 308 hlen += MIN(sizeof(struct icmp6_hdr), 309 fin->fin_dlen); 310 } 311 } 312 # endif 313 } 314 /* 315 * Get the interface number and name to which this packet is 316 * currently associated. 317 */ 318 # if SOLARIS && defined(_KERNEL) 319 ipfl.fl_unit = (u_int)0; 320 nif = NULL; 321 if (fin->fin_fi.fi_v == 4) 322 nif = ifs->ifs_ipf_ipv4; 323 else if (fin->fin_fi.fi_v == 6) 324 nif = ifs->ifs_ipf_ipv6; 325 if (nif != NULL) { 326 if (net_getifname(nif, (phy_if_t)ifp, 327 ipfl.fl_ifname, sizeof(ipfl.fl_ifname)) != 0) 328 return (-1); 329 } 330 331 # else 332 # if defined(__hpux) && defined(_KERNEL) 333 ipfl.fl_unit = (u_int)0; 334 (void) strncpy(ipfl.fl_ifname, IFNAME(ifp), sizeof(ipfl.fl_ifname)); 335 # else 336 # if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199603)) || \ 337 (defined(OpenBSD) && (OpenBSD >= 199603)) || defined(linux) || \ 338 (defined(__FreeBSD__) && (__FreeBSD_version >= 501113)) 339 COPYIFNAME(ifp, ipfl.fl_ifname); 340 # else 341 ipfl.fl_unit = (u_int)ifp->if_unit; 342 # if defined(_KERNEL) 343 if ((ipfl.fl_ifname[0] = ifp->if_name[0])) 344 if ((ipfl.fl_ifname[1] = ifp->if_name[1])) 345 if ((ipfl.fl_ifname[2] = ifp->if_name[2])) 346 ipfl.fl_ifname[3] = ifp->if_name[3]; 347 # else 348 (void) strncpy(ipfl.fl_ifname, IFNAME(ifp), sizeof(ipfl.fl_ifname)); 349 ipfl.fl_ifname[sizeof(ipfl.fl_ifname) - 1] = '\0'; 350 # endif 351 # endif 352 # endif /* __hpux */ 353 # endif /* SOLARIS */ 354 mlen = fin->fin_plen - hlen; 355 if (!ifs->ifs_ipl_logall) { 356 mlen = (flags & FR_LOGBODY) ? MIN(mlen, 128) : 0; 357 } else if ((flags & FR_LOGBODY) == 0) { 358 mlen = 0; 359 } 360 if (mlen < 0) 361 mlen = 0; 362 ipfl.fl_plen = (u_char)mlen; 363 ipfl.fl_hlen = (u_char)hlen; 364 ipfl.fl_rule = fin->fin_rule; 365 (void) strncpy(ipfl.fl_group, fin->fin_group, FR_GROUPLEN); 366 if (fin->fin_fr != NULL) { 367 ipfl.fl_loglevel = fin->fin_fr->fr_loglevel; 368 ipfl.fl_logtag = fin->fin_fr->fr_logtag; 369 } else { 370 ipfl.fl_loglevel = 0xffff; 371 ipfl.fl_logtag = FR_NOLOGTAG; 372 } 373 if (fin->fin_nattag != NULL) 374 bcopy(fin->fin_nattag, (void *)&ipfl.fl_nattag, 375 sizeof(ipfl.fl_nattag)); 376 ipfl.fl_flags = flags; 377 ipfl.fl_dir = fin->fin_out; 378 ipfl.fl_lflags = fin->fin_flx; 379 ptrs[0] = (void *)&ipfl; 380 sizes[0] = sizeof(ipfl); 381 types[0] = 0; 382 # if defined(MENTAT) && defined(_KERNEL) 383 /* 384 * Are we copied from the mblk or an aligned array ? 385 */ 386 if (fin->fin_ip == (ip_t *)m->b_rptr) { 387 ptrs[1] = m; 388 sizes[1] = hlen + mlen; 389 types[1] = 1; 390 } else { 391 ptrs[1] = fin->fin_ip; 392 sizes[1] = hlen + mlen; 393 types[1] = 0; 394 } 395 # else 396 ptrs[1] = m; 397 sizes[1] = hlen + mlen; 398 types[1] = 1; 399 # endif /* MENTAT */ 400 return ipllog(IPL_LOGIPF, fin, ptrs, sizes, types, 2, fin->fin_ifs); 401 } 402 403 404 /* ------------------------------------------------------------------------ */ 405 /* Function: ipllog */ 406 /* Returns: int - 0 == success, -1 == failure */ 407 /* Parameters: dev(I) - device that owns this log record */ 408 /* fin(I) - pointer to packet information */ 409 /* items(I) - array of pointers to log data */ 410 /* itemsz(I) - array of size of valid memory pointed to */ 411 /* types(I) - type of data pointed to by items pointers */ 412 /* cnt(I) - number of elements in arrays items/itemsz/types */ 413 /* */ 414 /* Takes an array of parameters and constructs one record to include the */ 415 /* miscellaneous packet information, as well as packet data, for reading */ 416 /* from the log device. */ 417 /* ------------------------------------------------------------------------ */ 418 int ipllog(dev, fin, items, itemsz, types, cnt, ifs) 419 int dev; 420 fr_info_t *fin; 421 void **items; 422 size_t *itemsz; 423 int *types, cnt; 424 ipf_stack_t *ifs; 425 { 426 caddr_t buf, ptr; 427 iplog_t *ipl; 428 size_t len; 429 int i; 430 SPL_INT(s); 431 432 /* 433 * Check to see if this log record has a CRC which matches the last 434 * record logged. If it does, just up the count on the previous one 435 * rather than create a new one. 436 */ 437 if (ifs->ifs_ipl_suppress) { 438 MUTEX_ENTER(&ifs->ifs_ipl_mutex); 439 if ((fin != NULL) && (fin->fin_off == 0)) { 440 if ((ifs->ifs_ipll[dev] != NULL) && 441 bcmp((char *)fin, (char *)&ifs->ifs_iplcrc[dev], 442 FI_LCSIZE) == 0) { 443 ifs->ifs_ipll[dev]->ipl_count++; 444 MUTEX_EXIT(&ifs->ifs_ipl_mutex); 445 return 0; 446 } 447 bcopy((char *)fin, (char *)&ifs->ifs_iplcrc[dev], 448 FI_LCSIZE); 449 } else 450 bzero((char *)&ifs->ifs_iplcrc[dev], FI_CSIZE); 451 MUTEX_EXIT(&ifs->ifs_ipl_mutex); 452 } 453 454 /* 455 * Get the total amount of data to be logged. 456 */ 457 for (i = 0, len = sizeof(iplog_t); i < cnt; i++) 458 len += itemsz[i]; 459 460 /* 461 * check that we have space to record this information and can 462 * allocate that much. 463 */ 464 KMALLOCS(buf, caddr_t, len); 465 if (buf == NULL) 466 return -1; 467 SPL_NET(s); 468 MUTEX_ENTER(&ifs->ifs_ipl_mutex); 469 if ((ifs->ifs_iplused[dev] + len) > IPFILTER_LOGSIZE) { 470 MUTEX_EXIT(&ifs->ifs_ipl_mutex); 471 SPL_X(s); 472 KFREES(buf, len); 473 return -1; 474 } 475 ifs->ifs_iplused[dev] += len; 476 MUTEX_EXIT(&ifs->ifs_ipl_mutex); 477 SPL_X(s); 478 479 /* 480 * advance the log pointer to the next empty record and deduct the 481 * amount of space we're going to use. 482 */ 483 ipl = (iplog_t *)buf; 484 ipl->ipl_magic = ipl_magic[dev]; 485 ipl->ipl_count = 1; 486 ipl->ipl_next = NULL; 487 ipl->ipl_dsize = len; 488 #ifdef _KERNEL 489 GETKTIME(&ipl->ipl_sec); 490 #else 491 ipl->ipl_sec = 0; 492 ipl->ipl_usec = 0; 493 #endif 494 495 /* 496 * Loop through all the items to be logged, copying each one to the 497 * buffer. Use bcopy for normal data or the mb_t copyout routine. 498 */ 499 for (i = 0, ptr = buf + sizeof(*ipl); i < cnt; i++) { 500 if (types[i] == 0) { 501 bcopy(items[i], ptr, itemsz[i]); 502 } else if (types[i] == 1) { 503 COPYDATA(items[i], 0, itemsz[i], ptr); 504 } 505 ptr += itemsz[i]; 506 } 507 SPL_NET(s); 508 MUTEX_ENTER(&ifs->ifs_ipl_mutex); 509 ifs->ifs_ipll[dev] = ipl; 510 *ifs->ifs_iplh[dev] = ipl; 511 ifs->ifs_iplh[dev] = &ipl->ipl_next; 512 513 /* 514 * Now that the log record has been completed and added to the queue, 515 * wake up any listeners who may want to read it. 516 */ 517 # if SOLARIS && defined(_KERNEL) 518 cv_signal(&ifs->ifs_iplwait); 519 MUTEX_EXIT(&ifs->ifs_ipl_mutex); 520 # else 521 MUTEX_EXIT(&ifs->ifs_ipl_mutex); 522 WAKEUP(&ifs->ifs_iplh, dev); 523 # endif 524 SPL_X(s); 525 # ifdef IPL_SELECT 526 iplog_input_ready(dev); 527 # endif 528 return 0; 529 } 530 531 532 /* ------------------------------------------------------------------------ */ 533 /* Function: ipflog_read */ 534 /* Returns: int - 0 == success, else error value. */ 535 /* Parameters: unit(I) - device we are reading from */ 536 /* uio(O) - pointer to information about where to store data */ 537 /* */ 538 /* Called to handle a read on an IPFilter device. Returns only complete */ 539 /* log messages - will not partially copy a log record out to userland. */ 540 /* */ 541 /* NOTE: This function will block and wait for a signal to return data if */ 542 /* there is none present. Asynchronous I/O is not implemented. */ 543 /* ------------------------------------------------------------------------ */ 544 int ipflog_read(unit, uio, ifs) 545 minor_t unit; 546 struct uio *uio; 547 ipf_stack_t *ifs; 548 { 549 size_t dlen, copied; 550 int error = 0; 551 iplog_t *ipl; 552 SPL_INT(s); 553 554 /* 555 * Sanity checks. Make sure the minor # is valid and we're copying 556 * a valid chunk of data. 557 */ 558 if (IPL_LOGMAX < unit) 559 return ENXIO; 560 if (uio->uio_resid == 0) 561 return 0; 562 if ((uio->uio_resid < sizeof(iplog_t)) || 563 (uio->uio_resid > ifs->ifs_ipl_logsize)) 564 return EINVAL; 565 566 /* 567 * Lock the log so we can snapshot the variables. Wait for a signal 568 * if the log is empty. 569 */ 570 SPL_NET(s); 571 MUTEX_ENTER(&ifs->ifs_ipl_mutex); 572 573 while (ifs->ifs_iplt[unit] == NULL) { 574 # if SOLARIS && defined(_KERNEL) 575 if (!cv_wait_sig(&ifs->ifs_iplwait, &ifs->ifs_ipl_mutex.ipf_lk)) { 576 MUTEX_EXIT(&ifs->ifs_ipl_mutex); 577 return EINTR; 578 } 579 # else 580 # if defined(__hpux) && defined(_KERNEL) 581 lock_t *l; 582 583 # ifdef IPL_SELECT 584 if (uio->uio_fpflags & (FNBLOCK|FNDELAY)) { 585 /* this is no blocking system call */ 586 MUTEX_EXIT(&ifs->ifs_ipl_mutex); 587 return 0; 588 } 589 # endif 590 591 MUTEX_EXIT(&ifs->ifs_ipl_mutex); 592 l = get_sleep_lock(&ifs->ifs_iplh[unit]); 593 error = sleep(&ifs->ifs_iplh[unit], PZERO+1); 594 spinunlock(l); 595 # else 596 # if defined(__osf__) && defined(_KERNEL) 597 error = mpsleep(&ifs->ifs_iplh[unit], PSUSP|PCATCH, "iplread", 0, 598 &ifs->ifs_ipl_mutex, MS_LOCK_SIMPLE); 599 # else 600 MUTEX_EXIT(&ifs->ifs_ipl_mutex); 601 SPL_X(s); 602 error = SLEEP(&ifs->ifs_iplh[unit], "ipl sleep"); 603 # endif /* __osf__ */ 604 # endif /* __hpux */ 605 if (error) 606 return error; 607 SPL_NET(s); 608 MUTEX_ENTER(&ifs->ifs_ipl_mutex); 609 # endif /* SOLARIS */ 610 } 611 612 # if (BSD >= 199101) || defined(__FreeBSD__) || defined(__osf__) 613 uio->uio_rw = UIO_READ; 614 # endif 615 616 for (copied = 0; ((ipl = ifs->ifs_iplt[unit]) != NULL); copied += dlen) { 617 dlen = ipl->ipl_dsize; 618 if (dlen > uio->uio_resid) 619 break; 620 /* 621 * Don't hold the mutex over the uiomove call. 622 */ 623 ifs->ifs_iplt[unit] = ipl->ipl_next; 624 ifs->ifs_iplused[unit] -= dlen; 625 if (ifs->ifs_iplt[unit] == NULL) { 626 ifs->ifs_iplh[unit] = &ifs->ifs_iplt[unit]; 627 ifs->ifs_ipll[unit] = NULL; 628 } 629 MUTEX_EXIT(&ifs->ifs_ipl_mutex); 630 SPL_X(s); 631 error = UIOMOVE((caddr_t)ipl, dlen, UIO_READ, uio); 632 if (error) { 633 SPL_NET(s); 634 MUTEX_ENTER(&ifs->ifs_ipl_mutex); 635 ifs->ifs_iplused[unit] += dlen; 636 ipl->ipl_next = ifs->ifs_iplt[unit]; 637 ifs->ifs_iplt[unit] = ipl; 638 ifs->ifs_ipll[unit] = ipl; 639 if (ifs->ifs_iplh[unit] == &ifs->ifs_iplt[unit]) { 640 *ifs->ifs_iplh[unit] = ipl; 641 ifs->ifs_iplh[unit] = &ipl->ipl_next; 642 } 643 break; 644 } 645 MUTEX_ENTER(&ifs->ifs_ipl_mutex); 646 KFREES((caddr_t)ipl, dlen); 647 SPL_NET(s); 648 } 649 650 MUTEX_EXIT(&ifs->ifs_ipl_mutex); 651 SPL_X(s); 652 return error; 653 } 654 655 656 /* ------------------------------------------------------------------------ */ 657 /* Function: ipflog_clear */ 658 /* Returns: int - number of log bytes cleared. */ 659 /* Parameters: unit(I) - device we are reading from */ 660 /* */ 661 /* Deletes all queued up log records for a given output device. */ 662 /* ------------------------------------------------------------------------ */ 663 int ipflog_clear(unit, ifs) 664 minor_t unit; 665 ipf_stack_t *ifs; 666 { 667 iplog_t *ipl; 668 int used; 669 SPL_INT(s); 670 671 SPL_NET(s); 672 MUTEX_ENTER(&ifs->ifs_ipl_mutex); 673 while ((ipl = ifs->ifs_iplt[unit]) != NULL) { 674 ifs->ifs_iplt[unit] = ipl->ipl_next; 675 KFREES((caddr_t)ipl, ipl->ipl_dsize); 676 } 677 ifs->ifs_iplh[unit] = &ifs->ifs_iplt[unit]; 678 ifs->ifs_ipll[unit] = NULL; 679 used = ifs->ifs_iplused[unit]; 680 ifs->ifs_iplused[unit] = 0; 681 bzero((char *)&ifs->ifs_iplcrc[unit], FI_CSIZE); 682 MUTEX_EXIT(&ifs->ifs_ipl_mutex); 683 SPL_X(s); 684 return used; 685 } 686 #endif /* IPFILTER_LOG */ 687