Esempio n. 1
0
/* drop incoming presence if the user isn't around,
 * so we don't have to load them during broadcasts */
mod_ret_t _presence_in_router(mod_instance_t mi, pkt_t pkt) {
    user_t user;
    sess_t sess;

    /* only check presence to users, pass presence to sm and probes */
    if(!(pkt->type & pkt_PRESENCE) || pkt->to->node[0] == '\0' || pkt->type == pkt_PRESENCE_PROBE)
        return mod_PASS;

    /* get the user _without_ doing a load */
    user = xhash_get(mi->mod->mm->sm->users, jid_user(pkt->to));

    /* no user, or no sessions, bail */
    if(user == NULL || user->sessions == NULL) {
        pkt_free(pkt);
        return mod_HANDLED;
    }

    /* only pass if there's at least one available session */
    for(sess = user->sessions; sess != NULL; sess = sess->next)
        if(sess->available)
            return mod_PASS;

    /* no available sessions, drop */
    pkt_free(pkt);

    return mod_HANDLED;
}
Esempio n. 2
0
File: nad.c Progetto: zipo/zipo
static void _nad_ptr_check(const char *func, nad_t nad) {
    char loc[24];
    snprintf(loc, sizeof(loc), "%x", (int) nad);

    if(xhash_get(_nad_alloc_tracked, loc) == NULL) {
        fprintf(stderr, ">>> NAD OP %s: 0x%x not allocated!\n", func, (int) nad);
        abort();
    }

    if(xhash_get(_nad_free_tracked, loc) != NULL) {
        fprintf(stderr, ">>> NAD OP %s: 0x%x previously freed!\n", func, (int) nad);
        abort();
    }

    fprintf(stderr, ">>> NAD OP %s: 0x%x\n", func, (int) nad);
}
Esempio n. 3
0
File: ns.c Progetto: Doap/transports
void mt_ns_rng(mpacket mp, session s)
{
    sbchat sc;
    char *user = mt_packet_data(mp,5);
    char *sid, *chal, *host, *port;

    sc = xhash_get(s->chats,user);  /* is there already is a SB session? */
    if (sc != NULL)
    {
        if (sc->state == sb_START)
        {
            log_debug(ZONE,"SB Session with '%s' already started",user);
            return;
        }

        log_debug(ZONE,"Replacing SB session");
        mt_chat_end(sc);
    }

    sid = mt_packet_data(mp,1);
    host = mt_packet_data(mp,2);
    chal = mt_packet_data(mp,4);
    port = strchr(host,':');

    if (port != NULL)
    {
        *port = '\0';
        port++;
    }

    mt_chat_join(s,user,host,j_atoi(port,1863),chal,sid);
}
Esempio n. 4
0
/*
 * get group's descriptive name by it's text id
 * returned value needs to be freed by caller
 */
static const char *_roster_publish_get_group_name(sm_t sm, roster_publish_t rp, const char *groupid)
{
    os_t os;
    os_object_t o;
    char *str;
    char *group;

#ifndef NO_SM_CACHE
    _roster_publish_group_cache_t group_cached;
#endif

    if(!groupid) return groupid;

#ifndef NO_SM_CACHE
    /* check for remembered group value in cache */
    if( rp->group_cache_ttl ) {
        if( rp->group_cache ) {
            group_cached = xhash_get(rp->group_cache, groupid);
            if( group_cached != NULL ) {
                if( (time(NULL) - group_cached->time) >= rp->group_cache_ttl ) {
                    log_debug(ZONE,"group cache: expiring cached value for %s",groupid);
                    xhash_zap(rp->group_cache, groupid);
                    free(group_cached);
                } else {
                    log_debug(ZONE,"group cache: returning cached value for %s",groupid);
                    return strdup(group_cached->groupname);
                }
            }
        } else {
            log_debug(ZONE,"group cache: creating cache");
            rp->group_cache = xhash_new(401);
        }
    }
#endif

    if(storage_get(sm->st, "published-roster-groups", groupid, NULL, &os) == st_SUCCESS && os_iter_first(os)) {
        o = os_iter_object(os);
        if( os_object_get_str(os, o, "groupname", &str) && str ) {
            group=strdup(str);
        } else {
            group=NULL;
        }
        os_free(os);
#ifndef NO_SM_CACHE
        if( rp->group_cache_ttl && group ) {
            log_debug(ZONE,"group cache: updating cache value for %s",groupid);
            group_cached = calloc(1, sizeof(struct _roster_publish_group_cache_st));
            group_cached->time = time(NULL);
            group_cached->groupid = strdup(groupid);
            group_cached->groupname = strdup(group);
            xhash_put(rp->group_cache, group_cached->groupid, group_cached);
        }
#endif
        return group;
    } else {
        return NULL;
    }
}
Esempio n. 5
0
/** get an attr for this value */
char *config_get_attr(config_t c, const char *key, int num, const char *attr)
{
    config_elem_t elem = (config_elem_t)xhash_get(c->hash, key);

    if(num >= elem->nvalues || elem->attrs == NULL || elem->attrs[num] == NULL)
        return NULL;

    return j_attr((const char **) elem->attrs[num], attr);
}
Esempio n. 6
0
/** how many values for this key? */
int config_count(config_t c, const char *key)
{
    config_elem_t elem = (config_elem_t)xhash_get(c->hash, key);

    if(elem == NULL)
        return 0;

    return elem->nvalues;
}
Esempio n. 7
0
File: aci.c Progetto: zipo/zipo
/** see if a username is in an acl */
int aci_check(xht aci, const char *type, const char *name) {
    aci_user_t list, scan;

    log_debug(ZONE, "checking for '%s' in acl 'all'", name);
    list = (aci_user_t) xhash_get(aci, "all");
    for(scan = list; scan != NULL; scan = scan->next)
        if(strcmp(scan->name, name) == 0)
            return 1;

    if(type != NULL) {
        log_debug(ZONE, "checking for '%s' in acl '%s'", name, type);
        list = (aci_user_t) xhash_get(aci, type);
        for(scan = list; scan != NULL; scan = scan->next)
            if(strcmp(scan->name, name) == 0)
                return 1;
    }

    return 0;
}
Esempio n. 8
0
static void _router_process_unbind(component_t comp, nad_t nad) {
    int attr;
    jid_t name;

    attr = nad_find_attr(nad, 0, -1, "name", NULL);
    if(attr < 0 || (name = jid_new(NAD_AVAL(nad, attr), NAD_AVAL_L(nad, attr))) == NULL) {
        log_debug(ZONE, "no or invalid 'name' on unbind packet, bouncing");
        nad_set_attr(nad, 0, -1, "error", "400", 3);
        sx_nad_write(comp->s, nad);
        return;
    }

    if(xhash_get(comp->routes, name->domain) == NULL) {
        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);
        nad_set_attr(nad, 0, -1, "name", NULL, 0);
        nad_set_attr(nad, 0, -1, "error", "404", 3);
        sx_nad_write(comp->s, nad);
        jid_free(name);
        return;
    }

    xhash_zap(comp->r->log_sinks, name->domain);
    _route_remove(comp->r->routes, name->domain, comp);
    xhash_zap(comp->routes, name->domain);

    if(comp->r->default_route != NULL && strcmp(comp->r->default_route, name->domain) == 0) {
        log_write(comp->r->log, LOG_NOTICE, "[%s] default route offline", name->domain);
        free((void*)(comp->r->default_route));
        comp->r->default_route = NULL;
    }

    log_write(comp->r->log, LOG_NOTICE, "[%s] offline", name->domain);

    nad_set_attr(nad, 0, -1, "name", NULL, 0);
    sx_nad_write(comp->s, nad);

    /* deadvertise name */
    if(xhash_get(comp->r->routes, name->domain) == NULL)
        _router_advertise(comp->r, name->domain, comp, 1);

    jid_free(name);
}
Esempio n. 9
0
/** see if a jid is in an acl */
int aci_check(xht acls, char *type, jid_t jid)
{
    jid_t list, dup;

    dup = jid_dup(jid);
    if (dup->resource[0]) {
        /* resourceless version */
        dup->resource[0] = '\0';
        dup->dirty = 1;
    }

    log_debug(ZONE, "checking for '%s' in acl 'all'", jid_full(jid));
    list = (jid_t) xhash_get(acls, "all");
    if(jid_search(list, jid)) {
        jid_free(dup);
        return 1;
    }

    log_debug(ZONE, "checking for '%s' in acl 'all'", jid_user(dup));
    if(jid_search(list, dup)) {
        jid_free(dup);
        return 1;
    }

    if(type != NULL) {
        log_debug(ZONE, "checking for '%s' in acl '%s'", jid_full(jid), type);
        list = (jid_t) xhash_get(acls, type);
        if(jid_search(list, jid)) {
            jid_free(dup);
            return 1;
        }

        log_debug(ZONE, "checking for '%s' in acl '%s'", jid_user(dup), type);
        if(jid_search(list, dup)) {
            jid_free(dup);
            return 1;
        }
    }

    jid_free(dup);
    return 0;
}
Esempio n. 10
0
File: iq.c Progetto: Doap/transports
int at_run_iqcb(ati ti, const char *ns, jpacket jp)
{
    iqcb cb;

    log_debug(ZONE, "Running callback for %s", ns);
    cb = xhash_get(ti->iq__callbacks, ns);
    if(cb == NULL)
        return -1;
    
    return cb(ti, jp);
}
Esempio n. 11
0
END_TEST

START_TEST(test_find)
{
	xhash_t* ht = g_ht;
	char buffer[255];
	int i;

	/* test bad match */
	fail_unless(xhash_get(ht, "bad") == NULL  , "invalid case not null");
	fail_unless(xhash_get(ht, "-1") == NULL   , "invalid case not null");
	fail_unless(xhash_get(ht, "10000") == NULL, "invalid case not null");

	/* test all good indexes */
	for (i = 0; i < g_hashableslen; ++i) {
		snprintf(buffer, sizeof(buffer), "%d", i);
		fail_unless(xhash_get(ht, buffer) == (g_hashables + i),
				"bad hashable item returned");
	}
}
Esempio n. 12
0
/** get config value n for this key */
const char *config_get_one(config_t c, const char* key, int num)
{
    config_elem_t elem = (config_elem_t) xhash_get(c->hash, key);

    if(elem == NULL)
        return NULL;

    if(num >= elem->nvalues)
        return NULL;

    return elem->values[num];
}
Esempio n. 13
0
/** unregister feature */
void feature_unregister(sm_t sm, const char *feature)
{
    int refcount = (int) (long) xhash_get(sm->features, feature);

    log_debug(ZONE, "unregistering feature %s", feature);

    if (refcount == 1) {
        xhash_zap(sm->features, feature);
    } else if (refcount > 1) {
        xhash_put(sm->features, feature, (void *) ((long) refcount - 1));
    }
}
Esempio n. 14
0
// Rate limit check:  Prevent denial-of-service due to excessive database queries
// Make sure owner is responsible for the query!
int sm_storage_rate_limit(sm_t sm, const char *owner) {
    rate_t rt;
    user_t user;
    sess_t sess;
    item_t item;

    if (sm->query_rate_total == 0 || owner == NULL)
    return FALSE;

    user = xhash_get(sm->users, owner);
    if (user != NULL) {
        rt = (rate_t) xhash_get(sm->query_rates, owner);
        if (rt == NULL) {
            rt = rate_new(sm->query_rate_total, sm->query_rate_seconds, sm->query_rate_wait);
            xhash_put(sm->query_rates, pstrdup(xhash_pool(sm->query_rates), owner), (void *) rt);
            pool_cleanup(xhash_pool(sm->query_rates), (void (*)(void *)) rate_free, rt);
        }

        if(rate_check(rt) == 0) {
            log_write(sm->log, LOG_WARNING, "[%s] is being disconnected, too many database queries within %d seconds", owner, sm->query_rate_seconds);
            user = xhash_get(sm->users, owner);
            for (sess = user->sessions; sess != NULL; sess = sess->next) {
                sm_c2s_action(sess, "ended", NULL);
            }
            if(xhash_iter_first(user->roster))
                do {
                    xhash_iter_get(user->roster, NULL, NULL, (void *) &item);
                    if(item->to) {
                        pkt_router(pkt_create(user->sm, "presence", "unavailable", jid_full(item->jid), jid_full(user->jid)));
                    }
                } while(xhash_iter_next(user->roster));
            return TRUE;
            } else {
                rate_add(rt, 1);
            }
        } else {
            log_debug(ZONE, "Error: could not get user data for %s", owner);
    }
    return FALSE;
}
Esempio n. 15
0
int at_iq_last(ati ti, jpacket jp)
{
    xmlnode last;
    xmlnode q;
    char str[10];

    /* XXX I can do last if I track logouts in the XDB... not too hard */
    if(jpacket_subtype(jp) != JPACKET__GET)
    {
        at_bounce(ti, jp, TERROR_BAD);
        return 1;
    }

    if(jp->to->user != NULL)
    {
        at_session s;
        at_buddy buddy;
        char *res;

        s = at_session_find_by_jid(ti, jp->from);
        if(s == NULL)
        {
            at_bounce(ti, jp, TERROR_REGISTER);
            return 1;
        }
        buddy = xhash_get(s->buddies, jp->to->user);
        if(buddy == NULL)
        {
            at_bounce(ti, jp, TERROR_BAD);
            return 1;
        }
         
        jutil_iqresult(jp->x);
        last = xmlnode_insert_tag(jp->x, "query");
        xmlnode_put_attrib(last,"xmlns",NS_LAST);
        sprintf(str, "%d", buddy->idle_time);
        xmlnode_put_attrib(last, "seconds", str);
        at_deliver(ti,jp->x);

        return 1;
    }

    jutil_iqresult(jp->x);
    last = xmlnode_insert_tag(jp->x, "query");
    xmlnode_put_attrib(last,"xmlns",NS_LAST);
    sprintf(str, "%d", time(NULL) - ti->start_time);
    xmlnode_put_attrib(last,"seconds", str);
    at_deliver(ti,jp->x);

    return 1;
}
Esempio n. 16
0
File: iq.c Progetto: Doap/transports
int at_register_iqns(ati ti, const char *ns, iqcb cb)
{
    iqcb cur;

    log_debug(ZONE, "Registering callback for %s", ns);
    cur = xhash_get(ti->iq__callbacks, ns);
    if(cur)
    {
        xhash_zap(ti->iq__callbacks, ns);
    }
    xhash_put(ti->iq__callbacks, ns, cb);

    return;
}
Esempio n. 17
0
/*
 * _find_alias_node_record - find a record for node with the alias of
 * the specified name supplied
 * IN: name - name to be aliased of the desired node
 * IN: log_missing - if set, then print an error message if the node is not found
 * OUT: return pointer to node record or NULL if not found
 */
