In the latest sources, http_RequestAndResponse and other methods that

use connect() are broken. More specifically, connect() in these methods
is returning with an EINVAL. The programatic cause is that the address_len
argument passed to connect() is different in IPV4 vs IPV6 (as described in:
http://www.opengroup.org/onlinepubs/009695399/functions/connect.html).
The current code always uses the IPV6 size. The fix modifies each use of
connect() to use the correct size based on the address family being used.

Patch submitted by Chandra (inactiveneurons).
This commit is contained in:
Marcelo Roberto Jimenez 2010-09-07 21:34:16 -03:00
parent 97af8b6fdb
commit 21660334e4
2 changed files with 355 additions and 379 deletions

View File

@ -2,6 +2,17 @@
Version 1.6.7
*******************************************************************************
2010-09-07 Marcelo Jimenez <mroberto(at)users.sourceforge.net>
In the latest sources, http_RequestAndResponse and other methods that
use connect() are broken. More specifically, connect() in these methods
is returning with an EINVAL. The programatic cause is that the address_len
argument passed to connect() is different in IPV4 vs IPV6 (as described in:
http://www.opengroup.org/onlinepubs/009695399/functions/connect.html).
The current code always uses the IPV6 size. The fix modifies each use of
connect() to use the correct size based on the address family being used.
Patch submitted by Chandra (inactiveneurons).
2010-09-07 Marcelo Jimenez <mroberto(at)users.sourceforge.net>
Fix compilation error in upnp/src/gena/gena_ctrlpt.c (this is most
likely an error on all platforms).

View File

@ -176,11 +176,13 @@ http_FixStrUrl( IN const char *urlstr,
* UPNP_E_OUTOF_SOCKET
* UPNP_E_SOCKET_CONNECT on error
************************************************************************/
int
http_Connect( IN uri_type * destination_url,
int http_Connect(
IN uri_type *destination_url,
OUT uri_type *url)
{
int connfd;
int sockaddr_len;
int ret_connect;
http_FixUrl(destination_url, url);
@ -188,9 +190,11 @@ http_Connect( IN uri_type * destination_url,
if (connfd == -1) {
return UPNP_E_OUTOF_SOCKET;
}
if( connect( connfd, ( struct sockaddr * )&url->hostport.IPaddress,
sizeof( url->hostport.IPaddress ) ) == -1 ) {
sockaddr_len = url->hostport.IPaddress.ss_family == AF_INET6 ?
sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in);
ret_connect = connect(connfd,
(struct sockaddr *)&url->hostport.IPaddress, sockaddr_len);
if (ret_connect == -1) {
#ifdef WIN32
UpnpPrintf(UPNP_CRITICAL, HTTP, __FILE__, __LINE__,
"connect error: %d\n", WSAGetLastError());
@ -536,8 +540,8 @@ end:
* Error Codes returned by http_SendMessage
* Error Codes returned by http_RecvMessage
************************************************************************/
int
http_RequestAndResponse( IN uri_type * destination,
int http_RequestAndResponse(
IN uri_type *destination,
IN const char *request,
IN size_t request_length,
IN http_method_t req_method,
@ -546,43 +550,45 @@ http_RequestAndResponse( IN uri_type * destination,
{
int tcp_connection;
int ret_code;
int sockaddr_len;
int http_error_code;
SOCKINFO info;
tcp_connection = socket( destination->hostport.IPaddress.ss_family, SOCK_STREAM, 0 );
tcp_connection = socket(
destination->hostport.IPaddress.ss_family, SOCK_STREAM, 0);
if (tcp_connection == -1) {
parser_response_init(response, req_method);
return UPNP_E_SOCKET_ERROR;
}
if( sock_init( &info, tcp_connection ) != UPNP_E_SUCCESS )
{
sock_destroy( &info, SD_BOTH );
if (sock_init(&info, tcp_connection) != UPNP_E_SUCCESS) {
parser_response_init(response, req_method);
return UPNP_E_SOCKET_ERROR;
ret_code = UPNP_E_SOCKET_ERROR;
goto end_function;
}
// connect
/* connect */
sockaddr_len = destination->hostport.IPaddress.ss_family == AF_INET6 ?
sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in);
ret_code = connect(info.socket,
( struct sockaddr * )&destination->hostport.
IPaddress, sizeof( struct sockaddr_storage ) );
(struct sockaddr *)&(destination->hostport.IPaddress), sockaddr_len);
if (ret_code == -1) {
sock_destroy( &info, SD_BOTH );
parser_response_init(response, req_method);
return UPNP_E_SOCKET_CONNECT;
ret_code = UPNP_E_SOCKET_CONNECT;
goto end_function;
}
// send request
/* send request */
ret_code = http_SendMessage(&info, &timeout_secs, "b",
request, request_length);
if (ret_code != 0) {
sock_destroy( &info, SD_BOTH );
parser_response_init(response, req_method);
return ret_code;
goto end_function;
}
// recv response
/* recv response */
ret_code = http_RecvMessage(&info, response, req_method,
&timeout_secs, &http_error_code);
sock_destroy( &info, SD_BOTH ); //should shutdown completely
end_function:
/* should shutdown completely */
sock_destroy(&info, SD_BOTH);
return ret_code;
}
@ -1000,63 +1006,56 @@ http_CloseHttpPost( IN void *Handle,
* UPNP_E_SOCKET_ERROR
* UPNP_E_SOCKET_CONNECT
************************************************************************/
int
http_OpenHttpPost( IN const char *url_str,
int http_OpenHttpPost(
IN const char *url_str,
IN OUT void **Handle,
IN const char *contentType,
IN int contentLength,
IN int timeout)
{
int ret_code;
int sockaddr_len;
int tcp_connection;
membuffer request;
http_post_handle_t *handle = NULL;
uri_type url;
if( ( !url_str ) || ( !Handle ) || ( !contentType ) ) {
if ( !url_str || !Handle || !contentType) {
return UPNP_E_INVALID_PARAM;
}
( *Handle ) = handle;
*Handle = handle;
if( ( ret_code =
MakePostMessage( url_str, &request, &url, contentLength,
contentType ) ) != UPNP_E_SUCCESS ) {
ret_code = MakePostMessage(url_str, &request, &url,
contentLength, contentType);
if (ret_code != UPNP_E_SUCCESS) {
return ret_code;
}
handle =
( http_post_handle_t * ) malloc( sizeof( http_post_handle_t ) );
if( handle == NULL ) {
handle = (http_post_handle_t *) malloc(sizeof(http_post_handle_t));
if (!handle) {
return UPNP_E_OUTOF_MEMORY;
}
handle->contentLength = contentLength;
tcp_connection = socket(url.hostport.IPaddress.ss_family, SOCK_STREAM, 0);
if (tcp_connection == -1) {
ret_code = UPNP_E_SOCKET_ERROR;
goto errorHandler;
}
if( sock_init( &handle->sock_info, tcp_connection ) != UPNP_E_SUCCESS )
{
if (sock_init(&handle->sock_info, tcp_connection) != UPNP_E_SUCCESS) {
sock_destroy( &handle->sock_info, SD_BOTH );
ret_code = UPNP_E_SOCKET_ERROR;
goto errorHandler;
}
sockaddr_len = url.hostport.IPaddress.ss_family == AF_INET6 ?
sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in);
ret_code = connect(handle->sock_info.socket,
( struct sockaddr * )&url.hostport.IPaddress,
sizeof( struct sockaddr_storage ) );
(struct sockaddr *)&(url.hostport.IPaddress), sockaddr_len);
if (ret_code == -1) {
sock_destroy(&handle->sock_info, SD_BOTH);
ret_code = UPNP_E_SOCKET_CONNECT;
goto errorHandler;
}
// send request
/* send request */
ret_code = http_SendMessage(&handle->sock_info, &timeout, "b",
request.buf, request.length);
if (ret_code != 0) {
@ -1065,7 +1064,8 @@ http_OpenHttpPost( IN const char *url_str,
errorHandler:
membuffer_destroy(&request);
( *Handle ) = handle;
*Handle = handle;
return ret_code;
}
@ -1565,8 +1565,8 @@ http_OpenHttpGet( IN const char *url_str,
* UPNP_E_SOCKET_ERROR
* UPNP_E_BAD_RESPONSE
************************************************************************/
int
http_OpenHttpGetProxy( IN const char *url_str,
int http_OpenHttpGetProxy(
IN const char *url_str,
IN const char *proxy_str,
IN OUT void **Handle,
IN OUT char **contentType,
@ -1575,6 +1575,7 @@ http_OpenHttpGetProxy( IN const char *url_str,
IN int timeout)
{
int ret_code;
int sockaddr_len;
int http_error_code;
memptr ctype;
int tcp_connection;
@ -1585,18 +1586,17 @@ http_OpenHttpGetProxy( IN const char *url_str,
uri_type *peer;
parse_status_t status;
if( ( !url_str ) || ( !Handle ) || ( !contentType )
|| ( !httpStatus ) ) {
if (!url_str || !Handle || !contentType || !httpStatus ) {
return UPNP_E_INVALID_PARAM;
}
( *httpStatus ) = 0;
( *Handle ) = handle;
( *contentType ) = NULL;
( *contentLength ) = 0;
*httpStatus = 0;
*Handle = handle;
*contentType = NULL;
*contentLength = 0;
if( ( ret_code =
MakeGetMessage( url_str, proxy_str, &request, &url ) ) != UPNP_E_SUCCESS ) {
ret_code = MakeGetMessage(url_str, proxy_str, &request, &url);
if (ret_code != UPNP_E_SUCCESS) {
return ret_code;
}
if (proxy_str) {
@ -1605,89 +1605,75 @@ http_OpenHttpGetProxy( IN const char *url_str,
} else {
peer = &url;
}
handle = (http_get_handle_t *)malloc(sizeof(http_get_handle_t));
if( handle == NULL ) {
if (!handle) {
return UPNP_E_OUTOF_MEMORY;
}
handle->entity_offset = 0;
handle->cancel = 0;
parser_response_init(&handle->response, HTTPMETHOD_GET);
tcp_connection = socket(peer->hostport.IPaddress.ss_family, SOCK_STREAM, 0);
if (tcp_connection == -1) {
ret_code = UPNP_E_SOCKET_ERROR;
goto errorHandler;
}
if( sock_init( &handle->sock_info, tcp_connection ) != UPNP_E_SUCCESS )
{
if (sock_init(&handle->sock_info, tcp_connection) != UPNP_E_SUCCESS) {
sock_destroy(&handle->sock_info, SD_BOTH);
ret_code = UPNP_E_SOCKET_ERROR;
goto errorHandler;
}
sockaddr_len = peer->hostport.IPaddress.ss_family == AF_INET6 ?
sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in);
ret_code = connect(handle->sock_info.socket,
( struct sockaddr * )&peer->hostport.IPaddress,
sizeof( struct sockaddr_storage ) );
(struct sockaddr *)&(peer->hostport.IPaddress), sockaddr_len);
if (ret_code == -1) {
sock_destroy(&handle->sock_info, SD_BOTH);
ret_code = UPNP_E_SOCKET_CONNECT;
goto errorHandler;
}
// send request
/* send request */
ret_code = http_SendMessage(&handle->sock_info, &timeout, "b",
request.buf, request.length);
if( ret_code != 0 ) {
if (ret_code) {
sock_destroy(&handle->sock_info, SD_BOTH);
goto errorHandler;
}
status =
ReadResponseLineAndHeaders( &handle->sock_info, &handle->response,
&timeout, &http_error_code );
status = ReadResponseLineAndHeaders(&handle->sock_info,
&handle->response, &timeout, &http_error_code);
if (status != PARSE_OK) {
ret_code = UPNP_E_BAD_RESPONSE;
goto errorHandler;
}
status = parser_get_entity_read_method(&handle->response);
if( ( status != PARSE_CONTINUE_1 ) && ( status != PARSE_SUCCESS ) ) {
if (status != PARSE_CONTINUE_1 && status != PARSE_SUCCESS) {
ret_code = UPNP_E_BAD_RESPONSE;
goto errorHandler;
}
( *httpStatus ) = handle->response.msg.status_code;
*httpStatus = handle->response.msg.status_code;
ret_code = UPNP_E_SUCCESS;
if( httpmsg_find_hdr( &handle->response.msg, HDR_CONTENT_TYPE, &ctype )
== NULL ) {
*contentType = NULL; // no content-type
if (!httpmsg_find_hdr(&handle->response.msg, HDR_CONTENT_TYPE, &ctype)) {
/* no content-type */
*contentType = NULL;
} else {
*contentType = ctype.buf;
}
if (handle->response.position == POS_COMPLETE) {
( *contentLength ) = 0;
*contentLength = 0;
} else if (handle->response.ent_position == ENTREAD_USING_CHUNKED) {
( *contentLength ) = UPNP_USING_CHUNKED;
*contentLength = UPNP_USING_CHUNKED;
} else if (handle->response.ent_position == ENTREAD_USING_CLEN) {
( *contentLength ) = handle->response.content_length;
*contentLength = handle->response.content_length;
} else if (handle->response.ent_position == ENTREAD_UNTIL_CLOSE) {
( *contentLength ) = UPNP_UNTIL_CLOSE;
*contentLength = UPNP_UNTIL_CLOSE;
}
errorHandler:
( *Handle ) = handle;
*Handle = handle;
membuffer_destroy(&request);
if (ret_code != UPNP_E_SUCCESS) {
httpmsg_destroy(&handle->response.msg);
}
@ -2201,8 +2187,8 @@ MakeGetMessageEx( const char *url_str,
* UPNP_E_SOCKET_ERROR
* UPNP_E_BAD_RESPONSE
************************************************************************/
int
http_OpenHttpGetEx( IN const char *url_str,
int http_OpenHttpGetEx(
IN const char *url_str,
IN OUT void **Handle,
IN OUT char **contentType,
OUT int *contentLength,
@ -2214,131 +2200,110 @@ http_OpenHttpGetEx( IN const char *url_str,
int http_error_code;
memptr ctype;
int tcp_connection;
int sockaddr_len;
membuffer request;
http_get_handle_t *handle = NULL;
uri_type url;
parse_status_t status;
int errCode = UPNP_E_SUCCESS;
// char rangeBuf[SIZE_RANGE_BUFFER];
/* char rangeBuf[SIZE_RANGE_BUFFER]; */
struct SendInstruction rangeBuf;
do {
// Checking Input parameters
if( ( !url_str ) || ( !Handle ) ||
( !contentType ) || ( !httpStatus ) ) {
/* Checking Input parameters */
if (!url_str || !Handle || !contentType || !httpStatus ) {
errCode = UPNP_E_INVALID_PARAM;
break;
}
// Initialize output parameters
( *httpStatus ) = 0;
( *Handle ) = handle;
( *contentType ) = NULL;
( *contentLength ) = 0;
/* Initialize output parameters */
*httpStatus = 0;
*Handle = handle;
*contentType = NULL;
*contentLength = 0;
if (lowRange > highRange) {
errCode = UPNP_E_INTERNAL_ERROR;
break;
}
memset(&rangeBuf, 0, sizeof(rangeBuf));
sprintf( rangeBuf.RangeHeader, "Range: bytes=%d-%d\r\n",
lowRange, highRange );
sprintf(rangeBuf.RangeHeader,
"Range: bytes=%d-%d\r\n", lowRange, highRange);
membuffer_init(&request);
if( ( errCode = MakeGetMessageEx( url_str,
&request, &url, &rangeBuf ) )
!= UPNP_E_SUCCESS ) {
errCode = MakeGetMessageEx(url_str, &request, &url, &rangeBuf);
if (errCode != UPNP_E_SUCCESS) {
break;
}
handle =
( http_get_handle_t * ) malloc( sizeof( http_get_handle_t ) );
if( handle == NULL ) {
handle = (http_get_handle_t *)malloc(sizeof(http_get_handle_t));
if (!handle) {
errCode = UPNP_E_OUTOF_MEMORY;
break;
}
memset(handle, 0, sizeof(*handle));
handle->entity_offset = 0;
parser_response_init(&handle->response, HTTPMETHOD_GET);
tcp_connection = socket(url.hostport.IPaddress.ss_family, SOCK_STREAM, 0);
if (tcp_connection == -1) {
errCode = UPNP_E_SOCKET_ERROR;
free(handle);
break;
}
if( sock_init( &handle->sock_info, tcp_connection ) !=
UPNP_E_SUCCESS ) {
if (sock_init(&handle->sock_info, tcp_connection) != UPNP_E_SUCCESS) {
sock_destroy(&handle->sock_info, SD_BOTH);
errCode = UPNP_E_SOCKET_ERROR;
free(handle);
break;
}
sockaddr_len = url.hostport.IPaddress.ss_family == AF_INET6 ?
sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in);
errCode = connect(handle->sock_info.socket,
( struct sockaddr * )&url.hostport.IPaddress,
sizeof( struct sockaddr_storage ) );
(struct sockaddr *)&(url.hostport.IPaddress), sockaddr_len);
if (errCode == -1) {
sock_destroy(&handle->sock_info, SD_BOTH);
errCode = UPNP_E_SOCKET_CONNECT;
free(handle);
break;
}
// send request
errCode = http_SendMessage( &handle->sock_info,
&timeout,
/* send request */
errCode = http_SendMessage(&handle->sock_info, &timeout,
"b", request.buf, request.length);
if (errCode != UPNP_E_SUCCESS) {
sock_destroy(&handle->sock_info, SD_BOTH);
free(handle);
break;
}
status = ReadResponseLineAndHeaders(&handle->sock_info,
&handle->response,
&timeout, &http_error_code );
&handle->response, &timeout, &http_error_code);
if (status != PARSE_OK) {
errCode = UPNP_E_BAD_RESPONSE;
free(handle);
break;
}
status = parser_get_entity_read_method(&handle->response);
if( ( status != PARSE_CONTINUE_1 ) && ( status != PARSE_SUCCESS ) ) {
if (status != PARSE_CONTINUE_1 && status != PARSE_SUCCESS) {
errCode = UPNP_E_BAD_RESPONSE;
free(handle);
break;
}
( *httpStatus ) = handle->response.msg.status_code;
*httpStatus = handle->response.msg.status_code;
errCode = UPNP_E_SUCCESS;
if( httpmsg_find_hdr( &handle->response.msg,
HDR_CONTENT_TYPE, &ctype ) == NULL ) {
*contentType = NULL; // no content-type
if (!httpmsg_find_hdr(&handle->response.msg, HDR_CONTENT_TYPE, &ctype)) {
/* no content-type */
*contentType = NULL;
} else {
*contentType = ctype.buf;
}
if (handle->response.position == POS_COMPLETE) {
( *contentLength ) = 0;
*contentLength = 0;
} else if(handle->response.ent_position == ENTREAD_USING_CHUNKED) {
( *contentLength ) = UPNP_USING_CHUNKED;
*contentLength = UPNP_USING_CHUNKED;
} else if(handle->response.ent_position == ENTREAD_USING_CLEN) {
( *contentLength ) = handle->response.content_length;
*contentLength = handle->response.content_length;
} else if(handle->response.ent_position == ENTREAD_UNTIL_CLOSE) {
( *contentLength ) = UPNP_UNTIL_CLOSE;
*contentLength = UPNP_UNTIL_CLOSE;
}
( *Handle ) = handle;
*Handle = handle;
} while (0);
membuffer_destroy(&request);