diff --git a/miniupnpd/pf/obsdrdr.c b/miniupnpd/pf/obsdrdr.c index 04c2ddb..349f68e 100644 --- a/miniupnpd/pf/obsdrdr.c +++ b/miniupnpd/pf/obsdrdr.c @@ -1,7 +1,7 @@ -/* $Id: obsdrdr.c,v 1.74 2012/05/01 09:20:43 nanard Exp $ */ +/* $Id: obsdrdr.c,v 1.80 2014/03/06 13:02:46 nanard Exp $ */ /* MiniUPnP project * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2006-2012 Thomas Bernard + * (c) 2006-2014 Thomas Bernard * This software is subject to the conditions detailed * in the LICENCE file provided within the distribution */ @@ -9,15 +9,19 @@ * pf rules created (with ext_if = xl1) * - OpenBSD up to version 4.6 : * rdr pass on xl1 inet proto udp from any to any port = 54321 \ - * label "test label" -> 192.168.0.141 port 12345 - * or a rdr rule + a pass rule + * keep state label "test label" -> 192.168.0.42 port 12345 + * or a rdr rule + a pass rule : + * rdr quick on xl1 inet proto udp from any to any port = 54321 \ + * keep state label "test label" -> 192.168.0.42 port 12345 + * pass in quick on xl1 inet proto udp from any to 192.168.0.42 port = 12345 \ + * flags S/SA keep state label "test label" * * - OpenBSD starting from version 4.7 * match in on xl1 inet proto udp from any to any port 54321 \ - * label "test label" rdr-to 192.168.0.141 port 12345 + * label "test label" rdr-to 192.168.0.42 port 12345 * or * pass in quick on xl1 inet proto udp from any to any port 54321 \ - * label "test label" rdr-to 192.168.0.141 port 12345 + * label "test label" rdr-to 192.168.0.42 port 12345 * * * @@ -176,6 +180,45 @@ clear_redirect_rules(void) error: return -1; } + +int +clear_filter_rules(void) +{ +#ifndef PF_ENABLE_FILTER_RULES + return 0; +#else + struct pfioc_trans io; + struct pfioc_trans_e ioe; + if(dev<0) { + syslog(LOG_ERR, "pf device is not open"); + return -1; + } + memset(&ioe, 0, sizeof(ioe)); + io.size = 1; + io.esize = sizeof(ioe); + io.array = &ioe; +#ifndef PF_NEWSTYLE + ioe.rs_num = PF_RULESET_FILTER; +#else + /* ? */ + ioe.type = PF_TRANS_RULESET; +#endif + strlcpy(ioe.anchor, anchor_name, MAXPATHLEN); + if(ioctl(dev, DIOCXBEGIN, &io) < 0) + { + syslog(LOG_ERR, "ioctl(dev, DIOCXBEGIN, ...): %m"); + goto error; + } + if(ioctl(dev, DIOCXCOMMIT, &io) < 0) + { + syslog(LOG_ERR, "ioctl(dev, DIOCXCOMMIT, ...): %m"); + goto error; + } + return 0; +error: + return -1; +#endif +} #endif /* add_redirect_rule2() : @@ -347,8 +390,11 @@ add_filter_rule2(const char * ifname, struct pfioc_rule pcr; #ifndef PF_NEWSTYLE struct pfioc_pooladdr pp; - struct pf_pooladdr *a; #endif +#ifndef USE_IFNAME_IN_RULES + UNUSED(ifname); +#endif + UNUSED(eport); if(dev<0) { syslog(LOG_ERR, "pf device is not open"); return -1; @@ -372,9 +418,8 @@ add_filter_rule2(const char * ifname, if(1) { #endif - pcr.rule.dst.port_op = PF_OP_EQ; - pcr.rule.dst.port[0] = htons(eport); + pcr.rule.dst.port[0] = htons(iport); pcr.rule.direction = PF_IN; pcr.rule.action = PF_PASS; pcr.rule.af = AF_INET; @@ -407,33 +452,16 @@ add_filter_rule2(const char * ifname, inet_pton(AF_INET, rhost, &pcr.rule.src.addr.v.a.addr.v4.s_addr); pcr.rule.src.addr.v.a.mask.v4.s_addr = htonl(INADDR_NONE); } -#ifndef PF_NEWSTYLE - pcr.rule.rpool.proxy_port[0] = eport; - a = calloc(1, sizeof(struct pf_pooladdr)); - inet_pton(AF_INET, iaddr, &a->addr.v.a.addr.v4.s_addr); - a->addr.v.a.mask.v4.s_addr = htonl(INADDR_NONE); - memcpy(&pp.addr, a, sizeof(struct pf_pooladdr)); - TAILQ_INIT(&pcr.rule.rpool.list); - inet_pton(AF_INET, iaddr, &a->addr.v.a.addr.v4.s_addr); - TAILQ_INSERT_TAIL(&pcr.rule.rpool.list, a, entries); - - /* we have any - any port = # keep state label */ /* we want any - iaddr port = # keep state label */ - /* memcpy(&pcr.rule.dst, a, sizeof(struct pf_pooladdr)); */ - - memcpy(&pp.addr, a, sizeof(struct pf_pooladdr)); - strlcpy(pcr.rule.label, desc, PF_RULE_LABEL_SIZE); - if(ioctl(dev, DIOCADDADDR, &pp) < 0) - { - syslog(LOG_ERR, "ioctl(dev, DIOCADDADDR, ...): %m"); - r = -1; - } - else - { -#else + inet_pton(AF_INET, iaddr, &pcr.rule.dst.addr.v.a.addr.v4.s_addr); + pcr.rule.dst.addr.v.a.mask.v4.s_addr = htonl(INADDR_NONE); +#ifndef PF_NEWSTYLE + pcr.rule.rpool.proxy_port[0] = iport; + pcr.rule.rpool.proxy_port[1] = iport; + TAILQ_INIT(&pcr.rule.rpool.list); +#endif if(1) { -#endif pcr.action = PF_CHANGE_GET_TICKET; if(ioctl(dev, DIOCCHANGERULE, &pcr) < 0) { @@ -450,9 +478,6 @@ add_filter_rule2(const char * ifname, } } } -#ifndef PF_NEWSTYLE - free(a); -#endif } return r; #endif @@ -575,8 +600,10 @@ error: return -1; } -int -delete_redirect_rule(const char * ifname, unsigned short eport, int proto) +static int +priv_delete_redirect_rule(const char * ifname, unsigned short eport, + int proto, unsigned short * iport, + in_addr_t * iaddr) { int i, n; struct pfioc_rule pr; @@ -614,6 +641,44 @@ delete_redirect_rule(const char * ifname, unsigned short eport, int proto) #endif && (pr.rule.proto == proto) ) { + /* retrieve iport in order to remove filter rule */ +#ifndef PF_NEWSTYLE + if(iport) *iport = pr.rule.rpool.proxy_port[0]; + if(iaddr) + { + /* retrieve internal address */ + struct pfioc_pooladdr pp; + memset(&pp, 0, sizeof(pp)); + strlcpy(pp.anchor, anchor_name, MAXPATHLEN); + pp.r_action = PF_RDR; + pp.r_num = i; + pp.ticket = pr.ticket; + if(ioctl(dev, DIOCGETADDRS, &pp) < 0) + { + syslog(LOG_ERR, "ioctl(dev, DIOCGETADDRS, ...): %m"); + goto error; + } + if(pp.nr != 1) + { + syslog(LOG_NOTICE, "No address associated with pf rule"); + goto error; + } + pp.nr = 0; /* first */ + if(ioctl(dev, DIOCGETADDR, &pp) < 0) + { + syslog(LOG_ERR, "ioctl(dev, DIOCGETADDR, ...): %m"); + goto error; + } + *iaddr = pp.addr.addr.v.a.addr.v4.s_addr; + } +#else + if(iport) *iport = pr.rule.rdr.proxy_port[0]; + if(iaddr) + { + /* retrieve internal address */ + *iaddr = pr.rule.rdr.addr.v.a.addr.v4.s_addr; + } +#endif pr.action = PF_CHANGE_GET_TICKET; if(ioctl(dev, DIOCCHANGERULE, &pr) < 0) { @@ -636,14 +701,23 @@ error: } int -delete_filter_rule(const char * ifname, unsigned short eport, int proto) +delete_redirect_rule(const char * ifname, unsigned short eport, + int proto) +{ + return priv_delete_redirect_rule(ifname, eport, proto, NULL, NULL); +} + +static int +priv_delete_filter_rule(const char * ifname, unsigned short iport, + int proto, in_addr_t iaddr) { #ifndef PF_ENABLE_FILTER_RULES - UNUSED(ifname); UNUSED(eport); UNUSED(proto); + UNUSED(ifname); UNUSED(iport); UNUSED(proto); return 0; #else int i, n; struct pfioc_rule pr; + UNUSED(ifname); if(dev<0) { syslog(LOG_ERR, "pf device is not open"); return -1; @@ -665,8 +739,16 @@ delete_filter_rule(const char * ifname, unsigned short eport, int proto) syslog(LOG_ERR, "ioctl(dev, DIOCGETRULE): %m"); goto error; } - if( (eport == ntohs(pr.rule.dst.port[0])) - && (pr.rule.proto == proto) ) +#ifdef TEST +syslog(LOG_DEBUG, "%2d port=%hu proto=%d addr=%8x", + i, ntohs(pr.rule.dst.port[0]), pr.rule.proto, + pr.rule.dst.addr.v.a.addr.v4.s_addr); +/*pr.rule.dst.addr.v.a.mask.v4.s_addr*/ +#endif + if( (iport == ntohs(pr.rule.dst.port[0])) + && (pr.rule.proto == proto) && + (iaddr == pr.rule.dst.addr.v.a.addr.v4.s_addr) + ) { pr.action = PF_CHANGE_GET_TICKET; if(ioctl(dev, DIOCCHANGERULE, &pr) < 0) @@ -689,6 +771,21 @@ error: #endif } +int +delete_redirect_and_filter_rules(const char * ifname, unsigned short eport, + int proto) +{ + int r; + unsigned short iport; + in_addr_t iaddr; + r = priv_delete_redirect_rule(ifname, eport, proto, &iport, &iaddr); + if(r == 0) + { + r = priv_delete_filter_rule(ifname, iport, proto, iaddr); + } + return r; +} + int get_redirect_rule_by_index(int index, char * ifname, unsigned short * eport, diff --git a/miniupnpd/pf/obsdrdr.h b/miniupnpd/pf/obsdrdr.h index 59225fd..3defa8e 100644 --- a/miniupnpd/pf/obsdrdr.h +++ b/miniupnpd/pf/obsdrdr.h @@ -1,7 +1,7 @@ -/* $Id: obsdrdr.h,v 1.20 2012/03/05 20:36:20 nanard Exp $ */ +/* $Id: obsdrdr.h,v 1.23 2014/03/06 12:24:33 nanard Exp $ */ /* MiniUPnP project * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2006 Thomas Bernard + * (c) 2006-2014 Thomas Bernard * This software is subject to the conditions detailed * in the LICENCE file provided within the distribution */ @@ -52,13 +52,18 @@ get_redirect_rule_by_index(int index, int delete_redirect_rule(const char * ifname, unsigned short eport, int proto); -/* delete_filter_rule() +/* delete_redirect_and_filter_rules() */ int -delete_filter_rule(const char * ifname, unsigned short eport, int proto); +delete_redirect_and_filter_rules(const char * ifname, unsigned short eport, + int proto); +#ifdef TEST int clear_redirect_rules(void); +int +clear_filter_rules(void); +#endif #endif diff --git a/miniupnpd/pf/testobsdrdr.c b/miniupnpd/pf/testobsdrdr.c index 3ce3c85..13d9ee5 100644 --- a/miniupnpd/pf/testobsdrdr.c +++ b/miniupnpd/pf/testobsdrdr.c @@ -1,10 +1,11 @@ -/* $Id: testobsdrdr.c,v 1.26 2014/02/28 18:03:31 nanard Exp $ */ +/* $Id: testobsdrdr.c,v 1.28 2014/03/06 13:02:47 nanard Exp $ */ /* MiniUPnP project * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ * (c) 2006-2014 Thomas Bernard * This software is subject to the conditions detailed * in the LICENCE file provided within the distribution */ +#include #include #include #include @@ -68,7 +69,7 @@ test_index(void) } int -main(int arc, char * * argv) +main(int argc, char * * argv) { char buf[32]; char desc[64]; @@ -78,6 +79,12 @@ main(int arc, char * * argv) unsigned int timestamp; u_int64_t packets = 0; u_int64_t bytes = 0; + int clear = 0; + + if(argc > 1) { + if(0 == strcmp(argv[1], "--clear") || 0 == strcmp(argv[1], "-c")) + clear = 1; + } openlog("testobsdrdr", LOG_PERROR, LOG_USER); if(init_redirect() < 0) @@ -89,12 +96,15 @@ main(int arc, char * * argv) 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", NULL, 12123, "127.1.2.3", 1234, - IPPROTO_TCP, "test description tcp", 0); - add_filter_rule2("em0", NULL, "127.1.2.3", 12123, 1234, IPPROTO_TCP, - "test description tcp"); + if(add_redirect_rule2("ep0", "8.8.8.8", 12123, "192.168.1.125", 1234, + IPPROTO_UDP, "test description", 0) < 0) + printf("add_redirect_rule2() #3 failed\n"); + if(add_redirect_rule2("em0", NULL, 12123, "127.1.2.3", 1234, + IPPROTO_TCP, "test description tcp", 0) < 0) + printf("add_redirect_rule2() #4 failed\n"); + if(add_filter_rule2("em0", NULL, "127.1.2.3", 12123, 1234, IPPROTO_TCP, + "test description tcp") < 0) + printf("add_filter_rule2() #1 failed\n"); list_rules(); list_eports_tcp(); @@ -114,20 +124,20 @@ main(int arc, char * * argv) 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_and_filter_rules("em0", 12123, IPPROTO_TCP) < 0) + printf("delete_redirect_and_filter_rules() failed\n"); + test_index(); - clear_redirect_rules(); - list_rules(); -#endif + if(clear) { + clear_redirect_rules(); + clear_filter_rules(); + } + /*list_rules();*/ return 0; } diff --git a/miniupnpd/upnpredirect.c b/miniupnpd/upnpredirect.c index 7b398ec..0b7e8a3 100644 --- a/miniupnpd/upnpredirect.c +++ b/miniupnpd/upnpredirect.c @@ -1,7 +1,7 @@ -/* $Id: upnpredirect.c,v 1.80 2012/05/01 20:08:22 nanard Exp $ */ +/* $Id: upnpredirect.c,v 1.82 2014/02/28 20:18:35 nanard Exp $ */ /* MiniUPnP project * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2006-2012 Thomas Bernard + * (c) 2006-2014 Thomas Bernard * This software is subject to the conditions detailed * in the LICENCE file provided within the distribution */ @@ -419,6 +419,8 @@ _upnp_delete_redir(unsigned short eport, int proto) int r; #if defined(__linux__) r = delete_redirect_and_filter_rules(eport, proto); +#elif defined(USE_PF) + r = delete_redirect_and_filter_rules(ext_if_name, eport, proto); #else r = delete_redirect_rule(ext_if_name, eport, proto); delete_filter_rule(ext_if_name, eport, proto);