Print this page
OS-7667 IPFilter needs to keep and report state for cloud firewall logging
Portions contributed by: Mike Gerdts <mike.gerdts@joyent.com>
   1 /*
   2  * Copyright (C) 1995-2003 by Darren Reed.
   3  *
   4  * See the IPFILTER.LICENCE file for details on licencing.
   5  *
   6  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
   7  *
   8  * Copyright (c) 2014, Joyent, Inc.  All rights reserved.
   9  */
  10 
  11 #if defined(KERNEL) || defined(_KERNEL)
  12 # undef KERNEL
  13 # undef _KERNEL
  14 # define        KERNEL  1
  15 # define        _KERNEL 1
  16 #endif
  17 #include <sys/errno.h>
  18 #include <sys/types.h>
  19 #include <sys/param.h>
  20 #include <sys/file.h>
  21 #if defined(__NetBSD__) && (NetBSD >= 199905) && !defined(IPFILTER_LKM) && \
  22     defined(_KERNEL)
  23 # include "opt_ipfilter_log.h"
  24 #endif
  25 #if defined(_KERNEL) && defined(__FreeBSD_version) && \
  26     (__FreeBSD_version >= 400000) && !defined(KLD_MODULE)
  27 #include "opt_inet6.h"
  28 #endif


  91 #include "netinet/ip_frag.h"
  92 #include "netinet/ip_state.h"
  93 #include "netinet/ip_proxy.h"
  94 #include "netinet/ipf_stack.h"
  95 #ifdef  IPFILTER_SYNC
  96 #include "netinet/ip_sync.h"
  97 #endif
  98 #ifdef  IPFILTER_SCAN
  99 #include "netinet/ip_scan.h"
 100 #endif
 101 #ifdef  USE_INET6
 102 #include <netinet/icmp6.h>
 103 #endif
 104 #if (__FreeBSD_version >= 300000)
 105 # include <sys/malloc.h>
 106 # if defined(_KERNEL) && !defined(IPFILTER_LKM)
 107 #  include <sys/libkern.h>
 108 #  include <sys/systm.h>
 109 # endif
 110 #endif

 111 /* END OF INCLUDES */
 112 
 113 
 114 #if !defined(lint)
 115 static const char sccsid[] = "@(#)ip_state.c    1.8 6/5/96 (C) 1993-2000 Darren Reed";
 116 static const char rcsid[] = "@(#)$Id: ip_state.c,v 2.186.2.36 2005/08/11 19:58:03 darrenr Exp $";
 117 #endif
 118 
 119 #ifdef  USE_INET6
 120 static ipstate_t *fr_checkicmp6matchingstate __P((fr_info_t *));
 121 #endif
 122 static ipstate_t *fr_matchsrcdst __P((fr_info_t *, ipstate_t *, i6addr_t *,
 123                                       i6addr_t *, tcphdr_t *, u_32_t));
 124 static ipstate_t *fr_checkicmpmatchingstate __P((fr_info_t *));
 125 static int fr_state_flush __P((int, int, ipf_stack_t *));
 126 static ips_stat_t *fr_statetstats __P((ipf_stack_t *));
 127 static int fr_state_remove __P((caddr_t, ipf_stack_t *));
 128 static void fr_ipsmove __P((ipstate_t *, u_int, ipf_stack_t *));
 129 static int fr_tcpstate __P((fr_info_t *, tcphdr_t *, ipstate_t *));
 130 static int fr_tcpoptions __P((fr_info_t *, tcphdr_t *, tcpdata_t *));


1428         }
1429         bcopy((char *)&ips, (char *)is, sizeof(*is));
1430         /*
1431          * Do not do the modulous here, it is done in fr_stinsert().
1432          */
1433         if (fr != NULL) {
1434                 (void) strncpy(is->is_group, fr->fr_group, FR_GROUPLEN);
1435                 if (fr->fr_age[0] != 0) {
1436                         is->is_tqehead[0] = 
1437                             fr_addtimeoutqueue(&ifs->ifs_ips_utqe,
1438                                                fr->fr_age[0], ifs);
1439                         is->is_sti.tqe_flags |= TQE_RULEBASED;
1440                 }
1441                 if (fr->fr_age[1] != 0) {
1442                         is->is_tqehead[1] = 
1443                             fr_addtimeoutqueue(&ifs->ifs_ips_utqe,
1444                                                fr->fr_age[1], ifs);
1445                         is->is_sti.tqe_flags |= TQE_RULEBASED;
1446                 }
1447                 is->is_tag = fr->fr_logtag;

1448 
1449                 is->is_ifp[(out << 1) + 1] = fr->fr_ifas[1];
1450                 is->is_ifp[(1 - out) << 1] = fr->fr_ifas[2];
1451                 is->is_ifp[((1 - out) << 1) + 1] = fr->fr_ifas[3];
1452 
1453                 if (((ifp = fr->fr_ifas[1]) != NULL) &&
1454                     (ifp != (void *)-1)) {
1455                         COPYIFNAME(ifp, is->is_ifname[(out << 1) + 1], fr->fr_v);
1456                 }
1457                 if (((ifp = fr->fr_ifas[2]) != NULL) &&
1458                     (ifp != (void *)-1)) {
1459                         COPYIFNAME(ifp, is->is_ifname[(1 - out) << 1], fr->fr_v);
1460                 }
1461                 if (((ifp = fr->fr_ifas[3]) != NULL) &&
1462                     (ifp != (void *)-1)) {
1463                         COPYIFNAME(ifp, is->is_ifname[((1 - out) << 1) + 1], fr->fr_v);
1464                 }
1465         }
1466 
1467         is->is_ifp[out << 1] = fin->fin_ifp;


1507                 * timer on it as we'll never see an error if it fails to
1508                 * connect.
1509                 */
1510                 (void) fr_tcp_age(&is->is_sti, fin, ifs->ifs_ips_tqtqb,
1511                                   is->is_flags);
1512                 MUTEX_EXIT(&is->is_lock);
1513 #ifdef  IPFILTER_SCAN
1514                 if ((is->is_flags & SI_CLONE) == 0)
1515                         (void) ipsc_attachis(is);
1516 #endif
1517         } else {
1518                 MUTEX_EXIT(&is->is_lock);
1519         }
1520 #ifdef  IPFILTER_SYNC
1521         if ((is->is_flags & IS_STATESYNC) && ((is->is_flags & SI_CLONE) == 0))
1522                 is->is_sync = ipfsync_new(SMC_STATE, fin, is);
1523 #endif
1524         if (ifs->ifs_ipstate_logging)
1525                 ipstate_log(is, ISL_NEW, ifs);
1526 



1527         RWLOCK_EXIT(&ifs->ifs_ipf_state);
1528         fin->fin_rev = IP6_NEQ(&is->is_dst, &fin->fin_daddr);
1529         fin->fin_flx |= FI_STATE;
1530         if (fin->fin_flx & FI_FRAG)
1531                 (void) fr_newfrag(fin, pass ^ FR_KEEPSTATE);
1532 
1533         return is;
1534 }
1535 
1536 
1537 /* ------------------------------------------------------------------------ */
1538 /* Function:    fr_tcpoptions                                               */
1539 /* Returns:     int - 1 == packet matches state entry, 0 == it does not     */
1540 /* Parameters:  fin(I) - pointer to packet information                      */
1541 /*              tcp(I) - pointer to TCP packet header                       */
1542 /*              td(I)  - pointer to TCP data held as part of the state      */
1543 /*                                                                          */
1544 /* Look after the TCP header for any options and deal with those that are   */
1545 /* present.  Record details about those that we recogise.                   */
1546 /* ------------------------------------------------------------------------ */


2297                                 is->is_sport = sp;
2298                                 is->is_send = ntohl(tcp->th_seq);
2299                         } else {
2300                                 is->is_sport = dp;
2301                                 is->is_send = ntohl(tcp->th_ack);
2302                         }
2303                         is->is_maxsend = is->is_send + 1;
2304                 } else if ((flags & SI_W_DPORT) != 0) {
2305                         if (rev == 0) {
2306                                 is->is_dport = dp;
2307                                 is->is_dend = ntohl(tcp->th_ack);
2308                         } else {
2309                                 is->is_dport = sp;
2310                                 is->is_dend = ntohl(tcp->th_seq);
2311                         }
2312                         is->is_maxdend = is->is_dend + 1;
2313                 }
2314                 is->is_flags &= ~(SI_W_SPORT|SI_W_DPORT);
2315                 if ((flags & SI_CLONED) && ifs->ifs_ipstate_logging)
2316                         ipstate_log(is, ISL_CLONE, ifs);


