Exemple #1
0
hdr_field_t* get_hdr(const sip_msg_t* const msg, const enum _hdr_types_t ht)
{
    hdr_field_t *hdr;

    if (msg->parsed_flag & HDR_T2F(ht))
        for(hdr = msg->headers; hdr; hdr = hdr->next) {
            if(hdr->type == ht) return hdr;
        }
    return NULL;
}
Exemple #2
0
/* note: it continues where it previously stopped and goes ahead until
   end is encountered or desired HFs are found; if you call it twice
   for the same HF which is present only once, it will fail the second
   time; if you call it twice and the HF is found on second time too,
   it's not replaced in the well-known HF pointer but just added to
   header list; if you want to use a dumb convenience function which will
   give you the first occurrence of a header you are interested in,
   look at check_transaction_quadruple
*/
int parse_headers(struct sip_msg* const msg, const hdr_flags_t flags, const int next)
{
    struct hdr_field* hf;
    char* tmp;
    char* rest;
    char* end;
    hdr_flags_t orig_flag;

    end=msg->buf+msg->len;
    tmp=msg->unparsed;

    if (unlikely(next)) {
        orig_flag = msg->parsed_flag;
        msg->parsed_flag &= ~flags;
    } else
        orig_flag=0;

#ifdef EXTRA_DEBUG
    DBG("parse_headers: flags=%llx\n", (unsigned long long)flags);
#endif
    while( tmp<end && (flags & msg->parsed_flag) != flags) {
        prefetch_loc_r(tmp+64, 1);
        hf=pkg_malloc(sizeof(struct hdr_field));
        if (unlikely(hf==0)) {
            ser_error=E_OUT_OF_MEM;
            LOG(L_ERR, "ERROR:parse_headers: memory allocation error\n");
            goto error;
        }
        memset(hf,0, sizeof(struct hdr_field));
        hf->type=HDR_ERROR_T;
        rest=get_hdr_field(tmp, end, hf);
        switch (hf->type) {
        case HDR_ERROR_T:
            LOG(L_INFO,"ERROR: bad header field [%.*s]\n",
                (end-tmp>20)?20:(int)(end-tmp), tmp);
            goto  error;
        case HDR_EOH_T:
            msg->eoh=tmp; /* or rest?*/
            msg->parsed_flag|=HDR_EOH_F;
            pkg_free(hf);
            goto skip;
        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_RETRY_AFTER_T:
        case HDR_OTHER_T: /* mark the type as found/parsed*/
            msg->parsed_flag|=HDR_T2F(hf->type);
            break;
        case HDR_CALLID_T:
            if (msg->callid==0) msg->callid=hf;
            msg->parsed_flag|=HDR_CALLID_F;
            break;
        case HDR_SIPIFMATCH_T:
            if (msg->sipifmatch==0) msg->sipifmatch=hf;
            msg->parsed_flag|=HDR_SIPIFMATCH_F;
            break;
        case HDR_TO_T:
            if (msg->to==0) msg->to=hf;
            msg->parsed_flag|=HDR_TO_F;
            break;
        case HDR_CSEQ_T:
            if (msg->cseq==0) msg->cseq=hf;
            msg->parsed_flag|=HDR_CSEQ_F;
            break;
        case HDR_FROM_T:
            if (msg->from==0) msg->from=hf;
            msg->parsed_flag|=HDR_FROM_F;
            break;
        case HDR_CONTACT_T:
            if (msg->contact==0) msg->contact=hf;
            msg->parsed_flag|=HDR_CONTACT_F;
            break;
        case HDR_MAXFORWARDS_T:
            if(msg->maxforwards==0) msg->maxforwards=hf;
            msg->parsed_flag|=HDR_MAXFORWARDS_F;
            break;
        case HDR_ROUTE_T:
            if (msg->route==0) msg->route=hf;
            msg->parsed_flag|=HDR_ROUTE_F;
            break;
        case HDR_RECORDROUTE_T:
            if (msg->record_route==0) msg->record_route = hf;
            msg->parsed_flag|=HDR_RECORDROUTE_F;
            break;
        case HDR_CONTENTTYPE_T:
            if (msg->content_type==0) msg->content_type = hf;
            msg->parsed_flag|=HDR_CONTENTTYPE_F;
            break;
        case HDR_CONTENTLENGTH_T:
            if (msg->content_length==0) msg->content_length = hf;
            msg->parsed_flag|=HDR_CONTENTLENGTH_F;
            break;
        case HDR_AUTHORIZATION_T:
            if (msg->authorization==0) msg->authorization = hf;
            msg->parsed_flag|=HDR_AUTHORIZATION_F;
            break;
        case HDR_EXPIRES_T:
            if (msg->expires==0) msg->expires = hf;
            msg->parsed_flag|=HDR_EXPIRES_F;
            break;
        case HDR_PROXYAUTH_T:
            if (msg->proxy_auth==0) msg->proxy_auth = hf;
            msg->parsed_flag|=HDR_PROXYAUTH_F;
            break;
        case HDR_PROXYREQUIRE_T:
            if (msg->proxy_require==0) msg->proxy_require = hf;
            msg->parsed_flag|=HDR_PROXYREQUIRE_F;
            break;
        case HDR_SUPPORTED_T:
            if (msg->supported==0) msg->supported=hf;
            msg->parsed_flag|=HDR_SUPPORTED_F;
            break;
        case HDR_REQUIRE_T:
            if (msg->require==0) msg->require=hf;
            msg->parsed_flag|=HDR_REQUIRE_F;
            break;
        case HDR_UNSUPPORTED_T:
            if (msg->unsupported==0) msg->unsupported=hf;
            msg->parsed_flag|=HDR_UNSUPPORTED_F;
            break;
        case HDR_ALLOW_T:
            if (msg->allow==0) msg->allow = hf;
            msg->parsed_flag|=HDR_ALLOW_F;
            break;
        case HDR_EVENT_T:
            if (msg->event==0) msg->event = hf;
            msg->parsed_flag|=HDR_EVENT_F;
            break;
        case HDR_ACCEPT_T:
            if (msg->accept==0) msg->accept = hf;
            msg->parsed_flag|=HDR_ACCEPT_F;
            break;
        case HDR_ACCEPTLANGUAGE_T:
            if (msg->accept_language==0) msg->accept_language = hf;
            msg->parsed_flag|=HDR_ACCEPTLANGUAGE_F;
            break;
        case HDR_ORGANIZATION_T:
            if (msg->organization==0) msg->organization = hf;
            msg->parsed_flag|=HDR_ORGANIZATION_F;
            break;
        case HDR_PRIORITY_T:
            if (msg->priority==0) msg->priority = hf;
            msg->parsed_flag|=HDR_PRIORITY_F;
            break;
        case HDR_SUBJECT_T:
            if (msg->subject==0) msg->subject = hf;
            msg->parsed_flag|=HDR_SUBJECT_F;
            break;
        case HDR_USERAGENT_T:
            if (msg->user_agent==0) msg->user_agent = hf;
            msg->parsed_flag|=HDR_USERAGENT_F;
            break;
        case HDR_SERVER_T:
            if (msg->server==0) msg->server = hf;
            msg->parsed_flag|=HDR_SERVER_F;
            break;
        case HDR_CONTENTDISPOSITION_T:
            if (msg->content_disposition==0) msg->content_disposition = hf;
            msg->parsed_flag|=HDR_CONTENTDISPOSITION_F;
            break;
        case HDR_DIVERSION_T:
            if (msg->diversion==0) msg->diversion = hf;
            msg->parsed_flag|=HDR_DIVERSION_F;
            break;
        case HDR_RPID_T:
            if (msg->rpid==0) msg->rpid = hf;
            msg->parsed_flag|=HDR_RPID_F;
            break;
        case HDR_REFER_TO_T:
            if (msg->refer_to==0) msg->refer_to = hf;
            msg->parsed_flag|=HDR_REFER_TO_F;
            break;
        case HDR_SESSIONEXPIRES_T:
            if (msg->session_expires==0) msg->session_expires = hf;
            msg->parsed_flag|=HDR_SESSIONEXPIRES_F;
            break;
        case HDR_MIN_SE_T:
            if (msg->min_se==0) msg->min_se = hf;
            msg->parsed_flag|=HDR_MIN_SE_F;
            break;
        case HDR_SUBSCRIPTION_STATE_T:
            if (msg->subscription_state==0) msg->subscription_state = hf;
            msg->parsed_flag|=HDR_SUBSCRIPTION_STATE_F;
            break;
        case HDR_VIA_T:
            msg->parsed_flag|=HDR_VIA_F;
            DBG("parse_headers: Via found, flags=%llx\n",
                (unsigned long long)flags);
            if (msg->via1==0) {
                DBG("parse_headers: this is the first via\n");
                msg->h_via1=hf;
                msg->via1=hf->parsed;
                if (msg->via1->next) {
                    msg->via2=msg->via1->next;
                    msg->parsed_flag|=HDR_VIA2_F;
                }
            } else if (msg->via2==0) {
                msg->h_via2=hf;
                msg->via2=hf->parsed;
                msg->parsed_flag|=HDR_VIA2_F;
                DBG("parse_headers: this is the second via\n");
            }
            break;
        case HDR_DATE_T:
            if (msg->date==0) msg->date=hf;
            msg->parsed_flag|=HDR_DATE_F;
            break;
        case HDR_IDENTITY_T:
            if (msg->identity==0) msg->identity=hf;
            msg->parsed_flag|=HDR_IDENTITY_F;
            break;
        case HDR_IDENTITY_INFO_T:
            if (msg->identity_info==0) msg->identity_info=hf;
            msg->parsed_flag|=HDR_IDENTITY_INFO_F;
            break;
        case HDR_PATH_T:
            if (msg->path==0) msg->path=hf;
            msg->parsed_flag|=HDR_PATH_F;
            break;
        case HDR_PRIVACY_T:
            if (msg->privacy==0) msg->privacy=hf;
            msg->parsed_flag|=HDR_PRIVACY_F;
            break;
        case HDR_PAI_T:
            if (msg->pai==0) msg->pai=hf;
            msg->parsed_flag|=HDR_PAI_F;
            break;
        case HDR_PPI_T:
            if (msg->ppi==0) msg->ppi=hf;
            msg->parsed_flag|=HDR_PPI_F;
            break;
        case HDR_REASON_T:
            msg->parsed_flag|=HDR_REASON_F;
            break;
        default:
            LOG(L_CRIT, "BUG: parse_headers: unknown header type %d\n",
                hf->type);
            goto error;
        }
        /* add the header to the list*/
        if (msg->last_header==0) {
            msg->headers=hf;
            msg->last_header=hf;
        } else {
            msg->last_header->next=hf;
            msg->last_header=hf;
        }
#ifdef EXTRA_DEBUG
        DBG("header field type %d, name=<%.*s>, body=<%.*s>\n",
            hf->type,
            hf->name.len, ZSW(hf->name.s),
            hf->body.len, ZSW(hf->body.s));
#endif
        tmp=rest;
    }
skip:
    msg->unparsed=tmp;
    /* restore original flags */
    msg->parsed_flag |= orig_flag;
    return 0;

error:
    ser_error=E_BAD_REQ;
    if (hf) pkg_free(hf);
    /* restore original flags */
    msg->parsed_flag |= orig_flag;
    return -1;
}
Exemple #3
0
/**
 * Find credentials with given realm in a SIP message header.
 * @param _m - the SIP message to look into
 * @param _realm - the realm to match in the authorization header
 * @param _hftype - the header type (HDR_AUTHORIZATION_T,HDR_PROXYAUTH_T)
 * @param _h - header pointer to fill with the match
 * @returns 0 on success, 1 if not found
 * \note This function is taken from the auth module
 */
