Two patches

Michel Arboi <[email protected]>
Newsgroups gmane.comp.security.nessus.devel
Message-ID <1052230734.4664.4.camel@rotissoire>
I will not commit those modifications until Renaud opens a "stable"
branch in the CVS repository.

1. array.patch implements a new syntax for NASL _constant_ arrays, like:
	v = [ "one", "two", "three" ];
or
	v = [ "A" => 1, "X" => "???" ];
This new operator is not supposed to replace the make_list() function.
This construction is rejected:
v = [ 1, 2];
w = [ v, 3 ];

2. asyncIO.patch removes the dirty SIGALRM handler in the network
library and replaces it with asynchronous sockets and select()
This has to be TESTED because it is a critical piece of code.
array.patch (text/plain, 7.8 KB)
--- libnasl/doc/nasl2_reference.lyx	7 Apr 2003 10:48:45 -0000	1.24
+++ libnasl/doc/nasl2_reference.lyx	6 May 2003 07:46:15 -0000
@@ -407,7 +407,7 @@
 \layout List
 \labelwidthstring 00.00.0000
 
-instr simple_instr\SpecialChar ~
+instr s_instr\SpecialChar ~
  
 \series bold 
 ;
@@ -422,7 +422,7 @@
 \layout List
 \labelwidthstring 00.00.0000
 
-simple_instr aff
+s_instr aff
 \newline 
 post_pre_incr
 \newline 
@@ -848,6 +848,8 @@
 \newline 
 aff
 \newline 
+cst_array
+\newline 
 ipaddr
 \layout List
 \labelwidthstring 00.00.0000
@@ -1112,6 +1114,42 @@
 \layout List
 \labelwidthstring 00.00.0000
 
+cst_array 
+\series bold 
+[
+\series default 
+ l_array 
+\series bold 
+]
+\layout List
+\labelwidthstring 00.00.0000
+
+l_array array_data
+\newline 
+array_data 
+\series bold 
+,
+\series default 
+ l_array
+\layout List
+\labelwidthstring 00.00.0000
+
+array_data atom
+\newline 
+string 
+\series bold 
+=>
+\series default 
+ atom
+\layout List
+\labelwidthstring 00.00.0000
+
+atom integer
+\newline 
+string
+\layout List
+\labelwidthstring 00.00.0000
+
 loc 
 \series bold 
 local_var
@@ -8629,11 +8667,15 @@
 \end_inset 
 
 .
- It takes an unnamed parameter (the input string) and an optional 
+ It takes an unnamed parameter (the input string), an optional 
 \series bold 
 sep
 \series default 
- string argument; it returns the array.
+ string argument and an optional 
+\series bold 
+keep
+\series default 
+ integer argument; it returns the array.
  
 \newline 
 If 
@@ -8655,9 +8697,25 @@
 \series default 
 .
 \newline 
-Note that the separator (whatever it is) will be included in the sub-strings
- or lines.
+By default
+\begin_inset Foot
+collapsed true
+
+\layout Standard
+
+The keep argument appeared in Nessus 2.0.2; older versions of the NASL library
+ do not recognize it.
+\end_inset 
+
+, the separator (whatever it is) will be included in the sub-strings or
+ lines, unless 
+\series bold 
+keep
+\series default 
+ is set top 
+\series bold 
+0
 \layout Itemize
 
 
--- libnasl/include/nasl.h	7 Jan 2003 01:39:22 -0000	1.7
+++ libnasl/include/nasl.h	6 May 2003 07:46:15 -0000
@@ -10,9 +10,12 @@
  *
  * Level 2000:
  * NASL2
+ *
+ * Level 2200
+ * "Constant arrays" added, e.g. v = [ 'a' => 1, 'x' => 'zzz' ];
  */
-#define NASL_LEVEL 2000
+#define NASL_LEVEL 2200
 
 
 int execute_nasl_script(struct arglist *, char *, int);
