Projet

Général

Profil

Télécharger (37 ko) Statistiques
| Branche: | Révision:

univnautes-tools / pfPorts / suricata / files / patch-alert-pf.diff @ f3607cde

1
diff -rNu ./src/Makefile.am ./src.new/Makefile.am
2
--- ./src/Makefile.am	2013-09-24 06:28:37.000000000 -0400
3
+++ ./src.new/Makefile.am	2014-04-18 16:36:04.000000000 -0400
4
@@ -10,6 +10,7 @@
5
 alert-debuglog.c alert-debuglog.h \
6
 alert-fastlog.c alert-fastlog.h \
7
 alert-pcapinfo.c alert-pcapinfo.h \
8
+alert-pf.c alert-pf.h \
9
 alert-prelude.c alert-prelude.h \
10
 alert-syslog.c alert-syslog.h \
11
 alert-unified2-alert.c alert-unified2-alert.h \
12
diff -rNu ./src/Makefile.in ./src.new/Makefile.in
13
--- ./src/Makefile.in	2013-09-24 06:28:49.000000000 -0400
14
+++ ./src.new/Makefile.in	2014-04-18 16:38:02.000000000 -0400
15
@@ -73,7 +73,7 @@
16
 PROGRAMS = $(bin_PROGRAMS)
17
 am__suricata_SOURCES_DIST = alert-debuglog.c alert-debuglog.h \
18
 	alert-fastlog.c alert-fastlog.h alert-pcapinfo.c \
19
-	alert-pcapinfo.h alert-prelude.c alert-prelude.h \
20
+	alert-pcapinfo.h alert-pf.c alert-pf.h alert-prelude.c alert-prelude.h \
21
 	alert-syslog.c alert-syslog.h alert-unified2-alert.c \
22
 	alert-unified2-alert.h app-layer.c app-layer.h \
23
 	app-layer-dcerpc.c app-layer-dcerpc.h app-layer-dcerpc-udp.c \
24
@@ -274,7 +274,7 @@
25
 	cuda-ptxdump.h
26
 am__objects_1 =
27
 am_suricata_OBJECTS = alert-debuglog.$(OBJEXT) alert-fastlog.$(OBJEXT) \
28
-	alert-pcapinfo.$(OBJEXT) alert-prelude.$(OBJEXT) \
29
+	alert-pcapinfo.$(OBJEXT) alert-pf.$(OBJEXT) alert-prelude.$(OBJEXT) \
30
 	alert-syslog.$(OBJEXT) alert-unified2-alert.$(OBJEXT) \
31
 	app-layer.$(OBJEXT) app-layer-dcerpc.$(OBJEXT) \
32
 	app-layer-dcerpc-udp.$(OBJEXT) \
33
@@ -621,6 +621,7 @@
34
 
35
 suricata_SOURCES = alert-debuglog.c alert-debuglog.h alert-fastlog.c \
36
 	alert-fastlog.h alert-pcapinfo.c alert-pcapinfo.h \
37
+	alert-pf.c alert-pf.h \
38
 	alert-prelude.c alert-prelude.h alert-syslog.c alert-syslog.h \
39
 	alert-unified2-alert.c alert-unified2-alert.h app-layer.c \
40
 	app-layer.h app-layer-dcerpc.c app-layer-dcerpc.h \
