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