From 9155889092ac9ff476d950a0c1b624ebad3cdad6 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 22 Aug 1996 06:32:03 +0000 Subject: - add timeouts to connect() for password server connections. This makes multiple password servers practical. (This used to be commit 5c3e8326cc45d3cbd076475e445ce461a2bf7560) --- source3/client/client.c | 4 +-- source3/client/clientutil.c | 4 +-- source3/include/local.h | 4 +++ source3/include/proto.h | 3 +- source3/lib/util.c | 69 +++++++++++++++++++++++++++++++++++++++++---- source3/nmbd/nmbd.c | 15 ++++++++-- source3/smbd/password.c | 2 +- 7 files changed, 86 insertions(+), 15 deletions(-) (limited to 'source3') diff --git a/source3/client/client.c b/source3/client/client.c index 6bd94be756..cc178967a1 100644 --- a/source3/client/client.c +++ b/source3/client/client.c @@ -2956,7 +2956,7 @@ static BOOL send_session_request(char *inbuf,char *outbuf) putip((char *)&dest_ip,inbuf+4); close_sockets(); - Client = open_socket_out(SOCK_STREAM, &dest_ip, port); + Client = open_socket_out(SOCK_STREAM, &dest_ip, port, LONG_CONNECT_TIMEOUT); if (Client == -1) return False; @@ -4025,7 +4025,7 @@ static BOOL open_sockets(int port ) } } - Client = open_socket_out(SOCK_STREAM, &dest_ip, port); + Client = open_socket_out(SOCK_STREAM, &dest_ip, port, LONG_CONNECT_TIMEOUT); if (Client == -1) return False; diff --git a/source3/client/clientutil.c b/source3/client/clientutil.c index e684d42612..3058f65474 100644 --- a/source3/client/clientutil.c +++ b/source3/client/clientutil.c @@ -212,7 +212,7 @@ BOOL cli_send_session_request(char *inbuf, char *outbuf) putip((char *)&dest_ip,inbuf+4); close_sockets(); - Client = open_socket_out(SOCK_STREAM, &dest_ip, port); + Client = open_socket_out(SOCK_STREAM, &dest_ip, port, SHORT_CONNECT_TIMEOUT); if (Client == -1) return False; @@ -835,7 +835,7 @@ BOOL cli_open_sockets(int port) putip((char *)&dest_ip,(char *)hp->h_addr); } - Client = open_socket_out(SOCK_STREAM, &dest_ip, port); + Client = open_socket_out(SOCK_STREAM, &dest_ip, port, SHORT_CONNECT_TIMEOUT); if (Client == -1) return False; diff --git a/source3/include/local.h b/source3/include/local.h index 5a577909e1..3f8572e73d 100644 --- a/source3/include/local.h +++ b/source3/include/local.h @@ -150,4 +150,8 @@ by many apps */ #define KEEP_PASSWORD_SERVER_OPEN 1 +/* how long to wait for a socket connect to happen */ +#define LONG_CONNECT_TIMEOUT 30 +#define SHORT_CONNECT_TIMEOUT 5 + #endif diff --git a/source3/include/proto.h b/source3/include/proto.h index f8685d21ea..e20238fee4 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -856,6 +856,7 @@ BOOL strhaslower(char *s); int count_chars(char *s,char c); void make_dir_struct(char *buf,char *mask,char *fname,unsigned int size,int mode,time_t date); void close_low_fds(void); +int set_blocking(int fd, int set); int write_socket(int fd,char *buf,int len); int read_udp_socket(int fd,char *buf,int len); int read_with_timeout(int fd,char *buf,int mincnt,int maxcnt,long time_out); @@ -891,7 +892,7 @@ void Abort(void ); BOOL get_myname(char *my_name,struct in_addr *ip); BOOL ip_equal(struct in_addr ip1,struct in_addr ip2); int open_socket_in(int type, int port, int dlevel,uint32 socket_addr); -int open_socket_out(int type, struct in_addr *addr, int port ); +int open_socket_out(int type, struct in_addr *addr, int port ,int timeout); int interpret_protocol(char *str,int def); int interpret_security(char *str,int def); uint32 interpret_addr(char *str); diff --git a/source3/lib/util.c b/source3/lib/util.c index 2fedded329..e13a4c37e8 100644 --- a/source3/lib/util.c +++ b/source3/lib/util.c @@ -477,6 +477,12 @@ struct #endif #ifdef SO_RCVLOWAT {"SO_RCVLOWAT", SOL_SOCKET, SO_RCVLOWAT, 0, OPT_INT}, +#endif +#ifdef SO_SNDTIMEO + {"SO_SNDTIMEO", SOL_SOCKET, SO_SNDTIMEO, 0, OPT_INT}, +#endif +#ifdef SO_RCVTIMEO + {"SO_RCVTIMEO", SOL_SOCKET, SO_RCVTIMEO, 0, OPT_INT}, #endif {NULL,0,0,0,0}}; @@ -1655,6 +1661,35 @@ void close_low_fds(void) } } +/**************************************************************************** +Set a fd into blocking/nonblocking mode. Uses POSIX O_NONBLOCK if available, +else +if SYSV use O_NDELAY +if BSD use FNDELAY +****************************************************************************/ +int set_blocking(int fd, int set) +{ + int val; +#ifdef O_NONBLOCK +#define FLAG_TO_SET O_NONBLOCK +#else +#ifdef SYSV +#define FLAG_TO_SET O_NDELAY +#else /* BSD */ +#define FLAG_TO_SET FNDELAY +#endif +#endif + + if((val = fcntl(fd, F_GETFL, 0)) == -1) + return -1; + if(set) /* Turn blocking on - ie. clear nonblock flag */ + val &= ~FLAG_TO_SET; + else + val |= FLAG_TO_SET; + return fcntl( fd, F_SETFL, val); +#undef FLAG_TO_SET +} + /**************************************************************************** write to a socket @@ -2813,10 +2848,12 @@ int open_socket_in(int type, int port, int dlevel,uint32 socket_addr) /**************************************************************************** create an outgoing socket **************************************************************************/ -int open_socket_out(int type, struct in_addr *addr, int port ) +int open_socket_out(int type, struct in_addr *addr, int port ,int timeout) { struct sockaddr_in sock_out; - int res; + int res,ret; + int connect_loop = 250; /* 250 milliseconds */ + int loops = (timeout * 1000) / connect_loop; /* create a socket to write to */ res = socket(PF_INET, type, 0); @@ -2831,15 +2868,35 @@ int open_socket_out(int type, struct in_addr *addr, int port ) sock_out.sin_port = htons( port ); sock_out.sin_family = PF_INET; + /* set it non-blocking */ + set_blocking(res,0); + DEBUG(3,("Connecting to %s at port %d\n",inet_ntoa(*addr),port)); /* and connect it to the destination */ - if (connect(res,(struct sockaddr *)&sock_out,sizeof(sock_out))<0) { - DEBUG(0,("connect error: %s\n",strerror(errno))); - close(res); - return(-1); +connect_again: + ret = connect(res,(struct sockaddr *)&sock_out,sizeof(sock_out)); + + if (ret < 0 && errno == EINPROGRESS && loops--) { + msleep(connect_loop); + goto connect_again; } + if (ret < 0 && errno == EINPROGRESS) { + DEBUG(2,("timeout connecting to %s:%d\n",inet_ntoa(*addr),port)); + close(res); + return -1; + } + + if (ret < 0) { + DEBUG(2,("error connecting to %s:%d (%s)\n", + inet_ntoa(*addr),port,strerror(errno))); + return -1; + } + + /* set it blocking again */ + set_blocking(res,1); + return res; } diff --git a/source3/nmbd/nmbd.c b/source3/nmbd/nmbd.c index 097e4f794a..5b3fd19491 100644 --- a/source3/nmbd/nmbd.c +++ b/source3/nmbd/nmbd.c @@ -357,17 +357,22 @@ static BOOL open_sockets(BOOL isdaemon, int port) ****************************************************************************/ static BOOL init_structs() { - if (!get_myname(myhostname,NULL)) - return(False); + extern fstring local_machine; + char *p; if (! *myname) { - char *p; strcpy(myname,myhostname); p = strchr(myname,'.'); if (p) *p = 0; } strupper(myname); + strcpy(local_machine,myname); + trim_string(local_machine," "," "); + p = strchr(local_machine,' '); + if (p) *p = 0; + strlower(local_machine); + return True; } @@ -479,11 +484,15 @@ static void usage(char *pname) DEBUG(1,("%s netbios nameserver version %s started\n",timestring(),VERSION)); DEBUG(1,("Copyright Andrew Tridgell 1994\n")); + get_myname(myhostname,NULL); + if (!reload_services(False)) return(-1); init_structs(); + reload_services(True); + set_samba_nb_type(); if (!is_daemon && !is_a_socket(0)) { diff --git a/source3/smbd/password.c b/source3/smbd/password.c index a5f597682f..fd3ff4fd17 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -1287,7 +1287,7 @@ BOOL server_cryptkey(char *buf) continue; } - password_client = open_socket_out(SOCK_STREAM, &dest_ip, port); + password_client = open_socket_out(SOCK_STREAM, &dest_ip, port, SHORT_CONNECT_TIMEOUT); if (password_client >= 0) { DEBUG(3,("connected to password server %s\n",p)); StrnCpy(pserver,p,sizeof(pserver)-1); -- cgit