Diff for /embedaddon/miniupnpd/minissdp.c between versions 1.1 and 1.1.1.2

version 1.1, 2012/02/21 23:16:02 version 1.1.1.2, 2012/05/29 12:55:57
Line 1 Line 1
 /* $Id$ */  /* $Id$ */
 /* MiniUPnP project  /* MiniUPnP project
  * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/   * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
 * (c) 2006-2010 Thomas Bernard * (c) 2006-2011 Thomas Bernard
  * This software is subject to the conditions detailed   * This software is subject to the conditions detailed
  * in the LICENCE file provided within the distribution */   * in the LICENCE file provided within the distribution */
   
Line 19 Line 19
 #include "upnphttp.h"  #include "upnphttp.h"
 #include "upnpglobalvars.h"  #include "upnpglobalvars.h"
 #include "minissdp.h"  #include "minissdp.h"
   #include "upnputils.h"
 #include "codelength.h"  #include "codelength.h"
   
 /* SSDP ip/port */  /* SSDP ip/port */
 #define SSDP_PORT (1900)  #define SSDP_PORT (1900)
 /* Prototypes */  
 void ProcessSSDPData(int s, char *bufr, struct sockaddr_in sendername, int n, unsigned short port) ;  
   
   
 #define SSDP_MCAST_ADDR ("239.255.255.250")  #define SSDP_MCAST_ADDR ("239.255.255.250")
   #define LL_SSDP_MCAST_ADDR ("FF02::C")
   #define SL_SSDP_MCAST_ADDR ("FF05::C")
   
   /* AddMulticastMembership()
    * param s              socket
    * param ifaddr ip v4 address
    */
 static int  static int
 AddMulticastMembership(int s, in_addr_t ifaddr)  AddMulticastMembership(int s, in_addr_t ifaddr)
 {  {
Line 48  AddMulticastMembership(int s, in_addr_t ifaddr) Line 51  AddMulticastMembership(int s, in_addr_t ifaddr)
         return 0;          return 0;
 }  }
   
   /* AddMulticastMembershipIPv6()
    * param s      socket (IPv6)
    * To be improved to target specific network interfaces */
   #ifdef ENABLE_IPV6
   static int
   AddMulticastMembershipIPv6(int s)
   {
           struct ipv6_mreq mr;
           /*unsigned int ifindex;*/
   
           memset(&mr, 0, sizeof(mr));
           inet_pton(AF_INET6, LL_SSDP_MCAST_ADDR, &mr.ipv6mr_multiaddr);
           /*mr.ipv6mr_interface = ifindex;*/
           mr.ipv6mr_interface = 0; /* 0 : all interfaces */
   #ifndef IPV6_ADD_MEMBERSHIP
   #define IPV6_ADD_MEMBERSHIP IPV6_JOIN_GROUP
   #endif
           if(setsockopt(s, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, &mr, sizeof(struct ipv6_mreq)) < 0)
           {
                   syslog(LOG_ERR, "setsockopt(udp, IPV6_ADD_MEMBERSHIP): %m");
                   return -1;
           }
           inet_pton(AF_INET6, SL_SSDP_MCAST_ADDR, &mr.ipv6mr_multiaddr);
           if(setsockopt(s, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, &mr, sizeof(struct ipv6_mreq)) < 0)
           {
                   syslog(LOG_ERR, "setsockopt(udp, IPV6_ADD_MEMBERSHIP): %m");
                   return -1;
           }
           return 0;
   }
   #endif
   
 /* Open and configure the socket listening for   /* Open and configure the socket listening for 
 * SSDP udp packets sent on 239.255.255.250 port 1900 */ * SSDP udp packets sent on 239.255.255.250 port 1900
  * SSDP v6 udp packets sent on FF02::C, or FF05::C, port 1900 */
 int  int
