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