Home | History | Annotate | Line # | Download | only in npftest
npfstream.c revision 1.1
      1  1.1  rmind /*	$NetBSD: npfstream.c,v 1.1 2012/05/30 21:38:04 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.1  rmind #include <net/if.h>
     20  1.1  rmind #include <net/ethertypes.h>
     21  1.1  rmind #include <net/if_ether.h>
     22  1.1  rmind #include <netinet/in_systm.h>
     23  1.1  rmind #include <netinet/ip.h>
     24  1.1  rmind #include <netinet/ip.h>
     25  1.1  rmind #include <netinet/tcp.h>
     26  1.1  rmind 
     27  1.1  rmind #include <rump/rump.h>
     28  1.1  rmind 
     29  1.1  rmind #include "npftest.h"
     30  1.1  rmind 
     31  1.1  rmind static struct in_addr	initial_ip;
     32  1.1  rmind static int		snd_packet_no = 0;
     33  1.1  rmind static int		rcv_packet_no = 0;
     34  1.1  rmind 
     35  1.1  rmind static void
     36  1.1  rmind process_tcpip(const void *data, size_t len, FILE *fp, unsigned idx)
     37  1.1  rmind {
     38  1.1  rmind 	const struct ether_header *eth = data;
     39  1.1  rmind 	const struct ip *ip;
     40  1.1  rmind 	const struct tcphdr *th;
     41  1.1  rmind 	unsigned hlen, tcpdlen;
     42  1.1  rmind 	int error, packetno;
     43  1.1  rmind 	tcp_seq seq;
     44  1.1  rmind 	bool forw;
     45  1.1  rmind 
     46  1.1  rmind 	if (ntohs(eth->ether_type) != ETHERTYPE_IP) {
     47  1.1  rmind 		errx(EXIT_FAILURE, "process_tcpip: not IP protocol (%d)",
     48  1.1  rmind 		    eth->ether_type);
     49  1.1  rmind 	}
     50  1.1  rmind 	ip = (const struct ip *)(eth + 1);
     51  1.1  rmind 	hlen = ip->ip_hl << 2;
     52  1.1  rmind 	th = (const struct tcphdr *)((const uint8_t *)ip + hlen);
     53  1.1  rmind 
     54  1.1  rmind 	tcpdlen = ntohs(ip->ip_len) - hlen - (th->th_off << 2);
     55  1.1  rmind 	if (th->th_flags & TH_SYN) {
     56  1.1  rmind 		tcpdlen++;
     57  1.1  rmind 	}
     58  1.1  rmind 	if (th->th_flags & TH_FIN) {
     59  1.1  rmind 		tcpdlen++;
     60  1.1  rmind 	}
     61  1.1  rmind 	seq = ntohl(th->th_seq);
     62  1.1  rmind 
     63  1.1  rmind 	if (snd_packet_no == 0) {
     64  1.1  rmind 		memcpy(&initial_ip, &ip->ip_src, sizeof(struct in_addr));
     65  1.1  rmind 	}
     66  1.1  rmind 
     67  1.1  rmind 	forw = (initial_ip.s_addr == ip->ip_src.s_addr);
     68  1.1  rmind 	packetno = forw ? ++snd_packet_no : ++rcv_packet_no;
     69  1.1  rmind 
     70  1.1  rmind 	int64_t result[9];
     71  1.1  rmind 	memset(result, 0, sizeof(result));
     72  1.1  rmind 
     73  1.1  rmind 	len = ntohs(ip->ip_len);
     74  1.1  rmind 	error = rumpns_npf_test_handlepkt(ip, len, idx, forw, result);
     75  1.1  rmind 
     76  1.1  rmind 	fprintf(fp, "%s%2x %5d %3d %11u %11u %11u %11u %12lx",
     77  1.1  rmind 	    forw ? ">" : "<", (th->th_flags & (TH_SYN | TH_ACK | TH_FIN)),
     78  1.1  rmind 	    packetno, error, (u_int)seq, (u_int)ntohl(th->th_ack),
     79  1.1  rmind 	    (u_int)(seq + tcpdlen), ntohs(th->th_win), (uintptr_t)result[0]);
     80  1.1  rmind 
     81  1.1  rmind 	for (unsigned i = 1; i < __arraycount(result); i++) {
     82  1.1  rmind 		fprintf(fp, "%11" PRIu64 " ", result[i]);
     83  1.1  rmind 	}
     84  1.1  rmind 	fputs("\n", fp);
     85  1.1  rmind }
     86  1.1  rmind 
     87  1.1  rmind int
     88  1.1  rmind process_stream(const char *input, const char *output, unsigned idx)
     89  1.1  rmind {
     90  1.1  rmind 	pcap_t *pcap;
     91  1.1  rmind 	char pcap_errbuf[PCAP_ERRBUF_SIZE];
     92  1.1  rmind 	struct pcap_pkthdr *phdr;
     93  1.1  rmind 	const uint8_t *data;
     94  1.1  rmind 	FILE *fp;
     95  1.1  rmind 
     96  1.1  rmind 	pcap = pcap_open_offline(input, pcap_errbuf);
     97  1.1  rmind 	if (pcap == NULL) {
     98  1.1  rmind 		errx(EXIT_FAILURE, "pcap_open_offline failed: %s", pcap_errbuf);
     99  1.1  rmind 	}
    100  1.1  rmind 	fp = output ? fopen(output, "w") : stdout;
    101  1.1  rmind 	if (fp == NULL) {
    102  1.1  rmind 		err(EXIT_FAILURE, "fopen");
    103  1.1  rmind 	}
    104  1.1  rmind 	fprintf(fp, "#   %5s %3s %11s %11s %11s %11s %11s %11s %11s\n",
    105  1.1  rmind 	    "No", "Err", "Seq", "Ack", "TCP Len", "Win",
    106  1.1  rmind 	    "Stream", "RetVal", "State");
    107  1.1  rmind 	while (pcap_next_ex(pcap, &phdr, &data) > 0) {
    108  1.1  rmind 		if (phdr->len != phdr->caplen) {
    109  1.1  rmind 			warnx("process_stream: truncated packet");
    110  1.1  rmind 		}
    111  1.1  rmind 		process_tcpip(data, phdr->caplen, fp, idx);
    112  1.1  rmind 	}
    113  1.1  rmind 	pcap_close(pcap);
    114  1.1  rmind 	fclose(fp);
    115  1.1  rmind 
    116  1.1  rmind 	return 0;
    117  1.1  rmind }
    118