Changeset 1383:0d71c0b2eed4 in freeDiameter for libfdcore
- Timestamp:
- Jul 9, 2019, 12:46:51 AM (5 years ago)
- Branch:
- default
- Phase:
- public
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
libfdcore/messages.c
r1323 r1383 53 53 { 54 54 TRACE_ENTRY(""); 55 55 56 56 /* Initialize the dictionary objects that we may use frequently */ 57 57 CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Session-Id", &dict_avp_SI , ENOENT) ); … … 59 59 CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Origin-Realm", &dict_avp_OR , ENOENT) ); 60 60 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 62 62 CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Result-Code", &dict_avp_RC , ENOENT) ); 63 63 CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Error-Message", &dict_avp_EM , ENOENT) ); 64 64 CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Error-Reporting-Host", &dict_avp_ERH , ENOENT) ); 65 65 CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Failed-AVP", &dict_avp_FAVP, ENOENT) ); 66 66 67 67 CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Disconnect-Cause", &fd_dict_avp_DC , ENOENT) ); 68 68 69 69 CHECK_FCT( fd_dict_search ( fd_g_config->cnf_dict, DICT_COMMAND, CMD_BY_NAME, "Capabilities-Exchange-Request", &fd_dict_cmd_CER, ENOENT ) ); 70 70 CHECK_FCT( fd_dict_search ( fd_g_config->cnf_dict, DICT_COMMAND, CMD_BY_NAME, "Device-Watchdog-Request", &fd_dict_cmd_DWR, ENOENT ) ); 71 71 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 74 74 return 0; 75 75 } … … 82 82 struct avp * avp_OR = NULL; 83 83 struct avp * avp_OSI = NULL; 84 84 85 85 TRACE_ENTRY("%p", msg); 86 86 CHECK_PARAMS( msg ); 87 87 88 88 /* Create the Origin-Host AVP */ 89 89 CHECK_FCT( fd_msg_avp_new( dict_avp_OH, 0, &avp_OH ) ); 90 90 91 91 /* Set its value */ 92 92 memset(&val, 0, sizeof(val)); … … 94 94 val.os.len = fd_g_config->cnf_diamid_len; 95 95 CHECK_FCT( fd_msg_avp_setvalue( avp_OH, &val ) ); 96 96 97 97 /* Add it to the message */ 98 98 CHECK_FCT( fd_msg_avp_add( msg, MSG_BRW_LAST_CHILD, avp_OH ) ); 99 100 99 100 101 101 /* Create the Origin-Realm AVP */ 102 102 CHECK_FCT( fd_msg_avp_new( dict_avp_OR, 0, &avp_OR ) ); 103 103 104 104 /* Set its value */ 105 105 memset(&val, 0, sizeof(val)); … … 107 107 val.os.len = fd_g_config->cnf_diamrlm_len; 108 108 CHECK_FCT( fd_msg_avp_setvalue( avp_OR, &val ) ); 109 109 110 110 /* Add it to the message */ 111 111 CHECK_FCT( fd_msg_avp_add( msg, MSG_BRW_LAST_CHILD, avp_OR ) ); 112 112 113 113 if (osi) { 114 114 /* Create the Origin-State-Id AVP */ … … 123 123 CHECK_FCT( fd_msg_avp_add( msg, MSG_BRW_LAST_CHILD, avp_OSI ) ); 124 124 } 125 125 126 126 return 0; 127 127 } … … 135 135 os0_t sid; 136 136 size_t sidlen; 137 137 138 138 TRACE_ENTRY("%p %p %zd", msg, opt, optlen); 139 139 CHECK_PARAMS( msg ); 140 140 141 141 /* Check there is not already a session in the message */ 142 142 CHECK_FCT( fd_msg_sess_get(fd_g_config->cnf_dict, msg, &sess, NULL) ); 143 143 CHECK_PARAMS( sess == NULL ); 144 144 145 145 /* Ok, now create the session */ 146 146 CHECK_FCT( fd_sess_new ( &sess, fd_g_config->cnf_diamid, fd_g_config->cnf_diamid_len, opt, optlen ) ); 147 147 CHECK_FCT( fd_sess_getsid( sess, &sid, &sidlen) ); 148 148 149 149 /* Create an AVP to hold it */ 150 150 CHECK_FCT( fd_msg_avp_new( dict_avp_SI, 0, &avp ) ); 151 151 152 152 /* Set its value */ 153 153 memset(&val, 0, sizeof(val)); … … 155 155 val.os.len = sidlen; 156 156 CHECK_FCT( fd_msg_avp_setvalue( avp, &val ) ); 157 157 158 158 /* Add it to the message */ 159 159 CHECK_FCT( fd_msg_avp_add( msg, MSG_BRW_FIRST_CHILD, avp ) ); 160 160 161 161 /* Save the session associated with the message */ 162 162 CHECK_FCT( fd_msg_sess_set( msg, sess) ); 163 163 164 164 /* Done! */ 165 165 return 0; … … 178 178 int set_e_bit=0; 179 179 int std_err_msg=0; 180 180 181 181 TRACE_ENTRY("%p %s %p %p %d", msg, rescode, errormsg, optavp, type_id); 182 182 183 183 CHECK_PARAMS( msg && rescode ); 184 184 185 185 /* Find the enum value corresponding to the rescode string, this will give the class of error */ 186 186 { … … 188 188 struct dict_enumval_request req; 189 189 memset(&req, 0, sizeof(struct dict_enumval_request)); 190 190 191 191 /* First, get the enumerated type of the Result-Code AVP (this is fast, no need to cache the object) */ 192 192 CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_TYPE, TYPE_OF_AVP, dict_avp_RC, &(req.type_obj), ENOENT ) ); 193 193 194 194 /* Now search for the value given as parameter */ 195 195 req.search.enum_name = rescode; 196 196 CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_ENUMVAL, ENUMVAL_BY_STRUCT, &req, &enum_obj, ENOTSUP) ); 197 197 198 198 /* finally retrieve its data */ 199 199 CHECK_FCT_DO( fd_dict_getval( enum_obj, &(req.search) ), return EINVAL ); 200 200 201 201 /* copy the found value, we're done */ 202 202 rc_val = req.search.enum_value.u32; 203 203 } 204 204 205 205 if (type_id == 1) { 206 206 /* Add the Origin-Host and Origin-Realm AVP */ 207 207 CHECK_FCT( fd_msg_add_origin ( msg, 0 ) ); 208 208 } 209 209 210 210 /* Create the Result-Code AVP */ 211 211 CHECK_FCT( fd_msg_avp_new( dict_avp_RC, 0, &avp_RC ) ); 212 212 213 213 /* Set its value */ 214 214 memset(&val, 0, sizeof(val)); 215 215 val.u32 = rc_val; 216 216 CHECK_FCT( fd_msg_avp_setvalue( avp_RC, &val ) ); 217 217 218 218 /* Add it to the message */ 219 219 CHECK_FCT( fd_msg_avp_add( msg, MSG_BRW_LAST_CHILD, avp_RC ) ); 220 220 221 221 if (type_id == 2) { 222 222 /* Add the Error-Reporting-Host AVP */ 223 223 224 224 CHECK_FCT( fd_msg_avp_new( dict_avp_ERH, 0, &avp_ERH ) ); 225 225 … … 232 232 /* Add it to the message */ 233 233 CHECK_FCT( fd_msg_avp_add( msg, MSG_BRW_LAST_CHILD, avp_ERH ) ); 234 235 } 236 234 235 } 236 237 237 /* Now add the optavp in a FailedAVP if provided */ 238 238 if (optavp) { … … 241 241 struct dict_object * opt_model = NULL; 242 242 int is_grouped = 0; 243 243 244 244 /* Create the Failed-AVP AVP */ 245 245 CHECK_FCT( fd_msg_avp_new( dict_avp_FAVP, 0, &avp_FAVP ) ); 246 246 247 247 /* Was this AVP a grouped one? Best effort only here */ 248 248 if (!fd_msg_model ( optavp, &opt_model ) && (opt_model != NULL)) { 249 249 struct dict_avp_data dictdata; 250 250 CHECK_FCT( fd_dict_getval(opt_model, &dictdata) ); 251 if (dictdata.avp_basetype == AVP_TYPE_GROUPED) 251 if (dictdata.avp_basetype == AVP_TYPE_GROUPED) 252 252 is_grouped = 1; 253 253 } 254 254 255 255 /* Create a new AVP with a copy of the data of the invalid or missing AVP */ 256 256 optavp_cpy = optavp; 257 257 258 258 if (is_grouped) { 259 259 CHECK_FCT( fd_msg_avp_new( opt_model, 0, &optavp_cpy) ); 260 260 } else { 261 261 CHECK_FCT( fd_msg_avp_new( NULL, AVPFL_SET_BLANK_VALUE | AVPFL_SET_RAWDATA_FROM_AVP, &optavp_cpy) ); 262 262 263 263 CHECK_FCT( fd_msg_avp_hdr(optavp, &opt_hdr) ); 264 264 CHECK_FCT( fd_msg_avp_hdr(optavp_cpy, &optcpy_hdr) ); 265 265 memcpy(optcpy_hdr, opt_hdr, sizeof(struct avp_hdr)); 266 266 } 267 267 268 268 /* Add the passed AVP inside it */ 269 269 CHECK_FCT( fd_msg_avp_add( avp_FAVP, MSG_BRW_LAST_CHILD, optavp_cpy ) ); 270 270 271 271 /* And add to the message */ 272 272 CHECK_FCT( fd_msg_avp_add( msg, MSG_BRW_LAST_CHILD, avp_FAVP ) ); 273 273 } 274 275 274 275 276 276 /* Deal with the 'E' bit and the error message */ 277 277 switch (rc_val / 1000) { … … 280 280 /* Nothing special here: no E bit, no error message unless one is specified */ 281 281 break; 282 282 283 283 case 3: /* Protocol Errors */ 284 284 set_e_bit = 1; 285 285 std_err_msg = 1; 286 286 break; 287 287 288 288 case 4: /* Transcient Failure */ 289 289 case 5: /* Permanent Failure */ … … 294 294 std_err_msg = 1; 295 295 break; 296 297 } 298 296 297 } 298 299 299 { 300 300 struct msg_hdr * hdr = NULL; 301 301 302 302 CHECK_FCT( fd_msg_hdr( msg, &hdr ) ); 303 303 304 304 if (set_e_bit) 305 305 hdr->msg_flags |= CMD_FLAG_ERROR; … … 307 307 hdr->msg_flags &= ~ CMD_FLAG_ERROR; 308 308 } 309 309 310 310 if (std_err_msg || errormsg) { 311 311 /* Add the Error-Message AVP */ 312 312 313 313 CHECK_FCT( fd_msg_avp_new( dict_avp_EM, 0, &avp_EM ) ); 314 314 315 315 /* Set its value */ 316 316 memset(&val, 0, sizeof(val)); 317 317 318 318 if (errormsg) { 319 319 val.os.data = (uint8_t *)errormsg; … … 328 328 CHECK_FCT( fd_msg_avp_add( msg, MSG_BRW_LAST_CHILD, avp_EM ) ); 329 329 } 330 330 331 331 return 0; 332 332 } … … 336 336 struct msg_hdr *hdr; 337 337 DiamId_t diamid; 338 338 339 339 /* Save the callback in the message, with the timeout */ 340 340 CHECK_FCT( fd_msg_anscb_associate( *pmsg, anscb, data, expirecb, timeout ) ); 341 341 342 342 /* If this is a new request, call the HOOK_MESSAGE_LOCAL hook */ 343 343 if ( (fd_msg_hdr(*pmsg, &hdr) == 0) … … 347 347 fd_hook_call(HOOK_MESSAGE_LOCAL, *pmsg, NULL, NULL, fd_msg_pmdl_get(*pmsg)); 348 348 } 349 349 350 350 /* Post the message in the outgoing queue */ 351 351 CHECK_FCT( fd_fifo_post(fd_g_outgoing, pmsg) ); 352 352 353 353 return 0; 354 354 } … … 359 359 TRACE_ENTRY("%p %p %p", pmsg, anscb, data); 360 360 CHECK_PARAMS( pmsg ); 361 361 362 362 return fd_msg_send_int(pmsg, anscb, data, NULL, NULL); 363 363 } … … 368 368 TRACE_ENTRY("%p %p %p %p %p", pmsg, anscb, data, expirecb, timeout); 369 369 CHECK_PARAMS( pmsg && expirecb && timeout ); 370 370 371 371 return fd_msg_send_int(pmsg, anscb, data, expirecb, timeout); 372 372 } … … 380 380 struct msg_hdr * hdr = NULL; 381 381 struct fd_pei pei; 382 382 383 383 TRACE_ENTRY("%p", msg); 384 384 385 385 CHECK_PARAMS(msg && *msg && error); 386 386 m = *msg; 387 387 *error = NULL; 388 388 389 389 /* Parse the message against our dictionary */ 390 390 ret = fd_msg_parse_rules ( m, fd_g_config->cnf_dict, &pei); … … 392 392 && (ret != ENOTSUP)) /* Command is not supported / Mandatory AVP is not supported */ 393 393 return ret; /* 0 or another error */ 394 394 395 395 /* Log */ 396 396 fd_hook_call(HOOK_MESSAGE_PARSING_ERROR, m, NULL, pei.pei_message ?: pei.pei_errcode, fd_msg_pmdl_get(m)); 397 397 398 398 CHECK_FCT( fd_msg_hdr(m, &hdr) ); 399 399 400 400 /* Now create an answer error if the message is a query */ 401 401 if (hdr->msg_flags & CMD_FLAG_REQUEST) { 402 402 403 403 /* Create the error message */ 404 404 CHECK_FCT( fd_msg_new_answer_from_req ( fd_g_config->cnf_dict, &m, pei.pei_protoerr ? MSGFL_ANSW_ERROR : 0 ) ); 405 405 406 406 /* Set the error code */ 407 407 CHECK_FCT( fd_msg_rescode_set(m, pei.pei_errcode, pei.pei_message, pei.pei_avp, 1 ) ); 408 408 409 409 /* free the pei AVP to avoid memory leak */ 410 410 if (pei.pei_avp_free) { 411 411 fd_msg_free(pei.pei_avp); 412 412 } 413 413 414 414 *msg = NULL; 415 415 *error = m; 416 416 417 417 } else { 418 418 do { /* Rescue error messages */ 419 419 struct avp * avp; 420 420 union avp_value * rc = NULL; 421 421 422 422 /* Search the Result-Code AVP */ 423 423 CHECK_FCT_DO( fd_msg_browse(*msg, MSG_BRW_FIRST_CHILD, &avp, NULL), break ); … … 425 425 struct avp_hdr * ahdr; 426 426 CHECK_FCT_DO( fd_msg_avp_hdr( avp, &ahdr ), break ); 427 427 428 428 if ((ahdr->avp_code == AC_RESULT_CODE) && (! (ahdr->avp_flags & AVP_FLAG_VENDOR)) ) { 429 429 /* 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 } 431 435 rc = ahdr->avp_value; 436 if (rc == NULL) { 437 TRACE_DEBUG(INFO, "invalid Result-Code AVP"); 438 break; 439 } 432 440 break; 433 441 } 434 442 435 443 /* Go to next AVP */ 436 444 CHECK_FCT_DO( fd_msg_browse(avp, MSG_BRW_NEXT, &avp, NULL), break ); 437 445 } 438 446 439 447 if (rc) { 440 448 switch (rc->u32 / 1000) { … … 443 451 /* In these cases, we want the message to validate the ABNF, so we will discard the bad message */ 444 452 break; 445 453 446 454 default: /* Other errors */ 447 455 /* We let the application decide what to do with the message, we rescue it */ … … 451 459 } while (0); 452 460 } 453 461 454 462 return EBADMSG; /* We convert ENOTSUP to EBADMSG as well */ 455 463 }
Note: See TracChangeset
for help on using the changeset viewer.