Projet

Général

Profil

Télécharger (5,57 ko) Statistiques
| Branche: | Révision:

univnautes-tools / pfPorts / filterlog / files / filterlog.c @ 8135339c

1

    
2
#include <sys/types.h>
3
#include <sys/socket.h>
4
#include <sys/sbuf.h>
5
#include <sys/file.h>
6

    
7
#include <net/if.h>
8
#include <pcap/pcap.h>
9

    
10
#include <net/pfvar.h>
11
#include <net/if_pflog.h>
12

    
13
#include <netinet/ip.h>
14

    
15
#include <stdlib.h>
16
#include <syslog.h>
17
#include <stdarg.h>
18
#include <time.h>
19
#include <string.h>
20
#include <unistd.h>
21

    
22
#include "common.h"
23

    
24
static pcap_t *tap = NULL;
25
static char *filterlog_pcap_file = NULL;
26
static char errbuf[PCAP_ERRBUF_SIZE];
27
static struct sbuf sbuf;
28
static u_char *sbuf_buf;
29
static char *pidfile;
30

    
31
static const struct tok pf_reasons[] = {
32
	{ 0,	"match" },
33
	{ 1,	"bad-offset" },
34
	{ 2,	"fragment" },
35
	{ 3,	"short" },
36
	{ 4,	"normalize" },
37
	{ 5,	"memory" },
38
	{ 6,	"bad-timestamp" },
39
	{ 7,	"congestion" },
40
	{ 8,	"ip-option" },
41
	{ 9,	"proto-cksum" },
42
	{ 10,	"state-mismatch" },
43
	{ 11,	"state-insert" },
44
	{ 12,	"state-limit" },
45
	{ 13,	"src-limit" },
46
	{ 14,	"synproxy" },
47
	{ 0,	NULL }
48
};
49

    
50
static const struct tok pf_actions[] = {
51
	{ PF_PASS,		"pass" },
52
	{ PF_DROP,		"block" },
53
	{ PF_SCRUB,		"scrub" },
54
	{ PF_NAT,		"nat" },
55
	{ PF_NONAT,		"nat" },
56
	{ PF_BINAT,		"binat" },
57
	{ PF_NOBINAT,		"binat" },
58
	{ PF_RDR,		"rdr" },
59
	{ PF_NORDR,		"rdr" },
60
	{ PF_SYNPROXY_DROP,	"synproxy-drop" },
61
	{ 0,			NULL }
62
};
63

    
64
static const struct tok pf_directions[] = {
65
	{ PF_INOUT,	"in/out" },
66
	{ PF_IN,	"in" },
67
	{ PF_OUT,	"out" },
68
	{ 0,		NULL }
69
};
70

    
71
const char *
72
code2str(const struct tok *trans, const char *unknown, int action)
73
{
74
	int i = 0;
75

    
76
	for (;;) {
77
		if (trans[i].descr == NULL)
78
			return unknown;
79

    
80
		if (action == trans[i].action)
81
			return (trans[i].descr);
82

    
83
		i++;
84
	}
85

    
86
	return (unknown);
87
}
88

    
89
static void
90
decode_packet(u_char *user __unused, const struct pcap_pkthdr *pkthdr, const u_char *packet)
91
{
92
	const struct pfloghdr *hdr;
93
	const struct ip *ip;
94
	u_int length = pkthdr->len;
95
	u_int hdrlen;
96
	u_int caplen = pkthdr->caplen;
97
	u_int32_t subrulenr;
98

    
99
	/* check length */
100
	if (caplen < sizeof(u_int8_t)) {
101
		sbuf_printf(&sbuf, "[|pflog]");
102
		goto printsbuf;
103
	}
104

    
105
#define MIN_PFLOG_HDRLEN	45
106
	hdr = (const struct pfloghdr *)packet;
107
	if (hdr->length < MIN_PFLOG_HDRLEN) {
108
		sbuf_printf(&sbuf, "[pflog: invalid header length!]");
109
		goto printsbuf;
110
	}
111
	hdrlen = PFLOG_HDRLEN;
112

    
113
	if (caplen < hdrlen) {
114
		sbuf_printf(&sbuf, "[|pflog]");
115
		goto printsbuf;
116
	}
117

    
118
	/* print what we know */
119
	sbuf_printf(&sbuf, "%u,", EXTRACT_32BITS(&hdr->rulenr));
120
	subrulenr = EXTRACT_32BITS(&hdr->subrulenr);
121
	if (subrulenr == (u_int32_t)-1)
122
		sbuf_printf(&sbuf, ",,");
123
	else
124
		sbuf_printf(&sbuf, "%u,%s,", subrulenr, hdr->ruleset); 
125
	sbuf_printf(&sbuf, "%u,%s,", hdr->ridentifier, hdr->ifname);
126
	sbuf_printf(&sbuf, "%s,", code2str(pf_reasons, "unkn(%u)", hdr->reason));
127
	sbuf_printf(&sbuf, "%s,", code2str(pf_actions, "unkn(%u)", hdr->action));
128
	sbuf_printf(&sbuf, "%s,", code2str(pf_directions, "unkn(%u)", hdr->dir));
129

    
130
	/* skip to the real packet */
131
	length -= hdrlen;
132
	packet += hdrlen;
133
	ip = (const const struct ip *)packet;
134

    
135
        if (length < 4) {
136
                sbuf_printf(&sbuf, "%d, IP(truncated-ip %d) ", IP_V(ip), length);
137
		goto printsbuf;
138
        }
139
        switch (IP_V(ip)) {
140
        case 4:
141
                ip_print(&sbuf, packet, length);
142
		break;
143
        case 6:
144
                ip6_print(&sbuf, packet, length);
145
		break;
146
        default:
147
                ip_print(&sbuf, packet, length);
148
                sbuf_printf(&sbuf, "%d", IP_V(ip));
149
                break;
150
        }
151

    
152
printsbuf:
153
	sbuf_finish(&sbuf);
154
	if (filterlog_pcap_file != NULL)
155
		printf("%s\n", sbuf_data(&sbuf));
156
	else
157
		syslog(LOG_INFO, "%s", sbuf_data(&sbuf));
158
	memset(sbuf_data(&sbuf), 0, sbuf_len(&sbuf));
159
	sbuf_clear(&sbuf);
160
	return;
161
}
162

    
163
int
164
main(int argc, char **argv)
165
{
166
	int perr, ch;
167
	char *interface;
168

    
169
	pidfile = NULL;
170
	interface = filterlog_pcap_file = NULL;
171
	tzset();
172

    
173
	while ((ch = getopt(argc, argv, "i:p:P:")) != -1) {
174
		switch (ch) {
175
		case 'i':
176
			interface = optarg;
177
			break;
178
		case 'p':
179
			pidfile = optarg;
180
			break;
181
		case 'P':
182
			filterlog_pcap_file = optarg;
183
			break;
184
		default:
185
			printf("Unknown option specified\n");
186
			return (-1);
187
		}
188
	}
189

    
190
	if (interface == NULL && filterlog_pcap_file == NULL) {
191
		printf("Should specify an interface or a pcap file\n");
192
		exit(-1);
193
	}
194

    
195
	if (filterlog_pcap_file == NULL)
196
		daemon(0, 0);
197

    
198
	if (pidfile) {
199
		FILE *pidfd;
200

    
201
                /* write PID to file */
202
                pidfd = fopen(pidfile, "w");
203
                if (pidfd) {
204
                        while (flock(fileno(pidfd), LOCK_EX) != 0)
205
                                ;
206
                        fprintf(pidfd, "%d\n", getpid());
207
                        flock(fileno(pidfd), LOCK_UN);
208
                        fclose(pidfd);
209
                } else
210
                        syslog(LOG_WARNING, "could not open pid file");
211
        }
212

    
213
	do {
214
		sbuf_buf = calloc(1, 2048);
215
	} while (sbuf_buf == NULL);
216

    
217
	sbuf_new(&sbuf, sbuf_buf, 2048, SBUF_AUTOEXTEND);
218

    
219
	openlog("filterlog", LOG_NDELAY, LOG_LOCAL0);
220

    
221
	while (1) {
222
		if (tap != NULL)
223
			pcap_close(tap);
224

    
225
		if (filterlog_pcap_file != NULL)
226
			tap = pcap_open_offline(filterlog_pcap_file, errbuf);
227
		else
228
			tap = pcap_open_live(interface, MAXIMUM_SNAPLEN, 1, 1000, errbuf);
229
		if (tap == NULL) {
230
			syslog(LOG_ERR, "Failed to initialize: %s(%m)", errbuf);
231
			return (-1);
232
		}
233

    
234
		if (pcap_datalink(tap) != DLT_PFLOG) {
235
			syslog(LOG_ERR, "Invalid datalink type");
236
			pcap_close(tap);
237
			tap = NULL;
238
			return (-1);
239
		}
240

    
241
		perr = pcap_loop(tap, -1, decode_packet, NULL);
242
		if (perr == -1) {
243
			syslog(LOG_ERR, "An error occured while reading device %s: %m", interface);
244
		} else if (perr == -2) {
245
			pcap_close(tap);
246
			break;
247
		} else if (perr == 0) {
248
			pcap_close(tap);
249
			tap = NULL;
250
		}
251

    
252
		if (filterlog_pcap_file != NULL)
253
			break;
254
	}
255

    
256
	closelog();
257

    
258
	return (0);
259
}
(4-4/11)