changeset 418:8155408c6dc5

Added early handling of Diameter answers
author Sebastien Decugis <sdecugis@nict.go.jp>
date Tue, 16 Jun 2009 15:38:18 +0900
parents 4d56917a5e42
children fc0d723c1f8b
files extensions/radius_gw/radius_gw.h extensions/radius_gw/rg_api.h extensions/radius_gw/rgw_extensions.c extensions/radius_gw/rgw_work.c
diffstat 4 files changed, 64 insertions(+), 7 deletions(-) [+]
line wrap: on
line diff
--- 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);
 
 
--- 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.
 	 */
 	
--- 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;
--- 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);
"Welcome to our mercurial repository"