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