Plan 9 from Bell Labs’s /usr/web/sources/contrib/axel/8021x/v216/ether.c

Copyright © 2021 Plan 9 Foundation.
Distributed under the MIT License.
Download the Plan 9 distribution.


#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);
}


Bell Labs OSI certified Powered by Plan 9

(Return to Plan 9 Home Page)

Copyright © 2021 Plan 9 Foundation. All Rights Reserved.
Comments to [email protected].