1: /* $Id: upnppinhole.c,v 1.1.1.1 2013/07/22 00:32:35 misho Exp $ */
2: /* MiniUPnP project
3: * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
4: * (c) 2006-2012 Thomas Bernard
5: * This software is subject to the conditions detailed
6: * in the LICENCE file provided within the distribution */
7:
8: #include <stdlib.h>
9: #include <string.h>
10: #include <syslog.h>
11: #include <sys/types.h>
12: #include <sys/socket.h>
13: #include <netinet/in.h>
14: #include <net/if.h>
15: #include <arpa/inet.h>
16:
17: #include <stdio.h>
18: #include <ctype.h>
19: #include <unistd.h>
20:
21: #include "macros.h"
22: #include "config.h"
23: #include "upnpredirect.h"
24: #include "upnpglobalvars.h"
25: #include "upnpevents.h"
26: #if defined(USE_NETFILTER)
27: #include "netfilter/iptpinhole.h"
28: #endif
29: #if defined(USE_PF)
30: #include "pf/pfpinhole.h"
31: #endif
32: #if defined(USE_IPF)
33: #endif
34: #if defined(USE_IPFW)
35: #endif
36:
37: #ifdef ENABLE_6FC_SERVICE
38: #if 0
39: int
40: upnp_check_outbound_pinhole(int proto, int * timeout)
41: {
42: int s, tmptimeout, tmptime_out;
43: switch(proto)
44: {
45: case IPPROTO_UDP:
46: s = retrieve_timeout("udp_timeout", timeout);
47: return s;
48: break;
49: case IPPROTO_UDPLITE:
50: s = retrieve_timeout("udp_timeout_stream", timeout);
51: return s;
52: break;
53: case IPPROTO_TCP:
54: s = retrieve_timeout("tcp_timeout_established", timeout);
55: return s;
56: break;
57: case 65535:
58: s = retrieve_timeout("udp_timeout", timeout);
59: s = retrieve_timeout("udp_timeout_stream", &tmptimeout);
60: s = retrieve_timeout("tcp_timeout_established", &tmptime_out);
61: if(tmptimeout<tmptime_out)
62: {
63: if(tmptimeout<*timeout)
64: *timeout = tmptimeout;
65: }
66: else
67: {
68: if(tmptime_out<*timeout)
69: *timeout = tmptimeout;
70: }
71: return s;
72: break;
73: default:
74: return -5;
75: break;
76: }
77: return 0;
78: }
79: #endif
80:
81: /* upnp_add_inboundpinhole()
82: * returns: 0 on success
83: * -1 failed to add pinhole
84: * -2 already created
85: * -3 inbound pinhole disabled
86: * TODO : return uid on success (positive) or error value (negative)
87: */
88: int
89: upnp_add_inboundpinhole(const char * raddr,
90: unsigned short rport,
91: const char * iaddr,
92: unsigned short iport,
93: int proto,
94: unsigned int leasetime,
95: int * uid)
96: {
97: int r;
98: time_t current;
99: unsigned int timestamp;
100: struct in6_addr address;
101:
102: if(inet_pton(AF_INET6, iaddr, &address) < 0)
103: {
104: syslog(LOG_ERR, "inet_pton(%s) : %m", iaddr);
105: return 0;
106: }
107: current = time(NULL);
108: timestamp = current + leasetime;
109: r = 0;
110:
111: #if 0
112: if(r == 1 && strcmp(iaddr, iaddr_old)==0 && iport==iport_old)
113: {
114: syslog(LOG_INFO, "Pinhole for inbound traffic from [%s]:%hu to [%s]:%hu with protocol %s already done. Updating it.", raddr, rport, iaddr_old, iport_old, protocol);
115: t = upnp_update_inboundpinhole(idfound, leaseTime);
116: *uid = atoi(idfound);
117: return t;
118: }
119: else
120: #endif
121: {
122: #if defined(USE_PF) || defined(USE_NETFILTER)
123: *uid = add_pinhole (0/*ext_if_name*/, raddr, rport,
124: iaddr, iport, proto, timestamp);
125: return 1;
126: #else
127: return -42; /* not implemented */
128: #endif
129: }
130: }
131:
132: #if 0
133: int
134: upnp_add_inboundpinhole_internal(const char * raddr, unsigned short rport,
135: const char * iaddr, unsigned short iport,
136: const char * proto, int * uid)
137: {
138: int c = 9999;
139: char cmd[256], cmd_raw[256], cuid[42];
140: #if 0
141: static const char cmdval_full_udptcp[] = "ip6tables -I %s %d -p %s -i %s -s %s --sport %hu -d %s --dport %hu -j ACCEPT";
142: static const char cmdval_udptcp[] = "ip6tables -I %s %d -p %s -i %s --sport %hu -d %s --dport %hu -j ACCEPT";
143: static const char cmdval_full_udplite[] = "ip6tables -I %s %d -p %s -i %s -s %s -d %s -j ACCEPT";
144: static const char cmdval_udplite[] = "ip6tables -I %s %d -p %s -i %s -d %s -j ACCEPT";
145: // raw table command
146: static const char cmdval_full_udptcp_raw[] = "ip6tables -t raw -I PREROUTING %d -p %s -i %s -s %s --sport %hu -d %s --dport %hu -j TRACE";
147: static const char cmdval_udptcp_raw[] = "ip6tables -t raw -I PREROUTING %d -p %s -i %s --sport %hu -d %s --dport %hu -j TRACE";
148: static const char cmdval_full_udplite_raw[] = "ip6tables -t raw -I PREROUTING %d -p %s -i %s -s %s -d %s -j TRACE";
149: static const char cmdval_udplite_raw[] = "ip6tables -t raw -I PREROUTING %d -p %s -i %s -d %s -j TRACE";
150: #endif
151: /*printf("%s\n", raddr);*/
152: if(raddr!=NULL)
153: {
154: #ifdef IPPROTO_UDPLITE
155: if(atoi(proto) == IPPROTO_UDPLITE)
156: {
157: /* snprintf(cmd, sizeof(cmd), cmdval_full_udplite, miniupnpd_forward_chain, line_number, proto, ext_if_name, raddr, iaddr);
158: snprintf(cmd_raw, sizeof(cmd_raw), cmdval_full_udplite_raw, line_number, proto, ext_if_name, raddr, iaddr);*/
159: }
160: else
161: #endif
162: {
163: /* snprintf(cmd, sizeof(cmd), cmdval_full_udptcp, miniupnpd_forward_chain, line_number, proto, ext_if_name, raddr, rport, iaddr, iport);
164: snprintf(cmd_raw, sizeof(cmd_raw), cmdval_full_udptcp_raw, line_number, proto, ext_if_name, raddr, rport, iaddr, iport);*/
165: }
166: }
167: else
168: {
169: #ifdef IPPROTO_UDPLITE
170: if(atoi(proto) == IPPROTO_UDPLITE)
171: {
172: /*snprintf(cmd, sizeof(cmd), cmdval_udplite, miniupnpd_forward_chain, line_number, proto, ext_if_name, iaddr);
173: snprintf(cmd_raw, sizeof(cmd_raw), cmdval_udplite_raw, line_number, proto, ext_if_name, iaddr);*/
174: }
175: else
176: #endif
177: {
178: /*snprintf(cmd, sizeof(cmd), cmdval_udptcp, miniupnpd_forward_chain, line_number, proto, ext_if_name, rport, iaddr, iport);
179: snprintf(cmd_raw, sizeof(cmd_raw), cmdval_udptcp_raw, line_number, proto, ext_if_name, rport, iaddr, iport);
180: */
181: }
182: }
183: #ifdef DEBUG
184: syslog(LOG_INFO, "Adding following ip6tables rule:");
185: syslog(LOG_INFO, " -> %s", cmd);
186: syslog(LOG_INFO, " -> %s", cmd_raw);
187: #endif
188: /* TODO Add a better checking error.*/
189: if(system(cmd) < 0 || system(cmd_raw) < 0)
190: {
191: return 0;
192: }
193: srand(time(NULL));
194: snprintf(cuid, sizeof(cuid), "%.4d", rand()%c);
195: *uid = atoi(cuid);
196: printf("\t_add_ uid: %s\n", cuid);
197: return 1;
198: }
199: #endif
200:
201: /* upnp_get_pinhole_info()
202: * return values :
203: * 0 OK
204: * -1 Internal error
205: * -2 NOT FOUND (no such entry)
206: * ..
207: * -42 Not implemented
208: */
209: int
210: upnp_get_pinhole_info(unsigned short uid,
211: char * raddr, int raddrlen,
212: unsigned short * rport,
213: char * iaddr, int iaddrlen,
214: unsigned short * iport,
215: int * proto,
216: unsigned int * leasetime,
217: unsigned int * packets)
218: {
219: /* Call Firewall specific code to get IPv6 pinhole infos */
220: #if defined(USE_PF) || defined(USE_NETFILTER)
221: int r;
222: unsigned int timestamp;
223: u_int64_t packets_tmp;
224: /*u_int64_t bytes_tmp;*/
225:
226: r = get_pinhole_info(uid, raddr, raddrlen, rport,
227: iaddr, iaddrlen, iport, proto,
228: leasetime ? ×tamp : NULL,
229: packets ? &packets_tmp : NULL,
230: NULL/*&bytes_tmp*/);
231: if(r >= 0) {
232: if(leasetime) {
233: time_t current_time;
234: current_time = time(NULL);
235: if(timestamp > (unsigned int)current_time)
236: *leasetime = timestamp - current_time;
237: else
238: *leasetime = 0;
239: }
240: if(packets)
241: *packets = (unsigned int)packets_tmp;
242: }
243: return r;
244: #else
245: UNUSED(uid);
246: UNUSED(raddr); UNUSED(raddrlen); UNUSED(rport);
247: UNUSED(iaddr); UNUSED(iaddrlen); UNUSED(iport);
248: UNUSED(proto); UNUSED(leasetime); UNUSED(packets);
249: return -42; /* not implemented */
250: #endif
251: }
252:
253: int
254: upnp_update_inboundpinhole(unsigned short uid, unsigned int leasetime)
255: {
256: #if defined(USE_PF) || defined(USE_NETFILTER)
257: unsigned int timestamp;
258:
259: timestamp = time(NULL) + leasetime;
260: return update_pinhole(uid, timestamp);
261: #else
262: UNUSED(uid); UNUSED(leasetime);
263:
264: return -42; /* not implemented */
265: #endif
266: }
267:
268: int
269: upnp_delete_inboundpinhole(unsigned short uid)
270: {
271: #if defined(USE_PF) || defined(USE_NETFILTER)
272: return delete_pinhole(uid);
273: #else
274: UNUSED(uid);
275:
276: return -1;
277: #endif
278: }
279:
280: #if 0
281: /*
282: * Result:
283: * 1: Found Result
284: * -4: No result
285: * -5: Result in another table
286: * -6: Result in another chain
287: * -7: Result in a chain not a rule
288: */
289: int
290: upnp_check_pinhole_working(const char * uid,
291: char * eaddr,
292: char * iaddr,
293: unsigned short * eport,
294: unsigned short * iport,
295: char * protocol,
296: int * rulenum_used)
297: {
298: /* TODO : to be implemented */
299: #if 0
300: FILE * fd;
301: time_t expire = time(NULL);
302: char buf[1024], filename[] = "/var/log/kern.log", expire_time[32]="";
303: int res = -4, str_len;
304:
305: str_len = strftime(expire_time, sizeof(expire_time), "%b %d %H:%M:%S", localtime(&expire));
306:
307: fd = fopen(filename, "r");
308: if (fd==NULL)
309: {
310: syslog(LOG_ERR, "Get_rule: could not open file: %s", filename);
311: return -1;
312: }
313:
314: syslog(LOG_INFO, "Get_rule: Starting getting info in file %s for %s\n", filename, uid);
315: buf[sizeof(buf)-1] = 0;
316: while(fgets(buf, sizeof(buf)-1, fd) != NULL && res != 1)
317: {
318: //printf("line: %s\n", buf);
319: char * r, * t, * c, * p;
320: // looking for something like filter:FORWARD:rule: or filter:MINIUPNPD:rule:
321: r = strstr(buf, ":rule:");
322: p = strstr(buf, ":policy:");
323: t = strstr(buf, "TRACE:"); // table pointeur
324: t += 7;
325: c = t + 7; // chain pointeur
326: if(r)
327: {
328: printf("\t** Found %.*s\n", 24 ,t);
329: char * src, * dst, * sport, * dport, * proto, * line;
330: char time[15]="", src_addr[40], dst_addr[40], proto_tmp[8];
331: int proto_int;
332: strncpy(time, buf, sizeof(time));
333: /*if(compare_time(time, expire_time)<0)
334: {
335: printf("\t\tNot corresponding time\n");
336: continue;
337: }*/
338:
339: line = r + 6;
340: printf("\trule line = %d\n", atoi(line));
341:
342: src = strstr(buf, "SRC=");
343: src += 4;
344: snprintf(src_addr, sizeof(src_addr), "%.*s", 39, src);
345: #if 0
346: del_char(src_addr);
347: add_char(src_addr);
348: #endif
349:
350: dst = strstr(buf, "DST=");
351: dst += 4;
352: snprintf(dst_addr, sizeof(dst_addr), "%.*s", 39, dst);
353: #if 0
354: del_char(dst_addr);
355: add_char(dst_addr);
356: #endif
357:
358: proto = strstr(buf, "PROTO=");
359: proto += 6;
360: proto_int = atoi(protocol);
361: if(proto_int == IPPROTO_UDP)
362: strcpy(proto_tmp, "UDP");
363: else if(proto_int == IPPROTO_TCP)
364: strcpy(proto_tmp, "TCP");
365: #ifdef IPPROTO_UDPLITE
366: else if(proto_int == IPPROTO_UDPLITE)
367: strcpy(proto_tmp, "UDPLITE");
368: #endif
369: else
370: strcpy(proto_tmp, "UnsupportedProto");
371:
372: // printf("\tCompare eaddr: %s // protocol: %s\n\t to addr: %s // protocol: %.*s\n", eaddr, proto_tmp, src_addr, strlen(proto_tmp), proto);
373: // printf("\tCompare iaddr: %s // protocol: %s\n\t to addr: %s // protocol: %.*s\n", iaddr, proto_tmp, dst_addr, strlen(proto_tmp), proto);
374: // TODO Check time
375: // Check that the paquet found in trace correspond to the one we are looking for
376: if( /*(strcmp(eaddr, src_addr) == 0) &&*/ (strcmp(iaddr, dst_addr) == 0) && (strncmp(proto_tmp, proto, strlen(proto_tmp))==0))
377: {
378: sport = strstr(buf, "SPT=");
379: sport += 4;
380: dport = strstr(buf, "DPT=");
381: dport += 4;
382: printf("\tCompare eport: %hu\n\t to port: %d\n", *eport, atoi(sport));
383: printf("\tCompare iport: %hu\n\t to port: %d\n", *iport, atoi(dport));
384: if(/*eport != atoi(sport) &&*/ *iport != atoi(dport))
385: {
386: printf("\t\tPort not corresponding\n");
387: continue;
388: }
389: printf("\ttable found: %.*s\n", 6, t);
390: printf("\tchain found: %.*s\n", 9, c);
391: // Check that the table correspond to the filter table
392: if(strncmp(t, "filter", 6)==0)
393: {
394: // Check that the table correspond to the MINIUPNP table
395: if(strncmp(c, "MINIUPNPD", 9)==0)
396: {
397: *rulenum_used = atoi(line);
398: res = 1;
399: }
400: else
401: {
402: res = -6;
403: continue;
404: }
405: }
406: else
407: {
408: res = -5;
409: continue;
410: }
411: }
412: else
413: {
414: printf("Packet information not corresponding\n");
415: continue;
416: }
417: }
418: if(!r && p)
419: {
420: printf("\t** Policy case\n");
421: char * src, * dst, * sport, * dport, * proto, * line;
422: char time[15], src_addr[40], dst_addr[40], proto_tmp[8];
423: int proto_int;
424: strncpy(time, buf, sizeof(time));
425: /*if(compare_time(time, expire_time)<0)
426: {
427: printf("\t\tNot corresponding time\n");
428: continue;
429: }*/
430:
431: line = p + 8;
432: printf("\trule line = %d\n", atoi(line));
433:
434: src = strstr(buf, "SRC=");
435: src += 4;
436: snprintf(src_addr, sizeof(src_addr), "%.*s", 39, src);
437: #if 0
438: del_char(src_addr);
439: add_char(src_addr);
440: #endif
441:
442: dst = strstr(buf, "DST=");
443: dst += 4;
444: snprintf(dst_addr, sizeof(dst_addr), "%.*s", 39, dst);
445: #if 0
446: del_char(dst_addr);
447: add_char(dst_addr);
448: #endif
449:
450: proto = strstr(buf, "PROTO=");
451: proto += 6;
452: proto_int = atoi(protocol);
453: if(proto_int == IPPROTO_UDP)
454: strcpy(proto_tmp, "UDP");
455: else if(proto_int == IPPROTO_TCP)
456: strcpy(proto_tmp, "TCP");
457: #ifdef IPPROTO_UDPLITE
458: else if(proto_int == IPPROTO_UDPLITE)
459: strcpy(proto_tmp, "UDPLITE");
460: #endif
461: else
462: strcpy(proto_tmp, "UnsupportedProto");
463:
464: // printf("\tCompare eaddr: %s // protocol: %s\n\t to addr: %s // protocol: %.*s\n", eaddr, proto_tmp, src_addr, strlen(proto_tmp), proto);
465: // printf("\tCompare iaddr: %s // protocol: %s\n\t to addr: %s // protocol: %.*s\n", iaddr, proto_tmp, dst_addr, strlen(proto_tmp), proto);
466: // Check that the paquet found in trace correspond to the one we are looking for
467: if( (strcmp(eaddr, src_addr) == 0) && (strcmp(iaddr, dst_addr) == 0) && (strncmp(proto_tmp, proto, 5)==0))
468: {
469: sport = strstr(buf, "SPT=");
470: sport += 4;
471: dport = strstr(buf, "DPT=");
472: dport += 4;
473: printf("\tCompare eport: %hu\n\t to port: %d\n", *eport, atoi(sport));
474: printf("\tCompare iport: %hu\n\t to port: %d\n", *iport, atoi(dport));
475: if(*eport != atoi(sport) && *iport != atoi(dport))
476: {
477: printf("\t\tPort not corresponding\n");
478: continue;
479: }
480: else
481: {
482: printf("Find a corresponding policy trace in the chain: %.*s\n", 10, c);
483: res = -7;
484: continue;
485: }
486: }
487: else
488: continue;
489: }
490: }
491: fclose(fd);
492: return res;
493: #else
494: return -42; /* to be implemented */
495: #endif
496: }
497: #endif
498:
499: int
500: upnp_clean_expired_pinholes(unsigned int * next_timestamp)
501: {
502: #if defined(USE_PF) || defined(USE_NETFILTER)
503: return clean_pinhole_list(next_timestamp);
504: #else
505: UNUSED(next_timestamp);
506:
507: return 0; /* nothing to do */
508: #endif
509: }
510: #endif
511:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>