Navigation


Changeset 1383:0d71c0b2eed4 in freeDiameter for libfdcore


Ignore:
Timestamp:
Jul 9, 2019, 12:46:51 AM (5 years ago)
Author:
Thomas Klausner <tk@giga.or.at>
Branch:
default
Phase:
public
Message:

Be loud, but don't exit on invalid mandatory AVP in Answer

File:
1 edited

Legend:

Unmodified
Added
Removed
  • libfdcore/messages.c

    r1323 r1383  
    5353{
    5454        TRACE_ENTRY("");
    55        
     55
    5656        /* Initialize the dictionary objects that we may use frequently */
    5757        CHECK_FCT(  fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Session-Id",         &dict_avp_SI , ENOENT)  );
     
    5959        CHECK_FCT(  fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Origin-Realm",       &dict_avp_OR  , ENOENT)  );
    6060        CHECK_FCT(  fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Origin-State-Id",    &fd_dict_avp_OSI , ENOENT)  );
    61        
     61
    6262        CHECK_FCT(  fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Result-Code",        &dict_avp_RC  , ENOENT)  );
    6363        CHECK_FCT(  fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Error-Message",      &dict_avp_EM  , ENOENT)  );
    6464        CHECK_FCT(  fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Error-Reporting-Host", &dict_avp_ERH , ENOENT)  );
    6565        CHECK_FCT(  fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Failed-AVP",         &dict_avp_FAVP, ENOENT)  );
    66        
     66
    6767        CHECK_FCT(  fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Disconnect-Cause",   &fd_dict_avp_DC , ENOENT)  );
    68        
     68
    6969        CHECK_FCT( fd_dict_search ( fd_g_config->cnf_dict, DICT_COMMAND, CMD_BY_NAME, "Capabilities-Exchange-Request", &fd_dict_cmd_CER, ENOENT ) );
    7070        CHECK_FCT( fd_dict_search ( fd_g_config->cnf_dict, DICT_COMMAND, CMD_BY_NAME, "Device-Watchdog-Request", &fd_dict_cmd_DWR, ENOENT ) );
    7171        CHECK_FCT( fd_dict_search ( fd_g_config->cnf_dict, DICT_COMMAND, CMD_BY_NAME, "Disconnect-Peer-Request", &fd_dict_cmd_DPR, ENOENT ) );
    72        
    73        
     72
     73
    7474        return 0;
    7575}
     
    8282        struct avp * avp_OR  = NULL;
    8383        struct avp * avp_OSI = NULL;
    84        
     84
    8585        TRACE_ENTRY("%p", msg);
    8686        CHECK_PARAMS(  msg  );
    87        
     87
    8888        /* Create the Origin-Host AVP */
    8989        CHECK_FCT( fd_msg_avp_new( dict_avp_OH, 0, &avp_OH ) );
    90        
     90
    9191        /* Set its value */
    9292        memset(&val, 0, sizeof(val));
     
    9494        val.os.len  = fd_g_config->cnf_diamid_len;
    9595        CHECK_FCT( fd_msg_avp_setvalue( avp_OH, &val ) );
    96        
     96
    9797        /* Add it to the message */
    9898        CHECK_FCT( fd_msg_avp_add( msg, MSG_BRW_LAST_CHILD, avp_OH ) );
    99        
    100        
     99
     100
    101101        /* Create the Origin-Realm AVP */
    102102        CHECK_FCT( fd_msg_avp_new( dict_avp_OR, 0, &avp_OR ) );
    103        
     103
    104104        /* Set its value */
    105105        memset(&val, 0, sizeof(val));
     
    107107        val.os.len  = fd_g_config->cnf_diamrlm_len;
    108108        CHECK_FCT( fd_msg_avp_setvalue( avp_OR, &val ) );
    109        
     109
    110110        /* Add it to the message */
    111111        CHECK_FCT( fd_msg_avp_add( msg, MSG_BRW_LAST_CHILD, avp_OR ) );
    112        
     112
    113113        if (osi) {
    114114                /* Create the Origin-State-Id AVP */
     
    123123                CHECK_FCT( fd_msg_avp_add( msg, MSG_BRW_LAST_CHILD, avp_OSI ) );
    124124        }
    125        
     125
    126126        return 0;
    127127}
     
    135135        os0_t sid;
    136136        size_t sidlen;
    137        
     137
    138138        TRACE_ENTRY("%p %p %zd", msg, opt, optlen);
    139139        CHECK_PARAMS(  msg  );
    140        
     140
    141141        /* Check there is not already a session in the message */
    142142        CHECK_FCT( fd_msg_sess_get(fd_g_config->cnf_dict, msg, &sess, NULL) );
    143143        CHECK_PARAMS( sess == NULL );
    144        
     144
    145145        /* Ok, now create the session */
    146146        CHECK_FCT( fd_sess_new ( &sess, fd_g_config->cnf_diamid, fd_g_config->cnf_diamid_len, opt, optlen ) );
    147147        CHECK_FCT( fd_sess_getsid( sess, &sid, &sidlen) );
    148        
     148
    149149        /* Create an AVP to hold it */
    150150        CHECK_FCT( fd_msg_avp_new( dict_avp_SI, 0, &avp ) );
    151        
     151
    152152        /* Set its value */
    153153        memset(&val, 0, sizeof(val));
     
    155155        val.os.len  = sidlen;
    156156        CHECK_FCT( fd_msg_avp_setvalue( avp, &val ) );
    157        
     157
    158158        /* Add it to the message */
    159159        CHECK_FCT( fd_msg_avp_add( msg, MSG_BRW_FIRST_CHILD, avp ) );
    160        
     160
    161161        /* Save the session associated with the message */
    162162        CHECK_FCT( fd_msg_sess_set( msg, sess) );
    163        
     163
    164164        /* Done! */
    165165        return 0;
     
    178178        int set_e_bit=0;
    179179        int std_err_msg=0;
    180        
     180
    181181        TRACE_ENTRY("%p %s %p %p %d", msg, rescode, errormsg, optavp, type_id);
    182                
     182
    183183        CHECK_PARAMS(  msg && rescode  );
    184        
     184
    185185        /* Find the enum value corresponding to the rescode string, this will give the class of error */
    186186        {
     
    188188                struct dict_enumval_request req;
    189189                memset(&req, 0, sizeof(struct dict_enumval_request));
    190                
     190
    191191                /* First, get the enumerated type of the Result-Code AVP (this is fast, no need to cache the object) */
    192192                CHECK_FCT(  fd_dict_search( fd_g_config->cnf_dict, DICT_TYPE, TYPE_OF_AVP, dict_avp_RC, &(req.type_obj), ENOENT  )  );
    193                
     193
    194194                /* Now search for the value given as parameter */
    195195                req.search.enum_name = rescode;
    196196                CHECK_FCT(  fd_dict_search( fd_g_config->cnf_dict, DICT_ENUMVAL, ENUMVAL_BY_STRUCT, &req, &enum_obj, ENOTSUP)  );
    197                
     197
    198198                /* finally retrieve its data */
    199199                CHECK_FCT_DO(  fd_dict_getval( enum_obj, &(req.search) ), return EINVAL );
    200                
     200
    201201                /* copy the found value, we're done */
    202202                rc_val = req.search.enum_value.u32;
    203203        }
    204        
     204
    205205        if (type_id == 1) {
    206206                /* Add the Origin-Host and Origin-Realm AVP */
    207207                CHECK_FCT( fd_msg_add_origin ( msg, 0 ) );
    208208        }
    209        
     209
    210210        /* Create the Result-Code AVP */
    211211        CHECK_FCT( fd_msg_avp_new( dict_avp_RC, 0, &avp_RC ) );
    212        
     212
    213213        /* Set its value */
    214214        memset(&val, 0, sizeof(val));
    215215        val.u32  = rc_val;
    216216        CHECK_FCT( fd_msg_avp_setvalue( avp_RC, &val ) );
    217        
     217
    218218        /* Add it to the message */
    219219        CHECK_FCT( fd_msg_avp_add( msg, MSG_BRW_LAST_CHILD, avp_RC ) );
    220        
     220
    221221        if (type_id == 2) {
    222222                /* Add the Error-Reporting-Host AVP */
    223                
     223
    224224                CHECK_FCT( fd_msg_avp_new( dict_avp_ERH, 0, &avp_ERH ) );
    225225
     
    232232                /* Add it to the message */
    233233                CHECK_FCT( fd_msg_avp_add( msg, MSG_BRW_LAST_CHILD, avp_ERH ) );
    234        
    235         }
    236        
     234
     235        }
     236
    237237        /* Now add the optavp in a FailedAVP if provided */
    238238        if (optavp) {
     
    241241                struct dict_object * opt_model = NULL;
    242242                int is_grouped = 0;
    243                
     243
    244244                /* Create the Failed-AVP AVP */
    245245                CHECK_FCT( fd_msg_avp_new( dict_avp_FAVP, 0, &avp_FAVP ) );
    246                
     246
    247247                /* Was this AVP a grouped one? Best effort only here */
    248248                if (!fd_msg_model ( optavp, &opt_model ) && (opt_model != NULL)) {
    249249                        struct dict_avp_data  dictdata;
    250250                        CHECK_FCT(  fd_dict_getval(opt_model, &dictdata)  );
    251                         if (dictdata.avp_basetype == AVP_TYPE_GROUPED) 
     251                        if (dictdata.avp_basetype == AVP_TYPE_GROUPED)
    252252                                is_grouped = 1;
    253253                }
    254                
     254
    255255                /* Create a new AVP with a copy of the data of the invalid or missing AVP */
    256256                optavp_cpy = optavp;
    257                
     257
    258258                if (is_grouped) {
    259259                        CHECK_FCT( fd_msg_avp_new( opt_model, 0, &optavp_cpy) );
    260260                } else {
    261261                        CHECK_FCT( fd_msg_avp_new( NULL, AVPFL_SET_BLANK_VALUE | AVPFL_SET_RAWDATA_FROM_AVP, &optavp_cpy) );
    262                
     262
    263263                        CHECK_FCT( fd_msg_avp_hdr(optavp, &opt_hdr) );
    264264                        CHECK_FCT( fd_msg_avp_hdr(optavp_cpy, &optcpy_hdr) );
    265265                        memcpy(optcpy_hdr, opt_hdr, sizeof(struct avp_hdr));
    266266                }
    267                
     267
    268268                /* Add the passed AVP inside it */
    269269                CHECK_FCT( fd_msg_avp_add( avp_FAVP, MSG_BRW_LAST_CHILD, optavp_cpy ) );
    270                
     270
    271271                /* And add to the message */
    272272                CHECK_FCT( fd_msg_avp_add( msg, MSG_BRW_LAST_CHILD, avp_FAVP ) );
    273273        }
    274        
    275        
     274
     275
    276276        /* Deal with the 'E' bit and the error message */
    277277        switch (rc_val / 1000) {
     
    280280                        /* Nothing special here: no E bit, no error message unless one is specified */
    281281                        break;
    282                        
     282
    283283                case 3: /* Protocol Errors */
    284284                        set_e_bit = 1;
    285285                        std_err_msg = 1;
    286286                        break;
    287                        
     287
    288288                case 4: /* Transcient Failure */
    289289                case 5: /* Permanent Failure */
     
    294294                        std_err_msg = 1;
    295295                        break;
    296                        
    297         }
    298        
     296
     297        }
     298
    299299        {
    300300                struct msg_hdr * hdr = NULL;
    301                
     301
    302302                CHECK_FCT(  fd_msg_hdr( msg, &hdr )  );
    303                
     303
    304304                if (set_e_bit)
    305305                        hdr->msg_flags |= CMD_FLAG_ERROR;
     
    307307                        hdr->msg_flags &= ~ CMD_FLAG_ERROR;
    308308        }
    309        
     309
    310310        if (std_err_msg || errormsg) {
    311311                /* Add the Error-Message AVP */
    312                
     312
    313313                CHECK_FCT( fd_msg_avp_new( dict_avp_EM, 0, &avp_EM ) );
    314314
    315315                /* Set its value */
    316316                memset(&val, 0, sizeof(val));
    317                
     317
    318318                if (errormsg) {
    319319                        val.os.data = (uint8_t *)errormsg;
     
    328328                CHECK_FCT( fd_msg_avp_add( msg, MSG_BRW_LAST_CHILD, avp_EM ) );
    329329        }
    330        
     330
    331331        return 0;
    332332}
     
    336336        struct msg_hdr *hdr;
    337337        DiamId_t diamid;
    338        
     338
    339339        /* Save the callback in the message, with the timeout */
    340340        CHECK_FCT(  fd_msg_anscb_associate( *pmsg, anscb, data, expirecb, timeout )  );
    341        
     341
    342342        /* If this is a new request, call the HOOK_MESSAGE_LOCAL hook */
    343343        if ( (fd_msg_hdr(*pmsg, &hdr) == 0)
     
    347347                fd_hook_call(HOOK_MESSAGE_LOCAL, *pmsg, NULL, NULL, fd_msg_pmdl_get(*pmsg));
    348348        }
    349                
     349
    350350        /* Post the message in the outgoing queue */
    351351        CHECK_FCT( fd_fifo_post(fd_g_outgoing, pmsg) );
    352        
     352
    353353        return 0;
    354354}
     
    359359        TRACE_ENTRY("%p %p %p", pmsg, anscb, data);
    360360        CHECK_PARAMS( pmsg );
    361        
     361
    362362        return fd_msg_send_int(pmsg, anscb, data, NULL, NULL);
    363363}
     
    368368        TRACE_ENTRY("%p %p %p %p %p", pmsg, anscb, data, expirecb, timeout);
    369369        CHECK_PARAMS( pmsg && expirecb && timeout );
    370        
     370
    371371        return fd_msg_send_int(pmsg, anscb, data, expirecb, timeout);
    372372}
     
    380380        struct msg_hdr * hdr = NULL;
    381381        struct fd_pei   pei;
    382        
     382
    383383        TRACE_ENTRY("%p", msg);
    384        
     384
    385385        CHECK_PARAMS(msg && *msg && error);
    386386        m = *msg;
    387387        *error = NULL;
    388        
     388
    389389        /* Parse the message against our dictionary */
    390390        ret = fd_msg_parse_rules ( m, fd_g_config->cnf_dict, &pei);
     
    392392                && (ret != ENOTSUP))    /* Command is not supported / Mandatory AVP is not supported */
    393393                return ret; /* 0 or another error */
    394        
     394
    395395        /* Log */
    396396        fd_hook_call(HOOK_MESSAGE_PARSING_ERROR, m, NULL, pei.pei_message ?: pei.pei_errcode, fd_msg_pmdl_get(m));
    397        
     397
    398398        CHECK_FCT( fd_msg_hdr(m, &hdr) );
    399        
     399
    400400        /* Now create an answer error if the message is a query */
    401401        if (hdr->msg_flags & CMD_FLAG_REQUEST) {
    402                
     402
    403403                /* Create the error message */
    404404                CHECK_FCT( fd_msg_new_answer_from_req ( fd_g_config->cnf_dict, &m, pei.pei_protoerr ? MSGFL_ANSW_ERROR : 0 ) );
    405                
     405
    406406                /* Set the error code */
    407407                CHECK_FCT( fd_msg_rescode_set(m, pei.pei_errcode, pei.pei_message, pei.pei_avp, 1 ) );
    408                
     408
    409409                /* free the pei AVP to avoid memory leak */
    410410                if (pei.pei_avp_free) {
    411411                        fd_msg_free(pei.pei_avp);
    412412                }
    413                
     413
    414414                *msg = NULL;
    415415                *error = m;
    416                
     416
    417417        } else {
    418418                do { /* Rescue error messages */
    419419                        struct avp * avp;
    420420                        union avp_value * rc = NULL;
    421                        
     421
    422422                        /* Search the Result-Code AVP */
    423423                        CHECK_FCT_DO(  fd_msg_browse(*msg, MSG_BRW_FIRST_CHILD, &avp, NULL), break  );
     
    425425                                struct avp_hdr * ahdr;
    426426                                CHECK_FCT_DO(  fd_msg_avp_hdr( avp, &ahdr ), break  );
    427                                
     427
    428428                                if ((ahdr->avp_code == AC_RESULT_CODE) && (! (ahdr->avp_flags & AVP_FLAG_VENDOR)) ) {
    429429                                        /* Parse this AVP */
    430                                         ASSERT( ahdr->avp_value );
     430                                        if (fd_msg_parse_dict(avp, fd_g_config->cnf_dict, &pei) < 0) {
     431                                                TRACE_DEBUG(INFO, "error parsing Result-Code AVP");
     432                                                rc = NULL;
     433                                                break;
     434                                        }
    431435                                        rc = ahdr->avp_value;
     436                                        if (rc == NULL) {
     437                                                TRACE_DEBUG(INFO, "invalid Result-Code AVP");
     438                                                break;
     439                                        }
    432440                                        break;
    433441                                }
    434                                
     442
    435443                                /* Go to next AVP */
    436444                                CHECK_FCT_DO(  fd_msg_browse(avp, MSG_BRW_NEXT, &avp, NULL), break  );
    437445                        }
    438                        
     446
    439447                        if (rc) {
    440448                                switch (rc->u32 / 1000) {
     
    443451                                                /* In these cases, we want the message to validate the ABNF, so we will discard the bad message */
    444452                                                break;
    445                                                
     453
    446454                                        default: /* Other errors */
    447455                                                /* We let the application decide what to do with the message, we rescue it */
     
    451459                } while (0);
    452460        }
    453        
     461
    454462        return EBADMSG; /* We convert ENOTSUP to EBADMSG as well */
    455463}
Note: See TracChangeset for help on using the changeset viewer.