Пример #1
0
/**
 * Checks if there is a match on REGISTER.
 * Inserts route headers and set the dst_uri
 * @param msg - the message to check
 * @param str1 - if the user was previously registered 0 - for initial registration, 1 for re/de-registration
 * @param str2 - not used
 * @returns #ISC_RETURN_TRUE if found, #ISC_RETURN_FALSE if not
 */
int isc_match_filter_reg(struct sip_msg *msg, char *str1, udomain_t* d) {
    int k;
    isc_match *m;
    str s = {0, 0};
    int ret = ISC_RETURN_FALSE;
    isc_mark old_mark;

    enum dialog_direction dir = DLG_MOBILE_ORIGINATING;

    LM_DBG("Checking triggers\n");

    /* starting or resuming? */
    memset(&old_mark, 0, sizeof (isc_mark));
    LM_DBG("Starting triggering\n");

    /* originating leg */
    if (dir == DLG_MOBILE_ORIGINATING) {
        k = cscf_get_originating_user(msg, &s);
        if (k) {
            if (str1 == 0 || strlen(str1) != 1) {
                LM_ERR("wrong parameter - must be \"0\" (initial registration) or \"1\"(previously registered) \n");
                return ret;
            } else if (str1[0] == '0')
                k = 0;
            else
                k = 1;

            LM_DBG("Orig User <%.*s> [%d]\n", s.len, s.s, k);
            m = isc_checker_find(s, old_mark.direction, old_mark.skip, msg, k, d);
            while (m) {
                LM_DBG("REGISTER match found in filter criteria\n");
                ret = isc_third_party_reg(msg, m, &old_mark);
                old_mark.skip = m->index + 1;
                isc_free_match(m);
                m = isc_checker_find(s, old_mark.direction, old_mark.skip, msg, k, d);
            }

            if (ret == ISC_RETURN_FALSE)
                LM_DBG("No REGISTER match found in filter criteria\n");
        }
    }
    return ret;
}
Пример #2
0
/**
 * Checks if there is a match.
 * Inserts route headers and set the dst_uri
 * @param msg - the message to check
 * @param str1 - the direction of the request orig/term
 * @param str2 - not used
 * @returns #ISC_RETURN_TRUE if found, #ISC_RETURN_FALSE if not, #ISC_RETURN_BREAK on error
 */
