⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 util_sock.c

📁 samba-3.0.22.tar.gz 编译smb服务器的源码
💻 C
📖 第 1 页 / 共 3 页
字号:
		/* Set initial timeout */	timeout.tv_sec = (time_t)(time_out / 1000);	timeout.tv_usec = (long)(1000 * (time_out % 1000));		for (nread=0; nread < mincnt; ) {      		FD_ZERO(&fds);		FD_SET(fd,&fds);				selrtn = sys_select_intr(fd+1,&fds,NULL,NULL,&timeout);				/* Check if error */		if (selrtn == -1) {			/* something is wrong. Maybe the socket is dead? */			if (fd == client_fd) {				/* Try and give an error message saying what client failed. */				DEBUG(0,("read_socket_with_timeout: timeout read for client %s. select error = %s.\n",					client_ip_string, strerror(errno) ));			} else {				DEBUG(0,("read_socket_with_timeout: timeout read. select error = %s.\n", strerror(errno) ));			}			smb_read_error = READ_ERROR;			return -1;		}				/* Did we timeout ? */		if (selrtn == 0) {			DEBUG(10,("read_socket_with_timeout: timeout read. select timed out.\n"));			smb_read_error = READ_TIMEOUT;			return -1;		}				readret = sys_read(fd, buf+nread, maxcnt-nread);				if (readret == 0) {			/* we got EOF on the file descriptor */			DEBUG(5,("read_socket_with_timeout: timeout read. EOF from client.\n"));			smb_read_error = READ_EOF;			return -1;		}				if (readret == -1) {			/* the descriptor is probably dead */			if (fd == client_fd) {				/* Try and give an error message saying what client failed. */				DEBUG(0,("read_socket_with_timeout: timeout read to client %s. read error = %s.\n",					client_ip_string, strerror(errno) ));			} else {				DEBUG(0,("read_socket_with_timeout: timeout read. read error = %s.\n", strerror(errno) ));			}			smb_read_error = READ_ERROR;			return -1;		}				nread += readret;	}		/* Return the number we got */	return (ssize_t)nread;}/**************************************************************************** Read data from the client, reading exactly N bytes. ****************************************************************************/ssize_t read_data(int fd,char *buffer,size_t N){	ssize_t ret;	size_t total=0;   	smb_read_error = 0;	while (total < N) {		ret = sys_read(fd,buffer + total,N - total);		if (ret == 0) {			DEBUG(10,("read_data: read of %d returned 0. Error = %s\n", (int)(N - total), strerror(errno) ));			smb_read_error = READ_EOF;			return 0;		}		if (ret == -1) {			if (fd == client_fd) {				/* Try and give an error message saying what client failed. */				DEBUG(0,("read_data: read failure for %d bytes to client %s. Error = %s\n",					(int)(N - total), client_ip_string, strerror(errno) ));			} else {				DEBUG(0,("read_data: read failure for %d. Error = %s\n", (int)(N - total), strerror(errno) ));			}			smb_read_error = READ_ERROR;			return -1;		}		total += ret;	}	return (ssize_t)total;}/**************************************************************************** Write data to a fd.****************************************************************************/ssize_t write_data(int fd, const char *buffer, size_t N){	size_t total=0;	ssize_t ret;	while (total < N) {		ret = sys_write(fd,buffer + total,N - total);		if (ret == -1) {			if (fd == client_fd) {				/* Try and give an error message saying what client failed. */				DEBUG(0,("write_data: write failure in writing to client %s. Error %s\n",					client_ip_string, strerror(errno) ));			} else {				DEBUG(0,("write_data: write failure. Error = %s\n", strerror(errno) ));			}			return -1;		}		if (ret == 0) {			return total;		}		total += ret;	}	return (ssize_t)total;}/**************************************************************************** Send a keepalive packet (rfc1002).****************************************************************************/BOOL send_keepalive(int client){	unsigned char buf[4];	buf[0] = SMBkeepalive;	buf[1] = buf[2] = buf[3] = 0;	return(write_data(client,(char *)buf,4) == 4);}/**************************************************************************** Read 4 bytes of a smb packet and return the smb length of the packet. Store the result in the buffer. This version of the function will return a length of zero on receiving a keepalive packet. Timeout is in milliseconds.****************************************************************************/static ssize_t read_smb_length_return_keepalive(int fd, char *inbuf, unsigned int timeout){	ssize_t len=0;	int msg_type;	BOOL ok = False;	while (!ok) {		if (timeout > 0)			ok = (read_socket_with_timeout(fd,inbuf,4,4,timeout) == 4);		else 			ok = (read_data(fd,inbuf,4) == 4);		if (!ok)			return(-1);		len = smb_len(inbuf);		msg_type = CVAL(inbuf,0);		if (msg_type == SMBkeepalive) 			DEBUG(5,("Got keepalive packet\n"));	}	DEBUG(10,("got smb length of %lu\n",(unsigned long)len));	return(len);}/**************************************************************************** Read 4 bytes of a smb packet and return the smb length of the packet. Store the result in the buffer. This version of the function will never return a session keepalive (length of zero). Timeout is in milliseconds.****************************************************************************/ssize_t read_smb_length(int fd, char *inbuf, unsigned int timeout){	ssize_t len;	for(;;) {		len = read_smb_length_return_keepalive(fd, inbuf, timeout);		if(len < 0)			return len;		/* Ignore session keepalives. */		if(CVAL(inbuf,0) != SMBkeepalive)			break;	}	DEBUG(10,("read_smb_length: got smb length of %lu\n",		  (unsigned long)len));	return len;}/**************************************************************************** Read an smb from a fd. Note that the buffer *MUST* be of size BUFFER_SIZE+SAFETY_MARGIN. The timeout is in milliseconds.  This function will return on receipt of a session keepalive packet. Doesn't check the MAC on signed packets.****************************************************************************/BOOL receive_smb_raw(int fd, char *buffer, unsigned int timeout){	ssize_t len,ret;	smb_read_error = 0;	memset(buffer,'\0',smb_size + 100);	len = read_smb_length_return_keepalive(fd,buffer,timeout);	if (len < 0) {		DEBUG(10,("receive_smb_raw: length < 0!\n"));		/*		 * Correct fix. smb_read_error may have already been		 * set. Only set it here if not already set. Global		 * variables still suck :-). JRA.		 */		if (smb_read_error == 0)			smb_read_error = READ_ERROR;		return False;	}	/*	 * A WRITEX with CAP_LARGE_WRITEX can be 64k worth of data plus 65 bytes	 * of header. Don't print the error if this fits.... JRA.	 */	if (len > (BUFFER_SIZE + LARGE_WRITEX_HDR_SIZE)) {		DEBUG(0,("Invalid packet length! (%lu bytes).\n",(unsigned long)len));		if (len > BUFFER_SIZE + (SAFETY_MARGIN/2)) {			/*			 * Correct fix. smb_read_error may have already been			 * set. Only set it here if not already set. Global			 * variables still suck :-). JRA.			 */			if (smb_read_error == 0)				smb_read_error = READ_ERROR;			return False;		}	}	if(len > 0) {		if (timeout > 0) {			ret = read_socket_with_timeout(fd,buffer+4,len,len,timeout);		} else {			ret = read_data(fd,buffer+4,len);		}		if (ret != len) {			if (smb_read_error == 0)				smb_read_error = READ_ERROR;			return False;		}				/* not all of samba3 properly checks for packet-termination of strings. This		   ensures that we don't run off into empty space. */		SSVAL(buffer+4,len, 0);	}	return True;}/**************************************************************************** Wrapper for receive_smb_raw(). Checks the MAC on signed packets.****************************************************************************/BOOL receive_smb(int fd, char *buffer, unsigned int timeout){	if (!receive_smb_raw(fd, buffer, timeout)) {		return False;	}	/* Check the incoming SMB signature. */	if (!srv_check_sign_mac(buffer, True)) {		DEBUG(0, ("receive_smb: SMB Signature verification failed on incoming packet!\n"));		if (smb_read_error == 0)			smb_read_error = READ_BAD_SIG;		return False;	};	return(True);}/**************************************************************************** Send an smb to a fd.****************************************************************************/BOOL send_smb(int fd, char *buffer){	size_t len;	size_t nwritten=0;	ssize_t ret;	/* Sign the outgoing packet if required. */	srv_calculate_sign_mac(buffer);	len = smb_len(buffer) + 4;	while (nwritten < len) {		ret = write_data(fd,buffer+nwritten,len - nwritten);		if (ret <= 0) {			DEBUG(0,("Error writing %d bytes to client. %d. (%s)\n",				(int)len,(int)ret, strerror(errno) ));			return False;		}		nwritten += ret;	}	return True;}/**************************************************************************** Open a socket of the specified type, port, and address for incoming data.****************************************************************************/int open_socket_in( int type, int port, int dlevel, uint32 socket_addr, BOOL rebind ){	struct sockaddr_in sock;	int res;	memset( (char *)&sock, '\0', sizeof(sock) );#ifdef HAVE_SOCK_SIN_LEN	sock.sin_len         = sizeof(sock);#endif	sock.sin_port        = htons( port );	sock.sin_family      = AF_INET;	sock.sin_addr.s_addr = socket_addr;	res = socket( AF_INET, type, 0 );	if( res == -1 ) {		if( DEBUGLVL(0) ) {			dbgtext( "open_socket_in(): socket() call failed: " );			dbgtext( "%s\n", strerror( errno ) );		}		return -1;	}	/* This block sets/clears the SO_REUSEADDR and possibly SO_REUSEPORT. */	{		int val = rebind ? 1 : 0;		if( setsockopt(res,SOL_SOCKET,SO_REUSEADDR,(char *)&val,sizeof(val)) == -1 ) {			if( DEBUGLVL( dlevel ) ) {				dbgtext( "open_socket_in(): setsockopt: " );				dbgtext( "SO_REUSEADDR = %s ", val?"True":"False" );				dbgtext( "on port %d failed ", port );				dbgtext( "with error = %s\n", strerror(errno) );			}		}#ifdef SO_REUSEPORT		if( setsockopt(res,SOL_SOCKET,SO_REUSEPORT,(char *)&val,sizeof(val)) == -1 ) {			if( DEBUGLVL( dlevel ) ) {				dbgtext( "open_socket_in(): setsockopt: ");				dbgtext( "SO_REUSEPORT = %s ", val?"True":"False" );				dbgtext( "on port %d failed ", port );				dbgtext( "with error = %s\n", strerror(errno) );			}		}#endif /* SO_REUSEPORT */	}	/* now we've got a socket - we need to bind it */	if( bind( res, (struct sockaddr *)&sock, sizeof(sock) ) == -1 ) {		if( DEBUGLVL(dlevel) && (port == SMB_PORT1 || port == SMB_PORT2 || port == NMB_PORT) ) {			dbgtext( "bind failed on port %d ", port );			dbgtext( "socket_addr = %s.\n", inet_ntoa( sock.sin_addr ) );			dbgtext( "Error = %s\n", strerror(errno) );		}		close( res ); 		return( -1 ); 	}	DEBUG( 10, ( "bind succeeded on port %d\n", port ) );	return( res ); }/**************************************************************************** Create an outgoing socket. timeout is in milliseconds.**************************************************************************/int open_socket_out(int type, struct in_addr *addr, int port ,int timeout){	struct sockaddr_in sock_out;	int res,ret;	int connect_loop = 10;	int increment = 10;	/* create a socket to write to */	res = socket(PF_INET, type, 0);	if (res == -1) {                DEBUG(0,("socket error (%s)\n", strerror(errno)));		return -1;	}	if (type != SOCK_STREAM)		return(res);  	memset((char *)&sock_out,'\0',sizeof(sock_out));	putip((char *)&sock_out.sin_addr,(char *)addr);  	sock_out.sin_port = htons( port );	sock_out.sin_family = PF_INET;	/* set it non-blocking */	set_blocking(res,False);	DEBUG(3,("Connecting to %s at port %d\n",inet_ntoa(*addr),port));  	/* and connect it to the destination */  connect_again:	ret = connect(res,(struct sockaddr *)&sock_out,sizeof(sock_out));	/* Some systems return EAGAIN when they mean EINPROGRESS */	if (ret < 0 && (errno == EINPROGRESS || errno == EALREADY ||			errno == EAGAIN) && (connect_loop < timeout) ) {		smb_msleep(connect_loop);		timeout -= connect_loop;		connect_loop += increment;		if (increment < 250) {			/* After 8 rounds we end up at a max of 255 msec */			increment *= 1.5;		}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -