]> arthur.barton.de Git - netatalk.git/blob - libatalk/util/atalk_addr.c
751c68e007b5c9f6ffc66671f5ea99e0949e0490
[netatalk.git] / libatalk / util / atalk_addr.c
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
29 int 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 }