int isc_match_filter(struct sip_msg *msg, char *str1, udomain_t* d) {
    int k = 0;
    isc_match *m = NULL;
    str s = {0, 0};

    //sometimes s is populated by an ims_getter method cscf_get_terminating_user that alloc memory that must be free-ed at the end
    int free_s = 0;


    int ret = ISC_RETURN_FALSE;
    isc_mark new_mark, old_mark;

    enum dialog_direction dir = get_dialog_direction(str1);

    LM_INFO("Checking triggers\n");

    if (dir == DLG_MOBILE_UNKNOWN)
        return ISC_RETURN_BREAK;

    if (!cscf_is_initial_request(msg))
        return ISC_RETURN_FALSE;

    /* starting or resuming? */
    memset(&old_mark, 0, sizeof (isc_mark));
    memset(&new_mark, 0, sizeof (isc_mark));
    if (isc_mark_get_from_msg(msg, &old_mark)) {
        LM_DBG("Message returned s=%d;h=%d;d=%d;a=%.*s\n", old_mark.skip, old_mark.handling, old_mark.direction, old_mark.aor.len, old_mark.aor.s);
    } else {
        LM_DBG("Starting triggering\n");
    }

    if (is_route_type(FAILURE_ROUTE)) {
        /* need to find the handling for the failed trigger */
        if (dir == DLG_MOBILE_ORIGINATING) {
            k = cscf_get_originating_user(msg, &s);
            if (k) {
                k = isc_is_registered(&s, d);
                if (k == IMPU_NOT_REGISTERED) {
                    ret = ISC_RETURN_FALSE;
                    goto done;
                }
                new_mark.direction = IFC_ORIGINATING_SESSION;
                LM_DBG("Orig User <%.*s> [%d]\n", s.len, s.s, k);
            } else
                goto done;
        }
        if (dir == DLG_MOBILE_TERMINATING) {
            k = cscf_get_terminating_user(msg, &s);
            //sometimes s is populated by an ims_getter method cscf_get_terminating_user that alloc memory that must be free-ed at the end
            free_s = 1;

            if (k) {
                k = isc_is_registered(&s, d);
                //LOG(L_DBG,"after isc_is_registered in ISC_match_filter\n");
                if (k == IMPU_REGISTERED) {
                    new_mark.direction = IFC_TERMINATING_SESSION;
                } else {
                    new_mark.direction = IFC_TERMINATING_UNREGISTERED;
                }
                LM_DBG("Term User <%.*s> [%d]\n", s.len, s.s, k);
            } else {
                goto done;
            }
        }
        struct cell * t = isc_tmb.t_gett();
        LM_CRIT("SKIP: %d\n", old_mark.skip);
        int index = old_mark.skip;
        for (k = 0; k < t->nr_of_outgoings; k++) {
            m = isc_checker_find(s, new_mark.direction, index, msg,
                    isc_is_registered(&s, d), d);
            if (m) {
                index = m->index;
                if (k < t->nr_of_outgoings - 1)
                    isc_free_match(m);
            } else {
                LM_ERR("On failure, previously matched trigger no longer matches?!\n");
                ret = ISC_RETURN_BREAK;
                goto done;
            }
        }
        if (m->default_handling == IFC_SESSION_TERMINATED) {
            /* Terminate the session */
            LM_DBG("Terminating session.\n");
            isc_tmb.t_reply(msg, IFC_AS_UNAVAILABLE_STATUS_CODE, "AS Contacting Failed - iFC terminated dialog");
            LM_DBG("Responding with %d to URI: %.*s\n",
                    IFC_AS_UNAVAILABLE_STATUS_CODE, msg->first_line.u.request.uri.len, msg->first_line.u.request.uri.s);
            isc_free_match(m);
            ret = ISC_RETURN_BREAK;
            goto done;
        }
        /* skip the failed triggers (IFC_SESSION_CONTINUED) */
        old_mark.skip = index + 1;

        isc_free_match(m);
        isc_mark_drop_route(msg);
    }

    LM_DBG("Checking if ISC is for originating user\n");
    /* originating leg */
    if (dir == DLG_MOBILE_ORIGINATING) {
        k = cscf_get_originating_user(msg, &s);
        LM_DBG("ISC is for Orig user\n");
        if (k) {
            LM_DBG("Orig user is [%.*s]\n", s.len, s.s);
            k = isc_is_registered(&s, d);
            if (k == IMPU_NOT_REGISTERED) {
                LM_DBG("User is not registered\n");
                return ISC_RETURN_FALSE;
            }

            LM_DBG("Orig User <%.*s> [%d]\n", s.len, s.s, k);
            //CHECK if this is a new call (According to spec if the new uri and old mark URI are different then this is a new call and should
            //be triggered accordingly
            LM_DBG("Checking if RURI has changed...comparing: <%.*s> and <%.*s>\n",
                    old_mark.aor.len, old_mark.aor.s,
                    s.len, s.s);
            if ((old_mark.aor.len == s.len) && memcmp(old_mark.aor.s, s.s, s.len) != 0) {
                LM_DBG("This is a new call....... trigger accordingly\n");
                m = isc_checker_find(s, old_mark.direction, 0, msg,
                        isc_is_registered(&s, d), d);
            } else {
                m = isc_checker_find(s, old_mark.direction, old_mark.skip, msg,
                        isc_is_registered(&s, d), d);
            }
            if (m) {
                new_mark.direction = IFC_ORIGINATING_SESSION;
                new_mark.skip = m->index + 1;
                new_mark.handling = m->default_handling;
                new_mark.aor = s;
                ret = isc_forward(msg, m, &new_mark);
                isc_free_match(m);
                goto done;
            }
        }
        goto done;
    }
    LM_DBG("Checking if ISC is for terminating user\n");
    /* terminating leg */
    if (dir == DLG_MOBILE_TERMINATING) {
        k = cscf_get_terminating_user(msg, &s);
        //sometimes s is populated by an ims_getter method cscf_get_terminating_user that alloc memory that must be free-ed at the end
        free_s = 1;
        LM_DBG("ISC is for Term user\n");
        if (k) {
            k = isc_is_registered(&s, d);
            if (k == IMPU_REGISTERED) {
                new_mark.direction = IFC_TERMINATING_SESSION;
            } else {
                new_mark.direction = IFC_TERMINATING_UNREGISTERED;
            }
            LM_DBG("Term User <%.*s> [%d]\n", s.len, s.s, k);
            //CHECK if this is a new call (According to spec if the new uri and old mark URI are different then this is a new call and should
            //be triggered accordingly
            LM_DBG("Checking if RURI has changed...comparing: <%.*s> and <%.*s>\n",
                    old_mark.aor.len, old_mark.aor.s,
                    s.len, s.s);
            if ((old_mark.aor.len == s.len) && memcmp(old_mark.aor.s, s.s, s.len) != 0) {
                LM_DBG("This is a new call....... trigger accordingly\n");
                m = isc_checker_find(s, new_mark.direction, 0, msg, isc_is_registered(&s, d), d);
            } else {
                LM_DBG("Resuming triggering\n");
                m = isc_checker_find(s, new_mark.direction, old_mark.skip, msg, isc_is_registered(&s, d), d);
            }
            if (m) {
                new_mark.skip = m->index + 1;
                new_mark.handling = m->default_handling;
                new_mark.aor = s;
                ret = isc_forward(msg, m, &new_mark);
                isc_free_match(m);
                goto done;
            }
        }
        goto done;
    }

done:

    if (s.s && free_s == 1)
        shm_free(s.s); // shm_malloc in cscf_get_terminating_user  

    if (old_mark.aor.s)
        pkg_free(old_mark.aor.s);
    return ret;
}
Пример #3
0
/**
 * Handle third party registration
 * @param msg - the SIP REGISTER message
 * @param m  - the isc_match that matched with info about where to forward it
 * @param mark  - the isc_mark that should be used to mark the message
 * @returns #ISC_RETURN_TRUE if allowed, #ISC_RETURN_FALSE if not
 */