static struct node_record *_find_alias_node_record(char *name, bool log_missing)
{
	int i;
	char *alias = NULL;

	if ((name == NULL) || (name[0] == '\0')) {
		info("%s: passed NULL name", __func__);
		return NULL;
	}
	/* Get the alias we have just to make sure the user isn't
	 * trying to use the real hostname to run on something that has
	 * been aliased.
	 */
	alias = slurm_conf_get_nodename(name);

	if (!alias)
		return NULL;

	/* try to find via hash table, if it exists */
	if (node_hash_table) {
		struct node_record *node_ptr;

		node_ptr = (struct node_record*) xhash_get(node_hash_table,
							   alias);
		if (node_ptr) {
			xassert(node_ptr->magic == NODE_MAGIC);
			xfree(alias);
			return node_ptr;
		}

		if (log_missing)
			error("%s: lookup failure for %s", __func__, name);
	}

	/* revert to sequential search */
	else {
		for (i = 0; i < node_record_count; i++) {
			if (!xstrcmp (alias, node_record_table_ptr[i].name)) {
				xfree(alias);
				return (&node_record_table_ptr[i]);
			}
		}
	}

	xfree(alias);
	return (struct node_record *) NULL;
}
Esempio n. 18
0
result dnsrv_deliver(instance i, dpacket p, void* args)
{
     dns_io di = (dns_io)args;
     xmlnode c;
     int timeout = di->cache_timeout;
     char *ip;
     jid to;

     /* if we get a route packet, it has to be to *us* and have the child as the real packet */
     if(p->type == p_ROUTE)
     {
        if(j_strcmp(p->host,i->id) != 0 || (to = jid_new(p->p,xmlnode_get_attrib(xmlnode_get_firstchild(p->x),"to"))) == NULL)
            return r_ERR;
        p->x=xmlnode_get_firstchild(p->x);
        p->id = to;
        p->host = to->server;
     }

     /* Ensure this packet doesn't already have an IP */
     if(xmlnode_get_attrib(p->x, "ip") || xmlnode_get_attrib(p->x, "iperror"))
     {
        log_notice(p->host, "dropping looping dns lookup request: %s", xmlnode2str(p->x));
        xmlnode_free(p->x);
        return r_DONE;
     }

     /* try the cache first */
     if((c = xhash_get(di->cache_table, p->host)) != NULL)
     {
         /* if there's no IP, cached failed lookup, time those out 10 times faster! (weird, I know, *shrug*) */
         if((ip = xmlnode_get_attrib(c,"ip")) == NULL)
            timeout = timeout / 10;
         if((time(NULL) - (int)xmlnode_get_vattrib(c,"t")) > timeout)
         { /* timed out of the cache, lookup again */
             xmlnode_free(c);
             xhash_zap(di->cache_table,p->host);
         }else{
             /* yay, send back right from the cache */
             dnsrv_resend(p->x, ip, xmlnode_get_attrib(c,"to"));
             return r_DONE;
         }
     }

    dnsrv_lookup(di, p);
    return r_DONE;
}
Esempio n. 19
0
END_TEST

