diff options
Diffstat (limited to '')
-rw-r--r-- | src/dns/dns_rr_filter.c | 150 |
1 files changed, 150 insertions, 0 deletions
diff --git a/src/dns/dns_rr_filter.c b/src/dns/dns_rr_filter.c new file mode 100644 index 0000000..a02d3de --- /dev/null +++ b/src/dns/dns_rr_filter.c @@ -0,0 +1,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); +} |