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
-
. (modified) (1 prop)
-
source3/lib/util_sock.c (modified) (20 diffs)
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 140 141 142 143 144 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 560 803 561 return status; 804 562 } … … 876 634 } 877 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 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 860 861 862 863 864 865 866 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 1562 1563 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 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723
Note:
See TracChangeset
for help on using the changeset viewer.
