📄 srv_resolv.c
字号:
/* -------------------------------------------------------------------------- * * License * * The contents of this file are subject to the Jabber Open Source License * Version 1.0 (the "JOSL"). You may not copy or use this file, in either * source code or executable form, except in compliance with the JOSL. You * may obtain a copy of the JOSL at http://www.jabber.org/ or at * http://www.opensource.org/. * * Software distributed under the JOSL is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the JOSL * for the specific language governing rights and limitations under the * JOSL. * * Copyrights * * Portions created by or assigned to Jabber.com, Inc. are * Copyright (c) 1999-2002 Jabber.com, Inc. All Rights Reserved. Contact * information for Jabber.com, Inc. is available at http://www.jabber.com/. * * Portions Copyright (c) 1998-1999 Jeremie Miller. * * Acknowledgements * * Special thanks to the Jabber Open Source Contributors for their * suggestions and support of Jabber. * * Alternatively, the contents of this file may be used under the terms of the * GNU General Public License Version 2 or later (the "GPL"), in which case * the provisions of the GPL are applicable instead of those above. If you * wish to allow use of your version of this file only under the terms of the * GPL and not to allow others to use your version of this file under the JOSL, * indicate your decision by deleting the provisions above and replace them * with the notice and other provisions required by the GPL. If you do not * delete the provisions above, a recipient may use your version of this file * under either the JOSL or the GPL. * * * --------------------------------------------------------------------------*/#include "jabberd.h"#include <netinet/in.h>#define BIND_8_COMPAT#include <arpa/nameser.h>#include <resolv.h>#include "srv_resolv.h"/** * @file srv_resolv.c * @brief implements SRV DNS resolving * * This file implements resolving of services in the DNS using the protocol defined in RFC 2782. */#ifndef T_SRV#define T_SRV 33#endif/** * @brief representation of a SRV DNS record * * This structure is used to build an ordered double linked list of SRV DNS records for a service on a domain */typedef struct __srv_list{ int priority; /**< priority value in this record */ char* port; /**< port value in this record */ char* host; /**< host name where this record points to */ struct __srv_list* next; /**< next value in the list (higher priority value) */ struct __srv_list* last; /**< previous value in the list (lower priority value) */} *srv_list, _srv_list;/** * convert an IPv4 (AF_INET) address to its textual representation using memory pools * * @param p the pool to be used * @param addrptr the address that should be printed * @return the address as a string */char* srv_inet_ntoa(pool p, unsigned char* addrptr){ char result[16]; result[15] = '\0'; snprintf(result, 16, "%d.%d.%d.%d", addrptr[0],addrptr[1],addrptr[2],addrptr[3]); return pstrdup(p, result);}#ifdef WITH_IPV6/** * convert an internet address to its textual representation using memory pools * * @param p the pool to be used * @param addrptr the address that should be printed * @param af the address family of addrptr * @return the address as a string */char* srv_inet_ntop(pool p, const unsigned char* addrptr, int af){ char result[INET6_ADDRSTRLEN]; inet_ntop(af, addrptr, result, sizeof(result)); return pstrdup(p, result);}#endif/** * convert a (numerical) port number to a string using memory pools * * @param p the pool to be used * @param port the port that should be converted * @return the port number as a string */char* srv_port2str(pool p, unsigned short port){ char* result = pmalloco(p, 6); snprintf(result, 6, "%d", port); return result;}/** * put a value in an xhash and join it with the previous value if there has been already one in the hash * * If there is no entry for this key, the function just enters the value. * If there is already an entry for this key, the function will append a "," * and the old value to the new value and insert it into the hash. * * @param p memory pool to be used * @param ht the hash table * @param key the key in the hash * @param value the value that should be inserted */void srv_xhash_join(pool p, xht ht, const char *key, char *value) { void *old = xhash_get(ht, key); if (old == NULL) { xhash_put(ht, key, value); return; } xhash_put(ht, key, spools(p, value, ",", (char*)old, p));}/** * helper function that lookups AAAA and A records in the dns * * this function will lookup AAAA and A records and return the IP addresses as a comma separated list * * @return 0 in case of success, non zero on error */int srv_lookup_aaaa_a(spool result, const char* domain) { int first_result = 1;#ifdef WITH_IPV6 int error_code; struct addrinfo hints; struct addrinfo* addr_res; struct addrinfo* addr_iter; char addr_str[INET6_ADDRSTRLEN];#else struct hostent* hp; char addr_str[16];#endif log_debug2(ZONE, LOGT_IO, "Standard resolution of %s", domain); #ifdef WITH_IPV6 /* setup the hints what we want to get */ bzero(&hints, sizeof(hints)); hints.ai_family = PF_UNSPEC; hints.ai_socktype = SOCK_STREAM; addr_res = NULL; /* start resolving */ error_code = getaddrinfo(domain, NULL, &hints, &addr_res); if (error_code) { log_debug2(ZONE, LOGT_IO, "Error while resolving %s: %s", domain, gai_strerror(error_code)); if (addr_res) { freeaddrinfo(addr_res); } return 1; } /* iterate through all results to find IPv6 and IPv4 results */ for (addr_iter = addr_res; addr_iter != NULL; addr_iter = addr_iter->ai_next) { switch (addr_iter->ai_family) { case PF_INET: inet_ntop(AF_INET, (char *)&((struct sockaddr_in*)addr_iter->ai_addr)->sin_addr, addr_str, sizeof(addr_str)); if (!first_result) { spooler(result, ",", addr_str, result); } else { first_result = 0; spool_add(result, addr_str); } break; case PF_INET6: inet_ntop(AF_INET6, (char *)&((struct sockaddr_in6*)addr_iter->ai_addr)->sin6_addr, addr_str, sizeof(addr_str)); if (!first_result) { spooler(result, ",", addr_str, result); } else { first_result = 0; spool_add(result, addr_str); } } } /* free memory */ if (addr_res) { freeaddrinfo(addr_res); } return 0;#else hp = gethostbyname(domain); if (!hp) { log_debug2(ZONE, LOGT_IO, "Unable to resolve: %s", domain); return 1; } snprintf(addr_str, sizeof(addr_str), "%u.%u.%u.%u", (unsigned char)(hp->h_addr[0]), (unsigned char)hp->h_addr[1], (unsigned char)hp->h_addr[2], (unsigned char)hp->h_addr[3]); spooler(result, addr_str, result); return 0;#endif}/** * do a DNS lookup * * This function implements a SRV DNS lookup and falls back to normal AAAA/A resolution * if no service has been given by the caller. * * @param p memory pool to be used by this function * @param service which service should be looked up (e.g. "_xmpp-server._tcp") * @param domain which domain should be looked up * @return comma separated list of results containing IPv4 and IPv6 addresses with or without ports * * @todo The function honors the priority values of a SRV record but not the weight values. Implement handling of weights! */char* srv_lookup(pool p, const char* service, const char* domain){ unsigned char reply[1024]; /* Reply buffer */ int replylen = 0; char host[1024];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -