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