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.4 (Berkeley) 02/04/86"; 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, eom, 104 cp, bp, buflen)) < 0) { 105 h_errno = NO_RECOVERY; 106 return (NULL); 107 } 108 cp += n + QFIXEDSZ; 109 host.h_name = bp; 110 n = strlen(bp) + 1; 111 bp += n; 112 buflen -= n; 113 } else 114 cp += dn_skip(cp) + QFIXEDSZ; 115 while (--qdcount > 0) 116 cp += dn_skip(cp) + QFIXEDSZ; 117 } else if (iquery) { 118 if (hp->aa) 119 h_errno = HOST_NOT_FOUND; 120 else 121 h_errno = TRY_AGAIN; 122 return (NULL); 123 } 124 ap = host_aliases; 125 host.h_aliases = host_aliases; 126 hap = h_addr_ptrs; 127 host.h_addr_list = h_addr_ptrs; 128 haveanswer = 0; 129 while (--ancount >= 0 && cp < eom) { 130 if ((n = dn_expand((char *)&answer, eom, cp, bp, buflen)) < 0) 131 break; 132 cp += n; 133 type = getshort(cp); 134 cp += sizeof(u_short); 135 class = getshort(cp); 136 cp += sizeof(u_short) + sizeof(u_long); 137 n = getshort(cp); 138 cp += sizeof(u_short); 139 if (type == T_CNAME) { 140 cp += n; 141 if (ap >= &host_aliases[MAXALIASES-1]) 142 continue; 143 *ap++ = bp; 144 n = strlen(bp) + 1; 145 bp += n; 146 buflen -= n; 147 continue; 148 } 149 if (type == T_PTR) { 150 if ((n = dn_expand((char *)&answer, eom, cp, bp, buflen)) < 151 0) { 152 cp += n; 153 continue; 154 } 155 cp += n; 156 host.h_name = bp; 157 return(&host); 158 } 159 if (type != T_A) { 160 #ifdef DEBUG 161 if (_res.options & RES_DEBUG) 162 printf("unexpected answer type %d, size %d\n", 163 type, n); 164 #endif 165 cp += n; 166 continue; 167 } 168 if (haveanswer) { 169 if (n != host.h_length) { 170 cp += n; 171 continue; 172 } 173 if (class != getclass) { 174 cp += n; 175 continue; 176 } 177 } else { 178 host.h_length = n; 179 getclass = class; 180 host.h_addrtype = (class == C_IN) ? AF_INET : AF_UNSPEC; 181 if (!iquery) { 182 host.h_name = bp; 183 bp += strlen(bp) + 1; 184 } 185 } 186 187 bp += ((u_long)bp % sizeof(align)); 188 189 if (bp + n >= &hostbuf[sizeof(hostbuf)]) { 190 #ifdef DEBUG 191 if (_res.options & RES_DEBUG) 192 printf("size (%d) too big\n", n); 193 #endif 194 break; 195 } 196 bcopy(cp, *hap++ = bp, n); 197 bp +=n; 198 cp += n; 199 haveanswer++; 200 } 201 if (haveanswer) { 202 *ap = NULL; 203 *hap = NULL; 204 return (&host); 205 } else { 206 h_errno = TRY_AGAIN; 207 return (NULL); 208 } 209 } 210 211 struct hostent * 212 gethostbyname(name) 213 char *name; 214 { 215 int n; 216 querybuf buf; 217 218 n = res_mkquery(QUERY, name, C_ANY, T_A, (char *)NULL, 0, NULL, 219 (char *)&buf, sizeof(buf)); 220 if (n < 0) { 221 #ifdef DEBUG 222 if (_res.options & RES_DEBUG) 223 printf("res_mkquery failed\n"); 224 #endif 225 return (NULL); 226 } 227 return(getanswer((char *)&buf, n, 0)); 228 } 229 230 struct hostent * 231 gethostbyaddr(addr, len, type) 232 char *addr; 233 int len, type; 234 { 235 int n; 236 querybuf buf; 237 register struct hostent *hp; 238 char qbuf[MAXDNAME]; 239 240 if (type != AF_INET) 241 return (NULL); 242 (void)sprintf(qbuf, "%d.%d.%d.%d.in-addr.arpa", 243 ((unsigned)addr[3] & 0xff), 244 ((unsigned)addr[2] & 0xff), 245 ((unsigned)addr[1] & 0xff), 246 ((unsigned)addr[0] & 0xff)); 247 n = res_mkquery(QUERY, qbuf, C_IN, T_PTR, NULL, 0, NULL, 248 (char *)&buf, sizeof(buf)); 249 if (n < 0) { 250 #ifdef DEBUG 251 if (_res.options & RES_DEBUG) 252 printf("res_mkquery failed\n"); 253 #endif 254 return (NULL); 255 } 256 if ((hp = getanswer((char *)&buf, n, 1)) == NULL) 257 return(NULL); 258 hp->h_addrtype = type; 259 hp->h_length = len; 260 h_addr_ptrs[0] = (char *)&host_addr; 261 h_addr_ptrs[1] = (char *)0; 262 host_addr = *(struct in_addr *)addr; 263 return(hp); 264 } 265 266