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.9 (Berkeley) 10/24/85"; 9 #endif not lint 10 11 #include <sys/types.h> 12 #include <sys/socket.h> 13 #include <netinet/in.h> 14 #include <netdb.h> 15 #include <stdio.h> 16 #include <arpa/nameser.h> 17 #include <arpa/resolv.h> 18 19 #define MAXALIASES 35 20 #define MAXADDRS 35 21 22 static char *h_addr_ptrs[MAXADDRS + 1]; 23 24 static struct hostent host; 25 static char *host_aliases[MAXALIASES]; 26 static char hostbuf[BUFSIZ+1]; 27 static struct in_addr host_addr; 28 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, qdcount, buflen; 41 int haveanswer, getclass; 42 char **hap; 43 44 n = res_send(msg, msglen, answer, sizeof(answer)); 45 if (n < 0) { 46 #ifdef DEBUG 47 if (_res.options & RES_DEBUG) 48 printf("res_send failed\n"); 49 #endif 50 return (NULL); 51 } 52 eom = answer + n; 53 /* 54 * find first satisfactory answer 55 */ 56 hp = (HEADER *) answer; 57 ancount = ntohs(hp->ancount); 58 qdcount = ntohs(hp->qdcount); 59 if (hp->rcode != NOERROR || ancount == 0) { 60 #ifdef DEBUG 61 if (_res.options & RES_DEBUG) 62 printf("rcode = %d, ancount=%d\n", hp->rcode, ancount); 63 #endif 64 return (NULL); 65 } 66 bp = hostbuf; 67 buflen = sizeof(hostbuf); 68 cp = answer + sizeof(HEADER); 69 if (qdcount) { 70 if (iquery) { 71 if ((n = dn_expand(answer, cp, bp, buflen)) < 0) 72 return (NULL); 73 cp += n + QFIXEDSZ; 74 host.h_name = bp; 75 n = strlen(bp) + 1; 76 bp += n; 77 buflen -= n; 78 } else 79 cp += dn_skip(cp) + QFIXEDSZ; 80 while (--qdcount > 0) 81 cp += dn_skip(cp) + QFIXEDSZ; 82 } else if (iquery) 83 return (NULL); 84 ap = host_aliases; 85 host.h_aliases = host_aliases; 86 hap = h_addr_ptrs; 87 host.h_addr_list = h_addr_ptrs; 88 haveanswer = 0; 89 while (--ancount >= 0 && cp < eom) { 90 if ((n = dn_expand(answer, cp, bp, buflen)) < 0) 91 break; 92 cp += n; 93 type = getshort(cp); 94 cp += sizeof(u_short); 95 class = getshort(cp); 96 cp += sizeof(u_short) + sizeof(u_long); 97 n = getshort(cp); 98 cp += sizeof(u_short); 99 if (type == T_CNAME) { 100 cp += n; 101 if (ap >= &host_aliases[MAXALIASES-1]) 102 continue; 103 *ap++ = bp; 104 n = strlen(bp) + 1; 105 bp += n; 106 buflen -= n; 107 continue; 108 } 109 if (type == T_PTR) { 110 if ((n = dn_expand(answer, cp, bp, buflen)) < 0) { 111 cp += n; 112 continue; 113 } 114 cp += n; 115 host.h_name = bp; 116 return(&host); 117 } 118 if (type != T_A) { 119 #ifdef DEBUG 120 if (_res.options & RES_DEBUG) 121 printf("unexpected answer type %d, size %d\n", 122 type, n); 123 #endif 124 cp += n; 125 continue; 126 } 127 if (haveanswer) { 128 if (n != host.h_length) { 129 cp += n; 130 continue; 131 } 132 if (class != getclass) { 133 cp += n; 134 continue; 135 } 136 } else { 137 host.h_length = n; 138 getclass = class; 139 host.h_addrtype = C_IN ? AF_INET : AF_UNSPEC; 140 if (!iquery) { 141 host.h_name = bp; 142 bp += strlen(bp) + 1; 143 } 144 } 145 if (bp + n >= &hostbuf[sizeof(hostbuf)]) { 146 #ifdef DEBUG 147 if (_res.options & RES_DEBUG) 148 printf("size (%d) too big\n", n); 149 #endif 150 break; 151 } 152 bcopy(cp, *hap++ = bp, n); 153 bp +=n; 154 cp += n; 155 haveanswer++; 156 } 157 if (haveanswer) { 158 *ap = NULL; 159 *hap = NULL; 160 return (&host); 161 } else 162 return (NULL); 163 } 164 165 struct hostent * 166 gethostbyname(name) 167 char *name; 168 { 169 int n; 170 char buf[BUFSIZ+1]; 171 172 n = res_mkquery(QUERY, name, C_ANY, T_A, (char *)NULL, 0, NULL, 173 buf, sizeof(buf)); 174 if (n < 0) { 175 #ifdef DEBUG 176 if (_res.options & RES_DEBUG) 177 printf("res_mkquery failed\n"); 178 #endif 179 return (NULL); 180 } 181 return(getanswer(buf, n, 0)); 182 } 183 184 struct hostent * 185 gethostbyaddr(addr, len, type) 186 char *addr; 187 int len, type; 188 { 189 int n; 190 char buf[BUFSIZ+1]; 191 register struct hostent *hp; 192 char qbuf[MAXDNAME]; 193 194 if (type != AF_INET) 195 return (NULL); 196 (void)sprintf(qbuf, "%d.%d.%d.%d.in-addr.arpa", 197 (*(unsigned *)addr >> 24 & 0xff), 198 (*(unsigned *)addr >> 16 & 0xff), 199 (*(unsigned *)addr >> 8 & 0xff), 200 (*(unsigned *)addr & 0xff)); 201 n = res_mkquery(QUERY, qbuf, C_IN, T_PTR, NULL, 0, NULL, 202 buf, sizeof(buf)); 203 if (n < 0) { 204 #ifdef DEBUG 205 if (_res.options & RES_DEBUG) 206 printf("res_mkquery failed\n"); 207 #endif 208 return (NULL); 209 } 210 if ((hp = getanswer(buf, n, 1)) == NULL) 211 return(NULL); 212 hp->h_addrtype = type; 213 hp->h_length = len; 214 h_addr_ptrs[0] = (char *)&host_addr; 215 h_addr_ptrs[1] = (char *)0; 216 host_addr = *(struct in_addr *)addr; 217 return(hp); 218 } 219