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