Working on DeletePinhole() and GetPinholePackets()

This commit is contained in:
Thomas Bernard 2012-04-23 01:47:37 +02:00
parent 82355aca40
commit d27f35ccde
6 changed files with 129 additions and 108 deletions

View File

@ -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 */

View File

@ -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);

View File

@ -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, &timestamp);
&proto, &timestamp,
&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;
}

View File

@ -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, &timestamp);
iaddr, iaddrlen, iport, proto, &timestamp,
&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)
{

View File

@ -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);

View File

@ -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[] =
"<u:UpdatePinholeResponse "
"xmlns:u=\"urn:schemas-upnp-org:service:WANIPv6FirewallControl:1\">"
"</u:UpdatePinholeResponse>";
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[] =
"<u:DeletePinholeResponse "
@ -1554,73 +1557,81 @@ DeletePinhole(struct upnphttp * h, const char * action)
"</u:DeletePinholeResponse>";
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[] =
"<u:%sResponse "
"xmlns:u=\"%s\">"
"<IsWorking>%d</IsWorking>"
"</u:%sResponse>";
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[] =
"<u:%sResponse "
"xmlns:u=\"%s\">"
"<PinholePackets>%d</PinholePackets>"
"<PinholePackets>%u</PinholePackets>"
"</u:%sResponse>";
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