Example #1
0
/*
 * 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;
}
Example #2
0
File: cpl.c Project: NormB/opensips
static int cpl_process_register(struct sip_msg* msg, int no_rpl)
{
	struct disposition *disp;
	struct disposition_param *param;
	int  ret;
	int  mime;
	int  *mimes;

	/* make sure that is a REGISTER ??? */

	/* here should be the CONTACT- hack */

	/* is there a CONTENT-TYPE hdr ? */
	mime = parse_content_type_hdr( msg );
	if (mime==-1)
		goto error;

	/* check the mime type */
	LM_DBG("Content-Type mime found %u, %u\n",
		mime>>16,mime&0x00ff);
	if ( mime && mime==(TYPE_APPLICATION<<16)+SUBTYPE_CPLXML ) {
		/* can be an upload or remove -> check for the content-purpose and
		 * content-action headers */
		LM_DBG("carrying CPL -> look at Content-Disposition\n");
		if (parse_content_disposition( msg )!=0) {
			LM_ERR("Content-Disposition missing or corrupted\n");
			goto error;
		}
		disp = get_content_disposition(msg);
		print_disposition( disp ); /* just for DEBUG */
		/* check if the type of disposition is SCRIPT */
		if (disp->type.len!=CPL_SCRIPT_LEN ||
		strncasecmp(disp->type.s,CPL_SCRIPT,CPL_SCRIPT_LEN) ) {
			LM_ERR("bogus message - Content-Type"
				"says CPL_SCRIPT, but Content-Disposition something else\n");
			goto error;
		}
		/* disposition type is OK -> look for action parameter */
		for(param=disp->params;param;param=param->next) {
			if (param->name.len==ACTION_PARAM_LEN &&
			!strncasecmp(param->name.s,ACTION_PARAM,ACTION_PARAM_LEN))
				break;
		}
		if (param==0) {
			LM_ERR("bogus message - "
				"Content-Disposition has no action param\n");
			goto error;
		}
		/* action param found -> check its value: store or remove */
		if (param->body.len==STORE_ACTION_LEN &&
		!strncasecmp( param->body.s, STORE_ACTION, STORE_ACTION_LEN)) {
			/* it's a store action -> get the script from body message and store
			 * it into database (CPL and BINARY format) */
			if (do_script_action( msg, STORE_SCRIPT)==-1)
				goto error;
		} else
		if (param->body.len==REMOVE_ACTION_LEN &&
		!strncasecmp( param->body.s, REMOVE_ACTION, REMOVE_ACTION_LEN)) {
			/* it's a remove action -> remove the script from database */
			if (do_script_action( msg, REMOVE_SCRIPT)==-1)
				goto error;
		} else {
			LM_ERR("unknown action <%.*s>\n",
				param->body.len,param->body.s);
			goto error;
		}

		/* do I have to send to reply? */
		if (no_rpl)
			goto resume_script;

		/* send a 200 OK reply back */
		cpl_fct.sigb.reply( msg, 200, &cpl_ok_rpl,NULL);
		/* I send the reply and I don't want to return to script execution, so
		 * I return 0 to do break */
		goto stop_script;
	}

	/* is there an ACCEPT hdr ? */
	if ( (ret=parse_accept_hdr(msg))<0)
		goto error;
	if (ret==0 || (mimes=get_accept(msg))==0 )
		/* accept header not present or no mimes found */
		goto resume_script;

	/* looks if the REGISTER accepts cpl-xml or * */
	while (*mimes) {
		LM_DBG("accept mime found %u, %u\n",
			(*mimes)>>16,(*mimes)&0x00ff);
		if (*mimes==(TYPE_ALL<<16)+SUBTYPE_ALL ||
		*mimes==(TYPE_APPLICATION<<16)+SUBTYPE_CPLXML )
			break;
		mimes++;
	}
	if (*mimes==0)
		/* no accept mime that matched cpl */
		goto resume_script;

	/* get the user name from msg, retrieve the script from db
	 * and appended to reply */
	if (do_script_download( msg )==-1)
		goto error;

	/* do I have to send to reply? */
	if (no_rpl)
		goto resume_script;

	/* send a 200 OK reply back */
	cpl_fct.sigb.reply( msg, 200, &cpl_ok_rpl,NULL);

stop_script:
	return 0;
resume_script:
	return 1;
error:
	/* send a error reply back */
	cpl_fct.sigb.reply( msg, cpl_err->err_code, &cpl_err->err_msg, NULL);
	/* I don't want to return to script execution, so I return 0 to do break */
	return 0;
}