diff --git a/miniupnpd/pf/pfpinhole.c b/miniupnpd/pf/pfpinhole.c index 500f022..ed8ce06 100644 --- a/miniupnpd/pf/pfpinhole.c +++ b/miniupnpd/pf/pfpinhole.c @@ -1,4 +1,4 @@ -/* $Id: pfpinhole.c,v 1.12 2012/04/22 00:55:51 nanard Exp $ */ +/* $Id: pfpinhole.c,v 1.15 2012/04/22 23:36:41 nanard Exp $ */ /* MiniUPnP project * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ * (c) 2012 Thomas Bernard @@ -199,13 +199,14 @@ int delete_pinhole(unsigned short uid) } } /* not found */ - return -1; + return -2; } int get_pinhole(unsigned short uid, char * rem_host, int rem_hostlen, unsigned short * rem_port, char * int_client, int int_clientlen, unsigned short * int_port, - int * proto, unsigned int * timestamp) + int * proto, unsigned int * timestamp, + u_int64_t * packets, u_int64_t * bytes) { int i, n; struct pfioc_rule pr; @@ -239,23 +240,40 @@ int get_pinhole(unsigned short uid, p = tmp_label; strsep(&p, " "); if(0 == strcmp(tmp_label, label_start)) { - if(inet_ntop(AF_INET6, &pr.rule.src.addr.v.a.addr.v6, rem_host, rem_hostlen) == NULL) { - return -2; + if(rem_host && (inet_ntop(AF_INET6, &pr.rule.src.addr.v.a.addr.v6, rem_host, rem_hostlen) == NULL)) { + return -1; } - *rem_port = ntohs(pr.rule.src.port[0]); - if(inet_ntop(AF_INET6, &pr.rule.dst.addr.v.a.addr.v6, int_client, int_clientlen) == NULL) { - return -2; + if(rem_port) + *rem_port = ntohs(pr.rule.src.port[0]); + if(int_client && (inet_ntop(AF_INET6, &pr.rule.dst.addr.v.a.addr.v6, int_client, int_clientlen) == NULL)) { + return -1; } - *int_port = ntohs(pr.rule.dst.port[0]); - *proto = pr.rule.proto; - sscanf(p, "ts-%u", timestamp); + if(int_port) + *int_port = ntohs(pr.rule.dst.port[0]); + if(proto) + *proto = pr.rule.proto; + if(timestamp) + sscanf(p, "ts-%u", timestamp); +#ifdef PFRULE_INOUT_COUNTS + if(packets) + *packets = pr.rule.packets[0] + pr.rule.packets[1]; + if(bytes) + *bytes = pr.rule.bytes[0] + pr.rule.bytes[1]; +#else + if(packets) + *packets = pr.rule.packets; + if(bytes) + *bytes = pr.rule.bytes; +#endif return 0; } } /* not found */ - return -1; + return -2; } +/* return the number of rules removed + * or a negative integer in case of error */ int clean_pinhole_list(unsigned int * next_timestamp) { int i; @@ -265,6 +283,7 @@ int clean_pinhole_list(unsigned int * next_timestamp) int uid; unsigned int min_ts = UINT_MAX; int min_uid = INT_MAX, max_uid = -1; + int n = 0; if(dev<0) { syslog(LOG_ERR, "pf device is not open"); @@ -303,6 +322,7 @@ int clean_pinhole_list(unsigned int * next_timestamp) syslog(LOG_ERR, "ioctl(dev, DIOCCHANGERULE, ...) PF_CHANGE_REMOVE: %m"); return -1; } + n++; #ifndef PF_NEWSTYLE pr.rule.action = PF_PASS; #endif @@ -329,7 +349,7 @@ int clean_pinhole_list(unsigned int * next_timestamp) next_uid = 1; } } - return 0; + return n; /* number of rules removed */ } #endif /* ENABLE_IPV6 */ diff --git a/miniupnpd/pf/pfpinhole.h b/miniupnpd/pf/pfpinhole.h index b9d7a20..97ce19b 100644 --- a/miniupnpd/pf/pfpinhole.h +++ b/miniupnpd/pf/pfpinhole.h @@ -1,4 +1,4 @@ -/* $Id: pfpinhole.h,v 1.6 2012/04/22 00:55:51 nanard Exp $ */ +/* $Id: pfpinhole.h,v 1.7 2012/04/22 23:08:51 nanard Exp $ */ /* MiniUPnP project * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ * (c) 2012 Thomas Bernard @@ -18,7 +18,8 @@ int delete_pinhole(unsigned short uid); int get_pinhole(unsigned short uid, char * rem_host, int rem_hostlen, unsigned short * rem_port, char * int_client, int int_clientlen, unsigned short * int_port, - int * proto, unsigned int * timestamp); + int * proto, unsigned int * timestamp, + u_int64_t * packets, u_int64_t * bytes); int clean_pinhole_list(unsigned int * next_timestamp); diff --git a/miniupnpd/pf/testpfpinhole.c b/miniupnpd/pf/testpfpinhole.c index e622e62..e09199c 100644 --- a/miniupnpd/pf/testpfpinhole.c +++ b/miniupnpd/pf/testpfpinhole.c @@ -1,4 +1,4 @@ -/* $Id: testpfpinhole.c,v 1.9 2012/04/22 00:55:51 nanard Exp $ */ +/* $Id: testpfpinhole.c,v 1.10 2012/04/22 23:12:51 nanard Exp $ */ /* MiniUPnP project * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ * (c) 2012 Thomas Bernard @@ -30,17 +30,20 @@ static int print_pinhole(int uid) unsigned short int_port; int proto; unsigned int timestamp; + u_int64_t packets, bytes; r = get_pinhole((unsigned short)uid, rem_host, sizeof(rem_host), &rem_port, int_client, sizeof(int_client), &int_port, - &proto, ×tamp); + &proto, ×tamp, + &packets, &bytes); if(r < 0) { fprintf(stderr, "get_pinhole(%d) returned %d\n", uid, r); } else { printf("pinhole %d : [%s]:%hu => [%s]:%hu proto=%d ts=%u\n", uid, rem_host, rem_port, int_client, int_port, proto, timestamp); + printf(" packets=%llu bytes=%llu\n", packets, bytes); } return r; } diff --git a/miniupnpd/upnpredirect.c b/miniupnpd/upnpredirect.c index c0b37e3..8cae9e8 100644 --- a/miniupnpd/upnpredirect.c +++ b/miniupnpd/upnpredirect.c @@ -1,4 +1,4 @@ -/* $Id: upnpredirect.c,v 1.70 2012/04/22 00:55:46 nanard Exp $ */ +/* $Id: upnpredirect.c,v 1.72 2012/04/22 23:25:22 nanard Exp $ */ /* MiniUPnP project * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ * (c) 2006-2012 Thomas Bernard @@ -763,6 +763,14 @@ upnp_add_inboundpinhole_internal(const char * raddr, unsigned short rport, return 1; } +/* 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, @@ -770,14 +778,17 @@ upnp_get_pinhole_info(unsigned short uid, char * iaddr, int iaddrlen, unsigned short * iport, int * proto, - unsigned int * leasetime) + unsigned int * leasetime, + unsigned int * packets) { /* Call Firewall specific code to get IPv6 pinhole infos */ #ifdef USE_PF int r; unsigned int timestamp; + u_int64_t packets_tmp, bytes_tmp; r = get_pinhole(uid, raddr, raddrlen, rport, - iaddr, iaddrlen, iport, proto, ×tamp); + iaddr, iaddrlen, iport, proto, ×tamp, + &packets_tmp, &bytes_tmp); if(r >= 0) { time_t current_time; current_time = time(NULL); @@ -785,6 +796,8 @@ upnp_get_pinhole_info(unsigned short uid, *leasetime = timestamp - current_time; else *leasetime = 0; + if(packets) + *packets = (unsigned int)packets_tmp; } return r; #else @@ -1040,26 +1053,6 @@ upnp_check_pinhole_working(const char * uid, #endif } -int -upnp_get_pinhole_packets(const char * uid, int * packets) -{ - /* TODO : to be implemented */ -#if 0 - int line=0, r; - char cmd[256]; - r = check_rule_from_file(uid, &line); - if(r < 0) - return r; - else - { - snprintf(cmd, sizeof(cmd), "ip6tables -L MINIUPNPD %d -v", line); - return retrieve_packets(cmd, &line, packets); - } -#else - return 0; -#endif -} - int upnp_clean_expired_pinholes(unsigned int * next_timestamp) { diff --git a/miniupnpd/upnpredirect.h b/miniupnpd/upnpredirect.h index dca2344..3710bd4 100644 --- a/miniupnpd/upnpredirect.h +++ b/miniupnpd/upnpredirect.h @@ -1,4 +1,4 @@ -/* $Id: upnpredirect.h,v 1.30 2012/04/22 00:55:46 nanard Exp $ */ +/* $Id: upnpredirect.h,v 1.31 2012/04/22 23:08:48 nanard Exp $ */ /* MiniUPnP project * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ * (c) 2006-2012 Thomas Bernard @@ -136,7 +136,8 @@ upnp_get_pinhole_info(unsigned short uid, char * iaddr, int iaddrlen, unsigned short * iport, int * proto, - unsigned int * leasetime); + unsigned int * leasetime, + unsigned int * packets); /* update the lease time */ int @@ -150,10 +151,6 @@ upnp_delete_inboundpinhole(unsigned short uid); int upnp_check_pinhole_working(const char * uid, char * eaddr, char * iaddr, unsigned short * eport, unsigned short * iport, char * protocol, int * rulenum_used); -/* number of packets that went through the pinhole */ -int -upnp_get_pinhole_packets(const char * uid, int * packets); - /* ? */ int upnp_clean_expired_pinholes(unsigned int * next_timestamp); diff --git a/miniupnpd/upnpsoap.c b/miniupnpd/upnpsoap.c index 757bbbf..cd62848 100644 --- a/miniupnpd/upnpsoap.c +++ b/miniupnpd/upnpsoap.c @@ -1,4 +1,4 @@ -/* $Id: upnpsoap.c,v 1.99 2012/04/22 00:02:46 nanard Exp $ */ +/* $Id: upnpsoap.c,v 1.104 2012/04/22 23:36:20 nanard Exp $ */ /* MiniUPnP project * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ * (c) 2006-2012 Thomas Bernard @@ -1224,7 +1224,6 @@ PinholeVerification(struct upnphttp * h, char * int_ip, unsigned short int_port) { inet_ntop(AF_INET6, (struct in6_addr *) p, int_ip, sizeof(struct in6_addr)); result_ip = *((struct in6_addr *) p); - /* fprintf(stderr, "upnpsoap / AddPinhole: assuming int addr = %s", int_ip); */ /* TODO : deal with more than one ip per hostname */ break; } @@ -1432,15 +1431,17 @@ clear_and_exit: static void UpdatePinhole(struct upnphttp * h, const char * action) { - int r, n; + int r/*, n*/; static const char resp[] = "" ""; struct NameValueParserData data; const char * uid, * leaseTime; +#if 0 char iaddr[40], proto[6], lt[12]; unsigned short iport; +#endif int ltime = -1; if(CheckStatus(h)==0) @@ -1461,6 +1462,7 @@ UpdatePinhole(struct upnphttp * h, const char * action) /* Check that client is not deleting an pinhole * it doesn't have access to, because of its public access */ +#if 0 n = upnp_get_pinhole_info(0, 0, iaddr, &iport, proto, uid, lt); if (n > 0) { @@ -1470,6 +1472,7 @@ UpdatePinhole(struct upnphttp * h, const char * action) return ; } } +#endif syslog(LOG_INFO, "%s: (inbound) updating lease duration to %s for pinhole with ID: %s", action, leaseTime, uid); @@ -1546,7 +1549,7 @@ GetOutboundPinholeTimeout(struct upnphttp * h, const char * action) static void DeletePinhole(struct upnphttp * h, const char * action) { - int r, n; + int n; static const char resp[] = ""; struct NameValueParserData data; - const char * uid; - char iaddr[40], proto[6], lt[12]; + const char * uid_str; + char iaddr[INET6_ADDRSTRLEN]; + int proto; unsigned short iport; + unsigned int leasetime; + int uid; if(CheckStatus(h)==0) return; ParseNameValue(h->req_buf + h->req_contentoff, h->req_contentlen, &data); - uid = GetValueFromNameValueList(&data, "UniqueID"); + uid_str = GetValueFromNameValueList(&data, "UniqueID"); + uid = uid_str ? atoi(uid_str) : -1; + ClearNameValueList(&data); - if(!uid || atoi(uid) < 0 || atoi(uid) > 65535) + if(uid < 0 || uid > 65535) { - ClearNameValueList(&data); SoapError(h, 402, "Invalid Args"); return; } /* Check that client is not deleting an pinhole * it doesn't have access to, because of its public access */ - n = upnp_get_pinhole_info(0, 0, iaddr, &iport, proto, uid, lt); - if (n > 0) + n = upnp_get_pinhole_info(uid, NULL, 0, NULL, + iaddr, sizeof(iaddr), &iport, + &proto, &leasetime, NULL); + if (n >= 0) { - if(PinholeVerification(h, iaddr, iport)==0) - { - ClearNameValueList(&data); - return ; - } + if(!PinholeVerification(h, iaddr, iport)) + return; } - - syslog(LOG_INFO, "%s: (inbound) delete pinhole with ID: %s", action, uid); - - r = upnp_delete_inboundpinhole(uid); - - if(r < 0) + else if(n == -2) { - syslog(LOG_INFO, "%s: (inbound) failed to remove pinhole with ID: %s", action, uid); - if(r==-4) - SoapError(h, 704, "NoSuchEntry"); - else - SoapError(h, 501, "ActionFailed"); + SoapError(h, 704, "NoSuchEntry"); + return; } else { - syslog(LOG_INFO, "%s: (inbound) pinhole successfully removed", action); - BuildSendAndCloseSoapResp(h, resp, sizeof(resp)-1); + SoapError(h, 501, "ActionFailed"); + return; } - ClearNameValueList(&data); + + n = upnp_delete_inboundpinhole(uid); + if(n < 0) + { + syslog(LOG_INFO, "%s: (inbound) failed to remove pinhole with ID: %d", + action, uid); + SoapError(h, 501, "ActionFailed"); + return; + } + syslog(LOG_INFO, "%s: (inbound) pinhole with ID %d successfully removed", + action, uid); + BuildSendAndCloseSoapResp(h, resp, sizeof(resp)-1); } static void CheckPinholeWorking(struct upnphttp * h, const char * action) { - int r, d; - +#if 0 static const char resp[] = "" "%d" ""; - char body[512]; int bodylen; + int r, d; +#endif struct NameValueParserData data; const char * uid; +#if 0 char eaddr[40], iaddr[40], proto[6], lt[12]; unsigned short eport, iport; int isWorking = 0; +#endif if(CheckStatus(h)==0) return; @@ -1637,6 +1648,7 @@ CheckPinholeWorking(struct upnphttp * h, const char * action) /* Check that client is not checking a pinhole * it doesn't have access to, because of its public access */ +#if 0 r = upnp_get_pinhole_info(eaddr, eport, iaddr, &iport, proto, uid, lt); if (r > 0) { @@ -1694,6 +1706,7 @@ CheckPinholeWorking(struct upnphttp * h, const char * action) SoapError(h, 704, "NoSuchEntry"); } else +#endif { SoapError(h, 501, "ActionFailed"); ClearNameValueList(&data); @@ -1705,66 +1718,60 @@ CheckPinholeWorking(struct upnphttp * h, const char * action) static void GetPinholePackets(struct upnphttp * h, const char * action) { - int r, n; - static const char resp[] = "" - "%d" + "%u" ""; - char body[512]; int bodylen; struct NameValueParserData data; - const char * uid; - char iaddr[40], proto[6], lt[12]; + const char * uid_str; + int n; + char iaddr[INET6_ADDRSTRLEN]; unsigned short iport; - int pinholePackets = 0; + unsigned int packets = 0; + int uid; + int proto; + unsigned int leasetime; if(CheckStatus(h)==0) return; ParseNameValue(h->req_buf + h->req_contentoff, h->req_contentlen, &data); - uid = GetValueFromNameValueList(&data, "UniqueID"); + uid_str = GetValueFromNameValueList(&data, "UniqueID"); + uid = uid_str ? atoi(uid_str) : -1; + ClearNameValueList(&data); - if(!uid) + if(uid < 0 || uid > 65535) { - ClearNameValueList(&data); SoapError(h, 402, "Invalid Args"); return; } /* Check that client is not getting infos of a pinhole * it doesn't have access to, because of its public access */ - r = upnp_get_pinhole_info(0, 0, iaddr, &iport, proto, uid, lt); - if (r > 0) + n = upnp_get_pinhole_info(uid, NULL, 0, NULL, + iaddr, sizeof(iaddr), &iport, + &proto, &leasetime, &packets); + if (n >= 0) { if(PinholeVerification(h, iaddr, iport)==0) { - ClearNameValueList(&data); return ; } } - - n = upnp_get_pinhole_packets(uid, &pinholePackets); - if(n > 0) - { - bodylen = snprintf(body, sizeof(body), resp, - action, "urn:schemas-upnp-org:service:WANIPv6FirewallControl:1", - pinholePackets, action); - BuildSendAndCloseSoapResp(h, body, bodylen); - } +#if 0 else if(r == -4 || r == -1) { SoapError(h, 704, "NoSuchEntry"); } - else - { - SoapError(h, 501, "ActionFailed"); - ClearNameValueList(&data); - return ; - } - ClearNameValueList(&data); +#endif + + bodylen = snprintf(body, sizeof(body), resp, + action, "urn:schemas-upnp-org:service:WANIPv6FirewallControl:1", + packets, action); + BuildSendAndCloseSoapResp(h, body, bodylen); } #endif