Tomato 1.28
[tomato.git] / release / src / router / miniupnpd / ipfw / ipfwrdr.c
blobd7a3c0e1e67cfa2218cc4a56e3c6003b752c4bc4
1 /* MiniUPnP project
2 * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
3 * (c) 2007 Darren Reed
4 * This software is subject to the conditions detailed
5 * in the LICENCE file provided within the distribution */
7 #include <sys/param.h>
8 #include <sys/types.h>
9 #include <sys/file.h>
12 // This is a workaround for <sys/uio.h> troubles on FreeBSD, HPUX, OpenBSD.
13 // Needed here because on some systems <sys/uio.h> gets included by things
14 // like <sys/socket.h>
16 #ifndef _KERNEL
17 # define ADD_KERNEL
18 # define _KERNEL
19 # define KERNEL
20 #endif
21 #ifdef __OpenBSD__
22 struct file;
23 #endif
24 #include <sys/uio.h>
25 #ifdef ADD_KERNEL
26 # undef _KERNEL
27 # undef KERNEL
28 #endif
30 #include <sys/time.h>
31 #include <sys/socket.h>
32 #include <sys/syslog.h>
33 #include <sys/ioctl.h>
34 #include <net/if.h>
35 #if __FreeBSD_version >= 300000
36 # include <net/if_var.h>
37 #endif
38 #include <netinet/in.h>
39 #include <netinet/in_systm.h>
40 #include <netinet/ip.h>
41 #include <netinet/ip_icmp.h>
42 #ifndef TCP_PAWS_IDLE // IRIX
43 # include <netinet/tcp.h>
44 #endif
45 #include <netinet/tcp.h>
46 #include <netinet/udp.h>
47 #include <arpa/inet.h>
49 #include <sys/types.h>
50 #include <sys/queue.h>
51 #include <sys/socket.h>
52 #include <errno.h>
53 #include <limits.h>
54 #include <netdb.h>
55 #include <stdlib.h>
56 #include <fcntl.h>
57 #include <syslog.h>
58 #include <stddef.h>
59 #include <stdio.h>
60 #if !defined(__SVR4) && !defined(__svr4__) && defined(sun)
61 # include <strings.h>
62 #endif
63 #include <string.h>
64 #include <unistd.h>
65 #include <netinet/ip_fw.h>
66 #include "ipfwaux.h"
68 #include "../config.h"
70 #ifndef __P
71 # ifdef __STDC__
72 # define __P(x) x
73 # else
74 # define __P(x) ()
75 # endif
76 #endif
77 #ifndef __STDC__
78 # undef const
79 # define const
80 #endif
83 // SunOS4
85 #if defined(sun) && !defined(__SVR4) && !defined(__svr4__)
86 extern int ioctl __P((int, int, void *));
87 #endif
89 #include "../upnpglobalvars.h"
92 int init_redirect(void) {
93 ipfw_exec(IP_FW_INIT, NULL, 0);
94 return 0;
97 void shutdown_redirect(void) {
98 ipfw_exec(IP_FW_TERM, NULL, 0);
101 int add_redirect_rule2(
102 const char * ifname,
103 unsigned short eport,
104 const char * iaddr,
105 unsigned short iport,
106 int proto,
107 const char * desc)
109 struct ip_fw rule;
111 if (ipfw_validate_protocol(proto) < 0)
112 return -1;
113 if (ipfw_validate_ifname(ifname) < 0)
114 return -1;
116 memset(&rule, 0, sizeof(struct ip_fw));
117 rule.version = IP_FW_CURRENT_API_VERSION;
118 //rule.fw_number = 1000; // rule number
119 rule.context = (void *)desc; // TODO keep this?
120 rule.fw_prot = proto; // protocol
121 rule.fw_flg |= IP_FW_F_IIFACE; // interfaces to check
122 rule.fw_flg |= IP_FW_F_IIFNAME; // interfaces to check by name
123 rule.fw_flg |= (IP_FW_F_IN | IP_FW_F_OUT); // packet direction
124 rule.fw_flg |= IP_FW_F_FWD; // forward action
125 #ifdef USE_IFNAME_IN_RULES
126 if (ifname != NULL) {
127 strcpy(rule.fw_in_if.fu_via_if.name, ifname); // src interface
128 rule.fw_in_if.fu_via_if.unit = -1;
130 #endif
131 if (inet_aton(iaddr, &rule.fw_out_if.fu_via_ip) == 0) {
132 syslog(LOG_ERR, "inet_aton(): %m");
133 return -1;
135 memcpy(&rule.fw_dst, &rule.fw_out_if.fu_via_ip, sizeof(struct in_addr));
136 memcpy(&rule.fw_fwd_ip.sin_addr, &rule.fw_out_if.fu_via_ip, sizeof(struct in_addr));
137 rule.fw_dmsk.s_addr = INADDR_BROADCAST;
138 IP_FW_SETNDSTP(&rule, 1); // number of external ports
139 rule.fw_uar.fw_pts[0] = eport; // external port
140 rule.fw_fwd_ip.sin_port = iport; // internal port
142 return ipfw_exec(IP_FW_ADD, &rule, sizeof(rule));
145 /* get_redirect_rule()
146 * return value : 0 success (found)
147 * -1 = error or rule not found */
148 int get_redirect_rule(
149 const char * ifname,
150 unsigned short eport,
151 int proto,
152 char * iaddr,
153 int iaddrlen,
154 unsigned short * iport,
155 char * desc,
156 int desclen,
157 u_int64_t * packets,
158 u_int64_t * bytes)
160 int i, count_rules, total_rules = 0;
161 struct ip_fw * rules = NULL;
163 if (ipfw_validate_protocol(proto) < 0)
164 return -1;
165 if (ipfw_validate_ifname(ifname) < 0)
166 return -1;
168 do {
169 count_rules = ipfw_fetch_ruleset(&rules, &total_rules, 10);
170 if (count_rules < 0)
171 goto error;
172 } while (count_rules == 10);
174 for (i=0; i<total_rules-1; i++) {
175 const struct ip_fw const * ptr = &rules[i];
176 if (proto == ptr->fw_prot && eport == ptr->fw_uar.fw_pts[0]) {
177 if (packets != NULL)
178 *packets = ptr->fw_pcnt;
179 if (bytes != NULL)
180 *bytes = ptr->fw_bcnt;
181 if (iport != NULL)
182 *iport = ptr->fw_fwd_ip.sin_port;
183 if (desc != NULL && desclen > 0)
184 strlcpy(desc, "", desclen); // TODO should we copy ptr->context?
185 if (iaddr != NULL && iaddrlen > 0) {
186 if (inet_ntop(AF_INET, &ptr->fw_out_if.fu_via_ip, iaddr, iaddrlen) == NULL) {
187 syslog(LOG_ERR, "inet_ntop(): %m");
188 goto error;
191 // And what if we found more than 1 matching rule?
192 ipfw_free_ruleset(&rules);
193 return 0;
197 error:
198 if (rules != NULL)
199 ipfw_free_ruleset(&rules);
200 return -1;
203 int delete_redirect_rule(
204 const char * ifname,
205 unsigned short eport,
206 int proto)
208 int i, count_rules, total_rules = 0;
209 struct ip_fw * rules = NULL;
211 if (ipfw_validate_protocol(proto) < 0)
212 return -1;
213 if (ipfw_validate_ifname(ifname) < 0)
214 return -1;
216 do {
217 count_rules = ipfw_fetch_ruleset(&rules, &total_rules, 10);
218 if (count_rules < 0)
219 goto error;
220 } while (count_rules == 10);
222 for (i=0; i<total_rules-1; i++) {
223 const struct ip_fw const * ptr = &rules[i];
224 if (proto == ptr->fw_prot && eport == ptr->fw_uar.fw_pts[0]) {
225 if (ipfw_exec(IP_FW_DEL, (struct ip_fw *)ptr, sizeof(*ptr)) < 0)
226 goto error;
227 // And what if we found more than 1 matching rule?
228 ipfw_free_ruleset(&rules);
229 return 0;
233 error:
234 if (rules != NULL)
235 ipfw_free_ruleset(&rules);
236 return -1;
239 int add_filter_rule2(
240 const char * ifname,
241 const char * iaddr,
242 unsigned short eport,
243 unsigned short iport,
244 int proto,
245 const char * desc)
247 return -1;
250 int delete_filter_rule(
251 const char * ifname,
252 unsigned short eport,
253 int proto)
255 return -1;
258 int get_redirect_rule_by_index(
259 int index,
260 char * ifname,
261 unsigned short * eport,
262 char * iaddr,
263 int iaddrlen,
264 unsigned short * iport,
265 int * proto,
266 char * desc,
267 int desclen,
268 u_int64_t * packets,
269 u_int64_t * bytes)
271 int total_rules = 0;
272 struct ip_fw * rules = NULL;
274 if (index < 0) // TODO shouldn't we also validate the maximum?
275 return -1;
277 ipfw_fetch_ruleset(&rules, &total_rules, index + 1);
279 if (total_rules == index + 1) {
280 const struct ip_fw const * ptr = &rules[index];
281 if (proto != NULL)
282 *proto = ptr->fw_prot;
283 if (eport != NULL)
284 *eport = ptr->fw_uar.fw_pts[0];
285 if (iport != NULL)
286 *iport = ptr->fw_fwd_ip.sin_port;
287 if (ifname != NULL)
288 strlcpy(ifname, ptr->fw_in_if.fu_via_if.name, IFNAMSIZ); // TODO does it work?
289 if (packets != NULL)
290 *packets = ptr->fw_pcnt;
291 if (bytes != NULL)
292 *bytes = ptr->fw_bcnt;
293 if (iport != NULL)
294 *iport = ptr->fw_fwd_ip.sin_port;
295 if (desc != NULL && desclen > 0)
296 strlcpy(desc, "", desclen); // TODO should we copy ptr->context?
297 if (iaddr != NULL && iaddrlen > 0) {
298 if (inet_ntop(AF_INET, &ptr->fw_out_if.fu_via_ip, iaddr, iaddrlen) == NULL) {
299 syslog(LOG_ERR, "inet_ntop(): %m");
300 goto error;
303 ipfw_free_ruleset(&rules);
304 return 0;
307 error:
308 if (rules != NULL)
309 ipfw_free_ruleset(&rules);
310 return -1;