• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-WNDR4500v2-V1.0.0.60_1.0.38/ap/gpl/timemachine/netatalk-2.2.5/libatalk/nbp/
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
40int 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
221lookup_err:
222    netddp_close(s);
223    return -1;
224}
225