1 2/* 3 * Copyright 2004, Broadcom Corporation 4 * All Rights Reserved. 5 * 6 * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY 7 * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM 8 * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS 9 * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. 10 * 11 * $Id: firewall_noipt.c,v 1.1.1.1 2008/10/15 03:28:48 james26_jang Exp $ 12 */ 13#include <stdio.h> 14#include <stdlib.h> 15#include <string.h> 16#include <signal.h> 17#include <sys/socket.h> 18#include <netinet/in.h> 19#include <arpa/inet.h> 20#include <sys/types.h> 21#include <dirent.h> 22 23#include <bcmnvram.h> 24#include <shutils.h> 25#include <rc.h> 26#include <netconf.h> 27#include <nvparse.h> 28 29/* Add filter to specified table */ 30static void 31add_filter(netconf_filter_t *filter, int dir) 32{ 33 filter->dir = dir; 34 netconf_add_filter(filter); 35} 36 37/* Add port forward and a matching ACCEPT rule to the FORWARD table */ 38void 39add_forward(netconf_nat_t *nat, int dir, int target) 40{ 41 netconf_filter_t filter; 42 43 /* Set up LAN side match */ 44 memset(&filter, 0, sizeof(filter)); 45 filter.match.ipproto = nat->match.ipproto; 46 filter.match.src.ports[1] = nat->match.src.ports[1]; 47 filter.match.dst.ipaddr.s_addr = nat->ipaddr.s_addr; 48 filter.match.dst.netmask.s_addr = htonl(0xffffffff); 49 filter.match.dst.ports[0] = nat->ports[0]; 50 filter.match.dst.ports[1] = nat->ports[1]; 51 strncpy(filter.match.in.name, nat->match.in.name, IFNAMSIZ); 52 53 /* Accept connection */ 54 filter.target = target; 55 filter.dir = dir; 56 57 /* Do it */ 58 netconf_add_nat(nat); 59 netconf_add_filter(&filter); 60} 61 62#ifdef NOIPTABLES 63/* Add port forward and a matching ACCEPT rule to the FORWARD table */ 64static void 65add_forward_ex(char *chain, char *proto, int port) 66{ 67#ifdef REMOVE 68 netconf_filter_t filter; 69 70 /* Set up LAN side match */ 71 memset(&filter, 0, sizeof(filter)); 72 filter.match.ipproto = nat->match.ipproto; 73 filter.match.src.ports[1] = nat->match.src.ports[1]; 74 filter.match.dst.ipaddr.s_addr = nat->ipaddr.s_addr; 75 filter.match.dst.netmask.s_addr = htonl(0xffffffff); 76 filter.match.dst.ports[0] = nat->ports[0]; 77 filter.match.dst.ports[1] = nat->ports[1]; 78 strncpy(filter.match.in.name, nat->match.in.name, IFNAMSIZ); 79 80 /* Accept connection */ 81 filter.target = target; 82 filter.dir = dir; 83 84 /* Do it */ 85 netconf_add_filter(&filter); 86#endif 87} 88 89static void 90add_netmap_ex(char *chain, char *proto, char *dstip, int port, char *toip) 91{ 92#ifdef REMOVE 93 netconf_filter_t filter; 94 95 /* Set up LAN side match */ 96 memset(&filter, 0, sizeof(filter)); 97 filter.match.ipproto = nat->match.ipproto; 98 filter.match.src.ports[1] = nat->match.src.ports[1]; 99 filter.match.dst.ipaddr.s_addr = nat->ipaddr.s_addr; 100 filter.match.dst.netmask.s_addr = htonl(0xffffffff); 101 filter.match.dst.ports[0] = nat->ports[0]; 102 filter.match.dst.ports[1] = nat->ports[1]; 103 strncpy(filter.match.in.name, nat->match.in.name, IFNAMSIZ); 104 105 /* Accept connection */ 106 filter.target = target; 107 filter.dir = dir; 108 109 /* Do it */ 110 netconf_add_nat(nat); 111#endif 112} 113#endif 114 115int 116start_firewall(void) 117{ 118 DIR *dir; 119 struct dirent *file; 120 FILE *fp; 121 char name[NAME_MAX]; 122 netconf_filter_t filter; 123 netconf_app_t app; 124 int i, j; 125 char var[256], *next; 126 int log_level, log_drop, log_accept; 127 128 /* Reset firewall */ 129 netconf_reset_fw(); 130 131#ifndef REMOVE_QTR 132 /* Block obviously spoofed IP addresses */ 133 if (!(dir = opendir("/proc/sys/net/ipv4/conf"))) 134 perror("/proc/sys/net/ipv4/conf"); 135 while (dir && (file = readdir(dir))) { 136 if (strncmp(file->d_name, ".", NAME_MAX) != 0 && 137 strncmp(file->d_name, "..", NAME_MAX) != 0) { 138 sprintf(name, "/proc/sys/net/ipv4/conf/%s/rp_filter", file->d_name); 139 if (!(fp = fopen(name, "r+"))) { 140 perror(name); 141 break; 142 } 143 fputc('1', fp); 144 fclose(fp); 145 } 146 } 147 if (dir) closedir(dir); 148#endif 149 150 /* Add max conntrack as 4096, thanks for Oleg */ 151 if ((fp=fopen("/proc/sys/net/ipv4/ip_conntrack_max", "r+"))) 152 { 153 if (nvram_get("misc_conntrack_x")==NULL) fputs("4096", fp); 154 else fputs(nvram_safe_get("misc_conntrack_x"), fp); 155 fclose(fp); 156 } 157 158 /* Optionally log connections */ 159 log_level = atoi(nvram_safe_get("log_level")); 160 log_drop = (log_level & 1) ? NETCONF_LOG_DROP : NETCONF_DROP; 161 log_accept = (log_level & 2) ? NETCONF_LOG_ACCEPT : NETCONF_ACCEPT; 162 163 /* 164 * Inbound drops 165 */ 166#ifndef REMOVE_QTR 167 /* Drop invalid packets */ 168 memset(&filter, 0, sizeof(filter)); 169 filter.match.state = NETCONF_INVALID; 170 filter.target = NETCONF_DROP; 171 add_filter(&filter, NETCONF_IN); 172 add_filter(&filter, NETCONF_FORWARD); 173#endif 174 175 /* 176 * Forward drops 177 */ 178 if (nvram_match("fw_lw_enable_x","1")) { 179 /* Client filters */ 180 for (i = 0; i < MAX_NVPARSE; i++) { 181 netconf_filter_t start, end; 182 183#ifdef ASUS_EXT 184 int days, daystart, dayend; 185 186 if (get_filter_client_ex(i, &start, &end, &days) && !(start.match.flags & NETCONF_DISABLED)) 187 { 188 189 while (ntohl(start.match.src.ipaddr.s_addr) <= ntohl(end.match.src.ipaddr.s_addr)) 190 { 191 192 /* Override target */ 193 start.target = log_drop; 194 j=0; 195 while(dayrange(days, &j, &daystart, &dayend)) 196 { 197 start.match.days[0] = daystart; 198 start.match.days[1] = dayend; 199 add_filter(&start, NETCONF_FORWARD); 200 if (j>=7) break; 201 202 } 203 start.match.src.ipaddr.s_addr = htonl(ntohl(start.match.src.ipaddr.s_addr) + 1); 204 } 205 } 206#else 207 if (get_filter_client(i, &start, &end) && !(start.match.flags & NETCONF_DISABLED)) { 208 while (ntohl(start.match.src.ipaddr.s_addr) <= ntohl(end.match.src.ipaddr.s_addr)) { 209 /* Override target */ 210 start.target = log_drop; 211 add_filter(&start, NETCONF_FORWARD); 212 start.match.src.ipaddr.s_addr = htonl(ntohl(start.match.src.ipaddr.s_addr) + 1); 213 } 214 } 215#endif 216 } 217 } 218 219#ifndef ASUS_EXT 220 /* Filter by MAC address */ 221 if (!nvram_match("filter_macmode", "disabled")) { 222 memset(&filter, 0, sizeof(filter)); 223 strcpy(filter.match.in.name, nvram_safe_get("lan_ifname")); 224 if (nvram_match("filter_macmode", "allow")) { 225 /* Allow new connections from the LAN side only from the specified addresses */ 226 filter.target = log_accept; 227 filter.match.state = NETCONF_NEW; 228 } else { 229 /* Drop connections from the specified addresses */ 230 filter.target = log_drop; 231 } 232 foreach(var, nvram_safe_get("filter_maclist"), next) { 233 if (ether_atoe(var, filter.match.mac.octet)) 234 add_filter(&filter, NETCONF_FORWARD); 235 } 236 } 237#endif 238 239#ifndef REMOVE_QTR 240 /* 241 * Inbound accepts 242 */ 243 /* Allow new connections from the loopback interface */ 244 memset(&filter, 0, sizeof(filter)); 245 filter.match.state = NETCONF_NEW; 246 strcpy(filter.match.in.name, "lo"); 247 filter.target = log_accept; 248 add_filter(&filter, NETCONF_IN); 249 add_filter(&filter, NETCONF_FORWARD); 250 251 /* Allow new connections from the LAN side */ 252 memset(&filter, 0, sizeof(filter)); 253 filter.match.state = NETCONF_NEW; 254 strcpy(filter.match.in.name, nvram_safe_get("lan_ifname")); 255 filter.target = log_accept; 256 add_filter(&filter, NETCONF_IN); 257 if (!nvram_match("filter_macmode", "allow")) 258 add_filter(&filter, NETCONF_FORWARD); 259 260 /* Allow established and related outbound connections back in */ 261 memset(&filter, 0, sizeof(filter)); 262 filter.match.state = NETCONF_ESTABLISHED | NETCONF_RELATED; 263 filter.target = log_accept; 264 add_filter(&filter, NETCONF_IN); 265 add_filter(&filter, NETCONF_FORWARD); 266#endif 267 /* 268 * NAT 269 */ 270 271 /* Enable IP masquerading */ 272 if ((fp = fopen("/proc/sys/net/ipv4/ip_forward", "r+"))) { 273 fputc('1', fp); 274 fclose(fp); 275 } else 276 perror("/proc/sys/net/ipv4/ip_forward"); 277 278 279 if (nvram_match("autofw_enable_x","1")) { 280 /* Application specific port forwards */ 281 for (i = 0; i < MAX_NVPARSE; i++) { 282 memset(&app, 0, sizeof(app)); 283 284 if ( 285#ifdef ASUS_EXT 286 get_autofw_port_ex(i, &app) 287#else 288 get_autofw_port(i, &app) 289#endif 290 && !(app.match.flags & NETCONF_DISABLED)) 291 netconf_add_fw((netconf_fw_t *) &app); 292 } 293 } 294 295#ifndef REMOVE_QTR 296 /* 297 * Inbound defaults 298 */ 299 300 /* Log refused connections */ 301 memset(&filter, 0, sizeof(filter)); 302 filter.target = log_drop; 303 add_filter(&filter, NETCONF_IN); 304 add_filter(&filter, NETCONF_FORWARD); 305#endif 306 307 dprintf("done\n"); 308 return 0; 309} 310 311 312int 313start_firewall2(char *wan_ifname) 314{ 315 netconf_nat_t nat; 316 netconf_filter_t filter; 317 int log_level, log_accept; 318 char tmp[100], prefix[] = "wanXXXXXXXXXX_"; 319 char wan_ip[32], lan_ip[32], lan_class[32]; 320 int i; 321 322 /* Optionally log connections */ 323 log_level = atoi(nvram_safe_get("log_level")); 324 log_accept = (log_level & 2) ? NETCONF_LOG_ACCEPT : NETCONF_ACCEPT; 325 326 /* Allow new connections from the WAN side */ 327 if (nvram_match("fw_disable", "1")) { 328 memset(&filter, 0, sizeof(filter)); 329 filter.match.state = NETCONF_NEW; 330 strcpy(filter.match.in.name, wan_ifname); 331 filter.target = log_accept; 332 add_filter(&filter, NETCONF_IN); 333 add_filter(&filter, NETCONF_FORWARD); 334 } 335 336 /* Enable IP masquerading */ 337 memset(&nat, 0, sizeof(nat)); 338 inet_aton(nvram_safe_get("lan_ipaddr"), &nat.match.src.ipaddr); 339 inet_aton(nvram_safe_get("lan_netmask"), &nat.match.src.netmask); 340 nat.match.src.ipaddr.s_addr &= nat.match.src.netmask.s_addr; 341 strcpy(nat.match.out.name, wan_ifname); 342 nat.target = NETCONF_MASQ; 343 netconf_add_nat(&nat); 344 345 /* Enable IP masquerading, loopback */ 346#ifndef REMOVE_QTR 347 memset(&nat, 0, sizeof(nat)); 348 inet_aton(nvram_safe_get("lan_ipaddr"), &nat.match.src.ipaddr); 349 inet_aton(nvram_safe_get("lan_netmask"), &nat.match.src.netmask); 350 nat.match.src.ipaddr.s_addr &= nat.match.src.netmask.s_addr; 351 inet_aton(nvram_safe_get("lan_ipaddr"), &nat.match.dst.ipaddr); 352 inet_aton(nvram_safe_get("lan_netmask"), &nat.match.dst.netmask); 353 nat.match.dst.ipaddr.s_addr &= nat.match.dst.netmask.s_addr; 354 strcpy(nat.match.out.name, nvram_safe_get("lan_ifname")); 355 nat.target = NETCONF_MASQ; 356 netconf_add_nat(&nat); 357#endif 358 /* Enable remote management */ 359 if (nvram_invmatch("http_wanport", "")) { 360 /* Set up WAN side match */ 361 memset(&nat, 0, sizeof(nat)); 362 nat.match.ipproto = IPPROTO_TCP; 363 nat.match.src.ports[1] = htons(0xffff); 364 nat.match.dst.ports[0] = htons(atoi(nvram_safe_get("http_wanport"))); 365 nat.match.dst.ports[1] = htons(atoi(nvram_safe_get("http_wanport"))); 366 //strncpy(nat.match.in.name, wan_ifname, IFNAMSIZ); 367 368 369 if (nvram_invmatch("wan_ipaddr_t", "")) 370 { 371 inet_aton("255.255.255.255", &nat.match.dst.netmask); 372 inet_aton(nvram_safe_get("wan_ipaddr_t") , &nat.match.dst.ipaddr); 373 } 374 375 /* Set up DNAT to LAN */ 376 nat.target = NETCONF_DNAT; 377 (void) inet_aton(nvram_safe_get("lan_ipaddr"), &nat.ipaddr); 378 nat.ports[0] = htons(atoi(nvram_safe_get("http_lanport"))); 379 nat.ports[1] = htons(atoi(nvram_safe_get("http_lanport"))); 380 381 add_forward(&nat, NETCONF_IN, log_accept); 382 } 383 384 /* Persistent (static) port forwards */ 385 if (nvram_match("vts_enable_x","1")) { 386 for (i = 0; i < MAX_NVPARSE; i++) { 387 memset(&nat, 0, sizeof(nat)); 388 if ( 389#ifdef ASUS_EXT 390 get_forward_port_ex(i, &nat) 391#else 392 get_forward_port(i, &nat) 393#endif 394 395 && !(nat.match.flags & NETCONF_DISABLED)) { 396 /* Set interface name (match packets entering WAN interface) */ 397 398 if (nvram_invmatch("wan_ipaddr_t", "")) 399 { 400 inet_aton("255.255.255.255", &nat.match.dst.netmask); 401 inet_aton(nvram_safe_get("wan_ipaddr_t") , &nat.match.dst.ipaddr); 402 } 403 //strncpy(nat.match.in.name, wan_ifname, IFNAMSIZ); 404 add_forward(&nat, NETCONF_FORWARD, log_accept); 405 } 406 } 407 } 408 409 /* Forward all WAN ports to DMZ IP address */ 410 if (nvram_invmatch("dmz_ip", "")) { 411 /* Set up WAN side match */ 412 memset(&nat, 0, sizeof(nat)); 413 nat.match.src.ports[1] = htons(0xffff); 414 nat.match.dst.ports[1] = htons(0xffff); 415 strncpy(nat.match.in.name, wan_ifname, IFNAMSIZ); 416 417 if (nvram_invmatch("wan_ipaddr_t", "")) 418 { 419 inet_aton("255.255.255.255", &nat.match.dst.netmask); 420 inet_aton(nvram_safe_get("wan_ipaddr_t") , &nat.match.dst.ipaddr); 421 } 422 423 /* Set up DNAT to LAN */ 424 nat.target = NETCONF_DNAT; 425 (void) inet_aton(nvram_safe_get("dmz_ip"), &nat.ipaddr); 426 nat.ports[1] = htons(0xffff); 427 428 nat.match.ipproto = IPPROTO_TCP; 429 add_forward(&nat, NETCONF_FORWARD, log_accept); 430 nat.match.ipproto = IPPROTO_UDP; 431 add_forward(&nat, NETCONF_FORWARD, log_accept); 432 } 433 434 /* Clamp TCP MSS to PMTU of WAN interface */ 435 sprintf(prefix, "wan%d_", wan_ifunit(wan_ifname)); 436 if (nvram_match(strcat_r(prefix, "proto", tmp), "pppoe")) 437 netconf_clamp_mss_to_pmtu(); 438 439 if (nvram_match("router_disable", "0") && nvram_invmatch("sp_battle_ips", "0")) 440 { 441 #define BASEPORT "6112" 442 #define BASEPORT_NEW 10000 443 444 strcpy(lan_ip, nvram_safe_get("lan_ipaddr")); 445 strcpy(wan_ip, nvram_safe_get("wan_ipaddr_t")); 446 ip2class(lan_ip, nvram_safe_get("lan_netmask"), lan_class); 447 448#ifdef NOIPTABLES 449 add_netmap_ex("PREROUTING", "udp", wan_ip, BASEPORT, lan_class); 450 add_netmap_ex("POSTROUTING", "udp", lan_class, BASEPORT, wan_ip); 451 add_forward_ex("FORWARD", "udp", BASEPORT); 452#else 453 /* run starcraft patch anyway */ 454 //fprintf(fp, "-A PREROUTING -p udp -d %s --sport %d -j NETMAP --to %s\n", wan_ip, BASEPORT, lan_class); 455 eval("iptables", "-t", "nat", "-I", "PREROUTING", "-p", "udp", "-d", wan_ip, "--sport", BASEPORT, "-j", "NETMAP", "--to", lan_class); 456 457 //fprintf(fp, "-A POSTROUTING -p udp -s %s --dport %d -j NETMAP --to %s\n", lan_class, BASEPORT, wan_ip); 458 eval("iptables", "-t", "nat", "-I", "POSTROUTING", "-p", "udp", "-s", lan_class, "--dport", BASEPORT, "-j", "NETMAP", "--to", wan_ip); 459 460 //fprintf(fp1, "-A FORWARD -p udp --dport %d -j %s\n", BASEPORT, logaccept); 461 eval("iptables", "-A", "FORWARD", "-p", "udp", "--dport", BASEPORT, "-j", "ACCEPT"); 462#endif 463 } 464 dprintf("done\n"); 465 return 0; 466} 467 468 469