eipconvtest.c (3135B)
1 #include <u.h> 2 #include <libc.h> 3 4 enum 5 { 6 Isprefix= 16, 7 }; 8 9 uchar prefixvals[256] = 10 { 11 [0x00] 0 | Isprefix, 12 [0x80] 1 | Isprefix, 13 [0xC0] 2 | Isprefix, 14 [0xE0] 3 | Isprefix, 15 [0xF0] 4 | Isprefix, 16 [0xF8] 5 | Isprefix, 17 [0xFC] 6 | Isprefix, 18 [0xFE] 7 | Isprefix, 19 [0xFF] 8 | Isprefix, 20 }; 21 22 uchar v4prefix[16] = { 23 0, 0, 0, 0, 24 0, 0, 0, 0, 25 0, 0, 0xff, 0xff, 26 0, 0, 0, 0 27 }; 28 29 void 30 hnputl(void *p, ulong v) 31 { 32 uchar *a; 33 34 a = p; 35 a[0] = v>>24; 36 a[1] = v>>16; 37 a[2] = v>>8; 38 a[3] = v; 39 } 40 41 int 42 eipconv(va_list *arg, Fconv *f) 43 { 44 char buf[8*5]; 45 static char *efmt = "%.2lux%.2lux%.2lux%.2lux%.2lux%.2lux"; 46 static char *ifmt = "%d.%d.%d.%d"; 47 uchar *p, ip[16]; 48 ulong *lp; 49 ushort s; 50 int i, j, n, eln, eli; 51 52 switch(f->chr) { 53 case 'E': /* Ethernet address */ 54 p = va_arg(*arg, uchar*); 55 sprint(buf, efmt, p[0], p[1], p[2], p[3], p[4], p[5]); 56 break; 57 case 'I': /* Ip address */ 58 p = va_arg(*arg, uchar*); 59 common: 60 if(memcmp(p, v4prefix, 12) == 0) 61 sprint(buf, ifmt, p[12], p[13], p[14], p[15]); 62 else { 63 /* find longest elision */ 64 eln = eli = -1; 65 for(i = 0; i < 16; i += 2){ 66 for(j = i; j < 16; j += 2) 67 if(p[j] != 0 || p[j+1] != 0) 68 break; 69 if(j > i && j - i > eln){ 70 eli = i; 71 eln = j - i; 72 } 73 } 74 75 /* print with possible elision */ 76 n = 0; 77 for(i = 0; i < 16; i += 2){ 78 if(i == eli){ 79 n += sprint(buf+n, "::"); 80 i += eln; 81 if(i >= 16) 82 break; 83 } else if(i != 0) 84 n += sprint(buf+n, ":"); 85 s = (p[i]<<8) + p[i+1]; 86 n += sprint(buf+n, "%ux", s); 87 } 88 } 89 break; 90 case 'i': /* v6 address as 4 longs */ 91 lp = va_arg(*arg, ulong*); 92 for(i = 0; i < 4; i++) 93 hnputl(ip+4*i, *lp++); 94 p = ip; 95 goto common; 96 case 'V': /* v4 ip address */ 97 p = va_arg(*arg, uchar*); 98 sprint(buf, ifmt, p[0], p[1], p[2], p[3]); 99 break; 100 case 'M': /* ip mask */ 101 p = va_arg(*arg, uchar*); 102 103 /* look for a prefix mask */ 104 for(i = 0; i < 16; i++) 105 if(p[i] != 0xff) 106 break; 107 if(i < 16){ 108 if((prefixvals[p[i]] & Isprefix) == 0) 109 goto common; 110 for(j = i+1; j < 16; j++) 111 if(p[j] != 0) 112 goto common; 113 n = 8*i + (prefixvals[p[i]] & ~Isprefix); 114 } else 115 n = 8*16; 116 117 /* got one, use /xx format */ 118 sprint(buf, "/%d", n); 119 break; 120 default: 121 strcpy(buf, "(eipconv)"); 122 } 123 strconv(buf, f); 124 return sizeof(uchar*); 125 } 126 127 uchar testvec[11][16] = 128 { 129 { 0,0,0,0, 0,0,0,0, 0,0,0xff,0xff, 1,3,4,5, }, 130 { 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, }, 131 { 0xff,0xff,0x80,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, }, 132 { 0xff,0xff,0xff,0xc0, 0,0,0,0, 0,0,0,0, 0,0,0,0, }, 133 { 0xff,0xff,0xff,0xff, 0xe0,0,0,0, 0,0,0,0, 0,0,0,0, }, 134 { 0xff,0xff,0xff,0xff, 0xff,0xf0,0,0, 0,0,0,0, 0,0,0,0, }, 135 { 0xff,0xff,0xff,0xff, 0xff,0xff,0xf8,0, 0,0,0,0, 0,0,0,0, }, 136 { 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, }, 137 { 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, }, 138 { 0,0,0,0, 0,0x11,0,0, 0,0,0,0, 0,0,0,0, }, 139 { 0,0,0,0x11, 0,0,0,0, 0,0,0,0, 0,0,0,0x12, }, 140 }; 141 142 void 143 main(void) 144 { 145 int i; 146 147 fmtinstall('I', eipconv); 148 fmtinstall('M', eipconv); 149 for(i = 0; i < 11; i++) 150 print("%I\n%M\n", testvec[i], testvec[i]); 151 exits(0); 152 }