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.7 (Berkeley) 09/14/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 28 29 static struct hostent * 30 getanswer(msg, msglen, iquery) 31 char *msg; 32 int msglen, iquery; 33 { 34 register HEADER *hp; 35 register char *cp; 36 register int n; 37 char answer[PACKETSZ]; 38 char *eom, *bp, **ap; 39 int type, class, ancount, buflen; 40 int haveanswer, getclass; 41 char **hap; 42 43 n = res_send(msg, msglen, answer, sizeof(answer)); 44 if (n < 0) { 45 #ifdef DEBUG 46 if (_res.options & RES_DEBUG) 47 printf("res_send failed\n"); 48 #endif 49 return (NULL); 50 } 51 eom = answer + n; 52 /* 53 * find first satisfactory answer 54 */ 55 hp = (HEADER *) answer; 56 ancount = ntohs(hp->ancount); 57 if (hp->rcode != NOERROR || ancount == 0) { 58 #ifdef DEBUG 59 if (_res.options & RES_DEBUG) 60 printf("rcode = %d, ancount=%d\n", hp->rcode, ancount); 61 #endif 62 return (NULL); 63 } 64 bp = hostbuf; 65 buflen = sizeof(hostbuf); 66 cp = answer + sizeof(HEADER); 67 if (hp->qdcount) { 68 if (iquery) { 69 if ((n = dn_expand(answer, cp, bp, buflen)) < 0) 70 return (NULL); 71 cp += n + QFIXEDSZ; 72 host.h_name = bp; 73 n = strlen(bp) + 1; 74 bp += n; 75 buflen -= n; 76 } else 77 cp += dn_skip(cp) + QFIXEDSZ; 78 } else if (iquery) 79 return (NULL); 80 ap = host_aliases; 81 host.h_aliases = host_aliases; 82 hap = h_addr_ptrs; 83 host.h_addr_list = h_addr_ptrs; 84 haveanswer = 0; 85 while (--ancount >= 0 && cp < eom) { 86 if ((n = dn_expand(answer, cp, bp, buflen)) < 0) 87 break; 88 cp += n; 89 type = getshort(cp); 90 cp += sizeof(u_short); 91 class = getshort(cp); 92 cp += sizeof(u_short) + sizeof(u_long); 93 n = getshort(cp); 94 cp += sizeof(u_short); 95 if (type == T_CNAME) { 96 cp += n; 97 if (ap >= &host_aliases[MAXALIASES-1]) 98 continue; 99 *ap++ = bp; 100 n = strlen(bp) + 1; 101 bp += n; 102 buflen -= n; 103 continue; 104 } 105 if (type != T_A) { 106 #ifdef DEBUG 107 if (_res.options & RES_DEBUG) 108 printf("unexpected answer type %d, size %d\n", 109 type, n); 110 #endif 111 cp += n; 112 continue; 113 } 114 if (haveanswer) { 115 if (n != host.h_length) { 116 cp += n; 117 continue; 118 } 119 if (class != getclass) { 120 cp += n; 121 continue; 122 } 123 } else { 124 host.h_length = n; 125 getclass = class; 126 host.h_addrtype = C_IN ? AF_INET : AF_UNSPEC; 127 if (!iquery) { 128 host.h_name = bp; 129 bp += strlen(bp) + 1; 130 } 131 } 132 if (bp + n >= &hostbuf[sizeof(hostbuf)]) { 133 #ifdef DEBUG 134 if (_res.options & RES_DEBUG) 135 printf("size (%d) too big\n", n); 136 #endif 137 break; 138 } 139 bcopy(cp, *hap++ = bp, n); 140 bp +=n; 141 cp += n; 142 haveanswer++; 143 } 144 if (haveanswer) { 145 *ap = NULL; 146 *hap = NULL; 147 return (&host); 148 } else 149 return (NULL); 150 } 151 152 struct hostent * 153 gethostbyname(name) 154 char *name; 155 { 156 int n; 157 char buf[BUFSIZ+1]; 158 159 n = res_mkquery(QUERY, name, C_ANY, T_A, (char *)NULL, 0, NULL, 160 buf, sizeof(buf)); 161 if (n < 0) { 162 #ifdef DEBUG 163 if (_res.options & RES_DEBUG) 164 printf("res_mkquery failed\n"); 165 #endif 166 return (NULL); 167 } 168 return(getanswer(buf, n, 0)); 169 } 170 171 struct hostent * 172 gethostbyaddr(addr, len, type) 173 char *addr; 174 int len, type; 175 { 176 int n; 177 char buf[BUFSIZ+1]; 178 179 if (type != AF_INET) 180 return (NULL); 181 n = res_mkquery(IQUERY, (char *)NULL, C_IN, T_A, addr, len, NULL, 182 buf, sizeof(buf)); 183 if (n < 0) { 184 #ifdef DEBUG 185 if (_res.options & RES_DEBUG) 186 printf("res_mkquery failed\n"); 187 #endif 188 return (NULL); 189 } 190 return(getanswer(buf, n, 1)); 191 } 192 193 194