int
osip_content_length_clone (const osip_content_length_t * ctl, osip_content_length_t ** dest)
{
  int i;
  osip_content_length_t *cl;

  *dest = NULL;
  if (ctl == NULL)
    return OSIP_BADPARAMETER;
  /*
     empty headers are allowed:
     if (ctl->value==NULL) return -1;
   */
  i = osip_content_length_init (&cl);
  if (i != 0)                   /* allocation failed */
    return i;
  if (ctl->value != NULL) {
    cl->value = osip_strdup (ctl->value);
    if (cl->value == NULL) {
      osip_content_length_free (cl);
      return OSIP_NOMEM;
    }
  }

  *dest = cl;
  return OSIP_SUCCESS;
}
Example #2
0
void
osip_message_free (osip_message_t * sip)
{
  if (sip == NULL)
    return;

  osip_free (sip->sip_method);
  osip_free (sip->sip_version);
  if (sip->req_uri != NULL)
    osip_uri_free (sip->req_uri);
  osip_free (sip->reason_phrase);

#ifndef MINISIZE
  osip_list_special_free (&sip->accepts, (void (*)(void *)) &osip_accept_free);
#endif
  osip_list_special_free (&sip->authorizations, (void (*)(void *)) &osip_authorization_free);
  if (sip->call_id != NULL)
    osip_call_id_free (sip->call_id);
#ifndef MINISIZE
  osip_list_special_free (&sip->accept_encodings, (void (*)(void *)) &osip_accept_encoding_free);
  osip_list_special_free (&sip->accept_languages, (void (*)(void *)) &osip_accept_language_free);
  osip_list_special_free (&sip->alert_infos, (void (*)(void *)) &osip_alert_info_free);
  osip_list_special_free (&sip->allows, (void (*)(void *)) &osip_allow_free);
  osip_list_special_free (&sip->authentication_infos, (void (*)(void *)) &osip_authentication_info_free);
  osip_list_special_free (&sip->content_encodings, (void (*)(void *)) &osip_content_encoding_free);
  osip_list_special_free (&sip->error_infos, (void (*)(void *)) &osip_error_info_free);
  osip_list_special_free (&sip->proxy_authentication_infos, (void (*)(void *))
                          &osip_proxy_authentication_info_free);
#endif
  osip_list_special_free (&sip->call_infos, (void (*)(void *)) &osip_call_info_free);
  osip_list_special_free (&sip->contacts, (void (*)(void *)) &osip_contact_free);
  if (sip->content_length != NULL)
    osip_content_length_free (sip->content_length);
  if (sip->content_type != NULL)
    osip_content_type_free (sip->content_type);
  if (sip->cseq != NULL)
    osip_cseq_free (sip->cseq);
  if (sip->from != NULL)
    osip_from_free (sip->from);
  if (sip->mime_version != NULL)
    osip_mime_version_free (sip->mime_version);
  osip_list_special_free (&sip->proxy_authenticates, (void (*)(void *)) &osip_proxy_authenticate_free);
  osip_list_special_free (&sip->proxy_authorizations, (void (*)(void *)) &osip_proxy_authorization_free);
  osip_list_special_free (&sip->record_routes, (void (*)(void *)) &osip_record_route_free);
  osip_list_special_free (&sip->routes, (void (*)(void *)) &osip_route_free);
  if (sip->to != NULL)
    osip_to_free (sip->to);
  osip_list_special_free (&sip->vias, (void (*)(void *)) &osip_via_free);
  osip_list_special_free (&sip->www_authenticates, (void (*)(void *)) &osip_www_authenticate_free);
  osip_list_special_free (&sip->headers, (void (*)(void *)) &osip_header_free);
  osip_list_special_free (&sip->bodies, (void (*)(void *)) &osip_body_free);
  osip_free (sip->message);
  osip_free (sip);
}
/* returns -1 on error. */
int
osip_message_set_content_length (osip_message_t * sip, const char *hvalue)
{
  int i;

  if (hvalue == NULL || hvalue[0] == '\0')
    return OSIP_SUCCESS;

  if (sip->content_length != NULL)
    return OSIP_SYNTAXERROR;
  i = osip_content_length_init (&(sip->content_length));
  if (i != 0)
    return i;
  sip->message_property = 2;
  i = osip_content_length_parse (sip->content_length, hvalue);
  if (i != 0) {
    osip_content_length_free (sip->content_length);
    sip->content_length = NULL;
    return i;
  }

  return OSIP_SUCCESS;
}
Example #4
0
File: proxy.c Project: OPSF/uClinux
/*
 * PROXY_REWRITE_INVITATION_BODY
 *
 * rewrites the outgoing INVITATION request or response packet
 * 
 * RETURNS
 *	STS_SUCCESS on success
 *	STS_FAILURE on error
 */
