| 186 | | fw_quiet = 0; |
| 187 | | |
| 188 | | /* Create authservers table here instead of in iptables_fw_set_authservers |
| 189 | | * so we only have to flush it and not destroy/create every time */ |
| 190 | | iptables_do_command("-t nat -N " TABLE_WIFIDOG_AUTHSERVERS); |
| 191 | | |
| 192 | | iptables_fw_set_authservers(); |
| 193 | | |
| 194 | | LOCK_CONFIG(); |
| 195 | | |
| 196 | | iptables_do_command("-t nat -N " TABLE_WIFIDOG_VALIDATE); |
| 197 | | iptables_do_command("-t nat -A " TABLE_WIFIDOG_VALIDATE " -j " TABLE_WIFIDOG_AUTHSERVERS); |
| 198 | | iptables_do_command("-t nat -A " TABLE_WIFIDOG_VALIDATE " -d %s -j ACCEPT", config->gw_address); |
| 199 | | |
| 200 | | UNLOCK_CONFIG(); |
| 201 | | |
| 202 | | /** Insert global rules BEFORE the "defaults" */ |
| 203 | | iptables_load_ruleset("global", TABLE_WIFIDOG_VALIDATE); |
| 204 | | iptables_load_ruleset("validating-users", TABLE_WIFIDOG_VALIDATE); |
| 205 | | |
| 206 | | LOCK_CONFIG(); |
| 207 | | |
| 208 | | iptables_do_command("-t nat -N " TABLE_WIFIDOG_UNKNOWN); |
| 209 | | iptables_do_command("-t nat -A " TABLE_WIFIDOG_UNKNOWN " -j " TABLE_WIFIDOG_AUTHSERVERS); |
| 210 | | iptables_do_command("-t nat -A " TABLE_WIFIDOG_UNKNOWN " -d %s -j ACCEPT", config->gw_address); |
| 211 | | |
| 212 | | UNLOCK_CONFIG(); |
| 213 | | |
| 214 | | /** Insert global rules BEFORE the "defaults" */ |
| 215 | | iptables_load_ruleset("global", TABLE_WIFIDOG_UNKNOWN); |
| 216 | | iptables_load_ruleset("unknown-users", TABLE_WIFIDOG_UNKNOWN); |
| 217 | | LOCK_CONFIG(); |
| 218 | | |
| 219 | | /* XXX If there's a rule in global for port 80, it overrides this. */ |
| 220 | | iptables_do_command("-t nat -A " TABLE_WIFIDOG_UNKNOWN " -p tcp --dport 80 -j REDIRECT --to-ports %d", config->gw_port); |
| 221 | | UNLOCK_CONFIG(); |
| 222 | | iptables_do_command("-t nat -A " TABLE_WIFIDOG_UNKNOWN " -j DROP"); |
| 223 | | |
| 224 | | iptables_do_command("-t nat -N " TABLE_WIFIDOG_KNOWN); |
| 225 | | /* Insert global rules BEFORE the "defaults" */ |
| 226 | | iptables_load_ruleset("global", TABLE_WIFIDOG_KNOWN); |
| 227 | | iptables_load_ruleset("known-users", TABLE_WIFIDOG_KNOWN); |
| 228 | | |
| 229 | | iptables_do_command("-t nat -N " TABLE_WIFIDOG_LOCKED); |
| 230 | | iptables_load_ruleset("locked-users", TABLE_WIFIDOG_KNOWN); |
| 231 | | |
| 232 | | iptables_do_command("-t nat -N " TABLE_WIFIDOG_CLASS); |
| 233 | | LOCK_CONFIG(); |
| 234 | | iptables_do_command("-t nat -A " TABLE_WIFIDOG_CLASS " -i %s -m mark --mark 0x%u -j " TABLE_WIFIDOG_VALIDATE, config->gw_interface, FW_MARK_PROBATION); |
| 235 | | iptables_do_command("-t nat -A " TABLE_WIFIDOG_CLASS " -i %s -m mark --mark 0x%u -j " TABLE_WIFIDOG_KNOWN, config->gw_interface, FW_MARK_KNOWN); |
| 236 | | iptables_do_command("-t nat -A " TABLE_WIFIDOG_CLASS " -i %s -m mark --mark 0x%u -j " TABLE_WIFIDOG_LOCKED, config->gw_interface, FW_MARK_LOCKED); |
| 237 | | iptables_do_command("-t nat -A " TABLE_WIFIDOG_CLASS " -i %s -j " TABLE_WIFIDOG_UNKNOWN, config->gw_interface); |
| 238 | | iptables_do_command("-t nat -I PREROUTING 1 -i %s -j " TABLE_WIFIDOG_CLASS, config->gw_interface); |
| 239 | | |
| 240 | | iptables_do_command("-t mangle -N " TABLE_WIFIDOG_OUTGOING); |
| 241 | | iptables_do_command("-t mangle -I PREROUTING 1 -i %s -j " TABLE_WIFIDOG_OUTGOING, config->gw_interface); |
| 242 | | |
| 243 | | iptables_do_command("-t mangle -N " TABLE_WIFIDOG_INCOMING); |
| 244 | | if (config->external_interface) { |
| 245 | | iptables_do_command("-t mangle -I FORWARD 1 -i %s -j " TABLE_WIFIDOG_INCOMING, config->external_interface); |
| 246 | | } else { |
| 247 | | iptables_do_command("-t mangle -I FORWARD 1 -j " TABLE_WIFIDOG_INCOMING); |
| 248 | | } |
| 249 | | |
| 250 | | iptables_do_command("-t filter -N " TABLE_WIFIDOG_WIFI_TO_GW); |
| 251 | | iptables_do_command("-t filter -I INPUT 1 -i %s -j " TABLE_WIFIDOG_WIFI_TO_GW, config->gw_interface); |
| 252 | | |
| 253 | | UNLOCK_CONFIG(); |
| 254 | | |
| | 191 | LOCK_CONFIG(); |
| | 192 | if (config->gw_interface) |
| | 193 | gw_interface = strdup(config->gw_interface); |
| | 194 | if (config->external_interface) |
| | 195 | external_interface = strdup(config->external_interface); |
| | 196 | gw_port = config->gw_port; |
| | 197 | UNLOCK_CONFIG(); |
| | 198 | |
| | 199 | /* |
| | 200 | * |
| | 201 | * Everything in the MANGLE table |
| | 202 | * |
| | 203 | */ |
| | 204 | |
| | 205 | /* Create new chains */ |
| | 206 | iptables_do_command("-t mangle -N " TABLE_WIFIDOG_OUTGOING); |
| | 207 | iptables_do_command("-t mangle -N " TABLE_WIFIDOG_INCOMING); |
| | 208 | |
| | 209 | /* Assign links and rules to these new chains */ |
| | 210 | iptables_do_command("-t mangle -I PREROUTING 1 -i %s -j " TABLE_WIFIDOG_OUTGOING, gw_interface); |
| | 211 | |
| | 212 | if (external_interface) { |
| | 213 | iptables_do_command("-t mangle -I FORWARD 1 -i %s -j " TABLE_WIFIDOG_INCOMING, external_interface); |
| | 214 | } |
| | 215 | else { |
| | 216 | iptables_do_command("-t mangle -I FORWARD 1 -j " TABLE_WIFIDOG_INCOMING); |
| | 217 | } |
| | 218 | |
| | 219 | |
| | 220 | /* |
| | 221 | * |
| | 222 | * Everything in the NAT table |
| | 223 | * |
| | 224 | */ |
| | 225 | |
| | 226 | /* Create new chains */ |
| | 227 | iptables_do_command("-t nat -N " TABLE_WIFIDOG_WIFI_TO_INTERNET); |
| | 228 | iptables_do_command("-t nat -N " TABLE_WIFIDOG_UNKNOWN); |
| | 229 | |
| | 230 | /* Assign links and rules to these new chains */ |
| | 231 | if (external_interface) { |
| | 232 | iptables_do_command("-t nat -I PREROUTING 1 -i %s -j " TABLE_WIFIDOG_WIFI_TO_INTERNET, gw_interface); |
| | 233 | } |
| | 234 | else { |
| | 235 | iptables_do_command("-t nat -I PREROUTING 1 -j " TABLE_WIFIDOG_WIFI_TO_INTERNET); |
| | 236 | } |
| | 237 | |
| | 238 | iptables_do_command("-t nat -A " TABLE_WIFIDOG_WIFI_TO_INTERNET " -m mark --mark 0x%u -j RETURN", FW_MARK_KNOWN); |
| | 239 | iptables_do_command("-t nat -A " TABLE_WIFIDOG_WIFI_TO_INTERNET " -m mark --mark 0x%u -j RETURN", FW_MARK_PROBATION); |
| | 240 | iptables_do_command("-t nat -A " TABLE_WIFIDOG_WIFI_TO_INTERNET " -j " TABLE_WIFIDOG_UNKNOWN); |
| | 241 | iptables_do_command("-t nat -A " TABLE_WIFIDOG_UNKNOWN " -p tcp --dport 80 -j REDIRECT --to-ports %d", gw_port); |
| | 242 | |
| | 243 | |
| | 244 | /* |
| | 245 | * |
| | 246 | * Everything in the FILTER table |
| | 247 | * |
| | 248 | */ |
| | 249 | |
| | 250 | /* Create new chains */ |
| | 251 | iptables_do_command("-t filter -N " TABLE_WIFIDOG_WIFI_TO_GW); |
| | 252 | iptables_do_command("-t filter -N " TABLE_WIFIDOG_WIFI_TO_INTERNET); |
| | 253 | iptables_do_command("-t filter -N " TABLE_WIFIDOG_AUTHSERVERS); |
| | 254 | iptables_do_command("-t filter -N " TABLE_WIFIDOG_LOCKED); |
| | 255 | iptables_do_command("-t filter -N " TABLE_WIFIDOG_GLOBAL); |
| | 256 | iptables_do_command("-t filter -N " TABLE_WIFIDOG_VALIDATE); |
| | 257 | iptables_do_command("-t filter -N " TABLE_WIFIDOG_KNOWN); |
| | 258 | iptables_do_command("-t filter -N " TABLE_WIFIDOG_UNKNOWN); |
| | 259 | |
| | 260 | /* Assign links and rules to these new chains */ |
| | 261 | iptables_do_command("-t filter -I INPUT 1 -i %s -j " TABLE_WIFIDOG_WIFI_TO_GW, gw_interface); |
| | 262 | |
| | 263 | if (external_interface) { |
| | 264 | iptables_do_command("-t filter -I FORWARD 1 -i %s -j " TABLE_WIFIDOG_WIFI_TO_INTERNET, gw_interface); |
| | 265 | } |
| | 266 | else { |
| | 267 | iptables_do_command("-t filter -I FORWARD 1 -j " TABLE_WIFIDOG_WIFI_TO_INTERNET); |
| | 268 | } |
| | 269 | |
| | 270 | iptables_do_command("-t filter -A " TABLE_WIFIDOG_WIFI_TO_INTERNET " -j " TABLE_WIFIDOG_AUTHSERVERS); |
| | 271 | iptables_fw_set_authservers(); |
| | 272 | |
| | 273 | iptables_do_command("-t filter -A " TABLE_WIFIDOG_WIFI_TO_INTERNET " -m mark --mark 0x%u -j " TABLE_WIFIDOG_LOCKED, FW_MARK_LOCKED); |
| | 274 | iptables_load_ruleset("locked-users", TABLE_WIFIDOG_LOCKED); |
| | 275 | |
| | 276 | iptables_do_command("-t filter -A " TABLE_WIFIDOG_WIFI_TO_INTERNET " -j " TABLE_WIFIDOG_GLOBAL); |
| | 277 | iptables_load_ruleset("global", TABLE_WIFIDOG_GLOBAL); |
| | 278 | |
| | 279 | iptables_do_command("-t filter -A " TABLE_WIFIDOG_WIFI_TO_INTERNET " -m mark --mark 0x%u -j " TABLE_WIFIDOG_VALIDATE, FW_MARK_PROBATION); |
| | 280 | iptables_load_ruleset("validating-users", TABLE_WIFIDOG_VALIDATE); |
| | 281 | |
| | 282 | iptables_do_command("-t filter -A " TABLE_WIFIDOG_WIFI_TO_INTERNET " -m mark --mark 0x%u -j " TABLE_WIFIDOG_KNOWN, FW_MARK_KNOWN); |
| | 283 | iptables_load_ruleset("known-users", TABLE_WIFIDOG_KNOWN); |
| | 284 | |
| | 285 | iptables_do_command("-t filter -A " TABLE_WIFIDOG_WIFI_TO_INTERNET " -j " TABLE_WIFIDOG_UNKNOWN); |
| | 286 | iptables_load_ruleset("unknown-users", TABLE_WIFIDOG_UNKNOWN); |
| | 287 | iptables_do_command("-t filter -A " TABLE_WIFIDOG_UNKNOWN " -j REJECT --reject-with icmp-port-unreachable"); |
| | 288 | |
| | 289 | if (gw_interface) |
| | 290 | free(gw_interface); |
| | 291 | if (external_interface) |
| | 292 | free(external_interface); |
| | 293 | |
| 282 | | iptables_do_command("-t nat -X " TABLE_WIFIDOG_KNOWN); |
| 283 | | iptables_do_command("-t nat -X " TABLE_WIFIDOG_LOCKED); |
| 284 | | |
| 285 | | /* We loop in case wifidog has crashed and left some unwanted rules, |
| 286 | | * maybe we shouldn't loop forever, we'll try anyway |
| 287 | | */ |
| 288 | | rc = 0; |
| 289 | | while (rc == 0) { |
| 290 | | rc = iptables_do_command("-t nat -D PREROUTING -i %s -j " TABLE_WIFIDOG_CLASS, config->gw_interface); |
| 291 | | } |
| 292 | | iptables_do_command("-t nat -X " TABLE_WIFIDOG_CLASS); |
| 293 | | |
| 294 | | rc = 0; |
| 295 | | while (rc == 0) { |
| 296 | | rc = iptables_do_command("-t filter -D INPUT -i %s -j " TABLE_WIFIDOG_WIFI_TO_GW, config->gw_interface); |
| 297 | | } |
| 298 | | iptables_do_command("-t filter -X " TABLE_WIFIDOG_WIFI_TO_GW); |
| 299 | | |
| 300 | | rc = 0; |
| 301 | | while (rc == 0) { |
| 302 | | rc = iptables_do_command("-t mangle -D PREROUTING -i %s -j " TABLE_WIFIDOG_OUTGOING, config->gw_interface); |
| 303 | | } |
| 304 | | iptables_do_command("-t mangle -X " TABLE_WIFIDOG_OUTGOING); |
| 305 | | |
| 306 | | rc = 0; |
| 307 | | while (rc == 0) { |
| 308 | | if (config->external_interface) { |
| 309 | | rc = iptables_do_command("-t mangle -D FORWARD -i %s -j " TABLE_WIFIDOG_INCOMING, config->external_interface); |
| 310 | | } else { |
| 311 | | rc = iptables_do_command("-t mangle -D FORWARD -j " TABLE_WIFIDOG_INCOMING); |
| 312 | | } |
| 313 | | } |
| 314 | | iptables_do_command("-t mangle -X " TABLE_WIFIDOG_INCOMING); |
| | 328 | |
| | 329 | /* |
| | 330 | * |
| | 331 | * Everything in the FILTER table |
| | 332 | * |
| | 333 | */ |
| | 334 | iptables_fw_destroy_mention("filter", "INPUT", TABLE_WIFIDOG_WIFI_TO_GW); |
| | 335 | iptables_fw_destroy_mention("filter", "FORWARD", TABLE_WIFIDOG_WIFI_TO_INTERNET); |
| | 336 | iptables_do_command("-t filter -F " TABLE_WIFIDOG_WIFI_TO_GW); |
| | 337 | iptables_do_command("-t filter -F " TABLE_WIFIDOG_WIFI_TO_INTERNET); |
| | 338 | iptables_do_command("-t filter -F " TABLE_WIFIDOG_AUTHSERVERS); |
| | 339 | iptables_do_command("-t filter -F " TABLE_WIFIDOG_LOCKED); |
| | 340 | iptables_do_command("-t filter -F " TABLE_WIFIDOG_GLOBAL); |
| | 341 | iptables_do_command("-t filter -F " TABLE_WIFIDOG_VALIDATE); |
| | 342 | iptables_do_command("-t filter -F " TABLE_WIFIDOG_KNOWN); |
| | 343 | iptables_do_command("-t filter -F " TABLE_WIFIDOG_UNKNOWN); |
| | 344 | iptables_do_command("-t filter -X " TABLE_WIFIDOG_WIFI_TO_GW); |
| | 345 | iptables_do_command("-t filter -X " TABLE_WIFIDOG_WIFI_TO_INTERNET); |
| | 346 | iptables_do_command("-t filter -X " TABLE_WIFIDOG_AUTHSERVERS); |
| | 347 | iptables_do_command("-t filter -X " TABLE_WIFIDOG_LOCKED); |
| | 348 | iptables_do_command("-t filter -X " TABLE_WIFIDOG_GLOBAL); |
| | 349 | iptables_do_command("-t filter -X " TABLE_WIFIDOG_VALIDATE); |
| | 350 | iptables_do_command("-t filter -X " TABLE_WIFIDOG_KNOWN); |
| | 351 | iptables_do_command("-t filter -X " TABLE_WIFIDOG_UNKNOWN); |
| | 354 | } |
| | 355 | |
| | 356 | /* |
| | 357 | * Helper for iptables_fw_destroy |
| | 358 | * @param table The table to search |
| | 359 | * @param chain The chain in that table to search |
| | 360 | * @param mention A word to find and delete in rules in the given table+chain |
| | 361 | */ |
| | 362 | int |
| | 363 | iptables_fw_destroy_mention( |
| | 364 | char * table, |
| | 365 | char * chain, |
| | 366 | char * mention |
| | 367 | ) { |
| | 368 | FILE *p = NULL; |
| | 369 | char *command = NULL; |
| | 370 | char *command2 = NULL; |
| | 371 | char line[MAX_BUF]; |
| | 372 | char rulenum[10]; |
| | 373 | int deleted = 0; |
| | 374 | |
| | 375 | asprintf(&command, "iptables -t %s -L %s -n --line-numbers -v", table, chain); |
| | 376 | |
| | 377 | if ((p = popen(command, "r"))) { |
| | 378 | /* Skip first 2 lines */ |
| | 379 | while (!feof(p) && fgetc(p) != '\n'); |
| | 380 | while (!feof(p) && fgetc(p) != '\n'); |
| | 381 | /* Loop over entries */ |
| | 382 | while (fgets(line, sizeof(line), p)) { |
| | 383 | /* Look for mention */ |
| | 384 | if (strstr(line, mention)) { |
| | 385 | /* Found mention - Get the rule number into rulenum*/ |
| | 386 | if (sscanf(line, "%9[0-9]", rulenum) == 1) { |
| | 387 | /* Delete the rule: */ |
| | 388 | asprintf(&command2, "-t %s -D %s %s", table, chain, rulenum); |
| | 389 | iptables_do_command(command2); |
| | 390 | free(command2); |
| | 391 | deleted = 1; |
| | 392 | /* Do not keep looping - the captures rulenums will no longer be accurate */ |
| | 393 | break; |
| | 394 | } |
| | 395 | } |
| | 396 | } |
| | 397 | pclose(p); |
| | 398 | } |
| | 399 | |
| | 400 | free(command); |
| | 401 | |
| | 402 | if (deleted) { |
| | 403 | /* Recurse just in case there are more in the same table+chain */ |
| | 404 | iptables_fw_destroy_mention(table, chain, mention); |
| | 405 | } |
| | 406 | |
| | 407 | return (deleted); |