Deleted Added
full compact
ip_fw_pfil.c (227085) ip_fw_pfil.c (240099)
1/*-
2 * Copyright (c) 2004 Andre Oppermann, Internet Business Solutions AG
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

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

20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 */
26
27#include <sys/cdefs.h>
1/*-
2 * Copyright (c) 2004 Andre Oppermann, Internet Business Solutions AG
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

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

20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 */
26
27#include <sys/cdefs.h>
28__FBSDID("$FreeBSD: head/sys/netinet/ipfw/ip_fw_pfil.c 227085 2011-11-04 16:24:19Z bz $");
28__FBSDID("$FreeBSD: head/sys/netinet/ipfw/ip_fw_pfil.c 240099 2012-09-04 19:43:26Z melifaro $");
29
30#include "opt_ipfw.h"
31#include "opt_inet.h"
32#include "opt_inet6.h"
33#ifndef INET
34#error IPFIREWALL requires INET.
35#endif /* INET */
36

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

42#include <sys/kernel.h>
43#include <sys/lock.h>
44#include <sys/rwlock.h>
45#include <sys/socket.h>
46#include <sys/sysctl.h>
47
48#include <net/if.h>
49#include <net/route.h>
29
30#include "opt_ipfw.h"
31#include "opt_inet.h"
32#include "opt_inet6.h"
33#ifndef INET
34#error IPFIREWALL requires INET.
35#endif /* INET */
36

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

42#include <sys/kernel.h>
43#include <sys/lock.h>
44#include <sys/rwlock.h>
45#include <sys/socket.h>
46#include <sys/sysctl.h>
47
48#include <net/if.h>
49#include <net/route.h>
50#include <net/ethernet.h>
50#include <net/pfil.h>
51#include <net/vnet.h>
52
53#include <netinet/in.h>
54#include <netinet/in_systm.h>
55#include <netinet/ip.h>
56#include <netinet/ip_var.h>
57#include <netinet/ip_fw.h>

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

67static VNET_DEFINE(int, fw_enable) = 1;
68#define V_fw_enable VNET(fw_enable)
69
70#ifdef INET6
71static VNET_DEFINE(int, fw6_enable) = 1;
72#define V_fw6_enable VNET(fw6_enable)
73#endif
74
51#include <net/pfil.h>
52#include <net/vnet.h>
53
54#include <netinet/in.h>
55#include <netinet/in_systm.h>
56#include <netinet/ip.h>
57#include <netinet/ip_var.h>
58#include <netinet/ip_fw.h>

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

