spiped 0.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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,98 @@
1
+ # Program name.
2
+ PROG = spiped
3
+ MAN1 = ${PROG}.1
4
+
5
+ # Libraries which are sometimes merged into libc
6
+ LDADD = -lrt
7
+ #LDADD += -lxnet # Missing on FreeBSD
8
+
9
+ # Library code required
10
+ LDADD_REQ = -lcrypto
11
+ LDADD_REQ += -lpthread
12
+
13
+ # spiped code
14
+ SRCS = main.c
15
+ SRCS += dispatch.c
16
+
17
+ # spipe protocol
18
+ .PATH.c : ../proto
19
+ SRCS += proto_conn.c
20
+ SRCS += proto_crypt.c
21
+ SRCS += proto_handshake.c
22
+ SRCS += proto_pipe.c
23
+ IDIRS += -I ../proto
24
+
25
+ # Fundamental algorithms
26
+ .PATH.c : ../libcperciva/alg
27
+ SRCS += sha256.c
28
+ IDIRS += -I ../libcperciva/alg
29
+
30
+ # Data structures
31
+ .PATH.c : ../libcperciva/datastruct
32
+ SRCS += elasticarray.c
33
+ SRCS += ptrheap.c
34
+ SRCS += timerqueue.c
35
+ IDIRS += -I ../libcperciva/datastruct
36
+
37
+ # DNS resolution
38
+ .PATH.c : ../lib/dnsthread
39
+ SRCS += dnsthread.c
40
+ IDIRS += -I ../lib/dnsthread
41
+
42
+ # Utility functions
43
+ .PATH.c : ../libcperciva/util
44
+ SRCS += asprintf.c
45
+ SRCS += daemonize.c
46
+ SRCS += entropy.c
47
+ SRCS += insecure_memzero.c
48
+ SRCS += monoclock.c
49
+ SRCS += noeintr.c
50
+ SRCS += sock.c
51
+ SRCS += sock_util.c
52
+ SRCS += warnp.c
53
+ IDIRS += -I ../libcperciva/util
54
+
55
+ # CPU features detection
56
+ .PATH.c : ../libcperciva/cpusupport
57
+ SRCS += cpusupport_x86_aesni.c
58
+ IDIRS += -I ../libcperciva/cpusupport
59
+
60
+ # Event loop
61
+ .PATH.c : ../libcperciva/events
62
+ SRCS += events_immediate.c
63
+ SRCS += events_network.c
64
+ SRCS += events_network_selectstats.c
65
+ SRCS += events_timer.c
66
+ SRCS += events.c
67
+ IDIRS += -I ../libcperciva/events
68
+
69
+ # Event-driven networking
70
+ .PATH.c : ../libcperciva/network
71
+ SRCS += network_accept.c
72
+ SRCS += network_connect.c
73
+ SRCS += network_read.c
74
+ SRCS += network_write.c
75
+ IDIRS += -I ../libcperciva/network
76
+
77
+ # Crypto code
78
+ .PATH.c : ../libcperciva/crypto
79
+ SRCS += crypto_aes.c
80
+ SRCS += crypto_aes_aesni.c
81
+ SRCS += crypto_aesctr.c
82
+ SRCS += crypto_dh.c
83
+ SRCS += crypto_dh_group14.c
84
+ SRCS += crypto_entropy.c
85
+ SRCS += crypto_verify_bytes.c
86
+ IDIRS += -I ../libcperciva/crypto
87
+
88
+ crypto_aes_aesni.o: crypto_aes_aesni.c cpusupport-config.h
89
+ . ./cpusupport-config.h; ${CC} ${CFLAGS} $${CFLAGS_X86_AESNI} -c $< -o $@
90
+ cflags-crypto_aes_aesni.o=$${CFLAGS_X86_AESNI}
91
+
92
+ # Debugging options
93
+ CFLAGS += -g
94
+ #CFLAGS += -DNDEBUG
95
+ #CFLAGS += -DDEBUG
96
+ #CFLAGS += -pg
97
+
98
+ .include <bsd.prog.mk>
@@ -0,0 +1,62 @@
1
+ spiped usage
2
+ ============
3
+
4
+ usage: spiped {-e | -d} -s <source socket> -t <target socket> -k <key file>
5
+ [-DFj] [-f | -g] [-n <max # connections>] [-o <connection timeout>]
6
+ [-p <pidfile>] [-r <rtime> | -R]
7
+
8
+ Options:
9
+ -e
10
+ Take unencrypted connections from the source socket and send
11
+ encrypted connections to the target socket.
12
+ -d
13
+ Take encrypted connections from the source socket and send
14
+ unencrypted connections to the target socket.
15
+ -s <source socket>
16
+ Address on which spiped should listen for incoming connections.
17
+ Must be in one of the following formats:
18
+ /absolute/path/to/unix/socket
19
+ host.name:port
20
+ [ip.v4.ad.dr]:port
21
+ [ipv6::addr]:port
22
+ Note that hostnames are resolved when spiped is launched and are not
23
+ re-resolved later; thus if DNS entries change spiped will continue to
24
+ connect to the expired address.
25
+ -t <target socket>
26
+ Address to which spiped should connect.
27
+ -k <key file>
28
+ Use the provided key file to authenticate and encrypt.
29
+ -D
30
+ Wait for DNS. Normally when spiped is launched it resolves addresses
31
+ and binds to its source socket before the parent process returns; with
32
+ this option it will daemonize first and retry failed DNS lookups until
33
+ they succeed. This allows spiped to launch even if DNS isn't set up
34
+ yet, but at the expense of losing the guarantee that once spiped has
35
+ finished launching it will be ready to create pipes.
36
+ -f
37
+ Use fast/weak handshaking: This reduces the CPU time spent in the
38
+ initial connection setup, at the expense of losing perfect forward
39
+ secrecy.
40
+ -g
41
+ Require perfect forward secrecy by dropping connections if the other
42
+ host is using the -f option.
43
+ -F
44
+ Run in foreground. This can be useful with systems like daemontools.
45
+ -j
46
+ Disable transport layer keep-alives. (By default they are enabled.)
47
+ -n <max # connections>
48
+ Limit on the number of simultaneous connections allowed. Defaults
49
+ to 100 connections.
50
+ -o <connection timeout>
51
+ Timeout, in seconds, after which an attempt to connect to the target
52
+ or a protocol handshake will be aborted (and the connection dropped)
53
+ if not completed. Defaults to 5s.
54
+ -p <pidfile>
55
+ File to which spiped's process ID should be written. Defaults to
56
+ <source socket>.pid (in the current directory if <source socket> is
57
+ not an absolute path).
58
+ -r <rtime>
59
+ Re-resolve the address of <target socket> every <rtime> seconds.
60
+ Defaults to re-resolution every 60 seconds.
61
+ -R
62
+ Do not re-resolve the address of <target socket>.
@@ -0,0 +1,214 @@
1
+ #include <stdint.h>
2
+ #include <stdlib.h>
3
+ #include <string.h>
4
+
5
+ #include "dnsthread.h"
6
+ #include "events.h"
7
+ #include "network.h"
8
+ #include "sock.h"
9
+ #include "sock_util.h"
10
+ #include "warnp.h"
11
+
12
+ #include "proto_conn.h"
13
+
14
+ #include "dispatch.h"
15
+
16
+ struct accept_state {
17
+ int s;
18
+ const char * tgt;
19
+ struct sock_addr ** sas;
20
+ double rtime;
21
+ int decr;
22
+ int nofps;
23
+ int requirefps;
24
+ int nokeepalive;
25
+ const struct proto_secret * K;
26
+ size_t nconn;
27
+ size_t nconn_max;
28
+ double timeo;
29
+ void * accept_cookie;
30
+ DNSTHREAD T;
31
+ };
32
+
33
+ static int callback_gotconn(void *, int);
34
+ static int callback_resolveagain(void *);
35
+
36
+ /* Callback from address resolution. */
37
+ static int
38
+ callback_resolve(void * cookie, struct sock_addr ** sas)
39
+ {
40
+ struct accept_state * A = cookie;
41
+
42
+ /* If the address resolution succeeded... */
43
+ if (sas != NULL) {
44
+ /* Free the old addresses. */
45
+ sock_addr_freelist(A->sas);
46
+
47
+ /* Use the new addresses. */
48
+ A->sas = sas;
49
+ }
50
+
51
+ /* Wait a while before resolving again. */
52
+ if (events_timer_register_double(callback_resolveagain,
53
+ A, A->rtime) == NULL)
54
+ goto err0;
55
+
56
+ /* Success! */
57
+ return (0);
58
+
59
+ err0:
60
+ /* Failure! */
61
+ return (-1);
62
+ }
63
+
64
+ /* Timer callback to trigger another address resolution. */
65
+ static int
66
+ callback_resolveagain(void * cookie)
67
+ {
68
+ struct accept_state * A = cookie;
69
+
70
+ /* Re-resolve the target address. */
71
+ return (dnsthread_resolveone(A->T, A->tgt, callback_resolve, A));
72
+ }
73
+
74
+ /* Non-blocking accept, if we can have more connections. */
75
+ static int
76
+ doaccept(struct accept_state * A)
77
+ {
78
+ int rc = 0;
79
+
80
+ /* If we can, accept a new connection. */
81
+ if ((A->nconn < A->nconn_max) && (A->accept_cookie == NULL)) {
82
+ if ((A->accept_cookie =
83
+ network_accept(A->s, callback_gotconn, A)) == NULL)
84
+ rc = -1;
85
+ }
86
+
87
+ /* Return success/fail status. */
88
+ return (rc);
89
+ }
90
+
91
+ /* A connection has closed. Accept more if necessary. */
92
+ static int
93
+ callback_conndied(void * cookie)
94
+ {
95
+ struct accept_state * A = cookie;
96
+
97
+ /* We've lost a connection. */
98
+ A->nconn -= 1;
99
+
100
+ /* Maybe accept more connections. */
101
+ return (doaccept(A));
102
+ }
103
+
104
+ /* Handle an incoming connection. */
105
+ static int
106
+ callback_gotconn(void * cookie, int s)
107
+ {
108
+ struct accept_state * A = cookie;
109
+ struct sock_addr ** sas;
110
+
111
+ /* This accept is no longer in progress. */
112
+ A->accept_cookie = NULL;
113
+
114
+ /* If we got a -1 descriptor, something went seriously wrong. */
115
+ if (s == -1) {
116
+ warnp("network_accept failed");
117
+ goto err0;
118
+ }
119
+
120
+ /* We have gained a connection. */
121
+ A->nconn += 1;
122
+
123
+ /* Duplicate the target address list. */
124
+ if ((sas = sock_addr_duplist(A->sas)) == NULL)
125
+ goto err1;
126
+
127
+ /* Create a new connection. */
128
+ if (proto_conn_create(s, sas, A->decr, A->nofps, A->requirefps,
129
+ A->nokeepalive, A->K, A->timeo, callback_conndied, A)) {
130
+ warnp("Failure setting up new connection");
131
+ goto err2;
132
+ }
133
+
134
+ /* Accept another connection if we can. */
135
+ if (doaccept(A))
136
+ goto err0;
137
+
138
+ /* Success! */
139
+ return (0);
140
+
141
+ err2:
142
+ sock_addr_freelist(sas);
143
+ err1:
144
+ A->nconn -= 1;
145
+ close(s);
146
+ err0:
147
+ /* Failure! */
148
+ return (-1);
149
+ }
150
+
151
+ /**
152
+ * dispatch_accept(s, tgt, rtime, sas, decr, nofps, requirefps, nokeepalive, K,
153
+ * nconn_max, timeo):
154
+ * Start accepting connections on the socket ${s}. Connect to the target
155
+ * ${tgt}, re-resolving it every ${rtime} seconds if ${rtime} > 0; on address
156
+ * resolution failure use the most recent successfully obtained addresses, or
157
+ * the addresses ${sas}. If ${decr} is 0, encrypt the outgoing connections; if
158
+ * ${decr} is non-zero, decrypt the incoming connections. Don't accept more
159
+ * than ${nconn_max} connections. If ${nofps} is non-zero, don't use perfect
160
+ * forward secrecy. If {$requirefps} is non-zero, require that both ends use
161
+ * perfect forward secrecy. Enable transport layer keep-alives (if applicable)
162
+ * if and only if ${nokeepalive} is zero. Drop connections if the handshake or
163
+ * connecting to the target takes more than ${timeo} seconds.
164
+ */
165
+ int
166
+ dispatch_accept(int s, const char * tgt, double rtime, struct sock_addr ** sas,
167
+ int decr, int nofps, int requirefps, int nokeepalive,
168
+ const struct proto_secret * K, size_t nconn_max, double timeo)
169
+ {
170
+ struct accept_state * A;
171
+
172
+ /* Bake a cookie. */
173
+ if ((A = malloc(sizeof(struct accept_state))) == NULL)
174
+ goto err0;
175
+ A->s = s;
176
+ A->tgt = tgt;
177
+ A->sas = sas;
178
+ A->rtime = rtime;
179
+ A->decr = decr;
180
+ A->nofps = nofps;
181
+ A->requirefps = requirefps;
182
+ A->nokeepalive = nokeepalive;
183
+ A->K = K;
184
+ A->nconn = 0;
185
+ A->nconn_max = nconn_max;
186
+ A->timeo = timeo;
187
+ A->accept_cookie = NULL;
188
+
189
+ /* If address re-resolution is enabled... */
190
+ if (rtime > 0.0) {
191
+ /* Launch an address resolution thread. */
192
+ A->T = dnsthread_spawn();
193
+
194
+ /* Re-resolve the target address after a while. */
195
+ if (events_timer_register_double(callback_resolveagain,
196
+ A, A->rtime) == NULL)
197
+ goto err1;
198
+ }
199
+
200
+ /* Accept a connection. */
201
+ if (doaccept(A))
202
+ goto err1;
203
+
204
+ /* Success! */
205
+ return (0);
206
+
207
+ err1:
208
+ if (rtime > 0.0)
209
+ dnsthread_kill(A->T);
210
+ free(A);
211
+ err0:
212
+ /* Failure! */
213
+ return (-1);
214
+ }
@@ -0,0 +1,27 @@
1
+ #ifndef _DISPATCH_H_
2
+ #define _DISPATCH_H_
3
+
4
+ #include <stdint.h>
5
+
6
+ /* Opaque structures. */
7
+ struct proto_secret;
8
+ struct sock_addr;
9
+
10
+ /**
11
+ * dispatch_accept(s, tgt, rtime, sas, decr, nofps, requirefps, nokeepalive, K,
12
+ * nconn_max, timeo):
13
+ * Start accepting connections on the socket ${s}. Connect to the target
14
+ * ${tgt}, re-resolving it every ${rtime} seconds if ${rtime} > 0; on address
15
+ * resolution failure use the most recent successfully obtained addresses, or
16
+ * the addresses ${sas}. If ${decr} is 0, encrypt the outgoing connections; if
17
+ * ${decr} is non-zero, decrypt the incoming connections. Don't accept more
18
+ * than ${nconn_max} connections. If ${nofps} is non-zero, don't use perfect
19
+ * forward secrecy. If {$requirefps} is non-zero, require that both ends use
20
+ * perfect forward secrecy. Enable transport layer keep-alives (if applicable)
21
+ * if and only if ${nokeepalive} is zero. Drop connections if the handshake or
22
+ * connecting to the target takes more than ${timeo} seconds.
23
+ */
24
+ int dispatch_accept(int, const char *, double, struct sock_addr **, int, int,
25
+ int, int, const struct proto_secret *, size_t, double);
26
+
27
+ #endif /* !_DISPATCH_H_ */
@@ -0,0 +1,267 @@
1
+ #include <inttypes.h>
2
+ #include <stdio.h>
3
+ #include <stdlib.h>
4
+ #include <string.h>
5
+ #include <unistd.h>
6
+
7
+ #include "asprintf.h"
8
+ #include "daemonize.h"
9
+ #include "events.h"
10
+ #include "sock.h"
11
+ #include "warnp.h"
12
+
13
+ #include "dispatch.h"
14
+ #include "proto_crypt.h"
15
+
16
+ static void
17
+ usage(void)
18
+ {
19
+
20
+ fprintf(stderr, "usage: spiped {-e | -d} -s <source socket> "
21
+ "-t <target socket> -k <key file>\n"
22
+ " [-DFj] [-f | -g] [-n <max # connections>] "
23
+ "[-o <connection timeout>]\n"
24
+ " [-p <pidfile>] [-r <rtime> | -R]\n");
25
+ exit(1);
26
+ }
27
+
28
+ /* Simplify error-handling in command-line parse loop. */
29
+ #define OPT_EPARSE(opt, arg) do { \
30
+ warnp("Error parsing argument: -%c %s", opt, arg); \
31
+ exit(1); \
32
+ } while (0)
33
+
34
+ int
35
+ main(int argc, char * argv[])
36
+ {
37
+ /* Command-line parameters. */
38
+ int opt_d = 0;
39
+ int opt_D = 0;
40
+ int opt_e = 0;
41
+ int opt_f = 0;
42
+ int opt_g = 0;
43
+ int opt_F = 0;
44
+ int opt_j = 0;
45
+ const char * opt_k = NULL;
46
+ intmax_t opt_n = 0;
47
+ double opt_o = 0.0;
48
+ char * opt_p = NULL;
49
+ double opt_r = 0.0;
50
+ int opt_R = 0;
51
+ const char * opt_s = NULL;
52
+ const char * opt_t = NULL;
53
+
54
+ /* Working variables. */
55
+ struct sock_addr ** sas_s;
56
+ struct sock_addr ** sas_t;
57
+ struct proto_secret * K;
58
+ int ch;
59
+ int s;
60
+
61
+ WARNP_INIT;
62
+
63
+ /* Parse the command line. */
64
+ while ((ch = getopt(argc, argv, "dDefFgjk:n:o:r:Rp:s:t:")) != -1) {
65
+ switch (ch) {
66
+ case 'd':
67
+ if (opt_d || opt_e)
68
+ usage();
69
+ opt_d = 1;
70
+ break;
71
+ case 'D':
72
+ if (opt_D)
73
+ usage();
74
+ opt_D = 1;
75
+ break;
76
+ case 'e':
77
+ if (opt_d || opt_e)
78
+ usage();
79
+ opt_e = 1;
80
+ break;
81
+ case 'f':
82
+ if (opt_f)
83
+ usage();
84
+ opt_f = 1;
85
+ break;
86
+ case 'F':
87
+ if (opt_F)
88
+ usage();
89
+ opt_F = 1;
90
+ break;
91
+ case 'g':
92
+ if (opt_g)
93
+ usage();
94
+ opt_g = 1;
95
+ break;
96
+ case 'j':
97
+ if (opt_j)
98
+ usage();
99
+ opt_j = 1;
100
+ break;
101
+ case 'k':
102
+ if (opt_k)
103
+ usage();
104
+ opt_k = optarg;
105
+ break;
106
+ case 'n':
107
+ if (opt_n != 0)
108
+ usage();
109
+ if ((opt_n = strtoimax(optarg, NULL, 0)) == 0) {
110
+ warn0("Invalid option: -n %s", optarg);
111
+ exit(1);
112
+ }
113
+ if ((opt_n <= 0) || (opt_n > 500)) {
114
+ warn0("The parameter to -n must be between 1 and 500\n");
115
+ exit(1);
116
+ }
117
+ break;
118
+ case 'o':
119
+ if (opt_o != 0.0)
120
+ usage();
121
+ if ((opt_o = strtod(optarg, NULL)) == 0.0) {
122
+ warn0("Invalid option: -o %s", optarg);
123
+ exit(1);
124
+ }
125
+ break;
126
+ case 'p':
127
+ if (opt_p)
128
+ usage();
129
+ if ((opt_p = strdup(optarg)) == NULL)
130
+ OPT_EPARSE(ch, optarg);
131
+ break;
132
+ case 'r':
133
+ if (opt_r != 0.0)
134
+ usage();
135
+ if ((opt_r = strtod(optarg, NULL)) == 0.0) {
136
+ warn0("Invalid option: -r %s", optarg);
137
+ exit(1);
138
+ }
139
+ break;
140
+ case 'R':
141
+ if (opt_R)
142
+ usage();
143
+ opt_R = 1;
144
+ break;
145
+ case 's':
146
+ if (opt_s)
147
+ usage();
148
+ opt_s = optarg;
149
+ break;
150
+ case 't':
151
+ if (opt_t)
152
+ usage();
153
+ opt_t = optarg;
154
+ break;
155
+ default:
156
+ usage();
157
+ }
158
+ }
159
+
160
+ /* We should have processed all the arguments. */
161
+ if (argc != optind)
162
+ usage();
163
+
164
+ /* Set defaults. */
165
+ if (opt_n == 0)
166
+ opt_n = 100;
167
+ if (opt_o == 0.0)
168
+ opt_o = 5.0;
169
+ if (opt_r == 0.0)
170
+ opt_r = 60.0;
171
+
172
+ /* Sanity-check options. */
173
+ if (!opt_d && !opt_e)
174
+ usage();
175
+ if (opt_f && opt_g)
176
+ usage();
177
+ if (opt_k == NULL)
178
+ usage();
179
+ if (!(opt_o > 0.0))
180
+ usage();
181
+ if ((opt_r != 60.0) && opt_R)
182
+ usage();
183
+ if (opt_s == NULL)
184
+ usage();
185
+ if (opt_t == NULL)
186
+ usage();
187
+
188
+ /* Figure out where our pid should be written. */
189
+ if (opt_p == NULL) {
190
+ if (asprintf(&opt_p, "%s.pid", opt_s) == -1) {
191
+ warnp("asprintf");
192
+ exit(1);
193
+ }
194
+ }
195
+
196
+ /* Daemonize early if we're going to wait for DNS to be ready. */
197
+ if (opt_D && !opt_F && daemonize(opt_p)) {
198
+ warnp("Failed to daemonize");
199
+ exit(1);
200
+ }
201
+
202
+ /* Resolve source address. */
203
+ while ((sas_s = sock_resolve(opt_s)) == NULL) {
204
+ if (!opt_D) {
205
+ warnp("Error resolving socket address: %s", opt_s);
206
+ exit(1);
207
+ }
208
+ sleep(1);
209
+ }
210
+ if (sas_s[0] == NULL) {
211
+ warn0("No addresses found for %s", opt_s);
212
+ exit(1);
213
+ }
214
+
215
+ /* Resolve target address. */
216
+ while ((sas_t = sock_resolve(opt_t)) == NULL) {
217
+ if (!opt_D) {
218
+ warnp("Error resolving socket address: %s", opt_t);
219
+ exit(1);
220
+ }
221
+ sleep(1);
222
+ }
223
+ if (sas_t[0] == NULL) {
224
+ warn0("No addresses found for %s", opt_t);
225
+ exit(1);
226
+ }
227
+
228
+ /* Load the keying data. */
229
+ if ((K = proto_crypt_secret(opt_k)) == NULL) {
230
+ warnp("Error reading shared secret");
231
+ exit(1);
232
+ }
233
+
234
+ /* Create and bind a socket, and mark it as listening. */
235
+ if (sas_s[1] != NULL)
236
+ warn0("Listening on first of multiple addresses found for %s",
237
+ opt_s);
238
+ if ((s = sock_listener(sas_s[0])) == -1)
239
+ exit(1);
240
+
241
+ /* Daemonize and write pid. */
242
+ if (!opt_F && daemonize(opt_p)) {
243
+ warnp("Failed to daemonize");
244
+ exit(1);
245
+ }
246
+
247
+ /* Start accepting connections. */
248
+ if (dispatch_accept(s, opt_t, opt_R ? 0.0 : opt_r, sas_t, opt_d,
249
+ opt_f, opt_g, opt_j, K, opt_n, opt_o)) {
250
+ warnp("Failed to initialize connection acceptor");
251
+ exit(1);
252
+ }
253
+
254
+ /* Infinite loop handling events. */
255
+ do {
256
+ if (events_run()) {
257
+ warnp("Error running event loop");
258
+ exit(1);
259
+ }
260
+ } while (1);
261
+
262
+ /* NOTREACHED */
263
+ /*
264
+ * If we could reach this point, we would free memory, close sockets,
265
+ * and otherwise clean up here.
266
+ */
267
+ }