xref: /netbsd-src/external/ibm-public/postfix/dist/src/dns/dns_rr_filter.c (revision e89934bbf778a6d6d6894877c4da59d0c7835b0f)
1 /*	$NetBSD: dns_rr_filter.c,v 1.2 2017/02/14 01:16:44 christos Exp $	*/
2 
3 /*++
4 /* NAME
5 /*	dns_rr_filter 3
6 /* SUMMARY
7 /*	DNS resource record filter
8 /* SYNOPSIS
9 /*	#include <dns.h>
10 /*
11 /*	void	dns_rr_filter_compile(title, map_names)
12 /*	const char *title;
13 /*	const char *map_names;
14 /* INTERNAL INTERFACES
15 /*	int	dns_rr_filter_execute(rrlist)
16 /*	DNS_RR	**rrlist;
17 /*
18 /*	MAPS	*dns_rr_filter_maps;
19 /* DESCRIPTION
20 /*	This module implements a simple filter for dns_lookup*()
21 /*	results.
22 /*
23 /*	dns_rr_filter_compile() initializes a result filter.  The
24 /*	title and map_names arguments are as with maps_create().
25 /*	This function may be invoked more than once; only the last
26 /*	filter takes effect.
27 /*
28 /*	dns_rr_filter_execute() converts each resource record in the
29 /*	specified list with dns_strrecord to ASCII form and matches
30 /*	that against the specified maps. If a match is found it
31 /*	executes the corresponding action.  Currently, only the
32 /*	"ignore" action is implemented. This removes the matched
33 /*	record from the list. The result is 0 in case of success,
34 /*	-1 in case of error.
35 /*
36 /*	dns_rr_filter_maps is updated by dns_rr_filter_compile().
37 /* LICENSE
38 /* .ad
39 /* .fi
40 /*	The Secure Mailer license must be distributed with this software.
41 /* AUTHOR(S)
42 /*	Wietse Venema
43 /*	IBM T.J. Watson Research
44 /*	P.O. Box 704
45 /*	Yorktown Heights, NY 10598, USA
46 /*--*/
47 
48  /*
49   * System library.
50   */
51 #include <sys_defs.h>
52 #include <ctype.h>
53 
54 #ifdef STRCASECMP_IN_STRINGS_H
55 #include <strings.h>
56 #endif
57 
58  /*
59   * Utility library.
60   */
61 #include <msg.h>
62 #include <vstring.h>
63 #include <myaddrinfo.h>
64 
65  /*
66   * Global library.
67   */
68 #include <maps.h>
69 
70  /*
71   * DNS library.
72   */
73 #define LIBDNS_INTERNAL
74 #include <dns.h>
75 
76  /*
77   * Application-specific.
78   */
79 MAPS   *dns_rr_filter_maps;
80 
81 static DNS_RR dns_rr_filter_error[1];
82 
83 #define STR vstring_str
84 
85 /* dns_rr_filter_compile - compile dns result filter */
86 
dns_rr_filter_compile(const char * title,const char * map_names)87 void    dns_rr_filter_compile(const char *title, const char *map_names)
88 {
89     if (dns_rr_filter_maps != 0)
90 	maps_free(dns_rr_filter_maps);
91     dns_rr_filter_maps = maps_create(title, map_names,
92 				     DICT_FLAG_LOCK | DICT_FLAG_FOLD_FIX);
93 }
94 
95 /* dns_rr_action - execute action from filter map */
96 
dns_rr_action(const char * cmd,DNS_RR * rr,const char * rr_text)97 static DNS_RR *dns_rr_action(const char *cmd, DNS_RR *rr, const char *rr_text)
98 {
99     const char *cmd_args = cmd + strcspn(cmd, " \t");
100     int     cmd_len = cmd_args - cmd;
101 
102     while (*cmd_args && ISSPACE(*cmd_args))
103 	cmd_args++;
104 
105 #define STREQUAL(x,y,l) (strncasecmp((x), (y), (l)) == 0 && (y)[l] == 0)
106 
107     if (STREQUAL(cmd, "IGNORE", cmd_len)) {
108 	msg_info("ignoring DNS RR: %s", rr_text);
109 	return (0);
110     } else {
111 	msg_warn("%s: unknown DNS filter action: \"%s\"",
112 		 dns_rr_filter_maps->title, cmd);
113 	return (dns_rr_filter_error);
114     }
115     return (rr);
116 }
117 
118 /* dns_rr_filter_execute - filter DNS lookup result */
119 
dns_rr_filter_execute(DNS_RR ** rrlist)120 int     dns_rr_filter_execute(DNS_RR **rrlist)
121 {
122     static VSTRING *buf = 0;
123     DNS_RR **rrp;
124     DNS_RR *rr;
125     const char *map_res;
126     DNS_RR *act_res;
127 
128     /*
129      * Convert the resource record to string form, then search the maps for a
130      * matching action.
131      */
132     if (buf == 0)
133 	buf = vstring_alloc(100);
134     for (rrp = rrlist; (rr = *rrp) != 0; /* see below */ ) {
135 	map_res = maps_find(dns_rr_filter_maps, dns_strrecord(buf, rr),
136 			    DICT_FLAG_NONE);
137 	if (map_res != 0) {
138 	    if ((act_res = dns_rr_action(map_res, rr, STR(buf))) == 0) {
139 		*rrp = rr->next;		/* do not advance in the list */
140 		rr->next = 0;
141 		dns_rr_free(rr);
142 		continue;
143 	    } else if (act_res == dns_rr_filter_error) {
144 		return (-1);
145 	    }
146 	} else if (dns_rr_filter_maps->error) {
147 	    return (-1);
148 	}
149 	rrp = &(rr->next);			/* do advance in the list */
150     }
151     return (0);
152 }
153