Presentation is loading. Please wait.

Presentation is loading. Please wait.

Implementing an extension for freeDiameter

Similar presentations


Presentation on theme: "Implementing an extension for freeDiameter"— Presentation transcript:

1 Implementing an extension for freeDiameter
Souheil Ben Ayed (Keio) Sebastien Decugis (NICT) FreeDiameter Extension WIDE AAA-WG

2 FreeDiameter Extension Tutorial
Goal : Introduce on writing an Extension for freeDiameter Tutorial based on “test_app” extension Tutorial includes: Writing an Extension start writing an extension Add object definition to Dictionary Manage diameter messages and AVPs Manage sessions Configuring an extension for freeDiameter Add Extension to freeDiameter Add/edit CMAKE configuration files Add Extension to be loaded. Build/test In this tutorial we will introduce on writing an extension for freeediameter. This tutorial is based on “test_app” an extension available with freediameter. We will start by writing an extension then adding object to dictionary , then manage messages and AVPs also manage sessions. Then we will configure thois extension for freediameter by adding it to freediameter, adding and editing Cmake configuration files, adding this extension to be loaded and finaly building and testing it. Souheil Ben Ayed, Sebastien Decugis March 10, 2010

3 Steps :writing an Extension for freeDiameter
Start writing your extension Includes, Entry point function, Cleanup callback function Add new objects to Dictionary Application object , commands objects , AVPs objects, rules … Add application to be announced (CER/CEA exchange) Manage Messages and AVPs Create Request/Response messages, send message … Add AVPs to message, set AVP Data, search for AVPs … Manage Sessions Create new session, store/retrieve session state, destroy session Add your extension to freeDiameter Edit freeDiameter configuration, Cmake configuration The main steps on writing an extension are: Souheil Ben Ayed, Sebastien Decugis March 10, 2010

4 Souheil Ben Ayed, Sebastien Decugis
Writing an extension Start writing an extension Adding objects to dictionary Manage Messages and AVPs Manage Sessions So we start by writing our extension. Souheil Ben Ayed, Sebastien Decugis March 10, 2010

5 Start writing your extension
Extension header file: freeDiameter API #include <freeDiameter/extension.h> static int ta_entry(char * conffile); EXTENSION_ENTRY("test_app", ta_entry); /* Entry point */ static int ta_entry(char * conffile) { TRACE_ENTRY("%p", conffile); return 0; } /* Cleanup callback*/ void fd_ext_fini(void) { return ; /* Extension is terminated */ Define the entry point Entry point called when loading the extension A simple and basic code needed by an extension is as follow: Function called when the freeDiameter daemon exits Souheil Ben Ayed, Sebastien Decugis March 10, 2010

6 Add Objects to the Dictionary
/* A simple object: the test application */ struct dict_object * ta_appli = NULL; struct dict_application_data appdata = { /*application_id =*/ , /* application_name =*/ "Test application" }; ret = fd_dict_new( dict, /* the dictionary we are adding into */ DICT_APPLICATION, &appdata, NULL, /* parent: optional (vendor in this case) */ &ta_appli ); /* Don’t forget to check the value of ret … */ Object reference The data of the new object The new application is defined in “dict” upon success. firstly we should add all objects needed by our application or our extension to the dictionary. Here we show an example of how to do this. For more details you can refers to the documentation included with freediameterlib. Souheil Ben Ayed, Sebastien Decugis March 10, 2010

7 Search in Dictionary (fd_dict_search) - 1
The function fd_dict_search is : Look for an application, command, AVP, vendor object… Check if an object is in the dictionary. dict : Target dictionary type : Type of object that is looking for: DICT_APPLICATION, DICT_AVP,… criteria: How to search for the object: APPLICATION_BY_NAME, AVP_BY_NAME, AVP_BY_CODE,… what : value of the criteria to match int fd_dict_search ( struct dictionary * dict, enum dict_object_type type, int criteria, void * what, struct dict_object **result, int retval ); In the dictionary we can look for an application, command, avp or vendor object or check if this object is in the dictionnary or not. Souheil Ben Ayed, Sebastien Decugis March 10, 2010

8 Search in Dictionary (fd_dict_search) - 2
To search for an object: Creates a dict_object : where the object will be store in. What is the type of the object : DICT_APPLICATION Choose your criteria for searching (+the value for this criteria): APPLICATION_BY_NAME Now we are ready to search for an object corresponding to this criteria in the dictionary. For example to search for an object we creates a dictionary object “dict_object” struct dict_object * appli, * avp_username; command_code_t code = 268; fd_dict_search(dict, DICT_APPLICATION, APPLICATION_BY_NAME, " Test application", &appli, ENOENT); fd_dict_search(dict, DICT_AVP, AVP_BY_CODE, &code, &avp_username, ENOENT); Souheil Ben Ayed, Sebastien Decugis March 10, 2010

9 Register application for advertising
To register an application to be advertized in CER/CEA exchanges. Example: int fd_disp_app_support ( struct dict_object * app, struct dict_object * vendor, int auth, int acct ); struct dict_object * ta_appli = NULL; struct dict_object * ta_vendor = NULL; application_id_t appli_id = ; /*search Application object by application ID*/ fd_dict_search(fd_g_config->cnf_dict, DICT_APPLICATION, APPLICATION_BY_ID, &appli_id, & ta_appli, ENOENT); /*search vendor object*/ fd_dict_search(fd_g_config->cnf_dict, DICT_VENDOR, VENDOR_OF_APPLICATION, &ta_appli, & ta_vendor, ENOENT); /* Advertise the support for the test application in the peer */ fd_disp_app_support ( ta_appli, ta_vendor, 1, 0 ) ; To be announced by diameter Capability exchange messages, an application should register it self. This function register an application. Application object an d vendor object (may be NULL if not needed) set authentication and/or accounting if supported by this application. Souheil Ben Ayed, Sebastien Decugis March 10, 2010

10 Register a callback function - 1
This callback will be called when a message matching criteria is received by freeDiameter daemon. To match criteria. APP ID, Command code, AVP code, … And give the value to match. Example: Command code criteria (DISP_HOW_CC). And for messages with: Application Id = 5, Command code = 268 struct disp_when { struct dict_object *app; struct dict_object *command; struct dict_object *avp; struct dict_object *value; }; We also need to register to callback function to be called when a message matching criteria for this application is received. enum disp_how { DISP_HOW_ANY = 1, DISP_HOW_APPID, DISP_HOW_CC, DISP_HOW_AVP, DISP_HOW_AVP_ENUMVAL }; Souheil Ben Ayed, Sebastien Decugis March 10, 2010

11 Register a callback function - 2
To register a callback function : Example: int fd_disp_register ( int (*cb)( struct msg **, struct avp *, struct session *, enum disp_action *), enum disp_how how, struct disp_when * when, struct disp_hdl ** handle ); /* int ta_tr_cb(struct msg **, struct avp *, struct session *, enum disp_action *); */ static struct disp_hdl * ta_hdl_tr = NULL; /* handler for Test-Request req cb */ struct disp_when data; data.app = ta_appli; data.command = ta_cmd_r; fd_disp_register( ta_tr_cb, DISP_HOW_CC, &data, &ta_hdl_tr ) ; Souheil Ben Ayed, Sebastien Decugis March 10, 2010

12 “test_app” extension entry point
Souheil Ben Ayed, Sebastien Decugis March 10, 2010

13 Manage Diameter Messages
A message object is made of a header and 0 or more AVPs. Structure of message header: Dump a message Message AVP Grp. AVP struct msg_hdr { uint8_t msg_version; uint32_t msg_length; uint8_t msg_flags; command_code_t msg_code; application_id_t msg_appl; uint32_t msg_hbhid; uint32_t msg_eteid; }; A message object is made of a header an 0 or more AVPs. This is the structure of a message header. We can dump the content of a message. /*Dump the content of message object recursively*/ void fd_msg_dump_walk ( int level, msg_or_avp *obj ); /*Dump only the content of message object itself */ void fd_msg_dump_one ( int level, msg_or_avp *obj ); Souheil Ben Ayed, Sebastien Decugis March 10, 2010

14 New request Diameter Message
fd_msg_new creates a new empty Diameter message from a request command template. model : corresponding to an object from dictionary. flags : options to create message ( combination of MSGFL_*) msg : the new created message Example : int fd_msg_new ( struct dict_object * model, int flags, struct msg ** msg ); struct msg * req; struct dict_object * ta_cmd_r; command_code_t code = 257; /*Search request command object by command code “257” */ fd_dict_search( fd_g_config->cnf_dict, DICT_COMMAND, CMD_BY_CODE_R,& code, &ta_cmd_r); /*Create new request message with command code “257” and an end-to-end Id*/ fd_msg_new( ta_cmd_r, MSGFL_ALLOC_ETEID, &req ); Fd_msg_new creates a new empty … We have the model … Souheil Ben Ayed, Sebastien Decugis March 10, 2010

15 New response Diameter Message
fd_msg_new_answer_from_req creates an empty answer message corresponding to a request. R flag cleared Command code, application id, hop-by-hop id and end-to-end id are added in the new message. The session Id AVP is copied if present in request. Or creates a new empty response message (with answer command model /CMD_BY_CODE_A). Int fd_msg_new_answer_from_req ( struct dictionary * dict, struct msg ** msg, int flag ); fd_msg_new_answer_from_req ( fd_g_config->cnf_dict, msg, 0 ); We can also create an answer message from a request. Or we can create an empty answer message but with the second method we should set command code application Id , … after creating the answer message. So the first method is better. fd_dict_search( fd_g_config->cnf_dict, DICT_COMMAND, CMD_BY_CODE_A,& code, &ta_cmd_a); /*Create new request message with command code “257” and an end-to-end Id*/ fd_msg_new( ta_cmd_a, NULL, &ans ); Souheil Ben Ayed, Sebastien Decugis March 10, 2010

16 Souheil Ben Ayed, Sebastien Decugis
Send Diameter message Both request and response messages are sent on network using fd_msg_send function. When sending message, a callback function may be specified for receiving the answer message. Example: int fd_msg_send ( struct msg ** pmsg, void (*anscb)(void *, struct msg **), void * data ); /*send answer message */ fd_msg_send( &ans, NULL, NULL ); /*send a request message with answer callback */ fd_msg_send( &req, ta_cb_ans, sdata); Souheil Ben Ayed, Sebastien Decugis March 10, 2010

17 Souheil Ben Ayed, Sebastien Decugis
AVPs AVPs are part of a message structure. Some AVPs can contain other AVPs: Grouped AVPs AVP header structure struct avp_hdr { avp_code_t avp_code; uint8_t avp_flags; uint32_t avp_len; vendor_id_t avp_vendor; union avp_value * avp_value; }; AVP value union avp_value { struct { uint8_t *data; /*bytes buffer*/ size_t len; } os; int32_t i32;/* integer 32 */ int64_t i64;/* integer 64 */ uint32_t u32;/* unsigned 32 */ uint64_t u64;/* unsigned 64 */ float f32;/* float 32 */ double f64;/* float 64 */ }; Avp value defines the Basic AVP Data Formats. Souheil Ben Ayed, Sebastien Decugis March 10, 2010

18 Create AVP, set value and add to message-1
fd_msg_avp_new creates a new AVP. fd_msg_avp_setvalue set AVP value . To add an AVP to a message or an AVP to an other AVP: reference: a message or AVP object dir : location where to insert this AVP MSG_BRW_FIRST_CHILD, MSG_BRW_LAST_CHILD, MSG_BRW_NEXT, MSG_BRW_PREV,… avp: an AVP to insert. int fd_msg_avp_new ( struct dict_object * model, int flags, struct avp ** avp ); int fd_msg_avp_setvalue ( struct avp *avp, union avp_value *value ); int fd_msg_avp_add ( msg_or_avp * reference, enum msg_brw_dir dir, struct avp *avp); These are some function for creating new AVP, setting value, adding it to message Souheil Ben Ayed, Sebastien Decugis March 10, 2010

