📄 resolv.c
字号:
/* resolv.c: DNS Resolver * * Copyright (C) 1998 Kenneth Albanowski <kjahds@kjahds.com>, * The Silver Hammer Group, Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version.*//* * Portions Copyright (c) 1985, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. *//* * Portions Copyright (c) 1993 by Digital Equipment Corporation. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies, and that * the name of Digital Equipment Corporation not be used in advertising or * publicity pertaining to distribution of the document or software without * specific, written prior permission. * * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS * SOFTWARE. *//* * Portions Copyright (c) 1996-1999 by Internet Software Consortium. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS * SOFTWARE. *//* * * 5-Oct-2000 W. Greathouse wgreathouse@smva.com * Fix memory leak and memory corruption. * -- Every name resolution resulted in * a new parse of resolv.conf and new * copy of nameservers allocated by * strdup. * -- Every name resolution resulted in * a new read of resolv.conf without * resetting index from prior read... * resulting in exceeding array bounds. * * Limit nameservers read from resolv.conf * * Add "search" domains from resolv.conf * * Some systems will return a security * signature along with query answer for * dynamic DNS entries. * -- skip/ignore this answer * * Include arpa/nameser.h for defines. * * General cleanup * * 20-Jun-2001 Michal Moskal <malekith@pld.org.pl> * partial IPv6 support (i.e. gethostbyname2() and resolve_address2() * functions added), IPv6 nameservers are also supported. * * 6-Oct-2001 Jari Korva <jari.korva@iki.fi> * more IPv6 support (IPv6 support for gethostbyaddr(); * address family parameter and improved IPv6 support for get_hosts_byname * and read_etc_hosts; getnameinfo() port from glibc; defined * defined ip6addr_any and in6addr_loopback) * * 2-Feb-2002 Erik Andersen <andersen@codepoet.org> * Added gethostent(), sethostent(), and endhostent() * * 17-Aug-2002 Manuel Novoa III <mjn3@codepoet.org> * Fixed __read_etc_hosts_r to return alias list, and modified buffer * allocation accordingly. See MAX_ALIASES and ALIAS_DIM below. * This fixes the segfault in the Python 2.2.1 socket test. * * 04-Jan-2003 Jay Kulpinski <jskulpin@berkshire.rr.com> * Fixed __decode_dotted to count the terminating null character * in a host name. * * 02-Oct-2003 Tony J. White <tjw@tjw.org> * Lifted dn_expand() and dependent ns_name_uncompress(), ns_name_unpack(), * and ns_name_ntop() from glibc 2.3.2 for compatibility with ipsec-tools * and openldap. * * 7-Sep-2004 Erik Andersen <andersen@codepoet.org> * Added gethostent_r() * */#define __FORCE_GLIBC#include <features.h>#include <string.h>#include <stdio.h>#include <signal.h>#include <errno.h>#include <sys/socket.h>#include <sys/types.h>#include <sys/time.h>#include <netinet/in.h>#include <arpa/inet.h>#include <stdlib.h>#include <unistd.h>#include <resolv.h>#include <netdb.h>#include <ctype.h>#include <arpa/nameser.h>#include <sys/utsname.h>#include <sys/un.h>#define MAX_RECURSE 5#define REPLY_TIMEOUT 10#define MAX_RETRIES 3#define MAX_SERVERS 3#define MAX_SEARCH 4#define MAX_ALIASES 5/* 1:ip + 1:full + MAX_ALIASES:aliases + 1:NULL */#define ALIAS_DIM (2 + MAX_ALIASES + 1)#undef DEBUG/* #define DEBUG */#ifdef DEBUG#define DPRINTF(X,args...) fprintf(stderr, X, ##args)#else#define DPRINTF(X,args...)#endif /* DEBUG *//* Global stuff (stuff needing to be locked to be thread safe)... */extern int __nameservers;extern char * __nameserver[MAX_SERVERS];extern int __searchdomains;extern char * __searchdomain[MAX_SEARCH];#ifdef __UCLIBC_HAS_THREADS__#include <pthread.h>extern pthread_mutex_t __resolv_lock;# define BIGLOCK __pthread_mutex_lock(&__resolv_lock)# define BIGUNLOCK __pthread_mutex_unlock(&__resolv_lock);#else# define BIGLOCK# define BIGUNLOCK#endif/* Structs */struct resolv_header { int id; int qr,opcode,aa,tc,rd,ra,rcode; int qdcount; int ancount; int nscount; int arcount;};struct resolv_question { char * dotted; int qtype; int qclass;};struct resolv_answer { char * dotted; int atype; int aclass; int ttl; int rdlength; unsigned char * rdata; int rdoffset;};enum etc_hosts_action { GET_HOSTS_BYNAME = 0, GETHOSTENT, GET_HOSTS_BYADDR,};/* function prototypes */extern int __get_hosts_byname_r(const char * name, int type, struct hostent * result_buf, char * buf, size_t buflen, struct hostent ** result, int * h_errnop);extern int __get_hosts_byaddr_r(const char * addr, int len, int type, struct hostent * result_buf, char * buf, size_t buflen, struct hostent ** result, int * h_errnop);extern void __open_etc_hosts(FILE **fp);extern int __read_etc_hosts_r(FILE *fp, const char * name, int type, enum etc_hosts_action action, struct hostent * result_buf, char * buf, size_t buflen, struct hostent ** result, int * h_errnop);extern int __dns_lookup(const char * name, int type, int nscount, char ** nsip, unsigned char ** outpacket, struct resolv_answer * a);extern int __encode_dotted(const char * dotted, unsigned char * dest, int maxlen);extern int __decode_dotted(const unsigned char * message, int offset, char * dest, int maxlen);extern int __length_dotted(const unsigned char * message, int offset);extern int __encode_header(struct resolv_header * h, unsigned char * dest, int maxlen);extern int __decode_header(unsigned char * data, struct resolv_header * h);extern int __encode_question(struct resolv_question * q, unsigned char * dest, int maxlen);extern int __decode_question(unsigned char * message, int offset, struct resolv_question * q);extern int __encode_answer(struct resolv_answer * a, unsigned char * dest, int maxlen);extern int __decode_answer(unsigned char * message, int offset, struct resolv_answer * a);extern int __length_question(unsigned char * message, int offset);extern int __open_nameservers(void);extern void __close_nameservers(void);extern int __dn_expand(const u_char *, const u_char *, const u_char *, char *, int);extern int __ns_name_uncompress(const u_char *, const u_char *, const u_char *, char *, size_t);extern int __ns_name_ntop(const u_char *, char *, size_t);extern int __ns_name_unpack(const u_char *, const u_char *, const u_char *, u_char *, size_t);#ifdef L_encodehint __encode_header(struct resolv_header *h, unsigned char *dest, int maxlen){ if (maxlen < HFIXEDSZ) return -1; dest[0] = (h->id & 0xff00) >> 8; dest[1] = (h->id & 0x00ff) >> 0; dest[2] = (h->qr ? 0x80 : 0) | ((h->opcode & 0x0f) << 3) | (h->aa ? 0x04 : 0) | (h->tc ? 0x02 : 0) | (h->rd ? 0x01 : 0); dest[3] = (h->ra ? 0x80 : 0) | (h->rcode & 0x0f); dest[4] = (h->qdcount & 0xff00) >> 8; dest[5] = (h->qdcount & 0x00ff) >> 0; dest[6] = (h->ancount & 0xff00) >> 8; dest[7] = (h->ancount & 0x00ff) >> 0; dest[8] = (h->nscount & 0xff00) >> 8; dest[9] = (h->nscount & 0x00ff) >> 0; dest[10] = (h->arcount & 0xff00) >> 8; dest[11] = (h->arcount & 0x00ff) >> 0; return HFIXEDSZ;}#endif#ifdef L_decodehint __decode_header(unsigned char *data, struct resolv_header *h){ h->id = (data[0] << 8) | data[1]; h->qr = (data[2] & 0x80) ? 1 : 0; h->opcode = (data[2] >> 3) & 0x0f; h->aa = (data[2] & 0x04) ? 1 : 0; h->tc = (data[2] & 0x02) ? 1 : 0; h->rd = (data[2] & 0x01) ? 1 : 0; h->ra = (data[3] & 0x80) ? 1 : 0; h->rcode = data[3] & 0x0f; h->qdcount = (data[4] << 8) | data[5]; h->ancount = (data[6] << 8) | data[7]; h->nscount = (data[8] << 8) | data[9]; h->arcount = (data[10] << 8) | data[11]; return HFIXEDSZ;}#endif#ifdef L_encoded/* Encode a dotted string into nameserver transport-level encoding. This routine is fairly dumb, and doesn't attempt to compress the data */int __encode_dotted(const char *dotted, unsigned char *dest, int maxlen){ int used = 0; while (dotted && *dotted) { char *c = strchr(dotted, '.'); int l = c ? c - dotted : strlen(dotted); if (l >= (maxlen - used - 1)) return -1; dest[used++] = l; memcpy(dest + used, dotted, l); used += l; if (c) dotted = c + 1; else break; } if (maxlen < 1) return -1; dest[used++] = 0; return used;}#endif#ifdef L_decoded/* Decode a dotted string from nameserver transport-level encoding. This routine understands compressed data. */int __decode_dotted(const unsigned char *data, int offset, char *dest, int maxlen){ int l; int measure = 1; int total = 0; int used = 0; if (!data) return -1; while ((l=data[offset++])) { if (measure) total++; if ((l & 0xc0) == (0xc0)) { if (measure) total++; /* compressed item, redirect */ offset = ((l & 0x3f) << 8) | data[offset]; measure = 0; continue; } if ((used + l + 1) >= maxlen) return -1; memcpy(dest + used, data + offset, l); offset += l; used += l; if (measure) total += l; if (data[offset] != 0) dest[used++] = '.'; else dest[used++] = '\0'; } /* The null byte must be counted too */ if (measure) { total++; } DPRINTF("Total decode len = %d\n", total); return total;}#endif#ifdef L_lengthdint __length_dotted(const unsigned char *data, int offset){ int orig_offset = offset; int l; if (!data) return -1; while ((l = data[offset++])) { if ((l & 0xc0) == (0xc0)) { offset++; break; } offset += l; } return offset - orig_offset;}#endif#ifdef L_encodeqint __encode_question(struct resolv_question *q, unsigned char *dest, int maxlen){ int i; i = __encode_dotted(q->dotted, dest, maxlen); if (i < 0) return i; dest += i; maxlen -= i; if (maxlen < 4) return -1; dest[0] = (q->qtype & 0xff00) >> 8; dest[1] = (q->qtype & 0x00ff) >> 0; dest[2] = (q->qclass & 0xff00) >> 8; dest[3] = (q->qclass & 0x00ff) >> 0; return i + 4;}#endif#ifdef L_decodeqint __decode_question(unsigned char *message, int offset, struct resolv_question *q){ char temp[256]; int i; i = __decode_dotted(message, offset, temp, sizeof(temp)); if (i < 0) return i; offset += i; q->dotted = strdup(temp); q->qtype = (message[offset + 0] << 8) | message[offset + 1]; q->qclass = (message[offset + 2] << 8) | message[offset + 3]; return i + 4;}#endif#ifdef L_lengthqint __length_question(unsigned char *message, int offset){ int i; i = __length_dotted(message, offset); if (i < 0) return i; return i + 4;}#endif#ifdef L_encodeaint __encode_answer(struct resolv_answer *a, unsigned char *dest, int maxlen){ int i; i = __encode_dotted(a->dotted, dest, maxlen); if (i < 0) return i; dest += i; maxlen -= i; if (maxlen < (RRFIXEDSZ+a->rdlength)) return -1; *dest++ = (a->atype & 0xff00) >> 8; *dest++ = (a->atype & 0x00ff) >> 0; *dest++ = (a->aclass & 0xff00) >> 8; *dest++ = (a->aclass & 0x00ff) >> 0; *dest++ = (a->ttl & 0xff000000) >> 24; *dest++ = (a->ttl & 0x00ff0000) >> 16; *dest++ = (a->ttl & 0x0000ff00) >> 8; *dest++ = (a->ttl & 0x000000ff) >> 0; *dest++ = (a->rdlength & 0xff00) >> 8; *dest++ = (a->rdlength & 0x00ff) >> 0; memcpy(dest, a->rdata, a->rdlength); return i + RRFIXEDSZ + a->rdlength;}#endif#ifdef L_decodeaint __decode_answer(unsigned char *message, int offset, struct resolv_answer *a){ char temp[256]; int i; i = __decode_dotted(message, offset, temp, sizeof(temp)); if (i < 0) return i; message += offset + i; a->dotted = strdup(temp); a->atype = (message[0] << 8) | message[1]; message += 2; a->aclass = (message[0] << 8) | message[1]; message += 2; a->ttl = (message[0] << 24) | (message[1] << 16) | (message[2] << 8) | (message[3] << 0); message += 4; a->rdlength = (message[0] << 8) | message[1]; message += 2; a->rdata = message; a->rdoffset = offset + i + RRFIXEDSZ; DPRINTF("i=%d,rdlength=%d\n", i, a->rdlength); return i + RRFIXEDSZ + a->rdlength;}#endif#ifdef L_encodepint __encode_packet(struct resolv_header *h, struct resolv_question **q, struct resolv_answer **an, struct resolv_answer **ns, struct resolv_answer **ar, unsigned char *dest, int maxlen){ int i, total = 0; int j; i = __encode_header(h, dest, maxlen); if (i < 0) return i; dest += i; maxlen -= i; total += i; for (j = 0; j < h->qdcount; j++) { i = __encode_question(q[j], dest, maxlen); if (i < 0) return i; dest += i; maxlen -= i; total += i; } for (j = 0; j < h->ancount; j++) { i = __encode_answer(an[j], dest, maxlen); if (i < 0) return i; dest += i; maxlen -= i; total += i; } for (j = 0; j < h->nscount; j++) { i = __encode_answer(ns[j], dest, maxlen); if (i < 0) return i; dest += i; maxlen -= i; total += i; } for (j = 0; j < h->arcount; j++) { i = __encode_answer(ar[j], dest, maxlen); if (i < 0) return i; dest += i; maxlen -= i; total += i; } return total;}#endif#ifdef L_decodepint __decode_packet(unsigned char *data, struct resolv_header *h){ return __decode_header(data, h);}#endif#ifdef L_formqueryint __form_query(int id, const char *name, int type, unsigned char *packet, int maxlen){ struct resolv_header h; struct resolv_question q; int i, j; memset(&h, 0, sizeof(h)); h.id = id; h.qdcount = 1; q.dotted = (char *) name; q.qtype = type; q.qclass = C_IN; /* CLASS_IN */ i = __encode_header(&h, packet, maxlen); if (i < 0) return i;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -