Example #1
0
static char *
target_name(const unsigned char *target) {
	char buf[NS_MAXDNAME];

	if (ns_name_ntop(target, buf, sizeof buf) == -1) {
		perror("ns_name_ntop");
		exit(EXIT_FAILURE);
	}
	return (strdup(buf));
}
Example #2
0
static void print_flag_qname(const u_char *qname, uint16_t setflags,
                             uint16_t invflag) {
    char tmp[XT_DNS_MAXSIZE];
    if (XT_DNS_FLAG_QNAME & setflags) {
        if (XT_DNS_FLAG_QNAME & invflag) {
            printf("! ");
        }
        if (ns_name_ntop(qname, tmp, sizeof(tmp)) == -1)
            xtables_error(PARAMETER_PROBLEM, "Unknown qname %s\n", tmp);
        printf("--qname %s ", tmp);
    }
}
Example #3
0
File: ns_name.c Project: aosm/bind
int
mdn_prepend(ns_name_ntop)(const u_char *src, char *dst, size_t dstsiz) {
	return (ns_name_ntop(src, dst, dstsiz));
}
Example #4
0
  DNS::HostMap DNS::resolve( const std::string& service, const std::string& proto,
                             const std::string& domain, const LogSink& logInstance )
  {
    buffer srvbuf;
    bool error = false;

    const std::string dname = "_" +  service + "._" + proto;

    if( !domain.empty() )
      srvbuf.len = res_querydomain( dname.c_str(), const_cast<char*>( domain.c_str() ),
                                    C_IN, T_SRV, srvbuf.buf, NS_PACKETSZ );
    else
      srvbuf.len = res_query( dname.c_str(), C_IN, T_SRV, srvbuf.buf, NS_PACKETSZ );

    if( srvbuf.len < 0 )
      return defaultHostMap( domain, logInstance );

    HEADER* hdr = (HEADER*)srvbuf.buf;
    unsigned char* here = srvbuf.buf + NS_HFIXEDSZ;

    if( ( hdr->tc ) || ( srvbuf.len < NS_HFIXEDSZ ) )
      error = true;

    if( hdr->rcode >= 1 && hdr->rcode <= 5 )
      error = true;

    if( ntohs( hdr->ancount ) == 0 )
      error = true;

    if( ntohs( hdr->ancount ) > NS_PACKETSZ )
      error = true;

    int cnt;
    for( cnt = ntohs( hdr->qdcount ); cnt>0; --cnt )
    {
      int strlen = dn_skipname( here, srvbuf.buf + srvbuf.len );
      here += strlen + NS_QFIXEDSZ;
    }

    unsigned char* srv[NS_PACKETSZ];
    int srvnum = 0;
    for( cnt = ntohs( hdr->ancount ); cnt>0; --cnt )
    {
      int strlen = dn_skipname( here, srvbuf.buf + srvbuf.len );
      here += strlen;
      srv[srvnum++] = here;
      here += SRV_FIXEDSZ;
      here += dn_skipname( here, srvbuf.buf + srvbuf.len );
    }

    if( error )
    {
      return defaultHostMap( domain, logInstance );
    }

    // (q)sort here

    HostMap servers;
    for( cnt=0; cnt<srvnum; ++cnt )
    {
      name srvname;

      if( ns_name_ntop( srv[cnt] + SRV_SERVER, (char*)srvname, NS_MAXDNAME ) < 0 )
        printf( "handle this error!\n" );

      servers[(char*)srvname] = ns_get16( srv[cnt] + SRV_PORT );
    }

    return servers;
  }