/* returns the number of item deleted from the hash table */
static int test_delete_helper()
{
	xhash_t* ht = g_ht;
	int ret = 0;
	int i;
	char buffer[255];
	for (i = 0; i < g_hashableslen; ++i) {
		snprintf(buffer, sizeof(buffer), "%d", i);
		if (xhash_get(ht, buffer) != (g_hashables + i)) {
			++ret;
		}
	}
	return ret;
}
Esempio n. 20
0
static int _route_add(xht hroutes, const char *name, component_t comp, route_type_t rtype) {
    routes_t routes;

    routes = xhash_get(hroutes, name);
    if(routes == NULL) {
        routes = (routes_t) calloc(1, sizeof(struct routes_st));
        routes->name = strdup(name);
        routes->rtype = rtype;
    }
    routes->comp = (component_t *) realloc(routes->comp, sizeof(component_t *) * (routes->ncomp + 1));
    routes->comp[routes->ncomp] = comp;
    routes->ncomp++;
    xhash_put(hroutes, routes->name, (void *) routes);

    if(routes->rtype != rtype)
        log_write(comp->r->log, LOG_ERR, "Mixed route types for '%s' bind request", name);

    return routes->ncomp;
}
Esempio n. 21
0
/*
 * _find_node_record - find a record for node with specified name
 * IN: name - name of the desired node
 * IN: test_alias - if set, also test NodeHostName value
 * IN: log_missing - if set, then print an error message if the node is not found
 * RET: pointer to node record or NULL if not found
 */
static struct node_record *_find_node_record (char *name, bool test_alias,
					      bool log_missing)
{
	int i;
	struct node_record *node_ptr;

	if ((name == NULL) || (name[0] == '\0')) {
		info("find_node_record passed NULL name");
		return NULL;
	}

	/* try to find via hash table, if it exists */
	if (node_hash_table) {
		node_ptr = (struct node_record*) xhash_get(node_hash_table,
							   name);
		if (node_ptr) {
			xassert(node_ptr->magic == NODE_MAGIC);
			return node_ptr;
		}

		if ((node_record_count == 1) &&
		    (xstrcmp(node_record_table_ptr[0].name, "localhost") == 0))
			return (&node_record_table_ptr[0]);

		if (log_missing)
			error ("find_node_record: lookup failure for %s", name);
	}
	/* revert to sequential search */
	else {
		for (i = 0; i < node_record_count; i++) {
			if (!xstrcmp (name, node_record_table_ptr[i].name)) {
				return (&node_record_table_ptr[i]);
			}
		}
	}

	if (test_alias) {
		/* look for the alias node record if the user put this in
	 	 * instead of what slurm sees the node name as */
		return _find_alias_node_record(name, log_missing);
	}
	return NULL;
}
Esempio n. 22
0
/* Hostname lookup requested */
void dnsrv_lookup(dns_io d, dpacket p)
{
    dns_packet_list l, lnew;
    xmlnode req;
    char *reqs;

    /* make sure we have a child! */
    if(d->out <= 0)
    {
        deliver_fail(p, "DNS Resolver Error");
        return;
    }

    /* Attempt to lookup this hostname in the packet table */
    l = (dns_packet_list)xhash_get(d->packet_table, p->host);

    /* IF: hashtable has the hostname, a lookup is already pending,
       so push the packet on the top of the list (most recent at the top) */
    if (l != NULL)
    {
         log_debug(ZONE, "dnsrv: Adding lookup request for %s to pending queue.", p->host);
         lnew = pmalloco(p->p, sizeof(_dns_packet_list));
         lnew->packet = p;
         lnew->stamp = time(NULL);
         lnew->next = l;
         xhash_put(d->packet_table, p->host, lnew);
         return;
    }

    /* insert the packet into the packet_table using the hostname
       as the key and send a request to the coprocess */
    log_debug(ZONE, "dnsrv: Creating lookup request queue for %s", p->host);
    l = pmalloco(p->p, sizeof(_dns_packet_list));
    l->packet = p;
    l->stamp  = time(NULL);
    xhash_put(d->packet_table, p->host, l);
    req = xmlnode_new_tag_pool(p->p,"host");
    xmlnode_insert_cdata(req,p->host,-1);

    reqs = xmlnode2str(req);
    log_debug(ZONE, "dnsrv: Transmitting lookup request: %s", reqs);
    pth_write(d->out, reqs, strlen(reqs));
}
Esempio n. 23
0
static void _route_remove(xht hroutes, const char *name, component_t comp) {
    routes_t routes;
    int i;

    routes = xhash_get(hroutes, name);
    if(routes == NULL) return;

    if(routes->ncomp > 1) {
        for(i = 0; i < routes->ncomp; i++) {
            if(routes->comp[i] == comp) {
                if(i != routes->ncomp - 1) {
                    routes->comp[i] = routes->comp[routes->ncomp - 1];
                }
                routes->ncomp--;
            }
        }
    }
    else {
        jqueue_push(comp->r->deadroutes, (void *) routes, 0);
        xhash_zap(hroutes, name);
    }
}
Esempio n. 24
0
END_TEST

