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
|