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

Cache object: aff61141f8550df6116c4e0a6faf0fc9


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