示例#1
0
void processSipMsg()
{
	int port;
	char host[256];
	char msg[MESSAGE_MAX_LENGTH];
	int msgLen;
	osip_event_t *sipevent;
	osip_transaction_t *transaction = NULL;
	struct sockaddr_in sa;
	int status;

	if((msgLen = networkMsgRecv(sipSock,msg,MESSAGE_MAX_LENGTH,&sa)) > 0){
		printf("processSipMsg: RECEIVED MSG\n");
		printf("%s\n",msg);
		sipevent = osip_parse(msg,msgLen);
		if((sipevent==NULL)||(sipevent->sip==NULL)){
			printf("Could not parse SIP message\n");
			osip_event_free(sipevent);
			return;
		}
	}
	osip_message_fix_last_via_header(sipevent->sip,(char *)inet_ntoa(sa.sin_addr),ntohs(sa.sin_port));
	if((status = osip_find_transaction_and_add_event(osip,sipevent)) != 0){
		printf("New transaction!\n");
		if(MSG_IS_REQUEST(sipevent->sip)){
			printf("Got New Request\n");;
		}else if(MSG_IS_RESPONSE(sipevent->sip)){
			printf("Bad Message:%s\n",msg);
			osip_event_free(sipevent);
		}else{
			printf("Unsupported message:%s\n",msg);
			osip_event_free(sipevent);
		}
	}
}
示例#2
0
int
_eXosip_dialog_init_as_uac (eXosip_dialog_t ** _jd, osip_message_t * _200Ok)
{
  int i;
  eXosip_dialog_t *jd;

  *_jd = NULL;
  jd = (eXosip_dialog_t *) osip_malloc (sizeof (eXosip_dialog_t));
  if (jd == NULL)
    return OSIP_NOMEM;
  memset (jd, 0, sizeof (eXosip_dialog_t));

  jd->d_id = -1;                /* not yet available to user */

  if (MSG_IS_REQUEST (_200Ok)) {
    i = osip_dialog_init_as_uac_with_remote_request (&(jd->d_dialog), _200Ok, -1);
  }
  else {                        /* normal usage with response */
    i = osip_dialog_init_as_uac (&(jd->d_dialog), _200Ok);
  }
  if (i != 0) {
    osip_free (jd);
    return i;
  }

  jd->d_count = 0;
  jd->d_session_timer_start = 0;
  jd->d_session_timer_length = 0;
  jd->d_refresher = -1;         /* 0 -> me / 1 -> remote */
  jd->d_timer = osip_getsystemtime (NULL);
  jd->d_200Ok = NULL;
  jd->d_ack = NULL;
  jd->next = NULL;
  jd->parent = NULL;
  jd->d_out_trs = (osip_list_t *) osip_malloc (sizeof (osip_list_t));
  if (jd->d_out_trs == NULL) {
    osip_dialog_free (jd->d_dialog);
    osip_free (jd);
    return OSIP_NOMEM;
  }
  osip_list_init (jd->d_out_trs);
  jd->d_inc_trs = (osip_list_t *) osip_malloc (sizeof (osip_list_t));
  if (jd->d_inc_trs == NULL) {
    osip_dialog_free (jd->d_dialog);
    osip_free (jd->d_out_trs);
    osip_free (jd);
    return OSIP_NOMEM;
  }
  osip_list_init (jd->d_inc_trs);

  *_jd = jd;
  return OSIP_SUCCESS;
}
示例#3
0
type_t
evt_set_type_incoming_sipmessage (osip_message_t * sip)
{
  if (MSG_IS_REQUEST (sip))
    {
      if (MSG_IS_INVITE (sip))
	return RCV_REQINVITE;
      else if (MSG_IS_ACK (sip))
	return RCV_REQACK;
      return RCV_REQUEST;
    }
  else
    {
      if (MSG_IS_STATUS_1XX (sip))
	return RCV_STATUS_1XX;
      else if (MSG_IS_STATUS_2XX (sip))
	return RCV_STATUS_2XX;
      return RCV_STATUS_3456XX;
    }
}
示例#4
0
int
eXosip_dialog_init_as_uac (eXosip_dialog_t ** _jd, osip_message_t * _200Ok)
{
  int i;
  eXosip_dialog_t *jd;

  *_jd = NULL;
  jd = (eXosip_dialog_t *) osip_malloc (sizeof (eXosip_dialog_t));
  memset (jd, 0, sizeof (eXosip_dialog_t));

  jd->d_id = -1;                /* not yet available to user */
  jd->d_STATE = JD_EMPTY;

  if (MSG_IS_REQUEST (_200Ok))
    {
      i =
        osip_dialog_init_as_uac_with_remote_request (&(jd->d_dialog), _200Ok, -1);
  } else
    {                           /* normal usage with response */
      i = osip_dialog_init_as_uac (&(jd->d_dialog), _200Ok);
    }
  if (i != 0)
    {
      osip_free (jd);
      return -1;
    }

  jd->d_timer = time (NULL);
  jd->d_200Ok = NULL;
  jd->d_ack = NULL;
  jd->next = NULL;
  jd->parent = NULL;
  jd->d_out_trs = (osip_list_t *) osip_malloc (sizeof (osip_list_t));
  osip_list_init (jd->d_out_trs);
  jd->d_inc_trs = (osip_list_t *) osip_malloc (sizeof (osip_list_t));
  osip_list_init (jd->d_inc_trs);

  /* jd->d_bh = sdp_handler_new(); */
  *_jd = jd;
  return 0;
}
示例#5
0
/* returns null on error. */
osip_event_t *
osip_new_outgoing_sipmessage (osip_message_t * sip)
{
  osip_event_t *sipevent;

  if (sip==NULL)
    return NULL;
  if (MSG_IS_REQUEST(sip))
    {
      if (sip->sip_method==NULL)
	return NULL;
      if (sip->req_uri==NULL)
	return NULL;
    }
  sipevent = (osip_event_t *) osip_malloc (sizeof (osip_event_t));
  if (sipevent == NULL)
    return NULL;

  sipevent->sip = sip;
  sipevent->type = evt_set_type_outgoing_sipmessage (sip);
  sipevent->transactionid = 0;
  return sipevent;
}
示例#6
0
static int
eXtl_update_local_target (osip_message_t * req)
{
  int pos = 0;

  struct eXosip_account_info *ainfo = NULL;
  char *proxy = NULL;
  int i;
  if (MSG_IS_REQUEST (req))
    {
      if (req->from != NULL
          && req->from->url != NULL && req->from->url->host != NULL)
        proxy = req->from->url->host;
  } else
    {
      if (req->to != NULL && req->to->url != NULL && req->to->url->host != NULL)
        proxy = req->to->url->host;
    }

  if (proxy != NULL)
    {
      for (i = 0; i < MAX_EXOSIP_ACCOUNT_INFO; i++)
        {
          if (eXosip.account_entries[i].proxy[0] != '\0')
            {
              if (strstr (eXosip.account_entries[i].proxy, proxy) != NULL
                  || strstr (proxy, eXosip.account_entries[i].proxy) != NULL)
                {
                  /* use ainfo */
                  if (eXosip.account_entries[i].nat_ip[0] != '\0')
                    {
                      ainfo = &eXosip.account_entries[i];
                      break;
                    }
                }
            }
        }
    }

  if (udp_firewall_ip != '\0')
    {

      while (!osip_list_eol (&req->contacts, pos))
        {
          osip_contact_t *co;

          co = (osip_contact_t *) osip_list_get (&req->contacts, pos);
          pos++;
          if (co != NULL && co->url != NULL && co->url->host != NULL
              && 0 == osip_strcasecmp (co->url->host, udp_firewall_ip))
            {
              if (ainfo == NULL)
                {
                  if (co->url->port == NULL &&
                      0 != osip_strcasecmp (udp_firewall_port, "5060"))
                    {
                      co->url->port = osip_strdup (udp_firewall_port);
                  } else if (co->url->port != NULL &&
                             0 != osip_strcasecmp (udp_firewall_port,
                                                   co->url->port))
                    {
                      osip_free (co->url->port);
                      co->url->port = osip_strdup (udp_firewall_port);
                    }
              } else
                {
                  if (co->url->port == NULL && ainfo->nat_port != 5060)
                    {
                      co->url->port = osip_malloc (10);
                      if (co->url->port == NULL)
                        return OSIP_NOMEM;
                      snprintf (co->url->port, 9, "%i", ainfo->nat_port);
                  } else if (co->url->port != NULL &&
                             ainfo->nat_port != atoi (co->url->port))
                    {
                      osip_free (co->url->port);
                      co->url->port = osip_malloc (10);
                      if (co->url->port == NULL)
                        return OSIP_NOMEM;
                      snprintf (co->url->port, 9, "%i", ainfo->nat_port);
                    }
                }
            }
        }
    }

  return OSIP_SUCCESS;
}
示例#7
0
文件: proxy.c 项目: 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;
}
示例#8
0
NS_EVENT Node::ReportRCVEvent(osip_message_t *M) 
{
	osip_generic_param_t *param ;
	osip_uri_param_get_byname(M->from->gen_params,"user",&param) ;

	//
	if(!strcmp(param->gvalue,"multicast"))
	{
		if(MSG_IS_REQUEST(M))
		{
			return MULTICAST_REQ_RCV ;
		}
		else
		{
			if(MSG_IS_STATUS_2XX(M))
				return MULTICAST_RESP_2XX ;
			else 
				return EVT_OTHER ;
		}
	}

	//
	else if(!strcmp(param->gvalue,"join"))
	{
		if(MSG_IS_REQUEST(M))
		{
			return JOIN_REQ_RCV ;
		}
		else
		{
			if(MSG_IS_STATUS_2XX(M))
				return JOIN_RESP_2XX ;
			else if(MSG_IS_STATUS_3XX(M))
				return JOIN_RESP_3XX ;
			else 
				return EVT_OTHER ;
		}
	}
	
	//
	else if(!strcmp(param->gvalue,"findsucc"))
	{
		if(MSG_IS_REQUEST(M))
		{
			return FINDSUCC_REQ_RCV ;
		}
		else
		{
			if(MSG_IS_STATUS_2XX(M))
				return FINDSUCC_RESP_2XX ;
			else if(MSG_IS_STATUS_3XX(M))
				return FINDSUCC_RESP_3XX ;
			else 
				return EVT_OTHER ;
		}
	}
	
	//
	else if(!strcmp(param->gvalue,"stabilize"))
	{
		if(MSG_IS_REQUEST(M))
		{
			return STABILIZE_REQ_RCV ;
		}
		else
		{
			if(MSG_IS_STATUS_2XX(M))
				return STABILIZE_RESP_2XX ;
			else 
				return EVT_OTHER ;
		}
	}
	
	//
	else if(!strcmp(param->gvalue,"leave"))
	{
		if(MSG_IS_REQUEST(M))
		{
			return LEAVE_REQ_RCV ;
		}
		else 
			return EVT_OTHER ;
	}
	
	//
	else if(!strcmp(param->gvalue,"user_registration"))
	{
		if(MSG_IS_REQUEST(M))
		{
			return USER_REG_RCV ;
		}
		else if(MSG_IS_STATUS_2XX(M))
		
			return USER_REG_RESP_2XX;

		else if(MSG_IS_STATUS_3XX(M))

			return USER_REG_RESP_3XX;
		
		else return EVT_OTHER ;

	}
	else if(!strcmp(param->gvalue,"red_register"))
	{
		if(MSG_IS_REQUEST(M))
			return RED_REGISTER_RCV;
		else if(MSG_IS_STATUS_2XX(M))
			return RED_REGISTER_RESP_2XX;
		else return EVT_OTHER;
	}
	//
		else if(!strcmp(param->gvalue,"user_query"))
	{
		if(MSG_IS_REQUEST(M))
		{
			return USER_QUERY_RCV ;
		}
		else if(MSG_IS_STATUS_2XX(M))
		
			return USER_QUERY_RESP_2XX;

		else if(MSG_IS_STATUS_3XX(M))

			return USER_QUERY_RESP_3XX;
		
		else return EVT_OTHER ;

	}
	//
	else
	{
		return EVT_OTHER ;
	}	
}
示例#9
0
文件: psp_core3.c 项目: gozfree/src
PPL_DECLARE (int) psp_core_event_add_sip_message (osip_event_t * evt)
{
  osip_transaction_t *transaction;
  osip_message_t *answer1xx;
  int i;

  if (MSG_IS_REQUEST (evt->sip))
    {
      /* delete request where cseq method does not match
	 the method in request-line */
      if (evt->sip->cseq==NULL || evt->sip==NULL
	  || evt->sip->cseq->method==NULL || evt->sip->sip_method==NULL)
	{
	  osip_event_free (evt);
	  return -1;
	}
      if (0 != strcmp (evt->sip->cseq->method, evt->sip->sip_method))
	{
	  OSIP_TRACE (osip_trace
		      (__FILE__, __LINE__, OSIP_WARNING, NULL,
		       "core module: Discard invalid message with method!=cseq!\n"));
	  osip_event_free (evt);
	  return -1;
	}
    }

  i = psp_core_find_osip_transaction_and_add_event (evt);
  if (i == 0)
    {
      psp_osip_wakeup (core->psp_osip);
      return 0;			/*evt consumed */
    }
  if (MSG_IS_REQUEST (evt->sip))
    {
      if (MSG_IS_ACK (evt->sip))
	{			/* continue as it is a new transaction... */
	  osip_route_t *route;

	  /* If a route header is present, then plugins will give
	     the correct location. */
	  osip_message_get_route (evt->sip, 0, &route);
	  if (route == NULL)
	    {
	      OSIP_TRACE (osip_trace
			  (__FILE__, __LINE__, OSIP_INFO1, NULL,
			   "core module: This is a late ACK to discard!\n"));
	      /* It can be a ACK for 200 ok, but those ACK SHOULD
	         never go through this proxy! (and should be sent to the
	         contact header of the 200ok */
#ifdef SUPPORT_FOR_BROKEN_UA
	      /* if this ACK has a request-uri that is not us,
		 forward the message there. How should I modify this
		 message?? */
	      
	      if (evt!=NULL
		  && evt->sip!=NULL
		  && evt->sip!=NULL
		  && evt->sip->req_uri!=NULL)
		{
		  if (psp_core_is_responsible_for_this_domain(evt->sip->req_uri)!=0)
		    {
		      int port = 5060;
		      if (evt->sip->req_uri->port != NULL)
			port = osip_atoi (evt->sip->req_uri->port);
		      psp_core_cb_snd_message(NULL, evt->sip,
					      evt->sip->req_uri->host,
					      port, -1);
 		    }
		}
#endif
	      osip_event_free (evt);
	      return 0;
	    }

	  OSIP_TRACE (osip_trace
		      (__FILE__, __LINE__, OSIP_INFO1, NULL,
		       "core module: This is a ACK for INVITE!\n"));
	  psp_core_event_add_sfp_inc_ack (evt->sip);
	  osip_free (evt);
	  return 0;
	}

      /* we can create the transaction and send a 1xx */
      transaction = osip_create_transaction (core->psp_osip->osip, evt);
      if (transaction == NULL)
	{
	  OSIP_TRACE (osip_trace
		      (__FILE__, __LINE__, OSIP_INFO3, NULL,
		       "core module: Could not create a transaction for this request!\n"));
	  osip_event_free (evt);
	  return -1;
	}

      /* now, all retransmissions will be handled by oSIP. */

      /* From rfc3261: (Section: 16.2)
         "Thus, a stateful proxy SHOULD NOT generate 100 (Trying) responses
         to non-INVITE requests." */
      if (MSG_IS_INVITE (evt->sip))
	{
	  i = osip_msg_build_response (&answer1xx, 100, evt->sip);
	  if (i != 0)
	    {
	      OSIP_TRACE (osip_trace
			  (__FILE__, __LINE__, OSIP_ERROR, NULL,
			   "sfp module: could not create a 100 Trying for this transaction. (discard it and let the transaction die itself)!\n"));
	      osip_event_free (evt);
	      return -1;
	    }

	  osip_transaction_add_event (transaction, evt);

	  evt = osip_new_outgoing_sipmessage (answer1xx);
	  evt->transactionid = transaction->transactionid;
	  osip_transaction_add_event (transaction, evt);
	}
      else
	osip_transaction_add_event (transaction, evt);

      psp_osip_wakeup (core->psp_osip);
      return 0;
    }
  else
    {
      OSIP_TRACE (osip_trace
		  (__FILE__, __LINE__, OSIP_INFO3, NULL,
		   "sfp module: No module seems to be able to forward this response!\n"));
      /* this is probably a late answer? */
      /* let's forward it! */
      i = psp_core_handle_late_answer (evt->sip);
      if (i != 0)
	{
	  osip_event_free (evt);
	  return -1;
	}
      osip_event_free (evt);
    }
  return 0;
}
示例#10
0
static int
udp_tl_send_message(osip_transaction_t * tr, osip_message_t * sip, char *host,
					int port, int out_socket)
{
	int len = 0;
	size_t length = 0;
	struct addrinfo *addrinfo;
	struct __eXosip_sockaddr addr;
	char *message = NULL;

	char ipbuf[INET6_ADDRSTRLEN];
	int i;
	osip_naptr_t *naptr_record=NULL;

	if (udp_socket <= 0)
		return -1;

	if (host == NULL) {
		host = sip->req_uri->host;
		if (sip->req_uri->port != NULL)
			port = osip_atoi(sip->req_uri->port);
		else
			port = 5060;
	}

	eXtl_update_local_target(sip);

	i = -1;
#ifndef MINISIZE
	if (tr==NULL)
	{
		_eXosip_srv_lookup(sip, &naptr_record);

		if (naptr_record!=NULL) {
			eXosip_dnsutils_dns_process(naptr_record, 1);
			if (naptr_record->naptr_state==OSIP_NAPTR_STATE_NAPTRDONE
				||naptr_record->naptr_state==OSIP_NAPTR_STATE_SRVINPROGRESS)
				eXosip_dnsutils_dns_process(naptr_record, 1);
		}

		if (naptr_record!=NULL && naptr_record->naptr_state==OSIP_NAPTR_STATE_SRVDONE)
		{
			/* 4: check if we have the one we want... */
			if (naptr_record->sipudp_record.name[0] != '\0'
				&& naptr_record->sipudp_record.srventry[naptr_record->sipudp_record.index].srv[0] != '\0') {
					/* always choose the first here.
					if a network error occur, remove first entry and
					replace with next entries.
					*/
					osip_srv_entry_t *srv;
					int n = 0;
					for (srv = &naptr_record->sipudp_record.srventry[naptr_record->sipudp_record.index];
						n < 10 && naptr_record->sipudp_record.srventry[naptr_record->sipudp_record.index].srv[0];
						srv = &naptr_record->sipudp_record.srventry[naptr_record->sipudp_record.index]) {
							if (srv->ipaddress[0])
								i = eXosip_get_addrinfo(&addrinfo, srv->ipaddress, srv->port, IPPROTO_UDP);
							else
								i = eXosip_get_addrinfo(&addrinfo, srv->srv, srv->port, IPPROTO_UDP);
							if (i == 0) {
								host = srv->srv;
								port = srv->port;
								break;
							}

							i = eXosip_dnsutils_rotate_srv(&naptr_record->sipudp_record);
							if (i<=0)
							{
								return -1;
							}
							if (i>=n)
							{
								return -1;
							}
							i = -1;
							/* copy next element */
							n++;
					}
			}
		}

		if (naptr_record!=NULL && naptr_record->keep_in_cache==0)
			osip_free(naptr_record);
		naptr_record=NULL;
	}
	else
	{
		naptr_record = tr->naptr_record;
	}

	if (naptr_record!=NULL)
	{
		/* 1: make sure there is no pending DNS */
		eXosip_dnsutils_dns_process(naptr_record, 0);
		if (naptr_record->naptr_state==OSIP_NAPTR_STATE_NAPTRDONE
			||naptr_record->naptr_state==OSIP_NAPTR_STATE_SRVINPROGRESS)
			eXosip_dnsutils_dns_process(naptr_record, 0);

		if (naptr_record->naptr_state==OSIP_NAPTR_STATE_UNKNOWN)
		{
			/* fallback to DNS A */
			if (naptr_record->keep_in_cache==0)
				osip_free(naptr_record);
			naptr_record=NULL;
			if (tr!=NULL)
				tr->naptr_record=NULL;
			/* must never happen? */
		}
		else if (naptr_record->naptr_state==OSIP_NAPTR_STATE_INPROGRESS)
		{
			/* 2: keep waiting (naptr answer not received) */
			return OSIP_SUCCESS + 1;
		}
		else if (naptr_record->naptr_state==OSIP_NAPTR_STATE_NAPTRDONE)
		{
			/* 3: keep waiting (naptr answer received/no srv answer received) */
			return OSIP_SUCCESS + 1;
		}
		else if (naptr_record->naptr_state==OSIP_NAPTR_STATE_SRVINPROGRESS)
		{
			/* 3: keep waiting (naptr answer received/no srv answer received) */
			return OSIP_SUCCESS + 1;
		}
		else if (naptr_record->naptr_state==OSIP_NAPTR_STATE_SRVDONE)
		{
			/* 4: check if we have the one we want... */
			if (naptr_record->sipudp_record.name[0] != '\0'
				&& naptr_record->sipudp_record.srventry[naptr_record->sipudp_record.index].srv[0] != '\0') {
					/* always choose the first here.
					if a network error occur, remove first entry and
					replace with next entries.
					*/
					osip_srv_entry_t *srv;
					int n = 0;
					for (srv = &naptr_record->sipudp_record.srventry[naptr_record->sipudp_record.index];
						n < 10 && naptr_record->sipudp_record.srventry[naptr_record->sipudp_record.index].srv[0];
						srv = &naptr_record->sipudp_record.srventry[naptr_record->sipudp_record.index]) {
							if (srv->ipaddress[0])
								i = eXosip_get_addrinfo(&addrinfo, srv->ipaddress, srv->port, IPPROTO_UDP);
							else
								i = eXosip_get_addrinfo(&addrinfo, srv->srv, srv->port, IPPROTO_UDP);
							if (i == 0) {
								host = srv->srv;
								port = srv->port;
								break;
							}

							i = eXosip_dnsutils_rotate_srv(&naptr_record->sipudp_record);
							if (i<=0)
							{
								return -1;
							}
							if (i>=n)
							{
								return -1;
							}
							i = -1;
							/* copy next element */
							n++;
					}
			}
		}
		else if (naptr_record->naptr_state==OSIP_NAPTR_STATE_NOTSUPPORTED
			||naptr_record->naptr_state==OSIP_NAPTR_STATE_RETRYLATER)
		{
			/* 5: fallback to DNS A */
			if (naptr_record->keep_in_cache==0)
				osip_free(naptr_record);
			naptr_record=NULL;
			if (tr!=NULL)
				tr->naptr_record=NULL;
		}
	}
#endif

	/* if SRV was used, destination may be already found */
	if (i != 0) {
		i = eXosip_get_addrinfo(&addrinfo, host, port, IPPROTO_UDP);
	}

	if (i != 0) {
		return -1;
	}

	memcpy(&addr, addrinfo->ai_addr, addrinfo->ai_addrlen);
	len = addrinfo->ai_addrlen;

	eXosip_freeaddrinfo(addrinfo);

	/* remove preloaded route if there is no tag in the To header
	 */
	{
		osip_route_t *route = NULL;
		osip_generic_param_t *tag = NULL;
		osip_message_get_route(sip, 0, &route);

		osip_to_get_tag(sip->to, &tag);
		if (tag == NULL && route != NULL && route->url != NULL) {
			osip_list_remove(&sip->routes, 0);
		}
		i = osip_message_to_str(sip, &message, &length);
		if (tag == NULL && route != NULL && route->url != NULL) {
			osip_list_add(&sip->routes, route, 0);
		}
	}

	if (i != 0 || length <= 0) {
		osip_free(message);
		return -1;
	}

	switch (((struct sockaddr *) &addr)->sa_family) {
	case AF_INET:
		inet_ntop(((struct sockaddr *) &addr)->sa_family,
				  &(((struct sockaddr_in *) &addr)->sin_addr), ipbuf,
				  sizeof(ipbuf));
		break;
	case AF_INET6:
		inet_ntop(((struct sockaddr *) &addr)->sa_family,
				  &(((struct sockaddr_in6 *) &addr)->sin6_addr), ipbuf,
				  sizeof(ipbuf));
		break;
	default:
		strncpy(ipbuf, "(unknown)", sizeof(ipbuf));
		break;
	}

	OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_INFO1, NULL,
						  "Message sent: (to dest=%s:%i)\n%s\n",
						  ipbuf, port, message));

	if (osip_strcasecmp(host, ipbuf)!=0 && MSG_IS_REQUEST(sip)) {
		if (MSG_IS_REGISTER(sip)) {
			struct eXosip_dns_cache entry;

			memset(&entry, 0, sizeof(struct eXosip_dns_cache));
			snprintf(entry.host, sizeof(entry.host), "%s", host);
			snprintf(entry.ip, sizeof(entry.ip), "%s", ipbuf);
			eXosip_set_option(EXOSIP_OPT_ADD_DNS_CACHE, (void *) &entry);
		}
	}

	if (tr != NULL) {
		if (tr->ict_context != NULL)
			osip_ict_set_destination(tr->ict_context, osip_strdup(ipbuf), port);
		if (tr->nict_context != NULL)
			osip_nict_set_destination(tr->nict_context, osip_strdup(ipbuf), port);
	}

	if (0 >
		sendto(udp_socket, (const void *) message, length, 0,
			   (struct sockaddr *) &addr, len))
	{
#ifndef MINISIZE
		if (naptr_record!=NULL)
		{
			/* rotate on failure! */
			if (eXosip_dnsutils_rotate_srv(&naptr_record->sipudp_record)>0)
			{
				osip_free(message);
				return OSIP_SUCCESS + 1;	/* retry for next retransmission! */
			}
		}
#endif
		/* SIP_NETWORK_ERROR; */
		osip_free(message);
		return -1;
	}
	
	if (eXosip.keep_alive > 0) {
		if (MSG_IS_REGISTER(sip)) {
			eXosip_reg_t *reg = NULL;

			if (_eXosip_reg_find(&reg, tr) == 0) {
				memcpy(&(reg->addr), &addr, len);
				reg->len = len;
			}
		}
	}

