Annotation of embedaddon/miniupnpd/ipf/ipfrdr.c, revision 1.1.1.2

1.1.1.2 ! misho       1: /* $Id: ipfrdr.c,v 1.13 2012/03/19 21:14:13 nanard Exp $ */
1.1       misho       2: /* MiniUPnP project
                      3:  * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
                      4:  * (c) 2007 Darren Reed
                      5:  * This software is subject to the conditions detailed
                      6:  * in the LICENCE file provided within the distribution */
                      7: 
                      8: #include <sys/param.h>
                      9: #include <sys/types.h>
                     10: #include <sys/file.h>
                     11: /*
                     12:  * This is a workaround for <sys/uio.h> troubles on FreeBSD, HPUX, OpenBSD.
                     13:  * Needed here because on some systems <sys/uio.h> gets included by things
                     14:  * like <sys/socket.h>
                     15:  */
                     16: #ifndef _KERNEL
                     17: # define ADD_KERNEL
                     18: # define _KERNEL
                     19: # define KERNEL
                     20: #endif
                     21: #ifdef __OpenBSD__
                     22: struct file;
                     23: #endif
                     24: #include <sys/uio.h>
                     25: #ifdef ADD_KERNEL
                     26: # undef _KERNEL
                     27: # undef KERNEL
                     28: #endif
                     29: #include <sys/time.h>
                     30: #include <sys/socket.h>
                     31: #include <sys/syslog.h>
                     32: #include <sys/ioctl.h>
                     33: #include <net/if.h>
                     34: #if __FreeBSD_version >= 300000
                     35: # include <net/if_var.h>
                     36: #endif
                     37: #include <netinet/in.h>
                     38: #include <netinet/in_systm.h>
                     39: #include <netinet/ip.h>
                     40: #include <netinet/ip_icmp.h>
                     41: #ifndef        TCP_PAWS_IDLE   /* IRIX */
                     42: # include <netinet/tcp.h>
                     43: #endif
                     44: #include <netinet/udp.h>
                     45: 
                     46: #include <arpa/inet.h>
                     47: 
                     48: #include <errno.h>
                     49: #include <limits.h>
                     50: #include <netdb.h>
                     51: #include <stdlib.h>
                     52: #include <fcntl.h>
                     53: #include <syslog.h>
                     54: #include <stddef.h>
                     55: #include <stdio.h>
                     56: #if !defined(__SVR4) && !defined(__svr4__) && defined(sun)
                     57: # include <strings.h>
                     58: #endif
                     59: #include <string.h>
                     60: #include <unistd.h>
                     61: 
                     62: #include "../config.h"
                     63: #include "netinet/ipl.h"
                     64: #include "netinet/ip_compat.h"
                     65: #include "netinet/ip_fil.h"
                     66: #include "netinet/ip_nat.h"
                     67: #include "netinet/ip_state.h"
                     68: 
                     69: 
                     70: #ifndef __P
                     71: # ifdef __STDC__
                     72: #  define      __P(x)  x
                     73: # else
                     74: #  define      __P(x)  ()
                     75: # endif
                     76: #endif
                     77: #ifndef __STDC__
                     78: # undef                const
                     79: # define       const
                     80: #endif
                     81: 
                     82: #ifndef        U_32_T
                     83: # define       U_32_T  1
                     84: # if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD__) || \
                     85:        defined(__sgi)
                     86: typedef        u_int32_t       u_32_t;
                     87: # else
                     88: #  if defined(__alpha__) || defined(__alpha) || defined(_LP64)
                     89: typedef unsigned int   u_32_t;
                     90: #  else
                     91: #   if SOLARIS2 >= 6
                     92: typedef uint32_t       u_32_t;
                     93: #   else
                     94: typedef unsigned int   u_32_t;
                     95: #   endif
                     96: #  endif
                     97: # endif /* __NetBSD__ || __OpenBSD__ || __FreeBSD__ || __sgi */
                     98: #endif /* U_32_T */
                     99: 
                    100: 
                    101: #if defined(__NetBSD__) || defined(__OpenBSD__) ||                     \
                    102:         (_BSDI_VERSION >= 199701) || (__FreeBSD_version >= 300000) ||  \
                    103:        SOLARIS || defined(__sgi) || defined(__osf__) || defined(linux)
                    104: # include <stdarg.h>
                    105: typedef        int     (* ioctlfunc_t) __P((int, ioctlcmd_t, ...));
                    106: #else
                    107: typedef        int     (* ioctlfunc_t) __P((dev_t, ioctlcmd_t, void *));
                    108: #endif
                    109: typedef        void    (* addfunc_t) __P((int, ioctlfunc_t, void *));
                    110: typedef        int     (* copyfunc_t) __P((void *, void *, size_t));
                    111: 
                    112: 
                    113: /*
                    114:  * SunOS4
                    115:  */
                    116: #if defined(sun) && !defined(__SVR4) && !defined(__svr4__)
                    117: extern int     ioctl __P((int, int, void *));
                    118: #endif
                    119: 
                    120: #include "../upnpglobalvars.h"
                    121: 
                    122: /* group name */
                    123: static const char group_name[] = "miniupnpd";
                    124: 
                    125: static int dev = -1;
                    126: static int dev_ipl = -1;
                    127: 
                    128: /* IPFilter cannot store redirection descriptions, so we use our
                    129:  * own structure to store them */
                    130: struct rdr_desc {
                    131:        struct rdr_desc * next;
                    132:        unsigned short eport;
                    133:        int proto;
1.1.1.2 ! misho     134:        unsigned int timestamp;
1.1       misho     135:        char str[];
                    136: };
                    137: 
                    138: /* pointer to the chained list where descriptions are stored */
                    139: static struct rdr_desc * rdr_desc_list;
                    140: 
                    141: static void
1.1.1.2 ! misho     142: add_redirect_desc(unsigned short eport, int proto,
        !           143:                   unsigned int timestamp, const char * desc)
1.1       misho     144: {
                    145:        struct rdr_desc * p;
                    146:        size_t l;
1.1.1.2 ! misho     147: 
1.1       misho     148:        if (desc != NULL) {
                    149:                l = strlen(desc) + 1;
                    150:                p = malloc(sizeof(struct rdr_desc) + l);
                    151:                if (p) {
                    152:                        p->next = rdr_desc_list;
                    153:                        p->eport = eport;
                    154:                        p->proto = proto;
1.1.1.2 ! misho     155:                        p->timestamp = timestamp;
1.1       misho     156:                        memcpy(p->str, desc, l);
                    157:                        rdr_desc_list = p;
                    158:                }
                    159:        }
                    160: }
                    161: 
                    162: static void
                    163: del_redirect_desc(unsigned short eport, int proto)
                    164: {
                    165:        struct rdr_desc * p, * last;
                    166: 
                    167:        last = NULL;
                    168:        for (p = rdr_desc_list; p; p = p->next) {
                    169:                if(p->eport == eport && p->proto == proto) {
                    170:                        if (last == NULL)
                    171:                                rdr_desc_list = p->next;
                    172:                        else
                    173:                                last->next = p->next;
                    174:                        free(p);
                    175:                        return;
                    176:                }
                    177:        }
                    178: }
                    179: 
                    180: static void
1.1.1.2 ! misho     181: get_redirect_desc(unsigned short eport, int proto, char * desc, int desclen, unsigned int * timestamp)
1.1       misho     182: {
                    183:        struct rdr_desc * p;
1.1.1.2 ! misho     184: 
1.1       misho     185:        if (desc == NULL || desclen == 0)
                    186:                return;
                    187:        for (p = rdr_desc_list; p; p = p->next) {
                    188:                if (p->eport == eport && p->proto == proto)
                    189:                {
                    190:                        strncpy(desc, p->str, desclen);
1.1.1.2 ! misho     191:                        *timestamp = p->timestamp;
1.1       misho     192:                        return;
                    193:                }
                    194:        }
1.1.1.2 ! misho     195:        return;
1.1       misho     196: }
                    197: 
                    198: int init_redirect(void)
                    199: {
1.1.1.2 ! misho     200: 
1.1       misho     201:        dev = open(IPNAT_NAME, O_RDWR);
                    202:        if (dev < 0) {
                    203:                syslog(LOG_ERR, "open(\"%s\"): %m", IPNAT_NAME);
                    204:                return -1;
                    205:        }
                    206:        dev_ipl = open(IPL_NAME, O_RDWR);
                    207:        if (dev_ipl < 0) {
                    208:                syslog(LOG_ERR, "open(\"%s\"): %m", IPL_NAME);
                    209:                return -1;
                    210:        }
                    211:        return 0;
                    212: }
                    213: 
                    214: void shutdown_redirect(void)
                    215: {
1.1.1.2 ! misho     216: 
1.1       misho     217:        if (dev >= 0) {
                    218:                close(dev);
                    219:                dev = -1;
                    220:        }
                    221:        if (dev_ipl >= 0) {
                    222:                close(dev_ipl);
                    223:                dev = -1;
                    224:        }
                    225:        return;
                    226: }
                    227: 
                    228: int
1.1.1.2 ! misho     229: add_redirect_rule2(const char * ifname, const char * rhost,
        !           230:     unsigned short eport, const char * iaddr, unsigned short iport,
        !           231:     int proto, const char * desc, unsigned int timestamp)
