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/netpfil/ipfilter/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 /*      $FreeBSD$       */
    2 
    3 /*
    4  * Copyright (C) 2012 by Darren Reed.
    5  *
    6  * See the IPFILTER.LICENCE file for details on licencing.
    7  *
    8  * $FreeBSD$
    9  * Id: ip_log.c,v 2.75.2.19 2007/09/09 11:32:06 darrenr Exp $
   10  */
   11 #include <sys/param.h>
   12 #if defined(KERNEL) || defined(_KERNEL)
   13 # undef KERNEL
   14 # undef _KERNEL
   15 # define        KERNEL  1
   16 # define        _KERNEL 1
   17 #endif
   18 #if defined(__FreeBSD__) && !defined(_KERNEL)
   19 # include <osreldate.h>
   20 #endif
   21 #ifndef SOLARIS
   22 # if defined(sun) && defined(__SVR4)
   23 #  define       SOLARIS         1
   24 # else
   25 #  define       SOLARIS         0
   26 # endif
   27 #endif
   28 #include <sys/errno.h>
   29 #include <sys/types.h>
   30 #include <sys/file.h>
   31 #ifndef _KERNEL
   32 # include <stdio.h>
   33 # include <string.h>
   34 # include <stdlib.h>
   35 # include <ctype.h>
   36 # define _KERNEL
   37 # define KERNEL
   38 # include <sys/uio.h>
   39 # undef _KERNEL
   40 # undef KERNEL
   41 #endif
   42 #if defined(__FreeBSD__) && defined(_KERNEL)
   43 # include <sys/fcntl.h>
   44 # include <sys/filio.h>
   45 #else
   46 # include <sys/ioctl.h>
   47 #endif
   48 #include <sys/time.h>
   49 #if defined(_KERNEL)
   50 # include <sys/systm.h>
   51 # if (defined(NetBSD) && (__NetBSD_Version__ >= 104000000))
   52 #  include <sys/proc.h>
   53 # endif
   54 #endif /* _KERNEL */
   55 # if defined(NetBSD) || defined(__FreeBSD__)
   56 #  include <sys/dirent.h>
   57 # include <sys/mbuf.h>
   58 # include <sys/select.h>
   59 # endif
   60 # if defined(__FreeBSD__)
   61 #  include <sys/selinfo.h>
   62 # endif
   63 #if SOLARIS && defined(_KERNEL)
   64 #  include <sys/filio.h>
   65 #  include <sys/cred.h>
   66 #  include <sys/ddi.h>
   67 #  include <sys/sunddi.h>
   68 #  include <sys/ksynch.h>
   69 #  include <sys/kmem.h>
   70 #  include <sys/mkdev.h>
   71 #  include <sys/dditypes.h>
   72 #  include <sys/cmn_err.h>
   73 #endif /* SOLARIS && _KERNEL */
   74 # include <sys/protosw.h>
   75 #include <sys/socket.h>
   76 
   77 #include <net/if.h>
   78 #ifdef sun
   79 # include <net/af.h>
   80 #endif
   81 #if defined(__FreeBSD__)
   82 # include <net/if_var.h>
   83 #endif
   84 #include <netinet/in.h>
   85 # include <netinet/in_var.h>
   86 #include <netinet/in_systm.h>
   87 #include <netinet/ip.h>
   88 #include <netinet/tcp.h>
   89 #include <netinet/udp.h>
   90 #include <netinet/ip_icmp.h>
   91 #ifdef USE_INET6
   92 # include <netinet/icmp6.h>
   93 #endif
   94 # include <netinet/ip_var.h>
   95 #ifndef _KERNEL
   96 # include <syslog.h>
   97 #endif
   98 #include "netinet/ip_compat.h"
   99 #include <netinet/tcpip.h>
  100 #include "netinet/ip_fil.h"
  101 #include "netinet/ip_nat.h"
  102 #include "netinet/ip_frag.h"
  103 #include "netinet/ip_state.h"
  104 #include "netinet/ip_auth.h"
  105 #if defined(__FreeBSD__) || defined(__NetBSD__)
  106 # include <sys/malloc.h>
  107 #endif
  108 /* END OF INCLUDES */
  109 
  110 #ifdef  IPFILTER_LOG
  111 
  112 typedef struct ipf_log_softc_s {
  113         ipfmutex_t      ipl_mutex[IPL_LOGSIZE];
  114 # if SOLARIS && defined(_KERNEL)
  115         kcondvar_t      ipl_wait[IPL_LOGSIZE];
  116 # endif
  117         iplog_t         **iplh[IPL_LOGSIZE];
  118         iplog_t         *iplt[IPL_LOGSIZE];
  119         iplog_t         *ipll[IPL_LOGSIZE];
  120         u_long          ipl_logfail[IPL_LOGSIZE];
  121         u_long          ipl_logok[IPL_LOGSIZE];
  122         fr_info_t       ipl_crc[IPL_LOGSIZE];
  123         u_32_t          ipl_counter[IPL_LOGSIZE];
  124         int             ipl_suppress;
  125         int             ipl_logall;
  126         int             ipl_log_init;
  127         int             ipl_logsize;
  128         int             ipl_used[IPL_LOGSIZE];
  129         int             ipl_magic[IPL_LOGSIZE];
  130         ipftuneable_t   *ipf_log_tune;
  131         int             ipl_readers[IPL_LOGSIZE];
  132 } ipf_log_softc_t;
  133 
  134 static int magic[IPL_LOGSIZE] = { IPL_MAGIC, IPL_MAGIC_NAT, IPL_MAGIC_STATE,
  135                                   IPL_MAGIC, IPL_MAGIC, IPL_MAGIC,
  136                                   IPL_MAGIC, IPL_MAGIC };
  137 
  138 static ipftuneable_t ipf_log_tuneables[] = {
  139         /* log */
  140         { { (void *)offsetof(ipf_log_softc_t, ipl_suppress) },
  141                 "log_suppress",         0,      1,
  142                 stsizeof(ipf_log_softc_t, ipl_suppress),
  143                 0,                      NULL,   NULL },
  144         { { (void *)offsetof(ipf_log_softc_t, ipl_logall) },
  145                 "log_all",              0,      1,
  146                 stsizeof(ipf_log_softc_t, ipl_logall),
  147                 0,                      NULL,   NULL },
  148         { { (void *)offsetof(ipf_log_softc_t, ipl_logsize) },
  149                 "log_size",             0,      0x80000,
  150                 stsizeof(ipf_log_softc_t, ipl_logsize),
  151                 0,                      NULL,   NULL },
  152         { { NULL },             NULL,                   0,      0,
  153                 0,
  154                 0,                      NULL,   NULL }
  155 };
  156 
  157 
  158 int
  159 ipf_log_main_load(void)
  160 {
  161         return (0);
  162 }
  163 
  164 
  165 int
  166 ipf_log_main_unload(void)
  167 {
  168         return (0);
  169 }
  170 
  171 /* ------------------------------------------------------------------------ */
  172 /* Function:    ipf_log_soft_create                                         */
  173 /* Returns:     void * - NULL = failure, else pointer to log context data   */
  174 /* Parameters:  softc(I) - pointer to soft context main structure           */
  175 /*                                                                          */
  176 /* Initialise log buffers & pointers.  Also iniialised the CRC to a local   */
  177 /* secret for use in calculating the "last log checksum".                   */
  178 /* ------------------------------------------------------------------------ */
  179 void *
  180 ipf_log_soft_create(ipf_main_softc_t *softc)
  181 {
  182         ipf_log_softc_t *softl;
  183         int i;
  184 
  185         KMALLOC(softl, ipf_log_softc_t *);
  186         if (softl == NULL)
  187                 return (NULL);
  188 
  189         bzero((char *)softl, sizeof(*softl));
  190         bcopy((char *)magic, (char *)softl->ipl_magic, sizeof(magic));
  191 
  192         softl->ipf_log_tune = ipf_tune_array_copy(softl,
  193                                                   sizeof(ipf_log_tuneables),
  194                                                   ipf_log_tuneables);
  195         if (softl->ipf_log_tune == NULL) {
  196                 ipf_log_soft_destroy(softc, softl);
  197                 return (NULL);
  198         }
  199         if (ipf_tune_array_link(softc, softl->ipf_log_tune) == -1) {
  200                 ipf_log_soft_destroy(softc, softl);
  201                 return (NULL);
  202         }
  203 
  204         for (i = IPL_LOGMAX; i >= 0; i--) {
  205                 MUTEX_INIT(&softl->ipl_mutex[i], "ipf log mutex");
  206         }
  207 
  208         softl->ipl_suppress = 1;
  209         softl->ipl_logall = 0;
  210         softl->ipl_log_init = 0;
  211         softl->ipl_logsize = IPFILTER_LOGSIZE;
  212 
  213         return (softl);
  214 }
  215 
  216 /* ------------------------------------------------------------------------ */
  217 /* Function:    ipf_log_soft_init                                           */
  218 /* Returns:     int - 0 == success (always returned)                        */
  219 /* Parameters:  softc(I) - pointer to soft context main structure           */
  220 /*                                                                          */
  221 /* Initialise log buffers & pointers.  Also iniialised the CRC to a local   */
  222 /* secret for use in calculating the "last log checksum".                   */
  223 /* ------------------------------------------------------------------------ */
  224 int
  225 ipf_log_soft_init(ipf_main_softc_t *softc, void *arg)
  226 {
  227         ipf_log_softc_t *softl = arg;
  228         int i;
  229 
  230         for (i = IPL_LOGMAX; i >= 0; i--) {
  231                 softl->iplt[i] = NULL;
  232                 softl->ipll[i] = NULL;
  233                 softl->iplh[i] = &softl->iplt[i];
  234                 bzero((char *)&softl->ipl_crc[i], sizeof(softl->ipl_crc[i]));
  235         }
  236 
  237 
  238         softl->ipl_log_init = 1;
  239 
  240         return (0);
  241 }
  242 
  243 
  244 /* ------------------------------------------------------------------------ */
  245 /* Function:    ipf_log_soft_fini                                           */
  246 /* Parameters:  softc(I) - pointer to soft context main structure           */
  247 /*              arg(I)   - pointer to log context structure                 */
  248 /*                                                                          */
  249 /* Clean up any log data that has accumulated without being read.           */
  250 /* ------------------------------------------------------------------------ */
  251 int
  252 ipf_log_soft_fini(ipf_main_softc_t *softc, void *arg)
  253 {
  254         ipf_log_softc_t *softl = arg;
  255         int i;
  256 
  257         if (softl->ipl_log_init == 0)
  258                 return (0);
  259 
  260         softl->ipl_log_init = 0;
  261 
  262         for (i = IPL_LOGMAX; i >= 0; i--) {
  263                 (void) ipf_log_clear(softc, i);
  264 
  265                 /*
  266                  * This is a busy-wait loop so as to avoid yet another lock
  267                  * to wait on.
  268                  */
  269                 MUTEX_ENTER(&softl->ipl_mutex[i]);
  270                 while (softl->ipl_readers[i] > 0) {
  271 # if SOLARIS && defined(_KERNEL)
  272                         cv_broadcast(&softl->ipl_wait[i]);
  273                         MUTEX_EXIT(&softl->ipl_mutex[i]);
  274                         delay(100);
  275                         pollwakeup(&softc->ipf_poll_head[i], POLLRDNORM);
  276 # else
  277                         MUTEX_EXIT(&softl->ipl_mutex[i]);
  278                         WAKEUP(softl->iplh, i);
  279                         POLLWAKEUP(i);
  280 # endif
  281                         MUTEX_ENTER(&softl->ipl_mutex[i]);
  282                 }
  283                 MUTEX_EXIT(&softl->ipl_mutex[i]);
  284         }
  285 
  286         return (0);
  287 }
  288 
  289 
  290 /* ------------------------------------------------------------------------ */
  291 /* Function:    ipf_log_soft_destroy                                        */
  292 /* Parameters:  softc(I) - pointer to soft context main structure           */
  293 /*              arg(I)   - pointer to log context structure                 */
  294 /*                                                                          */
  295 /* When this function is called, it is expected that there are no longer    */
  296 /* any threads active in the reading code path or the logging code path.    */
  297 /* ------------------------------------------------------------------------ */
  298 void
  299 ipf_log_soft_destroy(ipf_main_softc_t *softc, void *arg)
  300 {
  301         ipf_log_softc_t *softl = arg;
  302         int i;
  303 
  304         for (i = IPL_LOGMAX; i >= 0; i--) {
  305 # if SOLARIS && defined(_KERNEL)
  306                 cv_destroy(&softl->ipl_wait[i]);
  307 # endif
  308                 MUTEX_DESTROY(&softl->ipl_mutex[i]);
  309         }
  310 
  311         if (softl->ipf_log_tune != NULL) {
  312                 ipf_tune_array_unlink(softc, softl->ipf_log_tune);
  313                 KFREES(softl->ipf_log_tune, sizeof(ipf_log_tuneables));
  314                 softl->ipf_log_tune = NULL;
  315         }
  316 
  317         KFREE(softl);
  318 }
  319 
  320 
  321 /* ------------------------------------------------------------------------ */
  322 /* Function:    ipf_log_pkt                                                 */
  323 /* Returns:     int      - 0 == success, -1 == failure                      */
  324 /* Parameters:  fin(I)   - pointer to packet information                    */
  325 /*              flags(I) - flags from filter rules                          */
  326 /*                                                                          */
  327 /* Create a log record for a packet given that it has been triggered by a   */
  328 /* rule (or the default setting).  Calculate the transport protocol header  */
  329 /* size using predetermined size of a couple of popular protocols and thus  */
  330 /* how much data to copy into the log, including part of the data body if   */
  331 /* requested.                                                               */
  332 /* ------------------------------------------------------------------------ */
  333 int
  334 ipf_log_pkt(fr_info_t *fin, u_int flags)
  335 {
  336         ipf_main_softc_t *softc = fin->fin_main_soft;
  337         ipf_log_softc_t *softl = softc->ipf_log_soft;
  338         register size_t hlen;
  339         int types[2], mlen;
  340         size_t sizes[2];
  341         void *ptrs[2];
  342         ipflog_t ipfl;
  343         u_char p;
  344         mb_t *m;
  345 # if SOLARIS && defined(_KERNEL) && !defined(FW_HOOKS)
  346         qif_t *ifp;
  347 # else
  348         struct ifnet *ifp;
  349 # endif /* SOLARIS */
  350 
  351         m = fin->fin_m;
  352         if (m == NULL)
  353                 return (-1);
  354 
  355         ipfl.fl_nattag.ipt_num[0] = 0;
  356         ifp = fin->fin_ifp;
  357         hlen = (char *)fin->fin_dp - (char *)fin->fin_ip;
  358 
  359         /*
  360          * calculate header size.
  361          */
  362         if (fin->fin_off == 0) {
  363                 p = fin->fin_fi.fi_p;
  364                 if (p == IPPROTO_TCP)
  365                         hlen += MIN(sizeof(tcphdr_t), fin->fin_dlen);
  366                 else if (p == IPPROTO_UDP)
  367                         hlen += MIN(sizeof(udphdr_t), fin->fin_dlen);
  368                 else if (p == IPPROTO_ICMP) {
  369                         struct icmp *icmp;
  370 
  371                         icmp = (struct icmp *)fin->fin_dp;
  372 
  373                         /*
  374                          * For ICMP, if the packet is an error packet, also
  375                          * include the information about the packet which
  376                          * caused the error.
  377                          */
  378                         switch (icmp->icmp_type)
  379                         {
  380                         case ICMP_UNREACH :
  381                         case ICMP_SOURCEQUENCH :
  382                         case ICMP_REDIRECT :
  383                         case ICMP_TIMXCEED :
  384                         case ICMP_PARAMPROB :
  385                                 hlen += MIN(sizeof(struct icmp) + 8,
  386                                             fin->fin_dlen);
  387                                 break;
  388                         default :
  389                                 hlen += MIN(sizeof(struct icmp),
  390                                             fin->fin_dlen);
  391                                 break;
  392                         }
  393                 }
  394 # ifdef USE_INET6
  395                 else if (p == IPPROTO_ICMPV6) {
  396                         struct icmp6_hdr *icmp;
  397 
  398                         icmp = (struct icmp6_hdr *)fin->fin_dp;
  399 
  400                         /*
  401                          * For ICMPV6, if the packet is an error packet, also
  402                          * include the information about the packet which
  403                          * caused the error.
  404                          */
  405                         if (icmp->icmp6_type < 128) {
  406                                 hlen += MIN(sizeof(struct icmp6_hdr) + 8,
  407                                             fin->fin_dlen);
  408                         } else {
  409                                 hlen += MIN(sizeof(struct icmp6_hdr),
  410                                             fin->fin_dlen);
  411                         }
  412                 }
  413 # endif
  414         }
  415         /*
  416          * Get the interface number and name to which this packet is
  417          * currently associated.
  418          */
  419 # if SOLARIS && defined(_KERNEL)
  420 #  if !defined(FW_HOOKS)
  421         ipfl.fl_unit = (u_int)ifp->qf_ppa;
  422 #  endif
  423         COPYIFNAME(fin->fin_v, ifp, ipfl.fl_ifname);
  424 # else
  425 #  if (defined(NetBSD) && (NetBSD  <= 1991011) && (NetBSD >= 199603)) || \
  426       defined(__FreeBSD__)
  427         COPYIFNAME(fin->fin_v, ifp, ipfl.fl_ifname);
  428 #  else
  429         ipfl.fl_unit = (u_int)ifp->if_unit;
  430 #   if defined(_KERNEL)
  431         if ((ipfl.fl_ifname[0] = ifp->if_name[0]))
  432                 if ((ipfl.fl_ifname[1] = ifp->if_name[1]))
  433                         if ((ipfl.fl_ifname[2] = ifp->if_name[2]))
  434                                 ipfl.fl_ifname[3] = ifp->if_name[3];
  435 #   else
  436         (void) strncpy(ipfl.fl_ifname, IFNAME(ifp), sizeof(ipfl.fl_ifname));
  437         ipfl.fl_ifname[sizeof(ipfl.fl_ifname) - 1] = '\0';
  438 #   endif
  439 #  endif
  440 # endif /* __hpux || SOLARIS */
  441         mlen = fin->fin_plen - hlen;
  442         if (!softl->ipl_logall) {
  443                 mlen = (flags & FR_LOGBODY) ? MIN(mlen, 128) : 0;
  444         } else if ((flags & FR_LOGBODY) == 0) {
  445                 mlen = 0;
  446         }
  447         if (mlen < 0)
  448                 mlen = 0;
  449         ipfl.fl_plen = (u_char)mlen;
  450         ipfl.fl_hlen = (u_char)hlen;
  451         ipfl.fl_rule = fin->fin_rule;
  452         (void) strncpy(ipfl.fl_group, fin->fin_group, FR_GROUPLEN);
  453         if (fin->fin_fr != NULL) {
  454                 ipfl.fl_loglevel = fin->fin_fr->fr_loglevel;
  455                 ipfl.fl_logtag = fin->fin_fr->fr_logtag;
  456         } else {
  457                 ipfl.fl_loglevel = 0xffff;
  458                 ipfl.fl_logtag = FR_NOLOGTAG;
  459         }
  460         if (fin->fin_nattag != NULL)
  461                 bcopy(fin->fin_nattag, (void *)&ipfl.fl_nattag,
  462                       sizeof(ipfl.fl_nattag));
  463         ipfl.fl_flags = flags;
  464         ipfl.fl_breason = (fin->fin_reason & 0xff);
  465         ipfl.fl_dir = fin->fin_out;
  466         ipfl.fl_lflags = fin->fin_flx;
  467         ipfl.fl_family = fin->fin_family;
  468         ptrs[0] = (void *)&ipfl;
  469         sizes[0] = sizeof(ipfl);
  470         types[0] = 0;
  471 # if SOLARIS && defined(_KERNEL)
  472         /*
  473          * Are we copied from the mblk or an aligned array ?
  474          */
  475         if (fin->fin_ip == (ip_t *)m->b_rptr) {
  476                 ptrs[1] = m;
  477                 sizes[1] = hlen + mlen;
  478                 types[1] = 1;
  479         } else {
  480                 ptrs[1] = fin->fin_ip;
  481                 sizes[1] = hlen + mlen;
  482                 types[1] = 0;
  483         }
  484 # else
  485         ptrs[1] = m;
  486         sizes[1] = hlen + mlen;
  487         types[1] = 1;
  488 # endif /* SOLARIS */
  489         return (ipf_log_items(softc, IPL_LOGIPF, fin, ptrs, sizes, types, 2));
  490 }
  491 
  492 
  493 /* ------------------------------------------------------------------------ */
  494 /* Function:    ipf_log_items                                               */
  495 /* Returns:     int       - 0 == success, -1 == failure                     */
  496 /* Parameters:  softc(I)  - pointer to main soft context                    */
  497 /*              unit(I)   - device we are reading from                      */
  498 /*              fin(I)    - pointer to packet information                   */
  499 /*              items(I)  - array of pointers to log data                   */
  500 /*              itemsz(I) - array of size of valid memory pointed to        */
  501 /*              types(I)  - type of data pointed to by items pointers       */
  502 /*              cnt(I)    - number of elements in arrays items/itemsz/types */
  503 /*                                                                          */
  504 /* Takes an array of parameters and constructs one record to include the    */
  505 /* miscellaneous packet information, as well as packet data, for reading    */
  506 /* from the log device.                                                     */
  507 /* ------------------------------------------------------------------------ */
  508 int
  509 ipf_log_items(ipf_main_softc_t *softc, int unit, fr_info_t *fin, void **items,
  510         size_t *itemsz, int *types, int cnt)
  511 {
  512         ipf_log_softc_t *softl = softc->ipf_log_soft;
  513         caddr_t buf, ptr;
  514         iplog_t *ipl;
  515         size_t len;
  516         int i;
  517         SPL_INT(s);
  518 
  519         /*
  520          * Get the total amount of data to be logged.
  521          */
  522         for (i = 0, len = sizeof(iplog_t); i < cnt; i++)
  523                 len += itemsz[i];
  524 
  525         SPL_NET(s);
  526         MUTEX_ENTER(&softl->ipl_mutex[unit]);
  527         softl->ipl_counter[unit]++;
  528         /*
  529          * check that we have space to record this information and can
  530          * allocate that much.
  531          */
  532         if ((softl->ipl_used[unit] + len) > softl->ipl_logsize) {
  533                 softl->ipl_logfail[unit]++;
  534                 MUTEX_EXIT(&softl->ipl_mutex[unit]);
  535                 return (-1);
  536         }
  537 
  538         KMALLOCS(buf, caddr_t, len);
  539         if (buf == NULL) {
  540                 softl->ipl_logfail[unit]++;
  541                 MUTEX_EXIT(&softl->ipl_mutex[unit]);
  542                 return (-1);
  543         }
  544         ipl = (iplog_t *)buf;
  545         ipl->ipl_magic = softl->ipl_magic[unit];
  546         ipl->ipl_count = 1;
  547         ipl->ipl_seqnum = softl->ipl_counter[unit];
  548         ipl->ipl_next = NULL;
  549         ipl->ipl_dsize = len;
  550 #ifdef _KERNEL
  551         GETKTIME(&ipl->ipl_sec);
  552 #else
  553         ipl->ipl_sec = 0;
  554         ipl->ipl_usec = 0;
  555 #endif
  556 
  557         /*
  558          * Loop through all the items to be logged, copying each one to the
  559          * buffer.  Use bcopy for normal data or the mb_t copyout routine.
  560          */
  561         for (i = 0, ptr = buf + sizeof(*ipl); i < cnt; i++) {
  562                 if (types[i] == 0) {
  563                         bcopy(items[i], ptr, itemsz[i]);
  564                 } else if (types[i] == 1) {
  565                         COPYDATA(items[i], 0, itemsz[i], ptr);
  566                 }
  567                 ptr += itemsz[i];
  568         }
  569         /*
  570          * Check to see if this log record has a CRC which matches the last
  571          * record logged.  If it does, just up the count on the previous one
  572          * rather than create a new one.
  573          */
  574         if (softl->ipl_suppress) {
  575                 if ((fin != NULL) && (fin->fin_off == 0)) {
  576                         if ((softl->ipll[unit] != NULL) &&
  577                             (fin->fin_crc == softl->ipl_crc[unit].fin_crc) &&
  578                             bcmp((char *)fin, (char *)&softl->ipl_crc[unit],
  579                                  FI_LCSIZE) == 0) {
  580                                 softl->ipll[unit]->ipl_count++;
  581                                 MUTEX_EXIT(&softl->ipl_mutex[unit]);
  582                                 SPL_X(s);
  583                                 KFREES(buf, len);
  584                                 return (0);
  585                         }
  586                         bcopy((char *)fin, (char *)&softl->ipl_crc[unit],
  587                               FI_LCSIZE);
  588                         softl->ipl_crc[unit].fin_crc = fin->fin_crc;
  589                 } else
  590                         bzero((char *)&softl->ipl_crc[unit], FI_CSIZE);
  591         }
  592 
  593         /*
  594          * advance the log pointer to the next empty record and deduct the
  595          * amount of space we're going to use.
  596          */
  597         softl->ipl_logok[unit]++;
  598         softl->ipll[unit] = ipl;
  599         *softl->iplh[unit] = ipl;
  600         softl->iplh[unit] = &ipl->ipl_next;
  601         softl->ipl_used[unit] += len;
  602 
  603         /*
  604          * Now that the log record has been completed and added to the queue,
  605          * wake up any listeners who may want to read it.
  606          */
  607 # if SOLARIS && defined(_KERNEL)
  608         cv_signal(&softl->ipl_wait[unit]);
  609         MUTEX_EXIT(&softl->ipl_mutex[unit]);
  610         pollwakeup(&softc->ipf_poll_head[unit], POLLRDNORM);
  611 # else
  612         MUTEX_EXIT(&softl->ipl_mutex[unit]);
  613         WAKEUP(softl->iplh, unit);
  614         POLLWAKEUP(unit);
  615 # endif
  616         SPL_X(s);
  617         return (0);
  618 }
  619 
  620 
  621 /* ------------------------------------------------------------------------ */
  622 /* Function:    ipf_log_read                                                */
  623 /* Returns:     int      - 0 == success, else error value.                  */
  624 /* Parameters:  softc(I) - pointer to main soft context                     */
  625 /*              unit(I)  - device we are reading from                       */
  626 /*              uio(O)   - pointer to information about where to store data */
  627 /*                                                                          */
  628 /* Called to handle a read on an IPFilter device.  Returns only complete    */
  629 /* log messages - will not partially copy a log record out to userland.     */
  630 /*                                                                          */
  631 /* NOTE: This function will block and wait for a signal to return data if   */
  632 /* there is none present.  Asynchronous I/O is not implemented.             */
  633 /* ------------------------------------------------------------------------ */
  634 int
  635 ipf_log_read(ipf_main_softc_t *softc, minor_t unit, struct uio *uio)
  636 {
  637         ipf_log_softc_t *softl = softc->ipf_log_soft;
  638         size_t dlen;
  639         int error = 0;
  640         iplog_t *ipl;
  641         SPL_INT(s);
  642 
  643         if (softl->ipl_log_init == 0) {
  644                 IPFERROR(40007);
  645                 return (0);
  646         }
  647 
  648         /*
  649          * Sanity checks.  Make sure the minor # is valid and we're copying
  650          * a valid chunk of data.
  651          */
  652         if (IPL_LOGMAX < unit) {
  653                 IPFERROR(40001);
  654                 return (ENXIO);
  655         }
  656         if (uio->uio_resid == 0)
  657                 return (0);
  658 
  659         if (uio->uio_resid < sizeof(iplog_t)) {
  660                 IPFERROR(40002);
  661                 return (EINVAL);
  662         }
  663         if (uio->uio_resid > softl->ipl_logsize) {
  664                 IPFERROR(40005);
  665                 return (EINVAL);
  666         }
  667 
  668         /*
  669          * Lock the log so we can snapshot the variables.  Wait for a signal
  670          * if the log is empty.
  671          */
  672         SPL_NET(s);
  673         MUTEX_ENTER(&softl->ipl_mutex[unit]);
  674         softl->ipl_readers[unit]++;
  675 
  676         while (softl->ipl_log_init == 1 && softl->iplt[unit] == NULL) {
  677 # if SOLARIS && defined(_KERNEL)
  678                 if (!cv_wait_sig(&softl->ipl_wait[unit],
  679                                  &softl->ipl_mutex[unit].ipf_lk)) {
  680                         softl->ipl_readers[unit]--;
  681                         MUTEX_EXIT(&softl->ipl_mutex[unit]);
  682                         IPFERROR(40003);
  683                         return (EINTR);
  684                 }
  685 # else
  686                 MUTEX_EXIT(&softl->ipl_mutex[unit]);
  687                 SPL_X(s);
  688                 error = SLEEP(unit + softl->iplh, "ipl sleep");
  689                 SPL_NET(s);
  690                 MUTEX_ENTER(&softl->ipl_mutex[unit]);
  691                 if (error) {
  692                         softl->ipl_readers[unit]--;
  693                         MUTEX_EXIT(&softl->ipl_mutex[unit]);
  694                         IPFERROR(40004);
  695                         return (error);
  696                 }
  697 # endif /* SOLARIS */
  698         }
  699         if (softl->ipl_log_init != 1) {
  700                 softl->ipl_readers[unit]--;
  701                 MUTEX_EXIT(&softl->ipl_mutex[unit]);
  702                 IPFERROR(40008);
  703                 return (EIO);
  704         }
  705 
  706 # if defined(BSD)
  707         uio->uio_rw = UIO_READ;
  708 # endif
  709 
  710         for (; (ipl = softl->iplt[unit]) != NULL;) {
  711                 dlen = ipl->ipl_dsize;
  712                 if (dlen > uio->uio_resid)
  713                         break;
  714                 /*
  715                  * Don't hold the mutex over the uiomove call.
  716                  */
  717                 softl->iplt[unit] = ipl->ipl_next;
  718                 softl->ipl_used[unit] -= dlen;
  719                 MUTEX_EXIT(&softl->ipl_mutex[unit]);
  720                 SPL_X(s);
  721                 error = UIOMOVE(ipl, dlen, UIO_READ, uio);
  722                 if (error) {
  723                         SPL_NET(s);
  724                         MUTEX_ENTER(&softl->ipl_mutex[unit]);
  725                         IPFERROR(40006);
  726                         ipl->ipl_next = softl->iplt[unit];
  727                         softl->iplt[unit] = ipl;
  728                         softl->ipl_used[unit] += dlen;
  729                         break;
  730                 }
  731                 MUTEX_ENTER(&softl->ipl_mutex[unit]);
  732                 KFREES((caddr_t)ipl, dlen);
  733                 SPL_NET(s);
  734         }
  735         if (!softl->iplt[unit]) {
  736                 softl->ipl_used[unit] = 0;
  737                 softl->iplh[unit] = &softl->iplt[unit];
  738                 softl->ipll[unit] = NULL;
  739         }
  740 
  741         softl->ipl_readers[unit]--;
  742         MUTEX_EXIT(&softl->ipl_mutex[unit]);
  743         SPL_X(s);
  744         return (error);
  745 }
  746 
  747 
  748 /* ------------------------------------------------------------------------ */
  749 /* Function:    ipf_log_clear                                               */
  750 /* Returns:     int      - number of log bytes cleared.                     */
  751 /* Parameters:  softc(I) - pointer to main soft context                     */
  752 /*              unit(I)  - device we are reading from                       */
  753 /*                                                                          */
  754 /* Deletes all queued up log records for a given output device.             */
  755 /* ------------------------------------------------------------------------ */
  756 int
  757 ipf_log_clear(ipf_main_softc_t *softc, minor_t unit)
  758 {
  759         ipf_log_softc_t *softl = softc->ipf_log_soft;
  760         iplog_t *ipl;
  761         int used;
  762         SPL_INT(s);
  763 
  764         SPL_NET(s);
  765         MUTEX_ENTER(&softl->ipl_mutex[unit]);
  766         while ((ipl = softl->iplt[unit]) != NULL) {
  767                 softl->iplt[unit] = ipl->ipl_next;
  768                 KFREES((caddr_t)ipl, ipl->ipl_dsize);
  769         }
  770         softl->iplh[unit] = &softl->iplt[unit];
  771         softl->ipll[unit] = NULL;
  772         used = softl->ipl_used[unit];
  773         softl->ipl_used[unit] = 0;
  774         bzero((char *)&softl->ipl_crc[unit], FI_CSIZE);
  775         MUTEX_EXIT(&softl->ipl_mutex[unit]);
  776         SPL_X(s);
  777         return (used);
  778 }
  779 
  780 
  781 /* ------------------------------------------------------------------------ */
  782 /* Function:    ipf_log_canread                                             */
  783 /* Returns:     int      - 0 == no data to read, 1 = data present           */
  784 /* Parameters:  softc(I) - pointer to main soft context                     */
  785 /*              unit(I)  - device we are reading from                       */
  786 /*                                                                          */
  787 /* Returns an indication of whether or not there is data present in the     */
  788 /* current buffer for the selected ipf device.                              */
  789 /* ------------------------------------------------------------------------ */
  790 int
  791 ipf_log_canread(ipf_main_softc_t *softc, int unit)
  792 {
  793         ipf_log_softc_t *softl = softc->ipf_log_soft;
  794 
  795         return (softl->iplt[unit] != NULL);
  796 }
  797 
  798 
  799 /* ------------------------------------------------------------------------ */
  800 /* Function:    ipf_log_canread                                             */
  801 /* Returns:     int      - 0 == no data to read, 1 = data present           */
  802 /* Parameters:  softc(I) - pointer to main soft context                     */
  803 /*              unit(I)  - device we are reading from                       */
  804 /*                                                                          */
  805 /* Returns how many bytes are currently held in log buffers for the         */
  806 /* selected ipf device.                                                     */
  807 /* ------------------------------------------------------------------------ */
  808 int
  809 ipf_log_bytesused(ipf_main_softc_t *softc, int unit)
  810 {
  811         ipf_log_softc_t *softl = softc->ipf_log_soft;
  812 
  813         if (softl == NULL)
  814                 return (0);
  815 
  816         return (softl->ipl_used[unit]);
  817 }
  818 
  819 
  820 /* ------------------------------------------------------------------------ */
  821 /* Function:    ipf_log_failures                                            */
  822 /* Returns:     U_QUAD_T - number of log failures                           */
  823 /* Parameters:  softc(I) - pointer to main soft context                     */
  824 /*              unit(I)  - device we are reading from                       */
  825 /*                                                                          */
  826 /* Returns how many times we've tried to log a packet but failed to do so   */
  827 /* for the selected ipf device.                                             */
  828 /* ------------------------------------------------------------------------ */
  829 u_long
  830 ipf_log_failures(ipf_main_softc_t *softc, int unit)
  831 {
  832         ipf_log_softc_t *softl = softc->ipf_log_soft;
  833 
  834         if (softl == NULL)
  835                 return (0);
  836 
  837         return (softl->ipl_logfail[unit]);
  838 }
  839 
  840 
  841 /* ------------------------------------------------------------------------ */
  842 /* Function:    ipf_log_logok                                               */
  843 /* Returns:     U_QUAD_T - number of packets logged                         */
  844 /* Parameters:  softc(I) - pointer to main soft context                     */
  845 /*              unit(I)  - device we are reading from                       */
  846 /*                                                                          */
  847 /* Returns how many times we've successfully logged a packet for the        */
  848 /* selected ipf device.                                                     */
  849 /* ------------------------------------------------------------------------ */
  850 u_long
  851 ipf_log_logok(ipf_main_softc_t *softc, int unit)
  852 {
  853         ipf_log_softc_t *softl = softc->ipf_log_soft;
  854 
  855         if (softl == NULL)
  856                 return (0);
  857 
  858         return (softl->ipl_logok[unit]);
  859 }
  860 #endif /* IPFILTER_LOG */

Cache object: 7ee2364d2c384d0e39347e33fbe22fc5


[ 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.