diff --git a/modules/aaa_diameter/aaa_diameter.c b/modules/aaa_diameter/aaa_diameter.c index 9982729486..584f4f372d 100644 --- a/modules/aaa_diameter/aaa_diameter.c +++ b/modules/aaa_diameter/aaa_diameter.c @@ -352,30 +352,26 @@ static int dm_send_request(struct sip_msg *msg, int *app_id, int *cmd_code, goto error; } cJSON_Delete(avps); + avps = NULL; if (_dm_send_message(NULL, dmsg, &rpl) != 0) goto ret; - { - diameter_reply dm_rpl; - memset(&dm_rpl, 0, sizeof dm_rpl); - rc = _dm_get_message_response(rpl, - (rpl_avps_pv ? &rpl_avps : NULL), &dm_rpl); + rc = _dm_get_message_response(rpl, (rpl_avps_pv ? &rpl_avps : NULL)); - dm_last_result_code = dm_rpl.rc; - dm_last_experimental_rc = dm_rpl.experimental_rc; + dm_last_result_code = rpl->rpl.rc; + dm_last_experimental_rc = rpl->experimental_rc; - if (rpl_avps_pv) { - pv_value_t val = {(str){rpl_avps, strlen(rpl_avps)}, 0, PV_VAL_STR}; - if (pv_set_value(msg, rpl_avps_pv, 0, &val) != 0) - LM_ERR("failed to set output rpl_avps pv to: %s\n", rpl_avps); - _dm_release_message_response(rpl, rpl_avps); - } + if (rpl_avps_pv) { + pv_value_t val = {(str){rpl_avps, strlen(rpl_avps)}, 0, PV_VAL_STR}; + if (pv_set_value(msg, rpl_avps_pv, 0, &val) != 0) + LM_ERR("failed to set output rpl_avps pv to: %s\n", rpl_avps); + _dm_release_message_response(rpl, rpl_avps); + } - if (rc != 0) { - LM_ERR("Diameter request failed (rc: %d)\n", rc); - return -3; - } + if (rc != 0) { + LM_ERR("Diameter request failed (rc: %d)\n", rc); + return -3; } return 1; @@ -540,15 +536,12 @@ static int dm_send_request_async_reply(int fd, LM_ERR("could not resume async route!\n"); goto error; } - { - diameter_reply dm_rpl; - memset(&dm_rpl, 0, sizeof dm_rpl); - ret = _dm_get_message_response(amsg->cond, - (amsg->ret ? &rpl_avps : NULL), &dm_rpl); - dm_last_result_code = dm_rpl.rc; - dm_last_experimental_rc = dm_rpl.experimental_rc; - } + ret = _dm_get_message_response(amsg->cond, + (amsg->ret ? &rpl_avps : NULL)); + + dm_last_result_code = amsg->cond->rpl.rc; + dm_last_experimental_rc = amsg->cond->experimental_rc; if (ret == 0) ret = 1; diff --git a/modules/aaa_diameter/app_opensips/avps.c b/modules/aaa_diameter/app_opensips/avps.c index ee381a4833..38b19842c4 100644 --- a/modules/aaa_diameter/app_opensips/avps.c +++ b/modules/aaa_diameter/app_opensips/avps.c @@ -729,7 +729,8 @@ create_avp:; LOG_DBG("registered custom AVP (%s, code %d, type %s, enc %s, sub-avps: %d, vendor: %d)\n", nt_name, avp_code, avp_type2str(avp_type), enc_type2str(enc_type), avp_count, vendor_id); - free(nt_name); + if (nt_name) + free(nt_name); return 0; error: LOG_ERROR("failed to parse line: %s\n", line); @@ -889,7 +890,9 @@ int parse_command_def(char *line, FILE *fp, int cmd_type) unsigned int cmd_code = -1; char *p = line, cmd_name[128 + 1], *bkp, *newp; size_t buflen = strlen(line); - int i, len = buflen, cmd_name_len = -1, avp_count = 0; + size_t len = buflen; + ssize_t read; + int i, cmd_name_len = -1, avp_count = 0; struct dm_avp_def avps[128]; switch (cmd_type) { @@ -938,14 +941,17 @@ int parse_command_def(char *line, FILE *fp, int cmd_type) LOG_DBG("parsed Cmd-Code %d (%s)\n", cmd_code, cmd_name); - while (getline(&line, &buflen, fp) >= 0) { + free(line); + line = NULL; + len = 0; + while ((read = getline(&line, &buflen, fp)) >= 0) { p = line; len = strlen(p); while (isspace(*p)) { p++; len--; } if (*p == '{') - continue; + goto next; if (*p == '}' || !strlen(p)) goto define_req; @@ -959,6 +965,10 @@ int parse_command_def(char *line, FILE *fp, int cmd_type) LOG_ERROR("failed to parse Command AVP line: '%s'\n", line); return -1; } +next: + free(line); + line = NULL; + len = 0; } define_req: @@ -1057,14 +1067,14 @@ int parse_extra_avps(const char *extra_avps_file) // comment or empty line if (*p == '#' || p - line >= read) - continue; + goto next; rc = parse_app_vendor(p, fp); if (rc < 0) { ret = -1; goto out; } else if (rc == 0) { - continue; + goto next; } rc = parse_attr_def(p, fp); @@ -1072,7 +1082,7 @@ int parse_extra_avps(const char *extra_avps_file) ret = -1; goto out; } else if (rc == 0) { - continue; + goto next; } rc = parse_app_def(p, fp); @@ -1080,7 +1090,7 @@ int parse_extra_avps(const char *extra_avps_file) ret = -1; goto out; } else if (rc == 0) { - continue; + goto next; } rc = parse_command_def(p, fp, CMD_REQUEST); @@ -1089,7 +1099,7 @@ int parse_extra_avps(const char *extra_avps_file) goto out; } else if (rc == 0) { answers_needed++; - continue; + goto next; } rc = parse_command_def(p, fp, CMD_ANSWER); @@ -1101,6 +1111,11 @@ int parse_extra_avps(const char *extra_avps_file) continue; } + next: + free(line); + line = NULL; + len = 0; + // unknown line... ignoring } @@ -1112,7 +1127,6 @@ int parse_extra_avps(const char *extra_avps_file) out: fclose(fp); - free(line); return ret; } diff --git a/modules/aaa_diameter/diameter_api.h b/modules/aaa_diameter/diameter_api.h index a104d14f59..1071b3d9c2 100644 --- a/modules/aaa_diameter/diameter_api.h +++ b/modules/aaa_diameter/diameter_api.h @@ -34,9 +34,7 @@ typedef struct { cJSON *json; int is_error; - int rc; /* Result-Code AVP (268) */ - int experimental_rc; /* Experimental-Result-Code AVP (298) */ - int vendor_id; /* Vendor-Id from Experimental-Result (266) */ + int rc; } diameter_reply; /* diff --git a/modules/aaa_diameter/dm_impl.c b/modules/aaa_diameter/dm_impl.c index 4e988f10f6..62ce84defb 100644 --- a/modules/aaa_diameter/dm_impl.c +++ b/modules/aaa_diameter/dm_impl.c @@ -53,6 +53,7 @@ struct fd_msg_list { * to consume them */ struct list_head dm_unreplied_req; gen_lock_t dm_unreplied_req_lk; +gen_lock_t dm_inbound_req_lk; unsigned int dm_unreplied_req_timeout = 120; /* sec */ @@ -543,6 +544,9 @@ static int dm_receive_req(struct msg **_req, struct avp * avp, struct session * struct msg_hdr *hdr = NULL; str tid = STR_NULL, avp_arr = STR_NULL; + /* Request lock for inbound requests */ + lock_get(&dm_inbound_req_lk); + FD_CHECK(fd_msg_hdr(req, &hdr)); LM_DBG("received Diameter request (appl: %u, cmd: %u)\n", hdr->msg_appl, hdr->msg_code); @@ -610,6 +614,9 @@ static int dm_receive_req(struct msg **_req, struct avp * avp, struct session * cJSON_Delete(avps); cJSON_InitHooks(NULL); + /* Release lock */ + lock_release(&dm_inbound_req_lk); + *_req = NULL; *act = DISP_ACT_CONT; return 0; @@ -713,15 +720,17 @@ static int dm_receive_msg(struct msg **_msg, struct avp * avp, struct session * if (rc == 0 && a) { struct avp *child = NULL; fd_msg_browse(a, MSG_BRW_FIRST_CHILD, &child, NULL); + while (child) { rc = fd_msg_avp_hdr(child, &h); if (rc == 0) { - if (h->avp_code == 298) { - rpl_cond->rpl.experimental_rc = h->avp_value->u32; - LM_DBG("Experimental-Result-Code: %u\n", h->avp_value->u32); + if (h->avp_code == 298 && h->avp_value) { + rpl_cond->experimental_rc = h->avp_value->u32; + LM_DBG("Experimental-Result-Code: %u\n", h->avp_value->u32); + if (h->avp_value->u32 < 2000 || h->avp_value->u32 >= 3000) rpl_cond->rpl.is_error = 1; - } else if (h->avp_code == 266) { - rpl_cond->rpl.vendor_id = h->avp_value->u32; + } else if (h->avp_code == 266 && h->avp_value) { + rpl_cond->vendor_id = h->avp_value->u32; LM_DBG("Experimental-Result Vendor-Id: %u\n", h->avp_value->u32); } } @@ -2024,8 +2033,7 @@ static int _dm_get_message_reply(struct dm_cond *cond, diameter_reply *rpl) return (cond->rpl.is_error?-1:0); } -int _dm_get_message_response(struct dm_cond *cond, char **rpl_avps, - diameter_reply *rpl_out) +int _dm_get_message_response(struct dm_cond *cond, char **rpl_avps) { cJSON *obj; diameter_reply rpl; @@ -2036,10 +2044,6 @@ int _dm_get_message_response(struct dm_cond *cond, char **rpl_avps, *rpl_avps = cJSON_PrintUnformatted(obj); LM_DBG("AVPs: %s\n", *rpl_avps); } - - if (rpl_out) - *rpl_out = rpl; - return rc; } diff --git a/modules/aaa_diameter/dm_impl.h b/modules/aaa_diameter/dm_impl.h index 47fa7c7dfb..92b52b9d11 100644 --- a/modules/aaa_diameter/dm_impl.h +++ b/modules/aaa_diameter/dm_impl.h @@ -141,11 +141,15 @@ struct dm_cond { } sync; diameter_reply rpl; + + int experimental_rc; /* Experimental-Result-Code AVP (298) */ + int vendor_id; /* Vendor-Id from Experimental-Result (266) */ }; int init_mutex_cond(pthread_mutex_t *mutex, pthread_cond_t *cond); extern struct list_head dm_unreplied_req; extern gen_lock_t dm_unreplied_req_lk; +extern gen_lock_t dm_inbound_req_lk; extern unsigned int dm_unreplied_req_timeout; extern char *dm_conf_filename; extern char *extra_avps_file; @@ -172,8 +176,7 @@ int dm_build_avps(struct list_head *subavps, cJSON *array); int dm_send_message(aaa_conn *_, aaa_message *req, aaa_message **__); int _dm_send_message(aaa_conn *_, aaa_message *req, struct dm_cond **reply_cond); int _dm_send_message_async(aaa_conn *_, aaa_message *req, int *fd); -int _dm_get_message_response(struct dm_cond *cond, char **rpl_avps, - diameter_reply *rpl_out); +int _dm_get_message_response(struct dm_cond *cond, char **rpl_avps); void _dm_release_message_response(struct dm_cond *cond, char *rpl_avps); int dm_destroy_message(aaa_conn *con, aaa_message *msg); void _dm_destroy_message(aaa_message *msg); diff --git a/modules/aaa_diameter/dm_peer.c b/modules/aaa_diameter/dm_peer.c index 0a6c73db6f..7ae5718fe4 100644 --- a/modules/aaa_diameter/dm_peer.c +++ b/modules/aaa_diameter/dm_peer.c @@ -66,6 +66,7 @@ int dm_init_peer(void) INIT_LIST_HEAD(&dm_unreplied_req); lock_init(&dm_unreplied_req_lk); + lock_init(&dm_inbound_req_lk); return 0; } diff --git a/modules/tm/async.c b/modules/tm/async.c index a22649dbf1..25ceec4368 100644 --- a/modules/tm/async.c +++ b/modules/tm/async.c @@ -131,7 +131,8 @@ int t_resume_async_request(int fd, void*param, int was_timeout) backup_list = set_avp_list( &t->user_avps ); /* set default send address to the saved value */ backup_si = bind_address; - bind_address = TM_BRANCH( t, 0).request.dst.send_sock; + if (t->uac[0]) + bind_address = TM_BRANCH( t, 0).request.dst.send_sock; async_status = ASYNC_DONE; /* assume default status as done */ /* call the resume function in order to read and handle data */