/* $Id: upnppinhole.c,v 1.15 2021/08/21 08:12:49 nanard Exp $ */ /* vim: tabstop=4 shiftwidth=4 noexpandtab * MiniUPnP project * http://miniupnp.free.fr/ or https://miniupnp.tuxfamily.org/ * (c) 2006-2023 Thomas Bernard * This software is subject to the conditions detailed * in the LICENCE file provided within the distribution */ #include <stdlib.h> #include <string.h> #include <syslog.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <net/if.h> #include <arpa/inet.h> #include <stdio.h> #include <ctype.h> #include <unistd.h> #include "macros.h" #include "config.h" #include "upnpredirect.h" #include "upnpglobalvars.h" #include "upnpevents.h" #include "upnputils.h" #include "upnppinhole.h" #ifdef __APPLE__ /* XXX - Apple version of PF API seems to differ from what * pf/pfpinhole.c expects so don't use that at least.. */ #ifdef USE_PF #undef USE_PF #endif /* USE_PF */ #endif /* __APPLE__ */ #if defined(USE_NETFILTER) #include "netfilter/iptpinhole.h" #endif #if defined(USE_PF) #include "pf/pfpinhole.h" #endif #if defined(USE_IPF) #endif #if defined(USE_IPFW) #endif #ifdef ENABLE_LEASEFILE #include <sys/stat.h> #endif #ifdef ENABLE_UPNPPINHOLE #if 0 int upnp_check_outbound_pinhole(int proto, int * timeout) { int s, tmptimeout, tmptime_out; switch(proto) { case IPPROTO_UDP: s = retrieve_timeout("udp_timeout", timeout); return s; break; case IPPROTO_UDPLITE: s = retrieve_timeout("udp_timeout_stream", timeout); return s; break; case IPPROTO_TCP: s = retrieve_timeout("tcp_timeout_established", timeout); return s; break; case 65535: s = retrieve_timeout("udp_timeout", timeout); s = retrieve_timeout("udp_timeout_stream", &tmptimeout); s = retrieve_timeout("tcp_timeout_established", &tmptime_out); if(tmptimeout<tmptime_out) { if(tmptimeout<*timeout) *timeout = tmptimeout; } else { if(tmptime_out<*timeout) *timeout = tmptimeout; } return s; break; default: return -5; break; } return 0; } #endif #ifdef ENABLE_LEASEFILE /* proto_atoi() * convert the string "UDP" or "TCP" to IPPROTO_UDP and IPPROTO_UDP */ static int proto_atoi(const char * protocol) { int proto = IPPROTO_TCP; if(strcasecmp(protocol, "UDP") == 0) proto = IPPROTO_UDP; #ifdef IPPROTO_UDPLITE else if(strcasecmp(protocol, "UDPLITE") == 0) proto = IPPROTO_UDPLITE; #endif /* IPPROTO_UDPLITE */ return proto; } /* proto_itoa() * convert IPPROTO_UDP, IPPROTO_UDP, etc. to "UDP", "TCP" */ static const char * proto_itoa(int proto) { const char * protocol; switch(proto) { case IPPROTO_UDP: protocol = "UDP"; break; case IPPROTO_TCP: protocol = "TCP"; break; #ifdef IPPROTO_UDPLITE case IPPROTO_UDPLITE: protocol = "UDPLITE"; break; #endif /* IPPROTO_UDPLITE */ default: protocol = "*UNKNOWN*"; } return protocol; } static int lease_file6_add(const char * rem_client, unsigned short rem_port, const char * int_client, unsigned short int_port, int proto, int uid, const char * desc, unsigned int leaseduration) { unsigned int timestamp; FILE * fd; if (lease_file6 == NULL) return 0; fd = fopen( lease_file6, "a"); if (fd==NULL) { syslog(LOG_ERR, "could not open lease file: %s", lease_file); return -1; } timestamp = (leaseduration > 0) ? time(NULL) + leaseduration : 0; /* convert our time to unix time */ if (timestamp != 0) { timestamp -= upnp_time(); } fprintf(fd, "%s;%s;%hu;%s;%hu;%u;%u;%s\n", proto_itoa(proto), int_client, int_port, rem_client, rem_port, uid, timestamp, desc); fclose(fd); return 0; } static int lease_file6_update(int uid, unsigned int leaseduration) { FILE* fd, *fdt; char * p, * p2; unsigned short int_port, rem_port; char * proto; char * int_client; char * desc; char * rem_client; unsigned int timestamp_rule; unsigned int timestamp; char line[128]; char tmpfilename[128]; int uid_rule; int tmp; if (lease_file6 == NULL) return 0; if (strlen(lease_file6) + 7 > sizeof(tmpfilename)) { syslog(LOG_ERR, "Lease filename is too long"); return -1; } snprintf( tmpfilename, sizeof(tmpfilename), "%sXXXXXX", lease_file6); fd = fopen( lease_file6, "r"); if (fd==NULL) { return 0; } tmp = mkstemp(tmpfilename); if (tmp==-1) { fclose(fd); syslog(LOG_ERR, "could not open temporary lease file"); return -1; } fchmod(tmp, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); fdt = fdopen(tmp, "a"); timestamp = (leaseduration > 0) ? time(NULL) + leaseduration : 0; /* convert our time to unix time */ if (timestamp != 0) { timestamp -= upnp_time(); } while(fgets(line, sizeof(line), fd)) { syslog(LOG_DEBUG, "parsing lease file line '%s'", line); proto = line; p = strchr(line, ';'); if(!p) { syslog(LOG_ERR, "unrecognized data in lease file"); continue; } *(p++) = '\0'; p2 = strchr(p, ';'); if(!p2) { syslog(LOG_ERR, "unrecognized data in lease file"); continue; } *(p2++) = '\0'; int_port = (unsigned short)atoi(p2); int_client = p; p = strchr(p2, ';'); if(!p) { syslog(LOG_ERR, "unrecognized data in lease file"); continue; } *(p++) = '\0'; p2 = strchr(p, ';'); if(!p2) { syslog(LOG_ERR, "unrecognized data in lease file"); continue; } *(p2++) = '\0'; rem_port = (unsigned short)atoi(p2); rem_client = p; p = strchr(p2, ';'); if(!p) { syslog(LOG_ERR, "unrecognized data in lease file"); continue; } *(p++) = '\0'; p2 = strchr(p, ';'); if(!p2) { syslog(LOG_ERR, "unrecognized data in lease file"); continue; } *(p2++) = '\0'; desc = strchr(p2, ';'); uid_rule = atoi(p); if(!desc) { syslog(LOG_ERR, "unrecognized data in lease file"); continue; } *(desc++) = '\0'; timestamp_rule = (unsigned int)strtoul(p2, NULL, 10); if (uid == uid_rule) { timestamp_rule = timestamp; } fprintf(fdt, "%s;%s;%hu;%s;%hu;%u;%u;%s\n", proto, int_client, int_port, rem_client, rem_port, uid, timestamp_rule, desc); } fclose(fdt); fclose(fd); if (rename(tmpfilename, lease_file6) < 0) { syslog(LOG_ERR, "could not rename temporary lease file to %s", lease_file6); remove(tmpfilename); } return 0; } static int lease_file6_remove(const char * int_client, unsigned short int_port, int proto, int uid) { FILE* fd, *fdt; int tmp, uid_tmp; char buf[512], buf2[512]; char str[32]; char tmpfilename[128]; char *p, *p2; int str_size, buf_size; if (lease_file6 == NULL) return 0; if (strlen(lease_file6) + 7 > sizeof(tmpfilename)) { syslog(LOG_ERR, "Lease filename is too long"); return -1; } snprintf( tmpfilename, sizeof(tmpfilename), "%sXXXXXX", lease_file6); fd = fopen( lease_file6, "r"); if (fd==NULL) { return 0; } snprintf( str, sizeof(str), "%s;%s;%u", proto_itoa(proto), int_client, int_port); str_size = strlen(str); tmp = mkstemp(tmpfilename); if (tmp==-1) { fclose(fd); syslog(LOG_ERR, "could not open temporary lease file"); return -1; } fchmod(tmp, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); fdt = fdopen(tmp, "a"); buf[sizeof(buf)-1] = 0; while( fgets(buf, sizeof(buf)-1, fd) != NULL) { buf_size = strlen(buf); if (uid > 0) { strncpy(buf2, buf, buf_size); // Internal Host p = strchr(buf2, ';'); *(p++) = '\0'; // Internal Port p = strchr(p, ';'); *(p++) = '\0'; // External Host p = strchr(p, ';'); *(p++) = '\0'; // External Port p = strchr(p, ';'); *(p++) = '\0'; // uid p = strchr(p, ';'); *(p++) = '\0'; p2 = strchr(p, ';'); *(p2++) = '\0'; uid_tmp = atoi(p); if (uid != uid_tmp) { fwrite(buf, buf_size, 1, fdt); } } else if (buf_size < str_size || strncmp(str, buf, str_size)!=0) { fwrite(buf, buf_size, 1, fdt); } } fclose(fdt); fclose(fd); if (rename(tmpfilename, lease_file6) < 0) { syslog(LOG_ERR, "could not rename temporary lease file to %s", lease_file6); remove(tmpfilename); } return 0; } int lease_file6_expire() { FILE* fd, *fdt; char * p, * p2; int tmp; char buf[512]; char line[512]; char tmpfilename[128]; char * desc; int buf_size; unsigned int timestamp; time_t current_unix_time; if (lease_file6 == NULL) return 0; if (strlen(lease_file6) + 7 > sizeof(tmpfilename)) { syslog(LOG_ERR, "Lease filename is too long"); return -1; } snprintf( tmpfilename, sizeof(tmpfilename), "%sXXXXXX", lease_file6); fd = fopen( lease_file6, "r"); if (fd==NULL) { return 0; } current_unix_time = time(NULL); tmp = mkstemp(tmpfilename); if (tmp==-1) { fclose(fd); syslog(LOG_ERR, "could not open temporary lease file"); return -1; } fchmod(tmp, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); fdt = fdopen(tmp, "a"); buf[sizeof(buf)-1] = 0; while(fgets(line, sizeof(line), fd)) { strncpy(buf, line, sizeof(buf)); syslog(LOG_DEBUG, "Expire: parsing lease file line '%s'", line); // Internal Host p = strchr(line, ';'); if(!p) { syslog(LOG_ERR, "unrecognized data in lease file"); continue; } *(p++) = '\0'; // Internal Port p2 = strchr(p, ';'); if(!p2) { syslog(LOG_ERR, "unrecognized data in lease file"); continue; } *(p2++) = '\0'; // External Host p = strchr(p2, ';'); if(!p) { syslog(LOG_ERR, "unrecognized data in lease file"); continue; } *(p++) = '\0'; // External Port p2 = strchr(p, ';'); if(!p2) { syslog(LOG_ERR, "unrecognized data in lease file"); continue; } *(p2++) = '\0'; // uid p = strchr(p2, ';'); if(!p) { syslog(LOG_ERR, "unrecognized data in lease file"); continue; } *(p++) = '\0'; // Timestamp p2 = strchr(p, ';'); if(!p2) { syslog(LOG_ERR, "unrecognized data in lease file"); continue; } *(p2++) = '\0'; // descr desc = strchr(p2, ';'); if(!desc) { syslog(LOG_ERR, "unrecognized data in lease file"); continue; } *(desc++) = '\0'; /*timestamp = (unsigned int)atoi(p2);*/ timestamp = (unsigned int)strtoul(p2, NULL, 10); syslog(LOG_DEBUG, "Expire: timestamp is '%u'", timestamp); syslog(LOG_DEBUG, "Expire: current timestamp is '%u'", (unsigned int)current_unix_time); if((timestamp > 0 && timestamp <= (unsigned int)current_unix_time) || timestamp <= 0) { continue; } buf_size = strlen(buf); fwrite(buf, buf_size, 1, fdt); } fclose(fdt); fclose(fd); if (rename(tmpfilename, lease_file6) < 0) { syslog(LOG_ERR, "could not rename temporary lease file to %s", lease_file6); remove(tmpfilename); } return 0; } /* reload_from_lease_file() * read lease_file and add the rules contained */ int reload_from_lease_file6() { FILE * fd; char * p, * p2; unsigned short int_port, rem_port; char * proto; char * int_client; char * desc; char * rem_client; unsigned int leaseduration; unsigned int timestamp; time_t current_time; time_t current_unix_time; char line[128]; int r, uid; if(!lease_file6) return -1; fd = fopen( lease_file6, "r"); if (fd==NULL) { syslog(LOG_ERR, "could not open lease file: %s", lease_file6); return -1; } if(unlink(lease_file6) < 0) { syslog(LOG_WARNING, "could not unlink file %s : %m", lease_file6); } current_time = upnp_time(); current_unix_time = time(NULL); while(fgets(line, sizeof(line), fd)) { syslog(LOG_DEBUG, "parsing lease file line '%s'", line); proto = line; p = strchr(line, ';'); if(!p) { syslog(LOG_ERR, "unrecognized data in lease file"); continue; } *(p++) = '\0'; p2 = strchr(p, ';'); if(!p2) { syslog(LOG_ERR, "unrecognized data in lease file"); continue; } *(p2++) = '\0'; int_port = (unsigned short)atoi(p2); int_client = p; p = strchr(p2, ';'); if(!p) { syslog(LOG_ERR, "unrecognized data in lease file"); continue; } *(p++) = '\0'; p2 = strchr(p, ';'); if(!p2) { syslog(LOG_ERR, "unrecognized data in lease file"); continue; } *(p2++) = '\0'; rem_port = (unsigned short)atoi(p2); rem_client = p; p = strchr(p2, ';'); if(!p) { syslog(LOG_ERR, "unrecognized data in lease file"); continue; } *(p++) = '\0'; p2 = strchr(p, ';'); if(!p2) { syslog(LOG_ERR, "unrecognized data in lease file"); continue; } *(p2++) = '\0'; desc = strchr(p2, ';'); uid = atoi(p); if(!desc) { syslog(LOG_ERR, "unrecognized data in lease file"); continue; } *(desc++) = '\0'; /*timestamp = (unsigned int)atoi(p2);*/ timestamp = (unsigned int)strtoul(p2, NULL, 10); /* trim description */ while(isspace(*desc)) desc++; p = desc; while(*(p+1)) p++; while(isspace(*p) && (p > desc)) *(p--) = '\0'; if(timestamp > 0) { if(timestamp <= (unsigned int)current_unix_time) { syslog(LOG_NOTICE, "already expired lease in lease file"); continue; } else { leaseduration = timestamp - current_unix_time; timestamp = leaseduration + current_time; /* convert to our time */ } } else { leaseduration = 0; /* default value */ } r = upnp_add_inboundpinhole(rem_client, rem_port, int_client, int_port, proto_atoi(proto), desc, leaseduration, &uid); if(r == -1) { syslog(LOG_ERR, "Failed to add %s:%hu -> %s:%hu protocol %s", rem_client, rem_port, int_client, int_port, proto); } else if(r == -2) { /* Add the redirection again to the lease file */ lease_file6_add(rem_client, rem_port, int_client, int_port, proto_atoi(proto), uid, desc, timestamp); } } fclose(fd); return 0; } #endif int upnp_find_inboundpinhole(const char * raddr, unsigned short rport, const char * iaddr, unsigned short iport, int proto, char * desc, int desc_len, unsigned int * leasetime) { #if defined(USE_PF) || defined(USE_NETFILTER) int uid; uid = find_pinhole(NULL, raddr, rport, iaddr, iport, proto, desc, desc_len, leasetime); return uid; #else return -42; #endif } /* upnp_add_inboundpinhole() * returns: 1 on success * -1 Pinhole space exhausted * -4 invalid arguments * -42 not implemented * TODO : return uid on success (positive) or error value (negative) */ int upnp_add_inboundpinhole(const char * raddr, unsigned short rport, const char * iaddr, unsigned short iport, int proto, char * desc, unsigned int leasetime, int * uid) { int r; time_t current; unsigned int timestamp; struct in6_addr address; r = inet_pton(AF_INET6, iaddr, &address); if(r <= 0) { syslog(LOG_ERR, "inet_pton(%d, %s, %p) FAILED", AF_INET6, iaddr, &address); return -4; } current = upnp_time(); timestamp = current + leasetime; r = 0; *uid = upnp_find_inboundpinhole(raddr, rport, iaddr, iport, proto, NULL, 0, NULL); if(*uid >= 0) { syslog(LOG_INFO, "Pinhole for inbound traffic from [%s]:%hu to [%s]:%hu with proto %d found uid=%d. Updating it.", raddr, rport, iaddr, iport, proto, *uid); r = upnp_update_inboundpinhole(*uid, leasetime); #ifdef ENABLE_LEASEFILE if (r >= 0) { lease_file6_remove(iaddr, iport, proto, -1); lease_file6_add(raddr, rport, iaddr, iport, proto, *uid, desc, timestamp); } #endif /* ENABLE_LEASEFILE */ return (r >= 0) ? 1 : r; } #if defined(USE_PF) || defined(USE_NETFILTER) *uid = add_pinhole (ext_if_name6, raddr, rport, iaddr, iport, proto, desc, timestamp); #ifdef ENABLE_LEASEFILE if (*uid >= 0) { lease_file6_remove(iaddr, iport, proto, -1); lease_file6_add(raddr, rport, iaddr, iport, proto, *uid, desc, timestamp); } #endif /* ENABLE_LEASEFILE */ return *uid >= 0 ? 1 : -1; #else return -42; /* not implemented */ #endif } #if 0 int upnp_add_inboundpinhole_internal(const char * raddr, unsigned short rport, const char * iaddr, unsigned short iport, const char * proto, int * uid) { int c = 9999; char cmd[256], cmd_raw[256], cuid[42]; #if 0 static const char cmdval_full_udptcp[] = "ip6tables -I %s %d -p %s -i %s -s %s --sport %hu -d %s --dport %hu -j ACCEPT"; static const char cmdval_udptcp[] = "ip6tables -I %s %d -p %s -i %s --sport %hu -d %s --dport %hu -j ACCEPT"; static const char cmdval_full_udplite[] = "ip6tables -I %s %d -p %s -i %s -s %s -d %s -j ACCEPT"; static const char cmdval_udplite[] = "ip6tables -I %s %d -p %s -i %s -d %s -j ACCEPT"; // raw table command 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"; static const char cmdval_udptcp_raw[] = "ip6tables -t raw -I PREROUTING %d -p %s -i %s --sport %hu -d %s --dport %hu -j TRACE"; static const char cmdval_full_udplite_raw[] = "ip6tables -t raw -I PREROUTING %d -p %s -i %s -s %s -d %s -j TRACE"; static const char cmdval_udplite_raw[] = "ip6tables -t raw -I PREROUTING %d -p %s -i %s -d %s -j TRACE"; #endif /*printf("%s\n", raddr);*/ if(raddr!=NULL) { #ifdef IPPROTO_UDPLITE if(atoi(proto) == IPPROTO_UDPLITE) { /* snprintf(cmd, sizeof(cmd), cmdval_full_udplite, miniupnpd_forward_chain, line_number, proto, ext_if_name, raddr, iaddr); snprintf(cmd_raw, sizeof(cmd_raw), cmdval_full_udplite_raw, line_number, proto, ext_if_name, raddr, iaddr);*/ } else #endif { /* snprintf(cmd, sizeof(cmd), cmdval_full_udptcp, miniupnpd_forward_chain, line_number, proto, ext_if_name, raddr, rport, iaddr, iport); snprintf(cmd_raw, sizeof(cmd_raw), cmdval_full_udptcp_raw, line_number, proto, ext_if_name, raddr, rport, iaddr, iport);*/ } } else { #ifdef IPPROTO_UDPLITE if(atoi(proto) == IPPROTO_UDPLITE) { /*snprintf(cmd, sizeof(cmd), cmdval_udplite, miniupnpd_forward_chain, line_number, proto, ext_if_name, iaddr); snprintf(cmd_raw, sizeof(cmd_raw), cmdval_udplite_raw, line_number, proto, ext_if_name, iaddr);*/ } else #endif { /*snprintf(cmd, sizeof(cmd), cmdval_udptcp, miniupnpd_forward_chain, line_number, proto, ext_if_name, rport, iaddr, iport); snprintf(cmd_raw, sizeof(cmd_raw), cmdval_udptcp_raw, line_number, proto, ext_if_name, rport, iaddr, iport); */ } } #ifdef DEBUG syslog(LOG_INFO, "Adding following ip6tables rule:"); syslog(LOG_INFO, " -> %s", cmd); syslog(LOG_INFO, " -> %s", cmd_raw); #endif /* TODO Add a better checking error.*/ if(system(cmd) < 0 || system(cmd_raw) < 0) { return 0; } srand(time(NULL)); snprintf(cuid, sizeof(cuid), "%.4d", rand()%c); *uid = atoi(cuid); printf("\t_add_ uid: %s\n", cuid); return 1; } #endif /* upnp_get_pinhole_info() * return values : * 0 OK * -1 Internal error * -2 NOT FOUND (no such entry) * .. * -42 Not implemented */ int upnp_get_pinhole_info(unsigned short uid, char * raddr, int raddrlen, unsigned short * rport, char * iaddr, int iaddrlen, unsigned short * iport, int * proto, char * desc, int desclen, unsigned int * leasetime, unsigned int * packets) { /* Call Firewall specific code to get IPv6 pinhole infos */ #if defined(USE_PF) || defined(USE_NETFILTER) int r; unsigned int timestamp; u_int64_t packets_tmp; /*u_int64_t bytes_tmp;*/ r = get_pinhole_info(uid, raddr, raddrlen, rport, iaddr, iaddrlen, iport, proto, desc, desclen, leasetime ? ×tamp : NULL, packets ? &packets_tmp : NULL, NULL/*&bytes_tmp*/); if(r >= 0) { if(leasetime) { time_t current_time; current_time = upnp_time(); if(timestamp > (unsigned int)current_time) *leasetime = timestamp - current_time; else *leasetime = 0; } if(packets) *packets = (unsigned int)packets_tmp; } return r; #else UNUSED(uid); UNUSED(raddr); UNUSED(raddrlen); UNUSED(rport); UNUSED(iaddr); UNUSED(iaddrlen); UNUSED(iport); UNUSED(proto); UNUSED(desc); UNUSED(desclen); UNUSED(leasetime); UNUSED(packets); return -42; /* not implemented */ #endif } int upnp_get_pinhole_uid_by_index(int index) { #if defined (USE_NETFILTER) return get_pinhole_uid_by_index(index); #else UNUSED(index); return -42; #endif /* defined (USE_NETFILTER) */ } int upnp_update_inboundpinhole(unsigned short uid, unsigned int leasetime) { #if defined(USE_PF) || defined(USE_NETFILTER) unsigned int timestamp; int ret; timestamp = upnp_time() + leasetime; ret = update_pinhole(uid, timestamp); #ifdef ENABLE_LEASEFILE if (ret == 0) lease_file6_update(uid, timestamp); #endif return ret; #else UNUSED(uid); UNUSED(leasetime); return -42; /* not implemented */ #endif } int upnp_delete_inboundpinhole(unsigned short uid) { #if defined(USE_PF) || defined(USE_NETFILTER) int ret; ret = delete_pinhole(uid); #ifdef ENABLE_LEASEFILE if (ret == 0) lease_file6_remove((const char *)"*", 0, 0, uid); #endif return ret; #else UNUSED(uid); return -1; #endif } #if 0 /* * Result: * 1: Found Result * -4: No result * -5: Result in another table * -6: Result in another chain * -7: Result in a chain not a rule */ int upnp_check_pinhole_working(const char * uid, char * eaddr, char * iaddr, unsigned short * eport, unsigned short * iport, char * protocol, int * rulenum_used) { /* TODO : to be implemented */ #if 0 FILE * fd; time_t expire = upnp_time(); char buf[1024], filename[] = "/var/log/kern.log", expire_time[32]=""; int res = -4, str_len; str_len = strftime(expire_time, sizeof(expire_time), "%b %d %H:%M:%S", localtime(&expire)); fd = fopen(filename, "r"); if (fd==NULL) { syslog(LOG_ERR, "Get_rule: could not open file: %s", filename); return -1; } syslog(LOG_INFO, "Get_rule: Starting getting info in file %s for %s\n", filename, uid); buf[sizeof(buf)-1] = 0; while(fgets(buf, sizeof(buf)-1, fd) != NULL && res != 1) { //printf("line: %s\n", buf); char * r, * t, * c, * p; // looking for something like filter:FORWARD:rule: or filter:MINIUPNPD:rule: r = strstr(buf, ":rule:"); p = strstr(buf, ":policy:"); t = strstr(buf, "TRACE:"); // table pointeur t += 7; c = t + 7; // chain pointeur if(r) { printf("\t** Found %.*s\n", 24 ,t); char * src, * dst, * sport, * dport, * proto, * line; char time[15]="", src_addr[40], dst_addr[40], proto_tmp[8]; int proto_int; strncpy(time, buf, sizeof(time)); /*if(compare_time(time, expire_time)<0) { printf("\t\tNot corresponding time\n"); continue; }*/ line = r + 6; printf("\trule line = %d\n", atoi(line)); src = strstr(buf, "SRC="); src += 4; snprintf(src_addr, sizeof(src_addr), "%.*s", 39, src); #if 0 del_char(src_addr); add_char(src_addr); #endif dst = strstr(buf, "DST="); dst += 4; snprintf(dst_addr, sizeof(dst_addr), "%.*s", 39, dst); #if 0 del_char(dst_addr); add_char(dst_addr); #endif proto = strstr(buf, "PROTO="); proto += 6; proto_int = atoi(protocol); if(proto_int == IPPROTO_UDP) strcpy(proto_tmp, "UDP"); else if(proto_int == IPPROTO_TCP) strcpy(proto_tmp, "TCP"); #ifdef IPPROTO_UDPLITE else if(proto_int == IPPROTO_UDPLITE) strcpy(proto_tmp, "UDPLITE"); #endif else strcpy(proto_tmp, "UnsupportedProto"); // printf("\tCompare eaddr: %s // protocol: %s\n\t to addr: %s // protocol: %.*s\n", eaddr, proto_tmp, src_addr, strlen(proto_tmp), proto); // printf("\tCompare iaddr: %s // protocol: %s\n\t to addr: %s // protocol: %.*s\n", iaddr, proto_tmp, dst_addr, strlen(proto_tmp), proto); // TODO Check time // Check that the paquet found in trace correspond to the one we are looking for if( /*(strcmp(eaddr, src_addr) == 0) &&*/ (strcmp(iaddr, dst_addr) == 0) && (strncmp(proto_tmp, proto, strlen(proto_tmp))==0)) { sport = strstr(buf, "SPT="); sport += 4; dport = strstr(buf, "DPT="); dport += 4; printf("\tCompare eport: %hu\n\t to port: %d\n", *eport, atoi(sport)); printf("\tCompare iport: %hu\n\t to port: %d\n", *iport, atoi(dport)); if(/*eport != atoi(sport) &&*/ *iport != atoi(dport)) { printf("\t\tPort not corresponding\n"); continue; } printf("\ttable found: %.*s\n", 6, t); printf("\tchain found: %.*s\n", 9, c); // Check that the table correspond to the filter table if(strncmp(t, "filter", 6)==0) { // Check that the table correspond to the MINIUPNP table if(strncmp(c, "MINIUPNPD", 9)==0) { *rulenum_used = atoi(line); res = 1; } else { res = -6; continue; } } else { res = -5; continue; } } else { printf("Packet information not corresponding\n"); continue; } } if(!r && p) { printf("\t** Policy case\n"); char * src, * dst, * sport, * dport, * proto, * line; char time[15], src_addr[40], dst_addr[40], proto_tmp[8]; int proto_int; strncpy(time, buf, sizeof(time)); /*if(compare_time(time, expire_time)<0) { printf("\t\tNot corresponding time\n"); continue; }*/ line = p + 8; printf("\trule line = %d\n", atoi(line)); src = strstr(buf, "SRC="); src += 4; snprintf(src_addr, sizeof(src_addr), "%.*s", 39, src); #if 0 del_char(src_addr); add_char(src_addr); #endif dst = strstr(buf, "DST="); dst += 4; snprintf(dst_addr, sizeof(dst_addr), "%.*s", 39, dst); #if 0 del_char(dst_addr); add_char(dst_addr); #endif proto = strstr(buf, "PROTO="); proto += 6; proto_int = atoi(protocol); if(proto_int == IPPROTO_UDP) strcpy(proto_tmp, "UDP"); else if(proto_int == IPPROTO_TCP) strcpy(proto_tmp, "TCP"); #ifdef IPPROTO_UDPLITE else if(proto_int == IPPROTO_UDPLITE) strcpy(proto_tmp, "UDPLITE"); #endif else strcpy(proto_tmp, "UnsupportedProto"); // printf("\tCompare eaddr: %s // protocol: %s\n\t to addr: %s // protocol: %.*s\n", eaddr, proto_tmp, src_addr, strlen(proto_tmp), proto); // printf("\tCompare iaddr: %s // protocol: %s\n\t to addr: %s // protocol: %.*s\n", iaddr, proto_tmp, dst_addr, strlen(proto_tmp), proto); // Check that the paquet found in trace correspond to the one we are looking for if( (strcmp(eaddr, src_addr) == 0) && (strcmp(iaddr, dst_addr) == 0) && (strncmp(proto_tmp, proto, 5)==0)) { sport = strstr(buf, "SPT="); sport += 4; dport = strstr(buf, "DPT="); dport += 4; printf("\tCompare eport: %hu\n\t to port: %d\n", *eport, atoi(sport)); printf("\tCompare iport: %hu\n\t to port: %d\n", *iport, atoi(dport)); if(*eport != atoi(sport) && *iport != atoi(dport)) { printf("\t\tPort not corresponding\n"); continue; } else { printf("Find a corresponding policy trace in the chain: %.*s\n", 10, c); res = -7; continue; } } else continue; } } fclose(fd); return res; #else return -42; /* to be implemented */ #endif } #endif int upnp_clean_expired_pinholes(unsigned int * next_timestamp) { int ret = 0; #if defined(USE_PF) || defined(USE_NETFILTER) ret = clean_pinhole_list(next_timestamp); #else UNUSED(next_timestamp); #endif #ifdef ENABLE_LEASEFILE lease_file6_expire(); #endif return ret; } #endif /* ENABLE_UPNPPINHOLE */