# HG changeset patch # User Sebastien Decugis # Date 1363874843 -3600 # Node ID 7ca81c10ba06a3a722c825ce94b6a01bc6b39b04 # Parent 632913581c37be80cfa810aeff29efb8653327c7# Parent d03f7e3805ad332fc7ff7859b064d4e1e8f9a54b Merged diff -r 632913581c37 -r 7ca81c10ba06 include/freeDiameter/libfdproto.h --- a/include/freeDiameter/libfdproto.h Tue Mar 19 16:15:38 2013 +0100 +++ b/include/freeDiameter/libfdproto.h Thu Mar 21 15:07:23 2013 +0100 @@ -311,7 +311,7 @@ int fd_breakhere(void); /* Helper for tracing the CHECK_* macros below -- very very verbose code execution! */ -#define TRACE_DEBUG_ALL( str ) \ +#define TRACE_DEBUG_ALL( str... ) \ TRACE_DEBUG(CALL, str ); /* For development only, to keep track of TODO locations in the code */ @@ -478,22 +478,22 @@ /* Check the return value of a system function and execute fallback in case of error */ #define CHECK_SYS_DO( __call__, __fallback__ ) { \ int __ret__; \ - TRACE_DEBUG_ALL( "Check SYS: " #__call__ ); \ + TRACE_DEBUG_ALL( "Check SYS: %s", #__call__ ); \ __ret__ = (__call__); \ if (__ret__ < 0) { \ int __err__ = errno; /* We may handle EINTR here */ \ - TRACE_ERROR("ERROR: in '" #__call__ "' :\t%s", strerror(__err__));\ + TRACE_ERROR("ERROR: in '%s' :\t%s", #__call__ , strerror(__err__)); \ __fallback__; \ } \ } /* Check the return value of a system function, return error code on error */ #define CHECK_SYS( __call__ ) { \ int __ret__; \ - TRACE_DEBUG_ALL( "Check SYS: " #__call__ ); \ + TRACE_DEBUG_ALL( "Check SYS: %s", #__call__ ); \ __ret__ = (__call__); \ if (__ret__ < 0) { \ int __err__ = errno; /* We may handle EINTR here */ \ - TRACE_ERROR("ERROR: in '" #__call__ "' :\t%s", strerror(__err__));\ + TRACE_ERROR("ERROR: in '%s' :\t%s", #__call__ , strerror(__err__)); \ return __err__; \ } \ } @@ -501,13 +501,13 @@ /* Check the return value of a POSIX function and execute fallback in case of error or special value */ #define CHECK_POSIX_DO2( __call__, __speval__, __fallback1__, __fallback2__ ) { \ int __ret__; \ - TRACE_DEBUG_ALL( "Check POSIX: " #__call__ ); \ + TRACE_DEBUG_ALL( "Check POSIX: %s", #__call__ ); \ __ret__ = (__call__); \ if (__ret__ != 0) { \ if (__ret__ == (__speval__)) { \ __fallback1__; \ } else { \ - TRACE_ERROR("ERROR: in '" #__call__ "':\t%s", strerror(__ret__)); \ + TRACE_ERROR("ERROR: in '%s':\t%s", #__call__, strerror(__ret__)); \ __fallback2__; \ } \ } \ @@ -526,11 +526,11 @@ /* Check that a memory allocator did not return NULL, otherwise log an error and execute fallback */ #define CHECK_MALLOC_DO( __call__, __fallback__ ) { \ void * __ret__; \ - TRACE_DEBUG_ALL( "Check MALLOC: " #__call__ ); \ + TRACE_DEBUG_ALL( "Check MALLOC: %s", #__call__ ); \ __ret__ = (void *)( __call__ ); \ if (__ret__ == NULL) { \ int __err__ = errno; \ - TRACE_ERROR("ERROR: in '" #__call__ "':\t%s", strerror(__err__)); \ + TRACE_ERROR("ERROR: in '%s':\t%s", #__call__, strerror(__err__)); \ __fallback__; \ } \ } @@ -542,9 +542,9 @@ /* Check parameters at function entry, execute fallback on error */ #define CHECK_PARAMS_DO( __bool__, __fallback__ ) \ - TRACE_DEBUG_ALL( "Check PARAMS: " #__bool__ ); \ + TRACE_DEBUG_ALL( "Check PARAMS: %s", #__bool__ ); \ if ( ! (__bool__) ) { \ - TRACE_ERROR("Warning: Invalid parameter received in '" #__bool__ "'"); \ + TRACE_ERROR("Warning: Invalid parameter received in '%s'", #__bool__); \ __fallback__; \ } /* Check parameters at function entry, return EINVAL if the boolean is false (similar to assert) */ @@ -554,10 +554,10 @@ /* Check the return value of an internal function, log and propagate */ #define CHECK_FCT_DO( __call__, __fallback__ ) { \ int __ret__; \ - TRACE_DEBUG_ALL( "Check FCT: " #__call__ ); \ + TRACE_DEBUG_ALL( "Check FCT: %s", #__call__ ); \ __ret__ = (__call__); \ if (__ret__ != 0) { \ - TRACE_ERROR("ERROR: in '" #__call__ "':\t%s", strerror(__ret__)); \ + TRACE_ERROR("ERROR: in '%s':\t%s", #__call__, strerror(__ret__)); \ __fallback__; \ } \ } diff -r 632913581c37 -r 7ca81c10ba06 libfdcore/cnxctx.c --- a/libfdcore/cnxctx.c Tue Mar 19 16:15:38 2013 +0100 +++ b/libfdcore/cnxctx.c Thu Mar 21 15:07:23 2013 +0100 @@ -1207,7 +1207,7 @@ char buf[1024]; snprintf(buf, sizeof(buf), "\t - Certificate serial number: "); for (j = 0; j < size; j++) { - snprintf(buf+strlen(buf), sizeof(buf)-strlen(buf), "%02.2hhx", serial[j]); + snprintf(buf+strlen(buf), sizeof(buf)-strlen(buf), "%02hhx", serial[j]); } fd_log_debug(buf); } diff -r 632913581c37 -r 7ca81c10ba06 libfdproto/lists.c --- a/libfdproto/lists.c Tue Mar 19 16:15:38 2013 +0100 +++ b/libfdproto/lists.c Thu Mar 21 15:07:23 2013 +0100 @@ -74,12 +74,16 @@ /* Move all elements of list senti at the end of list ref */ void fd_list_move_end(struct fd_list * ref, struct fd_list * senti) { + struct fd_list * li; ASSERT(ref->head == ref); ASSERT(senti->head == senti); if (senti->next == senti) return; + for (li = senti->next; li != senti; li = li->next) + li->head = ref; + senti->next->prev = ref->prev; ref->prev->next = senti->next; senti->prev->next = ref; diff -r 632913581c37 -r 7ca81c10ba06 libfdproto/messages.c --- a/libfdproto/messages.c Tue Mar 19 16:15:38 2013 +0100 +++ b/libfdproto/messages.c Thu Mar 21 15:07:23 2013 +0100 @@ -302,6 +302,8 @@ static int bufferize_avp(unsigned char * buffer, size_t buflen, size_t * offset, struct avp * avp); static int parsebuf_list(unsigned char * buf, size_t buflen, struct fd_list * head); +static int parsedict_do_chain(struct dictionary * dict, struct fd_list * head, int mandatory, struct fd_pei *error_info); + /* Create answer from a request */ int fd_msg_new_answer_from_req ( struct dictionary * dict, struct msg ** msg, int flags ) @@ -365,6 +367,9 @@ /* Add all Proxy-Info AVPs from the query if any */ if (! (flags & MSGFL_ANSW_NOPROXYINFO)) { struct avp * avp; + struct fd_pei pei; + struct fd_list avpcpylist = FD_LIST_INITIALIZER(avpcpylist); + CHECK_FCT( fd_msg_browse(qry, MSG_BRW_FIRST_CHILD, &avp, NULL) ); while (avp) { if ( (avp->avp_public.avp_code == AC_PROXY_INFO) @@ -375,20 +380,26 @@ unsigned char * buf = NULL; size_t offset = 0; + /* Create a buffer with the content of the AVP. This is easier than going through the list */ CHECK_FCT( fd_msg_update_length(avp) ); CHECK_MALLOC( buf = malloc(avp->avp_public.avp_len) ); CHECK_FCT( bufferize_avp(buf, avp->avp_public.avp_len, &offset, avp) ); - /* Now we directly parse this buffer into the new message list */ - CHECK_FCT( parsebuf_list(buf, avp->avp_public.avp_len, &ans->msg_chain.children) ); + /* Now we parse this buffer to create a copy AVP */ + CHECK_FCT( parsebuf_list(buf, avp->avp_public.avp_len, &avpcpylist) ); + + /* Parse dictionary objects now to remove the dependency on the buffer */ + CHECK_FCT( parsedict_do_chain(dict, &avpcpylist, 0, &pei) ); /* Done for this AVP */ free(buf); + + /* We move this AVP now so that we do not parse again in next loop */ + fd_list_move_end(&ans->msg_chain.children, &avpcpylist); } /* move to next AVP in the message, we can have several Proxy-Info instances */ CHECK_FCT( fd_msg_browse(avp, MSG_BRW_NEXT, &avp, NULL) ); } - CHECK_FCT( fd_msg_parse_dict( ans, dict, NULL ) ); } /* associate with query */ @@ -1557,15 +1568,15 @@ /* In the case where we don't know the type of AVP, just copy the raw data or source */ CHECK_PARAMS( avp->avp_source || avp->avp_rawdata ); - if ( avp->avp_source != NULL ) { + if ( avp->avp_rawdata != NULL ) { + /* the content was stored in rawdata */ + memcpy(&buffer[*offset], avp->avp_rawdata, avp->avp_rawlen); + *offset += PAD4(avp->avp_rawlen); + } else { /* the message was not parsed completely */ size_t datalen = avp->avp_public.avp_len - GETAVPHDRSZ(avp->avp_public.avp_flags); memcpy(&buffer[*offset], avp->avp_source, datalen); *offset += PAD4(datalen); - } else { - /* the content was stored in rawdata */ - memcpy(&buffer[*offset], avp->avp_rawdata, avp->avp_rawlen); - *offset += PAD4(avp->avp_rawlen); } } else { @@ -1812,14 +1823,13 @@ * For command, if the dictionary model is not found, an error is returned. */ -static int parsedict_do_chain(struct dictionary * dict, struct fd_list * head, int mandatory, struct fd_pei *error_info); - static char error_message[256]; /* Process an AVP. If we are not in recheck, the avp_source must be set. */ static int parsedict_do_avp(struct dictionary * dict, struct avp * avp, int mandatory, struct fd_pei *error_info) { struct dict_avp_data dictdata; + uint8_t * source; TRACE_ENTRY("%p %p %d %p", dict, avp, mandatory, error_info); @@ -1912,13 +1922,16 @@ return EBADMSG; } + source = avp->avp_source; + avp->avp_source = NULL; + /* Now get the value inside */ switch (dictdata.avp_basetype) { case AVP_TYPE_GROUPED: { int ret; /* This is a grouped AVP, so let's parse the list of AVPs inside */ - CHECK_FCT_DO( ret = parsebuf_list(avp->avp_source, avp->avp_public.avp_len - GETAVPHDRSZ( avp->avp_public.avp_flags ), &avp->avp_chain.children), + CHECK_FCT_DO( ret = parsebuf_list(source, avp->avp_public.avp_len - GETAVPHDRSZ( avp->avp_public.avp_flags ), &avp->avp_chain.children), { if ((ret == EBADMSG) && (error_info)) { error_info->pei_errcode = "DIAMETER_INVALID_AVP_VALUE"; @@ -1926,6 +1939,7 @@ snprintf(error_message, sizeof(error_message), "I cannot parse this AVP as a Grouped AVP"); error_info->pei_message = error_message; } + avp->avp_source = source; return ret; } ); @@ -1940,36 +1954,37 @@ error_info->pei_errcode = "DIAMETER_INVALID_AVP_LENGTH"; error_info->pei_avp = avp; } + avp->avp_source = source; return EBADMSG; } ); avp->avp_storage.os.len = avp->avp_public.avp_len - GETAVPHDRSZ( avp->avp_public.avp_flags ); - CHECK_MALLOC( avp->avp_storage.os.data = os0dup(avp->avp_source, avp->avp_storage.os.len) ); + CHECK_MALLOC( avp->avp_storage.os.data = os0dup(source, avp->avp_storage.os.len) ); avp->avp_mustfreeos = 1; break; case AVP_TYPE_INTEGER32: - avp->avp_storage.i32 = (int32_t)ntohl(*(uint32_t *)avp->avp_source); + avp->avp_storage.i32 = (int32_t)ntohl(*(uint32_t *)source); break; case AVP_TYPE_INTEGER64: /* the storage might not be aligned on 64b boundary, so no direct indirection here is possible */ { uint64_t __stor; - memcpy(&__stor, avp->avp_source, sizeof(__stor)); + memcpy(&__stor, source, sizeof(__stor)); avp->avp_storage.i64 = (int64_t)ntohll(__stor); } break; case AVP_TYPE_UNSIGNED32: case AVP_TYPE_FLOAT32: /* For float, we must not cast, or the value is changed. Instead we use implicit cast by changing the member of the union */ - avp->avp_storage.u32 = (uint32_t)ntohl(*(uint32_t *)avp->avp_source); + avp->avp_storage.u32 = (uint32_t)ntohl(*(uint32_t *)source); break; case AVP_TYPE_UNSIGNED64: case AVP_TYPE_FLOAT64: /* same as 32 bits */ { uint64_t __stor; - memcpy(&__stor, avp->avp_source, sizeof(__stor)); + memcpy(&__stor, source, sizeof(__stor)); avp->avp_storage.u64 = (uint64_t)ntohll(__stor); } break; diff -r 632913581c37 -r 7ca81c10ba06 tests/tests.h --- a/tests/tests.h Tue Mar 19 16:15:38 2013 +0100 +++ b/tests/tests.h Thu Mar 21 15:07:23 2013 +0100 @@ -68,13 +68,13 @@ /* Define the macro to fail a test with a message */ #define FAILTEST( message... ){ \ TRACE_ERROR(message); \ - TRACE_NOTICE("Test %s failed", __FILE__); \ + TRACE_ERROR("FAILED: %s ", __STRIPPED_FILE__); \ exit(FAIL); \ } /* Define the macro to pass a test */ #define PASSTEST( ){ \ - TRACE_NOTICE("Test %s passed", __FILE__); \ + TRACE_NOTICE("PASS: %s", __STRIPPED_FILE__); \ (void)fd_core_shutdown(); \ (void)fd_core_wait_shutdown_complete(); \ (void)fd_thr_term(&signal_thr); \ @@ -88,16 +88,14 @@ /* Define the standard check routines */ #define CHECK( _val, _assert ){ \ if (test_verbo > 0) { \ - TRACE_DEBUG(INFO, \ - "%s:%-4d: CHECK( " #_assert " == "\ - #_val " )", \ - __FILE__, \ - __LINE__); \ + TRACE_NOTICE("CHECK( %s == %s )", \ + #_assert, \ + #_val); \ }{ \ __typeof__ (_val) __ret = (_assert); \ if (__ret != (_val)) { \ FAILTEST( "%s:%d: CHECK FAILED : %s == %lx != %lx", \ - __FILE__, \ + __STRIPPED_FILE__, \ __LINE__, \ #_assert, \ (unsigned long)__ret, \ @@ -198,7 +196,7 @@ CHECK( 0, fd_libproto_init() ); - fd_log_threadname(basename(fname)); + fd_log_threadname(fname); /* Parse the command line */ parse_cmdline(argc, argv); @@ -228,6 +226,6 @@ return; } -#define INIT_FD() test_init(argc, argv, __FILE__); +#define INIT_FD() test_init(argc, argv, __STRIPPED_FILE__) #endif /* _TESTS_H */