Пример #1
0
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;
	char *ports;

	if (!is_daemon) {
		return open_sockets_inetd();
	}

		
#ifdef HAVE_ATEXIT
	{
		static int atexit_set;
		if(atexit_set == 0) {
			atexit_set=1;
			atexit(killkids);
		}
	}
#endif

#ifndef _XBOX
	/* Stop zombies */
	CatchChild();
#endif

	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 {
			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,("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;
				}
			}
		}
	} 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 */
#ifndef _XBOX
			set_socket_options(s,"SO_KEEPALIVE"); 
#endif
			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;
			}
		}
	} 

	SAFE_FREE(ports);

        /* 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_CONF_UPDATED, smb_conf_updated); 

#ifdef DEVELOPER
	message_register(MSG_SMB_INJECT_FAULT, msg_inject_fault); 
#endif

	/* now accept incoming connections - forking a new process
	   for each incoming connection */
	DEBUG(2,("waiting for a connection\n"));
	while (1) {
		fd_set lfds;
		int num;
		
		/* Free up temporary memory from the main smbd. */
		lp_TALLOC_FREE();

		/* Ensure we respond to PING and DEBUG messages from the main smbd. */
		message_dispatch();

		memcpy((char *)&lfds, (char *)&listen_set, 
		       sizeof(listen_set));
		
		num = sys_select(maxfd+1,&lfds,NULL,NULL,NULL);
		
		if (num == -1 && errno == EINTR) {
			if (got_sig_term) {
				exit_server_cleanly(NULL);
			}

			/* check for sighup processing */
			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 */
		check_reload(time(NULL));

		/* 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)) {
					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));
			
			if (smbd_server_fd() == -1 && errno == EINTR)
				continue;
			
			if (smbd_server_fd() == -1) {
				DEBUG(0,("open_sockets_smbd: accept: %s\n",
					 strerror(errno)));
				continue;
			}

			/* Ensure child is set to blocking mode */
			set_blocking(smbd_server_fd(),True);

			if (smbd_server_fd() != -1 && interactive) {
#ifdef _XBOX
				xb_IncClientCount();
#endif
				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);
				am_parent = 0;
				
				set_socket_options(smbd_server_fd(),"SO_KEEPALIVE");
				set_socket_options(smbd_server_fd(),user_socket_options);
				
				/* this is needed so that we get decent entries
				   in smbstatus for port 445 connects */
				set_remote_machine_name(get_peer_addr(smbd_server_fd()), False);
				
				/* Reset the state of the random
				 * number generation system, so
				 * children do not get the same random
				 * numbers as each other */

				set_need_random_reseed();
				/* tdb needs special fork handling - remove CLEAR_IF_FIRST flags */
				if (tdb_reopen_all(1) == -1) {
					DEBUG(0,("tdb_reopen_all failed.\n"));
					smb_panic("tdb_reopen_all failed.");
				}

				return True; 
			}
			/* The parent doesn't need this socket */
			close(smbd_server_fd()); 

			/* Sun May 6 18:56:14 2001 [email protected]:
				Clear the closed fd info out of server_fd --
				and more importantly, out of client_fd in
				util_sock.c, to avoid a possible
				getpeername failure if we reopen the logs
				and use %I in the filename.
			*/

			smbd_set_server_fd(-1);

			/* Force parent to check log size after
			 * spawning child.  Fix from
			 * [email protected].  The
			 * parent smbd will log to logserver.smb.  It
			 * writes only two messages for each child
			 * started/finished. But each child writes,
			 * say, 50 messages also in logserver.smb,
			 * begining with the debug_count of the
			 * parent, before the child opens its own log
			 * file logserver.client. In a worst case
			 * scenario the size of logserver.smb would be
			 * checked after about 50*50=2500 messages
			 * (ca. 100kb).
			 * */
			force_check_log_size();
 
		} /* end for num */
	} /* end while 1 */