inline int find_credentials(struct sip_msg* _m, str* _realm,
									hdr_types_t _hftype, struct hdr_field** _h)
{
	struct hdr_field** hook, *ptr, *prev;
	hdr_flags_t hdr_flags;
	int res;
	str* r;

	     /*
	      * Determine if we should use WWW-Authorization or
	      * Proxy-Authorization header fields, this parameter
	      * is set in www_authorize and proxy_authorize
	      */
	switch(_hftype) {
	case HDR_AUTHORIZATION_T: 
							hook = &(_m->authorization);
							hdr_flags=HDR_AUTHORIZATION_F;
							break;
	case HDR_PROXYAUTH_T:
							hook = &(_m->proxy_auth);
							hdr_flags=HDR_PROXYAUTH_F;
							break;
	default:				
							hook = &(_m->authorization);
							hdr_flags=HDR_T2F(_hftype);
							break;
	}

	     /*
	      * If the credentials haven't been parsed yet, do it now
	      */
	if (*hook == 0) {
		     /* No credentials parsed yet */
		if (parse_headers(_m, hdr_flags, 0) == -1) {
			LOG(L_ERR, "find_credentials(): Error while parsing headers\n");
			return -1;
		}
	}

	ptr = *hook;

	     /*
	      * Iterate through the credentials in the message and
	      * find credentials with given realm
	      */
	while(ptr) {
		res = parse_credentials(ptr);
		ptr->type = HDR_AUTHORIZATION_T;
		if (res < 0) {
			LOG(L_ERR, "find_credentials(): Error while parsing credentials\n");
			return (res == -1) ? -2 : -3;
		} else if (res == 0) {
			if (_realm->len) {
				r = &(((auth_body_t*)(ptr->parsed))->digest.realm);
	
				if (r->len == _realm->len) {
					if (!strncasecmp(_realm->s, r->s, r->len)) {
						*_h = ptr;
						return 0;
					}
				}
			}
			else {
				*_h = ptr;
				return 0;
			}
			
		}

		prev = ptr;
		if (parse_headers(_m, hdr_flags, 1) == -1) {
			LOG(L_ERR, "find_credentials(): Error while parsing headers\n");
			return -4;
		} else {
			if (prev != _m->last_header) {
				if (_m->last_header->type == _hftype) ptr = _m->last_header;
				else break;
			} else break;
		}
	}
	
	     /*
	      * Credentials with given realm not found
	      */
	return 1;
}
Exemple #4
0
/**
 * Find credentials with given realm in a SIP message header
 * without parsing the credentials - just find the right 
 * authorize with stupid byte by byte comparison
 * Find credentials with given realm in a SIP message header.
 * @param _m - the SIP message to look into
 * @param realm - the realm to match in the authorization header
 * @param _hftype - the header type (HDR_AUTHORIZATION_T,HDR_PROXYAUTH_T)
 * @param _h - header pointer to fill with the match
 * @returns 0 on success, 1 if not found
 * \note This function is taken from the auth module
 */
