PageRenderTime 57ms CodeModel.GetById 15ms RepoModel.GetById 1ms app.codeStats 0ms

/src/sflsock.c

https://github.com/gbluma/gsl
C | 2126 lines | 1216 code | 252 blank | 658 comment | 188 complexity | 4a9dbb63d0825e46972cab6827944732 MD5 | raw file
Possible License(s): GPL-3.0, BSD-3-Clause
  1. /*===========================================================================*
  2. * *
  3. * sflsock.c - Socket handling functions *
  4. * *
  5. * Copyright (c) 1991-2010 iMatix Corporation *
  6. * *
  7. * ------------------ GPL Licensed Source Code ------------------ *
  8. * iMatix makes this software available under the GNU General *
  9. * Public License (GPL) license for open source projects. For *
  10. * details of the GPL license please see www.gnu.org or read the *
  11. * file license.gpl provided in this package. *
  12. * *
  13. * This program is free software; you can redistribute it and/or *
  14. * modify it under the terms of the GNU General Public License as *
  15. * published by the Free Software Foundation; either version 2 of *
  16. * the License, or (at your option) any later version. *
  17. * *
  18. * This program is distributed in the hope that it will be useful, *
  19. * but WITHOUT ANY WARRANTY; without even the implied warranty of *
  20. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
  21. * GNU General Public License for more details. *
  22. * *
  23. * You should have received a copy of the GNU General Public *
  24. * License along with this program in the file 'license.gpl'; if *
  25. * not, write to the Free Software Foundation, Inc., 59 Temple *
  26. * Place - Suite 330, Boston, MA 02111-1307, USA. *
  27. * *
  28. * You can also license this software under iMatix's General Terms *
  29. * of Business (GTB) for commercial projects. If you have not *
  30. * explicitly licensed this software under the iMatix GTB you may *
  31. * only use it under the terms of the GNU General Public License. *
  32. * *
  33. * For more information, send an email to info@imatix.com. *
  34. * -------------------------------------------------------------- *
  35. *===========================================================================*/
  36. #include "prelude.h" /* Universal header file */
  37. #include "sfllist.h" /* List-management functions */
  38. #include "sflmem.h" /* Memory-allocation functions */
  39. #include "sflsymb.h" /* Symbol-table functions */
  40. #include "sfltok.h" /* Token-handling functions */
  41. #include "sfluid.h" /* User/group functions */
  42. #include "sflcons.h" /* Console i/o functions */
  43. #include "sflfile.h" /* File handling functions */
  44. #include "sflprint.h" /* snprintf functions */
  45. #include "sflsock.h" /* Prototypes for functions */
  46. /* Implementation notes
  47. *
  48. * These functions work on 16-bit Windows, 32-bit Windows, 32-bit UNIX,
  49. * 64-bit UNIX, Digital OpenVMS. The size of a socket handle varies from
  50. * 16 bits to 64 bits. All native socket functions define a socket handle
  51. * as 'int'. However, we need a fixed-length external representation. So,
  52. * we define a type, 'sock_t', which is a qbyte (32 bits). Outside this
  53. * package, sockets are always a 'sock_t'. Internally, we always use an
  54. * (SOCKET) cast when passing a sock_t to a system function like connect().
  55. * If the system does not support sockets we fake them just a little.
  56. *
  57. * Modifications Oct 7 1998 for Unix by Grant McDorman <grant@isgtec.com> to
  58. * allow running with the program suid root; it will run as the user until
  59. * the socket must be opened; at that time, it will briefly switch to root
  60. * and then return to the actual user id.
  61. */
  62. /* Global variables */
  63. int
  64. ip_portbase = 0; /* Base for created services */
  65. Bool
  66. ip_nonblock = TRUE; /* Create non-blocking sockets */
  67. qbyte
  68. ip_passive = INADDR_ANY; /* IP address for passive connects */
  69. int
  70. ip_sockets = 0; /* Number of open sockets */
  71. /* The connect_error_value holds the last recorded error cause after a */
  72. /* connection attempt. */
  73. static int
  74. connect_error_value = 0;
  75. char
  76. *connect_errlist [] = { /* Corresponding error messages */
  77. "No errors",
  78. "System does not support sockets",
  79. "Host is not known",
  80. "Service or port not known",
  81. "Protocol not known",
  82. "Connection failed on socket()",
  83. "Connection failed on connect()",
  84. "Port is already used by another server",
  85. "Connection failed on listen()"
  86. };
  87. /* Internal functions used to create passive and active connections */
  88. #if (defined (DOES_SOCKETS))
  89. static void prepare_socket (sock_t handle);
  90. # if (defined (__WINDOWS__))
  91. static int win_error (int rc);
  92. # endif
  93. #endif
  94. /* ---------------------------------------------------------------------[<]-
  95. Function: sock_init
  96. Synopsis: Initialise the internet protocol. On most systems this is a
  97. null call. On some systems this loads dynamic libraries. Returns 0
  98. if everything was okay, else returns SOCKET_ERROR. You should call
  99. sock_term() when your program ends.
  100. ---------------------------------------------------------------------[>]-*/
  101. int
  102. sock_init (void)
  103. {
  104. #if (defined (__WINDOWS__))
  105. WORD
  106. wVersionRequested; /* We really want Winsock 1.1 */
  107. WSADATA
  108. wsaData;
  109. wVersionRequested = 0x0101; /* ... but we'll take 1.1 */
  110. if (WSAStartup (wVersionRequested, &wsaData) == 0)
  111. return (0);
  112. else
  113. return ((int) SOCKET_ERROR);
  114. #elif (defined (__UTYPE_BEOS))
  115. /* BeOS numbers sockets from 0 upwards, but this causes havoc with
  116. * programs that expect a BSD-style numbering of 1 or higher. We
  117. * force compatibility by creating (and wasting) one socket so that
  118. * further socket handles are guaranteed >0.
  119. */
  120. create_socket ("tcp");
  121. return (0);
  122. #elif (defined (DOES_SOCKETS) || defined (FAKE_SOCKETS))
  123. return (0);
  124. #else
  125. connect_error_value = IP_NOSOCKETS;
  126. return ((int) SOCKET_ERROR); /* Sockets not supported */
  127. #endif
  128. }
  129. /* ---------------------------------------------------------------------[<]-
  130. Function: sock_term
  131. Synopsis: Shuts-down the internet protocol. On most systems this is a
  132. null call. On some systems this unloads dynamic libraries. Returns -1
  133. if there was an error, or 0 if everything was okay. See sock_init().
  134. ---------------------------------------------------------------------[>]-*/
  135. int
  136. sock_term (void)
  137. {
  138. #if (defined (__WINDOWS__))
  139. WSACleanup ();
  140. #endif
  141. return (0);
  142. }
  143. /* ---------------------------------------------------------------------[<]-
  144. Function: passive_TCP
  145. Synopsis: Creates a passive bound TCP socket for the specified service.
  146. Returns socket number or INVALID_SOCKET. If it returns INVALID_SOCKET,
  147. you can get the reason for the error by calling connect_error (). This
  148. may be one of:
  149. <TABLE>
  150. IP_NOSOCKETS Sockets not supported on this system
  151. IP_BADSERVICE Service cannot be converted to port number
  152. IP_BADPROTOCOL Cannot understand protocol name
  153. IP_SOCKETERROR Cannot create the passive socket
  154. IP_BINDERROR Cannot bind to the port
  155. IP_LISTENERROR Cannot listen to port
  156. </TABLE>
  157. ---------------------------------------------------------------------[>]-*/
  158. sock_t
  159. passive_TCP (
  160. const char *service, /* Service name or port as string */
  161. int queue_length /* Queue length for listen() */
  162. )
  163. {
  164. ASSERT (service && *service);
  165. ASSERT (queue_length > 0);
  166. return (passive_socket (service, "tcp", queue_length));
  167. }
  168. /* ---------------------------------------------------------------------[<]-
  169. Function: passive_UDP
  170. Synopsis: Creates a passive UDP socket for the specified service.
  171. Returns socket number or INVALID_SOCKET. If it returns INVALID_SOCKET,
  172. you can get the reason for the error by calling connect_error (). This
  173. may be one of:
  174. <TABLE>
  175. IP_NOSOCKETS Sockets not supported on this system
  176. IP_BADSERVICE Service cannot be converted to port number
  177. IP_BADPROTOCOL Cannot understand protocol name
  178. IP_SOCKETERROR Cannot create the passive socket
  179. IP_BINDERROR Cannot bind to the port
  180. </TABLE>
  181. ---------------------------------------------------------------------[>]-*/
  182. sock_t
  183. passive_UDP (
  184. const char *service /* Service name or port as string */
  185. )
  186. {
  187. ASSERT (service && *service);
  188. return (passive_socket (service, "udp", 0));
  189. }
  190. /* ---------------------------------------------------------------------[<]-
  191. Function: passive_socket
  192. Synopsis:
  193. Creates a passive TCP or UDP socket. This function allows a server
  194. program to create a master socket, so that connections can be accepted.
  195. Used by the passive_TCP and passive_UDP functions. Returns a socket
  196. number or INVALID_SOCKET. If it returns INVALID_SOCKET, you can get the
  197. reason for the error by calling connect_error (). This may be one of:
  198. <TABLE>
  199. IP_NOSOCKETS Sockets not supported on this system
  200. IP_BADSERVICE Service cannot be converted to port number
  201. IP_BADPROTOCOL Cannot understand protocol name
  202. IP_SOCKETERROR Cannot create the passive socket
  203. IP_BINDERROR Cannot bind to the port
  204. IP_LISTENERROR Cannot listen to port
  205. </TABLE>
  206. By default, opens a socket on all available IP addresses. You can open
  207. the socket on a specific address, by setting the global variable
  208. ip_passive to the address (in network order). This variable is reset
  209. to INADDR_ANY after each call to passive_socket or one of the functions
  210. that calls it.
  211. ---------------------------------------------------------------------[>]-*/
  212. sock_t
  213. passive_socket (
  214. const char *service, /* Service name or port as string */
  215. const char *protocol, /* Protocol "tcp" or "udp" */
  216. int queue_length /* Queue length for TCP sockets */
  217. )
  218. {
  219. #if (defined (DOES_SOCKETS))
  220. struct servent
  221. *pse; /* Service information entry */
  222. struct sockaddr_in
  223. sin; /* Internet end-point address */
  224. sock_t
  225. handle; /* Socket from socket() call */
  226. ASSERT (service && *service);
  227. ASSERT (protocol && *protocol);
  228. connect_error_value = IP_NOERROR; /* Assume no errors */
  229. memset ((void *) &sin, 0, sizeof (sin));
  230. sin.sin_family = AF_INET;
  231. sin.sin_addr.s_addr = ip_passive;
  232. ip_passive = INADDR_ANY; /* Reset passive address */
  233. /* To allow privileged operations, if possible */
  234. set_uid_root ();
  235. /* Map service name to port number */
  236. pse = getservbyname (service, protocol);
  237. if (pse)
  238. sin.sin_port = htons ((dbyte) (ntohs (pse-> s_port) + ip_portbase));
  239. else
  240. {
  241. sin.sin_port = atoi (service);
  242. if (sin.sin_port + ip_portbase > 0)
  243. sin.sin_port = htons ((dbyte) (sin.sin_port + ip_portbase));
  244. else
  245. {
  246. connect_error_value = IP_BADSERVICE;
  247. set_uid_user ();
  248. return (INVALID_SOCKET);
  249. }
  250. }
  251. handle = create_socket (protocol);
  252. if (handle == INVALID_SOCKET) /* Cannot create the socket */
  253. {
  254. set_uid_user ();
  255. return (INVALID_SOCKET);
  256. }
  257. /* Bind the socket */
  258. if (bind ((SOCKET) handle, (struct sockaddr *) &sin,
  259. sizeof (sin)) == SOCKET_ERROR)
  260. {
  261. connect_error_value = IP_BINDERROR;
  262. set_uid_user ();
  263. return (INVALID_SOCKET); /* Cannot bind to port */
  264. }
  265. set_uid_user ();
  266. /* Specify incoming queue length for stream socket */
  267. if (streq (protocol, "tcp")
  268. && listen ((SOCKET) handle, queue_length) == SOCKET_ERROR)
  269. {
  270. connect_error_value = IP_LISTENERROR;
  271. return (INVALID_SOCKET); /* Cannot listen on port */
  272. }
  273. return (handle);
  274. #elif (defined (FAKE_SOCKETS))
  275. return (1); /* Return dummy handle */
  276. #else
  277. connect_error_value = IP_NOSOCKETS;
  278. return (INVALID_SOCKET); /* Sockets not supported */
  279. #endif
  280. }
  281. /* ---------------------------------------------------------------------[<]-
  282. Function: create_socket
  283. Synopsis:
  284. Creates a TCP or UDP socket. The socket is not connected. To use
  285. with TCP services you must bind or connect the socket. You can use
  286. the socket with UDP services - e.g. read_UDP () - immediately. Returns
  287. a socket number or INVALID_SOCKET, in which case you can get the reason
  288. for the error by calling connect_error (). This may be one of:
  289. <TABLE>
  290. IP_NOSOCKETS Sockets not supported on this system
  291. IP_BADPROTOCOL Cannot understand protocol name
  292. IP_SOCKETERROR Cannot create the socket
  293. </TABLE>
  294. ---------------------------------------------------------------------[>]-*/
  295. sock_t
  296. create_socket (
  297. const char *protocol /* Protocol "tcp" or "udp" */
  298. )
  299. {
  300. #if (defined (DOES_SOCKETS))
  301. struct protoent
  302. *ppe; /* Protocol information entry */
  303. int
  304. # if (!defined (__WINDOWS__))
  305. true_value = 1, /* Boolean value for setsockopt() */
  306. # endif
  307. sock_type; /* Type of socket we want */
  308. sock_t
  309. handle; /* Socket from socket() call */
  310. ASSERT (protocol && *protocol);
  311. connect_error_value = IP_NOERROR; /* Assume no errors */
  312. /* Map protocol name to protocol number */
  313. ppe = getprotobyname (protocol);
  314. if (ppe == NULL) /* Cannot get protocol entry */
  315. {
  316. connect_error_value = IP_BADPROTOCOL;
  317. return (INVALID_SOCKET);
  318. }
  319. /* Use protocol string to choose a socket type */
  320. if (streq (protocol, "udp"))
  321. sock_type = SOCK_DGRAM;
  322. else
  323. sock_type = SOCK_STREAM;
  324. /* Allocate a socket */
  325. handle = (sock_t) socket (AF_INET, sock_type, ppe-> p_proto);
  326. if (handle == INVALID_SOCKET) /* Cannot create passive socket */
  327. {
  328. connect_error_value = IP_SOCKETERROR;
  329. return (INVALID_SOCKET);
  330. }
  331. # if (!defined (__WINDOWS__))
  332. /* On BSD-socket systems we need to do this to allow the server to
  333. * restart on a previously-used socket, without an annoying timeout
  334. * of several minutes. With winsock the reuseaddr option lets the
  335. * server work with an already-used socket (!), so we don't do it.
  336. */
  337. setsockopt ((SOCKET) handle, SOL_SOCKET, SO_REUSEADDR,
  338. (char *) &true_value, sizeof (true_value));
  339. # endif
  340. prepare_socket (handle); /* Ready socket for use */
  341. ip_sockets++;
  342. return (handle);
  343. #elif (defined (FAKE_SOCKETS))
  344. return (1); /* Return dummy handle */
  345. #else
  346. connect_error_value = IP_NOSOCKETS;
  347. return (INVALID_SOCKET); /* Sockets not supported */
  348. #endif
  349. }
  350. #if (defined (DOES_SOCKETS))
  351. /* -------------------------------------------------------------------------
  352. * prepare_socket -- internal
  353. *
  354. * Does any system-specific work required to prepare a socket for normal
  355. * use. In Windows we have to set the socket to nonblocking mode. In
  356. * UNIX we do this if the ip_nonblock flag is set.
  357. */
  358. static void
  359. prepare_socket (sock_t handle)
  360. {
  361. #if (defined (__WINDOWS__))
  362. u_long
  363. command = ip_nonblock? 1: 0;
  364. /* Redirect events and set non-blocking mode */
  365. if (handle != INVALID_SOCKET)
  366. ioctlsocket ((SOCKET) handle, FIONBIO, &command);
  367. #elif (defined (__UTYPE_BEOS))
  368. setsockopt ((SOCKET) handle, SOL_SOCKET, SO_NONBLOCK,
  369. (void *) &ip_nonblock, sizeof (ip_nonblock));
  370. #elif (defined (__UNIX__) || defined (__OS2__))
  371. if (ip_nonblock)
  372. fcntl ((SOCKET) handle, F_SETFL, O_NONBLOCK
  373. | fcntl (handle, F_GETFL, 0));
  374. #endif
  375. }
  376. #endif
  377. /* ---------------------------------------------------------------------[<]-
  378. Function: connect_TCP
  379. Synopsis:
  380. Creates a TCP socket and connects it to a specified host and service.
  381. Returns a socket number or INVALID_SOCKET. In that case you can get
  382. the reason for the error by calling connect_error (). This may be:
  383. <TABLE>
  384. IP_NOSOCKETS Sockets not supported on this system
  385. IP_BADHOST Host is not known
  386. IP_BADPROTOCOL Cannot understand protocol name
  387. IP_SOCKETERROR Cannot open a socket
  388. IP_CONNECTERROR Cannot connect socket
  389. </TABLE>
  390. The host name may be a full name, NULL or "" meaning the current host,
  391. or a dotted-decimal number. The service may be a defined service, e.g.
  392. "echo", or a port number, specified as an ASCII string. See
  393. connect_socket() for details.
  394. Single-threaded clients may set ip_nonblock to FALSE and block on all
  395. read and write operations. They may use select() if they need to be
  396. able to time-out during reading/writing.
  397. Multi-threaded servers should set ip_nonblock to TRUE, and use select()
  398. to multiplex socket access. When ip_nonblock is TRUE, connect calls
  399. will return immediately, and the server should use select() to wait until
  400. the socket is ready for writing. On some systems (early Linux?), the
  401. select() call will fail in this situation. If you compile with
  402. -DBLOCKING_CONNECT, connects are done synchronously in all cases.
  403. Examples:
  404. sock_t handle;
  405. handle = connect_TCP ("", "8080");
  406. handle = connect_TCP (NULL, "echo");
  407. handle = connect_TCP ("www.imatix.com", "http");
  408. ---------------------------------------------------------------------[>]-*/
  409. sock_t
  410. connect_TCP (
  411. const char *host, /* Host name */
  412. const char *service /* Service name */
  413. )
  414. {
  415. ASSERT (service && *service);
  416. return (connect_socket (host, /* We have a host name */
  417. service, /* We have a service name */
  418. "tcp", /* Protocol is TCP */
  419. NULL, /* No prepared address */
  420. 3, 0)); /* 3 retries, no waiting */
  421. }
  422. /* ---------------------------------------------------------------------[<]-
  423. Function: connect_UDP
  424. Synopsis:
  425. Creates a UDP socket and connects it to a specified host and service.
  426. Returns a socket number or INVALID_SOCKET. In that case you can get
  427. the reason for the error by calling connect_error (). This may be:
  428. <TABLE>
  429. IP_NOSOCKETS Sockets not supported on this system
  430. IP_BADHOST Host is not known
  431. IP_BADPROTOCOL Cannot understand protocol name
  432. IP_SOCKETERROR Cannot open a socket
  433. IP_CONNECTERROR Cannot connect socket
  434. </TABLE>
  435. The host name may be a full name, NULL or "" meaning the current host,
  436. or a dotted-decimal number. The service may be a defined service, e.g.
  437. "echo", or a port number, specified as an ASCII string. See
  438. connect_socket() for details.
  439. Single-threaded clients may set ip_nonblock to FALSE and block on all
  440. read and write operations. They may use select() if they need to be
  441. able to time-out during reading/writing.
  442. Multi-threaded servers should set ip_nonblock to TRUE, and use select()
  443. to multiplex socket access. When ip_nonblock is TRUE, connect calls
  444. will return immediately, and the server should use select() to wait until
  445. the socket is ready for writing. On some systems (early Linux?), the
  446. select() call will fail in this situation. If you compile with
  447. -DBLOCKING_CONNECT, connects are done synchronously in all cases.
  448. Examples:
  449. sock_t handle;
  450. handle = connect_UDP ("", "7");
  451. handle = connect_UDP (NULL, "echo");
  452. handle = connect_UDP ("imatix.com", "echo");
  453. ---------------------------------------------------------------------[>]-*/
  454. sock_t
  455. connect_UDP (
  456. const char *host, /* Host name */
  457. const char *service /* Service name */
  458. )
  459. {
  460. ASSERT (service && *service);
  461. return (connect_socket (host, /* We have a host name */
  462. service, /* We have a service name */
  463. "udp", /* Protocol is UDP */
  464. NULL, /* No prepared address */
  465. 3, 0)); /* 3 retries, no waiting */
  466. }
  467. /* ---------------------------------------------------------------------[<]-
  468. Function: connect_TCP_fast
  469. Synopsis: Creates a TCP socket and connects it to a specified host/port
  470. address. Returns a socket number or INVALID_SOCKET. In that case you
  471. can get the reason for the error by calling connect_error (). This may
  472. be:
  473. <TABLE>
  474. IP_NOSOCKETS Sockets not supported on this system
  475. IP_BADHOST Host is not known
  476. IP_BADPROTOCOL Cannot understand protocol name
  477. IP_SOCKETERROR Cannot open a socket
  478. IP_CONNECTERROR Cannot connect socket
  479. </TABLE>
  480. This function is faster, if you know the host system address and port,
  481. than connect_TCP() because no translation is needed.
  482. You can get the host/address structure by calling address_end_point()
  483. or get_peer_addr(). See connect_socket() for details.
  484. ---------------------------------------------------------------------[>]-*/
  485. sock_t
  486. connect_TCP_fast (
  487. const struct sockaddr_in *sin /* Socket address structure */
  488. )
  489. {
  490. ASSERT (sin);
  491. return (connect_socket (NULL, /* No host name */
  492. NULL, /* No service name */
  493. "tcp", /* Protocol is TCP */
  494. sin, /* We have a prepared address */
  495. 1, 0)); /* 1 retry, no waiting */
  496. }
  497. /* ---------------------------------------------------------------------[<]-
  498. Function: connect_UDP_fast
  499. Synopsis:
  500. Creates a UDP socket and connects it to a specified host/port address.
  501. Returns a socket number or INVALID_SOCKET. In that case you can get
  502. the reason for the error by calling connect_error (). This may be:
  503. <TABLE>
  504. IP_NOSOCKETS Sockets not supported on this system
  505. IP_BADHOST Host is not known
  506. IP_BADPROTOCOL Cannot understand protocol name
  507. IP_SOCKETERROR Cannot open a socket
  508. IP_CONNECTERROR Cannot connect socket
  509. </TABLE>
  510. This function is faster, if you know the host system address and port,
  511. than connect_UDP() because no translation is needed.
  512. You can get the host/address structure by calling address_end_point()
  513. or get_peer_addr(). See connect_socket() for details.
  514. ---------------------------------------------------------------------[>]-*/
  515. sock_t
  516. connect_UDP_fast (
  517. const struct sockaddr_in *sin /* Socket address structure */
  518. )
  519. {
  520. ASSERT (sin);
  521. return (connect_socket (NULL, /* No host name */
  522. NULL, /* No service name */
  523. "udp", /* Protocol is UDP */
  524. sin, /* We have a prepared address */
  525. 1, 0)); /* 1 retry, no waiting */
  526. }
  527. /* ---------------------------------------------------------------------[<]-
  528. Function: connect_socket
  529. Synopsis:
  530. Makes a connection to a remote TCP or UDP port. This allows a client
  531. program to start sending information to a server. Used by the
  532. connect_TCP and connect_UDP functions. Returns a socket number or
  533. INVALID_SOCKET. If it returns INVALID_SOCKET, you can get the reason
  534. for the error by calling connect_error (). This may be one of:
  535. <TABLE>
  536. IP_NOSOCKETS Sockets not supported on this system
  537. IP_BADHOST Host is not known
  538. IP_BADPROTOCOL Cannot understand protocol name
  539. IP_SOCKETERROR Cannot open a socket
  540. IP_CONNECTERROR Cannot connect socket
  541. </TABLE>
  542. Always blocks until the connection has been made; i.e. when this
  543. function returns you can start to read and write on the socket.
  544. The host name may be a full name, NULL or "" meaning the current host,
  545. or a dotted-decimal number. The service may be a defined service, e.g.
  546. "echo", or a port number, specified as an ASCII string. Alternatively,
  547. both these values may be NULL or "", in which case the function uses
  548. the host_addr argument to supply an address. If you want to build the
  549. host_addr structure yourself, use build_sockaddr().
  550. Single-threaded clients may set ip_nonblock to FALSE and block on all
  551. read and write operations. They may use select() if they need to be
  552. able to time-out during reading/writing.
  553. Multi-threaded servers should set ip_nonblock to TRUE, and use select()
  554. to multiplex socket access. When ip_nonblock is TRUE, connect calls
  555. will return immediately, and the server should use select() to wait until
  556. the socket is ready for writing. On some systems (early Linux?), the
  557. select() call will fail in this situation. If you compile with
  558. -DBLOCKING_CONNECT, connects are done synchronously in all cases.
  559. Examples:
  560. struct sockaddr_in
  561. host_addr;
  562. sock_t
  563. handle;
  564. build_sockaddr (&host_addr, 32_bit_host, 16_bit_port);
  565. handle = connect_socket (NULL, NULL, "tcp", &host_addr, 3, 0);
  566. ---------------------------------------------------------------------[>]-*/
  567. sock_t
  568. connect_socket (
  569. const char *host, /* Name of host, "" = localhost */
  570. const char *service, /* Service name or port as string */
  571. const char *protocol, /* Protocol "tcp" or "udp" */
  572. const struct sockaddr_in *host_addr, /* Socket address structure */
  573. int retries_left, /* Max. number of retries */
  574. int retry_delay /* Delay between retries */
  575. )
  576. {
  577. #if (defined (DOES_SOCKETS))
  578. struct sockaddr_in
  579. sin; /* Internet end-point address */
  580. sock_t
  581. handle = 0; /* Created socket */
  582. int
  583. rc; /* Return code from call */
  584. Bool
  585. old_nonblock; /* Create non-blocking sockets */
  586. connect_error_value = IP_NOERROR; /* Assume no errors */
  587. /* Format sockaddr_in port and hostname, and quit if that failed */
  588. if (service && strused (service))
  589. {
  590. ASSERT (protocol && *protocol);
  591. if (address_end_point (host, service, protocol, &sin))
  592. return (INVALID_SOCKET);
  593. }
  594. else
  595. {
  596. ASSERT (host_addr);
  597. sin = *host_addr; /* Fast connect requested */
  598. }
  599. /* Connect socket and maybe retry a few times... */
  600. old_nonblock = ip_nonblock;
  601. # if (defined (BLOCKING_CONNECT))
  602. ip_nonblock = FALSE; /* Block on this socket */
  603. # endif
  604. while (retries_left)
  605. {
  606. handle = create_socket (protocol);
  607. if (handle == INVALID_SOCKET) /* Unable to open a socket */
  608. {
  609. ip_nonblock = old_nonblock;
  610. return (INVALID_SOCKET);
  611. }
  612. rc = connect ((SOCKET) handle, (struct sockaddr *) &sin, sizeof (sin));
  613. if (rc == 0)
  614. break; /* Connected okay */
  615. else
  616. {
  617. # if (defined (__WINDOWS__))
  618. if (WSAGetLastError () == WSAEWOULDBLOCK)
  619. # else
  620. if (errno == EINPROGRESS)
  621. # endif
  622. break; /* Still connecting, but okay */
  623. }
  624. /* Retry if we have any attempts left */
  625. close_socket (handle);
  626. if (--retries_left == 0) /* Connection failed */
  627. {
  628. connect_error_value = IP_CONNECTERROR;
  629. ip_nonblock = old_nonblock;
  630. return (INVALID_SOCKET);
  631. }
  632. sleep (retry_delay);
  633. }
  634. ip_nonblock = old_nonblock;
  635. prepare_socket (handle); /* Set final blocking mode */
  636. return (handle);
  637. #elif (defined (FAKE_SOCKETS))
  638. return (1); /* Return dummy handle */
  639. #else
  640. connect_error_value = IP_NOSOCKETS;
  641. return (INVALID_SOCKET); /* Sockets not supported */
  642. #endif
  643. }
  644. /* ---------------------------------------------------------------------[<]-
  645. Function: connect_to_peer
  646. Synopsis:
  647. Connects an unconnected TCP or UDP socket to a peer specified by a
  648. sockaddr structure. Returns 0 if the connection succeeded, or
  649. SOCKET_ERROR if there was a problem. In the latter case you can
  650. get the reason for the error by calling sockmsg().
  651. ---------------------------------------------------------------------[>]-*/
  652. int
  653. connect_to_peer (
  654. sock_t handle, /* Socket to connect */
  655. const struct sockaddr_in *sin /* Socket address structure */
  656. )
  657. {
  658. #if (defined (DOES_SOCKETS))
  659. int
  660. rc; /* Return code from call */
  661. Bool
  662. old_nonblock; /* Create non-blocking sockets */
  663. ASSERT (sin);
  664. old_nonblock = ip_nonblock;
  665. # if (defined (BLOCKING_CONNECT))
  666. ip_nonblock = FALSE; /* Block on this socket */
  667. # endif
  668. rc = connect ((SOCKET) handle, (struct sockaddr *) sin, sizeof (*sin));
  669. ip_nonblock = old_nonblock;
  670. prepare_socket (handle); /* Set final blocking mode */
  671. # if (defined (__WINDOWS__))
  672. return (win_error (rc));
  673. # else
  674. return (rc);
  675. # endif
  676. #else
  677. connect_error_value = IP_NOSOCKETS;
  678. return ((int) SOCKET_ERROR); /* Sockets not supported */
  679. #endif
  680. }
  681. /* ---------------------------------------------------------------------[<]-
  682. Function: address_end_point
  683. Synopsis:
  684. Formats an address block (struct sockaddr_in) for the specified host
  685. and service (port) information. Returns 0 if okay, SOCKET_ERROR if
  686. there was an error, in which case you can call connect_error () to get
  687. the reason for the error. This may be one of:
  688. <TABLE>
  689. IP_NOSOCKETS Sockets not supported on this system
  690. IP_BADHOST Host is not known
  691. </TABLE>
  692. ---------------------------------------------------------------------[>]-*/
  693. int
  694. address_end_point (
  695. const char *host, /* Name of host, "" = localhost */
  696. const char *service, /* Service name or port as string */
  697. const char *protocol, /* Protocol "tcp" or "udp" */
  698. struct sockaddr_in *sin /* Block for formatted address */
  699. )
  700. {
  701. #if (defined (DOES_SOCKETS))
  702. struct hostent
  703. *phe; /* Host information entry */
  704. struct servent
  705. *pse; /* Service information entry */
  706. char
  707. hostname [MAXHOSTNAMELEN + 1]; /* Name of this system */
  708. int
  709. feedback = 0; /* Assume everything works */
  710. ASSERT (service && *service);
  711. ASSERT (protocol && *protocol);
  712. ASSERT (sin);
  713. connect_error_value = IP_NOERROR; /* Assume no errors */
  714. memset ((void *) sin, 0, sizeof (*sin));
  715. sin-> sin_family = AF_INET;
  716. /* Map service name to a port number */
  717. pse = getservbyname (service, protocol);
  718. if (pse)
  719. sin-> sin_port = htons ((short) (ntohs (pse-> s_port)));
  720. else
  721. sin-> sin_port = htons ((short) (atoi (service)));
  722. /* Map host name to IP address, allowing for dotted decimal */
  723. if (host && strused (host))
  724. strcpy (hostname, host);
  725. else
  726. strcpy (hostname, "127.0.0.1");
  727. /* Check if it's a valid IP address first */
  728. sin-> sin_addr.s_addr = inet_addr (hostname);
  729. if (sin-> sin_addr.s_addr == (unsigned) INADDR_NONE)
  730. {
  731. /* Not a dotted address -- try to translate the name */
  732. phe = (void *) gethostbyname (hostname);
  733. if (phe)
  734. memcpy ((void *) &sin-> sin_addr, phe-> h_addr, phe-> h_length);
  735. else
  736. { /* Cannot map to host */
  737. connect_error_value = IP_BADHOST;
  738. feedback = (int) SOCKET_ERROR;
  739. }
  740. }
  741. return (feedback);
  742. #else
  743. connect_error_value = IP_NOSOCKETS;
  744. return ((int) SOCKET_ERROR); /* Sockets not supported */
  745. #endif
  746. }
  747. /* ---------------------------------------------------------------------[<]-
  748. Function: build_sockaddr
  749. Synopsis:
  750. Builds a socket address structure from the specified host and port
  751. addresses. Does not return any value except the built structure.
  752. ---------------------------------------------------------------------[>]-*/
  753. void
  754. build_sockaddr (
  755. struct sockaddr_in *sin, /* Socket address structure */
  756. qbyte host, /* 32-bit host address */
  757. dbyte port /* 16-bit port number */
  758. )
  759. {
  760. ASSERT (sin);
  761. sin-> sin_family = AF_INET;
  762. sin-> sin_addr.s_addr = htonl (host);
  763. sin-> sin_port = htons (port);
  764. }
  765. /* ---------------------------------------------------------------------[<]-
  766. Function: socket_localaddr
  767. Synopsis: Returns a string containing the local host address for the
  768. specified connected socket. The string is formatted as a string
  769. "n.n.n.n". Returns the address of a static string or a buffer that
  770. is overwritten by each call. If sockets are not supported, or there
  771. was an error, returns the loopback address "127.0.0.1".
  772. ---------------------------------------------------------------------[>]-*/
  773. char *
  774. socket_localaddr (
  775. sock_t handle)
  776. {
  777. #define NTOA_MAX 16
  778. #if (defined (DOES_SOCKETS))
  779. static char
  780. localaddr [NTOA_MAX + 1]; /* xxx.xxx.xxx.xxx */
  781. struct sockaddr_in
  782. sin; /* Address of local system */
  783. if (get_sock_addr (handle, &sin, NULL, 0))
  784. return ("127.0.0.1");
  785. else
  786. {
  787. strncpy (localaddr, inet_ntoa (sin.sin_addr), NTOA_MAX);
  788. return (localaddr);
  789. }
  790. #else
  791. return ("127.0.0.1");
  792. #endif
  793. }
  794. /* ---------------------------------------------------------------------[<]-
  795. Function: socket_peeraddr
  796. Synopsis: Returns a string containing the peer host address for the
  797. specified connected socket. The string is formatted as a string
  798. "n.n.n.n". Returns the address of a static string or a buffer that
  799. is overwritten by each call. If sockets are not supported, or there
  800. was an error, returns the loopback address "127.0.0.1".
  801. ---------------------------------------------------------------------[>]-*/
  802. char *
  803. socket_peeraddr (
  804. sock_t handle)
  805. {
  806. #if (defined (DOES_SOCKETS))
  807. static char
  808. peeraddr [NTOA_MAX + 1]; /* xxx.xxx.xxx.xxx */
  809. struct sockaddr_in
  810. sin; /* Address of peer system */
  811. if (get_peer_addr (handle, &sin, NULL, 0))
  812. return ("127.0.0.1");
  813. else
  814. {
  815. strncpy (peeraddr, inet_ntoa (sin.sin_addr), NTOA_MAX);
  816. return (peeraddr);
  817. }
  818. #else
  819. return ("127.0.0.1");
  820. #endif
  821. }
  822. /* ---------------------------------------------------------------------[<]-
  823. Function: socket_nodelay
  824. Synopsis: Disables Nagle's algorithm for the specified socket; use this
  825. when you want to ensure that data is sent outwards as fast as possible,
  826. and when you are certain that Nagle's algorithm is causing a slowdown in
  827. performance. Recommended for HTTP, but not recommended for telnet.
  828. Returns 0 if okay, SOCKET_ERROR if there was a problem.
  829. ---------------------------------------------------------------------[>]-*/
  830. int
  831. socket_nodelay (
  832. sock_t handle)
  833. {
  834. #if (defined (__WINDOWS__))
  835. int
  836. true_value = 1; /* Boolean value for setsockopt() */
  837. return (setsockopt ((SOCKET) handle, IPPROTO_TCP, TCP_NODELAY,
  838. (char *) &true_value, sizeof (true_value)));
  839. #elif (defined (TCP_NODELAY) && defined (SOL_TCP))
  840. int
  841. true_value = 1; /* Boolean value for setsockopt() */
  842. return (setsockopt ((SOCKET) handle, SOL_TCP, TCP_NODELAY,
  843. (char *) &true_value, sizeof (true_value)));
  844. #elif (defined (TCP_NODELAY) && defined (IPPROTO_TCP))
  845. int
  846. true_value = 1; /* Boolean value for setsockopt() */
  847. return (setsockopt ((SOCKET) handle, IPPROTO_TCP, TCP_NODELAY,
  848. (char *) &true_value, sizeof (true_value)));
  849. #else
  850. return (0); /* Not applicable to this system */
  851. #endif
  852. }
  853. /* ---------------------------------------------------------------------[<]-
  854. Function: socket_is_alive
  855. Synopsis:
  856. Returns TRUE if the socket is open. Returns FALSE if the socket is no
  857. longer accessible. You can use this function to check that a socket has
  858. not been closed by the other party, before doing reading or writing.
  859. ---------------------------------------------------------------------[>]-*/
  860. Bool
  861. socket_is_alive (
  862. sock_t handle)
  863. {
  864. #if (defined (__UTYPE_BEOS))
  865. /* BeOS 4.5 does not support the getsockopt() function */
  866. int
  867. rc;
  868. rc = setsockopt ((SOCKET) handle, SOL_SOCKET, SO_NONBLOCK,
  869. (void *) &ip_nonblock, sizeof (ip_nonblock));
  870. return (rc == 0);
  871. #elif (defined (DOES_SOCKETS))
  872. int
  873. rc;
  874. rc = socket_error (handle);
  875. if (rc == 0
  876. || rc == EINPROGRESS
  877. || rc == EAGAIN
  878. || rc == EWOULDBLOCK)
  879. return TRUE;
  880. else
  881. return FALSE;
  882. #else
  883. return (FALSE);
  884. #endif
  885. }
  886. /* ---------------------------------------------------------------------[<]-
  887. Function: socket_error
  888. Synopsis: Returns an errno value for the socket, or 0 if no error was
  889. outstanding on the socket. This function is useful if you are handling
  890. sockets using the select() function: this may return error indicators
  891. on sockets, without precision on the type of error. This function will
  892. return the precise error number. Errors like EINPROGRESS, EAGAIN, and
  893. EWOULDBLOCK can usually be ignored or handled by retrying.
  894. ---------------------------------------------------------------------[>]-*/
  895. int
  896. socket_error (
  897. sock_t handle)
  898. {
  899. #if (defined (DOES_SOCKETS))
  900. # if (defined (__UTYPE_BEOS))
  901. return (errno);
  902. # else
  903. int
  904. socket_error,
  905. rc;
  906. argsize_t
  907. error_size = sizeof (socket_error);
  908. rc = getsockopt ((SOCKET) handle, SOL_SOCKET, SO_ERROR,
  909. (char *) &socket_error, &error_size);
  910. if (rc)
  911. errno = rc;
  912. else
  913. errno = socket_error;
  914. return (errno);
  915. # endif
  916. #else
  917. return (0);
  918. #endif
  919. }
  920. /* ---------------------------------------------------------------------[<]-
  921. Function: accept_socket
  922. Synopsis: Accepts a connection on a specified master socket. If you
  923. do not want to wait on this call, use select() to poll the socket until
  924. there is an incoming request, then call accept_socket. Returns the
  925. number of the new slave socket, or INVALID_SOCKET if there was an error
  926. on the accept call. You can handle errors as fatal except for EAGAIN
  927. which indicates that the operation would cause a non-blocking socket to
  928. block (treat EWOULDBLOCK in the same way).
  929. ---------------------------------------------------------------------[>]-*/
  930. sock_t
  931. accept_socket (
  932. sock_t master_socket)
  933. {
  934. #if (defined (DOES_SOCKETS))
  935. sock_t
  936. slave_socket; /* Connected slave socket */
  937. struct sockaddr_in
  938. sin; /* Address of connecting party */
  939. argsize_t
  940. sin_length; /* Length of address */
  941. connect_error_value = IP_NOERROR; /* Assume no errors */
  942. sin_length = (int) sizeof (sin);
  943. slave_socket = accept ((SOCKET) master_socket,
  944. (struct sockaddr *) &sin, &sin_length);
  945. /* On non-Windows systems, accept returns -1 in case of error, which */
  946. /* is the same as INVALID_SOCKET. */
  947. # if (defined (__WINDOWS__))
  948. if (slave_socket == INVALID_SOCKET)
  949. {
  950. int sock_errno = WSAGetLastError ();
  951. if (sock_errno == WSAEWOULDBLOCK || sock_errno == WSAEINPROGRESS)
  952. errno = EAGAIN;
  953. }
  954. # endif
  955. if (slave_socket != INVALID_SOCKET)
  956. {
  957. prepare_socket (slave_socket);
  958. ip_sockets++;
  959. }
  960. return (slave_socket);
  961. #else
  962. connect_error_value = IP_NOSOCKETS;
  963. return (INVALID_SOCKET); /* Sockets not supported */
  964. #endif
  965. }
  966. /* ---------------------------------------------------------------------[<]-
  967. Function: connect_error
  968. Synopsis:
  969. Returns the last error code from one of the connection functions. For
  970. portability in a multithreaded environment, call immediately after the
  971. call to the connection function.
  972. ---------------------------------------------------------------------[>]-*/
  973. int
  974. connect_error (void)
  975. {
  976. return (connect_error_value);
  977. }
  978. /* ---------------------------------------------------------------------[<]-
  979. Function: get_sock_addr
  980. Synopsis: Builds an address block (struct sockaddr_in) for the local
  981. end of the specified connected socket. Returns 0 if okay, SOCKET_ERROR
  982. if there was an error. If the name argument is not null, looks-up the
  983. host name and returns it. The name is truncated to namesize characters,
  984. including a trailing null character.
  985. ---------------------------------------------------------------------[>]-*/
  986. int
  987. get_sock_addr (
  988. sock_t handle, /* Socket to get address for */
  989. struct sockaddr_in *sin, /* Block for formatted address */
  990. char *name, /* Buffer for host name, or NULL */
  991. int namesize /* Size of host name buffer */
  992. )
  993. {
  994. #if (defined (DOES_SOCKETS))
  995. int
  996. rc; /* Return code from call */
  997. struct hostent
  998. *phe; /* Host information entry */
  999. argsize_t
  1000. sin_length; /* Length of address */
  1001. ASSERT (sin);
  1002. /* Get address for local connected socket */
  1003. sin_length = sizeof (struct sockaddr_in);
  1004. rc = getsockname ((SOCKET) handle, (struct sockaddr *) sin, &sin_length);
  1005. /* Translate into host name string, only if wanted */
  1006. if (name != NULL && rc == 0)
  1007. {
  1008. phe = (void *)gethostbyaddr ((char *) &sin-> sin_addr,
  1009. sizeof (sin-> sin_addr), AF_INET);
  1010. if (phe)
  1011. {
  1012. strncpy (name, phe-> h_name, namesize);
  1013. name [namesize - 1] = '\0';
  1014. }
  1015. }
  1016. # if (defined (__WINDOWS__))
  1017. return (win_error (rc));
  1018. # else
  1019. return (rc);
  1020. # endif
  1021. #else
  1022. return ((int) SOCKET_ERROR); /* Sockets not supported */
  1023. #endif
  1024. }
  1025. /* ---------------------------------------------------------------------[<]-
  1026. Function: get_peer_addr
  1027. Synopsis: Builds an address block (struct sockaddr_in) for the remote
  1028. end of the specified connected socket. Returns 0 if okay, SOCKET_ERROR
  1029. if there was an error. If the name argument is not null, looks-up the
  1030. host name and returns it. The name is truncated to namesize characters,
  1031. including a trailing null character.
  1032. ---------------------------------------------------------------------[>]-*/
  1033. int
  1034. get_peer_addr (
  1035. sock_t handle, /* Socket to get address for */
  1036. struct sockaddr_in *sin, /* Block for formatted address */
  1037. char *name, /* Buffer for host name, or NULL */
  1038. int namesize /* Size of host name buffer */
  1039. )
  1040. {
  1041. #if (defined (DOES_SOCKETS))
  1042. int
  1043. rc; /* Return code from call */
  1044. struct hostent
  1045. *phe; /* Host information entry */
  1046. argsize_t
  1047. sin_length; /* Length of address */
  1048. ASSERT (sin);
  1049. /* Get address for connected socket peer */
  1050. sin_length = sizeof (struct sockaddr_in);
  1051. rc = getpeername ((SOCKET) handle, (struct sockaddr *) sin, &sin_length);
  1052. /* Translate into host name string, only if wanted */
  1053. if (name != NULL && rc == 0)
  1054. {
  1055. phe = (void *)gethostbyaddr ((char *) &sin-> sin_addr,
  1056. sizeof (sin-> sin_addr), AF_INET);
  1057. if (phe)
  1058. {
  1059. strncpy (name, phe-> h_name, namesize);
  1060. name [namesize - 1] = '\0';
  1061. }
  1062. }
  1063. # if (defined (__WINDOWS__))
  1064. return (win_error (rc));
  1065. # else
  1066. return (rc);
  1067. # endif
  1068. #else
  1069. return ((int) SOCKET_ERROR); /* Sockets not supported */
  1070. #endif
  1071. }
  1072. /* ---------------------------------------------------------------------[<]-
  1073. Function: read_TCP
  1074. Synopsis:
  1075. Reads data from the socket. On UNIX, VMS, OS/2, passes through to the
  1076. standard read function; some other systems have particular ways of
  1077. accessing sockets. If there is an error on the read this function
  1078. returns SOCKET_ERROR. You can handle errors (in sockerrno) as fatal except
  1079. for EAGAIN which indicates that the operation would cause a non-blocking
  1080. socket to block, and EPIPE or ECONNRESET which indicate that the socket
  1081. was closed at the other end. Treat EWOULDBLOCK as EAGAIN.
  1082. ---------------------------------------------------------------------[>]-*/
  1083. int
  1084. read_TCP (
  1085. sock_t handle, /* Socket handle */
  1086. void *buffer, /* Buffer to receive data */
  1087. size_t length /* Maximum amount of data to read */
  1088. )
  1089. {
  1090. #if (defined (DOES_SOCKETS))
  1091. # if (defined (__UTYPE_BEOS))
  1092. return (recv ((SOCKET) handle, buffer, length, 0));
  1093. # elif (defined (__UNIX__) || defined (__VMS__) || defined (__OS2__))
  1094. return (read ((SOCKET) handle, buffer, length));
  1095. # elif (defined (__WINDOWS__))
  1096. int
  1097. rc; /* Return code from call */
  1098. ASSERT (buffer);
  1099. rc = recv ((SOCKET) handle, buffer, length, 0);
  1100. return (win_error (rc));
  1101. # else
  1102. # error "No code for function body."
  1103. return ((int) SOCKET_ERROR); /* Sockets not supported */
  1104. # endif
  1105. #else
  1106. return ((int) SOCKET_ERROR); /* Sockets not supported */
  1107. #endif
  1108. }
  1109. #if (defined (__WINDOWS__))
  1110. /* -------------------------------------------------------------------------
  1111. * win_error -- internal
  1112. *
  1113. * For Winsockets only: fetches real error code and sticks it in errno,
  1114. * if the return code from the last call was SOCKET_ERROR. Returns rc.
  1115. */
  1116. static int
  1117. win_error (int rc)
  1118. {
  1119. if (rc == (int) SOCKET_ERROR)
  1120. errno = winsock_last_error ();
  1121. return (rc);
  1122. }
  1123. #endif
  1124. /* ---------------------------------------------------------------------[<]-
  1125. Function: write_TCP
  1126. Synopsis:
  1127. Writes data to the socket. On UNIX, VMS, OS/2, calls the standard
  1128. write function; some other systems have particular ways of accessing
  1129. sockets. If there is an error on the write this function returns
  1130. SOCKET_ERROR. You can handle errors (in sockerrno) as fatal except for
  1131. EAGAIN which indicates that the operation would cause a non-blocking
  1132. socket to block, and EPIPE or ECONNRESET which indicate that the socket
  1133. was closed at the other end. Treat EWOULDBLOCK as EAGAIN.
  1134. ---------------------------------------------------------------------[>]-*/
  1135. int
  1136. write_TCP (
  1137. sock_t handle, /* Socket handle */
  1138. const void *buffer, /* Buffer containing data */
  1139. size_t length /* Amount of data to write */
  1140. )
  1141. {
  1142. #if (defined (DOES_SOCKETS))
  1143. # if (defined (__UTYPE_BEOS))
  1144. return (send ((SOCKET) handle, buffer, length, 0));
  1145. # elif (defined (__UNIX__) || defined (__VMS__) || defined (__OS2__))
  1146. return (write ((SOCKET) handle, buffer, length));
  1147. # elif (defined (__WINDOWS__))
  1148. int
  1149. rc; /* Return code from call */
  1150. ASSERT (buffer);
  1151. rc = send ((SOCKET) handle, buffer, length, 0);
  1152. return (win_error (rc));
  1153. # else
  1154. # error "No code for function body."
  1155. return ((int) SOCKET_ERROR); /* Sockets not supported */
  1156. # endif
  1157. #else
  1158. return ((int) SOCKET_ERROR); /* Sockets not supported */
  1159. #endif
  1160. }
  1161. /* ---------------------------------------------------------------------[<]-
  1162. Function: read_UDP
  1163. Synopsis:
  1164. Reads data from a connected or unconnected UDP socket. To prepare a
  1165. connected UDP socket you call connect_UDP (). This makes a connection
  1166. to a specific port on a specific host, and returns a socket handle.
  1167. When you call this function with a null value for the address argument,
  1168. it assumes you are using a connected UDP socket.
  1169. To prepare an unconnected UDP socket, call create_socket () with the
  1170. string "udp" as argument. This returns a sock_t handle that you can
  1171. use in this function. If you use an unconnected UDP socket you must
  1172. provide an address structure. The function places the remote host and
  1173. port in this structure. This lets you reply using write_UDP ().
  1174. Generally a server can use unconnected sockets, and a client can use
  1175. connected sockets. You can also format an address for a specific host
  1176. and port using the address_end_point () function.
  1177. If there is an error on the read this function returns SOCKET_ERROR.
  1178. You can handle errors (in sockerrno) as fatal except for EAGAIN which
  1179. indicates that the operation would cause a non-blocking socket to block.
  1180. Treat EWOULDBLOCK as EAGAIN.
  1181. ---------------------------------------------------------------------[>]-*/
  1182. int
  1183. read_UDP (
  1184. sock_t handle, /* Socket handle */
  1185. void *buffer, /* Buffer to receive data */
  1186. size_t length, /* Maximum amount of data to read */
  1187. const struct sockaddr_in *sin /* Block for address, or null */
  1188. )
  1189. {
  1190. #if (defined (DOES_SOCKETS))
  1191. argsize_t
  1192. sin_length; /* Length of address */
  1193. int
  1194. flags = 0, /* Flags for call */
  1195. rc; /* Return code from call */
  1196. ASSERT (buffer);
  1197. sin_length = (int) sizeof (*sin);
  1198. if (sin)
  1199. /* Read from unconnected UDP socket; we accept the address of the */
  1200. /* sending party in the sin argument. */
  1201. rc = recvfrom ((SOCKET) handle, buffer, length, flags,
  1202. (struct sockaddr *) sin, &sin_length);
  1203. else
  1204. /* Read from a connected UDP socket; we don't need to get the */
  1205. /* address, since we already know it. */
  1206. rc = recv ((SOCKET) handle, buffer, length, flags);
  1207. # if (defined (__WINDOWS__))
  1208. return (win_error (rc));
  1209. # else
  1210. return (rc);
  1211. # endif
  1212. #else
  1213. return ((int) SOCKET_ERROR); /* Sockets not supported */
  1214. #endif
  1215. }
  1216. /* ---------------------------------------------------------------------[<]-
  1217. Function: write_UDP
  1218. Synopsis:
  1219. Writes data to a connected or unconnected UDP socket. To prepare a
  1220. connected UDP socket you call connect_UDP (). This makes a connection
  1221. to a specific port on a specific host, and returns a socket handle.
  1222. When you call this function with a null value for the address argument,
  1223. it assumes you are using a connected UDP socket.
  1224. To prepare an unconnected UDP socket, call create_socket () with the
  1225. string "udp" as argument. This returns a sock_t handle that you can
  1226. use in this function. If you use an unconnected UDP socket you must
  1227. provide an address structure containing a valid host and port. You can
  1228. get this information from a read_UDP () or through address_end_point ().
  1229. If there is an error on the write this function returns SOCKET_ERROR.
  1230. You can handle errors as fatal except for EAGAIN which indicates that
  1231. the operation would cause a non-blocking socket to block. Treat
  1232. EWOULDBLOCK as EAGAIN.
  1233. ---------------------------------------------------------------------[>]-*/
  1234. int
  1235. write_UDP (
  1236. sock_t handle, /* Socket handle */
  1237. const void *buffer, /* Buffer containing data */
  1238. size_t length, /* Amount of data to write */
  1239. const struct sockaddr_in *sin /* Address to send to, or null */
  1240. )
  1241. {
  1242. #if (defined (DOES_SOCKETS))
  1243. int
  1244. sin_length, /* Length of address */
  1245. flags = 0, /* Flags for call */
  1246. rc; /* Return code from call */
  1247. ASSERT (buffer);
  1248. sin_length = (int) sizeof (*sin);
  1249. if (sin)
  1250. /* Write to unconnected UDP socket; we provide the address of */
  1251. /* the receiving party in the sin argument. */
  1252. rc = sendto ((SOCKET) handle, buffer, length, flags,
  1253. (struct sockaddr *) sin, sin_length);
  1254. else
  1255. /* Write to a connected UDP socket; we don't need to supply */
  1256. /* the address, since we already know it. */
  1257. rc = send ((SOCKET) handle, buffer, length, flags);
  1258. # if (defined (__WINDOWS__))
  1259. return (win_error (rc));
  1260. # else
  1261. return (rc);
  1262. # endif
  1263. #else
  1264. return ((int) SOCKET_ERROR); /* Sockets not supported */
  1265. #endif
  1266. }
  1267. /* ---------------------------------------------------------------------[<]-
  1268. Function: close_socket
  1269. Synopsis:
  1270. Closes the socket. On UNIX, VMS, OS/2 calls the standard close
  1271. function; some other systems have particular ways of accessing sockets.
  1272. If there is an error on the close this function returns SOCKET_ERROR.
  1273. You can handle errors (in sockerrno) as fatal except for EAGAIN which
  1274. indicates that the operation would cause a non-blocking socket to block.
  1275. Treat EWOULDBLOCK as EAGAIN.
  1276. ---------------------------------------------------------------------[>]-*/
  1277. int
  1278. close_socket (
  1279. sock_t handle /* Socket handle */
  1280. )
  1281. {
  1282. #if (defined (FAKE_SOCKETS))
  1283. return (0); /* Okay, closed */
  1284. #elif (defined (DOES_SOCKETS))
  1285. # if (defined (__UNIX__) || defined (__VMS__) || defined (__OS2__))
  1286. if (!socket_is_alive (handle))
  1287. return (0);
  1288. ip_sockets--;
  1289. shutdown (handle, 2);
  1290. return (close ((SOCKET) handle));
  1291. # elif (defined (__WINDOWS__))
  1292. int
  1293. rc;
  1294. if (!socket_is_alive (handle))
  1295. return (0);
  1296. ip_sockets--;
  1297. shutdown ((SOCKET) handle, 2);
  1298. rc = closesocket ((SOCKET) handle);
  1299. return (win_error (rc));
  1300. # else
  1301. # error "No code for function body."
  1302. return ((int) SOCKET_ERROR); /* Sockets not supported */
  1303. # endif
  1304. #else
  1305. return ((int) SOCKET_ERROR); /* Sockets not supported */
  1306. #endif
  1307. }
  1308. /* ---------------------------------------------------------------------[<]-
  1309. Function: sock_select
  1310. Synopsis: Performs the standard select() call. Use this in preference
  1311. to select(), as some systems may not be 100% compatible with BSD sockets,
  1312. Uses the same arguments as the select() call, and gives the same return
  1313. codes. If sockets are not supported, always returns 0. This function
  1314. will return 0 (nothing done, no error) if the operating system reports
  1315. the select was interrupted during execution (eg, by a signal). This is
  1316. done to distinguish it from other error conditions (like invalid file
  1317. handles which require more drastic handling). Programs using this
  1318. function should not rely on this function having run until the timeout
  1319. expires if it returns 0. (Instead check to see if the time you were
  1320. waiting for has arrived.)
  1321. ---------------------------------------------------------------------[>]-*/
  1322. int
  1323. sock_select (int nfds, fd_set *readfds, fd_set *writefds,
  1324. fd_set *errorfds, struct timeval *timeout)
  1325. {
  1326. #if (defined (DOES_SOCKETS))
  1327. int
  1328. rc = 0; /* Return code from select() */
  1329. /* ASSERT (timeout); Removed: allow no timeout */
  1330. # if (defined (__UTYPE_BEOS))
  1331. /* BeOS only supports the readfds argument */
  1332. rc = select (nfds, FD_SETTYPE readfds, NULL, NULL, timeout);
  1333. if (rc == -1)
  1334. coprintf ("Error after select(): %s", strerror (errno));
  1335. return (rc);
  1336. # elif (defined (WIN32))
  1337. /* Windows occasionally aborts during the select call... */
  1338. __try {
  1339. if (readfds->fd_count == 0
  1340. && writefds->fd_count == 0
  1341. && errorfds->fd_count == 0)
  1342. return 0;
  1343. else
  1344. rc = select (nfds, FD_SETTYPE readfds, FD_SETTYPE writefds,
  1345. FD_SETTYPE errorfds, timeout);
  1346. }
  1347. __except (1) {
  1348. coprintf ("select() aborted - arguments: %d, %p, %p, %p, %p",
  1349. nfds, FD_SETTYPE readfds, FD_SETTYPE writefds,
  1350. FD_SETTYPE errorfds, timeout);
  1351. }
  1352. return (rc);
  1353. # else
  1354. rc = select (nfds, FD_SETTYPE readfds, FD_SETTYPE writefds,
  1355. FD_SETTYPE errorfds, timeout);
  1356. if (rc < 0 && errno == EINTR)
  1357. return 0;
  1358. else
  1359. return (rc);
  1360. # endif
  1361. #else
  1362. return (0);
  1363. #endif
  1364. }
  1365. /* ---------------------------------------------------------------------[<]-
  1366. Function: get_hostname
  1367. Synopsis: Returns a string containing the local hostname. The returned
  1368. string is in a static area. Only performs the local hostname lookup one
  1369. time; the returned value is cached for later repeated calls to this
  1370. function. If sockets are not supported, returns the value "localhost".
  1371. ---------------------------------------------------------------------[>]-*/
  1372. char *
  1373. get_hostname (void)
  1374. {
  1375. #if (defined (DOES_SOCKETS))
  1376. static char
  1377. host_name [LINE_MAX + 1] = "";
  1378. if (strnull (host_name))
  1379. if (gethostname (host_name, LINE_MAX))
  1380. strcpy (host_name, "localhost");
  1381. return (host_name);
  1382. #else
  1383. return ("localhost");
  1384. #endif
  1385. }
  1386. /* ---------------------------------------------------------------------[<]-
  1387. Function: get_hostaddr
  1388. Synopsis: Returns the current the host address as a 4-byte value in
  1389. network order. Returns 0x7f000001 (loopback) if sockets are not
  1390. supported or there was an error getting the current host IP address.
  1391. If there are several IP addresses on the system, returns one arbitrary
  1392. address.
  1393. ---------------------------------------------------------------------[>]-*/
  1394. qbyte
  1395. get_hostaddr (void)
  1396. {
  1397. #if (defined (DOES_SOCKETS))
  1398. struct hostent
  1399. *phe; /* Host information entry */
  1400. phe = (void *)gethostbyname (get_hostname ());
  1401. if (phe)
  1402. return (*(qbyte *) (phe-> h_addr_list [0]));
  1403. else
  1404. return (htonl (SOCKET_LOOPBACK));
  1405. #else
  1406. return (htonl (SOCKET_LOOPBACK));
  1407. #endif
  1408. }
  1409. /* ---------------------------------------------------------------------[<]-
  1410. Function: get_hostaddrs
  1411. Synopsis: Returns a table of all host IP addresses. The table ends in
  1412. a zero address. Each address is a 4-byte value in host format. Returns
  1413. NULL if there was an error. If sockets are not supported, returns a
  1414. table with the loopback address (127.0.0.1) and a null address. The
  1415. caller must free the table using mem_free() when finished using it.
  1416. ---------------------------------------------------------------------[>]-*/
  1417. qbyte *
  1418. get_hostaddrs (void)
  1419. {
  1420. #if (defined (DOES_SOCKETS))
  1421. int
  1422. addr_count; /* How many addresses do we have */
  1423. qbyte
  1424. *addr_table; /* Where we store the addresses */
  1425. struct hostent
  1426. *phe; /* Host information entry */
  1427. if ((phe = (void *)gethostbyname (get_hostname ())) == NULL)
  1428. return (NULL);
  1429. /* Count the addresses */
  1430. for (addr_count = 0; phe-> h_addr_list [addr_count]; addr_count++);
  1431. /* Allocate a table; socket addresses are 4 bytes */
  1432. addr_table = mem_alloc (4 * (addr_count + 1));
  1433. /* Store the addresses */
  1434. for (addr_count = 0; phe-> h_addr_list [addr_count]; addr_count++)
  1435. addr_table [addr_count]
  1436. = *(qbyte *) (phe-> h_addr_list [addr_count]);
  1437. addr_table [addr_count] = 0;
  1438. return (addr_table);
  1439. #else
  1440. qbyte
  1441. *addr_table; /* Where we store the addresses */
  1442. addr_table = mem_alloc (8); /* Addresses are 4 bytes */
  1443. addr_table [0] = htonl (SOCKET_LOOPBACK);
  1444. addr_table [1] = 0;
  1445. return (addr_table);
  1446. #endif
  1447. }
  1448. /* ---------------------------------------------------------------------[<]-
  1449. Function: sock_ntoa
  1450. Synopsis: Converts an IP address in network order to a string in dotted
  1451. format. The string is stored in a statically-allocated buffer that is
  1452. overwritten by each call.
  1453. ---------------------------------------------------------------------[>]-*/
  1454. char *
  1455. sock_ntoa (qbyte address)
  1456. {
  1457. static char
  1458. string [16]; /* xxx.xxx.xxx.xxx */
  1459. byte
  1460. *part;
  1461. /* Network order is high-low so we can address the bytes in order */
  1462. part = (byte *) &address;
  1463. snprintf (string, sizeof (string),
  1464. "%d.%d.%d.%d", part [0], part [1], part [2], part [3]);
  1465. return (string);
  1466. }
  1467. /* ---------------------------------------------------------------------[<]-
  1468. Function: sockmsg
  1469. Synopsis:
  1470. Returns a string describing the cause of the last fatal error to occur
  1471. a socket. Should be called directly after a socket i/o operation; if you
  1472. do other i/o operations or allow other threads to proceed in the meantime,
  1473. the returned string may be incorrect.
  1474. ---------------------------------------------------------------------[>]-*/
  1475. const char *
  1476. sockmsg (void)
  1477. {
  1478. #if (defined (__WINDOWS__))
  1479. char
  1480. *message;
  1481. switch (WSAGetLastError ())
  1482. {
  1483. case WSAEINTR: message = "WSAEINTR"; break;
  1484. case WSAEBADF: message = "WSAEBADF"; break;
  1485. case WSAEACCES: message = "WSAEACCES"; break;
  1486. case WSAEFAULT: message = "WSAEFAULT"; break;
  1487. case WSAEINVAL: message = "WSAEINVAL"; break;
  1488. case WSAEMFILE: message = "WSAEMFILE"; break;
  1489. case WSAEWOULDBLOCK: message = "WSAEWOULDBLOCK"; break;
  1490. case WSAEINPROGRESS: message = "WSAEINPROGRESS"; break;
  1491. case WSAEALREADY: message = "WSAEALREADY"; break;
  1492. case WSAENOTSOCK: message = "WSAENOTSOCK"; break;
  1493. case WSAEDESTADDRREQ: message = "WSAEDESTADDRREQ"; break;
  1494. case WSAEMSGSIZE: message = "WSAEMSGSIZE"; break;
  1495. case WSAEPROTOTYPE: message = "WSAEPROTOTYPE"; break;
  1496. case WSAENOPROTOOPT: message = "WSAENOPROTOOPT"; break;
  1497. case WSAEPROTONOSUPPORT: message = "WSAEPROTONOSUPPORT"; break;
  1498. case WSAESOCKTNOSUPPORT: message = "WSAESOCKTNOSUPPORT"; break;
  1499. case WSAEOPNOTSUPP: message = "WSAEOPNOTSUPP"; break;
  1500. case WSAEPFNOSUPPORT: message = "WSAEPFNOSUPPORT"; break;
  1501. case WSAEAFNOSUPPORT: message = "WSAEAFNOSUPPORT"; break;
  1502. case WSAEADDRINUSE: message = "WSAEADDRINUSE"; break;
  1503. case WSAEADDRNOTAVAIL: message = "WSAEADDRNOTAVAIL"; break;
  1504. case WSAENETDOWN: message = "WSAENETDOWN"; break;
  1505. case WSAENETUNREACH: message = "WSAENETUNREACH"; break;
  1506. case WSAENETRESET: message = "WSAENETRESET"; break;
  1507. case WSAECONNABORTED: message = "WSAECONNABORTED"; break;
  1508. case WSAECONNRESET: message = "WSAECONNRESET"; break;
  1509. case WSAENOBUFS: message = "WSAENOBUFS"; break;
  1510. case WSAEISCONN: message = "WSAEISCONN"; break;
  1511. case WSAENOTCONN: message = "WSAENOTCONN"; break;
  1512. case WSAESHUTDOWN: message = "WSAESHUTDOWN"; break;
  1513. case WSAETOOMANYREFS: message = "WSAETOOMANYREFS"; break;
  1514. case WSAETIMEDOUT: message = "WSAETIMEDOUT"; break;
  1515. case WSAECONNREFUSED: message = "WSAECONNREFUSED"; break;
  1516. case WSAELOOP: message = "WSAELOOP"; break;
  1517. case WSAENAMETOOLONG: message = "WSAENAMETOOLONG"; break;
  1518. case WSAEHOSTDOWN: message = "WSAEHOSTDOWN"; break;
  1519. case WSAEHOSTUNREACH: message = "WSAEHOSTUNREACH"; break;
  1520. case WSAENOTEMPTY: message = "WSAENOTEMPTY"; break;
  1521. case WSAEPROCLIM: message = "WSAEPROCLIM"; break;
  1522. case WSAEUSERS: message = "WSAEUSERS"; break;
  1523. case WSAEDQUOT: message = "WSAEDQUOT"; break;
  1524. case WSAESTALE: message = "WSAESTALE"; break;
  1525. case WSAEREMOTE: message = "WSAEREMOTE"; break;
  1526. case WSAEDISCON: message = "WSAEDISCON"; break;
  1527. case WSASYSNOTREADY: message = "WSASYSNOTREADY"; break;
  1528. case WSAVERNOTSUPPORTED: message = "WSAVERNOTSUPPORTED"; break;
  1529. case WSANOTINITIALISED: message = "WSANOTINITIALISED"; break;
  1530. default: message = "No error";
  1531. }
  1532. return (message);
  1533. #else
  1534. return (strerror (errno));
  1535. #endif
  1536. }
  1537. #if (defined (__WINDOWS__))
  1538. /* ---------------------------------------------------------------------[<]-
  1539. Function: winsock_last_error
  1540. Synopsis: Convert a winsock error into a errno value.
  1541. ---------------------------------------------------------------------[>]-*/
  1542. int
  1543. winsock_last_error (void)
  1544. {
  1545. int
  1546. error = 0;
  1547. switch (WSAGetLastError ())
  1548. {
  1549. case WSAEINTR: error = EINTR; break;
  1550. case WSAEBADF: error = EBADF; break;
  1551. case WSAEWOULDBLOCK: error = EAGAIN; break;
  1552. case WSAEINPROGRESS: error = EAGAIN; break;
  1553. case WSAENETDOWN: error = EAGAIN; break;
  1554. case WSAECONNRESET: error = ECONNRESET; break;
  1555. case WSAECONNABORTED: error = EPIPE; break;
  1556. case WSAESHUTDOWN: error = ECONNRESET; break;
  1557. case WSAEINVAL: error = EPIPE; break;
  1558. # if (defined (WIN32))
  1559. default: error = GetLastError ();
  1560. # else
  1561. default: error = errno;
  1562. # endif
  1563. }
  1564. return (error);
  1565. }
  1566. #endif
  1567. /* ---------------------------------------------------------------------[<]-
  1568. Function: socket_is_permitted
  1569. Synopsis: Compares the specified address with a mask and returns
  1570. TRUE if the address matches the mask, or FALSE if it does not. The
  1571. address is formatted as a string "xxx.xxx.xxx.xxx". The mask is
  1572. formatted as zero or more patterns, delimited by whitespace or commas.
  1573. A pattern is an address string, with zero or more of the last
  1574. components replaced by '*'. The pattern may also be prefixed by '!'
  1575. to indicate exclusion. This is an example of a mask: "127.0.0.1,
  1576. 253.34.*, !253.35.*". This mask allows all addresses: "*". To get
  1577. the string address for a remote socket, use socket_peer_address().
  1578. ---------------------------------------------------------------------[>]-*/
  1579. Bool
  1580. socket_is_permitted (const char *address, const char *mask)
  1581. {
  1582. char
  1583. *addrptr, /* Pointer into address */
  1584. *maskptr; /* Pointer into mask */
  1585. Bool
  1586. negate, /* If !pattern */
  1587. feedback = FALSE; /* False unless matched */
  1588. ASSERT (address);
  1589. ASSERT (mask);
  1590. maskptr = (char *) mask;
  1591. while (*maskptr)
  1592. {
  1593. while (isspace (*maskptr) || *maskptr == ',')
  1594. maskptr++;
  1595. /* Get negation if necessary */
  1596. if (*maskptr == '!')
  1597. {
  1598. negate = TRUE;
  1599. maskptr++;
  1600. }
  1601. else
  1602. negate = FALSE;
  1603. /* Compare pattern with address up to the end of the pattern */
  1604. for (addrptr = (char *) address; *addrptr; addrptr++)
  1605. {
  1606. if (*maskptr == '*') /* Matched address up to * */
  1607. return (!negate); /* So either accepted or failed */
  1608. else
  1609. if (*maskptr == '\0') /* Did not match address */
  1610. return (negate); /* so fail unless negated */
  1611. else
  1612. if (*addrptr != *maskptr) /* Some difference */
  1613. break; /* so stop comparing */
  1614. maskptr++;
  1615. }
  1616. if (*addrptr == '\0' /* Matched exact address? */
  1617. && (*maskptr == '\0' || isspace (*maskptr) || *maskptr == ','))
  1618. return (!negate); /* Either accepted or failed */
  1619. until (*maskptr == '\0' || isspace (*maskptr) || *maskptr == ',')
  1620. maskptr++; /* Skip to end of this pattern */
  1621. }
  1622. return (feedback);
  1623. }
  1624. /* ---------------------------------------------------------------------[<]-
  1625. Function: get_host_file
  1626. Synopsis: returns the full path name of the host lookup file, if provided
  1627. by the OS, and found. If not found, returns "hosts". The returned string
  1628. is held in a static area of memory that may be overwritten by each call.
  1629. ---------------------------------------------------------------------[>]-*/
  1630. char *
  1631. get_host_file (void)
  1632. {
  1633. #if (defined (WIN32))
  1634. static OSVERSIONINFO
  1635. version_info;
  1636. static char
  1637. name [LINE_MAX + 1];
  1638. strclr (name);
  1639. GetWindowsDirectory (name, LINE_MAX);
  1640. version_info.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
  1641. if (GetVersionEx (&version_info))
  1642. /* On Windows NT the hosts file is well-hidden; on Win95 it's
  1643. * more visible */
  1644. if (version_info.dwPlatformId == VER_PLATFORM_WIN32_NT)
  1645. strcat (name, "\\system32\\drivers\\etc\\hosts");
  1646. else
  1647. strcat (name, "\\hosts");
  1648. return (name);
  1649. #elif (defined (__UNIX__))
  1650. return ("/etc/hosts");
  1651. #elif (defined (__VMS__))
  1652. return ("/etc/hosts"); /* Not correct -- needs more work */
  1653. #elif (defined (__OS2__))
  1654. /* Under OS/2 the hosts information is stored in the "hosts" file which
  1655. * is in the directory pointed at by the %ETC% environment variable.
  1656. * If that environment variable is not set, then TCP/IP support is not
  1657. * properly installed. In that instance we return "/mptn/etc/hosts"
  1658. * (the likely value on OS/2 Warp 3 Connect and OS/2 Warp 4) and hope
  1659. * for the best.
  1660. */
  1661. /* A static array is used only because the other versions use a static
  1662. * array. If the resulting file name will not fit in the space allowed
  1663. * then "/mtpn/etc/hosts" is used as before.
  1664. */
  1665. static char
  1666. name [LINE_MAX + 1];
  1667. char
  1668. *etcenv = NULL;
  1669. etcenv = getenv ("ETC");
  1670. if (etcenv != NULL && strlen (etcenv) < (LINE_MAX - 6))
  1671. { /* We've already checked it will all fit. */
  1672. strcpy (name, etcenv);
  1673. strcat (name, "/hosts");
  1674. return (name);
  1675. }
  1676. else
  1677. return ("/mptn/etc/hosts");
  1678. #else
  1679. return ("hosts");
  1680. #endif
  1681. }
  1682. /* ---------------------------------------------------------------------[<]-
  1683. Function: get_name_server
  1684. Synopsis: gets the addresses of the DNS servers defined in the TCP/IP
  1685. configuration. The addresses are returned in a user-provided struct
  1686. sockaddr_in array. The maximum number of addresses in this array is
  1687. supplied as the ns_max argument. Return the number of address found.
  1688. ---------------------------------------------------------------------[>]-*/
  1689. int
  1690. get_name_server (struct sockaddr_in *ns_address, int ns_max)
  1691. {
  1692. int
  1693. ns_count = 0; /* Number of servers that we found */
  1694. #if (defined (WIN32))
  1695. static OSVERSIONINFO
  1696. version_info;
  1697. HKEY
  1698. hkey; /* Handle to returned reg. key */
  1699. static char
  1700. registry_value [LINE_MAX + 1]; /* DNS server info from registry */
  1701. long
  1702. size = LINE_MAX; /* Max. size of returned value */
  1703. DWORD
  1704. type;
  1705. char
  1706. *key,
  1707. **address_list = NULL;
  1708. int
  1709. address_nbr;
  1710. /* Look in registry; this sometimes works, but not always */
  1711. version_info.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
  1712. if (GetVersionEx (&version_info)
  1713. && version_info.dwPlatformId == VER_PLATFORM_WIN32_NT)
  1714. key = "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters";
  1715. else
  1716. key = "SYSTEM\\CurrentControlSet\\Services\\Vxd\\Mstcp\\Parameters";
  1717. if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, key, 0,
  1718. KEY_QUERY_VALUE, &hkey) == ERROR_SUCCESS
  1719. && RegQueryValueEx (hkey, "NameServer", NULL, (LPDWORD) &type,
  1720. (LPBYTE) registry_value, (LPDWORD) &size) == ERROR_SUCCESS)
  1721. {
  1722. address_list = tok_split (registry_value);
  1723. for (address_nbr = 0; address_list [address_nbr]; address_nbr++)
  1724. {
  1725. if (ns_count >= ns_max)
  1726. break;
  1727. ns_address [ns_count].sin_family = AF_INET;
  1728. ns_address [ns_count].sin_port = htons (DNS_PORT);
  1729. ns_address [ns_count].sin_addr.s_addr =
  1730. inet_addr (address_list [address_nbr]);
  1731. ns_count++;
  1732. }
  1733. tok_free (address_list);
  1734. RegCloseKey (hkey);
  1735. }
  1736. #elif (defined (__UNIX__))
  1737. static char
  1738. buffer [LINE_MAX + 1],
  1739. address [16];
  1740. FILE
  1741. *resolver;
  1742. int
  1743. rc;
  1744. resolver = file_open ("/etc/resolv.conf", 'r');
  1745. if (resolver)
  1746. {
  1747. while (file_read (resolver, buffer))
  1748. {
  1749. rc = sscanf (buffer, "nameserver %s", address);
  1750. if (rc > 0 && rc != EOF)
  1751. {
  1752. if (ns_count >= ns_max)
  1753. break;
  1754. ns_address [ns_count].sin_family = AF_INET;
  1755. ns_address [ns_count].sin_port = htons (DNS_PORT);
  1756. ns_address [ns_count].sin_addr.s_addr = inet_addr (address);
  1757. ns_count++;
  1758. }
  1759. }
  1760. file_close (resolver);
  1761. }
  1762. #elif (defined (__OS2__))
  1763. static char
  1764. buffer [LINE_MAX + 1],
  1765. address [16];
  1766. char
  1767. *etcenv = NULL,
  1768. *filename = NULL;
  1769. FILE
  1770. *resolver = NULL;
  1771. int
  1772. rc;
  1773. /* Under OS/2 the file controlling the resolver is stored in the */
  1774. /* directory pointed at by the ETC environment variable. It is called */
  1775. /* resolv2 or resolv (I *think* that is the order of preference), so we */
  1776. /* try those two file names in that order. */
  1777. /* If the ETC environment variable is not set we try the /mptn/etc */
  1778. /* directory since that is a likely default location for it. */
  1779. etcenv = getenv ("ETC");
  1780. if (etcenv)
  1781. {
  1782. filename = mem_alloc (strlen(etcenv) + 10);
  1783. if (!filename)
  1784. return 0; /* Cannot allocate memory for filename */
  1785. strcpy (filename, etcenv);
  1786. strcat (filename, "/resolv2");
  1787. resolver = file_open (filename, 'r');
  1788. if (! resolver)
  1789. { /* Not available under that filename, let's try the other one */
  1790. strcpy (filename, etcenv);
  1791. strcat (filename, "/resolv");
  1792. resolver = file_open (filename, 'r');
  1793. }
  1794. mem_free (filename);
  1795. }
  1796. else
  1797. { /* No environment variable around, try using the defaults */
  1798. resolver = file_open ("/mptn/etc/resolv2", 'r');
  1799. if (! resolver)
  1800. resolver = file_open ("/mptn/etc/resolv", 'r');
  1801. }
  1802. if (resolver)
  1803. {
  1804. while (file_read (resolver, buffer))
  1805. {
  1806. rc = sscanf (buffer, "nameserver %s", address);
  1807. if (rc > 0 && rc != EOF)
  1808. {
  1809. if (ns_count >= ns_max)
  1810. break;
  1811. ns_address [ns_count].sin_family = AF_INET;
  1812. ns_address [ns_count].sin_port = htons (DNS_PORT);
  1813. ns_address [ns_count].sin_addr.s_addr = inet_addr (address);
  1814. ns_count++;
  1815. }
  1816. }
  1817. file_close (resolver);
  1818. }
  1819. #endif
  1820. return (ns_count);
  1821. }