41
@@ -947,6 +948,7 @@
42
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/alert-debuglog.Po@am__quote@
43
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/alert-fastlog.Po@am__quote@
44
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/alert-pcapinfo.Po@am__quote@
45
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/alert-pf.Po@am__quote@
46
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/alert-prelude.Po@am__quote@
47
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/alert-syslog.Po@am__quote@
48
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/alert-unified2-alert.Po@am__quote@
49
diff -rNu ./src/alert-pf.c ./src.new/alert-pf.c
50
--- ./src/alert-pf.c	1969-12-31 19:00:00.000000000 -0500
51
+++ ./src.new/alert-pf.c	2014-04-30 20:20:08.000000000 -0400
52
@@ -0,0 +1,835 @@
53
+/* Copyright (C) 2007-2014 Open Information Security Foundation
54
+ *
55
+ * You can copy, redistribute or modify this Program under the terms of
56
+ * the GNU General Public License version 2 as published by the Free
57
+ * Software Foundation.
58
+ *
59
+ * This program is distributed in the hope that it will be useful,
60
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
61
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
62
+ * GNU General Public License for more details.
63
+ *
64
+ * You should have received a copy of the GNU General Public License
65
+ * version 2 along with this program; if not, write to the Free Software
66
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
67
+ * 02110-1301, USA.
68
+ *
69
+ * Portions of this module are based on previous works of the following:
70
+ *
71
+ * Copyright (c) 2012  Ermal Lu?i
72
+ * Copyright (c) 2006  Antonio Benojar <zz.stalker@gmail.com>
73
+ * Copyright (c) 2005  Antonio Benojar <zz.stalker@gmail.com>
74
+ *
75
+ * Copyright (c) 2003, 2004 Armin Wolfermann:
76
+ * 
77
+ * The AlertPfBlock() function is based 
78
+ * on Armin's Wolfermann pftabled-1.03 functions.
79
+ *
80
+ * All rights reserved.
81
+ *
82
+ * Redistribution and use in source and binary forms, with or without
83
+ * modification, are permitted provided that the following conditions
84
+ * are met:
85
+ *
86
+ * 1. Redistributions of source code must retain the above copyright
87
+ *    notice, this list of conditions and the following disclaimer.
88
+ *
89
+ * 2. Redistributions in binary form must reproduce the above copyright
90
+ *    notice, this list of conditions and the following disclaimer in the
91
+ *    documentation and/or other materials provided with the distribution.
92
+ *
93
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS OR
94
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
95
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
96
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
97
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
98
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
99
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
100
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
101
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
102
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
103
+ */
104
+
105
+/**
106
+ * \file
107
+ *
108
+ * \author Bill Meeks <bill@themeeks.net>
109
+ *
110
+ * Inserts blocks for IP alerts into the pf firewall used in NetBSD and FreeBSD, 
111
+ * and logs the event, including the IP address, in "block.log".
112
+ *
113
+ *    # alert_pf blocking plugin
114
+ *    - alert-pf:
115
+ *        enabled: yes/no            # "yes" to enable blocking plugin
116
+ *        kill-state: yes/no         # "yes" to kill open state table entries associated with blocked IP addresses (default is YES)
117
+ *        pass-list: <filename>      # complete path and filename for txt file of single IP addresses or CIDR networks that should never be blocked
118
+ *        block-ip: src/dst/both     # which IP in packet to block (default is BOTH)
119
+ *        pf-table: <pf table name>  # name of packet filter firewall table where block IP addresses should be added.  This table must exist!
120
+ *
121
+ */
122
+
123
+#include "suricata-common.h"
124
+#include "conf.h"
125
+#include "output.h"
126
+#include "threads.h"
127
+#include "tm-threads.h"
128
+#include "threadvars.h"
129
+
130
+#include "alert-pf.h"
131
+
132
+#include "util-atomic.h"
133
+#include "util-debug.h"
134
+#include "util-logopenfile.h"
135
+#include "util-print.h"
136
+#include "util-proto-name.h"
137
+#include "util-radix-tree.h"
138
+
139
+#include <sys/types.h>
140
+#include <sys/ioctl.h>
141
+#include <sys/socket.h>
142
+#include <sys/stat.h>
143
+#include <ctype.h>
144
+#include <net/if.h>
145
+#include <net/pfvar.h>
146
+#include <err.h>
147
+#include <unistd.h>
148
+#include <regex.h>
149
+
150
+#define PFDEVICE	"/dev/pf"
151
+#define WLMAX		1024
152
+#define MODULE_NAME	"AlertPf"
153
+#define DEFAULT_LOG_FILENAME "block.log"
154
+
155
+enum spblock { BLOCK_SRC, BLOCK_DST, BLOCK_BOTH };
156
+
157
+TmEcode AlertPf (ThreadVars *, Packet *, void *, PacketQueue *, PacketQueue *);
158
+TmEcode AlertPfIPv4(ThreadVars *, Packet *, void *, PacketQueue *, PacketQueue *);
159
+TmEcode AlertPfIPv6(ThreadVars *, Packet *, void *, PacketQueue *, PacketQueue *);
160
+TmEcode AlertPfThreadInit(ThreadVars *, void *, void **);
161
+TmEcode AlertPfThreadDeinit(ThreadVars *, void *);
162
+void AlertPfExitPrintStats(ThreadVars *, void *);
163
+static void AlertPfDeInitCtx(OutputCtx *);
164
+
165
+void TmModuleAlertPfRegister (void) {
166
+    tmm_modules[TMM_ALERTPF].name = MODULE_NAME;
167
+    tmm_modules[TMM_ALERTPF].ThreadInit = AlertPfThreadInit;
168
+    tmm_modules[TMM_ALERTPF].Func = AlertPf;
169
+    tmm_modules[TMM_ALERTPF].ThreadExitPrintStats = AlertPfExitPrintStats;
170
+    tmm_modules[TMM_ALERTPF].ThreadDeinit = AlertPfThreadDeinit;
171
+    tmm_modules[TMM_ALERTPF].RegisterTests = NULL;
172
+    tmm_modules[TMM_ALERTPF].cap_flags = 0;
173
+
174
+    OutputRegisterModule(MODULE_NAME, "alert-pf", AlertPfInitCtx);
175
+}
176
+
177
+void TmModuleAlertPfIPv4Register (void) {
178
+    tmm_modules[TMM_ALERTPF4].name = "AlertPfIPv4";
179
+    tmm_modules[TMM_ALERTPF4].ThreadInit = AlertPfThreadInit;
180
+    tmm_modules[TMM_ALERTPF4].Func = AlertPfIPv4;
181
+    tmm_modules[TMM_ALERTPF4].ThreadExitPrintStats = AlertPfExitPrintStats;
182
+    tmm_modules[TMM_ALERTPF4].ThreadDeinit = AlertPfThreadDeinit;
183
+    tmm_modules[TMM_ALERTPF4].RegisterTests = NULL;
184
+}
185
+
186
+void TmModuleAlertPfIPv6Register (void) {
187
+    tmm_modules[TMM_ALERTPF6].name = "AlertPfIPv6";
188
+    tmm_modules[TMM_ALERTPF6].ThreadInit = AlertPfThreadInit;
189
+    tmm_modules[TMM_ALERTPF6].Func = AlertPfIPv6;
190
+    tmm_modules[TMM_ALERTPF6].ThreadExitPrintStats = AlertPfExitPrintStats;
191
+    tmm_modules[TMM_ALERTPF6].ThreadDeinit = AlertPfThreadDeinit;
192
+    tmm_modules[TMM_ALERTPF6].RegisterTests = NULL;
193
+}
194
+
195
+/**
196
+ * This holds global structures and variables.
197
+ * Each thread gets a pointer to this data.
198
+ */
199
+typedef struct _AlertPfCtx_ {
200
+    char *pftable; 
201
+    int kill_state;
202
+    enum spblock block_ip;
203
+    SCRadixTree *tree;
204
+    LogFileCtx* file_ctx;
205
+} AlertPfCtx;
206
+
207
+/**
208
+ * This holds per-thread specific structures and variables.
209
+ */
210
+typedef struct AlertPfThread_ {
211
+    AlertPfCtx* ctx;       /* Pointer to the global context data */
212
+    int fd;                /* pf device handle */
213
+} AlertPfThread;
214
+
215
+SC_ATOMIC_DECLARE(uint64_t, alert_pf_blocks);  /**< Atomic counter, to hold block count */
216
+
217
+static int AlertPf_parse_line(char *, FILE *);
218
+static int AlertPfLoadPassList(char *, AlertPfCtx *);
219
+static int AlertPfDeviceInit(void);
220
+static int AlertPfTableExists(char *);
221
+static int AlertPfBlock(AlertPfThread *, Address *net_addr);
222
+
223
+/** \brief Print and format a UNIX timestamp into supplied buffer
224
+ *  \param *ts pointer to a timeval structure
225
+ *  \param *str pointer to a buffer to hold output string
226
+ *  \param size size of output string buffer
227
+ *  \retval None */
228
+static void CreateTimeString (const struct timeval *ts, char *str, size_t size) {
229
+    time_t time = ts->tv_sec;
230
+    struct tm local_tm;
231
+    struct tm *t = (struct tm *)SCLocalTime(time, &local_tm);
232
+
233
+    snprintf(str, size, "%02d/%02d/%02d-%02d:%02d:%02d.%06u",
234
+            t->tm_mon + 1, t->tm_mday, t->tm_year + 1900, t->tm_hour,
235
+            t->tm_min, t->tm_sec, (uint32_t) ts->tv_usec);
236
+}
237
+
238
+/**
239
+ * This opens the pf device and returns a file descriptor.
240
+ */
241
+static int AlertPfDeviceInit(void)
242
+{
243
+    return(open(PFDEVICE, O_RDWR));
244
+}
245
+
246
+/** \brief Verifies the supplied pf table exists
247
+ *  \param *tablename pointer to pf table name string
248
+ *  \retval -1 on error, 1 if table exists or 0 if not */
249
+static int AlertPfTableExists(char *tablename)
250
+{
251
+    int i;
252
+    int dev;
253
+    struct pfioc_table io;
254
+    struct pfr_table *table_aux = NULL;
255
+	
256
+    memset(&io, 0x00, sizeof(struct pfioc_table));
257
+	
258
+    io.pfrio_buffer = table_aux;
259
+    io.pfrio_esize  = sizeof(struct pfr_table);
260
+    io.pfrio_size   = 0;
261
+
262
+    dev = AlertPfDeviceInit();
263
+    if (dev == -1) {
264
+	SCLogError(SC_ERR_SYSCALL, "Failed to open pf device.");
265
+	return -1;
266
+    }
267
+	
268
+    if(ioctl(dev, DIOCRGETTABLES, &io)) {  
269
+        SCLogError(SC_ERR_SYSCALL, "AlertPfTableExists() => ioctl() DIOCRGETTABLES: %s\n", strerror(errno));
270
+	return -1;
271
+    }
272
+	
273
+    table_aux = (struct pfr_table*)malloc(sizeof(struct pfr_table)*io.pfrio_size);
274
+	
275
+    if (table_aux == NULL) { 
276
+        SCLogError(SC_ERR_SYSCALL, "AlertPfTableExists() => malloc(): %s\n", strerror(errno));
277
+        return -1;
278
+    }
279
+	
280
+    io.pfrio_buffer = table_aux;
281
+    io.pfrio_esize = sizeof(struct pfr_table);
282
+	
283
+    if(ioctl(dev, DIOCRGETTABLES, &io)) {
284
+        SCLogError(SC_ERR_SYSCALL, "AlertPfTableExists() => ioctl() DIOCRGETTABLES: %s\n", strerror(errno));
285
+	return -1;
286
+    }
287
+
288
+    for(i=0; i < io.pfrio_size; i++) {
289
+        if (!strcmp(table_aux[i].pfrt_name, tablename))
290
+            return 1;	
291
+    }
292
+	
293
+    return 0;
294
+}
295
+
296
+/** \brief Inserts the passed IP address into the pf block table
297
+ *  \param *data pointer to AlertPfThread structure for current thread
298
+ *  \param *net_addr pointer to IP address to block
299
+ *  \retval -1 on error, 1 if IP blocked, 0 if already blocked */
300
+static int AlertPfBlock(AlertPfThread *data, Address *net_addr) 
301
+{ 
302
+    struct pfioc_table io; 
303
+    struct pfr_table table; 
304
+    struct pfr_addr addr; 
305
+
306
+    if (data->fd < 0)
307
+	data->fd = AlertPfDeviceInit();
308
+    if (data->fd == -1) {
309
+	SCLogError(SC_ERR_SYSCALL, "AlertPfDeviceInit() => no pf device\n");
310
+	return -1;
311
+    }
312
+
313
+    memset(&io,    0x00, sizeof(struct pfioc_table)); 
314
+    memset(&table, 0x00, sizeof(struct pfr_table)); 
315
+    memset(&addr,  0x00, sizeof(struct pfr_addr)); 
316
+            
317
+    strlcpy(table.pfrt_name, data->ctx->pftable, PF_TABLE_NAME_SIZE); 
318
+        
319
+    net_addr->family == AF_INET ? memcpy(&addr.pfra_ip4addr.s_addr, net_addr->addr_data32, sizeof(in_addr_t)) : memcpy(&addr.pfra_ip6addr, net_addr->addr_data8, sizeof(struct in6_addr));
320
+
321
+    addr.pfra_af  = net_addr->family; 
322
+    addr.pfra_net = net_addr->family == AF_INET ? 32 : 128;
323
+
324
+    io.pfrio_table  = table; 
325
+    io.pfrio_buffer = &addr; 
326
+    io.pfrio_esize  = sizeof(addr); 
327
+    io.pfrio_size   = 1; 
328
+        
329
+    if (ioctl(data->fd, DIOCRADDADDRS, &io)) {
330
+	SCLogError(SC_ERR_SYSCALL, "AlertPfBlock() => ioctl() DIOCRADDADDRS: %s\n", strerror(errno));
331
+	return (-1);
332
+    }
333
+ 
334
+    if (io.pfrio_nadd > 0) {
335
+        SC_ATOMIC_ADD(alert_pf_blocks, 1);
336
+    }
337
+
338
+    if (data->ctx->kill_state) {
339
+	struct pfioc_state_kill psk;
340
+
341
+        memset(&psk, 0, sizeof(psk));
342
+	memset(&psk.psk_src.addr.v.a.mask, 0xff, sizeof(psk.psk_src.addr.v.a.mask));
343
+	psk.psk_af = net_addr->family;
344
+	if (psk.psk_af == AF_INET)
345
+	    memcpy(&psk.psk_src.addr.v.a.addr.v4.s_addr, net_addr->addr_data32, sizeof(in_addr_t));
346
+	else if (psk.psk_af == AF_INET6)
347
+	    memcpy(&psk.psk_src.addr.v.a.addr.v6, net_addr->addr_data8, sizeof(struct in6_addr));
348
+	else {
349
+            SCLogError(SC_ERR_UNKNOWN_VALUE, "AlertPfBlock() unknown address family type: %d for source IP.", psk.psk_af);
350
+	    return (-1);
351
+        }
352
+
353
+	/* Attempt to clear any open states for source IP */
354
+	if (ioctl(data->fd, DIOCKILLSTATES, &psk))
355
+	    SCLogError(SC_ERR_SYSCALL, "AlertPfBlock() => ioctl() DIOCKILLSTATES: %s\n", strerror(errno));
356
+
357
+	memset(&psk, 0, sizeof(psk));
358
+	memset(&psk.psk_dst.addr.v.a.mask, 0xff, sizeof(psk.psk_dst.addr.v.a.mask));
359
+	psk.psk_af = net_addr->family;
360
+	if (psk.psk_af == AF_INET)
361
+	    memcpy(&psk.psk_dst.addr.v.a.addr.v4.s_addr, net_addr->addr_data32, sizeof(in_addr_t));
362
+	else if (psk.psk_af == AF_INET6)
363
+	    memcpy(&psk.psk_dst.addr.v.a.addr.v6, net_addr->addr_data8, sizeof(struct in6_addr));
364
+	else {
365
+            SCLogError(SC_ERR_UNKNOWN_VALUE, "AlertPfBlock() unknown address family type: %d for destination IP.", psk.psk_af);
366
+	    return (-1);
367
+        }
368
+
369
+	/* Attempt to clear any open states for destination IP */
370
+	if (ioctl(data->fd, DIOCKILLSTATES, &psk))
371
+	    SCLogError(SC_ERR_SYSCALL, "AlertPfBlock() => ioctl() DIOCKILLSTATES: %s\n", strerror(errno));
372
+    }
373
+
374
+    /* Return the number of effective IP blocks inserted */
375
+    return (io.pfrio_nadd); 
376
+}
377
+
378
+/** \brief Load and parse a single line of text from Pass List file
379
+ *  \param buf buffer of length WLMAX to receive a line of text from Pass List file
380
+ *  \param *wfile FILE pointer to open Pass List text file
381
+ *  \retval buf[] filled with next line of text from Pass List file
382
+ *  \retval 0 on EOF, 1 if success or -1 if line exceed WLMAX length */
383
+static int AlertPf_parse_line(char buf[WLMAX], FILE* wfile)
384
+{
385
+    static char     next_ch = '\n';
386
+    int             i = 0;
387
+
388
+    if (feof(wfile))
389
+        return (0);
390
+
391
+    do {
392
+        next_ch = fgetc(wfile);
393
+        if (i < WLMAX)
394
+            buf[i++] = next_ch;
395
+    } while (!feof(wfile) && next_ch != '\n');
396
+
397
+    if (i >= WLMAX)
398
+        return (-1);
399
+
400
+    buf[--i] = '\0';
401
+    return (1);
402
+}
403
+
404
+/** \brief Load and parse a Pass List text file and insert
405
+ *   the IP addresses and networks (in CIDR form) into a
406
+ *   Radix Tree for easy searching.
407
+ *  \param *plfile pointer to Pass List filename string
408
+ *  \param *ctx pointer to AlertPfCtx global data structure
409
+ *  \retval false (0) if error, true (-1) if success */
410
+static int AlertPfLoadPassList(char *plfile, AlertPfCtx *ctx)
411
+{
412
+    FILE *wfile;
413
+    struct flock lock;
414
+    char cad[WLMAX];
415
+    int ret;
416
+    int count = 0;
417
+
418
+    wfile = fopen(plfile, "r");
419
+    if (wfile == NULL) {
420
+        SCLogError(SC_ERR_FATAL, "Unable to open Pass List file: %s", strerror(errno));
421
+        return (0);
422
+    }
423
+
424
+    memset(&lock, 0x00, sizeof(struct flock));
425
+    lock.l_type = F_RDLCK;
426
+    fcntl(fileno(wfile), F_SETLKW, &lock);
427
+
428
+    ctx->tree = SCRadixCreateRadixTree(free, NULL);
429
+
430
+    memset(cad, 0, WLMAX);
431
+    while((ret = AlertPf_parse_line(cad, wfile)) != 0) {
432
+	if (ret == 1 && strlen(cad) > 0) {
433
+	    /* is it an IPv6 address? */
434
+	    if (strchr(cad, ':') != NULL) {
435
+	        if (SCRadixAddKeyIPV6String(cad, ctx->tree, NULL) == NULL) {
436
+		    SCLogInfo("Invalid IP(%s) parameter provided in Pass List, skipping...", cad);
437
+		    continue;
438
+		}
439
+		count++;
440
+	    }
441
+	    else {
442
+		if (SCRadixAddKeyIPV4String(cad, ctx->tree, NULL) == NULL) {
443
+		    SCLogInfo("Invalid IP(%s) parameter provided in Pass List, skipping...", cad);
444
+		    continue;
445
+		}
446
+		count++;
447
+	    }
448
+	} else if (ret == -1)
449
+	    SCLogInfo("Error occurred parsing line(%s) in Pass List, skipping...", cad);
450
+    }
451
+
452
+    lock.l_type = F_UNLCK;
453
+    fcntl(fileno(wfile), F_SETLKW, &lock);
454
+    fclose(wfile);
455
+
456
+    if (count == 1)
457
+	SCLogInfo("Pass List %s parsed: %d IP address loaded.", plfile, count);
458
+    else
459
+	SCLogInfo("Pass List %s parsed: %d IP addresses loaded.", plfile, count);
460
+
461
+    return (-1);
462
+}
463
+
464
+/**
465
+ * This initializes the data for a new thread.
466
+ */
467
+TmEcode AlertPfThreadInit(ThreadVars *t, void *initdata, void **data)
468
+{
469
+    AlertPfThread *apft;
470
+
471
+    if(initdata == NULL)
472
+    {
473
+        SCLogDebug("Error getting context for Alert-PF.  \"initdata\" argument NULL");
474
+        return TM_ECODE_FAILED;
475
+    }
476
+
477
+    apft = SCMalloc(sizeof(AlertPfThread));
478
+
479
+    if (unlikely(apft == NULL))
480
+        return TM_ECODE_FAILED;
481
+    memset(apft, 0, sizeof(AlertPfThread));
482
+
483
+    /* Use the Ouput Context */
484
+    apft->ctx = ((OutputCtx *)initdata)->data;
485
+
486
+    /* Open the pf device */
487
+    apft->fd = AlertPfDeviceInit();
488
+    if (apft->fd == -1) {
489
+	SCLogError(SC_ERR_SYSCALL, "Failed to open pf device, alert-pf module thread init failed.");
490
+        return TM_ECODE_FAILED;
491
+    }
492
+
493
+    *data = (void *)apft;
494
+    return TM_ECODE_OK;
495
+}
496
+
497
+/**
498
+ * This clears and releases the data for a thread.
499
+ */
500
+TmEcode AlertPfThreadDeinit(ThreadVars *t, void *data)
501
+{
502
+    AlertPfThread *apft = (AlertPfThread *)data;
503
+
504
+    if (apft == NULL) {
505
+        SCLogDebug("AlertPfThreadDeinit done (error)");
506
+        return TM_ECODE_FAILED;
507
+    }
508
+
509
+    /* Close the pf device */
510
+    close(apft->fd);
511
+
512
+    /* clear memory */
513
+    memset(apft, 0, sizeof(AlertPfThread));
514
+    SCFree(apft);
515
+
516
+    return TM_ECODE_OK;
517
+}
518
+
519
+/** \brief Print the pf alert module blocking stats.
520
+ *  \param *tv pointer to ThreadVars structure
521
+ *  \param *data pointer to AlertPfThread structure
522
+*/
523
+void AlertPfExitPrintStats(ThreadVars *tv, void *data)
524
+{
525
+    AlertPfThread *apft = (AlertPfThread *)data;
526
+    if (apft == NULL) {
527
+        return;
528
+    }
529
+
530
+    uint64_t alerts = SC_ATOMIC_GET(alert_pf_blocks);
531
+    if (alerts == 1)
532
+        SCLogInfo("alert-pf output inserted %" PRIu64 " IP address block", alerts);
533
+    else
534
+        SCLogInfo("alert-pf output inserted %" PRIu64 " IP address blocks", alerts);
535
+
536
+    if (apft->ctx->file_ctx->alerts == 1)
537
+        SCLogInfo("alert-pf output wrote %" PRIu64 " alerts", apft->ctx->file_ctx->alerts);
538
+    else
539
+        SCLogInfo("alert-pf output wrote %" PRIu64 " alerts", apft->ctx->file_ctx->alerts);
540
+
541
+    SC_ATOMIC_DESTROY(alert_pf_blocks);
542
+}
543
+
544
+/** \brief Initialize the pf alert blocking module.
545
+ *  \param *conf pointer to module's ConfNode structure
546
+ * \return A newly allocated AlertPfCtx structure, or NULL
547
+ */
548
+OutputCtx *AlertPfInitCtx(ConfNode *conf)
549
+{
550
+    AlertPfCtx *ctx;
551
+    LogFileCtx *logfile_ctx;
552
+    const char *pass_list_name;
553
+    const char *kill_state;
554
+    const char *block_ip;
555
+    const char *pf_table;
556
+    OutputCtx *output_ctx;
557
+
558
+    pass_list_name = ConfNodeLookupChildValue(conf, "pass-list");
559
+    if (pass_list_name == NULL) {
560
+	SCLogWarning(SC_WARN_UNCOMMON, "alert-pf: No Pass List specified, critical interface IPs may become blocked.");
561
+    }
562
+
563
+    kill_state = ConfNodeLookupChildValue(conf, "kill-state");
564
+    block_ip = ConfNodeLookupChildValue(conf, "block-ip");
565
+    pf_table = ConfNodeLookupChildValue(conf, "pf-table");
566
+
567
+    if (unlikely(pf_table == NULL)) {
568
+	SCLogError(SC_ERR_INVALID_ARGUMENT, "alert-pf: No PF table name specified, module init failed.");
569
+        exit(EXIT_FAILURE);
570
+    }
571
+
572
+    ctx = SCMalloc(sizeof(AlertPfCtx));
573
+    if (unlikely(ctx == NULL)) {
574
+	SCLogError(SC_ERR_MEM_ALLOC, "alert-pf: Unable to allocate memory for AlertPfCtx, module init failed.");
575
+        exit(EXIT_FAILURE);
576
+    }
577
+
578
+    /* Create a LogFileCtx for the block.log output */
579
+    logfile_ctx = LogFileNewCtx();
580
+    if (logfile_ctx == NULL) {
581
+        SCLogDebug("AlertPfInitCtx: Could not create new LogFileCtx");
582
+        SCFree(ctx);
583
+        return NULL;
584
+    }
585
+
586
+    if (SCConfLogOpenGeneric(conf, logfile_ctx, DEFAULT_LOG_FILENAME) < 0) {
587
+        LogFileFreeCtx(logfile_ctx);
588
+        SCLogDebug("AlertPfInitCtx: Could not create new LogFileCtx");
589
+        SCFree(ctx);
590
+        return NULL;
591
+    }
592
+
593
+    ctx->file_ctx = logfile_ctx;
594
+
595
+    ctx->kill_state = 1;
596
+    if (kill_state == NULL) {
597
+        SCLogWarning(SC_ERR_INVALID_ARGUMENT, "alert-pf: kill-state parameter not recognized, defaulting to 'yes'.");
598
+    }
599
+    if (kill_state && ConfValIsFalse(kill_state))
600
+        ctx->kill_state = 0;
601
+
602
+    if (block_ip == NULL) {
603
+        SCLogWarning(SC_ERR_INVALID_ARGUMENT, "alert-pf: block-ip parameter not recognized, defaulting to 'both'.");
604
+    }
605
+    if (block_ip && !strncasecmp("src", block_ip, strlen("src")))
606
+        ctx->block_ip = BLOCK_SRC;
607
+    else if (block_ip && !strncasecmp("dst", block_ip, strlen("dst")))
608
+        ctx->block_ip = BLOCK_DST;
609
+    else
610
+        ctx->block_ip = BLOCK_BOTH;
611
+
612
+    if (pass_list_name) {
613
+	AlertPfLoadPassList(SCStrdup(pass_list_name), ctx);
614
+    }
615
+
616
+    ctx->pftable = SCStrdup(pf_table);
617
+
618
+    /* TODO -- add validation of pf table */
619
+    if (AlertPfTableExists(ctx->pftable) != 1) {
620
+        LogFileFreeCtx(logfile_ctx);
621
+        SCFree(ctx);
622
+	SCLogError(SC_ERR_INVALID_ARGUMENT, "alert-pf: Could not validate pf table: %s, module init failed.", pf_table);
623
+        exit(EXIT_FAILURE);
624
+    }
625
+
626
+    output_ctx = SCMalloc(sizeof(OutputCtx));
627
+    if (unlikely(output_ctx == NULL)) {
628
+        LogFileFreeCtx(logfile_ctx);
629
+        SCFree(ctx);
630
+	SCLogError(SC_ERR_MEM_ALLOC, "alert-pf: Unable to allocate memory for OutputCtx, module init failed.");
631
+        exit(EXIT_FAILURE);
632
+    }
633
+    output_ctx->data = ctx;
634
+    output_ctx->DeInit = AlertPfDeInitCtx;
635
+    SC_ATOMIC_INIT(alert_pf_blocks);
636
+
637
+    const char *block;
638
+    switch (ctx->block_ip) {
639
+        case BLOCK_SRC:
640
+            block = "src";
641
+            break;
642
+
643
+        case BLOCK_DST:
644
+            block = "dst";
645
+            break;
646
+
647
+        default:
648
+            block = "both";
649
+    }
650
+    const char *state = ctx->kill_state ? "on" : "off";
651
+    SCLogInfo("alert-pf output initialized, pf-table=%s  block-ip=%s  kill-state=%s", ctx->pftable, block, state);
652
+
653
+    return output_ctx;
654
+}
655
+
656
+/** \brief This releases the memory used by the global
657
+ * AlertPfCtx data structure.
658
+ */
659
+static void AlertPfDeInitCtx(OutputCtx *output_ctx)
660
+{
661
+    AlertPfCtx *ctx = (AlertPfCtx *)output_ctx->data;
662
+    LogFileFreeCtx(ctx->file_ctx);
663
+    SCRadixReleaseRadixTree(ctx->tree);
664
+    SCFree(ctx);
665
+    SCFree(output_ctx);
666
+}
667
+
668
+/** \brief This processes an IPv4 alert and inserts the appropriate
669
+ * block if the IP address is not on the Pass List.
670
+ */
671
+TmEcode AlertPfIPv4(ThreadVars *tv, Packet *p, void *data, PacketQueue *pq, PacketQueue *postpq)
672
+{
673
+    AlertPfThread *apft = (AlertPfThread *)data;
674
+    int i;
675
+    char proto[16] = "";
676
+    char timebuf[64];
677
+    char srcip[16], dstip[16];
678
+
679
+    if (p->alerts.cnt == 0)
680
+        return TM_ECODE_OK;
681
+
682
+    CreateTimeString(&p->ts, timebuf, sizeof(timebuf));
683
+    PrintInet(AF_INET, (const void *)GET_IPV4_SRC_ADDR_PTR(p), srcip, sizeof(srcip));
684
+    PrintInet(AF_INET, (const void *)GET_IPV4_DST_ADDR_PTR(p), dstip, sizeof(dstip));
685
+
686
+    if (SCProtoNameValid(IPV4_GET_IPPROTO(p)) == TRUE) {
687
+        strlcpy(proto, known_proto[IPV4_GET_IPPROTO(p)], sizeof(proto));
688
+    } else {
689
+        snprintf(proto, sizeof(proto), "PROTO:%03" PRIu32, IPV4_GET_IPPROTO(p));
690
+    }
691
+
692
+    for (i = 0; i < p->alerts.cnt; i++) {
693
+        PacketAlert *pa = &p->alerts.alerts[i];
694
+        if (unlikely(pa->s == NULL)) {
695
+            continue;
696
+        }
697
+
698
+        switch (apft->ctx->block_ip) {
699
+
700
+            case BLOCK_BOTH:
701
+	        /* Block only if IP is not in Pass List */
702
+	        if (SCRadixFindKeyIPV4BestMatch((uint8_t *)&GET_IPV4_SRC_ADDR_U32(p), apft->ctx->tree) == NULL) {
703
+                    if (AlertPfBlock(apft, &p->src) > 0) {
704
+                        SCMutexLock(&apft->ctx->file_ctx->fp_mutex);
705
+                        fprintf(apft->ctx->file_ctx->fp, "%s,Block Src,%" PRIu32 ",%" PRIu32 ",%"
706
+                                PRIu32 ",%s,%s,%" PRIu32
707
+                                ",%s,%s,%" PRIu32 "\n", timebuf, pa->s->gid,
708
+                                pa->s->id, pa->s->rev, pa->s->msg, pa->s->class_msg, pa->s->prio,
709
+                                proto, srcip, p->sp);
710
+                        fflush(apft->ctx->file_ctx->fp);
711
+                        apft->ctx->file_ctx->alerts++;
712
+                        SCMutexUnlock(&apft->ctx->file_ctx->fp_mutex);
713
+                    }
714
+                }
715
+                if (SCRadixFindKeyIPV4BestMatch((uint8_t *)&GET_IPV4_DST_ADDR_U32(p), apft->ctx->tree) == NULL) {
716
+                    if (AlertPfBlock(apft, &p->dst) > 0) {
717
+                        SCMutexLock(&apft->ctx->file_ctx->fp_mutex);
718
+                        fprintf(apft->ctx->file_ctx->fp, "%s,Block Dst,%" PRIu32 ",%" PRIu32 ",%"
719
+                                PRIu32 ",%s,%s,%" PRIu32
720
+                                ",%s,%s,%" PRIu32 "\n", timebuf, pa->s->gid,
721
+                                pa->s->id, pa->s->rev, pa->s->msg, pa->s->class_msg, pa->s->prio,
722
+                                proto, dstip, p->dp);
723
+                        fflush(apft->ctx->file_ctx->fp);
724
+                        apft->ctx->file_ctx->alerts++;
725
+                        SCMutexUnlock(&apft->ctx->file_ctx->fp_mutex);
726
+                    }
727
+                }
728
+                break;
729
+
730
+            case BLOCK_SRC:
731
+                /* Block SRC only if IP is not in Pass List */
732
+	        if (SCRadixFindKeyIPV4BestMatch((uint8_t *)&GET_IPV4_SRC_ADDR_U32(p), apft->ctx->tree) == NULL) {
733
+                    if (AlertPfBlock(apft, &p->src) > 0) {
734
+                        SCMutexLock(&apft->ctx->file_ctx->fp_mutex);
735
+                        fprintf(apft->ctx->file_ctx->fp, "%s,Block Src,%" PRIu32 ",%" PRIu32 ",%"
736
+                                PRIu32 ",%s,%s,%" PRIu32
737
+                                ",%s,%s,%" PRIu32 "\n", timebuf, pa->s->gid,
738
+                                pa->s->id, pa->s->rev, pa->s->msg, pa->s->class_msg, pa->s->prio,
739
+                                proto, srcip, p->sp);
740
+                        fflush(apft->ctx->file_ctx->fp);
741
+                        apft->ctx->file_ctx->alerts++;
742
+                        SCMutexUnlock(&apft->ctx->file_ctx->fp_mutex);
743
+                    }
744
+                }
745
+                break;
746
+
747
+            case BLOCK_DST:
748
+	        /* Block DST only if IP is not in Pass List */
749
+	        if (SCRadixFindKeyIPV4BestMatch((uint8_t *)&GET_IPV4_DST_ADDR_U32(p), apft->ctx->tree) == NULL) {
750
+                    if (AlertPfBlock(apft, &p->dst) > 0) {
751
+                        SCMutexLock(&apft->ctx->file_ctx->fp_mutex);
752
+                        fprintf(apft->ctx->file_ctx->fp, "%s,Block Dst,%" PRIu32 ",%" PRIu32 ",%"
753
+                                PRIu32 ",%s,%s,%" PRIu32
754
+                                ",%s,%s,%" PRIu32 "\n", timebuf, pa->s->gid,
755
+                                pa->s->id, pa->s->rev, pa->s->msg, pa->s->class_msg, pa->s->prio,
756
+                                proto, dstip, p->dp);
757
+                        fflush(apft->ctx->file_ctx->fp);
758
+                        apft->ctx->file_ctx->alerts++;
759
+                        SCMutexUnlock(&apft->ctx->file_ctx->fp_mutex);
760
+                    }
761
+                }
762
+        }
763
+
764
+        /* Once we find and block the first packet alert for this IP, we're done */
765
+        break;
766
+    }
767
+
768
+    return TM_ECODE_OK;
769
+}
770
+
771
+/** \brief This processes an IPv6 alert and inserts the appropriate
772
+ * block if the IP address is not on the Pass List.
773
+ */
774
+TmEcode AlertPfIPv6(ThreadVars *tv, Packet *p, void *data, PacketQueue *pq, PacketQueue *postpq)
775
+{
776
+    AlertPfThread *apft = (AlertPfThread *)data;
777
+    int i;
778
+    char proto[16] = "";
779
+    char timebuf[64];
780
+    char srcip[46], dstip[46];
781
+
782
+    if (p->alerts.cnt == 0)
783
+        return TM_ECODE_OK;
784
+
785
+    CreateTimeString(&p->ts, timebuf, sizeof(timebuf));
786
+    PrintInet(AF_INET6, (const void *)GET_IPV6_SRC_ADDR(p), srcip, sizeof(srcip));
787
+    PrintInet(AF_INET6, (const void *)GET_IPV6_DST_ADDR(p), dstip, sizeof(dstip));
788
+
789
+    if (SCProtoNameValid(IPV6_GET_L4PROTO(p)) == TRUE) {
790
+        strlcpy(proto, known_proto[IPV6_GET_L4PROTO(p)], sizeof(proto));
791
+    } else {
792
+        snprintf(proto, sizeof(proto), "PROTO:%03" PRIu32, IPV6_GET_L4PROTO(p));
793
+    }
794
+
795
+    for (i = 0; i < p->alerts.cnt; i++) {
796
+        PacketAlert *pa = &p->alerts.alerts[i];
797
+        if (unlikely(pa->s == NULL)) {
798
+            continue;
799
+        }
800
+
801
+        switch (apft->ctx->block_ip) {
802
+
803
+    	    case BLOCK_BOTH:
804
+                /* Block only if IP is not in Pass List */
805
+	        if (SCRadixFindKeyIPV6BestMatch((uint8_t *)&GET_IPV6_SRC_ADDR(p), apft->ctx->tree) == NULL) {
806
+                    if (AlertPfBlock(apft, &p->src) > 0) {
807
+                        SCMutexLock(&apft->ctx->file_ctx->fp_mutex);
808
+                        fprintf(apft->ctx->file_ctx->fp, "%s,Block Src,%" PRIu32 ",%" PRIu32 ",%"
809
+                                PRIu32 ",%s,%s,%" PRIu32
810
+                                ",%s,%s,%" PRIu32 "\n", timebuf, pa->s->gid,
811
+                                pa->s->id, pa->s->rev, pa->s->msg, pa->s->class_msg, pa->s->prio,
812
+                                proto, srcip, p->sp);
813
+                        fflush(apft->ctx->file_ctx->fp);
814
+                        apft->ctx->file_ctx->alerts++;
815
+                        SCMutexUnlock(&apft->ctx->file_ctx->fp_mutex);
816
+                    }
817
+                }
818
+	        if (SCRadixFindKeyIPV6BestMatch((uint8_t *)&GET_IPV6_DST_ADDR(p), apft->ctx->tree) == NULL) {
819
+                    if (AlertPfBlock(apft, &p->dst) > 0) {
820
+                        SCMutexLock(&apft->ctx->file_ctx->fp_mutex);
821
+                        fprintf(apft->ctx->file_ctx->fp, "%s,Block Dst,%" PRIu32 ",%" PRIu32 ",%"
822
+                                PRIu32 ",%s,%s,%" PRIu32
823
+                                ",%s,%s,%" PRIu32 "\n", timebuf, pa->s->gid,
824
+                                pa->s->id, pa->s->rev, pa->s->msg, pa->s->class_msg, pa->s->prio,
825
+                                proto, dstip, p->dp);
826
+                        fflush(apft->ctx->file_ctx->fp);
827
+                        apft->ctx->file_ctx->alerts++;
828
+                        SCMutexUnlock(&apft->ctx->file_ctx->fp_mutex);
829
+                    }
830
+                }
831
+	        break;
832
+
833
+	    case BLOCK_SRC:
834
+	        /* Block SRC only if IP is not in Pass List */
835
+	        if (SCRadixFindKeyIPV6BestMatch((uint8_t *)&GET_IPV6_SRC_ADDR(p), apft->ctx->tree) == NULL) {
836
+                    if (AlertPfBlock(apft, &p->src) > 0) {
837
+                        SCMutexLock(&apft->ctx->file_ctx->fp_mutex);
838
+                        fprintf(apft->ctx->file_ctx->fp, "%s,Block Src,%" PRIu32 ",%" PRIu32 ",%"
839
+                                PRIu32 ",%s,%s,%" PRIu32
840
+                                ",%s,%s,%" PRIu32 "\n", timebuf, pa->s->gid,
841
+                                pa->s->id, pa->s->rev, pa->s->msg, pa->s->class_msg, pa->s->prio,
842
+                                proto, srcip, p->sp);
843
+                        fflush(apft->ctx->file_ctx->fp);
844
+                        apft->ctx->file_ctx->alerts++;
845
+                        SCMutexUnlock(&apft->ctx->file_ctx->fp_mutex);
846
+                    }
847
+                }
848
+	        break;
849
+
850
+	    case BLOCK_DST:
851
+	        /* Block DST only if IP is not in Pass List */
852
+	        if (SCRadixFindKeyIPV6BestMatch((uint8_t *)&GET_IPV6_DST_ADDR(p), apft->ctx->tree) == NULL) {
853
+                    if (AlertPfBlock(apft, &p->dst) > 0) {
854
+                        SCMutexLock(&apft->ctx->file_ctx->fp_mutex);
855
+                        fprintf(apft->ctx->file_ctx->fp, "%s,Block Dst,%" PRIu32 ",%" PRIu32 ",%"
856
+                                PRIu32 ",%s,%s,%" PRIu32
857
+                                ",%s,%s,%" PRIu32 "\n", timebuf, pa->s->gid,
858
+                                pa->s->id, pa->s->rev, pa->s->msg, pa->s->class_msg, pa->s->prio,
859
+                                proto, dstip, p->dp);
860
+                        fflush(apft->ctx->file_ctx->fp);
861
+                        apft->ctx->file_ctx->alerts++;
862
+                        SCMutexUnlock(&apft->ctx->file_ctx->fp_mutex);
863
+                    }
864
+                }
865
+        }
866
+
867
+        /* Once we find and block the first packet alert for this IP, we're done */
868
+        break;
869
+    }
870
+
871
+    return TM_ECODE_OK;
872
+}
873
+
874
+/** \brief This processes an IP alert and routes it to the
875
+ * appropriate handler.
876
+ */
877
+TmEcode AlertPf (ThreadVars *tv, Packet *p, void *data, PacketQueue *pq, PacketQueue *postpq)
878
+{
879
+    if (PKT_IS_IPV4(p)) {
880
+        return AlertPfIPv4(tv, p, data, pq, postpq);
881
+    } else if (PKT_IS_IPV6(p)) {
882
+        return AlertPfIPv6(tv, p, data, pq, postpq);
883
+    }
884
+
885
+    return TM_ECODE_OK;
886
+}
887
+
888
diff -rNu ./src/alert-pf.h ./src.new/alert-pf.h
889
--- ./src/alert-pf.h	1969-12-31 19:00:00.000000000 -0500
890
+++ ./src.new/alert-pf.h	2014-04-21 20:13:22.000000000 -0400
891
@@ -0,0 +1,51 @@
892
+/* Copyright (C) 2007-2010 Open Information Security Foundation
893
+ *
894
+ * You can copy, redistribute or modify this Program under the terms of
895
+ * the GNU General Public License version 2 as published by the Free
896
+ * Software Foundation.
897
+ *
898
+ * This program is distributed in the hope that it will be useful,
899
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
900
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
901
+ * GNU General Public License for more details.
902
+ *
903
+ * You should have received a copy of the GNU General Public License
904
+ * version 2 along with this program; if not, write to the Free Software
905
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
906
+ * 02110-1301, USA.
907
+ */
908
+
909
+/**
910
+ * \file
911
+ *
912
+ * \author Bill Meeks <bill@themeeks.net>
913
+ */
914
+
915
+#ifndef __ALERT_PF_H__
916
+#define __ALERT_PF_H__
917
+
918
+/**
919
+ * define these macros since we need them in <net/pfvar.h>
920
+ * and Suricata by default uses it's own customized
921
+ * <queue.h> file that omits these particular macros.
922
+ */
923
+#define SLIST_HEAD(name, type)						\
924
+struct name {								\
925
+	struct type *slh_first;	/* first element */			\
926
+}
927
+
928
+#define	SLIST_HEAD_INITIALIZER(head)					\
929
+	{ NULL }
930
+
931
+#define SLIST_ENTRY(type)						\
932
+struct {								\
933
+	struct type *sle_next;	/* next element */			\
934
+}
935
+
936
+void TmModuleAlertPfRegister (void);
937
+void TmModuleAlertPfIPv4Register (void);
938
+void TmModuleAlertPfIPv6Register (void);
939
+OutputCtx *AlertPfInitCtx(ConfNode *);
940
+
941
+#endif /* __ALERT_PF_H__ */
942
+
943
diff -rNu ./src/suricata.c ./src.new/suricata.c
944
--- ./src/suricata.c	2013-09-24 06:28:37.000000000 -0400
945
+++ ./src.new/suricata.c	2014-04-30 19:20:58.000000000 -0400
946
@@ -100,6 +100,7 @@
947
 #include "alert-prelude.h"
