PageRenderTime 51ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/src/src/ip.c

https://gitlab.com/Exim/exim
C | 723 lines | 409 code | 115 blank | 199 comment | 103 complexity | d29119ee60259cf8e534227036596288 MD5 | raw file
Possible License(s): GPL-2.0
  1. /*************************************************
  2. * Exim - an Internet mail transport agent *
  3. *************************************************/
  4. /* Copyright (c) University of Cambridge 1995 - 2014 */
  5. /* See the file NOTICE for conditions of use and distribution. */
  6. /* Functions for doing things with sockets. With the advent of IPv6 this has
  7. got messier, so that it's worth pulling out the code into separate functions
  8. that other parts of Exim can call, expecially as there are now several
  9. different places in the code where sockets are used. */
  10. #include "exim.h"
  11. /*************************************************
  12. * Create a socket *
  13. *************************************************/
  14. /* Socket creation happens in a number of places so it's packaged here for
  15. convenience.
  16. Arguments:
  17. type SOCK_DGRAM or SOCK_STREAM
  18. af AF_INET or AF_INET6
  19. Returns: socket number or -1 on failure
  20. */
  21. int
  22. ip_socket(int type, int af)
  23. {
  24. int sock = socket(af, type, 0);
  25. if (sock < 0)
  26. log_write(0, LOG_MAIN, "IPv%c socket creation failed: %s",
  27. (af == AF_INET6)? '6':'4', strerror(errno));
  28. return sock;
  29. }
  30. #if HAVE_IPV6
  31. /*************************************************
  32. * Convert printing address to numeric *
  33. *************************************************/
  34. /* This function converts the textual form of an IP address into a numeric form
  35. in an appropriate structure in an IPv6 environment. The getaddrinfo() function
  36. can (apparently) handle more complicated addresses (e.g. those containing
  37. scopes) than inet_pton() in some environments. We use hints to tell it that the
  38. input must be a numeric address.
  39. However, apparently some operating systems (or libraries) don't support
  40. getaddrinfo(), so there is a build-time option to revert to inet_pton() (which
  41. does not support scopes).
  42. Arguments:
  43. address textual form of the address
  44. addr where to copy back the answer
  45. Returns: nothing - failure provokes a panic-die
  46. */
  47. static void
  48. ip_addrinfo(const uschar *address, struct sockaddr_in6 *saddr)
  49. {
  50. #ifdef IPV6_USE_INET_PTON
  51. if (inet_pton(AF_INET6, CCS address, &saddr->sin6_addr) != 1)
  52. log_write(0, LOG_MAIN|LOG_PANIC_DIE, "unable to parse \"%s\" as an "
  53. "IP address", address);
  54. saddr->sin6_family = AF_INET6;
  55. #else
  56. int rc;
  57. struct addrinfo hints, *res;
  58. memset(&hints, 0, sizeof(hints));
  59. hints.ai_family = AF_INET6;
  60. hints.ai_socktype = SOCK_STREAM;
  61. hints.ai_flags = AI_NUMERICHOST;
  62. if ((rc = getaddrinfo(CCS address, NULL, &hints, &res)) != 0 || res == NULL)
  63. log_write(0, LOG_MAIN|LOG_PANIC_DIE, "unable to parse \"%s\" as an "
  64. "IP address: %s", address,
  65. (rc == 0)? "NULL result returned" : gai_strerror(rc));
  66. memcpy(saddr, res->ai_addr, res->ai_addrlen);
  67. freeaddrinfo(res);
  68. #endif
  69. }
  70. #endif /* HAVE_IPV6 */
  71. /*************************************************
  72. * Bind socket to interface and port *
  73. *************************************************/
  74. int
  75. ip_addr(void * sin_, int af, const uschar * address, int port)
  76. {
  77. union sockaddr_46 * sin = sin_;
  78. memset(sin, 0, sizeof(*sin));
  79. /* Setup code when using an IPv6 socket. The wildcard address is ":", to
  80. ensure an IPv6 socket is used. */
  81. #if HAVE_IPV6
  82. if (af == AF_INET6)
  83. {
  84. if (address[0] == ':' && address[1] == 0)
  85. {
  86. sin->v6.sin6_family = AF_INET6;
  87. sin->v6.sin6_addr = in6addr_any;
  88. }
  89. else
  90. ip_addrinfo(address, &sin->v6); /* Panic-dies on error */
  91. sin->v6.sin6_port = htons(port);
  92. return sizeof(sin->v6);
  93. }
  94. else
  95. #else /* HAVE_IPv6 */
  96. af = af; /* Avoid compiler warning */
  97. #endif /* HAVE_IPV6 */
  98. /* Setup code when using IPv4 socket. The wildcard address is "". */
  99. {
  100. sin->v4.sin_family = AF_INET;
  101. sin->v4.sin_port = htons(port);
  102. sin->v4.sin_addr.s_addr = address[0] == 0
  103. ? (S_ADDR_TYPE)INADDR_ANY
  104. : (S_ADDR_TYPE)inet_addr(CS address);
  105. return sizeof(sin->v4);
  106. }
  107. }
  108. /* This function binds a socket to a local interface address and port. For a
  109. wildcard IPv6 bind, the address is ":".
  110. Arguments:
  111. sock the socket
  112. af AF_INET or AF_INET6 - the socket type
  113. address the IP address, in text form
  114. port the IP port (host order)
  115. Returns: the result of bind()
  116. */
  117. int
  118. ip_bind(int sock, int af, uschar *address, int port)
  119. {
  120. union sockaddr_46 sin;
  121. int s_len = ip_addr(&sin, af, address, port);
  122. return bind(sock, (struct sockaddr *)&sin, s_len);
  123. }
  124. /*************************************************
  125. * Connect socket to remote host *
  126. *************************************************/
  127. /* This function connects a socket to a remote address and port. The socket may
  128. or may not have previously been bound to a local interface. The socket is not
  129. closed, even in cases of error. It is expected that the calling function, which
  130. created the socket, will be the one that closes it.
  131. Arguments:
  132. sock the socket
  133. af AF_INET6 or AF_INET for the socket type
  134. address the remote address, in text form
  135. port the remote port
  136. timeout a timeout (zero for indefinite timeout)
  137. Returns: 0 on success; -1 on failure, with errno set
  138. */
  139. int
  140. ip_connect(int sock, int af, const uschar *address, int port, int timeout)
  141. {
  142. struct sockaddr_in s_in4;
  143. struct sockaddr *s_ptr;
  144. int s_len, rc, save_errno;
  145. /* For an IPv6 address, use an IPv6 sockaddr structure. */
  146. #if HAVE_IPV6
  147. struct sockaddr_in6 s_in6;
  148. if (af == AF_INET6)
  149. {
  150. memset(&s_in6, 0, sizeof(s_in6));
  151. ip_addrinfo(address, &s_in6); /* Panic-dies on error */
  152. s_in6.sin6_port = htons(port);
  153. s_ptr = (struct sockaddr *)&s_in6;
  154. s_len = sizeof(s_in6);
  155. }
  156. else
  157. #else /* HAVE_IPV6 */
  158. af = af; /* Avoid compiler warning */
  159. #endif /* HAVE_IPV6 */
  160. /* For an IPv4 address, use an IPv4 sockaddr structure, even on a system with
  161. IPv6 support. */
  162. {
  163. memset(&s_in4, 0, sizeof(s_in4));
  164. s_in4.sin_family = AF_INET;
  165. s_in4.sin_port = htons(port);
  166. s_in4.sin_addr.s_addr = (S_ADDR_TYPE)inet_addr(CCS address);
  167. s_ptr = (struct sockaddr *)&s_in4;
  168. s_len = sizeof(s_in4);
  169. }
  170. /* If no connection timeout is set, just call connect() without setting a
  171. timer, thereby allowing the inbuilt OS timeout to operate. */
  172. sigalrm_seen = FALSE;
  173. if (timeout > 0) alarm(timeout);
  174. rc = connect(sock, s_ptr, s_len);
  175. save_errno = errno;
  176. alarm(0);
  177. /* There is a testing facility for simulating a connection timeout, as I
  178. can't think of any other way of doing this. It converts a connection refused
  179. into a timeout if the timeout is set to 999999. */
  180. if (running_in_test_harness && save_errno == ECONNREFUSED && timeout == 999999)
  181. {
  182. rc = -1;
  183. save_errno = EINTR;
  184. sigalrm_seen = TRUE;
  185. }
  186. /* Success */
  187. if (rc >= 0) return 0;
  188. /* A failure whose error code is "Interrupted system call" is in fact
  189. an externally applied timeout if the signal handler has been run. */
  190. errno = save_errno == EINTR && sigalrm_seen ? ETIMEDOUT : save_errno;
  191. return -1;
  192. }
  193. /*************************************************
  194. * Create connected socket to remote host *
  195. *************************************************/
  196. /* Create a socket and connect to host (name or number, ipv6 ok)
  197. at one of port-range.
  198. Arguments:
  199. type SOCK_DGRAM or SOCK_STREAM
  200. af AF_INET6 or AF_INET for the socket type
  201. address the remote address, in text form
  202. portlo,porthi the remote port range
  203. timeout a timeout
  204. connhost if not NULL, host_item filled in with connection details
  205. errstr pointer for allocated string on error
  206. Return:
  207. socket fd, or -1 on failure (having allocated an error string)
  208. */
  209. int
  210. ip_connectedsocket(int type, const uschar * hostname, int portlo, int porthi,
  211. int timeout, host_item * connhost, uschar ** errstr)
  212. {
  213. int namelen, port;
  214. host_item shost;
  215. host_item *h;
  216. int af = 0, fd, fd4 = -1, fd6 = -1;
  217. shost.next = NULL;
  218. shost.address = NULL;
  219. shost.port = portlo;
  220. shost.mx = -1;
  221. namelen = Ustrlen(hostname);
  222. /* Anything enclosed in [] must be an IP address. */
  223. if (hostname[0] == '[' &&
  224. hostname[namelen - 1] == ']')
  225. {
  226. uschar * host = string_copy(hostname);
  227. host[namelen - 1] = 0;
  228. host++;
  229. if (string_is_ip_address(host, NULL) == 0)
  230. {
  231. *errstr = string_sprintf("malformed IP address \"%s\"", hostname);
  232. return -1;
  233. }
  234. shost.name = shost.address = host;
  235. }
  236. /* Otherwise check for an unadorned IP address */
  237. else if (string_is_ip_address(hostname, NULL) != 0)
  238. shost.name = shost.address = string_copy(hostname);
  239. /* Otherwise lookup IP address(es) from the name */
  240. else
  241. {
  242. shost.name = string_copy(hostname);
  243. if (host_find_byname(&shost, NULL, HOST_FIND_QUALIFY_SINGLE,
  244. NULL, FALSE) != HOST_FOUND)
  245. {
  246. *errstr = string_sprintf("no IP address found for host %s", shost.name);
  247. return -1;
  248. }
  249. }
  250. /* Try to connect to the server - test each IP till one works */
  251. for (h = &shost; h != NULL; h = h->next)
  252. {
  253. fd = (Ustrchr(h->address, ':') != 0)
  254. ? (fd6 < 0) ? (fd6 = ip_socket(type, af = AF_INET6)) : fd6
  255. : (fd4 < 0) ? (fd4 = ip_socket(type, af = AF_INET )) : fd4;
  256. if (fd < 0)
  257. {
  258. *errstr = string_sprintf("failed to create socket: %s", strerror(errno));
  259. goto bad;
  260. }
  261. for(port = portlo; port <= porthi; port++)
  262. if (ip_connect(fd, af, h->address, port, timeout) == 0)
  263. {
  264. if (fd != fd6) close(fd6);
  265. if (fd != fd4) close(fd4);
  266. if (connhost)
  267. {
  268. h->port = port;
  269. *connhost = *h;
  270. connhost->next = NULL;
  271. }
  272. return fd;
  273. }
  274. }
  275. *errstr = string_sprintf("failed to connect to any address for %s: %s",
  276. hostname, strerror(errno));
  277. bad:
  278. close(fd4); close(fd6); return -1;
  279. }
  280. int
  281. ip_tcpsocket(const uschar * hostport, uschar ** errstr, int tmo)
  282. {
  283. int scan;
  284. uschar hostname[256];
  285. unsigned int portlow, porthigh;
  286. /* extract host and port part */
  287. scan = sscanf(CS hostport, "%255s %u-%u", hostname, &portlow, &porthigh);
  288. if (scan != 3)
  289. {
  290. if (scan != 2)
  291. {
  292. *errstr = string_sprintf("invalid socket '%s'", hostport);
  293. return -1;
  294. }
  295. porthigh = portlow;
  296. }
  297. return ip_connectedsocket(SOCK_STREAM, hostname, portlow, porthigh,
  298. tmo, NULL, errstr);
  299. }
  300. int
  301. ip_unixsocket(const uschar * path, uschar ** errstr)
  302. {
  303. int sock;
  304. struct sockaddr_un server;
  305. if ((sock = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
  306. {
  307. *errstr = US"can't open UNIX socket.";
  308. return -1;
  309. }
  310. server.sun_family = AF_UNIX;
  311. Ustrncpy(server.sun_path, path, sizeof(server.sun_path)-1);
  312. server.sun_path[sizeof(server.sun_path)-1] = '\0';
  313. if (connect(sock, (struct sockaddr *) &server, sizeof(server)) < 0)
  314. {
  315. int err = errno;
  316. (void)close(sock);
  317. *errstr = string_sprintf("unable to connect to UNIX socket (%s): %s",
  318. path, strerror(err));
  319. return -1;
  320. }
  321. return sock;
  322. }
  323. int
  324. ip_streamsocket(const uschar * spec, uschar ** errstr, int tmo)
  325. {
  326. return *spec == '/'
  327. ? ip_unixsocket(spec, errstr) : ip_tcpsocket(spec, errstr, tmo);
  328. }
  329. /*************************************************
  330. * Set keepalive on a socket *
  331. *************************************************/
  332. /* Can be called for both incoming and outgoing sockets.
  333. Arguments:
  334. sock the socket
  335. address the remote host address, for failure logging
  336. torf true for outgoing connection, false for incoming
  337. Returns: nothing
  338. */
  339. void
  340. ip_keepalive(int sock, const uschar *address, BOOL torf)
  341. {
  342. int fodder = 1;
  343. if (setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE,
  344. (uschar *)(&fodder), sizeof(fodder)) != 0)
  345. log_write(0, LOG_MAIN, "setsockopt(SO_KEEPALIVE) on connection %s %s "
  346. "failed: %s", torf? "to":"from", address, strerror(errno));
  347. }
  348. /*************************************************
  349. * Receive from a socket with timeout *
  350. *************************************************/
  351. /*
  352. Arguments:
  353. fd the file descriptor
  354. timeout the timeout, seconds
  355. Returns: TRUE => ready for i/o
  356. FALSE => timed out, or other error
  357. */
  358. BOOL
  359. fd_ready(int fd, int timeout)
  360. {
  361. fd_set select_inset;
  362. struct timeval tv;
  363. time_t start_recv = time(NULL);
  364. int rc;
  365. if (timeout <= 0)
  366. {
  367. errno = ETIMEDOUT;
  368. return FALSE;
  369. }
  370. /* Wait until the socket is ready */
  371. do
  372. {
  373. FD_ZERO (&select_inset);
  374. FD_SET (fd, &select_inset);
  375. tv.tv_sec = timeout;
  376. tv.tv_usec = 0;
  377. /*DEBUG(D_transport) debug_printf("waiting for data on fd\n");*/
  378. rc = select(fd + 1, (SELECT_ARG2_TYPE *)&select_inset, NULL, NULL, &tv);
  379. /* If some interrupt arrived, just retry. We presume this to be rare,
  380. but it can happen (e.g. the SIGUSR1 signal sent by exiwhat causes
  381. select() to exit).
  382. Aug 2004: Somebody set up a cron job that ran exiwhat every 2 minutes, making
  383. the interrupt not at all rare. Since the timeout is typically more than 2
  384. minutes, the effect was to block the timeout completely. To prevent this
  385. happening again, we do an explicit time test. */
  386. if (rc < 0 && errno == EINTR)
  387. {
  388. DEBUG(D_transport) debug_printf("EINTR while waiting for socket data\n");
  389. if (time(NULL) - start_recv < timeout) continue;
  390. DEBUG(D_transport) debug_printf("total wait time exceeds timeout\n");
  391. }
  392. /* Handle a timeout, and treat any other select error as a timeout, including
  393. an EINTR when we have been in this loop for longer than timeout. */
  394. if (rc <= 0)
  395. {
  396. errno = ETIMEDOUT;
  397. return FALSE;
  398. }
  399. /* If the socket is ready, break out of the loop. */
  400. }
  401. while (!FD_ISSET(fd, &select_inset));
  402. return TRUE;
  403. }
  404. /* The timeout is implemented using select(), and we loop to cover select()
  405. getting interrupted, and the possibility of select() returning with a positive
  406. result but no ready descriptor. Is this in fact possible?
  407. Arguments:
  408. sock the socket
  409. buffer to read into
  410. bufsize the buffer size
  411. timeout the timeout
  412. Returns: > 0 => that much data read
  413. <= 0 on error or EOF; errno set - zero for EOF
  414. */
  415. int
  416. ip_recv(int sock, uschar *buffer, int buffsize, int timeout)
  417. {
  418. int rc;
  419. if (!fd_ready(sock, timeout))
  420. return -1;
  421. /* The socket is ready, read from it (via TLS if it's active). On EOF (i.e.
  422. close down of the connection), set errno to zero; otherwise leave it alone. */
  423. #ifdef SUPPORT_TLS
  424. if (tls_out.active == sock)
  425. rc = tls_read(FALSE, buffer, buffsize);
  426. else if (tls_in.active == sock)
  427. rc = tls_read(TRUE, buffer, buffsize);
  428. else
  429. #endif
  430. rc = recv(sock, buffer, buffsize, 0);
  431. if (rc > 0) return rc;
  432. if (rc == 0) errno = 0;
  433. return -1;
  434. }
  435. /*************************************************
  436. * Lookup address family of potential socket *
  437. *************************************************/
  438. /* Given a file-descriptor, check to see if it's a socket and, if so,
  439. return the address family; detects IPv4 vs IPv6. If not a socket then
  440. return -1.
  441. The value 0 is typically AF_UNSPEC, which should not be seen on a connected
  442. fd. If the return is -1, the errno will be from getsockname(); probably
  443. ENOTSOCK or ECONNRESET.
  444. Arguments: socket-or-not fd
  445. Returns: address family or -1
  446. */
  447. int
  448. ip_get_address_family(int fd)
  449. {
  450. struct sockaddr_storage ss;
  451. socklen_t sslen = sizeof(ss);
  452. if (getsockname(fd, (struct sockaddr *) &ss, &sslen) < 0)
  453. return -1;
  454. return (int) ss.ss_family;
  455. }
  456. /*************************************************
  457. * Lookup DSCP settings for a socket *
  458. *************************************************/
  459. struct dscp_name_tableentry {
  460. const uschar *name;
  461. int value;
  462. };
  463. /* Keep both of these tables sorted! */
  464. static struct dscp_name_tableentry dscp_table[] = {
  465. #ifdef IPTOS_DSCP_AF11
  466. { CUS"af11", IPTOS_DSCP_AF11 },
  467. { CUS"af12", IPTOS_DSCP_AF12 },
  468. { CUS"af13", IPTOS_DSCP_AF13 },
  469. { CUS"af21", IPTOS_DSCP_AF21 },
  470. { CUS"af22", IPTOS_DSCP_AF22 },
  471. { CUS"af23", IPTOS_DSCP_AF23 },
  472. { CUS"af31", IPTOS_DSCP_AF31 },
  473. { CUS"af32", IPTOS_DSCP_AF32 },
  474. { CUS"af33", IPTOS_DSCP_AF33 },
  475. { CUS"af41", IPTOS_DSCP_AF41 },
  476. { CUS"af42", IPTOS_DSCP_AF42 },
  477. { CUS"af43", IPTOS_DSCP_AF43 },
  478. { CUS"ef", IPTOS_DSCP_EF },
  479. #endif
  480. #ifdef IPTOS_LOWCOST
  481. { CUS"lowcost", IPTOS_LOWCOST },
  482. #endif
  483. { CUS"lowdelay", IPTOS_LOWDELAY },
  484. #ifdef IPTOS_MINCOST
  485. { CUS"mincost", IPTOS_MINCOST },
  486. #endif
  487. { CUS"reliability", IPTOS_RELIABILITY },
  488. { CUS"throughput", IPTOS_THROUGHPUT }
  489. };
  490. static int dscp_table_size =
  491. sizeof(dscp_table) / sizeof(struct dscp_name_tableentry);
  492. /* DSCP values change by protocol family, and so do the options used for
  493. setsockopt(); this utility does all the lookups. It takes an unexpanded
  494. option string, expands it, strips off affix whitespace, then checks if it's
  495. a number. If all of what's left is a number, then that's how the option will
  496. be parsed and success/failure is a range check. If it's not all a number,
  497. then it must be a supported keyword.
  498. Arguments:
  499. dscp_name a string, so far unvalidated
  500. af address_family in use
  501. level setsockopt level to use
  502. optname setsockopt name to use
  503. dscp_value value for dscp_name
  504. Returns: TRUE if okay to setsockopt(), else FALSE
  505. *level and *optname may be set even if FALSE is returned
  506. */
  507. BOOL
  508. dscp_lookup(const uschar *dscp_name, int af,
  509. int *level, int *optname, int *dscp_value)
  510. {
  511. uschar *dscp_lookup, *p;
  512. int first, last;
  513. long rawlong;
  514. if (af == AF_INET)
  515. {
  516. *level = IPPROTO_IP;
  517. *optname = IP_TOS;
  518. }
  519. #if HAVE_IPV6 && defined(IPV6_TCLASS)
  520. else if (af == AF_INET6)
  521. {
  522. *level = IPPROTO_IPV6;
  523. *optname = IPV6_TCLASS;
  524. }
  525. #endif
  526. else
  527. {
  528. DEBUG(D_transport)
  529. debug_printf("Unhandled address family %d in dscp_lookup()\n", af);
  530. return FALSE;
  531. }
  532. if (!dscp_name)
  533. {
  534. DEBUG(D_transport)
  535. debug_printf("[empty DSCP]\n");
  536. return FALSE;
  537. }
  538. dscp_lookup = expand_string(US dscp_name);
  539. if (dscp_lookup == NULL || *dscp_lookup == '\0')
  540. return FALSE;
  541. p = dscp_lookup + Ustrlen(dscp_lookup) - 1;
  542. while (isspace(*p)) *p-- = '\0';
  543. while (isspace(*dscp_lookup) && dscp_lookup < p) dscp_lookup++;
  544. if (*dscp_lookup == '\0')
  545. return FALSE;
  546. rawlong = Ustrtol(dscp_lookup, &p, 0);
  547. if (p != dscp_lookup && *p == '\0')
  548. {
  549. /* We have six bits available, which will end up shifted to fit in 0xFC mask.
  550. RFC 2597 defines the values unshifted. */
  551. if (rawlong < 0 || rawlong > 0x3F)
  552. {
  553. DEBUG(D_transport)
  554. debug_printf("DSCP value %ld out of range, ignored.\n", rawlong);
  555. return FALSE;
  556. }
  557. *dscp_value = rawlong << 2;
  558. return TRUE;
  559. }
  560. first = 0;
  561. last = dscp_table_size;
  562. while (last > first)
  563. {
  564. int middle = (first + last)/2;
  565. int c = Ustrcmp(dscp_lookup, dscp_table[middle].name);
  566. if (c == 0)
  567. {
  568. *dscp_value = dscp_table[middle].value;
  569. return TRUE;
  570. }
  571. else if (c > 0)
  572. first = middle + 1;
  573. else
  574. last = middle;
  575. }
  576. return FALSE;
  577. }
  578. void
  579. dscp_list_to_stream(FILE *stream)
  580. {
  581. int i;
  582. for (i=0; i < dscp_table_size; ++i)
  583. fprintf(stream, "%s\n", dscp_table[i].name);
  584. }
  585. /* End of ip.c */
  586. /* vi: aw ai sw=2
  587. */