From 99865727f85eb96f5462158eed8dc935710d1a0b Mon Sep 17 00:00:00 2001 From: Pekka Riikonen Date: Thu, 29 Nov 2001 19:07:44 +0000 Subject: [PATCH] updates. --- CHANGES | 20 +++++++ TODO | 14 +---- acconfig.h.pre | 3 + apps/silcd/server.c | 54 ++++++++--------- apps/silcd/serverid.c | 22 +++---- apps/silcd/serverid.h | 3 +- configure.in.pre | 39 +++++++++++- includes/silcincludes.h | 2 +- lib/silcutil/silcnet.c | 88 ++++++++++++++++++++++++++++ lib/silcutil/silcnet.h | 64 +++++++++++++++++++- lib/silcutil/silcsockconn.c | 5 -- lib/silcutil/silcutil.c | 36 ++++++++---- lib/silcutil/unix/silcunixthread.c | 20 +++++-- lib/silcutil/win32/silcwin32thread.c | 19 +++++- 14 files changed, 306 insertions(+), 83 deletions(-) diff --git a/CHANGES b/CHANGES index 84a339e2..84e615f0 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,23 @@ +Thu Nov 29 19:31:23 EET 2001 Pekka Riikonen ' + + * 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 ' * Added silc_net_gethostby[addr/name] into the diff --git a/TODO b/TODO index eb752293..3149ab18 100644 --- a/TODO +++ b/TODO @@ -87,10 +87,6 @@ TODO/bugs In SILC Server 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 @@ -114,15 +110,7 @@ TODO/bugs In SILC Server 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) diff --git a/acconfig.h.pre b/acconfig.h.pre index a1649da8..d8a1fcca 100644 --- a/acconfig.h.pre +++ b/acconfig.h.pre @@ -17,6 +17,9 @@ #undef SILC_THREADS #undef SILC_HAVE_PTHREAD +/* IPv6 support */ +#undef HAVE_IPV6 + /* Default paths */ #undef SILC_ETCDIR #undef SILC_HELPDIR diff --git a/apps/silcd/server.c b/apps/silcd/server.c index 4543cc28..c831c158 100644 --- a/apps/silcd/server.c +++ b/apps/silcd/server.c @@ -222,11 +222,32 @@ int silc_server_init(SilcServer server) 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); @@ -248,33 +269,10 @@ int silc_server_init(SilcServer 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; } diff --git a/apps/silcd/serverid.c b/apps/silcd/serverid.c index 2d153f32..05cf1b35 100644 --- a/apps/silcd/serverid.c +++ b/apps/silcd/serverid.c @@ -25,30 +25,24 @@ /* 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))); diff --git a/apps/silcd/serverid.h b/apps/silcd/serverid.h index 4a81a4a4..9873ec2d 100644 --- a/apps/silcd/serverid.h +++ b/apps/silcd/serverid.h @@ -22,7 +22,8 @@ #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, diff --git a/configure.in.pre b/configure.in.pre index 82762d44..d7722afa 100644 --- a/configure.in.pre +++ b/configure.in.pre @@ -611,12 +611,49 @@ AC_ARG_WITH(win32, 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 + #endif + #ifdef HAVE_NETDB_H + #include + #endif + #include + #ifdef HAVE_NETDB_IN_H + #include + #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) diff --git a/includes/silcincludes.h b/includes/silcincludes.h index 7ee3c0d0..9117082c 100644 --- a/includes/silcincludes.h +++ b/includes/silcincludes.h @@ -233,6 +233,7 @@ typedef uint32 * void *; /* SILC util library includes */ #include "silcmutex.h" #include "silcthread.h" +#include "silcschedule.h" #include "silchashtable.h" #include "silclog.h" #include "silcmemory.h" @@ -242,7 +243,6 @@ typedef uint32 * void *; #include "silcnet.h" #include "silcutil.h" #include "silcconfig.h" -#include "silcschedule.h" #include "silcprotocol.h" #include "silcsockconn.h" diff --git a/lib/silcutil/silcnet.c b/lib/silcutil/silcnet.c index f7795865..272e7e30 100644 --- a/lib/silcutil/silcnet.c +++ b/lib/silcutil/silcnet.c @@ -87,6 +87,60 @@ bool silc_net_is_ip(const char *addr) 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, @@ -131,6 +185,23 @@ 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) @@ -165,6 +236,23 @@ 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. */ diff --git a/lib/silcutil/silcnet.h b/lib/silcutil/silcnet.h index 69f49221..7089acb2 100644 --- a/lib/silcutil/silcnet.h +++ b/lib/silcutil/silcnet.h @@ -232,6 +232,22 @@ bool silc_net_is_ip(const char *addr); ***/ 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 @@ -241,7 +257,7 @@ bool silc_net_addr2bin(const char *addr, void *bin, uint32 bin_len); * * 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. @@ -250,6 +266,28 @@ bool silc_net_addr2bin(const char *addr, void *bin, uint32 bin_len); 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 @@ -259,7 +297,7 @@ bool silc_net_gethostbyname(const char *name, char *address, * * 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. @@ -267,6 +305,28 @@ bool silc_net_gethostbyname(const char *name, char *address, ***/ 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 diff --git a/lib/silcutil/silcsockconn.c b/lib/silcutil/silcsockconn.c index 942b30d8..d722cd0d 100644 --- a/lib/silcutil/silcsockconn.c +++ b/lib/silcutil/silcsockconn.c @@ -224,10 +224,5 @@ void silc_socket_host_lookup(SilcSocketConnection sock, 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 } diff --git a/lib/silcutil/silcutil.c b/lib/silcutil/silcutil.c index c37ec4e5..15ad5eab 100644 --- a/lib/silcutil/silcutil.c +++ b/lib/silcutil/silcutil.c @@ -539,12 +539,16 @@ char *silc_id_render(void *id, uint16 type) 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)); } @@ -560,12 +564,16 @@ char *silc_id_render(void *id, uint16 type) 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)); } @@ -582,12 +590,16 @@ char *silc_id_render(void *id, uint16 type) 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)); } diff --git a/lib/silcutil/unix/silcunixthread.c b/lib/silcutil/unix/silcunixthread.c index 7751603f..575c54a8 100644 --- a/lib/silcutil/unix/silcunixthread.c +++ b/lib/silcutil/unix/silcunixthread.c @@ -21,11 +21,10 @@ #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; @@ -61,25 +60,38 @@ SilcThread silc_thread_create(SilcThreadStart start_func, void *context, 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 */ diff --git a/lib/silcutil/win32/silcwin32thread.c b/lib/silcutil/win32/silcwin32thread.c index e88a09f0..6e6a9094 100644 --- a/lib/silcutil/win32/silcwin32thread.c +++ b/lib/silcutil/win32/silcwin32thread.c @@ -49,10 +49,12 @@ unsigned __stdcall silc_thread_win32_start(void *context) return 0; } +#endif SilcThread silc_thread_create(SilcThreadStart start_func, void *context, bool waitable) { +#ifdef SILC_THREADS SilcWin32Thread thread; unsigned id; @@ -71,10 +73,16 @@ SilcThread silc_thread_create(SilcThreadStart start_func, void *context, } 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) { @@ -89,10 +97,12 @@ void silc_thread_exit(void *exit_value) } _endthreadex(0); +#endif } SilcThread silc_thread_self(void) { +#ifdef SILC_THREADS SilcWin32Thread self = TlsGetValue(silc_thread_tls); if (!self) { @@ -107,10 +117,14 @@ SilcThread silc_thread_self(void) } 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)); @@ -127,6 +141,7 @@ bool silc_thread_wait(SilcThread thread, void **exit_value) *exit_value = NULL; return TRUE; +#else + return FALSE; +#endif } - -#endif /* SILC_THREADS */ -- 2.24.0