?? 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. * * 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 * 6-2-2001 Craig Graham * - Ported to ISS OS * - Added better answer search algorithm * - Added support for static builtin name server list * - Added defines to use the uC/IP UDP API directly instead of going via the * (slightly slower) generic socket API. * - Added uC/IP style timeouts on waiting for a response (ISS OS doesn't support signals) */#define USE_UCIP_DIRECT 1#include <config.h>#include <string.h>#include <stdio.h>#include <errno.h>#include <sys/socket.h>#if (USE_UCIP_DIRECT==0)#include <signal.h>#include <sys/types.h>#include <netinet/in.h>#include <arpa/inet.h>#endif#include "netconf.h"#include "net.h"#include "netbuf.h"#include "netip.h"//#include "net_adl.h"#include "nettimer.h"#include "netudp.h"#include <stdlib.h>#include <unistd.h>//#include <cfgfile.h>#include "resolv.h"#include "nameser.h"#include <stdarg.h>#ifdef ISS_OS#include <adl.h>#include <adl_ls808.h>#else#define UNCACHED(X) (X)#endif#define MAX_RECURSE 5#define REPLY_TIMEOUT 10#define MAX_RETRIES 15#define MAX_SERVERS 3#define MAX_SEARCH 4#define L_encodeh#define L_decodeh#define L_encoded#define L_decoded#define L_lengthd#define L_encodeq#define L_decodeq#define L_lengthq#define L_encodea#define L_decodea#define L_encodep#define L_decodep#define L_formquery#define L_dnslookup#define L_resolveaddress#define L_resolvemailbox#define L_opennameservers#define L_closenameservers#define L_resolvename#define L_gethostbyname//#define L_gethostbyaddr#if 0#define RESOLVDEBUG(A) printf A#else#define RESOLVDEBUG(A)#endif/** * Switch. * 0=use /etc/resolv.conf for nameserver list, * 1=static nameserver list */#define USE_RESOLV_CONF 0#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++) break; 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'; } RESOLVDEBUG(("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); printf("a->dotted=%p\n",a->dotted); 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; RESOLVDEBUG(("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; j = encode_question(&q, packet + i, maxlen - i); if (j < 0) return j; return i + j;}#endif#ifdef L_dnslookupstatic volatile int dns_caught_signal = 0;#if USE_UCIP_DIRECTextern void unblock(int sockfd);static void dns_timeout(void *p){ dns_caught_signal = 1; udpUnblockRead((int)p);}#elsevoid dns_catch_signal(int signo){ dns_caught_signal = 1;}#endifint dns_lookup(const char *name, int type, int nscount, char **nsip, unsigned char **outpacket, struct resolv_answer *a){ static int id = 1; int i, j, len, fd, pos; static int ns = 0; struct sockaddr_in sa;#if (USE_UCIP_DIRECT==0) int oldalarm; __sighandler_t oldhandler;#endif struct resolv_header h; struct resolv_question q; int retries = 0; unsigned char * packet = malloc(PACKETSZ); unsigned char * lookup = malloc(MAXDNAME); int variant = 0; extern int searchdomains; extern const char * searchdomain[MAX_SEARCH]; struct resolv_answer tmpA; fd = -1; if (!packet || !lookup || !nscount) goto fail; RESOLVDEBUG(("Looking up type %d answer for '%s'\n", type, name)); ns %= nscount; a->atype=0; while (retries++ < MAX_RETRIES) { if (fd != -1)#if USE_UCIP_DIRECT udpClose(fd);#else close(fd);#endif#if USE_UCIP_DIRECT fd=udpOpen();#else fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);#endif if (fd == -1) goto fail; memset(packet, 0, PACKETSZ); memset(&h, 0, sizeof(h)); h.id = ++id; h.qdcount = 1; h.rd = 1; RESOLVDEBUG(("encoding header\n", h.rd)); i = encode_header(&h, packet, PACKETSZ); if (i < 0) goto fail; strncpy(lookup,name,MAXDNAME); if (variant < searchdomains) { strncat(lookup,".", MAXDNAME); strncat(lookup,searchdomain[variant], MAXDNAME); } RESOLVDEBUG(("lookup name: %s\n", lookup)); q.dotted = (char *)lookup; q.qtype = type; q.qclass = C_IN; /* CLASS_IN */ j = encode_question(&q, packet+i, PACKETSZ-i); if (j < 0) goto fail; len = i + j; RESOLVDEBUG(("On try %d, sending query to port %d of machine %s\n", retries, NAMESERVER_PORT, nsip[ns])); sa.sin_family = AF_INET; sa.sin_port = htons(NAMESERVER_PORT); sa.sin_addr.s_addr = inet_addr(nsip[ns]);#if USE_UCIP_DIRECT if (udpConnect(fd, UNCACHED(&sa), 0) == -1)#else if (connect(fd, (struct sockaddr *) &sa, sizeof(sa)) == -1)#endif { if (errno == ENETUNREACH) { /* routing error, presume not transient */ goto tryall; } else{ /* retry */ continue; } } RESOLVDEBUG(("Transmitting packet of length %d, id=%d, qr=%d\n", len, h.id, h.qr));#if USE_UCIP_DIRECT udpWrite(fd,UNCACHED(packet),len);#else write(fd, packet, len);#endif
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -