Example #1
0
int th_prepare_msg(sip_msg_t *msg)
{
	if (parse_msg(msg->buf, msg->len, msg)!=0)
	{
		LM_DBG("outbuf buffer parsing failed!");
		return 1;
	}

	if(msg->first_line.type==SIP_REQUEST)
	{
		if(!IS_SIP(msg))
		{
			LM_DBG("non sip request message\n");
			return 1;
		}
	} else if(msg->first_line.type!=SIP_REPLY) {
		LM_DBG("non sip message\n");
		return 1;
	}

	if (parse_headers(msg, HDR_EOH_F, 0)==-1)
	{
		LM_DBG("parsing headers failed [[%.*s]]\n",
				msg->len, msg->buf);
		return 2;
	}

	/* force 2nd via parsing here - it helps checking it later */
	if (parse_headers(msg, HDR_VIA2_F, 0)==-1
		|| (msg->via2==0) || (msg->via2->error!=PARSE_OK))
	{
		LM_DBG("no second via in this message \n");
	}

	if(parse_from_header(msg)<0)
	{
		LM_ERR("cannot parse FROM header\n");
		return 3;
	}

	if(parse_to_header(msg)<0 || msg->to==NULL)
	{
		LM_ERR("cannot parse TO header\n");
		return 3;
	}

	if(get_to(msg)==NULL)
	{
		LM_ERR("cannot get TO header\n");
		return 3;
	}

	if(msg->via1==NULL || msg->callid==NULL) {
		LM_ERR("mandatory headers missing - via1: %p callid: %p\n",
				msg->via1, msg->callid);
		return 4;
	}

	return 0;
}
Example #2
0
int uac_reg_tmdlg(dlg_t *tmdlg, sip_msg_t *rpl)
{
	if(tmdlg==NULL || rpl==NULL)
		return -1;

	if (parse_headers(rpl, HDR_EOH_F, 0) < 0) {
		LM_ERR("error while parsing all headers in the reply\n");
		return -1;
	}
	if(parse_to_header(rpl)<0 || parse_from_header(rpl)<0) {
		LM_ERR("error while parsing From/To headers in the reply\n");
		return -1;
	}
	memset(tmdlg, 0, sizeof(dlg_t));

	str2int(&(get_cseq(rpl)->number), &tmdlg->loc_seq.value);
	tmdlg->loc_seq.is_set = 1;

	tmdlg->id.call_id = rpl->callid->body;
	trim(&tmdlg->id.call_id);

	if (get_from(rpl)->tag_value.len) {
		tmdlg->id.loc_tag = get_from(rpl)->tag_value;
	}
#if 0
	if (get_to(rpl)->tag_value.len) {
		tmdlg->id.rem_tag = get_to(rpl)->tag_value;
	}
#endif
	tmdlg->loc_uri = get_from(rpl)->uri;
	tmdlg->rem_uri = get_to(rpl)->uri;
	tmdlg->state= DLG_CONFIRMED;
	return 0;
}
Example #3
0
sip_uri_t *parse_to_uri(sip_msg_t* const msg)
{
	to_body_t *tb = NULL;
	
	if(msg==NULL)
		return NULL;

	if(parse_to_header(msg)<0)
	{
		LM_ERR("cannot parse TO header\n");
		return NULL;
	}

	if(msg->to==NULL || get_to(msg)==NULL)
		return NULL;

	tb = get_to(msg);
	
	if(tb->parsed_uri.user.s!=NULL || tb->parsed_uri.host.s!=NULL)
		return &tb->parsed_uri;

	if (parse_uri(tb->uri.s, tb->uri.len , &tb->parsed_uri)<0)
	{
		LM_ERR("failed to parse To uri\n");
		memset(&tb->parsed_uri, 0, sizeof(struct sip_uri));
		return NULL;
	}

	return &tb->parsed_uri;
}
Example #4
0
static int sip_trace_prepare(sip_msg_t *msg)
{
	if(parse_from_header(msg)==-1 || msg->from==NULL || get_from(msg)==NULL) {
		LM_ERR("cannot parse FROM header\n");
		goto error;
	}

	if(parse_to_header(msg)==-1 || msg->to==NULL || get_to(msg)==NULL) {
		LM_ERR("cannot parse To header\n");
		goto error;
	}

	if(parse_headers(msg, HDR_CALLID_F, 0)!=0 || msg->callid==NULL
			|| msg->callid->body.s==NULL) {
		LM_ERR("cannot parse call-id\n");
		goto error;
	}

	if(msg->cseq==NULL && ((parse_headers(msg, HDR_CSEQ_F, 0)==-1)
				|| (msg->cseq==NULL)))
	{
		LM_ERR("cannot parse cseq\n");
		goto error;
	}

	return 0;
error:
	return -1;
}
Example #5
0
static int dlg_cseq_prepare_msg(sip_msg_t *msg)
{
	LM_DBG("prepare msg for cseq update operations\n");

	if(msg->first_line.type==SIP_REQUEST) {
		if(!IS_SIP(msg)) {
			LM_DBG("non sip request message\n");
			return 1;
		}
	} else if(msg->first_line.type==SIP_REPLY) {
		if(!IS_SIP_REPLY(msg)) {
			LM_DBG("non sip reply message\n");
			return 1;
		}
	} else {
		LM_DBG("non sip message\n");
		return 1;
	}

	if((!msg->cseq && (parse_headers(msg,HDR_CSEQ_F,0)<0 || !msg->cseq))
		|| !msg->cseq->parsed){
		LM_DBG("parsing cseq header failed\n");
		return 2;
	}

	if(msg->first_line.type==SIP_REPLY) {
		/* reply to local transaction -- nothing to do */
		if (parse_headers(msg, HDR_VIA2_F, 0)==-1
				|| (msg->via2==0) || (msg->via2->error!=PARSE_OK)) {
			if(get_cseq(msg)->method_id != METHOD_CANCEL) {
				LM_DBG("no second via in this message \n");
				return 3;
			}
		}
	}

	if(parse_from_header(msg)<0) {
		LM_ERR("cannot parse FROM header\n");
		return 3;
	}

	if(parse_to_header(msg)<0 || msg->to==NULL) {
		LM_ERR("cannot parse TO header\n");
		return 3;
	}

	if(get_to(msg)==NULL) {
		LM_ERR("cannot get TO header\n");
		return 3;
	}

	return 0;
}
Example #6
0
int dlg_cseq_prepare_msg(sip_msg_t *msg)
{
	if (parse_msg(msg->buf, msg->len, msg)!=0) {
		LM_DBG("outbuf buffer parsing failed!");
		return 1;
	}

	if(msg->first_line.type==SIP_REQUEST) {
		if(!IS_SIP(msg))
		{
			LM_DBG("non sip request message\n");
			return 1;
		}
	} else if(msg->first_line.type!=SIP_REPLY) {
		LM_DBG("non sip message\n");
		return 1;
	}

	if (parse_headers(msg, HDR_CSEQ_F, 0)==-1) {
		LM_DBG("parsing cseq header failed\n");
		return 2;
	}

	if(msg->first_line.type==SIP_REPLY) {
		/* reply to local transaction -- nothing to do */
		if (parse_headers(msg, HDR_VIA2_F, 0)==-1
				|| (msg->via2==0) || (msg->via2->error!=PARSE_OK)) {
			LM_DBG("no second via in this message \n");
			return 3;
		}
	}

	if(parse_from_header(msg)<0)
	{
		LM_ERR("cannot parse FROM header\n");
		return 3;
	}

	if(parse_to_header(msg)<0 || msg->to==NULL)
	{
		LM_ERR("cannot parse TO header\n");
		return 3;
	}

	if(get_to(msg)==NULL)
	{
		LM_ERR("cannot get TO header\n");
		return 3;
	}

	return 0;
}
Example #7
0
int dlg_th_callid_pre_parse(struct sip_msg *msg,int want_from)
{
#ifdef CHANGEABLE_DEBUG_LEVEL
	int prev_dbg_level;
#endif

#ifdef CHANGEABLE_DEBUG_LEVEL
	prev_dbg_level = *debug;
	*debug = L_ALERT; 
#endif

	if (parse_msg(msg->buf,msg->len,msg)!=0) {
		LM_ERR("Invalid SIP msg\n");
		goto error;
	}

	if (parse_headers(msg,HDR_EOH_F,0)<0) {
		LM_ERR("Failed to parse SIP headers\n");
		goto error;
	}

	if (msg->cseq==NULL || get_cseq(msg)==NULL) {
		LM_ERR("Failed to parse CSEQ header\n");
		goto error;
	}       

	if((get_cseq(msg)->method_id)&MSG_SKIP_BITMASK) {
		LM_DBG("Skipping %d for DLG callid topo hiding\n",get_cseq(msg)->method_id);
		goto error;
	}

	if (parse_to_header(msg)<0 || msg->to==NULL || get_to(msg)==NULL) {
		LM_ERR("cannot parse TO header\n");
		goto error;
	}

	if (parse_from_header(msg)<0 || msg->from==NULL || get_from(msg)==NULL) {
		LM_ERR("cannot parse TO header\n");
		goto error;
	}

#ifdef CHANGEABLE_DEBUG_LEVEL
	*debug = prev_dbg_level; 
#endif
	return 0;

error:
#ifdef CHANGEABLE_DEBUG_LEVEL
	*debug = prev_dbg_level; 
#endif
	return -1;
}
Example #8
0
int registered4(struct sip_msg* _m, udomain_t* _d, str* _uri, int match_flag,
		int match_action_flag)
{
	str uri, aor;
	urecord_t* r;
	ucontact_t* ptr;
	int res;
	str match_callid = {0,0};
	str match_received = {0,0};
	str match_contact = {0,0};
	sr_xavp_t *vavp = NULL;

	if(_uri!=NULL)
	{
		uri = *_uri;
	} else {
		if(IS_SIP_REPLY(_m)) {
			if (parse_to_header(_m) < 0) {
				LM_ERR("failed to prepare the message\n");
				return -1;
			}
			uri = get_to(_m)->uri;
		} else {
			if (_m->new_uri.s) uri = _m->new_uri;
			else uri = _m->first_line.u.request.uri;
		}
	}

	if (extract_aor(&uri, &aor, NULL) < 0) {
		LM_ERR("failed to extract address of record\n");
		return -1;
	}

	ul.lock_udomain(_d, &aor);
	res = ul.get_urecord(_d, &aor, &r);

	if (res < 0) {
		ul.unlock_udomain(_d, &aor);
		LM_ERR("failed to query usrloc\n");
		return -1;
	}

	if (res == 0) {
		LM_DBG("searching with match flags (%d,%d)\n", match_flag,
				match_action_flag);
		if(reg_xavp_cfg.s!=NULL) {

			if((match_flag & 1)
					&& (vavp = xavp_get_child_with_sval(&reg_xavp_cfg,
							&match_callid_name)) != NULL
					&& vavp->val.v.s.len > 0) {
				match_callid = vavp->val.v.s;
				LM_DBG("matching with callid %.*s\n", match_callid.len,
						match_callid.s);
			}

			if((match_flag & 2)
					&& (vavp = xavp_get_child_with_sval(&reg_xavp_cfg,
							&match_received_name)) != NULL
					&& vavp->val.v.s.len > 0) {
				match_received = vavp->val.v.s;
				LM_DBG("matching with received %.*s\n", match_received.len,
						match_received.s);
			}

			if((match_flag & 4)
					&& (vavp = xavp_get_child_with_sval(&reg_xavp_cfg,
							&match_contact_name)) != NULL
					&& vavp->val.v.s.len > 0) {
				match_contact = vavp->val.v.s;
				LM_DBG("matching with contact %.*s\n", match_contact.len,
						match_contact.s);
			}
		}

		for (ptr = r->contacts; ptr; ptr = ptr->next) {
			if(!VALID_CONTACT(ptr, act_time)) continue;
			if (match_callid.s && /* optionally enforce tighter matching w/ Call-ID */
				match_callid.len > 0 &&
				(match_callid.len != ptr->callid.len ||
				memcmp(match_callid.s, ptr->callid.s, match_callid.len)))
				continue;
			if (match_received.s && /* optionally enforce tighter matching w/ ip:port */
				match_received.len > 0 &&
				(match_received.len != ptr->received.len ||
				memcmp(match_received.s, ptr->received.s, match_received.len)))
				continue;
			if (match_contact.s && /* optionally enforce tighter matching w/ Contact */
				match_contact.len > 0 &&
				(match_contact.len != ptr->c.len ||
				memcmp(match_contact.s, ptr->c.s, match_contact.len)))
				continue;

			if(!(match_action_flag & 2)) {
				xavp_rcd_helper(ptr);
			}

			if((ptr->xavp!=NULL) && (match_action_flag & 1)) {
				sr_xavp_t *xavp = xavp_clone_level_nodata(ptr->xavp);
				if(xavp_add(xavp, NULL)<0) {
					LM_ERR("error adding xavp for %.*s after successful match\n",
							aor.len, ZSW(aor.s));
					xavp_destroy_list(&xavp);
				}
			}

			ul.release_urecord(r);
			ul.unlock_udomain(_d, &aor);
			LM_DBG("'%.*s' found in usrloc\n", aor.len, ZSW(aor.s));

			return 1;
		}
	}

	ul.unlock_udomain(_d, &aor);
	LM_DBG("'%.*s' not found in usrloc\n", aor.len, ZSW(aor.s));
	return -1;
}
Example #9
0
static int has_to_tag(struct sip_msg* msg)
{
	if (parse_to_header(msg) < 0) return 0;
	return (get_to(msg)->tag_value.len > 0) ? 1 : 0;
}
Example #10
0
int record_route_advertised_address(struct sip_msg* _m, str* _data)
{
    str user = {NULL, 0};
    str *tag = NULL;
    struct lump* l;
    struct lump* l2;
    int use_ob = rr_obb.use_outbound ? rr_obb.use_outbound(_m) : 0;
    int sips;
    int ret = 0;

    user.len = 0;
    user.s = 0;

    if (add_username) {
        if (get_username(_m, &user) < 0) {
            LM_ERR("failed to extract username\n");
            return -1;
        }
    } else if (use_ob == 1) {
        if (rr_obb.encode_flow_token(&user, _m->rcv) != 0) {
            LM_ERR("encoding outbound flow-token\n");
            return -1;
        }
    } else if (use_ob == 2) {
        if (copy_flow_token(&user, _m) != 0) {
            LM_ERR("copying outbound flow-token\n");
            return -1;
        }
    }

    if (append_fromtag) {
        if (is_direction(_m, RR_FLOW_UPSTREAM) == 0) {
            if (parse_to_header(_m) < 0) {
                LM_ERR("To parsing failed\n");
                ret = -2;
                goto error;
            }
            tag = &((struct to_body*)_m->to->parsed)->tag_value;
        } else {
            if (parse_from_header(_m) < 0) {
                LM_ERR("From parsing failed\n");
                ret = -2;
                goto error;
            }
            tag = &((struct to_body*)_m->from->parsed)->tag_value;
        }
    } else {
        tag = 0;
    }

    sips = rr_is_sips(_m);

    if (enable_double_rr) {
        l = anchor_lump(_m, _m->headers->name.s - _m->buf,0,HDR_RECORDROUTE_T);
        l2 = anchor_lump(_m, _m->headers->name.s - _m->buf, 0, 0);
        if (!l || !l2) {
            LM_ERR("failed to create an anchor\n");
            ret = -3;
            goto error;
        }
        l = insert_cond_lump_after(l,
                                   (enable_double_rr == 2) ? COND_TRUE : COND_IF_DIFF_PROTO, 0);
        l2 = insert_cond_lump_before(l2,
                                     (enable_double_rr == 2) ? COND_TRUE : COND_IF_DIFF_PROTO, 0);
        if (!l || !l2) {
            LM_ERR("failed to insert conditional lump\n");
            ret = -4;
            goto error;
        }
        if (build_advertised_rr(l, l2, _data, &user, tag, OUTBOUND,
                                sips) < 0) {
            LM_ERR("failed to insert outbound Record-Route\n");
            ret = -5;
            goto error;
        }
    }

    l = anchor_lump(_m, _m->headers->name.s - _m->buf, 0, HDR_RECORDROUTE_T);
    l2 = anchor_lump(_m, _m->headers->name.s - _m->buf, 0, 0);
    if (!l || !l2) {
        LM_ERR("failed to create an anchor\n");
        ret = -6;
        goto error;
    }

    if (build_advertised_rr(l, l2, _data, &user, tag, INBOUND, sips) < 0) {
        LM_ERR("failed to insert outbound Record-Route\n");
        ret = -7;
        goto error;
    }
    ret = 1;
error:
    if ((use_ob == 1) || (use_ob == 2))
        if (user.s != NULL)
            pkg_free(user.s);
    return ret;
}
Example #11
0
/*!
 * \brief Insert a new Record-Route header field with lr parameter
 *
 * Insert a new Record-Route header field and also 2nd one if it is enabled
 * and the realm changed so the 2nd record-route header will be necessary.
 * \param _m SIP message
 * \param params RR parameter
 * \return 0 on success, negative on failure
 */
