#include <threading/rwlock.h>
/**
- * Default RADIUS server port, when not configured
+ * Default RADIUS server port for authentication
*/
-#define RADIUS_PORT 1812
+#define AUTH_PORT 1812
+
+/**
+ * Default RADIUS server port for accounting
+ */
+#define ACCT_PORT 1813
typedef struct private_eap_radius_plugin_t private_eap_radius_plugin_t;
enumerator_t *enumerator;
radius_server_t *server;
char *nas_identifier, *secret, *address, *section;
- int port, sockets, preference;
+ int auth_port, acct_port, sockets, preference;
address = lib->settings->get_str(lib->settings,
"charon.plugins.eap-radius.server", NULL);
}
nas_identifier = lib->settings->get_str(lib->settings,
"charon.plugins.eap-radius.nas_identifier", "strongSwan");
- port = lib->settings->get_int(lib->settings,
- "charon.plugins.eap-radius.port", RADIUS_PORT);
+ auth_port = lib->settings->get_int(lib->settings,
+ "charon.plugins.eap-radius.port", AUTH_PORT);
sockets = lib->settings->get_int(lib->settings,
"charon.plugins.eap-radius.sockets", 1);
- server = radius_server_create(address, address, port, nas_identifier,
- secret, sockets, 0);
+ server = radius_server_create(address, address, auth_port, ACCT_PORT,
+ nas_identifier, secret, sockets, 0);
if (!server)
{
DBG1(DBG_CFG, "no RADUIS server defined");
nas_identifier = lib->settings->get_str(lib->settings,
"charon.plugins.eap-radius.servers.%s.nas_identifier",
"strongSwan", section);
- port = lib->settings->get_int(lib->settings,
- "charon.plugins.eap-radius.servers.%s.port", RADIUS_PORT, section);
+ auth_port = lib->settings->get_int(lib->settings,
+ "charon.plugins.eap-radius.servers.%s.auth_port",
+ lib->settings->get_int(lib->settings,
+ "charon.plugins.eap-radius.servers.%s.port",
+ AUTH_PORT, section),
+ section);
+ acct_port = lib->settings->get_int(lib->settings,
+ "charon.plugins.eap-radius.servers.%s.acct_port", ACCT_PORT, section);
sockets = lib->settings->get_int(lib->settings,
"charon.plugins.eap-radius.servers.%s.sockets", 1, section);
preference = lib->settings->get_int(lib->settings,
"charon.plugins.eap-radius.servers.%s.preference", 0, section);
- server = radius_server_create(section, address, port, nas_identifier,
- secret, sockets, preference);
+ server = radius_server_create(section, address, auth_port, acct_port,
+ nas_identifier, secret, sockets, preference);
if (!server)
{
DBG1(DBG_CFG, "loading RADIUS server '%s' failed, skipped", section);
/**
* See header
*/
-radius_server_t *radius_server_create(char *name, char *address, u_int16_t port,
- char *nas_identifier, char *secret, int sockets, int preference)
+radius_server_t *radius_server_create(char *name, char *address,
+ u_int16_t auth_port, u_int16_t acct_port,
+ char *nas_identifier, char *secret,
+ int sockets, int preference)
{
private_radius_server_t *this;
radius_socket_t *socket;
while (sockets--)
{
- socket = radius_socket_create(address, port,
+ socket = radius_socket_create(address, auth_port, acct_port,
chunk_create(secret, strlen(secret)));
if (!socket)
{
*
* @param name server name
* @param address server address
- * @param port server port
+ * @param auth_port server port for authentication
+ * @param acct_port server port for accounting
* @param nas_identifier NAS-Identifier to use with this server
* @param secret secret to use with this server
* @param sockets number of sockets to create in pool
* @param preference preference boost for this server
*/
-radius_server_t *radius_server_create(char *name, char *address, u_int16_t port,
- char *nas_identifier, char *secret, int sockets, int preference);
+radius_server_t *radius_server_create(char *name, char *address,
+ u_int16_t auth_port, u_int16_t acct_port,
+ char *nas_identifier, char *secret,
+ int sockets, int preference);
#endif /** RADIUS_SERVER_H_ @}*/
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
/**
* 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);
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;
}
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;
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 */
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",
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);
}
/**
* 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;
.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);
* Create a radius_socket instance.
*
* @param address server name
- * @param port server port
+ * @param auth_port server port for authentication
+ * @param acct_port server port for accounting
* @param secret RADIUS secret
*/
-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);
#endif /** RADIUS_SOCKET_H_ @}*/