--- libnasl/nasl/exec.c	1 Apr 2003 11:10:39 -0000	1.43
+++ libnasl/nasl/exec.c	6 May 2003 07:46:16 -0000
@@ -151,6 +151,7 @@
     {
     case CONST_INT:
       p = malloc(16);
+      if (p != NULL)
       sprintf(p, "%d", c->x.i_val);
       return p;
       
@@ -249,8 +250,7 @@
   int		flag, x1, x2, typ, typ1, typ2;
   char		*s1, *s2;
   int		len_s1, len_s2, len_min;
-  tree_cell	*d1 = NULL, *d2 = NULL;
 
 
 #if NASL_DEBUG >= 0
--- libnasl/nasl/nasl_grammar.y	24 Mar 2003 22:33:50 -0000	1.26
+++ libnasl/nasl/nasl_grammar.y	6 May 2003 07:46:16 -0000
@@ -89,6 +89,7 @@
 %token R_USHIFT_EQ
 %token RE_MATCH
 %token RE_NOMATCH
+%token ARROW
 
 %token <str> IDENT
 %token <str> STRING1
@@ -104,6 +105,7 @@
 %type <node> aff rep ret expr aff_func array_index array_elem lvalue var
 %type <node> ipaddr post_pre_incr
 %type <node> inc loc glob
+%type <node> atom const_array list_array_data array_data simple_array_data
 
 %type <str>  identifier string
 
@@ -122,6 +124,7 @@
 %nonassoc UMINUS BIT_NOT
 %right EXPO
 %nonassoc PLUS_PLUS MINUS_MINUS
+%nonassoc ARROW
 
 %start	tiptop
 
@@ -385,16 +388,36 @@
 	| expr NEQ expr { $$ = alloc_expr_cell(LNB, COMP_NE, $1, $3); }
 	| expr SUPEQ expr { $$ = alloc_expr_cell(LNB, COMP_GE, $1, $3); }
 	| expr INFEQ expr { $$ = alloc_expr_cell(LNB, COMP_LE, $1, $3); }
-	| INTEGER { $$ = alloc_tree_cell(LNB, NULL); $$->x.i_val = $1; $$->type = CONST_INT; }
+	| var | aff | ipaddr | atom | const_array ;
+
+
+const_array:	'[' list_array_data ']' { $$ = make_array_from_elems($2); } ;
+
+list_array_data: array_data { $$ = $1; }
+	| array_data ',' list_array_data {
+		$1->link[1] = $3; $$ = $1;
+	};
+
+array_data: simple_array_data { 
+	  $$ = alloc_typed_cell(ARRAY_ELEM); 
+	  $$->link[0] = $1;
+	} | string ARROW simple_array_data {
+	  $$ = alloc_typed_cell(ARRAY_ELEM);
+	  $$->link[0] = $3;
+	  $$->x.str_val = $1;
+	} ;
+
+atom:	INTEGER {  $$ = alloc_typed_cell(CONST_INT); $$->x.i_val = $1; }
 	| STRING2 { 
-	  $$ = alloc_tree_cell(LNB, NULL); $$->x.str_val = $1;
-	  $$->type = CONST_STR; $$->size = strlen($1);
+	  $$ = alloc_typed_cell(CONST_STR); $$->x.str_val = $1;
+	  $$->size = strlen($1);
 	}
 	| STRING1 { 
-	  $$ = alloc_tree_cell(LNB, NULL); $$->x.str_val = $1;
-	  $$->type = CONST_DATA; $$->size = strlen($1);
-	}
-	| var | aff | ipaddr;
+	  $$ = alloc_typed_cell(CONST_DATA); $$->x.str_val = $1;
+	  $$->size = strlen($1);
+	} ;
+
+simple_array_data: atom;
 
 var:	identifier { $$ = alloc_tree_cell(LNB, $1); $$->type = NODE_VAR; }
 	| array_elem | func_call;
@@ -950,7 +973,9 @@
 	    return EQ;
 	  else if (c == '~')
 	    return RE_MATCH;
+	  else if (c == '>')
+	    return ARROW;
 	  ungetc(c, fp);
 	  if (c ==  '\n')
 	    ctx->line_nb --;
--- libnasl/nasl/nasl_tree.c	6 Mar 2003 11:30:07 -0000	1.24
+++ libnasl/nasl/nasl_tree.c	6 May 2003 07:46:16 -0000
@@ -280,6 +280,8 @@
   "CONST_DATA",
   "CONST_REGEX",
 
+  "ARRAY_ELEM",
+
   "REF_VAR",
   "REF_ARRAY",
   "DYN_ARRAY"
@@ -385,7 +387,8 @@
     case NODE_DECL:
     case NODE_ARG:
     case NODE_ARRAY_EL:
