📄 ppldnsv6.c
字号:
/* This is the ppl library. It provides a portable interface to usual OS features Copyright (C) 2002,2003 WellX Telecom - <partysip@wellx.com> Copyright (C) 2002,2003 Aymeric MOIZARD - <jack@atosc.org> The ppl library free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. The ppl library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with the ppl library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA*/#include <ppl/ppl_dns.h>#include <ppl/ppl_socket.h>#include <osipparser2/osip_port.h>#include <osip2/osip_fifo.h>osip_fifo_t *dns_entries; /* list of domain or FQDN strings to resolv */struct osip_mutex *m_dns_result;ppl_dns_entry_t *dns_results;ppl_dns_error_t *dns_errors;static intppl_dns_lock_result_access (void){ return osip_mutex_lock (m_dns_result);}static intppl_dns_unlock_result_access (void){ return osip_mutex_unlock (m_dns_result);}static intcompare (const void *a, const void *b){ ppl_dns_ip_t *aa, *bb; if (!a) return 1; if (!b) return -1; aa = (ppl_dns_ip_t *) * (int *) a; bb = (ppl_dns_ip_t *) * (int *) b; if (aa->pref > bb->pref) return 1; if (aa->pref < bb->pref) return -1; if (aa->rweight > bb->rweight) return -1; if (aa->rweight < bb->rweight) return 1; return 0;}PPL_DECLARE (char *) ppl_dns_get_next_query (){ return osip_fifo_get (dns_entries);}PPL_DECLARE (char *) ppl_dns_tryget_next_query (){ return osip_fifo_tryget (dns_entries);}PPL_DECLARE (ppl_status_t) ppl_dns_init (){ dns_results = NULL; dns_errors = NULL; m_dns_result = osip_mutex_init (); if (m_dns_result == NULL) return -1; dns_entries = (osip_fifo_t *) osip_malloc (sizeof (osip_fifo_t)); if (dns_entries == NULL) { osip_mutex_destroy (m_dns_result); return -1; } osip_fifo_init (dns_entries); return 0;}PPL_DECLARE (int) ppl_dns_ip_init (ppl_dns_ip_t ** ip){ *ip = (ppl_dns_ip_t *) osip_malloc (sizeof (ppl_dns_ip_t)); if (*ip == NULL) return -1; (*ip)->srv_ns_flag = PSP_NS_LOOKUP; /* default is a NS lookup result */ (*ip)->ttl = 60; (*ip)->pref = 0; (*ip)->name = NULL; (*ip)->port = 0; (*ip)->weight = 0; (*ip)->rweight = 0; (*ip)->next = NULL; (*ip)->parent = NULL; return 0;}PPL_DECLARE (int) ppl_dns_ip_free (ppl_dns_ip_t * ip){ if (ip == NULL) return -1; osip_free (ip->name); if (ip->addrinfo!=NULL) { freeaddrinfo(ip->addrinfo); } osip_free(ip); return 0;}PPL_DECLARE (int) ppl_dns_ip_clone (ppl_dns_ip_t * ip, ppl_dns_ip_t ** dest){ ppl_dns_ip_t *tmp; int i; int len; *dest = NULL; if (ip == NULL || ip->name == NULL) return -1; i = ppl_dns_ip_init (&tmp); if (i != 0) return -1; tmp->srv_ns_flag = ip->srv_ns_flag; tmp->ttl = ip->ttl; tmp->name = osip_strdup (ip->name); if (ip->addrinfo->ai_canonname==NULL) /* no cannonname */ len = sizeof(struct addrinfo) + sizeof (struct sockaddr_in); else len = sizeof(struct addrinfo) + sizeof (struct sockaddr_in) + strlen(ip->name) +1; tmp->addrinfo = (struct addrinfo *) osip_malloc(len); memcpy(tmp->addrinfo, ip->addrinfo, len); /* only the first one */ /* FIXME: We have to loop on all addrinfo! */ tmp->pref = ip->pref; tmp->port = ip->port; tmp->weight = ip->weight; tmp->rweight = ip->rweight; tmp->next = NULL; tmp->parent = NULL; *dest = tmp; return 0;}PPL_DECLARE (void) ppl_dns_entry_free (ppl_dns_entry_t * dns){ ppl_dns_ip_t *ip; if (dns == NULL) return; osip_free (dns->name); osip_free (dns->protocol); for (ip = dns->dns_ips; ip != NULL; ip = dns->dns_ips) { REMOVE_ELEMENT (dns->dns_ips, ip); if (ip->addrinfo!=NULL) { freeaddrinfo(ip->addrinfo); } osip_free (ip->name); osip_free (ip); } osip_free (dns); return;}PPL_DECLARE (void) ppl_dns_entry_add_ref (ppl_dns_entry_t * dns){ if (dns == NULL) return; dns->ref++;}PPL_DECLARE (void) ppl_dns_entry_remove_ref (ppl_dns_entry_t * dns){ if (dns == NULL) return; dns->ref--;}PPL_DECLARE (ppl_status_t) ppl_dns_close (){ ppl_dns_entry_t *dns; ppl_dns_error_t *err; for (dns = dns_results; dns != NULL; dns = dns_results) { REMOVE_ELEMENT (dns_results, dns); ppl_dns_entry_free (dns); } for (err = dns_errors; err != NULL; err = dns_errors) { REMOVE_ELEMENT (dns_errors, err); osip_free (err->domain); osip_free (err); } osip_mutex_destroy (m_dns_result); osip_fifo_free (dns_entries); /* endhostent(); */ return 0;}PPL_DECLARE (void) ppl_dns_remove_entry (ppl_dns_entry_t * dns){ ppl_dns_ip_t *d; if (dns->ref == 0) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO4, NULL, "DNS cache entry removed: %s \n", dns->name)); REMOVE_ELEMENT (dns_results, dns); osip_free (dns->name); osip_free (dns->protocol); for (d = dns->dns_ips; d != NULL; d = dns->dns_ips) { REMOVE_ELEMENT (dns->dns_ips, d); if (d->addrinfo!=NULL) { freeaddrinfo(d->addrinfo); } osip_free (d->name); osip_free (d); } osip_free (dns); } else { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_WARNING, NULL, "DNS cache entry not removed: %s\n", dns->name)); }}static ppl_status_tppl_dns_resolv (ppl_dns_ip_t ** dns_ips, querybuf * answer, int n){ ppl_dns_ip_t **array; 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; *dns_ips = NULL; 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) return -1; cp += n + QFIXEDSZ; } array = (ppl_dns_ip_t **) malloc (ancount * sizeof (ppl_dns_ip_t *)); for (n = 0; n < ancount; n++) array[n] = NULL; answerno = 0; /* loop through the answer buffer and extract SRV records */ while (ancount-- > 0 && cp < eom) { n = dn_expand (msg, eom, cp, (char *) hostbuf, 256); if (n < 0) { for (n = 0; n < answerno; n++) { osip_free (array[n]->name); (void) free (array[n]); } (void) free (array); return -1; } 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; array[answerno] = (ppl_dns_ip_t *) osip_malloc (sizeof (ppl_dns_ip_t)); array[answerno]->srv_ns_flag = PSP_SRV_LOOKUP; array[answerno]->ttl = ttl; array[answerno]->pref = pref; array[answerno]->weight = weight; if (weight) array[answerno]->rweight = 1 + random () % (10000 * weight); else array[answerno]->rweight = 0; array[answerno]->port = port; array[answerno]->next = NULL; array[answerno]->name = osip_strdup ((char *) hostbuf); answerno++; } if (answerno == 0) { return -1; } qsort (array, answerno, sizeof (ppl_dns_ip_t *), compare); /* Recreate a linked list from the sorted array... */ array[0]->parent = NULL; for (n = 0; n < answerno; n++) { if (n != 0) array[n]->parent = array[n - 1]; array[n]->next = array[n + 1]; } array[answerno - 1]->next = NULL; *dns_ips = array[0]; (void) free (array); return 0;}PPL_DECLARE (ppl_status_t) ppl_dns_error_add (char *address){ ppl_dns_error_t *error; if (address == NULL) return -1; error = (ppl_dns_error_t *) osip_malloc (sizeof (ppl_dns_error_t)); error->domain = address; error->expires = time(NULL); error->next = NULL; error->parent = NULL; ppl_dns_lock_result_access (); ADD_ELEMENT (dns_errors, error); ppl_dns_unlock_result_access (); return 0;}PPL_DECLARE (ppl_status_t)ppl_dns_get_error (ppl_dns_error_t ** dns_error, char *domain){ ppl_dns_error_t *error; *dns_error = NULL; ppl_dns_lock_result_access (); for (error = dns_errors; error != NULL && 0 != strcmp (error->domain, domain); error = error->next) { } if (error == NULL) { ppl_dns_unlock_result_access (); return -1; } /* REMOVE_ELEMENT(dns_results, res); We could keep it for a while? */ ppl_dns_unlock_result_access (); *dns_error = error; return 0;}/** * Add a result in the list of known result * @param dns the the dns result to add. */PPL_DECLARE (ppl_status_t) ppl_dns_add_domain_result (ppl_dns_entry_t * dns){ if (dns == NULL) return -1; ppl_dns_lock_result_access (); ADD_ELEMENT (dns_results, dns); ppl_dns_unlock_result_access (); return 0;}/** * A an entry in the list of known result
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -