Annotation of embedaddon/miniupnpd/upnpredirect.c, revision 1.1.1.3

1.1.1.3 ! misho       1: /* $Id: upnpredirect.c,v 1.80 2012/05/01 20:08:22 nanard Exp $ */
1.1       misho       2: /* MiniUPnP project
                      3:  * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
1.1.1.3 ! misho       4:  * (c) 2006-2012 Thomas Bernard
1.1       misho       5:  * This software is subject to the conditions detailed
                      6:  * in the LICENCE file provided within the distribution */
                      7: 
                      8: #include <stdlib.h>
                      9: #include <string.h>
                     10: #include <syslog.h>
                     11: #include <sys/types.h>
                     12: #include <sys/socket.h>
                     13: #include <netinet/in.h>
                     14: #include <net/if.h>
                     15: #include <arpa/inet.h>
                     16: 
                     17: #include <stdio.h>
                     18: #include <ctype.h>
                     19: #include <unistd.h>
                     20: 
1.1.1.3 ! misho      21: #include "macros.h"
1.1       misho      22: #include "config.h"
                     23: #include "upnpredirect.h"
                     24: #include "upnpglobalvars.h"
                     25: #include "upnpevents.h"
                     26: #if defined(USE_NETFILTER)
                     27: #include "netfilter/iptcrdr.h"
                     28: #endif
                     29: #if defined(USE_PF)
                     30: #include "pf/obsdrdr.h"
                     31: #endif
                     32: #if defined(USE_IPF)
                     33: #include "ipf/ipfrdr.h"
                     34: #endif
                     35: #if defined(USE_IPFW)
                     36: #include "ipfw/ipfwrdr.h"
                     37: #endif
                     38: #ifdef USE_MINIUPNPDCTL
                     39: #include <stdio.h>
                     40: #include <unistd.h>
                     41: #endif
                     42: #ifdef ENABLE_LEASEFILE
                     43: #include <sys/stat.h>
                     44: #endif
                     45: 
                     46: /* from <inttypes.h> */
                     47: #ifndef PRIu64
                     48: #define PRIu64 "llu"
                     49: #endif
                     50: 
1.1.1.3 ! misho      51: /* proto_atoi()
1.1       misho      52:  * convert the string "UDP" or "TCP" to IPPROTO_UDP and IPPROTO_UDP */
                     53: static int
                     54: proto_atoi(const char * protocol)
                     55: {
                     56:        int proto = IPPROTO_TCP;
                     57:        if(strcmp(protocol, "UDP") == 0)
                     58:                proto = IPPROTO_UDP;
                     59:        return proto;
                     60: }
                     61: 
                     62: #ifdef ENABLE_LEASEFILE
1.1.1.2   misho      63: static int
                     64: lease_file_add(unsigned short eport,
                     65:                const char * iaddr,
                     66:                unsigned short iport,
                     67:                int proto,
                     68:                const char * desc,
                     69:                unsigned int timestamp)
1.1       misho      70: {
                     71:        FILE * fd;
                     72: 
                     73:        if (lease_file == NULL) return 0;
                     74: 
                     75:        fd = fopen( lease_file, "a");
                     76:        if (fd==NULL) {
                     77:                syslog(LOG_ERR, "could not open lease file: %s", lease_file);
                     78:                return -1;
                     79:        }
                     80: 
1.1.1.2   misho      81:        fprintf(fd, "%s:%hu:%s:%hu:%u:%s\n",
                     82:                ((proto==IPPROTO_TCP)?"TCP":"UDP"), eport, iaddr, iport,
                     83:                timestamp, desc);
1.1       misho      84:        fclose(fd);
1.1.1.3 ! misho      85: 
1.1       misho      86:        return 0;
                     87: }
                     88: 
1.1.1.2   misho      89: static int
                     90: lease_file_remove(unsigned short eport, int proto)
