/** * Every time a new dialog is created (from a new INVITE) the dialog * module will call this callback function. We need to track the * dialogs lifespan from this point forward until it is terminated * with a BYE, CANCEL, etc. In the process, we will see if either or * both ends of the conversation are trying to re-negotiate the media. * * This function will setup the other types of dialog callbacks * required to track the lifespan of the dialog. * * * @param did - The dialog ID * @param type - The trigger event type (CREATED) * @param msg - The SIP message that triggered the callback (INVITE) * @param param - The pointer to nothing. As we did not attach * anything to this callback in the dialog module. */ void qos_dialog_created_CB(struct dlg_cell *did, int type, struct dlg_cb_params * params) { qos_ctx_t *qos_ctx = NULL; struct sip_msg* msg = params->req; unsigned int dir = params->direction, role, other_role; if (dir == DLG_DIR_UPSTREAM) { role = QOS_CALLEE; other_role = QOS_CALLER; } else if (dir == DLG_DIR_DOWNSTREAM) { role = QOS_CALLER; other_role = QOS_CALLEE; } else { LM_ERR("Unknown dir %d\n", dir); return; } if (msg == NULL || msg == FAKED_REPLY) { LM_ERR("Improper msg\n"); return; } /* look only at INVITE */ if (msg->first_line.type != SIP_REQUEST || msg->first_line.u.request.method_value != METHOD_INVITE) { LM_WARN("Dialog create callback called with a non-INVITE req.\n"); return; } qos_ctx = build_new_qos_ctx(); if (qos_ctx==NULL) { /* Error message printed in build_new_qos_ctx() */ return; } LM_DBG("setup_dialog_callbacks( %p , %p )\n", did, qos_ctx); setup_dialog_callbacks(did, qos_ctx); run_create_cbs(qos_ctx, msg); if (0 == parse_sdp(msg)) { lock_get(&qos_ctx->lock); add_sdp(qos_ctx, dir, msg, role, other_role); lock_release(&qos_ctx->lock); } return; }
void sst_dialog_loaded_CB(struct dlg_cell *did, int type, struct dlg_cb_params *params){ /* Check if this is previously marked by sst module */ if (!dlg_binds->is_mod_flag_set(did, SST_DIALOG_FLAG)) return; /* We try to get the original sst info back */ sst_info_t *info = (sst_info_t *)shm_malloc(sizeof(sst_info_t)); if (info == NULL) { LM_ERR ("No more shared memory!\n"); return; } str raw_info = {(char*)info, sizeof(sst_info_t)}; if (dlg_binds->fetch_dlg_value(did, &info_val_name, &raw_info, 1) != 0){ LM_ERR ("No sst_info found!\n"); return; } setup_dialog_callbacks(did, info); }
/** * Every time a new dialog is created (from a new INVITE) the dialog * module will call this callback function. We need to track the * dialogs lifespan from this point forward until it is terminated * with a BYE, CANCEL, etc. In the process, we will see if either or * both ends of the conversation supports SIP Session Timers and setup * the dialog timeout to expire at the session timer expire time. Each * time the new re-INVITE is seen to update the SST, we will reset the * life span of the dialog to match it. * * This function will setup the other types of dialog callbacks * required to track the lifespan of the dialog. It will also start * the state tracking to figure out if and who supports SST. * * As per RFC4028: Request handling: * * - The proxy may insert a SE header if none found. * - The SE value can be anything >= Min-SE (if found) * - The proxy MUST NOT add a refresher parameter to the SE. * * - If SE is already there, the Proxy can reduce its value but no * lower then the Min-SE value if present. * - If the SE value is >= Min-SE the proxy MUST NOT increase it! * - If the SE value is < Min-SE (settable by the proxy) the proxy * MUST increase the SE value to >= the new Min-SE. * - The proxy MUST NOT insert or change the refresher parameter. * * - If the supported=timer is found, the proxy may reject the request * with a 422 if the SE value is smaller then the local policy. The * 422 MUST hold the proxies Min-SE value >= 90. * - If support=timer is NOT indecated, the proxy can't reject with a * 422 but can include/increase the MIN-SE: to be = to local policy. * and increase the SE to match the new Min-SE value. * - the proxy MUST NOT insert/change the Min-SE header if * supported=timer is present. (DoS attacks) * * @param did - The dialog ID * @param type - The trigger event type (CREATED) * @param params - The pointer to nothing. As we did not attach * anything to this callback in the dialog module. */ void sst_dialog_created_CB(struct dlg_cell *did, int type, struct dlg_cb_params * params) { sst_info_t *info = NULL; sst_msg_info_t minfo; struct sip_msg* msg = params->msg; memset(&minfo, 0, sizeof(sst_msg_info_t)); /* * Only deal with messages flaged as SST interested. */ if ((msg->flags & sst_flag) != sst_flag) { LM_DBG("SST flag was not set for this request\n"); return; } /* * look only at INVITE */ if (msg->first_line.type != SIP_REQUEST || msg->first_line.u.request.method_value != METHOD_INVITE) { LM_WARN("dialog create callback called with a non-INVITE request.\n"); return; } /* * Gather all he information about SST for this message */ if (parse_msg_for_sst_info(msg, &minfo)) { LM_ERR("failed to parse sst information\n"); return; } info = (sst_info_t *)shm_malloc(sizeof(sst_info_t)); memset(info, 0, sizeof(sst_info_t)); info->requester = (minfo.se?SST_UAC:SST_UNDF); info->supported = (minfo.supported?SST_UAC:SST_UNDF); info->interval = MAX(sst_interval, 90); /* For now, will set for real * later */ if (minfo.se != 0) { /* * There is a SE already there, this is good, we just need to * check the values out a little before passing it along. */ if (minfo.se < sst_min_se) { /* * Problem, the requested Session-Expires is too small for * our local policy. We need to fix it, or reject it or * ignore it. */ if (!minfo.supported) { /* * Increase the Min-SE: value in the request and * forward it. */ char buf[80]; if (minfo.min_se) { /* We need to update, which means, remove + * insert */ remove_minse_header(msg); } info->interval = MAX(sst_min_se, minfo.min_se); snprintf(buf, 80, "Min-SE: %d\r\n", info->interval); if (append_header(msg, buf)) { LM_ERR("Could not append modified Min-SE: header\n"); } } else if (sst_reject) { /* Make sure that that all are at least 90 */ send_reject(msg, MAX(MAX(sst_min_se, minfo.min_se), 90)); shm_free(info); return; } } /* end of se < sst_min_se */ else { /* Use the INVITE SE: value */ info->interval = minfo.se; } } else { /* * No Session-Expire: stated in request. */ char buf[80]; info->interval = MAX(minfo.min_se, sst_min_se); if (minfo.min_se && minfo.min_se < sst_min_se) { remove_minse_header(msg); snprintf(buf, 80, "Min-SE: %d\r\n", info->interval); if (append_header(msg, buf)) { LM_ERR("failed to append modified Min-SE: header\n"); /* What to do? Let is slide, we can still work */ } } info->interval = MAX(info->interval, sst_interval); info->requester = SST_PXY; snprintf(buf, 80, "Session-Expires: %d\r\n", info->interval); if (append_header(msg, buf)) { LM_ERR("failed to append Session-Expires header to proxy " "requested SST.\n"); shm_free(info); return; /* Nothing we can do! */ } } /* We keep the sst_info in the dialog's vals in case of restarting */ /* No const here because of store_dlg_value's definition */ str raw_info = {(char*)info, sizeof(sst_info_t)}; if (dlg_binds->store_dlg_value(did, &info_val_name, &raw_info) != 0) { LM_ERR("No sst_info can be added to the dialog." "This dialog won't be considered after restart!\n"); } dlg_binds->set_mod_flag(did, SST_DIALOG_FLAG); setup_dialog_callbacks(did, info); /* Early setup of default timeout */ set_dialog_lifetime(did, info->interval); return; }
/** * Every time a new dialog is created (from a new INVITE) the dialog * module will call this callback function. We need to track the * dialogs lifespan from this point forward until it is terminated * with a BYE, CANCEL, etc. In the process, we will see if either or * both ends of the conversation supports SIP Session Timers and setup * the dialog timeout to expire at the session timer expire time. Each * time the new re-INVITE is seen to update the SST, we will reset the * life span of the dialog to match it. * * This function will setup the other types of dialog callbacks * required to track the lifespan of the dialog. It will also start * the state tracking to figure out if and who supports SST. * * As per RFC4028: Request handling: * * - The proxy may insert a SE header if none found. * - The SE value can be anything >= Min-SE (if found) * - The proxy MUST NOT add a refresher parameter to the SE. * * - If SE is already there, the Proxy can reduce its value but no * lower then the Min-SE value if present. * - If the SE value is >= Min-SE the proxy MUST NOT increase it! * - If the SE value is < Min-SE (settable by the proxy) the proxy * MUST increase the SE value to >= the new Min-SE. * - The proxy MUST NOT insert or change the refresher parameter. * * - If the supported=timer is found, the proxy may reject the request * with a 422 if the SE value is smaller then the local policy. The * 422 MUST hold the proxies Min-SE value >= 90. * - If support=timer is NOT indecated, the proxy can't reject with a * 422 but can include/increase the MIN-SE: to be = to local policy. * and increase the SE to match the new Min-SE value. * - the proxy MUST NOT insert/change the Min-SE header if * supported=timer is present. (DoS attacks) * * @param did - The dialog ID * @param type - The trigger event type (CREATED) * @param params - The pointer to nothing. As we did not attach * anything to this callback in the dialog module. */ void sst_dialog_created_CB(struct dlg_cell *did, int type, struct dlg_cb_params * params) { sst_info_t *info = NULL; sst_msg_info_t minfo; struct sip_msg* msg = params->req; memset(&minfo, 0, sizeof(sst_msg_info_t)); /* * Only deal with messages flaged as SST interested. */ if ((msg->flags & sst_flag) != sst_flag) { LM_DBG("SST flag was not set for this request\n"); return; } /* * look only at INVITE */ if (msg->first_line.type != SIP_REQUEST || msg->first_line.u.request.method_value != METHOD_INVITE) { LM_WARN("dialog create callback called with a non-INVITE request.\n"); return; } /* * Gather all he information about SST for this message */ if (parse_msg_for_sst_info(msg, &minfo)) { LM_ERR("failed to parse sst information\n"); return; } info = (sst_info_t *)shm_malloc(sizeof(sst_info_t)); memset(info, 0, sizeof(sst_info_t)); info->requester = (minfo.se?SST_UAC:SST_UNDF); info->supported = (minfo.supported?SST_UAC:SST_UNDF); info->interval = MAX(sst_min_se, 90); /* For now, will set for real * later */ if (minfo.se != 0) { /* * There is a SE already there, this is good, we just need to * check the values out a little before passing it along. */ if (minfo.se < sst_min_se) { /* * Problem, the requested Session-Expires is too small for * our local policy. We need to fix it, or reject it or * ignore it. */ if (!minfo.supported) { /* * Increase the Min-SE: value in the request and * forward it. */ str msehdr; if (minfo.min_se) { /* We need to update, which means, remove + * insert */ remove_header(msg, "Min-SE"); } info->interval = MAX(sst_min_se, minfo.min_se); sst_build_minse_hdr(info->interval, &msehdr); if (append_header(msg, msehdr.s)) { LM_ERR("Could not append modified Min-SE: header\n"); } } else if (sst_reject) { /* Make sure that that all are at least 90 */ send_reject(msg, MAX(MAX(sst_min_se, minfo.min_se), 90)); shm_free(info); return; } } /* end of se < sst_min_se */ else { /* Use the INVITE SE: value */ info->interval = minfo.se; } } else { /* * No Session-Expire: stated in request. */ str msehdr; info->interval = MAX(minfo.min_se, sst_min_se); if (minfo.min_se && minfo.min_se < sst_min_se) { remove_header(msg, "Min-SE"); sst_build_minse_hdr(info->interval, &msehdr); if (append_header(msg, msehdr.s)) { LM_ERR("failed to append modified Min-SE: header\n"); /* What to do? Let is slide, we can still work */ } } info->requester = SST_PXY; sst_build_se_hdr(info->interval, &msehdr, NULL); if (append_header(msg, msehdr.s)) { LM_ERR("failed to append Session-Expires header to proxy " "requested SST.\n"); shm_free(info); return; /* Nothing we can do! */ } } setup_dialog_callbacks(did, info); set_timeout_avp(msg, info->interval); return; }