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