2317         }
2318 
2319         ret = -1;
2320 
2321         if (is->is_flx[out][rev] == 0) {
2322                 is->is_flx[out][rev] = flx;
2323                 /*
2324                  * If we are dealing with the first packet coming in reverse
2325                  * direction (sent by peer), then we have to set options into
2326                  * state.
2327                  */
2328                 if (rev == 1 && is->is_optmsk[1] == 0x0) {
2329                         is->is_optmsk[1] = 0xffffffff;
2330                         is->is_opt[1] = fin->fin_optmsk;
2331                         DTRACE_PROBE(set_rev_opts);
2332                 }
2333                 if (is->is_v == 6) {
2334                         is->is_opt[rev] &= ~0x8;
2335                         is->is_optmsk[rev] &= ~0x8;
2336                 }


3380                 ipfsync_del(is->is_sync);
3381 #endif
3382 #ifdef  IPFILTER_SCAN
3383         (void) ipsc_detachis(is);
3384 #endif
3385 
3386         /*
3387          * Now remove it from master list of state table entries.
3388          */
3389         if (is->is_pnext != NULL) {
3390                 *is->is_pnext = is->is_next;
3391                 if (is->is_next != NULL) {
3392                         is->is_next->is_pnext = is->is_pnext;
3393                         is->is_next = NULL;
3394                 }
3395                 is->is_pnext = NULL;
3396         }
3397  
3398         if (ifs->ifs_ipstate_logging != 0 && why != 0)
3399                 ipstate_log(is, why, ifs);
3400 








3401         if (is->is_rule != NULL) {
3402                 is->is_rule->fr_statecnt--;
3403                 (void)fr_derefrule(&is->is_rule, ifs);
3404         }
3405 
3406         MUTEX_DESTROY(&is->is_lock);
3407         KFREE(is);
3408         ifs->ifs_ips_num--;
3409 
3410         return (0);
3411 }
3412 
3413 
3414 /* ------------------------------------------------------------------------ */
3415 /* Function:    fr_timeoutstate                                             */
3416 /* Returns:     Nil                                                         */
3417 /* Parameters:  ifs - ipf stack instance                                    */
3418 /*                                                                          */
3419 /* Slowly expire held state for thingslike UDP and ICMP.  The algorithm     */
3420 /* used here is to keep the queue sorted with the oldest things at the top  */


