miniupnpc: parseURL()/miniwget() : IPv6 addresses scope

This commit is contained in:
Thomas Bernard 2012-06-24 00:55:31 +02:00
parent 0e85a91784
commit c585986d2f
8 changed files with 92 additions and 44 deletions

View File

@ -4,6 +4,8 @@ miniUPnP client Changelog.
2012/06/23:
More error return checks in upnpc.c
#define MINIUPNPC_GET_SRC_ADDR enables receivedata() to get scope_id
parseURL() now parses IPv6 addresses scope
new parameter for miniwget() : IPv6 address scope
increment API_VERSION to 9
2012/06/20:

View File

@ -1,4 +1,4 @@
/* $Id: connecthostport.c,v 1.6 2012/01/21 13:30:31 nanard Exp $ */
/* $Id: connecthostport.c,v 1.8 2012/06/23 22:32:33 nanard Exp $ */
/* Project : miniupnp
* Author : Thomas Bernard
* Copyright (c) 2010-2012 Thomas Bernard
@ -52,7 +52,8 @@
/* connecthostport()
* return a socket connected (TCP) to the host and port
* or -1 in case of error */
int connecthostport(const char * host, unsigned short port)
int connecthostport(const char * host, unsigned short port,
unsigned int scope_id)
{
int s, n;
#ifdef USE_GETHOSTBYNAME
@ -145,10 +146,12 @@ int connecthostport(const char * host, unsigned short port)
if(host[0] == '[')
{
/* literal ip v6 address */
int i;
for(i = 0; host[i+1] && (host[i+1] != ']') && i < MAXHOSTNAMELEN; i++)
int i, j;
for(i = 0, j = 1; host[j] && (host[j] != ']') && i < MAXHOSTNAMELEN; i++, j++)
{
tmp_host[i] = host[i+1];
tmp_host[i] = host[j];
if(0 == memcmp(host+j, "%25", 3)) /* %25 is just url encoding for '%' */
j+=2; /* skip "25" */
}
tmp_host[i] = '\0';
}
@ -173,6 +176,10 @@ int connecthostport(const char * host, unsigned short port)
s = socket(p->ai_family, p->ai_socktype, p->ai_protocol);
if(s < 0)
continue;
if(p->ai_addr->sa_family == AF_INET6 && scope_id > 0) {
struct sockaddr_in6 * addr6 = (struct sockaddr_in6 *)p->ai_addr;
addr6->sin6_scope_id = scope_id;
}
#ifdef MINIUPNPC_SET_SOCKET_TIMEOUT
/* setting a 3 seconds timeout for the connect() call */
timeout.tv_sec = 3;

View File

@ -1,8 +1,8 @@
/* $Id: connecthostport.h,v 1.1 2010/04/04 23:21:03 nanard Exp $ */
/* $Id: connecthostport.h,v 1.2 2012/06/23 22:32:33 nanard Exp $ */
/* Project: miniupnp
* http://miniupnp.free.fr/
* Author: Thomas Bernard
* Copyright (c) 2010 Thomas Bernard
* Copyright (c) 2010-2012 Thomas Bernard
* This software is subjects to the conditions detailed
* in the LICENCE file provided within this distribution */
#ifndef __CONNECTHOSTPORT_H__
@ -11,7 +11,8 @@
/* connecthostport()
* return a socket connected (TCP) to the host and port
* or -1 in case of error */
int connecthostport(const char * host, unsigned short port);
int connecthostport(const char * host, unsigned short port,
unsigned int scope_id);
#endif

View File

@ -1,4 +1,4 @@
/* $Id: miniupnpc.c,v 1.106 2012/06/11 16:08:17 nanard Exp $ */
/* $Id: miniupnpc.c,v 1.107 2012/06/23 22:36:35 nanard Exp $ */
/* Project : miniupnp
* Web : http://miniupnp.free.fr/
* Author : Thomas BERNARD
@ -189,12 +189,11 @@ char * simpleUPnPcommand2(int s, const char * url, const char * service,
strncpy(p, "></" SOAPPREFIX ":Body></" SOAPPREFIX ":Envelope>\r\n",
soapbody + sizeof(soapbody) - p);
}
if(!parseURL(url, hostname, &port, &path)) return NULL;
if(s<0)
{
s = connecthostport(hostname, port);
if(s < 0)
{
if(!parseURL(url, hostname, &port, &path, NULL)) return NULL;
if(s < 0) {
s = connecthostport(hostname, port, 0);
if(s < 0) {
/* failed to connect */
return NULL;
}
}
@ -686,6 +685,7 @@ upnpDiscover(int delay, const char * multicastif,
tmp->buffer[urlsize] = '\0';
memcpy(tmp->buffer + urlsize + 1, st, stsize);
tmp->buffer[urlsize+1+stsize] = '\0';
tmp->scope_id = scope_id;
devlist = tmp;
}
}
@ -873,7 +873,8 @@ UPNP_GetValidIGD(struct UPNPDev * devlist,
if(state == 1)
{
desc[i].xml = miniwget_getaddr(dev->descURL, &(desc[i].size),
lanaddr, lanaddrlen);
lanaddr, lanaddrlen,
dev->scope_id);
#ifdef DEBUG
if(!desc[i].xml)
{
@ -944,7 +945,7 @@ UPNP_GetIGDFromUrl(const char * rootdescurl,
char * descXML;
int descXMLsize = 0;
descXML = miniwget_getaddr(rootdescurl, &descXMLsize,
lanaddr, lanaddrlen);
lanaddr, lanaddrlen, 0);
if(descXML) {
memset(data, 0, sizeof(struct IGDdatas));
memset(urls, 0, sizeof(struct UPNPUrls));

View File

@ -37,6 +37,7 @@ struct UPNPDev {
struct UPNPDev * pNext;
char * descURL;
char * st;
unsigned int scope_id;
char buffer[2];
};

View File

@ -1,4 +1,4 @@
/* $Id: miniwget.c,v 1.56 2012/05/01 16:16:08 nanard Exp $ */
/* $Id: miniwget.c,v 1.57 2012/06/23 22:35:58 nanard Exp $ */
/* Project : miniupnp
* Website : http://miniupnp.free.fr/
* Author : Thomas Bernard
@ -36,6 +36,7 @@
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <net/if.h>
#include <netdb.h>
#define closesocket close
/* defining MINIUPNPC_IGNORE_EINTR enable the ignore of interruptions
@ -289,7 +290,7 @@ static void *
miniwget3(const char * host,
unsigned short port, const char * path,
int * size, char * addr_str, int addr_str_len,
const char * httpversion)
const char * httpversion, unsigned int scope_id)
{
char buf[2048];
int s;
@ -299,7 +300,7 @@ miniwget3(const char * host,
void * content;
*size = 0;
s = connecthostport(host, port);
s = connecthostport(host, port, scope_id);
if(s < 0)
return NULL;
@ -392,22 +393,27 @@ miniwget3(const char * host,
static void *
miniwget2(const char * host,
unsigned short port, const char * path,
int * size, char * addr_str, int addr_str_len)
int * size, char * addr_str, int addr_str_len,
unsigned int scope_id)
{
char * respbuffer;
respbuffer = miniwget3(host, port, path, size, addr_str, addr_str_len, "1.1");
/*
respbuffer = miniwget3(host, port, path, size, addr_str, addr_str_len, "1.0");
#if 1
respbuffer = miniwget3(host, port, path, size,
addr_str, addr_str_len, "1.1", scope_id);
#else
respbuffer = miniwget3(host, port, path, size,
addr_str, addr_str_len, "1.0", scope_id);
if (*size == 0)
{
#ifdef DEBUG
printf("Retrying with HTTP/1.1\n");
#endif
free(respbuffer);
respbuffer = miniwget3(host, port, path, size, addr_str, addr_str_len, "1.1");
respbuffer = miniwget3(host, port, path, size,
addr_str, addr_str_len, "1.1", scope_id);
}
*/
#endif
return respbuffer;
}
@ -424,7 +430,10 @@ miniwget2(const char * host,
* Return values :
* 0 - Failure
* 1 - Success */
int parseURL(const char * url, char * hostname, unsigned short * port, char * * path)
int
parseURL(const char * url,
char * hostname, unsigned short * port,
char * * path, unsigned int * scope_id)
{
char * p1, *p2, *p3;
if(!url)
@ -440,7 +449,29 @@ int parseURL(const char * url, char * hostname, unsigned short * port, char * *
if(*p1 == '[')
{
/* IP v6 : http://[2a00:1450:8002::6a]/path/abc */
char * scope;
scope = strchr(p1, '%');
p2 = strchr(p1, ']');
if(p2 && scope && scope < p2 && scope_id) {
/* parse scope */
#ifdef IF_NAMESIZE
char tmp[IF_NAMESIZE];
int l;
scope++;
/* "%25" is just '%' in URL encoding */
if(scope[0] == '2' && scope[1] == '5')
scope += 2; /* skip "25" */
l = p2 - scope;
if(l >= IF_NAMESIZE)
l = IF_NAMESIZE - 1;
memcpy(tmp, scope, l);
tmp[l] = '\0';
*scope_id = if_nametoindex(tmp);
if(*scope_id == 0) {
*scope_id = (unsigned int)strtoul(tmp, NULL, 10);
}
#endif
}
p3 = strchr(p1, '/');
if(p2 && p3)
{
@ -490,22 +521,26 @@ int parseURL(const char * url, char * hostname, unsigned short * port, char * *
return 1;
}
void * miniwget(const char * url, int * size)
void *
miniwget(const char * url, int * size, unsigned int scope_id)
{
unsigned short port;
char * path;
/* protocol://host:port/chemin */
char hostname[MAXHOSTNAMELEN+1];
*size = 0;
if(!parseURL(url, hostname, &port, &path))
if(!parseURL(url, hostname, &port, &path, &scope_id))
return NULL;
#ifdef DEBUG
printf("parsed url : hostname='%s' port=%hu path='%s'\n", hostname, port, path);
printf("parsed url : hostname='%s' port=%hu path='%s' scope_id=%u\n",
hostname, port, path, scope_id);
#endif
return miniwget2(hostname, port, path, size, 0, 0);
return miniwget2(hostname, port, path, size, 0, 0, scope_id);
}
void * miniwget_getaddr(const char * url, int * size, char * addr, int addrlen)
void *
miniwget_getaddr(const char * url, int * size,
char * addr, int addrlen, unsigned int scope_id)
{
unsigned short port;
char * path;
@ -514,11 +549,12 @@ void * miniwget_getaddr(const char * url, int * size, char * addr, int addrlen)
*size = 0;
if(addr)
addr[0] = '\0';
if(!parseURL(url, hostname, &port, &path))
if(!parseURL(url, hostname, &port, &path, &scope_id))
return NULL;
#ifdef DEBUG
printf("parsed url : hostname='%s' port=%hu path='%s'\n", hostname, port, path);
printf("parsed url : hostname='%s' port=%hu path='%s' scope_id=%u\n",
hostname, port, path, scope_id);
#endif
return miniwget2(hostname, port, path, size, addr, addrlen);
return miniwget2(hostname, port, path, size, addr, addrlen, scope_id);
}

View File

@ -1,7 +1,7 @@
/* $Id: miniwget.h,v 1.6 2010/12/09 16:11:33 nanard Exp $ */
/* $Id: miniwget.h,v 1.7 2012/06/23 22:35:59 nanard Exp $ */
/* Project : miniupnp
* Author : Thomas Bernard
* Copyright (c) 2005 Thomas Bernard
* Copyright (c) 2005-2012 Thomas Bernard
* This software is subject to the conditions detailed in the
* LICENCE file provided in this distribution.
* */
@ -16,11 +16,11 @@ extern "C" {
LIBSPEC void * getHTTPResponse(int s, int * size);
LIBSPEC void * miniwget(const char *, int *);
LIBSPEC void * miniwget(const char *, int *, unsigned int);
LIBSPEC void * miniwget_getaddr(const char *, int *, char *, int);
LIBSPEC void * miniwget_getaddr(const char *, int *, char *, int, unsigned int);
int parseURL(const char *, char *, unsigned short *, char * *);
int parseURL(const char *, char *, unsigned short *, char * *, unsigned int *);
#ifdef __cplusplus
}

View File

@ -1,7 +1,7 @@
/* $Id: testminiwget.c,v 1.3 2011/05/06 16:33:53 nanard Exp $ */
/* $Id: testminiwget.c,v 1.4 2012/06/23 22:35:59 nanard Exp $ */
/* Project : miniupnp
* Author : Thomas Bernard
* Copyright (c) 2005-2011 Thomas Bernard
* Copyright (c) 2005-2012 Thomas Bernard
* This software is subject to the conditions detailed in the
* LICENCE file provided in this distribution.
* */
@ -20,13 +20,13 @@ int main(int argc, char * * argv)
int size, writtensize;
FILE *f;
char addr[64];
if(argc < 3) {
fprintf(stderr, "Usage:\t%s url file\n", argv[0]);
fprintf(stderr, "Example:\t%s http://www.google.com/ out.html\n", argv[0]);
return 1;
}
/*data = miniwget(argv[1], &size);*/
data = miniwget_getaddr(argv[1], &size, addr, sizeof(addr));
data = miniwget_getaddr(argv[1], &size, addr, sizeof(addr), 0);
if(!data) {
fprintf(stderr, "Error fetching %s\n", argv[1]);
return 1;