xref: /dragonfly/sys/net/ipfw3/ip_fw3_set.c (revision d8d5b238)
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/mplock2.h>
56 
57 #include <net/ethernet.h>
58 #include <net/netmsg2.h>
59 #include <net/netisr2.h>
60 #include <net/route.h>
61 #include <net/if.h>
62 
63 #include <netinet/in.h>
64 #include <netinet/ip.h>
65 #include <netinet/ip_icmp.h>
66 #include <netinet/tcp.h>
67 #include <netinet/tcp_timer.h>
68 #include <netinet/tcp_var.h>
69 #include <netinet/tcpip.h>
70 #include <netinet/udp.h>
71 #include <netinet/udp_var.h>
72 #include <netinet/in_systm.h>
73 #include <netinet/in_var.h>
74 #include <netinet/in_pcb.h>
75 #include <netinet/ip_var.h>
76 #include <netinet/ip_divert.h>
77 #include <net/ipfw3/ip_fw.h>
78 
79 #include "ip_fw3.h"
80 #include "ip_fw3_set.h"
81 
82 
83 extern struct ipfw3_context 		*fw3_ctx[MAXCPU];
84 
85 void
86 move_set_dispatch(netmsg_t smsg)
87 {
88 	struct netmsg_sets *msg = (struct netmsg_sets *)smsg;
89 	struct ipfw3_context *ctx = fw3_ctx[mycpuid];
90 	struct ip_fw *rule;
91 	for (rule = ctx->rules; rule; rule = rule->next) {
92 		if (rule->set == msg->set_from)
93 			rule->set = msg->set_to;
94 	}
95 	netisr_forwardmsg_all(&smsg->base, mycpuid + 1);
96 }
97 
98 int
99 ip_fw3_ctl_set_move_set(struct sockopt *sopt)
100 {
101 	struct ipfw3_context *ctx;
102 	struct netmsg_sets msg;
103 	int *set1, *set2;
104 
105 	ctx = fw3_ctx[mycpuid];
106 	set1 =(int *)sopt->sopt_val;
107 	set2 = set1 + 1;
108 	if (*set1 > 0 && *set1 < 32 && *set2 > 0 && *set2 < 32) {
109 		bzero(&msg, sizeof(msg));
110 		netmsg_init(&msg.base, NULL, &curthread->td_msgport,
111 				0, move_set_dispatch);
112 		msg.set_from = *set1;
113 		msg.set_to = *set2;
114 
115 		netisr_domsg(&msg.base, 0);
116 	}
117 	return 0;
118 }
119 
120 void
121 move_rule_dispatch(netmsg_t smsg)
122 {
123 	struct netmsg_sets *msg = (struct netmsg_sets *)smsg;
124 	struct ipfw3_context *ctx = fw3_ctx[mycpuid];
125 	struct ip_fw *rule;
126 	for (rule = ctx->rules; rule; rule = rule->next) {
127 		if (rule->rulenum == msg->rule_num)
128 			rule->set = msg->set_to;
129 	}
130 	netisr_forwardmsg_all(&smsg->base, mycpuid + 1);
131 }
132 
133 int
134 ip_fw3_ctl_set_move_rule(struct sockopt *sopt)
135 {
136 	struct ipfw3_context *ctx;
137 	struct netmsg_sets msg;
138 	int *rule_num, *set;
139 
140 	ctx = fw3_ctx[mycpuid];
141 	rule_num =(int *)sopt->sopt_val;
142 	set = rule_num + 1;
143 	if (*rule_num > 0 && *rule_num < 65535 && *set >= 0 && *set < 32) {
144 		bzero(&msg, sizeof(msg));
145 		netmsg_init(&msg.base, NULL, &curthread->td_msgport,
146 				0, move_rule_dispatch);
147 		msg.rule_num = *rule_num;
148 		msg.set_to = *set;
149 		netisr_domsg(&msg.base, 0);
150 	}
151 	return 0;
152 }
153 
154 void
155 set_swap_dispatch(netmsg_t smsg)
156 {
157 	struct netmsg_sets *msg = (struct netmsg_sets *)smsg;
158 	struct ipfw3_context *ctx = fw3_ctx[mycpuid];
159 	struct ip_fw *rule;
160 
161 	for (rule = ctx->rules; rule; rule = rule->next) {
162 		if (rule->set == msg->set_from)
163 			rule->set = msg->set_to;
164 		else if (rule->set == msg->set_to)
165 			rule->set = msg->set_from;
166 	}
167 	netisr_forwardmsg_all(&smsg->base, mycpuid + 1);
168 }
169 
170 int
171 ip_fw3_ctl_set_swap(struct sockopt *sopt)
172 {
173 	struct ipfw3_context *ctx;
174 	struct netmsg_sets msg;
175 	int *set1, *set2;
176 
177 	ctx = fw3_ctx[mycpuid];
178 	set1 =(int *)sopt->sopt_val;
179 	set2 = set1 + 1;
180 	if (*set1 > 0 && *set1 < 32 && *set2 > 0 && *set2 < 32) {
181 		bzero(&msg, sizeof(msg));
182 		netmsg_init(&msg.base, NULL, &curthread->td_msgport,
183 				0, set_swap_dispatch);
184 		msg.set_from = *set1;
185 		msg.set_to = *set2;
186 
187 		netisr_domsg(&msg.base, 0);
188 	}
189 	return 0;
190 }
191 
192 int
193 ip_fw3_ctl_set_toggle(struct sockopt *sopt)
194 {
195 	struct ipfw3_context *ctx;
196 	int *num;
197 
198 	ctx = fw3_ctx[mycpuid];
199 
200 	num =(int *)sopt->sopt_val;
201 	if (*num > 0 && *num < 32) {
202 		ctx->sets = ctx->sets ^ (1 << *num);
203 	}
204 	return 0;
205 }
206 
207 int
208 ip_fw3_ctl_set_get(struct sockopt *sopt)
209 {
210 	struct ipfw3_context *ctx;
211 
212 	ctx = fw3_ctx[mycpuid];
213 
214 	bcopy(&ctx->sets, sopt->sopt_val, sopt->sopt_valsize);
215 	return 0;
216 }
217 
218 void
219 set_flush_dispatch(netmsg_t smsg)
220 {
221 	struct netmsg_sets *msg = (struct netmsg_sets *)smsg;
222 	struct ipfw3_context *ctx = fw3_ctx[mycpuid];
223 	struct ip_fw *prev, *rule;
224 
225 	prev = NULL;
226 	rule = ctx->rules;
227 	while (rule != NULL) {
228 		if (rule->set == msg->set_to) {
229 			rule = ip_fw3_delete_rule(ctx, prev, rule);
230 		} else {
231 			prev = rule;
232 			rule = rule->next;
233 		}
234 	}
235 	netisr_forwardmsg_all(&smsg->base, mycpuid + 1);
236 }
237 
238 int
239 ip_fw3_ctl_set_flush(struct sockopt *sopt)
240 {
241 	struct netmsg_sets msg;
242 	int *num;
243 
244 	num =(int *)sopt->sopt_val;
245 	if (*num > 0 && *num < 32) {
246 		bzero(&msg, sizeof(msg));
247 		netmsg_init(&msg.base, NULL, &curthread->td_msgport,
248 				0, set_flush_dispatch);
249 		msg.set_to = *num;
250 
251 		netisr_domsg(&msg.base, 0);
252 	}
253 	return 0;
254 }
255 
256 int
257 ip_fw3_ctl_set_sockopt(struct sockopt *sopt)
258 {
259 	int error = 0;
260 	switch (sopt->sopt_name) {
261 	case IP_FW_SET_GET:
262 		error = ip_fw3_ctl_set_get(sopt);
263 		break;
264 	case IP_FW_SET_TOGGLE:
265 		error = ip_fw3_ctl_set_toggle(sopt);
266 		break;
267 	case IP_FW_SET_SWAP:
268 		error = ip_fw3_ctl_set_swap(sopt);
269 		break;
270 	case IP_FW_SET_MOVE_RULE:
271 		error = ip_fw3_ctl_set_move_rule(sopt);
272 		break;
273 	case IP_FW_SET_MOVE_SET:
274 		error = ip_fw3_ctl_set_move_set(sopt);
275 		break;
276 	case IP_FW_SET_FLUSH:
277 		error = ip_fw3_ctl_set_flush(sopt);
278 		break;
279 	default:
280 		kprintf("ipfw3 set invalid socket option %d\n",
281 				sopt->sopt_name);
282 	}
283 	return error;
284 }
285 
286