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