Mercurial > hg > freeDiameter
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 } |