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 $
|
$Id: Changelog.txt,v 1.267 2012/04/06 17:24:36 nanard Exp $
|
||||||
|
|
||||||
2012/04/06:
|
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.
|
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
|
Allow LAN interface to be given as interface names, instead of interface
|
||||||
IP addresses. It will allow IPv6 operations.
|
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
|
/* MiniUPnP project
|
||||||
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
|
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
|
||||||
* (c) 2006-2012 Thomas Bernard
|
* (c) 2006-2012 Thomas Bernard
|
||||||
|
@ -26,8 +26,8 @@
|
||||||
/* SSDP ip/port */
|
/* SSDP ip/port */
|
||||||
#define SSDP_PORT (1900)
|
#define SSDP_PORT (1900)
|
||||||
#define SSDP_MCAST_ADDR ("239.255.255.250")
|
#define SSDP_MCAST_ADDR ("239.255.255.250")
|
||||||
#define LL_SSDP_MCAST_ADDR ("FF02::C")
|
#define LL_SSDP_MCAST_ADDR "FF02::C"
|
||||||
#define SL_SSDP_MCAST_ADDR ("FF05::C")
|
#define SL_SSDP_MCAST_ADDR "FF05::C"
|
||||||
|
|
||||||
/* AddMulticastMembership()
|
/* AddMulticastMembership()
|
||||||
* param s socket
|
* param s socket
|
||||||
|
@ -216,28 +216,68 @@ OpenAndConfSSDPNotifySocket(in_addr_t addr)
|
||||||
return s;
|
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
|
int
|
||||||
OpenAndConfSSDPNotifySockets(int * sockets)
|
OpenAndConfSSDPNotifySockets(int * sockets)
|
||||||
/*OpenAndConfSSDPNotifySockets(int * sockets,
|
/*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;
|
||||||
struct lan_addr_s * lan_addr;
|
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);
|
sockets[i] = OpenAndConfSSDPNotifySocket(lan_addr->addr.s_addr);
|
||||||
if(sockets[i] < 0)
|
if(sockets[i] < 0)
|
||||||
{
|
goto error;
|
||||||
for(j=0; j<i; j++)
|
i++;
|
||||||
{
|
#ifdef ENABLE_IPV6
|
||||||
close(sockets[j]);
|
sockets[i] = OpenAndConfSSDPNotifySocketIPv6(lan_addr->index);
|
||||||
sockets[j] = -1;
|
if(sockets[i] < 0)
|
||||||
}
|
goto error;
|
||||||
return -1;
|
i++;
|
||||||
}
|
#endif
|
||||||
}
|
}
|
||||||
return 0;
|
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"
|
"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 */
|
"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 */
|
"01-NLS: %u\r\n" /* same as BOOTID. UDA v1.1 */
|
||||||
"BOOTID.UPNP.ORG: %u\r\n" /* UDA v1.1 */
|
"BOOTID.UPNP.ORG: %u\r\n" /* UDA v1.1 */
|
||||||
"CONFIGID.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
|
static void
|
||||||
SendSSDPNotifies(int s, const char * host, unsigned short port,
|
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;
|
struct sockaddr_in sockname;
|
||||||
|
#endif
|
||||||
int l, n, i=0;
|
int l, n, i=0;
|
||||||
char bufr[512];
|
char bufr[512];
|
||||||
|
|
||||||
memset(&sockname, 0, sizeof(struct sockaddr_in));
|
memset(&sockname, 0, sizeof(sockname));
|
||||||
sockname.sin_family = AF_INET;
|
#ifdef ENABLE_IPV6
|
||||||
sockname.sin_port = htons(SSDP_PORT);
|
if(ipv6)
|
||||||
sockname.sin_addr.s_addr = inet_addr(SSDP_MCAST_ADDR);
|
{
|
||||||
|
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])
|
while(known_service_types[i])
|
||||||
{
|
{
|
||||||
|
@ -354,12 +413,13 @@ SendSSDPNotifies(int s, const char * host, unsigned short port,
|
||||||
"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 */
|
"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 */
|
"01-NLS: %u\r\n" /* same as BOOTID field. UDA v1.1 */
|
||||||
"BOOTID.UPNP.ORG: %u\r\n" /* UDA v1.1 */
|
"BOOTID.UPNP.ORG: %u\r\n" /* UDA v1.1 */
|
||||||
"CONFIGID.UPNP.ORG: %u\r\n" /* UDA v1.1 */
|
"CONFIGID.UPNP.ORG: %u\r\n" /* UDA v1.1 */
|
||||||
"\r\n",
|
"\r\n",
|
||||||
SSDP_MCAST_ADDR, SSDP_PORT,
|
ipv6 ? "[" LL_SSDP_MCAST_ADDR "]" : SSDP_MCAST_ADDR,
|
||||||
|
SSDP_PORT,
|
||||||
lifetime,
|
lifetime,
|
||||||
host, port,
|
host, port,
|
||||||
known_service_types[i], (i==0?"":"1"),
|
known_service_types[i], (i==0?"":"1"),
|
||||||
|
@ -371,7 +431,13 @@ SendSSDPNotifies(int s, const char * host, unsigned short port,
|
||||||
l = sizeof(bufr);
|
l = sizeof(bufr);
|
||||||
}
|
}
|
||||||
n = sendto(s, bufr, l, 0,
|
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)
|
if(n < 0)
|
||||||
{
|
{
|
||||||
/* XXX handle EINTR, EAGAIN, EWOULDBLOCK */
|
/* XXX handle EINTR, EAGAIN, EWOULDBLOCK */
|
||||||
|
@ -388,9 +454,18 @@ SendSSDPNotifies2(int * sockets,
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
struct lan_addr_s * lan_addr;
|
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)
|
SendSSDPGoodbye(int * sockets, int n_sockets)
|
||||||
{
|
{
|
||||||
struct sockaddr_in sockname;
|
struct sockaddr_in sockname;
|
||||||
|
#ifdef ENABLE_IPV6
|
||||||
|
struct sockaddr_in6 sockname6;
|
||||||
|
#endif
|
||||||
int n, l;
|
int n, l;
|
||||||
int i, j;
|
int i, j;
|
||||||
char bufr[512];
|
char bufr[512];
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
int ipv6 = 0;
|
||||||
|
|
||||||
memset(&sockname, 0, sizeof(struct sockaddr_in));
|
memset(&sockname, 0, sizeof(struct sockaddr_in));
|
||||||
sockname.sin_family = AF_INET;
|
sockname.sin_family = AF_INET;
|
||||||
sockname.sin_port = htons(SSDP_PORT);
|
sockname.sin_port = htons(SSDP_PORT);
|
||||||
sockname.sin_addr.s_addr = inet_addr(SSDP_MCAST_ADDR);
|
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++)
|
for(j=0; j<n_sockets; j++)
|
||||||
{
|
{
|
||||||
|
#ifdef ENABLE_IPV6
|
||||||
|
ipv6 = j & 1;
|
||||||
|
#endif
|
||||||
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),
|
||||||
|
@ -573,17 +661,19 @@ SendSSDPGoodbye(int * sockets, int n_sockets)
|
||||||
"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"
|
||||||
"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 */
|
"01-NLS: %u\r\n" /* same as BOOTID field. UDA v1.1 */
|
||||||
"BOOTID.UPNP.ORG: %u\r\n" /* UDA v1.1 */
|
"BOOTID.UPNP.ORG: %u\r\n" /* UDA v1.1 */
|
||||||
"CONFIGID.UPNP.ORG: %u\r\n" /* UDA v1.1 */
|
"CONFIGID.UPNP.ORG: %u\r\n" /* UDA v1.1 */
|
||||||
"\r\n",
|
"\r\n",
|
||||||
SSDP_MCAST_ADDR, SSDP_PORT,
|
ipv6 ? "[" LL_SSDP_MCAST_ADDR "]" : SSDP_MCAST_ADDR,
|
||||||
|
SSDP_PORT,
|
||||||
known_service_types[i], (i==0?"":"1"),
|
known_service_types[i], (i==0?"":"1"),
|
||||||
uuidvalue, known_service_types[i], (i==0?"":"1"),
|
uuidvalue, known_service_types[i], (i==0?"":"1"),
|
||||||
upnp_bootid, upnp_bootid, upnp_configid);
|
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) );
|
ipv6 ? (struct sockaddr *)&sockname6 : (struct sockaddr *)&sockname,
|
||||||
|
ipv6 ? sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in) );
|
||||||
if(n < 0)
|
if(n < 0)
|
||||||
{
|
{
|
||||||
syslog(LOG_ERR, "SendSSDPGoodbye: sendto(udp_shutdown=%d): %m",
|
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
|
/* MiniUPnP project
|
||||||
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
|
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
|
||||||
* (c) 2006-2012 Thomas Bernard
|
* (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)
|
for(lan_addr = lan_addrs.lh_first; lan_addr != NULL; lan_addr = lan_addr->list.le_next)
|
||||||
addr_count++;
|
addr_count++;
|
||||||
if(addr_count > 0) {
|
if(addr_count > 0) {
|
||||||
|
#ifndef ENABLE_IPV6
|
||||||
snotify = calloc(addr_count, sizeof(int));
|
snotify = calloc(addr_count, sizeof(int));
|
||||||
|
#else
|
||||||
|
/* one for IPv4, one for IPv6 */
|
||||||
|
snotify = calloc(addr_count * 2, sizeof(int));
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
#ifdef ENABLE_NATPMP
|
#ifdef ENABLE_NATPMP
|
||||||
if(addr_count > 0) {
|
if(addr_count > 0) {
|
||||||
|
@ -1725,14 +1730,21 @@ shutdown:
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*if(SendSSDPGoodbye(snotify, v.n_lan_addr) < 0)*/
|
|
||||||
if (GETFLAG(ENABLEUPNPMASK))
|
if (GETFLAG(ENABLEUPNPMASK))
|
||||||
{
|
{
|
||||||
|
#ifndef ENABLE_IPV6
|
||||||
if(SendSSDPGoodbye(snotify, addr_count) < 0)
|
if(SendSSDPGoodbye(snotify, addr_count) < 0)
|
||||||
|
#else
|
||||||
|
if(SendSSDPGoodbye(snotify, addr_count * 2) < 0)
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
syslog(LOG_ERR, "Failed to broadcast good-bye notifications");
|
syslog(LOG_ERR, "Failed to broadcast good-bye notifications");
|
||||||
}
|
}
|
||||||
|
#ifndef ENABLE_IPV6
|
||||||
for(i = 0; i < addr_count; i++)
|
for(i = 0; i < addr_count; i++)
|
||||||
|
#else
|
||||||
|
for(i = 0; i < addr_count * 2; i++)
|
||||||
|
#endif
|
||||||
close(snotify[i]);
|
close(snotify[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue