1 /* $Id: ssp_pf.c,v 3.6 2009/11/27 01:39:40 fknobbe Exp $
2 *
3 * Copyright (c) 2003 Hector Paterno <apaterno@dsnsecurity.com>
4 * Copyright (c) 2004-2008 Olaf Schreck <chakl@syscall.de>
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 *
28 *
29 * ssp_pf.c
30 *
31 * Purpose:
32 *
33 * This SnortSam plugin is meant for dynamic (un)blocking on PF (OpenBSD) firewall,
34 * SnortSam will expire the blocks itself since PF does not have
35 * automatic time-out functionality.
36 *
37 * It Works on OpenBSD >= 3_3, and for FreeBSD >= 5.1.
38 * For newer *BSD versions use the PF2 plugin.
39 */
40
41 #ifndef USE_SSP_PF
42 #if defined(OpenBSD) || defined(FreeBSD) || defined(NetBSD)
43
44 #ifndef __SSP_PF_C__
45 #define __SSP_PF_C__
46
47 #include "snortsam.h"
48 #include "ssp_pf.h"
49
50 #include <sys/types.h>
51 #include <stdio.h>
52 #include <string.h>
53 #include <time.h>
54 #include <netinet/in.h>
55 #include <arpa/inet.h>
56 /* By pf */
57 #include <sys/ioctl.h>
58 #include <sys/fcntl.h>
59 #include <net/if.h>
60 #include <net/pfvar.h>
61 #include <sys/param.h>
62 #include <errno.h>
63 /* End */
64
65 /* Defines should be done in ssp_pf.h */
66
67
68 /* Routine for opt parsing ( opt=value opt2=value2 etc. ) */
parse_opts(char * line,opt_s * opt,char * sep,char * int_sep,int nopt)69 int parse_opts(char *line, opt_s *opt, char *sep, char *int_sep, int nopt)
70 {
71 char *last;
72 char *last2;
73 char *pt;
74 char *pt2;
75 int fo=0;
76 int di=0;
77
78 if((line==NULL) || (opt==NULL) || (sep==NULL) || (int_sep==NULL))
79 return -1;
80
81 for(pt=strtok_r(line, sep, &last); pt; pt=strtok_r(NULL, sep, &last))
82 {
83 for(pt2=strtok_r(pt, int_sep, &last2), fo=0; pt2; pt2=strtok_r(NULL, int_sep, &last2))
84 {
85 if(fo==0)
86 {
87 for(; fo<nopt; fo++)
88 {
89 if (strncmp(opt[fo].name, pt2, MAX_OPT_NAME)==0)
90 {
91 fo++;
92 di++;
93 break;
94 }
95 }
96 }
97 else
98 {
99 if(di)
100 if(opt[--fo].vt>0)
101 strncpy(opt[fo].v.value_s, pt2, MAX_OPT_VALUE);
102 else
103 opt[fo].v.value_d=atoi(pt2);
104 fo=0;
105 di=0;
106 }
107 }
108 }
109
110 return;
111 }
112
113
114 /*
115 * This routine parses the pf statements in the config file.
116 * TODO: If the "auto" parameter is pased, initialize the main rule, anchor and rulesets/rules
117 */
118 void
PFParse(char * val,char * file,unsigned long line,DATALIST * plugindatalist)119 PFParse(char *val, char *file, unsigned long line, DATALIST * plugindatalist)
120 {
121 PFDATA *pfp = NULL;
122 char msg[STRBUFSIZE + 2];
123 opt_s options[5]={
124 {"auto", 0, 0},
125 {"log", 0, 0},
126 {"eth", "", 1},
127 {"anchor", "", 1},
128 {"table", "", 1}
129 };
130
131 /* used for auto=1 */
132 int pfdev;
133 struct pfioc_rule rule;
134 struct pfioc_pooladdr paddr;
135 struct pfioc_table tablemain;
136 struct pfr_table table;
137
138
139 #ifdef FWSAMDEBUG
140 printf("Debug: [pf] Plugin Parsing...\n");
141 #endif
142
143 if (*val)
144 {
145 if(parse_opts(val, options, " \t", "=", (sizeof(options)/sizeof(opt_s)))<0)
146 {
147 snprintf(msg, sizeof(msg) - 1, "Error: [%s: %lu] invalid PF parameters !. PF Plugin disabled.", file, line);
148 logmessage(1, msg, "pf", 0);
149 plugindatalist->data=NULL;
150 return;
151 }
152
153 pfp = safemalloc(sizeof(PFDATA), "PFParse", "pfp");
154 bzero(pfp, sizeof(PFDATA));
155 plugindatalist->data = pfp;
156
157 /* Check Anchor */
158 if(strlen(options[PF_OPT_ANCHOR].v.value_s)<1)
159 {
160 snprintf(msg, sizeof(msg) - 1, "Info: [%s: %lu] PF anchor name not defined, using \"snortsam\"", file, line );
161 logmessage(1, msg, "pf", 0);
162 safecopy(pfp->anchorname, "snortsam"); /* save anchorname */
163 }
164 else
165 {
166 safecopy(pfp->anchorname, options[PF_OPT_ANCHOR].v.value_s); /* save anchorname */
167 }
168
169 /* define the table (fixed cannot changed) */
170 safecopy(pfp->tablename, "block"); /* save tablename */
171
172 /* Check eth */
173 if(strlen(options[PF_OPT_ETH].v.value_s)<1)
174 {
175 snprintf(msg, sizeof(msg) - 1, "Warning: [%s: %lu] PF ethernet name not defined, the IPs will be blocked on all interfaces !", file, line);
176 logmessage(1, msg, "pf", 0);
177 }
178 else
179 {
180 safecopy(pfp->iface, options[PF_OPT_ETH].v.value_s); /* save eth */
181 }
182
183 /* Save the log option */
184 pfp->logopt = options[PF_OPT_LOG].v.value_d;
185
186 }else
187 {
188 snprintf(msg, sizeof(msg) - 1, "Error: [%s: %lu] PF defined without parameters! PF plugin disabled.", file, line);
189 logmessage(1, msg, "pf", 0);
190 free(pfp);
191 plugindatalist->data=NULL;
192 return;
193 }
194
195 if(options[PF_OPT_AUTO].v.value_d) /* Create the anchor call rules, create the anchor, rulesets and tables */
196 {
197 if ((pfdev = open(PFDEV, PFPERM)) == -1)
198 {
199 snprintf(msg, sizeof(msg) - 1, "Error: Can't open %s device (auto=1), %s. PF plugin disabled.", PFDEV, strerror(errno));
200 logmessage(1, msg, "pf", 0);
201 free(pfp);
202 plugindatalist->data=NULL;
203 return;
204 }
205
206 /* Create the anchor call rule in main */
207 bzero(&rule, sizeof(struct pfioc_rule));
208 strncpy(rule.rule.ifname, pfp->iface, IFNAMSIZ);
209 strncpy(rule.anchor_call, pfp->anchorname, PF_ANCHOR_NAME_SIZE-1);
210
211 rule.action = PF_CHANGE_GET_TICKET;
212 if(ioctl(pfdev, DIOCCHANGERULE, &rule)<0)
213 {
214 snprintf(msg, sizeof(msg) - 1, "Error: DIOCCHANGERULE 1 (auto=1) : %s. PF plugin disabled.", strerror(errno));
215 logmessage(1, msg, "pf", 0);
216 free(pfp);
217 plugindatalist->data=NULL;
218 return;
219 }
220
221 if(ioctl(pfdev, DIOCBEGINADDRS, &paddr)<0)
222 {
223 snprintf(msg, sizeof(msg) - 1, "Error: DIOCBEGINADDRS 2 (auto=1) : %s. PF plugin disabled.", strerror(errno));
224 logmessage(1, msg, "pf", 0);
225 free(pfp);
226 plugindatalist->data=NULL;
227 return;
228 }
229
230 rule.pool_ticket = paddr.ticket;
231
232 rule.action = PF_CHANGE_ADD_HEAD;
233 if(ioctl(pfdev, DIOCCHANGERULE, &rule)<0)
234 {
235 snprintf(msg, sizeof(msg) - 1, "Error: DIOCCHANGERULE 3 (auto=1) : %s. PF plugin disabled.", strerror(errno));
236 logmessage(1, msg, "pf", 0);
237 free(pfp);
238 plugindatalist->data=NULL;
239 return;
240 }
241
242 /* Create the Ruleset IN With It rule and table in the anchor */
243 bzero(&tablemain, sizeof(struct pfioc_table));
244 bzero(&table, sizeof(struct pfr_table));
245
246 /* The table */
247 strncpy(&(table.pfrt_anchor[0]), pfp->anchorname, PF_ANCHOR_NAME_SIZE-1);
248 strncpy(&(table.pfrt_name[0]), "blockin", PF_TABLE_NAME_SIZE-1);
249 table.pfrt_flags = PFR_TFLAG_PERSIST;
250 tablemain.pfrio_buffer = &table;
251 tablemain.pfrio_size = 1;
252 tablemain.pfrio_esize = sizeof(table);
253
254 if(ioctl(pfdev, DIOCRADDTABLES, &tablemain)<0)
255 {
256 snprintf(msg, sizeof(msg) - 1, "Error: DIOCRADDTABLES (auto=1) : %s. PF plugin disabled.", strerror(errno));
257 logmessage(1, msg, "pf", 0);
258 free(pfp);
259 plugindatalist->data=NULL;
260 return;
261 }
262 /* The rule (block in <logopt> from <tablename> to any */
263 bzero(&rule, sizeof(struct pfioc_rule));
264 strncpy(&(table.pfrt_anchor[0]), pfp->anchorname, PF_ANCHOR_NAME_SIZE-1);
265 strncpy(rule.anchor, pfp->anchorname, PF_ANCHOR_NAME_SIZE-1);
266 rule.rule.action=PF_DROP;
267 rule.rule.direction=PF_IN;
268 rule.rule.quick=1;
269 rule.rule.log=pfp->logopt;
270 rule.rule.src.addr.type = PF_ADDR_TABLE;
271
272 strncpy(rule.rule.src.addr.v.tblname, "blockin", PF_TABLE_NAME_SIZE-1);
273
274 rule.action = PF_CHANGE_GET_TICKET;
275 if(ioctl(pfdev, DIOCCHANGERULE, &rule)<0)
276 {
277 snprintf(msg, sizeof(msg) - 1, "Error: DIOCCHANGERULE 4 (auto=1) : %s. PF plugin disabled.", strerror(errno));
278 logmessage(1, msg, "pf", 0);
279 free(pfp);
280 plugindatalist->data=NULL;
281 return;
282 }
283
284 if(ioctl(pfdev, DIOCBEGINADDRS, &paddr)<0)
285 {
286 snprintf(msg, sizeof(msg) - 1, "Error: DIOCBEGINADDRS (auto=1) : %s. PF plugin disabled.", strerror(errno));
287 logmessage(1, msg, "pf", 0);
288 free(pfp);
289 plugindatalist->data=NULL;
290 return;
291 }
292
293 rule.pool_ticket = paddr.ticket;
294
295 rule.action = PF_CHANGE_ADD_HEAD;
296 if(ioctl(pfdev, DIOCCHANGERULE, &rule)<0)
297 {
298 snprintf(msg, sizeof(msg) - 1, "Error: DIOCCHANGERULE 5 (auto=1) : %s. PF plugin disabled.", strerror(errno));
299 logmessage(1, msg, "pf", 0);
300 free(pfp);
301 plugindatalist->data=NULL;
302 return;
303 }
304
305 /* Create the Ruleset OUT With It rule and table in the anchor */
306 bzero(&tablemain, sizeof(struct pfioc_table));
307 bzero(&table, sizeof(struct pfr_table));
308
309 /* The table */
310 strncpy(&(table.pfrt_anchor[0]), pfp->anchorname, PF_ANCHOR_NAME_SIZE-1);
311 strncpy(&(table.pfrt_name[0]), "blockout", PF_TABLE_NAME_SIZE-1);
312 table.pfrt_flags = PFR_TFLAG_PERSIST;
313 tablemain.pfrio_buffer = &table;
314 tablemain.pfrio_size = 1;
315 tablemain.pfrio_esize = sizeof(table);
316
317 if(ioctl(pfdev, DIOCRADDTABLES, &tablemain)<0)
318 {
319 snprintf(msg, sizeof(msg) - 1, "Error: DIOCRADDTABLES (auto=1) : %s. PF plugin disabled.", strerror(errno));
320 logmessage(1, msg, "pf", 0);
321 free(pfp);
322 plugindatalist->data=NULL;
323 return;
324 }
325 /* The rule (block out <logopt> from any to <tablename>*/
326 bzero(&rule, sizeof(struct pfioc_rule));
327 strncpy(&(table.pfrt_anchor[0]), pfp->anchorname, PF_ANCHOR_NAME_SIZE-1);
328 strncpy(rule.anchor, pfp->anchorname, PF_ANCHOR_NAME_SIZE-1);
329 rule.rule.action=PF_DROP;
330 rule.rule.direction=PF_OUT;
331 rule.rule.quick=1;
332 rule.rule.log=pfp->logopt;
333 rule.rule.dst.addr.type = PF_ADDR_TABLE;
334
335 strncpy(rule.rule.dst.addr.v.tblname, "blockout", PF_TABLE_NAME_SIZE-1);
336
337 rule.action = PF_CHANGE_GET_TICKET;
338 if(ioctl(pfdev, DIOCCHANGERULE, &rule)<0)
339 {
340 snprintf(msg, sizeof(msg) - 1, "Error: DIOCCHANGERULE 6 (auto=1) : %s. PF plugin disabled.", strerror(errno));
341 logmessage(1, msg, "pf", 0);
342 free(pfp);
343 plugindatalist->data=NULL;
344 return;
345 }
346
347 if(ioctl(pfdev, DIOCBEGINADDRS, &paddr)<0)
348 {
349 snprintf(msg, sizeof(msg) - 1, "Error: DIOCBEGINADDRS (auto=1) : %s. PF plugin disabled.", strerror(errno));
350 logmessage(1, msg, "pf", 0);
351 free(pfp);
352 plugindatalist->data=NULL;
353 return;
354 }
355
356 rule.pool_ticket = paddr.ticket;
357
358 rule.action = PF_CHANGE_ADD_HEAD;
359 if(ioctl(pfdev, DIOCCHANGERULE, &rule)<0)
360 {
361 snprintf(msg, sizeof(msg) - 1, "Error: DIOCCHANGERULE 7 (auto=1) : %s. PF plugin disabled.", strerror(errno));
362 logmessage(1, msg, "pf", 0);
363 free(pfp);
364 plugindatalist->data=NULL;
365 return;
366 }
367
368 /* Create the Ruleset INOUT With It rule and table in the anchor */
369 bzero(&tablemain, sizeof(struct pfioc_table));
370 bzero(&table, sizeof(struct pfr_table));
371
372 /* The table */
373 strncpy(&(table.pfrt_anchor[0]), pfp->anchorname, PF_ANCHOR_NAME_SIZE-1);
374 strncpy(&(table.pfrt_name[0]), "blockinout", PF_TABLE_NAME_SIZE-1);
375 table.pfrt_flags = PFR_TFLAG_PERSIST;
376 tablemain.pfrio_buffer = &table;
377 tablemain.pfrio_size = 1;
378 tablemain.pfrio_esize = sizeof(table);
379
380 if(ioctl(pfdev, DIOCRADDTABLES, &tablemain)<0)
381 {
382 snprintf(msg, sizeof(msg) - 1, "Error: DIOCRADDTABLES (auto=1) : %s. PF plugin disabled.", strerror(errno));
383 logmessage(1, msg, "pf", 0);
384 free(pfp);
385 plugindatalist->data=NULL;
386 return;
387 }
388 /* The rules (block in <logopt> from <tablename> to any, and, block out <logopt> from any to <tablename>*/
389 /* The IN */
390 bzero(&rule, sizeof(struct pfioc_rule));
391 strncpy(&(table.pfrt_anchor[0]), pfp->anchorname, PF_ANCHOR_NAME_SIZE-1);
392 strncpy(rule.anchor, pfp->anchorname, PF_ANCHOR_NAME_SIZE-1);
393 rule.rule.action=PF_DROP;
394 rule.rule.direction=PF_IN;
395 rule.rule.quick=1;
396 rule.rule.log=pfp->logopt;
397 rule.rule.src.addr.type = PF_ADDR_TABLE;
398
399 strncpy(rule.rule.src.addr.v.tblname, "blockinout", PF_TABLE_NAME_SIZE-1);
400
401 rule.action = PF_CHANGE_GET_TICKET;
402 if(ioctl(pfdev, DIOCCHANGERULE, &rule)<0)
403 {
404 snprintf(msg, sizeof(msg) - 1, "Error: DIOCCHANGERULE 8 (auto=1) : %s. PF plugin disabled.", strerror(errno));
405 logmessage(1, msg, "pf", 0);
406 free(pfp);
407 plugindatalist->data=NULL;
408 return;
409 }
410
411 if(ioctl(pfdev, DIOCBEGINADDRS, &paddr)<0)
412 {
413 snprintf(msg, sizeof(msg) - 1, "Error: DIOCBEGINADDRS (auto=1) : %s. PF plugin disabled.", strerror(errno));
414 logmessage(1, msg, "pf", 0);
415 free(pfp);
416 plugindatalist->data=NULL;
417 return;
418 }
419
420 rule.pool_ticket = paddr.ticket;
421
422 rule.action = PF_CHANGE_ADD_HEAD;
423 if(ioctl(pfdev, DIOCCHANGERULE, &rule)<0)
424 {
425 snprintf(msg, sizeof(msg) - 1, "Error: DIOCCHANGERULE 9 (auto=1) : %s. PF plugin disabled.", strerror(errno));
426 logmessage(1, msg, "pf", 0);
427 free(pfp);
428 plugindatalist->data=NULL;
429 return;
430 }
431
432 /* The OUT */
433 bzero(&rule, sizeof(struct pfioc_rule));
434 strncpy(&(table.pfrt_anchor[0]), pfp->anchorname, PF_ANCHOR_NAME_SIZE-1);
435 strncpy(rule.anchor, pfp->anchorname, PF_ANCHOR_NAME_SIZE-1);
436 rule.rule.action=PF_DROP;
437 rule.rule.direction=PF_OUT;
438 rule.rule.quick=1;
439 rule.rule.log=pfp->logopt;
440 rule.rule.dst.addr.type = PF_ADDR_TABLE;
441
442 strncpy(rule.rule.dst.addr.v.tblname, "blockinout", PF_TABLE_NAME_SIZE-1);
443
444 rule.action = PF_CHANGE_GET_TICKET;
445 if(ioctl(pfdev, DIOCCHANGERULE, &rule)<0)
446 {
447 snprintf(msg, sizeof(msg) - 1, "Error: DIOCCHANGERULE 10 (auto=1) : %s. PF plugin disabled.", strerror(errno));
448 logmessage(1, msg, "pf", 0);
449 free(pfp);
450 plugindatalist->data=NULL;
451 return;
452 }
453
454 if(ioctl(pfdev, DIOCBEGINADDRS, &paddr)<0)
455 {
456 snprintf(msg, sizeof(msg) - 1, "Error: DIOCBEGINADDRS (auto=1) : %s. PF plugin disabled.", strerror(errno));
457 logmessage(1, msg, "pf", 0);
458 free(pfp);
459 plugindatalist->data=NULL;
460 return;
461 }
462
463 rule.pool_ticket = paddr.ticket;
464
465 rule.action = PF_CHANGE_ADD_HEAD;
466 if(ioctl(pfdev, DIOCCHANGERULE, &rule)<0)
467 {
468 snprintf(msg, sizeof(msg) - 1, "Error: DIOCCHANGERULE 11 (auto=1) : %s. PF plugin disabled.", strerror(errno));
469 logmessage(1, msg, "pf", 0);
470 free(pfp);
471 plugindatalist->data=NULL;
472 return;
473 }
474
475
476 /* Start PF */
477
478 if(ioctl(pfdev, DIOCSTART, 0)<0)
479 {
480 if(errno==EEXIST)
481 {
482 snprintf(msg, sizeof(msg) - 1, "Info: PF Already Enabled (auto=1).");
483 logmessage(1, msg, "pf", 0);
484 }
485 else
486 {
487 snprintf(msg, sizeof(msg) - 1, "Error: Can't start PF (auto=1) : %s. PF plugin disabled.", strerror(errno));
488 logmessage(1, msg, "pf", 0);
489 free(pfp);
490 plugindatalist->data=NULL;
491 return;
492 }
493
494 }
495
496
497
498 } /* auto=1 */
499
500 #ifdef FWSAMDEBUG
501 printf("Debug: [pf] Adding PF: \n");
502 printf("auto=%d\nlog=%d\neth=%s\n",options[PF_OPT_AUTO].v.value_d, pfp->logopt, pfp->iface);
503 printf("anchor=%s\ntable=%s\n",pfp->anchorname, pfp->tablename);
504 #endif
505
506 }
507
508
509 /*
510 * BLOCK/UNBLOCK Routine
511 */
512 void
PFBlock(BLOCKINFO * bd,void * data,unsigned long qp)513 PFBlock(BLOCKINFO * bd, void * data,unsigned long qp)
514 {
515 PFDATA *pfp;
516 int pfdev;
517 struct pfioc_table table;
518 struct pfr_addr pfr;
519 char msg[STRBUFSIZE + 2];
520 #ifdef FWSAMDEBUG
521 pthread_t threadid=pthread_self();
522 #endif
523
524 if(!data)
525 return;
526
527 pfp=(PFDATA *)data;
528
529 #ifdef FWSAMDEBUG
530 printf("Debug: [pf][%lx] Plugin Blocking...\n", threadid);
531 #endif
532
533 if((pfdev=open(PFDEV, PFPERM))==-1)
534 {
535 snprintf(msg, sizeof(msg) - 1, "Error: Can't open %d device, %s", PFDEV, strerror(errno));
536 logmessage(1, msg, "pf", 0);
537 return;
538 }
539
540
541 bzero(&table, sizeof(struct pfioc_table));
542 bzero(&pfr, sizeof(struct pfr_addr));
543 pfr.pfra_af = AF_INET;
544 pfr.pfra_net = 32;
545 table.pfrio_buffer = 𝔭
546 table.pfrio_size = 1;
547 table.pfrio_esize = sizeof(pfr);
548 strncpy(table.pfrio_table.pfrt_anchor, pfp->anchorname, PF_ANCHOR_NAME_SIZE-1);
549 switch(bd->mode & FWSAM_HOW)
550 {
551 case FWSAM_HOW_THIS:
552 strncpy(table.pfrio_table.pfrt_name, "blockinout", PF_TABLE_NAME_SIZE - 1);
553 break;
554 case FWSAM_HOW_IN:
555 strncpy(table.pfrio_table.pfrt_name, "blockin", PF_TABLE_NAME_SIZE - 1);
556 break;
557 case FWSAM_HOW_OUT:
558 strncpy(table.pfrio_table.pfrt_name, "blockout", PF_TABLE_NAME_SIZE - 1);
559 break;
560 case FWSAM_HOW_INOUT:
561 strncpy(table.pfrio_table.pfrt_name, "blockinout", PF_TABLE_NAME_SIZE - 1);
562 break;
563 }
564
565
566 /* BLOCK */
567 if (bd->block)
568 {
569 snprintf(msg, sizeof(msg) - 1, "Info: Blocking ip %s", inettoa(bd->blockip));
570 logmessage(3, msg, "pf", 0);
571 switch(bd->mode & FWSAM_HOW)
572 {
573
574 case FWSAM_HOW_THIS: /* We Need a rule for this */
575 /* No yet, because the need to track the rule number (rn) to delete it */
576 /* Handled as HOW_INOUT */
577 pfr.pfra_u._pfra_ip4addr.s_addr = (u_int32_t) bd->blockip;
578 break;
579
580 case FWSAM_HOW_IN: /* ruleset : IN */
581 pfr.pfra_u._pfra_ip4addr.s_addr = (u_int32_t) bd->blockip;
582 break;
583
584 case FWSAM_HOW_OUT: /* ruleset : OUT */
585 pfr.pfra_u._pfra_ip4addr.s_addr = (u_int32_t) bd->blockip;
586 break;
587
588 case FWSAM_HOW_INOUT: /* ruleset : INOUT */
589 pfr.pfra_u._pfra_ip4addr.s_addr = (u_int32_t) bd->blockip;
590 break;
591
592 }
593 if(ioctl(pfdev, DIOCRADDADDRS, &table) < 0)
594 {
595 snprintf(msg, sizeof(msg) - 1, "Error: Can't Block ip %s (%s)", inettoa(bd->blockip), strerror(errno));
596 logmessage(1, msg, "pf", 0);
597 return; /* TODO: Should I return a negativa value ?, what if It Fails ? It will try to unblock it lather ? */
598 }
599 } /* BLOCK */
600 else /* UNBLOCK */
601 {
602 snprintf(msg, sizeof(msg) - 1, "Info: Unblocking ip %s", inettoa(bd->blockip));
603 logmessage(3, msg, "pf", 0);
604
605
606 switch(bd->mode & FWSAM_HOW)
607 {
608
609 case FWSAM_HOW_THIS: /* We Need a rule for this */
610 /* Handled as INOUT */
611 pfr.pfra_u._pfra_ip4addr.s_addr = (u_int32_t) bd->blockip;
612 break;
613
614 case FWSAM_HOW_IN: /* Uses the table */
615 pfr.pfra_u._pfra_ip4addr.s_addr = (u_int32_t) bd->blockip;
616 break;
617
618 case FWSAM_HOW_OUT:
619 pfr.pfra_u._pfra_ip4addr.s_addr = (u_int32_t) bd->blockip;
620 break;
621
622 case FWSAM_HOW_INOUT:
623 pfr.pfra_u._pfra_ip4addr.s_addr = (u_int32_t) bd->blockip;
624 break;
625
626 }
627 if(ioctl(pfdev, DIOCRDELADDRS, &table) < 0)
628 {
629 snprintf(msg, sizeof(msg) - 1, "Error: Can't Unblock ip %s (%s)", inettoa(bd->blockip), strerror(errno));
630 logmessage(1, msg, "pf", 0);
631 return;
632 }
633 } /* UNBLOCK */
634
635 close(pfdev);
636 return;
637 } /* PFBLOCK */
638
639 #endif /* __SSP_PF_C__ */
640
641 #endif /* OpenBSD || FreeBSD || NetBSD */
642 #endif /* USE_SSP_PF */
643
644