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 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 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 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 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 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 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 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 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 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 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 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