OpenAndConfSSDPReceiveSocket()OpenAndConfSSDPReceiveSocket(int ipv6)
 {  {
         int s;          int s;
        int i;        struct sockaddr_storage sockname;
         socklen_t sockname_len;
         struct lan_addr_s * lan_addr;
         int j = 1;          int j = 1;
        struct sockaddr_in sockname;
                if( (s = socket(ipv6 ? PF_INET6 : PF_INET, SOCK_DGRAM, 0)) < 0)
        if( (s = socket(PF_INET, SOCK_DGRAM, 0)) < 0) 
         {          {
                 syslog(LOG_ERR, "socket(udp): %m");                  syslog(LOG_ERR, "socket(udp): %m");
                 return -1;                  return -1;
        }               }
         
        memset(&sockname, 0, sizeof(struct sockaddr_in)); 
    sockname.sin_family = AF_INET; 
    sockname.sin_port = htons(SSDP_PORT); 
        /* NOTE : it seems it doesnt work when binding on the specific address */ 
    /*sockname.sin_addr.s_addr = inet_addr(UPNP_MCAST_ADDR);*/ 
    sockname.sin_addr.s_addr = htonl(INADDR_ANY); 
    /*sockname.sin_addr.s_addr = inet_addr(ifaddr);*/ 
   
           memset(&sockname, 0, sizeof(struct sockaddr_storage));
           if(ipv6) {
                   struct sockaddr_in6 * saddr = (struct sockaddr_in6 *)&sockname;
                   saddr->sin6_family = AF_INET6;
                   saddr->sin6_port = htons(SSDP_PORT);
                   saddr->sin6_addr = in6addr_any;
                   sockname_len = sizeof(struct sockaddr_in6);
           } else {
                   struct sockaddr_in * saddr = (struct sockaddr_in *)&sockname;
                   saddr->sin_family = AF_INET;
                   saddr->sin_port = htons(SSDP_PORT);
                   /* NOTE : it seems it doesnt work when binding on the specific address */
                   /*saddr->sin_addr.s_addr = inet_addr(UPNP_MCAST_ADDR);*/
                   saddr->sin_addr.s_addr = htonl(INADDR_ANY);
                   /*saddr->sin_addr.s_addr = inet_addr(ifaddr);*/
                   sockname_len = sizeof(struct sockaddr_in);
           }
   
         if(setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &j, sizeof(j)) < 0)          if(setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &j, sizeof(j)) < 0)
         {          {
                 syslog(LOG_WARNING, "setsockopt(udp, SO_REUSEADDR): %m");                  syslog(LOG_WARNING, "setsockopt(udp, SO_REUSEADDR): %m");
         }          }
   
   
    if(bind(s, (struct sockaddr *)&sockname, sizeof(struct sockaddr_in)) < 0)        if(bind(s, (struct sockaddr *)&sockname, sockname_len) < 0)
         {          {
                syslog(LOG_ERR, "bind(udp): %m");                syslog(LOG_ERR, "bind(udp%s): %m", ipv6 ? "6" : "");
                 close(s);                  close(s);
                 return -1;                  return -1;
    }        }
   
        i = n_lan_addr;#ifdef ENABLE_IPV6
        while(i>0)        if(ipv6)
         {          {
                i--;                AddMulticastMembershipIPv6(s);
                if(AddMulticastMembership(s, lan_addr[i].addr.s_addr) < 0)        }
         else
 #endif
         {
                 for(lan_addr = lan_addrs.lh_first; lan_addr != NULL; lan_addr = lan_addr->list.le_next)
                 {                  {
                        syslog(LOG_WARNING,                        if(AddMulticastMembership(s, lan_addr->addr.s_addr) < 0)
                               "Failed to add multicast membership for address %s",                         {
                               lan_addr[i].str );                                syslog(LOG_WARNING,
                                        "Failed to add multicast membership for interface %s", 
                                        lan_addr->str);
                         }
                 }                  }
         }          }
   
