Home | History | Annotate | Line # | Download | only in libnpftest
npf_ext_test.c revision 1.1
      1 
      2 
      3 
      4 #ifdef _KERNEL
      5 #include <sys/types.h>
      6 #endif
      7 
      8 #include "npf_impl.h"
      9 #include "npf_test.h"
     10 
     11 static const struct test_case {
     12 	const char *	src;
     13 	in_port_t	sport;
     14 	const char *	dst;
     15 	in_port_t	dport;
     16 	const char *	ifname;
     17 	int		di;
     18 	int		af;
     19 } test_cases[] = {
     20 	{
     21 		LOCAL_IP60,	15000,		LOCAL_IP70,	7000,
     22 		IFNAME_EXT,	PFIL_OUT,
     23 		AF_INET
     24 	},
     25 	{
     26 		LOCAL_IP60,	15040,		LOCAL_IP70,	6000,
     27 		IFNAME_EXT,	PFIL_OUT,
     28 		AF_INET
     29 	},
     30 
     31 };
     32 
     33 #define TCP_OPT_LEN 4
     34 static struct mbuf *
     35 mbuf_get_pkt_with_option(int af, int proto, const char *src, const char *dst,
     36     int sport, int dport)
     37 {
     38 	struct mbuf *m;
     39 	struct ip *ip;
     40 	struct tcphdr *th;
     41 	void *ipsrc, *ipdst;
     42 	int size = 0;
     43 	uint8_t *opt;
     44 	uint16_t mss = 1400;
     45 
     46 	m = m_gethdr(M_WAITOK, MT_HEADER);
     47 	ip = mtod(m, struct ip *);
     48 
     49 	ip->ip_v = IPVERSION;
     50 	ip->ip_hl = sizeof(struct ip) >> 2;
     51 	ip->ip_off = 0;
     52 	ip->ip_ttl = 64;
     53 	ip->ip_p = proto;
     54 
     55 	ipsrc = &ip->ip_src.s_addr;
     56 	ipdst = &ip->ip_dst.s_addr;
     57 
     58 	npf_inet_pton(af, src, ipsrc);
     59 	npf_inet_pton(af, dst, ipdst);
     60 
     61 	th = mbuf_return_hdrs(m, false, &ip);
     62 	size = sizeof(struct ip) + sizeof(struct tcphdr) + TCP_OPT_LEN;
     63 	th->th_flags |= TH_SYN;
     64 	th->th_off = (sizeof(struct tcphdr) + TCP_OPT_LEN)  >> 2;
     65 	th->th_sport = htons(sport);
     66 	th->th_dport = htons(dport);
     67 
     68 	opt = (uint8_t *)th + sizeof(struct tcphdr);
     69 	opt[0] = TCPOPT_MAXSEG;         /* Kind = 2 */
     70 	opt[1] = TCPOLEN_MAXSEG;        /* Length = 4 */
     71 	opt[2] = (mss >> 8) & 0xff;    /* 0x05 */
     72 	opt[3] = mss & 0xff;           /* 0x29 */
     73 
     74 	ip->ip_len = htons(size);
     75 
     76 	m->m_pkthdr.len = size;
     77 	m->m_len = size;
     78 	m->m_next = NULL;
     79 	return m;
     80 }
     81 
     82 static int
     83 run_raw_testcase(npf_cache_t *npc, unsigned i, bool verbose)
     84 {
     85 	const struct test_case *t = &test_cases[i];
     86 	npf_t *npf = npf_getkernctx();
     87 	int slock, error;
     88 	npf_rproc_t *rp;
     89 	npf_rule_t *rl;
     90 	npf_match_info_t mi;
     91 	int decision = 1;
     92 
     93 	slock = npf_config_read_enter(npf);
     94 	rl = npf_ruleset_inspect(npc, npf_config_ruleset(npf), t->di, NPF_RULE_LAYER_3);
     95 	if (rl) {
     96 		error = npf_rule_conclude(rl, &mi);
     97 	} else {
     98 		error = ENOENT;
     99 		return error;
    100 	}
    101 	npf_config_read_exit(npf, slock);
    102 
    103 	rp = npf_rule_getrproc(rl);
    104 	assert(rp != NULL);
    105 
    106 	error = npf_rproc_run(npc, rp, &mi, &decision);
    107 
    108 	if (error == 1) {
    109 		npf_rproc_release(rp);
    110 	}
    111 
    112 	return error;
    113 }
    114 
    115 static void
    116 npf_get_normalize_params(npf_cache_t *npc, uint16_t *ip_ttl, uint8_t *ip_id, int *df, uint16_t *maxmss)
    117 {
    118     int wscale;
    119     struct ip *ip = npc->npc_ip.v4;
    120     *ip_id = ip->ip_id;
    121     *ip_ttl = ip->ip_ttl;
    122     *df = ip->ip_off & IP_DF;
    123     npf_fetch_tcpopts(npc, maxmss, &wscale);
    124 }
    125 
    126 bool
    127 npf_procedure_test(bool verbose)
    128 {
    129 	int ret;
    130 	for (unsigned i = 0; i < __arraycount(test_cases); i++) {
    131 		const struct test_case *t = &test_cases[i];
    132 		npf_cache_t *npc;
    133 		struct mbuf *m;
    134 		uint16_t ip_ttl;
    135     	uint8_t ip_id;
    136     	int df;
    137     	uint16_t maxmss;
    138 
    139 		if (npf_test_getif(t->ifname) == NULL) {
    140 			printf("Interface %s is not configured.\n", t->ifname);
    141 			return false;
    142 		}
    143 
    144 		m = mbuf_get_pkt_with_option(t->af, IPPROTO_TCP, t->src, t->dst, 9000, 9000);
    145 		npc = get_cached_pkt(m, t->ifname,  NPF_RULE_LAYER_3);
    146 
    147 		ret = run_raw_testcase(npc, i, verbose);
    148 		if (verbose) {
    149 			printf("%s: expected return in raw testcase 1, returned %d\n", __func__, ret);
    150 		}
    151 		CHECK_TRUE(ret == 1);
    152 
    153 		npf_get_normalize_params(npc, &ip_ttl, &ip_id, &df, &maxmss);
    154 		maxmss = ntohs(maxmss);
    155 
    156 		if (verbose) {
    157 			printf("Normalization:\texpected 164 ttl but got %u\n", ip_ttl);
    158 			printf("Normalization:\texpected 1321 maxmss but got %u\n", maxmss);
    159 		}
    160 		CHECK_TRUE((df & IP_DF) == 0);
    161     	CHECK_TRUE(maxmss == 1321);
    162 		CHECK_TRUE(ip_ttl == 164);
    163 		put_cached_pkt(npc);
    164 	}
    165 
    166 	return true;
    167 }
    168