1.1       misho      91: {
                     92:        FILE* fd, *fdt;
                     93:        int tmp;
                     94:        char buf[512];
                     95:        char str[32];
                     96:        char tmpfilename[128];
                     97:        int str_size, buf_size;
                     98: 
                     99: 
                    100:        if (lease_file == NULL) return 0;
                    101: 
                    102:        if (strlen( lease_file) + 7 > sizeof(tmpfilename)) {
                    103:                syslog(LOG_ERR, "Lease filename is too long");
                    104:                return -1;
                    105:        }
                    106: 
                    107:        strncpy( tmpfilename, lease_file, sizeof(tmpfilename) );
                    108:        strncat( tmpfilename, "XXXXXX", sizeof(tmpfilename) - strlen(tmpfilename));
                    109: 
                    110:        fd = fopen( lease_file, "r");
                    111:        if (fd==NULL) {
                    112:                return 0;
                    113:        }
                    114: 
                    115:        snprintf( str, sizeof(str), "%s:%u", ((proto==IPPROTO_TCP)?"TCP":"UDP"), eport);
                    116:        str_size = strlen(str);
                    117: 
                    118:        tmp = mkstemp(tmpfilename);
                    119:        if (tmp==-1) {
                    120:                fclose(fd);
                    121:                syslog(LOG_ERR, "could not open temporary lease file");
                    122:                return -1;
                    123:        }
                    124:        fchmod(tmp, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
                    125:        fdt = fdopen(tmp, "a");
                    126: 
                    127:        buf[sizeof(buf)-1] = 0;
1.1.1.2   misho     128:        while( fgets(buf, sizeof(buf)-1, fd) != NULL) {
1.1       misho     129:                buf_size = strlen(buf);
                    130: 
1.1.1.2   misho     131:                if (buf_size < str_size || strncmp(str, buf, str_size)!=0) {
1.1       misho     132:                        fwrite(buf, buf_size, 1, fdt);
                    133:                }
                    134:        }
                    135:        fclose(fdt);
                    136:        fclose(fd);
1.1.1.3 ! misho     137: 
1.1.1.2   misho     138:        if (rename(tmpfilename, lease_file) < 0) {
1.1       misho     139:                syslog(LOG_ERR, "could not rename temporary lease file to %s", lease_file);
1.1.1.2   misho     140:                remove(tmpfilename);
1.1       misho     141:        }
1.1.1.3 ! misho     142: 
1.1       misho     143:        return 0;
1.1.1.3 ! misho     144: 
1.1       misho     145: }
                    146: 
                    147: /* reload_from_lease_file()
                    148:  * read lease_file and add the rules contained
                    149:  */
                    150: int reload_from_lease_file()
                    151: {
                    152:        FILE * fd;
                    153:        char * p;
                    154:        unsigned short eport, iport;
                    155:        char * proto;
                    156:        char * iaddr;
                    157:        char * desc;
1.1.1.2   misho     158:        char * rhost;
                    159:        unsigned int leaseduration;
                    160:        unsigned int timestamp;
                    161:        time_t current_time;
1.1       misho     162:        char line[128];
                    163:        int r;
                    164: 
                    165:        if(!lease_file) return -1;
                    166:        fd = fopen( lease_file, "r");
                    167:        if (fd==NULL) {
                    168:                syslog(LOG_ERR, "could not open lease file: %s", lease_file);
                    169:                return -1;
                    170:        }
                    171:        if(unlink(lease_file) < 0) {
                    172:                syslog(LOG_WARNING, "could not unlink file %s : %m", lease_file);
                    173:        }
                    174: 
1.1.1.2   misho     175:        current_time = time(NULL);
1.1       misho     176:        while(fgets(line, sizeof(line), fd)) {
                    177:                syslog(LOG_DEBUG, "parsing lease file line '%s'", line);
                    178:                proto = line;
                    179:                p = strchr(line, ':');
                    180:                if(!p) {
                    181:                        syslog(LOG_ERR, "unrecognized data in lease file");
                    182:                        continue;
                    183:                }
                    184:                *(p++) = '\0';
                    185:                iaddr = strchr(p, ':');
                    186:                if(!iaddr) {
                    187:                        syslog(LOG_ERR, "unrecognized data in lease file");
                    188:                        continue;
                    189:                }
                    190:                *(iaddr++) = '\0';
                    191:                eport = (unsigned short)atoi(p);
                    192:                p = strchr(iaddr, ':');
                    193:                if(!p) {
                    194:                        syslog(LOG_ERR, "unrecognized data in lease file");
                    195:                        continue;
                    196:                }
                    197:                *(p++) = '\0';
1.1.1.3 ! misho     198:                iport = (unsigned short)atoi(p);
1.1.1.2   misho     199:                p = strchr(p, ':');
                    200:                if(!p) {
                    201:                        syslog(LOG_ERR, "unrecognized data in lease file");
                    202:                        continue;
                    203:                }
                    204:                *(p++) = '\0';
1.1       misho     205:                desc = strchr(p, ':');
                    206:                if(!desc) {
                    207:                        syslog(LOG_ERR, "unrecognized data in lease file");
                    208:                        continue;
                    209:                }
                    210:                *(desc++) = '\0';
1.1.1.3 ! misho     211:                /*timestamp = (unsigned int)atoi(p);*/
        !           212:                timestamp = (unsigned int)strtoul(p, NULL, 10);
1.1       misho     213:                /* trim description */
                    214:                while(isspace(*desc))
                    215:                        desc++;
                    216:                p = desc;
                    217:                while(*(p+1))
                    218:                        p++;
                    219:                while(isspace(*p) && (p > desc))
                    220:                        *(p--) = '\0';
                    221: 
1.1.1.2   misho     222:                if(timestamp > 0) {
1.1.1.3 ! misho     223:                        if(timestamp <= (unsigned int)current_time) {
1.1.1.2   misho     224:                                syslog(LOG_NOTICE, "already expired lease in lease file");
                    225:                                continue;
                    226:                        } else {
1.1.1.3 ! misho     227:                                leaseduration = timestamp - current_time;
1.1.1.2   misho     228:                        }
                    229:                } else {
                    230:                        leaseduration = 0;      /* default value */
                    231:                }
                    232:                rhost = NULL;
                    233:                r = upnp_redirect(rhost, eport, iaddr, iport, proto, desc, leaseduration);
1.1       misho     234:                if(r == -1) {
                    235:                        syslog(LOG_ERR, "Failed to redirect %hu -> %s:%hu protocol %s",
                    236:                               eport, iaddr, iport, proto);
                    237:                } else if(r == -2) {
                    238:                        /* Add the redirection again to the lease file */
1.1.1.2   misho     239:                        lease_file_add(eport, iaddr, iport, proto_atoi(proto),
                    240:                                       desc, timestamp);
1.1       misho     241:                }
                    242:        }
                    243:        fclose(fd);
1.1.1.3 ! misho     244: 
1.1       misho     245:        return 0;
                    246: }
                    247: #endif
                    248: 
1.1.1.3 ! misho     249: /* upnp_redirect()
1.1       misho     250:  * calls OS/fw dependant implementation of the redirection.
                    251:  * protocol should be the string "TCP" or "UDP"
                    252:  * returns: 0 on success
                    253:  *          -1 failed to redirect
                    254:  *          -2 already redirected
                    255:  *          -3 permission check failed
                    256:  */
                    257: int
1.1.1.3 ! misho     258: upnp_redirect(const char * rhost, unsigned short eport,
1.1       misho     259:               const char * iaddr, unsigned short iport,
1.1.1.2   misho     260:               const char * protocol, const char * desc,
                    261:               unsigned int leaseduration)
1.1       misho     262: {
                    263:        int proto, r;
                    264:        char iaddr_old[32];
                    265:        unsigned short iport_old;
                    266:        struct in_addr address;
1.1.1.2   misho     267:        unsigned int timestamp;
                    268: 
1.1       misho     269:        proto = proto_atoi(protocol);
                    270:        if(inet_aton(iaddr, &address) < 0) {
                    271:                syslog(LOG_ERR, "inet_aton(%s) : %m", iaddr);
                    272:                return -1;
                    273:        }
                    274: 
                    275:        if(!check_upnp_rule_against_permissions(upnppermlist, num_upnpperm,
                    276:                                                eport, address, iport)) {
                    277:                syslog(LOG_INFO, "redirection permission check failed for "
                    278:                                 "%hu->%s:%hu %s", eport, iaddr, iport, protocol);
                    279:                return -3;
                    280:        }
                    281:        r = get_redirect_rule(ext_if_name, eport, proto,
1.1.1.2   misho     282:                              iaddr_old, sizeof(iaddr_old), &iport_old, 0, 0,
                    283:                              0, 0,
                    284:                              &timestamp, 0, 0);
1.1       misho     285:        if(r == 0) {
                    286:                /* if existing redirect rule matches redirect request return success
                    287:                 * xbox 360 does not keep track of the port it redirects and will
                    288:                 * redirect another port when receiving ConflictInMappingEntry */
1.1.1.2   misho     289:                if(strcmp(iaddr, iaddr_old)==0 && iport==iport_old) {
1.1       misho     290:                        syslog(LOG_INFO, "ignoring redirect request as it matches existing redirect");
                    291:                } else {
                    292: 
                    293:                        syslog(LOG_INFO, "port %hu protocol %s already redirected to %s:%hu",
                    294:                                eport, protocol, iaddr_old, iport_old);
                    295:                        return -2;
                    296:                }
                    297:        } else {
1.1.1.2   misho     298:                timestamp = (leaseduration > 0) ? time(NULL) + leaseduration : 0;
1.1       misho     299:                syslog(LOG_INFO, "redirecting port %hu to %s:%hu protocol %s for: %s",
1.1.1.3 ! misho     300:                        eport, iaddr, iport, protocol, desc);
1.1.1.2   misho     301:                return upnp_redirect_internal(rhost, eport, iaddr, iport, proto,
                    302:                                              desc, timestamp);
1.1       misho     303:        }
                    304: 
                    305:        return 0;
                    306: }
                    307: 
                    308: int
1.1.1.2   misho     309: upnp_redirect_internal(const char * rhost, unsigned short eport,
1.1       misho     310:                        const char * iaddr, unsigned short iport,
1.1.1.2   misho     311:                        int proto, const char * desc,
                    312:                        unsigned int timestamp)
1.1       misho     313: {
                    314:        /*syslog(LOG_INFO, "redirecting port %hu to %s:%hu protocol %s for: %s",
                    315:                eport, iaddr, iport, protocol, desc);                   */
1.1.1.2   misho     316:        if(add_redirect_rule2(ext_if_name, rhost, eport, iaddr, iport, proto,
                    317:                              desc, timestamp) < 0) {
1.1       misho     318:                return -1;
                    319:        }
                    320: 
                    321: #ifdef ENABLE_LEASEFILE
1.1.1.2   misho     322:        lease_file_add( eport, iaddr, iport, proto, desc, timestamp);
1.1       misho     323: #endif
                    324: /*     syslog(LOG_INFO, "creating pass rule to %s:%hu protocol %s for: %s",
                    325:                iaddr, iport, protocol, desc);*/
1.1.1.2   misho     326:        if(add_filter_rule2(ext_if_name, rhost, iaddr, eport, iport, proto, desc) < 0) {
1.1       misho     327:                /* clean up the redirect rule */
                    328: #if !defined(__linux__)
                    329:                delete_redirect_rule(ext_if_name, eport, proto);
                    330: #endif
                    331:                return -1;
                    332:        }
1.1.1.2   misho     333:        if(timestamp > 0) {
                    334:                if(!nextruletoclean_timestamp || (timestamp < nextruletoclean_timestamp))
                    335:                        nextruletoclean_timestamp = timestamp;
                    336:        }
1.1       misho     337: #ifdef ENABLE_EVENTS
1.1.1.2   misho     338:        /* the number of port mappings changed, we must
                    339:         * inform the subscribers */
1.1       misho     340:        upnp_event_var_change_notify(EWanIPC);
                    341: #endif
                    342:        return 0;
                    343: }
                    344: 
                    345: 
                    346: 
1.1.1.2   misho     347: /* Firewall independant code which call the FW dependant code. */
1.1       misho     348: int
                    349: upnp_get_redirection_infos(unsigned short eport, const char * protocol,
                    350:                            unsigned short * iport,
                    351:                            char * iaddr, int iaddrlen,
1.1.1.2   misho     352:                            char * desc, int desclen,
                    353:                            char * rhost, int rhostlen,
                    354:                            unsigned int * leaseduration)
1.1       misho     355: {
1.1.1.2   misho     356:        int r;
                    357:        unsigned int timestamp;
                    358:        time_t current_time;
                    359: 
1.1       misho     360:        if(desc && (desclen > 0))
                    361:                desc[0] = '\0';
1.1.1.2   misho     362:        if(rhost && (rhostlen > 0))
                    363:                rhost[0] = '\0';
                    364:        r = get_redirect_rule(ext_if_name, eport, proto_atoi(protocol),
                    365:                              iaddr, iaddrlen, iport, desc, desclen,
                    366:                              rhost, rhostlen, &timestamp,
                    367:                              0, 0);
1.1.1.3 ! misho     368:        if(r == 0 &&
        !           369:           timestamp > 0 &&
        !           370:           timestamp > (unsigned int)(current_time = time(NULL))) {
1.1.1.2   misho     371:                *leaseduration = timestamp - current_time;
                    372:        } else {
                    373:                *leaseduration = 0;
                    374:        }
                    375:        return r;
1.1       misho     376: }
                    377: 
                    378: int
                    379: upnp_get_redirection_infos_by_index(int index,
                    380:                                     unsigned short * eport, char * protocol,
1.1.1.3 ! misho     381:                                     unsigned short * iport,
1.1       misho     382:                                     char * iaddr, int iaddrlen,
1.1.1.2   misho     383:                                     char * desc, int desclen,
                    384:                                     char * rhost, int rhostlen,
                    385:                                     unsigned int * leaseduration)
1.1       misho     386: {
                    387:        /*char ifname[IFNAMSIZ];*/
                    388:        int proto = 0;
1.1.1.2   misho     389:        unsigned int timestamp;
                    390:        time_t current_time;
1.1       misho     391: 
                    392:        if(desc && (desclen > 0))
                    393:                desc[0] = '\0';
1.1.1.3 ! misho     394:        if(rhost && (rhostlen > 0))
1.1.1.2   misho     395:                rhost[0] = '\0';
1.1       misho     396:        if(get_redirect_rule_by_index(index, 0/*ifname*/, eport, iaddr, iaddrlen,
1.1.1.2   misho     397:                                      iport, &proto, desc, desclen,
                    398:                                      rhost, rhostlen, &timestamp,
                    399:                                      0, 0) < 0)
1.1       misho     400:                return -1;
                    401:        else
                    402:        {
1.1.1.2   misho     403:                current_time = time(NULL);
1.1.1.3 ! misho     404:                *leaseduration = (timestamp > (unsigned int)current_time)
1.1.1.2   misho     405:                                 ? (timestamp - current_time)
                    406:                                 : 0;
1.1       misho     407:                if(proto == IPPROTO_TCP)
                    408:                        memcpy(protocol, "TCP", 4);
                    409:                else
                    410:                        memcpy(protocol, "UDP", 4);
                    411:                return 0;
                    412:        }
                    413: }
                    414: 
1.1.1.2   misho     415: /* called from natpmp.c too */
1.1       misho     416: int
                    417: _upnp_delete_redir(unsigned short eport, int proto)
                    418: {
                    419:        int r;
                    420: #if defined(__linux__)
                    421:        r = delete_redirect_and_filter_rules(eport, proto);
                    422: #else
                    423:        r = delete_redirect_rule(ext_if_name, eport, proto);
                    424:        delete_filter_rule(ext_if_name, eport, proto);
                    425: #endif
                    426: #ifdef ENABLE_LEASEFILE
                    427:        lease_file_remove( eport, proto);
                    428: #endif
                    429: 
                    430: #ifdef ENABLE_EVENTS
                    431:        upnp_event_var_change_notify(EWanIPC);
                    432: #endif
                    433:        return r;
                    434: }
                    435: 
                    436: int
                    437: upnp_delete_redirection(unsigned short eport, const char * protocol)
                    438: {
                    439:        syslog(LOG_INFO, "removing redirect rule port %hu %s", eport, protocol);
                    440:        return _upnp_delete_redir(eport, proto_atoi(protocol));
                    441: }
                    442: 
                    443: /* upnp_get_portmapping_number_of_entries()
1.1.1.2   misho     444:  * TODO: improve this code. */
1.1       misho     445: int
                    446: upnp_get_portmapping_number_of_entries()
                    447: {
                    448:        int n = 0, r = 0;
                    449:        unsigned short eport, iport;
1.1.1.2   misho     450:        char protocol[4], iaddr[32], desc[64], rhost[32];
                    451:        unsigned int leaseduration;
1.1       misho     452:        do {
                    453:                protocol[0] = '\0'; iaddr[0] = '\0'; desc[0] = '\0';
                    454:                r = upnp_get_redirection_infos_by_index(n, &eport, protocol, &iport,
                    455:                                                        iaddr, sizeof(iaddr),
1.1.1.2   misho     456:                                                        desc, sizeof(desc),
                    457:                                                        rhost, sizeof(rhost),
                    458:                                                        &leaseduration);
1.1       misho     459:                n++;
                    460:        } while(r==0);
                    461:        return (n-1);
                    462: }
                    463: 
1.1.1.2   misho     464: /* functions used to remove unused rules
                    465:  * As a side effect, delete expired rules (based on LeaseDuration) */
1.1       misho     466: struct rule_state *
                    467: get_upnp_rules_state_list(int max_rules_number_target)
                    468: {
                    469:        /*char ifname[IFNAMSIZ];*/
                    470:        int proto;
                    471:        unsigned short iport;
1.1.1.2   misho     472:        unsigned int timestamp;
1.1       misho     473:        struct rule_state * tmp;
                    474:        struct rule_state * list = 0;
1.1.1.2   misho     475:        struct rule_state * * p;
1.1       misho     476:        int i = 0;
1.1.1.2   misho     477:        time_t current_time;
                    478: 
1.1       misho     479:        /*ifname[0] = '\0';*/
                    480:        tmp = malloc(sizeof(struct rule_state));
                    481:        if(!tmp)
                    482:                return 0;
1.1.1.2   misho     483:        current_time = time(NULL);
                    484:        nextruletoclean_timestamp = 0;
1.1       misho     485:        while(get_redirect_rule_by_index(i, /*ifname*/0, &tmp->eport, 0, 0,
1.1.1.2   misho     486:                                      &iport, &proto, 0, 0, 0,0, &timestamp,
1.1       misho     487:                                                                  &tmp->packets, &tmp->bytes) >= 0)
                    488:        {
1.1.1.2   misho     489:                tmp->to_remove = 0;
                    490:                if(timestamp > 0) {
                    491:                        /* need to remove this port mapping ? */
1.1.1.3 ! misho     492:                        if(timestamp <= (unsigned int)current_time)
1.1.1.2   misho     493:                                tmp->to_remove = 1;
1.1.1.3 ! misho     494:                        else if((nextruletoclean_timestamp <= (unsigned int)current_time)
1.1.1.2   misho     495:                               || (timestamp < nextruletoclean_timestamp))
                    496:                                nextruletoclean_timestamp = timestamp;
                    497:                }
1.1       misho     498:                tmp->proto = (short)proto;
                    499:                /* add tmp to list */
                    500:                tmp->next = list;
                    501:                list = tmp;
                    502:                /* prepare next iteration */
                    503:                i++;
                    504:                tmp = malloc(sizeof(struct rule_state));
                    505:                if(!tmp)
                    506:                        break;
                    507:        }
                    508:        free(tmp);
1.1.1.2   misho     509:        /* remove the redirections that need to be removed */
                    510:        for(p = &list, tmp = list; tmp; tmp = *p)
                    511:        {
                    512:                if(tmp->to_remove)
                    513:                {
                    514:                        syslog(LOG_NOTICE, "remove port mapping %hu %s because it has expired",
                    515:                               tmp->eport, (tmp->proto==IPPROTO_TCP)?"TCP":"UDP");
                    516:                        _upnp_delete_redir(tmp->eport, tmp->proto);
                    517:                        *p = tmp->next;
                    518:                        free(tmp);
                    519:                        i--;
                    520:                } else {
                    521:                        p = &(tmp->next);
                    522:                }
                    523:        }
1.1       misho     524:        /* return empty list if not enough redirections */
                    525:        if(i<=max_rules_number_target)
                    526:                while(list)
                    527:                {
                    528:                        tmp = list;
                    529:                        list = tmp->next;
                    530:                        free(tmp);
                    531:                }
                    532:        /* return list */
                    533:        return list;
                    534: }
                    535: 
                    536: void
                    537: remove_unused_rules(struct rule_state * list)
                    538: {
                    539:        char ifname[IFNAMSIZ];
                    540:        unsigned short iport;
                    541:        struct rule_state * tmp;
                    542:        u_int64_t packets;
                    543:        u_int64_t bytes;
1.1.1.2   misho     544:        unsigned int timestamp;
1.1       misho     545:        int n = 0;
1.1.1.2   misho     546: 
1.1       misho     547:        while(list)
                    548:        {
                    549:                /* remove the rule if no traffic has used it */
                    550:                if(get_redirect_rule(ifname, list->eport, list->proto,
1.1.1.2   misho     551:                                 0, 0, &iport, 0, 0, 0, 0, &timestamp,
                    552:                                     &packets, &bytes) >= 0)
1.1       misho     553:                {
                    554:                        if(packets == list->packets && bytes == list->bytes)
                    555:                        {
                    556:                                _upnp_delete_redir(list->eport, list->proto);
                    557:                                n++;
                    558:                        }
                    559:                }
                    560:                tmp = list;
                    561:                list = tmp->next;
                    562:                free(tmp);
                    563:        }
                    564:        if(n>0)
                    565:                syslog(LOG_NOTICE, "removed %d unused rules", n);
                    566: }
                    567: 
1.1.1.2   misho     568: /* upnp_get_portmappings_in_range()
                    569:  * return a list of all "external" ports for which a port
                    570:  * mapping exists */
                    571: unsigned short *
                    572: upnp_get_portmappings_in_range(unsigned short startport,
                    573:                                unsigned short endport,
                    574:                                const char * protocol,
                    575:                                unsigned int * number)
                    576: {
                    577:        int proto;
                    578:        proto = proto_atoi(protocol);
                    579:        if(!number)
                    580:                return NULL;
                    581:        return get_portmappings_in_range(startport, endport, proto, number);
                    582: }
                    583: 
1.1       misho     584: /* stuff for miniupnpdctl */
                    585: #ifdef USE_MINIUPNPDCTL
                    586: void
                    587: write_ruleset_details(int s)
                    588: {
                    589:        int proto = 0;
                    590:        unsigned short eport, iport;
                    591:        char desc[64];
                    592:        char iaddr[32];
1.1.1.2   misho     593:        char rhost[32];
                    594:        unsigned int timestamp;
1.1       misho     595:        u_int64_t packets;
                    596:        u_int64_t bytes;
                    597:        int i = 0;
                    598:        char buffer[256];
                    599:        int n;
1.1.1.2   misho     600: 
1.1       misho     601:        write(s, "Ruleset :\n", 10);
1.1.1.2   misho     602:        while(get_redirect_rule_by_index(i, 0/*ifname*/, &eport, iaddr, sizeof(iaddr),
1.1       misho     603:                                         &iport, &proto, desc, sizeof(desc),
1.1.1.2   misho     604:                                         rhost, sizeof(rhost),
                    605:                                         &timestamp,
1.1       misho     606:                                         &packets, &bytes) >= 0)
                    607:        {
1.1.1.2   misho     608:                n = snprintf(buffer, sizeof(buffer),
                    609:                             "%2d %s %s:%hu->%s:%hu "
                    610:                             "'%s' %u %" PRIu64 " %" PRIu64 "\n",
                    611:                             /*"'%s' %llu %llu\n",*/
                    612:                             i, proto==IPPROTO_TCP?"TCP":"UDP", rhost,
                    613:                             eport, iaddr, iport, desc, timestamp, packets, bytes);
1.1       misho     614:                write(s, buffer, n);
                    615:                i++;
                    616:        }
                    617: }
                    618: #endif
                    619: 

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