npf_mbuf_subr.c revision 1.4 1 1.3 rmind /* $NetBSD: npf_mbuf_subr.c,v 1.4 2012/12/24 19:05:47 rmind Exp $ */
2 1.1 rmind
3 1.1 rmind /*
4 1.1 rmind * NPF testing - helper routines.
5 1.1 rmind *
6 1.1 rmind * Public Domain.
7 1.1 rmind */
8 1.1 rmind
9 1.1 rmind #include <sys/types.h>
10 1.1 rmind #include <sys/kmem.h>
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 struct mbuf *
16 1.2 rmind mbuf_getwithdata(const void *data, size_t len)
17 1.1 rmind {
18 1.1 rmind struct mbuf *m;
19 1.2 rmind void *dst;
20 1.1 rmind
21 1.2 rmind m = m_gethdr(M_WAITOK, MT_HEADER);
22 1.1 rmind assert(m != NULL);
23 1.2 rmind dst = mtod(m, void *);
24 1.2 rmind memcpy(dst, data, len);
25 1.4 rmind m->m_pkthdr.len = len;
26 1.1 rmind m->m_len = len;
27 1.1 rmind return m;
28 1.1 rmind }
29 1.1 rmind
30 1.1 rmind struct mbuf *
31 1.1 rmind mbuf_construct_ether(int proto)
32 1.1 rmind {
33 1.1 rmind struct mbuf *m0, *m1;
34 1.1 rmind struct ether_header *ethdr;
35 1.1 rmind
36 1.1 rmind m0 = m_gethdr(M_WAITOK, MT_HEADER);
37 1.1 rmind ethdr = mtod(m0, struct ether_header *);
38 1.1 rmind ethdr->ether_type = htons(ETHERTYPE_IP);
39 1.4 rmind m0->m_pkthdr.len = sizeof(struct ether_header);
40 1.1 rmind m0->m_len = sizeof(struct ether_header);
41 1.1 rmind
42 1.1 rmind m1 = mbuf_construct(proto);
43 1.1 rmind m0->m_next = m1;
44 1.1 rmind m1->m_next = NULL;
45 1.1 rmind return m0;
46 1.1 rmind }
47 1.1 rmind
48 1.3 rmind static int
49 1.3 rmind mbuf_fill_proto(int proto, void *l4data)
50 1.3 rmind {
51 1.3 rmind struct tcphdr *th;
52 1.3 rmind int size = 0;
53 1.3 rmind
54 1.3 rmind switch (proto) {
55 1.3 rmind case IPPROTO_TCP:
56 1.3 rmind th = l4data;
57 1.3 rmind th->th_off = sizeof(struct tcphdr) >> 2;
58 1.3 rmind size = sizeof(struct tcphdr);
59 1.3 rmind break;
60 1.3 rmind case IPPROTO_UDP:
61 1.3 rmind size = sizeof(struct udphdr);
62 1.3 rmind break;
63 1.3 rmind case IPPROTO_ICMP:
64 1.3 rmind size = offsetof(struct icmp, icmp_data);
65 1.3 rmind break;
66 1.3 rmind }
67 1.3 rmind return size;
68 1.3 rmind }
69 1.3 rmind
70 1.1 rmind struct mbuf *
71 1.1 rmind mbuf_construct(int proto)
72 1.1 rmind {
73 1.1 rmind struct mbuf *m;
74 1.1 rmind struct ip *iphdr;
75 1.3 rmind void *l4data;
76 1.1 rmind int size;
77 1.1 rmind
78 1.1 rmind m = m_gethdr(M_WAITOK, MT_HEADER);
79 1.1 rmind iphdr = mtod(m, struct ip *);
80 1.1 rmind
81 1.1 rmind iphdr->ip_v = IPVERSION;
82 1.1 rmind iphdr->ip_hl = sizeof(struct ip) >> 2;
83 1.1 rmind iphdr->ip_off = 0;
84 1.1 rmind iphdr->ip_ttl = 64;
85 1.1 rmind iphdr->ip_p = proto;
86 1.1 rmind
87 1.1 rmind size = sizeof(struct ip);
88 1.3 rmind l4data = (void *)(iphdr + 1);
89 1.3 rmind size += mbuf_fill_proto(proto, l4data);
90 1.3 rmind iphdr->ip_len = htons(size);
91 1.3 rmind
92 1.4 rmind m->m_pkthdr.len = size;
93 1.3 rmind m->m_len = size;
94 1.3 rmind m->m_next = NULL;
95 1.3 rmind return m;
96 1.3 rmind }
97 1.3 rmind
98 1.3 rmind struct mbuf *
99 1.3 rmind mbuf_construct6(int proto)
100 1.3 rmind {
101 1.3 rmind struct mbuf *m;
102 1.3 rmind struct ip6_hdr *ip6;
103 1.3 rmind void *l4data;
104 1.3 rmind int size;
105 1.1 rmind
106 1.3 rmind m = m_gethdr(M_WAITOK, MT_HEADER);
107 1.3 rmind ip6 = mtod(m, struct ip6_hdr *);
108 1.3 rmind
109 1.3 rmind ip6->ip6_vfc = IPV6_VERSION;
110 1.3 rmind ip6->ip6_nxt = proto;
111 1.3 rmind ip6->ip6_hlim = 64;
112 1.3 rmind
113 1.3 rmind size = sizeof(struct ip6_hdr);
114 1.3 rmind l4data = (void *)(ip6 + 1);
115 1.3 rmind size += mbuf_fill_proto(proto, l4data);
116 1.3 rmind ip6->ip6_plen = htons(size);
117 1.1 rmind
118 1.4 rmind m->m_pkthdr.len = size;
119 1.1 rmind m->m_len = size;
120 1.1 rmind m->m_next = NULL;
121 1.1 rmind return m;
122 1.1 rmind }
123 1.1 rmind
124 1.1 rmind void *
125 1.1 rmind mbuf_return_hdrs(struct mbuf *m, bool ether, struct ip **ip)
126 1.1 rmind {
127 1.1 rmind struct ip *iphdr;
128 1.1 rmind
129 1.1 rmind if (ether) {
130 1.1 rmind struct mbuf *mn = m->m_next;
131 1.1 rmind iphdr = mtod(mn, struct ip *);
132 1.1 rmind } else {
133 1.1 rmind iphdr = mtod(m, struct ip *);
134 1.1 rmind }
135 1.1 rmind *ip = iphdr;
136 1.1 rmind return (void *)(iphdr + 1);
137 1.1 rmind }
138 1.1 rmind
139 1.1 rmind void
140 1.1 rmind mbuf_icmp_append(struct mbuf *m, struct mbuf *m_orig)
141 1.1 rmind {
142 1.1 rmind struct ip *iphdr = mtod(m, struct ip *);
143 1.1 rmind const size_t hlen = iphdr->ip_hl << 2;
144 1.1 rmind struct icmp *ic = (struct icmp *)((uint8_t *)iphdr + hlen);
145 1.4 rmind const size_t addlen = m_length(m_orig);
146 1.1 rmind
147 1.1 rmind iphdr->ip_len = htons(ntohs(iphdr->ip_len) + addlen);
148 1.1 rmind memcpy(&ic->icmp_ip, mtod(m_orig, struct ip *), addlen);
149 1.4 rmind m->m_pkthdr.len += addlen;
150 1.1 rmind m->m_len += addlen;
151 1.1 rmind m_freem(m_orig);
152 1.1 rmind }
153