1 #include <errno.h> 2 #include <string.h> 3 #include <sys/types.h> 4 #include <netinet/in.h> 5 6 #include "utils.h" 7 8 static __inline__ u_int16_t dn_ntohs(u_int16_t addr) 9 { 10 union { 11 u_int8_t byte[2]; 12 u_int16_t word; 13 } u; 14 15 u.word = addr; 16 return ((u_int16_t)u.byte[0]) | (((u_int16_t)u.byte[1]) << 8); 17 } 18 19 static __inline__ int do_digit(char *str, u_int16_t *addr, u_int16_t scale, size_t *pos, size_t len, int *started) 20 { 21 u_int16_t tmp = *addr / scale; 22 23 if (*pos == len) 24 return 1; 25 26 if (((tmp) > 0) || *started || (scale == 1)) { 27 *str = tmp + '0'; 28 *started = 1; 29 (*pos)++; 30 *addr -= (tmp * scale); 31 } 32 33 return 0; 34 } 35 36 37 static const char *dnet_ntop1(const struct dn_naddr *dna, char *str, size_t len) 38 { 39 u_int16_t addr, area; 40 size_t pos = 0; 41 int started = 0; 42 43 memcpy(&addr, dna->a_addr, sizeof(addr)); 44 addr = dn_ntohs(addr); 45 area = addr >> 10; 46 47 if (dna->a_len != 2) 48 return NULL; 49 50 addr &= 0x03ff; 51 52 if (len == 0) 53 return str; 54 55 if (do_digit(str + pos, &area, 10, &pos, len, &started)) 56 return str; 57 58 if (do_digit(str + pos, &area, 1, &pos, len, &started)) 59 return str; 60 61 if (pos == len) 62 return str; 63 64 *(str + pos) = '.'; 65 pos++; 66 started = 0; 67 68 if (do_digit(str + pos, &addr, 1000, &pos, len, &started)) 69 return str; 70 71 if (do_digit(str + pos, &addr, 100, &pos, len, &started)) 72 return str; 73 74 if (do_digit(str + pos, &addr, 10, &pos, len, &started)) 75 return str; 76 77 if (do_digit(str + pos, &addr, 1, &pos, len, &started)) 78 return str; 79 80 if (pos == len) 81 return str; 82 83 *(str + pos) = 0; 84 85 return str; 86 } 87 88 89 const char *dnet_ntop(int af, const void *addr, char *str, size_t len) 90 { 91 switch(af) { 92 case AF_DECnet: 93 errno = 0; 94 return dnet_ntop1((struct dn_naddr *)addr, str, len); 95 default: 96 errno = EAFNOSUPPORT; 97 } 98 99 return NULL; 100 } 101