int via_diff(struct sip_msg *req,struct sip_msg *resp) { struct hdr_field *hf; struct via_body *vb; int i,j,k; i=j=k=0; /* count how many via bodies come in the response*/ for(hf=resp->h_via1;hf;hf=next_sibling_hdr(hf)){ if(!hf->parsed){ if((vb=pkg_malloc(sizeof(struct via_body)))==0){ LM_ERR("Out of mem in via_diff!!\n"); return -1; } memset(vb,0,sizeof(struct via_body)); if(parse_via(hf->body.s,hf->body.s+hf->body.len+1,vb)==0){ LM_ERR("Unable to parse via in via_diff!\n"); pkg_free(vb); return -1; } hf->parsed=vb; j=1; } for(vb=hf->parsed;vb;vb=vb->next){ i++; } if(j){ free_via_list((struct via_body*)hf->parsed); hf->parsed=NULL; j=0; } } j=0; /* count how many via bodies were in the orig. request*/ for(hf=req->h_via1;hf;hf=next_sibling_hdr(hf)){ if(!hf->parsed){ if((vb=pkg_malloc(sizeof(struct via_body)))==0){ goto error; } memset(vb,0,sizeof(struct via_body)); if(parse_via(hf->body.s,hf->body.s+hf->body.len+1,vb)==0){ goto error; } hf->parsed=vb; j=1; } for(vb=hf->parsed;vb;vb=vb->next){ k++; } if(j){ free_via_list((struct via_body*)hf->parsed); hf->parsed=NULL; j=0; } } return i-k; error: return -1; }
/** * Looks for the Last Via header and returns it. * @param msg - the SIP message * @returns the last via body body */ struct via_body* cscf_get_last_via(struct sip_msg *msg) { struct hdr_field *h=0,*i; struct via_body *vb; if (parse_headers(msg,HDR_EOH_F,0)!=0) { LM_ERR("cscf_get_last_via: Error parsing until last header\n"); return 0; } i = msg->headers; while(i){ if (i->type == HDR_VIA_T){ h = i; } i = i->next; } if (!h) return 0; if (!h->parsed){ vb = pkg_malloc(sizeof(struct via_body)); if (!vb){ LM_ERR("cscf_get_last_via: Error allocating %lx bytes\n",sizeof(struct via_body)); return 0; } parse_via(h->body.s,h->body.s+h->body.len,vb); h->parsed = vb; } vb = h->parsed; while(vb->next) vb = vb->next; return vb; }
/* returns pointer to next header line, and fill hdr_f ; * if at end of header returns pointer to the last crlf (always buf)*/ char* get_hdr_field(char* const buf, char* const end, struct hdr_field* const hdr) { char *tmp = 0; char *match; struct via_body *vb; struct cseq_body* cseq_b; struct to_body* to_b; int integer, err; unsigned uval; if(!buf) { DBG("null buffer pointer\n"); goto error; } if ((*buf)=='\n' || (*buf)=='\r') { /* double crlf or lflf or crcr */ DBG("found end of header\n"); hdr->type=HDR_EOH_T; return buf; } tmp=parse_hname(buf, end, hdr); if (hdr->type==HDR_ERROR_T) { LOG(L_ERR, "ERROR: get_hdr_field: bad header\n"); goto error; } /* eliminate leading whitespace */ tmp=eat_lws_end(tmp, end); if (tmp>=end) { LOG(L_ERR, "ERROR: get_hdr_field: HF empty\n"); goto error; } /* if header-field well-known, parse it, find its end otherwise ; * after leaving the hdr->type switch, tmp should be set to the * next header field */ switch(hdr->type) { case HDR_VIA_T: /* keep number of vias parsed -- we want to report it in replies for diagnostic purposes */ via_cnt++; vb=pkg_malloc(sizeof(struct via_body)); if (vb==0) { LOG(L_ERR, "get_hdr_field: out of memory\n"); goto error; } memset(vb,0,sizeof(struct via_body)); hdr->body.s=tmp; tmp=parse_via(tmp, end, vb); if (vb->error==PARSE_ERROR) { LOG(L_ERR, "ERROR: get_hdr_field: bad via\n"); free_via_list(vb); goto error; } hdr->parsed=vb; vb->hdr.s=hdr->name.s; vb->hdr.len=hdr->name.len; hdr->body.len=tmp-hdr->body.s; break; case HDR_CSEQ_T: cseq_b=pkg_malloc(sizeof(struct cseq_body)); if (cseq_b==0) { LOG(L_ERR, "get_hdr_field: out of memory\n"); goto error; } memset(cseq_b, 0, sizeof(struct cseq_body)); hdr->body.s=tmp; tmp=parse_cseq(tmp, end, cseq_b); if (cseq_b->error==PARSE_ERROR) { LOG(L_ERR, "ERROR: get_hdr_field: bad cseq\n"); free_cseq(cseq_b); goto error; } hdr->parsed=cseq_b; hdr->body.len=tmp-hdr->body.s; DBG("get_hdr_field: cseq <%.*s>: <%.*s> <%.*s>\n", hdr->name.len, ZSW(hdr->name.s), cseq_b->number.len, ZSW(cseq_b->number.s), cseq_b->method.len, cseq_b->method.s); break; case HDR_TO_T: to_b=pkg_malloc(sizeof(struct to_body)); if (to_b==0) { LOG(L_ERR, "get_hdr_field: out of memory\n"); goto error; } memset(to_b, 0, sizeof(struct to_body)); hdr->body.s=tmp; tmp=parse_to(tmp, end,to_b); if (to_b->error==PARSE_ERROR) { LOG(L_ERR, "ERROR: get_hdr_field: bad to header\n"); free_to(to_b); goto error; } hdr->parsed=to_b; hdr->body.len=tmp-hdr->body.s; DBG("DEBUG: get_hdr_field: <%.*s> [%d]; uri=[%.*s] \n", hdr->name.len, ZSW(hdr->name.s), hdr->body.len, to_b->uri.len,ZSW(to_b->uri.s)); DBG("DEBUG: to body [%.*s]\n",to_b->body.len, ZSW(to_b->body.s)); break; case HDR_CONTENTLENGTH_T: hdr->body.s=tmp; tmp=parse_content_length(tmp,end, &integer); if (tmp==0) { LOG(L_ERR, "ERROR:get_hdr_field: bad content_length header\n"); goto error; } hdr->parsed=(void*)(long)integer; hdr->body.len=tmp-hdr->body.s; DBG("DEBUG: get_hdr_body : content_length=%d\n", (int)(long)hdr->parsed); break; case HDR_RETRY_AFTER_T: hdr->body.s=tmp; tmp=parse_retry_after(tmp,end, &uval, &err); if (err) { LOG(L_ERR, "ERROR:get_hdr_field: bad retry_after header\n"); goto error; } hdr->parsed=(void*)(unsigned long)uval; hdr->body.len=tmp-hdr->body.s; DBG("DEBUG: get_hdr_body : retry_after=%d\n", (unsigned)(long)hdr->parsed); break; case HDR_IDENTITY_T: case HDR_DATE_T: case HDR_IDENTITY_INFO_T: case HDR_SUPPORTED_T: case HDR_REQUIRE_T: case HDR_CONTENTTYPE_T: case HDR_FROM_T: case HDR_CALLID_T: case HDR_CONTACT_T: case HDR_ROUTE_T: case HDR_RECORDROUTE_T: case HDR_MAXFORWARDS_T: case HDR_AUTHORIZATION_T: case HDR_EXPIRES_T: case HDR_PROXYAUTH_T: case HDR_PROXYREQUIRE_T: case HDR_UNSUPPORTED_T: case HDR_ALLOW_T: case HDR_EVENT_T: case HDR_ACCEPT_T: case HDR_ACCEPTLANGUAGE_T: case HDR_ORGANIZATION_T: case HDR_PRIORITY_T: case HDR_SUBJECT_T: case HDR_USERAGENT_T: case HDR_SERVER_T: case HDR_CONTENTDISPOSITION_T: case HDR_DIVERSION_T: case HDR_RPID_T: case HDR_SIPIFMATCH_T: case HDR_REFER_TO_T: case HDR_SESSIONEXPIRES_T: case HDR_MIN_SE_T: case HDR_SUBSCRIPTION_STATE_T: case HDR_ACCEPTCONTACT_T: case HDR_ALLOWEVENTS_T: case HDR_CONTENTENCODING_T: case HDR_REFERREDBY_T: case HDR_REJECTCONTACT_T: case HDR_REQUESTDISPOSITION_T: case HDR_WWW_AUTHENTICATE_T: case HDR_PROXY_AUTHENTICATE_T: case HDR_PATH_T: case HDR_PRIVACY_T: case HDR_PAI_T: case HDR_PPI_T: case HDR_REASON_T: case HDR_OTHER_T: /* just skip over it */ hdr->body.s=tmp; /* find end of header */ /* find lf */ do { match=q_memchr(tmp, '\n', end-tmp); if (match) { match++; } else { LOG(L_ERR, "ERROR: get_hdr_field: bad body for <%s>(%d)\n", hdr->name.s, hdr->type); /* abort(); */ tmp=end; goto error; } tmp=match; } while( match<end &&( (*match==' ')||(*match=='\t') ) ); tmp=match; hdr->body.len=match-hdr->body.s; break; default: LOG(L_CRIT, "BUG: get_hdr_field: unknown header type %d\n", hdr->type); goto error; } /* jku: if \r covered by current length, shrink it */ trim_r( hdr->body ); hdr->len=tmp-hdr->name.s; return tmp; error: DBG("get_hdr_field: error exit\n"); STATS_BAD_MSG_HDR(); hdr->type=HDR_ERROR_T; hdr->len=tmp-hdr->name.s; return tmp; }
/* * Create a fake topmost Via header field because HTTP clients * do not generate Vias */ static int insert_fake_via(struct sip_msg* msg, char* via, int via_len) { struct via_body* vb = 0; via_cnt++; vb = pkg_malloc(sizeof(struct via_body)); if (vb == 0){ ERR("insert_fake_via: Out of memory\n"); goto error; } msg->h_via1 = pkg_malloc(sizeof(struct hdr_field)); if (!msg->h_via1) { ERR("No memory left\n"); goto error; } memset(msg->h_via1, 0, sizeof(struct hdr_field)); memset(vb, 0, sizeof(struct via_body)); /* FIXME: The code below would break if the VIA prefix * gets changed in config.h */ msg->h_via1->name.s = via; msg->h_via1->name.len = 3; msg->h_via1->body.s = via + 5; msg->h_via1->body.len = via_len - 5 - CRLF_LEN; msg->h_via1->type = HDR_VIA_T; msg->h_via1->parsed = vb; /* This field is used by the msg translator to add a new * via when forwarding the request. It must point to an existing * header field because otherwise call to anchor_lump, which does * hdr.s - buf, would crash */ vb->hdr.s = msg->headers->name.s; vb->hdr.len = 0; msg->via1 = vb; /* We have to replace the zero terminating character right behind * CRLF because otherwise the parser will return an error. * It expects that there is either a next header field or another * CRLF delimiter */ via[via_len] = 'a'; parse_via(via + 5, via + via_len + 1, vb); if (vb->error == PARSE_ERROR){ ERR("Bad via\n"); goto error; } if (msg->last_header == 0) { msg->headers = msg->h_via1; msg->last_header = msg->h_via1; } else { msg->last_header->next = msg->h_via1; msg->last_header = msg->h_via1; } return 0; error: if (vb) { free_via_list(vb); pkg_free(vb); } if (msg->h_via1) pkg_free(msg->h_via1); return -1; }
int th_unmask_via(sip_msg_t *msg, str *cookie) { hdr_field_t *hdr; struct via_body *via; struct via_body *via2; struct via_param *vp; struct lump* l; int i; str out; int vlen; 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++; LM_DBG("=======via[%d]\n", i); LM_DBG("hdr: [%.*s]\n", via->hdr.len, via->hdr.s); vlen = th_skip_rw(via->name.s, via->bsize); LM_DBG("body: %d: [%.*s]\n", vlen, vlen, via->name.s); if(i!=1) { vp = th_get_via_param(via, &th_vparam_name); if(vp==NULL) { LM_ERR("cannot find param in via %d\n", i); return -1; } if(i==2) out.s = th_mask_decode(vp->value.s, vp->value.len, &th_vparam_prefix, CRLF_LEN+1, &out.len); else out.s = th_mask_decode(vp->value.s, vp->value.len, &th_vparam_prefix, 0, &out.len); if(out.s==NULL) { LM_ERR("cannot encode via %d\n", i); return -1; } LM_DBG("+body: %d: [%.*s]\n", out.len, out.len, out.s); if(i==2) { via2=pkg_malloc(sizeof(struct via_body)); if (via2==0) { LM_ERR("out of memory\n"); pkg_free(out.s); return -1; } memset(via2, 0, sizeof(struct via_body)); memcpy(out.s+out.len, CRLF, CRLF_LEN); out.s[out.len+CRLF_LEN]='X'; if(parse_via(out.s, out.s+out.len+CRLF_LEN+1, via2)==NULL) { LM_ERR("error parsing decoded via2\n"); free_via_list(via2); pkg_free(out.s); return -1; } out.s[out.len] = '\0'; vp = th_get_via_param(via2, &th_cookie_name); if(vp==NULL) { LM_ERR("cannot find cookie in via2\n"); free_via_list(via2); pkg_free(out.s); return -1; } *cookie = vp->value; free_via_list(via2); } l=del_lump(msg, via->name.s-msg->buf, vlen, 0); if (l==0) { LM_ERR("failed deleting via [%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; } } } } return 0; }
/* returns pointer to next header line, and fill hdr_f ; * if at end of header returns pointer to the last crlf (always buf)*/ char* get_hdr_field(char* buf, char* end, struct hdr_field* hdr) { char* tmp; char *match; struct via_body *vb; struct cseq_body* cseq_b; struct to_body* to_b; int integer; if ((*buf)=='\n' || (*buf)=='\r'){ /* double crlf or lflf or crcr */ LM_DBG("found end of header\n"); hdr->type=HDR_EOH_T; return buf; } tmp=parse_hname(buf, end, hdr); if (hdr->type==HDR_ERROR_T){ LM_ERR("bad header\n"); goto error_bad_hdr; } /* eliminate leading whitespace */ tmp=eat_lws_end(tmp, end); if (tmp>=end) { LM_ERR("hf empty\n"); goto error_bad_hdr; } /* if header-field well-known, parse it, find its end otherwise ; * after leaving the hdr->type switch, tmp should be set to the * next header field */ switch(hdr->type){ case HDR_VIA_T: /* keep number of vias parsed -- we want to report it in replies for diagnostic purposes */ via_cnt++; vb=pkg_malloc(sizeof(struct via_body)); if (vb==0){ LM_ERR("out of pkg memory\n"); goto error; } memset(vb,0,sizeof(struct via_body)); hdr->body.s=tmp; tmp=parse_via(tmp, end, vb); if (vb->error==PARSE_ERROR){ LM_ERR("bad via\n"); free_via_list(vb); set_err_info(OSER_EC_PARSER, OSER_EL_MEDIUM, "error parsing Via"); set_err_reply(400, "bad Via header"); goto error; } hdr->parsed=vb; vb->hdr.s=hdr->name.s; vb->hdr.len=hdr->name.len; hdr->body.len=tmp-hdr->body.s; break; case HDR_CSEQ_T: cseq_b=pkg_malloc(sizeof(struct cseq_body)); if (cseq_b==0){ LM_ERR("out of pkg memory\n"); goto error; } memset(cseq_b, 0, sizeof(struct cseq_body)); hdr->body.s=tmp; tmp=parse_cseq(tmp, end, cseq_b); if (cseq_b->error==PARSE_ERROR){ LM_ERR("bad cseq\n"); pkg_free(cseq_b); set_err_info(OSER_EC_PARSER, OSER_EL_MEDIUM, "error parsing CSeq`"); set_err_reply(400, "bad CSeq header"); goto error; } hdr->parsed=cseq_b; hdr->body.len=tmp-hdr->body.s; LM_DBG("cseq <%.*s>: <%.*s> <%.*s>\n", hdr->name.len, ZSW(hdr->name.s), cseq_b->number.len, ZSW(cseq_b->number.s), cseq_b->method.len, cseq_b->method.s); break; case HDR_TO_T: to_b=pkg_malloc(sizeof(struct to_body)); if (to_b==0){ LM_ERR("out of pkg memory\n"); goto error; } memset(to_b, 0, sizeof(struct to_body)); hdr->body.s=tmp; tmp=parse_to(tmp, end,to_b); if (to_b->error==PARSE_ERROR){ LM_ERR("bad to header\n"); pkg_free(to_b); set_err_info(OSER_EC_PARSER, OSER_EL_MEDIUM, "error parsing To header"); set_err_reply(400, "bad header"); goto error; } hdr->parsed=to_b; hdr->body.len=tmp-hdr->body.s; LM_DBG("<%.*s> [%d]; uri=[%.*s] \n", hdr->name.len, ZSW(hdr->name.s), hdr->body.len, to_b->uri.len,ZSW(to_b->uri.s)); LM_DBG("to body [%.*s]\n",to_b->body.len, ZSW(to_b->body.s)); break; case HDR_CONTENTLENGTH_T: hdr->body.s=tmp; tmp=parse_content_length(tmp,end, &integer); if (tmp==0){ LM_ERR("bad content_length header\n"); set_err_info(OSER_EC_PARSER, OSER_EL_MEDIUM, "error parsing Content-Length"); set_err_reply(400, "bad Content-Length header"); goto error; } hdr->parsed=(void*)(long)integer; hdr->body.len=tmp-hdr->body.s; LM_DBG("content_length=%d\n", (int)(long)hdr->parsed); break; case HDR_SUPPORTED_T: case HDR_CONTENTTYPE_T: case HDR_FROM_T: case HDR_CALLID_T: case HDR_CONTACT_T: case HDR_ROUTE_T: case HDR_RECORDROUTE_T: case HDR_PATH_T: case HDR_MAXFORWARDS_T: case HDR_AUTHORIZATION_T: case HDR_EXPIRES_T: case HDR_PROXYAUTH_T: case HDR_PROXYREQUIRE_T: case HDR_UNSUPPORTED_T: case HDR_ALLOW_T: case HDR_EVENT_T: case HDR_ACCEPT_T: case HDR_ACCEPTLANGUAGE_T: case HDR_ORGANIZATION_T: case HDR_PRIORITY_T: case HDR_SUBJECT_T: case HDR_USERAGENT_T: case HDR_CONTENTDISPOSITION_T: case HDR_ACCEPTDISPOSITION_T: case HDR_DIVERSION_T: case HDR_RPID_T: case HDR_REFER_TO_T: case HDR_SESSION_EXPIRES_T: case HDR_MIN_SE_T: case HDR_MIN_EXPIRES_T: case HDR_PPI_T: case HDR_PAI_T: case HDR_PRIVACY_T: case HDR_RETRY_AFTER_T: case HDR_CALL_INFO_T: case HDR_WWW_AUTHENTICATE_T: case HDR_PROXY_AUTHENTICATE_T: case HDR_OTHER_T: /* just skip over it */ hdr->body.s=tmp; /* find end of header */ /* find lf */ do{ match=q_memchr(tmp, '\n', end-tmp); if (match){ match++; }else { LM_ERR("bad body for <%s>(%d)\n", hdr->name.s, hdr->type); tmp=end; goto error_bad_hdr; } tmp=match; }while( match<end &&( (*match==' ')||(*match=='\t') ) ); tmp=match; hdr->body.len=match-hdr->body.s; break; default: LM_CRIT("unknown header type %d\n", hdr->type); goto error; } /* jku: if \r covered by current length, shrink it */ trim_r( hdr->body ); hdr->len=tmp-hdr->name.s; return tmp; error_bad_hdr: set_err_info(OSER_EC_PARSER, OSER_EL_MEDIUM, "error parsing headers"); set_err_reply(400, "bad headers"); error: LM_DBG("error exit\n"); update_stat( bad_msg_hdr, 1); hdr->type=HDR_ERROR_T; hdr->len=tmp-hdr->name.s; return tmp; }
/* * This function encodes an arbitrary header into a chunk of bytes, * ready to be sent to the Application Server. * * The header codes start with this encoded-bytes: * 2: SIP-MSG-START based pointer to the header (including header name) * 2: length of the header * 1: length of the header name */ int encode_header(struct sip_msg *sipmsg,struct hdr_field *hdr,unsigned char *payload,int paylen) { int len=0; unsigned int integer,*methods=0; char *hdrstart,*tmp; unsigned short int ptr; struct to_body *tobody=0; struct via_body *viabody=0; struct cseq_body *cseqbody=0; char *msg,*myerror; int mlen; msg=sipmsg->buf; mlen=sipmsg->len; hdrstart = hdr->name.s; if(hdrstart-msg<0){ LM_ERR("header(%.*s) does not belong to sip_msg(hdrstart<msg)\n", hdr->name.len,hdr->name.s); return -1; } ptr=htons((short int)(hdrstart-msg)); if((hdrstart-msg)>mlen){ LM_ERR("out of the sip_msg bounds (%d>%d)\n",ntohs(ptr),mlen); return -1; } if(hdr->len>(1<<16)){ LM_ERR("length of header too long\n"); return -1; } memcpy(payload,&ptr,2); ptr=htons((short int)(hdr->len)); memcpy(payload+HEADER_LEN_IDX,&ptr,2); payload[HEADER_NAME_LEN_IDX]=(unsigned char)hdr->name.len; switch(hdr->type){ case HDR_FROM_T: case HDR_TO_T: case HDR_REFER_TO_T: case HDR_RPID_T: if(!hdr->parsed){ if((tobody=pkg_malloc(sizeof(struct to_body)))==0){ myerror="Out of memory !!\n"; goto error; } parse_to(hdr->body.s,hdr->body.s+hdr->body.len+1,tobody); if (tobody->error == PARSE_ERROR) { myerror="bad (REFER,TO,FROM,RPID) header\n"; pkg_free(tobody); return 5; goto error; } hdr->parsed=(struct to_body*)tobody; }else tobody=(struct to_body*)hdr->parsed; if((len=encode_to_body(hdr->name.s,hdr->len,tobody,payload+5))<0){ myerror="parsing from or to header\n"; goto error; }else{ return 5+len; } break; case HDR_CONTACT_T: if(!hdr->parsed) if(parse_contact(hdr)<0){ myerror="parsing contact\n"; goto error; } if((len=encode_contact_body(hdr->name.s,hdr->len,(contact_body_t*)hdr->parsed,payload+5))<0){ myerror="encoding contact header\n"; goto error; }else{ return 5+len; } break; case HDR_ROUTE_T: case HDR_RECORDROUTE_T: if(!hdr->parsed) if(parse_rr(hdr)<0){ myerror="encoding route or recordroute\n"; goto error; } if((len=encode_route_body(hdr->name.s,hdr->len,(rr_t*)hdr->parsed,payload+5))<0){ myerror="encoding route or recordroute header\n"; goto error; }else{ return 5+len; } break; case HDR_CONTENTLENGTH_T: if(!hdr->parsed){ tmp=parse_content_length(hdr->body.s,hdr->body.s+hdr->body.len+1,(int*)&integer); if (tmp==0){ myerror="bad content_length header\n"; goto error; } hdr->parsed=(void*)(long)integer; } if((len=encode_contentlength(hdr->name.s,hdr->len,(long int)hdr->parsed,(char*)(payload+5)))<0){ myerror="encoding content-length header\n"; goto error; }else{ return 5+len; } break; case HDR_VIA_T: if(!hdr->parsed){ if((viabody=pkg_malloc(sizeof(struct via_body)))==0){ myerror="out of memory\n"; goto error; } memset(viabody,0,sizeof(struct via_body)); if(parse_via(hdr->body.s,hdr->body.s+hdr->body.len+1,viabody)==0){ myerror="encoding via \n"; goto error; } hdr->parsed=viabody; } if((len=encode_via_body(hdr->name.s,hdr->len,(struct via_body*)hdr->parsed,payload+5))<0){ myerror="encoding via header\n"; goto error; }else{ return 5+len; } break; case HDR_ACCEPT_T: if(!hdr->parsed){ if(parse_accept_hdr(sipmsg)<0){ return 5; } } if((len=encode_accept(hdr->name.s,hdr->len,(unsigned int*)hdr->parsed,(char*)(payload+5)))<0){ myerror="encoding via header\n"; goto error; }else{ return 5+len; } break; case HDR_CONTENTTYPE_T: if(!hdr->parsed){ if(parse_content_type_hdr(sipmsg)<0){ myerror="encoding content-type header\n"; goto error; } } if((len=encode_content_type(hdr->name.s,hdr->len,(unsigned int)get_content_type(sipmsg),(char*)(payload+5)))<0){ myerror="encoding via header\n"; goto error; }else{ return 5+len; } break; case HDR_CSEQ_T: if(!hdr->parsed){ if((cseqbody=pkg_malloc(sizeof(struct cseq_body)))==0){ myerror="out of memory\n"; goto error; } memset(cseqbody,0,sizeof(struct cseq_body)); if(parse_cseq(hdr->name.s,hdr->body.s+hdr->body.len+1,cseqbody)==0){ myerror="encoding cseq header\n"; goto error; } hdr->parsed=cseqbody; } if((len=encode_cseq(hdr->name.s,hdr->len,(struct cseq_body*)hdr->parsed,payload+5))<0){ myerror="encoding via header\n"; goto error; }else{ return 5+len; } break; case HDR_EXPIRES_T: if(!hdr->parsed){ if(parse_expires(hdr)<0){ myerror="encoding expires header\n"; goto error; } } if((len=encode_expires(hdr->name.s,hdr->len,(exp_body_t *)hdr->parsed,payload+5))<0){ myerror="encoding expires header\n"; goto error; }else{ return 5+len; } break; case HDR_ALLOW_T: if(!hdr->parsed){ if((methods=pkg_malloc(sizeof(unsigned int)))==0){ myerror="out of memory\n"; goto error; } *methods=0; if(parse_methods(&hdr->body,methods)!=0){ myerror="encoding allow header\n"; pkg_free(methods); return 5; /*goto error;*/ } hdr->parsed=methods; } if((len=encode_allow(hdr->name.s,hdr->len,(unsigned int*)hdr->parsed,(char*)(payload+5)))<0){ myerror="encoding allow header\n"; goto error; }else{ return 5+len; } break; case HDR_AUTHORIZATION_T: case HDR_PROXYAUTH_T: if(!hdr->parsed){ if(parse_credentials(hdr)<0){ myerror="encoding a digest header\n"; goto error; } } if((len=encode_digest(hdr->name.s,hdr->len,(dig_cred_t*)(&(((auth_body_t*)hdr->parsed)->digest)),payload+5))<0){ myerror="encoding allow header\n"; goto error; }else{ return 5+len; } break; default: return 5; } return 1; error: if(tobody) pkg_free(tobody); if(cseqbody) pkg_free(cseqbody); if(viabody) free_via_list(viabody); if(methods) pkg_free(methods); LM_ERR("%s",myerror); return -1; }
/* returns pointer to next header line, and fill hdr_f ; * if at end of header returns pointer to the last crlf (always buf)*/ char* get_hdr_field(char* buf, char* end, struct hdr_field* hdr) { char* tmp; char *match; struct via_body *vb; struct cseq_body* cseq_b; struct to_body* to_b; int integer; if ((*buf)=='\n' || (*buf)=='\r'){ /* double crlf or lflf or crcr */ DBG("found end of header\n"); hdr->type=HDR_EOH; return buf; } tmp=parse_hname(buf, end, hdr); if (hdr->type==HDR_ERROR){ LOG(L_ERR, "ERROR: get_hdr_field: bad header\n"); goto error; } /* eliminate leading whitespace */ tmp=eat_lws_end(tmp, end); if (tmp>=end) { LOG(L_ERR, "ERROR: get_hdr_field: HF empty\n"); goto error; } /* if header-field well-known, parse it, find its end otherwise ; * after leaving the hdr->type switch, tmp should be set to the * next header field */ switch(hdr->type){ case HDR_VIA: /* keep number of vias parsed -- we want to report it in replies for diagnostic purposes */ via_cnt++; vb=pkg_malloc(sizeof(struct via_body)); if (vb==0){ LOG(L_ERR, "get_hdr_field: out of memory\n"); goto error; } memset(vb,0,sizeof(struct via_body)); hdr->body.s=tmp; tmp=parse_via(tmp, end, vb); if (vb->error==PARSE_ERROR){ LOG(L_ERR, "ERROR: get_hdr_field: bad via\n"); free_via_list(vb); goto error; } hdr->parsed=vb; vb->hdr.s=hdr->name.s; vb->hdr.len=hdr->name.len; hdr->body.len=tmp-hdr->body.s; break; case HDR_CSEQ: cseq_b=pkg_malloc(sizeof(struct cseq_body)); if (cseq_b==0){ LOG(L_ERR, "get_hdr_field: out of memory\n"); goto error; } memset(cseq_b, 0, sizeof(struct cseq_body)); hdr->body.s=tmp; tmp=parse_cseq(tmp, end, cseq_b); if (cseq_b->error==PARSE_ERROR){ LOG(L_ERR, "ERROR: get_hdr_field: bad cseq\n"); pkg_free(cseq_b); goto error; } hdr->parsed=cseq_b; hdr->body.len=tmp-hdr->body.s; DBG("get_hdr_field: cseq <%.*s>: <%.*s> <%.*s>\n", hdr->name.len, ZSW(hdr->name.s), cseq_b->number.len, ZSW(cseq_b->number.s), cseq_b->method.len, cseq_b->method.s); break; case HDR_TO: to_b=pkg_malloc(sizeof(struct to_body)); if (to_b==0){ LOG(L_ERR, "get_hdr_field: out of memory\n"); goto error; } memset(to_b, 0, sizeof(struct to_body)); hdr->body.s=tmp; tmp=parse_to(tmp, end,to_b); if (to_b->error==PARSE_ERROR){ LOG(L_ERR, "ERROR: get_hdr_field: bad to header\n"); pkg_free(to_b); goto error; } hdr->parsed=to_b; hdr->body.len=tmp-hdr->body.s; DBG("DEBUG: get_hdr_field: <%.*s> [%d]; uri=[%.*s] \n", hdr->name.len, ZSW(hdr->name.s), hdr->body.len, to_b->uri.len,ZSW(to_b->uri.s)); DBG("DEBUG: to body [%.*s]\n",to_b->body.len, ZSW(to_b->body.s)); break; case HDR_CONTENTLENGTH: hdr->body.s=tmp; tmp=parse_content_length(tmp,end, &integer); if (tmp==0){ LOG(L_ERR, "ERROR:get_hdr_field: bad content_length header\n"); goto error; } hdr->parsed=(void*)(long)integer; hdr->body.len=tmp-hdr->body.s; DBG("DEBUG: get_hdr_body : content_length=%d\n", (int)(long)hdr->parsed); break; case HDR_SUPPORTED: case HDR_CONTENTTYPE: case HDR_FROM: case HDR_CALLID: case HDR_CONTACT: case HDR_ROUTE: case HDR_RECORDROUTE: case HDR_MAXFORWARDS: case HDR_AUTHORIZATION: case HDR_EXPIRES: case HDR_PROXYAUTH: case HDR_PROXYREQUIRE: case HDR_UNSUPPORTED: case HDR_ALLOW: case HDR_EVENT: case HDR_ACCEPT: case HDR_ACCEPTLANGUAGE: case HDR_ORGANIZATION: case HDR_PRIORITY: case HDR_SUBJECT: case HDR_USERAGENT: case HDR_CONTENTDISPOSITION: case HDR_ACCEPTDISPOSITION: case HDR_DIVERSION: case HDR_RPID: case HDR_OTHER: /* just skip over it */ hdr->body.s=tmp; /* find end of header */ /* find lf */ do{ match=q_memchr(tmp, '\n', end-tmp); if (match){ match++; }else { LOG(L_ERR, "ERROR: get_hdr_field: bad body for <%s>(%d)\n", hdr->name.s, hdr->type); /* abort(); */ tmp=end; goto error; } tmp=match; }while( match<end &&( (*match==' ')||(*match=='\t') ) ); tmp=match; hdr->body.len=match-hdr->body.s; break; default: LOG(L_CRIT, "BUG: get_hdr_field: unknown header type %d\n", hdr->type); goto error; } /* jku: if \r covered by current length, shrink it */ trim_r( hdr->body ); hdr->len=tmp-hdr->name.s; return tmp; error: DBG("get_hdr_field: error exit\n"); hdr->type=HDR_ERROR; hdr->len=tmp-hdr->name.s; return tmp; }