#include <u.h>
#include <libc.h>
#include <thread.h>
#include <ip.h>
#include "dat.h"
#include "fns.h"
// ========== receive eapol frames
Etherstate theEther;
static void*
newPacket(void)
{
Packet *p;
p = malloc(sizeof(Packet));
if (p == nil)
logfatal(1, "could not allocate Packet");
memset(p, 0, sizeof(Packet));
p->b = malloc(Pktlen);
if (p->b == nil)
logfatal(1, "could not allocate Packet buffer");
p->e = p->b;
p->ether = (Ether*)p->b;
p->eapol = (Eapol*)p->ether->data;
p->eap = (Eap*)p->eapol->data;
return p;
}
Etherstate* initether(void)
{
Etherstate *e;
int i;
e = &theEther;
memset(e, 0, sizeof(Ether));
e->lastEapId = -1;
e->packetc = chancreate(sizeof(Packet*), 0);
e->statusc = chancreate(sizeof(int), 0);
e->donec = chancreate(sizeof(int), 0);
e->donesent = 0;
// e->keyTime = e->startTime;
for (i = 0; i < Npkt; i++)
e->pktr[i] = newPacket();
e->pktt = newPacket();
return e;
}
void
etherproc(void *arg)
{
Etherstate *e;
Packet *rx;
int n;
e = arg;
for(;;) {
rx = e->pktr[e->pkgidx];
loglog("etherproc: waiting for %d into %p", e->fd, rx);
// don't do this: we do not reset rx-> for packets not sent over packetc
//if (rx->e != rx->b)
// logfatal("assertion failed: rx->e != rx->b (n == %ld)", rx->e - rx->b);
n = read(e->fd, rx->b, Pktlen);
loglog("etherproc: read from %d into %p: %d", e->fd, rx, n);
if(n <= 0)
break;
rx->e = rx->b + n;
if (rx->e < rx->ether->data) {
logall("etherproc: skipping short packet (ether len=%d)", n);
continue;
}
if (nhgets(rx->ether->t) != ETEAPOL) {
logall("etherproc: skipping non-ETEAPOL %x", nhgets(rx->ether->t));
continue;
}
if (rx->e < rx->eapol->data) {
logall("etherproc: skipping short packet (ether len=%d)", n);
continue;
}
if (rx->e < rx->eapol->data + nhgets(rx->eapol->ln)) {
logall("etherproc: skipping short packet (ether len=%d)", n);
continue;
}
switch(rx->eapol->tp) {
case EapolTpEap:
if (rx->e < rx->eap->data) {
logall("etherproc: skipping short packet (ether len=%d)", n);
continue;
}
if (rx->e < rx->eapol->data + nhgets(rx->eap->ln)) {
logall("etherproc: skipping short packet (ether len=%d)", n);
continue;
}
if (e->lastEapId == rx->eap->id)
loglog("etherproc lastEapId==eap->id==%d", rx->eap->id);
e->lastEapId = rx->eap->id;
switch(rx->eap->code) {
case EapRequest:
loglog("- - - - Eap Request id=%d - - - - ", rx->eap->id);
loglog("etherproc: about to send %p ", rx);
send(e->packetc, &rx);
loglog("\tetherproc: done send %p ", rx);
e->pkgidx = (e->pkgidx+1)%Npkt;
break;
case EapResponse:
loglog("- - - - Eap Response id=%d - - - - ", rx->eap->id);
break;
case EapSuccess:
loglog("- - - - success id=%d - - - -", rx->eap->id);
syslog(0, logname, "etherproc: success id=%d", rx->eap->id);
e->verdictTime = nsec();
e->eapSuccess = 1;
send(e->statusc, nil);
if (! e->donesent) {
e->donesent = 1;
send(e->donec, nil);
}
clearlog(getKeysbuf());
break;
case EapFailure:
loglog("- - - - fail id=%d - - - -", rx->eap->id);
syslog(0, logname, "etherproc: fail id=%d", rx->eap->id);
e->verdictTime = nsec();
e->eapFail = 1;
send(e->statusc, nil);
clearlog(getKeysbuf());
break;
default:
loglog("- - - - unknown eap id=%d type=%d - - - - ", rx->eap->id, rx->eap->code);
syslog(0, logname, "etherproc: unknown eap id=%d type=%d", rx->eap->id, rx->eap->code);
break;
}
break;
case EapolTpStart:
logall("etherproc: start (ignored)");
break;
case EapolTpLogoff:
logall("etherproc: logoff (ignored)");
break;
case EapolTpKey:
if (e->keyRun || e->eapSuccess) {
loglog("- - - - key - - - -");
syslog(0, logname, "etherproc: key");
e->keyTime = nsec();
handleKey(e->cfd, rx->eapol, rx->e - rx->ether->data);
e->keyDone = 1;
} else
logall("etherproc: ignoring key (not authed yet)");
break;
case EapolTpAsf:
logall("etherproc: asf (ignored)");
break;
default:
logall("etherproc: unknown type%d", rx->eapol->tp);
break;
}
}
logfatal(0, "etherproc: oops read %d...", n);
}
|