3914         if (rval == 2) {
3915                 DTRACE_PROBE1(state_keeping_timer, int, nstate);
3916                 rval = 1;
3917         }
3918         else if (rval == 1) {
3919                 tqe->tqe_state[dir] = nstate;
3920                 /*
3921                  * The nstate can either advance to a new state, or remain
3922                  * unchanged, resetting the timer by moving to the bottom of
3923                  * the queue.
3924                  */
3925                 DTRACE_PROBE1(state_done, int, nstate);
3926 
3927                 if ((tqe->tqe_flags & TQE_RULEBASED) == 0)
3928                         fr_movequeue(tqe, tqe->tqe_ifq, tqtab + nstate, ifs);
3929         }
3930 
3931         return rval;
3932 }
3933 
3934 
3935 /* ------------------------------------------------------------------------ */
3936 /* Function:    ipstate_log                                                 */
3937 /* Returns:     Nil                                                         */
3938 /* Parameters:  is(I)   - pointer to state structure                        */
3939 /*              type(I) - type of log entry to create                       */
3940 /*                                                                          */
3941 /* Creates a state table log entry using the state structure and type info. */
3942 /* passed in.  Log packet/byte counts, source/destination address and other */
3943 /* protocol specific information.                                           */
3944 /* ------------------------------------------------------------------------ */
3945 void ipstate_log(is, type, ifs)
3946 struct ipstate *is;
3947 u_int type;
3948 ipf_stack_t *ifs;
3949 {
3950 #ifdef  IPFILTER_LOG
3951         struct  ipslog  ipsl;
3952         size_t sizes[1];
3953         void *items[1];
3954         int types[1];


   1 /*
   2  * Copyright (C) 1995-2003 by Darren Reed.
   3  *
   4  * See the IPFILTER.LICENCE file for details on licencing.
   5  *
   6  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
   7  *
   8  * Copyright 2019 Joyent, Inc.
   9  */
  10 
  11 #if defined(KERNEL) || defined(_KERNEL)
  12 # undef KERNEL
  13 # undef _KERNEL
  14 # define        KERNEL  1
  15 # define        _KERNEL 1
  16 #endif
  17 #include <sys/errno.h>
  18 #include <sys/types.h>
  19 #include <sys/param.h>
  20 #include <sys/file.h>
  21 #if defined(__NetBSD__) && (NetBSD >= 199905) && !defined(IPFILTER_LKM) && \
  22     defined(_KERNEL)
  23 # include "opt_ipfilter_log.h"
  24 #endif
  25 #if defined(_KERNEL) && defined(__FreeBSD_version) && \
  26     (__FreeBSD_version >= 400000) && !defined(KLD_MODULE)
  27 #include "opt_inet6.h"
  28 #endif


  91 #include "netinet/ip_frag.h"
  92 #include "netinet/ip_state.h"
  93 #include "netinet/ip_proxy.h"
  94 #include "netinet/ipf_stack.h"
  95 #ifdef  IPFILTER_SYNC
  96 #include "netinet/ip_sync.h"
  97 #endif
  98 #ifdef  IPFILTER_SCAN
  99 #include "netinet/ip_scan.h"
 100 #endif
 101 #ifdef  USE_INET6
 102 #include <netinet/icmp6.h>
 103 #endif
 104 #if (__FreeBSD_version >= 300000)
 105 # include <sys/malloc.h>
 106 # if defined(_KERNEL) && !defined(IPFILTER_LKM)
 107 #  include <sys/libkern.h>
 108 #  include <sys/systm.h>
 109 # endif
 110 #endif
 111 #include <sys/uuid.h>
 112 /* END OF INCLUDES */
 113 
 114 
 115 #if !defined(lint)
 116 static const char sccsid[] = "@(#)ip_state.c    1.8 6/5/96 (C) 1993-2000 Darren Reed";
 117 static const char rcsid[] = "@(#)$Id: ip_state.c,v 2.186.2.36 2005/08/11 19:58:03 darrenr Exp $";
 118 #endif
 119 
 120 #ifdef  USE_INET6
 121 static ipstate_t *fr_checkicmp6matchingstate __P((fr_info_t *));
 122 #endif
 123 static ipstate_t *fr_matchsrcdst __P((fr_info_t *, ipstate_t *, i6addr_t *,
 124                                       i6addr_t *, tcphdr_t *, u_32_t));
 125 static ipstate_t *fr_checkicmpmatchingstate __P((fr_info_t *));
 126 static int fr_state_flush __P((int, int, ipf_stack_t *));
 127 static ips_stat_t *fr_statetstats __P((ipf_stack_t *));
 128 static int fr_state_remove __P((caddr_t, ipf_stack_t *));
 129 static void fr_ipsmove __P((ipstate_t *, u_int, ipf_stack_t *));
 130 static int fr_tcpstate __P((fr_info_t *, tcphdr_t *, ipstate_t *));
 131 static int fr_tcpoptions __P((fr_info_t *, tcphdr_t *, tcpdata_t *));


1429         }
1430         bcopy((char *)&ips, (char *)is, sizeof(*is));
1431         /*
1432          * Do not do the modulous here, it is done in fr_stinsert().
1433          */
1434         if (fr != NULL) {
1435                 (void) strncpy(is->is_group, fr->fr_group, FR_GROUPLEN);
1436                 if (fr->fr_age[0] != 0) {
1437                         is->is_tqehead[0] = 
1438                             fr_addtimeoutqueue(&ifs->ifs_ips_utqe,
1439                                                fr->fr_age[0], ifs);
1440                         is->is_sti.tqe_flags |= TQE_RULEBASED;
1441                 }
1442                 if (fr->fr_age[1] != 0) {
1443                         is->is_tqehead[1] = 
1444                             fr_addtimeoutqueue(&ifs->ifs_ips_utqe,
1445                                                fr->fr_age[1], ifs);
1446                         is->is_sti.tqe_flags |= TQE_RULEBASED;
1447                 }
1448                 is->is_tag = fr->fr_logtag;
1449                 memcpy(is->is_uuid, fr->fr_uuid, sizeof (uuid_t));
1450 
1451                 is->is_ifp[(out << 1) + 1] = fr->fr_ifas[1];
1452                 is->is_ifp[(1 - out) << 1] = fr->fr_ifas[2];
1453                 is->is_ifp[((1 - out) << 1) + 1] = fr->fr_ifas[3];
1454 
1455                 if (((ifp = fr->fr_ifas[1]) != NULL) &&
1456                     (ifp != (void *)-1)) {
1457                         COPYIFNAME(ifp, is->is_ifname[(out << 1) + 1], fr->fr_v);
1458                 }
1459                 if (((ifp = fr->fr_ifas[2]) != NULL) &&
1460                     (ifp != (void *)-1)) {
1461                         COPYIFNAME(ifp, is->is_ifname[(1 - out) << 1], fr->fr_v);
1462                 }
1463                 if (((ifp = fr->fr_ifas[3]) != NULL) &&
1464                     (ifp != (void *)-1)) {
1465                         COPYIFNAME(ifp, is->is_ifname[((1 - out) << 1) + 1], fr->fr_v);
1466                 }
1467         }
1468 
1469         is->is_ifp[out << 1] = fin->fin_ifp;


