comparison libfdproto/messages.c @ 1001:d03f7e3805ad

Fix generation of the Proxy-Info AVP in fd_msg_new_answer_from_req
author Sebastien Decugis <sdecugis@freediameter.net>
date Thu, 21 Mar 2013 15:05:54 +0100
parents 2016a0c46bda
children 1b0b1ab77be5
comparison
equal deleted inserted replaced
1000:aeb202e2dbef 1001:d03f7e3805ad
300 return 0; 300 return 0;
301 } 301 }
302 302
303 static int bufferize_avp(unsigned char * buffer, size_t buflen, size_t * offset, struct avp * avp); 303 static int bufferize_avp(unsigned char * buffer, size_t buflen, size_t * offset, struct avp * avp);
304 static int parsebuf_list(unsigned char * buf, size_t buflen, struct fd_list * head); 304 static int parsebuf_list(unsigned char * buf, size_t buflen, struct fd_list * head);
305 static int parsedict_do_chain(struct dictionary * dict, struct fd_list * head, int mandatory, struct fd_pei *error_info);
306
305 307
306 /* Create answer from a request */ 308 /* Create answer from a request */
307 int fd_msg_new_answer_from_req ( struct dictionary * dict, struct msg ** msg, int flags ) 309 int fd_msg_new_answer_from_req ( struct dictionary * dict, struct msg ** msg, int flags )
308 { 310 {
309 struct dict_object * model = NULL; 311 struct dict_object * model = NULL;
363 } 365 }
364 366
365 /* Add all Proxy-Info AVPs from the query if any */ 367 /* Add all Proxy-Info AVPs from the query if any */
366 if (! (flags & MSGFL_ANSW_NOPROXYINFO)) { 368 if (! (flags & MSGFL_ANSW_NOPROXYINFO)) {
367 struct avp * avp; 369 struct avp * avp;
370 struct fd_pei pei;
371 struct fd_list avpcpylist = FD_LIST_INITIALIZER(avpcpylist);
372
368 CHECK_FCT( fd_msg_browse(qry, MSG_BRW_FIRST_CHILD, &avp, NULL) ); 373 CHECK_FCT( fd_msg_browse(qry, MSG_BRW_FIRST_CHILD, &avp, NULL) );
369 while (avp) { 374 while (avp) {
370 if ( (avp->avp_public.avp_code == AC_PROXY_INFO) 375 if ( (avp->avp_public.avp_code == AC_PROXY_INFO)
371 && (avp->avp_public.avp_vendor == 0) ) { 376 && (avp->avp_public.avp_vendor == 0) ) {
372 /* We found a Proxy-Info, need to duplicate it in the answer */ 377 /* We found a Proxy-Info, need to duplicate it in the answer */
373 378
374 /* In order to avoid dealing with all different possibilities of states, we just create a buffer then parse it */ 379 /* In order to avoid dealing with all different possibilities of states, we just create a buffer then parse it */
375 unsigned char * buf = NULL; 380 unsigned char * buf = NULL;
376 size_t offset = 0; 381 size_t offset = 0;
377 382
383 /* Create a buffer with the content of the AVP. This is easier than going through the list */
378 CHECK_FCT( fd_msg_update_length(avp) ); 384 CHECK_FCT( fd_msg_update_length(avp) );
379 CHECK_MALLOC( buf = malloc(avp->avp_public.avp_len) ); 385 CHECK_MALLOC( buf = malloc(avp->avp_public.avp_len) );
380 CHECK_FCT( bufferize_avp(buf, avp->avp_public.avp_len, &offset, avp) ); 386 CHECK_FCT( bufferize_avp(buf, avp->avp_public.avp_len, &offset, avp) );
381 387
382 /* Now we directly parse this buffer into the new message list */ 388 /* Now we parse this buffer to create a copy AVP */
383 CHECK_FCT( parsebuf_list(buf, avp->avp_public.avp_len, &ans->msg_chain.children) ); 389 CHECK_FCT( parsebuf_list(buf, avp->avp_public.avp_len, &avpcpylist) );
390
391 /* Parse dictionary objects now to remove the dependency on the buffer */
392 CHECK_FCT( parsedict_do_chain(dict, &avpcpylist, 0, &pei) );
384 393
385 /* Done for this AVP */ 394 /* Done for this AVP */
386 free(buf); 395 free(buf);
396
397 /* We move this AVP now so that we do not parse again in next loop */
398 fd_list_move_end(&ans->msg_chain.children, &avpcpylist);
387 } 399 }
388 /* move to next AVP in the message, we can have several Proxy-Info instances */ 400 /* move to next AVP in the message, we can have several Proxy-Info instances */
389 CHECK_FCT( fd_msg_browse(avp, MSG_BRW_NEXT, &avp, NULL) ); 401 CHECK_FCT( fd_msg_browse(avp, MSG_BRW_NEXT, &avp, NULL) );
390 } 402 }
391 CHECK_FCT( fd_msg_parse_dict( ans, dict, NULL ) );
392 } 403 }
393 404
394 /* associate with query */ 405 /* associate with query */
395 ans->msg_query = qry; 406 ans->msg_query = qry;
396 qry->msg_associated = 1; 407 qry->msg_associated = 1;
1555 1566
1556 if (avp->avp_model == NULL) { 1567 if (avp->avp_model == NULL) {
1557 /* In the case where we don't know the type of AVP, just copy the raw data or source */ 1568 /* In the case where we don't know the type of AVP, just copy the raw data or source */
1558 CHECK_PARAMS( avp->avp_source || avp->avp_rawdata ); 1569 CHECK_PARAMS( avp->avp_source || avp->avp_rawdata );
1559 1570
1560 if ( avp->avp_source != NULL ) { 1571 if ( avp->avp_rawdata != NULL ) {
1572 /* the content was stored in rawdata */
1573 memcpy(&buffer[*offset], avp->avp_rawdata, avp->avp_rawlen);
1574 *offset += PAD4(avp->avp_rawlen);
1575 } else {
1561 /* the message was not parsed completely */ 1576 /* the message was not parsed completely */
1562 size_t datalen = avp->avp_public.avp_len - GETAVPHDRSZ(avp->avp_public.avp_flags); 1577 size_t datalen = avp->avp_public.avp_len - GETAVPHDRSZ(avp->avp_public.avp_flags);
1563 memcpy(&buffer[*offset], avp->avp_source, datalen); 1578 memcpy(&buffer[*offset], avp->avp_source, datalen);
1564 *offset += PAD4(datalen); 1579 *offset += PAD4(datalen);
1565 } else {
1566 /* the content was stored in rawdata */
1567 memcpy(&buffer[*offset], avp->avp_rawdata, avp->avp_rawlen);
1568 *offset += PAD4(avp->avp_rawlen);
1569 } 1580 }
1570 1581
1571 } else { 1582 } else {
1572 /* The AVP is defined in the dictionary */ 1583 /* The AVP is defined in the dictionary */
1573 CHECK_FCT( fd_dict_getval(avp->avp_model, &dictdata) ); 1584 CHECK_FCT( fd_dict_getval(avp->avp_model, &dictdata) );
1810 * When the model is not found, the data is copied as rawdata and saved (in case we FW the message). 1821 * When the model is not found, the data is copied as rawdata and saved (in case we FW the message).
1811 * Therefore, after this function has been called, the source buffer can be freed. 1822 * Therefore, after this function has been called, the source buffer can be freed.
1812 * For command, if the dictionary model is not found, an error is returned. 1823 * For command, if the dictionary model is not found, an error is returned.
1813 */ 1824 */
1814 1825
1815 static int parsedict_do_chain(struct dictionary * dict, struct fd_list * head, int mandatory, struct fd_pei *error_info);
1816
1817 static char error_message[256]; 1826 static char error_message[256];
1818 1827
1819 /* Process an AVP. If we are not in recheck, the avp_source must be set. */ 1828 /* Process an AVP. If we are not in recheck, the avp_source must be set. */
1820 static int parsedict_do_avp(struct dictionary * dict, struct avp * avp, int mandatory, struct fd_pei *error_info) 1829 static int parsedict_do_avp(struct dictionary * dict, struct avp * avp, int mandatory, struct fd_pei *error_info)
1821 { 1830 {
1822 struct dict_avp_data dictdata; 1831 struct dict_avp_data dictdata;
1832 uint8_t * source;
1823 1833
1824 TRACE_ENTRY("%p %p %d %p", dict, avp, mandatory, error_info); 1834 TRACE_ENTRY("%p %p %d %p", dict, avp, mandatory, error_info);
1825 1835
1826 /* First check we received an AVP as input */ 1836 /* First check we received an AVP as input */
1827 CHECK_PARAMS( CHECK_AVP(avp) ); 1837 CHECK_PARAMS( CHECK_AVP(avp) );
1910 } 1920 }
1911 avp->avp_model = NULL; 1921 avp->avp_model = NULL;
1912 return EBADMSG; 1922 return EBADMSG;
1913 } 1923 }
1914 1924
1925 source = avp->avp_source;
1926 avp->avp_source = NULL;
1927
1915 /* Now get the value inside */ 1928 /* Now get the value inside */
1916 switch (dictdata.avp_basetype) { 1929 switch (dictdata.avp_basetype) {
1917 case AVP_TYPE_GROUPED: { 1930 case AVP_TYPE_GROUPED: {
1918 int ret; 1931 int ret;
1919 1932
1920 /* This is a grouped AVP, so let's parse the list of AVPs inside */ 1933 /* This is a grouped AVP, so let's parse the list of AVPs inside */
1921 CHECK_FCT_DO( ret = parsebuf_list(avp->avp_source, avp->avp_public.avp_len - GETAVPHDRSZ( avp->avp_public.avp_flags ), &avp->avp_chain.children), 1934 CHECK_FCT_DO( ret = parsebuf_list(source, avp->avp_public.avp_len - GETAVPHDRSZ( avp->avp_public.avp_flags ), &avp->avp_chain.children),
1922 { 1935 {
1923 if ((ret == EBADMSG) && (error_info)) { 1936 if ((ret == EBADMSG) && (error_info)) {
1924 error_info->pei_errcode = "DIAMETER_INVALID_AVP_VALUE"; 1937 error_info->pei_errcode = "DIAMETER_INVALID_AVP_VALUE";
1925 error_info->pei_avp = avp; 1938 error_info->pei_avp = avp;
1926 snprintf(error_message, sizeof(error_message), "I cannot parse this AVP as a Grouped AVP"); 1939 snprintf(error_message, sizeof(error_message), "I cannot parse this AVP as a Grouped AVP");
1927 error_info->pei_message = error_message; 1940 error_info->pei_message = error_message;
1928 } 1941 }
1942 avp->avp_source = source;
1929 return ret; 1943 return ret;
1930 } ); 1944 } );
1931 1945
1932 return parsedict_do_chain(dict, &avp->avp_chain.children, mandatory && (avp->avp_public.avp_flags & AVP_FLAG_MANDATORY), error_info); 1946 return parsedict_do_chain(dict, &avp->avp_chain.children, mandatory && (avp->avp_public.avp_flags & AVP_FLAG_MANDATORY), error_info);
1933 } 1947 }
1938 { 1952 {
1939 if (error_info) { 1953 if (error_info) {
1940 error_info->pei_errcode = "DIAMETER_INVALID_AVP_LENGTH"; 1954 error_info->pei_errcode = "DIAMETER_INVALID_AVP_LENGTH";
1941 error_info->pei_avp = avp; 1955 error_info->pei_avp = avp;
1942 } 1956 }
1957 avp->avp_source = source;
1943 return EBADMSG; 1958 return EBADMSG;
1944 } ); 1959 } );
1945 avp->avp_storage.os.len = avp->avp_public.avp_len - GETAVPHDRSZ( avp->avp_public.avp_flags ); 1960 avp->avp_storage.os.len = avp->avp_public.avp_len - GETAVPHDRSZ( avp->avp_public.avp_flags );
1946 CHECK_MALLOC( avp->avp_storage.os.data = os0dup(avp->avp_source, avp->avp_storage.os.len) ); 1961 CHECK_MALLOC( avp->avp_storage.os.data = os0dup(source, avp->avp_storage.os.len) );
1947 avp->avp_mustfreeos = 1; 1962 avp->avp_mustfreeos = 1;
1948 break; 1963 break;
1949 1964
1950 case AVP_TYPE_INTEGER32: 1965 case AVP_TYPE_INTEGER32:
1951 avp->avp_storage.i32 = (int32_t)ntohl(*(uint32_t *)avp->avp_source); 1966 avp->avp_storage.i32 = (int32_t)ntohl(*(uint32_t *)source);
1952 break; 1967 break;
1953 1968
1954 case AVP_TYPE_INTEGER64: 1969 case AVP_TYPE_INTEGER64:
1955 /* the storage might not be aligned on 64b boundary, so no direct indirection here is possible */ 1970 /* the storage might not be aligned on 64b boundary, so no direct indirection here is possible */
1956 { 1971 {
1957 uint64_t __stor; 1972 uint64_t __stor;
1958 memcpy(&__stor, avp->avp_source, sizeof(__stor)); 1973 memcpy(&__stor, source, sizeof(__stor));
1959 avp->avp_storage.i64 = (int64_t)ntohll(__stor); 1974 avp->avp_storage.i64 = (int64_t)ntohll(__stor);
1960 } 1975 }
1961 break; 1976 break;
1962 1977
1963 case AVP_TYPE_UNSIGNED32: 1978 case AVP_TYPE_UNSIGNED32:
1964 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 */ 1979 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 */
1965 avp->avp_storage.u32 = (uint32_t)ntohl(*(uint32_t *)avp->avp_source); 1980 avp->avp_storage.u32 = (uint32_t)ntohl(*(uint32_t *)source);
1966 break; 1981 break;
1967 1982
1968 case AVP_TYPE_UNSIGNED64: 1983 case AVP_TYPE_UNSIGNED64:
1969 case AVP_TYPE_FLOAT64: /* same as 32 bits */ 1984 case AVP_TYPE_FLOAT64: /* same as 32 bits */
1970 { 1985 {
1971 uint64_t __stor; 1986 uint64_t __stor;
1972 memcpy(&__stor, avp->avp_source, sizeof(__stor)); 1987 memcpy(&__stor, source, sizeof(__stor));
1973 avp->avp_storage.u64 = (uint64_t)ntohll(__stor); 1988 avp->avp_storage.u64 = (uint64_t)ntohll(__stor);
1974 } 1989 }
1975 break; 1990 break;
1976 1991
1977 } 1992 }
"Welcome to our mercurial repository"