# HG changeset patch # User Thomas Klausner # Date 1361444252 -3600 # Node ID 51c15f98a965cdb37be5eed7f68f6ddf88143eea # Parent ad5c976e0dc7ed0ef2b2adff2cca5a4014397aae# Parent 877592751fee97896606a70ce5277bda84eee86f merge current version from 1.1 branch (927:877592751fee). diff -r ad5c976e0dc7 -r 51c15f98a965 INSTALL.FreeBSD --- a/INSTALL.FreeBSD Thu Feb 21 11:52:53 2013 +0100 +++ b/INSTALL.FreeBSD Thu Feb 21 11:57:32 2013 +0100 @@ -8,7 +8,7 @@ cmake flex bison gnutls Then the cmake command had to look like: - cmake -DFLEX_EXECUTABLE:FILEPATH=/usr/local/bin/flex ... + cmake -DFLEX_EXECUTABLE:FILEPATH=/usr/local/bin/flex -DSCTP_USE_MAPPED_ADDRESSES:BOOL=ON ... --------------------- @@ -45,7 +45,7 @@ # cd fD-build 7) Run cmake for freeDiameter (add other flags as you see fit, see INSTALL for more details) - # /usr/local/bin/cmake -DFLEX_EXECUTABLE:FILEPATH=/usr/local/bin/flex ../freeDiameter + # /usr/local/bin/cmake -DFLEX_EXECUTABLE:FILEPATH=/usr/local/bin/flex -DSCTP_USE_MAPPED_ADDRESSES:BOOL=ON ../freeDiameter 8) Compile, optionnaly test # make diff -r ad5c976e0dc7 -r 51c15f98a965 extensions/app_radgw/rgwx_auth.c --- a/extensions/app_radgw/rgwx_auth.c Thu Feb 21 11:52:53 2013 +0100 +++ b/extensions/app_radgw/rgwx_auth.c Thu Feb 21 11:57:32 2013 +0100 @@ -457,7 +457,7 @@ if (si_len) { /* We already have the Session-Id, just use it */ - CHECK_FCT( fd_sess_fromsid ( si, si_len, session, NULL) ); + CHECK_FCT( fd_sess_fromsid_msg ( si, si_len, session, NULL) ); } else { /* Create a new Session-Id string */ @@ -495,6 +495,7 @@ value.os.len = sess_strlen; CHECK_FCT( fd_msg_avp_setvalue ( avp, &value ) ); CHECK_FCT( fd_msg_avp_add ( *diam_fw, MSG_BRW_FIRST_CHILD, avp) ); + CHECK_FCT( fd_msg_sess_set( *diam_fw, *session) ); } diff -r ad5c976e0dc7 -r 51c15f98a965 extensions/app_radgw/rgwx_sip.c --- a/extensions/app_radgw/rgwx_sip.c Thu Feb 21 11:52:53 2013 +0100 +++ b/extensions/app_radgw/rgwx_sip.c Thu Feb 21 11:57:32 2013 +0100 @@ -479,6 +479,7 @@ value.os.len = sidlen; CHECK_FCT( fd_msg_avp_setvalue ( avp, &value ) ); CHECK_FCT( fd_msg_avp_add ( *diam_fw, MSG_BRW_FIRST_CHILD, avp) ); + CHECK_FCT( fd_msg_sess_set( *diam_fw, *session) ); /* If the RADIUS Access-Request message does not diff -r ad5c976e0dc7 -r 51c15f98a965 extensions/app_sip/registrationtermination.c --- a/extensions/app_sip/registrationtermination.c Thu Feb 21 11:52:53 2013 +0100 +++ b/extensions/app_sip/registrationtermination.c Thu Feb 21 11:57:32 2013 +0100 @@ -147,15 +147,7 @@ // Create a new session { #define APP_SIP_SID_OPT "app_sip" - CHECK_FCT( fd_sess_new( &sess, fd_g_config->cnf_diamid, fd_g_config->cnf_diamid_len, (os0_t)APP_SIP_SID_OPT, CONSTSTRLEN(APP_SIP_SID_OPT) )); - os0_t sid; - size_t sidlen; - CHECK_FCT( fd_sess_getsid ( sess, &sid, &sidlen )); - CHECK_FCT( fd_msg_avp_new ( sip_dict.Session_Id, 0, &avp )); - value.os.data = sid; - value.os.len = sidlen; - CHECK_FCT( fd_msg_avp_setvalue( avp, &value )); - CHECK_FCT( fd_msg_avp_add( message, MSG_BRW_FIRST_CHILD, avp )); + CHECK_FCT( fd_msg_new_session( message, (os0_t)APP_SIP_SID_OPT, CONSTSTRLEN(APP_SIP_SID_OPT) ) ); } //Add the Auth-Application-Id diff -r ad5c976e0dc7 -r 51c15f98a965 extensions/test_app/ta_bench.c --- a/extensions/test_app/ta_bench.c Thu Feb 21 11:52:53 2013 +0100 +++ b/extensions/test_app/ta_bench.c Thu Feb 21 11:57:32 2013 +0100 @@ -121,7 +121,6 @@ struct avp * avp; union avp_value val; struct ta_mess_info * mi = NULL; - struct session *sess = NULL; TRACE_DEBUG(FULL, "Creating a new message for sending."); @@ -130,7 +129,7 @@ /* Create a new session */ #define TEST_APP_SID_OPT "app_testb" - CHECK_FCT_DO( fd_sess_new( &sess, fd_g_config->cnf_diamid, fd_g_config->cnf_diamid_len, (os0_t)TEST_APP_SID_OPT, CONSTSTRLEN(TEST_APP_SID_OPT) ), goto out ); + CHECK_FCT_DO( fd_msg_new_session( req, (os0_t)TEST_APP_SID_OPT, CONSTSTRLEN(TEST_APP_SID_OPT) ), goto out ); /* Create the random value to store with the session */ mi = malloc(sizeof(struct ta_mess_info)); @@ -143,19 +142,6 @@ /* Now set all AVPs values */ - /* Session-Id */ - { - os0_t sid; - size_t sidlen; - CHECK_FCT_DO( fd_sess_getsid ( sess, &sid, &sidlen ), goto out ); - CHECK_FCT_DO( fd_msg_avp_new ( ta_sess_id, 0, &avp ), goto out ); - val.os.data = sid; - val.os.len = sidlen; - CHECK_FCT_DO( fd_msg_avp_setvalue( avp, &val ), goto out ); - CHECK_FCT_DO( fd_msg_avp_add( req, MSG_BRW_FIRST_CHILD, avp ), goto out ); - - } - /* Set the Destination-Realm AVP */ { CHECK_FCT_DO( fd_msg_avp_new ( ta_dest_realm, 0, &avp ), goto out ); diff -r ad5c976e0dc7 -r 51c15f98a965 extensions/test_app/ta_cli.c --- a/extensions/test_app/ta_cli.c Thu Feb 21 11:52:53 2013 +0100 +++ b/extensions/test_app/ta_cli.c Thu Feb 21 11:57:32 2013 +0100 @@ -150,7 +150,8 @@ /* Create a new session */ #define TEST_APP_SID_OPT "app_test" - CHECK_FCT_DO( fd_sess_new( &sess, fd_g_config->cnf_diamid, fd_g_config->cnf_diamid_len, (os0_t)TEST_APP_SID_OPT, CONSTSTRLEN(TEST_APP_SID_OPT) ), goto out ); + CHECK_FCT_DO( fd_msg_new_session( req, (os0_t)TEST_APP_SID_OPT, CONSTSTRLEN(TEST_APP_SID_OPT) ), goto out ); + CHECK_FCT_DO( fd_msg_sess_get(fd_g_config->cnf_dict, req, &sess, NULL), goto out ); /* Create the random value to store with the session */ mi = malloc(sizeof(struct ta_mess_info)); @@ -163,19 +164,6 @@ /* Now set all AVPs values */ - /* Session-Id */ - { - os0_t sid; - size_t sidlen; - CHECK_FCT_DO( fd_sess_getsid ( sess, &sid, &sidlen ), goto out ); - CHECK_FCT_DO( fd_msg_avp_new ( ta_sess_id, 0, &avp ), goto out ); - val.os.data = sid; - val.os.len = sidlen; - CHECK_FCT_DO( fd_msg_avp_setvalue( avp, &val ), goto out ); - CHECK_FCT_DO( fd_msg_avp_add( req, MSG_BRW_FIRST_CHILD, avp ), goto out ); - - } - /* Set the Destination-Realm AVP */ { CHECK_FCT_DO( fd_msg_avp_new ( ta_dest_realm, 0, &avp ), goto out ); diff -r ad5c976e0dc7 -r 51c15f98a965 extensions/test_sip/locationinfo.c --- a/extensions/test_sip/locationinfo.c Thu Feb 21 11:52:53 2013 +0100 +++ b/extensions/test_sip/locationinfo.c Thu Feb 21 11:57:32 2013 +0100 @@ -41,7 +41,6 @@ struct dict_object * lir_model=NULL; struct msg * message=NULL; struct avp *avp=NULL; - struct session *sess=NULL; union avp_value value; //Fake values START @@ -61,15 +60,7 @@ // Create a new session { - CHECK_FCT( fd_sess_new( &sess, fd_g_config->cnf_diamid, fd_g_config->cnf_diamid_len, (os0_t)"appsip", 6 )); - os0_t sid; - size_t sidlen; - CHECK_FCT( fd_sess_getsid ( sess, &sid, &sidlen )); - CHECK_FCT( fd_msg_avp_new ( sip_dict.Session_Id, 0, &avp )); - value.os.data = sid; - value.os.len = sidlen; - CHECK_FCT( fd_msg_avp_setvalue( avp, &value )); - CHECK_FCT( fd_msg_avp_add( message, MSG_BRW_FIRST_CHILD, avp )); + CHECK_FCT( fd_msg_new_session( message, (os0_t)"appsip", CONSTSTRLEN("appsip") ) ); } //Add the Auth-Application-Id diff -r ad5c976e0dc7 -r 51c15f98a965 extensions/test_sip/locationinfosl.c --- a/extensions/test_sip/locationinfosl.c Thu Feb 21 11:52:53 2013 +0100 +++ b/extensions/test_sip/locationinfosl.c Thu Feb 21 11:57:32 2013 +0100 @@ -41,7 +41,6 @@ struct dict_object * lir_model=NULL; struct msg * message=NULL; struct avp *avp=NULL; - struct session *sess=NULL; union avp_value value; //Fake values START @@ -61,15 +60,7 @@ // Create a new session { - CHECK_FCT( fd_sess_new( &sess, fd_g_config->cnf_diamid, fd_g_config->cnf_diamid_len, (os0_t)"appsip", 6 )); - os0_t sid; - size_t sidlen; - CHECK_FCT( fd_sess_getsid ( sess, &sid, &sidlen )); - CHECK_FCT( fd_msg_avp_new ( sip_dict.Session_Id, 0, &avp )); - value.os.data = sid; - value.os.len = sidlen; - CHECK_FCT( fd_msg_avp_setvalue( avp, &value )); - CHECK_FCT( fd_msg_avp_add( message, MSG_BRW_FIRST_CHILD, avp )); + CHECK_FCT( fd_msg_new_session( message, (os0_t)"appsip", CONSTSTRLEN("appsip") ) ); } //Add the Auth-Application-Id diff -r ad5c976e0dc7 -r 51c15f98a965 extensions/test_sip/serverassignment.c --- a/extensions/test_sip/serverassignment.c Thu Feb 21 11:52:53 2013 +0100 +++ b/extensions/test_sip/serverassignment.c Thu Feb 21 11:57:32 2013 +0100 @@ -41,7 +41,6 @@ struct dict_object * sar_model=NULL; struct msg * message=NULL; struct avp *avp=NULL; - struct session *sess=NULL; union avp_value value; //Fake values START @@ -70,15 +69,7 @@ // Create a new session { - CHECK_FCT( fd_sess_new( &sess, fd_g_config->cnf_diamid, fd_g_config->cnf_diamid_len, (os0_t)"appsip", 6 )); - os0_t sid; - size_t sidlen; - CHECK_FCT( fd_sess_getsid ( sess, &sid, &sidlen )); - CHECK_FCT( fd_msg_avp_new ( sip_dict.Session_Id, 0, &avp )); - value.os.data = sid; - value.os.len = sidlen; - CHECK_FCT( fd_msg_avp_setvalue( avp, &value )); - CHECK_FCT( fd_msg_avp_add( message, MSG_BRW_FIRST_CHILD, avp )); + CHECK_FCT( fd_msg_new_session( message, (os0_t)"appsip", CONSTSTRLEN("appsip") ) ); } //Add the Auth-Application-Id diff -r ad5c976e0dc7 -r 51c15f98a965 extensions/test_sip/userauthorization.c --- a/extensions/test_sip/userauthorization.c Thu Feb 21 11:52:53 2013 +0100 +++ b/extensions/test_sip/userauthorization.c Thu Feb 21 11:57:32 2013 +0100 @@ -41,7 +41,6 @@ struct dict_object * uar_model=NULL; struct msg * message=NULL; struct avp *avp=NULL; - struct session *sess=NULL; union avp_value value; //Fake values START @@ -66,15 +65,7 @@ // Create a new session { - CHECK_FCT( fd_sess_new( &sess, fd_g_config->cnf_diamid, fd_g_config->cnf_diamid_len, (os0_t)"appsip", 6 )); - os0_t sid; - size_t sidlen; - CHECK_FCT( fd_sess_getsid ( sess, &sid, &sidlen )); - CHECK_FCT( fd_msg_avp_new ( sip_dict.Session_Id, 0, &avp )); - value.os.data = sid; - value.os.len = sidlen; - CHECK_FCT( fd_msg_avp_setvalue( avp, &value )); - CHECK_FCT( fd_msg_avp_add( message, MSG_BRW_FIRST_CHILD, avp )); + CHECK_FCT( fd_msg_new_session( message, (os0_t)"appsip", CONSTSTRLEN("appsip") ) ); } //Add the Auth-Application-Id diff -r ad5c976e0dc7 -r 51c15f98a965 include/freeDiameter/libfdproto.h --- a/include/freeDiameter/libfdproto.h Thu Feb 21 11:52:53 2013 +0100 +++ b/include/freeDiameter/libfdproto.h Thu Feb 21 11:57:32 2013 +0100 @@ -1157,6 +1157,26 @@ TYPE_OF_AVP /* "what" points to a struct dict_object containing an AVP object. */ }; +/**** + Callbacks defined in libfdproto/dictionary_functions.c file -- see that file for usage. + */ + +/* Convert an Address type AVP into a struct sockaddr_storage */ +int fd_dictfct_Address_encode(void * data, union avp_value * avp_value); +int fd_dictfct_Address_interpret(union avp_value * avp_value, void * interpreted); +char * fd_dictfct_Address_dump(union avp_value * avp_value); + +/* Display the content of an AVP of type UTF8String in the log file */ +char * fd_dictfct_UTF8String_dump(union avp_value * avp_value); + +/* For Time AVPs, map with time_t value directly */ +int fd_dictfct_Time_encode(void * data, union avp_value * avp_value); +int fd_dictfct_Time_interpret(union avp_value * avp_value, void * interpreted); +char * fd_dictfct_Time_dump(union avp_value * avp_value); + + + +/****/ /*** * API usage : @@ -1187,7 +1207,7 @@ } */ - + /* *************************************************************************** * @@ -1789,9 +1809,9 @@ * If diamId is NULL, the string is exactly the content of opt. * * RETURN VALUE: - * 0 : The session is created. + * 0 : The session is created, the initial msg refcount is 1. * EINVAL : A parameter is invalid. - * EALREADY : A session with the same name already exists (returned in *session) + * EALREADY : A session with the same name already exists (returned in *session), the msg refcount is increased. * ENOMEM : Not enough memory to complete the operation */ int fd_sess_new ( struct session ** session, DiamId_t diamid, size_t diamidlen, uint8_t * opt, size_t optlen ); @@ -2478,6 +2498,10 @@ */ int fd_msg_sess_get(struct dictionary * dict, struct msg * msg, struct session ** session, int * isnew); +/* This one is used by the libfdcore, you should use fd_msg_new_session rather than fd_sess_new, when possible */ +int fd_msg_sess_set(struct msg * msg, struct session * session); + + /***************************************/ /* Manage AVP values */ /***************************************/ diff -r ad5c976e0dc7 -r 51c15f98a965 libfdcore/dict_base_proto.c --- a/libfdcore/dict_base_proto.c Thu Feb 21 11:52:53 2013 +0100 +++ b/libfdcore/dict_base_proto.c Thu Feb 21 11:57:32 2013 +0100 @@ -44,169 +44,6 @@ /* The pointer for the global dictionary (initialized from main) */ struct dictionary * fd_g_dict = NULL; -/* The functions to encode and interpret the derived types defined in the base protocol */ - -/* Address AVP <-> struct sockaddr_storage */ -static int Address_encode(void * data, union avp_value * avp_value) -{ - sSS * ss = (sSS *) data; - uint16_t AddressType = 0; - size_t size = 0; - unsigned char * buf = NULL; - - TRACE_ENTRY("%p %p", data, avp_value); - CHECK_PARAMS( data && avp_value ); - - switch (ss->ss_family) { - case AF_INET: - { - /* We are encoding an IP address */ - sSA4 * sin = (sSA4 *)ss; - - AddressType = 1;/* see http://www.iana.org/assignments/address-family-numbers/ */ - size = 6; /* 2 for AddressType + 4 for data */ - - CHECK_MALLOC( buf = malloc(size) ); - - /* may not work because of alignment: *(uint32_t *)(buf+2) = htonl(sin->sin_addr.s_addr); */ - memcpy(buf + 2, &sin->sin_addr.s_addr, 4); - } - break; - - case AF_INET6: - { - /* We are encoding an IPv6 address */ - sSA6 * sin6 = (sSA6 *)ss; - - AddressType = 2;/* see http://www.iana.org/assignments/address-family-numbers/ */ - size = 18; /* 2 for AddressType + 16 for data */ - - CHECK_MALLOC( buf = malloc(size) ); - - /* The order is already good here */ - memcpy(buf + 2, &sin6->sin6_addr.s6_addr, 16); - } - break; - - default: - CHECK_PARAMS( AddressType = 0 ); - } - - *(uint16_t *)buf = htons(AddressType); - - avp_value->os.len = size; - avp_value->os.data = buf; - - return 0; -} - -static int Address_interpret(union avp_value * avp_value, void * interpreted) -{ - uint16_t AddressType = 0; - unsigned char * buf; - - TRACE_ENTRY("%p %p", avp_value, interpreted); - - CHECK_PARAMS( avp_value && interpreted && (avp_value->os.len >= 2) ); - - AddressType = ntohs(*(uint16_t *)avp_value->os.data); - buf = &avp_value->os.data[2]; - - switch (AddressType) { - case 1 /* IP */: - { - sSA4 * sin = (sSA4 *)interpreted; - - CHECK_PARAMS( avp_value->os.len == 6 ); - - sin->sin_family = AF_INET; - /* sin->sin_addr.s_addr = ntohl( * (uint32_t *) buf); -- may not work because of bad alignment */ - memcpy(&sin->sin_addr.s_addr, buf, 4); - } - break; - - case 2 /* IP6 */: - { - sSA6 * sin6 = (sSA6 *)interpreted; - - CHECK_PARAMS( avp_value->os.len == 18 ); - - sin6->sin6_family = AF_INET6; - memcpy(&sin6->sin6_addr.s6_addr, buf, 16); - } - break; - - default: - CHECK_PARAMS( AddressType = 0 ); - } - - return 0; -} - -/* Dump the content of an Address AVP */ -static char * Address_dump(union avp_value * avp_value) -{ - char * ret; - #define STR_LEN 1024 - union { - sSA sa; - sSS ss; - sSA4 sin; - sSA6 sin6; - } s; - uint16_t fam; - - memset(&s, 0, sizeof(s)); - - CHECK_MALLOC_DO( ret = malloc(STR_LEN), return NULL ); - - /* The first two octets represent the address family, http://www.iana.org/assignments/address-family-numbers/ */ - if (avp_value->os.len < 2) { - snprintf(ret, STR_LEN, "[invalid length: %zd]", avp_value->os.len); - return ret; - } - - /* Following octets are the address in network byte order already */ - fam = avp_value->os.data[0] << 8 | avp_value->os.data[1]; - switch (fam) { - case 1: - /* IP */ - s.sa.sa_family = AF_INET; - if (avp_value->os.len != 6) { - snprintf(ret, STR_LEN, "[invalid IP length: %zd]", avp_value->os.len); - return ret; - } - memcpy(&s.sin.sin_addr.s_addr, avp_value->os.data + 2, 4); - break; - case 2: - /* IP6 */ - s.sa.sa_family = AF_INET6; - if (avp_value->os.len != 18) { - snprintf(ret, STR_LEN, "[invalid IP6 length: %zd]", avp_value->os.len); - return ret; - } - memcpy(&s.sin6.sin6_addr.s6_addr, avp_value->os.data + 2, 16); - break; - default: - snprintf(ret, STR_LEN, "[unsupported family: 0x%hx]", fam); - return ret; - } - - { - int rc = getnameinfo(&s.sa, sSAlen(&s.sa), ret, STR_LEN, NULL, 0, NI_NUMERICHOST); - if (rc) - snprintf(ret, STR_LEN, "%s", (char *)gai_strerror(rc)); - } - - return ret; -} - -static char * UTF8String_dump(union avp_value * avp_value) -{ - return strndup((char *)avp_value->os.data, 42); /* avoid very long strings */ -} - - #define CHECK_dict_new( _type, _data, _parent, _ref ) \ @@ -294,7 +131,7 @@ defined in [IANAADFAM]. The AddressType is used to discriminate the content and format of the remaining octets. */ - struct dict_type_data data = { AVP_TYPE_OCTETSTRING, "Address" , Address_interpret , Address_encode, Address_dump }; + struct dict_type_data data = { AVP_TYPE_OCTETSTRING, "Address" , fd_dictfct_Address_interpret , fd_dictfct_Address_encode, fd_dictfct_Address_dump }; CHECK_dict_new( DICT_TYPE, &data , NULL, NULL); } @@ -313,7 +150,7 @@ SNTP [RFC4330] describes a procedure to extend the time to 2104. This procedure MUST be supported by all DIAMETER nodes. */ - struct dict_type_data data = { AVP_TYPE_OCTETSTRING, "Time" , NULL , NULL , NULL }; + struct dict_type_data data = { AVP_TYPE_OCTETSTRING, "Time" , fd_dictfct_Time_interpret , fd_dictfct_Time_encode, fd_dictfct_Time_dump }; CHECK_dict_new( DICT_TYPE, &data , NULL, NULL); } @@ -351,7 +188,7 @@ Note that the AVP Length field of an UTF8String is measured in octets, not characters. */ - struct dict_type_data data = { AVP_TYPE_OCTETSTRING, "UTF8String" , NULL , NULL , UTF8String_dump }; + struct dict_type_data data = { AVP_TYPE_OCTETSTRING, "UTF8String" , NULL , NULL , fd_dictfct_UTF8String_dump }; CHECK_dict_new( DICT_TYPE, &data , NULL, NULL); } @@ -380,7 +217,7 @@ interactions between the Diameter protocol and Internationalized Domain Name (IDNs). */ - struct dict_type_data data = { AVP_TYPE_OCTETSTRING, "DiameterIdentity" , NULL , NULL , UTF8String_dump }; + struct dict_type_data data = { AVP_TYPE_OCTETSTRING, "DiameterIdentity" , NULL , NULL , fd_dictfct_UTF8String_dump }; CHECK_dict_new( DICT_TYPE, &data , NULL, NULL); } @@ -435,7 +272,7 @@ aaa://host.example.com:6666;transport=tcp;protocol=diameter aaa://host.example.com:1813;transport=udp;protocol=radius */ - struct dict_type_data data = { AVP_TYPE_OCTETSTRING, "DiameterURI" , NULL , NULL , UTF8String_dump }; + struct dict_type_data data = { AVP_TYPE_OCTETSTRING, "DiameterURI" , NULL , NULL , fd_dictfct_UTF8String_dump }; CHECK_dict_new( DICT_TYPE, &data , NULL, NULL); } @@ -497,7 +334,7 @@ supplied rules, for example to protect the access device owner's infrastructure. */ - struct dict_type_data data = { AVP_TYPE_OCTETSTRING, "IPFilterRule" , NULL , NULL , UTF8String_dump }; + struct dict_type_data data = { AVP_TYPE_OCTETSTRING, "IPFilterRule" , NULL , NULL , fd_dictfct_UTF8String_dump }; CHECK_dict_new( DICT_TYPE, &data , NULL, NULL); } } diff -r ad5c976e0dc7 -r 51c15f98a965 libfdcore/fdd.l --- a/libfdcore/fdd.l Thu Feb 21 11:52:53 2013 +0100 +++ b/libfdcore/fdd.l Thu Feb 21 11:57:32 2013 +0100 @@ -51,7 +51,8 @@ #define YY_USER_ACTION { \ yylloc->first_column = yylloc->last_column + 1; \ yylloc->last_column = yylloc->first_column + yyleng - 1; \ - TRACE_DEBUG_ERROR("(%d:%d-%d:%d) matched rule %d, length=%d, txt='%s'\n", \ + TRACE_DEBUG_ERROR( \ + "(%d:%d-%d:%d) matched rule %d, length=%d, txt='%s'\n", \ yylloc->first_line, yylloc->first_column, \ yylloc->last_line, yylloc->last_column, \ yy_act, yyleng, yytext); \ @@ -144,7 +145,7 @@ /* Unrecognized token */ <*>[[:alnum:]]+ | /* This rule is only useful to print a complete token in error messages */ /* Unrecognized character */ -<*>. { +<*>. { TRACE_DEBUG_ERROR("Unrecognized text on line %d col %d: '%s'.\n", yylloc->first_line, yylloc->first_column, yytext); return LEX_ERROR; } diff -r ad5c976e0dc7 -r 51c15f98a965 libfdcore/fdd.y --- a/libfdcore/fdd.y Thu Feb 21 11:52:53 2013 +0100 +++ b/libfdcore/fdd.y Thu Feb 21 11:57:32 2013 +0100 @@ -327,7 +327,7 @@ } if (fd == NULL) { int ret = errno; - TRACE_DEBUG(INFO, "Unable to open extension file %s for reading: %s\n", fname, strerror(ret)); + TRACE_DEBUG_ERROR("Unable to open extension file %s for reading: %s\n", fname, strerror(ret)); yyerror (&yylloc, conf, "Error adding extension"); YYERROR; } @@ -501,7 +501,7 @@ fd = fopen($3, "r"); if (fd == NULL) { int ret = errno; - TRACE_DEBUG(INFO, "Unable to open certificate file %s for reading: %s\n", $3, strerror(ret)); + TRACE_DEBUG_ERROR("Unable to open certificate file %s for reading: %s\n", $3, strerror(ret)); yyerror (&yylloc, conf, "Error on file name"); YYERROR; } @@ -509,7 +509,7 @@ fd = fopen($5, "r"); if (fd == NULL) { int ret = errno; - TRACE_DEBUG(INFO, "Unable to open private key file %s for reading: %s\n", $5, strerror(ret)); + TRACE_DEBUG_ERROR("Unable to open private key file %s for reading: %s\n", $5, strerror(ret)); yyerror (&yylloc, conf, "Error on file name"); YYERROR; } @@ -532,7 +532,7 @@ fd = fopen($3, "rb"); if (fd == NULL) { int ret = errno; - TRACE_DEBUG(INFO, "Unable to open CA file %s for reading: %s\n", $3, strerror(ret)); + TRACE_DEBUG_ERROR("Unable to open CA file %s for reading: %s\n", $3, strerror(ret)); yyerror (&yylloc, conf, "Error on file name"); YYERROR; } @@ -572,7 +572,7 @@ fd = fopen($3, "rb"); if (fd == NULL) { int ret = errno; - TRACE_DEBUG(INFO, "Unable to open CRL file %s for reading: %s\n", $3, strerror(ret)); + TRACE_DEBUG_ERROR("Unable to open CRL file %s for reading: %s\n", $3, strerror(ret)); yyerror (&yylloc, conf, "Error on file name"); YYERROR; } @@ -615,7 +615,7 @@ conf->cnf_sec_data.prio_string, &err_pos), { yyerror (&yylloc, conf, "Error setting Priority parameter."); - fprintf(stderr, "Error at position : %s\n", err_pos); + TRACE_DEBUG_ERROR("Error at position : %s\n", err_pos); YYERROR; } ); } ; @@ -632,7 +632,7 @@ fd = fopen($3, "r"); if (fd == NULL) { int ret = errno; - TRACE_DEBUG(INFO, "Unable to open DH file %s for reading: %s\n", $3, strerror(ret)); + TRACE_DEBUG_ERROR("Unable to open DH file %s for reading: %s\n", $3, strerror(ret)); yyerror (&yylloc, conf, "Error on file name"); YYERROR; } diff -r ad5c976e0dc7 -r 51c15f98a965 libfdcore/messages.c --- a/libfdcore/messages.c Thu Feb 21 11:52:53 2013 +0100 +++ b/libfdcore/messages.c Thu Feb 21 11:57:32 2013 +0100 @@ -158,6 +158,9 @@ /* Add it to the message */ CHECK_FCT( fd_msg_avp_add( msg, MSG_BRW_FIRST_CHILD, avp ) ); + /* Save the session associated with the message */ + CHECK_FCT( fd_msg_sess_set( msg, sess) ); + /* Done! */ return 0; } @@ -283,7 +286,7 @@ if (set_e_bit) hdr->msg_flags |= CMD_FLAG_ERROR; else - hdr->msg_flags &= ! CMD_FLAG_ERROR; + hdr->msg_flags &= ~ CMD_FLAG_ERROR; } if (std_err_msg || errormsg) { diff -r ad5c976e0dc7 -r 51c15f98a965 libfdcore/peers.c --- a/libfdcore/peers.c Thu Feb 21 11:52:53 2013 +0100 +++ b/libfdcore/peers.c Thu Feb 21 11:57:32 2013 +0100 @@ -548,7 +548,7 @@ ev_data->cnx = *cnx; ev_data->validate = !found; - CHECK_FCT_DO( ret = fd_event_send(peer->p_events, FDEVP_CNX_INCOMING, sizeof(ev_data), ev_data), goto out ); + CHECK_FCT_DO( ret = fd_event_send(peer->p_events, FDEVP_CNX_INCOMING, sizeof(*ev_data), ev_data), goto out ); out: CHECK_POSIX( pthread_rwlock_unlock(&fd_g_peers_rw) ); diff -r ad5c976e0dc7 -r 51c15f98a965 libfdcore/sctp.c --- a/libfdcore/sctp.c Thu Feb 21 11:52:53 2013 +0100 +++ b/libfdcore/sctp.c Thu Feb 21 11:57:32 2013 +0100 @@ -653,7 +653,7 @@ #ifndef SCTP_USE_MAPPED_ADDRESSES if (ep->sa.sa_family == AF_INET6) #else /* SCTP_USE_MAPPED_ADDRESSES */ - if (target_family == AF_INET6) { + if (target_family == AF_INET6) #endif /* SCTP_USE_MAPPED_ADDRESSES */ sz = sizeof(sSA6); else @@ -1086,7 +1086,7 @@ /* We will loop while all data is not received. */ incomplete: - if (datasize == bufsz - sizeof(struct timespec)) { + while (datasize + sizeof(struct timespec) >= bufsz ) { /* The buffer is full, enlarge it */ bufsz += mempagesz; CHECK_MALLOC( data = realloc(data, bufsz ) ); diff -r ad5c976e0dc7 -r 51c15f98a965 libfdproto/CMakeLists.txt --- a/libfdproto/CMakeLists.txt Thu Feb 21 11:52:53 2013 +0100 +++ b/libfdproto/CMakeLists.txt Thu Feb 21 11:57:32 2013 +0100 @@ -5,6 +5,7 @@ SET(LFDPROTO_SRC fdproto-internal.h dictionary.c + dictionary_functions.c dispatch.c fifo.c init.c diff -r ad5c976e0dc7 -r 51c15f98a965 libfdproto/dictionary_functions.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libfdproto/dictionary_functions.c Thu Feb 21 11:57:32 2013 +0100 @@ -0,0 +1,331 @@ +/********************************************************************************************************* +* Software License Agreement (BSD License) * +* Author: Sebastien Decugis * +* * +* Copyright (c) 2013, 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. * +*********************************************************************************************************/ + +#include "fdproto-internal.h" + +/* This file contains helpers functions to be reused as callbacks in the struct dict_type_data structure. +There are three callbacks there: + + - type_encode : + - type_interpret : + Those two callbacks allow to manipulate more natural structures of data in the code, and to + map transparently these natural structures with the AVP-encoded format by calling the functions + msg_avp_value_encode or msg_avp_value_interpret. + - type_dump : + This callback if provided gives a more human-readable debug information. + + */ + +/****************************/ +/* Address AVP type */ +/****************************/ + +/* The interpret and encode functions work with a "struct sockaddr_storage" pointer for mapping +the contents of the AVP */ + +int fd_dictfct_Address_encode(void * data, union avp_value * avp_value) +{ + sSS * ss = (sSS *) data; + uint16_t AddressType = 0; + size_t size = 0; + unsigned char * buf = NULL; + + TRACE_ENTRY("%p %p", data, avp_value); + CHECK_PARAMS( data && avp_value ); + + switch (ss->ss_family) { + case AF_INET: + { + /* We are encoding an IP address */ + sSA4 * sin = (sSA4 *)ss; + + AddressType = 1;/* see http://www.iana.org/assignments/address-family-numbers/ */ + size = 6; /* 2 for AddressType + 4 for data */ + + CHECK_MALLOC( buf = malloc(size) ); + + /* may not work because of alignment: *(uint32_t *)(buf+2) = htonl(sin->sin_addr.s_addr); */ + memcpy(buf + 2, &sin->sin_addr.s_addr, 4); + } + break; + + case AF_INET6: + { + /* We are encoding an IPv6 address */ + sSA6 * sin6 = (sSA6 *)ss; + + AddressType = 2;/* see http://www.iana.org/assignments/address-family-numbers/ */ + size = 18; /* 2 for AddressType + 16 for data */ + + CHECK_MALLOC( buf = malloc(size) ); + + /* The order is already good here */ + memcpy(buf + 2, &sin6->sin6_addr.s6_addr, 16); + } + break; + + default: + CHECK_PARAMS( AddressType = 0 ); + } + + *(uint16_t *)buf = htons(AddressType); + + avp_value->os.len = size; + avp_value->os.data = buf; + + return 0; +} + +int fd_dictfct_Address_interpret(union avp_value * avp_value, void * interpreted) +{ + uint16_t AddressType = 0; + unsigned char * buf; + + TRACE_ENTRY("%p %p", avp_value, interpreted); + + CHECK_PARAMS( avp_value && interpreted && (avp_value->os.len >= 2) ); + + AddressType = ntohs(*(uint16_t *)avp_value->os.data); + buf = &avp_value->os.data[2]; + + switch (AddressType) { + case 1 /* IP */: + { + sSA4 * sin = (sSA4 *)interpreted; + + CHECK_PARAMS( avp_value->os.len == 6 ); + + sin->sin_family = AF_INET; + /* sin->sin_addr.s_addr = ntohl( * (uint32_t *) buf); -- may not work because of bad alignment */ + memcpy(&sin->sin_addr.s_addr, buf, 4); + } + break; + + case 2 /* IP6 */: + { + sSA6 * sin6 = (sSA6 *)interpreted; + + CHECK_PARAMS( avp_value->os.len == 18 ); + + sin6->sin6_family = AF_INET6; + memcpy(&sin6->sin6_addr.s6_addr, buf, 16); + } + break; + + default: + CHECK_PARAMS( AddressType = 0 ); + } + + return 0; +} + +/* Dump the content of an Address AVP */ +char * fd_dictfct_Address_dump(union avp_value * avp_value) +{ + char * ret; + #define STR_LEN 1024 + union { + sSA sa; + sSS ss; + sSA4 sin; + sSA6 sin6; + } s; + uint16_t fam; + + memset(&s, 0, sizeof(s)); + + CHECK_MALLOC_DO( ret = malloc(STR_LEN), return NULL ); + + /* The first two octets represent the address family, http://www.iana.org/assignments/address-family-numbers/ */ + if (avp_value->os.len < 2) { + snprintf(ret, STR_LEN, "[invalid length: %zd]", avp_value->os.len); + return ret; + } + + /* Following octets are the address in network byte order already */ + fam = avp_value->os.data[0] << 8 | avp_value->os.data[1]; + switch (fam) { + case 1: + /* IP */ + s.sa.sa_family = AF_INET; + if (avp_value->os.len != 6) { + snprintf(ret, STR_LEN, "[invalid IP length: %zd]", avp_value->os.len); + return ret; + } + memcpy(&s.sin.sin_addr.s_addr, avp_value->os.data + 2, 4); + break; + case 2: + /* IP6 */ + s.sa.sa_family = AF_INET6; + if (avp_value->os.len != 18) { + snprintf(ret, STR_LEN, "[invalid IP6 length: %zd]", avp_value->os.len); + return ret; + } + memcpy(&s.sin6.sin6_addr.s6_addr, avp_value->os.data + 2, 16); + break; + default: + snprintf(ret, STR_LEN, "[unsupported family: 0x%hx]", fam); + return ret; + } + + { + int rc = getnameinfo(&s.sa, sSAlen(&s.sa), ret, STR_LEN, NULL, 0, NI_NUMERICHOST); + if (rc) + snprintf(ret, STR_LEN, "%s", (char *)gai_strerror(rc)); + } + + return ret; +} + + + +/*******************************/ +/* UTF8String AVP type */ +/*******************************/ + +/* Dump the AVP in a natural human-readable format */ +char * fd_dictfct_UTF8String_dump(union avp_value * avp_value) +{ +#define TRUNC_LEN 42 /* avoid very long strings */ + char * ret = strndup((char *)avp_value->os.data, TRUNC_LEN); + if (ret && (*ret != '\0')) { + /* We sanitize the returned string to avoid UTF8 boundary problem. + We do this whether the string is trucated at TRUNC_LEN or not, to avoid potential problem + with malformed AVP */ + + char * end = strchr(ret, '\0'); + + while (end > ret) { + end--; + char b = *end; + /* after the position pointed by end, we have only \0s */ + if ((b & 0x80) == 0) { + break; /* this is a single byte char, no problem */ + } else { + /* this byte is start or cont. of multibyte sequence, as we do not know the next byte we need to delete it. */ + *end = '\0'; + if (b & 0x40) + break; /* This was a start byte, we can stop the loop */ + } + } + } + return ret; +} + + +/*******************************/ +/* Time AVP type */ +/*******************************/ + +/* The interpret and encode functions work with a "time_t" pointer for mapping +the contents of the AVP */ + +/* Unix Epoch starts 1970-01-01, NTP 0 is at 1900-01-01 */ +#define DIFF_EPOCH_TO_NTP ((365*(1970-1900) + 17ul) * 24 * 60 * 60) + +static int diameter_string_to_time_t(const char *str, size_t len, time_t *result) { + time_t time_stamp; + CHECK_PARAMS(len == 4); + + time_stamp = (((unsigned long)(str[0]&0xff))<<24) + ((str[1]&0xff)<<16) + ((str[2]&0xff)<<8) + ((str[3]&0xff)); + time_stamp -= DIFF_EPOCH_TO_NTP; +#ifdef FIX__NEEDED_FOR_YEAR_2036_AND_LATER +/* NTP overflows in 2036; after that, values start at zero again */ +#define NTP_OVERFLOW_CORRECTION (0x100000000ull) + /* XXX: debug and find correct conversion */ + if (str[0] & 0x80 == 0x00) { + time_stamp += NTP_OVERFLOW_CORRECTION; + } +#endif + *result = time_stamp; + return 0; +} + +static int time_t_to_diameter_string(time_t time_stamp, char **result) { + uint64_t out = time_stamp; + char *conv; + /* XXX: 2036 fix */ + out += DIFF_EPOCH_TO_NTP; + CHECK_PARAMS( (out & 0xffffffff00000000) == 0); + + CHECK_MALLOC(conv=(char *)malloc(5)); + + conv[0] = (out>>24) & 0xff; + conv[1] = (out>>16) & 0xff; + conv[2] = (out>> 8) & 0xff; + conv[3] = out & 0xff; + conv[4] = '\0'; + *result = conv; + return 0; +} + +int fd_dictfct_Time_encode(void * data, union avp_value * avp_value) +{ + char * buf; + size_t len; + + TRACE_ENTRY("%p %p", data, avp_value); + CHECK_PARAMS( data && avp_value ); + + CHECK_FCT( time_t_to_diameter_string( *((time_t *)data), &buf) ); + /* FIXME: return len from the function above? */ len = 4; + + avp_value->os.len = len; + avp_value->os.data = buf; + return 0; +} + +int fd_dictfct_Time_interpret(union avp_value * avp_value, void * interpreted) +{ + TRACE_ENTRY("%p %p", avp_value, interpreted); + + CHECK_PARAMS( avp_value && interpreted ); + + return diameter_string_to_time_t(avp_value->os.data, avp_value->os.len, interpreted); +} + +char * fd_dictfct_Time_dump(union avp_value * avp_value) +{ + char * ret; + CHECK_MALLOC_DO( ret = malloc(STR_LEN), return NULL ); + if (avp_value->os.len != 4) { + snprintf(ret, STR_LEN, "[invalid length: %zd]", avp_value->os.len); + return ret; + } + /* TODO: display the time as human-readable */ + snprintf(ret, STR_LEN, "[TODO Time dump: 0x%02hhx%02hhx%02hhx%02hhx]", avp_value->os.data[0], avp_value->os.data[1], avp_value->os.data[2], avp_value->os.data[3]); + return ret; +} + diff -r ad5c976e0dc7 -r 51c15f98a965 libfdproto/fdproto-internal.h --- a/libfdproto/fdproto-internal.h Thu Feb 21 11:52:53 2013 +0100 +++ b/libfdproto/fdproto-internal.h Thu Feb 21 11:57:32 2013 +0100 @@ -69,6 +69,7 @@ int fd_sess_ref_msg ( struct session * session ); int fd_sess_reclaim_msg ( struct session ** session ); + /* For dump routines into string buffers */ #include static __inline__ int dump_init_str(char **outstr, size_t *offset, size_t *outlen) diff -r ad5c976e0dc7 -r 51c15f98a965 libfdproto/messages.c --- a/libfdproto/messages.c Thu Feb 21 11:52:53 2013 +0100 +++ b/libfdproto/messages.c Thu Feb 21 11:57:32 2013 +0100 @@ -105,7 +105,7 @@ /* Macro to cast a msg_avp_t */ #define _A(_x) ((struct avp *)(_x)) /* Check the type and eyecatcher */ -#define CHECK_AVP(_x) ((_C(_x)->type == MSG_AVP) && (_A(_x)->avp_eyec == MSG_AVP_EYEC)) +#define CHECK_AVP(_x) ((_x) && (_C(_x)->type == MSG_AVP) && (_A(_x)->avp_eyec == MSG_AVP_EYEC)) /* The following structure represents an instance of a message (command and children AVPs). */ struct msg { @@ -238,7 +238,7 @@ new->avp_rawlen = (*avp)->avp_public.avp_len - GETAVPHDRSZ( (*avp)->avp_public.avp_flags ); if (new->avp_rawlen) { CHECK_MALLOC( new->avp_rawdata = malloc(new->avp_rawlen) ); - memset(new->avp_rawdata, 0xFF, new->avp_rawlen); + memset(new->avp_rawdata, 0x00, new->avp_rawlen); } } @@ -1215,6 +1215,20 @@ return 0; } +/* Associate a session with a message, use only when the session was just created */ +int fd_msg_sess_set(struct msg * msg, struct session * session) +{ + TRACE_ENTRY("%p %p", msg, session); + + /* Check we received valid parameters */ + CHECK_PARAMS( CHECK_MSG(msg) ); + CHECK_PARAMS( session ); + CHECK_PARAMS( msg->msg_sess == NULL ); + + msg->msg_sess = session; + return 0; +} + /* Retrieve the session of the message */ int fd_msg_sess_get(struct dictionary * dict, struct msg * msg, struct session ** session, int * new) @@ -1260,8 +1274,13 @@ ASSERT( avp->avp_public.avp_value ); /* Resolve the session and we are done */ - CHECK_FCT( fd_sess_fromsid_msg ( avp->avp_public.avp_value->os.data, avp->avp_public.avp_value->os.len, &msg->msg_sess, new) ); - *session = msg->msg_sess; + if (avp->avp_public.avp_value->os.len > 0) { + CHECK_FCT( fd_sess_fromsid_msg ( avp->avp_public.avp_value->os.data, avp->avp_public.avp_value->os.len, &msg->msg_sess, new) ); + *session = msg->msg_sess; + } else { + TRACE_DEBUG(FULL, "Session-Id AVP with 0-byte length found in message %p", msg); + *session = NULL; + } return 0; } @@ -1647,7 +1666,7 @@ while (offset < buflen) { struct avp * avp; - if (buflen - offset <= AVPHDRSZ_NOVEND) { + if (buflen - offset < AVPHDRSZ_NOVEND) { TRACE_DEBUG(INFO, "truncated buffer: remaining only %d bytes", buflen - offset); return EBADMSG; } @@ -1665,7 +1684,7 @@ offset += 8; if (avp->avp_public.avp_flags & AVP_FLAG_VENDOR) { - if (buflen - offset <= 4) { + if (buflen - offset < 4) { TRACE_DEBUG(INFO, "truncated buffer: remaining only %d bytes for vendor and data", buflen - offset); free(avp); return EBADMSG; @@ -1675,7 +1694,8 @@ } /* Check there is enough remaining data in the buffer */ - if (buflen - offset < avp->avp_public.avp_len - GETAVPHDRSZ(avp->avp_public.avp_flags)) { + if ( (avp->avp_public.avp_len > GETAVPHDRSZ(avp->avp_public.avp_flags)) + && (buflen - offset < avp->avp_public.avp_len - GETAVPHDRSZ(avp->avp_public.avp_flags))) { TRACE_DEBUG(INFO, "truncated buffer: remaining only %d bytes for data, and avp data size is %d", buflen - offset, avp->avp_public.avp_len - GETAVPHDRSZ(avp->avp_public.avp_flags)); diff -r ad5c976e0dc7 -r 51c15f98a965 libfdproto/sessions.c --- a/libfdproto/sessions.c Thu Feb 21 11:52:53 2013 +0100 +++ b/libfdproto/sessions.c Thu Feb 21 11:57:32 2013 +0100 @@ -359,7 +359,7 @@ -/* Create a new session object with the default timeout value, and link it */ +/* Create a new session object with the default timeout value, and link it. The refcount is increased by 1, whether the session existed or not */ int fd_sess_new ( struct session ** session, DiamId_t diamid, size_t diamidlen, uint8_t * opt, size_t optlen ) { os0_t sid = NULL; @@ -460,16 +460,22 @@ } ); fd_list_insert_before(li, &sess->chain_h); /* hash table */ + sess->msg_cnt++; } else { free(sid); + + CHECK_POSIX( pthread_mutex_lock(&(*session)->stlock) ); + (*session)->msg_cnt++; + CHECK_POSIX( pthread_mutex_unlock(&(*session)->stlock) ); + /* it was found: was it previously destroyed? */ if ((*session)->is_destroyed == 0) { ret = EALREADY; goto out; } else { /* the session was marked destroyed, let's re-activate it. */ - TODO("Re-creating a deleted session. Should investigate if this can lead to an issue... (need more feedback)"); sess = *session; + sess->is_destroyed = 0; /* update the expiry time */ CHECK_SYS_DO( clock_gettime(CLOCK_REALTIME, &sess->timeout), { ASSERT(0); } ); @@ -500,7 +506,7 @@ CHECK_POSIX_DO( pthread_mutex_unlock( &exp_lock ), { ASSERT(0); } ); /* if it fails, we might not pop the cleanup handler, but this should not happen -- and we'd have a serious problem otherwise */ out: - ; + ; pthread_cleanup_pop(0); CHECK_POSIX( pthread_mutex_unlock( H_LOCK(hash) ) ); @@ -511,8 +517,8 @@ return 0; } -/* Find or create a session */ -int fd_sess_fromsid ( uint8_t * sid, size_t len, struct session ** session, int * new) +/* Find or create a session -- the msg refcount is increased */ +int fd_sess_fromsid_msg ( uint8_t * sid, size_t len, struct session ** session, int * new) { int ret; @@ -801,17 +807,19 @@ } /* For the messages module */ -int fd_sess_fromsid_msg ( uint8_t * sid, size_t len, struct session ** session, int * new) +int fd_sess_fromsid ( uint8_t * sid, size_t len, struct session ** session, int * new) { TRACE_ENTRY("%p %zd %p %p", sid, len, session, new); CHECK_PARAMS( sid && len && session ); /* Get the session object */ - CHECK_FCT( fd_sess_fromsid ( sid, len, session, new) ); + CHECK_FCT( fd_sess_fromsid_msg ( sid, len, session, new) ); - /* Increase count */ - CHECK_FCT( fd_sess_ref_msg ( *session ) ); - + /* Decrease the refcount */ + CHECK_POSIX( pthread_mutex_lock(&(*session)->stlock) ); + (*session)->msg_cnt--; /* was increased in fd_sess_new */ + CHECK_POSIX( pthread_mutex_unlock(&(*session)->stlock) ); + /* Done */ return 0; } @@ -832,16 +840,27 @@ int fd_sess_reclaim_msg ( struct session ** session ) { int reclaim; + uint32_t hash; TRACE_ENTRY("%p", session); CHECK_PARAMS( session && VALIDATE_SI(*session) ); + /* Lock the hash line to avoid possibility that session is freed while we are reclaiming */ + hash = (*session)->hash; + CHECK_POSIX( pthread_mutex_lock( H_LOCK(hash)) ); + pthread_cleanup_push( fd_cleanup_mutex, H_LOCK(hash) ); + /* Update the msg refcount */ CHECK_POSIX( pthread_mutex_lock(&(*session)->stlock) ); reclaim = (*session)->msg_cnt; (*session)->msg_cnt = reclaim - 1; CHECK_POSIX( pthread_mutex_unlock(&(*session)->stlock) ); + /* Ok, now unlock the hash line */ + pthread_cleanup_pop( 0 ); + CHECK_POSIX( pthread_mutex_unlock( H_LOCK(hash) ) ); + + /* and reclaim if no message references the session anymore */ if (reclaim == 1) { CHECK_FCT(fd_sess_reclaim ( session )); } else {