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