Led Firewall (netled)

Last Updated or created 2023-01-04

FW led box without labels

Above is a picture of a Box with leds which lightup when certain network packets are seen on the network.

It is connected to the parallel port of a PC (using port 0x3bc)

Makefile:

CC=gcc
CCOPT=-O2 -I/usr/include/pcap
LIBS=-lpcap

all:	netled

netled:	netled.c
	$(CC) $(CCOPT) -o netled netled.c $(LIBS)

netled.c code ( older version, i will upload a newer if found)

#include <stdio.h>
#include <pcap.h>
#include <netinet/in.h>
#include <sys/io.h>
#include <sys/time.h>
#include <signal.h>
#include "ether.h"
#include "ethertype.h"
#include "ip.h"
#include "tcp.h"

#define LP_PORT 0x3bc
#define CAPLEN 64
#define DELAY 30000

char *program_name;
static pcap_t *pd;
const u_char *snapend;
u_char leds = 0;
int mode = 0;
long packets;

void do_leds() {
    mode ^= 1;

    if(!leds && mode) return;

    if(mode) {
	outb(leds, LP_PORT);
	leds = 0;
    }
    else {
	outb(0, LP_PORT);
    }
}

int do_tcp(register const u_char *bp) {
    register const struct tcphdr *tp;
    u_int16_t sport, dport;

    tp = (struct tcphdr *)bp;
    sport = ntohs(tp->th_sport);
    dport = ntohs(tp->th_dport);

    if (sport == 22 || dport == 22) {
	leds |= 8;
    }

    return;
}

int do_ip(register const u_char *bp, register u_int length) {
    register const struct ip *ip;
    register u_int hlen, len, len0, off;
    register const u_char *cp;

    ip = (const struct ip *)bp;

    if ((u_char *)(ip + 1) > snapend ||
	length < sizeof (struct ip)) {
	return;
    }

    hlen = IP_HL(ip) * 4;
    if (hlen < sizeof (struct ip)) {
	fprintf(stderr, "bad-hlen %d\n", hlen);
	return;
    }

    len = ntohs(ip->ip_len);
    if (length < len)
	(void)printf("truncated-ip - %d bytes missing!",
	    len - length);
    len -= hlen;
    len0 = len;


    off = ntohs(ip->ip_off);
    if ((off & 0x1fff) == 0) {
	cp = (const u_char *)ip + hlen;

	switch(ip->ip_p) {

	    case IPPROTO_TCP:
		// fprintf(stderr, "TCP!\n");
		leds |= 128;
		do_tcp(cp);
		break;

	    case IPPROTO_UDP:
		// fprintf(stderr, "UDP!\n");
		leds |= 64;
		break;

	    case IPPROTO_ICMP:
		// fprintf(stderr, "ICMP!\n");
		leds |= 32;
		break;

	    default:
		fprintf(stderr, "HUH? [ip_proto: %i]\n", ip->ip_p);
		break;
	}
    }
}

void handler(u_char *user, const struct pcap_pkthdr *h, const u_char *p) {
    u_int caplen = h->caplen;
    u_int length = h->len;
    u_short ether_type;
    register const struct ether_header *ep;
    u_short extracted_ethertype;

    if (caplen < ETHER_HDRLEN) {
	printf("c: [%d] e: [%d]\n", caplen, ETHER_HDRLEN);
	return;
    }

    ep = (struct ether_header *)p;
    ether_type = ntohs(ep->ether_type);

    snapend = p + caplen;
    p += ETHER_HDRLEN;
    length -= ETHER_HDRLEN;
    if (ether_type > ETHERMTU) {


	switch (ether_type) {

	    case ETHERTYPE_ARP:
	    case ETHERTYPE_REVARP:
		// leds |= 8;
                // fprintf(stderr, "(R)ARP\n");
		break;

	    case ETHERTYPE_IP:
		// fprintf(stderr, "IP!\n");
		do_ip(p, length);
		break;

	    default:
		fprintf(stderr, "HUH? [et: %i]\n", ether_type);

	}
    }
}

int main(int argc, char *argv[]) {
    char *device;
    char ebuf[PCAP_ERRBUF_SIZE];
    register char *cp;
    u_char *pcap_userdata;
    void *sig_old;
    struct itimerval timer_old, timer_new;

    if ((cp = (char *)strrchr(argv[0], '/')) != NULL)
	program_name = cp + 1;
    else
	program_name = argv[0];

    if(ioperm(LP_PORT,3,1))
	error("IOPEEEEERM!\n");

    sig_old = signal(SIGALRM, do_leds);
    if (sig_old == SIG_ERR)
	error("SIGNAAAAAAAAAAAAAL!\n");
    timer_new.it_value.tv_usec = DELAY;
    timer_new.it_value.tv_sec = 0;
    timer_new.it_interval.tv_usec = DELAY;
    timer_new.it_interval.tv_sec = 0;
    if(setitimer(ITIMER_REAL, &timer_new, &timer_old))
	error("SETITIMEEEEEER!\n");

    device = pcap_lookupdev(ebuf);
    if (device == NULL)
	error("%s", ebuf);

    pd = pcap_open_live(device, CAPLEN, 1, 1000, ebuf);
    if (pd == NULL)
	error("%s", ebuf);

    if (pcap_loop(pd, -1, handler, pcap_userdata) < 0) {
	(void)fprintf(stderr, "%s: pcap_loop: %s\n",
	    program_name, pcap_geterr(pd));
	exit(1);
    }

    return 0;
}