diff options
| -rw-r--r-- | hostport.c | 2 | ||||
| -rw-r--r-- | list.c | 14 | ||||
| -rw-r--r-- | list.h | 12 | ||||
| -rw-r--r-- | radsecproxy.c | 1 | ||||
| -rw-r--r-- | util.c | 45 | ||||
| -rw-r--r-- | util.h | 3 | 
6 files changed, 68 insertions, 9 deletions
| @@ -285,7 +285,7 @@ int connecttcphostlist(struct list *hostports,  struct addrinfo *src) {      for (entry = list_first(hostports); entry; entry = list_next(entry)) {  	hp = (struct hostportres *)entry->data;  	debug(DBG_WARN, "connecttcphostlist: trying to open TCP connection to %s port %s", hp->host, hp->port); -	if ((s = connecttcp(hp->addrinfo, src)) >= 0) { +	if ((s = connecttcp(hp->addrinfo, src, list_count(hostports) > 1 ? 5 : 30)) >= 0) {  	    debug(DBG_WARN, "connecttcphostlist: TCP connection to %s port %s up", hp->host, hp->port);  	    return s;  	} @@ -1,5 +1,5 @@  /* - * Copyright (C) 2006-2008 Stig Venaas <venaas@uninett.no> + * Copyright (C) 2006-2009 Stig Venaas <venaas@uninett.no>   *   * Permission to use, copy, modify, and distribute this software for any   * purpose with or without fee is hereby granted, provided that the above @@ -49,7 +49,8 @@ int list_push(struct list *list, void *data) {      else  	list->first = node;      list->last = node; -     + +    list->count++;      return 1;  } @@ -67,7 +68,7 @@ void *list_shift(struct list *list) {  	list->last = NULL;      data = node->data;      free(node); -     +    list->count--;      return data;  } @@ -82,6 +83,7 @@ void list_removedata(struct list *list, void *data) {      while (node->data == data) {  	list->first = node->next;  	free(node); +	list->count--;  	node = list->first;  	if (!node) {  	    list->last = NULL; @@ -93,6 +95,7 @@ void list_removedata(struct list *list, void *data) {  	    t = node->next;  	    node->next = t->next;  	    free(t); +	    list->count--;  	    if (!node->next) { /* we removed the last one */  		list->last = node;  		return; @@ -109,3 +112,8 @@ struct list_node *list_first(struct list *list) {  struct list_node *list_next(struct list_node *node) {      return node->next;  } + +/* returns number of nodes */ +uint32_t list_count(struct list *list) { +    return list->count; +} @@ -1,11 +1,17 @@  /* - * Copyright (C) 2006-2008 Stig Venaas <venaas@uninett.no> + * Copyright (C) 2006-2009 Stig Venaas <venaas@uninett.no>   *   * Permission to use, copy, modify, and distribute this software for any   * purpose with or without fee is hereby granted, provided that the above   * copyright notice and this permission notice appear in all copies.   */ +#ifdef SYS_SOLARIS9 +#include <sys/inttypes.h> +#else +#include <stdint.h> +#endif +  struct list_node {      struct list_node *next;      void *data; @@ -13,6 +19,7 @@ struct list_node {  struct list {      struct list_node *first, *last; +    uint32_t count;  };  /* allocates and initialises list structure; returns NULL if malloc fails */ @@ -35,3 +42,6 @@ struct list_node *list_first(struct list *list);  /* returns the next node after the argument */  struct list_node *list_next(struct list_node *node); + +/* returns number of nodes */ +uint32_t list_count(struct list *list); diff --git a/radsecproxy.c b/radsecproxy.c index 79625ca..5aae539 100644 --- a/radsecproxy.c +++ b/radsecproxy.c @@ -53,7 +53,6 @@  #endif  #include <sys/time.h>  #include <sys/types.h> -#include <sys/select.h>  #include <ctype.h>  #include <sys/wait.h>  #include <arpa/inet.h> @@ -13,6 +13,9 @@  #include <stdlib.h>  #include <string.h>  #include <unistd.h> +#include <fcntl.h> +#include <errno.h> +#include <sys/select.h>  #include <stdarg.h>  #include "debug.h"  #include "util.h" @@ -157,18 +160,56 @@ int bindtoaddr(struct addrinfo *addrinfo, int family, int reuse, int v6only) {      return -1;  } -int connecttcp(struct addrinfo *addrinfo, struct addrinfo *src) { +int connectnonblocking(int s, const struct sockaddr *addr, socklen_t addrlen, struct timeval *timeout) { +    int origflags, error = 0, r = -1; +    fd_set writefds; +    socklen_t len; +     +    origflags = fcntl(s, F_GETFL, 0); +    fcntl(s, F_SETFL, origflags | O_NONBLOCK); +    if (!connect(s, addr, addrlen)) { +	r = 0; +	goto exit; +    } +    if (errno != EINPROGRESS) +	goto exit; + +    FD_ZERO(&writefds); +    FD_SET(s, &writefds); +    if (select(s + 1, NULL, &writefds, NULL, timeout) < 1) +	goto exit; + +    len = sizeof(error); +    if (!getsockopt(s, SOL_SOCKET, SO_ERROR, (char*)&error, &len) && !error) +	r = 0; + + exit:     +    fcntl(s, F_SETFL, origflags); +    return r; +} + +int connecttcp(struct addrinfo *addrinfo, struct addrinfo *src, uint16_t timeout) {      int s;      struct addrinfo *res; +    struct timeval to;      s = -1; +    if (timeout) { +	if (res && res->ai_next && timeout > 5) +	    timeout = 5; +	to.tv_sec = timeout; +	to.tv_usec = 0; +    } +          for (res = addrinfo; res; res = res->ai_next) {  	s = bindtoaddr(src, res->ai_family, 1, 1);  	if (s < 0) {  	    debug(DBG_WARN, "connecttoserver: socket failed");  	    continue;  	} -	if (connect(s, res->ai_addr, res->ai_addrlen) == 0) +	if ((timeout +	     ? connectnonblocking(s, res->ai_addr, res->ai_addrlen, &to) +	     : connect(s, res->ai_addr, res->ai_addrlen)) == 0)  	    break;  	debug(DBG_WARN, "connecttoserver: connect failed");  	close(s); @@ -16,4 +16,5 @@ void port_set(struct sockaddr *sa, uint16_t port);  void printfchars(char *prefixfmt, char *prefix, char *charfmt, char *chars, int len);  int bindtoaddr(struct addrinfo *addrinfo, int family, int reuse, int v6only); -int connecttcp(struct addrinfo *addrinfo, struct addrinfo *src); +int connecttcp(struct addrinfo *addrinfo, struct addrinfo *src, uint16_t timeout); + | 