1509                 * timer on it as we'll never see an error if it fails to
1510                 * connect.
1511                 */
1512                 (void) fr_tcp_age(&is->is_sti, fin, ifs->ifs_ips_tqtqb,
1513                                   is->is_flags);
1514                 MUTEX_EXIT(&is->is_lock);
1515 #ifdef  IPFILTER_SCAN
1516                 if ((is->is_flags & SI_CLONE) == 0)
1517                         (void) ipsc_attachis(is);
1518 #endif
1519         } else {
1520                 MUTEX_EXIT(&is->is_lock);
1521         }
1522 #ifdef  IPFILTER_SYNC
1523         if ((is->is_flags & IS_STATESYNC) && ((is->is_flags & SI_CLONE) == 0))
1524                 is->is_sync = ipfsync_new(SMC_STATE, fin, is);
1525 #endif
1526         if (ifs->ifs_ipstate_logging)
1527                 ipstate_log(is, ISL_NEW, ifs);
1528 
1529         if (IFS_CFWLOG(ifs, is->is_rule))
1530                 ipf_log_cfwlog(is, ISL_NEW, ifs);
1531 
1532         RWLOCK_EXIT(&ifs->ifs_ipf_state);
1533         fin->fin_rev = IP6_NEQ(&is->is_dst, &fin->fin_daddr);
1534         fin->fin_flx |= FI_STATE;
1535         if (fin->fin_flx & FI_FRAG)
1536                 (void) fr_newfrag(fin, pass ^ FR_KEEPSTATE);
1537 
1538         return is;
1539 }
1540 
1541 
1542 /* ------------------------------------------------------------------------ */
1543 /* Function:    fr_tcpoptions                                               */
1544 /* Returns:     int - 1 == packet matches state entry, 0 == it does not     */
1545 /* Parameters:  fin(I) - pointer to packet information                      */
1546 /*              tcp(I) - pointer to TCP packet header                       */
1547 /*              td(I)  - pointer to TCP data held as part of the state      */
1548 /*                                                                          */
1549 /* Look after the TCP header for any options and deal with those that are   */
1550 /* present.  Record details about those that we recogise.                   */
1551 /* ------------------------------------------------------------------------ */


