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