23 #include <stringprep.h>
64 if((f = fopen(pidfile,
"w+")) == NULL) {
65 log_write(s2s->
log, LOG_ERR,
"couldn't open %s for writing: %s", pidfile, strerror(errno));
69 if(fprintf(f,
"%d", pid) < 0) {
70 log_write(s2s->
log, LOG_ERR,
"couldn't write to %s: %s", pidfile, strerror(errno));
77 log_write(s2s->
log, LOG_INFO,
"process id is %d, written to %s", pid, pidfile);
82 char *str, secret[41];
121 if(strcmp(str,
"file") == 0)
123 else if(strcmp(str,
"syslog") == 0)
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);
222 if (elem)
for(i = 0; i < elem->
nvalues; i++) {
225 log_write(s2s->
log, LOG_ERR,
"cannot allocate memory for new host, aborting");
229 realm =
j_attr((
const char **) elem->
attrs[i],
"realm");
232 strncpy(
id, elem->
values[i], 1024);
234 if (stringprep_nameprep(
id, 1024) != 0) {
235 log_write(s2s->
log, LOG_ERR,
"cannot stringprep id %s, aborting",
id);
277 if(s2s->
fd == NULL) {
278 if(errno == ECONNREFUSED)
295 time_t now, dialback_time;
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);
351 log_debug(
ZONE,
"running time checks for %.*s", keylen, rkey);
352 c = memchr(rkey,
'/', keylen);
354 c_len = keylen - (c - rkey);
358 if(dns != NULL && dns->pending) {
361 log_write(s2s->
log, LOG_NOTICE,
"dns lookup for %.*s timed out", c_len, c);
369 if (dns->query != NULL) {
370 if (dns->query->query != NULL)
371 dns_cancel(NULL, dns->query->query);
374 free((
void*)dns->query->name);
402 log_write(s2s->
log, LOG_NOTICE,
"[%d] [%s, port=%d] connection to %s timed out", conn->
fd->
fd, conn->
ip, conn->
port, c);
434 log_debug(
ZONE,
"checking dialback state for outgoing conn %.*s", keylen, key);
436 log_debug(
ZONE,
"checking pending verify requests for outgoing conn %.*s", keylen, key);
438 log_write(s2s->
log, LOG_NOTICE,
"[%d] [%s, port=%d] dialback verify request timed out", conn->
fd->
fd, conn->
ip, conn->
port);
451 log_debug(
ZONE,
"checking pending verify requests for outgoing conn %s (%s)", conn->
dkey, conn->
key);
453 log_write(s2s->
log, LOG_NOTICE,
"[%d] [%s, port=%d] dialback verify request timed out", conn->
fd->
fd, conn->
ip, conn->
port);
467 log_debug(
ZONE,
"checking dialback state for incoming conn %.*s", keylen, key);
471 log_write(s2s->
log, LOG_NOTICE,
"[%d] [%s, port=%d] no dialback started", conn->
fd->
fd, conn->
ip, conn->
port);
483 log_debug(
ZONE,
"checking stream connection state for incoming conn %i", conn->
fd->
fd);
485 log_write(s2s->
log, LOG_NOTICE,
"[%d] [%s, port=%d] stream initiation timed out", conn->
fd->
fd, conn->
ip, conn->
port);
528 log_debug(
ZONE,
"checking idle state for %.*s", keylen, key);
552 log_debug(
ZONE,
"checking idle state for %.*s", keylen, key);
582 if (dns->
query != NULL) {
592 else if (dns == NULL) {
601 if (res && now > res->
expiry) {
605 free((
void*)res->
key);
608 else if (res == NULL) {
620 dns_ioevent(0, time(NULL));
635 for (i = 0, j = 0; i < nvalues; i++) {
636 elem_len = strlen(values[i]);
638 log_debug(
ZONE,
"whitelist domain element is too large, skipping");
642 log_debug(
ZONE,
"whitelist domain element is blank, skipping");
665 char **segments = NULL;
667 char *seg_tmp = NULL;
676 char *domain_ptr = &domain[0];
679 strncpy(domain, in_domain,
sizeof(domain));
680 domain[
sizeof(domain)-1] =
'\0';
681 domain_len = strlen((
const char *)&domain);
683 if (domain_len <= 0) {
684 log_write(s2s->
log, LOG_NOTICE,
"s2s_domain_in_whitelist: in_domain is empty");
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);
709 for (dotcount = 0, x = 0; domain[x] !=
'\0'; x++) {
710 if (domain[x] ==
'.')
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");
719 memset((
char **)segments, 0, (
sizeof(
char*) * (dotcount + 1)));
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) {
728 for (x = 0; x < segcount; x++) {
736 seg_tmp = strsep(&domain_ptr,
".");
737 if (seg_tmp == NULL) {
741 seg_tmp_len = strlen(seg_tmp);
744 if (seg_tmp != NULL) {
748 for (x = 0; x < segcount; x++) {
756 dst = &segments[segcount];
757 *dst = (
char *)malloc(seg_tmp_len + 1);
759 strncpy(*dst, seg_tmp, seg_tmp_len + 1);
760 (*dst)[seg_tmp_len] =
'\0';
762 if (seg_tmp != NULL) {
766 for (x = 0; x < segcount; x++) {
772 log_write(s2s->
log, LOG_ERR,
"s2s_domain_in_whitelist: malloc() error");
776 }
while (seg_tmp != NULL);
779 for (domain_index = segcount-2; domain_index > 0; domain_index--) {
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';
786 strncat((
char *)&matchstr, (
char *)segments[i],
sizeof(matchstr)-strlen(matchstr)-1);
787 matchstr[
sizeof(matchstr)-1] =
'\0';
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++) {
808 for (x = 0; x < segcount; x++) {
818 JABBER_MAIN(
"jabberd2s2s",
"Jabber 2 S2S",
"Jabber Open Source Server: Server to Server",
"jabberd2router\0")
828 time_t check_time = 0, now = 0;
829 const char *cli_id = 0;
832 umask((mode_t) 0027);
837 #ifdef HAVE_WINSOCK2_H
840 WORD wVersionRequested;
844 wVersionRequested = MAKEWORD( 2, 2 );
846 err = WSAStartup( wVersionRequested, &wsaData );
871 config_file = CONFIG_DIR
"/s2s.xml";
874 while((optchar = getopt(argc, argv,
"Dc:hi:?")) >= 0)
879 config_file = optarg;
885 printf(
"WARN: Debugging not enabled. Ignoring -D.\n");
891 case 'h':
case '?':
default:
893 "s2s - jabberd server-to-server connector (" VERSION
")\n"
894 "Usage: s2s <options>\n"
896 " -c <config> config file to use [default: " CONFIG_DIR
"/s2s.xml]\n"
897 " -i id Override <id> config element\n"
899 " -D Show debug output\n"
910 fputs(
"s2s: couldn't load config, aborting\n", stderr);
942 log_write(s2s->
log, LOG_ERR,
"failed to load local SSL pemfile, SSL will not be available to peers");
945 log_debug(
ZONE,
"loaded pemfile for SSL connections to peers");
952 log_write(s2s->
log, LOG_ERR,
"failed to load router SSL pemfile, channel to router will not be SSL encrypted");
967 log_write(s2s->
log, LOG_ERR,
"failed to initialise SASL context, aborting");
979 if((s2s->
udns_fd = dns_init(NULL, 1)) < 0) {
980 log_write(s2s->
log, LOG_ERR,
"unable to initialize dns library, aborting");
989 mio_run(s2s->
mio, dns_timeouts(0, 5, time(NULL)));
1006 log_write(s2s->
log, LOG_NOTICE,
"attempting reconnect");
1041 free((
void*)conn->
key);
1042 free((
void*)conn->
dkey);
1066 if(now > check_time + 60) {
1071 int fd = open(s2s->
packet_stats, O_TRUNC | O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR | S_IRGRP);
1074 int len = snprintf(buf, 100,
"%lld\n", s2s->
packet_count);
1075 write(fd, buf, len);
1144 if(conn->
key != NULL) free((
void*)conn->
key);
1145 if(conn->
dkey != NULL) free((
void*)conn->
dkey);
1166 if (dns->
query != NULL) {
1181 free((
void*)res->
key);
1185 if (dns_active(NULL) > 0)
1186 log_debug(
ZONE,
"there are still active dns queries (%d)", dns_active(NULL));
static sig_atomic_t s2s_logrotate
int retry_init
connect retry
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
char ip[INET6_ADDRSTRLEN+1]
sx_t router
router's conn
int config_load_with_id(config_t c, const char *file, const char *id)
turn an xml file into a config hash
static int _s2s_populate_whitelist_domains(s2s_t s2s, const char **values, int nvalues)
const char * local_ip
ip/port to listen on
time_t expiry
time that this entry expires
int s2s_router_mio_callback(mio_t m, mio_action_t a, mio_fd_t fd, void *data, void *arg)
void config_free(config_t c)
cleanup
int s2s_db_init(sx_env_t env, sx_plugin_t p, va_list args)
xht hosts
srv lookup results (key host/port)
mio_t mio_new(int maxfd)
create/free the mio subsytem
#define mio_run(m, timeout)
give some cpu time to mio to check it's sockets, 0 is non-blocking
jqueue_t dead
list of sx_t on the way out
struct dnsres_st * dnsres_t
void * xhash_getx(xht h, const char *key, int len)
int jqueue_size(jqueue_t q)
char ** whitelist_domains
void log_write(log_t log, int level, const char *msgfmt,...)
const char * router_ip
how to connect to the router
void xhash_iter_zap(xht h)
xht in_accept
incoming conns prior to stream initiation (key is ip/port)
int s2s_router_sx_callback(sx_t s, sx_event_t e, void *data, void *arg)
our master callback
sx_t sx_new(sx_env_t env, int tag, sx_callback_t cb, void *arg)
config_t config_new(void)
new config structure
const char ** lookup_srv
srvs to lookup
static char * config_file
int verify
number and last timestamp of outstanding db:verify requests
char * host_private_key_password
private key password
void sx_raw_write(sx_t s, const char *buf, int len)
app version
xht states
states of outgoing dialbacks (key is local/remote)
int j_atoi(const char *a, int def)
int out_bounce_route_queue(s2s_t s2s, const char *rkey, int rkeylen, int err)
void out_pkt_free(pkt_t pkt)
mio_action_t
these are the actions and a handler type assigned by the applicaiton using mio
int host_verify_mode
verify-mode
xht outq
queues of packets waiting to go out (key is route)
const char * packet_stats
time_t expiry
time that this entry expires
xht out_host
outgoing conns (key is ip/port)
int xhash_iter_next(xht h)
long long int packet_count
packet counter
sx_env_t sx_env_new(void)
#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) ...
xht dnscache
dns resolution cache
xht out_dest
outgoing conns (key is dest)
xht routes
routes that this conn handles (key is local/remote)
#define mio_read(m, fd)
process read events for this fd
static void _s2s_pidfile(s2s_t s2s)
store the process id
char * config_get_attr(config_t c, const char *key, int num, const char *attr)
get an attr for this value
void jqueue_free(jqueue_t q)
xht dns_bad
dns resolution bad host cache
#define MIO_ERROR
all MIO related routines should use those for error reporting
sx_env_t sx_env
sx environment
#define stanza_err_REMOTE_SERVER_TIMEOUT
int compression
enable Stream Compression
static void _s2s_signal(int signum)
int etc_hosts_ttl
/etc/hosts ttl limits
int pending
set when we're waiting for a resolve response
sx_plugin_t sx_env_plugin(sx_env_t env, sx_plugin_init_t init,...)
load a plugin into the environment
int stanza_size_limit
maximum stanza size
holds the state for a single stream
#define stream_err_SYSTEM_SHUTDOWN
int local_verify_mode
verify-mode
const char * local_cachain
certificate chain
packet summary data wrapper
void * pmalloco(pool_t p, int size)
easy safety utility (for creating blank mem for structs, etc)
void sx_client_init(sx_t s, unsigned int flags, const char *ns, const char *to, const char *from, const char *version)
void set_debug_log_from_config(config_t c)
const char * log_facility
xht results
results (key ip/port)
char name[1024]
the name proper
int s2s_domain_in_whitelist(s2s_t s2s, const char *in_domain)
const char * realm
our realm (SASL)
jqueue_t dead_conn
list of conn_t on the way out
void xhash_put(xht h, const char *key, void *val)
xht states_time
time of the last state change (key is local/remote)
xht results
host lookup results (key ip/port)
const char * local_secret
dialback secret
int xhash_iter_get(xht h, const char **key, int *keylen, void **val)
#define stanza_err_REMOTE_SERVER_NOT_FOUND
const char * host_pemfile
starttls pemfile
static int _s2s_router_connect(s2s_t s2s)
void xhash_zap(xht h, const char *key)
jsighandler_t * jabber_signal(int signo, jsighandler_t *func)
const char * name
domain name
int out_reuse
reuse outgoing conns keyed by ip/port
void xhash_zapx(xht h, const char *key, int len)
const char * router_pemfile
int check_interval
time checks
mio_fd_t server_fd
listening sockets
char * dns_make_ipport(const char *host, int port)
void sx_error(sx_t s, int err, const char *text)
static void _s2s_signal_hup(int signum)
JABBERD2_API int sx_sasl_init(sx_env_t env, sx_plugin_t p, va_list args)
init function
static void _s2s_time_checks(s2s_t s2s)
config_elem_t config_get(config_t c, const char *key)
get the config element for this key
int io_max_fds
max file descriptors
#define stream_err_CONNECTION_TIMEOUT
int resolve_aaaa
if we resolve AAAA records
void * jqueue_pull(jqueue_t q)
int xhash_count(xht h)
return the total number of entries in this xht
const char ** origin_ips
ip(s) to originate connections from
static void _s2s_config_expand(s2s_t s2s)
pull values out of the config file
struct dns_query * query
set when we're waiting for a resolve response
int xhash_iter_first(xht h)
iteration
jqueue_t jqueue_new(void)
sig_atomic_t s2s_lost_router
void set_debug_flag(int v)
const char * router_private_key_password
int sx_ssl_init(sx_env_t env, sx_plugin_t p, va_list args)
args: name, pemfile, cachain, mode
int _s2s_check_conn_routes(s2s_t s2s, conn_t conn, const char *direction)
static void _s2s_signal_usr2(int signum)
static void _s2s_hosts_expand(s2s_t s2s)
int sx_compress_init(sx_env_t env, sx_plugin_t p, va_list args)
args: none
pool_t xhash_pool(xht h)
get our pool
int out_bounce_conn_queues(conn_t out, int err)
const char * id
our id (hostname) with the router
log_type_t log_type
log data
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...
const char * router_cachain
xht in
incoming conns (key is stream id)
void * xhash_get(xht h, const char *key)
#define mio_close(m, fd)
request that mio close this fd
#define JABBER_MAIN(name, display, description, depends)
char * j_attr(const char **atts, const char *attr)
const char * local_private_key_password
private key password for local pemfile, if encrypted
static sig_atomic_t s2s_shutdown
log_t log_new(log_type_t type, const char *ident, const char *facility)
int require_tls
Apple security options.
one item in the dns resolution cache
const char * config_get_one(config_t c, const char *key, int num)
get config value n for this key
void sx_env_free(sx_env_t env)
static void _s2s_signal_usr1(int signum)
#define mio_register(m, fd, app, arg)
for adding an existing socket connected to this mio
#define stanza_err_SERVICE_UNAVAILABLE
int config_count(config_t c, const char *key)
how many values for this key?
static int _mio_resolver_callback(mio_t m, mio_action_t a, mio_fd_t fd, void *data, void *arg)
responses from the resolver
const char * local_pemfile
pemfile for peer connections
time_t last_activity
timestamps for idle timeouts
int dns_min_ttl
dns ttl limits
static void _s2s_dns_expiry(s2s_t s2s)
const char * host_cachain
certificate chain