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