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