xref: /dragonfly/sys/net/ipfw3/ip_fw3_set.c (revision b0ae6fbc)
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/thread2.h>
49 #include <sys/in_cksum.h>
50 #include <sys/systm.h>
51 #include <sys/proc.h>
52 #include <sys/socket.h>
53 #include <sys/syslog.h>
54 #include <sys/ucred.h>
55 #include <sys/lock.h>
56 #include <sys/mplock2.h>
57 
58 #include <net/ethernet.h>
59 #include <net/netmsg2.h>
60 #include <net/netisr2.h>
61 #include <net/route.h>
62 #include <net/if.h>
63 
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>
79 
80 #include "ip_fw3.h"
81 #include "ip_fw3_set.h"
82 
83 
84 extern struct ipfw3_context 		*fw3_ctx[MAXCPU];
85 
86 void
87 move_set_dispatch(netmsg_t smsg)
88 {
89 	struct netmsg_sets *msg = (struct netmsg_sets *)smsg;
90 	struct ipfw3_context *ctx = fw3_ctx[mycpuid];
91 	struct ip_fw *rule;
92 	for (rule = ctx->rules; rule; rule = rule->next) {
93 		if (rule->set == msg->set_from)
94 			rule->set = msg->set_to;
95 	}
96 	netisr_forwardmsg_all(&smsg->base, mycpuid + 1);
97 }
98 
99 int
100 ip_fw3_ctl_set_move_set(struct sockopt *sopt)
101 {
102 	struct ipfw3_context *ctx;
103 	struct netmsg_sets msg;
104 	int *set1, *set2;
105 
106 	ctx = fw3_ctx[mycpuid];
107 	set1 =(int *)sopt->sopt_val;
108 	set2 = set1 + 1;
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;
114 		msg.set_to = *set2;
115 
116 		netisr_domsg(&msg.base, 0);
117 	}
118 	return 0;
119 }
120 
121 void
122 move_rule_dispatch(netmsg_t smsg)
123 {
124 	struct netmsg_sets *msg = (struct netmsg_sets *)smsg;
125 	struct ipfw3_context *ctx = fw3_ctx[mycpuid];
126 	struct ip_fw *rule;
127 	for (rule = ctx->rules; rule; rule = rule->next) {
128 		if (rule->rulenum == msg->rule_num)
129 			rule->set = msg->set_to;
130 	}
131 	netisr_forwardmsg_all(&smsg->base, mycpuid + 1);
132 }
133 
134 int
135 ip_fw3_ctl_set_move_rule(struct sockopt *sopt)
136 {
137 	struct ipfw3_context *ctx;
138 	struct netmsg_sets msg;
139 	int *rule_num, *set;
140 
141 	ctx = fw3_ctx[mycpuid];
142 	rule_num =(int *)sopt->sopt_val;
143 	set = rule_num + 1;
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;
149 		msg.set_to = *set;
150 		netisr_domsg(&msg.base, 0);
151 	}
152 	return 0;
153 }
154 
155 void
156 set_swap_dispatch(netmsg_t smsg)
157 {
158 	struct netmsg_sets *msg = (struct netmsg_sets *)smsg;
159 	struct ipfw3_context *ctx = fw3_ctx[mycpuid];
160 	struct ip_fw *rule;
161 
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;
167 	}
168 	netisr_forwardmsg_all(&smsg->base, mycpuid + 1);
169 }
170 
171 int
172 ip_fw3_ctl_set_swap(struct sockopt *sopt)
173 {
174 	struct ipfw3_context *ctx;
175 	struct netmsg_sets msg;
176 	int *set1, *set2;
177 
178 	ctx = fw3_ctx[mycpuid];
179 	set1 =(int *)sopt->sopt_val;
180 	set2 = set1 + 1;
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;
186 		msg.set_to = *set2;
187 
188 		netisr_domsg(&msg.base, 0);
189 	}
190 	return 0;
191 }
192 
193 int
194 ip_fw3_ctl_set_toggle(struct sockopt *sopt)
195 {
196 	struct ipfw3_context *ctx;
197 	int *num;
198 
199 	ctx = fw3_ctx[mycpuid];
200 
201 	num =(int *)sopt->sopt_val;
202 	if (*num > 0 && *num < 32) {
203 		ctx->sets = ctx->sets ^ (1 << *num);
204 	}
205 	return 0;
206 }
207 
208 int
209 ip_fw3_ctl_set_get(struct sockopt *sopt)
210 {
211 	struct ipfw3_context *ctx;
212 
213 	ctx = fw3_ctx[mycpuid];
214 
215 	bcopy(&ctx->sets, sopt->sopt_val, sopt->sopt_valsize);
216 	return 0;
217 }
218 
219 void
220 set_flush_dispatch(netmsg_t smsg)
221 {
222 	struct netmsg_sets *msg = (struct netmsg_sets *)smsg;
223 	struct ipfw3_context *ctx = fw3_ctx[mycpuid];
224 	struct ip_fw *prev, *rule;
225 
226 	prev = NULL;
227 	rule = ctx->rules;
228 	while (rule != NULL) {
229 		if (rule->set == msg->set_to) {
230 			rule = ip_fw3_delete_rule(ctx, prev, rule);
231 		} else {
232 			prev = rule;
233 			rule = rule->next;
234 		}
235 	}
236 	netisr_forwardmsg_all(&smsg->base, mycpuid + 1);
237 }
238 
239 int
240 ip_fw3_ctl_set_flush(struct sockopt *sopt)
241 {
242 	struct netmsg_sets msg;
243 	int *num;
244 
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);
250 		msg.set_to = *num;
251 
252 		netisr_domsg(&msg.base, 0);
253 	}
254 	return 0;
255 }
256 
257 int
258 ip_fw3_ctl_set_sockopt(struct sockopt *sopt)
259 {
260 	int error = 0;
261 	switch (sopt->sopt_name) {
262 	case IP_FW_SET_GET:
263 		error = ip_fw3_ctl_set_get(sopt);
264 		break;
265 	case IP_FW_SET_TOGGLE:
266 		error = ip_fw3_ctl_set_toggle(sopt);
267 		break;
268 	case IP_FW_SET_SWAP:
269 		error = ip_fw3_ctl_set_swap(sopt);
270 		break;
271 	case IP_FW_SET_MOVE_RULE:
272 		error = ip_fw3_ctl_set_move_rule(sopt);
273 		break;
274 	case IP_FW_SET_MOVE_SET:
275 		error = ip_fw3_ctl_set_move_set(sopt);
276 		break;
277 	case IP_FW_SET_FLUSH:
278 		error = ip_fw3_ctl_set_flush(sopt);
279 		break;
280 	default:
281 		kprintf("ipfw3 set invalid socket option %d\n",
282 				sopt->sopt_name);
283 	}
284 	return error;
285 }
286 
287