⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 router.c

📁 这是一个完全开放的
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * jabberd - Jabber Open Source Server * Copyright (c) 2002 Jeremie Miller, Thomas Muldowney, *                    Ryan Eatmon, Robert Norris * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA02111-1307USA */#include "router.h"/** info for broadcasts */typedef struct broadcast_st {    router_t      r;    component_t   src;    nad_t         nad;} *broadcast_t;/** broadcast a packet */static void _router_broadcast(xht routes, const char *key, void *val, void *arg) {    broadcast_t bc = (broadcast_t) arg;    component_t comp = (component_t) val;    /* I don't care about myself or the elderly (!?) */    if(comp == bc->src || comp->legacy)        return;    sx_nad_write(comp->s, nad_copy(bc->nad));}/** domain advertisement */static void _router_advertise(router_t r, char *domain, component_t src, int unavail) {    struct broadcast_st bc;    int ns;    log_debug(ZONE, "advertising %s to all routes (unavail=%d)", domain, unavail);    bc.r = r;    bc.src = src;    /* create a new packet */    bc.nad = nad_new(src->s->nad_cache);    ns = nad_add_namespace(bc.nad, uri_COMPONENT, NULL);    nad_append_elem(bc.nad, ns, "presence", 0);    nad_append_attr(bc.nad, -1, "from", domain);    if(unavail)        nad_append_attr(bc.nad, -1, "type", "unavailable");    xhash_walk(r->routes, _router_broadcast, (void *) &bc);    nad_free(bc.nad);}/** tell a component about all the others */static void _router_advertise_reverse(xht routes, const char *key, void *val, void *arg) {    component_t dest = (component_t) arg, comp = (component_t) val;    int ns;    nad_t nad;    /* don't tell me about myself */    if(comp == dest)        return;    log_debug(ZONE, "informing component about %s", key);    /* create a new packet */    nad = nad_new(dest->s->nad_cache);    ns = nad_add_namespace(nad, uri_COMPONENT, NULL);    nad_append_elem(nad, ns, "presence", 0);    nad_append_attr(nad, -1, "from", (char *) key);    sx_nad_write(dest->s, nad);}static void _router_process_handshake(component_t comp, nad_t nad) {    char *hash;    int hashlen;    /* must have a hash as cdata */    if(NAD_CDATA_L(nad, 0) != 40) {        log_debug(ZONE, "handshake isn't long enough to be a sha1 hash");        sx_error(comp->s, stream_err_NOT_AUTHORIZED, "handshake isn't long enough to be a sha1 hash");        sx_close(comp->s);        nad_free(nad);        return;    }    /* make room for shahash_r to work .. needs at least 41 chars */    hashlen = strlen(comp->s->id) + strlen(comp->r->local_secret) + 1;    if(hashlen < 41)        hashlen = 41;    /* build the creds and hash them */    hash = (char *) malloc(sizeof(char) * hashlen);    sprintf(hash, "%s%s", comp->s->id, comp->r->local_secret);    shahash_r(hash, hash);    /* check */    log_debug(ZONE, "checking their hash %.*s against our hash %s", 40, NAD_CDATA(nad, 0), hash);    if(strncmp(hash, NAD_CDATA(nad, 0), 40) == 0) {        log_debug(ZONE, "handshake succeeded");        free(hash);        /* respond */        nad->elems[0].icdata = nad->elems[0].itail = -1;        nad->elems[0].lcdata = nad->elems[0].ltail = 0;        sx_nad_write(comp->s, nad);        sx_auth(comp->s, "handshake", comp->s->req_to);                return;    }        log_debug(ZONE, "auth failed");    free(hash);    /* failed, let them know */    sx_error(comp->s, stream_err_NOT_AUTHORIZED, "hash didn't match, auth failed");    sx_close(comp->s);    nad_free(nad);}static void _router_process_bind(component_t comp, nad_t nad) {    int attr;    jid_t name;    alias_t alias;    char *user, *c;    attr = nad_find_attr(nad, 0, -1, "name", NULL);    if(attr < 0 || (name = jid_new(comp->r->pc, 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;    }    if(xhash_get(comp->r->routes, name->domain) != NULL) {        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);    xhash_put(comp->r->routes, pstrdup(xhash_pool(comp->r->routes), name->domain), (void *) comp);    xhash_put(comp->routes, pstrdup(xhash_pool(comp->routes), name->domain), (void *) comp);    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) {            xhash_put(comp->r->routes, pstrdup(xhash_pool(comp->r->routes), alias->name), (void *) comp);            xhash_put(comp->routes, pstrdup(xhash_pool(comp->r->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);}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(comp->r->pc, 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->routes, name->domain);    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(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 */    _router_advertise(comp->r, name->domain, comp, 1);    jid_free(name);}static void _router_comp_write(component_t comp, nad_t nad) {    int attr;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -