diff options
-rw-r--r-- | sys/net/if_bridge.c | 12 | ||||
-rw-r--r-- | sys/net/if_ethersubr.c | 15 | ||||
-rw-r--r-- | sys/netgraph/ng_ipfw.c | 6 | ||||
-rw-r--r-- | sys/netgraph/ng_ipfw.h | 26 | ||||
-rw-r--r-- | sys/netinet/in.h | 26 | ||||
-rw-r--r-- | sys/netinet/ip_dummynet.h | 31 | ||||
-rw-r--r-- | sys/netinet/ipfw/ip_dummynet.c | 52 | ||||
-rw-r--r-- | sys/netinet/ipfw/ip_fw2.c | 87 | ||||
-rw-r--r-- | sys/netinet/ipfw/ip_fw_dynamic.c | 4 | ||||
-rw-r--r-- | sys/netinet/ipfw/ip_fw_log.c | 27 | ||||
-rw-r--r-- | sys/netinet/ipfw/ip_fw_nat.c | 16 | ||||
-rw-r--r-- | sys/netinet/ipfw/ip_fw_pfil.c | 475 | ||||
-rw-r--r-- | sys/netinet/ipfw/ip_fw_private.h | 56 | ||||
-rw-r--r-- | sys/netinet/ipfw/ip_fw_sockopt.c | 2 |
14 files changed, 342 insertions, 493 deletions
diff --git a/sys/net/if_bridge.c b/sys/net/if_bridge.c index b380ef0..d0d2242 100644 --- a/sys/net/if_bridge.c +++ b/sys/net/if_bridge.c @@ -3041,13 +3041,17 @@ bridge_pfil(struct mbuf **mp, struct ifnet *bifp, struct ifnet *ifp, int dir) /* XXX this section is also in if_ethersubr.c */ if (V_ip_fw_chk_ptr && pfil_ipfw != 0 && dir == PFIL_OUT && ifp != NULL) { - struct dn_pkt_tag *dn_tag; + struct m_tag *mtag; error = -1; - dn_tag = ip_dn_claim_tag(*mp); - if (dn_tag == NULL) { + mtag = m_tag_find(*mp, PACKET_TAG_DUMMYNET, NULL); + if (mtag == NULL) { args.slot = 0; } else { + struct dn_pkt_tag *dn_tag; + + mtag->m_tag_id = PACKET_TAG_NONE; + dn_tag = (struct dn_pkt_tag *)(mtag + 1); if (dn_tag->slot != 0 && V_fw_one_pass) /* packet already partially processed */ goto ipfwpass; @@ -3081,7 +3085,7 @@ bridge_pfil(struct mbuf **mp, struct ifnet *bifp, struct ifnet *ifp, int dir) * packet will return to us via bridge_dummynet(). */ args.oif = ifp; - ip_dn_io_ptr(mp, DN_TO_IFB_FWD, &args); + ip_dn_io_ptr(mp, DIR_FWD | PROTO_IFB, &args); return (error); } diff --git a/sys/net/if_ethersubr.c b/sys/net/if_ethersubr.c index 95554ca..5fd53e8 100644 --- a/sys/net/if_ethersubr.c +++ b/sys/net/if_ethersubr.c @@ -467,13 +467,16 @@ ether_ipfw_chk(struct mbuf **m0, struct ifnet *dst, int shared) struct mbuf *m; int i; struct ip_fw_args args; - struct dn_pkt_tag *dn_tag; + struct m_tag *mtag; - dn_tag = ip_dn_claim_tag(*m0); - - if (dn_tag == NULL) { + mtag = m_tag_find(*m0, PACKET_TAG_DUMMYNET, NULL); + if (mtag == NULL) { args.slot = 0; } else { + struct dn_pkt_tag *dn_tag; + + mtag->m_tag_id = PACKET_TAG_NONE; + dn_tag = (struct dn_pkt_tag *)(mtag + 1); if (dn_tag->slot != 0 && V_fw_one_pass) /* dummynet packet, already partially processed */ return (1); @@ -532,6 +535,7 @@ ether_ipfw_chk(struct mbuf **m0, struct ifnet *dst, int shared) return 1; if (ip_dn_io_ptr && (i == IP_FW_DUMMYNET)) { + int dir; /* * Pass the pkt to dummynet, which consumes it. * If shared, make a copy and keep the original. @@ -547,7 +551,8 @@ ether_ipfw_chk(struct mbuf **m0, struct ifnet *dst, int shared) */ *m0 = NULL ; } - ip_dn_io_ptr(&m, dst ? DN_TO_ETH_OUT: DN_TO_ETH_DEMUX, &args); + dir = PROTO_LAYER2 | (dst ? DIR_OUT : DIR_IN); + ip_dn_io_ptr(&m, dir, &args); return 0; } /* diff --git a/sys/netgraph/ng_ipfw.c b/sys/netgraph/ng_ipfw.c index 974f48f..c02ca75 100644 --- a/sys/netgraph/ng_ipfw.c +++ b/sys/netgraph/ng_ipfw.c @@ -234,7 +234,7 @@ ng_ipfw_rcvdata(hook_p hook, item_p item) }; switch (ngit->dir) { - case NG_IPFW_OUT: + case DIR_OUT: { struct ip *ip; @@ -249,7 +249,7 @@ ng_ipfw_rcvdata(hook_p hook, item_p item) return ip_output(m, NULL, NULL, IP_FORWARDING, NULL, NULL); } - case NG_IPFW_IN: + case DIR_IN: ip_input(m); return (0); default: @@ -298,7 +298,7 @@ ng_ipfw_input(struct mbuf **m0, int dir, struct ip_fw_args *fwa, int tee) ngit->rule_id = fwa->rule_id; ngit->chain_id = fwa->chain_id; ngit->dir = dir; - ngit->ifp = fwa->oif; +// ngit->ifp = fwa->oif; /* XXX do we use it ? */ m_tag_prepend(m, &ngit->mt); } else diff --git a/sys/netgraph/ng_ipfw.h b/sys/netgraph/ng_ipfw.h index 9fb4cf7..c463d6a 100644 --- a/sys/netgraph/ng_ipfw.h +++ b/sys/netgraph/ng_ipfw.h @@ -26,27 +26,7 @@ * $FreeBSD$ */ +#ifndef _NG_IPFW_H +#define _NG_IPFW_H #define NG_IPFW_NODE_TYPE "ipfw" -#define NGM_IPFW_COOKIE 1105988990 - -#ifdef _KERNEL - -typedef int ng_ipfw_input_t(struct mbuf **, int, struct ip_fw_args *, int); -extern ng_ipfw_input_t *ng_ipfw_input_p; -#define NG_IPFW_LOADED (ng_ipfw_input_p != NULL) - -struct ng_ipfw_tag { - struct m_tag mt; /* tag header */ - uint32_t slot; /* slot for next rule */ - uint32_t rulenum; /* matching rule number */ - uint32_t rule_id; /* matching rule id */ - uint32_t chain_id; /* ruleset id */ - struct ifnet *ifp; /* interface, for ip_output */ - int dir; -#define NG_IPFW_OUT 0 -#define NG_IPFW_IN 1 -}; - -#define TAGSIZ (sizeof(struct ng_ipfw_tag) - sizeof(struct m_tag)) - -#endif /* _KERNEL */ +#endif /* _NG_IPFW_H */ diff --git a/sys/netinet/in.h b/sys/netinet/in.h index e83d94b..4f47658 100644 --- a/sys/netinet/in.h +++ b/sys/netinet/in.h @@ -734,6 +734,32 @@ void in_ifdetach(struct ifnet *); #define sintosa(sin) ((struct sockaddr *)(sin)) #define ifatoia(ifa) ((struct in_ifaddr *)(ifa)) +/* + * Historically, BSD keeps ip_len and ip_off in host format + * when doing layer 3 processing, and this often requires + * to translate the format back and forth. + * To make the process explicit, we define a couple of macros + * that also take into account the fact that at some point + * we may want to keep those fields always in net format. + */ + +#if (BYTE_ORDER == BIG_ENDIAN) || defined(HAVE_NET_IPLEN) +#define SET_NET_IPLEN(p) do {} while (0) +#define SET_HOST_IPLEN(p) do {} while (0) +#else +#define SET_NET_IPLEN(p) do { \ + struct ip *h_ip = (p); \ + h_ip->ip_len = htons(h_ip->ip_len); \ + h_ip->ip_off = htons(h_ip->ip_off); \ + } while (0) + +#define SET_HOST_IPLEN(p) do { \ + struct ip *h_ip = (p); \ + h_ip->ip_len = ntohs(h_ip->ip_len); \ + h_ip->ip_off = ntohs(h_ip->ip_off); \ + } while (0) +#endif /* !HAVE_NET_IPLEN */ + #endif /* _KERNEL */ /* INET6 stuff */ diff --git a/sys/netinet/ip_dummynet.h b/sys/netinet/ip_dummynet.h index 9d5223f..4d039ee 100644 --- a/sys/netinet/ip_dummynet.h +++ b/sys/netinet/ip_dummynet.h @@ -110,21 +110,19 @@ struct dn_heap { * them that carries their dummynet state. This is used within * the dummynet code as well as outside when checking for special * processing requirements. + * Note that the first part is the reinject info and is common to + * other forms of packet reinjection. */ struct dn_pkt_tag { + /* first part, reinject info */ uint32_t slot; /* slot of next rule to use */ uint32_t rulenum; /* matching rule number */ uint32_t rule_id; /* matching rule id */ uint32_t chain_id; /* ruleset id */ + + /* second part, dummynet specific */ int dn_dir; /* action when packet comes out. */ -#define DN_TO_IP_OUT 1 -#define DN_TO_IP_IN 2 -/* Obsolete: #define DN_TO_BDG_FWD 3 */ -#define DN_TO_ETH_DEMUX 4 -#define DN_TO_ETH_OUT 5 -#define DN_TO_IP6_IN 6 -#define DN_TO_IP6_OUT 7 -#define DN_TO_IFB_FWD 8 + /* see ip_fw_private.h */ dn_key output_time; /* when the pkt is due for delivery */ struct ifnet *ifp; /* interface, for ip_output */ @@ -377,21 +375,4 @@ struct dn_pipe_max { SLIST_HEAD(dn_pipe_head, dn_pipe); -#ifdef _KERNEL - -/* - * Return the dummynet tag; if any. - * Make sure that the dummynet tag is not reused by lower layers. - */ -static __inline struct dn_pkt_tag * -ip_dn_claim_tag(struct mbuf *m) -{ - struct m_tag *mtag = m_tag_find(m, PACKET_TAG_DUMMYNET, NULL); - if (mtag != NULL) { - mtag->m_tag_id = PACKET_TAG_NONE; - return ((struct dn_pkt_tag *)(mtag + 1)); - } else - return (NULL); -} -#endif #endif /* _IP_DUMMYNET_H */ diff --git a/sys/netinet/ipfw/ip_dummynet.c b/sys/netinet/ipfw/ip_dummynet.c index 2b9b928..2142751 100644 --- a/sys/netinet/ipfw/ip_dummynet.c +++ b/sys/netinet/ipfw/ip_dummynet.c @@ -551,7 +551,6 @@ transmit_event(struct dn_pipe *pipe, struct mbuf **head, struct mbuf **tail) } #define div64(a, b) ((int64_t)(a) / (int64_t)(b)) -#define DN_TO_DROP 0xffff /* * Compute how many ticks we have to wait before being able to send * a packet. This is computed as the "wire time" for the packet @@ -589,7 +588,7 @@ compute_extra_bits(struct mbuf *pkt, struct dn_pipe *p) if (index >= p->loss_level) { struct dn_pkt_tag *dt = dn_tag_get(pkt); if (dt) - dt->dn_dir = DN_TO_DROP; + dt->dn_dir = DIR_DROP; } return extra_bits; } @@ -964,49 +963,48 @@ dummynet_task(void *context, int pending) static void dummynet_send(struct mbuf *m) { - struct dn_pkt_tag *pkt; struct mbuf *n; - struct ip *ip; - int dst; for (; m != NULL; m = n) { + struct ifnet *ifp; + int dst; + n = m->m_nextpkt; m->m_nextpkt = NULL; if (m_tag_first(m) == NULL) { - pkt = NULL; /* probably unnecessary */ - dst = DN_TO_DROP; + dst = DIR_DROP; } else { - pkt = dn_tag_get(m); + struct dn_pkt_tag *pkt = dn_tag_get(m); dst = pkt->dn_dir; + ifp = pkt->ifp; } switch (dst) { - case DN_TO_IP_OUT: + case DIR_OUT: ip_output(m, NULL, NULL, IP_FORWARDING, NULL, NULL); break ; - case DN_TO_IP_IN : - ip = mtod(m, struct ip *); - ip->ip_len = htons(ip->ip_len); - ip->ip_off = htons(ip->ip_off); + case DIR_IN : + /* put header in network format for ip_input() */ + SET_NET_IPLEN(mtod(m, struct ip *)); netisr_dispatch(NETISR_IP, m); break; #ifdef INET6 - case DN_TO_IP6_IN: + case DIR_IN | PROTO_IPV6: netisr_dispatch(NETISR_IPV6, m); break; - case DN_TO_IP6_OUT: + case DIR_OUT | PROTO_IPV6: ip6_output(m, NULL, NULL, IPV6_FORWARDING, NULL, NULL, NULL); break; #endif - case DN_TO_IFB_FWD: + case DIR_FWD | PROTO_IFB: /* DN_TO_IFB_FWD: */ if (bridge_dn_p != NULL) - ((*bridge_dn_p)(m, pkt->ifp)); + ((*bridge_dn_p)(m, ifp)); else printf("dummynet: if_bridge not loaded\n"); break; - case DN_TO_ETH_DEMUX: + case DIR_IN | PROTO_LAYER2: /* DN_TO_ETH_DEMUX: */ /* * The Ethernet code assumes the Ethernet header is * contiguous in the first mbuf header. @@ -1020,17 +1018,17 @@ dummynet_send(struct mbuf *m) } ether_demux(m->m_pkthdr.rcvif, m); break; - case DN_TO_ETH_OUT: - ether_output_frame(pkt->ifp, m); + case DIR_OUT | PROTO_LAYER2: /* N_TO_ETH_OUT: */ + ether_output_frame(ifp, m); break; - case DN_TO_DROP: + case DIR_DROP: /* drop the packet after some time */ dn_free_pkt(m); break; default: - printf("dummynet: bad switch %d!\n", pkt->dn_dir); + printf("dummynet: bad switch %d!\n", dst); dn_free_pkt(m); break; } @@ -1545,8 +1543,8 @@ dummynet_io(struct mbuf **m0, int dir, struct ip_fw_args *fwa) } } done: - if (head == m && dir != DN_TO_IFB_FWD && dir != DN_TO_ETH_DEMUX && - dir != DN_TO_ETH_OUT) { /* Fast io. */ + if (head == m && (dir & PROTO_LAYER2) == 0 ) { + /* Fast io. */ io_pkt_fast++; if (m->m_nextpkt != NULL) printf("dummynet: fast io: pkt chain detected!\n"); @@ -1810,13 +1808,15 @@ config_pipe(struct dn_pipe *p) pipe->idle_heap.size = pipe->idle_heap.elements = 0; pipe->idle_heap.offset = offsetof(struct dn_flow_queue, heap_pos); - } else + } else { /* Flush accumulated credit for all queues. */ - for (i = 0; i <= pipe->fs.rq_size; i++) + for (i = 0; i <= pipe->fs.rq_size; i++) { for (q = pipe->fs.rq[i]; q; q = q->next) { q->numbytes = p->burst + (io_fast ? p->bandwidth : 0); } + } + } pipe->bandwidth = p->bandwidth; pipe->burst = p->burst; diff --git a/sys/netinet/ipfw/ip_fw2.c b/sys/netinet/ipfw/ip_fw2.c index 719ed6c..bf10214 100644 --- a/sys/netinet/ipfw/ip_fw2.c +++ b/sys/netinet/ipfw/ip_fw2.c @@ -75,7 +75,6 @@ __FBSDID("$FreeBSD$"); #include <netinet/ip_fw.h> #include <netinet/ipfw/ip_fw_private.h> #include <netinet/ip_divert.h> -#include <netinet/ip_dummynet.h> #include <netinet/ip_carp.h> #include <netinet/pim.h> #include <netinet/tcp_var.h> @@ -83,8 +82,6 @@ __FBSDID("$FreeBSD$"); #include <netinet/udp_var.h> #include <netinet/sctp.h> -#include <netgraph/ng_ipfw.h> - #include <netinet/ip6.h> #include <netinet/icmp6.h> #ifdef INET6 @@ -591,7 +588,7 @@ send_reject6(struct ip_fw_args *args, int code, u_int hlen, struct ip6_hdr *ip6) * sends a reject message, consuming the mbuf passed as an argument. */ static void -send_reject(struct ip_fw_args *args, int code, int ip_len, struct ip *ip) +send_reject(struct ip_fw_args *args, int code, int iplen, struct ip *ip) { #if 0 @@ -607,8 +604,7 @@ send_reject(struct ip_fw_args *args, int code, int ip_len, struct ip *ip) if (code != ICMP_REJECT_RST) { /* Send an ICMP unreach */ /* We need the IP header in host order for icmp_error(). */ if (args->eh != NULL) { - ip->ip_len = ntohs(ip->ip_len); - ip->ip_off = ntohs(ip->ip_off); + SET_HOST_IPLEN(ip); } icmp_error(args->m, ICMP_UNREACH, code, 0L, 0); } else if (args->f_id.proto == IPPROTO_TCP) { @@ -851,12 +847,12 @@ ipfw_chk(struct ip_fw_args *args) * src_ip, dst_ip ip addresses, in NETWORK format. * Only valid for IPv4 packets. */ - u_int8_t proto; - u_int16_t src_port = 0, dst_port = 0; /* NOTE: host format */ + uint8_t proto; + uint16_t src_port = 0, dst_port = 0; /* NOTE: host format */ struct in_addr src_ip, dst_ip; /* NOTE: network format */ - u_int16_t ip_len=0; + uint16_t iplen=0; int pktlen; - u_int16_t etype = 0; /* Host order stored ether type */ + uint16_t etype = 0; /* Host order stored ether type */ /* * dyn_dir = MATCH_UNKNOWN when rules unchecked, @@ -1094,14 +1090,17 @@ do { \ proto = ip->ip_p; src_ip = ip->ip_src; dst_ip = ip->ip_dst; - if (args->eh != NULL) { /* layer 2 packets are as on the wire */ - offset = ntohs(ip->ip_off) & IP_OFFMASK; - ip_len = ntohs(ip->ip_len); - } else { +#ifndef HAVE_NET_IPLEN + if (args->eh == NULL) { /* on l3 these are in host format */ offset = ip->ip_off & IP_OFFMASK; - ip_len = ip->ip_len; + iplen = ip->ip_len; + } else +#endif /* !HAVE_NET_IPLEN */ + { /* otherwise they are in net format */ + offset = ntohs(ip->ip_off) & IP_OFFMASK; + iplen = ntohs(ip->ip_len); } - pktlen = ip_len < pktlen ? ip_len : pktlen; + pktlen = iplen < pktlen ? iplen : pktlen; if (offset == 0) { switch (proto) { @@ -1144,6 +1143,7 @@ do { \ IPFW_RUNLOCK(chain); return (IP_FW_PASS); /* accept */ } + /* XXX divert should be handled same as other tags */ mtag = m_tag_find(m, PACKET_TAG_DIVERT, NULL); if (args->slot) { /* @@ -1355,27 +1355,29 @@ do { \ case O_IP_SRC_LOOKUP: case O_IP_DST_LOOKUP: if (is_ipv4) { - uint32_t a = + uint32_t key = (cmd->opcode == O_IP_DST_LOOKUP) ? dst_ip.s_addr : src_ip.s_addr; uint32_t v = 0; if (cmdlen > F_INSN_SIZE(ipfw_insn_u32)) { - /* generic lookup */ + /* generic lookup. The key must be + * in 32bit big-endian format. + */ v = ((ipfw_insn_u32 *)cmd)->d[1]; if (v == 0) - a = dst_ip.s_addr; + key = dst_ip.s_addr; else if (v == 1) - a = src_ip.s_addr; + key = src_ip.s_addr; else if (offset != 0) break; else if (proto != IPPROTO_TCP && proto != IPPROTO_UDP) break; else if (v == 2) - a = dst_port; + key = htonl(dst_port); else if (v == 3) - a = src_port; + key = htons(src_port); else if (v == 4 || v == 5) { check_uidgid( (ipfw_insn_u32 *)cmd, @@ -1384,14 +1386,15 @@ do { \ src_ip, src_port, &ucred_cache, &ucred_lookup, args->inp); if (v == 4 /* O_UID */) - a = ucred_cache->cr_uid; + key = ucred_cache->cr_uid; else if (v == 5 /* O_JAIL */) - a = ucred_cache->cr_prison->pr_id; + key = ucred_cache->cr_prison->pr_id; + key = htonl(key); } else break; } - match = ipfw_lookup_table(chain, cmd->arg1, a, - &v); + match = ipfw_lookup_table(chain, + cmd->arg1, key, &v); if (!match) break; if (cmdlen == F_INSN_SIZE(ipfw_insn_u32)) @@ -1514,7 +1517,7 @@ do { \ int i; if (cmd->opcode == O_IPLEN) - x = ip_len; + x = iplen; else if (cmd->opcode == O_IPTTL) x = ip->ip_ttl; else /* must be IPID */ @@ -1549,7 +1552,7 @@ do { \ int i; tcp = TCP(ulp); - x = ip_len - + x = iplen - ((ip->ip_hl + tcp->th_off) << 2); if (cmdlen == 1) { match = (cmd->arg1 == x); @@ -2022,7 +2025,7 @@ do { \ is_icmp_query(ICMP(ulp))) && !(m->m_flags & (M_BCAST|M_MCAST)) && !IN_MULTICAST(ntohl(dst_ip.s_addr))) { - send_reject(args, cmd->arg1, ip_len, ip); + send_reject(args, cmd->arg1, iplen, ip); m = args->m; } /* FALLTHROUGH */ @@ -2124,8 +2127,13 @@ do { \ f->bcnt += pktlen; l = 0; /* in any case exit inner loop */ - ip_off = (args->eh != NULL) ? - ntohs(ip->ip_off) : ip->ip_off; +#ifndef HAVE_NET_IPLEN + if (args->eh == NULL) + ip_off = ip->ip_off; + else +#endif /* !HAVE_NET_IPLEN */ + ip_off = ntohs(ip->ip_off); + /* if not fragmented, go to next rule */ if ((ip_off & (IP_MF | IP_OFFMASK)) == 0) break; @@ -2135,8 +2143,7 @@ do { \ * from layer2. */ if (args->eh != NULL) { - ip->ip_len = ntohs(ip->ip_len); - ip->ip_off = ntohs(ip->ip_off); + SET_HOST_IPLEN(ip); } args->m = m = ip_reass(m); @@ -2153,9 +2160,10 @@ do { \ ip = mtod(m, struct ip *); hlen = ip->ip_hl << 2; - /* revert len & off for layer2 pkts */ - if (args->eh != NULL) - ip->ip_len = htons(ip->ip_len); + /* revert len. & off to net format if needed */ + if (args->eh != NULL) { + SET_NET_IPLEN(ip); + } ip->ip_sum = 0; if (hlen == sizeof(struct ip)) ip->ip_sum = in_cksum_hdr(ip); @@ -2364,7 +2372,7 @@ vnet_ipfw_init(const void *unused) */ V_ip_fw_ctl_ptr = ipfw_ctl; V_ip_fw_chk_ptr = ipfw_chk; - error = ipfw_attach_hooks(); + error = ipfw_attach_hooks(1); return (error); } @@ -2384,10 +2392,7 @@ vnet_ipfw_uninit(const void *unused) * Then grab, release and grab again the WLOCK so we make * sure the update is propagated and nobody will be in. */ - ipfw_unhook(); -#ifdef INET6 - ipfw6_unhook(); -#endif + (void)ipfw_attach_hooks(0 /* detach */); V_ip_fw_chk_ptr = NULL; V_ip_fw_ctl_ptr = NULL; IPFW_UH_WLOCK(chain); diff --git a/sys/netinet/ipfw/ip_fw_dynamic.c b/sys/netinet/ipfw/ip_fw_dynamic.c index a5f24a7..70a0147 100644 --- a/sys/netinet/ipfw/ip_fw_dynamic.c +++ b/sys/netinet/ipfw/ip_fw_dynamic.c @@ -1002,7 +1002,11 @@ ipfw_send_pkt(struct mbuf *replyto, struct ipfw_flow_id *id, u_int32_t seq, h->ip_hl = sizeof(*h) >> 2; h->ip_tos = IPTOS_LOWDELAY; h->ip_off = 0; +#ifdef HAVE_NET_IPLEN /* XXX do we handle layer2 ? */ + h->ip_len = htons(len); +#else h->ip_len = len; +#endif h->ip_ttl = V_ip_defttl; h->ip_sum = 0; break; diff --git a/sys/netinet/ipfw/ip_fw_log.c b/sys/netinet/ipfw/ip_fw_log.c index e3515af..e2aa4d2 100644 --- a/sys/netinet/ipfw/ip_fw_log.c +++ b/sys/netinet/ipfw/ip_fw_log.c @@ -87,6 +87,12 @@ __FBSDID("$FreeBSD$"); #define SNPARGS(buf, len) buf + len, sizeof(buf) > len ? sizeof(buf) - len : 0 #define SNP(buf) buf, sizeof(buf) +#ifdef WITHOUT_BPF +void +ipfw_log_bpf(int onoff) +{ +} +#else /* !WITHOUT_BPF */ static struct ifnet *log_if; /* hook to attach to bpf */ /* we use this dummy function for all ifnet callbacks */ @@ -128,6 +134,7 @@ ipfw_log_bpf(int onoff) log_if = NULL; } } +#endif /* !WITHOUT_BPF */ /* * We enter here when we have a rule with O_LOG. @@ -138,12 +145,12 @@ ipfw_log(struct ip_fw *f, u_int hlen, struct ip_fw_args *args, struct mbuf *m, struct ifnet *oif, u_short offset, uint32_t tablearg, struct ip *ip) { - struct ether_header *eh = args->eh; char *action; int limit_reached = 0; char action2[40], proto[128], fragment[32]; if (V_fw_verbose == 0) { +#ifndef WITHOUT_BPF struct m_hdr mh; if (log_if == NULL || log_if->if_bpf == NULL) @@ -160,16 +167,15 @@ ipfw_log(struct ip_fw *f, u_int hlen, struct ip_fw_args *args, mh.mh_data = "DDDDDDSSSSSS\x08\x00"; if (args->f_id.addr_type == 4) { /* restore wire format */ - ip->ip_off = ntohs(ip->ip_off); - ip->ip_len = ntohs(ip->ip_len); + SET_NET_IPLEN(ip); } } BPF_MTAP(log_if, (struct mbuf *)&mh); if (args->eh == NULL && args->f_id.addr_type == 4) { /* restore host format */ - ip->ip_off = htons(ip->ip_off); - ip->ip_len = htons(ip->ip_len); + SET_HOST_IPLEN(ip); } +#endif /* !WITHOUT_BPF */ return; } /* the old 'log' function */ @@ -404,12 +410,15 @@ ipfw_log(struct ip_fw *f, u_int hlen, struct ip_fw_args *args, #endif { int ip_off, ip_len; - if (eh != NULL) { /* layer 2 packets are as on the wire */ - ip_off = ntohs(ip->ip_off); - ip_len = ntohs(ip->ip_len); - } else { +#ifndef HAVE_NET_IPLEN + if (args->eh == NULL) { ip_off = ip->ip_off; ip_len = ip->ip_len; + } else +#endif /* !HAVE_NET_IPLEN */ + { + ip_off = ntohs(ip->ip_off); + ip_len = ntohs(ip->ip_len); } if (ip_off & (IP_MF | IP_OFFMASK)) snprintf(SNPARGS(fragment, 0), diff --git a/sys/netinet/ipfw/ip_fw_nat.c b/sys/netinet/ipfw/ip_fw_nat.c index c0a8cb8..549d779 100644 --- a/sys/netinet/ipfw/ip_fw_nat.c +++ b/sys/netinet/ipfw/ip_fw_nat.c @@ -29,14 +29,11 @@ __FBSDID("$FreeBSD$"); #include <sys/param.h> #include <sys/systm.h> -#include <sys/condvar.h> #include <sys/eventhandler.h> #include <sys/malloc.h> #include <sys/kernel.h> #include <sys/lock.h> #include <sys/module.h> -#include <sys/priv.h> -#include <sys/proc.h> #include <sys/rwlock.h> #define IPFW_INTERNAL /* Access to protected data structures in ip_fw.h. */ @@ -223,8 +220,7 @@ ipfw_nat(struct ip_fw_args *args, struct cfg_nat *t, struct mbuf *m) } ip = mtod(mcl, struct ip *); if (args->eh == NULL) { - ip->ip_len = htons(ip->ip_len); - ip->ip_off = htons(ip->ip_off); + SET_NET_IPLEN(ip); } /* @@ -302,11 +298,11 @@ ipfw_nat(struct ip_fw_args *args, struct cfg_nat *t, struct mbuf *m) struct udphdr *uh; u_short cksum; - ip->ip_len = ntohs(ip->ip_len); + /* XXX check if ip_len can stay in net format */ cksum = in_pseudo( ip->ip_src.s_addr, ip->ip_dst.s_addr, - htons(ip->ip_p + ip->ip_len - (ip->ip_hl << 2)) + htons(ip->ip_p + ntohs(ip->ip_len) - (ip->ip_hl << 2)) ); switch (ip->ip_p) { @@ -333,14 +329,10 @@ ipfw_nat(struct ip_fw_args *args, struct cfg_nat *t, struct mbuf *m) in_delayed_cksum(mcl); mcl->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA; } - ip->ip_len = htons(ip->ip_len); } - if (args->eh == NULL) { - ip->ip_len = ntohs(ip->ip_len); - ip->ip_off = ntohs(ip->ip_off); + SET_HOST_IPLEN(ip); } - args->m = mcl; return (IP_FW_NAT); } diff --git a/sys/netinet/ipfw/ip_fw_pfil.c b/sys/netinet/ipfw/ip_fw_pfil.c index 35ee157..f59d341 100644 --- a/sys/netinet/ipfw/ip_fw_pfil.c +++ b/sys/netinet/ipfw/ip_fw_pfil.c @@ -46,9 +46,7 @@ __FBSDID("$FreeBSD$"); #include <sys/lock.h> #include <sys/rwlock.h> #include <sys/socket.h> -#include <sys/socketvar.h> #include <sys/sysctl.h> -#include <sys/ucred.h> #include <net/if.h> #include <net/route.h> @@ -64,8 +62,6 @@ __FBSDID("$FreeBSD$"); #include <netinet/ip_divert.h> #include <netinet/ip_dummynet.h> -#include <netgraph/ng_ipfw.h> - #include <machine/in_cksum.h> static VNET_DEFINE(int, fw_enable) = 1; @@ -85,9 +81,7 @@ ip_divert_packet_t *ip_divert_ptr = NULL; ng_ipfw_input_t *ng_ipfw_input_p = NULL; /* Forward declarations. */ -static int ipfw_divert(struct mbuf **, int, int); -#define DIV_DIR_IN 1 -#define DIV_DIR_OUT 0 +static void ipfw_divert(struct mbuf **, int, int); #ifdef SYSCTL_NODE SYSCTL_DECL(_net_inet_ip_fw); @@ -102,162 +96,32 @@ SYSCTL_VNET_PROC(_net_inet6_ip6_fw, OID_AUTO, enable, #endif /* INET6 */ #endif /* SYSCTL_NODE */ -int -ipfw_check_in(void *arg, struct mbuf **m0, struct ifnet *ifp, int dir, - struct inpcb *inp) -{ - struct ip_fw_args args; - struct ng_ipfw_tag *ng_tag; - struct m_tag *dn_tag; - int ipfw = 0; - int divert; - int tee; -#ifdef IPFIREWALL_FORWARD - struct m_tag *fwd_tag; -#endif - - KASSERT(dir == PFIL_IN, ("ipfw_check_in wrong direction!")); - - bzero(&args, sizeof(args)); - - ng_tag = (struct ng_ipfw_tag *)m_tag_locate(*m0, NGM_IPFW_COOKIE, 0, - NULL); - if (ng_tag != NULL) { - KASSERT(ng_tag->dir == NG_IPFW_IN, - ("ng_ipfw tag with wrong direction")); - args.slot = ng_tag->slot; - args.rulenum = ng_tag->rulenum; - args.rule_id = ng_tag->rule_id; - args.chain_id = ng_tag->chain_id; - m_tag_delete(*m0, (struct m_tag *)ng_tag); - } - -again: - dn_tag = m_tag_find(*m0, PACKET_TAG_DUMMYNET, NULL); - if (dn_tag != NULL){ - struct dn_pkt_tag *dt; - - dt = (struct dn_pkt_tag *)(dn_tag+1); - args.slot = dt->slot; - args.rulenum = dt->rulenum; - args.rule_id = dt->rule_id; - args.chain_id = dt->chain_id; - m_tag_delete(*m0, dn_tag); - } - - args.m = *m0; - args.inp = inp; - tee = 0; - - if (V_fw_one_pass == 0 || args.slot == 0) { - ipfw = ipfw_chk(&args); - *m0 = args.m; - } else - ipfw = IP_FW_PASS; - - KASSERT(*m0 != NULL || ipfw == IP_FW_DENY, ("%s: m0 is NULL", - __func__)); - - switch (ipfw) { - case IP_FW_PASS: - if (args.next_hop == NULL) - goto pass; - -#ifdef IPFIREWALL_FORWARD - fwd_tag = m_tag_get(PACKET_TAG_IPFORWARD, - sizeof(struct sockaddr_in), M_NOWAIT); - if (fwd_tag == NULL) - goto drop; - bcopy(args.next_hop, (fwd_tag+1), sizeof(struct sockaddr_in)); - m_tag_prepend(*m0, fwd_tag); - - if (in_localip(args.next_hop->sin_addr)) - (*m0)->m_flags |= M_FASTFWD_OURS; - goto pass; -#endif - break; /* not reached */ - - case IP_FW_DENY: - goto drop; - break; /* not reached */ - - case IP_FW_DUMMYNET: - if (ip_dn_io_ptr == NULL) - goto drop; - if (mtod(*m0, struct ip *)->ip_v == 4) - ip_dn_io_ptr(m0, DN_TO_IP_IN, &args); - else if (mtod(*m0, struct ip *)->ip_v == 6) - ip_dn_io_ptr(m0, DN_TO_IP6_IN, &args); - if (*m0 != NULL) - goto again; - return 0; /* packet consumed */ - - case IP_FW_TEE: - tee = 1; - /* fall through */ - - case IP_FW_DIVERT: - divert = ipfw_divert(m0, DIV_DIR_IN, tee); - if (divert) { - *m0 = NULL; - return 0; /* packet consumed */ - } else { - args.slot = 0; - goto again; /* continue with packet */ - } - - case IP_FW_NGTEE: - if (!NG_IPFW_LOADED) - goto drop; - (void)ng_ipfw_input_p(m0, NG_IPFW_IN, &args, 1); - goto again; /* continue with packet */ - - case IP_FW_NETGRAPH: - if (!NG_IPFW_LOADED) - goto drop; - return ng_ipfw_input_p(m0, NG_IPFW_IN, &args, 0); - - case IP_FW_NAT: - goto again; /* continue with packet */ - - case IP_FW_REASS: - goto again; - - default: - KASSERT(0, ("%s: unknown retval", __func__)); - } - -drop: - if (*m0) - m_freem(*m0); - *m0 = NULL; - return (EACCES); -pass: - return 0; /* not filtered */ -} - -int -ipfw_check_out(void *arg, struct mbuf **m0, struct ifnet *ifp, int dir, +/* + * The pfilter hook to pass packets to ipfw_chk and then to + * dummynet, divert, netgraph or other modules. + * The packet may be consumed. + */ +static int +ipfw_check_hook(void *arg, struct mbuf **m0, struct ifnet *ifp, int dir, struct inpcb *inp) { struct ip_fw_args args; struct ng_ipfw_tag *ng_tag; struct m_tag *dn_tag; - int ipfw = 0; - int divert; - int tee; + int ipfw; + int ret; #ifdef IPFIREWALL_FORWARD struct m_tag *fwd_tag; #endif - KASSERT(dir == PFIL_OUT, ("ipfw_check_out wrong direction!")); - + /* convert dir to IPFW values */ + dir = (dir == PFIL_IN) ? DIR_IN : DIR_OUT; bzero(&args, sizeof(args)); ng_tag = (struct ng_ipfw_tag *)m_tag_locate(*m0, NGM_IPFW_COOKIE, 0, NULL); if (ng_tag != NULL) { - KASSERT(ng_tag->dir == NG_IPFW_OUT, + KASSERT(ng_tag->dir == dir, ("ng_ipfw tag with wrong direction")); args.slot = ng_tag->slot; args.rulenum = ng_tag->rulenum; @@ -280,9 +144,8 @@ again: } args.m = *m0; - args.oif = ifp; + args.oif = dir == DIR_OUT ? ifp : NULL; args.inp = inp; - tee = 0; if (V_fw_one_pass == 0 || args.slot == 0) { ipfw = ipfw_chk(&args); @@ -293,255 +156,209 @@ again: KASSERT(*m0 != NULL || ipfw == IP_FW_DENY, ("%s: m0 is NULL", __func__)); + /* breaking out of the switch means drop */ + ret = 0; /* default return value for pass */ switch (ipfw) { case IP_FW_PASS: + /* next_hop may be set by ipfw_chk */ if (args.next_hop == NULL) - goto pass; -#ifdef IPFIREWALL_FORWARD - /* Overwrite existing tag. */ - fwd_tag = m_tag_find(*m0, PACKET_TAG_IPFORWARD, NULL); - if (fwd_tag == NULL) { + break; /* pass */ +#ifndef IPFIREWALL_FORWARD + ret = EACCES; +#else + /* Incoming packets should not be tagged so we do not + * m_tag_find. Outgoing packets may be tagged, so we + * reuse the tag if present. + */ + fwd_tag = (dir == DIR_IN) ? NULL : + m_tag_find(*m0, PACKET_TAG_IPFORWARD, NULL); + if (fwd_tag != NULL) { + m_tag_unlink(*m0, fwd_tag); + } else { fwd_tag = m_tag_get(PACKET_TAG_IPFORWARD, sizeof(struct sockaddr_in), M_NOWAIT); - if (fwd_tag == NULL) - goto drop; - } else - m_tag_unlink(*m0, fwd_tag); + if (fwd_tag == NULL) { + ret = EACCES; + break; /* i.e. drop */ + } + } bcopy(args.next_hop, (fwd_tag+1), sizeof(struct sockaddr_in)); m_tag_prepend(*m0, fwd_tag); if (in_localip(args.next_hop->sin_addr)) (*m0)->m_flags |= M_FASTFWD_OURS; - goto pass; #endif - break; /* not reached */ + break; case IP_FW_DENY: - goto drop; - break; /* not reached */ + ret = EACCES; + break; /* i.e. drop */ case IP_FW_DUMMYNET: + ret = EACCES; if (ip_dn_io_ptr == NULL) - break; + break; /* i.e. drop */ if (mtod(*m0, struct ip *)->ip_v == 4) - ip_dn_io_ptr(m0, DN_TO_IP_OUT, &args); + ret = ip_dn_io_ptr(m0, dir, &args); else if (mtod(*m0, struct ip *)->ip_v == 6) - ip_dn_io_ptr(m0, DN_TO_IP6_OUT, &args); + ret = ip_dn_io_ptr(m0, dir | PROTO_IPV6, &args); + else + break; /* drop it */ + /* + * XXX should read the return value. + * dummynet normally eats the packet and sets *m0=NULL + * unless the packet can be sent immediately. In this + * case args is updated and we should re-run the + * check without clearing args. + */ if (*m0 != NULL) goto again; - return 0; /* packet consumed */ - break; case IP_FW_TEE: - tee = 1; - /* fall through */ - case IP_FW_DIVERT: - divert = ipfw_divert(m0, DIV_DIR_OUT, tee); - if (divert) { - *m0 = NULL; - return 0; /* packet consumed */ - } else { + if (ip_divert_ptr == NULL) { + ret = EACCES; + break; /* i.e. drop */ + } + ipfw_divert(m0, dir, (ipfw == IP_FW_TEE) ? 1 : 0); + if (*m0) { + /* continue processing for this one. We set + * args.slot=0, but the divert tag is processed + * in ipfw_chk to jump to the right place. + */ args.slot = 0; goto again; /* continue with packet */ } + break; case IP_FW_NGTEE: - if (!NG_IPFW_LOADED) - goto drop; - (void)ng_ipfw_input_p(m0, NG_IPFW_OUT, &args, 1); - goto again; /* continue with packet */ - case IP_FW_NETGRAPH: - if (!NG_IPFW_LOADED) - goto drop; - return ng_ipfw_input_p(m0, NG_IPFW_OUT, &args, 0); + if (!NG_IPFW_LOADED) { + ret = EACCES; + break; /* i.e. drop */ + } + ret = ng_ipfw_input_p(m0, dir, &args, + (ipfw == IP_FW_NGTEE) ? 1 : 0); + if (ipfw == IP_FW_NGTEE) /* ignore errors for NGTEE */ + goto again; /* continue with packet */ + break; case IP_FW_NAT: - goto again; /* continue with packet */ - case IP_FW_REASS: - goto again; + goto again; /* continue with packet */ default: KASSERT(0, ("%s: unknown retval", __func__)); } -drop: - if (*m0) - m_freem(*m0); - *m0 = NULL; - return (EACCES); -pass: - return 0; /* not filtered */ + if (ret != 0) { + if (*m0) + m_freem(*m0); + *m0 = NULL; + } + return ret; } -static int -ipfw_divert(struct mbuf **m, int incoming, int tee) +static void +ipfw_divert(struct mbuf **m0, int incoming, int tee) { /* * ipfw_chk() has already tagged the packet with the divert tag. * If tee is set, copy packet and return original. * If not tee, consume packet and send it to divert socket. */ - struct mbuf *clone, *reass; + struct mbuf *clone; struct ip *ip; - int hlen; - - reass = NULL; - - /* Is divert module loaded? */ - if (ip_divert_ptr == NULL) - goto nodivert; /* Cloning needed for tee? */ - if (tee) - clone = m_dup(*m, M_DONTWAIT); - else - clone = *m; - - /* In case m_dup was unable to allocate mbufs. */ - if (clone == NULL) - goto teeout; + if (tee == 0) { + clone = *m0; /* use the original mbuf */ + *m0 = NULL; + } else { + clone = m_dup(*m0, M_DONTWAIT); + /* If we cannot duplicate the mbuf, we sacrifice the divert + * chain and continue with the tee-ed packet. + */ + if (clone == NULL) + return; + } /* - * Divert listeners can only handle non-fragmented packets. - * However when tee is set we will *not* de-fragment the packets; - * Doing do would put the reassembly into double-jeopardy. On top - * of that someone doing a tee will probably want to get the packet - * in its original form. + * Divert listeners can normally handle non-fragmented packets, + * but we can only reass in the non-tee case. + * This means that listeners on a tee rule may get fragments, + * and have to live with that. + * Note that we now have the 'reass' ipfw option so if we care + * we can do it before a 'tee'. */ ip = mtod(clone, struct ip *); if (!tee && ip->ip_off & (IP_MF | IP_OFFMASK)) { + int hlen; + struct mbuf *reass; - /* Reassemble packet. */ - reass = ip_reass(clone); - + reass = ip_reass(clone); /* Reassemble packet. */ + if (reass == NULL) + return; + /* if reass = NULL then it was consumed by ip_reass */ /* * IP header checksum fixup after reassembly and leave header * in network byte order. */ - if (reass != NULL) { - ip = mtod(reass, struct ip *); - hlen = ip->ip_hl << 2; - ip->ip_len = htons(ip->ip_len); - ip->ip_off = htons(ip->ip_off); - ip->ip_sum = 0; - if (hlen == sizeof(struct ip)) - ip->ip_sum = in_cksum_hdr(ip); - else - ip->ip_sum = in_cksum(reass, hlen); - clone = reass; - } else - clone = NULL; + ip = mtod(reass, struct ip *); + hlen = ip->ip_hl << 2; + SET_NET_IPLEN(ip); + ip->ip_sum = 0; + if (hlen == sizeof(struct ip)) + ip->ip_sum = in_cksum_hdr(ip); + else + ip->ip_sum = in_cksum(reass, hlen); + clone = reass; } else { /* Convert header to network byte order. */ - ip->ip_len = htons(ip->ip_len); - ip->ip_off = htons(ip->ip_off); + SET_NET_IPLEN(ip); } /* Do the dirty job... */ - if (clone && ip_divert_ptr != NULL) - ip_divert_ptr(clone, incoming); - -teeout: - /* - * For tee we leave the divert tag attached to original packet. - * It will then continue rule evaluation after the tee rule. - */ - if (tee) - return 0; - - /* Packet diverted and consumed */ - return 1; - -nodivert: - m_freem(*m); - return 1; -} - -static int -ipfw_hook(void) -{ - struct pfil_head *pfh_inet; - - pfh_inet = pfil_head_get(PFIL_TYPE_AF, AF_INET); - if (pfh_inet == NULL) - return ENOENT; - - (void)pfil_add_hook(ipfw_check_in, NULL, PFIL_IN | PFIL_WAITOK, - pfh_inet); - (void)pfil_add_hook(ipfw_check_out, NULL, PFIL_OUT | PFIL_WAITOK, - pfh_inet); - - return 0; -} - -int -ipfw_unhook(void) -{ - struct pfil_head *pfh_inet; - - pfh_inet = pfil_head_get(PFIL_TYPE_AF, AF_INET); - if (pfh_inet == NULL) - return ENOENT; - - (void)pfil_remove_hook(ipfw_check_in, NULL, PFIL_IN | PFIL_WAITOK, - pfh_inet); - (void)pfil_remove_hook(ipfw_check_out, NULL, PFIL_OUT | PFIL_WAITOK, - pfh_inet); - - return 0; + ip_divert_ptr(clone, incoming); } -#ifdef INET6 +/* + * attach or detach hooks for a given protocol family + */ static int -ipfw6_hook(void) -{ - struct pfil_head *pfh_inet6; - - pfh_inet6 = pfil_head_get(PFIL_TYPE_AF, AF_INET6); - if (pfh_inet6 == NULL) - return ENOENT; - - (void)pfil_add_hook(ipfw_check_in, NULL, PFIL_IN | PFIL_WAITOK, - pfh_inet6); - (void)pfil_add_hook(ipfw_check_out, NULL, PFIL_OUT | PFIL_WAITOK, - pfh_inet6); - - return 0; -} - -int -ipfw6_unhook(void) +ipfw_hook(int onoff, int pf) { - struct pfil_head *pfh_inet6; + const int arg = PFIL_IN | PFIL_OUT | PFIL_WAITOK; + struct pfil_head *pfh; - pfh_inet6 = pfil_head_get(PFIL_TYPE_AF, AF_INET6); - if (pfh_inet6 == NULL) + pfh = pfil_head_get(PFIL_TYPE_AF, pf); + if (pfh == NULL) return ENOENT; - (void)pfil_remove_hook(ipfw_check_in, NULL, PFIL_IN | PFIL_WAITOK, - pfh_inet6); - (void)pfil_remove_hook(ipfw_check_out, NULL, PFIL_OUT | PFIL_WAITOK, - pfh_inet6); + if (onoff) + (void)pfil_add_hook(ipfw_check_hook, NULL, arg, pfh); + else + (void)pfil_remove_hook(ipfw_check_hook, NULL, arg, pfh); return 0; } -#endif /* INET6 */ int -ipfw_attach_hooks(void) +ipfw_attach_hooks(int arg) { int error = 0; - if (V_fw_enable && ipfw_hook() != 0) { + if (arg == 0) /* detach */ + ipfw_hook(0, AF_INET); + else if (V_fw_enable && ipfw_hook(1, AF_INET) != 0) { error = ENOENT; /* see ip_fw_pfil.c::ipfw_hook() */ printf("ipfw_hook() error\n"); } #ifdef INET6 - if (V_fw6_enable && ipfw6_hook() != 0) { + if (arg == 0) /* detach */ + ipfw_hook(0, AF_INET6); + else if (V_fw6_enable && ipfw_hook(1, AF_INET6) != 0) { error = ENOENT; printf("ipfw6_hook() error\n"); } @@ -555,13 +372,16 @@ ipfw_chg_hook(SYSCTL_HANDLER_ARGS) int enable; int oldenable; int error; + int af; if (arg1 == &VNET_NAME(fw_enable)) { enable = V_fw_enable; + af = AF_INET; } #ifdef INET6 else if (arg1 == &VNET_NAME(fw6_enable)) { enable = V_fw6_enable; + af = AF_INET6; } #endif else @@ -579,25 +399,14 @@ ipfw_chg_hook(SYSCTL_HANDLER_ARGS) if (enable == oldenable) return (0); - if (arg1 == &VNET_NAME(fw_enable)) { - if (enable) - error = ipfw_hook(); - else - error = ipfw_unhook(); - if (error) - return (error); + error = ipfw_hook(enable, af); + if (error) + return (error); + if (af == AF_INET) V_fw_enable = enable; - } #ifdef INET6 - else if (arg1 == &VNET_NAME(fw6_enable)) { - if (enable) - error = ipfw6_hook(); - else - error = ipfw6_unhook(); - if (error) - return (error); + else if (af == AF_INET6) V_fw6_enable = enable; - } #endif return (0); diff --git a/sys/netinet/ipfw/ip_fw_private.h b/sys/netinet/ipfw/ip_fw_private.h index da5db8e..780d16e 100644 --- a/sys/netinet/ipfw/ip_fw_private.h +++ b/sys/netinet/ipfw/ip_fw_private.h @@ -101,19 +101,33 @@ struct ip_fw_args { MALLOC_DECLARE(M_IPFW); /* - * Function definitions. + * Hooks sometime need to know the direction of the packet + * (divert, dummynet, netgraph, ...) + * We use a generic definition here, with bit0-1 indicating the + * direction, bit 2 indicating layer2 or 3, bit 3-4 indicating the + * specific protocol + * indicating the protocol (if necessary) */ +enum { + DIR_MASK = 0x3, + DIR_OUT = 0, + DIR_IN = 1, + DIR_FWD = 2, + DIR_DROP = 3, + PROTO_LAYER2 = 0x4, /* set for layer 2 */ + /* PROTO_DEFAULT = 0, */ + PROTO_IPV4 = 0x08, + PROTO_IPV6 = 0x10, + PROTO_IFB = 0x0c, /* layer2 + ifbridge */ + /* PROTO_OLDBDG = 0x14, unused, old bridge */ +}; -/* Firewall hooks */ - -int ipfw_check_in(void *, struct mbuf **, struct ifnet *, - int, struct inpcb *inp); -int ipfw_check_out(void *, struct mbuf **, struct ifnet *, - int, struct inpcb *inp); +/* + * Function definitions. + */ -int ipfw_attach_hooks(void); -int ipfw_unhook(void); -int ipfw6_unhook(void); +/* attach (arg = 1) or detach (arg = 0) hooks */ +int ipfw_attach_hooks(int); #ifdef NOTYET void ipfw_nat_destroy(void); #endif @@ -257,5 +271,27 @@ extern ipfw_nat_cfg_t *ipfw_nat_del_ptr; extern ipfw_nat_cfg_t *ipfw_nat_get_cfg_ptr; extern ipfw_nat_cfg_t *ipfw_nat_get_log_ptr; +/* netgraph prototypes */ +#define NGM_IPFW_COOKIE 1105988990 + +typedef int ng_ipfw_input_t(struct mbuf **, int, struct ip_fw_args *, int); +extern ng_ipfw_input_t *ng_ipfw_input_p; +#define NG_IPFW_LOADED (ng_ipfw_input_p != NULL) + +struct ng_ipfw_tag { + struct m_tag mt; /* tag header */ + /* reinject info */ + uint32_t slot; /* slot for next rule */ + uint32_t rulenum; /* matching rule number */ + uint32_t rule_id; /* matching rule id */ + uint32_t chain_id; /* ruleset id */ + int dir; + +// struct ifnet *ifp; /* interface, for ip_output */ +}; + +#define TAGSIZ (sizeof(struct ng_ipfw_tag) - sizeof(struct m_tag)) + + #endif /* _KERNEL */ #endif /* _IPFW2_PRIVATE_H */ diff --git a/sys/netinet/ipfw/ip_fw_sockopt.c b/sys/netinet/ipfw/ip_fw_sockopt.c index e14952a..40d6ed7 100644 --- a/sys/netinet/ipfw/ip_fw_sockopt.c +++ b/sys/netinet/ipfw/ip_fw_sockopt.c @@ -67,8 +67,6 @@ __FBSDID("$FreeBSD$"); #include <netinet/ipfw/ip_fw_private.h> #include <netinet/ip_divert.h> -#include <netgraph/ng_ipfw.h> - #ifdef MAC #include <security/mac/mac_framework.h> #endif |