START_TEST(test_add)
{
	xhash_t* ht = NULL;
	hashable_t a[4] = {{"0", 0}, {"1", 1}, {"2", 2}, {"3", 3}};
	int i, len = sizeof(a)/sizeof(a[0]);
	char buffer[255];
	ht = xhash_init(hashable_identify, NULL, NULL, 0);
	fail_unless(xhash_add(NULL, a) == NULL, "invalid cases not null");
	fail_unless(xhash_add(ht, NULL) == NULL, "invalid cases not null");
	fail_unless(xhash_add(ht, a)   != NULL, "xhash_add failed");
	fail_unless(xhash_add(ht, a+1) != NULL, "xhash_add failed");
	fail_unless(xhash_add(ht, a+2) != NULL, "xhash_add failed");
	fail_unless(xhash_add(ht, a+3) != NULL, "xhash_add failed");
	for (i = 0; i < len; ++i) {
		snprintf(buffer, sizeof(buffer), "%d", i);
		fail_unless(xhash_get(ht, buffer) == (a + i),
				"bad hashable item returned");
	}
	xhash_free(ht);
}
Esempio n. 25
0
st_ret_t storage_count(storage_t st, const char *type, const char *owner, const char *filter, int *count) {
    st_driver_t drv;
    st_ret_t ret;

    log_debug(ZONE, "storage_count: type=%s owner=%s filter=%s", type, owner, filter);

    /* find the handler for this type */
    drv = xhash_get(st->types, type);
    if(drv == NULL) {
        /* never seen it before, so it goes to the default driver */
        drv = st->default_drv;
        if(drv == NULL) {
            log_debug(ZONE, "no driver associated with type, and no default driver");
            return st_NOTIMPL;
        }

        /* register the type */
        ret = storage_add_type(st, drv->name, type);
        if(ret != st_SUCCESS)
            return ret;
    }

    return ((drv->count != NULL) ? (drv->count)(drv, type, owner, filter, count) : st_NOTIMPL);
}
Esempio n. 26
0
int entity_add_data(entity_t* entity, const char* key, void* value,
		    void (*_free)(void*))
{
	entity_data_t* result;
	entity_data_t* new_data_item;
	if (!key || !*key || !value)
		return 0;
	result = (entity_data_t*)xhash_get(entity->data, key);
	if (result != NULL) {
		if (_free)
			_free(result->value);
		result->value = value;
		return 1;
	}
	new_data_item = (entity_data_t*)xmalloc(sizeof(entity_data_t));
	new_data_item->key = key;
	new_data_item->value = value;
	result = xhash_add(entity->data, new_data_item);
	if (result == NULL) {
		xfree(new_data_item);
		return 0;
	}
	return 1;
}
Esempio n. 27
0
static mod_ret_t _iq_private_in_sess(mod_instance_t mi, sess_t sess, pkt_t pkt) {
    module_t mod = mi->mod;
    int ns, elem, target, targetns;
    st_ret_t ret;
    char filter[4096];
    os_t os;
    os_object_t o;
    nad_t nad;
    pkt_t result;
    sess_t sscan;

    /* only handle private sets and gets */
    if((pkt->type != pkt_IQ && pkt->type != pkt_IQ_SET) || pkt->ns != ns_PRIVATE)
        return mod_PASS;

    /* we're only interested in no to, to our host, or to us */
    if(pkt->to != NULL && jid_compare_user(sess->jid, pkt->to) != 0 && strcmp(sess->jid->domain, jid_user(pkt->to)) != 0)
        return mod_PASS;

    ns = nad_find_scoped_namespace(pkt->nad, uri_PRIVATE, NULL);
    elem = nad_find_elem(pkt->nad, 1, ns, "query", 1);

    /* find the first child */
    target = elem + 1;
    while(target < pkt->nad->ecur)
    {
        if(pkt->nad->elems[target].depth > pkt->nad->elems[elem].depth)
            break;

        target++;
    }

    /* not found, so we're done */
    if(target == pkt->nad->ecur)
        return -stanza_err_BAD_REQUEST;

    /* find the target namespace */
    targetns = NAD_ENS(pkt->nad, target);

    /* gotta have a namespace */
    if(targetns < 0)
    {
        log_debug(ZONE, "no namespace specified");
        return -stanza_err_BAD_REQUEST;
    }

    log_debug(ZONE, "processing private request for %.*s", NAD_NURI_L(pkt->nad, targetns), NAD_NURI(pkt->nad, targetns));

    /* get */
    if(pkt->type == pkt_IQ) {
#ifdef ENABLE_EXPERIMENTAL
        /* remember that this resource requested the namespace */
        if(sess->module_data[mod->index] == NULL) {
            /* create new hash if necesary */
            sess->module_data[mod->index] = xhash_new(101);
            pool_cleanup(sess->p, (void (*))(void *) xhash_free, sess->module_data[mod->index]);
        }
        xhash_put(sess->module_data[mod->index], pstrdupx(sess->p, NAD_NURI(pkt->nad, targetns), NAD_NURI_L(pkt->nad, targetns)), (void *) 1);
#endif
        snprintf(filter, 4096, "(ns=%i:%.*s)", NAD_NURI_L(pkt->nad, targetns), NAD_NURI_L(pkt->nad, targetns), NAD_NURI(pkt->nad, targetns));
        ret = storage_get(sess->user->sm->st, "private", jid_user(sess->jid), filter, &os);
        switch(ret) {
            case st_SUCCESS:
                if(os_iter_first(os)) {
                    o = os_iter_object(os);
                    if(os_object_get_nad(os, o, "xml", &nad)) {
                        result = pkt_new(sess->user->sm, nad_copy(nad));
                        if(result != NULL) {
                            nad_set_attr(result->nad, 1, -1, "type", "result", 6);

                            pkt_id(pkt, result);

                            pkt_sess(result, sess);

                            pkt_free(pkt);

                            os_free(os);
                
                            return mod_HANDLED;
                        }
                    }
                }

                os_free(os);

                /* drop through */
                log_debug(ZONE, "storage_get succeeded, but couldn't make packet, faking st_NOTFOUND");

            case st_NOTFOUND:

                log_debug(ZONE, "namespace not found, returning");

                /*
                 * !!! really, we should just return a 404. 1.4 just slaps a
                 *     result on the packet and sends it back. hurrah for
                 *     legacy namespaces.
                 */
                nad_set_attr(pkt->nad, 1, -1, "type", "result", 6);

                pkt_sess(pkt_tofrom(pkt), sess);
                
                return mod_HANDLED;

            case st_FAILED:
                return -stanza_err_INTERNAL_SERVER_ERROR;

            case st_NOTIMPL:
                return -stanza_err_FEATURE_NOT_IMPLEMENTED;
        }
    }

    os = os_new();
    o = os_object_new(os);

    snprintf(filter, 4096, "%.*s", NAD_NURI_L(pkt->nad, targetns), NAD_NURI(pkt->nad, targetns));
    os_object_put(o, "ns", filter, os_type_STRING);
    os_object_put(o, "xml", pkt->nad, os_type_NAD);

    snprintf(filter, 4096, "(ns=%i:%.*s)", NAD_NURI_L(pkt->nad, targetns), NAD_NURI_L(pkt->nad, targetns), NAD_NURI(pkt->nad, targetns));

    ret = storage_replace(sess->user->sm->st, "private", jid_user(sess->jid), filter, os);
    os_free(os);

    switch(ret) {
        case st_FAILED:
            return -stanza_err_INTERNAL_SERVER_ERROR;

        case st_NOTIMPL:
            return -stanza_err_FEATURE_NOT_IMPLEMENTED;

        default:
            /* create result packet */
            result = pkt_create(sess->user->sm, "iq", "result", NULL, NULL);
            pkt_id(pkt, result);
            /* and flush it to the session */
            pkt_sess(result, sess);
#ifdef ENABLE_EXPERIMENTAL
            /* push it to all resources that read this xmlns item */
            snprintf(filter, 4096, "%.*s", NAD_NURI_L(pkt->nad, targetns), NAD_NURI(pkt->nad, targetns));
            for(sscan = sess->user->sessions; sscan != NULL; sscan = sscan->next) {
                /* skip our resource and those that didn't read any private-storage */
                if(sscan == sess || sscan->module_data[mod->index] == NULL)
                    continue;

                /* check whether namespace was read */
                if(xhash_get(sscan->module_data[mod->index], filter)) {
                    result = pkt_dup(pkt, jid_full(sscan->jid), NULL);
                    if(result->from != NULL) {
                        jid_free(result->from);
                        nad_set_attr(result->nad, 1, -1, "from", NULL, 0);
                    }
                    pkt_id_new(result);
                    pkt_sess(result, sscan);
                }
            }
#endif
            /* finally free the packet */
            pkt_free(pkt);
            return mod_HANDLED;
    }

    /* we never get here */
    return 0;
}
Esempio n. 28
0
/**
 * process commandline
 * @return: 0 to indicate that output needs to be written
 */
