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