112891Swpaul/* 220907Swpaul * Copyright (c) 1995, 1996 312891Swpaul * Bill Paul <wpaul@ctr.columbia.edu>. All rights reserved. 412891Swpaul * 512891Swpaul * Redistribution and use in source and binary forms, with or without 612891Swpaul * modification, are permitted provided that the following conditions 712891Swpaul * are met: 812891Swpaul * 1. Redistributions of source code must retain the above copyright 912891Swpaul * notice, this list of conditions and the following disclaimer. 1012891Swpaul * 2. Redistributions in binary form must reproduce the above copyright 1112891Swpaul * notice, this list of conditions and the following disclaimer in the 1212891Swpaul * documentation and/or other materials provided with the distribution. 1312891Swpaul * 3. All advertising materials mentioning features or use of this software 1412891Swpaul * must display the following acknowledgement: 1512891Swpaul * This product includes software developed by Bill Paul. 1612891Swpaul * 4. Neither the name of the University nor the names of its contributors 1712891Swpaul * may be used to endorse or promote products derived from this software 1812891Swpaul * without specific prior written permission. 1912891Swpaul * 2012891Swpaul * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND 2112891Swpaul * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2212891Swpaul * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2312891Swpaul * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR CONTRIBUTORS BE LIABLE 2412891Swpaul * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2512891Swpaul * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2612891Swpaul * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2712891Swpaul * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2812891Swpaul * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2912891Swpaul * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3012891Swpaul * SUCH DAMAGE. 3112891Swpaul */ 3212891Swpaul 33114601Sobrien#include <sys/cdefs.h> 34114601Sobrien__FBSDID("$FreeBSD$"); 3530827Scharnier 3612891Swpaul/* 3712891Swpaul * Do standard and reverse DNS lookups using the resolver library. 3812891Swpaul * Take care of all the dirty work here so the main program only has to 3912891Swpaul * pass us a pointer to an array of characters. 4012891Swpaul * 4112891Swpaul * We have to use direct resolver calls here otherwise the YP server 4212891Swpaul * could end up looping by calling itself over and over again until 4312891Swpaul * it disappeared up its own belly button. 4412891Swpaul */ 4512891Swpaul 4612891Swpaul#include <sys/param.h> 4720818Swpaul#include <sys/socket.h> 4820818Swpaul#include <sys/time.h> 4920818Swpaul#include <sys/fcntl.h> 5020818Swpaul#include <sys/queue.h> 5112891Swpaul#include <netinet/in.h> 5212891Swpaul#include <arpa/inet.h> 5320818Swpaul#include <arpa/nameser.h> 5420818Swpaul 5520818Swpaul#include <ctype.h> 5630827Scharnier#include <errno.h> 5720818Swpaul#include <netdb.h> 5830827Scharnier#include <stdio.h> 5920818Swpaul#include <stdlib.h> 6020818Swpaul#include <string.h> 6130827Scharnier#include <resolv.h> 6230827Scharnier#include <unistd.h> 6320818Swpaul 6420818Swpaul#include <rpcsvc/yp.h> 6512891Swpaul#include "yp_extern.h" 6612891Swpaul 6790298Sdesstatic char * 6890298Sdesparse(struct hostent *hp) 6912891Swpaul{ 7012891Swpaul static char result[MAXHOSTNAMELEN * 2]; 71146446Scharnier int i; 72146446Scharnier size_t len; 73145792Sume char addr[46]; 7412891Swpaul 7520818Swpaul if (hp == NULL) 7620818Swpaul return(NULL); 7720818Swpaul 78145792Sume if (inet_ntop(hp->h_addrtype, hp->h_addr, addr, sizeof(addr)) == NULL) 79145792Sume return(NULL); 80145792Sume 81145792Sume len = strlen(addr) + 1 + strlen(hp->h_name); 8212891Swpaul for (i = 0; hp->h_aliases[i]; i++) 8312891Swpaul len += strlen(hp->h_aliases[i]) + 1; 8436797Simp len++; 8512891Swpaul 8636797Simp if (len > sizeof(result)) 8736797Simp return(NULL); 8836797Simp 8912891Swpaul bzero(result, sizeof(result)); 90145792Sume snprintf(result, sizeof(result), "%s %s", addr, hp->h_name); 9112891Swpaul for (i = 0; hp->h_aliases[i]; i++) { 9212891Swpaul strcat(result, " "); 9312891Swpaul strcat(result, hp->h_aliases[i]); 9412891Swpaul } 9512891Swpaul 9612891Swpaul return ((char *)&result); 9712891Swpaul} 9812891Swpaul 99145792Sume#define MAXPACKET (64*1024) 10020818Swpaul#define DEF_TTL 50 10120818Swpaul 10221389Swpaul#define BY_DNS_ID 1 10321389Swpaul#define BY_RPC_XID 2 10421389Swpaul 10590297Sdesextern struct hostent *__dns_getanswer(char *, int, char *, int); 10620818Swpaul 10770493Sphkstatic TAILQ_HEAD(dns_qhead, circleq_dnsentry) qhead; 10820818Swpaul 10920818Swpaulstruct circleq_dnsentry { 11020818Swpaul SVCXPRT *xprt; 11120818Swpaul unsigned long xid; 11220818Swpaul struct sockaddr_in client_addr; 11320907Swpaul unsigned long ypvers; 11420818Swpaul unsigned long id; 11520818Swpaul unsigned long ttl; 11620818Swpaul unsigned long type; 11720893Swpaul unsigned short prot_type; 11820818Swpaul char **domain; 11920818Swpaul char *name; 120145792Sume int addrtype; 121145792Sume int addrlen; 122145792Sume uint32_t addr[4]; /* IPv4 or IPv6 */ 12370493Sphk TAILQ_ENTRY(circleq_dnsentry) links; 12420818Swpaul}; 12520818Swpaul 12620818Swpaulstatic int pending = 0; 12720818Swpaul 12890298Sdesint 12990298Sdesyp_init_resolver(void) 13012891Swpaul{ 13170493Sphk TAILQ_INIT(&qhead); 13220818Swpaul if (!(_res.options & RES_INIT) && res_init() == -1) { 13320818Swpaul yp_error("res_init failed"); 13420818Swpaul return(1); 13520818Swpaul } 13620818Swpaul if ((resfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) { 13720818Swpaul yp_error("couldn't create socket"); 13820818Swpaul return(1); 13920818Swpaul } 14020818Swpaul if (fcntl(resfd, F_SETFL, O_NONBLOCK) == -1) { 14120818Swpaul yp_error("couldn't make resolver socket non-blocking"); 14220818Swpaul return(1); 14320818Swpaul } 14420818Swpaul return(0); 14520818Swpaul} 14612891Swpaul 14790298Sdesstatic struct 14890298Sdescircleq_dnsentry *yp_malloc_dnsent(void) 14920818Swpaul{ 15020818Swpaul register struct circleq_dnsentry *q; 15120818Swpaul 15220818Swpaul q = (struct circleq_dnsentry *)malloc(sizeof(struct circleq_dnsentry)); 15320818Swpaul 15420818Swpaul if (q == NULL) { 15530827Scharnier yp_error("failed to malloc() circleq dns entry"); 15620818Swpaul return(NULL); 15720818Swpaul } 15820818Swpaul 15920818Swpaul return(q); 16012891Swpaul} 16112891Swpaul 16220818Swpaul/* 16320818Swpaul * Transmit a query. 16420818Swpaul */ 16590298Sdesstatic unsigned long 16690298Sdesyp_send_dns_query(char *name, int type) 16712891Swpaul{ 16820818Swpaul char buf[MAXPACKET]; 16920818Swpaul int n; 17020818Swpaul HEADER *hptr; 17120818Swpaul int ns; 17220818Swpaul int rval; 17320818Swpaul unsigned long id; 17412891Swpaul 17520818Swpaul bzero(buf, sizeof(buf)); 17612891Swpaul 17720818Swpaul n = res_mkquery(QUERY,name,C_IN,type,NULL,0,NULL,buf,sizeof(buf)); 17820818Swpaul 17920818Swpaul if (n <= 0) { 180103717Smarkm yp_error("res_mkquery failed for %s type %d", name, type); 18120818Swpaul return(0); 18220818Swpaul } 18320818Swpaul 18420818Swpaul hptr = (HEADER *)&buf; 18520818Swpaul id = ntohs(hptr->id); 18620818Swpaul 18720818Swpaul for (ns = 0; ns < _res.nscount; ns++) { 18820818Swpaul rval = sendto(resfd, buf, n, 0, 18920818Swpaul (struct sockaddr *)&_res.nsaddr_list[ns], 19020818Swpaul sizeof(struct sockaddr)); 19120818Swpaul if (rval == -1) { 19220818Swpaul yp_error("sendto failed"); 19320818Swpaul return(0); 19420818Swpaul } 19520818Swpaul } 19620818Swpaul 19720818Swpaul return(id); 19812891Swpaul} 19920818Swpaul 20090298Sdesstatic struct circleq_dnsentry * 20190298Sdesyp_find_dnsqent(unsigned long id, int type) 20220818Swpaul{ 20320818Swpaul register struct circleq_dnsentry *q; 20420818Swpaul 20570493Sphk TAILQ_FOREACH(q, &qhead, links) { 20690297Sdes switch (type) { 20721389Swpaul case BY_RPC_XID: 20821389Swpaul if (id == q->xid) 20921389Swpaul return(q); 21021389Swpaul break; 21121389Swpaul case BY_DNS_ID: 21221389Swpaul default: 21321389Swpaul if (id == q->id) 21421389Swpaul return(q); 21521389Swpaul break; 21621389Swpaul } 21720818Swpaul } 21820818Swpaul return (NULL); 21920818Swpaul} 22020818Swpaul 22190298Sdesstatic void 22290298Sdesyp_send_dns_reply(struct circleq_dnsentry *q, char *buf) 22320818Swpaul{ 22420907Swpaul ypresponse result_v1; 22520907Swpaul ypresp_val result_v2; 22620818Swpaul unsigned long xid; 22720818Swpaul struct sockaddr_in client_addr; 22820907Swpaul xdrproc_t xdrfunc; 22920907Swpaul char *result; 23020818Swpaul 23120907Swpaul /* 23220907Swpaul * Set up correct reply struct and 23320907Swpaul * XDR filter depending on ypvers. 23420907Swpaul */ 23590297Sdes switch (q->ypvers) { 23620907Swpaul case YPVERS: 23720907Swpaul bzero((char *)&result_v2, sizeof(result_v2)); 23820818Swpaul 23920907Swpaul if (buf == NULL) 24020907Swpaul result_v2.stat = YP_NOKEY; 24120907Swpaul else { 24220907Swpaul result_v2.val.valdat_len = strlen(buf); 24320907Swpaul result_v2.val.valdat_val = buf; 24420907Swpaul result_v2.stat = YP_TRUE; 24520907Swpaul } 24620907Swpaul result = (char *)&result_v2; 24720907Swpaul xdrfunc = (xdrproc_t)xdr_ypresp_val; 24820907Swpaul break; 24920907Swpaul case YPOLDVERS: 25020907Swpaul /* 25120907Swpaul * The odds are we will _never_ execute this 25220907Swpaul * particular code, but we include it anyway 25320907Swpaul * for the sake of completeness. 25420907Swpaul */ 25520907Swpaul bzero((char *)&result_v1, sizeof(result_v1)); 25620907Swpaul result_v1.yp_resptype = YPRESP_VAL; 25720907Swpaul 25890298Sdes#define YPVAL ypresponse_u.yp_resp_valtype 25920907Swpaul if (buf == NULL) 26020907Swpaul result_v1.YPVAL.stat = YP_NOKEY; 26120907Swpaul else { 26220907Swpaul result_v1.YPVAL.val.valdat_len = strlen(buf); 26320907Swpaul result_v1.YPVAL.val.valdat_val = buf; 26420907Swpaul result_v1.YPVAL.stat = YP_TRUE; 26520907Swpaul } 26620907Swpaul result = (char *)&result_v1; 26720907Swpaul xdrfunc = (xdrproc_t)xdr_ypresponse; 26820907Swpaul break; 26920907Swpaul default: 27030827Scharnier yp_error("bad YP program version (%lu)!", q->ypvers); 27120907Swpaul return; 27220907Swpaul break; 27320818Swpaul } 27420818Swpaul 27520818Swpaul if (debug) 27630827Scharnier yp_error("sending dns reply to %s (%lu)", 27720907Swpaul inet_ntoa(q->client_addr.sin_addr), q->id); 27820818Swpaul /* 27920818Swpaul * XXX This is disgusting. There's basically one transport 28020818Swpaul * handle for UDP, but we're holding off on replying to a 28120818Swpaul * client until we're ready, by which time we may have received 28220818Swpaul * several other queries from other clients with different 28320818Swpaul * transaction IDs. So to make the delayed response thing work, 28420818Swpaul * we have to save the transaction ID and client address of 28520818Swpaul * each request, then jam them into the transport handle when 28620818Swpaul * we're ready to send a reply. Then after we've send the reply, 28720818Swpaul * we put the old transaction ID and remote address back the 28820818Swpaul * way we found 'em. This is _INCREDIBLY_ non-portable; it's 28920818Swpaul * not even supported by the RPC library. 29020818Swpaul */ 29120893Swpaul /* 29220907Swpaul * XXX Don't frob the transaction ID for TCP handles. 29320893Swpaul */ 29420893Swpaul if (q->prot_type == SOCK_DGRAM) 29520893Swpaul xid = svcudp_set_xid(q->xprt, q->xid); 29620818Swpaul client_addr = q->xprt->xp_raddr; 29720818Swpaul q->xprt->xp_raddr = q->client_addr; 29820907Swpaul 29920907Swpaul if (!svc_sendreply(q->xprt, xdrfunc, result)) 30020818Swpaul yp_error("svc_sendreply failed"); 30120907Swpaul 30220907Swpaul /* 30320907Swpaul * Now that we sent the reply, 30420907Swpaul * put the handle back the way it was. 30520907Swpaul */ 30620893Swpaul if (q->prot_type == SOCK_DGRAM) 30720893Swpaul svcudp_set_xid(q->xprt, xid); 30820818Swpaul q->xprt->xp_raddr = client_addr; 30920907Swpaul 31020818Swpaul return; 31120818Swpaul} 31220818Swpaul 31320907Swpaul/* 31420907Swpaul * Decrement TTL on all queue entries, possibly nuking 31520907Swpaul * any that have been around too long without being serviced. 31620907Swpaul */ 31790298Sdesvoid 31890298Sdesyp_prune_dnsq(void) 31920818Swpaul{ 32027713Swpaul register struct circleq_dnsentry *q, *n; 32120818Swpaul 32270493Sphk q = TAILQ_FIRST(&qhead); 32390297Sdes while (q != NULL) { 32420818Swpaul q->ttl--; 32570493Sphk n = TAILQ_NEXT(q, links); 32620818Swpaul if (!q->ttl) { 32770493Sphk TAILQ_REMOVE(&qhead, q, links); 32820818Swpaul free(q->name); 32920818Swpaul free(q); 33020818Swpaul pending--; 33120818Swpaul } 33227713Swpaul q = n; 33320818Swpaul } 33420818Swpaul 33520818Swpaul if (pending < 0) 33620818Swpaul pending = 0; 33720818Swpaul 33820818Swpaul return; 33920818Swpaul} 34020818Swpaul 34120907Swpaul/* 34220907Swpaul * Data is pending on the DNS socket; check for valid replies 34320907Swpaul * to our queries and dispatch them to waiting clients. 34420907Swpaul */ 34590298Sdesvoid 34690298Sdesyp_run_dnsq(void) 34720818Swpaul{ 34820818Swpaul register struct circleq_dnsentry *q; 34920818Swpaul char buf[sizeof(HEADER) + MAXPACKET]; 35020818Swpaul struct sockaddr_in sin; 351143415Sstefanf socklen_t len; 35220818Swpaul int rval; 35320818Swpaul HEADER *hptr; 35420818Swpaul struct hostent *hent; 35520818Swpaul 35620818Swpaul if (debug) 35730827Scharnier yp_error("running dns queue"); 35820818Swpaul 35920818Swpaul bzero(buf, sizeof(buf)); 36020818Swpaul 36120818Swpaul len = sizeof(struct sockaddr_in); 36220818Swpaul rval = recvfrom(resfd, buf, sizeof(buf), 0, 36320818Swpaul (struct sockaddr *)&sin, &len); 36420818Swpaul 36520818Swpaul if (rval == -1) { 36620818Swpaul yp_error("recvfrom failed: %s", strerror(errno)); 36720818Swpaul return; 36820818Swpaul } 36920818Swpaul 37020907Swpaul /* 37120907Swpaul * We may have data left in the socket that represents 37220907Swpaul * replies to earlier queries that we don't care about 37320907Swpaul * anymore. If there are no lookups pending or the packet 37420907Swpaul * ID doesn't match any of the queue IDs, just drop it 37520907Swpaul * on the floor. 37620907Swpaul */ 37720818Swpaul hptr = (HEADER *)&buf; 37821389Swpaul if (!pending || 37921389Swpaul (q = yp_find_dnsqent(ntohs(hptr->id), BY_DNS_ID)) == NULL) { 38020907Swpaul /* ignore */ 38120818Swpaul return; 38220818Swpaul } 38320818Swpaul 38420818Swpaul if (debug) 38530827Scharnier yp_error("got dns reply from %s", inet_ntoa(sin.sin_addr)); 38620818Swpaul 38720818Swpaul hent = __dns_getanswer(buf, rval, q->name, q->type); 38820818Swpaul 389103717Smarkm if (hent != NULL) { 39020893Swpaul if (q->type == T_PTR) { 391145792Sume hent->h_addr = (char *)q->addr; 392145792Sume hent->h_addrtype = q->addrtype; 393145792Sume hent->h_length = q->addrlen; 39420893Swpaul } 39520818Swpaul } 39620818Swpaul 39720907Swpaul /* Got an answer ready for a client -- send it off. */ 39820818Swpaul yp_send_dns_reply(q, parse(hent)); 39920818Swpaul pending--; 40070493Sphk TAILQ_REMOVE(&qhead, q, links); 40120818Swpaul free(q->name); 40220818Swpaul free(q); 40320818Swpaul 40420907Swpaul /* Decrement TTLs on other entries while we're here. */ 40520818Swpaul yp_prune_dnsq(); 40620818Swpaul 40720818Swpaul return; 40820818Swpaul} 40920818Swpaul 41020907Swpaul/* 41120907Swpaul * Queue and transmit an asynchronous DNS hostname lookup. 41220907Swpaul */ 41390298Sdesypstat 414145792Sumeyp_async_lookup_name(struct svc_req *rqstp, char *name, int af) 41520818Swpaul{ 41620818Swpaul register struct circleq_dnsentry *q; 417143415Sstefanf socklen_t len; 418143415Sstefanf int type; 41920818Swpaul 42021389Swpaul /* Check for SOCK_DGRAM or SOCK_STREAM -- we need to know later */ 421143415Sstefanf type = -1; 422143415Sstefanf len = sizeof(type); 42374462Salfred if (getsockopt(rqstp->rq_xprt->xp_fd, SOL_SOCKET, 42421389Swpaul SO_TYPE, &type, &len) == -1) { 42521389Swpaul yp_error("getsockopt failed: %s", strerror(errno)); 42621389Swpaul return(YP_YPERR); 42721389Swpaul } 42821389Swpaul 42921389Swpaul /* Avoid transmitting dupe requests. */ 43021389Swpaul if (type == SOCK_DGRAM && 43121389Swpaul yp_find_dnsqent(svcudp_get_xid(rqstp->rq_xprt),BY_RPC_XID) != NULL) 43221389Swpaul return(YP_TRUE); 43321389Swpaul 43420818Swpaul if ((q = yp_malloc_dnsent()) == NULL) 43520818Swpaul return(YP_YPERR); 43620818Swpaul 437145792Sume q->type = (af == AF_INET) ? T_A : T_AAAA; 43820818Swpaul q->ttl = DEF_TTL; 43920907Swpaul q->xprt = rqstp->rq_xprt; 44020907Swpaul q->ypvers = rqstp->rq_vers; 44120893Swpaul q->prot_type = type; 44220893Swpaul if (q->prot_type == SOCK_DGRAM) 44320907Swpaul q->xid = svcudp_get_xid(q->xprt); 44420907Swpaul q->client_addr = q->xprt->xp_raddr; 44538234Swpaul q->domain = _res.dnsrch; 44620818Swpaul q->id = yp_send_dns_query(name, q->type); 44720818Swpaul 44820818Swpaul if (q->id == 0) { 44920818Swpaul yp_error("DNS query failed"); 45020818Swpaul free(q); 45120818Swpaul return(YP_YPERR); 45220818Swpaul } 45320818Swpaul 45420818Swpaul q->name = strdup(name); 45570493Sphk TAILQ_INSERT_HEAD(&qhead, q, links); 45620818Swpaul pending++; 45720818Swpaul 45820818Swpaul if (debug) 459253350Shrs yp_error("queueing async DNS name lookup (%lu)", q->id); 46020818Swpaul 46127713Swpaul yp_prune_dnsq(); 46220818Swpaul return(YP_TRUE); 46320818Swpaul} 46420818Swpaul 46520907Swpaul/* 46620907Swpaul * Queue and transmit an asynchronous DNS IP address lookup. 46720907Swpaul */ 46890298Sdesypstat 469145792Sumeyp_async_lookup_addr(struct svc_req *rqstp, char *addr, int af) 47020818Swpaul{ 47120818Swpaul register struct circleq_dnsentry *q; 472145792Sume char buf[MAXHOSTNAMELEN], *qp; 473145792Sume uint32_t abuf[4]; /* IPv4 or IPv6 */ 474145792Sume u_char *uaddr = (u_char *)abuf; 475143415Sstefanf socklen_t len; 476145792Sume int type, n; 47720818Swpaul 47821389Swpaul /* Check for SOCK_DGRAM or SOCK_STREAM -- we need to know later */ 479143415Sstefanf type = -1; 480143415Sstefanf len = sizeof(type); 48174462Salfred if (getsockopt(rqstp->rq_xprt->xp_fd, SOL_SOCKET, 48221389Swpaul SO_TYPE, &type, &len) == -1) { 48321389Swpaul yp_error("getsockopt failed: %s", strerror(errno)); 48421389Swpaul return(YP_YPERR); 48521389Swpaul } 48621389Swpaul 48721389Swpaul /* Avoid transmitting dupe requests. */ 48890297Sdes if (type == SOCK_DGRAM && 48921389Swpaul yp_find_dnsqent(svcudp_get_xid(rqstp->rq_xprt),BY_RPC_XID) != NULL) 49021389Swpaul return(YP_TRUE); 49121389Swpaul 49220818Swpaul if ((q = yp_malloc_dnsent()) == NULL) 49320818Swpaul return(YP_YPERR); 49420818Swpaul 495145792Sume switch (af) { 496145792Sume case AF_INET: 497145792Sume if (inet_aton(addr, (struct in_addr *)uaddr) != 1) 498145792Sume return(YP_NOKEY); 499145792Sume snprintf(buf, sizeof(buf), "%u.%u.%u.%u.in-addr.arpa", 500145792Sume (uaddr[3] & 0xff), (uaddr[2] & 0xff), 501145792Sume (uaddr[1] & 0xff), (uaddr[0] & 0xff)); 502145792Sume len = INADDRSZ; 503145792Sume break; 504145792Sume case AF_INET6: 505145792Sume if (inet_pton(af, addr, uaddr) != 1) 506145792Sume return(YP_NOKEY); 507145792Sume qp = buf; 508145792Sume for (n = IN6ADDRSZ - 1; n >= 0; n--) { 509145792Sume qp += (size_t)sprintf(qp, "%x.%x.", uaddr[n] & 0xf, 510145792Sume (uaddr[n] >> 4) & 0xf); 511145792Sume } 512145792Sume strlcat(buf, "ip6.arpa", sizeof(buf)); 513145792Sume len = IN6ADDRSZ; 514145792Sume break; 515145792Sume default: 516145792Sume return(YP_YPERR); 517145792Sume } 51820818Swpaul 51920818Swpaul if (debug) 52020818Swpaul yp_error("DNS address is: %s", buf); 52120818Swpaul 52220818Swpaul q->type = T_PTR; 52320818Swpaul q->ttl = DEF_TTL; 52420907Swpaul q->xprt = rqstp->rq_xprt; 52520907Swpaul q->ypvers = rqstp->rq_vers; 52620818Swpaul q->domain = NULL; 52720893Swpaul q->prot_type = type; 52820893Swpaul if (q->prot_type == SOCK_DGRAM) 52920907Swpaul q->xid = svcudp_get_xid(q->xprt); 53020907Swpaul q->client_addr = q->xprt->xp_raddr; 53120818Swpaul q->id = yp_send_dns_query(buf, q->type); 53220818Swpaul 53320818Swpaul if (q->id == 0) { 53420818Swpaul yp_error("DNS query failed"); 53520818Swpaul free(q); 53620818Swpaul return(YP_YPERR); 53720818Swpaul } 53820818Swpaul 539145792Sume memcpy(q->addr, uaddr, len); 540145792Sume q->addrlen = len; 541145792Sume q->addrtype = af; 54220818Swpaul q->name = strdup(buf); 54370493Sphk TAILQ_INSERT_HEAD(&qhead, q, links); 54420818Swpaul pending++; 54520818Swpaul 54620818Swpaul if (debug) 547253350Shrs yp_error("queueing async DNS address lookup (%lu)", q->id); 54820818Swpaul 54927713Swpaul yp_prune_dnsq(); 55020818Swpaul return(YP_TRUE); 55120818Swpaul} 552