Another copy of my dotfiles. Because I don't completely trust GitHub.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

209 lines
4.3 KiB

  1. /* See LICENSE file for copyright and license details. */
  2. #include <arpa/inet.h>
  3. #include <errno.h>
  4. #include <fcntl.h>
  5. #include <netdb.h>
  6. #include <netinet/in.h>
  7. #include <stddef.h>
  8. #include <stdio.h>
  9. #include <string.h>
  10. #include <sys/types.h>
  11. #include <sys/socket.h>
  12. #include <sys/stat.h>
  13. #include <sys/time.h>
  14. #include <sys/un.h>
  15. #include <unistd.h>
  16. #include "sock.h"
  17. #include "util.h"
  18. int
  19. sock_get_ips(const char *host, const char* port)
  20. {
  21. struct addrinfo hints = {
  22. .ai_flags = AI_NUMERICSERV,
  23. .ai_family = AF_UNSPEC,
  24. .ai_socktype = SOCK_STREAM,
  25. };
  26. struct addrinfo *ai, *p;
  27. int ret, insock = 0;
  28. if ((ret = getaddrinfo(host, port, &hints, &ai))) {
  29. die("getaddrinfo: %s", gai_strerror(ret));
  30. }
  31. for (p = ai; p; p = p->ai_next) {
  32. if ((insock = socket(p->ai_family, p->ai_socktype,
  33. p->ai_protocol)) < 0) {
  34. continue;
  35. }
  36. if (setsockopt(insock, SOL_SOCKET, SO_REUSEADDR,
  37. &(int){1}, sizeof(int)) < 0) {
  38. die("setsockopt:");
  39. }
  40. if (bind(insock, p->ai_addr, p->ai_addrlen) < 0) {
  41. /* bind failed, close the insock and retry */
  42. if (close(insock) < 0) {
  43. die("close:");
  44. }
  45. continue;
  46. }
  47. break;
  48. }
  49. freeaddrinfo(ai);
  50. if (!p) {
  51. /* we exhaustet the addrinfo-list and found no connection */
  52. if (errno == EACCES) {
  53. die("You need to run as root or have "
  54. "CAP_NET_BIND_SERVICE set to bind to "
  55. "privileged ports");
  56. } else {
  57. die("bind:");
  58. }
  59. }
  60. if (listen(insock, SOMAXCONN) < 0) {
  61. die("listen:");
  62. }
  63. return insock;
  64. }
  65. int
  66. sock_get_uds(const char *udsname, uid_t uid, gid_t gid)
  67. {
  68. struct sockaddr_un addr = {
  69. .sun_family = AF_UNIX,
  70. };
  71. size_t udsnamelen;
  72. int insock, sockmode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP |
  73. S_IROTH | S_IWOTH;
  74. if ((insock = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
  75. die("socket:");
  76. }
  77. if ((udsnamelen = strlen(udsname)) > sizeof(addr.sun_path) - 1) {
  78. die("UNIX-domain socket name truncated");
  79. }
  80. memcpy(addr.sun_path, udsname, udsnamelen + 1);
  81. if (bind(insock, (const struct sockaddr *)&addr, sizeof(addr)) < 0) {
  82. die("bind '%s':", udsname);
  83. }
  84. if (listen(insock, SOMAXCONN) < 0) {
  85. sock_rem_uds(udsname);
  86. die("listen:");
  87. }
  88. if (chmod(udsname, sockmode) < 0) {
  89. sock_rem_uds(udsname);
  90. die("chmod '%s':", udsname);
  91. }
  92. if (chown(udsname, uid, gid) < 0) {
  93. sock_rem_uds(udsname);
  94. die("chown '%s':", udsname);
  95. }
  96. return insock;
  97. }
  98. void
  99. sock_rem_uds(const char *udsname)
  100. {
  101. if (unlink(udsname) < 0) {
  102. die("unlink '%s':", udsname);
  103. }
  104. }
  105. int
  106. sock_set_timeout(int fd, int sec)
  107. {
  108. struct timeval tv;
  109. tv.tv_sec = sec;
  110. tv.tv_usec = 0;
  111. if (setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) < 0 ||
  112. setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)) < 0) {
  113. warn("setsockopt:");
  114. return 1;
  115. }
  116. return 0;
  117. }
  118. int
  119. sock_set_nonblocking(int fd)
  120. {
  121. int flags;
  122. if ((flags = fcntl(fd, F_GETFL, 0)) < 0) {
  123. warn("fcntl:");
  124. return 1;
  125. }
  126. flags |= O_NONBLOCK;
  127. if (fcntl(fd, F_SETFL, flags) < 0) {
  128. warn("fcntl:");
  129. return 1;
  130. }
  131. return 0;
  132. }
  133. int
  134. sock_get_inaddr_str(const struct sockaddr_storage *in_sa, char *str,
  135. size_t len)
  136. {
  137. switch (in_sa->ss_family) {
  138. case AF_INET:
  139. if (!inet_ntop(AF_INET,
  140. &(((struct sockaddr_in *)in_sa)->sin_addr),
  141. str, len)) {
  142. warn("inet_ntop:");
  143. return 1;
  144. }
  145. break;
  146. case AF_INET6:
  147. if (!inet_ntop(AF_INET6,
  148. &(((struct sockaddr_in6 *)in_sa)->sin6_addr),
  149. str, len)) {
  150. warn("inet_ntop:");
  151. return 1;
  152. }
  153. break;
  154. case AF_UNIX:
  155. snprintf(str, len, "uds");
  156. break;
  157. default:
  158. snprintf(str, len, "-");
  159. }
  160. return 0;
  161. }
  162. int
  163. sock_same_addr(const struct sockaddr_storage *sa1, const struct sockaddr_storage *sa2)
  164. {
  165. /* return early if address-families don't match */
  166. if (sa1->ss_family != sa2->ss_family) {
  167. return 0;
  168. }
  169. switch (sa1->ss_family) {
  170. case AF_INET6:
  171. return memcmp(((struct sockaddr_in6 *)sa1)->sin6_addr.s6_addr,
  172. ((struct sockaddr_in6 *)sa2)->sin6_addr.s6_addr,
  173. sizeof(((struct sockaddr_in6 *)sa1)->sin6_addr.s6_addr));
  174. case AF_INET:
  175. return ntohl(((struct sockaddr_in *)sa1)->sin_addr.s_addr) ==
  176. ntohl(((struct sockaddr_in *)sa2)->sin_addr.s_addr);
  177. default: /* AF_UNIX */
  178. return strcmp(((struct sockaddr_un *)sa1)->sun_path,
  179. ((struct sockaddr_un *)sa2)->sun_path) == 0;
  180. }
  181. }