spf_response.c

Go to the documentation of this file.
00001 /* 
00002  * This program is free software; you can redistribute it and/or modify
00003  * it under the terms of either:
00004  * 
00005  *   a) The GNU Lesser General Public License as published by the Free
00006  *      Software Foundation; either version 2.1, or (at your option) any
00007  *      later version, 
00008  * 
00009  *   OR
00010  * 
00011  *   b) The two-clause BSD license.
00012  *
00013  * These licenses can be found with the distribution in the file LICENSES
00014  */
00015 
00016 #include "spf_sys_config.h"
00017 
00018 #ifdef STDC_HEADERS
00019 # include <stdio.h>        /* stdin / stdout */
00020 # include <stdlib.h>       /* malloc / free */
00021 #endif
00022 
00023 #ifdef HAVE_STRING_H
00024 # include <string.h>       /* strstr / strdup */
00025 #else
00026 # ifdef HAVE_STRINGS_H
00027 #  include <strings.h>       /* strstr / strdup */
00028 # endif
00029 #endif
00030 
00031 
00032 #include "spf.h"
00033 #include "spf_dns.h"
00034 #include "spf_response.h"
00035 
00036 SPF_response_t *
00037 SPF_response_new(SPF_request_t *spf_request)
00038 {
00039         SPF_response_t  *rp;
00040 
00041         rp = (SPF_response_t *)malloc(sizeof(SPF_response_t));
00042         if (! rp)
00043                 return rp;
00044         memset(rp, 0, sizeof(SPF_response_t));
00045 
00046         rp->spf_request = spf_request;
00047         rp->result = SPF_RESULT_INVALID;
00048 
00049         return rp;
00050 }
00051 
00052 void
00053 SPF_response_free(SPF_response_t *rp)
00054 {
00055         int      i;
00056 
00057         if (rp->received_spf)
00058                 free(rp->received_spf);
00059         /* Don't free received_spf_value - it points into received_spf */
00060         if (rp->header_comment)
00061                 free(rp->header_comment);
00062         if (rp->smtp_comment)
00063                 free(rp->smtp_comment);
00064         if (rp->explanation)
00065                 free(rp->explanation);
00066 
00067         if (rp->errors) {
00068                 for (i = 0; i < rp->errors_length; i++) {
00069                         free(rp->errors[i].message);
00070                 }
00071                 free(rp->errors);
00072         }
00073 
00074         free(rp);
00075 }
00076 
00077 static SPF_response_t *
00078 SPF_response_choose(SPF_response_t *yes, SPF_response_t *no)
00079 {
00080         SPF_response_free(no);
00081         return yes;
00082 }
00083 
00084 /*
00085  * This is rather a guess-and-fiddle routine which tries to pick
00086  * the best of both worlds. It doesn't currently deal with error
00087  * messages at all.
00088  */
00089 SPF_response_t *
00090 SPF_response_combine(SPF_response_t *main, SPF_response_t *r2mx)
00091 {
00092         switch (SPF_response_result(main)) {
00093                 case SPF_RESULT_INVALID:
00094                         /* If the main failed entirely, use the secondary */
00095                         return SPF_response_choose(r2mx, main);
00096 
00097                 case SPF_RESULT_PASS:
00098                         /* If the main passed, use main */
00099                         return SPF_response_choose(main, r2mx);
00100 
00101                 case SPF_RESULT_NEUTRAL:
00102                         /* If the main is neutral: */
00103                         switch (SPF_response_result(r2mx)) {
00104                                 case SPF_RESULT_PASS:
00105                                         /* Use the secondary if it passed */
00106                                         return SPF_response_choose(r2mx, main);
00107                                 default:
00108                                         /* Otherwise just use the main */
00109                                         return SPF_response_choose(main, r2mx);
00110                         }
00111 
00112                 case SPF_RESULT_FAIL:
00113                         /* If the main failed, use the secondary */
00114                         return SPF_response_choose(r2mx, main);
00115 
00116                 case SPF_RESULT_TEMPERROR:
00117                 case SPF_RESULT_PERMERROR:
00118                 case SPF_RESULT_SOFTFAIL:
00119                 default:
00120                         /* If the main is peculiar, including softfail: */
00121                         switch (SPF_response_result(r2mx)) {
00122                                 case SPF_RESULT_PASS:
00123                                 case SPF_RESULT_NEUTRAL:
00124                                 case SPF_RESULT_SOFTFAIL:
00125                                         /* Use the secondary if it didn't fail */
00126                                         return SPF_response_choose(r2mx, main);
00127                                 default:
00128                                         /* Otherwise just use the main */
00129                                         return SPF_response_choose(main, r2mx);
00130                         }
00131         }
00132 }
00133 
00134 SPF_result_t
00135 SPF_response_result(SPF_response_t *rp)
00136 {
00137         return rp->result;
00138 }
00139 
00140 SPF_reason_t
00141 SPF_response_reason(SPF_response_t *rp)
00142 {
00143         return rp->reason;
00144 }
00145 
00146 SPF_errcode_t
00147 SPF_response_errcode(SPF_response_t *rp)
00148 {
00149         return rp->err;
00150 }
00151 
00152 const char *
00153 SPF_response_get_received_spf(SPF_response_t *rp)
00154 {
00155         return rp->received_spf;
00156 }
00157 
00158 const char *
00159 SPF_response_get_received_spf_value(SPF_response_t *rp)
00160 {
00161         return rp->received_spf_value;
00162 }
00163 
00164 const char *
00165 SPF_response_get_header_comment(SPF_response_t *rp)
00166 {
00167         return rp->header_comment;
00168 }
00169 
00170 const char *
00171 SPF_response_get_smtp_comment(SPF_response_t *rp)
00172 {
00173         return rp->smtp_comment;
00174 }
00175 
00176 const char *
00177 SPF_response_get_explanation(SPF_response_t *rp)
00178 {
00179         return rp->explanation;
00180 }
00181 
00182 /* Error manipulation functions */
00183 
00184 #define SPF_ERRMSGSIZE          4096
00185 
00186 static SPF_errcode_t
00187 SPF_response_add_error_v(SPF_response_t *rp,
00188                                 SPF_errcode_t code, int is_error,
00189                                 const char *text, int idx,
00190                                 const char *format, va_list ap)
00191 {
00192         SPF_error_t     *tmp;
00193         char             buf[SPF_ERRMSGSIZE];
00194         int                      size;
00195 
00196         /* TODO: Use text and idx */
00197 
00198         if (!format)
00199                 format = SPF_strerror(code);
00200     size = vsnprintf(buf, sizeof(buf), format, ap);
00201         if (text != NULL) {
00202                 snprintf(&buf[size], sizeof(buf) - size,
00203                                 " near '%.12s'", &text[idx]);
00204         }
00205         buf[SPF_ERRMSGSIZE - 1] = '\0';
00206 
00207         if (rp->errors_length == rp->errors_size) {
00208                 size = rp->errors_size + (rp->errors_size / 4) + 4;
00209                 tmp = (SPF_error_t *)realloc(rp->errors, size * sizeof(SPF_error_t));
00210                 if (! tmp) {
00211                         SPF_error("Failed to allocate memory for extra response error");
00212                         return code;
00213                 }
00214                 rp->errors = tmp;
00215                 rp->errors_size = size;
00216         }
00217 
00218         rp->errors[rp->errors_length].code = code;
00219         rp->errors[rp->errors_length].is_error = is_error;
00220         /* If we are a memory error, this might fail. */
00221         rp->errors[rp->errors_length].message = strdup(buf);
00222         rp->errors_length++;
00223 
00224         return code;
00225 }
00226 
00227 #define SPF_ADD_ERROR(_ise, _txt, _ix) \
00228     va_list      ap; va_start(ap, format); \
00229         SPF_response_add_error_v(rp, code, _ise, _txt, _ix, format, ap); \
00230         rp->num_errors++; \
00231     va_end(ap); return code;
00232 #define SPF_ADD_WARN(_ise, _txt, _ix) \
00233     va_list      ap; va_start(ap, format); \
00234         SPF_response_add_error_v(rp, code, _ise, _txt, _ix, format, ap); \
00235     va_end(ap); return code;
00236 
00237 SPF_errcode_t
00238 SPF_response_add_error_ptr(SPF_response_t *rp,
00239                                 SPF_errcode_t code,
00240                                 const char *text, const char *tptr,
00241                                 const char *format, ...)
00242 {
00243         SPF_ADD_ERROR(1, text ? text : tptr, text ? (tptr - text) : 0);
00244 }
00245 
00246 SPF_errcode_t
00247 SPF_response_add_error_idx(SPF_response_t *rp,
00248                                 SPF_errcode_t code,
00249                                 const char *text, int idx,
00250                                 const char *format, ...)
00251 {
00252         SPF_ADD_ERROR(1, text, idx);
00253 }
00254 
00255 SPF_errcode_t
00256 SPF_response_add_error(SPF_response_t *rp,
00257                                 SPF_errcode_t code,
00258                                 const char *format, ...)
00259 {
00260         SPF_ADD_ERROR(1, NULL, 0);
00261 }
00262 
00263 SPF_errcode_t
00264 SPF_response_add_warn_ptr(SPF_response_t *rp,
00265                                 SPF_errcode_t code,
00266                                 const char *text, const char *tptr,
00267                                 const char *format, ...)
00268 {
00269         SPF_ADD_WARN(0, text ? text : tptr, text ? (tptr - text) : 0);
00270 }
00271 
00272 SPF_errcode_t
00273 SPF_response_add_warn_idx(SPF_response_t *rp,
00274                                 SPF_errcode_t code,
00275                                 const char *text, int idx,
00276                                 const char *format, ...)
00277 {
00278         SPF_ADD_WARN(0, text, idx);
00279 }
00280 
00281 SPF_errcode_t
00282 SPF_response_add_warn(SPF_response_t *rp,
00283                                 SPF_errcode_t code,
00284                                 const char *format, ...)
00285 {
00286         SPF_ADD_WARN(0, NULL, 0);
00287 }
00288 
00289 int
00290 SPF_response_messages(SPF_response_t *rp)
00291 {
00292         return rp->errors_length;
00293 }
00294 
00295 int
00296 SPF_response_errors(SPF_response_t *rp)
00297 {
00298         return rp->num_errors;
00299 }
00300 
00301 int
00302 SPF_response_warnings(SPF_response_t *rp)
00303 {
00304         return rp->errors_length - rp->num_errors;
00305 }
00306 
00307 SPF_error_t *
00308 SPF_response_message(SPF_response_t *rp, int idx)
00309 {
00310         return &rp->errors[idx];
00311 }
00312 
00313 SPF_errcode_t   
00314 SPF_error_code(SPF_error_t *err)
00315 {
00316         return err->code;
00317 }
00318 
00319 const char *
00320 SPF_error_message(SPF_error_t *err)
00321 {
00322         return err->message;
00323 }
00324 
00325 char
00326 SPF_error_errorp(SPF_error_t *err)
00327 {
00328         return err->is_error;
00329 }

Generated on Tue Nov 4 13:27:39 2008 for libspf2 by  doxygen 1.5.4