ref: d1cebf608b05e45b148108ac6c16ae94f6862097
dir: /sys/src/cmd/ip/snoopy/arp.c/
#include <u.h> #include <libc.h> #include <ip.h> #include "dat.h" #include "protos.h" typedef struct Hdr Hdr; struct Hdr { uchar hrd[2]; uchar pro[2]; uchar hln; uchar pln; uchar op[2]; uchar sha[6]; uchar spa[4]; uchar tha[6]; uchar tpa[4]; }; enum { ARPLEN= 28, }; enum { Ospa, Otpa, Ostpa, Osha, Otha, Ostha, Opa, }; static Field p_fields[] = { {"spa", Fv4ip, Ospa, "protocol source", } , {"tpa", Fv4ip, Otpa, "protocol target", } , {"a", Fv4ip, Ostpa, "protocol source/target", } , {"sha", Fba, Osha, "hardware source", } , {"tha", Fba, Otha, "hardware target", } , {"ah", Fba, Ostha, "hardware source/target", } , {0} }; static void p_compile(Filter *f) { if(f->op == '='){ compile_cmp(arp.name, f, p_fields); return; } sysfatal("unknown arp field: %s", f->s); } static int p_filter(Filter *f, Msg *m) { Hdr *h; if(m->pe - m->ps < ARPLEN) return 0; h = (Hdr*)m->ps; m->ps += ARPLEN; switch(f->subop){ case Ospa: return h->pln == 4 && NetL(h->spa) == f->ulv; case Otpa: return h->pln == 4 && NetL(h->tpa) == f->ulv; case Ostpa: return h->pln == 4 && (NetL(h->tpa) == f->ulv || NetL(h->spa) == f->ulv); case Osha: return memcmp(h->sha, f->a, h->hln) == 0; case Otha: return memcmp(h->tha, f->a, h->hln) == 0; case Ostha: return memcmp(h->sha, f->a, h->hln)==0 ||memcmp(h->tha, f->a, h->hln)==0; } return 0; } static int p_seprint(Msg *m) { Hdr *h; if(m->pe - m->ps < ARPLEN) return -1; h = (Hdr*)m->ps; m->ps += ARPLEN; /* no next protocol */ m->pr = nil; m->p = seprint(m->p, m->e, "op=%1d len=%1d/%1d spa=%V sha=%E tpa=%V tha=%E", NetS(h->op), h->pln, h->hln, h->spa, h->sha, h->tpa, h->tha); return 0; } Proto arp = { "arp", p_compile, p_filter, p_seprint, nil, nil, p_fields, defaultframer, }; Proto rarp = { "rarp", p_compile, p_filter, p_seprint, nil, nil, p_fields, defaultframer, };