1 #line 982 "../../src/builtin/snarf.m4"
2 /* -*- buffer-read-only: t -*- vi: set ro:
3    THIS FILE IS GENERATED AUTOMATICALLY.  PLEASE DO NOT EDIT.
4 */
5 #line 982
6 #ifdef HAVE_CONFIG_H
7 #line 982
8 # include <config.h>
9 #line 982
10 #endif
11 #line 982
12 #include <sys/types.h>
13 #line 982
14 
15 #line 982
16 #include "mailfromd.h"
17 #line 982
18 #include "prog.h"
19 #line 982
20 #include "builtin.h"
21 #line 982
22 
23 #line 982
24 
25 #line 1022 "../../src/builtin/snarf.m4"
26 
27 /* End of snarf.m4 */
28 #line 1 "dns.bi"
29 /* This file is part of Mailfromd.             -*- c -*-
30    Copyright (C) 2006-2021 Sergey Poznyakoff
31 
32    This program is free software; you can redistribute it and/or modify
33    it under the terms of the GNU General Public License as published by
34    the Free Software Foundation; either version 3, or (at your option)
35    any later version.
36 
37    This program is distributed in the hope that it will be useful,
38    but WITHOUT ANY WARRANTY; without even the implied warranty of
39    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
40    GNU General Public License for more details.
41 
42    You should have received a copy of the GNU General Public License
43    along with this program.  If not, see <http://www.gnu.org/licenses/>. */
44 
45 
46 
47 #include <sys/socket.h>
48 #include <netinet/in.h>
49 #include <netdb.h>
50 #include <arpa/inet.h>
51 #include <limits.h>
52 #include "srvcfg.h"
53 #include "global.h"
54 
55 void
56 #line 27
bi_primitive_hostname(eval_environ_t env)57 bi_primitive_hostname(eval_environ_t env)
58 #line 27
59 
60 #line 27
61 
62 #line 27 "dns.bi"
63 {
64 #line 27
65 
66 #line 27
67 
68 #line 27
69 
70 #line 27
71 char * MFL_DATASEG string;
72 #line 27
73 
74 #line 27
75 get_string_arg(env, 0, &string);
76 #line 27
77 
78 #line 27
79 
80 #line 27
81         adjust_stack(env, 1);
82 #line 27
83 
84 #line 27
85 
86 #line 27
87 	if (builtin_module_trace(BUILTIN_IDX_dns))
88 #line 27
89 		prog_trace(env, "primitive_hostname %s",string);;
90 #line 27
91 
92 {
93 	char *hbuf;
94 	mf_status stat;
95 
96 	stat = resolve_ipstr(string, &hbuf);
97 		if (!(stat == mf_success))
98 #line 33
99 		(
100 #line 33
101 	env_throw_bi(env, mf_status_to_exception(stat), "primitive_hostname", _("cannot resolve IP %s"),string)
102 #line 33
103 )
104 #line 36
105 ;
106 
107 	pushs(env, hbuf);
108 	free(hbuf);
109 }
110 
111 #line 41
112         env_function_cleanup_flush(env, NULL);
113 #line 41
114 	return;
115 #line 41
116 }
117 
118 void
119 #line 43
bi_primitive_resolve(eval_environ_t env)120 bi_primitive_resolve(eval_environ_t env)
121 #line 43
122 
123 #line 43
124 
125 #line 43 "dns.bi"
126 {
127 #line 43
128 
129 #line 43
130 
131 #line 43
132 long __bi_argcnt;
133 #line 43
134 char * MFL_DATASEG string;
135 #line 43
136         char * MFL_DATASEG domain;
137 #line 43
138 
139 #line 43
140 get_string_arg(env, 1, &string);
141 #line 43
142         get_string_arg(env, 2, &domain);
143 #line 43
144 
145 #line 43
146 get_numeric_arg(env, 0, &__bi_argcnt);
147 #line 43
148         adjust_stack(env, __bi_argcnt + 1);
149 #line 43
150 
151 #line 43
152 
153 #line 43
154 	if (builtin_module_trace(BUILTIN_IDX_dns))
155 #line 43
156 		prog_trace(env, "primitive_resolve %s %s",string, ((__bi_argcnt > 1) ? domain : ""));;
157 #line 43
158 
159 {
160 	char *ipstr;
161 	mf_status stat;
162 
163 	if (((__bi_argcnt > 1) ? domain : "")[0]) {
164 		stat = resolve_ipstr_domain(string, domain, &ipstr);
165 			if (!(stat == mf_success))
166 #line 50
167 		(
168 #line 50
169 	env_throw_bi(env, mf_status_to_exception(stat), "primitive_resolve", _("cannot resolve %s.%s"),string,domain)
170 #line 50
171 )
172 #line 52
173 ;
174 	} else {
175 		stat = resolve_hostname(string, &ipstr);
176 			if (!(stat == mf_success))
177 #line 55
178 		(
179 #line 55
180 	env_throw_bi(env, mf_status_to_exception(stat), "primitive_resolve", _("cannot resolve %s"),string)
181 #line 55
182 )
183 #line 57
184 ;
185 	}
186 	pushs(env, ipstr);
187 	free(ipstr);
188 }
189 
190 #line 62
191         env_function_cleanup_flush(env, NULL);
192 #line 62
193 	return;
194 #line 62
195 }
196 
197 void
198 #line 64
bi_primitive_hasmx(eval_environ_t env)199 bi_primitive_hasmx(eval_environ_t env)
200 #line 64
201 
202 #line 64
203 
204 #line 64 "dns.bi"
205 {
206 #line 64
207 
208 #line 64
209 
210 #line 64
211 
212 #line 64
213 char *  string;
214 #line 64
215 
216 #line 64
217 get_string_arg(env, 0, &string);
218 #line 64
219 
220 #line 64
221 
222 #line 64
223         adjust_stack(env, 1);
224 #line 64
225 
226 #line 64
227 
228 #line 64
229 	if (builtin_module_trace(BUILTIN_IDX_dns))
230 #line 64
231 		prog_trace(env, "primitive_hasmx %s",string);;
232 #line 64
233 
234 {
235 	struct dns_reply repl;
236 	mf_status mxstat;
237 
238 	mxstat = dns_to_mf_status(mx_lookup(string, 0, &repl));
239 
240 		if (!(mxstat == mf_success || mxstat == mf_not_found))
241 #line 71
242 		(
243 #line 71
244 	env_throw_bi(env, mf_status_to_exception(mxstat), "primitive_hasmx", _("cannot get MX records for %s"),string)
245 #line 71
246 )
247 #line 74
248 ;
249 	dns_reply_free(&repl);
250 	if (mxstat == mf_success) {
251 
252 #line 77
253 do {
254 #line 77
255   push(env, (STKVAL)(mft_number)(1));
256 #line 77
257   goto endlab;
258 #line 77
259 } while (0);
260 	}
261 
262 #line 79
263 do {
264 #line 79
265   push(env, (STKVAL)(mft_number)(0));
266 #line 79
267   goto endlab;
268 #line 79
269 } while (0);
270 }
271 endlab:
272 #line 81
273         env_function_cleanup_flush(env, NULL);
274 #line 81
275 	return;
276 #line 81
277 }
278 
279 static dns_status
resolve_host(const char * string,struct dns_reply * reply)280 resolve_host(const char *string, struct dns_reply *reply)
281 {
282 	struct in_addr addr;
283 
284 	if (inet_aton(string, &addr)) {
285 		dns_reply_init(reply, dns_reply_ip, 1);
286 		reply->data.ip[0] = addr.s_addr;
287 		return dns_success;
288 	}
289 	return a_lookup(string, reply);
290 }
291 
292 static int
dns_replies_intersect(struct dns_reply const * a,struct dns_reply const * b)293 dns_replies_intersect(struct dns_reply const *a, struct dns_reply const *b)
294 {
295 	int i, j;
296 
297 	if (a->type == b->type && a->type == dns_reply_ip) {
298 		for (i = 0; i < a->count; i++)
299 			for (j = 0; j < b->count; j++)
300 				if (a->data.ip[i] == b->data.ip[j])
301 					return 1;
302 	}
303 	return 0;
304 }
305 
306 void
307 #line 110
bi_primitive_ismx(eval_environ_t env)308 bi_primitive_ismx(eval_environ_t env)
309 #line 110
310 
311 #line 110
312 
313 #line 110 "dns.bi"
314 {
315 #line 110
316 
317 #line 110
318 
319 #line 110
320 
321 #line 110
322 char *  domain;
323 #line 110
324         char *  ipstr;
325 #line 110
326 
327 #line 110
328 get_string_arg(env, 0, &domain);
329 #line 110
330         get_string_arg(env, 1, &ipstr);
331 #line 110
332 
333 #line 110
334 
335 #line 110
336         adjust_stack(env, 2);
337 #line 110
338 
339 #line 110
340 
341 #line 110
342 	if (builtin_module_trace(BUILTIN_IDX_dns))
343 #line 110
344 		prog_trace(env, "primitive_ismx %s %s",domain, ipstr);;
345 #line 110
346 
347 {
348 	struct dns_reply areply, mxreply;
349 	dns_status status;
350 	int rc = 0;
351 
352 	status = resolve_host(ipstr, &areply);
353 		if (!(status == dns_success))
354 #line 117
355 		(
356 #line 117
357 	env_throw_bi(env, mf_status_to_exception(dns_to_mf_status(status)), "primitive_ismx", _("cannot resolve host name %s"),ipstr)
358 #line 117
359 )
360 #line 119
361 ;
362 	status = mx_lookup(domain, 1, &mxreply);
363 	if (status != dns_success) {
364 		dns_reply_free(&areply);
365 		(
366 #line 123
367 	env_throw_bi(env, mf_status_to_exception(dns_to_mf_status(status)), "primitive_ismx", _("cannot get MXs for %s"),domain)
368 #line 123
369 );
370 #line 125
371 	}
372 	rc = dns_replies_intersect(&areply, &mxreply);
373 	dns_reply_free(&areply);
374 	dns_reply_free(&mxreply);
375 
376 #line 129
377 do {
378 #line 129
379   push(env, (STKVAL)(mft_number)(rc));
380 #line 129
381   goto endlab;
382 #line 129
383 } while (0);
384 }
385 endlab:
386 #line 131
387         env_function_cleanup_flush(env, NULL);
388 #line 131
389 	return;
390 #line 131
391 }
392 
393 void
394 #line 133
bi_relayed(eval_environ_t env)395 bi_relayed(eval_environ_t env)
396 #line 133
397 
398 #line 133
399 
400 #line 133 "dns.bi"
401 {
402 #line 133
403 
404 #line 133
405 
406 #line 133
407 
408 #line 133
409 char *  s;
410 #line 133
411 
412 #line 133
413 get_string_arg(env, 0, &s);
414 #line 133
415 
416 #line 133
417 
418 #line 133
419         adjust_stack(env, 1);
420 #line 133
421 
422 #line 133
423 
424 #line 133
425 	if (builtin_module_trace(BUILTIN_IDX_dns))
426 #line 133
427 		prog_trace(env, "relayed %s",s);;
428 #line 133
429 
430 {
431 
432 #line 135
433 do {
434 #line 135
435   push(env, (STKVAL)(mft_number)(relayed_domain_p(s)));
436 #line 135
437   goto endlab;
438 #line 135
439 } while (0);
440 }
441 endlab:
442 #line 137
443         env_function_cleanup_flush(env, NULL);
444 #line 137
445 	return;
446 #line 137
447 }
448 
449 void
450 #line 139
bi_ptr_validate(eval_environ_t env)451 bi_ptr_validate(eval_environ_t env)
452 #line 139
453 
454 #line 139
455 
456 #line 139 "dns.bi"
457 {
458 #line 139
459 
460 #line 139
461 
462 #line 139
463 
464 #line 139
465 char *  s;
466 #line 139
467 
468 #line 139
469 get_string_arg(env, 0, &s);
470 #line 139
471 
472 #line 139
473 
474 #line 139
475         adjust_stack(env, 1);
476 #line 139
477 
478 #line 139
479 
480 #line 139
481 	if (builtin_module_trace(BUILTIN_IDX_dns))
482 #line 139
483 		prog_trace(env, "ptr_validate %s",s);;
484 #line 139
485 
486 {
487 	int rc, res;
488 	switch (rc = ptr_validate(s, NULL)) {
489 	case dns_success:
490 		res = 1;
491 		break;
492 	case dns_not_found:
493 		res = 0;
494 		break;
495 	default:
496 		(
497 #line 150
498 	env_throw_bi(env, mf_status_to_exception(dns_to_mf_status(rc)), "ptr_validate", _("failed to get PTR record for %s"),s)
499 #line 150
500 );
501 #line 152
502 	}
503 
504 #line 153
505 do {
506 #line 153
507   push(env, (STKVAL)(mft_number)(res));
508 #line 153
509   goto endlab;
510 #line 153
511 } while (0);
512 }
513 endlab:
514 #line 155
515         env_function_cleanup_flush(env, NULL);
516 #line 155
517 	return;
518 #line 155
519 }
520 
521 void
522 #line 157
bi_primitive_hasns(eval_environ_t env)523 bi_primitive_hasns(eval_environ_t env)
524 #line 157
525 
526 #line 157
527 
528 #line 157 "dns.bi"
529 {
530 #line 157
531 
532 #line 157
533 
534 #line 157
535 
536 #line 157
537 char *  dom;
538 #line 157
539 
540 #line 157
541 get_string_arg(env, 0, &dom);
542 #line 157
543 
544 #line 157
545 
546 #line 157
547         adjust_stack(env, 1);
548 #line 157
549 
550 #line 157
551 
552 #line 157
553 	if (builtin_module_trace(BUILTIN_IDX_dns))
554 #line 157
555 		prog_trace(env, "primitive_hasns %s",dom);;
556 #line 157
557 
558 {
559 	struct dns_reply repl;
560 	mf_status stat = dns_to_mf_status(ns_lookup(dom, 0, &repl));
561 		if (!(stat == mf_success || stat == mf_not_found))
562 #line 161
563 		(
564 #line 161
565 	env_throw_bi(env, mf_status_to_exception(stat), "primitive_hasns", _("cannot get NS records for %s"),dom)
566 #line 161
567 )
568 #line 164
569 ;
570 	dns_reply_free(&repl);
571 	if (stat == mf_success) {
572 
573 #line 167
574 do {
575 #line 167
576   push(env, (STKVAL)(mft_number)(1));
577 #line 167
578   goto endlab;
579 #line 167
580 } while (0);
581 	}
582 
583 #line 169
584 do {
585 #line 169
586   push(env, (STKVAL)(mft_number)(0));
587 #line 169
588   goto endlab;
589 #line 169
590 } while (0);
591 }
592 endlab:
593 #line 171
594         env_function_cleanup_flush(env, NULL);
595 #line 171
596 	return;
597 #line 171
598 }
599 
600 static int
cmp_ip(void const * a,void const * b)601 cmp_ip(void const *a, void const *b)
602 {
603 	GACOPYZ_UINT32_T ipa = ntohl(*(GACOPYZ_UINT32_T const *)a);
604 	GACOPYZ_UINT32_T ipb = ntohl(*(GACOPYZ_UINT32_T const *)b);
605 	if (ipa < ipb)
606 		return -1;
607 	if (ipa > ipb)
608 		return 1;
609 	return 0;
610 }
611 
612 static int
cmp_str(void const * a,void const * b)613 cmp_str(void const *a, void const *b)
614 {
615 	char * const *stra = a;
616 	char * const *strb = b;
617 	return strcmp(*stra, *strb);
618 }
619 
620 static int
cmp_hostname(const void * a,const void * b)621 cmp_hostname(const void *a, const void *b)
622 {
623 	return strcasecmp(*(const char**) a, *(const char**) b);
624 }
625 
626 typedef long DNS_REPLY_COUNT;
627 #define DNS_REPLY_MAX LONG_MAX
628 
629 struct dns_reply_storage {
630 	DNS_REPLY_COUNT reply_count;
631 	size_t reply_max;
632 	struct dns_reply *reply_tab;
633 };
634 
635 static inline int
dns_reply_entry_unused(struct dns_reply_storage * rs,DNS_REPLY_COUNT n)636 dns_reply_entry_unused(struct dns_reply_storage *rs, DNS_REPLY_COUNT n)
637 {
638 	return n == -1 || rs->reply_tab[n].type == -1;
639 }
640 
641 static inline void
dns_reply_entry_release(struct dns_reply_storage * rs,DNS_REPLY_COUNT n)642 dns_reply_entry_release(struct dns_reply_storage *rs, DNS_REPLY_COUNT n)
643 {
644 	rs->reply_tab[n].type = -1;
645 }
646 
647 static inline struct dns_reply *
dns_reply_entry_locate(struct dns_reply_storage * rs,DNS_REPLY_COUNT n)648 dns_reply_entry_locate(struct dns_reply_storage *rs, DNS_REPLY_COUNT n)
649 {
650 	if (n < 0 || n >= rs->reply_count || dns_reply_entry_unused(rs, n))
651 		return NULL;
652 	return &rs->reply_tab[n];
653 }
654 
655 static void *
dns_reply_storage_alloc(void)656 dns_reply_storage_alloc(void)
657 {
658 	struct dns_reply_storage *rs = mu_alloc(sizeof(*rs));
659 	rs->reply_count = 0;
660 	rs->reply_max = 0;
661 	rs->reply_tab = NULL;
662 	return rs;
663 }
664 
665 static void
dns_reply_storage_destroy(void * data)666 dns_reply_storage_destroy(void *data)
667 {
668 	struct dns_reply_storage *rs = data;
669 	DNS_REPLY_COUNT i;
670 
671 	for (i = 0; i < rs->reply_count; i++) {
672 		if (!dns_reply_entry_unused(rs, i)) {
673 			dns_reply_free(&rs->reply_tab[i]);
674 			dns_reply_entry_release(rs, i);
675 		}
676 	}
677 	free(rs->reply_tab);
678 	free(rs);
679 }
680 
681 
682 #line 254
683 
684 #line 254
685 static int DNS_id;
686 #line 254 "dns.bi"
687 
688 
689 static inline DNS_REPLY_COUNT
dns_reply_entry_alloc(struct dns_reply_storage * rs,struct dns_reply ** return_reply)690 dns_reply_entry_alloc(struct dns_reply_storage *rs,
691 		      struct dns_reply **return_reply)
692 {
693 	DNS_REPLY_COUNT i;
694 
695 	for (i = 0; i < rs->reply_count; i++) {
696 		if (dns_reply_entry_unused(rs, i)) {
697 			*return_reply = &rs->reply_tab[i];
698 			return i;
699 		}
700 	}
701 	if (rs->reply_count == DNS_REPLY_MAX)
702 		return -1;
703 	if (rs->reply_count == rs->reply_max) {
704 		size_t n = rs->reply_max;
705 		rs->reply_tab = mu_2nrealloc(rs->reply_tab, &rs->reply_max,
706 					     sizeof(rs->reply_tab[0]));
707 		for (; n < rs->reply_max; n++)
708 			dns_reply_entry_release(rs, n);
709 	}
710 	*return_reply = &rs->reply_tab[rs->reply_count];
711 	return rs->reply_count++;
712 }
713 
714 void
715 #line 281
bi_dns_reply_release(eval_environ_t env)716 bi_dns_reply_release(eval_environ_t env)
717 #line 281
718 
719 #line 281
720 
721 #line 281 "dns.bi"
722 {
723 #line 281
724 
725 #line 281
726 
727 #line 281
728 
729 #line 281
730 long  n;
731 #line 281
732 
733 #line 281
734 get_numeric_arg(env, 0, &n);
735 #line 281
736 
737 #line 281
738 
739 #line 281
740         adjust_stack(env, 1);
741 #line 281
742 
743 #line 281
744 
745 #line 281
746 	if (builtin_module_trace(BUILTIN_IDX_dns))
747 #line 281
748 		prog_trace(env, "dns_reply_release %lu",n);;
749 #line 281
750 
751 {
752 	struct dns_reply_storage *repl = env_get_builtin_priv(env,DNS_id);
753 	if (!dns_reply_entry_unused(repl, n)) {
754 		dns_reply_free(&repl->reply_tab[n]);
755 		dns_reply_entry_release(repl, n);
756 	}
757 }
758 
759 #line 289
760         env_function_cleanup_flush(env, NULL);
761 #line 289
762 	return;
763 #line 289
764 }
765 
766 void
767 #line 291
bi_dns_reply_count(eval_environ_t env)768 bi_dns_reply_count(eval_environ_t env)
769 #line 291
770 
771 #line 291
772 
773 #line 291 "dns.bi"
774 {
775 #line 291
776 
777 #line 291
778 
779 #line 291
780 
781 #line 291
782 long  n;
783 #line 291
784 
785 #line 291
786 get_numeric_arg(env, 0, &n);
787 #line 291
788 
789 #line 291
790 
791 #line 291
792         adjust_stack(env, 1);
793 #line 291
794 
795 #line 291
796 
797 #line 291
798 	if (builtin_module_trace(BUILTIN_IDX_dns))
799 #line 291
800 		prog_trace(env, "dns_reply_count %lu",n);;
801 #line 291
802 
803 {
804 	struct dns_reply_storage *rs = env_get_builtin_priv(env,DNS_id);
805 	struct dns_reply *reply;
806 
807 	if (n == -1)
808 
809 #line 297
810 do {
811 #line 297
812   push(env, (STKVAL)(mft_number)(0));
813 #line 297
814   goto endlab;
815 #line 297
816 } while (0);
817 	if (n < 0)
818 		(
819 #line 299
820 	env_throw_bi(env, mfe_failure, "dns_reply_count", _("invalid DNS reply number: %ld"),n)
821 #line 299
822 );
823 #line 301
824 	reply = dns_reply_entry_locate(rs, n);
825 	if (!reply)
826 		(
827 #line 303
828 	env_throw_bi(env, mfe_failure, "dns_reply_count", _("no such reply: %ld"),n)
829 #line 303
830 );
831 #line 305
832 
833 #line 305
834 do {
835 #line 305
836   push(env, (STKVAL)(mft_number)(reply->count));
837 #line 305
838   goto endlab;
839 #line 305
840 } while (0);
841 }
842 endlab:
843 #line 307
844         env_function_cleanup_flush(env, NULL);
845 #line 307
846 	return;
847 #line 307
848 }
849 
850 void
851 #line 309
bi_dns_reply_string(eval_environ_t env)852 bi_dns_reply_string(eval_environ_t env)
853 #line 309
854 
855 #line 309
856 
857 #line 309 "dns.bi"
858 {
859 #line 309
860 
861 #line 309
862 
863 #line 309
864 
865 #line 309
866 long  n;
867 #line 309
868         long  i;
869 #line 309
870 
871 #line 309
872 get_numeric_arg(env, 0, &n);
873 #line 309
874         get_numeric_arg(env, 1, &i);
875 #line 309
876 
877 #line 309
878 
879 #line 309
880         adjust_stack(env, 2);
881 #line 309
882 
883 #line 309
884 
885 #line 309
886 	if (builtin_module_trace(BUILTIN_IDX_dns))
887 #line 309
888 		prog_trace(env, "dns_reply_string %lu %lu",n, i);;
889 #line 309
890 
891 {
892 	struct dns_reply_storage *rs = env_get_builtin_priv(env,DNS_id);
893 	struct dns_reply *reply = dns_reply_entry_locate(rs, n);
894 	if (!reply)
895 		(
896 #line 314
897 	env_throw_bi(env, mfe_failure, "dns_reply_string", _("no such reply: %ld"),n)
898 #line 314
899 );
900 #line 316
901 	if (i < 0 || i >= reply->count)
902 		(
903 #line 317
904 	env_throw_bi(env, mfe_range, "dns_reply_string", _("index out of range: %ld"),i)
905 #line 317
906 );
907 #line 319
908 	if (reply->type == dns_reply_ip) {
909 		struct in_addr addr;
910 		addr.s_addr = reply->data.ip[i];
911 
912 #line 322
913 do {
914 #line 322
915   pushs(env, inet_ntoa(addr));
916 #line 322
917   goto endlab;
918 #line 322
919 } while (0);
920 	}
921 
922 #line 324
923 do {
924 #line 324
925   pushs(env, reply->data.str[i]);
926 #line 324
927   goto endlab;
928 #line 324
929 } while (0);
930 }
931 endlab:
932 #line 326
933         env_function_cleanup_flush(env, NULL);
934 #line 326
935 	return;
936 #line 326
937 }
938 
939 void
940 #line 328
bi_dns_reply_ip(eval_environ_t env)941 bi_dns_reply_ip(eval_environ_t env)
942 #line 328
943 
944 #line 328
945 
946 #line 328 "dns.bi"
947 {
948 #line 328
949 
950 #line 328
951 
952 #line 328
953 
954 #line 328
955 long  n;
956 #line 328
957         long  i;
958 #line 328
959 
960 #line 328
961 get_numeric_arg(env, 0, &n);
962 #line 328
963         get_numeric_arg(env, 1, &i);
964 #line 328
965 
966 #line 328
967 
968 #line 328
969         adjust_stack(env, 2);
970 #line 328
971 
972 #line 328
973 
974 #line 328
975 	if (builtin_module_trace(BUILTIN_IDX_dns))
976 #line 328
977 		prog_trace(env, "dns_reply_ip %lu %lu",n, i);;
978 #line 328
979 
980 {
981 	struct dns_reply_storage *rs = env_get_builtin_priv(env,DNS_id);
982 	struct dns_reply *reply = dns_reply_entry_locate(rs, n);
983 	if (!reply)
984 		(
985 #line 333
986 	env_throw_bi(env, mfe_failure, "dns_reply_ip", _("no such reply: %ld"),n)
987 #line 333
988 );
989 #line 335
990 	if (i < 0 || i >= reply->count)
991 		(
992 #line 336
993 	env_throw_bi(env, mfe_range, "dns_reply_ip", _("index out of range: %ld"),i)
994 #line 336
995 );
996 #line 338
997 	if (reply->type == dns_reply_str) {
998 		(
999 #line 339
1000 	env_throw_bi(env, mfe_failure, "dns_reply_ip", _("can't use dns_reply_ip on string replies"))
1001 #line 339
1002 );
1003 #line 341
1004 	}
1005 
1006 #line 342
1007 do {
1008 #line 342
1009   pushs(env, reply->data.str[i]);
1010 #line 342
1011   goto endlab;
1012 #line 342
1013 } while (0);
1014 }
1015 endlab:
1016 #line 344
1017         env_function_cleanup_flush(env, NULL);
1018 #line 344
1019 	return;
1020 #line 344
1021 }
1022 
1023 enum {
1024 	DNS_TYPE_A = 1,
1025 	DNS_TYPE_NS = 2,
1026 	DNS_TYPE_PTR = 12,
1027 	DNS_TYPE_MX = 15,
1028 	DNS_TYPE_TXT = 16,
1029 };
1030 
1031 static char *dns_type_name[] = {
1032 	[DNS_TYPE_A] = "a",
1033 	[DNS_TYPE_NS] = "ns",
1034 	[DNS_TYPE_PTR] = "ptr",
1035 	[DNS_TYPE_MX] = "mx",
1036 	[DNS_TYPE_TXT] = "txt"
1037 };
1038 
1039 void
1040 #line 362
bi_dns_query(eval_environ_t env)1041 bi_dns_query(eval_environ_t env)
1042 #line 362
1043 
1044 #line 362
1045 
1046 #line 362 "dns.bi"
1047 {
1048 #line 362
1049 
1050 #line 362
1051 
1052 #line 362
1053 long __bi_argcnt;
1054 #line 362
1055 long  type;
1056 #line 362
1057         char *  domain;
1058 #line 362
1059         long  sort;
1060 #line 362
1061         long  resolve;
1062 #line 362
1063 
1064 #line 362
1065 get_numeric_arg(env, 1, &type);
1066 #line 362
1067         get_string_arg(env, 2, &domain);
1068 #line 362
1069         get_numeric_arg(env, 3, &sort);
1070 #line 362
1071         get_numeric_arg(env, 4, &resolve);
1072 #line 362
1073 
1074 #line 362
1075 get_numeric_arg(env, 0, &__bi_argcnt);
1076 #line 362
1077         adjust_stack(env, __bi_argcnt + 1);
1078 #line 362
1079 
1080 #line 362
1081 
1082 #line 362
1083 	if (builtin_module_trace(BUILTIN_IDX_dns))
1084 #line 362
1085 		prog_trace(env, "dns_query %lu %s %lu %lu",type, domain, ((__bi_argcnt > 2) ? sort : 0), ((__bi_argcnt > 3) ? resolve : 0));;
1086 
1087 {
1088 	struct dns_reply_storage *rs = env_get_builtin_priv(env,DNS_id);
1089 	dns_status dnsstat;
1090 	mf_status stat;
1091 	DNS_REPLY_COUNT ret;
1092 	struct dns_reply *reply;
1093 	int (*cmpfun)(const void *, const void *) = NULL;
1094 	struct in_addr addr;
1095 
1096 	ret = dns_reply_entry_alloc(rs, &reply);
1097 		if (!(ret >= 0))
1098 #line 374
1099 		(
1100 #line 374
1101 	env_throw_bi(env, mfe_failure, "dns_query", _("DNS reply table full"))
1102 #line 374
1103 )
1104 #line 376
1105 ;
1106 
1107 	switch (type) {
1108 	case DNS_TYPE_PTR:
1109 			if (!(inet_aton(domain, &addr)))
1110 #line 380
1111 		(
1112 #line 380
1113 	env_throw_bi(env, mfe_invip, "dns_query", _("invalid IP: %s"),domain)
1114 #line 380
1115 )
1116 #line 382
1117 ;
1118 		dnsstat = ptr_lookup(addr, reply);
1119 		cmpfun = cmp_hostname;
1120 		break;
1121 
1122 	case DNS_TYPE_A:
1123 		dnsstat = resolve_host(domain, reply);
1124 		break;
1125 
1126 	case DNS_TYPE_TXT:
1127 		dnsstat = txt_lookup(domain, reply);
1128 		break;
1129 
1130 	case DNS_TYPE_MX:
1131 		dnsstat = mx_lookup(domain, ((__bi_argcnt > 3) ? resolve : 0), reply);
1132 		break;
1133 
1134 	case DNS_TYPE_NS:
1135 		dnsstat = ns_lookup(domain, ((__bi_argcnt > 3) ? resolve : 0), reply);
1136 		break;
1137 
1138 	default:
1139 		dns_reply_entry_release(rs, ret);
1140 		(
1141 #line 405
1142 	env_throw_bi(env, mfe_failure, "dns_query", _("unsupported type: %ld"),type)
1143 #line 405
1144 );
1145 #line 407
1146 	}
1147 
1148 	stat = dns_to_mf_status(dnsstat);
1149 
1150 	if (!mf_resolved(stat)) {
1151 		dns_reply_entry_release(rs, ret);
1152 		(
1153 #line 413
1154 	env_throw_bi(env, mf_status_to_exception(stat), "dns_query", _("cannot get %s records for %s"),dns_type_name[type],domain)
1155 #line 413
1156 );
1157 #line 416
1158 	}
1159 	if (stat == mf_not_found) {
1160 		dns_reply_entry_release(rs, ret);
1161 
1162 #line 419
1163 do {
1164 #line 419
1165   push(env, (STKVAL)(mft_number)(-1));
1166 #line 419
1167   goto endlab;
1168 #line 419
1169 } while (0);
1170 	}
1171 	if (sort) {
1172 		size_t entry_size;
1173 
1174 		if (!cmpfun) {
1175 			if (reply->type == dns_reply_str) {
1176 				cmpfun = cmp_str;
1177 			} else {
1178 				cmpfun = cmp_ip;
1179 			}
1180 		}
1181 		if (reply->type == dns_reply_str) {
1182 			entry_size = sizeof(reply->data.str[0]);
1183 		} else {
1184 			entry_size = sizeof(reply->data.ip[0]);
1185 		}
1186 
1187 		qsort(reply->data.ptr, reply->count, entry_size, cmpfun);
1188 	}
1189 
1190 #line 439
1191 do {
1192 #line 439
1193   push(env, (STKVAL)(mft_number)(ret));
1194 #line 439
1195   goto endlab;
1196 #line 439
1197 } while (0);
1198 }
1199 endlab:
1200 #line 441
1201         env_function_cleanup_flush(env, NULL);
1202 #line 441
1203 	return;
1204 #line 441
1205 }
1206 #line 982 "../../src/builtin/snarf.m4"
1207 
1208 #line 982
1209 
1210 #line 982
1211 
1212 #line 982
1213 void
1214 #line 982
dns_init_builtin(void)1215 dns_init_builtin(void)
1216 #line 982
1217 {
1218 #line 982
1219 
1220 #line 982
1221 	#line 27 "dns.bi"
1222 va_builtin_install_ex("primitive_hostname", bi_primitive_hostname, 0, dtype_string, 1, 0, 0|0, dtype_string);
1223 #line 43 "dns.bi"
1224 va_builtin_install_ex("primitive_resolve", bi_primitive_resolve, 0, dtype_string, 2, 1, 0|0, dtype_string, dtype_string);
1225 #line 64 "dns.bi"
1226 va_builtin_install_ex("primitive_hasmx", bi_primitive_hasmx, 0, dtype_number, 1, 0, 0|0, dtype_string);
1227 #line 110 "dns.bi"
1228 va_builtin_install_ex("primitive_ismx", bi_primitive_ismx, 0, dtype_number, 2, 0, 0|0, dtype_string, dtype_string);
1229 #line 133 "dns.bi"
1230 va_builtin_install_ex("relayed", bi_relayed, 0, dtype_number, 1, 0, 0|0, dtype_string);
1231 #line 139 "dns.bi"
1232 va_builtin_install_ex("ptr_validate", bi_ptr_validate, 0, dtype_number, 1, 0, 0|0, dtype_string);
1233 #line 157 "dns.bi"
1234 va_builtin_install_ex("primitive_hasns", bi_primitive_hasns, 0, dtype_number, 1, 0, 0|0, dtype_string);
1235 #line 254 "dns.bi"
1236 DNS_id = builtin_priv_register(dns_reply_storage_alloc, dns_reply_storage_destroy,
1237 #line 254
1238 NULL);
1239 #line 281 "dns.bi"
1240 va_builtin_install_ex("dns_reply_release", bi_dns_reply_release, 0, dtype_unspecified, 1, 0, 0|0, dtype_number);
1241 #line 291 "dns.bi"
1242 va_builtin_install_ex("dns_reply_count", bi_dns_reply_count, 0, dtype_number, 1, 0, 0|0, dtype_number);
1243 #line 309 "dns.bi"
1244 va_builtin_install_ex("dns_reply_string", bi_dns_reply_string, 0, dtype_string, 2, 0, 0|0, dtype_number, dtype_number);
1245 #line 328 "dns.bi"
1246 va_builtin_install_ex("dns_reply_ip", bi_dns_reply_ip, 0, dtype_string, 2, 0, 0|0, dtype_number, dtype_number);
1247 #line 362 "dns.bi"
1248 va_builtin_install_ex("dns_query", bi_dns_query, 0, dtype_number, 4, 2, 0|0, dtype_number, dtype_string, dtype_number, dtype_number);
1249 
1250 #line 982 "../../src/builtin/snarf.m4"
1251 
1252 #line 982
1253 }
1254 #line 982 "../../src/builtin/snarf.m4"
1255 
1256