xref: /illumos-gate/usr/src/lib/libldap5/sources/ldap/common/getdxbyname.c (revision 1da57d551424de5a9d469760be7c4b4d4f10a755)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the Netscape Public
3*7c478bd9Sstevel@tonic-gate  * License Version 1.1 (the "License"); you may not use this file
4*7c478bd9Sstevel@tonic-gate  * except in compliance with the License. You may obtain a copy of
5*7c478bd9Sstevel@tonic-gate  * the License at http://www.mozilla.org/NPL/
6*7c478bd9Sstevel@tonic-gate  *
7*7c478bd9Sstevel@tonic-gate  * Software distributed under the License is distributed on an "AS
8*7c478bd9Sstevel@tonic-gate  * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
9*7c478bd9Sstevel@tonic-gate  * implied. See the License for the specific language governing
10*7c478bd9Sstevel@tonic-gate  * rights and limitations under the License.
11*7c478bd9Sstevel@tonic-gate  *
12*7c478bd9Sstevel@tonic-gate  * The Original Code is Mozilla Communicator client code, released
13*7c478bd9Sstevel@tonic-gate  * March 31, 1998.
14*7c478bd9Sstevel@tonic-gate  *
15*7c478bd9Sstevel@tonic-gate  * The Initial Developer of the Original Code is Netscape
16*7c478bd9Sstevel@tonic-gate  * Communications Corporation. Portions created by Netscape are
17*7c478bd9Sstevel@tonic-gate  * Copyright (C) 1998-1999 Netscape Communications Corporation. All
18*7c478bd9Sstevel@tonic-gate  * Rights Reserved.
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * Contributor(s):
21*7c478bd9Sstevel@tonic-gate  */
22*7c478bd9Sstevel@tonic-gate /*
23*7c478bd9Sstevel@tonic-gate  *  Copyright (c) 1995 Regents of the University of Michigan.
24*7c478bd9Sstevel@tonic-gate  *  All rights reserved.
25*7c478bd9Sstevel@tonic-gate  */
26*7c478bd9Sstevel@tonic-gate /*
27*7c478bd9Sstevel@tonic-gate  * nsldapi_getdxbyname - retrieve DX records from the DNS (from
28*7c478bd9Sstevel@tonic-gate  * TXT records for now)
29*7c478bd9Sstevel@tonic-gate  */
30*7c478bd9Sstevel@tonic-gate 
31*7c478bd9Sstevel@tonic-gate #include <stdio.h>
32*7c478bd9Sstevel@tonic-gate 
33*7c478bd9Sstevel@tonic-gate #ifdef LDAP_DNS
34*7c478bd9Sstevel@tonic-gate 
35*7c478bd9Sstevel@tonic-gate XXX not MT-safe XXX
36*7c478bd9Sstevel@tonic-gate 
37*7c478bd9Sstevel@tonic-gate #include <string.h>
38*7c478bd9Sstevel@tonic-gate #include <ctype.h>
39*7c478bd9Sstevel@tonic-gate 
40*7c478bd9Sstevel@tonic-gate #ifdef macintosh
41*7c478bd9Sstevel@tonic-gate #include <stdlib.h>
42*7c478bd9Sstevel@tonic-gate #include "macos.h"
43*7c478bd9Sstevel@tonic-gate #endif /* macintosh */
44*7c478bd9Sstevel@tonic-gate 
45*7c478bd9Sstevel@tonic-gate #ifdef _WINDOWS
46*7c478bd9Sstevel@tonic-gate #include <windows.h>
47*7c478bd9Sstevel@tonic-gate #endif
48*7c478bd9Sstevel@tonic-gate 
49*7c478bd9Sstevel@tonic-gate #if !defined(macintosh) && !defined(DOS) && !defined( _WINDOWS )
50*7c478bd9Sstevel@tonic-gate #include <sys/types.h>
51*7c478bd9Sstevel@tonic-gate #include <netinet/in.h>
52*7c478bd9Sstevel@tonic-gate #include <arpa/nameser.h>
53*7c478bd9Sstevel@tonic-gate #include <sys/time.h>
54*7c478bd9Sstevel@tonic-gate #include <sys/types.h>
55*7c478bd9Sstevel@tonic-gate #include <sys/socket.h>
56*7c478bd9Sstevel@tonic-gate #include <netdb.h>
57*7c478bd9Sstevel@tonic-gate #include <resolv.h>
58*7c478bd9Sstevel@tonic-gate #endif
59*7c478bd9Sstevel@tonic-gate #include "ldap-int.h"
60*7c478bd9Sstevel@tonic-gate 
61*7c478bd9Sstevel@tonic-gate #if defined( DOS )
62*7c478bd9Sstevel@tonic-gate #include "msdos.h"
63*7c478bd9Sstevel@tonic-gate #endif /* DOS */
64*7c478bd9Sstevel@tonic-gate 
65*7c478bd9Sstevel@tonic-gate 
66*7c478bd9Sstevel@tonic-gate #ifdef NEEDPROTOS
67*7c478bd9Sstevel@tonic-gate static char ** decode_answer( unsigned char *answer, int len );
68*7c478bd9Sstevel@tonic-gate #else /* NEEDPROTOS */
69*7c478bd9Sstevel@tonic-gate static char **decode_answer();
70*7c478bd9Sstevel@tonic-gate #endif /* NEEDPROTOS */
71*7c478bd9Sstevel@tonic-gate 
72*7c478bd9Sstevel@tonic-gate extern int h_errno;
73*7c478bd9Sstevel@tonic-gate extern char *h_errlist[];
74*7c478bd9Sstevel@tonic-gate 
75*7c478bd9Sstevel@tonic-gate 
76*7c478bd9Sstevel@tonic-gate #define MAX_TO_SORT	32
77*7c478bd9Sstevel@tonic-gate 
78*7c478bd9Sstevel@tonic-gate 
79*7c478bd9Sstevel@tonic-gate /*
80*7c478bd9Sstevel@tonic-gate  * nsldapi_getdxbyname - lookup DNS DX records for domain and return an ordered
81*7c478bd9Sstevel@tonic-gate  *	array.
82*7c478bd9Sstevel@tonic-gate  */
83*7c478bd9Sstevel@tonic-gate char **
nsldapi_getdxbyname(char * domain)84*7c478bd9Sstevel@tonic-gate nsldapi_getdxbyname( char *domain )
85*7c478bd9Sstevel@tonic-gate {
86*7c478bd9Sstevel@tonic-gate     unsigned char	buf[ PACKETSZ ];
87*7c478bd9Sstevel@tonic-gate     char		**dxs;
88*7c478bd9Sstevel@tonic-gate     int			rc;
89*7c478bd9Sstevel@tonic-gate 
90*7c478bd9Sstevel@tonic-gate     LDAPDebug( LDAP_DEBUG_TRACE, "nsldapi_getdxbyname( %s )\n", domain, 0, 0 );
91*7c478bd9Sstevel@tonic-gate 
92*7c478bd9Sstevel@tonic-gate     memset( buf, 0, sizeof( buf ));
93*7c478bd9Sstevel@tonic-gate 
94*7c478bd9Sstevel@tonic-gate     /* XXX not MT safe XXX */
95*7c478bd9Sstevel@tonic-gate     if (( rc = res_search( domain, C_IN, T_TXT, buf, sizeof( buf ))) < 0
96*7c478bd9Sstevel@tonic-gate 		|| ( dxs = decode_answer( buf, rc )) == NULL ) {
97*7c478bd9Sstevel@tonic-gate 	/*
98*7c478bd9Sstevel@tonic-gate 	 * punt:  return list conisting of the original domain name only
99*7c478bd9Sstevel@tonic-gate 	 */
100*7c478bd9Sstevel@tonic-gate 	if (( dxs = (char **)NSLDAPI_MALLOC( 2 * sizeof( char * ))) == NULL ||
101*7c478bd9Sstevel@tonic-gate 		( dxs[ 0 ] = nsldapi_strdup( domain )) == NULL ) {
102*7c478bd9Sstevel@tonic-gate 	    if ( dxs != NULL ) {
103*7c478bd9Sstevel@tonic-gate 		NSLDAPI_FREE( dxs );
104*7c478bd9Sstevel@tonic-gate 	    }
105*7c478bd9Sstevel@tonic-gate 	    dxs = NULL;
106*7c478bd9Sstevel@tonic-gate 	} else {
107*7c478bd9Sstevel@tonic-gate 	    dxs[ 1 ] = NULL;
108*7c478bd9Sstevel@tonic-gate 	}
109*7c478bd9Sstevel@tonic-gate     }
110*7c478bd9Sstevel@tonic-gate 
111*7c478bd9Sstevel@tonic-gate     return( dxs );
112*7c478bd9Sstevel@tonic-gate }
113*7c478bd9Sstevel@tonic-gate 
114*7c478bd9Sstevel@tonic-gate 
115*7c478bd9Sstevel@tonic-gate static char **
decode_answer(unsigned char * answer,int len)116*7c478bd9Sstevel@tonic-gate decode_answer( unsigned char *answer, int len )
117*7c478bd9Sstevel@tonic-gate {
118*7c478bd9Sstevel@tonic-gate     HEADER		*hp;
119*7c478bd9Sstevel@tonic-gate     char		buf[ 256 ], **dxs;
120*7c478bd9Sstevel@tonic-gate     unsigned char	*eom, *p;
121*7c478bd9Sstevel@tonic-gate     int			ancount, err, rc, type, class, dx_count, rr_len;
122*7c478bd9Sstevel@tonic-gate     int			dx_pref[ MAX_TO_SORT ];
123*7c478bd9Sstevel@tonic-gate 
124*7c478bd9Sstevel@tonic-gate #ifdef LDAP_DEBUG
125*7c478bd9Sstevel@tonic-gate     if ( ldap_debug & LDAP_DEBUG_PACKETS ) {
126*7c478bd9Sstevel@tonic-gate /*	__p_query( answer );	*/
127*7c478bd9Sstevel@tonic-gate     }
128*7c478bd9Sstevel@tonic-gate #endif /* LDAP_DEBUG */
129*7c478bd9Sstevel@tonic-gate 
130*7c478bd9Sstevel@tonic-gate     dxs = NULL;
131*7c478bd9Sstevel@tonic-gate     hp = (HEADER *)answer;
132*7c478bd9Sstevel@tonic-gate     eom = answer + len;
133*7c478bd9Sstevel@tonic-gate 
134*7c478bd9Sstevel@tonic-gate     if ( ntohs( hp->qdcount ) != 1 ) {
135*7c478bd9Sstevel@tonic-gate 	h_errno = NO_RECOVERY;
136*7c478bd9Sstevel@tonic-gate 	return( NULL );
137*7c478bd9Sstevel@tonic-gate     }
138*7c478bd9Sstevel@tonic-gate 
139*7c478bd9Sstevel@tonic-gate     ancount = ntohs( hp->ancount );
140*7c478bd9Sstevel@tonic-gate     if ( ancount < 1 ) {
141*7c478bd9Sstevel@tonic-gate 	h_errno = NO_DATA;
142*7c478bd9Sstevel@tonic-gate 	return( NULL );
143*7c478bd9Sstevel@tonic-gate     }
144*7c478bd9Sstevel@tonic-gate 
145*7c478bd9Sstevel@tonic-gate     /*
146*7c478bd9Sstevel@tonic-gate      * skip over the query
147*7c478bd9Sstevel@tonic-gate      */
148*7c478bd9Sstevel@tonic-gate     p = answer + HFIXEDSZ;
149*7c478bd9Sstevel@tonic-gate     if (( rc = dn_expand( answer, eom, p, buf, sizeof( buf ))) < 0 ) {
150*7c478bd9Sstevel@tonic-gate 	h_errno = NO_RECOVERY;
151*7c478bd9Sstevel@tonic-gate 	return( NULL );
152*7c478bd9Sstevel@tonic-gate     }
153*7c478bd9Sstevel@tonic-gate     p += ( rc + QFIXEDSZ );
154*7c478bd9Sstevel@tonic-gate 
155*7c478bd9Sstevel@tonic-gate     /*
156*7c478bd9Sstevel@tonic-gate      * pull out the answers we are interested in
157*7c478bd9Sstevel@tonic-gate      */
158*7c478bd9Sstevel@tonic-gate     err = dx_count = 0;
159*7c478bd9Sstevel@tonic-gate     while ( ancount > 0 && err == 0 && p < eom ) {
160*7c478bd9Sstevel@tonic-gate 	if (( rc = dn_expand( answer, eom, p, buf, sizeof( buf ))) < 0 ) {
161*7c478bd9Sstevel@tonic-gate 	    err = NO_RECOVERY;
162*7c478bd9Sstevel@tonic-gate 	    continue;
163*7c478bd9Sstevel@tonic-gate 	}
164*7c478bd9Sstevel@tonic-gate 	p += rc;	/* skip over name */
165*7c478bd9Sstevel@tonic-gate 	type = _getshort( p );
166*7c478bd9Sstevel@tonic-gate 	p += INT16SZ;
167*7c478bd9Sstevel@tonic-gate 	class = _getshort( p );
168*7c478bd9Sstevel@tonic-gate 	p += INT16SZ;
169*7c478bd9Sstevel@tonic-gate 	p += INT32SZ;		/* skip over TTL */
170*7c478bd9Sstevel@tonic-gate 	rr_len = _getshort( p );
171*7c478bd9Sstevel@tonic-gate 	p += INT16SZ;
172*7c478bd9Sstevel@tonic-gate 	if ( class == C_IN && type == T_TXT ) {
173*7c478bd9Sstevel@tonic-gate 	    int 	i, n, pref, txt_len;
174*7c478bd9Sstevel@tonic-gate 	    char	*q, *r;
175*7c478bd9Sstevel@tonic-gate 
176*7c478bd9Sstevel@tonic-gate 	    q = (char *)p;
177*7c478bd9Sstevel@tonic-gate 	    while ( q < (char *)p + rr_len && err == 0 ) {
178*7c478bd9Sstevel@tonic-gate 		if ( *q >= 3 && strncasecmp( q + 1, "dx:", 3 ) == 0 ) {
179*7c478bd9Sstevel@tonic-gate 		    txt_len = *q - 3;
180*7c478bd9Sstevel@tonic-gate 		    r = q + 4;
181*7c478bd9Sstevel@tonic-gate 		    while ( isspace( *r )) {
182*7c478bd9Sstevel@tonic-gate 			++r;
183*7c478bd9Sstevel@tonic-gate 			--txt_len;
184*7c478bd9Sstevel@tonic-gate 		    }
185*7c478bd9Sstevel@tonic-gate 		    pref = 0;
186*7c478bd9Sstevel@tonic-gate 		    while ( isdigit( *r )) {
187*7c478bd9Sstevel@tonic-gate 			pref *= 10;
188*7c478bd9Sstevel@tonic-gate 			pref += ( *r - '0' );
189*7c478bd9Sstevel@tonic-gate 			++r;
190*7c478bd9Sstevel@tonic-gate 			--txt_len;
191*7c478bd9Sstevel@tonic-gate 		    }
192*7c478bd9Sstevel@tonic-gate 		    if ( dx_count < MAX_TO_SORT - 1 ) {
193*7c478bd9Sstevel@tonic-gate 			dx_pref[ dx_count ] = pref;
194*7c478bd9Sstevel@tonic-gate 		    }
195*7c478bd9Sstevel@tonic-gate 		    while ( isspace( *r )) {
196*7c478bd9Sstevel@tonic-gate 			++r;
197*7c478bd9Sstevel@tonic-gate 			--txt_len;
198*7c478bd9Sstevel@tonic-gate 		    }
199*7c478bd9Sstevel@tonic-gate 		    if ( dx_count == 0 ) {
200*7c478bd9Sstevel@tonic-gate 			dxs = (char **)NSLDAPI_MALLOC( 2 * sizeof( char * ));
201*7c478bd9Sstevel@tonic-gate 		    } else {
202*7c478bd9Sstevel@tonic-gate 			dxs = (char **)NSLDAPI_REALLOC( dxs,
203*7c478bd9Sstevel@tonic-gate 				( dx_count + 2 ) * sizeof( char * ));
204*7c478bd9Sstevel@tonic-gate 		    }
205*7c478bd9Sstevel@tonic-gate 		    if ( dxs == NULL || ( dxs[ dx_count ] =
206*7c478bd9Sstevel@tonic-gate 			    (char *)NSLDAPI_CALLOC( 1, txt_len + 1 ))
207*7c478bd9Sstevel@tonic-gate 			    == NULL ) {
208*7c478bd9Sstevel@tonic-gate 			err = NO_RECOVERY;
209*7c478bd9Sstevel@tonic-gate 			continue;
210*7c478bd9Sstevel@tonic-gate 		    }
211*7c478bd9Sstevel@tonic-gate 		    SAFEMEMCPY( dxs[ dx_count ], r, txt_len );
212*7c478bd9Sstevel@tonic-gate 		    dxs[ ++dx_count ] = NULL;
213*7c478bd9Sstevel@tonic-gate 		}
214*7c478bd9Sstevel@tonic-gate 		q += ( *q + 1 );	/* move past last TXT record */
215*7c478bd9Sstevel@tonic-gate 	    }
216*7c478bd9Sstevel@tonic-gate 	}
217*7c478bd9Sstevel@tonic-gate 	p += rr_len;
218*7c478bd9Sstevel@tonic-gate     }
219*7c478bd9Sstevel@tonic-gate 
220*7c478bd9Sstevel@tonic-gate     if ( err == 0 ) {
221*7c478bd9Sstevel@tonic-gate 	if ( dx_count == 0 ) {
222*7c478bd9Sstevel@tonic-gate 	    err = NO_DATA;
223*7c478bd9Sstevel@tonic-gate 	} else {
224*7c478bd9Sstevel@tonic-gate 	    /*
225*7c478bd9Sstevel@tonic-gate 	     * sort records based on associated preference value
226*7c478bd9Sstevel@tonic-gate 	     */
227*7c478bd9Sstevel@tonic-gate 	    int		i, j, sort_count, tmp_pref;
228*7c478bd9Sstevel@tonic-gate 	    char	*tmp_dx;
229*7c478bd9Sstevel@tonic-gate 
230*7c478bd9Sstevel@tonic-gate 	    sort_count = ( dx_count < MAX_TO_SORT ) ? dx_count : MAX_TO_SORT;
231*7c478bd9Sstevel@tonic-gate 	    for ( i = 0; i < sort_count; ++i ) {
232*7c478bd9Sstevel@tonic-gate 		for ( j = i + 1; j < sort_count; ++j ) {
233*7c478bd9Sstevel@tonic-gate 		    if ( dx_pref[ i ] > dx_pref[ j ] ) {
234*7c478bd9Sstevel@tonic-gate 			tmp_pref = dx_pref[ i ];
235*7c478bd9Sstevel@tonic-gate 			dx_pref[ i ] = dx_pref[ j ];
236*7c478bd9Sstevel@tonic-gate 			dx_pref[ j ] = tmp_pref;
237*7c478bd9Sstevel@tonic-gate 			tmp_dx = dxs[ i ];
238*7c478bd9Sstevel@tonic-gate 			dxs[ i ] = dxs[ j ];
239*7c478bd9Sstevel@tonic-gate 			dxs[ j ] = tmp_dx;
240*7c478bd9Sstevel@tonic-gate 		    }
241*7c478bd9Sstevel@tonic-gate 		}
242*7c478bd9Sstevel@tonic-gate 	    }
243*7c478bd9Sstevel@tonic-gate 	}
244*7c478bd9Sstevel@tonic-gate     }
245*7c478bd9Sstevel@tonic-gate 
246*7c478bd9Sstevel@tonic-gate     h_errno = err;
247*7c478bd9Sstevel@tonic-gate     return( dxs );
248*7c478bd9Sstevel@tonic-gate }
249*7c478bd9Sstevel@tonic-gate 
250*7c478bd9Sstevel@tonic-gate #endif /* LDAP_DNS */
251