2 * Copyright (c) 2014 - 2018 The DragonFly Project. All rights reserved.
4 * This code is derived from software contributed to The DragonFly Project
5 * by Bill Yuan <bycn82@dragonflybsd.org>
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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
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.
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
38 #error IPFIREWALL3 requires INET.
41 #include <sys/param.h>
42 #include <sys/kernel.h>
43 #include <sys/malloc.h>
45 #include <sys/socketvar.h>
46 #include <sys/sysctl.h>
47 #include <sys/systimer.h>
48 #include <sys/thread2.h>
49 #include <sys/in_cksum.h>
50 #include <sys/systm.h>
52 #include <sys/socket.h>
53 #include <sys/syslog.h>
54 #include <sys/ucred.h>
56 #include <sys/mplock2.h>
58 #include <net/ethernet.h>
59 #include <net/netmsg2.h>
60 #include <net/netisr2.h>
61 #include <net/route.h>
64 #include <netinet/in.h>
65 #include <netinet/ip.h>
66 #include <netinet/ip_icmp.h>
67 #include <netinet/tcp.h>
68 #include <netinet/tcp_timer.h>
69 #include <netinet/tcp_var.h>
70 #include <netinet/tcpip.h>
71 #include <netinet/udp.h>
72 #include <netinet/udp_var.h>
73 #include <netinet/in_systm.h>
74 #include <netinet/in_var.h>
75 #include <netinet/in_pcb.h>
76 #include <netinet/ip_var.h>
77 #include <netinet/ip_divert.h>
78 #include <net/ipfw3/ip_fw.h>
81 #include "ip_fw3_set.h"
84 extern struct ipfw3_context
*fw3_ctx
[MAXCPU
];
87 move_set_dispatch(netmsg_t smsg
)
89 struct netmsg_sets
*msg
= (struct netmsg_sets
*)smsg
;
90 struct ipfw3_context
*ctx
= fw3_ctx
[mycpuid
];
92 for (rule
= ctx
->rules
; rule
; rule
= rule
->next
) {
93 if (rule
->set
== msg
->set_from
)
94 rule
->set
= msg
->set_to
;
96 netisr_forwardmsg_all(&smsg
->base
, mycpuid
+ 1);
100 ip_fw3_ctl_set_move_set(struct sockopt
*sopt
)
102 struct ipfw3_context
*ctx
;
103 struct netmsg_sets msg
;
106 ctx
= fw3_ctx
[mycpuid
];
107 set1
=(int *)sopt
->sopt_val
;
109 if (*set1
> 0 && *set1
< 32 && *set2
> 0 && *set2
< 32) {
110 bzero(&msg
, sizeof(msg
));
111 netmsg_init(&msg
.base
, NULL
, &curthread
->td_msgport
,
112 0, move_set_dispatch
);
113 msg
.set_from
= *set1
;
116 netisr_domsg(&msg
.base
, 0);
122 move_rule_dispatch(netmsg_t smsg
)
124 struct netmsg_sets
*msg
= (struct netmsg_sets
*)smsg
;
125 struct ipfw3_context
*ctx
= fw3_ctx
[mycpuid
];
127 for (rule
= ctx
->rules
; rule
; rule
= rule
->next
) {
128 if (rule
->rulenum
== msg
->rule_num
)
129 rule
->set
= msg
->set_to
;
131 netisr_forwardmsg_all(&smsg
->base
, mycpuid
+ 1);
135 ip_fw3_ctl_set_move_rule(struct sockopt
*sopt
)
137 struct ipfw3_context
*ctx
;
138 struct netmsg_sets msg
;
141 ctx
= fw3_ctx
[mycpuid
];
142 rule_num
=(int *)sopt
->sopt_val
;
144 if (*rule_num
> 0 && *rule_num
< 65535 && *set
>= 0 && *set
< 32) {
145 bzero(&msg
, sizeof(msg
));
146 netmsg_init(&msg
.base
, NULL
, &curthread
->td_msgport
,
147 0, move_rule_dispatch
);
148 msg
.rule_num
= *rule_num
;
150 netisr_domsg(&msg
.base
, 0);
156 set_swap_dispatch(netmsg_t smsg
)
158 struct netmsg_sets
*msg
= (struct netmsg_sets
*)smsg
;
159 struct ipfw3_context
*ctx
= fw3_ctx
[mycpuid
];
162 for (rule
= ctx
->rules
; rule
; rule
= rule
->next
) {
163 if (rule
->set
== msg
->set_from
)
164 rule
->set
= msg
->set_to
;
165 else if (rule
->set
== msg
->set_to
)
166 rule
->set
= msg
->set_from
;
168 netisr_forwardmsg_all(&smsg
->base
, mycpuid
+ 1);
172 ip_fw3_ctl_set_swap(struct sockopt
*sopt
)
174 struct ipfw3_context
*ctx
;
175 struct netmsg_sets msg
;
178 ctx
= fw3_ctx
[mycpuid
];
179 set1
=(int *)sopt
->sopt_val
;
181 if (*set1
> 0 && *set1
< 32 && *set2
> 0 && *set2
< 32) {
182 bzero(&msg
, sizeof(msg
));
183 netmsg_init(&msg
.base
, NULL
, &curthread
->td_msgport
,
184 0, set_swap_dispatch
);
185 msg
.set_from
= *set1
;
188 netisr_domsg(&msg
.base
, 0);
194 ip_fw3_ctl_set_toggle(struct sockopt
*sopt
)
196 struct ipfw3_context
*ctx
;
199 ctx
= fw3_ctx
[mycpuid
];
201 num
=(int *)sopt
->sopt_val
;
202 if (*num
> 0 && *num
< 32) {
203 ctx
->sets
= ctx
->sets
^ (1 << *num
);
209 ip_fw3_ctl_set_get(struct sockopt
*sopt
)
211 struct ipfw3_context
*ctx
;
213 ctx
= fw3_ctx
[mycpuid
];
215 bcopy(&ctx
->sets
, sopt
->sopt_val
, sopt
->sopt_valsize
);
220 set_flush_dispatch(netmsg_t smsg
)
222 struct netmsg_sets
*msg
= (struct netmsg_sets
*)smsg
;
223 struct ipfw3_context
*ctx
= fw3_ctx
[mycpuid
];
224 struct ip_fw
*prev
, *rule
;
228 while (rule
!= NULL
) {
229 if (rule
->set
== msg
->set_to
) {
230 rule
= ip_fw3_delete_rule(ctx
, prev
, rule
);
236 netisr_forwardmsg_all(&smsg
->base
, mycpuid
+ 1);
240 ip_fw3_ctl_set_flush(struct sockopt
*sopt
)
242 struct netmsg_sets msg
;
245 num
=(int *)sopt
->sopt_val
;
246 if (*num
> 0 && *num
< 32) {
247 bzero(&msg
, sizeof(msg
));
248 netmsg_init(&msg
.base
, NULL
, &curthread
->td_msgport
,
249 0, set_flush_dispatch
);
252 netisr_domsg(&msg
.base
, 0);
258 ip_fw3_ctl_set_sockopt(struct sockopt
*sopt
)
261 switch (sopt
->sopt_name
) {
263 error
= ip_fw3_ctl_set_get(sopt
);
265 case IP_FW_SET_TOGGLE
:
266 error
= ip_fw3_ctl_set_toggle(sopt
);
269 error
= ip_fw3_ctl_set_swap(sopt
);
271 case IP_FW_SET_MOVE_RULE
:
272 error
= ip_fw3_ctl_set_move_rule(sopt
);
274 case IP_FW_SET_MOVE_SET
:
275 error
= ip_fw3_ctl_set_move_set(sopt
);
277 case IP_FW_SET_FLUSH
:
278 error
= ip_fw3_ctl_set_flush(sopt
);
281 kprintf("ipfw3 set invalid socket option %d\n",