int isc_third_party_reg(struct sip_msg *msg, isc_match *m, isc_mark *mark, udomain_t* d) {
    r_third_party_registration r;
    str path, path_received;
    int expires = 0;
    str req_uri = {0, 0};
    str to = {0, 0};
    str pvni = {0, 0};
    str pani = {0, 0};
    str cv = {0, 0};
	str s = {0, 0};

	impurecord_t *p;

    struct hdr_field *hdr;

    LM_DBG("isc_third_party_reg: Enter\n");

    /* Set Request Uri to IFC matching server name */
    req_uri.len = m->server_name.len;
    req_uri.s = m->server_name.s;

    /* Get To header*/
    to = cscf_get_public_identity(msg);

	if (cscf_get_originating_user(msg, &s)) {

		isc_ulb.lock_udomain(d, &s);
		if ( isc_ulb.get_impurecord(d,&s,&p) != 0) {
			isc_ulb.unlock_udomain(d, &s);
			LM_ERR("Failed to get IMPU domain from usrloc\n");
			goto no_pai;
		}
		if ( build_p_associated_uri(p->s) != 0) {
			isc_ulb.unlock_udomain(d, &s);
			LM_ERR("Failed to build P-Associated URI for 3rd party reg\n");
			goto no_pai;
		}
		isc_ulb.unlock_udomain(d, &s);
	}

    /*TODO - check if the min/max expires is in the acceptable limits
     * this does not work correctly if the user has multiple contacts
     * and register/deregisters them individually!!!
     */
no_pai:
    expires = cscf_get_max_expires(msg, 0);

    /* Get P-Visited-Network-Id header */
    pvni = cscf_get_visited_network_id(msg, &hdr);
    /* Get P-Access-Network-Info header */
    pani = cscf_get_access_network_info(msg, &hdr);

    if (build_path_vector(msg, &path, &path_received) < 0) {
	LM_ERR("Failed to parse PATH header for third-party reg\n");
	return ISC_RETURN_FALSE;
    }
    LM_DBG("PATH header in REGISTER is [%.*s]\n", path.len, path.s);

    /* Get P-Charging-Vector header */
    /* Just forward the charging header received from P-CSCF */
    /* Todo: implement also according to TS 24.229, chap 5.4.1.7 */
    cv = cscf_get_charging_vector(msg, &hdr);

    if (req_uri.s) {

	memset(&r, 0, sizeof (r_third_party_registration));

	r.req_uri = req_uri;
	r.to = to;
	r.from = isc_my_uri_sip;
	r.pvni = pvni;
	r.pani = pani;
	r.cv = cv;
	if (m->service_info.s && m->service_info.len) {
		r.body.content_type = CT_SERVICE_INFO;
		r.body.content = m->service_info;
	} else if (m->include_register_request) {
		r.body.content_type = CT_REGISTER_REQ;
                r.body.content.s = msg->first_line.u.request.method.s;
		r.body.content.len = msg->len;
	} else if (m->include_register_response) {
		struct bookmark dummy_bm;
		r.body.content_type = CT_REGISTER_RESP;
                r.body.content.s = build_res_buf_from_sip_req(200, &reg_resp_200OK, 0, msg, (unsigned int*)&r.body.content.len, &dummy_bm);
		if (!r.body.content.s) {
			LM_DBG("response building failed for body of third party register request");
			r.body.content_type = CT_NONE;
		}
	} else {
		r.body.content_type = CT_NONE;
	}
	r.path = path;

	if (expires <= 0)
	    r_send_third_party_reg(&r, 0);
	else
	    r_send_third_party_reg(&r, expires + isc_expires_grace);
	return ISC_RETURN_TRUE;
    } else {
	return ISC_RETURN_FALSE;
    }
}