@@ -530,6 +530,57 @@ static int get_port_from_addr(const sockname_t *addr)
530530#endif
531531}
532532
533+ /* Check for O_NONBLOCK connect() EINPROGRESS could be ECONNREFUSED
534+ * eggdrop sockets are always O_NONBLOCK, see setsock()
535+ */
536+ int connect_nonblock (int s , sockname_t * addr , int check_tcl_event_ident ) {
537+ int rc , res , e ;
538+ struct timeval tv ;
539+ fd_set sockset ;
540+ socklen_t res_len ;
541+
542+ rc = connect (s , & addr -> addr .sa , addr -> addrlen );
543+ /* To minimize a proven race condition, call ident here (especially when
544+ * rc < 0 and errno == EINPROGRESS)
545+ */
546+ if (check_tcl_event_ident ) {
547+ /* push/pop errno, better safe than sorry */
548+ e = errno ;
549+ check_tcl_event ("ident" );
550+ errno = e ;
551+ }
552+ if (rc < 0 ) {
553+ if (errno == EINPROGRESS ) {
554+ /* Async connection... don't return socket descriptor
555+ * until after we confirm if it was successful or not */
556+ tv .tv_sec = 0 ;
557+ tv .tv_usec = 500000 ; /* 0.5 second timeout, more than enough to detect
558+ * ECONNREFUSED */
559+ FD_ZERO (& sockset );
560+ FD_SET (s , & sockset );
561+ select (s + 1 , NULL , & sockset , NULL , & tv );
562+ res_len = sizeof (res );
563+ getsockopt (s , SOL_SOCKET , SO_ERROR , & res , & res_len );
564+ if (res == EINPROGRESS ) /* Operation now in progress */
565+ return s ; /* This could probably fail somewhere */
566+ if (res == ECONNREFUSED ) { /* Connection refused */
567+ debug2 ("net: attempted socket connection refused: %s:%i" ,
568+ iptostr (& addr -> addr .sa ), get_port_from_addr (addr ));
569+ errno = res ;
570+ return -4 ;
571+ }
572+ if (res != 0 ) {
573+ debug1 ("net: getsockopt error %d" , res );
574+ return -1 ;
575+ }
576+ return s ; /* async success! */
577+ }
578+ debug2 ("net: check_connect(): socket %i error %s" , s , strerror (errno ));
579+ return -1 ;
580+ }
581+ return s ;
582+ }
583+
533584/* Starts a connection attempt through a socket
534585 *
535586 * The server address should be filled in addr by setsockname() or by the
@@ -540,11 +591,8 @@ static int get_port_from_addr(const sockname_t *addr)
540591 */
541592int open_telnet_raw (int sock , sockname_t * addr )
542593{
594+ int i , j ;
543595 sockname_t name ;
544- socklen_t res_len ;
545- fd_set sockset ;
546- struct timeval tv ;
547- int i , j , rc , errno_tmp , res ;
548596 struct threaddata * td = threaddata ();
549597
550598 for (i = 0 ; i < dcc_total ; i ++ )
@@ -568,45 +616,7 @@ int open_telnet_raw(int sock, sockname_t *addr)
568616 }
569617 if (addr -> family == AF_INET && firewall [0 ])
570618 return proxy_connect (sock , addr );
571- rc = connect (sock , & addr -> addr .sa , addr -> addrlen );
572- /* To minimize a proven race condition, call ident here (especially when
573- * rc < 0 and errno == EINPROGRESS)
574- */
575- if (dcc [i ].status & STAT_SERV ) {
576- errno_tmp = errno ;
577- check_tcl_event ("ident" );
578- errno = errno_tmp ;
579- }
580- if (rc < 0 ) {
581- if (errno == EINPROGRESS ) {
582- /* Async connection... don't return socket descriptor
583- * until after we confirm if it was successful or not */
584- tv .tv_sec = 1 ;
585- tv .tv_usec = 0 ;
586- FD_ZERO (& sockset );
587- FD_SET (sock , & sockset );
588- select (sock + 1 , NULL , & sockset , NULL , & tv );
589- res_len = sizeof (res );
590- getsockopt (sock , SOL_SOCKET , SO_ERROR , & res , & res_len );
591- if (res == EINPROGRESS ) /* Operation now in progress */
592- return sock ; /* This could probably fail somewhere */
593- if (res == ECONNREFUSED ) { /* Connection refused */
594- debug2 ("net: attempted socket connection refused: %s:%i" ,
595- iptostr (& addr -> addr .sa ), get_port_from_addr (addr ));
596- errno = res ;
597- return -4 ;
598- }
599- if (res != 0 ) {
600- debug1 ("net: getsockopt error %d" , res );
601- return -1 ;
602- }
603- return sock ; /* async success! */
604- }
605- else {
606- return -1 ;
607- }
608- }
609- return sock ;
619+ return connect_nonblock (sock , addr , dcc [i ].status & STAT_SERV );
610620}
611621
612622/* Ordinary non-binary connection attempt
0 commit comments