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
|
/* GRE flag bits */
enum {
GRE_chksum = (1<<15),
GRE_routing = (1<<14),
GRE_key = (1<<13),
GRE_seq = (1<<12),
GRE_srcrt = (1<<11),
GRE_recur = (7<<8),
GRE_ack = (1<<7),
GRE_ver = 0x7
};
/* GRE protocols */
enum {
GRE_sna = 0x0004,
GRE_osi = 0x00fe,
GRE_pup = 0x0200,
GRE_xns = 0x0600,
GRE_ip = 0x0800,
GRE_chaos = 0x0804,
GRE_rfc826 = 0x0806,
GRE_frarp = 0x0808,
GRE_vines = 0x0bad,
GRE_vinesecho = 0x0bae,
GRE_vinesloop = 0x0baf,
GRE_decnetIV = 0x6003,
GRE_ppp = 0x880b
};
int
sprintgre(void *a, char *buf, int len)
{
int flag, prot, chksum, offset, key, seq, ack;
int n;
uchar *p = a;
chksum = offset = key = seq = ack = 0;
flag = NetS(p);
prot = NetS(p+2);
p += 4; len -= 4;
if(flag & (GRE_chksum|GRE_routing)){
chksum = NetS(p);
offset = NetS(p+2);
p += 4; len -= 4;
}
if(flag&GRE_key){
key = NetL(p);
p += 4; len -= 4;
}
if(flag&GRE_seq){
seq = NetL(p);
p += 4; len -= 4;
}
if(flag&GRE_ack){
ack = NetL(p);
p += 4; len -= 4;
}
/* skip routing if present */
if(flag&GRE_routing) {
while(len >= 4 && (n=p[3]) != 0) {
len -= n;
p += n;
}
}
USED(offset);
USED(chksum);
n = sprint(buf, "GRE(f %4.4ux p %ux k %ux", flag, prot, key);
if(flag&GRE_seq)
n += sprint(buf+n, " s %ux", seq);
if(flag&GRE_ack)
n += sprint(buf+n, " a %ux", ack);
n += sprint(buf+n, " len = %d/%d) ", len, key>>16);
if(prot == GRE_ppp && len > 0)
n += sprintppp(p, buf+n, len);
else
n += sprintx(p, buf+n, len);
return n;
}
|