+    case ARRAY_ELEM:
       prefix(n, 0);
       if (c->x.str_val == NULL)
 	printf("Val=(null)\n");
--- libnasl/nasl/nasl_tree.h	23 Feb 2003 11:05:37 -0000	1.16
+++ libnasl/nasl/nasl_tree.h	6 May 2003 07:46:17 -0000
@@ -103,7 +103,9 @@
   CONST_DATA,			/* binary data / "pure" string */
   CONST_REGEX,			/* Compiled regex */
 
+  ARRAY_ELEM,			/* val = char index or NULL if integer,
+				 * [0] = value, [1] = next element */
   /* For exec only */
   REF_VAR,
   REF_ARRAY,
--- libnasl/nasl/nasl_var.c	25 Mar 2003 22:33:10 -0000	1.36
+++ libnasl/nasl/nasl_var.c	6 May 2003 07:46:18 -0000
@@ -1461,4 +1461,79 @@
   return 0;
 }
 
+/*
+ * make_array_from_list is used by the parser only
+ * The list of elements is freed after use
+ */
+
+tree_cell*
+make_array_from_elems(tree_cell* el)
+{
+  int		n;
+  tree_cell	*c, *c2;
+  nasl_array	*a;
+  anon_nasl_var	v;
+  char		*p;
+
+  a = emalloc(sizeof(nasl_array));
+  /* Either the elements are all "named", or they are "numbered". No mix! */
+  if (el->x.str_val == NULL) /* numbered */
+    {
+      for (n = 0, c = el; c != NULL; c= c->link[1])
+	n ++;
+      a->max_idx = n;
+      a->num_elt = emalloc(sizeof(anon_nasl_var*) * n);
+      a->hash_elt = NULL;
+    }
+  else
+    {
+      a->num_elt = NULL;
+      a->hash_elt = emalloc(VAR_NAME_HASH * sizeof(named_nasl_var*));
+    }
+  
+  for (n = 0, c = el; c != NULL; c= c->link[1])
+    {
+      c2 = c->link[0];
+      if (c2 != NULL && c2 != FAKE_CELL)
+	{
+	  memset(&v, 0, sizeof(v));
+	  switch (c2->type)
+	    {
+	    case CONST_INT:
+	      v.var_type = VAR2_INT;
+	      v.v.v_int = c2->x.i_val;
+	      break;
+	    case CONST_STR:
+	    case CONST_DATA:
+	      v.var_type = c2->type == CONST_STR ? VAR2_STRING : VAR2_DATA;
+	      if (c2->x.str_val == NULL )
+		{
+		  v.v.v_str.s_val = NULL;
+		  v.v.v_str.s_siz = 0;
+		}
+	      else
+		{
+		  v.v.v_str.s_siz = c2->size;
+		  v.v.v_str.s_val = c2->x.str_val;
+		}
+	      break;
+	    default:
+	      nasl_perror(NULL, "make_array_from_list: unhandled cell type %s at position %d\n", nasl_type_name(c2->type), n);
+	      v.var_type = VAR2_UNDEF;
+	      break;
+	    }
+	}
+
+      if (c->x.str_val == NULL)
+	add_var_to_list(a, n ++, &v);
+      else
+	add_var_to_array(a, c->x.str_val, &v);
+    }
+
+  c = alloc_typed_cell(DYN_ARRAY);
+  c->x.ref_val = a;
+  deref_cell(el);
+  return c;
+}
+
--- libnasl/nasl/nasl_var.h	25 Mar 2003 22:33:10 -0000	1.14
+++ libnasl/nasl/nasl_var.h	6 May 2003 07:46:18 -0000
@@ -103,4 +103,6 @@
 int		hash_str2(const char*, int);
 tree_cell*	var2cell(anon_nasl_var*);
 
+tree_cell*	make_array_from_elems(tree_cell*);
+
 #endif
asyncIO.patch (text/plain, 12 KB)
--- nessus-libraries/include/libnessus.h	6 Feb 2003 21:07:51 -0000	1.73
+++ nessus-libraries/include/libnessus.h	6 May 2003 07:46:19 -0000
@@ -395,7 +395,8 @@
 #ifdef HAVE_SSL
 ExtFunc        X509*   stream_get_server_certificate(int);
 ExtFunc	       char*   stream_get_ascii_server_certificate(int);
