Home | History | Annotate | Download | only in lib
      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