resolve.c

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

C
712
字号
	rr->u.sshfp->type      = p[1];	rr->u.sshfp->sshfp_len  = sshfp_len;	memcpy (rr->u.sshfp->sshfp_data, p + 2, sshfp_len);	break;    }    case rk_ns_t_ds: {	size_t digest_len;	if (size < 4) {	    dns_free_rr(rr);	    return -1;	}	digest_len = size - 4;	rr->u.ds = malloc (sizeof(*rr->u.ds) + digest_len - 1);	if (rr->u.ds == NULL) {	    dns_free_rr(rr);	    return -1;	}	rr->u.ds->key_tag     = (p[0] << 8) | p[1];	rr->u.ds->algorithm   = p[2];	rr->u.ds->digest_type = p[3];	rr->u.ds->digest_len  = digest_len;	memcpy (rr->u.ds->digest_data, p + 4, digest_len);	break;    }    default:	rr->u.data = (unsigned char*)malloc(size);	if(size != 0 && rr->u.data == NULL) {	    dns_free_rr(rr);	    return -1;	}	if (size)	    memcpy(rr->u.data, p, size);    }    *pp = p + size;    *ret_rr = rr;    return 0;}#ifndef TEST_RESOLVEstatic#endifstruct dns_reply*parse_reply(const unsigned char *data, size_t len){    const unsigned char *p;    int status;    int i;    char host[MAXDNAME];    const unsigned char *end_data = data + len;    struct dns_reply *r;    struct resource_record **rr;        r = calloc(1, sizeof(*r));    if (r == NULL)	return NULL;    p = data;    r->h.id = (p[0] << 8) | p[1];    r->h.flags = 0;    if (p[2] & 0x01)	r->h.flags |= rk_DNS_HEADER_RESPONSE_FLAG;    r->h.opcode = (p[2] >> 1) & 0xf;    if (p[2] & 0x20)	r->h.flags |= rk_DNS_HEADER_AUTHORITIVE_ANSWER;    if (p[2] & 0x40)	r->h.flags |= rk_DNS_HEADER_TRUNCATED_MESSAGE;    if (p[2] & 0x80)	r->h.flags |= rk_DNS_HEADER_RECURSION_DESIRED;    if (p[3] & 0x01)	r->h.flags |= rk_DNS_HEADER_RECURSION_AVAILABLE;    if (p[3] & 0x04)	r->h.flags |= rk_DNS_HEADER_AUTHORITIVE_ANSWER;    if (p[3] & 0x08)	r->h.flags |= rk_DNS_HEADER_CHECKING_DISABLED;    r->h.response_code = (p[3] >> 4) & 0xf;    r->h.qdcount = (p[4] << 8) | p[5];    r->h.ancount = (p[6] << 8) | p[7];    r->h.nscount = (p[8] << 8) | p[9];    r->h.arcount = (p[10] << 8) | p[11];    p += 12;    if(r->h.qdcount != 1) {	free(r);	return NULL;    }    status = dn_expand(data, end_data, p, host, sizeof(host));    if(status < 0){	dns_free_data(r);	return NULL;    }    r->q.domain = strdup(host);    if(r->q.domain == NULL) {	dns_free_data(r);	return NULL;    }    if (p + status + 4 > end_data) {	dns_free_data(r);	return NULL;    }    p += status;    r->q.type = (p[0] << 8 | p[1]);    p += 2;    r->q.class = (p[0] << 8 | p[1]);    p += 2;        rr = &r->head;    for(i = 0; i < r->h.ancount; i++) {	if(parse_record(data, end_data, &p, rr) != 0) {	    dns_free_data(r);	    return NULL;	}	rr = &(*rr)->next;    }    for(i = 0; i < r->h.nscount; i++) {	if(parse_record(data, end_data, &p, rr) != 0) {	    dns_free_data(r);	    return NULL;	}	rr = &(*rr)->next;    }    for(i = 0; i < r->h.arcount; i++) {	if(parse_record(data, end_data, &p, rr) != 0) {	    dns_free_data(r);	    return NULL;	}	rr = &(*rr)->next;    }    *rr = NULL;    return r;}#ifdef HAVE_RES_NSEARCH#ifdef HAVE_RES_NDESTROY#define rk_res_free(x) res_ndestroy(x)#else#define rk_res_free(x) res_nclose(x)#endif#endifstatic struct dns_reply *dns_lookup_int(const char *domain, int rr_class, int rr_type){    struct dns_reply *r;    unsigned char *reply = NULL;    int size;    int len;#ifdef HAVE_RES_NSEARCH    struct __res_state state;    memset(&state, 0, sizeof(state));    if(res_ninit(&state))	return NULL; /* is this the best we can do? */#elif defined(HAVE__RES)    u_long old_options = 0;#endif        size = 0;    len = 1000;    do {	if (reply) {	    free(reply);	    reply = NULL;	}	if (size <= len)	    size = len;	if (_resolve_debug) {#ifdef HAVE_RES_NSEARCH	    state.options |= RES_DEBUG;#elif defined(HAVE__RES)	    old_options = _res.options;	    _res.options |= RES_DEBUG;#endif	    fprintf(stderr, "dns_lookup(%s, %d, %s), buffer size %d\n", domain,		    rr_class, dns_type_to_string(rr_type), size);	}	reply = malloc(size);	if (reply == NULL) {#ifdef HAVE_RES_NSEARCH	    rk_res_free(&state);#endif	    return NULL;	}#ifdef HAVE_RES_NSEARCH	len = res_nsearch(&state, domain, rr_class, rr_type, reply, size);#else	len = res_search(domain, rr_class, rr_type, reply, size);#endif	if (_resolve_debug) {#if defined(HAVE__RES) && !defined(HAVE_RES_NSEARCH)	    _res.options = old_options;#endif	    fprintf(stderr, "dns_lookup(%s, %d, %s) --> %d\n",		    domain, rr_class, dns_type_to_string(rr_type), len);	}	if (len < 0) {#ifdef HAVE_RES_NSEARCH	    rk_res_free(&state);#endif	    free(reply);	    return NULL;	}    } while (size < len && len < rk_DNS_MAX_PACKET_SIZE);#ifdef HAVE_RES_NSEARCH    rk_res_free(&state);#endif    len = min(len, size);    r = parse_reply(reply, len);    free(reply);    return r;}struct dns_reply * ROKEN_LIB_FUNCTIONdns_lookup(const char *domain, const char *type_name){    int type;        type = dns_string_to_type(type_name);    if(type == -1) {	if(_resolve_debug)	    fprintf(stderr, "dns_lookup: unknown resource type: `%s'\n", 		    type_name);	return NULL;    }    return dns_lookup_int(domain, C_IN, type);}static intcompare_srv(const void *a, const void *b){    const struct resource_record *const* aa = a, *const* bb = b;    if((*aa)->u.srv->priority == (*bb)->u.srv->priority)	return ((*aa)->u.srv->weight - (*bb)->u.srv->weight);    return ((*aa)->u.srv->priority - (*bb)->u.srv->priority);}#ifndef HAVE_RANDOM#define random() rand()#endif/* try to rearrange the srv-records by the algorithm in RFC2782 */void ROKEN_LIB_FUNCTIONdns_srv_order(struct dns_reply *r){    struct resource_record **srvs, **ss, **headp;    struct resource_record *rr;    int num_srv = 0;#if defined(HAVE_INITSTATE) && defined(HAVE_SETSTATE)    int state[256 / sizeof(int)];    char *oldstate;#endif    for(rr = r->head; rr; rr = rr->next) 	if(rr->type == rk_ns_t_srv)	    num_srv++;    if(num_srv == 0)	return;    srvs = malloc(num_srv * sizeof(*srvs));    if(srvs == NULL)	return; /* XXX not much to do here */        /* unlink all srv-records from the linked list and put them in       a vector */    for(ss = srvs, headp = &r->head; *headp; )	if((*headp)->type == rk_ns_t_srv) {	    *ss = *headp;	    *headp = (*headp)->next;	    (*ss)->next = NULL;	    ss++;	} else	    headp = &(*headp)->next;        /* sort them by priority and weight */    qsort(srvs, num_srv, sizeof(*srvs), compare_srv);#if defined(HAVE_INITSTATE) && defined(HAVE_SETSTATE)    oldstate = initstate(time(NULL), (char*)state, sizeof(state));#endif    headp = &r->head;        for(ss = srvs; ss < srvs + num_srv; ) {	int sum, rnd, count;	struct resource_record **ee, **tt;	/* find the last record with the same priority and count the           sum of all weights */	for(sum = 0, tt = ss; tt < srvs + num_srv; tt++) {	    assert(*tt != NULL);	    if((*tt)->u.srv->priority != (*ss)->u.srv->priority)		break;	    sum += (*tt)->u.srv->weight;	}	ee = tt;	/* ss is now the first record of this priority and ee is the           first of the next */	while(ss < ee) {	    rnd = random() % (sum + 1);	    for(count = 0, tt = ss; ; tt++) {		if(*tt == NULL)		    continue;		count += (*tt)->u.srv->weight;		if(count >= rnd)		    break;	    }	    assert(tt < ee);	    /* insert the selected record at the tail (of the head) of               the list */	    (*tt)->next = *headp;	    *headp = *tt;	    headp = &(*tt)->next;	    sum -= (*tt)->u.srv->weight;	    *tt = NULL;	    while(ss < ee && *ss == NULL)		ss++;	}    }    #if defined(HAVE_INITSTATE) && defined(HAVE_SETSTATE)    setstate(oldstate);#endif    free(srvs);    return;}#else /* NOT defined(HAVE_RES_SEARCH) && defined(HAVE_DN_EXPAND) */struct dns_reply * ROKEN_LIB_FUNCTIONdns_lookup(const char *domain, const char *type_name){    return NULL;}void ROKEN_LIB_FUNCTIONdns_free_data(struct dns_reply *r){}void ROKEN_LIB_FUNCTIONdns_srv_order(struct dns_reply *r){}#endif

⌨️ 快捷键说明

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