Example #5
0
void
verify_next_assertion(val_context_t * ctx,
                      struct val_digested_auth_chain *as,
                      struct val_digested_auth_chain *the_trust,
                      u_int32_t flags)
{
    struct rrset_rec *the_set;
    struct rrset_rr  *the_sig;
    u_char       *signby_name_n;
    u_int16_t       signby_footprint_n;
    val_dnskey_rdata_t dnskey;
    int             is_a_wildcard;
    struct rrset_rr  *nextrr;
    struct rrset_rr  *keyrr;
    u_int16_t       tag_h;
    char            name_p[NS_MAXDNAME];

    if ((as == NULL) || (as->val_ac_rrset.ac_data == NULL) || (the_trust == NULL)) {
        val_log(ctx, LOG_INFO, "verify_next_assertion(): Cannot verify assertion - no data");
        return;
    }

    the_set = as->val_ac_rrset.ac_data;
    dnskey.public_key = NULL;


    if (-1 == ns_name_ntop(the_set->rrs_name_n, name_p, sizeof(name_p)))
        snprintf(name_p, sizeof(name_p), "unknown/error");

    if (the_set->rrs_sig == NULL) {
        val_log(ctx, LOG_INFO, "verify_next_assertion(): RRSIG is missing");
        as->val_ac_status = VAL_AC_RRSIG_MISSING;
        return;
    }

    if (the_set->rrs_type_h != ns_t_dnskey) {
        /*
         * trust path contains the key 
         */
        if (the_trust->val_ac_rrset.ac_data == NULL) {
            val_log(ctx, LOG_INFO, "verify_next_assertion(): Key is empty");
            as->val_ac_status = VAL_AC_DNSKEY_MISSING;
            return;
        }
        keyrr = the_trust->val_ac_rrset.ac_data->rrs_data;
    } else {
        /*
         * data itself contains the key 
         */
        if (the_set->rrs_data == NULL) {
            val_log(ctx, LOG_INFO, "verify_next_assertion(): Key is empty");
            as->val_ac_status = VAL_AC_DNSKEY_MISSING;
            return;
        }
        keyrr = the_set->rrs_data;
    }

    for (the_sig = the_set->rrs_sig;
         the_sig; the_sig = the_sig->rr_next) {

        /*
         * do wildcard processing 
         */
        if (!check_label_count(the_set, the_sig, &is_a_wildcard)) {
            SET_STATUS(as->val_ac_status, the_sig,
                       VAL_AC_WRONG_LABEL_COUNT);
            val_log(ctx, LOG_INFO, "verify_next_assertion(): Incorrect RRSIG label count");
            continue;
        }

        /*
         * for each sig, identify key, 
         */
        if (VAL_NO_ERROR != identify_key_from_sig(the_sig, &signby_name_n,
                              &signby_footprint_n)) {
            SET_STATUS(as->val_ac_status, the_sig,
                       VAL_AC_INVALID_RRSIG);
            val_log(ctx, LOG_INFO, "verify_next_assertion(): Cannot extract key footprint from RRSIG");
            continue;
        }

        tag_h = ntohs(signby_footprint_n);
        for (nextrr = keyrr; nextrr; nextrr = nextrr->rr_next) {
            int             is_verified = 0;
            if (VAL_NO_ERROR != val_parse_dnskey_rdata(nextrr->rr_rdata,
                                             nextrr->rr_rdata_length,
                                             &dnskey)) {
                val_log(ctx, LOG_INFO, "verify_next_assertion(): Cannot parse DNSKEY data");
                nextrr->rr_status = VAL_AC_INVALID_KEY;
                continue;
            }

            dnskey.next = NULL;
            if (dnskey.key_tag != tag_h) {
                if (dnskey.public_key != NULL) {
                    FREE(dnskey.public_key);
                    dnskey.public_key = NULL;
                }
                continue;
            }

            val_log(ctx, LOG_DEBUG, "verify_next_assertion(): Found potential matching DNSKEY for RRSIG");

            /*
             * check the signature 
             */
            is_verified = do_verify(ctx, signby_name_n,
                      &nextrr->rr_status,
                      &the_sig->rr_status,
                      the_set, the_sig, &dnskey, is_a_wildcard, flags);

            /*
             * There might be multiple keys with the same key tag; set this as
             * the signing key only if we dont have other status for this key
             */
            SET_STATUS(as->val_ac_status, the_sig, the_sig->rr_status);
            if (nextrr->rr_status == VAL_AC_UNSET) {
                nextrr->rr_status = VAL_AC_SIGNING_KEY;
            }

            if (is_verified) {

                val_log(ctx, LOG_INFO, "verify_next_assertion(): Verified a RRSIG for %s (%s) using a DNSKEY (%d)",
                        name_p, p_type(the_set->rrs_type_h),
                        dnskey.key_tag);

                if ( as->val_ac_status == VAL_AC_TRUST ||
                    nextrr->rr_status == VAL_AC_TRUST_POINT) {
                    /* we've verified a trust anchor */
                    as->val_ac_status = VAL_AC_TRUST; 
                    val_log(ctx, LOG_INFO, "verify_next_assertion(): verification traces back to trust anchor");
                    if (dnskey.public_key != NULL) {
                        FREE(dnskey.public_key);
                        dnskey.public_key = NULL;
                    }
                    return;
                }
            
                /* Check if we're trying to verify some key in the authentication chain */
                if ( the_set->rrs_type_h == ns_t_dnskey && 
                    as != the_trust) {
                    /* Check if we have reached our trust key */
                    /*
                     * If this record contains a DNSKEY, check if the DS record contains this key 
                     * DNSKEYs cannot be wildcard expanded, so VAL_AC_WCARD_VERIFIED does not
                     * count as a good sig
                     * Create the link even if the DNSKEY algorithm is unknown since this 
                     * may be the provably insecure case
                     */
                    /*
                     * follow the trust path 
                     */
                    struct rrset_rr  *dsrec =
                        the_trust->val_ac_rrset.ac_data->rrs_data;
                    while (dsrec) {
                        val_ds_rdata_t  ds;
                        ds.d_hash = NULL;
                        int retval = val_parse_ds_rdata(dsrec->rr_rdata,
                                       dsrec->rr_rdata_length, &ds);
                        if(retval == VAL_NOT_IMPLEMENTED) {
                            val_log(ctx, LOG_INFO, "verify_next_assertion(): DS hash not supported");
                            dsrec->rr_status = VAL_AC_ALGORITHM_NOT_SUPPORTED;
                        } else if (retval != VAL_NO_ERROR) {
                            val_log(ctx, LOG_INFO, "verify_next_assertion(): DS parse error");
                            dsrec->rr_status = VAL_AC_INVALID_DS;
                        } else if (DNSKEY_MATCHES_DS(ctx, &dnskey, &ds, 
                                    the_set->rrs_name_n, nextrr, 
                                    &dsrec->rr_status)) {
                            val_log(ctx, LOG_DEBUG, 
                                    "verify_next_assertion(): DNSKEY tag (%d) matches DS tag (%d)",
                                    (&dnskey)->key_tag,                                         
                                    (&ds)->d_keytag);
                            /*
                             * the first match is enough 
                             */
                            nextrr->rr_status = VAL_AC_VERIFIED_LINK;
                            FREE(ds.d_hash);
                            ds.d_hash = NULL;
                            if (dnskey.public_key) {
                                FREE(dnskey.public_key);
                                dnskey.public_key = NULL;
                            }
                            val_log(ctx, LOG_INFO, "verify_next_assertion(): Key links upward");
                            return;
                        } else {
                            /*
                             * Didn't find a valid entry in the DS record set 
                             * Not necessarily a problem, since there is no requirement that a DS be present
                             * If none match, then we set the status accordingly. See below.
                             */
                            nextrr->rr_status = VAL_AC_DS_NOMATCH;
                        } 

                        if (ds.d_hash != NULL)
                            FREE(ds.d_hash);

                        dsrec = dsrec->rr_next;
                    }
                }
            } 

            if (dnskey.public_key != NULL) {
                FREE(dnskey.public_key);
            }
            dnskey.public_key = NULL;
        }

        val_log(ctx, LOG_INFO, "verify_next_assertion(): Could not link this RRSIG to a DNSKEY");
        SET_STATUS(as->val_ac_status, the_sig, VAL_AC_DNSKEY_NOMATCH);
    }
        
    /* 
     * If we reach here and we're a keyset, we either didn't verify the keyset or
     * didn't verify the link from the key to the DS 
     */ 
    if (the_set->rrs_type_h == ns_t_dnskey){
        as->val_ac_status = VAL_AC_NO_LINK;
    }
}
Example #6
0
/* Setup a client socket for the named service over the given protocol under
 * the given domain name.
 */