1.1       misho     232: {
                    233:        struct ipnat ipnat;
                    234:        struct ipfobj obj;
                    235:        int r;
                    236: 
                    237:        if (dev < 0) {
                    238:                syslog(LOG_ERR, "%s not open", IPNAT_NAME);
                    239:                return -1;
                    240:        }
                    241: 
                    242:        memset(&obj, 0, sizeof(obj));
                    243:        memset(&ipnat, 0, sizeof(ipnat));
                    244: 
                    245:        ipnat.in_redir = NAT_REDIRECT;
                    246:        ipnat.in_p = proto;
                    247:        if (proto == IPPROTO_TCP)
                    248:                ipnat.in_flags = IPN_TCP;
                    249:        if (proto == IPPROTO_UDP)
                    250:                ipnat.in_flags = IPN_UDP;
                    251:        ipnat.in_dcmp = FR_EQUAL;
                    252:        ipnat.in_pmin = htons(eport);
                    253:        ipnat.in_pmax = htons(eport);
                    254:        ipnat.in_pnext = htons(iport);
                    255:        ipnat.in_v = 4;
                    256:        strlcpy(ipnat.in_tag.ipt_tag, group_name, IPFTAG_LEN);
                    257: 
                    258: #ifdef USE_IFNAME_IN_RULES
                    259:        if (ifname) {
                    260:                strlcpy(ipnat.in_ifnames[0], ifname, IFNAMSIZ);
                    261:                strlcpy(ipnat.in_ifnames[1], ifname, IFNAMSIZ);
                    262:        }
                    263: #endif
                    264: 
1.1.1.2 ! misho     265:        if(rhost && rhost[0] != '\0' && rhost[0] != '*')
        !           266:        {
        !           267:                inet_pton(AF_INET, rhost, &ipnat.in_src[0].in4);
        !           268:                ipnat.in_src[1].in4.s_addr = 0xffffffff;
        !           269:        }
        !           270: 
1.1       misho     271:        inet_pton(AF_INET, iaddr, &ipnat.in_in[0].in4);
                    272:        ipnat.in_in[1].in4.s_addr = 0xffffffff;
                    273: 
                    274:        obj.ipfo_rev = IPFILTER_VERSION;
                    275:        obj.ipfo_size = sizeof(ipnat);
                    276:        obj.ipfo_ptr = &ipnat;
                    277:        obj.ipfo_type = IPFOBJ_IPNAT;
                    278: 
                    279:        r = ioctl(dev, SIOCADNAT, &obj);
                    280:        if (r == -1)
                    281:                syslog(LOG_ERR, "ioctl(SIOCADNAT): %m");
                    282:        else
1.1.1.2 ! misho     283:                add_redirect_desc(eport, proto, timestamp, desc);
1.1       misho     284:        return r;
                    285: }
                    286: 
                    287: /* get_redirect_rule()
                    288:  * return value : 0 success (found)
                    289:  * -1 = error or rule not found */
                    290: int
                    291: get_redirect_rule(const char * ifname, unsigned short eport, int proto,
                    292:     char * iaddr, int iaddrlen, unsigned short * iport,
                    293:     char * desc, int desclen,
1.1.1.2 ! misho     294:     char * rhost, int rhostlen,
        !           295:     unsigned int * timestamp,
1.1       misho     296:     u_int64_t * packets, u_int64_t * bytes)
                    297: {
                    298:        ipfgeniter_t iter;
                    299:        ipfobj_t obj;
                    300:        ipnat_t ipn;
                    301:        int r;
                    302: 
                    303:        memset(&obj, 0, sizeof(obj));
                    304:        obj.ipfo_rev = IPFILTER_VERSION;
                    305:        obj.ipfo_type = IPFOBJ_GENITER;
                    306:        obj.ipfo_size = sizeof(iter);
                    307:        obj.ipfo_ptr = &iter;
                    308: 
                    309:        iter.igi_type = IPFGENITER_IPNAT;
                    310: #if IPFILTER_VERSION > 4011300
                    311:        iter.igi_nitems = 1;
                    312: #endif
                    313:        iter.igi_data = &ipn;
                    314: 
                    315:        if (dev < 0) {
                    316:                syslog(LOG_ERR, "%s not open", IPNAT_NAME);
                    317:                return -1;
                    318:        }
                    319: 
                    320:        r = -1;
                    321:        do {
                    322:                if (ioctl(dev, SIOCGENITER, &obj) == -1) {
                    323:                        syslog(LOG_ERR, "ioctl(dev, SIOCGENITER): %m");
                    324:                        break;
                    325:                }
                    326:                if (eport == ntohs(ipn.in_pmin) &&
                    327:                    eport == ntohs(ipn.in_pmax) &&
                    328:                    strcmp(ipn.in_tag.ipt_tag, group_name) == 0 &&
                    329:                    ipn.in_p == proto)
                    330:                {
                    331:                        strlcpy(desc, "", desclen);
                    332:                        if (packets != NULL)
                    333:                                *packets = 0;
                    334:                        if (bytes != NULL)
                    335:                                *bytes = 0;
                    336:                        if (iport != NULL)
                    337:                                *iport = ntohs(ipn.in_pnext);
1.1.1.2 ! misho     338:                        if ((desc != NULL) && (timestamp != NULL))
        !           339:                                get_redirect_desc(eport, proto, desc, desclen, timestamp);
        !           340:                        if ((rhost != NULL) && (rhostlen > 0))
        !           341:                                inet_ntop(AF_INET, &ipn.in_src[0].in4, rhost, rhostlen);
1.1       misho     342:                        inet_ntop(AF_INET, &ipn.in_in[0].in4, iaddr, iaddrlen);
                    343:                        r = 0;
                    344:                }
                    345:        } while (ipn.in_next != NULL);
                    346:        return r;
                    347: }
                    348: 
                    349: 
                    350: int
                    351: get_redirect_rule_by_index(int index,
                    352:     char * ifname, unsigned short * eport,
                    353:     char * iaddr, int iaddrlen, unsigned short * iport,
                    354:     int * proto, char * desc, int desclen,
1.1.1.2 ! misho     355:     char * rhost, int rhostlen,
        !           356:     unsigned int * timestamp,
1.1       misho     357:     u_int64_t * packets, u_int64_t * bytes)
                    358: {
                    359:        ipfgeniter_t iter;
                    360:        ipfobj_t obj;
                    361:        ipnat_t ipn;
                    362:        int n, r;
                    363: 
                    364:        if (index < 0)
                    365:                return -1;
                    366: 
                    367:        if (dev < 0) {
                    368:                syslog(LOG_ERR, "%s not open", IPNAT_NAME);
                    369:                return -1;
                    370:        }
                    371: 
                    372:        memset(&obj, 0, sizeof(obj));
                    373:        obj.ipfo_rev = IPFILTER_VERSION;
                    374:        obj.ipfo_ptr = &iter;
                    375:        obj.ipfo_size = sizeof(iter);
                    376:        obj.ipfo_type = IPFOBJ_GENITER;
                    377: 
                    378:        iter.igi_type = IPFGENITER_IPNAT;
                    379: #if IPFILTER_VERSION > 4011300
                    380:        iter.igi_nitems = 1;
                    381: #endif
                    382:        iter.igi_data = &ipn;
                    383: 
                    384:        n = 0;
                    385:        r = -1;
                    386:        do {
                    387:                if (ioctl(dev, SIOCGENITER, &obj) == -1) {
                    388:                        syslog(LOG_ERR, "%s:ioctl(SIOCGENITER): %m",
                    389:                            "get_redirect_rule_by_index");
                    390:                        break;
                    391:                }
                    392: 
                    393:                if (strcmp(ipn.in_tag.ipt_tag, group_name) != 0)
                    394:                        continue;
                    395: 
                    396:                if (index == n++) {
                    397:                        *proto = ipn.in_p;
                    398:                        *eport = ntohs(ipn.in_pmax);
                    399:                        *iport = ntohs(ipn.in_pnext);
                    400: 
                    401:                        if (ifname)
                    402:                                strlcpy(ifname, ipn.in_ifnames[0], IFNAMSIZ);
                    403:                        if (packets != NULL)
                    404:                                *packets = 0;
                    405:                        if (bytes != NULL)
                    406:                                *bytes = 0;
1.1.1.2 ! misho     407:                        if ((desc != NULL) && (timestamp != NULL))
        !           408:                                get_redirect_desc(*eport, *proto, desc, desclen, timestamp);
        !           409:                        if ((rhost != NULL) && (rhostlen > 0))
        !           410:                                inet_ntop(AF_INET, &ipn.in_src[0].in4, rhost, rhostlen);
1.1       misho     411:                        inet_ntop(AF_INET, &ipn.in_in[0].in4, iaddr, iaddrlen);
                    412:                        r = 0;
                    413:                }
                    414:        } while (ipn.in_next != NULL);
                    415:        return r;
                    416: }
                    417: 
                    418: static int
                    419: real_delete_redirect_rule(const char * ifname, unsigned short eport, int proto)
                    420: {
                    421:        ipfgeniter_t iter;
                    422:        ipfobj_t obj;
                    423:        ipnat_t ipn;
                    424:        int r;
                    425: 
                    426:        memset(&obj, 0, sizeof(obj));
                    427:        obj.ipfo_rev = IPFILTER_VERSION;
                    428:        obj.ipfo_type = IPFOBJ_GENITER;
                    429:        obj.ipfo_size = sizeof(iter);
                    430:        obj.ipfo_ptr = &iter;
                    431: 
                    432:        iter.igi_type = IPFGENITER_IPNAT;
                    433: #if IPFILTER_VERSION > 4011300
                    434:        iter.igi_nitems = 1;
                    435: #endif
                    436:        iter.igi_data = &ipn;
                    437: 
                    438:        if (dev < 0) {
                    439:                syslog(LOG_ERR, "%s not open", IPNAT_NAME);
                    440:                return -1;
                    441:        }
                    442: 
                    443:        r = -1;
                    444:        do {
                    445:                if (ioctl(dev, SIOCGENITER, &obj) == -1) {
                    446:                        syslog(LOG_ERR, "%s:ioctl(SIOCGENITER): %m",
                    447:                            "delete_redirect_rule");
                    448:                        break;
                    449:                }
                    450:                if (eport == ntohs(ipn.in_pmin) &&
                    451:                    eport == ntohs(ipn.in_pmax) &&
                    452:                    strcmp(ipn.in_tag.ipt_tag, group_name) == 0 &&
                    453:                    ipn.in_p == proto)
                    454:                {
                    455:                        obj.ipfo_rev = IPFILTER_VERSION;
                    456:                        obj.ipfo_size = sizeof(ipn);
                    457:                        obj.ipfo_ptr = &ipn;
                    458:                        obj.ipfo_type = IPFOBJ_IPNAT;
                    459:                        r = ioctl(dev, SIOCRMNAT, &obj);
                    460:                        if (r == -1)
                    461:                                syslog(LOG_ERR, "%s:ioctl(SIOCRMNAT): %m",
                    462:                                    "delete_redirect_rule");
                    463:                        /* Delete the desc even if the above failed */
                    464:                        del_redirect_desc(eport, proto);
                    465:                        break;
                    466:                }
                    467:        } while (ipn.in_next != NULL);
                    468:        return r;
                    469: }
                    470: 
                    471: /* FIXME: For some reason, the iter isn't reset every other delete,
                    472:  * so we attempt 2 deletes. */
                    473: int
                    474: delete_redirect_rule(const char * ifname, unsigned short eport, int proto)
                    475: {
                    476:        int r;
                    477: 
                    478:        r = real_delete_redirect_rule(ifname, eport, proto);
                    479:        if (r == -1)
                    480:                r = real_delete_redirect_rule(ifname, eport, proto);
                    481:        return r;
                    482: }
                    483: 
                    484: /* thanks to Seth Mos for this function */
                    485: int
1.1.1.2 ! misho     486: add_filter_rule2(const char * ifname, const char * rhost,
        !           487:     const char * iaddr, unsigned short eport, unsigned short iport,
1.1       misho     488:     int proto, const char * desc)
                    489: {
                    490:        ipfobj_t obj;
                    491:        frentry_t fr;
                    492:        fripf_t ipffr;
                    493:        int r;
                    494: 
                    495:        if (dev_ipl < 0) {
                    496:                syslog(LOG_ERR, "%s not open", IPL_NAME);
                    497:                return -1;
                    498:        }
                    499: 
                    500:        memset(&obj, 0, sizeof(obj));
                    501:        memset(&fr, 0, sizeof(fr));
                    502:        memset(&ipffr, 0, sizeof(ipffr));
                    503: 
                    504:        fr.fr_flags = FR_PASS|FR_KEEPSTATE|FR_QUICK|FR_INQUE;
                    505:        if (GETFLAG(LOGPACKETSMASK))
                    506:                fr.fr_flags |= FR_LOG|FR_LOGFIRST;
                    507:        fr.fr_v = 4;
                    508: 
                    509:        fr.fr_type = FR_T_IPF;
                    510:        fr.fr_dun.fru_ipf = &ipffr;
                    511:        fr.fr_dsize = sizeof(ipffr);
                    512:        fr.fr_isc = (void *)-1;
                    513: 
                    514:        fr.fr_proto = proto;
                    515:        fr.fr_mproto = 0xff;
                    516:        fr.fr_dcmp = FR_EQUAL;
                    517:        fr.fr_dport = eport;
                    518: #ifdef USE_IFNAME_IN_RULES
                    519:        if (ifname)
                    520:                strlcpy(fr.fr_ifnames[0], ifname, IFNAMSIZ);
                    521: #endif
                    522:        strlcpy(fr.fr_group, group_name, sizeof(fr.fr_group));
                    523: 
                    524:        if (proto == IPPROTO_TCP) {
                    525:                fr.fr_tcpf = TH_SYN;
                    526:                fr.fr_tcpfm = TH_SYN|TH_ACK|TH_RST|TH_FIN|TH_URG|TH_PUSH;
                    527:        }
                    528: 
1.1.1.2 ! misho     529:        if(rhost && rhost[0] != '\0' && rhost[0] != '*')
        !           530:        {
        !           531:                inet_pton(AF_INET, rhost, &fr.fr_saddr);
        !           532:                fr.fr_smask = 0xffffffff;
        !           533:        }
        !           534: 
1.1       misho     535:        inet_pton(AF_INET, iaddr, &fr.fr_daddr);
                    536:        fr.fr_dmask = 0xffffffff;
                    537: 
                    538:        obj.ipfo_rev = IPFILTER_VERSION;
                    539:        obj.ipfo_ptr = &fr;
                    540:        obj.ipfo_size = sizeof(fr);
                    541: 
                    542:        r = ioctl(dev_ipl, SIOCINAFR, &obj);
                    543:        if (r == -1) {
                    544:                if (errno == ESRCH)
                    545:                        syslog(LOG_ERR,
                    546:                            "SIOCINAFR(missing 'head %s' rule?):%m",
                    547:                            group_name);
                    548:                else
                    549:                        syslog(LOG_ERR, "SIOCINAFR:%m");
                    550:        }
                    551:        return r;
                    552: }
                    553: 
                    554: int
                    555: delete_filter_rule(const char * ifname, unsigned short eport, int proto)
                    556: {
                    557:        ipfobj_t wobj, dobj;
                    558:        ipfruleiter_t rule;
                    559:        u_long darray[1000];
                    560:        u_long array[1000];
                    561:        friostat_t fio;
                    562:        frentry_t *fp;
                    563:        int r;
                    564: 
                    565:        if (dev_ipl < 0) {
                    566:                syslog(LOG_ERR, "%s not open", IPL_NAME);
                    567:                return -1;
                    568:        }
                    569: 
                    570:        wobj.ipfo_rev = IPFILTER_VERSION;
                    571:        wobj.ipfo_type = IPFOBJ_IPFSTAT;
                    572:        wobj.ipfo_size = sizeof(fio);
                    573:        wobj.ipfo_ptr = &fio;
                    574: 
                    575:        if (ioctl(dev_ipl, SIOCGETFS, &wobj) == -1) {
                    576:                syslog(LOG_ERR, "ioctl(SIOCGETFS): %m");
                    577:                return -1;
                    578:        }
                    579: 
                    580:        wobj.ipfo_rev = IPFILTER_VERSION;
                    581:        wobj.ipfo_ptr = &rule;
                    582:        wobj.ipfo_size = sizeof(rule);
                    583:        wobj.ipfo_type = IPFOBJ_IPFITER;
                    584: 
                    585:        fp = (frentry_t *)array;
                    586:        fp->fr_dun.fru_data = darray;
                    587:        fp->fr_dsize = sizeof(darray);
                    588: 
                    589:        rule.iri_inout = 0;
                    590:        rule.iri_active = fio.f_active;
                    591: #if IPFILTER_VERSION > 4011300
                    592:        rule.iri_nrules = 1;
                    593:        rule.iri_v = 4;
                    594: #endif
                    595:        rule.iri_rule = fp;
                    596:        strlcpy(rule.iri_group, group_name, sizeof(rule.iri_group));
                    597: 
                    598:        dobj.ipfo_rev = IPFILTER_VERSION;
                    599:        dobj.ipfo_size = sizeof(*fp);
                    600:        dobj.ipfo_type = IPFOBJ_FRENTRY;
                    601: 
                    602:        r = -1;
                    603:        do {
                    604:                memset(array, 0xff, sizeof(array));
                    605: 
                    606:                if (ioctl(dev_ipl, SIOCIPFITER, &wobj) == -1) {
                    607:                        syslog(LOG_ERR, "ioctl(SIOCIPFITER): %m");
                    608:                        break;
                    609:                }
                    610: 
                    611:                if (fp->fr_data != NULL)
                    612:                        fp->fr_data = (char *)fp + sizeof(*fp);
                    613:                if ((fp->fr_type & ~FR_T_BUILTIN) == FR_T_IPF &&
                    614:                    fp->fr_dport == eport &&
                    615:                    fp->fr_proto == proto)
                    616:                {
                    617:                        dobj.ipfo_ptr = fp;
                    618: 
                    619:                        r = ioctl(dev_ipl, SIOCRMAFR, &dobj);
                    620:                        if (r == -1)
                    621:                                syslog(LOG_ERR, "ioctl(SIOCRMAFR): %m");
                    622:                        break;
                    623:                }
                    624:        } while (fp->fr_next != NULL);
                    625:        return r;
                    626: }
                    627: 
