1 /* $NetBSD: npf_test_subr.c,v 1.11 2014/08/10 16:44:37 tls Exp $ */ 2 3 /* 4 * NPF initialisation and handler routines. 5 * 6 * Public Domain. 7 */ 8 9 #include <sys/types.h> 10 #include <sys/cprng.h> 11 #include <net/if.h> 12 #include <net/if_types.h> 13 14 #include "npf_impl.h" 15 #include "npf_test.h" 16 17 /* State of the current stream. */ 18 static npf_state_t cstream_state; 19 static void * cstream_ptr; 20 static bool cstream_retval; 21 22 static long (*_random_func)(void); 23 static int (*_pton_func)(int, const char *, void *); 24 static const char * (*_ntop_func)(int, const void *, char *, socklen_t); 25 26 static void npf_state_sample(npf_state_t *, bool); 27 28 void 29 npf_test_init(int (*pton_func)(int, const char *, void *), 30 const char *(*ntop_func)(int, const void *, char *, socklen_t), 31 long (*rndfunc)(void)) 32 { 33 npf_state_setsampler(npf_state_sample); 34 _pton_func = pton_func; 35 _ntop_func = ntop_func; 36 _random_func = rndfunc; 37 } 38 39 int 40 npf_test_load(const void *xml) 41 { 42 prop_dictionary_t npf_dict = prop_dictionary_internalize(xml); 43 return npfctl_load(0, npf_dict); 44 } 45 46 ifnet_t * 47 npf_test_addif(const char *ifname, bool reg, bool verbose) 48 { 49 ifnet_t *ifp = if_alloc(IFT_OTHER); 50 51 /* 52 * This is a "fake" interface with explicitly set index. 53 * Note: test modules may not setup pfil(9) hooks and if_attach() 54 * may not trigger npf_ifmap_attach(), so we call it manually. 55 */ 56 strlcpy(ifp->if_xname, ifname, sizeof(ifp->if_xname)); 57 ifp->if_dlt = DLT_NULL; 58 ifp->if_index = 0; 59 if_attach(ifp); 60 if_alloc_sadl(ifp); 61 62 npf_ifmap_attach(ifp); 63 if (reg) { 64 npf_ifmap_register(ifname); 65 } 66 67 if (verbose) { 68 printf("+ Interface %s\n", ifname); 69 } 70 return ifp; 71 } 72 73 ifnet_t * 74 npf_test_getif(const char *ifname) 75 { 76 return ifunit(ifname); 77 } 78 79 /* 80 * State sampler - this routine is called from inside of NPF state engine. 81 */ 82 static void 83 npf_state_sample(npf_state_t *nst, bool retval) 84 { 85 /* Pointer will serve as an ID. */ 86 cstream_ptr = nst; 87 memcpy(&cstream_state, nst, sizeof(npf_state_t)); 88 cstream_retval = retval; 89 } 90 91 int 92 npf_test_statetrack(const void *data, size_t len, ifnet_t *ifp, 93 bool forw, int64_t *result) 94 { 95 struct mbuf *m; 96 int i = 0, error; 97 98 m = mbuf_getwithdata(data, len); 99 error = npf_packet_handler(NULL, &m, ifp, forw ? PFIL_OUT : PFIL_IN); 100 if (error) { 101 assert(m == NULL); 102 return error; 103 } 104 assert(m != NULL); 105 m_freem(m); 106 107 const int di = forw ? NPF_FLOW_FORW : NPF_FLOW_BACK; 108 npf_tcpstate_t *fstate = &cstream_state.nst_tcpst[di]; 109 npf_tcpstate_t *tstate = &cstream_state.nst_tcpst[!di]; 110 111 result[i++] = (intptr_t)cstream_ptr; 112 result[i++] = cstream_retval; 113 result[i++] = cstream_state.nst_state; 114 115 result[i++] = fstate->nst_end; 116 result[i++] = fstate->nst_maxend; 117 result[i++] = fstate->nst_maxwin; 118 result[i++] = fstate->nst_wscale; 119 120 result[i++] = tstate->nst_end; 121 result[i++] = tstate->nst_maxend; 122 result[i++] = tstate->nst_maxwin; 123 result[i++] = tstate->nst_wscale; 124 125 return 0; 126 } 127 128 int 129 npf_inet_pton(int af, const char *src, void *dst) 130 { 131 return _pton_func(af, src, dst); 132 } 133 134 const char * 135 npf_inet_ntop(int af, const void *src, char *dst, socklen_t size) 136 { 137 return _ntop_func(af, src, dst, size); 138 } 139 140 /* 141 * Need to override cprng_fast32() -- we need deterministic PRNG. 142 */ 143 uint32_t 144 cprng_fast32(void) 145 { 146 return (uint32_t)(_random_func ? _random_func() : random()); 147 } 148