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