#ifndef MINISIZE
	if (naptr_record!=NULL)
	{
		if (tr!=NULL && MSG_IS_REGISTER(sip) && tr->last_response==NULL)
		{
			/* failover for outgoing transaction */
			time_t now;
			now = time(NULL);
			OSIP_TRACE(osip_trace
				(__FILE__, __LINE__, OSIP_INFO2, NULL,
				"not yet answered\n"));
			if (tr != NULL && now - tr->birth_time > 10 && now - tr->birth_time < 13)
			{
				/* avoid doing this twice... */
				if (eXosip_dnsutils_rotate_srv(&naptr_record->sipudp_record)>0)
				{
					OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_INFO1, NULL,
						"Doing failover: %s:%i->%s:%i\n",
						host, port,
						naptr_record->sipudp_record.srventry[naptr_record->sipudp_record.index].srv,
						naptr_record->sipudp_record.srventry[naptr_record->sipudp_record.index].port));
					osip_free(message);
					return OSIP_SUCCESS + 1;	/* retry for next retransmission! */
				}
			}
		}
	}
#endif

	osip_free(message);
	return OSIP_SUCCESS;
}
示例#11
0
static int
dtls_tl_send_message(osip_transaction_t * tr, osip_message_t * sip, char *host,
                    int port, int out_socket)
{
  int len = 0;
  size_t length = 0;
  struct addrinfo *addrinfo;
  struct __eXosip_sockaddr addr;
  char *message;

  char ipbuf[INET6_ADDRSTRLEN];
  int i;

  int pos;
  struct socket_tab *socket_tab_used=NULL;
  BIO *sbio=NULL;

  if (dtls_socket <= 0)
    return -1;

  if (host == NULL)
    {
      host = sip->req_uri->host;
      if (sip->req_uri->port != NULL)
        port = osip_atoi (sip->req_uri->port);
      else
        port = 5061;
    }

  if (port == 5060)
    port = 5061;

  if (MSG_IS_REQUEST(sip))
    {
      if (MSG_IS_REGISTER(sip)
	  ||MSG_IS_INVITE(sip)
	  ||MSG_IS_SUBSCRIBE(sip)
	  || MSG_IS_NOTIFY(sip))
	eXtl_update_local_target(sip);
    }

  i=-1;
#ifndef MINISIZE
  if (tr!=NULL && tr->record.name[0]!='\0' && tr->record.srventry[0].srv[0]!='\0')
    {
      /* always choose the first here.
	 if a network error occur, remove first entry and
	 replace with next entries.
      */
      osip_srv_entry_t *srv;
      int n=0;
      for (srv = &tr->record.srventry[0];
	   n<10 && tr->record.srventry[0].srv[0];
	   srv = &tr->record.srventry[0])
	{
	  i = eXosip_get_addrinfo (&addrinfo, srv->srv, srv->port, IPPROTO_UDP);
	  if (i == 0)
	    {
	      host = srv->srv;
	      port = srv->port;
	      break;
	    }
	  memmove(&tr->record.srventry[0], &tr->record.srventry[1], 9*sizeof(osip_srv_entry_t));
	  memset(&tr->record.srventry[9], 0, sizeof(osip_srv_entry_t));
	  i=-1;
	  /* copy next element */
	  n++;
	}
    }
#endif
  
  /* if SRV was used, distination may be already found */
  if (i != 0)
    {
      i = eXosip_get_addrinfo (&addrinfo, host, port, IPPROTO_UDP);
    }
  
  if (i != 0)
    {
      return -1;
    }
  
  memcpy (&addr, addrinfo->ai_addr, addrinfo->ai_addrlen);
  len = addrinfo->ai_addrlen;
  
  eXosip_freeaddrinfo (addrinfo);
  
  /* remove preloaded route if there is no tag in the To header
   */
  {
    osip_route_t *route=NULL;
    osip_generic_param_t *tag=NULL;
    osip_message_get_route (sip, 0, &route);
    
    osip_to_get_tag (sip->to, &tag);
    if (tag==NULL && route != NULL && route->url != NULL)
      {
	osip_list_remove(&sip->routes, 0);
      }
    i = osip_message_to_str (sip, &message, &length);
    if (tag==NULL && route != NULL && route->url != NULL)
      {
	osip_list_add(&sip->routes, route, 0);
      }
  }
  
  if (i != 0 || length <= 0)
    {
      return -1;
    }
  
  switch ( ((struct sockaddr *)&addr)->sa_family )
    {
    case AF_INET:
      inet_ntop (((struct sockaddr *)&addr)->sa_family, &(((struct sockaddr_in *) &addr)->sin_addr),
		 ipbuf, sizeof (ipbuf));
      break;
    case AF_INET6:
      inet_ntop (((struct sockaddr *)&addr)->sa_family,
		 &(((struct sockaddr_in6 *) &addr)->sin6_addr), ipbuf,
		 sizeof (ipbuf));
      break;
    default:
      strncpy (ipbuf, "(unknown)", sizeof (ipbuf));
      break;
    }
  
  OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO1, NULL,
                          "Message sent: \n%s (to dest=%s:%i)\n",
                          message, ipbuf, port));

  for (pos = 0; pos < EXOSIP_MAX_SOCKETS; pos++)
    {
      if (dtls_socket_tab[pos].ssl_conn != NULL
	  && dtls_socket_tab[pos].ssl_type == EXOSIP_AS_A_SERVER)
	{
	  if (dtls_socket_tab[pos].remote_port == port &&
	      (strcmp (dtls_socket_tab[pos].remote_ip, ipbuf) == 0))
	    {
	      BIO *rbio;
	      socket_tab_used = &dtls_socket_tab[pos];
	      rbio = BIO_new_dgram (dtls_socket, BIO_NOCLOSE);
	      BIO_dgram_set_peer (rbio, &addr);
	      dtls_socket_tab[pos].ssl_conn->rbio = rbio;
	      break;
	    }
	}
    }
  if (socket_tab_used==NULL)
    {
      for (pos = 0; pos < EXOSIP_MAX_SOCKETS; pos++)
	{
	  if (dtls_socket_tab[pos].ssl_conn != NULL
	      && dtls_socket_tab[pos].ssl_type == EXOSIP_AS_A_CLIENT)
	    {
	      if (dtls_socket_tab[pos].remote_port == port &&
		  (strcmp (dtls_socket_tab[pos].remote_ip, ipbuf) == 0))
		{
		  BIO *rbio;
		  socket_tab_used = &dtls_socket_tab[pos];
		  rbio = BIO_new_dgram (dtls_socket, BIO_NOCLOSE);
		  BIO_dgram_set_peer (rbio, &addr);
		  dtls_socket_tab[pos].ssl_conn->rbio = rbio;
		  break;
		}
	    }
	}
    }

  if (socket_tab_used==NULL)
    {
      /* delete an old one! */
      pos=0;
      if (dtls_socket_tab[pos].ssl_conn != NULL)
	{
	  shutdown_free_client_dtls (pos);
	  shutdown_free_server_dtls (pos);
	}
      
      memset(&dtls_socket_tab[pos], 0, sizeof(struct socket_tab));
    }
  
  if (dtls_socket_tab[pos].ssl_conn == NULL)
    {
      /* create a new one */
      SSL_CTX_set_read_ahead (client_ctx, 1);
      dtls_socket_tab[pos].ssl_conn = SSL_new (client_ctx);

      if (dtls_socket_tab[pos].ssl_conn == NULL)
	{
	  OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL,
				  "DTLS SSL_new error\n"));

	  if (dtls_socket_tab[pos].ssl_conn != NULL)
	    {
	      shutdown_free_client_dtls (pos);
	      shutdown_free_server_dtls (pos);
	    }
	  
	  memset(&dtls_socket_tab[pos], 0, sizeof(struct socket_tab));

	  osip_free (message);
	  return -1;
	}

      if (connect (dtls_socket, (struct sockaddr *) &addr, sizeof (addr)) == -1)
	{
	  OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL,
				  "DTLS connect error\n"));
	  if (dtls_socket_tab[pos].ssl_conn != NULL)
	    {
	      shutdown_free_client_dtls (pos);
	      shutdown_free_server_dtls (pos);
	    }
	  
	  memset(&dtls_socket_tab[pos], 0, sizeof(struct socket_tab));

	  osip_free (message);
	  return -1;
	}
      
      SSL_set_options (dtls_socket_tab[pos].ssl_conn, SSL_OP_NO_QUERY_MTU);
      SSL_set_mtu (dtls_socket_tab[pos].ssl_conn, 2000);
      SSL_set_connect_state (dtls_socket_tab[pos].ssl_conn);
      sbio = BIO_new_dgram (dtls_socket, BIO_NOCLOSE);
      BIO_ctrl_set_connected (sbio, 1, (struct sockaddr *) &addr);
      SSL_set_bio (dtls_socket_tab[pos].ssl_conn, sbio, sbio);

      dtls_socket_tab[pos].ssl_type = 2;
      dtls_socket_tab[pos].ssl_state = 2;
      
      osip_strncpy (dtls_socket_tab[pos].remote_ip, ipbuf,
		    sizeof (dtls_socket_tab[pos].remote_ip));
      dtls_socket_tab[pos].remote_port = port;
    }

  i = SSL_write (dtls_socket_tab[pos].ssl_conn, message, length);

  if (i<0)
    {
      i = SSL_get_error (dtls_socket_tab[pos].ssl_conn, i);
      print_ssl_error (i);
      if (i==SSL_ERROR_SSL
	  || i==SSL_ERROR_SYSCALL)
	{
	  OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL,
				  "DTLS SSL_write error\n"));
	  if (dtls_socket_tab[pos].ssl_conn != NULL)
	      {
		shutdown_free_client_dtls (pos);
		shutdown_free_server_dtls (pos);
	      }
	  
	  memset(&dtls_socket_tab[pos], 0, sizeof(struct socket_tab));
	  
	}

