1 /* 2 * Copyright (c) 1985 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 6.3 (Berkeley) 11/15/85"; 9 #endif not lint 10 11 #include <sys/param.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 typedef union { 30 HEADER qb1; 31 char qb2[PACKETSZ]; 32 } querybuf; 33 34 static union { 35 long al; 36 char ac; 37 } align; 38 39 40 int h_errno; 41 42 static struct hostent * 43 getanswer(msg, msglen, iquery) 44 char *msg; 45 int msglen, iquery; 46 { 47 register HEADER *hp; 48 register char *cp; 49 register int n; 50 querybuf answer; 51 char *eom, *bp, **ap; 52 int type, class, ancount, qdcount, buflen; 53 int haveanswer, getclass; 54 char **hap; 55 56 n = res_send(msg, msglen, (char *)&answer, sizeof(answer)); 57 if (n < 0) { 58 #ifdef DEBUG 59 if (_res.options & RES_DEBUG) 60 printf("res_send failed\n"); 61 #endif 62 h_errno = TRY_AGAIN; 63 return (NULL); 64 } 65 eom = (char *)&answer + n; 66 /* 67 * find first satisfactory answer 68 */ 69 hp = (HEADER *) &answer; 70 ancount = ntohs(hp->ancount); 71 qdcount = ntohs(hp->qdcount); 72 if (hp->rcode != NOERROR || ancount == 0) { 73 #ifdef DEBUG 74 if (_res.options & RES_DEBUG) 75 printf("rcode = %d, ancount=%d\n", hp->rcode, ancount); 76 #endif 77 switch (hp->rcode) { 78 case NXDOMAIN: 79 /* Check if it's an authoritive answer */ 80 if (hp->aa) 81 h_errno = HOST_NOT_FOUND; 82 else 83 h_errno = TRY_AGAIN; 84 break; 85 case SERVFAIL: 86 h_errno = TRY_AGAIN; 87 break; 88 case NOERROR: 89 h_errno = NO_ADDRESS; 90 break; 91 case FORMERR: 92 case NOTIMP: 93 case REFUSED: 94 h_errno = NO_RECOVERY; 95 } 96 return (NULL); 97 } 98 bp = hostbuf; 99 buflen = sizeof(hostbuf); 100 cp = (char *)&answer + sizeof(HEADER); 101 if (qdcount) { 102 if (iquery) { 103 if ((n = dn_expand((char *)&answer, cp, bp, buflen)) < 0) { 104 h_errno = NO_RECOVERY; 105 return (NULL); 106 } 107 cp += n + QFIXEDSZ; 108 host.h_name = bp; 109 n = strlen(bp) + 1; 110 bp += n; 111 buflen -= n; 112 } else 113 cp += dn_skip(cp) + QFIXEDSZ; 114 while (--qdcount > 0) 115 cp += dn_skip(cp) + QFIXEDSZ; 116 } else if (iquery) { 117 if (hp->aa) 118 h_errno = HOST_NOT_FOUND; 119 else 120 h_errno = TRY_AGAIN; 121 return (NULL); 122 } 123 ap = host_aliases; 124 host.h_aliases = host_aliases; 125 hap = h_addr_ptrs; 126 host.h_addr_list = h_addr_ptrs; 127 haveanswer = 0; 128 while (--ancount >= 0 && cp < eom) { 129 if ((n = dn_expand((char *)&answer, cp, bp, buflen)) < 0) 130 break; 131 cp += n; 132 type = getshort(cp); 133 cp += sizeof(u_short); 134 class = getshort(cp); 135 cp += sizeof(u_short) + sizeof(u_long); 136 n = getshort(cp); 137 cp += sizeof(u_short); 138 if (type == T_CNAME) { 139 cp += n; 140 if (ap >= &host_aliases[MAXALIASES-1]) 141 continue; 142 *ap++ = bp; 143 n = strlen(bp) + 1; 144 bp += n; 145 buflen -= n; 146 continue; 147 } 148 if (type == T_PTR) { 149 if ((n = dn_expand((char *)&answer, cp, bp, buflen)) < 150 0) { 151 cp += n; 152 continue; 153 } 154 cp += n; 155 host.h_name = bp; 156 return(&host); 157 } 158 if (type != T_A) { 159 #ifdef DEBUG 160 if (_res.options & RES_DEBUG) 161 printf("unexpected answer type %d, size %d\n", 162 type, n); 163 #endif 164 cp += n; 165 continue; 166 } 167 if (haveanswer) { 168 if (n != host.h_length) { 169 cp += n; 170 continue; 171 } 172 if (class != getclass) { 173 cp += n; 174 continue; 175 } 176 } else { 177 host.h_length = n; 178 getclass = class; 179 host.h_addrtype = (class == C_IN) ? AF_INET : AF_UNSPEC; 180 if (!iquery) { 181 host.h_name = bp; 182 bp += strlen(bp) + 1; 183 } 184 } 185 186 bp += ((u_long)bp % sizeof(align)); 187 188 if (bp + n >= &hostbuf[sizeof(hostbuf)]) { 189 #ifdef DEBUG 190 if (_res.options & RES_DEBUG) 191 printf("size (%d) too big\n", n); 192 #endif 193 break; 194 } 195 bcopy(cp, *hap++ = bp, n); 196 bp +=n; 197 cp += n; 198 haveanswer++; 199 } 200 if (haveanswer) { 201 *ap = NULL; 202 *hap = NULL; 203 return (&host); 204 } else { 205 h_errno = TRY_AGAIN; 206 return (NULL); 207 } 208 } 209 210 struct hostent * 211 gethostbyname(name) 212 char *name; 213 { 214 int n; 215 querybuf buf; 216 217 n = res_mkquery(QUERY, name, C_ANY, T_A, (char *)NULL, 0, NULL, 218 (char *)&buf, sizeof(buf)); 219 if (n < 0) { 220 #ifdef DEBUG 221 if (_res.options & RES_DEBUG) 222 printf("res_mkquery failed\n"); 223 #endif 224 return (NULL); 225 } 226 return(getanswer((char *)&buf, n, 0)); 227 } 228 229 struct hostent * 230 gethostbyaddr(addr, len, type) 231 char *addr; 232 int len, type; 233 { 234 int n; 235 querybuf buf; 236 register struct hostent *hp; 237 char qbuf[MAXDNAME]; 238 239 if (type != AF_INET) 240 return (NULL); 241 (void)sprintf(qbuf, "%d.%d.%d.%d.in-addr.arpa", 242 ((unsigned)addr[3] & 0xff), 243 ((unsigned)addr[2] & 0xff), 244 ((unsigned)addr[1] & 0xff), 245 ((unsigned)addr[0] & 0xff)); 246 n = res_mkquery(QUERY, qbuf, C_IN, T_PTR, NULL, 0, NULL, 247 (char *)&buf, sizeof(buf)); 248 if (n < 0) { 249 #ifdef DEBUG 250 if (_res.options & RES_DEBUG) 251 printf("res_mkquery failed\n"); 252 #endif 253 return (NULL); 254 } 255 if ((hp = getanswer((char *)&buf, n, 1)) == NULL) 256 return(NULL); 257 hp->h_addrtype = type; 258 hp->h_length = len; 259 h_addr_ptrs[0] = (char *)&host_addr; 260 h_addr_ptrs[1] = (char *)0; 261 host_addr = *(struct in_addr *)addr; 262 return(hp); 263 } 264 265