# HG changeset patch # User Sebastien Decugis # Date 1245134298 -32400 # Node ID 8155408c6dc5e143b99bf1575d3e3d4c8ff04a08 # Parent 4d56917a5e422176e63a5d83cfb0603a69bef66e Added early handling of Diameter answers diff -r 4d56917a5e42 -r 8155408c6dc5 extensions/radius_gw/radius_gw.h --- a/extensions/radius_gw/radius_gw.h Tue Jun 16 15:08:30 2009 +0900 +++ b/extensions/radius_gw/radius_gw.h Tue Jun 16 15:38:18 2009 +0900 @@ -126,6 +126,7 @@ void rgw_extensions_dump(void); void rgw_extensions_start_cache(void); int rgw_extensions_loop_req(struct rgw_radius_msg_meta **rad, sess_id_t **session, msg_t **diam_msg, struct rgw_client * cli); +int rgw_extensions_loop_ans(struct rgw_radius_msg_meta *req, sess_id_t *session, msg_t **diam_ans, struct radius_msg ** rad_ans, struct rgw_client * cli); void rgw_extensions_fini(void); diff -r 4d56917a5e42 -r 8155408c6dc5 extensions/radius_gw/rg_api.h --- a/extensions/radius_gw/rg_api.h Tue Jun 16 15:08:30 2009 +0900 +++ b/extensions/radius_gw/rg_api.h Tue Jun 16 15:38:18 2009 +0900 @@ -52,7 +52,7 @@ 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 - ret -2: reply the content of rad_ans (created with rg_msg_create_ans) to the RADIUS client immediatly + ret -2: reply the content of rad_ans to the RADIUS client immediatly ret >0: critical error (errno), log and exit. */ diff -r 4d56917a5e42 -r 8155408c6dc5 extensions/radius_gw/rgw_extensions.c --- a/extensions/radius_gw/rgw_extensions.c Tue Jun 16 15:08:30 2009 +0900 +++ b/extensions/radius_gw/rgw_extensions.c Tue Jun 16 15:38:18 2009 +0900 @@ -404,6 +404,54 @@ } +/* Loop in the extension list (same as req) to convert data from diam_ans to rad_ans */ +int rgw_extensions_loop_ans(struct rgw_radius_msg_meta *req, sess_id_t *session, msg_t **diam_ans, struct radius_msg ** rad_ans, struct rgw_client * cli) +{ + int ret = 0; + struct rg_list * head = NULL, *li; + + TRACE_ENTRY("%p %p %p %p %p", req, session, diam_ans, rad_ans, cli); + CHECK_PARAMS( req && session && diam_ans && *diam_ans && rad_ans && *rad_ans && cli); + + /* Get the list of extensions of the RADIUS request */ + CHECK_FCT( get_accelerator(&head, req->radius.hdr->code, req->serv_type) ); + + /* Loop in the list of extensions */ + for (li = head->next; li != head; li = li->next) { + struct ext_descr * ext = ((struct ext_accel_item *) li)->ext; + + if (ext->api.rga_diam_ans_cb) { + TRACE_DEBUG(ANNOYING, "Calling next extension: %s", ext->extname); + ret = (*ext->api.rga_diam_ans_cb)(ext->cs, session, diam_ans, rad_ans, (void *)cli); + if (ret) + break; + } else { + TRACE_DEBUG(ANNOYING, "Skipping extension '%s' (NULL callback)", ext->extname); + } + } + + /* If no error encountered, we're done here */ + if (ret == 0) + return 0; + + /* Destroy the temporary RADIUS answer */ + if (*rad_ans) { + radius_msg_free(*rad_ans); + free(*rad_ans); + *rad_ans = NULL; + } + + if (ret > 0) { + /* Critical error, log and exit */ + log_error("An error occurred while handling a DIAMETER answer to a converted RADIUS request, turn on DEBUG for details: %s\n", strerror(ret)); + return ret; + } + + /* We might define other return values with special meaning here (ret == -1, ...) for example create a new Diameter request */ + + return 0; +} + void rgw_extensions_fini(void) { struct rg_list * item, *subitem; diff -r 4d56917a5e42 -r 8155408c6dc5 extensions/radius_gw/rgw_work.c --- a/extensions/radius_gw/rgw_work.c Tue Jun 16 15:08:30 2009 +0900 +++ b/extensions/radius_gw/rgw_work.c Tue Jun 16 15:38:18 2009 +0900 @@ -65,28 +65,36 @@ static void work_receive_diam_answer(void * paback, msg_t **ans) { struct pending_answer * pa = (struct pending_answer *)paback; - + struct radius_msg * rad_ans; + 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 */ - + CHECK_MALLOC_DO( rad_ans = radius_msg_new(RADIUS_CODE_ACCESS_REJECT, pa->rad->radius.hdr->identifier), goto out ); /* Pass the Diameter answer to the same extensions as the request */ - + CHECK_FCT_DO( rgw_extensions_loop_ans(pa->rad, pa->sess, ans, &rad_ans, pa->cli), goto out ); /* Now try and send the RADIUS answer */ - + if (rad_ans) { + CHECK_FCT_DO( rgw_client_finish_send(&rad_ans, pa->rad, pa->cli), goto out); + } 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), ); - *ans = NULL; + if (*ans) { + CHECK_FCT_DO( msg_free(*ans, 1), ); + *ans = NULL; + } + + /* Release reference on the client */ + rgw_clients_dispose(&pa->cli); /* Clear the answer data */ free(pa);