1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25#define FOR_host
26#include "toys.h"
27#include <resolv.h>
28
29GLOBALS(
30 char *t;
31
32 char **nsname;
33 unsigned nslen;
34)
35
36static const struct rrt {
37 char *name, *msg;
38 int type;
39} rrt[] = { { "A", "has address", 1 }, { "NS", "name server", 2 },
40 { "CNAME", "is a nickname for", 5 }, { "SOA", "start of authority", 6 },
41 { "PTR", "domain name pointer", 12 }, { "MX", "mail is handled", 15 },
42 { "TXT", "descriptive text", 16 }, { "AAAA", "has address", 28 },
43 { "SRV", "mail is handled", 33 }
44};
45
46int xdn_expand(char *packet, char *endpkt, char *comp, char *expand, int elen)
47{
48 int i = dn_expand(packet, endpkt, comp, expand, elen);
49
50 if (i<1) error_exit("bad dn_expand");
51
52 return i;
53}
54
55
56static void get_nsname(char **pline, long len)
57{
58 char *line, *p;
59
60 if (!len) return;
61 line = *pline;
62 if (strstart(&line, "nameserver") && isspace(*line)) {
63 while (isspace(*line)) line++;
64 for (p = line; *p && !isspace(*p) && *p!='#'; p++);
65 if (p == line) return;
66 *p = 0;
67 if (!(TT.nslen&8))
68 TT.nsname = xrealloc(TT.nsname, (TT.nslen+8)*sizeof(void *));
69 TT.nsname[TT.nslen++] = xstrdup(line);
70 }
71}
72
73void host_main(void)
74{
75 int verbose = FLAG(a)||FLAG(v), type, abuf_len = 65536,
76 i, j, sec, rcode, qlen, alen QUIET, pllen = 0, t2len = 2048;
77 unsigned count, ttl;
78 char *abuf = xmalloc(abuf_len), *name = *toys.optargs, *p, *ss,
79 *t2 = toybuf+t2len;
80 struct addrinfo *ai;
81
82
83 if (!TT.t && FLAG(a)) TT.t = "255";
84 if (!getaddrinfo(name, 0,&(struct addrinfo){.ai_flags=AI_NUMERICHOST}, &ai)) {
85 name = toybuf;
86 if (ai->ai_family == AF_INET) {
87 p = (void *)&((struct sockaddr_in *)ai->ai_addr)->sin_addr;
88 sprintf(name, "%d.%d.%d.%d.in-addr.arpa", p[3], p[2], p[1], p[0]);
89 } else if (ai->ai_family == AF_INET6) {
90 p = (void *)&((struct sockaddr_in6 *)ai->ai_addr)->sin6_addr;
91 for (j = 0, i = 15; i>=0; i--)
92 j += sprintf(name+j, "%x.%x.", p[i]&15, p[i]>>4);
93 strcpy(name+j, "ip6.arpa");
94 }
95 if (!TT.t) TT.t = "12";
96 } else if (!TT.t) TT.t = "1";
97
98
99 if (TT.t[0]-'0'<10) type = atoi(TT.t);
100 else if (!strcasecmp(TT.t, "any") || strcmp(TT.t, "*")) type = 255;
101 else {
102 for (i = 0; i<ARRAY_LEN(rrt); i++) if (!strcasecmp(TT.t, rrt[i].name)) {
103 type = rrt[i].type;
104 break;
105 }
106 if (i == ARRAY_LEN(rrt)) error_exit("bad -t: %s", TT.t);
107 }
108 qlen = res_mkquery(0, name, 1, type, 0, 0, 0, t2, 280);
109 if (qlen<0) error_exit("bad NAME: %s", name);
110
111
112 if (toys.optargs[1]) TT.nsname = toys.optargs+1;
113 else do_lines(xopen("/etc/resolv.conf", O_RDONLY), '\n', get_nsname);
114 if (!TT.nsname) error_exit("No nameservers");
115
116
117 while (*TT.nsname) {
118 if (verbose) printf("Using domain server %s:\n", *TT.nsname);
119 ai = xgetaddrinfo(*TT.nsname, "53", 0, SOCK_DGRAM, 0, 0);
120 i = xsocket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
121 xconnect(i, ai->ai_addr, ai->ai_addrlen);
122 setsockopt(i, SOL_SOCKET, SO_RCVTIMEO, &(struct timeval){ .tv_sec = 5 },
123 sizeof(struct timeval));
124 send(i, t2, qlen, 0);
125 if (16 < (alen = recv(i, abuf, abuf_len, 0))) break;
126 if (!*++TT.nsname) error_exit("Host not found.");
127 close(i);
128 }
129
130
131 rcode = abuf[3]&7;
132 if (verbose) {
133 printf("rcode = %d, ancount = %d\n", rcode, (int)peek_be(abuf+6, 2));
134 if (!(abuf[2]&4)) puts("The following answer is not authoritative:");
135 }
136 if (rcode) error_exit("Host not found: %s",
137 (char *[]){ "Format error", "Server failure",
138 "Non-existant domain", "Not implemented", "Refused", ""}[rcode-1]);
139
140
141 p = abuf + 12;
142 for (sec = 0; sec<(2<<verbose); sec++) {
143 count = peek_be(abuf+4+2*sec, 2);
144 if (verbose && count>0 && sec>1)
145 puts(sec==2 ? "For authoritative answers, see:"
146 : "Additional information:");
147
148 for (; count--; p += pllen) {
149 p += xdn_expand(abuf, abuf+alen, p, toybuf, 4096-t2len);
150 if (alen-(p-abuf)<10) error_exit("tilt");
151 type = peek_be(p, 2);
152 p += 4;
153 if (!sec) continue;
154 ttl = peek_be(p, 4);
155 p += 4;
156 pllen = peek_be(p, 2);
157 p += 2;
158 if ((p-abuf)+pllen>alen) error_exit("tilt");
159
160 if (type==1 || type == 28)
161 inet_ntop(type==1 ? AF_INET : AF_INET6, p, t2, t2len);
162 else if (type==2 || type==5) xdn_expand(abuf, abuf+alen, p, t2, t2len);
163 else if (type==16) sprintf(t2, "\"%.*s\"", minof(pllen, t2len), p);
164 else if (type==6) {
165 ss = p+xdn_expand(abuf, abuf+alen, p, t2, t2len-1);
166 j = strlen(t2);
167 t2[j++] = ' ';
168 ss += xdn_expand(abuf, abuf+alen, ss, t2+j, t2len-j);
169 j += strlen(t2+j);
170 snprintf(t2+j, t2len-j, "(\n\t\t%u\t;serial (version)\n\t\t%u\t"
171 ";refresh period\n\t\t%u\t;retry interval\n\t\t%u\t;expire time\n"
172 "\t\t%u\t;default ttl\n\t\t)", (unsigned)peek_be(ss, 4),
173 (unsigned)peek_be(ss+4, 4), (unsigned)peek_be(ss+8, 4),
174 (unsigned)peek_be(ss+12, 4), (unsigned)peek_be(ss+16, 4));
175 } else if (type==15) {
176 j = peek_be(p, 2);
177 j = sprintf(t2, verbose ? "%d " : "(pri=%d) by ", j);
178 xdn_expand(abuf, abuf+alen, p+2, t2+j, t2len-j);
179 } else if (type==33) {
180 j = sprintf(t2, "%u %u %u ", (int)peek_be(p, 2), (int)peek_be(p+2, 2),
181 (int)peek_be(p+4, 2));
182 xdn_expand(abuf, abuf+alen, p+6, t2+j, t2len-j);
183 } else {
184 printf("%s unsupported RR type %u\n", toybuf, type);
185 continue;
186 }
187
188 for (i = 0; rrt[i].type != type; i++);
189 if (verbose) printf("%s\t%u\tIN %s\t%s\n", toybuf, ttl, rrt[i].name, t2);
190 else printf("%s %s %s\n", toybuf, rrt[type].msg, t2);
191 }
192 }
193
194 if (CFG_TOYBOX_FREE) free(abuf);
195 toys.exitval = rcode;
196}
197