📄 util_sock.c
字号:
goto connect_again; } if (ret < 0 && (errno == EINPROGRESS || errno == EALREADY || errno == EAGAIN)) { DEBUG(1,("timeout connecting to %s:%d\n",inet_ntoa(*addr),port)); close(res); return -1; }#ifdef EISCONN if (ret < 0 && errno == EISCONN) { errno = 0; ret = 0; }#endif if (ret < 0) { DEBUG(2,("error connecting to %s:%d (%s)\n", inet_ntoa(*addr),port,strerror(errno))); close(res); return -1; } /* set it blocking again */ set_blocking(res,True); return res;}/**************************************************************************** Create an outgoing TCP socket to any of the addrs. This is for simultaneous connects to port 445 and 139 of a host or even a variety of DC's all of which are equivalent for our purposes.**************************************************************************/BOOL open_any_socket_out(struct sockaddr_in *addrs, int num_addrs, int timeout, int *fd_index, int *fd){ int i, resulting_index, res; int *sockets; BOOL good_connect; fd_set r_fds, wr_fds; struct timeval tv; int maxfd; int connect_loop = 10000; /* 10 milliseconds */ timeout *= 1000; /* convert to microseconds */ sockets = SMB_MALLOC_ARRAY(int, num_addrs); if (sockets == NULL) return False; resulting_index = -1; for (i=0; i<num_addrs; i++) sockets[i] = -1; for (i=0; i<num_addrs; i++) { sockets[i] = socket(PF_INET, SOCK_STREAM, 0); if (sockets[i] < 0) goto done; set_blocking(sockets[i], False); } connect_again: good_connect = False; for (i=0; i<num_addrs; i++) { if (sockets[i] == -1) continue; if (connect(sockets[i], (struct sockaddr *)&(addrs[i]), sizeof(*addrs)) == 0) { /* Rather unlikely as we are non-blocking, but it * might actually happen. */ resulting_index = i; goto done; } if (errno == EINPROGRESS || errno == EALREADY || errno == EAGAIN) { /* These are the error messages that something is progressing. */ good_connect = True; } else if (errno != 0) { /* There was a direct error */ close(sockets[i]); sockets[i] = -1; } } if (!good_connect) { /* All of the connect's resulted in real error conditions */ goto done; } /* Lets see if any of the connect attempts succeeded */ maxfd = 0; FD_ZERO(&wr_fds); FD_ZERO(&r_fds); for (i=0; i<num_addrs; i++) { if (sockets[i] == -1) continue; FD_SET(sockets[i], &wr_fds); FD_SET(sockets[i], &r_fds); if (sockets[i]>maxfd) maxfd = sockets[i]; } tv.tv_sec = 0; tv.tv_usec = connect_loop; res = sys_select(maxfd+1, &r_fds, &wr_fds, NULL, &tv); if (res < 0) goto done; if (res == 0) goto next_round; for (i=0; i<num_addrs; i++) { if (sockets[i] == -1) continue; /* Stevens, Network Programming says that if there's a * successful connect, the socket is only writable. Upon an * error, it's both readable and writable. */ if (FD_ISSET(sockets[i], &r_fds) && FD_ISSET(sockets[i], &wr_fds)) { /* readable and writable, so it's an error */ close(sockets[i]); sockets[i] = -1; continue; } if (!FD_ISSET(sockets[i], &r_fds) && FD_ISSET(sockets[i], &wr_fds)) { /* Only writable, so it's connected */ resulting_index = i; goto done; } } next_round: timeout -= connect_loop; if (timeout <= 0) goto done; connect_loop *= 1.5; if (connect_loop > timeout) connect_loop = timeout; goto connect_again; done: for (i=0; i<num_addrs; i++) { if (i == resulting_index) continue; if (sockets[i] >= 0) close(sockets[i]); } if (resulting_index >= 0) { *fd_index = resulting_index; *fd = sockets[*fd_index]; set_blocking(*fd, True); } free(sockets); return (resulting_index >= 0);}/**************************************************************************** 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 in_addr *addr; 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; 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 in_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 (!strequal(remotehost, hp->h_name) && !strequal(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", inet_ntoa(addr), hp->h_name)); return False;}/******************************************************************* Return the DNS name of the remote end of a socket.******************************************************************/char *get_peer_name(int fd, BOOL force_lookup){ static pstring name_buf; pstring tmp_name; static fstring addr_buf; struct hostent *hp; struct in_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_peer_addr(fd); } p = get_peer_addr(fd); /* it might be the same as the last one - save some DNS work */ if (strcmp(p, addr_buf) == 0) return name_buf; pstrcpy(name_buf,"UNKNOWN"); if (fd == -1) return name_buf; fstrcpy(addr_buf, p); addr = *interpret_addr2(p); /* Look up the remote host name. */ if ((hp = gethostbyaddr((char *)&addr.s_addr, sizeof(addr.s_addr), AF_INET)) == 0) { DEBUG(1,("Gethostbyaddr failed for %s\n",p)); pstrcpy(name_buf, p); } else { pstrcpy(name_buf,(char *)hp->h_name); if (!matchname(name_buf, addr)) { DEBUG(0,("Matchname failed on %s %s\n",name_buf,p)); pstrcpy(name_buf,"UNKNOWN"); } } /* can't pass the same source and dest strings in when you use --enable-developer or the clobber_region() call will get you */ pstrcpy( tmp_name, name_buf ); alpha_strcpy(name_buf, tmp_name, "_-.", sizeof(name_buf)); if (strstr(name_buf,"..")) { pstrcpy(name_buf, "UNKNOWN"); } return name_buf;}/******************************************************************* Return the IP addr of the remote end of a socket as a string. ******************************************************************/char *get_peer_addr(int fd){ struct sockaddr sa; struct sockaddr_in *sockin = (struct sockaddr_in *) (&sa); socklen_t length = sizeof(sa); static fstring addr_buf; fstrcpy(addr_buf,"0.0.0.0"); if (fd == -1) { return addr_buf; } if (getpeername(fd, &sa, &length) < 0) { DEBUG(0,("getpeername failed. Error was %s\n", strerror(errno) )); return addr_buf; } fstrcpy(addr_buf,(char *)inet_ntoa(sockin->sin_addr)); return addr_buf;}/******************************************************************* Create protected unix domain socket. Some unixes cannot set permissions on a ux-dom-sock, so we have to make sure that the directory contains the protection permissions instead. ******************************************************************/int create_pipe_sock(const char *socket_dir, const char *socket_name, mode_t dir_perms){#ifdef HAVE_UNIXSOCKET struct sockaddr_un sunaddr; struct stat st; int sock; mode_t old_umask; pstring path; old_umask = umask(0); /* Create the socket directory or reuse the existing one */ if (lstat(socket_dir, &st) == -1) { if (errno == ENOENT) { /* Create directory */ if (mkdir(socket_dir, dir_perms) == -1) { DEBUG(0, ("error creating socket directory " "%s: %s\n", socket_dir, strerror(errno))); goto out_umask; } } else { DEBUG(0, ("lstat failed on socket directory %s: %s\n", socket_dir, strerror(errno))); goto out_umask; } } else { /* Check ownership and permission on existing directory */ if (!S_ISDIR(st.st_mode)) { DEBUG(0, ("socket directory %s isn't a directory\n", socket_dir)); goto out_umask; } if ((st.st_uid != sec_initial_uid()) || ((st.st_mode & 0777) != dir_perms)) { DEBUG(0, ("invalid permissions on socket directory " "%s\n", socket_dir)); goto out_umask; } } /* Create the socket file */ sock = socket(AF_UNIX, SOCK_STREAM, 0); if (sock == -1) { perror("socket"); goto out_umask; } pstr_sprintf(path, "%s/%s", socket_dir, socket_name); unlink(path); memset(&sunaddr, 0, sizeof(sunaddr)); sunaddr.sun_family = AF_UNIX; safe_strcpy(sunaddr.sun_path, path, sizeof(sunaddr.sun_path)-1); if (bind(sock, (struct sockaddr *)&sunaddr, sizeof(sunaddr)) == -1) { DEBUG(0, ("bind failed on pipe socket %s: %s\n", path, strerror(errno))); goto out_close; } if (listen(sock, 5) == -1) { DEBUG(0, ("listen failed on pipe socket %s: %s\n", path, strerror(errno))); goto out_close; } umask(old_umask); return sock;out_close: close(sock);out_umask: umask(old_umask); return -1;#else DEBUG(0, ("create_pipe_sock: No Unix sockets on this system\n")); return -1;#endif /* HAVE_UNIXSOCKET */}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -