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

1.1       misho       1: /* $Id: ipfrdr.c,v 1.11 2009/10/10 18:34:39 nanard Exp $ */
                      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;
                    134:        char str[];
                    135: };
                    136: 
                    137: /* pointer to the chained list where descriptions are stored */
                    138: static struct rdr_desc * rdr_desc_list;
                    139: 
                    140: static void
                    141: add_redirect_desc(unsigned short eport, int proto, const char * desc)
                    142: {
                    143:        struct rdr_desc * p;
                    144:        size_t l;
                    145:        
                    146:        if (desc != NULL) {
                    147:                l = strlen(desc) + 1;
                    148:                p = malloc(sizeof(struct rdr_desc) + l);
                    149:                if (p) {
                    150:                        p->next = rdr_desc_list;
                    151:                        p->eport = eport;
                    152:                        p->proto = proto;
                    153:                        memcpy(p->str, desc, l);
                    154:                        rdr_desc_list = p;
                    155:                }
                    156:        }
                    157: }
                    158: 
                    159: static void
                    160: del_redirect_desc(unsigned short eport, int proto)
                    161: {
                    162:        struct rdr_desc * p, * last;
                    163: 
                    164:        last = NULL;
                    165:        for (p = rdr_desc_list; p; p = p->next) {
                    166:                if(p->eport == eport && p->proto == proto) {
                    167:                        if (last == NULL)
                    168:                                rdr_desc_list = p->next;
                    169:                        else
                    170:                                last->next = p->next;
                    171:                        free(p);
                    172:                        return;
                    173:                }
                    174:        }
                    175: }
                    176: 
                    177: static void
                    178: get_redirect_desc(unsigned short eport, int proto, char * desc, int desclen)
                    179: {
                    180:        struct rdr_desc * p;
                    181:        
                    182:        if (desc == NULL || desclen == 0)
                    183:                return;
                    184:        for (p = rdr_desc_list; p; p = p->next) {
                    185:                if (p->eport == eport && p->proto == proto)
                    186:                {
                    187:                        strncpy(desc, p->str, desclen);
                    188:                        return;
                    189:                }
                    190:        }
                    191: }
                    192: 
                    193: int init_redirect(void)
                    194: {
                    195:        
                    196:        dev = open(IPNAT_NAME, O_RDWR);
                    197:        if (dev < 0) {
                    198:                syslog(LOG_ERR, "open(\"%s\"): %m", IPNAT_NAME);
                    199:                return -1;
                    200:        }
                    201:        dev_ipl = open(IPL_NAME, O_RDWR);
                    202:        if (dev_ipl < 0) {
                    203:                syslog(LOG_ERR, "open(\"%s\"): %m", IPL_NAME);
                    204:                return -1;
                    205:        }
                    206:        return 0;
                    207: }
                    208: 
                    209: void shutdown_redirect(void)
                    210: {
                    211:        
                    212:        if (dev >= 0) {
                    213:                close(dev);
                    214:                dev = -1;
                    215:        }
                    216:        if (dev_ipl >= 0) {
                    217:                close(dev_ipl);
                    218:                dev = -1;
                    219:        }
                    220:        return;
                    221: }
                    222: 
                    223: int
                    224: add_redirect_rule2(const char * ifname, unsigned short eport,
                    225:     const char * iaddr, unsigned short iport, int proto,
                    226:     const char * desc)
                    227: {
                    228:        struct ipnat ipnat;
                    229:        struct ipfobj obj;
                    230:        int r;
                    231: 
                    232:        if (dev < 0) {
                    233:                syslog(LOG_ERR, "%s not open", IPNAT_NAME);
                    234:                return -1;
                    235:        }
                    236: 
                    237:        memset(&obj, 0, sizeof(obj));
                    238:        memset(&ipnat, 0, sizeof(ipnat));
                    239: 
                    240:        ipnat.in_redir = NAT_REDIRECT;
                    241:        ipnat.in_p = proto;
                    242:        if (proto == IPPROTO_TCP)
                    243:                ipnat.in_flags = IPN_TCP;
                    244:        if (proto == IPPROTO_UDP)
                    245:                ipnat.in_flags = IPN_UDP;
                    246:        ipnat.in_dcmp = FR_EQUAL;
                    247:        ipnat.in_pmin = htons(eport);
                    248:        ipnat.in_pmax = htons(eport);
                    249:        ipnat.in_pnext = htons(iport);
                    250:        ipnat.in_v = 4;
                    251:        strlcpy(ipnat.in_tag.ipt_tag, group_name, IPFTAG_LEN);
                    252: 
                    253: #ifdef USE_IFNAME_IN_RULES
                    254:        if (ifname) {
                    255:                strlcpy(ipnat.in_ifnames[0], ifname, IFNAMSIZ);
                    256:                strlcpy(ipnat.in_ifnames[1], ifname, IFNAMSIZ);
                    257:        }
                    258: #endif
                    259: 
                    260:        inet_pton(AF_INET, iaddr, &ipnat.in_in[0].in4);
                    261:        ipnat.in_in[1].in4.s_addr = 0xffffffff;
                    262: 
                    263:        obj.ipfo_rev = IPFILTER_VERSION;
                    264:        obj.ipfo_size = sizeof(ipnat);
                    265:        obj.ipfo_ptr = &ipnat;
                    266:        obj.ipfo_type = IPFOBJ_IPNAT;
                    267: 
                    268:        r = ioctl(dev, SIOCADNAT, &obj);
                    269:        if (r == -1)
                    270:                syslog(LOG_ERR, "ioctl(SIOCADNAT): %m");
                    271:        else
                    272:                add_redirect_desc(eport, proto, desc);
                    273:        return r;
                    274: }
                    275: 
                    276: /* get_redirect_rule()
                    277:  * return value : 0 success (found)
                    278:  * -1 = error or rule not found */
                    279: int
                    280: get_redirect_rule(const char * ifname, unsigned short eport, int proto,
                    281:     char * iaddr, int iaddrlen, unsigned short * iport,
                    282:     char * desc, int desclen,
                    283:     u_int64_t * packets, u_int64_t * bytes)
                    284: {
                    285:        ipfgeniter_t iter;
                    286:        ipfobj_t obj;
                    287:        ipnat_t ipn;
                    288:        int r;
                    289: 
                    290:        memset(&obj, 0, sizeof(obj));
                    291:        obj.ipfo_rev = IPFILTER_VERSION;
                    292:        obj.ipfo_type = IPFOBJ_GENITER;
                    293:        obj.ipfo_size = sizeof(iter);
                    294:        obj.ipfo_ptr = &iter;
                    295: 
                    296:        iter.igi_type = IPFGENITER_IPNAT;
                    297: #if IPFILTER_VERSION > 4011300
                    298:        iter.igi_nitems = 1;
                    299: #endif
                    300:        iter.igi_data = &ipn;
                    301: 
                    302:        if (dev < 0) {
                    303:                syslog(LOG_ERR, "%s not open", IPNAT_NAME);
                    304:                return -1;
                    305:        }
                    306: 
                    307:        r = -1;
                    308:        do {
                    309:                if (ioctl(dev, SIOCGENITER, &obj) == -1) {
                    310:                        syslog(LOG_ERR, "ioctl(dev, SIOCGENITER): %m");
                    311:                        break;
                    312:                }
                    313:                if (eport == ntohs(ipn.in_pmin) &&
                    314:                    eport == ntohs(ipn.in_pmax) &&
                    315:                    strcmp(ipn.in_tag.ipt_tag, group_name) == 0 &&
                    316:                    ipn.in_p == proto)
                    317:                {
                    318:                        strlcpy(desc, "", desclen);
                    319:                        if (packets != NULL)
                    320:                                *packets = 0;
                    321:                        if (bytes != NULL)
                    322:                                *bytes = 0;
                    323:                        if (iport != NULL)
                    324:                                *iport = ntohs(ipn.in_pnext);
                    325:                        if (desc != NULL)
                    326:                                get_redirect_desc(eport, proto, desc, desclen);
                    327:                        inet_ntop(AF_INET, &ipn.in_in[0].in4, iaddr, iaddrlen);
                    328:                        r = 0;
                    329:                }
                    330:        } while (ipn.in_next != NULL);
                    331:        return r;
                    332: }
                    333: 
                    334: 
                    335: int
                    336: get_redirect_rule_by_index(int index,
                    337:     char * ifname, unsigned short * eport,
                    338:     char * iaddr, int iaddrlen, unsigned short * iport,
                    339:     int * proto, char * desc, int desclen,
                    340:     u_int64_t * packets, u_int64_t * bytes)
                    341: {
                    342:        ipfgeniter_t iter;
                    343:        ipfobj_t obj;
                    344:        ipnat_t ipn;
                    345:        int n, r;
                    346: 
                    347:        if (index < 0)
                    348:                return -1;
                    349: 
                    350:        if (dev < 0) {
                    351:                syslog(LOG_ERR, "%s not open", IPNAT_NAME);
                    352:                return -1;
                    353:        }
                    354: 
                    355:        memset(&obj, 0, sizeof(obj));
                    356:        obj.ipfo_rev = IPFILTER_VERSION;
                    357:        obj.ipfo_ptr = &iter;
                    358:        obj.ipfo_size = sizeof(iter);
                    359:        obj.ipfo_type = IPFOBJ_GENITER;
                    360: 
                    361:        iter.igi_type = IPFGENITER_IPNAT;
                    362: #if IPFILTER_VERSION > 4011300
                    363:        iter.igi_nitems = 1;
                    364: #endif
                    365:        iter.igi_data = &ipn;
                    366: 
                    367:        n = 0;
                    368:        r = -1;
                    369:        do {
                    370:                if (ioctl(dev, SIOCGENITER, &obj) == -1) {
                    371:                        syslog(LOG_ERR, "%s:ioctl(SIOCGENITER): %m",
                    372:                            "get_redirect_rule_by_index");
                    373:                        break;
                    374:                }
                    375: 
                    376:                if (strcmp(ipn.in_tag.ipt_tag, group_name) != 0)
                    377:                        continue;
                    378: 
                    379:                if (index == n++) {
                    380:                        *proto = ipn.in_p;
                    381:                        *eport = ntohs(ipn.in_pmax);
                    382:                        *iport = ntohs(ipn.in_pnext);
                    383: 
                    384:                        if (ifname)
                    385:                                strlcpy(ifname, ipn.in_ifnames[0], IFNAMSIZ);
                    386:                        if (packets != NULL)
                    387:                                *packets = 0;
                    388:                        if (bytes != NULL)
                    389:                                *bytes = 0;
                    390:                        if (desc != NULL)
                    391:                                get_redirect_desc(*eport, *proto, desc, desclen);
                    392:                        inet_ntop(AF_INET, &ipn.in_in[0].in4, iaddr, iaddrlen);
                    393:                        r = 0;
                    394:                }
                    395:        } while (ipn.in_next != NULL);
                    396:        return r;
                    397: }
                    398: 
                    399: static int
                    400: real_delete_redirect_rule(const char * ifname, unsigned short eport, int proto)
                    401: {
                    402:        ipfgeniter_t iter;
                    403:        ipfobj_t obj;
                    404:        ipnat_t ipn;
                    405:        int r;
                    406: 
                    407:        memset(&obj, 0, sizeof(obj));
                    408:        obj.ipfo_rev = IPFILTER_VERSION;
                    409:        obj.ipfo_type = IPFOBJ_GENITER;
                    410:        obj.ipfo_size = sizeof(iter);
                    411:        obj.ipfo_ptr = &iter;
                    412: 
                    413:        iter.igi_type = IPFGENITER_IPNAT;
                    414: #if IPFILTER_VERSION > 4011300
                    415:        iter.igi_nitems = 1;
                    416: #endif
                    417:        iter.igi_data = &ipn;
                    418: 
                    419:        if (dev < 0) {
                    420:                syslog(LOG_ERR, "%s not open", IPNAT_NAME);
                    421:                return -1;
                    422:        }
                    423: 
                    424:        r = -1;
                    425:        do {
                    426:                if (ioctl(dev, SIOCGENITER, &obj) == -1) {
                    427:                        syslog(LOG_ERR, "%s:ioctl(SIOCGENITER): %m",
                    428:                            "delete_redirect_rule");
                    429:                        break;
                    430:                }
                    431:                if (eport == ntohs(ipn.in_pmin) &&
                    432:                    eport == ntohs(ipn.in_pmax) &&
                    433:                    strcmp(ipn.in_tag.ipt_tag, group_name) == 0 &&
                    434:                    ipn.in_p == proto)
                    435:                {
                    436:                        obj.ipfo_rev = IPFILTER_VERSION;
                    437:                        obj.ipfo_size = sizeof(ipn);
                    438:                        obj.ipfo_ptr = &ipn;
                    439:                        obj.ipfo_type = IPFOBJ_IPNAT;
                    440:                        r = ioctl(dev, SIOCRMNAT, &obj);
                    441:                        if (r == -1)
                    442:                                syslog(LOG_ERR, "%s:ioctl(SIOCRMNAT): %m",
                    443:                                    "delete_redirect_rule");
                    444:                        /* Delete the desc even if the above failed */
                    445:                        del_redirect_desc(eport, proto);
                    446:                        break;
                    447:                }
                    448:        } while (ipn.in_next != NULL);
                    449:        return r;
                    450: }
                    451: 
                    452: /* FIXME: For some reason, the iter isn't reset every other delete,
                    453:  * so we attempt 2 deletes. */
                    454: int
                    455: delete_redirect_rule(const char * ifname, unsigned short eport, int proto)
                    456: {
                    457:        int r;
                    458: 
                    459:        r = real_delete_redirect_rule(ifname, eport, proto);
                    460:        if (r == -1)
                    461:                r = real_delete_redirect_rule(ifname, eport, proto);
                    462:        return r;
                    463: }
                    464: 
                    465: /* thanks to Seth Mos for this function */
                    466: int
                    467: add_filter_rule2(const char * ifname, const char * iaddr,
                    468:     unsigned short eport, unsigned short iport,
                    469:     int proto, const char * desc)
                    470: {
                    471:        ipfobj_t obj;
                    472:        frentry_t fr;
                    473:        fripf_t ipffr;
                    474:        int r;
                    475: 
                    476:        if (dev_ipl < 0) {
                    477:                syslog(LOG_ERR, "%s not open", IPL_NAME);
                    478:                return -1;
                    479:        }
                    480: 
                    481:        memset(&obj, 0, sizeof(obj));
                    482:        memset(&fr, 0, sizeof(fr));
                    483:        memset(&ipffr, 0, sizeof(ipffr));
                    484: 
                    485:        fr.fr_flags = FR_PASS|FR_KEEPSTATE|FR_QUICK|FR_INQUE;
                    486:        if (GETFLAG(LOGPACKETSMASK))
                    487:                fr.fr_flags |= FR_LOG|FR_LOGFIRST;
                    488:        fr.fr_v = 4;
                    489: 
                    490:        fr.fr_type = FR_T_IPF;
                    491:        fr.fr_dun.fru_ipf = &ipffr;
                    492:        fr.fr_dsize = sizeof(ipffr);
                    493:        fr.fr_isc = (void *)-1;
                    494: 
                    495:        fr.fr_proto = proto;
                    496:        fr.fr_mproto = 0xff;
                    497:        fr.fr_dcmp = FR_EQUAL;
                    498:        fr.fr_dport = eport;
                    499: #ifdef USE_IFNAME_IN_RULES
                    500:        if (ifname)
                    501:                strlcpy(fr.fr_ifnames[0], ifname, IFNAMSIZ);
                    502: #endif
                    503:        strlcpy(fr.fr_group, group_name, sizeof(fr.fr_group));
                    504: 
                    505:        if (proto == IPPROTO_TCP) {
                    506:                fr.fr_tcpf = TH_SYN;
                    507:                fr.fr_tcpfm = TH_SYN|TH_ACK|TH_RST|TH_FIN|TH_URG|TH_PUSH;
                    508:        }
                    509: 
                    510:        inet_pton(AF_INET, iaddr, &fr.fr_daddr);
                    511:        fr.fr_dmask = 0xffffffff;
                    512: 
                    513:        obj.ipfo_rev = IPFILTER_VERSION;
                    514:        obj.ipfo_ptr = &fr;
                    515:        obj.ipfo_size = sizeof(fr);
                    516: 
                    517:        r = ioctl(dev_ipl, SIOCINAFR, &obj);
                    518:        if (r == -1) {
                    519:                if (errno == ESRCH)
                    520:                        syslog(LOG_ERR,
                    521:                            "SIOCINAFR(missing 'head %s' rule?):%m",
                    522:                            group_name);
                    523:                else
                    524:                        syslog(LOG_ERR, "SIOCINAFR:%m");
                    525:        }
                    526:        return r;
                    527: }
                    528: 
                    529: int
                    530: delete_filter_rule(const char * ifname, unsigned short eport, int proto)
                    531: {
                    532:        ipfobj_t wobj, dobj;
                    533:        ipfruleiter_t rule;
                    534:        u_long darray[1000];
                    535:        u_long array[1000];
                    536:        friostat_t fio;
                    537:        frentry_t *fp;
                    538:        int r;
                    539: 
                    540:        if (dev_ipl < 0) {
                    541:                syslog(LOG_ERR, "%s not open", IPL_NAME);
                    542:                return -1;
                    543:        }
                    544: 
                    545:        wobj.ipfo_rev = IPFILTER_VERSION;
                    546:        wobj.ipfo_type = IPFOBJ_IPFSTAT;
                    547:        wobj.ipfo_size = sizeof(fio);
                    548:        wobj.ipfo_ptr = &fio;
                    549: 
                    550:        if (ioctl(dev_ipl, SIOCGETFS, &wobj) == -1) {
                    551:                syslog(LOG_ERR, "ioctl(SIOCGETFS): %m");
                    552:                return -1;
                    553:        }
                    554: 
                    555:        wobj.ipfo_rev = IPFILTER_VERSION;
                    556:        wobj.ipfo_ptr = &rule;
                    557:        wobj.ipfo_size = sizeof(rule);
                    558:        wobj.ipfo_type = IPFOBJ_IPFITER;
                    559: 
                    560:        fp = (frentry_t *)array;
                    561:        fp->fr_dun.fru_data = darray;
                    562:        fp->fr_dsize = sizeof(darray);
                    563: 
                    564:        rule.iri_inout = 0;
                    565:        rule.iri_active = fio.f_active;
                    566: #if IPFILTER_VERSION > 4011300
                    567:        rule.iri_nrules = 1;
                    568:        rule.iri_v = 4;
                    569: #endif
                    570:        rule.iri_rule = fp;
                    571:        strlcpy(rule.iri_group, group_name, sizeof(rule.iri_group));
                    572: 
                    573:        dobj.ipfo_rev = IPFILTER_VERSION;
                    574:        dobj.ipfo_size = sizeof(*fp);
                    575:        dobj.ipfo_type = IPFOBJ_FRENTRY;
                    576: 
                    577:        r = -1;
                    578:        do {
                    579:                memset(array, 0xff, sizeof(array));
                    580: 
                    581:                if (ioctl(dev_ipl, SIOCIPFITER, &wobj) == -1) {
                    582:                        syslog(LOG_ERR, "ioctl(SIOCIPFITER): %m");
                    583:                        break;
                    584:                }
                    585: 
                    586:                if (fp->fr_data != NULL)
                    587:                        fp->fr_data = (char *)fp + sizeof(*fp);
                    588:                if ((fp->fr_type & ~FR_T_BUILTIN) == FR_T_IPF &&
                    589:                    fp->fr_dport == eport &&
                    590:                    fp->fr_proto == proto)
                    591:                {
                    592:                        dobj.ipfo_ptr = fp;
                    593: 
                    594:                        r = ioctl(dev_ipl, SIOCRMAFR, &dobj);
                    595:                        if (r == -1)
                    596:                                syslog(LOG_ERR, "ioctl(SIOCRMAFR): %m");
                    597:                        break;
                    598:                }
                    599:        } while (fp->fr_next != NULL);
                    600:        return r;
                    601: }
                    602: 

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