Blob


1 #include <u.h>
2 #include <libc.h>
3 #include <ip.h>
5 enum
6 {
7 Isprefix= 16
8 };
10 /* XXX: manually initialize once to placate the Sun monster */
11 uchar prefixvals[256];
12 #ifdef NOTDEF
13 uchar prefixvals[256] =
14 {
15 [0x00] 0 | Isprefix,
16 [0x80] 1 | Isprefix,
17 [0xC0] 2 | Isprefix,
18 [0xE0] 3 | Isprefix,
19 [0xF0] 4 | Isprefix,
20 [0xF8] 5 | Isprefix,
21 [0xFC] 6 | Isprefix,
22 [0xFE] 7 | Isprefix,
23 [0xFF] 8 | Isprefix,
24 };
25 #endif
27 int
28 eipfmt(Fmt *f)
29 {
30 char buf[5*8];
31 static char *efmt = "%.2ux%.2ux%.2ux%.2ux%.2ux%.2ux";
32 static char *altefmt = "%.2ux:%.2ux:%.2ux:%.2ux:%.2ux:%.2ux";
33 static char *ifmt = "%d.%d.%d.%d";
34 char *fmt;
35 uchar *p, ip[16];
36 ulong *lp;
37 ushort s;
38 int i, j, n, eln, eli;
40 static int once = 0; /* XXX: placate the Sun monster */
42 if(!once){
43 once = 1;
44 memset(prefixvals, 0, sizeof(prefixvals));
45 prefixvals[0x00] = 0 | Isprefix;
46 prefixvals[0x80] = 1 | Isprefix;
47 prefixvals[0xC0] = 2 | Isprefix;
48 prefixvals[0xE0] = 3 | Isprefix;
49 prefixvals[0xF0] = 4 | Isprefix;
50 prefixvals[0xF8] = 5 | Isprefix;
51 prefixvals[0xFC] = 6 | Isprefix;
52 prefixvals[0xFE] = 7 | Isprefix;
53 prefixvals[0xFF] = 8 | Isprefix;
54 }
56 switch(f->r) {
57 case 'E': /* Ethernet address */
58 p = va_arg(f->args, uchar*);
59 fmt = efmt;
60 if(f->flags&FmtSharp)
61 fmt = altefmt;
62 snprint(buf, sizeof buf, fmt, p[0], p[1], p[2], p[3], p[4], p[5]);
63 return fmtstrcpy(f, buf);
65 case 'I': /* Ip address */
66 p = va_arg(f->args, uchar*);
67 common:
68 if(memcmp(p, v4prefix, 12) == 0){
69 snprint(buf, sizeof buf, ifmt, p[12], p[13], p[14], p[15]);
70 return fmtstrcpy(f, buf);
71 }
73 /* find longest elision */
74 eln = eli = -1;
75 for(i = 0; i < 16; i += 2){
76 for(j = i; j < 16; j += 2)
77 if(p[j] != 0 || p[j+1] != 0)
78 break;
79 if(j > i && j - i > eln){
80 eli = i;
81 eln = j - i;
82 }
83 }
85 /* print with possible elision */
86 n = 0;
87 for(i = 0; i < 16; i += 2){
88 if(i == eli){
89 n += sprint(buf+n, "::");
90 i += eln;
91 if(i >= 16)
92 break;
93 } else if(i != 0)
94 n += sprint(buf+n, ":");
95 s = (p[i]<<8) + p[i+1];
96 n += sprint(buf+n, "%ux", s);
97 }
98 return fmtstrcpy(f, buf);
100 case 'i': /* v6 address as 4 longs */
101 lp = va_arg(f->args, ulong*);
102 for(i = 0; i < 4; i++)
103 hnputl(ip+4*i, *lp++);
104 p = ip;
105 goto common;
107 case 'V': /* v4 ip address */
108 p = va_arg(f->args, uchar*);
109 snprint(buf, sizeof buf, ifmt, p[0], p[1], p[2], p[3]);
110 return fmtstrcpy(f, buf);
112 case 'M': /* ip mask */
113 p = va_arg(f->args, uchar*);
115 /* look for a prefix mask */
116 for(i = 0; i < 16; i++)
117 if(p[i] != 0xff)
118 break;
119 if(i < 16){
120 if((prefixvals[p[i]] & Isprefix) == 0)
121 goto common;
122 for(j = i+1; j < 16; j++)
123 if(p[j] != 0)
124 goto common;
125 n = 8*i + (prefixvals[p[i]] & ~Isprefix);
126 } else
127 n = 8*16;
129 /* got one, use /xx format */
130 snprint(buf, sizeof buf, "/%d", n);
131 return fmtstrcpy(f, buf);
133 return fmtstrcpy(f, "(eipfmt)");