"Fossies" - the Fresh Open Source Software Archive 
Member "libspf2-1.2.10/src/libspf2/spf_dns.c" (28 Jan 2012, 7415 Bytes) of package /linux/privat/libspf2-1.2.10.tar.gz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
For more information about "spf_dns.c" see the
Fossies "Dox" file reference documentation.
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 #include "spf_sys_config.h"
18
19 #ifdef STDC_HEADERS
20 # include <stdio.h> /* stdin / stdout */
21 # include <stdlib.h> /* malloc / free */
22 #endif
23
24 #ifdef HAVE_STRING_H
25 # include <string.h> /* strstr / strdup */
26 #else
27 # ifdef HAVE_STRINGS_H
28 # include <strings.h> /* strstr / strdup */
29 # endif
30 #endif
31
32 #ifdef HAVE_NETDB_H
33 #include <netdb.h>
34 #endif
35
36
37 #include "spf.h"
38 #include "spf_dns.h"
39 #include "spf_internal.h"
40 #include "spf_dns_internal.h"
41
42
43 /*
44 * helper functions
45 */
46
47 static void
48 SPF_dns_debug_pre(SPF_dns_server_t *spf_dns_server, const char *domain,
49 ns_type rr_type, int should_cache)
50 {
51 if (spf_dns_server->debug) {
52 SPF_debugf("DNS[%s] lookup: %s %s (%d)",
53 spf_dns_server->name, domain,
54 SPF_strrrtype(rr_type), rr_type);
55 }
56 }
57
58 static void
59 SPF_dns_debug_post(SPF_dns_server_t *spf_dns_server, SPF_dns_rr_t *spfrr)
60 {
61 if (spf_dns_server->debug) {
62 char ip4_buf[ INET_ADDRSTRLEN ];
63 char ip6_buf[ INET6_ADDRSTRLEN ];
64 int i;
65
66 SPF_debugf("DNS[%s] found record", spf_dns_server->name);
67 SPF_debugf(" DOMAIN: %s TYPE: %s (%d)",
68 spfrr->domain,
69 SPF_strrrtype(spfrr->rr_type), spfrr->rr_type);
70 SPF_debugf(" TTL: %ld RR found: %d herrno: %d source: %s",
71 (long)spfrr->ttl, spfrr->num_rr, spfrr->herrno,
72 (spfrr->source
73 ? (spfrr->source->name
74 ? spfrr->source->name
75 : "(unnamed source)")
76 : "(null source)"));
77 for (i = 0; i < spfrr->num_rr; i++) {
78 switch (spfrr->rr_type) {
79 case ns_t_a:
80 SPF_debugf(" - A: %s",
81 inet_ntop(AF_INET, &(spfrr->rr[i]->a),
82 ip4_buf, sizeof(ip4_buf)));
83 break;
84
85 case ns_t_ptr:
86 SPF_debugf(" - PTR: %s", spfrr->rr[i]->ptr);
87 break;
88
89 case ns_t_mx:
90 SPF_debugf(" - MX: %s", spfrr->rr[i]->mx);
91 break;
92
93 case ns_t_txt:
94 SPF_debugf(" - TXT: %s", spfrr->rr[i]->txt);
95 break;
96
97 case ns_t_spf:
98 SPF_debugf(" - SPF: %s", spfrr->rr[i]->txt);
99 break;
100
101 case ns_t_aaaa:
102 SPF_debugf(" - AAAA: %s",
103 inet_ntop(AF_INET6, &(spfrr->rr[i]->aaaa),
104 ip6_buf, sizeof(ip6_buf)));
105 break;
106
107 default:
108 SPF_debugf(" - Unknown RR type");
109 break;
110 }
111 }
112 }
113 }
114
115 void
116 SPF_dns_free(SPF_dns_server_t *spf_dns_server)
117 {
118 SPF_dns_server_t *layer_below;
119
120 SPF_ASSERT_NOTNULL(spf_dns_server);
121 // SPF_ASSERT_NOTNULL(spf_dns_server->destroy);
122 layer_below = spf_dns_server->layer_below;
123
124 /* If this is not set, we assume someone else knows, and will destroy it. */
125 if (spf_dns_server->destroy) {
126 spf_dns_server->destroy(spf_dns_server);
127 if (layer_below != NULL)
128 SPF_dns_free(layer_below);
129 }
130 }
131
132 SPF_dns_rr_t *
133 SPF_dns_lookup(SPF_dns_server_t *spf_dns_server, const char *domain,
134 ns_type rr_type, int should_cache)
135 {
136 SPF_dns_rr_t *spfrr;
137
138 SPF_ASSERT_NOTNULL(spf_dns_server);
139 SPF_dns_debug_pre(spf_dns_server, domain, rr_type, should_cache);
140 SPF_ASSERT_NOTNULL(spf_dns_server->lookup);
141 spfrr = spf_dns_server->lookup(spf_dns_server,
142 domain, rr_type, should_cache);
143 if (spfrr == NULL)
144 SPF_error( "SPF DNS layer return NULL during a lookup." );
145 SPF_dns_debug_post(spf_dns_server, spfrr);
146 return spfrr;
147 }
148
149 SPF_dns_rr_t *
150 SPF_dns_rlookup(SPF_dns_server_t *spf_dns_server, struct in_addr ipv4,
151 ns_type rr_type, int should_cache)
152 {
153 char domain[ sizeof("111.222.333.444.in-addr.arpa") ];
154 union {
155 struct in_addr ipv4;
156 unsigned char x[4];
157 } tmp;
158
159 /*
160 * make sure the scratch buffer is big enough
161 */
162 tmp.ipv4 = ipv4;
163
164 snprintf(domain, sizeof(domain), "%d.%d.%d.%d.in-addr.arpa",
165 tmp.x[3], tmp.x[2], tmp.x[1], tmp.x[0]);
166
167 return SPF_dns_lookup(spf_dns_server, domain, rr_type,should_cache);
168 }
169
170 SPF_dns_rr_t *
171 SPF_dns_rlookup6(SPF_dns_server_t *spf_dns_server,
172 struct in6_addr ipv6, ns_type rr_type, int should_cache)
173 {
174 char domain[ sizeof(struct in6_addr) * 4 + sizeof(".ip6.arpa" ) + 1]; /* nibbles */
175 char *p, *p_end;
176 int i;
177
178 p = domain;
179 p_end = p + sizeof( domain );
180
181 for (i = sizeof(struct in6_addr) - 1; i >= 0; i--) {
182 p += snprintf(p, p_end - p, "%.1x.%.1x.",
183 ipv6.s6_addr[i] & 0xf,
184 ipv6.s6_addr[i] >> 4);
185 }
186
187 /* squash the final '.' */
188 p += snprintf(p, p_end - p, "ip6.arpa");
189
190 return SPF_dns_lookup(spf_dns_server, domain, rr_type, should_cache);
191 }
192
193
194
195 /* XXX FIXME */
196 /*
197 * Set the SMTP client domain name
198 */
199
200 /**
201 * This may return NULL if the strdup() fails.
202 *
203 * This ought to be refactored with the PTR code in the interpreter.
204 */
205 char *
206 SPF_dns_get_client_dom( SPF_dns_server_t *spf_dns_server,
207 SPF_request_t *sr )
208 {
209 char *client_dom;
210 SPF_dns_rr_t *rr_ptr;
211 SPF_dns_rr_t *rr_a;
212 SPF_dns_rr_t *rr_aaaa;
213
214 int i, j;
215
216 int max_ptr;
217
218 SPF_ASSERT_NOTNULL(spf_dns_server);
219 SPF_ASSERT_NOTNULL(sr);
220
221
222 /*
223 * The "p" macro expands to the validated domain name of the SMTP
224 * client. The validation procedure is described in section 5.4. If
225 * there are no validated domain names, the word "unknown" is
226 * substituted. If multiple validated domain names exist, the first one
227 * returned in the PTR result is chosen.
228 *
229 *
230 * sending-host_names := ptr_lookup(sending-host_IP);
231 * for each name in (sending-host_names) {
232 * IP_addresses := a_lookup(name);
233 * if the sending-host_IP is one of the IP_addresses {
234 * validated_sending-host_names += name;
235 * } }
236 */
237
238 if ( sr->client_ver == AF_INET ) {
239 rr_ptr = SPF_dns_rlookup( spf_dns_server, sr->ipv4, ns_t_ptr, FALSE );
240
241 max_ptr = rr_ptr->num_rr;
242 /* XXX TODO? Or irrelevant?
243 if (max_ptr > sr->max_dns_ptr)
244 max_ptr = sr->max_dns_ptr;
245 */
246 /* XXX do we want to report if this is exceeded and we
247 * might've missed a validated name because of that?
248 */
249 if (max_ptr > SPF_MAX_DNS_PTR)
250 max_ptr = SPF_MAX_DNS_PTR;
251
252 for (i = 0; i < max_ptr; i++) {
253 rr_a = SPF_dns_lookup(spf_dns_server, rr_ptr->rr[i]->ptr, ns_t_a, FALSE);
254
255 for (j = 0; j < rr_a->num_rr; j++) {
256 if (rr_a->rr[j]->a.s_addr == sr->ipv4.s_addr) {
257 client_dom = strdup(rr_ptr->rr[i]->ptr);
258 SPF_dns_rr_free(rr_ptr);
259 SPF_dns_rr_free(rr_a);
260 return client_dom;
261 }
262 }
263 SPF_dns_rr_free(rr_a);
264 }
265 SPF_dns_rr_free(rr_ptr);
266 }
267
268 else if ( sr->client_ver == AF_INET6 ) {
269 rr_ptr = SPF_dns_rlookup6( spf_dns_server, sr->ipv6, ns_t_ptr, FALSE );
270
271 max_ptr = rr_ptr->num_rr;
272 /*
273 if ( max_ptr > sr->max_dns_ptr )
274 max_ptr = sr->max_dns_ptr;
275 */
276 /* XXX do we want to report if this is exceeded and we
277 * might've missed a validated name because of that?
278 */
279 if ( max_ptr > SPF_MAX_DNS_PTR )
280 max_ptr = SPF_MAX_DNS_PTR;
281
282 for( i = 0; i < max_ptr; i++ ) {
283 rr_aaaa = SPF_dns_lookup( spf_dns_server, rr_ptr->rr[i]->ptr, ns_t_aaaa, FALSE );
284
285 for( j = 0; j < rr_aaaa->num_rr; j++ ) {
286 if ( memcmp( &rr_aaaa->rr[j]->aaaa, &sr->ipv6,
287 sizeof( sr->ipv6 ) ) == 0 ) {
288 client_dom = strdup( rr_ptr->rr[i]->ptr );
289 SPF_dns_rr_free( rr_ptr );
290 SPF_dns_rr_free( rr_aaaa );
291 return client_dom;
292 }
293 }
294 SPF_dns_rr_free( rr_aaaa );
295 }
296 SPF_dns_rr_free( rr_ptr );
297 }
298
299 return strdup( "unknown" );
300 }