Back to index

lightning-sunbird  0.9+nobinonly
getdxbyname.c
Go to the documentation of this file.
00001 /* ***** BEGIN LICENSE BLOCK *****
00002  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00003  *
00004  * The contents of this file are subject to the Mozilla Public License Version
00005  * 1.1 (the "License"); you may not use this file except in compliance with
00006  * the License. You may obtain a copy of the License at
00007  * http://www.mozilla.org/MPL/
00008  *
00009  * Software distributed under the License is distributed on an "AS IS" basis,
00010  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00011  * for the specific language governing rights and limitations under the
00012  * License.
00013  *
00014  * The Original Code is Mozilla Communicator client code, released
00015  * March 31, 1998.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1998-1999
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *
00024  * Alternatively, the contents of this file may be used under the terms of
00025  * either the GNU General Public License Version 2 or later (the "GPL"), or
00026  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00027  * in which case the provisions of the GPL or the LGPL are applicable instead
00028  * of those above. If you wish to allow use of your version of this file only
00029  * under the terms of either the GPL or the LGPL, and not to allow others to
00030  * use your version of this file under the terms of the MPL, indicate your
00031  * decision by deleting the provisions above and replace them with the notice
00032  * and other provisions required by the GPL or the LGPL. If you do not delete
00033  * the provisions above, a recipient may use your version of this file under
00034  * the terms of any one of the MPL, the GPL or the LGPL.
00035  *
00036  * ***** END LICENSE BLOCK ***** */
00037 /*
00038  *  Copyright (c) 1995 Regents of the University of Michigan.
00039  *  All rights reserved.
00040  */
00041 /*
00042  * nsldapi_getdxbyname - retrieve DX records from the DNS (from 
00043  * TXT records for now)
00044  */
00045 
00046 #include <stdio.h>
00047 
00048 #ifdef LDAP_DNS
00049 
00050 XXX not MT-safe XXX
00051 
00052 #include <string.h>
00053 #include <ctype.h>
00054 
00055 #ifdef macintosh
00056 #include <stdlib.h>
00057 #include "macos.h"
00058 #endif /* macintosh */
00059 
00060 #ifdef _WINDOWS
00061 #include <windows.h>
00062 #endif
00063 
00064 #if !defined(macintosh) && !defined(DOS) && !defined( _WINDOWS )
00065 #include <sys/types.h>
00066 #include <netinet/in.h>
00067 #include <arpa/nameser.h>
00068 #include <sys/time.h>
00069 #include <sys/types.h>
00070 #include <sys/socket.h>
00071 #include <netdb.h>
00072 #include <resolv.h>
00073 #endif
00074 #include "ldap-int.h"
00075 
00076 #if defined( DOS ) 
00077 #include "msdos.h"
00078 #endif /* DOS */
00079 
00080 
00081 #ifdef NEEDPROTOS
00082 static char ** decode_answer( unsigned char *answer, int len );
00083 #else /* NEEDPROTOS */
00084 static char **decode_answer();
00085 #endif /* NEEDPROTOS */
00086 
00087 extern int h_errno;
00088 extern char *h_errlist[];
00089 
00090 
00091 #define MAX_TO_SORT  32
00092 
00093 
00094 /*
00095  * nsldapi_getdxbyname - lookup DNS DX records for domain and return an ordered
00096  *     array.
00097  */
00098 char **
00099 nsldapi_getdxbyname( char *domain )
00100 {
00101     unsigned char    buf[ PACKETSZ ];
00102     char             **dxs;
00103     int                     rc;
00104 
00105     LDAPDebug( LDAP_DEBUG_TRACE, "nsldapi_getdxbyname( %s )\n", domain, 0, 0 );
00106 
00107     memset( buf, 0, sizeof( buf ));
00108 
00109     /* XXX not MT safe XXX */
00110     if (( rc = res_search( domain, C_IN, T_TXT, buf, sizeof( buf ))) < 0
00111               || ( dxs = decode_answer( buf, rc )) == NULL ) {
00112        /*
00113         * punt:  return list conisting of the original domain name only
00114         */
00115        if (( dxs = (char **)NSLDAPI_MALLOC( 2 * sizeof( char * ))) == NULL ||
00116               ( dxs[ 0 ] = nsldapi_strdup( domain )) == NULL ) {
00117            if ( dxs != NULL ) {
00118               NSLDAPI_FREE( dxs );
00119            }
00120            dxs = NULL;
00121        } else {
00122            dxs[ 1 ] = NULL;
00123        }
00124     }
00125 
00126     return( dxs );
00127 }
00128 
00129 
00130 static char **
00131 decode_answer( unsigned char *answer, int len )
00132 {
00133     HEADER           *hp;
00134     char             buf[ 256 ], **dxs;
00135     unsigned char    *eom, *p;
00136     int                     ancount, err, rc, type, class, dx_count, rr_len;
00137     int                     dx_pref[ MAX_TO_SORT ];
00138 
00139 #ifdef LDAP_DEBUG
00140     if ( ldap_debug & LDAP_DEBUG_PACKETS ) {
00141 /*     __p_query( answer ); */
00142     }
00143 #endif /* LDAP_DEBUG */
00144 
00145     dxs = NULL;
00146     hp = (HEADER *)answer;
00147     eom = answer + len;
00148 
00149     if ( ntohs( hp->qdcount ) != 1 ) {
00150        h_errno = NO_RECOVERY;
00151        return( NULL );
00152     }
00153 
00154     ancount = ntohs( hp->ancount );
00155     if ( ancount < 1 ) {
00156        h_errno = NO_DATA;
00157        return( NULL );
00158     }
00159 
00160     /*
00161      * skip over the query
00162      */
00163     p = answer + HFIXEDSZ;
00164     if (( rc = dn_expand( answer, eom, p, buf, sizeof( buf ))) < 0 ) {
00165        h_errno = NO_RECOVERY;
00166        return( NULL );
00167     }
00168     p += ( rc + QFIXEDSZ );
00169 
00170     /*
00171      * pull out the answers we are interested in
00172      */
00173     err = dx_count = 0;
00174     while ( ancount > 0 && err == 0 && p < eom ) {
00175        if (( rc = dn_expand( answer, eom, p, buf, sizeof( buf ))) < 0 ) {
00176            err = NO_RECOVERY;
00177            continue;
00178        }
00179        p += rc;      /* skip over name */
00180        type = _getshort( p );
00181        p += INT16SZ;
00182        class = _getshort( p );
00183        p += INT16SZ;
00184        p += INT32SZ;        /* skip over TTL */
00185        rr_len = _getshort( p );
00186        p += INT16SZ;
00187        if ( class == C_IN && type == T_TXT ) {
00188            int       i, n, pref, txt_len;
00189            char      *q, *r;
00190 
00191            q = (char *)p;
00192            while ( q < (char *)p + rr_len && err == 0 ) {
00193               if ( *q >= 3 && strncasecmp( q + 1, "dx:", 3 ) == 0 ) {
00194                   txt_len = *q - 3;
00195                   r = q + 4;
00196                   while ( isspace( *r )) { 
00197                      ++r;
00198                      --txt_len;
00199                   }
00200                   pref = 0;
00201                   while ( isdigit( *r )) {
00202                      pref *= 10;
00203                      pref += ( *r - '0' );
00204                      ++r;
00205                      --txt_len;
00206                   }
00207                   if ( dx_count < MAX_TO_SORT - 1 ) {
00208                      dx_pref[ dx_count ] = pref;
00209                   }
00210                   while ( isspace( *r )) { 
00211                      ++r;
00212                      --txt_len;
00213                   }
00214                   if ( dx_count == 0 ) {
00215                      dxs = (char **)NSLDAPI_MALLOC( 2 * sizeof( char * ));
00216                   } else {
00217                      dxs = (char **)NSLDAPI_REALLOC( dxs,
00218                             ( dx_count + 2 ) * sizeof( char * ));
00219                   }
00220                   if ( dxs == NULL || ( dxs[ dx_count ] =
00221                          (char *)NSLDAPI_CALLOC( 1, txt_len + 1 ))
00222                          == NULL ) {
00223                      err = NO_RECOVERY;
00224                      continue;
00225                   }
00226                   SAFEMEMCPY( dxs[ dx_count ], r, txt_len );
00227                   dxs[ ++dx_count ] = NULL;
00228               }
00229               q += ( *q + 1 );     /* move past last TXT record */
00230            }
00231        }
00232        p += rr_len;
00233     }
00234 
00235     if ( err == 0 ) {
00236        if ( dx_count == 0 ) {
00237            err = NO_DATA;
00238        } else {
00239            /*
00240             * sort records based on associated preference value
00241             */
00242            int              i, j, sort_count, tmp_pref;
00243            char      *tmp_dx;
00244 
00245            sort_count = ( dx_count < MAX_TO_SORT ) ? dx_count : MAX_TO_SORT;
00246            for ( i = 0; i < sort_count; ++i ) {
00247               for ( j = i + 1; j < sort_count; ++j ) {
00248                   if ( dx_pref[ i ] > dx_pref[ j ] ) {
00249                      tmp_pref = dx_pref[ i ];
00250                      dx_pref[ i ] = dx_pref[ j ];
00251                      dx_pref[ j ] = tmp_pref;
00252                      tmp_dx = dxs[ i ];
00253                      dxs[ i ] = dxs[ j ];
00254                      dxs[ j ] = tmp_dx;
00255                   }
00256               }
00257            }
00258        }
00259     }
00260 
00261     h_errno = err;
00262     return( dxs );
00263 }
00264 
00265 #endif /* LDAP_DNS */