ip.c 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. #include "tunala.h"
  2. #ifndef NO_IP
  3. # define IP_LISTENER_BACKLOG 511/* So if it gets masked by 256 or some other
  4. * such value it'll still be respectable */
  5. /* Any IP-related initialisations. For now, this means blocking SIGPIPE */
  6. int ip_initialise(void)
  7. {
  8. struct sigaction sa;
  9. sa.sa_handler = SIG_IGN;
  10. sa.sa_flags = 0;
  11. sigemptyset(&sa.sa_mask);
  12. if (sigaction(SIGPIPE, &sa, NULL) != 0)
  13. return 0;
  14. return 1;
  15. }
  16. int ip_create_listener_split(const char *ip, unsigned short port)
  17. {
  18. struct sockaddr_in in_addr;
  19. int fd = -1;
  20. int reuseVal = 1;
  21. /* Create the socket */
  22. if ((fd = socket(PF_INET, SOCK_STREAM, 0)) == -1)
  23. goto err;
  24. /* Set the SO_REUSEADDR flag - servers act weird without it */
  25. if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)(&reuseVal),
  26. sizeof(reuseVal)) != 0)
  27. goto err;
  28. /* Prepare the listen address stuff */
  29. in_addr.sin_family = AF_INET;
  30. memcpy(&in_addr.sin_addr.s_addr, ip, 4);
  31. in_addr.sin_port = htons(port);
  32. /* Bind to the required port/address/interface */
  33. if (bind(fd, (struct sockaddr *)&in_addr, sizeof(struct sockaddr_in)) !=
  34. 0)
  35. goto err;
  36. /* Start "listening" */
  37. if (listen(fd, IP_LISTENER_BACKLOG) != 0)
  38. goto err;
  39. return fd;
  40. err:
  41. if (fd != -1)
  42. close(fd);
  43. return -1;
  44. }
  45. int ip_create_connection_split(const char *ip, unsigned short port)
  46. {
  47. struct sockaddr_in in_addr;
  48. int flags, fd = -1;
  49. /* Create the socket */
  50. if ((fd = socket(PF_INET, SOCK_STREAM, 0)) == -1)
  51. goto err;
  52. /* Make it non-blocking */
  53. if (((flags = fcntl(fd, F_GETFL, 0)) < 0) ||
  54. (fcntl(fd, F_SETFL, flags | O_NONBLOCK) < 0))
  55. goto err;
  56. /* Prepare the connection address stuff */
  57. in_addr.sin_family = AF_INET;
  58. memcpy(&in_addr.sin_addr.s_addr, ip, 4);
  59. in_addr.sin_port = htons(port);
  60. /* Start a connect (non-blocking, in all likelihood) */
  61. if ((connect(fd, (struct sockaddr *)&in_addr,
  62. sizeof(struct sockaddr_in)) != 0) && (errno != EINPROGRESS))
  63. goto err;
  64. return fd;
  65. err:
  66. if (fd != -1)
  67. close(fd);
  68. return -1;
  69. }
  70. static char all_local_ip[] = { 0x00, 0x00, 0x00, 0x00 };
  71. int ip_parse_address(const char *address, const char **parsed_ip,
  72. unsigned short *parsed_port, int accept_all_ip)
  73. {
  74. char buf[256];
  75. struct hostent *lookup;
  76. unsigned long port;
  77. const char *ptr = strstr(address, ":");
  78. const char *ip = all_local_ip;
  79. if (!ptr) {
  80. /*
  81. * We assume we're listening on all local interfaces and have only
  82. * specified a port.
  83. */
  84. if (!accept_all_ip)
  85. return 0;
  86. ptr = address;
  87. goto determine_port;
  88. }
  89. if ((ptr - address) > 255)
  90. return 0;
  91. memset(buf, 0, 256);
  92. memcpy(buf, address, ptr - address);
  93. ptr++;
  94. if ((lookup = gethostbyname(buf)) == NULL) {
  95. /*
  96. * Spit a message to differentiate between lookup failures and bad
  97. * strings.
  98. */
  99. fprintf(stderr, "hostname lookup for '%s' failed\n", buf);
  100. return 0;
  101. }
  102. ip = lookup->h_addr_list[0];
  103. determine_port:
  104. if (strlen(ptr) < 1)
  105. return 0;
  106. if (!int_strtoul(ptr, &port) || (port > 65535))
  107. return 0;
  108. *parsed_ip = ip;
  109. *parsed_port = (unsigned short)port;
  110. return 1;
  111. }
  112. int ip_create_listener(const char *address)
  113. {
  114. const char *ip;
  115. unsigned short port;
  116. if (!ip_parse_address(address, &ip, &port, 1))
  117. return -1;
  118. return ip_create_listener_split(ip, port);
  119. }
  120. int ip_create_connection(const char *address)
  121. {
  122. const char *ip;
  123. unsigned short port;
  124. if (!ip_parse_address(address, &ip, &port, 0))
  125. return -1;
  126. return ip_create_connection_split(ip, port);
  127. }
  128. int ip_accept_connection(int listen_fd)
  129. {
  130. return accept(listen_fd, NULL, NULL);
  131. }
  132. #endif /* !defined(NO_IP) */