Changeset 745 for trunk/server/source3/lib/util_sock.c
- Timestamp:
- Nov 27, 2012, 4:43:17 PM (13 years ago)
- Location:
- trunk/server
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/server
- Property svn:mergeinfo changed
/vendor/current merged: 581,587,591,594,597,600,615,618,740
- Property svn:mergeinfo changed
-
trunk/server/source3/lib/util_sock.c
r599 r745 21 21 22 22 #include "includes.h" 23 24 /**************************************************************************** 25 Get a port number in host byte order from a sockaddr_storage. 26 ****************************************************************************/ 27 28 uint16_t get_sockaddr_port(const struct sockaddr_storage *pss) 29 { 30 uint16_t port = 0; 31 32 if (pss->ss_family != AF_INET) { 33 #if defined(HAVE_IPV6) 34 /* IPv6 */ 35 const struct sockaddr_in6 *sa6 = 36 (const struct sockaddr_in6 *)pss; 37 port = ntohs(sa6->sin6_port); 38 #endif 39 } else { 40 const struct sockaddr_in *sa = 41 (const struct sockaddr_in *)pss; 42 port = ntohs(sa->sin_port); 43 } 44 return port; 45 } 46 47 /**************************************************************************** 48 Print out an IPv4 or IPv6 address from a struct sockaddr_storage. 49 ****************************************************************************/ 50 51 static char *print_sockaddr_len(char *dest, 52 size_t destlen, 53 const struct sockaddr *psa, 54 socklen_t psalen) 55 { 56 if (destlen > 0) { 57 dest[0] = '\0'; 58 } 59 (void)sys_getnameinfo(psa, 60 psalen, 61 dest, destlen, 62 NULL, 0, 63 NI_NUMERICHOST); 64 return dest; 65 } 66 67 /**************************************************************************** 68 Print out an IPv4 or IPv6 address from a struct sockaddr_storage. 69 ****************************************************************************/ 70 71 char *print_sockaddr(char *dest, 72 size_t destlen, 73 const struct sockaddr_storage *psa) 74 { 75 return print_sockaddr_len(dest, destlen, (struct sockaddr *)psa, 76 sizeof(struct sockaddr_storage)); 77 } 78 79 /**************************************************************************** 80 Print out a canonical IPv4 or IPv6 address from a struct sockaddr_storage. 81 ****************************************************************************/ 82 83 char *print_canonical_sockaddr(TALLOC_CTX *ctx, 84 const struct sockaddr_storage *pss) 85 { 86 char addr[INET6_ADDRSTRLEN]; 87 char *dest = NULL; 88 int ret; 89 90 /* Linux getnameinfo() man pages says port is unitialized if 91 service name is NULL. */ 92 93 ret = sys_getnameinfo((const struct sockaddr *)pss, 94 sizeof(struct sockaddr_storage), 95 addr, sizeof(addr), 96 NULL, 0, 97 NI_NUMERICHOST); 98 if (ret != 0) { 99 return NULL; 100 } 101 102 if (pss->ss_family != AF_INET) { 103 #if defined(HAVE_IPV6) 104 dest = talloc_asprintf(ctx, "[%s]", addr); 105 #else 106 return NULL; 107 #endif 108 } else { 109 dest = talloc_asprintf(ctx, "%s", addr); 110 } 111 112 return dest; 113 } 114 115 /**************************************************************************** 116 Return the string of an IP address (IPv4 or IPv6). 117 ****************************************************************************/ 118 119 static const char *get_socket_addr(int fd, char *addr_buf, size_t addr_len) 120 { 121 struct sockaddr_storage sa; 122 socklen_t length = sizeof(sa); 123 124 /* Ok, returning a hard coded IPv4 address 125 * is bogus, but it's just as bogus as a 126 * zero IPv6 address. No good choice here. 127 */ 128 129 strlcpy(addr_buf, "0.0.0.0", addr_len); 130 131 if (fd == -1) { 132 return addr_buf; 133 } 134 135 if (getsockname(fd, (struct sockaddr *)&sa, &length) < 0) { 136 DEBUG(0,("getsockname failed. Error was %s\n", 137 strerror(errno) )); 138 return addr_buf; 139 } 140 141 return print_sockaddr_len(addr_buf, addr_len, (struct sockaddr *)&sa, length); 142 } 143 144 /**************************************************************************** 145 Return the port number we've bound to on a socket. 146 ****************************************************************************/ 147 148 int get_socket_port(int fd) 149 { 150 struct sockaddr_storage sa; 151 socklen_t length = sizeof(sa); 152 153 if (fd == -1) { 154 return -1; 155 } 156 157 if (getsockname(fd, (struct sockaddr *)&sa, &length) < 0) { 158 DEBUG(0,("getpeername failed. Error was %s\n", 159 strerror(errno) )); 160 return -1; 161 } 162 163 #if defined(HAVE_IPV6) 164 if (sa.ss_family == AF_INET6) { 165 return ntohs(((struct sockaddr_in6 *)&sa)->sin6_port); 166 } 167 #endif 168 if (sa.ss_family == AF_INET) { 169 return ntohs(((struct sockaddr_in *)&sa)->sin_port); 170 } 171 return -1; 172 } 23 #include "system/filesys.h" 24 #include "memcache.h" 25 #include "../lib/async_req/async_sock.h" 26 #include "../lib/util/select.h" 27 #include "interfaces.h" 28 #include "../lib/util/tevent_unix.h" 29 #include "../lib/util/tevent_ntstatus.h" 173 30 174 31 const char *client_name(int fd) … … 180 37 { 181 38 return get_peer_addr(fd,addr,addrlen); 182 }183 184 const char *client_socket_addr(int fd, char *addr, size_t addr_len)185 {186 return get_socket_addr(fd, addr, addr_len);187 39 } 188 40 … … 285 137 #ifdef TCP_QUICKACK 286 138 {"TCP_QUICKACK", IPPROTO_TCP, TCP_QUICKACK, 0, OPT_BOOL}, 139 #endif 140 #ifdef TCP_KEEPALIVE_THRESHOLD 141 {"TCP_KEEPALIVE_THRESHOLD", IPPROTO_TCP, TCP_KEEPALIVE_THRESHOLD, 0, OPT_INT}, 142 #endif 143 #ifdef TCP_KEEPALIVE_ABORT_THRESHOLD 144 {"TCP_KEEPALIVE_ABORT_THRESHOLD", IPPROTO_TCP, TCP_KEEPALIVE_ABORT_THRESHOLD, 0, OPT_INT}, 287 145 #endif 288 146 {NULL,0,0,0,0}}; … … 437 295 size_t *size_ret) 438 296 { 439 fd_set fds; 440 int selrtn; 297 int pollrtn; 441 298 ssize_t readret; 442 299 size_t nread = 0; 443 struct timeval timeout;444 char addr[INET6_ADDRSTRLEN];445 int save_errno;446 300 447 301 /* just checking .... */ … … 465 319 466 320 if (readret == -1) { 467 save_errno = errno; 468 if (fd == get_client_fd()) { 469 /* Try and give an error message 470 * saying what client failed. */ 471 DEBUG(0,("read_fd_with_timeout: " 472 "client %s read error = %s.\n", 473 get_peer_addr(fd,addr,sizeof(addr)), 474 strerror(save_errno) )); 475 } else { 476 DEBUG(0,("read_fd_with_timeout: " 477 "read error = %s.\n", 478 strerror(save_errno) )); 479 } 480 return map_nt_error_from_unix(save_errno); 321 return map_nt_error_from_unix(errno); 481 322 } 482 323 nread += readret; … … 491 332 select always returns true on disk files */ 492 333 493 /* Set initial timeout */494 timeout.tv_sec = (time_t)(time_out / 1000);495 timeout.tv_usec = (long)(1000 * (time_out % 1000));496 497 334 for (nread=0; nread < mincnt; ) { 498 if (fd < 0 || fd >= FD_SETSIZE) { 499 errno = EBADF; 500 return map_nt_error_from_unix(EBADF); 501 } 502 503 FD_ZERO(&fds); 504 FD_SET(fd,&fds); 505 506 selrtn = sys_select_intr(fd+1,&fds,NULL,NULL,&timeout); 335 int revents; 336 337 pollrtn = poll_intr_one_fd(fd, POLLIN|POLLHUP, time_out, 338 &revents); 507 339 508 340 /* Check if error */ 509 if (selrtn == -1) { 510 save_errno = errno; 511 /* something is wrong. Maybe the socket is dead? */ 512 if (fd == get_client_fd()) { 513 /* Try and give an error message saying 514 * what client failed. */ 515 DEBUG(0,("read_fd_with_timeout: timeout " 516 "read for client %s. select error = %s.\n", 517 get_peer_addr(fd,addr,sizeof(addr)), 518 strerror(save_errno) )); 519 } else { 520 DEBUG(0,("read_fd_with_timeout: timeout " 521 "read. select error = %s.\n", 522 strerror(save_errno) )); 523 } 524 return map_nt_error_from_unix(save_errno); 341 if (pollrtn == -1) { 342 return map_nt_error_from_unix(errno); 525 343 } 526 344 527 345 /* Did we timeout ? */ 528 if (selrtn == 0) { 346 if ((pollrtn == 0) || 347 ((revents & (POLLIN|POLLHUP|POLLERR)) == 0)) { 529 348 DEBUG(10,("read_fd_with_timeout: timeout read. " 530 349 "select timed out.\n")); … … 542 361 543 362 if (readret == -1) { 544 save_errno = errno;545 /* the descriptor is probably dead */546 if (fd == get_client_fd()) {547 /* Try and give an error message548 * saying what client failed. */549 DEBUG(0,("read_fd_with_timeout: timeout "550 "read to client %s. read error = %s.\n",551 get_peer_addr(fd,addr,sizeof(addr)),552 strerror(save_errno) ));553 } else {554 DEBUG(0,("read_fd_with_timeout: timeout "555 "read. read error = %s.\n",556 strerror(save_errno) ));557 }558 363 return map_nt_error_from_unix(errno); 559 364 } … … 660 465 ssize_t write_data(int fd, const char *buffer, size_t N) 661 466 { 662 ssize_t ret;663 467 struct iovec iov; 664 468 665 469 iov.iov_base = CONST_DISCARD(void *, buffer); 666 470 iov.iov_len = N; 667 668 ret = write_data_iov(fd, &iov, 1); 669 if (ret >= 0) { 670 return ret; 671 } 672 673 if (fd == get_client_fd()) { 674 char addr[INET6_ADDRSTRLEN]; 675 /* 676 * Try and give an error message saying what client failed. 677 */ 678 DEBUG(0, ("write_data: write failure in writing to client %s. " 679 "Error %s\n", get_peer_addr(fd,addr,sizeof(addr)), 680 strerror(errno))); 681 } else { 682 DEBUG(0,("write_data: write failure. Error = %s\n", 683 strerror(errno) )); 684 } 685 686 return -1; 471 return write_data_iov(fd, &iov, 1); 687 472 } 688 473 … … 730 515 731 516 DEBUG(10,("got smb length of %lu\n",(unsigned long)(*len))); 732 733 return NT_STATUS_OK;734 }735 736 /****************************************************************************737 Read 4 bytes of a smb packet and return the smb length of the packet.738 Store the result in the buffer. This version of the function will739 never return a session keepalive (length of zero).740 Timeout is in milliseconds.741 ****************************************************************************/742 743 NTSTATUS read_smb_length(int fd, char *inbuf, unsigned int timeout,744 size_t *len)745 {746 uint8_t msgtype = SMBkeepalive;747 748 while (msgtype == SMBkeepalive) {749 NTSTATUS status;750 751 status = read_smb_length_return_keepalive(fd, inbuf, timeout,752 len);753 if (!NT_STATUS_IS_OK(status)) {754 return status;755 }756 757 msgtype = CVAL(inbuf, 0);758 }759 760 DEBUG(10,("read_smb_length: got smb length of %lu\n",761 (unsigned long)len));762 517 763 518 return NT_STATUS_OK; … … 782 537 783 538 if (!NT_STATUS_IS_OK(status)) { 784 DEBUG(10, ("receive_smb_raw: %s!\n", nt_errstr(status))); 539 DEBUG(0, ("read_fd_with_timeout failed, read " 540 "error = %s.\n", nt_errstr(status))); 785 541 return status; 786 542 } … … 801 557 802 558 if (!NT_STATUS_IS_OK(status)) { 559 DEBUG(0, ("read_fd_with_timeout failed, read error = " 560 "%s.\n", nt_errstr(status))); 803 561 return status; 804 562 } … … 876 634 } 877 635 636 #ifdef HAVE_IPV6 637 /* 638 * As IPV6_V6ONLY is the default on some systems, 639 * we better try to be consistent and always use it. 640 * 641 * This also avoids using IPv4 via AF_INET6 sockets 642 * and makes sure %I never resolves to a '::ffff:192.168.0.1' 643 * string. 644 */ 645 if (sock.ss_family == AF_INET6) { 646 int val = 1; 647 int ret; 648 649 ret = setsockopt(res, IPPROTO_IPV6, IPV6_V6ONLY, 650 (const void *)&val, sizeof(val)); 651 if (ret == -1) { 652 if(DEBUGLVL(0)) { 653 dbgtext("open_socket_in(): IPV6_ONLY failed: "); 654 dbgtext("%s\n", strerror(errno)); 655 } 656 close(res); 657 return -1; 658 } 659 } 660 #endif 661 878 662 /* now we've got a socket - we need to bind it */ 879 663 if (bind(res, (struct sockaddr *)&sock, slen) == -1 ) { … … 1072 856 } 1073 857 858 /** 859 * @brief open a socket 860 * 861 * @param pss a struct sockaddr_storage defining the address to connect to 862 * @param port to connect to 863 * @param timeout in MILLISECONDS 864 * @param pfd file descriptor returned 865 * 866 * @return NTSTATUS code 867 */ 1074 868 NTSTATUS open_socket_out(const struct sockaddr_storage *pss, uint16_t port, 1075 869 int timeout, int *pfd) … … 1197 991 } 1198 992 1199 /*******************************************************************1200 Create an outgoing TCP socket to the first addr that connects.1201 1202 This is for simultaneous connection attempts to port 445 and 139 of a host1203 or for simultatneous connection attempts to multiple DCs at once. We return1204 a socket fd of the first successful connection.1205 1206 @param[in] addrs list of Internet addresses and ports to connect to1207 @param[in] num_addrs number of address/port pairs in the addrs list1208 @param[in] timeout time after which we stop waiting for a socket connection1209 to succeed, given in milliseconds1210 @param[out] fd_index the entry in addrs which we successfully connected to1211 @param[out] fd fd of the open and connected socket1212 @return true on a successful connection, false if all connection attempts1213 failed or we timed out1214 *******************************************************************/1215 1216 bool open_any_socket_out(struct sockaddr_storage *addrs, int num_addrs,1217 int timeout, int *fd_index, int *fd)1218 {1219 int i, resulting_index, res;1220 int *sockets;1221 bool good_connect;1222 1223 fd_set r_fds, wr_fds;1224 struct timeval tv;1225 int maxfd;1226 1227 int connect_loop = 10000; /* 10 milliseconds */1228 1229 timeout *= 1000; /* convert to microseconds */1230 1231 sockets = SMB_MALLOC_ARRAY(int, num_addrs);1232 1233 if (sockets == NULL)1234 return false;1235 1236 resulting_index = -1;1237 1238 for (i=0; i<num_addrs; i++)1239 sockets[i] = -1;1240 1241 for (i=0; i<num_addrs; i++) {1242 sockets[i] = socket(addrs[i].ss_family, SOCK_STREAM, 0);1243 if (sockets[i] < 0 || sockets[i] >= FD_SETSIZE)1244 goto done;1245 set_blocking(sockets[i], false);1246 }1247 1248 connect_again:1249 good_connect = false;1250 1251 for (i=0; i<num_addrs; i++) {1252 const struct sockaddr * a =1253 (const struct sockaddr *)&(addrs[i]);1254 1255 if (sockets[i] == -1)1256 continue;1257 1258 if (sys_connect(sockets[i], a) == 0) {1259 /* Rather unlikely as we are non-blocking, but it1260 * might actually happen. */1261 resulting_index = i;1262 goto done;1263 }1264 1265 if (errno == EINPROGRESS || errno == EALREADY ||1266 #ifdef EISCONN1267 errno == EISCONN ||1268 #endif1269 errno == EAGAIN || errno == EINTR) {1270 /* These are the error messages that something is1271 progressing. */1272 good_connect = true;1273 } else if (errno != 0) {1274 /* There was a direct error */1275 close(sockets[i]);1276 sockets[i] = -1;1277 }1278 }1279 1280 if (!good_connect) {1281 /* All of the connect's resulted in real error conditions */1282 goto done;1283 }1284 1285 /* Lets see if any of the connect attempts succeeded */1286 1287 maxfd = 0;1288 FD_ZERO(&wr_fds);1289 FD_ZERO(&r_fds);1290 1291 for (i=0; i<num_addrs; i++) {1292 if (sockets[i] < 0 || sockets[i] >= FD_SETSIZE) {1293 /* This cannot happen - ignore if so. */1294 continue;1295 }1296 FD_SET(sockets[i], &wr_fds);1297 FD_SET(sockets[i], &r_fds);1298 if (sockets[i]>maxfd)1299 maxfd = sockets[i];1300 }1301 1302 tv.tv_sec = 0;1303 tv.tv_usec = connect_loop;1304 1305 res = sys_select_intr(maxfd+1, &r_fds, &wr_fds, NULL, &tv);1306 1307 if (res < 0)1308 goto done;1309 1310 if (res == 0)1311 goto next_round;1312 1313 for (i=0; i<num_addrs; i++) {1314 1315 if (sockets[i] < 0 || sockets[i] >= FD_SETSIZE) {1316 /* This cannot happen - ignore if so. */1317 continue;1318 }1319 1320 /* Stevens, Network Programming says that if there's a1321 * successful connect, the socket is only writable. Upon an1322 * error, it's both readable and writable. */1323 1324 if (FD_ISSET(sockets[i], &r_fds) &&1325 FD_ISSET(sockets[i], &wr_fds)) {1326 /* readable and writable, so it's an error */1327 close(sockets[i]);1328 sockets[i] = -1;1329 continue;1330 }1331 1332 if (!FD_ISSET(sockets[i], &r_fds) &&1333 FD_ISSET(sockets[i], &wr_fds)) {1334 /* Only writable, so it's connected */1335 resulting_index = i;1336 goto done;1337 }1338 }1339 1340 next_round:1341 1342 timeout -= connect_loop;1343 if (timeout <= 0)1344 goto done;1345 connect_loop *= 1.5;1346 if (connect_loop > timeout)1347 connect_loop = timeout;1348 goto connect_again;1349 1350 done:1351 for (i=0; i<num_addrs; i++) {1352 if (i == resulting_index)1353 continue;1354 if (sockets[i] >= 0)1355 close(sockets[i]);1356 }1357 1358 if (resulting_index >= 0) {1359 *fd_index = resulting_index;1360 *fd = sockets[*fd_index];1361 set_blocking(*fd, true);1362 }1363 1364 free(sockets);1365 1366 return (resulting_index >= 0);1367 }1368 993 /**************************************************************************** 1369 994 Open a connected UDP socket to host on port … … 1438 1063 1439 1064 if (getpeername(fd, (struct sockaddr *)pss, plength) < 0) { 1440 DEBUG(0,("getpeername failed. Error was %s\n", 1441 strerror(errno) )); 1065 int level = (errno == ENOTCONN) ? 2 : 0; 1066 DEBUG(level, ("getpeername failed. Error was %s\n", 1067 strerror(errno))); 1442 1068 return addr_buf; 1443 1069 } … … 1731 1357 #ifdef __OS2__ 1732 1358 if (asprintf(&path, "\\socket\\samba\\%s\\%s", socket_dir, socket_name) == -1) { 1733 #else 1359 #else 1734 1360 if (asprintf(&path, "%s/%s", socket_dir, socket_name) == -1) { 1735 1361 #endif … … 1863 1489 } 1864 1490 1865 if (is_zero_addr( (struct sockaddr *)&ss) ||1491 if (is_zero_addr(&ss) || 1866 1492 is_loopback_addr((struct sockaddr *)&ss)) { 1867 1493 return false; … … 1933 1559 } 1934 1560 1561 /* Maybe its an IP address? */ 1562 if (is_ipaddress(servername)) { 1563 return is_my_ipaddr(servername); 1564 } 1565 1935 1566 /* Handle possible CNAME records - convert to an IP addr. list. */ 1936 if (!is_ipaddress(servername)){1567 { 1937 1568 /* Use DNS to resolve the name, check all addresses. */ 1938 1569 struct addrinfo *p = NULL; … … 1962 1593 } 1963 1594 1964 /* Maybe its an IP address? */1965 if (is_ipaddress(servername)) {1966 return is_my_ipaddr(servername);1967 }1968 1969 1595 /* No match */ 1970 1596 return false; … … 2052 1678 return state->ret; 2053 1679 } 1680 1681 int poll_one_fd(int fd, int events, int timeout, int *revents) 1682 { 1683 struct pollfd *fds; 1684 int ret; 1685 int saved_errno; 1686 1687 fds = TALLOC_ZERO_ARRAY(talloc_tos(), struct pollfd, 2); 1688 if (fds == NULL) { 1689 errno = ENOMEM; 1690 return -1; 1691 } 1692 fds[0].fd = fd; 1693 fds[0].events = events; 1694 1695 ret = sys_poll(fds, 1, timeout); 1696 1697 /* 1698 * Assign whatever poll did, even in the ret<=0 case. 1699 */ 1700 *revents = fds[0].revents; 1701 saved_errno = errno; 1702 TALLOC_FREE(fds); 1703 errno = saved_errno; 1704 1705 return ret; 1706 } 1707 1708 int poll_intr_one_fd(int fd, int events, int timeout, int *revents) 1709 { 1710 struct pollfd pfd; 1711 int ret; 1712 1713 pfd.fd = fd; 1714 pfd.events = events; 1715 1716 ret = sys_poll_intr(&pfd, 1, timeout); 1717 if (ret <= 0) { 1718 *revents = 0; 1719 return ret; 1720 } 1721 *revents = pfd.revents; 1722 return 1; 1723 }
Note:
See TracChangeset
for help on using the changeset viewer.