Commit 50058c53 authored by Rémi Denis-Courmont's avatar Rémi Denis-Courmont

* configure.ac: check for struct sockaddr_storage

* src/misc/httpd.c: use sockaddr_storage instead of sockaddr_in
         (so I may have a chance of storing a sockaddr_in6 one day)
parent 29f8c4b3
...@@ -343,6 +343,26 @@ if test "${ac_cv_type_socklen_t}" != "no"; then ...@@ -343,6 +343,26 @@ if test "${ac_cv_type_socklen_t}" != "no"; then
AC_DEFINE(HAVE_SOCKLEN_T, 1, [Define if <sys/socket.h> defines socklen_t.]) AC_DEFINE(HAVE_SOCKLEN_T, 1, [Define if <sys/socket.h> defines socklen_t.])
fi fi
dnl Check for struct sockaddr_storage
AH_TEMPLATE(sockaddr_storage, [Define to `sockaddr' if <sys/socket.h> does not define.])
AH_TEMPLATE(ss_family, [Define to `sa_family' if <sys/socket.h> does not define.])
AC_CACHE_CHECK([for struct sockaddr_storage], ac_cv_struct_sockaddr_storage,
[AC_TRY_COMPILE(
[#include <sys/types.h>
#if defined( UNDER_CE )
# include <winsock.h>
#elif defined( WIN32 )
# include <winsock2.h>
#else
# include <sys/socket.h>
#endif], [struct sockaddr_storage addr;],
ac_cv_struct_sockaddr_storage=yes,
ac_cv_struct_sockaddr_storage=no)])
if test $ac_cv_struct_sockaddr_storage = no; then
AC_DEFINE(sockaddr_storage, sockaddr)
AC_DEFINE(ss_family, sa_family)
fi
dnl Check for va_copy dnl Check for va_copy
AC_CACHE_CHECK([for va_copy], ac_cv_c_va_copy, AC_CACHE_CHECK([for va_copy], ac_cv_c_va_copy,
AC_TRY_LINK( AC_TRY_LINK(
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
* $Id$ * $Id$
* *
* Authors: Laurent Aimar <fenrir@via.ecp.fr> * Authors: Laurent Aimar <fenrir@via.ecp.fr>
* Remi Denis-Courmont <courmisch@via.ecp.fr>
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
...@@ -26,6 +27,7 @@ ...@@ -26,6 +27,7 @@
#include "vlc_httpd.h" #include "vlc_httpd.h"
#include <string.h>
#include <errno.h> #include <errno.h>
#ifdef HAVE_UNISTD_H #ifdef HAVE_UNISTD_H
# include <unistd.h> # include <unistd.h>
...@@ -200,8 +202,9 @@ struct httpd_host_t ...@@ -200,8 +202,9 @@ struct httpd_host_t
int i_ref; int i_ref;
/* address/port and socket for listening at connections */ /* address/port and socket for listening at connections */
struct sockaddr_in sock; struct sockaddr_storage sock;
int fd; int i_sock_size;
int fd;
vlc_mutex_t lock; vlc_mutex_t lock;
...@@ -260,7 +263,8 @@ struct httpd_client_t ...@@ -260,7 +263,8 @@ struct httpd_client_t
int i_ref; int i_ref;
struct sockaddr_in sock; struct sockaddr_storage sock;
int i_sock_size;
int fd; int fd;
int i_mode; int i_mode;
...@@ -857,7 +861,7 @@ void httpd_StreamDelete( httpd_stream_t *stream ) ...@@ -857,7 +861,7 @@ void httpd_StreamDelete( httpd_stream_t *stream )
#endif #endif
static void httpd_HostThread( httpd_host_t * ); static void httpd_HostThread( httpd_host_t * );
static int BuildAddr( struct sockaddr_in * p_socket, static int BuildAddr( struct sockaddr_storage * p_socket, int *pi_sock_size,
const char * psz_address, int i_port ); const char * psz_address, int i_port );
...@@ -867,11 +871,11 @@ httpd_host_t *httpd_HostNew( vlc_object_t *p_this, char *psz_host, int i_port ) ...@@ -867,11 +871,11 @@ httpd_host_t *httpd_HostNew( vlc_object_t *p_this, char *psz_host, int i_port )
httpd_t *httpd; httpd_t *httpd;
httpd_host_t *host; httpd_host_t *host;
vlc_value_t lockval; vlc_value_t lockval;
struct sockaddr_in sock; struct sockaddr_storage sock;
int i; int i, i_sock_size;
/* resolv */ /* resolv */
if( BuildAddr( &sock, psz_host, i_port ) ) if( BuildAddr( &sock, &i_sock_size, psz_host, i_port ) )
{ {
msg_Err( p_this, "cannot build address for %s:%d", psz_host, i_port ); msg_Err( p_this, "cannot build address for %s:%d", psz_host, i_port );
return NULL; return NULL;
...@@ -901,9 +905,34 @@ httpd_host_t *httpd_HostNew( vlc_object_t *p_this, char *psz_host, int i_port ) ...@@ -901,9 +905,34 @@ httpd_host_t *httpd_HostNew( vlc_object_t *p_this, char *psz_host, int i_port )
/* verify if it already exist */ /* verify if it already exist */
for( i = 0; i < httpd->i_host; i++ ) for( i = 0; i < httpd->i_host; i++ )
{ {
if( httpd->host[i]->sock.sin_port == sock.sin_port && vlc_bool_t b_match = VLC_FALSE;
( httpd->host[i]->sock.sin_addr.s_addr == INADDR_ANY ||
httpd->host[i]->sock.sin_addr.s_addr == sock.sin_addr.s_addr ) ) if (sock.ss_family != httpd->host[i]->sock.ss_family ||
i_sock_size != httpd->host[i]->i_sock_size)
continue;
switch (sock.ss_family)
{
case AF_INET:
{
const struct sockaddr_in *p_mysock, *p_thatsock;
p_mysock = (const struct sockaddr_in *)&sock;
p_thatsock = (const struct sockaddr_in *)&httpd->host[i]->sock;
b_match = p_mysock->sin_port == p_thatsock->sin_port &&
( p_mysock->sin_addr.s_addr == INADDR_ANY ||
p_mysock->sin_addr.s_addr ==
p_thatsock->sin_addr.s_addr ) ?
VLC_TRUE : VLC_FALSE;
break;
}
default:
msg_Dbg( p_this, "host with unknown address family" );
}
if (b_match == VLC_TRUE)
{ {
/* yep found */ /* yep found */
host = httpd->host[i]; host = httpd->host[i];
...@@ -920,14 +949,15 @@ httpd_host_t *httpd_HostNew( vlc_object_t *p_this, char *psz_host, int i_port ) ...@@ -920,14 +949,15 @@ httpd_host_t *httpd_HostNew( vlc_object_t *p_this, char *psz_host, int i_port )
host->httpd = httpd; host->httpd = httpd;
vlc_mutex_init( httpd, &host->lock ); vlc_mutex_init( httpd, &host->lock );
host->i_ref = 1; host->i_ref = 1;
memcpy( &host->sock, &sock, sizeof( struct sockaddr_in ) ); memcpy( &host->sock, &sock, sizeof( struct sockaddr_storage ) );
host->i_sock_size = i_sock_size;
host->i_url = 0; host->i_url = 0;
host->url = NULL; host->url = NULL;
host->i_client = 0; host->i_client = 0;
host->client = NULL; host->client = NULL;
/* create the listening socket */ /* create the listening socket */
if( ( host->fd = socket( AF_INET, SOCK_STREAM, 0 ) ) < 0 ) if( ( host->fd = socket( PF_INET, SOCK_STREAM, 0 ) ) < 0 )
{ {
goto socket_error; goto socket_error;
} }
...@@ -939,8 +969,7 @@ httpd_host_t *httpd_HostNew( vlc_object_t *p_this, char *psz_host, int i_port ) ...@@ -939,8 +969,7 @@ httpd_host_t *httpd_HostNew( vlc_object_t *p_this, char *psz_host, int i_port )
msg_Warn( p_this, "cannot configure socket (SO_REUSEADDR)" ); msg_Warn( p_this, "cannot configure socket (SO_REUSEADDR)" );
} }
/* bind it */ /* bind it */
if( bind( host->fd, (struct sockaddr *)&host->sock, if( bind( host->fd, (struct sockaddr *)&host->sock, host->i_sock_size ) )
sizeof( struct sockaddr_in ) ) < 0 )
{ {
msg_Err( p_this, "cannot bind socket" ); msg_Err( p_this, "cannot bind socket" );
goto socket_error; goto socket_error;
...@@ -1291,8 +1320,8 @@ void httpd_ClientModeBidir( httpd_client_t *cl ) ...@@ -1291,8 +1320,8 @@ void httpd_ClientModeBidir( httpd_client_t *cl )
char* httpd_ClientIP( httpd_client_t *cl ) char* httpd_ClientIP( httpd_client_t *cl )
{ {
/* FIXME not thread safe */ /* FIXME not thread safe - should use inet_ntop if available */
return strdup( inet_ntoa( cl->sock.sin_addr ) ); return strdup( inet_ntoa( ((const struct sockaddr_in *)&cl->sock)->sin_addr ) );
} }
static void httpd_ClientClean( httpd_client_t *cl ) static void httpd_ClientClean( httpd_client_t *cl )
...@@ -1313,7 +1342,8 @@ static void httpd_ClientClean( httpd_client_t *cl ) ...@@ -1313,7 +1342,8 @@ static void httpd_ClientClean( httpd_client_t *cl )
} }
} }
static httpd_client_t *httpd_ClientNew( int fd, struct sockaddr_in *sock ) static httpd_client_t *httpd_ClientNew( int fd, struct sockaddr_storage *sock,
int i_sock_size )
{ {
httpd_client_t *cl = malloc( sizeof( httpd_client_t ) ); httpd_client_t *cl = malloc( sizeof( httpd_client_t ) );
/* set this new socket non-block */ /* set this new socket non-block */
...@@ -1327,7 +1357,8 @@ static httpd_client_t *httpd_ClientNew( int fd, struct sockaddr_in *sock ) ...@@ -1327,7 +1357,8 @@ static httpd_client_t *httpd_ClientNew( int fd, struct sockaddr_in *sock )
#endif #endif
cl->i_ref = 0; cl->i_ref = 0;
cl->fd = fd; cl->fd = fd;
cl->sock = *sock; memcpy( &cl->sock, sock, sizeof( cl->sock ) );
cl->i_sock_size = i_sock_size;
cl->url = NULL; cl->url = NULL;
httpd_ClientInit( cl ); httpd_ClientInit( cl );
...@@ -1796,7 +1827,7 @@ static void httpd_HostThread( httpd_host_t *host ) ...@@ -1796,7 +1827,7 @@ static void httpd_HostThread( httpd_host_t *host )
cl->i_activity_date + cl->i_activity_timeout < mdate() ) ) ) cl->i_activity_date + cl->i_activity_timeout < mdate() ) ) )
{ {
msg_Dbg( host, "connection closed(%s)", msg_Dbg( host, "connection closed(%s)",
inet_ntoa(cl->sock.sin_addr) ); inet_ntoa(((const struct sockaddr_in *)&cl->sock)->sin_addr) );
httpd_ClientClean( cl ); httpd_ClientClean( cl );
TAB_REMOVE( host->i_client, host->client, cl ); TAB_REMOVE( host->i_client, host->client, cl );
free( cl ); free( cl );
...@@ -2141,21 +2172,21 @@ static void httpd_HostThread( httpd_host_t *host ) ...@@ -2141,21 +2172,21 @@ static void httpd_HostThread( httpd_host_t *host )
/* accept new connections */ /* accept new connections */
if( FD_ISSET( host->fd, &fds_read ) ) if( FD_ISSET( host->fd, &fds_read ) )
{ {
int i_sock_size = sizeof( struct sockaddr_in ); int i_sock_size = sizeof( struct sockaddr_storage );
struct sockaddr_in sock; struct sockaddr_storage sock;
int fd; int fd;
fd = accept( host->fd, (struct sockaddr *)&sock, &i_sock_size ); fd = accept( host->fd, (struct sockaddr *)&sock, &i_sock_size );
if( fd > 0 ) if( fd > 0 )
{ {
httpd_client_t *cl = httpd_ClientNew( fd, &sock ); httpd_client_t *cl = httpd_ClientNew( fd, &sock, i_sock_size );
vlc_mutex_lock( &host->lock ); vlc_mutex_lock( &host->lock );
TAB_APPEND( host->i_client, host->client, cl ); TAB_APPEND( host->i_client, host->client, cl );
vlc_mutex_unlock( &host->lock ); vlc_mutex_unlock( &host->lock );
msg_Dbg( host, "new connection (%s)", msg_Dbg( host, "new connection (%s)",
inet_ntoa(sock.sin_addr) ); inet_ntoa(((const struct sockaddr_in *)&sock)->sin_addr) );
} }
} }
/* now try all others socket */ /* now try all others socket */
...@@ -2183,16 +2214,17 @@ static void httpd_HostThread( httpd_host_t *host ) ...@@ -2183,16 +2214,17 @@ static void httpd_HostThread( httpd_host_t *host )
} }
} }
static int BuildAddr( struct sockaddr_in * p_socket, static int BuildAddr( struct sockaddr_storage * p_socket, int *pi_sock_size,
const char * psz_address, int i_port ) const char * psz_address, int i_port )
{ {
/* Reset struct */ /* Reset struct */
memset( p_socket, 0, sizeof( struct sockaddr_in ) ); memset( p_socket, 0, sizeof( struct sockaddr_storage ) );
p_socket->sin_family = AF_INET; /* family */ p_socket->ss_family = AF_INET; /* family */
p_socket->sin_port = htons( (uint16_t)i_port ); *pi_sock_size = sizeof( struct sockaddr_in );
((struct sockaddr_in *)p_socket)->sin_port = htons( (uint16_t)i_port );
if( !*psz_address ) if( !*psz_address )
{ {
p_socket->sin_addr.s_addr = INADDR_ANY; ((struct sockaddr_in *)p_socket)->sin_addr.s_addr = INADDR_ANY;
} }
else else
{ {
...@@ -2201,11 +2233,11 @@ static int BuildAddr( struct sockaddr_in * p_socket, ...@@ -2201,11 +2233,11 @@ static int BuildAddr( struct sockaddr_in * p_socket,
/* Try to convert address directly from in_addr - this will work if /* Try to convert address directly from in_addr - this will work if
* psz_address is dotted decimal. */ * psz_address is dotted decimal. */
#ifdef HAVE_ARPA_INET_H #ifdef HAVE_ARPA_INET_H
if( !inet_aton( psz_address, &p_socket->sin_addr ) ) if( !inet_aton( psz_address, &((struct sockaddr_in *)p_socket)->sin_addr ) )
#else #else
p_socket->sin_addr.s_addr = inet_addr( psz_address ); ((struct sockaddr_in *)p_socket)->sin_addr.s_addr = inet_addr( psz_address );
/* if( p_socket->sin_addr.s_addr == INADDR_NONE )*/ /* if( ((struct sockaddr_in *)p_socket)->sin_addr.s_addr == INADDR_NONE )*/
if( p_socket->sin_addr.s_addr == INADDR_BROADCAST ) if( ((struct sockaddr_in *)p_socket)->sin_addr.s_addr == INADDR_BROADCAST )
#endif #endif
{ {
/* We have a fqdn, try to find its address */ /* We have a fqdn, try to find its address */
...@@ -2215,7 +2247,7 @@ static int BuildAddr( struct sockaddr_in * p_socket, ...@@ -2215,7 +2247,7 @@ static int BuildAddr( struct sockaddr_in * p_socket,
} }
/* Copy the first address of the host in the socket address */ /* Copy the first address of the host in the socket address */
memcpy( &p_socket->sin_addr, p_hostent->h_addr_list[0], memcpy( &((struct sockaddr_in *)p_socket)->sin_addr, p_hostent->h_addr_list[0],
p_hostent->h_length ); p_hostent->h_length );
} }
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment