+Thu Nov 29 19:31:23 EET 2001 Pekka Riikonen <priikone@silcnet.org>'
+
+ * Added IPv6 support checking to the configure.in.pre, added
+ also --enable-ipv6 option to override the check. Affected
+ file configure.in.pre.
+
+ * The silc_thread_create now calls the start function
+ directly if threads support is not compiled in. Removes
+ ugly #ifdef's from generic code. Affected files are
+ lib/silcutil/unix/silcunixthread, win32/silcwin32thread.c.
+
+ * Added silc_net_gethostby[name/addr]_async to asynchronously
+ resolve. Affected files are lib/silcutil/silcnet.[ch].
+
+ * Added support for rendering IPv6 based server, client and
+ channel IDs. Affected file lib/silcutil/silcutil.c.
+
+ * Added support for creating IPv6 based server IDs. Affected
+ file is silcd/serverid.c.
+
Wed Nov 28 23:46:09 EET 2001 Pekka Riikonen <priikone@silcnet.org>'
* Added silc_net_gethostby[addr/name] into the
If it is, there is no reason to send it to the router, since the server
knows it best.
- o Incomplete IPv6 support:
-
- o silcd/serverid.c and its routines supports only IPv4.
-
o New configuration file format must be added. The new one will be
done using the dotconf config library (lib/dotconf). The following
tasks relates closely to this as well and must be done at the same time
TODO/bugs In SILC Libraries
===========================
- o Incomplete IPv6 support:
-
- o All network routines in lib/silcutil/silcnet.[ch] does not
- support IPv6.
- o silc_id_render supports only IPv4 based ID's in the file
- lib/silcutil/silcutil.c.
-
- o Add silc_net_gethostbyname, silc_net_gethostbyaddr,
- silc_net_gethostbyname_async and silc_net_gethostbyaddr_async functions.
+ o See client library TODO/bugs
TODO/Bugs in native WIN32 support (libraries)
#undef SILC_THREADS
#undef SILC_HAVE_PTHREAD
+/* IPv6 support */
+#undef HAVE_IPV6
+
/* Default paths */
#undef SILC_ETCDIR
#undef SILC_HELPDIR
silc_net_set_socket_nonblock(sock[i]);
server->sock = sock[i];
+ /* Add ourselves also to the socket table. The entry allocated above
+ is sent as argument for fast referencing in the future. */
+ silc_socket_alloc(sock[i], SILC_SOCKET_TYPE_SERVER, NULL, &newsocket);
+ server->sockets[sock[i]] = newsocket;
+
+ /* Perform name and address lookups to resolve the listenning address
+ and port. */
+ if (!silc_net_check_local_by_sock(sock[i], &newsocket->hostname,
+ &newsocket->ip)) {
+ if ((server->params->require_reverse_mapping && !newsocket->hostname) ||
+ !newsocket->ip) {
+ SILC_LOG_ERROR(("IP/DNS lookup failed for local host %s",
+ newsocket->hostname ? newsocket->hostname :
+ newsocket->ip ? newsocket->ip : ""));
+ server->stat.conn_failures++;
+ goto err0;
+ }
+ if (!newsocket->hostname)
+ newsocket->hostname = strdup(newsocket->ip);
+ }
+ newsocket->port = silc_net_get_local_port(sock[i]);
+
/* Create a Server ID for the server. */
- silc_id_create_server_id(sock[i], server->rng, &id);
- if (!id) {
+ silc_id_create_server_id(newsocket->ip, newsocket->port, server->rng, &id);
+ if (!id)
goto err0;
- }
server->id = id;
server->id_string = silc_id_id2str(id, SILC_ID_SERVER);
}
id_entry->data.status |= SILC_IDLIST_STATUS_REGISTERED;
- /* Add ourselves also to the socket table. The entry allocated above
- is sent as argument for fast referencing in the future. */
- silc_socket_alloc(sock[i], SILC_SOCKET_TYPE_SERVER, id_entry,
- &newsocket);
-
- server->sockets[sock[i]] = newsocket;
-
- /* Perform name and address lookups to resolve the listenning address
- and port. */
- if (!silc_net_check_local_by_sock(sock[i], &newsocket->hostname,
- &newsocket->ip)) {
- if ((server->params->require_reverse_mapping && !newsocket->hostname) ||
- !newsocket->ip) {
- SILC_LOG_ERROR(("IP/DNS lookup failed for local host %s",
- newsocket->hostname ? newsocket->hostname :
- newsocket->ip ? newsocket->ip : ""));
- server->stat.conn_failures++;
- goto err0;
- }
- if (!newsocket->hostname)
- newsocket->hostname = strdup(newsocket->ip);
- }
- newsocket->port = silc_net_get_local_port(sock[i]);
-
/* Put the allocated socket pointer also to the entry allocated above
for fast back-referencing to the socket list. */
- id_entry->connection = (void *)server->sockets[sock[i]];
+ newsocket->user_data = (void *)id_entry;
+ id_entry->connection = (void *)newsocket;
server->id_entry = id_entry;
}
/* Creates a Server ID. Newly created Server ID is returned to the
new_id argument. */
-void silc_id_create_server_id(int sock, SilcRng rng, SilcServerID **new_id)
+void silc_id_create_server_id(const char *ip, uint16 port, SilcRng rng,
+ SilcServerID **new_id)
{
- struct sockaddr_in server;
- int rval, len;
-
SILC_LOG_DEBUG(("Creating new Server ID"));
*new_id = silc_calloc(1, sizeof(**new_id));
- /* Get IP address */
- len = sizeof(server);
- rval = getsockname(sock, (struct sockaddr *)&server, &len);
- if (rval < 0) {
- SILC_LOG_ERROR(("Could not get IP address: %s", strerror(errno)));
+ /* Create the ID */
+
+ if (!silc_net_addr2bin(ip, (*new_id)->ip.data,
+ sizeof((*new_id)->ip.data))) {
silc_free(*new_id);
*new_id = NULL;
return;
}
- /* Create the ID */
- /* XXX Does not support IPv6 */
- memcpy((*new_id)->ip.data, &server.sin_addr.s_addr, 4);
- (*new_id)->ip.data_len = 4;
- (*new_id)->port = server.sin_port;
+ (*new_id)->ip.data_len = silc_net_is_ip4(ip) ? 4 : 16;
+ (*new_id)->port = htons(port);
(*new_id)->rnd = silc_rng_get_rn16(rng);
SILC_LOG_DEBUG(("New ID (%s)", silc_id_render(*new_id, SILC_ID_SERVER)));
#define SERVERID_H
/* Prototypes */
-void silc_id_create_server_id(int sock, SilcRng rng, SilcServerID **new_id);
+void silc_id_create_server_id(const char *ip, uint16 port, SilcRng rng,
+ SilcServerID **new_id);
bool silc_id_create_client_id(SilcServer server,
SilcServerID *server_id, SilcRng rng,
SilcHash md5hash, char *nickname,
AM_CONDITIONAL(SILC_WIN32, test x$win32-support = xtrue)
+#
+# IPv6 support
+#
+AC_MSG_CHECKING(for IPv6 support)
+AC_ARG_ENABLE(ipv6,
+[ --enable-ipv6 Enable IPv6 support],
+[ case "${enableval}" in
+ yes)
+ want_ipv6=true
+ check_ipv6=false
+ AC_DEFINE(HAVE_IPV6)
+ AC_MSG_RESULT(yes)
+ ;;
+ *)
+ want_ipv6=false
+ check_ipv6=false
+ AC_MSG_RESULT(no)
+ ;;
+esac ], check_ipv6=true)
+
+if test x$check_ipv6 = xtrue; then
+ AC_TRY_COMPILE([#ifdef HAVE_NETINET_TCP_H
+ #include <netinet/tcp.h>
+ #endif
+ #ifdef HAVE_NETDB_H
+ #include <netdb.h>
+ #endif
+ #include <sys/socket.h>
+ #ifdef HAVE_NETDB_IN_H
+ #include <netinet/in.h>
+ #endif],
+ [struct sockaddr_in6 sin6;
+ int family = AF_INET6;
+ ], [AC_DEFINE(HAVE_IPV6)
+ AC_MSG_RESULT(yes)], [AC_MSG_RESULT(no)])
+fi
+
#
# Debug checking
#
AC_MSG_CHECKING(for enabled debugging)
AC_ARG_ENABLE(debug,
-[ --enable-debug Enable debugging (warning: it is heavy!)],
+[ --enable-debug Enable debugging],
[ case "${enableval}" in
yes)
AC_MSG_RESULT(yes)
/* SILC util library includes */
#include "silcmutex.h"
#include "silcthread.h"
+#include "silcschedule.h"
#include "silchashtable.h"
#include "silclog.h"
#include "silcmemory.h"
#include "silcnet.h"
#include "silcutil.h"
#include "silcconfig.h"
-#include "silcschedule.h"
#include "silcprotocol.h"
#include "silcsockconn.h"
return silc_net_is_ip6(addr);
}
+/* Internal context for async resolving */
+typedef struct {
+ SilcNetResolveCallback completion;
+ void *context;
+ SilcSchedule schedule;
+ char *input;
+ char *result;
+} *SilcNetResolveContext;
+
+SILC_TASK_CALLBACK(silc_net_resolve_completion)
+{
+ SilcNetResolveContext r = (SilcNetResolveContext)context;
+
+ /* Call the completion callback */
+ if (r->completion)
+ (*r->completion)(r->result, r->context);
+
+ silc_free(r->input);
+ silc_free(r->result);
+ silc_free(r);
+}
+
+/* Thread function to resolve the address for hostname. */
+
+static void *silc_net_gethostbyname_thread(void *context)
+{
+ SilcNetResolveContext r = (SilcNetResolveContext)context;
+ char tmp[64];
+
+ if (silc_net_gethostbyname(r->input, tmp, sizeof(tmp)))
+ r->result = strdup(tmp);
+
+ silc_schedule_task_add(r->schedule, 0, silc_net_resolve_completion, r, 0, 1,
+ SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
+ silc_schedule_wakeup(r->schedule);
+ return NULL;
+}
+
+/* Thread function to resolve the hostname for address. */
+
+static void *silc_net_gethostbyaddr_thread(void *context)
+{
+ SilcNetResolveContext r = (SilcNetResolveContext)context;
+ char tmp[256];
+
+ if (silc_net_gethostbyaddr(r->input, tmp, sizeof(tmp)))
+ r->result = strdup(tmp);
+
+ silc_schedule_task_add(r->schedule, 0, silc_net_resolve_completion, r, 0, 1,
+ SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
+ silc_schedule_wakeup(r->schedule);
+ return NULL;
+}
+
/* Resolves IP address for hostname. */
bool silc_net_gethostbyname(const char *name, char *address,
return TRUE;
}
+/* Resolves IP address for hostname async. */
+
+void silc_net_gethostbyname_async(const char *name,
+ SilcSchedule schedule,
+ SilcNetResolveCallback completion,
+ void *context)
+{
+ SilcNetResolveContext r = silc_calloc(1, sizeof(*r));
+
+ r->completion = completion;
+ r->context = context;
+ r->schedule = schedule;
+ r->input = strdup(name);
+
+ silc_thread_create(silc_net_gethostbyname_thread, r, FALSE);
+}
+
/* Resolves hostname by IP address. */
bool silc_net_gethostbyaddr(const char *addr, char *name, uint32 name_len)
return TRUE;
}
+/* Resolves hostname by IP address async. */
+
+void silc_net_gethostbyaddr_async(const char *addr,
+ SilcSchedule schedule,
+ SilcNetResolveCallback completion,
+ void *context)
+{
+ SilcNetResolveContext r = silc_calloc(1, sizeof(*r));
+
+ r->completion = completion;
+ r->context = context;
+ r->schedule = schedule;
+ r->input = strdup(addr);
+
+ silc_thread_create(silc_net_gethostbyaddr_thread, r, FALSE);
+}
+
/* Performs lookups for remote name and IP address. This peforms reverse
lookup as well to verify that the IP has FQDN. */
***/
bool silc_net_addr2bin(const char *addr, void *bin, uint32 bin_len);
+/****f* silcutil/SilcNetAPI/SilcNetResolveCallback
+ *
+ * SYNOPSIS
+ *
+ * typedef void (*SilcNetResolveCallback)(const char *result,
+ * void *context);
+ *
+ * DESCRIPTION
+ *
+ * A callback function of this type is called after the asynchronous
+ * resolving operation has been completed. This callback is used
+ * when asynchronously resolving IP addresses and hostnames.
+ *
+ ***/
+typedef void (*SilcNetResolveCallback)(const char *result, void *context);
+
/****f* silcutil/SilcNetAPI/silc_net_gethostbyname
*
* SYNOPSIS
*
* DESCRIPTION
*
- * Resolves the IP address of the hostname indicated by the `host'
+ * Resolves the IP address of the hostname indicated by the `host'.
* This returns TRUE and the IP address of the host, or FALSE
* if the address could not be resolved. This is synchronous
* function and will block the calling process.
bool silc_net_gethostbyname(const char *name, char *address,
uint32 address_len);
+/****f* silcutil/SilcNetAPI/silc_net_gethostbyname_async
+ *
+ * SYNOPSIS
+ *
+ * void silc_net_gethostbyname_async(const char *name,
+ * SilcSchedule schedule,
+ * SilcNetResolveCallback completion,
+ * void *context)
+ *
+ * DESCRIPTION
+ *
+ * Asynchronouosly resolves the IP address of the hostname indicated
+ * by the `host'. This function returns immediately, and the
+ * `completion' callback will be called after the resolving is
+ * completed.
+ *
+ ***/
+void silc_net_gethostbyname_async(const char *name,
+ SilcSchedule schedule,
+ SilcNetResolveCallback completion,
+ void *context);
+
/****f* silcutil/SilcNetAPI/silc_net_gethostbyaddr
*
* SYNOPSIS
*
* DESCRIPTION
*
- * Resolves the hostname of the IP address indicated by the `addr'
+ * Resolves the hostname for the IP address indicated by the `addr'
* This returns TRUE and the resolved hostname, or FALSE on error.
* The `addr' may be either IPv4 or IPv6 address. This is
* synchronous function and will block the calling process.
***/
bool silc_net_gethostbyaddr(const char *addr, char *name, uint32 name_len);
+/****f* silcutil/SilcNetAPI/silc_net_gethostbyaddr_async
+ *
+ * SYNOPSIS
+ *
+ * void silc_net_gethostbyaddr_async(const char *addr,
+ * SilcSchedule schedule,
+ * SilcNetResolveCallback completion,
+ * void *context)
+ *
+ * DESCRIPTION
+ *
+ * Asynchronouosly resolves the hostname for the IP address indicated
+ * by the `addr'. This function returns immediately, and the
+ * `completion' callback will be called after the resolving is
+ * completed.
+ *
+ ***/
+void silc_net_gethostbyaddr_async(const char *addr,
+ SilcSchedule schedule,
+ SilcNetResolveCallback completion,
+ void *context);
+
/****f* silcutil/SilcNetAPI/silc_net_check_host_by_sock
*
* SYNOPSIS
lookup->port = port_lookup;
SILC_SET_HOST_LOOKUP(sock);
-
-#ifdef SILC_THREADS
silc_thread_create(silc_socket_host_lookup_start, lookup, FALSE);
-#else
- silc_socket_host_lookup_start((void *)lookup);
-#endif
}
case SILC_ID_SERVER:
{
SilcServerID *server_id = (SilcServerID *)id;
- struct in_addr ipv4;
-
if (server_id->ip.data_len > 4) {
-
+#ifdef HAVE_IPV6
+ struct in6_addr ipv6;
+ memmove(&ipv6, server_id->ip.data, sizeof(ipv6));
+ if (!inet_ntop(AF_INET6, &ipv6, tmp, sizeof(tmp)))
+ strcat(rid, tmp);
+#endif
} else {
- memcpy(&ipv4.s_addr, server_id->ip.data, 4);
+ struct in_addr ipv4;
+ memmove(&ipv4.s_addr, server_id->ip.data, 4);
strcat(rid, inet_ntoa(ipv4));
}
case SILC_ID_CLIENT:
{
SilcClientID *client_id = (SilcClientID *)id;
- struct in_addr ipv4;
-
if (client_id->ip.data_len > 4) {
-
+#ifdef HAVE_IPV6
+ struct in6_addr ipv6;
+ memmove(&ipv6, client_id->ip.data, sizeof(ipv6));
+ if (!inet_ntop(AF_INET6, &ipv6, tmp, sizeof(tmp)))
+ strcat(rid, tmp);
+#endif
} else {
- memcpy(&ipv4.s_addr, client_id->ip.data, 4);
+ struct in_addr ipv4;
+ memmove(&ipv4.s_addr, client_id->ip.data, 4);
strcat(rid, inet_ntoa(ipv4));
}
case SILC_ID_CHANNEL:
{
SilcChannelID *channel_id = (SilcChannelID *)id;
- struct in_addr ipv4;
-
if (channel_id->ip.data_len > 4) {
-
+#ifdef HAVE_IPV6
+ struct in6_addr ipv6;
+ memmove(&ipv6, channel_id->ip.data, sizeof(ipv6));
+ if (!inet_ntop(AF_INET6, &ipv6, tmp, sizeof(tmp)))
+ strcat(rid, tmp);
+#endif
} else {
- memcpy(&ipv4.s_addr, channel_id->ip.data, 4);
+ struct in_addr ipv4;
+ memmove(&ipv4.s_addr, channel_id->ip.data, 4);
strcat(rid, inet_ntoa(ipv4));
}
#include "silcincludes.h"
-#ifdef SILC_THREADS
-
SilcThread silc_thread_create(SilcThreadStart start_func, void *context,
bool waitable)
{
+#ifdef SILC_THREADS
pthread_attr_t attr;
pthread_t thread;
int ret;
SILC_LOG_DEBUG(("Created thread %p", (SilcThread)thread));
return (SilcThread)thread;
+#else
+ /* Call thread callback immediately */
+ (*start_func)(context);
+ return NULL;
+#endif
}
void silc_thread_exit(void *exit_value)
{
+#ifdef SILC_THREADS
pthread_exit(exit_value);
+#endif
}
SilcThread silc_thread_self(void)
{
+#ifdef SILC_THREADS
pthread_t self = pthread_self();
return (SilcThread)self;
+#else
+ return NULL;
+#endif
}
bool silc_thread_wait(SilcThread thread, void **exit_value)
{
+#ifdef SILC_THREADS
SILC_LOG_DEBUG(("Waiting for thread %p", thread));
if (!pthread_join(*(pthread_t *)thread, exit_value))
return TRUE;
return FALSE;
+#else
+ return FALSE;
+#endif
}
-
-#endif /* SILC_THREADS */
return 0;
}
+#endif
SilcThread silc_thread_create(SilcThreadStart start_func, void *context,
bool waitable)
{
+#ifdef SILC_THREADS
SilcWin32Thread thread;
unsigned id;
}
return (SilcThread)thread;
+#else
+ /* Call thread callback immediately */
+ (*start_func)(context);
+ return NULL;
+#endif
}
void silc_thread_exit(void *exit_value)
{
+#ifdef SILC_THREADS
SilcWin32Thread thread = TlsGetValue(silc_thread_tls);
if (thread) {
}
_endthreadex(0);
+#endif
}
SilcThread silc_thread_self(void)
{
+#ifdef SILC_THREADS
SilcWin32Thread self = TlsGetValue(silc_thread_tls);
if (!self) {
}
return (SilcThread)self;
+#else
+ return NULL;
+#endif
}
bool silc_thread_wait(SilcThread thread, void **exit_value)
{
+#ifdef SILC_THREADS
SilcWin32Thread self = (SilcWin32Thread)thread;
SILC_LOG_DEBUG(("Waiting for thread %p", self));
*exit_value = NULL;
return TRUE;
+#else
+ return FALSE;
+#endif
}
-
-#endif /* SILC_THREADS */