From f934bf5d17b7246607f04a4b430fcbb758072de8 Mon Sep 17 00:00:00 2001 From: Thomas Bernard Date: Wed, 18 Apr 2012 22:53:51 +0200 Subject: [PATCH] Start to code IPv6 "pinhole" for pf Also update tests in miniupnpd/pf/ --- miniupnpd/pf/Makefile | 13 ++++- miniupnpd/pf/obsdrdr.c | 8 +-- miniupnpd/pf/obsdrdr.h | 2 +- miniupnpd/pf/pfpinhole.c | 110 +++++++++++++++++++++++++++++++++++ miniupnpd/pf/pfpinhole.h | 17 ++++++ miniupnpd/pf/testobsdrdr.c | 45 ++++++++------ miniupnpd/pf/testpfpinhole.c | 36 ++++++++++++ 7 files changed, 205 insertions(+), 26 deletions(-) create mode 100644 miniupnpd/pf/pfpinhole.c create mode 100644 miniupnpd/pf/pfpinhole.h create mode 100644 miniupnpd/pf/testpfpinhole.c diff --git a/miniupnpd/pf/Makefile b/miniupnpd/pf/Makefile index aebd324..d0d28c9 100644 --- a/miniupnpd/pf/Makefile +++ b/miniupnpd/pf/Makefile @@ -1,7 +1,7 @@ -# $Id: Makefile,v 1.2 2010/03/08 17:10:37 nanard Exp $ +# $Id: Makefile,v 1.4 2012/04/18 20:45:33 nanard Exp $ # made for GNU Make (and BSD make) -CFLAGS = -Wall -g -DTEST -EXECUTABLES = testobsdrdr +CFLAGS = -Wall -g -ansi -DTEST +EXECUTABLES = testobsdrdr testpfpinhole all: $(EXECUTABLES) @@ -11,7 +11,14 @@ clean: testobsdrdr: testobsdrdr.o obsdrdr.o $(CC) $(CFLAGS) -o $@ $> +testpfpinhole: testpfpinhole.o obsdrdr.o pfpinhole.o + $(CC) $(CFLAGS) -o $@ $> + obsdrdr.o: obsdrdr.c obsdrdr.h +pfpinhole.o: pfpinhole.c pfpinhole.h + testobsdrdr.o: testobsdrdr.c obsdrdr.h +testpfpinhole.o: testpfpinhole.c pfpinhole.h + diff --git a/miniupnpd/pf/obsdrdr.c b/miniupnpd/pf/obsdrdr.c index c989c2d..da26f82 100644 --- a/miniupnpd/pf/obsdrdr.c +++ b/miniupnpd/pf/obsdrdr.c @@ -1,7 +1,7 @@ -/* $Id: obsdrdr.c,v 1.71 2012/03/11 08:46:19 nanard Exp $ */ +/* $Id: obsdrdr.c,v 1.73 2012/04/18 20:45:12 nanard Exp $ */ /* MiniUPnP project * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2006-2010 Thomas Bernard + * (c) 2006-2012 Thomas Bernard * This software is subject to the conditions detailed * in the LICENCE file provided within the distribution */ @@ -102,7 +102,7 @@ remove_timestamp_entry(unsigned short eport, int proto) } /* /dev/pf when opened */ -static int dev = -1; +int dev = -1; /* shutdown_redirect() : * close the /dev/pf device */ @@ -868,7 +868,7 @@ list_rules(void) perror("DIOCGETRULE"); printf(" %s %s %d:%d -> %d:%d proto %d keep_state=%d action=%d\n", pr.rule.ifname, - inet_ntop(AF_INET, &pr.rule.src.addr.v.a.addr.v4.s_addr, buf, 32); + inet_ntop(AF_INET, &pr.rule.src.addr.v.a.addr.v4.s_addr, buf, 32), (int)ntohs(pr.rule.dst.port[0]), (int)ntohs(pr.rule.dst.port[1]), #ifndef PF_NEWSTYLE diff --git a/miniupnpd/pf/obsdrdr.h b/miniupnpd/pf/obsdrdr.h index 65a3d98..4386cc5 100644 --- a/miniupnpd/pf/obsdrdr.h +++ b/miniupnpd/pf/obsdrdr.h @@ -1,4 +1,4 @@ -/* $Id: obsdrdr.h,v 1.19 2011/06/04 15:47:18 nanard Exp $ */ +/* $Id: obsdrdr.h,v 1.20 2012/03/05 20:36:20 nanard Exp $ */ /* MiniUPnP project * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ * (c) 2006 Thomas Bernard diff --git a/miniupnpd/pf/pfpinhole.c b/miniupnpd/pf/pfpinhole.c new file mode 100644 index 0000000..5d6da02 --- /dev/null +++ b/miniupnpd/pf/pfpinhole.c @@ -0,0 +1,110 @@ +/* $Id: pfpinhole.c,v 1.2 2012/04/18 20:45:33 nanard Exp $ */ +/* MiniUPnP project + * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ + * (c) 2006-2012 Thomas Bernard + * This software is subject to the conditions detailed + * in the LICENCE file provided within the distribution */ + +#include +#include +#include +#include +#include +#include +#include +#ifdef __DragonFly__ +#include +#else +#include +#endif +#include +#include +#include +#include +#include +#include +#include + +#include "../config.h" +#include "../upnpglobalvars.h" + +/* /dev/pf when opened */ +extern int dev; + +int add_pinhole (const char * ifname, + const char * rem_host, unsigned short rem_port, + const char * int_client, unsigned short int_port, + int proto) +{ + int r; + struct pfioc_rule pcr; + + if(dev<0) { + syslog(LOG_ERR, "pf device is not open"); + return -1; + } + r = 0; + memset(&pcr, 0, sizeof(pcr)); + { + pcr.rule.direction = PF_IN; + pcr.rule.action = PF_PASS; + pcr.rule.af = AF_INET6; +#ifdef USE_IFNAME_IN_RULES + if(ifname) + strlcpy(pcr.rule.ifname, ifname, IFNAMSIZ); +#endif + pcr.rule.proto = proto; + + pcr.rule.quick = 1;/*(GETFLAG(PFNOQUICKRULESMASK))?0:1;*/ + pcr.rule.log = (GETFLAG(LOGPACKETSMASK))?1:0; /*logpackets;*/ +/* see the discussion on the forum : + * http://miniupnp.tuxfamily.org/forum/viewtopic.php?p=638 */ + pcr.rule.flags = TH_SYN; + pcr.rule.flagset = (TH_SYN|TH_ACK); +#ifdef PFRULE_HAS_RTABLEID + pcr.rule.rtableid = -1; /* first appeared in OpenBSD 4.0 */ +#endif +#ifdef PFRULE_HAS_ONRDOMAIN + pcr.rule.onrdomain = -1; /* first appeared in OpenBSD 5.0 */ +#endif + pcr.rule.keep_state = 1; + /*strlcpy(pcr.rule.label, desc, PF_RULE_LABEL_SIZE);*/ + if(queue) + strlcpy(pcr.rule.qname, queue, PF_QNAME_SIZE); + if(tag) + strlcpy(pcr.rule.tagname, tag, PF_TAG_NAME_SIZE); + + pcr.rule.src.port_op = PF_OP_EQ; + pcr.rule.src.port[0] = htons(rem_port); + if(rem_host && rem_host[0] != '\0' && rem_host[0] != '*') + { + inet_pton(AF_INET6, rem_host, &pcr.rule.src.addr.v.a.addr.v6); + memset(&pcr.rule.src.addr.v.a.mask.addr8, 255, 16); + } + + pcr.rule.dst.port_op = PF_OP_EQ; + pcr.rule.dst.port[0] = htons(int_port); + if(inet_pton(AF_INET6, int_client, &pcr.rule.dst.addr.v.a.addr.v6) != 1) { + syslog(LOG_ERR, "inet_pton(%s) failed", int_client); + } + memset(&pcr.rule.dst.addr.v.a.mask.addr8, 255, 16); + + if(ifname) + strlcpy(pcr.rule.ifname, ifname, IFNAMSIZ); + + pcr.action = PF_CHANGE_GET_TICKET; + if(ioctl(dev, DIOCCHANGERULE, &pcr) < 0) { + syslog(LOG_ERR, "ioctl(dev, DIOCCHANGERULE, ...) PF_CHANGE_GET_TICKET: %m"); + return -1; + } else { + pcr.action = PF_CHANGE_ADD_TAIL; + if(ioctl(dev, DIOCCHANGERULE, &pcr) < 0) { + syslog(LOG_ERR, "ioctl(dev, DIOCCHANGERULE, ...) PF_CHANGE_ADD_TAIL: %m"); + return -1; + } + } + } + + return 0; +} + diff --git a/miniupnpd/pf/pfpinhole.h b/miniupnpd/pf/pfpinhole.h new file mode 100644 index 0000000..d09c7ca --- /dev/null +++ b/miniupnpd/pf/pfpinhole.h @@ -0,0 +1,17 @@ +/* $Id: pfpinhole.h,v 1.1 2012/04/18 20:45:33 nanard Exp $ */ +/* MiniUPnP project + * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ + * (c) 2012 Thomas Bernard + * This software is subject to the conditions detailed + * in the LICENCE file provided within the distribution */ + +#ifndef __PFPINHOLE_H__ +#define __PFPINHOLE_H__ + +int add_pinhole (const char * ifname, + const char * rem_host, unsigned short rem_port, + const char * int_client, unsigned short int_port, + int proto); + +#endif + diff --git a/miniupnpd/pf/testobsdrdr.c b/miniupnpd/pf/testobsdrdr.c index 408c85e..7d288c6 100644 --- a/miniupnpd/pf/testobsdrdr.c +++ b/miniupnpd/pf/testobsdrdr.c @@ -1,7 +1,7 @@ -/* $Id: testobsdrdr.c,v 1.22 2011/06/04 16:45:22 nanard Exp $ */ +/* $Id: testobsdrdr.c,v 1.24 2012/04/18 19:42:03 nanard Exp $ */ /* MiniUPnP project * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2006-2011 Thomas Bernard + * (c) 2006-2012 Thomas Bernard * This software is subject to the conditions detailed * in the LICENCE file provided within the distribution */ @@ -16,6 +16,7 @@ /*int logpackets = 1;*/ int runtime_flags = 0; const char * tag = 0; +const char * anchor_name = "miniupnpd"; void list_rules(void); @@ -70,6 +71,7 @@ main(int arc, char * * argv) { char buf[32]; char desc[64]; + char rhost[64]; /*char rhost[32];*/ unsigned short iport; unsigned int timestamp; @@ -82,12 +84,16 @@ main(int arc, char * * argv) fprintf(stderr, "init_redirect() failed\n"); return 1; } - //add_redirect_rule("ep0", 12123, "192.168.1.23", 1234); - //add_redirect_rule2("ep0", 12155, "192.168.1.155", 1255, IPPROTO_TCP); +#if 0 + add_redirect_rule("ep0", 12123, "192.168.1.23", 1234); + add_redirect_rule2("ep0", 12155, "192.168.1.155", 1255, IPPROTO_TCP); +#endif add_redirect_rule2("ep0", "8.8.8.8", 12123, "192.168.1.125", 1234, IPPROTO_UDP, "test description", 0); - //add_redirect_rule2("em0", 12123, "127.1.2.3", 1234, - // IPPROTO_TCP, "test description tcp"); +#if 0 + add_redirect_rule2("em0", 12123, "127.1.2.3", 1234, + IPPROTO_TCP, "test description tcp"); +#endif list_rules(); list_eports_tcp(); @@ -95,6 +101,7 @@ main(int arc, char * * argv) if(get_redirect_rule("xl1", 4662, IPPROTO_TCP, buf, sizeof(buf), &iport, desc, sizeof(desc), + rhost, sizeof(rhost), ×tamp, &packets, &bytes) < 0) printf("get_redirect_rule() failed\n"); @@ -103,21 +110,23 @@ main(int arc, char * * argv) printf("\n%s:%d '%s' packets=%llu bytes=%llu\n", buf, (int)iport, desc, packets, bytes); } + + if(delete_redirect_rule("ep0", 12123, IPPROTO_UDP) < 0) + printf("delete_redirect_rule() failed\n"); + else + printf("delete_redirect_rule() succeded\n"); + + if(delete_redirect_rule("ep0", 12123, IPPROTO_UDP) < 0) + printf("delete_redirect_rule() failed\n"); + else + printf("delete_redirect_rule() succeded\n"); + #if 0 - if(delete_redirect_rule("ep0", 12123, IPPROTO_UDP) < 0) - printf("delete_redirect_rule() failed\n"); - else - printf("delete_redirect_rule() succeded\n"); + test_index(); - if(delete_redirect_rule("ep0", 12123, IPPROTO_UDP) < 0) - printf("delete_redirect_rule() failed\n"); - else - printf("delete_redirect_rule() succeded\n"); + clear_redirect_rules(); + list_rules(); #endif - //test_index(); - - //clear_redirect_rules(); - //list_rules(); return 0; } diff --git a/miniupnpd/pf/testpfpinhole.c b/miniupnpd/pf/testpfpinhole.c new file mode 100644 index 0000000..cb8fd10 --- /dev/null +++ b/miniupnpd/pf/testpfpinhole.c @@ -0,0 +1,36 @@ +/* $Id: testpfpinhole.c,v 1.1 2012/04/18 20:45:33 nanard Exp $ */ +/* MiniUPnP project + * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ + * (c) 2006-2012 Thomas Bernard + * This software is subject to the conditions detailed + * in the LICENCE file provided within the distribution */ + +#include +#include +#include +#include +#include + +#include "obsdrdr.h" +#include "pfpinhole.h" + +int runtime_flags = 0; +const char * tag = NULL; + +const char * anchor_name = "miniupnpd"; +const char * queue = NULL; + +int main(int argc, char * *argv) +{ + int ret; + + openlog("testpfpinhole", LOG_PERROR, LOG_USER); + if(init_redirect() < 0) { + fprintf(stderr, "init_redirect() failed\n"); + return 1; + } + + ret = add_pinhole("ep0", "2001::1:2:3", 12345, "123::ff", 54321, IPPROTO_UDP); + return 0; +} +