static int insrv_lookup (int (*mksox) (int,const struct sockaddr *,socklen_t),
			char *service, char *proto, char *domain,
			char *cnxhost, size_t cnxhlen, int *cnxport) {
	// 1. convert service/proto to svcnm
	// 2. construct SRV query for _service._proto.domain
	// 3. try connecting to all answers in turn
	// 4. if no SRV records exist, lookup A record to connect to on stdport
	// 5. return connection socket or error code

	iobuf query, names;
	name svcnm;
	int error=0;
	int ctr;
	int rnd;
	int sox=0;
	HEADER *nameshdr;
	unsigned char *here, *srv[MAXNUM_SRV], *ip;
	int num_srv=0;
	// Storage for fallback SRV list, constructed when DNS gives no SRV
	unsigned char fallbacksrv [2*(MAXCDNAME+SRV_FIXEDSZ+MAXCDNAME)];

	srv_flags &= ~SRV_GOT_MASK;
	srv_flags |=  SRV_GOT_SRV;

	strcpy (svcnm, "_");
	strcat (svcnm, service);
	strcat (svcnm, "._");
	strcat (svcnm, proto);

	// Note that SRV records are only defined for class IN
	if (domain) {
		names.len=res_querydomain (svcnm, domain,
				C_IN, T_SRV,
				names.buf, PACKETSZ);
	} else {
		names.len=res_query (svcnm,
				C_IN, T_SRV,
				names.buf, PACKETSZ);
	}
	if (names.len < 0) {
		error = -ENOENT;
		goto fallback;
	}
	nameshdr=(HEADER *) names.buf;
	here=names.buf + HFIXEDSZ;
	rnd=nameshdr->id; 	// Heck, gimme one reason why not!

	if ((names.len < HFIXEDSZ) || nameshdr->tc) {
		error = -EMSGSIZE;
	}
	switch (nameshdr->rcode) {
		case 1:
			error = -EFAULT;
			goto fallback;
		case 2:
			error = -EAGAIN;
			goto fallback;
		case 3:
			error = -ENOENT;
			goto fallback;
		case 4:
			error = -ENOSYS;
			goto fallback;
		case 5:
			error = -EPERM;
			goto fallback;
		default:
			break;
	}
	if (ntohs (nameshdr->ancount) == 0) {
		error = -ENOENT;
		goto fallback;
	}
	if (ntohs (nameshdr->ancount) > MAXNUM_SRV) {
		error = -ERANGE;
		goto fallback;
	}
	for (ctr=ntohs (nameshdr->qdcount); ctr>0; ctr--) {
		int strlen=dn_skipname (here, names.buf+names.len);
		here += strlen + QFIXEDSZ;
	}
	for (ctr=ntohs (nameshdr->ancount); ctr>0; ctr--) {
		int strlen=dn_skipname (here, names.buf+names.len);
		here += strlen;
		srv [num_srv++] = here;
		here += SRV_FIXEDSZ;
		here += dn_skipname (here, names.buf+names.len);
	}

	// In case an error occurred, there are no SRV records.
	// Fallback strategy now is: construct two. One with the domain name,
	// the other with the /standard/ service name prefixed.
	// Note: Assuming a domain without the service name prefixed!
fallback:
	if (error) {
		struct servent *servent = getservbyname (service, proto);

		srv_flags &= ~SRV_GOT_MASK;
		srv_flags |=  SRV_GOT_A;

		num_srv = 2;
		if (!servent) {
			return error; // First error returned
		}
		srv [0] = here = fallbacksrv;
		// Only few record fields are really needed:
		*(unsigned short *)(here + SRV_COST)   = htons (0);
		*(unsigned short *)(here + SRV_WEIGHT) = htons (0);
		*(unsigned short *)(here + SRV_PORT)   = servent->s_port;
		here += SRV_FIXEDSZ;
		if (domain) {
			here += dn_comp (domain, here, MAXCDNAME, NULL, NULL);
		}
		// Forget about the name whose SRV IN this is, no need for it
		srv [1] = here;
		// Only few record fields are really needed:
		*(unsigned short *)(here + SRV_COST)   = htons (1);
		*(unsigned short *)(here + SRV_WEIGHT) = htons (0);
		*(unsigned short *)(here + SRV_PORT)   = servent->s_port;
		here += SRV_FIXEDSZ;
		here += dn_comp (servent->s_name, here, MAXCDNAME, NULL, NULL);
		here--; // Go back to overwrite final zero byte
		if (domain) {
			here += dn_comp (domain, here, MAXCDNAME, NULL, NULL);
		}
		rnd = 1;
	}
	// End of fallback construction, making sure that variables are defined
	// srv[] points to the SRV RR, num_srv counts the number of entries.
	// Every SRV RR has at least cost, weight, port and servername set.
	
#ifdef DEBUG
	for (ctr=0; ctr<num_srv; ctr++) {
		name srvname;
		if (ns_name_ntop (srv [ctr]+SRV_SERVER, srvname, MAXDNAME) < 0) {
			return -errno;
		}
		printf ("Considering SRV server %d %d %d\t%s\n",
				ns_get16 (srv [ctr]+SRV_COST),
				ns_get16 (srv [ctr]+SRV_WEIGHT),
				ns_get16 (srv [ctr]+SRV_PORT),
				srvname
			);
	}
#endif

	// Overwrite weight with rnd-spread version to divide load over weights
	for (ctr=0; ctr<num_srv; ctr++) {
		*(unsigned short *)(srv [ctr]+SRV_WEIGHT)
			= rnd % (1+ns_get16 (srv [ctr]+SRV_WEIGHT));
	}
	qsort (srv, num_srv, sizeof (*srv), srvcmp);


	for (ctr=0; ctr<num_srv; ctr++) {
		name srvname;
		struct hostent *host;
		// Open a socket to connect with
		int sox = socket (PF_INET, (*proto!='u')? SOCK_STREAM: SOCK_DGRAM, 0);
		if (sox < 0) {
			return -errno;
		}
		if (ns_name_ntop (srv [ctr]+SRV_SERVER, srvname, MAXDNAME) < 0) {
			return -errno;
		}
#ifdef DEBUG
		printf ("Trying SRV server %d %d\t%s\n",
				ns_get16 (srv [ctr]+SRV_COST),
				*(unsigned short *)(srv [ctr]+SRV_WEIGHT),
				srvname
			);
#endif
		if ((host=gethostbyname (srvname))
				&& (host->h_addrtype == AF_INET)) {
			char **ip=host->h_addr_list;
			while (*ip) {
				char *ipnr=*ip;
				struct sockaddr_in sin;
				memset (&sin, 0, sizeof (sin));
				sin.sin_family = AF_INET;
				memcpy (&sin.sin_addr,
						ipnr,
						sizeof (sin.sin_addr));
				sin.sin_port = *(unsigned short *) (srv [ctr]+SRV_PORT);
#ifdef DEBUG
				fprintf (stderr, "\tbind_connect (%d, 0x%08lx, %d)\t",
					sox,
					ntohl(*(unsigned long *)ipnr),
					ntohs (sin.sin_port));
#endif
#ifdef DEBUG
				if (mksox == connect) {
					printf ("mksox == connect\n");
				}
				if (mksox == bind) {
					printf ("mksox == bind\n");
				}
				{ int i; printf ("SIN ="); for (i=0; i<sizeof (sin); i++) printf (" %02x", (int) (((unsigned char *) &sin) [i])); printf ("\n"); }
#endif
				if (mksox (sox, (struct sockaddr *) &sin, sizeof (sin)) == 0) {
#ifdef DEBUG
					fprintf (stderr, "Connected or bound to %s:%d\n", srvname, ntohs (sin.sin_port));
#endif
					if (cnxhost) {
						if (strlen (cnxhost) > cnxhlen-1) {
							*cnxhost = '\0';
						} else {
							strncpy (cnxhost,srvname,cnxhlen);
						}
					}
					if (cnxport) {
						*cnxport = ntohs (sin.sin_port);
					}
					return sox;
				} else {
					if (!error) {
						error = -errno;
					}
				}
				ip++;
			}
			
		}
#ifdef DEBUG
		printf ("Closing socket %d\n", sox);
#endif
		close (sox);
	}

	if (!error) {
		error = -ENOENT;
	}
	return error;

}
Example #7
0
/*
 * A thread-safe, re-entrant version of val_gethostbyaddr 
 */
int
val_gethostbyaddr_r(val_context_t * context,
                    const char *addr,
                    int len,
                    int type,
                    struct hostent *ret,
                    char *buf,
                    int buflen,
                    struct hostent **result,
                    int *h_errnop, val_status_t * val_status)
{

    char            domain_string[NS_MAXDNAME];
    int             ret_status = 0, bufused = 0;
    struct val_answer_chain *val_res = NULL;
    struct val_answer_chain *res;
    int retval;
    val_context_t *ctx = NULL;
    
    /*
     * check misc parameters exist 
     */
    if (!addr || !ret || !buf || (buflen <= 0) ||
        !result || !h_errnop || !val_status) {
        if (h_errnop)
            *h_errnop = NO_RECOVERY;
        return (NO_RECOVERY);
    }

    /*
     * default the input parameters 
     */
    *result = NULL;
    ret->h_name = NULL;
    ret->h_aliases = NULL;
    ret->h_addr_list = NULL;
    *h_errnop = 0;
    *val_status = VAL_UNTRUSTED_ANSWER;

    /*
     * get the address values, only support IPv4 and IPv6 
     */
    if (AF_INET == type && len >= sizeof(struct in_addr)) {
        ret->h_addrtype = type;
        ret->h_length = sizeof(struct in_addr);
    } 
#ifdef VAL_IPV6
    else if (AF_INET6 == type && len >= sizeof(struct in6_addr)) {
        ret->h_addrtype = type;
        ret->h_length = sizeof(struct in6_addr);
    } 
#endif
    else {
        *h_errnop = NO_RECOVERY;
        return (NO_RECOVERY);
    }

    memset(domain_string, 0, sizeof(domain_string));

    if (0 !=
        (ret_status = address_to_reverse_domain(addr, type,
                                                domain_string, sizeof(domain_string)))
        ) {
        *h_errnop = ret_status;
        return ret_status;
    }

    /*
     * if there is memory, add the address to hostent's address list 
     */
    if ((buflen > bufused) && 
        ((buflen - bufused) >= (ret->h_length + (sizeof(char *) * 2)))) {
        ret->h_addr_list = (char **) (buf + bufused);
        bufused = bufused + (sizeof(char *) * 2);
        ret->h_addr_list[0] = buf + bufused;
        ret->h_addr_list[1] = NULL;
        bufused = bufused + ret->h_length;
        memcpy(ret->h_addr_list[0], addr, ret->h_length);
    } else {                    /* no memory, fail */
        *h_errnop = NO_RECOVERY;
        return (NO_RECOVERY);
    }

    ctx = val_create_or_refresh_context(context); /* does CTX_LOCK_POL_SH */
    if (ctx == NULL) {
        *h_errnop = NO_RECOVERY;
        return (NO_RECOVERY);
    }

    if (VAL_NO_ERROR != (retval = val_get_rrset(ctx,   /* val_context_t *  */
                                                domain_string, /* domain name */ 
                                                ns_c_in,   /* const u_int16_t q_class */
                                                ns_t_ptr,  /* const u_int16_t type */
                                                0,
                                                &val_res))) { /* struct val_answer_chain **results */
        val_log(ctx, LOG_ERR, 
                "val_gethostbyaddr_r(): val_get_rrset failed - %s", p_val_err(retval));
        CTX_UNLOCK_POL(ctx);
        *h_errnop = NO_RECOVERY;
        return NO_RECOVERY;
    }

    CTX_UNLOCK_POL(ctx);

    if (!val_res) {
        *h_errnop = NO_RECOVERY;
        return NO_RECOVERY;
    }

    for (res = val_res; res; res=res->val_ans_next) {

        struct rr_rec  *rr = res->val_ans;
        if (rr) {
            struct rr_rec  *rr_it = NULL;
            int             count = 0;
            int aliases_sz = 0;
            /*
             * if the buffer has enough room add the first host address 
             */
            if (rr->rr_length < (buflen - bufused - 1)) {
                /*
                 * setup hostent 
                 */
                ret->h_name = buf + bufused;
                ns_name_ntop(rr->rr_data, ret->h_name,
                             (buflen - bufused));
                bufused = bufused + strlen(ret->h_name) + 1;

                rr_it = rr->rr_next;
                /*
                 * are there other hostnames? 
                 */
                if (rr_it) {
                    /*
                     * calculate the amount of memory we need for aliases. 
                     */
                    do {
                        count++;
                        aliases_sz = aliases_sz + rr_it->rr_length + 1;
                    } while (NULL != (rr_it = rr_it->rr_next));

                    /*
                     * check that we have the space in the buffer 
                     */
                    if (buflen >=
                        (bufused + (sizeof(char *) * (count + 1)) +
                        aliases_sz)) {
                        /*
                         * assign the string pointer array 
                         */
                        ret->h_aliases = (char **) (buf + bufused);
                        bufused = bufused + (sizeof(char *) * (count + 1));

                        /*
                         * assign the strings 
                         */
                        rr_it = rr->rr_next;
                        count = 0;
                        do {
                            ret->h_aliases[count] = buf + bufused;
                            ns_name_ntop(rr_it->rr_data,
                                         ret->h_aliases[count],
                                        (buflen - bufused));
                            bufused =
                                bufused + strlen(ret->h_aliases[count]) + 1;
                            count++;
                        } while (NULL != (rr_it = rr_it->rr_next));
                        /*
                         * mark end of array 
                         */
                        ret->h_aliases[count] = NULL;
                    }
                    /*
                     * else we didn't have enough memory for the aliases.  They
                     * will be ignored with only one hostname returned 
                     */
                }                   /* else there are no other hostnames/aliases */

            } else {                /* else there is not enough room for even one host name, fail */
                ret->h_name = NULL;
                *h_errnop = NO_RECOVERY;
                return NO_RECOVERY;
            }
            break;

        } else if  (val_does_not_exist(res->val_ans_status)) {
                    
            if ((res->val_ans_status == VAL_NONEXISTENT_TYPE) ||
                (res->val_ans_status == VAL_NONEXISTENT_TYPE_NOCHAIN)) {
                    *h_errnop = NO_DATA;
            } else if ((res->val_ans_status == VAL_NONEXISTENT_NAME) ||
                       (res->val_ans_status == VAL_NONEXISTENT_NAME_NOCHAIN)) {
                    *h_errnop = HOST_NOT_FOUND;
            }

            *result = ret;
            return *h_errnop;
        }
    }

    if (!res) { /* no rrset, but a succesful return from the query?, fail */
        ret->h_name = NULL;
        *h_errnop = NO_RECOVERY;
        return NO_RECOVERY;
    }

    /* set the value of merged trusted and validated status values */
    if (val_isvalidated(res->val_ans_status))
        *val_status = VAL_VALIDATED_ANSWER; 
    else if (val_istrusted(res->val_ans_status))
        *val_status = VAL_TRUSTED_ANSWER; 

    /*
     * no error, set result 
     */
    *result = ret;
    return *h_errnop;

}                               /* val_getthostbyaddr_r */
Example #8
0
/* Setup a client socket for the named service over the given protocol under
 * the given domain name.
 */
