📄 ppldns.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 <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);}#ifndef WIN32static 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;}#endifPPL_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); 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); 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(); */ /* Not sure this is the correct method to call? Elements allocated by gethsotbyname_r still exists! */ 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); osip_free (d->name); osip_free (d); } osip_free (dns); } else { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO4, NULL, "DNS cache entry removed: %s \n", dns->name)); }}/* I DON'T KNOW HOW TO SUPPORT SRV RECORD ON WINDOWS, TODO */PPL_DECLARE (ppl_status_t)ppl_dns_resolv (ppl_dns_ip_t ** dns_ips, querybuf * answer, int n){ *dns_ips = NULL; return -1;}PPL_DECLARE (ppl_status_t)ppl_dns_query (ppl_dns_entry_t ** dest, char *domain, char *protocol){ *dest = NULL; return -1;}#define BUFLEN 512PPL_DECLARE (char *)ppl_inet_ntop (struct sockaddr *sockaddr){ char *ptr = NULL; switch (sockaddr->sa_family) { case AF_INET: ptr = inet_ntoa (((struct sockaddr_in *)sockaddr)->sin_addr); break; case AF_INET6: ptr = NULL; break; default: return NULL; } if (ptr==NULL) return NULL; return osip_strdup(ptr);}PPL_DECLARE (int)ppl_inet_pton (const char *src, void *dst){ if (strchr (src, ':')) /* possible IPv6 address */ return -1; /* (inet_pton(AF_INET6, src, dst)); */ else if (strchr (src, '.')) /* possible IPv4 address */ { ((struct sockaddr_in *)dst)->sin_port = 0; /* to N. byte order */ ((struct sockaddr_in *)dst)->sin_family = AF_INET; ((struct sockaddr_in *)dst)->sin_addr.s_addr = inet_addr(src); /* already in N. byte order */ if (((struct sockaddr_in *)dst)->sin_addr.s_addr == INADDR_NONE) return 0; return 1; /* (inet_pton(AF_INET, src, dst)); */ } else /* Impossibly a valid ip address */ return INADDR_NONE;}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->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 * @param domain Domain to search */PPL_DECLARE (ppl_status_t) ppl_dns_add_domain_query (char *domain){ if (domain == NULL) return -1; osip_fifo_add (dns_entries, domain); return 0;}PPL_DECLARE (ppl_status_t)ppl_dns_get_result (ppl_dns_entry_t ** dns, char *domain){ ppl_dns_entry_t *res; ppl_dns_entry_t *resnext; ppl_time_t now; now = ppl_time (); *dns = NULL; ppl_dns_lock_result_access (); res = dns_results; resnext = res; for (; res != NULL && 0 != strcmp (res->name, domain); res = resnext) { resnext = res->next; if (res->dns_ips != NULL) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO4, NULL, "time to live: %li, date: %i\n", res->dns_ips->ttl, res->date)); if (now - res->date > res->dns_ips->ttl) /* expired entry! */ { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO4, NULL, "ENTRY REMOVED1\n")); ppl_dns_remove_entry (res);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -