summaryrefslogtreecommitdiff
path: root/sys/src/9/ip/eipconvtest.c
diff options
context:
space:
mode:
authorTaru Karttunen <taruti@taruti.net>2011-03-30 15:46:40 +0300
committerTaru Karttunen <taruti@taruti.net>2011-03-30 15:46:40 +0300
commite5888a1ffdae813d7575f5fb02275c6bb07e5199 (patch)
treed8d51eac403f07814b9e936eed0c9a79195e2450 /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-xsys/src/9/ip/eipconvtest.c152
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);
+}