]> arthur.barton.de Git - netatalk.git/blob - libatalk/nbp/nbp_lkup.c
Remove bdb env on exit
[netatalk.git] / libatalk / nbp / nbp_lkup.c
1 /*
2  * $Id: nbp_lkup.c,v 1.5 2009-10-13 22:55:37 didg Exp $
3  *
4  * Copyright (c) 1990,1997 Regents of The University of Michigan.
5  * All Rights Reserved. See COPYRIGHT.
6  */
7
8 #ifdef HAVE_CONFIG_H
9 #include "config.h"
10 #endif /* HAVE_CONFIG_H */
11
12 #include <string.h>
13 #include <errno.h>
14 #include <signal.h>
15
16 #include <sys/types.h>
17 #include <sys/param.h>
18 #include <sys/socket.h>
19 #include <sys/time.h>
20
21 #include <netatalk/endian.h>
22 #include <netatalk/at.h>
23 #include <netatalk/ddp.h>
24 #include <atalk/compat.h>
25 #include <atalk/nbp.h>
26 #include <atalk/netddp.h>
27 #include <atalk/ddp.h>
28
29 #ifdef HAVE_NETDB_H
30 #include <netdb.h>
31 #endif /* HAVE_NETDB_H */
32
33 #include  "nbp_conf.h"
34
35 /* FIXME/SOCKLEN_T: socklen_t is a unix98 feature. */
36 #ifndef SOCKLEN_T
37 #define SOCKLEN_T unsigned int
38 #endif /* ! SOCKLEN_T */
39
40 int nbp_lookup( const char *obj, const char *type, const char *zone, struct nbpnve *nn,
41     int                 nncnt,
42     const struct at_addr *ataddr)
43 {
44     struct sockaddr_at  addr, from;
45     struct timeval      tv, tv_begin, tv_end;
46     fd_set              fds;
47     struct nbpnve       nve;
48     struct nbphdr       nh;
49     struct nbptuple     nt;
50     struct servent      *se;
51     char                *data = nbp_send;
52     SOCKLEN_T           namelen;
53     int                 s, cnt, tries, sc, cc, i, c;
54
55     memset(&addr, 0, sizeof(addr));
56     memset(&from, 0, sizeof(from));
57     if (ataddr) 
58       memcpy(&addr.sat_addr, ataddr, sizeof(struct at_addr));
59     if ((s = netddp_open(&addr, &from)) < 0)
60       return -1;
61
62     *data++ = DDPTYPE_NBP;
63 #ifdef MACOSX_SERVER
64     nh.nh_op = from.sat_addr.s_node ? NBPOP_BRRQ : NBPOP_LKUP;
65 #else /* MACOSX_SERVER */
66     nh.nh_op = NBPOP_BRRQ;
67 #endif /* MACOSX_SERVER */
68
69     nh.nh_cnt = 1;
70     nh.nh_id = ++nbp_id;
71     memcpy( data, &nh, SZ_NBPHDR );
72     data += SZ_NBPHDR;
73
74     memset(&nt, 0, sizeof(nt));
75     nt.nt_net = addr.sat_addr.s_net;
76     nt.nt_node = addr.sat_addr.s_node;
77     nt.nt_port = addr.sat_port;
78
79     memcpy( data, &nt, SZ_NBPTUPLE);
80     data += SZ_NBPTUPLE;
81
82     if ( obj ) {
83         if (( cc = strlen( obj )) > NBPSTRLEN ) goto lookup_err;
84         *data++ = cc;
85         memcpy( data, obj, cc );
86         data += cc;
87     } else {
88         *data++ = 1;
89         *data++ = '='; /* match anything */
90     }
91
92     if ( type ) {
93         if (( cc = strlen( type )) > NBPSTRLEN ) goto lookup_err;
94         *data++ = cc;
95         memcpy( data, type, cc );
96         data += cc;
97     } else {
98         *data++ = 1;
99         *data++ = '='; /* match anything */
100     }
101
102     if ( zone ) {
103         if (( cc = strlen( zone )) > NBPSTRLEN ) goto lookup_err;
104         *data++ = cc;
105         memcpy( data, zone, cc );
106         data += cc;
107     } else {
108         *data++ = 1;
109         *data++ = '*'; /* default zone */
110     }
111
112     if ( nbp_port == 0 ) {
113       if (( se = getservbyname( "nbp", "ddp" )) == NULL ) {
114                     nbp_port = 2;
115       } else {
116                     nbp_port = ntohs( se->s_port );
117       }
118     }
119
120 #ifdef MACOSX_SERVER
121     if (from.sat_addr.s_node) {
122       memcpy(&addr.sat_addr, &from.sat_addr, sizeof(addr.sat_addr));
123     } else {
124       addr.sat_addr.s_net = ATADDR_ANYNET;
125       addr.sat_addr.s_node = ATADDR_BCAST;
126     }
127 #endif /* MACOSX_SERVER */
128     addr.sat_port = nbp_port;
129
130     cnt = 0;
131     tries = 3;
132     sc = data - nbp_send;
133     while ( tries > 0 ) {
134         if ( netddp_sendto( s, nbp_send, sc, 0, (struct sockaddr *)&addr,
135                 sizeof( struct sockaddr_at )) < 0 ) {
136             goto lookup_err;
137         }
138
139         tv.tv_sec = 2L;
140         tv.tv_usec = 0;
141
142         for (;;) {
143             FD_ZERO( &fds );
144             FD_SET( s, &fds );
145             if ( gettimeofday( &tv_begin, NULL ) < 0 ) {
146                 goto lookup_err;
147             }
148             if (( c = select( s + 1, &fds, NULL, NULL, &tv )) < 0 ) {
149                 goto lookup_err;
150             }
151             if ( c == 0 || FD_ISSET( s, &fds ) == 0 ) {
152                 break;
153             }
154             if ( gettimeofday( &tv_end, NULL ) < 0 ) {
155                 goto lookup_err;
156             }
157             if ( tv_begin.tv_usec > tv_end.tv_sec ) {
158                 tv_end.tv_usec += 1000000;
159                 tv_end.tv_sec -= 1;
160             }
161             if (( tv.tv_usec -= ( tv_end.tv_usec - tv_begin.tv_usec )) < 0 ) {
162                 tv.tv_usec += 1000000;
163                 tv.tv_sec -= 1;
164             }
165             if (( tv.tv_sec -= ( tv_end.tv_sec - tv_begin.tv_sec )) < 0 ) {
166                 break;
167             }
168
169             namelen = sizeof( struct sockaddr_at );
170             if (( cc = netddp_recvfrom( s, nbp_recv, sizeof( nbp_recv ), 0,
171                     (struct sockaddr *)&from, &namelen )) < 0 ) {
172                 goto lookup_err;
173             }
174
175             data = nbp_recv;
176             if ( *data++ != DDPTYPE_NBP ) {
177                 continue;
178             }
179             cc--;
180
181             memcpy( &nh, data, SZ_NBPHDR );
182             data += SZ_NBPHDR;
183             if ( nh.nh_op != NBPOP_LKUPREPLY ) {
184                 continue;
185             }
186             cc -= SZ_NBPHDR;
187
188             while (( i = nbp_parse( data, &nve, cc )) >= 0 ) {
189                 data += cc - i;
190                 cc = i;
191                 /*
192                  * Check to see if nve is already in nn. If not,
193                  * put it in, and increment cnt.
194                  */
195                 for ( i = 0; i < cnt; i++ ) {
196                     if ( nbp_match( &nve, &nn[ i ],
197                             NBPMATCH_NOZONE|NBPMATCH_NOGLOB )) {
198                         break;
199                     }
200                 }
201                 if ( i == cnt ) {
202                     nn[ cnt++ ] = nve;
203                 }
204                 if ( cnt == nncnt ) {
205                     tries = 0;
206                     break;
207                 }
208             }
209             if ( cnt == nncnt ) {
210                 tries = 0;
211                 break;
212             }
213         }
214         tries--;
215     }
216
217     netddp_close(s);
218     errno = 0;
219     return( cnt );
220
221 lookup_err:
222     netddp_close(s);
223     return -1;
224 }