Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
#include <u.h>
2
#include <libc.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
	ulong *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, ulong*);
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
}