+Sat Feb 23 20:31:43 EET 2002 Pekka Riikonen <priikone@silcnet.org>
+
+ * Added `prefer_ipv6' argument to the functions
+ silc_net_gethostbyname[_async]. If it is TRUE it will return
+ IPv6 address over IPv4. If FALSE IPv4 address is returned
+ even if IPv6 address was found. Affected files
+ lib/silcutil/silcnet.[ch].
+
+ * Added support silc_net_create_connection[_async] to fallback
+ to IPv4 address if IPv6 address could not be used (like if
+ it doesn't work on a specific system). Affected file in
+ lib/silcutil/unix/silcunixnet.c.
+
+Sat Feb 23 15:20:30 EET 2002 Pekka Riikonen <priikone@silcnet.org>
+
+ * Added silc_schedule_reinit function to do the enlarging
+ of the max tasks handling capabilities of the scheduler.
+ Affected files lib/silcutil/silcschedule.[ch].
+
Wed Feb 20 20:41:01 EET 2002 Pekka Riikonen <priikone@silcnet.org>
* Added automatic extern "C" { ... } for C++ compilers so the
TODO/bugs In SILC Server
========================
+ o Remove old 0.6.x backwards support.
+
o Configuration file additions:
o Add incoming connection frequency, incoming connection frequency
lib/silcutil/Makefile
lib/silcutil/unix/Makefile
lib/silcutil/win32/Makefile
+lib/silcutil/beos/Makefile
+lib/silcutil/os2/Makefile
+lib/silcutil/epoc/Makefile
lib/silcsftp/Makefile
lib/silcsftp/tests/Makefile
doc/example_silcd.conf
</tt>
<br /> <br />
-Also defines (#define) are always capitalised and include underscores to
-separate words in the name. Also all defines start with the "SILC_" prefix.
+Also other defines (#define) are always capitalised and include
+underscores to separate words in the name. Also all defines start with
+the "SILC_" prefix.
<br /> <br />
<b>Structures</b>
*
* DESCRIPTION
*
- * Processes and decrypts the incmoing data, and calls parser callback
+ * Processes and decrypts the incoming data, and calls parser callback
* for each received packet that will handle the actual packet parsing.
* If more than one packet was received this calls the parser multiple
* times. The parser callback will get context SilcPacketParserContext
typedef struct {
SilcNetResolveCallback completion;
void *context;
+ bool prefer_ipv6;
SilcSchedule schedule;
char *input;
char *result;
SilcNetResolveContext r = (SilcNetResolveContext)context;
char tmp[64];
- if (silc_net_gethostbyname(r->input, tmp, sizeof(tmp)))
+ if (silc_net_gethostbyname(r->input, r->prefer_ipv6, tmp, sizeof(tmp)))
r->result = strdup(tmp);
silc_schedule_task_add(r->schedule, 0, silc_net_resolve_completion, r, 0, 1,
/* Resolves IP address for hostname. */
-bool silc_net_gethostbyname(const char *name, char *address,
+bool silc_net_gethostbyname(const char *name, bool prefer_ipv6, char *address,
uint32 address_len)
{
#ifdef HAVE_IPV6
- struct addrinfo hints, *ai;
+ struct addrinfo hints, *ai, *tmp, *ip4 = NULL, *ip6 = NULL;
memset(&hints, 0, sizeof(hints));
hints.ai_socktype = SOCK_STREAM;
if (getaddrinfo(name, NULL, &hints, &ai))
return FALSE;
- if (getnameinfo(ai->ai_addr, ai->ai_addrlen, address,
- address_len, NULL, 0, NI_NUMERICHOST)) {
+ for (tmp = ai; tmp; tmp = tmp->ai_next) {
+ if (tmp->ai_family == AF_INET6) {
+ ip6 = tmp;
+ if (ip4)
+ break;
+ continue;
+ }
+ if (tmp->ai_family == AF_INET) {
+ ip4 = tmp;
+ if (ip6)
+ break;
+ continue;
+ }
+ }
+
+ tmp = (prefer_ipv6 ? (ip6 ? ip6 : ip4) : (ip4 ? ip4 : ip6));
+ if (!tmp) {
freeaddrinfo(ai);
return FALSE;
- } else {
+ }
+
+ if (getnameinfo(tmp->ai_addr, tmp->ai_addrlen, address,
+ address_len, NULL, 0, NI_NUMERICHOST)) {
freeaddrinfo(ai);
+ return FALSE;
}
+
+ freeaddrinfo(ai);
#else
struct hostent *hp;
struct in_addr ip;
/* Resolves IP address for hostname async. */
void silc_net_gethostbyname_async(const char *name,
+ bool prefer_ipv6,
SilcSchedule schedule,
SilcNetResolveCallback completion,
void *context)
r->completion = completion;
r->context = context;
+ r->prefer_ipv6 = prefer_ipv6;
r->schedule = schedule;
r->input = strdup(name);
if (gethostname(hostname, sizeof(hostname)))
return NULL;
- if (!silc_net_gethostbyname(hostname, ip_addr, sizeof(ip_addr)))
+ if (!silc_net_gethostbyname(hostname, TRUE, ip_addr, sizeof(ip_addr)))
return strdup(hostname);
silc_net_gethostbyaddr(ip_addr, hostname, sizeof(hostname));
if (gethostname(hostname, sizeof(hostname)))
return NULL;
- if (!silc_net_gethostbyname(hostname, ip_addr, sizeof(ip_addr)))
+ if (!silc_net_gethostbyname(hostname, TRUE, ip_addr, sizeof(ip_addr)))
return NULL;
return strdup(ip_addr);
*
* SYNOPSIS
*
- * bool silc_net_gethostbyname(const char *name, char *address,
- * uint32 address_len);
+ * bool silc_net_gethostbyname(const char *name, bool prefer_ipv6,
+ * char *address, uint32 address_len);
*
* DESCRIPTION
*
- * 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.
+ * Resolves the IP address of the hostname indicated by the `name'.
+ * This returns TRUE and the IP address of the host to the `address'
+ * buffer, or FALSE if the address could not be resolved. This is
+ * synchronous function and will block the calling process. If the
+ * `prefer_ipv6' is TRUE then this will return IPv6 address if it
+ * finds. If FALSE if returns IPv4 address even if it found IPv6
+ * address also.
*
***/
-bool silc_net_gethostbyname(const char *name, char *address,
+bool silc_net_gethostbyname(const char *name, bool prefer_ipv6, char *address,
uint32 address_len);
/****f* silcutil/SilcNetAPI/silc_net_gethostbyname_async
* SYNOPSIS
*
* void silc_net_gethostbyname_async(const char *name,
+ * bool prefer_ipv6,
* SilcSchedule schedule,
* SilcNetResolveCallback completion,
* void *context)
* DESCRIPTION
*
* Asynchronously resolves the IP address of the hostname indicated
- * by the `host'. This function returns immediately, and the
+ * by the `name'. This function returns immediately, and the
* `completion' callback will be called after the resolving is
* completed.
*
+ * If the `prefer_ipv6' is TRUE then this will return IPv6 address if it
+ * finds. If FALSE if returns IPv4 address even if it found IPv6
+ * address also.
+ *
***/
void silc_net_gethostbyname_async(const char *name,
+ bool prefer_ipv6,
SilcSchedule schedule,
SilcNetResolveCallback completion,
void *context);
* DESCRIPTION
*
* 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.
+ * This returns TRUE and the resolved hostname to the `name' buffer,
+ * 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);
return TRUE;
}
+/* Enlarge the capabilities of the scheduler to handle tasks to `max_tasks'. */
+
+bool silc_schedule_reinit(SilcSchedule schedule, int max_tasks)
+{
+ silc_mutex_lock(schedule->lock);
+ if (schedule->max_fd <= max_tasks)
+ return FALSE;
+ schedule->fd_list = silc_realloc(schedule->fd_list,
+ (sizeof(*schedule->fd_list) * max_tasks));
+ schedule->max_fd = max_tasks;
+ silc_mutex_unlock(schedule->lock);
+ return TRUE;
+}
+
/* Stops the schedule even if it is not supposed to be stopped yet.
After calling this, one should call silc_schedule_uninit (after the
silc_schedule has returned). */
***/
bool silc_schedule_uninit(SilcSchedule schedule);
+/****f* silcutil/SilcScheduleAPI/silc_schedule_reinit
+ *
+ * SYNOPSIS
+ *
+ * SilcSchedule silc_schedule_reinit(int max_tasks);
+ *
+ * DESCRIPTION
+ *
+ * This function can be called to enlarge the task handling capabilities
+ * of the scheduler indicated by `schedule'. The `max_tasks' must be
+ * larger than what was set in silc_schedule_init function. This function
+ * returns FALSE if it cannot reinit the scheduler. This function does
+ * not do anything else except ready the scheduler to handle `max_tasks'
+ * number of tasks after this function returns. It is safe to call this
+ * function at any time, and it is guaranteed that existing tasks remain
+ * as they are in the scheduler.
+ *
+ ***/
+bool silc_schedule_reinit(SilcSchedule schedule, int max_tasks);
+
/****f* silcutil/SilcScheduleAPI/silc_schedule_stop
*
* SYNOPSIS
int sock, rval;
char ip_addr[64];
SilcSockaddr desthost;
+ bool prefer_ipv6 = TRUE;
SILC_LOG_DEBUG(("Creating connection to host %s port %d", host, port));
/* Do host lookup */
- if (!silc_net_gethostbyname(host, ip_addr, sizeof(ip_addr))) {
+ retry:
+ if (!silc_net_gethostbyname(host, prefer_ipv6, ip_addr, sizeof(ip_addr))) {
SILC_LOG_ERROR(("Network (%s) unreachable: could not resolve the "
"IP address", host));
return -1;
/* Create the connection socket */
sock = socket(desthost.sin.sin_family, SOCK_STREAM, 0);
if (sock < 0) {
+ /* If address is IPv6, then fallback to IPv4 and see whether we can do
+ better with that on socket creation. */
+ if (prefer_ipv6 && silc_net_is_ip6(ip_addr)) {
+ prefer_ipv6 = FALSE;
+ goto retry;
+ }
+
SILC_LOG_ERROR(("Cannot create socket: %s", strerror(errno)));
return -1;
}
int sock, rval;
char ip_addr[64];
SilcSockaddr desthost;
+ bool prefer_ipv6 = TRUE;
SILC_LOG_DEBUG(("Creating connection (async) to host %s port %d",
host, port));
/* Do host lookup */
- if (!silc_net_gethostbyname(host, ip_addr, sizeof(ip_addr))) {
+ retry:
+ if (!silc_net_gethostbyname(host, prefer_ipv6, ip_addr, sizeof(ip_addr))) {
SILC_LOG_ERROR(("Network (%s) unreachable: could not resolve the "
"IP address", host));
return -1;
/* Create the connection socket */
sock = socket(desthost.sin.sin_family, SOCK_STREAM, 0);
if (sock < 0) {
+ /* If address is IPv6, then fallback to IPv4 and see whether we can do
+ better with that on socket creation. */
+ if (prefer_ipv6 && silc_net_is_ip6(ip_addr)) {
+ prefer_ipv6 = FALSE;
+ goto retry;
+ }
+
SILC_LOG_ERROR(("Cannot create socket: %s", strerror(errno)));
return -1;
}