Mercurial > hg > waaad
view extensions/rt_default/rt_default.c @ 400:22f29007b931
Detect when extensions are loaded several times (not allowed)
author | Sebastien Decugis <sdecugis@nict.go.jp> |
---|---|
date | Tue, 02 Jun 2009 14:49:37 +0900 |
parents | 316bb3f38d04 |
children |
line wrap: on
line source
/********************************************************************************************************* * Software License Agreement (BSD License) * * Author: Sebastien Decugis <sdecugis@nict.go.jp> * * * * 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. * *********************************************************************************************************/ /* * Basic routing of the messages based on their Destination-Realm, Destination-Host, and configuration file. */ #define DECLARE_API_POINTERS #include "rt_default.h" static dict_object_t * dict_avp_DH = NULL; /* Destination-Host */ static dict_object_t * dict_avp_DR = NULL; /* Destination-Realm */ int rt_default_verbosity = 0; /* Analyze a message content to find Destination-Realm and Destination-Host */ static int find_avps(msg_t * msg, avp_value_t ** dr, avp_value_t ** dh) { int ret = 0; msg_avp_t * avp = NULL; msg_avp_data_t * avpdata; /* Destination-Host */ ret = msg_search_avp( msg, dict_avp_DH, &avp ); if (ret != 0) { TRACE_DEBUG(INFO, "Error in msg_search_avp: %s", strerror(ret)); return ret; } if (avp != NULL) { ret = msg_avp_data( avp, &avpdata ); if (ret != 0) { TRACE_DEBUG(INFO, "Error in msg_avp_data: %s", strerror(ret)); return ret; } *dh = avpdata->avp_data; } /* Destination-Realm */ ret = msg_search_avp( msg, dict_avp_DR, &avp ); if (ret != 0) { TRACE_DEBUG(INFO, "Error in msg_search_avp: %s", strerror(ret)); return ret; } if (avp != NULL) { ret = msg_avp_data( avp, &avpdata ); if (ret != 0) { TRACE_DEBUG(INFO, "Error in msg_avp_data: %s", strerror(ret)); return ret; } *dr = avpdata->avp_data; } return 0; } /* The callback doing all the work */ static int cb_def_out(void * data, msg_t * msg, rt_dpl_t * list ) { int ret = 0; avp_value_t * dr = NULL; avp_value_t * dh = NULL; rt_dpl_t * candidate = list; TRACE_ENTRY("%p %p", msg, list); /* First find Destination Realm and Destination Host AVPs in msg */ ret = find_avps(msg, &dr, &dh); if (ret != 0) { TRACE_DEBUG(INFO, "Failed to analyze the message: %s", strerror(ret)); return ret; } /* Then for each candidate peer for routing */ while (candidate != NULL) { char * candname = NULL; /* name of this candidate peer */ int tablescore = 0; ret = peer_get(candidate->peer, PEER_DIAMETER_ID, (void *)&candname); if (ret != 0) { TRACE_DEBUG(INFO, "Unable to retrieve peer name: %s", strerror(ret)); return ret; } /* Is destination host ? */ if ((rtd_conf->do_dest_host) && (dh != NULL)) { if ((dh->os.len == strlen(candname)) && (strncasecmp(candname, (char *)dh->os.data, dh->os.len) == 0)) { TRACE_DEBUG(FULL, "Peer '%s' is Destination-Host, adding appropriate score", candname); candidate->score += rtd_conf->sc_dest_host; } } /* Is matching destination realm ? */ if ((rtd_conf->do_dest_realm) && (dr != NULL)) { char * candrealm = NULL; /* realm of this candidate peer */ ret = peer_get(candidate->peer, PEER_REALM, (void *)&candrealm); if (ret != 0) { TRACE_DEBUG(INFO, "Unable to retrieve peer realm: %s", strerror(ret)); return ret; } if ((dr->os.len == strlen(candrealm)) && (strncasecmp(candrealm, (char *)dr->os.data, dr->os.len) == 0)) { TRACE_DEBUG(FULL, "Peer '%s' has matching Destination-Realm, adding appropriate score", candname); candidate->score += rtd_conf->sc_dest_realm; } } /* Is defined in configuration as a default route ? */ ret = rtd_search( dr ? dr->os.data : NULL, dr ? dr->os.len : 0, candname, &tablescore); if (ret != 0) { TRACE_DEBUG(INFO, "Internal extension error, search failed: %s", strerror(ret)); return ret; } candidate->score += tablescore; /* Move to next candidate */ candidate = candidate->next; } return 0; } /* Initialize the configuration */ rtd_conf_t * rtd_conf = NULL; static rtd_conf_t _conf; static int conf_init(void) { rtd_conf = &_conf; memset(rtd_conf, 0, sizeof(rtd_conf_t)); /* Set the default values */ rtd_conf->do_dest_host = 1; rtd_conf->do_dest_realm = 1; rtd_conf->sc_dest_host = PEER_SCORE_FINALDEST; rtd_conf->sc_dest_realm = PEER_SCORE_DEFAULT_REALM; rtd_conf->sc_no_info = 0; rtd_conf->sc_all = PEER_SCORE_DEFAULT; rtd_conf->sc_all_pref = PEER_SCORE_DEFAULT + PEER_SCORE_LOAD_BALANCE; rtd_conf->sc_rlm = PEER_SCORE_DEFAULT_REALM; rtd_conf->sc_rlm_pref = PEER_SCORE_DEFAULT_REALM + PEER_SCORE_LOAD_BALANCE; return 0; } static void conf_dump(void) { TRACE_DEBUG(FULL, "rt_default configuration dump:\n" " Verbosity...........: %d\n" " Handle Dest Host....: %d\n" " Handle Dest Realm...: %d\n" " Score Dest Host.....: %d\n" " Score Dest Realm....: %d\n" " Score no info.......: %d\n" " Score default route.: %d\n" " Score default pref..: %d\n" " Score realm.........: %d\n" " Score realm pref....: %d", rt_default_verbosity, rtd_conf->do_dest_host, rtd_conf->do_dest_realm, rtd_conf->sc_dest_host, rtd_conf->sc_dest_realm, rtd_conf->sc_no_info, rtd_conf->sc_all, rtd_conf->sc_all_pref, rtd_conf->sc_rlm, rtd_conf->sc_rlm_pref); } /* handler */ static rt_out_hdl_t * rt_def_hdl = NULL; /* entry point */ static int entry(char * conffile) { int ret = 0; TRACE_ENTRY("%p", conffile); ret = dict_search( DICT_AVP, AVP_BY_NAME, "Destination-Host", &dict_avp_DH, ENOENT ); if (ret != 0) { log_error("Error initializing extension's dictionary objects: %s\n", strerror(ret)); return ret; } ret = dict_search( DICT_AVP, AVP_BY_NAME, "Destination-Realm", &dict_avp_DR, ENOENT ); if (ret != 0) { log_error("Error initializing extension's dictionary objects: %s\n", strerror(ret)); return ret; } ret = conf_init(); if (ret != 0) { log_error("Error initializing extension: %s\n", strerror(ret)); return ret; } ret = rtd_init(); if (ret != 0) { log_error("Error initializing extension: %s\n", strerror(ret)); return ret; } if (conffile != NULL) { ret = rtd_conf_handle(conffile); if (ret != 0) { log_error("Error parsing extension configuration: %s\n", strerror(ret)); return ret; } TRACE_DEBUG(INFO, "Extension RT/Default initialized with configuration: '%s'", conffile); conf_dump(); rtd_dump(); } else { TRACE_DEBUG(INFO, "Extension RT/Default initialized with default configuration"); } return rt_out_register( cb_def_out, NULL, RT_OUT_NORMAL, &rt_def_hdl ); } /* Unload */ void waaad_ext_fini(void) { rt_out_unregister ( rt_def_hdl ); rtd_fini(); } EXTENSION_API_INIT( API_MODULE_ALL, entry, "rt_default", 1);