jabberd2  2.2.17
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 "s2s.h"
22 
24 int s2s_router_sx_callback(sx_t s, sx_event_t e, void *data, void *arg) {
25  s2s_t s2s = (s2s_t) arg;
26  sx_buf_t buf = (sx_buf_t) data;
27  sx_error_t *sxe;
28  nad_t nad;
29  int len, ns, elem, attr, i;
30  pkt_t pkt;
31 
32  switch(e) {
33  case event_WANT_READ:
34  log_debug(ZONE, "want read");
35  mio_read(s2s->mio, s2s->fd);
36  break;
37 
38  case event_WANT_WRITE:
39  log_debug(ZONE, "want write");
40  mio_write(s2s->mio, s2s->fd);
41  break;
42 
43  case event_READ:
44  log_debug(ZONE, "reading from %d", s2s->fd->fd);
45 
46  /* do the read */
47  len = recv(s2s->fd->fd, buf->data, buf->len, 0);
48 
49  if(len < 0) {
50  if(MIO_WOULDBLOCK) {
51  buf->len = 0;
52  return 0;
53  }
54 
55  log_write(s2s->log, LOG_NOTICE, "[%d] [router] read error: %s (%d)", s2s->fd->fd, MIO_STRERROR(MIO_ERROR), MIO_ERROR);
56 
57  sx_kill(s);
58 
59  return -1;
60  }
61 
62  else if(len == 0) {
63  /* they went away */
64  sx_kill(s);
65 
66  return -1;
67  }
68 
69  log_debug(ZONE, "read %d bytes", len);
70 
71  buf->len = len;
72 
73  return len;
74 
75  case event_WRITE:
76  log_debug(ZONE, "writing to %d", s2s->fd->fd);
77 
78  len = send(s2s->fd->fd, buf->data, buf->len, 0);
79  if(len >= 0) {
80  log_debug(ZONE, "%d bytes written", len);
81  return len;
82  }
83 
84  if(MIO_WOULDBLOCK)
85  return 0;
86 
87  log_write(s2s->log, LOG_NOTICE, "[%d] [router] write error: %s (%d)", s2s->fd->fd, MIO_STRERROR(MIO_ERROR), MIO_ERROR);
88 
89  sx_kill(s);
90 
91  return -1;
92 
93  case event_ERROR:
94  sxe = (sx_error_t *) data;
95  log_write(s2s->log, LOG_NOTICE, "error from router: %s (%s)", sxe->generic, sxe->specific);
96 
97  if(sxe->code == SX_ERR_AUTH)
98  sx_close(s);
99 
100  break;
101 
102  case event_STREAM:
103  break;
104 
105  case event_OPEN:
106  log_write(s2s->log, LOG_NOTICE, "connection to router established");
107 
108  /* set connection attempts counter */
109  s2s->retry_left = s2s->retry_lost;
110 
111  nad = nad_new();
112  ns = nad_add_namespace(nad, uri_COMPONENT, NULL);
113  nad_append_elem(nad, ns, "bind", 0);
114  nad_append_attr(nad, -1, "name", s2s->id);
115  if(s2s->router_default)
116  nad_append_elem(nad, ns, "default", 1);
117 
118  log_debug(ZONE, "requesting component bind for '%s'", s2s->id);
119 
120  sx_nad_write(s2s->router, nad);
121 
122  break;
123 
124  case event_PACKET:
125  nad = (nad_t) data;
126 
127  /* drop unqualified packets */
128  if(NAD_ENS(nad, 0) < 0) {
129  nad_free(nad);
130  return 0;
131  }
132 
133  /* watch for the features packet */
134  if(s->state == state_STREAM) {
135  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) {
136  log_debug(ZONE, "got a non-features packet on an unauth'd stream, dropping");
137  nad_free(nad);
138  return 0;
139  }
140 
141 #ifdef HAVE_SSL
142  /* starttls if we can */
143  if(s2s->sx_ssl != NULL && s2s->router_pemfile != NULL && s->ssf == 0) {
144  ns = nad_find_scoped_namespace(nad, uri_TLS, NULL);
145  if(ns >= 0) {
146  elem = nad_find_elem(nad, 0, ns, "starttls", 1);
147  if(elem >= 0) {
148  if(sx_ssl_client_starttls(s2s->sx_ssl, s, s2s->router_pemfile) == 0) {
149  nad_free(nad);
150  return 0;
151  }
152  log_write(s2s->log, LOG_NOTICE, "unable to establish encrypted session with router");
153  }
154  }
155  }
156 #endif
157 
158  /* !!! pull the list of mechanisms, and choose the best one.
159  * if there isn't an appropriate one, error and bail */
160 
161  /* authenticate */
162  sx_sasl_auth(s2s->sx_sasl, s, "jabberd-router", "DIGEST-MD5", s2s->router_user, s2s->router_pass);
163 
164  nad_free(nad);
165  return 0;
166  }
167 
168  /* watch for the bind response */
169  if(s->state == state_OPEN && !s2s->online) {
170  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)) {
171  log_debug(ZONE, "got a packet from router, but we're not online, dropping");
172  nad_free(nad);
173  return 0;
174  }
175 
176  /* catch errors */
177  attr = nad_find_attr(nad, 0, -1, "error", NULL);
178  if(attr >= 0) {
179  log_write(s2s->log, LOG_NOTICE, "router refused bind request (%.*s)", NAD_AVAL_L(nad, attr), NAD_AVAL(nad, attr));
180  exit(1);
181  }
182 
183  log_debug(ZONE, "coming online");
184 
185  /* if we're coming online for the first time, setup listening sockets */
186  if(s2s->server_fd == 0) {
187  if(s2s->local_port != 0) {
188  s2s->server_fd = mio_listen(s2s->mio, s2s->local_port, s2s->local_ip, in_mio_callback, (void *) s2s);
189  if(s2s->server_fd == NULL) {
190  log_write(s2s->log, LOG_ERR, "[%s, port=%d] failed to listen", s2s->local_ip, s2s->local_port);
191  exit(1);
192  } else
193  log_write(s2s->log, LOG_NOTICE, "[%s, port=%d] listening for connections", s2s->local_ip, s2s->local_port);
194  }
195  }
196 
197  /* we're online */
198  s2s->online = s2s->started = 1;
199  log_write(s2s->log, LOG_NOTICE, "ready for connections", s2s->id);
200 
201  nad_free(nad);
202  return 0;
203  }
204 
205  log_debug(ZONE, "got a packet");
206 
207  /* sanity checks */
208  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) {
209  log_debug(ZONE, "unknown namespace, dropping packet");
210  nad_free(nad);
211  return 0;
212  }
213 
214  if(NAD_ENAME_L(nad, 0) != 5 || strncmp("route", NAD_ENAME(nad, 0), 5) != 0) {
215  log_debug(ZONE, "dropping non-route packet");
216  nad_free(nad);
217  return 0;
218  }
219 
220  if(nad_find_attr(nad, 0, -1, "type", NULL) >= 0) {
221  log_debug(ZONE, "dropping non-unicast packet");
222  nad_free(nad);
223  return 0;
224  }
225 
226  /* packets to us */
227  attr = nad_find_attr(nad, 0, -1, "to", NULL);
228  if(NAD_AVAL_L(nad, attr) == strlen(s2s->id) && strncmp(s2s->id, NAD_AVAL(nad, attr), NAD_AVAL_L(nad, attr)) == 0) {
229  log_debug(ZONE, "dropping unknown or invalid packet for s2s component proper");
230  nad_free(nad);
231 
232  return 0;
233  }
234 
235  /* mangle error packet to create bounce */
236  if((attr = nad_find_attr(nad, 0, -1, "error", NULL)) >= 0) {
237  log_debug(ZONE, "bouncing error packet");
239  if(attr >= 0) {
240  for(i=0; _stanza_errors[i].code != NULL; i++)
241  if(strncmp(_stanza_errors[i].code, NAD_AVAL(nad, attr), NAD_AVAL_L(nad, attr)) == 0) {
242  elem = stanza_err_BAD_REQUEST + i;
243  break;
244  }
245  }
246  stanza_tofrom(stanza_tofrom(stanza_error(nad, 1, elem), 1), 0);
247  if( (elem = nad_find_attr(nad, 1, -1, "to", NULL)) >= 0 )
248  nad_set_attr(nad, 0, -1, "to", NAD_AVAL(nad, elem), NAD_AVAL_L(nad, elem));
249  }
250 
251  /* new packet */
252  pkt = (pkt_t) calloc(1, sizeof(struct pkt_st));
253 
254  pkt->nad = nad;
255 
256  if((attr = nad_find_attr(pkt->nad, 1, -1, "from", NULL)) >= 0 && NAD_AVAL_L(pkt->nad, attr) > 0)
257  pkt->from = jid_new(NAD_AVAL(pkt->nad, attr), NAD_AVAL_L(pkt->nad, attr));
258  else {
259  attr = nad_find_attr(nad, 0, -1, "from", NULL);
260  pkt->from = jid_new(NAD_AVAL(nad, attr), NAD_AVAL_L(nad, attr));
261  }
262 
263  if((attr = nad_find_attr(pkt->nad, 1, -1, "to", NULL)) >= 0 && NAD_AVAL_L(pkt->nad, attr) > 0)
264  pkt->to = jid_new(NAD_AVAL(pkt->nad, attr), NAD_AVAL_L(pkt->nad, attr));
265  else {
266  attr = nad_find_attr(nad, 0, -1, "to", NULL);
267  pkt->to = jid_new(NAD_AVAL(nad, attr), NAD_AVAL_L(nad, attr));
268  }
269 
270  /* change the packet so it looks like it came to us, so the router won't reject it if we bounce it later */
271  nad_set_attr(nad, 0, -1, "to", s2s->id, 0);
272 
273  /* flag dialback */
274  if(NAD_NURI_L(pkt->nad, 0) == uri_DIALBACK_L && strncmp(uri_DIALBACK, NAD_NURI(pkt->nad, 0), uri_DIALBACK_L) == 0)
275  pkt->db = 1;
276 
277  /* send it out */
278  out_packet(s2s, pkt);
279 
280  return 0;
281 
282  case event_CLOSED:
283  mio_close(s2s->mio, s2s->fd);
284  s2s->fd = NULL;
285  return -1;
286  }
287 
288  return 0;
289 }
290 
291 int s2s_router_mio_callback(mio_t m, mio_action_t a, mio_fd_t fd, void *data, void *arg) {
292  s2s_t s2s = (s2s_t) arg;
293  int nbytes;
294 
295  switch(a) {
296  case action_READ:
297  log_debug(ZONE, "read action on fd %d", fd->fd);
298 
299  ioctl(fd->fd, FIONREAD, &nbytes);
300  if(nbytes == 0) {
301  sx_kill(s2s->router);
302  return 0;
303  }
304 
305  return sx_can_read(s2s->router);
306 
307  case action_WRITE:
308  log_debug(ZONE, "write action on fd %d", fd->fd);
309  return sx_can_write(s2s->router);
310 
311  case action_CLOSE:
312  log_debug(ZONE, "close action on fd %d", fd->fd);
313  log_write(s2s->log, LOG_NOTICE, "connection to router closed");
314 
315  s2s_lost_router = 1;
316 
317  /* we're offline */
318  s2s->online = 0;
319 
320  break;
321 
322  case action_ACCEPT:
323  break;
324  }
325 
326  return 0;
327 }