1778c7b1cSBill Paul /* 2adc4fa33SBill Paul * Copyright (c) 1995, 1996 3778c7b1cSBill Paul * Bill Paul <wpaul@ctr.columbia.edu>. All rights reserved. 4778c7b1cSBill Paul * 5778c7b1cSBill Paul * Redistribution and use in source and binary forms, with or without 6778c7b1cSBill Paul * modification, are permitted provided that the following conditions 7778c7b1cSBill Paul * are met: 8778c7b1cSBill Paul * 1. Redistributions of source code must retain the above copyright 9778c7b1cSBill Paul * notice, this list of conditions and the following disclaimer. 10778c7b1cSBill Paul * 2. Redistributions in binary form must reproduce the above copyright 11778c7b1cSBill Paul * notice, this list of conditions and the following disclaimer in the 12778c7b1cSBill Paul * documentation and/or other materials provided with the distribution. 13778c7b1cSBill Paul * 3. All advertising materials mentioning features or use of this software 14778c7b1cSBill Paul * must display the following acknowledgement: 15778c7b1cSBill Paul * This product includes software developed by Bill Paul. 16778c7b1cSBill Paul * 4. Neither the name of the University nor the names of its contributors 17778c7b1cSBill Paul * may be used to endorse or promote products derived from this software 18778c7b1cSBill Paul * without specific prior written permission. 19778c7b1cSBill Paul * 20778c7b1cSBill Paul * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND 21778c7b1cSBill Paul * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22778c7b1cSBill Paul * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23778c7b1cSBill Paul * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR CONTRIBUTORS BE LIABLE 24778c7b1cSBill Paul * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25778c7b1cSBill Paul * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26778c7b1cSBill Paul * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27778c7b1cSBill Paul * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28778c7b1cSBill Paul * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29778c7b1cSBill Paul * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30778c7b1cSBill Paul * SUCH DAMAGE. 31778c7b1cSBill Paul * 327deb24a6SBill Paul * $Id: yp_dnslookup.c,v 1.10 1997/02/22 16:15:10 peter Exp $ 33778c7b1cSBill Paul */ 34778c7b1cSBill Paul 35778c7b1cSBill Paul /* 36778c7b1cSBill Paul * Do standard and reverse DNS lookups using the resolver library. 37778c7b1cSBill Paul * Take care of all the dirty work here so the main program only has to 38778c7b1cSBill Paul * pass us a pointer to an array of characters. 39778c7b1cSBill Paul * 40778c7b1cSBill Paul * We have to use direct resolver calls here otherwise the YP server 41778c7b1cSBill Paul * could end up looping by calling itself over and over again until 42778c7b1cSBill Paul * it disappeared up its own belly button. 43778c7b1cSBill Paul */ 44778c7b1cSBill Paul 45778c7b1cSBill Paul #include <sys/param.h> 46778c7b1cSBill Paul #include <sys/socket.h> 47180807d2SBill Paul #include <sys/time.h> 48180807d2SBill Paul #include <sys/fcntl.h> 49180807d2SBill Paul #include <sys/queue.h> 50180807d2SBill Paul #include <netinet/in.h> 51778c7b1cSBill Paul #include <arpa/inet.h> 52180807d2SBill Paul #include <arpa/nameser.h> 53180807d2SBill Paul 54180807d2SBill Paul #include <stdio.h> 55180807d2SBill Paul #include <ctype.h> 56180807d2SBill Paul #include <resolv.h> 57180807d2SBill Paul #include <netdb.h> 58180807d2SBill Paul #include <unistd.h> 59180807d2SBill Paul #include <stdlib.h> 60180807d2SBill Paul #include <string.h> 61180807d2SBill Paul #include <errno.h> 62180807d2SBill Paul #include <err.h> 63180807d2SBill Paul 64180807d2SBill Paul #include <rpcsvc/yp.h> 65778c7b1cSBill Paul #include "yp_extern.h" 66778c7b1cSBill Paul 671fbdac93SBill Paul #ifndef lint 687deb24a6SBill Paul static const char rcsid[] = "$Id: yp_dnslookup.c,v 1.10 1997/02/22 16:15:10 peter Exp $"; 691fbdac93SBill Paul #endif 701fbdac93SBill Paul 71778c7b1cSBill Paul static char *parse(hp) 72778c7b1cSBill Paul struct hostent *hp; 73778c7b1cSBill Paul { 74778c7b1cSBill Paul static char result[MAXHOSTNAMELEN * 2]; 75778c7b1cSBill Paul int len,i; 76778c7b1cSBill Paul struct in_addr addr; 77778c7b1cSBill Paul 78180807d2SBill Paul if (hp == NULL) 79180807d2SBill Paul return(NULL); 80180807d2SBill Paul 81778c7b1cSBill Paul len = 16 + strlen(hp->h_name); 82778c7b1cSBill Paul for (i = 0; hp->h_aliases[i]; i++) 83778c7b1cSBill Paul len += strlen(hp->h_aliases[i]) + 1; 84778c7b1cSBill Paul 85778c7b1cSBill Paul bzero(result, sizeof(result)); 86778c7b1cSBill Paul 87778c7b1cSBill Paul bcopy(hp->h_addr, &addr, sizeof(struct in_addr)); 88778c7b1cSBill Paul snprintf(result, sizeof(result), "%s %s", inet_ntoa(addr), hp->h_name); 89778c7b1cSBill Paul 90778c7b1cSBill Paul for (i = 0; hp->h_aliases[i]; i++) { 91778c7b1cSBill Paul strcat(result, " "); 92778c7b1cSBill Paul strcat(result, hp->h_aliases[i]); 93778c7b1cSBill Paul } 94778c7b1cSBill Paul 95778c7b1cSBill Paul return ((char *)&result); 96778c7b1cSBill Paul } 97778c7b1cSBill Paul 98180807d2SBill Paul #define MAXPACKET 1024 99180807d2SBill Paul #define DEF_TTL 50 100180807d2SBill Paul 1019c171de0SBill Paul #define BY_DNS_ID 1 1029c171de0SBill Paul #define BY_RPC_XID 2 1039c171de0SBill Paul 104180807d2SBill Paul extern struct hostent *__dns_getanswer __P((char *, int, char *, int)); 105180807d2SBill Paul 106180807d2SBill Paul static CIRCLEQ_HEAD(dns_qhead, circleq_dnsentry) qhead; 107180807d2SBill Paul 108180807d2SBill Paul struct circleq_dnsentry { 109180807d2SBill Paul SVCXPRT *xprt; 110180807d2SBill Paul unsigned long xid; 111180807d2SBill Paul struct sockaddr_in client_addr; 112adc4fa33SBill Paul unsigned long ypvers; 113180807d2SBill Paul unsigned long id; 114180807d2SBill Paul unsigned long ttl; 115180807d2SBill Paul unsigned long type; 116926f037aSBill Paul unsigned short prot_type; 117180807d2SBill Paul char **domain; 118180807d2SBill Paul char *name; 119180807d2SBill Paul struct in_addr addr; 120180807d2SBill Paul CIRCLEQ_ENTRY(circleq_dnsentry) links; 121180807d2SBill Paul }; 122180807d2SBill Paul 123180807d2SBill Paul static int pending = 0; 124180807d2SBill Paul 125180807d2SBill Paul int yp_init_resolver() 126778c7b1cSBill Paul { 127180807d2SBill Paul CIRCLEQ_INIT(&qhead); 128180807d2SBill Paul if (!(_res.options & RES_INIT) && res_init() == -1) { 129180807d2SBill Paul yp_error("res_init failed"); 130180807d2SBill Paul return(1); 131180807d2SBill Paul } 132180807d2SBill Paul if ((resfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) { 133180807d2SBill Paul yp_error("couldn't create socket"); 134180807d2SBill Paul return(1); 135180807d2SBill Paul } 136180807d2SBill Paul if (fcntl(resfd, F_SETFL, O_NONBLOCK) == -1) { 137180807d2SBill Paul yp_error("couldn't make resolver socket non-blocking"); 138180807d2SBill Paul return(1); 139180807d2SBill Paul } 140180807d2SBill Paul return(0); 141778c7b1cSBill Paul } 142778c7b1cSBill Paul 143180807d2SBill Paul static struct circleq_dnsentry *yp_malloc_dnsent() 144180807d2SBill Paul { 145180807d2SBill Paul register struct circleq_dnsentry *q; 146778c7b1cSBill Paul 147180807d2SBill Paul q = (struct circleq_dnsentry *)malloc(sizeof(struct circleq_dnsentry)); 148180807d2SBill Paul 149180807d2SBill Paul if (q == NULL) { 150180807d2SBill Paul yp_error("failed to malloc() circleq dns entry: %s", 151180807d2SBill Paul strerror(errno)); 152180807d2SBill Paul return(NULL); 153180807d2SBill Paul } 154180807d2SBill Paul 155180807d2SBill Paul return(q); 156180807d2SBill Paul } 157180807d2SBill Paul 158180807d2SBill Paul /* 159180807d2SBill Paul * Transmit a query. 160180807d2SBill Paul */ 161180807d2SBill Paul static unsigned long yp_send_dns_query(name, type) 162180807d2SBill Paul char *name; 163180807d2SBill Paul int type; 164180807d2SBill Paul { 165180807d2SBill Paul char buf[MAXPACKET]; 166180807d2SBill Paul int n; 167180807d2SBill Paul HEADER *hptr; 168180807d2SBill Paul int ns; 169180807d2SBill Paul int rval; 170180807d2SBill Paul unsigned long id; 171180807d2SBill Paul 172180807d2SBill Paul bzero(buf, sizeof(buf)); 173180807d2SBill Paul 174180807d2SBill Paul n = res_mkquery(QUERY,name,C_IN,type,NULL,0,NULL,buf,sizeof(buf)); 175180807d2SBill Paul 176180807d2SBill Paul if (n <= 0) { 177180807d2SBill Paul yp_error("res_mkquery failed"); 178180807d2SBill Paul return(0); 179180807d2SBill Paul } 180180807d2SBill Paul 181180807d2SBill Paul hptr = (HEADER *)&buf; 182180807d2SBill Paul id = ntohs(hptr->id); 183180807d2SBill Paul 184180807d2SBill Paul for (ns = 0; ns < _res.nscount; ns++) { 185180807d2SBill Paul rval = sendto(resfd, buf, n, 0, 186180807d2SBill Paul (struct sockaddr *)&_res.nsaddr_list[ns], 187180807d2SBill Paul sizeof(struct sockaddr)); 188180807d2SBill Paul if (rval == -1) { 189180807d2SBill Paul yp_error("sendto failed"); 190180807d2SBill Paul return(0); 191180807d2SBill Paul } 192180807d2SBill Paul } 193180807d2SBill Paul 194180807d2SBill Paul return(id); 195180807d2SBill Paul } 196180807d2SBill Paul 1979c171de0SBill Paul static struct circleq_dnsentry *yp_find_dnsqent(id, type) 198180807d2SBill Paul unsigned long id; 1999c171de0SBill Paul int type; 200180807d2SBill Paul { 201180807d2SBill Paul register struct circleq_dnsentry *q; 202180807d2SBill Paul 203180807d2SBill Paul for (q = qhead.cqh_first; q != (void *)&qhead; q = q->links.cqe_next) { 2049c171de0SBill Paul switch(type) { 2059c171de0SBill Paul case BY_RPC_XID: 2069c171de0SBill Paul if (id == q->xid) 2079c171de0SBill Paul return(q); 2089c171de0SBill Paul break; 2099c171de0SBill Paul case BY_DNS_ID: 2109c171de0SBill Paul default: 211adc4fa33SBill Paul if (id == q->id) 212180807d2SBill Paul return(q); 2139c171de0SBill Paul break; 2149c171de0SBill Paul } 215180807d2SBill Paul } 216180807d2SBill Paul return (NULL); 217180807d2SBill Paul } 218180807d2SBill Paul 219180807d2SBill Paul static void yp_send_dns_reply(q, buf) 220180807d2SBill Paul struct circleq_dnsentry *q; 221180807d2SBill Paul char *buf; 222180807d2SBill Paul { 223adc4fa33SBill Paul ypresponse result_v1; 224adc4fa33SBill Paul ypresp_val result_v2; 225180807d2SBill Paul unsigned long xid; 226180807d2SBill Paul struct sockaddr_in client_addr; 227adc4fa33SBill Paul xdrproc_t xdrfunc; 228adc4fa33SBill Paul char *result; 229180807d2SBill Paul 230adc4fa33SBill Paul /* 231adc4fa33SBill Paul * Set up correct reply struct and 232adc4fa33SBill Paul * XDR filter depending on ypvers. 233adc4fa33SBill Paul */ 234adc4fa33SBill Paul switch(q->ypvers) { 235adc4fa33SBill Paul case YPVERS: 236adc4fa33SBill Paul bzero((char *)&result_v2, sizeof(result_v2)); 237180807d2SBill Paul 238180807d2SBill Paul if (buf == NULL) 239adc4fa33SBill Paul result_v2.stat = YP_NOKEY; 240180807d2SBill Paul else { 241adc4fa33SBill Paul result_v2.val.valdat_len = strlen(buf); 242adc4fa33SBill Paul result_v2.val.valdat_val = buf; 243adc4fa33SBill Paul result_v2.stat = YP_TRUE; 244adc4fa33SBill Paul } 245adc4fa33SBill Paul result = (char *)&result_v2; 246adc4fa33SBill Paul xdrfunc = (xdrproc_t)xdr_ypresp_val; 247adc4fa33SBill Paul break; 248adc4fa33SBill Paul case YPOLDVERS: 249adc4fa33SBill Paul /* 250adc4fa33SBill Paul * The odds are we will _never_ execute this 251adc4fa33SBill Paul * particular code, but we include it anyway 252adc4fa33SBill Paul * for the sake of completeness. 253adc4fa33SBill Paul */ 254adc4fa33SBill Paul bzero((char *)&result_v1, sizeof(result_v1)); 255adc4fa33SBill Paul result_v1.yp_resptype = YPRESP_VAL; 256adc4fa33SBill Paul # define YPVAL ypresponse_u.yp_resp_valtype 257adc4fa33SBill Paul 258adc4fa33SBill Paul if (buf == NULL) 259adc4fa33SBill Paul result_v1.YPVAL.stat = YP_NOKEY; 260adc4fa33SBill Paul else { 261adc4fa33SBill Paul result_v1.YPVAL.val.valdat_len = strlen(buf); 262adc4fa33SBill Paul result_v1.YPVAL.val.valdat_val = buf; 263adc4fa33SBill Paul result_v1.YPVAL.stat = YP_TRUE; 264adc4fa33SBill Paul } 265adc4fa33SBill Paul result = (char *)&result_v1; 266adc4fa33SBill Paul xdrfunc = (xdrproc_t)xdr_ypresponse; 267adc4fa33SBill Paul break; 268adc4fa33SBill Paul default: 269adc4fa33SBill Paul yp_error("Bad YP program version (%lu)!",q->ypvers); 270adc4fa33SBill Paul return; 271adc4fa33SBill Paul break; 272180807d2SBill Paul } 273180807d2SBill Paul 274180807d2SBill Paul if (debug) 275180807d2SBill Paul yp_error("Sending dns reply to %s (%lu)", 276adc4fa33SBill Paul inet_ntoa(q->client_addr.sin_addr), q->id); 277180807d2SBill Paul /* 278180807d2SBill Paul * XXX This is disgusting. There's basically one transport 279180807d2SBill Paul * handle for UDP, but we're holding off on replying to a 280180807d2SBill Paul * client until we're ready, by which time we may have received 281180807d2SBill Paul * several other queries from other clients with different 282180807d2SBill Paul * transaction IDs. So to make the delayed response thing work, 283180807d2SBill Paul * we have to save the transaction ID and client address of 284180807d2SBill Paul * each request, then jam them into the transport handle when 285180807d2SBill Paul * we're ready to send a reply. Then after we've send the reply, 286180807d2SBill Paul * we put the old transaction ID and remote address back the 287180807d2SBill Paul * way we found 'em. This is _INCREDIBLY_ non-portable; it's 288180807d2SBill Paul * not even supported by the RPC library. 289180807d2SBill Paul */ 290926f037aSBill Paul /* 291adc4fa33SBill Paul * XXX Don't frob the transaction ID for TCP handles. 292926f037aSBill Paul */ 293926f037aSBill Paul if (q->prot_type == SOCK_DGRAM) 294180807d2SBill Paul xid = svcudp_set_xid(q->xprt, q->xid); 295180807d2SBill Paul client_addr = q->xprt->xp_raddr; 296180807d2SBill Paul q->xprt->xp_raddr = q->client_addr; 297adc4fa33SBill Paul 298adc4fa33SBill Paul if (!svc_sendreply(q->xprt, xdrfunc, result)) 299180807d2SBill Paul yp_error("svc_sendreply failed"); 300adc4fa33SBill Paul 301adc4fa33SBill Paul /* 302adc4fa33SBill Paul * Now that we sent the reply, 303adc4fa33SBill Paul * put the handle back the way it was. 304adc4fa33SBill Paul */ 305926f037aSBill Paul if (q->prot_type == SOCK_DGRAM) 306180807d2SBill Paul svcudp_set_xid(q->xprt, xid); 307180807d2SBill Paul q->xprt->xp_raddr = client_addr; 308adc4fa33SBill Paul 309180807d2SBill Paul return; 310180807d2SBill Paul } 311180807d2SBill Paul 312adc4fa33SBill Paul /* 313adc4fa33SBill Paul * Decrement TTL on all queue entries, possibly nuking 314adc4fa33SBill Paul * any that have been around too long without being serviced. 315adc4fa33SBill Paul */ 316180807d2SBill Paul void yp_prune_dnsq() 317180807d2SBill Paul { 3187deb24a6SBill Paul register struct circleq_dnsentry *q, *n; 319180807d2SBill Paul 3207deb24a6SBill Paul q = qhead.cqh_first; 3217deb24a6SBill Paul while(q != (void *)&qhead) { 322180807d2SBill Paul q->ttl--; 3237deb24a6SBill Paul n = q->links.cqe_next; 324180807d2SBill Paul if (!q->ttl) { 325180807d2SBill Paul CIRCLEQ_REMOVE(&qhead, q, links); 326180807d2SBill Paul free(q->name); 327180807d2SBill Paul free(q); 328180807d2SBill Paul pending--; 329180807d2SBill Paul } 3307deb24a6SBill Paul q = n; 331180807d2SBill Paul } 332180807d2SBill Paul 333180807d2SBill Paul if (pending < 0) 334180807d2SBill Paul pending = 0; 335180807d2SBill Paul 336180807d2SBill Paul return; 337180807d2SBill Paul } 338180807d2SBill Paul 339adc4fa33SBill Paul /* 340adc4fa33SBill Paul * Data is pending on the DNS socket; check for valid replies 341adc4fa33SBill Paul * to our queries and dispatch them to waiting clients. 342adc4fa33SBill Paul */ 343180807d2SBill Paul void yp_run_dnsq() 344180807d2SBill Paul { 345180807d2SBill Paul register struct circleq_dnsentry *q; 346180807d2SBill Paul char buf[sizeof(HEADER) + MAXPACKET]; 347adc4fa33SBill Paul char retrybuf[MAXHOSTNAMELEN]; 348180807d2SBill Paul struct sockaddr_in sin; 349180807d2SBill Paul int rval; 350180807d2SBill Paul int len; 351180807d2SBill Paul HEADER *hptr; 352180807d2SBill Paul struct hostent *hent; 353180807d2SBill Paul 354180807d2SBill Paul if (debug) 355180807d2SBill Paul yp_error("Running dns queue"); 356180807d2SBill Paul 357180807d2SBill Paul bzero(buf, sizeof(buf)); 358180807d2SBill Paul 359180807d2SBill Paul len = sizeof(struct sockaddr_in); 360180807d2SBill Paul rval = recvfrom(resfd, buf, sizeof(buf), 0, 361180807d2SBill Paul (struct sockaddr *)&sin, &len); 362180807d2SBill Paul 363180807d2SBill Paul if (rval == -1) { 364180807d2SBill Paul yp_error("recvfrom failed: %s", strerror(errno)); 365180807d2SBill Paul return; 366180807d2SBill Paul } 367180807d2SBill Paul 368adc4fa33SBill Paul /* 369adc4fa33SBill Paul * We may have data left in the socket that represents 370adc4fa33SBill Paul * replies to earlier queries that we don't care about 371adc4fa33SBill Paul * anymore. If there are no lookups pending or the packet 372adc4fa33SBill Paul * ID doesn't match any of the queue IDs, just drop it 373adc4fa33SBill Paul * on the floor. 374adc4fa33SBill Paul */ 375180807d2SBill Paul hptr = (HEADER *)&buf; 3769c171de0SBill Paul if (!pending || 3779c171de0SBill Paul (q = yp_find_dnsqent(ntohs(hptr->id), BY_DNS_ID)) == NULL) { 378adc4fa33SBill Paul /* ignore */ 379180807d2SBill Paul return; 380180807d2SBill Paul } 381180807d2SBill Paul 382180807d2SBill Paul if (debug) 383180807d2SBill Paul yp_error("Got dns reply from %s", inet_ntoa(sin.sin_addr)); 384180807d2SBill Paul 385180807d2SBill Paul hent = __dns_getanswer(buf, rval, q->name, q->type); 386180807d2SBill Paul 387adc4fa33SBill Paul /* 388adc4fa33SBill Paul * If the lookup failed, try appending one of the domains 389adc4fa33SBill Paul * from resolv.conf. If we have no domains to test, the 390adc4fa33SBill Paul * query has failed. 391adc4fa33SBill Paul */ 392180807d2SBill Paul if (hent == NULL) { 393926f037aSBill Paul if (h_errno == TRY_AGAIN && q->domain && *q->domain) { 394180807d2SBill Paul snprintf(retrybuf, sizeof(retrybuf), "%s.%s", 395180807d2SBill Paul q->name, *q->domain); 396180807d2SBill Paul if (debug) 397180807d2SBill Paul yp_error("Retrying with: %s", retrybuf); 398180807d2SBill Paul q->id = yp_send_dns_query(retrybuf, q->type); 399180807d2SBill Paul q->ttl = DEF_TTL; 400180807d2SBill Paul q->domain++; 401180807d2SBill Paul return; 402180807d2SBill Paul } 403926f037aSBill Paul } else { 404180807d2SBill Paul if (q->type == T_PTR) { 405180807d2SBill Paul hent->h_addr = (char *)&q->addr.s_addr; 406180807d2SBill Paul hent->h_length = sizeof(struct in_addr); 407180807d2SBill Paul } 408926f037aSBill Paul } 409926f037aSBill Paul 410adc4fa33SBill Paul /* Got an answer ready for a client -- send it off. */ 411180807d2SBill Paul yp_send_dns_reply(q, parse(hent)); 412180807d2SBill Paul pending--; 413180807d2SBill Paul CIRCLEQ_REMOVE(&qhead, q, links); 414180807d2SBill Paul free(q->name); 415180807d2SBill Paul free(q); 416180807d2SBill Paul 417adc4fa33SBill Paul /* Decrement TTLs on other entries while we're here. */ 418180807d2SBill Paul yp_prune_dnsq(); 419180807d2SBill Paul 420180807d2SBill Paul return; 421180807d2SBill Paul } 422180807d2SBill Paul 423adc4fa33SBill Paul /* 424adc4fa33SBill Paul * Queue and transmit an asynchronous DNS hostname lookup. 425adc4fa33SBill Paul */ 426adc4fa33SBill Paul ypstat yp_async_lookup_name(rqstp, name) 427adc4fa33SBill Paul struct svc_req *rqstp; 428180807d2SBill Paul char *name; 429180807d2SBill Paul { 430180807d2SBill Paul register struct circleq_dnsentry *q; 431926f037aSBill Paul int type, len; 432180807d2SBill Paul 4339c171de0SBill Paul /* Check for SOCK_DGRAM or SOCK_STREAM -- we need to know later */ 4341f552b61SBill Paul type = -1; len = sizeof(type); 4359c171de0SBill Paul if (getsockopt(rqstp->rq_xprt->xp_sock, SOL_SOCKET, 4369c171de0SBill Paul SO_TYPE, &type, &len) == -1) { 4379c171de0SBill Paul yp_error("getsockopt failed: %s", strerror(errno)); 4389c171de0SBill Paul return(YP_YPERR); 4399c171de0SBill Paul } 4409c171de0SBill Paul 4419c171de0SBill Paul /* Avoid transmitting dupe requests. */ 4429c171de0SBill Paul if (type == SOCK_DGRAM && 4439c171de0SBill Paul yp_find_dnsqent(svcudp_get_xid(rqstp->rq_xprt),BY_RPC_XID) != NULL) 4449c171de0SBill Paul return(YP_TRUE); 4459c171de0SBill Paul 446180807d2SBill Paul if ((q = yp_malloc_dnsent()) == NULL) 447180807d2SBill Paul return(YP_YPERR); 448180807d2SBill Paul 449180807d2SBill Paul q->type = T_A; 450180807d2SBill Paul q->ttl = DEF_TTL; 451adc4fa33SBill Paul q->xprt = rqstp->rq_xprt; 452adc4fa33SBill Paul q->ypvers = rqstp->rq_vers; 453926f037aSBill Paul q->prot_type = type; 454926f037aSBill Paul if (q->prot_type == SOCK_DGRAM) 455adc4fa33SBill Paul q->xid = svcudp_get_xid(q->xprt); 456adc4fa33SBill Paul q->client_addr = q->xprt->xp_raddr; 457180807d2SBill Paul if (!strchr(name, '.')) 458180807d2SBill Paul q->domain = _res.dnsrch; 459180807d2SBill Paul else 460180807d2SBill Paul q->domain = NULL; 461180807d2SBill Paul q->id = yp_send_dns_query(name, q->type); 462180807d2SBill Paul 463180807d2SBill Paul if (q->id == 0) { 464180807d2SBill Paul yp_error("DNS query failed"); 465180807d2SBill Paul free(q); 466180807d2SBill Paul return(YP_YPERR); 467180807d2SBill Paul } 468180807d2SBill Paul 469180807d2SBill Paul q->name = strdup(name); 470180807d2SBill Paul CIRCLEQ_INSERT_HEAD(&qhead, q, links); 471180807d2SBill Paul pending++; 472180807d2SBill Paul 473180807d2SBill Paul if (debug) 474180807d2SBill Paul yp_error("Queueing async DNS name lookup (%d)", q->id); 475180807d2SBill Paul 4767deb24a6SBill Paul yp_prune_dnsq(); 477180807d2SBill Paul return(YP_TRUE); 478180807d2SBill Paul } 479180807d2SBill Paul 480adc4fa33SBill Paul /* 481adc4fa33SBill Paul * Queue and transmit an asynchronous DNS IP address lookup. 482adc4fa33SBill Paul */ 483adc4fa33SBill Paul ypstat yp_async_lookup_addr(rqstp, addr) 484adc4fa33SBill Paul struct svc_req *rqstp; 485180807d2SBill Paul char *addr; 486180807d2SBill Paul { 487180807d2SBill Paul register struct circleq_dnsentry *q; 488180807d2SBill Paul char buf[MAXHOSTNAMELEN]; 489180807d2SBill Paul int a, b, c, d; 490926f037aSBill Paul int type, len; 491180807d2SBill Paul 4929c171de0SBill Paul /* Check for SOCK_DGRAM or SOCK_STREAM -- we need to know later */ 4931f552b61SBill Paul type = -1; len = sizeof(type); 4949c171de0SBill Paul if (getsockopt(rqstp->rq_xprt->xp_sock, SOL_SOCKET, 4959c171de0SBill Paul SO_TYPE, &type, &len) == -1) { 4969c171de0SBill Paul yp_error("getsockopt failed: %s", strerror(errno)); 4979c171de0SBill Paul return(YP_YPERR); 4989c171de0SBill Paul } 4999c171de0SBill Paul 5009c171de0SBill Paul /* Avoid transmitting dupe requests. */ 5019c171de0SBill Paul if (type == SOCK_DGRAM && 5029c171de0SBill Paul yp_find_dnsqent(svcudp_get_xid(rqstp->rq_xprt),BY_RPC_XID) != NULL) 5039c171de0SBill Paul return(YP_TRUE); 5049c171de0SBill Paul 505180807d2SBill Paul if ((q = yp_malloc_dnsent()) == NULL) 506180807d2SBill Paul return(YP_YPERR); 507180807d2SBill Paul 508180807d2SBill Paul if (sscanf(addr, "%d.%d.%d.%d", &a, &b, &c, &d) != 4) 509180807d2SBill Paul return(YP_NOKEY); 510180807d2SBill Paul 5119c171de0SBill Paul snprintf(buf, sizeof(buf), "%d.%d.%d.%d.in-addr.arpa", d, c, b, a); 512180807d2SBill Paul 513180807d2SBill Paul if (debug) 514180807d2SBill Paul yp_error("DNS address is: %s", buf); 515180807d2SBill Paul 516180807d2SBill Paul q->type = T_PTR; 517180807d2SBill Paul q->ttl = DEF_TTL; 518adc4fa33SBill Paul q->xprt = rqstp->rq_xprt; 519adc4fa33SBill Paul q->ypvers = rqstp->rq_vers; 520180807d2SBill Paul q->domain = NULL; 521926f037aSBill Paul q->prot_type = type; 522926f037aSBill Paul if (q->prot_type == SOCK_DGRAM) 523adc4fa33SBill Paul q->xid = svcudp_get_xid(q->xprt); 524adc4fa33SBill Paul q->client_addr = q->xprt->xp_raddr; 525180807d2SBill Paul q->id = yp_send_dns_query(buf, q->type); 526180807d2SBill Paul 527180807d2SBill Paul if (q->id == 0) { 528180807d2SBill Paul yp_error("DNS query failed"); 529180807d2SBill Paul free(q); 530180807d2SBill Paul return(YP_YPERR); 531180807d2SBill Paul } 532180807d2SBill Paul 533180807d2SBill Paul inet_aton(addr, &q->addr); 534180807d2SBill Paul q->name = strdup(buf); 535180807d2SBill Paul CIRCLEQ_INSERT_HEAD(&qhead, q, links); 536180807d2SBill Paul pending++; 537180807d2SBill Paul 538180807d2SBill Paul if (debug) 539180807d2SBill Paul yp_error("Queueing async DNS address lookup (%d)", q->id); 540180807d2SBill Paul 5417deb24a6SBill Paul yp_prune_dnsq(); 542180807d2SBill Paul return(YP_TRUE); 543778c7b1cSBill Paul } 544