1 /* 2 * Copyright (c) 1983 Regents of the University of California. 3 * All rights reserved. The Berkeley software License Agreement 4 * specifies the terms and conditions for redistribution. 5 */ 6 7 #ifndef lint 8 static char sccsid[] = "@(#)gethostnamadr.c 5.1 (Berkeley) 05/30/85"; 9 #endif not lint 10 11 /* 12 * Copyright (c) 1985 Regents of the University of California 13 * All Rights Reserved 14 */ 15 16 #include <sys/types.h> 17 #include <sys/socket.h> 18 #include <netinet/in.h> 19 #include <netdb.h> 20 #include <stdio.h> 21 #include <nameser.h> 22 #include <resolv.h> 23 24 #define MAXALIASES 35 25 26 static struct hostent host; 27 static char *host_aliases[MAXALIASES]; 28 static char hostbuf[BUFSIZ+1]; 29 30 static struct hostent * 31 getanswer(msg, msglen, iquery) 32 char *msg; 33 int msglen, iquery; 34 { 35 register HEADER *hp; 36 register char *cp; 37 register int n; 38 char answer[PACKETSZ]; 39 char *eom, *bp, **ap; 40 int type, class, ancount, buflen; 41 42 n = res_send(msg, msglen, answer, sizeof(answer)); 43 if (n < 0) { 44 if (_res.options & RES_DEBUG) 45 printf("res_send failed\n"); 46 return (NULL); 47 } 48 eom = answer + n; 49 /* 50 * find first satisfactory answer 51 */ 52 hp = (HEADER *) answer; 53 ancount = ntohs(hp->ancount); 54 if (hp->rcode != NOERROR || ancount == 0) { 55 if (_res.options & RES_DEBUG) 56 printf("rcode = %d, ancount=%d\n", hp->rcode, ancount); 57 return (NULL); 58 } 59 bp = hostbuf; 60 buflen = sizeof(hostbuf); 61 ap = host_aliases; 62 cp = answer + sizeof(HEADER); 63 if (hp->qdcount) { 64 if (iquery) { 65 if ((n = dn_expand(answer, cp, bp, buflen)) < 0) 66 return (NULL); 67 cp += n + QFIXEDSZ; 68 host.h_name = bp; 69 n = strlen(bp) + 1; 70 bp += n; 71 buflen -= n; 72 } else 73 cp += dn_skip(cp) + QFIXEDSZ; 74 } else if (iquery) 75 return (NULL); 76 while (--ancount >= 0 && cp < eom) { 77 if ((n = dn_expand(answer, cp, bp, buflen)) < 0) 78 return (NULL); 79 cp += n; 80 type = getshort(cp); 81 cp += sizeof(u_short); 82 class = getshort(cp); 83 cp += sizeof(u_short) + sizeof(u_long); 84 n = getshort(cp); 85 cp += sizeof(u_short); 86 if (type == T_CNAME) { 87 cp += n; 88 if (ap >= &host_aliases[MAXALIASES-1]) 89 continue; 90 *ap++ = bp; 91 n = strlen(bp) + 1; 92 bp += n; 93 buflen -= n; 94 continue; 95 } 96 if (type != T_A || n != 4) { 97 if (_res.options & RES_DEBUG) 98 printf("unexpected answer type %d, size %d\n", 99 type, n); 100 continue; 101 } 102 if (!iquery) { 103 host.h_name = bp; 104 bp += strlen(bp) + 1; 105 } 106 *ap = NULL; 107 host.h_aliases = host_aliases; 108 host.h_addrtype = class == C_IN ? AF_INET : AF_UNSPEC; 109 if (bp + n >= &hostbuf[sizeof(hostbuf)]) { 110 if (_res.options & RES_DEBUG) 111 printf("size (%d) too big\n", n); 112 return (NULL); 113 } 114 bcopy(cp, host.h_addr = bp, host.h_length = n); 115 return (&host); 116 } 117 return (NULL); 118 } 119 120 struct hostent * 121 gethostbyname(name) 122 char *name; 123 { 124 int n; 125 126 n = res_mkquery(QUERY, name, C_ANY, T_A, NULL, 0, NULL, 127 hostbuf, sizeof(hostbuf)); 128 if (n < 0) { 129 if (_res.options & RES_DEBUG) 130 printf("res_mkquery failed\n"); 131 return (NULL); 132 } 133 return (getanswer(hostbuf, n, 0)); 134 } 135 136 struct hostent * 137 gethostbyaddr(addr, len, type) 138 char *addr; 139 int len, type; 140 { 141 int n; 142 143 if (type != AF_INET) 144 return (NULL); 145 n = res_mkquery(IQUERY, NULL, C_IN, T_A, addr, len, NULL, 146 hostbuf, sizeof(hostbuf)); 147 if (n < 0) { 148 if (_res.options & RES_DEBUG) 149 printf("res_mkquery failed\n"); 150 return (NULL); 151 } 152 return (getanswer(hostbuf, n, 1)); 153 } 154