Exemplo n.º 1
0
int
osip_uri_param_get_byname (osip_list_t * params, char *pname,
                           osip_uri_param_t ** url_param)
{
  int pos = 0;
  size_t pname_len;
  osip_uri_param_t *u_param;

  *url_param = NULL;
  if (pname == NULL)
    return -1;
  pname_len = strlen (pname);
  if (pname_len <= 0)
    return -1;
  while (!osip_list_eol (params, pos))
    {
      size_t len;

      u_param = (osip_uri_param_t *) osip_list_get (params, pos);
      len = strlen (u_param->gname);
      if (pname_len == len
          && osip_strncasecmp (u_param->gname, pname, strlen (pname)) == 0)
        {
          *url_param = u_param;
          return 0;
        }
      pos++;
    }
  return -1;
}
Exemplo n.º 2
0
char *osip_strcasestr(const char *haystack, const char *needle)
{
	char c, sc;
	size_t len;

	if ((c = *needle++) != 0) {
		c = tolower((unsigned char) c);
		len = strlen(needle);
		do {
			do {
				if ((sc = *haystack++) == 0)
					return (NULL);
			} while ((char) tolower((unsigned char) sc) != c);
		} while (osip_strncasecmp(haystack, needle, len) != 0);
		haystack--;
	}
	return (char *) haystack;
}
Exemplo n.º 3
0
Arquivo: proxy.c Projeto: OPSF/uClinux
/*
 * PROXY_RESPONSE
 *
 * RETURNS
 *	STS_SUCCESS on success
 *	STS_FAILURE on error
 * RFC3261
 *    Section 16.7: Proxy Behavior - Response Processing
 *    1.  Find the appropriate response context
 *    2.  Update timer C for provisional responses
 *    3.  Remove the topmost Via
 *    4.  Add the response to the response context
 *    5.  Check to see if this response should be forwarded immediately
 *    6.  When necessary, choose the best final response from the
 *        response context
 *    7.  Aggregate authorization header field values if necessary
 *    8.  Optionally rewrite Record-Route header field values
 *    9.  Forward the response
 *    10. Generate any necessary CANCEL requests 
 *
 */
