]> jfr.im git - irc/rqf/shadowircd.git/blob - ssld/ssld.c
m_stats.c fixed not to use kb in tstats output
[irc/rqf/shadowircd.git] / ssld / ssld.c
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
36 static void setup_signals(void);
37
38 static 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
48 static 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
57 static 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
65 static 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
74 static char inbuf[READBUF_SIZE];
75 static char outbuf[READBUF_SIZE];
76
77 typedef 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
86 typedef 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
96 static mod_ctl_t *mod_ctl;
97
98
99 #ifdef HAVE_LIBZ
100 typedef struct _zlib_stream
101 {
102 z_stream instream;
103 z_stream outstream;
104 } zlib_stream_t;
105 #endif
106
107 typedef 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
153 static rb_dlink_list connid_hash_table[CONN_HASH_SIZE];
154 static rb_dlink_list dead_list;
155
156 static void conn_mod_write_sendq(rb_fde_t *, void *data);
157 static void conn_plain_write_sendq(rb_fde_t *, void *data);
158 static void mod_write_ctl(rb_fde_t *, void *data);
159 static void conn_plain_read_cb(rb_fde_t * fd, void *data);
160 static void mod_cmd_write_queue(mod_ctl_t *ctl, const void *data, size_t len);
161 static const char *remote_closed = "Remote host closed the connection";
162 static int ssl_ok;
163 #ifdef HAVE_LIBZ
164 static int zlib_ok = 1;
165 #else
166 static int zlib_ok = 0;
167 #endif
168 static void *
169 ssld_alloc(void *unused, size_t count, size_t size)
170 {
171 return rb_malloc(count * size);
172 }
173
174 static void
175 ssld_free(void *unused, void *ptr)
176 {
177 rb_free(ptr);
178 }
179
180 static conn_t *
181 conn_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
195 static void
196 conn_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
202 static void
203 free_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
216 static void
217 clean_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
230 static void
231 close_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
266 static conn_t *
267 make_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
282 static void
283 conn_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
324 static void
325 conn_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
332 static void
333 conn_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
340 static void
341 mod_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
354 static void
355 common_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
387 static void
388 common_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
426 static int
427 plain_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
443 static void
444 conn_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
491 static void
492 conn_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
543 static void
544 conn_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
569 static int
570 maxconn(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
583 static void
584 ssl_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
597 static void
598 ssl_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
612 static void
613 ssl_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
637 static void
638 ssl_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
660 static void
661 process_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
689 static void
690 zlib_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
699 static void
700 zlib_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
757 static void
758 init_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
769 static void
770 ssl_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
792 static void
793 send_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
811 static void
812 send_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
818 static void
819 send_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
836 static void
837 mod_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
914 static void
915 mod_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
948 static void
949 mod_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
978 static void
979 read_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
992 int
993 main(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
1064 static void
1065 dummy_handler(int sig)
1066 {
1067 return;
1068 }
1069
1070 static void
1071 setup_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