diff options
author | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
---|---|---|
committer | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
commit | e5888a1ffdae813d7575f5fb02275c6bb07e5199 (patch) | |
tree | d8d51eac403f07814b9e936eed0c9a79195e2450 /sys/src/9/ip/eipconvtest.c |
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/9/ip/eipconvtest.c')
-rwxr-xr-x | sys/src/9/ip/eipconvtest.c | 152 |
1 files changed, 152 insertions, 0 deletions
diff --git a/sys/src/9/ip/eipconvtest.c b/sys/src/9/ip/eipconvtest.c new file mode 100755 index 000000000..06b0f9b50 --- /dev/null +++ b/sys/src/9/ip/eipconvtest.c @@ -0,0 +1,152 @@ +#include <u.h> +#include <libc.h> + +enum +{ + Isprefix= 16, +}; + +uchar prefixvals[256] = +{ +[0x00] 0 | Isprefix, +[0x80] 1 | Isprefix, +[0xC0] 2 | Isprefix, +[0xE0] 3 | Isprefix, +[0xF0] 4 | Isprefix, +[0xF8] 5 | Isprefix, +[0xFC] 6 | Isprefix, +[0xFE] 7 | Isprefix, +[0xFF] 8 | Isprefix, +}; + +uchar v4prefix[16] = { + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0xff, 0xff, + 0, 0, 0, 0 +}; + +void +hnputl(void *p, ulong v) +{ + uchar *a; + + a = p; + a[0] = v>>24; + a[1] = v>>16; + a[2] = v>>8; + a[3] = v; +} + +int +eipconv(va_list *arg, Fconv *f) +{ + char buf[8*5]; + static char *efmt = "%.2lux%.2lux%.2lux%.2lux%.2lux%.2lux"; + static char *ifmt = "%d.%d.%d.%d"; + uchar *p, ip[16]; + ulong *lp; + ushort s; + int i, j, n, eln, eli; + + switch(f->chr) { + case 'E': /* Ethernet address */ + p = va_arg(*arg, uchar*); + sprint(buf, efmt, p[0], p[1], p[2], p[3], p[4], p[5]); + break; + case 'I': /* Ip address */ + p = va_arg(*arg, uchar*); +common: + if(memcmp(p, v4prefix, 12) == 0) + sprint(buf, ifmt, p[12], p[13], p[14], p[15]); + else { + /* find longest elision */ + eln = eli = -1; + for(i = 0; i < 16; i += 2){ + for(j = i; j < 16; j += 2) + if(p[j] != 0 || p[j+1] != 0) + break; + if(j > i && j - i > eln){ + eli = i; + eln = j - i; + } + } + + /* print with possible elision */ + n = 0; + for(i = 0; i < 16; i += 2){ + if(i == eli){ + n += sprint(buf+n, "::"); + i += eln; + if(i >= 16) + break; + } else if(i != 0) + n += sprint(buf+n, ":"); + s = (p[i]<<8) + p[i+1]; + n += sprint(buf+n, "%ux", s); + } + } + break; + case 'i': /* v6 address as 4 longs */ + lp = va_arg(*arg, ulong*); + for(i = 0; i < 4; i++) + hnputl(ip+4*i, *lp++); + p = ip; + goto common; + case 'V': /* v4 ip address */ + p = va_arg(*arg, uchar*); + sprint(buf, ifmt, p[0], p[1], p[2], p[3]); + break; + case 'M': /* ip mask */ + p = va_arg(*arg, uchar*); + + /* look for a prefix mask */ + for(i = 0; i < 16; i++) + if(p[i] != 0xff) + break; + if(i < 16){ + if((prefixvals[p[i]] & Isprefix) == 0) + goto common; + for(j = i+1; j < 16; j++) + if(p[j] != 0) + goto common; + n = 8*i + (prefixvals[p[i]] & ~Isprefix); + } else + n = 8*16; + + /* got one, use /xx format */ + sprint(buf, "/%d", n); + break; + default: + strcpy(buf, "(eipconv)"); + } + strconv(buf, f); + return sizeof(uchar*); +} + +uchar testvec[11][16] = +{ + { 0,0,0,0, 0,0,0,0, 0,0,0xff,0xff, 1,3,4,5, }, + { 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, }, + { 0xff,0xff,0x80,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, }, + { 0xff,0xff,0xff,0xc0, 0,0,0,0, 0,0,0,0, 0,0,0,0, }, + { 0xff,0xff,0xff,0xff, 0xe0,0,0,0, 0,0,0,0, 0,0,0,0, }, + { 0xff,0xff,0xff,0xff, 0xff,0xf0,0,0, 0,0,0,0, 0,0,0,0, }, + { 0xff,0xff,0xff,0xff, 0xff,0xff,0xf8,0, 0,0,0,0, 0,0,0,0, }, + { 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, }, + { 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, }, + { 0,0,0,0, 0,0x11,0,0, 0,0,0,0, 0,0,0,0, }, + { 0,0,0,0x11, 0,0,0,0, 0,0,0,0, 0,0,0,0x12, }, +}; + +void +main(void) +{ + int i; + + fmtinstall('I', eipconv); + fmtinstall('M', eipconv); + for(i = 0; i < 11; i++) + print("%I\n%M\n", testvec[i], testvec[i]); + exits(0); +} |