libspf2  1.2.11
spfquery.c
Go to the documentation of this file.
1 /*
2  * spfquery - Sender Policy Framwork command line utility
3  *
4  * Author: Wayne Schlitt <wayne@midwestcs.com>
5  *
6  * File: spfquery.c
7  * Desc: SPF command line utility
8  *
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of either:
12  *
13  * a) The GNU Lesser General Public License as published by the Free
14  * Software Foundation; either version 2.1, or (at your option) any
15  * later version,
16  *
17  * OR
18  *
19  * b) The two-clause BSD license.
20  *
21  *
22  * The two-clause BSD license:
23  *
24  *
25  * Redistribution and use in source and binary forms, with or without
26  * modification, are permitted provided that the following conditions
27  * are met:
28  *
29  * 1. Redistributions of source code must retain the above copyright
30  * notice, this list of conditions and the following disclaimer.
31  * 2. Redistributions in binary form must reproduce the above copyright
32  * notice, this list of conditions and the following disclaimer in the
33  * documentation and/or other materials provided with the distribution.
34  *
35  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
36  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
37  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
38  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
39  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
40  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
41  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
42  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
43  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
44  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
45  */
46 
47 #define SPF_TEST_VERSION "3.0"
48 
50 
51 #ifdef HAVE_CONFIG_H
52 # include "config.h"
53 #endif
54 
55 #ifdef STDC_HEADERS
56 # include <stdio.h>
57 # include <stdlib.h> /* malloc / free */
58 #endif
59 
60 #ifdef HAVE_SYS_TYPES_H
61 #include <sys/types.h> /* types (u_char .. etc..) */
62 #endif
63 
64 #ifdef HAVE_INTTYPES_H
65 #include <inttypes.h>
66 #endif
67 
68 #ifdef HAVE_STRING_H
69 # include <string.h> /* strstr / strdup */
70 #else
71 # ifdef HAVE_STRINGS_H
72 # include <strings.h> /* strstr / strdup */
73 # endif
74 #endif
75 
76 #ifdef HAVE_SYS_SOCKET_H
77 # include <sys/socket.h> /* inet_ functions / structs */
78 #endif
79 #ifdef HAVE_NETINET_IN_H
80 # include <netinet/in.h> /* inet_ functions / structs */
81 #endif
82 
83 #ifdef HAVE_ARPA_NAMESER_H
84 # include <arpa/nameser.h> /* DNS HEADER struct */
85 #endif
86 
87 #ifdef HAVE_ARPA_INET_H
88 # include <arpa/inet.h> /* in_addr struct */
89 #endif
90 
91 #ifdef HAVE_GETOPT_LONG_ONLY
92 #define _GNU_SOURCE
93 #include <getopt.h>
94 #else
95 #include "libreplace/getopt.h"
96 #endif
97 
98 #ifdef _WIN32
99 #include "spf_win32.h"
100 #endif
101 
102 #include "spf.h"
103 #include "spf_dns.h"
104 #include "spf_dns_null.h"
105 #include "spf_dns_test.h"
106 #include "spf_dns_cache.h"
107 #ifndef _WIN32
108 #include "spf_dns_resolv.h"
109 #else
110 #include "spf_dns_windns.h"
111 #endif
112 
113 
114 
115 #define TRUE 1
116 #define FALSE 0
117 
118 #define FREE(x, f) do { if ((x)) (f)((x)); (x) = NULL; } while(0)
119 #define FREE_REQUEST(x) FREE((x), SPF_request_free)
120 #define FREE_RESPONSE(x) FREE((x), SPF_response_free)
121 
122 #define CONTINUE_ERROR do { res = 255; continue; } while(0)
123 #define WARN_ERROR do { res = 255; } while(0)
124 #define FAIL_ERROR do { res = 255; goto error; } while(0)
125 
126 #define RESIZE_RESULT(n) do { \
127  if (result == NULL) { \
128  result_len = 256 + n; \
129  result = malloc(result_len); \
130  result[0] = '\0'; \
131  } \
132  else if (strlen(result) + n >= result_len) { \
133  result_len = result_len + (result_len >> 1) + 8 + n; \
134  result = realloc(result, result_len); \
135  } \
136 } while(0)
137 #define APPEND_RESULT(n) do { \
138  partial_result = SPF_strresult(n); \
139  RESIZE_RESULT(strlen(partial_result)); \
140  strcat(result, partial_result); \
141 } while(0)
142 
143 #define X_OR_EMPTY(x) ((x) ? (x) : "")
144 
145 static struct option long_options[] = {
146  {"file", 1, 0, 'f'},
147 
148  {"ip", 1, 0, 'i'},
149  {"sender", 1, 0, 's'},
150  {"helo", 1, 0, 'h'},
151  {"rcpt-to", 1, 0, 'r'},
152 
153  {"debug", 2, 0, 'd'},
154  {"local", 1, 0, 'l'},
155  {"trusted", 1, 0, 't'},
156  {"guess", 1, 0, 'g'},
157  {"default-explanation", 1, 0, 'e'},
158  {"max-lookup", 1, 0, 'm'},
159  {"sanitize", 1, 0, 'c'},
160  {"name", 1, 0, 'n'},
161  {"override", 1, 0, 'a'},
162  {"fallback", 1, 0, 'z'},
163 
164  {"keep-comments", 0, 0, 'k'},
165  {"version", 0, 0, 'v'},
166  {"help", 0, 0, '?'},
167 
168  {0, 0, 0, 0}
169 };
170 
171 static void
172 unimplemented(const char flag)
173 {
174  struct option *opt;
175  int i;
176 
177  for (i = 0; (opt = &long_options[i])->name; i++) {
178  if (flag == opt->val) {
179  fprintf(stderr, "Unimplemented option: -%s or -%c\n",
180  opt->name, flag);
181  return;
182  }
183  }
184 
185  fprintf(stderr, "Unimplemented option: -%c\n", flag);
186 }
187 
188 
189 static void
190 usage()
191 {
192  fprintf(
193  stderr,
194  "Usage:\n"
195  "\n"
196  "spfquery [control options | data options] ...\n"
197  "\n"
198  "Use the -help option for more information\n"
199  );
200 }
201 
202 static void
203 help()
204 {
205  fprintf(
206  stderr,
207  "Usage:\n"
208  "\n"
209  "spfquery [control options | data options] ...\n"
210  "\n"
211  "Valid data options are:\n"
212  " -file <filename> read spf data from a file. Use '-'\n"
213  " to read from stdin.\n"
214  "\n"
215  " -ip <IP address> The IP address that is sending email\n"
216  " -sender <email address> The email address used as the\n"
217  " envelope-from. If no username (local\n"
218  " part) is given, 'postmaster' will be\n"
219  " assumed.\n"
220  " -helo <domain name> The domain name given on the SMTP HELO\n"
221  " command. This is only needed if the\n"
222  " -sender option is not given.\n"
223  " -rcpt-to <email addresses> A comma separated lists of email addresses\n"
224  " that will have email from their secondary\n"
225  " MXes automatically allowed.\n"
226  "\n"
227  "The data options are required. The -file option conflicts with all\n"
228  "the other data options. The -helo and -rcpt-to are optional.\n"
229  "\n"
230  "\n"
231  "Valid control options are:\n"
232  " -debug [debug level] debug level.\n"
233  " -local <SPF mechanisms> Local policy for whitelisting.\n"
234  " -trusted <0|1> Should trusted-forwarder.org be checked?\n"
235  " -guess <SPF mechanisms> Default checks if no SPF record is found.\n"
236  " -default-explanation <str> Default explanation string to use.\n"
237  " -max-lookup <number> Maximum number of DNS lookups to allow\n"
238  " -sanitize <0|1> Clean up invalid characters in output?\n"
239  " -name <domain name> The name of the system doing the SPF\n"
240  " checking\n"
241  " -override <...> Override SPF records for domains\n"
242  " -fallback <...> Fallback SPF records for domains\n"
243  "\n"
244  " -keep-comments Print comments found when reading\n"
245  " from a file.\n"
246  " -version Print version of spfquery.\n"
247  " -help Print out these options.\n"
248  "\n"
249  "Examples:\n"
250  "\n"
251  "spfquery -ip=11.22.33.44 -sender=user@aol.com -helo=spammer.tld\n"
252  "spfquery -f test_data\n"
253  "echo \"127.0.0.1 myname@mydomain.com helohost.com\" | spfquery -f -\n"
254  );
255 }
256 
257 
258 static void
259 response_print_errors(const char *context,
260  SPF_response_t *spf_response, SPF_errcode_t err)
261 {
262  SPF_error_t *spf_error;
263  int i;
264 
265  printf("StartError\n");
266 
267  if (context != NULL)
268  printf("Context: %s\n", context);
269  if (err != SPF_E_SUCCESS)
270  printf("ErrorCode: (%d) %s\n", err, SPF_strerror(err));
271 
272  if (spf_response != NULL) {
273  for (i = 0; i < SPF_response_messages(spf_response); i++) {
274  spf_error = SPF_response_message(spf_response, i);
275  printf( "%s: %s%s\n",
276  SPF_error_errorp(spf_error) ? "Error" : "Warning",
277  // SPF_error_code(spf_error),
278  // SPF_strerror(SPF_error_code(spf_error)),
279  ((SPF_error_errorp(spf_error) && (!err))
280  ? "[UNRETURNED] "
281  : ""),
282  SPF_error_message(spf_error) );
283  }
284  }
285  else {
286  printf("libspf2 gave a NULL spf_response\n");
287  }
288  printf("EndError\n");
289 }
290 
291 static void
292 response_print(const char *context, SPF_response_t *spf_response)
293 {
294  printf("--vv--\n");
295  printf("Context: %s\n", context);
296  if (spf_response == NULL) {
297  printf("NULL RESPONSE!\n");
298  }
299  else {
300  printf("Response result: %s\n",
301  SPF_strresult(SPF_response_result(spf_response)));
302  printf("Response reason: %s\n",
303  SPF_strreason(SPF_response_reason(spf_response)));
304  printf("Response err: %s\n",
305  SPF_strerror(SPF_response_errcode(spf_response)));
306  response_print_errors(NULL, spf_response,
307  SPF_response_errcode(spf_response));
308  }
309  printf("--^^--\n");
310 }
311 
312 typedef
313 struct SPF_client_options_struct {
314  // void *hook;
315  char *localpolicy;
316  const char *explanation;
317  const char *fallback;
318  const char *rec_dom;
321  int sanitize;
322  int debug;
324 
325 typedef
326 struct SPF_client_request_struct {
327  char *ip;
328  char *sender;
329  char *helo;
330  char *rcpt_to;
332 
333 int main( int argc, char *argv[] )
334 {
335  SPF_client_options_t *opts;
337 
338  SPF_server_t *spf_server = NULL;
339  SPF_request_t *spf_request = NULL;
340  SPF_response_t *spf_response = NULL;
341  SPF_response_t *spf_response_2mx = NULL;
342  SPF_response_t *spf_response_fallback = NULL;
343  SPF_errcode_t err;
344 
345  char *opt_file = NULL;
346  int opt_keep_comments = 0;
347 
348  FILE *fin;
349  char in_line[4096];
350  char *p, *p_end;
351  int done_once;
352  int major, minor, patch;
353 
354  int res = 0;
355  int c;
356 
357  const char *partial_result;
358  char *result = NULL;
359  int result_len = 0;
360 
361  opts = (SPF_client_options_t *)malloc(sizeof(SPF_client_options_t));
362  memset(opts, 0, sizeof(SPF_client_options_t));
363 
364  req = (SPF_client_request_t *)malloc(sizeof(SPF_client_request_t));
365  memset(req, 0, sizeof(SPF_client_request_t));
366 
367  opts->rec_dom = "spfquery";
368 
369 #ifdef _WIN32
370  if (SPF_win32_startup() == 0) {
371  fprintf( stderr, "Could not startup WinSock, wrong version." );
372  FAIL_ERROR;
373  }
374 #endif
375 
376  /*
377  * check the arguments
378  */
379 
380  for (;;) {
381  int option_index; /* Largely unused */
382 
383  c = getopt_long_only (argc, argv, "f:i:s:h:r:lt::gemcnd::kz:a:v",
384  long_options, &option_index);
385 
386  if (c == -1)
387  break;
388 
389  switch (c) {
390  case 'f':
391  opt_file = optarg;
392  break;
393 
394 
395  case 'i':
396  req->ip = optarg;
397  break;
398 
399  case 's':
400  req->sender = optarg;
401  break;
402 
403  case 'h':
404  req->helo = optarg;
405  break;
406 
407  case 'r':
408  req->rcpt_to = optarg;
409  break;
410 
411 
412  case 'l':
413  opts->localpolicy = optarg;
414  break;
415 
416  case 't':
417  if (optarg == NULL)
418  opts->use_trusted = 1;
419  else
420  opts->use_trusted = atoi(optarg);
421  break;
422 
423  case 'g':
424  opts->fallback = optarg;
425  break;
426 
427  case 'e':
428  opts->explanation = optarg;
429  break;
430 
431  case 'm':
432  opts->max_lookup = atoi(optarg);
433  break;
434 
435  case 'c': /* "clean" */
436  opts->sanitize = atoi(optarg);
437  break;
438 
439  case 'n': /* name of host doing SPF checking */
440  opts->rec_dom = optarg;
441  break;
442 
443  case 'a':
444  unimplemented('a');
445  break;
446 
447  case 'z':
448  unimplemented('z');
449  break;
450 
451 
452  case 'v':
453  fprintf( stderr, "spfquery version information:\n" );
454  fprintf( stderr, "SPF test system version: %s\n",
456  fprintf( stderr, "Compiled with SPF library version: %d.%d.%d\n",
459  SPF_get_lib_version( &major, &minor, &patch );
460  fprintf( stderr, "Running with SPF library version: %d.%d.%d\n",
461  major, minor, patch );
462  fprintf( stderr, "\n" );
463  usage();
464  FAIL_ERROR;
465  break;
466 
467  case 0:
468  case '?':
469  help();
470  FAIL_ERROR;
471  break;
472 
473  case 'k':
474  opt_keep_comments = 1;
475  break;
476 
477  case 'd':
478  if (optarg == NULL)
479  opts->debug = 1;
480  else
481  opts->debug = atoi( optarg );
482  break;
483 
484  default:
485  fprintf( stderr, "Error: getopt returned character code 0%o ??\n", c);
486  FAIL_ERROR;
487  }
488  }
489 
490  if (optind != argc) {
491  help();
492  FAIL_ERROR;
493  }
494 
495  /*
496  * set up the SPF configuration
497  */
498 
499  spf_server = SPF_server_new(SPF_DNS_CACHE, opts->debug);
500 
501  if ( opts->rec_dom )
502  SPF_server_set_rec_dom( spf_server, opts->rec_dom );
503  if ( opts->sanitize )
504  SPF_server_set_sanitize( spf_server, opts->sanitize );
505  if ( opts->max_lookup )
506  SPF_server_set_max_dns_mech(spf_server, opts->max_lookup);
507 
508  if (opts->localpolicy) {
509  err = SPF_server_set_localpolicy( spf_server, opts->localpolicy, opts->use_trusted, &spf_response);
510  if ( err ) {
511  response_print_errors("Error setting local policy",
512  spf_response, err);
513  WARN_ERROR;
514  }
515  FREE_RESPONSE(spf_response);
516  }
517 
518 
519  if ( opts->explanation ) {
520  err = SPF_server_set_explanation( spf_server, opts->explanation, &spf_response );
521  if ( err ) {
522  response_print_errors("Error setting default explanation",
523  spf_response, err);
524  WARN_ERROR;
525  }
526  FREE_RESPONSE(spf_response);
527  }
528 
529  /*
530  * process the SPF request
531  */
532 
533  if (opt_file) {
534  /*
535  * the requests are on STDIN
536  */
537  if (strcmp(opt_file, "-" ) == 0)
538  fin = stdin;
539  else
540  fin = fopen( opt_file, "r" );
541 
542  if (!fin) {
543  fprintf( stderr, "Could not open: %s\n", opt_file );
544  FAIL_ERROR;
545  }
546  }
547  else {
548  fin = NULL;
549 
550  if ((req->ip == NULL) ||
551  (req->sender == NULL && req->helo == NULL) ) {
552  usage();
553  FAIL_ERROR;
554  }
555  }
556 
557  done_once = FALSE;
558 
559  while ( TRUE ) {
560  if ( fin ) {
561  if ( fgets( in_line, sizeof( in_line ), fin ) == NULL )
562  break;
563 
564  in_line[strcspn(in_line, "\r\n")] = '\0';
565  p = in_line;
566 
567  p += strspn( p, " \t\n" );
568  {
569  if ( *p == '\0' || *p == '#' ) {
570  if ( opt_keep_comments )
571  printf( "%s\n", in_line );
572  continue;
573  }
574  }
575  req->ip = p;
576  p += strcspn( p, " \t\n" );
577  *p++ = '\0';
578 
579  p += strspn( p, " \t\n" );
580  req->sender = p;
581  p += strcspn( p, " \t\n" );
582  *p++ = '\0';
583 
584  p += strspn( p, " \t\n" );
585  req->helo = p;
586  p += strcspn( p, " \t\n" );
587  *p++ = '\0';
588 
589  p += strspn( p, " \t\n" );
590  req->rcpt_to = p;
591  p += strcspn( p, " \t\n" );
592  *p++ = '\0';
593  }
594  else {
595  if ( done_once )
596  break;
597  done_once = TRUE;
598  }
599 
600  /* We have to do this here else we leak on CONTINUE_ERROR */
601  FREE_REQUEST(spf_request);
602  FREE_RESPONSE(spf_response);
603 
604  spf_request = SPF_request_new(spf_server);
605 
606  if (SPF_request_set_ipv4_str(spf_request, req->ip)
607  && SPF_request_set_ipv6_str(spf_request, req->ip)) {
608  printf( "Invalid IP address.\n" );
610  }
611 
612  if (req->helo) {
613  if (SPF_request_set_helo_dom( spf_request, req->helo ) ) {
614  printf( "Invalid HELO domain.\n" );
616  }
617  }
618 
619  if (SPF_request_set_env_from( spf_request, req->sender ) ) {
620  printf( "Invalid envelope from address.\n" );
622  }
623 
624  err = SPF_request_query_mailfrom(spf_request, &spf_response);
625  if (opts->debug)
626  response_print("Main query", spf_response);
627  if (err) {
628  response_print_errors("Failed to query MAIL-FROM",
629  spf_response, err);
631  }
632 
633  if (result != NULL)
634  result[0] = '\0';
635  APPEND_RESULT(SPF_response_result(spf_response));
636 
637  if (req->rcpt_to != NULL && *req->rcpt_to != '\0' ) {
638  p = req->rcpt_to;
639  p_end = p + strcspn(p, ",;");
640 
641  /* This is some incarnation of 2mx mode. */
642  while (SPF_response_result(spf_response)!=SPF_RESULT_PASS) {
643  if (*p_end)
644  *p_end = '\0';
645  else
646  p_end = NULL; /* Note this is last rcpt */
647 
648  err = SPF_request_query_rcptto(spf_request,
649  &spf_response_2mx, p);
650  if (opts->debug)
651  response_print("2mx query", spf_response_2mx);
652  if (err) {
653  response_print_errors("Failed to query RCPT-TO",
654  spf_response, err);
656  }
657 
658  /* append the result */
659  APPEND_RESULT(SPF_response_result(spf_response_2mx));
660 
661  spf_response = SPF_response_combine(spf_response,
662  spf_response_2mx);
663 
664  if (!p_end)
665  break;
666  p = p_end + 1;
667  }
668  }
669 
670  /* We now have an option to call SPF_request_query_fallback */
671  if (opts->fallback) {
672  err = SPF_request_query_fallback(spf_request,
673  &spf_response_fallback, opts->fallback);
674  if (opts->debug)
675  response_print("fallback query", spf_response_fallback);
676  if (err) {
677  response_print_errors("Failed to query best-guess",
678  spf_response_fallback, err);
680  }
681 
682  /* append the result */
683  APPEND_RESULT(SPF_response_result(spf_response_fallback));
684 
685  spf_response = SPF_response_combine(spf_response,
686  spf_response_fallback);
687  }
688 
689  printf( "%s\n%s\n%s\n%s\n",
690  result,
694  );
695 
696  res = SPF_response_result(spf_response);
697 
698  fflush(stdout);
699  }
700 
701  error:
702  FREE(result, free);
703  FREE_RESPONSE(spf_response);
704  FREE_REQUEST(spf_request);
705  FREE(spf_server, SPF_server_free);
706 
707  FREE(req, free);
708  FREE(opts, free);
709 
710 #ifdef _WIN32
711  SPF_win32_cleanup();
712 #endif
713 
714  return res;
715 }
const char * SPF_strresult(SPF_result_t result)
Definition: spf_utils.c:84
const char * SPF_strreason(SPF_reason_t reason)
Definition: spf_utils.c:131
void SPF_get_lib_version(int *major, int *minor, int *patch)
Definition: spf_utils.c:41
const char * SPF_strerror(SPF_errcode_t spf_err)
Definition: spf_strerror.c:33
A testing layer for DNS.
#define NULL
Definition: spf_internal.h:28
#define SPF_LIB_VERSION_PATCH
#define SPF_LIB_VERSION_MINOR
#define SPF_LIB_VERSION_MAJOR
SPF_errcode_t SPF_request_set_ipv6_str(SPF_request_t *sr, const char *astr)
Definition: spf_request.c:106
SPF_errcode_t SPF_request_query_fallback(SPF_request_t *spf_request, SPF_response_t **spf_responsep, const char *record)
Definition: spf_request.c:300
int SPF_request_set_env_from(SPF_request_t *sr, const char *from)
Definition: spf_request.c:139
SPF_errcode_t SPF_request_set_helo_dom(SPF_request_t *sr, const char *dom)
Definition: spf_request.c:117
SPF_request_t * SPF_request_new(SPF_server_t *spf_server)
Definition: spf_request.c:41
SPF_errcode_t SPF_request_set_ipv4_str(SPF_request_t *sr, const char *astr)
Definition: spf_request.c:95
SPF_errcode_t SPF_request_query_rcptto(SPF_request_t *spf_request, SPF_response_t **spf_responsep, const char *rcpt_to)
Definition: spf_request.c:340
SPF_errcode_t SPF_request_query_mailfrom(SPF_request_t *spf_request, SPF_response_t **spf_responsep)
Definition: spf_request.c:270
@ SPF_RESULT_PASS
Definition: spf_response.h:82
const char * SPF_error_message(SPF_error_t *err)
Definition: spf_response.c:320
const char * SPF_response_get_header_comment(SPF_response_t *rp)
Definition: spf_response.c:165
SPF_errcode_t SPF_response_errcode(SPF_response_t *rp)
Definition: spf_response.c:147
SPF_error_t * SPF_response_message(SPF_response_t *rp, int idx)
Definition: spf_response.c:308
const char * SPF_response_get_received_spf(SPF_response_t *rp)
Definition: spf_response.c:153
SPF_response_t * SPF_response_combine(SPF_response_t *main, SPF_response_t *r2mx)
Definition: spf_response.c:90
int SPF_response_messages(SPF_response_t *rp)
Definition: spf_response.c:290
char SPF_error_errorp(SPF_error_t *err)
Definition: spf_response.c:326
SPF_errcode_t
Definition: spf_response.h:119
@ SPF_E_SUCCESS
Definition: spf_response.h:120
SPF_result_t SPF_response_result(SPF_response_t *rp)
Definition: spf_response.c:135
SPF_reason_t SPF_response_reason(SPF_response_t *rp)
Definition: spf_response.c:141
const char * SPF_response_get_smtp_comment(SPF_response_t *rp)
Definition: spf_response.c:171
@ SPF_DNS_CACHE
Definition: spf_server.h:73
SPF_errcode_t SPF_server_set_explanation(SPF_server_t *sp, const char *exp, SPF_response_t **spf_responsep)
Definition: spf_server.c:235
SPF_server_t * SPF_server_new(SPF_server_dnstype_t dnstype, int debug)
Definition: spf_server.c:132
void SPF_server_free(SPF_server_t *sp)
Definition: spf_server.c:200
SPF_errcode_t SPF_server_set_sanitize(SPF_server_t *sp, int sanitize)
Definition: spf_server.c:228
SPF_errcode_t SPF_server_set_localpolicy(SPF_server_t *sp, const char *policy, int use_default_whitelist, SPF_response_t **spf_responsep)
Definition: spf_server.c:267
SPF_errcode_t SPF_server_set_rec_dom(SPF_server_t *sp, const char *dom)
Definition: spf_server.c:215
int getopt_long_only()
int optind
char * optarg
void usage(void)
Definition: spfd.c:446
int main(int argc, char *argv[])
Definition: spfquery.c:333
#define CONTINUE_ERROR
Definition: spfquery.c:122
#define X_OR_EMPTY(x)
Definition: spfquery.c:143
#define FREE_RESPONSE(x)
Definition: spfquery.c:120
#define FAIL_ERROR
Definition: spfquery.c:124
#define APPEND_RESULT(n)
Definition: spfquery.c:137
#define WARN_ERROR
Definition: spfquery.c:123
#define FREE_REQUEST(x)
Definition: spfquery.c:119
#define FREE(x, f)
Definition: spfquery.c:118
#define TRUE
Definition: spfquery.c:115
#define FALSE
Definition: spfquery.c:116
#define SPF_TEST_VERSION
Definition: spfquery.c:47
Definition: getopt.h:80
int val
Definition: getopt.h:90
char * name
Definition: getopt.h:84
int * flag
Definition: getopt.h:89
const char * explanation
Definition: spfquery.c:316
const char * rec_dom
Definition: spfquery.c:318
const char * fallback
Definition: spfquery.c:317