示例#1
0
/*
 * 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;
}
示例#2
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_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;
}
示例#3
0
/*
 * 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;
}