ref: c5c19dfe4998fa40de5f58f61439fd5fd65c9056
dir: /sys/src/cmd/ip/snoopy/udp.c/
#include <u.h> #include <libc.h> #include <ip.h> #include "dat.h" #include "protos.h" typedef struct Hdr Hdr; struct Hdr { uchar sport[2]; /* Source port */ uchar dport[2]; /* Destination port */ uchar len[2]; /* data length */ uchar cksum[2]; /* Checksum */ }; enum { UDPLEN= 8, }; enum { Os, Od, Osd, Osetport, }; static Field p_fields[] = { {"s", Fnum, Os, "source port", } , {"d", Fnum, Od, "dest port", } , {"a", Fnum, Osd, "source/dest port", } , {"sd", Fnum, Osd, "source/dest port", } , {0} }; #define ANYPORT ~0UL static Mux p_mux[] = { {"dns", 53, }, {"bootp", 67, }, {"ninep", 6346, }, /* tvs */ {"rtp", ANYPORT, }, {"rtcp", ANYPORT, }, {0}, }; /* default next protocol, can be changed by p_filter, reset by p_compile */ static Proto *defproto = &dump; static void p_compile(Filter *f) { Mux *m; if(f->op == '='){ compile_cmp(udp.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 = Osd; return; } sysfatal("unknown udp field or protocol: %s", f->s); } static int p_filter(Filter *f, Msg *m) { Hdr *h; if(m->pe - m->ps < UDPLEN) return 0; h = (Hdr*)m->ps; m->ps += UDPLEN; switch(f->subop){ case Os: return NetS(h->sport) == f->ulv; case Od: return NetS(h->dport) == f->ulv; case Osd: if(f->ulv == ANYPORT){ defproto = f->pr; return 1; } return NetS(h->sport) == f->ulv || NetS(h->dport) == f->ulv; } return 0; } static int p_seprint(Msg *m) { Hdr *h; int dport, sport; if(m->pe - m->ps < UDPLEN) return -1; h = (Hdr*)m->ps; m->ps += UDPLEN; /* next protocol */ sport = NetS(h->sport); dport = NetS(h->dport); demux(p_mux, sport, dport, m, defproto); defproto = &dump; m->p = seprint(m->p, m->e, "s=%d d=%d ck=%4.4ux ln=%4d", NetS(h->sport), dport, NetS(h->cksum), NetS(h->len)); return 0; } Proto udp = { "udp", p_compile, p_filter, p_seprint, p_mux, "%lud", p_fields, defaultframer, };