pcap_names = @names c32le { typedef struct pcap_hdr_s pcap_hdr_t; struct pcap_hdr_s { @0 uint32 magic_number; /* magic number */ @4 uint16 version_major; /* major version number */ @6 uint16 version_minor; /* minor version number */ @8 int32 thiszone; /* GMT to local correction */ @12 uint32 sigfigs; /* accuracy of timestamps */ @16 uint32 snaplen; /* max length of captured packets, in octets */ @20 uint32 network; /* data link type */ @24; }; struct timeval { @0x0 int32 tv_sec; @0x4 int32 tv_usec; @0x8; }; struct pcap_pkthdr { @0x0 struct timeval ts; @0x8 uint32 caplen; @0xc uint32 len; @0x10; }; // from libpcap/savefile.c // there are others possible enum pcap_magic { TCPDUMP_MAGIC = 0xa1b2c3d4, KUZNETZOV_TCPDUMP_MAGIC = 0xa1b2cd34, FMESQUITA_TCPDUMP_MAGIC = 0xa1b234cd, NAVTEL_TCPDUMP_MAGIC = 0xa12b3c4d, NSEC_TCPDUMP_MAGIC = 0xa1b23c4d, }; // from libpcap/savefile.c // Not even close to all them are here... enum pcap_linktype { LINKTYPE_NULL = 0, LINKTYPE_ETHERNET = 1, /* also for 100Mb and up */ LINKTYPE_EXP_ETHERNET = 2, /* 3Mb experimental Ethernet */ }; }; eth_names = @names c32be { // ethernet stuff from linux/if_ether.h struct ethhdr { @0 unsigned char h_dest[6]; /* destination eth addr */ @6 unsigned char h_source[6]; /* source ether addr */ @12 uint16 h_proto; /* packet type ID field */ @14; }; // not exhaustive... enum proto_ids { ETH_P_LOOP = 0x0060, /* Ethernet Loopback packet */ ETH_P_PUP = 0x0200, /* Xerox PUP packet */ ETH_P_PUPAT= 0x0201, /* Xerox PUP Addr Trans packet */ ETH_P_IP = 0x0800, /* Internet Protocol packet */ ETH_P_X25 = 0x0805, /* CCITT X.25 */ ETH_P_ARP = 0x0806, /* Address Resolution packet */ }; struct iphdr { @@0x0 uint8 ip_vers:4; @@0x4 uint8 ip_hlen:4; @@0x8 uint8 ip_prec:3; @@0xb uint8 ip_mdflag:1; @@0xc uint8 ip_mtflag:1; @@0xd uint8 ip_mrflag:1; @@0xe uint8 ip_mmflag:1; @0x2 uint16 ip_len; @0x4 uint16 ip_id; @@0x31 uint8 ip_dfflag:1; @@0x32 uint8 ip_mfflag:1; @@0x33 uint16 ip_fragoffs:13; @0x8 uint8 ip_ttl; @0x9 uint8 ip_proto; @0xa uint16 ip_csum; @0xc uint32 ip_src; @0x10 uint32 ip_dst; @0x14; }; // from include/netinet/in.h enum ip_protos { IPPROTO_IP = 0, /* Dummy protocol for TCP. */ IPPROTO_HOPOPTS = 0, /* IPv6 Hop-by-Hop options. */ IPPROTO_ICMP = 1, /* Internet Control Message Protocol. */ IPPROTO_IGMP = 2, /* Internet Group Management Protocol. */ IPPROTO_IPIP = 4, /* IPIP tunnels (older KA9Q tunnels use 94). */ IPPROTO_TCP = 6, /* Transmission Control Protocol. */ IPPROTO_EGP = 8, /* Exterior Gateway Protocol. */ IPPROTO_PUP = 12, /* PUP protocol. */ IPPROTO_UDP = 17, /* User Datagram Protocol. */ IPPROTO_IDP = 22, /* XNS IDP protocol. */ IPPROTO_TP = 29, /* SO Transport Protocol Class 4. */ IPPROTO_IPV6 = 41, /* IPv6 header. */ IPPROTO_ROUTING = 43, /* IPv6 routing header. */ IPPROTO_FRAGMENT = 44, /* IPv6 fragmentation header. */ IPPROTO_RSVP = 46, /* Reservation Protocol. */ IPPROTO_GRE = 47, /* General Routing Encapsulation. */ IPPROTO_ESP = 50, /* encapsulating security payload. */ IPPROTO_AH = 51, /* authentication header. */ IPPROTO_ICMPV6 = 58, /* ICMPv6. */ IPPROTO_NONE = 59, /* IPv6 no next header. */ IPPROTO_DSTOPTS = 60, /* IPv6 destination options. */ IPPROTO_MTP = 92, /* Multicast Transport Protocol. */ IPPROTO_ENCAP = 98, /* Encapsulation Header. */ IPPROTO_PIM = 103, /* Protocol Independent Multicast. */ IPPROTO_COMP = 108, /* Compression Header Protocol. */ IPPROTO_SCTP = 132, /* Stream Control Transmission Protocol. */ IPPROTO_RAW = 255, /* Raw IP packets. */ }; struct tcphdr { @0x0 uint16 source; @0x2 uint16 dest; @0x4 uint32 seq; @0x8 uint32 ack_seq; @@0x60 uint16 doff:4; @@0x6a uint16 urg:1; @@0x6b uint16 ack:1; @@0x6c uint16 psh:1; @@0x6d uint16 rst:1; @@0x6e uint16 syn:1; @@0x6f uint16 fin:1; @0xe uint16 window; @0x10 uint16 check; @0x12 uint16 urg_ptr; @0x14; }; struct udphdr { @0x0 uint16 source; @0x2 uint16 dest; @0x4 uint16 len; @0x6 uint16 check; @0x8; }; }; @define mkpcapdom(fname) { @local myas; myas = mksas(mapfile(fname)); return mkdom(pcap_names, myas); } @define pcap_domlen(pdom){ return rangelen(vecref(pdom.map(),0)); } // pdom: pcap domain from mkpcapdom() // fn(hdrptr, pktnum): called for each packet with ptr to header and pktnum @define pcap_iter(pdom, fn) { @local cur, cnt, sz; sz = pcap_domlen(pdom); cur = sizeof(pdom`pcap_hdr_t); cnt = 0; while (cur < sz) { @local pkthdr; pkthdr = (struct pdom`pcap_pkthdr *){pdom}cur; fn(pkthdr, cnt); cur = cur + sizeof(struct pdom`pcap_pkthdr) + pkthdr->caplen; cnt++; } } @define pcap_numpkts(pdom) { @local cnt; cnt = 0; pcap_iter(pdom, @lambda(hdr, i) { cnt++; }); return cnt; } @define pcap_info(pdom) { @local hdr; @local fsz; fsz = pcap_domlen(pdom); hdr = (pdom`pcap_hdr_t *){pdom}0; printf("magic: %e\n", (enum pdom`pcap_magic)hdr->magic_number); printf("version_major: 0x%x\n", hdr->version_major); printf("version_minor: 0x%x\n", hdr->version_minor); printf("zone: 0x%x\n", hdr->thiszone); printf("sigfigs: 0x%x\n", hdr->sigfigs); printf("snaplen: 0x%x\n", hdr->snaplen); printf("network: %e\n", (enum pdom`pcap_linktype)hdr->network); printf("File size: %d bytes\n", fsz); printf("Packets: %d\n", pcap_numpkts(pdom)); } @define ethaddr2str(addr) { return sprintfa("%.2x:%.2x:%.2x:%.2x:%.2x:%.2x", addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]); } @define ipv42str(a) { return sprintfa("%d.%d.%d.%d", a >> 24, (a & 0xff0000)>>16, (a & 0xff00)>>8, (a & 0xff)); } @define pcap_dump_tcp(tpkt) { printf("source: %u\n", tpkt->source); printf("dest: %u\n", tpkt->dest); printf("seq: %u\n", tpkt->seq); printf("ack: %u\n", tpkt->ack_seq); printf("doff: %u\n", tpkt->doff); printf("Flags: %s\n", sprintfa("%s%s%s%s%s%s", tpkt->urg ? "urg " : "", tpkt->ack ? "ack " : "", tpkt->psh ? "psh " : "", tpkt->rst ? "rst " : "", tpkt->syn ? "syn " : "", tpkt->fin ? "fin " : "")); printf("Window: %d\n", tpkt->window); } @define pcap_dump_udp(upkt) { printf("source: %u\n", upkt->source); printf("dest: %u\n", upkt->dest); printf("length: %u\n", upkt->len); } @define pcap_dump_ip(ipkt) { @local ipdom; printf("Version: %d\n", ipkt->ip_vers); printf("Header len: %d\n", ipkt->ip_hlen); printf("Length: %d\n", ipkt->ip_len); printf("ID: %d\n", ipkt->ip_id); printf("Frag: %s\n", ipkt->ip_dfflag ? "If necessary" : "No"); printf("More frag: %s\n", ipkt->ip_mfflag ? "yes" : "no"); printf("Frag offs: %d\n", ipkt->ip_fragoffs); printf("TTL: %d\n", ipkt->ip_ttl); printf("Proto: %e\n", (enum ip_protos)ipkt->ip_proto); printf("SRC: %s\n", ipv42str(ipkt->ip_src)); printf("DST: %s\n", ipv42str(ipkt->ip_dst)); ipdom = domof(ipkt); switch(ipkt->ip_proto) { case ipdom`IPPROTO_TCP: pcap_dump_tcp((struct ipdom`tcphdr *)((unsigned char *) ipkt + 4 * ipkt->ip_hlen)); break; case ipdom`IPPROTO_UDP: pcap_dump_udp((struct ipdom`udphdr *)((unsigned char *) ipkt + 4 * ipkt->ip_hlen)); break; } } @define pcap_dump(pdom) { pcap_iter(pdom, @lambda(hdr, n) { @local edom, ehdr; printf("\nPacket %d\n", n); edom = mkdom(eth_names, pdom.as); ehdr = (struct edom`ethhdr *){edom}((unsigned char *)hdr + sizeof(*hdr)); printf("dst: %s\n", ethaddr2str(ehdr->h_dest)); printf("src: %s\n", ethaddr2str(ehdr->h_source)); printf("proto: %e\n", (enum edom`proto_ids)ehdr->h_proto); switch(ehdr->h_proto) { case edom`ETH_P_IP: pcap_dump_ip((struct edom`iphdr *)((unsigned char *)ehdr + sizeof(struct edom`ethhdr))); break; } }); }