19 Create AVP, set value and add to message-2
strcut avp * avp; struct msg * req; int randval; unsigned char * username; union avp_value val; struct dict_object * ta_user_name, *ta_avp; { fd_msg_avp_new ( ta_user_name, 0, &avp ); val.os.data = (unsigned char *)(user_name); val.os.len = strlen(user_name); fd_msg_avp_setvalue( avp, &val ); fd_msg_avp_add( req, MSG_BRW_LAST_CHILD, avp ); } { fd_msg_avp_new ( ta_avp, 0, &avp ); val.i32 = mi->randval; /* Set the User-Name AVP if needed*/ /* Set the Test-AVP AVP */ Souheil Ben Ayed, Sebastien Decugis March 10, 2010

20 Others functions To add Origin-Host AVP and Origin-Realm AVP:
If osi is set add the Origin-State-Id AVP at the end of the message. To add Result-Code AVP. If optavp is provided, a Failed AVP will be added to the message with the optavp content inside it. To search an AVP in a message: int fd_msg_add_origin ( struct msg * msg, int osi ); int fd_msg_rescode_set( struct msg * msg, char * rescode, char * errormsg, struct avp * optavp, int type_id ); int fd_msg_search_avp ( struct msg * msg, struct dict_object * what, struct avp ** avp ); Souheil Ben Ayed, Sebastien Decugis March 10, 2010

21 Retrieve AVP header and get AVP value
With fd_msg_avp_hdr we can retrieve the header of an AVP. From AVP header we can get stored AVP value. (stored value depends on value type) struct avp * avp; struct dict_object * ta_avp; struct avp_hdr * hdr; fd_msg_search_avp ( *msg, ta_avp, &avp); if (avp) { fd_msg_avp_hdr( avp, &hdr ); printf("%x (%s) ", hdr->avp_value->i32, (hdr->avp_value->i32 == mi->randval) ? "Ok" : "PROBLEM"); } else { printf("no_Test-AVP "); } To get the value of an AVP we get the header of this AVP and the value is store in avp_value variable. The stored value depends on the value type. Souheil Ben Ayed, Sebastien Decugis March 10, 2010

22 Receive message (server side)
Souheil Ben Ayed, Sebastien Decugis March 10, 2010

23 Souheil Ben Ayed, Sebastien Decugis
Manage Sessions -1 Only one session object for each session-Id AVP. To associate a state with a session object we must first register a handler for sessions. struct session { int eyec; char *sid; uint32_t hash; struct fd_list chain_h struct timespec timeout; struct fd_list expire; pthread_mutex_t stlock; struct fd_list states; int msg_cnt; }; Souheil Ben Ayed, Sebastien Decugis March 10, 2010

24 Souheil Ben Ayed, Sebastien Decugis
Manage Sessions -2 To create a session object : fd_sess_new. A Session-Id string is generated. opt : is optional string to be concatenated to the identifier. fd_sess_destroy destroys a session and all associated data. Destroying a session is equivalent to a session timeout expired. int fd_sess_new ( struct session ** session, char * diamId, char * opt, size_t optlen ); When we create a session object a session-id is generated we can add a optional string to be concatenated to the identifier. Fd_sess_new to create new session object. And fd_sess_destroy to destroy the session. When we destroy a session we destroy all associated data. And this is equivalent to a session timeout expired. int fd_sess_destroy ( struct session ** session ); Souheil Ben Ayed, Sebastien Decugis March 10, 2010

25 Souheil Ben Ayed, Sebastien Decugis
Manage Sessions -3 We can retrieve a session object from a Session-Id string. Retrieve the session identifier of a session object. Modify the timeout for a session object. int fd_sess_getsid ( struct session * session, char ** sid ); int fd_sess_fromsid ( char * sid, size_t len, struct session ** session, int * new); int fd_sess_settimeout( struct session * session, const struct timespec * timeout ); Souheil Ben Ayed, Sebastien Decugis March 10, 2010

26 Session handler To associate a state with a Session-Id we must first create a handler for sessions. handler : the handler for sessions. cleanup : a callback function that must be called when the session with associated data is destroyed. This session handler should be destroyed at the cleanup callback. int fd_sess_handler_create( struct session_handler ** handler, void (*cleanup)(char * sid, session_state * state)) int fd_sess_handler_destroy( struct session_handler ** handler) Souheil Ben Ayed, Sebastien Decugis March 10, 2010

27 Save/Retrieve session’s state
To store a state with a session: fd_sess_state_store To retrieve the saved state for a session: fd_sess_state_retrieve Retrieving stored state implies disassociating the state with the session. Use fd_sess_state_store to associate the new state with the session. int fd_sess_state_store( struct session_handler * handler, struct session * session, session_state ** state); int fd_sess_state_retrieve( struct session_handler * handler, struct session * session, session_state ** state); Souheil Ben Ayed, Sebastien Decugis March 10, 2010

28 Using sessions and session handler - 1
static struct session_handler * ta_cli_reg = NULL; /*session handler*/ struct session *sess ; fd_sess_handler_create(&ta_cli_reg, free); …. /* Create a new session */ fd_sess_new( &sess, fd_g_config->cnf_diamid, "app_test", 8 ); /* Session-Id */ { char * sid; fd_sess_getsid ( sess, &sid ); fd_msg_avp_new ( ta_sess_id, 0, &avp ); val.os.data = sid; val.os.len = strlen(sid); fd_msg_avp_setvalue( avp, &val ); fd_msg_avp_add( req, MSG_BRW_FIRST_CHILD, avp ); } /* Store the value of mi in the session */ fd_sess_state_store ( ta_cli_reg, sess, &mi ); Souheil Ben Ayed, Sebastien Decugis March 10, 2010

29 Using sessions and session handler - 2
/* Search the session, retrieve its data */ { int new; fd_msg_sess_get(fd_g_config->cnf_dict, *msg, &sess, &new); fd_sess_state_retrieve( ta_cli_reg, sess, &mi ); } void fd_ext_fini( void) (void) fd_sess_handler_destroy(&ta_cli_reg); }; Souheil Ben Ayed, Sebastien Decugis March 10, 2010

