version 1.1.1.1, 2012/02/21 23:16:02
|
version 1.1.1.2, 2012/05/29 12:55:57
|
Line 2
|
Line 2
|
/* Project : miniupnp |
/* Project : miniupnp |
* Website : http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ |
* Website : http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ |
* Author : Thomas Bernard |
* Author : Thomas Bernard |
* Copyright (c) 2005-2008 Thomas Bernard | * Copyright (c) 2005-2011 Thomas Bernard |
* This software is subject to the conditions detailed in the |
* This software is subject to the conditions detailed in the |
* LICENCE file included in this distribution. |
* LICENCE file included in this distribution. |
* */ |
* */ |
Line 13
|
Line 13
|
#include <sys/types.h> |
#include <sys/types.h> |
#include <sys/socket.h> |
#include <sys/socket.h> |
#include <sys/param.h> |
#include <sys/param.h> |
|
#include <arpa/inet.h> |
#include <syslog.h> |
#include <syslog.h> |
#include <ctype.h> |
#include <ctype.h> |
#include "config.h" |
#include "config.h" |
Line 303 ProcessHTTPPOST_upnphttp(struct upnphttp * h)
|
Line 304 ProcessHTTPPOST_upnphttp(struct upnphttp * h)
|
} |
} |
|
|
#ifdef ENABLE_EVENTS |
#ifdef ENABLE_EVENTS |
|
/** |
|
* returns 0 if the callback header value is not valid |
|
* 1 if it is valid. |
|
*/ |
|
static int |
|
checkCallbackURL(struct upnphttp * h) |
|
{ |
|
char addrstr[48]; |
|
int ipv6; |
|
const char * p; |
|
int i; |
|
|
|
if(!h->req_Callback || h->req_CallbackLen < 8) |
|
return 0; |
|
if(memcmp(h->req_Callback, "http://", 7) != 0) |
|
return 0; |
|
ipv6 = 0; |
|
i = 0; |
|
p = h->req_Callback + 7; |
|
if(*p == '[') { |
|
p++; |
|
ipv6 = 1; |
|
while(*p != ']' && i < (sizeof(addrstr)-1) |
|
&& p < (h->req_Callback + h->req_CallbackLen)) |
|
addrstr[i++] = *(p++); |
|
} else { |
|
while(*p != '/' && *p != ':' && i < (sizeof(addrstr)-1) |
|
&& p < (h->req_Callback + h->req_CallbackLen)) |
|
addrstr[i++] = *(p++); |
|
} |
|
addrstr[i] = '\0'; |
|
if(ipv6) { |
|
struct in6_addr addr; |
|
if(inet_pton(AF_INET6, addrstr, &addr) <= 0) |
|
return 0; |
|
#ifdef ENABLE_IPV6 |
|
if(!h->ipv6 |
|
|| (0!=memcmp(&addr, &(h->clientaddr_v6), sizeof(struct in6_addr)))) |
|
return 0; |
|
#else |
|
return 0; |
|
#endif |
|
} else { |
|
struct in_addr addr; |
|
if(inet_pton(AF_INET, addrstr, &addr) <= 0) |
|
return 0; |
|
#ifdef ENABLE_IPV6 |
|
if(h->ipv6) { |
|
if(!IN6_IS_ADDR_V4MAPPED(&(h->clientaddr_v6))) |
|
return 0; |
|
if(0!=memcmp(&addr, ((const char *)&(h->clientaddr_v6) + 12), 4)) |
|
return 0; |
|
} else { |
|
if(0!=memcmp(&addr, &(h->clientaddr), sizeof(struct in_addr))) |
|
return 0; |
|
} |
|
#else |
|
if(0!=memcmp(&addr, &(h->clientaddr), sizeof(struct in_addr))) |
|
return 0; |
|
#endif |
|
} |
|
return 1; |
|
} |
|
|
static void |
static void |
ProcessHTTPSubscribe_upnphttp(struct upnphttp * h, const char * path) |
ProcessHTTPSubscribe_upnphttp(struct upnphttp * h, const char * path) |
{ |
{ |
Line 323 ProcessHTTPSubscribe_upnphttp(struct upnphttp * h, con
|
Line 388 ProcessHTTPSubscribe_upnphttp(struct upnphttp * h, con
|
* - respond HTTP/x.x 200 OK |
* - respond HTTP/x.x 200 OK |
* - Send the initial event message */ |
* - Send the initial event message */ |
/* Server:, SID:; Timeout: Second-(xx|infinite) */ |
/* Server:, SID:; Timeout: Second-(xx|infinite) */ |
|
/* Check that the callback URL is on the same IP as |
|
* the request, and not on the internet, nor on ourself (DOS attack ?) */ |
if(h->req_Callback) { |
if(h->req_Callback) { |
sid = upnpevents_addSubscriber(path, h->req_Callback, | if(checkCallbackURL(h)) { |
h->req_CallbackLen, h->req_Timeout); | sid = upnpevents_addSubscriber(path, h->req_Callback, |
h->respflags = FLAG_TIMEOUT; | h->req_CallbackLen, h->req_Timeout); |
if(sid) { | h->respflags = FLAG_TIMEOUT; |
syslog(LOG_DEBUG, "generated sid=%s", sid); | if(sid) { |
h->respflags |= FLAG_SID; | syslog(LOG_DEBUG, "generated sid=%s", sid); |
h->req_SID = sid; | h->respflags |= FLAG_SID; |
h->req_SIDLen = strlen(sid); | h->req_SID = sid; |
| h->req_SIDLen = strlen(sid); |
| } |
| BuildResp_upnphttp(h, 0, 0); |
| } else { |
| syslog(LOG_WARNING, "Invalid Callback in SUBSCRIBE %.*s", |
| h->req_CallbackLen, h->req_Callback); |
| BuildResp2_upnphttp(h, 412, "Precondition Failed", 0, 0); |
} |
} |
BuildResp_upnphttp(h, 0, 0); |
|
} else { |
} else { |
/* subscription renew */ |
/* subscription renew */ |
/* Invalid SID |
/* Invalid SID |
Line 343 with HTTP error 412 Precondition Failed. */
|
Line 416 with HTTP error 412 Precondition Failed. */
|
if(renewSubscription(h->req_SID, h->req_SIDLen, h->req_Timeout) < 0) { |
if(renewSubscription(h->req_SID, h->req_SIDLen, h->req_Timeout) < 0) { |
BuildResp2_upnphttp(h, 412, "Precondition Failed", 0, 0); |
BuildResp2_upnphttp(h, 412, "Precondition Failed", 0, 0); |
} else { |
} else { |
|
h->respflags = FLAG_TIMEOUT; |
BuildResp_upnphttp(h, 0, 0); |
BuildResp_upnphttp(h, 0, 0); |
} |
} |
} |
} |
Line 429 ProcessHttpQuery_upnphttp(struct upnphttp * h)
|
Line 503 ProcessHttpQuery_upnphttp(struct upnphttp * h)
|
sendXMLdesc(h, genL3F); |
sendXMLdesc(h, genL3F); |
} |
} |
#endif |
#endif |
|
#ifdef ENABLE_6FC_SERVICE |
|
else if(strcasecmp(WANIP6FC_PATH, HttpUrl) == 0) |
|
{ |
|
sendXMLdesc(h, gen6FC); |
|
} |
|
#endif |
|
#ifdef ENABLE_DP_SERVICE |
|
else if(strcasecmp(DP_PATH, HttpUrl) == 0) |
|
{ |
|
sendXMLdesc(h, genDP); |
|
} |
|
#endif |
else |
else |
{ |
{ |
syslog(LOG_NOTICE, "%s not found, responding ERROR 404", HttpUrl); |
syslog(LOG_NOTICE, "%s not found, responding ERROR 404", HttpUrl); |
Line 535 static const char httpresphead[] =
|
Line 621 static const char httpresphead[] =
|
"Content-Type: %s\r\n" |
"Content-Type: %s\r\n" |
"Connection: close\r\n" |
"Connection: close\r\n" |
"Content-Length: %d\r\n" |
"Content-Length: %d\r\n" |
/*"Server: miniupnpd/1.0 UPnP/1.0\r\n"*/ |
|
"Server: " MINIUPNPD_SERVER_STRING "\r\n" |
"Server: " MINIUPNPD_SERVER_STRING "\r\n" |
; /*"\r\n";*/ |
; /*"\r\n";*/ |
/* |
/* |
Line 560 BuildHeader_upnphttp(struct upnphttp * h, int respcode
|
Line 645 BuildHeader_upnphttp(struct upnphttp * h, int respcode
|
{ |
{ |
templen = sizeof(httpresphead) + 128 + bodylen; |
templen = sizeof(httpresphead) + 128 + bodylen; |
h->res_buf = (char *)malloc(templen); |
h->res_buf = (char *)malloc(templen); |
|
if(!h->res_buf) |
|
{ |
|
syslog(LOG_ERR, "malloc error in BuildHeader_upnphttp()"); |
|
return; |
|
} |
h->res_buf_alloclen = templen; |
h->res_buf_alloclen = templen; |
} |
} |
h->res_buflen = snprintf(h->res_buf, h->res_buf_alloclen, |
h->res_buflen = snprintf(h->res_buf, h->res_buf_alloclen, |
Line 593 BuildHeader_upnphttp(struct upnphttp * h, int respcode
|
Line 683 BuildHeader_upnphttp(struct upnphttp * h, int respcode
|
h->res_buf[h->res_buflen++] = '\n'; |
h->res_buf[h->res_buflen++] = '\n'; |
if(h->res_buf_alloclen < (h->res_buflen + bodylen)) |
if(h->res_buf_alloclen < (h->res_buflen + bodylen)) |
{ |
{ |
h->res_buf = (char *)realloc(h->res_buf, (h->res_buflen + bodylen)); | char * tmp; |
h->res_buf_alloclen = h->res_buflen + bodylen; | tmp = (char *)realloc(h->res_buf, (h->res_buflen + bodylen)); |
| if(tmp) |
| { |
| h->res_buf = tmp; |
| h->res_buf_alloclen = h->res_buflen + bodylen; |
| } |
| else |
| { |
| syslog(LOG_ERR, "realloc error in BuildHeader_upnphttp()"); |
| } |
} |
} |
} |
} |
|
|
Line 620 BuildResp_upnphttp(struct upnphttp * h,
|
Line 719 BuildResp_upnphttp(struct upnphttp * h,
|
void |
void |
SendResp_upnphttp(struct upnphttp * h) |
SendResp_upnphttp(struct upnphttp * h) |
{ |
{ |
int n; | char * p; |
n = send(h->socket, h->res_buf, h->res_buflen, 0); | ssize_t n; |
if(n<0) | size_t len; |
| p = h->res_buf; |
| len = h->res_buflen; |
| while (len > 0) |
{ |
{ |
syslog(LOG_ERR, "send(res_buf): %m"); | n = send(h->socket, p, len, 0); |
} | if(n<0) |
else if(n < h->res_buflen) | { |
{ | syslog(LOG_ERR, "send(res_buf): %m"); |
/* TODO : handle correctly this case */ | } |
syslog(LOG_ERR, "send(res_buf): %d bytes sent (out of %d)", | else if(n == 0) |
n, h->res_buflen); | { |
| syslog(LOG_ERR, "send(res_buf): %zd bytes sent (out of %zu)", |
| n, len); |
| break; |
| } |
| else |
| { |
| p += n; |
| len -= n; |
| } |
} |
} |
} |
} |
|
|