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