inline int find_credentials_noparse(struct sip_msg* _m, str* realm,
									hdr_types_t _hftype, struct hdr_field** _h)
{
	struct hdr_field** hook, *ptr, *prev;
	hdr_flags_t hdr_flags;
	int i,k;

	     /*
	      * Determine if we should use WWW-Authorization or
	      * Proxy-Authorization header fields, this parameter
	      * is set in www_authorize and proxy_authorize
	      */
	switch(_hftype) {
	case HDR_AUTHORIZATION_T: 
							hook = &(_m->authorization);
							hdr_flags=HDR_AUTHORIZATION_F;
							break;
	case HDR_PROXYAUTH_T:
							hook = &(_m->proxy_auth);
							hdr_flags=HDR_PROXYAUTH_F;
							break;
	default:				
							hook = &(_m->authorization);
							hdr_flags=HDR_T2F(_hftype);
							break;
	}

	     /*
	      * If the credentials haven't been parsed yet, do it now
	      */
	if (*hook == 0) {
		     /* No credentials parsed yet */
		if (parse_headers(_m, hdr_flags, 0) == -1) {
			LOG(L_ERR, "find_credentials(): Error while parsing headers\n");
			return -1;
		}
	}

	ptr = *hook;

	     /*
	      * Iterate through the credentials in the message and
	      * find credentials with given realm
	      */
	while(ptr) {
		k = ptr->body.len - realm_par.len - realm->len;
		for(i=0;i<k;i++)
		 if (strncasecmp(ptr->body.s+i,realm_par.s,realm_par.len)==0){
		 	if (strncasecmp(ptr->body.s+i+realm_par.len,realm->s,realm->len)==0){
				*_h = ptr;
				return 0;		
		 	} 
		 	else 
		 		break; 		
		 }
		 	
		
		prev = ptr;
		if (parse_headers(_m, hdr_flags, 1) == -1) {
			LOG(L_ERR, "find_credentials(): Error while parsing headers\n");
			return -4;
		} else {
			if (prev != _m->last_header) {
				if (_m->last_header->type == _hftype) ptr = _m->last_header;
				else break;
			} else break;
		}
	}
	
	     /*
	      * Credentials with given realm not found
	      */
	return 1;
}
Exemple #5
0
/*
 * Find credentials with given realm in a SIP message header
 */