948
 #include "alert-syslog.h"
949
 #include "alert-pcapinfo.h"
950
+#include "alert-pf.h"
951
 
952
 #include "log-droplog.h"
953
 #include "log-httplog.h"
954
@@ -1557,6 +1558,10 @@
955
     /* napatech */
956
     TmModuleNapatechStreamRegister();
957
     TmModuleNapatechDecodeRegister();
958
+    /* alert pf */
959
+    TmModuleAlertPfRegister();
960
+    TmModuleAlertPfIPv4Register();
961
+    TmModuleAlertPfIPv6Register();
962
 
963
     /* stream engine */
964
     TmModuleStreamTcpRegister();
965
@@ -1887,6 +1892,7 @@
966
         if (engine_analysis) {
967
             exit(EXIT_SUCCESS);
968
         }
969
+        SCThresholdConfInitContext(de_ctx,NULL);
970
     }
971
 
972
     /* registering singal handlers we use.  We register usr2 here, so that one
973
@@ -1898,7 +1904,6 @@
974
     SCCudaPBSetUpQueuesAndBuffers();
975
 #endif /* __SC_CUDA_SUPPORT__ */
976
 
977
-    SCThresholdConfInitContext(de_ctx,NULL);
978
     SCAsn1LoadConfig();
979
 