int proxy_rewrite_invitation_body(osip_message_t *mymsg, int direction){
   osip_body_t *body;
   sdp_message_t  *sdp;
   struct in_addr map_addr, addr_sess, addr_media, outside_addr, inside_addr;
   int sts;
   char *bodybuff;
   int bodybuflen;
   char clen[8]; /* content length: probably never more than 7 digits !*/
   int map_port, msg_port;
   int media_stream_no;
   sdp_connection_t *sdp_conn;
   sdp_media_t *sdp_med;
   int rtp_direction=0;
   int have_c_media=0;

   if (configuration.rtp_proxy_enable == 0) return STS_SUCCESS;

   /*
    * get SDP structure
    */
   sts = osip_message_get_body(mymsg, 0, &body);
   if (sts != 0) {
#if 0
      if ((MSG_IS_RESPONSE_FOR(mymsg,"INVITE")) &&
          (MSG_IS_STATUS_1XX(mymsg))) {
         /* 1xx responses *MAY* contain SDP data */
         DEBUGC(DBCLASS_PROXY, "rewrite_invitation_body: "
                "no body found in message");
         return STS_SUCCESS;
      } else {
         /* INVITE request and 200 response *MUST* contain SDP data */
         ERROR("rewrite_invitation_body: no body found in message");
         return STS_FAILURE;
      }
#else
      DEBUGC(DBCLASS_PROXY, "rewrite_invitation_body: "
                            "no body found in message");
      return STS_SUCCESS;
#endif
   }

   sts = sip_body_to_str(body, &bodybuff, &bodybuflen);
   if (sts != 0) {
      ERROR("rewrite_invitation_body: unable to sip_body_to_str");
   }
   sts = sdp_message_init(&sdp);
   sts = sdp_message_parse (sdp, bodybuff);
   if (sts != 0) {
      ERROR("rewrite_invitation_body: unable to sdp_message_parse body");
      DUMP_BUFFER(-1, bodybuff, bodybuflen);
      osip_free(bodybuff);
      sdp_message_free(sdp);
      return STS_FAILURE;
   }
   osip_free(bodybuff);


if (configuration.debuglevel)
{ /* just dump the buffer */
   char *tmp, *tmp2;
   int tmplen;
   sts = osip_message_get_body(mymsg, 0, &body);
   sts = sip_body_to_str(body, &tmp, &tmplen);
   osip_content_length_to_str(mymsg->content_length, &tmp2);
   DEBUG("Body before rewrite (clen=%s, strlen=%i):\n%s\n----",
         tmp2, tmplen, tmp);
   osip_free(tmp);
   osip_free(tmp2);
}

   /*
    * RTP proxy: get ready and start forwarding
    * start forwarding for each media stream ('m=' item in SIP message)
    */

   /* get outbound address */
   if (get_interface_ip(IF_OUTBOUND, &outside_addr) != STS_SUCCESS) {
      sdp_message_free(sdp);
      return STS_FAILURE;
   }

   /* get inbound address */
   if (get_interface_ip(IF_INBOUND, &inside_addr) != STS_SUCCESS) {
      sdp_message_free(sdp);
      return STS_FAILURE;
   }

   /* figure out what address to use for RTP masquerading */
   if (MSG_IS_REQUEST(mymsg)) {
      if (direction == DIR_INCOMING) {
         memcpy(&map_addr, &inside_addr, sizeof (map_addr));
         rtp_direction = DIR_OUTGOING;
      } else {
         memcpy(&map_addr, &outside_addr, sizeof (map_addr));
         rtp_direction = DIR_INCOMING;
      }
   } else /* MSG_IS_REPONSE(mymsg) */ {
      if (direction == DIR_INCOMING) {
         memcpy(&map_addr, &inside_addr, sizeof (map_addr));
         rtp_direction = DIR_OUTGOING;
      } else {
         memcpy(&map_addr, &outside_addr, sizeof (map_addr));
         rtp_direction = DIR_INCOMING;
      }
   }

   DEBUGC(DBCLASS_PROXY, "proxy_rewrite_invitation_body: SIP[%s %s] RTP[%s %s]",
          MSG_IS_REQUEST(mymsg)? "RQ" : "RS",
          (direction==DIR_INCOMING)? "IN" : "OUT",
          (rtp_direction==DIR_INCOMING)? "IN" : "OUT",
          utils_inet_ntoa(map_addr));


   /*
    * first, check presence of a 'c=' item on session level
    */
   if (sdp->c_connection==NULL || sdp->c_connection->c_addr==NULL) {
      /*
       * No 'c=' on session level, search on media level now
       *
       * According to RFC2327, ALL media description must
       * include a 'c=' item now:
       */
      media_stream_no=0;
      while (!sdp_message_endof_media(sdp, media_stream_no)) {
         /* check if n'th media stream is present */
         if (sdp_message_c_addr_get(sdp, media_stream_no, 0) == NULL) {
            ERROR("SDP: have no 'c=' on session level and neither "
                  "on media level (media=%i)",media_stream_no);
            sdp_message_free(sdp);
            return STS_FAILURE;
         }
         media_stream_no++;
      } /* while */
   }

   /* Required 'c=' items ARE present */


   /*
    * rewrite 'c=' item on session level if present and not yet done.
    * remember the original address in addr_sess
    */
   memset(&addr_sess, 0, sizeof(addr_sess));
   if (sdp->c_connection && sdp->c_connection->c_addr) {
      sts = get_ip_by_host(sdp->c_connection->c_addr, &addr_sess);
      if (sts == STS_FAILURE) {
         ERROR("SDP: cannot resolve session 'c=' host [%s]",
               sdp->c_connection->c_addr);
         sdp_message_free(sdp);
         return STS_FAILURE;
      }
      /*
       * Rewrite
       * an IP address of 0.0.0.0 means *MUTE*, don't rewrite such
       */
      if (strcmp(sdp->c_connection->c_addr, "0.0.0.0") != 0) {
         osip_free(sdp->c_connection->c_addr);
         sdp->c_connection->c_addr=osip_malloc(HOSTNAME_SIZE);
         sprintf(sdp->c_connection->c_addr, "%s", utils_inet_ntoa(map_addr));
      } else {
         /* 0.0.0.0 - don't rewrite */
         DEBUGC(DBCLASS_PROXY, "proxy_rewrite_invitation_body: "
                "got a MUTE c= record (on session level - legal?)");
      }
   }


   /*
    * rewrite 'o=' item (originator) on session level if present.
    */
   if (sdp->o_addrtype && sdp->o_addr) {
      if (strcmp(sdp->o_addrtype, "IP4") != 0) {
         ERROR("got IP6 in SDP originator - not yet suported by siproxd");
         sdp_message_free(sdp);
         return STS_FAILURE;
      }

      osip_free(sdp->o_addr);
      sdp->o_addr=osip_malloc(HOSTNAME_SIZE);
      sprintf(sdp->o_addr, "%s", utils_inet_ntoa(map_addr));
   }


   /*
    * loop through all media descritions,
    * start RTP proxy and rewrite them
    */
   for (media_stream_no=0;;media_stream_no++) {
      /* check if n'th media stream is present */
      if (sdp_message_m_port_get(sdp, media_stream_no) == NULL) break;

      /*
       * check if a 'c=' item is present in this media description,
       * if so -> rewrite it
       */
      memset(&addr_media, 0, sizeof(addr_media));
      have_c_media=0;
      sdp_conn=sdp_message_connection_get(sdp, media_stream_no, 0);
      if (sdp_conn && sdp_conn->c_addr) {
         if (strcmp(sdp_conn->c_addr, "0.0.0.0") != 0) {
            sts = get_ip_by_host(sdp_conn->c_addr, &addr_media);
            have_c_media=1;
            /* have a valid address */
            osip_free(sdp_conn->c_addr);
            sdp_conn->c_addr=osip_malloc(HOSTNAME_SIZE);
            sprintf(sdp_conn->c_addr, "%s", utils_inet_ntoa(map_addr));
         } else {
            /* 0.0.0.0 - don't rewrite */
            DEBUGC(DBCLASS_PROXY, "proxy_rewrite_invitation_body: got a "
                   "MUTE c= record (media level)");
         }
      }

      /* start an RTP proxying stream */
      if (sdp_message_m_port_get(sdp, media_stream_no)) {
         msg_port=atoi(sdp_message_m_port_get(sdp, media_stream_no));

         if (msg_port > 0) {
            osip_uri_t *cont_url = NULL;
            char *client_id=NULL;
            /* try to get some additional UA specific unique ID.
             * Try:
             * 1) User part of Contact header
             * 2) Host part of Contact header (will be different
             *    between internal UA and external UA)
             */
            if (!osip_list_eol(mymsg->contacts, 0))
               cont_url = ((osip_contact_t*)(mymsg->contacts->node->element))->url;
            if (cont_url) {
               client_id=cont_url->username;
               if (client_id == NULL) client_id=cont_url->host;
            }


            /*
             * do we have a 'c=' item on media level?
             * if not, use the same as on session level
             */
            if (have_c_media == 0) {
               memcpy(&addr_media, &addr_sess, sizeof(addr_sess));
            }

            /*
             * Am I running in front of the routing device? Then I cannot
             * use the external IP to bind a listen socket to, so force
             * the use of my inbound IP for listening.
             */
            if ((rtp_direction == DIR_INCOMING) &&
                (configuration.outbound_host) &&
                (strcmp(configuration.outbound_host, "")!=0)) {
               DEBUGC(DBCLASS_PROXY, "proxy_rewrite_invitation_body: "
                      "in-front-of-NAT-Router");
               memcpy(&map_addr, &inside_addr, sizeof (map_addr));
            }

            sts = rtp_start_fwd(osip_message_get_call_id(mymsg),
                                client_id,
                                rtp_direction,
                                media_stream_no,
                                map_addr, &map_port,
                                addr_media, msg_port);

            if (sts == STS_SUCCESS) {
               /* and rewrite the port */
               sdp_med=osip_list_get(sdp->m_medias, media_stream_no);
               if (sdp_med && sdp_med->m_port) {
                  osip_free(sdp_med->m_port);
                  sdp_med->m_port=osip_malloc(8); /* 5 digits, \0 + align */
                  sprintf(sdp_med->m_port, "%i", map_port);
                  DEBUGC(DBCLASS_PROXY, "proxy_rewrite_invitation_body: "
                         "m= rewrote port to [%i]",map_port);
               } else {
                  ERROR("rewriting port in m= failed sdp_med=%p, "
                        "m_number_of_port=%p", sdp_med, sdp_med->m_port);
               }
            } /* sts == success */
         } /* if msg_port > 0 */
      } else {
         /* no port defined - skip entry */
         WARN("no port defined in m=(media) stream_no=%i", media_stream_no);
         continue;
      }
   } /* for media_stream_no */

   /* remove old body */
   sts = osip_list_remove(mymsg->bodies, 0);
   osip_body_free(body);

   /* dump new body */
   sdp_message_to_str(sdp, &bodybuff);
   bodybuflen=strlen(bodybuff);

   /* free sdp structure */
   sdp_message_free(sdp);

   /* include new body */
   sip_message_set_body(mymsg, bodybuff, bodybuflen);
   if (sts != 0) {
      ERROR("rewrite_invitation_body: unable to sip_message_set_body body");
   }

   /* free content length resource and include new one*/
   osip_content_length_free(mymsg->content_length);
   mymsg->content_length=NULL;
   sprintf(clen,"%i",bodybuflen);
   sts = osip_message_set_content_length(mymsg, clen);

   /* free old body */
   osip_free(bodybuff);

if (configuration.debuglevel)
{ /* just dump the buffer */
   char *tmp, *tmp2;
   int tmplen;
   sts = osip_message_get_body(mymsg, 0, &body);
   sts = sip_body_to_str(body, &tmp, &tmplen);
   osip_content_length_to_str(mymsg->content_length, &tmp2);
   DEBUG("Body after rewrite (clen=%s, strlen=%i):\n%s\n----",
         tmp2, tmplen, tmp);
   osip_free(tmp);
   osip_free(tmp2);
}
   return STS_SUCCESS;
}
Example #5
0
/* osip_message_t *sip is filled while analysing buf */
static int
_osip_message_parse (osip_message_t * sip, const char *buf, size_t length, int sipfrag)
{
  int i;
  const char *next_header_index;
  char *tmp;
  char *beg;

  tmp = osip_malloc (length + 2);
  if (tmp == NULL) {
    OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "Could not allocate memory.\n"));
    return OSIP_NOMEM;
  }
  beg = tmp;
  memcpy (tmp, buf, length);    /* may contain binary data */
  tmp[length] = '\0';
  /* skip initial \r\n */
  while (tmp[0] == '\r' || tmp[0] == '\n')
    tmp++;
  osip_util_replace_all_lws (tmp);
  /* parse request or status line */
  i = __osip_message_startline_parse (sip, tmp, &next_header_index);
  if (i != 0 && !sipfrag) {
    OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "Could not parse start line of message.\n"));
    osip_free (beg);
    return i;
  }
  tmp = (char *) next_header_index;

  /* parse headers */
  i = msg_headers_parse (sip, tmp, &next_header_index);
  if (i != 0) {
    OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "error in msg_headers_parse()\n"));
    osip_free (beg);
    return i;
  }
  tmp = (char *) next_header_index;

  if (sip->content_length != NULL && sip->content_length->value == NULL) {
    /* empty content_length header */
    osip_content_length_free(sip->content_length);
    sip->content_length=NULL;
  }

  if (sip->content_length != NULL && sip->content_length->value != NULL && atoi(sip->content_length->value) >0) {
    /* body exist */
  } else if (sip->content_length == NULL && '\r' == next_header_index[0] && '\n' == next_header_index[1] && length - (tmp - beg) - (2) >0) {
    /* body exist */
  } else if (sip->content_length == NULL && '\n' == next_header_index[0] && length - (tmp - beg) - (1) >0) {
    /* body exist */
  } else {
    if (sip->content_length == NULL)
      osip_message_set_content_length (sip, "0");
    osip_free (beg);
    return OSIP_SUCCESS;        /* no body found */
  }

  i = msg_osip_body_parse (sip, tmp, &next_header_index, length - (tmp - beg));
  osip_free (beg);
  if (i != 0) {
    OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "error in msg_osip_body_parse()\n"));
    return i;
  }

  /* this is mandatory in the oSIP stack */
  if (sip->content_length == NULL)
    osip_message_set_content_length (sip, "0");

  return OSIP_SUCCESS;
}
/*
 * Processing.
 * 
 */
