1 /*
2 ** Copyright 1998 - 2011 Double Precision, Inc.
3 ** See COPYING for distribution information.
4 */
5
6 #include "config.h"
7 #include "rfc1035.h"
8 #include "spf.h"
9 #include <sys/types.h>
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <string.h>
13 #include <errno.h>
14 #include <arpa/inet.h>
15
16 #include "soxwrap/soxwrap.h"
17
18
setns(const char * p,struct rfc1035_res * res)19 static void setns(const char *p, struct rfc1035_res *res)
20 {
21 RFC1035_ADDR ia[4];
22 int i=0;
23 char *q=malloc(strlen(p)+1), *r;
24
25 strcpy(q, p);
26 for (r=q; (r=strtok(r, ", ")) != 0; r=0)
27 if (i < 4)
28 {
29 if (rfc1035_aton(r, &ia[i]) == 0)
30 {
31 ++i;
32 }
33 else
34 {
35 fprintf(stderr, "%s: invalid IP address\n",
36 r);
37 }
38 }
39 free(q);
40 rfc1035_init_ns(res, ia, i);
41 }
42
43 extern char rfc1035_spf_gettxt(const char *current_domain,
44 char *buf);
45 extern char rfc1035_spf_gettxt_n(const char *current_domain,
46 char **buf);
47
48
spflookup(const char * current_domain)49 static void spflookup(const char *current_domain)
50 {
51 char *buf;
52
53 switch (rfc1035_spf_gettxt_n(current_domain, &buf)) {
54 case SPF_NONE:
55 printf("none\n");
56 return;
57 case SPF_NEUTRAL:
58 printf("neutral\n");
59 return;
60 case SPF_PASS:
61 printf("pass: %s\n", buf);
62 return;
63 case SPF_FAIL:
64 printf("fail\n");
65 return;
66 case SPF_SOFTFAIL:
67 printf("softfail\n");
68 return;
69 case SPF_ERROR:
70 printf("error\n");
71 return;
72 default:
73 printf("unknown\n");
74 }
75 }
76
get_q_type_pass(const char * p,void (* cb)(unsigned char,void *),void * ptr)77 static int get_q_type_pass(const char *p,
78 void (*cb)(unsigned char, void *),
79 void *ptr)
80 {
81 char qbuf[strlen(p)+1];
82 char *q;
83
84 strcpy(qbuf, p);
85
86 for (q=qbuf; (q=strtok(q, ", \t\r\n")); q=0)
87 {
88 int n=rfc1035_type_strtoi(q);
89
90 if (n < 0)
91 return -1;
92
93 (*cb)(n, ptr);
94 }
95
96 return 0;
97 }
98
get_q_type_count(unsigned char c,void * ptr)99 static void get_q_type_count(unsigned char c, void *ptr)
100 {
101 ++*(size_t *)ptr;
102 }
103
get_q_type_save(unsigned char c,void * ptr)104 static void get_q_type_save(unsigned char c, void *ptr)
105 {
106 *(*(unsigned char **)ptr)++=c;
107 }
108
get_q_type(const char * p)109 static unsigned char *get_q_type(const char *p)
110 {
111 size_t n=0;
112 unsigned char *buf, *q;
113
114 errno=EINVAL;
115 if (get_q_type_pass(p, &get_q_type_count, &n) < 0)
116 return 0;
117
118 if ((buf=(unsigned char *)malloc(n+1)) == 0)
119 return 0;
120
121 q=buf;
122 get_q_type_pass(p, &get_q_type_save, &q);
123
124 *q=0;
125
126 return buf;
127 }
128
main(int argc,char ** argv)129 int main(int argc, char **argv)
130 {
131 struct rfc1035_res res;
132 struct rfc1035_reply *replyp;
133 int argn;
134 const char *q_name;
135 unsigned char *q_type;
136 int q_class;
137 int q_xflag=0;
138 int q_rflag=0;
139 char ptrbuf[RFC1035_MAXNAMESIZE+1];
140
141 rfc1035_init_resolv(&res);
142
143 argn=1;
144 while (argn < argc)
145 {
146 if (argv[argn][0] == '@')
147 {
148 setns(argv[argn]+1, &res);
149 ++argn;
150 continue;
151 }
152
153 if (strcmp(argv[argn], "-x") == 0)
154 {
155 q_xflag=1;
156 ++argn;
157 continue;
158 }
159 if (strcmp(argv[argn], "-r") == 0)
160 {
161 q_rflag=1;
162 ++argn;
163 continue;
164 }
165
166 if (strcmp(argv[argn], "-dnssec") == 0)
167 {
168 rfc1035_init_dnssec_enable(&res, 1);
169 ++argn;
170 continue;
171 }
172
173 if (strcmp(argv[argn], "-udpsize") == 0)
174 {
175 ++argn;
176
177 if (argn < argc)
178 {
179 rfc1035_init_edns_payload(&res,
180 atoi(argv[argn]));
181 ++argn;
182 }
183 continue;
184 }
185
186 break;
187 }
188
189 if (argn >= argc) exit(0);
190
191 q_name=argv[argn++];
192
193 if (q_xflag)
194 {
195 struct in_addr ia;
196 #if RFC1035_IPV6
197 struct in6_addr ia6;
198
199 if (inet_pton(AF_INET6, q_name, &ia6) > 0)
200 {
201 const char *sin6=(const char *)&ia6;
202 unsigned i;
203
204 ptrbuf[0]=0;
205
206 for (i=sizeof(struct in6_addr); i; )
207 {
208 char buf[10];
209
210 --i;
211 sprintf(buf, "%x.%x.",
212 (int)(unsigned char)(sin6[i] & 0x0F),
213 (int)(unsigned char)((sin6[i] >> 4)
214 & 0x0F));
215 strcat(ptrbuf, buf);
216 }
217 strcat(ptrbuf, "ip6.arpa");
218 q_name=ptrbuf;
219 }
220 else
221 #endif
222 if ( rfc1035_aton_ipv4(q_name, &ia) == 0)
223 {
224 char buf[RFC1035_MAXNAMESIZE];
225 unsigned char a=0,b=0,c=0,d=0;
226 const char *p=buf;
227
228 rfc1035_ntoa_ipv4(&ia, buf);
229
230 while (*p >= '0' && *p <= '9')
231 a= (int)a * 10 + (*p++ - '0');
232 if (*p) p++;
233 while (*p >= '0' && *p <= '9')
234 b= (int)b * 10 + (*p++ - '0');
235 if (*p) p++;
236 while (*p >= '0' && *p <= '9')
237 c= (int)c * 10 + (*p++ - '0');
238 if (*p) p++;
239 while (*p >= '0' && *p <= '9')
240 d= (int)d * 10 + (*p++ - '0');
241
242 sprintf(ptrbuf, "%d.%d.%d.%d.in-addr.arpa",
243 (int)d, (int)c, (int)b, (int)a);
244 q_name=ptrbuf;
245 }
246 }
247
248 if (q_rflag)
249 {
250 RFC1035_ADDR a;
251 int rc;
252
253 if (rfc1035_aton(q_name, &a) == 0)
254 {
255 rc=rfc1035_ptr(&res, &a,ptrbuf);
256 if (rc == 0)
257 {
258 printf("%s\n", ptrbuf);
259 exit(0);
260 }
261 }
262 else
263 {
264 RFC1035_ADDR *aptr;
265 unsigned alen;
266
267 rc=rfc1035_a(&res, q_name, &aptr, &alen);
268 if (rc == 0)
269 {
270 unsigned i;
271
272 for (i=0; i<alen; i++)
273 {
274 rfc1035_ntoa(&aptr[i], ptrbuf);
275 printf("%s\n", ptrbuf);
276 }
277 exit(0);
278 }
279 }
280 fprintf(stderr, "%s error.\n", errno == ENOENT ? "Hard":"Soft");
281 exit(1);
282 }
283
284 q_type=0;
285
286 if (argn < argc)
287 {
288 if (strcmp(argv[argn], "spf") == 0)
289 {
290 spflookup(q_name);
291 exit(0);
292 }
293 q_type=get_q_type(argv[argn]);
294 if (!q_type)
295 {
296 perror(argv[argn]);
297 exit(1);
298 }
299 argn++;
300 }
301
302 if (q_type == 0)
303 q_type=get_q_type(q_xflag ? "PTR":"ANY");
304
305 q_class= -1;
306 if (argn < argc)
307 q_class=rfc1035_class_strtoi(argv[argn]);
308 if (q_class < 0)
309 q_class=RFC1035_CLASS_IN;
310
311 if (q_type[0] && q_type[1])
312 {
313 char namebuf[RFC1035_MAXNAMESIZE+1];
314
315 namebuf[0]=0;
316 strncat(namebuf, q_name, RFC1035_MAXNAMESIZE);
317
318 if (rfc1035_resolve_cname_multiple(&res, namebuf,
319 q_type, q_class,
320 &replyp,
321 RFC1035_X_RANDOMIZE)
322 < 0)
323 replyp=0;
324 }
325 else
326 {
327 replyp=rfc1035_resolve(&res, RFC1035_OPCODE_QUERY,
328 q_name, q_type[0], q_class);
329 }
330 free(q_type);
331 if (!replyp)
332 {
333 perror(argv[0]);
334 exit(1);
335 }
336
337 if (q_type[0] && q_type[1])
338 {
339 struct rfc1035_reply *q;
340
341 for (q=replyp; q; q=q->next)
342 {
343 struct rfc1035_reply *s=q->next;
344
345 q->next=0;
346 rfc1035_dump(q, stdout);
347 q->next=s;
348 }
349 }
350 else
351 {
352 rfc1035_dump(replyp, stdout);
353 }
354 rfc1035_replyfree(replyp);
355 rfc1035_destroy_resolv(&res);
356 return (0);
357 }
358