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 5.3 (Berkeley) 09/03/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 21 #define XX 2 22 static char h_addr_buf[sizeof(struct in_addr) * XX]; 23 static char *h_addr_ptr[XX] = { 24 &h_addr_buf[0], 25 &h_addr_buf[sizeof(struct in_addr)] 26 }; 27 static struct hostent host = { 28 NULL, /* official name of host */ 29 NULL, /* alias list */ 30 0, /* host address type */ 31 0, /* length of address */ 32 h_addr_ptr /* list of addresses from name server */ 33 }; 34 static char *host_aliases[MAXALIASES]; 35 static char hostbuf[BUFSIZ+1]; 36 37 #ifdef BOMBPROOFING 38 #include <ndbm.h> 39 DBM *_host_db = NULL; 40 int _host_stayopen = 0; 41 int _host_bombed; 42 struct hostent *_oldgethostbyname(), *_oldgethostbyaddr(); 43 #endif BOMBPROOFING 44 45 static struct hostent * 46 getanswer(msg, msglen, iquery) 47 char *msg; 48 int msglen, iquery; 49 { 50 register HEADER *hp; 51 register char *cp; 52 register int n; 53 char answer[PACKETSZ]; 54 char *eom, *bp, **ap; 55 int type, class, ancount, buflen; 56 57 #ifdef BOMBPROOFING 58 _host_bombed = 0; 59 #endif BOMBPROOFING 60 n = res_send(msg, msglen, answer, sizeof(answer)); 61 if (n < 0) { 62 if (_res.options & RES_DEBUG) 63 printf("res_send failed\n"); 64 #ifdef BOMBPROOFING 65 _host_bombed++; 66 #endif BOMBPROOFING 67 return (NULL); 68 } 69 eom = answer + n; 70 /* 71 * find first satisfactory answer 72 */ 73 hp = (HEADER *) answer; 74 ancount = ntohs(hp->ancount); 75 if (hp->rcode != NOERROR || ancount == 0) { 76 if (_res.options & RES_DEBUG) 77 printf("rcode = %d, ancount=%d\n", hp->rcode, ancount); 78 #ifdef BOMBPROOFING 79 if (!(hp->rcode == NOERROR && ancount == 0)) 80 _host_bombed++; 81 #endif BOMBPROOFING 82 return (NULL); 83 } 84 bp = hostbuf; 85 buflen = sizeof(hostbuf); 86 ap = host_aliases; 87 cp = answer + sizeof(HEADER); 88 if (hp->qdcount) { 89 if (iquery) { 90 if ((n = dn_expand(answer, cp, bp, buflen)) < 0) 91 return (NULL); 92 cp += n + QFIXEDSZ; 93 host.h_name = bp; 94 n = strlen(bp) + 1; 95 bp += n; 96 buflen -= n; 97 } else 98 cp += dn_skip(cp) + QFIXEDSZ; 99 } else if (iquery) 100 return (NULL); 101 while (--ancount >= 0 && cp < eom) { 102 if ((n = dn_expand(answer, cp, bp, buflen)) < 0) 103 return (NULL); 104 cp += n; 105 type = getshort(cp); 106 cp += sizeof(u_short); 107 class = getshort(cp); 108 cp += sizeof(u_short) + sizeof(u_long); 109 n = getshort(cp); 110 cp += sizeof(u_short); 111 if (type == T_CNAME) { 112 cp += n; 113 if (ap >= &host_aliases[MAXALIASES-1]) 114 continue; 115 *ap++ = bp; 116 n = strlen(bp) + 1; 117 bp += n; 118 buflen -= n; 119 continue; 120 } 121 if (type != T_A || n != 4) { 122 if (_res.options & RES_DEBUG) 123 printf("unexpected answer type %d, size %d\n", 124 type, n); 125 continue; 126 } 127 if (!iquery) { 128 host.h_name = bp; 129 bp += strlen(bp) + 1; 130 } 131 *ap = NULL; 132 host.h_aliases = host_aliases; 133 host.h_addrtype = class == C_IN ? AF_INET : AF_UNSPEC; 134 if (bp + n >= &hostbuf[sizeof(hostbuf)]) { 135 if (_res.options & RES_DEBUG) 136 printf("size (%d) too big\n", n); 137 return (NULL); 138 } 139 bcopy(cp, host.h_addr = bp, host.h_length = n); 140 return (&host); 141 } 142 return (NULL); 143 } 144 145 struct hostent * 146 gethostbyname(name) 147 char *name; 148 { 149 int n; 150 #ifdef BOMBPROOFING 151 register struct hostent *hp; 152 #endif BOMBPROOFING 153 154 n = res_mkquery(QUERY, name, C_ANY, T_A, NULL, 0, NULL, 155 hostbuf, sizeof(hostbuf)); 156 if (n < 0) { 157 if (_res.options & RES_DEBUG) 158 printf("res_mkquery failed\n"); 159 return (NULL); 160 #ifndef BOMBPROOFING 161 } 162 return(getanswer(hostbuf, n, 0)); 163 #else 164 } else 165 hp = getanswer(hostbuf, n, 0); 166 if (n < 0 || (hp == NULL && _host_bombed)) 167 return (_oldgethostbyname(name)); 168 else 169 return (hp); 170 #endif BOMBPROOFING 171 } 172 173 struct hostent * 174 gethostbyaddr(addr, len, type) 175 char *addr; 176 int len, type; 177 { 178 int n; 179 #ifdef BOMBPROOFING 180 register struct hostent *hp; 181 #endif BOMBPROOFING 182 183 if (type != AF_INET) 184 return (NULL); 185 n = res_mkquery(IQUERY, NULL, C_IN, T_A, addr, len, NULL, 186 hostbuf, sizeof(hostbuf)); 187 if (n < 0) { 188 if (_res.options & RES_DEBUG) 189 printf("res_mkquery failed\n"); 190 return (NULL); 191 #ifndef BOMBPROOFING 192 } 193 return (getanswer(hostbuf, n, 1)); 194 #else 195 } else 196 hp = getanswer(hostbuf, n, 1); 197 if (n < 0 || (hp == NULL && _host_bombed)) 198 return (_oldgethostbyaddr(addr)); 199 else 200 return (hp); 201 #endif BOMBPROOFING 202 } 203 204 #ifdef BOMBPROOFING 205 static 206 struct hostent * 207 _oldgethostbyname(name) 208 register char *name; 209 { 210 register struct hostent *hp; 211 register char **cp; 212 datum key; 213 214 if ((_host_db == (DBM *)NULL) 215 && ((_host_db = dbm_open(_host_file, O_RDONLY)) == (DBM *)NULL)) { 216 sethostent(_host_stayopen); 217 while (hp = gethostent()) { 218 if (strcmp(hp->h_name, nam) == 0) 219 break; 220 for (cp = hp->h_aliases; cp != 0 && *cp != 0; cp++) 221 if (strcmp(*cp, nam) == 0) 222 goto found; 223 } 224 found: 225 if (!_host_stayopen) 226 endhostent(); 227 return (hp); 228 } 229 key.dptr = nam; 230 key.dsize = strlen(nam); 231 hp = fetchhost(key); 232 if (!_host_stayopen) { 233 dbm_close(_host_db); 234 _host_db = (DBM *)NULL; 235 } 236 return (hp); 237 } 238 239 240 static 241 struct hostent * 242 _oldgethostbyaddr(addr, len, type) 243 char *addr; 244 register int len, type; 245 { 246 247 register struct hostent *hp; 248 datum key; 249 250 if ((_host_db == (DBM *)NULL) 251 && ((_host_db = dbm_open(_host_file, O_RDONLY)) == (DBM *)NULL)) { 252 sethostent(_host_stayopen); 253 while (hp = gethostent()) { 254 if (hp->h_addrtype == type && hp->h_length == length 255 && bcmp(hp->h_addr, addr, length) == 0) 256 break; 257 } 258 if (!_host_stayopen) 259 endhostent(); 260 return (hp); 261 } 262 key.dptr = addr; 263 key.dsize = length; 264 hp = fetchhost(key); 265 if (!_host_stayopen) { 266 dbm_close(_host_db); 267 _host_db = (DBM *)NULL; 268 } 269 return (hp); 270 } 271 #endif BOMBPROOFING 272 273