1#ifdef HAVE_CONFIG_H 2#include "config.h" 3#endif 4 5#include <sys/types.h> 6#include <netatalk/at.h> 7#include <netatalk/endian.h> 8#include <atalk/util.h> 9#include <ctype.h> 10 11/* 12 * Check whether "cp" is a valid ascii representation 13 * of an AppleTalk address and convert to a binary address. 14 * Examples of accepted forms are (in decimal, net of 4321, 15 * node of 65): 16 * 17 * 4321.65 18 * 0x10E1.41 19 * 16.225.65 20 * 0x10.E1.41 21 * 22 * If hex is used, and the first digit is one of A-F, the leading 23 * 0x is redundant. Returns 1 if the address is valid, 0 if not. 24 * 25 * Unlike Internet addresses, AppleTalk addresses can have leading 26 * 0's. This means that we can't support octal addressing. 27 */ 28 29int atalk_aton(char *cp, struct at_addr *addr) 30{ 31 u_int32_t val, base, n; 32 char c; 33 34 val = 0; base = 10; 35 if ( *cp == '0' && ( *++cp == 'x' || *cp == 'X' )) { 36 base = 16, cp++; 37 } 38 if ( !isdigit( *cp ) && isxdigit( *cp )) { 39 base = 16; 40 } 41 42 for ( n = 0;; n++ ) { 43 while (( c = *cp ) != '\0') { 44 if ( isascii( c ) && isdigit( c )) { 45 val = (val * base) + (c - '0'); 46 cp++; 47 continue; 48 } 49 50 if ( base == 16 && isascii( c ) && isxdigit( c )) { 51 val = ( val << 4 ) + ( c + 10 - ( islower( c ) ? 'a' : 'A' )); 52 cp++; 53 continue; 54 } 55 break; 56 } 57 58 if ( c != '.' && c != '\0' ) { 59 return( 0 ); 60 } 61 62 switch ( n ) { 63 case 0: 64 if ( addr ) { 65 if ( val > 65535 ) { 66 return( 0 ); 67 } 68 addr->s_net = val; 69 } 70 if ( *cp++ ) { 71 val = 0; 72 } else { 73 break; 74 } 75 continue; 76 77 case 2: 78 if ( addr ) { 79 if ( addr->s_net > 255 ) { 80 return( 0 ); 81 } 82 addr->s_net <<= 8; 83 addr->s_net += addr->s_node; 84 } 85 /*FALLTHROUGH*/ 86 87 case 1: 88 if ( addr ) { 89 if ( val > 255 ) { 90 return( 0 ); 91 } 92 addr->s_node = val; 93 } 94 if ( *cp++ ) { 95 val = 0; 96 } else { 97 break; 98 } 99 continue; 100 101 default: 102 return( 0 ); 103 } 104 break; 105 } 106 107 if ( n < 1 ) { 108 return( 0 ); 109 } 110 if ( addr ) { 111 addr->s_net = htons( addr->s_net ); 112 } 113 return (1); 114} 115