int find_credentials(struct sip_msg* msg, str* realm,
		hdr_types_t hftype, struct hdr_field** hdr)
{
	struct hdr_field** hook, *ptr;
	hdr_flags_t hdr_flags;
	int res;
	str* r;

	/*
	 * Determine if we should use WWW-Authorization or
	 * Proxy-Authorization header fields, this parameter
	 * is set in www_authorize and proxy_authorize
	 */
	switch(hftype) {
	case HDR_AUTHORIZATION_T:
		hook = &(msg->authorization);
		hdr_flags=HDR_AUTHORIZATION_F;
		break;
	case HDR_PROXYAUTH_T:
		hook = &(msg->proxy_auth);
		hdr_flags=HDR_PROXYAUTH_F;
		break;
	default:
		hook = &(msg->authorization);
		hdr_flags=HDR_T2F(hftype);
		break;
	}

	/*
	 * If the credentials haven't been parsed yet, do it now
	 */
	if (*hook == 0) {
		/* No credentials parsed yet */
		if (parse_headers(msg, hdr_flags, 0) == -1) {
			LM_ERR("error while parsing headers\n");
			return -1;
		}
	}

	ptr = *hook;

	/*
	 * Iterate through the credentials in the message and
	 * find credentials with given realm
	 */
	while(ptr) {
		res = parse_credentials(ptr);
		if (res < 0) {
			LM_ERR("error while parsing credentials\n");
			return (res == -1) ? -2 : -3;
		} else if (res == 0) {
			r = &(((auth_body_t*)(ptr->parsed))->digest.realm);

			if (r->len == realm->len) {
				if (!strncasecmp(realm->s, r->s, r->len)) {
					*hdr = ptr;
					return 0;
				}
			}
		}

		if (parse_headers(msg, hdr_flags, 1) == -1) {
			LM_ERR("error while parsing headers\n");
			return -4;
		} else {
			ptr = next_sibling_hdr(ptr);
			if (!ptr)
				break;
		}
	}

	/*
	 * Credentials with given realm not found
	 */
	return 1;
}
Exemple #6
0
/* Find credentials with given realm in a SIP message header */
int find_credentials(struct sip_msg* _m, str* _realm, int _hftype,
													struct hdr_field** _h)
{
	struct hdr_field** hook, *ptr, *prev;
	int res;
	hdr_flags_t hdr_flags;
	str* r;

	switch(_hftype)
	{
		case HDR_AUTHORIZATION_T:
			hook = &(_m->authorization);
			hdr_flags=HDR_AUTHORIZATION_F;
			break;
		case HDR_PROXYAUTH_T:
			hook = &(_m->proxy_auth);
			hdr_flags=HDR_PROXYAUTH_F;
			break;
		default:
			hook = &(_m->authorization);
			hdr_flags=HDR_T2F(_hftype);
			break;
	}

	/* If the credentials haven't been parsed yet, do it now */
	if (*hook == 0)
		if (parse_headers(_m, hdr_flags, 0) == -1)
		{
			LM_ERR("failed to parse headers\n");
			return -1;
		}

	ptr = *hook;

	/* Iterate through the credentials of the message to find
		credentials with given realm
	*/
	while(ptr)
	{
		res = parse_credentials(ptr);
		if (res < 0)
		{
			LM_ERR("failed to parse credentials\n");
			return (res == -1) ? -2 : -3;
		}
		else
			if (res == 0)
			{
				r = &(((auth_body_t*)(ptr->parsed))->digest.realm);

				if (r->len == _realm->len)
				{
					if (!strncasecmp(_realm->s, r->s, r->len))
					{
						*_h = ptr;
						return 0;
					}
				}
			}

			prev = ptr;
			if (parse_headers(_m, hdr_flags, 1) == -1)
			{
				LM_ERR("failed to parse headers\n");
				return -4;
			}
			else
			{
				if (prev != _m->last_header)
				{
					if (_m->last_header->type == _hftype) ptr = _m->last_header;
					else break;
				}
				else break;
			}
	}

