/* * This method is used to parse Call-Info header. * * params: msg : sip msg * returns 0 on success, * -1 on failure. */ int parse_call_info_header( struct sip_msg *msg ) { struct call_info_body *callinfo_b, *old_callinfo_b=NULL; struct to_body *call_info_b; struct hdr_field *call_info; void **parsed; char *tmp, *end, *start; unsigned int len; if ( !msg->call_info && (parse_headers(msg, HDR_CALL_INFO_F,0)==-1 || !msg->call_info)) { return -1; } call_info=msg->call_info; /* maybe the header is already parsed! */ if (call_info->parsed) return 0; parsed = &(call_info->parsed); while(*parsed == NULL) { len = call_info->body.len+1; start = call_info->body.s; end = start + len; LM_DBG("parsing the whole body [%.*s]\n", len, call_info->body.s); for( tmp=call_info->body.s; tmp<=end; tmp++) { if (*tmp == ',' || tmp==end) { LM_DBG("[%.*s]\n",(int)(tmp-start),start); callinfo_b = pkg_malloc(sizeof(struct call_info_body)); if (callinfo_b == NULL) { LM_ERR("out of pkg_memory\n"); goto error; } memset(callinfo_b, 0, sizeof(struct call_info_body)); /* now parse it!! */ call_info_b = &(callinfo_b->call_info_body); parse_to(start, tmp, call_info_b); if (call_info_b->error == PARSE_ERROR) { LM_ERR("bad Call-Info header\n"); pkg_free(call_info_b); set_err_info(OSER_EC_PARSER, OSER_EL_MEDIUM, "error parsing Call-Info header"); set_err_reply(400, "bad header"); goto error; } /* Save the first parsed body */ if (*parsed == NULL) *parsed = callinfo_b; else old_callinfo_b->next = callinfo_b; old_callinfo_b = callinfo_b; start = tmp + 1; } } call_info = call_info->sibling; LM_DBG("done ... next call_info [%p]\n", call_info); if (call_info == NULL) { break; } parsed = &(call_info->parsed); } return 0; error: 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 */ 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_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 method is used to parse Privacy HF body, which consist of * comma separated list of priv-values. After parsing, msg->privacy->parsed * contains enum bits of privacy values defined in parse_privacy.h. * Returns 0 on success and -1 on failure. */ int parse_privacy(struct sip_msg *msg) { unsigned int val_len, value, values, len; str next; char *p, *beyond; /* maybe the header is already parsed! */ if (msg->privacy && msg->privacy->parsed) return 0; /* parse Privacy HF (there should be only one) */ if (!msg->privacy && (parse_headers(msg, HDR_PRIVACY_F, 0) == -1 || !msg->privacy)) { goto error; } next.len = msg->privacy->body.len; next.s = msg->privacy->body.s; trim_leading(&next); if (next.len == 0) { LM_ERR("no values\n"); goto parse_error; } values = 0; p = next.s; len = next.len; beyond = p + len; while (p < beyond) { if((val_len = parse_priv_value(p, len, &value)) != 0) { values |= value; p = p + val_len; len = len - val_len; } else { LM_ERR("invalid privacy value\n"); goto parse_error; } while(p < beyond && (*p == ' ' || *p == '\t' || *p == '\r' || *p == '\n')) p++; if(p >= beyond) break; if (*p == ';') { p++; while(p < beyond && (*p == ' ' || *p == '\t' || *p == '\r' || *p == '\n')) p++; if(p >= beyond) { LM_ERR("no privacy value after comma\n"); goto parse_error; } } else { LM_ERR("semicolon expected\n"); goto parse_error; } } if ((values & PRIVACY_NONE) && (values ^ PRIVACY_NONE)) { LM_ERR("no other privacy values allowed with 'none'\n"); goto parse_error; } msg->privacy->parsed = (void *)(long)values; return 0; parse_error: set_err_info(OSER_EC_PARSER, OSER_EL_MEDIUM, "error parsing privacy header"); set_err_reply(400, "bad headers"); error: return -1; }