jabberd2  2.3.3
router.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 "router.h"
22 
23 #define MAX_JID 3072 // node(1023) + '@'(1) + domain(1023) + '/'(1) + resource(1023) + '\0'(1)
24 #define MAX_MESSAGE 65535
25 #define SECS_PER_DAY 86400
26 #define BYTES_PER_MEG 1048576
27 
29 typedef struct broadcast_st {
33 } *broadcast_t;
34 
36 static void _router_broadcast(const char *key, int keylen, void *val, void *arg) {
37  int i;
38  broadcast_t bc = (broadcast_t) arg;
39  routes_t routes = (routes_t) val;
40 
41  for(i = 0; i < routes->ncomp; i++) {
42  /* I don't care about myself or the elderly (!?) */
43  if(routes->comp[i] == bc->src || routes->comp[i]->legacy)
44  continue;
45 
46  sx_nad_write(routes->comp[i]->s, nad_copy(bc->nad));
47  }
48 }
49 
51 static void _router_advertise(router_t r, const char *domain, component_t src, int unavail) {
52  struct broadcast_st bc;
53  int ns;
54 
55  log_debug(ZONE, "advertising %s to all routes (unavail=%d)", domain, unavail);
56 
57  bc.r = r;
58  bc.src = src;
59 
60  /* create a new packet */
61  bc.nad = nad_new();
62  ns = nad_add_namespace(bc.nad, uri_COMPONENT, NULL);
63  nad_append_elem(bc.nad, ns, "presence", 0);
64  nad_append_attr(bc.nad, -1, "from", domain);
65  if(unavail)
66  nad_append_attr(bc.nad, -1, "type", "unavailable");
67 
68  xhash_walk(r->routes, _router_broadcast, (void *) &bc);
69 
70  nad_free(bc.nad);
71 }
72 
74 static void _router_advertise_reverse(const char *key, int keylen, void *val, void *arg) {
75  component_t dest = (component_t) arg;
76  routes_t routes = (routes_t) val;
77  int el, ns, i;
78  nad_t nad;
79 
80  assert((int) (routes->name != NULL));
81  assert((int) (routes->comp != NULL));
82  assert(routes->ncomp);
83 
84  /* don't tell me about myself */
85  for(i = 0; i < routes->ncomp; i++)
86  if(routes->comp[i] == dest)
87  return;
88 
89  log_debug(ZONE, "informing component about %.*s", keylen, key);
90 
91  /* create a new packet */
92  nad = nad_new();
93  ns = nad_add_namespace(nad, uri_COMPONENT, NULL);
94  el = nad_append_elem(nad, ns, "presence", 0);
95  nad_set_attr(nad, el, -1, "from", key, keylen);
96 
97  sx_nad_write(dest->s, nad);
98 }
99 
101  char *hash;
102  int hashlen;
103 
104  /* must have a hash as cdata */
105  if(NAD_CDATA_L(nad, 0) != 40) {
106  log_debug(ZONE, "handshake isn't long enough to be a sha1 hash");
107  sx_error(comp->s, stream_err_NOT_AUTHORIZED, "handshake isn't long enough to be a sha1 hash");
108  sx_close(comp->s);
109 
110  nad_free(nad);
111  return;
112  }
113 
114  /* make room for shahash_r to work .. needs at least 41 chars */
115  hashlen = strlen(comp->s->id) + strlen(comp->r->local_secret) + 1;
116  if(hashlen < 41)
117  hashlen = 41;
118 
119  /* build the creds and hash them */
120  hash = (char *) malloc(sizeof(char) * hashlen);
121  sprintf(hash, "%s%s", comp->s->id, comp->r->local_secret);
122  shahash_r(hash, hash);
123 
124  /* check */
125  log_debug(ZONE, "checking their hash %.*s against our hash %s", 40, NAD_CDATA(nad, 0), hash);
126 
127  if(strncmp(hash, NAD_CDATA(nad, 0), 40) == 0) {
128  log_debug(ZONE, "handshake succeeded");
129 
130  free(hash);
131 
132  /* respond */
133  nad->elems[0].icdata = nad->elems[0].itail = -1;
134  nad->elems[0].lcdata = nad->elems[0].ltail = 0;
135  sx_nad_write(comp->s, nad);
136 
137  sx_auth(comp->s, "handshake", comp->s->req_to);
138 
139  return;
140  }
141 
142  log_debug(ZONE, "auth failed");
143 
144  free(hash);
145 
146  /* failed, let them know */
147  sx_error(comp->s, stream_err_NOT_AUTHORIZED, "hash didn't match, auth failed");
148  sx_close(comp->s);
149 
150  nad_free(nad);
151 }
152 
153 void routes_free(routes_t routes) {
154  if(routes->name) free((void*)routes->name);
155  if(routes->comp) free(routes->comp);
156  free(routes);
157 }
158 
159 static int _route_add(xht hroutes, const char *name, component_t comp, route_type_t rtype) {
160  routes_t routes;
161 
162  routes = xhash_get(hroutes, name);
163  if(routes == NULL) {
164  routes = (routes_t) calloc(1, sizeof(struct routes_st));
165  routes->name = strdup(name);
166  routes->rtype = rtype;
167  }
168  routes->comp = (component_t *) realloc(routes->comp, sizeof(component_t *) * (routes->ncomp + 1));
169  routes->comp[routes->ncomp] = comp;
170  routes->ncomp++;
171  xhash_put(hroutes, routes->name, (void *) routes);
172 
173  if(routes->rtype != rtype)
174  log_write(comp->r->log, LOG_ERR, "Mixed route types for '%s' bind request", name);
175 
176  return routes->ncomp;
177 }
178 
179 static void _route_remove(xht hroutes, const char *name, component_t comp) {
180  routes_t routes;
181  int i;
182 
183  routes = xhash_get(hroutes, name);
184  if(routes == NULL) return;
185 
186  if(routes->ncomp > 1) {
187  for(i = 0; i < routes->ncomp; i++) {
188  if(routes->comp[i] == comp) {
189  if(i != routes->ncomp - 1) {
190  routes->comp[i] = routes->comp[routes->ncomp - 1];
191  }
192  routes->ncomp--;
193  }
194  }
195  }
196  else {
197  jqueue_push(comp->r->deadroutes, (void *) routes, 0);
198  xhash_zap(hroutes, name);
199  }
200 }
201 
203  int attr, multi, n;
204  jid_t name;
205  alias_t alias;
206  char *user, *c;
207 
208  attr = nad_find_attr(nad, 0, -1, "name", NULL);
209  if(attr < 0 || (name = jid_new(NAD_AVAL(nad, attr), NAD_AVAL_L(nad, attr))) == NULL) {
210  log_debug(ZONE, "no or invalid 'name' on bind packet, bouncing");
211  nad_set_attr(nad, 0, -1, "error", "400", 3);
212  sx_nad_write(comp->s, nad);
213  return;
214  }
215 
216  user = strdup(comp->s->auth_id);
217  c = strchr(user, '@');
218  if(c != NULL) *c = '\0';
219 
220  if(strcmp(user, name->domain) != 0 && !aci_check(comp->r->aci, "bind", user)) {
221  log_write(comp->r->log, LOG_NOTICE, "[%s, port=%d] tried to bind '%s', but their username (%s) is not permitted to bind other names", comp->ip, comp->port, name->domain, user);
222  nad_set_attr(nad, 0, -1, "name", NULL, 0);
223  nad_set_attr(nad, 0, -1, "error", "403", 3);
224  sx_nad_write(comp->s, nad);
225  jid_free(name);
226  free(user);
227  return;
228  }
229 
230  multi = nad_find_attr(nad, 0, -1, "multi", NULL);
231  if(xhash_get(comp->r->routes, name->domain) != NULL && multi < 0) {
232  log_write(comp->r->log, LOG_NOTICE, "[%s, port=%d] tried to bind '%s', but it's already bound", comp->ip, comp->port, name->domain);
233  nad_set_attr(nad, 0, -1, "name", NULL, 0);
234  nad_set_attr(nad, 0, -1, "error", "409", 3);
235  sx_nad_write(comp->s, nad);
236  jid_free(name);
237  free(user);
238  return;
239  }
240 
241  for(alias = comp->r->aliases; alias != NULL; alias = alias->next)
242  if(strcmp(alias->name, name->domain) == 0) {
243  log_write(comp->r->log, LOG_NOTICE, "[%s, port=%d] tried to bind '%s', but that name is aliased", comp->ip, comp->port);
244  nad_set_attr(nad, 0, -1, "name", NULL, 0);
245  nad_set_attr(nad, 0, -1, "error", "409", 3);
246  sx_nad_write(comp->s, nad);
247  jid_free(name);
248  free(user);
249  return;
250  }
251 
252  /* default route */
253  if(nad_find_elem(nad, 0, NAD_ENS(nad, 0), "default", 1) >= 0) {
254  if(!aci_check(comp->r->aci, "default-route", user)) {
255  log_write(comp->r->log, LOG_NOTICE, "[%s, port=%d] tried to bind '%s' as the default route, but their username (%s) is not permitted to set a default route", comp->ip, comp->port, name->domain, user);
256  nad_set_attr(nad, 0, -1, "name", NULL, 0);
257  nad_set_attr(nad, 0, -1, "error", "403", 3);
258  sx_nad_write(comp->s, nad);
259  jid_free(name);
260  free(user);
261  return;
262  }
263 
264  if(comp->r->default_route != NULL) {
265  log_write(comp->r->log, LOG_NOTICE, "[%s, port=%d] tried to bind '%s' as the default route, but one already exists", comp->ip, comp->port, name->domain);
266  nad_set_attr(nad, 0, -1, "name", NULL, 0);
267  nad_set_attr(nad, 0, -1, "error", "409", 3);
268  sx_nad_write(comp->s, nad);
269  jid_free(name);
270  return;
271  }
272 
273  log_write(comp->r->log, LOG_NOTICE, "[%s] set as default route", name->domain);
274 
275  comp->r->default_route = strdup(name->domain);
276  }
277 
278  /* log sinks */
279  if(nad_find_elem(nad, 0, NAD_ENS(nad, 0), "log", 1) >= 0) {
280  if(!aci_check(comp->r->aci, "log", user)) {
281  log_write(comp->r->log, LOG_NOTICE, "[%s, port=%d] tried to bind '%s' as a log sink, but their username (%s) is not permitted to do this", comp->ip, comp->port, name->domain, user);
282  nad_set_attr(nad, 0, -1, "name", NULL, 0);
283  nad_set_attr(nad, 0, -1, "error", "403", 3);
284  sx_nad_write(comp->s, nad);
285  jid_free(name);
286  free(user);
287  return;
288  }
289 
290  log_write(comp->r->log, LOG_NOTICE, "[%s] set as log sink", name->domain);
291 
292  xhash_put(comp->r->log_sinks, pstrdup(xhash_pool(comp->r->log_sinks), name->domain), (void *) comp);
293  }
294 
295  free(user);
296 
297  n = _route_add(comp->r->routes, name->domain, comp, multi<0?route_SINGLE:route_MULTI_TO);
298  xhash_put(comp->routes, pstrdup(xhash_pool(comp->routes), name->domain), (void *) comp);
299 
300  if(n>1)
301  log_write(comp->r->log, LOG_NOTICE, "[%s]:%d online (bound to %s, port %d)", name->domain, n, comp->ip, comp->port);
302  else
303  log_write(comp->r->log, LOG_NOTICE, "[%s] online (bound to %s, port %d)", name->domain, comp->ip, comp->port);
304 
305  nad_set_attr(nad, 0, -1, "name", NULL, 0);
306  sx_nad_write(comp->s, nad);
307 
308  /* advertise name */
309  _router_advertise(comp->r, name->domain, comp, 0);
310 
311  /* tell the new component about everyone else */
312  xhash_walk(comp->r->routes, _router_advertise_reverse, (void *) comp);
313 
314  /* bind aliases */
315  for(alias = comp->r->aliases; alias != NULL; alias = alias->next) {
316  if(strcmp(alias->target, name->domain) == 0) {
317  _route_add(comp->r->routes, name->domain, comp, route_MULTI_TO);
318  xhash_put(comp->routes, pstrdup(xhash_pool(comp->routes), alias->name), (void *) comp);
319 
320  log_write(comp->r->log, LOG_NOTICE, "[%s] online (alias of '%s', bound to %s, port %d)", alias->name, name->domain, comp->ip, comp->port);
321 
322  /* advertise name */
323  _router_advertise(comp->r, alias->name, comp, 0);
324  }
325  }
326 
327  /* done with this */
328  jid_free(name);
329 }
330 
332  int attr;
333  jid_t name;
334 
335  attr = nad_find_attr(nad, 0, -1, "name", NULL);
336  if(attr < 0 || (name = jid_new(NAD_AVAL(nad, attr), NAD_AVAL_L(nad, attr))) == NULL) {
337  log_debug(ZONE, "no or invalid 'name' on unbind packet, bouncing");
338  nad_set_attr(nad, 0, -1, "error", "400", 3);
339  sx_nad_write(comp->s, nad);
340  return;
341  }
342 
343  if(xhash_get(comp->routes, name->domain) == NULL) {
344  log_write(comp->r->log, LOG_NOTICE, "[%s, port=%d] tried to unbind '%s', but it's not bound to this component", comp->ip, comp->port, name->domain);
345  nad_set_attr(nad, 0, -1, "name", NULL, 0);
346  nad_set_attr(nad, 0, -1, "error", "404", 3);
347  sx_nad_write(comp->s, nad);
348  jid_free(name);
349  return;
350  }
351 
352  xhash_zap(comp->r->log_sinks, name->domain);
353  _route_remove(comp->r->routes, name->domain, comp);
354  xhash_zap(comp->routes, name->domain);
355 
356  if(comp->r->default_route != NULL && strcmp(comp->r->default_route, name->domain) == 0) {
357  log_write(comp->r->log, LOG_NOTICE, "[%s] default route offline", name->domain);
358  free((void*)(comp->r->default_route));
359  comp->r->default_route = NULL;
360  }
361 
362  log_write(comp->r->log, LOG_NOTICE, "[%s] offline", name->domain);
363 
364  nad_set_attr(nad, 0, -1, "name", NULL, 0);
365  sx_nad_write(comp->s, nad);
366 
367  /* deadvertise name */
368  if(xhash_get(comp->r->routes, name->domain) == NULL)
369  _router_advertise(comp->r, name->domain, comp, 1);
370 
371  jid_free(name);
372 }
373 
375  int attr;
376 
377  if(comp->tq != NULL) {
378  log_debug(ZONE, "%s port %d is throttled, jqueueing packet", comp->ip, comp->port);
379  jqueue_push(comp->tq, nad, 0);
380  return;
381  }
382 
383  /* packets go raw to normal components */
384  if(!comp->legacy) {
385  sx_nad_write(comp->s, nad);
386  return;
387  }
388 
389  log_debug(ZONE, "packet for legacy component, munging");
390 
391  attr = nad_find_attr(nad, 0, -1, "error", NULL);
392  if(attr >= 0) {
393  if(NAD_AVAL_L(nad, attr) == 3 && strncmp("400", NAD_AVAL(nad, attr), 3) == 0)
395  else
397  }
398 
399  sx_nad_write_elem(comp->s, nad, 1);
400 }
401 
402 static void _router_route_log_sink(const char *key, int keylen, void *val, void *arg) {
403  component_t comp = (component_t) val;
404  nad_t nad = (nad_t) arg;
405 
406  log_debug(ZONE, "copying route to '%.*s' (%s, port %d)", keylen, key, comp->ip, comp->port);
407 
408  nad = nad_copy(nad);
409  nad_set_attr(nad, 0, -1, "type", "log", 3);
410  _router_comp_write(comp, nad);
411 }
412 
414  int atype, ato, afrom;
415  unsigned int dest;
416  struct jid_st sto, sfrom;
417  jid_static_buf sto_buf, sfrom_buf;
418  jid_t to = NULL, from = NULL;
419  routes_t targets;
420  component_t target;
421  union xhashv xhv;
422 
423  /* init static jid */
424  jid_static(&sto,&sto_buf);
425  jid_static(&sfrom,&sfrom_buf);
426 
427  if(nad_find_attr(nad, 0, -1, "error", NULL) >= 0) {
428  log_debug(ZONE, "dropping error packet, trying to avoid loops");
429  nad_free(nad);
430  return;
431  }
432 
433  atype = nad_find_attr(nad, 0, -1, "type", NULL);
434  ato = nad_find_attr(nad, 0, -1, "to", NULL);
435  afrom = nad_find_attr(nad, 0, -1, "from", NULL);
436 
437  if(ato >= 0) to = jid_reset(&sto, NAD_AVAL(nad, ato), NAD_AVAL_L(nad, ato));
438  if(afrom >= 0) from = jid_reset(&sfrom, NAD_AVAL(nad, afrom), NAD_AVAL_L(nad, afrom));
439 
440  /* unicast */
441  if(atype < 0) {
442  if(to == NULL || from == NULL) {
443  log_debug(ZONE, "unicast route with missing or invalid to or from, bouncing");
444  nad_set_attr(nad, 0, -1, "error", "400", 3);
445  _router_comp_write(comp, nad);
446  return;
447  }
448 
449  log_debug(ZONE, "unicast route from %s to %s", from->domain, to->domain);
450 
451  /* check the from */
452  if(xhash_get(comp->routes, from->domain) == NULL) {
453  log_write(comp->r->log, LOG_NOTICE, "[%s, port=%d] tried to send a packet from '%s', but that name is not bound to this component", comp->ip, comp->port, from->domain);
454  nad_set_attr(nad, 0, -1, "error", "401", 3);
455  _router_comp_write(comp, nad);
456  return;
457  }
458 
459  /* filter it */
460  if(comp->r->filter != NULL) {
461  int ret = filter_packet(comp->r, nad);
462  if(ret == stanza_err_REDIRECT) {
463  ato = nad_find_attr(nad, 0, -1, "to", NULL);
464  if(ato >= 0) to = jid_reset(&sto, NAD_AVAL(nad, ato), NAD_AVAL_L(nad, ato));
465  }
466  else if(ret > 0) {
467  log_debug(ZONE, "packet filtered out: %s (%s)", _stanza_errors[ret - stanza_err_BAD_REQUEST].name, _stanza_errors[ret - stanza_err_BAD_REQUEST].code);
468  nad_set_attr(nad, 0, -1, "error", _stanza_errors[ret - stanza_err_BAD_REQUEST].code, 3);
469  _router_comp_write(comp, nad);
470  return;
471  }
472  }
473 
474  /* find a target */
475  targets = xhash_get(comp->r->routes, to->domain);
476  if(targets == NULL) {
477  if(comp->r->default_route != NULL && strcmp(from->domain, comp->r->default_route) == 0) {
478  log_debug(ZONE, "%s is unbound, bouncing", from->domain);
479  nad_set_attr(nad, 0, -1, "error", "404", 3);
480  _router_comp_write(comp, nad);
481  return;
482  }
483  targets = xhash_get(comp->r->routes, comp->r->default_route);
484  }
485 
486  if(targets == NULL) {
487  log_debug(ZONE, "%s is unbound, and no default route, bouncing", to->domain);
488  nad_set_attr(nad, 0, -1, "error", "404", 3);
489  _router_comp_write(comp, nad);
490  return;
491  }
492 
493  /* copy to any log sinks */
494  if(xhash_count(comp->r->log_sinks) > 0)
495  xhash_walk(comp->r->log_sinks, _router_route_log_sink, (void *) nad);
496 
497  /* get route candidate */
498  if(targets->ncomp == 1) {
499  dest = 0;
500  }
501  else {
502  switch(targets->rtype) {
503  case route_MULTI_TO:
504  ato = nad_find_attr(nad, 1, -1, "to", NULL);
505  if(ato >= 0) to = jid_reset(&sto, NAD_AVAL(nad, ato), NAD_AVAL_L(nad, ato));
506  else {
507  ato = nad_find_attr(nad, 1, -1, "target", NULL);
508  if(ato >= 0) to = jid_reset(&sto, NAD_AVAL(nad, ato), NAD_AVAL_L(nad, ato));
509  else {
510  const char *out; int len;
511  nad_print(nad, 0, &out, &len);
512  log_write(comp->r->log, LOG_ERR, "Cannot get destination for multiple route: %.*s", len, out);
513  }
514  }
515  break;
516  case route_MULTI_FROM:
517  ato = nad_find_attr(nad, 1, -1, "from", NULL);
518  if(ato >= 0) to = jid_reset(&sto, NAD_AVAL(nad, ato), NAD_AVAL_L(nad, ato));
519  else {
520  const char *out; int len;
521  nad_print(nad, 0, &out, &len);
522  log_write(comp->r->log, LOG_ERR, "Cannot get source for multiple route: %.*s", len, out);
523  }
524  break;
525  default:
526  log_write(comp->r->log, LOG_ERR, "Multiple components bound to single component route '%s'", targets->name);
527  /* simulate no 'to' info in this case */
528  }
529  if(to->node == NULL || strlen(to->node) == 0) {
530  /* no node in destination JID - going random */
531  dest = rand();
532  log_debug(ZONE, "randomized to %u %% %d = %d", dest, targets->ncomp, dest % targets->ncomp);
533  }
534  else {
535  /* use JID hash */
536  unsigned char hashval[20];
537  unsigned int *val;
538  int i;
539 
540  shahash_raw(jid_user(to), hashval);
541 
542  val = (unsigned int *) hashval;
543  dest = *val;
544  for(i=1; i < 20 / (sizeof(unsigned int)/sizeof(unsigned char)); i++, val++) {
545  dest ^= *val;
546  }
547  dest >>= 2;
548 
549  log_debug(ZONE, "JID %s hashed to %u %% %d = %d", jid_user(to), dest, targets->ncomp, dest % targets->ncomp);
550 
551  /* jid_user() calls jid_expand() which may allocate some memory in _user and _full */
552  if (to->_user != NULL )
553  free(to->_user);
554  if (to->_full != NULL )
555  free(to->_full);
556  }
557  dest = dest % targets->ncomp;
558  }
559 
560  target = targets->comp[dest];
561 
562  /* push it out */
563  log_debug(ZONE, "writing route for '%s'*%u to %s, port %d", to->domain, dest+1, target->ip, target->port);
564 
565  /* if logging enabled, log messages that match our criteria */
566  if (comp->r->message_logging_enabled && comp->r->message_logging_file != NULL) {
567  int attr_msg_to;
568  int attr_msg_from;
569  int attr_route_to;
570  int attr_route_from;
571  jid_t jid_msg_from = NULL;
572  jid_t jid_msg_to = NULL;
573  jid_t jid_route_from = NULL;
574  jid_t jid_route_to = NULL;
575 
576  if ((NAD_ENAME_L(nad, 1) == 7 && strncmp("message", NAD_ENAME(nad, 1), 7) == 0) && // has a "message" element
577  ((attr_route_from = nad_find_attr(nad, 0, -1, "from", NULL)) >= 0) &&
578  ((attr_route_to = nad_find_attr(nad, 0, -1, "to", NULL)) >= 0) &&
579  ((strncmp(NAD_AVAL(nad, attr_route_to), "c2s", 3)) != 0) && // ignore messages to "c2s" or we'd have dups
580  ((jid_route_from = jid_new(NAD_AVAL(nad, attr_route_from), NAD_AVAL_L(nad, attr_route_from))) != NULL) && // has valid JID source in route
581  ((jid_route_to = jid_new(NAD_AVAL(nad, attr_route_to), NAD_AVAL_L(nad, attr_route_to))) != NULL) && // has valid JID destination in route
582  ((attr_msg_from = nad_find_attr(nad, 1, -1, "from", NULL)) >= 0) &&
583  ((attr_msg_to = nad_find_attr(nad, 1, -1, "to", NULL)) >= 0) &&
584  ((jid_msg_from = jid_new(NAD_AVAL(nad, attr_msg_from), NAD_AVAL_L(nad, attr_msg_from))) != NULL) && // has valid JID source in message
585  ((jid_msg_to = jid_new(NAD_AVAL(nad, attr_msg_to), NAD_AVAL_L(nad, attr_msg_to))) != NULL)) // has valid JID dest in message
586  {
587  message_log(nad, comp->r, jid_full(jid_msg_from), jid_full(jid_msg_to));
588  }
589  if (jid_msg_from != NULL)
590  jid_free(jid_msg_from);
591  if (jid_msg_to != NULL)
592  jid_free(jid_msg_to);
593  if (jid_route_from != NULL)
594  jid_free(jid_route_from);
595  if (jid_route_to != NULL)
596  jid_free(jid_route_to);
597  }
598 
599  _router_comp_write(target, nad);
600 
601  return;
602  }
603 
604  /* broadcast */
605  if(NAD_AVAL_L(nad, atype) == 9 && strncmp("broadcast", NAD_AVAL(nad, atype), 9) == 0) {
606  if(from == NULL) {
607  log_debug(ZONE, "broadcast route with missing or invalid from, bouncing");
608  nad_set_attr(nad, 0, -1, "error", "400", 3);
609  _router_comp_write(comp, nad);
610  return;
611  }
612 
613  log_debug(ZONE, "broadcast route from %s", from->domain);
614 
615  /* check the from */
616  if(xhash_get(comp->routes, from->domain) == NULL) {
617  log_write(comp->r->log, LOG_NOTICE, "[%s, port=%d] tried to send a packet from '%s', but that name is not bound to this component", comp->ip, comp->port, from->domain);
618  nad_set_attr(nad, 0, -1, "error", "401", 3);
619  _router_comp_write(comp, nad);
620  return;
621  }
622 
623  /* loop the components and distribute */
624  if(xhash_iter_first(comp->r->components))
625  do {
626  xhv.comp_val = &target;
627  xhash_iter_get(comp->r->components, NULL, NULL, xhv.val);
628 
629  if(target != comp) {
630  log_debug(ZONE, "writing broadcast to %s, port %d", target->ip, target->port);
631 
632  _router_comp_write(target, nad_copy(nad));
633  }
634  } while(xhash_iter_next(comp->r->components));
635 
636  nad_free(nad);
637 
638  return;
639  }
640 
641  log_debug(ZONE, "unknown route type '%.*s', dropping", NAD_AVAL_L(nad, atype), NAD_AVAL(nad, atype));
642 
643  nad_free(nad);
644 }
645 
647  jqueue_t tq;
648  nad_t pkt;
649 
650  if(comp->tq == NULL) {
651  _router_comp_write(comp, nad);
652 
653  log_write(comp->r->log, LOG_NOTICE, "[%s, port=%d] throttling packets on request", comp->ip, comp->port);
654  comp->tq = jqueue_new();
655  }
656 
657  else {
658  log_write(comp->r->log, LOG_NOTICE, "[%s, port=%d] unthrottling packets on request", comp->ip, comp->port);
659  tq = comp->tq;
660  comp->tq = NULL;
661 
662  _router_comp_write(comp, nad);
663 
664  while((pkt = jqueue_pull(tq)) != NULL)
665  _router_comp_write(comp, pkt);
666 
667  jqueue_free(tq);
668  }
669 }
670 
671 static int _router_sx_callback(sx_t s, sx_event_t e, void *data, void *arg) {
672  component_t comp = (component_t) arg;
673  sx_buf_t buf = (sx_buf_t) data;
674  int rlen, len, attr, ns, sns, n;
675  sx_error_t *sxe;
676  nad_t nad;
677  struct jid_st sto, sfrom;
678  jid_static_buf sto_buf, sfrom_buf;
679  jid_t to, from;
680  alias_t alias;
681 
682  /* init static jid */
683  jid_static(&sto,&sto_buf);
684  jid_static(&sfrom,&sfrom_buf);
685 
686  switch(e) {
687  case event_WANT_READ:
688  log_debug(ZONE, "want read");
689  mio_read(comp->r->mio, comp->fd);
690  break;
691 
692  case event_WANT_WRITE:
693  log_debug(ZONE, "want write");
694  mio_write(comp->r->mio, comp->fd);
695  break;
696 
697  case event_READ:
698  log_debug(ZONE, "reading from %d", comp->fd->fd);
699 
700  /* check rate limits */
701  if(comp->rate != NULL) {
702  if(rate_check(comp->rate) == 0) {
703 
704  /* inform the app if we haven't already */
705  if(!comp->rate_log) {
706  log_write(comp->r->log, LOG_NOTICE, "[%s, port=%d] is being byte rate limited", comp->ip, comp->port);
707 
708  comp->rate_log = 1;
709  }
710 
711  log_debug(ZONE, "%d is throttled, delaying read", comp->fd->fd);
712 
713  buf->len = 0;
714  return 0;
715  }
716 
717  /* find out how much we can have */
718  rlen = rate_left(comp->rate);
719  if(rlen > buf->len)
720  rlen = buf->len;
721  }
722 
723  /* no limit, just read as much as we can */
724  else
725  rlen = buf->len;
726 
727  /* do the read */
728  len = recv(comp->fd->fd, buf->data, rlen, 0);
729 
730  /* update rate limits */
731  if(comp->rate != NULL && len > 0) {
732  comp->rate_log = 0;
733  rate_add(comp->rate, len);
734  }
735 
736  if(len < 0) {
737  if(MIO_WOULDBLOCK) {
738  buf->len = 0;
739  return 0;
740  }
741 
742  log_debug(ZONE, "read failed: %s", strerror(errno));
743 
744  sx_kill(comp->s);
745 
746  return -1;
747  }
748 
749  else if(len == 0) {
750  /* they went away */
751  sx_kill(comp->s);
752 
753  return -1;
754  }
755 
756  log_debug(ZONE, "read %d bytes", len);
757 
758  buf->len = len;
759 
760  return len;
761 
762  case event_WRITE:
763  log_debug(ZONE, "writing to %d", comp->fd->fd);
764 
765  len = send(comp->fd->fd, buf->data, buf->len, 0);
766  if(len >= 0) {
767  log_debug(ZONE, "%d bytes written", len);
768  return len;
769  }
770 
771  if(MIO_WOULDBLOCK)
772  return 0;
773 
774  log_debug(ZONE, "write failed: %s", strerror(errno));
775 
776  sx_kill(comp->s);
777 
778  return -1;
779 
780  case event_ERROR:
781  sxe = (sx_error_t *) data;
782  log_write(comp->r->log, LOG_NOTICE, "[%s, port=%d] error: %s (%s)", comp->ip, comp->port, sxe->generic, sxe->specific);
783 
784  break;
785 
786  case event_STREAM:
787 
788  /* legacy check */
789  if(s->ns == NULL || strcmp("jabber:component:accept", s->ns) != 0)
790  return 0;
791 
792  /* component, old skool */
793  comp->legacy = 1;
794 
795  /* enabled? */
796  if(comp->r->local_secret == NULL) {
797  sx_error(s, stream_err_INVALID_NAMESPACE, "support for legacy components not available"); /* !!! correct error? */
798  sx_close(s);
799  return 0;
800  }
801 
802  /* sanity */
803  if(s->req_to == NULL) {
804  sx_error(s, stream_err_HOST_UNKNOWN, "no 'to' attribute on stream header");
805  sx_close(s);
806  return 0;
807  }
808 
809  break;
810 
811  case event_OPEN:
812 
813  log_write(comp->r->log, LOG_NOTICE, "[%s, port=%d] authenticated as %s", comp->ip, comp->port, comp->s->auth_id);
814 
815  /* make a route for legacy components */
816  if(comp->legacy) {
817  for(alias = comp->r->aliases; alias != NULL; alias = alias->next)
818  if(strcmp(alias->name, s->req_to) == 0) {
819  sx_error(s, stream_err_HOST_UNKNOWN, "requested name is aliased"); /* !!! correct error? */
820  sx_close(s);
821  return 0;
822  }
823 
824 
825  n = _route_add(comp->r->routes, s->req_to, comp, route_MULTI_FROM);
826  xhash_put(comp->routes, pstrdup(xhash_pool(comp->routes), s->req_to), (void *) comp);
827 
828  if(n>1)
829  log_write(comp->r->log, LOG_NOTICE, "[%s]:%d online (bound to %s, port %d)", s->req_to, n, comp->ip, comp->port);
830  else
831  log_write(comp->r->log, LOG_NOTICE, "[%s] online (bound to %s, port %d)", s->req_to, comp->ip, comp->port);
832 
833  /* advertise the name */
834  _router_advertise(comp->r, s->req_to, comp, 0);
835 
836  /* this is a legacy component, so we don't tell it about other routes */
837 
838  /* bind aliases */
839  for(alias = comp->r->aliases; alias != NULL; alias = alias->next) {
840  if(strcmp(alias->target, s->req_to) == 0) {
841  _route_add(comp->r->routes, alias->name, comp, route_MULTI_FROM);
842  xhash_put(comp->routes, pstrdup(xhash_pool(comp->routes), alias->name), (void *) comp);
843 
844  log_write(comp->r->log, LOG_NOTICE, "[%s] online (alias of '%s', bound to %s, port %d)", alias->name, s->req_to, comp->ip, comp->port);
845 
846  /* advertise name */
847  _router_advertise(comp->r, alias->name, comp, 0);
848  }
849  }
850  }
851 
852  break;
853 
854  case event_PACKET:
855  nad = (nad_t) data;
856 
857  /* preauth */
858  if(comp->s->state == state_STREAM) {
859  /* non-legacy components can't do anything before auth */
860  if(!comp->legacy) {
861  log_debug(ZONE, "stream is preauth, dropping packet");
862  nad_free(nad);
863  return 0;
864  }
865 
866  /* watch for handshake requests */
867  if(NAD_ENAME_L(nad, 0) != 9 || strncmp("handshake", NAD_ENAME(nad, 0), NAD_ENAME_L(nad, 0)) != 0) {
868  log_debug(ZONE, "unknown preauth packet %.*s, dropping", NAD_ENAME_L(nad, 0), NAD_ENAME(nad, 0));
869 
870  nad_free(nad);
871  return 0;
872  }
873 
874  /* process incoming handshakes */
875  _router_process_handshake(comp, nad);
876 
877  return 0;
878  }
879 
880  /* legacy processing */
881  if(comp->legacy) {
882  log_debug(ZONE, "packet from legacy component, munging it");
883 
884  attr = nad_find_attr(nad, 0, -1, "to", NULL);
885  if(attr < 0 || (to = jid_reset(&sto, NAD_AVAL(nad, attr), NAD_AVAL_L(nad, attr))) == NULL) {
886  log_debug(ZONE, "invalid or missing 'to' address on legacy packet, dropping it");
887  nad_free(nad);
888  return 0;
889  }
890 
891  attr = nad_find_attr(nad, 0, -1, "from", NULL);
892  if(attr < 0 || (from = jid_reset(&sfrom, NAD_AVAL(nad, attr), NAD_AVAL_L(nad, attr))) == NULL) {
893  log_debug(ZONE, "invalid or missing 'from' address on legacy packet, dropping it");
894  nad_free(nad);
895  return 0;
896  }
897 
898  /* rewrite component packets into client packets */
899  ns = nad_find_namespace(nad, 0, "jabber:component:accept", NULL);
900  if(ns >= 0) {
901  if(nad->elems[0].ns == ns)
902  nad->elems[0].ns = nad->nss[nad->elems[0].ns].next;
903  else {
904  for(sns = nad->elems[0].ns; sns >= 0 && nad->nss[sns].next != ns; sns = nad->nss[sns].next);
905  nad->nss[sns].next = nad->nss[nad->nss[sns].next].next;
906  }
907  }
908 
909  ns = nad_find_namespace(nad, 0, uri_CLIENT, NULL);
910  if(ns < 0) {
911  ns = nad_add_namespace(nad, uri_CLIENT, NULL);
912  nad->scope = -1;
913  nad->nss[ns].next = nad->elems[0].ns;
914  nad->elems[0].ns = ns;
915  }
916  nad->elems[0].my_ns = ns;
917 
918  /* wrap up the packet */
919  ns = nad_add_namespace(nad, uri_COMPONENT, NULL);
920 
921  nad_wrap_elem(nad, 0, ns, "route");
922 
923  nad_set_attr(nad, 0, -1, "to", to->domain, 0);
924  nad_set_attr(nad, 0, -1, "from", from->domain, 0);
925  }
926 
927  /* top element must be router scoped */
928  if(NAD_ENS(nad, 0) < 0 || NAD_NURI_L(nad, NAD_ENS(nad, 0)) != strlen(uri_COMPONENT) || strncmp(uri_COMPONENT, NAD_NURI(nad, NAD_ENS(nad, 0)), strlen(uri_COMPONENT)) != 0) {
929  log_debug(ZONE, "invalid packet namespace, dropping");
930  nad_free(nad);
931  return 0;
932  }
933 
934  /* bind a name to this component */
935  if(NAD_ENAME_L(nad, 0) == 4 && strncmp("bind", NAD_ENAME(nad, 0), 4) == 0) {
936  _router_process_bind(comp, nad);
937  return 0;
938  }
939 
940  /* unbind a name from this component */
941  if(NAD_ENAME_L(nad, 0) == 6 && strncmp("unbind", NAD_ENAME(nad, 0), 6) == 0) {
942  _router_process_unbind(comp, nad);
943  return 0;
944  }
945 
946  /* route packets */
947  if(NAD_ENAME_L(nad, 0) == 5 && strncmp("route", NAD_ENAME(nad, 0), 5) == 0) {
948  _router_process_route(comp, nad);
949  return 0;
950  }
951 
952  /* throttle packets */
953  if(NAD_ENAME_L(nad, 0) == 8 && strncmp("throttle", NAD_ENAME(nad, 0), 8) == 0) {
954  _router_process_throttle(comp, nad);
955  return 0;
956  }
957 
958  log_debug(ZONE, "unknown packet, dropping");
959 
960  nad_free(nad);
961  return 0;
962 
963  case event_CLOSED:
964  {
965  /* close comp->fd by putting it in closefd ... unless it is already there */
966  _jqueue_node_t n;
967  for (n = comp->r->closefd->front; n != NULL; n = n->prev)
968  if (n->data == comp->fd) break;
969  if (!n) jqueue_push(comp->r->closefd, (void *) comp->fd, 0 /*priority*/);
970  return 0;
971  }
972  }
973 
974  return 0;
975 }
976 
977 static int _router_accept_check(router_t r, mio_fd_t fd, const char *ip) {
978  rate_t rt;
979 
980  if(access_check(r->access, ip) == 0) {
981  log_write(r->log, LOG_NOTICE, "[%d] [%s] access denied by configuration", fd->fd, ip);
982  return 1;
983  }
984 
985  if(r->conn_rate_total != 0) {
986  rt = (rate_t) xhash_get(r->conn_rates, ip);
987  if(rt == NULL) {
989  xhash_put(r->conn_rates, pstrdup(xhash_pool(r->conn_rates), ip), (void *) rt);
990  }
991 
992  if(rate_check(rt) == 0) {
993  log_write(r->log, LOG_NOTICE, "[%d] [%s] is being rate limited", fd->fd, ip);
994  return 1;
995  }
996 
997  rate_add(rt, 1);
998  }
999 
1000  return 0;
1001 }
1002 
1003 static void _router_route_unbind_walker(const char *key, int keylen, void *val, void *arg) {
1004  component_t comp = (component_t) arg;
1005 
1006  char * local_key;
1007  xhash_zapx(comp->r->log_sinks, key, keylen);
1008  local_key = (char *) malloc(keylen + 1);
1009  memcpy(local_key, key, keylen);
1010  local_key[keylen] = 0;
1011  _route_remove(comp->r->routes, local_key, comp);
1012  xhash_zapx(comp->routes, key, keylen);
1013 
1014  if(comp->r->default_route != NULL && strlen(comp->r->default_route) == keylen && strncmp(key, comp->r->default_route, keylen) == 0) {
1015  log_write(comp->r->log, LOG_NOTICE, "[%.*s] default route offline", keylen, key);
1016  free((void*)(comp->r->default_route));
1017  comp->r->default_route = NULL;
1018  }
1019 
1020  log_write(comp->r->log, LOG_NOTICE, "[%.*s] offline", keylen, key);
1021 
1022  /* deadvertise name */
1023  if(xhash_getx(comp->r->routes, key, keylen) == NULL)
1024  _router_advertise(comp->r, local_key, comp, 1);
1025  free(local_key);
1026 }
1027 
1028 int router_mio_callback(mio_t m, mio_action_t a, mio_fd_t fd, void *data, void *arg) {
1029  component_t comp = (component_t) arg;
1030  router_t r = (router_t) arg;
1031  struct sockaddr_storage sa;
1032  socklen_t namelen = sizeof(sa);
1033  int port, nbytes;
1034 
1035  switch(a) {
1036  case action_READ:
1037  log_debug(ZONE, "read action on fd %d", fd->fd);
1038 
1039  /* they did something */
1040  comp->last_activity = time(NULL);
1041 
1042  ioctl(fd->fd, FIONREAD, &nbytes);
1043  if(nbytes == 0) {
1044  sx_kill(comp->s);
1045  return 0;
1046  }
1047 
1048  return sx_can_read(comp->s);
1049 
1050  case action_WRITE:
1051  log_debug(ZONE, "write action on fd %d", fd->fd);
1052 
1053  /* update activity timestamp */
1054  comp->last_activity = time(NULL);
1055 
1056  return sx_can_write(comp->s);
1057 
1058  case action_CLOSE:
1059  log_debug(ZONE, "close action on fd %d", fd->fd);
1060 
1061  r = comp->r;
1062 
1063  log_write(r->log, LOG_NOTICE, "[%s, port=%d] disconnect", comp->ip, comp->port);
1064 
1065  /* unbind names */
1066  xhash_walk(comp->routes, _router_route_unbind_walker, (void *) comp);
1067 
1068  /* deregister component */
1069  xhash_zap(r->components, comp->ipport);
1070 
1071  xhash_free(comp->routes);
1072 
1073  if(comp->tq != NULL)
1074  /* !!! bounce packets */
1075  jqueue_free(comp->tq);
1076 
1077  rate_free(comp->rate);
1078 
1079  jqueue_push(comp->r->dead, (void *) comp->s, 0);
1080 
1081  free(comp);
1082 
1083  break;
1084 
1085  case action_ACCEPT:
1086  log_debug(ZONE, "accept action on fd %d", fd->fd);
1087 
1088  getpeername(fd->fd, (struct sockaddr *) &sa, &namelen);
1089  port = j_inet_getport(&sa);
1090 
1091  log_write(r->log, LOG_NOTICE, "[%s, port=%d] connect", (char *) data, port);
1092 
1093  if(_router_accept_check(r, fd, (char *) data) != 0)
1094  return 1;
1095 
1096  comp = (component_t) calloc(1, sizeof(struct component_st));
1097 
1098  comp->r = r;
1099 
1100  comp->fd = fd;
1101 
1102  snprintf(comp->ip, INET6_ADDRSTRLEN, "%s", (char *) data);
1103  comp->port = port;
1104 
1105  snprintf(comp->ipport, INET6_ADDRSTRLEN + 6, "%s:%d", comp->ip, comp->port);
1106 
1107  comp->s = sx_new(r->sx_env, fd->fd, _router_sx_callback, (void *) comp);
1108  mio_app(m, fd, router_mio_callback, (void *) comp);
1109 
1110  if(r->byte_rate_total != 0)
1112 
1113  comp->routes = xhash_new(51);
1114 
1115  /* register component */
1116  log_debug(ZONE, "new component (%p) \"%s\"", comp, comp->ipport);
1117  xhash_put(r->components, comp->ipport, (void *) comp);
1118 
1119 #ifdef HAVE_SSL
1121 #else
1122  sx_server_init(comp->s, SX_SASL_OFFER);
1123 #endif
1124 
1125  break;
1126  }
1127 
1128  return 0;
1129 }
1130 
1131 
1132 int message_log(nad_t nad, router_t r, const char *msg_from, const char *msg_to) {
1133  time_t t;
1134  struct tm *time_pos;
1135  char timestamp[25];
1136  struct stat filestat;
1137  FILE *message_file;
1138  short int new_msg_file = 0;
1139  int i;
1140  int nad_body_len = 0;
1141  char *nad_body = NULL;
1142  int elem;
1143 
1144  assert((int) (nad != NULL));
1145 
1146  // Find the message body
1147  elem = nad_find_elem(nad, 0, -1, "message", 1);
1148  if (elem >= 0) {
1149  elem = nad_find_elem(nad, elem, -1, "body", 1);
1150  }
1151 
1152  // Don't log anything if we found no NAD body
1153  if (elem == -1) {
1154  return 0;
1155  }
1156 
1157  nad_body_len = NAD_CDATA_L(nad, elem);
1158  nad_body = NAD_CDATA(nad, elem);
1159 
1160  // temporary replace line endings with 0x01, ASCII: <control> SOH <start of heading>
1161  for (i = 0; i < nad_body_len; i++) {
1162  if (nad_body[i] == '\n') {
1163  nad_body[i] = 0x01;
1164  }
1165  }
1166 
1167  // Log our message
1168  umask((mode_t) 0077);
1169  if (stat(r->message_logging_file, &filestat)) {
1170  new_msg_file = 1;
1171  }
1172 
1173  if ((message_file = fopen(r->message_logging_file, "a")) == NULL) {
1174  log_write(r->log, LOG_ERR, "Unable to open message log for writing: %s", strerror(errno));
1175  return 1;
1176  }
1177 
1178  if (new_msg_file) {
1179  if (! fprintf(message_file, "# This message log is created by the jabberd router.\n"))
1180  {
1181  log_write(r->log, LOG_ERR, "Unable to write to message log: %s", strerror(errno));
1182  return 1;
1183  }
1184  fprintf(message_file, "# See router.xml for logging options.\n");
1185  fprintf(message_file, "# Format: DateTime FromJID ToJID MessageBody<line end>\n");
1186  }
1187 
1188  /* ISO8601 timestamp */
1189  t = time(NULL);
1190  time_pos = localtime(&t);
1191  if (strftime(timestamp, sizeof(timestamp), "%Y-%m-%dT%H:%M:%S%z", time_pos) == 0) {
1192  log_write(r->log, LOG_ERR, "strftime failed: %s", strerror(errno));
1193  }
1194 
1195  elem = fprintf(message_file, "%s %s %s %.*s\n", timestamp, msg_from, msg_to, nad_body_len, nad_body);
1196 
1197  fclose(message_file);
1198 
1199  // revert line endings
1200  for (i = 0; i < nad_body_len; i++) {
1201  if (nad_body[i] == 0x01) {
1202  nad_body[i] = '\n';
1203  }
1204  }
1205 
1206  if (!elem) {
1207  log_write(r->log, LOG_ERR, "Unable to write to message log: %s", strerror(errno));
1208  return 1;
1209  }
1210 
1211  return 0;
1212 }
router_t r
Definition: router.c:30
sx_env_t sx_env
sx environment
Definition: router.h:117
jqueue_t closefd
list of mio_fd_t waiting to be closed
Definition: router.h:155
#define INET6_ADDRSTRLEN
maximum length of the string representation of an IPv6 address
Definition: util_compat.h:46
xht routes
valid routes, key is route name (packet "to" address), var is component_t
Definition: router.h:137
alias_t next
Definition: router.h:218
char * _user
Definition: jid.h:58
struct nad_elem_st * elems
Definition: nad.h:95
Definition: nad.h:93
struct router_st * router_t
Definition: router.h:51
struct _stanza_error_st _stanza_errors[]
if you change these, reflect your changes in the defines in util.h
Definition: stanza.c:24
nad_t nad_new(void)
create a new nad
Definition: nad.c:125
jid_t jid_reset(jid_t jid, const char *id, int len)
build a jid from an id
Definition: jid.c:113
Definition: sx.h:113
static void _router_advertise(router_t r, const char *domain, component_t src, int unavail)
domain advertisement
Definition: router.c:51
int nad_append_attr(nad_t nad, int ns, const char *name, const char *val)
attach new attr to the last elem
Definition: nad.c:701
xht aci
access control lists
Definition: router.h:149
jqueue_t deadroutes
list of routes_t waiting to be cleaned up
Definition: router.h:158
_sx_state_t state
Definition: sx.h:313
#define NAD_CDATA_L(N, E)
Definition: nad.h:186
#define sx_nad_write(s, nad)
Definition: sx.h:166
void sx_nad_write_elem(sx_t s, nad_t nad, int elem)
app version
Definition: io.c:420
Definition: sx.h:59
int ltail
Definition: nad.h:73
route_type_t
route types
Definition: router.h:200
void xhash_free(xht h)
Definition: xhash.c:241
multi component route - route by 'from'
Definition: router.h:203
const char * jid_user(jid_t jid)
expand and return the user
Definition: jid.c:339
const char * req_to
Definition: sx.h:280
const char * jid_full(jid_t jid)
expand and return the full
Definition: jid.c:347
jid_t jid_new(const char *id, int len)
make a new jid
Definition: jid.c:81
void rate_add(rate_t rt, int count)
Add a number of events to the counter.
Definition: rate.c:48
int nad_find_elem(nad_t nad, int elem, int ns, const char *name, int depth)
locate the next elem at a given depth with an optional matching name
Definition: nad.c:204
component_t src
Definition: router.c:31
void jid_static(jid_t jid, jid_static_buf *buf)
Make jid to use static buffer (jid data won't be allocated dynamically, but given buffer will be alwa...
Definition: jid.c:102
Definition: sx.h:65
void * xhash_getx(xht h, const char *key, int len)
Definition: xhash.c:170
void log_write(log_t log, int level, const char *msgfmt,...)
Definition: log.c:104
static void _router_process_handshake(component_t comp, nad_t nad)
Definition: router.c:100
const char * default_route
default route, only one
Definition: router.h:140
rate_t rate_new(int total, int seconds, int wait)
Definition: rate.c:25
error info for event_ERROR
Definition: sx.h:99
void routes_free(routes_t routes)
Definition: router.c:153
struct routes_st * routes_t
Definition: router.h:53
sx_t sx_new(sx_env_t env, int tag, sx_callback_t cb, void *arg)
Definition: sx.c:23
int legacy
true if this is an old component:accept stream
Definition: router.h:190
void shahash_r(const char *str, char hashbuf[41])
convenience (originally by Thomas Muldowney)
Definition: str.c:358
void * data
Definition: util.h:315
int sx_can_write(sx_t s)
Definition: io.c:318
nad_t nad
Definition: router.c:32
int icdata
Definition: nad.h:72
int nad_add_namespace(nad_t nad, const char *uri, const char *prefix)
bring a new namespace into scope
Definition: nad.c:734
void sx_server_init(sx_t s, unsigned int flags)
Definition: server.c:228
access_t access
access controls
Definition: router.h:102
#define NAD_ENAME(N, E)
Definition: nad.h:183
#define stream_err_INVALID_NAMESPACE
Definition: sx.h:134
jqueue_t tq
throttle queue
Definition: router.h:193
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 message_logging_enabled
simple message logging
Definition: router.h:161
_jqueue_node_t front
Definition: util.h:327
int nad_append_elem(nad_t nad, int ns, const char *name, int depth)
create a new elem on the list
Definition: nad.c:667
const char * ns
Definition: sx.h:277
void nad_free(nad_t nad)
free that nad
Definition: nad.c:178
int rate_log
Definition: router.h:184
void nad_wrap_elem(nad_t nad, int elem, int ns, const char *name)
wrap an element with another element
Definition: nad.c:475
nad_t nad_copy(nad_t nad)
copy a nad
Definition: nad.c:145
int xhash_iter_next(xht h)
Definition: xhash.c:320
struct component_st * component_t
Definition: router.h:52
Definition: sx.h:60
char ip[INET6_ADDRSTRLEN]
remote ip and port
Definition: router.h:173
void rate_free(rate_t rt)
Definition: rate.c:36
#define mio_read(m, fd)
process read events for this fd
Definition: mio.h:161
void jqueue_free(jqueue_t q)
Definition: jqueue.c:38
time_t last_activity
timestamps for idle timeouts
Definition: router.h:196
rate_t rate
rate limits
Definition: router.h:183
static void _router_process_bind(component_t comp, nad_t nad)
Definition: router.c:202
void nad_set_attr(nad_t nad, int elem, int ns, const char *name, const char *val, int vallen)
create, update, or zap any matching attr on this elem
Definition: nad.c:375
a single component
Definition: router.h:166
static void _route_remove(xht hroutes, const char *name, component_t comp)
Definition: router.c:179
#define MIO_WOULDBLOCK
Definition: mio.h:171
int sx_can_read(sx_t s)
we can read
Definition: io.c:181
static void _router_route_log_sink(const char *key, int keylen, void *val, void *arg)
Definition: router.c:402
struct rate_st * rate_t
char * _full
Definition: jid.h:61
static void _router_process_route(component_t comp, nad_t nad)
Definition: router.c:413
xht routes
valid routes to this component, key is route name
Definition: router.h:187
holds the state for a single stream
Definition: sx.h:251
char * data
Definition: sx.h:114
int conn_rate_wait
Definition: router.h:107
void shahash_raw(const char *str, unsigned char hashval[20])
Definition: str.c:364
int j_inet_getport(struct sockaddr_storage *sa)
get the port number out of a struct sockaddr_storage
Definition: inaddr.c:148
char jid_static_buf[3 *1025]
JID static buffer.
Definition: jid.h:77
void ** val
Definition: c2s.h:384
struct nad_ns_st * nss
Definition: nad.h:97
static void _router_process_throttle(component_t comp, nad_t nad)
Definition: router.c:646
#define NAD_ENAME_L(N, E)
Definition: nad.h:184
void jqueue_push(jqueue_t q, void *data, int priority)
Definition: jqueue.c:44
#define NAD_NURI_L(N, NS)
Definition: nad.h:192
const char * target
Definition: router.h:216
void jid_free(jid_t jid)
free a jid
Definition: jid.c:286
int aci_check(xht aci, const char *type, const char *name)
see if a username is in an acl
Definition: aci.c:93
component_t * comp_val
Definition: router.h:244
static void _router_process_unbind(component_t comp, nad_t nad)
Definition: router.c:331
int byte_rate_seconds
Definition: router.h:113
void xhash_put(xht h, const char *key, void *val)
Definition: xhash.c:163
int ncomp
Definition: router.h:211
#define SX_SSL_STARTTLS_OFFER
Definition: plugins.h:26
char ipport[INET6_ADDRSTRLEN+6]
ip:port pair
Definition: router.h:177
xht conn_rates
Definition: router.h:109
log_t log
logging
Definition: router.h:84
static int _router_accept_check(router_t r, mio_fd_t fd, const char *ip)
Definition: router.c:977
#define stanza_err_BAD_REQUEST
Definition: util.h:367
char * domain
Definition: jid.h:45
#define stanza_err_REDIRECT
Definition: util.h:379
acl_t filter
user table
Definition: router.h:80
const char * generic
Definition: sx.h:101
Definition: jid.h:42
multi component route - route by 'to'
Definition: router.h:202
struct broadcast_st * broadcast_t
info for broadcasts
jqueue_t dead
list of sx_t waiting to be cleaned up
Definition: router.h:152
alias_t aliases
configured aliases
Definition: router.h:146
_jqueue_node_t prev
Definition: util.h:320
int xhash_iter_get(xht h, const char **key, int *keylen, void **val)
Definition: xhash.c:374
#define NAD_AVAL_L(N, A)
Definition: nad.h:190
void sx_close(sx_t s)
Definition: io.c:480
int byte_rate_total
default byte rates (karma)
Definition: router.h:112
mio_fd_t fd
file descriptor
Definition: router.h:170
void xhash_zap(xht h, const char *key)
Definition: xhash.c:235
const char * auth_id
Definition: sx.h:328
#define log_debug(...)
Definition: log.h:65
int conn_rate_seconds
Definition: router.h:106
void xhash_zapx(xht h, const char *key, int len)
Definition: xhash.c:219
int rate_check(rate_t rt)
Definition: rate.c:78
nad_t stanza_error(nad_t nad, int elem, int err)
error the packet
Definition: stanza.c:52
#define uri_CLIENT
Definition: uri.h:35
#define NAD_AVAL(N, A)
Definition: nad.h:189
struct _sx_buf_st * sx_buf_t
utility: buffer
Definition: sx.h:112
component_t * comp
Definition: router.h:210
int ns
Definition: nad.h:75
void sx_error(sx_t s, int err, const char *text)
Definition: error.c:88
#define SX_SASL_OFFER
Definition: plugins.h:29
int router_mio_callback(mio_t m, mio_action_t a, mio_fd_t fd, void *data, void *arg)
Definition: router.c:1028
static void _router_broadcast(const char *key, int keylen, void *val, void *arg)
broadcast a packet
Definition: router.c:36
int scope
Definition: nad.h:107
int message_log(nad_t nad, router_t r, const char *msg_from, const char *msg_to)
Definition: router.c:1132
#define mio_app(m, fd, app, arg)
re-set the app handler
Definition: mio.h:152
void * jqueue_pull(jqueue_t q)
Definition: jqueue.c:96
router_t r
Definition: router.h:167
int xhash_count(xht h)
return the total number of entries in this xht
Definition: xhash.c:297
const char * specific
Definition: sx.h:102
int xhash_iter_first(xht h)
iteration
Definition: xhash.c:311
void xhash_walk(xht h, xhash_walker w, void *arg)
Definition: xhash.c:268
int fd
Definition: mio.h:102
jqueue_t jqueue_new(void)
Definition: jqueue.c:25
int filter_packet(router_t r, nad_t nad)
Definition: filter.c:182
xht log_sinks
log sinks, key is route name, var is component_t
Definition: router.h:143
unsigned int len
Definition: sx.h:115
int nad_find_namespace(nad_t nad, int elem, const char *uri, const char *prefix)
get a matching ns on this elem, both uri and optional prefix
Definition: nad.c:262
pool_t xhash_pool(xht h)
get our pool
Definition: xhash.c:305
int access_check(access_t access, const char *ip)
Definition: access.c:203
int rate_left(rate_t rt)
Definition: rate.c:69
const char * name
Definition: router.h:208
const char * name
Definition: router.h:215
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
#define NAD_CDATA(N, E)
Definition: nad.h:185
void sx_kill(sx_t s)
Definition: io.c:495
Definition: util.h:258
static void _router_advertise_reverse(const char *key, int keylen, void *val, void *arg)
tell a component about all the others
Definition: router.c:74
void * xhash_get(xht h, const char *key)
Definition: xhash.c:184
#define uri_COMPONENT
Definition: uri.h:51
#define stream_err_NOT_AUTHORIZED
Definition: sx.h:136
#define mio_write(m, fd)
mio should try the write action on this fd now
Definition: mio.h:158
static int _route_add(xht hroutes, const char *name, component_t comp, route_type_t rtype)
Definition: router.c:159
#define ZONE
Definition: mio_impl.h:76
session packet handling
Definition: c2s.h:382
int byte_rate_wait
Definition: router.h:114
#define NAD_NURI(N, NS)
Definition: nad.h:191
sx_event_t
things that can happen
Definition: sx.h:56
route_type_t rtype
Definition: router.h:209
xht xhash_new(int prime)
Definition: xhash.c:96
int next
Definition: nad.h:90
int nad_find_attr(nad_t nad, int elem, int ns, const char *name, const char *val)
get a matching attr on this elem, both name and optional val
Definition: nad.c:235
info for broadcasts
Definition: router.c:29
mio_t mio
managed io
Definition: router.h:122
sx_t s
our stream
Definition: router.h:180
int conn_rate_total
connection rates
Definition: router.h:105
int itail
Definition: nad.h:73
#define stream_err_HOST_UNKNOWN
Definition: sx.h:129
int lcdata
Definition: nad.h:72
Definition: sx.h:62
void sx_auth(sx_t s, const char *auth_method, const char *auth_id)
force advance into auth state
Definition: sx.c:141
struct nad_st * nad_t
const char * local_secret
Definition: router.h:94
#define stanza_err_SERVICE_UNAVAILABLE
Definition: util.h:384
xht components
attached components, key is 'ip:port', var is component_t
Definition: router.h:134
const char * id
Definition: sx.h:290
single component route
Definition: router.h:201
void nad_print(nad_t nad, int elem, const char **xml, int *len)
create a string representation of the given element (and children), point references to it ...
Definition: nad.c:1164
char * node
Definition: jid.h:44
static void _router_route_unbind_walker(const char *key, int keylen, void *val, void *arg)
Definition: router.c:1003
static int _router_sx_callback(sx_t s, sx_event_t e, void *data, void *arg)
Definition: router.c:671
static void _router_comp_write(component_t comp, nad_t nad)
Definition: router.c:374
#define NAD_ENS(N, E)
Definition: nad.h:196
int port
Definition: router.h:174
int my_ns
Definition: nad.h:76
const char * message_logging_file
Definition: router.h:162