30 Send/Receive message ( client side)
Souheil Ben Ayed, Sebastien Decugis March 10, 2010

31 Add an extension to freeDiameter
Add Extension Add/edit CMAKE configuration files Add Extension to be loaded. Build/test Souheil Ben Ayed, Sebastien Decugis March 10, 2010

32 Souheil Ben Ayed, Sebastien Decugis
Add your Extension Make sure that you have Cmake installed. Add your extension to freeDiameter extensions. Add the extension to be built with freeDiameter (freeDiameter_path\extensions\CMakeList.txt) # Create an option “BUILD_TEST_APP” set to ON OPTION(BUILD_TEST_APP "Build test_app.fdx? (Test application)" ON) #If the “BUILD_TEST_APP” is set add the extension directory to be built IF (BUILD_TEST_APP) SUBDIRS (test_app) ENDIF (BUILD_TEST_APP) Souheil Ben Ayed, Sebastien Decugis March 10, 2010

33 Create a CMakeFile for your extension
Add a CMakeList.txt file to the extension. Example : (CMakeList.txt for test_app) # The Test Diameter Application extension PROJECT("Test Diameter Application" C) # Parser files BISON_FILE(ta_conf.y) FLEX_FILE(ta_conf.l) SET_SOURCE_FILES_PROPERTIES(lex.ta_conf.c ta_conf.tab.c PROPERTIES COMPILE_FLAGS "-I ${CMAKE_CURRENT_SOURCE_DIR}") # List of source files SET( APP_TEST_SRC test_app.h test_app.c lex.ta_conf.c ta_conf.tab.c ta_conf.tab.h ta_sig.c ta_dict.c ta_cli.c ta_serv.c ) # Compile as a module FD_ADD_EXTENSION(test_app ${APP_TEST_SRC}) Souheil Ben Ayed, Sebastien Decugis March 10, 2010

34 Add extension to be loaded and build
Add extension to be loaded by freeDiameter daemon, (freeDiameter configuration file) Then generate Makefiles and Build: cmake command or cmake-gui # Extension without configuration file LoadExtension = "extensions/test_app.fdx"; # Extension with a configuration file LoadExtension = "extensions/test_app.fdx":" extensions/test_app/test_app.conf"; Souheil Ben Ayed, Sebastien Decugis March 10, 2010

35 Souheil Ben Ayed, Sebastien Decugis
Questions ??? Next >>> Demonstration Souheil Ben Ayed, Sebastien Decugis March 10, 2010


Download ppt "Implementing an extension for freeDiameter"

Similar presentations


Ads by Google