int record_route(struct sip_msg* _m, str *params)
{
    struct lump* l, *l2;
    str user = {NULL, 0};
    str* tag;
    int use_ob = rr_obb.use_outbound ? rr_obb.use_outbound(_m) : 0;
    int sips;
    int ret = 0;

    user.len = 0;

    if (add_username) {
        /* check if there is a custom user set */
        if (get_custom_user(_m, &user) < 0) {
            if (get_username(_m, &user) < 0) {
                LM_ERR("failed to extract username\n");
                return -1;
            }
        }
    } else if (use_ob == 1) {
        if (rr_obb.encode_flow_token(&user, _m->rcv) != 0) {
            LM_ERR("encoding outbound flow-token\n");
            return -1;
        }
    } else if (use_ob == 2) {
        if (copy_flow_token(&user, _m) != 0) {
            LM_ERR("copying outbound flow-token\n");
            return -1;
        }
    }

    if (append_fromtag) {
        if (is_direction(_m, RR_FLOW_UPSTREAM) == 0) {
            if (parse_to_header(_m) < 0) {
                LM_ERR("To parsing failed\n");
                ret = -2;
                goto error;
            }
            tag = &((struct to_body*)_m->to->parsed)->tag_value;
        } else {
            if (parse_from_header(_m) < 0) {
                LM_ERR("From parsing failed\n");
                ret = -2;
                goto error;
            }
            tag = &((struct to_body*)_m->from->parsed)->tag_value;
        }
    } else {
        tag = 0;
    }

    if (rr_param_buf.len && rr_param_msg!=_m->id) {
        /* rr_params were set for a different message -> reset buffer */
        rr_param_buf.len = 0;
    }

    sips = rr_is_sips(_m);

    if (enable_double_rr) {
        l = anchor_lump(_m, _m->headers->name.s - _m->buf,0,HDR_RECORDROUTE_T);
        l2 = anchor_lump(_m, _m->headers->name.s - _m->buf, 0, 0);
        if (!l || !l2) {
            LM_ERR("failed to create an anchor\n");
            ret = -5;
            goto error;
        }
        l = insert_cond_lump_after(l,
                                   (enable_double_rr == 2) ? COND_TRUE : COND_IF_DIFF_REALMS, 0);
        l2 = insert_cond_lump_before(l2,
                                     (enable_double_rr == 2) ? COND_TRUE : COND_IF_DIFF_REALMS, 0);
        if (!l || !l2) {
            LM_ERR("failed to insert conditional lump\n");
            ret = -6;
            goto error;
        }
        if (build_rr(l, l2, &user, tag, params, OUTBOUND, sips) < 0) {
            LM_ERR("failed to insert outbound Record-Route\n");
            ret = -7;
            goto error;
        }
    }

    l = anchor_lump(_m, _m->headers->name.s - _m->buf, 0, HDR_RECORDROUTE_T);
    l2 = anchor_lump(_m, _m->headers->name.s - _m->buf, 0, 0);
    if (!l || !l2) {
        LM_ERR("failed to create an anchor\n");
        ret = -3;
        goto error;
    }

    if (build_rr(l, l2, &user, tag, params, INBOUND, sips) < 0) {
        LM_ERR("failed to insert inbound Record-Route\n");
        ret = -4;
        goto error;
    }

    /* reset the rr_param buffer */
    rr_param_buf.len = 0;
    ret = 0;
error:
    if ((use_ob == 1) || (use_ob == 2))
        if (user.s != NULL)
            pkg_free(user.s);
    return ret;
}
Example #12
0
int dlg_th_post_raw(str *data)
{
	struct sip_msg msg;
	struct dlg_cell *dlg; 

	memset(&msg,0,sizeof(struct sip_msg));
	msg.buf=data->s;
	msg.len=data->len;

	if (parse_msg(msg.buf,msg.len,&msg)!=0) {
		LM_ERR("Invalid SIP msg \n");
		goto error;
	}

	if (parse_headers(&msg,HDR_EOH_F,0)<0) {
		LM_ERR("Failed to parse SIP headers\n");
		goto error;
	}

	if (msg.cseq==NULL || get_cseq(&msg)==NULL) {
		LM_ERR("Failed to parse CSEQ header \n");
		goto error;
	}       

	if((get_cseq(&msg)->method_id)&MSG_SKIP_BITMASK) {
		LM_DBG("Skipping %d for DLG callid topo hiding\n",get_cseq(&msg)->method_id);
		goto error;
	}

	if (parse_to_header(&msg)<0 || msg.to==NULL || get_to(&msg)==NULL) {
		LM_ERR("cannot parse TO header\n");
		goto error;
	}

	if (parse_from_header(&msg)<0 || msg.from==NULL || get_from(&msg)==NULL) {
		LM_ERR("cannot parse TO header\n");
		goto error;
	}

	if (msg.first_line.type==SIP_REQUEST) {
		if (get_to(&msg)->tag_value.len>0) {
			/* sequential request, check if callid needs to be unmasked */
			dlg = get_current_dialog(); 
			if (dlg == NULL || (dlg->flags & DLG_FLAG_TOPH_HIDE_CALLID) == 0 ) {
				/* dialog module not involved or not callid topo hiding
				 - let is pass freely */
			} else {
				if (get_from(&msg)->tag_value.len != 0) {
					if (memcmp(get_from(&msg)->tag_value.s,
					dlg->legs[0].tag.s,dlg->legs[0].tag.len) == 0) {
						/* request from caller -  need to encode callid */
						if (dlg_th_encode_callid(&msg) < 0) {
							LM_ERR("Failed to mask callid for initial request \n");
							goto error;
						}
						goto rebuild_req;
					} else {
						/* let request go through - was decoded on the in side */
					}
				} else {
					/* no from tag in request - kinda foobar ? - let it through */
				}
			}
		} else {
			/* initial request */
			dlg = get_current_dialog(); 
			if (dlg == NULL || (dlg->flags & DLG_FLAG_TOPH_HIDE_CALLID) == 0 ) {
				/* dialog module not involved or not callid topo hiding
				 - let is pass freely */
			} else {
				/* mask callid */
				if (dlg_th_encode_callid(&msg) < 0) {
					LM_ERR("Failed to mask callid for initial request \n");
					goto error;
				}
				goto rebuild_req;
			}	
		}
	} else if (msg.first_line.type==SIP_REPLY) {
		/* we need to look at the direction */
		dlg = get_current_dialog(); 
		if (dlg == NULL || (dlg->flags & DLG_FLAG_TOPH_HIDE_CALLID) == 0 ) {
			/* dialog module not involved or not callid topo hiding
			 - let is pass freely */
		} else {
			if (get_from(&msg)->tag_value.len != 0) {
				if (memcmp(get_from(&msg)->tag_value.s,
				dlg->legs[0].tag.s,dlg->legs[0].tag.len) == 0) {
					/* reply going to caller - 
					decode was done on the receiving end, let it unchanged */
				} else {
					/* reply going to callee , need to encode callid */
					if (dlg_th_encode_callid(&msg) < 0) {
						LM_ERR("Failed to decode callid for reply \n");
						goto error;
					}
					goto rebuild_rpl;
				}
			} else {
				/* no from tag in reply - kinda foobar ? - let it through */
			}
		}
	}

	free_sip_msg(&msg);
	return 0;

rebuild_req:
	data->s = dlg_th_rebuild_req(&msg,&data->len);
	free_sip_msg(&msg);
	return 0;
rebuild_rpl:
	data->s = dlg_th_rebuild_rpl(&msg,&data->len);
	free_sip_msg(&msg);
	return 0;
	
error:
	free_sip_msg(&msg);
	return -1;
}
Example #13
0
int dlg_th_pre_raw(str *data)
{
	struct sip_msg msg;

	memset(&msg,0,sizeof(struct sip_msg));
	msg.buf=data->s;
	msg.len=data->len;

	if (parse_msg(msg.buf,msg.len,&msg)!=0) {
		LM_ERR("Invalid SIP msg \n");
		goto error;
	}

	if (parse_headers(&msg,HDR_EOH_F,0)<0) {
		LM_ERR("Failed to parse SIP headers\n");
		goto error;
	}

	if (msg.cseq==NULL || get_cseq(&msg)==NULL) {
		LM_ERR("Failed to parse CSEQ header \n");
		goto error;
	}       

	if((get_cseq(&msg)->method_id)&MSG_SKIP_BITMASK) {
		LM_DBG("Skipping %d for DLG callid topo hiding\n",get_cseq(&msg)->method_id);
		goto error;
	}

	if (parse_to_header(&msg)<0 || msg.to==NULL || get_to(&msg)==NULL) {
		LM_ERR("cannot parse TO header\n");
		goto error;
	}

	if (msg.first_line.type==SIP_REQUEST) {
		if (get_to(&msg)->tag_value.len>0) {
			/* sequential request, check if callid needs to be unmasked */
			if (dlg_th_needs_decoding(&msg)) {
				if (dlg_th_decode_callid(&msg) < 0) {
					LM_ERR("Failed to decode callid for sequential request \n");
					goto error;
				}
				goto rebuild_msg;
			}	
		} else {
			/* initial request, don't do anything
			callid masking will be done on the out side */
		}
	} else if (msg.first_line.type==SIP_REPLY) {
		/* we might need to decode callid if mangled */
		if (dlg_th_needs_decoding(&msg)) {
			if (dlg_th_decode_callid(&msg) < 0) {
				LM_ERR("Failed to decode callid for reply \n");
				goto error;
			}
			goto rebuild_rpl;
		} else {
			/* encoding will be done on the out side */
		}	
	} else {
		/* non sip, most likely, let it through */
		return 0;
	}

	free_sip_msg(&msg);
	return 0;

rebuild_msg:
	data->s = dlg_th_rebuild_req(&msg,&data->len);
	free_sip_msg(&msg);
	return 0;

rebuild_rpl:
	data->s = dlg_th_rebuild_rpl(&msg,&data->len);
	free_sip_msg(&msg);
	return 0;
error:
	free_sip_msg(&msg);
	return -1;
}