int _pbx_process_command(c2s_t c2s, char *cmd)
{
	jid_t jid;
	int action = 0, len;
	sess_t sess;
	unsigned char hashbuf[44] = "PBX";
	unsigned char *sesshash;

	sesshash = hashbuf+3;

	/* get command */
	if(!strncasecmp("START ", cmd, 6)) {
		cmd += 6;
		action = 1;
	}
	if(!strncasecmp("STOP ", cmd, 5)) {
		cmd += 5;
		action = 2;
	}
	if(action != 0) {
		len = _pbx_command_part_len(cmd);
		if(len > 0) {
			jid = jid_new(cmd, len);
			if(jid) {
				cmd += len;
				if(*cmd != '\0') cmd++;

				shahash_r(jid_full(jid), sesshash);
				sess = xhash_get(c2s->sessions, hashbuf);

				switch(action) {
					case 1:
						log_debug(ZONE, "STARTing session for %s/%s (%s) with commandline: %s", jid_user(jid), jid->resource, hashbuf, cmd);

						if(sess == NULL) {
						/* create new session */
							sess = (sess_t) calloc(1, sizeof(struct sess_st));
							sess->c2s = c2s;
							sess->last_activity = time(NULL);
							/* put into sessions hash */
							snprintf(sess->skey, sizeof(sess->skey), "%s", hashbuf);
							xhash_put(c2s->sessions, sess->skey, (void *) sess);
							/* generate bound resource */
							sess->resources = (bres_t) calloc(1, sizeof(struct bres_st));
							snprintf(sess->resources->c2s_id, sizeof(sess->resources->c2s_id), "%s", hashbuf);
							sess->resources->jid = jid;
							/* open SM session */
							log_write(sess->c2s->log, LOG_NOTICE, "[PBX] requesting session: jid=%s", jid_full(jid));
							sm_start(sess, sess->resources);

							/* generate presence packet to get session online */
							/* a bit hacky, but we need to emulate _some_ of the client behavior */
							sess->result = _pbx_presence_nad(1, cmd);
						}
						else {
							/* just send the presence */
							sm_packet(sess, sess->resources, _pbx_presence_nad(1, cmd));
						}

						break;

					case 2:
						log_debug(ZONE, "STOPping session for %s/%s with commandline: %s", jid_user(jid), jid->resource, cmd);

						if(sess != NULL) {
							/* send unavailable presence */
							sm_packet(sess, sess->resources, _pbx_presence_nad(0, cmd));
							/* end the session */
							sm_end(sess, sess->resources);
							xhash_zap(c2s->sessions, sess->skey);
							jqueue_push(c2s->dead_sess, (void *) sess, 0);
						}

						break;
				}

				/* TODO: respond with "OK", return 0 */
				return -1;
			}
		}
		/* TODO: generate "ERR" response, return 0 */
		return -1;
	}
	if(!strncasecmp("STATUS", cmd, 6)) {
		log_write(c2s->log, LOG_INFO, "STATUS PBX command not implemented yet");
		return -1;
	}
    return -1;
}
Esempio n. 29
0
static void _router_process_route(component_t comp, nad_t nad) {
    int atype, ato, afrom;
    unsigned int dest;
    struct jid_st sto, sfrom;
    jid_static_buf sto_buf, sfrom_buf;
    jid_t to = NULL, from = NULL;
    routes_t targets;
    component_t target;
    union xhashv xhv;

    /* init static jid */
    jid_static(&sto,&sto_buf);
    jid_static(&sfrom,&sfrom_buf);

    if(nad_find_attr(nad, 0, -1, "error", NULL) >= 0) {
        log_debug(ZONE, "dropping error packet, trying to avoid loops");
        nad_free(nad);
        return;
    }

    atype = nad_find_attr(nad, 0, -1, "type", NULL);
    ato = nad_find_attr(nad, 0, -1, "to", NULL);
    afrom = nad_find_attr(nad, 0, -1, "from", NULL);

    if(ato >= 0) to = jid_reset(&sto, NAD_AVAL(nad, ato), NAD_AVAL_L(nad, ato));
    if(afrom >= 0) from = jid_reset(&sfrom, NAD_AVAL(nad, afrom), NAD_AVAL_L(nad, afrom));

    /* unicast */
    if(atype < 0) {
        if(to == NULL || from == NULL) {
            log_debug(ZONE, "unicast route with missing or invalid to or from, bouncing");
            nad_set_attr(nad, 0, -1, "error", "400", 3);
            _router_comp_write(comp, nad);
            return;
        }
        
        log_debug(ZONE, "unicast route from %s to %s", from->domain, to->domain);

        /* check the from */
        if(xhash_get(comp->routes, from->domain) == NULL) {
            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);
            nad_set_attr(nad, 0, -1, "error", "401", 3);
            _router_comp_write(comp, nad);
            return;
        }

        /* filter it */
        if(comp->r->filter != NULL) {
            int ret = filter_packet(comp->r, nad);
            if(ret == stanza_err_REDIRECT) {
                ato = nad_find_attr(nad, 0, -1, "to", NULL);
                if(ato >= 0) to = jid_reset(&sto, NAD_AVAL(nad, ato), NAD_AVAL_L(nad, ato));
            }
            else if(ret > 0) {
                log_debug(ZONE, "packet filtered out: %s (%s)", _stanza_errors[ret - stanza_err_BAD_REQUEST].name, _stanza_errors[ret - stanza_err_BAD_REQUEST].code);
                nad_set_attr(nad, 0, -1, "error", _stanza_errors[ret - stanza_err_BAD_REQUEST].code, 3);
                _router_comp_write(comp, nad);
                return;
            }
        }

        /* find a target */
        targets = xhash_get(comp->r->routes, to->domain);
        if(targets == NULL) {
            if(comp->r->default_route != NULL && strcmp(from->domain, comp->r->default_route) == 0) {
                log_debug(ZONE, "%s is unbound, bouncing", from->domain);
                nad_set_attr(nad, 0, -1, "error", "404", 3);
                _router_comp_write(comp, nad);
                return;
            }
            targets = xhash_get(comp->r->routes, comp->r->default_route);
        }

        if(targets == NULL) {
            log_debug(ZONE, "%s is unbound, and no default route, bouncing", to->domain);
            nad_set_attr(nad, 0, -1, "error", "404", 3);
            _router_comp_write(comp, nad);
            return;
        }

        /* copy to any log sinks */
        if(xhash_count(comp->r->log_sinks) > 0)
            xhash_walk(comp->r->log_sinks, _router_route_log_sink, (void *) nad);

        /* get route candidate */
        if(targets->ncomp == 1) {
            dest = 0;
        }
        else {
            switch(targets->rtype) {
                case route_MULTI_TO:
                    ato = nad_find_attr(nad, 1, -1, "to", NULL);
                    if(ato >= 0) to = jid_reset(&sto, NAD_AVAL(nad, ato), NAD_AVAL_L(nad, ato));
                    else {
                        ato = nad_find_attr(nad, 1, -1, "target", NULL);
                        if(ato >= 0) to = jid_reset(&sto, NAD_AVAL(nad, ato), NAD_AVAL_L(nad, ato));
                        else {
                            const char *out; int len;
                            nad_print(nad, 0, &out, &len);
                            log_write(comp->r->log, LOG_ERR, "Cannot get destination for multiple route: %.*s", len, out);
                        }
                    }
                    break;
                case route_MULTI_FROM:
                    ato = nad_find_attr(nad, 1, -1, "from", NULL);
                    if(ato >= 0) to = jid_reset(&sto, NAD_AVAL(nad, ato), NAD_AVAL_L(nad, ato));
                    else {
                        const char *out; int len;
                        nad_print(nad, 0, &out, &len);
                        log_write(comp->r->log, LOG_ERR, "Cannot get source for multiple route: %.*s", len, out);
                    }
                    break;
                default:
                    log_write(comp->r->log, LOG_ERR, "Multiple components bound to single component route '%s'", targets->name);
                    /* simulate no 'to' info in this case */
            }
            if(to->node == NULL || strlen(to->node) == 0) {
                /* no node in destination JID - going random */
                dest = rand();
                log_debug(ZONE, "randomized to %u %% %d = %d", dest, targets->ncomp, dest % targets->ncomp);
            }
            else {
                /* use JID hash */
                unsigned char hashval[20];
                unsigned int *val;
                int i;
                
                shahash_raw(jid_user(to), hashval);
                
                val = (unsigned int *) hashval;
                dest = *val;
                for(i=1; i < 20 / (sizeof(unsigned int)/sizeof(unsigned char)); i++, val++) {
                    dest ^= *val;
                }
                dest >>= 2;

                log_debug(ZONE, "JID %s hashed to %u %% %d = %d", jid_user(to), dest, targets->ncomp, dest % targets->ncomp);

                /* jid_user() calls jid_expand() which may allocate some memory in _user and _full */
                if (to->_user != NULL )
                    free(to->_user);
                if (to->_full != NULL )
                    free(to->_full);
            }
            dest = dest % targets->ncomp;
        }

        target = targets->comp[dest];

        /* push it out */
        log_debug(ZONE, "writing route for '%s'*%u to %s, port %d", to->domain, dest+1, target->ip, target->port);

        /* if logging enabled, log messages that match our criteria */
        if (comp->r->message_logging_enabled && comp->r->message_logging_file != NULL) {
            int attr_msg_to;
            int attr_msg_from;
            int attr_route_to;
            int attr_route_from;
            jid_t jid_msg_from = NULL;
            jid_t jid_msg_to = NULL;
            jid_t jid_route_from = NULL;
            jid_t jid_route_to = NULL;

            if ((NAD_ENAME_L(nad, 1) == 7 && strncmp("message", NAD_ENAME(nad, 1), 7) == 0) &&		// has a "message" element 
                ((attr_route_from = nad_find_attr(nad, 0, -1, "from", NULL)) >= 0) &&
                ((attr_route_to = nad_find_attr(nad, 0, -1, "to", NULL)) >= 0) &&
                ((strncmp(NAD_AVAL(nad, attr_route_to), "c2s", 3)) != 0) &&							// ignore messages to "c2s" or we'd have dups
                ((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
                ((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
                ((attr_msg_from = nad_find_attr(nad, 1, -1, "from", NULL)) >= 0) &&
                ((attr_msg_to = nad_find_attr(nad, 1, -1, "to", NULL)) >= 0) &&
                ((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 
                ((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
            {
                message_log(nad, comp->r, jid_full(jid_msg_from), jid_full(jid_msg_to));
            }
            if (jid_msg_from != NULL)
                jid_free(jid_msg_from);
            if (jid_msg_to != NULL)
                jid_free(jid_msg_to);
            if (jid_route_from != NULL)
                jid_free(jid_route_from);
            if (jid_route_to != NULL)
                jid_free(jid_route_to);
        }

        _router_comp_write(target, nad);

        return;
    }

    /* broadcast */
    if(NAD_AVAL_L(nad, atype) == 9 && strncmp("broadcast", NAD_AVAL(nad, atype), 9) == 0) {
        if(from == NULL) {
            log_debug(ZONE, "broadcast route with missing or invalid from, bouncing");
            nad_set_attr(nad, 0, -1, "error", "400", 3);
            _router_comp_write(comp, nad);
            return;
        }
        
        log_debug(ZONE, "broadcast route from %s", from->domain);

        /* check the from */
        if(xhash_get(comp->routes, from->domain) == NULL) {
            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);
            nad_set_attr(nad, 0, -1, "error", "401", 3);
            _router_comp_write(comp, nad);
            return;
        }

        /* loop the components and distribute */
        if(xhash_iter_first(comp->r->components))
            do {
                xhv.comp_val = &target;
                xhash_iter_get(comp->r->components, NULL, NULL, xhv.val);

                if(target != comp) {
                    log_debug(ZONE, "writing broadcast to %s, port %d", target->ip, target->port);

                    _router_comp_write(target, nad_copy(nad));
                }
            } while(xhash_iter_next(comp->r->components));

        nad_free(nad);

        return;
    }

    log_debug(ZONE, "unknown route type '%.*s', dropping", NAD_AVAL_L(nad, atype), NAD_AVAL(nad, atype));

    nad_free(nad);
}
Esempio n. 30
0
static void _router_process_bind(component_t comp, nad_t nad) {
    int attr, multi, n;
    jid_t name;
    alias_t alias;
    char *user, *c;

    attr = nad_find_attr(nad, 0, -1, "name", NULL);
    if(attr < 0 || (name = jid_new(NAD_AVAL(nad, attr), NAD_AVAL_L(nad, attr))) == NULL) {
        log_debug(ZONE, "no or invalid 'name' on bind packet, bouncing");
        nad_set_attr(nad, 0, -1, "error", "400", 3);
        sx_nad_write(comp->s, nad);
        return;
    }

    user = strdup(comp->s->auth_id);
    c = strchr(user, '@');
    if(c != NULL) *c = '\0';

    if(strcmp(user, name->domain) != 0 && !aci_check(comp->r->aci, "bind", user)) {
        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);
        nad_set_attr(nad, 0, -1, "name", NULL, 0);
        nad_set_attr(nad, 0, -1, "error", "403", 3);
        sx_nad_write(comp->s, nad);
        jid_free(name);
        free(user);
        return;
    }

    multi = nad_find_attr(nad, 0, -1, "multi", NULL);
    if(xhash_get(comp->r->routes, name->domain) != NULL && multi < 0) {
        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);
        nad_set_attr(nad, 0, -1, "name", NULL, 0);
        nad_set_attr(nad, 0, -1, "error", "409", 3);
        sx_nad_write(comp->s, nad);
        jid_free(name);
        free(user);
        return;
    }

    for(alias = comp->r->aliases; alias != NULL; alias = alias->next)
        if(strcmp(alias->name, name->domain) == 0) {
            log_write(comp->r->log, LOG_NOTICE, "[%s, port=%d] tried to bind '%s', but that name is aliased", comp->ip, comp->port);
            nad_set_attr(nad, 0, -1, "name", NULL, 0);
            nad_set_attr(nad, 0, -1, "error", "409", 3);
            sx_nad_write(comp->s, nad);
            jid_free(name);
            free(user);
            return;
        }

    /* default route */
    if(nad_find_elem(nad, 0, NAD_ENS(nad, 0), "default", 1) >= 0) {
        if(!aci_check(comp->r->aci, "default-route", user)) {
            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);
            nad_set_attr(nad, 0, -1, "name", NULL, 0);
            nad_set_attr(nad, 0, -1, "error", "403", 3);
            sx_nad_write(comp->s, nad);
            jid_free(name);
            free(user);
            return;
        }

        if(comp->r->default_route != NULL) {
            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);
            nad_set_attr(nad, 0, -1, "name", NULL, 0);
            nad_set_attr(nad, 0, -1, "error", "409", 3);
            sx_nad_write(comp->s, nad);
            jid_free(name);
            return;
        }

        log_write(comp->r->log, LOG_NOTICE, "[%s] set as default route", name->domain);

        comp->r->default_route = strdup(name->domain);
    }

    /* log sinks */
    if(nad_find_elem(nad, 0, NAD_ENS(nad, 0), "log", 1) >= 0) {
        if(!aci_check(comp->r->aci, "log", user)) {
            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);
            nad_set_attr(nad, 0, -1, "name", NULL, 0);
            nad_set_attr(nad, 0, -1, "error", "403", 3);
            sx_nad_write(comp->s, nad);
            jid_free(name);
            free(user);
            return;
        }

        log_write(comp->r->log, LOG_NOTICE, "[%s] set as log sink", name->domain);

        xhash_put(comp->r->log_sinks, pstrdup(xhash_pool(comp->r->log_sinks), name->domain), (void *) comp);
    }

    free(user);

    n = _route_add(comp->r->routes, name->domain, comp, multi<0?route_SINGLE:route_MULTI_TO);
    xhash_put(comp->routes, pstrdup(xhash_pool(comp->routes), name->domain), (void *) comp);

    if(n>1)
        log_write(comp->r->log, LOG_NOTICE, "[%s]:%d online (bound to %s, port %d)", name->domain, n, comp->ip, comp->port);
    else
        log_write(comp->r->log, LOG_NOTICE, "[%s] online (bound to %s, port %d)", name->domain, comp->ip, comp->port);

    nad_set_attr(nad, 0, -1, "name", NULL, 0);
    sx_nad_write(comp->s, nad);

    /* advertise name */
    _router_advertise(comp->r, name->domain, comp, 0);

    /* tell the new component about everyone else */
    xhash_walk(comp->r->routes, _router_advertise_reverse, (void *) comp);

    /* bind aliases */
    for(alias = comp->r->aliases; alias != NULL; alias = alias->next) {
        if(strcmp(alias->target, name->domain) == 0) {
            _route_add(comp->r->routes, name->domain, comp, route_MULTI_TO);
            xhash_put(comp->routes, pstrdup(xhash_pool(comp->routes), alias->name), (void *) comp);
            
            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);

            /* advertise name */
            _router_advertise(comp->r, alias->name, comp, 0);
        }
    }

    /* done with this */
    jid_free(name);
}