fluffy/pcat.c

208 lines
3.8 KiB
C
Raw Normal View History

2013-07-23 16:30:38 -06:00
/*
* pcat.c -- pcap to text
*
* Reads pcap on stdin, dumps text representation to stdout.
* This discards or ignores some parts of packets. If fidelity is a concern,
* deal directly with the original pcap.
*
* Output lines are of the form:
*
* PROTO SRC DST OPTS PAYLOAD
*
*/
2013-01-29 21:45:44 -07:00
#include <stdio.h>
#include <stdint.h>
#include "pcap.h"
#include "stream.h"
#define IPPROTO_TCP 6
#define IPPROTO_UDP 17
2013-02-11 15:50:30 -07:00
#define IPPROTO_ICMP 1
2013-01-29 21:45:44 -07:00
#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)
{
2013-01-29 21:53:17 -07:00
snprintf(addr_s, 16, "%u.%u.%u.%u", (addr >> 24) & 0xff, (addr >> 16) & 0xff, (addr >> 8) & 0xff, (addr >> 0) & 0xff);
2013-01-29 21:45:44 -07:00
}
void
print_payload(struct stream *s)
{
while (s->len) {
printf("%02x", read_uint8(s));
2013-01-29 21:53:17 -07:00
}
2013-01-29 21:45:44 -07:00
}
void
process_tcp(struct stream *s, char *saddr_s, char *daddr_s)
{
2013-07-23 16:30:38 -06:00
uint16_t sport = read_uint16(s);
uint16_t dport = read_uint16(s);
uint32_t seq = read_uint32(s);
uint32_t ack = read_uint32(s);
2013-01-29 21:53:17 -07:00
uint8_t off = read_uint8(s);
uint8_t hlen = (off >> 4) * 4;
uint8_t flags = read_uint8(s);
2013-07-23 16:30:38 -06:00
uint16_t window = read_uint16(s);
uint16_t chksum = read_uint16(s);
uint16_t urgent = read_uint16(s);
2013-01-29 21:53:17 -07:00
if (hlen < 20) {
printf("!");
}
2013-07-23 16:30:38 -06:00
printf("TCP %s,%u %s,%u %u,%u,%d ", saddr_s, sport, daddr_s, dport, seq, ack, flags);
2013-01-29 21:45:44 -07:00
}
void
process_udp(struct stream *s, char *saddr_s, char *daddr_s)
{
2013-07-23 16:30:38 -06:00
uint16_t sport = read_uint16(s);
uint16_t dport = read_uint16(s);
uint16_t len = read_uint16(s);
uint16_t chksum = read_uint16(s);
2013-01-29 21:53:17 -07:00
2013-07-23 16:30:38 -06:00
printf("UDP %s,%u %s,%u 0 ", saddr_s, sport, daddr_s, dport);
2013-02-11 15:50:30 -07:00
}
2013-01-29 21:53:17 -07:00
2013-02-11 15:50:30 -07:00
void
process_icmp(struct stream *s, char *saddr_s, char *daddr_s)
{
uint8_t type = read_uint8(s);
uint8_t code = read_uint8(s);
2013-07-23 16:30:38 -06:00
uint16_t checksum = read_uint16(s);
2013-02-11 15:50:30 -07:00
2013-07-26 14:08:48 -06:00
printf("ICMP %d,%d %s %s ", type, code, saddr_s, daddr_s);
2013-01-29 21:45:44 -07:00
}
void
process_ip4(struct stream *s)
{
2013-01-29 21:53:17 -07:00
uint8_t vhl = read_uint8(s);
uint8_t ihl = (vhl & 0x0f) * 4;
uint8_t tos = read_uint8(s);
2013-07-23 16:30:38 -06:00
uint16_t length = read_uint16(s);
uint16_t id = read_uint16(s);
uint16_t off = read_uint16(s);
2013-01-29 21:53:17 -07:00
uint8_t ttl = read_uint8(s);
uint8_t proto = read_uint8(s);
2013-07-23 16:30:38 -06:00
uint16_t chksum = read_uint16(s);
uint32_t saddr = read_uint32(s);
uint32_t daddr = read_uint32(s);
2013-01-29 21:53:17 -07:00
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;
2013-02-11 15:50:30 -07:00
case IPPROTO_ICMP:
process_icmp(s, saddr_s, daddr_s);
break;
2013-01-29 21:53:17 -07:00
default:
printf("P%d %s %s ", proto, saddr_s, daddr_s);
break;
}
print_payload(s);
2013-01-29 21:45:44 -07:00
}
void
print_ethernet(struct stream *s)
{
2013-01-29 21:53:17 -07:00
uint8_t saddr[6];
uint8_t daddr[6];
uint16_t ethertype;
sread(s, &saddr, sizeof(saddr));
sread(s, &daddr, sizeof(daddr));
2013-07-23 16:30:38 -06:00
ethertype = read_uint16(s);
2013-01-29 21:53:17 -07:00
if (ethertype == 0x8100) {
// VLAN
2013-07-23 16:30:38 -06:00
read_uint16(s);
ethertype = read_uint16(s);
2013-01-29 21:53:17 -07:00
}
switch (ethertype) {
case 0x0800: // IPv4
process_ip4(s);
break;
}
2013-01-29 21:45:44 -07:00
}
void
2013-02-11 15:50:30 -07:00
print_frame(struct pcap_file *p, struct pcap_pkthdr *hdr, char const *frame)
2013-01-29 21:45:44 -07:00
{
2013-01-29 21:53:17 -07:00
struct stream streambuf;
struct stream *s = &streambuf;
sinit(s, frame, hdr->caplen);
2013-01-29 22:25:15 -07:00
printf("%u.%u ", hdr->ts.tv_sec, hdr->ts.tv_usec);
2013-02-11 15:50:30 -07:00
switch (p->linktype) {
case LINKTYPE_ETHERNET:
print_ethernet(s);
break;
case LINKTYPE_RAW:
process_ip4(s);
break;
}
2013-01-29 21:53:17 -07:00
printf("\n");
2013-01-29 21:45:44 -07:00
}
void
2013-01-29 21:53:17 -07:00
pcat(FILE * f)
2013-01-29 21:45:44 -07:00
{
struct pcap_file p;
2013-01-29 21:53:17 -07:00
if (-1 == pcap_open_in(&p, f))
return;
2013-01-29 21:45:44 -07:00
for (;;) {
struct pcap_pkthdr hdr;
char frame[MAXFRAME];
2013-01-29 21:53:17 -07:00
2013-01-29 21:45:44 -07:00
if (-1 == pcap_read_pkthdr(&p, &hdr)) {
break;
}
2013-01-29 21:53:17 -07:00
2013-01-29 21:45:44 -07:00
if (1 != fread(frame, hdr.caplen, 1, f)) {
break;
}
2013-01-29 21:53:17 -07:00
2013-02-11 15:50:30 -07:00
print_frame(&p, &hdr, frame);
2013-01-29 21:45:44 -07:00
}
}
int
main(int argc, char *argv[])
{
pcat(stdin);
2013-01-29 21:53:17 -07:00
2013-01-29 21:45:44 -07:00
return 0;
2013-01-29 21:53:17 -07:00
}