jabberd2  2.2.16
s2s/router.c
Go to the documentation of this file.
00001 /*
00002  * jabberd - Jabber Open Source Server
00003  * Copyright (c) 2002 Jeremie Miller, Thomas Muldowney,
00004  *                    Ryan Eatmon, Robert Norris
00005  *
00006  * This program is free software; you can redistribute it and/or modify
00007  * it under the terms of the GNU General Public License as published by
00008  * the Free Software Foundation; either version 2 of the License, or
00009  * (at your option) any later version.
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with this program; if not, write to the Free Software
00018  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA02111-1307USA
00019  */
00020 
00021 #include "s2s.h"
00022 
00024 int s2s_router_sx_callback(sx_t s, sx_event_t e, void *data, void *arg) {
00025     s2s_t s2s = (s2s_t) arg;
00026     sx_buf_t buf = (sx_buf_t) data;
00027     sx_error_t *sxe;
00028     nad_t nad;
00029     int len, ns, elem, attr, i;
00030     pkt_t pkt;
00031 
00032     switch(e) {
00033         case event_WANT_READ:
00034             log_debug(ZONE, "want read");
00035             mio_read(s2s->mio, s2s->fd);
00036             break;
00037 
00038         case event_WANT_WRITE:
00039             log_debug(ZONE, "want write");
00040             mio_write(s2s->mio, s2s->fd);
00041             break;
00042 
00043         case event_READ:
00044             log_debug(ZONE, "reading from %d", s2s->fd->fd);
00045 
00046             /* do the read */
00047             len = recv(s2s->fd->fd, buf->data, buf->len, 0);
00048 
00049             if(len < 0) {
00050                 if(MIO_WOULDBLOCK) {
00051                     buf->len = 0;
00052                     return 0;
00053                 }
00054 
00055                 log_write(s2s->log, LOG_NOTICE, "[%d] [router] read error: %s (%d)", s2s->fd->fd, MIO_STRERROR(MIO_ERROR), MIO_ERROR);
00056 
00057                 sx_kill(s);
00058                 
00059                 return -1;
00060             }
00061 
00062             else if(len == 0) {
00063                 /* they went away */
00064                 sx_kill(s);
00065 
00066                 return -1;
00067             }
00068 
00069             log_debug(ZONE, "read %d bytes", len);
00070 
00071             buf->len = len;
00072 
00073             return len;
00074 
00075         case event_WRITE:
00076             log_debug(ZONE, "writing to %d", s2s->fd->fd);
00077 
00078             len = send(s2s->fd->fd, buf->data, buf->len, 0);
00079             if(len >= 0) {
00080                 log_debug(ZONE, "%d bytes written", len);
00081                 return len;
00082             }
00083 
00084             if(MIO_WOULDBLOCK)
00085                 return 0;
00086 
00087             log_write(s2s->log, LOG_NOTICE, "[%d] [router] write error: %s (%d)", s2s->fd->fd, MIO_STRERROR(MIO_ERROR), MIO_ERROR);
00088 
00089             sx_kill(s);
00090 
00091             return -1;
00092 
00093         case event_ERROR:
00094             sxe = (sx_error_t *) data;
00095             log_write(s2s->log, LOG_NOTICE, "error from router: %s (%s)", sxe->generic, sxe->specific);
00096 
00097             if(sxe->code == SX_ERR_AUTH)
00098                 sx_close(s);
00099 
00100             break;
00101 
00102         case event_STREAM:
00103             break;
00104 
00105         case event_OPEN:
00106             log_write(s2s->log, LOG_NOTICE, "connection to router established");
00107 
00108             /* set connection attempts counter */
00109             s2s->retry_left = s2s->retry_lost;
00110 
00111             nad = nad_new();
00112             ns = nad_add_namespace(nad, uri_COMPONENT, NULL);
00113             nad_append_elem(nad, ns, "bind", 0);
00114             nad_append_attr(nad, -1, "name", s2s->id);
00115             if(s2s->router_default)
00116                 nad_append_elem(nad, ns, "default", 1);
00117 
00118             log_debug(ZONE, "requesting component bind for '%s'", s2s->id);
00119 
00120             sx_nad_write(s2s->router, nad);
00121 
00122             break;
00123 
00124         case event_PACKET:
00125             nad = (nad_t) data;
00126 
00127             /* drop unqualified packets */
00128             if(NAD_ENS(nad, 0) < 0) {
00129                 nad_free(nad);
00130                 return 0;
00131             }
00132 
00133             /* watch for the features packet */
00134             if(s->state == state_STREAM) {
00135                 if(NAD_NURI_L(nad, NAD_ENS(nad, 0)) != strlen(uri_STREAMS) || strncmp(uri_STREAMS, NAD_NURI(nad, NAD_ENS(nad, 0)), strlen(uri_STREAMS)) != 0 || NAD_ENAME_L(nad, 0) != 8 || strncmp("features", NAD_ENAME(nad, 0), 8) != 0) {
00136                     log_debug(ZONE, "got a non-features packet on an unauth'd stream, dropping");
00137                     nad_free(nad);
00138                     return 0;
00139                 }
00140 
00141 #ifdef HAVE_SSL
00142                 /* starttls if we can */
00143                 if(s2s->sx_ssl != NULL && s2s->router_pemfile != NULL && s->ssf == 0) {
00144                     ns = nad_find_scoped_namespace(nad, uri_TLS, NULL);
00145                     if(ns >= 0) {
00146                         elem = nad_find_elem(nad, 0, ns, "starttls", 1);
00147                         if(elem >= 0) {
00148                             if(sx_ssl_client_starttls(s2s->sx_ssl, s, s2s->router_pemfile) == 0) {
00149                                 nad_free(nad);
00150                                 return 0;
00151                             }
00152                             log_write(s2s->log, LOG_NOTICE, "unable to establish encrypted session with router");
00153                         }
00154                     }
00155                 }
00156 #endif
00157 
00158                 /* !!! pull the list of mechanisms, and choose the best one.
00159                  *     if there isn't an appropriate one, error and bail */
00160 
00161                 /* authenticate */
00162                 sx_sasl_auth(s2s->sx_sasl, s, "jabberd-router", "DIGEST-MD5", s2s->router_user, s2s->router_pass);
00163 
00164                 nad_free(nad);
00165                 return 0;
00166             }
00167 
00168             /* watch for the bind response */
00169             if(s->state == state_OPEN && !s2s->online) {
00170                 if(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 || NAD_ENAME_L(nad, 0) != 4 || strncmp("bind", NAD_ENAME(nad, 0), 4)) {
00171                     log_debug(ZONE, "got a packet from router, but we're not online, dropping");
00172                     nad_free(nad);
00173                     return 0;
00174                 }
00175 
00176                 /* catch errors */
00177                 attr = nad_find_attr(nad, 0, -1, "error", NULL);
00178                 if(attr >= 0) {
00179                     log_write(s2s->log, LOG_NOTICE, "router refused bind request (%.*s)", NAD_AVAL_L(nad, attr), NAD_AVAL(nad, attr));
00180                     exit(1);
00181                 }
00182 
00183                 log_debug(ZONE, "coming online");
00184 
00185                 /* if we're coming online for the first time, setup listening sockets */
00186                 if(s2s->server_fd == 0) {
00187                     if(s2s->local_port != 0) {
00188                         s2s->server_fd = mio_listen(s2s->mio, s2s->local_port, s2s->local_ip, in_mio_callback, (void *) s2s);
00189                         if(s2s->server_fd == NULL) {
00190                             log_write(s2s->log, LOG_ERR, "[%s, port=%d] failed to listen", s2s->local_ip, s2s->local_port);
00191                             exit(1);
00192                         } else
00193                             log_write(s2s->log, LOG_NOTICE, "[%s, port=%d] listening for connections", s2s->local_ip, s2s->local_port);
00194                     }
00195                 }
00196 
00197                 /* we're online */
00198                 s2s->online = s2s->started = 1;
00199                 log_write(s2s->log, LOG_NOTICE, "ready for connections", s2s->id);
00200 
00201                 nad_free(nad);
00202                 return 0;
00203             }
00204 
00205             log_debug(ZONE, "got a packet");
00206 
00207             /* sanity checks */
00208             if(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) {
00209                 log_debug(ZONE, "unknown namespace, dropping packet");
00210                 nad_free(nad);
00211                 return 0;
00212             }
00213 
00214             if(NAD_ENAME_L(nad, 0) != 5 || strncmp("route", NAD_ENAME(nad, 0), 5) != 0) {
00215                 log_debug(ZONE, "dropping non-route packet");
00216                 nad_free(nad);
00217                 return 0;
00218             }
00219 
00220             if(nad_find_attr(nad, 0, -1, "type", NULL) >= 0) {
00221                 log_debug(ZONE, "dropping non-unicast packet");
00222                 nad_free(nad);
00223                 return 0;
00224             }
00225 
00226             /* packets to us */
00227             attr = nad_find_attr(nad, 0, -1, "to", NULL);
00228             if(NAD_AVAL_L(nad, attr) == strlen(s2s->id) && strncmp(s2s->id, NAD_AVAL(nad, attr), NAD_AVAL_L(nad, attr)) == 0) {
00229                 log_debug(ZONE, "dropping unknown or invalid packet for s2s component proper");
00230                 nad_free(nad);
00231 
00232                 return 0;
00233             }
00234 
00235             /* mangle error packet to create bounce */
00236             if((attr = nad_find_attr(nad, 0, -1, "error", NULL)) >= 0) {
00237                 log_debug(ZONE, "bouncing error packet");
00238                 elem = stanza_err_REMOTE_SERVER_NOT_FOUND;
00239                 if(attr >= 0) {
00240                     for(i=0; _stanza_errors[i].code != NULL; i++)
00241                         if(strncmp(_stanza_errors[i].code, NAD_AVAL(nad, attr), NAD_AVAL_L(nad, attr)) == 0) {
00242                             elem = stanza_err_BAD_REQUEST + i;
00243                             break;
00244                         }
00245                 }
00246                 stanza_tofrom(stanza_tofrom(stanza_error(nad, 1, elem), 1), 0);
00247                 if( (elem = nad_find_attr(nad, 1, -1, "to", NULL)) >= 0 )
00248                     nad_set_attr(nad, 0, -1, "to",  NAD_AVAL(nad, elem), NAD_AVAL_L(nad, elem));
00249             }
00250 
00251             /* new packet */
00252             pkt = (pkt_t) calloc(1, sizeof(struct pkt_st));
00253 
00254             pkt->nad = nad;
00255 
00256             if((attr = nad_find_attr(pkt->nad, 1, -1, "from", NULL)) >= 0 && NAD_AVAL_L(pkt->nad, attr) > 0)
00257                 pkt->from = jid_new(NAD_AVAL(pkt->nad, attr), NAD_AVAL_L(pkt->nad, attr));
00258             else {
00259                 attr = nad_find_attr(nad, 0, -1, "from", NULL);
00260                 pkt->from = jid_new(NAD_AVAL(nad, attr), NAD_AVAL_L(nad, attr));
00261             }
00262 
00263             if((attr = nad_find_attr(pkt->nad, 1, -1, "to", NULL)) >= 0 && NAD_AVAL_L(pkt->nad, attr) > 0)
00264                 pkt->to = jid_new(NAD_AVAL(pkt->nad, attr), NAD_AVAL_L(pkt->nad, attr));
00265             else {
00266                 attr = nad_find_attr(nad, 0, -1, "to", NULL);
00267                 pkt->to = jid_new(NAD_AVAL(nad, attr), NAD_AVAL_L(nad, attr));
00268             }
00269 
00270             /* change the packet so it looks like it came to us, so the router won't reject it if we bounce it later */
00271             nad_set_attr(nad, 0, -1, "to", s2s->id, 0);
00272 
00273             /* flag dialback */
00274             if(NAD_NURI_L(pkt->nad, 0) == uri_DIALBACK_L && strncmp(uri_DIALBACK, NAD_NURI(pkt->nad, 0), uri_DIALBACK_L) == 0)
00275                 pkt->db = 1;
00276 
00277             /* send it out */
00278             out_packet(s2s, pkt);
00279 
00280             return 0;
00281 
00282         case event_CLOSED:
00283             mio_close(s2s->mio, s2s->fd);
00284             s2s->fd = NULL;
00285             return -1;
00286     }
00287 
00288     return 0;
00289 }
00290 
00291 int s2s_router_mio_callback(mio_t m, mio_action_t a, mio_fd_t fd, void *data, void *arg) {
00292     s2s_t s2s = (s2s_t) arg;
00293     int nbytes;
00294 
00295     switch(a) {
00296         case action_READ:
00297             log_debug(ZONE, "read action on fd %d", fd->fd);
00298 
00299             ioctl(fd->fd, FIONREAD, &nbytes);
00300             if(nbytes == 0) {
00301                 sx_kill(s2s->router);
00302                 return 0;
00303             }
00304 
00305             return sx_can_read(s2s->router);
00306 
00307         case action_WRITE:
00308             log_debug(ZONE, "write action on fd %d", fd->fd);
00309             return sx_can_write(s2s->router);
00310 
00311         case action_CLOSE:
00312             log_debug(ZONE, "close action on fd %d", fd->fd);
00313             log_write(s2s->log, LOG_NOTICE, "connection to router closed");
00314 
00315             s2s_lost_router = 1;
00316 
00317             /* we're offline */
00318             s2s->online = 0;
00319 
00320             break;
00321 
00322         case action_ACCEPT:
00323             break;
00324     }
00325 
00326     return 0;
00327 }