Send SSDP NOTIFY ssdp:alive and ssdp:goodbye in IPv6 too
This commit is contained in:
parent
c28d256b30
commit
593dc26608
|
@ -1,6 +1,8 @@
|
|||
$Id: Changelog.txt,v 1.267 2012/04/06 17:24:36 nanard Exp $
|
||||
|
||||
2012/04/06:
|
||||
Implementing IPv6 support :
|
||||
Send SSDP NOTIFY ssdp:alive and ssdp:goodbye messages in IPv6.
|
||||
Use UPnP/1.1 in SERVER: string as required in UPnP Device architecture 1.1.
|
||||
Allow LAN interface to be given as interface names, instead of interface
|
||||
IP addresses. It will allow IPv6 operations.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $Id: minissdp.c,v 1.29 2012/02/09 20:15:24 nanard Exp $ */
|
||||
/* $Id: minissdp.c,v 1.31 2012/04/06 17:24:37 nanard Exp $ */
|
||||
/* MiniUPnP project
|
||||
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
|
||||
* (c) 2006-2012 Thomas Bernard
|
||||
|
@ -26,8 +26,8 @@
|
|||
/* SSDP ip/port */
|
||||
#define SSDP_PORT (1900)
|
||||
#define SSDP_MCAST_ADDR ("239.255.255.250")
|
||||
#define LL_SSDP_MCAST_ADDR ("FF02::C")
|
||||
#define SL_SSDP_MCAST_ADDR ("FF05::C")
|
||||
#define LL_SSDP_MCAST_ADDR "FF02::C"
|
||||
#define SL_SSDP_MCAST_ADDR "FF05::C"
|
||||
|
||||
/* AddMulticastMembership()
|
||||
* param s socket
|
||||
|
@ -216,28 +216,68 @@ OpenAndConfSSDPNotifySocket(in_addr_t addr)
|
|||
return s;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_IPV6
|
||||
/* open the UDP socket used to send SSDP notifications to
|
||||
* the multicast group reserved for them. IPv6 */
|
||||
static int
|
||||
OpenAndConfSSDPNotifySocketIPv6(unsigned int if_index)
|
||||
{
|
||||
int s;
|
||||
unsigned int loop = 0;
|
||||
|
||||
s = socket(PF_INET6, SOCK_DGRAM, 0);
|
||||
if(s < 0)
|
||||
{
|
||||
syslog(LOG_ERR, "socket(udp_notify IPv6): %m");
|
||||
return -1;
|
||||
}
|
||||
if(setsockopt(s, IPPROTO_IPV6, IPV6_MULTICAST_IF, &if_index, sizeof(if_index)) < 0)
|
||||
{
|
||||
syslog(LOG_ERR, "setsockopt(udp_notify IPv6, IPV6_MULTICAST_IF, %u): %m", if_index);
|
||||
close(s);
|
||||
return -1;
|
||||
}
|
||||
if(setsockopt(s, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &loop, sizeof(loop)) < 0)
|
||||
{
|
||||
syslog(LOG_ERR, "setsockopt(udp_notify, IPV6_MULTICAST_LOOP): %m");
|
||||
close(s);
|
||||
return -1;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
#endif
|
||||
|
||||
int
|
||||
OpenAndConfSSDPNotifySockets(int * sockets)
|
||||
/*OpenAndConfSSDPNotifySockets(int * sockets,
|
||||
struct lan_addr_s * lan_addr, int n_lan_addr)*/
|
||||
{
|
||||
int i, j;
|
||||
int 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++)
|
||||
for(i=0, lan_addr = lan_addrs.lh_first;
|
||||
lan_addr != NULL;
|
||||
lan_addr = lan_addr->list.le_next)
|
||||
{
|
||||
sockets[i] = OpenAndConfSSDPNotifySocket(lan_addr->addr.s_addr);
|
||||
if(sockets[i] < 0)
|
||||
{
|
||||
for(j=0; j<i; j++)
|
||||
{
|
||||
close(sockets[j]);
|
||||
sockets[j] = -1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
goto error;
|
||||
i++;
|
||||
#ifdef ENABLE_IPV6
|
||||
sockets[i] = OpenAndConfSSDPNotifySocketIPv6(lan_addr->index);
|
||||
if(sockets[i] < 0)
|
||||
goto error;
|
||||
i++;
|
||||
#endif
|
||||
}
|
||||
return 0;
|
||||
error:
|
||||
while(--i >= 0)
|
||||
{
|
||||
close(sockets[i]);
|
||||
sockets[i] = -1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -288,7 +328,7 @@ SendSSDPAnnounce2(int s, const struct sockaddr * addr,
|
|||
"EXT:\r\n"
|
||||
"SERVER: " MINIUPNPD_SERVER_STRING "\r\n"
|
||||
"LOCATION: http://%s:%u" ROOTDESC_PATH "\r\n"
|
||||
"OPT: \"http://schemas.upnp.org/upnp/1/0/\";\r\n" /* UDA v1.1 */
|
||||
"OPT: \"http://schemas.upnp.org/upnp/1/0/\"; ns=01\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 */
|
||||
|
@ -332,16 +372,35 @@ static const char * const known_service_types[] =
|
|||
|
||||
static void
|
||||
SendSSDPNotifies(int s, const char * host, unsigned short port,
|
||||
unsigned int lifetime)
|
||||
unsigned int lifetime, int ipv6)
|
||||
{
|
||||
#ifdef ENABLE_IPV6
|
||||
struct sockaddr_storage sockname;
|
||||
#else
|
||||
struct sockaddr_in sockname;
|
||||
#endif
|
||||
int l, n, i=0;
|
||||
char bufr[512];
|
||||
|
||||
memset(&sockname, 0, sizeof(struct sockaddr_in));
|
||||
sockname.sin_family = AF_INET;
|
||||
sockname.sin_port = htons(SSDP_PORT);
|
||||
sockname.sin_addr.s_addr = inet_addr(SSDP_MCAST_ADDR);
|
||||
memset(&sockname, 0, sizeof(sockname));
|
||||
#ifdef ENABLE_IPV6
|
||||
if(ipv6)
|
||||
{
|
||||
struct sockaddr_in6 * p = (struct sockaddr_in6 *)&sockname;
|
||||
p->sin6_family = AF_INET6;
|
||||
p->sin6_port = htons(SSDP_PORT);
|
||||
inet_pton(AF_INET6, LL_SSDP_MCAST_ADDR, &(p->sin6_addr));
|
||||
}
|
||||
else
|
||||
{
|
||||
#endif
|
||||
struct sockaddr_in *p = (struct sockaddr_in *)&sockname;
|
||||
p->sin_family = AF_INET;
|
||||
p->sin_port = htons(SSDP_PORT);
|
||||
p->sin_addr.s_addr = inet_addr(SSDP_MCAST_ADDR);
|
||||
#ifdef ENABLE_IPV6
|
||||
}
|
||||
#endif
|
||||
|
||||
while(known_service_types[i])
|
||||
{
|
||||
|
@ -354,12 +413,13 @@ SendSSDPNotifies(int s, const char * host, unsigned short port,
|
|||
"NT: %s%s\r\n"
|
||||
"USN: %s::%s%s\r\n"
|
||||
"NTS: ssdp:alive\r\n"
|
||||
"OPT: \"http://schemas.upnp.org/upnp/1/0/\";\r\n" /* UDA v1.1 */
|
||||
"OPT: \"http://schemas.upnp.org/upnp/1/0/\"; ns=01\r\n" /* UDA v1.1 */
|
||||
"01-NLS: %u\r\n" /* same as BOOTID field. UDA v1.1 */
|
||||
"BOOTID.UPNP.ORG: %u\r\n" /* UDA v1.1 */
|
||||
"CONFIGID.UPNP.ORG: %u\r\n" /* UDA v1.1 */
|
||||
"\r\n",
|
||||
SSDP_MCAST_ADDR, SSDP_PORT,
|
||||
ipv6 ? "[" LL_SSDP_MCAST_ADDR "]" : SSDP_MCAST_ADDR,
|
||||
SSDP_PORT,
|
||||
lifetime,
|
||||
host, port,
|
||||
known_service_types[i], (i==0?"":"1"),
|
||||
|
@ -371,7 +431,13 @@ SendSSDPNotifies(int s, const char * host, unsigned short port,
|
|||
l = sizeof(bufr);
|
||||
}
|
||||
n = sendto(s, bufr, l, 0,
|
||||
(struct sockaddr *)&sockname, sizeof(struct sockaddr_in) );
|
||||
(struct sockaddr *)&sockname,
|
||||
#ifdef ENABLE_IPV6
|
||||
ipv6 ? sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in)
|
||||
#else
|
||||
sizeof(struct sockaddr_in)
|
||||
#endif
|
||||
);
|
||||
if(n < 0)
|
||||
{
|
||||
/* XXX handle EINTR, EAGAIN, EWOULDBLOCK */
|
||||
|
@ -388,9 +454,18 @@ SendSSDPNotifies2(int * sockets,
|
|||
{
|
||||
int 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++)
|
||||
for(i=0, lan_addr = lan_addrs.lh_first;
|
||||
lan_addr != NULL;
|
||||
lan_addr = lan_addr->list.le_next)
|
||||
{
|
||||
SendSSDPNotifies(sockets[i], lan_addr->str, port, lifetime);
|
||||
SendSSDPNotifies(sockets[i], lan_addr->str, port,
|
||||
lifetime, 0);
|
||||
i++;
|
||||
#ifdef ENABLE_IPV6
|
||||
SendSSDPNotifies(sockets[i], ipv6_addr_for_http_with_brackets, port,
|
||||
lifetime, 1);
|
||||
i++;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -553,18 +628,31 @@ int
|
|||
SendSSDPGoodbye(int * sockets, int n_sockets)
|
||||
{
|
||||
struct sockaddr_in sockname;
|
||||
#ifdef ENABLE_IPV6
|
||||
struct sockaddr_in6 sockname6;
|
||||
#endif
|
||||
int n, l;
|
||||
int i, j;
|
||||
char bufr[512];
|
||||
int ret = 0;
|
||||
int ipv6 = 0;
|
||||
|
||||
memset(&sockname, 0, sizeof(struct sockaddr_in));
|
||||
sockname.sin_family = AF_INET;
|
||||
sockname.sin_port = htons(SSDP_PORT);
|
||||
sockname.sin_addr.s_addr = inet_addr(SSDP_MCAST_ADDR);
|
||||
#ifdef ENABLE_IPV6
|
||||
memset(&sockname6, 0, sizeof(struct sockaddr_in6));
|
||||
sockname6.sin6_family = AF_INET6;
|
||||
sockname6.sin6_port = htons(SSDP_PORT);
|
||||
inet_pton(AF_INET6, LL_SSDP_MCAST_ADDR, &(sockname6.sin6_addr));
|
||||
#endif
|
||||
|
||||
for(j=0; j<n_sockets; j++)
|
||||
{
|
||||
#ifdef ENABLE_IPV6
|
||||
ipv6 = j & 1;
|
||||
#endif
|
||||
for(i=0; known_service_types[i]; i++)
|
||||
{
|
||||
l = snprintf(bufr, sizeof(bufr),
|
||||
|
@ -573,17 +661,19 @@ SendSSDPGoodbye(int * sockets, int n_sockets)
|
|||
"NT: %s%s\r\n"
|
||||
"USN: %s::%s%s\r\n"
|
||||
"NTS: ssdp:byebye\r\n"
|
||||
"OPT: \"http://schemas.upnp.org/upnp/1/0/\";\r\n" /* UDA v1.1 */
|
||||
"OPT: \"http://schemas.upnp.org/upnp/1/0/\"; ns=01\r\n" /* UDA v1.1 */
|
||||
"01-NLS: %u\r\n" /* same as BOOTID field. UDA v1.1 */
|
||||
"BOOTID.UPNP.ORG: %u\r\n" /* UDA v1.1 */
|
||||
"CONFIGID.UPNP.ORG: %u\r\n" /* UDA v1.1 */
|
||||
"\r\n",
|
||||
SSDP_MCAST_ADDR, SSDP_PORT,
|
||||
ipv6 ? "[" LL_SSDP_MCAST_ADDR "]" : 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,
|
||||
(struct sockaddr *)&sockname, sizeof(struct sockaddr_in) );
|
||||
ipv6 ? (struct sockaddr *)&sockname6 : (struct sockaddr *)&sockname,
|
||||
ipv6 ? sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in) );
|
||||
if(n < 0)
|
||||
{
|
||||
syslog(LOG_ERR, "SendSSDPGoodbye: sendto(udp_shutdown=%d): %m",
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $Id: miniupnpd.c,v 1.150 2012/04/06 15:27:20 nanard Exp $ */
|
||||
/* $Id: miniupnpd.c,v 1.151 2012/04/06 17:24:37 nanard Exp $ */
|
||||
/* MiniUPnP project
|
||||
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
|
||||
* (c) 2006-2012 Thomas Bernard
|
||||
|
@ -1167,7 +1167,12 @@ main(int argc, char * * argv)
|
|||
for(lan_addr = lan_addrs.lh_first; lan_addr != NULL; lan_addr = lan_addr->list.le_next)
|
||||
addr_count++;
|
||||
if(addr_count > 0) {
|
||||
#ifndef ENABLE_IPV6
|
||||
snotify = calloc(addr_count, sizeof(int));
|
||||
#else
|
||||
/* one for IPv4, one for IPv6 */
|
||||
snotify = calloc(addr_count * 2, sizeof(int));
|
||||
#endif
|
||||
}
|
||||
#ifdef ENABLE_NATPMP
|
||||
if(addr_count > 0) {
|
||||
|
@ -1725,14 +1730,21 @@ shutdown:
|
|||
}
|
||||
#endif
|
||||
|
||||
/*if(SendSSDPGoodbye(snotify, v.n_lan_addr) < 0)*/
|
||||
if (GETFLAG(ENABLEUPNPMASK))
|
||||
{
|
||||
#ifndef ENABLE_IPV6
|
||||
if(SendSSDPGoodbye(snotify, addr_count) < 0)
|
||||
#else
|
||||
if(SendSSDPGoodbye(snotify, addr_count * 2) < 0)
|
||||
#endif
|
||||
{
|
||||
syslog(LOG_ERR, "Failed to broadcast good-bye notifications");
|
||||
}
|
||||
for(i=0; i<addr_count; i++)
|
||||
#ifndef ENABLE_IPV6
|
||||
for(i = 0; i < addr_count; i++)
|
||||
#else
|
||||
for(i = 0; i < addr_count * 2; i++)
|
||||
#endif
|
||||
close(snotify[i]);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue