1/* 2 * $Id: getzones.c,v 1.9 2009-10-14 01:38:28 didg Exp $ 3 */ 4 5#ifdef HAVE_CONFIG_H 6#include "config.h" 7#endif /* HAVE_CONFIG_H */ 8 9#include <sys/types.h> 10#include <sys/socket.h> 11#include <sys/param.h> 12#include <sys/uio.h> 13#include <sys/time.h> 14#ifdef HAVE_UNISTD_H 15#include <unistd.h> 16#endif /* HAVE_UNISTD_H */ 17#ifdef HAVE_NETDB_H 18#include <netdb.h> 19#endif /* HAVE_NETDB_H */ 20#include <stdio.h> 21#include <string.h> 22#include <stdlib.h> 23#include <netatalk/endian.h> 24#include <netatalk/at.h> 25#include <atalk/atp.h> 26#include <atalk/util.h> 27#include <atalk/unicode.h> 28#include <atalk/zip.h> 29 30static void print_zones(short n, char *buf); 31 32static void usage( char *s) 33{ 34 fprintf( stderr, "usage:\t%s [-m | -l] [address]\n", s ); 35 exit( 1 ); 36} 37 38int main( int argc, char *argv[]) 39{ 40 struct atp_handle *ah; 41 struct atp_block atpb; 42 struct sockaddr_at saddr; 43 struct servent *se; 44 char reqdata[4], buf[ ATP_MAXDATA ]; 45 struct iovec iov; 46 short temp, index = 0; 47 int c, myzoneflg = 0, localzonesflg = 0, errflg = 0; 48 extern int optind; 49 50 reqdata[ 0 ] = ZIPOP_GETZONELIST; 51 52 while (( c = getopt( argc, argv, "ml" )) != EOF ) { 53 switch (c) { 54 case 'm': 55 if ( localzonesflg ) { 56 ++errflg; 57 } 58 ++myzoneflg; 59 reqdata[ 0 ] = ZIPOP_GETMYZONE; 60 break; 61 case 'l': 62 if ( myzoneflg ) { 63 ++errflg; 64 } 65 ++localzonesflg; 66 reqdata[ 0 ] = ZIPOP_GETLOCALZONES; 67 break; 68 default: 69 ++errflg; 70 } 71 } 72 73 if ( errflg || argc - optind > 1 ) { 74 usage( argv[ 0 ] ); 75 } 76 77 memset( &saddr, 0, sizeof( struct sockaddr_at )); 78#ifdef BSD4_4 79 saddr.sat_len = sizeof( struct sockaddr_at ); 80#endif /* BSD4_4 */ 81 saddr.sat_family = AF_APPLETALK; 82 if (( se = getservbyname( "zip", "ddp" )) == NULL ) 83 saddr.sat_port = 6; 84 else 85 saddr.sat_port = ntohs( se->s_port ); 86 87 if ( argc == optind ) { 88 saddr.sat_addr.s_net = ATADDR_ANYNET; 89 saddr.sat_addr.s_node = ATADDR_ANYNODE; 90 } else { 91 if ( !atalk_aton( argv[ optind ], &saddr.sat_addr )) { 92 fprintf( stderr, "Bad address.\n" ); 93 exit( 1 ); 94 } 95 } 96 97 if (( ah = atp_open( ATADDR_ANYPORT, &saddr.sat_addr )) == NULL ) { 98 perror( "atp_open" ); 99 exit( 1 ); 100 } 101 102 index = ( myzoneflg ? 0 : 1 ); 103 reqdata[1] = 0; 104 105 do { 106 atpb.atp_saddr = &saddr; 107 temp = htons( index ); 108 memcpy( reqdata + 2, &temp, 2 ); 109 atpb.atp_sreqdata = reqdata; 110 atpb.atp_sreqdlen = 4; 111 atpb.atp_sreqto = 2; 112 atpb.atp_sreqtries = 5; 113 114 /* send getzone request zones (or get my zone) 115 */ 116 if ( atp_sreq( ah, &atpb, 1, 0 ) < 0 ) { 117 perror( "atp_sreq" ); 118 exit( 1 ); 119 } 120 121 iov.iov_base = buf; 122 iov.iov_len = ATP_MAXDATA; 123 atpb.atp_rresiov = &iov; 124 atpb.atp_rresiovcnt = 1; 125 126 if ( atp_rresp( ah, &atpb ) < 0 ) { 127 perror( "atp_rresp" ); 128 exit( 1 ); 129 } 130 131 memcpy( &temp, (char *) iov.iov_base + 2, 2 ); 132 temp = ntohs( temp ); 133 print_zones( temp, (char *) iov.iov_base+4 ); 134 index += temp; 135 } while ( !myzoneflg && !((char *)iov.iov_base)[ 0 ] ); 136 137 if ( atp_close( ah ) != 0 ) { 138 perror( "atp_close" ); 139 exit( 1 ); 140 } 141 142 exit( 0 ); 143} 144 145 146/* 147 * n: number of zones in this packet 148 * buf: zone length/name pairs 149 */ 150static void print_zones( short n, char *buf ) 151{ 152 size_t zone_len; 153 char *zone; 154 155 for ( ; n--; buf += (*buf) + 1 ) { 156 157 if ((size_t)(-1) == (zone_len = convert_string_allocate( CH_MAC, 158 CH_UNIX, buf+1, *buf, &zone)) ) { 159 zone_len = *buf; 160 if (( zone = strdup(buf+1)) == NULL ) { 161 perror( "strdup" ); 162 exit( 1 ); 163 } 164 } 165 166 printf( "%.*s\n", (int)zone_len, zone ); 167 168 free(zone); 169 } 170} 171