mirror of https://github.com/dirtbags/fluffy.git
Nascent pcat utility
This commit is contained in:
parent
010ae25fa3
commit
31e9beb71a
3
Makefile
3
Makefile
|
@ -1,12 +1,13 @@
|
||||||
CFLAGS = -Wall -Werror
|
CFLAGS = -Wall -Werror
|
||||||
TARGETS = pmerge puniq p4split hd
|
TARGETS = pmerge puniq p4split hd
|
||||||
TARGETS += pyesc printfesc
|
TARGETS += pyesc printfesc pcat
|
||||||
|
|
||||||
all: $(TARGETS)
|
all: $(TARGETS)
|
||||||
|
|
||||||
pmerge: pmerge.o pcap.o
|
pmerge: pmerge.o pcap.o
|
||||||
puniq: puniq.o pcap.o
|
puniq: puniq.o pcap.o
|
||||||
p4split: p4split.c pcap.o
|
p4split: p4split.c pcap.o
|
||||||
|
pcat: pcat.c pcap.o stream.o
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f $(TARGETS) *.o
|
rm -f $(TARGETS) *.o
|
||||||
|
|
|
@ -0,0 +1,199 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include "pcap.h"
|
||||||
|
#include "stream.h"
|
||||||
|
|
||||||
|
#define IPPROTO_TCP 6
|
||||||
|
#define IPPROTO_UDP 17
|
||||||
|
#define TH_FIN 0x01
|
||||||
|
#define TH_SYN 0x02
|
||||||
|
#define TH_RST 0x04
|
||||||
|
#define TH_PSH 0x08
|
||||||
|
#define TH_ACK 0x10
|
||||||
|
#define TH_URG 0x20
|
||||||
|
|
||||||
|
void
|
||||||
|
ip4_addr(char *addr_s, uint32_t addr)
|
||||||
|
{
|
||||||
|
snprintf(addr_s, 16, "%u.%u.%u.%u",
|
||||||
|
(addr >> 24) & 0xff,
|
||||||
|
(addr >> 16) & 0xff,
|
||||||
|
(addr >> 8) & 0xff,
|
||||||
|
(addr >> 0) & 0xff);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
print_payload(struct stream *s)
|
||||||
|
{
|
||||||
|
while (s->len) {
|
||||||
|
printf("%02x", read_uint8(s));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
process_tcp(struct stream *s, char *saddr_s, char *daddr_s)
|
||||||
|
{
|
||||||
|
uint16_t sport = read_uint16be(s);
|
||||||
|
uint16_t dport = read_uint16be(s);
|
||||||
|
uint32_t seq = read_uint32be(s);
|
||||||
|
uint32_t ack = read_uint32be(s);
|
||||||
|
uint8_t off = read_uint8(s);
|
||||||
|
uint8_t hlen = (off >> 4) * 4;
|
||||||
|
uint8_t flags = read_uint8(s);
|
||||||
|
uint16_t window = read_uint16be(s);
|
||||||
|
uint16_t chksum = read_uint16be(s);
|
||||||
|
uint16_t urgent = read_uint16be(s);
|
||||||
|
|
||||||
|
if (hlen < 20) {
|
||||||
|
printf("!");
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("TCP4 %s:%u %s:%u ", saddr_s, sport, daddr_s, dport);
|
||||||
|
|
||||||
|
// shut the compiler up
|
||||||
|
if (false &&
|
||||||
|
urgent &&
|
||||||
|
chksum &&
|
||||||
|
window &&
|
||||||
|
flags &&
|
||||||
|
ack &&
|
||||||
|
seq &&
|
||||||
|
false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
process_udp(struct stream *s, char *saddr_s, char *daddr_s)
|
||||||
|
{
|
||||||
|
uint16_t sport = read_uint16be(s);
|
||||||
|
uint16_t dport = read_uint16be(s);
|
||||||
|
uint16_t len = read_uint16be(s);
|
||||||
|
uint16_t chksum = read_uint16be(s);
|
||||||
|
|
||||||
|
printf("UDP4 %s:%u %s:%u ", saddr_s, sport, daddr_s, dport);
|
||||||
|
|
||||||
|
// Now, do some shit!
|
||||||
|
if (false &&
|
||||||
|
len &&
|
||||||
|
chksum &&
|
||||||
|
false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
process_ip4(struct stream *s)
|
||||||
|
{
|
||||||
|
uint8_t vhl = read_uint8(s);
|
||||||
|
uint8_t ihl = (vhl & 0x0f) * 4;
|
||||||
|
uint8_t tos = read_uint8(s);
|
||||||
|
uint16_t length = read_uint16be(s);
|
||||||
|
uint16_t id = read_uint16be(s);
|
||||||
|
uint16_t off = read_uint16be(s);
|
||||||
|
uint8_t ttl = read_uint8(s);
|
||||||
|
uint8_t proto = read_uint8(s);
|
||||||
|
uint16_t chksum = read_uint16be(s);
|
||||||
|
uint32_t saddr = read_uint32be(s);
|
||||||
|
uint32_t daddr = read_uint32be(s);
|
||||||
|
|
||||||
|
char saddr_s[20];
|
||||||
|
char daddr_s[20];
|
||||||
|
|
||||||
|
ip4_addr(saddr_s, saddr);
|
||||||
|
ip4_addr(daddr_s, daddr);
|
||||||
|
|
||||||
|
// Ignore options
|
||||||
|
sskip(s, 20 - ihl);
|
||||||
|
|
||||||
|
// Force stream length to IP payload length
|
||||||
|
s->len = length - ihl;
|
||||||
|
|
||||||
|
switch (proto) {
|
||||||
|
case IPPROTO_TCP:
|
||||||
|
process_tcp(s, saddr_s, daddr_s);
|
||||||
|
break;
|
||||||
|
case IPPROTO_UDP:
|
||||||
|
process_udp(s, saddr_s, daddr_s);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
printf("P%d %s %s ", proto, saddr_s, daddr_s);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
print_payload(s);
|
||||||
|
|
||||||
|
/* Placate compiler */
|
||||||
|
if (false &&
|
||||||
|
chksum &&
|
||||||
|
id &&
|
||||||
|
tos &&
|
||||||
|
ttl &&
|
||||||
|
off &&
|
||||||
|
false);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
print_ethernet(struct stream *s)
|
||||||
|
{
|
||||||
|
uint8_t saddr[6];
|
||||||
|
uint8_t daddr[6];
|
||||||
|
uint16_t ethertype;
|
||||||
|
|
||||||
|
sread(s, &saddr, sizeof(saddr));
|
||||||
|
sread(s, &daddr, sizeof(daddr));
|
||||||
|
ethertype = read_uint16be(s);
|
||||||
|
|
||||||
|
if (ethertype == 0x8100) {
|
||||||
|
// VLAN
|
||||||
|
read_uint16be(s);
|
||||||
|
ethertype = read_uint16be(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (ethertype) {
|
||||||
|
case 0x0800: // IPv4
|
||||||
|
process_ip4(s);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
print_frame(struct pcap_pkthdr *hdr, char const *frame)
|
||||||
|
{
|
||||||
|
struct stream streambuf;
|
||||||
|
struct stream *s = &streambuf;
|
||||||
|
|
||||||
|
sinit(s, frame, hdr->caplen);
|
||||||
|
printf("%u,%u ", hdr->ts.tv_sec, hdr->ts.tv_usec);
|
||||||
|
print_ethernet(s);
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
pcat(FILE *f)
|
||||||
|
{
|
||||||
|
struct pcap_file p;
|
||||||
|
|
||||||
|
if (-1 == pcap_open_in(&p, f)) return;
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
struct pcap_pkthdr hdr;
|
||||||
|
char frame[MAXFRAME];
|
||||||
|
|
||||||
|
if (-1 == pcap_read_pkthdr(&p, &hdr)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (1 != fread(frame, hdr.caplen, 1, f)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
print_frame(&hdr, frame);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
pcat(stdin);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,106 @@
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "stream.h"
|
||||||
|
|
||||||
|
void
|
||||||
|
sinit(struct stream *s, char const *buf, size_t buflen)
|
||||||
|
{
|
||||||
|
s->buf = buf;
|
||||||
|
s->len = buflen;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
sskip(struct stream *s, size_t count)
|
||||||
|
{
|
||||||
|
if (count > s->len) {
|
||||||
|
s->len = 0;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
s->buf += count;
|
||||||
|
s->len -= count;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
sread(struct stream *s, void *buf, size_t count)
|
||||||
|
{
|
||||||
|
void const *d = s->buf;
|
||||||
|
|
||||||
|
if (! sskip(s, count)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
memcpy(buf, d, count);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t
|
||||||
|
read_uint8(struct stream *s)
|
||||||
|
{
|
||||||
|
uint8_t *d = (uint8_t *)s->buf;
|
||||||
|
|
||||||
|
if (! sskip(s, 1)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return d[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t
|
||||||
|
read_uint16be(struct stream *s)
|
||||||
|
{
|
||||||
|
uint8_t *d = (uint8_t *)s->buf;
|
||||||
|
|
||||||
|
if (! sskip(s, 2)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
(d[0] << 8) |
|
||||||
|
(d[1] << 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t
|
||||||
|
read_uint16le(struct stream *s)
|
||||||
|
{
|
||||||
|
uint8_t *d = (uint8_t *)s->buf;
|
||||||
|
|
||||||
|
if (! sskip(s, 2)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
(d[0] << 0) |
|
||||||
|
(d[1] << 8));
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t
|
||||||
|
read_uint32be(struct stream *s)
|
||||||
|
{
|
||||||
|
uint8_t *d = (uint8_t *)s->buf;
|
||||||
|
|
||||||
|
if (! sskip(s, 4)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
(d[0] << 24) |
|
||||||
|
(d[1] << 16) |
|
||||||
|
(d[2] << 8) |
|
||||||
|
(d[3] << 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t
|
||||||
|
read_uint32le(struct stream *s)
|
||||||
|
{
|
||||||
|
uint8_t *d = (uint8_t *)s->buf;
|
||||||
|
|
||||||
|
if (! sskip(s, 4)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
(d[0] << 0) |
|
||||||
|
(d[1] << 8) |
|
||||||
|
(d[2] << 16) |
|
||||||
|
(d[3] << 24));
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
#ifndef _STREAM_H
|
||||||
|
#define _STREAM_H
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
struct stream {
|
||||||
|
char const *buf;
|
||||||
|
size_t len;
|
||||||
|
};
|
||||||
|
|
||||||
|
void sinit(struct stream *s, char const *buf, size_t len);
|
||||||
|
bool sskip(struct stream *s, size_t count);
|
||||||
|
bool sread(struct stream *s, void *buf, size_t count);
|
||||||
|
uint8_t read_uint8(struct stream *s);
|
||||||
|
uint16_t read_uint16be(struct stream *s);
|
||||||
|
uint16_t read_uint16le(struct stream *s);
|
||||||
|
uint32_t read_uint32be(struct stream *s);
|
||||||
|
uint32_t read_uint32le(struct stream *s);
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in New Issue