pflogd.c (22d6889b4d3eb8a5cb2aaaefe5bedb40e885b425) pflogd.c (61a1372b419ef876d7a8948241bc561a1866448c)
1/* $OpenBSD: pflogd.c,v 1.27 2004/02/13 19:01:57 otto Exp $ */
1/* $OpenBSD: pflogd.c,v 1.33 2005/02/09 12:09:30 henning Exp $ */
2
3/*
4 * Copyright (c) 2001 Theo de Raadt
5 * Copyright (c) 2001 Can Erkin Acar
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions

--- 15 unchanged lines hidden (view full) ---

25 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
26 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
29 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 * POSSIBILITY OF SUCH DAMAGE.
31 */
32
2
3/*
4 * Copyright (c) 2001 Theo de Raadt
5 * Copyright (c) 2001 Can Erkin Acar
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions

--- 15 unchanged lines hidden (view full) ---

25 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
26 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
29 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 * POSSIBILITY OF SUCH DAMAGE.
31 */
32
33#include <sys/cdefs.h>
34__FBSDID("$FreeBSD$");
35
36#include <sys/types.h>
37#include <sys/ioctl.h>
38#include <sys/file.h>
39#include <sys/stat.h>
40#include <stdio.h>
41#include <stdlib.h>
42#include <string.h>
43#include <unistd.h>
44#include <pcap-int.h>
45#include <pcap.h>
46#include <syslog.h>
47#include <signal.h>
48#include <errno.h>
49#include <stdarg.h>
50#include <fcntl.h>
33#include <sys/types.h>
34#include <sys/ioctl.h>
35#include <sys/file.h>
36#include <sys/stat.h>
37#include <stdio.h>
38#include <stdlib.h>
39#include <string.h>
40#include <unistd.h>
41#include <pcap-int.h>
42#include <pcap.h>
43#include <syslog.h>
44#include <signal.h>
45#include <errno.h>
46#include <stdarg.h>
47#include <fcntl.h>
51#ifdef __FreeBSD__
52#include "pidfile.h"
53#else
54#include <util.h>
48#include <util.h>
55#endif
56
57#include "pflogd.h"
58
59pcap_t *hpcap;
60static FILE *dpcap;
61
62int Debug = 0;
63static int snaplen = DEF_SNAPLEN;
64static int cur_snaplen = DEF_SNAPLEN;

--- 82 unchanged lines hidden (view full) ---

147 if (log_debug) {
148 vfprintf(stderr, message, ap);
149 fprintf(stderr, "\n");
150 } else
151 vsyslog(pri, message, ap);
152 va_end(ap);
153}
154
49#include "pflogd.h"
50
51pcap_t *hpcap;
52static FILE *dpcap;
53
54int Debug = 0;
55static int snaplen = DEF_SNAPLEN;
56static int cur_snaplen = DEF_SNAPLEN;

--- 82 unchanged lines hidden (view full) ---

139 if (log_debug) {
140 vfprintf(stderr, message, ap);
141 fprintf(stderr, "\n");
142 } else
143 vsyslog(pri, message, ap);
144 va_end(ap);
145}
146
155#ifdef __FreeBSD__
156__dead2 void
157#else
158__dead void
147__dead void
159#endif
160usage(void)
161{
162 fprintf(stderr, "usage: pflogd [-Dx] [-d delay] [-f filename] ");
163 fprintf(stderr, "[-s snaplen] [expression]\n");
164 exit(1);
165}
166
167void

--- 43 unchanged lines hidden (view full) ---

211 hpcap = NULL;
212 return (-1);
213 }
214
215 set_pcap_filter();
216
217 cur_snaplen = snaplen = pcap_snapshot(hpcap);
218
148usage(void)
149{
150 fprintf(stderr, "usage: pflogd [-Dx] [-d delay] [-f filename] ");
151 fprintf(stderr, "[-s snaplen] [expression]\n");
152 exit(1);
153}
154
155void

--- 43 unchanged lines hidden (view full) ---

