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) |