Exemple #1
0
void linphone_proxy_config_register_again_with_updated_contact(LinphoneProxyConfig *obj, osip_message_t *orig_request, osip_message_t *last_answer){
	osip_message_t *msg;
	const char *rport,*received;
	osip_via_t *via=NULL;
	osip_generic_param_t *param=NULL;
	osip_contact_t *ctt=NULL;
	osip_message_get_via(last_answer,0,&via);
	if (!via) return;
	osip_via_param_get_byname(via,"rport",&param);
	if (param) rport=param->gvalue;
	else return;
	param=NULL;
	osip_via_param_get_byname(via,"received",&param);
	if (param) received=param->gvalue;
	else return;
	osip_message_get_contact(orig_request,0,&ctt);
	if (strcmp(ctt->url->host,received)==0 && (ctt->url->port!=0 && strcmp(ctt->url->port,rport)==0)){
		ms_message("Register has up to date contact, doing nothing.");
		return;
	}
	eXosip_lock();
	eXosip_register_build_register(obj->rid,obj->expires,&msg);
	osip_message_get_contact(msg,0,&ctt);
	if (ctt->url->host!=NULL){
		osip_free(ctt->url->host);
	}
	ctt->url->host=osip_strdup(received);
	if (ctt->url->port!=NULL){
		osip_free(ctt->url->port);
	}
	ctt->url->port=osip_strdup(rport);
	eXosip_register_send_register(obj->rid,msg);
	eXosip_unlock();
	ms_message("Resending new register with updated contact %s:%i",received,rport);
}
Exemple #2
0
int
eXosip_update_top_via (osip_message_t * sip)
{
  unsigned int number;
  char tmp[40];
  osip_generic_param_t *br=NULL;
  osip_via_t *via = (osip_via_t *) osip_list_get (&sip->vias, 0);

  if (via==NULL)
    {
      OSIP_TRACE (osip_trace
		  (__FILE__, __LINE__, OSIP_ERROR, NULL,
		   "missing via in SIP message\n"));
      return -1;
    }
  /* browse parameter and replace "branch" */
  osip_via_param_get_byname (via, "branch", &br);

  if (br==NULL || br->gvalue==NULL)
    {
      OSIP_TRACE (osip_trace
		  (__FILE__, __LINE__, OSIP_ERROR, NULL,
		   "missing branch parameter via in SIP message\n"));
      return -1;
    }
  
  osip_free(br->gvalue);
  number = osip_build_random_number ();

  sprintf (tmp, "z9hG4bK%u", number);
  br->gvalue = osip_strdup(tmp);
  return 0;
}
Exemple #3
0
void
udp_tl_learn_port_from_via (osip_message_t * sip)
{
  /* EXOSIP_OPT_UDP_LEARN_PORT option set */
  if (eXosip.learn_port > 0)
    {
      osip_via_t *via = NULL;
      osip_generic_param_t *br;

      osip_message_get_via (sip, 0, &via);
      if (via != NULL && via->protocol != NULL
          && (osip_strcasecmp (via->protocol, "udp") == 0
              || osip_strcasecmp (via->protocol, "dtls-udp") == 0))
        {
          osip_via_param_get_byname (via, "rport", &br);
          if (br != NULL && br->gvalue != NULL)
            {
              struct eXosip_account_info ainfo;
              memset (&ainfo, 0, sizeof (struct eXosip_account_info));
              snprintf (udp_firewall_port, 20, "%s", br->gvalue);
              OSIP_TRACE (osip_trace
                          (__FILE__, __LINE__, OSIP_INFO1, NULL,
                           "SIP port modified from rport in SIP answer\r\n"));

              osip_via_param_get_byname (via, "received", &br);
              if (br != NULL && br->gvalue != NULL
                  && sip->from != NULL && sip->from->url != NULL
                  && sip->from->url->host != NULL)
                {
                  snprintf (ainfo.proxy, sizeof (ainfo.proxy), "%s",
                            sip->from->url->host);
                  ainfo.nat_port = atoi (udp_firewall_port);
                  snprintf (ainfo.nat_ip, sizeof (ainfo.nat_ip), "%s", br->gvalue);
                  eXosip_set_option (EXOSIP_OPT_ADD_ACCOUNT_INFO, &ainfo);
                }
            }
        }
    }
  return;
}
Exemple #4
0
int sip_gateway_find_invite_transaction(osip_message_t* osip_msg)
{
    osip_via_t* via = osip_list_get (&osip_msg->vias, 0);

    if (NULL != via)
    {
        osip_uri_param_t* branch = NULL;
        osip_via_param_get_byname(via, "branch", &branch);

        if (NULL != branch)
        {
            osip_uri_header_free(branch);
        }
    }

    return RC_ERR;
}
/* This method just add a received parameter in the Via
   as requested by rfc3261 */
