Annotation of embedaddon/miniupnpd/minissdp.c, revision 1.1

1.1     ! misho       1: /* $Id: minissdp.c,v 1.19 2010/09/21 15:31:02 nanard Exp $ */
        !             2: /* MiniUPnP project
        !             3:  * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
        !             4:  * (c) 2006-2010 Thomas Bernard
        !             5:  * This software is subject to the conditions detailed
        !             6:  * in the LICENCE file provided within the distribution */
        !             7: 
        !             8: #include <stdio.h>
        !             9: #include <string.h>
        !            10: #include <unistd.h>
        !            11: #include <sys/socket.h>
        !            12: #include <sys/un.h>
        !            13: #include <netinet/in.h>
        !            14: #include <arpa/inet.h>
        !            15: #include <syslog.h>
        !            16: #include "config.h"
        !            17: #include "upnpdescstrings.h"
        !            18: #include "miniupnpdpath.h"
        !            19: #include "upnphttp.h"
        !            20: #include "upnpglobalvars.h"
        !            21: #include "minissdp.h"
        !            22: #include "codelength.h"
        !            23: 
        !            24: /* SSDP ip/port */
        !            25: #define SSDP_PORT (1900)
        !            26: /* Prototypes */
        !            27: void ProcessSSDPData(int s, char *bufr, struct sockaddr_in sendername, int n, unsigned short port) ;
        !            28: 
        !            29: 
        !            30: #define SSDP_MCAST_ADDR ("239.255.255.250")
        !            31: 
        !            32: static int
        !            33: AddMulticastMembership(int s, in_addr_t ifaddr)
        !            34: {
        !            35:        struct ip_mreq imr;     /* Ip multicast membership */
        !            36: 
        !            37:     /* setting up imr structure */
        !            38:     imr.imr_multiaddr.s_addr = inet_addr(SSDP_MCAST_ADDR);
        !            39:     /*imr.imr_interface.s_addr = htonl(INADDR_ANY);*/
        !            40:     imr.imr_interface.s_addr = ifaddr; /*inet_addr(ifaddr);*/
        !            41:        
        !            42:        if (setsockopt(s, IPPROTO_IP, IP_ADD_MEMBERSHIP, (void *)&imr, sizeof(struct ip_mreq)) < 0)
        !            43:        {
        !            44:         syslog(LOG_ERR, "setsockopt(udp, IP_ADD_MEMBERSHIP): %m");
        !            45:                return -1;
        !            46:     }
        !            47: 
        !            48:        return 0;
        !            49: }
        !            50: 
        !            51: /* Open and configure the socket listening for 
        !            52:  * SSDP udp packets sent on 239.255.255.250 port 1900 */
        !            53: int
        !            54: OpenAndConfSSDPReceiveSocket()
        !            55: {
        !            56:        int s;
        !            57:        int i;
        !            58:        int j = 1;
        !            59:        struct sockaddr_in sockname;
        !            60:        
        !            61:        if( (s = socket(PF_INET, SOCK_DGRAM, 0)) < 0)
        !            62:        {
        !            63:                syslog(LOG_ERR, "socket(udp): %m");
        !            64:                return -1;
        !            65:        }       
        !            66:        
        !            67:        memset(&sockname, 0, sizeof(struct sockaddr_in));
        !            68:     sockname.sin_family = AF_INET;
        !            69:     sockname.sin_port = htons(SSDP_PORT);
        !            70:        /* NOTE : it seems it doesnt work when binding on the specific address */
        !            71:     /*sockname.sin_addr.s_addr = inet_addr(UPNP_MCAST_ADDR);*/
        !            72:     sockname.sin_addr.s_addr = htonl(INADDR_ANY);
        !            73:     /*sockname.sin_addr.s_addr = inet_addr(ifaddr);*/
        !            74: 
        !            75:        if(setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &j, sizeof(j)) < 0)
        !            76:        {
        !            77:                syslog(LOG_WARNING, "setsockopt(udp, SO_REUSEADDR): %m");
        !            78:        }
        !            79: 
        !            80: 
        !            81:     if(bind(s, (struct sockaddr *)&sockname, sizeof(struct sockaddr_in)) < 0)
        !            82:        {
        !            83:                syslog(LOG_ERR, "bind(udp): %m");
        !            84:                close(s);
        !            85:                return -1;
        !            86:     }
        !            87: 
        !            88:        i = n_lan_addr;
        !            89:        while(i>0)
        !            90:        {
        !            91:                i--;
        !            92:                if(AddMulticastMembership(s, lan_addr[i].addr.s_addr) < 0)
        !            93:                {
        !            94:                        syslog(LOG_WARNING,
        !            95:                               "Failed to add multicast membership for address %s", 
        !            96:                               lan_addr[i].str );
        !            97:                }
        !            98:        }
        !            99: 
        !           100:        return s;
        !           101: }
        !           102: 
        !           103: /* open the UDP socket used to send SSDP notifications to
        !           104:  * the multicast group reserved for them */
        !           105: static int
        !           106: OpenAndConfSSDPNotifySocket(in_addr_t addr)
        !           107: {
        !           108:        int s;
        !           109:        unsigned char loopchar = 0;
        !           110:        int bcast = 1;
        !           111:        struct in_addr mc_if;
        !           112:        struct sockaddr_in sockname;
        !           113:        
        !           114:        if( (s = socket(PF_INET, SOCK_DGRAM, 0)) < 0)
        !           115:        {
        !           116:                syslog(LOG_ERR, "socket(udp_notify): %m");
        !           117:                return -1;
        !           118:        }
        !           119: 
        !           120:        mc_if.s_addr = addr;    /*inet_addr(addr);*/
        !           121: 
        !           122:        if(setsockopt(s, IPPROTO_IP, IP_MULTICAST_LOOP, (char *)&loopchar, sizeof(loopchar)) < 0)
        !           123:        {
        !           124:                syslog(LOG_ERR, "setsockopt(udp_notify, IP_MULTICAST_LOOP): %m");
        !           125:                close(s);
        !           126:                return -1;
        !           127:        }
        !           128: 
        !           129:        if(setsockopt(s, IPPROTO_IP, IP_MULTICAST_IF, (char *)&mc_if, sizeof(mc_if)) < 0)
        !           130:        {
        !           131:                syslog(LOG_ERR, "setsockopt(udp_notify, IP_MULTICAST_IF): %m");
        !           132:                close(s);
        !           133:                return -1;
        !           134:        }
        !           135:        
        !           136:        if(setsockopt(s, SOL_SOCKET, SO_BROADCAST, &bcast, sizeof(bcast)) < 0)
        !           137:        {
        !           138:                syslog(LOG_ERR, "setsockopt(udp_notify, SO_BROADCAST): %m");
        !           139:                close(s);
        !           140:                return -1;
        !           141:        }
        !           142: 
        !           143:        memset(&sockname, 0, sizeof(struct sockaddr_in));
        !           144:     sockname.sin_family = AF_INET;
        !           145:     sockname.sin_addr.s_addr = addr;   /*inet_addr(addr);*/
        !           146: 
        !           147:     if (bind(s, (struct sockaddr *)&sockname, sizeof(struct sockaddr_in)) < 0)
        !           148:        {
        !           149:                syslog(LOG_ERR, "bind(udp_notify): %m");
        !           150:                close(s);
        !           151:                return -1;
        !           152:     }
        !           153: 
        !           154:        return s;
        !           155: }
        !           156: 
        !           157: int
        !           158: OpenAndConfSSDPNotifySockets(int * sockets)
        !           159: /*OpenAndConfSSDPNotifySockets(int * sockets,
        !           160:                              struct lan_addr_s * lan_addr, int n_lan_addr)*/
        !           161: {
        !           162:        int i, j;
        !           163:        for(i=0; i<n_lan_addr; i++)
        !           164:        {
        !           165:                sockets[i] = OpenAndConfSSDPNotifySocket(lan_addr[i].addr.s_addr);
        !           166:                if(sockets[i] < 0)
        !           167:                {
        !           168:                        for(j=0; j<i; j++)
        !           169:                        {
        !           170:                                close(sockets[j]);
        !           171:                                sockets[j] = -1;
        !           172:                        }
        !           173:                        return -1;
        !           174:                }
        !           175:        }
        !           176:        return 0;
        !           177: }
        !           178: 
        !           179: /*
        !           180:  * response from a LiveBox (Wanadoo)
        !           181: HTTP/1.1 200 OK
        !           182: CACHE-CONTROL: max-age=1800
        !           183: DATE: Thu, 01 Jan 1970 04:03:23 GMT
        !           184: EXT:
        !           185: LOCATION: http://192.168.0.1:49152/gatedesc.xml
        !           186: SERVER: Linux/2.4.17, UPnP/1.0, Intel SDK for UPnP devices /1.2
        !           187: ST: upnp:rootdevice
        !           188: USN: uuid:75802409-bccb-40e7-8e6c-fa095ecce13e::upnp:rootdevice
        !           189: 
        !           190:  * response from a Linksys 802.11b :
        !           191: HTTP/1.1 200 OK
        !           192: Cache-Control:max-age=120
        !           193: Location:http://192.168.5.1:5678/rootDesc.xml
        !           194: Server:NT/5.0 UPnP/1.0
        !           195: ST:upnp:rootdevice
        !           196: USN:uuid:upnp-InternetGatewayDevice-1_0-0090a2777777::upnp:rootdevice
        !           197: EXT:
        !           198:  */
        !           199: 
        !           200: /* not really an SSDP "announce" as it is the response
        !           201:  * to a SSDP "M-SEARCH" */
        !           202: static void
        !           203: SendSSDPAnnounce2(int s, struct sockaddr_in sockname,
        !           204:                   const char * st, int st_len, const char * suffix,
        !           205:                   const char * host, unsigned short port)
        !           206: {
        !           207:        int l, n;
        !           208:        char buf[512];
        !           209:        /* 
        !           210:         * follow guideline from document "UPnP Device Architecture 1.0"
        !           211:         * uppercase is recommended.
        !           212:         * DATE: is recommended
        !           213:         * SERVER: OS/ver UPnP/1.0 miniupnpd/1.0
        !           214:         * - check what to put in the 'Cache-Control' header 
        !           215:         * */
        !           216:        l = snprintf(buf, sizeof(buf), "HTTP/1.1 200 OK\r\n"
        !           217:                "CACHE-CONTROL: max-age=120\r\n"
        !           218:                /*"DATE: ...\r\n"*/
        !           219:                "ST: %.*s%s\r\n"
        !           220:                "USN: %s::%.*s%s\r\n"
        !           221:                "EXT:\r\n"
        !           222:                "SERVER: " MINIUPNPD_SERVER_STRING "\r\n"
        !           223:                "LOCATION: http://%s:%u" ROOTDESC_PATH "\r\n"
        !           224:                "\r\n",
        !           225:                st_len, st, suffix,
        !           226:                uuidvalue, st_len, st, suffix,
        !           227:                host, (unsigned int)port);
        !           228:        n = sendto(s, buf, l, 0,
        !           229:                   (struct sockaddr *)&sockname, sizeof(struct sockaddr_in) );
        !           230:        syslog(LOG_INFO, "SSDP Announce %d bytes to %s:%d ST: %.*s",n,
        !           231:                        inet_ntoa(sockname.sin_addr),
        !           232:                ntohs(sockname.sin_port),
        !           233:                l, buf);
        !           234:        if(n < 0)
        !           235:        {
        !           236:                syslog(LOG_ERR, "sendto(udp): %m");
        !           237:        }
        !           238: }
        !           239: 
        !           240: static const char * const known_service_types[] =
        !           241: {
        !           242:        "upnp:rootdevice",
        !           243:        "urn:schemas-upnp-org:device:InternetGatewayDevice:",
        !           244:        "urn:schemas-upnp-org:device:WANConnectionDevice:",
        !           245:        "urn:schemas-upnp-org:device:WANDevice:",
        !           246:        "urn:schemas-upnp-org:service:WANCommonInterfaceConfig:",
        !           247:        "urn:schemas-upnp-org:service:WANIPConnection:",
        !           248:        "urn:schemas-upnp-org:service:WANPPPConnection:",
        !           249:        "urn:schemas-upnp-org:service:Layer3Forwarding:",
        !           250:        0
        !           251: };
        !           252: 
        !           253: static void
        !           254: SendSSDPNotifies(int s, const char * host, unsigned short port,
        !           255:                  unsigned int lifetime)
        !           256: {
        !           257:        struct sockaddr_in sockname;
        !           258:        int l, n, i=0;
        !           259:        char bufr[512];
        !           260: 
        !           261:        memset(&sockname, 0, sizeof(struct sockaddr_in));
        !           262:        sockname.sin_family = AF_INET;
        !           263:        sockname.sin_port = htons(SSDP_PORT);
        !           264:        sockname.sin_addr.s_addr = inet_addr(SSDP_MCAST_ADDR);
        !           265: 
        !           266:        while(known_service_types[i])
        !           267:        {
        !           268:                l = snprintf(bufr, sizeof(bufr), 
        !           269:                                "NOTIFY * HTTP/1.1\r\n"
        !           270:                                "HOST:%s:%d\r\n"
        !           271:                                "Cache-Control:max-age=%u\r\n"
        !           272:                                "Location:http://%s:%d" ROOTDESC_PATH"\r\n"
        !           273:                                /*"Server:miniupnpd/1.0 UPnP/1.0\r\n"*/
        !           274:                                "Server: " MINIUPNPD_SERVER_STRING "\r\n"
        !           275:                                "NT:%s%s\r\n"
        !           276:                                "USN:%s::%s%s\r\n"
        !           277:                                "NTS:ssdp:alive\r\n"
        !           278:                                "\r\n",
        !           279:                                SSDP_MCAST_ADDR, SSDP_PORT,
        !           280:                                lifetime,
        !           281:                                host, port,
        !           282:                                known_service_types[i], (i==0?"":"1"),
        !           283:                                uuidvalue, known_service_types[i], (i==0?"":"1") );
        !           284:                if(l>=sizeof(bufr))
        !           285:                {
        !           286:                        syslog(LOG_WARNING, "SendSSDPNotifies(): truncated output");
        !           287:                        l = sizeof(bufr);
        !           288:                }
        !           289:                n = sendto(s, bufr, l, 0,
        !           290:                        (struct sockaddr *)&sockname, sizeof(struct sockaddr_in) );
        !           291:                if(n < 0)
        !           292:                {
        !           293:                        syslog(LOG_ERR, "sendto(udp_notify=%d, %s): %m", s, host);
        !           294:                }
        !           295:                i++;
        !           296:        }
        !           297: }
        !           298: 
        !           299: void
        !           300: SendSSDPNotifies2(int * sockets,
        !           301:                   unsigned short port,
        !           302:                   unsigned int lifetime)
        !           303: /*SendSSDPNotifies2(int * sockets, struct lan_addr_s * lan_addr, int n_lan_addr,
        !           304:                   unsigned short port,
        !           305:                   unsigned int lifetime)*/
        !           306: {
        !           307:        int i;
        !           308:        for(i=0; i<n_lan_addr; i++)
        !           309:        {
        !           310:                SendSSDPNotifies(sockets[i], lan_addr[i].str, port, lifetime);
        !           311:        }
        !           312: }
        !           313: 
        !           314: /* ProcessSSDPRequest()
        !           315:  * process SSDP M-SEARCH requests and responds to them */
        !           316: void
        !           317: ProcessSSDPRequest(int s, unsigned short port)
        !           318: {
        !           319:        int n;
        !           320:        char bufr[1500];
        !           321:        socklen_t len_r;
        !           322:        struct sockaddr_in sendername;
        !           323:        len_r = sizeof(struct sockaddr_in);
        !           324: 
        !           325:        n = recvfrom(s, bufr, sizeof(bufr), 0,
        !           326:                     (struct sockaddr *)&sendername, &len_r);
        !           327:        if(n < 0)
        !           328:        {
        !           329:                syslog(LOG_ERR, "recvfrom(udp): %m");
        !           330:                return;
        !           331:        }
        !           332:        ProcessSSDPData(s, bufr, sendername, n, port);
        !           333: 
        !           334: }
        !           335: 
        !           336: void ProcessSSDPData(int s, char *bufr, struct sockaddr_in sendername, int n, unsigned short port) {
        !           337:        int i, l;
        !           338:        int lan_addr_index = 0;
        !           339:        char * st = 0;
        !           340:        int st_len = 0;
        !           341: 
        !           342: 
        !           343:        if(memcmp(bufr, "NOTIFY", 6) == 0)
        !           344:        {
        !           345:                /* ignore NOTIFY packets. We could log the sender and device type */
        !           346:                return;
        !           347:        }
        !           348:        else if(memcmp(bufr, "M-SEARCH", 8) == 0)
        !           349:        {
        !           350:                i = 0;
        !           351:                while(i < n)
        !           352:                {
        !           353:                        while((i < n - 1) && (bufr[i] != '\r' || bufr[i+1] != '\n'))
        !           354:                                i++;
        !           355:                        i += 2;
        !           356:                        if((i < n - 3) && (strncasecmp(bufr+i, "st:", 3) == 0))
        !           357:                        {
        !           358:                                st = bufr+i+3;
        !           359:                                st_len = 0;
        !           360:                                while((*st == ' ' || *st == '\t') && (st < bufr + n))
        !           361:                                        st++;
        !           362:                                while(st[st_len]!='\r' && st[st_len]!='\n'
        !           363:                                     && (st + st_len < bufr + n))
        !           364:                                        st_len++;
        !           365:                                /*syslog(LOG_INFO, "ST: %.*s", st_len, st);*/
        !           366:                                /*j = 0;*/
        !           367:                                /*while(bufr[i+j]!='\r') j++;*/
        !           368:                                /*syslog(LOG_INFO, "%.*s", j, bufr+i);*/
        !           369:                        }
        !           370:                }
        !           371:                /*syslog(LOG_INFO, "SSDP M-SEARCH packet received from %s:%d",
        !           372:                   inet_ntoa(sendername.sin_addr),
        !           373:                   ntohs(sendername.sin_port) );*/
        !           374:                if(st && (st_len > 0))
        !           375:                {
        !           376:                        /* TODO : doesnt answer at once but wait for a random time */
        !           377:                        syslog(LOG_INFO, "SSDP M-SEARCH from %s:%d ST: %.*s",
        !           378:                           inet_ntoa(sendername.sin_addr),
        !           379:                           ntohs(sendername.sin_port),
        !           380:                                   st_len, st);
        !           381:                        /* find in which sub network the client is */
        !           382:                        for(i = 0; i<n_lan_addr; i++)
        !           383:                        {
        !           384:                                if( (sendername.sin_addr.s_addr & lan_addr[i].mask.s_addr)
        !           385:                                   == (lan_addr[i].addr.s_addr & lan_addr[i].mask.s_addr))
        !           386:                                {
        !           387:                                        lan_addr_index = i;
        !           388:                                        break;
        !           389:                                }
        !           390:                        }
        !           391:                        /* Responds to request with a device as ST header */
        !           392:                        for(i = 0; known_service_types[i]; i++)
        !           393:                        {
        !           394:                                l = (int)strlen(known_service_types[i]);
        !           395:                                if(l<=st_len && (0 == memcmp(st, known_service_types[i], l)))
        !           396:                                {
        !           397:                                        syslog(LOG_INFO, "Single search found");
        !           398:                                        SendSSDPAnnounce2(s, sendername,
        !           399:                                                          st, st_len, "",
        !           400:                                                          lan_addr[lan_addr_index].str, port);
        !           401:                                        break;
        !           402:                                }
        !           403:                        }
        !           404:                        /* Responds to request with ST: ssdp:all */
        !           405:                        /* strlen("ssdp:all") == 8 */
        !           406:                        if(st_len==8 && (0 == memcmp(st, "ssdp:all", 8)))
        !           407:                        {
        !           408:                                syslog(LOG_INFO, "ssdp:all found");
        !           409:                                for(i=0; known_service_types[i]; i++)
        !           410:                                {
        !           411:                                        l = (int)strlen(known_service_types[i]);
        !           412:                                        SendSSDPAnnounce2(s, sendername,
        !           413:                                                          known_service_types[i], l, i==0?"":"1",
        !           414:                                                          lan_addr[lan_addr_index].str, port);
        !           415:                                }
        !           416:                        }
        !           417:                        /* responds to request by UUID value */
        !           418:                        l = (int)strlen(uuidvalue);
        !           419:                        if(l==st_len && (0 == memcmp(st, uuidvalue, l)))
        !           420:                        {
        !           421:                                syslog(LOG_INFO, "ssdp:uuid found");
        !           422:                                SendSSDPAnnounce2(s, sendername, st, st_len, "",
        !           423:                                                  lan_addr[lan_addr_index].str, port);
        !           424:                        }
        !           425:                }
        !           426:                else
        !           427:                {
        !           428:                        syslog(LOG_INFO, "Invalid SSDP M-SEARCH from %s:%d",
        !           429:                           inet_ntoa(sendername.sin_addr), ntohs(sendername.sin_port));
        !           430:                }
        !           431:        }
        !           432:        else
        !           433:        {
        !           434:                syslog(LOG_NOTICE, "Unknown udp packet received from %s:%d",
        !           435:                       inet_ntoa(sendername.sin_addr), ntohs(sendername.sin_port));
        !           436:        }
        !           437: }
        !           438: 
        !           439: /* This will broadcast ssdp:byebye notifications to inform 
        !           440:  * the network that UPnP is going down. */
        !           441: int
        !           442: SendSSDPGoodbye(int * sockets, int n_sockets)
        !           443: {
        !           444:        struct sockaddr_in sockname;
        !           445:        int n, l;
        !           446:        int i, j;
        !           447:        char bufr[512];
        !           448: 
        !           449:     memset(&sockname, 0, sizeof(struct sockaddr_in));
        !           450:     sockname.sin_family = AF_INET;
        !           451:     sockname.sin_port = htons(SSDP_PORT);
        !           452:     sockname.sin_addr.s_addr = inet_addr(SSDP_MCAST_ADDR);
        !           453: 
        !           454:        for(j=0; j<n_sockets; j++)
        !           455:        {
        !           456:            for(i=0; known_service_types[i]; i++)
        !           457:            {
        !           458:                l = snprintf(bufr, sizeof(bufr),
        !           459:                         "NOTIFY * HTTP/1.1\r\n"
        !           460:                         "HOST:%s:%d\r\n"
        !           461:                         "NT:%s%s\r\n"
        !           462:                         "USN:%s::%s%s\r\n"
        !           463:                         "NTS:ssdp:byebye\r\n"
        !           464:                         "\r\n",
        !           465:                         SSDP_MCAST_ADDR, SSDP_PORT,
        !           466:                                         known_service_types[i], (i==0?"":"1"),
        !           467:                         uuidvalue, known_service_types[i], (i==0?"":"1"));
        !           468:                n = sendto(sockets[j], bufr, l, 0,
        !           469:                           (struct sockaddr *)&sockname, sizeof(struct sockaddr_in) );
        !           470:                        if(n < 0)
        !           471:                        {
        !           472:                                syslog(LOG_ERR, "SendSSDPGoodbye: sendto(udp_shutdown=%d): %m",
        !           473:                                       sockets[j]);
        !           474:                                return -1;
        !           475:                        }
        !           476:        }
        !           477:        }
        !           478:        return 0;
        !           479: }
        !           480: 
        !           481: /* SubmitServicesToMiniSSDPD() :
        !           482:  * register services offered by MiniUPnPd to a running instance of
        !           483:  * MiniSSDPd */
        !           484: int
        !           485: SubmitServicesToMiniSSDPD(const char * host, unsigned short port) {
        !           486:        struct sockaddr_un addr;
        !           487:        int s;
        !           488:        unsigned char buffer[2048];
        !           489:        char strbuf[256];
        !           490:        unsigned char * p;
        !           491:        int i, l;
        !           492: 
        !           493:        s = socket(AF_UNIX, SOCK_STREAM, 0);
        !           494:        if(s < 0) {
        !           495:                syslog(LOG_ERR, "socket(unix): %m");
        !           496:                return -1;
        !           497:        }
        !           498:        addr.sun_family = AF_UNIX;
        !           499:        strncpy(addr.sun_path, minissdpdsocketpath, sizeof(addr.sun_path));
        !           500:        if(connect(s, (struct sockaddr *)&addr, sizeof(struct sockaddr_un)) < 0) {
        !           501:                syslog(LOG_ERR, "connect(\"%s\"): %m", minissdpdsocketpath);
        !           502:                return -1;
        !           503:        }
        !           504:        for(i = 0; known_service_types[i]; i++) {
        !           505:                buffer[0] = 4;
        !           506:                p = buffer + 1;
        !           507:                l = (int)strlen(known_service_types[i]);
        !           508:                if(i > 0)
        !           509:                        l++;
        !           510:                CODELENGTH(l, p);
        !           511:                memcpy(p, known_service_types[i], l);
        !           512:                if(i > 0)
        !           513:                        p[l-1] = '1';
        !           514:                p += l;
        !           515:                l = snprintf(strbuf, sizeof(strbuf), "%s::%s%s", 
        !           516:                             uuidvalue, known_service_types[i], (i==0)?"":"1");
        !           517:                CODELENGTH(l, p);
        !           518:                memcpy(p, strbuf, l);
        !           519:                p += l;
        !           520:                l = (int)strlen(MINIUPNPD_SERVER_STRING);
        !           521:                CODELENGTH(l, p);
        !           522:                memcpy(p, MINIUPNPD_SERVER_STRING, l);
        !           523:                p += l;
        !           524:                l = snprintf(strbuf, sizeof(strbuf), "http://%s:%u" ROOTDESC_PATH,
        !           525:                             host, (unsigned int)port);
        !           526:                CODELENGTH(l, p);
        !           527:                memcpy(p, strbuf, l);
        !           528:                p += l;
        !           529:                if(write(s, buffer, p - buffer) < 0) {
        !           530:                        syslog(LOG_ERR, "write(): %m");
        !           531:                        return -1;
        !           532:                }
        !           533:        }
        !           534:        close(s);
        !           535:        return 0;
        !           536: }
        !           537: 

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