root/src/noit_listener.c

Revision 4c963d7e24928576cb0e4a600c35e964b4ba5cca, 10.0 kB (checked in by Theo Schlossnagle <jesus@omniti.com>, 6 years ago)

write the eventer... checks are working, but the telnet console is not, refs #32

  • Property mode set to 100644
Line 
1 /*
2  * Copyright (c) 2007, OmniTI Computer Consulting, Inc.
3  * All rights reserved.
4  */
5
6 #include "noit_defines.h"
7
8 #include <unistd.h>
9 #include <errno.h>
10 #include <sys/time.h>
11 #include <sys/types.h>
12 #include <sys/socket.h>
13 #include <sys/ioctl.h>
14 #include <netinet/in.h>
15 #include <sys/un.h>
16 #include <arpa/inet.h>
17
18 #include "eventer/eventer.h"
19 #include "utils/noit_log.h"
20 #include "noit_listener.h"
21 #include "noit_conf.h"
22
23 void
24 acceptor_closure_free(acceptor_closure_t *ac) {
25   if(ac->remote_cn) free(ac->remote_cn);
26   free(ac);
27 }
28
29 static int
30 noit_listener_accept_ssl(eventer_t e, int mask,
31                          void *closure, struct timeval *tv) {
32   int rv;
33   listener_closure_t listener_closure = (listener_closure_t)closure;
34   acceptor_closure_t *ac = NULL;
35   if(!closure) goto socketfail;
36   ac = listener_closure->dispatch_closure;
37
38   rv = eventer_SSL_accept(e, &mask);
39   if(rv > 0) {
40     eventer_ssl_ctx_t *sslctx;
41     e->callback = listener_closure->dispatch_callback;
42     /* We must make a copy of the acceptor_closure_t for each new
43      * connection.
44      */
45     if((sslctx = eventer_get_eventer_ssl_ctx(e)) != NULL) {
46       char *cn, *end;
47       cn = eventer_ssl_get_peer_subject(sslctx);
48       if(cn && (cn = strstr(cn, "CN=")) != NULL) {
49         cn += 3;
50         end = cn;
51         while(*end && *end != '/') end++;
52         ac->remote_cn = malloc(end - cn + 1);
53         memcpy(ac->remote_cn, cn, end - cn);
54         ac->remote_cn[end-cn] = '\0';
55       }
56     }
57     e->closure = ac;
58     return e->callback(e, mask, e->closure, tv);
59   }
60   if(errno == EAGAIN) return mask|EVENTER_EXCEPTION;
61
62  socketfail:
63   if(listener_closure) free(listener_closure);
64   if(ac) acceptor_closure_free(ac);
65   eventer_remove_fd(e->fd);
66   e->opset->close(e->fd, &mask, e);
67   return 0;
68 }
69
70 static int
71 noit_listener_acceptor(eventer_t e, int mask,
72                        void *closure, struct timeval *tv) {
73   int conn, newmask = EVENTER_READ;
74   socklen_t salen;
75   listener_closure_t listener_closure = (listener_closure_t)closure;
76   acceptor_closure_t *ac = NULL;
77
78   if(mask & EVENTER_EXCEPTION) {
79  socketfail:
80     if(ac) acceptor_closure_free(ac);
81     eventer_remove_fd(e->fd);
82     e->opset->close(e->fd, &mask, e);
83     return 0;
84   }
85
86   ac = malloc(sizeof(*ac));
87   memcpy(ac, listener_closure->dispatch_closure, sizeof(*ac));
88   salen = sizeof(ac->remote);
89   conn = e->opset->accept(e->fd, &ac->remote.remote_addr, &salen, &newmask, e);
90   if(conn >= 0) {
91     socklen_t on = 1;
92     eventer_t newe;
93     if(ioctl(conn, FIONBIO, &on)) {
94       close(conn);
95       goto accept_bail;
96     }
97     newe = eventer_alloc();
98     newe->fd = conn;
99     newe->mask = EVENTER_READ | EVENTER_WRITE | EVENTER_EXCEPTION;
100
101     if(listener_closure->sslconfig->size) {
102       char *cert, *key, *ca, *ciphers;
103       eventer_ssl_ctx_t *ctx;
104       /* We have an SSL configuration.  While our socket accept is
105        * complete, we now have to SSL_accept, which could require
106        * several reads and writes and needs its own event callback.
107        */
108 #define SSLCONFGET(var,name) do { \
109   if(!noit_hash_retrieve(listener_closure->sslconfig, name, strlen(name), \
110                          (void **)&var)) var = NULL; } while(0)
111       SSLCONFGET(cert, "certificate_file");
112       SSLCONFGET(key, "key_file");
113       SSLCONFGET(ca, "ca_chain");
114       SSLCONFGET(ciphers, "ciphers");
115       ctx = eventer_ssl_ctx_new(SSL_SERVER, cert, key, ca, ciphers);
116       if(!ctx) {
117         eventer_free(newe);
118         goto socketfail;
119       }
120       eventer_ssl_ctx_set_verify(ctx, eventer_ssl_verify_cert,
121                                  listener_closure->sslconfig);
122       EVENTER_ATTACH_SSL(newe, ctx);
123       newe->callback = noit_listener_accept_ssl;
124       newe->closure = malloc(sizeof(*listener_closure));
125       memcpy(newe->closure, listener_closure, sizeof(*listener_closure));
126       ((listener_closure_t)newe->closure)->dispatch_closure = ac;
127     }
128     else {
129       newe->callback = listener_closure->dispatch_callback;
130       /* We must make a copy of the acceptor_closure_t for each new
131        * connection.
132        */
133       newe->closure = ac;
134     }
135     eventer_add(newe);
136   }
137  accept_bail:
138   return newmask | EVENTER_EXCEPTION;
139 }
140
141 int
142 noit_listener(char *host, unsigned short port, int type,
143               int backlog, noit_hash_table *sslconfig,
144               noit_hash_table *config,
145               eventer_func_t handler, void *service_ctx) {
146   int rv, fd;
147   int8_t family;
148   int sockaddr_len;
149   socklen_t on, reuse;
150   listener_closure_t listener_closure;
151   eventer_t event;
152   union {
153     struct in_addr addr4;
154     struct in6_addr addr6;
155   } a;
156   union {
157     struct sockaddr_in addr4;
158     struct sockaddr_in6 addr6;
159     struct sockaddr_un addru;
160   } s;
161   const char *event_name;
162
163   noitL(noit_debug, "noit_listener(%s, %d, %d, %d, %s, %p)\n",
164         host, port, type, backlog,
165         (event_name = eventer_name_for_callback(handler))?event_name:"??",
166         service_ctx);
167   if(host[0] == '/') {
168     family = AF_UNIX;
169   }
170   else {
171     family = AF_INET;
172     rv = inet_pton(family, host, &a);
173     if(rv != 1) {
174       family = AF_INET6;
175       rv = inet_pton(family, host, &a);
176       if(rv != 1) {
177         if(!strcmp(host, "*")) {
178           family = AF_INET;
179           a.addr4.s_addr = INADDR_ANY;
180         } else {
181           noitL(noit_stderr, "Cannot translate '%s' to IP\n", host);
182           return -1;
183         }
184       }
185     }
186   }
187
188   fd = socket(family, type, 0);
189   if(fd < 0) {
190     noitL(noit_stderr, "Cannot create socket: %s\n", strerror(errno));
191     return -1;
192   }
193
194   on = 1;
195   if(ioctl(fd, FIONBIO, &on)) {
196     close(fd);
197     noitL(noit_stderr, "Cannot make socket non-blocking: %s\n",
198           strerror(errno));
199     return -1;
200   }
201
202   reuse = 1;
203   if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,
204                  (void*)&reuse, sizeof(reuse)) != 0) {
205     close(fd);
206     noitL(noit_stderr, "Cannot set SO_REUSEADDR: %s\n", strerror(errno));
207     return -1;
208   }
209
210   memset(&s, 0, sizeof(s));
211   if(family == AF_UNIX) {
212     struct stat sb;
213     /* unlink the path iff it is a socket */
214     if(stat(host, &sb) == -1) {
215       if(errno != ENOENT) {
216         noitL(noit_stderr, "%s: %s\n", host, strerror(errno));
217         close(fd);
218         return -1;
219       }
220     }
221     else {
222       if(sb.st_mode & S_IFSOCK)
223         unlink(host);
224       else {
225         noitL(noit_stderr, "unlink %s failed: %s\n", host, strerror(errno));
226         close(fd);
227         return -1;
228       }
229     }
230     strncpy(s.addru.sun_path, host, sizeof(s.addru.sun_path)-1);
231     sockaddr_len = sizeof(s.addru);
232   }
233   else {
234     s.addr6.sin6_family = family;
235     s.addr6.sin6_port = htons(port);
236     memcpy(&s.addr6.sin6_addr, &a, sizeof(a));
237     sockaddr_len = (family == AF_INET) ?  sizeof(s.addr4) : sizeof(s.addr6);
238   }
239   if(bind(fd, (struct sockaddr *)&s, sockaddr_len) < 0) {
240     noitL(noit_stderr, "bind failed[%s]: %s\n", host, strerror(errno));
241     close(fd);
242     return -1;
243   }
244
245   if(type == SOCK_STREAM) {
246     if(listen(fd, backlog) < 0) {
247       close(fd);
248       return -1;
249     }
250   }
251
252   listener_closure = calloc(1, sizeof(*listener_closure));
253   listener_closure->family = family;
254   listener_closure->port = htons(port);
255   listener_closure->sslconfig = calloc(1, sizeof(noit_hash_table));
256   noit_hash_merge_as_dict(listener_closure->sslconfig, sslconfig);
257   listener_closure->dispatch_callback = handler;
258
259   listener_closure->dispatch_closure =
260     calloc(1, sizeof(*listener_closure->dispatch_closure));
261   listener_closure->dispatch_closure->config = config;
262   listener_closure->dispatch_closure->service_ctx = service_ctx;
263
264   event = eventer_alloc();
265   event->fd = fd;
266   event->mask = EVENTER_READ | EVENTER_EXCEPTION;
267   event->callback = noit_listener_acceptor;
268   event->closure = listener_closure;
269
270   eventer_add(event);
271   return 0;
272 }
273
274 void
275 noit_listener_reconfig(const char *toplevel) {
276   int i, cnt = 0;
277   noit_conf_section_t *listener_configs;
278   char path[256];
279
280   snprintf(path, sizeof(path), "/%s/listeners//listener",
281            toplevel ? toplevel : "*");
282   listener_configs = noit_conf_get_sections(NULL, path, &cnt);
283   noitL(noit_stderr, "Found %d %s stanzas\n", cnt, path);
284   for(i=0; i<cnt; i++) {
285     char address[256];
286     char type[256];
287     unsigned short port;
288     int portint;
289     int backlog;
290     eventer_func_t f;
291     noit_conf_boolean ssl;
292     noit_hash_table *sslconfig, *config;
293
294     if(!noit_conf_get_stringbuf(listener_configs[i],
295                                 "ancestor-or-self::node()/@type",
296                                 type, sizeof(type))) {
297       noitL(noit_stderr, "No type specified in listener stanza %d\n", i+1);
298       continue;
299     }
300     f = eventer_callback_for_name(type);
301     if(!f) {
302       noitL(noit_stderr,
303             "Cannot find handler for listener type: '%s'\n", type);
304       continue;
305     }
306     if(!noit_conf_get_stringbuf(listener_configs[i],
307                                 "ancestor-or-self::node()/@address",
308                                 address, sizeof(address))) {
309       address[0] = '*';
310       address[1] = '\0';
311     }
312     if(!noit_conf_get_int(listener_configs[i],
313                           "ancestor-or-self::node()/@port", &portint))
314       portint = 0;
315     port = (unsigned short) portint;
316     if(address[0] != '/' && (portint == 0 || (port != portint))) {
317       /* UNIX sockets don't require a port (they'll ignore it if specified */
318       noitL(noit_stderr,
319             "Invalid port [%d] specified in stanza %d\n", port, i+1);
320       continue;
321     }
322     if(!noit_conf_get_int(listener_configs[i],
323                           "ancestor-or-self::node()/@backlog", &backlog))
324       backlog = 5;
325
326     if(!noit_conf_get_boolean(listener_configs[i],
327                               "ancestor-or-self::node()/@ssl", &ssl))
328      ssl = noit_false;
329
330     sslconfig = ssl ?
331                   noit_conf_get_hash(listener_configs[i], "sslconfig") :
332                   NULL;
333     config = noit_conf_get_hash(listener_configs[i], "config");
334
335     noit_listener(address, port, SOCK_STREAM, backlog,
336                   sslconfig, config, f, NULL);
337   }
338 }
339 void
340 noit_listener_init(const char *toplevel) {
341   eventer_name_callback("noit_listener_acceptor", noit_listener_acceptor);
342   eventer_name_callback("noit_listener_accept_ssl", noit_listener_accept_ssl);
343   noit_listener_reconfig(toplevel);
344 }
345
Note: See TracBrowser for help on using the browser.