int
osip_message_fix_last_via_header(osip_message_t * request,
								 const char *ip_addr, int port)
{
	osip_generic_param_t *rport;
	osip_via_t *via;

	/* get Top most Via header: */
	if (request == NULL)
		return OSIP_BADPARAMETER;
	if (MSG_IS_RESPONSE(request))
		return OSIP_SUCCESS;	/* Don't fix Via header */

	via = osip_list_get(&request->vias, 0);
	if (via == NULL || via->host == NULL)
		/* Hey, we could build it? */
		return OSIP_BADPARAMETER;

	osip_via_param_get_byname(via, "rport", &rport);
	if (rport != NULL) {
		if (rport->gvalue == NULL) {
			rport->gvalue = (char *) osip_malloc(9);
			if (rport->gvalue == NULL)
				return OSIP_NOMEM;
#if !defined __PALMOS__ && (defined WIN32 || defined _WIN32_WCE)
			_snprintf(rport->gvalue, 8, "%i", port);
#else
			snprintf(rport->gvalue, 8, "%i", port);
#endif
		}						/* else bug? */
	}

	/* only add the received parameter if the 'sent-by' value does not contains
	   this ip address */
	if (0 == strcmp(via->host, ip_addr))	/* don't need the received parameter */
		return OSIP_SUCCESS;
	osip_via_set_received(via, osip_strdup(ip_addr));
	return OSIP_SUCCESS;
}
void udp_tl_learn_port_from_via(CSipMessage* sip)
{
	/* EXOSIP_OPT_UDP_LEARN_PORT option set */ 
	CVia* via = NULL;
	CUrlParam* br;
	
	sip->GetVia(0,&via);
	if (via !=
		NULL &&
		via->m_pcProtocol !=
		NULL &&
		(zstr_strcasecmp(via->m_pcProtocol, "udp") == 0 ||
		zstr_strcasecmp(via->m_pcProtocol,
		"dtls-udp") == 0))
	{
		osip_via_param_get_byname(via, "rport", &br);
		if (br != NULL && br->gvalue != NULL)
		{
			//_snprintf(udp_firewall_port, 20, "%s", br->gvalue);
		}
	}
	
	return;
}
Exemple #7
0
void
nist_snd_23456xx (osip_transaction_t * nist, osip_event_t * evt)
{
  int i;
  osip_via_t *via;
  osip_t *osip = (osip_t *) nist->config;

  if (nist->last_response != NULL)
    {
      osip_message_free (nist->last_response);
    }
  nist->last_response = evt->sip;

  via = (osip_via_t *) osip_list_get (nist->last_response->vias, 0);
  if (via)
    {
      char *host;
      int port;
      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);
      /* 1: user should not use the provided information
         (host and port) if they are using a reliable
         transport. Instead, they should use the already
         open socket attached to this transaction. */
      /* 2: check maddr and multicast usage */
      if (maddr != NULL)
	host = maddr->gvalue;
      /* we should check if this is a multicast address and use
         set the "ttl" in this case. (this must be done in the
         UDP message (not at the SIP layer) */
      else if (received != NULL)
	host = received->gvalue;
      else
	host = via->host;

      if (rport == NULL || rport->gvalue == NULL)
	{
	  if (via->port != NULL)
	    port = osip_atoi (via->port);
	  else
	    port = 5060;
	}
      else
	port = osip_atoi (rport->gvalue);
      i = osip->cb_send_message (nist, nist->last_response, host,
				 port, nist->out_socket);
    }
  else
    i = -1;
  if (i != 0)
    {
      nist_handle_transport_error (nist, i);
      return;
    }
  else
    {
      if (EVT_IS_SND_STATUS_2XX (evt))
	__osip_message_callback (OSIP_NIST_STATUS_2XX_SENT, nist, nist->last_response);
      else if (MSG_IS_STATUS_3XX (nist->last_response))
	__osip_message_callback (OSIP_NIST_STATUS_3XX_SENT, nist, nist->last_response);
      else if (MSG_IS_STATUS_4XX (nist->last_response))
	__osip_message_callback (OSIP_NIST_STATUS_4XX_SENT, nist, nist->last_response);
      else if (MSG_IS_STATUS_5XX (nist->last_response))
	__osip_message_callback (OSIP_NIST_STATUS_5XX_SENT, nist, nist->last_response);
      else
	__osip_message_callback (OSIP_NIST_STATUS_6XX_SENT, nist, nist->last_response);
    }

  if (nist->state != NIST_COMPLETED)	/* start J timer */
    nist->nist_context->timer_j_start = time (NULL);

  __osip_transaction_set_state (nist, NIST_COMPLETED);
}
Exemple #8
0
void
nist_rcv_request (osip_transaction_t * nist, osip_event_t * evt)
{
  int i;
  osip_t *osip = (osip_t *) nist->config;

  if (nist->state == NIST_PRE_TRYING)	/* announce new REQUEST */
    {
      /* Here we have ist->orig_request == NULL */
      nist->orig_request = evt->sip;

      if (MSG_IS_REGISTER (evt->sip))
	__osip_message_callback (OSIP_NIST_REGISTER_RECEIVED, nist,
			   nist->orig_request);
      else if (MSG_IS_BYE (evt->sip))
	__osip_message_callback (OSIP_NIST_BYE_RECEIVED, nist,
			   nist->orig_request);
      else if (MSG_IS_OPTIONS (evt->sip))
	__osip_message_callback (OSIP_NIST_OPTIONS_RECEIVED, nist,
			   nist->orig_request);
      else if (MSG_IS_INFO (evt->sip))
	__osip_message_callback (OSIP_NIST_INFO_RECEIVED, nist,
			   nist->orig_request);
      else if (MSG_IS_CANCEL (evt->sip))
	__osip_message_callback (OSIP_NIST_CANCEL_RECEIVED, nist,
			   nist->orig_request);
      else if (MSG_IS_NOTIFY (evt->sip))
	__osip_message_callback (OSIP_NIST_NOTIFY_RECEIVED, nist,
			   nist->orig_request);
      else if (MSG_IS_SUBSCRIBE (evt->sip))
	__osip_message_callback (OSIP_NIST_SUBSCRIBE_RECEIVED, nist,
			   nist->orig_request);
      else
	__osip_message_callback (OSIP_NIST_UNKNOWN_REQUEST_RECEIVED, nist,
			   nist->orig_request);
    }
  else				/* NIST_PROCEEDING or NIST_COMPLETED */
    {
      /* delete retransmission */
      osip_message_free (evt->sip);

      __osip_message_callback (OSIP_NIST_REQUEST_RECEIVED_AGAIN, nist,
			 nist->orig_request);
      if (nist->last_response != NULL)	/* retransmit last response */
	{
	  osip_via_t *via;

	  via = (osip_via_t *) osip_list_get (nist->last_response->vias, 0);
	  if (via)
	    {
	      char *host;
	      int port;
	      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);
	      /* 1: user should not use the provided information
	         (host and port) if they are using a reliable
	         transport. Instead, they should use the already
	         open socket attached to this transaction. */
	      /* 2: check maddr and multicast usage */
	      if (maddr != NULL)
		host = maddr->gvalue;
	      /* we should check if this is a multicast address and use
	         set the "ttl" in this case. (this must be done in the
	         UDP message (not at the SIP layer) */
	      else if (received != NULL)
		host = received->gvalue;
	      else
		host = via->host;

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

	      i = osip->cb_send_message (nist, nist->last_response, host,
					 port, nist->out_socket);
	    }
	  else
	    i = -1;
	  if (i != 0)
	    {
              nist_handle_transport_error (nist, i);
	      return;
	    }
	  else
	    {
	      if (MSG_IS_STATUS_1XX (nist->last_response))
		__osip_message_callback (OSIP_NIST_STATUS_1XX_SENT, nist,
				   nist->last_response);
	      else if (MSG_IS_STATUS_2XX (nist->last_response))
		__osip_message_callback (OSIP_NIST_STATUS_2XX_SENT_AGAIN, nist,
				   nist->last_response);
	      else
		__osip_message_callback (OSIP_NIST_STATUS_3456XX_SENT_AGAIN, nist,
				   nist->last_response);
	      return;
	    }
	}
      /* we are already in the proper state */
      return;
    }

  /* we come here only if it was the first REQUEST received */
  __osip_transaction_set_state (nist, NIST_TRYING);
}
/*
 * SIP_CALCULATE_BRANCH
 *
 * Calculates a branch parameter according to RFC3261 section 16.11
 *
 * The returned 'id' will be HASHHEXLEN + strlen(magic_cookie)
 * characters (32 + 7) long. The caller must supply at least this
 * amount of space in 'id'.
 *
 * RETURNS
 *	STS_SUCCESS on success
 *	STS_FAILURE on error
 */