int insrv_lookup (const char *service, const char *proto, const char *domain, 
	list<t_dns_result> &result) 
{
	// 1. convert service/proto to svcnm
	// 2. construct SRV query for _service._proto.domain

	iobuf names;
	name svcnm;
	int ctr;
	int rnd;
	HEADER *nameshdr;
	unsigned char *here, *srv[MAXNUM_SRV];
	int num_srv=0;
	// Storage for fallback SRV list, constructed when DNS gives no SRV
	//unsigned char fallbacksrv [2*(MAXCDNAME+SRV_FIXEDSZ+MAXCDNAME)];

	// srv_flags &= ~SRV_GOT_MASK;
	// srv_flags |=  SRV_GOT_SRV;

	strcpy (svcnm, "_");
	strcat (svcnm, service);
	strcat (svcnm, "._");
	strcat (svcnm, proto);

	// Note that SRV records are only defined for class IN
	if (domain) {
		names.len=res_querydomain (svcnm, domain,
				C_IN, T_SRV,
				names.buf, PACKETSZ);
	} else {
		names.len=res_query (svcnm,
				C_IN, T_SRV,
				names.buf, PACKETSZ);
	}
	if (names.len < 0) {
		return -ENOENT;
	}
	nameshdr=(HEADER *) names.buf;
	here=names.buf + HFIXEDSZ;
	rnd=nameshdr->id; 	// Heck, gimme one reason why not!

	if ((names.len < HFIXEDSZ) || nameshdr->tc) {
		return -EMSGSIZE;
	}
	switch (nameshdr->rcode) {
		case 1:
			return -EFAULT;
		case 2:
			return -EAGAIN;
		case 3:
			return -ENOENT;
		case 4:
			return -ENOSYS;
		case 5:
			return -EPERM;
		default:
			break;
	}
	if (ntohs (nameshdr->ancount) == 0) {
		return -ENOENT;
	}
	if (ntohs (nameshdr->ancount) > MAXNUM_SRV) {
		return -ERANGE;
	}
	for (ctr=ntohs (nameshdr->qdcount); ctr>0; ctr--) {
		int strlen=dn_skipname (here, names.buf+names.len);
		here += strlen + QFIXEDSZ;
	}
	for (ctr=ntohs (nameshdr->ancount); ctr>0; ctr--) {
		int strlen=dn_skipname (here, names.buf+names.len);
		here += strlen;
		srv [num_srv++] = here;
		here += SRV_FIXEDSZ;
		here += dn_skipname (here, names.buf+names.len);
	}
	
	// Overwrite weight with rnd-spread version to divide load over weights
	for (ctr=0; ctr<num_srv; ctr++) {
		*(unsigned short *) (srv [ctr]+SRV_WEIGHT)
			= htons(rnd % (1+ns_get16 (srv [ctr]+SRV_WEIGHT)));
	}
	qsort (srv, num_srv, sizeof (*srv), srvcmp);
	
	result.clear();
	for (ctr=0; ctr<num_srv; ctr++) {
		name srvname;
		if (ns_name_ntop (srv [ctr]+SRV_SERVER, srvname, MAXDNAME) < 0) {
			return -errno;
		}
		
		t_dns_result r;
		r.hostname = srvname;
		r.port = ns_get16(srv [ctr]+SRV_PORT);
		result.push_back(r);
	}
	
	return 0;
}