eipfmt.c (2189B)
1 #include "u.h" 2 #include "lib.h" 3 #include "ip.h" 4 5 enum 6 { 7 Isprefix= 16, 8 }; 9 10 uchar prefixvals[256] = 11 { 12 [0x00] 0 | Isprefix, 13 [0x80] 1 | Isprefix, 14 [0xC0] 2 | Isprefix, 15 [0xE0] 3 | Isprefix, 16 [0xF0] 4 | Isprefix, 17 [0xF8] 5 | Isprefix, 18 [0xFC] 6 | Isprefix, 19 [0xFE] 7 | Isprefix, 20 [0xFF] 8 | Isprefix, 21 }; 22 23 int 24 eipfmt(Fmt *f) 25 { 26 char buf[5*8]; 27 static char *efmt = "%.2ux%.2ux%.2ux%.2ux%.2ux%.2ux"; 28 static char *ifmt = "%d.%d.%d.%d"; 29 uchar *p, ip[16]; 30 uint32 *lp; 31 ushort s; 32 int i, j, n, eln, eli; 33 34 switch(f->r) { 35 case 'E': /* Ethernet address */ 36 p = va_arg(f->args, uchar*); 37 snprint(buf, sizeof buf, efmt, p[0], p[1], p[2], p[3], p[4], p[5]); 38 return fmtstrcpy(f, buf); 39 40 case 'I': /* Ip address */ 41 p = va_arg(f->args, uchar*); 42 common: 43 if(memcmp(p, v4prefix, 12) == 0){ 44 snprint(buf, sizeof buf, ifmt, p[12], p[13], p[14], p[15]); 45 return fmtstrcpy(f, buf); 46 } 47 48 /* find longest elision */ 49 eln = eli = -1; 50 for(i = 0; i < 16; i += 2){ 51 for(j = i; j < 16; j += 2) 52 if(p[j] != 0 || p[j+1] != 0) 53 break; 54 if(j > i && j - i > eln){ 55 eli = i; 56 eln = j - i; 57 } 58 } 59 60 /* print with possible elision */ 61 n = 0; 62 for(i = 0; i < 16; i += 2){ 63 if(i == eli){ 64 n += sprint(buf+n, "::"); 65 i += eln; 66 if(i >= 16) 67 break; 68 } else if(i != 0) 69 n += sprint(buf+n, ":"); 70 s = (p[i]<<8) + p[i+1]; 71 n += sprint(buf+n, "%ux", s); 72 } 73 return fmtstrcpy(f, buf); 74 75 case 'i': /* v6 address as 4 longs */ 76 lp = va_arg(f->args, uint32*); 77 for(i = 0; i < 4; i++) 78 hnputl(ip+4*i, *lp++); 79 p = ip; 80 goto common; 81 82 case 'V': /* v4 ip address */ 83 p = va_arg(f->args, uchar*); 84 snprint(buf, sizeof buf, ifmt, p[0], p[1], p[2], p[3]); 85 return fmtstrcpy(f, buf); 86 87 case 'M': /* ip mask */ 88 p = va_arg(f->args, uchar*); 89 90 /* look for a prefix mask */ 91 for(i = 0; i < 16; i++) 92 if(p[i] != 0xff) 93 break; 94 if(i < 16){ 95 if((prefixvals[p[i]] & Isprefix) == 0) 96 goto common; 97 for(j = i+1; j < 16; j++) 98 if(p[j] != 0) 99 goto common; 100 n = 8*i + (prefixvals[p[i]] & ~Isprefix); 101 } else 102 n = 8*16; 103 104 /* got one, use /xx format */ 105 snprint(buf, sizeof buf, "/%d", n); 106 return fmtstrcpy(f, buf); 107 } 108 return fmtstrcpy(f, "(eipfmt)"); 109 }