Mark some functions in userland __printflike.
[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
54/***************************************************************************
55 * CRYPTO HANDSHAKE *
56 ***************************************************************************
57 *
58 * The initial public-key exchange is implementing by transmitting a
59 * 512-byte buffer to the other side in a symmetrical fashion. This
60 * buffer contains the following:
61 *
62 * (1) A random session key. 512 bits is specified. We use aes_256_cbc()
63 * and initialize the key with the first 256 bits and the iv[] with
64 * the second. Note that the transmitted and received session
65 * keys are XOR'd together to create the session key used for
66 * communications (so even if the verifier is compromised the session
67 * will still be gobbly gook if the public key has not been completely
68 * broken).
69 *
70 * (2) A verifier to determine that the decode was successful. It encodes
71 * an XOR of each group of 4 bytes from the session key.
72 *
73 * (3) Additional configuration and additional random data.
74 *
75 * - The hammer2 message header magic for endian detect
76 *
77 * - The hammer2 protocol version. The two sides agree on the
78 * smaller of the two.
79 *
80 * - All unused fields (junk*) are filled with random data.
81 *
82 * This structure must be exactly 512 bytes and expects to use 256-byte
83 * RSA keys.
84 */
85struct dmsg_handshake {
86 char pad1[8]; /* 000 */
87 uint16_t magic; /* 008 DMSG_HDR_MAGIC for endian detect */
88 uint16_t version; /* 00A hammer2 protocol version */
89 uint32_t flags; /* 00C protocol extension flags */
90 uint8_t sess[64]; /* 010 512-bit session key */
91 uint8_t verf[16]; /* 050 verifier = ~sess */
92 char quickmsg[32]; /* 060 reason for connecting */
93 char junk080[128]; /* 080-0FF */
94 char pad2[8]; /* 100-107 */
95 char junk100[256-8]; /* 108-1FF */
96};
97
98typedef struct dmsg_handshake dmsg_handshake_t;
99
100
101#define DMSG_CRYPTO_CHUNK_SIZE DMSG_ALIGN
102#define DMSG_MAX_IV_SIZE 32
103
104#define DMSG_CRYPTO_GCM_IV_FIXED_SIZE 4
105#define DMSG_CRYPTO_GCM_IV_SIZE 12
106#define DMSG_CRYPTO_GCM_KEY_SIZE 32
107#define DMSG_CRYPTO_GCM_TAG_SIZE 16
108
109#define DMSG_CRYPTO_ALGO_GCM_IDX 0
110
111#define DMSG_CRYPTO_ALGO DMSG_CRYPTO_ALGO_GCM_IDX
112
0c3a8cd0
MD
113/***************************************************************************
114 * LOW LEVEL MESSAGING *
115 ***************************************************************************
116 *
117 * dmsg_msg - A standalone copy of a message, typically referenced by
118 * or embedded in other structures, or used with I/O queues.
119 *
120 * These structures are strictly temporary, so they do not have to be
121 * particularly optimized for size. All possible message headers are
122 * directly embedded (any), and the message may contain a reference
123 * to allocated auxillary data. The structure is recycled quite often
124 * by a connection.
125 *
126 * This structure is typically not used for storing persistent message
127 * state (see dmsg_persist for that).
128 */
129struct dmsg_iocom;
130struct dmsg_persist;
131struct dmsg_state;
132struct dmsg_router;
133struct dmsg_msg;
134
135TAILQ_HEAD(dmsg_state_queue, dmsg_state);
136TAILQ_HEAD(dmsg_msg_queue, dmsg_msg);
137RB_HEAD(dmsg_state_tree, dmsg_state);
138RB_HEAD(dmsg_router_tree, dmsg_router);
139
140struct h2span_link;
141struct h2span_relay;
142struct h2span_conn;
143
144struct dmsg_state {
145 RB_ENTRY(dmsg_state) rbnode; /* indexed by msgid */
146 struct dmsg_iocom *iocom;
147 struct dmsg_router *router; /* if routed */
148 uint32_t txcmd; /* mostly for CMDF flags */
149 uint32_t rxcmd; /* mostly for CMDF flags */
150 uint64_t msgid; /* {spanid,msgid} uniq */
151 int flags;
152 int error;
153 struct dmsg_msg *msg;
154 void (*func)(struct dmsg_msg *);
155 union {
156 void *any;
157 struct h2span_link *link;
158 struct h2span_conn *conn;
159 struct h2span_relay *relay;
160 } any;
161};
162
163#define DMSG_STATE_INSERTED 0x0001
164#define DMSG_STATE_DYNAMIC 0x0002
165#define DMSG_STATE_NODEID 0x0004 /* manages a node id */
166
167struct dmsg_msg {
168 TAILQ_ENTRY(dmsg_msg) qentry;
169 struct dmsg_router *router;
170 struct dmsg_state *state;
171 size_t hdr_size;
172 size_t aux_size;
173 char *aux_data;
174 dmsg_any_t any;
175};
176
177typedef struct dmsg_state dmsg_state_t;
178typedef struct dmsg_msg dmsg_msg_t;
179typedef struct dmsg_msg_queue dmsg_msg_queue_t;
180
181int dmsg_state_cmp(dmsg_state_t *state1, dmsg_state_t *state2);
182RB_PROTOTYPE(dmsg_state_tree, dmsg_state, rbnode, dmsg_state_cmp);
183
184/*
185 * dmsg_ioq - An embedded component of dmsg_conn, holds state
186 * for the buffering and parsing of incoming and outgoing messages.
187 *
188 * cdx - beg - processed buffer data, encrypted or decrypted
189 * end - cdn - unprocessed buffer data not yet encrypted or decrypted
190 */
191struct dmsg_ioq {
192 enum { DMSG_MSGQ_STATE_HEADER1,
193 DMSG_MSGQ_STATE_HEADER2,
194 DMSG_MSGQ_STATE_AUXDATA1,
195 DMSG_MSGQ_STATE_AUXDATA2,
196 DMSG_MSGQ_STATE_ERROR } state;
197 size_t fifo_beg; /* buffered data */
198 size_t fifo_cdx; /* cdx-beg processed */
199 size_t fifo_cdn; /* end-cdn unprocessed */
200 size_t fifo_end;
201 size_t hbytes; /* header size */
202 size_t abytes; /* aux_data size */
203 int error;
204 int seq; /* salt sequencer */
205 int msgcount;
206 EVP_CIPHER_CTX ctx;
207 char iv[DMSG_MAX_IV_SIZE]; /* encrypt or decrypt iv[] */
208 dmsg_msg_t *msg;
209 dmsg_msg_queue_t msgq;
210 char buf[DMSG_BUF_SIZE]; /* staging buffer */
211};
212
213typedef struct dmsg_ioq dmsg_ioq_t;
214
215#define DMSG_IOQ_ERROR_SYNC 1 /* bad magic / out of sync */
216#define DMSG_IOQ_ERROR_EOF 2 /* unexpected EOF */
217#define DMSG_IOQ_ERROR_SOCK 3 /* read() error on socket */
218#define DMSG_IOQ_ERROR_FIELD 4 /* invalid field */
219#define DMSG_IOQ_ERROR_HCRC 5 /* core header crc bad */
220#define DMSG_IOQ_ERROR_XCRC 6 /* ext header crc bad */
221#define DMSG_IOQ_ERROR_ACRC 7 /* aux data crc bad */
222#define DMSG_IOQ_ERROR_STATE 8 /* bad state */
223#define DMSG_IOQ_ERROR_NOPEER 9 /* bad socket peer */
224#define DMSG_IOQ_ERROR_NORKEY 10 /* no remote keyfile found */
225#define DMSG_IOQ_ERROR_NOLKEY 11 /* no local keyfile found */
226#define DMSG_IOQ_ERROR_KEYXCHGFAIL 12 /* key exchange failed */
227#define DMSG_IOQ_ERROR_KEYFMT 13 /* key file format problem */
228#define DMSG_IOQ_ERROR_BADURANDOM 14 /* /dev/urandom is bad */
229#define DMSG_IOQ_ERROR_MSGSEQ 15 /* message sequence error */
230#define DMSG_IOQ_ERROR_EALREADY 16 /* ignore this message */
231#define DMSG_IOQ_ERROR_TRANS 17 /* state transaction issue */
232#define DMSG_IOQ_ERROR_IVWRAP 18 /* IVs exhaused */
233#define DMSG_IOQ_ERROR_MACFAIL 19 /* MAC of encr alg failed */
234#define DMSG_IOQ_ERROR_ALGO 20 /* Misc. encr alg error */
235
236#define DMSG_IOQ_MAXIOVEC 16
237
238/*
239 * dmsg_router - governs the routing of a message. Passed into
240 * dmsg_msg_write.
241 *
242 * The router is either connected to an iocom (socket) directly, or
243 * connected to a SPAN transaction (h2span_link structure for outgoing)
244 * or to a SPAN transaction (h2span_relay structure for incoming).
245 */
246struct dmsg_router {
247 RB_ENTRY(dmsg_router) rbnode; /* indexed by target */
248 struct dmsg_iocom *iocom;
249 struct h2span_link *link; /* may be NULL */
250 struct h2span_relay *relay; /* may be NULL */
251 void (*signal_callback)(struct dmsg_router *);
252 void (*rcvmsg_callback)(struct dmsg_msg *);
253 void (*altmsg_callback)(struct dmsg_iocom *);
254 void (*dbgmsg_callback)(dmsg_msg_t *msg);
255 struct dmsg_state_tree staterd_tree; /* active messages */
256 struct dmsg_state_tree statewr_tree; /* active messages */
257 dmsg_msg_queue_t txmsgq; /* tx msgq from remote */
258 uint64_t target; /* for routing */
259 int flags;
260 int refs; /* refs prevent destruction */
261};
262
263#define DMSG_ROUTER_CONNECTED 0x0001 /* on global RB tree */
264#define DMSG_ROUTER_DELETED 0x0002 /* parent structure destroyed */
265
266typedef struct dmsg_router dmsg_router_t;
267
268int dmsg_router_cmp(dmsg_router_t *router1, dmsg_router_t *router2);
269RB_PROTOTYPE(dmsg_router_tree, dmsg_router, rbnode, dmsg_router_cmp);
270
271/*
272 * dmsg_iocom - governs a messaging stream connection
273 */
274struct dmsg_iocom {
275 dmsg_ioq_t ioq_rx;
276 dmsg_ioq_t ioq_tx;
277 dmsg_msg_queue_t freeq; /* free msgs hdr only */
278 dmsg_msg_queue_t freeq_aux; /* free msgs w/aux_data */
279 int sock_fd; /* comm socket or pipe */
280 int alt_fd; /* thread signal, tty, etc */
281 int wakeupfds[2]; /* pipe wakes up iocom thread */
282 int flags;
283 int rxmisc;
284 int txmisc;
285 struct dmsg_router *router;
286 pthread_mutex_t mtx; /* mutex for state*tree/rmsgq */
287};
288
289typedef struct dmsg_iocom dmsg_iocom_t;
290
291#define DMSG_IOCOMF_EOF 0x00000001 /* EOF or ERROR on desc */
292#define DMSG_IOCOMF_RREQ 0x00000002 /* request read-data event */
293#define DMSG_IOCOMF_WREQ 0x00000004 /* request write-avail event */
294#define DMSG_IOCOMF_RWORK 0x00000008 /* immediate work pending */
295#define DMSG_IOCOMF_WWORK 0x00000010 /* immediate work pending */
296#define DMSG_IOCOMF_PWORK 0x00000020 /* immediate work pending */
297#define DMSG_IOCOMF_ARWORK 0x00000040 /* immediate work pending */
298#define DMSG_IOCOMF_AWWORK 0x00000080 /* immediate work pending */
299#define DMSG_IOCOMF_SWORK 0x00000100 /* immediate work pending */
300#define DMSG_IOCOMF_CRYPTED 0x00000200 /* encrypt enabled */
301
302/*
303 * Crypto algorithm table and related typedefs.
304 */
0c3a8cd0
MD
305typedef int (*algo_init_fn)(dmsg_ioq_t *, char *, int, char *, int, int);
306typedef int (*algo_enc_fn)(dmsg_ioq_t *, char *, char *, int, int *);
307typedef int (*algo_dec_fn)(dmsg_ioq_t *, char *, char *, int, int *);
308
309struct crypto_algo {
310 const char *name;
311 int keylen;
312 int taglen;
313 algo_init_fn init;
314 algo_enc_fn enc_chunk;
315 algo_dec_fn dec_chunk;
316};
317
11f7caf4
MD
318/*
319 * Master service thread info
320 */
321struct dmsg_master_service_info {
322 int fd;
323 int detachme;
185ace93 324 void *handle;
11f7caf4 325 void (*dbgmsg_callback)(dmsg_msg_t *msg);
185ace93 326 void (*exit_callback)(void *handle);
11f7caf4
MD
327};
328
329typedef struct dmsg_master_service_info dmsg_master_service_info_t;
330
331
0c3a8cd0
MD
332/*
333 * icrc
334 */
335uint32_t dmsg_icrc32(const void *buf, size_t size);
336uint32_t dmsg_icrc32c(const void *buf, size_t size, uint32_t crc);
337
338/*
339 * debug
340 */
341const char *dmsg_basecmd_str(uint32_t cmd);
342const char *dmsg_msg_str(dmsg_msg_t *msg);
343
344/*
345 * subs
346 */
347void *dmsg_alloc(size_t bytes);
348void dmsg_free(void *ptr);
349const char *dmsg_uuid_to_str(uuid_t *uuid, char **strp);
350int dmsg_connect(const char *hostname);
351
352/*
353 * Msg support functions
354 */
355void dmsg_bswap_head(dmsg_hdr_t *head);
356void dmsg_ioq_init(dmsg_iocom_t *iocom, dmsg_ioq_t *ioq);
357void dmsg_ioq_done(dmsg_iocom_t *iocom, dmsg_ioq_t *ioq);
358void dmsg_iocom_init(dmsg_iocom_t *iocom, int sock_fd, int alt_fd,
359 void (*state_func)(dmsg_router_t *),
360 void (*rcvmsg_func)(dmsg_msg_t *),
11f7caf4 361 void (*dbgmsg_func)(dmsg_msg_t *),
0c3a8cd0
MD
362 void (*altmsg_func)(dmsg_iocom_t *));
363void dmsg_router_restate(dmsg_router_t *router,
364 void (*state_func)(dmsg_router_t *),
365 void (*rcvmsg_func)(dmsg_msg_t *),
366 void (*altmsg_func)(dmsg_iocom_t *));
367void dmsg_router_signal(dmsg_router_t *router);
368void dmsg_iocom_done(dmsg_iocom_t *iocom);
369dmsg_msg_t *dmsg_msg_alloc(dmsg_router_t *router,
370 size_t aux_size, uint32_t cmd,
371 void (*func)(dmsg_msg_t *), void *data);
372void dmsg_msg_reply(dmsg_msg_t *msg, uint32_t error);
373void dmsg_msg_result(dmsg_msg_t *msg, uint32_t error);
374void dmsg_state_reply(dmsg_state_t *state, uint32_t error);
375
376void dmsg_msg_free(dmsg_msg_t *msg);
377
378void dmsg_iocom_core(dmsg_iocom_t *iocom);
379dmsg_msg_t *dmsg_ioq_read(dmsg_iocom_t *iocom);
380void dmsg_msg_write(dmsg_msg_t *msg);
381
382void dmsg_iocom_drain(dmsg_iocom_t *iocom);
383void dmsg_iocom_flush1(dmsg_iocom_t *iocom);
384void dmsg_iocom_flush2(dmsg_iocom_t *iocom);
385
386void dmsg_state_cleanuprx(dmsg_iocom_t *iocom, dmsg_msg_t *msg);
387void dmsg_state_free(dmsg_state_t *state);
388
389dmsg_router_t *dmsg_router_alloc(void);
390void dmsg_router_connect(dmsg_router_t *router);
391void dmsg_router_disconnect(dmsg_router_t **routerp);
392
393/*
394 * Msg protocol functions
395 */
396void dmsg_msg_lnk_signal(dmsg_router_t *router);
397void dmsg_msg_lnk(dmsg_msg_t *msg);
398void dmsg_msg_dbg(dmsg_msg_t *msg);
399void dmsg_shell_tree(dmsg_router_t *router, char *cmdbuf __unused);
400
401/*
402 * Crypto functions
403 */
404void dmsg_crypto_setup(void);
405void dmsg_crypto_negotiate(dmsg_iocom_t *iocom);
406void dmsg_crypto_decrypt(dmsg_iocom_t *iocom, dmsg_ioq_t *ioq);
407int dmsg_crypto_encrypt(dmsg_iocom_t *iocom, dmsg_ioq_t *ioq,
408 struct iovec *iov, int n, size_t *nactp);
409
410/*
411 * Service daemon functions
412 */
413void *dmsg_master_service(void *data);
f7eac9d2
SW
414void dmsg_router_printf(dmsg_router_t *router, const char *ctl, ...)
415 __printflike(2, 3);
0c3a8cd0
MD
416
417extern int DMsgDebugOpt;