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