199 hpcap = NULL;
200 return (-1);
201 }
202
203 set_pcap_filter();
204
205 cur_snaplen = snaplen = pcap_snapshot(hpcap);
206
219#ifdef __FreeBSD__
220 /* We can not lock bpf devices ... yet */
221#else
222 /* lock */
223 if (ioctl(pcap_fileno(hpcap), BIOCLOCK) < 0) {
224 logmsg(LOG_ERR, "BIOCLOCK: %s", strerror(errno));
225 return (-1);
226 }
207 /* lock */
208 if (ioctl(pcap_fileno(hpcap), BIOCLOCK) < 0) {
209 logmsg(LOG_ERR, "BIOCLOCK: %s", strerror(errno));
210 return (-1);
211 }
227#endif
228
229 return (0);
230}
231
232int
233set_snaplen(int snap)
234{
235 if (priv_set_snaplen(snap))

--- 30 unchanged lines hidden (view full) ---

266 */
267 fd = priv_open_log();
268 if (fd < 0)
269 return (1);
270
271 fp = fdopen(fd, "a+");
272
273 if (fp == NULL) {
212
213 return (0);
214}
215
216int
217set_snaplen(int snap)
218{
219 if (priv_set_snaplen(snap))

--- 30 unchanged lines hidden (view full) ---

250 */
251 fd = priv_open_log();
252 if (fd < 0)
253 return (1);
254
255 fp = fdopen(fd, "a+");
256
257 if (fp == NULL) {
258 close(fd);
274 logmsg(LOG_ERR, "Error: %s: %s", filename, strerror(errno));
275 return (1);
276 }
277 if (fstat(fileno(fp), &st) == -1) {
259 logmsg(LOG_ERR, "Error: %s: %s", filename, strerror(errno));
260 return (1);
261 }
262 if (fstat(fileno(fp), &st) == -1) {
263 fclose(fp);
278 logmsg(LOG_ERR, "Error: %s: %s", filename, strerror(errno));
279 return (1);
280 }
281
282 /* set FILE unbuffered, we do our own buffering */
283 if (setvbuf(fp, NULL, _IONBF, 0)) {
264 logmsg(LOG_ERR, "Error: %s: %s", filename, strerror(errno));
265 return (1);
266 }
267
268 /* set FILE unbuffered, we do our own buffering */
269 if (setvbuf(fp, NULL, _IONBF, 0)) {
270 fclose(fp);
284 logmsg(LOG_ERR, "Failed to set output buffers");
285 return (1);
286 }
287
288#define TCPDUMP_MAGIC 0xa1b2c3d4
289
290 if (st.st_size == 0) {
291 if (snaplen != cur_snaplen) {
292 logmsg(LOG_NOTICE, "Using snaplen %d", snaplen);
293 if (set_snaplen(snaplen)) {
271 logmsg(LOG_ERR, "Failed to set output buffers");
272 return (1);
273 }
274
275#define TCPDUMP_MAGIC 0xa1b2c3d4
276
277 if (st.st_size == 0) {
278 if (snaplen != cur_snaplen) {
279 logmsg(LOG_NOTICE, "Using snaplen %d", snaplen);
280 if (set_snaplen(snaplen)) {
281 fclose(fp);
294 logmsg(LOG_WARNING,
295 "Failed, using old settings");
296 }
297 }
298 hdr.magic = TCPDUMP_MAGIC;
299 hdr.version_major = PCAP_VERSION_MAJOR;
300 hdr.version_minor = PCAP_VERSION_MINOR;
301 hdr.thiszone = hpcap->tzoff;

--- 18 unchanged lines hidden (view full) ---

320
321 return (0);
322}
323
324int
325scan_dump(FILE *fp, off_t size)
326{
327 struct pcap_file_header hdr;
282 logmsg(LOG_WARNING,
283 "Failed, using old settings");
284 }
285 }
286 hdr.magic = TCPDUMP_MAGIC;
287 hdr.version_major = PCAP_VERSION_MAJOR;
288 hdr.version_minor = PCAP_VERSION_MINOR;
289 hdr.thiszone = hpcap->tzoff;

--- 18 unchanged lines hidden (view full) ---

308
309 return (0);
310}
311
312int
313scan_dump(FILE *fp, off_t size)
314{
315 struct pcap_file_header hdr;
328#ifdef __FreeBSD__
329 struct pcap_sf_pkthdr ph;
330#else
331 struct pcap_pkthdr ph;
316 struct pcap_pkthdr ph;
332#endif
333 off_t pos;
334
335 /*
336 * Must read the file, compare the header against our new
337 * options (in particular, snaplen) and adjust our options so
338 * that we generate a correct file. Furthermore, check the file
339 * for consistency so that we can append safely.
340 *

--- 53 unchanged lines hidden (view full) ---

394 return (1);
395}
396
397/* dump a packet directly to the stream, which is unbuffered */
398void
399dump_packet_nobuf(u_char *user, const struct pcap_pkthdr *h, const u_char *sp)
400{
401 FILE *f = (FILE *)user;
317 off_t pos;
318
319 /*
320 * Must read the file, compare the header against our new
321 * options (in particular, snaplen) and adjust our options so
322 * that we generate a correct file. Furthermore, check the file
323 * for consistency so that we can append safely.
324 *

--- 53 unchanged lines hidden (view full) ---

378 return (1);
379}
380
381/* dump a packet directly to the stream, which is unbuffered */
382void
383dump_packet_nobuf(u_char *user, const struct pcap_pkthdr *h, const u_char *sp)
384{
385 FILE *f = (FILE *)user;
402#ifdef __FreeBSD__
403 struct pcap_sf_pkthdr sh;
404#endif
405
406 if (suspended) {
407 packets_dropped++;
408 return;
409 }
410
386
387 if (suspended) {
388 packets_dropped++;
389 return;
390 }
391
411#ifdef __FreeBSD__
412 sh.ts.tv_sec = (bpf_int32)h->ts.tv_sec;
413 sh.ts.tv_usec = (bpf_int32)h->ts.tv_usec;
414 sh.caplen = h->caplen;
415 sh.len = h->len;
416
417 if (fwrite((char *)&sh, sizeof(sh), 1, f) != 1) {
418#else
419 if (fwrite((char *)h, sizeof(*h), 1, f) != 1) {
392 if (fwrite((char *)h, sizeof(*h), 1, f) != 1) {
420#endif
421 /* try to undo header to prevent corruption */
422 off_t pos = ftello(f);
393 off_t pos = ftello(f);
423#ifdef __FreeBSD__
424 if (pos < sizeof(sh) ||
425 ftruncate(fileno(f), pos - sizeof(sh))) {
426#else
394
395 /* try to undo header to prevent corruption */
427 if (pos < sizeof(*h) ||
428 ftruncate(fileno(f), pos - sizeof(*h))) {
396 if (pos < sizeof(*h) ||
397 ftruncate(fileno(f), pos - sizeof(*h))) {
429#endif
430 logmsg(LOG_ERR, "Write failed, corrupted logfile!");
431 set_suspended(1);
432 gotsig_close = 1;
433 return;
434 }
435 goto error;
436 }
437

--- 52 unchanged lines hidden (view full) ---

490 bufpkt = 0;
491}
492
493/* append packet to the buffer, flushing if necessary */
494void
495dump_packet(u_char *user, const struct pcap_pkthdr *h, const u_char *sp)
496{
497 FILE *f = (FILE *)user;
398 logmsg(LOG_ERR, "Write failed, corrupted logfile!");
399 set_suspended(1);
400 gotsig_close = 1;
401 return;
402 }
403 goto error;
404 }
405

--- 52 unchanged lines hidden (view full) ---

458 bufpkt = 0;
459}
460
461/* append packet to the buffer, flushing if necessary */
462void
463dump_packet(u_char *user, const struct pcap_pkthdr *h, const u_char *sp)
464{
465 FILE *f = (FILE *)user;
498#ifdef __FreeBSD__
499 struct pcap_sf_pkthdr sh;
500 size_t len = sizeof(sh) + h->caplen;
501#else
502 size_t len = sizeof(*h) + h->caplen;
466 size_t len = sizeof(*h) + h->caplen;
503#endif
504
505 if (len < sizeof(*h) || h->caplen > (size_t)cur_snaplen) {
506 logmsg(LOG_NOTICE, "invalid size %u (%u/%u), packet dropped",
507 len, cur_snaplen, snaplen);
508 packets_dropped++;
509 return;
510 }
511

--- 10 unchanged lines hidden (view full) ---

522 return;
523 }
524
525 if (len > bufleft) {
526 dump_packet_nobuf(user, h, sp);
527 return;
528 }
529
467
468 if (len < sizeof(*h) || h->caplen > (size_t)cur_snaplen) {
469 logmsg(LOG_NOTICE, "invalid size %u (%u/%u), packet dropped",
470 len, cur_snaplen, snaplen);
471 packets_dropped++;
472 return;
473 }
474

--- 10 unchanged lines hidden (view full) ---

485 return;
486 }
487
488 if (len > bufleft) {
489 dump_packet_nobuf(user, h, sp);
490 return;
491 }
492
530 append:
531#ifdef __FreeBSD__
532 sh.ts.tv_sec = (bpf_int32)h->ts.tv_sec;
533 sh.ts.tv_usec = (bpf_int32)h->ts.tv_usec;
534 sh.caplen = h->caplen;
535 sh.len = h->len;
536
537 memcpy(bufpos, &sh, sizeof(sh));
538 memcpy(bufpos + sizeof(sh), sp, h->caplen);
539#else
493 append:
540 memcpy(bufpos, h, sizeof(*h));
541 memcpy(bufpos + sizeof(*h), sp, h->caplen);
494 memcpy(bufpos, h, sizeof(*h));
495 memcpy(bufpos + sizeof(*h), sp, h->caplen);
542#endif
543
544 bufpos += len;
545 bufleft -= len;
546 bufpkt++;
547
548 return;
549}
550
551int
552main(int argc, char **argv)
553{
554 struct pcap_stat pstat;
555 int ch, np, Xflag = 0;
556 pcap_handler phandler = dump_packet;
496
497 bufpos += len;
498 bufleft -= len;
499 bufpkt++;
500
501 return;
502}
503
504int
505main(int argc, char **argv)
506{
507 struct pcap_stat pstat;
508 int ch, np, Xflag = 0;
509 pcap_handler phandler = dump_packet;
510 const char *errstr = NULL;
557
511
558#ifdef __FreeBSD__
559 /* another ?paranoid? safety measure we do not have */
560#else
561 closefrom(STDERR_FILENO + 1);
512 closefrom(STDERR_FILENO + 1);
562#endif
563
564 while ((ch = getopt(argc, argv, "Dxd:s:f:")) != -1) {
565 switch (ch) {
566 case 'D':
567 Debug = 1;
568 break;
569 case 'd':
513
514 while ((ch = getopt(argc, argv, "Dxd:s:f:")) != -1) {
515 switch (ch) {
516 case 'D':
517 Debug = 1;
518 break;
519 case 'd':
570 delay = atoi(optarg);
571 if (delay < 5 || delay > 60*60)
520 delay = strtonum(optarg, 5, 60*60, &errstr);
521 if (errstr)
572 usage();
573 break;
574 case 'f':
575 filename = optarg;
576 break;
577 case 's':
522 usage();
523 break;
524 case 'f':
525 filename = optarg;
526 break;
527 case 's':
578 snaplen = atoi(optarg);
528 snaplen = strtonum(optarg, 0, PFLOGD_MAXSNAPLEN,
529 &errstr);
579 if (snaplen <= 0)
580 snaplen = DEF_SNAPLEN;
530 if (snaplen <= 0)
531 snaplen = DEF_SNAPLEN;
581 if (snaplen > PFLOGD_MAXSNAPLEN)
532 if (errstr)
582 snaplen = PFLOGD_MAXSNAPLEN;
583 break;
584 case 'x':
585 Xflag++;
586 break;
587 default:
588 usage();
589 }

--- 8 unchanged lines hidden (view full) ---

598 openlog("pflogd", LOG_PID | LOG_CONS, LOG_DAEMON);
599 if (daemon(0, 0)) {
600 logmsg(LOG_WARNING, "Failed to become daemon: %s",
601 strerror(errno));
602 }
603 pidfile(NULL);
604 }
605
533 snaplen = PFLOGD_MAXSNAPLEN;
534 break;
535 case 'x':
536 Xflag++;
537 break;
538 default:
539 usage();
540 }

--- 8 unchanged lines hidden (view full) ---

549 openlog("pflogd", LOG_PID | LOG_CONS, LOG_DAEMON);
550 if (daemon(0, 0)) {
551 logmsg(LOG_WARNING, "Failed to become daemon: %s",
552 strerror(errno));
553 }
554 pidfile(NULL);
555 }
556
557 tzset();
606 (void)umask(S_IRWXG | S_IRWXO);
607
608 /* filter will be used by the privileged process */
609 if (argc) {
610 filter = copy_argv(argv);
611 if (filter == NULL)
612 logmsg(LOG_NOTICE, "Failed to form filter expression");
613 }

--- 36 unchanged lines hidden (view full) ---

650
651 logmsg(LOG_ERR, "Logging suspended: open error");
652 set_suspended(1);
653 } else if (Xflag)
654 return (0);
655
656 while (1) {
657 np = pcap_dispatch(hpcap, PCAP_NUM_PKTS,
558 (void)umask(S_IRWXG | S_IRWXO);
559
560 /* filter will be used by the privileged process */
561 if (argc) {
562 filter = copy_argv(argv);
563 if (filter == NULL)
564 logmsg(LOG_NOTICE, "Failed to form filter expression");
565 }

--- 36 unchanged lines hidden (view full) ---

602
603 logmsg(LOG_ERR, "Logging suspended: open error");
604 set_suspended(1);
605 } else if (Xflag)
606 return (0);
607
608 while (1) {
609 np = pcap_dispatch(hpcap, PCAP_NUM_PKTS,
658 dump_packet, (u_char *)dpcap);
659 if (np < 0) {
660#ifdef __FreeBSD__
661 if (errno == ENXIO) {
662 logmsg(LOG_ERR,
663 "Device not/no longer configured");
664 break;
665 }
666#endif
610 phandler, (u_char *)dpcap);
611 if (np < 0)
667 logmsg(LOG_NOTICE, "%s", pcap_geterr(hpcap));
612 logmsg(LOG_NOTICE, "%s", pcap_geterr(hpcap));
668 }
669
670 if (gotsig_close)
671 break;
672 if (gotsig_hup) {
673 if (reset_dump()) {
674 logmsg(LOG_ERR,
675 "Logging suspended: open error");
676 set_suspended(1);

--- 31 unchanged lines hidden ---
613
614 if (gotsig_close)
615 break;
616 if (gotsig_hup) {
617 if (reset_dump()) {
618 logmsg(LOG_ERR,
619 "Logging suspended: open error");
620 set_suspended(1);

--- 31 unchanged lines hidden ---