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