comparison libfreeDiameter/messages.c @ 114:5b3868944e2b

Reporting errors in parse_dict function
author Sebastien Decugis <sdecugis@nict.go.jp>
date Tue, 08 Dec 2009 16:55:18 +0900
parents 6a294d977878
children 4e49c086d2c4
comparison
equal deleted inserted replaced
113:2cf9f62cdcc7 114:5b3868944e2b
154 }; 154 };
155 #define CHECK_BASETYPE( _type ) ( ((_type) <= AVP_TYPE_MAX) && ((_type) >= 0) ) 155 #define CHECK_BASETYPE( _type ) ( ((_type) <= AVP_TYPE_MAX) && ((_type) >= 0) )
156 #define GETINITIALSIZE( _type, _vend ) (avp_value_sizes[ CHECK_BASETYPE(_type) ? (_type) : 0] + GETAVPHDRSZ(_vend)) 156 #define GETINITIALSIZE( _type, _vend ) (avp_value_sizes[ CHECK_BASETYPE(_type) ? (_type) : 0] + GETAVPHDRSZ(_vend))
157 157
158 /* Forward declaration */ 158 /* Forward declaration */
159 static int parsedict_do_msg(struct dictionary * dict, struct msg * msg, int only_hdr); 159 static int parsedict_do_msg(struct dictionary * dict, struct msg * msg, int only_hdr, struct fd_pei *error_info);
160 160
161 /***************************************************************************************************************/ 161 /***************************************************************************************************************/
162 /* Creating objects */ 162 /* Creating objects */
163 163
164 /* Initialize a msg_avp_chain structure */ 164 /* Initialize a msg_avp_chain structure */
304 if (flags & MSGFL_ANSW_ERROR) { 304 if (flags & MSGFL_ANSW_ERROR) {
305 /* The model is the generic error format */ 305 /* The model is the generic error format */
306 CHECK_FCT( fd_dict_get_error_cmd(dict, &model) ); 306 CHECK_FCT( fd_dict_get_error_cmd(dict, &model) );
307 } else { 307 } else {
308 /* The model is the answer corresponding to the query. It supposes that these are defined in the dictionary */ 308 /* The model is the answer corresponding to the query. It supposes that these are defined in the dictionary */
309 CHECK_FCT_DO( parsedict_do_msg( dict, qry, 1), /* continue */ ); 309 CHECK_FCT_DO( parsedict_do_msg( dict, qry, 1, NULL), /* continue */ );
310 if (qry->msg_model) { 310 if (qry->msg_model) {
311 CHECK_FCT( fd_dict_search ( dict, DICT_COMMAND, CMD_ANSWER, qry->msg_model, &model, EINVAL ) ); 311 CHECK_FCT( fd_dict_search ( dict, DICT_COMMAND, CMD_ANSWER, qry->msg_model, &model, EINVAL ) );
312 } 312 }
313 } 313 }
314 314
548 *avp = nextavp; 548 *avp = nextavp;
549 549
550 if (avp && nextavp) { 550 if (avp && nextavp) {
551 struct dictionary * dict; 551 struct dictionary * dict;
552 CHECK_FCT( fd_dict_getdict( what, &dict) ); 552 CHECK_FCT( fd_dict_getdict( what, &dict) );
553 CHECK_FCT_DO( fd_msg_parse_dict( nextavp, dict ), /* nothing */ ); 553 CHECK_FCT_DO( fd_msg_parse_dict( nextavp, dict, NULL ), /* nothing */ );
554 } 554 }
555 555
556 if (avp || nextavp) 556 if (avp || nextavp)
557 return 0; 557 return 0;
558 else 558 else
1190 *session = NULL; 1190 *session = NULL;
1191 return 0; 1191 return 0;
1192 } 1192 }
1193 1193
1194 if (!avp->avp_model) { 1194 if (!avp->avp_model) {
1195 CHECK_FCT( fd_msg_parse_dict ( avp, dict ) ); 1195 CHECK_FCT( fd_msg_parse_dict ( avp, dict, NULL ) );
1196 } 1196 }
1197 1197
1198 ASSERT( avp->avp_public.avp_value ); 1198 ASSERT( avp->avp_public.avp_value );
1199 1199
1200 /* Resolve the session and we are done */ 1200 /* Resolve the session and we are done */
1693 * When the model is not found, the data is copied as rawdata and saved (in case we FW the message). 1693 * When the model is not found, the data is copied as rawdata and saved (in case we FW the message).
1694 * Therefore, after this function has been called, the source buffer can be freed. 1694 * Therefore, after this function has been called, the source buffer can be freed.
1695 * For command, if the dictionary model is not found, an error is returned. 1695 * For command, if the dictionary model is not found, an error is returned.
1696 */ 1696 */
1697 1697
1698 static int parsedict_do_chain(struct dictionary * dict, struct fd_list * head, int mandatory); 1698 static int parsedict_do_chain(struct dictionary * dict, struct fd_list * head, int mandatory, struct fd_pei *error_info);
1699 1699
1700 /* Process an AVP. If we are not in recheck, the avp_source must be set. */ 1700 /* Process an AVP. If we are not in recheck, the avp_source must be set. */
1701 static int parsedict_do_avp(struct dictionary * dict, struct avp * avp, int mandatory) 1701 static int parsedict_do_avp(struct dictionary * dict, struct avp * avp, int mandatory, struct fd_pei *error_info)
1702 { 1702 {
1703 struct dict_avp_data dictdata; 1703 struct dict_avp_data dictdata;
1704 1704
1705 TRACE_ENTRY("%p %p %d", dict, avp, mandatory); 1705 TRACE_ENTRY("%p %p %d %p", dict, avp, mandatory, error_info);
1706 1706
1707 /* First check we received an AVP as input */ 1707 /* First check we received an AVP as input */
1708 CHECK_PARAMS( CHECK_AVP(avp) ); 1708 CHECK_PARAMS( CHECK_AVP(avp) );
1709 1709
1710 if (avp->avp_model != NULL) { 1710 if (avp->avp_model != NULL) {
1712 1712
1713 CHECK_FCT( fd_dict_getval(avp->avp_model, &dictdata) ); 1713 CHECK_FCT( fd_dict_getval(avp->avp_model, &dictdata) );
1714 1714
1715 if ( avp->avp_public.avp_code == dictdata.avp_code ) { 1715 if ( avp->avp_public.avp_code == dictdata.avp_code ) {
1716 /* Ok then just process the children if any */ 1716 /* Ok then just process the children if any */
1717 return parsedict_do_chain(dict, &avp->avp_chain.children, mandatory && (avp->avp_public.avp_flags & AVP_FLAG_MANDATORY)); 1717 return parsedict_do_chain(dict, &avp->avp_chain.children, mandatory && (avp->avp_public.avp_flags & AVP_FLAG_MANDATORY), error_info);
1718 } else { 1718 } else {
1719 /* We just erase the old model */ 1719 /* We just erase the old model */
1720 avp->avp_model = NULL; 1720 avp->avp_model = NULL;
1721 } 1721 }
1722 } 1722 }
1736 if (!avp->avp_model) { 1736 if (!avp->avp_model) {
1737 1737
1738 if (mandatory && (avp->avp_public.avp_flags & AVP_FLAG_MANDATORY)) { 1738 if (mandatory && (avp->avp_public.avp_flags & AVP_FLAG_MANDATORY)) {
1739 TRACE_DEBUG(INFO, "Unsupported mandatory AVP found:"); 1739 TRACE_DEBUG(INFO, "Unsupported mandatory AVP found:");
1740 msg_dump_intern(INFO, avp, 2); 1740 msg_dump_intern(INFO, avp, 2);
1741 if (error_info) {
1742 error_info->pei_errcode = "DIAMETER_AVP_UNSUPPORTED";
1743 error_info->pei_avp = avp;
1744 }
1741 return ENOTSUP; 1745 return ENOTSUP;
1742 } 1746 }
1743 1747
1744 if (avp->avp_source) { 1748 if (avp->avp_source) {
1745 /* we must copy the data from the source to the internal buffer area */ 1749 /* we must copy the data from the source to the internal buffer area */
1771 ASSERT(CHECK_BASETYPE(dictdata.avp_basetype)); 1775 ASSERT(CHECK_BASETYPE(dictdata.avp_basetype));
1772 1776
1773 /* Check the size is valid */ 1777 /* Check the size is valid */
1774 if ((avp_value_sizes[dictdata.avp_basetype] != 0) && 1778 if ((avp_value_sizes[dictdata.avp_basetype] != 0) &&
1775 (avp->avp_public.avp_len - GETAVPHDRSZ( avp->avp_public.avp_flags ) != avp_value_sizes[dictdata.avp_basetype])) { 1779 (avp->avp_public.avp_len - GETAVPHDRSZ( avp->avp_public.avp_flags ) != avp_value_sizes[dictdata.avp_basetype])) {
1776 TRACE_DEBUG(INFO, "The AVP size is not suitable for the type. EBADMSG."); 1780 TRACE_DEBUG(INFO, "The AVP size is not suitable for the type.");
1781 if (error_info) {
1782 error_info->pei_errcode = "DIAMETER_INVALID_AVP_LENGTH";
1783 error_info->pei_avp = avp;
1784 }
1777 return EBADMSG; 1785 return EBADMSG;
1778 } 1786 }
1779 1787
1780 /* Now get the value inside */ 1788 /* Now get the value inside */
1781 switch (dictdata.avp_basetype) { 1789 switch (dictdata.avp_basetype) {
1782 case AVP_TYPE_GROUPED: 1790 case AVP_TYPE_GROUPED: {
1791 int ret;
1792
1783 /* This is a grouped AVP, so let's parse the list of AVPs inside */ 1793 /* This is a grouped AVP, so let's parse the list of AVPs inside */
1784 CHECK_FCT( parsebuf_list(avp->avp_source, avp->avp_public.avp_len - GETAVPHDRSZ( avp->avp_public.avp_flags ), &avp->avp_chain.children) ); 1794 CHECK_FCT_DO( ret = parsebuf_list(avp->avp_source, avp->avp_public.avp_len - GETAVPHDRSZ( avp->avp_public.avp_flags ), &avp->avp_chain.children),
1785 1795 {
1786 return parsedict_do_chain(dict, &avp->avp_chain.children, mandatory && (avp->avp_public.avp_flags & AVP_FLAG_MANDATORY)); 1796 if ((ret == EBADMSG) && (error_info)) {
1797 error_info->pei_errcode = "DIAMETER_INVALID_AVP_VALUE";
1798 error_info->pei_avp = avp;
1799 }
1800 return ret;
1801 } );
1802
1803 return parsedict_do_chain(dict, &avp->avp_chain.children, mandatory && (avp->avp_public.avp_flags & AVP_FLAG_MANDATORY), error_info);
1804 }
1787 1805
1788 case AVP_TYPE_OCTETSTRING: 1806 case AVP_TYPE_OCTETSTRING:
1789 /* We just have to copy the string into the storage area */ 1807 /* We just have to copy the string into the storage area */
1790 CHECK_PARAMS( avp->avp_public.avp_len > GETAVPHDRSZ( avp->avp_public.avp_flags ) ); 1808 CHECK_PARAMS_DO( avp->avp_public.avp_len > GETAVPHDRSZ( avp->avp_public.avp_flags ),
1809 {
1810 if (error_info) {
1811 error_info->pei_errcode = "DIAMETER_INVALID_AVP_LENGTH";
1812 error_info->pei_avp = avp;
1813 }
1814 return EBADMSG;
1815 } );
1791 avp->avp_storage.os.len = avp->avp_public.avp_len - GETAVPHDRSZ( avp->avp_public.avp_flags ); 1816 avp->avp_storage.os.len = avp->avp_public.avp_len - GETAVPHDRSZ( avp->avp_public.avp_flags );
1792 CHECK_MALLOC( avp->avp_storage.os.data = malloc(avp->avp_storage.os.len) ); 1817 CHECK_MALLOC( avp->avp_storage.os.data = malloc(avp->avp_storage.os.len) );
1793 avp->avp_mustfreeos = 1; 1818 avp->avp_mustfreeos = 1;
1794 memcpy(avp->avp_storage.os.data, avp->avp_source, avp->avp_storage.os.len); 1819 memcpy(avp->avp_storage.os.data, avp->avp_source, avp->avp_storage.os.len);
1795 break; 1820 break;
1818 avp->avp_public.avp_value = &avp->avp_storage; 1843 avp->avp_public.avp_value = &avp->avp_storage;
1819 return 0; 1844 return 0;
1820 } 1845 }
1821 1846
1822 /* Process a list of AVPs */ 1847 /* Process a list of AVPs */
1823 static int parsedict_do_chain(struct dictionary * dict, struct fd_list * head, int mandatory) 1848 static int parsedict_do_chain(struct dictionary * dict, struct fd_list * head, int mandatory, struct fd_pei *error_info)
1824 { 1849 {
1825 struct fd_list * avpch; 1850 struct fd_list * avpch;
1826 1851
1827 TRACE_ENTRY("%p %p %d", dict, head, mandatory); 1852 TRACE_ENTRY("%p %p %d %p", dict, head, mandatory, error_info);
1828 1853
1829 /* Sanity check */ 1854 /* Sanity check */
1830 ASSERT ( head == head->head ); 1855 ASSERT ( head == head->head );
1831 1856
1832 /* Now process the list */ 1857 /* Now process the list */
1833 for (avpch=head->next; avpch != head; avpch = avpch->next) { 1858 for (avpch=head->next; avpch != head; avpch = avpch->next) {
1834 CHECK_FCT( parsedict_do_avp(dict, _A(avpch->o), mandatory) ); 1859 CHECK_FCT( parsedict_do_avp(dict, _A(avpch->o), mandatory, error_info) );
1835 } 1860 }
1836 1861
1837 /* Done */ 1862 /* Done */
1838 return 0; 1863 return 0;
1839 } 1864 }
1840 1865
1841 /* Process a msg header. */ 1866 /* Process a msg header. */
1842 static int parsedict_do_msg(struct dictionary * dict, struct msg * msg, int only_hdr) 1867 static int parsedict_do_msg(struct dictionary * dict, struct msg * msg, int only_hdr, struct fd_pei *error_info)
1843 { 1868 {
1844 int ret = 0; 1869 int ret = 0;
1845 1870
1846 TRACE_ENTRY("%p %p %d", dict, msg, only_hdr); 1871 TRACE_ENTRY("%p %p %d %p", dict, msg, only_hdr, error_info);
1847 1872
1848 CHECK_PARAMS( CHECK_MSG(msg) ); 1873 CHECK_PARAMS( CHECK_MSG(msg) );
1849 1874
1850 /* Look for the model from the header */ 1875 /* Look for the model from the header */
1851 CHECK_FCT( fd_dict_search ( dict, DICT_COMMAND, 1876 CHECK_FCT_DO( ret = fd_dict_search ( dict, DICT_COMMAND,
1852 (msg->msg_public.msg_flags & CMD_FLAG_REQUEST) ? CMD_BY_CODE_R : CMD_BY_CODE_A, 1877 (msg->msg_public.msg_flags & CMD_FLAG_REQUEST) ? CMD_BY_CODE_R : CMD_BY_CODE_A,
1853 &msg->msg_public.msg_code, 1878 &msg->msg_public.msg_code,
1854 &msg->msg_model, ENOTSUP) ); 1879 &msg->msg_model, ENOTSUP),
1880 {
1881 if ((ret == ENOTSUP) && (error_info)) {
1882 error_info->pei_errcode = "DIAMETER_COMMAND_UNSUPPORTED";
1883 error_info->pei_protoerr = 1;
1884 }
1885 return ret;
1886 } );
1855 1887
1856 if (!only_hdr) { 1888 if (!only_hdr) {
1857 /* Then process the children */ 1889 /* Then process the children */
1858 ret = parsedict_do_chain(dict, &msg->msg_chain.children, 1); 1890 ret = parsedict_do_chain(dict, &msg->msg_chain.children, 1, error_info);
1859 1891
1860 /* Free the raw buffer if any */ 1892 /* Free the raw buffer if any */
1861 if ((ret == 0) && (msg->msg_rawbuffer != NULL)) { 1893 if ((ret == 0) && (msg->msg_rawbuffer != NULL)) {
1862 free(msg->msg_rawbuffer); 1894 free(msg->msg_rawbuffer);
1863 msg->msg_rawbuffer=NULL; 1895 msg->msg_rawbuffer=NULL;
1865 } 1897 }
1866 1898
1867 return ret; 1899 return ret;
1868 } 1900 }
1869 1901
1870 int fd_msg_parse_dict ( msg_or_avp * object, struct dictionary * dict ) 1902 int fd_msg_parse_dict ( msg_or_avp * object, struct dictionary * dict, struct fd_pei *error_info )
1871 { 1903 {
1872 TRACE_ENTRY("%p %p", dict, object); 1904 TRACE_ENTRY("%p %p %p", dict, object, error_info);
1873 1905
1874 CHECK_PARAMS( VALIDATE_OBJ(object) ); 1906 CHECK_PARAMS( VALIDATE_OBJ(object) );
1907
1908 if (error_info)
1909 memset(error_info, 0, sizeof(struct fd_pei));
1875 1910
1876 switch (_C(object)->type) { 1911 switch (_C(object)->type) {
1877 case MSG_MSG: 1912 case MSG_MSG:
1878 return parsedict_do_msg(dict, _M(object), 0); 1913 return parsedict_do_msg(dict, _M(object), 0, error_info);
1879 1914
1880 case MSG_AVP: 1915 case MSG_AVP:
1881 return parsedict_do_avp(dict, _A(object), 0); 1916 return parsedict_do_avp(dict, _A(object), 0, error_info);
1882 1917
1883 default: 1918 default:
1884 ASSERT(0); 1919 ASSERT(0);
1885 } 1920 }
1886 return EINVAL; 1921 return EINVAL;
2154 2189
2155 if (error_info) 2190 if (error_info)
2156 memset(error_info, 0, sizeof(struct fd_pei)); 2191 memset(error_info, 0, sizeof(struct fd_pei));
2157 2192
2158 /* Resolve the dictionary objects when missing. This also validates the object. */ 2193 /* Resolve the dictionary objects when missing. This also validates the object. */
2159 CHECK_FCT( fd_msg_parse_dict ( object, dict ) ); 2194 CHECK_FCT( fd_msg_parse_dict ( object, dict, error_info ) );
2160 2195
2161 /* Call the recursive function */ 2196 /* Call the recursive function */
2162 return parserules_do ( dict, object, error_info, 1 ) ; 2197 return parserules_do ( dict, object, error_info, 1 ) ;
2163 } 2198 }
2164 2199
"Welcome to our mercurial repository"