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