1 /* 2 * Copyright (c) 1983 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.2 (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 static struct hostent host; 22 static char *host_aliases[MAXALIASES]; 23 static char hostbuf[BUFSIZ+1]; 24 25 static struct hostent * 26 getanswer(msg, msglen, iquery) 27 char *msg; 28 int msglen, iquery; 29 { 30 register HEADER *hp; 31 register char *cp; 32 register int n; 33 char answer[PACKETSZ]; 34 char *eom, *bp, **ap; 35 int type, class, ancount, buflen; 36 37 n = res_send(msg, msglen, answer, sizeof(answer)); 38 if (n < 0) { 39 if (_res.options & RES_DEBUG) 40 printf("res_send failed\n"); 41 return (NULL); 42 } 43 eom = answer + n; 44 /* 45 * find first satisfactory answer 46 */ 47 hp = (HEADER *) answer; 48 ancount = ntohs(hp->ancount); 49 if (hp->rcode != NOERROR || ancount == 0) { 50 if (_res.options & RES_DEBUG) 51 printf("rcode = %d, ancount=%d\n", hp->rcode, ancount); 52 return (NULL); 53 } 54 bp = hostbuf; 55 buflen = sizeof(hostbuf); 56 ap = host_aliases; 57 cp = answer + sizeof(HEADER); 58 if (hp->qdcount) { 59 if (iquery) { 60 if ((n = dn_expand(answer, cp, bp, buflen)) < 0) 61 return (NULL); 62 cp += n + QFIXEDSZ; 63 host.h_name = bp; 64 n = strlen(bp) + 1; 65 bp += n; 66 buflen -= n; 67 } else 68 cp += dn_skip(cp) + QFIXEDSZ; 69 } else if (iquery) 70 return (NULL); 71 while (--ancount >= 0 && cp < eom) { 72 if ((n = dn_expand(answer, cp, bp, buflen)) < 0) 73 return (NULL); 74 cp += n; 75 type = getshort(cp); 76 cp += sizeof(u_short); 77 class = getshort(cp); 78 cp += sizeof(u_short) + sizeof(u_long); 79 n = getshort(cp); 80 cp += sizeof(u_short); 81 if (type == T_CNAME) { 82 cp += n; 83 if (ap >= &host_aliases[MAXALIASES-1]) 84 continue; 85 *ap++ = bp; 86 n = strlen(bp) + 1; 87 bp += n; 88 buflen -= n; 89 continue; 90 } 91 if (type != T_A || n != 4) { 92 if (_res.options & RES_DEBUG) 93 printf("unexpected answer type %d, size %d\n", 94 type, n); 95 continue; 96 } 97 if (!iquery) { 98 host.h_name = bp; 99 bp += strlen(bp) + 1; 100 } 101 *ap = NULL; 102 host.h_aliases = host_aliases; 103 host.h_addrtype = class == C_IN ? AF_INET : AF_UNSPEC; 104 if (bp + n >= &hostbuf[sizeof(hostbuf)]) { 105 if (_res.options & RES_DEBUG) 106 printf("size (%d) too big\n", n); 107 return (NULL); 108 } 109 bcopy(cp, host.h_addr = bp, host.h_length = n); 110 return (&host); 111 } 112 return (NULL); 113 } 114 115 struct hostent * 116 gethostbyname(name) 117 char *name; 118 { 119 int n; 120 121 n = res_mkquery(QUERY, name, C_ANY, T_A, NULL, 0, NULL, 122 hostbuf, sizeof(hostbuf)); 123 if (n < 0) { 124 if (_res.options & RES_DEBUG) 125 printf("res_mkquery failed\n"); 126 return (NULL); 127 } 128 return (getanswer(hostbuf, n, 0)); 129 } 130 131 struct hostent * 132 gethostbyaddr(addr, len, type) 133 char *addr; 134 int len, type; 135 { 136 int n; 137 138 if (type != AF_INET) 139 return (NULL); 140 n = res_mkquery(IQUERY, NULL, C_IN, T_A, addr, len, NULL, 141 hostbuf, sizeof(hostbuf)); 142 if (n < 0) { 143 if (_res.options & RES_DEBUG) 144 printf("res_mkquery failed\n"); 145 return (NULL); 146 } 147 return (getanswer(hostbuf, n, 1)); 148 } 149