"Fossies" - the Fresh Open Source Software Archive

Member "libspf2-1.2.10/src/libspf2/spf_dns_windns.c" (28 Jan 2012, 11073 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_windns.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 #ifdef _WIN32
   17 
   18 #include "spf_sys_config.h"
   19 
   20 #ifdef HAVE_ERRNO_H
   21 #include <errno.h>
   22 #endif
   23 
   24 #ifdef STDC_HEADERS
   25 # include <stdio.h>        /* stdin / stdout */
   26 # include <stdlib.h>       /* malloc / free */
   27 #endif
   28 
   29 #ifdef HAVE_STRING_H
   30 # include <string.h>       /* strstr / strdup */
   31 #else
   32 # ifdef HAVE_STRINGS_H
   33 #  include <strings.h>       /* strstr / strdup */
   34 # endif
   35 #endif
   36 
   37 #include "spf.h"
   38 #include "spf_dns.h"
   39 #include "spf_internal.h"
   40 #include "spf_dns_internal.h"
   41 #include "spf_dns_windns.h"
   42 #pragma comment(lib, "dnsapi.lib")
   43 #include <windns.h>
   44 
   45 
   46 typedef struct
   47 {
   48     int     debug;
   49     SPF_dns_rr_t spfrr;
   50 } SPF_dns_windns_config_t; 
   51 
   52 
   53 #define SPF_h_errno WSAGetLastError()
   54 
   55 
   56 static inline SPF_dns_windns_config_t *SPF_voidp2spfhook( void *hook ) 
   57     { return (SPF_dns_windns_config_t *)hook; }
   58 static inline void *SPF_spfhook2voidp( SPF_dns_windns_config_t *spfhook ) 
   59     { return (void *)spfhook; }
   60 
   61 
   62 LPSTR SPF_dns_create_error_message_windns(DWORD last_error)
   63 {
   64     LPSTR error_message;
   65 
   66     if (!FormatMessageA( 
   67         (FORMAT_MESSAGE_ALLOCATE_BUFFER | 
   68         FORMAT_MESSAGE_FROM_SYSTEM | 
   69         FORMAT_MESSAGE_IGNORE_INSERTS),
   70         NULL,
   71         last_error,
   72         MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
   73         (LPSTR) &error_message,
   74         0,
   75         NULL))
   76     {
   77         return NULL;
   78     }
   79 
   80     return error_message;
   81 }
   82 
   83 
   84 void SPF_dns_destroy_error_message_windns(LPSTR error_message)
   85 {
   86     LocalFree( error_message );
   87 }
   88 
   89 
   90 size_t SPF_dns_txt_get_length_windns(DWORD count, PSTR strings[])
   91 {
   92     size_t  length;
   93     DWORD   i;
   94 
   95     length = 0;
   96 
   97     for( i = 0; i < count; i++ )
   98     {
   99         length = length + strlen(strings[i]);
  100     }
  101 
  102     return length;
  103 }
  104 
  105 
  106 char *SPF_dns_txt_concat_windns(char *buffer, DWORD count, PSTR strings[])
  107 {
  108     DWORD   i;
  109 
  110     buffer[0] = 0;
  111 
  112     for( i = 0; i < count; i++ )
  113     {
  114         if ( strcat( buffer, strings[i] ) == NULL )
  115             return NULL;
  116     }
  117 
  118     return buffer;
  119 }
  120 
  121 
  122 static SPF_dns_rr_t *SPF_dns_lookup_windns( SPF_dns_config_t spfdcid, const char *domain, ns_type rr_type, int should_cache )
  123 {
  124     SPF_dns_iconfig_t       *spfdic = SPF_dcid2spfdic( spfdcid );
  125     SPF_dns_windns_config_t *spfhook = SPF_voidp2spfhook( spfdic->hook );
  126     SPF_dns_rr_t *spfrr;
  127 
  128     int     cnt;
  129 
  130     PDNS_RECORDA pDnsRecord;
  131 
  132     DNS_STATUS  status;
  133     LPSTR   error_message;
  134     
  135     char    ip4_buf[ INET_ADDRSTRLEN ];
  136     char    ip6_buf[ INET6_ADDRSTRLEN ];
  137     
  138     int     rdlen;
  139 
  140     DNS_A_DATA      *pA_data;
  141     DNS_AAAA_DATA   *pAAAA_data;
  142     DNS_MX_DATAA    *pMX_data;
  143     DNS_TXT_DATAA   *pTXT_data;
  144     DNS_PTR_DATAA   *pPTR_data;
  145 
  146     size_t  txt_data_len;
  147     char    *txt_concat;
  148  
  149     
  150     /*
  151      * initialize stuff
  152      */
  153     spfrr = &spfhook->spfrr;
  154     SPF_dns_reset_rr( spfrr );
  155     spfrr->herrno = NO_RECOVERY;
  156     spfrr->rr_type = rr_type;
  157     if ( domain && domain[0] != '\0' )
  158     {
  159         char   *new_domain;
  160         size_t new_len = strlen( domain ) + 1;
  161 
  162         if ( spfrr->domain_buf_len < new_len )
  163         {
  164             new_domain = realloc( spfrr->domain, new_len );
  165             if ( new_domain == NULL )
  166                 return spfrr;
  167 
  168             spfrr->domain = new_domain;
  169             spfrr->domain_buf_len = new_len;
  170         }
  171         strcpy( spfrr->domain, domain );
  172     }
  173     else if ( spfrr->domain )
  174         spfrr->domain[0] = '\0';
  175 
  176     cnt = 0;
  177         
  178     if ( spfhook->debug )
  179         SPF_debugf( "WinDNS looking for:  %s  %s (%d)",
  180             domain,
  181             (
  182                 (rr_type == ns_t_a)     ? "A" :
  183                 (rr_type == ns_t_aaaa)  ? "AAAA" :
  184                 (rr_type == ns_t_mx)    ? "MX" :
  185                 (rr_type == ns_t_txt)   ? "TXT" :
  186                 (rr_type == ns_t_ptr)   ? "PTR" :
  187                 (rr_type == ns_t_any)   ? "ANY" :
  188                 "??" 
  189             ),
  190             rr_type );
  191 
  192     
  193     /*
  194      * try resolving the name
  195      */
  196     status = DnsQuery_A( domain, rr_type, 
  197                 (DNS_QUERY_STANDARD + DNS_QUERY_TREAT_AS_FQDN), 
  198                 NULL, &pDnsRecord, NULL );
  199 
  200     if ( status != DNS_RCODE_NOERROR )
  201     {
  202         if ( spfhook->debug )
  203         {
  204             error_message = SPF_dns_create_error_message_windns(SPF_h_errno);
  205 
  206             SPF_debugf( "query failed: err = %d  %s (%d)",
  207                 status, error_message, SPF_h_errno );
  208 
  209             SPF_dns_destroy_error_message_windns(error_message);
  210         }
  211 
  212         if ( 
  213             ( SPF_h_errno == HOST_NOT_FOUND ) && 
  214             ( spfdic->layer_below )
  215             )
  216             return SPF_dcid2spfdic( spfdic->layer_below )->lookup( spfdic->layer_below, domain, rr_type, should_cache );
  217 
  218         spfrr->herrno = SPF_h_errno;
  219         return spfrr;
  220     }
  221     else
  222         spfrr->herrno = NETDB_SUCCESS;
  223 
  224     while (pDnsRecord)
  225     {
  226         rdlen = pDnsRecord->wDataLength;
  227 
  228         if ( spfhook->debug > 1 )
  229             SPF_debugf( "name: %s  type: %d  ttl: %d  rdlen: %d",
  230                 pDnsRecord->pName, pDnsRecord->wType,
  231                 pDnsRecord->dwTtl, rdlen );
  232 
  233         if ( rdlen <= 0 )
  234         {
  235             pDnsRecord = pDnsRecord->pNext;
  236             continue;
  237         }
  238 
  239         /* No sense in doing this twice */
  240         if (pDnsRecord->wType == ns_t_txt)
  241         {
  242             pTXT_data = &pDnsRecord->Data.TXT;
  243 
  244             txt_data_len = 
  245                 SPF_dns_txt_get_length_windns( 
  246                     pTXT_data->dwStringCount, 
  247                     pTXT_data->pStringArray 
  248                     );
  249         }
  250 
  251         if ( spfhook->debug > 1 )
  252         {
  253         switch( pDnsRecord->wType )
  254         {
  255         case ns_t_a:
  256 
  257             pA_data = &pDnsRecord->Data.A;
  258 
  259             SPF_debugf( "A: %s",
  260                 inet_ntop( AF_INET, &pA_data->IpAddress,
  261                        ip4_buf, sizeof( ip4_buf ) ));
  262             break;
  263         
  264         case ns_t_aaaa:
  265 
  266             pAAAA_data = &pDnsRecord->Data.AAAA;
  267 
  268             SPF_debugf( "AAAA: %s",
  269                 inet_ntop( AF_INET6, &pAAAA_data->Ip6Address,
  270                 ip6_buf, sizeof( ip6_buf ) ));
  271             break;
  272         
  273         case ns_t_ns:
  274 
  275             SPF_debugf( "NS: %s", pDnsRecord->Data.NS.pNameHost );
  276             break;
  277         
  278         case ns_t_cname:
  279 
  280             SPF_debugf( "CNAME: %s", pDnsRecord->Data.CNAME.pNameHost );
  281             break;
  282 
  283         case ns_t_mx:
  284 
  285             pMX_data = &pDnsRecord->Data.MX;
  286 
  287             SPF_debugf( "MX: %d %s", 
  288                 pMX_data->wPreference, pMX_data->pNameExchange );
  289             break;
  290         
  291         case ns_t_txt:
  292 
  293             txt_concat = malloc(txt_data_len + 1);
  294 
  295             if ( txt_concat == NULL )
  296                 SPF_debugf( "TXT: (%d) - no memory for concatination",
  297                     txt_data_len );
  298             else
  299             {
  300                 if ( SPF_dns_txt_concat_windns(
  301                         txt_concat, 
  302                         pTXT_data->dwStringCount, 
  303                         pTXT_data->pStringArray
  304                         ) == NULL )
  305                     SPF_debugf( "TXT: (%d) - error in concatination",
  306                         txt_data_len );
  307                 else
  308                 {
  309                     SPF_debugf( "TXT: (%d) \"%s\"",
  310                         txt_data_len, txt_concat );
  311                 }
  312                 free( txt_concat );
  313             }
  314             break;
  315         
  316         case ns_t_ptr:
  317 
  318             pPTR_data = &pDnsRecord->Data.PTR;
  319 
  320             SPF_debugf( "PTR: %s", pPTR_data->pNameHost );
  321             break;
  322         
  323         default:
  324             SPF_debugf( "not parsed:  type: %d", pDnsRecord->wType );
  325             break;
  326         }
  327         }
  328 
  329         if ( 
  330             ( pDnsRecord->Flags.S.Section != DNSREC_ANSWER ) && 
  331             ( spfhook->debug > 1 ) 
  332             )
  333         {
  334             pDnsRecord = pDnsRecord->pNext;
  335             continue;
  336         }
  337         
  338 
  339         if (
  340             ( pDnsRecord->wType != spfrr->rr_type ) && 
  341             ( pDnsRecord->wType != ns_t_cname )
  342             )
  343         {
  344             SPF_debugf( "unexpected rr type: %d   expected: %d",
  345                 pDnsRecord->wType, rr_type );
  346             pDnsRecord = pDnsRecord->pNext;
  347             continue;
  348         }
  349 
  350         switch( pDnsRecord->wType )
  351         {
  352         case ns_t_a:
  353 
  354             pA_data = &pDnsRecord->Data.A;
  355 
  356             if ( SPF_dns_rr_buf_malloc(
  357                 spfrr, cnt, sizeof( pA_data->IpAddress ) 
  358                 ) != SPF_E_SUCCESS )
  359                 return spfrr;
  360             
  361             memmove( &spfrr->rr[cnt]->a, &pA_data->IpAddress, 
  362                 sizeof( pA_data->IpAddress ) );
  363 
  364             cnt++;
  365             break;
  366         
  367         case ns_t_aaaa:
  368 
  369             pAAAA_data = &pDnsRecord->Data.AAAA;
  370 
  371             if ( SPF_dns_rr_buf_malloc( 
  372                 spfrr, cnt, sizeof( pAAAA_data->Ip6Address ) 
  373                 ) != SPF_E_SUCCESS )
  374                 return spfrr;
  375             
  376             memmove( &spfrr->rr[cnt]->aaaa, &pAAAA_data->Ip6Address, 
  377                 sizeof( pAAAA_data->Ip6Address ) );
  378 
  379             cnt++;
  380             break;
  381 
  382         case ns_t_ns:
  383             break;
  384 
  385         case ns_t_cname:
  386             /* FIXME:  are CNAMEs always sent with the real RR? */
  387             break;
  388         
  389         case ns_t_mx:
  390 
  391             pMX_data = &pDnsRecord->Data.MX;
  392 
  393             if ( SPF_dns_rr_buf_malloc(
  394                 spfrr, cnt, strlen( pMX_data->pNameExchange ) + 1 
  395                 ) != SPF_E_SUCCESS )
  396                 return spfrr;
  397 
  398             strcpy( spfrr->rr[cnt]->mx, pMX_data->pNameExchange );
  399 
  400             cnt++;
  401             break;
  402         
  403         case ns_t_txt:
  404 
  405             if ( SPF_dns_rr_buf_malloc( 
  406                     spfrr, cnt, txt_data_len + 1 
  407                     ) != SPF_E_SUCCESS )
  408                 return spfrr;
  409 
  410             if ( SPF_dns_txt_concat_windns(
  411                     spfrr->rr[cnt]->txt, 
  412                     pTXT_data->dwStringCount, 
  413                     pTXT_data->pStringArray
  414                     ) == NULL )
  415                 return spfrr;
  416 
  417             cnt++;
  418             break;
  419         
  420         case ns_t_ptr:
  421 
  422             pPTR_data = &pDnsRecord->Data.PTR;
  423 
  424             if ( SPF_dns_rr_buf_malloc(
  425                 spfrr, cnt, strlen( pPTR_data->pNameHost ) + 1 
  426                 ) != SPF_E_SUCCESS )
  427                 return spfrr;
  428 
  429             strcpy( spfrr->rr[cnt]->ptr, pPTR_data->pNameHost );
  430 
  431             cnt++;
  432             break;
  433         
  434         default:
  435             break;
  436         }
  437         
  438         spfrr->num_rr = cnt;
  439 
  440         pDnsRecord = pDnsRecord->pNext;
  441     }
  442 
  443     if ( spfrr->num_rr == 0 )
  444         spfhook->spfrr.herrno = NO_DATA;
  445 
  446     return spfrr;
  447 }
  448 
  449 
  450 SPF_dns_config_t SPF_dns_create_config_windns( SPF_dns_config_t layer_below, int debug )
  451 {
  452     SPF_dns_iconfig_t     *spfdic;
  453     SPF_dns_windns_config_t *spfhook;
  454 
  455     
  456     spfdic = malloc( sizeof( *spfdic ) );
  457     if ( spfdic == NULL )
  458     return NULL;
  459 
  460     spfdic->hook = calloc( 1, sizeof( SPF_dns_windns_config_t ) );
  461     if ( spfdic->hook == NULL )
  462     {
  463     free( spfdic );
  464     return NULL;
  465     }
  466     
  467     spfdic->destroy     = SPF_dns_destroy_config_windns;
  468     spfdic->lookup      = SPF_dns_lookup_windns;
  469     spfdic->get_spf     = NULL;
  470     spfdic->get_exp     = NULL;
  471     spfdic->add_cache   = NULL;
  472     spfdic->layer_below = layer_below;
  473     spfdic->name        = "windns";
  474     
  475     spfhook = SPF_voidp2spfhook( spfdic->hook );
  476 
  477     spfhook->debug = debug;
  478     SPF_dns_reset_rr( &spfhook->spfrr );
  479     spfhook->spfrr.source = SPF_spfdic2dcid( spfdic );
  480 
  481     return SPF_spfdic2dcid( spfdic );
  482 }
  483 
  484 void SPF_dns_reset_config_windns( SPF_dns_config_t spfdcid )
  485 {
  486     SPF_dns_iconfig_t    *spfdic = SPF_dcid2spfdic( spfdcid );
  487 
  488 
  489     if ( spfdcid == NULL )
  490     SPF_error( "spfdcid is NULL" );
  491 
  492 
  493     SPF_dns_reset_rr( &(SPF_voidp2spfhook( spfdic->hook )->spfrr) );
  494 }
  495 
  496 void SPF_dns_destroy_config_windns( SPF_dns_config_t spfdcid )
  497 {
  498     SPF_dns_iconfig_t     *spfdic = SPF_dcid2spfdic( spfdcid );
  499 
  500     if ( spfdcid == NULL )
  501     SPF_error( "spfdcid is NULL" );
  502 
  503     if ( spfdic->hook )
  504     {
  505     SPF_dns_windns_config_t *spfhook = SPF_voidp2spfhook( spfdic->hook );
  506 
  507     SPF_dns_destroy_rr_var( &spfhook->spfrr );
  508 
  509     free( spfdic->hook );
  510     }
  511 
  512     if ( spfdic )
  513     free( spfdic );
  514 }
  515 
  516 #endif