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

1.1.1.2 ! misho       1: /* $Id: miniupnpd.c,v 1.138 2011/05/27 21:58:12 nanard Exp $ */
1.1       misho       2: /* MiniUPnP project
                      3:  * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
1.1.1.2 ! misho       4:  * (c) 2006-2011 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 "config.h"
                      9: 
                     10: /* Experimental support for NFQUEUE interfaces */
                     11: #ifdef ENABLE_NFQUEUE
                     12: /* apt-get install libnetfilter-queue-dev */
                     13: #include <netinet/ip.h>
                     14: #include <netinet/udp.h>
                     15: //#include <linux/netfilter_ipv4.h>  /* Defines verdicts (NF_ACCEPT, etc) */
                     16: #include <linux/netfilter.h>
                     17: #include <libnetfilter_queue/libnetfilter_queue.h>
                     18: #include <linux/netfilter/nfnetlink_queue.h>
                     19: #endif
                     20: 
                     21: #include <stdlib.h>
                     22: #include <unistd.h>
                     23: #include <string.h>
                     24: #include <stdio.h>
                     25: #include <ctype.h>
                     26: #include <sys/types.h>
                     27: #include <sys/socket.h>
                     28: #include <netinet/in.h>
                     29: #include <arpa/inet.h>
                     30: #include <fcntl.h>
                     31: #include <sys/file.h>
                     32: #include <syslog.h>
                     33: #include <sys/time.h>
                     34: #include <time.h>
                     35: #include <signal.h>
                     36: #include <errno.h>
                     37: #include <sys/param.h>
                     38: #if defined(sun)
                     39: #include <kstat.h>
                     40: #else
                     41: /* for BSD's sysctl */
                     42: #include <sys/sysctl.h>
                     43: #endif
                     44: 
                     45: /* unix sockets */
                     46: #ifdef USE_MINIUPNPDCTL
                     47: #include <sys/un.h>
                     48: #endif
                     49: 
                     50: #include "upnpglobalvars.h"
                     51: #include "upnphttp.h"
                     52: #include "upnpdescgen.h"
                     53: #include "miniupnpdpath.h"
                     54: #include "getifaddr.h"
                     55: #include "upnpsoap.h"
                     56: #include "options.h"
                     57: #include "minissdp.h"
                     58: #include "upnpredirect.h"
                     59: #include "miniupnpdtypes.h"
                     60: #include "daemonize.h"
                     61: #include "upnpevents.h"
                     62: #ifdef ENABLE_NATPMP
                     63: #include "natpmp.h"
                     64: #endif
                     65: #include "commonrdr.h"
1.1.1.2 ! misho      66: #include "upnputils.h"
        !            67: #ifdef USE_IFACEWATCHER
        !            68: #include "ifacewatcher.h"
        !            69: #endif
1.1       misho      70: 
                     71: #ifndef DEFAULT_CONFIG
                     72: #define DEFAULT_CONFIG "/etc/miniupnpd.conf"
                     73: #endif
                     74: 
                     75: #ifdef USE_MINIUPNPDCTL
                     76: struct ctlelem {
                     77:        int socket;
                     78:        LIST_ENTRY(ctlelem) entries;
                     79: };
                     80: #endif
                     81: 
                     82: #ifdef ENABLE_NFQUEUE
                     83: /* globals */
                     84: static struct nfq_handle *nfqHandle;
                     85: static struct sockaddr_in ssdp;
                     86: 
                     87: /* prototypes */
                     88: static int nfqueue_cb( struct nfq_q_handle *qh, struct nfgenmsg *nfmsg, struct nfq_data *nfa, void *data) ;
                     89: int identify_ip_protocol (char *payload);
                     90: int get_udp_dst_port (char *payload);
                     91: #endif
                     92: 
1.1.1.2 ! misho      93: /* variables used by signals */
1.1       misho      94: static volatile int quitting = 0;
1.1.1.2 ! misho      95: volatile int should_send_public_address_change_notif = 0;
1.1       misho      96: 
                     97: /* OpenAndConfHTTPSocket() :
                     98:  * setup the socket used to handle incoming HTTP connections. */
                     99: static int
                    100: OpenAndConfHTTPSocket(unsigned short port)
                    101: {
                    102:        int s;
                    103:        int i = 1;
1.1.1.2 ! misho     104: #ifdef ENABLE_IPV6
        !           105:        struct sockaddr_in6 listenname;
        !           106: #else
1.1       misho     107:        struct sockaddr_in listenname;
1.1.1.2 ! misho     108: #endif
        !           109:        socklen_t listenname_len;
1.1       misho     110: 
1.1.1.2 ! misho     111:        if( (s = socket(
        !           112: #ifdef ENABLE_IPV6
        !           113:                        PF_INET6,
        !           114: #else
        !           115:                        PF_INET,
        !           116: #endif
        !           117:                        SOCK_STREAM, 0)) < 0)
1.1       misho     118:        {
                    119:                syslog(LOG_ERR, "socket(http): %m");
                    120:                return -1;
                    121:        }
                    122: 
                    123:        if(setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &i, sizeof(i)) < 0)
                    124:        {
                    125:                syslog(LOG_WARNING, "setsockopt(http, SO_REUSEADDR): %m");
                    126:        }
1.1.1.2 ! misho     127: #if 0
        !           128:        /* enable this to force IPV6 only for IPV6 socket.
        !           129:         * see http://www.ietf.org/rfc/rfc3493.txt section 5.3 */
        !           130:        if(setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, &i, sizeof(i)) < 0)
        !           131:        {
        !           132:                syslog(LOG_WARNING, "setsockopt(http, IPV6_V6ONLY): %m");
        !           133:        }
        !           134: #endif
1.1       misho     135: 
1.1.1.2 ! misho     136: #ifdef ENABLE_IPV6
        !           137:        memset(&listenname, 0, sizeof(struct sockaddr_in6));
        !           138:        listenname.sin6_family = AF_INET6;
        !           139:        listenname.sin6_port = htons(port);
        !           140:        listenname.sin6_addr = in6addr_any;
        !           141:        listenname_len =  sizeof(struct sockaddr_in6);
        !           142: #else
1.1       misho     143:        listenname.sin_family = AF_INET;
                    144:        listenname.sin_port = htons(port);
                    145:        listenname.sin_addr.s_addr = htonl(INADDR_ANY);
1.1.1.2 ! misho     146:        listenname_len =  sizeof(struct sockaddr_in);
        !           147: #endif
1.1       misho     148: 
1.1.1.2 ! misho     149:        if(bind(s, (struct sockaddr *)&listenname, listenname_len) < 0)
1.1       misho     150:        {
                    151:                syslog(LOG_ERR, "bind(http): %m");
                    152:                close(s);
                    153:                return -1;
                    154:        }
                    155: 