1.1.1.2 ! misho     628: unsigned short *
        !           629: get_portmappings_in_range(unsigned short startport, unsigned short endport,
        !           630:                           int proto, unsigned int * number)
        !           631: {
        !           632:        unsigned short * array;
        !           633:        unsigned int capacity;
        !           634:        unsigned short eport;
        !           635:        ipfgeniter_t iter;
        !           636:        ipfobj_t obj;
        !           637:        ipnat_t ipn;
        !           638: 
        !           639:        *number = 0;
        !           640:        if (dev < 0) {
        !           641:                syslog(LOG_ERR, "%s not open", IPNAT_NAME);
        !           642:                return NULL;
        !           643:        }
        !           644:        capacity = 128;
        !           645:        array = calloc(capacity, sizeof(unsigned short));
        !           646:        if(!array)
        !           647:        {
        !           648:                syslog(LOG_ERR, "get_portmappings_in_range() : calloc error");
        !           649:                return NULL;
        !           650:        }
        !           651:        
        !           652:        memset(&obj, 0, sizeof(obj));
        !           653:        obj.ipfo_rev = IPFILTER_VERSION;
        !           654:        obj.ipfo_ptr = &iter;
        !           655:        obj.ipfo_size = sizeof(iter);
        !           656:        obj.ipfo_type = IPFOBJ_GENITER;
        !           657: 
        !           658:        iter.igi_type = IPFGENITER_IPNAT;
        !           659: #if IPFILTER_VERSION > 4011300
        !           660:        iter.igi_nitems = 1;
        !           661: #endif
        !           662:        iter.igi_data = &ipn;
        !           663: 
        !           664:        do {
        !           665:                if (ioctl(dev, SIOCGENITER, &obj) == -1) {
        !           666:                        syslog(LOG_ERR, "%s:ioctl(SIOCGENITER): %m",
        !           667:                            "get_portmappings_in_range");
        !           668:                        break;
        !           669:                }
        !           670:                
        !           671:                if (strcmp(ipn.in_tag.ipt_tag, group_name) != 0)
        !           672:                        continue;
        !           673:                
        !           674:                eport = ntohs(ipn.in_pmin);
        !           675:                if( (eport == ntohs(ipn.in_pmax))
        !           676:                  && (ipn.in_p == proto)
        !           677:                  && (startport <= eport) && (eport <= endport) )
        !           678:                {
        !           679:                        if(*number >= capacity)
        !           680:                        {
        !           681:                                /* need to increase the capacity of the array */
        !           682:                                capacity += 128;
        !           683:                                array = realloc(array, sizeof(unsigned short)*capacity);
        !           684:                                if(!array)
        !           685:                                {
        !           686:                                        syslog(LOG_ERR, "get_portmappings_in_range() : realloc(%lu) error", sizeof(unsigned short)*capacity);
        !           687:                                        *number = 0;
        !           688:                                        return NULL;
        !           689:                                }
        !           690:                        }
        !           691:                        array[*number] = eport;
        !           692:                        (*number)++;
        !           693:                }
        !           694:        } while (ipn.in_next != NULL);
        !           695:        return array;
        !           696: }

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