📄 ppldnsv6.c
字号:
* @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; { /* free some unusfull memory */ ppl_dns_error_t *error; ppl_dns_error_t *enext; int now; now = time(NULL); for (error = dns_errors; error != NULL; error = enext) { enext = error->next; if ( now-error->expires > 120 ) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO2, NULL, "release old bad resolution info for '%s'\n", error->domain)); REMOVE_ELEMENT (dns_errors, error); osip_free(error->domain); osip_free(error); } } } 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); } } } if (res == NULL) { ppl_dns_unlock_result_access (); return -1; } 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 REMOVED2\n")); ppl_dns_remove_entry (res); res = 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 = res; return 0;}PPL_DECLARE (ppl_status_t)ppl_dns_query (ppl_dns_entry_t ** dest, char *domain, char *protocol){ ppl_dns_entry_t *dns; ppl_dns_ip_t *next; ppl_dns_ip_t *ip; querybuf answer; /* answer buffer from nameserver */ int n; char *zone; *dest = NULL; if (!domain || !*domain || !protocol || !*protocol) return -1; zone = (char *) malloc (strlen (domain) + 5 + strlen (protocol) + 20); if (zone == NULL) return -1; *zone = '\0'; strcat (zone, "_sip"); strcat (zone, "."); strcat (zone, "_"); strcat (zone, protocol); strcat (zone, "."); strcat (zone, domain); 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)) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO2, NULL, "Did not get a valid response for query '%s IN SRV'\n", zone)); (void) free (zone); return -1; } OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO2, NULL, "Got valid response for query '%s IN SRV'\n", zone)); (void) free (zone); dns = (ppl_dns_entry_t *) osip_malloc (sizeof (ppl_dns_entry_t)); dns->name = domain; dns->protocol = osip_strdup(protocol); dns->date = ppl_time (); dns->dns_ips = NULL; dns->ref = 0; dns->next = NULL; dns->parent = NULL; n = ppl_dns_resolv (&(dns->dns_ips), &answer, n); if (n != 0) { dns->name = NULL; /* fix bug: keep the name allocated after a failure. */ ppl_dns_entry_free (dns); return -1; } for (ip = dns->dns_ips; ip != NULL; ip = ip->next) { n = ppl_dns_get_addrinfo (&(ip->addrinfo), ip->name, ip->port); if (n != PPL_SUCCESS) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO2, NULL, "Hostname '%s' does not resolve", ip->name)); if (ip->addrinfo!=NULL) { freeaddrinfo(ip->addrinfo); } osip_free (ip->name); ip->name = NULL; /* mark for deletion */ } } /* delete ppl_dns_ip_t elements marked for deletion */ for (ip = dns->dns_ips; ip != NULL; ip = next) { if (ip->name == NULL) { next = ip->next; REMOVE_ELEMENT (dns->dns_ips, ip); osip_free (ip); } else { next = ip->next; OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO2, NULL, "Hostname '%s' resolved to '%s'\n", ip->name, ip->addrinfo->ai_canonname)); } } *dest = dns; return 0;}#define BUFLEN 512PPL_DECLARE (char *)ppl_inet_ntop (struct sockaddr *sockaddr){ char buf[BUFLEN]; char *ptr = NULL; switch (sockaddr->sa_family) { case AF_INET: ptr = (char*)inet_ntop(sockaddr->sa_family, &((struct sockaddr_in *)sockaddr)->sin_addr, buf, BUFLEN-1); break; case AF_INET6: ptr = (char*)inet_ntop(sockaddr->sa_family, &((struct sockaddr_in6 *)sockaddr)->sin6_addr, buf, BUFLEN-1); break; default: return NULL; } if (ptr==NULL) return NULL; return osip_strdup(buf);}PPL_DECLARE (int)ppl_inet_pton (const char *src, void *dst){ if (strchr (src, ':')) /* possible IPv6 address */ return (inet_pton(AF_INET6, src, dst)); else if (strchr (src, '.')) /* possible IPv4 address */ return (inet_pton(AF_INET, src, dst)); else /* Impossibly a valid ip address */ return INADDR_NONE;}PPL_DECLARE (ppl_status_t)ppl_dns_get_addrinfo (struct addrinfo **addrinfo, char *hostname, int service){ struct in_addr addr; struct in6_addr addrv6; struct addrinfo hints; int error; char portbuf[10]; if (service!=0) snprintf(portbuf, sizeof(portbuf), "%d", service); memset (&hints, 0, sizeof (hints));#if 0 if (inet_pton(AF_INET, hostname, &addr)>0) { /* ipv4 address detected */ struct addrinfo *_addrinfo; _addrinfo = (struct addrinfo *)osip_malloc(sizeof(struct addrinfo) + sizeof (struct sockaddr_in) + 0); /* no cannonname */ _addrinfo->ai_flags = AI_NUMERICHOST; _addrinfo->ai_family = AF_INET; _addrinfo->ai_socktype = SOCK_DGRAM; _addrinfo->ai_protocol = IPPROTO_UDP; _addrinfo->ai_addrlen = sizeof(struct sockaddr_in); _addrinfo->ai_addr = (void *) (_addrinfo) + sizeof (struct addrinfo); memset(_addrinfo->ai_addr, 0, sizeof(struct sockaddr_in)); ((struct sockaddr_in*)_addrinfo->ai_addr)->sin_family = AF_INET; ((struct sockaddr_in*)_addrinfo->ai_addr)->sin_addr.s_addr = inet_addr(hostname); if (service==0) ((struct sockaddr_in*)_addrinfo->ai_addr)->sin_port = htons (5060); else ((struct sockaddr_in*)_addrinfo->ai_addr)->sin_port = htons (service); _addrinfo->ai_canonname = NULL; _addrinfo->ai_next = NULL; OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO2, NULL, "No DNS resolution needed for %s:%i\n", hostname, service)); *addrinfo = _addrinfo; OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO2, NULL, "IPv4 address detected: %s\n", hostname)); return 0; } else if (inet_pton(AF_INET6, hostname, &addrv6)>0) { hints.ai_flags = AI_CANONNAME; hints.ai_family = PF_INET6; /* ipv6 support */ } else#endif { hints.ai_flags = AI_CANONNAME; hints.ai_family = PF_UNSPEC; /* ipv4 & ipv6 support */#if 0 hints.ai_family = PF_UNSPEC; /* ipv4 & ipv6 support */#endif } hints.ai_socktype = SOCK_DGRAM; hints.ai_protocol = IPPROTO_UDP; if (service==0) { error = getaddrinfo (hostname, "sip", &hints, addrinfo); OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO2, NULL, "SRV resolution with udp-sip-%s\n", hostname)); } else { error = getaddrinfo (hostname, portbuf, &hints, addrinfo); OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO2, NULL, "DNS resolution with %s:%i\n", hostname, service)); } if (error || *addrinfo == NULL) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO2, NULL, "getaddrinfo failure. %s:%i\n", hostname, service)); return -1; } /* fprintf (stdout, "canonnical name is: %s\n", (*addrinfo)->ai_canonname); fprintf (stdout, "ai_addrlen is: %i\n", (*addrinfo)->ai_addrlen); */ /* memcpy (sin, res0->ai_addr, res0->ai_addrlen); */ /* freeaddrinfo (res0); */ return PPL_SUCCESS;}PPL_DECLARE (int)ppl_dns_query_host (ppl_dns_entry_t ** dest, char *hostname, int port){ struct addrinfo *addr; ppl_dns_ip_t *dns_ip; ppl_dns_entry_t *dns; int my_error; char portbuf[10]; *dest = NULL; snprintf(portbuf, sizeof(portbuf), "%d", port); my_error = ppl_dns_get_addrinfo (&addr, hostname, port); if (my_error) return my_error; dns_ip = (ppl_dns_ip_t *) osip_malloc (sizeof (ppl_dns_ip_t)); dns_ip->srv_ns_flag = PSP_NS_LOOKUP; dns_ip->ttl = 60; dns_ip->pref = 10; dns_ip->weight = 0; dns_ip->rweight = 0; dns_ip->port = port; dns_ip->next = NULL; dns_ip->parent = NULL; /* dns_ip->sin.sin_family = addr.sin_family; */ /* dns_ip->sin.sin_addr = addr.sin_addr; */ /* dns_ip->sin.sin_port = htons (port); */ dns_ip->addrinfo = addr; /* dns_ip->name = osip_strdup(addr->ai_canonname); */ dns_ip->name = ppl_inet_ntop ((struct sockaddr *)(addr->ai_addr)); if (dns_ip->name==NULL) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO2, NULL, "getaddrinfo failure. could not get printable version\n")); return -1; } dns = (ppl_dns_entry_t *) osip_malloc (sizeof (ppl_dns_entry_t)); if (dns == NULL) { /* MLEAK! I have to free first_ip and following dns_ip!! */ if (dns_ip->addrinfo!=NULL) { freeaddrinfo(dns_ip->addrinfo); } osip_free (dns_ip->name); osip_free (dns_ip); return -1; } dns->name = hostname; dns->protocol = NULL; dns->date = ppl_time (); dns->dns_ips = dns_ip; dns->ref = 0; dns->next = NULL; dns->parent = NULL; *dest = dns; return 0;}#include <sys/ioctl.h>#include <net/if.h>static int ppl_dns_default_gateway_ipv4 (char *address, int size);static int ppl_dns_default_gateway_ipv6 (char *address, int size);intppl_dns_default_gateway (int familiy, char *address, int size){ if (familiy==AF_INET6) { return ppl_dns_default_gateway_ipv6 (address, size); } else { return ppl_dns_default_gateway_ipv4 (address, size); }}/* This is a portable way to find the default gateway. * The ip of the default interface is returned. */static intppl_dns_default_gateway_ipv4 (char *address, int size){ unsigned int len; int sock_rt, on=1; struct sockaddr_in iface_out; struct sockaddr_in remote; memset(&remote, 0, sizeof(struct sockaddr_in)); remote.sin_family = AF_INET; remote.sin_addr.s_addr = inet_addr("217.12.3.11"); remote.sin_port = htons(11111); memset(&iface_out, 0, sizeof(iface_out)); sock_rt = socket(AF_INET, SOCK_DGRAM, 0 ); if (setsockopt(sock_rt, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on)) == -1) { perror("DEBUG: [get_output_if] setsockopt(SOL_SOCKET, SO_BROADCAST"); close(sock_rt); return -1; } if (connect(sock_rt, (struct sockaddr*)&remote, sizeof(struct sockaddr_in)) == -1 ) { perror("DEBUG: [get_output_if] connect"); close(sock_rt); return -1; } len = sizeof(iface_out); if (getsockname(sock_rt, (struct sockaddr *)&iface_out, &len) == -1 ) { perror("DEBUG: [get_output_if] getsockname"); close(sock_rt); return -1; } close(sock_rt); if (iface_out.sin_addr.s_addr == 0) { /* what is this case?? */ return -1; } osip_strncpy(address, inet_ntoa(iface_out.sin_addr), size-1); return 0;}/* This is a portable way to find the default gateway. * The ip of the default interface is returned. */static intppl_dns_default_gateway_ipv6 (char *address, int size){ unsigned int len; int sock_rt, on=1; struct sockaddr_in6 iface_out; struct sockaddr_in6 remote; memset(&remote, 0, sizeof(struct sockaddr_in)); remote.sin6_family = AF_INET6; inet_pton(AF_INET6, "2001:638:500:101:2e0:81ff:fe24:37c6", &remote.sin6_addr); remote.sin6_port = htons(11111); memset(&iface_out, 0, sizeof(iface_out)); sock_rt = socket(AF_INET6, SOCK_DGRAM, 0 );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -