Deleted Added
full compact
frag6.c (54350) frag6.c (62587)
1/* $FreeBSD: head/sys/netinet6/frag6.c 62587 2000-07-04 16:35:15Z itojun $ */
2/* $KAME: frag6.c,v 1.24 2000/03/25 07:23:41 sumikawa Exp $ */
3
1/*
2 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 11 unchanged lines hidden (view full) ---

20 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
4/*
5 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright

--- 11 unchanged lines hidden (view full) ---

23 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
28 *
29 * $FreeBSD: head/sys/netinet6/frag6.c 54350 1999-12-09 08:56:50Z shin $
30 */
31
32#include <sys/param.h>
33#include <sys/systm.h>
34#include <sys/malloc.h>
35#include <sys/mbuf.h>
36#include <sys/domain.h>
37#include <sys/protosw.h>
38#include <sys/socket.h>
39#include <sys/errno.h>
40#include <sys/time.h>
41#include <sys/kernel.h>
42#include <sys/syslog.h>
43
44#include <net/if.h>
45#include <net/route.h>
46
47#include <netinet/in.h>
48#include <netinet/in_var.h>
31 */
32
33#include <sys/param.h>
34#include <sys/systm.h>
35#include <sys/malloc.h>
36#include <sys/mbuf.h>
37#include <sys/domain.h>
38#include <sys/protosw.h>
39#include <sys/socket.h>
40#include <sys/errno.h>
41#include <sys/time.h>
42#include <sys/kernel.h>
43#include <sys/syslog.h>
44
45#include <net/if.h>
46#include <net/route.h>
47
48#include <netinet/in.h>
49#include <netinet/in_var.h>
49#include <netinet6/ip6.h>
50#include
50#include <netinet6/ip6_var.h>
51#include <netinet6/ip6_var.h>
51#include <netinet6/icmp6.h>
52#include
52
53#include <net/net_osdep.h>
54
55/*
56 * Define it to get a correct behavior on per-interface statistics.
57 * You will need to perform an extra routing table lookup, per fragment,
58 * to do it. This may, or may not be, a performance hit.
59 */
53
54#include <net/net_osdep.h>
55
56/*
57 * Define it to get a correct behavior on per-interface statistics.
58 * You will need to perform an extra routing table lookup, per fragment,
59 * to do it. This may, or may not be, a performance hit.
60 */
60#define IN6_IFSTAT_STRICT
61#define IN6_IFSTAT_STRICT
61
62
62static void frag6_enq __P((struct ip6asfrag *, struct ip6asfrag *));
63static void frag6_deq __P((struct ip6asfrag *));
64static void frag6_insque __P((struct ip6q *, struct ip6q *));
65static void frag6_remque __P((struct ip6q *));
66static void frag6_freef __P((struct ip6q *));
63static void frag6_enq __P((struct ip6asfrag *, struct ip6asfrag *));
64static void frag6_deq __P((struct ip6asfrag *));
65static void frag6_insque __P((struct ip6q *, struct ip6q *));
66static void frag6_remque __P((struct ip6q *));
67static void frag6_freef __P((struct ip6q *));
67
68
68int frag6_doing_reass;
69u_int frag6_nfragpackets;
70struct ip6q ip6q; /* ip6 reassemble queue */
69int frag6_doing_reass;
70u_int frag6_nfragpackets;
71struct ip6q ip6q; /* ip6 reassemble queue */
71
72
72#if !defined(M_FTABLE)
73/* FreeBSD tweak */
73MALLOC_DEFINE(M_FTABLE, "fragment", "fragment reassembly header");
74MALLOC_DEFINE(M_FTABLE, "fragment", "fragment reassembly header");
75
76#ifndef offsetof /* XXX */
77#define offsetof(type, member) ((size_t)(&((type *)0)->member))
74#endif
75
76/*
77 * Initialise reassembly queue and fragment identifier.
78 */
79void
80frag6_init()
81{
82 struct timeval tv;
83
84 /*
85 * in many cases, random() here does NOT return random number
86 * as initialization during bootstrap time occur in fixed order.
87 */
88 microtime(&tv);
78#endif
79
80/*
81 * Initialise reassembly queue and fragment identifier.
82 */
83void
84frag6_init()
85{
86 struct timeval tv;
87
88 /*
89 * in many cases, random() here does NOT return random number
90 * as initialization during bootstrap time occur in fixed order.
91 */
92 microtime(&tv);
89 ip6q.ip6q_next = ip6q.ip6q_prev = &ip6q;
90 ip6_id = random() ^ tv.tv_usec;
93 ip6_id = random() ^ tv.tv_usec;
94 ip6q.ip6q_next = ip6q.ip6q_prev = &ip6q;
91}
92
93/*
95}
96
97/*
98 * In RFC2460, fragment and reassembly rule do not agree with each other,
99 * in terms of next header field handling in fragment header.
100 * While the sender will use the same value for all of the fragmented packets,
101 * receiver is suggested not to check the consistency.
102 *
103 * fragment rule (p20):
104 * (2) A Fragment header containing:
105 * The Next Header value that identifies the first header of
106 * the Fragmentable Part of the original packet.
107 * -> next header field is same for all fragments
108 *
109 * reassembly rule (p21):
110 * The Next Header field of the last header of the Unfragmentable
111 * Part is obtained from the Next Header field of the first
112 * fragment's Fragment header.
113 * -> should grab it from the first fragment only
114 *
115 * The following note also contradicts with fragment rule - noone is going to
116 * send different fragment with different next header field.
117 *
118 * additional note (p22):
119 * The Next Header values in the Fragment headers of different
120 * fragments of the same original packet may differ. Only the value
121 * from the Offset zero fragment packet is used for reassembly.
122 * -> should grab it from the first fragment only
123 *
124 * There is no explicit reason given in the RFC. Historical reason maybe?
125 */
126/*
94 * Fragment input
95 */
96int
97frag6_input(mp, offp, proto)
98 struct mbuf **mp;
99 int *offp, proto;
100{
101 struct mbuf *m = *mp, *t;
102 struct ip6_hdr *ip6;
103 struct ip6_frag *ip6f;
104 struct ip6q *q6;
127 * Fragment input
128 */
129int
130frag6_input(mp, offp, proto)
131 struct mbuf **mp;
132 int *offp, proto;
133{
134 struct mbuf *m = *mp, *t;
135 struct ip6_hdr *ip6;
136 struct ip6_frag *ip6f;
137 struct ip6q *q6;
105 struct ip6asfrag *af6, *ip6af;
138 struct ip6asfrag *af6, *ip6af, *af6dwn;
106 int offset = *offp, nxt, i, next;
107 int first_frag = 0;
139 int offset = *offp, nxt, i, next;
140 int first_frag = 0;
108 u_short fragoff, frgpartlen;
141 int fragoff, frgpartlen; /* must be larger than u_int16_t */
109 struct ifnet *dstifp;
110#ifdef IN6_IFSTAT_STRICT
111 static struct route_in6 ro;
112 struct sockaddr_in6 *dst;
113#endif
114
142 struct ifnet *dstifp;
143#ifdef IN6_IFSTAT_STRICT
144 static struct route_in6 ro;
145 struct sockaddr_in6 *dst;
146#endif
147
115 IP6_EXTHDR_CHECK(m, offset, sizeof(struct ip6_frag), IPPROTO_DONE);
116
117 ip6 = mtod(m, struct ip6_hdr *);
148 ip6 = mtod(m, struct ip6_hdr *);
149#ifndef PULLDOWN_TEST
150 IP6_EXTHDR_CHECK(m, offset, sizeof(struct ip6_frag), IPPROTO_DONE);
118 ip6f = (struct ip6_frag *)((caddr_t)ip6 + offset);
151 ip6f = (struct ip6_frag *)((caddr_t)ip6 + offset);
152#else
153 IP6_EXTHDR_GET(ip6f, struct ip6_frag *, m, offset, sizeof(*ip6f));
154 if (ip6f == NULL)
155 return IPPROTO_DONE;
156#endif
119
120 dstifp = NULL;
121#ifdef IN6_IFSTAT_STRICT
122 /* find the destination interface of the packet. */
123 dst = (struct sockaddr_in6 *)&ro.ro_dst;
124 if (ro.ro_rt
125 && ((ro.ro_rt->rt_flags & RTF_UP) == 0
126 || !IN6_ARE_ADDR_EQUAL(&dst->sin6_addr, &ip6->ip6_dst))) {

--- 27 unchanged lines hidden (view full) ---

154 * multiple of 8 octets.
155 * sizeof(struct ip6_frag) == 8
156 * sizeof(struct ip6_hdr) = 40
157 */
158 if ((ip6f->ip6f_offlg & IP6F_MORE_FRAG) &&
159 (((ntohs(ip6->ip6_plen) - offset) & 0x7) != 0)) {
160 icmp6_error(m, ICMP6_PARAM_PROB,
161 ICMP6_PARAMPROB_HEADER,
157
158 dstifp = NULL;
159#ifdef IN6_IFSTAT_STRICT
160 /* find the destination interface of the packet. */
161 dst = (struct sockaddr_in6 *)&ro.ro_dst;
162 if (ro.ro_rt
163 && ((ro.ro_rt->rt_flags & RTF_UP) == 0
164 || !IN6_ARE_ADDR_EQUAL(&dst->sin6_addr, &ip6->ip6_dst))) {

--- 27 unchanged lines hidden (view full) ---

192 * multiple of 8 octets.
193 * sizeof(struct ip6_frag) == 8
194 * sizeof(struct ip6_hdr) = 40
195 */
196 if ((ip6f->ip6f_offlg & IP6F_MORE_FRAG) &&
197 (((ntohs(ip6->ip6_plen) - offset) & 0x7) != 0)) {
198 icmp6_error(m, ICMP6_PARAM_PROB,
199 ICMP6_PARAMPROB_HEADER,
162 (caddr_t)&ip6->ip6_plen - (caddr_t)ip6);
200 offsetof(struct ip6_hdr, ip6_plen));
163 in6_ifstat_inc(dstifp, ifs6_reass_fail);
164 return IPPROTO_DONE;
165 }
166
167 ip6stat.ip6s_fragments++;
168 in6_ifstat_inc(dstifp, ifs6_reass_reqd);
169
201 in6_ifstat_inc(dstifp, ifs6_reass_fail);
202 return IPPROTO_DONE;
203 }
204
205 ip6stat.ip6s_fragments++;
206 in6_ifstat_inc(dstifp, ifs6_reass_reqd);
207
170 /*
171 * Presence of header sizes in mbufs
172 * would confuse code below.
173 */
174
208 /* offset now points to data portion */
175 offset += sizeof(struct ip6_frag);
209 offset += sizeof(struct ip6_frag);
176 m->m_data += offset;
177 m->m_len -= offset;
178
179 for (q6 = ip6q.ip6q_next; q6 != &ip6q; q6 = q6->ip6q_next)
180 if (ip6f->ip6f_ident == q6->ip6q_ident &&
181 IN6_ARE_ADDR_EQUAL(&ip6->ip6_src, &q6->ip6q_src) &&
182 IN6_ARE_ADDR_EQUAL(&ip6->ip6_dst, &q6->ip6q_dst))
183 break;
184
185 if (q6 == &ip6q) {

--- 13 unchanged lines hidden (view full) ---

199 ip6stat.ip6s_fragoverflow++;
200 in6_ifstat_inc(dstifp, ifs6_reass_fail);
201 frag6_freef(ip6q.ip6q_prev);
202 }
203 q6 = (struct ip6q *)malloc(sizeof(struct ip6q), M_FTABLE,
204 M_DONTWAIT);
205 if (q6 == NULL)
206 goto dropfrag;
210
211 for (q6 = ip6q.ip6q_next; q6 != &ip6q; q6 = q6->ip6q_next)
212 if (ip6f->ip6f_ident == q6->ip6q_ident &&
213 IN6_ARE_ADDR_EQUAL(&ip6->ip6_src, &q6->ip6q_src) &&
214 IN6_ARE_ADDR_EQUAL(&ip6->ip6_dst, &q6->ip6q_dst))
215 break;
216
217 if (q6 == &ip6q) {

--- 13 unchanged lines hidden (view full) ---

231 ip6stat.ip6s_fragoverflow++;
232 in6_ifstat_inc(dstifp, ifs6_reass_fail);
233 frag6_freef(ip6q.ip6q_prev);
234 }
235 q6 = (struct ip6q *)malloc(sizeof(struct ip6q), M_FTABLE,
236 M_DONTWAIT);
237 if (q6 == NULL)
238 goto dropfrag;
239 bzero(q6, sizeof(*q6));
207
208 frag6_insque(q6, &ip6q);
209
240
241 frag6_insque(q6, &ip6q);
242
243 /* ip6q_nxt will be filled afterwards, from 1st fragment */
210 q6->ip6q_down = q6->ip6q_up = (struct ip6asfrag *)q6;
244 q6->ip6q_down = q6->ip6q_up = (struct ip6asfrag *)q6;
245#ifdef notyet
246 q6->ip6q_nxtp = (u_char *)nxtp;
247#endif
211 q6->ip6q_ident = ip6f->ip6f_ident;
212 q6->ip6q_arrive = 0; /* Is it used anywhere? */
213 q6->ip6q_ttl = IPV6_FRAGTTL;
214 q6->ip6q_src = ip6->ip6_src;
215 q6->ip6q_dst = ip6->ip6_dst;
216 q6->ip6q_unfrglen = -1; /* The 1st fragment has not arrived. */
217 }
218

--- 8 unchanged lines hidden (view full) ---

227 q6->ip6q_nxt = ip6f->ip6f_nxt;
228 }
229
230 /*
231 * Check that the reassembled packet would not exceed 65535 bytes
232 * in size.
233 * If it would exceed, discard the fragment and return an ICMP error.
234 */
248 q6->ip6q_ident = ip6f->ip6f_ident;
249 q6->ip6q_arrive = 0; /* Is it used anywhere? */
250 q6->ip6q_ttl = IPV6_FRAGTTL;
251 q6->ip6q_src = ip6->ip6_src;
252 q6->ip6q_dst = ip6->ip6_dst;
253 q6->ip6q_unfrglen = -1; /* The 1st fragment has not arrived. */
254 }
255

--- 8 unchanged lines hidden (view full) ---

264 q6->ip6q_nxt = ip6f->ip6f_nxt;
265 }
266
267 /*
268 * Check that the reassembled packet would not exceed 65535 bytes
269 * in size.
270 * If it would exceed, discard the fragment and return an ICMP error.
271 */
235 frgpartlen = sizeof(struct ip6_hdr) + ntohs(ip6->ip6_plen) - offset;
272 frgpartlen = sizeof(struct ip6_hdr) + ntohs(ip6->ip6_plen) - offset;
236 if (q6->ip6q_unfrglen >= 0) {
237 /* The 1st fragment has already arrived. */
238 if (q6->ip6q_unfrglen + fragoff + frgpartlen > IPV6_MAXPACKET) {
273 if (q6->ip6q_unfrglen >= 0) {
274 /* The 1st fragment has already arrived. */
275 if (q6->ip6q_unfrglen + fragoff + frgpartlen > IPV6_MAXPACKET) {
239 m->m_data -= offset;
240 m->m_len += offset;
241 icmp6_error(m, ICMP6_PARAM_PROB, ICMP6_PARAMPROB_HEADER,
276 icmp6_error(m, ICMP6_PARAM_PROB, ICMP6_PARAMPROB_HEADER,
242 offset - sizeof(struct ip6_frag) + 2);
277 offset - sizeof(struct ip6_frag) +
278 offsetof(struct ip6_frag, ip6f_offlg));
243 return(IPPROTO_DONE);
244 }
245 }
246 else if (fragoff + frgpartlen > IPV6_MAXPACKET) {
279 return(IPPROTO_DONE);
280 }
281 }
282 else if (fragoff + frgpartlen > IPV6_MAXPACKET) {
247 m->m_data -= offset;
248 m->m_len += offset;
249 icmp6_error(m, ICMP6_PARAM_PROB, ICMP6_PARAMPROB_HEADER,
283 icmp6_error(m, ICMP6_PARAM_PROB, ICMP6_PARAMPROB_HEADER,
250 offset - sizeof(struct ip6_frag) + 2);
284 offset - sizeof(struct ip6_frag) +
285 offsetof(struct ip6_frag, ip6f_offlg));
251 return(IPPROTO_DONE);
252 }
253 /*
254 * If it's the first fragment, do the above check for each
255 * fragment already stored in the reassembly queue.
256 */
257 if (fragoff == 0) {
286 return(IPPROTO_DONE);
287 }
288 /*
289 * If it's the first fragment, do the above check for each
290 * fragment already stored in the reassembly queue.
291 */
292 if (fragoff == 0) {
258 struct ip6asfrag *af6dwn;
259
260 for (af6 = q6->ip6q_down; af6 != (struct ip6asfrag *)q6;
261 af6 = af6dwn) {
262 af6dwn = af6->ip6af_down;
263
264 if (q6->ip6q_unfrglen + af6->ip6af_off + af6->ip6af_frglen >
265 IPV6_MAXPACKET) {
266 struct mbuf *merr = IP6_REASS_MBUF(af6);
267 struct ip6_hdr *ip6err;
268 int erroff = af6->ip6af_offset;
269
270 /* dequeue the fragment. */
271 frag6_deq(af6);
293 for (af6 = q6->ip6q_down; af6 != (struct ip6asfrag *)q6;
294 af6 = af6dwn) {
295 af6dwn = af6->ip6af_down;
296
297 if (q6->ip6q_unfrglen + af6->ip6af_off + af6->ip6af_frglen >
298 IPV6_MAXPACKET) {
299 struct mbuf *merr = IP6_REASS_MBUF(af6);
300 struct ip6_hdr *ip6err;
301 int erroff = af6->ip6af_offset;
302
303 /* dequeue the fragment. */
304 frag6_deq(af6);
305 free(af6, M_FTABLE);
272
273 /* adjust pointer. */
306
307 /* adjust pointer. */
274 merr->m_data -= af6->ip6af_offset;
275 merr->m_len += af6->ip6af_offset;
276 ip6err = mtod(merr, struct ip6_hdr *);
277
278 /*
279 * Restore source and destination addresses
280 * in the erroneous IPv6 header.
281 */
282 ip6err->ip6_src = q6->ip6q_src;
283 ip6err->ip6_dst = q6->ip6q_dst;
284
285 icmp6_error(merr, ICMP6_PARAM_PROB,
286 ICMP6_PARAMPROB_HEADER,
308 ip6err = mtod(merr, struct ip6_hdr *);
309
310 /*
311 * Restore source and destination addresses
312 * in the erroneous IPv6 header.
313 */
314 ip6err->ip6_src = q6->ip6q_src;
315 ip6err->ip6_dst = q6->ip6q_dst;
316
317 icmp6_error(merr, ICMP6_PARAM_PROB,
318 ICMP6_PARAMPROB_HEADER,
287 erroff - sizeof(struct ip6_frag) + 2);
319 erroff - sizeof(struct ip6_frag) +
320 offsetof(struct ip6_frag, ip6f_offlg));
288 }
289 }
290 }
291
321 }
322 }
323 }
324
292 /* Override the IPv6 header */
293 ip6af = (struct ip6asfrag *)ip6;
325 ip6af = (struct ip6asfrag *)malloc(sizeof(struct ip6asfrag), M_FTABLE,
326 M_DONTWAIT);
327 if (ip6af == NULL)
328 goto dropfrag;
329 bzero(ip6af, sizeof(*ip6af));
330 ip6af->ip6af_head = ip6->ip6_flow;
331 ip6af->ip6af_len = ip6->ip6_plen;
332 ip6af->ip6af_nxt = ip6->ip6_nxt;
333 ip6af->ip6af_hlim = ip6->ip6_hlim;
294 ip6af->ip6af_mff = ip6f->ip6f_offlg & IP6F_MORE_FRAG;
295 ip6af->ip6af_off = fragoff;
296 ip6af->ip6af_frglen = frgpartlen;
297 ip6af->ip6af_offset = offset;
298 IP6_REASS_MBUF(ip6af) = m;
299
300 if (first_frag) {
301 af6 = (struct ip6asfrag *)q6;
302 goto insert;
303 }
304
305 /*
306 * Find a segment which begins after this one does.
307 */
308 for (af6 = q6->ip6q_down; af6 != (struct ip6asfrag *)q6;
309 af6 = af6->ip6af_down)
310 if (af6->ip6af_off > ip6af->ip6af_off)
311 break;
312
334 ip6af->ip6af_mff = ip6f->ip6f_offlg & IP6F_MORE_FRAG;
335 ip6af->ip6af_off = fragoff;
336 ip6af->ip6af_frglen = frgpartlen;
337 ip6af->ip6af_offset = offset;
338 IP6_REASS_MBUF(ip6af) = m;
339
340 if (first_frag) {
341 af6 = (struct ip6asfrag *)q6;
342 goto insert;
343 }
344
345 /*
346 * Find a segment which begins after this one does.
347 */
348 for (af6 = q6->ip6q_down; af6 != (struct ip6asfrag *)q6;
349 af6 = af6->ip6af_down)
350 if (af6->ip6af_off > ip6af->ip6af_off)
351 break;
352
353#if 0
313 /*
354 /*
355 * If there is a preceding segment, it may provide some of
356 * our data already. If so, drop the data from the incoming
357 * segment. If it provides all of our data, drop us.
358 */
359 if (af6->ip6af_up != (struct ip6asfrag *)q6) {
360 i = af6->ip6af_up->ip6af_off + af6->ip6af_up->ip6af_frglen
361 - ip6af->ip6af_off;
362 if (i > 0) {
363 if (i >= ip6af->ip6af_frglen)
364 goto dropfrag;
365 m_adj(IP6_REASS_MBUF(ip6af), i);
366 ip6af->ip6af_off += i;
367 ip6af->ip6af_frglen -= i;
368 }
369 }
370
371 /*
372 * While we overlap succeeding segments trim them or,
373 * if they are completely covered, dequeue them.
374 */
375 while (af6 != (struct ip6asfrag *)q6 &&
376 ip6af->ip6af_off + ip6af->ip6af_frglen > af6->ip6af_off) {
377 i = (ip6af->ip6af_off + ip6af->ip6af_frglen) - af6->ip6af_off;
378 if (i < af6->ip6af_frglen) {
379 af6->ip6af_frglen -= i;
380 af6->ip6af_off += i;
381 m_adj(IP6_REASS_MBUF(af6), i);
382 break;
383 }
384 af6 = af6->ip6af_down;
385 m_freem(IP6_REASS_MBUF(af6->ip6af_up));
386 frag6_deq(af6->ip6af_up);
387 }
388#else
389 /*
314 * If the incoming framgent overlaps some existing fragments in
315 * the reassembly queue, drop it, since it is dangerous to override
316 * existing fragments from a security point of view.
317 */
318 if (af6->ip6af_up != (struct ip6asfrag *)q6) {
319 i = af6->ip6af_up->ip6af_off + af6->ip6af_up->ip6af_frglen
320 - ip6af->ip6af_off;
321 if (i > 0) {

--- 7 unchanged lines hidden (view full) ---

329 i = (ip6af->ip6af_off + ip6af->ip6af_frglen) - af6->ip6af_off;
330 if (i > 0) {
331 log(LOG_ERR, "%d bytes of a fragment from %s "
332 "overlaps the succeeding fragment",
333 i, ip6_sprintf(&q6->ip6q_src));
334 goto dropfrag;
335 }
336 }
390 * If the incoming framgent overlaps some existing fragments in
391 * the reassembly queue, drop it, since it is dangerous to override
392 * existing fragments from a security point of view.
393 */
394 if (af6->ip6af_up != (struct ip6asfrag *)q6) {
395 i = af6->ip6af_up->ip6af_off + af6->ip6af_up->ip6af_frglen
396 - ip6af->ip6af_off;
397 if (i > 0) {

--- 7 unchanged lines hidden (view full) ---

405 i = (ip6af->ip6af_off + ip6af->ip6af_frglen) - af6->ip6af_off;
406 if (i > 0) {
407 log(LOG_ERR, "%d bytes of a fragment from %s "
408 "overlaps the succeeding fragment",
409 i, ip6_sprintf(&q6->ip6q_src));
410 goto dropfrag;
411 }
412 }
413#endif
337
338insert:
339
340 /*
341 * Stick new segment in its place;
342 * check for complete reassembly.
343 * Move to front of packet queue, as we are
344 * the most recently active fragmented packet.
345 */
346 frag6_enq(ip6af, af6->ip6af_up);
414
415insert:
416
417 /*
418 * Stick new segment in its place;
419 * check for complete reassembly.
420 * Move to front of packet queue, as we are
421 * the most recently active fragmented packet.
422 */
423 frag6_enq(ip6af, af6->ip6af_up);
424#if 0 /* xxx */
425 if (q6 != ip6q.ip6q_next) {
426 frag6_remque(q6);
427 frag6_insque(q6, &ip6q);
428 }
429#endif
347 next = 0;
348 for (af6 = q6->ip6q_down; af6 != (struct ip6asfrag *)q6;
349 af6 = af6->ip6af_down) {
350 if (af6->ip6af_off != next) {
351 frag6_doing_reass = 0;
352 return IPPROTO_DONE;
353 }
354 next += af6->ip6af_frglen;
355 }
356 if (af6->ip6af_up->ip6af_mff) {
357 frag6_doing_reass = 0;
358 return IPPROTO_DONE;
359 }
360
361 /*
362 * Reassembly is complete; concatenate fragments.
363 */
430 next = 0;
431 for (af6 = q6->ip6q_down; af6 != (struct ip6asfrag *)q6;
432 af6 = af6->ip6af_down) {
433 if (af6->ip6af_off != next) {
434 frag6_doing_reass = 0;
435 return IPPROTO_DONE;
436 }
437 next += af6->ip6af_frglen;
438 }
439 if (af6->ip6af_up->ip6af_mff) {
440 frag6_doing_reass = 0;
441 return IPPROTO_DONE;
442 }
443
444 /*
445 * Reassembly is complete; concatenate fragments.
446 */
364
365 ip6af = q6->ip6q_down;
366 t = m = IP6_REASS_MBUF(ip6af);
367 af6 = ip6af->ip6af_down;
447 ip6af = q6->ip6q_down;
448 t = m = IP6_REASS_MBUF(ip6af);
449 af6 = ip6af->ip6af_down;
450 frag6_deq(ip6af);
368 while (af6 != (struct ip6asfrag *)q6) {
451 while (af6 != (struct ip6asfrag *)q6) {
452 af6dwn = af6->ip6af_down;
453 frag6_deq(af6);
369 while (t->m_next)
370 t = t->m_next;
371 t->m_next = IP6_REASS_MBUF(af6);
454 while (t->m_next)
455 t = t->m_next;
456 t->m_next = IP6_REASS_MBUF(af6);
372 af6 = af6->ip6af_down;
457 m_adj(t->m_next, af6->ip6af_offset);
458 free(af6, M_FTABLE);
459 af6 = af6dwn;
373 }
374
375 /* adjust offset to point where the original next header starts */
376 offset = ip6af->ip6af_offset - sizeof(struct ip6_frag);
460 }
461
462 /* adjust offset to point where the original next header starts */
463 offset = ip6af->ip6af_offset - sizeof(struct ip6_frag);
377 ip6 = (struct ip6_hdr *)ip6af;
464 free(ip6af, M_FTABLE);
465 ip6 = mtod(m, struct ip6_hdr *);
378 ip6->ip6_plen = htons((u_short)next + offset - sizeof(struct ip6_hdr));
379 ip6->ip6_src = q6->ip6q_src;
380 ip6->ip6_dst = q6->ip6q_dst;
381 nxt = q6->ip6q_nxt;
466 ip6->ip6_plen = htons((u_short)next + offset - sizeof(struct ip6_hdr));
467 ip6->ip6_src = q6->ip6q_src;
468 ip6->ip6_dst = q6->ip6q_dst;
469 nxt = q6->ip6q_nxt;
470#ifdef notyet
471 *q6->ip6q_nxtp = (u_char)(nxt & 0xff);
472#endif
382
383 /*
384 * Delete frag6 header with as a few cost as possible.
385 */
473
474 /*
475 * Delete frag6 header with as a few cost as possible.
476 */
386
387 if (offset < m->m_len)
477 if (offset < m->m_len) {
388 ovbcopy((caddr_t)ip6, (caddr_t)ip6 + sizeof(struct ip6_frag),
389 offset);
478 ovbcopy((caddr_t)ip6, (caddr_t)ip6 + sizeof(struct ip6_frag),
479 offset);
390 else {
391 ovbcopy(mtod(m, caddr_t), (caddr_t)ip6 + offset, m->m_len);
392 m->m_data -= sizeof(struct ip6_frag);
480 m->m_data += sizeof(struct ip6_frag);
481 m->m_len -= sizeof(struct ip6_frag);
482 } else {
483 /* this comes with no copy if the boundary is on cluster */
484 if ((t = m_split(m, offset, M_DONTWAIT)) == NULL) {
485 frag6_remque(q6);
486 free(q6, M_FTABLE);
487 frag6_nfragpackets--;
488 goto dropfrag;
489 }
490 m_adj(t, sizeof(struct ip6_frag));
491 m_cat(m, t);
393 }
492 }
394 m->m_data -= offset;
395 m->m_len += offset;
396
397 /*
398 * Store NXT to the original.
399 */
400 {
401 char *prvnxtp = ip6_get_prevhdr(m, offset); /* XXX */
402 *prvnxtp = nxt;
403 }

--- 49 unchanged lines hidden (view full) ---

453 /*
454 * Return ICMP time exceeded error for the 1st fragment.
455 * Just free other fragments.
456 */
457 if (af6->ip6af_off == 0) {
458 struct ip6_hdr *ip6;
459
460 /* adjust pointer */
493
494 /*
495 * Store NXT to the original.
496 */
497 {
498 char *prvnxtp = ip6_get_prevhdr(m, offset); /* XXX */
499 *prvnxtp = nxt;
500 }

--- 49 unchanged lines hidden (view full) ---

550 /*
551 * Return ICMP time exceeded error for the 1st fragment.
552 * Just free other fragments.
553 */
554 if (af6->ip6af_off == 0) {
555 struct ip6_hdr *ip6;
556
557 /* adjust pointer */
461 m->m_data -= af6->ip6af_offset;
462 m->m_len += af6->ip6af_offset;
463 ip6 = mtod(m, struct ip6_hdr *);
464
465 /* restoure source and destination addresses */
466 ip6->ip6_src = q6->ip6q_src;
467 ip6->ip6_dst = q6->ip6q_dst;
468
469 icmp6_error(m, ICMP6_TIME_EXCEEDED,
470 ICMP6_TIME_EXCEED_REASSEMBLY, 0);
558 ip6 = mtod(m, struct ip6_hdr *);
559
560 /* restoure source and destination addresses */
561 ip6->ip6_src = q6->ip6q_src;
562 ip6->ip6_dst = q6->ip6q_dst;
563
564 icmp6_error(m, ICMP6_TIME_EXCEEDED,
565 ICMP6_TIME_EXCEED_REASSEMBLY, 0);
471 }
472 else
566 } else
473 m_freem(m);
567 m_freem(m);
568 free(af6, M_FTABLE);
474 }
475 frag6_remque(q6);
476 free(q6, M_FTABLE);
477 frag6_nfragpackets--;
478}
479
480/*
481 * Put an ip fragment on a reassembly chain.

--- 43 unchanged lines hidden (view full) ---

525 * if a timer expires on a reassembly
526 * queue, discard it.
527 */
528void
529frag6_slowtimo()
530{
531 struct ip6q *q6;
532 int s = splnet();
569 }
570 frag6_remque(q6);
571 free(q6, M_FTABLE);
572 frag6_nfragpackets--;
573}
574
575/*
576 * Put an ip fragment on a reassembly chain.

--- 43 unchanged lines hidden (view full) ---

620 * if a timer expires on a reassembly
621 * queue, discard it.
622 */
623void
624frag6_slowtimo()
625{
626 struct ip6q *q6;
627 int s = splnet();
628#if 0
629 extern struct route_in6 ip6_forward_rt;
630#endif
533
534 frag6_doing_reass = 1;
535 q6 = ip6q.ip6q_next;
536 if (q6)
537 while (q6 != &ip6q) {
538 --q6->ip6q_ttl;
539 q6 = q6->ip6q_next;
540 if (q6->ip6q_prev->ip6q_ttl == 0) {

--- 8 unchanged lines hidden (view full) ---

549 * enough to get down to the new limit.
550 */
551 while (frag6_nfragpackets > (u_int)ip6_maxfragpackets) {
552 ip6stat.ip6s_fragoverflow++;
553 /* XXX in6_ifstat_inc(ifp, ifs6_reass_fail) */
554 frag6_freef(ip6q.ip6q_prev);
555 }
556 frag6_doing_reass = 0;
631
632 frag6_doing_reass = 1;
633 q6 = ip6q.ip6q_next;
634 if (q6)
635 while (q6 != &ip6q) {
636 --q6->ip6q_ttl;
637 q6 = q6->ip6q_next;
638 if (q6->ip6q_prev->ip6q_ttl == 0) {

--- 8 unchanged lines hidden (view full) ---

647 * enough to get down to the new limit.
648 */
649 while (frag6_nfragpackets > (u_int)ip6_maxfragpackets) {
650 ip6stat.ip6s_fragoverflow++;
651 /* XXX in6_ifstat_inc(ifp, ifs6_reass_fail) */
652 frag6_freef(ip6q.ip6q_prev);
653 }
654 frag6_doing_reass = 0;
655
656#if 0
657 /*
658 * Routing changes might produce a better route than we last used;
659 * make sure we notice eventually, even if forwarding only for one
660 * destination and the cache is never replaced.
661 */
662 if (ip6_forward_rt.ro_rt) {
663 RTFREE(ip6_forward_rt.ro_rt);
664 ip6_forward_rt.ro_rt = 0;
665 }
666 if (ipsrcchk_rt.ro_rt) {
667 RTFREE(ipsrcchk_rt.ro_rt);
668 ipsrcchk_rt.ro_rt = 0;
669 }
670#endif
671
557 splx(s);
558}
559
560/*
561 * Drain off all datagram fragments.
562 */
563void
564frag6_drain()
565{
566 if (frag6_doing_reass)
567 return;
568 while (ip6q.ip6q_next != &ip6q) {
569 ip6stat.ip6s_fragdropped++;
570 /* XXX in6_ifstat_inc(ifp, ifs6_reass_fail) */
571 frag6_freef(ip6q.ip6q_next);
572 }
573}
672 splx(s);
673}
674
675/*
676 * Drain off all datagram fragments.
677 */
678void
679frag6_drain()
680{
681 if (frag6_doing_reass)
682 return;
683 while (ip6q.ip6q_next != &ip6q) {
684 ip6stat.ip6s_fragdropped++;
685 /* XXX in6_ifstat_inc(ifp, ifs6_reass_fail) */
686 frag6_freef(ip6q.ip6q_next);
687 }
688}