int  sip_calculate_branch_id (sip_ticket_t *ticket, char *id) {
/* RFC3261 section 16.11 recommends the following procedure:
 *   The stateless proxy MAY use any technique it likes to guarantee
 *   uniqueness of its branch IDs across transactions.  However, the
 *   following procedure is RECOMMENDED.  The proxy examines the
 *   branch ID in the topmost Via header field of the received
 *   request.  If it begins with the magic cookie, the first
 *   component of the branch ID of the outgoing request is computed
 *   as a hash of the received branch ID.  Otherwise, the first
 *   component of the branch ID is computed as a hash of the topmost
 *   Via, the tag in the To header field, the tag in the From header
 *   field, the Call-ID header field, the CSeq number (but not
 *   method), and the Request-URI from the received request.  One of
 *   these fields will always vary across two different
 *   transactions.
 *
 * The branch value will consist of:
 * - magic cookie "z9hG4bK"
 * - 1st part (unique calculated ID
 * - 2nd part (value for loop detection) <<- not yet used by siproxd
 */
   osip_message_t *sip_msg=ticket->sipmsg;
   static char *magic_cookie="z9hG4bK";
   osip_via_t *via;
   osip_uri_param_t *param=NULL;
   osip_call_id_t *call_id=NULL;
   HASHHEX hashstring;

   hashstring[0]='\0';

   /*
    * Examine topmost via and look for a magic cookie.
    * If it is there, I use THIS branch parameter as input for
    * our hash calculation
    */
   via = osip_list_get (sip_msg->vias, 0);
   if (via == NULL) {
      ERROR("have a SIP message without any via header");
      return STS_FAILURE;
   }

   param=NULL;
   osip_via_param_get_byname(via, "branch", &param);
   if (param && param->gvalue) {
      DEBUGC(DBCLASS_BABBLE, "looking for magic cookie [%s]",param->gvalue);
      if (strncmp(param->gvalue, magic_cookie,
                  strlen(magic_cookie))==0) {
         /* calculate MD5 hash */
         MD5_CTX Md5Ctx;
         HASH HA1;

         MD5Init(&Md5Ctx);
         MD5Update(&Md5Ctx, param->gvalue,
                   strlen(param->gvalue));
         MD5Final(HA1, &Md5Ctx);
         CvtHex(HA1, hashstring);

         DEBUGC(DBCLASS_BABBLE, "existing branch -> branch hash [%s]",
                hashstring);
      }
   }

   /*
    * If I don't have a branch parameter in the existing topmost via,
    * then I need:
    *   - the topmost via
    *   - the tag in the To header field
    *   - the tag in the From header field
    *   - the Call-ID header field
    *   - the CSeq number (but not method)
    *   - the Request-URI from the received request
    */
   if (hashstring[0] == '\0') {
      /* calculate MD5 hash */
      MD5_CTX Md5Ctx;
      HASH HA1;
      char *tmp;

      MD5Init(&Md5Ctx);

      /* topmost via */
      osip_via_to_str(via, &tmp);
      if (tmp) {
         MD5Update(&Md5Ctx, tmp, strlen(tmp));
         osip_free(tmp);
      }
     
      /* Tag in To header */
      osip_to_get_tag(sip_msg->to, &param);
      if (param && param->gvalue) {
         MD5Update(&Md5Ctx, param->gvalue, strlen(param->gvalue));
      }

      /* Tag in From header */
      osip_from_get_tag(sip_msg->from, &param);
      if (param && param->gvalue) {
         MD5Update(&Md5Ctx, param->gvalue, strlen(param->gvalue));
      }

      /* Call-ID */
      call_id = osip_message_get_call_id(sip_msg);
      osip_call_id_to_str(call_id, &tmp);
      if (tmp) {
         MD5Update(&Md5Ctx, tmp, strlen(tmp));
         osip_free(tmp);
      }

      /* CSeq number (but not method) */
      tmp = osip_cseq_get_number(sip_msg->cseq);
      if (tmp) {
         MD5Update(&Md5Ctx, tmp, strlen(tmp));
      }
 
      /* Request URI */
      osip_uri_to_str(sip_msg->req_uri, &tmp);
      if (tmp) {
         MD5Update(&Md5Ctx, tmp, strlen(tmp));
         osip_free(tmp);
      }

      MD5Final(HA1, &Md5Ctx);
      CvtHex(HA1, hashstring);

      DEBUGC(DBCLASS_BABBLE, "non-existing branch -> branch hash [%s]",
             hashstring);
   }

   /* include the magic cookie */
   sprintf(id, "%s%s", magic_cookie, hashstring);

   return STS_SUCCESS;
}
Exemple #10
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;
}