spf_dns_windns.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 #ifdef _WIN32
00017 
00018 #include "spf_sys_config.h"
00019 
00020 #ifdef HAVE_ERRNO_H
00021 #include <errno.h>
00022 #endif
00023 
00024 #ifdef STDC_HEADERS
00025 # include <stdio.h>        /* stdin / stdout */
00026 # include <stdlib.h>       /* malloc / free */
00027 #endif
00028 
00029 #ifdef HAVE_STRING_H
00030 # include <string.h>       /* strstr / strdup */
00031 #else
00032 # ifdef HAVE_STRINGS_H
00033 #  include <strings.h>       /* strstr / strdup */
00034 # endif
00035 #endif
00036 
00037 #include "spf.h"
00038 #include "spf_dns.h"
00039 #include "spf_internal.h"
00040 #include "spf_dns_internal.h"
00041 #include "spf_dns_windns.h"
00042 #pragma comment(lib, "dnsapi.lib")
00043 #include <windns.h>
00044 
00045 
00046 typedef struct
00047 {
00048     int         debug;
00049     SPF_dns_rr_t spfrr;
00050 } SPF_dns_windns_config_t; 
00051 
00052 
00053 #define SPF_h_errno WSAGetLastError()
00054 
00055 
00056 static inline SPF_dns_windns_config_t *SPF_voidp2spfhook( void *hook ) 
00057     { return (SPF_dns_windns_config_t *)hook; }
00058 static inline void *SPF_spfhook2voidp( SPF_dns_windns_config_t *spfhook ) 
00059     { return (void *)spfhook; }
00060 
00061 
00062 LPSTR SPF_dns_create_error_message_windns(DWORD last_error)
00063 {
00064         LPSTR error_message;
00065 
00066         if (!FormatMessageA( 
00067                 (FORMAT_MESSAGE_ALLOCATE_BUFFER | 
00068                 FORMAT_MESSAGE_FROM_SYSTEM | 
00069                 FORMAT_MESSAGE_IGNORE_INSERTS),
00070                 NULL,
00071                 last_error,
00072                 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
00073                 (LPSTR) &error_message,
00074         0,
00075         NULL))
00076         {
00077                 return NULL;
00078         }
00079 
00080         return error_message;
00081 }
00082 
00083 
00084 void SPF_dns_destroy_error_message_windns(LPSTR error_message)
00085 {
00086         LocalFree( error_message );
00087 }
00088 
00089 
00090 size_t SPF_dns_txt_get_length_windns(DWORD count, PSTR strings[])
00091 {
00092         size_t  length;
00093         DWORD   i;
00094 
00095         length = 0;
00096 
00097         for( i = 0; i < count; i++ )
00098         {
00099                 length = length + strlen(strings[i]);
00100         }
00101 
00102         return length;
00103 }
00104 
00105 
00106 char *SPF_dns_txt_concat_windns(char *buffer, DWORD count, PSTR strings[])
00107 {
00108         DWORD   i;
00109 
00110         buffer[0] = 0;
00111 
00112         for( i = 0; i < count; i++ )
00113         {
00114                 if ( strcat( buffer, strings[i] ) == NULL )
00115                         return NULL;
00116         }
00117 
00118         return buffer;
00119 }
00120 
00121 
00122 static SPF_dns_rr_t *SPF_dns_lookup_windns( SPF_dns_config_t spfdcid, const char *domain, ns_type rr_type, int should_cache )
00123 {
00124     SPF_dns_iconfig_t           *spfdic = SPF_dcid2spfdic( spfdcid );
00125     SPF_dns_windns_config_t     *spfhook = SPF_voidp2spfhook( spfdic->hook );
00126     SPF_dns_rr_t *spfrr;
00127 
00128     int         cnt;
00129 
00130         PDNS_RECORDA pDnsRecord;
00131 
00132     DNS_STATUS  status;
00133         LPSTR   error_message;
00134     
00135     char        ip4_buf[ INET_ADDRSTRLEN ];
00136     char        ip6_buf[ INET6_ADDRSTRLEN ];
00137     
00138     int         rdlen;
00139 
00140         DNS_A_DATA              *pA_data;
00141         DNS_AAAA_DATA   *pAAAA_data;
00142         DNS_MX_DATAA    *pMX_data;
00143         DNS_TXT_DATAA   *pTXT_data;
00144         DNS_PTR_DATAA   *pPTR_data;
00145 
00146         size_t  txt_data_len;
00147         char    *txt_concat;
00148  
00149     
00150     /*
00151      * initialize stuff
00152      */
00153     spfrr = &spfhook->spfrr;
00154     SPF_dns_reset_rr( spfrr );
00155     spfrr->herrno = NO_RECOVERY;
00156     spfrr->rr_type = rr_type;
00157     if ( domain && domain[0] != '\0' )
00158     {
00159                 char   *new_domain;
00160                 size_t new_len = strlen( domain ) + 1;
00161 
00162                 if ( spfrr->domain_buf_len < new_len )
00163                 {
00164                         new_domain = realloc( spfrr->domain, new_len );
00165                         if ( new_domain == NULL )
00166                                 return spfrr;
00167 
00168                         spfrr->domain = new_domain;
00169                         spfrr->domain_buf_len = new_len;
00170                 }
00171                 strcpy( spfrr->domain, domain );
00172         }
00173     else if ( spfrr->domain )
00174                 spfrr->domain[0] = '\0';
00175 
00176     cnt = 0;
00177         
00178     if ( spfhook->debug )
00179                 SPF_debugf( "WinDNS looking for:  %s  %s (%d)",
00180                         domain,
00181                         (
00182                                 (rr_type == ns_t_a)     ? "A" :
00183                                 (rr_type == ns_t_aaaa)  ? "AAAA" :
00184                                 (rr_type == ns_t_mx)    ? "MX" :
00185                                 (rr_type == ns_t_txt)   ? "TXT" :
00186                                 (rr_type == ns_t_ptr)   ? "PTR" :
00187                                 (rr_type == ns_t_any)   ? "ANY" :
00188                                 "??" 
00189                         ),
00190                         rr_type );
00191 
00192     
00193     /*
00194      * try resolving the name
00195      */
00196     status = DnsQuery_A( domain, rr_type, 
00197                 (DNS_QUERY_STANDARD + DNS_QUERY_TREAT_AS_FQDN), 
00198                 NULL, &pDnsRecord, NULL );
00199 
00200     if ( status != DNS_RCODE_NOERROR )
00201     {
00202                 if ( spfhook->debug )
00203                 {
00204                         error_message = SPF_dns_create_error_message_windns(SPF_h_errno);
00205 
00206                         SPF_debugf( "query failed: err = %d  %s (%d)",
00207                                 status, error_message, SPF_h_errno );
00208 
00209                         SPF_dns_destroy_error_message_windns(error_message);
00210                 }
00211 
00212                 if ( 
00213                         ( SPF_h_errno == HOST_NOT_FOUND ) && 
00214                         ( spfdic->layer_below )
00215                         )
00216                         return SPF_dcid2spfdic( spfdic->layer_below )->lookup( spfdic->layer_below, domain, rr_type, should_cache );
00217 
00218                 spfrr->herrno = SPF_h_errno;
00219                 return spfrr;
00220     }
00221     else
00222                 spfrr->herrno = NETDB_SUCCESS;
00223 
00224         while (pDnsRecord)
00225         {
00226             rdlen = pDnsRecord->wDataLength;
00227 
00228                 if ( spfhook->debug > 1 )
00229                         SPF_debugf( "name: %s  type: %d  ttl: %d  rdlen: %d",
00230                                 pDnsRecord->pName, pDnsRecord->wType,
00231                                 pDnsRecord->dwTtl, rdlen );
00232 
00233             if ( rdlen <= 0 )
00234                 {
00235                         pDnsRecord = pDnsRecord->pNext;
00236                         continue;
00237                 }
00238 
00239                 /* No sense in doing this twice */
00240                 if (pDnsRecord->wType == ns_t_txt)
00241                 {
00242                         pTXT_data = &pDnsRecord->Data.TXT;
00243 
00244                         txt_data_len = 
00245                                 SPF_dns_txt_get_length_windns( 
00246                                         pTXT_data->dwStringCount, 
00247                                         pTXT_data->pStringArray 
00248                                         );
00249                 }
00250 
00251             if ( spfhook->debug > 1 )
00252             {
00253                 switch( pDnsRecord->wType )
00254                 {
00255                 case ns_t_a:
00256 
00257                         pA_data = &pDnsRecord->Data.A;
00258 
00259                     SPF_debugf( "A: %s",
00260                             inet_ntop( AF_INET, &pA_data->IpAddress,
00261                                        ip4_buf, sizeof( ip4_buf ) ));
00262                     break;
00263                 
00264                 case ns_t_aaaa:
00265 
00266                         pAAAA_data = &pDnsRecord->Data.AAAA;
00267 
00268                     SPF_debugf( "AAAA: %s",
00269                             inet_ntop( AF_INET6, &pAAAA_data->Ip6Address,
00270                             ip6_buf, sizeof( ip6_buf ) ));
00271                     break;
00272                 
00273                 case ns_t_ns:
00274 
00275                         SPF_debugf( "NS: %s", pDnsRecord->Data.NS.pNameHost );
00276                     break;
00277                 
00278                 case ns_t_cname:
00279 
00280                         SPF_debugf( "CNAME: %s", pDnsRecord->Data.CNAME.pNameHost );
00281                     break;
00282 
00283                 case ns_t_mx:
00284 
00285                         pMX_data = &pDnsRecord->Data.MX;
00286 
00287                         SPF_debugf( "MX: %d %s", 
00288                                 pMX_data->wPreference, pMX_data->pNameExchange );
00289                     break;
00290                 
00291                 case ns_t_txt:
00292 
00293                         txt_concat = malloc(txt_data_len + 1);
00294 
00295                         if ( txt_concat == NULL )
00296                                 SPF_debugf( "TXT: (%d) - no memory for concatination",
00297                                         txt_data_len );
00298                         else
00299                         {
00300                                 if ( SPF_dns_txt_concat_windns(
00301                                                 txt_concat, 
00302                                                 pTXT_data->dwStringCount, 
00303                                                 pTXT_data->pStringArray
00304                                                 ) == NULL )
00305                                         SPF_debugf( "TXT: (%d) - error in concatination",
00306                                                 txt_data_len );
00307                                 else
00308                                 {
00309                                         SPF_debugf( "TXT: (%d) \"%s\"",
00310                                                 txt_data_len, txt_concat );
00311                                 }
00312                                 free( txt_concat );
00313                         }
00314                     break;
00315                 
00316                 case ns_t_ptr:
00317 
00318                         pPTR_data = &pDnsRecord->Data.PTR;
00319 
00320                         SPF_debugf( "PTR: %s", pPTR_data->pNameHost );
00321                     break;
00322                 
00323                 default:
00324                     SPF_debugf( "not parsed:  type: %d", pDnsRecord->wType );
00325                     break;
00326                 }
00327                 }
00328 
00329                 if ( 
00330                         ( pDnsRecord->Flags.S.Section != DNSREC_ANSWER ) && 
00331                         ( spfhook->debug > 1 ) 
00332                         )
00333                 {
00334                         pDnsRecord = pDnsRecord->pNext;
00335                         continue;
00336                 }
00337                 
00338 
00339             if (
00340                         ( pDnsRecord->wType != spfrr->rr_type ) && 
00341                         ( pDnsRecord->wType != ns_t_cname )
00342                         )
00343             {
00344                         SPF_debugf( "unexpected rr type: %d   expected: %d",
00345                                 pDnsRecord->wType, rr_type );
00346                         pDnsRecord = pDnsRecord->pNext;
00347                         continue;
00348             }
00349 
00350             switch( pDnsRecord->wType )
00351             {
00352             case ns_t_a:
00353 
00354                         pA_data = &pDnsRecord->Data.A;
00355 
00356                         if ( SPF_dns_rr_buf_malloc(
00357                                 spfrr, cnt,     sizeof( pA_data->IpAddress ) 
00358                                 ) != SPF_E_SUCCESS )
00359                                 return spfrr;
00360             
00361                         memmove( &spfrr->rr[cnt]->a, &pA_data->IpAddress, 
00362                                 sizeof( pA_data->IpAddress ) );
00363 
00364                         cnt++;
00365                         break;
00366                 
00367                 case ns_t_aaaa:
00368 
00369                         pAAAA_data = &pDnsRecord->Data.AAAA;
00370 
00371                         if ( SPF_dns_rr_buf_malloc( 
00372                                 spfrr, cnt, sizeof( pAAAA_data->Ip6Address ) 
00373                                 ) != SPF_E_SUCCESS )
00374                                 return spfrr;
00375             
00376                         memmove( &spfrr->rr[cnt]->aaaa, &pAAAA_data->Ip6Address, 
00377                                 sizeof( pAAAA_data->Ip6Address ) );
00378 
00379                         cnt++;
00380                         break;
00381 
00382             case ns_t_ns:
00383                         break;
00384 
00385             case ns_t_cname:
00386                         /* FIXME:  are CNAMEs always sent with the real RR? */
00387                         break;
00388                 
00389             case ns_t_mx:
00390 
00391                         pMX_data = &pDnsRecord->Data.MX;
00392 
00393                         if ( SPF_dns_rr_buf_malloc(
00394                                 spfrr, cnt,     strlen( pMX_data->pNameExchange ) + 1 
00395                                 ) != SPF_E_SUCCESS )
00396                                 return spfrr;
00397 
00398                         strcpy( spfrr->rr[cnt]->mx, pMX_data->pNameExchange );
00399 
00400                         cnt++;
00401                         break;
00402                 
00403             case ns_t_txt:
00404 
00405                         if ( SPF_dns_rr_buf_malloc( 
00406                                         spfrr, cnt, txt_data_len + 1 
00407                                         ) != SPF_E_SUCCESS )
00408                                 return spfrr;
00409 
00410                         if ( SPF_dns_txt_concat_windns(
00411                                         spfrr->rr[cnt]->txt, 
00412                                         pTXT_data->dwStringCount, 
00413                                         pTXT_data->pStringArray
00414                                         ) == NULL )
00415                                 return spfrr;
00416 
00417                         cnt++;
00418                         break;
00419                 
00420             case ns_t_ptr:
00421 
00422                         pPTR_data = &pDnsRecord->Data.PTR;
00423 
00424                         if ( SPF_dns_rr_buf_malloc(
00425                                 spfrr, cnt,     strlen( pPTR_data->pNameHost ) + 1 
00426                                 ) != SPF_E_SUCCESS )
00427                                 return spfrr;
00428 
00429                         strcpy( spfrr->rr[cnt]->ptr, pPTR_data->pNameHost );
00430 
00431                         cnt++;
00432                         break;
00433                 
00434             default:
00435                         break;
00436                 }
00437         
00438                 spfrr->num_rr = cnt;
00439 
00440                 pDnsRecord = pDnsRecord->pNext;
00441         }
00442 
00443     if ( spfrr->num_rr == 0 )
00444                 spfhook->spfrr.herrno = NO_DATA;
00445 
00446     return spfrr;
00447 }
00448 
00449 
00450 SPF_dns_config_t SPF_dns_create_config_windns( SPF_dns_config_t layer_below, int debug )
00451 {
00452     SPF_dns_iconfig_t     *spfdic;
00453     SPF_dns_windns_config_t *spfhook;
00454 
00455     
00456     spfdic = malloc( sizeof( *spfdic ) );
00457     if ( spfdic == NULL )
00458         return NULL;
00459 
00460     spfdic->hook = calloc( 1, sizeof( SPF_dns_windns_config_t ) );
00461     if ( spfdic->hook == NULL )
00462     {
00463         free( spfdic );
00464         return NULL;
00465     }
00466     
00467     spfdic->destroy     = SPF_dns_destroy_config_windns;
00468     spfdic->lookup      = SPF_dns_lookup_windns;
00469     spfdic->get_spf     = NULL;
00470     spfdic->get_exp     = NULL;
00471     spfdic->add_cache   = NULL;
00472     spfdic->layer_below = layer_below;
00473     spfdic->name        = "windns";
00474     
00475     spfhook = SPF_voidp2spfhook( spfdic->hook );
00476 
00477     spfhook->debug = debug;
00478     SPF_dns_reset_rr( &spfhook->spfrr );
00479     spfhook->spfrr.source = SPF_spfdic2dcid( spfdic );
00480 
00481     return SPF_spfdic2dcid( spfdic );
00482 }
00483 
00484 void SPF_dns_reset_config_windns( SPF_dns_config_t spfdcid )
00485 {
00486     SPF_dns_iconfig_t    *spfdic = SPF_dcid2spfdic( spfdcid );
00487 
00488 
00489     if ( spfdcid == NULL )
00490         SPF_error( "spfdcid is NULL" );
00491 
00492 
00493     SPF_dns_reset_rr( &(SPF_voidp2spfhook( spfdic->hook )->spfrr) );
00494 }
00495 
00496 void SPF_dns_destroy_config_windns( SPF_dns_config_t spfdcid )
00497 {
00498     SPF_dns_iconfig_t     *spfdic = SPF_dcid2spfdic( spfdcid );
00499 
00500     if ( spfdcid == NULL )
00501         SPF_error( "spfdcid is NULL" );
00502 
00503     if ( spfdic->hook )
00504     {
00505         SPF_dns_windns_config_t *spfhook = SPF_voidp2spfhook( spfdic->hook );
00506 
00507         SPF_dns_destroy_rr_var( &spfhook->spfrr );
00508 
00509         free( spfdic->hook );
00510     }
00511 
00512     if ( spfdic )
00513         free( spfdic );
00514 }
00515 
00516 #endif

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