Annotation of embedaddon/miniupnpd/pf/obsdrdr.c, revision 1.1

1.1     ! misho       1: /* $Id: obsdrdr.c,v 1.59 2010/05/11 16:19:26 nanard Exp $ */
        !             2: /* MiniUPnP project
        !             3:  * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
        !             4:  * (c) 2006-2010 Thomas Bernard 
        !             5:  * This software is subject to the conditions detailed
        !             6:  * in the LICENCE file provided within the distribution */
        !             7: 
        !             8: /*
        !             9:  * pf rules created (with ext_if = xl1)
        !            10:  * - OpenBSD up to version 4.6 :
        !            11:  *     rdr pass on xl1 inet proto udp from any to any port = 54321 \
        !            12:  *            label "test label" -> 192.168.0.141 port 12345
        !            13:  *   or a rdr rule + a pass rule
        !            14:  *
        !            15:  * - OpenBSD starting from version 4.7
        !            16:  *     match in on xl1 inet proto udp from any to any port 54321 \
        !            17:  *            label "test label" rdr-to 192.168.0.141 port 12345
        !            18:  *   or
        !            19:  *     pass in quick on xl1 inet proto udp from any to any port 54321 \
        !            20:  *            label "test label" rdr-to 192.168.0.141 port 12345
        !            21:  *
        !            22:  *
        !            23:  *
        !            24:  * Macros/#defines :
        !            25:  * - PF_ENABLE_FILTER_RULES
        !            26:  *   If set, two rules are created : rdr + pass. Else a rdr/pass rule
        !            27:  *   is created.
        !            28:  * - USE_IFNAME_IN_RULES
        !            29:  *   If set the interface name is set in the rule.
        !            30:  * - PFRULE_INOUT_COUNTS
        !            31:  *   Must be set with OpenBSD version 3.8 and up.
        !            32:  * - PFRULE_HAS_RTABLEID
        !            33:  *   Must be set with OpenBSD version 4.0 and up.
        !            34:  * - PF_NEWSSTYLE
        !            35:  *   Must be set with OpenBSD version 4.7 and up.
        !            36:  */
        !            37: 
        !            38: #include <sys/types.h>
        !            39: #include <sys/socket.h>
        !            40: #include <sys/param.h>
        !            41: #include <net/if.h>
        !            42: #include <netinet/in.h>
        !            43: #include <netinet/tcp.h>
        !            44: #include <arpa/inet.h>
        !            45: #ifdef __DragonFly__
        !            46: #include <net/pf/pfvar.h>
        !            47: #else
        !            48: #include <net/pfvar.h>
        !            49: #endif
        !            50: #include <fcntl.h>
        !            51: #include <sys/ioctl.h>
        !            52: #include <unistd.h>
        !            53: #include <string.h>
        !            54: #include <syslog.h>
        !            55: #include <stdio.h>
        !            56: #include <stdlib.h>
        !            57: 
        !            58: #include "../config.h"
        !            59: #include "obsdrdr.h"
        !            60: #include "../upnpglobalvars.h"
        !            61: 
        !            62: /* anchor name */
        !            63: static const char anchor_name[] = "miniupnpd";
        !            64: 
        !            65: /* /dev/pf when opened */
        !            66: static int dev = -1;
        !            67: 
        !            68: /* shutdown_redirect() :
        !            69:  * close the /dev/pf device */
        !            70: void
        !            71: shutdown_redirect(void)
        !            72: {
        !            73:        if(close(dev)<0)
        !            74:                syslog(LOG_ERR, "close(\"/dev/pf\"): %m");
        !            75:        dev = -1;
        !            76: }
        !            77: 
        !            78: /* open the device */
        !            79: int
        !            80: init_redirect(void)
        !            81: {
        !            82:        struct pf_status status;
        !            83:        if(dev>=0)
        !            84:                shutdown_redirect();
        !            85:        dev = open("/dev/pf", O_RDWR);
        !            86:        if(dev<0) {
        !            87:                syslog(LOG_ERR, "open(\"/dev/pf\"): %m");
        !            88:                return -1;
        !            89:        }
        !            90:        if(ioctl(dev, DIOCGETSTATUS, &status)<0) {
        !            91:                syslog(LOG_ERR, "DIOCGETSTATUS: %m");
        !            92:                return -1;
        !            93:        }
        !            94:        if(!status.running) {
        !            95:                syslog(LOG_ERR, "pf is disabled");
        !            96:                return -1;
        !            97:        }
        !            98:        return 0;
        !            99: }
        !           100: 
        !           101: #if TEST
        !           102: /* for debug */
        !           103: int
        !           104: clear_redirect_rules(void)
        !           105: {
        !           106:        struct pfioc_trans io;
        !           107:        struct pfioc_trans_e ioe;
        !           108:        if(dev<0) {
        !           109:                syslog(LOG_ERR, "pf device is not open");
        !           110:                return -1;
        !           111:        }
        !           112:        memset(&ioe, 0, sizeof(ioe));
        !           113:        io.size = 1;
        !           114:        io.esize = sizeof(ioe);
        !           115:        io.array = &ioe;
        !           116: #ifndef PF_NEWSTYLE
        !           117:        ioe.rs_num = PF_RULESET_RDR;
        !           118: #else
        !           119:        ioe.type = PF_TRANS_RULESET;
        !           120: #endif
        !           121:        strlcpy(ioe.anchor, anchor_name, MAXPATHLEN);
        !           122:        if(ioctl(dev, DIOCXBEGIN, &io) < 0)
        !           123:        {
        !           124:                syslog(LOG_ERR, "ioctl(dev, DIOCXBEGIN, ...): %m");
        !           125:                goto error;
        !           126:        }
        !           127:        if(ioctl(dev, DIOCXCOMMIT, &io) < 0)
        !           128:        {
        !           129:                syslog(LOG_ERR, "ioctl(dev, DIOCXCOMMIT, ...): %m");
        !           130:                goto error;
        !           131:        }
        !           132:        return 0;
        !           133: error:
        !           134:        return -1;
        !           135: }
        !           136: #endif
        !           137: 
        !           138: /* add_redirect_rule2() :
        !           139:  * create a rdr rule */
        !           140: int
        !           141: add_redirect_rule2(const char * ifname, unsigned short eport,
        !           142:                    const char * iaddr, unsigned short iport, int proto,
        !           143:                                   const char * desc)
        !           144: {
        !           145:        int r;
        !           146:        struct pfioc_rule pcr;
        !           147: #ifndef PF_NEWSTYLE
        !           148:        struct pfioc_pooladdr pp;
        !           149:        struct pf_pooladdr *a;
        !           150: #endif
        !           151:        if(dev<0) {
        !           152:                syslog(LOG_ERR, "pf device is not open");
        !           153:                return -1;
        !           154:        }
        !           155:        r = 0;
        !           156:        memset(&pcr, 0, sizeof(pcr));
        !           157:        strlcpy(pcr.anchor, anchor_name, MAXPATHLEN);
        !           158: 
        !           159: #ifndef PF_NEWSTYLE
        !           160:        memset(&pp, 0, sizeof(pp));
        !           161:        strlcpy(pp.anchor, anchor_name, MAXPATHLEN);
        !           162:        if(ioctl(dev, DIOCBEGINADDRS, &pp) < 0)
        !           163:        {
        !           164:                syslog(LOG_ERR, "ioctl(dev, DIOCBEGINADDRS, ...): %m");
        !           165:                r = -1;
        !           166:        }
        !           167:        else
        !           168:        {
        !           169:                pcr.pool_ticket = pp.ticket;
        !           170: #else
        !           171:        if(1)
        !           172:        {
        !           173:                pcr.rule.direction = PF_IN;
        !           174:                //pcr.rule.src.addr.type = PF_ADDR_NONE;
        !           175:                pcr.rule.src.addr.type = PF_ADDR_ADDRMASK;
        !           176:                pcr.rule.dst.addr.type = PF_ADDR_ADDRMASK;
        !           177:                pcr.rule.nat.addr.type = PF_ADDR_NONE;
        !           178:                pcr.rule.rdr.addr.type = PF_ADDR_ADDRMASK;
        !           179: #endif
        !           180:                
        !           181:                pcr.rule.dst.port_op = PF_OP_EQ;
        !           182:                pcr.rule.dst.port[0] = htons(eport);
        !           183:                pcr.rule.dst.port[1] = htons(eport);
        !           184: #ifndef PF_NEWSTYLE
        !           185:                pcr.rule.action = PF_RDR;
        !           186: #ifndef PF_ENABLE_FILTER_RULES
        !           187:                pcr.rule.natpass = 1;
        !           188: #else
        !           189:                pcr.rule.natpass = 0;
        !           190: #endif
        !           191: #else
        !           192: #ifndef PF_ENABLE_FILTER_RULES
        !           193:                pcr.rule.action = PF_PASS;
        !           194: #else
        !           195:                pcr.rule.action = PF_MATCH;
        !           196: #endif
        !           197: #endif
        !           198:                pcr.rule.af = AF_INET;
        !           199: #ifdef USE_IFNAME_IN_RULES
        !           200:                if(ifname)
        !           201:                        strlcpy(pcr.rule.ifname, ifname, IFNAMSIZ);
        !           202: #endif
        !           203:                pcr.rule.proto = proto;
        !           204:                pcr.rule.log = (GETFLAG(LOGPACKETSMASK))?1:0;   /*logpackets;*/
        !           205: #ifdef PFRULE_HAS_RTABLEID
        !           206:                pcr.rule.rtableid = -1; /* first appeared in OpenBSD 4.0 */
        !           207: #endif
        !           208:                pcr.rule.quick = 1;
        !           209:                pcr.rule.keep_state = PF_STATE_NORMAL;
        !           210:                if(tag)
        !           211:                        strlcpy(pcr.rule.tagname, tag, PF_TAG_NAME_SIZE);
        !           212:                strlcpy(pcr.rule.label, desc, PF_RULE_LABEL_SIZE);
        !           213: #ifndef PF_NEWSTYLE
        !           214:                pcr.rule.rpool.proxy_port[0] = iport;
        !           215:                pcr.rule.rpool.proxy_port[1] = iport;
        !           216:                TAILQ_INIT(&pcr.rule.rpool.list);
        !           217:                a = calloc(1, sizeof(struct pf_pooladdr));
        !           218:                inet_pton(AF_INET, iaddr, &a->addr.v.a.addr.v4.s_addr);
        !           219:                a->addr.v.a.mask.v4.s_addr = htonl(INADDR_NONE);
        !           220:                TAILQ_INSERT_TAIL(&pcr.rule.rpool.list, a, entries);
        !           221: 
        !           222:                memcpy(&pp.addr, a, sizeof(struct pf_pooladdr));
        !           223:                if(ioctl(dev, DIOCADDADDR, &pp) < 0)
        !           224:                {
        !           225:                        syslog(LOG_ERR, "ioctl(dev, DIOCADDADDR, ...): %m");
        !           226:                        r = -1;
        !           227:                }
        !           228:                else
        !           229:                {
        !           230: #else
        !           231:                pcr.rule.rdr.proxy_port[0] = iport;
        !           232:                pcr.rule.rdr.proxy_port[1] = iport;
        !           233:                inet_pton(AF_INET, iaddr, &pcr.rule.rdr.addr.v.a.addr.v4.s_addr);
        !           234:                pcr.rule.rdr.addr.v.a.mask.v4.s_addr = htonl(INADDR_NONE);
        !           235:                if(1)
        !           236:                {
        !           237: #endif
        !           238:                        pcr.action = PF_CHANGE_GET_TICKET;
        !           239:                if(ioctl(dev, DIOCCHANGERULE, &pcr) < 0)
        !           240:                        {
        !           241:                syslog(LOG_ERR, "ioctl(dev, DIOCCHANGERULE, ...) PF_CHANGE_GET_TICKET: %m");
        !           242:                                r = -1;
        !           243:                        }
        !           244:                        else
        !           245:                        {
        !           246:                                pcr.action = PF_CHANGE_ADD_TAIL;
        !           247:                                if(ioctl(dev, DIOCCHANGERULE, &pcr) < 0)
        !           248:                                {
        !           249:                                        syslog(LOG_ERR, "ioctl(dev, DIOCCHANGERULE, ...) PF_CHANGE_ADD_TAIL: %m");
        !           250:                                        r = -1;
        !           251:                                }
        !           252:                        }
        !           253:                }
        !           254: #ifndef PF_NEWSTYLE
        !           255:                free(a);
        !           256: #endif
        !           257:        }
        !           258:        return r;
        !           259: }
        !           260: 
        !           261: /* thanks to Seth Mos for this function */
        !           262: int
        !           263: add_filter_rule2(const char * ifname, const char * iaddr,
        !           264:                  unsigned short eport, unsigned short iport,
        !           265:                                 int proto, const char * desc)
        !           266: {
        !           267: #ifndef PF_ENABLE_FILTER_RULES
        !           268:        return 0;
        !           269: #else
        !           270:        int r;
        !           271:        struct pfioc_rule pcr;
        !           272: #ifndef PF_NEWSTYLE
        !           273:        struct pfioc_pooladdr pp;
        !           274:        struct pf_pooladdr *a;
        !           275: #endif
        !           276:        if(dev<0) {
        !           277:                syslog(LOG_ERR, "pf device is not open");
        !           278:                return -1;
        !           279:        }
        !           280:        r = 0;
        !           281:        memset(&pcr, 0, sizeof(pcr));
        !           282:        strlcpy(pcr.anchor, anchor_name, MAXPATHLEN);
        !           283: 
        !           284: #ifndef PF_NEWSTYLE
        !           285:        memset(&pp, 0, sizeof(pp));
        !           286:        strlcpy(pp.anchor, anchor_name, MAXPATHLEN);
        !           287:        if(ioctl(dev, DIOCBEGINADDRS, &pp) < 0)
        !           288:        {
        !           289:                syslog(LOG_ERR, "ioctl(dev, DIOCBEGINADDRS, ...): %m");
        !           290:                r = -1;
        !           291:        }
        !           292:        else
        !           293:        {
        !           294:                pcr.pool_ticket = pp.ticket;
        !           295: #else
        !           296:        if(1)
        !           297:        {
        !           298: #endif
        !           299:                
        !           300:                pcr.rule.dst.port_op = PF_OP_EQ;
        !           301:                pcr.rule.dst.port[0] = htons(eport);
        !           302:                pcr.rule.direction = PF_IN;
        !           303:                pcr.rule.action = PF_PASS;
        !           304:                pcr.rule.af = AF_INET;
        !           305: #ifdef USE_IFNAME_IN_RULES
        !           306:                if(ifname)
        !           307:                        strlcpy(pcr.rule.ifname, ifname, IFNAMSIZ);
        !           308: #endif
        !           309:                pcr.rule.proto = proto;
        !           310:                pcr.rule.quick = (GETFLAG(PFNOQUICKRULESMASK))?0:1;
        !           311:                pcr.rule.log = (GETFLAG(LOGPACKETSMASK))?1:0;   /*logpackets;*/
        !           312: /* see the discussion on the forum :
        !           313:  * http://miniupnp.tuxfamily.org/forum/viewtopic.php?p=638 */
        !           314:                pcr.rule.flags = TH_SYN;
        !           315:                pcr.rule.flagset = (TH_SYN|TH_ACK);
        !           316: #ifdef PFRULE_HAS_RTABLEID
        !           317:                pcr.rule.rtableid = -1; /* first appeared in OpenBSD 4.0 */ 
        !           318: #endif
        !           319:                pcr.rule.keep_state = 1;
        !           320:                strlcpy(pcr.rule.label, desc, PF_RULE_LABEL_SIZE);
        !           321:                if(queue)
        !           322:                        strlcpy(pcr.rule.qname, queue, PF_QNAME_SIZE);
        !           323:                if(tag)
        !           324:                        strlcpy(pcr.rule.tagname, tag, PF_TAG_NAME_SIZE);
        !           325: 
        !           326: #ifndef PF_NEWSTYLE
        !           327:                pcr.rule.rpool.proxy_port[0] = eport;
        !           328:                a = calloc(1, sizeof(struct pf_pooladdr));
        !           329:                inet_pton(AF_INET, iaddr, &a->addr.v.a.addr.v4.s_addr);
        !           330:                a->addr.v.a.mask.v4.s_addr = htonl(INADDR_NONE);
        !           331:                memcpy(&pp.addr, a, sizeof(struct pf_pooladdr));
        !           332:                TAILQ_INIT(&pcr.rule.rpool.list);
        !           333:                inet_pton(AF_INET, iaddr, &a->addr.v.a.addr.v4.s_addr);
        !           334:                TAILQ_INSERT_TAIL(&pcr.rule.rpool.list, a, entries);
        !           335:                
        !           336:                /* we have any - any port = # keep state label */
        !           337:                /* we want any - iaddr port = # keep state label */
        !           338:                /* memcpy(&pcr.rule.dst, a, sizeof(struct pf_pooladdr)); */
        !           339: 
        !           340:                memcpy(&pp.addr, a, sizeof(struct pf_pooladdr));
        !           341:                strlcpy(pcr.rule.label, desc, PF_RULE_LABEL_SIZE);
        !           342:                if(ioctl(dev, DIOCADDADDR, &pp) < 0)
        !           343:                {
        !           344:                        syslog(LOG_ERR, "ioctl(dev, DIOCADDADDR, ...): %m");
        !           345:                        r = -1;
        !           346:                }
        !           347:                else
        !           348:                {
        !           349: #else
        !           350:                if(1)
        !           351:                {
        !           352: #endif
        !           353:                        pcr.action = PF_CHANGE_GET_TICKET;
        !           354:                if(ioctl(dev, DIOCCHANGERULE, &pcr) < 0)
        !           355:                        {
        !           356:                syslog(LOG_ERR, "ioctl(dev, DIOCCHANGERULE, ...) PF_CHANGE_GET_TICKET: %m");
        !           357:                                r = -1;
        !           358:                        }
        !           359:                        else
        !           360:                        {
        !           361:                                pcr.action = PF_CHANGE_ADD_TAIL;
        !           362:                                if(ioctl(dev, DIOCCHANGERULE, &pcr) < 0)
        !           363:                                {
        !           364:                                        syslog(LOG_ERR, "ioctl(dev, DIOCCHANGERULE, ...) PF_CHANGE_ADD_TAIL: %m");
        !           365:                                        r = -1;
        !           366:                                }
        !           367:                        }
        !           368:                }
        !           369: #ifndef PF_NEWSTYLE
        !           370:                free(a);
        !           371: #endif
        !           372:        }
        !           373:        return r;
        !           374: #endif
        !           375: }
        !           376: 
        !           377: /* get_redirect_rule()
        !           378:  * return value : 0 success (found)
        !           379:  * -1 = error or rule not found */
        !           380: int
        !           381: get_redirect_rule(const char * ifname, unsigned short eport, int proto,
        !           382:                   char * iaddr, int iaddrlen, unsigned short * iport,
        !           383:                   char * desc, int desclen,
        !           384:                   u_int64_t * packets, u_int64_t * bytes)
        !           385: {
        !           386:        int i, n;
        !           387:        struct pfioc_rule pr;
        !           388: #ifndef PF_NEWSTYLE
        !           389:        struct pfioc_pooladdr pp;
        !           390: #endif
        !           391:        if(dev<0) {
        !           392:                syslog(LOG_ERR, "pf device is not open");
        !           393:                return -1;
        !           394:        }
        !           395:        memset(&pr, 0, sizeof(pr));
        !           396:        strlcpy(pr.anchor, anchor_name, MAXPATHLEN);
        !           397: #ifndef PF_NEWSTYLE
        !           398:        pr.rule.action = PF_RDR;
        !           399: #endif
        !           400:        if(ioctl(dev, DIOCGETRULES, &pr) < 0)
        !           401:        {
        !           402:                syslog(LOG_ERR, "ioctl(dev, DIOCGETRULES, ...): %m");
        !           403:                goto error;
        !           404:        }
        !           405:        n = pr.nr;
        !           406:        for(i=0; i<n; i++)
        !           407:        {
        !           408:                pr.nr = i;
        !           409:                if(ioctl(dev, DIOCGETRULE, &pr) < 0)
        !           410:                {
        !           411:                        syslog(LOG_ERR, "ioctl(dev, DIOCGETRULE): %m");
        !           412:                        goto error;
        !           413:                }
        !           414:                if( (eport == ntohs(pr.rule.dst.port[0]))
        !           415:                  && (eport == ntohs(pr.rule.dst.port[1]))
        !           416:                  && (pr.rule.proto == proto) )
        !           417:                {
        !           418: #ifndef PF_NEWSTYLE
        !           419:                        *iport = pr.rule.rpool.proxy_port[0];
        !           420: #else
        !           421:                        *iport = pr.rule.rdr.proxy_port[0];
        !           422: #endif
        !           423:                        if(desc)
        !           424:                                strlcpy(desc, pr.rule.label, desclen);
        !           425: #ifdef PFRULE_INOUT_COUNTS
        !           426:                        if(packets)
        !           427:                                *packets = pr.rule.packets[0] + pr.rule.packets[1];
        !           428:                        if(bytes)
        !           429:                                *bytes = pr.rule.bytes[0] + pr.rule.bytes[1];
        !           430: #else
        !           431:                        if(packets)
        !           432:                                *packets = pr.rule.packets;
        !           433:                        if(bytes)
        !           434:                                *bytes = pr.rule.bytes;
        !           435: #endif
        !           436: #ifndef PF_NEWSTYLE
        !           437:                        memset(&pp, 0, sizeof(pp));
        !           438:                        strlcpy(pp.anchor, anchor_name, MAXPATHLEN);
        !           439:                        pp.r_action = PF_RDR;
        !           440:                        pp.r_num = i;
        !           441:                        pp.ticket = pr.ticket;
        !           442:                        if(ioctl(dev, DIOCGETADDRS, &pp) < 0)
        !           443:                        {
        !           444:                                syslog(LOG_ERR, "ioctl(dev, DIOCGETADDRS, ...): %m");
        !           445:                                goto error;
        !           446:                        }
        !           447:                        if(pp.nr != 1)
        !           448:                        {
        !           449:                                syslog(LOG_NOTICE, "No address associated with pf rule");
        !           450:                                goto error;
        !           451:                        }
        !           452:                        pp.nr = 0;      /* first */
        !           453:                        if(ioctl(dev, DIOCGETADDR, &pp) < 0)
        !           454:                        {
        !           455:                                syslog(LOG_ERR, "ioctl(dev, DIOCGETADDR, ...): %m");
        !           456:                                goto error;
        !           457:                        }
        !           458:                        inet_ntop(AF_INET, &pp.addr.addr.v.a.addr.v4.s_addr,
        !           459:                                  iaddr, iaddrlen);
        !           460: #else
        !           461:                        inet_ntop(AF_INET, &pr.rule.rdr.addr.v.a.addr.v4.s_addr,
        !           462:                                  iaddr, iaddrlen);
        !           463: #endif
        !           464:                        return 0;
        !           465:                }
        !           466:        }
        !           467: error:
        !           468:        return -1;
        !           469: }
        !           470: 
        !           471: int
        !           472: delete_redirect_rule(const char * ifname, unsigned short eport, int proto)
        !           473: {
        !           474:        int i, n;
        !           475:        struct pfioc_rule pr;
        !           476:        if(dev<0) {
        !           477:                syslog(LOG_ERR, "pf device is not open");
        !           478:                return -1;
        !           479:        }
        !           480:        memset(&pr, 0, sizeof(pr));
        !           481:        strlcpy(pr.anchor, anchor_name, MAXPATHLEN);
        !           482: #ifndef PF_NEWSTYLE
        !           483:        pr.rule.action = PF_RDR;
        !           484: #endif
        !           485:        if(ioctl(dev, DIOCGETRULES, &pr) < 0)
        !           486:        {
        !           487:                syslog(LOG_ERR, "ioctl(dev, DIOCGETRULES, ...): %m");
        !           488:                goto error;
        !           489:        }
        !           490:        n = pr.nr;
        !           491:        for(i=0; i<n; i++)
        !           492:        {
        !           493:                pr.nr = i;
        !           494:                if(ioctl(dev, DIOCGETRULE, &pr) < 0)
        !           495:                {
        !           496:                        syslog(LOG_ERR, "ioctl(dev, DIOCGETRULE): %m");
        !           497:                        goto error;
        !           498:                }
        !           499:                if( (eport == ntohs(pr.rule.dst.port[0]))
        !           500:                  && (eport == ntohs(pr.rule.dst.port[1]))
        !           501:                  && (pr.rule.proto == proto) )
        !           502:                {
        !           503:                        pr.action = PF_CHANGE_GET_TICKET;
        !           504:                if(ioctl(dev, DIOCCHANGERULE, &pr) < 0)
        !           505:                        {
        !           506:                syslog(LOG_ERR, "ioctl(dev, DIOCCHANGERULE, ...) PF_CHANGE_GET_TICKET: %m");
        !           507:                                goto error;
        !           508:                        }
        !           509:                        pr.action = PF_CHANGE_REMOVE;
        !           510:                        pr.nr = i;
        !           511:                        if(ioctl(dev, DIOCCHANGERULE, &pr) < 0)
        !           512:                        {
        !           513:                                syslog(LOG_ERR, "ioctl(dev, DIOCCHANGERULE, ...) PF_CHANGE_REMOVE: %m");
        !           514:                                goto error;
        !           515:                        }
        !           516:                        return 0;
        !           517:                }
        !           518:        }
        !           519: error:
        !           520:        return -1;
        !           521: }
        !           522: 
        !           523: int
        !           524: delete_filter_rule(const char * ifname, unsigned short eport, int proto)
        !           525: {
        !           526: #ifndef PF_ENABLE_FILTER_RULES
        !           527:        return 0;
        !           528: #else
        !           529:        int i, n;
        !           530:        struct pfioc_rule pr;
        !           531:        if(dev<0) {
        !           532:                syslog(LOG_ERR, "pf device is not open");
        !           533:                return -1;
        !           534:        }
        !           535:        memset(&pr, 0, sizeof(pr));
        !           536:        strlcpy(pr.anchor, anchor_name, MAXPATHLEN);
        !           537:        pr.rule.action = PF_PASS;
        !           538:        if(ioctl(dev, DIOCGETRULES, &pr) < 0)
        !           539:        {
        !           540:                syslog(LOG_ERR, "ioctl(dev, DIOCGETRULES, ...): %m");
        !           541:                goto error;
        !           542:        }
        !           543:        n = pr.nr;
        !           544:        for(i=0; i<n; i++)
        !           545:        {
        !           546:                pr.nr = i;
        !           547:                if(ioctl(dev, DIOCGETRULE, &pr) < 0)
        !           548:                {
        !           549:                        syslog(LOG_ERR, "ioctl(dev, DIOCGETRULE): %m");
        !           550:                        goto error;
        !           551:                }
        !           552:                if( (eport == ntohs(pr.rule.dst.port[0]))
        !           553:                  && (pr.rule.proto == proto) )
        !           554:                {
        !           555:                        pr.action = PF_CHANGE_GET_TICKET;
        !           556:                if(ioctl(dev, DIOCCHANGERULE, &pr) < 0)
        !           557:                        {
        !           558:                syslog(LOG_ERR, "ioctl(dev, DIOCCHANGERULE, ...) PF_CHANGE_GET_TICKET: %m");
        !           559:                                goto error;
        !           560:                        }
        !           561:                        pr.action = PF_CHANGE_REMOVE;
        !           562:                        pr.nr = i;
        !           563:                        if(ioctl(dev, DIOCCHANGERULE, &pr) < 0)
        !           564:                        {
        !           565:                                syslog(LOG_ERR, "ioctl(dev, DIOCCHANGERULE, ...) PF_CHANGE_REMOVE: %m");
        !           566:                                goto error;
        !           567:                        }
        !           568:                        return 0;
        !           569:                }
        !           570:        }
        !           571: error:
        !           572:        return -1;
        !           573: #endif
        !           574: }
        !           575: 
        !           576: int
        !           577: get_redirect_rule_by_index(int index,
        !           578:                            char * ifname, unsigned short * eport,
        !           579:                            char * iaddr, int iaddrlen, unsigned short * iport,
        !           580:                            int * proto, char * desc, int desclen,
        !           581:                            u_int64_t * packets, u_int64_t * bytes)
        !           582: {
        !           583:        int n;
        !           584:        struct pfioc_rule pr;
        !           585: #ifndef PF_NEWSTYLE
        !           586:        struct pfioc_pooladdr pp;
        !           587: #endif
        !           588:        if(index < 0)
        !           589:                return -1;
        !           590:        if(dev<0) {
        !           591:                syslog(LOG_ERR, "pf device is not open");
        !           592:                return -1;
        !           593:        }
        !           594:        memset(&pr, 0, sizeof(pr));
        !           595:        strlcpy(pr.anchor, anchor_name, MAXPATHLEN);
        !           596: #ifndef PF_NEWSTYLE
        !           597:        pr.rule.action = PF_RDR;
        !           598: #endif
        !           599:        if(ioctl(dev, DIOCGETRULES, &pr) < 0)
        !           600:        {
        !           601:                syslog(LOG_ERR, "ioctl(dev, DIOCGETRULES, ...): %m");
        !           602:                goto error;
        !           603:        }
        !           604:        n = pr.nr;
        !           605:        if(index >= n)
        !           606:                goto error;
        !           607:        pr.nr = index;
        !           608:        if(ioctl(dev, DIOCGETRULE, &pr) < 0)
        !           609:        {
        !           610:                syslog(LOG_ERR, "ioctl(dev, DIOCGETRULE): %m");
        !           611:                goto error;
        !           612:        }
        !           613:        *proto = pr.rule.proto;
        !           614:        *eport = ntohs(pr.rule.dst.port[0]);
        !           615: #ifndef PF_NEWSTYLE
        !           616:        *iport = pr.rule.rpool.proxy_port[0];
        !           617: #else
        !           618:        *iport = pr.rule.rdr.proxy_port[0];
        !           619: #endif
        !           620:        if(ifname)
        !           621:                strlcpy(ifname, pr.rule.ifname, IFNAMSIZ);
        !           622:        if(desc)
        !           623:                strlcpy(desc, pr.rule.label, desclen);
        !           624: #ifdef PFRULE_INOUT_COUNTS
        !           625:        if(packets)
        !           626:                *packets = pr.rule.packets[0] + pr.rule.packets[1];
        !           627:        if(bytes)
        !           628:                *bytes = pr.rule.bytes[0] + pr.rule.bytes[1];
        !           629: #else
        !           630:        if(packets)
        !           631:                *packets = pr.rule.packets;
        !           632:        if(bytes)
        !           633:                *bytes = pr.rule.bytes;
        !           634: #endif
        !           635: #ifndef PF_NEWSTYLE
        !           636:        memset(&pp, 0, sizeof(pp));
        !           637:        strlcpy(pp.anchor, anchor_name, MAXPATHLEN);
        !           638:        pp.r_action = PF_RDR;
        !           639:        pp.r_num = index;
        !           640:        pp.ticket = pr.ticket;
        !           641:        if(ioctl(dev, DIOCGETADDRS, &pp) < 0)
        !           642:        {
        !           643:                syslog(LOG_ERR, "ioctl(dev, DIOCGETADDRS, ...): %m");
        !           644:                goto error;
        !           645:        }
        !           646:        if(pp.nr != 1)
        !           647:        {
        !           648:                syslog(LOG_NOTICE, "No address associated with pf rule");
        !           649:                goto error;
        !           650:        }
        !           651:        pp.nr = 0;      /* first */
        !           652:        if(ioctl(dev, DIOCGETADDR, &pp) < 0)
        !           653:        {
        !           654:                syslog(LOG_ERR, "ioctl(dev, DIOCGETADDR, ...): %m");
        !           655:                goto error;
        !           656:        }
        !           657:        inet_ntop(AF_INET, &pp.addr.addr.v.a.addr.v4.s_addr,
        !           658:                  iaddr, iaddrlen);
        !           659: #else
        !           660:        inet_ntop(AF_INET, &pr.rule.rdr.addr.v.a.addr.v4.s_addr,
        !           661:                  iaddr, iaddrlen);
        !           662: #endif
        !           663:        return 0;
        !           664: error:
        !           665:        return -1;
        !           666: }
        !           667: 
        !           668: /* this function is only for testing */
        !           669: #if TEST
        !           670: void
        !           671: list_rules(void)
        !           672: {
        !           673:        char buf[32];
        !           674:        int i, n;
        !           675:        struct pfioc_rule pr;
        !           676: #ifndef PF_NEWSTYLE
        !           677:        struct pfioc_pooladdr pp;
        !           678: #endif
        !           679: 
        !           680:        if(dev<0)
        !           681:        {
        !           682:                perror("pf dev not open");
        !           683:                return ;
        !           684:        }
        !           685:        memset(&pr, 0, sizeof(pr));
        !           686:        strlcpy(pr.anchor, anchor_name, MAXPATHLEN);
        !           687:        pr.rule.action = PF_RDR;
        !           688:        if(ioctl(dev, DIOCGETRULES, &pr) < 0)
        !           689:                perror("DIOCGETRULES");
        !           690:        printf("ticket = %d, nr = %d\n", pr.ticket, pr.nr);
        !           691:        n = pr.nr;
        !           692:        for(i=0; i<n; i++)
        !           693:        {
        !           694:                printf("-- rule %d --\n", i);
        !           695:                pr.nr = i;
        !           696:                if(ioctl(dev, DIOCGETRULE, &pr) < 0)
        !           697:                        perror("DIOCGETRULE");
        !           698:                printf(" %s %d:%d -> %d:%d  proto %d keep_state=%d action=%d\n",
        !           699:                        pr.rule.ifname,
        !           700:                        (int)ntohs(pr.rule.dst.port[0]),
        !           701:                        (int)ntohs(pr.rule.dst.port[1]),
        !           702: #ifndef PF_NEWSTYLE
        !           703:                        (int)pr.rule.rpool.proxy_port[0],
        !           704:                        (int)pr.rule.rpool.proxy_port[1],
        !           705: #else
        !           706:                        (int)pr.rule.rdr.proxy_port[0],
        !           707:                        (int)pr.rule.rdr.proxy_port[1],
        !           708: #endif
        !           709:                        (int)pr.rule.proto,
        !           710:                        (int)pr.rule.keep_state,
        !           711:                        (int)pr.rule.action);
        !           712:                printf("  description: \"%s\"\n", pr.rule.label);
        !           713: #ifndef PF_NEWSTYLE
        !           714:                memset(&pp, 0, sizeof(pp));
        !           715:                strlcpy(pp.anchor, anchor_name, MAXPATHLEN);
        !           716:                pp.r_action = PF_RDR;
        !           717:                pp.r_num = i;
        !           718:                pp.ticket = pr.ticket;
        !           719:                if(ioctl(dev, DIOCGETADDRS, &pp) < 0)
        !           720:                        perror("DIOCGETADDRS");
        !           721:                printf("  nb pool addr = %d ticket=%d\n", pp.nr, pp.ticket);
        !           722:                /*if(ioctl(dev, DIOCGETRULE, &pr) < 0)
        !           723:                        perror("DIOCGETRULE"); */
        !           724:                pp.nr = 0;      /* first */
        !           725:                if(ioctl(dev, DIOCGETADDR, &pp) < 0)
        !           726:                        perror("DIOCGETADDR");
        !           727:                /* addr.v.a.addr.v4.s_addr */
        !           728:                printf("  %s\n", inet_ntop(AF_INET, &pp.addr.addr.v.a.addr.v4.s_addr, buf, 32));
        !           729: #else
        !           730:                printf("  rule_flag=%08x action=%d direction=%d log=%d logif=%d "
        !           731:                       "quick=%d ifnot=%d af=%d type=%d code=%d rdr.port_op=%d rdr.opts=%d\n",
        !           732:                       pr.rule.rule_flag, pr.rule.action, pr.rule.direction,
        !           733:                       pr.rule.log, pr.rule.logif, pr.rule.quick, pr.rule.ifnot,
        !           734:                       pr.rule.af, pr.rule.type, pr.rule.code,
        !           735:                       pr.rule.rdr.port_op, pr.rule.rdr.opts);
        !           736:                printf("  %s\n", inet_ntop(AF_INET, &pr.rule.rdr.addr.v.a.addr.v4.s_addr, buf, 32));
        !           737: #endif
        !           738:        }
        !           739: }
        !           740: #endif
        !           741: 

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>