spiped 0.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (102) hide show
  1. checksums.yaml +7 -0
  2. data/ext/spiped/extconf.rb +3 -0
  3. data/ext/spiped/spiped-source/BUILDING +46 -0
  4. data/ext/spiped/spiped-source/CHANGELOG +44 -0
  5. data/ext/spiped/spiped-source/COPYRIGHT +33 -0
  6. data/ext/spiped/spiped-source/Makefile +47 -0
  7. data/ext/spiped/spiped-source/Makefile.POSIX +27 -0
  8. data/ext/spiped/spiped-source/Makefile.inc +20 -0
  9. data/ext/spiped/spiped-source/Makefile.prog +23 -0
  10. data/ext/spiped/spiped-source/POSIX/README +10 -0
  11. data/ext/spiped/spiped-source/POSIX/posix-cflags.sh +10 -0
  12. data/ext/spiped/spiped-source/POSIX/posix-clock_realtime.c +3 -0
  13. data/ext/spiped/spiped-source/POSIX/posix-l.c +1 -0
  14. data/ext/spiped/spiped-source/POSIX/posix-l.sh +14 -0
  15. data/ext/spiped/spiped-source/POSIX/posix-msg_nosignal.c +3 -0
  16. data/ext/spiped/spiped-source/README +198 -0
  17. data/ext/spiped/spiped-source/STYLE +151 -0
  18. data/ext/spiped/spiped-source/lib/dnsthread/dnsthread.c +464 -0
  19. data/ext/spiped/spiped-source/lib/dnsthread/dnsthread.h +45 -0
  20. data/ext/spiped/spiped-source/libcperciva/alg/sha256.c +442 -0
  21. data/ext/spiped/spiped-source/libcperciva/alg/sha256.h +95 -0
  22. data/ext/spiped/spiped-source/libcperciva/cpusupport/Build/cpusupport-X86-AESNI.c +13 -0
  23. data/ext/spiped/spiped-source/libcperciva/cpusupport/Build/cpusupport-X86-CPUID.c +8 -0
  24. data/ext/spiped/spiped-source/libcperciva/cpusupport/Build/cpusupport.sh +37 -0
  25. data/ext/spiped/spiped-source/libcperciva/cpusupport/cpusupport.h +63 -0
  26. data/ext/spiped/spiped-source/libcperciva/cpusupport/cpusupport_x86_aesni.c +30 -0
  27. data/ext/spiped/spiped-source/libcperciva/crypto/crypto_aes.c +166 -0
  28. data/ext/spiped/spiped-source/libcperciva/crypto/crypto_aes.h +31 -0
  29. data/ext/spiped/spiped-source/libcperciva/crypto/crypto_aes_aesni.c +229 -0
  30. data/ext/spiped/spiped-source/libcperciva/crypto/crypto_aes_aesni.h +31 -0
  31. data/ext/spiped/spiped-source/libcperciva/crypto/crypto_aesctr.c +124 -0
  32. data/ext/spiped/spiped-source/libcperciva/crypto/crypto_aesctr.h +41 -0
  33. data/ext/spiped/spiped-source/libcperciva/crypto/crypto_dh.c +293 -0
  34. data/ext/spiped/spiped-source/libcperciva/crypto/crypto_dh.h +43 -0
  35. data/ext/spiped/spiped-source/libcperciva/crypto/crypto_dh_group14.c +46 -0
  36. data/ext/spiped/spiped-source/libcperciva/crypto/crypto_dh_group14.h +9 -0
  37. data/ext/spiped/spiped-source/libcperciva/crypto/crypto_entropy.c +215 -0
  38. data/ext/spiped/spiped-source/libcperciva/crypto/crypto_entropy.h +14 -0
  39. data/ext/spiped/spiped-source/libcperciva/crypto/crypto_verify_bytes.c +21 -0
  40. data/ext/spiped/spiped-source/libcperciva/crypto/crypto_verify_bytes.h +14 -0
  41. data/ext/spiped/spiped-source/libcperciva/datastruct/elasticarray.c +276 -0
  42. data/ext/spiped/spiped-source/libcperciva/datastruct/elasticarray.h +167 -0
  43. data/ext/spiped/spiped-source/libcperciva/datastruct/mpool.h +85 -0
  44. data/ext/spiped/spiped-source/libcperciva/datastruct/ptrheap.c +334 -0
  45. data/ext/spiped/spiped-source/libcperciva/datastruct/ptrheap.h +89 -0
  46. data/ext/spiped/spiped-source/libcperciva/datastruct/timerqueue.c +241 -0
  47. data/ext/spiped/spiped-source/libcperciva/datastruct/timerqueue.h +60 -0
  48. data/ext/spiped/spiped-source/libcperciva/events/events.c +203 -0
  49. data/ext/spiped/spiped-source/libcperciva/events/events.h +106 -0
  50. data/ext/spiped/spiped-source/libcperciva/events/events_immediate.c +149 -0
  51. data/ext/spiped/spiped-source/libcperciva/events/events_internal.h +95 -0
  52. data/ext/spiped/spiped-source/libcperciva/events/events_network.c +347 -0
  53. data/ext/spiped/spiped-source/libcperciva/events/events_network_selectstats.c +106 -0
  54. data/ext/spiped/spiped-source/libcperciva/events/events_timer.c +273 -0
  55. data/ext/spiped/spiped-source/libcperciva/network/network.h +95 -0
  56. data/ext/spiped/spiped-source/libcperciva/network/network_accept.c +103 -0
  57. data/ext/spiped/spiped-source/libcperciva/network/network_connect.c +258 -0
  58. data/ext/spiped/spiped-source/libcperciva/network/network_read.c +155 -0
  59. data/ext/spiped/spiped-source/libcperciva/network/network_write.c +188 -0
  60. data/ext/spiped/spiped-source/libcperciva/util/asprintf.c +49 -0
  61. data/ext/spiped/spiped-source/libcperciva/util/asprintf.h +16 -0
  62. data/ext/spiped/spiped-source/libcperciva/util/daemonize.c +134 -0
  63. data/ext/spiped/spiped-source/libcperciva/util/daemonize.h +10 -0
  64. data/ext/spiped/spiped-source/libcperciva/util/entropy.c +76 -0
  65. data/ext/spiped/spiped-source/libcperciva/util/entropy.h +13 -0
  66. data/ext/spiped/spiped-source/libcperciva/util/imalloc.h +33 -0
  67. data/ext/spiped/spiped-source/libcperciva/util/insecure_memzero.c +19 -0
  68. data/ext/spiped/spiped-source/libcperciva/util/insecure_memzero.h +33 -0
  69. data/ext/spiped/spiped-source/libcperciva/util/monoclock.c +52 -0
  70. data/ext/spiped/spiped-source/libcperciva/util/monoclock.h +14 -0
  71. data/ext/spiped/spiped-source/libcperciva/util/noeintr.c +54 -0
  72. data/ext/spiped/spiped-source/libcperciva/util/noeintr.h +14 -0
  73. data/ext/spiped/spiped-source/libcperciva/util/sock.c +472 -0
  74. data/ext/spiped/spiped-source/libcperciva/util/sock.h +56 -0
  75. data/ext/spiped/spiped-source/libcperciva/util/sock_internal.h +14 -0
  76. data/ext/spiped/spiped-source/libcperciva/util/sock_util.c +271 -0
  77. data/ext/spiped/spiped-source/libcperciva/util/sock_util.h +51 -0
  78. data/ext/spiped/spiped-source/libcperciva/util/sysendian.h +146 -0
  79. data/ext/spiped/spiped-source/libcperciva/util/warnp.c +76 -0
  80. data/ext/spiped/spiped-source/libcperciva/util/warnp.h +59 -0
  81. data/ext/spiped/spiped-source/proto/proto_conn.c +362 -0
  82. data/ext/spiped/spiped-source/proto/proto_conn.h +25 -0
  83. data/ext/spiped/spiped-source/proto/proto_crypt.c +396 -0
  84. data/ext/spiped/spiped-source/proto/proto_crypt.h +102 -0
  85. data/ext/spiped/spiped-source/proto/proto_handshake.c +330 -0
  86. data/ext/spiped/spiped-source/proto/proto_handshake.h +30 -0
  87. data/ext/spiped/spiped-source/proto/proto_pipe.c +202 -0
  88. data/ext/spiped/spiped-source/proto/proto_pipe.h +23 -0
  89. data/ext/spiped/spiped-source/spipe/Makefile +90 -0
  90. data/ext/spiped/spiped-source/spipe/README +24 -0
  91. data/ext/spiped/spiped-source/spipe/main.c +178 -0
  92. data/ext/spiped/spiped-source/spipe/pushbits.c +101 -0
  93. data/ext/spiped/spiped-source/spipe/pushbits.h +10 -0
  94. data/ext/spiped/spiped-source/spipe/spipe.1 +60 -0
  95. data/ext/spiped/spiped-source/spiped/Makefile +98 -0
  96. data/ext/spiped/spiped-source/spiped/README +62 -0
  97. data/ext/spiped/spiped-source/spiped/dispatch.c +214 -0
  98. data/ext/spiped/spiped-source/spiped/dispatch.h +27 -0
  99. data/ext/spiped/spiped-source/spiped/main.c +267 -0
  100. data/ext/spiped/spiped-source/spiped/spiped.1 +112 -0
  101. data/lib/spiped.rb +3 -0
  102. metadata +143 -0
@@ -0,0 +1,13 @@
1
+ #ifndef _ENTROPY_H_
2
+ #define _ENTROPY_H_
3
+
4
+ #include <stddef.h>
5
+ #include <stdint.h>
6
+
7
+ /**
8
+ * entropy_read(buf, buflen):
9
+ * Fill the given buffer with random bytes provided by the operating system.
10
+ */
11
+ int entropy_read(uint8_t *, size_t);
12
+
13
+ #endif /* !_ENTROPY_H_ */
@@ -0,0 +1,33 @@
1
+ #ifndef _IMALLOC_H_
2
+ #define _IMALLOC_H_
3
+
4
+ #include <errno.h>
5
+ #include <stdint.h>
6
+ #include <stdlib.h>
7
+
8
+ /**
9
+ * imalloc(nrec, reclen):
10
+ * Allocate ${nrec} records of length ${reclen}. Check for size_t overflow.
11
+ */
12
+ static inline void *
13
+ imalloc(size_t nrec, size_t reclen)
14
+ {
15
+
16
+ if (nrec > SIZE_MAX / reclen) {
17
+ errno = ENOMEM;
18
+ return (NULL);
19
+ } else {
20
+ return (malloc(nrec * reclen));
21
+ }
22
+ }
23
+
24
+ /**
25
+ * IMALLOC(p, nrec, type):
26
+ * Allocate ${nrec} records of type ${type} and store the pointer in ${p}.
27
+ * Return non-zero on failure.
28
+ */
29
+ #define IMALLOC(p, nrec, type) \
30
+ ((((p) = (type *)imalloc((nrec), sizeof(type))) == NULL) && \
31
+ ((nrec) > 0))
32
+
33
+ #endif /* !_IMALLOC_H_ */
@@ -0,0 +1,19 @@
1
+ #include <stddef.h>
2
+ #include <stdint.h>
3
+
4
+ #include "insecure_memzero.h"
5
+
6
+ /* Fucntion which does the zeroing. */
7
+ static void
8
+ insecure_memzero_func(volatile void * buf, size_t len)
9
+ {
10
+ volatile uint8_t * _buf = buf;
11
+ size_t i;
12
+
13
+ for (i = 0; i < len; i++)
14
+ _buf[i] = 0;
15
+ }
16
+
17
+ /* Pointer to memory-zeroing function. */
18
+ void (* volatile insecure_memzero_ptr)(volatile void *, size_t) =
19
+ insecure_memzero_func;
@@ -0,0 +1,33 @@
1
+ #ifndef _INSECURE_MEMZERO_H_
2
+ #define _INSECURE_MEMZERO_H_
3
+
4
+ #include <stddef.h>
5
+
6
+ /* Pointer to memory-zeroing function. */
7
+ extern void (* volatile insecure_memzero_ptr)(volatile void *, size_t);
8
+
9
+ /**
10
+ * insecure_memzero(buf, len):
11
+ * Attempt to zero ${len} bytes at ${buf} in spite of optimizing compilers'
12
+ * best (standards-compliant) attempts to remove the buffer-zeroing. In
13
+ * particular, to avoid performing the zeroing, a compiler would need to
14
+ * use optimistic devirtualization; recognize that non-volatile objects do not
15
+ * need to be treated as volatile, even if they are accessed via volatile
16
+ * qualified pointers; and perform link-time optimization; in addition to the
17
+ * dead-code elimination which often causes buffer-zeroing to be elided.
18
+ *
19
+ * Note however that zeroing a buffer does nto guarantee that the data held
20
+ * in the buffer is not stored elsewhere; in particular, there may be copies
21
+ * held in CPU registers or in anonymous allocations on the stack, even if
22
+ * every named variable is successfully sanitized. Solving the "wipe data
23
+ * from the system" problem will require a C language extension which does not
24
+ * yet exist.
25
+ */
26
+ static inline void
27
+ insecure_memzero(volatile void * buf, size_t len)
28
+ {
29
+
30
+ (insecure_memzero_ptr)(buf, len);
31
+ }
32
+
33
+ #endif /* !_INSECURE_MEMZERO_H_ */
@@ -0,0 +1,52 @@
1
+ #include <sys/time.h>
2
+
3
+ #include <time.h>
4
+
5
+ #include "warnp.h"
6
+
7
+ #include "monoclock.h"
8
+
9
+ /**
10
+ * monoclock_get(tv):
11
+ * Store the current time in ${tv}. If CLOCK_MONOTONIC is available, use
12
+ * that clock; if CLOCK_MONOTONIC is unavailable, use CLOCK_REALTIME (if
13
+ * available) or gettimeofday(2).
14
+ */
15
+ int
16
+ monoclock_get(struct timeval * tv)
17
+ {
18
+ #if defined(CLOCK_MONOTONIC) || !defined(POSIXFAIL_CLOCK_REALTIME)
19
+ struct timespec tp;
20
+ #endif
21
+
22
+ #ifdef CLOCK_MONOTONIC
23
+ if (clock_gettime(CLOCK_MONOTONIC, &tp) == 0) {
24
+ tv->tv_sec = tp.tv_sec;
25
+ tv->tv_usec = tp.tv_nsec / 1000;
26
+ } else if ((errno != ENOSYS) && (errno != EINVAL)) {
27
+ warnp("clock_gettime(CLOCK_MONOTONIC)");
28
+ goto err0;
29
+ } else
30
+ #endif
31
+ #ifndef POSIXFAIL_CLOCK_REALTIME
32
+ if (clock_gettime(CLOCK_REALTIME, &tp) == 0) {
33
+ tv->tv_sec = tp.tv_sec;
34
+ tv->tv_usec = tp.tv_nsec / 1000;
35
+ } else {
36
+ warnp("clock_gettime(CLOCK_REALTIME)");
37
+ goto err0;
38
+ }
39
+ #else
40
+ if (gettimeofday(tv, NULL)) {
41
+ warnp("gettimeofday");
42
+ goto err0;
43
+ }
44
+ #endif
45
+
46
+ /* Success! */
47
+ return (0);
48
+
49
+ err0:
50
+ /* Failure! */
51
+ return (-1);
52
+ }
@@ -0,0 +1,14 @@
1
+ #ifndef _MONOCLOCK_H_
2
+ #define _MONOCLOCK_H_
3
+
4
+ #include <sys/time.h>
5
+
6
+ /**
7
+ * monoclock_get(tv):
8
+ * Store the current time in ${tv}. If CLOCK_MONOTONIC is available, use
9
+ * that clock; if CLOCK_MONOTONIC is unavailable, use CLOCK_REALTIME (if
10
+ * available) or gettimeofday(2).
11
+ */
12
+ int monoclock_get(struct timeval *);
13
+
14
+ #endif /* !_MONOCLOCK_H_ */
@@ -0,0 +1,54 @@
1
+ #include <assert.h>
2
+ #include <errno.h>
3
+ #include <limits.h>
4
+ #include <stdint.h>
5
+ #include <unistd.h>
6
+
7
+ #include "noeintr.h"
8
+
9
+ /**
10
+ * noeintr_write(d, buf, nbytes):
11
+ * Write ${nbytes} bytes of data from ${buf} to the file descriptor ${d} per
12
+ * the write(2) system call, but looping until completion if interrupted by
13
+ * a signal. Return ${nbytes} on success or -1 on error.
14
+ */
15
+ ssize_t
16
+ noeintr_write(int d, const void * buf, size_t nbyte)
17
+ {
18
+ const uint8_t * p = buf;
19
+ size_t len = nbyte;
20
+ ssize_t lenwrit;
21
+
22
+ /* Implementation-defined: Don't allow oversized writes. */
23
+ assert(nbyte <= SSIZE_MAX);
24
+
25
+ /* Loop until we have no data left to write. */
26
+ while (len > 0) {
27
+ if ((lenwrit = write(d, p, len)) == -1) {
28
+ /* EINTR is harmless. */
29
+ if (errno == EINTR)
30
+ continue;
31
+
32
+ /* Anything else isn't. */
33
+ goto err0;
34
+ }
35
+
36
+ /* Sanity check. */
37
+ assert(lenwrit >= 0);
38
+ assert(lenwrit <= (ssize_t)len);
39
+
40
+ /*
41
+ * We might have done a partial write; advance the buffer
42
+ * pointer and adjust the remaining write length.
43
+ */
44
+ p += lenwrit;
45
+ len -= lenwrit;
46
+ }
47
+
48
+ /* Success! */
49
+ return (nbyte);
50
+
51
+ err0:
52
+ /* Failure! */
53
+ return (-1);
54
+ }
@@ -0,0 +1,14 @@
1
+ #ifndef _NOEINTR_H_
2
+ #define _NOEINTR_H_
3
+
4
+ #include <unistd.h>
5
+
6
+ /**
7
+ * noeintr_write(d, buf, nbytes):
8
+ * Write ${nbytes} bytes of data from ${buf} to the file descriptor ${d} per
9
+ * the write(2) system call, but looping until completion if interrupted by
10
+ * a signal. Return ${nbytes} on success or -1 on error.
11
+ */
12
+ ssize_t noeintr_write(int, const void *, size_t);
13
+
14
+ #endif /* _NOEINTR_H_ */
@@ -0,0 +1,472 @@
1
+ #include <sys/types.h>
2
+ #include <sys/socket.h>
3
+ #include <sys/un.h>
4
+
5
+ #include <netinet/in.h>
6
+
7
+ #include <arpa/inet.h>
8
+
9
+ #include <errno.h>
10
+ #include <fcntl.h>
11
+ #include <netdb.h>
12
+ #include <stdint.h>
13
+ #include <string.h>
14
+ #include <unistd.h>
15
+
16
+ #include "imalloc.h"
17
+ #include "warnp.h"
18
+
19
+ #include "sock.h"
20
+ #include "sock_internal.h"
21
+
22
+ /* Convert a path into a socket address. */
23
+ static struct sock_addr **
24
+ sock_resolve_unix(const char * addr)
25
+ {
26
+ struct sock_addr ** sas;
27
+ struct sock_addr * sa;
28
+ struct sockaddr_un * sa_un;
29
+
30
+ /* Allocate and populate a sockaddr_un structure. */
31
+ if ((sa_un = calloc(1, sizeof(struct sockaddr_un))) == NULL)
32
+ goto err0;
33
+ sa_un->sun_family = AF_UNIX;
34
+ if (strlen(addr) >= sizeof(sa_un->sun_path)) {
35
+ warn0("socket path too long: %s", addr);
36
+ goto err1;
37
+ }
38
+ strcpy(sa_un->sun_path, addr);
39
+
40
+ /* Allocate and populate our wrapper. */
41
+ if ((sa = malloc(sizeof(struct sock_addr))) == NULL)
42
+ goto err1;
43
+ sa->ai_family = AF_UNIX;
44
+ sa->ai_socktype = SOCK_STREAM;
45
+ sa->name = (struct sockaddr *)sa_un;
46
+ sa->namelen = sizeof(struct sockaddr_un);
47
+
48
+ /* Allocate and populate an array of pointers. */
49
+ if ((sas = malloc(2 * sizeof(struct sock_addr *))) == NULL)
50
+ goto err2;
51
+ sas[0] = sa;
52
+ sas[1] = NULL;
53
+
54
+ /* Success! */
55
+ return (sas);
56
+
57
+ err2:
58
+ free(sa);
59
+ err1:
60
+ free(sa_un);
61
+ err0:
62
+ /* Failure! */
63
+ return (NULL);
64
+ }
65
+
66
+ /* Resolve a host into a list of socket addresses. */
67
+ static struct sock_addr **
68
+ sock_resolve_host(const char * addr, const char * ports)
69
+ {
70
+ struct addrinfo hints;
71
+ struct addrinfo * res;
72
+ struct addrinfo * r;
73
+ struct sock_addr ** sas;
74
+ size_t n;
75
+ int error;
76
+
77
+ /* Create hints structure. */
78
+ memset(&hints, 0, sizeof(hints));
79
+ hints.ai_family = AF_UNSPEC;
80
+ hints.ai_socktype = SOCK_STREAM;
81
+ hints.ai_protocol = IPPROTO_TCP;
82
+
83
+ /* Perform DNS lookup. */
84
+ if ((error = getaddrinfo(addr, ports, &hints, &res)) != 0) {
85
+ warn0("Error looking up %s: %s", addr, gai_strerror(error));
86
+ goto err0;
87
+ }
88
+
89
+ /* Count addresses returned. */
90
+ for (n = 0, r = res; r != NULL; r = r->ai_next)
91
+ n++;
92
+
93
+ /* Allocate our response array. */
94
+ if (IMALLOC(sas, n + 1, struct sock_addr *))
95
+ goto err1;
96
+
97
+ /* Create address structures. */
98
+ for (n = 0, r = res; r != NULL; n++, r = r->ai_next) {
99
+ /* Allocate a structure. */
100
+ if ((sas[n] = malloc(sizeof(struct sock_addr))) == NULL)
101
+ goto err2;
102
+
103
+ /* Copy in the address metadata. */
104
+ sas[n]->ai_family = r->ai_family;
105
+ sas[n]->ai_socktype = r->ai_socktype;
106
+ sas[n]->namelen = r->ai_addrlen;
107
+
108
+ /* Duplicate the address. */
109
+ if ((sas[n]->name = malloc(sas[n]->namelen)) == NULL)
110
+ goto err3;
111
+ memcpy(sas[n]->name, r->ai_addr, sas[n]->namelen);
112
+ }
113
+
114
+ /* Terminate array with a NULL. */
115
+ sas[n] = NULL;
116
+
117
+ /* Free the linked list of addresses returned by getaddrinfo. */
118
+ freeaddrinfo(res);
119
+
120
+ /* Success! */
121
+ return (sas);
122
+
123
+ err3:
124
+ free(sas[n]);
125
+ err2:
126
+ for (; n > 0; n--)
127
+ sock_addr_free(sas[n - 1]);
128
+ free(sas);
129
+ err1:
130
+ freeaddrinfo(res);
131
+ err0:
132
+ /* Failure! */
133
+ return (NULL);
134
+ }
135
+
136
+ /* Parse an IPv6 address into a socket address. */
137
+ static struct sock_addr **
138
+ sock_resolve_ipv6(const char * addr, in_port_t p)
139
+ {
140
+ struct sock_addr ** sas;
141
+ struct sock_addr * sa;
142
+ struct sockaddr_in6 * sin6;
143
+
144
+ /* Allocate and populate a sockaddr_in6 structure. */
145
+ if ((sin6 = calloc(1, sizeof(struct sockaddr_in6))) == NULL)
146
+ goto err0;
147
+ sin6->sin6_family = AF_INET6;
148
+ sin6->sin6_port = htons(p);
149
+ if (inet_pton(AF_INET6, addr, &sin6->sin6_addr) != 1) {
150
+ warn0("Error parsing IP address: %s", addr);
151
+ goto err1;
152
+ }
153
+
154
+ /* Allocate and populate our wrapper. */
155
+ if ((sa = malloc(sizeof(struct sock_addr))) == NULL)
156
+ goto err1;
157
+ sa->ai_family = AF_INET6;
158
+ sa->ai_socktype = SOCK_STREAM;
159
+ sa->name = (struct sockaddr *)sin6;
160
+ sa->namelen = sizeof(struct sockaddr_in6);
161
+
162
+ /* Allocate and populate an array of pointers. */
163
+ if ((sas = malloc(2 * sizeof(struct sock_addr *))) == NULL)
164
+ goto err2;
165
+ sas[0] = sa;
166
+ sas[1] = NULL;
167
+
168
+ /* Success! */
169
+ return (sas);
170
+
171
+ err2:
172
+ free(sa);
173
+ err1:
174
+ free(sin6);
175
+ err0:
176
+ /* Failure! */
177
+ return (NULL);
178
+ }
179
+
180
+ /* Parse an IPv4 address into a socket address. */
181
+ static struct sock_addr **
182
+ sock_resolve_ipv4(const char * addr, in_port_t p)
183
+ {
184
+ struct sock_addr ** sas;
185
+ struct sock_addr * sa;
186
+ struct sockaddr_in * sin;
187
+
188
+ /* Allocate and populate a sockaddr_in structure. */
189
+ if ((sin = calloc(1, sizeof(struct sockaddr_in))) == NULL)
190
+ goto err0;
191
+ sin->sin_family = AF_INET;
192
+ sin->sin_port = htons(p);
193
+ if (inet_pton(AF_INET, addr, &sin->sin_addr) != 1) {
194
+ warn0("Error parsing IP address: %s", addr);
195
+ goto err1;
196
+ }
197
+
198
+ /* Allocate and populate our wrapper. */
199
+ if ((sa = malloc(sizeof(struct sock_addr))) == NULL)
200
+ goto err1;
201
+ sa->ai_family = AF_INET;
202
+ sa->ai_socktype = SOCK_STREAM;
203
+ sa->name = (struct sockaddr *)sin;
204
+ sa->namelen = sizeof(struct sockaddr_in);
205
+
206
+ /* Allocate and populate an array of pointers. */
207
+ if ((sas = malloc(2 * sizeof(struct sock_addr *))) == NULL)
208
+ goto err2;
209
+ sas[0] = sa;
210
+ sas[1] = NULL;
211
+
212
+ /* Success! */
213
+ return (sas);
214
+
215
+ err2:
216
+ free(sa);
217
+ err1:
218
+ free(sin);
219
+ err0:
220
+ /* Failure! */
221
+ return (NULL);
222
+ }
223
+
224
+ /**
225
+ * sock_resolve(addr):
226
+ * Return a NULL-terminated array of pointers to sock_addr structures.
227
+ */
228
+ struct sock_addr **
229
+ sock_resolve(const char * addr)
230
+ {
231
+ struct sock_addr ** res;
232
+ char * s;
233
+ char * ports;
234
+ char * ips;
235
+ long p;
236
+
237
+ /* If the address starts with '/', it's a unix socket. */
238
+ if (addr[0] == '/') {
239
+ res = sock_resolve_unix(addr);
240
+ goto done0;
241
+ }
242
+
243
+ /* Copy the address so that we can mangle it. */
244
+ if ((s = strdup(addr)) == NULL)
245
+ goto err0;
246
+
247
+ /* The address should end with :port. Look for the last ':'. */
248
+ if ((ports = strrchr(s, ':')) == NULL) {
249
+ warn0("Address must contain port number: %s", s);
250
+ goto err1;
251
+ }
252
+ *ports++ = '\0';
253
+
254
+ /* If the address doesn't start with '[', it's a host name. */
255
+ if (s[0] != '[') {
256
+ res = sock_resolve_host(s, ports);
257
+ goto done1;
258
+ }
259
+
260
+ /* The address (sans :port) should end with ']'. */
261
+ if (s[strlen(s) - 1] != ']') {
262
+ warn0("Invalid [IP address]: %s", s);
263
+ goto err1;
264
+ }
265
+
266
+ /* Extract the IP address string. */
267
+ ips = &s[1];
268
+ ips[strlen(ips) - 1] = '\0';
269
+
270
+ /*
271
+ * Parse the port number. If strtol fails to parse the port number,
272
+ * it will return 0; but that's fine since port 0 is invalid anyway.
273
+ */
274
+ p = strtol(ports, NULL, 10);
275
+ if ((p <= 0) || (p >= 65536)) {
276
+ warn0("Invalid port number: %s", ports);
277
+ goto err1;
278
+ }
279
+
280
+ /* If the IP address contains ':', it's IPv6; otherwise, IPv4. */
281
+ if (strchr(ips, ':') != NULL)
282
+ res = sock_resolve_ipv6(ips, p);
283
+ else
284
+ res = sock_resolve_ipv4(ips, p);
285
+
286
+ done1:
287
+ /* Free string allocated by strdup. */
288
+ free(s);
289
+ done0:
290
+ /* Return result from sock_resolve_foo. */
291
+ return (res);
292
+
293
+ err1:
294
+ free(s);
295
+ err0:
296
+ /* Failure! */
297
+ return (NULL);
298
+ }
299
+
300
+ /**
301
+ * sock_listener(sa):
302
+ * Create a socket, set SO_REUSEADDR, bind it to the socket address ${sa},
303
+ * mark it for listening, and mark it as non-blocking.
304
+ */
305
+ int
306
+ sock_listener(const struct sock_addr * sa)
307
+ {
308
+ int s;
309
+ int val = 1;
310
+
311
+ /* Create a socket. */
312
+ if ((s = socket(sa->ai_family, sa->ai_socktype, 0)) == -1) {
313
+ warnp("socket(%d, %d)", sa->ai_family, sa->ai_socktype);
314
+ goto err0;
315
+ }
316
+
317
+ /* Set SO_REUSEADDR. */
318
+ if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val))) {
319
+ warnp("setsockopt(SO_REUSEADDR)");
320
+ goto err1;
321
+ }
322
+
323
+ /* Bind the socket. */
324
+ if (bind(s, sa->name, sa->namelen)) {
325
+ warnp("Error binding socket");
326
+ goto err1;
327
+ }
328
+
329
+ /* Mark the socket as listening. */
330
+ if (listen(s, 10)) {
331
+ warnp("Error marking socket as listening");
332
+ goto err1;
333
+ }
334
+
335
+ /* Mark the socket as non-blocking. */
336
+ if (fcntl(s, F_SETFL, O_NONBLOCK) == -1) {
337
+ warnp("Error marking socket as non-blocking");
338
+ goto err1;
339
+ }
340
+
341
+ /* Success! */
342
+ return (s);
343
+
344
+ err1:
345
+ close(s);
346
+ err0:
347
+ /* Failure! */
348
+ return (-1);
349
+ }
350
+
351
+ /**
352
+ * sock_connect(sas):
353
+ * Iterate through the addresses in ${sas}, attempting to create a socket and
354
+ * connect (blockingly). Once connected, stop iterating, mark the socket as
355
+ * non-blocking, and return it.
356
+ */
357
+ int
358
+ sock_connect(struct sock_addr * const * sas)
359
+ {
360
+ int s = -1;
361
+
362
+ /* Iterate through the addresses provided. */
363
+ for (; sas[0] != NULL; sas++) {
364
+ /* Create a socket. */
365
+ if ((s = socket(sas[0]->ai_family,
366
+ sas[0]->ai_socktype, 0)) == -1)
367
+ continue;
368
+
369
+ /* Attempt to connect. */
370
+ if (connect(s, sas[0]->name, sas[0]->namelen) == 0)
371
+ break;
372
+
373
+ /* Close the socket; this address didn't work. */
374
+ close(s);
375
+ }
376
+
377
+ /* Did we manage to connect? */
378
+ if (sas[0] == NULL) {
379
+ warn0("Could not connect");
380
+ goto err0;
381
+ }
382
+
383
+ /* Mark the socket as non-blocking. */
384
+ if (fcntl(s, F_SETFL, O_NONBLOCK) == -1) {
385
+ warnp("Cannot make connection non-blocking");
386
+ goto err1;
387
+ }
388
+
389
+ /* Success! */
390
+ return (s);
391
+
392
+ err1:
393
+ close(s);
394
+ err0:
395
+ /* Failure! */
396
+ return (-1);
397
+ }
398
+
399
+ /**
400
+ * sock_connect_nb(sa):
401
+ * Create a socket, mark it as non-blocking, and attempt to connect to the
402
+ * address ${sa}. Return the socket (connected or in the process of
403
+ * connecting) or -1 on error.
404
+ */
405
+ int
406
+ sock_connect_nb(const struct sock_addr * sa)
407
+ {
408
+ int s;
409
+
410
+ /* Create a socket. */
411
+ if ((s = socket(sa->ai_family, sa->ai_socktype, 0)) == -1)
412
+ goto err0;
413
+
414
+ /* Mark the socket as non-blocking. */
415
+ if (fcntl(s, F_SETFL, O_NONBLOCK) == -1) {
416
+ warnp("Cannot make socket non-blocking");
417
+ goto err1;
418
+ }
419
+
420
+ /* Attempt to connect. */
421
+ if ((connect(s, sa->name, sa->namelen) == -1) &&
422
+ (errno != EINPROGRESS) &&
423
+ (errno != EINTR))
424
+ goto err1;
425
+
426
+ /* We have a connect(ed|ing) socket. */
427
+ return (s);
428
+
429
+ err1:
430
+ close(s);
431
+ err0:
432
+ /* We failed to connect to this address. */
433
+ return (-1);
434
+ }
435
+
436
+ /**
437
+ * sock_addr_free(sa):
438
+ * Free the provided sock_addr structure.
439
+ */
440
+ void
441
+ sock_addr_free(struct sock_addr * sa)
442
+ {
443
+
444
+ /* Compatibility with free(NULL). */
445
+ if (sa == NULL)
446
+ return;
447
+
448
+ /* Free the protocol-specific address structure and our struct. */
449
+ free(sa->name);
450
+ free(sa);
451
+ }
452
+
453
+ /**
454
+ * sock_addr_freelist(sas):
455
+ * Free the provided NULL-terminated array of sock_addr structures.
456
+ */
457
+ void
458
+ sock_addr_freelist(struct sock_addr ** sas)
459
+ {
460
+ struct sock_addr ** p;
461
+
462
+ /* Compatibility with free(NULL). */
463
+ if (sas == NULL)
464
+ return;
465
+
466
+ /* Free structures until we hit NULL. */
467
+ for (p = sas; *p != NULL; p++)
468
+ sock_addr_free(*p);
469
+
470
+ /* Free the list. */
471
+ free(sas);
472
+ }