/* 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; | |
} |