libsodium: Needed for Dnscrypto-proxy Release 1.3.0
[tomato.git] / release / src / router / rc / forward.c
blob1f5717e4dcb4fe1dd5594cdf93f569030822a7eb
1 /*
3 Tomato Firmware
4 Copyright (C) 2006-2009 Jonathan Zarate
6 */
8 #include "rc.h"
10 #include <arpa/inet.h>
12 extern char chain_wan_prerouting[];
14 static const char tcpudp[2][4] = {"tcp", "udp"};
16 void ipt_forward(ipt_table_t table)
18 char *nv, *nvp, *b;
19 const char *proto, *saddr, *xports, *iport, *iaddr, *desc;
20 const char *c;
21 const char *mdport;
22 int i, n;
23 char ip[64];
24 char src[64];
26 nvp = nv = strdup(nvram_safe_get("portforward"));
27 if (!nv) return;
29 while ((b = strsep(&nvp, ">")) != NULL) {
31 [<1.01] 1<3<30,40-45<60<5<desc
32 [<1.07] 1<3<30,40-45<60<192.168.1.5<desc
34 1<3<71.72.73.74<30,40-45<60<192.168.1.5<desc
36 1 = enabled
37 3 = tcp & udp
38 71.72.73.74 = src addr
39 30,40-45 = ext port
40 60 = int port
41 192.168.1.5 = dst addr
42 desc = desc
45 n = vstrsep(b, "<", &c, &proto, &saddr, &xports, &iport, &iaddr, &desc);
46 if ((n < 6) || (*c != '1')) continue;
47 if (n == 6) {
48 // <1.07
49 desc = iaddr;
50 iaddr = iport;
51 iport = xports;
52 xports = saddr;
53 saddr = "";
56 if (!ipt_addr(src, sizeof(src), saddr, "src", IPT_V4, 1, "IPv4 port forwarding", desc))
57 continue;
59 if (strchr(iaddr, '.') == NULL && strtol(iaddr, NULL, 10) > 0) {
60 // < 1.01: 5 -> 192.168.1.5
61 strcpy(ip, lan_cclass);
62 strlcat(ip, iaddr, sizeof(ip));
64 else {
65 if (host_addrtypes(iaddr, IPT_V4) != IPT_V4) {
66 ipt_log_unresolved(iaddr, "IPv4", "IPv4 port forwarding", desc);
67 continue;
69 strlcpy(ip, iaddr, sizeof(ip));
72 mdport = (strchr(xports, ',') != NULL) ? "-m multiport --dports" : "--dport";
73 for (i = 0; i < 2; ++i) {
74 if ((1 << i) & (*proto - '0')) {
75 c = tcpudp[i];
76 if (table == IPT_TABLE_NAT) {
77 ipt_write("-A %s -p %s %s %s %s -j DNAT --to-destination %s%s%s\n",
78 chain_wan_prerouting,
80 src,
81 mdport, xports,
82 ip, *iport ? ":" : "", iport);
84 if (nvram_get_int("nf_loopback") == 1) {
85 for (n = 0; n < wanfaces.count; ++n) {
86 if (*(wanfaces.iface[n].name)) {
87 ipt_write("-A POSTROUTING -p %s %s %s -s %s/%s -d %s -j SNAT --to-source %s\n",
89 mdport, *iport ? iport : xports,
90 nvram_safe_get("lan_ipaddr"), // corrected by ipt
91 nvram_safe_get("lan_netmask"),
92 ip,
93 wanfaces.iface[n].ip);
98 else { // filter
99 ipt_write("-A wanin %s -p %s -m %s -d %s %s %s -j %s\n",
100 src,
104 mdport, *iport ? iport : xports,
105 chain_in_accept);
110 free(nv);
113 void ipt_triggered(ipt_table_t table)
115 char *nv, *nvp, *b;
116 const char *proto, *mports, *fports;
117 const char *c;
118 char *p;
119 int i;
120 int first;
121 char s[256];
123 nvp = nv = strdup(nvram_safe_get("trigforward"));
124 if (!nv) return;
126 first = 1;
127 while ((b = strsep(&nvp, ">")) != NULL) {
128 if ((vstrsep(b, "<", &c, &proto, &mports, &fports) != 4) || (*c != '1')) continue;
129 for (i = 0; i < 2; ++i) {
130 if ((1 << i) & (*proto - '0')) {
131 if (first) {
132 // should only be created if there is at least one enabled
134 if (table == IPT_TABLE_NAT) {
135 ipt_write("-A %s -j TRIGGER --trigger-type dnat\n", chain_wan_prerouting);
136 goto QUIT;
139 ipt_write(":triggers - [0:0]\n"
140 "-A wanout -j triggers\n"
141 "-A wanin -j TRIGGER --trigger-type in\n");
143 first = 0;
145 strlcpy(s, mports, sizeof(s));
146 if ((p = strchr(s, ':')) != NULL) *p = '-';
147 if ((p = strchr(fports, ':')) != NULL) *p = '-';
148 c = tcpudp[i];
149 ipt_write("-A triggers -p %s -m %s --dport %s "
150 "-j TRIGGER --trigger-type out --trigger-proto %s --trigger-match %s --trigger-relate %s\n",
151 c, c, mports,
152 c, s, fports);
153 // can't use multiport... trigger-match must be set to the same
154 // ports as dport since it's used to refresh timer during inbound -- zzz
159 QUIT:
160 free(nv);
163 #ifdef TCONFIG_IPV6
164 void ip6t_forward(void)
166 char *nv, *nvp, *b;
167 const char *proto, *saddr, *daddr, *dports, *desc;
168 const char *c;
169 const char *mdport;
170 int i;
171 char src[128];
173 nvp = nv = strdup(nvram_safe_get("ipv6_portforward"));
174 if (!nv) return;
176 while ((b = strsep(&nvp, ">")) != NULL) {
178 1<3<2001:23:45:67::/64<2600:abc:def:123::1<30,40-45<desc
180 1 = enabled
181 3 = tcp & udp
182 2001:23:45:67::/64 = src addr
183 2600:abc:def:123::1 = dst addr (optional)
184 30,40-45 = dst port
185 desc = desc
187 if ((vstrsep(b, "<", &c, &proto, &saddr, &daddr, &dports, &desc) != 6) || (*c != '1')) continue;
189 if (!ipt_addr(src, sizeof(src), saddr, "src", IPT_V6, 1, "IPv6 port forwarding", desc))
190 continue;
192 if ((*daddr) && (host_addrtypes(daddr, IPT_V6) != IPT_V6)) {
193 ipt_log_unresolved(daddr, "IPv6", "IPv6 port forwarding", desc);
194 continue;
197 mdport = (strchr(dports, ',') != NULL) ? "-m multiport --dports" : "--dport";
198 for (i = 0; i < 2; ++i) {
199 if ((1 << i) & (*proto - '0')) {
200 c = tcpudp[i];
201 ip6t_write("-A wanin %s -p %s -m %s %s%s %s %s -j %s\n",
202 src,
205 (*daddr) ? "-d " : "", daddr,
206 mdport, dports,
207 chain_in_accept);
211 free(nv);
213 #endif