2302                                 is->is_sport = sp;
2303                                 is->is_send = ntohl(tcp->th_seq);
2304                         } else {
2305                                 is->is_sport = dp;
2306                                 is->is_send = ntohl(tcp->th_ack);
2307                         }
2308                         is->is_maxsend = is->is_send + 1;
2309                 } else if ((flags & SI_W_DPORT) != 0) {
2310                         if (rev == 0) {
2311                                 is->is_dport = dp;
2312                                 is->is_dend = ntohl(tcp->th_ack);
2313                         } else {
2314                                 is->is_dport = sp;
2315                                 is->is_dend = ntohl(tcp->th_seq);
2316                         }
2317                         is->is_maxdend = is->is_dend + 1;
2318                 }
2319                 is->is_flags &= ~(SI_W_SPORT|SI_W_DPORT);
2320                 if ((flags & SI_CLONED) && ifs->ifs_ipstate_logging)
2321                         ipstate_log(is, ISL_CLONE, ifs);
2322                 if ((flags & SI_CLONED) && IFS_CFWLOG(ifs, is->is_rule))
2323                         ipf_log_cfwlog(is, ISL_CLONE, ifs);
2324         }
2325 
2326         ret = -1;
2327 
2328         if (is->is_flx[out][rev] == 0) {
2329                 is->is_flx[out][rev] = flx;
2330                 /*
2331                  * If we are dealing with the first packet coming in reverse
2332                  * direction (sent by peer), then we have to set options into
2333                  * state.
2334                  */
2335                 if (rev == 1 && is->is_optmsk[1] == 0x0) {
2336                         is->is_optmsk[1] = 0xffffffff;
2337                         is->is_opt[1] = fin->fin_optmsk;
2338                         DTRACE_PROBE(set_rev_opts);
2339                 }
2340                 if (is->is_v == 6) {
2341                         is->is_opt[rev] &= ~0x8;
2342                         is->is_optmsk[rev] &= ~0x8;
2343                 }


3387                 ipfsync_del(is->is_sync);
3388 #endif
3389 #ifdef  IPFILTER_SCAN
3390         (void) ipsc_detachis(is);
3391 #endif
3392 
3393         /*
3394          * Now remove it from master list of state table entries.
3395          */
3396         if (is->is_pnext != NULL) {
3397                 *is->is_pnext = is->is_next;
3398                 if (is->is_next != NULL) {
3399                         is->is_next->is_pnext = is->is_pnext;
3400                         is->is_next = NULL;
3401                 }
3402                 is->is_pnext = NULL;
3403         }
3404  
3405         if (ifs->ifs_ipstate_logging != 0 && why != 0)
3406                 ipstate_log(is, why, ifs);
3407 #if 0
3408         /*
3409          * For now, ipf_log_cfwlog() copes with all "why" values. Strictly
3410          * speaking, though, they all map to one event (CFWEV_END), which for
3411          * now is not supported, hence the #if 0.
3412          */
3413         if (why != 0 && IFS_CFWLOG(ifs, is->is_rule))
3414                 ipf_log_cfwlog(is, why, ifs);
3415 #endif
3416         if (is->is_rule != NULL) {
3417                 is->is_rule->fr_statecnt--;
3418                 (void)fr_derefrule(&is->is_rule, ifs);
3419         }
3420 
3421         MUTEX_DESTROY(&is->is_lock);
3422         KFREE(is);
3423         ifs->ifs_ips_num--;
3424 
3425         return (0);
3426 }
3427 
3428 
3429 /* ------------------------------------------------------------------------ */
3430 /* Function:    fr_timeoutstate                                             */
3431 /* Returns:     Nil                                                         */
3432 /* Parameters:  ifs - ipf stack instance                                    */
3433 /*                                                                          */
3434 /* Slowly expire held state for thingslike UDP and ICMP.  The algorithm     */
3435 /* used here is to keep the queue sorted with the oldest things at the top  */


3929         if (rval == 2) {
3930                 DTRACE_PROBE1(state_keeping_timer, int, nstate);
3931                 rval = 1;
3932         }
3933         else if (rval == 1) {
3934                 tqe->tqe_state[dir] = nstate;
3935                 /*
3936                  * The nstate can either advance to a new state, or remain
3937                  * unchanged, resetting the timer by moving to the bottom of
3938                  * the queue.
3939                  */
3940                 DTRACE_PROBE1(state_done, int, nstate);
3941 
3942                 if ((tqe->tqe_flags & TQE_RULEBASED) == 0)
3943                         fr_movequeue(tqe, tqe->tqe_ifq, tqtab + nstate, ifs);
3944         }
3945 
3946         return rval;
3947 }
3948 

3949 /* ------------------------------------------------------------------------ */
3950 /* Function:    ipstate_log                                                 */
3951 /* Returns:     Nil                                                         */
3952 /* Parameters:  is(I)   - pointer to state structure                        */
3953 /*              type(I) - type of log entry to create                       */
3954 /*                                                                          */
3955 /* Creates a state table log entry using the state structure and type info. */
3956 /* passed in.  Log packet/byte counts, source/destination address and other */
3957 /* protocol specific information.                                           */
3958 /* ------------------------------------------------------------------------ */
3959 void ipstate_log(is, type, ifs)
3960 struct ipstate *is;
3961 u_int type;
3962 ipf_stack_t *ifs;
3963 {
3964 #ifdef  IPFILTER_LOG
3965         struct  ipslog  ipsl;
3966         size_t sizes[1];
3967         void *items[1];
3968         int types[1];