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  */
79MAPS   *dns_rr_filter_maps;
80
81static DNS_RR dns_rr_filter_error[1];
82
83#define STR vstring_str
84
85/* dns_rr_filter_compile - compile dns result filter */
86
87void    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
97static 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
120int     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