diff options
Diffstat (limited to 'src/cmd/ip/snoopy/ip.c')
-rwxr-xr-x | src/cmd/ip/snoopy/ip.c | 236 |
1 files changed, 236 insertions, 0 deletions
diff --git a/src/cmd/ip/snoopy/ip.c b/src/cmd/ip/snoopy/ip.c new file mode 100755 index 00000000..e321e2fe --- /dev/null +++ b/src/cmd/ip/snoopy/ip.c @@ -0,0 +1,236 @@ +#include <u.h> +#include <libc.h> +#include <ip.h> +#include "dat.h" +#include "protos.h" + +typedef struct Hdr Hdr; +struct Hdr +{ + uchar vihl; /* Version and header length */ + uchar tos; /* Type of service */ + uchar length[2]; /* packet length */ + uchar id[2]; /* ip->identification */ + uchar frag[2]; /* Fragment information */ + uchar ttl; /* Time to live */ + uchar proto; /* Protocol */ + uchar cksum[2]; /* Header checksum */ + uchar src[4]; /* IP source */ + uchar dst[4]; /* IP destination */ +}; + +enum +{ + IPHDR = 20, /* sizeof(Iphdr) */ + IP_VER = 0x40, /* Using IP version 4 */ + IP_DF = 0x4000, /* Don't fragment */ + IP_MF = 0x2000, /* More fragments */ +}; + +static Mux p_mux[] = +{ + { "icmp", 1, }, + { "igmp", 2, }, + { "ggp", 3, }, + { "ip", 4, }, + { "st", 5, }, + { "tcp", 6, }, + { "ucl", 7, }, + { "egp", 8, }, + { "igp", 9, }, + { "bbn-rcc-mon", 10, }, + { "nvp-ii", 11, }, + { "pup", 12, }, + { "argus", 13, }, + { "emcon", 14, }, + { "xnet", 15, }, + { "chaos", 16, }, + { "udp", 17, }, + { "mux", 18, }, + { "dcn-meas", 19, }, + { "hmp", 20, }, + { "prm", 21, }, + { "xns-idp", 22, }, + { "trunk-1", 23, }, + { "trunk-2", 24, }, + { "leaf-1", 25, }, + { "leaf-2", 26, }, + { "rdp", 27, }, + { "irtp", 28, }, + { "iso-tp4", 29, }, + { "netblt", 30, }, + { "mfe-nsp", 31, }, + { "merit-inp", 32, }, + { "sep", 33, }, + { "3pc", 34, }, + { "idpr", 35, }, + { "xtp", 36, }, + { "ddp", 37, }, + { "idpr-cmtp", 38, }, + { "tp++", 39, }, + { "il", 40, }, + { "sip", 41, }, + { "sdrp", 42, }, + { "sip-sr", 43, }, + { "sip-frag", 44, }, + { "idrp", 45, }, + { "rsvp", 46, }, + { "gre", 47, }, + { "mhrp", 48, }, + { "bna", 49, }, + { "sipp-esp", 50, }, + { "sipp-ah", 51, }, + { "i-nlsp", 52, }, + { "swipe", 53, }, + { "nhrp", 54, }, + { "any", 61, }, + { "cftp", 62, }, + { "any", 63, }, + { "sat-expak", 64, }, + { "kryptolan", 65, }, + { "rvd", 66, }, + { "ippc", 67, }, + { "any", 68, }, + { "sat-mon", 69, }, + { "visa", 70, }, + { "ipcv", 71, }, + { "cpnx", 72, }, + { "cphb", 73, }, + { "wsn", 74, }, + { "pvp", 75, }, + { "br-sat-mon", 76, }, + { "sun-nd", 77, }, + { "wb-mon", 78, }, + { "wb-expak", 79, }, + { "iso-ip", 80, }, + { "vmtp", 81, }, + { "secure-vmtp", 82, }, + { "vines", 83, }, + { "ttp", 84, }, + { "nsfnet-igp", 85, }, + { "dgp", 86, }, + { "tcf", 87, }, + { "igrp", 88, }, + { "ospf", 89, }, + { "sprite-rpc", 90, }, + { "larp", 91, }, + { "mtp", 92, }, + { "ax.25", 93, }, + { "ipip", 94, }, + { "micp", 95, }, + { "scc-sp", 96, }, + { "etherip", 97, }, + { "encap", 98, }, + { "any", 99, }, + { "gmtp", 100, }, + { "rudp", 254, }, + { 0 } +}; + +enum +{ + Os, // source + Od, // destination + Osd, // source or destination + Ot, // type +}; + +static Field p_fields[] = +{ + {"s", Fv4ip, Os, "source address", } , + {"d", Fv4ip, Od, "destination address", } , + {"a", Fv4ip, Osd, "source|destination address",} , + {"sd", Fv4ip, Osd, "source|destination address",} , + {"t", Fnum, Ot, "sub protocol number", } , + {0} +}; + +static void +p_compile(Filter *f) +{ + Mux *m; + + if(f->op == '='){ + compile_cmp(ip.name, f, p_fields); + return; + } + for(m = p_mux; m->name != nil; m++) + if(strcmp(f->s, m->name) == 0){ + f->pr = m->pr; + f->ulv = m->val; + f->subop = Ot; + return; + } + sysfatal("unknown ip field or protocol: %s", f->s); +} + +static int +p_filter(Filter *f, Msg *m) +{ + Hdr *h; + + if(m->pe - m->ps < IPHDR) + return 0; + + h = (Hdr*)m->ps; + m->ps += ((h->vihl&0xf)<<2); + + switch(f->subop){ + case Os: + return NetL(h->src) == f->ulv; + case Od: + return NetL(h->dst) == f->ulv; + case Osd: + return NetL(h->src) == f->ulv || NetL(h->dst) == f->ulv; + case Ot: + return h->proto == f->ulv; + } + return 0; +} + +static int +p_seprint(Msg *m) +{ + Hdr *h; + int f; + int len; + + if(m->pe - m->ps < IPHDR) + return -1; + h = (Hdr*)m->ps; + + /* next protocol, just dump unless this is the first fragment */ + m->pr = &dump; + f = NetS(h->frag); + if((f & ~(IP_DF|IP_MF)) == 0) + demux(p_mux, h->proto, h->proto, m, &dump); + + /* truncate the message if there's extra */ + len = NetS(h->length); + if(len < m->pe - m->ps) + m->pe = m->ps + len; + + /* next header */ + m->ps += ((h->vihl&0xf)<<2); + + m->p = seprint(m->p, m->e, "s=%V d=%V id=%4.4ux frag=%4.4ux ttl=%3d pr=%d ln=%d", + h->src, h->dst, + NetS(h->id), + NetS(h->frag), + h->ttl, + h->proto, + NetS(h->length) + ); + return 0; +} + +Proto ip = +{ + "ip", + p_compile, + p_filter, + p_seprint, + p_mux, + p_fields, + defaultframer, +}; |