resolve.c

来自「samba最新软件」· C语言 代码 · 共 712 行 · 第 1/2 页

C
712
字号
/* * Copyright (c) 1995 - 2006 Kungliga Tekniska H鰃skolan * (Royal Institute of Technology, Stockholm, Sweden). * 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. *  * 3. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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. */#ifdef HAVE_CONFIG_H#include <config.h>#endif#include <roken.h>#ifdef HAVE_ARPA_NAMESER_H#include <arpa/nameser.h>#endif#ifdef HAVE_RESOLV_H#include <resolv.h>#endif#include "resolve.h"#include <assert.h>RCSID("$Id: resolve.c 19869 2007-01-12 16:03:14Z lha $");#ifdef _AIX /* AIX have broken res_nsearch() in 5.1 (5.0 also ?) */#undef HAVE_RES_NSEARCH#endif#define DECL(X) {#X, rk_ns_t_##X}static struct stot{    const char *name;    int type;}stot[] = {    DECL(a),    DECL(aaaa),    DECL(ns),    DECL(cname),    DECL(soa),    DECL(ptr),    DECL(mx),    DECL(txt),    DECL(afsdb),    DECL(sig),    DECL(key),    DECL(srv),    DECL(naptr),    DECL(sshfp),    DECL(ds),    {NULL, 	0}};int _resolve_debug = 0;int ROKEN_LIB_FUNCTIONdns_string_to_type(const char *name){    struct stot *p = stot;    for(p = stot; p->name; p++)	if(strcasecmp(name, p->name) == 0)	    return p->type;    return -1;}const char * ROKEN_LIB_FUNCTIONdns_type_to_string(int type){    struct stot *p = stot;    for(p = stot; p->name; p++)	if(type == p->type)	    return p->name;    return NULL;}#if (defined(HAVE_RES_SEARCH) || defined(HAVE_RES_NSEARCH)) && defined(HAVE_DN_EXPAND)static voiddns_free_rr(struct resource_record *rr){    if(rr->domain)	free(rr->domain);    if(rr->u.data)	free(rr->u.data);    free(rr);}void ROKEN_LIB_FUNCTIONdns_free_data(struct dns_reply *r){    struct resource_record *rr;    if(r->q.domain)	free(r->q.domain);    for(rr = r->head; rr;){	struct resource_record *tmp = rr;	rr = rr->next;	dns_free_rr(tmp);    }    free (r);}static intparse_record(const unsigned char *data, const unsigned char *end_data, 	     const unsigned char **pp, struct resource_record **ret_rr){    struct resource_record *rr;    int type, class, ttl, size;    int status;    char host[MAXDNAME];    const unsigned char *p = *pp;    *ret_rr = NULL;    status = dn_expand(data, end_data, p, host, sizeof(host));    if(status < 0) 	return -1;    if (p + status + 10 > end_data)	return -1;    p += status;    type = (p[0] << 8) | p[1];    p += 2;    class = (p[0] << 8) | p[1];    p += 2;    ttl = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];    p += 4;    size = (p[0] << 8) | p[1];    p += 2;    if (p + size > end_data)	return -1;    rr = calloc(1, sizeof(*rr));    if(rr == NULL) 	return -1;    rr->domain = strdup(host);    if(rr->domain == NULL) {	dns_free_rr(rr);	return -1;    }    rr->type = type;    rr->class = class;    rr->ttl = ttl;    rr->size = size;    switch(type){    case rk_ns_t_ns:    case rk_ns_t_cname:    case rk_ns_t_ptr:	status = dn_expand(data, end_data, p, host, sizeof(host));	if(status < 0) {	    dns_free_rr(rr);	    return -1;	}	rr->u.txt = strdup(host);	if(rr->u.txt == NULL) {	    dns_free_rr(rr);	    return -1;	}	break;    case rk_ns_t_mx:    case rk_ns_t_afsdb:{	size_t hostlen;	status = dn_expand(data, end_data, p + 2, host, sizeof(host));	if(status < 0){	    dns_free_rr(rr);	    return -1;	}	if (status + 2 > size) {	    dns_free_rr(rr);	    return -1;	}	hostlen = strlen(host);	rr->u.mx = (struct mx_record*)malloc(sizeof(struct mx_record) + 						hostlen);	if(rr->u.mx == NULL) {	    dns_free_rr(rr);	    return -1;	}	rr->u.mx->preference = (p[0] << 8) | p[1];	strlcpy(rr->u.mx->domain, host, hostlen + 1);	break;    }    case rk_ns_t_srv:{	size_t hostlen;	status = dn_expand(data, end_data, p + 6, host, sizeof(host));	if(status < 0){	    dns_free_rr(rr);	    return -1;	}	if (status + 6 > size) {	    dns_free_rr(rr);	    return -1;	}	hostlen = strlen(host);	rr->u.srv = 	    (struct srv_record*)malloc(sizeof(struct srv_record) + 				       hostlen);	if(rr->u.srv == NULL) {	    dns_free_rr(rr);	    return -1;	}	rr->u.srv->priority = (p[0] << 8) | p[1];	rr->u.srv->weight = (p[2] << 8) | p[3];	rr->u.srv->port = (p[4] << 8) | p[5];	strlcpy(rr->u.srv->target, host, hostlen + 1);	break;    }    case rk_ns_t_txt:{	if(size == 0 || size < *p + 1) {	    dns_free_rr(rr);	    return -1;	}	rr->u.txt = (char*)malloc(*p + 1);	if(rr->u.txt == NULL) {	    dns_free_rr(rr);	    return -1;	}	strncpy(rr->u.txt, (const char*)(p + 1), *p);	rr->u.txt[*p] = '\0';	break;    }    case rk_ns_t_key : {	size_t key_len;	if (size < 4) {	    dns_free_rr(rr);	    return -1;	}	key_len = size - 4;	rr->u.key = malloc (sizeof(*rr->u.key) + key_len - 1);	if (rr->u.key == NULL) {	    dns_free_rr(rr);	    return -1;	}	rr->u.key->flags     = (p[0] << 8) | p[1];	rr->u.key->protocol  = p[2];	rr->u.key->algorithm = p[3];	rr->u.key->key_len   = key_len;	memcpy (rr->u.key->key_data, p + 4, key_len);	break;    }    case rk_ns_t_sig : {	size_t sig_len, hostlen;	if(size <= 18) {	    dns_free_rr(rr);	    return -1;	}	status = dn_expand (data, end_data, p + 18, host, sizeof(host));	if (status < 0) {	    dns_free_rr(rr);	    return -1;	}	if (status + 18 > size) {	    dns_free_rr(rr);	    return -1;	}	/* the signer name is placed after the sig_data, to make it           easy to free this structure; the size calculation below           includes the zero-termination if the structure itself.	   don't you just love C?	*/	sig_len = size - 18 - status;	hostlen = strlen(host);	rr->u.sig = malloc(sizeof(*rr->u.sig)			      + hostlen + sig_len);	if (rr->u.sig == NULL) {	    dns_free_rr(rr);	    return -1;	}	rr->u.sig->type           = (p[0] << 8) | p[1];	rr->u.sig->algorithm      = p[2];	rr->u.sig->labels         = p[3];	rr->u.sig->orig_ttl       = (p[4] << 24) | (p[5] << 16)	    | (p[6] << 8) | p[7];	rr->u.sig->sig_expiration = (p[8] << 24) | (p[9] << 16)	    | (p[10] << 8) | p[11];	rr->u.sig->sig_inception  = (p[12] << 24) | (p[13] << 16)	    | (p[14] << 8) | p[15];	rr->u.sig->key_tag        = (p[16] << 8) | p[17];	rr->u.sig->sig_len        = sig_len;	memcpy (rr->u.sig->sig_data, p + 18 + status, sig_len);	rr->u.sig->signer         = &rr->u.sig->sig_data[sig_len];	strlcpy(rr->u.sig->signer, host, hostlen + 1);	break;    }    case rk_ns_t_cert : {	size_t cert_len;	if (size < 5) {	    dns_free_rr(rr);	    return -1;	}	cert_len = size - 5;	rr->u.cert = malloc (sizeof(*rr->u.cert) + cert_len - 1);	if (rr->u.cert == NULL) {	    dns_free_rr(rr);	    return -1;	}	rr->u.cert->type      = (p[0] << 8) | p[1];	rr->u.cert->tag       = (p[2] << 8) | p[3];	rr->u.cert->algorithm = p[4];	rr->u.cert->cert_len  = cert_len;	memcpy (rr->u.cert->cert_data, p + 5, cert_len);	break;    }    case rk_ns_t_sshfp : {	size_t sshfp_len;	if (size < 2) {	    dns_free_rr(rr);	    return -1;	}	sshfp_len = size - 2;	rr->u.sshfp = malloc (sizeof(*rr->u.sshfp) + sshfp_len - 1);	if (rr->u.sshfp == NULL) {	    dns_free_rr(rr);	    return -1;	}	rr->u.sshfp->algorithm = p[0];

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?