]> jfr.im git - irc/rqf/shadowircd.git/blame - ssld/ssld.c
m_stats.c fixed not to use kb in tstats output
[irc/rqf/shadowircd.git] / ssld / ssld.c
CommitLineData
7f87f8d2
VY
1/*
2 * ssld.c: The ircd-ratbox ssl/zlib helper daemon thingy
3 * Copyright (C) 2007 Aaron Sethman <androsyn@ratbox.org>
4 * Copyright (C) 2007 ircd-ratbox development team
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
19 * USA
20 *
21 * $Id: ssld.c 25179 2008-03-30 16:34:57Z androsyn $
22 */
23
24
25#include "stdinc.h"
26
27#ifdef HAVE_LIBZ
28#include <zlib.h>
29#endif
30
31#define MAXPASSFD 4
32#ifndef READBUF_SIZE
33#define READBUF_SIZE 16384
34#endif
35
36static void setup_signals(void);
37
38static inline rb_int32_t buf_to_int32(char *buf)
39{
40 rb_int32_t x;
41 x = *buf << 24;
42 x |= *(++buf) << 16;
43 x |= *(++buf) << 8;
44 x |= *(++buf);
45 return x;
46}
47
48static inline void int32_to_buf(char *buf, rb_int32_t x)
49{
50 *(buf) = x >> 24 & 0xFF;
51 *(++buf) = x >> 16 & 0xFF;
52 *(++buf) = x >> 8 & 0xFF;
53 *(++buf) = x & 0xFF;
54 return;
55}
56
57static inline rb_uint16_t buf_to_uint16(char *buf)
58{
59 rb_uint16_t x;
60 x = *(buf) << 8;
61 x |= *(++buf);
62 return x;
63}
64
65static inline void uint16_to_buf(char *buf, rb_uint16_t x)
66{
67 *(buf) = x >> 8 & 0xFF;
68 *(++buf) = x & 0xFF;
69 return;
70}
71
72
73
74static char inbuf[READBUF_SIZE];
75static char outbuf[READBUF_SIZE];
76
77typedef struct _mod_ctl_buf
78{
79 rb_dlink_node node;
80 char *buf;
81 size_t buflen;
82 rb_fde_t *F[MAXPASSFD];
83 int nfds;
84} mod_ctl_buf_t;
85
86typedef struct _mod_ctl
87{
88 rb_dlink_node node;
89 int cli_count;
90 rb_fde_t *F;
91 rb_fde_t *F_pipe;
92 rb_dlink_list readq;
93 rb_dlink_list writeq;
94} mod_ctl_t;
95
96static mod_ctl_t *mod_ctl;
97
98
99#ifdef HAVE_LIBZ
100typedef struct _zlib_stream
101{
102 z_stream instream;
103 z_stream outstream;
104} zlib_stream_t;
105#endif
106
107typedef struct _conn
108{
109 rb_dlink_node node;
110 mod_ctl_t *ctl;
111 rawbuf_head_t *modbuf_out;
112 rawbuf_head_t *plainbuf_out;
113
114 rb_int32_t id;
115
116 rb_fde_t *mod_fd;
117 rb_fde_t *plain_fd;
118 unsigned long long mod_out;
119 unsigned long long mod_in;
120 unsigned long long plain_in;
121 unsigned long long plain_out;
122 rb_uint8_t flags;
123 void *stream;
124} conn_t;
125
126#define FLAG_SSL 0x01
127#define FLAG_ZIP 0x02
128#define FLAG_CORK 0x04
129#define FLAG_DEAD 0x08
130
131
132#define IsSSL(x) ((x)->flags & FLAG_SSL)
133#define IsZip(x) ((x)->flags & FLAG_ZIP)
134#define IsCork(x) ((x)->flags & FLAG_CORK)
135#define IsDead(x) ((x)->flags & FLAG_DEAD)
136
137#define SetSSL(x) ((x)->flags |= FLAG_SSL)
138#define SetZip(x) ((x)->flags |= FLAG_ZIP)
139#define SetCork(x) ((x)->flags |= FLAG_CORK)
140#define SetDead(x) ((x)->flags |= FLAG_DEAD)
141
142#define ClearSSL(x) ((x)->flags &= ~FLAG_SSL)
143#define ClearZip(x) ((x)->flags &= ~FLAG_ZIP)
144#define ClearCork(x) ((x)->flags &= ~FLAG_CORK)
145#define ClearDead(x) ((x)->flags &= ~FLAG_DEAD)
146
147#define NO_WAIT 0x0
148#define WAIT_PLAIN 0x1
149
150#define CONN_HASH_SIZE 2000
151#define connid_hash(x) (&connid_hash_table[(x % CONN_HASH_SIZE)])
152
153static rb_dlink_list connid_hash_table[CONN_HASH_SIZE];
154static rb_dlink_list dead_list;
155
156static void conn_mod_write_sendq(rb_fde_t *, void *data);
157static void conn_plain_write_sendq(rb_fde_t *, void *data);
158static void mod_write_ctl(rb_fde_t *, void *data);
159static void conn_plain_read_cb(rb_fde_t * fd, void *data);
160static void mod_cmd_write_queue(mod_ctl_t *ctl, const void *data, size_t len);
161static const char *remote_closed = "Remote host closed the connection";
162static int ssl_ok;
163#ifdef HAVE_LIBZ
164static int zlib_ok = 1;
165#else
166static int zlib_ok = 0;
167#endif
168static void *
169ssld_alloc(void *unused, size_t count, size_t size)
170{
171 return rb_malloc(count * size);
172}
173
174static void
175ssld_free(void *unused, void *ptr)
176{
177 rb_free(ptr);
178}
179
180static conn_t *
181conn_find_by_id(rb_int32_t id)
182{
183 rb_dlink_node *ptr;
184 conn_t *conn;
185
186 RB_DLINK_FOREACH(ptr, (connid_hash(id))->head)
187 {
188 conn = ptr->data;
189 if(conn->id == id && !IsDead(conn))
190 return conn;
191 }
192 return NULL;
193}
194
195static void
196conn_add_id_hash(conn_t * conn, rb_int32_t id)
197{
198 conn->id = id;
199 rb_dlinkAdd(conn, &conn->node, connid_hash(id));
200}
201
202static void
203free_conn(conn_t * conn)
204{
205 rb_free_rawbuffer(conn->modbuf_out);
206 rb_free_rawbuffer(conn->plainbuf_out);
207 if(IsZip(conn))
208 {
209 zlib_stream_t *stream = conn->stream;
210 inflateEnd(&stream->instream);
211 deflateEnd(&stream->outstream);
212 }
213 rb_free(conn);
214}
215
216static void
217clean_dead_conns(void *unused)
218{
219 conn_t *conn;
220 rb_dlink_node *ptr, *next;
221 RB_DLINK_FOREACH_SAFE(ptr, next, dead_list.head)
222 {
223 conn = ptr->data;
224 free_conn(conn);
225 }
226 dead_list.tail = dead_list.head = NULL;
227}
228
229
230static void
231close_conn(conn_t * conn, int wait_plain, const char *fmt, ...)
232{
233 va_list ap;
234 char reason[128]; /* must always be under 250 bytes */
235 char buf[256];
236 int len;
237 if(IsDead(conn))
238 return;
239
240 rb_rawbuf_flush(conn->modbuf_out, conn->mod_fd);
241 rb_rawbuf_flush(conn->plainbuf_out, conn->plain_fd);
242 rb_close(conn->mod_fd);
243 SetDead(conn);
244
245 if(!wait_plain || fmt == NULL)
246 {
247 rb_close(conn->plain_fd);
248
249 if(conn->id >= 0)
250 rb_dlinkDelete(&conn->node, connid_hash(conn->id));
251 rb_dlinkAdd(conn, &conn->node, &dead_list);
252 return;
253 }
254 rb_setselect(conn->plain_fd, RB_SELECT_WRITE|RB_SELECT_READ, NULL, NULL);
255 va_start(ap, fmt);
256 rb_vsnprintf(reason, sizeof(reason), fmt, ap);
257 va_end(ap);
258
259 buf[0] = 'D';
260 int32_to_buf(&buf[1], conn->id);
261 strcpy(&buf[5], reason);
262 len = (strlen(reason) + 1) + 5;
263 mod_cmd_write_queue(conn->ctl, buf, len);
264}
265
266static conn_t *
267make_conn(mod_ctl_t *ctl, rb_fde_t * mod_fd, rb_fde_t * plain_fd)
268{
269 conn_t *conn = rb_malloc(sizeof(conn_t));
270 conn->ctl = ctl;
271 conn->modbuf_out = rb_new_rawbuffer();
272 conn->plainbuf_out = rb_new_rawbuffer();
273 conn->mod_fd = mod_fd;
274 conn->plain_fd = plain_fd;
275 conn->id = -1;
276 conn->stream = NULL;
277 rb_set_nb(mod_fd);
278 rb_set_nb(plain_fd);
279 return conn;
280}
281
282static void
283conn_mod_write_sendq(rb_fde_t * fd, void *data)
284{
285 conn_t *conn = data;
286 const char *err;
287 int retlen;
288 if(IsDead(conn))
289 return;
290
291 while ((retlen = rb_rawbuf_flush(conn->modbuf_out, fd)) > 0)
292 conn->mod_out += retlen;
293
294 if(retlen == 0 || (retlen < 0 && !rb_ignore_errno(errno)))
295 {
296 if(retlen == 0)
297 close_conn(conn, WAIT_PLAIN, "%s", remote_closed);
298 if(IsSSL(conn) && retlen == RB_RW_SSL_ERROR)
299 err = rb_get_ssl_strerror(conn->mod_fd);
300 else
301 err = strerror(errno);
302 close_conn(conn, WAIT_PLAIN, "Write error: %s", err);
303 return;
304 }
305 if(rb_rawbuf_length(conn->modbuf_out) > 0)
306 {
307 int flags = RB_SELECT_WRITE;
308 if(retlen == RB_RW_SSL_NEED_READ)
309 flags |= RB_SELECT_READ;
310
311 rb_setselect(conn->mod_fd, flags, conn_mod_write_sendq, conn);
312 }
313 else
314 rb_setselect(conn->mod_fd, RB_SELECT_WRITE, NULL, NULL);
315
316 if(IsCork(conn) && rb_rawbuf_length(conn->modbuf_out) == 0)
317 {
318 ClearCork(conn);
319 conn_plain_read_cb(conn->plain_fd, conn);
320 }
321
322}
323
324static void
325conn_mod_write(conn_t * conn, void *data, size_t len)
326{
327 if(IsDead(conn)) /* no point in queueing to a dead man */
328 return;
329 rb_rawbuf_append(conn->modbuf_out, data, len);
330}
331
332static void
333conn_plain_write(conn_t * conn, void *data, size_t len)
334{
335 if(IsDead(conn)) /* again no point in queueing to dead men */
336 return;
337 rb_rawbuf_append(conn->plainbuf_out, data, len);
338}
339
340static void
341mod_cmd_write_queue(mod_ctl_t * ctl, const void *data, size_t len)
342{
343 mod_ctl_buf_t *ctl_buf;
344 ctl_buf = rb_malloc(sizeof(mod_ctl_buf_t));
345 ctl_buf->buf = rb_malloc(len);
346 ctl_buf->buflen = len;
347 memcpy(ctl_buf->buf, data, len);
348 ctl_buf->nfds = 0;
349 rb_dlinkAddTail(ctl_buf, &ctl_buf->node, &ctl->writeq);
350 mod_write_ctl(ctl->F, ctl);
351}
352
353#ifdef HAVE_LIBZ
354static void
355common_zlib_deflate(conn_t * conn, void *buf, size_t len)
356{
357 int ret, have;
358 z_stream *outstream = &((zlib_stream_t *)conn->stream)->outstream;
359 outstream->next_in = buf;
360 outstream->avail_in = len;
361 outstream->next_out = (Bytef *) outbuf;
362 outstream->avail_out = sizeof(outbuf);
363
364 ret = deflate(outstream, Z_SYNC_FLUSH);
365 if(ret != Z_OK)
366 {
367 /* deflate error */
368 close_conn(conn, WAIT_PLAIN, "Deflate failed: %s", zError(ret));
369 return;
370 }
371 if(outstream->avail_out == 0)
372 {
373 /* avail_out empty */
374 close_conn(conn, WAIT_PLAIN, "error compressing data, avail_out == 0");
375 return;
376 }
377 if(outstream->avail_in != 0)
378 {
379 /* avail_in isn't empty...*/
380 close_conn(conn, WAIT_PLAIN, "error compressing data, avail_in != 0");
381 return;
382 }
383 have = sizeof(outbuf) - outstream->avail_out;
384 conn_mod_write(conn, outbuf, have);
385}
386
387static void
388common_zlib_inflate(conn_t * conn, void *buf, size_t len)
389{
390 int ret, have;
391 ((zlib_stream_t *)conn->stream)->instream.next_in = buf;
392 ((zlib_stream_t *)conn->stream)->instream.avail_in = len;
393 ((zlib_stream_t *)conn->stream)->instream.next_out = (Bytef *) outbuf;
394 ((zlib_stream_t *)conn->stream)->instream.avail_out = sizeof(outbuf);
395
396 while (((zlib_stream_t *)conn->stream)->instream.avail_in)
397 {
398 ret = inflate(&((zlib_stream_t *)conn->stream)->instream, Z_NO_FLUSH);
399 if(ret != Z_OK)
400 {
401 if(!strncmp("ERROR ", buf, 6))
402 {
403 close_conn(conn, WAIT_PLAIN, "Received uncompressed ERROR");
404 return;
405 }
406 close_conn(conn, WAIT_PLAIN, "Inflate failed: %s", zError(ret));
407 return;
408 }
409 have = sizeof(outbuf) - ((zlib_stream_t *)conn->stream)->instream.avail_out;
410
411 if(((zlib_stream_t *)conn->stream)->instream.avail_in)
412 {
413 conn_plain_write(conn, outbuf, have);
414 have = 0;
415 ((zlib_stream_t *)conn->stream)->instream.next_out = (Bytef *) outbuf;
416 ((zlib_stream_t *)conn->stream)->instream.avail_out = sizeof(outbuf);
417 }
418 }
419 if(have == 0)
420 return;
421
422 conn_plain_write(conn, outbuf, have);
423}
424#endif
425
426static int
427plain_check_cork(conn_t * conn)
428{
429 if(rb_rawbuf_length(conn->modbuf_out) >= 4096)
430 {
431 /* if we have over 4k pending outbound, don't read until
432 * we've cleared the queue */
433 SetCork(conn);
434 rb_setselect(conn->plain_fd, RB_SELECT_READ, NULL, NULL);
435 /* try to write */
436 conn_mod_write_sendq(conn->mod_fd, conn);
437 return 1;
438 }
439 return 0;
440}
441
442
443static void
444conn_plain_read_cb(rb_fde_t * fd, void *data)
445{
446 conn_t *conn = data;
447 int length = 0;
448 if(conn == NULL)
449 return;
450
451 if(IsDead(conn))
452 return;
453
454 if(plain_check_cork(conn))
455 return;
456
457 while (1)
458 {
459 if(IsDead(conn))
460 return;
461
462 length = rb_read(conn->plain_fd, inbuf, sizeof(inbuf));
463
464 if(length == 0 || (length < 0 && !rb_ignore_errno(errno)))
465 {
466 close_conn(conn, NO_WAIT, NULL);
467 return;
468 }
469
470 if(length < 0)
471 {
472 rb_setselect(conn->plain_fd, RB_SELECT_READ, conn_plain_read_cb, conn);
473 conn_mod_write_sendq(conn->mod_fd, conn);
474 return;
475 }
476 conn->plain_in += length;
477
478#ifdef HAVE_LIBZ
479 if(IsZip(conn))
480 common_zlib_deflate(conn, inbuf, length);
481 else
482#endif
483 conn_mod_write(conn, inbuf, length);
484 if(IsDead(conn))
485 return;
486 if(plain_check_cork(conn))
487 return;
488 }
489}
490
491static void
492conn_mod_read_cb(rb_fde_t * fd, void *data)
493{
494 conn_t *conn = data;
495 const char *err = remote_closed;
496 int length;
497 if(conn == NULL)
498 return;
499 if(IsDead(conn))
500 return;
501
502 while (1)
503 {
504 if(IsDead(conn))
505 return;
506
507 length = rb_read(conn->mod_fd, inbuf, sizeof(inbuf));
508
509 if(length == 0 || (length < 0 && !rb_ignore_errno(errno)))
510 {
511 if(length == 0) {
512 close_conn(conn, WAIT_PLAIN, "%s", remote_closed);
513 return;
514 }
515
516 if(IsSSL(conn) && length == RB_RW_SSL_ERROR)
517 err = rb_get_ssl_strerror(conn->mod_fd);
518 else
519 err = strerror(errno);
520 close_conn(conn, WAIT_PLAIN, "Read error: %s", err);
521 return;
522 }
523 if(length < 0)
524 {
525 int flags = RB_SELECT_READ;
526 if(length == RB_RW_SSL_NEED_WRITE)
527 flags |= RB_SELECT_WRITE;
528
529 rb_setselect(conn->mod_fd, flags, conn_mod_read_cb, conn);
530 conn_plain_write_sendq(conn->plain_fd, conn);
531 return;
532 }
533 conn->mod_in += length;
534#ifdef HAVE_LIBZ
535 if(IsZip(conn))
536 common_zlib_inflate(conn, inbuf, length);
537 else
538#endif
539 conn_plain_write(conn, inbuf, length);
540 }
541}
542
543static void
544conn_plain_write_sendq(rb_fde_t * fd, void *data)
545{
546 conn_t *conn = data;
547 int retlen;
548
549 if(IsDead(conn))
550 return;
551
552 while ((retlen = rb_rawbuf_flush(conn->plainbuf_out, fd)) > 0)
553 {
554 conn->plain_out += retlen;
555 }
556 if(retlen == 0 || (retlen < 0 && !rb_ignore_errno(errno)))
557 {
558 close_conn(data, NO_WAIT, NULL);
559 return;
560 }
561
562
563 if(rb_rawbuf_length(conn->plainbuf_out) > 0)
564 rb_setselect(conn->plain_fd, RB_SELECT_WRITE, conn_plain_write_sendq, conn);
565 else
566 rb_setselect(conn->plain_fd, RB_SELECT_WRITE, NULL, NULL);
567}
568
569static int
570maxconn(void)
571{
572#if defined(RLIMIT_NOFILE) && defined(HAVE_SYS_RESOURCE_H)
573 struct rlimit limit;
574
575 if(!getrlimit(RLIMIT_NOFILE, &limit))
576 {
577 return limit.rlim_cur;
578 }
579#endif /* RLIMIT_FD_MAX */
580 return MAXCONNECTIONS;
581}
582
583static void
584ssl_process_accept_cb(rb_fde_t * F, int status, struct sockaddr *addr, rb_socklen_t len, void *data)
585{
586 conn_t *conn = data;
587 if(status == RB_OK)
588 {
589 conn_mod_read_cb(conn->mod_fd, conn);
590 conn_plain_read_cb(conn->plain_fd, conn);
591 return;
592 }
593 close_conn(conn, NO_WAIT, 0);
594 return;
595}
596
597static void
598ssl_process_connect_cb(rb_fde_t * F, int status, void *data)
599{
600 conn_t *conn = data;
601 if(status == RB_OK)
602 {
603 conn_mod_read_cb(conn->mod_fd, conn);
604 conn_plain_read_cb(conn->plain_fd, conn);
605 return;
606 }
607 close_conn(conn, NO_WAIT, 0);
608 return;
609}
610
611
612static void
613ssl_process_accept(mod_ctl_t * ctl, mod_ctl_buf_t * ctlb)
614{
615 conn_t *conn;
616 rb_int32_t id;
617
618 conn = make_conn(ctl, ctlb->F[0], ctlb->F[1]);
619
620 id = buf_to_int32(&ctlb->buf[1]);
621
622 if(id >= 0)
623 conn_add_id_hash(conn, id);
624 SetSSL(conn);
625
626 if(rb_get_type(conn->mod_fd) & RB_FD_UNKNOWN)
627 {
628
629 rb_set_type(conn->mod_fd, RB_FD_SOCKET);
630 }
631 if(rb_get_type(conn->mod_fd) == RB_FD_UNKNOWN)
632 rb_set_type(conn->plain_fd, RB_FD_SOCKET);
633
634 rb_ssl_start_accepted(ctlb->F[0], ssl_process_accept_cb, conn, 10);
635}
636
637static void
638ssl_process_connect(mod_ctl_t * ctl, mod_ctl_buf_t * ctlb)
639{
640 conn_t *conn;
641 rb_int32_t id;
642 conn = make_conn(ctl, ctlb->F[0], ctlb->F[1]);
643
644 id = buf_to_int32(&ctlb->buf[1]);
645
646 if(id >= 0)
647 conn_add_id_hash(conn, id);
648 SetSSL(conn);
649
650 if(rb_get_type(conn->mod_fd) == RB_FD_UNKNOWN)
651 rb_set_type(conn->mod_fd, RB_FD_SOCKET);
652
653 if(rb_get_type(conn->mod_fd) == RB_FD_UNKNOWN)
654 rb_set_type(conn->plain_fd, RB_FD_SOCKET);
655
656
657 rb_ssl_start_connected(ctlb->F[0], ssl_process_connect_cb, conn, 10);
658}
659
660static void
661process_stats(mod_ctl_t * ctl, mod_ctl_buf_t * ctlb)
662{
663 char outstat[512];
664 conn_t *conn;
665 const char *odata;
666 rb_int32_t id;
667
668 id = buf_to_int32(&ctlb->buf[1]);
669
670 if(id < 0)
671 return;
672
673 odata = &ctlb->buf[5];
674 conn = conn_find_by_id(id);
675
676 if(conn == NULL)
677 return;
678
679 rb_snprintf(outstat, sizeof(outstat), "S %s %llu %llu %llu %llu", odata,
680 conn->plain_out, conn->mod_in, conn->plain_in, conn->mod_out);
681 conn->plain_out = 0;
682 conn->plain_in = 0;
683 conn->mod_in = 0;
684 conn->mod_out = 0;
685 mod_cmd_write_queue(ctl, outstat, strlen(outstat) + 1); /* +1 is so we send the \0 as well */
686}
687
688#ifdef HAVE_LIBZ
689static void
690zlib_send_zip_ready(mod_ctl_t *ctl, conn_t *conn)
691{
692 char buf[5];
693
694 buf[0] = 'R';
695 int32_to_buf(&buf[1], conn->id);
696 mod_cmd_write_queue(conn->ctl, buf, sizeof(buf));
697}
698
699static void
700zlib_process(mod_ctl_t * ctl, mod_ctl_buf_t * ctlb)
701{
702 rb_uint8_t level;
703 size_t recvqlen;
704 size_t hdr = (sizeof(rb_uint8_t) * 2) + sizeof(rb_int32_t);
705 void *recvq_start;
706 z_stream *instream, *outstream;
707 conn_t *conn;
708 rb_int32_t id;
709
710 conn = make_conn(ctl, ctlb->F[0], ctlb->F[1]);
711 if(rb_get_type(conn->mod_fd) == RB_FD_UNKNOWN)
712 rb_set_type(conn->mod_fd, RB_FD_SOCKET);
713
714 if(rb_get_type(conn->plain_fd) == RB_FD_UNKNOWN)
715 rb_set_type(conn->plain_fd, RB_FD_SOCKET);
716
717 id = buf_to_int32(&ctlb->buf[1]);
718 conn_add_id_hash(conn, id);
719
720 level = (rb_uint8_t) ctlb->buf[5];
721
722 recvqlen = ctlb->buflen - hdr;
723 recvq_start = &ctlb->buf[6];
724
725 SetZip(conn);
726 conn->stream = rb_malloc(sizeof(zlib_stream_t));
727 instream = &((zlib_stream_t *)conn->stream)->instream;
728 outstream = &((zlib_stream_t *)conn->stream)->outstream;
729
730 instream->total_in = 0;
731 instream->total_out = 0;
732 instream->zalloc = (alloc_func) ssld_alloc;
733 instream->zfree = (free_func) ssld_free;
734 instream->data_type = Z_ASCII;
735 inflateInit(&((zlib_stream_t *)conn->stream)->instream);
736
737 outstream->total_in = 0;
738 outstream->total_out = 0;
739 outstream->zalloc = (alloc_func) ssld_alloc;
740 outstream->zfree = (free_func) ssld_free;
741 outstream->data_type = Z_ASCII;
742
743 if(level > 9)
744 level = Z_DEFAULT_COMPRESSION;
745
746 deflateInit(&((zlib_stream_t *)conn->stream)->outstream, level);
747 if(recvqlen > 0)
748 common_zlib_inflate(conn, recvq_start, recvqlen);
749 zlib_send_zip_ready(ctl, conn);
750 conn_mod_read_cb(conn->mod_fd, conn);
751 conn_plain_read_cb(conn->plain_fd, conn);
752 return;
753
754}
755#endif
756
757static void
758init_prng(mod_ctl_t * ctl, mod_ctl_buf_t * ctl_buf)
759{
760 char *path;
761 prng_seed_t seed_type;
762
763 seed_type = (prng_seed_t)ctl_buf->buf[1];
764 path = &ctl_buf->buf[2];
765 rb_init_prng(path, seed_type);
766}
767
768
769static void
770ssl_new_keys(mod_ctl_t * ctl, mod_ctl_buf_t * ctl_buf)
771{
772 char *buf;
773 char *cert, *key, *dhparam;
774
775 buf = &ctl_buf->buf[2];
776 cert = buf;
777 buf += strlen(cert) + 1;
778 key = buf;
779 buf += strlen(key) + 1;
780 dhparam = buf;
781 if(strlen(dhparam) == 0)
782 dhparam = NULL;
783
784 if(!rb_setup_ssl_server(cert, key, dhparam))
785 {
786 const char *invalid = "I";
787 mod_cmd_write_queue(ctl, invalid, strlen(invalid));
788 return;
789 }
790}
791
792static void
793send_nossl_support(mod_ctl_t *ctl, mod_ctl_buf_t *ctlb)
794{
795 static const char *nossl_cmd = "N";
796 conn_t *conn;
797 rb_int32_t id;
798
799 if(ctlb != NULL)
800 {
801 conn = make_conn(ctl, ctlb->F[0], ctlb->F[1]);
802 id = buf_to_int32(&ctlb->buf[1]);
803
804 if(id >= 0)
805 conn_add_id_hash(conn, id);
806 close_conn(conn, WAIT_PLAIN, "libratbox reports no SSL/TLS support");
807 }
808 mod_cmd_write_queue(ctl, nossl_cmd, strlen(nossl_cmd));
809}
810
811static void
812send_i_am_useless(mod_ctl_t *ctl)
813{
814 static const char *useless = "U";
815 mod_cmd_write_queue(ctl, useless, strlen(useless));
816}
817
818static void
819send_nozlib_support(mod_ctl_t *ctl, mod_ctl_buf_t *ctlb)
820{
821 static const char *nozlib_cmd = "z";
822 conn_t *conn;
823 rb_int32_t id;
824 if(ctlb != NULL)
825 {
826 conn = make_conn(ctl, ctlb->F[0], ctlb->F[1]);
827 id = buf_to_int32(&ctlb->buf[1]);
828
829 if(id >= 0)
830 conn_add_id_hash(conn, id);
831 close_conn(conn, WAIT_PLAIN, "libratbox reports no zlib support");
832 }
833 mod_cmd_write_queue(ctl, nozlib_cmd, strlen(nozlib_cmd));
834}
835
836static void
837mod_process_cmd_recv(mod_ctl_t * ctl)
838{
839 rb_dlink_node *ptr, *next;
840 mod_ctl_buf_t *ctl_buf;
841
842 RB_DLINK_FOREACH_SAFE(ptr, next, ctl->readq.head)
843 {
844 ctl_buf = ptr->data;
845
846 switch (*ctl_buf->buf)
847 {
848 case 'A':
849 {
850 if(!ssl_ok)
851 {
852 send_nossl_support(ctl, ctl_buf);
853 break;
854 }
855 ssl_process_accept(ctl, ctl_buf);
856 break;
857 }
858 case 'C':
859 {
860 if(!ssl_ok)
861 {
862 send_nossl_support(ctl, ctl_buf);
863 break;
864 }
865 ssl_process_connect(ctl, ctl_buf);
866 break;
867 }
868
869 case 'K':
870 {
871 if(!ssl_ok)
872 {
873 send_nossl_support(ctl, ctl_buf);
874 break;
875 }
876 ssl_new_keys(ctl, ctl_buf);
877 break;
878 }
879 case 'I':
880 init_prng(ctl, ctl_buf);
881 break;
882 case 'S':
883 {
884 process_stats(ctl, ctl_buf);
885 break;
886 }
887#ifdef HAVE_LIBZ
888 case 'Z':
889 {
890 /* just zlib only */
891 zlib_process(ctl, ctl_buf);
892 break;
893 }
894#else
895 case 'Y':
896 case 'Z':
897 send_nozlib_support(ctl);
898 break;
899
900#endif
901 default:
902 break;
903 /* Log unknown commands */
904 }
905 rb_dlinkDelete(ptr, &ctl->readq);
906 rb_free(ctl_buf->buf);
907 rb_free(ctl_buf);
908 }
909
910}
911
912
913
914static void
915mod_read_ctl(rb_fde_t * F, void *data)
916{
917 mod_ctl_buf_t *ctl_buf;
918 mod_ctl_t *ctl = data;
919 int retlen;
920
921 do
922 {
923 ctl_buf = rb_malloc(sizeof(mod_ctl_buf_t));
924 ctl_buf->buf = rb_malloc(READBUF_SIZE);
925 ctl_buf->buflen = READBUF_SIZE;
926 retlen = rb_recv_fd_buf(ctl->F, ctl_buf->buf, ctl_buf->buflen, ctl_buf->F,
927 MAXPASSFD);
928 if(retlen <= 0)
929 {
930 rb_free(ctl_buf->buf);
931 rb_free(ctl_buf);
932 }
933 else
934 {
935 ctl_buf->buflen = retlen;
936 rb_dlinkAddTail(ctl_buf, &ctl_buf->node, &ctl->readq);
937 }
938 }
939 while (retlen > 0);
940
941 if(retlen == 0 || (retlen < 0 && !rb_ignore_errno(errno)))
942 exit(0);
943
944 mod_process_cmd_recv(ctl);
945 rb_setselect(ctl->F, RB_SELECT_READ, mod_read_ctl, ctl);
946}
947
948static void
949mod_write_ctl(rb_fde_t * F, void *data)
950{
951 mod_ctl_t *ctl = data;
952 mod_ctl_buf_t *ctl_buf;
953 rb_dlink_node *ptr, *next;
954 int retlen, x;
955
956 RB_DLINK_FOREACH_SAFE(ptr, next, ctl->writeq.head)
957 {
958 ctl_buf = ptr->data;
959 retlen = rb_send_fd_buf(ctl->F, ctl_buf->F, ctl_buf->nfds, ctl_buf->buf,
960 ctl_buf->buflen);
961 if(retlen > 0)
962 {
963 rb_dlinkDelete(ptr, &ctl->writeq);
964 for (x = 0; x < ctl_buf->nfds; x++)
965 rb_close(ctl_buf->F[x]);
966 rb_free(ctl_buf->buf);
967 rb_free(ctl_buf);
968
969 }
970 if(retlen == 0 || (retlen < 0 && !rb_ignore_errno(errno)))
971 exit(0);
972
973 rb_setselect(ctl->F, RB_SELECT_WRITE, mod_write_ctl, ctl);
974 }
975}
976
977
978static void
979read_pipe_ctl(rb_fde_t * F, void *data)
980{
981 int retlen;
982 while ((retlen = rb_read(F, inbuf, sizeof(inbuf))) > 0)
983 {
984 ;; /* we don't do anything with the pipe really, just care if the other process dies.. */
985 }
986 if(retlen == 0 || (retlen < 0 && !rb_ignore_errno(errno)))
987 exit(0);
988 rb_setselect(F, RB_SELECT_READ, read_pipe_ctl, NULL);
989
990}
991
992int
993main(int argc, char **argv)
994{
995 const char *s_ctlfd, *s_pipe;
996 int ctlfd, pipefd, x, maxfd;
997 maxfd = maxconn();
998 s_ctlfd = getenv("CTL_FD");
999 s_pipe = getenv("CTL_PIPE");
1000
1001 if(s_ctlfd == NULL || s_pipe == NULL)
1002 {
1003 fprintf(stderr, "This is ircd-ratbox ssld. You know you aren't supposed to run me directly?\n");
1004 fprintf(stderr, "You get an Id tag for this: $Id: ssld.c 25179 2008-03-30 16:34:57Z androsyn $\n");
1005 fprintf(stderr, "Have a nice life\n");
1006 exit(1);
1007 }
1008
1009 ctlfd = atoi(s_ctlfd);
1010 pipefd = atoi(s_pipe);
1011
1012 for (x = 0; x < maxfd; x++)
1013 {
1014 if(x != ctlfd && x != pipefd && x > 2)
1015 close(x);
1016 }
1017
1018#if 0
1019 x = open("/dev/null", O_RDWR);
1020 if(x >= 0)
1021 {
1022 if(ctlfd != 0 && pipefd != 0)
1023 dup2(x, 0);
1024 if(ctlfd != 1 && pipefd != 1)
1025 dup2(x, 1);
1026 if(ctlfd != 2 && pipefd != 2)
1027 dup2(x, 2);
1028 if(x > 2)
1029 close(x);
1030 }
1031#endif
1032 setup_signals();
1033 rb_lib_init(NULL, NULL, NULL, 0, maxfd, 1024, 4096);
1034 rb_init_rawbuffers(1024);
1035 ssl_ok = rb_supports_ssl();
1036
1037 mod_ctl = rb_malloc(sizeof(mod_ctl_t));
1038 mod_ctl->F = rb_open(ctlfd, RB_FD_SOCKET, "ircd control socket");
1039 mod_ctl->F_pipe = rb_open(pipefd, RB_FD_PIPE, "ircd pipe");
1040 rb_set_nb(mod_ctl->F);
1041 rb_set_nb(mod_ctl->F_pipe);
1042 rb_event_addish("clean_dead_conns", clean_dead_conns, NULL, 10);
1043 read_pipe_ctl(mod_ctl->F_pipe, NULL);
1044 mod_read_ctl(mod_ctl->F, mod_ctl);
1045 if(!zlib_ok && !ssl_ok)
1046 {
1047 /* this is really useless... */
1048 send_i_am_useless(mod_ctl);
1049 /* sleep until the ircd kills us */
1050 rb_sleep(2<<30, 0);
1051 exit(1);
1052 }
1053
1054 if(!zlib_ok)
1055 send_nozlib_support(mod_ctl, NULL);
1056 if(!ssl_ok)
1057 send_nossl_support(mod_ctl, NULL);
1058 rb_lib_loop(0);
1059 return 0;
1060}
1061
1062
1063
1064static void
1065dummy_handler(int sig)
1066{
1067 return;
1068}
1069
1070static void
1071setup_signals()
1072{
1073 struct sigaction act;
1074
1075 act.sa_flags = 0;
1076 act.sa_handler = SIG_IGN;
1077 sigemptyset(&act.sa_mask);
1078 sigaddset(&act.sa_mask, SIGPIPE);
1079 sigaddset(&act.sa_mask, SIGALRM);
1080#ifdef SIGTRAP
1081 sigaddset(&act.sa_mask, SIGTRAP);
1082#endif
1083
1084#ifdef SIGWINCH
1085 sigaddset(&act.sa_mask, SIGWINCH);
1086 sigaction(SIGWINCH, &act, 0);
1087#endif
1088 sigaction(SIGPIPE, &act, 0);
1089#ifdef SIGTRAP
1090 sigaction(SIGTRAP, &act, 0);
1091#endif
1092
1093 act.sa_handler = dummy_handler;
1094 sigaction(SIGALRM, &act, 0);
1095}
1096