/* NOTREACHED	return True; */
}
Пример #2
0
static NTSTATUS ipv6_set_option(struct socket_context *sock, const char *option, const char *val)
{
    set_socket_options(sock->fd, option);
    return NT_STATUS_OK;
}
Пример #3
0
void cli_sockopt(struct cli_state *cli, const char *options)
{
	set_socket_options(cli->fd, options);
}
Пример #4
0
/*
 * connect_by_number:  Wheeeee. Yet another monster function i get to fix
 * for the sake of it being inadequate for extension.
 *
 * we now take four arguments:
 *
 *	- hostname - name of the host (pathname) to connect to (if applicable)
 *	- portnum - port number to connect to or listen on (0 if you dont care)
 *	- service -	0 - set up a listening socket
 *			1 - set up a connecting socket
 *	- protocol - 	0 - use the TCP protocol
 *			1 - use the UDP protocol
 *
 *
 * Returns:
 *	Non-negative number -- new file descriptor ready for use
 *	-1 -- could not open a new file descriptor or 
 *		an illegal value for the protocol was specified
 *	-2 -- call to bind() failed
 *	-3 -- call to listen() failed.
 *	-4 -- call to connect() failed
 *	-5 -- call to getsockname() failed
 *	-6 -- the name of the host could not be resolved
 *	-7 -- illegal or unsupported request
 *	-8 -- no socks access
 *
 *
 * Credit: I couldnt have put this together without the help of BSD4.4-lite
 * User SupplimenTary Document #20 (Inter-process Communications tutorial)
 */
