summaryrefslogtreecommitdiffstats
path: root/src/dns/dns_rr_filter.c
blob: a02d3de6a16515c98fa5bd8cc7d391f457e76fa9 (plain)
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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
/*++
/* NAME
/*	dns_rr_filter 3
/* SUMMARY
/*	DNS resource record filter
/* SYNOPSIS
/*	#include <dns.h>
/*
/*	void	dns_rr_filter_compile(title, map_names)
/*	const char *title;
/*	const char *map_names;
/* INTERNAL INTERFACES
/*	int	dns_rr_filter_execute(rrlist)
/*	DNS_RR	**rrlist;
/*
/*	MAPS	*dns_rr_filter_maps;
/* DESCRIPTION
/*	This module implements a simple filter for dns_lookup*()
/*	results.
/*
/*	dns_rr_filter_compile() initializes a result filter.  The
/*	title and map_names arguments are as with maps_create().
/*	This function may be invoked more than once; only the last
/*	filter takes effect.
/*
/*	dns_rr_filter_execute() converts each resource record in the
/*	specified list with dns_strrecord to ASCII form and matches
/*	that against the specified maps. If a match is found it
/*	executes the corresponding action.  Currently, only the
/*	"ignore" action is implemented. This removes the matched
/*	record from the list. The result is 0 in case of success,
/*	-1 in case of error.
/*
/*	dns_rr_filter_maps is updated by dns_rr_filter_compile().
/* LICENSE
/* .ad
/* .fi
/*	The Secure Mailer license must be distributed with this software.
/* AUTHOR(S)
/*	Wietse Venema
/*	IBM T.J. Watson Research
/*	P.O. Box 704
/*	Yorktown Heights, NY 10598, USA
/*--*/

 /*
  * System library.
  */
#include <sys_defs.h>
#include <ctype.h>

#ifdef STRCASECMP_IN_STRINGS_H
#include <strings.h>
#endif

 /*
  * Utility library.
  */
#include <msg.h>
#include <vstring.h>
#include <myaddrinfo.h>

 /*
  * Global library.
  */
#include <maps.h>

 /*
  * DNS library.
  */
#define LIBDNS_INTERNAL
#include <dns.h>

 /*
  * Application-specific.
  */
MAPS   *dns_rr_filter_maps;

static DNS_RR dns_rr_filter_error[1];

#define STR vstring_str

/* dns_rr_filter_compile - compile dns result filter */

void    dns_rr_filter_compile(const char *title, const char *map_names)
{
    if (dns_rr_filter_maps != 0)
	maps_free(dns_rr_filter_maps);
    dns_rr_filter_maps = maps_create(title, map_names,
				     DICT_FLAG_LOCK | DICT_FLAG_FOLD_FIX);
}

/* dns_rr_action - execute action from filter map */

static DNS_RR *dns_rr_action(const char *cmd, DNS_RR *rr, const char *rr_text)
{
    const char *cmd_args = cmd + strcspn(cmd, " \t");
    int     cmd_len = cmd_args - cmd;

    while (*cmd_args && ISSPACE(*cmd_args))
	cmd_args++;

#define STREQUAL(x,y,l) (strncasecmp((x), (y), (l)) == 0 && (y)[l] == 0)

    if (STREQUAL(cmd, "IGNORE", cmd_len)) {
	msg_info("ignoring DNS RR: %s", rr_text);
	return (0);
    } else {
	msg_warn("%s: unknown DNS filter action: \"%s\"", 
		 dns_rr_filter_maps->title, cmd);
	return (dns_rr_filter_error);
    }
    return (rr);
}

/* dns_rr_filter_execute - filter DNS lookup result */

int     dns_rr_filter_execute(DNS_RR **rrlist)
{
    static VSTRING *buf = 0;
    DNS_RR **rrp;
    DNS_RR *rr;
    const char *map_res;
    DNS_RR *act_res;

    /*
     * Convert the resource record to string form, then search the maps for a
     * matching action.
     */
    if (buf == 0)
	buf = vstring_alloc(100);
    for (rrp = rrlist; (rr = *rrp) != 0; /* see below */ ) {
	map_res = maps_find(dns_rr_filter_maps, dns_strrecord(buf, rr),
			    DICT_FLAG_NONE);
	if (map_res != 0) {
	    if ((act_res = dns_rr_action(map_res, rr, STR(buf))) == 0) {
		*rrp = rr->next;		/* do not advance in the list */
		rr->next = 0;
		dns_rr_free(rr);
		continue;
	    } else if (act_res == dns_rr_filter_error) {
		return (-1);
	    }
	} else if (dns_rr_filter_maps->error) {
	    return (-1);
	}
	rrp = &(rr->next);			/* do advance in the list */
    }
    return (0);
}