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