+ExtFunc		int	stream_SSL_error(int);
 #endif
 
 
--- nessus-libraries/libnessus/network.c	23 Apr 2003 21:27:21 -0000	1.104
+++ nessus-libraries/libnessus/network.c	6 May 2003 07:46:19 -0000
@@ -42,11 +42,6 @@
 #endif
 
 
-
-
-
-
-
 extern int plug_get_port_transport(struct arglist*, int);
 extern void plug_set_port_transport(struct arglist*, int, int);
 
@@ -69,6 +64,7 @@
   SSL_CTX* 	ssl_ctx;	/* SSL context 	*/
   SSL_METHOD* 	ssl_mt;		/* SSL method   */
   SSL* 		ssl;		/* SSL handler  */
+  int		last_ssl_err;	/* Last SSL error code */
 #endif
  pid_t		pid;		/* Owner - for debugging only */
 } nessus_connection;
@@ -243,30 +239,38 @@
  * High-level connection management                               *
  *----------------------------------------------------------------*/
 
-
 static int __port_closed;
-static volatile int __timeout;
-static void
-connect_alarm_handler()
+
+static int unblock_socket(int soc)
+{
+  int	flags =  fcntl(soc, F_GETFL, 0);
+  if (flags < 0)
 {
- __timeout = 1;
+      perror("fcntl(F_GETFL)");
+      return -1;
+    }
+  if (fcntl(soc, F_SETFL, O_NONBLOCK | flags) < 0)
+    {
+      perror("fcntl(F_SETFL,O_NONBLOCK)");
+      return -1;
+    }
+  return 0;
 }
 
-
-static void
-sig_alrm(int timeout)
+static int block_socket(int soc)
 {
-#ifdef HAVE_SIGACTION
-  struct sigaction sa;
-  sa.sa_handler = connect_alarm_handler;
-  sa.sa_flags = 0;
-  sigemptyset(&sa.sa_mask);
-  sigaction(SIGALRM,&sa,(struct sigaction *) 0);
-#else
-  signal(SIGALRM, connect_alarm_handler);
-#endif
-  __timeout = 0;
-  alarm(timeout);
+  int	flags =  fcntl(soc, F_GETFL, 0);
+  if (flags < 0)
+    {
+      perror("fcntl(F_GETFL)");
+      return -1;
+    }
+  if (fcntl(soc, F_SETFL, (~O_NONBLOCK) & flags) < 0)
+    {
+      perror("fcntl(F_SETFL,~O_NONBLOCK)");
+      return -1;
+    }
+  return 0;
 }
 
 /*
@@ -461,7 +465,10 @@
      char		*cert, *key, *passwd; 
      STACK_OF(X509_NAME)	*cert_names;
 {
-  int		ret;
+  int		ret, err;
+  time_t	tictac;
+  fd_set	fdw, fdr;
+  struct timeval	to;
 
 
   nessus_SSL_init(NULL);
@@ -525,24 +532,57 @@
       return -1;
     }
     
-  sig_alrm(timeout);
+  unblock_socket(fp->fd);
+
+  tictac = time(NULL);
+  for (;;)
+    {
   ret = SSL_connect(fp->ssl);
-  alarm(0);
-  if(__timeout)
+#if 0
+      block_socket(fp->fd);
+#endif
+      if (ret > 0)
+	return ret;
+      else if (ret < 0)
+	{
+	  sslerror("SSL_connect");
+	  return -1;
+	}
+      /* ret == 0 */
+      fp->last_ssl_err = err = SSL_get_error(fp->ssl, 0);
+      FD_ZERO(&fdr); FD_ZERO(&fdw);
+      switch (err)
+	{
+	case SSL_ERROR_WANT_READ:
+	  FD_SET(fp->fd, &fdr);
+	  break;
+	case SSL_ERROR_WANT_WRITE:
+	  FD_SET(fp->fd, &fdw);
+	  break;
+	default:
+	  sslerror("SSL_connect");
+	  break;
+	}
+
+      to.tv_sec = time(NULL) - tictac + timeout;
+      if (to.tv_sec <= 0)
+	break;
+      to.tv_usec = 0;
+
+      if (select(fp->fd + 1, &fdr, &fdw, NULL, &to) <= 0)
     {
 #if DEBUG_SSL > 1
-      fprintf(stderr,
-	      "open_stream_connection: SSL_connection timed out (%d s)\n", 
-	      timeout);
+	  perror("select");
 #endif	
-      return -1;
+	  break;
+	}
     }
      
