int
osip_message_set_multiple_header(osip_message_t * sip, char *hname, char *hvalue)
{
	int i;
	char *ptr;					/* 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 */
	char *quote1;				/* first quote of a pair of quotes   */
	char *quote2;				/* second quuote of a pair of quotes */
	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 == 2 && strncmp(hname, "to", 2) == 0)
		|| (hname_len == 4 && strncmp(hname, "from", 4) == 0)
		|| (hname_len == 7 && strncmp(hname, "call-id", 7) == 0)
		|| (hname_len == 4 && strncmp(hname, "cseq", 4) == 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))
		/* 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;
	end = NULL;
	quote2 = NULL;
	while (comma != NULL) {
		quote1 = __osip_quote_find(ptr);
		if (quote1 != NULL) {
			quote2 = __osip_quote_find(quote1 + 1);
			if (quote2 == NULL)
				return OSIP_SYNTAXERROR;	/* quotes comes by pair */
			ptr = quote2 + 1;
		}

		if ((quote1 == NULL) || (quote1 > comma)) {
			/* We must search for the next comma which is not
			   within quotes! */
			end = comma;

			if (quote1 != NULL && quote1 > comma) {
				/* comma may be within the quotes */
				/* ,<sip:[email protected]>;methods=\"INVITE,BYE,OPTIONS,ACK,CANCEL\",<sip:[email protected]> */
				/* we want the next comma after the quotes */
				char *tmp_comma;
				char *tmp_quote1;
				char *tmp_quote2;

				tmp_quote1 = quote1;
				tmp_quote2 = quote2;
				tmp_comma = strchr(comma + 1, ',');
				while (1) {
					if (tmp_comma < tmp_quote1)
						break;	/* ok (before to quotes) */
					if (tmp_comma < tmp_quote2) {
						tmp_comma = strchr(tmp_quote2 + 1, ',');
					}
					tmp_quote1 = __osip_quote_find(tmp_quote2 + 1);
					if (tmp_quote1 == NULL)
						break;
					tmp_quote2 = __osip_quote_find(tmp_quote1 + 1);
					if (tmp_quote2 == NULL)
						break;	/* probably a malformed message? */
				}
				comma = tmp_comma;	/* this one is not enclosed within quotes */
			} else
				comma = strchr(comma + 1, ',');
			if (comma != NULL)
				ptr = comma + 1;

		} else if ((quote1 < comma) && (quote2 < comma)) {	/* quotes are located before the comma, */
			/* continue the search for next quotes  */
			ptr = quote2 + 1;
		} else if ((quote1 < comma) && (comma < quote2)) {	/* if comma is inside the quotes... */
			/* continue with the next comma.    */
			ptr = quote2 + 1;
			comma = strchr(ptr, ',');
			if (comma == NULL)
				/* this header last at the end of the line! */
			{					/* this one does not need an allocation... */
#if 0
				if (strlen(beg) < 2)
					return OSIP_SUCCESS;	/* empty header */
#else
				if (beg[0] == '\0' || beg[1] == '\0')
					return OSIP_SUCCESS;	/* empty header */
#endif
				osip_clrspace(beg);
				i = osip_message_set__header(sip, hname, beg);
				if (i != 0)
					return i;
				return OSIP_SUCCESS;
			}
		}

		if (end != NULL) {
			char *avalue;

			if (end - beg + 1 < 2)
				return OSIP_SYNTAXERROR;
			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;
			end = NULL;
			if (comma == NULL)
				/* this header last at the end of the line! */
			{					/* this one does not need an allocation... */
#if 0
				if (strlen(beg) < 2)
					return OSIP_SUCCESS;	/* empty header */
#else
				if (beg[0] == '\0' || beg[1] == '\0')
					return OSIP_SUCCESS;	/* empty header */
#endif
				osip_clrspace(beg);
				i = osip_message_set__header(sip, hname, beg);
				if (i != 0)
					return i;
				return OSIP_SUCCESS;
			}
		}
	}
	return OSIP_SYNTAXERROR;	/* if comma is NULL, we should have already return 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;
    }
  }
}
Beispiel #3
0
int
eXosip_get_srv_record(struct osip_srv_record *record, char *domain, char *protocol)
{
	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, pref, weight, port;
	long ttl;
	int answerno;
	char tr[100];

	memset(zone, 0, sizeof(zone));
	memset(record, 0, sizeof(struct osip_srv_record));

	if (domain == NULL || protocol == NULL)
		return OSIP_BADPARAMETER;

	if (eXosip.dns_capabilities <= 0)
		return OSIP_UNKNOWN_HOST;	/* disabled */

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

	if (strlen(protocol) >= 100)
		return OSIP_BADPARAMETER;
	snprintf(tr, 100, protocol);
	osip_tolower(tr);
	if (eXosip.dns_capabilities >= 2)
		n = eXosip_get_naptr(domain, protocol, zone, sizeof(zone) - 1);
	else
		n = -1;					/* avoid NAPTR */
	if (n == OSIP_SUCCESS && zone[0] == '\0') {
		/* protocol is not listed in NAPTR answer: not supported */
		return OSIP_UNKNOWN_HOST;
	}
	if (n != OSIP_SUCCESS) {
		snprintf(zone, sizeof(zone) - 1, "_sip._%s.%s", tr, domain);
		OSIP_TRACE(osip_trace
				   (__FILE__, __LINE__, OSIP_INFO2, NULL,
					"Using locally generated SRV record %s\n", zone));
	}

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

	n = res_query(zone, C_IN, T_SRV, (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) {
		struct osip_srv_entry *srventry;

		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;


#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_SRV) {
			cp += dlen;
			continue;
		}
#if defined(__NetBSD__) || defined(__OpenBSD__) ||\
defined(OLD_NAMESER) || defined(__FreeBSD__)
		pref = _get_short(cp);
		cp += sizeof(u_short);
#elif defined(__APPLE_CC__)
		GETSHORT(pref, cp);
#else
		NS_GET16(pref, cp);
#endif

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

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

		n = dn_expand(msg, eom, cp, (char *) hostbuf, 256);
		if (n < 0)
			break;
		cp += n;

		srventry = &record->srventry[answerno];
		snprintf(srventry->srv, sizeof(srventry->srv), "%s", hostbuf);

		srventry->priority = pref;
		srventry->weight = weight;
		if (weight)
			srventry->rweight = 1 + random() % (10000 * srventry->weight);
		else
			srventry->rweight = 0;
		srventry->port = port;

		OSIP_TRACE(osip_trace
				   (__FILE__, __LINE__, OSIP_INFO2, NULL,
					"SRV record %s IN SRV -> %s:%i/%i/%i/%i\n",
					zone, srventry->srv, srventry->port, srventry->priority,
					srventry->weight, srventry->rweight));

		answerno++;
		if (answerno == 10)
			break;
	}

	if (answerno == 0)
		return OSIP_UNKNOWN_HOST;
	osip_srv_record_sort(record, answerno);
	snprintf(record->name, sizeof(record->name), "%s", domain);
	return OSIP_SUCCESS;
}
Beispiel #4
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;
}
Beispiel #5
0
int
eXosip_get_srv_record(struct osip_srv_record *record, char *domain, char *protocol)
{
	char zone[1024];
	PDNS_RECORD answer, tmp;	/* answer buffer from nameserver */
	int n;
	char tr[100];

	memset(zone, 0, sizeof(zone));
	memset(record, 0, sizeof(struct osip_srv_record));

	if (domain == NULL || protocol == NULL)
		return OSIP_BADPARAMETER;

	if (eXosip.dns_capabilities <= 0)
		return OSIP_UNKNOWN_HOST;	/* disabled */

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

	if (strlen(protocol) >= 100)
		return OSIP_BADPARAMETER;
	snprintf(tr, 100, protocol);
	osip_tolower(tr);
	if (eXosip.dns_capabilities >= 2)
		n = eXosip_get_naptr(domain, protocol, zone, sizeof(zone) - 1);
	else
		n = -1;					/* avoid NAPTR */
	if (n == OSIP_SUCCESS && zone[0] == '\0') {
		/* protocol is not listed in NAPTR answer: not supported */
		return OSIP_UNKNOWN_HOST;
	}

	if (n != OSIP_SUCCESS) {
		if (osip_strcasecmp(tr, "TLS") == 0)
			snprintf(zone, sizeof(zone) - 1, "_sips._tcp.%s", domain);
		else if (osip_strcasecmp(tr, "DTLS") == 0)
			snprintf(zone, sizeof(zone) - 1, "_sips._udp.%s", domain);
		else
			snprintf(zone, sizeof(zone) - 1, "_sip._%s.%s", tr, domain);

		OSIP_TRACE(osip_trace
				   (__FILE__, __LINE__, OSIP_INFO2, NULL,
					"Using locally generated SRV record %s\n", zone));
	}

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

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

	n = 0;
	for (tmp = answer; tmp != NULL; tmp = tmp->pNext) {
		struct osip_srv_entry *srventry;

		DNS_SRV_DATA *data;

		if (tmp->wType != DNS_TYPE_SRV)
			continue;
		srventry = &record->srventry[n];
		data = &tmp->Data.SRV;
		snprintf(srventry->srv, sizeof(srventry->srv), "%s", data->pNameTarget);

		srventry->priority = data->wPriority;
		srventry->weight = data->wWeight;
		if (srventry->weight)
			srventry->rweight = 1 + rand() % (10000 * srventry->weight);
		else
			srventry->rweight = 0;
		srventry->port = data->wPort;

		OSIP_TRACE(osip_trace
				   (__FILE__, __LINE__, OSIP_INFO2, NULL,
					"SRV record %s IN SRV -> %s:%i/%i/%i/%i\n",
					zone, srventry->srv, srventry->port, srventry->priority,
					srventry->weight, srventry->rweight));

		n++;
		if (n == 10)
			break;
	}

	DnsRecordListFree(answer, DnsFreeRecordList);

	if (n == 0)
		return OSIP_UNKNOWN_HOST;
	osip_srv_record_sort(record, n);
	snprintf(record->name, sizeof(record->name), "%s", domain);
	return OSIP_SUCCESS;
}
Beispiel #6
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;
}