Line 160  OpenAndConfSSDPNotifySockets(int * sockets) Line 214  OpenAndConfSSDPNotifySockets(int * sockets)
                              struct lan_addr_s * lan_addr, int n_lan_addr)*/                               struct lan_addr_s * lan_addr, int n_lan_addr)*/
 {  {
         int i, j;          int i, j;
        for(i=0; i<n_lan_addr; i++)        struct lan_addr_s * lan_addr;
 
         for(i=0, lan_addr = lan_addrs.lh_first; lan_addr != NULL; lan_addr = lan_addr->list.le_next, i++)
         {          {
                sockets[i] = OpenAndConfSSDPNotifySocket(lan_addr[i].addr.s_addr);                sockets[i] = OpenAndConfSSDPNotifySocket(lan_addr->addr.s_addr);
                 if(sockets[i] < 0)                  if(sockets[i] < 0)
                 {                  {
                         for(j=0; j<i; j++)                          for(j=0; j<i; j++)
Line 200  EXT: Line 256  EXT:
 /* not really an SSDP "announce" as it is the response  /* not really an SSDP "announce" as it is the response
  * to a SSDP "M-SEARCH" */   * to a SSDP "M-SEARCH" */
 static void  static void
SendSSDPAnnounce2(int s, struct sockaddr_in sockname,SendSSDPAnnounce2(int s, const struct sockaddr * addr,
                   const char * st, int st_len, const char * suffix,                    const char * st, int st_len, const char * suffix,
                   const char * host, unsigned short port)                    const char * host, unsigned short port)
 {  {
         int l, n;          int l, n;
         char buf[512];          char buf[512];
           socklen_t addrlen;
         /*           /* 
          * follow guideline from document "UPnP Device Architecture 1.0"           * follow guideline from document "UPnP Device Architecture 1.0"
          * uppercase is recommended.           * uppercase is recommended.
          * DATE: is recommended           * DATE: is recommended
          * SERVER: OS/ver UPnP/1.0 miniupnpd/1.0           * SERVER: OS/ver UPnP/1.0 miniupnpd/1.0
          * - check what to put in the 'Cache-Control' header            * - check what to put in the 'Cache-Control' header 
         * */         *
          * have a look at the document "UPnP Device Architecture v1.1 */
         l = snprintf(buf, sizeof(buf), "HTTP/1.1 200 OK\r\n"          l = snprintf(buf, sizeof(buf), "HTTP/1.1 200 OK\r\n"
                 "CACHE-CONTROL: max-age=120\r\n"                  "CACHE-CONTROL: max-age=120\r\n"
                 /*"DATE: ...\r\n"*/                  /*"DATE: ...\r\n"*/
Line 221  SendSSDPAnnounce2(int s, struct sockaddr_in sockname, Line 279  SendSSDPAnnounce2(int s, struct sockaddr_in sockname,
                 "EXT:\r\n"                  "EXT:\r\n"
                 "SERVER: " MINIUPNPD_SERVER_STRING "\r\n"                  "SERVER: " MINIUPNPD_SERVER_STRING "\r\n"
                 "LOCATION: http://%s:%u" ROOTDESC_PATH "\r\n"                  "LOCATION: http://%s:%u" ROOTDESC_PATH "\r\n"
                   "OPT: \"http://schemas.upnp.org/upnp/1/0/\";\r\n" /* UDA v1.1 */
                   "01-NLS: %u\r\n" /* same as BOOTID. UDA v1.1 */
                   "BOOTID.UPNP.ORG: %u\r\n" /* UDA v1.1 */
                   "CONFIGID.UPNP.ORG: %u\r\n" /* UDA v1.1 */
                 "\r\n",                  "\r\n",
                 st_len, st, suffix,                  st_len, st, suffix,
                 uuidvalue, st_len, st, suffix,                  uuidvalue, st_len, st, suffix,
                host, (unsigned int)port);                host, (unsigned int)port,
                 upnp_bootid, upnp_bootid, upnp_configid);
         addrlen = (addr->sa_family == AF_INET6)
                   ? sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in);
         n = sendto(s, buf, l, 0,          n = sendto(s, buf, l, 0,
                   (struct sockaddr *)&sockname, sizeof(struct sockaddr_in) );                   addr, addrlen);
         syslog(LOG_INFO, "SSDP Announce %d bytes to %s:%d ST: %.*s",n,          syslog(LOG_INFO, "SSDP Announce %d bytes to %s:%d ST: %.*s",n,
                inet_ntoa(sockname.sin_addr),                inet_ntoa(((const struct sockaddr_in *)addr)->sin_addr),
                ntohs(sockname.sin_port),                ntohs(((const struct sockaddr_in *)addr)->sin_port),
                 l, buf);                  l, buf);
         if(n < 0)          if(n < 0)
         {          {
Line 246  static const char * const known_service_types[] = Line 311  static const char * const known_service_types[] =
         "urn:schemas-upnp-org:service:WANCommonInterfaceConfig:",          "urn:schemas-upnp-org:service:WANCommonInterfaceConfig:",
         "urn:schemas-upnp-org:service:WANIPConnection:",          "urn:schemas-upnp-org:service:WANIPConnection:",
         "urn:schemas-upnp-org:service:WANPPPConnection:",          "urn:schemas-upnp-org:service:WANPPPConnection:",
   #ifdef ENABLE_L3F_SERVICE
         "urn:schemas-upnp-org:service:Layer3Forwarding:",          "urn:schemas-upnp-org:service:Layer3Forwarding:",
   #endif
   #ifdef ENABLE_6FC_SERVICE
           "url:schemas-upnp-org:service:WANIPv6FirewallControl:",
   #endif
         0          0
 };  };
   
Line 266  SendSSDPNotifies(int s, const char * host, unsigned sh Line 336  SendSSDPNotifies(int s, const char * host, unsigned sh
         while(known_service_types[i])          while(known_service_types[i])
         {          {
                 l = snprintf(bufr, sizeof(bufr),                   l = snprintf(bufr, sizeof(bufr), 
                                "NOTIFY * HTTP/1.1\r\n"                        "NOTIFY * HTTP/1.1\r\n"
                                "HOST:%s:%d\r\n"                        "HOST: %s:%d\r\n"
                                "Cache-Control:max-age=%u\r\n"                        "CACHE-CONTROL: max-age=%u\r\n"
                                "Location:http://%s:%d" ROOTDESC_PATH"\r\n"                        "lOCATION: http://%s:%d" ROOTDESC_PATH"\r\n"
                                /*"Server:miniupnpd/1.0 UPnP/1.0\r\n"*/                        "SERVER: " MINIUPNPD_SERVER_STRING "\r\n"
                                "Server: " MINIUPNPD_SERVER_STRING "\r\n"                        "NT: %s%s\r\n"
                                "NT:%s%s\r\n"                        "USN: %s::%s%s\r\n"
                                "USN:%s::%s%s\r\n"                        "NTS: ssdp:alive\r\n"
                                "NTS:ssdp:alive\r\n"                        "OPT: \"http://schemas.upnp.org/upnp/1/0/\";\r\n" /* UDA v1.1 */
                                "\r\n",                        "01-NLS: %u\r\n" /* same as BOOTID field. UDA v1.1 */
                                SSDP_MCAST_ADDR, SSDP_PORT,                        "BOOTID.UPNP.ORG: %u\r\n" /* UDA v1.1 */
                                lifetime,                        "CONFIGID.UPNP.ORG: %u\r\n" /* UDA v1.1 */
                                host, port,                        "\r\n",
                                known_service_types[i], (i==0?"":"1"),                        SSDP_MCAST_ADDR, SSDP_PORT,
                                uuidvalue, known_service_types[i], (i==0?"":"1") );                        lifetime,
                         host, port,
                         known_service_types[i], (i==0?"":"1"),
                         uuidvalue, known_service_types[i], (i==0?"":"1"),
                         upnp_bootid, upnp_bootid, upnp_configid );
                 if(l>=sizeof(bufr))                  if(l>=sizeof(bufr))
                 {                  {
                         syslog(LOG_WARNING, "SendSSDPNotifies(): truncated output");                          syslog(LOG_WARNING, "SendSSDPNotifies(): truncated output");
Line 300  void Line 374  void
 SendSSDPNotifies2(int * sockets,  SendSSDPNotifies2(int * sockets,
                   unsigned short port,                    unsigned short port,
                   unsigned int lifetime)                    unsigned int lifetime)
 /*SendSSDPNotifies2(int * sockets, struct lan_addr_s * lan_addr, int n_lan_addr,  
                   unsigned short port,  
                   unsigned int lifetime)*/  
 {  {
         int i;          int i;
        for(i=0; i<n_lan_addr; i++)        struct lan_addr_s * lan_addr;
         for(i=0, lan_addr = lan_addrs.lh_first; lan_addr != NULL; lan_addr = lan_addr->list.le_next, i++)
         {          {
                SendSSDPNotifies(sockets[i], lan_addr[i].str, port, lifetime);                SendSSDPNotifies(sockets[i], lan_addr->str, port, lifetime);
         }          }
 }  }
   
Line 319  ProcessSSDPRequest(int s, unsigned short port) Line 391  ProcessSSDPRequest(int s, unsigned short port)
         int n;          int n;
         char bufr[1500];          char bufr[1500];
         socklen_t len_r;          socklen_t len_r;
   #ifdef ENABLE_IPV6
           struct sockaddr_storage sendername;
           len_r = sizeof(struct sockaddr_storage);
   #else
         struct sockaddr_in sendername;          struct sockaddr_in sendername;
         len_r = sizeof(struct sockaddr_in);          len_r = sizeof(struct sockaddr_in);
   #endif
   
         n = recvfrom(s, bufr, sizeof(bufr), 0,          n = recvfrom(s, bufr, sizeof(bufr), 0,
                      (struct sockaddr *)&sendername, &len_r);                       (struct sockaddr *)&sendername, &len_r);
Line 329  ProcessSSDPRequest(int s, unsigned short port) Line 406  ProcessSSDPRequest(int s, unsigned short port)
                 syslog(LOG_ERR, "recvfrom(udp): %m");                  syslog(LOG_ERR, "recvfrom(udp): %m");
                 return;                  return;
         }          }
        ProcessSSDPData(s, bufr, sendername, n, port);        ProcessSSDPData(s, bufr, n, (struct sockaddr *)&sendername, port);
   
 }  }
   
void ProcessSSDPData(int s, char *bufr, struct sockaddr_in sendername, int n, unsigned short port) {void
 ProcessSSDPData(int s, const char *bufr, int n,
                 const struct sockaddr * sender, unsigned short port) {
         int i, l;          int i, l;
        int lan_addr_index = 0;        struct lan_addr_s * lan_addr = NULL;
        char * st = 0;        const char * st = NULL;
         int st_len = 0;          int st_len = 0;
           char sender_str[64];
           const char * announced_host = NULL;
   
           /* get the string representation of the sender address */
           sockaddr_to_string(sender, sender_str, sizeof(sender_str));
   
         if(memcmp(bufr, "NOTIFY", 6) == 0)          if(memcmp(bufr, "NOTIFY", 6) == 0)
         {          {
Line 368  void ProcessSSDPData(int s, char *bufr, struct sockadd Line 451  void ProcessSSDPData(int s, char *bufr, struct sockadd
                                 /*syslog(LOG_INFO, "%.*s", j, bufr+i);*/                                  /*syslog(LOG_INFO, "%.*s", j, bufr+i);*/
                         }                          }
                 }                  }
                /*syslog(LOG_INFO, "SSDP M-SEARCH packet received from %s:%d",                /*syslog(LOG_INFO, "SSDP M-SEARCH packet received from %s",
                   inet_ntoa(sendername.sin_addr),                   sender_str );*/
                   ntohs(sendername.sin_port) );*/ 
                 if(st && (st_len > 0))                  if(st && (st_len > 0))
                 {                  {
                         /* TODO : doesnt answer at once but wait for a random time */                          /* TODO : doesnt answer at once but wait for a random time */
                        syslog(LOG_INFO, "SSDP M-SEARCH from %s:%d ST: %.*s",                        syslog(LOG_INFO, "SSDP M-SEARCH from %s ST: %.*s",
                           inet_ntoa(sendername.sin_addr),                               sender_str, st_len, st);
                           ntohs(sendername.sin_port), 
                                   st_len, st); 
                         /* find in which sub network the client is */                          /* find in which sub network the client is */
                        for(i = 0; i<n_lan_addr; i++)                        if(sender->sa_family == AF_INET)
                         {                          {
                                if( (sendername.sin_addr.s_addr & lan_addr[i].mask.s_addr)                                for(lan_addr = lan_addrs.lh_first;
                                   == (lan_addr[i].addr.s_addr & lan_addr[i].mask.s_addr))                                    lan_addr != NULL;
                                     lan_addr = lan_addr->list.le_next)
                                 {                                  {
                                        lan_addr_index = i;                                        if( (((const struct sockaddr_in *)sender)->sin_addr.s_addr & lan_addr->mask.s_addr)
                                        break;                                   == (lan_addr->addr.s_addr & lan_addr->mask.s_addr))
                                                 break;
                                 }                                  }
                                   if (lan_addr == NULL)
                                   {
                                           syslog(LOG_ERR, "Can't find in which sub network the client is");
                                           return;
                                   }
                                   announced_host = lan_addr->str;
                         }                          }
   #ifdef ENABLE_IPV6
                           else
                           {
                                   /* IPv6 address with brackets */
                                   announced_host = ipv6_addr_for_http_with_brackets;
                           }
   #endif
                         /* Responds to request with a device as ST header */                          /* Responds to request with a device as ST header */
                         for(i = 0; known_service_types[i]; i++)                          for(i = 0; known_service_types[i]; i++)
                         {                          {
Line 395  void ProcessSSDPData(int s, char *bufr, struct sockadd Line 490  void ProcessSSDPData(int s, char *bufr, struct sockadd
                                 if(l<=st_len && (0 == memcmp(st, known_service_types[i], l)))                                  if(l<=st_len && (0 == memcmp(st, known_service_types[i], l)))
                                 {                                  {
                                         syslog(LOG_INFO, "Single search found");                                          syslog(LOG_INFO, "Single search found");
                                        SendSSDPAnnounce2(s, sendername,                                        SendSSDPAnnounce2(s, sender,
                                                           st, st_len, "",                                                            st, st_len, "",
                                                          lan_addr[lan_addr_index].str, port);                                                          announced_host, port);
                                         break;                                          break;
                                 }                                  }
                         }                          }
Line 409  void ProcessSSDPData(int s, char *bufr, struct sockadd Line 504  void ProcessSSDPData(int s, char *bufr, struct sockadd
                                 for(i=0; known_service_types[i]; i++)                                  for(i=0; known_service_types[i]; i++)
                                 {                                  {
                                         l = (int)strlen(known_service_types[i]);                                          l = (int)strlen(known_service_types[i]);
                                        SendSSDPAnnounce2(s, sendername,                                        SendSSDPAnnounce2(s, sender,
                                                           known_service_types[i], l, i==0?"":"1",                                                            known_service_types[i], l, i==0?"":"1",
                                                          lan_addr[lan_addr_index].str, port);                                                          announced_host, port);
                                 }                                  }
                         }                          }
                         /* responds to request by UUID value */                          /* responds to request by UUID value */
Line 419  void ProcessSSDPData(int s, char *bufr, struct sockadd Line 514  void ProcessSSDPData(int s, char *bufr, struct sockadd
                         if(l==st_len && (0 == memcmp(st, uuidvalue, l)))                          if(l==st_len && (0 == memcmp(st, uuidvalue, l)))
                         {                          {
                                 syslog(LOG_INFO, "ssdp:uuid found");                                  syslog(LOG_INFO, "ssdp:uuid found");
                                SendSSDPAnnounce2(s, sendername, st, st_len, "",                                SendSSDPAnnounce2(s, sender, st, st_len, "",
                                                  lan_addr[lan_addr_index].str, port);                                                  announced_host, port);
                         }                          }
                 }                  }
                 else                  else
                 {                  {
                        syslog(LOG_INFO, "Invalid SSDP M-SEARCH from %s:%d",                        syslog(LOG_INFO, "Invalid SSDP M-SEARCH from %s", sender_str);
                           inet_ntoa(sendername.sin_addr), ntohs(sendername.sin_port)); 
                 }                  }
         }          }
         else          else
         {          {
                syslog(LOG_NOTICE, "Unknown udp packet received from %s:%d",                syslog(LOG_NOTICE, "Unknown udp packet received from %s", sender_str);
                       inet_ntoa(sendername.sin_addr), ntohs(sendername.sin_port)); 
         }          }
 }  }
   
Line 456  SendSSDPGoodbye(int * sockets, int n_sockets) Line 549  SendSSDPGoodbye(int * sockets, int n_sockets)
             for(i=0; known_service_types[i]; i++)              for(i=0; known_service_types[i]; i++)
             {              {
                 l = snprintf(bufr, sizeof(bufr),                  l = snprintf(bufr, sizeof(bufr),
                         "NOTIFY * HTTP/1.1\r\n"                 "NOTIFY * HTTP/1.1\r\n"
                         "HOST:%s:%d\r\n"                 "HOST: %s:%d\r\n"
                         "NT:%s%s\r\n"                 "NT: %s%s\r\n"
                         "USN:%s::%s%s\r\n"                 "USN: %s::%s%s\r\n"
                         "NTS:ssdp:byebye\r\n"                 "NTS: ssdp:byebye\r\n"
                         "\r\n",                                 "OPT: \"http://schemas.upnp.org/upnp/1/0/\";\r\n" /* UDA v1.1 */
                         SSDP_MCAST_ADDR, SSDP_PORT,                                 "01-NLS: %u\r\n" /* same as BOOTID field. UDA v1.1 */
                                         known_service_types[i], (i==0?"":"1"),                                 "BOOTID.UPNP.ORG: %u\r\n" /* UDA v1.1 */
                         uuidvalue, known_service_types[i], (i==0?"":"1"));                                 "CONFIGID.UPNP.ORG: %u\r\n" /* UDA v1.1 */
                  "\r\n",
                  SSDP_MCAST_ADDR, SSDP_PORT,
                                  known_service_types[i], (i==0?"":"1"),
                  uuidvalue, known_service_types[i], (i==0?"":"1"),
                  upnp_bootid, upnp_bootid, upnp_configid);
                 n = sendto(sockets[j], bufr, l, 0,                  n = sendto(sockets[j], bufr, l, 0,
                            (struct sockaddr *)&sockname, sizeof(struct sockaddr_in) );                             (struct sockaddr *)&sockname, sizeof(struct sockaddr_in) );
                         if(n < 0)                          if(n < 0)

Removed from v.1.1  
changed lines
  Added in v.1.1.1.2


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