1 /* Copyright 2011,2013 NORDUnet A/S. All rights reserved.
2 See LICENSE for licensing information. */
4 #if defined HAVE_CONFIG_H
9 #include <event2/event.h>
10 #include <event2/bufferevent.h>
11 #if defined (RS_ENABLE_TLS)
12 #include <event2/bufferevent_ssl.h>
13 #include <openssl/err.h>
15 #include <radius/client.h>
16 #include <radsec/radsec.h>
17 #include <radsec/radsec-impl.h>
25 #include <event2/buffer.h>
28 /** Read one RADIUS message header. Return !0 on error. */
30 _read_header (struct rs_message *msg)
34 n = bufferevent_read (TO_BASE_CONN(msg->conn)->bev, msg->hdr, RS_HEADER_LEN);
35 if (n == RS_HEADER_LEN)
37 msg->flags |= RS_MESSAGE_HEADER_READ;
38 msg->rpkt->length = (msg->hdr[2] << 8) + msg->hdr[3];
39 if (msg->rpkt->length < 20 || msg->rpkt->length > RS_MAX_PACKET_LEN)
40 return rs_err_conn_push (msg->conn, RSE_INVALID_MSG,
41 "invalid message length: %d",
43 memcpy (msg->rpkt->data, msg->hdr, RS_HEADER_LEN);
44 bufferevent_setwatermark (TO_BASE_CONN(msg->conn)->bev, EV_READ,
45 msg->rpkt->length - RS_HEADER_LEN, 0);
46 rs_debug (("%s: message header read, total msg len=%d\n",
47 __func__, msg->rpkt->length));
50 rs_debug (("%s: buffer frozen while reading header\n", __func__));
51 else /* Error: libevent gave us less than the low watermark. */
52 return rs_err_conn_push_fl (msg->conn, RSE_INTERNAL, __FILE__, __LINE__,
53 "got %d octets reading header", n);
57 /** Read a message, check that it's valid RADIUS and hand it off to
58 registered user callback.
60 The message is read from the bufferevent associated with \a msg and
61 the data is stored in \a msg->rpkt.
63 Return 0 on success and !0 on failure. */
65 _read_message (struct rs_message *msg)
70 rs_debug (("%s: trying to read %d octets of message data\n", __func__,
71 msg->rpkt->length - RS_HEADER_LEN));
73 n = bufferevent_read (msg->conn->base_.bev,
74 msg->rpkt->data + RS_HEADER_LEN,
75 msg->rpkt->length - RS_HEADER_LEN);
77 rs_debug (("%s: read %ld octets of message data\n", __func__, n));
79 if (n == msg->rpkt->length - RS_HEADER_LEN)
81 bufferevent_disable (msg->conn->base_.bev, EV_READ);
82 rs_debug (("%s: complete message read\n", __func__));
83 msg->flags &= ~RS_MESSAGE_HEADER_READ;
84 memset (msg->hdr, 0, sizeof(*msg->hdr));
86 /* Checks done by nr_packet_ok:
87 - lenghts (FIXME: checks really ok for tcp?)
89 - attribute lengths >= 2
90 - attribute sizes adding up correctly */
91 err = nr_packet_ok (msg->rpkt);
93 return rs_err_conn_push_fl (msg->conn, err, __FILE__, __LINE__,
97 /* Find out what happens if there's data left in the buffer. */
101 evbuffer_get_length (bufferevent_get_input (msg->conn->base_.bev));
103 rs_debug (("%s: returning with %d octets left in buffer\n", __func__,
108 /* Hand over message to user. This changes ownership of msg.
109 Don't touch it afterwards -- it might have been freed. */
110 if (msg->conn->callbacks.received_cb)
111 msg->conn->callbacks.received_cb (msg, msg->conn->base_.user_data);
113 else if (n < 0) /* Buffer frozen. */
114 rs_debug (("%s: buffer frozen when reading message\n", __func__));
115 else /* Short message. */
116 rs_debug (("%s: waiting for another %d octets\n", __func__,
117 msg->rpkt->length - RS_HEADER_LEN - n));
122 /* The read callback for TCP.
124 Read exactly one RADIUS message from \a bev and store it in the
125 struct rs_message passed in \a user_data.
127 Inform upper layer about successful reception of received RADIUS
128 message by invoking conn->callbacks.recevied_cb(), if not NULL. */
130 tcp_read_cb (struct bufferevent *bev, void *user_data)
132 struct rs_message *msg = (struct rs_message *) user_data;
138 msg->rpkt->sockfd = msg->conn->base_.fd;
139 msg->rpkt->vps = NULL; /* FIXME: can this be done when initializing msg? */
141 /* Read a message header if not already read, return if that
142 fails. Read a message and have it dispatched to the user
145 Room for improvement: Peek inside buffer (evbuffer_copyout()) to
146 avoid the extra copying. */
147 if ((msg->flags & RS_MESSAGE_HEADER_READ) == 0)
148 if (_read_header (msg))
149 return; /* Invalid header. */
150 if (_read_message (msg))
151 return; /* Invalid message. */
155 tcp_event_cb (struct bufferevent *bev, short events, void *user_data)
157 struct rs_message *msg = (struct rs_message *) user_data;
158 struct rs_connection *conn = NULL;
160 #if defined (RS_ENABLE_TLS)
161 unsigned long tlserr = 0;
164 struct rs_peer *p = NULL;
171 assert (conn->active_peer);
172 p = conn->active_peer;
175 if (events & BEV_EVENT_CONNECTED)
179 if (conn_originating_p (conn)) /* We're a client. */
183 evtimer_del (conn->tev); /* Cancel connect timer. */
184 err = event_on_connect_orig (conn, msg);
186 else /* We're a server. */
188 assert (conn->tev == NULL);
189 err = event_on_connect_term (conn, msg);
193 event_on_disconnect (conn);
194 event_loopbreak (conn);
197 else if (events & BEV_EVENT_EOF)
199 event_on_disconnect (conn);
201 else if (events & BEV_EVENT_TIMEOUT)
203 rs_debug (("%s: %p times out on %s\n", __func__, p,
204 (events & BEV_EVENT_READING) ? "read" : "write"));
205 rs_err_conn_push_fl (conn, RSE_TIMEOUT_IO, __FILE__, __LINE__, NULL);
207 else if (events & BEV_EVENT_ERROR)
209 sockerr = evutil_socket_geterror (conn->active_peer->fd);
210 if (sockerr == 0) /* FIXME: True that errno == 0 means closed? */
212 event_on_disconnect (conn);
213 rs_err_conn_push_fl (conn, RSE_DISCO, __FILE__, __LINE__, NULL);
217 rs_debug (("%s: %d: %d (%s)\n", __func__, conn->base_.fd, sockerr,
218 evutil_socket_error_to_string (sockerr)));
219 rs_err_conn_push_fl (conn, RSE_SOCKERR, __FILE__, __LINE__,
220 "%d: %d (%s)", conn->base_.fd, sockerr,
221 evutil_socket_error_to_string (sockerr));
223 #if defined (RS_ENABLE_TLS)
224 if (conn->tls_ssl) /* FIXME: correct check? */
226 for (tlserr = bufferevent_get_openssl_error (conn->base_.bev);
228 tlserr = bufferevent_get_openssl_error (conn->base_.bev))
230 rs_debug (("%s: openssl error: %s\n", __func__,
231 ERR_error_string (tlserr, NULL)));
232 rs_err_conn_push_fl (conn, RSE_SSLERR, __FILE__, __LINE__,
233 ERR_error_string (tlserr, NULL));
236 #endif /* RS_ENABLE_TLS */
237 event_loopbreak (conn);
241 if (events & BEV_EVENT_ERROR && events != BEV_EVENT_ERROR)
242 rs_debug (("%s: BEV_EVENT_ERROR and more: 0x%x\n", __func__, events));
247 tcp_write_cb (struct bufferevent *bev, void *ctx)
249 struct rs_message *msg = (struct rs_message *) ctx;
254 if (msg->conn->callbacks.sent_cb)
255 msg->conn->callbacks.sent_cb (msg->conn->base_.user_data);
259 tcp_init_connect_timer (struct rs_connection *conn)
262 assert (conn->base_.ctx);
265 event_free (conn->tev);
266 conn->tev = evtimer_new (conn->base_.ctx->evb, event_conn_timeout_cb, conn);
268 return rs_err_conn_push_fl (conn, RSE_EVENT, __FILE__, __LINE__,