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