From 7636505962a348d9564e53922834dc6df1274653 Mon Sep 17 00:00:00 2001 From: Linus Nordberg Date: Sun, 6 Mar 2011 14:46:57 +0100 Subject: UDP w/o bufferevents, part 1. Sending, no retransmitting and no receiving. --- lib/conn.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) (limited to 'lib/conn.c') diff --git a/lib/conn.c b/lib/conn.c index 904596b..48d2fe5 100644 --- a/lib/conn.c +++ b/lib/conn.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include @@ -126,25 +127,22 @@ rs_conn_destroy (struct rs_connection *conn) assert (conn); - if (conn->is_connected) - { - err = rs_conn_disconnect (conn); - if (err) - return err; - } - /* NOTE: conn->realm is owned by context. */ /* NOTE: conn->peers is owned by context. */ + if (conn->is_connected) + err = rs_conn_disconnect (conn); if (conn->tev) event_free (conn->tev); + if (conn->bev) + bufferevent_free (conn->bev); if (conn->evb) event_base_free (conn->evb); /* TODO: free tls_ctx */ /* TODO: free tls_ssl */ - return 0; + return err; } int -- cgit v1.1 From 5c60297a1eaab7b10d6f584ba329493a41b812d0 Mon Sep 17 00:00:00 2001 From: Linus Nordberg Date: Sun, 6 Mar 2011 15:53:58 +0100 Subject: Restructure code, moving most code out of packet.c Also, move copyright notice out of COPYING and into every file. --- lib/conn.c | 93 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 92 insertions(+), 1 deletion(-) (limited to 'lib/conn.c') diff --git a/lib/conn.c b/lib/conn.c index 48d2fe5..14693ae 100644 --- a/lib/conn.c +++ b/lib/conn.c @@ -1,4 +1,5 @@ -/* See the file COPYING for licensing information. */ +/* Copyright 2010, 2011 NORDUnet A/S. All rights reserved. + See the file COPYING for licensing information. */ #if defined HAVE_CONFIG_H #include @@ -11,6 +12,8 @@ #include #include #include +#include "event.h" +#include "tcp.h" int rs_conn_create (struct rs_context *ctx, struct rs_connection **conn, @@ -193,3 +196,91 @@ int rs_conn_fd (struct rs_connection *conn) assert (conn->active_peer); return conn->fd; } + +static void +_rcb (struct rs_packet *packet, void *user_data) +{ + struct rs_packet *pkt = (struct rs_packet *) user_data; + assert (pkt); + pkt->valid_flag = 1; + if (pkt->conn->bev) + bufferevent_disable (pkt->conn->bev, EV_WRITE|EV_READ); + else + event_del (pkt->conn->rev); +} + +/* Special function used in libradsec blocking dispatching mode, + i.e. with socket set to block on read/write and with no libradsec + callbacks registered. + + For any other use of libradsec, a the received_cb callback should + be registered in the callbacks member of struct rs_connection. + + On successful reception, verification and decoding of a RADIUS + message, PKT_OUT will upon return point at a pointer to a struct + rs_packet containing the message. + + If anything goes wrong or if the read times out (TODO: explain), + PKT_OUT will point at the NULL pointer and one or more errors are + pushed on the connection (available through rs_err_conn_pop()). */ + +int +rs_conn_receive_packet (struct rs_connection *conn, + struct rs_packet *request, + struct rs_packet **pkt_out) +{ + int err = 0; + struct rs_packet *pkt = NULL; + + assert (conn); + assert (conn->realm); + assert (!conn->user_dispatch_flag); /* Dispatching mode only. */ + + if (rs_packet_create (conn, pkt_out)) + return -1; + pkt = *pkt_out; + pkt->conn = conn; + pkt->original = request; + + assert (conn->evb); + assert (conn->bev); + assert (conn->active_peer); + assert (conn->fd >= 0); + + conn->callbacks.received_cb = _rcb; + conn->user_data = pkt; + if (conn->bev) + { + bufferevent_setwatermark (conn->bev, EV_READ, RS_HEADER_LEN, 0); + bufferevent_setcb (conn->bev, tcp_read_cb, NULL, tcp_event_cb, pkt); + bufferevent_enable (conn->bev, EV_READ); + } + else + { + err = event_add (conn->rev, NULL); + if (err < 0) + return rs_err_conn_push_fl (pkt->conn, RSE_EVENT, __FILE__, __LINE__, + "event_add: %s", + evutil_gai_strerror (err)); + } + + /* Dispatch. */ + rs_debug (("%s: entering event loop\n", __func__)); + err = event_base_dispatch (conn->evb); + conn->callbacks.received_cb = NULL; + if (err < 0) + return rs_err_conn_push_fl (pkt->conn, RSE_EVENT, __FILE__, __LINE__, + "event_base_dispatch: %s", + evutil_gai_strerror (err)); + rs_debug (("%s: event loop done\n", __func__)); + + if (!pkt->valid_flag) + return -1; + +#if defined (DEBUG) + rs_dump_packet (pkt); +#endif + + pkt->original = NULL; /* FIXME: Why? */ + return RSE_OK; +} -- cgit v1.1 From cbcaa6a7c8f8a6704f6b4a68f260020957214a07 Mon Sep 17 00:00:00 2001 From: Linus Nordberg Date: Mon, 7 Mar 2011 15:23:40 +0100 Subject: Move verification of response packets up to a level where it makes sense. Replace the user_dispatch_flag on connections with conn_user_dispatch_p(). Remove the 'original' member from packet and instead have an upper layer verify. Rename packet valid_flag --> received_flag to reflect that we don't verify. Move _close_conn() --> conn_close(). Move packet flags into a single unsigned int, for portability. (_read_packet): Don't verify packet. (rs_conn_receive_packet): Don't touch PKT_OUT if there isn't a packet. (rs_conn_receive_packet): Verify packet using packet_verify_response(). --- lib/conn.c | 73 +++++++++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 51 insertions(+), 22 deletions(-) (limited to 'lib/conn.c') diff --git a/lib/conn.c b/lib/conn.c index 14693ae..028302c 100644 --- a/lib/conn.c +++ b/lib/conn.c @@ -12,10 +12,35 @@ #include #include #include +#include "conn.h" #include "event.h" +#include "packet.h" #include "tcp.h" int +conn_close (struct rs_connection **connp) +{ + int r; + assert (connp); + assert (*connp); + r = rs_conn_destroy (*connp); + if (!r) + *connp = NULL; + return r; +} + +int +conn_user_dispatch_p (const struct rs_connection *conn) +{ + assert (conn); + + return (conn->callbacks.connected_cb || + conn->callbacks.disconnected_cb || + conn->callbacks.received_cb || + conn->callbacks.sent_cb); +} + +int rs_conn_create (struct rs_context *ctx, struct rs_connection **conn, const char *config) { @@ -158,7 +183,6 @@ void rs_conn_set_callbacks (struct rs_connection *conn, struct rs_conn_callbacks *cb) { assert (conn); - conn->user_dispatch_flag = 1; memcpy (&conn->callbacks, cb, sizeof (conn->callbacks)); } @@ -166,7 +190,6 @@ void rs_conn_del_callbacks (struct rs_connection *conn) { assert (conn); - conn->user_dispatch_flag = 0; memset (&conn->callbacks, 0, sizeof (conn->callbacks)); } @@ -202,7 +225,9 @@ _rcb (struct rs_packet *packet, void *user_data) { struct rs_packet *pkt = (struct rs_packet *) user_data; assert (pkt); - pkt->valid_flag = 1; + assert (pkt->conn); + + pkt->flags |= rs_packet_received_flag; if (pkt->conn->bev) bufferevent_disable (pkt->conn->bev, EV_WRITE|EV_READ); else @@ -216,17 +241,18 @@ _rcb (struct rs_packet *packet, void *user_data) For any other use of libradsec, a the received_cb callback should be registered in the callbacks member of struct rs_connection. - On successful reception, verification and decoding of a RADIUS - message, PKT_OUT will upon return point at a pointer to a struct - rs_packet containing the message. + On successful reception of a RADIUS message it will be verified + against REQ_MSG, if !NULL. - If anything goes wrong or if the read times out (TODO: explain), - PKT_OUT will point at the NULL pointer and one or more errors are - pushed on the connection (available through rs_err_conn_pop()). */ + If PKT_OUT is !NULL it will upon return point at a pointer to a + struct rs_packet containing the message. + If anything goes wrong or if the read times out (TODO: explain), + PKT_OUT will not be changed and one or more errors are pushed on + the connection (available through rs_err_conn_pop()). */ int rs_conn_receive_packet (struct rs_connection *conn, - struct rs_packet *request, + struct rs_packet *req_msg, struct rs_packet **pkt_out) { int err = 0; @@ -234,13 +260,11 @@ rs_conn_receive_packet (struct rs_connection *conn, assert (conn); assert (conn->realm); - assert (!conn->user_dispatch_flag); /* Dispatching mode only. */ + assert (!conn_user_dispatch_p (conn)); /* Dispatching mode only. */ - if (rs_packet_create (conn, pkt_out)) + if (rs_packet_create (conn, &pkt)) return -1; - pkt = *pkt_out; pkt->conn = conn; - pkt->original = request; assert (conn->evb); assert (conn->bev); @@ -249,6 +273,8 @@ rs_conn_receive_packet (struct rs_connection *conn, conn->callbacks.received_cb = _rcb; conn->user_data = pkt; + pkt->flags &= ~rs_packet_received_flag; + if (conn->bev) { bufferevent_setwatermark (conn->bev, EV_READ, RS_HEADER_LEN, 0); @@ -264,7 +290,7 @@ rs_conn_receive_packet (struct rs_connection *conn, evutil_gai_strerror (err)); } - /* Dispatch. */ + rs_debug (("%s: entering event loop\n", __func__)); err = event_base_dispatch (conn->evb); conn->callbacks.received_cb = NULL; @@ -274,13 +300,16 @@ rs_conn_receive_packet (struct rs_connection *conn, evutil_gai_strerror (err)); rs_debug (("%s: event loop done\n", __func__)); - if (!pkt->valid_flag) - return -1; - -#if defined (DEBUG) - rs_dump_packet (pkt); -#endif + if ((pkt->flags & rs_packet_received_flag) == 0 + || (req_msg + && packet_verify_response (pkt->conn, pkt, req_msg) != RSE_OK)) + { + assert (rs_err_conn_peek_code (pkt->conn)); + return -1; + } - pkt->original = NULL; /* FIXME: Why? */ + if (pkt_out) + *pkt_out = pkt; return RSE_OK; } + -- cgit v1.1 From 1073de4a6139cf1b78ed82bc93e26be385cb76b1 Mon Sep 17 00:00:00 2001 From: Linus Nordberg Date: Tue, 8 Mar 2011 13:20:20 +0100 Subject: Don't return -1 to user but rather an error code. NOTE: Changes rs_conn_receive_packet() and rs_packet_send() only. --- lib/conn.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/conn.c') diff --git a/lib/conn.c b/lib/conn.c index 028302c..feed856 100644 --- a/lib/conn.c +++ b/lib/conn.c @@ -305,7 +305,7 @@ rs_conn_receive_packet (struct rs_connection *conn, && packet_verify_response (pkt->conn, pkt, req_msg) != RSE_OK)) { assert (rs_err_conn_peek_code (pkt->conn)); - return -1; + return rs_err_conn_peek_code (conn); } if (pkt_out) -- cgit v1.1 From d464ebb9235fe78e6588e95d4d3333d5ee95ca48 Mon Sep 17 00:00:00 2001 From: Linus Nordberg Date: Tue, 8 Mar 2011 13:37:46 +0100 Subject: Timeout implemented in request objects, supported by TCP. TODO: UDP. --- lib/conn.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'lib/conn.c') diff --git a/lib/conn.c b/lib/conn.c index feed856..0786de2 100644 --- a/lib/conn.c +++ b/lib/conn.c @@ -64,6 +64,7 @@ rs_conn_create (struct rs_context *ctx, struct rs_connection **conn, c->peers = r->peers; /* FIXME: Copy instead? */ for (p = c->peers; p; p = p->next) p->conn = c; + c->timeout.tv_sec = r->timeout; c->tryagain = r->retries; } else @@ -313,3 +314,10 @@ rs_conn_receive_packet (struct rs_connection *conn, return RSE_OK; } +void +rs_conn_set_timeout(struct rs_connection *conn, struct timeval *tv) +{ + assert (conn); + assert (tv); + conn->timeout = *tv; +} -- cgit v1.1 From fac0219dad91c574417f78ec674aa0dd10949e15 Mon Sep 17 00:00:00 2001 From: Linus Nordberg Date: Wed, 9 Mar 2011 10:14:20 +0100 Subject: Rename and move around a few helper functions. --- lib/conn.c | 41 +---------------------------------------- 1 file changed, 1 insertion(+), 40 deletions(-) (limited to 'lib/conn.c') diff --git a/lib/conn.c b/lib/conn.c index 0786de2..85cd7d5 100644 --- a/lib/conn.c +++ b/lib/conn.c @@ -7,11 +7,11 @@ #include #include -#include #include #include #include #include +#include "debug.h" #include "conn.h" #include "event.h" #include "packet.h" @@ -90,45 +90,6 @@ rs_conn_set_type (struct rs_connection *conn, rs_conn_type_t type) conn->realm->type = type; } - -struct rs_error * /* FIXME: Return int as all the others? */ -_rs_resolv (struct evutil_addrinfo **addr, rs_conn_type_t type, - const char *hostname, const char *service) -{ - int err; - struct evutil_addrinfo hints, *res = NULL; - - memset (&hints, 0, sizeof(struct evutil_addrinfo)); - hints.ai_family = AF_INET; /* IPv4 only. TODO: Set AF_UNSPEC. */ - hints.ai_flags = AI_ADDRCONFIG; - switch (type) - { - case RS_CONN_TYPE_NONE: - return _rs_err_create (RSE_INVALID_CONN, __FILE__, __LINE__, NULL, NULL); - case RS_CONN_TYPE_TCP: - /* Fall through. */ - case RS_CONN_TYPE_TLS: - hints.ai_socktype = SOCK_STREAM; - hints.ai_protocol = IPPROTO_TCP; - break; - case RS_CONN_TYPE_UDP: - /* Fall through. */ - case RS_CONN_TYPE_DTLS: - hints.ai_socktype = SOCK_DGRAM; - hints.ai_protocol = IPPROTO_UDP; - break; - default: - return _rs_err_create (RSE_INVALID_CONN, __FILE__, __LINE__, NULL, NULL); - } - err = evutil_getaddrinfo (hostname, service, &hints, &res); - if (err) - return _rs_err_create (RSE_BADADDR, __FILE__, __LINE__, - "%s:%s: bad host name or service name (%s)", - hostname, service, evutil_gai_strerror(err)); - *addr = res; /* Simply use first result. */ - return NULL; -} - int rs_conn_add_listener (struct rs_connection *conn, rs_conn_type_t type, const char *hostname, int port) -- cgit v1.1 From ce4d6dfe1728e5633a8f49fc4b16c36df0d23521 Mon Sep 17 00:00:00 2001 From: Linus Nordberg Date: Wed, 9 Mar 2011 10:18:06 +0100 Subject: Add retransmission timer support (UDP). --- lib/conn.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'lib/conn.c') diff --git a/lib/conn.c b/lib/conn.c index 85cd7d5..3981f6a 100644 --- a/lib/conn.c +++ b/lib/conn.c @@ -282,3 +282,20 @@ rs_conn_set_timeout(struct rs_connection *conn, struct timeval *tv) assert (tv); conn->timeout = *tv; } + +int +conn_activate_timeout (struct rs_connection *conn) +{ + assert (conn); + assert (conn->tev); + assert (conn->evb); + if (conn->timeout.tv_sec || conn->timeout.tv_usec) + { + rs_debug (("%s: activating timer: %d.%d\n", __func__, + conn->timeout.tv_sec, conn->timeout.tv_usec)); + if (evtimer_add (conn->tev, &conn->timeout)) + return rs_err_conn_push_fl (conn, RSE_EVENT, __FILE__, __LINE__, + "evtimer_add: %d", errno); + } + return RSE_OK; +} -- cgit v1.1 From f9bc41973f176e8bb4fb3f27b2a7f24247a56d28 Mon Sep 17 00:00:00 2001 From: Linus Nordberg Date: Wed, 9 Mar 2011 13:12:20 +0100 Subject: Remove superfluous assignment. This is done in rs_packet_create(). --- lib/conn.c | 1 - 1 file changed, 1 deletion(-) (limited to 'lib/conn.c') diff --git a/lib/conn.c b/lib/conn.c index 3981f6a..8d369ab 100644 --- a/lib/conn.c +++ b/lib/conn.c @@ -226,7 +226,6 @@ rs_conn_receive_packet (struct rs_connection *conn, if (rs_packet_create (conn, &pkt)) return -1; - pkt->conn = conn; assert (conn->evb); assert (conn->bev); -- cgit v1.1 From 0a7d803b9aa40512cf0f0c574d397ccba3ff1d13 Mon Sep 17 00:00:00 2001 From: Linus Nordberg Date: Wed, 9 Mar 2011 23:09:26 +0100 Subject: Get UDP working. For UDP, activate retransmit timer before receiving rather than sending makes the event loop break nicely after sending a message (which is important for blocking mode). Not quite sure that this is really accurate wrt to retransmission timing though but it should do for now. For UDP, set the user_data member for the read callback in rs_conn_receive_packet -- the one from udp_init() doesn't do much good now. For UDP, implement receiving message. Add compat_recv(). --- lib/conn.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'lib/conn.c') diff --git a/lib/conn.c b/lib/conn.c index 8d369ab..5382888 100644 --- a/lib/conn.c +++ b/lib/conn.c @@ -228,29 +228,33 @@ rs_conn_receive_packet (struct rs_connection *conn, return -1; assert (conn->evb); - assert (conn->bev); - assert (conn->active_peer); assert (conn->fd >= 0); conn->callbacks.received_cb = _rcb; conn->user_data = pkt; pkt->flags &= ~rs_packet_received_flag; - if (conn->bev) + if (conn->bev) /* TCP. */ { bufferevent_setwatermark (conn->bev, EV_READ, RS_HEADER_LEN, 0); bufferevent_setcb (conn->bev, tcp_read_cb, NULL, tcp_event_cb, pkt); bufferevent_enable (conn->bev, EV_READ); } - else + else /* UDP. */ { + /* Put fresh packet in user_data for the callback and enable the + read event. */ + event_assign (conn->rev, conn->evb, event_get_fd (conn->rev), + EV_READ, event_get_callback (conn->rev), pkt); err = event_add (conn->rev, NULL); if (err < 0) return rs_err_conn_push_fl (pkt->conn, RSE_EVENT, __FILE__, __LINE__, "event_add: %s", evutil_gai_strerror (err)); - } + /* Activae retransmission timer. */ + conn_activate_timeout (pkt->conn); + } rs_debug (("%s: entering event loop\n", __func__)); err = event_base_dispatch (conn->evb); -- cgit v1.1 From 2913a6b0f4fc5d097843d8c80786b8c313fb9d30 Mon Sep 17 00:00:00 2001 From: Linus Nordberg Date: Fri, 11 Mar 2011 13:19:01 +0100 Subject: Do free the connection object. --- lib/conn.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'lib/conn.c') diff --git a/lib/conn.c b/lib/conn.c index 5382888..f737820 100644 --- a/lib/conn.c +++ b/lib/conn.c @@ -132,6 +132,8 @@ rs_conn_destroy (struct rs_connection *conn) /* TODO: free tls_ctx */ /* TODO: free tls_ssl */ + rs_free (conn->ctx, conn); + return err; } -- cgit v1.1