#ifndef MINISIZE
      /* delete first SRV entry that is not reachable */
      if (tr->record.name[0]!='\0' && tr->record.srventry[0].srv[0]!='\0')
	{
	  memmove(&tr->record.srventry[0], &tr->record.srventry[1], 9*sizeof(osip_srv_entry_t));
	  memset(&tr->record.srventry[9], 0, sizeof(osip_srv_entry_t));
	  osip_free (message);
	  return 0; /* retry for next retransmission! */
	}
#endif
      /* SIP_NETWORK_ERROR; */
      osip_free (message);
      return -1;
    }

  if (eXosip.keep_alive > 0)
    {
      if (MSG_IS_REGISTER (sip))
        {
          eXosip_reg_t *reg = NULL;
	  
          if (_eXosip_reg_find (&reg, tr) == 0)
            {
              memcpy (&(reg->addr), &addr, len);
              reg->len = len;
            }
        }
    }
  
  osip_free (message);
  return 0;
}
示例#12
0
int main (int argc, char *argv[]) 
{
   int sts;
   int i;
   int buflen;
   int access;
   char buff [BUFFER_SIZE];
   sip_ticket_t ticket;

   extern char *optarg;         /* Defined in libc getopt and unistd.h */
   int ch1;
   
   char configfile[64]="siproxd";       /* basename of configfile */
   int  config_search=1;                /* search the config file */
   int  cmdline_debuglevel=0;
   char *pidfilename=NULL;
   struct sigaction act;

   log_set_stderr(1);

/*
 * setup signal handlers
 */
   act.sa_handler=sighandler;
   sigemptyset(&act.sa_mask);
   act.sa_flags=SA_RESTART;
   if (sigaction(SIGTERM, &act, NULL)) {
      ERROR("Failed to install SIGTERM handler");
   }
   if (sigaction(SIGINT, &act, NULL)) {
      ERROR("Failed to install SIGINT handler");
   }
   if (sigaction(SIGUSR2, &act, NULL)) {
      ERROR("Failed to install SIGUSR2 handler");
   }


/*
 * prepare default configuration
 */
   make_default_config();

   log_set_pattern(configuration.debuglevel);

/*
 * parse command line
 */
{
#ifdef  HAVE_GETOPT_LONG
   int option_index = 0;
   static struct option long_options[] = {
      {"help", no_argument, NULL, 'h'},
      {"config", required_argument, NULL, 'c'},
      {"debug", required_argument, NULL, 'd'},
      {"pid-file", required_argument, NULL,'p'},
      {0,0,0,0}
   };

    while ((ch1 = getopt_long(argc, argv, "hc:d:p:",
                  long_options, &option_index)) != -1) {
#else   /* ! HAVE_GETOPT_LONG */
    while ((ch1 = getopt(argc, argv, "hc:d:p:")) != -1) {
#endif
      switch (ch1) {
      case 'h': /* help */
         DEBUGC(DBCLASS_CONFIG,"option: help");
         fprintf(stderr,str_helpmsg);
         exit(0);
         break;

      case 'c': /* load config file */
         DEBUGC(DBCLASS_CONFIG,"option: config file=%s",optarg);
         i=sizeof(configfile)-1;
         strncpy(configfile,optarg,i-1);
         configfile[i]='\0';
         config_search=0;
         break; 

      case 'd': /* set debug level */
         DEBUGC(DBCLASS_CONFIG,"option: set debug level: %s",optarg);
         cmdline_debuglevel=atoi(optarg);
         log_set_pattern(cmdline_debuglevel);
         break;

      case 'p':
         pidfilename = optarg;
         break;

      default:
         DEBUGC(DBCLASS_CONFIG,"no command line options");
         break; 
      }
   }
}

/*
 * Init stuff
 */
   INFO(PACKAGE"-"VERSION"-"BUILDSTR" "UNAME" starting up");

   /* read the config file */
   if (read_config(configfile, config_search) == STS_FAILURE) exit(1);

   /* if a debug level > 0 has been given on the commandline use its
      value and not what is in the config file */
   if (cmdline_debuglevel != 0) {
      configuration.debuglevel=cmdline_debuglevel;
   }

/*
 * open a the pwfile instance, so we still have access after
 * we possibly have chroot()ed to somewhere.
 */
   if (configuration.proxy_auth_pwfile) {
      siproxd_passwordfile = fopen(configuration.proxy_auth_pwfile, "r");
   } else {
      siproxd_passwordfile = NULL;
   }

   /* set debug level as desired */
   log_set_pattern(configuration.debuglevel);
   log_set_listen_port(configuration.debugport);

   /* change user and group IDs */
   secure_enviroment();

   /* daemonize if requested to */
   if (configuration.daemonize) {
      DEBUGC(DBCLASS_CONFIG,"daemonizing");
      if (fork()!=0) exit(0);
      setsid();
      if (fork()!=0) exit(0);

      log_set_stderr(0);
      INFO("daemonized, pid=%i", getpid());
   }

   /* write PID file of main thread */
   if (pidfilename == NULL) pidfilename = configuration.pid_file;
   if (pidfilename) {
      FILE *pidfile;
      DEBUGC(DBCLASS_CONFIG,"creating PID file [%s]", pidfilename);
      sts=unlink(configuration.pid_file);
      if ((sts==0) ||(errno == ENOENT)) {
         if ((pidfile=fopen(pidfilename, "w"))) {
            fprintf(pidfile,"%i\n",(int)getpid());
            fclose(pidfile);
         } else {
            WARN("couldn't create new PID file: %s", strerror(errno));
         }
      } else {
         WARN("couldn't delete old PID file: %s", strerror(errno));
      }
   }

   /* initialize the RTP proxy */
   sts=rtpproxy_init();
   if (sts != STS_SUCCESS) {
      ERROR("unable to initialize RTP proxy - aborting"); 
      exit(1);
   }

   /* init the oSIP parser */
   parser_init();

   /* listen for incoming messages */
   sts=sipsock_listen();
   if (sts == STS_FAILURE) {
      /* failure to allocate SIP socket... */
      ERROR("unable to bind to SIP listening socket - aborting"); 
      exit(1);
   }

   /* initialize the registration facility */
   register_init();

/*
 * silence the log - if so required...
 */
   log_set_silence(configuration.silence_log);

   INFO(PACKAGE"-"VERSION"-"BUILDSTR" "UNAME" started");

/*****************************
 * Main loop
 *****************************/
   while (!exit_program) {

      DEBUGC(DBCLASS_BABBLE,"going into sipsock_wait\n");
      while (sipsock_wait()<=0) {
         /* got no input, here by timeout. do aging */
         register_agemap();

         /* TCP log: check for a connection */
         log_tcp_connect();

         /* dump memory stats if requested to do so */
         if (dmalloc_dump) {
            dmalloc_dump=0;
#ifdef DMALLOC
            INFO("SIGUSR2 - DMALLOC statistics is dumped");
            dmalloc_log_stats();
            dmalloc_log_unfreed();
#else
            INFO("SIGUSR2 - DMALLOC support is not compiled in");
#endif
         }

         if (exit_program) goto exit_prg;
      }

      /*
       * got input, process
       */
      DEBUGC(DBCLASS_BABBLE,"back from sipsock_wait");
      ticket.direction=0;

      buflen=sipsock_read(&buff, sizeof(buff)-1, &ticket.from,
                           &ticket.protocol);
      buff[buflen]='\0';

      /*
       * evaluate the access lists (IP based filter)
       */
      access=accesslist_check(ticket.from);
      if (access == 0) {
         DEBUGC(DBCLASS_ACCESS,"access for this packet was denied");
         continue; /* there are no resources to free */
      }

      /*
       * integrity checks
       */
      sts=security_check_raw(buff, buflen);
      if (sts != STS_SUCCESS) {
         DEBUGC(DBCLASS_SIP,"security check (raw) failed");
         continue; /* there are no resources to free */
      }

      /*
       * init sip_msg
       */
      sts=osip_message_init(&ticket.sipmsg);
      ticket.sipmsg->message=NULL;
      if (sts != 0) {
         ERROR("osip_message_init() failed... this is not good");
         continue; /* skip, there are no resources to free */
      }

      /*
       * RFC 3261, Section 16.3 step 1
       * Proxy Behavior - Request Validation - Reasonable Syntax
       * (parse the received message)
       */
      sts=sip_message_parse(ticket.sipmsg, buff, buflen);
      if (sts != 0) {
         ERROR("sip_message_parse() failed... this is not good");
         DUMP_BUFFER(-1, buff, buflen);
         goto end_loop; /* skip and free resources */
      }

      /*
       * integrity checks - parsed buffer
       */
      sts=security_check_sip(&ticket);
      if (sts != STS_SUCCESS) {
         ERROR("security_check_sip() failed... this is not good");
         DUMP_BUFFER(-1, buff, buflen);
         goto end_loop; /* skip and free resources */
      }

      /*
       * RFC 3261, Section 16.3 step 2
       * Proxy Behavior - Request Validation - URI scheme
       * (check request URI and refuse with 416 if not understood)
       */
      /* NOT IMPLEMENTED */

      /*
       * RFC 3261, Section 16.3 step 3
       * Proxy Behavior - Request Validation - Max-Forwards check
       * (check Max-Forwards header and refuse with 483 if too many hops)
       */
      {
         osip_header_t *max_forwards;
         int forwards_count = DEFAULT_MAXFWD;

         osip_message_get_max_forwards(ticket.sipmsg, 0, &max_forwards);
         if (max_forwards && max_forwards->hvalue) {
            forwards_count = atoi(max_forwards->hvalue);
         }

         DEBUGC(DBCLASS_PROXY,"checking Max-Forwards (=%i)",forwards_count);
         if (forwards_count <= 0) {
            DEBUGC(DBCLASS_SIP, "Forward count reached 0 -> 483 response");
            sip_gen_response(&ticket, 483 /*Too many hops*/);
            goto end_loop; /* skip and free resources */
         }
      }

      /*
       * RFC 3261, Section 16.3 step 4
       * Proxy Behavior - Request Validation - Loop Detection check
       * (check for loop and return 482 if a loop is detected)
       */
      if (check_vialoop(&ticket) == STS_TRUE) {
         /* make sure we don't end up in endless loop when detecting
          * an loop in an "loop detected" message - brrr */
         if (MSG_IS_RESPONSE(ticket.sipmsg) && 
             MSG_TEST_CODE(ticket.sipmsg, 482)) {
            DEBUGC(DBCLASS_SIP,"loop in loop-response detected, ignoring");
         } else {
            DEBUGC(DBCLASS_SIP,"via loop detected, ignoring request");
            sip_gen_response(&ticket, 482 /*Loop detected*/);
         }
         goto end_loop; /* skip and free resources */
      }

      /*
       * RFC 3261, Section 16.3 step 5
       * Proxy Behavior - Request Validation - Proxy-Require check
       * (check Proxy-Require header and return 420 if unsupported option)
       */
      /* NOT IMPLEMENTED */

      /*
       * RFC 3261, Section 16.5
       * Proxy Behavior - Determining Request Targets
       */
      /* NOT IMPLEMENTED */

      DEBUGC(DBCLASS_SIP,"received SIP type %s:%s",
             (MSG_IS_REQUEST(ticket.sipmsg))? "REQ" : "RES",
             (MSG_IS_REQUEST(ticket.sipmsg) ?
                ((ticket.sipmsg->sip_method)?
                   ticket.sipmsg->sip_method : "NULL") :
                ((ticket.sipmsg->reason_phrase) ? 
                   ticket.sipmsg->reason_phrase : "NULL")));

      /*********************************
       * The message did pass all the
       * tests above and is now ready
       * to be proxied.
       * Before we do so, we apply some
       * additional preprocessing
       *********************************/
      /* Dial shortcuts */
      if (configuration.pi_shortdial) {
         sts = plugin_shortdial(&ticket);
         if (sts == STS_SIP_SENT) goto end_loop;
      }


      /*********************************
       * finally proxy the message.
       * This includes the masquerading
       * of the local UA and starting/
       * stopping the RTP proxy for this
       * call
       *********************************/

      /*
       * if a REQ REGISTER, check if it is directed to myself,
       * or am I just the outbound proxy but no registrar.
       * - If I'm the registrar, register & generate answer
       * - If I'm just the outbound proxy, register, rewrite & forward
       */
      if (MSG_IS_REGISTER(ticket.sipmsg) && 
          MSG_IS_REQUEST(ticket.sipmsg)) {
         if (access & ACCESSCTL_REG) {
            osip_uri_t *url;
            struct in_addr addr1, addr2, addr3;
            int dest_port;

            url = osip_message_get_uri(ticket.sipmsg);
            dest_port= (url->port)?atoi(url->port):SIP_PORT;

            if ( (get_ip_by_host(url->host, &addr1) == STS_SUCCESS) &&
                 (get_interface_ip(IF_INBOUND,&addr2) == STS_SUCCESS) &&
                 (get_interface_ip(IF_OUTBOUND,&addr3) == STS_SUCCESS)) {

               if ((configuration.sip_listen_port == dest_port) &&
                   ((memcmp(&addr1, &addr2, sizeof(addr1)) == 0) ||
                    (memcmp(&addr1, &addr3, sizeof(addr1)) == 0))) {
                  /* I'm the registrar, send response myself */
                  sts = register_client(&ticket, 0);
                  sts = register_response(&ticket, sts);
               } else {
                  /* I'm just the outbound proxy */
                  DEBUGC(DBCLASS_SIP,"proxying REGISTER request to:%s",
                         url->host);
                  sts = register_client(&ticket, 1);
                  if (sts == STS_SUCCESS) {
                     sts = proxy_request(&ticket);
                  }
               }
            } else {
               sip_gen_response(&ticket, 408 /*request timeout*/);
            }
         } else {
            WARN("non-authorized registration attempt from %s",
                 utils_inet_ntoa(ticket.from.sin_addr));
         }

      /*
       * check if outbound interface is UP.
       * If not, send back error to UA and
       * skip any proxying attempt
       */
      } else if (get_interface_ip(IF_OUTBOUND,NULL) !=
                 STS_SUCCESS) {
         DEBUGC(DBCLASS_SIP, "got a %s to proxy, but outbound interface "
                "is down", (MSG_IS_REQUEST(ticket.sipmsg))? "REQ" : "RES");

         if (MSG_IS_REQUEST(ticket.sipmsg))
            sip_gen_response(&ticket, 408 /*request timeout*/);
      
      /*
       * MSG is a request, add current via entry,
       * do a lookup in the URLMAP table and
       * send to the final destination
       */
      } else if (MSG_IS_REQUEST(ticket.sipmsg)) {
         if (access & ACCESSCTL_SIP) {
            sts = proxy_request(&ticket);
         } else {
            INFO("non-authorized request received from %s",
                 utils_inet_ntoa(ticket.from.sin_addr));
         }

      /*
       * MSG is a response, remove current via and
       * send to the next VIA in chain
       */
      } else if (MSG_IS_RESPONSE(ticket.sipmsg)) {
         if (access & ACCESSCTL_SIP) {
            sts = proxy_response(&ticket);
         } else {
            INFO("non-authorized response received from %s",
                 utils_inet_ntoa(ticket.from.sin_addr));
         }
         
      /*
       * unsupported message
       */
      } else {
         ERROR("received unsupported SIP type %s %s",
               (MSG_IS_REQUEST(ticket.sipmsg))? "REQ" : "RES",
               ticket.sipmsg->sip_method);
      }

      /*********************************
       * Done with proxying. Message
       * has been sent to its destination.
       *********************************/
/*
 * free the SIP message buffers
 */
      end_loop:
      osip_message_free(ticket.sipmsg);

   } /* while TRUE */
   exit_prg:

   /* save current known SIP registrations */
   register_save();
   INFO("properly terminating siproxd");

   /* remove PID file */
   if (pidfilename) {
      DEBUGC(DBCLASS_CONFIG,"deleting PID file [%s]", pidfilename);
      sts=unlink(pidfilename);
      if (sts != 0) {
         WARN("couldn't delete old PID file: %s", strerror(errno));
      }
   }

   /* END */
   return 0;
} /* main */

/*
 * Signal handler
 *
 * this one is called asynchronously whevener a registered
 * signal is applied. Just set a flag and don't do any funny
 * things here.
 */
static void sighandler(int sig) {
   if (sig==SIGTERM) exit_program=1;
   if (sig==SIGINT)  exit_program=1;
   if (sig==SIGUSR2) dmalloc_dump=1;
   return;
}
示例#13
0
/*
 * SIP_IS_OUTGOING
 *
 * Figures out if this is an outgoing or incoming request/response.
 * The direction is stored in the ticket->direction property.
 *
 * RETURNS
 *	STS_SUCCESS on success
 *	STS_FAILURE if unable to determine
 */
int  sip_find_direction(sip_ticket_t *ticket, int *urlidx) {
   int type;
   int i, sts;
   struct sockaddr_in *from;
   osip_message_t *request;
   osip_message_t *response;

   from=&ticket->from;
   request=ticket->sipmsg;
   response=ticket->sipmsg;
   type = 0;

   ticket->direction = 0;

   /*
    * did I receive the telegram from a REGISTERED host?
    * -> it must be an OUTGOING request
    */
   for (i=0; i<URLMAP_SIZE; i++) {
      struct in_addr tmp_addr;

      if (urlmap[i].active == 0) continue;
      if (get_ip_by_host(urlmap[i].true_url->host, &tmp_addr) == STS_FAILURE) {
         DEBUGC(DBCLASS_SIP, "sip_find_direction: cannot resolve host [%s]",
             urlmap[i].true_url->host);
      } else {
         DEBUGC(DBCLASS_SIP, "sip_find_direction: reghost:%s ip:%s",
                urlmap[i].true_url->host, utils_inet_ntoa(from->sin_addr));
         if (memcmp(&tmp_addr, &from->sin_addr, sizeof(tmp_addr)) == 0) {
            if (MSG_IS_REQUEST(ticket->sipmsg)) {
               type=REQTYP_OUTGOING;
            } else {
               type=RESTYP_OUTGOING;
            }
            break;
         }
      }
   }

   /*
    * is the telegram directed to an internally registered host?
    * -> it must be an INCOMING request
    */
   if (type == 0) {
      for (i=0; i<URLMAP_SIZE; i++) {
         if (urlmap[i].active == 0) continue;
         /* RFC3261:
          * 'To' contains a display name (Bob) and a SIP or SIPS URI
          * (sip:[email protected]) towards which the request was originally
          * directed.  Display names are described in RFC 2822 [3].
          */

         /* So this means, that we must check the SIP URI supplied with the
          * INVITE method, as this points to the real wanted target.
          * Q: does there exist a situation where the SIP URI itself does
          *    point to "somewhere" but the To: points to the correct UA?
          * So for now, we just look at both of them (SIP URI and To: header)
          */

         if (MSG_IS_REQUEST(ticket->sipmsg)) {
            /* REQUEST */
            /* incoming request (SIP URI == 'masq') || ((SIP URI == 'reg') && !REGISTER)*/
            if ((compare_url(request->req_uri, urlmap[i].masq_url)==STS_SUCCESS) ||
                (!MSG_IS_REGISTER(request) &&
                 (compare_url(request->req_uri, urlmap[i].reg_url)==STS_SUCCESS))) {
               type=REQTYP_INCOMING;
               break;
            }
            /* incoming request ('to' == 'masq') || (('to' == 'reg') && !REGISTER)*/
            if ((compare_url(request->to->url, urlmap[i].masq_url)==STS_SUCCESS) ||
                (!MSG_IS_REGISTER(request) &&
                 (compare_url(request->to->url, urlmap[i].reg_url)==STS_SUCCESS))) {
               type=REQTYP_INCOMING;
               break;
            }
         } else { 
            /* RESPONSE */
            /* incoming response ('from' == 'masq') || ('from' == 'reg') */
            if ((compare_url(response->from->url, urlmap[i].reg_url)==STS_SUCCESS) ||
                (compare_url(response->from->url, urlmap[i].masq_url)==STS_SUCCESS)) {
               type=RESTYP_INCOMING;
               break;
            }
         } /* is request */
      } /* for i */
   } /* if type == 0 */


   if (MSG_IS_RESPONSE(ticket->sipmsg)) {
      /* &&&& Open Issue &&&&
         it has been seen with cross-provider calls that the FROM may be 'garbled'
         (e.g [email protected] for calls made sipphone -> FWD)
         How can we deal with this? Should I take into consideration the 'Via'
         headers? This is the only clue I have, pointing to the *real* UA.
         Maybe I should put in a 'siproxd' ftag value to recognize it as a header
         inserted by myself
      */
      if ((type == 0) && (!osip_list_eol(response->vias, 0))) {
         osip_via_t *via;
         struct in_addr addr_via, addr_myself;
         int port_via, port_ua;

         /* get the via address */
         via = (osip_via_t *) osip_list_get (response->vias, 0);
         DEBUGC(DBCLASS_SIP, "sip_find_direction: check via [%s] for "
                "registered UA",via->host);
         sts=get_ip_by_host(via->host, &addr_via);
         if (sts == STS_FAILURE) {
            DEBUGC(DBCLASS_SIP, "sip_find_direction: cannot resolve VIA [%s]",
                   via->host);
         } else {

            for (i=0; i<URLMAP_SIZE; i++) {
               if (urlmap[i].active == 0) continue;
               /* incoming response (1st via in list points to a registered UA) */
               sts=get_ip_by_host(urlmap[i].true_url->host, &addr_myself);
               if (sts == STS_FAILURE) {
                  DEBUGC(DBCLASS_SIP, "sip_find_direction: cannot resolve "
                         "true_url [%s]", via->host);
                  continue;
               }

               port_via=0;
               if (via->port) port_via=atoi(via->port);
               if (port_via <= 0) port_via=SIP_PORT;

               port_ua=0;
               if (urlmap[i].true_url->port)
                  port_ua=atoi(urlmap[i].true_url->port);
               if (port_ua <= 0) port_ua=SIP_PORT;

               DEBUGC(DBCLASS_SIP, "sip_find_direction: checking for registered "
                      "host [%s:%i] <-> [%s:%i]",
                      urlmap[i].true_url->host, port_ua,
                      via->host, port_via);

               if ((memcmp(&addr_myself, &addr_via, sizeof(addr_myself))==0) &&
                   (port_via == port_ua)) {
                  type=RESTYP_INCOMING;
                  break;
               }
            } /* for i */
         }
      } /* if type == 0 */
   } /* is response */

   if (type == 0) {
      DEBUGC(DBCLASS_SIP, "sip_find_direction: unable to determine "
                          "direction of SIP packet");
      return STS_FAILURE;
   }

   ticket->direction=type;
   if (urlidx) *urlidx=i;
   return STS_SUCCESS;
}
示例#14
0
/* return NULL  if message cannot be parsed            */
osip_event_t *
osip_parse (char *buf)
{
  osip_event_t *se = __osip_event_new (UNKNOWN_EVT, 0);
  int i;

#ifdef TEST_PARSER_SPEED
  {
    int kk;
    int pstime1, pstime;
    struct timespec tv1;

    clock_get_time (CLOCK_REALTIME, &tv1);
    pstime = ((tv1.tv_sec * 1000) + (tv1.tv_nsec / 1000000));
    for (kk = 0; kk < 10000; kk++)
      {

	i = osip_message_init (&(se->sip));

	if (osip_message_parse (se->sip, buf) == -1)
	  {
	    fprintf (stdout, "osip_message_parse retrun -1\n");
	    osip_message_free (se->sip);
	  }
	else
	  {			/* msg is parsed */
	    osip_message_free (se->sip);
	  }
      }
    clock_get_time (CLOCK_REALTIME, &tv1);
    pstime1 = ((tv1.tv_sec * 1000) + (tv1.tv_nsec / 1000000));
    fprintf (stdout, "CPU clock ticks for 10000 messages - T1: %i - T2: %i\n",
	     pstime1, pstime);
    fprintf (stdout, "CPU time for 10000 messages - %d\n",
	     (pstime1 - pstime));
  }
  osip_free (se);
  return NULL;
#endif
  /* parse message and set up an event */
  i = osip_message_init (&(se->sip));
  if (osip_message_parse (se->sip, buf) == -1)
    {
      OSIP_TRACE (osip_trace
		  (__FILE__, __LINE__, OSIP_ERROR, NULL,
		   "could not parse message\n"));
      osip_message_free (se->sip);
      osip_free (se);
      return NULL;
    }
  else
    {
      if (se->sip->call_id!=NULL && se->sip->call_id->number!=NULL)
	{
	  OSIP_TRACE (osip_trace
		      (__FILE__, __LINE__, OSIP_INFO3, NULL,
		       "MESSAGE REC. CALLID:%s\n", se->sip->call_id->number));
	}

      if (MSG_IS_REQUEST(se->sip))
	{
	  if (se->sip->sip_method==NULL || se->sip->req_uri==NULL)
	    {
	      osip_message_free (se->sip);
	      osip_free (se);
	      return NULL;
	    }
	}

      se->type = evt_set_type_incoming_sipmessage (se->sip);
      return se;
    }
}
示例#15
0
int
_eXosip_srv_lookup(osip_transaction_t * tr, osip_message_t * sip,
				   struct osip_srv_record *record)
{
	int use_srv = 1;

	int port;

	char *host;

	osip_via_t *via;

	via = (osip_via_t *) osip_list_get(&sip->vias, 0);
	if (via == NULL || via->protocol == NULL)
		return OSIP_BADPARAMETER;

	if (MSG_IS_REQUEST(sip)) {
		osip_route_t *route;

		osip_message_get_route(sip, 0, &route);
		if (route != NULL) {
			osip_uri_param_t *lr_param = NULL;

			osip_uri_uparam_get_byname(route->url, "lr", &lr_param);
			if (lr_param == NULL)
				route = NULL;
		}

		if (route != NULL) {
			port = 5060;
			if (route->url->port != NULL) {
				port = osip_atoi(route->url->port);
				use_srv = 0;
			}
			host = route->url->host;
		} else {
			/* search for maddr parameter */
			osip_uri_param_t *maddr_param = NULL;

			osip_uri_uparam_get_byname(sip->req_uri, "maddr", &maddr_param);
			host = NULL;
			if (maddr_param != NULL && maddr_param->gvalue != NULL)
				host = maddr_param->gvalue;

			port = 5060;
			if (sip->req_uri->port != NULL) {
				use_srv = 0;
				port = osip_atoi(sip->req_uri->port);
			}

			if (host == NULL)
				host = sip->req_uri->host;
		}
	} else {
		osip_generic_param_t *maddr;

		osip_generic_param_t *received;

		osip_generic_param_t *rport;

		osip_via_param_get_byname(via, "maddr", &maddr);
		osip_via_param_get_byname(via, "received", &received);
		osip_via_param_get_byname(via, "rport", &rport);
		if (maddr != NULL)
			host = maddr->gvalue;
		else if (received != NULL)
			host = received->gvalue;
		else
			host = via->host;

		if (via->port == NULL)
			use_srv = 0;
		if (rport == NULL || rport->gvalue == NULL) {
			if (via->port != NULL)
				port = osip_atoi(via->port);
			else
				port = 5060;
		} else
			port = osip_atoi(rport->gvalue);
	}

	if (host == NULL) {
		return OSIP_UNKNOWN_HOST;
	}

	/* check if we have an IPv4 or IPv6 address */
	if (strchr(host, ':') || (INADDR_NONE != inet_addr(host))) {
		return OSIP_UNKNOWN_HOST;
	}

	if (use_srv == 1) {
		int i;

		i = eXosip_get_srv_record(record, host, via->protocol);
		return i;
	}
	return OSIP_SUCCESS;
}