68static VNET_DEFINE(int, fw_enable) = 1;
69#define V_fw_enable VNET(fw_enable)
70
71#ifdef INET6
72static VNET_DEFINE(int, fw6_enable) = 1;
73#define V_fw6_enable VNET(fw6_enable)
74#endif
75
76static VNET_DEFINE(int, fwlink_enable) = 0;
77#define V_fwlink_enable VNET(fwlink_enable)
78
75int ipfw_chg_hook(SYSCTL_HANDLER_ARGS);
76
77/* Forward declarations. */
78static int ipfw_divert(struct mbuf **, int, struct ipfw_rule_ref *, int);
79int ipfw_chg_hook(SYSCTL_HANDLER_ARGS);
80
81/* Forward declarations. */
82static int ipfw_divert(struct mbuf **, int, struct ipfw_rule_ref *, int);
83static int ipfw_check_packet(void *, struct mbuf **, struct ifnet *, int,
84 struct inpcb *);
85static int ipfw_check_frame(void *, struct mbuf **, struct ifnet *, int,
86 struct inpcb *);
79
80#ifdef SYSCTL_NODE
81
82SYSBEGIN(f1)
83
84SYSCTL_DECL(_net_inet_ip_fw);
85SYSCTL_VNET_PROC(_net_inet_ip_fw, OID_AUTO, enable,
86 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_SECURE3, &VNET_NAME(fw_enable), 0,
87 ipfw_chg_hook, "I", "Enable ipfw");
88#ifdef INET6
89SYSCTL_DECL(_net_inet6_ip6_fw);
90SYSCTL_VNET_PROC(_net_inet6_ip6_fw, OID_AUTO, enable,
91 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_SECURE3, &VNET_NAME(fw6_enable), 0,
92 ipfw_chg_hook, "I", "Enable ipfw+6");
93#endif /* INET6 */
94
87
88#ifdef SYSCTL_NODE
89
90SYSBEGIN(f1)
91
92SYSCTL_DECL(_net_inet_ip_fw);
93SYSCTL_VNET_PROC(_net_inet_ip_fw, OID_AUTO, enable,
94 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_SECURE3, &VNET_NAME(fw_enable), 0,
95 ipfw_chg_hook, "I", "Enable ipfw");
96#ifdef INET6
97SYSCTL_DECL(_net_inet6_ip6_fw);
98SYSCTL_VNET_PROC(_net_inet6_ip6_fw, OID_AUTO, enable,
99 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_SECURE3, &VNET_NAME(fw6_enable), 0,
100 ipfw_chg_hook, "I", "Enable ipfw+6");
101#endif /* INET6 */
102
103SYSCTL_DECL(_net_link_ether);
104SYSCTL_VNET_PROC(_net_link_ether, OID_AUTO, ipfw,
105 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_SECURE3, &VNET_NAME(fwlink_enable), 0,
106 ipfw_chg_hook, "I", "Pass ether pkts through firewall");
107
95SYSEND
96
97#endif /* SYSCTL_NODE */
98
99/*
100 * The pfilter hook to pass packets to ipfw_chk and then to
101 * dummynet, divert, netgraph or other modules.
102 * The packet may be consumed.
103 */
108SYSEND
109
110#endif /* SYSCTL_NODE */
111
112/*
113 * The pfilter hook to pass packets to ipfw_chk and then to
114 * dummynet, divert, netgraph or other modules.
115 * The packet may be consumed.
116 */
104int
105ipfw_check_hook(void *arg, struct mbuf **m0, struct ifnet *ifp, int dir,
117static int
118ipfw_check_packet(void *arg, struct mbuf **m0, struct ifnet *ifp, int dir,
106 struct inpcb *inp)
107{
108 struct ip_fw_args args;
109 struct m_tag *tag;
110 int ipfw;
111 int ret;
112
113 /* all the processing now uses ip_len in net format */

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

273 FREE_PKT(*m0);
274 *m0 = NULL;
275 }
276 if (*m0 && mtod(*m0, struct ip *)->ip_v == 4)
277 SET_HOST_IPLEN(mtod(*m0, struct ip *));
278 return ret;
279}
280
119 struct inpcb *inp)
120{
121 struct ip_fw_args args;
122 struct m_tag *tag;
123 int ipfw;
124 int ret;
125
126 /* all the processing now uses ip_len in net format */

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

286 FREE_PKT(*m0);
287 *m0 = NULL;
288 }
289 if (*m0 && mtod(*m0, struct ip *)->ip_v == 4)
290 SET_HOST_IPLEN(mtod(*m0, struct ip *));
291 return ret;
292}
293
294/*
295 * ipfw processing for ethernet packets (in and out).
296 * Inteface is NULL from ether_demux, and ifp from
297 * ether_output_frame.
298 */
299static int
300ipfw_check_frame(void *arg, struct mbuf **m0, struct ifnet *dst, int dir,
301 struct inpcb *inp)
302{
303 struct ether_header *eh;
304 struct ether_header save_eh;
305 struct mbuf *m;
306 int i, ret;
307 struct ip_fw_args args;
308 struct m_tag *mtag;
309
310 /* fetch start point from rule, if any */
311 mtag = m_tag_locate(*m0, MTAG_IPFW_RULE, 0, NULL);
312 if (mtag == NULL) {
313 args.rule.slot = 0;
314 } else {
315 /* dummynet packet, already partially processed */
316 struct ipfw_rule_ref *r;
317
318 /* XXX can we free it after use ? */
319 mtag->m_tag_id = PACKET_TAG_NONE;
320 r = (struct ipfw_rule_ref *)(mtag + 1);
321 if (r->info & IPFW_ONEPASS)
322 return (0);
323 args.rule = *r;
324 }
325
326 /* I need some amt of data to be contiguous */
327 m = *m0;
328 i = min(m->m_pkthdr.len, max_protohdr);
329 if (m->m_len < i) {
330 m = m_pullup(m, i);
331 if (m == NULL) {
332 *m0 = m;
333 return (0);
334 }
335 }
336 eh = mtod(m, struct ether_header *);
337 save_eh = *eh; /* save copy for restore below */
338 m_adj(m, ETHER_HDR_LEN); /* strip ethernet header */
339
340 args.m = m; /* the packet we are looking at */
341 args.oif = dst; /* destination, if any */
342 args.next_hop = NULL; /* we do not support forward yet */
343 args.next_hop6 = NULL; /* we do not support forward yet */
344 args.eh = &save_eh; /* MAC header for bridged/MAC packets */
345 args.inp = NULL; /* used by ipfw uid/gid/jail rules */
346 i = ipfw_chk(&args);
347 m = args.m;
348 if (m != NULL) {
349 /*
350 * Restore Ethernet header, as needed, in case the
351 * mbuf chain was replaced by ipfw.
352 */
353 M_PREPEND(m, ETHER_HDR_LEN, M_DONTWAIT);
354 if (m == NULL) {
355 *m0 = NULL;
356 return (0);
357 }
358 if (eh != mtod(m, struct ether_header *))
359 bcopy(&save_eh, mtod(m, struct ether_header *),
360 ETHER_HDR_LEN);
361 }
362 *m0 = m;
363
364 ret = 0;
365 /* Check result of ipfw_chk() */
366 switch (i) {
367 case IP_FW_PASS:
368 break;
369
370 case IP_FW_DENY:
371 ret = EACCES;
372 break; /* i.e. drop */
373
374 case IP_FW_DUMMYNET:
375 ret = EACCES;
376 int dir;
377
378 if (ip_dn_io_ptr == NULL)
379 break; /* i.e. drop */
380
381 *m0 = NULL;
382 dir = PROTO_LAYER2 | (dst ? DIR_OUT : DIR_IN);
383 ip_dn_io_ptr(&m, dir, &args);
384 return 0;
385
386 default:
387 KASSERT(0, ("%s: unknown retval", __func__));
388 }
389
390 if (ret != 0) {
391 if (*m0)
392 FREE_PKT(*m0);
393 *m0 = NULL;
394 }
395
396 return ret;
397}
398
281/* do the divert, return 1 on error 0 on success */
282static int
283ipfw_divert(struct mbuf **m0, int incoming, struct ipfw_rule_ref *rule,
284 int tee)
285{
286 /*
287 * ipfw_chk() has already tagged the packet with the divert tag.
288 * If tee is set, copy packet and return original.

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

374
375/*
376 * attach or detach hooks for a given protocol family
377 */
378static int
379ipfw_hook(int onoff, int pf)
380{
381 struct pfil_head *pfh;
399/* do the divert, return 1 on error 0 on success */
400static int
401ipfw_divert(struct mbuf **m0, int incoming, struct ipfw_rule_ref *rule,
402 int tee)
403{
404 /*
405 * ipfw_chk() has already tagged the packet with the divert tag.
406 * If tee is set, copy packet and return original.

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

492
493/*
494 * attach or detach hooks for a given protocol family
495 */
496static int
497ipfw_hook(int onoff, int pf)
498{
499 struct pfil_head *pfh;
500 void *hook_func;
382
383 pfh = pfil_head_get(PFIL_TYPE_AF, pf);
384 if (pfh == NULL)
385 return ENOENT;
386
501
502 pfh = pfil_head_get(PFIL_TYPE_AF, pf);
503 if (pfh == NULL)
504 return ENOENT;
505
506 hook_func = (pf == AF_LINK) ? ipfw_check_frame : ipfw_check_packet;
507
387 (void) (onoff ? pfil_add_hook : pfil_remove_hook)
508 (void) (onoff ? pfil_add_hook : pfil_remove_hook)
388 (ipfw_check_hook, NULL, PFIL_IN | PFIL_OUT | PFIL_WAITOK, pfh);
509 (hook_func, NULL, PFIL_IN | PFIL_OUT | PFIL_WAITOK, pfh);
389
390 return 0;
391}
392
393int
394ipfw_attach_hooks(int arg)
395{
396 int error = 0;

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

404#ifdef INET6
405 if (arg == 0) /* detach */
406 ipfw_hook(0, AF_INET6);
407 else if (V_fw6_enable && ipfw_hook(1, AF_INET6) != 0) {
408 error = ENOENT;
409 printf("ipfw6_hook() error\n");
410 }
411#endif
510
511 return 0;
512}
513
514int
515ipfw_attach_hooks(int arg)
516{
517 int error = 0;

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

525#ifdef INET6
526 if (arg == 0) /* detach */
527 ipfw_hook(0, AF_INET6);
528 else if (V_fw6_enable && ipfw_hook(1, AF_INET6) != 0) {
529 error = ENOENT;
530 printf("ipfw6_hook() error\n");
531 }
532#endif
533 if (arg == 0) /* detach */
534 ipfw_hook(0, AF_LINK);
535 else if (V_fwlink_enable && ipfw_hook(1, AF_LINK) != 0) {
536 error = ENOENT;
537 printf("ipfw_link_hook() error\n");
538 }
412 return error;
413}
414
415int
416ipfw_chg_hook(SYSCTL_HANDLER_ARGS)
417{
539 return error;
540}
541
542int
543ipfw_chg_hook(SYSCTL_HANDLER_ARGS)
544{
418 int enable;
419 int oldenable;
545 int *enable;
546 int newval;
420 int error;
421 int af;
422
423 if (arg1 == &VNET_NAME(fw_enable)) {
547 int error;
548 int af;
549
550 if (arg1 == &VNET_NAME(fw_enable)) {
424 enable = V_fw_enable;
551 enable = &V_fw_enable;
425 af = AF_INET;
426 }
427#ifdef INET6
428 else if (arg1 == &VNET_NAME(fw6_enable)) {
552 af = AF_INET;
553 }
554#ifdef INET6
555 else if (arg1 == &VNET_NAME(fw6_enable)) {
429 enable = V_fw6_enable;
556 enable = &V_fw6_enable;
430 af = AF_INET6;
431 }
432#endif
557 af = AF_INET6;
558 }
559#endif
560 else if (arg1 == &VNET_NAME(fwlink_enable)) {
561 enable = &V_fwlink_enable;
562 af = AF_LINK;
563 }
433 else
434 return (EINVAL);
435
564 else
565 return (EINVAL);
566
436 oldenable = enable;
567 newval = *enable;
437
568
438 error = sysctl_handle_int(oidp, &enable, 0, req);
569 /* Handle sysctl change */
570 error = sysctl_handle_int(oidp, &newval, 0, req);
439
440 if (error)
441 return (error);
442
571
572 if (error)
573 return (error);
574
443 enable = (enable) ? 1 : 0;
575 /* Formalize new value */
576 newval = (newval) ? 1 : 0;
444
577
445 if (enable == oldenable)
578 if (*enable == newval)
446 return (0);
447
579 return (0);
580
448 error = ipfw_hook(enable, af);
581 error = ipfw_hook(newval, af);
449 if (error)
450 return (error);
582 if (error)
583 return (error);
451 if (af == AF_INET)
452 V_fw_enable = enable;
453#ifdef INET6
454 else if (af == AF_INET6)
455 V_fw6_enable = enable;
456#endif
584 *enable = newval;
457
458 return (0);
459}
460/* end of file */
585
586 return (0);
587}
588/* end of file */