1 1.9 rmind /* $NetBSD: npfstream.c,v 1.9 2019/07/23 00:52:02 rmind Exp $ */ 2 1.1 rmind 3 1.1 rmind /* 4 1.1 rmind * NPF stream processor. 5 1.1 rmind * 6 1.1 rmind * Public Domain. 7 1.1 rmind */ 8 1.1 rmind 9 1.1 rmind #include <stdio.h> 10 1.1 rmind #include <stdlib.h> 11 1.1 rmind #include <stdbool.h> 12 1.1 rmind #include <string.h> 13 1.1 rmind #include <inttypes.h> 14 1.1 rmind #include <err.h> 15 1.1 rmind #include <pcap.h> 16 1.1 rmind 17 1.1 rmind #include <arpa/inet.h> 18 1.1 rmind 19 1.7 christos #if !defined(_NPF_STANDALONE) 20 1.1 rmind #include <net/if.h> 21 1.1 rmind #include <net/ethertypes.h> 22 1.1 rmind #include <net/if_ether.h> 23 1.1 rmind #include <netinet/in_systm.h> 24 1.1 rmind #include <netinet/ip.h> 25 1.1 rmind #include <netinet/ip.h> 26 1.1 rmind #include <netinet/tcp.h> 27 1.1 rmind 28 1.1 rmind #include <rump/rump.h> 29 1.7 christos #endif 30 1.1 rmind 31 1.1 rmind #include "npftest.h" 32 1.1 rmind 33 1.1 rmind static struct in_addr initial_ip; 34 1.1 rmind static int snd_packet_no = 0; 35 1.1 rmind static int rcv_packet_no = 0; 36 1.1 rmind 37 1.1 rmind static void 38 1.6 rmind process_tcpip(const void *data, size_t len, FILE *fp, ifnet_t *ifp) 39 1.1 rmind { 40 1.1 rmind const struct ether_header *eth = data; 41 1.1 rmind const struct ip *ip; 42 1.1 rmind const struct tcphdr *th; 43 1.1 rmind unsigned hlen, tcpdlen; 44 1.1 rmind int error, packetno; 45 1.8 rmind const void *p; 46 1.1 rmind tcp_seq seq; 47 1.1 rmind bool forw; 48 1.1 rmind 49 1.1 rmind if (ntohs(eth->ether_type) != ETHERTYPE_IP) { 50 1.8 rmind p = (const char *)data + 4; 51 1.3 rmind } else { 52 1.8 rmind p = eth + 1; 53 1.1 rmind } 54 1.8 rmind ip = (const struct ip *)p; 55 1.1 rmind hlen = ip->ip_hl << 2; 56 1.8 rmind p = (const uint8_t *)ip + hlen; 57 1.8 rmind th = (const struct tcphdr *)p; 58 1.1 rmind 59 1.1 rmind tcpdlen = ntohs(ip->ip_len) - hlen - (th->th_off << 2); 60 1.1 rmind if (th->th_flags & TH_SYN) { 61 1.1 rmind tcpdlen++; 62 1.1 rmind } 63 1.1 rmind if (th->th_flags & TH_FIN) { 64 1.1 rmind tcpdlen++; 65 1.1 rmind } 66 1.1 rmind seq = ntohl(th->th_seq); 67 1.1 rmind 68 1.1 rmind if (snd_packet_no == 0) { 69 1.1 rmind memcpy(&initial_ip, &ip->ip_src, sizeof(struct in_addr)); 70 1.1 rmind } 71 1.1 rmind 72 1.1 rmind forw = (initial_ip.s_addr == ip->ip_src.s_addr); 73 1.1 rmind packetno = forw ? ++snd_packet_no : ++rcv_packet_no; 74 1.1 rmind 75 1.2 rmind int64_t result[11]; 76 1.1 rmind memset(result, 0, sizeof(result)); 77 1.1 rmind 78 1.1 rmind len = ntohs(ip->ip_len); 79 1.6 rmind error = rumpns_npf_test_statetrack(ip, len, ifp, forw, result); 80 1.1 rmind 81 1.4 martin fprintf(fp, "%s%2x %5d %3d %11u %11u %11u %11u %12" PRIxPTR, 82 1.1 rmind forw ? ">" : "<", (th->th_flags & (TH_SYN | TH_ACK | TH_FIN)), 83 1.9 rmind packetno, error, (unsigned)seq, (unsigned)ntohl(th->th_ack), 84 1.2 rmind tcpdlen, ntohs(th->th_win), (uintptr_t)result[0]); 85 1.1 rmind 86 1.1 rmind for (unsigned i = 1; i < __arraycount(result); i++) { 87 1.1 rmind fprintf(fp, "%11" PRIu64 " ", result[i]); 88 1.1 rmind } 89 1.1 rmind fputs("\n", fp); 90 1.1 rmind } 91 1.1 rmind 92 1.1 rmind int 93 1.6 rmind process_stream(const char *input, const char *output, ifnet_t *ifp) 94 1.1 rmind { 95 1.1 rmind pcap_t *pcap; 96 1.1 rmind char pcap_errbuf[PCAP_ERRBUF_SIZE]; 97 1.1 rmind struct pcap_pkthdr *phdr; 98 1.1 rmind const uint8_t *data; 99 1.1 rmind FILE *fp; 100 1.1 rmind 101 1.1 rmind pcap = pcap_open_offline(input, pcap_errbuf); 102 1.1 rmind if (pcap == NULL) { 103 1.1 rmind errx(EXIT_FAILURE, "pcap_open_offline failed: %s", pcap_errbuf); 104 1.1 rmind } 105 1.1 rmind fp = output ? fopen(output, "w") : stdout; 106 1.1 rmind if (fp == NULL) { 107 1.1 rmind err(EXIT_FAILURE, "fopen"); 108 1.1 rmind } 109 1.2 rmind fprintf(fp, "#FL %5s %3s %11s %11s %11s %11s %11s %11s %11s " 110 1.2 rmind "%11s %11s %11s %5s %11s %11s %11s %5s\n", 111 1.1 rmind "No", "Err", "Seq", "Ack", "TCP Len", "Win", 112 1.2 rmind "Stream", "RetVal", "State", 113 1.2 rmind "F.END", "F.MAXEND", "F.MAXWIN", "F.WSC", 114 1.2 rmind "T.END", "T.MAXEND", "T.MAXWIN", "T.WSC"); 115 1.1 rmind while (pcap_next_ex(pcap, &phdr, &data) > 0) { 116 1.1 rmind if (phdr->len != phdr->caplen) { 117 1.1 rmind warnx("process_stream: truncated packet"); 118 1.1 rmind } 119 1.6 rmind process_tcpip(data, phdr->caplen, fp, ifp); 120 1.1 rmind } 121 1.1 rmind pcap_close(pcap); 122 1.1 rmind fclose(fp); 123 1.1 rmind 124 1.1 rmind return 0; 125 1.1 rmind } 126