# HG changeset patch # User Sebastien Decugis # Date 1245127066 -32400 # Node ID 540ed390c04f8ece89c70d7ab811b657118b81e8 # Parent c7ce13cb7d230b81a05e380ac0d57d99f6983c65 Added sess_destroy function diff -r c7ce13cb7d23 -r 540ed390c04f extensions/radius_gw/rg_api.h --- a/extensions/radius_gw/rg_api.h Mon Jun 15 15:00:10 2009 +0900 +++ b/extensions/radius_gw/rg_api.h Tue Jun 16 13:37:46 2009 +0900 @@ -49,19 +49,15 @@ void (*rga_conf_free_cb) (struct rga_conf_state * cs); /* Free an object returned by rga_conf_parse_cb */ /* handle an incoming RADIUS message */ - int (*rga_rad_req_cb) ( struct rga_conf_state * cs, sess_id_t ** session, struct radius_msg * rad_req, struct radius_msg ** rad_ans, msg_t ** diam_fw, void * cli ); + int (*rga_rad_req_cb) ( struct rga_conf_state * cs, sess_id_t * session, struct radius_msg * rad_req, struct radius_msg ** rad_ans, msg_t ** diam_fw, void * cli ); /* ret 0: continue; - ret -1: stop processing this message and destroy the session (or fallback if supported) - ret -2: stop processing this message and keep the session (or fallback if supported) - ret -3: reply the content of rad_ans to the RADIUS client immediatly and destroy the session - ret -4: reply the content of rad_ans to the RADIUS client immediatly and keep the session + ret -1: stop processing this message + ret -2: reply the content of rad_ans (created with rg_msg_create_ans) to the RADIUS client immediatly ret >0: critical error (errno), log and exit. - - for cases 3 and 4, the answer must be created with rg_msg_create_ans. */ /* handle the corresponding Diameter answer */ - int (*rga_diam_ans_cb) ( struct rga_conf_state * cs, sess_id_t ** session, msg_t ** diam_ans, struct radius_msg ** rad_fw, void * cli ); + int (*rga_diam_ans_cb) ( struct rga_conf_state * cs, sess_id_t * session, msg_t ** diam_ans, struct radius_msg ** rad_fw, void * cli ); /* ret 0: continue; ret >0: error; ret: -1 ... (tbd) */ }; diff -r c7ce13cb7d23 -r 540ed390c04f extensions/radius_gw/rgw_extensions.c --- a/extensions/radius_gw/rgw_extensions.c Mon Jun 15 15:00:10 2009 +0900 +++ b/extensions/radius_gw/rgw_extensions.c Tue Jun 16 13:37:46 2009 +0900 @@ -364,11 +364,11 @@ if (ext->api.rga_rad_req_cb) { TRACE_DEBUG(ANNOYING, "Calling next extension: %s", ext->extname); - ret = (*ext->api.rga_rad_req_cb)(ext->cs, session, &(*rad)->radius, &rad_ans, diam_msg, (void *)cli); + ret = (*ext->api.rga_rad_req_cb)(ext->cs, *session, &(*rad)->radius, &rad_ans, diam_msg, (void *)cli); if (ret) break; } else { - TRACE_DEBUG(ANNOYING, "Skipping next extension: %s (NULL callback)", ext->extname); + TRACE_DEBUG(ANNOYING, "Skipping extension '%s' (NULL callback)", ext->extname); } } @@ -382,14 +382,13 @@ *diam_msg = NULL; } - /* Destroy the session unless instructed to keep it */ - if (*session && (ret != -2) && (ret != -4)) { - CHECK_FCT_DO( sess_unlink(*session), ); - *session = NULL; + /* Destroy the session, there won't be a reply message to retrieve the data */ + if (*session) { + CHECK_FCT_DO( sess_destroy(session), ); } /* Send the radius message back if required */ - if (((ret == -3) || (ret == -4)) && rad_ans && rad) { + if ((ret == -2) && rad_ans && rad) { CHECK_FCT_DO( rgw_client_finish_send(&rad_ans, *rad, cli), /* It failed, it can't be helped... */); } diff -r c7ce13cb7d23 -r 540ed390c04f extensions/radius_gw/rgw_servers.c --- a/extensions/radius_gw/rgw_servers.c Mon Jun 15 15:00:10 2009 +0900 +++ b/extensions/radius_gw/rgw_servers.c Tue Jun 16 13:37:46 2009 +0900 @@ -254,14 +254,14 @@ } if (!ret) { - TRACE_DEBUG(INFO, "Trying to send a message with a disabled server: %s / %s", + TRACE_DEBUG(INFO, "Trying to send a message from a disabled server: %s / %s", (type == RGW_EXT_TYPE_AUTH) ? "Auth" : "Acct", (to->sa_family == AF_INET) ? "IPv4" : "IPv6"); return EINVAL; } /* Prepare the destination info */ - memset(&sto, 0, sizeof(to)); + memset(&sto, 0, sizeof(sto)); if (to->sa_family == AF_INET) { memcpy(&sto, to, sizeof(struct sockaddr_in)); ((struct sockaddr_in *)&sto)->sin_port = to_port; @@ -277,7 +277,7 @@ char portstr[8]; if (ret = getnameinfo((struct sockaddr *)&sto, sto_len, &ipstr[0], INET6_ADDRSTRLEN, &portstr[0], sizeof(portstr), NI_NUMERICHOST | NI_NUMERICSERV)) { - TRACE_DEBUG(FULL, "Sending %d bytes to unknown source: %s", buflen, gai_strerror(ret)); + TRACE_DEBUG(FULL, "Sending %d bytes to unknown destination: %s", buflen, gai_strerror(ret)); } else { TRACE_DEBUG(FULL, "Sending %d bytes to [%s]:%s", buflen, ipstr, portstr); } diff -r c7ce13cb7d23 -r 540ed390c04f extensions/radius_gw/rgw_work.c --- a/extensions/radius_gw/rgw_work.c Mon Jun 15 15:00:10 2009 +0900 +++ b/extensions/radius_gw/rgw_work.c Tue Jun 16 13:37:46 2009 +0900 @@ -67,9 +67,31 @@ struct pending_answer * pa = (struct pending_answer *)paback; TRACE_ENTRY("%p %p", pa, ans); + CHECK_PARAMS_DO( pa && ans, return ); TRACE_DEBUG(INFO, "Handling Diameter answer: Not implemented yet..."); + /* Create an empty RADIUS answer message */ + + + /* Pass the Diameter answer to the same extensions as the request */ + + + /* Now try and send the RADIUS answer */ + + +out: + /* Destroy remaining session data (stateless gateway) */ + CHECK_FCT_DO( sess_destroy(&pa->sess), ); + + /* Clear the Diameter message */ + CHECK_FCT_DO( msg_free(ans, 1), ); + + /* Clear the answer data */ + free(pa); + + /* Finished */ + return; } /* Worker thread, processing incoming RADIUS messages (after parsing) */ @@ -150,7 +172,8 @@ session = NULL; diam_msg = NULL; - /* Create the session and empty message with some common AVPs */ + + /* Create the session and an empty message with some common AVPs */ CHECK_FCT_DO( rgw_msg_create_base(msg, cli, &session, &diam_msg), { /* An error occurred, discard message */ @@ -203,7 +226,7 @@ if (pb) { /* Something went wrong during the conversion */ if (session) { - CHECK_FCT_DO( sess_unlink(&session), ); + CHECK_FCT_DO( sess_destroy(&session), ); } if (diam_msg) { @@ -230,8 +253,7 @@ /* If an error occurs, log and destroy the data */ log_error("An error occurred while sending Diameter message, please turn Debug on for detail.\n"); if (session) { - CHECK_FCT_DO( sess_unlink(session), ); - session = NULL; + CHECK_FCT_DO( sess_destroy(&session), ); } if (diam_msg) { diff -r c7ce13cb7d23 -r 540ed390c04f extensions/radius_gw/sub_acct.c --- a/extensions/radius_gw/sub_acct.c Mon Jun 15 15:00:10 2009 +0900 +++ b/extensions/radius_gw/sub_acct.c Tue Jun 16 13:37:46 2009 +0900 @@ -51,7 +51,6 @@ struct rga_conf_state { char * conffile; void * dl_handle; - int (*rgw_client_session_stop)(void * cli, sess_id_t * sess, int32_t reason); }; static struct rga_conf_state * acct_conf_parse(char * conffile) @@ -72,7 +71,6 @@ } CHECK_FCT_DO( rg_pointers_init(&cs->dl_handle), return NULL ); - rg_pointers_resolve(cs->rgw_client_session_stop, cs->dl_handle, "rgw_client_session_stop", NULL); return cs; } @@ -86,7 +84,7 @@ return; } -static int acct_rad_req(struct rga_conf_state * cs, sess_id_t ** session, struct radius_msg * rad_req, struct radius_msg ** rad_ans, msg_t ** diam_fw, void * cli ) +static int acct_rad_req(struct rga_conf_state * cs, sess_id_t * session, struct radius_msg * rad_req, struct radius_msg ** rad_ans, msg_t ** diam_fw, void * cli ) { int idx; int got_id = 0; @@ -113,19 +111,11 @@ return EINVAL; } - /* Handle the Accounting-On case: nothing to do, just reply OK, since Diameter does not support this */ - if (status_type == RADIUS_ACCT_STATUS_TYPE_ACCOUNTING_ON) { + /* Handle the Accounting-On/Off case: nothing to do, just reply OK, since Diameter does not support this */ + if ((status_type == RADIUS_ACCT_STATUS_TYPE_ACCOUNTING_ON) || (status_type == RADIUS_ACCT_STATUS_TYPE_ACCOUNTING_OFF)) { TRACE_DEBUG(FULL, "Received Accounting-On Acct-Status-Type attribute, replying directly."); CHECK_MALLOC( *rad_ans = radius_msg_new(RADIUS_CODE_ACCOUNTING_RESPONSE, rad_req->hdr->identifier) ); - return -3; - } - - /* Handle Accounting-Off case: terminate all registered sessions with this RADIUS client */ - if (status_type == RADIUS_ACCT_STATUS_TYPE_ACCOUNTING_OFF) { - TRACE_DEBUG(FULL, "Received Accounting-Off Acct-Status-Type attribute, replying directly and terminating all sessions."); - CHECK_MALLOC( *rad_ans = radius_msg_new(RADIUS_CODE_ACCOUNTING_RESPONSE, rad_req->hdr->identifier) ); - CHECK_FCT( (*cs->rgw_client_session_stop)(cli, NULL, 4 /* DIAMETER_ADMINISTRATIVE */) ); - return -3; + return -2; } /* @@ -155,7 +145,7 @@ return ENOTSUP; } -static int acct_diam_ans(struct rga_conf_state * cs, sess_id_t ** session, msg_t ** diam_ans, struct radius_msg ** rad_fw, void * cli ) +static int acct_diam_ans(struct rga_conf_state * cs, sess_id_t * session, msg_t ** diam_ans, struct radius_msg ** rad_fw, void * cli ) { TRACE_ENTRY("%p %p %p %p %p", cs, session, diam_ans, rad_fw, cli); CHECK_PARAMS(cs); diff -r c7ce13cb7d23 -r 540ed390c04f extensions/radius_gw/sub_auth.c --- a/extensions/radius_gw/sub_auth.c Mon Jun 15 15:00:10 2009 +0900 +++ b/extensions/radius_gw/sub_auth.c Tue Jun 16 13:37:46 2009 +0900 @@ -91,7 +91,7 @@ return; } -static int auth_rad_req(struct rga_conf_state * cs, sess_id_t ** session, struct radius_msg * rad_req, struct radius_msg ** rad_ans, msg_t ** diam_fw, void * cli ) +static int auth_rad_req(struct rga_conf_state * cs, sess_id_t * session, struct radius_msg * rad_req, struct radius_msg ** rad_ans, msg_t ** diam_fw, void * cli ) { int idx; int got_id = 0; @@ -819,7 +819,7 @@ return 0; } -static int auth_diam_ans(struct rga_conf_state * cs, sess_id_t ** session, msg_t ** diam_ans, struct radius_msg ** rad_fw, void * cli ) +static int auth_diam_ans(struct rga_conf_state * cs, sess_id_t * session, msg_t ** diam_ans, struct radius_msg ** rad_fw, void * cli ) { TRACE_ENTRY("%p %p %p %p %p", cs, session, diam_ans, rad_fw, cli); CHECK_PARAMS(cs); diff -r c7ce13cb7d23 -r 540ed390c04f extensions/radius_gw/sub_debug.c --- a/extensions/radius_gw/sub_debug.c Mon Jun 15 15:00:10 2009 +0900 +++ b/extensions/radius_gw/sub_debug.c Tue Jun 16 13:37:46 2009 +0900 @@ -110,11 +110,11 @@ radius_msg_dump(msg); } -static int debug_rad_req(struct rga_conf_state * cs, sess_id_t ** session, struct radius_msg * rad_req, struct radius_msg ** rad_ans, msg_t ** diam_fw, void * cli ) +static int debug_rad_req(struct rga_conf_state * cs, sess_id_t * session, struct radius_msg * rad_req, struct radius_msg ** rad_ans, msg_t ** diam_fw, void * cli ) { TRACE_ENTRY("%p %p %p %p %p %p", cs, session, rad_req, rad_ans, diam_fw, cli); - log_debug("sub_debug ( c:'%s' ) state dump start for incoming RADIUS message (session: %p->%p)\n", cs->conffile, session, session?*session:NULL); + log_debug("sub_debug ( c:'%s' ) state dump start for incoming RADIUS message (session: %p)\n", cs->conffile, session); if (!rad_req) { log_debug(" RADIUS request: NULL pointer\n"); @@ -142,11 +142,11 @@ return 0; } -static int debug_diam_ans(struct rga_conf_state * cs, sess_id_t ** session, msg_t ** diam_ans, struct radius_msg ** rad_fw, void * cli ) +static int debug_diam_ans(struct rga_conf_state * cs, sess_id_t * session, msg_t ** diam_ans, struct radius_msg ** rad_fw, void * cli ) { TRACE_ENTRY("%p %p %p %p %p", cs, session, diam_ans, rad_fw, cli); CHECK_PARAMS(cs); - log_debug("sub_debug ( c:'%s' ) state dump start for incoming Diameter answer (session: %p->%p)\n", cs->conffile, session, session?*session:NULL); + log_debug("sub_debug ( c:'%s' ) state dump start for incoming Diameter answer (session: %p)\n", cs->conffile, session); if (!diam_ans || ! *diam_ans) { log_debug(" Diameter message: NULL pointer\n"); diff -r c7ce13cb7d23 -r 540ed390c04f extensions/radius_gw/sub_echo_drop.c --- a/extensions/radius_gw/sub_echo_drop.c Mon Jun 15 15:00:10 2009 +0900 +++ b/extensions/radius_gw/sub_echo_drop.c Tue Jun 16 13:37:46 2009 +0900 @@ -127,9 +127,8 @@ } /* Handle attributes from a RADIUS request as specified in the configuration */ -static int sed_rad_req(struct rga_conf_state * cs, sess_id_t ** session, struct radius_msg * rad_req, struct radius_msg ** rad_ans, msg_t ** diam_fw, void * cli ) +static int sed_rad_req(struct rga_conf_state * cs, sess_id_t * session, struct radius_msg * rad_req, struct radius_msg ** rad_ans, msg_t ** diam_fw, void * cli ) { - size_t *nattr_pos; size_t nattr_used = 0; int idx; @@ -141,8 +140,6 @@ rg_list_init(&echo_list); - CHECK_MALLOC( nattr_pos = malloc(rad_req->attr_size * sizeof(size_t)) ); - /* For each attribute in the original message */ for (idx = 0; idx < rad_req->attr_used; idx++) { int action = 0; @@ -219,36 +216,31 @@ } break; - case 0: /* Attribute was not specified in the configuration */ - default: /* unknown action value */ + default: /* Attribute was not specified in the configuration */ /* We just keep the attribute in the RADIUS message */ - nattr_pos[nattr_used++] = rad_req->attr_pos[idx]; + rad_req->attr_pos[nattr_used++] = rad_req->attr_pos[idx]; } } + rad_req->attr_used = nattr_used; /* Save the echoed values in the session, if any */ if (!rg_list_is_empty(&echo_list)) { - CHECK_PARAMS(session && *session); + CHECK_PARAMS(session); CHECK_MALLOC( li = malloc(sizeof(struct rg_list)) ); memcpy(li, &echo_list, sizeof(struct rg_list)); /* Check that we have no previous data stored for this session, for debug */ - ASSERT( sess_data_dereg(*session, cs->sess_hdl, NULL) == ENOENT ); + ASSERT( sess_data_dereg(session, cs->sess_hdl, NULL) == ENOENT ); /* Save the list in the session */ - CHECK_FCT( sess_data_reg(*session, cs->sess_hdl, li, ssi_cleanup) ); + CHECK_FCT( sess_data_reg(session, cs->sess_hdl, li, ssi_cleanup) ); } - /* Finally update the radius message to remove all handled attributes */ - free(rad_req->attr_pos); - rad_req->attr_pos = nattr_pos; - rad_req->attr_used = nattr_used; - return 0; } -/* Process an answer: add back the ECHO attributes, if any */ -static int sed_diam_ans(struct rga_conf_state * cs, sess_id_t ** session, msg_t ** diam_ans, struct radius_msg ** rad_fw, void * cli ) +/* Process an answer: add the ECHO attributes back, if any */ +static int sed_diam_ans(struct rga_conf_state * cs, sess_id_t * session, msg_t ** diam_ans, struct radius_msg ** rad_fw, void * cli ) { int ret; struct rg_list * list = NULL; @@ -257,13 +249,13 @@ CHECK_PARAMS(cs); /* If there is no session associated, just give up */ - if (! session || ! *session) { + if (! session ) { TRACE_DEBUG(FULL, "No session associated with the message, nothing to do here..."); return 0; } - /* No try and retrieve any data from the session */ - ret = sess_data_dereg( *session, cs->sess_hdl, (void *)&list ); + /* Now try and retrieve any data from the session */ + ret = sess_data_dereg( session, cs->sess_hdl, (void *)&list ); if (ret == ENOENT) { TRACE_DEBUG(FULL, "No data saved in the session, no attribute to add back"); return 0; diff -r c7ce13cb7d23 -r 540ed390c04f include/waaad/session-api.h --- a/include/waaad/session-api.h Mon Jun 15 15:00:10 2009 +0900 +++ b/include/waaad/session-api.h Tue Jun 16 13:37:46 2009 +0900 @@ -212,6 +212,21 @@ int sess_unlink ( sess_id_t ** session ); /* + * FUNCTION: sess_destroy + * + * PARAMETERS: + * session : Pointer to a session object. + * + * DESCRIPTION: + * Destroys a session an all associated data, if any. + * + * RETURN VALUE: + * 0 : The session no longer exists. + * EINVAL : A parameter is invalid. + */ +int sess_destroy ( sess_id_t ** session ); + +/* * FUNCTION: sess_regext * * PARAMETERS: @@ -308,7 +323,7 @@ #endif /* ! IN_EXTENSION */ /* The version of this API, to check binary compatibility -- increment each time a change is made in api_sess_t */ -#define WAAAD_API_SESSION_VER 1 +#define WAAAD_API_SESSION_VER 2 /* Now define the type of the structure that contains the callback to pass to extensions */ typedef struct { @@ -322,6 +337,7 @@ int (*sess_getsid) ( sess_id_t * session, char ** sid ); int (*sess_link) ( sess_id_t * session ); int (*sess_unlink) ( sess_id_t ** session ); + int (*sess_destroy) ( sess_id_t ** session ); int (*sess_regext) ( sess_reg_t ** client ); int (*sess_deregext) ( sess_reg_t * client ); int (*sess_data_reg) ( sess_id_t * session, sess_reg_t * client, void * data, void (*cleanup)(void *) ); @@ -344,6 +360,7 @@ #define sess_getsid g_api_session->sess_getsid #define sess_link g_api_session->sess_link #define sess_unlink g_api_session->sess_unlink +#define sess_destroy g_api_session->sess_destroy #define sess_regext g_api_session->sess_regext #define sess_deregext g_api_session->sess_deregext #define sess_data_reg g_api_session->sess_data_reg @@ -354,7 +371,7 @@ #else /* IN_EXTENSION */ /* From the daemon, we must initialize the API object, in extension.c */ -# define MY_WAAAD_API_SESSION_VER 1 +# define MY_WAAAD_API_SESSION_VER 2 # if MY_WAAAD_API_SESSION_VER != WAAAD_API_SESSION_VER # error "You must update API_INIT_SESSION also" # endif @@ -368,6 +385,7 @@ (api_session).sess_getsid = sess_getsid; \ (api_session).sess_link = sess_link; \ (api_session).sess_unlink = sess_unlink; \ + (api_session).sess_destroy = sess_destroy; \ (api_session).sess_regext = sess_regext; \ (api_session).sess_deregext = sess_deregext; \ (api_session).sess_data_reg = sess_data_reg; \ diff -r c7ce13cb7d23 -r 540ed390c04f waaad/session.c --- a/waaad/session.c Mon Jun 15 15:00:10 2009 +0900 +++ b/waaad/session.c Tue Jun 16 13:37:46 2009 +0900 @@ -57,6 +57,7 @@ /* The following two integers are used to generate values which are eternaly unique */ static uint32_t g_sid_h; /* initialized to the current time at module initialization */ static uint32_t g_sid_l; /* incremented each time a session id is created. */ + static pthread_mutex_t g_sid_lock = PTHREAD_MUTEX_INITIALIZER; /************ sess_id_t ***********/ @@ -536,7 +537,7 @@ TRACE_ENTRY( "%p", session ); /* Check the parameter */ - CHECK_PARAMS( VALIDATE_SI(*session) && (session != NULL) ); + CHECK_PARAMS( session && VALIDATE_SI(*session) ); /* Copy the hash value */ hash = _SI(*session)->hash; @@ -743,6 +744,41 @@ return noent ? ENOENT : 0; } +/* Destroy a session and any registered data */ +int sess_destroy( sess_id_t ** session ) +{ + int ret = 0; + uti_list_t *li, *item = NULL; + + TRACE_ENTRY( "%p", session ); + + /* Check the parameter */ + CHECK_PARAMS( session && VALIDATE_SI(*session) ); + + /* Lock the global list of handlers */ + CHECK_POSIX( pthread_mutex_lock(&_str_lock) ); + + for (li = _srt_sentinel.next; li != &_srt_sentinel; li = li->next) { + /* Lock the sublist */ + CHECK_POSIX( pthread_mutex_lock( &_SR(li)->lock ) ); + + /* Search for data registered for this session in this handler */ + ret = find_sd(_SI(*session), &_SR(li)->sentinel, &item); + + /* If found, destroy it */ + if (ret == 0) { + CHECK_FCT( _destroy_sr_data(_SD(item), NULL) ) + } + + CHECK_POSIX( pthread_mutex_unlock( &_SR(li)->lock ) ); + } + + CHECK_POSIX( pthread_mutex_unlock(&_str_lock) ); + + /* Now unlink the session. It will be freed unless someone had called "sess_link" explicitely. */ + return sess_unlink(session); +} + /* End of the module */ int sess_fini ( void ) {