980
     CoredumpLoadConfig();
981
@@ -2019,6 +2024,7 @@
982
             if (de_ctx->failure_fatal)
983
                 exit(EXIT_FAILURE);
984
         }
985
+        SCThresholdConfInitContext(de_ctx,NULL);
986
         TmThreadActivateDummySlot();
987
         SCLogInfo("Signature(s) loaded, Detect thread(s) activated.");
988
     }
989
diff -rNu ./src/tm-modules.c ./src.new/tm-modules.c
990
--- ./src/tm-modules.c	2013-09-24 06:28:37.000000000 -0400
991
+++ ./src.new/tm-modules.c	2014-04-18 16:45:17.000000000 -0400
992
@@ -238,6 +238,9 @@
993
         CASE_CODE (TMM_ALERTPRELUDE);
994
         CASE_CODE (TMM_ALERTDEBUGLOG);
995
         CASE_CODE (TMM_ALERTSYSLOG);
996
+	CASE_CODE (TMM_ALERTPF);
997
+	CASE_CODE (TMM_ALERTPF4);
998
+	CASE_CODE (TMM_ALERTPF6);
999
         CASE_CODE (TMM_LOGDROPLOG);
1000
         CASE_CODE (TMM_ALERTSYSLOG4);
1001
         CASE_CODE (TMM_ALERTSYSLOG6);
1002
diff -rNu ./src/tm-threads-common.h ./src.new/tm-threads-common.h
1003
--- ./src/tm-threads-common.h	2013-09-24 06:28:37.000000000 -0400
1004
+++ ./src.new/tm-threads-common.h	2014-04-18 18:59:26.000000000 -0400
1005
@@ -78,6 +78,9 @@
1006
     TMM_ALERTPCAPINFO,
1007
     TMM_RECEIVENAPATECH,
1008
     TMM_DECODENAPATECH,
1009
+    TMM_ALERTPF,
1010
+    TMM_ALERTPF4,
1011
+    TMM_ALERTPF6,
1012
     TMM_SIZE,
1013
 } TmmId;
1014
 
(2-2/4)