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