root/src/noit_listener.c

Revision c172fd5c72852dc9800dc1eaa1b6434555e232fe, 17.2 kB (checked in by Theo Schlossnagle <jesus@omniti.com>, 3 years ago)

This is debugging

  • Property mode set to 100644
Line 
1 /*
2  * Copyright (c) 2007, OmniTI Computer Consulting, Inc.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are
7  * met:
8  *
9  *     * Redistributions of source code must retain the above copyright
10  *       notice, this list of conditions and the following disclaimer.
11  *     * Redistributions in binary form must reproduce the above
12  *       copyright notice, this list of conditions and the following
13  *       disclaimer in the documentation and/or other materials provided
14  *       with the distribution.
15  *     * Neither the name OmniTI Computer Consulting, Inc. nor the names
16  *       of its contributors may be used to endorse or promote products
17  *       derived from this software without specific prior written
18  *       permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32
33 #include "noit_defines.h"
34
35 #include <unistd.h>
36 #include <errno.h>
37 #include <sys/time.h>
38 #include <sys/types.h>
39 #include <sys/socket.h>
40 #include <netinet/in.h>
41 #include <sys/un.h>
42 #include <arpa/inet.h>
43
44 #include "eventer/eventer.h"
45 #include "utils/noit_log.h"
46 #include "noit_listener.h"
47 #include "noit_conf.h"
48
49 static noit_log_stream_t nlerr = NULL;
50 static noit_log_stream_t nldeb = NULL;
51 static noit_hash_table listener_commands = NOIT_HASH_EMPTY;
52 noit_hash_table *
53 noit_listener_commands() {
54   return &listener_commands;
55 }
56
57 void
58 acceptor_closure_free(acceptor_closure_t *ac) {
59   if(ac->remote_cn) free(ac->remote_cn);
60   if(ac->service_ctx_free && ac->service_ctx)
61     ac->service_ctx_free(ac->service_ctx);
62   free(ac);
63 }
64
65 static int
66 noit_listener_accept_ssl(eventer_t e, int mask,
67                          void *closure, struct timeval *tv) {
68   int rv;
69   listener_closure_t listener_closure = (listener_closure_t)closure;
70   acceptor_closure_t *ac = NULL;
71   if(!closure) goto socketfail;
72   ac = listener_closure->dispatch_closure;
73
74   rv = eventer_SSL_accept(e, &mask);
75   if(rv > 0) {
76     eventer_ssl_ctx_t *sslctx;
77     e->callback = listener_closure->dispatch_callback;
78     /* We must make a copy of the acceptor_closure_t for each new
79      * connection.
80      */
81     if((sslctx = eventer_get_eventer_ssl_ctx(e)) != NULL) {
82       const char *cn, *end;
83       cn = eventer_ssl_get_peer_subject(sslctx);
84       if(cn && (cn = strstr(cn, "CN=")) != NULL) {
85         cn += 3;
86         end = cn;
87         while(*end && *end != '/') end++;
88         ac->remote_cn = malloc(end - cn + 1);
89         memcpy(ac->remote_cn, cn, end - cn);
90         ac->remote_cn[end-cn] = '\0';
91       }
92     }
93     e->closure = ac;
94     noitL(nlerr, "noit_listener[%s] SSL_accept on fd %d [%s]\n",
95           eventer_name_for_callback(e->callback),
96           e->fd, ac->remote_cn ? ac->remote_cn : "anonymous");
97     return e->callback(e, mask, e->closure, tv);
98   }
99   if(errno == EAGAIN) return mask|EVENTER_EXCEPTION;
100
101  socketfail:
102   if(listener_closure) free(listener_closure);
103   if(ac) acceptor_closure_free(ac);
104   eventer_remove_fd(e->fd);
105   e->opset->close(e->fd, &mask, e);
106   return 0;
107 }
108
109 static int
110 noit_listener_acceptor(eventer_t e, int mask,
111                        void *closure, struct timeval *tv) {
112   int conn, newmask = EVENTER_READ;
113   socklen_t salen;
114   listener_closure_t listener_closure = (listener_closure_t)closure;
115   acceptor_closure_t *ac = NULL;
116
117   if(mask & EVENTER_EXCEPTION) {
118  socketfail:
119     if(ac) acceptor_closure_free(ac);
120     /* We don't shut down the socket, it's out listener! */
121     return EVENTER_READ | EVENTER_WRITE | EVENTER_EXCEPTION;
122   }
123
124   do {
125     ac = malloc(sizeof(*ac));
126     memcpy(ac, listener_closure->dispatch_closure, sizeof(*ac));
127     salen = sizeof(ac->remote);
128     conn = e->opset->accept(e->fd, &ac->remote.remote_addr, &salen, &newmask, e);
129     if(conn >= 0) {
130       eventer_t newe;
131       noitL(nldeb, "noit_listener[%s] accepted fd %d\n",
132             eventer_name_for_callback(listener_closure->dispatch_callback),
133             conn);
134       if(eventer_set_fd_nonblocking(conn)) {
135         close(conn);
136         free(ac);
137         goto accept_bail;
138       }
139       newe = eventer_alloc();
140       newe->fd = conn;
141       newe->mask = EVENTER_READ | EVENTER_WRITE | EVENTER_EXCEPTION;
142  
143       if(listener_closure->sslconfig->size) {
144         const char *cert, *key, *ca, *ciphers, *crl;
145         eventer_ssl_ctx_t *ctx;
146         /* We have an SSL configuration.  While our socket accept is
147          * complete, we now have to SSL_accept, which could require
148          * several reads and writes and needs its own event callback.
149          */
150   #define SSLCONFGET(var,name) do { \
151     if(!noit_hash_retr_str(listener_closure->sslconfig, name, strlen(name), \
152                            &var)) var = NULL; } while(0)
153         SSLCONFGET(cert, "certificate_file");
154         SSLCONFGET(key, "key_file");
155         SSLCONFGET(ca, "ca_chain");
156         SSLCONFGET(ciphers, "ciphers");
157         ctx = eventer_ssl_ctx_new(SSL_SERVER, cert, key, ca, ciphers);
158         if(!ctx) {
159           newe->opset->close(newe->fd, &newmask, e);
160           eventer_free(newe);
161           goto socketfail;
162         }
163         SSLCONFGET(crl, "crl");
164         if(crl) {
165           if(!eventer_ssl_use_crl(ctx, crl)) {
166             noitL(noit_error, "Failed to load CRL from %s\n", crl);
167             eventer_ssl_ctx_free(ctx);
168             newe->opset->close(newe->fd, &newmask, e);
169             eventer_free(newe);
170             goto socketfail;
171           }
172         }
173
174         eventer_ssl_ctx_set_verify(ctx, eventer_ssl_verify_cert,
175                                    listener_closure->sslconfig);
176         EVENTER_ATTACH_SSL(newe, ctx);
177         newe->callback = noit_listener_accept_ssl;
178         newe->closure = malloc(sizeof(*listener_closure));
179         memcpy(newe->closure, listener_closure, sizeof(*listener_closure));
180         ((listener_closure_t)newe->closure)->dispatch_closure = ac;
181       }
182       else {
183         newe->callback = listener_closure->dispatch_callback;
184         /* We must make a copy of the acceptor_closure_t for each new
185          * connection.
186          */
187         newe->closure = ac;
188       }
189       eventer_add(newe);
190     }
191     else {
192       if(errno == EAGAIN) {
193         if(ac) acceptor_closure_free(ac);
194       }
195       else if(errno != EINTR) {
196         noitL(noit_error, "accept socket error: %s\n", strerror(errno));
197         goto socketfail;
198       }
199     }
200   } while(conn >= 0);
201  accept_bail:
202   return newmask | EVENTER_EXCEPTION;
203 }
204
205 int
206 noit_listener(char *host, unsigned short port, int type,
207               int backlog, noit_hash_table *sslconfig,
208               noit_hash_table *config,
209               eventer_func_t handler, void *service_ctx) {
210   int rv, fd;
211   int8_t family;
212   int sockaddr_len;
213   socklen_t reuse;
214   listener_closure_t listener_closure;
215   eventer_t event;
216   union {
217     struct in_addr addr4;
218     struct in6_addr addr6;
219   } a;
220   union {
221     struct sockaddr_in addr4;
222     struct sockaddr_in6 addr6;
223     struct sockaddr_un addru;
224   } s;
225   const char *event_name;
226
227   noitL(nldeb, "noit_listener(%s, %d, %d, %d, %s, %p)\n",
228         host, port, type, backlog,
229         (event_name = eventer_name_for_callback(handler))?event_name:"??",
230         service_ctx);
231   if(host[0] == '/') {
232     family = AF_UNIX;
233   }
234   else {
235     family = AF_INET;
236     rv = inet_pton(family, host, &a);
237     if(rv != 1) {
238       family = AF_INET6;
239       rv = inet_pton(family, host, &a);
240       if(rv != 1) {
241         if(!strcmp(host, "*")) {
242           family = AF_INET;
243           a.addr4.s_addr = INADDR_ANY;
244         } else {
245           noitL(noit_stderr, "Cannot translate '%s' to IP\n", host);
246           return -1;
247         }
248       }
249     }
250   }
251
252   fd = socket(family, type, 0);
253   if(fd < 0) {
254     noitL(noit_stderr, "Cannot create socket: %s\n", strerror(errno));
255     return -1;
256   }
257
258   if(eventer_set_fd_nonblocking(fd)) {
259     close(fd);
260     noitL(noit_stderr, "Cannot make socket non-blocking: %s\n",
261           strerror(errno));
262     return -1;
263   }
264
265   reuse = 1;
266   if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,
267                  (void*)&reuse, sizeof(reuse)) != 0) {
268     close(fd);
269     noitL(noit_stderr, "Cannot set SO_REUSEADDR: %s\n", strerror(errno));
270     return -1;
271   }
272
273   memset(&s, 0, sizeof(s));
274   if(family == AF_UNIX) {
275     struct stat sb;
276     /* unlink the path if it is a socket */
277     if(stat(host, &sb) == -1) {
278       if(errno != ENOENT) {
279         noitL(noit_stderr, "%s: %s\n", host, strerror(errno));
280         close(fd);
281         return -1;
282       }
283     }
284     else {
285       if(sb.st_mode & S_IFSOCK)
286         unlink(host);
287       else {
288         noitL(noit_stderr, "unlink %s failed: %s\n", host, strerror(errno));
289         close(fd);
290         return -1;
291       }
292     }
293     s.addru.sun_family = AF_UNIX;
294     strncpy(s.addru.sun_path, host, sizeof(s.addru.sun_path)-1);
295     sockaddr_len = sizeof(s.addru);
296   }
297   else {
298     if(family == AF_INET6) {
299       s.addr6.sin6_family = family;
300       s.addr6.sin6_port = htons(port);
301       memcpy(&s.addr6.sin6_addr, &a.addr6, sizeof(a.addr6));
302     }
303     else {
304       s.addr4.sin_family = family;
305       s.addr4.sin_port = htons(port);
306       memcpy(&s.addr4.sin_addr, &a.addr4, sizeof(a.addr4));
307     }
308     sockaddr_len = (family == AF_INET) ?  sizeof(s.addr4) : sizeof(s.addr6);
309   }
310   if(bind(fd, (struct sockaddr *)&s, sockaddr_len) < 0) {
311     noitL(noit_stderr, "bind failed[%s]: %s\n", host, strerror(errno));
312     close(fd);
313     return -1;
314   }
315
316   if(type == SOCK_STREAM) {
317     if(listen(fd, backlog) < 0) {
318       close(fd);
319       return -1;
320     }
321   }
322
323   listener_closure = calloc(1, sizeof(*listener_closure));
324   listener_closure->family = family;
325   listener_closure->port = htons(port);
326   listener_closure->sslconfig = calloc(1, sizeof(noit_hash_table));
327   noit_hash_merge_as_dict(listener_closure->sslconfig, sslconfig);
328   listener_closure->dispatch_callback = handler;
329
330   listener_closure->dispatch_closure =
331     calloc(1, sizeof(*listener_closure->dispatch_closure));
332   listener_closure->dispatch_closure->config = config;
333   listener_closure->dispatch_closure->dispatch = handler;
334   listener_closure->dispatch_closure->service_ctx = service_ctx;
335
336   event = eventer_alloc();
337   event->fd = fd;
338   event->mask = EVENTER_READ | EVENTER_EXCEPTION;
339   event->callback = noit_listener_acceptor;
340   event->closure = listener_closure;
341
342   eventer_add(event);
343   return 0;
344 }
345
346 void
347 noit_listener_reconfig(const char *toplevel) {
348   int i, cnt = 0;
349   noit_conf_section_t *listener_configs;
350   char path[256];
351
352   snprintf(path, sizeof(path), "/%s/listeners//listener",
353            toplevel ? toplevel : "*");
354   listener_configs = noit_conf_get_sections(NULL, path, &cnt);
355   noitL(noit_stderr, "Found %d %s stanzas\n", cnt, path);
356   for(i=0; i<cnt; i++) {
357     char address[256];
358     char type[256];
359     unsigned short port;
360     int portint;
361     int backlog;
362     eventer_func_t f;
363     noit_boolean ssl;
364     noit_hash_table *sslconfig, *config;
365
366     if(!noit_conf_get_stringbuf(listener_configs[i],
367                                 "ancestor-or-self::node()/@type",
368                                 type, sizeof(type))) {
369       noitL(noit_stderr, "No type specified in listener stanza %d\n", i+1);
370       continue;
371     }
372     f = eventer_callback_for_name(type);
373     if(!f) {
374       noitL(noit_stderr,
375             "Cannot find handler for listener type: '%s'\n", type);
376       continue;
377     }
378     if(!noit_conf_get_stringbuf(listener_configs[i],
379                                 "ancestor-or-self::node()/@address",
380                                 address, sizeof(address))) {
381       address[0] = '*';
382       address[1] = '\0';
383     }
384     if(!noit_conf_get_int(listener_configs[i],
385                           "ancestor-or-self::node()/@port", &portint))
386       portint = 0;
387     port = (unsigned short) portint;
388     if(address[0] != '/' && (portint == 0 || (port != portint))) {
389       /* UNIX sockets don't require a port (they'll ignore it if specified */
390       noitL(noit_stderr,
391             "Invalid port [%d] specified in stanza %d\n", port, i+1);
392       continue;
393     }
394     if(!noit_conf_get_int(listener_configs[i],
395                           "ancestor-or-self::node()/@backlog", &backlog))
396       backlog = 5;
397
398     if(!noit_conf_get_boolean(listener_configs[i],
399                               "ancestor-or-self::node()/@ssl", &ssl))
400      ssl = noit_false;
401
402     sslconfig = ssl ?
403                   noit_conf_get_hash(listener_configs[i], "sslconfig") :
404                   NULL;
405     config = noit_conf_get_hash(listener_configs[i], "config");
406
407     if(noit_listener(address, port, SOCK_STREAM, backlog,
408                      sslconfig, config, f, NULL) != 0) {
409       noit_hash_destroy(config,free,free);
410       free(config);
411     }
412     if(sslconfig) {
413       /* A copy of this is made within noit_listener */
414       noit_hash_destroy(sslconfig,free,free);
415       free(sslconfig);
416     }
417   }
418   free(listener_configs);
419 }
420 int
421 noit_control_dispatch(eventer_t e, int mask, void *closure,
422                       struct timeval *now) {
423   u_int32_t cmd;
424   int len;
425   void *vdelegation_table;
426   noit_hash_table *delegation_table = NULL;
427   acceptor_closure_t *ac = closure;
428
429   len = e->opset->read(e->fd, &cmd, sizeof(cmd), &mask, e);
430
431   if(len == -1 && errno == EAGAIN)
432     return EVENTER_READ | EVENTER_EXCEPTION;
433
434   if(mask & EVENTER_EXCEPTION || len != sizeof(cmd)) {
435     int newmask;
436 socket_error:
437     /* Exceptions cause us to simply snip the connection */
438     eventer_remove_fd(e->fd);
439     e->opset->close(e->fd, &newmask, e);
440     if(ac) acceptor_closure_free(ac);
441     return 0;
442   }
443
444   ac->cmd = ntohl(cmd);
445   /* Lookup cmd and dispatch */
446   if(noit_hash_retrieve(&listener_commands,
447                         (char *)&ac->dispatch, sizeof(ac->dispatch),
448                         (void **)&vdelegation_table)) {
449     void *vfunc;
450     delegation_table = (noit_hash_table *)vdelegation_table;
451     if(noit_hash_retrieve(delegation_table,
452                           (char *)&ac->cmd, sizeof(ac->cmd), &vfunc)) {
453       e->callback = *((eventer_func_t *)vfunc);
454       return e->callback(e, mask, closure, now);
455     }
456     else {
457     const char *event_name;
458       noitL(noit_error, "listener (%s %p) has no command: 0x%8x\n",
459             (event_name = eventer_name_for_callback(ac->dispatch))?event_name:"???",
460             delegation_table, cmd);
461     }
462   }
463   else {
464     const char *event_name;
465     noitL(noit_error, "No delegation table for listener (%s %p)\n",
466           (event_name = eventer_name_for_callback(ac->dispatch))?event_name:"???",
467           delegation_table);
468   }
469   goto socket_error;
470 }
471 void
472 noit_control_dispatch_delegate(eventer_func_t listener_dispatch,
473                                u_int32_t cmd,
474                                eventer_func_t delegate_dispatch) {
475   u_int32_t *cmd_copy;
476   eventer_func_t *handler_copy;
477   void *vdelegation_table;
478   noit_hash_table *delegation_table;
479   if(!noit_hash_retrieve(&listener_commands,
480                          (char *)&listener_dispatch, sizeof(listener_dispatch),
481                          &vdelegation_table)) {
482     delegation_table = calloc(1, sizeof(*delegation_table));
483     handler_copy = malloc(sizeof(*handler_copy));
484     *handler_copy = listener_dispatch;
485     noit_hash_store(&listener_commands,
486                     (char *)handler_copy, sizeof(*handler_copy),
487                     delegation_table);
488   }
489   else
490     delegation_table = (noit_hash_table *)vdelegation_table;
491
492   cmd_copy = malloc(sizeof(*cmd_copy));
493   *cmd_copy = cmd;
494   handler_copy = malloc(sizeof(*handler_copy));
495   *handler_copy = delegate_dispatch;
496   noit_hash_replace(delegation_table,
497                     (char *)cmd_copy, sizeof(*cmd_copy),
498                     handler_copy,
499                     free, free);
500 }
501
502 int
503 noit_convert_sockaddr_to_buff(char *buff, int blen, struct sockaddr *remote) {
504   char name[128] = "";
505   buff[0] = '\0';
506   if(remote) {
507     int len = 0;
508     switch(remote->sa_family) {
509       case AF_INET:
510         len = sizeof(struct sockaddr_in);
511         inet_ntop(remote->sa_family, &((struct sockaddr_in *)remote)->sin_addr,
512                   name, len);
513         break;
514       case AF_INET6:
515        len = sizeof(struct sockaddr_in6);
516         inet_ntop(remote->sa_family, &((struct sockaddr_in6 *)remote)->sin6_addr,
517                   name, len);
518        break;
519       case AF_UNIX:
520         snprintf(name, sizeof(name), "%s", ((struct sockaddr_un *)remote)->sun_path);
521         break;
522       default: return 0;
523     }
524   }
525   strlcpy(buff, name, blen);
526   return strlen(buff);
527 }
528
529 void
530 noit_listener_init(const char *toplevel) {
531   nlerr = noit_log_stream_find("error/listener");
532   nldeb = noit_log_stream_find("debug/listener");
533   if(!nlerr) nlerr = noit_error;
534   if(!nldeb) nldeb = noit_debug;
535   eventer_name_callback("noit_listener_acceptor", noit_listener_acceptor);
536   eventer_name_callback("noit_listener_accept_ssl", noit_listener_accept_ssl);
537   eventer_name_callback("control_dispatch", noit_control_dispatch);
538   noit_listener_reconfig(toplevel);
539 }
540
Note: See TracBrowser for help on using the browser.