19a747e4fSDavid du Colombier #include <u.h>
29a747e4fSDavid du Colombier #include <libc.h>
39a747e4fSDavid du Colombier #include <ip.h>
49a747e4fSDavid du Colombier #include "dat.h"
59a747e4fSDavid du Colombier #include "protos.h"
69a747e4fSDavid du Colombier
79a747e4fSDavid du Colombier typedef struct Hdr Hdr;
89a747e4fSDavid du Colombier struct Hdr {
99a747e4fSDavid du Colombier uchar d[6];
109a747e4fSDavid du Colombier uchar s[6];
119a747e4fSDavid du Colombier uchar type[2];
129a747e4fSDavid du Colombier char data[1500];
139a747e4fSDavid du Colombier };
14*e6dcbf51SDavid du Colombier
159a747e4fSDavid du Colombier #define ETHERMINTU 60 /* minimum transmit size */
169a747e4fSDavid du Colombier #define ETHERMAXTU 1514 /* maximum transmit size */
179a747e4fSDavid du Colombier #define ETHERHDRSIZE 14 /* size of an ethernet header */
189a747e4fSDavid du Colombier
199a747e4fSDavid du Colombier static Mux p_mux[] =
209a747e4fSDavid du Colombier {
219a747e4fSDavid du Colombier {"ip", 0x0800, } ,
229a747e4fSDavid du Colombier {"arp", 0x0806, } ,
239a747e4fSDavid du Colombier {"rarp", 0x0806, } ,
249a747e4fSDavid du Colombier {"ip6", 0x86dd, } ,
25d9306527SDavid du Colombier {"pppoe_disc", 0x8863, },
26d9306527SDavid du Colombier {"pppoe_sess", 0x8864, },
27ed397113SDavid du Colombier {"eapol", 0x888e, },
28*e6dcbf51SDavid du Colombier {"aoe", 0x88a2, } ,
29*e6dcbf51SDavid du Colombier {"cec", 0xbcbc, } ,
309a747e4fSDavid du Colombier {0}
319a747e4fSDavid du Colombier };
329a747e4fSDavid du Colombier
339a747e4fSDavid du Colombier enum
349a747e4fSDavid du Colombier {
35*e6dcbf51SDavid du Colombier Os, /* source */
36*e6dcbf51SDavid du Colombier Od, /* destination */
37*e6dcbf51SDavid du Colombier Oa, /* source or destination */
38*e6dcbf51SDavid du Colombier Ot, /* type */
399a747e4fSDavid du Colombier };
409a747e4fSDavid du Colombier
419a747e4fSDavid du Colombier static Field p_fields[] =
429a747e4fSDavid du Colombier {
439a747e4fSDavid du Colombier {"s", Fether, Os, "source address", } ,
449a747e4fSDavid du Colombier {"d", Fether, Od, "destination address", } ,
459a747e4fSDavid du Colombier {"a", Fether, Oa, "source|destination address" } ,
46dc5a79c1SDavid du Colombier {"sd", Fether, Oa, "source|destination address" } ,
479a747e4fSDavid du Colombier {"t", Fnum, Ot, "type" } ,
489a747e4fSDavid du Colombier {0}
499a747e4fSDavid du Colombier };
509a747e4fSDavid du Colombier
519a747e4fSDavid du Colombier static void
p_compile(Filter * f)529a747e4fSDavid du Colombier p_compile(Filter *f)
539a747e4fSDavid du Colombier {
549a747e4fSDavid du Colombier Mux *m;
559a747e4fSDavid du Colombier
569a747e4fSDavid du Colombier if(f->op == '='){
579a747e4fSDavid du Colombier compile_cmp(ether.name, f, p_fields);
589a747e4fSDavid du Colombier return;
599a747e4fSDavid du Colombier }
609a747e4fSDavid du Colombier for(m = p_mux; m->name != nil; m++)
619a747e4fSDavid du Colombier if(strcmp(f->s, m->name) == 0){
629a747e4fSDavid du Colombier f->pr = m->pr;
639a747e4fSDavid du Colombier f->ulv = m->val;
649a747e4fSDavid du Colombier f->subop = Ot;
659a747e4fSDavid du Colombier return;
669a747e4fSDavid du Colombier }
679a747e4fSDavid du Colombier sysfatal("unknown ethernet field or protocol: %s", f->s);
689a747e4fSDavid du Colombier }
699a747e4fSDavid du Colombier
709a747e4fSDavid du Colombier static int
p_filter(Filter * f,Msg * m)719a747e4fSDavid du Colombier p_filter(Filter *f, Msg *m)
729a747e4fSDavid du Colombier {
739a747e4fSDavid du Colombier Hdr *h;
749a747e4fSDavid du Colombier
759a747e4fSDavid du Colombier if(m->pe - m->ps < ETHERHDRSIZE)
769a747e4fSDavid du Colombier return 0;
779a747e4fSDavid du Colombier
789a747e4fSDavid du Colombier h = (Hdr*)m->ps;
799a747e4fSDavid du Colombier m->ps += ETHERHDRSIZE;
809a747e4fSDavid du Colombier
819a747e4fSDavid du Colombier switch(f->subop){
829a747e4fSDavid du Colombier case Os:
83*e6dcbf51SDavid du Colombier return memcmp(h->s, f->a, 6) == 0;
849a747e4fSDavid du Colombier case Od:
85*e6dcbf51SDavid du Colombier return memcmp(h->d, f->a, 6) == 0;
869a747e4fSDavid du Colombier case Oa:
879a747e4fSDavid du Colombier return memcmp(h->s, f->a, 6) == 0 || memcmp(h->d, f->a, 6) == 0;
889a747e4fSDavid du Colombier case Ot:
899a747e4fSDavid du Colombier return NetS(h->type) == f->ulv;
909a747e4fSDavid du Colombier }
919a747e4fSDavid du Colombier return 0;
929a747e4fSDavid du Colombier }
939a747e4fSDavid du Colombier
949a747e4fSDavid du Colombier static int
p_seprint(Msg * m)959a747e4fSDavid du Colombier p_seprint(Msg *m)
969a747e4fSDavid du Colombier {
979a747e4fSDavid du Colombier int len;
98*e6dcbf51SDavid du Colombier uint t;
99*e6dcbf51SDavid du Colombier Hdr *h;
1009a747e4fSDavid du Colombier
1019a747e4fSDavid du Colombier len = m->pe - m->ps;
1029a747e4fSDavid du Colombier if(len < ETHERHDRSIZE)
1039a747e4fSDavid du Colombier return -1;
1049a747e4fSDavid du Colombier
1059a747e4fSDavid du Colombier h = (Hdr*)m->ps;
1069a747e4fSDavid du Colombier m->ps += ETHERHDRSIZE;
1079a747e4fSDavid du Colombier
1089a747e4fSDavid du Colombier t = NetS(h->type);
1099a747e4fSDavid du Colombier demux(p_mux, t, t, m, &dump);
1109a747e4fSDavid du Colombier
1119a747e4fSDavid du Colombier m->p = seprint(m->p, m->e, "s=%E d=%E pr=%4.4ux ln=%d", h->s, h->d,
1129a747e4fSDavid du Colombier t, len);
1139a747e4fSDavid du Colombier return 0;
1149a747e4fSDavid du Colombier }
1159a747e4fSDavid du Colombier
1169a747e4fSDavid du Colombier Proto ether =
1179a747e4fSDavid du Colombier {
1189a747e4fSDavid du Colombier "ether",
1199a747e4fSDavid du Colombier p_compile,
1209a747e4fSDavid du Colombier p_filter,
1219a747e4fSDavid du Colombier p_seprint,
1229a747e4fSDavid du Colombier p_mux,
123ed397113SDavid du Colombier "%#.4lux",
1249a747e4fSDavid du Colombier p_fields,
1253ff48bf5SDavid du Colombier defaultframer
1269a747e4fSDavid du Colombier };
127