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