File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / miniupnpd / upnppinhole.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Mon Jul 22 00:32:35 2013 UTC (11 years, 5 months ago) by misho
Branches: elwix, MAIN
CVS tags: v1_8p0, v1_8, HEAD
1.8

    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 ? &timestamp : 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>