diff options
Diffstat (limited to 'source4/lib')
-rw-r--r-- | source4/lib/util_sock.c | 374 |
1 files changed, 1 insertions, 373 deletions
diff --git a/source4/lib/util_sock.c b/source4/lib/util_sock.c index 7fe42f7ffc..1859aef4d7 100644 --- a/source4/lib/util_sock.c +++ b/source4/lib/util_sock.c @@ -23,16 +23,6 @@ #include "system/network.h" -/**************************************************************************** - Determine if a file descriptor is in fact a socket. -****************************************************************************/ -BOOL is_a_socket(int fd) -{ - int v,l; - l = sizeof(int); - return getsockopt(fd, SOL_SOCKET, SO_TYPE, (char *)&v, &l) == 0; -} - enum SOCK_OPT_TYPES {OPT_BOOL,OPT_INT,OPT_ON}; typedef struct smb_socket_option { @@ -79,28 +69,10 @@ static const smb_socket_option socket_options[] = { #endif {NULL,0,0,0,0}}; -/**************************************************************************** - Print socket options. -****************************************************************************/ - -static void print_socket_options(int s) -{ - int value, vlen = 4; - const smb_socket_option *p = &socket_options[0]; - - for (; p->name != NULL; p++) { - if (getsockopt(s, p->level, p->option, (void *)&value, &vlen) == -1) { - DEBUG(5,("Could not test socket option %s.\n", p->name)); - } else { - DEBUG(5,("socket option %s = %d\n",p->name,value)); - } - } - } /**************************************************************************** Set user socket options. ****************************************************************************/ - void set_socket_options(int fd, const char *options) { fstring tok; @@ -148,43 +120,12 @@ void set_socket_options(int fd, const char *options) if (ret != 0) DEBUG(0,("Failed to set socket option %s (Error %s)\n",tok, strerror(errno) )); } - - print_socket_options(fd); -} - -/**************************************************************************** - Read from a socket. -****************************************************************************/ - -ssize_t read_udp_socket(int fd, char *buf, size_t len, - struct ipv4_addr *from_addr, int *from_port) -{ - ssize_t ret; - struct sockaddr_in sock; - socklen_t socklen = sizeof(sock); - - ret = recvfrom(fd,buf,len, 0, (struct sockaddr *)&sock, &socklen); - if (ret <= 0) { - DEBUG(2,("read socket failed. ERRNO=%s\n",strerror(errno))); - return 0; - } - - if (from_addr) { - from_addr->addr = sock.sin_addr.s_addr; - } - if (from_port) { - *from_port = ntohs(sock.sin_port); - } - - return ret; } - /**************************************************************************** Check the timeout. ****************************************************************************/ - static BOOL timeout_until(struct timeval *timeout, const struct timeval *endtime) { @@ -206,7 +147,6 @@ static BOOL timeout_until(struct timeval *timeout, /**************************************************************************** Read data from the client, reading exactly N bytes, with timeout. ****************************************************************************/ - ssize_t read_data_until(int fd,char *buffer,size_t N, const struct timeval *endtime) { @@ -247,10 +187,10 @@ ssize_t read_data_until(int fd,char *buffer,size_t N, return (ssize_t)total; } + /**************************************************************************** Write data to a fd with timeout. ****************************************************************************/ - ssize_t write_data_until(int fd,char *buffer,size_t N, const struct timeval *endtime) { @@ -290,50 +230,6 @@ ssize_t write_data_until(int fd,char *buffer,size_t N, } -/**************************************************************************** - Open a socket of the specified type, port, and address for incoming data. -****************************************************************************/ -int open_socket_in( int type, int port, int dlevel, uint32_t 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 ) { - DEBUG(0,("open_socket_in(): socket() call failed: %s\n", strerror(errno))); - return -1; - } - - /* This block sets/clears the SO_REUSEADDR and possibly SO_REUSEPORT. */ - { - int val = rebind ? 1 : 0; - setsockopt(res,SOL_SOCKET,SO_REUSEADDR,(char *)&val,sizeof(val)); -#ifdef SO_REUSEPORT - setsockopt(res,SOL_SOCKET,SO_REUSEPORT,(char *)&val,sizeof(val)); -#endif - } - - /* now we've got a socket - we need to bind it */ - if( bind( res, (struct sockaddr *)&sock, sizeof(sock) ) == -1 ) { - DEBUG(0,("bind failed on port %d - %s\n", port, 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. @@ -401,271 +297,3 @@ connect_again: return res; } -/* - open a connected UDP socket to host on port -*/ -int open_udp_socket(const char *host, int port) -{ - int type = SOCK_DGRAM; - struct sockaddr_in sock_out; - int res; - struct ipv4_addr addr; - TALLOC_CTX *mem_ctx; - - mem_ctx = talloc_init("open_udp_socket"); - if (!mem_ctx) { - return -1; - } - addr = interpret_addr2(host); - - res = socket(PF_INET, type, 0); - if (res == -1) { - return -1; - } - - 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; - - talloc_free(mem_ctx); - - if (connect(res,(struct sockaddr *)&sock_out,sizeof(sock_out))) { - close(res); - return -1; - } - - return res; -} - - -/******************************************************************* - matchname - determine if host name matches IP address. Used to - confirm a hostname lookup to prevent spoof attacks - ******************************************************************/ -static BOOL matchname(char *remotehost, struct ipv4_addr addr) -{ - struct hostent *hp; - int i; - - if ((hp = sys_gethostbyname(remotehost)) == 0) { - DEBUG(0,("sys_gethostbyname(%s): lookup failure.\n", remotehost)); - return False; - } - - /* - * Make sure that gethostbyname() returns the "correct" host name. - * Unfortunately, gethostbyname("localhost") sometimes yields - * "localhost.domain". Since the latter host name comes from the - * local DNS, we just have to trust it (all bets are off if the local - * DNS is perverted). We always check the address list, though. - */ - - if (strcasecmp(remotehost, hp->h_name) - && strcasecmp(remotehost, "localhost")) { - DEBUG(0,("host name/name mismatch: %s != %s\n", - remotehost, hp->h_name)); - return False; - } - - /* Look up the host address in the address list we just got. */ - for (i = 0; hp->h_addr_list[i]; i++) { - if (memcmp(hp->h_addr_list[i], (char *) & addr, sizeof(addr)) == 0) - return True; - } - - /* - * The host name does not map to the original host address. Perhaps - * someone has compromised a name server. More likely someone botched - * it, but that could be dangerous, too. - */ - - DEBUG(0,("host name/address mismatch: %s != %s\n", - sys_inet_ntoa(addr), hp->h_name)); - return False; -} - - -/******************************************************************* - return the DNS name of the remote end of a socket - ******************************************************************/ -char *get_socket_name(TALLOC_CTX *mem_ctx, int fd, BOOL force_lookup) -{ - char *name_buf; - struct hostent *hp; - struct ipv4_addr addr; - char *p; - - /* reverse lookups can be *very* expensive, and in many - situations won't work because many networks don't link dhcp - with dns. To avoid the delay we avoid the lookup if - possible */ - if (!lp_hostname_lookups() && (force_lookup == False)) { - return get_socket_addr(mem_ctx, fd); - } - - p = get_socket_addr(mem_ctx, fd); - - name_buf = talloc_strdup(mem_ctx, "UNKNOWN"); - if (fd == -1) return name_buf; - - addr = interpret_addr2(p); - - /* Look up the remote host name. */ - if ((hp = gethostbyaddr((char *)&addr.addr, sizeof(addr.addr), AF_INET)) == 0) { - DEBUG(1,("Gethostbyaddr failed for %s\n",p)); - name_buf = talloc_strdup(mem_ctx, p); - } else { - name_buf = talloc_strdup(mem_ctx, (char *)hp->h_name); - if (!matchname(name_buf, addr)) { - DEBUG(0,("Matchname failed on %s %s\n",name_buf,p)); - name_buf = talloc_strdup(mem_ctx, "UNKNOWN"); - } - } - - alpha_strcpy(name_buf, name_buf, "_-.", strlen(name_buf)+1); - if (strstr(name_buf,"..")) { - name_buf = talloc_strdup(mem_ctx, "UNKNOWN"); - } - - return name_buf; -} - -/******************************************************************* - return the IP addr of the remote end of a socket as a string - ******************************************************************/ -char *get_socket_addr(TALLOC_CTX *mem_ctx, int fd) -{ - struct sockaddr sa; - struct sockaddr_in *sockin = (struct sockaddr_in *) (&sa); - int length = sizeof(sa); - - if (fd == -1 || getpeername(fd, &sa, &length) == -1) { - return talloc_strdup(mem_ctx, "0.0.0.0"); - } - - return talloc_strdup(mem_ctx, (char *)inet_ntoa(sockin->sin_addr)); -} - - - -/******************************************************************* -this is like socketpair but uses tcp. It is used by the Samba -regression test code -The function guarantees that nobody else can attach to the socket, -or if they do that this function fails and the socket gets closed -returns 0 on success, -1 on failure -the resulting file descriptors are symmetrical - ******************************************************************/ -static int socketpair_tcp(int fd[2]) -{ - int listener; - struct sockaddr_in sock; - struct sockaddr_in sock2; - socklen_t socklen = sizeof(sock); - int connect_done = 0; - - fd[0] = fd[1] = listener = -1; - - memset(&sock, 0, sizeof(sock)); - - if ((listener = socket(PF_INET, SOCK_STREAM, 0)) == -1) goto failed; - - memset(&sock2, 0, sizeof(sock2)); -#ifdef HAVE_SOCK_SIN_LEN - sock2.sin_len = sizeof(sock2); -#endif - sock2.sin_family = PF_INET; - - bind(listener, (struct sockaddr *)&sock2, sizeof(sock2)); - - if (listen(listener, 1) != 0) goto failed; - - if (getsockname(listener, (struct sockaddr *)&sock, &socklen) != 0) goto failed; - - if ((fd[1] = socket(PF_INET, SOCK_STREAM, 0)) == -1) goto failed; - - set_blocking(fd[1], 0); - - sock.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - - if (connect(fd[1],(struct sockaddr *)&sock,sizeof(sock)) == -1) { - if (errno != EINPROGRESS) goto failed; - } else { - connect_done = 1; - } - - if ((fd[0] = accept(listener, (struct sockaddr *)&sock, &socklen)) == -1) goto failed; - - close(listener); - if (connect_done == 0) { - if (connect(fd[1],(struct sockaddr *)&sock,sizeof(sock)) != 0 - && errno != EISCONN) goto failed; - } - - set_blocking(fd[1], 1); - - /* all OK! */ - return 0; - - failed: - if (fd[0] != -1) close(fd[0]); - if (fd[1] != -1) close(fd[1]); - if (listener != -1) close(listener); - return -1; -} - - -/******************************************************************* -run a program on a local tcp socket, this is used to launch smbd -when regression testing -the return value is a socket which is attached to a subprocess -running "prog". stdin and stdout are attached. stderr is left -attached to the original stderr - ******************************************************************/ -int sock_exec(const char *prog) -{ - int fd[2]; - if (socketpair_tcp(fd) != 0) { - DEBUG(0,("socketpair_tcp failed (%s)\n", strerror(errno))); - return -1; - } - if (fork() == 0) { - close(fd[0]); - close(0); - close(1); - dup(fd[1]); - dup(fd[1]); - exit(system(prog)); - } - close(fd[1]); - return fd[0]; -} - - -/* - determine if a packet is pending for receive on a socket -*/ -BOOL socket_pending(int fd) -{ - fd_set fds; - int selrtn; - struct timeval timeout; - - FD_ZERO(&fds); - FD_SET(fd,&fds); - - /* immediate timeout */ - timeout.tv_sec = 0; - timeout.tv_usec = 0; - - /* yes, this is supposed to be a normal select not a sys_select() */ - selrtn = select(fd+1,&fds,NULL,NULL,&timeout); - - if (selrtn == 1) { - /* the fd is readable */ - return True; - } - - return False; -} |