/* * (C)opyright 1993,1994,1995 by Darren Reed. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and due credit is given * to the original author and the contributors. */ #include #include #if !defined(__SVR4) && !defined(__GNUC__) #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "ip_fil.h" #include "ipf.h" #include "ipt.h" #include "pcap.h" struct llc { int lc_sz; /* LLC header length */ int lc_to; /* LLC Type offset */ int lc_tl; /* LLC Type length */ }; /* * While many of these maybe the same, some do have different header formats * which make this useful. */ #define DLT_MAX 10 static struct llc llcs[DLT_MAX+1] = { { 0, 0, 0 }, /* DLT_NULL */ { 14, 12, 2 }, /* DLT_E10MB */ { 0, 0, 0 }, /* DLT_EN3MB */ { 0, 0, 0 }, /* DLT_AX25 */ { 0, 0, 0 }, /* DLT_PRONET */ { 0, 0, 0 }, /* DLT_CHAOS */ { 0, 0, 0 }, /* DLT_IEEE802 */ { 0, 0, 0 }, /* DLT_ARCNET */ { 0, 0, 0 }, /* DLT_SLIP */ { 0, 0, 0 }, /* DLT_PPP */ { 0, 0, 0 } /* DLT_FDDI */ }; static int pcap_open(), pcap_close(), pcap_readip(); static int pfd = -1, s_type = -1; struct ipread pcap = { pcap_open, pcap_close, pcap_readip }; static int pcap_open(fname) char *fname; { pcaphdr_t ph; int fd; if (pfd != -1) return pfd; if (!strcmp(fname, "-")) fd = 0; else if ((fd = open(fname, O_RDONLY)) == -1) return -1; if (read(fd, (char *)&ph, sizeof(ph)) != sizeof(ph)) return -2; if (ph.pc_v_maj != PCAP_VERSION_MAJ || ph.pc_type > DLT_MAX) { (void) close(fd); return -2; } pfd = fd; s_type = ph.pc_type; printf("opened pcap file %s:\n", fname); printf("\tid: %08x version: %d.%d type: %d snap %d\n", ph.pc_id, ph.pc_v_maj, ph.pc_v_min, ph.pc_type, ph.pc_slen); return fd; } static int pcap_close() { return close(pfd); } /* * read in the header (and validate) which should be the first record * in a pcap file. */ static int pcap_read_rec(rec) struct pcap_pkthdr *rec; { int n, p; if (read(pfd, (char *)rec, sizeof(*rec)) != sizeof(*rec)) return -2; p = rec->ph_clen; n = MIN(p, rec->ph_len); if (!n || n < 0) return -3; return p; } #ifdef notyet /* * read an entire pcap packet record. only the data part is copied into * the available buffer, with the number of bytes copied returned. */ static int pcap_read(buf, cnt) char *buf; int cnt; { struct pcap_pkthdr rec; static char *bufp = NULL; int i, n; if ((i = pcap_read_rec(&rec)) <= 0) return i; if (!bufp) bufp = malloc(i); else bufp = realloc(bufp, i); if (read(pfd, bufp, i) != i) return -2; n = MIN(i, cnt); bcopy(bufp, buf, n); return n; } #endif /* * return only an IP packet read into buf */ static int pcap_readip(buf, cnt, ifn, dir) char *buf, **ifn; int cnt, *dir; { static char *bufp = NULL; struct pcap_pkthdr rec; struct llc *l; char *s, ty[4]; int i, n; do { if ((i = pcap_read_rec(&rec)) <= 0) return i; if (!bufp) bufp = malloc(i); else bufp = realloc(bufp, i); s = bufp; if (read(pfd, s, i) != i) return -2; l = &llcs[s_type]; i -= l->lc_sz; s += l->lc_to; bcopy(s, ty, l->lc_tl); s += l->lc_tl; } while (ty[0] != 0x8 && ty[1] != 0); n = MIN(i, cnt); bcopy(s, buf, n); return n; }