# HG changeset patch # User Sebastien Decugis # Date 1243320303 -32400 # Node ID 52b7e13cb1e7771c041548621fe072fe89e54543 # Parent 883330e610e1a106a7ac78e5c13ddeff1ef1e6bd Added a quick and dirty debug subextension diff -r 883330e610e1 -r 52b7e13cb1e7 extensions/radius_gw/CMakeLists.txt --- a/extensions/radius_gw/CMakeLists.txt Tue May 26 11:37:32 2009 +0900 +++ b/extensions/radius_gw/CMakeLists.txt Tue May 26 15:45:03 2009 +0900 @@ -74,3 +74,9 @@ sub_echo_drop.tab.h) TARGET_LINK_LIBRARIES(sub_echo_drop rg_common) ENDIF (BUILD_SUB_ECHO_DROP) + +OPTION(BUILD_SUB_DEBUG "Build debug sub-extension? (display status of RADIUS and Diameter messages)" ON) + IF (BUILD_SUB_DEBUG) + ADD_LIBRARY(sub_debug MODULE ${RG_COMMON_HEADER} sub_debug.c) + TARGET_LINK_LIBRARIES(sub_debug rg_common) + ENDIF (BUILD_SUB_DEBUG) diff -r 883330e610e1 -r 52b7e13cb1e7 extensions/radius_gw/sub_debug.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/extensions/radius_gw/sub_debug.c Tue May 26 15:45:03 2009 +0900 @@ -0,0 +1,190 @@ +/********************************************************************************************************* +* Software License Agreement (BSD License) * +* Author: Sebastien Decugis * +* * +* Copyright (c) 2009, WIDE Project and NICT * +* All rights reserved. * +* * +* Redistribution and use of this software in source and binary forms, with or without modification, are * +* permitted provided that the following conditions are met: * +* * +* * Redistributions of source code must retain the above * +* copyright notice, this list of conditions and the * +* following disclaimer. * +* * +* * Redistributions in binary form must reproduce the above * +* copyright notice, this list of conditions and the * +* following disclaimer in the documentation and/or other * +* materials provided with the distribution. * +* * +* * Neither the name of the WIDE Project or NICT nor the * +* names of its contributors may be used to endorse or * +* promote products derived from this software without * +* specific prior written permission of WIDE Project and * +* NICT. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED * +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A * +* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * +* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR * +* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * +* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +*********************************************************************************************************/ + +/* Debug sub extension for radius_gw */ + +#define IN_EXTENSION +#define DEFINE_DEBUG_MACRO sub_debug +#define DECLARE_API_POINTERS +#include + +#include "rg_common.h" + +#include + +int sub_debug_verbosity = 2; + +struct rga_conf_state { + char * conffile; + void * waaad_handle; + void (*waaad_msg_dump_walk)( int level, void * obj ); +}; + +static struct rga_conf_state * debug_conf_parse(char * conffile) +{ + struct rga_conf_state * ret; + + TRACE_ENTRY("%p", conffile); + + CHECK_MALLOC_DO( ret = malloc(sizeof(struct rga_conf_state)), return NULL ); + memset(ret, 0, sizeof(struct rga_conf_state)); + + if (conffile) + ret->conffile = conffile; + else + ret->conffile = "-"; + + CHECK_MALLOC_DO(ret->waaad_handle = dlopen(0, RTLD_LAZY), return NULL); + + CHECK_MALLOC_DO(ret->waaad_msg_dump_walk = dlsym(ret->waaad_handle, "msg_dump_walk"), return NULL); + + return ret; +} + +static void debug_conf_free(struct rga_conf_state * cs) +{ + TRACE_ENTRY("%p", cs); + CHECK_PARAMS_DO(cs, return); + dlclose(cs->waaad_handle); + free(cs); + return; +} + +#include "rgw_msg_attrtype.c" +#include "rgw_msg_codes.c" + +static void debug_dump_radius(struct radius_msg *msg) +{ + unsigned char *auth; + size_t i; + + auth = &(msg->hdr->authenticator[0]); + log_debug("--- Dump method 1:\n"); + + log_debug(" id: %02hhx, code: %hhd (%s)\n", msg->hdr->identifier, msg->hdr->code, rgw_msg_code_str(msg->hdr->code)); + log_debug(" auth: %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx\n", + auth[0], auth[1], auth[2], auth[3], + auth[4], auth[5], auth[6], auth[7]); + log_debug(" %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx\n", + auth[8], auth[9], auth[10], auth[11], + auth[12], auth[13], auth[14], auth[15]); + for (i = 0; i < msg->attr_used; i++) { + struct radius_attr_hdr *attr = (struct radius_attr_hdr *)(msg->buf + msg->attr_pos[i]); + log_debug(" attr: len:%3hhd, type:%02hhx (%s)\n", attr->length, attr->type, rgw_msg_attrtype_str(attr->type)); + /* If we need to dump the value, it's better to call directly radius_msg_dump instead... */ + } + + log_debug("--- Dump method 2:\n"); + 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 ) +{ + TRACE_ENTRY("%p %p %p %p %p", cs, session, rad_req, rad_ans, diam_fw); + + log_debug("sub_debug ( c:'%s' ) state dump start for incoming RADIUS message (session: %p->%p)\n", cs->conffile, session, session?*session:NULL); + + if (!rad_req) { + log_debug(" RADIUS request: NULL pointer\n"); + } else { + log_debug(" RADIUS request (%p) DUMP:", rad_req); + debug_dump_radius(rad_req); + } + + if (!rad_ans || ! *rad_ans) { + log_debug(" RADIUS answer: NULL pointer\n"); + } else { + log_debug(" RADIUS answer (%p) DUMP:", *rad_ans); + debug_dump_radius(*rad_ans); + } + + if (!diam_fw || ! *diam_fw) { + log_debug(" Diameter message: NULL pointer\n"); + } else { + log_debug(" Diameter message (%p) DUMP:", *diam_fw); + (*cs->waaad_msg_dump_walk)(0, *diam_fw); + } + + log_debug("sub_debug ( c:'%s' ) state dump complete\n", cs->conffile); + + 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 ) +{ + TRACE_ENTRY("%p %p %p %p", cs, session, diam_ans, rad_fw); + 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); + + if (!diam_ans || ! *diam_ans) { + log_debug(" Diameter message: NULL pointer\n"); + } else { + log_debug(" Diameter message (%p) DUMP:", *diam_ans); + debug_dump_diameter(*diam_ans); + } + + if (!rad_fw || ! *rad_fw) { + log_debug(" RADIUS answer: NULL pointer\n"); + } else { + log_debug(" RADIUS answer (%p) DUMP:", *rad_fw); + debug_dump_radius(*rad_fw); + } + + log_debug("sub_debug ( c:'%s' ) state dump complete\n", cs->conffile); + return 0; +} + +int rga_register(int version, waaad_api_t * waaad_api, struct radius_gw_api * api) +{ + TRACE_ENTRY("%d %p %p", version, waaad_api, api); + CHECK_PARAMS( waaad_api && api ); + + if (version != RADIUS_GW_API_VER) { + log_error("ABI version mismatch, please recompile this extension (%s)\n", __FILE__); + return EINVAL; + } + + /* Required to use the waaad api from this sub-extension: */ + EXTENSION_API_INIT_INTERN( API_MODULE_ALL, "sub_debug", waaad_api ); + + /* Initialize the radius_gw api callbacks */ + api->rga_conf_parse_cb = debug_conf_parse; + api->rga_conf_free_cb = debug_conf_free; + api->rga_rad_req_cb = debug_rad_req; + api->rga_diam_ans_cb = debug_diam_ans; + + /* We're done, we must not initialize any state here since the extension must be re-entrant, but in sample_conf_parse */ + return 0; +}