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