/* $NetBSD: npfstream.c,v 1.5 2013/09/24 02:04:21 rmind Exp $ */ /* * NPF stream processor. * * Public Domain. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "npftest.h" static struct in_addr initial_ip; static int snd_packet_no = 0; static int rcv_packet_no = 0; static void process_tcpip(const void *data, size_t len, FILE *fp, unsigned idx) { const struct ether_header *eth = data; const struct ip *ip; const struct tcphdr *th; unsigned hlen, tcpdlen; int error, packetno; tcp_seq seq; bool forw; if (ntohs(eth->ether_type) != ETHERTYPE_IP) { ip = (const struct ip *)((const char *)data + 4); } else { ip = (const struct ip *)(eth + 1); } hlen = ip->ip_hl << 2; th = (const struct tcphdr *)((const uint8_t *)ip + hlen); tcpdlen = ntohs(ip->ip_len) - hlen - (th->th_off << 2); if (th->th_flags & TH_SYN) { tcpdlen++; } if (th->th_flags & TH_FIN) { tcpdlen++; } seq = ntohl(th->th_seq); if (snd_packet_no == 0) { memcpy(&initial_ip, &ip->ip_src, sizeof(struct in_addr)); } forw = (initial_ip.s_addr == ip->ip_src.s_addr); packetno = forw ? ++snd_packet_no : ++rcv_packet_no; int64_t result[11]; memset(result, 0, sizeof(result)); len = ntohs(ip->ip_len); error = rumpns_npf_test_statetrack(ip, len, idx, forw, result); fprintf(fp, "%s%2x %5d %3d %11u %11u %11u %11u %12" PRIxPTR, forw ? ">" : "<", (th->th_flags & (TH_SYN | TH_ACK | TH_FIN)), packetno, error, (u_int)seq, (u_int)ntohl(th->th_ack), tcpdlen, ntohs(th->th_win), (uintptr_t)result[0]); for (unsigned i = 1; i < __arraycount(result); i++) { fprintf(fp, "%11" PRIu64 " ", result[i]); } fputs("\n", fp); } int process_stream(const char *input, const char *output, unsigned idx) { pcap_t *pcap; char pcap_errbuf[PCAP_ERRBUF_SIZE]; struct pcap_pkthdr *phdr; const uint8_t *data; FILE *fp; pcap = pcap_open_offline(input, pcap_errbuf); if (pcap == NULL) { errx(EXIT_FAILURE, "pcap_open_offline failed: %s", pcap_errbuf); } fp = output ? fopen(output, "w") : stdout; if (fp == NULL) { err(EXIT_FAILURE, "fopen"); } fprintf(fp, "#FL %5s %3s %11s %11s %11s %11s %11s %11s %11s " "%11s %11s %11s %5s %11s %11s %11s %5s\n", "No", "Err", "Seq", "Ack", "TCP Len", "Win", "Stream", "RetVal", "State", "F.END", "F.MAXEND", "F.MAXWIN", "F.WSC", "T.END", "T.MAXEND", "T.MAXWIN", "T.WSC"); while (pcap_next_ex(pcap, &phdr, &data) > 0) { if (phdr->len != phdr->caplen) { warnx("process_stream: truncated packet"); } process_tcpip(data, phdr->caplen, fp, idx); } pcap_close(pcap); fclose(fp); return 0; }