int BX_connect_by_number(char *hostn, unsigned short *portnum, int service, int protocol, int nonblocking)
{
	int fd = -1;
	int is_unix = (hostn && *hostn == '/');
	int sock_type, proto_type;

#ifndef __OPENNT
	sock_type = (is_unix) ? AF_UNIX : AF_INET;
#else
	sock_type = AF_INET;
#endif

	proto_type = (protocol == PROTOCOL_TCP) ? SOCK_STREAM : SOCK_DGRAM;

	if ((fd = socket(sock_type, proto_type, 0)) < 0)
		return -1;

	set_socket_options (fd);

	/* Unix domain server */
#ifdef HAVE_SYS_UN_H
	if (is_unix)
	{
		struct sockaddr_un name;

		memset(&name, 0, sizeof(struct sockaddr_un));
		name.sun_family = AF_UNIX;
		strcpy(name.sun_path, hostn);
#ifdef HAVE_SUN_LEN
# ifdef SUN_LEN
		name.sun_len = SUN_LEN(&name);
# else
		name.sun_len = strlen(hostn) + 1;
# endif
#endif

		if (is_unix && (service == SERVICE_SERVER))
		{
			if (bind(fd, (struct sockaddr *)&name, strlen(name.sun_path) + sizeof(name.sun_family)))
				return close(fd), -2;
			if (protocol == PROTOCOL_TCP)
				if (listen(fd, 4) < 0)
					return close(fd), -3;
		}

		/* Unix domain client */
		else if (service == SERVICE_CLIENT)
		{
			alarm(get_int_var(CONNECT_TIMEOUT_VAR));
			if (connect (fd, (struct sockaddr *)&name, strlen(name.sun_path) + 2) < 0)
			{
				alarm(0);
				return close(fd), -4;
			}
			alarm(0);
		}
	}
	else
#endif

	/* Inet domain server */
	if (!is_unix && (service == SERVICE_SERVER))
	{
		int length;
#ifdef IP_PORTRANGE
		int ports;
#endif
		/* Even on an IPv6 client this opens up a IPv4 socket... for now.
		 * (Some OSes need two sockets to be able to accept both IPv4 and
		 * IPv6 connections). */
		struct sockaddr_in name;

		memset(&name, 0, sizeof name);
		name.sin_family = AF_INET;
		name.sin_addr.s_addr = htonl(INADDR_ANY);

		name.sin_port = htons(*portnum);
#ifdef PARANOID
		name.sin_port += (unsigned short)(rand() & 255);
#endif
		
#ifdef IP_PORTRANGE
		if (getenv("EPIC_USE_HIGHPORTS"))
		{
			ports = IP_PORTRANGE_HIGH;
			setsockopt(fd, IPPROTO_IP, IP_PORTRANGE, 
					(char *)&ports, sizeof(ports));
		}
#endif

		if (bind(fd, (struct sockaddr *)&name, sizeof(name)))
			return close(fd), -2;

		length = sizeof (name);
		if (getsockname(fd, (struct sockaddr *)&name, &length))
			return close(fd), -5;

		*portnum = ntohs(name.sin_port);

		if (protocol == PROTOCOL_TCP)
			if (listen(fd, 4) < 0)
				return close(fd), -3;
#ifdef NON_BLOCKING_CONNECTS
		if (nonblocking && set_non_blocking(fd) < 0)
			return close(fd), -4;
#endif
	}

	/* Inet domain client */
	else if (!is_unix && (service == SERVICE_CLIENT))
	{
		struct sockaddr_foobar server;
		int server_len;
		struct hostent *hp;
#ifdef WINNT
		char buf[BIG_BUFFER_SIZE+1];
#endif		
#ifdef IPV6
		struct addrinfo hints, *res;
		struct sockaddr_foobar *sf = NULL;
#else
		struct sockaddr_in localaddr;
		if (LocalHostName)
		{
			memset(&localaddr, 0, sizeof(struct sockaddr_in));
			localaddr.sin_family = AF_INET;
			localaddr.sin_addr = LocalHostAddr.sf_addr;
			localaddr.sin_port = 0;
			if (bind(fd, (struct sockaddr *)&localaddr, sizeof(localaddr)))
				return close(fd), -2;
		}
#endif

		memset(&server, 0, sizeof server);
#ifndef WINNT

#ifdef IPV6
		memset(&hints, 0, sizeof(hints));
		if (!getaddrinfo(hostn, NULL, &hints, &res) && res)
		{
			sf = (struct sockaddr_foobar*) res->ai_addr;

			close(fd);

			proto_type = (protocol == PROTOCOL_TCP) ? SOCK_STREAM : SOCK_DGRAM;
			if ((fd = socket(sf->sf_family, proto_type, 0)) < 0)
				return -1;
			set_socket_options (fd);

			if ((server.sf_family = sf->sf_family) == AF_INET)
			{
				memcpy(&server.sf_addr, &sf->sf_addr, sizeof(struct in_addr));
				server_len = sizeof server.sins.sin;
			}	
			else
			{
				memcpy(&server.sf_addr6, &sf->sf_addr6, sizeof(struct in6_addr));
				server_len = sizeof server.sins.sin6;
			}
			server.sf_port = htons(*portnum);

			memset(&hints, 0, sizeof(struct addrinfo));
			hints.ai_family = res->ai_family;
			freeaddrinfo(res);
 
			if (LocalHostName && !getaddrinfo(LocalHostName, NULL, &hints, &res) && res)
			{
				if (bind(fd, (struct sockaddr *) res->ai_addr, res->ai_addrlen))
					return close(fd), -2;
				freeaddrinfo(res);
			}
		}
		else
			return close(fd), -6;

#else
		if (isdigit((unsigned char)hostn[strlen(hostn)-1]))
			inet_aton(hostn, (struct in_addr *)&server.sf_addr);
		else
		{
			if (!(hp = gethostbyname(hostn)))
	  			return close(fd), -6;
			memcpy(&server.sf_addr, hp->h_addr, hp->h_length);
		}
		server.sf_family = AF_INET;
		server.sf_port = htons(*portnum);
		server_len = sizeof server.sins.sin;
#endif /* IPV6 */
		
#else
		/* for some odd reason resolv() fails on NT... */
/*		server = (*(struct sockaddr_in *) hostn);*/
		if (!hostn)
		{
			gethostname(buf, sizeof(buf));
			hostn = buf;
		}
		if ((server.sf_addr.s_addr = inet_addr(hostn)) == -1)
		{
			if ((hp = gethostbyname(hostn)) != NULL)
			{
				memset(&server, 0, sizeof(server));
				bcopy(hp->h_addr, (char *) &server.sf_addr,
					hp->h_length);
				server.sf_family = hp->h_addrtype;
			}
			else
				return (-2);
		}
		else
		server.sf_family = AF_INET;
		server.sf_port = (unsigned short) htons(*portnum);
		server_len = sizeof server.sins.sin;
#endif /* WINNT */

#ifdef NON_BLOCKING_CONNECTS
		if (!use_socks && nonblocking && set_non_blocking(fd) < 0)
			return close(fd), -4;
#endif

#if !defined(WTERM_C) && !defined(STERM_C) && !defined(IPV6)

		if (use_socks && get_string_var(SOCKS_HOST_VAR))
		{

			fd = handle_socks(fd, *((struct sockaddr_in*) &server), get_string_var(SOCKS_HOST_VAR), get_int_var(SOCKS_PORT_VAR));
			if (fd == -1)
				return -4;
			else
				return fd;
		}
#endif
		alarm(get_int_var(CONNECT_TIMEOUT_VAR));
		if (connect(fd, (struct sockaddr *)&server, server_len) < 0 && errno != EINPROGRESS)
		{
			alarm(0);
			return close(fd), -4;
		}
		alarm(0);
	}

	/* error */
	else
		return close(fd), -7;

	return fd;
}
Пример #5
0
static bool smbd_open_one_socket(struct smbd_parent_context *parent,
				 struct tevent_context *ev_ctx,
				 struct messaging_context *msg_ctx,
				 const struct sockaddr_storage *ifss,
				 uint16_t port)
{
	struct smbd_open_socket *s;

	s = talloc(parent, struct smbd_open_socket);
	if (!s) {
		return false;
	}

	s->parent = parent;
	s->fd = open_socket_in(SOCK_STREAM,
			       port,
			       parent->sockets == NULL ? 0 : 2,
			       ifss,
			       true);
	if (s->fd == -1) {
		DEBUG(0,("smbd_open_once_socket: open_socket_in: "
			"%s\n", strerror(errno)));
		TALLOC_FREE(s);
		/*
		 * We ignore an error here, as we've done before
		 */
		return true;
	}

	/* ready to listen */
	set_socket_options(s->fd, "SO_KEEPALIVE");
	set_socket_options(s->fd, lp_socket_options());

	/* Set server socket to
	 * non-blocking for the accept. */
	set_blocking(s->fd, False);

	if (listen(s->fd, SMBD_LISTEN_BACKLOG) == -1) {
		DEBUG(0,("open_sockets_smbd: listen: "
			"%s\n", strerror(errno)));
			close(s->fd);
		TALLOC_FREE(s);
		return false;
	}

	s->fde = tevent_add_fd(ev_ctx,
			       s,
			       s->fd, TEVENT_FD_READ,
			       smbd_accept_connection,
			       s);
	if (!s->fde) {
		DEBUG(0,("open_sockets_smbd: "
			 "tevent_add_fd: %s\n",
			 strerror(errno)));
		close(s->fd);
		TALLOC_FREE(s);
		return false;
	}
	tevent_fd_set_close_fn(s->fde, smbd_open_socket_close_fn);

	DLIST_ADD_END(parent->sockets, s, struct smbd_open_socket *);

	return true;
}
Пример #6
0
static struct subnet_record *make_subnet(const char *name, enum subnet_type type,
					 struct in_addr myip, struct in_addr bcast_ip, 
					 struct in_addr mask_ip)
{
	struct subnet_record *subrec = NULL;
	int nmb_sock, dgram_sock;

	/* Check if we are creating a non broadcast subnet - if so don't create
		sockets.  */

	if(type != NORMAL_SUBNET) {
		nmb_sock = -1;
		dgram_sock = -1;
	} else {
		/*
		 * Attempt to open the sockets on port 137/138 for this interface
		 * and bind them.
		 * Fail the subnet creation if this fails.
		 */

		if((nmb_sock = open_socket_in(SOCK_DGRAM, global_nmb_port,0, myip.s_addr,True)) == -1) {
			if( DEBUGLVL( 0 ) ) {
				Debug1( "nmbd_subnetdb:make_subnet()\n" );
				Debug1( "  Failed to open nmb socket on interface %s ", inet_ntoa(myip) );
				Debug1( "for port %d.  ", global_nmb_port );
				Debug1( "Error was %s\n", strerror(errno) );
			}
			return NULL;
		}

		if((dgram_sock = open_socket_in(SOCK_DGRAM,DGRAM_PORT,3, myip.s_addr,True)) == -1) {
			if( DEBUGLVL( 0 ) ) {
				Debug1( "nmbd_subnetdb:make_subnet()\n" );
				Debug1( "  Failed to open dgram socket on interface %s ", inet_ntoa(myip) );
				Debug1( "for port %d.  ", DGRAM_PORT );
				Debug1( "Error was %s\n", strerror(errno) );
			}
			return NULL;
		}

		/* Make sure we can broadcast from these sockets. */
		set_socket_options(nmb_sock,"SO_BROADCAST");
		set_socket_options(dgram_sock,"SO_BROADCAST");

		/* Set them non-blocking. */
		set_blocking(nmb_sock, False);
		set_blocking(dgram_sock, False);
	}

	subrec = SMB_MALLOC_P(struct subnet_record);
	if (!subrec) {
		DEBUG(0,("make_subnet: malloc fail !\n"));
		close(nmb_sock);
		close(dgram_sock);
		return(NULL);
	}
  
	ZERO_STRUCTP(subrec);

	if((subrec->subnet_name = SMB_STRDUP(name)) == NULL) {
		DEBUG(0,("make_subnet: malloc fail for subnet name !\n"));
		close(nmb_sock);
		close(dgram_sock);
		ZERO_STRUCTP(subrec);
		SAFE_FREE(subrec);
		return(NULL);
	}

	DEBUG(2, ("making subnet name:%s ", name ));
	DEBUG(2, ("Broadcast address:%s ", inet_ntoa(bcast_ip)));
	DEBUG(2, ("Subnet mask:%s\n", inet_ntoa(mask_ip)));
 
	subrec->namelist_changed = False;
	subrec->work_changed = False;
 
	subrec->bcast_ip = bcast_ip;
	subrec->mask_ip  = mask_ip;
	subrec->myip = myip;
	subrec->type = type;
	subrec->nmb_sock = nmb_sock;
	subrec->dgram_sock = dgram_sock;
  
	return subrec;
}
Пример #7
0
/*
 * connect_by_number:  Wheeeee. Yet another monster function i get to fix
 * for the sake of it being inadequate for extension.
 *
 * we now take four arguments:
 *
 *      - hostname - name of the host (pathname) to connect to (if applicable)
 *      - portnum - port number to connect to or listen on (0 if you dont care)
 *      - service -     0 - set up a listening socket
 *                      1 - set up a connecting socket
 *      - protocol -    0 - use the TCP protocol
 *                      1 - use the UDP protocol
 *
 *
 * Returns:
 *      Non-negative number -- new file descriptor ready for use
 *      -1 -- could not open a new file descriptor or 
 *              an illegal value for the protocol was specified
 *      -2 -- call to bind() failed
 *      -3 -- call to listen() failed.
 *      -4 -- call to connect() failed
 *      -5 -- call to getsockname() failed
 *      -6 -- the name of the host could not be resolved
 *      -7 -- illegal or unsupported request
 *
 *
 * Credit: I couldnt have put this together without the help of BSD4.4-lite
 * User Supplimentary Document #20 (Inter-process Communications tutorial)
 */
