Home | History | Annotate | Line # | Download | only in libnpftest
npf_mbuf_subr.c revision 1.8
      1  1.1     rmind /*
      2  1.1     rmind  * NPF testing - helper routines.
      3  1.1     rmind  *
      4  1.1     rmind  * Public Domain.
      5  1.1     rmind  */
      6  1.1     rmind 
      7  1.6  christos #ifdef _KERNEL
      8  1.1     rmind #include <sys/types.h>
      9  1.1     rmind #include <sys/kmem.h>
     10  1.6  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.6  christos 
     16  1.6  christos #if defined(_NPF_STANDALONE)
     17  1.6  christos struct mbuf *
     18  1.6  christos npfkern_m_get(int flags, int space)
     19  1.6  christos {
     20  1.6  christos 	unsigned mlen = offsetof(struct mbuf, m_data0[space]);
     21  1.6  christos 	struct mbuf *m;
     22  1.6  christos 
     23  1.7     rmind 	m = calloc(1, mlen);
     24  1.6  christos 	if (m) {
     25  1.6  christos 		m->m_type = 1;
     26  1.6  christos 		m->m_flags = flags;
     27  1.6  christos 		m->m_data = m->m_data0;
     28  1.6  christos 	}
     29  1.6  christos 	return m;
     30  1.6  christos }
     31  1.6  christos #else
     32  1.6  christos struct mbuf *
     33  1.6  christos npfkern_m_get(int flags, int space)
     34  1.6  christos {
     35  1.6  christos 	return m_get(flags, space);
     36  1.6  christos }
     37  1.6  christos #endif
     38  1.6  christos 
     39  1.6  christos static void *
     40  1.6  christos npfkern_m_getdata(const struct mbuf *m)
     41  1.6  christos {
     42  1.6  christos 	return m->m_data;
     43  1.6  christos }
     44  1.6  christos 
     45  1.6  christos static struct mbuf *
     46  1.6  christos npfkern_m_next(struct mbuf *m)
     47  1.6  christos {
     48  1.6  christos 	return m->m_next;
     49  1.6  christos }
     50  1.6  christos 
     51  1.6  christos static size_t
     52  1.6  christos npfkern_m_buflen(const struct mbuf *m)
     53  1.6  christos {
     54  1.6  christos 	return m->m_len;
     55  1.6  christos }
     56  1.6  christos 
     57  1.6  christos size_t
     58  1.6  christos npfkern_m_length(const struct mbuf *m)
     59  1.6  christos {
     60  1.6  christos 	const struct mbuf *m0;
     61  1.6  christos 	unsigned pktlen = 0;
     62  1.6  christos 
     63  1.6  christos 	if ((m->m_flags & M_PKTHDR) != 0)
     64  1.6  christos 		return m->m_pkthdr.len;
     65  1.6  christos 	for (m0 = m; m0 != NULL; m0 = m0->m_next)
     66  1.6  christos 		pktlen += m0->m_len;
     67  1.6  christos 	return pktlen;
     68  1.6  christos }
     69  1.6  christos 
     70  1.6  christos void
     71  1.6  christos npfkern_m_freem(struct mbuf *m)
     72  1.6  christos {
     73  1.6  christos #ifdef _NPF_STANDALONE
     74  1.6  christos 	struct mbuf *n;
     75  1.6  christos 
     76  1.6  christos 	do {
     77  1.6  christos 		n = m->m_next;
     78  1.6  christos 		m->m_type = MT_FREE;
     79  1.6  christos 		free(m);
     80  1.6  christos 		m = n;
     81  1.6  christos 	} while (m);
     82  1.6  christos #else
     83  1.6  christos 	m_freem(m);
     84  1.6  christos #endif
     85  1.6  christos }
     86  1.6  christos 
     87  1.6  christos static bool
     88  1.6  christos npfkern_m_ensure_contig(struct mbuf **m0, size_t len)
     89  1.6  christos {
     90  1.6  christos 	struct mbuf *m1;
     91  1.6  christos 	unsigned tlen;
     92  1.6  christos 	char *dptr;
     93  1.6  christos 
     94  1.6  christos 	tlen = npfkern_m_length(*m0);
     95  1.6  christos 	if ((m1 = npfkern_m_get(M_PKTHDR, tlen)) == NULL) {
     96  1.6  christos 		return false;
     97  1.6  christos 	}
     98  1.6  christos 	m1->m_pkthdr.len = m1->m_len = tlen;
     99  1.6  christos 	dptr = m1->m_data;
    100  1.6  christos 	for (struct mbuf *m = *m0; m != NULL; m = m->m_next) {
    101  1.6  christos 		memcpy(dptr, m->m_data, m->m_len);
    102  1.6  christos 		dptr += m->m_len;
    103  1.6  christos 	}
    104  1.6  christos 	*m0 = m1;
    105  1.7     rmind 	(void)len;
    106  1.6  christos 	return true;
    107  1.6  christos }
    108  1.6  christos 
    109  1.6  christos 
    110  1.1     rmind struct mbuf *
    111  1.2     rmind mbuf_getwithdata(const void *data, size_t len)
    112  1.1     rmind {
    113  1.1     rmind 	struct mbuf *m;
    114  1.2     rmind 	void *dst;
    115  1.1     rmind 
    116  1.2     rmind 	m = m_gethdr(M_WAITOK, MT_HEADER);
    117  1.1     rmind 	assert(m != NULL);
    118  1.2     rmind 	dst = mtod(m, void *);
    119  1.2     rmind 	memcpy(dst, data, len);
    120  1.4     rmind 	m->m_pkthdr.len = len;
    121  1.1     rmind 	m->m_len = len;
    122  1.1     rmind 	return m;
    123  1.1     rmind }
    124  1.1     rmind 
    125  1.1     rmind struct mbuf *
    126  1.1     rmind mbuf_construct_ether(int proto)
    127  1.1     rmind {
    128  1.1     rmind 	struct mbuf *m0, *m1;
    129  1.1     rmind 	struct ether_header *ethdr;
    130  1.1     rmind 
    131  1.1     rmind 	m0 = m_gethdr(M_WAITOK, MT_HEADER);
    132  1.1     rmind 	ethdr = mtod(m0, struct ether_header *);
    133  1.1     rmind 	ethdr->ether_type = htons(ETHERTYPE_IP);
    134  1.4     rmind 	m0->m_pkthdr.len = sizeof(struct ether_header);
    135  1.1     rmind 	m0->m_len = sizeof(struct ether_header);
    136  1.1     rmind 
    137  1.1     rmind 	m1 = mbuf_construct(proto);
    138  1.1     rmind 	m0->m_next = m1;
    139  1.1     rmind 	m1->m_next = NULL;
    140  1.1     rmind 	return m0;
    141  1.1     rmind }
    142  1.1     rmind 
    143  1.3     rmind static int
    144  1.3     rmind mbuf_fill_proto(int proto, void *l4data)
    145  1.3     rmind {
    146  1.3     rmind 	struct tcphdr *th;
    147  1.3     rmind 	int size = 0;
    148  1.3     rmind 
    149  1.3     rmind 	switch (proto) {
    150  1.3     rmind 	case IPPROTO_TCP:
    151  1.3     rmind 		th = l4data;
    152  1.3     rmind 		th->th_off = sizeof(struct tcphdr) >> 2;
    153  1.3     rmind 		size = sizeof(struct tcphdr);
    154  1.3     rmind 		break;
    155  1.3     rmind 	case IPPROTO_UDP:
    156  1.3     rmind 		size = sizeof(struct udphdr);
    157  1.3     rmind 		break;
    158  1.3     rmind 	case IPPROTO_ICMP:
    159  1.3     rmind 		size = offsetof(struct icmp, icmp_data);
    160  1.3     rmind 		break;
    161  1.3     rmind 	}
    162  1.3     rmind 	return size;
    163  1.3     rmind }
    164  1.3     rmind 
    165  1.1     rmind struct mbuf *
    166  1.1     rmind mbuf_construct(int proto)
    167  1.1     rmind {
    168  1.1     rmind 	struct mbuf *m;
    169  1.1     rmind 	struct ip *iphdr;
    170  1.3     rmind 	void *l4data;
    171  1.1     rmind 	int size;
    172  1.1     rmind 
    173  1.1     rmind 	m = m_gethdr(M_WAITOK, MT_HEADER);
    174  1.1     rmind 	iphdr = mtod(m, struct ip *);
    175  1.1     rmind 
    176  1.1     rmind 	iphdr->ip_v = IPVERSION;
    177  1.1     rmind 	iphdr->ip_hl = sizeof(struct ip) >> 2;
    178  1.1     rmind 	iphdr->ip_off = 0;
    179  1.1     rmind 	iphdr->ip_ttl = 64;
    180  1.1     rmind 	iphdr->ip_p = proto;
    181  1.1     rmind 
    182  1.1     rmind 	size = sizeof(struct ip);
    183  1.3     rmind 	l4data = (void *)(iphdr + 1);
    184  1.3     rmind 	size += mbuf_fill_proto(proto, l4data);
    185  1.3     rmind 	iphdr->ip_len = htons(size);
    186  1.3     rmind 
    187  1.4     rmind 	m->m_pkthdr.len = size;
    188  1.3     rmind 	m->m_len = size;
    189  1.3     rmind 	m->m_next = NULL;
    190  1.3     rmind 	return m;
    191  1.3     rmind }
    192  1.3     rmind 
    193  1.3     rmind struct mbuf *
    194  1.3     rmind mbuf_construct6(int proto)
    195  1.3     rmind {
    196  1.3     rmind 	struct mbuf *m;
    197  1.3     rmind 	struct ip6_hdr *ip6;
    198  1.3     rmind 	void *l4data;
    199  1.3     rmind 	int size;
    200  1.1     rmind 
    201  1.3     rmind 	m = m_gethdr(M_WAITOK, MT_HEADER);
    202  1.3     rmind 	ip6 = mtod(m, struct ip6_hdr *);
    203  1.3     rmind 
    204  1.3     rmind 	ip6->ip6_vfc = IPV6_VERSION;
    205  1.3     rmind 	ip6->ip6_nxt = proto;
    206  1.3     rmind 	ip6->ip6_hlim = 64;
    207  1.3     rmind 
    208  1.3     rmind 	size = sizeof(struct ip6_hdr);
    209  1.3     rmind 	l4data = (void *)(ip6 + 1);
    210  1.3     rmind 	size += mbuf_fill_proto(proto, l4data);
    211  1.3     rmind 	ip6->ip6_plen = htons(size);
    212  1.1     rmind 
    213  1.4     rmind 	m->m_pkthdr.len = size;
    214  1.1     rmind 	m->m_len = size;
    215  1.1     rmind 	m->m_next = NULL;
    216  1.1     rmind 	return m;
    217  1.1     rmind }
    218  1.1     rmind 
    219  1.1     rmind void *
    220  1.1     rmind mbuf_return_hdrs(struct mbuf *m, bool ether, struct ip **ip)
    221  1.1     rmind {
    222  1.1     rmind 	struct ip *iphdr;
    223  1.1     rmind 
    224  1.1     rmind 	if (ether) {
    225  1.1     rmind 		struct mbuf *mn = m->m_next;
    226  1.1     rmind 		iphdr = mtod(mn, struct ip *);
    227  1.1     rmind 	} else {
    228  1.1     rmind 		iphdr = mtod(m, struct ip *);
    229  1.1     rmind 	}
    230  1.1     rmind 	*ip = iphdr;
    231  1.1     rmind 	return (void *)(iphdr + 1);
    232  1.1     rmind }
    233  1.1     rmind 
    234  1.5     rmind void *
    235  1.5     rmind mbuf_return_hdrs6(struct mbuf *m, struct ip6_hdr **ip6)
    236  1.5     rmind {
    237  1.5     rmind 	struct ip6_hdr *ip6hdr = mtod(m, struct ip6_hdr *);
    238  1.5     rmind 
    239  1.5     rmind 	*ip6 = ip6hdr;
    240  1.5     rmind 	return (void *)(ip6hdr + 1);
    241  1.5     rmind }
    242  1.5     rmind 
    243  1.1     rmind void
    244  1.1     rmind mbuf_icmp_append(struct mbuf *m, struct mbuf *m_orig)
    245  1.1     rmind {
    246  1.1     rmind 	struct ip *iphdr = mtod(m, struct ip *);
    247  1.1     rmind 	const size_t hlen = iphdr->ip_hl << 2;
    248  1.8     rmind 	void *p = (uint8_t *)iphdr + hlen;
    249  1.8     rmind 	struct icmp *ic = (struct icmp *)p;
    250  1.4     rmind 	const size_t addlen = m_length(m_orig);
    251  1.1     rmind 
    252  1.1     rmind 	iphdr->ip_len = htons(ntohs(iphdr->ip_len) + addlen);
    253  1.1     rmind 	memcpy(&ic->icmp_ip, mtod(m_orig, struct ip *), addlen);
    254  1.4     rmind 	m->m_pkthdr.len += addlen;
    255  1.1     rmind 	m->m_len += addlen;
    256  1.1     rmind 	m_freem(m_orig);
    257  1.1     rmind }
    258  1.6  christos 
    259  1.6  christos const npf_mbufops_t npftest_mbufops = {
    260  1.6  christos 	.alloc			= npfkern_m_get,
    261  1.6  christos 	.free			= npfkern_m_freem,
    262  1.6  christos 	.getdata		= npfkern_m_getdata,
    263  1.6  christos 	.getnext		= npfkern_m_next,
    264  1.6  christos 	.getlen			= npfkern_m_buflen,
    265  1.6  christos 	.getchainlen		= npfkern_m_length,
    266  1.6  christos 	.ensure_contig		= npfkern_m_ensure_contig,
    267  1.6  christos 	.ensure_writable	= NULL,
    268  1.6  christos };
    269