"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 }