1.1.1.2 ! misho     156:        if(listen(s, 5) < 0)
1.1       misho     157:        {
                    158:                syslog(LOG_ERR, "listen(http): %m");
                    159:                close(s);
                    160:                return -1;
                    161:        }
                    162: 
                    163:        return s;
                    164: }
                    165: #ifdef ENABLE_NFQUEUE
                    166: 
                    167: int identify_ip_protocol(char *payload) {
                    168:     return payload[9];
                    169: }
                    170: 
                    171: 
                    172: /*
                    173:  * This function returns the destination port of the captured packet UDP
                    174:  */
                    175: int get_udp_dst_port(char *payload) {
                    176:         char *pkt_data_ptr = NULL;
                    177:         pkt_data_ptr = payload + sizeof(struct ip);
                    178: 
                    179:     /* Cast the UDP Header from the raw packet */
                    180:     struct udphdr *udp = (struct udphdr *) pkt_data_ptr;
                    181: 
                    182:     /* get the dst port of the packet */
                    183:     return(ntohs(udp->dest));
                    184: 
                    185: }
                    186: static int
                    187: OpenAndConfNFqueue(){
                    188: 
                    189:         struct nfq_q_handle *myQueue;
                    190:         struct nfnl_handle *netlinkHandle;
                    191: 
                    192:         int fd = 0, e = 0;
                    193: 
                    194:        inet_pton(AF_INET, "239.255.255.250", &(ssdp.sin_addr));
                    195: 
                    196:         //Get a queue connection handle from the module
                    197:         if (!(nfqHandle = nfq_open())) {
                    198:                syslog(LOG_ERR, "Error in nfq_open(): %m");
                    199:                 return -1;
                    200:         }
                    201: 
                    202:         //Unbind the handler from processing any IP packets
                    203:         //      Not totally sure why this is done, or if it's necessary...
                    204:         if ((e = nfq_unbind_pf(nfqHandle, AF_INET)) < 0) {
                    205:                syslog(LOG_ERR, "Error in nfq_unbind_pf(): %m");
                    206:                 return -1;
                    207:         }
                    208: 
                    209:         //Bind this handler to process IP packets...
                    210:         if (nfq_bind_pf(nfqHandle, AF_INET) < 0) {
                    211:                syslog(LOG_ERR, "Error in nfq_bind_pf(): %m");
                    212:                 return -1;
                    213:         }
                    214: 
                    215:         //      Install a callback on queue -Q
                    216:         if (!(myQueue = nfq_create_queue(nfqHandle,  nfqueue, &nfqueue_cb, NULL))) {
                    217:                syslog(LOG_ERR, "Error in nfq_create_queue(): %m");
                    218:                 return -1;
                    219:         }
                    220: 
                    221:         //      Turn on packet copy mode
                    222:         if (nfq_set_mode(myQueue, NFQNL_COPY_PACKET, 0xffff) < 0) {
                    223:                syslog(LOG_ERR, "Error setting packet copy mode (): %m");
                    224:                 return -1;
                    225:         }
                    226: 
                    227:         netlinkHandle = nfq_nfnlh(nfqHandle);
                    228:         fd = nfnl_fd(netlinkHandle);
                    229: 
                    230:        return fd;
                    231: 
                    232: }
                    233: 
                    234: 
                    235: static int nfqueue_cb(
                    236:                 struct nfq_q_handle *qh,
                    237:                 struct nfgenmsg *nfmsg,
                    238:                 struct nfq_data *nfa,
                    239:                 void *data) {
                    240: 
                    241:        char    *pkt;
                    242:        struct nfqnl_msg_packet_hdr *ph;
                    243:        ph = nfq_get_msg_packet_hdr(nfa);
                    244: 
                    245:        if ( ph ) {
                    246: 
                    247:                int id = 0, size = 0;
                    248:                id = ntohl(ph->packet_id);
                    249: 
                    250:                size = nfq_get_payload(nfa, &pkt);
                    251: 
                    252:                struct ip *iph = (struct ip *) pkt;
                    253: 
                    254:                int id_protocol = identify_ip_protocol(pkt);
                    255: 
                    256:                int dport = get_udp_dst_port(pkt);
                    257: 
                    258:                int x = sizeof (struct ip) + sizeof (struct udphdr);
                    259:        
                    260:                /* packets we are interested in are UDP multicast to 239.255.255.250:1900       
                    261:                 * and start with a data string M-SEARCH
                    262:                 */
                    263:                if ( (dport == 1900) && (id_protocol == IPPROTO_UDP) 
                    264:                        && (ssdp.sin_addr.s_addr == iph->ip_dst.s_addr) ) {
                    265:                
                    266:                        /* get the index that the packet came in on */
                    267:                        u_int32_t idx = nfq_get_indev(nfa);
                    268:                        int i = 0;
                    269:                        for ( ;i < n_nfqix ; i++) {
                    270:                                if ( nfqix[i] == idx ) {
                    271: 
                    272:                                        struct udphdr *udp = (struct udphdr *) (pkt + sizeof(struct ip));
                    273: 
                    274:                                        char *dd = pkt + x;
                    275:                                        
                    276:                                        struct sockaddr_in sendername;
                    277:                                        sendername.sin_family = AF_INET;
                    278:                                        sendername.sin_port = udp->source;
                    279:                                        sendername.sin_addr.s_addr = iph->ip_src.s_addr;
                    280: 
                    281:                                        /* printf("pkt found %s\n",dd);*/
1.1.1.2 ! misho     282:                                        ProcessSSDPData (sudp, dd, size - x,
        !           283:                                                         &sendername, (unsigned short) 5555);
1.1       misho     284:                                }
                    285:                        }
                    286:                }
                    287:                
                    288:                nfq_set_verdict(qh, id, NF_ACCEPT, 0, NULL);
                    289: 
                    290:        } else {
                    291:                syslog(LOG_ERR,"nfq_get_msg_packet_hdr failed");
                    292:                return 1; // from nfqueue source: 0 = ok, >0 = soft error, <0 hard error
                    293:        }
                    294: 
                    295:        return 0;
                    296: }
                    297: 
                    298: static void ProcessNFQUEUE(int fd){
                    299:        char buf[4096];
                    300: 
                    301:        socklen_t len_r;
                    302:        struct sockaddr_in sendername;
                    303:        len_r = sizeof(struct sockaddr_in);
                    304: 
                    305:         int res = recvfrom(fd, buf, sizeof(buf), 0,
                    306:                        (struct sockaddr *)&sendername, &len_r);
                    307: 
                    308:        nfq_handle_packet(nfqHandle, buf, res);
                    309: }
                    310: #endif
                    311: 
                    312: /* Functions used to communicate with miniupnpdctl */
                    313: #ifdef USE_MINIUPNPDCTL
                    314: static int
                    315: OpenAndConfCtlUnixSocket(const char * path)
                    316: {
                    317:        struct sockaddr_un localun;
                    318:        int s;
                    319:        s = socket(AF_UNIX, SOCK_STREAM, 0);
                    320:        localun.sun_family = AF_UNIX;
                    321:        strncpy(localun.sun_path, path,
                    322:                  sizeof(localun.sun_path));
                    323:        if(bind(s, (struct sockaddr *)&localun,
                    324:                sizeof(struct sockaddr_un)) < 0)
                    325:        {
                    326:                syslog(LOG_ERR, "bind(sctl): %m");
                    327:                close(s);
                    328:                s = -1;
                    329:        }
                    330:        else if(listen(s, 5) < 0)
                    331:        {
                    332:                syslog(LOG_ERR, "listen(sctl): %m");
                    333:                close(s);
                    334:                s = -1;
                    335:        }
                    336:        return s;
                    337: }
                    338: 
                    339: static void
                    340: write_upnphttp_details(int fd, struct upnphttp * e)
                    341: {
                    342:        char buffer[256];
                    343:        int len;
                    344:        write(fd, "HTTP :\n", 7);
                    345:        while(e)
                    346:        {
                    347:                len = snprintf(buffer, sizeof(buffer),
                    348:                               "%d %d %s req_buf=%p(%dbytes) res_buf=%p(%dbytes alloc)\n",
                    349:                               e->socket, e->state, e->HttpVer,
                    350:                               e->req_buf, e->req_buflen,
                    351:                               e->res_buf, e->res_buf_alloclen);
                    352:                write(fd, buffer, len);
                    353:                e = e->entries.le_next;
                    354:        }
                    355: }
                    356: 
                    357: static void
                    358: write_ctlsockets_list(int fd, struct ctlelem * e)
                    359: {
                    360:        char buffer[256];
                    361:        int len;
                    362:        write(fd, "CTL :\n", 6);
                    363:        while(e)
                    364:        {
                    365:                len = snprintf(buffer, sizeof(buffer),
                    366:                               "struct ctlelem: socket=%d\n", e->socket);
                    367:                write(fd, buffer, len);
                    368:                e = e->entries.le_next;
                    369:        }
                    370: }
                    371: 
                    372: static void
                    373: write_option_list(int fd)
                    374: {
                    375:        char buffer[256];
                    376:        int len;
                    377:        int i;
                    378:        write(fd, "Options :\n", 10);
                    379:        for(i=0; i<num_options; i++)
                    380:        {
                    381:                len = snprintf(buffer, sizeof(buffer),
                    382:                               "opt=%02d %s\n",
                    383:                               ary_options[i].id, ary_options[i].value);
                    384:                write(fd, buffer, len);
                    385:        }
                    386: }
                    387: 
                    388: static void
                    389: write_command_line(int fd, int argc, char * * argv)
                    390: {
                    391:        char buffer[256];
                    392:        int len;
                    393:        int i;
                    394:        write(fd, "Command Line :\n", 15);
                    395:        for(i=0; i<argc; i++)
                    396:        {
                    397:                len = snprintf(buffer, sizeof(buffer),
                    398:                               "argv[%02d]='%s'\n",
                    399:                                i, argv[i]);
                    400:                write(fd, buffer, len);
                    401:        }
                    402: }
                    403: 
                    404: #endif
                    405: 
                    406: /* Handler for the SIGTERM signal (kill) 
                    407:  * SIGINT is also handled */
                    408: static void
                    409: sigterm(int sig)
                    410: {
                    411:        /*int save_errno = errno;*/
                    412:        signal(sig, SIG_IGN);   /* Ignore this signal while we are quitting */
                    413: 
                    414:        syslog(LOG_NOTICE, "received signal %d, good-bye", sig);
                    415: 
                    416:        quitting = 1;
                    417:        /*errno = save_errno;*/
                    418: }
                    419: 
                    420: /* Handler for the SIGUSR1 signal indicating public IP address change. */
                    421: static void
                    422: sigusr1(int sig)
                    423: {
                    424:        syslog(LOG_INFO, "received signal %d, public ip address change", sig);
                    425: 
                    426:        should_send_public_address_change_notif = 1;
                    427: }
                    428: 
                    429: /* record the startup time, for returning uptime */
                    430: static void
                    431: set_startup_time(int sysuptime)
                    432: {
                    433:        startup_time = time(NULL);
                    434:        if(sysuptime)
                    435:        {
                    436:                /* use system uptime instead of daemon uptime */
                    437: #if defined(__linux__)
                    438:                char buff[64];
                    439:                int uptime = 0, fd;
                    440:                fd = open("/proc/uptime", O_RDONLY);
                    441:                if(fd < 0)
                    442:                {
                    443:                        syslog(LOG_ERR, "open(\"/proc/uptime\" : %m");
                    444:                }
                    445:                else
                    446:                {
                    447:                        memset(buff, 0, sizeof(buff));
                    448:                        if(read(fd, buff, sizeof(buff) - 1) < 0)
                    449:                        {
                    450:                                syslog(LOG_ERR, "read(\"/proc/uptime\" : %m");
                    451:                        }
                    452:                        else
                    453:                        {
                    454:                                uptime = atoi(buff);
                    455:                                syslog(LOG_INFO, "system uptime is %d seconds", uptime);
                    456:                        }
                    457:                        close(fd);
                    458:                        startup_time -= uptime;
                    459:                }
                    460: #elif defined(SOLARIS_KSTATS)
                    461:                kstat_ctl_t *kc;
                    462:                kc = kstat_open();
                    463:                if(kc != NULL)
                    464:                {
                    465:                        kstat_t *ksp;
                    466:                        ksp = kstat_lookup(kc, "unix", 0, "system_misc");
                    467:                        if(ksp && (kstat_read(kc, ksp, NULL) != -1))
                    468:                        {
                    469:                                void *ptr = kstat_data_lookup(ksp, "boot_time");
                    470:                                if(ptr)
                    471:                                        memcpy(&startup_time, ptr, sizeof(startup_time));
                    472:                                else
                    473:                                        syslog(LOG_ERR, "cannot find boot_time kstat");
                    474:                        }
                    475:                        else
                    476:                                syslog(LOG_ERR, "cannot open kstats for unix/0/system_misc: %m");
                    477:                        kstat_close(kc);
                    478:                }
                    479: #else
                    480:                struct timeval boottime;
                    481:                size_t size = sizeof(boottime);
                    482:                int name[2] = { CTL_KERN, KERN_BOOTTIME };
                    483:                if(sysctl(name, 2, &boottime, &size, NULL, 0) < 0)
                    484:                {
                    485:                        syslog(LOG_ERR, "sysctl(\"kern.boottime\") failed");
                    486:                }
                    487:                else
                    488:                {
                    489:                        startup_time = boottime.tv_sec;
                    490:                }
                    491: #endif
                    492:        }
                    493: }
                    494: 
                    495: /* structure containing variables used during "main loop"
                    496:  * that are filled during the init */
                    497: struct runtime_vars {
                    498:        /* LAN IP addresses for SSDP traffic and HTTP */
                    499:        /* moved to global vars */
                    500:        int port;       /* HTTP Port */
                    501:        int notify_interval;    /* seconds between SSDP announces */
                    502:        /* unused rules cleaning related variables : */
                    503:        int clean_ruleset_threshold;    /* threshold for removing unused rules */
                    504:        int clean_ruleset_interval;             /* (minimum) interval between checks */
                    505: };
                    506: 
                    507: /* parselanaddr()
                    508:  * parse address with mask
                    509:  * ex: 192.168.1.1/24
                    510:  * When MULTIPLE_EXTERNAL_IP is enabled, the ip address of the
                    511:  * external interface associated with the lan subnet follows.
                    512:  * ex : 192.168.1.1/24 81.21.41.11
                    513:  *
                    514:  * return value : 
                    515:  *    0 : ok
                    516:  *   -1 : error */
                    517: static int
                    518: parselanaddr(struct lan_addr_s * lan_addr, const char * str)
                    519: {
                    520:        const char * p;
                    521:        int nbits = 24; /* by default, networks are /24 */
                    522:        int n;
                    523:        p = str;
                    524:        while(*p && *p != '/' && !isspace(*p))
                    525:                p++;
                    526:        n = p - str;
                    527:        if(*p == '/')
                    528:        {
                    529:                nbits = atoi(++p);
                    530:                while(*p && !isspace(*p))
                    531:                        p++;
                    532:        }
                    533:        if(n>15)
                    534:        {
                    535:                fprintf(stderr, "Error parsing address/mask : %s\n", str);
                    536:                return -1;
                    537:        }
                    538:        memcpy(lan_addr->str, str, n);
                    539:        lan_addr->str[n] = '\0';
                    540:        if(!inet_aton(lan_addr->str, &lan_addr->addr))
                    541:        {
                    542:                fprintf(stderr, "Error parsing address/mask : %s\n", str);
                    543:                return -1;
                    544:        }
                    545:        lan_addr->mask.s_addr = htonl(nbits ? (0xffffffff << (32 - nbits)) : 0);
                    546: #ifdef MULTIPLE_EXTERNAL_IP
                    547:        /* skip spaces */
                    548:        while(*p && isspace(*p))
                    549:                p++;
                    550:        if(*p) {
                    551:                /* parse the exteral ip address to associate with this subnet */
                    552:                n = 0;
                    553:                while(p[n] && !isspace(*p))
                    554:                        n++;
                    555:                if(n<=15) {
                    556:                        memcpy(lan_addr->ext_ip_str, p, n);
                    557:                        lan_addr->ext_ip_str[n] = '\0';
                    558:                        if(!inet_aton(lan_addr->ext_ip_str, &lan_addr->ext_ip_addr)) {
                    559:                                /* error */
                    560:                                fprintf(stderr, "Error parsing address : %s\n", lan_addr->ext_ip_str);
                    561:                        }
                    562:                }
                    563:        }
                    564: #endif
                    565:        return 0;
                    566: }
                    567: 
                    568: /* init phase :
                    569:  * 1) read configuration file
                    570:  * 2) read command line arguments
                    571:  * 3) daemonize
                    572:  * 4) open syslog
                    573:  * 5) check and write pid file
                    574:  * 6) set startup time stamp
                    575:  * 7) compute presentation URL
                    576:  * 8) set signal handlers */
                    577: static int
                    578: init(int argc, char * * argv, struct runtime_vars * v)
                    579: {
                    580:        int i;
                    581:        int pid;
                    582:        int debug_flag = 0;
                    583:        int options_flag = 0;
                    584:        int openlog_option;
                    585:        struct sigaction sa;
                    586:        /*const char * logfilename = 0;*/
                    587:        const char * presurl = 0;
                    588:        const char * optionsfile = DEFAULT_CONFIG;
1.1.1.2 ! misho     589:        struct lan_addr_s * lan_addr;
        !           590:        struct lan_addr_s * lan_addr2;
1.1       misho     591: 
                    592:        /* only print usage if -h is used */
                    593:        for(i=1; i<argc; i++)
                    594:        {
                    595:                if(0 == strcmp(argv[i], "-h"))
                    596:                        goto print_usage;
                    597:        }
                    598:        /* first check if "-f" option is used */
                    599:        for(i=2; i<argc; i++)
                    600:        {
                    601:                if(0 == strcmp(argv[i-1], "-f"))
                    602:                {
                    603:                        optionsfile = argv[i];
                    604:                        options_flag = 1;
                    605:                        break;
                    606:                }
                    607:        }
                    608: 
                    609:        /* set initial values */
                    610:        SETFLAG(ENABLEUPNPMASK);
                    611: 
1.1.1.2 ! misho     612:        LIST_INIT(&lan_addrs);
1.1       misho     613:        v->port = -1;
                    614:        v->notify_interval = 30;        /* seconds between SSDP announces */
                    615:        v->clean_ruleset_threshold = 20;
                    616:        v->clean_ruleset_interval = 0;  /* interval between ruleset check. 0=disabled */
                    617: 
                    618:        /* read options file first since
                    619:         * command line arguments have final say */
                    620:        if(readoptionsfile(optionsfile) < 0)
                    621:        {
                    622:                /* only error if file exists or using -f */
                    623:                if(access(optionsfile, F_OK) == 0 || options_flag)
                    624:                        fprintf(stderr, "Error reading configuration file %s\n", optionsfile);
                    625:        }
                    626:        else
                    627:        {
                    628:                for(i=0; i<num_options; i++)
                    629:                {
                    630:                        switch(ary_options[i].id)
                    631:                        {
                    632:                        case UPNPEXT_IFNAME:
                    633:                                ext_if_name = ary_options[i].value;
                    634:                                break;
                    635:                        case UPNPEXT_IP:
                    636:                                use_ext_ip_addr = ary_options[i].value;
                    637:                                break;
                    638:                        case UPNPLISTENING_IP:
1.1.1.2 ! misho     639:                                lan_addr = (struct lan_addr_s *) malloc(sizeof(struct lan_addr_s));
        !           640:                                if (lan_addr == NULL)
1.1       misho     641:                                {
1.1.1.2 ! misho     642:                                        fprintf(stderr, "malloc(sizeof(struct lan_addr_s)): %m");
        !           643:                                        break;
1.1       misho     644:                                }
1.1.1.2 ! misho     645:                                if(parselanaddr(lan_addr, ary_options[i].value) != 0)
1.1       misho     646:                                {
1.1.1.2 ! misho     647:                                        fprintf(stderr, "can't parse \"%s\" as valid lan address\n", ary_options[i].value);
        !           648:                                        free(lan_addr);
        !           649:                                        break;
1.1       misho     650:                                }
1.1.1.2 ! misho     651:                                LIST_INSERT_HEAD(&lan_addrs, lan_addr, list);
1.1       misho     652:                                break;
                    653:                        case UPNPPORT:
                    654:                                v->port = atoi(ary_options[i].value);
                    655:                                break;
                    656:                        case UPNPBITRATE_UP:
                    657:                                upstream_bitrate = strtoul(ary_options[i].value, 0, 0);
                    658:                                break;
                    659:                        case UPNPBITRATE_DOWN:
                    660:                                downstream_bitrate = strtoul(ary_options[i].value, 0, 0);
                    661:                                break;
                    662:                        case UPNPPRESENTATIONURL:
                    663:                                presurl = ary_options[i].value;
                    664:                                break;
                    665: #ifdef USE_NETFILTER
                    666:                        case UPNPFORWARDCHAIN:
                    667:                                miniupnpd_forward_chain = ary_options[i].value;
                    668:                                break;
                    669:                        case UPNPNATCHAIN:
                    670:                                miniupnpd_nat_chain = ary_options[i].value;
                    671:                                break;
                    672: #endif
                    673:                        case UPNPNOTIFY_INTERVAL:
                    674:                                v->notify_interval = atoi(ary_options[i].value);
                    675:                                break;
                    676:                        case UPNPSYSTEM_UPTIME:
                    677:                                if(strcmp(ary_options[i].value, "yes") == 0)
                    678:                                        SETFLAG(SYSUPTIMEMASK); /*sysuptime = 1;*/
                    679:                                break;
                    680:                        case UPNPPACKET_LOG:
                    681:                                if(strcmp(ary_options[i].value, "yes") == 0)
                    682:                                        SETFLAG(LOGPACKETSMASK);        /*logpackets = 1;*/
                    683:                                break;
                    684:                        case UPNPUUID:
                    685:                                strncpy(uuidvalue+5, ary_options[i].value,
                    686:                                        strlen(uuidvalue+5) + 1);
                    687:                                break;
                    688:                        case UPNPSERIAL:
                    689:                                strncpy(serialnumber, ary_options[i].value, SERIALNUMBER_MAX_LEN);
                    690:                                serialnumber[SERIALNUMBER_MAX_LEN-1] = '\0';
                    691:                                break;                          
                    692:                        case UPNPMODEL_NUMBER:
                    693:                                strncpy(modelnumber, ary_options[i].value, MODELNUMBER_MAX_LEN);
                    694:                                modelnumber[MODELNUMBER_MAX_LEN-1] = '\0';
                    695:                                break;
                    696:                        case UPNPCLEANTHRESHOLD:
                    697:                                v->clean_ruleset_threshold = atoi(ary_options[i].value);
                    698:                                break;
                    699:                        case UPNPCLEANINTERVAL:
                    700:                                v->clean_ruleset_interval = atoi(ary_options[i].value);
                    701:                                break;
                    702: #ifdef USE_PF
                    703:                        case UPNPQUEUE:
                    704:                                queue = ary_options[i].value;
                    705:                                break;
                    706:                        case UPNPTAG:
                    707:                                tag = ary_options[i].value;
                    708:                                break;
                    709: #endif
                    710: #ifdef ENABLE_NATPMP
                    711:                        case UPNPENABLENATPMP:
                    712:                                if(strcmp(ary_options[i].value, "yes") == 0)
                    713:                                        SETFLAG(ENABLENATPMPMASK);      /*enablenatpmp = 1;*/
                    714:                                else
                    715:                                        if(atoi(ary_options[i].value))
                    716:                                                SETFLAG(ENABLENATPMPMASK);
                    717:                                        /*enablenatpmp = atoi(ary_options[i].value);*/
                    718:                                break;
                    719: #endif
                    720: #ifdef PF_ENABLE_FILTER_RULES
                    721:                        case UPNPQUICKRULES:
                    722:                                if(strcmp(ary_options[i].value, "no") == 0)
                    723:                                        SETFLAG(PFNOQUICKRULESMASK);
                    724:                                break;
                    725: #endif
                    726:                        case UPNPENABLE:
                    727:                                if(strcmp(ary_options[i].value, "yes") != 0)
                    728:                                        CLEARFLAG(ENABLEUPNPMASK);
                    729:                                break;
                    730:                        case UPNPSECUREMODE:
                    731:                                if(strcmp(ary_options[i].value, "yes") == 0)
                    732:                                        SETFLAG(SECUREMODEMASK);
                    733:                                break;
                    734: #ifdef ENABLE_LEASEFILE
                    735:                        case UPNPLEASEFILE:
                    736:                                lease_file = ary_options[i].value;
                    737:                                break;
                    738: #endif
                    739:                        case UPNPMINISSDPDSOCKET:
                    740:                                minissdpdsocketpath = ary_options[i].value;
                    741:                                break;
                    742:                        default:
                    743:                                fprintf(stderr, "Unknown option in file %s\n",
                    744:                                        optionsfile);
                    745:                        }
                    746:                }
                    747:        }
                    748: 
                    749:        /* command line arguments processing */
                    750:        for(i=1; i<argc; i++)
                    751:        {
                    752:                if(argv[i][0]!='-')
                    753:                {
                    754:                        fprintf(stderr, "Unknown option: %s\n", argv[i]);
                    755:                }
                    756:                else switch(argv[i][1])
                    757:                {
                    758:                case 'o':
                    759:                        if(i+1 < argc)
                    760:                                use_ext_ip_addr = argv[++i];
                    761:                        else
                    762:                                fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]);
                    763:                        break;
                    764:                case 't':
                    765:                        if(i+1 < argc)
                    766:                                v->notify_interval = atoi(argv[++i]);
                    767:                        else
                    768:                                fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]);
                    769:                        break;
                    770:                case 'u':
                    771:                        if(i+1 < argc)
                    772:                                strncpy(uuidvalue+5, argv[++i], strlen(uuidvalue+5) + 1);
                    773:                        else
                    774:                                fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]);
                    775:                        break;
                    776:                case 's':
                    777:                        if(i+1 < argc)
                    778:                                strncpy(serialnumber, argv[++i], SERIALNUMBER_MAX_LEN);
                    779:                        else
                    780:                                fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]);
                    781:                        serialnumber[SERIALNUMBER_MAX_LEN-1] = '\0';
                    782:                        break;
                    783:                case 'm':
                    784:                        if(i+1 < argc)
                    785:                                strncpy(modelnumber, argv[++i], MODELNUMBER_MAX_LEN);
                    786:                        else
                    787:                                fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]);
                    788:                        modelnumber[MODELNUMBER_MAX_LEN-1] = '\0';
                    789:                        break;
                    790: #ifdef ENABLE_NATPMP
                    791:                case 'N':
                    792:                        /*enablenatpmp = 1;*/
                    793:                        SETFLAG(ENABLENATPMPMASK);
                    794:                        break;
                    795: #endif
                    796:                case 'U':
                    797:                        /*sysuptime = 1;*/
                    798:                        SETFLAG(SYSUPTIMEMASK);
                    799:                        break;
                    800:                /*case 'l':
                    801:                        logfilename = argv[++i];
                    802:                        break;*/
                    803:                case 'L':
                    804:                        /*logpackets = 1;*/
                    805:                        SETFLAG(LOGPACKETSMASK);
                    806:                        break;
                    807:                case 'S':
                    808:                        SETFLAG(SECUREMODEMASK);
                    809:                        break;
                    810:                case 'i':
                    811:                        if(i+1 < argc)
                    812:                                ext_if_name = argv[++i];
                    813:                        else
                    814:                                fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]);
                    815:                        break;
                    816: #ifdef USE_PF
                    817:                case 'q':
                    818:                        if(i+1 < argc)
                    819:                                queue = argv[++i];
                    820:                        else
                    821:                                fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]);
                    822:                        break;
                    823:                case 'T':
                    824:                        if(i+1 < argc)
                    825:                                tag = argv[++i];
                    826:                        else
                    827:                                fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]);
                    828:                        break;
                    829: #endif
                    830:                case 'p':
                    831:                        if(i+1 < argc)
                    832:                                v->port = atoi(argv[++i]);
                    833:                        else
                    834: #ifdef ENABLE_NFQUEUE
                    835:                case 'Q':
                    836:                        if(i+1<argc)
                    837:                        {
                    838:                                nfqueue = atoi(argv[++i]);
                    839:                        }
                    840:                        else
                    841:                                fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]);
                    842:                        break;
                    843:                case 'n':
                    844:                        if (i+1 < argc) {
                    845:                                i++;
                    846:                                if(n_nfqix < MAX_LAN_ADDR) {
                    847:                                        nfqix[n_nfqix++] = if_nametoindex(argv[i]);
                    848:                                } else {
                    849:                                        fprintf(stderr,"Too many nfq interfaces. Ignoring %s\n", argv[i]);
                    850:                                }
                    851:                        } else {
                    852:                                fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]);
                    853:                        }
                    854:                        break;
                    855: #endif
                    856:                                fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]);
                    857:                        break;
                    858:                case 'P':
                    859:                        if(i+1 < argc)
                    860:                                pidfilename = argv[++i];
                    861:                        else
                    862:                                fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]);
                    863:                        break;
                    864:                case 'd':
                    865:                        debug_flag = 1;
                    866:                        break;
                    867:                case 'w':
                    868:                        if(i+1 < argc)
                    869:                                presurl = argv[++i];
                    870:                        else
                    871:                                fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]);
                    872:                        break;
                    873:                case 'B':
                    874:                        if(i+2<argc)
                    875:                        {
                    876:                                downstream_bitrate = strtoul(argv[++i], 0, 0);
                    877:                                upstream_bitrate = strtoul(argv[++i], 0, 0);
                    878:                        }
                    879:                        else
                    880:                                fprintf(stderr, "Option -%c takes two arguments.\n", argv[i][1]);
                    881:                        break;
                    882:                case 'a':
                    883:                        if(i+1 < argc)
                    884:                        {
                    885:                                i++;
1.1.1.2 ! misho     886:                                lan_addr = (struct lan_addr_s *) malloc(sizeof(struct lan_addr_s));
        !           887:                                if (lan_addr == NULL)
1.1       misho     888:                                {
1.1.1.2 ! misho     889:                                        fprintf(stderr, "malloc(sizeof(struct lan_addr_s)): %m");
1.1       misho     890:                                        break;
1.1.1.2 ! misho     891:                                }
        !           892:                                if(parselanaddr(lan_addr, argv[i]) != 0)
1.1       misho     893:                                {
1.1.1.2 ! misho     894:                                        fprintf(stderr, "can't parse \"%s\" as valid lan address\n", argv[i]);
        !           895:                                        free(lan_addr);
        !           896:                                        break;
1.1       misho     897:                                }
1.1.1.2 ! misho     898:                                /* check if we already have this address */
        !           899:                                for(lan_addr2 = lan_addrs.lh_first; lan_addr2 != NULL; lan_addr2 = lan_addr2->list.le_next)
1.1       misho     900:                                {
1.1.1.2 ! misho     901:                                        if (0 == strncmp(lan_addr2->str, lan_addr->str, 15))
        !           902:                                                break;
1.1       misho     903:                                }
1.1.1.2 ! misho     904:                                if (lan_addr2 == NULL)
        !           905:                                        LIST_INSERT_HEAD(&lan_addrs, lan_addr, list);
1.1       misho     906:                        }
                    907:                        else
                    908:                                fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]);
                    909:                        break;
                    910:                case 'f':
                    911:                        i++;    /* discarding, the config file is already read */
                    912:                        break;
                    913:                default:
                    914:                        fprintf(stderr, "Unknown option: %s\n", argv[i]);
                    915:                }
                    916:        }
