xref: /dragonfly/sys/net/ipfw3_basic/ip_fw3_basic.c (revision d844908498ae4df842725aa2750f57900989799f)
1 /*
2  * Copyright (c) 2014 - 2018 The DragonFly Project.  All rights reserved.
3  *
4  * This code is derived from software contributed to The DragonFly Project
5  * by Bill Yuan <bycn82@dragonflybsd.org>
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  *
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in
15  *    the documentation and/or other materials provided with the
16  *    distribution.
17  * 3. Neither the name of The DragonFly Project nor the names of its
18  *    contributors may be used to endorse or promote products derived
19  *    from this software without specific, prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
25  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26  * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
27  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
31  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32  * SUCH DAMAGE.
33  */
34 
35 #include "opt_ipfw.h"
36 #include "opt_inet.h"
37 #ifndef INET
38 #error IPFIREWALL3 requires INET.
39 #endif /* INET */
40 
41 #include <sys/param.h>
42 #include <sys/kernel.h>
43 #include <sys/malloc.h>
44 #include <sys/mbuf.h>
45 #include <sys/socketvar.h>
46 #include <sys/sysctl.h>
47 #include <sys/systimer.h>
48 #include <sys/in_cksum.h>
49 #include <sys/systm.h>
50 #include <sys/proc.h>
51 #include <sys/socket.h>
52 #include <sys/syslog.h>
53 #include <sys/ucred.h>
54 #include <sys/lock.h>
55 #include <sys/tree.h>
56 
57 #include <net/if.h>
58 #include <net/ethernet.h>
59 #include <net/netmsg2.h>
60 #include <net/netisr2.h>
61 #include <net/route.h>
62 
63 #include <netinet/ip.h>
64 #include <netinet/in.h>
65 #include <netinet/in_systm.h>
66 #include <netinet/in_var.h>
67 #include <netinet/in_pcb.h>
68 #include <netinet/ip_var.h>
69 #include <netinet/ip_icmp.h>
70 #include <netinet/tcp.h>
71 #include <netinet/tcp_timer.h>
72 #include <netinet/tcp_var.h>
73 #include <netinet/tcpip.h>
74 #include <netinet/udp.h>
75 #include <netinet/udp_var.h>
76 #include <netinet/ip_divert.h>
77 #include <netinet/if_ether.h>
78 
79 #include <net/ipfw3/ip_fw.h>
80 #include <net/ipfw3_basic/ip_fw3_table.h>
81 #include <net/ipfw3_basic/ip_fw3_sync.h>
82 #include <net/ipfw3_basic/ip_fw3_basic.h>
83 #include <net/ipfw3_basic/ip_fw3_state.h>
84 
85 extern struct ipfw3_context             *fw3_ctx[MAXCPU];
86 extern struct ipfw3_sync_context        fw3_sync_ctx;
87 extern struct ipfw3_state_context       *fw3_state_ctx[MAXCPU];
88 extern ip_fw_ctl_t                      *ipfw_ctl_basic_ptr;
89 
90 extern int                                        sysctl_var_fw3_verbose;
91 
92 extern int                              sysctl_var_state_max_tcp_in;
93 extern int                              sysctl_var_state_max_udp_in;
94 extern int                              sysctl_var_state_max_icmp_in;
95 
96 extern int                              sysctl_var_state_max_tcp_out;
97 extern int                              sysctl_var_state_max_udp_out;
98 extern int                              sysctl_var_state_max_icmp_out;
99 
100 extern int                              sysctl_var_icmp_timeout;
101 extern int                              sysctl_var_tcp_timeout;
102 extern int                              sysctl_var_udp_timeout;
103 
104 static struct ip_fw *
lookup_next_rule(struct ip_fw * me)105 lookup_next_rule(struct ip_fw *me)
106 {
107           struct ip_fw *rule = NULL;
108           ipfw_insn *cmd;
109 
110           /* look for action, in case it is a skipto */
111           cmd = ACTION_PTR(me);
112           if ((int)cmd->module == MODULE_BASIC_ID &&
113                     (int)cmd->opcode == O_BASIC_SKIPTO) {
114                     for (rule = me->next; rule; rule = rule->next) {
115                               if (rule->rulenum >= cmd->arg1)
116                                         break;
117                     }
118           }
119           if (rule == NULL) /* failure or not a skipto */
120                     rule = me->next;
121 
122           me->next_rule = rule;
123           return rule;
124 }
125 
126 
127 static int
iface_match(struct ifnet * ifp,ipfw_insn_if * cmd)128 iface_match(struct ifnet *ifp, ipfw_insn_if *cmd)
129 {
130           if (ifp == NULL)    /* no iface with this packet, match fails */
131                     return 0;
132 
133           /* Check by name or by IP address */
134           if (cmd->name[0] != '\0') { /* match by name */
135                     /* Check name */
136                     if (cmd->p.glob) {
137                               if (kfnmatch(cmd->name, ifp->if_xname, 0) == 0)
138                                         return(1);
139                     } else {
140                               if (strncmp(ifp->if_xname, cmd->name, IFNAMSIZ) == 0)
141                                         return(1);
142                     }
143           } else {
144                     struct ifaddr_container *ifac;
145 
146                     TAILQ_FOREACH(ifac, &ifp->if_addrheads[mycpuid], ifa_link) {
147                               struct ifaddr *ia = ifac->ifa;
148 
149                               if (ia->ifa_addr == NULL)
150                                         continue;
151                               if (ia->ifa_addr->sa_family != AF_INET)
152                                         continue;
153                               if (cmd->p.ip.s_addr ==
154                                         ((struct sockaddr_in *)
155                                         (ia->ifa_addr))->sin_addr.s_addr)
156                                                   return(1);          /* match */
157 
158                     }
159           }
160           return 0; /* no match, fail ... */
161 }
162 
163 /* implimentation of the checker functions */
164 void
check_count(int * cmd_ctl,int * cmd_val,struct ip_fw_args ** args,struct ip_fw ** f,ipfw_insn * cmd,uint16_t ip_len)165 check_count(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args,
166           struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len)
167 {
168           (*f)->pcnt++;
169           (*f)->bcnt += ip_len;
170           (*f)->timestamp = time_second;
171           *cmd_ctl = IP_FW_CTL_NEXT;
172 }
173 
174 void
check_skipto(int * cmd_ctl,int * cmd_val,struct ip_fw_args ** args,struct ip_fw ** f,ipfw_insn * cmd,uint16_t ip_len)175 check_skipto(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args,
176           struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len)
177 {
178           (*f)->pcnt++;
179           (*f)->bcnt += ip_len;
180           (*f)->timestamp = time_second;
181           if ((*f)->next_rule == NULL)
182                     lookup_next_rule(*f);
183           *f = (*f)->next_rule;
184           *cmd_ctl = IP_FW_CTL_AGAIN;
185 }
186 
187 void
check_forward(int * cmd_ctl,int * cmd_val,struct ip_fw_args ** args,struct ip_fw ** f,ipfw_insn * cmd,uint16_t ip_len)188 check_forward(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args,
189           struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len)
190 {
191           struct sockaddr_in *sin, *sa;
192           struct m_tag *mtag;
193 
194           if ((*args)->eh) {  /* not valid on layer2 pkts */
195                     *cmd_ctl=IP_FW_CTL_NEXT;
196                     return;
197           }
198 
199           (*f)->pcnt++;
200           (*f)->bcnt += ip_len;
201           (*f)->timestamp = time_second;
202           if ((*f)->next_rule == NULL)
203                     lookup_next_rule(*f);
204 
205           mtag = m_tag_get(PACKET_TAG_IPFORWARD,
206                               sizeof(*sin), M_INTWAIT | M_NULLOK);
207           if (mtag == NULL) {
208                     *cmd_val = IP_FW_DENY;
209                     *cmd_ctl = IP_FW_CTL_DONE;
210                     return;
211           }
212           sin = m_tag_data(mtag);
213           sa = &((ipfw_insn_sa *)cmd)->sa;
214           /* arg3: count of the dest, arg1: type of fwd */
215           int i = 0;
216           if(cmd->arg3 > 1) {
217                     if (cmd->arg1 == 0) {                   /* type: random */
218                               i = krandom() % cmd->arg3;
219                     } else if (cmd->arg1 == 1) {  /* type: round-robin */
220                               i = cmd->arg2++ % cmd->arg3;
221                     } else if (cmd->arg1 == 2) {  /* type: sticky */
222                               struct ip *ip = mtod((*args)->m, struct ip *);
223                               i = ip->ip_src.s_addr & (cmd->arg3 - 1);
224                     }
225                     sa += i;
226           }
227           *sin = *sa;         /* apply the destination */
228           m_tag_prepend((*args)->m, mtag);
229           (*args)->m->m_pkthdr.fw_flags |= IPFORWARD_MBUF_TAGGED;
230           (*args)->m->m_pkthdr.fw_flags &= ~BRIDGE_MBUF_TAGGED;
231           *cmd_ctl = IP_FW_CTL_DONE;
232           *cmd_val = IP_FW_PASS;
233 }
234 
235 void
check_in(int * cmd_ctl,int * cmd_val,struct ip_fw_args ** args,struct ip_fw ** f,ipfw_insn * cmd,uint16_t ip_len)236 check_in(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args,
237           struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len)
238 {
239           *cmd_ctl = IP_FW_CTL_NO;
240           *cmd_val = ((*args)->oif == NULL);
241 }
242 
243 void
check_out(int * cmd_ctl,int * cmd_val,struct ip_fw_args ** args,struct ip_fw ** f,ipfw_insn * cmd,uint16_t ip_len)244 check_out(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args,
245           struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len)
246 {
247           *cmd_ctl = IP_FW_CTL_NO;
248           *cmd_val = ((*args)->oif != NULL);
249 }
250 
251 void
check_via(int * cmd_ctl,int * cmd_val,struct ip_fw_args ** args,struct ip_fw ** f,ipfw_insn * cmd,uint16_t ip_len)252 check_via(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args,
253           struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len)
254 {
255           *cmd_ctl = IP_FW_CTL_NO;
256           *cmd_val = iface_match((*args)->oif ?
257                               (*args)->oif : (*args)->m->m_pkthdr.rcvif,
258                               (ipfw_insn_if *)cmd);
259 }
260 
261 void
check_proto(int * cmd_ctl,int * cmd_val,struct ip_fw_args ** args,struct ip_fw ** f,ipfw_insn * cmd,uint16_t ip_len)262 check_proto(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args,
263           struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len)
264 {
265           *cmd_ctl = IP_FW_CTL_NO;
266           *cmd_val = ((*args)->f_id.proto == cmd->arg1);
267 }
268 
269 void
check_prob(int * cmd_ctl,int * cmd_val,struct ip_fw_args ** args,struct ip_fw ** f,ipfw_insn * cmd,uint16_t ip_len)270 check_prob(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args,
271           struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len)
272 {
273           *cmd_ctl = IP_FW_CTL_NO;
274           *cmd_val = (krandom() % 100) < cmd->arg1;
275 }
276 
277 void
check_from(int * cmd_ctl,int * cmd_val,struct ip_fw_args ** args,struct ip_fw ** f,ipfw_insn * cmd,uint16_t ip_len)278 check_from(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args,
279           struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len)
280 {
281           u_int hlen = 0;
282           struct mbuf *m = (*args)->m;
283           struct ip *ip = mtod(m, struct ip *);
284           struct in_addr src_ip = ip->ip_src;
285 
286           if ((*args)->eh == NULL ||
287                     (m->m_pkthdr.len >= sizeof(struct ip) &&
288                     ntohs((*args)->eh->ether_type) == ETHERTYPE_IP)) {
289                     hlen = ip->ip_hl << 2;
290           }
291           *cmd_val = (hlen > 0 &&
292                               ((ipfw_insn_ip *)cmd)->addr.s_addr == src_ip.s_addr);
293           *cmd_ctl = IP_FW_CTL_NO;
294 }
295 
296 void
check_from_lookup(int * cmd_ctl,int * cmd_val,struct ip_fw_args ** args,struct ip_fw ** f,ipfw_insn * cmd,uint16_t ip_len)297 check_from_lookup(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args,
298           struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len)
299 {
300           struct ipfw3_context *ctx = fw3_ctx[mycpuid];
301           struct ipfw3_table_context *table_ctx;
302           struct radix_node_head *rnh;
303           struct sockaddr_in sa;
304 
305           struct mbuf *m = (*args)->m;
306           struct ip *ip = mtod(m, struct ip *);
307           struct in_addr src_ip = ip->ip_src;
308 
309           *cmd_val = IP_FW_NOT_MATCH;
310 
311           table_ctx = ctx->table_ctx;
312           table_ctx += cmd->arg1;
313 
314         if (table_ctx->type != 0) {
315                 rnh = table_ctx->node;
316                 sa.sin_len = 8;
317                 sa.sin_addr.s_addr = src_ip.s_addr;
318                 if (rnh->rnh_lookup(&sa, NULL, rnh) != NULL)
319                         *cmd_val = IP_FW_MATCH;
320         }
321           *cmd_ctl = IP_FW_CTL_NO;
322 }
323 
324 void
check_from_me(int * cmd_ctl,int * cmd_val,struct ip_fw_args ** args,struct ip_fw ** f,ipfw_insn * cmd,uint16_t ip_len)325 check_from_me(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args,
326           struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len)
327 {
328           u_int hlen = 0;
329           struct mbuf *m = (*args)->m;
330           struct ip *ip = mtod(m, struct ip *);
331           struct in_addr src_ip = ip->ip_src;
332 
333           if ((*args)->eh == NULL ||
334                     (m->m_pkthdr.len >= sizeof(struct ip) &&
335                     ntohs((*args)->eh->ether_type) == ETHERTYPE_IP)) {
336                     hlen = ip->ip_hl << 2;
337           }
338           *cmd_ctl = IP_FW_CTL_NO;
339           if (hlen > 0) {
340                     struct ifnet *tif;
341                     tif = INADDR_TO_IFP(&src_ip);
342                     *cmd_val = (tif != NULL);
343           } else {
344                     *cmd_val = IP_FW_NOT_MATCH;
345           }
346 }
347 
348 void
check_from_mask(int * cmd_ctl,int * cmd_val,struct ip_fw_args ** args,struct ip_fw ** f,ipfw_insn * cmd,uint16_t ip_len)349 check_from_mask(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args,
350           struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len)
351 {
352           u_int hlen = 0;
353           struct mbuf *m = (*args)->m;
354           struct ip *ip = mtod(m, struct ip *);
355           struct in_addr src_ip = ip->ip_src;
356 
357           if ((*args)->eh == NULL ||
358                     (m->m_pkthdr.len >= sizeof(struct ip) &&
359                     ntohs((*args)->eh->ether_type) == ETHERTYPE_IP)) {
360                     hlen = ip->ip_hl << 2;
361           }
362 
363           *cmd_ctl = IP_FW_CTL_NO;
364           *cmd_val = (hlen > 0 &&
365                               ((ipfw_insn_ip *)cmd)->addr.s_addr ==
366                               (src_ip.s_addr &
367                               ((ipfw_insn_ip *)cmd)->mask.s_addr));
368 }
369 
370 void
check_to(int * cmd_ctl,int * cmd_val,struct ip_fw_args ** args,struct ip_fw ** f,ipfw_insn * cmd,uint16_t ip_len)371 check_to(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args,
372           struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len)
373 {
374           u_int hlen = 0;
375           struct mbuf *m = (*args)->m;
376           struct ip *ip = mtod(m, struct ip *);
377           struct in_addr dst_ip = ip->ip_dst;
378 
379           if ((*args)->eh == NULL ||
380                     (m->m_pkthdr.len >= sizeof(struct ip) &&
381                      ntohs((*args)->eh->ether_type) == ETHERTYPE_IP)) {
382                     hlen = ip->ip_hl << 2;
383           }
384           *cmd_val = (hlen > 0 &&
385                               ((ipfw_insn_ip *)cmd)->addr.s_addr == dst_ip.s_addr);
386           *cmd_ctl = IP_FW_CTL_NO;
387 }
388 
389 void
check_to_lookup(int * cmd_ctl,int * cmd_val,struct ip_fw_args ** args,struct ip_fw ** f,ipfw_insn * cmd,uint16_t ip_len)390 check_to_lookup(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args,
391           struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len)
392 {
393           struct ipfw3_context *ctx = fw3_ctx[mycpuid];
394           struct ipfw3_table_context *table_ctx;
395           struct radix_node_head *rnh;
396           struct sockaddr_in sa;
397 
398           struct mbuf *m = (*args)->m;
399           struct ip *ip = mtod(m, struct ip *);
400           struct in_addr dst_ip = ip->ip_dst;
401 
402           *cmd_val = IP_FW_NOT_MATCH;
403 
404           table_ctx = ctx->table_ctx;
405           table_ctx += cmd->arg1;
406 
407         if (table_ctx->type != 0) {
408                 rnh = table_ctx->node;
409                 sa.sin_len = 8;
410                 sa.sin_addr.s_addr = dst_ip.s_addr;
411                 if (rnh->rnh_lookup(&sa, NULL, rnh) != NULL)
412                         *cmd_val = IP_FW_MATCH;
413         }
414           *cmd_ctl = IP_FW_CTL_NO;
415 }
416 
417 void
check_to_me(int * cmd_ctl,int * cmd_val,struct ip_fw_args ** args,struct ip_fw ** f,ipfw_insn * cmd,uint16_t ip_len)418 check_to_me(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args,
419           struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len)
420 {
421           u_int hlen = 0;
422           struct mbuf *m = (*args)->m;
423           struct ip *ip = mtod(m, struct ip *);
424           struct in_addr dst_ip = ip->ip_dst;
425 
426           if ((*args)->eh == NULL ||
427                     (m->m_pkthdr.len >= sizeof(struct ip) &&
428                     ntohs((*args)->eh->ether_type) == ETHERTYPE_IP)) {
429                     hlen = ip->ip_hl << 2;
430           }
431           *cmd_ctl = IP_FW_CTL_NO;
432           if (hlen > 0) {
433                     struct ifnet *tif;
434                     tif = INADDR_TO_IFP(&dst_ip);
435                     *cmd_val = (tif != NULL);
436           } else {
437                     *cmd_val = IP_FW_NOT_MATCH;
438           }
439 }
440 
441 void
check_to_mask(int * cmd_ctl,int * cmd_val,struct ip_fw_args ** args,struct ip_fw ** f,ipfw_insn * cmd,uint16_t ip_len)442 check_to_mask(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args,
443           struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len)
444 {
445           u_int hlen = 0;
446           struct mbuf *m = (*args)->m;
447           struct ip *ip = mtod(m, struct ip *);
448           struct in_addr dst_ip = ip->ip_dst;
449 
450           if ((*args)->eh == NULL ||
451                     (m->m_pkthdr.len >= sizeof(struct ip) &&
452                     ntohs((*args)->eh->ether_type) == ETHERTYPE_IP)) {
453                     hlen = ip->ip_hl << 2;
454           }
455 
456           *cmd_ctl = IP_FW_CTL_NO;
457           *cmd_val = (hlen > 0 &&
458                               ((ipfw_insn_ip *)cmd)->addr.s_addr ==
459                               (dst_ip.s_addr &
460                               ((ipfw_insn_ip *)cmd)->mask.s_addr));
461 }
462 
463 void
check_tag(int * cmd_ctl,int * cmd_val,struct ip_fw_args ** args,struct ip_fw ** f,ipfw_insn * cmd,uint16_t ip_len)464 check_tag(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args,
465           struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len)
466 {
467           struct m_tag *mtag = m_tag_locate((*args)->m,
468                               MTAG_IPFW, cmd->arg1, NULL);
469           if (mtag == NULL) {
470                     mtag = m_tag_alloc(MTAG_IPFW,cmd->arg1, 0, M_NOWAIT);
471                     if (mtag != NULL)
472                               m_tag_prepend((*args)->m, mtag);
473 
474           }
475           (*f)->pcnt++;
476           (*f)->bcnt += ip_len;
477           (*f)->timestamp = time_second;
478           *cmd_ctl = IP_FW_CTL_NEXT;
479 }
480 
481 void
check_untag(int * cmd_ctl,int * cmd_val,struct ip_fw_args ** args,struct ip_fw ** f,ipfw_insn * cmd,uint16_t ip_len)482 check_untag(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args,
483           struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len)
484 {
485           struct m_tag *mtag = m_tag_locate((*args)->m,
486                               MTAG_IPFW, cmd->arg1, NULL);
487           if (mtag != NULL)
488                     m_tag_delete((*args)->m, mtag);
489 
490           (*f)->pcnt++;
491           (*f)->bcnt += ip_len;
492           (*f)->timestamp = time_second;
493           *cmd_ctl = IP_FW_CTL_NEXT;
494 }
495 
496 void
check_tagged(int * cmd_ctl,int * cmd_val,struct ip_fw_args ** args,struct ip_fw ** f,ipfw_insn * cmd,uint16_t ip_len)497 check_tagged(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args,
498           struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len)
499 {
500           *cmd_ctl = IP_FW_CTL_NO;
501           if (m_tag_locate( (*args)->m, MTAG_IPFW,cmd->arg1, NULL) != NULL )
502                     *cmd_val = IP_FW_MATCH;
503           else
504                     *cmd_val = IP_FW_NOT_MATCH;
505 }
506 
507 void
check_src_port(int * cmd_ctl,int * cmd_val,struct ip_fw_args ** args,struct ip_fw ** f,ipfw_insn * cmd,uint16_t ip_len)508 check_src_port(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args,
509         struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len)
510 {
511         *cmd_ctl = IP_FW_CTL_NO;
512         if ((*args)->f_id.src_port == cmd->arg1)
513                 *cmd_val = IP_FW_MATCH;
514         else
515                 *cmd_val = IP_FW_NOT_MATCH;
516 }
517 
518 void
check_dst_port(int * cmd_ctl,int * cmd_val,struct ip_fw_args ** args,struct ip_fw ** f,ipfw_insn * cmd,uint16_t ip_len)519 check_dst_port(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args,
520         struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len)
521 {
522         *cmd_ctl = IP_FW_CTL_NO;
523         if ((*args)->f_id.dst_port == cmd->arg1)
524                 *cmd_val = IP_FW_MATCH;
525         else
526                 *cmd_val = IP_FW_NOT_MATCH;
527 }
528 
529 void
check_src_n_port(int * cmd_ctl,int * cmd_val,struct ip_fw_args ** args,struct ip_fw ** f,ipfw_insn * cmd,uint16_t ip_len)530 check_src_n_port(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args,
531           struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len)
532 {
533           struct in_addr src_ip;
534           u_int hlen = 0;
535           struct mbuf *m = (*args)->m;
536           struct ip *ip = mtod(m, struct ip *);
537           src_ip = ip->ip_src;
538           if ((*args)->eh == NULL ||
539                     (m->m_pkthdr.len >= sizeof(struct ip) &&
540                     ntohs((*args)->eh->ether_type) == ETHERTYPE_IP)) {
541                     hlen = ip->ip_hl << 2;
542           }
543           *cmd_val = (hlen > 0 && ((ipfw_insn_ip *)cmd)->addr.s_addr == src_ip.s_addr);
544           *cmd_ctl = IP_FW_CTL_NO;
545           if (*cmd_val && (*args)->f_id.src_port == cmd->arg1)
546                     *cmd_val = IP_FW_MATCH;
547           else
548                     *cmd_val = IP_FW_NOT_MATCH;
549 }
550 
551 void
check_dst_n_port(int * cmd_ctl,int * cmd_val,struct ip_fw_args ** args,struct ip_fw ** f,ipfw_insn * cmd,uint16_t ip_len)552 check_dst_n_port(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args,
553           struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len)
554 {
555           struct in_addr dst_ip;
556           u_int hlen = 0;
557           struct mbuf *m = (*args)->m;
558           struct ip *ip = mtod(m, struct ip *);
559           dst_ip = ip->ip_dst;
560           if ((*args)->eh == NULL ||
561                     (m->m_pkthdr.len >= sizeof(struct ip) &&
562                      ntohs((*args)->eh->ether_type) == ETHERTYPE_IP)) {
563                     hlen = ip->ip_hl << 2;
564           }
565           *cmd_val = (hlen > 0 && ((ipfw_insn_ip *)cmd)->addr.s_addr == dst_ip.s_addr);
566           *cmd_ctl = IP_FW_CTL_NO;
567           if (*cmd_val && (*args)->f_id.dst_port == cmd->arg1)
568                     *cmd_val = IP_FW_MATCH;
569           else
570                     *cmd_val = IP_FW_NOT_MATCH;
571 }
572 
573 int
ip_fw3_basic_init(void)574 ip_fw3_basic_init(void)
575 {
576           ip_fw3_register_module(MODULE_BASIC_ID, MODULE_BASIC_NAME);
577           ip_fw3_register_filter_funcs(MODULE_BASIC_ID, O_BASIC_COUNT,
578                               (filter_func)check_count);
579           ip_fw3_register_filter_funcs(MODULE_BASIC_ID, O_BASIC_SKIPTO,
580                               (filter_func)check_skipto);
581           ip_fw3_register_filter_funcs(MODULE_BASIC_ID, O_BASIC_FORWARD,
582                               (filter_func)check_forward);
583           ip_fw3_register_filter_funcs(MODULE_BASIC_ID, O_BASIC_KEEP_STATE,
584                               (filter_func)check_keep_state);
585           ip_fw3_register_filter_funcs(MODULE_BASIC_ID, O_BASIC_CHECK_STATE,
586                               (filter_func)check_check_state);
587 
588           ip_fw3_register_filter_funcs(MODULE_BASIC_ID,
589                               O_BASIC_IN, (filter_func)check_in);
590           ip_fw3_register_filter_funcs(MODULE_BASIC_ID,
591                               O_BASIC_OUT, (filter_func)check_out);
592           ip_fw3_register_filter_funcs(MODULE_BASIC_ID,
593                               O_BASIC_VIA, (filter_func)check_via);
594           ip_fw3_register_filter_funcs(MODULE_BASIC_ID,
595                               O_BASIC_XMIT, (filter_func)check_via);
596           ip_fw3_register_filter_funcs(MODULE_BASIC_ID,
597                               O_BASIC_RECV, (filter_func)check_via);
598 
599           ip_fw3_register_filter_funcs(MODULE_BASIC_ID,
600                               O_BASIC_PROTO, (filter_func)check_proto);
601           ip_fw3_register_filter_funcs(MODULE_BASIC_ID,
602                               O_BASIC_PROB, (filter_func)check_prob);
603           ip_fw3_register_filter_funcs(MODULE_BASIC_ID,
604                               O_BASIC_IP_SRC, (filter_func)check_from);
605           ip_fw3_register_filter_funcs(MODULE_BASIC_ID,
606                               O_BASIC_IP_SRC_LOOKUP, (filter_func)check_from_lookup);
607           ip_fw3_register_filter_funcs(MODULE_BASIC_ID,
608                               O_BASIC_IP_SRC_ME, (filter_func)check_from_me);
609           ip_fw3_register_filter_funcs(MODULE_BASIC_ID,
610                               O_BASIC_IP_SRC_MASK, (filter_func)check_from_mask);
611           ip_fw3_register_filter_funcs(MODULE_BASIC_ID,
612                               O_BASIC_IP_DST, (filter_func)check_to);
613           ip_fw3_register_filter_funcs(MODULE_BASIC_ID,
614                               O_BASIC_IP_DST_LOOKUP, (filter_func)check_to_lookup);
615           ip_fw3_register_filter_funcs(MODULE_BASIC_ID,
616                               O_BASIC_IP_DST_ME, (filter_func)check_to_me);
617           ip_fw3_register_filter_funcs(MODULE_BASIC_ID,
618                               O_BASIC_IP_DST_MASK, (filter_func)check_to_mask);
619           ip_fw3_register_filter_funcs(MODULE_BASIC_ID,
620                               O_BASIC_TAG, (filter_func)check_tag);
621           ip_fw3_register_filter_funcs(MODULE_BASIC_ID,
622                               O_BASIC_UNTAG, (filter_func)check_untag);
623           ip_fw3_register_filter_funcs(MODULE_BASIC_ID,
624                               O_BASIC_TAGGED, (filter_func)check_tagged);
625           ip_fw3_register_filter_funcs(MODULE_BASIC_ID,
626                               O_BASIC_IP_SRCPORT, (filter_func)check_src_port);
627           ip_fw3_register_filter_funcs(MODULE_BASIC_ID,
628                               O_BASIC_IP_DSTPORT, (filter_func)check_dst_port);
629           ip_fw3_register_filter_funcs(MODULE_BASIC_ID,
630                               O_BASIC_IP_SRC_N_PORT, (filter_func)check_src_n_port);
631           ip_fw3_register_filter_funcs(MODULE_BASIC_ID,
632                               O_BASIC_IP_DST_N_PORT, (filter_func)check_dst_n_port);
633 
634           return 0;
635 }
636 
637 int
ip_fw3_basic_fini(void)638 ip_fw3_basic_fini(void)
639 {
640           return ip_fw3_unregister_module(MODULE_BASIC_ID);
641 }
642 
643 static int
ipfw3_basic_modevent(module_t mod,int type,void * data)644 ipfw3_basic_modevent(module_t mod, int type, void *data)
645 {
646           int err;
647           switch (type) {
648                     case MOD_LOAD:
649                               err = ip_fw3_basic_init();
650                               break;
651                     case MOD_UNLOAD:
652                               err = ip_fw3_basic_fini();
653                               break;
654                     default:
655                               err = 1;
656           }
657           ip_fw3_state_modevent(type);
658           ip_fw3_table_modevent(type);
659           return err;
660 }
661 
662 static moduledata_t ipfw3_basic_mod = {
663           "ipfw3_basic",
664           ipfw3_basic_modevent,
665           NULL
666 };
667 DECLARE_MODULE(ipfw3_basic, ipfw3_basic_mod, SI_SUB_PROTO_END, SI_ORDER_ANY);
668 MODULE_DEPEND(ipfw3_basic, ipfw3, 1, 1, 1);
669 MODULE_VERSION(ipfw3_basic, 1);
670