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,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
+ }