-#if DEBUG_SSL > 0
-  if (ret <= 0)
-    sslerror("SSL_set_fd");
+#if DEBUG_SSL > 1
+  fprintf(stderr, "open_stream_connection: SSL_connection timed out (%d s)\n", 
+	  timeout);
 #endif	
-  return ret;
+  return -1;
 }
 #endif
 
@@ -776,6 +816,26 @@
   else
     return fp->ssl;
 }
+
+int
+stream_SSL_error(int fd)
+{
+  nessus_connection * fp;
+  if(!NESSUS_STREAM(fd))
+    {
+      fprintf(stderr, "stream_SSL_error: invalid fd=%d\n", fd);
+      errno = EINVAL;
+      return 0;
+    }
+  fp = &(connections[fd - NESSUS_FD_OFF]);
+  if (! IS_ENCAPS_SSL(fp->transport))
+    {
+      fprintf(stderr, "stream_SSL_error: fd=%d is not a SSL stream\n", fd);
+      return 0;
+    }
+  return fp->last_ssl_err;
+}
+
 #endif
 
 ExtFunc int
@@ -819,11 +879,11 @@
  void* buf0;
  int min_len, max_len;
 {
-  int			ret, errcode, realfd, trp, t;
+  int			ret, realfd, trp, t, err;
   int			total = 0, flag = 0, timeout = TIMEOUT, waitall = 0;
   unsigned char		* buf = (unsigned char*)buf0;
   nessus_connection	*fp = NULL;
-  fd_set		fds;
+  fd_set		fdr, fdw;
   struct timeval	tv;
  
 #if 0
@@ -864,10 +924,9 @@
 	{
 	  tv.tv_sec = INCR_TIMEOUT; /* Not timeout! */
 	  tv.tv_usec = 0;
-	  FD_ZERO(&fds);
-	  FD_SET(realfd, &fds);
-	  if(select(realfd + 1, &fds, NULL, NULL,
-		    timeout > 0 ? &tv : NULL) <= 0)
+	  FD_ZERO(&fdr);
+	  FD_SET(realfd, &fdr);
+	  if(select(realfd + 1, &fdr, NULL, NULL, timeout > 0 ? &tv : NULL) <= 0)
 	    {
 	      t += INCR_TIMEOUT;
 	      if (min_len <= 0)
@@ -901,9 +960,6 @@
       return total;
     }
 
-  FD_ZERO(&fds);
-  FD_SET(realfd, &fds);
-
   switch(trp)
     {
       /* NESSUS_ENCAPS_IP was treated before with the non-Nessus fd */
@@ -921,18 +977,52 @@
 	}
 # endif
 
+      FD_ZERO(&fdr); FD_ZERO(&fdw);
+      FD_SET(realfd, &fdr); FD_SET(realfd, &fdw); 
       for (t = 0; timeout <= 0 || t < timeout; t += INCR_TIMEOUT)
 	{
-	  if (timeout > 0)
-	    sig_alrm(INCR_TIMEOUT); /* Not timeout! */
+	  tv.tv_sec = INCR_TIMEOUT; tv.tv_usec = 0;
+	  if (select(realfd+1, &fdr, &fdw, NULL, &tv) > 0)
+	    {
 	  ret = SSL_read(fp->ssl, buf + total, max_len - total);
-	  alarm(0);
 	  if (ret > 0)
+		{
 	    total += ret;
+		  FD_SET(realfd, &fdr);
+		  FD_SET(realfd, &fdw); 
+		}
+
 	  if (total >= max_len)
 	    return total;
-	  if (__timeout)
+	      if (ret < 0)
+		{
+#if DEBUG_SSL > 0
+		  sslerror("SSL_read");
+#endif
+		  return total;
+		}
+	      else if (ret == 0)
+		{
+		  err = SSL_get_error(fp->ssl, ret);
+		  FD_ZERO(&fdr); FD_ZERO(&fdw);
+
+		  switch (err)
 	   {
+		    case SSL_ERROR_WANT_READ:
+		      FD_SET(realfd, &fdr);
+		      break;
+		    case SSL_ERROR_WANT_WRITE:
+		      FD_SET(realfd, &fdw);
+		      break;
+		    default:
+#if DEBUG_SSL > 0
+		      sslerror2("SSL_read", err);
+#endif
+		      return total;
+		    }
+		}
+	    }
+
 	    if (min_len <= 0)
 	      {
 		/* Be smart */
@@ -941,22 +1031,10 @@
 		else
 		  flag ++;
 	      }
-	    else
-	      if (total > min_len)
+	  else if (total > min_len)
 		return total;
-	      else			/* No timeout */
-		if(ret <= 0)
-		  {
-		    errcode = SSL_get_error(fp->ssl, ret);
-#if DEBUG_SSL > 0
-		    sslerror("SSL_read");
-#endif
-		    if(ret == 0 || errcode != SSL_ERROR_WANT_READ)
-		      break;
 		  }
-	    }
-	}
-      break;
+      return total;
 #endif
     default :
       fprintf(stderr, "Severe bug! Unhandled transport layer %d (fd=%d)\n",
@@ -964,8 +1042,7 @@
       errno = EINVAL;
       return -1;
     }
-    
-  return total;
+  /*NOTREACHED*/
 }
 
 ExtFunc int 
