int recordroute_diff(struct sip_msg *req,struct sip_msg *resp) { struct hdr_field *hf; rr_t *rr1; int i,j,k; i=j=k=0; /* count how many record-route bodies come in the response*/ /* this does not work, I think because of siblings for(hf=resp->record_route;hf;hf=hf->sibling,j=0){ */ for(hf=resp->headers;hf;hf=hf->next,j=0){ if(hf->type != HDR_RECORDROUTE_T) continue; if(!hf->parsed){ if(0>parse_rr(hf)) goto error; j=1; } for(rr1=hf->parsed;rr1;rr1=rr1->next){ i++; } if(j){ free_rr((rr_t**)(void*)&hf->parsed); hf->parsed=NULL; } } /* for(hf=req->record_route;hf;hf=hf->sibling,j=0){ */ for(hf=req->headers;hf;hf=hf->next,j=0){ if(hf->type != HDR_RECORDROUTE_T) continue; if(!hf->parsed){ if(0>parse_rr(hf)) goto error; j=1; } for(rr1=hf->parsed;rr1;rr1=rr1->next){ k++; } if(j){ free_rr((rr_t**)(void*)&hf->parsed); hf->parsed=NULL; } } return i-k; error: return -1; }
/** * Returns the first entry of the P-Associated-URI header. * @param msg - the SIP message to look into * @param public_id - the public identity to be filled with the result * @returns 1 on success or 0 on failure */ int cscf_get_first_p_associated_uri(struct sip_msg *msg,str *public_id) { struct hdr_field *h; rr_t *r; public_id->s=0;public_id->len=0; if (!msg) return 0; if (parse_headers(msg, HDR_EOH_F, 0)<0){ LOG(L_ERR,"ERR:"M_NAME":cscf_get_p_associated_uri: error parsing headers\n"); return 0; } h = msg->headers; while(h){ if (h->name.len==16 && strncasecmp(h->name.s,"P-Associated-URI",16)==0) break; h = h->next; } if (!h){ LOG(L_DBG,"DBG:"M_NAME":cscf_get_p_associated_uri: Header P-Associated-URI not found\n"); return 0; } if (parse_rr(h)<0){ LOG(L_ERR,"ERR:"M_NAME":cscf_get_p_associated_uri: Error parsing as Route header\n"); return 0; } r = (rr_t*)h->parsed; h->type = HDR_ROUTE_T; if (r) { *public_id=r->nameaddr.uri; return 1; } else return 0; }
/*! * \brief Copy flow-token from top-Route: to a string * * Copy the user part of the top-Route: to a string (allocating private memory * for this). * \param token where the user-part of the top-Route: will be copied to * \param _m the SIP message to extract the top-Route: from * \return 0 on success, negative on failure */ static int copy_flow_token(str *token, struct sip_msg *_m) { rr_t *rt; struct sip_uri puri; if (_m->route || (parse_headers(_m, HDR_ROUTE_F, 0) != -1 && _m->route)) { if (parse_rr(_m->route) < 0) { LM_ERR("parsing Route: header body\n"); return -1; } rt = (rr_t *) _m->route->parsed; if (!rt) { LM_ERR("empty Route:\n"); return -1; } if (parse_uri(rt->nameaddr.uri.s, rt->nameaddr.uri.len, &puri) < 0) { LM_ERR("parsing Route-URI\n"); return -1; } token->s = pkg_malloc(puri.user.len * sizeof(char)); if (token->s == NULL) { LM_ERR("allocating memory\n"); return -1; } memcpy(token->s, puri.user.s, puri.user.len); token->len = puri.user.len; return 0; } LM_ERR("no Route: headers found\n"); return -1; }
/** * Finds if the message contains the orig parameter in the first Route header * @param msg - the SIP message * @param str1 - not used * @param str2 - not used * @returns #CSCF_RETURN_TRUE if yes, else #CSCF_RETURN_FALSE */ int cscf_has_originating(struct sip_msg *msg,char *str1,char *str2) { //int ret=CSCF_RETURN_FALSE; struct hdr_field *h; str* uri; rr_t *r; if (parse_headers(msg, HDR_ROUTE_F, 0)<0){ LM_DBG("I_originating: error parsing headers\n"); return CSCF_RETURN_FALSE; } h = msg->route; if (!h){ LM_DBG("I_originating: Header Route not found\n"); return CSCF_RETURN_FALSE; } if (parse_rr(h)<0){ LM_DBG("I_originating: Error parsing as Route header\n"); return CSCF_RETURN_FALSE; } r = (rr_t*)h->parsed; uri = &r->nameaddr.uri; struct sip_uri puri; if (parse_uri(uri->s, uri->len, &puri) < 0) { LM_DBG( "I_originating: Error while parsing the first route URI\n"); return -1; } if (puri.params.len < 4) return CSCF_RETURN_FALSE; int c = 0; int state = 0; while (c < puri.params.len) { switch (puri.params.s[c]) { case 'o': if (state==0) state=1; break; case 'r': if (state==1) state=2; break; case 'i': if (state==2) state=3; break; case 'g': if (state==3) state=4; break; case ' ': case '\t': case '\r': case '\n': case ',': case ';': if (state==4) return CSCF_RETURN_TRUE; state=0; break; case '=': if (state==4) return CSCF_RETURN_TRUE; state=-1; break; default: state=-1; } c++; } return state==4 ? CSCF_RETURN_TRUE : CSCF_RETURN_FALSE; }
static int get_direction(struct sip_msg* msg) { int ret; if (parse_orig_ruri(msg) < 0) { return -1; } if (!msg->parsed_orig_ruri_ok) { ERR("Error while parsing original Request-URI\n"); return -1; } ret = check_self(&msg->parsed_orig_ruri.host, msg->parsed_orig_ruri.port_no ? msg->parsed_orig_ruri.port_no : SIP_PORT, 0);/* match all protos*/ if (ret < 0) return -1; if (ret > 0) { /* Route is in ruri */ return check_ftag(msg, &msg->first_line.u.request.uri); } else { if (msg->route) { if (parse_rr(msg->route) < 0) { ERR("Error while parsing Route HF\n"); return -1; } ret = check_ftag(msg, &((rr_t*)msg->route->parsed)->nameaddr.uri); if (msg->route->parsed) free_rr((rr_t**)(void*)&msg->route->parsed); return ret; } else { DBG("No Route headers found\n"); return -1; } } }
str* get_route_set(struct sip_msg *msg,int *nr_routes) { static str uris[MAX_RR_HDRS]; struct hdr_field *it; rr_t *p; int n = 0; if (msg == NULL || msg->route == NULL) { LM_ERR("null sip msg or no route headers\n"); return 0; } if (routing_type == ROUTING_SS || routing_type == ROUTING_LS) { /* must manually insert RURI, as it was part * of the route deleted to make up for strict routing */ uris[n++] = msg->new_uri; } it = msg->route; while (it != NULL) { if (parse_rr(it) < 0) { LM_ERR("failed to parse RR\n"); return 0; } p = (rr_t*)it->parsed; while (p) { if (p->deleted == 0) { uris[n++] = p->nameaddr.uri; if(n==MAX_RR_HDRS) { LM_ERR("too many RR\n"); return 0; } } else LM_DBG("Route [%.*s] has been deleted\n",p->nameaddr.uri.len, p->nameaddr.uri.s); p = p->next; } it = it->sibling; } /* if SS - remove last route */ if (routing_type == ROUTING_SS) n--; if (nr_routes) *nr_routes = n; return uris; }
/** * Returns the content of the P-Associated-URI header * Public_id is pkg_alloced and should be later freed. * Inside values are not duplicated. * @param msg - the SIP message to look into * @param public_id - array to be allocated and filled with the result * @param public_id_cnt - the size of the public_id array * @param is_shm - msg from shared memory * @returns 1 on success or 0 on error */ int cscf_get_p_associated_uri(struct sip_msg *msg, str **public_id, int *public_id_cnt, int is_shm) { struct hdr_field *h; rr_t *r, *r2; *public_id = 0; *public_id_cnt = 0; if (!msg) return 0; if (parse_headers(msg, HDR_EOH_F, 0) < 0) { LM_ERR("error parsing headers\n"); return 0; } h = msg->headers; while (h) { if (h->name.len == 16 && strncasecmp(h->name.s, "P-Associated-URI", 16) == 0) { break; } h = h->next; } if (!h) { LM_DBG("Header P-Associated-URI not found\n"); return 0; } if (parse_rr(h) < 0) { LM_DBG("Error parsing as Route header\n"); return 0; } r = (rr_t*) h->parsed; h->type = HDR_ROUTE_T; *public_id_cnt = 0; r2 = r; while (r2) { (*public_id_cnt) = (*public_id_cnt) + 1; r2 = r2->next; } *public_id = pkg_malloc(sizeof(str)*(*public_id_cnt)); if (!public_id) { LM_ERR("Error out of pkg memory"); return 0; } r2 = r; *public_id_cnt = 0; while (r2) { (*public_id)[(*public_id_cnt)] = r2->nameaddr.uri; (*public_id_cnt) = (*public_id_cnt) + 1; r2 = r2->next; } if (is_shm) { r = (rr_t*) h->parsed; h->parsed = 0; free_rr(&r); } return 1; }
int th_mask_record_route(sip_msg_t *msg) { hdr_field_t *hdr; struct lump* l; int i; rr_t *rr; str out; if(msg->record_route==NULL) { LM_DBG("no record route header\n"); return 0; } hdr = msg->record_route; i = 0; while(hdr!=NULL) { if (parse_rr(hdr) < 0) { LM_ERR("failed to parse RR\n"); return -1; } rr =(rr_t*)hdr->parsed; while(rr) { i++; if(i!=1) { out.s = th_mask_encode(rr->nameaddr.uri.s, rr->nameaddr.uri.len, &th_uri_prefix, &out.len); if(out.s==NULL) { LM_ERR("cannot encode r-r %d\n", i); return -1; } l=del_lump(msg, rr->nameaddr.uri.s-msg->buf, rr->nameaddr.uri.len, 0); if (l==0) { LM_ERR("failed deleting r-r [%d]\n", i); pkg_free(out.s); return -1; } if (insert_new_lump_after(l, out.s, out.len, 0)==0){ LM_ERR("could not insert new lump\n"); pkg_free(out.s); return -1; } } rr = rr->next; } hdr = next_sibling_hdr(hdr); } return 0; }
static void cares_callback(void *arg, int status, unsigned char *abuf, int alen) { int i; unsigned int ancount, nscount, arcount; const unsigned char *aptr; #ifdef DEBUG printf("cares_callback: status=%i, alen=%i\n", status, alen); #endif if (status != ARES_SUCCESS) { if (verbose > 1) printf("ares failed: %s\n", ares_strerror(status)); return; } ancount = DNS_HEADER_ANCOUNT(abuf); nscount = DNS_HEADER_NSCOUNT(abuf); arcount = DNS_HEADER_ARCOUNT(abuf); #ifdef DEBUG printf("ancount: %i, nscount: %i, arcount: %i\n", ancount, nscount, arcount); #endif /* safety check */ if (alen < NS_HFIXEDSZ) return; aptr = abuf + NS_HFIXEDSZ; aptr = skip_query(aptr, abuf, alen); for (i = 0; i < ancount && caadr == 0; i++) { if (ca_tmpname == NULL) aptr = parse_rr(aptr, abuf, alen); else aptr = skip_rr(aptr, abuf, alen); } if (caadr == 0) { for (i = 0; i < nscount; i++) { aptr = skip_rr(aptr, abuf, alen); } for (i = 0; i < arcount && caadr == 0; i++) { aptr = parse_rr(aptr, abuf, alen); } } }
static int parse_rr_header(struct sip_msg *msg) { if ( !msg->record_route && ( parse_headers(msg,HDR_RECORDROUTE_F,0) == -1)) { LM_ERR("bad msg or missing Record-Route header\n"); return -1; } if (!msg->record_route) { LM_DBG("No Record-Route header field found\n"); return -1; } return parse_rr(msg->record_route); }
/* * Parse the message and find first occurrence of * Route header field. The function returns -1 or -2 * on a parser error, 0 if there is a Route HF and * 1 if there is no Route HF. */ static inline int find_first_route(struct sip_msg* _m) { if (parse_headers(_m, HDR_ROUTE_F, 0) == -1) { LOG(L_ERR, "find_first_route: Error while parsing headers\n"); return -1; } else { if (_m->route) { if (parse_rr(_m->route) < 0) { LOG(L_ERR, "find_first_route: Error while parsing Route HF\n"); return -2; } return 0; } else { DBG("find_first_route: No Route headers found\n"); return 1; } } }
/*! * \brief Parse the message and find first occurrence of Route header field. * \param _m SIP message * \return -1 or -2 on a parser error, 0 if there is a Route HF and 1 if there is no Route HF */ static inline int find_first_route(struct sip_msg* _m) { if (parse_headers(_m, HDR_ROUTE_F, 0) == -1) { LM_ERR("failed to parse headers\n"); return -1; } else { if (_m->route) { if (parse_rr(_m->route) < 0) { LM_ERR("failed to parse Route HF\n"); return -2; } return 0; } else { LM_DBG("No Route headers found\n"); return 1; } } }
/** * Looks for the P-Asserted-Identity header and extracts its content * @param msg - the sip message * @returns the asserted identity */ str cscf_get_asserted_identity(struct sip_msg *msg) { name_addr_t id; struct hdr_field *h; rr_t *r; memset(&id,0,sizeof(name_addr_t)); if (!msg) return id.uri; if (parse_headers(msg, HDR_EOH_F, 0)<0) { return id.uri; } h = msg->headers; while(h) { if (h->name.len == s_asserted_identity.len && strncasecmp(h->name.s,s_asserted_identity.s,s_asserted_identity.len)==0) { if (parse_rr(h)<0){ //This might be an old client LOG(L_CRIT,"WARN:"M_NAME":cscf_get_asserted_identity: P-Asserted-Identity header must contain a Nameaddr!!! Fix the client!\n"); id.name.s = h->body.s; id.name.len = 0; id.len = h->body.len; id.uri = h->body; while(id.uri.len && (id.uri.s[0]==' ' || id.uri.s[0]=='\t' || id.uri.s[0]=='<')){ id.uri.s = id.uri.s+1; id.uri.len --; } while(id.uri.len && (id.uri.s[id.uri.len-1]==' ' || id.uri.s[id.uri.len-1]=='\t' || id.uri.s[id.uri.len-1]=='>')){ id.uri.len--; } return id.uri; } r = (rr_t*) h->parsed; id = r->nameaddr; free_rr(&r); h->parsed=r; //LOG(L_RIT,"%.*s",id.uri.len,id.uri.s); return id.uri; } h = h->next; } return id.uri; }
int tps_route_direction(sip_msg_t *msg) { rr_t *rr; struct sip_uri puri; str ftn = {"ftag", 4}; str ftv = {0, 0}; if(get_from(msg)->tag_value.len<=0) { LM_ERR("failed to get from header tag\n"); return -1; } if(msg->route==NULL) { LM_DBG("no route header - downstream\n"); return 0; } if (parse_rr(msg->route) < 0) { LM_ERR("failed to parse route header\n"); return -1; } rr =(rr_t*)msg->route->parsed; if (parse_uri(rr->nameaddr.uri.s, rr->nameaddr.uri.len, &puri) < 0) { LM_ERR("failed to parse the first route URI\n"); return -1; } if(tps_get_param_value(&puri.params, &ftn, &ftv)!=0) return 0; if(get_from(msg)->tag_value.len!=ftv.len || strncmp(get_from(msg)->tag_value.s, ftv.s, ftv.len)!=0) { LM_DBG("ftag mismatch\n"); return 1; } LM_DBG("ftag match\n"); return 0; }
int dump_rr(struct iso_directory_record * idr){ int len; char * pnt; len = idr->length[0] & 0xff; len -= (sizeof(struct iso_directory_record) - sizeof(idr->name)); len -= idr->name_len[0]; pnt = (char *) idr; pnt += (sizeof(struct iso_directory_record) - sizeof(idr->name)); pnt += idr->name_len[0]; if((idr->name_len[0] & 1) == 0){ pnt++; len--; }; rr_goof = 0; parse_rr(pnt, len, 0); return rr_goof; }
/* * Create a copy of route set either in normal or reverse order */ static inline int get_route_set(struct sip_msg* _m, rr_t** _rs, unsigned char _order) { struct hdr_field* ptr; rr_t* last, *p, *t; last = 0; ptr = _m->record_route; while(ptr) { if (ptr->type == HDR_RECORDROUTE_T) { if (parse_rr(ptr) < 0) { LOG(L_ERR, "get_route_set(): Error while parsing Record-Route body\n"); goto error; } p = (rr_t*)ptr->parsed; if (shm_duplicate_rr(&t, p) < 0) { LOG(L_ERR, "get_route_set(): Error while duplicating rr_t\n"); goto error; } if (!*_rs) *_rs = t; if (last) last->next = t; last = t; while (last->next) last = last->next; /* !!! there may be more routes in one hdr field !!! */ } ptr = ptr->next; } if ((*_rs) && (_order != NORMAL_ORDER)) { /* better to revert the route outside of cycle above */ *_rs = revert_route(*_rs); } return 0; error: shm_free_rr(_rs); return -1; }
/** * Retrieves the mark from message. * - the marking should be in a header like described before * @param msg - SIP mesage to mark * @param mark - mark to load into * @returns 1 if found, 0 if not */ int isc_mark_get_from_msg(struct sip_msg *msg, isc_mark *mark) { struct hdr_field *hdr; rr_t *rr; str x; LM_DBG("isc_mark_get_from_msg: Trying to get the mark from the message \n"); memset(mark, 0, sizeof(isc_mark)); parse_headers(msg, HDR_EOH_F, 0); hdr = msg->headers; while (hdr) { if (hdr->type == HDR_ROUTE_T) { if (!hdr->parsed) { if (parse_rr(hdr) < 0) { LM_ERR("isc_mark_get_from_msg: Error while parsing Route HF\n"); hdr = hdr->next; continue; } } rr = (rr_t*) hdr->parsed; while (rr) { x = rr->nameaddr.uri; if (x.len >= ISC_MARK_USERNAME_LEN + 1 + isc_my_uri.len && strncasecmp(x.s, ISC_MARK_USERNAME, ISC_MARK_USERNAME_LEN) == 0 && strncasecmp(x.s + ISC_MARK_USERNAME_LEN + 1, isc_my_uri.s, isc_my_uri.len) == 0) { LM_DBG("isc_mark_get_from_msg: Found <%.*s>\n", x.len, x.s); isc_mark_get(x, mark); return 1; } rr = rr->next; } } hdr = hdr->next; } return 0; }
/* * Return the URI of the topmost Route-Header. */ static int pv_get_route_uri_f(struct sip_msg *msg, pv_param_t *param, pv_value_t *res) { struct hdr_field* hdr; rr_t* rt; str uri; if (!msg) { LM_ERR("No message?!?\n"); return -1; } /* Parse the message until the First-Route-Header: */ if (parse_headers(msg, HDR_ROUTE_F, 0) == -1) { LM_ERR("while parsing message\n"); return -1; } if (!msg->route) { LM_INFO("No route header present.\n"); return -1; } hdr = msg->route; /* Parse the contents of the header: */ if (parse_rr(hdr) == -1) { LM_ERR("Error while parsing Route header\n"); return -1; } /* Retrieve the Route-Header */ rt = (rr_t*)hdr->parsed; uri = rt->nameaddr.uri; return pv_get_strval(msg, param, res, &uri); }
/*! * \brief Find and parse next Route header field * \param _m SIP message * \param _hdr SIP header * \return negative on failure, 0 if the Route header was already parsed, 1 if no next * Route header could be found */ static inline int find_next_route(struct sip_msg* _m, struct hdr_field** _hdr) { struct hdr_field* ptr; ptr = (*_hdr)->next; /* Try to find already parsed Route headers */ while(ptr) { if (ptr->type == HDR_ROUTE_T) goto found; ptr = ptr->next; } /* There are no already parsed Route headers, try to find next * occurrence of Route header */ if (parse_headers(_m, HDR_ROUTE_F, 1) == -1) { LM_ERR("failed to parse headers\n"); return -1; } if ((_m->last_header->type!=HDR_ROUTE_T) || (_m->last_header==*_hdr)) { LM_DBG("No next Route HF found\n"); return 1; } ptr = _m->last_header; found: if (parse_rr(ptr) < 0) { LM_ERR("failed to parse Route body\n"); return -2; } *_hdr = ptr; return 0; }
/* * Find last route in the last Route header field, * if there was a previous route in the last Route header * field, it will be saved in _p parameter */ static inline int find_rem_target(struct sip_msg* _m, struct hdr_field** _h, rr_t** _l, rr_t** _p) { struct hdr_field* ptr, *last; if (parse_headers(_m, HDR_EOH_F, 0) == -1) { LOG(L_ERR, "find_rem_target: Error while parsing message header\n"); return -1; } ptr = _m->route; last = 0; while(ptr) { if (ptr->type == HDR_ROUTE_T) last = ptr; ptr = ptr->next; } if (last) { if (parse_rr(last) < 0) { LOG(L_ERR, "find_rem_target: Error while parsing last Route HF\n"); return -2; } *_h = last; *_p = 0; *_l = (rr_t*)last->parsed; while ((*_l)->next) { *_p = *_l; *_l = (*_l)->next; } return 0; } else { LOG(L_ERR, "find_rem_target: Can't find last Route HF\n"); return 1; } }
/*! * \brief Find last route in the last Route header field * * Find last route in the last Route header field, if there was a previous * route in the last Route header field, it will be saved in _p parameter * \param _m SIP message * \param _h SIP header field * \param _l Route & Record-Route header field body * \param _p Route & Record-Route header field body * \return negative on failure, 0 on success */ static inline int find_rem_target(struct sip_msg* _m, struct hdr_field** _h, rr_t** _l, rr_t** _p) { struct hdr_field* ptr, *last; if (parse_headers(_m, HDR_EOH_F, 0) == -1) { LM_ERR("failed to parse message header\n"); return -1; } ptr = _m->route; last = 0; while(ptr) { if (ptr->type == HDR_ROUTE_T) last = ptr; ptr = ptr->next; } if (last) { if (parse_rr(last) < 0) { LM_ERR("failed to parse last Route HF\n"); return -2; } *_p = 0; *_l = (rr_t*)last->parsed; *_h = last; while ((*_l)->next) { *_p = *_l; *_l = (*_l)->next; } return 0; } else { LM_ERR("search for last Route HF failed\n"); return 1; } }
static int l_siplua_getRoute(lua_State *L) { struct sipapi_object *o; rr_t *rt; str uri; struct sip_uri puri; int n = 1; o = luaL_checkudata(L, 1, "siplua.api"); if (parse_headers(o->msg, HDR_ROUTE_F, 0) == -1) return luaL_error(L, "failed to parse headers"); if (!o->msg->route) { lua_pushnil(L); return 1; } if (parse_rr(o->msg->route) < 0) return luaL_error(L, "failed to parse route HF"); lua_newtable(L); for (rt = (rr_t *)o->msg->route->parsed; rt; rt = rt->next ) { uri = rt->nameaddr.uri; lua_pushinteger(L, n++); lua_newtable(L); lua_pushliteral(L, "uri"); lua_pushlstring(L, uri.s, uri.len); lua_rawset(L, -3); if (parse_uri(uri.s, uri.len, &puri) < 0) { if (n == 1) return luaL_error(L, "failed to parse the first route URI"); continue; } lua_pushliteral(L, "user"); lua_pushlstring(L, puri.user.s, puri.user.len); lua_rawset(L, -3); lua_pushliteral(L, "host"); lua_pushlstring(L, puri.host.s, puri.host.len); lua_rawset(L, -3); lua_pushliteral(L, "port"); lua_pushinteger(L, puri.port_no); lua_rawset(L, -3); lua_pushliteral(L, "params"); lua_pushlstring(L, puri.params.s, puri.params.len); lua_rawset(L, -3); lua_pushliteral(L, "lr"); lua_pushlstring(L, puri.lr.s, puri.lr.len); lua_rawset(L, -3); lua_pushliteral(L, "lr_val"); lua_pushlstring(L, puri.lr_val.s, puri.lr_val.len); lua_rawset(L, -3); lua_pushliteral(L, "r2"); lua_pushlstring(L, puri.r2.s, puri.r2.len); lua_rawset(L, -3); lua_pushliteral(L, "r2_val"); lua_pushlstring(L, puri.r2_val.s, puri.r2_val.len); lua_rawset(L, -3); lua_pushliteral(L, "is_myself"); if (check_self(&puri.host, puri.port_no ? puri.port_no : SIP_PORT, 0) >= 0) lua_pushboolean(L, 1); else lua_pushboolean(L, 0); lua_rawset(L, -3); lua_rawset(L, -3); } return 1; }
int tps_pack_request(sip_msg_t *msg, tps_data_t *ptsd) { hdr_field_t *hdr; via_body_t *via; rr_t *rr; int i; int vlen; if(ptsd->cp==NULL) { ptsd->cp = ptsd->cbuf; } i = 0; for(hdr=msg->h_via1; hdr; hdr=next_sibling_hdr(hdr)) { for(via=(struct via_body*)hdr->parsed; via; via=via->next) { i++; vlen = tps_skip_rw(via->name.s, via->bsize); if(ptsd->cp + vlen + 2 >= ptsd->cbuf + TPS_DATA_SIZE) { LM_ERR("no more spage to pack via headers\n"); return -1; } if(i>1) { *ptsd->cp = ','; ptsd->cp++; if(i>2) { ptsd->x_via2.len++; } } memcpy(ptsd->cp, via->name.s, vlen); if(i==1) { ptsd->x_via1.s = ptsd->cp; ptsd->x_via1.len = vlen; if(via->branch!=NULL) { ptsd->x_vbranch1.s = ptsd->x_via1.s + (via->branch->value.s - via->name.s); ptsd->x_vbranch1.len = via->branch->value.len; } } else { if(i==2) { ptsd->x_via2.s = ptsd->cp; } ptsd->x_via2.len += vlen; } ptsd->cp += vlen; } } LM_DBG("compacted headers - x_via1: [%.*s](%d) - x_via2: [%.*s](%d)" " - x_vbranch1: [%.*s](%d)\n", ptsd->x_via1.len, ZSW(ptsd->x_via1.s), ptsd->x_via1.len, ptsd->x_via2.len, ZSW(ptsd->x_via2.s), ptsd->x_via2.len, ptsd->x_vbranch1.len, ZSW(ptsd->x_vbranch1.s), ptsd->x_vbranch1.len); i = 0; ptsd->a_rr.len = 0; for(hdr=msg->record_route; hdr; hdr=next_sibling_hdr(hdr)) { if (parse_rr(hdr) < 0) { LM_ERR("failed to parse RR\n"); return -1; } for(rr =(rr_t*)hdr->parsed; rr; rr=rr->next) { i++; if(ptsd->cp + rr->nameaddr.uri.len + 4 >= ptsd->cbuf + TPS_DATA_SIZE) { LM_ERR("no more spage to pack rr headers\n"); return -1; } if(i>1) { *ptsd->cp = ','; ptsd->cp++; ptsd->a_rr.len++; } *ptsd->cp = '<'; if(i==1) { ptsd->a_rr.s = ptsd->cp; } ptsd->cp++; ptsd->a_rr.len++; memcpy(ptsd->cp, rr->nameaddr.uri.s, rr->nameaddr.uri.len); if(i==1) { ptsd->bs_contact.s = ptsd->cp; ptsd->bs_contact.len = rr->nameaddr.uri.len; if(strnstr(ptsd->bs_contact.s, ";r2=on", ptsd->bs_contact.len)==NULL) { LM_DBG("single record routing by proxy\n"); ptsd->as_contact.s = ptsd->cp; ptsd->as_contact.len = rr->nameaddr.uri.len; } } else { if(i==2 && ptsd->as_contact.len==0) { LM_DBG("double record routing by proxy\n"); ptsd->as_contact.s = ptsd->cp; ptsd->as_contact.len = rr->nameaddr.uri.len; } } ptsd->a_rr.len += rr->nameaddr.uri.len; ptsd->cp += rr->nameaddr.uri.len; *ptsd->cp = '>'; ptsd->cp++; ptsd->a_rr.len++; } } LM_DBG("compacted headers - a_rr: [%.*s](%d) - b_rr: [%.*s](%d)\n", ptsd->a_rr.len, ZSW(ptsd->a_rr.s), ptsd->a_rr.len, ptsd->b_rr.len, ZSW(ptsd->b_rr.s), ptsd->b_rr.len); LM_DBG("compacted headers - as_contact: [%.*s](%d) - bs_contact: [%.*s](%d)\n", ptsd->as_contact.len, ZSW(ptsd->as_contact.s), ptsd->as_contact.len, ptsd->bs_contact.len, ZSW(ptsd->bs_contact.s), ptsd->bs_contact.len); return 0; }
/** * Returns the content of the Service-Route header. * data vector is pkg_alloced and should be later freed * inside values are not duplicated * @param msg - the SIP message * @param size - size of the returned vector, filled with the result * @param is_shm - msg from shared memory * @returns - the str vector of uris */ str* cscf_get_service_route(struct sip_msg *msg, int *size, int is_shm) { struct hdr_field *h; rr_t *r, *r2; str *x = 0; int k; if (!size) return 0; *size = 0; if (!msg) return 0; if (parse_headers(msg, HDR_EOH_F, 0) < 0) { LM_ERR("error parsing headers\n"); return 0; } h = msg->headers; while (h) { if (h->name.len == 13 && strncasecmp(h->name.s, "Service-Route", 13) == 0) { if (parse_rr(h) < 0) { LM_ERR("Error parsing as Route header\n"); continue; } r = (rr_t*) h->parsed; h->type = HDR_ROUTE_T; r2 = r; k = 0; while (r2) { k++; r2 = r2->next; } if (!k) { LM_DBG("No items in this Service-Route\n"); continue; } x = pkg_realloc(x,(*size+k)*sizeof(str)); if (!x) { LM_ERR("Error our of pkg memory"); return 0; } r2 = r; while (r2) { x[*size] = r2->nameaddr.uri; (*size) = (*size) + 1; r2 = r2->next; } } h = h->next; } if (is_shm) { h = msg->headers; while (h) { if (h->name.len == 13 && strncasecmp(h->name.s, "Service-Route", 13) == 0) { r = (rr_t*) h->parsed; h->parsed = 0; free_rr(&r); } h = h->next; } } return x; }
/** * Extract route set from the message (out of Record-Route, if reply, OR * Route, if request). * The route set is returned into the "UAC-format" (keep order for Rs, reverse * RRs). */ static inline int get_uac_rs(sip_msg_t *msg, int is_req, struct rte **rtset) { struct hdr_field* ptr; rr_t *p, *new_p; struct rte *t, *head, *old_head; head = 0; for (ptr = is_req ? msg->route : msg->record_route; ptr; ptr = ptr->next) { switch (ptr->type) { case HDR_RECORDROUTE_T: if (is_req) continue; break; case HDR_ROUTE_T: if (! is_req) continue; break; default: continue; } if (parse_rr(ptr) < 0) { LM_ERR("failed to parse Record-/Route HF (%d).\n", ptr->type); goto err; } p = (rr_t*)ptr->parsed; while(p) { if (! (t = pkg_malloc(sizeof(struct rte)))) { LM_ERR("out of pkg mem (asked for: %d).\n", (int)sizeof(struct rte)); goto err; } if (is_req) { /* in case of requests, the sip_msg structure is free'd before * rte list is evaluated => must do a copy of it */ if (duplicate_rr(&new_p, p) < 0) { pkg_free(t); LM_ERR("failed to duplicate RR"); goto err; } t->ptr = new_p; } else { t->ptr = p; } t->free_rr = is_req; t->next = head; head = t; p = p->next; } } if (is_req) { /* harvesting the R/RR HF above inserts at head, which suites RRs (as * they must be reversed, anyway), but not Rs => reverse once more */ old_head = head; head = 0; while (old_head) { t = old_head; old_head = old_head->next; t->next = head; head = t; } } *rtset = head; return 0; err: free_rte_list(head); return -1; }
int th_flip_record_route(sip_msg_t *msg, int mode) { hdr_field_t *hdr; struct lump* l; int i; rr_t *rr; str out; int utype; str pval; int r2; int act; if(msg->record_route==NULL) { LM_DBG("no record route header\n"); return 0; } hdr = msg->record_route; i = 0; act = 0; if(mode==1) act = 2; while(hdr!=NULL) { if (parse_rr(hdr) < 0) { LM_ERR("failed to parse RR\n"); return -1; } rr =(rr_t*)hdr->parsed; while(rr) { i++; r2 = 0; utype = th_get_uri_type(&rr->nameaddr.uri, &r2, &pval); if(utype==0 && mode==1) { if(r2==1) { act--; if(act==0) return 0; utype = 1; } else { return 0; } } out.s = NULL; switch(utype) { case 1: /* encode */ if(act!=0 && mode==1) { out.s = th_mask_encode(rr->nameaddr.uri.s, rr->nameaddr.uri.len, &th_uri_prefix, &out.len); if(out.s==NULL) { LM_ERR("cannot encode r-r %d\n", i); return -1; } } break; case 2: /* decode */ if(mode==0) { out.s = th_mask_decode(pval.s, pval.len, &th_uparam_prefix, 0, &out.len); if(out.s==NULL) { LM_ERR("cannot decode r-r %d\n", i); return -1; } } break; } if(out.s!=NULL) { l=del_lump(msg, rr->nameaddr.uri.s-msg->buf, rr->nameaddr.uri.len, 0); if (l==0) { LM_ERR("failed deleting r-r [%d]\n", i); pkg_free(out.s); return -1; } if (insert_new_lump_after(l, out.s, out.len, 0)==0){ LM_ERR("could not insert new lump\n"); pkg_free(out.s); return -1; } } rr = rr->next; } hdr = next_sibling_hdr(hdr); } return 0; }
/* Actions are composed as follows: * (the action length and type as always= 5 bytes) * * TODO performance speedup: instead of using * dynamically allocated memory for headers,body,totag,reason and my_msg * use static buffers. * */ int ac_sl_msg(as_p the_as,unsigned char processor_id,unsigned int flags,char *action,int len) { struct sip_msg *my_msg; str *uri; struct proxy_l *proxy; rr_t *my_route; int k,retval; //enum sip_protos proto; my_msg=NULL; k=0; proxy=0; if(!(my_msg = parse_ac_msg(HDR_EOH_F,action+k,len-k))){ LM_ERR("out of memory!\n"); goto error; } if(my_msg->first_line.type == SIP_REQUEST) LM_DBG("forwarding request:\"%.*s\" statelessly \n",my_msg->first_line.u.request.method.len+1+\ my_msg->first_line.u.request.uri.len,my_msg->first_line.u.request.method.s); else LM_DBG("forwarding reply:\"%.*s\" statelessly \n",my_msg->first_line.u.reply.status.len+1+\ my_msg->first_line.u.reply.reason.len,my_msg->first_line.u.reply.status.s); if (my_msg->route) { if (parse_rr(my_msg->route) < 0) { LM_ERR( "Error while parsing Route body\n"); goto error; } my_route = (rr_t*)my_msg->route->parsed; uri=&(my_route->nameaddr.uri); }else{ uri = GET_RURI(my_msg); } set_force_socket(my_msg, grep_sock_info(&my_msg->via1->host, my_msg->via1->port, my_msg->via1->proto) ); /* or also could be: my_msg->force_send_socket=the_as->binds[processor_id].bind_address; not sure which is better... */ /*proxy=uri2proxy(uri,PROTO_NONE); if (proxy==0) { LM_ERR("unable to create proxy from URI \n"); goto error; } proto=proxy->proto; */ //TODO my_msg->recvd if(0>forward_sl_request(my_msg,uri,PROTO_NONE)) goto error; retval=0; goto exit; error: retval = -1; exit: if(proxy){ free_proxy(proxy); pkg_free(proxy); } if(my_msg){ free_sip_msg_lite(my_msg); pkg_free(my_msg); } return retval; }
int w_is_first_hop(sip_msg_t *msg, char *p1, char *p2) { int ret; rr_t* r = NULL; sip_uri_t puri; struct ip_addr *ip; if(msg==NULL) return -1; if(msg->first_line.type == SIP_REQUEST) { if (parse_headers( msg, HDR_VIA2_F, 0 )<0 || (msg->via2==0) || (msg->via2->error!=PARSE_OK)) { /* sip request: if more than one via, then not first hop */ /* no second via or error */ LM_DBG("no 2nd via found - first hop\n"); return 1; } return -1; } else if(msg->first_line.type == SIP_REPLY) { /* sip reply: if top record-route is myself * and not received from myself (loop), then is first hop */ if (parse_headers( msg, HDR_EOH_F, 0 )<0) { LM_DBG("error parsing headers\n"); return -1; } if(msg->record_route==NULL) { LM_DBG("no record-route header - first hop\n"); return 1; } if(parse_rr(msg->record_route)<0) { LM_DBG("failed to parse first record-route header\n"); return -1; } r = (rr_t*)msg->record_route->parsed; if(parse_uri(r->nameaddr.uri.s, r->nameaddr.uri.len, &puri)<0) { LM_DBG("failed to parse uri in first record-route header\n"); return -1; } if (((ip = str2ip(&(puri.host))) == NULL) && ((ip = str2ip6(&(puri.host))) == NULL)) { LM_DBG("uri host is not an ip address\n"); return -1; } ret = check_self(&puri.host, (puri.port.s)?puri.port_no:0, (puri.transport_val.s)?puri.proto:0); if(ret!=1) { LM_DBG("top record route uri is not myself\n"); return -1; } if (ip_addr_cmp(ip, &(msg->rcv.src_ip)) && ((msg->rcv.src_port == puri.port_no) || ((puri.port.len == 0) && (msg->rcv.src_port == 5060))) && (puri.proto==msg->rcv.proto || (puri.proto==0 && msg->rcv.proto==PROTO_UDP)) ) { LM_DBG("source address matches top record route uri - loop\n"); return -1; } /* todo - check spirals */ return 1; } else { return -1; } }
/*! * get first RR header and print comma separated bodies in oroute * - order = 0 normal; order = 1 reverse * - nb_recs - input=skip number of rr; output=number of printed rrs */ int print_rr_body(struct hdr_field *iroute, str *oroute, int order, unsigned int * nb_recs) { rr_t *p; int n = 0, nr=0; int i = 0; int route_len; #define MAX_RR_HDRS 64 static str route[MAX_RR_HDRS]; char *cp, *start; if(iroute==NULL) return 0; route_len= 0; memset(route, 0, MAX_RR_HDRS*sizeof(str)); while (iroute!=NULL) { if (parse_rr(iroute) < 0) { LM_ERR("failed to parse RR\n"); goto error; } p =(rr_t*)iroute->parsed; while (p) { route[n].s = p->nameaddr.name.s; route[n].len = p->len; LM_DBG("current rr is %.*s\n", route[n].len, route[n].s); n++; if(n==MAX_RR_HDRS) { LM_ERR("too many RR\n"); goto error; } p = p->next; } iroute = next_sibling_hdr(iroute); } for(i=0;i<n;i++){ if(!nb_recs || (nb_recs && ( (!order&& (i>=*nb_recs)) || (order && (i<=(n-*nb_recs)) )) ) ) { route_len+= route[i].len; nr++; } } if(nb_recs) LM_DBG("skipping %i route records\n", *nb_recs); route_len += --nr; /* for commas */ oroute->s=(char*)pkg_malloc(route_len); if(oroute->s==0) { LM_ERR("no more pkg mem\n"); goto error; } cp = start = oroute->s; if(order==0) { i= (nb_recs == NULL) ? 0:*nb_recs; while (i<n) { memcpy(cp, route[i].s, route[i].len); cp += route[i].len; if (++i<n) *(cp++) = ','; } } else { i = (nb_recs == NULL) ? n-1 : (n-*nb_recs-1); while (i>=0) { memcpy(cp, route[i].s, route[i].len); cp += route[i].len; if (i-->0) *(cp++) = ','; } } oroute->len=cp - start; LM_DBG("out rr [%.*s]\n", oroute->len, oroute->s); LM_DBG("we have %i records\n", n); if(nb_recs != NULL) *nb_recs = (unsigned int)n; return 0; error: return -1; }
/*Actions are composed as follows: * (the action length and type as always= 5 bytes) * 4:uac_id * * int request(str* method, str* req_uri, str* to, str* from, str* headers, str* body, transaction_cb c, void* cp) * TODO performance speedup: instead of using * dynamically allocated memory for headers,body,totag,reason and my_msg * use static buffers. * */ int ac_uac_req(as_p the_as,unsigned char processor_id,unsigned int flags,char *action,int len) { unsigned int cseq; char err_buf[MAX_REASON_LEN]; struct sip_msg *my_msg; struct to_body *fb,*tb; struct cseq_body *cseqb; struct as_uac_param *the_param; dlg_t *my_dlg; int k,retval,uac_id,sip_error,ret,err_ret; long clen; str headers,body,fake_uri; uac_req_t uac_r; headers.s=body.s=fake_uri.s=NULL; my_dlg=NULL; my_msg=NULL; the_param=NULL; k=clen=0; net2hostL(uac_id,action,k); if(!(headers.s=pkg_malloc(MAX_HEADER))){ LM_ERR("Out of Memory!!"); goto error; } headers.len=0; LM_DBG("Action UAC Message: uac_id:%d processor_id=%d\n",uac_id,processor_id); if (!(my_msg = parse_ac_msg(HDR_EOH_F,action+k,len-k))) { LM_ERR("out of memory!\n"); goto error; } if(my_msg->first_line.type==SIP_REPLY){ LM_ERR("trying to create a UAC with a SIP response!!\n"); goto error; } if(parse_headers(my_msg,HDR_EOH_F,0)==-1){ LM_ERR("ERROR:seas:ac_uac_req:parsing headers\n"); goto error; } if(parse_from_header(my_msg)<0){ LM_ERR("parsing from header ! \n"); goto error; } if(check_transaction_quadruple(my_msg)==0){ as_action_fail_resp(uac_id,SE_UAC,"Headers missing (to,from,call-id,cseq)?",0); LM_ERR("Headers missing (to,from,call-id,cseq)?"); goto error; } if(!(get_from(my_msg)) || !(get_from(my_msg)->tag_value.s) || !(get_from(my_msg)->tag_value.len)){ as_action_fail_resp(uac_id,SE_UAC,"From tag missing",0); LM_ERR("From tag missing"); goto error; } fb=my_msg->from->parsed; tb=my_msg->to->parsed; cseqb=my_msg->cseq->parsed; if(0!=(str2int(&cseqb->number,&cseq))){ LM_DBG("unable to parse CSeq\n"); goto error; } if(my_msg->first_line.u.request.method_value != METHOD_ACK && my_msg->first_line.u.request.method_value != METHOD_CANCEL) { /** we trick req_within */ cseq--; } if(seas_f.tmb.new_dlg_uac(&(my_msg->callid->body),&(fb->tag_value),cseq,\ &(fb->uri),&(tb->uri),&my_dlg) < 0) { as_action_fail_resp(uac_id,SE_UAC,"Error creating new dialog",0); LM_ERR("Error while creating new dialog\n"); goto error; } if(seas_f.tmb.dlg_add_extra(my_dlg,&(fb->display),&(tb->display)) < 0 ) { as_action_fail_resp(uac_id,SE_UAC, "Error adding the display names to the new dialog",0); LM_ERR("failed to add display names to the new dialog\n"); goto error; } if(tb->tag_value.s && tb->tag_value.len) shm_str_dup(&my_dlg->id.rem_tag,&tb->tag_value); /**Awful hack: to be able to set our own CSeq, from_tag and call-ID we have * to use req_within instead of req_outside (it sets it's own CSeq,Call-ID * and ftag), so we have to simulate that the dialog is already in completed * state so... */ server_signature=0; my_dlg->state = DLG_CONFIRMED; if(0>(headers.len=extract_allowed_headers(my_msg,1,-1,HDR_CONTENTLENGTH_F|HDR_ROUTE_F|HDR_TO_F|HDR_FROM_F|HDR_CALLID_F|HDR_CSEQ_F,headers.s,MAX_HEADER))) { LM_ERR("Unable to extract allowed headers!!\n"); goto error; } headers.s[headers.len]=0; /*let's get the body*/ if(my_msg->content_length) clen=(long)get_content_length(my_msg); if(clen!=0){ if(!(body.s=pkg_malloc(clen))){ LM_ERR("Out of Memory!"); goto error; } memcpy(body.s,get_body(my_msg),clen); body.len=clen; body.s[clen]=0; LM_DBG("Trying to construct a Sip Request with: body:%d[%.*s] headers:%d[%.*s]\n",\ body.len,body.len,body.s,headers.len,headers.len,headers.s); /*t_reply_with_body un-ref-counts the transaction, so dont use it anymore*/ }else{ body.s=NULL; body.len=0; } /*Now... create the UAC !! * it would be great to know the hash_index and the label that have been assigned * to our newly created cell, but t_uac does not leave any way for us to know... * only that when that transaction transitions its state (ie. a response is received, * a timeout is reached, etc...) the callback will be called with the given parameter. * * So the only way we have to know who we are, is passing as a parameter a structure with * 2 pointers: one to the app_server and the other, the identifier of the UAC (uac_id). * */ if(!(the_param=shm_malloc(sizeof(struct as_uac_param)))){ LM_ERR("out of shared memory\n"); goto error; } the_param->who=my_as; the_param->uac_id=uac_id; the_param->processor_id=processor_id; the_param->destroy_cb_set=0; shm_str_dup(&my_dlg->rem_target,&my_msg->first_line.u.request.uri); if (my_msg->route) { if (parse_rr(my_msg->route) < 0) { LM_ERR( "Error while parsing Route body\n"); goto error; } /* TODO route_set should be a shm copy of my_msg->route->parsed */ my_dlg->route_set=(rr_t*)my_msg->route->parsed; /** this SHOULD be: shm_duplicate_rr(&my_dlg->route_set,my_msg->route->parsed); * but it will last more... */ } calculate_hooks(my_dlg); if(flags & SPIRAL_FLAG){ memcpy(headers.s+headers.len,SPIRAL_HDR CRLF,SPIRAL_HDR_LEN + CRLF_LEN); headers.len+=SPIRAL_HDR_LEN+CRLF_LEN; headers.s[headers.len]=0; fake_uri.s=pkg_malloc(200); fake_uri.len=print_local_uri(the_as,processor_id,fake_uri.s,200); if(fake_uri.len<0){ LM_ERR("printing local uri\n"); goto error; } my_dlg->hooks.next_hop=&fake_uri; } /* Kamailio and OpenSIPs seem to have diverged quite a bit on flags and events notified to UACs. Let's see if kamailio gets it right by now, if not this is a TODO: check PASS_PROVISIONAL my_dlg->T_flags=T_NO_AUTO_ACK|T_PASS_PROVISIONAL_FLAG ; this is the same as (TMCB_DONT_ACK|TMCB_LOCAL_RESPONSE_OUT) in Kamailio */ set_uac_req(&uac_r, &(my_msg->first_line.u.request.method), &headers, &body, my_dlg,TMCB_DONT_ACK|TMCB_LOCAL_RESPONSE_OUT, uac_cb, (void*)the_param); ret=seas_f.tmb.t_request_within(&uac_r); /** now undo all the fakes we have put in my_dlg*/ /*because my_dlg->route_set should be shm but we fake it (its pkg_mem)*/ my_dlg->route_set=(rr_t *)0; if (ret < 0) { err_ret = err2reason_phrase(ret,&sip_error,err_buf, sizeof(err_buf), "SEAS/UAC"); LM_ERR("failed to send the [%.*s] request\n",uac_r.method->len,uac_r.method->s); LM_ERR("Error on request_within %s\n",err_buf ); if(err_ret > 0) { as_action_fail_resp(uac_id,ret,err_buf,0); }else{ as_action_fail_resp(uac_id,E_UNSPEC,"500 SEAS/UAC error",0); } goto error; } retval=0; goto exit; error: retval = -1; if(the_param) shm_free(the_param); exit: seas_f.tmb.free_dlg(my_dlg); if(headers.s) pkg_free(headers.s); if(body.s) pkg_free(body.s); if(fake_uri.s) pkg_free(fake_uri.s); if(my_msg){ if(my_msg->headers) free_hdr_field_lst(my_msg->headers); pkg_free(my_msg); } return retval; }