int  PLUGIN_PROCESS(int stage, sip_ticket_t *ticket){
   /* stage contains the PLUGIN_* value - the stage of SIP processing. */
   int sts;
   char *buff;
   size_t buflen;
   osip_body_t *body;
   sdp_message_t  *sdp;
   int content_length;
   osip_content_type_t *content_type;
   char clen[8]; /* content length: probably never more than 7 digits !*/

   //
   // check that we have the expected payload "application/sdp"
   //

   // get content length
   content_length=0;
   if (ticket->sipmsg && ticket->sipmsg->content_length 
       && ticket->sipmsg->content_length->value) {
      sts=sscanf(ticket->sipmsg->content_length->value, "%i", &content_length);
   }

   // check if we have a content type defined and that payload length >0
   content_type=osip_message_get_content_type(ticket->sipmsg);
   if ((content_length == 0) || (content_type == NULL) 
       || (content_type->type == NULL) || (content_type->subtype == NULL)) {
      DEBUGC(DBCLASS_PLUGIN, "%s: no content", name);
      return STS_SUCCESS;
   }

   // check content type: must be "application/sdp"
   if ((strncmp(content_type->type, "application", sizeof("application")) != 0)
       || (strncmp(content_type->subtype, "sdp", sizeof("sdp")) != 0)) {
      DEBUGC(DBCLASS_PLUGIN, "%s: unsupported content-type %s/%s", name,
             content_type->type, content_type->subtype);
      return STS_SUCCESS;
   }

   DEBUGC(DBCLASS_PLUGIN, "%s: content-type %s/%s, size=%i", name, 
          content_type->type, content_type->subtype, content_length);

   //
   // parse the payload
   //

   // get a pointer to the payload of the SIP packet
   sts = osip_message_get_body(ticket->sipmsg, 0, &body);
   if (sts != 0) {
      DEBUGC(DBCLASS_PLUGIN, "%s: no body found in message", name);
      return STS_SUCCESS;
   }
   // dump it into a buffer
   sts = sip_body_to_str(body, &buff, &buflen);
   if (sts != 0) {
      WARN("%s: unable to sip_body_to_str", name);
      return STS_SUCCESS;
   }
   // and parse it into an SDP structure
   sts = sdp_message_init(&sdp);
   sts = sdp_message_parse (sdp, buff);
   if (sts != 0) {
      WARN("%s: unable to sdp_message_parse() body", name);
      DUMP_BUFFER(-1, buff, buflen);
      osip_free(buff);
      buff=NULL;
      sdp_message_free(sdp);
      return STS_SUCCESS;
   }
   osip_free(buff);
   buff=NULL;

   //
   // now do the codec filtering magic...
   sdp_filter_codec(sdp);

   //
   // replace the original payload with the new modified payload
   //
   
   // remove old body from SIP packet
   sts = osip_list_remove(&(ticket->sipmsg->bodies), 0);
   osip_body_free(body);
   body=NULL;

   // dump new body to buffer
   sdp_message_to_str(sdp, &buff);
   buflen=strlen(buff);

   // free sdp structure (no longer needed)
   sdp_message_free(sdp);
   sdp=NULL;

   // put new body into SIP message
   sts=sip_message_set_body(ticket->sipmsg, buff, buflen);
   if (sts != 0) {
      ERROR("%s: unable to sip_message_set_body body", name);
      DUMP_BUFFER(-1, buff, buflen);
      buflen=0;
   }
   // free buffer
   osip_free(buff);
   buff=NULL;

   //
   // set new content length
   //

   // remove old content leght field
   osip_content_length_free(ticket->sipmsg->content_length);
   ticket->sipmsg->content_length=NULL;

   // set new content length
   sprintf(clen,"%ld",(long)buflen);
   sts = osip_message_set_content_length(ticket->sipmsg, clen);

   return STS_SUCCESS;
}
Example #7
0
void
osip_message_free (osip_message_t * sip)
{
    int pos = 0;

    if (sip == NULL)
        return;

    osip_free (sip->sip_method);
    osip_free (sip->sip_version);
    if (sip->req_uri != NULL)
    {
        osip_uri_free (sip->req_uri);
    }
    osip_free (sip->reason_phrase);

    {
        osip_accept_t *accept;

        while (!osip_list_eol (&sip->accepts, pos))
        {
            accept = (osip_accept_t *) osip_list_get (&sip->accepts, pos);
            osip_list_remove (&sip->accepts, pos);
            osip_accept_free (accept);
        }
    }
    {
        osip_accept_encoding_t *accept_encoding;

        while (!osip_list_eol (&sip->accept_encodings, pos))
        {
            accept_encoding =
                (osip_accept_encoding_t *) osip_list_get (&sip->accept_encodings, pos);
            osip_list_remove (&sip->accept_encodings, pos);
            osip_accept_encoding_free (accept_encoding);
        }
    }
    {
        osip_accept_language_t *accept_language;

        while (!osip_list_eol (&sip->accept_languages, pos))
        {
            accept_language =
                (osip_accept_language_t *) osip_list_get (&sip->accept_languages, pos);
            osip_list_remove (&sip->accept_languages, pos);
            osip_accept_language_free (accept_language);
        }
    }
    {
        osip_alert_info_t *alert_info;

        while (!osip_list_eol (&sip->alert_infos, pos))
        {
            alert_info = (osip_alert_info_t *) osip_list_get (&sip->alert_infos, pos);
            osip_list_remove (&sip->alert_infos, pos);
            osip_alert_info_free (alert_info);
        }
    }
    {
        osip_allow_t *al;

        while (!osip_list_eol (&sip->allows, pos))
        {
            al = (osip_allow_t *) osip_list_get (&sip->allows, pos);
            osip_list_remove (&sip->allows, pos);
            osip_allow_free (al);
        }
    }
    {
        osip_authentication_info_t *al;

        while (!osip_list_eol (&sip->authentication_infos, pos))
        {
            al =
                (osip_authentication_info_t *) osip_list_get (&sip->
                        authentication_infos, pos);
            osip_list_remove (&sip->authentication_infos, pos);
            osip_authentication_info_free (al);
        }
    }
    {
        osip_authorization_t *al;

        while (!osip_list_eol (&sip->authorizations, pos))
        {
            al = (osip_authorization_t *) osip_list_get (&sip->authorizations, pos);
            osip_list_remove (&sip->authorizations, pos);
            osip_authorization_free (al);
        }
    }
    if (sip->call_id != NULL)
    {
        osip_call_id_free (sip->call_id);
    }
    {
        osip_call_info_t *call_info;

        while (!osip_list_eol (&sip->call_infos, pos))
        {
            call_info = (osip_call_info_t *) osip_list_get (&sip->call_infos, pos);
            osip_list_remove (&sip->call_infos, pos);
            osip_call_info_free (call_info);
        }
    }
    {
        osip_contact_t *contact;

        while (!osip_list_eol (&sip->contacts, pos))
        {
            contact = (osip_contact_t *) osip_list_get (&sip->contacts, pos);
            osip_list_remove (&sip->contacts, pos);
            osip_contact_free (contact);
        }
    }
    {
        osip_content_encoding_t *ce;

        while (!osip_list_eol (&sip->content_encodings, pos))
        {
            ce =
                (osip_content_encoding_t *) osip_list_get (&sip->content_encodings, pos);
            osip_list_remove (&sip->content_encodings, pos);
            osip_content_encoding_free (ce);
        }
    }
    if (sip->content_length != NULL)
    {
        osip_content_length_free (sip->content_length);
    }
    if (sip->content_type != NULL)
    {
        osip_content_type_free (sip->content_type);
    }
    if (sip->cseq != NULL)
    {
        osip_cseq_free (sip->cseq);
    }
    {
        osip_error_info_t *error_info;

        while (!osip_list_eol (&sip->error_infos, pos))
        {
            error_info = (osip_error_info_t *) osip_list_get (&sip->error_infos, pos);
            osip_list_remove (&sip->error_infos, pos);
            osip_error_info_free (error_info);
        }
    }
    if (sip->from != NULL)
    {
        osip_from_free (sip->from);
    }
    if (sip->mime_version != NULL)
    {
        osip_mime_version_free (sip->mime_version);
    }
    {
        osip_proxy_authenticate_t *al;

        while (!osip_list_eol (&sip->proxy_authenticates, pos))
        {
            al =
                (osip_proxy_authenticate_t *) osip_list_get (&sip->
                        proxy_authenticates, pos);
            osip_list_remove (&sip->proxy_authenticates, pos);
            osip_proxy_authenticate_free (al);
        }
    }
    {
        osip_proxy_authentication_info_t *al;

        while (!osip_list_eol (&sip->proxy_authentication_infos, pos))
        {
            al =
                (osip_proxy_authentication_info_t *) osip_list_get (&sip->
                        proxy_authentication_infos,
                        pos);
            osip_list_remove (&sip->proxy_authentication_infos, pos);
            osip_proxy_authentication_info_free (al);
        }
    }
    {
        osip_proxy_authorization_t *proxy_authorization;

        while (!osip_list_eol (&sip->proxy_authorizations, pos))
        {
            proxy_authorization =
                (osip_proxy_authorization_t *) osip_list_get (&sip->
                        proxy_authorizations, pos);
            osip_list_remove (&sip->proxy_authorizations, pos);
            osip_proxy_authorization_free (proxy_authorization);
        }
    }
    {
        osip_record_route_t *record_route;

        while (!osip_list_eol (&sip->record_routes, pos))
        {
            record_route =
                (osip_record_route_t *) osip_list_get (&sip->record_routes, pos);
            osip_list_remove (&sip->record_routes, pos);
            osip_record_route_free (record_route);
        }
    }
    {
        osip_route_t *route;

        while (!osip_list_eol (&sip->routes, pos))
        {
            route = (osip_route_t *) osip_list_get (&sip->routes, pos);
            osip_list_remove (&sip->routes, pos);
            osip_route_free (route);
        }
    }
    if (sip->to != NULL)
    {
        osip_to_free (sip->to);
    }
    {
        osip_via_t *via;

        while (!osip_list_eol (&sip->vias, pos))
        {
            via = (osip_via_t *) osip_list_get (&sip->vias, pos);
            osip_list_remove (&sip->vias, pos);
            osip_via_free (via);
        }
    }
    {
        osip_www_authenticate_t *al;

        while (!osip_list_eol (&sip->www_authenticates, pos))
        {
            al =
                (osip_www_authenticate_t *) osip_list_get (&sip->www_authenticates, pos);
            osip_list_remove (&sip->www_authenticates, pos);
            osip_www_authenticate_free (al);
        }
    }

    {
        osip_header_t *header;

        while (!osip_list_eol (&sip->headers, pos))
        {
            header = (osip_header_t *) osip_list_get (&sip->headers, pos);
            osip_list_remove (&sip->headers, pos);
            osip_header_free (header);
        }
    }

    {
        osip_body_t *body;

        while (!osip_list_eol (&sip->bodies, pos))
        {
            body = (osip_body_t *) osip_list_get (&sip->bodies, pos);
            osip_list_remove (&sip->bodies, pos);
            osip_body_free (body);
        }
    }
    osip_free (sip->message);
    osip_free (sip);
}