jabberd2  2.7.0
main.c
Go to the documentation of this file.
1 /*
2  * jabberd - Jabber Open Source Server
3  * Copyright (c) 2002 Jeremie Miller, Thomas Muldowney,
4  * Ryan Eatmon, Robert Norris
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., 59 Temple Place, Suite 330, Boston, MA02111-1307USA
19  */
20 
21 #include "s2s.h"
22 
23 #include <stringprep.h>
24 #include <unistd.h>
25 #ifdef HAVE_SSL
26 #include <openssl/rand.h>
27 #endif
28 
29 static sig_atomic_t s2s_shutdown = 0;
30 sig_atomic_t s2s_lost_router = 0;
31 static sig_atomic_t s2s_logrotate = 0;
32 
33 static void _s2s_signal(int signum) {
34  s2s_shutdown = 1;
35  s2s_lost_router = 0;
36 }
37 
38 static void _s2s_signal_hup(int signum) {
39  s2s_logrotate = 1;
40 }
41 
42 static void _s2s_signal_usr1(int signum)
43 {
44  set_debug_flag(0);
45 }
46 
47 static void _s2s_signal_usr2(int signum)
48 {
49  set_debug_flag(1);
50 }
51 
52 static int _s2s_populate_whitelist_domains(s2s_t s2s, const char **values, int nvalues);
53 
54 
56 static void _s2s_pidfile(s2s_t s2s) {
57  const char *pidfile;
58  FILE *f;
59  pid_t pid;
60 
61  pidfile = config_get_one(s2s->config, "pidfile", 0);
62  if(pidfile == NULL)
63  return;
64 
65  pid = getpid();
66 
67  if((f = fopen(pidfile, "w+")) == NULL) {
68  log_write(s2s->log, LOG_ERR, "couldn't open %s for writing: %s", pidfile, strerror(errno));
69  return;
70  }
71 
72  if(fprintf(f, "%d", pid) < 0) {
73  log_write(s2s->log, LOG_ERR, "couldn't write to %s: %s", pidfile, strerror(errno));
74  fclose(f);
75  return;
76  }
77 
78  fclose(f);
79 
80  log_write(s2s->log, LOG_INFO, "process id is %d, written to %s", pid, pidfile);
81 }
82 
84 static void _s2s_config_expand(s2s_t s2s) {
85  char *str, secret[41];
86  config_elem_t elem;
87  int i, r;
88 
90 
91  s2s->id = config_get_one(s2s->config, "id", 0);
92  if(s2s->id == NULL)
93  s2s->id = "s2s";
94 
95  s2s->router_ip = config_get_one(s2s->config, "router.ip", 0);
96  if(s2s->router_ip == NULL)
97  s2s->router_ip = "127.0.0.1";
98 
99  s2s->router_port = j_atoi(config_get_one(s2s->config, "router.port", 0), 5347);
100 
101  s2s->router_user = config_get_one(s2s->config, "router.user", 0);
102  if(s2s->router_user == NULL)
103  s2s->router_user = "jabberd";
104  s2s->router_pass = config_get_one(s2s->config, "router.pass", 0);
105  if(s2s->router_pass == NULL)
106  s2s->router_pass = "secret";
107 
108  s2s->router_pemfile = config_get_one(s2s->config, "router.pemfile", 0);
109 
110  s2s->router_cachain = config_get_one(s2s->config, "router.cachain", 0);
111 
112  s2s->router_private_key_password = config_get_one(s2s->config, "router.private_key_password", 0);
113  s2s->router_ciphers = config_get_one(s2s->config, "router.ciphers", 0);
114 
115  s2s->retry_init = j_atoi(config_get_one(s2s->config, "router.retry.init", 0), 3);
116  s2s->retry_lost = j_atoi(config_get_one(s2s->config, "router.retry.lost", 0), 3);
117  if((s2s->retry_sleep = j_atoi(config_get_one(s2s->config, "router.retry.sleep", 0), 2)) < 1)
118  s2s->retry_sleep = 1;
119 
120  s2s->router_default = config_count(s2s->config, "router.non-default") ? 0 : 1;
121 
122  s2s->log_type = log_STDOUT;
123  if(config_get(s2s->config, "log") != NULL) {
124  if((str = config_get_attr(s2s->config, "log", 0, "type")) != NULL) {
125  if(strcmp(str, "file") == 0)
126  s2s->log_type = log_FILE;
127  else if(strcmp(str, "syslog") == 0)
128  s2s->log_type = log_SYSLOG;
129  }
130  }
131 
132  if(s2s->log_type == log_SYSLOG) {
133  s2s->log_facility = config_get_one(s2s->config, "log.facility", 0);
134  s2s->log_ident = config_get_one(s2s->config, "log.ident", 0);
135  if(s2s->log_ident == NULL)
136  s2s->log_ident = "jabberd/s2s";
137  } else if(s2s->log_type == log_FILE)
138  s2s->log_ident = config_get_one(s2s->config, "log.file", 0);
139 
140  s2s->packet_stats = config_get_one(s2s->config, "stats.packet", 0);
141 
142  s2s->local_ip = config_get_one(s2s->config, "local.ip", 0);
143  if(s2s->local_ip == NULL)
144  s2s->local_ip = "0.0.0.0";
145  if((elem = config_get(s2s->config, "local.origins.ip")) != NULL) {
146  s2s->origin_ips = elem->values;
147  s2s->origin_nips = elem->nvalues;
148  }
149 
150  s2s->local_port = j_atoi(config_get_one(s2s->config, "local.port", 0), 0);
151 
152  if(config_get(s2s->config, "local.secret") != NULL)
153  s2s->local_secret = strdup(config_get_one(s2s->config, "local.secret", 0));
154  else {
155 #ifdef HAVE_SSL
156  if (!RAND_bytes(secret, 40)) {
157  log_write(s2s->log, LOG_ERR, "Failed to pull 40 RAND_bytes");
158  exit(1);
159  }
160 #else
161 # warning "Using unsecure random number generator for dialback keys"
162  log_write(s2s->log, LOG_WARNING, "Using unsecure random number generator for dialback keys - set local.secret to a random string!");
163 #endif
164  for(i = 0; i < 40; i++) {
165 #ifdef HAVE_SSL
166  r = (int) (36.0 * secret[i] / 255);
167 #else
168  r = (int) (36.0 * rand() / RAND_MAX);
169 #endif
170  secret[i] = (r >= 0 && r <= 9) ? (r + 48) : (r + 87);
171  }
172  secret[40] = '\0';
173  s2s->local_secret = strdup(secret);
174  }
175 
176  if(s2s->local_secret == NULL)
177  s2s->local_secret = "secret";
178 
179  s2s->local_pemfile = config_get_one(s2s->config, "local.pemfile", 0);
180  s2s->local_cachain = config_get_one(s2s->config, "local.cachain", 0);
181  s2s->local_verify_mode = j_atoi(config_get_one(s2s->config, "local.verify-mode", 0), 0);
182  s2s->local_private_key_password = config_get_one(s2s->config, "local.private_key_password", 0);
183  s2s->local_ciphers = config_get_one(s2s->config, "local.ciphers", 0);
184 
185  s2s->io_max_fds = j_atoi(config_get_one(s2s->config, "io.max_fds", 0), 1024);
186 
187  s2s->compression = (config_get(s2s->config, "io.compression") != NULL);
188 
189  s2s->stanza_size_limit = j_atoi(config_get_one(s2s->config, "io.limits.stanzasize", 0), 0);
190  s2s->require_tls = j_atoi(config_get_one(s2s->config, "security.require_tls", 0), 0);
191  s2s->enable_whitelist = j_atoi(config_get_one(s2s->config, "security.enable_whitelist", 0), 0);
192  if((elem = config_get(s2s->config, "security.whitelist_domain")) != NULL) {
194  }
195 
196  s2s->check_interval = j_atoi(config_get_one(s2s->config, "check.interval", 0), 60);
197  s2s->check_queue = j_atoi(config_get_one(s2s->config, "check.queue", 0), 60);
198  s2s->check_keepalive = j_atoi(config_get_one(s2s->config, "check.keepalive", 0), 0);
199  s2s->check_idle = j_atoi(config_get_one(s2s->config, "check.idle", 0), 86400);
200  s2s->check_dnscache = j_atoi(config_get_one(s2s->config, "check.dnscache", 0), 300);
201  s2s->retry_limit = j_atoi(config_get_one(s2s->config, "check.retry", 0), 300);
202 
203  if((elem = config_get(s2s->config, "lookup.srv")) != NULL) {
204  s2s->lookup_srv = elem->values;
205  s2s->lookup_nsrv = elem->nvalues;
206  }
207 
208  s2s->resolve_aaaa = config_count(s2s->config, "lookup.resolve-ipv6") ? 1 : 0;
209  s2s->dns_cache_enabled = config_count(s2s->config, "lookup.no-cache") ? 0 : 1;
210  s2s->dns_bad_timeout = j_atoi(config_get_one(s2s->config, "lookup.bad-host-timeout", 0), 3600);
211  s2s->dns_min_ttl = j_atoi(config_get_one(s2s->config, "lookup.min-ttl", 0), 30);
212  if (s2s->dns_min_ttl < 5)
213  s2s->dns_min_ttl = 5;
214  s2s->dns_max_ttl = j_atoi(config_get_one(s2s->config, "lookup.max-ttl", 0), 86400);
215  s2s->etc_hosts_ttl = j_atoi(config_get_one(s2s->config, "lookup.etc-hosts-ttl", 0), 86400);
216  s2s->out_reuse = config_count(s2s->config, "out-conn-reuse") ? 1 : 0;
217 }
218 
219 static void _s2s_hosts_expand(s2s_t s2s)
220 {
221  char *realm;
222  config_elem_t elem;
223  char id[1024];
224  int i;
225 
226  elem = config_get(s2s->config, "local.id");
227 
228  if (elem) for(i = 0; i < elem->nvalues; i++) {
229  host_t host = (host_t) pmalloco(xhash_pool(s2s->hosts), sizeof(struct host_st));
230  if(!host) {
231  log_write(s2s->log, LOG_ERR, "cannot allocate memory for new host, aborting");
232  exit(1);
233  }
234 
235  realm = j_attr((const char **) elem->attrs[i], "realm");
236 
237  /* stringprep ids (domain names) so that they are in canonical form */
238  strncpy(id, elem->values[i], 1024);
239  id[1023] = '\0';
240  if (stringprep_nameprep(id, 1024) != 0) {
241  log_write(s2s->log, LOG_ERR, "cannot stringprep id %s, aborting", id);
242  exit(1);
243  }
244 
245  host->realm = (realm != NULL) ? realm : pstrdup(xhash_pool(s2s->hosts), id);
246 
247  host->host_pemfile = j_attr((const char **) elem->attrs[i], "pemfile");
248 
249  host->host_cachain = j_attr((const char **) elem->attrs[i], "cachain");
250 
251  host->host_verify_mode = j_atoi(j_attr((const char **) elem->attrs[i], "verify-mode"), 0);
252 
253  host->host_private_key_password = j_attr((const char **) elem->attrs[i], "private-key-password");
254 
255  host->host_ciphers = j_attr((const char **) elem->attrs[i], "ciphers");
256 
257 #ifdef HAVE_SSL
258  if(host->host_pemfile != NULL) {
259  if(s2s->sx_ssl == NULL) {
261  if(s2s->sx_ssl == NULL) {
262  log_write(s2s->log, LOG_ERR, "failed to load %s SSL pemfile", host->realm);
263  host->host_pemfile = NULL;
264  }
265  } else {
266  if(sx_ssl_server_addcert(s2s->sx_ssl, host->realm, host->host_pemfile, host->host_cachain, host->host_verify_mode, host->host_private_key_password, host->host_ciphers) != 0) {
267  log_write(s2s->log, LOG_ERR, "failed to load %s SSL pemfile", host->realm);
268  host->host_pemfile = NULL;
269  }
270  }
271  }
272 #endif
273 
274  /* insert into vHosts xhash */
275  xhash_put(s2s->hosts, pstrdup(xhash_pool(s2s->hosts), id), host);
276 
277  log_write(s2s->log, LOG_NOTICE, "[%s] configured; realm=%s", id, host->realm);
278  }
279 }
280 
281 static int _s2s_router_connect(s2s_t s2s) {
282  log_write(s2s->log, LOG_NOTICE, "attempting connection to router at %s, port=%d", s2s->router_ip, s2s->router_port);
283 
284  s2s->fd = mio_connect(s2s->mio, s2s->router_port, s2s->router_ip, NULL, s2s_router_mio_callback, (void *) s2s);
285  if(s2s->fd == NULL) {
286  if(errno == ECONNREFUSED)
287  s2s_lost_router = 1;
288  log_write(s2s->log, LOG_NOTICE, "connection attempt to router failed: %s (%d)", MIO_STRERROR(MIO_ERROR), MIO_ERROR);
289  return 1;
290  }
291 
292  s2s->router = sx_new(s2s->sx_env, s2s->fd->fd, s2s_router_sx_callback, (void *) s2s);
293  sx_client_init(s2s->router, 0, NULL, NULL, NULL, "1.0");
294 
295  return 0;
296 }
297 
298 int _s2s_check_conn_routes(s2s_t s2s, conn_t conn, const char *direction)
299 {
300  char *rkey;
301  int rkeylen;
302  conn_state_t state;
303  time_t now, dialback_time;
304 
305  now = time(NULL);
306 
307  if(xhash_iter_first(conn->states))
308  do {
309  /* retrieve state in a separate operation, as sizeof(int) != sizeof(void *) on 64-bit platforms,
310  so passing a pointer to state in xhash_iter_get is unsafe */
311  xhash_iter_get(conn->states, (const char **) &rkey, &rkeylen, NULL);
312  state = (conn_state_t) xhash_getx(conn->states, rkey, rkeylen);
313 
314  if (state == conn_INPROGRESS) {
315  dialback_time = (time_t) xhash_getx(conn->states_time, rkey, rkeylen);
316 
317  if(now > dialback_time + s2s->check_queue) {
318  log_write(s2s->log, LOG_NOTICE, "[%d] [%s, port=%d] dialback for %s route '%.*s' timed out", conn->fd->fd, conn->ip, conn->port, direction, rkeylen, rkey);
319 
320  xhash_zapx(conn->states, rkey, rkeylen);
321  xhash_zapx(conn->states_time, rkey, rkeylen);
322 
323  /* stream error */
324  sx_error(conn->s, stream_err_CONNECTION_TIMEOUT, "dialback timed out");
325 
326  /* close connection as per XMPP/RFC3920 */
327  sx_close(conn->s);
328 
329  /* indicate that we closed the connection */
330  return 0;
331  }
332  }
333  } while(xhash_iter_next(conn->states));
334 
335  /* all ok */
336  return 1;
337 }
338 
339 static void _s2s_time_checks(s2s_t s2s) {
340  conn_t conn;
341  time_t now;
342  char *rkey, *key;
343  int keylen;
344  jqueue_t q;
345  dnscache_t dns;
346  char *c;
347  int c_len;
348  union xhashv xhv;
349 
350  now = time(NULL);
351 
352  /* queue expiry */
353  if(s2s->check_queue > 0) {
354  if(xhash_iter_first(s2s->outq))
355  do {
356  xhv.jq_val = &q;
357  xhash_iter_get(s2s->outq, (const char **) &rkey, &keylen, xhv.val);
358 
359  log_debug(ZONE, "running time checks for %.*s", keylen, rkey);
360  c = memchr(rkey, '/', keylen);
361  c++;
362  c_len = keylen - (c - rkey);
363 
364  /* dns lookup timeout check first */
365  dns = xhash_getx(s2s->dnscache, c, c_len);
366  if(dns != NULL && dns->pending) {
367  log_debug(ZONE, "dns lookup pending for %.*s", c_len, c);
368  if(now > dns->init_time + s2s->check_queue) {
369  log_write(s2s->log, LOG_NOTICE, "dns lookup for %.*s timed out", c_len, c);
370 
371  /* bounce queue */
373 
374  /* expire pending dns entry */
375  xhash_zap(s2s->dnscache, dns->name);
376  xhash_free(dns->results);
377  if (dns->query != NULL) {
378  if (dns->query->query != NULL)
379  dns_cancel(NULL, dns->query->query);
380  xhash_free(dns->query->hosts);
381  xhash_free(dns->query->results);
382  free((void*)dns->query->name);
383  free(dns->query);
384  }
385  free(dns);
386  }
387 
388  continue;
389  }
390 
391  /* get the conn */
392  conn = xhash_getx(s2s->out_dest, c, c_len);
393  if(conn == NULL) {
394  if(jqueue_size(q) > 0) {
395  /* no pending conn? perhaps it failed? */
396  log_debug(ZONE, "no pending connection for %.*s, bouncing %i packets in queue", c_len, c, jqueue_size(q));
397 
398  /* bounce queue */
400  }
401 
402  continue;
403  }
404 
405  /* connect timeout check */
406  if(!conn->online && now > conn->init_time + s2s->check_queue) {
407  dnsres_t bad;
408  char *ipport;
409 
410  log_write(s2s->log, LOG_NOTICE, "[%d] [%s, port=%d] connection to %s timed out", conn->fd->fd, conn->ip, conn->port, c);
411 
412  if (s2s->dns_bad_timeout > 0) {
413  /* mark this host as bad */
414  ipport = dns_make_ipport(conn->ip, conn->port);
415  bad = xhash_get(s2s->dns_bad, ipport);
416  if (bad == NULL) {
417  bad = (dnsres_t) calloc(1, sizeof(struct dnsres_st));
418  bad->key = ipport;
419  xhash_put(s2s->dns_bad, ipport, bad);
420  } else {
421  free(ipport);
422  }
423  bad->expiry = time(NULL) + s2s->dns_bad_timeout;
424  }
425 
426  /* close connection as per XMPP/RFC3920 */
427  /* the close function will retry or bounce the queue */
428  sx_close(conn->s);
429  }
430  } while(xhash_iter_next(s2s->outq));
431  }
432 
433  /* expiry of connected routes in conn_INPROGRESS state */
434  if(s2s->check_queue > 0) {
435 
436  /* outgoing connections */
437  if(s2s->out_reuse) {
438  if(xhash_iter_first(s2s->out_host))
439  do {
440  xhv.conn_val = &conn;
441  xhash_iter_get(s2s->out_host, (const char **) &key, &keylen, xhv.val);
442  log_debug(ZONE, "checking dialback state for outgoing conn %.*s", keylen, key);
443  if (_s2s_check_conn_routes(s2s, conn, "outgoing")) {
444  log_debug(ZONE, "checking pending verify requests for outgoing conn %.*s", keylen, key);
445  if (conn->verify > 0 && now > conn->last_verify + s2s->check_queue) {
446  log_write(s2s->log, LOG_NOTICE, "[%d] [%s, port=%d] dialback verify request timed out", conn->fd->fd, conn->ip, conn->port);
447  sx_error(conn->s, stream_err_CONNECTION_TIMEOUT, "dialback verify request timed out");
448  sx_close(conn->s);
449  }
450  }
451  } while(xhash_iter_next(s2s->out_host));
452  } else {
453  if(xhash_iter_first(s2s->out_dest))
454  do {
455  xhv.conn_val = &conn;
456  xhash_iter_get(s2s->out_dest, (const char **) &key, &keylen, xhv.val);
457  log_debug(ZONE, "checking dialback state for outgoing conn %s (%s)", conn->dkey, conn->key);
458  if (_s2s_check_conn_routes(s2s, conn, "outgoing")) {
459  log_debug(ZONE, "checking pending verify requests for outgoing conn %s (%s)", conn->dkey, conn->key);
460  if (conn->verify > 0 && now > conn->last_verify + s2s->check_queue) {
461  log_write(s2s->log, LOG_NOTICE, "[%d] [%s, port=%d] dialback verify request timed out", conn->fd->fd, conn->ip, conn->port);
462  sx_error(conn->s, stream_err_CONNECTION_TIMEOUT, "dialback verify request timed out");
463  sx_close(conn->s);
464  }
465  }
466  } while(xhash_iter_next(s2s->out_dest));
467  }
468 
469  /* incoming open streams */
470  if(xhash_iter_first(s2s->in))
471  do {
472  xhv.conn_val = &conn;
473  xhash_iter_get(s2s->in, (const char **) &key, &keylen, xhv.val);
474 
475  log_debug(ZONE, "checking dialback state for incoming conn %.*s", keylen, key);
476  if (_s2s_check_conn_routes(s2s, conn, "incoming"))
477  /* if the connection is still valid, check that dialbacks have been initiated */
478  if(!xhash_count(conn->states) && now > conn->init_time + s2s->check_queue) {
479  log_write(s2s->log, LOG_NOTICE, "[%d] [%s, port=%d] no dialback started", conn->fd->fd, conn->ip, conn->port);
480  sx_error(conn->s, stream_err_CONNECTION_TIMEOUT, "no dialback initiated");
481  sx_close(conn->s);
482  }
483  } while(xhash_iter_next(s2s->in));
484 
485  /* incoming open connections (not yet streams) */
486  if(xhash_iter_first(s2s->in_accept))
487  do {
488  xhv.conn_val = &conn;
489  xhash_iter_get(s2s->in_accept, (const char **) &key, &keylen, xhv.val);
490 
491  log_debug(ZONE, "checking stream connection state for incoming conn %i", conn->fd->fd);
492  if(!conn->online && now > conn->init_time + s2s->check_queue) {
493  log_write(s2s->log, LOG_NOTICE, "[%d] [%s, port=%d] stream initiation timed out", conn->fd->fd, conn->ip, conn->port);
494  sx_close(conn->s);
495  }
496  } while(xhash_iter_next(s2s->in_accept));
497 
498  }
499 
500  /* keepalives */
501  if(s2s->out_reuse) {
502  if(xhash_iter_first(s2s->out_host))
503  do {
504  xhv.conn_val = &conn;
505  xhash_iter_get(s2s->out_host, NULL, NULL, xhv.val);
506 
507  if(s2s->check_keepalive > 0 && conn->last_activity > 0 && now > conn->last_activity + s2s->check_keepalive && conn->s->state >= state_STREAM) {
508  log_debug(ZONE, "sending keepalive for %d", conn->fd->fd);
509 
510  sx_raw_write(conn->s, " ", 1);
511  }
512  } while(xhash_iter_next(s2s->out_host));
513  } else {
514  if(xhash_iter_first(s2s->out_dest))
515  do {
516  xhv.conn_val = &conn;
517  xhash_iter_get(s2s->out_dest, NULL, NULL, xhv.val);
518 
519  if(s2s->check_keepalive > 0 && conn->last_activity > 0 && now > conn->last_activity + s2s->check_keepalive && conn->s->state >= state_STREAM) {
520  log_debug(ZONE, "sending keepalive for %d", conn->fd->fd);
521 
522  sx_raw_write(conn->s, " ", 1);
523  }
524  } while(xhash_iter_next(s2s->out_dest));
525  }
526 
527  /* idle timeouts - disconnect connections through which no packets have been sent for <idle> seconds */
528  if(s2s->check_idle > 0) {
529 
530  /* outgoing connections */
531  if(s2s->out_reuse) {
532  if(xhash_iter_first(s2s->out_host))
533  do {
534  xhv.conn_val = &conn;
535  xhash_iter_get(s2s->out_host, (const char **) &key, &keylen, xhv.val);
536  log_debug(ZONE, "checking idle state for %.*s", keylen, key);
537  if (conn->last_packet > 0 && now > conn->last_packet + s2s->check_idle && conn->s->state >= state_STREAM) {
538  log_write(s2s->log, LOG_NOTICE, "[%d] [%s, port=%d] idle timeout", conn->fd->fd, conn->ip, conn->port);
539  sx_close(conn->s);
540  }
541  } while(xhash_iter_next(s2s->out_host));
542  } else {
543  if(xhash_iter_first(s2s->out_dest))
544  do {
545  xhv.conn_val = &conn;
546  xhash_iter_get(s2s->out_dest, (const char **) &key, &keylen, xhv.val);
547  log_debug(ZONE, "checking idle state for %s (%s)", conn->dkey, conn->key);
548  if (conn->last_packet > 0 && now > conn->last_packet + s2s->check_idle && conn->s->state >= state_STREAM) {
549  log_write(s2s->log, LOG_NOTICE, "[%d] [%s, port=%d] idle timeout", conn->fd->fd, conn->ip, conn->port);
550  sx_close(conn->s);
551  }
552  } while(xhash_iter_next(s2s->out_dest));
553  }
554 
555  /* incoming connections */
556  if(xhash_iter_first(s2s->in))
557  do {
558  xhv.conn_val = &conn;
559  xhash_iter_get(s2s->in, (const char **) &key, &keylen, xhv.val);
560  log_debug(ZONE, "checking idle state for %.*s", keylen, key);
561  if (conn->last_packet > 0 && now > conn->last_packet + s2s->check_idle && conn->s->state >= state_STREAM) {
562  log_write(s2s->log, LOG_NOTICE, "[%d] [%s, port=%d] idle timeout", conn->fd->fd, conn->ip, conn->port);
563  sx_close(conn->s);
564  }
565  } while(xhash_iter_next(s2s->in));
566 
567  }
568 
569  return;
570 }
571 
572 static void _s2s_dns_expiry(s2s_t s2s) {
573  time_t now;
574  dnscache_t dns = NULL;
575  dnsres_t res = NULL;
576  union xhashv xhv;
577 
578  now = time(NULL);
579 
580  /* dnscache timeouts */
581  if(xhash_iter_first(s2s->dnscache))
582  do {
583  xhv.dns_val = &dns;
584  xhash_iter_get(s2s->dnscache, NULL, NULL, xhv.val);
585  if (dns && !dns->pending && now > dns->expiry) {
586  log_debug(ZONE, "expiring DNS cache for %s", dns->name);
587  xhash_iter_zap(s2s->dnscache);
588 
589  xhash_free(dns->results);
590  if (dns->query != NULL) {
591  if (dns->query->query != NULL)
592  dns_cancel(NULL, dns->query->query);
593  xhash_free(dns->query->hosts);
594  xhash_free(dns->query->results);
595  free((void*)dns->query->name);
596  free(dns->query);
597  }
598  free(dns);
599  }
600  else if (dns == NULL) {
601  xhash_iter_zap(s2s->dnscache);
602  }
603  } while(xhash_iter_next(s2s->dnscache));
604 
605  if(xhash_iter_first(s2s->dns_bad))
606  do {
607  xhv.dnsres_val = &res;
608  xhash_iter_get(s2s->dns_bad, NULL, NULL, xhv.val);
609  if (res && now > res->expiry) {
610  log_debug(ZONE, "expiring DNS bad host %s", res->key);
611  xhash_iter_zap(s2s->dns_bad);
612 
613  free((void*)res->key);
614  free(res);
615  }
616  else if (res == NULL) {
617  xhash_iter_zap(s2s->dns_bad);
618  }
619  } while(xhash_iter_next(s2s->dns_bad));
620 }
622 static int _mio_resolver_callback(mio_t m, mio_action_t a, mio_fd_t fd, void *data, void *arg) {
623 
624  switch(a) {
625  case action_READ:
626  log_debug(ZONE, "read action on fd %d", fd->fd);
627 
628  dns_ioevent(0, time(NULL));
629 
630  default:
631  break;
632  }
633 
634  return 0;
635 }
636 
637 /* Populate the whitelist_domains array with the config file values */
638 int _s2s_populate_whitelist_domains(s2s_t s2s, const char **values, int nvalues) {
639  int i, j;
640  int elem_len;
641  s2s->whitelist_domains = (char **)malloc(sizeof(char*) * (nvalues));
642  memset(s2s->whitelist_domains, 0, (sizeof(char *) * (nvalues)));
643  for (i = 0, j = 0; i < nvalues; i++) {
644  elem_len = strlen(values[i]);
645  if (elem_len > MAX_DOMAIN_LEN) {
646  log_debug(ZONE, "whitelist domain element is too large, skipping");
647  continue;
648  }
649  if (elem_len == 0) {
650  log_debug(ZONE, "whitelist domain element is blank, skipping");
651  continue;
652  }
653  s2s->whitelist_domains[j] = (char *) malloc(sizeof(char) * (elem_len+1));
654  strncpy(s2s->whitelist_domains[j], values[i], elem_len);
655  s2s->whitelist_domains[j][elem_len] = '\0';
656  log_debug(ZONE, "s2s whitelist domain read from file: %s\n", s2s->whitelist_domains[j]);
657  j++;
658  }
659 
660  s2s->n_whitelist_domains = j;
661  log_debug(ZONE, "n_whitelist_domains = %d", s2s->n_whitelist_domains);
662  return 0;
663 }
664 
665 
666 /* Compare a domain with whitelist values.
667  The whitelist values may be FQDN or domain only (with no prepended hostname).
668  returns 1 on match, 0 on failure to match
669 */
670 int s2s_domain_in_whitelist(s2s_t s2s, const char *in_domain) {
671  int segcount = 0;
672  int dotcount;
673  char **segments = NULL;
674  char **dst = NULL;
675  char *seg_tmp = NULL;
676  int seg_tmp_len;
677  char matchstr[MAX_DOMAIN_LEN + 1];
678  int domain_index;
679  int x, i;
680  int wl_index;
681  int wl_len;
682  int matchstr_len;
683  char domain[1024];
684  char *domain_ptr = &domain[0];
685  int domain_len;
686 
687  strncpy(domain, in_domain, sizeof(domain));
688  domain[sizeof(domain)-1] = '\0';
689  domain_len = strlen((const char *)&domain);
690 
691  if (domain_len <= 0) {
692  log_write(s2s->log, LOG_NOTICE, "s2s_domain_in_whitelist: in_domain is empty");
693  return 0;
694  }
695 
696  if (domain_len > MAX_DOMAIN_LEN) {
697  log_write(s2s->log, LOG_NOTICE, "s2s_domain_in_whitelist: in_domain is longer than %s chars", MAX_DOMAIN_LEN);
698  return 0;
699  }
700 
701  // first try matching the FQDN with whitelist domains
702  if (s2s->n_whitelist_domains <= 0)
703  return 0;
704 
705  for (wl_index =0; wl_index < s2s->n_whitelist_domains; wl_index++) {
706  wl_len = strlen(s2s->whitelist_domains[wl_index]);
707  if (!strncmp((const char *)&domain, s2s->whitelist_domains[wl_index], (domain_len > wl_len) ? domain_len : wl_len)) {
708  log_debug(ZONE, "domain \"%s\" matches whitelist entry", &domain);
709  return 1;
710  }
711  else {
712  //log_debug(ZONE, "domain: %s (len %d) does not match whitelist_domains[%d]: %s (len %d)", &domain, strlen((const char *)&domain), wl_index, s2s->whitelist_domains[wl_index], strlen(s2s->whitelist_domains[wl_index]));
713  }
714  }
715 
716  // break domain into segments for domain-only comparision
717  for (dotcount = 0, x = 0; domain[x] != '\0'; x++) {
718  if (domain[x] == '.')
719  dotcount++;
720  }
721 
722  segments = (char **)malloc(sizeof(char*) * (dotcount + 1));
723  if (segments == NULL) {
724  log_write(s2s->log, LOG_ERR, "s2s_domain_in_whitelist: malloc() error");
725  return 0;
726  }
727  memset((char **)segments, 0, (sizeof(char*) * (dotcount + 1)));
728 
729  do {
730  if (segcount > (dotcount+1)) {
731  log_write(s2s->log, LOG_ERR, "s2s_domain_in_whitelist: did not malloc enough room for domain segments; should never get here");
732  if (seg_tmp != NULL) {
733  free(seg_tmp);
734  seg_tmp = NULL;
735  }
736  for (x = 0; x < segcount; x++) {
737  free(segments[x]);
738  segments[x] = NULL;
739  }
740  free(segments);
741  segments = NULL;
742  return 0;
743  }
744  seg_tmp = strsep(&domain_ptr, ".");
745  if (seg_tmp == NULL) {
746  break;
747  }
748 
749  seg_tmp_len = strlen(seg_tmp);
750  if (seg_tmp_len > MAX_DOMAIN_LEN) {
751  log_write(s2s->log, LOG_NOTICE, "s2s_domain_in_whitelist: domain contains a segment greater than %s chars", MAX_DOMAIN_LEN);
752  free(seg_tmp);
753  seg_tmp = NULL;
754  for (x = 0; x < segcount; x++) {
755  free(segments[x]);
756  segments[x] = NULL;
757  }
758  free(segments);
759  segments = NULL;
760  return 0;
761  }
762  dst = &segments[segcount];
763  *dst = (char *)malloc(seg_tmp_len + 1);
764  if (*dst != NULL) {
765  strncpy(*dst, seg_tmp, seg_tmp_len + 1);
766  (*dst)[seg_tmp_len] = '\0';
767  } else {
768  free(seg_tmp);
769  seg_tmp = NULL;
770  for (x = 0; x < segcount; x++) {
771  free(segments[x]);
772  segments[x] = NULL;
773  }
774  free(segments);
775  segments = NULL;
776  log_write(s2s->log, LOG_ERR, "s2s_domain_in_whitelist: malloc() error");
777  return 0;
778  }
779  segcount++;
780  } while (seg_tmp != NULL);
781 
782  if (segcount > 1) {
783  for (domain_index = segcount-2; domain_index > 0; domain_index--) {
784  matchstr[0] = '\0';
785  for (i = domain_index; i < segcount; i++) {
786  if (i > domain_index) {
787  strncat((char *)&matchstr, ".", sizeof(matchstr));
788  matchstr[sizeof(matchstr)-1] = '\0';
789  }
790  strncat((char *)&matchstr, (char *)segments[i], sizeof(matchstr)-strlen(matchstr)-1);
791  matchstr[sizeof(matchstr)-1] = '\0';
792  }
793  for (wl_index = 0; wl_index < s2s->n_whitelist_domains; wl_index++) {
794  wl_len = strlen(s2s->whitelist_domains[wl_index]);
795  matchstr_len = strlen((const char *)&matchstr);
796  if (!strncmp((const char *)&matchstr, s2s->whitelist_domains[wl_index], (wl_len > matchstr_len ? wl_len : matchstr_len))) {
797  log_debug(ZONE, "matchstr \"%s\" matches whitelist entry", &matchstr);
798  for (x = 0; x < segcount; x++) {
799  free(segments[x]);
800  segments[x] = NULL;
801  }
802  free(segments);
803  segments = NULL;
804  return 1;
805  }
806  else {
807  //log_debug(ZONE, "matchstr: %s (len %d) does not match whitelist_domains[%d]: %s (len %d)", &matchstr, strlen((const char *)&matchstr), wl_index, s2s->whitelist_domains[wl_index], strlen(s2s->whitelist_domains[wl_index]));
808  }
809  }
810  }
811  }
812  for (x = 0; x < segcount; x++) {
813  free(segments[x]);
814  segments[x] = NULL;
815  }
816  free(segments);
817  segments = NULL;
818 
819  return 0;
820 }
821 
822 JABBER_MAIN("jabberd2s2s", "Jabber 2 S2S", "Jabber Open Source Server: Server to Server", "jabberd2router\0")
823 {
824  s2s_t s2s;
825  char *config_file;
826  int optchar;
827  conn_t conn;
828  jqueue_t q;
829  dnscache_t dns;
830  dnsres_t res;
831  union xhashv xhv;
832  time_t check_time = 0, now = 0;
833  const char *cli_id = 0;
834 
835 #ifdef HAVE_UMASK
836  umask((mode_t) 0027);
837 #endif
838 
839  srand(time(NULL));
840 
841 #ifdef HAVE_WINSOCK2_H
842 /* get winsock running */
843  {
844  WORD wVersionRequested;
845  WSADATA wsaData;
846  int err;
847 
848  wVersionRequested = MAKEWORD( 2, 2 );
849 
850  err = WSAStartup( wVersionRequested, &wsaData );
851  if ( err != 0 ) {
852  /* !!! tell user that we couldn't find a usable winsock dll */
853  return 0;
854  }
855  }
856 #endif
857 
858  jabber_signal(SIGINT, _s2s_signal);
859  jabber_signal(SIGTERM, _s2s_signal);
860 #ifdef SIGHUP
862 #endif
863 #ifdef SIGPIPE
864  jabber_signal(SIGPIPE, SIG_IGN);
865 #endif
868 
869 
870  s2s = (s2s_t) calloc(1, sizeof(struct s2s_st));
871 
872  /* load our config */
873  s2s->config = config_new();
874 
875  config_file = CONFIG_DIR "/s2s.xml";
876 
877  /* cmdline parsing */
878  while((optchar = getopt(argc, argv, "Dc:hi:?")) >= 0)
879  {
880  switch(optchar)
881  {
882  case 'c':
883  config_file = optarg;
884  break;
885  case 'D':
886 #ifdef DEBUG
887  set_debug_flag(1);
888 #else
889  printf("WARN: Debugging not enabled. Ignoring -D.\n");
890 #endif
891  break;
892  case 'i':
893  cli_id = optarg;
894  break;
895  case 'h': case '?': default:
896  fputs(
897  "s2s - jabberd server-to-server connector (" VERSION ")\n"
898  "Usage: s2s <options>\n"
899  "Options are:\n"
900  " -c <config> config file to use [default: " CONFIG_DIR "/s2s.xml]\n"
901  " -i id Override <id> config element\n"
902 #ifdef DEBUG
903  " -D Show debug output\n"
904 #endif
905  ,
906  stdout);
907  config_free(s2s->config);
908  free(s2s);
909  return 1;
910  }
911  }
912 
913  if(config_load_with_id(s2s->config, config_file, cli_id) != 0) {
914  fputs("s2s: couldn't load config, aborting\n", stderr);
915  config_free(s2s->config);
916  free(s2s);
917  return 2;
918  }
919 
920  _s2s_config_expand(s2s);
921 
922  s2s->log = log_new(s2s->log_type, s2s->log_ident, s2s->log_facility);
923  log_write(s2s->log, LOG_NOTICE, "starting up (interval=%i, queue=%i, keepalive=%i, idle=%i)", s2s->check_interval, s2s->check_queue, s2s->check_keepalive, s2s->check_idle);
924 
925  _s2s_pidfile(s2s);
926 
927  s2s->outq = xhash_new(401);
928  s2s->out_host = xhash_new(401);
929  s2s->out_dest = xhash_new(401);
930  s2s->in = xhash_new(401);
931  s2s->in_accept = xhash_new(401);
932  s2s->dnscache = xhash_new(401);
933  s2s->dns_bad = xhash_new(401);
934 
935  s2s->dead = jqueue_new();
936  s2s->dead_conn = jqueue_new();
937 
938  s2s->sx_env = sx_env_new();
939 
940 #ifdef HAVE_SSL
941  /* get the ssl context up and running */
942  if(s2s->local_pemfile != NULL) {
944 
945  if(s2s->sx_ssl == NULL) {
946  log_write(s2s->log, LOG_ERR, "failed to load local SSL pemfile, SSL will not be available to peers");
947  s2s->local_pemfile = NULL;
948  } else
949  log_debug(ZONE, "loaded pemfile for SSL connections to peers");
950  }
951 
952  /* try and get something online, so at least we can encrypt to the router */
953  if(s2s->sx_ssl == NULL && s2s->router_pemfile != NULL) {
955  if(s2s->sx_ssl == NULL) {
956  log_write(s2s->log, LOG_ERR, "failed to load router SSL pemfile, channel to router will not be SSL encrypted");
957  s2s->router_pemfile = NULL;
958  }
959  }
960 #endif
961 
962 #ifdef HAVE_LIBZ
963  /* get compression up and running */
964  if(s2s->compression)
966 #endif
967 
968  /* get sasl online */
969  s2s->sx_sasl = sx_env_plugin(s2s->sx_env, sx_sasl_init, "xmpp", NULL, NULL);
970  if(s2s->sx_sasl == NULL) {
971  log_write(s2s->log, LOG_ERR, "failed to initialise SASL context, aborting");
972  exit(1);
973  }
974 
975  /* hosts mapping */
976  s2s->hosts = xhash_new(1021);
977  _s2s_hosts_expand(s2s);
978 
979  s2s->sx_db = sx_env_plugin(s2s->sx_env, s2s_db_init);
980 
981  s2s->mio = mio_new(s2s->io_max_fds);
982 
983  if((s2s->udns_fd = dns_init(NULL, 1)) < 0) {
984  log_write(s2s->log, LOG_ERR, "unable to initialize dns library, aborting");
985  exit(1);
986  }
987  s2s->udns_mio_fd = mio_register(s2s->mio, s2s->udns_fd, _mio_resolver_callback, (void *) s2s);
988 
989  s2s->retry_left = s2s->retry_init;
990  _s2s_router_connect(s2s);
991 
992  while(!s2s_shutdown) {
993  mio_run(s2s->mio, dns_timeouts(0, 5, time(NULL)));
994 
995  now = time(NULL);
996 
997  if(s2s_logrotate) {
998  set_debug_log_from_config(s2s->config);
999 
1000  log_write(s2s->log, LOG_NOTICE, "reopening log ...");
1001  log_free(s2s->log);
1002  s2s->log = log_new(s2s->log_type, s2s->log_ident, s2s->log_facility);
1003  log_write(s2s->log, LOG_NOTICE, "log started");
1004 
1005  s2s_logrotate = 0;
1006  }
1007 
1008  if(s2s_lost_router) {
1009  if(s2s->retry_left < 0) {
1010  log_write(s2s->log, LOG_NOTICE, "attempting reconnect");
1011  sleep(s2s->retry_sleep);
1012  s2s_lost_router = 0;
1013  if (s2s->router) sx_free(s2s->router);
1014  _s2s_router_connect(s2s);
1015  }
1016 
1017  else if(s2s->retry_left == 0) {
1018  s2s_shutdown = 1;
1019  }
1020 
1021  else {
1022  log_write(s2s->log, LOG_NOTICE, "attempting reconnect (%d left)", s2s->retry_left);
1023  s2s->retry_left--;
1024  sleep(s2s->retry_sleep);
1025  s2s_lost_router = 0;
1026  if (s2s->router) sx_free(s2s->router);
1027  _s2s_router_connect(s2s);
1028  }
1029  }
1030 
1031  /* this has to be read unconditionally - we could receive replies to queries we cancelled */
1032  mio_read(s2s->mio, s2s->udns_mio_fd);
1033 
1034  /* cleanup dead sx_ts */
1035  while(jqueue_size(s2s->dead) > 0)
1036  sx_free((sx_t) jqueue_pull(s2s->dead));
1037 
1038  /* cleanup dead conn_ts */
1039  while(jqueue_size(s2s->dead_conn) > 0) {
1040  conn = (conn_t) jqueue_pull(s2s->dead_conn);
1041  xhash_free(conn->states);
1042  xhash_free(conn->states_time);
1043  xhash_free(conn->routes);
1044 
1045  free((void*)conn->key);
1046  free((void*)conn->dkey);
1047  free(conn);
1048  }
1049 
1050  /* time checks */
1051  if(s2s->check_interval > 0 && now >= s2s->next_check) {
1052  log_debug(ZONE, "running time checks");
1053 
1054  _s2s_time_checks(s2s);
1055 
1056  s2s->next_check = now + s2s->check_interval;
1057  log_debug(ZONE, "next time check at %d", s2s->next_check);
1058  }
1059 
1060  /* dnscache expiry */
1061  if(s2s->check_dnscache > 0 && now >= s2s->next_expiry) {
1062  log_debug(ZONE, "running dns expiry");
1063 
1064  _s2s_dns_expiry(s2s);
1065 
1066  s2s->next_expiry = now + s2s->check_dnscache;
1067  log_debug(ZONE, "next dns expiry at %d", s2s->next_expiry);
1068  }
1069 
1070  if(now > check_time + 60) {
1071 #ifdef POOL_DEBUG
1072  pool_stat(1);
1073 #endif
1074  if(s2s->packet_stats != NULL) {
1075  int fd = open(s2s->packet_stats, O_TRUNC | O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR | S_IRGRP);
1076  if(fd >= 0) {
1077  char buf[100];
1078  int len = snprintf(buf, 100, "%lld\n", s2s->packet_count);
1079  write(fd, buf, len);
1080  close(fd);
1081  } else {
1082  log_write(s2s->log, LOG_ERR, "failed to write packet statistics to: %s (%s)", s2s->packet_stats, strerror(errno));
1083  s2s_shutdown = 1;
1084  }
1085  }
1086 
1087  check_time = now;
1088  }
1089  }
1090 
1091  log_write(s2s->log, LOG_NOTICE, "shutting down");
1092 
1093  /* close active streams gracefully */
1094  xhv.conn_val = &conn;
1095  if(s2s->out_reuse) {
1096  if(xhash_iter_first(s2s->out_host))
1097  do {
1098  xhash_iter_get(s2s->out_host, NULL, NULL, xhv.val);
1099  if(conn) {
1100  sx_error(conn->s, stream_err_SYSTEM_SHUTDOWN, "s2s shutdown");
1102  sx_close(conn->s);
1103  }
1104  } while(xhash_iter_next(s2s->out_host));
1105  } else {
1106  if(xhash_iter_first(s2s->out_dest))
1107  do {
1108  xhash_iter_get(s2s->out_dest, NULL, NULL, xhv.val);
1109  if(conn) {
1110  sx_error(conn->s, stream_err_SYSTEM_SHUTDOWN, "s2s shutdown");
1112  sx_close(conn->s);
1113  }
1114  } while(xhash_iter_next(s2s->out_dest));
1115  }
1116 
1117  if(xhash_iter_first(s2s->in))
1118  do {
1119  xhash_iter_get(s2s->in, NULL, NULL, xhv.val);
1120  if(conn) {
1121  sx_error(conn->s, stream_err_SYSTEM_SHUTDOWN, "s2s shutdown");
1123  sx_close(conn->s);
1124  }
1125  } while(xhash_iter_next(s2s->in));
1126 
1127  if(xhash_iter_first(s2s->in_accept))
1128  do {
1129  xhash_iter_get(s2s->in_accept, NULL, NULL, xhv.val);
1130  if(conn) {
1132  sx_close(conn->s);
1133  }
1134  } while(xhash_iter_next(s2s->in_accept));
1135 
1136 
1137  /* remove dead streams */
1138  while(jqueue_size(s2s->dead) > 0)
1139  sx_free((sx_t) jqueue_pull(s2s->dead));
1140 
1141  /* cleanup dead conn_ts */
1142  while(jqueue_size(s2s->dead_conn) > 0) {
1143  conn = (conn_t) jqueue_pull(s2s->dead_conn);
1144  xhash_free(conn->states);
1145  xhash_free(conn->states_time);
1146  xhash_free(conn->routes);
1147 
1148  if(conn->key != NULL) free((void*)conn->key);
1149  if(conn->dkey != NULL) free((void*)conn->dkey);
1150  free(conn);
1151  }
1152 
1153  /* free outgoing queues */
1154  xhv.jq_val = &q;
1155  if(xhash_iter_first(s2s->outq))
1156  do {
1157  xhash_iter_get(s2s->outq, NULL, NULL, xhv.val);
1158  while (jqueue_size(q) > 0)
1160  free(q->key);
1161  jqueue_free(q);
1162  } while(xhash_iter_next(s2s->outq));
1163 
1164  /* walk & free resolve queues */
1165  xhv.dns_val = &dns;
1166  if(xhash_iter_first(s2s->dnscache))
1167  do {
1168  xhash_iter_get(s2s->dnscache, NULL, NULL, xhv.val);
1169  xhash_free(dns->results);
1170  if (dns->query != NULL) {
1171  if (dns->query->query != NULL)
1172  dns_cancel(NULL, dns->query->query);
1173  xhash_free(dns->query->hosts);
1174  xhash_free(dns->query->results);
1175  free((void*)dns->query->name);
1176  free(dns->query);
1177  }
1178  free(dns);
1179  } while(xhash_iter_next(s2s->dnscache));
1180 
1181  xhv.dnsres_val = &res;
1182  if(xhash_iter_first(s2s->dns_bad))
1183  do {
1184  xhash_iter_get(s2s->dns_bad, NULL, NULL, xhv.val);
1185  free((void*)res->key);
1186  free(res);
1187  } while(xhash_iter_next(s2s->dns_bad));
1188 
1189  if (dns_active(NULL) > 0)
1190  log_debug(ZONE, "there are still active dns queries (%d)", dns_active(NULL));
1191  dns_close(NULL);
1192 
1193  /* close mio */
1194  mio_close(s2s->mio, s2s->udns_mio_fd);
1195  if(s2s->fd != NULL)
1196  mio_close(s2s->mio, s2s->fd);
1197  if(s2s->server_fd != NULL)
1198  mio_close(s2s->mio, s2s->server_fd);
1199 
1200  /* free hashes */
1201  xhash_free(s2s->outq);
1202  xhash_free(s2s->out_host);
1203  xhash_free(s2s->out_dest);
1204  xhash_free(s2s->in);
1205  xhash_free(s2s->in_accept);
1206  xhash_free(s2s->dnscache);
1207  xhash_free(s2s->dns_bad);
1208  xhash_free(s2s->hosts);
1209 
1210  jqueue_free(s2s->dead);
1211  jqueue_free(s2s->dead_conn);
1212 
1213  sx_free(s2s->router);
1214 
1215  sx_env_free(s2s->sx_env);
1216 
1217  mio_free(s2s->mio);
1218 
1219  log_free(s2s->log);
1220 
1221  config_free(s2s->config);
1222 
1223  free((void*)s2s->local_secret);
1224  free(s2s);
1225 
1226 #ifdef POOL_DEBUG
1227  pool_stat(1);
1228 #endif
1229 
1230  return 0;
1231 }
#define MAX_DOMAIN_LEN
Definition: s2s.h:391
static sig_atomic_t s2s_logrotate
Definition: main.c:31
int retry_init
connect retry
Definition: s2s.h:113
Definition: s2s.h:66
const char ** values
Definition: util.h:209
char ip[INET6_ADDRSTRLEN+1]
Definition: s2s.h:262
const char * dkey
Definition: s2s.h:257
int enable_whitelist
Definition: s2s.h:187
_sx_state_t state
Definition: sx.h:319
int config_load_with_id(config_t c, const char *file, const char *id)
turn an xml file into a config hash
Definition: config.c:80
int check_dnscache
Definition: s2s.h:176
static int _s2s_populate_whitelist_domains(s2s_t s2s, const char **values, int nvalues)
Definition: main.c:638
struct host_st * host_t
Definition: c2s.h:52
const char * local_ip
ip/port to listen on
Definition: s2s.h:119
void xhash_free(xht h)
Definition: xhash.c:241
time_t expiry
time that this entry expires
Definition: s2s.h:359
log_t log
logging
Definition: s2s.h:101
int s2s_router_mio_callback(mio_t m, mio_action_t a, mio_fd_t fd, void *data, void *arg)
Definition: router.c:291
void config_free(config_t c)
cleanup
Definition: config.c:411
const char * router_pass
Definition: s2s.h:74
int s2s_db_init(sx_env_t env, sx_plugin_t p, va_list args)
Definition: db.c:55
const char * log_ident
Definition: s2s.h:106
xht hosts
srv lookup results (key host/port)
Definition: s2s.h:302
mio_t mio_new(int maxfd)
create/free the mio subsytem
Definition: mio.c:38
#define mio_run(m, timeout)
give some cpu time to mio to check it&#39;s sockets, 0 is non-blocking
Definition: mio.h:164
jqueue_t dead
list of sx_t on the way out
Definition: s2s.h:192
struct dnsres_st * dnsres_t
Definition: s2s.h:44
void * xhash_getx(xht h, const char *key, int len)
Definition: xhash.c:170
int jqueue_size(jqueue_t q)
Definition: jqueue.c:126
char ** whitelist_domains
Definition: s2s.h:188
const char * host_ciphers
list of TLS ciphers
Definition: c2s.h:144
void log_write(log_t log, int level, const char *msgfmt,...)
Definition: log.c:104
const char * router_ip
how to connect to the router
Definition: s2s.h:71
void xhash_iter_zap(xht h)
Definition: xhash.c:363
int port
Definition: s2s.h:263
xht in_accept
incoming conns prior to stream initiation (key is ip/port)
Definition: s2s.h:219
int s2s_router_sx_callback(sx_t s, sx_event_t e, void *data, void *arg)
our master callback
Definition: router.c:24
sx_t sx_new(sx_env_t env, int tag, sx_callback_t cb, void *arg)
if you change these, reflect your changes in the table in error.c
Definition: sx.c:23
config_t config_new(void)
new config structure
Definition: config.c:25
const char ** lookup_srv
srvs to lookup
Definition: s2s.h:157
const char * key
ip/port
Definition: s2s.h:350
#define MIO_STRERROR(e)
Definition: mio.h:170
xht hosts
hosts mapping
Definition: s2s.h:145
#define mio_free(m)
Definition: mio.h:137
int sx_ssl_server_addcert(sx_plugin_t p, const char *name, const char *pemfile, const char *cachain, int mode, const char *password, const char *ciphers)
args: name, pemfile, cachain, mode
Definition: ssl.c:977
mio_fd_t fd
Definition: s2s.h:92
static char * config_file
Definition: main.c:34
int verify
number and last timestamp of outstanding db:verify requests
Definition: s2s.h:279
char * host_private_key_password
private key password
Definition: c2s.h:135
dns resolution results
Definition: s2s.h:348
void sx_raw_write(sx_t s, const char *buf, int len)
app version
Definition: io.c:483
xht states
states of outgoing dialbacks (key is local/remote)
Definition: s2s.h:266
int j_atoi(const char *a, int def)
Definition: str.c:87
int out_bounce_route_queue(s2s_t s2s, const char *rkey, int rkeylen, int err)
Definition: out.c:1830
void out_pkt_free(pkt_t pkt)
Definition: out.c:617
struct conn_st * conn_t
Definition: s2s.h:41
mio_action_t
these are the actions and a handler type assigned by the applicaiton using mio
Definition: mio.h:106
Definition: mio.h:109
int host_verify_mode
verify-mode
Definition: c2s.h:138
xht outq
queues of packets waiting to go out (key is route)
Definition: s2s.h:204
const char * packet_stats
Definition: s2s.h:110
time_t expiry
time that this entry expires
Definition: s2s.h:338
xht out_host
outgoing conns (key is ip/port)
Definition: s2s.h:210
void log_free(log_t log)
Definition: log.c:174
int xhash_iter_next(xht h)
Definition: xhash.c:320
int check_queue
Definition: s2s.h:172
time_t last_verify
Definition: s2s.h:280
dnsquery_t query
Definition: s2s.h:344
sx_env_t sx_env_new(void)
Definition: env.c:23
#define mio_connect(m, port, hostip, srcip, app, arg)
for creating a new socket connected to this ip:port (returns new fd or <0, use mio_read/write first) ...
Definition: mio.h:144
xht dnscache
dns resolution cache
Definition: s2s.h:226
xht out_dest
outgoing conns (key is dest)
Definition: s2s.h:213
xht routes
routes that this conn handles (key is local/remote)
Definition: s2s.h:272
#define mio_read(m, fd)
process read events for this fd
Definition: mio.h:161
dnsres_t * dnsres_val
Definition: s2s.h:404
sx_plugin_t sx_db
Definition: s2s.h:88
static void _s2s_pidfile(s2s_t s2s)
store the process id
Definition: main.c:56
char * config_get_attr(config_t c, const char *key, int num, const char *attr)
get an attr for this value
Definition: config.c:315
void jqueue_free(jqueue_t q)
Definition: jqueue.c:38
xht dns_bad
dns resolution bad host cache
Definition: s2s.h:230
int local_port
Definition: s2s.h:120
Definition: log.h:42
#define MIO_ERROR
all MIO related routines should use those for error reporting
Definition: mio.h:168
int router_port
Definition: s2s.h:72
sx_env_t sx_env
sx environment
Definition: s2s.h:85
#define stanza_err_REMOTE_SERVER_TIMEOUT
Definition: util.h:382
int udns_fd
udns fds
Definition: s2s.h:222
int compression
enable Stream Compression
Definition: s2s.h:154
static void _s2s_signal(int signum)
Definition: main.c:33
int etc_hosts_ttl
/etc/hosts ttl limits
Definition: s2s.h:168
int pending
set when we&#39;re waiting for a resolve response
Definition: s2s.h:343
sx_plugin_t sx_env_plugin(sx_env_t env, sx_plugin_init_t init,...)
load a plugin into the environment
Definition: env.c:48
int online
Definition: s2s.h:276
int stanza_size_limit
maximum stanza size
Definition: s2s.h:151
holds the state for a single stream
Definition: sx.h:253
#define stream_err_SYSTEM_SHUTDOWN
Definition: sx.h:142
int local_verify_mode
verify-mode
Definition: s2s.h:139
int dns_cache_enabled
Definition: s2s.h:227
const char * local_cachain
certificate chain
Definition: s2s.h:136
conn_state_t
Definition: s2s.h:246
void ** val
Definition: c2s.h:404
packet summary data wrapper
Definition: sm.h:129
void * pmalloco(pool_t p, int size)
easy safety utility (for creating blank mem for structs, etc)
Definition: pool.c:183
void sx_client_init(sx_t s, unsigned int flags, const char *ns, const char *to, const char *from, const char *version)
Definition: client.c:111
jqueue_t * jq_val
Definition: s2s.h:402
const char * key
Definition: s2s.h:256
mio_fd_t udns_mio_fd
Definition: s2s.h:223
int check_keepalive
Definition: s2s.h:174
void set_debug_log_from_config(config_t c)
Definition: log.c:267
const char * log_facility
Definition: s2s.h:105
xht results
results (key ip/port)
Definition: s2s.h:335
char name[1024]
the name proper
Definition: s2s.h:332
int s2s_domain_in_whitelist(s2s_t s2s, const char *in_domain)
Definition: main.c:670
const char * realm
our realm (SASL)
Definition: c2s.h:126
int retry_limit
Definition: s2s.h:177
sx_plugin_t sx_ssl
Definition: s2s.h:86
jqueue_t dead_conn
list of conn_t on the way out
Definition: s2s.h:195
sx_t s
Definition: s2s.h:259
void pool_stat(int full)
Definition: pool.c:285
void xhash_put(xht h, const char *key, void *val)
Definition: xhash.c:163
xht states_time
time of the last state change (key is local/remote)
Definition: s2s.h:269
conn_t * conn_val
Definition: s2s.h:400
Definition: c2s.h:124
xht results
host lookup results (key ip/port)
Definition: s2s.h:320
const char * local_secret
dialback secret
Definition: s2s.h:127
dnscache_t * dns_val
Definition: s2s.h:403
int xhash_iter_get(xht h, const char **key, int *keylen, void **val)
Definition: xhash.c:374
#define stanza_err_REMOTE_SERVER_NOT_FOUND
Definition: util.h:381
void sx_free(sx_t s)
Definition: sx.c:70
const char * host_pemfile
starttls pemfile
Definition: c2s.h:129
int dns_max_ttl
Definition: s2s.h:165
int router_default
Definition: s2s.h:79
void sx_close(sx_t s)
Definition: io.c:512
JABBER_MAIN("jabberd2c2s", "Jabber 2 C2S", "Jabber Open Source Server: Client to Server", "jabberd2router\)
Definition: main.c:657
static int _s2s_router_connect(s2s_t s2s)
Definition: main.c:281
void xhash_zap(xht h, const char *key)
Definition: xhash.c:235
#define log_debug(...)
Definition: log.h:65
jsighandler_t * jabber_signal(int signo, jsighandler_t *func)
Definition: jsignal.c:33
const char * name
domain name
Definition: s2s.h:296
int out_reuse
reuse outgoing conns keyed by ip/port
Definition: s2s.h:207
void xhash_zapx(xht h, const char *key, int len)
Definition: xhash.c:219
const char * router_pemfile
Definition: s2s.h:75
const char * local_ciphers
list of TLS ciphers
Definition: s2s.h:142
int check_interval
time checks
Definition: s2s.h:171
char * dns_make_ipport(const char *host, int port)
Definition: out.c:740
void sx_error(sx_t s, int err, const char *text)
Definition: error.c:94
static void _s2s_signal_hup(int signum)
Definition: main.c:38
JABBERD2_API int sx_sasl_init(sx_env_t env, sx_plugin_t p, va_list args)
init function
Definition: sasl.c:881
int retry_lost
Definition: s2s.h:114
static void _s2s_time_checks(s2s_t s2s)
Definition: main.c:339
config_elem_t config_get(config_t c, const char *key)
get the config element for this key
Definition: config.c:272
int io_max_fds
max file descriptors
Definition: s2s.h:148
#define stream_err_CONNECTION_TIMEOUT
Definition: sx.h:127
config_t config
config
Definition: s2s.h:98
time_t last_packet
Definition: s2s.h:284
int resolve_aaaa
if we resolve AAAA records
Definition: s2s.h:161
void * jqueue_pull(jqueue_t q)
Definition: jqueue.c:96
int xhash_count(xht h)
return the total number of entries in this xht
Definition: xhash.c:297
const char ** origin_ips
ip(s) to originate connections from
Definition: s2s.h:123
static void _s2s_config_expand(s2s_t s2s)
pull values out of the config file
Definition: main.c:84
struct dns_query * query
set when we&#39;re waiting for a resolve response
Definition: s2s.h:326
int xhash_iter_first(xht h)
iteration
Definition: xhash.c:311
char * key
Definition: util.h:331
const char * router_ciphers
Definition: s2s.h:78
int fd
Definition: mio.h:102
jqueue_t jqueue_new(void)
Definition: jqueue.c:25
sig_atomic_t s2s_lost_router
Definition: main.c:30
int n_whitelist_domains
Definition: s2s.h:189
struct s2s_st * s2s_t
Definition: s2s.h:39
void set_debug_flag(int v)
Definition: log.c:264
const char * router_private_key_password
Definition: s2s.h:77
int sx_ssl_init(sx_env_t env, sx_plugin_t p, va_list args)
args: name, pemfile, cachain, mode
Definition: ssl.c:928
int _s2s_check_conn_routes(s2s_t s2s, conn_t conn, const char *direction)
Definition: main.c:298
static void _s2s_signal_usr2(int signum)
Definition: main.c:47
static void _s2s_hosts_expand(s2s_t s2s)
Definition: main.c:219
const char *** attrs
Definition: util.h:211
int sx_compress_init(sx_env_t env, sx_plugin_t p, va_list args)
args: none
Definition: compress.c:328
pool_t xhash_pool(xht h)
get our pool
Definition: xhash.c:305
int out_bounce_conn_queues(conn_t out, int err)
Definition: out.c:1864
const char * id
our id (hostname) with the router
Definition: s2s.h:68
mio_t mio
mio context
Definition: s2s.h:82
log_type_t log_type
log data
Definition: s2s.h:104
char * pstrdup(pool_t p, const char *src)
XXX efficient: move this to const char * and then loop throug the existing heaps to see if src is wit...
Definition: pool.c:191
Definition: mio.h:100
Definition: log.h:43
const char * router_cachain
Definition: s2s.h:76
xht in
incoming conns (key is stream id)
Definition: s2s.h:216
const char * router_user
Definition: s2s.h:73
Definition: log.h:44
void * xhash_get(xht h, const char *key)
Definition: xhash.c:184
#define mio_close(m, fd)
request that mio close this fd
Definition: mio.h:155
char * j_attr(const char **atts, const char *attr)
Definition: str.c:95
const char * local_private_key_password
private key password for local pemfile, if encrypted
Definition: s2s.h:133
static sig_atomic_t s2s_shutdown
Definition: main.c:29
log_t log_new(log_type_t type, const char *ident, const char *facility)
Definition: log.c:69
int require_tls
Apple security options.
Definition: s2s.h:186
one item in the dns resolution cache
Definition: s2s.h:330
#define ZONE
Definition: mio_impl.h:76
Definition: s2s.h:253
session packet handling
Definition: c2s.h:402
const char * config_get_one(config_t c, const char *key, int num)
get config value n for this key
Definition: config.c:278
int dns_bad_timeout
Definition: s2s.h:231
xht xhash_new(int prime)
Definition: xhash.c:96
int lookup_nsrv
Definition: s2s.h:158
void sx_env_free(sx_env_t env)
Definition: env.c:31
int origin_nips
Definition: s2s.h:124
a single element
Definition: util.h:207
static void _s2s_signal_usr1(int signum)
Definition: main.c:42
#define mio_register(m, fd, app, arg)
for adding an existing socket connected to this mio
Definition: mio.h:148
#define stanza_err_SERVICE_UNAVAILABLE
Definition: util.h:384
int retry_sleep
Definition: s2s.h:115
int config_count(config_t c, const char *key)
how many values for this key?
Definition: config.c:304
mio_fd_t fd
Definition: s2s.h:260
static int _mio_resolver_callback(mio_t m, mio_action_t a, mio_fd_t fd, void *data, void *arg)
responses from the resolver
Definition: main.c:622
const char * local_pemfile
pemfile for peer connections
Definition: s2s.h:130
time_t init_time
Definition: s2s.h:274
int nvalues
Definition: util.h:210
time_t last_activity
timestamps for idle timeouts
Definition: s2s.h:283
int check_idle
Definition: s2s.h:175
sx_plugin_t sx_sasl
Definition: s2s.h:87
int dns_min_ttl
dns ttl limits
Definition: s2s.h:164
static void _s2s_dns_expiry(s2s_t s2s)
Definition: main.c:572
const char * host_cachain
certificate chain
Definition: c2s.h:132