]> arthur.barton.de Git - netatalk.git/blob - libatalk/nbp/nbp_lkup.c
Trunk-BP: includes cleanup.
[netatalk.git] / libatalk / nbp / nbp_lkup.c
1 /*
2  * $Id: nbp_lkup.c,v 1.3.2.1 2002-02-08 00:04:49 srittau 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( obj, type, zone, nn, nncnt, ataddr )
41     const char          *obj, *type, *zone;
42     struct nbpnve       *nn;
43     int                 nncnt;
44     const struct at_addr *ataddr;
45 {
46     struct sockaddr_at  addr, from;
47     struct timeval      tv, tv_begin, tv_end;
48     fd_set              fds;
49     struct nbpnve       nve;
50     struct nbphdr       nh;
51     struct nbptuple     nt;
52     struct servent      *se;
53     char                *data = nbp_send;
54     SOCKLEN_T           namelen;
55     int                 s, cnt, tries, sc, cc, i, c;
56
57     memset(&addr, 0, sizeof(addr));
58     memset(&from, 0, sizeof(from));
59     if (ataddr) 
60       memcpy(&addr.sat_addr, ataddr, sizeof(struct at_addr));
61     if ((s = netddp_open(&addr, &from)) < 0)
62       return -1;
63
64     *data++ = DDPTYPE_NBP;
65 #ifdef MACOSX_SERVER
66     nh.nh_op = from.sat_addr.s_node ? NBPOP_BRRQ : NBPOP_LKUP;
67 #else /* MACOSX_SERVER */
68     nh.nh_op = NBPOP_BRRQ;
69 #endif /* MACOSX_SERVER */
70
71     nh.nh_cnt = 1;
72     nh.nh_id = ++nbp_id;
73     memcpy( data, &nh, SZ_NBPHDR );
74     data += SZ_NBPHDR;
75
76     memset(&nt, 0, sizeof(nt));
77     nt.nt_net = addr.sat_addr.s_net;
78     nt.nt_node = addr.sat_addr.s_node;
79     nt.nt_port = addr.sat_port;
80
81     memcpy( data, &nt, SZ_NBPTUPLE);
82     data += SZ_NBPTUPLE;
83
84     if ( obj ) {
85         if (( cc = strlen( obj )) > NBPSTRLEN ) goto lookup_err;
86         *data++ = cc;
87         memcpy( data, obj, cc );
88         data += cc;
89     } else {
90         *data++ = 1;
91         *data++ = '='; /* match anything */
92     }
93
94     if ( type ) {
95         if (( cc = strlen( type )) > NBPSTRLEN ) goto lookup_err;
96         *data++ = cc;
97         memcpy( data, type, cc );
98         data += cc;
99     } else {
100         *data++ = 1;
101         *data++ = '='; /* match anything */
102     }
103
104     if ( zone ) {
105         if (( cc = strlen( zone )) > NBPSTRLEN ) goto lookup_err;
106         *data++ = cc;
107         memcpy( data, zone, cc );
108         data += cc;
109     } else {
110         *data++ = 1;
111         *data++ = '*'; /* default zone */
112     }
113
114     if ( nbp_port == 0 ) {
115       if (( se = getservbyname( "nbp", "ddp" )) == NULL ) {
116                     nbp_port = 2;
117       } else {
118                     nbp_port = ntohs( se->s_port );
119       }
120     }
121
122 #ifdef MACOSX_SERVER
123     if (from.sat_addr.s_node) {
124       memcpy(&addr.sat_addr, &from.sat_addr, sizeof(addr.sat_addr));
125     } else {
126       addr.sat_addr.s_net = ATADDR_ANYNET;
127       addr.sat_addr.s_node = ATADDR_BCAST;
128     }
129 #endif /* MACOSX_SERVER */
130     addr.sat_port = nbp_port;
131
132     cnt = 0;
133     tries = 3;
134     sc = data - nbp_send;
135     while ( tries > 0 ) {
136         if ( netddp_sendto( s, nbp_send, sc, 0, (struct sockaddr *)&addr,
137                 sizeof( struct sockaddr_at )) < 0 ) {
138             goto lookup_err;
139         }
140
141         tv.tv_sec = 2L;
142         tv.tv_usec = 0;
143
144         for (;;) {
145             FD_ZERO( &fds );
146             FD_SET( s, &fds );
147             if ( gettimeofday( &tv_begin, NULL ) < 0 ) {
148                 goto lookup_err;
149             }
150             if (( c = select( s + 1, &fds, NULL, NULL, &tv )) < 0 ) {
151                 goto lookup_err;
152             }
153             if ( c == 0 || FD_ISSET( s, &fds ) == 0 ) {
154                 break;
155             }
156             if ( gettimeofday( &tv_end, NULL ) < 0 ) {
157                 goto lookup_err;
158             }
159             if ( tv_begin.tv_usec > tv_end.tv_sec ) {
160                 tv_end.tv_usec += 1000000;
161                 tv_end.tv_sec -= 1;
162             }
163             if (( tv.tv_usec -= ( tv_end.tv_usec - tv_begin.tv_usec )) < 0 ) {
164                 tv.tv_usec += 1000000;
165                 tv.tv_sec -= 1;
166             }
167             if (( tv.tv_sec -= ( tv_end.tv_sec - tv_begin.tv_sec )) < 0 ) {
168                 break;
169             }
170
171             namelen = sizeof( struct sockaddr_at );
172             if (( cc = netddp_recvfrom( s, nbp_recv, sizeof( nbp_recv ), 0,
173                     (struct sockaddr *)&from, &namelen )) < 0 ) {
174                 goto lookup_err;
175             }
176
177             data = nbp_recv;
178             if ( *data++ != DDPTYPE_NBP ) {
179                 continue;
180             }
181             cc--;
182
183             memcpy( &nh, data, SZ_NBPHDR );
184             data += SZ_NBPHDR;
185             if ( nh.nh_op != NBPOP_LKUPREPLY ) {
186                 continue;
187             }
188             cc -= SZ_NBPHDR;
189
190             while (( i = nbp_parse( data, &nve, cc )) >= 0 ) {
191                 data += cc - i;
192                 cc = i;
193                 /*
194                  * Check to see if nve is already in nn. If not,
195                  * put it in, and increment cnt.
196                  */
197                 for ( i = 0; i < cnt; i++ ) {
198                     if ( nbp_match( &nve, &nn[ i ],
199                             NBPMATCH_NOZONE|NBPMATCH_NOGLOB )) {
200                         break;
201                     }
202                 }
203                 if ( i == cnt ) {
204                     nn[ cnt++ ] = nve;
205                 }
206                 if ( cnt == nncnt ) {
207                     tries = 0;
208                     break;
209                 }
210             }
211             if ( cnt == nncnt ) {
212                 tries = 0;
213                 break;
214             }
215         }
216         tries--;
217     }
218
219     netddp_close(s);
220     errno = 0;
221     return( cnt );
222
223 lookup_err:
224     netddp_close(s);
225     return -1;
226 }