1 /*
2  * This program is free software; you can redistribute it and/or modify
3  * it under the terms of either:
4  *
5  *   a) The GNU Lesser General Public License as published by the Free
6  *      Software Foundation; either version 2.1, or (at your option) any
7  *      later version,
8  *
9  *   OR
10  *
11  *   b) The two-clause BSD license.
12  *
13  * These licenses can be found with the distribution in the file LICENSES
14  */
15 
16 
17 
18 
19 #ifndef INC_SPF_DNS
20 #define INC_SPF_DNS
21 
22 
23 /**
24  * @file
25  *
26  * This library has the ability to use one or more of any of a number
27  * of DNS "layers" to obtain DNS information.  These layers all have
28  * compatible APIs, with only minor differences that relate to their
29  * specific functions.  So, they can be mixed and matched in any order
30  * to do what you want.
31  *
32  * When you create a new DNS layer, you can (optionally) specify the
33  * layer below it.  If the current DNS layer is not able to resolve
34  * the query, it will automatically call the lower layer.
35  *
36  * Some of the DNS layers allow for debugging information to be
37  * printed, some do caching, and, of course, some return actual DNS
38  * results either by query the network or by looking up the query in a
39  * database.
40  *
41  * For details about each DNS layer, see the appropriate
42  * spf_dns_<layer>.h include file.
43  *
44  *
45  * For example, there is a caching DNS layer that saves the compiled
46  * SPF records for future use.  While it takes a small amount of time
47  * to compile the AOL SPF record, you will more than make up for it by
48  * not having to parse the record every time you get a message from
49  * AOL.
50  *
51  * If you wanted to, you can even run the SPF system without using
52  * real DNS lookups at all.  For testing, I used a DNS layer that
53  * contained a built-in zone file.  This idea could easily be extended
54  * to being able to read the zone file from disk, or to use a database
55  * to access information.
56  *
57  * One example of what you could do with such a zone file would be to
58  * create your own SPF records for the many free-email providers.
59  * Depending on whether you layer this local zone file before or after
60  * the real DNS lookups, you can either override published SPF
61  * records, or you can provide defaults until SPF records are
62  * published.
63  *
64  */
65 
66 
67 /*
68  * For those who don't have <arpa/nameserv.h>
69  */
70 
71 /* XXX This should use a more sensible define. */
72 #if !defined( HAVE_NS_TYPE )
73 
74 #define	ns_t_invalid	0
75 #define	ns_t_a		1
76 #define	ns_t_ns		2
77 #define	ns_t_cname	5
78 #define	ns_t_ptr	12
79 #define	ns_t_mx		15
80 #define	ns_t_txt	16
81 #define ns_t_aaaa	28
82 /* #define ns_t_a6		38 */
83 #define	ns_t_any        255		/**< Wildcard match. */
84 
85 typedef int	ns_type;
86 #endif
87 
88 #if ! HAVE_DECL_NS_T_SPF
89 #define ns_t_spf	99
90 #endif
91 
92 #if ! HAVE_DECL_NS_T_INVALID
93 #define	ns_t_invalid	0
94 #endif
95 
96 
97 /*
98  * For those who don't have <netdb.h>
99  */
100 
101 #if !defined(HAVE_NETDB_H) && !defined(_WIN32)
102 #define NETDB_SUCCESS	0
103 #define	HOST_NOT_FOUND 	1		/**< NXDOMAIN (authoritative answer)*/
104 #define	TRY_AGAIN		2		/**< SERVFAIL (no authoritative answer)*/
105 #define	NO_RECOVERY		3		/**< invalid/unimplmeneted query	*/
106 #define	NO_DATA			4		/**< host found, but no RR of req type*/
107 #endif
108 typedef int SPF_dns_stat_t;
109 
110 typedef struct SPF_dns_server_struct SPF_dns_server_t;
111 
112 #include "spf_request.h"
113 #include "spf_dns_rr.h"
114 
115 /*
116  * bundle up the info needed to use a dns method
117  */
118 
119 typedef void (*SPF_dns_destroy_t)(SPF_dns_server_t *spf_dns_server);
120 typedef SPF_dns_rr_t *(*SPF_dns_lookup_t)(
121 				SPF_dns_server_t *spf_dns_server,
122 				const char *domain,
123 				ns_type ns_type, int should_cache
124 					);
125 typedef SPF_errcode_t (*SPF_dns_get_spf_t)( SPF_server_t *spf_server,
126 					SPF_request_t *spf_request,
127 					SPF_response_t *spf_response,
128 					SPF_record_t **spf_recordp);
129 typedef SPF_errcode_t (*SPF_dns_get_exp_t)( SPF_server_t *spf_server,
130 					const char *domain,
131 					char **buf, size_t *buf_len );
132 typedef int (*SPF_dns_add_cache_t)( SPF_server_t *spf_server,
133 				    SPF_dns_rr_t spfrr );
134 
135 struct SPF_dns_server_struct
136 {
137 	/** The destructor for this SPF_dns_server_t. If this is NULL, then
138 	 * the structure is assumed to be shared between multiple SPF_server_t
139 	 * objects, and is not freed when the server is destroyed, or by any call
140 	 * to SPF_dns_free(). In this case, it is assumed that somebody else knows,
141 	 * and will free the resolver at the appropriate object. */
142     SPF_dns_destroy_t	 destroy;
143 
144     SPF_dns_lookup_t	 lookup;
145     SPF_dns_get_spf_t	 get_spf;
146     SPF_dns_get_exp_t	 get_exp;
147     SPF_dns_add_cache_t  add_cache;
148 
149     /* the next DNS layer down to call if this layer can't give an answer */
150     SPF_dns_server_t	*layer_below;
151 
152     const char			*name;		/* name of the layer		*/
153 	int					 debug;
154     void				*hook;		/* server-specific data */
155 };
156 
157 
158 void			 SPF_dns_free( SPF_dns_server_t *spf_dns_server );
159 SPF_dns_rr_t	*SPF_dns_lookup( SPF_dns_server_t *spf_dns_server,
160 			      const char *domain, ns_type rr_type,
161 			      int should_cache );
162 SPF_dns_rr_t	*SPF_dns_rlookup( SPF_dns_server_t *spf_dns_server,
163 			       struct in_addr ipv4, ns_type rr_type,
164 			       int should_cache );
165 SPF_dns_rr_t	*SPF_dns_rlookup6( SPF_dns_server_t *spf_dns_server,
166 				struct in6_addr ipv6, ns_type rr_type,
167 				int should_cache );
168 
169 
170 /**
171  * The client domain is the validated domain name of the client IP
172  * address.  This is not just the domain name(s) found in the reverse
173  * DNS tree, but involves checking to make sure these name(s) use the
174  * client IP address.  The complete validation procedure is described
175  * in section 5.4 of the SPF spec.
176  */
177 char		*SPF_dns_get_client_dom(SPF_dns_server_t *spf_dns_server,
178 				SPF_request_t *sr);
179 
180 
181 #endif
182