     /* Credentials with given realm not found */
	return 1;
}
Exemple #7
0
/**
 * Strips the "<strip_top_vias>" topmost via headers.
 * Leaves only the topmost "<allow_top_routes>" Record-Route headers.
 *
 */
int extract_allowed_headers(struct sip_msg *my_msg,int strip_top_vias,int allow_top_Rroutes,hdr_flags_t forbidden_hdrs,char *headers,int headers_len)
{
   struct hdr_field *hf;
   rr_t *rb;
   struct via_body *vb;
   int len,k,rtcnt,i;

   len=0;
   rtcnt=allow_top_Rroutes;
   rb=NULL;
   vb=NULL;

   for(hf=my_msg->headers;hf;hf=hf->next){
      if(forbidden_hdrs & HDR_T2F(hf->type)){
	 LM_DBG("Skipping header (%.*s)\n",hf->name.len,hf->name.s);
	 continue;
      }else if(hf->type==HDR_VIA_T && strip_top_vias > 0){
	 /** All vias MUST be parsed !!*/
	 for(i=0,vb=hf->parsed;vb;vb=vb->next,i++);
	 if(i<=strip_top_vias){
	    LM_DBG("Stripping vias [%.*s]\n",hf->len,hf->name.s);
	    /** skip this via header*/
	    strip_top_vias-=i;
	 }else{
	    assert(i>1);
	    vb=hf->parsed;
	    while(strip_top_vias--)
	       vb=vb->next;
	    k= (hf->name.s + hf->len) - vb->name.s;
	    LM_DBG("Stripping vias [%.*s]\n",(int)(vb->name.s-hf->name.s),
		  hf->name.s);
	    if(k+VIA_LEN<headers_len){
	       memcpy(headers+len,VIA,VIA_LEN);
	       len+=VIA_LEN;
	       memcpy(headers+len,vb->name.s,k);
	       len+=k;
	    }else{
	       LM_ERR("Out Of Space !!\n");
	       goto error;
	    }
	 }
      }else if(hf->type==HDR_RECORDROUTE_T && rtcnt>=0){
	 if(rtcnt==0)
	    continue;
	 if(!hf->parsed && 0>parse_rr(hf)){
	    LM_ERR("parsing Record-Route:\"%.*s\"\n",hf->body.len,hf->body.s);
	    goto error;
	 }
	 for(i=0,rb=hf->parsed;rb;rb=rb->next,i++);
	 if(i<=rtcnt){
	    if((len+hf->len)<headers_len){
	       LM_DBG("Allowing RecordRoute [%.*s]\n",hf->len,hf->name.s);
	       memcpy(headers+len,hf->name.s,hf->len);
	       len+=hf->len;
	    }else{
	       LM_ERR("Unable to keep recordroute (not enough space left in headers) Discarding \"%.*s\" \n",hf->name.len,hf->name.s);
	       goto error;
	    }
	    /** is this dangerous ? because the rtcnt is the control variable for this conditional 'if'
	     * so if I change rtcnt value in one of the statements... what then ??? */
	    rtcnt-=i;
	 }else{
	    assert(rtcnt>0);
	    rb=hf->parsed;
	    while(--rtcnt)
	       rb=rb->next;
	    k= (((rb->nameaddr.name.s) + rb->len)-hf->name.s) ;
	    if(len+k+CRLF_LEN<headers_len){
	       memcpy(headers+len,hf->name.s,k);
	       LM_DBG("Allowing RecordRoute [%.*s\r\n]\n",k,hf->name.s);
	       len+=k;
	       memcpy(headers+len,CRLF,CRLF_LEN);
	       len+=CRLF_LEN;
	    }else{
	       LM_ERR("Out Of Space !!\n");
	       goto error;
	    }
	 }
	 if(hf->parsed){
	    free_rr((rr_t **)(void*)(&hf->parsed));
	    hf->parsed=NULL;
	 }
      }else{
	 if((len+hf->len)<headers_len){
	    memcpy(headers+len,hf->name.s,hf->len);
	    len+=hf->len;
	 }else{
	    LM_WARN("Too many headers. Discarding \"%.*s\" \n",
				hf->name.len,hf->name.s);
	 }
      }
   }/*for*/
   return len;
error:
   return -1;
}