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