The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/netinet/ip_log.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

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

Cache object: 6718ace5aecb90eb38d9208d6af56472


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.