gdb - Local mods (compile)
[dragonfly.git] / lib / libdmsg / dmsg.h
CommitLineData
0c3a8cd0
MD
1/*
2 * Copyright (c) 2011-2012 The DragonFly Project. All rights reserved.
3 *
4 * This code is derived from software contributed to The DragonFly Project
5 * by Matthew Dillon <dillon@dragonflybsd.org>
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
16 * distribution.
17 * 3. Neither the name of The DragonFly Project nor the names of its
18 * contributors may be used to endorse or promote products derived
19 * from this software without specific, prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
31 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 */
34
35#include <sys/types.h>
36#include <sys/queue.h>
37#include <sys/tree.h>
38#include <sys/dmsg.h>
39
40#include <pthread.h>
41
42#if 0
43#include <openssl/rsa.h> /* public/private key functions */
44#include <openssl/pem.h> /* public/private key file load */
45#endif
46#include <openssl/err.h>
47#include <openssl/evp.h> /* aes_256_cbc functions */
48
49#define DMSG_DEFAULT_DIR "/etc/hammer2"
50#define DMSG_PATH_REMOTE DMSG_DEFAULT_DIR "/remote"
51
52#define DMSG_LISTEN_PORT 987
53
5ab1caed
MD
54#define dm_printf(level, ctl, ...) \
55 if (DMsgDebugOpt >= (level)) \
56 fprintf(stderr, "libdmsg: " ctl, __VA_ARGS__)
57#define dmx_printf(level, ctl, ...) \
58 if (DMsgDebugOpt >= (level)) \
59 fprintf(stderr, ctl, __VA_ARGS__)
60#define dmio_printf(iocom, level, ctl, ...) \
61 if (DMsgDebugOpt >= (level)) \
62 fprintf(stderr, "libdmsg: " ctl, __VA_ARGS__)
63
64
0c3a8cd0
MD
65/***************************************************************************
66 * CRYPTO HANDSHAKE *
67 ***************************************************************************
68 *
69 * The initial public-key exchange is implementing by transmitting a
70 * 512-byte buffer to the other side in a symmetrical fashion. This
71 * buffer contains the following:
72 *
73 * (1) A random session key. 512 bits is specified. We use aes_256_cbc()
74 * and initialize the key with the first 256 bits and the iv[] with
75 * the second. Note that the transmitted and received session
76 * keys are XOR'd together to create the session key used for
77 * communications (so even if the verifier is compromised the session
78 * will still be gobbly gook if the public key has not been completely
79 * broken).
80 *
81 * (2) A verifier to determine that the decode was successful. It encodes
82 * an XOR of each group of 4 bytes from the session key.
83 *
84 * (3) Additional configuration and additional random data.
85 *
86 * - The hammer2 message header magic for endian detect
87 *
88 * - The hammer2 protocol version. The two sides agree on the
89 * smaller of the two.
90 *
91 * - All unused fields (junk*) are filled with random data.
92 *
93 * This structure must be exactly 512 bytes and expects to use 256-byte
94 * RSA keys.
95 */
96struct dmsg_handshake {
97 char pad1[8]; /* 000 */
98 uint16_t magic; /* 008 DMSG_HDR_MAGIC for endian detect */
99 uint16_t version; /* 00A hammer2 protocol version */
100 uint32_t flags; /* 00C protocol extension flags */
101 uint8_t sess[64]; /* 010 512-bit session key */
102 uint8_t verf[16]; /* 050 verifier = ~sess */
103 char quickmsg[32]; /* 060 reason for connecting */
104 char junk080[128]; /* 080-0FF */
105 char pad2[8]; /* 100-107 */
106 char junk100[256-8]; /* 108-1FF */
107};
108
109typedef struct dmsg_handshake dmsg_handshake_t;
110
111
112#define DMSG_CRYPTO_CHUNK_SIZE DMSG_ALIGN
113#define DMSG_MAX_IV_SIZE 32
114
115#define DMSG_CRYPTO_GCM_IV_FIXED_SIZE 4
116#define DMSG_CRYPTO_GCM_IV_SIZE 12
117#define DMSG_CRYPTO_GCM_KEY_SIZE 32
118#define DMSG_CRYPTO_GCM_TAG_SIZE 16
119
120#define DMSG_CRYPTO_ALGO_GCM_IDX 0
121
122#define DMSG_CRYPTO_ALGO DMSG_CRYPTO_ALGO_GCM_IDX
123
0c3a8cd0
MD
124/***************************************************************************
125 * LOW LEVEL MESSAGING *
126 ***************************************************************************
127 *
128 * dmsg_msg - A standalone copy of a message, typically referenced by
129 * or embedded in other structures, or used with I/O queues.
130 *
131 * These structures are strictly temporary, so they do not have to be
132 * particularly optimized for size. All possible message headers are
133 * directly embedded (any), and the message may contain a reference
134 * to allocated auxillary data. The structure is recycled quite often
135 * by a connection.
0c3a8cd0
MD
136 */
137struct dmsg_iocom;
0c3a8cd0 138struct dmsg_state;
0c3a8cd0
MD
139struct dmsg_msg;
140
141TAILQ_HEAD(dmsg_state_queue, dmsg_state);
142TAILQ_HEAD(dmsg_msg_queue, dmsg_msg);
143RB_HEAD(dmsg_state_tree, dmsg_state);
0c3a8cd0
MD
144
145struct h2span_link;
146struct h2span_relay;
147struct h2span_conn;
148
01e43224
MD
149/*
150 * This represents a media, managed by LNK_CONN connection state
151 */
152TAILQ_HEAD(dmsg_media_queue, dmsg_media);
153
154struct dmsg_media {
155 TAILQ_ENTRY(dmsg_media) entry;
7750fd72 156 uuid_t media_id;
01e43224
MD
157 int refs;
158 void *usrhandle;
159};
160
161typedef struct dmsg_media dmsg_media_t;
162
0d20ec8a
MD
163/*
164 * The state structure is ref-counted. The iocom cannot go away while
165 * state structures are active. However, the related h2span_* linkages
166 * can be destroyed and NULL'd out if the state is terminated in both
167 * directions.
168 */
0c3a8cd0 169struct dmsg_state {
d30cab67 170 RB_ENTRY(dmsg_state) rbnode; /* by state->msgid */
0a9eefca 171 struct dmsg_state *scan; /* scan check */
1b8eded1
MD
172 TAILQ_HEAD(, dmsg_state) subq; /* active stacked states */
173 TAILQ_ENTRY(dmsg_state) entry; /* on parent subq */
0c3a8cd0 174 struct dmsg_iocom *iocom;
1b8eded1 175 struct dmsg_state *parent; /* transaction stacking */
d30cab67 176 struct dmsg_state *relay; /* routing */
0d20ec8a 177 uint32_t icmd; /* command creating state */
0c3a8cd0
MD
178 uint32_t txcmd; /* mostly for CMDF flags */
179 uint32_t rxcmd; /* mostly for CMDF flags */
1b8eded1 180 uint64_t msgid;
0c3a8cd0
MD
181 int flags;
182 int error;
0d20ec8a 183 int refs; /* prevent destruction */
0c3a8cd0
MD
184 void (*func)(struct dmsg_msg *);
185 union {
186 void *any;
187 struct h2span_link *link;
188 struct h2span_conn *conn;
189 struct h2span_relay *relay;
190 } any;
01e43224 191 dmsg_media_t *media;
0c3a8cd0
MD
192};
193
a06d536b 194#define DMSG_STATE_SUBINSERTED 0x0001
0c3a8cd0 195#define DMSG_STATE_DYNAMIC 0x0002
0a9eefca
MD
196#define DMSG_STATE_UNUSED0004 0x0004
197#define DMSG_STATE_ABORTING 0x0008
1b8eded1 198#define DMSG_STATE_OPPOSITE 0x0010 /* initiated by other end */
d30cab67 199#define DMSG_STATE_CIRCUIT 0x0020 /* LNK_SPAN special case */
323c0947 200#define DMSG_STATE_DYING 0x0040 /* indicates circuit failure */
a06d536b 201#define DMSG_STATE_RBINSERTED 0x0080
0a9eefca 202#define DMSG_STATE_NEW 0x0400 /* defer abort processing */
d30cab67 203#define DMSG_STATE_ROOT 0x8000 /* iocom->state0 */
0c3a8cd0 204
0d20ec8a
MD
205/*
206 * This is the core in-memory representation of a message structure.
1b8eded1
MD
207 * state is the local representation of the transactional state and
208 * will point to &iocom->state0 for non-transactional messages.
209 *
210 * Message headers are embedded while auxillary data is separately allocated.
0a9eefca
MD
211 * The 'any' portion of the message is allocated dynamically based on
212 * hdr_size.
0d20ec8a 213 */
0c3a8cd0
MD
214struct dmsg_msg {
215 TAILQ_ENTRY(dmsg_msg) qentry;
0d20ec8a 216 struct dmsg_state *state; /* message state */
0c3a8cd0
MD
217 size_t hdr_size;
218 size_t aux_size;
219 char *aux_data;
8e226bc8 220 uint32_t tcmd; /* easy-switch cmd */
a2179323 221 dmsg_any_t any; /* must be last element */
0c3a8cd0
MD
222};
223
224typedef struct dmsg_state dmsg_state_t;
225typedef struct dmsg_msg dmsg_msg_t;
226typedef struct dmsg_msg_queue dmsg_msg_queue_t;
227
228int dmsg_state_cmp(dmsg_state_t *state1, dmsg_state_t *state2);
229RB_PROTOTYPE(dmsg_state_tree, dmsg_state, rbnode, dmsg_state_cmp);
230
231/*
232 * dmsg_ioq - An embedded component of dmsg_conn, holds state
233 * for the buffering and parsing of incoming and outgoing messages.
234 *
235 * cdx - beg - processed buffer data, encrypted or decrypted
236 * end - cdn - unprocessed buffer data not yet encrypted or decrypted
237 */
238struct dmsg_ioq {
239 enum { DMSG_MSGQ_STATE_HEADER1,
240 DMSG_MSGQ_STATE_HEADER2,
241 DMSG_MSGQ_STATE_AUXDATA1,
242 DMSG_MSGQ_STATE_AUXDATA2,
243 DMSG_MSGQ_STATE_ERROR } state;
244 size_t fifo_beg; /* buffered data */
245 size_t fifo_cdx; /* cdx-beg processed */
246 size_t fifo_cdn; /* end-cdn unprocessed */
247 size_t fifo_end;
248 size_t hbytes; /* header size */
f306de83
MD
249 size_t abytes; /* aligned aux_data size */
250 size_t unaligned_aux_size; /* actual aux_data size */
0c3a8cd0
MD
251 int error;
252 int seq; /* salt sequencer */
253 int msgcount;
254 EVP_CIPHER_CTX ctx;
255 char iv[DMSG_MAX_IV_SIZE]; /* encrypt or decrypt iv[] */
256 dmsg_msg_t *msg;
257 dmsg_msg_queue_t msgq;
258 char buf[DMSG_BUF_SIZE]; /* staging buffer */
259};
260
261typedef struct dmsg_ioq dmsg_ioq_t;
262
263#define DMSG_IOQ_ERROR_SYNC 1 /* bad magic / out of sync */
264#define DMSG_IOQ_ERROR_EOF 2 /* unexpected EOF */
265#define DMSG_IOQ_ERROR_SOCK 3 /* read() error on socket */
266#define DMSG_IOQ_ERROR_FIELD 4 /* invalid field */
267#define DMSG_IOQ_ERROR_HCRC 5 /* core header crc bad */
268#define DMSG_IOQ_ERROR_XCRC 6 /* ext header crc bad */
269#define DMSG_IOQ_ERROR_ACRC 7 /* aux data crc bad */
270#define DMSG_IOQ_ERROR_STATE 8 /* bad state */
271#define DMSG_IOQ_ERROR_NOPEER 9 /* bad socket peer */
272#define DMSG_IOQ_ERROR_NORKEY 10 /* no remote keyfile found */
273#define DMSG_IOQ_ERROR_NOLKEY 11 /* no local keyfile found */
274#define DMSG_IOQ_ERROR_KEYXCHGFAIL 12 /* key exchange failed */
275#define DMSG_IOQ_ERROR_KEYFMT 13 /* key file format problem */
276#define DMSG_IOQ_ERROR_BADURANDOM 14 /* /dev/urandom is bad */
277#define DMSG_IOQ_ERROR_MSGSEQ 15 /* message sequence error */
278#define DMSG_IOQ_ERROR_EALREADY 16 /* ignore this message */
279#define DMSG_IOQ_ERROR_TRANS 17 /* state transaction issue */
280#define DMSG_IOQ_ERROR_IVWRAP 18 /* IVs exhaused */
281#define DMSG_IOQ_ERROR_MACFAIL 19 /* MAC of encr alg failed */
282#define DMSG_IOQ_ERROR_ALGO 20 /* Misc. encr alg error */
d30cab67 283#define DMSG_IOQ_ERROR_UNUSED21 21
0d20ec8a
MD
284#define DMSG_IOQ_ERROR_BAD_CIRCUIT 22 /* unconfigured circuit */
285#define DMSG_IOQ_ERROR_UNUSED23 23
286#define DMSG_IOQ_ERROR_ASSYM 24 /* Assymetric path */
0c3a8cd0
MD
287
288#define DMSG_IOQ_MAXIOVEC 16
289
0c3a8cd0
MD
290/*
291 * dmsg_iocom - governs a messaging stream connection
292 */
293struct dmsg_iocom {
f306de83 294 char *label; /* label for error reporting */
0c3a8cd0
MD
295 dmsg_ioq_t ioq_rx;
296 dmsg_ioq_t ioq_tx;
1b8eded1
MD
297 dmsg_state_t state0; /* root state for stacking */
298 struct dmsg_state_tree staterd_tree; /* active transactions */
299 struct dmsg_state_tree statewr_tree; /* active transactions */
0c3a8cd0
MD
300 int sock_fd; /* comm socket or pipe */
301 int alt_fd; /* thread signal, tty, etc */
302 int wakeupfds[2]; /* pipe wakes up iocom thread */
303 int flags;
304 int rxmisc;
305 int txmisc;
0d20ec8a 306 void (*signal_callback)(struct dmsg_iocom *);
0d20ec8a 307 void (*altmsg_callback)(struct dmsg_iocom *);
01e43224
MD
308 void (*rcvmsg_callback)(dmsg_msg_t *msg);
309 void (*usrmsg_callback)(dmsg_msg_t *msg, int unmanaged);
0d20ec8a
MD
310 dmsg_msg_queue_t txmsgq; /* tx msgq from remote */
311 struct h2span_conn *conn; /* if LNK_CONN active */
1b8eded1
MD
312 uint64_t conn_msgid; /* LNK_CONN circuit */
313 pthread_mutex_t mtx; /* mutex for state*tree/rmsgq */
0c3a8cd0
MD
314};
315
316typedef struct dmsg_iocom dmsg_iocom_t;
317
318#define DMSG_IOCOMF_EOF 0x00000001 /* EOF or ERROR on desc */
319#define DMSG_IOCOMF_RREQ 0x00000002 /* request read-data event */
320#define DMSG_IOCOMF_WREQ 0x00000004 /* request write-avail event */
321#define DMSG_IOCOMF_RWORK 0x00000008 /* immediate work pending */
322#define DMSG_IOCOMF_WWORK 0x00000010 /* immediate work pending */
323#define DMSG_IOCOMF_PWORK 0x00000020 /* immediate work pending */
324#define DMSG_IOCOMF_ARWORK 0x00000040 /* immediate work pending */
325#define DMSG_IOCOMF_AWWORK 0x00000080 /* immediate work pending */
326#define DMSG_IOCOMF_SWORK 0x00000100 /* immediate work pending */
327#define DMSG_IOCOMF_CRYPTED 0x00000200 /* encrypt enabled */
98126869 328#define DMSG_IOCOMF_CLOSEALT 0x00000400 /* close alt_fd */
0c3a8cd0
MD
329
330/*
331 * Crypto algorithm table and related typedefs.
332 */
0c3a8cd0
MD
333typedef int (*algo_init_fn)(dmsg_ioq_t *, char *, int, char *, int, int);
334typedef int (*algo_enc_fn)(dmsg_ioq_t *, char *, char *, int, int *);
335typedef int (*algo_dec_fn)(dmsg_ioq_t *, char *, char *, int, int *);
336
337struct crypto_algo {
338 const char *name;
339 int keylen;
340 int taglen;
341 algo_init_fn init;
342 algo_enc_fn enc_chunk;
343 algo_dec_fn dec_chunk;
344};
345
11f7caf4
MD
346/*
347 * Master service thread info
348 */
349struct dmsg_master_service_info {
350 int fd;
2892d211 351 int altfd;
98126869 352 int noclosealt;
11f7caf4 353 int detachme;
f306de83 354 char *label;
185ace93 355 void *handle;
01e43224
MD
356 void (*altmsg_callback)(dmsg_iocom_t *iocom);
357 void (*usrmsg_callback)(dmsg_msg_t *msg, int unmanaged);
185ace93 358 void (*exit_callback)(void *handle);
11f7caf4
MD
359};
360
361typedef struct dmsg_master_service_info dmsg_master_service_info_t;
362
0d20ec8a
MD
363/*
364 * node callbacks
365 */
366#define DMSG_NODEOP_ADD 1
367#define DMSG_NODEOP_DEL 2
368
0c3a8cd0
MD
369/*
370 * icrc
371 */
372uint32_t dmsg_icrc32(const void *buf, size_t size);
373uint32_t dmsg_icrc32c(const void *buf, size_t size, uint32_t crc);
374
375/*
376 * debug
377 */
378const char *dmsg_basecmd_str(uint32_t cmd);
379const char *dmsg_msg_str(dmsg_msg_t *msg);
380
381/*
382 * subs
383 */
384void *dmsg_alloc(size_t bytes);
385void dmsg_free(void *ptr);
386const char *dmsg_uuid_to_str(uuid_t *uuid, char **strp);
0d20ec8a 387const char *dmsg_peer_type_to_str(uint8_t type);
0c3a8cd0
MD
388int dmsg_connect(const char *hostname);
389
390/*
391 * Msg support functions
392 */
393void dmsg_bswap_head(dmsg_hdr_t *head);
394void dmsg_ioq_init(dmsg_iocom_t *iocom, dmsg_ioq_t *ioq);
395void dmsg_ioq_done(dmsg_iocom_t *iocom, dmsg_ioq_t *ioq);
396void dmsg_iocom_init(dmsg_iocom_t *iocom, int sock_fd, int alt_fd,
01e43224
MD
397 void (*state_func)(dmsg_iocom_t *iocom),
398 void (*rcvmsg_func)(dmsg_msg_t *msg),
399 void (*usrmsg_func)(dmsg_msg_t *msg, int unmanaged),
400 void (*altmsg_func)(dmsg_iocom_t *iocom));
0d20ec8a 401void dmsg_iocom_restate(dmsg_iocom_t *iocom,
01e43224
MD
402 void (*state_func)(dmsg_iocom_t *iocom),
403 void (*rcvmsg_func)(dmsg_msg_t *msg));
f306de83 404void dmsg_iocom_label(dmsg_iocom_t *iocom, const char *ctl, ...);
0d20ec8a 405void dmsg_iocom_signal(dmsg_iocom_t *iocom);
0c3a8cd0 406void dmsg_iocom_done(dmsg_iocom_t *iocom);
323c0947
MD
407dmsg_msg_t *dmsg_msg_alloc(dmsg_state_t *state, size_t aux_size,
408 uint32_t cmd,
409 void (*func)(dmsg_msg_t *), void *data);
410dmsg_msg_t *dmsg_msg_alloc_locked(dmsg_state_t *state, size_t aux_size,
411 uint32_t cmd,
0c3a8cd0
MD
412 void (*func)(dmsg_msg_t *), void *data);
413void dmsg_msg_reply(dmsg_msg_t *msg, uint32_t error);
414void dmsg_msg_result(dmsg_msg_t *msg, uint32_t error);
415void dmsg_state_reply(dmsg_state_t *state, uint32_t error);
0d20ec8a 416void dmsg_state_result(dmsg_state_t *state, uint32_t error);
0c3a8cd0
MD
417
418void dmsg_msg_free(dmsg_msg_t *msg);
419
420void dmsg_iocom_core(dmsg_iocom_t *iocom);
421dmsg_msg_t *dmsg_ioq_read(dmsg_iocom_t *iocom);
422void dmsg_msg_write(dmsg_msg_t *msg);
423
424void dmsg_iocom_drain(dmsg_iocom_t *iocom);
425void dmsg_iocom_flush1(dmsg_iocom_t *iocom);
426void dmsg_iocom_flush2(dmsg_iocom_t *iocom);
427
d30cab67 428void dmsg_state_relay(dmsg_msg_t *msg);
0c3a8cd0 429void dmsg_state_cleanuprx(dmsg_iocom_t *iocom, dmsg_msg_t *msg);
323c0947
MD
430void dmsg_state_hold(dmsg_state_t *state);
431void dmsg_state_drop(dmsg_state_t *state);
0c3a8cd0
MD
432
433/*
434 * Msg protocol functions
435 */
0d20ec8a 436void dmsg_msg_lnk_signal(dmsg_iocom_t *iocom);
0c3a8cd0
MD
437void dmsg_msg_lnk(dmsg_msg_t *msg);
438void dmsg_msg_dbg(dmsg_msg_t *msg);
1b8eded1 439void dmsg_shell_tree(dmsg_iocom_t *iocom, char *cmdbuf __unused);
a2179323 440int dmsg_debug_findspan(uint64_t msgid, dmsg_state_t **statep);
1b8eded1 441dmsg_state_t *dmsg_findspan(const char *label);
a2179323 442
0c3a8cd0
MD
443
444/*
445 * Crypto functions
446 */
447void dmsg_crypto_setup(void);
448void dmsg_crypto_negotiate(dmsg_iocom_t *iocom);
449void dmsg_crypto_decrypt(dmsg_iocom_t *iocom, dmsg_ioq_t *ioq);
450int dmsg_crypto_encrypt(dmsg_iocom_t *iocom, dmsg_ioq_t *ioq,
451 struct iovec *iov, int n, size_t *nactp);
452
453/*
454 * Service daemon functions
455 */
456void *dmsg_master_service(void *data);
1b8eded1 457void dmsg_printf(dmsg_iocom_t *iocom, const char *ctl, ...) __printflike(2, 3);
0c3a8cd0
MD
458
459extern int DMsgDebugOpt;