int proxy_response (sip_ticket_t *ticket) {
   int i;
   int sts;
   int type;
   struct in_addr sendto_addr;
   osip_via_t *via;
   int port;
   char *buffer;
   int buflen;
   osip_message_t *response;
   struct sockaddr_in *from;

   DEBUGC(DBCLASS_PROXY,"proxy_response");

   if (ticket==NULL) {
      ERROR("proxy_response: called with NULL ticket");
      return STS_FAILURE;
   }

   response=ticket->sipmsg;
   from=&ticket->from;

   /*
    * RFC 3261, Section 16.7 step 3
    * Proxy Behavior - Response Processing - Remove my Via header field value
    */
   /* remove my Via header line */
   sts = sip_del_myvia(ticket);
   if (sts == STS_FAILURE) {
      DEBUGC(DBCLASS_PROXY,"not addressed to my VIA, ignoring response");
      return STS_FAILURE;
   }

   /*
    * figure out if this is an request coming from the outside
    * world to one of our registered clients
    */

   /* Ahhrghh...... a response seems to have NO contact information... 
    * so let's take FROM instead...
    * the TO and FROM headers are EQUAL to the request - that means 
    * they are swapped in their meaning for a response...
    */

#if _OLD_DIRECTION_EVALUATION
   type = 0;
   for (i=0; i<URLMAP_SIZE; i++) {
      if (urlmap[i].active == 0) continue;

      /* 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;
         DEBUGC(DBCLASS_PROXY,"incoming response for %s@%s from outbound",
	   response->from->url->username? response->from->url->username:"******",
	   response->from->url->host? response->from->url->host : "*NULL*");
	 break;
      }

      /* outgoing response ('to' == 'reg') || ('to' == 'masq' ) */
      if ((compare_url(response->to->url, urlmap[i].masq_url)==STS_SUCCESS) ||
          (compare_url(response->to->url, urlmap[i].reg_url)==STS_SUCCESS)){
         type=RESTYP_OUTGOING;
         DEBUGC(DBCLASS_PROXY,"outgoing response for %s@%s from inbound",
	        response->from->url->username ?
                   response->from->url->username : "******",
	        response->from->url->host ? 
                   response->from->url->host : "*NULL*");
	 break;
      }
   }
#else
   type = 0;
   /*
    * did I receive the telegram from a REGISTERED host?
    * -> it must be an OUTGOING response
    */
   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_PROXY, "proxy_response: cannot resolve host [%s]",
             urlmap[i].true_url);
      } else {
         DEBUGC(DBCLASS_PROXY, "proxy_response: 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) {
            type=RESTYP_OUTGOING;
	    break;
         }
      }
   }
   /*
    * is the telegram directed to an internal registered host?
    * -> it must be an INCOMING response
    */
   if (type == 0) {
      for (i=0; i<URLMAP_SIZE; i++) {
         if (urlmap[i].active == 0) continue;
         /* 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;
         }
      }
   }
/* &&&& 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_PROXY, "proxy_response: check via [%s] for "
             "registered UA",via->host);
      sts=get_ip_by_host(via->host, &addr_via);
      if (sts == STS_FAILURE) {
         DEBUGC(DBCLASS_DNS, "proxy_response: 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_DNS, "proxy_response: 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_BABBLE, "proxy_response: 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;
            }
         }
      }
   }
    
#endif
   ticket->direction=type;

/*
 * ok, we got a response that we are allowed to process.
 */
   switch (type) {
  /*
   * from an external host to the internal masqueraded host
   */
   case RESTYP_INCOMING:
      DEBUGC(DBCLASS_PROXY,"incoming response for %s@%s from outbound",
	response->from->url->username? response->from->url->username:"******",
	response->from->url->host? response->from->url->host : "*NULL*");

      /*
       * Response for INVITE - deal with RTP data in body and
       *                       start RTP proxy stream(s). In case
       *                       of a negative answer, stop RTP stream
       */
      if (MSG_IS_RESPONSE_FOR(response,"INVITE")) {
         /* positive response, start RTP stream */
         if ((MSG_IS_STATUS_1XX(response)) || 
              (MSG_IS_STATUS_2XX(response))) {
            if (configuration.rtp_proxy_enable == 1) {
               sts = proxy_rewrite_invitation_body(response, DIR_INCOMING);
            }
         /* negative - stop a possibly started RTP stream */
         } else if ((MSG_IS_STATUS_4XX(response))  ||
                     (MSG_IS_STATUS_5XX(response)) ||
                     (MSG_IS_STATUS_6XX(response))) {
            rtp_stop_fwd(osip_message_get_call_id(response), DIR_INCOMING);
            rtp_stop_fwd(osip_message_get_call_id(response), DIR_OUTGOING);
         }
      } /* if INVITE */

      /*
       * Response for REGISTER - special handling of Contact header
       */
      if (MSG_IS_RESPONSE_FOR(response,"REGISTER")) {
         /*
          * REGISTER returns *my* Contact header information.
          * Rewrite Contact header back to represent the true address.
          * Other responses do return the Contact header of the sender.
          */
         sip_rewrite_contact(ticket, DIR_INCOMING);
      }

      /* 
       * Response for SUBSCRIBE
       *
       * HACK for Grandstream SIP phones (with newer firmware like 1.0.4.40):
       *   They send a SUBSCRIBE request to the registration server. In
       *   case of beeing registering directly to siproxd, this request of
       *   course will eventually be forwarded back to the same UA.
       *   Grandstream then does reply with an '202' response (A 202
       *   response merely indicates that the subscription has been
       *   understood, and that authorization may or may not have been
       *   granted), which then of course is forwarded back to the phone.
       *   Ans it seems that the Grandstream can *not* *handle* this
       *   response, as it immediately sends another SUBSCRIBE request.
       *   And this games goes on and on and on...
       *
       *   As a workaround we will transform any 202 response to a
       *   '404 unknown destination'
       *   
       */
{
      osip_header_t *ua_hdr=NULL;
      osip_message_get_user_agent(response, 0, &ua_hdr);
      if (ua_hdr && ua_hdr->hvalue &&
          (osip_strncasecmp(ua_hdr->hvalue,"grandstream", 11)==0) &&
          (MSG_IS_RESPONSE_FOR(response,"SUBSCRIBE")) &&
          (MSG_TEST_CODE(response, 202))) {
         DEBUGC(DBCLASS_PROXY, "proxy_response: Grandstream hack 202->404");
         response->status_code=404;
      }
}
      break;
   
  /*
   * from the internal masqueraded host to an external host
   */
   case RESTYP_OUTGOING:
      DEBUGC(DBCLASS_PROXY,"outgoing response for %s@%s from inbound",
	     response->from->url->username ?
                response->from->url->username : "******",
	     response->from->url->host ? 
                response->from->url->host : "*NULL*");

      /* rewrite Contact header to represent the masqued address */
      sip_rewrite_contact(ticket, DIR_OUTGOING);

      /*
       * If an 2xx OK or 1xx response, answer to an INVITE request,
       * rewrite body
       *
       * In case of a negative answer, stop RTP stream
       */
      if (MSG_IS_RESPONSE_FOR(response,"INVITE")) {
         /* positive response, start RTP stream */
         if ((MSG_IS_STATUS_1XX(response)) || 
              (MSG_IS_STATUS_2XX(response))) {
            /* This is an outgoing response, therefore an outgoing stream */
            sts = proxy_rewrite_invitation_body(response, DIR_OUTGOING);
         /* megative - stop a possibly started RTP stream */
         } else if ((MSG_IS_STATUS_4XX(response))  ||
                     (MSG_IS_STATUS_5XX(response)) ||
                     (MSG_IS_STATUS_6XX(response))) {
            rtp_stop_fwd(osip_message_get_call_id(response), DIR_INCOMING);
            rtp_stop_fwd(osip_message_get_call_id(response), DIR_OUTGOING);
         }
      } /* if INVITE */

      break;
   
   default:
      DEBUGC(DBCLASS_PROXY, "response from/to unregistered UA (%s@%s)",
	   response->from->url->username? response->from->url->username:"******",
	   response->from->url->host? response->from->url->host : "*NULL*");
      return STS_FAILURE;
   }

   /*
    * for ALL incoming response include my Record-Route header.
    * The local UA will probably send its answer to the topmost 
    * Route Header (8.1.2 of RFC3261)
    */
    if (type == RESTYP_INCOMING) {
       DEBUGC(DBCLASS_PROXY,"Adding my Record-Route");
       route_add_recordroute(ticket);
    } else {
       /*
        * outgoing packets must not have my record route header, as
        * this likely will contain a private IP address (my inbound).
        */
       DEBUGC(DBCLASS_PROXY,"Purging Record-Routes (outgoing packet)");
       route_purge_recordroute(ticket);
    }

   /*
    * Determine Next-Hop Address
    */
/*&&&& priority probably should be:
 * 1) Route header
 * 2) fixed outbound proxy
 * 3) SIP URI
 */
   /*
    * check if we need to send to an outbound proxy
    */
   if ((type == RESTYP_OUTGOING) &&
       (sip_find_outbound_proxy(ticket, &sendto_addr, &port) == STS_SUCCESS)) {
      DEBUGC(DBCLASS_PROXY, "proxy_response: have outbound proxy %s:%i",
             utils_inet_ntoa(sendto_addr), port);
   /*
    * Route present?
    * If so, fetch address from topmost Route: header and remove it.
    */
   } else if ((type == RESTYP_OUTGOING) && 
              (response->routes && !osip_list_eol(response->routes, 0))) {
      sts=route_determine_nexthop(ticket, &sendto_addr, &port);
      if (sts == STS_FAILURE) {
         DEBUGC(DBCLASS_PROXY, "proxy_response: route_determine_nexthop failed");
         return STS_FAILURE;
      }
      DEBUGC(DBCLASS_PROXY, "proxy_response: have Route header to %s:%i",
             utils_inet_ntoa(sendto_addr), port);
   } else {
      /* get target address and port from VIA header */
      via = (osip_via_t *) osip_list_get (response->vias, 0);
      if (via == NULL) {
         ERROR("proxy_response: list_get via failed");
         return STS_FAILURE;
      }

      sts = get_ip_by_host(via->host, &sendto_addr);
      if (sts == STS_FAILURE) {
         DEBUGC(DBCLASS_PROXY, "proxy_response: cannot resolve VIA [%s]",
                via->host);
         return STS_FAILURE;
      }

      if (via->port) {
         port=atoi(via->port);
      } else {
         port=SIP_PORT;
      }
   }

   sts = sip_message_to_str(response, &buffer, &buflen);
   if (sts != 0) {
      ERROR("proxy_response: sip_message_to_str failed");
      return STS_FAILURE;
   }

   sipsock_send(sendto_addr, port, ticket->protocol,
                buffer, buflen); 
   osip_free (buffer);
   return STS_SUCCESS;
}
Exemplo n.º 4
0
int
__osip_quoted_string_set (const char *name, const char *str, char **result, const char **next)
{
  *next = str;
  if (*result != NULL)
    return OSIP_SUCCESS;        /* already parsed */
  *next = NULL;
  while ((' ' == *str) || ('\t' == *str) || (',' == *str))
    if (*str)
      str++;
    else
      return OSIP_SYNTAXERROR;  /* bad header format */

  if (osip_strncasecmp (name, str, strlen (name)) == 0) {
    const char *quote1;
    const char *quote2;
    const char *tmp;
    const char *hack = strchr (str, '=');

    if (hack == NULL)
      return OSIP_SYNTAXERROR;

    while (' ' == *(hack - 1))  /* get rid of extra spaces */
      hack--;
    if ((size_t) (hack - str) != strlen (name)) {
      *next = str;
      return OSIP_SUCCESS;
    }

    quote1 = __osip_quote_find (str);
    if (quote1 == NULL)
      return OSIP_SYNTAXERROR;  /* bad header format... */
    quote2 = __osip_quote_find (quote1 + 1);
    if (quote2 == NULL)
      return OSIP_SYNTAXERROR;  /* bad header format... */
    if (quote2 - quote1 == 1) {
      /* this is a special case! The quote contains nothing! */
      /* example:   Digest opaque="",cnonce=""               */
      /* in this case, we just forget the parameter... this  */
      /* this should prevent from user manipulating empty    */
      /* strings */
      tmp = quote2 + 1;         /* next element start here */
      for (; *tmp == ' ' || *tmp == '\t'; tmp++) {
      }
      for (; *tmp == '\n' || *tmp == '\r'; tmp++) {
      }                         /* skip LWS */
      *next = NULL;
      if (*tmp == '\0')         /* end of header detected */
        return OSIP_SUCCESS;
      if (*tmp != '\t' && *tmp != ' ')
        /* LWS here ? */
        *next = tmp;
      else {                    /* it is: skip it... */
        for (; *tmp == ' ' || *tmp == '\t'; tmp++) {
        }
        if (*tmp == '\0')       /* end of header detected */
          return OSIP_SUCCESS;
        *next = tmp;
      }
      return OSIP_SUCCESS;
    }
    *result = (char *) osip_malloc (quote2 - quote1 + 3);
    if (*result == NULL)
      return OSIP_NOMEM;
    osip_strncpy (*result, quote1, quote2 - quote1 + 1);
    tmp = quote2 + 1;           /* next element start here */
    for (; *tmp == ' ' || *tmp == '\t'; tmp++) {
    }
    for (; *tmp == '\n' || *tmp == '\r'; tmp++) {
    }                           /* skip LWS */
    *next = NULL;
    if (*tmp == '\0')           /* end of header detected */
      return OSIP_SUCCESS;
    if (*tmp != '\t' && *tmp != ' ')
      /* LWS here ? */
      *next = tmp;
    else {                      /* it is: skip it... */
      for (; *tmp == ' ' || *tmp == '\t'; tmp++) {
      }
      if (*tmp == '\0')         /* end of header detected */
        return OSIP_SUCCESS;
      *next = tmp;
    }
  }
  else
    *next = str;                /* wrong header asked! */
  return OSIP_SUCCESS;
}
Exemplo n.º 5
0
int
__osip_token_set (const char *name, const char *str, char **result, const char **next)
{
  const char *beg;
  const char *tmp;

  *next = str;
  if (*result != NULL)
    return OSIP_SUCCESS;        /* already parsed */
  *next = NULL;

  beg = strchr (str, '=');
  if (beg == NULL)
    return OSIP_SYNTAXERROR;    /* bad header format... */

  if (strlen (str) < 6)
    return OSIP_SUCCESS;        /* end of header... */

  while ((' ' == *str) || ('\t' == *str) || (',' == *str))
    if (*str)
      str++;
    else
      return OSIP_SYNTAXERROR;  /* bad header format */

  if (osip_strncasecmp (name, str, strlen (name)) == 0) {
    const char *end;

    end = strchr (str, ',');
    if (end == NULL)
      end = str + strlen (str); /* This is the end of the header */

    if (end - beg < 2)
      return OSIP_SYNTAXERROR;
    *result = (char *) osip_malloc (end - beg);
    if (*result == NULL)
      return OSIP_NOMEM;
    osip_clrncpy (*result, beg + 1, end - beg - 1);

    /* make sure the element does not contain more parameter */
    tmp = (*end) ? (end + 1) : end;
    for (; *tmp == ' ' || *tmp == '\t'; tmp++) {
    }
    for (; *tmp == '\n' || *tmp == '\r'; tmp++) {
    }                           /* skip LWS */
    *next = NULL;
    if (*tmp == '\0')           /* end of header detected */
      return OSIP_SUCCESS;
    if (*tmp != '\t' && *tmp != ' ')
      /* LWS here ? */
      *next = tmp;
    else {                      /* it is: skip it... */
      for (; *tmp == ' ' || *tmp == '\t'; tmp++) {
      }
      if (*tmp == '\0')         /* end of header detected */
        return OSIP_SUCCESS;
      *next = tmp;
    }
  }
  else
    *next = str;                /* next element start here */
  return OSIP_SUCCESS;
}
Exemplo n.º 6
0
static int
osip_body_parse_header (osip_body_t * body,
			const char *start_of_osip_body_header,
			const char **next_body)
{
  const char *start_of_line;
  const char *end_of_line;
  const char *colon_index;
  char *hname;
  char *hvalue;
  int i;

  *next_body = NULL;
  start_of_line = start_of_osip_body_header;
  for (;;)
    {
      i = __osip_find_next_crlf (start_of_line, &end_of_line);
      if (i == -1)
	return -1;		/* error case: no end of body found */

      /* find the headere name */
      colon_index = strchr (start_of_line, ':');
      if (colon_index == NULL)
	return -1;		/* this is also an error case */

      if (colon_index - start_of_line + 1 < 2)
	return -1;
      hname = (char *) osip_malloc (colon_index - start_of_line + 1);
      if (hname == NULL)
	return -1;
      osip_strncpy (hname, start_of_line, colon_index - start_of_line);
      osip_clrspace (hname);

      if ((end_of_line - 2) - colon_index < 2)
	return -1;
      hvalue = (char *) osip_malloc ((end_of_line - 2) - colon_index);
      if (hvalue == NULL)
	{
	  osip_free (hname);
	  return -1;
	}
      osip_strncpy (hvalue, colon_index + 1,
		    (end_of_line - 2) - colon_index - 1);
      osip_clrspace (hvalue);

      /* really store the header in the sip structure */
      if (osip_strncasecmp (hname, "content-type", 12) == 0)
	i = osip_body_set_contenttype (body, hvalue);
      else
	i = osip_body_set_header (body, hname, hvalue);
      osip_free (hname);
      osip_free (hvalue);
      if (i == -1)
	return -1;

      if (strncmp (end_of_line, CRLF, 2) == 0
	  || strncmp (end_of_line, "\n", 1) == 0
	  || strncmp (end_of_line, "\r", 1) == 0)
	{
	  *next_body = end_of_line;
	  return 0;
	}
      start_of_line = end_of_line;
    }
}
Exemplo n.º 7
0
int ice_sound_send_stun_request(RtpSession *session, struct CandidatePair *remote_candidates, int round)
{
	int roll=250;
#if 0
    /* in "passive" mode (UA not behind a NATor behind a full cone NAT),
    wait a few delay before sending the first STUN request:
    this help to traverse */
    if (session->setup_passive>0)
    {
        return 0;
    }
#endif

	if (remote_candidates==NULL)
		return 0;

	if (round>500)
		roll=2*roll;

    if (round%roll==50)
    {
        int pos;

#if 0
        /* do this only with application that support this */
        if (osip_strncasecmp(remote_useragent, "linphone/", 8)!=0)
        {
            /* use stun only with linphone to linphone softphone */
            return 0;
        }
#endif

        for (pos=0;pos<10 && remote_candidates[pos].remote_candidate.ipaddr[0]!='\0';pos++)
        {
            int media_socket = rtp_session_get_rtp_socket(session);
            StunAddress4 stunServerAddr;
            StunAtrString username;
            StunAtrString password;
            bool res;
            int  pad_size;

            struct CandidatePair *cand_pair = &remote_candidates[pos]; 
            username.sizeValue = 0;
            password.sizeValue = 0;

            /* set username to L3:1:R2:1 */
            snprintf(username.value, sizeof(username.value), "%s:%i:%s:%i",
                cand_pair->local_candidate.candidate_id,
                1,
                cand_pair->remote_candidate.candidate_id,
                1);
            username.sizeValue = (UInt16)strlen(username.value);
            pad_size = username.sizeValue % 4;

            username.value[username.sizeValue]='\0';
            username.value[username.sizeValue+1]='\0';
            username.value[username.sizeValue+2]='\0';
            username.value[username.sizeValue+3]='\0';

            username.sizeValue = username.sizeValue + 4 - pad_size;

            snprintf(password.value, sizeof(password.value), "%s",
                cand_pair->remote_candidate.password);
            password.sizeValue = (UInt16)strlen(password.value);

#if 0
            pad_size = password.sizeValue%4;
            password.value[password.sizeValue]='\0';
            password.value[password.sizeValue+1]='\0';
            password.value[password.sizeValue+2]='\0';
            password.value[password.sizeValue+3]='\0';
            password.sizeValue = password.sizeValue + pad_size;
#endif

            res = stunParseServerName(cand_pair->remote_candidate.ipaddr,
                &stunServerAddr);
            if ( res == true )
            {
                stunServerAddr.port = cand_pair->remote_candidate.port;
                ice_sendtest(media_socket, &stunServerAddr, &username, &password, 1, 0/*false*/,
                    &(cand_pair->tid));
            }
        }
    }

    return 0;
}
Exemplo n.º 8
0
int
__osip_nict_init (osip_nict_t ** nict, osip_t * osip, osip_message_t * request)
{
  osip_route_t *route;
  int i;
  time_t now;

  OSIP_TRACE (osip_trace
	      (__FILE__, __LINE__, OSIP_INFO2, NULL,
	       "allocating NICT context\n"));

  *nict = (osip_nict_t *) osip_malloc (sizeof (osip_nict_t));
  if (*nict == NULL)
    return -1;
  now = time (NULL);
#ifndef DISABLE_MEMSET
  memset (*nict, 0, sizeof (osip_nict_t));
#else
  (*ict)->destination = NULL;
#endif
  /* for REQUEST retransmissions */
  {
    osip_via_t *via;
    char *proto;

    i = osip_message_get_via (request, 0, &via);	/* get top via */
    if (i != 0)
      goto ii_error_1;
    proto = via_get_protocol (via);
    if (proto == NULL)
      goto ii_error_1;

    i = osip_strncasecmp (proto, "TCP", 3);
    if (i != 0)
      {				/* for other reliable protocol than TCP, the timer
				   must be desactived by the external application */
	(*nict)->timer_e_length = DEFAULT_T1;
	(*nict)->timer_e_start = now;	/* started */

	(*nict)->timer_k_length = DEFAULT_T4;
	(*nict)->timer_k_start = -1;	/* not started */
      }
    else
      {				/* TCP is used: */
	(*nict)->timer_e_length = -1;	/* E is not ACTIVE */
	(*nict)->timer_e_start = -1;

	(*nict)->timer_k_length = 0;	/* MUST do the transition immediatly */
	(*nict)->timer_k_start = -1;	/* not started */
      }
  }

  /* for PROXY, the destination MUST be set by the application layer,
     this one may not be correct. */
  osip_message_get_route (request, 0, &route);
  if (route != NULL)
    {
      int port = 5060;

      if (route->url->port != NULL)
	port = osip_atoi (route->url->port);
      osip_nict_set_destination ((*nict), osip_strdup (route->url->host), port);
    }
  else
    (*nict)->port = 5060;

  (*nict)->timer_f_length = 64 * DEFAULT_T1;
  (*nict)->timer_f_start = now;	/* started */

  /* Oups! a Bug! */
  /*  (*nict)->port  = 5060; */

  return 0;

ii_error_1:
  osip_free (*nict);
  return -1;
}
Exemplo n.º 9
0
int
osip_message_set_multiple_header (osip_message_t * sip, char *hname, char *hvalue)
{
  int i;
  char *ptr, *p;                /* current location of the search */
  char *comma;                  /* This is the separator we are elooking for */
  char *beg;                    /* beg of a header */
  char *end;                    /* end of a header */
  int inquotes, inuri;          /* state for inside/outside of double-qoutes or URI */
  size_t hname_len;

  /* Find header based upon lowercase comparison */
  osip_tolower (hname);

  if (hvalue == NULL) {
    i = osip_message_set__header (sip, hname, hvalue);
    if (i != 0)
      return i;
    return OSIP_SUCCESS;
  }

  ptr = hvalue;
  comma = strchr (ptr, ',');

  hname_len = strlen (hname);

  if (comma == NULL || (hname_len == 4 && strncmp (hname, "date", 4) == 0)
      || (hname_len == 1 && strncmp (hname, "t", 1) == 0)
      || (hname_len == 2 && strncmp (hname, "to", 2) == 0)
      || (hname_len == 1 && strncmp (hname, "f", 1) == 0)
      || (hname_len == 4 && strncmp (hname, "from", 4) == 0)
      || (hname_len == 1 && strncmp (hname, "i", 1) == 0)
      || (hname_len == 7 && strncmp (hname, "call-id", 7) == 0)
      || (hname_len == 4 && strncmp (hname, "cseq", 4) == 0)
      || (hname_len == 1 && strncmp (hname, "s", 1) == 0)
      || (hname_len == 7 && strncmp (hname, "subject", 7) == 0)
      || (hname_len == 7 && strncmp (hname, "expires", 7) == 0)
      || (hname_len == 6 && strncmp (hname, "server", 6) == 0)
      || (hname_len == 10 && strncmp (hname, "user-agent", 10) == 0)
      || (hname_len == 16 && strncmp (hname, "www-authenticate", 16) == 0)
      || (hname_len == 19 && strncmp (hname, "authentication-info", 19) == 0)
      || (hname_len == 18 && strncmp (hname, "proxy-authenticate", 18) == 0)
      || (hname_len == 19 && strncmp (hname, "proxy-authorization", 19) == 0)
      || (hname_len == 25 && strncmp (hname, "proxy-authentication-info", 25) == 0)
      || (hname_len == 12 && strncmp (hname, "organization", 12) == 0)
      || (hname_len == 13 && strncmp (hname, "authorization", 13) == 0)
      || (hname_len == 1 && strncmp (hname, "r", 1) == 0) /* refer-to */
      || (hname_len == 8 && strncmp (hname, "refer-to", 8) == 0)
      || (hname_len == 1 && strncmp (hname, "b", 1) == 0) /* referred-by */
      || (hname_len == 11 && strncmp (hname, "referred-by", 11) == 0))
    /* there is no multiple header! likely      */
    /* to happen most of the time...            */
    /* or hname is a TEXT-UTF8-TRIM and may     */
    /* contain a comma. this is not a separator */
    /* THIS DOES NOT WORK FOR UNKNOWN HEADER!!!! */
  {
    i = osip_message_set__header (sip, hname, hvalue);
    if (i != 0)
      return i;
    return OSIP_SUCCESS;
  }

  beg = hvalue;
  inquotes = 0;
  inuri = 0;
  /* Seach for a comma that is not within quotes or a URI */
  for (;; ptr++)
  {
    switch (*ptr)
    {
    case '"':
      /* Check that the '"' is not escaped */
      for (i = 0, p = ptr; p >= beg && *p == '\\'; p--, i++);
      if (i % 2 == 0)
        inquotes = !inquotes; /* the '"' was not escaped */
      break;

    case '<':
      if (!inquotes)
      {
        if (!inuri)
        {
          if((osip_strncasecmp(ptr+1, "sip:", 4) == 0
              || osip_strncasecmp(ptr+1, "sips:", 5) == 0
              || osip_strncasecmp(ptr+1, "http:", 5) == 0
              || osip_strncasecmp(ptr+1, "https:", 6) == 0
              || osip_strncasecmp(ptr+1, "tel:", 4) == 0)
              && strchr(ptr, '>'))
            inuri = 1;
        }
	/*
	  else {
	  if we found such sequence: "<sip:" "<sip:" ">"
	  It might be a valid header containing data and not URIs.
	  Thus, we ignore inuri
	  }
	*/
      }
      break;

    case '>':
      if (!inquotes)
      {
        if (inuri)
          inuri = 0;
      }
      break;

    case '\0':
      /* we discard any validation we tried: no valid uri detected */
      inquotes=0;
      inuri=0;
    case ',':
      if (!inquotes && !inuri)
      {
        char *avalue;

        if (beg[0] == '\0')
          return OSIP_SUCCESS; /* empty header */

        end = ptr;
        if (end - beg + 1 < 2)
	  {
	    beg=end+1;
	    break; /* skip empty header */
	  }
        avalue = (char *) osip_malloc (end - beg + 1);
        if (avalue==NULL)
          return OSIP_NOMEM;
        osip_clrncpy (avalue, beg, end - beg);
        /* really store the header in the sip structure */
        i = osip_message_set__header (sip, hname, avalue);
        osip_free (avalue);
        if (i != 0)
          return i;
        beg = end + 1;
      }
      if (*ptr == '\0')
        return OSIP_SUCCESS;
      break;

    default:
      break;
    }
  }
}
Exemplo n.º 10
0
/* return -1 on error */
int
osip_uri_parse (osip_uri_t * url, const char *buf)
{
  char *username;
  char *password;
  char *host;
  const char *port;
  const char *params;
  const char *headers;
  const char *tmp;

  /* basic tests */
  if (buf == NULL || buf[0] == '\0')
    return -1;

  tmp = strchr (buf, ':');
  if (tmp == NULL)
    return -1;

  if (tmp - buf < 2)
    return -1;
  url->scheme = (char *) osip_malloc (tmp - buf + 1);
  if (url->scheme == NULL)
    return -1;
  osip_strncpy (url->scheme, buf, tmp - buf);

  if (strlen (url->scheme) < 3 ||
      (0 != osip_strncasecmp (url->scheme, "sip", 3)
       && 0 != osip_strncasecmp (url->scheme, "sips", 4)))
    {                           /* Is not a sipurl ! */
      size_t i = strlen (tmp + 1);

      if (i < 2)
        return -1;
      url->string = (char *) osip_malloc (i + 1);
      if (url->string == NULL)
        return -1;
      osip_strncpy (url->string, tmp + 1, i);
      return 0;
    }

  /*  law number 1:
     if ('?' exists && is_located_after '@')
     or   if ('?' exists && '@' is not there -no username-)
     =====>  HEADER_PARAM EXIST
     =====>  start at index(?)
     =====>  end at the end of url
   */

  /* find the beginning of host */
  username = strchr (buf, ':');
  /* if ':' does not exist, the url is not valid */
  if (username == NULL)
    return -1;

  host = strchr (buf, '@');

  if (host == NULL)
    host = username;
  else if (username[1] == '@')  /* username is empty */
    host = username + 1;
  else
    /* username exists */
    {
      password = next_separator (username + 1, ':', '@');
      if (password == NULL)
        password = host;
      else
        /* password exists */
        {
          if (host - password < 2)
            return -1;
          url->password = (char *) osip_malloc (host - password);
          if (url->password == NULL)
            return -1;
          osip_strncpy (url->password, password + 1, host - password - 1);
          __osip_uri_unescape (url->password);
        }
      if (password - username < 2)
        return -1;
      {
        url->username = (char *) osip_malloc (password - username);
        if (url->username == NULL)
          return -1;
        osip_strncpy (url->username, username + 1, password - username - 1);
        __osip_uri_unescape (url->username);
      }
    }


  /* search for header after host */
  headers = strchr (host, '?');

  if (headers == NULL)
    headers = buf + strlen (buf);
  else
    /* headers exist */
    osip_uri_parse_headers (url, headers);


  /* search for params after host */
  params = strchr (host, ';');  /* search for params after host */
  if (params == NULL)
    params = headers;
  else
    /* params exist */
    {
      char *tmpbuf;

      if (headers - params + 1 < 2)
        return -1;
      tmpbuf = osip_malloc (headers - params + 1);
      if (tmpbuf == NULL)
        return -1;
      tmpbuf = osip_strncpy (tmpbuf, params, headers - params);
      osip_uri_parse_params (url, tmpbuf);
      osip_free (tmpbuf);
    }

  port = params - 1;
  while (port > host && *port != ']' && *port != ':')
    port--;
  if (*port == ':')
    {
      if (host == port)
        port = params;
      else
        {
          if ((params - port < 2) || (params - port > 8))
            return -1;          /* error cases */
          url->port = (char *) osip_malloc (params - port);
          if (url->port == NULL)
            return -1;
          osip_clrncpy (url->port, port + 1, params - port - 1);
        }
  } else
    port = params;
  /* adjust port for ipv6 address */
  tmp = port;
  while (tmp > host && *tmp != ']')
    tmp--;
  if (*tmp == ']')
    {
      port = tmp;
      while (host < port && *host != '[')
        host++;
      if (host >= port)
        return -1;
    }

  if (port - host < 2)
    return -1;
  url->host = (char *) osip_malloc (port - host);
  if (url->host == NULL)
    return -1;
  osip_clrncpy (url->host, host + 1, port - host - 1);

  return 0;
}
Exemplo n.º 11
0
int
eXosip_get_naptr(char *domain, char *protocol, char *srv_record, int max_length)
{
	querybuf answer;			/* answer buffer from nameserver */
	int n;
	char zone[1024];
	int ancount, qdcount;		/* answer count and query count */
	HEADER *hp;					/* answer buffer header */
	char hostbuf[256];
	unsigned char *msg, *eom, *cp;	/* answer buffer positions */
	int dlen, type, aclass;
	long ttl;
	int answerno;
	char tr[100];

	memset(srv_record, 0, max_length);
	if (domain == NULL || protocol == NULL)
		return OSIP_BADPARAMETER;

	if (strlen(domain) + strlen(protocol) > 1000)
		return OSIP_BADPARAMETER;

	if (strlen(protocol) >= 100)
		return OSIP_BADPARAMETER;
	snprintf(tr, 100, protocol);
	osip_tolower(tr);

	snprintf(zone, 1024, "%s", domain);

	OSIP_TRACE(osip_trace
			   (__FILE__, __LINE__, OSIP_INFO2, NULL,
				"About to ask for '%s IN NAPTR\n", zone));

	n = res_query(zone, C_IN, T_NAPTR, (unsigned char *) &answer, sizeof(answer));

	if (n < (int) sizeof(HEADER)) {
		return OSIP_UNKNOWN_HOST;
	}

	/* browse message and search for DNS answers part */
	hp = (HEADER *) & answer;
	qdcount = ntohs(hp->qdcount);
	ancount = ntohs(hp->ancount);

	msg = (unsigned char *) (&answer);
	eom = (unsigned char *) (&answer) + n;
	cp = (unsigned char *) (&answer) + sizeof(HEADER);

	while (qdcount-- > 0 && cp < eom) {
		n = dn_expand(msg, eom, cp, (char *) hostbuf, 256);
		if (n < 0) {
			OSIP_TRACE(osip_trace
					   (__FILE__, __LINE__, OSIP_ERROR, NULL,
						"Invalid SRV record answer for '%s': bad format\n", zone));
			return OSIP_UNDEFINED_ERROR;
		}
		cp += n + QFIXEDSZ;
	}


	/* browse DNS answers */
	answerno = 0;

	/* loop through the answer buffer and extract SRV records */
	while (ancount-- > 0 && cp < eom) {
		int len;

		typedef struct {
			unsigned short order;
			unsigned short pref;
			char flag[256];
			char service[1024];
			char regexp[1024];
			char replacement[1024];
		} osip_naptr_t;

		osip_naptr_t anaptr;

		n = dn_expand(msg, eom, cp, (char *) hostbuf, 256);
		if (n < 0) {
			OSIP_TRACE(osip_trace
					   (__FILE__, __LINE__, OSIP_ERROR, NULL,
						"Invalid NAPTR answer for '%s': bad format\n", zone));
			return OSIP_UNDEFINED_ERROR;
		}

		cp += n;

#if defined(__NetBSD__) || defined(__OpenBSD__) ||\
defined(OLD_NAMESER) || defined(__FreeBSD__)
		type = _get_short(cp);
		cp += sizeof(u_short);
#elif defined(__APPLE_CC__)
		GETSHORT(type, cp);
#else
		NS_GET16(type, cp);
#endif

#if defined(__NetBSD__) || defined(__OpenBSD__) ||\
defined(OLD_NAMESER) || defined(__FreeBSD__)
		aclass = _get_short(cp);
		cp += sizeof(u_short);
#elif defined(__APPLE_CC__)
		GETSHORT(aclass, cp);
#else
		NS_GET16(aclass, cp);
#endif

#if defined(__NetBSD__) || defined(__OpenBSD__) ||\
defined(OLD_NAMESER) || defined(__FreeBSD__)
		ttl = _get_long(cp);
		cp += sizeof(u_long);
#elif defined(__APPLE_CC__)
		GETLONG(ttl, cp);
#else
		NS_GET32(ttl, cp);
#endif

#if defined(__NetBSD__) || defined(__OpenBSD__) ||\
defined(OLD_NAMESER) || defined(__FreeBSD__)
		dlen = _get_short(cp);
		cp += sizeof(u_short);
#elif defined(__APPLE_CC__)
		GETSHORT(dlen, cp);
#else
		NS_GET16(dlen, cp);
#endif

		if (type != T_NAPTR) {
			cp += dlen;
			continue;
		}

		memset(&anaptr, 0, sizeof(osip_naptr_t));

		memcpy((void *) &anaptr.order, cp, 2);
		anaptr.order = ntohs(anaptr.order);	/*((unsigned short)cp[0] << 8) | ((unsigned short)cp[1]); */
		cp += sizeof(unsigned short);
		memcpy((void *) &anaptr.pref, cp, 2);
		anaptr.pref = ntohs(anaptr.pref);	/* ((unsigned short)cp[0] << 8) | ((unsigned short)cp[1]); */
		cp += sizeof(unsigned short);

		len = *cp;
		cp++;
		strncpy(anaptr.flag, (char *) cp, len);
		anaptr.flag[len] = '\0';
		cp += len;

		len = *cp;
		cp++;
		strncpy(anaptr.service, (char *) cp, len);
		anaptr.service[len] = '\0';
		cp += len;

		len = *cp;
		cp++;
		strncpy(anaptr.regexp, (char *) cp, len);
		anaptr.regexp[len] = '\0';
		cp += len;

		n = dn_expand(msg, eom, cp, anaptr.replacement, 1024 - 1);

		if (n < 0)
			break;
		cp += n;

		OSIP_TRACE(osip_trace
				   (__FILE__, __LINE__, OSIP_INFO2, NULL,
					"NAPTR %s ->%i/%i/%s/%s/%s/%s\n",
					zone, anaptr.order, anaptr.pref, anaptr.flag,
					anaptr.service, anaptr.regexp, anaptr.replacement));

		if (osip_strncasecmp(tr, "udp", 4) == 0
			&& osip_strncasecmp(anaptr.service, "SIP+D2U", 8) == 0) {
			snprintf(srv_record, max_length, "%s", anaptr.replacement);
			return OSIP_SUCCESS;
		} else if (osip_strncasecmp(tr, "tcp", 4) == 0
				   && osip_strncasecmp(anaptr.service, "SIP+D2T", 8) == 0) {
			snprintf(srv_record, max_length, "%s", anaptr.replacement);
			return OSIP_SUCCESS;
		} else if (osip_strncasecmp(tr, "udp-tls", 8) == 0
				   && osip_strncasecmp(anaptr.service, "SIPS+D2U", 9) == 0) {
			snprintf(srv_record, max_length, "%s", anaptr.replacement);
			return OSIP_SUCCESS;
		} else if (osip_strncasecmp(tr, "tls", 4) == 0
				   && osip_strncasecmp(anaptr.service, "SIPS+D2T", 9) == 0) {
			snprintf(srv_record, max_length, "%s", anaptr.replacement);
			return OSIP_SUCCESS;
		} else if (osip_strncasecmp(tr, "sctp", 5) == 0
				   && osip_strncasecmp(anaptr.service, "SIP+D2S", 8) == 0) {
			snprintf(srv_record, max_length, "%s", anaptr.replacement);
			return OSIP_SUCCESS;
		}

		answerno++;
	}

	if (answerno == 0)
		return OSIP_UNKNOWN_HOST;

	OSIP_TRACE(osip_trace
			   (__FILE__, __LINE__, OSIP_INFO2, NULL,
				"protocol: %s is not supported by domain %s\n", protocol, domain));
	return OSIP_SUCCESS;
}
Exemplo n.º 12
0
int
eXosip_get_naptr(char *domain, char *protocol, char *srv_record, int max_length)
{
	char zone[1024];

	PDNS_RECORD answer, tmp;	/* answer buffer from nameserver */

	int n;

	char tr[100];

	memset(srv_record, 0, max_length);
	if (domain == NULL || protocol == NULL)
		return OSIP_BADPARAMETER;

	if (strlen(domain) + strlen(protocol) > 1000)
		return OSIP_BADPARAMETER;

	if (strlen(protocol) >= 100)
		return OSIP_BADPARAMETER;
	snprintf(tr, 100, protocol);
	osip_tolower(tr);

	snprintf(zone, 1024, "%s", domain);

	OSIP_TRACE(osip_trace
			   (__FILE__, __LINE__, OSIP_INFO2, NULL,
				"About to ask for '%s NAPTR'\n", zone));

	if (DnsQuery(zone, DNS_TYPE_NAPTR, DNS_QUERY_STANDARD, NULL, &answer, NULL) !=
		0) {
		return OSIP_UNKNOWN_HOST;
	}

	n = 0;
	for (tmp = answer; tmp != NULL; tmp = tmp->pNext) {
		char *buf = (char *) &tmp->Data;

		int len;
		OSVERSIONINFOEX ovi;
		typedef struct {
			unsigned short order;
			unsigned short pref;
			char flag[256];
			char service[1024];
			char regexp[1024];
			char replacement[1024];
		} osip_naptr_t;

		osip_naptr_t anaptr;

		if (tmp->wType != DNS_TYPE_NAPTR)
			continue;

		memset(&anaptr, 0, sizeof(osip_naptr_t));
		memset(&ovi, 0, sizeof(ovi));
		ovi.dwOSVersionInfoSize = sizeof(ovi);
		GetVersionEx((LPOSVERSIONINFO) & ovi);

		/* Minimum: client: Windows 2000 Professional */
		/* Minimum: server: Windows 2000 Server */
		OSIP_TRACE(osip_trace
				   (__FILE__, __LINE__, OSIP_INFO2, NULL,
					"check OS support for NAPTR: %i %i %i\n",
					ovi.dwMajorVersion, ovi.dwMinorVersion, ovi.dwBuildNumber));
		if (ovi.dwMajorVersion > 5) {

#if (_WIN32_WINNT >= 0x0600)
			/* RUN only on Vista? */
			/* compile starting from SDK 6.0A? even on XP... */
			anaptr.order = tmp->Data.NAPTR.wOrder;
			anaptr.pref = tmp->Data.NAPTR.wPreference;
			strncpy(anaptr.flag, tmp->Data.NAPTR.pFlags, sizeof(anaptr.flag) - 1);
			strncpy(anaptr.service, tmp->Data.NAPTR.pService,
					sizeof(anaptr.service) - 1);
			strncpy(anaptr.regexp, tmp->Data.NAPTR.pRegularExpression,
					sizeof(anaptr.regexp) - 1);
			strncpy(anaptr.replacement, tmp->Data.NAPTR.pReplacement,
					sizeof(anaptr.replacement) - 1);

#endif
		}

		else {
			memcpy((void *) &anaptr.order, buf, 2);
			anaptr.order = ntohs(anaptr.order);	/* ((unsigned short)buf[0] << 8) | ((unsigned short)buf[1]); */
			buf += sizeof(unsigned short);
			memcpy((void *) &anaptr.pref, buf, 2);
			anaptr.pref = ntohs(anaptr.pref);	/* ((unsigned short)buf[0] << 8) | ((unsigned short)buf[1]); */
			buf += sizeof(unsigned short);

			len = *buf;
			if (len < 0 || len > 255)
				break;
			buf++;
			strncpy(anaptr.flag, buf, len);
			anaptr.flag[len] = '\0';
			buf += len;

			len = *buf;
			if (len < 0 || len > 1023)
				break;
			buf++;
			strncpy(anaptr.service, buf, len);
			anaptr.service[len] = '\0';
			buf += len;

			len = *buf;
			if (len < 0 || len > 1023)
				break;
			buf++;
			strncpy(anaptr.regexp, buf, len);
			anaptr.regexp[len] = '\0';
			buf += len;

			len =
				_eX_dn_expand((char *) &tmp->Data,
							  ((char *) &tmp->Data) + tmp->wDataLength, buf,
							  anaptr.replacement, 1024 - 1);

			if (len < 0)
				break;
			buf += len;
		}

		OSIP_TRACE(osip_trace
				   (__FILE__, __LINE__, OSIP_INFO2, NULL,
					"NAPTR %s ->%i/%i/%s/%s/%s/%s\n",
					zone, anaptr.order, anaptr.pref, anaptr.flag,
					anaptr.service, anaptr.regexp, anaptr.replacement));

		if (osip_strncasecmp(tr, "udp", 4) == 0
			&& osip_strncasecmp(anaptr.service, "SIP+D2U", 8) == 0) {
			snprintf(srv_record, max_length, "%s", anaptr.replacement);
			DnsRecordListFree(answer, DnsFreeRecordList);
			return OSIP_SUCCESS;
		} else if (osip_strncasecmp(tr, "tcp", 4) == 0
				   && osip_strncasecmp(anaptr.service, "SIP+D2T", 8) == 0) {
			snprintf(srv_record, max_length, "%s", anaptr.replacement);
			DnsRecordListFree(answer, DnsFreeRecordList);
			return OSIP_SUCCESS;
		} else if (osip_strncasecmp(tr, "udp-tls", 8) == 0
				   && osip_strncasecmp(anaptr.service, "SIPS+D2U", 9) == 0) {
			snprintf(srv_record, max_length, "%s", anaptr.replacement);
			DnsRecordListFree(answer, DnsFreeRecordList);
			return OSIP_SUCCESS;
		} else if (osip_strncasecmp(tr, "tls", 4) == 0
				   && osip_strncasecmp(anaptr.service, "SIPS+D2T", 9) == 0) {
			snprintf(srv_record, max_length, "%s", anaptr.replacement);
			DnsRecordListFree(answer, DnsFreeRecordList);
			return OSIP_SUCCESS;
		} else if (osip_strncasecmp(tr, "sctp", 5) == 0
				   && osip_strncasecmp(anaptr.service, "SIP+D2S", 8) == 0) {
			snprintf(srv_record, max_length, "%s", anaptr.replacement);
			DnsRecordListFree(answer, DnsFreeRecordList);
			return OSIP_SUCCESS;
		}

		n++;
	}

	DnsRecordListFree(answer, DnsFreeRecordList);

	if (n == 0)
		return OSIP_UNKNOWN_HOST;

	OSIP_TRACE(osip_trace
			   (__FILE__, __LINE__, OSIP_INFO2, NULL,
				"protocol: %s is not supported by domain %s\n", protocol, domain));
	return OSIP_SUCCESS;
}