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