1.1.1.2 ! misho     917:        if(!ext_if_name || !lan_addrs.lh_first)
1.1       misho     918:        {
                    919:                /* bad configuration */
                    920:                goto print_usage;
                    921:        }
                    922: 
                    923:        if(debug_flag)
                    924:        {
                    925:                pid = getpid();
                    926:        }
                    927:        else
                    928:        {
                    929: #ifdef USE_DAEMON
                    930:                if(daemon(0, 0)<0) {
                    931:                        perror("daemon()");
                    932:                }
                    933:                pid = getpid();
                    934: #else
                    935:                pid = daemonize();
                    936: #endif
                    937:        }
                    938: 
                    939:        openlog_option = LOG_PID|LOG_CONS;
                    940:        if(debug_flag)
                    941:        {
                    942:                openlog_option |= LOG_PERROR;   /* also log on stderr */
                    943:        }
                    944: 
                    945:        openlog("miniupnpd", openlog_option, LOG_MINIUPNPD);
                    946: 
                    947:        if(!debug_flag)
                    948:        {
                    949:                /* speed things up and ignore LOG_INFO and LOG_DEBUG */
                    950:                setlogmask(LOG_UPTO(LOG_NOTICE));
                    951:        }
                    952: 
                    953:        if(checkforrunning(pidfilename) < 0)
                    954:        {
                    955:                syslog(LOG_ERR, "MiniUPnPd is already running. EXITING");
                    956:                return 1;
                    957:        }       
                    958: 
                    959:        set_startup_time(GETFLAG(SYSUPTIMEMASK));
                    960: 
                    961:        /* presentation url */
                    962:        if(presurl)
                    963:        {
                    964:                strncpy(presentationurl, presurl, PRESENTATIONURL_MAX_LEN);
                    965:                presentationurl[PRESENTATIONURL_MAX_LEN-1] = '\0';
                    966:        }
                    967:        else
                    968:        {
                    969:                snprintf(presentationurl, PRESENTATIONURL_MAX_LEN,
1.1.1.2 ! misho     970:                         "http://%s/", lan_addrs.lh_first->str);
        !           971:                         /*"http://%s:%d/", lan_addrs.lh_first->str, 80);*/
1.1       misho     972:        }
                    973: 
                    974:        /* set signal handler */
                    975:        memset(&sa, 0, sizeof(struct sigaction));
                    976:        sa.sa_handler = sigterm;
                    977: 
                    978:        if (sigaction(SIGTERM, &sa, NULL))
                    979:        {
                    980:                syslog(LOG_ERR, "Failed to set %s handler. EXITING", "SIGTERM");
                    981:                return 1;
                    982:        }
                    983:        if (sigaction(SIGINT, &sa, NULL))
                    984:        {
                    985:                syslog(LOG_ERR, "Failed to set %s handler. EXITING", "SIGINT");
                    986:                return 1;
                    987:        }
                    988: 
                    989:        if(signal(SIGPIPE, SIG_IGN) == SIG_ERR) {
                    990:                syslog(LOG_ERR, "Failed to ignore SIGPIPE signals");
                    991:        }
                    992: 
                    993:        sa.sa_handler = sigusr1;
                    994:        if (sigaction(SIGUSR1, &sa, NULL))
                    995:        {
                    996:                syslog(LOG_NOTICE, "Failed to set %s handler", "SIGUSR1");
                    997:        }
                    998: 
                    999:        if(init_redirect() < 0)
                   1000:        {
                   1001:                syslog(LOG_ERR, "Failed to init redirection engine. EXITING");
                   1002:                return 1;
                   1003:        }
                   1004: 
                   1005:        writepidfile(pidfilename, pid);
                   1006: 
                   1007: #ifdef ENABLE_LEASEFILE
                   1008:        /*remove(lease_file);*/
                   1009:        syslog(LOG_INFO, "Reloading rules from lease file");
                   1010:        reload_from_lease_file();
                   1011: #endif
                   1012: 
                   1013:        return 0;
                   1014: print_usage:
                   1015:        fprintf(stderr, "Usage:\n\t"
                   1016:                "%s [-f config_file] [-i ext_ifname] [-o ext_ip]\n"
                   1017: #ifndef ENABLE_NATPMP
                   1018:                        "\t\t[-a listening_ip] [-p port] [-d] [-L] [-U] [-S]\n"
                   1019: #else
                   1020:                        "\t\t[-a listening_ip] [-p port] [-d] [-L] [-U] [-S] [-N]\n"
                   1021: #endif
                   1022:                        /*"[-l logfile] " not functionnal */
                   1023:                        "\t\t[-u uuid] [-s serial] [-m model_number] \n"
                   1024:                        "\t\t[-t notify_interval] [-P pid_filename]\n"
                   1025:                        "\t\t[-B down up] [-w url]\n"
                   1026: #ifdef USE_PF
                   1027:                         "\t\t[-q queue] [-T tag]\n"
                   1028: #endif
                   1029: #ifdef ENABLE_NFQUEUE
                   1030:                         "\t\t[-Q queue] [-n name]\n"
                   1031: #endif
                   1032:                "\nNotes:\n\tThere can be one or several listening_ips.\n"
                   1033:                "\tNotify interval is in seconds. Default is 30 seconds.\n"
                   1034:                        "\tDefault pid file is '%s'.\n"
                   1035:                        "\tDefault config file is '%s'.\n"
                   1036:                        "\tWith -d miniupnpd will run as a standard program.\n"
                   1037:                        "\t-L sets packet log in pf and ipf on.\n"
                   1038:                        "\t-S sets \"secure\" mode : clients can only add mappings to their own ip\n"
                   1039:                        "\t-U causes miniupnpd to report system uptime instead "
                   1040:                        "of daemon uptime.\n"
                   1041: #ifdef ENABLE_NATPMP
                   1042:                        "\t-N enable NAT-PMP functionnality.\n"
                   1043: #endif
                   1044:                        "\t-B sets bitrates reported by daemon in bits per second.\n"
                   1045:                        "\t-w sets the presentation url. Default is http address on port 80\n"
                   1046: #ifdef USE_PF
                   1047:                        "\t-q sets the ALTQ queue in pf.\n"
                   1048:                        "\t-T sets the tag name in pf.\n"
                   1049: #endif
                   1050: #ifdef ENABLE_NFQUEUE
                   1051:                         "\t-Q sets the queue number that is used by NFQUEUE.\n"
                   1052:                         "\t-n sets the name of the interface(s) that packets will arrive on.\n"
                   1053: #endif
                   1054:                        "\t-h prints this help and quits.\n"
                   1055:                "", argv[0], pidfilename, DEFAULT_CONFIG);
                   1056:        return 1;
                   1057: }
                   1058: 
                   1059: /* === main === */
                   1060: /* process HTTP or SSDP requests */
                   1061: int
                   1062: main(int argc, char * * argv)
                   1063: {
                   1064:        int i;
1.1.1.2 ! misho    1065:        int shttpl = -1;        /* socket for HTTP */
        !          1066:        int sudp = -1;          /* IP v4 socket for receiving SSDP */
        !          1067: #ifdef ENABLE_IPV6
        !          1068:        int sudpv6 = -1;        /* IP v6 socket for receiving SSDP */
        !          1069: #endif
1.1       misho    1070: #ifdef ENABLE_NATPMP
1.1.1.2 ! misho    1071:        int * snatpmp;
        !          1072: #endif
1.1       misho    1073: #ifdef ENABLE_NFQUEUE
                   1074:        int nfqh = -1;
                   1075: #endif
1.1.1.2 ! misho    1076: #ifdef USE_IFACEWATCHER
        !          1077:        int sifacewatcher = -1;
1.1       misho    1078: #endif
1.1.1.2 ! misho    1079: 
        !          1080:        int * snotify;
        !          1081:        int addr_count;
1.1       misho    1082:        LIST_HEAD(httplisthead, upnphttp) upnphttphead;
                   1083:        struct upnphttp * e = 0;
                   1084:        struct upnphttp * next;
                   1085:        fd_set readset; /* for select() */
                   1086: #ifdef ENABLE_EVENTS
                   1087:        fd_set writeset;
                   1088: #endif
                   1089:        struct timeval timeout, timeofday, lasttimeofday = {0, 0};
                   1090:        int max_fd = -1;
                   1091: #ifdef USE_MINIUPNPDCTL
                   1092:        int sctl = -1;
                   1093:        LIST_HEAD(ctlstructhead, ctlelem) ctllisthead;
                   1094:        struct ctlelem * ectl;
                   1095:        struct ctlelem * ectlnext;
                   1096: #endif
                   1097:        struct runtime_vars v;
                   1098:        /* variables used for the unused-rule cleanup process */
                   1099:        struct rule_state * rule_list = 0;
                   1100:        struct timeval checktime = {0, 0};
1.1.1.2 ! misho    1101:        struct lan_addr_s * lan_addr;
1.1       misho    1102:        syslog(LOG_INFO, "SNet version started");
                   1103: 
1.1.1.2 ! misho    1104:        if(init(argc, argv, &v) != 0)
        !          1105:                return 1;
        !          1106:        /* count lan addrs */
        !          1107:        addr_count = 0;
        !          1108:        for(lan_addr = lan_addrs.lh_first; lan_addr != NULL; lan_addr = lan_addr->list.le_next)
        !          1109:                addr_count++;
        !          1110:        snotify = (int*) malloc(addr_count * sizeof(int));
1.1       misho    1111:        memset(snotify, 0, sizeof(snotify));
                   1112: #ifdef ENABLE_NATPMP
1.1.1.2 ! misho    1113:        snatpmp = (int*) malloc(addr_count * sizeof(int));
        !          1114:        for(i = 0; i < addr_count; i++)
1.1       misho    1115:                snatpmp[i] = -1;
                   1116: #endif
                   1117: 
                   1118:        LIST_INIT(&upnphttphead);
                   1119: #ifdef USE_MINIUPNPDCTL
                   1120:        LIST_INIT(&ctllisthead);
                   1121: #endif
                   1122: 
                   1123:        if(
                   1124: #ifdef ENABLE_NATPMP
                   1125:         !GETFLAG(ENABLENATPMPMASK) &&
                   1126: #endif
                   1127:         !GETFLAG(ENABLEUPNPMASK) ) {
                   1128:                syslog(LOG_ERR, "Why did you run me anyway?");
                   1129:                return 0;
                   1130:        }
                   1131: 
                   1132:        if(GETFLAG(ENABLEUPNPMASK))
                   1133:        {
                   1134: 
                   1135:                /* open socket for HTTP connections. Listen on the 1st LAN address */
                   1136:                shttpl = OpenAndConfHTTPSocket((v.port > 0) ? v.port : 0);
                   1137:                if(shttpl < 0)
                   1138:                {
                   1139:                        syslog(LOG_ERR, "Failed to open socket for HTTP. EXITING");
                   1140:                        return 1;
                   1141:                }
                   1142:                if(v.port <= 0) {
                   1143:                        struct sockaddr_in sockinfo;
                   1144:                        socklen_t len = sizeof(struct sockaddr_in);
                   1145:                        if (getsockname(shttpl, (struct sockaddr *)&sockinfo, &len) < 0) {
                   1146:                                syslog(LOG_ERR, "getsockname(): %m");
                   1147:                                return 1;
                   1148:                        }
                   1149:                        v.port = ntohs(sockinfo.sin_port);
                   1150:                }
                   1151:                syslog(LOG_NOTICE, "HTTP listening on port %d", v.port);
1.1.1.2 ! misho    1152: #ifdef ENABLE_IPV6
        !          1153:                if(find_ipv6_addr(NULL, ipv6_addr_for_http_with_brackets, sizeof(ipv6_addr_for_http_with_brackets)) > 0) {
        !          1154:                        syslog(LOG_NOTICE, "HTTP IPv6 address given to control points : %s",
        !          1155:                               ipv6_addr_for_http_with_brackets);
        !          1156:                } else {
        !          1157:                        memcpy(ipv6_addr_for_http_with_brackets, "[::1]", 6);
        !          1158:                        syslog(LOG_WARNING, "no HTTP IPv6 address");
        !          1159:                }
        !          1160: #endif
1.1       misho    1161: 
                   1162:                /* open socket for SSDP connections */
1.1.1.2 ! misho    1163:                sudp = OpenAndConfSSDPReceiveSocket(0);
1.1       misho    1164:                if(sudp < 0)
                   1165:                {
                   1166:                        syslog(LOG_INFO, "Failed to open socket for receiving SSDP. Trying to use MiniSSDPd");
1.1.1.2 ! misho    1167:                        if(SubmitServicesToMiniSSDPD(lan_addrs.lh_first->str, v.port) < 0) {
1.1       misho    1168:                                syslog(LOG_ERR, "Failed to connect to MiniSSDPd. EXITING");
                   1169:                                return 1;
                   1170:                        }
                   1171:                }
1.1.1.2 ! misho    1172: #ifdef ENABLE_IPV6
        !          1173:                sudpv6 = OpenAndConfSSDPReceiveSocket(1);
        !          1174:                if(sudpv6 < 0)
        !          1175:                {
        !          1176:                        syslog(LOG_INFO, "Failed to open socket for receiving SSDP (IP v6).");
        !          1177:                }
        !          1178: #endif
1.1       misho    1179: 
                   1180:                /* open socket for sending notifications */
                   1181:                if(OpenAndConfSSDPNotifySockets(snotify) < 0)
                   1182:                {
                   1183:                        syslog(LOG_ERR, "Failed to open sockets for sending SSDP notify "
                   1184:                                "messages. EXITING");
                   1185:                        return 1;
                   1186:                }
1.1.1.2 ! misho    1187: 
        !          1188: #ifdef USE_IFACEWATCHER
        !          1189:                /* open socket for kernel notifications about new network interfaces */
        !          1190:                if (sudp >= 0)
        !          1191:                {
        !          1192:                        sifacewatcher = OpenAndConfInterfaceWatchSocket();
        !          1193:                        if (sifacewatcher < 0)
        !          1194:                        {
        !          1195:                                syslog(LOG_ERR, "Failed to open socket for receiving network interface notifications");
        !          1196:                        }
        !          1197:                }
        !          1198: #endif
1.1       misho    1199:        }
                   1200: 
                   1201: #ifdef ENABLE_NATPMP
                   1202:        /* open socket for NAT PMP traffic */
                   1203:        if(GETFLAG(ENABLENATPMPMASK))
                   1204:        {
                   1205:                if(OpenAndConfNATPMPSockets(snatpmp) < 0)
                   1206:                {
                   1207:                        syslog(LOG_ERR, "Failed to open sockets for NAT PMP.");
                   1208:                } else {
                   1209:                        syslog(LOG_NOTICE, "Listening for NAT-PMP traffic on port %u",
                   1210:                               NATPMP_PORT);
                   1211:                }
1.1.1.2 ! misho    1212: #if 0
1.1       misho    1213:                ScanNATPMPforExpiration();
1.1.1.2 ! misho    1214: #endif
1.1       misho    1215:        }
                   1216: #endif
                   1217: 
                   1218:        /* for miniupnpdctl */
                   1219: #ifdef USE_MINIUPNPDCTL
                   1220:        sctl = OpenAndConfCtlUnixSocket("/var/run/miniupnpd.ctl");
                   1221: #endif
                   1222: 
                   1223: #ifdef ENABLE_NFQUEUE
                   1224:        if ( nfqueue != -1 && n_nfqix > 0) {
                   1225:                nfqh = OpenAndConfNFqueue();
                   1226:                if(nfqh < 0) {
                   1227:                        syslog(LOG_ERR, "Failed to open fd for NFQUEUE.");
                   1228:                        return 1;
                   1229:                } else {
                   1230:                        syslog(LOG_NOTICE, "Opened NFQUEUE %d",nfqueue);
                   1231:                }
                   1232:        }
                   1233: #endif
                   1234:        /* main loop */
                   1235:        while(!quitting)
                   1236:        {
                   1237:                /* Correct startup_time if it was set with a RTC close to 0 */
                   1238:                if((startup_time<60*60*24) && (time(NULL)>60*60*24))
                   1239:                {
                   1240:                        set_startup_time(GETFLAG(SYSUPTIMEMASK));
                   1241:                } 
1.1.1.2 ! misho    1242:                /* send public address change notifications if needed */
        !          1243:                if(should_send_public_address_change_notif)
        !          1244:                {
        !          1245:                        syslog(LOG_DEBUG, "should send external iface address change notification(s)");
        !          1246: #ifdef ENABLE_NATPMP
        !          1247:                        if(GETFLAG(ENABLENATPMPMASK))
        !          1248:                                SendNATPMPPublicAddressChangeNotification(snatpmp, addr_count);
        !          1249: #endif
        !          1250: #ifdef ENABLE_EVENTS
        !          1251:                        if(GETFLAG(ENABLEUPNPMASK))
        !          1252:                        {
        !          1253:                                upnp_event_var_change_notify(EWanIPC);
        !          1254:                        }
        !          1255: #endif
        !          1256:                        should_send_public_address_change_notif = 0;
        !          1257:                }
1.1       misho    1258:                /* Check if we need to send SSDP NOTIFY messages and do it if
                   1259:                 * needed */
                   1260:                if(gettimeofday(&timeofday, 0) < 0)
                   1261:                {
                   1262:                        syslog(LOG_ERR, "gettimeofday(): %m");
                   1263:                        timeout.tv_sec = v.notify_interval;
                   1264:                        timeout.tv_usec = 0;
                   1265:                }
                   1266:                else
                   1267:                {
                   1268:                        /* the comparaison is not very precise but who cares ? */
                   1269:                        if(timeofday.tv_sec >= (lasttimeofday.tv_sec + v.notify_interval))
                   1270:                        {
                   1271:                                if (GETFLAG(ENABLEUPNPMASK))
                   1272:                                        SendSSDPNotifies2(snotify,
                   1273:                                                  (unsigned short)v.port,
                   1274:                                                  v.notify_interval << 1);
                   1275:                                memcpy(&lasttimeofday, &timeofday, sizeof(struct timeval));
                   1276:                                timeout.tv_sec = v.notify_interval;
                   1277:                                timeout.tv_usec = 0;
                   1278:                        }
                   1279:                        else
                   1280:                        {
                   1281:                                timeout.tv_sec = lasttimeofday.tv_sec + v.notify_interval
                   1282:                                                 - timeofday.tv_sec;
                   1283:                                if(timeofday.tv_usec > lasttimeofday.tv_usec)
                   1284:                                {
                   1285:                                        timeout.tv_usec = 1000000 + lasttimeofday.tv_usec
                   1286:                                                          - timeofday.tv_usec;
                   1287:                                        timeout.tv_sec--;
                   1288:                                }
                   1289:                                else
                   1290:                                {
                   1291:                                        timeout.tv_usec = lasttimeofday.tv_usec - timeofday.tv_usec;
                   1292:                                }
                   1293:                        }
                   1294:                }
                   1295:                /* remove unused rules */
                   1296:                if( v.clean_ruleset_interval
                   1297:                  && (timeofday.tv_sec >= checktime.tv_sec + v.clean_ruleset_interval))
                   1298:                {
                   1299:                        if(rule_list)
                   1300:                        {
                   1301:                                remove_unused_rules(rule_list);
                   1302:                                rule_list = NULL;
                   1303:                        }
                   1304:                        else
                   1305:                        {
                   1306:                                rule_list = get_upnp_rules_state_list(v.clean_ruleset_threshold);
                   1307:                        }
                   1308:                        memcpy(&checktime, &timeofday, sizeof(struct timeval));
                   1309:                }
1.1.1.2 ! misho    1310:                /* Remove expired port mappings, based on UPnP IGD LeaseDuration
        !          1311:                 * or NAT-PMP lifetime) */
        !          1312:                if(nextruletoclean_timestamp
        !          1313:                  && (timeofday.tv_sec >= nextruletoclean_timestamp))
        !          1314:                {
        !          1315:                        syslog(LOG_DEBUG, "cleaning expired Port Mappings");
        !          1316:                        get_upnp_rules_state_list(0);
        !          1317:                }
        !          1318:                if(nextruletoclean_timestamp
        !          1319:                  && timeout.tv_sec >= (nextruletoclean_timestamp - timeofday.tv_sec))
        !          1320:                {
        !          1321:                        timeout.tv_sec = nextruletoclean_timestamp - timeofday.tv_sec;
        !          1322:                        timeout.tv_usec = 0;
        !          1323:                        syslog(LOG_DEBUG, "setting timeout to %u sec",
        !          1324:                               (unsigned)timeout.tv_sec);
        !          1325:                }
1.1       misho    1326: #ifdef ENABLE_NATPMP
1.1.1.2 ! misho    1327: #if 0
1.1       misho    1328:                /* Remove expired NAT-PMP mappings */
1.1.1.2 ! misho    1329:                while(nextnatpmptoclean_timestamp
        !          1330:                     && (timeofday.tv_sec >= nextnatpmptoclean_timestamp + startup_time))
1.1       misho    1331:                {
                   1332:                        /*syslog(LOG_DEBUG, "cleaning expired NAT-PMP mappings");*/
                   1333:                        if(CleanExpiredNATPMP() < 0) {
                   1334:                                syslog(LOG_ERR, "CleanExpiredNATPMP() failed");
                   1335:                                break;
                   1336:                        }
                   1337:                }
1.1.1.2 ! misho    1338:                if(nextnatpmptoclean_timestamp
        !          1339:                  && timeout.tv_sec >= (nextnatpmptoclean_timestamp + startup_time - timeofday.tv_sec))
1.1       misho    1340:                {
1.1.1.2 ! misho    1341:                        /*syslog(LOG_DEBUG, "setting timeout to %d sec",
        !          1342:                               nextnatpmptoclean_timestamp + startup_time - timeofday.tv_sec);*/
1.1       misho    1343:                        timeout.tv_sec = nextnatpmptoclean_timestamp + startup_time - timeofday.tv_sec;
                   1344:                        timeout.tv_usec = 0;
                   1345:                }
                   1346: #endif
1.1.1.2 ! misho    1347: #endif
1.1       misho    1348: 
                   1349:                /* select open sockets (SSDP, HTTP listen, and all HTTP soap sockets) */
                   1350:                FD_ZERO(&readset);
                   1351: 
                   1352:                if (sudp >= 0) 
                   1353:                {
                   1354:                        FD_SET(sudp, &readset);
                   1355:                        max_fd = MAX( max_fd, sudp);
1.1.1.2 ! misho    1356: #ifdef USE_IFACEWATCHER
        !          1357:                        if (sifacewatcher >= 0)
        !          1358:                        {
        !          1359:                                FD_SET(sifacewatcher, &readset);
        !          1360:                                max_fd = MAX(max_fd, sifacewatcher);
        !          1361:                        }
        !          1362: #endif
1.1       misho    1363:                }
                   1364:                if (shttpl >= 0) 
                   1365:                {
                   1366:                        FD_SET(shttpl, &readset);
                   1367:                        max_fd = MAX( max_fd, shttpl);
                   1368:                }
1.1.1.2 ! misho    1369: #ifdef ENABLE_IPV6
        !          1370:                if (sudpv6 >= 0)
        !          1371:                {
        !          1372:                        FD_SET(sudpv6, &readset);
        !          1373:                        max_fd = MAX( max_fd, sudpv6);
        !          1374:                }
        !          1375: #endif
        !          1376: 
        !          1377: #ifdef ENABLE_NFQUEUE
        !          1378:                if (nfqh >= 0) 
        !          1379:                {
        !          1380:                        FD_SET(nfqh, &readset);
        !          1381:                        max_fd = MAX( max_fd, nfqh);
        !          1382:                }
        !          1383: #endif
1.1       misho    1384: 
                   1385:                i = 0;  /* active HTTP connections count */
                   1386:                for(e = upnphttphead.lh_first; e != NULL; e = e->entries.le_next)
                   1387:                {
                   1388:                        if((e->socket >= 0) && (e->state <= 2))
                   1389:                        {
                   1390:                                FD_SET(e->socket, &readset);
                   1391:                                max_fd = MAX( max_fd, e->socket);
                   1392:                                i++;
                   1393:                        }
                   1394:                }
                   1395:                /* for debug */
                   1396: #ifdef DEBUG
                   1397:                if(i > 1)
                   1398:                {
                   1399:                        syslog(LOG_DEBUG, "%d active incoming HTTP connections", i);
                   1400:                }
                   1401: #endif
                   1402: #ifdef ENABLE_NATPMP
1.1.1.2 ! misho    1403:                for(i=0; i<addr_count; i++) {
1.1       misho    1404:                        if(snatpmp[i] >= 0) {
                   1405:                                FD_SET(snatpmp[i], &readset);
                   1406:                                max_fd = MAX( max_fd, snatpmp[i]);
                   1407:                        }
                   1408:                }
                   1409: #endif
                   1410: #ifdef USE_MINIUPNPDCTL
                   1411:                if(sctl >= 0) {
                   1412:                        FD_SET(sctl, &readset);
                   1413:                        max_fd = MAX( max_fd, sctl);
                   1414:                }
                   1415:                
                   1416:                for(ectl = ctllisthead.lh_first; ectl; ectl = ectl->entries.le_next)
                   1417:                {
                   1418:                        if(ectl->socket >= 0) {
                   1419:                                FD_SET(ectl->socket, &readset);
                   1420:                                max_fd = MAX( max_fd, ectl->socket);
                   1421:                        }
                   1422:                }
                   1423: #endif
                   1424: 
                   1425: #ifdef ENABLE_EVENTS
                   1426:                FD_ZERO(&writeset);
                   1427:                upnpevents_selectfds(&readset, &writeset, &max_fd);
                   1428: #endif
                   1429: 
                   1430: #ifdef ENABLE_EVENTS
                   1431:                if(select(max_fd+1, &readset, &writeset, 0, &timeout) < 0)
                   1432: #else
                   1433:                if(select(max_fd+1, &readset, 0, 0, &timeout) < 0)
                   1434: #endif
                   1435:                {
                   1436:                        if(quitting) goto shutdown;
                   1437:                        if(errno == EINTR) continue; /* interrupted by a signal, start again */
                   1438:                        syslog(LOG_ERR, "select(all): %m");
                   1439:                        syslog(LOG_ERR, "Failed to select open sockets. EXITING");
                   1440:                        return 1;       /* very serious cause of error */
                   1441:                }
                   1442: #ifdef USE_MINIUPNPDCTL
                   1443:                for(ectl = ctllisthead.lh_first; ectl;)
                   1444:                {
                   1445:                        ectlnext =  ectl->entries.le_next;
                   1446:                        if((ectl->socket >= 0) && FD_ISSET(ectl->socket, &readset))
                   1447:                        {
                   1448:                                char buf[256];
                   1449:                                int l;
                   1450:                                l = read(ectl->socket, buf, sizeof(buf));
                   1451:                                if(l > 0)
                   1452:                                {
                   1453:                                        /*write(ectl->socket, buf, l);*/
                   1454:                                        write_command_line(ectl->socket, argc, argv);
                   1455:                                        write_option_list(ectl->socket);
                   1456:                                        write_permlist(ectl->socket, upnppermlist, num_upnpperm);
                   1457:                                        write_upnphttp_details(ectl->socket, upnphttphead.lh_first);
                   1458:                                        write_ctlsockets_list(ectl->socket, ctllisthead.lh_first);
                   1459:                                        write_ruleset_details(ectl->socket);
                   1460: #ifdef ENABLE_EVENTS
                   1461:                                        write_events_details(ectl->socket);
                   1462: #endif
                   1463:                                        /* close the socket */
                   1464:                                        close(ectl->socket);
                   1465:                                        ectl->socket = -1;
                   1466:                                }
                   1467:                                else
                   1468:                                {
                   1469:                                        close(ectl->socket);
                   1470:                                        ectl->socket = -1;
                   1471:                                }
                   1472:                        }
                   1473:                        if(ectl->socket < 0)
                   1474:                        {
                   1475:                                LIST_REMOVE(ectl, entries);
                   1476:                                free(ectl);
                   1477:                        }
                   1478:                        ectl = ectlnext;
                   1479:                }
                   1480:                if((sctl >= 0) && FD_ISSET(sctl, &readset))
                   1481:                {
                   1482:                        int s;
                   1483:                        struct sockaddr_un clientname;
                   1484:                        struct ctlelem * tmp;
                   1485:                        socklen_t clientnamelen = sizeof(struct sockaddr_un);
                   1486:                        //syslog(LOG_DEBUG, "sctl!");
                   1487:                        s = accept(sctl, (struct sockaddr *)&clientname,
                   1488:                                   &clientnamelen);
                   1489:                        syslog(LOG_DEBUG, "sctl! : '%s'", clientname.sun_path);
                   1490:                        tmp = malloc(sizeof(struct ctlelem));
                   1491:                        tmp->socket = s;
                   1492:                        LIST_INSERT_HEAD(&ctllisthead, tmp, entries);
                   1493:                }
                   1494: #endif
                   1495: #ifdef ENABLE_EVENTS
                   1496:                upnpevents_processfds(&readset, &writeset);
                   1497: #endif
                   1498: #ifdef ENABLE_NATPMP
                   1499:                /* process NAT-PMP packets */
1.1.1.2 ! misho    1500:                for(i=0; i<addr_count; i++)
1.1       misho    1501:                {
                   1502:                        if((snatpmp[i] >= 0) && FD_ISSET(snatpmp[i], &readset))
                   1503:                        {
                   1504:                                ProcessIncomingNATPMPPacket(snatpmp[i]);
                   1505:                        }
                   1506:                }
                   1507: #endif
                   1508:                /* process SSDP packets */
                   1509:                if(sudp >= 0 && FD_ISSET(sudp, &readset))
                   1510:                {
                   1511:                        /*syslog(LOG_INFO, "Received UDP Packet");*/
                   1512:                        ProcessSSDPRequest(sudp, (unsigned short)v.port);
                   1513:                }
1.1.1.2 ! misho    1514: #ifdef ENABLE_IPV6
        !          1515:                if(sudpv6 >= 0 && FD_ISSET(sudpv6, &readset))
        !          1516:                {
        !          1517:                        syslog(LOG_INFO, "Received UDP Packet (IPv6)");
        !          1518:                        ProcessSSDPRequest(sudpv6, (unsigned short)v.port);
        !          1519:                }
        !          1520: #endif
        !          1521: #ifdef USE_IFACEWATCHER
        !          1522:                /* process kernel notifications */
        !          1523:                if (sifacewatcher >= 0 && FD_ISSET(sifacewatcher, &readset))
        !          1524:                        ProcessInterfaceWatchNotify(sifacewatcher);
        !          1525: #endif
        !          1526: 
1.1       misho    1527:                /* process active HTTP connections */
                   1528:                /* LIST_FOREACH macro is not available under linux */
                   1529:                for(e = upnphttphead.lh_first; e != NULL; e = e->entries.le_next)
                   1530:                {
                   1531:                        if(  (e->socket >= 0) && (e->state <= 2)
                   1532:                                &&(FD_ISSET(e->socket, &readset)) )
                   1533:                        {
                   1534:                                Process_upnphttp(e);
                   1535:                        }
                   1536:                }
                   1537:                /* process incoming HTTP connections */
                   1538:                if(shttpl >= 0 && FD_ISSET(shttpl, &readset))
                   1539:                {
                   1540:                        int shttp;
                   1541:                        socklen_t clientnamelen;
1.1.1.2 ! misho    1542: #ifdef ENABLE_IPV6
        !          1543:                        struct sockaddr_storage clientname;
        !          1544:                        clientnamelen = sizeof(struct sockaddr_storage);
        !          1545: #else
1.1       misho    1546:                        struct sockaddr_in clientname;
                   1547:                        clientnamelen = sizeof(struct sockaddr_in);
1.1.1.2 ! misho    1548: #endif
1.1       misho    1549:                        shttp = accept(shttpl, (struct sockaddr *)&clientname, &clientnamelen);
                   1550:                        if(shttp<0)
                   1551:                        {
                   1552:                                syslog(LOG_ERR, "accept(http): %m");
                   1553:                        }
                   1554:                        else
                   1555:                        {
                   1556:                                struct upnphttp * tmp = 0;
1.1.1.2 ! misho    1557:                                char addr_str[64];
        !          1558: 
        !          1559:                                sockaddr_to_string((struct sockaddr *)&clientname, addr_str, sizeof(addr_str));
        !          1560:                                syslog(LOG_INFO, "HTTP connection from %s", addr_str);
1.1       misho    1561:                                /*if (fcntl(shttp, F_SETFL, O_NONBLOCK) < 0) {
                   1562:                                        syslog(LOG_ERR, "fcntl F_SETFL, O_NONBLOCK");
                   1563:                                }*/
                   1564:                                /* Create a new upnphttp object and add it to
                   1565:                                 * the active upnphttp object list */
                   1566:                                tmp = New_upnphttp(shttp);
                   1567:                                if(tmp)
                   1568:                                {
1.1.1.2 ! misho    1569: #ifdef ENABLE_IPV6
        !          1570:                                        if(clientname.ss_family == AF_INET)
        !          1571:                                        {
        !          1572:                                                tmp->clientaddr = ((struct sockaddr_in *)&clientname)->sin_addr;
        !          1573:                                        }
        !          1574:                                        else if(clientname.ss_family == AF_INET6)
        !          1575:                                        {
        !          1576:                                                struct sockaddr_in6 * addr = (struct sockaddr_in6 *)&clientname;
        !          1577:                                                if(IN6_IS_ADDR_V4MAPPED(&addr->sin6_addr))
        !          1578:                                                {
        !          1579:                                                        memcpy(&tmp->clientaddr,
        !          1580:                                                               &addr->sin6_addr.s6_addr[12],
        !          1581:                                                               4);
        !          1582:                                                }
        !          1583:                                                else
        !          1584:                                                {
        !          1585:                                                        tmp->ipv6 = 1;
        !          1586:                                                        memcpy(&tmp->clientaddr_v6,
        !          1587:                                                               &addr->sin6_addr,
        !          1588:                                                               sizeof(struct in6_addr));
        !          1589:                                                }
        !          1590:                                        }
        !          1591: #else
1.1       misho    1592:                                        tmp->clientaddr = clientname.sin_addr;
1.1.1.2 ! misho    1593: #endif
1.1       misho    1594:                                        LIST_INSERT_HEAD(&upnphttphead, tmp, entries);
                   1595:                                }
                   1596:                                else
                   1597:                                {
                   1598:                                        syslog(LOG_ERR, "New_upnphttp() failed");
                   1599:                                        close(shttp);
                   1600:                                }
                   1601:                        }
                   1602:                }
1.1.1.2 ! misho    1603: #ifdef ENABLE_NFQUEUE
        !          1604:                /* process NFQ packets */
        !          1605:                if(nfqh >= 0 && FD_ISSET(nfqh, &readset))
        !          1606:                {
        !          1607:                        /* syslog(LOG_INFO, "Received NFQUEUE Packet");*/
        !          1608:                        ProcessNFQUEUE(nfqh);
        !          1609:                }
        !          1610: #endif
1.1       misho    1611:                /* delete finished HTTP connections */
                   1612:                for(e = upnphttphead.lh_first; e != NULL; )
                   1613:                {
                   1614:                        next = e->entries.le_next;
                   1615:                        if(e->state >= 100)
                   1616:                        {
                   1617:                                LIST_REMOVE(e, entries);
                   1618:                                Delete_upnphttp(e);
                   1619:                        }
                   1620:                        e = next;
                   1621:                }
                   1622: 
                   1623:        }       /* end of main loop */
                   1624: 
                   1625: shutdown:
                   1626:        /* close out open sockets */
                   1627:        while(upnphttphead.lh_first != NULL)
                   1628:        {
                   1629:                e = upnphttphead.lh_first;
                   1630:                LIST_REMOVE(e, entries);
                   1631:                Delete_upnphttp(e);
                   1632:        }
                   1633: 
                   1634:        if (sudp >= 0) close(sudp);
                   1635:        if (shttpl >= 0) close(shttpl);
1.1.1.2 ! misho    1636: #ifdef ENABLE_IPV6
        !          1637:        if (sudpv6 >= 0) close(sudpv6);
        !          1638:        //if (shttplv6 >= 0) close(shttplv6);
        !          1639: #endif
        !          1640: #ifdef USE_IFACEWATCHER
        !          1641:        if(sifacewatcher >= 0) close(sifacewatcher);
        !          1642: #endif
1.1       misho    1643: #ifdef ENABLE_NATPMP
1.1.1.2 ! misho    1644:        for(i=0; i<addr_count; i++) {
1.1       misho    1645:                if(snatpmp[i]>=0)
                   1646:                {
                   1647:                        close(snatpmp[i]);
                   1648:                        snatpmp[i] = -1;
                   1649:                }
                   1650:        }
                   1651: #endif
                   1652: #ifdef USE_MINIUPNPDCTL
                   1653:        if(sctl>=0)
                   1654:        {
                   1655:                close(sctl);
                   1656:                sctl = -1;
                   1657:                if(unlink("/var/run/miniupnpd.ctl") < 0)
                   1658:                {
                   1659:                        syslog(LOG_ERR, "unlink() %m");
                   1660:                }
                   1661:        }
                   1662: #endif
                   1663:        
                   1664:        /*if(SendSSDPGoodbye(snotify, v.n_lan_addr) < 0)*/
                   1665:        if (GETFLAG(ENABLEUPNPMASK))
                   1666:        {
1.1.1.2 ! misho    1667:                if(SendSSDPGoodbye(snotify, addr_count) < 0)
1.1       misho    1668:                {
                   1669:                        syslog(LOG_ERR, "Failed to broadcast good-bye notifications");
                   1670:                }
1.1.1.2 ! misho    1671:                for(i=0; i<addr_count; i++)
1.1       misho    1672:                        close(snotify[i]);
                   1673:        }
                   1674: 
                   1675:        if(unlink(pidfilename) < 0)
                   1676:        {
                   1677:                syslog(LOG_ERR, "Failed to remove pidfile %s: %m", pidfilename);
                   1678:        }
                   1679: 
1.1.1.2 ! misho    1680:        /* delete lists */
        !          1681:        while(lan_addrs.lh_first != NULL)
        !          1682:        {
        !          1683:                lan_addr = lan_addrs.lh_first;
        !          1684:                LIST_REMOVE(lan_addrs.lh_first, list);
        !          1685:                free(lan_addr);
        !          1686:        }
        !          1687: 
        !          1688: #ifdef ENABLE_NATPMP
        !          1689:        free(snatpmp);
        !          1690: #endif
        !          1691:        free(snotify);
1.1       misho    1692:        closelog();     
                   1693:        freeoptions();
                   1694:        
                   1695:        return 0;
                   1696: }
                   1697: 

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