@@ -985,9 +1062,11 @@
  void * buf0;
  int n;
 {
- int ret, count, errcode;
+  int			err, ret, count;
  unsigned char* buf = (unsigned char*)buf0;
  nessus_connection * fp;
+  fd_set		fdr, fdw;
+  struct timeval	tv;
 
  if(!NESSUS_STREAM(fd))
    {
@@ -1024,8 +1103,6 @@
      else
        ret = send(fp->fd, buf + count, n - count, 0);
 
-      
-          
     if(ret <= 0)
      {
       if(errno != EPIPE)
@@ -1040,29 +1117,46 @@
   case NESSUS_ENCAPS_SSLv23:
   case NESSUS_ENCAPS_SSLv3:
   case NESSUS_ENCAPS_TLSv1:
+      FD_ZERO(&fdr); FD_ZERO(&fdw); 
+      FD_SET(fp->fd, & fdr); FD_SET(fp->fd, & fdw);
+
     for(count = 0; count < n;)
     { 
-     sig_alrm(TIMEOUT);
      ret = SSL_write(fp->ssl, buf + count, n - count);
-     alarm(0);
-     if(__timeout){
-#if DEBUG_SSL > 2
-      fprintf(stderr, "write_stream_connection: time out\n");
+	  if (ret > 0)
+	    count += ret;
+	  else
+	    {
+	      fp->last_ssl_err = SSL_get_error(fp->ssl, ret);
+
+	      if(ret <= 0)
+		break;
+	      /* ret == 0 */
+	      FD_ZERO(&fdw); FD_ZERO(&fdr); 
+	      if (err == SSL_ERROR_WANT_WRITE)
+		FD_SET(fp->fd, &fdw);
+	      else if (err == SSL_ERROR_WANT_READ)
+		FD_SET(fp->fd, &fdr);
+	      else
+		{
+#if DEBUG_SSL > 0
+		  sslerror2("SSL_write", err);
 #endif    
       break;
      }
-     if(ret <= 0)
+	      if (fp->timeout >= 0)
+		tv.tv_sec = fp->timeout;
+	      else
+		tv.tv_sec = TIMEOUT;
+	      tv.tv_usec = 0;
+	      if (select(fp->fd+1, &fdr, &fdw, NULL, &tv) <= 0)
      { 
-      errcode = SSL_get_error(fp->ssl, ret);
 #if DEBUG_SSL > 0
-      sslerror("SSL_write");
+		  perror("select");
 #endif      
-      if (ret == 0
-    		|| errcode != SSL_ERROR_WANT_WRITE  /* ret = -1 */ )
   	break;
      }
-     else 
-       count += ret;
+	    }
      }
     break;
 #endif
@@ -1113,7 +1207,9 @@
 #endif
  /* Trying OS's send() */
  {
-   int	n = send(fd, data, length, i_opt);
+   int		n;
+   block_socket(fd);		/* ??? */
+   n = send(fd, data, length, i_opt);
    if (n < 0)
      fprintf(stderr, "[%d] nsend():send %s\n", getpid(), strerror(errno));
    return n;
@@ -1137,6 +1233,7 @@
     return read_stream_connection(fd, data, length);
  }
  /* Trying OS's recv() */
+ block_socket(fd);		/* ??? */
  return recv(fd, data, length, i_opt);
 }
  
@@ -1222,12 +1319,66 @@
  }
 }
 
-static void 
-sighand_alarm()
+static int
+open_socket(struct sockaddr_in *paddr, 
+	    int port, int type, int protocol, int timeout)
+{
+  fd_set		fd_w;
+  struct timeval	to;
+  int			soc, x;
+
+  if ((soc = socket(AF_INET, type, protocol)) < 0)
 {
- printf("could not open the connection : timeout\n");
+      perror("socket");
+      return -1;
+    }
+
+  if (timeout == -2)
+    timeout = TIMEOUT;
+
+  if (timeout > 0)
+    if (unblock_socket(soc) < 0)
+      {
+	closesocket(soc);
+	return -1;
 }
 
+  if (connect(soc, (struct sockaddr*) paddr, sizeof(*paddr)) < 0)
+    {
+      switch (errno)
+	{
+	case EINPROGRESS:
+	case EAGAIN:
+	  FD_ZERO(&fd_w);
+	  FD_SET(soc, &fd_w);
+	  to.tv_sec = timeout;
+	  to.tv_usec = 0;
+	  x = select(soc + 1, NULL, &fd_w, NULL, &to);
+	  if (x == 0)
+	    {
+	      closesocket(soc);
+	      errno = ETIMEDOUT;
+	      return -1;
+	    }
+	  else if (x < 0)
+	    {
+	      perror("select");
+	      closesocket(soc);
+	      return -1;
+	    }
+	  break;
+
+	default:
+	  __port_closed = 1;
+	  closesocket(soc);
+	  return  -1;
+	}
+    }
+  block_socket(soc);
+  return soc;
+}
+
+
 ExtFunc 
 int open_sock_opt_hn(hostname, port, type, protocol, timeout)
  const char * hostname; 
@@ -1238,6 +1389,9 @@
 {
  struct sockaddr_in addr;
  int soc;
+ fd_set		fd_w;
+ struct timeval	to;
+ int		x;
   
   __port_closed = 0;
   bzero((void*)&addr, sizeof(addr));
@@ -1245,29 +1399,12 @@
   addr.sin_port=htons((unsigned short)port);
   addr.sin_addr = nn_resolve(hostname);
   if (addr.sin_addr.s_addr == INADDR_NONE || addr.sin_addr.s_addr == 0)
-    return(-1);
-    
-  if ((soc = socket(AF_INET, type, protocol)) < 0)
-    return -1;   
-
-  if (timeout == -2)
-    timeout = TIMEOUT;
-  if (timeout > 0)
-    sig_alrm(TIMEOUT);
-  if (connect(soc, (struct sockaddr*)&addr, sizeof(addr)) < 0)
     {
-      __port_closed = 1;
-      closesocket(soc);
-      alarm(0);
+      fprintf(stderr, "open_sock_opt_hn: invalid socket address\n");
       return  -1;
     }
    
-  if (timeout > 0)
-    {
-      signal(SIGALRM, SIG_IGN);
-      alarm(0); 
-    }
-  return soc;
+  return open_socket(&addr, port, type, protocol, timeout);
 }
 
 
@@ -1309,7 +1446,6 @@
 {
   struct sockaddr_in addr;
   struct in_addr * t;
-  int soc;
   
   if(host_get_port_state(args, port)<=0)return(-1);
   bzero((void*)&addr, sizeof(addr));
@@ -1326,27 +1462,8 @@
   if (addr.sin_addr.s_addr == INADDR_NONE)
     return(-1);
     
-  if ((soc = socket(AF_INET, type, protocol)) < 0)
-    {
-      nessus_perror("socket");
-      return -1;  
-    }
-
-  if (timeout == -2)
-    timeout = TIMEOUT;
-  if (timeout > 0)
-    sig_alrm(timeout);
-  if (connect(soc, (struct sockaddr*)&addr, sizeof(addr)) < 0)
-    {
-      /* nessus_perror("connect"); */
-      closesocket(soc);
-      alarm(0);
-      return  -1;
+  return open_socket(&addr, port, type, protocol, timeout);
     }
-  alarm(0); 
-  return soc;
-}
-
 
 
 /* This function reads a text from the socket stream into the
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.