diff --git a/source/Makefile.in b/source/Makefile.in index f8efbcd9275..c5db7023d6f 100644 --- a/source/Makefile.in +++ b/source/Makefile.in @@ -498,7 +498,8 @@ SMBD_OBJ_SRV = smbd/files.o smbd/chgpasswd.o smbd/connection.o \ smbd/change_trust_pw.o smbd/fake_file.o \ smbd/quotas.o smbd/ntquotas.o $(AFS_OBJ) smbd/msdfs.o \ $(AFS_SETTOKEN_OBJ) smbd/aio.o smbd/statvfs.o \ - smbd/dmapi.o lib/launchd.o $(MANGLE_OBJ) @VFS_STATIC@ + smbd/dmapi.o lib/launchd.o smbd/sockinit.o \ + $(MANGLE_OBJ) @VFS_STATIC@ SMBD_OBJ_BASE = $(PARAM_OBJ) $(SMBD_OBJ_SRV) $(LIBSMB_OBJ) \ $(RPC_SERVER_OBJ) $(RPC_PARSE_OBJ) $(SECRETS_OBJ) \ diff --git a/source/smbd/server.c b/source/smbd/server.c index 78f9779cfc3..ee5d219b97c 100644 --- a/source/smbd/server.c +++ b/source/smbd/server.c @@ -22,7 +22,6 @@ */ #include "includes.h" -#include "smb_launchd.h" static_decl_rpc; @@ -298,153 +297,6 @@ static BOOL allowable_number_of_smbd_processes(void) return num_children < max_processes; } -static int init_sockets_smbd(const char *smb_ports, - int fd_listenset[FD_SETSIZE]) -{ - int num_interfaces = iface_count(); - char * ports; - int num_sockets = 0; - int i, s; - - /* 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 { - ports = smb_xstrdup(ports); - } - } else { - ports = smb_xstrdup(smb_ports); - } - - 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. - */ - - /* Now open a listen socket for each of the - interfaces. */ - for(i = 0; i < num_interfaces; i++) { - struct in_addr *ifip = iface_n_ip(i); - fstring tok; - const char *ptr; - - if(ifip == NULL) { - DEBUG(0,("init_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 0; - - /* 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 0; - } - - num_sockets++; - if (num_sockets >= FD_SETSIZE) { - DEBUG(0,("init_sockets_smbd: Too many sockets to bind to\n")); - return 0; - } - } - } - } 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 0; - - /* 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,("init_sockets_smbd: listen: %s\n", - strerror(errno))); - close(s); - return 0; - } - - fd_listenset[num_sockets] = s; - num_sockets++; - - if (num_sockets >= FD_SETSIZE) { - DEBUG(0,("init_sockets_smbd: Too many sockets to bind to\n")); - return 0; - } - } - } - - SAFE_FREE(ports); - return num_sockets; -} - -static int init_sockets_launchd(const struct smb_launch_info *linfo, - const char * smb_ports, - int fd_listenset[FD_SETSIZE]) -{ - int num_sockets; - int i; - - /* The launchd service configuration does not have to provide sockets, - * even though it's basically useless without it. - */ - if (!linfo->num_sockets) { - return init_sockets_smbd(smb_ports, fd_listenset); - } - - /* Make sure we don't get more sockets than we can handle. */ - num_sockets = MIN(FD_SETSIZE, linfo->num_sockets); - memcpy(fd_listenset, linfo->socket_list, num_sockets * sizeof(int)); - - /* Get the sockets ready. This could be hoisted into - * open_sockets_smbd(), but the order of socket operations might - * matter for some platforms, so this approach seems less risky. - * --jpeach - */ - for (i = 0; i < num_sockets; ++i) { - set_socket_options(fd_listenset[i], "SO_KEEPALIVE"); - set_socket_options(fd_listenset[i], user_socket_options); - - /* Set server socket to non-blocking for the accept. */ - set_blocking(fd_listenset[i], False); - } - - return num_sockets; -} - /**************************************************************************** Open the socket communication. ****************************************************************************/ @@ -458,7 +310,6 @@ static BOOL open_sockets_smbd(enum smb_server_mode server_mode, const char *smb_ int maxfd = 0; int i; struct timeval idle_timeout = {0, 0}; - struct smb_launch_info linfo; if (server_mode == SERVER_MODE_INETD) { return open_sockets_inetd(); @@ -480,25 +331,9 @@ static BOOL open_sockets_smbd(enum smb_server_mode server_mode, const char *smb_ FD_ZERO(&listen_set); /* At this point, it doesn't matter what daemon mode we are in, we - * need some sockets to listen on. If we are in FOREGROUND mode, - * the launchd checkin might succeed. If we are in DAEMON or - * INTERACTIVE modes, it will fail and we will open the sockets - * ourselves. + * need some sockets to listen on. */ - if (smb_launchd_checkin(&linfo)) { - /* We are running under launchd and launchd has - * opened some sockets for us. - */ - num_sockets = init_sockets_launchd(&linfo, - smb_ports, - fd_listenset); - idle_timeout.tv_sec = linfo.idle_timeout_secs; - smb_launchd_checkout(&linfo); - } else { - num_sockets = init_sockets_smbd(smb_ports, - fd_listenset); - } - + num_sockets = smbd_sockinit(smb_ports, fd_listenset, &idle_timeout); if (num_sockets == 0) { return False; } diff --git a/source/smbd/sockinit.c b/source/smbd/sockinit.c new file mode 100644 index 00000000000..a4b9d63810d --- /dev/null +++ b/source/smbd/sockinit.c @@ -0,0 +1,201 @@ +/* + Unix SMB/CIFS implementation. + + Copyright (C) Andrew Tridgell 1992-1998 + Copyright (C) James Peach 2007 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" +#include "smb_launchd.h" + +extern pstring user_socket_options; + +static int init_sockets_smbd(const char *smb_ports, int listenset[FD_SETSIZE]) +{ + int num_interfaces = iface_count(); + char * ports; + int num_sockets = 0; + int i, s; + + /* 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 { + ports = smb_xstrdup(ports); + } + } else { + ports = smb_xstrdup(smb_ports); + } + + 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. + */ + + /* Now open a listen socket for each of the + interfaces. */ + for(i = 0; i < num_interfaces; i++) { + struct in_addr *ifip = iface_n_ip(i); + fstring tok; + const char *ptr; + + if(ifip == NULL) { + DEBUG(0,("init_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 = listenset[num_sockets] = open_socket_in(SOCK_STREAM, port, 0, ifip->s_addr, True); + if(s == -1) + return 0; + + /* 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 0; + } + + num_sockets++; + if (num_sockets >= FD_SETSIZE) { + DEBUG(0,("init_sockets_smbd: Too many sockets to bind to\n")); + return 0; + } + } + } + } 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 0; + + /* 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,("init_sockets_smbd: listen: %s\n", + strerror(errno))); + close(s); + return 0; + } + + listenset[num_sockets] = s; + num_sockets++; + + if (num_sockets >= FD_SETSIZE) { + DEBUG(0,("init_sockets_smbd: Too many sockets to bind to\n")); + return 0; + } + } + } + + SAFE_FREE(ports); + return num_sockets; +} + +static int init_sockets_launchd(const struct smb_launch_info *linfo, + const char * smb_ports, + int listenset[FD_SETSIZE]) +{ + int num_sockets; + int i; + + /* The launchd service configuration does not have to provide sockets, + * even though it's basically useless without it. + */ + if (!linfo->num_sockets) { + return init_sockets_smbd(smb_ports, listenset); + } + + /* Make sure we don't get more sockets than we can handle. */ + num_sockets = MIN(FD_SETSIZE, linfo->num_sockets); + memcpy(listenset, linfo->socket_list, num_sockets * sizeof(int)); + + /* Get the sockets ready. This could be hoisted into + * open_sockets_smbd(), but the order of socket operations might + * matter for some platforms, so this approach seems less risky. + * --jpeach + */ + for (i = 0; i < num_sockets; ++i) { + set_socket_options(listenset[i], "SO_KEEPALIVE"); + set_socket_options(listenset[i], user_socket_options); + + /* Set server socket to non-blocking for the accept. */ + set_blocking(listenset[i], False); + } + + return num_sockets; +} + +/* This function is responsible for opening (or retrieving) all the sockets we + * smbd will be listening on. It should apply all the configured socket options + * and return the number of valid sockets in listenset. + */ +int smbd_sockinit(const char *cmdline_ports, int listenset[FD_SETSIZE], + struct timeval *idle) +{ + int num_sockets; + struct smb_launch_info linfo; + + ZERO_STRUCTP(idle); + + if (smb_launchd_checkin(&linfo)) { + /* We are running under launchd and launchd has + * opened some sockets for us. + */ + num_sockets = init_sockets_launchd(&linfo, + cmdline_ports, + listenset); + idle->tv_sec = linfo.idle_timeout_secs; + smb_launchd_checkout(&linfo); + } else { + num_sockets = init_sockets_smbd(cmdline_ports, + listenset); + } + + return num_sockets; +} +