IRC IPv6 support.
This commit is contained in:
@@ -11,7 +11,7 @@
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
* License for more details.
|
||||
*
|
||||
* $Id: libirc_errors.h 28 2004-10-04 10:34:58Z gyunaev $
|
||||
* $Id: libirc_errors.h 28M 2007-09-16 23:43:28Z (local) $
|
||||
*/
|
||||
|
||||
/*!
|
||||
@@ -193,8 +193,17 @@
|
||||
#define LIBIRC_ERR_TERMINATED 15
|
||||
|
||||
|
||||
/*! \brief IPv6 not supported
|
||||
*
|
||||
* The function which requires IPv6 support was called, but the IPv6 support was not compiled
|
||||
* into the application
|
||||
*
|
||||
* \ingroup errorcodes
|
||||
*/
|
||||
#define LIBIRC_ERR_NOIPV6 16
|
||||
|
||||
/*! brief Internal max error value count
|
||||
*/
|
||||
#define LIBIRC_ERR_MAX 16
|
||||
#define LIBIRC_ERR_MAX 17
|
||||
|
||||
#endif /* INCLUDE_IRC_ERRORS_H */
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
* License for more details.
|
||||
*
|
||||
* $Id: libirc_session.h 18 2004-09-14 19:50:10Z gyunaev $
|
||||
* $Id: libirc_session.h 18M 2007-09-17 01:14:31Z (local) $
|
||||
*/
|
||||
|
||||
|
||||
@@ -54,7 +54,11 @@ struct irc_session_s
|
||||
char * username;
|
||||
char * nick;
|
||||
|
||||
#if defined( ENABLE_IPV6 )
|
||||
struct in6_addr local_addr;
|
||||
#else
|
||||
struct in_addr local_addr;
|
||||
#endif
|
||||
irc_dcc_t dcc_last_id;
|
||||
irc_dcc_session_t * dcc_sessions;
|
||||
port_mutex_t mutex_dcc;
|
||||
|
||||
@@ -50,6 +50,7 @@
|
||||
#include <netinet/in.h> /* sockaddr_in */
|
||||
#else
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
@@ -228,6 +229,13 @@ int irc_connect (irc_session_t * session,
|
||||
const char * username,
|
||||
const char * realname);
|
||||
|
||||
int irc_connect6 (irc_session_t * session,
|
||||
const char * server,
|
||||
unsigned short port,
|
||||
const char * server_password,
|
||||
const char * nick,
|
||||
const char * username,
|
||||
const char * realname);
|
||||
|
||||
/*!
|
||||
* \fn void irc_disconnect (irc_session_t * session)
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
* License for more details.
|
||||
*
|
||||
* $Id: errors.c 2 2004-09-08 11:49:02Z gyunaev $
|
||||
* $Id: errors.c 2M 2007-09-16 23:42:08Z (local) $
|
||||
*/
|
||||
|
||||
static const char * libirc_strerror[LIBIRC_ERR_MAX] =
|
||||
@@ -32,6 +32,7 @@ static const char * libirc_strerror[LIBIRC_ERR_MAX] =
|
||||
"Timeout error",
|
||||
"Could not open file",
|
||||
"IRC session terminated",
|
||||
"IPv6 not supported",
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -11,10 +11,9 @@
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
* License for more details.
|
||||
*
|
||||
* $Id: libircclient.c 42 2004-10-10 16:16:15Z gyunaev $
|
||||
* $Id: libircclient.c 42M 2007-09-17 01:15:57Z (local) $
|
||||
*/
|
||||
|
||||
|
||||
#include "portable.c"
|
||||
#include "sockets.c"
|
||||
|
||||
@@ -27,10 +26,17 @@
|
||||
#include "dcc.c"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
/*
|
||||
|
||||
* The debugger of MSVC 2005 does not like strdup.
|
||||
* It complains about heap corruption when free is called.
|
||||
* Use _strdup instead.
|
||||
*/
|
||||
#undef strdup
|
||||
#define strdup _strdup
|
||||
#endif
|
||||
|
||||
|
||||
#define IS_DEBUG_ENABLED(s) ((s)->option & LIBIRC_OPTION_DEBUG)
|
||||
|
||||
|
||||
@@ -133,9 +139,10 @@ int irc_connect (irc_session_t * session,
|
||||
session->nick = strdup (nick);
|
||||
session->server = strdup (server);
|
||||
|
||||
memset (&saddr, 0, sizeof(saddr));
|
||||
// IPv4 address resolving
|
||||
memset( &saddr, 0, sizeof(saddr) );
|
||||
saddr.sin_family = AF_INET;
|
||||
saddr.sin_port = htons (port);
|
||||
saddr.sin_port = htons (port);
|
||||
saddr.sin_addr.s_addr = inet_addr (server);
|
||||
|
||||
if ( saddr.sin_addr.s_addr == INADDR_NONE )
|
||||
@@ -150,7 +157,7 @@ int irc_connect (irc_session_t * session,
|
||||
hp = 0;
|
||||
#else
|
||||
hp = gethostbyname (server);
|
||||
#endif
|
||||
#endif // HAVE_GETHOSTBYNAME_R
|
||||
if ( !hp )
|
||||
{
|
||||
session->lasterror = LIBIRC_ERR_RESOLV;
|
||||
@@ -161,7 +168,7 @@ int irc_connect (irc_session_t * session,
|
||||
}
|
||||
|
||||
// create the IRC server socket
|
||||
if ( socket_create (PF_INET, SOCK_STREAM, &session->sock)
|
||||
if ( socket_create( PF_INET, SOCK_STREAM, &session->sock)
|
||||
|| socket_make_nonblocking (&session->sock) )
|
||||
{
|
||||
session->lasterror = LIBIRC_ERR_SOCKET;
|
||||
@@ -181,6 +188,144 @@ int irc_connect (irc_session_t * session,
|
||||
}
|
||||
|
||||
|
||||
|
||||
#if defined (ENABLE_IPV6) && defined (_WIN32)
|
||||
typedef int (WSAAPI * getaddrinfo_ptr_t) (const char *, const char* , const struct addrinfo *, struct addrinfo **);
|
||||
typedef void (WSAAPI * freeaddrinfo_ptr_t) (struct addrinfo*);
|
||||
#endif
|
||||
|
||||
int irc_connect6 (irc_session_t * session,
|
||||
const char * server,
|
||||
unsigned short port,
|
||||
const char * server_password,
|
||||
const char * nick,
|
||||
const char * username,
|
||||
const char * realname)
|
||||
{
|
||||
#if defined (ENABLE_IPV6)
|
||||
struct sockaddr_in6 saddr;
|
||||
struct addrinfo ainfo, *res;
|
||||
#if defined (_WIN32)
|
||||
int addrlen = sizeof(saddr);
|
||||
HMODULE hWsock;
|
||||
getaddrinfo_ptr_t getaddrinfo_ptr;
|
||||
freeaddrinfo_ptr_t freeaddrinfo_ptr;
|
||||
int resolvesuccess = 0;
|
||||
#endif
|
||||
|
||||
// Check and copy all the specified fields
|
||||
if ( !server || !nick )
|
||||
{
|
||||
session->lasterror = LIBIRC_ERR_INVAL;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ( session->state != LIBIRC_STATE_INIT )
|
||||
{
|
||||
session->lasterror = LIBIRC_ERR_STATE;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ( username )
|
||||
session->username = strdup (username);
|
||||
|
||||
if ( server_password )
|
||||
session->server_password = strdup (server_password);
|
||||
|
||||
if ( realname )
|
||||
session->realname = strdup (realname);
|
||||
|
||||
session->nick = strdup (nick);
|
||||
session->server = strdup (server);
|
||||
|
||||
memset( &saddr, 0, sizeof(saddr) );
|
||||
saddr.sin6_family = AF_INET6;
|
||||
saddr.sin6_port = htons (port);
|
||||
saddr.sin6_flowinfo = 0;
|
||||
saddr.sin6_scope_id = 0;
|
||||
|
||||
#if defined (_WIN32)
|
||||
if ( WSAStringToAddressA( (LPSTR)server, AF_INET6, NULL, (struct sockaddr *)&saddr, &addrlen ) == SOCKET_ERROR )
|
||||
{
|
||||
hWsock = LoadLibraryA("ws2_32");
|
||||
|
||||
if (hWsock)
|
||||
{
|
||||
// Determine functions at runtime, because windows systems < XP do not
|
||||
// support getaddrinfo.
|
||||
getaddrinfo_ptr = (getaddrinfo_ptr_t)GetProcAddress(hWsock, "getaddrinfo");
|
||||
freeaddrinfo_ptr = (freeaddrinfo_ptr_t)GetProcAddress(hWsock, "freeaddrinfo");
|
||||
|
||||
if (getaddrinfo_ptr && freeaddrinfo_ptr)
|
||||
{
|
||||
memset(&ainfo, 0, sizeof(ainfo));
|
||||
ainfo.ai_family = AF_INET6;
|
||||
ainfo.ai_socktype = SOCK_STREAM;
|
||||
ainfo.ai_protocol = 0;
|
||||
ainfo.ai_addrlen = sizeof( saddr );
|
||||
ainfo.ai_addr = (struct sockaddr *) &saddr;
|
||||
|
||||
if ( getaddrinfo_ptr(server, 0, &ainfo, &res) == 0);
|
||||
{
|
||||
resolvesuccess = 1;
|
||||
memcpy( &saddr.sin6_addr, res->ai_addr, sizeof( saddr.sin6_addr ) );
|
||||
freeaddrinfo_ptr( res );
|
||||
}
|
||||
}
|
||||
FreeLibrary(hWsock);
|
||||
}
|
||||
if (!resolvesuccess)
|
||||
{
|
||||
session->lasterror = LIBIRC_ERR_RESOLV;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
#else
|
||||
if ( inet_pton( AF_INET6, server, (void*) &saddr.sin6_addr ) <= 0 )
|
||||
{
|
||||
memset( &ainfo, 0, sizeof(ainfo) );
|
||||
ainfo.ai_family = AF_INET6;
|
||||
ainfo.ai_socktype = SOCK_STREAM;
|
||||
ainfo.ai_protocol = 0;
|
||||
ainfo.ai_addrlen = sizeof( saddr );
|
||||
ainfo.ai_addr = (struct sockaddr *) &saddr;
|
||||
|
||||
if ( getaddrinfo( server, 0, &ainfo, &res ) )
|
||||
{
|
||||
session->lasterror = LIBIRC_ERR_RESOLV;
|
||||
return 1;
|
||||
}
|
||||
|
||||
memcpy( &saddr.sin6_addr, res->ai_addr, sizeof( saddr.sin6_addr ) );
|
||||
freeaddrinfo( res );
|
||||
}
|
||||
#endif
|
||||
|
||||
// create the IRC server socket
|
||||
if ( socket_create( PF_INET6, SOCK_STREAM, &session->sock)
|
||||
|| socket_make_nonblocking (&session->sock) )
|
||||
{
|
||||
session->lasterror = LIBIRC_ERR_SOCKET;
|
||||
return 1;
|
||||
}
|
||||
|
||||
// and connect to the IRC server
|
||||
if ( socket_connect (&session->sock, (struct sockaddr *) &saddr, sizeof(saddr)) )
|
||||
{
|
||||
session->lasterror = LIBIRC_ERR_CONNECT;
|
||||
return 1;
|
||||
}
|
||||
|
||||
session->state = LIBIRC_STATE_CONNECTING;
|
||||
session->motd_received = 0; // reset in case of reconnect
|
||||
return 0;
|
||||
#else
|
||||
session->lasterror = LIBIRC_ERR_NOIPV6;
|
||||
return 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
int irc_is_connected (irc_session_t * session)
|
||||
{
|
||||
return (session->state == LIBIRC_STATE_CONNECTED
|
||||
@@ -279,7 +424,7 @@ static void libirc_process_incoming_data (irc_session_t * session, int process_l
|
||||
memcpy (buf, session->incoming_buf, process_length);
|
||||
buf[process_length] = '\0';
|
||||
|
||||
memset (params, 0, sizeof(params));
|
||||
memset ((char *)params, 0, sizeof(params));
|
||||
p = buf;
|
||||
|
||||
/*
|
||||
|
||||
@@ -43,6 +43,7 @@
|
||||
#endif
|
||||
#else
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
#include <windows.h>
|
||||
#include <time.h>
|
||||
#include <stdio.h>
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
* License for more details.
|
||||
*
|
||||
* $Id: sockets.c 53 2004-10-17 11:16:03Z gyunaev $
|
||||
* $Id: sockets.c 53M 2007-09-16 23:57:59Z (local) $
|
||||
*/
|
||||
|
||||
/*
|
||||
@@ -28,8 +28,9 @@
|
||||
typedef int socket_t;
|
||||
|
||||
#else
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
#include <windows.h>
|
||||
#include <winsock.h>
|
||||
|
||||
#define IS_SOCKET_ERROR(a) ((a)==SOCKET_ERROR)
|
||||
|
||||
@@ -37,7 +38,6 @@
|
||||
#define EINPROGRESS WSAEINPROGRESS
|
||||
#define EINTR WSAEINTR
|
||||
|
||||
typedef unsigned int socklen_t;
|
||||
typedef SOCKET socket_t;
|
||||
|
||||
#endif
|
||||
@@ -59,7 +59,7 @@ static int socket_error()
|
||||
|
||||
static int socket_create (int domain, int type, socket_t * sock)
|
||||
{
|
||||
*sock = socket (PF_INET, SOCK_STREAM, 0);
|
||||
*sock = socket (domain, type, 0);
|
||||
return IS_SOCKET_ERROR(*sock) ? 1 : 0;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user