Пример #1
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;
}
size_t
FileManager::_read(void *buf, size_t len)
{
	// starting point for crc computation
	uint8_t *start = reinterpret_cast<uint8_t *>(buf);

	if (_z_err == Z_DATA_ERROR || _z_err == Z_ERRNO) {
		return -1;
	}
	if (_z_err == Z_STREAM_END) {
		return 0;  // EOF
	}
	_stream->next_out = reinterpret_cast<uint8_t *>(buf);
	_stream->avail_out = len;

	int got;
	while (_stream->avail_out != 0) {
		if (!_compressed) {
			// Copy first the lookahead bytes
			uint32_t n = _stream->avail_in;
			if (n > _stream->avail_out)
				n = _stream->avail_out;
			if (n > 0) {
				memcpy(_stream->next_out, _stream->next_in, n);
				_stream->next_out  += n;
				_stream->next_in   += n;
				_stream->avail_out -= n;
				_stream->avail_in  -= n;
			}
			if (_stream->avail_out > 0) {
				got = _file->read(_stream->next_out,
				    _stream->avail_out);
				if (got == -1) {
					return(got);
				}
				_stream->avail_out -= got;
			}
			return(int)(len - _stream->avail_out);
		}

		if (_stream->avail_in == 0 && !_z_eof) {
			got = _file->read(_inbuf, Z_BUFSIZE);
			if (got <= 0)
				_z_eof = 1;

			_stream->avail_in = got;
			_stream->next_in = _inbuf;
		}

		_z_err = inflate(_stream, Z_NO_FLUSH);

		if (_z_err == Z_STREAM_END) {
			/* Check CRC and original size */
			_crc = crc32(_crc, start,(unsigned int)
			    (_stream->next_out - start));
			start = _stream->next_out;

			if (_get_long() != _crc ||
			    _get_long() != _stream->total_out) {
				_z_err = Z_DATA_ERROR;
			} else {
				/* Check for concatenated .gz files: */
				_check_header();
				if (_z_err == Z_OK) {
					inflateReset(_stream);
					_crc = crc32(0L, Z_NULL, 0);
				}
			}
		}
		if (_z_err != Z_OK || _z_eof)
			break;
	}

	_crc = crc32(_crc, start,(unsigned int)(_stream->next_out - start));

	return(int)(len - _stream->avail_out);
}
Пример #3
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;
}