comparison libfreeDiameter/messages.c @ 34:0e2b57789361

Backup for the WE, some warnings remaining
author Sebastien Decugis <sdecugis@nict.go.jp>
date Fri, 30 Oct 2009 17:23:06 +0900
parents e5af94b04946
children 6486e97f56ae
comparison
equal deleted inserted replaced
33:e6fcdf12b9a0 34:0e2b57789361
121 struct { 121 struct {
122 void (*fct)(void *, struct msg **); 122 void (*fct)(void *, struct msg **);
123 void * data; 123 void * data;
124 } msg_cb; /* Callback to be called when an answer is received, if not NULL */ 124 } msg_cb; /* Callback to be called when an answer is received, if not NULL */
125 char * msg_src_id; /* Diameter Id of the peer this message was received from. This string is malloc'd and must be freed */ 125 char * msg_src_id; /* Diameter Id of the peer this message was received from. This string is malloc'd and must be freed */
126 uint32_t msg_src_hash; /* Hash of the msg_src_id value */
127 }; 126 };
128 127
129 /* Macro to compute the message header size */ 128 /* Macro to compute the message header size */
130 #define GETMSGHDRSZ() 20 129 #define GETMSGHDRSZ() 20
131 130
665 msg->msg_public.msg_code, 664 msg->msg_public.msg_code,
666 msg->msg_public.msg_appl, 665 msg->msg_public.msg_appl,
667 msg->msg_public.msg_hbhid, 666 msg->msg_public.msg_hbhid,
668 msg->msg_public.msg_eteid 667 msg->msg_public.msg_eteid
669 ); 668 );
670 fd_log_debug(INOBJHDR "intern: rwb:%p rt:%d cb:%p(%p) qry:%p h:%x src:%s\n", 669 fd_log_debug(INOBJHDR "intern: rwb:%p rt:%d cb:%p(%p) qry:%p src:%s\n",
671 INOBJHDRVAL, msg->msg_rawbuffer, msg->msg_routable, msg->msg_cb.fct, msg->msg_cb.data, msg->msg_query, msg->msg_src_hash, msg->msg_src_id?:"(nil)"); 670 INOBJHDRVAL, msg->msg_rawbuffer, msg->msg_routable, msg->msg_cb.fct, msg->msg_cb.data, msg->msg_query, msg->msg_src_id?:"(nil)");
672 } 671 }
673 672
674 #define DUMP_VALUE(_format, _parms...) fd_log_debug(INOBJHDR "value : t:'%s' v:'" _format "'\n", INOBJHDRVAL, typename, ## _parms); 673 #define DUMP_VALUE(_format, _parms...) fd_log_debug(INOBJHDR "value : t:'%s' v:'" _format "'\n", INOBJHDRVAL, typename, ## _parms);
675 /* Dump an AVP value that is not a constant */ 674 /* Dump an AVP value that is not a constant */
676 static void dump_basic_type(union avp_value * value, enum dict_avp_basetype type, const char * typename, int indent) 675 static void dump_basic_type(union avp_value * value, enum dict_avp_basetype type, const char * typename, int indent)
1074 1073
1075 return (msg->msg_routable == 1) ? 1 : 0; 1074 return (msg->msg_routable == 1) ? 1 : 0;
1076 } 1075 }
1077 1076
1078 /* Associate source peer */ 1077 /* Associate source peer */
1079 int fd_msg_source_set( struct msg * msg, char * diamid, uint32_t hash, int add_rr, struct dictionary * dict ) 1078 int fd_msg_source_set( struct msg * msg, char * diamid, int add_rr, struct dictionary * dict )
1080 { 1079 {
1081 TRACE_ENTRY( "%p %p %x %d %p", msg, diamid, hash, add_rr, dict); 1080 TRACE_ENTRY( "%p %p %d %p", msg, diamid, add_rr, dict);
1082 1081
1083 /* Check we received a valid message */ 1082 /* Check we received a valid message */
1084 CHECK_PARAMS( CHECK_MSG(msg) && dict ); 1083 CHECK_PARAMS( CHECK_MSG(msg) && dict );
1085 1084
1086 /* Cleanup any previous source */ 1085 /* Cleanup any previous source */
1087 free(msg->msg_src_id); msg->msg_src_id = NULL; 1086 free(msg->msg_src_id); msg->msg_src_id = NULL;
1088 1087
1089 /* If the request is to cleanup the source, we are done */ 1088 /* If the request is to cleanup the source, we are done */
1090 if (diamid == NULL) { 1089 if (diamid == NULL) {
1091 msg->msg_src_hash = 0;
1092 return 0; 1090 return 0;
1093 } 1091 }
1094 1092
1095 /* Otherwise save the new informations */ 1093 /* Otherwise save the new informations */
1096 CHECK_MALLOC( msg->msg_src_id = strdup(diamid) ); 1094 CHECK_MALLOC( msg->msg_src_id = strdup(diamid) );
1097 msg->msg_src_hash = hash;
1098 1095
1099 if (add_rr) { 1096 if (add_rr) {
1100 struct dict_object *avp_rr_model; 1097 struct dict_object *avp_rr_model;
1101 avp_code_t code = AC_ROUTE_RECORD; 1098 avp_code_t code = AC_ROUTE_RECORD;
1102 struct avp *avp; 1099 struct avp *avp;
1120 1117
1121 /* done */ 1118 /* done */
1122 return 0; 1119 return 0;
1123 } 1120 }
1124 1121
1125 int fd_msg_source_get( struct msg * msg, char ** diamid, uint32_t *hash ) 1122 int fd_msg_source_get( struct msg * msg, char ** diamid )
1126 { 1123 {
1127 TRACE_ENTRY( "%p %p %p", msg, diamid, hash); 1124 TRACE_ENTRY( "%p %p", msg, diamid);
1128 1125
1129 /* Check we received valid parameters */ 1126 /* Check we received valid parameters */
1130 CHECK_PARAMS( CHECK_MSG(msg) ); 1127 CHECK_PARAMS( CHECK_MSG(msg) );
1131 CHECK_PARAMS( diamid ); 1128 CHECK_PARAMS( diamid );
1132 1129
1133 /* Copy the informations */ 1130 /* Copy the informations */
1134 *diamid = msg->msg_src_id; 1131 *diamid = msg->msg_src_id;
1135 if (hash)
1136 *hash = msg->msg_src_hash;
1137 1132
1138 /* done */ 1133 /* done */
1139 return 0; 1134 return 0;
1140 } 1135 }
1141 1136
1860 } 1855 }
1861 } 1856 }
1862 1857
1863 /* We use this structure as parameter for the next function */ 1858 /* We use this structure as parameter for the next function */
1864 struct parserules_data { 1859 struct parserules_data {
1865 struct fd_list * sentinel; /* Sentinel of the list of children AVP */ 1860 struct fd_list * sentinel; /* Sentinel of the list of children AVP */
1866 struct dict_object * ruleavp; /* If the rule conflicts, save the rule_avp here (we don't have direct access to the rule but it can be searched) */ 1861 struct fd_pei * pei; /* If the rule conflicts, save the error here */
1867 }; 1862 };
1863
1864 /* Create an empty AVP of a given model (to use in Failed-AVP) */
1865 static struct avp * empty_avp(struct dict_object * model_avp)
1866 {
1867 TODO("Create the AVP instance and set a 0 value");
1868 return NULL;
1869 }
1868 1870
1869 /* Check that a list of AVPs is compliant with a given rule -- will be iterated on the list of rules */ 1871 /* Check that a list of AVPs is compliant with a given rule -- will be iterated on the list of rules */
1870 static int parserules_check_one_rule(void * data, struct dict_rule_data *rule) 1872 static int parserules_check_one_rule(void * data, struct dict_rule_data *rule)
1871 { 1873 {
1872 int ret = 0, count, first, last, min; 1874 int count, first, last, min;
1873 struct parserules_data * pr_data = (struct parserules_data *) data; 1875 struct parserules_data * pr_data = data;
1874 1876
1875 TRACE_ENTRY("%p %p", data, rule); 1877 TRACE_ENTRY("%p %p", data, rule);
1876 1878
1877 /* Get statistics of the AVP concerned by this rule in the message instance */ 1879 /* Get statistics of the AVP concerned by this rule in the parent instance */
1878 parserules_stat_avps( rule->rule_avp, pr_data->sentinel, &count, &first, &last); 1880 parserules_stat_avps( rule->rule_avp, pr_data->sentinel, &count, &first, &last);
1879 1881
1880 if (TRACE_BOOL(ANNOYING)) 1882 if (TRACE_BOOL(ANNOYING))
1881 { 1883 {
1882 struct dict_avp_data avpdata; 1884 struct dict_avp_data avpdata;
1885 int ret;
1883 ret = fd_dict_getval(rule->rule_avp, &avpdata); 1886 ret = fd_dict_getval(rule->rule_avp, &avpdata);
1884 1887
1885 TRACE_DEBUG(ANNOYING, "Checking rule: p:%d(%d) m/M:%2d/%2d. Counted %d (first: %d, last:%d) of AVP '%s'", 1888 TRACE_DEBUG(ANNOYING, "Checking rule: p:%d(%d) m/M:%2d/%2d. Counted %d (first: %d, last:%d) of AVP '%s'",
1886 rule->rule_position, 1889 rule->rule_position,
1887 rule->rule_order, 1890 rule->rule_order,
1893 (ret == 0) ? avpdata.avp_name : "???" 1896 (ret == 0) ? avpdata.avp_name : "???"
1894 ); 1897 );
1895 } 1898 }
1896 1899
1897 /* Now check the rule is not conflicting */ 1900 /* Now check the rule is not conflicting */
1898 ret = 0;
1899 1901
1900 /* Check the "min" value */ 1902 /* Check the "min" value */
1901 if ((min = rule->rule_min) == -1) { 1903 if ((min = rule->rule_min) == -1) {
1902 if (rule->rule_position == RULE_OPTIONAL) 1904 if (rule->rule_position == RULE_OPTIONAL)
1903 min = 0; 1905 min = 0;
1904 else 1906 else
1905 min = 1; 1907 min = 1;
1906 } 1908 }
1907 if (count < min) { 1909 if (count < min) {
1908 TRACE_DEBUG(INFO, "Conflicting rule: the number of occurences (%d) is < the rule min (%d).", count, min); 1910 TRACE_DEBUG(INFO, "Conflicting rule: the number of occurences (%d) is < the rule min (%d).", count, min);
1909 ret = EBADMSG; 1911 if (pr_data->pei) {
1910 goto end; 1912 pr_data->pei->pei_errcode = "DIAMETER_MISSING_AVP";
1913 pr_data->pei->pei_avp = empty_avp(rule->rule_avp);
1914 }
1915 return EBADMSG;
1911 } 1916 }
1912 1917
1913 /* Check the "max" value */ 1918 /* Check the "max" value */
1914 if ((rule->rule_max != -1) && (count > rule->rule_max)) { 1919 if ((rule->rule_max != -1) && (count > rule->rule_max)) {
1915 TRACE_DEBUG(INFO, "Conflicting rule: the number of occurences (%d) is > the rule max (%d).", count, rule->rule_max); 1920 TRACE_DEBUG(INFO, "Conflicting rule: the number of occurences (%d) is > the rule max (%d).", count, rule->rule_max);
1916 ret = EBADMSG; 1921 if (pr_data->pei) {
1917 goto end; 1922 if (rule->rule_max == 0)
1923 pr_data->pei->pei_errcode = "DIAMETER_AVP_NOT_ALLOWED";
1924 else
1925 pr_data->pei->pei_errcode = "DIAMETER_AVP_OCCURS_TOO_MANY_TIMES";
1926 pr_data->pei->pei_avp = empty_avp(rule->rule_avp); /* Well we are supposed to return the (max + 1)th instance of the AVP instead... Pfff... */ TODO("Improve...");
1927 }
1928 return EBADMSG;
1918 } 1929 }
1919 1930
1920 /* Check the position and order (if relevant) */ 1931 /* Check the position and order (if relevant) */
1921 switch (rule->rule_position) { 1932 switch (rule->rule_position) {
1922 case RULE_OPTIONAL: 1933 case RULE_OPTIONAL:
1926 1937
1927 case RULE_FIXED_HEAD: 1938 case RULE_FIXED_HEAD:
1928 /* Since "0*1<fixed>" is a valid rule specifier, we only reject cases where the AVP appears *after* its fixed position */ 1939 /* Since "0*1<fixed>" is a valid rule specifier, we only reject cases where the AVP appears *after* its fixed position */
1929 if (first > rule->rule_order) { 1940 if (first > rule->rule_order) {
1930 TRACE_DEBUG(INFO, "Conflicting rule: the FIXED_HEAD AVP appears first in (%d) position, the rule requires (%d).", first, rule->rule_order); 1941 TRACE_DEBUG(INFO, "Conflicting rule: the FIXED_HEAD AVP appears first in (%d) position, the rule requires (%d).", first, rule->rule_order);
1931 ret = EBADMSG; 1942 if (pr_data->pei) {
1932 goto end; 1943 pr_data->pei->pei_errcode = "DIAMETER_MISSING_AVP";
1944 pr_data->pei->pei_message = "AVP was not in its fixed position";
1945 pr_data->pei->pei_avp = empty_avp(rule->rule_avp);
1946 }
1947 return EBADMSG;
1933 } 1948 }
1934 break; 1949 break;
1935 1950
1936 case RULE_FIXED_TAIL: 1951 case RULE_FIXED_TAIL:
1937 /* Since "0*1<fixed>" is a valid rule specifier, we only reject cases where the AVP appears *before* its fixed position */ 1952 /* Since "0*1<fixed>" is a valid rule specifier, we only reject cases where the AVP appears *before* its fixed position */
1938 if (last > rule->rule_order) { /* We have a ">" here because we count in reverse order (i.e. from the end) */ 1953 if (last > rule->rule_order) { /* We have a ">" here because we count in reverse order (i.e. from the end) */
1939 TRACE_DEBUG(INFO, "Conflicting rule: the FIXED_TAIL AVP appears last in (%d) position, the rule requires (%d).", last, rule->rule_order); 1954 TRACE_DEBUG(INFO, "Conflicting rule: the FIXED_TAIL AVP appears last in (%d) position, the rule requires (%d).", last, rule->rule_order);
1940 ret = EBADMSG; 1955 if (pr_data->pei) {
1941 goto end; 1956 pr_data->pei->pei_errcode = "DIAMETER_MISSING_AVP";
1957 pr_data->pei->pei_message = "AVP was not in its fixed position";
1958 pr_data->pei->pei_avp = empty_avp(rule->rule_avp);
1959 }
1960 return EBADMSG;
1942 } 1961 }
1943 break; 1962 break;
1944 1963
1945 default: 1964 default:
1946 /* What is this position ??? */ 1965 /* What is this position ??? */
1947 ASSERT(0); 1966 ASSERT(0);
1948 ret = ENOTSUP; 1967 return ENOTSUP;
1949 } 1968 }
1950 1969
1951 /* We've checked all the parameters */ 1970 /* We've checked all the parameters */
1952 end: 1971 return 0;
1953 if (ret == EBADMSG) {
1954 pr_data->ruleavp = rule->rule_avp;
1955 }
1956
1957 return ret;
1958 } 1972 }
1959 1973
1960 /* Check the rules recursively */ 1974 /* Check the rules recursively */
1961 static int parserules_do ( struct dictionary * dict, msg_or_avp * object, struct dict_object ** conflict_rule, int mandatory) 1975 static int parserules_do ( struct dictionary * dict, msg_or_avp * object, struct fd_pei *error_info, int mandatory)
1962 { 1976 {
1963 int ret = 0;
1964 struct parserules_data data; 1977 struct parserules_data data;
1965 struct dict_object * model = NULL; 1978 struct dict_object * model = NULL;
1966 1979
1967 TRACE_ENTRY("%p %p %p %d", dict, object, conflict_rule, mandatory); 1980 TRACE_ENTRY("%p %p %p %d", dict, object, error_info, mandatory);
1968 1981
1969 /* object has already been checked and dict-parsed when we are called. */ 1982 /* object has already been checked and dict-parsed when we are called. */
1970 1983
1971 /* First, handle the cases where there is no model */ 1984 /* First, handle the cases where there is no model */
1972 { 1985 {
1978 model = _M(object)->msg_model; 1991 model = _M(object)->msg_model;
1979 } 1992 }
1980 /* Commands MUST be supported in the dictionary */ 1993 /* Commands MUST be supported in the dictionary */
1981 if (model == NULL) { 1994 if (model == NULL) {
1982 TRACE_DEBUG(INFO, "Message with no dictionary model. EBADMSG"); 1995 TRACE_DEBUG(INFO, "Message with no dictionary model. EBADMSG");
1996 if (error_info) {
1997 error_info->pei_errcode = "DIAMETER_COMMAND_UNSUPPORTED";
1998 error_info->pei_protoerr = 1;
1999 }
1983 return EBADMSG; 2000 return EBADMSG;
1984 } 2001 }
1985 } 2002 }
1986 2003
1987 /* AVP with the 'M' flag must also be recognized in the dictionary -- except inside an optional grouped AVP */ 2004 /* AVP with the 'M' flag must also be recognized in the dictionary -- except inside an optional grouped AVP */
1988 if (CHECK_AVP(object) && ((model = _A(object)->avp_model) == NULL)) { 2005 if (CHECK_AVP(object) && ((model = _A(object)->avp_model) == NULL)) {
1989 if ( mandatory && (_A(object)->avp_public.avp_flags & AVP_FLAG_MANDATORY)) { 2006 if ( mandatory && (_A(object)->avp_public.avp_flags & AVP_FLAG_MANDATORY)) {
1990 /* Return an error in this case */ 2007 /* Return an error in this case */
1991 TRACE_DEBUG(INFO, "Mandatory AVP with no dictionary model. EBADMSG"); 2008 TRACE_DEBUG(INFO, "Mandatory AVP with no dictionary model. EBADMSG");
2009 if (error_info) {
2010 error_info->pei_errcode = "DIAMETER_AVP_UNSUPPORTED";
2011 error_info->pei_avp = object;
2012 }
1992 return EBADMSG; 2013 return EBADMSG;
1993 } else { 2014 } else {
1994 /* We don't know any rule for this object, so assume OK */ 2015 /* We don't know any rule for this object, so assume OK */
1995 TRACE_DEBUG(FULL, "Unknown informational AVP, ignoring..."); 2016 TRACE_DEBUG(FULL, "Unknown informational AVP, ignoring...");
1996 return 0; 2017 return 0;
2016 struct fd_list * ch = NULL; 2037 struct fd_list * ch = NULL;
2017 if ( CHECK_MSG(object) 2038 if ( CHECK_MSG(object)
2018 || (mandatory && (_A(object)->avp_public.avp_flags & AVP_FLAG_MANDATORY)) ) 2039 || (mandatory && (_A(object)->avp_public.avp_flags & AVP_FLAG_MANDATORY)) )
2019 is_child_mand = 1; 2040 is_child_mand = 1;
2020 for (ch = _C(object)->children.next; ch != &_C(object)->children; ch = ch->next) { 2041 for (ch = _C(object)->children.next; ch != &_C(object)->children; ch = ch->next) {
2021 CHECK_FCT( parserules_do ( dict, _C(ch->o), conflict_rule, is_child_mand ) ); 2042 CHECK_FCT( parserules_do ( dict, _C(ch->o), error_info, is_child_mand ) );
2022 } 2043 }
2023 } 2044 }
2024 2045
2025 /* Now check all rules of this object */ 2046 /* Now check all rules of this object */
2026 data.sentinel = &_C(object)->children; 2047 data.sentinel = &_C(object)->children;
2027 data.ruleavp = NULL; 2048 data.pei = error_info;
2028 ret = fd_dict_iterate_rules ( model, &data, parserules_check_one_rule ); 2049 CHECK_FCT( fd_dict_iterate_rules ( model, &data, parserules_check_one_rule ) );
2029 2050
2030 /* Save the reference to the eventual conflicting rule; otherwise set to NULL */ 2051 return 0;
2031 if (conflict_rule && data.ruleavp) { 2052 }
2032 /* data.ruleavp contains the AVP, and model is the parent */ 2053
2033 struct dict_object * rule = NULL; 2054 int fd_msg_parse_rules ( msg_or_avp * object, struct dictionary * dict, struct fd_pei *error_info)
2034 struct dict_rule_request req = { model, data.ruleavp }; 2055 {
2035 2056 TRACE_ENTRY("%p %p %p", object, dict, error_info);
2036 CHECK_FCT_DO( fd_dict_search ( dict, DICT_RULE, RULE_BY_AVP_AND_PARENT, &req, &rule, ENOENT), rule = NULL );
2037
2038 *conflict_rule = rule;
2039 }
2040
2041 return ret;
2042 }
2043
2044 int fd_msg_parse_rules ( msg_or_avp * object, struct dictionary * dict, struct dict_object ** rule)
2045 {
2046 TRACE_ENTRY("%p %p", object, rule);
2047 2057
2048 /* Resolve the dictionary objects when missing. This also validates the object. */ 2058 /* Resolve the dictionary objects when missing. This also validates the object. */
2049 CHECK_FCT( fd_msg_parse_dict ( object, dict ) ); 2059 CHECK_FCT( fd_msg_parse_dict ( object, dict ) );
2050 2060
2061 if (error_info)
2062 memset(error_info, 0, sizeof(struct fd_pei));
2063
2051 /* Call the recursive function */ 2064 /* Call the recursive function */
2052 return parserules_do ( dict, object, rule, 1 ) ; 2065 return parserules_do ( dict, object, error_info, 1 ) ;
2053 } 2066 }
2054 2067
2055 /***************************************************************************************************************/ 2068 /***************************************************************************************************************/
2056 2069
2057 /* Compute the lengh of an object and its subtree. */ 2070 /* Compute the lengh of an object and its subtree. */
"Welcome to our mercurial repository"