--- source/smbd/server.orig Fri Nov 10 18:59:07 2006 +++ source/smbd/server.c Fri Nov 10 22:37:55 2006 @@ -224,19 +224,81 @@ return True; } + +/*************************************************************************** + Parse the ports for the interface specified by sock_addr and create a + listening socket. +****************************************************************************/ +static BOOL mk_sockets_for_if(const int sock_addr, const char *ports, int *maxfd, fd_set *listenset, int *fd_listenset, int *num_sockets) +{ + + unsigned port; + + int s; + + fstring tok; + + while(next_token(&ports, tok, " \t,", sizeof(tok))) + { + + port = atoi(tok); + + if (port == 0) { + continue; + } + + s = open_socket_in(SOCK_STREAM, port, 0, sock_addr, True); + // "fd_listenset[num_sockets] = s" equivalent below + *(fd_listenset+(*num_sockets)) = s; + + if(s == -1) { + return False; + } + + /* ready to listen */ + set_socket_options(s, "SO_KEEPALIVE"); + set_socket_options(s, user_socket_options); + + /* Set server socket to non-blocking for the accept. */ + set_blocking(s,False); + + if (listen(s, SMBD_LISTEN_BACKLOG) == -1) { + DEBUG(0,("listen: %s\n", strerror(errno))); + close(s); + return False; + } + + FD_SET(s, listenset); + *maxfd = MAX( *maxfd, s); + + (*num_sockets)++; + + if (*num_sockets >= FD_SETSIZE) { + DEBUG(0,("open_sockets_smbd: Too many sockets to bind to\n")); + return False; + } + + } + + return True; + +} + + /**************************************************************************** Open the socket communication. ****************************************************************************/ - static BOOL open_sockets_smbd(BOOL is_daemon, BOOL interactive, const char *smb_ports) { + int num_interfaces = iface_count(); int num_sockets = 0; int fd_listenset[FD_SETSIZE]; fd_set listen_set; - int s; int maxfd = 0; int i; + int s; + char *ports; if (!is_daemon) { @@ -247,31 +309,39 @@ #ifdef HAVE_ATEXIT { static int atexit_set; + if(atexit_set == 0) { atexit_set=1; atexit(killkids); } + } #endif /* Stop zombies */ CatchChild(); - + FD_ZERO(&listen_set); /* use a reasonable default set of ports - listing on 445 and 139 */ if (!smb_ports) { + ports = lp_smb_ports(); + if (!ports || !*ports) { ports = smb_xstrdup(SMB_PORTS); - } else { + } + else { ports = smb_xstrdup(ports); } + } else { ports = smb_xstrdup(smb_ports); } - if (lp_interfaces() && lp_bind_interfaces_only()) { + if (lp_interfaces() && lp_bind_interfaces_only()) + { + /* We have been given an interfaces line, and been told to only bind to those interfaces. Create a socket per interface and bind to only these. @@ -279,102 +349,58 @@ /* Now open a listen socket for each of the interfaces. */ + + struct in_addr *ifip; + for(i = 0; i < num_interfaces; i++) { - struct in_addr *ifip = iface_n_ip(i); - fstring tok; - const char *ptr; + + ifip = iface_n_ip(i); if(ifip == NULL) { DEBUG(0,("open_sockets_smbd: interface %d has NULL IP address !\n", i)); continue; } - for (ptr=ports; next_token(&ptr, tok, " \t,", sizeof(tok)); ) { - unsigned port = atoi(tok); - if (port == 0) { - continue; - } - s = fd_listenset[num_sockets] = open_socket_in(SOCK_STREAM, port, 0, ifip->s_addr, True); - if(s == -1) - return False; - - /* ready to listen */ - set_socket_options(s,"SO_KEEPALIVE"); - set_socket_options(s,user_socket_options); - - /* Set server socket to non-blocking for the accept. */ - set_blocking(s,False); - - if (listen(s, SMBD_LISTEN_BACKLOG) == -1) { - DEBUG(0,("listen: %s\n",strerror(errno))); - close(s); - return False; - } - FD_SET(s,&listen_set); - maxfd = MAX( maxfd, s); - - num_sockets++; - if (num_sockets >= FD_SETSIZE) { - DEBUG(0,("open_sockets_smbd: Too many sockets to bind to\n")); - return False; - } + if(False == mk_sockets_for_if( ifip->s_addr, + ports, + &maxfd, + &listen_set, + &fd_listenset[0], + &num_sockets) + ) { + return False; } + } - } else { + + } + + else { /* Just bind to 0.0.0.0 - accept connections from anywhere. */ - fstring tok; - const char *ptr; - num_interfaces = 1; - - for (ptr=ports; next_token(&ptr, tok, " \t,", sizeof(tok)); ) { - unsigned port = atoi(tok); - if (port == 0) { - continue; - } - /* open an incoming socket */ - s = open_socket_in(SOCK_STREAM, port, 0, - interpret_addr(lp_socket_address()),True); - if (s == -1) - return(False); - - /* ready to listen */ - set_socket_options(s,"SO_KEEPALIVE"); - set_socket_options(s,user_socket_options); - - /* Set server socket to non-blocking for the accept. */ - set_blocking(s,False); - - if (listen(s, SMBD_LISTEN_BACKLOG) == -1) { - DEBUG(0,("open_sockets_smbd: listen: %s\n", - strerror(errno))); - close(s); - return False; - } - fd_listenset[num_sockets] = s; - FD_SET(s,&listen_set); - maxfd = MAX( maxfd, s); - - num_sockets++; - - if (num_sockets >= FD_SETSIZE) { - DEBUG(0,("open_sockets_smbd: Too many sockets to bind to\n")); - return False; - } + if(False == mk_sockets_for_if( interpret_addr( lp_socket_address() ), + ports, + &maxfd, + &listen_set, + &fd_listenset[0], + &num_sockets) + ) { + return False; } + } SAFE_FREE(ports); - /* Listen to messages */ + /* Listen to messages */ - message_register(MSG_SMB_SAM_SYNC, msg_sam_sync); - message_register(MSG_SMB_SAM_REPL, msg_sam_repl); - message_register(MSG_SHUTDOWN, msg_exit_server); - message_register(MSG_SMB_FILE_RENAME, msg_file_was_renamed); + message_register(MSG_SMB_SAM_SYNC, msg_sam_sync); + message_register(MSG_SMB_SAM_REPL, msg_sam_repl); + message_register(MSG_SHUTDOWN, msg_exit_server); + message_register(MSG_SMB_FILE_RENAME, msg_file_was_renamed); message_register(MSG_SMB_CONF_UPDATED, smb_conf_updated); #ifdef DEVELOPER @@ -384,7 +410,10 @@ /* now accept incoming connections - forking a new process for each incoming connection */ DEBUG(2,("waiting for a connection\n")); - while (1) { + + while (1) + { + fd_set lfds; int num; @@ -394,25 +423,29 @@ /* Ensure we respond to PING and DEBUG messages from the main smbd. */ message_dispatch(); - memcpy((char *)&lfds, (char *)&listen_set, - sizeof(listen_set)); - + memcpy((char *)&lfds, (char *)&listen_set, sizeof(listen_set)); + num = sys_select(maxfd+1,&lfds,NULL,NULL,NULL); - if (num == -1 && errno == EINTR) { + if (num == -1 && errno == EINTR) + { + if (got_sig_term) { exit_server_cleanly(NULL); } /* check for sighup processing */ - if (reload_after_sighup) { + if (reload_after_sighup) + { change_to_root_user(); DEBUG(1,("Reloading services after SIGHUP\n")); reload_services(False); reload_after_sighup = 0; + } continue; + } /* check if we need to reload services */ @@ -421,18 +454,24 @@ /* Find the sockets that are read-ready - accept on these. */ for( ; num > 0; num--) { + struct sockaddr addr; socklen_t in_addrlen = sizeof(addr); s = -1; + for(i = 0; i < num_sockets; i++) { - if(FD_ISSET(fd_listenset[i],&lfds)) { + + if(FD_ISSET(fd_listenset[i], &lfds)) { + s = fd_listenset[i]; /* Clear this so we don't look at it again. */ FD_CLR(fd_listenset[i],&lfds); break; + } + } smbd_set_server_fd(accept(s,&addr,&in_addrlen)); @@ -441,8 +480,7 @@ continue; if (smbd_server_fd() == -1) { - DEBUG(0,("open_sockets_smbd: accept: %s\n", - strerror(errno))); + DEBUG(0,("open_sockets_smbd: accept: %s\n", strerror(errno))); continue; } @@ -453,12 +491,13 @@ return True; if (allowable_number_of_smbd_processes() && smbd_server_fd() != -1 && sys_fork()==0) { + /* Child code ... */ - + /* close the listening socket(s) */ for(i = 0; i < num_sockets; i++) close(fd_listenset[i]); - + /* close our standard file descriptors */ close_low_fds(False); @@ -484,7 +523,9 @@ } return True; + } + /* The parent doesn't need this socket */ close(smbd_server_fd()); @@ -515,6 +556,7 @@ force_check_log_size(); } /* end for num */ + } /* end while 1 */ /* NOTREACHED return True; */