diff options
author | Martin Willi <martin@revosec.ch> | 2012-01-30 19:15:20 +0100 |
---|---|---|
committer | Martin Willi <martin@revosec.ch> | 2012-01-30 19:15:20 +0100 |
commit | 8e5b4aa023accbf7b3406050b3b7175b9bd0b6b7 (patch) | |
tree | 761167fec5fc8860bb7029dbdfacd933a3123770 /src/libcharon/plugins/eap_radius/radius_socket.c | |
parent | a69aff5f17d25f606e89e9a91410019e3d376afd (diff) | |
download | strongswan-8e5b4aa023accbf7b3406050b3b7175b9bd0b6b7.tar.bz2 strongswan-8e5b4aa023accbf7b3406050b3b7175b9bd0b6b7.tar.xz |
Open RADIUS accounting sockets to exchange accounting messages
Diffstat (limited to 'src/libcharon/plugins/eap_radius/radius_socket.c')
-rw-r--r-- | src/libcharon/plugins/eap_radius/radius_socket.c | 80 |
1 files changed, 54 insertions, 26 deletions
diff --git a/src/libcharon/plugins/eap_radius/radius_socket.c b/src/libcharon/plugins/eap_radius/radius_socket.c index 46513ee57..56b65fea8 100644 --- a/src/libcharon/plugins/eap_radius/radius_socket.c +++ b/src/libcharon/plugins/eap_radius/radius_socket.c @@ -44,19 +44,29 @@ struct private_radius_socket_t { radius_socket_t public; /** - * socket file descriptor + * Server port for authentication */ - int fd; + u_int16_t auth_port; /** - * Server address + * socket file descriptor for authentication */ - char *address; + int auth_fd; /** - * Server port + * Server port for accounting */ - u_int16_t port; + u_int16_t acct_port; + + /** + * socket file descriptor for accounting + */ + int acct_fd; + + /** + * Server address + */ + char *address; /** * current RADIUS identifier @@ -87,35 +97,36 @@ struct private_radius_socket_t { /** * Check or establish RADIUS connection */ -static bool check_connection(private_radius_socket_t *this) +static bool check_connection(private_radius_socket_t *this, + int *fd, u_int16_t port) { - if (this->fd == -1) + if (*fd == -1) { host_t *server; - server = host_create_from_dns(this->address, AF_UNSPEC, this->port); + server = host_create_from_dns(this->address, AF_UNSPEC, port); if (!server) { DBG1(DBG_CFG, "resolving RADIUS server address '%s' failed", this->address); return FALSE; } - this->fd = socket(server->get_family(server), SOCK_DGRAM, IPPROTO_UDP); - if (this->fd == -1) + *fd = socket(server->get_family(server), SOCK_DGRAM, IPPROTO_UDP); + if (*fd == -1) { DBG1(DBG_CFG, "opening RADIUS socket for %#H failed: %s", server, strerror(errno)); server->destroy(server); return FALSE; } - if (connect(this->fd, server->get_sockaddr(server), + if (connect(*fd, server->get_sockaddr(server), *server->get_sockaddr_len(server)) < 0) { DBG1(DBG_CFG, "connecting RADIUS socket to %#H failed: %s", server, strerror(errno)); server->destroy(server); - close(this->fd); - this->fd = -1; + close(*fd); + *fd = -1; return FALSE; } server->destroy(server); @@ -127,14 +138,25 @@ METHOD(radius_socket_t, request, radius_message_t*, private_radius_socket_t *this, radius_message_t *request) { chunk_t data; - int i; + int i, *fd; + u_int16_t port; /* set Message Identifier */ request->set_identifier(request, this->identifier++); /* sign the request */ request->sign(request, this->rng, this->signer, this->hasher, this->secret); - if (!check_connection(this)) + if (request->get_code(request) == RMC_ACCOUNTING_REQUEST) + { + fd = &this->acct_fd; + port = this->acct_port; + } + else + { + fd = &this->auth_fd; + port = this->auth_port; + } + if (!check_connection(this, fd, port)) { return NULL; } @@ -150,7 +172,7 @@ METHOD(radius_socket_t, request, radius_message_t*, fd_set fds; int res; - if (send(this->fd, data.ptr, data.len, 0) != data.len) + if (send(*fd, data.ptr, data.len, 0) != data.len) { DBG1(DBG_CFG, "sending RADIUS message failed: %s", strerror(errno)); return NULL; @@ -161,8 +183,8 @@ METHOD(radius_socket_t, request, radius_message_t*, while (TRUE) { FD_ZERO(&fds); - FD_SET(this->fd, &fds); - res = select(this->fd + 1, &fds, NULL, NULL, &tv); + FD_SET(*fd, &fds); + res = select((*fd) + 1, &fds, NULL, NULL, &tv); /* TODO: updated tv to time not waited. Linux does this for us. */ if (res < 0) { /* failed */ @@ -176,7 +198,7 @@ METHOD(radius_socket_t, request, radius_message_t*, retransmit = TRUE; break; } - res = recv(this->fd, buf, sizeof(buf), MSG_DONTWAIT); + res = recv(*fd, buf, sizeof(buf), MSG_DONTWAIT); if (res <= 0) { DBG1(DBG_CFG, "receiving RADIUS message failed: %s", @@ -311,9 +333,13 @@ METHOD(radius_socket_t, destroy, void, DESTROY_IF(this->hasher); DESTROY_IF(this->signer); DESTROY_IF(this->rng); - if (this->fd != -1) + if (this->auth_fd != -1) + { + close(this->auth_fd); + }; + if (this->acct_fd != -1) { - close(this->fd); + close(this->acct_fd); } free(this); } @@ -321,8 +347,8 @@ METHOD(radius_socket_t, destroy, void, /** * See header */ -radius_socket_t *radius_socket_create(char *address, u_int16_t port, - chunk_t secret) +radius_socket_t *radius_socket_create(char *address, u_int16_t auth_port, + u_int16_t acct_port, chunk_t secret) { private_radius_socket_t *this; @@ -333,8 +359,10 @@ radius_socket_t *radius_socket_create(char *address, u_int16_t port, .destroy = _destroy, }, .address = address, - .port = port, - .fd = -1, + .auth_port = auth_port, + .auth_fd = -1, + .acct_port = acct_port, + .acct_fd = -1, ); this->hasher = lib->crypto->create_hasher(lib->crypto, HASH_MD5); |