xref: /plan9-contrib/sys/src/cmd/ip/snoopy/eapol.c (revision ed397113cdcf7aafea372b730bbcd17b05ee3f60)
1 #include <u.h>
2 #include <libc.h>
3 #include <ip.h>
4 #include "dat.h"
5 #include "protos.h"
6 
7 typedef struct Hdr	Hdr;
8 struct Hdr
9 {
10 	uchar	vi;		/* version */
11 	uchar	type;
12 	uchar	len[2];	/* length of data following this header */
13 };
14 
15 enum
16 {
17 	EAPOLHDR=	4,		/* sizeof(Hdr) */
18 
19 	/* eapol types */
20 	Eap = 0,
21 	Start,
22 	Logoff,
23 	Key,
24 	AsfAlert,
25 };
26 
27 enum
28 {
29 	Ot,	/* type */
30 };
31 
32 static Mux p_mux[] =
33 {
34 	{ "eap", Eap, },
35 	{ "eapol_start", Start, },
36 	{ "eapol_logoff", Logoff, },
37 	{ "eapol_key", Key, },
38 	{ "asf_alert", AsfAlert, },
39 	{ 0 }
40 };
41 
42 static void
p_compile(Filter * f)43 p_compile(Filter *f)
44 {
45 	Mux *m;
46 
47 	for(m = p_mux; m->name != nil; m++)
48 		if(strcmp(f->s, m->name) == 0){
49 			f->pr = m->pr;
50 			f->ulv = m->val;
51 			f->subop = Ot;
52 			return;
53 		}
54 	sysfatal("unknown eapol field or type: %s", f->s);
55 }
56 
57 static int
p_filter(Filter * f,Msg * m)58 p_filter(Filter *f, Msg *m)
59 {
60 	Hdr *h;
61 
62 	if(m->pe - m->ps < EAPOLHDR)
63 		return 0;
64 
65 	h = (Hdr*)m->ps;
66 
67 	/* len does not include header */
68 	m->ps += EAPOLHDR;
69 
70 	switch(f->subop){
71 	case Ot:
72 		return h->type == f->ulv;
73 	}
74 	return 0;
75 }
76 
77 static char*
op(int i)78 op(int i)
79 {
80 	static char x[20];
81 
82 	switch(i){
83 	case Eap:
84 		return "Eap";
85 	case Start:
86 		return "Start";
87 	case Logoff:
88 		return "Logoff";
89 	case Key:
90 		return "Key";
91 	case AsfAlert:
92 		return "AsfAlert";
93 	default:
94 		sprint(x, "%1d", i);
95 		return x;
96 	}
97 }
98 
99 static int
p_seprint(Msg * m)100 p_seprint(Msg *m)
101 {
102 	Hdr *h;
103 	int len;
104 
105 	if(m->pe - m->ps < EAPOLHDR)
106 		return -1;
107 
108 	h = (Hdr*)m->ps;
109 
110 	/* len does not include header */
111 	m->ps += EAPOLHDR;
112 
113 	/* truncate the message if there's extra */
114 	len = NetS(h->len);
115 	if(m->ps + len < m->pe)
116 		m->pe = m->ps + len;
117 	else if(m->ps+len > m->pe)
118 		return -1;
119 
120 	/* next protocol  depending on type*/
121 	demux(p_mux, h->type, h->type, m, &dump);
122 
123 	m->p = seprint(m->p, m->e, "type=%s version=%1d datalen=%1d",
124 			op(h->type), h->vi, len);
125 	return 0;
126 }
127 
128 Proto eapol =
129 {
130 	"eapol",
131 	p_compile,
132 	p_filter,
133 	p_seprint,
134 	p_mux,
135 	"%lud",
136 	nil,
137 	defaultframer,
138 };
139