~ubuntu-branches/ubuntu/vivid/minissdpd/vivid

« back to all changes in this revision

Viewing changes to minissdpd.c

  • Committer: Bazaar Package Importer
  • Author(s): Thomas Goirand
  • Date: 2011-07-29 14:41:55 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20110729144155-2jqu1bmsv60qcnmi
Tags: 1.0.20110729-1
* New upstream release 1.0.20110729, fixing root exploit issue reported on
launchpad (Closes: #635836) (LP: #813313), thanks to Moritz Muehlenhoff
<jmm@debian.org> for the bug report, and to falks at Ubuntu for the
investigation of the issue.
* Added build-arch: and build-indep: targets in debian/rules.
* Bumped standard-version to 3.9.2.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* $Id: minissdpd.c,v 1.18 2008/10/07 12:24:54 nanard Exp $ */
 
1
/* $Id: minissdpd.c,v 1.22 2011/07/29 08:44:04 nanard Exp $ */
2
2
/* MiniUPnP project
3
 
 * (c) 2007-2008 Thomas Bernard
 
3
 * (c) 2007-2011 Thomas Bernard
4
4
 * website : http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
5
5
 * This software is subject to the conditions detailed
6
6
 * in the LICENCE file provided within the distribution */
7
7
 
 
8
#include "config.h"
 
9
 
8
10
#include <stdlib.h>
9
11
#include <stdio.h>
10
12
#include <string.h>
24
26
#include <sys/stat.h>
25
27
/* unix sockets */
26
28
#include <sys/un.h>
 
29
/* for getpwnam() and getgrnam() */
 
30
#include <pwd.h>
 
31
#include <grp.h>
27
32
 
28
 
/*#include "minissdp.h"*/
 
33
#include "upnputils.h"
29
34
#include "openssdpsocket.h"
30
35
#include "daemonize.h"
31
36
#include "codelength.h"
59
64
/* discovered device list kept in memory */
60
65
struct device * devlist = 0;
61
66
 
 
67
/* bootid and configid */
 
68
unsigned int upnp_bootid = 1;
 
69
unsigned int upnp_configid = 1337;
 
70
 
62
71
/* updateDevice() :
63
72
 * adds or updates the device to the list.
64
73
 * return value :
 
74
 *  -1 : error
65
75
 *   0 : the device was updated
66
76
 *   1 : the device was new    */
67
77
int updateDevice(const struct header * headers, time_t t)
102
112
                int i;
103
113
                p = malloc(  sizeof(struct device)
104
114
                           + headers[0].l+headers[1].l+headers[2].l );
 
115
                if(!p) {
 
116
                        syslog(LOG_ERR, "updateDevice(): cannot allocate memory");
 
117
                        return -1;
 
118
                }
105
119
                p->next = devlist;
106
120
                p->t = t;
107
121
                pc = p->data;
148
162
/* SendSSDPMSEARCHResponse() :
149
163
 * build and send response to M-SEARCH SSDP packets. */
150
164
static void
151
 
SendSSDPMSEARCHResponse(int s, const struct sockaddr_in * sockname,
 
165
SendSSDPMSEARCHResponse(int s, const struct sockaddr * sockname,
152
166
                        const char * st, const char * usn,
153
167
                        const char * server, const char * location)
154
168
{
155
 
    int l, n;
156
 
    char buf[512];
157
 
    /*
158
 
     * follow guideline from document "UPnP Device Architecture 1.0"
159
 
     * uppercase is recommended.
160
 
     * DATE: is recommended
161
 
     * SERVER: OS/ver UPnP/1.0 miniupnpd/1.0
162
 
     * - check what to put in the 'Cache-Control' header
163
 
     * */
164
 
    l = snprintf(buf, sizeof(buf), "HTTP/1.1 200 OK\r\n"
165
 
        "CACHE-CONTROL: max-age=120\r\n"
166
 
        /*"DATE: ...\r\n"*/
167
 
        "ST: %s\r\n"
168
 
        "USN: %s\r\n"
169
 
        "EXT:\r\n"
170
 
        "SERVER: %s\r\n"
171
 
        "LOCATION: %s\r\n"
172
 
        "\r\n",
173
 
        st, usn,
174
 
        server, location);
175
 
    n = sendto(s, buf, l, 0,
176
 
               (struct sockaddr *)sockname, sizeof(struct sockaddr_in) );
177
 
    if(n < 0) {
178
 
        syslog(LOG_ERR, "sendto(udp): %m");
179
 
    }
 
169
        int l, n;
 
170
        char buf[512];
 
171
        socklen_t sockname_len;
 
172
        /*
 
173
         * follow guideline from document "UPnP Device Architecture 1.0"
 
174
         * uppercase is recommended.
 
175
         * DATE: is recommended
 
176
         * SERVER: OS/ver UPnP/1.0 miniupnpd/1.0
 
177
         * - check what to put in the 'Cache-Control' header
 
178
         *
 
179
         * have a look at the document "UPnP Device Architecture v1.1 */
 
180
        l = snprintf(buf, sizeof(buf), "HTTP/1.1 200 OK\r\n"
 
181
                "CACHE-CONTROL: max-age=120\r\n"
 
182
                /*"DATE: ...\r\n"*/
 
183
        "ST: %s\r\n"
 
184
        "USN: %s\r\n"
 
185
        "EXT:\r\n"
 
186
        "SERVER: %s\r\n"
 
187
        "LOCATION: %s\r\n"
 
188
                "OPT: \"http://schemas.upnp.org/upnp/1/0/\";\r\n" /* UDA v1.1 */
 
189
                "01-NLS: %u\r\n" /* same as BOOTID. UDA v1.1 */
 
190
                "BOOTID.UPNP.ORG: %u\r\n" /* UDA v1.1 */
 
191
                "CONFIGID.UPNP.ORG: %u\r\n" /* UDA v1.1 */
 
192
        "\r\n",
 
193
                st, usn,
 
194
                server, location,
 
195
                upnp_bootid, upnp_bootid, upnp_configid);
 
196
#ifdef ENABLE_IPV6
 
197
        sockname_len = (sockname->sa_family == PF_INET6)
 
198
                     ? sizeof(struct sockaddr_in6)
 
199
                     : sizeof(struct sockaddr_in);
 
200
#else
 
201
        sockname_len = sizeof(struct sockaddr_in);
 
202
#endif
 
203
        n = sendto(s, buf, l, 0,
 
204
                   sockname, sockname_len );
 
205
        if(n < 0) {
 
206
                syslog(LOG_ERR, "sendto(udp): %m");
 
207
        }
180
208
}
181
209
 
182
210
/* Services stored for answering to M-SEARCH */
191
219
 
192
220
/* Process M-SEARCH requests */
193
221
void processMSEARCH(int s, const char * st, int st_len,
194
 
                    const struct sockaddr_in * addr)
 
222
                    const struct sockaddr * addr)
195
223
{
196
224
        struct service * serv;
 
225
#ifdef ENABLE_IPV6
 
226
        char buf[64];
 
227
#endif
 
228
 
197
229
        if(!st || st_len==0)
198
230
                return;
 
231
#ifdef ENABLE_IPV6
 
232
        sockaddr_to_string(addr, buf, sizeof(buf));
 
233
        syslog(LOG_INFO, "SSDP M-SEARCH from %s ST:%.*s",
 
234
               buf, st_len, st);
 
235
#else
199
236
        syslog(LOG_INFO, "SSDP M-SEARCH from %s:%d ST: %.*s",
200
 
           inet_ntoa(addr->sin_addr),
201
 
           ntohs(addr->sin_port),
202
 
           st_len, st);
 
237
               inet_ntoa(((const struct sockaddr_in *)addr)->sin_addr),
 
238
               ntohs(((const struct sockaddr_in *)addr)->sin_port),
 
239
               st_len, st);
 
240
#endif
203
241
        if(st_len==8 && (0==memcmp(st, "ssdp:all", 8))) {
204
242
                /* send a response for all services */
205
243
                for(serv = servicelisthead.lh_first;
247
285
 *     0 : no device removed nor added
248
286
 *     1 : a device was added.  */
249
287
int ParseSSDPPacket(int s, const char * p, ssize_t n,
250
 
                    const struct sockaddr_in * addr)
 
288
                    const struct sockaddr * addr)
251
289
{
252
290
        const char * linestart;
253
291
        const char * lineend;
273
311
        while(linestart < p + n - 2) {
274
312
                /* start parsing the line : detect line end */
275
313
                lineend = linestart;
276
 
                while(*lineend != '\n' && *lineend != '\r' && lineend < p + n)
 
314
                while(lineend < p + n && *lineend != '\n' && *lineend != '\r')
277
315
                        lineend++;
278
316
                //printf("line: '%.*s'\n", lineend - linestart, linestart);
279
317
                /* detect name end : ':' character */
280
318
                nameend = linestart;
281
 
                while(*nameend != ':' && nameend < lineend)
 
319
                while(nameend < lineend && *nameend != ':')
282
320
                        nameend++;
283
321
                /* detect value */
284
 
                valuestart = nameend + 1;
285
 
                while(isspace(*valuestart) && valuestart < lineend)
 
322
                if(nameend < lineend)
 
323
                        valuestart = nameend + 1;
 
324
                else
 
325
                        valuestart = nameend;
 
326
                /* trim spaces */
 
327
                while(valuestart < lineend && isspace(*valuestart))
286
328
                        valuestart++;
287
329
                /* suppress leading " if needed */
288
 
                if(*valuestart=='\"')
 
330
                if(valuestart < lineend && *valuestart=='\"')
289
331
                        valuestart++;
290
332
                if(nameend > linestart && valuestart < lineend) {
291
 
                        int l = nameend - linestart;
292
 
                        int m = lineend - valuestart;
 
333
                        int l = nameend - linestart;    /* header name length */
 
334
                        int m = lineend - valuestart;   /* header value length */
293
335
                        /* suppress tailing spaces */
294
336
                        while(m>0 && isspace(valuestart[m-1]))
295
337
                                m--;
296
338
                        /* suppress tailing ' if needed */
297
 
                        if(valuestart[m-1] == '\"')
 
339
                        if(m>0 && valuestart[m-1] == '\"')
298
340
                                m--;
299
341
                        i = -1;
300
342
                        /*printf("--%.*s: (%d)%.*s--\n", l, linestart,
312
354
                        else if(l==8 && 0==strncasecmp(linestart, "location", 8))
313
355
                                i = HEADER_LOCATION;
314
356
                        else if(l==13 && 0==strncasecmp(linestart, "cache-control", 13)) {
315
 
                                const char * name = valuestart;
316
 
                                const char * val;
317
 
                                int rem = m;
 
357
                                /* parse "name1=value1, name_alone, name2=value2" string */
 
358
                                const char * name = valuestart; /* name */
 
359
                                const char * val;                               /* value */
 
360
                                int rem = m;    /* remaining bytes to process */
318
361
                                while(rem > 0) {
319
362
                                        val = name;
320
 
                                        while(*val != '=' && *val != ',')
 
363
                                        while(val < name + rem && *val != '=' && *val != ',')
321
364
                                                val++;
 
365
                                        if(val >= name + rem)
 
366
                                                break;
322
367
                                        if(*val == '=') {
323
 
                                                while(*val == '=' || isspace(*val))
 
368
                                                while(val < name + rem && (*val == '=' || isspace(*val)))
324
369
                                                        val++;
 
370
                                                if(val >= name + rem)
 
371
                                                        break;
325
372
                                                if(0==strncasecmp(name, "max-age", 7))
326
373
                                                        lifetime = (unsigned int)strtoul(val, 0, 0);
 
374
                                                /* move to the next name=value pair */
327
375
                                                while(rem > 0 && *name != ',') {
328
376
                                                        rem--;
329
377
                                                        name++;
330
378
                                                }
 
379
                                                /* skip spaces */
331
380
                                                while(rem > 0 && (*name == ',' || isspace(*name))) {
332
381
                                                        rem--;
333
382
                                                        name++;
435
484
        unsigned char * rp = rbuf+1;
436
485
        unsigned char nrep = 0;
437
486
        time_t t;
438
 
        struct service * newserv;
 
487
        struct service * newserv = NULL;
439
488
        struct service * serv;
440
489
 
441
490
        n = read(req->socket, buf, sizeof(buf));
442
491
        if(n<0) {
443
492
                syslog(LOG_ERR, "(s=%d) processRequest(): read(): %m", req->socket);
444
 
                close(req->socket);
445
 
                req->socket = -1;
446
 
                return;
 
493
                goto error;
447
494
        }
448
495
        if(n==0) {
449
496
                syslog(LOG_INFO, "(s=%d) request connection closed", req->socket);
450
 
                close(req->socket);
451
 
                req->socket = -1;
452
 
                return;
 
497
                goto error;
453
498
        }
454
499
        t = time(NULL);
455
500
        type = buf[0];
456
501
        p = buf + 1;
457
502
        DECODELENGTH(l, p);
 
503
        if(p+l > buf+n) {
 
504
                syslog(LOG_WARNING, "bad request (length encoding)");
 
505
                goto error;
 
506
        }
458
507
        syslog(LOG_INFO, "(s=%d) request type=%d str='%.*s'",
459
508
               req->socket, type, l, p);
460
509
        switch(type) {
497
546
                for(serv = servicelisthead.lh_first;
498
547
                    serv && (nrep < 255);
499
548
                    serv = serv->entries.le_next) {
 
549
                        /* test if we can put more responses in the buffer */
500
550
                        if(strlen(serv->location) + strlen(serv->st)
501
551
                          + strlen(serv->usn) + 6 + (rp - rbuf) >= sizeof(rbuf))
502
552
                                break;
523
573
                        }
524
574
                }
525
575
                rbuf[0] = nrep;
526
 
                if(write(req->socket, rbuf, rp - rbuf) < 0)
 
576
                if(write(req->socket, rbuf, rp - rbuf) < 0) {
527
577
                        syslog(LOG_ERR, "(s=%d) write: %m", req->socket);
 
578
                        goto error;
 
579
                }
528
580
                break;
529
581
        case 4:
530
582
                newserv = malloc(sizeof(struct service));
531
583
                if(!newserv) {
532
584
                        syslog(LOG_ERR, "cannot allocate memory");
533
 
                        return;
 
585
                        goto error;
534
586
                }
535
587
                newserv->st = malloc(l + 1);
536
588
                if(!newserv->st) {
537
589
                        syslog(LOG_ERR, "cannot allocate memory");
538
 
                        return;
 
590
                        goto error;
539
591
                }
540
592
                memcpy(newserv->st, p, l);
541
593
                newserv->st[l] = '\0';
542
594
                p += l;
 
595
                if(p >= buf + n) {
 
596
                        syslog(LOG_WARNING, "bad request (missing usn)");
 
597
                        goto error;
 
598
                }
543
599
                DECODELENGTH(l, p);
 
600
                if(p+l > buf+n) {
 
601
                        syslog(LOG_WARNING, "bad request (length encoding)");
 
602
                        goto error;
 
603
                }
544
604
                syslog(LOG_INFO, "usn='%.*s'", l, p);
545
605
                newserv->usn = malloc(l + 1);
546
606
                if(!newserv->usn) {
547
607
                        syslog(LOG_ERR, "cannot allocate memory");
548
 
                        return;
 
608
                        goto error;
549
609
                }
550
610
                memcpy(newserv->usn, p, l);
551
611
                newserv->usn[l] = '\0';
555
615
                newserv->server = malloc(l + 1);
556
616
                if(!newserv->server) {
557
617
                        syslog(LOG_ERR, "cannot allocate memory");
558
 
                        return;
 
618
                        goto error;
559
619
                }
560
620
                memcpy(newserv->server, p, l);
561
621
                newserv->server[l] = '\0';
565
625
                newserv->location = malloc(l + 1);
566
626
                if(!newserv->location) {
567
627
                        syslog(LOG_ERR, "cannot allocate memory");
568
 
                        return;
 
628
                        goto error;
569
629
                }
570
630
                memcpy(newserv->location, p, l);
571
631
                newserv->location[l] = '\0';
583
643
                                free(serv->location);
584
644
                                serv->location = newserv->location;
585
645
                                free(newserv);
 
646
                                newserv = NULL;
586
647
                                return;
587
648
                        }
588
649
                }
589
650
                /* Inserting new service */
590
651
                LIST_INSERT_HEAD(&servicelisthead, newserv, entries);
 
652
                newserv = NULL;
591
653
                /*rbuf[0] = '\0';
592
654
                if(write(req->socket, rbuf, 1) < 0)
593
655
                        syslog(LOG_ERR, "(s=%d) write: %m", req->socket);
596
658
        default:
597
659
                syslog(LOG_WARNING, "Unknown request type %d", type);
598
660
                rbuf[0] = '\0';
599
 
                if(write(req->socket, rbuf, 1) < 0)
 
661
                if(write(req->socket, rbuf, 1) < 0) {
600
662
                        syslog(LOG_ERR, "(s=%d) write: %m", req->socket);
601
 
        }
 
663
                        goto error;
 
664
                }
 
665
        }
 
666
        return;
 
667
error:
 
668
        if(newserv) {
 
669
                free(newserv->st);
 
670
                free(newserv->usn);
 
671
                free(newserv->server);
 
672
                free(newserv->location);
 
673
                free(newserv);
 
674
                newserv = NULL;
 
675
        }
 
676
        close(req->socket);
 
677
        req->socket = -1;
 
678
        return;
602
679
}
603
680
 
604
681
static volatile int quitting = 0;
614
691
/* main(): program entry point */
615
692
int main(int argc, char * * argv)
616
693
{
 
694
        int ret = 0;
617
695
        int pid;
618
696
        struct sigaction sa;
619
697
        char buf[1500];
620
698
        ssize_t n;
621
 
        int s_ssdp;     /* udp socket receiving ssdp packets */
622
 
        int s_unix;     /* unix socket communicating with clients */
 
699
        int s_ssdp = -1;        /* udp socket receiving ssdp packets */
 
700
#ifdef ENABLE_IPV6
 
701
        int s_ssdp6 = -1;       /* udp socket receiving ssdp packets IPv6*/
 
702
#endif
 
703
        int s_unix = -1;        /* unix socket communicating with clients */
623
704
        int s;
624
705
        LIST_HEAD(reqstructhead, reqelem) reqlisthead;
625
706
        struct reqelem * req;
631
712
        const char * sockpath = "/var/run/minissdpd.sock";
632
713
        const char * pidfilename = "/var/run/minissdpd.pid";
633
714
        int debug_flag = 0;
 
715
        int ipv6 = 0;
634
716
        int deltadev = 0;
635
717
        struct sockaddr_in sendername;
636
 
        socklen_t len_r;
637
 
        len_r = sizeof(struct sockaddr_in);
 
718
        socklen_t sendername_len;
 
719
#ifdef ENABLE_IPV6
 
720
        struct sockaddr_in6 sendername6;
 
721
        socklen_t sendername6_len;
 
722
#endif
638
723
 
639
724
        LIST_INIT(&reqlisthead);
640
725
        LIST_INIT(&servicelisthead);
653
738
                        sockpath = argv[++i];
654
739
                else if(0==strcmp(argv[i], "-p"))
655
740
                        pidfilename = argv[++i];
 
741
#ifdef ENABLE_IPV6
 
742
                else if(0==strcmp(argv[i], "-6"))
 
743
                        ipv6 = 1;
 
744
#endif
656
745
        }
657
746
        if(n_if_addr < 1)
658
747
        {
659
748
                fprintf(stderr,
660
 
                        "Usage: %s [-d] [-s socket] [-p pidfile] "
661
 
                                "-i <interface_address> [-i <interface_address2>] ...\n",
 
749
                        "Usage: %s [-d] [-6] [-s socket] [-p pidfile] "
 
750
                                "-i <interface> [-i <interface2>] ...\n",
662
751
                        argv[0]);
663
752
                fprintf(stderr,
664
 
                        "By default, socket will be open as %s "
 
753
                        "\n  <interface> is either an IPv4 address such as 192.168.1.42, or an\ninterface name such as eth0.\n");
 
754
                fprintf(stderr,
 
755
                        "\n  By default, socket will be open as %s\n"
665
756
                        "and pid written to file %s\n",
666
757
                        sockpath, pidfilename);
667
758
                return 1;
700
791
        if(sigaction(SIGTERM, &sa, NULL))
701
792
        {
702
793
                syslog(LOG_ERR, "Failed to set SIGTERM handler. EXITING");
703
 
                return 1;
 
794
                ret = 1;
 
795
                goto quit;
704
796
        }
705
797
        if(sigaction(SIGINT, &sa, NULL))
706
798
        {
707
799
                syslog(LOG_ERR, "Failed to set SIGINT handler. EXITING");
708
 
                return 1;
 
800
                ret = 1;
 
801
                goto quit;
709
802
        }
710
 
        s_ssdp = OpenAndConfSSDPReceiveSocket(n_if_addr, if_addr);
 
803
        /* open UDP socket(s) for receiving SSDP packets */
 
804
        s_ssdp = OpenAndConfSSDPReceiveSocket(n_if_addr, if_addr, 0);
711
805
        if(s_ssdp < 0)
712
806
        {
713
807
                syslog(LOG_ERR, "Cannot open socket for receiving SSDP messages, exiting");
714
 
                return 1;
715
 
        }
 
808
                ret = 1;
 
809
                goto quit;
 
810
        }
 
811
#ifdef ENABLE_IPV6
 
812
        if(ipv6) {
 
813
                s_ssdp6 = OpenAndConfSSDPReceiveSocket(n_if_addr, if_addr, 1);
 
814
                if(s_ssdp6 < 0)
 
815
                {
 
816
                        syslog(LOG_ERR, "Cannot open socket for receiving SSDP messages (IPv6), exiting");
 
817
                        ret = 1;
 
818
                        goto quit;
 
819
                }
 
820
        }
 
821
#endif
 
822
        /* Open Unix socket to communicate with other programs on
 
823
         * the same machine */
716
824
        s_unix = OpenUnixSocket(sockpath);
717
825
        if(s_unix < 0)
718
826
        {
719
827
                syslog(LOG_ERR, "Cannot open unix socket for communicating with clients. Exiting");
720
 
                return 1;
721
 
        }
 
828
                ret = 1;
 
829
                goto quit;
 
830
        }
 
831
 
 
832
        /* drop privileges */
 
833
#if 0
 
834
        /* if we drop privileges, how to unlink(/var/run/minissdpd.sock) ? */
 
835
        if(getuid() == 0) {
 
836
                struct passwd * user;
 
837
                struct group * group;
 
838
                user = getpwnam("nobody");
 
839
                if(!user) {
 
840
                        syslog(LOG_ERR, "getpwnam(\"%s\") : %m", "nobody");
 
841
                        ret = 1;
 
842
                        goto quit;
 
843
                }
 
844
                group = getgrnam("nogroup");
 
845
                if(!group) {
 
846
                        syslog(LOG_ERR, "getgrnam(\"%s\") : %m", "nogroup");
 
847
                        ret = 1;
 
848
                        goto quit;
 
849
                }
 
850
                if(setgid(group->gr_gid) < 0) {
 
851
                        syslog(LOG_ERR, "setgit(%d) : %m", group->gr_gid);
 
852
                        ret = 1;
 
853
                        goto quit;
 
854
                }
 
855
                if(setuid(user->pw_uid) < 0) {
 
856
                        syslog(LOG_ERR, "setuid(%d) : %m", user->pw_uid);
 
857
                        ret = 1;
 
858
                        goto quit;
 
859
                }
 
860
        }
 
861
#endif
722
862
 
723
863
        /* Main loop */
724
864
        while(!quitting)
726
866
                /* fill readfds fd_set */
727
867
                FD_ZERO(&readfds);
728
868
                FD_SET(s_ssdp, &readfds);
 
869
#ifdef ENABLE_IPV6
 
870
                if(s_ssdp6 >= 0) {
 
871
                        FD_SET(s_ssdp6, &readfds);
 
872
                }
 
873
#endif
729
874
                FD_SET(s_unix, &readfds);
730
875
                for(req = reqlisthead.lh_first; req; req = req->entries.le_next)
731
876
                {
739
884
                                syslog(LOG_ERR, "select: %m");
740
885
                        break;
741
886
                }
 
887
#ifdef ENABLE_IPV6
 
888
                if((s_ssdp6 >= 0) && FD_ISSET(s_ssdp6, &readfds))
 
889
                {
 
890
                        sendername6_len = sizeof(struct sockaddr_in6);
 
891
                        n = recvfrom(s_ssdp6, buf, sizeof(buf), 0,
 
892
                                     (struct sockaddr *)&sendername6, &sendername6_len);
 
893
                        if(n<0)
 
894
                        {
 
895
                                syslog(LOG_ERR, "recvfrom: %m");
 
896
                        }
 
897
                        else
 
898
                        {
 
899
                                /* Parse and process the packet received */
 
900
                                /*printf("%.*s", n, buf);*/
 
901
                                i = ParseSSDPPacket(s_ssdp6, buf, n,
 
902
                                                    (struct sockaddr *)&sendername6);
 
903
                                syslog(LOG_DEBUG, "** i=%d deltadev=%d **", i, deltadev);
 
904
                                if(i==0 || (i*deltadev < 0))
 
905
                                {
 
906
                                        if(deltadev > 0)
 
907
                                                syslog(LOG_NOTICE, "%d new devices added", deltadev);
 
908
                                        else if(deltadev < 0)
 
909
                                                syslog(LOG_NOTICE, "%d devices removed (good-bye!)", -deltadev);
 
910
                                        deltadev = i;
 
911
                                }
 
912
                                else if((i*deltadev) >= 0)
 
913
                                {
 
914
                                        deltadev += i;
 
915
                                }
 
916
                        }
 
917
                }
 
918
#endif
742
919
                if(FD_ISSET(s_ssdp, &readfds))
743
920
                {
 
921
                        sendername_len = sizeof(struct sockaddr_in);
744
922
                        n = recvfrom(s_ssdp, buf, sizeof(buf), 0,
745
 
                                     (struct sockaddr *)&sendername, &len_r);
 
923
                                     (struct sockaddr *)&sendername, &sendername_len);
746
924
                        if(n<0)
747
925
                        {
748
926
                                syslog(LOG_ERR, "recvfrom: %m");
751
929
                        {
752
930
                                /* Parse and process the packet received */
753
931
                                /*printf("%.*s", n, buf);*/
754
 
                                i = ParseSSDPPacket(s_ssdp, buf, n, &sendername);
 
932
                                i = ParseSSDPPacket(s_ssdp, buf, n,
 
933
                                                    (struct sockaddr *)&sendername);
755
934
                                syslog(LOG_DEBUG, "** i=%d deltadev=%d **", i, deltadev);
756
935
                                if(i==0 || (i*deltadev < 0))
757
936
                                {
767
946
                                }
768
947
                        }
769
948
                }
 
949
                /* processing unix socket requests */
770
950
                for(req = reqlisthead.lh_first; req;)
771
951
                {
772
952
                        reqnext = req->entries.le_next;
781
961
                        }
782
962
                        req = reqnext;
783
963
                }
 
964
                /* processing new requests */
784
965
                if(FD_ISSET(s_unix, &readfds))
785
966
                {
786
967
                        struct reqelem * tmp;
793
974
                        {
794
975
                                syslog(LOG_INFO, "(s=%d) new request connection", s);
795
976
                                tmp = malloc(sizeof(struct reqelem));
796
 
                                tmp->socket = s;
797
 
                                LIST_INSERT_HEAD(&reqlisthead, tmp, entries);
 
977
                                if(!tmp)
 
978
                                {
 
979
                                        syslog(LOG_ERR, "cannot allocate memory for request");
 
980
                                        close(s);
 
981
                                }
 
982
                                else
 
983
                                {
 
984
                                        tmp->socket = s;
 
985
                                        LIST_INSERT_HEAD(&reqlisthead, tmp, entries);
 
986
                                }
798
987
                        }
799
988
                }
800
989
        }
 
990
 
801
991
        /* closing and cleaning everything */
802
 
        close(s_ssdp);
803
 
        close(s_unix);
 
992
quit:
 
993
        if(s_ssdp >= 0) {
 
994
                close(s_ssdp);
 
995
                s_ssdp = -1;
 
996
        }
 
997
#ifdef ENABLE_IPV6
 
998
        if(s_ssdp6 >= 0) {
 
999
                close(s_ssdp6);
 
1000
                s_ssdp6 = -1;
 
1001
        }
 
1002
#endif
 
1003
        if(s_unix >= 0) {
 
1004
                close(s_unix);
 
1005
                s_unix = -1;
 
1006
        }
804
1007
        if(unlink(sockpath) < 0)
805
1008
                syslog(LOG_ERR, "unlink(%s): %m", sockpath);
806
1009
        if(unlink(pidfilename) < 0)
807
1010
                syslog(LOG_ERR, "unlink(%s): %m", pidfilename);
808
1011
        closelog();
809
 
        return 0;
 
1012
        return ret;
810
1013
}
811
1014