int connect_by_number(char *hostn, unsigned short *portnum, int service, int protocol, int nonblocking)
{
    int fd = -1;
    int is_unix = (hostn && *hostn == '/');
    int sock_type, proto_type;

    sock_type = (is_unix) ? AF_UNIX : AF_INET;
    proto_type = (protocol == PROTOCOL_TCP) ? SOCK_STREAM : SOCK_DGRAM;

    if ((fd = socket(sock_type, proto_type, 0)) < 0)
	return -1;

    set_socket_options(fd);

    /* Unix domain server */
#ifdef HAVE_SYS_UN_H
    if (is_unix) {
	struct sockaddr_un name;

	memset(&name, 0, sizeof(struct sockaddr_un));
	name.sun_family = AF_UNIX;
	strcpy(name.sun_path, hostn);
#ifdef HAVE_SUN_LEN
#ifdef SUN_LEN
	name.sun_len = SUN_LEN(&name);
#else
	name.sun_len = strlen(hostn) + 1;
#endif
#endif

	if (is_unix && (service == SERVICE_SERVER)) {
	    if (bind(fd, (struct sockaddr *) &name, strlen(name.sun_path) + 2))
		return close(fd), -2;

	    if (protocol == PROTOCOL_TCP)
		if (listen(fd, 4) < 0)
		    return close(fd), -3;
	}

	/* Unix domain client */
	else if (service == SERVICE_CLIENT) {
	    alarm(get_int_var(CONNECT_TIMEOUT_VAR));
	    if (connect(fd, (struct sockaddr *) &name, strlen(name.sun_path) + 2) < 0) {
		alarm(0);
		return close(fd), -4;
	    }
	    alarm(0);
	}
    } else
#endif

	/* Inet domain server */
    if (!is_unix && (service == SERVICE_SERVER)) {
	socklen_t length;
	struct sockaddr_in name;

	memset(&name, 0, sizeof(struct sockaddr_in));
	name.sin_family = AF_INET;
	name.sin_addr.s_addr = htonl(INADDR_ANY);
	name.sin_port = htons(*portnum);

	if (bind(fd, (struct sockaddr *) &name, sizeof(name)))
	    return close(fd), -2;

	length = sizeof(name);
	if (getsockname(fd, (struct sockaddr *) &name, &length))
	    return close(fd), -5;

	*portnum = ntohs(name.sin_port);

	if (protocol == PROTOCOL_TCP)
	    if (listen(fd, 4) < 0)
		return close(fd), -3;
	if (nonblocking && set_non_blocking(fd) < 0)
	    return close(fd), -4;
    }

    /* Inet domain client */
    else if (!is_unix && (service == SERVICE_CLIENT)) {
	struct sockaddr_in server;
	struct hostent *hp;

#if 0
	/* 
	 * Doing this bind is bad news unless you are sure that
	 * the hostname is valid.  This is not true for me at home,
	 * since i dynamic-ip it.
	 */
	if (LocalHostName) {
	    struct sockaddr_in localaddr;
	    memset(&localaddr, 0, sizeof(struct sockaddr_in));
	    localaddr.sin_family = AF_INET;
	    localaddr.sin_addr = LocalHostAddr;
	    localaddr.sin_port = 0;
	    if (bind(fd, (struct sockaddr *) &localaddr, sizeof(localaddr)))
		return close(fd), -2;
	}
#endif

	memset(&server, 0, sizeof(struct sockaddr_in));
	if (!(hp = resolv(hostn)))
	    return close(fd), -6;
	memcpy(&(server.sin_addr), hp->h_addr, hp->h_length);
	server.sin_family = AF_INET;
	server.sin_port = htons(*portnum);

	if (nonblocking && set_non_blocking(fd) < 0)
	    return close(fd), -4;
	alarm(get_int_var(CONNECT_TIMEOUT_VAR));
	if (connect(fd, (struct sockaddr *) &server, sizeof(server)) < 0) {
	    alarm(0);
	    if (errno != EINPROGRESS && !nonblocking)
		return close(fd), -4;
	}
	alarm(0);
    }

    /* error */
    else
	return close(fd), -7;

    return fd;
}