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