From f4ab414190953e7cb70d7844a382491fc6e1dc11 Mon Sep 17 00:00:00 2001 From: Michael Jerris Date: Thu, 12 Feb 2009 21:04:13 +0000 Subject: [PATCH] Tue Feb 10 08:11:37 CST 2009 Pekka Pessi * check_nua: use s2dns git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@11937 d0543943-73ff-0310-b7d9-9358b9ac24b2 --- libs/sofia-sip/libsofia-sip-ua/nua/test_s2.c | 480 +------------------ libs/sofia-sip/libsofia-sip-ua/nua/test_s2.h | 6 - 2 files changed, 8 insertions(+), 478 deletions(-) diff --git a/libs/sofia-sip/libsofia-sip-ua/nua/test_s2.c b/libs/sofia-sip/libsofia-sip-ua/nua/test_s2.c index 99c6db08fa..0cd616f892 100644 --- a/libs/sofia-sip/libsofia-sip-ua/nua/test_s2.c +++ b/libs/sofia-sip/libsofia-sip-ua/nua/test_s2.c @@ -37,6 +37,7 @@ #define TP_MAGIC_T struct tp_magic_s #include "test_s2.h" +#include "s2dns.h" #include #include @@ -45,6 +46,7 @@ #include #include #include +#include #include #include @@ -1058,471 +1060,6 @@ s2_setup_tport(char const * const *protocols, } } -/* ---------------------------------------------------------------------- */ -/* S2 DNS server */ - -#include - -extern uint16_t _sres_default_port; - -static int s2_dns_query(struct tester *s2, - su_wait_t *w, - su_wakeup_arg_t *arg); - -void s2_setup_dns(void) -{ - int n; - su_socket_t socket; - su_wait_t *wait; - su_sockaddr_t su[1]; - socklen_t sulen = sizeof su->su_sin; - - assert(s2->nua == NULL); assert(s2->root != NULL); - - memset(su, 0, sulen); - su->su_len = sulen; - su->su_family = AF_INET; - - /* su->su_port = htons(1053); */ - - socket = su_socket(su->su_family, SOCK_DGRAM, 0); - - n = bind(socket, &su->su_sa, sulen); assert(n == 0); - n = getsockname(socket, &su->su_sa, &sulen); assert(n == 0); - - _sres_default_port = ntohs(su->su_port); - - wait = s2->dns.wait; - n = su_wait_create(wait, socket, SU_WAIT_IN); assert(n == 0); - s2->dns.reg = su_root_register(s2->root, wait, s2_dns_query, NULL, 0); - assert(s2->dns.reg > 0); - s2->dns.socket = socket; -} - -static -struct s2_dns_response { - struct s2_dns_response *next; - uint16_t qlen, dlen; - struct m_header { - /* Header defined in RFC 1035 section 4.1.1 (page 26) */ - uint16_t mh_id; /* Query ID */ - uint16_t mh_flags; /* Flags */ - uint16_t mh_qdcount; /* Question record count */ - uint16_t mh_ancount; /* Answer record count */ - uint16_t mh_nscount; /* Authority records count */ - uint16_t mh_arcount; /* Additional records count */ - } header[1]; - uint8_t data[1500]; -} *zonedata; - -enum { - FLAGS_QR = (1 << 15), - FLAGS_QUERY = (0 << 11), - FLAGS_IQUERY = (1 << 11), - FLAGS_STATUS = (2 << 11), - FLAGS_OPCODE = (15 << 11), /* mask */ - FLAGS_AA = (1 << 10), /* */ - FLAGS_TC = (1 << 9), - FLAGS_RD = (1 << 8), - FLAGS_RA = (1 << 7), - - FLAGS_RCODE = (15 << 0), /* mask of return code */ - - FLAGS_OK = 0, /* No error condition. */ - FLAGS_FORMAT_ERR = 1, /* Server could not interpret query. */ - FLAGS_SERVER_ERR = 2, /* Server error. */ - FLAGS_NAME_ERR = 3, /* No domain name. */ - FLAGS_UNIMPL_ERR = 4, /* Not implemented. */ - FLAGS_AUTH_ERR = 5, /* Refused */ -}; - -uint32_t s2_dns_ttl = 3600; - -static int -s2_dns_query(struct tester *s2, - su_wait_t *w, - su_wakeup_arg_t *arg) -{ - union { - struct m_header header[1]; - uint8_t buffer[1500]; - } request; - ssize_t len; - - su_socket_t socket; - su_sockaddr_t su[1]; - socklen_t sulen = sizeof su; - uint16_t flags; - struct s2_dns_response *r; - size_t const hlen = sizeof r->header; - - (void)arg; - - socket = s2->dns.socket; - - len = su_recvfrom(socket, request.buffer, sizeof request.buffer, 0, - &su->su_sa, &sulen); - - flags = ntohs(request.header->mh_flags); - - if (len < (ssize_t)hlen) - return 0; - if ((flags & FLAGS_QR) == FLAGS_QR) - return 0; - if ((flags & FLAGS_RCODE) != FLAGS_OK) - return 0; - - if ((flags & FLAGS_OPCODE) != FLAGS_QUERY - || ntohs(request.header->mh_qdcount) != 1) { - flags |= FLAGS_QR | FLAGS_UNIMPL_ERR; - request.header->mh_flags = htons(flags); - su_sendto(socket, request.buffer, len, 0, &su->su_sa, sulen); - return 0; - } - - for (r = zonedata; r; r = r->next) { - if (memcmp(r->data, request.buffer + hlen, r->qlen) == 0) - break; - } - - if (r) { - flags |= FLAGS_QR | FLAGS_AA | FLAGS_OK; - request.header->mh_flags = htons(flags); - request.header->mh_ancount = htons(r->header->mh_ancount); - request.header->mh_nscount = htons(r->header->mh_nscount); - request.header->mh_arcount = htons(r->header->mh_arcount); - memcpy(request.buffer + hlen + r->qlen, - r->data + r->qlen, - r->dlen - r->qlen); - len = hlen + r->dlen; - } - else { - flags |= FLAGS_QR | FLAGS_AA | FLAGS_NAME_ERR; - } - - request.header->mh_flags = htons(flags); - su_sendto(socket, request.buffer, len, 0, &su->su_sa, sulen); - return 0; -} - -static void put_uint16(struct s2_dns_response *m, uint16_t h) -{ - uint8_t *p = m->data + m->dlen; - - assert(m->dlen + (sizeof h) < sizeof m->data); - p[0] = h >> 8; p[1] = h; - m->dlen += (sizeof h); -} - -static void put_uint32(struct s2_dns_response *m, uint32_t w) -{ - uint8_t *p = m->data + m->dlen; - - assert(m->dlen + (sizeof w) < sizeof m->data); - p[0] = w >> 24; p[1] = w >> 16; p[2] = w >> 8; p[3] = w; - m->dlen += (sizeof w); -} - -static void put_domain(struct s2_dns_response *m, char const *domain) -{ - char const *label; - size_t llen; - - /* Copy domain into query label at a time */ - for (label = domain; label && label[0]; label += llen) { - assert(!(label[0] == '.' && label[1] != '\0')); - llen = strcspn(label, "."); - assert(llen < 64); - assert(m->dlen + llen + 1 < sizeof m->data); - m->data[m->dlen++] = (uint8_t)llen; - if (llen == 0) - return; - - memcpy(m->data + m->dlen, label, llen); - m->dlen += (uint16_t)llen; - - if (label[llen] == '\0') - break; - if (label[llen + 1]) - llen++; - } - - assert(m->dlen < sizeof m->data); - m->data[m->dlen++] = '\0'; -} - -static void put_string(struct s2_dns_response *m, char const *string) -{ - uint8_t *p = m->data + m->dlen; - size_t len = strlen(string); - - assert(len <= 255); - assert(m->dlen + len + 1 < sizeof m->data); - - *p++ = (uint8_t)len; - memcpy(p, string, len); - m->dlen += len + 1; -} - -static uint16_t put_len_at(struct s2_dns_response *m) -{ - uint16_t at = m->dlen; - assert(m->dlen + sizeof(at) < sizeof m->data); - memset(m->data + m->dlen, 0, sizeof(at)); - m->dlen += sizeof(at); - return at; -} - -static void put_len(struct s2_dns_response *m, uint16_t start) -{ - uint8_t *p = m->data + start; - uint16_t len = m->dlen - (start + 2); - p[0] = len >> 8; p[1] = len; -} - -static void put_data(struct s2_dns_response *m, void *data, uint16_t len) -{ - assert(m->dlen + len < sizeof m->data); - memcpy(m->data + m->dlen, data, len); - m->dlen += len; -} - -static void put_query(struct s2_dns_response *m, char const *domain, - uint16_t qtype) -{ - assert(m->header->mh_qdcount == 0); - put_domain(m, domain), put_uint16(m, qtype), put_uint16(m, sres_class_in); - m->header->mh_qdcount++; - m->qlen = m->dlen; -} - -static void put_a_record(struct s2_dns_response *m, - char const *domain, - struct in_addr addr) -{ - uint16_t start; - - put_domain(m, domain); - put_uint16(m, sres_type_a); - put_uint16(m, sres_class_in); - put_uint32(m, s2_dns_ttl); - start = put_len_at(m); - - put_data(m, &addr, sizeof addr); - put_len(m, start); -} - -static void put_srv_record(struct s2_dns_response *m, - char const *domain, - uint16_t prio, uint16_t weight, - uint16_t port, char const *target) -{ - uint16_t start; - put_domain(m, domain); - put_uint16(m, sres_type_srv); - put_uint16(m, sres_class_in); - put_uint32(m, s2_dns_ttl); - start = put_len_at(m); - - put_uint16(m, prio); - put_uint16(m, weight); - put_uint16(m, port); - put_domain(m, target); - put_len(m, start); -} - -static void put_naptr_record(struct s2_dns_response *m, - char const *domain, - uint16_t order, uint16_t preference, - char const *flags, - char const *services, - char const *regexp, - char const *replace) -{ - uint16_t start; - put_domain(m, domain); - put_uint16(m, sres_type_naptr); - put_uint16(m, sres_class_in); - put_uint32(m, s2_dns_ttl); - start = put_len_at(m); - - put_uint16(m, order); - put_uint16(m, preference); - put_string(m, flags); - put_string(m, services); - put_string(m, regexp); - put_domain(m, replace); - put_len(m, start); -} - -static void put_srv_record_from_uri(struct s2_dns_response *m, - char const *base, - uint16_t prio, uint16_t weight, - url_t const *uri, char const *server) -{ - char domain[1024] = "none"; - char const *service = url_port(uri); - uint16_t port; - - if (uri->url_type == url_sips) { - strcpy(domain, "_sips._tcp."); - } - else if (uri->url_type == url_sip) { - if (url_has_param(uri, "transport=udp")) { - strcpy(domain, "_sip._udp."); - } - else if (url_has_param(uri, "transport=tcp")) { - strcpy(domain, "_sip._tcp."); - } - } - - assert(strcmp(domain, "none")); - - strcat(domain, base); - - if (m->header->mh_qdcount == 0) - put_query(m, domain, sres_type_srv); - - port = (uint16_t)strtoul(service, NULL, 10); - - put_srv_record(m, domain, prio, weight, port, server); -} - -static -void s2_add_to_zone(struct s2_dns_response *_r) -{ - size_t size = offsetof(struct s2_dns_response, data[_r->dlen]); - struct s2_dns_response *r = malloc(size); assert(r); - - memcpy(r, _r, size); - r->next = zonedata; - zonedata = r; -} - - -static void make_server(char *server, char const *prefix, char const *domain) -{ - strcpy(server, prefix); - - if (strlen(server) == 0 || server[strlen(server) - 1] != '.') { - strcat(server, "."); - strcat(server, domain); - } -} - -/** Set up DNS domain */ -void s2_dns_domain(char const *domain, int use_naptr, - /* char *prefix, int priority, url_t const *uri, */ - ...) -{ - struct s2_dns_response m[1]; - - char server[1024], target[1024]; - - va_list va0, va; - char const *prefix; int priority; url_t const *uri; - struct in_addr localhost; - - assert(s2->dns.reg != 0); - - su_inet_pton(AF_INET, "127.0.0.1", &localhost); - - va_start(va0, use_naptr); - - if (use_naptr) { - memset(m, 0, sizeof m); - put_query(m, domain, sres_type_naptr); - - va_copy(va, va0); - - for (;(prefix = va_arg(va, char *));) { - char *services = NULL; - - priority = va_arg(va, int); - uri = va_arg(va, url_t *); assert(uri); - - if (uri->url_type == url_sips) { - services = "SIPS+D2T"; - strcpy(target, "_sips._tcp."); - } - else if (uri->url_type == url_sip) { - if (url_has_param(uri, "transport=udp")) { - services = "SIP+D2U"; - strcpy(target, "_sip._udp."); - } - else if (url_has_param(uri, "transport=tcp")) { - services = "SIP+D2T"; - strcpy(target, "_sip._tcp."); - } - } - - strcat(target, domain); - assert(services); - put_naptr_record(m, domain, 1, priority, "s", services, "", target); - m->header->mh_ancount++; - } - - va_end(va); - va_copy(va, va0); - - for (;(prefix = va_arg(va, char *));) { - priority = va_arg(va, int); - uri = va_arg(va, url_t *); assert(uri); - - make_server(server, prefix, domain); - - put_srv_record_from_uri(m, domain, priority, 10, uri, server); - m->header->mh_arcount++; - - put_a_record(m, server, localhost); - m->header->mh_arcount++; - } - va_end(va); - - s2_add_to_zone(m); - } - - /* Add SRV records */ - va_copy(va, va0); - for (;(prefix = va_arg(va, char *));) { - priority = va_arg(va, int); - uri = va_arg(va, url_t *); assert(uri); - - make_server(server, prefix, domain); - - memset(m, 0, sizeof m); - put_srv_record_from_uri(m, domain, priority, 10, uri, server); - m->header->mh_ancount++; - - strcpy(server, prefix); strcat(server, domain); - - put_a_record(m, server, localhost); - m->header->mh_arcount++; - - s2_add_to_zone(m); - } - va_end(va); - - /* Add A records */ - va_copy(va, va0); - for (;(prefix = va_arg(va, char *));) { - (void)va_arg(va, int); - (void)va_arg(va, url_t *); - - memset(m, 0, sizeof m); - make_server(server, prefix, domain); - - put_query(m, server, sres_type_a); - put_a_record(m, server, localhost); - m->header->mh_ancount++; - - s2_add_to_zone(m); - } - va_end(va); - - va_end(va0); -} - static char const *s2_teardown_label = NULL; void @@ -1552,28 +1089,25 @@ s2_teardown(void) /* ====================================================================== */ -#include - nua_t *s2_nua_setup(char const *label, tag_type_t tag, tag_value_t value, ...) { ta_list ta; s2_setup_base(label, NULL); - s2_setup_dns(); + s2_dns_setup(s2->root); s2_setup_logs(0); s2_setup_tport(NULL, TAG_END()); assert(s2->contact); - - /* enable/disable multithreading */ - su_root_threading(s2->root, s2_nua_thread); - s2_dns_domain("example.org", 1, "s2", 1, s2->udp.contact->m_url, "s2", 1, s2->tcp.contact->m_url, NULL); + /* enable/disable multithreading */ + su_root_threading(s2->root, s2_nua_thread); + ta_start(ta, tag, value); s2->nua = nua_create(s2->root, @@ -1583,6 +1117,7 @@ nua_t *s2_nua_setup(char const *label, /* NUTAG_PROXY((url_string_t *)s2->contact->m_url), */ /* Use internal DNS server */ NUTAG_PROXY("sip:example.org"), + /* Force sresolv to use localhost and s2dns as DNS server */ #if HAVE_WIN32 SRESTAG_RESOLV_CONF("NUL"), #else @@ -1598,6 +1133,7 @@ void s2_nua_teardown(void) { nua_destroy(s2->nua); s2->nua = NULL; + s2_dns_teardown(); s2_teardown(); } diff --git a/libs/sofia-sip/libsofia-sip-ua/nua/test_s2.h b/libs/sofia-sip/libsofia-sip-ua/nua/test_s2.h index 1d1a423ad9..773484893b 100644 --- a/libs/sofia-sip/libsofia-sip-ua/nua/test_s2.h +++ b/libs/sofia-sip/libsofia-sip-ua/nua/test_s2.h @@ -60,12 +60,6 @@ struct tester su_time_t when; } *received; - struct { - su_socket_t socket; - su_wait_t wait[1]; - int reg; - } dns; - nua_t *nua; struct event {