1 1.1 rmind /* 2 1.8 rmind * 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.1 rmind const tcp_meta_t *p = &packet_sequence[i]; 137 1.9 rmind npf_cache_t *npc; 138 1.1 rmind int ret; 139 1.1 rmind 140 1.1 rmind if (p->flags == 0) { 141 1.1 rmind npf_state_destroy(nst); 142 1.1 rmind *snew = true; 143 1.1 rmind return true; 144 1.1 rmind } 145 1.1 rmind 146 1.11 joe npc = get_cached_pkt(construct_packet(p), NULL, NPF_RULE_LAYER_3); 147 1.1 rmind if (*snew) { 148 1.9 rmind ret = npf_state_init(npc, nst); 149 1.1 rmind KASSERT(ret == true); 150 1.1 rmind *snew = false; 151 1.1 rmind } 152 1.10 rmind ret = npf_state_inspect(npc, nst, 153 1.10 rmind (p->flags == OUT) ? NPF_FLOW_FORW : NPF_FLOW_BACK); 154 1.9 rmind put_cached_pkt(npc); 155 1.1 rmind 156 1.1 rmind return ret ? true : (p->flags & ERR) != 0; 157 1.1 rmind } 158 1.1 rmind 159 1.1 rmind bool 160 1.1 rmind npf_state_test(bool verbose) 161 1.1 rmind { 162 1.1 rmind npf_state_t nst; 163 1.1 rmind bool snew = true; 164 1.3 rmind bool ok = true; 165 1.1 rmind 166 1.9 rmind for (unsigned i = 0; i < __arraycount(packet_sequence); i++) { 167 1.1 rmind if (process_packet(i, &nst, &snew)) { 168 1.1 rmind continue; 169 1.1 rmind } 170 1.1 rmind if (verbose) { 171 1.1 rmind printf("Failed on packet %d, state dump:\n", i); 172 1.1 rmind npf_state_dump(&nst); 173 1.1 rmind } 174 1.3 rmind ok = false; 175 1.1 rmind } 176 1.3 rmind return ok; 177 1.1 rmind } 178