1315a7da3SJan Lentfer /* $OpenBSD: pflogd.c,v 1.45 2007/06/06 14:11:26 henning Exp $ */
295cc27f0SJoerg Sonnenberger
395cc27f0SJoerg Sonnenberger /*
495cc27f0SJoerg Sonnenberger * Copyright (c) 2001 Theo de Raadt
595cc27f0SJoerg Sonnenberger * Copyright (c) 2001 Can Erkin Acar
695cc27f0SJoerg Sonnenberger * All rights reserved.
795cc27f0SJoerg Sonnenberger *
895cc27f0SJoerg Sonnenberger * Redistribution and use in source and binary forms, with or without
995cc27f0SJoerg Sonnenberger * modification, are permitted provided that the following conditions
1095cc27f0SJoerg Sonnenberger * are met:
1195cc27f0SJoerg Sonnenberger *
1295cc27f0SJoerg Sonnenberger * - Redistributions of source code must retain the above copyright
1395cc27f0SJoerg Sonnenberger * notice, this list of conditions and the following disclaimer.
1495cc27f0SJoerg Sonnenberger * - Redistributions in binary form must reproduce the above
1595cc27f0SJoerg Sonnenberger * copyright notice, this list of conditions and the following
1695cc27f0SJoerg Sonnenberger * disclaimer in the documentation and/or other materials provided
1795cc27f0SJoerg Sonnenberger * with the distribution.
1895cc27f0SJoerg Sonnenberger *
1995cc27f0SJoerg Sonnenberger * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2095cc27f0SJoerg Sonnenberger * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2195cc27f0SJoerg Sonnenberger * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
2295cc27f0SJoerg Sonnenberger * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
2395cc27f0SJoerg Sonnenberger * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
2495cc27f0SJoerg Sonnenberger * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
2595cc27f0SJoerg Sonnenberger * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
2695cc27f0SJoerg Sonnenberger * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
2795cc27f0SJoerg Sonnenberger * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2895cc27f0SJoerg Sonnenberger * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
2995cc27f0SJoerg Sonnenberger * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
3095cc27f0SJoerg Sonnenberger * POSSIBILITY OF SUCH DAMAGE.
3195cc27f0SJoerg Sonnenberger */
3295cc27f0SJoerg Sonnenberger
3395cc27f0SJoerg Sonnenberger #include <sys/types.h>
3495cc27f0SJoerg Sonnenberger #include <sys/ioctl.h>
3595cc27f0SJoerg Sonnenberger #include <sys/file.h>
3695cc27f0SJoerg Sonnenberger #include <sys/stat.h>
37315a7da3SJan Lentfer #include <sys/socket.h>
38315a7da3SJan Lentfer #include <net/if.h>
39315a7da3SJan Lentfer
4095cc27f0SJoerg Sonnenberger #include <errno.h>
41315a7da3SJan Lentfer #include <err.h>
4295cc27f0SJoerg Sonnenberger #include <fcntl.h>
4395cc27f0SJoerg Sonnenberger #include <syslog.h>
4495cc27f0SJoerg Sonnenberger #include <signal.h>
4595cc27f0SJoerg Sonnenberger #include <stdarg.h>
4695cc27f0SJoerg Sonnenberger #include <stdio.h>
4795cc27f0SJoerg Sonnenberger #include <stdlib.h>
4895cc27f0SJoerg Sonnenberger #include <string.h>
4995cc27f0SJoerg Sonnenberger #include <unistd.h>
5095cc27f0SJoerg Sonnenberger
5195cc27f0SJoerg Sonnenberger #include <libutil.h>
5295cc27f0SJoerg Sonnenberger #include <pcap-int.h>
5395cc27f0SJoerg Sonnenberger #include <pcap.h>
5495cc27f0SJoerg Sonnenberger
5595cc27f0SJoerg Sonnenberger #include "pflogd.h"
5695cc27f0SJoerg Sonnenberger
5795cc27f0SJoerg Sonnenberger pcap_t *hpcap;
5895cc27f0SJoerg Sonnenberger static FILE *dpcap;
5995cc27f0SJoerg Sonnenberger
6095cc27f0SJoerg Sonnenberger int Debug = 0;
6195cc27f0SJoerg Sonnenberger static int snaplen = DEF_SNAPLEN;
6295cc27f0SJoerg Sonnenberger static int cur_snaplen = DEF_SNAPLEN;
6395cc27f0SJoerg Sonnenberger
64e437855fSPeeter volatile sig_atomic_t gotsig_close, gotsig_alrm, gotsig_hup, gotsig_usr1;
6595cc27f0SJoerg Sonnenberger
6695cc27f0SJoerg Sonnenberger const char *filename = PFLOGD_LOG_FILE;
6795cc27f0SJoerg Sonnenberger const char *interface = PFLOGD_DEFAULT_IF;
6895cc27f0SJoerg Sonnenberger char *filter = NULL;
6995cc27f0SJoerg Sonnenberger
7095cc27f0SJoerg Sonnenberger char errbuf[PCAP_ERRBUF_SIZE];
7195cc27f0SJoerg Sonnenberger
7295cc27f0SJoerg Sonnenberger int log_debug = 0;
7395cc27f0SJoerg Sonnenberger unsigned int delay = FLUSH_DELAY;
7495cc27f0SJoerg Sonnenberger
7595cc27f0SJoerg Sonnenberger char *copy_argv(char * const *);
7695cc27f0SJoerg Sonnenberger void dump_packet(u_char *, const struct pcap_pkthdr *, const u_char *);
7795cc27f0SJoerg Sonnenberger void dump_packet_nobuf(u_char *, const struct pcap_pkthdr *, const u_char *);
78e437855fSPeeter void log_pcap_stats(void);
7995cc27f0SJoerg Sonnenberger int flush_buffer(FILE *);
80315a7da3SJan Lentfer int if_exists(char *);
8195cc27f0SJoerg Sonnenberger int init_pcap(void);
8295cc27f0SJoerg Sonnenberger void purge_buffer(void);
83c929e0dfSJan Lentfer int reset_dump(int);
8495cc27f0SJoerg Sonnenberger int scan_dump(FILE *, off_t);
8595cc27f0SJoerg Sonnenberger int set_snaplen(int);
8695cc27f0SJoerg Sonnenberger void set_suspended(int);
8795cc27f0SJoerg Sonnenberger void sig_alrm(int);
88e437855fSPeeter void sig_usr1(int);
8995cc27f0SJoerg Sonnenberger void sig_close(int);
9095cc27f0SJoerg Sonnenberger void sig_hup(int);
91fe08e20dSSascha Wildner void usage(void) __dead2;
9295cc27f0SJoerg Sonnenberger
93c929e0dfSJan Lentfer static int try_reset_dump(int);
94c929e0dfSJan Lentfer
9595cc27f0SJoerg Sonnenberger /* buffer must always be greater than snaplen */
9695cc27f0SJoerg Sonnenberger static int bufpkt = 0; /* number of packets in buffer */
9795cc27f0SJoerg Sonnenberger static size_t buflen = 0; /* allocated size of buffer */
9895cc27f0SJoerg Sonnenberger static char *buffer = NULL; /* packet buffer */
9995cc27f0SJoerg Sonnenberger static char *bufpos = NULL; /* position in buffer */
10095cc27f0SJoerg Sonnenberger static size_t bufleft = 0; /* bytes left in buffer */
10195cc27f0SJoerg Sonnenberger
10295cc27f0SJoerg Sonnenberger /* if error, stop logging but count dropped packets */
10395cc27f0SJoerg Sonnenberger static int suspended = -1;
10495cc27f0SJoerg Sonnenberger static long packets_dropped = 0;
10595cc27f0SJoerg Sonnenberger
10695cc27f0SJoerg Sonnenberger void
set_suspended(int s)10795cc27f0SJoerg Sonnenberger set_suspended(int s)
10895cc27f0SJoerg Sonnenberger {
10995cc27f0SJoerg Sonnenberger if (suspended == s)
11095cc27f0SJoerg Sonnenberger return;
11195cc27f0SJoerg Sonnenberger
11295cc27f0SJoerg Sonnenberger suspended = s;
113c929e0dfSJan Lentfer setproctitle("[%s] -s %d -i %s -f %s",
114c929e0dfSJan Lentfer suspended ? "suspended" : "running",
115c929e0dfSJan Lentfer cur_snaplen, interface, filename);
11695cc27f0SJoerg Sonnenberger }
11795cc27f0SJoerg Sonnenberger
11895cc27f0SJoerg Sonnenberger char *
copy_argv(char * const * argv)11995cc27f0SJoerg Sonnenberger copy_argv(char * const *argv)
12095cc27f0SJoerg Sonnenberger {
12195cc27f0SJoerg Sonnenberger size_t len = 0, n;
12295cc27f0SJoerg Sonnenberger char *buf;
12395cc27f0SJoerg Sonnenberger
12495cc27f0SJoerg Sonnenberger if (argv == NULL)
12595cc27f0SJoerg Sonnenberger return (NULL);
12695cc27f0SJoerg Sonnenberger
12795cc27f0SJoerg Sonnenberger for (n = 0; argv[n]; n++)
12895cc27f0SJoerg Sonnenberger len += strlen(argv[n])+1;
12995cc27f0SJoerg Sonnenberger if (len == 0)
13095cc27f0SJoerg Sonnenberger return (NULL);
13195cc27f0SJoerg Sonnenberger
13295cc27f0SJoerg Sonnenberger buf = malloc(len);
13395cc27f0SJoerg Sonnenberger if (buf == NULL)
13495cc27f0SJoerg Sonnenberger return (NULL);
13595cc27f0SJoerg Sonnenberger
13695cc27f0SJoerg Sonnenberger strlcpy(buf, argv[0], len);
13795cc27f0SJoerg Sonnenberger for (n = 1; argv[n]; n++) {
13895cc27f0SJoerg Sonnenberger strlcat(buf, " ", len);
13995cc27f0SJoerg Sonnenberger strlcat(buf, argv[n], len);
14095cc27f0SJoerg Sonnenberger }
14195cc27f0SJoerg Sonnenberger return (buf);
14295cc27f0SJoerg Sonnenberger }
14395cc27f0SJoerg Sonnenberger
14495cc27f0SJoerg Sonnenberger void
logmsg(int pri,const char * message,...)14595cc27f0SJoerg Sonnenberger logmsg(int pri, const char *message, ...)
14695cc27f0SJoerg Sonnenberger {
14795cc27f0SJoerg Sonnenberger va_list ap;
14895cc27f0SJoerg Sonnenberger va_start(ap, message);
14995cc27f0SJoerg Sonnenberger
15095cc27f0SJoerg Sonnenberger if (log_debug) {
15195cc27f0SJoerg Sonnenberger vfprintf(stderr, message, ap);
15295cc27f0SJoerg Sonnenberger fprintf(stderr, "\n");
15395cc27f0SJoerg Sonnenberger } else
15495cc27f0SJoerg Sonnenberger vsyslog(pri, message, ap);
15595cc27f0SJoerg Sonnenberger va_end(ap);
15695cc27f0SJoerg Sonnenberger }
15795cc27f0SJoerg Sonnenberger
15895cc27f0SJoerg Sonnenberger void
usage(void)15995cc27f0SJoerg Sonnenberger usage(void)
16095cc27f0SJoerg Sonnenberger {
16195cc27f0SJoerg Sonnenberger fprintf(stderr, "usage: pflogd [-Dx] [-d delay] [-f filename]");
162315a7da3SJan Lentfer fprintf(stderr, " [-i interface] [-p pidfile]\n");
163315a7da3SJan Lentfer fprintf(stderr, " [-s snaplen] [expression]\n");
16495cc27f0SJoerg Sonnenberger exit(1);
16595cc27f0SJoerg Sonnenberger }
16695cc27f0SJoerg Sonnenberger
16795cc27f0SJoerg Sonnenberger void
sig_close(int sig __unused)16895cc27f0SJoerg Sonnenberger sig_close(int sig __unused)
16995cc27f0SJoerg Sonnenberger {
17095cc27f0SJoerg Sonnenberger gotsig_close = 1;
17195cc27f0SJoerg Sonnenberger }
17295cc27f0SJoerg Sonnenberger
17395cc27f0SJoerg Sonnenberger void
sig_hup(int sig __unused)17495cc27f0SJoerg Sonnenberger sig_hup(int sig __unused)
17595cc27f0SJoerg Sonnenberger {
17695cc27f0SJoerg Sonnenberger gotsig_hup = 1;
17795cc27f0SJoerg Sonnenberger }
17895cc27f0SJoerg Sonnenberger
17995cc27f0SJoerg Sonnenberger void
sig_alrm(int sig __unused)18095cc27f0SJoerg Sonnenberger sig_alrm(int sig __unused)
18195cc27f0SJoerg Sonnenberger {
18295cc27f0SJoerg Sonnenberger gotsig_alrm = 1;
18395cc27f0SJoerg Sonnenberger }
18495cc27f0SJoerg Sonnenberger
18595cc27f0SJoerg Sonnenberger void
sig_usr1(int sig __unused)186e437855fSPeeter sig_usr1(int sig __unused)
187e437855fSPeeter {
188e437855fSPeeter gotsig_usr1 = 1;
189e437855fSPeeter }
190e437855fSPeeter
191e437855fSPeeter void
set_pcap_filter(void)19295cc27f0SJoerg Sonnenberger set_pcap_filter(void)
19395cc27f0SJoerg Sonnenberger {
19495cc27f0SJoerg Sonnenberger struct bpf_program bprog;
19595cc27f0SJoerg Sonnenberger
19695cc27f0SJoerg Sonnenberger if (pcap_compile(hpcap, &bprog, filter, PCAP_OPT_FIL, 0) < 0)
19795cc27f0SJoerg Sonnenberger logmsg(LOG_WARNING, "%s", pcap_geterr(hpcap));
19895cc27f0SJoerg Sonnenberger else {
19995cc27f0SJoerg Sonnenberger if (pcap_setfilter(hpcap, &bprog) < 0)
20095cc27f0SJoerg Sonnenberger logmsg(LOG_WARNING, "%s", pcap_geterr(hpcap));
20195cc27f0SJoerg Sonnenberger pcap_freecode(&bprog);
20295cc27f0SJoerg Sonnenberger }
20395cc27f0SJoerg Sonnenberger }
20495cc27f0SJoerg Sonnenberger
20595cc27f0SJoerg Sonnenberger int
if_exists(char * ifname)206315a7da3SJan Lentfer if_exists(char *ifname)
207315a7da3SJan Lentfer {
208315a7da3SJan Lentfer int s;
209315a7da3SJan Lentfer struct ifreq ifr;
210315a7da3SJan Lentfer struct if_data ifrdat;
211315a7da3SJan Lentfer
212315a7da3SJan Lentfer if ((s = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
213315a7da3SJan Lentfer err(1, "socket");
214315a7da3SJan Lentfer bzero(&ifr, sizeof(ifr));
215315a7da3SJan Lentfer if (strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)) >=
216315a7da3SJan Lentfer sizeof(ifr.ifr_name))
217315a7da3SJan Lentfer errx(1, "main ifr_name: strlcpy");
218315a7da3SJan Lentfer ifr.ifr_data = (caddr_t)&ifrdat;
219315a7da3SJan Lentfer if (ioctl(s, SIOCGIFDATA, (caddr_t)&ifr) == -1)
220315a7da3SJan Lentfer return (0);
221315a7da3SJan Lentfer if (close(s))
222315a7da3SJan Lentfer err(1, "close");
223315a7da3SJan Lentfer
224315a7da3SJan Lentfer return (1);
225315a7da3SJan Lentfer }
226315a7da3SJan Lentfer
227315a7da3SJan Lentfer int
init_pcap(void)22895cc27f0SJoerg Sonnenberger init_pcap(void)
22995cc27f0SJoerg Sonnenberger {
23095cc27f0SJoerg Sonnenberger hpcap = pcap_open_live(interface, snaplen, 1, PCAP_TO_MS, errbuf);
23195cc27f0SJoerg Sonnenberger if (hpcap == NULL) {
23295cc27f0SJoerg Sonnenberger logmsg(LOG_ERR, "Failed to initialize: %s", errbuf);
23395cc27f0SJoerg Sonnenberger return (-1);
23495cc27f0SJoerg Sonnenberger }
23595cc27f0SJoerg Sonnenberger
23695cc27f0SJoerg Sonnenberger if (pcap_datalink(hpcap) != DLT_PFLOG) {
23795cc27f0SJoerg Sonnenberger logmsg(LOG_ERR, "Invalid datalink type");
23895cc27f0SJoerg Sonnenberger pcap_close(hpcap);
23995cc27f0SJoerg Sonnenberger hpcap = NULL;
24095cc27f0SJoerg Sonnenberger return (-1);
24195cc27f0SJoerg Sonnenberger }
24295cc27f0SJoerg Sonnenberger
24395cc27f0SJoerg Sonnenberger set_pcap_filter();
24495cc27f0SJoerg Sonnenberger
24595cc27f0SJoerg Sonnenberger cur_snaplen = snaplen = pcap_snapshot(hpcap);
24695cc27f0SJoerg Sonnenberger
24795cc27f0SJoerg Sonnenberger /* From contrib/pf/pflogd.c 1.5 FreeBSD: BPF locking is not
24895cc27f0SJoerg Sonnenberger * (yet) supported.
24995cc27f0SJoerg Sonnenberger */
25095cc27f0SJoerg Sonnenberger #ifndef __DragonFly__
25195cc27f0SJoerg Sonnenberger /* lock */
25295cc27f0SJoerg Sonnenberger if (ioctl(pcap_fileno(hpcap), BIOCLOCK) < 0) {
25395cc27f0SJoerg Sonnenberger logmsg(LOG_ERR, "BIOCLOCK: %s", strerror(errno));
25495cc27f0SJoerg Sonnenberger return (-1);
25595cc27f0SJoerg Sonnenberger }
25695cc27f0SJoerg Sonnenberger #endif
25795cc27f0SJoerg Sonnenberger
25895cc27f0SJoerg Sonnenberger return (0);
25995cc27f0SJoerg Sonnenberger }
26095cc27f0SJoerg Sonnenberger
26195cc27f0SJoerg Sonnenberger int
set_snaplen(int snap)26295cc27f0SJoerg Sonnenberger set_snaplen(int snap)
26395cc27f0SJoerg Sonnenberger {
26495cc27f0SJoerg Sonnenberger if (priv_set_snaplen(snap))
26595cc27f0SJoerg Sonnenberger return (1);
26695cc27f0SJoerg Sonnenberger
26795cc27f0SJoerg Sonnenberger if (cur_snaplen > snap)
26895cc27f0SJoerg Sonnenberger purge_buffer();
26995cc27f0SJoerg Sonnenberger
27095cc27f0SJoerg Sonnenberger cur_snaplen = snap;
27195cc27f0SJoerg Sonnenberger
27295cc27f0SJoerg Sonnenberger return (0);
27395cc27f0SJoerg Sonnenberger }
27495cc27f0SJoerg Sonnenberger
27595cc27f0SJoerg Sonnenberger int
reset_dump(int nomove)276c929e0dfSJan Lentfer reset_dump(int nomove)
277c929e0dfSJan Lentfer {
278c929e0dfSJan Lentfer int ret;
279c929e0dfSJan Lentfer
280c929e0dfSJan Lentfer for (;;) {
281c929e0dfSJan Lentfer ret = try_reset_dump(nomove);
282c929e0dfSJan Lentfer if (ret <= 0)
283c929e0dfSJan Lentfer break;
284c929e0dfSJan Lentfer }
285c929e0dfSJan Lentfer
286c929e0dfSJan Lentfer return (ret);
287c929e0dfSJan Lentfer }
288c929e0dfSJan Lentfer
289c929e0dfSJan Lentfer /*
290c929e0dfSJan Lentfer * tries to (re)open log file, nomove flag is used with -x switch
291c929e0dfSJan Lentfer * returns 0: success, 1: retry (log moved), -1: error
292c929e0dfSJan Lentfer */
293c929e0dfSJan Lentfer int
try_reset_dump(int nomove)294c929e0dfSJan Lentfer try_reset_dump(int nomove)
29595cc27f0SJoerg Sonnenberger {
29695cc27f0SJoerg Sonnenberger struct pcap_file_header hdr;
29795cc27f0SJoerg Sonnenberger struct stat st;
29895cc27f0SJoerg Sonnenberger int fd;
29995cc27f0SJoerg Sonnenberger FILE *fp;
30095cc27f0SJoerg Sonnenberger
30195cc27f0SJoerg Sonnenberger if (hpcap == NULL)
30295cc27f0SJoerg Sonnenberger return (-1);
30395cc27f0SJoerg Sonnenberger
30495cc27f0SJoerg Sonnenberger if (dpcap) {
30595cc27f0SJoerg Sonnenberger flush_buffer(dpcap);
30695cc27f0SJoerg Sonnenberger fclose(dpcap);
30795cc27f0SJoerg Sonnenberger dpcap = NULL;
30895cc27f0SJoerg Sonnenberger }
30995cc27f0SJoerg Sonnenberger
31095cc27f0SJoerg Sonnenberger /*
31195cc27f0SJoerg Sonnenberger * Basically reimplement pcap_dump_open() because it truncates
31295cc27f0SJoerg Sonnenberger * files and duplicates headers and such.
31395cc27f0SJoerg Sonnenberger */
31495cc27f0SJoerg Sonnenberger fd = priv_open_log();
31595cc27f0SJoerg Sonnenberger if (fd < 0)
316c929e0dfSJan Lentfer return (-1);
31795cc27f0SJoerg Sonnenberger
31895cc27f0SJoerg Sonnenberger fp = fdopen(fd, "a+");
31995cc27f0SJoerg Sonnenberger
32095cc27f0SJoerg Sonnenberger if (fp == NULL) {
32195cc27f0SJoerg Sonnenberger logmsg(LOG_ERR, "Error: %s: %s", filename, strerror(errno));
322c929e0dfSJan Lentfer close(fd);
323c929e0dfSJan Lentfer return (-1);
32495cc27f0SJoerg Sonnenberger }
32595cc27f0SJoerg Sonnenberger if (fstat(fileno(fp), &st) == -1) {
32695cc27f0SJoerg Sonnenberger logmsg(LOG_ERR, "Error: %s: %s", filename, strerror(errno));
327c929e0dfSJan Lentfer fclose(fp);
328c929e0dfSJan Lentfer return (-1);
32995cc27f0SJoerg Sonnenberger }
33095cc27f0SJoerg Sonnenberger
33195cc27f0SJoerg Sonnenberger /* set FILE unbuffered, we do our own buffering */
33295cc27f0SJoerg Sonnenberger if (setvbuf(fp, NULL, _IONBF, 0)) {
33395cc27f0SJoerg Sonnenberger logmsg(LOG_ERR, "Failed to set output buffers");
334c929e0dfSJan Lentfer fclose(fp);
335c929e0dfSJan Lentfer return (-1);
33695cc27f0SJoerg Sonnenberger }
33795cc27f0SJoerg Sonnenberger
33895cc27f0SJoerg Sonnenberger #define TCPDUMP_MAGIC 0xa1b2c3d4
33995cc27f0SJoerg Sonnenberger
34095cc27f0SJoerg Sonnenberger if (st.st_size == 0) {
34195cc27f0SJoerg Sonnenberger if (snaplen != cur_snaplen) {
34295cc27f0SJoerg Sonnenberger logmsg(LOG_NOTICE, "Using snaplen %d", snaplen);
343c929e0dfSJan Lentfer if (set_snaplen(snaplen))
34495cc27f0SJoerg Sonnenberger logmsg(LOG_WARNING,
34595cc27f0SJoerg Sonnenberger "Failed, using old settings");
34695cc27f0SJoerg Sonnenberger }
34795cc27f0SJoerg Sonnenberger hdr.magic = TCPDUMP_MAGIC;
34895cc27f0SJoerg Sonnenberger hdr.version_major = PCAP_VERSION_MAJOR;
34995cc27f0SJoerg Sonnenberger hdr.version_minor = PCAP_VERSION_MINOR;
350*3f75611eSAntonio Huete Jimenez /* https://www.tcpdump.org/manpages/pcap-savefile.5.txt */
351*3f75611eSAntonio Huete Jimenez hdr.thiszone = 0;
35295cc27f0SJoerg Sonnenberger hdr.snaplen = hpcap->snapshot;
35395cc27f0SJoerg Sonnenberger hdr.sigfigs = 0;
35495cc27f0SJoerg Sonnenberger hdr.linktype = hpcap->linktype;
35595cc27f0SJoerg Sonnenberger
35695cc27f0SJoerg Sonnenberger if (fwrite((char *)&hdr, sizeof(hdr), 1, fp) != 1) {
35795cc27f0SJoerg Sonnenberger fclose(fp);
358c929e0dfSJan Lentfer return (-1);
35995cc27f0SJoerg Sonnenberger }
36095cc27f0SJoerg Sonnenberger } else if (scan_dump(fp, st.st_size)) {
36195cc27f0SJoerg Sonnenberger fclose(fp);
362c929e0dfSJan Lentfer if (nomove || priv_move_log()) {
363c929e0dfSJan Lentfer logmsg(LOG_ERR,
364c929e0dfSJan Lentfer "Invalid/incompatible log file, move it away");
365c929e0dfSJan Lentfer return (-1);
366c929e0dfSJan Lentfer }
36795cc27f0SJoerg Sonnenberger return (1);
36895cc27f0SJoerg Sonnenberger }
36995cc27f0SJoerg Sonnenberger
37095cc27f0SJoerg Sonnenberger dpcap = fp;
37195cc27f0SJoerg Sonnenberger
37295cc27f0SJoerg Sonnenberger set_suspended(0);
37395cc27f0SJoerg Sonnenberger flush_buffer(fp);
37495cc27f0SJoerg Sonnenberger
37595cc27f0SJoerg Sonnenberger return (0);
37695cc27f0SJoerg Sonnenberger }
37795cc27f0SJoerg Sonnenberger
37895cc27f0SJoerg Sonnenberger int
scan_dump(FILE * fp,off_t size)37995cc27f0SJoerg Sonnenberger scan_dump(FILE *fp, off_t size)
38095cc27f0SJoerg Sonnenberger {
38195cc27f0SJoerg Sonnenberger struct pcap_file_header hdr;
382e437855fSPeeter struct pcap_sf_pkthdr ph;
38395cc27f0SJoerg Sonnenberger off_t pos;
38495cc27f0SJoerg Sonnenberger
38595cc27f0SJoerg Sonnenberger /*
38695cc27f0SJoerg Sonnenberger * Must read the file, compare the header against our new
38795cc27f0SJoerg Sonnenberger * options (in particular, snaplen) and adjust our options so
38895cc27f0SJoerg Sonnenberger * that we generate a correct file. Furthermore, check the file
38995cc27f0SJoerg Sonnenberger * for consistency so that we can append safely.
39095cc27f0SJoerg Sonnenberger *
39195cc27f0SJoerg Sonnenberger * XXX this may take a long time for large logs.
39295cc27f0SJoerg Sonnenberger */
39371126e33SSascha Wildner fseek(fp, 0L, SEEK_SET);
39495cc27f0SJoerg Sonnenberger
39595cc27f0SJoerg Sonnenberger if (fread((char *)&hdr, sizeof(hdr), 1, fp) != 1) {
39695cc27f0SJoerg Sonnenberger logmsg(LOG_ERR, "Short file header");
39795cc27f0SJoerg Sonnenberger return (1);
39895cc27f0SJoerg Sonnenberger }
39995cc27f0SJoerg Sonnenberger
40095cc27f0SJoerg Sonnenberger if (hdr.magic != TCPDUMP_MAGIC ||
40195cc27f0SJoerg Sonnenberger hdr.version_major != PCAP_VERSION_MAJOR ||
40295cc27f0SJoerg Sonnenberger hdr.version_minor != PCAP_VERSION_MINOR ||
40395cc27f0SJoerg Sonnenberger (int)hdr.linktype != hpcap->linktype ||
40495cc27f0SJoerg Sonnenberger hdr.snaplen > PFLOGD_MAXSNAPLEN) {
40595cc27f0SJoerg Sonnenberger return (1);
40695cc27f0SJoerg Sonnenberger }
40795cc27f0SJoerg Sonnenberger
40895cc27f0SJoerg Sonnenberger pos = sizeof(hdr);
40995cc27f0SJoerg Sonnenberger
41095cc27f0SJoerg Sonnenberger while (!feof(fp)) {
41195cc27f0SJoerg Sonnenberger off_t len = fread((char *)&ph, 1, sizeof(ph), fp);
41295cc27f0SJoerg Sonnenberger if (len == 0)
41395cc27f0SJoerg Sonnenberger break;
41495cc27f0SJoerg Sonnenberger
41595cc27f0SJoerg Sonnenberger if (len != sizeof(ph))
41695cc27f0SJoerg Sonnenberger goto error;
41795cc27f0SJoerg Sonnenberger if (ph.caplen > hdr.snaplen || ph.caplen > PFLOGD_MAXSNAPLEN)
41895cc27f0SJoerg Sonnenberger goto error;
41995cc27f0SJoerg Sonnenberger pos += sizeof(ph) + ph.caplen;
42095cc27f0SJoerg Sonnenberger if (pos > size)
42195cc27f0SJoerg Sonnenberger goto error;
42295cc27f0SJoerg Sonnenberger fseek(fp, ph.caplen, SEEK_CUR);
42395cc27f0SJoerg Sonnenberger }
42495cc27f0SJoerg Sonnenberger
42595cc27f0SJoerg Sonnenberger if (pos != size)
42695cc27f0SJoerg Sonnenberger goto error;
42795cc27f0SJoerg Sonnenberger
42895cc27f0SJoerg Sonnenberger if ((int)hdr.snaplen != cur_snaplen) {
42995cc27f0SJoerg Sonnenberger logmsg(LOG_WARNING,
43095cc27f0SJoerg Sonnenberger "Existing file has different snaplen %u, using it",
43195cc27f0SJoerg Sonnenberger hdr.snaplen);
43295cc27f0SJoerg Sonnenberger if (set_snaplen(hdr.snaplen)) {
43395cc27f0SJoerg Sonnenberger logmsg(LOG_WARNING,
43495cc27f0SJoerg Sonnenberger "Failed, using old settings, offset %llu",
43595cc27f0SJoerg Sonnenberger (unsigned long long) size);
43695cc27f0SJoerg Sonnenberger }
43795cc27f0SJoerg Sonnenberger }
43895cc27f0SJoerg Sonnenberger
43995cc27f0SJoerg Sonnenberger return (0);
44095cc27f0SJoerg Sonnenberger
44195cc27f0SJoerg Sonnenberger error:
44295cc27f0SJoerg Sonnenberger logmsg(LOG_ERR, "Corrupted log file.");
44395cc27f0SJoerg Sonnenberger return (1);
44495cc27f0SJoerg Sonnenberger }
44595cc27f0SJoerg Sonnenberger
44695cc27f0SJoerg Sonnenberger /* dump a packet directly to the stream, which is unbuffered */
44795cc27f0SJoerg Sonnenberger void
dump_packet_nobuf(u_char * user,const struct pcap_pkthdr * h,const u_char * sp)44895cc27f0SJoerg Sonnenberger dump_packet_nobuf(u_char *user, const struct pcap_pkthdr *h, const u_char *sp)
44995cc27f0SJoerg Sonnenberger {
45095cc27f0SJoerg Sonnenberger FILE *f = (FILE *)user;
4512461cb13SPeeter struct pcap_sf_pkthdr sh;
45295cc27f0SJoerg Sonnenberger
45395cc27f0SJoerg Sonnenberger if (suspended) {
45495cc27f0SJoerg Sonnenberger packets_dropped++;
45595cc27f0SJoerg Sonnenberger return;
45695cc27f0SJoerg Sonnenberger }
45795cc27f0SJoerg Sonnenberger
4582461cb13SPeeter sh.ts.tv_sec = (bpf_int32)h->ts.tv_sec;
4592461cb13SPeeter sh.ts.tv_usec = (bpf_int32)h->ts.tv_usec;
4602461cb13SPeeter sh.caplen = h->caplen;
4612461cb13SPeeter sh.len = h->len;
4622461cb13SPeeter
4632461cb13SPeeter if (fwrite((char *)&sh, sizeof(sh), 1, f) != 1) {
46495cc27f0SJoerg Sonnenberger off_t pos = ftello(f);
465c929e0dfSJan Lentfer
466c929e0dfSJan Lentfer /* try to undo header to prevent corruption */
4672461cb13SPeeter if ((size_t)pos < sizeof(sh) ||
4682461cb13SPeeter ftruncate(fileno(f), pos - sizeof(sh))) {
46995cc27f0SJoerg Sonnenberger logmsg(LOG_ERR, "Write failed, corrupted logfile!");
47095cc27f0SJoerg Sonnenberger set_suspended(1);
47195cc27f0SJoerg Sonnenberger gotsig_close = 1;
47295cc27f0SJoerg Sonnenberger return;
47395cc27f0SJoerg Sonnenberger }
47495cc27f0SJoerg Sonnenberger goto error;
47595cc27f0SJoerg Sonnenberger }
47695cc27f0SJoerg Sonnenberger
47795cc27f0SJoerg Sonnenberger if (fwrite(sp, h->caplen, 1, f) != 1)
47895cc27f0SJoerg Sonnenberger goto error;
47995cc27f0SJoerg Sonnenberger
48095cc27f0SJoerg Sonnenberger return;
48195cc27f0SJoerg Sonnenberger
48295cc27f0SJoerg Sonnenberger error:
48395cc27f0SJoerg Sonnenberger set_suspended(1);
48495cc27f0SJoerg Sonnenberger packets_dropped ++;
48595cc27f0SJoerg Sonnenberger logmsg(LOG_ERR, "Logging suspended: fwrite: %s", strerror(errno));
48695cc27f0SJoerg Sonnenberger }
48795cc27f0SJoerg Sonnenberger
48895cc27f0SJoerg Sonnenberger int
flush_buffer(FILE * f)48995cc27f0SJoerg Sonnenberger flush_buffer(FILE *f)
49095cc27f0SJoerg Sonnenberger {
49195cc27f0SJoerg Sonnenberger off_t offset;
49295cc27f0SJoerg Sonnenberger int len = bufpos - buffer;
49395cc27f0SJoerg Sonnenberger
49495cc27f0SJoerg Sonnenberger if (len <= 0)
49595cc27f0SJoerg Sonnenberger return (0);
49695cc27f0SJoerg Sonnenberger
49795cc27f0SJoerg Sonnenberger offset = ftello(f);
49895cc27f0SJoerg Sonnenberger if (offset == (off_t)-1) {
49995cc27f0SJoerg Sonnenberger set_suspended(1);
50095cc27f0SJoerg Sonnenberger logmsg(LOG_ERR, "Logging suspended: ftello: %s",
50195cc27f0SJoerg Sonnenberger strerror(errno));
50295cc27f0SJoerg Sonnenberger return (1);
50395cc27f0SJoerg Sonnenberger }
50495cc27f0SJoerg Sonnenberger
50595cc27f0SJoerg Sonnenberger if (fwrite(buffer, len, 1, f) != 1) {
50695cc27f0SJoerg Sonnenberger set_suspended(1);
50795cc27f0SJoerg Sonnenberger logmsg(LOG_ERR, "Logging suspended: fwrite: %s",
50895cc27f0SJoerg Sonnenberger strerror(errno));
50995cc27f0SJoerg Sonnenberger ftruncate(fileno(f), offset);
51095cc27f0SJoerg Sonnenberger return (1);
51195cc27f0SJoerg Sonnenberger }
51295cc27f0SJoerg Sonnenberger
51395cc27f0SJoerg Sonnenberger set_suspended(0);
51495cc27f0SJoerg Sonnenberger bufpos = buffer;
51595cc27f0SJoerg Sonnenberger bufleft = buflen;
51695cc27f0SJoerg Sonnenberger bufpkt = 0;
51795cc27f0SJoerg Sonnenberger
51895cc27f0SJoerg Sonnenberger return (0);
51995cc27f0SJoerg Sonnenberger }
52095cc27f0SJoerg Sonnenberger
52195cc27f0SJoerg Sonnenberger void
purge_buffer(void)52295cc27f0SJoerg Sonnenberger purge_buffer(void)
52395cc27f0SJoerg Sonnenberger {
52495cc27f0SJoerg Sonnenberger packets_dropped += bufpkt;
52595cc27f0SJoerg Sonnenberger
52695cc27f0SJoerg Sonnenberger set_suspended(0);
52795cc27f0SJoerg Sonnenberger bufpos = buffer;
52895cc27f0SJoerg Sonnenberger bufleft = buflen;
52995cc27f0SJoerg Sonnenberger bufpkt = 0;
53095cc27f0SJoerg Sonnenberger }
53195cc27f0SJoerg Sonnenberger
53295cc27f0SJoerg Sonnenberger /* append packet to the buffer, flushing if necessary */
53395cc27f0SJoerg Sonnenberger void
dump_packet(u_char * user,const struct pcap_pkthdr * h,const u_char * sp)53495cc27f0SJoerg Sonnenberger dump_packet(u_char *user, const struct pcap_pkthdr *h, const u_char *sp)
53595cc27f0SJoerg Sonnenberger {
53695cc27f0SJoerg Sonnenberger FILE *f = (FILE *)user;
5372461cb13SPeeter struct pcap_sf_pkthdr sh;
5382461cb13SPeeter size_t len = sizeof(sh) + h->caplen;
53995cc27f0SJoerg Sonnenberger
54095cc27f0SJoerg Sonnenberger if (len < sizeof(*h) || h->caplen > (size_t)cur_snaplen) {
541b58f1e66SSascha Wildner logmsg(LOG_NOTICE, "invalid size %zd (%u/%u), packet dropped",
54295cc27f0SJoerg Sonnenberger len, cur_snaplen, snaplen);
54395cc27f0SJoerg Sonnenberger packets_dropped++;
54495cc27f0SJoerg Sonnenberger return;
54595cc27f0SJoerg Sonnenberger }
54695cc27f0SJoerg Sonnenberger
54795cc27f0SJoerg Sonnenberger if (len <= bufleft)
54895cc27f0SJoerg Sonnenberger goto append;
54995cc27f0SJoerg Sonnenberger
55095cc27f0SJoerg Sonnenberger if (suspended) {
55195cc27f0SJoerg Sonnenberger packets_dropped++;
55295cc27f0SJoerg Sonnenberger return;
55395cc27f0SJoerg Sonnenberger }
55495cc27f0SJoerg Sonnenberger
55595cc27f0SJoerg Sonnenberger if (flush_buffer(f)) {
55695cc27f0SJoerg Sonnenberger packets_dropped++;
55795cc27f0SJoerg Sonnenberger return;
55895cc27f0SJoerg Sonnenberger }
55995cc27f0SJoerg Sonnenberger
56095cc27f0SJoerg Sonnenberger if (len > bufleft) {
56195cc27f0SJoerg Sonnenberger dump_packet_nobuf(user, h, sp);
56295cc27f0SJoerg Sonnenberger return;
56395cc27f0SJoerg Sonnenberger }
56495cc27f0SJoerg Sonnenberger
56595cc27f0SJoerg Sonnenberger append:
5662461cb13SPeeter sh.ts.tv_sec = (bpf_int32)h->ts.tv_sec;
5672461cb13SPeeter sh.ts.tv_usec = (bpf_int32)h->ts.tv_usec;
5682461cb13SPeeter sh.caplen = h->caplen;
5692461cb13SPeeter sh.len = h->len;
5702461cb13SPeeter
5712461cb13SPeeter memcpy(bufpos, &sh, sizeof(sh));
5722461cb13SPeeter memcpy(bufpos + sizeof(sh), sp, h->caplen);
57395cc27f0SJoerg Sonnenberger
57495cc27f0SJoerg Sonnenberger bufpos += len;
57595cc27f0SJoerg Sonnenberger bufleft -= len;
57695cc27f0SJoerg Sonnenberger bufpkt++;
57795cc27f0SJoerg Sonnenberger
57895cc27f0SJoerg Sonnenberger return;
57995cc27f0SJoerg Sonnenberger }
58095cc27f0SJoerg Sonnenberger
581e437855fSPeeter void
log_pcap_stats(void)582e437855fSPeeter log_pcap_stats(void)
583e437855fSPeeter {
584e437855fSPeeter struct pcap_stat pstat;
585e437855fSPeeter if (pcap_stats(hpcap, &pstat) < 0)
586e437855fSPeeter logmsg(LOG_WARNING, "Reading stats: %s", pcap_geterr(hpcap));
587e437855fSPeeter else
588e437855fSPeeter logmsg(LOG_NOTICE,
589e437855fSPeeter "%u packets received, %u/%ld dropped (kernel/pflogd)",
590e437855fSPeeter pstat.ps_recv, pstat.ps_drop, packets_dropped);
591e437855fSPeeter }
592e437855fSPeeter
59395cc27f0SJoerg Sonnenberger int
main(int argc,char ** argv)59495cc27f0SJoerg Sonnenberger main(int argc, char **argv)
59595cc27f0SJoerg Sonnenberger {
596315a7da3SJan Lentfer int ch, np, ret, Xflag = 0;
59795cc27f0SJoerg Sonnenberger pcap_handler phandler = dump_packet;
598c929e0dfSJan Lentfer const char *errstr = NULL;
599d316f7c9SJohn Marino struct pidfh *pfh = NULL;
600315a7da3SJan Lentfer char *pidf = NULL;
60195cc27f0SJoerg Sonnenberger
602a8838a5fSSascha Wildner ret = 0;
603a8838a5fSSascha Wildner
60495cc27f0SJoerg Sonnenberger /* Neither FreeBSD nor DFly have this; Max seems to think this may
60595cc27f0SJoerg Sonnenberger * be a paranoid check. Comment it out:
60695cc27f0SJoerg Sonnenberger closefrom(STDERR_FILENO + 1);
60795cc27f0SJoerg Sonnenberger */
60895cc27f0SJoerg Sonnenberger
609315a7da3SJan Lentfer while ((ch = getopt(argc, argv, "Dxd:f:i:p:s:")) != -1) {
61095cc27f0SJoerg Sonnenberger switch (ch) {
61195cc27f0SJoerg Sonnenberger case 'D':
61295cc27f0SJoerg Sonnenberger Debug = 1;
61395cc27f0SJoerg Sonnenberger break;
61495cc27f0SJoerg Sonnenberger case 'd':
615c929e0dfSJan Lentfer delay = strtonum(optarg, 5, 60*60, &errstr);
616c929e0dfSJan Lentfer if (errstr)
61795cc27f0SJoerg Sonnenberger usage();
61895cc27f0SJoerg Sonnenberger break;
61995cc27f0SJoerg Sonnenberger case 'f':
62095cc27f0SJoerg Sonnenberger filename = optarg;
62195cc27f0SJoerg Sonnenberger break;
622c929e0dfSJan Lentfer case 'i':
623c929e0dfSJan Lentfer interface = optarg;
624c929e0dfSJan Lentfer break;
625315a7da3SJan Lentfer case 'p':
626315a7da3SJan Lentfer pidf = optarg;
627315a7da3SJan Lentfer break;
62895cc27f0SJoerg Sonnenberger case 's':
629c929e0dfSJan Lentfer snaplen = strtonum(optarg, 0, PFLOGD_MAXSNAPLEN,
630c929e0dfSJan Lentfer &errstr);
63195cc27f0SJoerg Sonnenberger if (snaplen <= 0)
63295cc27f0SJoerg Sonnenberger snaplen = DEF_SNAPLEN;
633c929e0dfSJan Lentfer if (errstr)
63495cc27f0SJoerg Sonnenberger snaplen = PFLOGD_MAXSNAPLEN;
63595cc27f0SJoerg Sonnenberger break;
63695cc27f0SJoerg Sonnenberger case 'x':
63795cc27f0SJoerg Sonnenberger Xflag++;
63895cc27f0SJoerg Sonnenberger break;
63995cc27f0SJoerg Sonnenberger default:
64095cc27f0SJoerg Sonnenberger usage();
64195cc27f0SJoerg Sonnenberger }
64295cc27f0SJoerg Sonnenberger
64395cc27f0SJoerg Sonnenberger }
64495cc27f0SJoerg Sonnenberger
64595cc27f0SJoerg Sonnenberger log_debug = Debug;
64695cc27f0SJoerg Sonnenberger argc -= optind;
64795cc27f0SJoerg Sonnenberger argv += optind;
64895cc27f0SJoerg Sonnenberger
649315a7da3SJan Lentfer /* does interface exist */
650315a7da3SJan Lentfer if (!if_exists(__DECONST(char *, interface))) {
651315a7da3SJan Lentfer warn("Failed to initialize: %s", interface);
652315a7da3SJan Lentfer logmsg(LOG_ERR, "Failed to initialize: %s", interface);
653315a7da3SJan Lentfer logmsg(LOG_ERR, "Exiting, init failure");
654315a7da3SJan Lentfer exit(1);
655315a7da3SJan Lentfer }
656315a7da3SJan Lentfer
65795cc27f0SJoerg Sonnenberger if (!Debug) {
65895cc27f0SJoerg Sonnenberger openlog("pflogd", LOG_PID | LOG_CONS, LOG_DAEMON);
659d316f7c9SJohn Marino pfh = pidfile_open(pidf, 0600, NULL);
66095cc27f0SJoerg Sonnenberger if (daemon(0, 0)) {
66195cc27f0SJoerg Sonnenberger logmsg(LOG_WARNING, "Failed to become daemon: %s",
66295cc27f0SJoerg Sonnenberger strerror(errno));
66395cc27f0SJoerg Sonnenberger }
664d316f7c9SJohn Marino pidfile_write(pfh);
66595cc27f0SJoerg Sonnenberger }
66695cc27f0SJoerg Sonnenberger
667e437855fSPeeter tzset();
66871126e33SSascha Wildner umask(S_IRWXG | S_IRWXO);
66995cc27f0SJoerg Sonnenberger
67095cc27f0SJoerg Sonnenberger /* filter will be used by the privileged process */
67195cc27f0SJoerg Sonnenberger if (argc) {
67295cc27f0SJoerg Sonnenberger filter = copy_argv(argv);
67395cc27f0SJoerg Sonnenberger if (filter == NULL)
67495cc27f0SJoerg Sonnenberger logmsg(LOG_NOTICE, "Failed to form filter expression");
67595cc27f0SJoerg Sonnenberger }
67695cc27f0SJoerg Sonnenberger
67795cc27f0SJoerg Sonnenberger /* initialize pcap before dropping privileges */
67895cc27f0SJoerg Sonnenberger if (init_pcap()) {
67995cc27f0SJoerg Sonnenberger logmsg(LOG_ERR, "Exiting, init failure");
68095cc27f0SJoerg Sonnenberger exit(1);
68195cc27f0SJoerg Sonnenberger }
68295cc27f0SJoerg Sonnenberger
68395cc27f0SJoerg Sonnenberger /* Privilege separation begins here */
68495cc27f0SJoerg Sonnenberger if (priv_init()) {
68595cc27f0SJoerg Sonnenberger logmsg(LOG_ERR, "unable to privsep");
68695cc27f0SJoerg Sonnenberger exit(1);
68795cc27f0SJoerg Sonnenberger }
68895cc27f0SJoerg Sonnenberger
68995cc27f0SJoerg Sonnenberger setproctitle("[initializing]");
69095cc27f0SJoerg Sonnenberger /* Process is now unprivileged and inside a chroot */
69195cc27f0SJoerg Sonnenberger signal(SIGTERM, sig_close);
69295cc27f0SJoerg Sonnenberger signal(SIGINT, sig_close);
69395cc27f0SJoerg Sonnenberger signal(SIGQUIT, sig_close);
69495cc27f0SJoerg Sonnenberger signal(SIGALRM, sig_alrm);
695e437855fSPeeter signal(SIGUSR1, sig_usr1);
69695cc27f0SJoerg Sonnenberger signal(SIGHUP, sig_hup);
69795cc27f0SJoerg Sonnenberger alarm(delay);
69895cc27f0SJoerg Sonnenberger
69995cc27f0SJoerg Sonnenberger buffer = malloc(PFLOGD_BUFSIZE);
70095cc27f0SJoerg Sonnenberger
70195cc27f0SJoerg Sonnenberger if (buffer == NULL) {
70295cc27f0SJoerg Sonnenberger logmsg(LOG_WARNING, "Failed to allocate output buffer");
70395cc27f0SJoerg Sonnenberger phandler = dump_packet_nobuf;
70495cc27f0SJoerg Sonnenberger } else {
70595cc27f0SJoerg Sonnenberger bufleft = buflen = PFLOGD_BUFSIZE;
70695cc27f0SJoerg Sonnenberger bufpos = buffer;
70795cc27f0SJoerg Sonnenberger bufpkt = 0;
70895cc27f0SJoerg Sonnenberger }
70995cc27f0SJoerg Sonnenberger
710c929e0dfSJan Lentfer if (reset_dump(Xflag) < 0) {
71195cc27f0SJoerg Sonnenberger if (Xflag)
71295cc27f0SJoerg Sonnenberger return (1);
71395cc27f0SJoerg Sonnenberger
71495cc27f0SJoerg Sonnenberger logmsg(LOG_ERR, "Logging suspended: open error");
71595cc27f0SJoerg Sonnenberger set_suspended(1);
71695cc27f0SJoerg Sonnenberger } else if (Xflag)
71795cc27f0SJoerg Sonnenberger return (0);
71895cc27f0SJoerg Sonnenberger
71995cc27f0SJoerg Sonnenberger while (1) {
72095cc27f0SJoerg Sonnenberger np = pcap_dispatch(hpcap, PCAP_NUM_PKTS,
721c929e0dfSJan Lentfer phandler, (u_char *)dpcap);
722315a7da3SJan Lentfer if (np < 0) {
7234bb97943SSascha Wildner if (!if_exists(__DECONST(char *, interface))) {
724315a7da3SJan Lentfer logmsg(LOG_NOTICE, "interface %s went away",
725315a7da3SJan Lentfer interface);
726315a7da3SJan Lentfer ret = -1;
727315a7da3SJan Lentfer break;
728315a7da3SJan Lentfer }
72995cc27f0SJoerg Sonnenberger logmsg(LOG_NOTICE, "%s", pcap_geterr(hpcap));
730315a7da3SJan Lentfer }
73195cc27f0SJoerg Sonnenberger
73295cc27f0SJoerg Sonnenberger if (gotsig_close)
73395cc27f0SJoerg Sonnenberger break;
73495cc27f0SJoerg Sonnenberger if (gotsig_hup) {
735c929e0dfSJan Lentfer if (reset_dump(0)) {
73695cc27f0SJoerg Sonnenberger logmsg(LOG_ERR,
73795cc27f0SJoerg Sonnenberger "Logging suspended: open error");
73895cc27f0SJoerg Sonnenberger set_suspended(1);
73995cc27f0SJoerg Sonnenberger }
74095cc27f0SJoerg Sonnenberger gotsig_hup = 0;
74195cc27f0SJoerg Sonnenberger }
74295cc27f0SJoerg Sonnenberger
74395cc27f0SJoerg Sonnenberger if (gotsig_alrm) {
74495cc27f0SJoerg Sonnenberger if (dpcap)
74595cc27f0SJoerg Sonnenberger flush_buffer(dpcap);
746c929e0dfSJan Lentfer else
747c929e0dfSJan Lentfer gotsig_hup = 1;
74895cc27f0SJoerg Sonnenberger gotsig_alrm = 0;
74995cc27f0SJoerg Sonnenberger alarm(delay);
75095cc27f0SJoerg Sonnenberger }
751e437855fSPeeter
752e437855fSPeeter if (gotsig_usr1) {
753e437855fSPeeter log_pcap_stats();
754e437855fSPeeter gotsig_usr1 = 0;
755e437855fSPeeter }
75695cc27f0SJoerg Sonnenberger }
75795cc27f0SJoerg Sonnenberger
75895cc27f0SJoerg Sonnenberger logmsg(LOG_NOTICE, "Exiting");
75995cc27f0SJoerg Sonnenberger if (dpcap) {
76095cc27f0SJoerg Sonnenberger flush_buffer(dpcap);
76195cc27f0SJoerg Sonnenberger fclose(dpcap);
76295cc27f0SJoerg Sonnenberger }
76395cc27f0SJoerg Sonnenberger purge_buffer();
76495cc27f0SJoerg Sonnenberger
765e437855fSPeeter log_pcap_stats();
76695cc27f0SJoerg Sonnenberger pcap_close(hpcap);
76795cc27f0SJoerg Sonnenberger if (!Debug)
76895cc27f0SJoerg Sonnenberger closelog();
769315a7da3SJan Lentfer return (ret);
77095cc27f0SJoerg Sonnenberger }
771