Home | History | Annotate | Line # | Download | only in libnpftest
npf_state_test.c revision 1.7.14.1
      1       1.1     rmind /*
      2  1.7.14.1  christos  * NPF state tracking tests.
      3       1.1     rmind  *
      4       1.1     rmind  * Public Domain.
      5       1.1     rmind  */
      6       1.1     rmind 
      7       1.7  christos #ifdef _KERNEL
      8       1.1     rmind #include <sys/types.h>
      9       1.1     rmind #include <sys/kmem.h>
     10       1.7  christos #endif
     11       1.1     rmind 
     12       1.1     rmind #include "npf_impl.h"
     13       1.1     rmind #include "npf_test.h"
     14       1.1     rmind 
     15       1.1     rmind typedef struct {
     16       1.1     rmind 	int		tcpfl;		/* TCP flags. */
     17       1.1     rmind 	int		tlen;		/* TCP data length. */
     18       1.1     rmind 	uint32_t	seq;		/* SEQ number. */
     19       1.1     rmind 	uint32_t	ack;		/* ACK number. */
     20       1.1     rmind 	uint32_t	win;		/* TCP Window. */
     21       1.1     rmind 	int		flags;		/* Direction et al. */
     22       1.1     rmind } tcp_meta_t;
     23       1.1     rmind 
     24       1.1     rmind #define	S	TH_SYN
     25       1.1     rmind #define	A	TH_ACK
     26       1.1     rmind #define	F	TH_FIN
     27       1.1     rmind #define	OUT	0x1
     28       1.1     rmind #define	IN	0x2
     29       1.1     rmind #define	ERR	0x4
     30       1.1     rmind #define	CLEAR	.flags = 0
     31       1.1     rmind 
     32       1.1     rmind static const tcp_meta_t packet_sequence[] = {
     33       1.1     rmind 	/*
     34       1.1     rmind 	 *	TCP data	SEQ	ACK		WIN
     35       1.1     rmind 	 */
     36       1.1     rmind 
     37       1.1     rmind 	/* Out of order ACK. */
     38       1.1     rmind 	{ S,	0,		9999,	0,		4096,	OUT	},
     39       1.1     rmind 	{ S|A,	0,		9,	10000,		2048,	IN	},
     40       1.1     rmind 	{ A,	0,		10000,	10,		4096,	OUT	},
     41       1.1     rmind 	/* --- */
     42       1.1     rmind 	{ A,	0,		10,	10000,		2048,	IN	},
     43       1.1     rmind 	{ A,	1000,		10000,	10,		4096,	OUT	},
     44       1.1     rmind 	{ A,	1000,		11000,	10,		4096,	OUT	},
     45       1.1     rmind 	{ A,	0,		10,	12000,		2048,	IN	},
     46       1.1     rmind 	{ A,	0,		10,	13000,		2048,	IN	},
     47       1.1     rmind 	{ A,	1000,		12000,	10,		4096,	OUT	},
     48       1.1     rmind 	{ A,	0,		10,	11000,		1048,	IN	},
     49       1.1     rmind 	/* --- */
     50       1.1     rmind 	{ A,	1000,		14000,	10,		4096,	OUT	},
     51       1.1     rmind 	{ A,	0,		10,	13000,		2048,	IN	},
     52       1.1     rmind 	{ CLEAR },
     53       1.1     rmind 
     54       1.1     rmind 	/* Retransmission after out of order ACK and missing ACK. */
     55       1.1     rmind 	{ S,	0,		9999,	0,		1000,	OUT	},
     56       1.1     rmind 	{ S|A,	0,		9,	10000,		4000,	IN	},
     57       1.1     rmind 	{ A,	0,		10000,	10,		1000,	OUT	},
     58       1.1     rmind 	/* --- */
     59       1.1     rmind 	{ A,	1000,		10000,	10,		1000,	OUT	},
     60       1.1     rmind 	{ A,	0,		10,	11000,		4000,	IN	},
     61       1.1     rmind 	{ A,	1000,		11000,	10,		1000,	OUT	},
     62       1.1     rmind 	{ A,	1000,		12000,	10,		1000,	OUT	},
     63       1.1     rmind 	{ A,	1000,		13000,	10,		1000,	OUT	},
     64       1.1     rmind 	{ A,	1000,		14000,	10,		1000,	OUT	},
     65       1.1     rmind 	/* --- Assume the first was delayed; second was lost after us. */
     66       1.1     rmind 	{ A,	0,		10,	15000,		4000,	IN	},
     67       1.1     rmind 	{ A,	0,		10,	15000,		2000,	IN	},
     68       1.1     rmind 	/* --- */
     69       1.1     rmind 	{ A,	1000,		12000,	10,		1000,	OUT	},
     70       1.1     rmind 	{ CLEAR },
     71       1.1     rmind 
     72       1.2     rmind 	/* FIN exchange with retransmit. */
     73       1.2     rmind 	{ S,	0,		999,	0,		1000,	OUT	},
     74       1.2     rmind 	{ S|A,	0,		9,	1000,		2000,	IN	},
     75       1.2     rmind 	{ A,	0,		1000,	10,		1000,	OUT	},
     76       1.2     rmind 	/* --- */
     77       1.2     rmind 	{ F,	0,		10,	1000,		2000,	IN	},
     78       1.2     rmind 	{ F,	0,		1000,	10,		1000,	OUT	},
     79       1.2     rmind 	{ A,	0,		1000,	11,		1000,	OUT	},
     80       1.2     rmind 	/* --- */
     81       1.2     rmind 	{ F,	0,		1000,	11,		1000,	OUT	},
     82       1.2     rmind 	{ F,	0,		1000,	11,		1000,	OUT	},
     83       1.2     rmind 	{ A,	0,		11,	1001,		2000,	OUT	},
     84       1.2     rmind 	{ CLEAR },
     85       1.2     rmind 
     86       1.1     rmind 	/* Out of window. */
     87       1.1     rmind 	{ S,	0,		9,	0,		8760,	OUT	},
     88       1.1     rmind 	{ S|A,	0,		9999,	10,		1000,	IN	},
     89       1.1     rmind 	{ A,	0,		10,	10000,		8760,	OUT	},
     90       1.1     rmind 	/* --- */
     91       1.1     rmind 	{ A,	1460,		10000,	10,		1000,	IN	},
     92       1.1     rmind 	{ A,	1460,		11460,	10,		1000,	IN	},
     93       1.1     rmind 	{ A,	0,		10,	12920,		8760,	OUT	},
     94       1.1     rmind 	{ A,	1460,		12920,	10,		1000,	IN	},
     95       1.1     rmind 	{ A,	0,		10,	14380,		8760,	OUT	},
     96       1.1     rmind 	{ A,	1460,		17300,	10,		1000,	IN	},
     97       1.1     rmind 	{ A,	0,		10,	14380,		8760,	OUT	},
     98       1.1     rmind 	{ A,	1460,		18760,	10,		1000,	IN	},
     99       1.1     rmind 	{ A,	0,		10,	14380,		8760,	OUT	},
    100       1.1     rmind 	{ A,	1460,		20220,	10,		1000,	IN	},
    101       1.1     rmind 	{ A,	0,		10,	14380,		8760,	OUT	},
    102       1.1     rmind 	{ A,	1460,		21680,	10,		1000,	IN	},
    103       1.1     rmind 	{ A,	0,		10,	14380,		8760,	OUT	},
    104       1.1     rmind 	/* --- */
    105       1.1     rmind 	{ A,	1460,		14380,	10,		1000,	IN	},
    106       1.1     rmind 	{ A,	1460,		23140,	10,		1000,	IN|ERR	},
    107       1.1     rmind 	{ CLEAR },
    108       1.1     rmind 
    109       1.1     rmind };
    110       1.1     rmind 
    111       1.1     rmind #undef S
    112       1.1     rmind #undef A
    113       1.1     rmind #undef F
    114       1.1     rmind 
    115       1.1     rmind static struct mbuf *
    116       1.1     rmind construct_packet(const tcp_meta_t *p)
    117       1.1     rmind {
    118       1.1     rmind 	struct mbuf *m = mbuf_construct(IPPROTO_TCP);
    119       1.1     rmind 	struct ip *ip;
    120       1.1     rmind 	struct tcphdr *th;
    121       1.1     rmind 
    122       1.1     rmind 	th = mbuf_return_hdrs(m, false, &ip);
    123       1.1     rmind 
    124       1.1     rmind 	/* Imitate TCP payload, set TCP sequence numbers, flags and window. */
    125       1.1     rmind 	ip->ip_len = htons(sizeof(struct ip) + sizeof(struct tcphdr) + p->tlen);
    126       1.1     rmind 	th->th_seq = htonl(p->seq);
    127       1.1     rmind 	th->th_ack = htonl(p->ack);
    128       1.1     rmind 	th->th_flags = p->tcpfl;
    129       1.1     rmind 	th->th_win = htons(p->win);
    130       1.1     rmind 	return m;
    131       1.1     rmind }
    132       1.1     rmind 
    133       1.1     rmind static bool
    134       1.1     rmind process_packet(const int i, npf_state_t *nst, bool *snew)
    135       1.1     rmind {
    136       1.5     rmind 	ifnet_t *dummy_ifp = npf_test_addif(IFNAME_TEST, false, false);
    137       1.1     rmind 	const tcp_meta_t *p = &packet_sequence[i];
    138       1.7  christos 	npf_cache_t npc = { .npc_info = 0, .npc_ctx = npf_getkernctx() };
    139       1.4     rmind 	nbuf_t nbuf;
    140       1.1     rmind 	int ret;
    141       1.1     rmind 
    142       1.1     rmind 	if (p->flags == 0) {
    143       1.1     rmind 		npf_state_destroy(nst);
    144       1.1     rmind 		*snew = true;
    145       1.1     rmind 		return true;
    146       1.1     rmind 	}
    147       1.1     rmind 
    148       1.7  christos 	nbuf_init(npf_getkernctx(), &nbuf, construct_packet(p), dummy_ifp);
    149       1.6     rmind 	npc.npc_nbuf = &nbuf;
    150       1.6     rmind 	ret = npf_cache_all(&npc);
    151       1.1     rmind 	KASSERT((ret & NPC_IPFRAG) == 0);
    152       1.1     rmind 
    153       1.1     rmind 	if (*snew) {
    154       1.6     rmind 		ret = npf_state_init(&npc, nst);
    155       1.1     rmind 		KASSERT(ret == true);
    156       1.1     rmind 		*snew = false;
    157       1.1     rmind 	}
    158       1.6     rmind 	ret = npf_state_inspect(&npc, nst, p->flags == OUT);
    159       1.4     rmind 	m_freem(nbuf.nb_mbuf);
    160       1.1     rmind 
    161       1.1     rmind 	return ret ? true : (p->flags & ERR) != 0;
    162       1.1     rmind }
    163       1.1     rmind 
    164       1.1     rmind bool
    165       1.1     rmind npf_state_test(bool verbose)
    166       1.1     rmind {
    167       1.1     rmind 	npf_state_t nst;
    168       1.1     rmind 	bool snew = true;
    169       1.3     rmind 	bool ok = true;
    170       1.1     rmind 
    171       1.1     rmind 	for (u_int i = 0; i < __arraycount(packet_sequence); i++) {
    172       1.1     rmind 		if (process_packet(i, &nst, &snew)) {
    173       1.1     rmind 			continue;
    174       1.1     rmind 		}
    175       1.1     rmind 		if (verbose) {
    176       1.1     rmind 			printf("Failed on packet %d, state dump:\n", i);
    177       1.1     rmind 			npf_state_dump(&nst);
    178       1.1     rmind 		}
    179       1.3     rmind 		ok = false;
    180       1.1     rmind 	}
    181       1.3     rmind 	return ok;
    182       1.1     rmind }
    183