]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/netinet6/frag6.c
Initial import from vendor-sys branch of openzfs
[FreeBSD/FreeBSD.git] / sys / netinet6 / frag6.c
1 /*-
2  * SPDX-License-Identifier: BSD-3-Clause
3  *
4  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
5  * All rights reserved.
6  * Copyright (c) 2019 Netflix, Inc.
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
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 3. Neither the name of the project nor the names of its contributors
17  *    may be used to endorse or promote products derived from this software
18  *    without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
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.
31  *
32  *      $KAME: frag6.c,v 1.33 2002/01/07 11:34:48 kjc Exp $
33  */
34
35 #include <sys/cdefs.h>
36 __FBSDID("$FreeBSD$");
37
38 #include "opt_rss.h"
39
40 #include <sys/param.h>
41 #include <sys/systm.h>
42 #include <sys/domain.h>
43 #include <sys/eventhandler.h>
44 #include <sys/hash.h>
45 #include <sys/kernel.h>
46 #include <sys/malloc.h>
47 #include <sys/mbuf.h>
48 #include <sys/protosw.h>
49 #include <sys/queue.h>
50 #include <sys/socket.h>
51 #include <sys/sysctl.h>
52 #include <sys/syslog.h>
53
54 #include <net/if.h>
55 #include <net/if_var.h>
56 #include <net/netisr.h>
57 #include <net/route.h>
58 #include <net/vnet.h>
59
60 #include <netinet/in.h>
61 #include <netinet/in_var.h>
62 #include <netinet/ip6.h>
63 #include <netinet6/ip6_var.h>
64 #include <netinet/icmp6.h>
65 #include <netinet/in_systm.h>   /* For ECN definitions. */
66 #include <netinet/ip.h>         /* For ECN definitions. */
67
68 #ifdef MAC
69 #include <security/mac/mac_framework.h>
70 #endif
71
72 /*
73  * A "big picture" of how IPv6 fragment queues are all linked together.
74  *
75  * struct ip6qbucket ip6qb[...];                        hashed buckets
76  * ||||||||
77  * |
78  * +--- TAILQ(struct ip6q, packets) *q6;                tailq entries holding
79  *      ||||||||                                        fragmented packets
80  *      |                                               (1 per original packet)
81  *      |
82  *      +--- TAILQ(struct ip6asfrag, ip6q_frags) *af6;  tailq entries of IPv6
83  *           |                                   *ip6af;fragment packets
84  *           |                                          for one original packet
85  *           + *mbuf
86  */
87
88 /* Reassembly headers are stored in hash buckets. */
89 #define IP6REASS_NHASH_LOG2     10
90 #define IP6REASS_NHASH          (1 << IP6REASS_NHASH_LOG2)
91 #define IP6REASS_HMASK          (IP6REASS_NHASH - 1)
92
93 TAILQ_HEAD(ip6qhead, ip6q);
94 struct ip6qbucket {
95         struct ip6qhead packets;
96         struct mtx      lock;
97         int             count;
98 };
99
100 struct ip6asfrag {
101         TAILQ_ENTRY(ip6asfrag) ip6af_tq;
102         struct mbuf     *ip6af_m;
103         int             ip6af_offset;   /* Offset in ip6af_m to next header. */
104         int             ip6af_frglen;   /* Fragmentable part length. */
105         int             ip6af_off;      /* Fragment offset. */
106         bool            ip6af_mff;      /* More fragment bit in frag off. */
107 };
108
109 static MALLOC_DEFINE(M_FRAG6, "frag6", "IPv6 fragment reassembly header");
110
111 #ifdef VIMAGE
112 /* A flag to indicate if IPv6 fragmentation is initialized. */
113 VNET_DEFINE_STATIC(bool,                frag6_on);
114 #define V_frag6_on                      VNET(frag6_on)
115 #endif
116
117 /* System wide (global) maximum and count of packets in reassembly queues. */
118 static int ip6_maxfrags;
119 static volatile u_int frag6_nfrags = 0;
120
121 /* Maximum and current packets in per-VNET reassembly queue. */
122 VNET_DEFINE_STATIC(int,                 ip6_maxfragpackets);
123 VNET_DEFINE_STATIC(volatile u_int,      frag6_nfragpackets);
124 #define V_ip6_maxfragpackets            VNET(ip6_maxfragpackets)
125 #define V_frag6_nfragpackets            VNET(frag6_nfragpackets)
126
127 /* Maximum per-VNET reassembly queues per bucket and fragments per packet. */
128 VNET_DEFINE_STATIC(int,                 ip6_maxfragbucketsize);
129 VNET_DEFINE_STATIC(int,                 ip6_maxfragsperpacket);
130 #define V_ip6_maxfragbucketsize         VNET(ip6_maxfragbucketsize)
131 #define V_ip6_maxfragsperpacket         VNET(ip6_maxfragsperpacket)
132
133 /* Per-VNET reassembly queue buckets. */
134 VNET_DEFINE_STATIC(struct ip6qbucket,   ip6qb[IP6REASS_NHASH]);
135 VNET_DEFINE_STATIC(uint32_t,            ip6qb_hashseed);
136 #define V_ip6qb                         VNET(ip6qb)
137 #define V_ip6qb_hashseed                VNET(ip6qb_hashseed)
138
139 #define IP6QB_LOCK(_b)          mtx_lock(&V_ip6qb[(_b)].lock)
140 #define IP6QB_TRYLOCK(_b)       mtx_trylock(&V_ip6qb[(_b)].lock)
141 #define IP6QB_LOCK_ASSERT(_b)   mtx_assert(&V_ip6qb[(_b)].lock, MA_OWNED)
142 #define IP6QB_UNLOCK(_b)        mtx_unlock(&V_ip6qb[(_b)].lock)
143 #define IP6QB_HEAD(_b)          (&V_ip6qb[(_b)].packets)
144
145 /*
146  * By default, limit the number of IP6 fragments across all reassembly
147  * queues to  1/32 of the total number of mbuf clusters.
148  *
149  * Limit the total number of reassembly queues per VNET to the
150  * IP6 fragment limit, but ensure the limit will not allow any bucket
151  * to grow above 100 items. (The bucket limit is
152  * IP_MAXFRAGPACKETS / (IPREASS_NHASH / 2), so the 50 is the correct
153  * multiplier to reach a 100-item limit.)
154  * The 100-item limit was chosen as brief testing seems to show that
155  * this produces "reasonable" performance on some subset of systems
156  * under DoS attack.
157  */
158 #define IP6_MAXFRAGS            (nmbclusters / 32)
159 #define IP6_MAXFRAGPACKETS      (imin(IP6_MAXFRAGS, IP6REASS_NHASH * 50))
160
161
162 /*
163  * Sysctls and helper function.
164  */
165 SYSCTL_DECL(_net_inet6_ip6);
166
167 SYSCTL_UINT(_net_inet6_ip6, OID_AUTO, frag6_nfrags,
168         CTLFLAG_RD, __DEVOLATILE(u_int *, &frag6_nfrags), 0,
169         "Global number of IPv6 fragments across all reassembly queues.");
170
171 static void
172 frag6_set_bucketsize(void)
173 {
174         int i;
175
176         if ((i = V_ip6_maxfragpackets) > 0)
177                 V_ip6_maxfragbucketsize = imax(i / (IP6REASS_NHASH / 2), 1);
178 }
179
180 SYSCTL_INT(_net_inet6_ip6, IPV6CTL_MAXFRAGS, maxfrags,
181         CTLFLAG_RW, &ip6_maxfrags, 0,
182         "Maximum allowed number of outstanding IPv6 packet fragments. "
183         "A value of 0 means no fragmented packets will be accepted, while a "
184         "a value of -1 means no limit");
185
186 static int
187 sysctl_ip6_maxfragpackets(SYSCTL_HANDLER_ARGS)
188 {
189         int error, val;
190
191         val = V_ip6_maxfragpackets;
192         error = sysctl_handle_int(oidp, &val, 0, req);
193         if (error != 0 || !req->newptr)
194                 return (error);
195         V_ip6_maxfragpackets = val;
196         frag6_set_bucketsize();
197         return (0);
198 }
199 SYSCTL_PROC(_net_inet6_ip6, IPV6CTL_MAXFRAGPACKETS, maxfragpackets,
200         CTLFLAG_VNET | CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NEEDGIANT,
201         NULL, 0, sysctl_ip6_maxfragpackets, "I",
202         "Default maximum number of outstanding fragmented IPv6 packets. "
203         "A value of 0 means no fragmented packets will be accepted, while a "
204         "a value of -1 means no limit");
205 SYSCTL_UINT(_net_inet6_ip6, OID_AUTO, frag6_nfragpackets,
206         CTLFLAG_VNET | CTLFLAG_RD,
207         __DEVOLATILE(u_int *, &VNET_NAME(frag6_nfragpackets)), 0,
208         "Per-VNET number of IPv6 fragments across all reassembly queues.");
209 SYSCTL_INT(_net_inet6_ip6, IPV6CTL_MAXFRAGSPERPACKET, maxfragsperpacket,
210         CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(ip6_maxfragsperpacket), 0,
211         "Maximum allowed number of fragments per packet");
212 SYSCTL_INT(_net_inet6_ip6, IPV6CTL_MAXFRAGBUCKETSIZE, maxfragbucketsize,
213         CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(ip6_maxfragbucketsize), 0,
214         "Maximum number of reassembly queues per hash bucket");
215
216
217 /*
218  * Remove the IPv6 fragmentation header from the mbuf.
219  */
220 int
221 ip6_deletefraghdr(struct mbuf *m, int offset, int wait __unused)
222 {
223         struct ip6_hdr *ip6;
224
225         KASSERT(m->m_len >= offset + sizeof(struct ip6_frag),
226             ("%s: ext headers not contigous in mbuf %p m_len %d >= "
227             "offset %d + %zu\n", __func__, m, m->m_len, offset,
228             sizeof(struct ip6_frag)));
229
230         /* Delete frag6 header. */
231         ip6 = mtod(m, struct ip6_hdr *);
232         bcopy(ip6, (char *)ip6 + sizeof(struct ip6_frag), offset);
233         m->m_data += sizeof(struct ip6_frag);
234         m->m_len -= sizeof(struct ip6_frag);
235         m->m_flags |= M_FRAGMENTED;
236
237         return (0);
238 }
239
240 /*
241  * Free a fragment reassembly header and all associated datagrams.
242  */
243 static void
244 frag6_freef(struct ip6q *q6, uint32_t bucket)
245 {
246         struct ip6_hdr *ip6;
247         struct ip6asfrag *af6;
248         struct mbuf *m;
249
250         IP6QB_LOCK_ASSERT(bucket);
251
252         while ((af6 = TAILQ_FIRST(&q6->ip6q_frags)) != NULL) {
253
254                 m = af6->ip6af_m;
255                 TAILQ_REMOVE(&q6->ip6q_frags, af6, ip6af_tq);
256
257                 /*
258                  * Return ICMP time exceeded error for the 1st fragment.
259                  * Just free other fragments.
260                  */
261                 if (af6->ip6af_off == 0 && m->m_pkthdr.rcvif != NULL) {
262
263                         /* Adjust pointer. */
264                         ip6 = mtod(m, struct ip6_hdr *);
265
266                         /* Restore source and destination addresses. */
267                         ip6->ip6_src = q6->ip6q_src;
268                         ip6->ip6_dst = q6->ip6q_dst;
269
270                         icmp6_error(m, ICMP6_TIME_EXCEEDED,
271                             ICMP6_TIME_EXCEED_REASSEMBLY, 0);
272                 } else
273                         m_freem(m);
274
275                 free(af6, M_FRAG6);
276         }
277
278         TAILQ_REMOVE(IP6QB_HEAD(bucket), q6, ip6q_tq);
279         V_ip6qb[bucket].count--;
280         atomic_subtract_int(&frag6_nfrags, q6->ip6q_nfrag);
281 #ifdef MAC
282         mac_ip6q_destroy(q6);
283 #endif
284         free(q6, M_FRAG6);
285         atomic_subtract_int(&V_frag6_nfragpackets, 1);
286 }
287
288 /*
289  * Drain off all datagram fragments belonging to
290  * the given network interface.
291  */
292 static void
293 frag6_cleanup(void *arg __unused, struct ifnet *ifp)
294 {
295         struct ip6qhead *head;
296         struct ip6q *q6;
297         struct ip6asfrag *af6;
298         uint32_t bucket;
299
300         KASSERT(ifp != NULL, ("%s: ifp is NULL", __func__));
301
302         CURVNET_SET_QUIET(ifp->if_vnet);
303 #ifdef VIMAGE
304         /*
305          * Skip processing if IPv6 reassembly is not initialised or
306          * torn down by frag6_destroy().
307          */
308         if (!V_frag6_on) {
309                 CURVNET_RESTORE();
310                 return;
311         }
312 #endif
313
314         for (bucket = 0; bucket < IP6REASS_NHASH; bucket++) {
315                 IP6QB_LOCK(bucket);
316                 head = IP6QB_HEAD(bucket);
317                 /* Scan fragment list. */
318                 TAILQ_FOREACH(q6, head, ip6q_tq) {
319                         TAILQ_FOREACH(af6, &q6->ip6q_frags, ip6af_tq) {
320
321                                 /* Clear no longer valid rcvif pointer. */
322                                 if (af6->ip6af_m->m_pkthdr.rcvif == ifp)
323                                         af6->ip6af_m->m_pkthdr.rcvif = NULL;
324                         }
325                 }
326                 IP6QB_UNLOCK(bucket);
327         }
328         CURVNET_RESTORE();
329 }
330 EVENTHANDLER_DEFINE(ifnet_departure_event, frag6_cleanup, NULL, 0);
331
332 /*
333  * Like in RFC2460, in RFC8200, fragment and reassembly rules do not agree with
334  * each other, in terms of next header field handling in fragment header.
335  * While the sender will use the same value for all of the fragmented packets,
336  * receiver is suggested not to check for consistency.
337  *
338  * Fragment rules (p18,p19):
339  *      (2)  A Fragment header containing:
340  *      The Next Header value that identifies the first header
341  *      after the Per-Fragment headers of the original packet.
342  *              -> next header field is same for all fragments
343  *
344  * Reassembly rule (p20):
345  *      The Next Header field of the last header of the Per-Fragment
346  *      headers is obtained from the Next Header field of the first
347  *      fragment's Fragment header.
348  *              -> should grab it from the first fragment only
349  *
350  * The following note also contradicts with fragment rule - no one is going to
351  * send different fragment with different next header field.
352  *
353  * Additional note (p22) [not an error]:
354  *      The Next Header values in the Fragment headers of different
355  *      fragments of the same original packet may differ.  Only the value
356  *      from the Offset zero fragment packet is used for reassembly.
357  *              -> should grab it from the first fragment only
358  *
359  * There is no explicit reason given in the RFC.  Historical reason maybe?
360  */
361 /*
362  * Fragment input.
363  */
364 int
365 frag6_input(struct mbuf **mp, int *offp, int proto)
366 {
367         struct mbuf *m, *t;
368         struct ip6_hdr *ip6;
369         struct ip6_frag *ip6f;
370         struct ip6qhead *head;
371         struct ip6q *q6;
372         struct ip6asfrag *af6, *ip6af, *af6tmp;
373         struct in6_ifaddr *ia6;
374         struct ifnet *dstifp, *srcifp;
375         uint32_t hashkey[(sizeof(struct in6_addr) * 2 +
376                     sizeof(ip6f->ip6f_ident)) / sizeof(uint32_t)];
377         uint32_t bucket, *hashkeyp;
378         int fragoff, frgpartlen;        /* Must be larger than uint16_t. */
379         int nxt, offset, plen;
380         uint8_t ecn, ecn0;
381         bool only_frag;
382 #ifdef RSS
383         struct ip6_direct_ctx *ip6dc;
384         struct m_tag *mtag;
385 #endif
386
387         m = *mp;
388         offset = *offp;
389
390         M_ASSERTPKTHDR(m);
391
392         if (m->m_len < offset + sizeof(struct ip6_frag)) {
393                 m = m_pullup(m, offset + sizeof(struct ip6_frag));
394                 if (m == NULL) {
395                         IP6STAT_INC(ip6s_exthdrtoolong);
396                         *mp = NULL;
397                         return (IPPROTO_DONE);
398                 }
399         }
400         ip6 = mtod(m, struct ip6_hdr *);
401
402         dstifp = NULL;
403         /* Find the destination interface of the packet. */
404         ia6 = in6ifa_ifwithaddr(&ip6->ip6_dst, 0 /* XXX */);
405         if (ia6 != NULL) {
406                 dstifp = ia6->ia_ifp;
407                 ifa_free(&ia6->ia_ifa);
408         }
409
410         /* Jumbo payload cannot contain a fragment header. */
411         if (ip6->ip6_plen == 0) {
412                 icmp6_error(m, ICMP6_PARAM_PROB, ICMP6_PARAMPROB_HEADER, offset);
413                 in6_ifstat_inc(dstifp, ifs6_reass_fail);
414                 *mp = NULL;
415                 return (IPPROTO_DONE);
416         }
417
418         /*
419          * Check whether fragment packet's fragment length is a
420          * multiple of 8 octets (unless it is the last one).
421          * sizeof(struct ip6_frag) == 8
422          * sizeof(struct ip6_hdr) = 40
423          */
424         ip6f = (struct ip6_frag *)((caddr_t)ip6 + offset);
425         if ((ip6f->ip6f_offlg & IP6F_MORE_FRAG) &&
426             (((ntohs(ip6->ip6_plen) - offset) & 0x7) != 0)) {
427                 icmp6_error(m, ICMP6_PARAM_PROB, ICMP6_PARAMPROB_HEADER,
428                     offsetof(struct ip6_hdr, ip6_plen));
429                 in6_ifstat_inc(dstifp, ifs6_reass_fail);
430                 *mp = NULL;
431                 return (IPPROTO_DONE);
432         }
433
434         IP6STAT_INC(ip6s_fragments);
435         in6_ifstat_inc(dstifp, ifs6_reass_reqd);
436
437         /*
438          * Handle "atomic" fragments (offset and m bit set to 0) upfront,
439          * unrelated to any reassembly.  We need to remove the frag hdr
440          * which is ugly.
441          * See RFC 6946 and section 4.5 of RFC 8200.
442          */
443         if ((ip6f->ip6f_offlg & ~IP6F_RESERVED_MASK) == 0) {
444                 IP6STAT_INC(ip6s_atomicfrags);
445                 nxt = ip6f->ip6f_nxt;
446                 /*
447                  * Set nxt(-hdr field value) to the original value.
448                  * We cannot just set ip6->ip6_nxt as there might be
449                  * an unfragmentable part with extension headers and
450                  * we must update the last one.
451                  */
452                 m_copyback(m, ip6_get_prevhdr(m, offset), sizeof(uint8_t),
453                     (caddr_t)&nxt);
454                 ip6->ip6_plen = htons(ntohs(ip6->ip6_plen) -
455                     sizeof(struct ip6_frag));
456                 if (ip6_deletefraghdr(m, offset, M_NOWAIT) != 0)
457                         goto dropfrag2;
458                 m->m_pkthdr.len -= sizeof(struct ip6_frag);
459                 in6_ifstat_inc(dstifp, ifs6_reass_ok);
460                 *mp = m;
461                 return (nxt);
462         }
463
464         /* Offset now points to data portion. */
465         offset += sizeof(struct ip6_frag);
466
467         /* Get fragment length and discard 0-byte fragments. */
468         frgpartlen = sizeof(struct ip6_hdr) + ntohs(ip6->ip6_plen) - offset;
469         if (frgpartlen == 0) {
470                 icmp6_error(m, ICMP6_PARAM_PROB, ICMP6_PARAMPROB_HEADER,
471                     offsetof(struct ip6_hdr, ip6_plen));
472                 in6_ifstat_inc(dstifp, ifs6_reass_fail);
473                 IP6STAT_INC(ip6s_fragdropped);
474                 *mp = NULL;
475                 return (IPPROTO_DONE);
476         }
477
478         /*
479          * Enforce upper bound on number of fragments for the entire system.
480          * If maxfrag is 0, never accept fragments.
481          * If maxfrag is -1, accept all fragments without limitation.
482          */
483         if (ip6_maxfrags < 0)
484                 ;
485         else if (atomic_load_int(&frag6_nfrags) >= (u_int)ip6_maxfrags)
486                 goto dropfrag2;
487
488         /*
489          * Validate that a full header chain to the ULP is present in the
490          * packet containing the first fragment as per RFC RFC7112 and
491          * RFC 8200 pages 18,19:
492          * The first fragment packet is composed of:
493          * (3)  Extension headers, if any, and the Upper-Layer header.  These
494          *      headers must be in the first fragment.  ...
495          */
496         fragoff = ntohs(ip6f->ip6f_offlg & IP6F_OFF_MASK);
497         /* XXX TODO.  thj has D16851 open for this. */
498         /* Send ICMPv6 4,3 in case of violation. */
499
500         /* Store receive network interface pointer for later. */
501         srcifp = m->m_pkthdr.rcvif;
502
503         /* Generate a hash value for fragment bucket selection. */
504         hashkeyp = hashkey;
505         memcpy(hashkeyp, &ip6->ip6_src, sizeof(struct in6_addr));
506         hashkeyp += sizeof(struct in6_addr) / sizeof(*hashkeyp);
507         memcpy(hashkeyp, &ip6->ip6_dst, sizeof(struct in6_addr));
508         hashkeyp += sizeof(struct in6_addr) / sizeof(*hashkeyp);
509         *hashkeyp = ip6f->ip6f_ident;
510         bucket = jenkins_hash32(hashkey, nitems(hashkey), V_ip6qb_hashseed);
511         bucket &= IP6REASS_HMASK;
512         IP6QB_LOCK(bucket);
513         head = IP6QB_HEAD(bucket);
514
515         TAILQ_FOREACH(q6, head, ip6q_tq)
516                 if (ip6f->ip6f_ident == q6->ip6q_ident &&
517                     IN6_ARE_ADDR_EQUAL(&ip6->ip6_src, &q6->ip6q_src) &&
518                     IN6_ARE_ADDR_EQUAL(&ip6->ip6_dst, &q6->ip6q_dst)
519 #ifdef MAC
520                     && mac_ip6q_match(m, q6)
521 #endif
522                     )
523                         break;
524
525         only_frag = false;
526         if (q6 == NULL) {
527
528                 /* A first fragment to arrive creates a reassembly queue. */
529                 only_frag = true;
530
531                 /*
532                  * Enforce upper bound on number of fragmented packets
533                  * for which we attempt reassembly;
534                  * If maxfragpackets is 0, never accept fragments.
535                  * If maxfragpackets is -1, accept all fragments without
536                  * limitation.
537                  */
538                 if (V_ip6_maxfragpackets < 0)
539                         ;
540                 else if (V_ip6qb[bucket].count >= V_ip6_maxfragbucketsize ||
541                     atomic_load_int(&V_frag6_nfragpackets) >=
542                     (u_int)V_ip6_maxfragpackets)
543                         goto dropfrag;
544
545                 /* Allocate IPv6 fragement packet queue entry. */
546                 q6 = (struct ip6q *)malloc(sizeof(struct ip6q), M_FRAG6,
547                     M_NOWAIT | M_ZERO);
548                 if (q6 == NULL)
549                         goto dropfrag;
550 #ifdef MAC
551                 if (mac_ip6q_init(q6, M_NOWAIT) != 0) {
552                         free(q6, M_FRAG6);
553                         goto dropfrag;
554                 }
555                 mac_ip6q_create(m, q6);
556 #endif
557                 atomic_add_int(&V_frag6_nfragpackets, 1);
558
559                 /* ip6q_nxt will be filled afterwards, from 1st fragment. */
560                 TAILQ_INIT(&q6->ip6q_frags);
561                 q6->ip6q_ident  = ip6f->ip6f_ident;
562                 q6->ip6q_ttl    = IPV6_FRAGTTL;
563                 q6->ip6q_src    = ip6->ip6_src;
564                 q6->ip6q_dst    = ip6->ip6_dst;
565                 q6->ip6q_ecn    =
566                     (ntohl(ip6->ip6_flow) >> 20) & IPTOS_ECN_MASK;
567                 q6->ip6q_unfrglen = -1; /* The 1st fragment has not arrived. */
568
569                 /* Add the fragemented packet to the bucket. */
570                 TAILQ_INSERT_HEAD(head, q6, ip6q_tq);
571                 V_ip6qb[bucket].count++;
572         }
573
574         /*
575          * If it is the 1st fragment, record the length of the
576          * unfragmentable part and the next header of the fragment header.
577          * Assume the first 1st fragement to arrive will be correct.
578          * We do not have any duplicate checks here yet so another packet
579          * with fragoff == 0 could come and overwrite the ip6q_unfrglen
580          * and worse, the next header, at any time.
581          */
582         if (fragoff == 0 && q6->ip6q_unfrglen == -1) {
583                 q6->ip6q_unfrglen = offset - sizeof(struct ip6_hdr) -
584                     sizeof(struct ip6_frag);
585                 q6->ip6q_nxt = ip6f->ip6f_nxt;
586                 /* XXX ECN? */
587         }
588
589         /*
590          * Check that the reassembled packet would not exceed 65535 bytes
591          * in size.
592          * If it would exceed, discard the fragment and return an ICMP error.
593          */
594         if (q6->ip6q_unfrglen >= 0) {
595                 /* The 1st fragment has already arrived. */
596                 if (q6->ip6q_unfrglen + fragoff + frgpartlen > IPV6_MAXPACKET) {
597                         if (only_frag) {
598                                 TAILQ_REMOVE(head, q6, ip6q_tq);
599                                 V_ip6qb[bucket].count--;
600                                 atomic_subtract_int(&V_frag6_nfragpackets, 1);
601 #ifdef MAC
602                                 mac_ip6q_destroy(q6);
603 #endif
604                                 free(q6, M_FRAG6);
605                         }
606                         IP6QB_UNLOCK(bucket);
607                         icmp6_error(m, ICMP6_PARAM_PROB, ICMP6_PARAMPROB_HEADER,
608                             offset - sizeof(struct ip6_frag) +
609                             offsetof(struct ip6_frag, ip6f_offlg));
610                         *mp = NULL;
611                         return (IPPROTO_DONE);
612                 }
613         } else if (fragoff + frgpartlen > IPV6_MAXPACKET) {
614                 if (only_frag) {
615                         TAILQ_REMOVE(head, q6, ip6q_tq);
616                         V_ip6qb[bucket].count--;
617                         atomic_subtract_int(&V_frag6_nfragpackets, 1);
618 #ifdef MAC
619                         mac_ip6q_destroy(q6);
620 #endif
621                         free(q6, M_FRAG6);
622                 }
623                 IP6QB_UNLOCK(bucket);
624                 icmp6_error(m, ICMP6_PARAM_PROB, ICMP6_PARAMPROB_HEADER,
625                     offset - sizeof(struct ip6_frag) +
626                     offsetof(struct ip6_frag, ip6f_offlg));
627                 *mp = NULL;
628                 return (IPPROTO_DONE);
629         }
630
631         /*
632          * If it is the first fragment, do the above check for each
633          * fragment already stored in the reassembly queue.
634          */
635         if (fragoff == 0 && !only_frag) {
636                 TAILQ_FOREACH_SAFE(af6, &q6->ip6q_frags, ip6af_tq, af6tmp) {
637
638                         if (q6->ip6q_unfrglen + af6->ip6af_off +
639                             af6->ip6af_frglen > IPV6_MAXPACKET) {
640                                 struct ip6_hdr *ip6err;
641                                 struct mbuf *merr;
642                                 int erroff;
643
644                                 merr = af6->ip6af_m;
645                                 erroff = af6->ip6af_offset;
646
647                                 /* Dequeue the fragment. */
648                                 TAILQ_REMOVE(&q6->ip6q_frags, af6, ip6af_tq);
649                                 q6->ip6q_nfrag--;
650                                 atomic_subtract_int(&frag6_nfrags, 1);
651                                 free(af6, M_FRAG6);
652
653                                 /* Set a valid receive interface pointer. */
654                                 merr->m_pkthdr.rcvif = srcifp;
655
656                                 /* Adjust pointer. */
657                                 ip6err = mtod(merr, struct ip6_hdr *);
658
659                                 /*
660                                  * Restore source and destination addresses
661                                  * in the erroneous IPv6 header.
662                                  */
663                                 ip6err->ip6_src = q6->ip6q_src;
664                                 ip6err->ip6_dst = q6->ip6q_dst;
665
666                                 icmp6_error(merr, ICMP6_PARAM_PROB,
667                                     ICMP6_PARAMPROB_HEADER,
668                                     erroff - sizeof(struct ip6_frag) +
669                                     offsetof(struct ip6_frag, ip6f_offlg));
670                         }
671                 }
672         }
673
674         /* Allocate an IPv6 fragement queue entry for this fragmented part. */
675         ip6af = (struct ip6asfrag *)malloc(sizeof(struct ip6asfrag), M_FRAG6,
676             M_NOWAIT | M_ZERO);
677         if (ip6af == NULL)
678                 goto dropfrag;
679         ip6af->ip6af_mff = (ip6f->ip6f_offlg & IP6F_MORE_FRAG) ? true : false;
680         ip6af->ip6af_off = fragoff;
681         ip6af->ip6af_frglen = frgpartlen;
682         ip6af->ip6af_offset = offset;
683         ip6af->ip6af_m = m;
684
685         if (only_frag) {
686                 /*
687                  * Do a manual insert rather than a hard-to-understand cast
688                  * to a different type relying on data structure order to work.
689                  */
690                 TAILQ_INSERT_HEAD(&q6->ip6q_frags, ip6af, ip6af_tq);
691                 goto postinsert;
692         }
693
694         /* Do duplicate, condition, and boundry checks. */
695         /*
696          * Handle ECN by comparing this segment with the first one;
697          * if CE is set, do not lose CE.
698          * Drop if CE and not-ECT are mixed for the same packet.
699          */
700         ecn = (ntohl(ip6->ip6_flow) >> 20) & IPTOS_ECN_MASK;
701         ecn0 = q6->ip6q_ecn;
702         if (ecn == IPTOS_ECN_CE) {
703                 if (ecn0 == IPTOS_ECN_NOTECT) {
704                         free(ip6af, M_FRAG6);
705                         goto dropfrag;
706                 }
707                 if (ecn0 != IPTOS_ECN_CE)
708                         q6->ip6q_ecn = IPTOS_ECN_CE;
709         }
710         if (ecn == IPTOS_ECN_NOTECT && ecn0 != IPTOS_ECN_NOTECT) {
711                 free(ip6af, M_FRAG6);
712                 goto dropfrag;
713         }
714
715         /* Find a fragmented part which begins after this one does. */
716         TAILQ_FOREACH(af6, &q6->ip6q_frags, ip6af_tq)
717                 if (af6->ip6af_off > ip6af->ip6af_off)
718                         break;
719
720         /*
721          * If the incoming framgent overlaps some existing fragments in
722          * the reassembly queue, drop both the new fragment and the
723          * entire reassembly queue.  However, if the new fragment
724          * is an exact duplicate of an existing fragment, only silently
725          * drop the existing fragment and leave the fragmentation queue
726          * unchanged, as allowed by the RFC.  (RFC 8200, 4.5)
727          */
728         if (af6 != NULL)
729                 af6tmp = TAILQ_PREV(af6, ip6fraghead, ip6af_tq);
730         else
731                 af6tmp = TAILQ_LAST(&q6->ip6q_frags, ip6fraghead);
732         if (af6tmp != NULL) {
733                 if (af6tmp->ip6af_off + af6tmp->ip6af_frglen -
734                     ip6af->ip6af_off > 0) {
735                         if (af6tmp->ip6af_off != ip6af->ip6af_off ||
736                             af6tmp->ip6af_frglen != ip6af->ip6af_frglen)
737                                 frag6_freef(q6, bucket);
738                         free(ip6af, M_FRAG6);
739                         goto dropfrag;
740                 }
741         }
742         if (af6 != NULL) {
743                 if (ip6af->ip6af_off + ip6af->ip6af_frglen -
744                     af6->ip6af_off > 0) {
745                         if (af6->ip6af_off != ip6af->ip6af_off ||
746                             af6->ip6af_frglen != ip6af->ip6af_frglen)
747                                 frag6_freef(q6, bucket);
748                         free(ip6af, M_FRAG6);
749                         goto dropfrag;
750                 }
751         }
752
753 #ifdef MAC
754         mac_ip6q_update(m, q6);
755 #endif
756
757         /*
758          * Stick new segment in its place; check for complete reassembly.
759          * If not complete, check fragment limit.  Move to front of packet
760          * queue, as we are the most recently active fragmented packet.
761          */
762         if (af6 != NULL)
763                 TAILQ_INSERT_BEFORE(af6, ip6af, ip6af_tq);
764         else
765                 TAILQ_INSERT_TAIL(&q6->ip6q_frags, ip6af, ip6af_tq);
766 postinsert:
767         atomic_add_int(&frag6_nfrags, 1);
768         q6->ip6q_nfrag++;
769
770         plen = 0;
771         TAILQ_FOREACH(af6, &q6->ip6q_frags, ip6af_tq) {
772                 if (af6->ip6af_off != plen) {
773                         if (q6->ip6q_nfrag > V_ip6_maxfragsperpacket) {
774                                 IP6STAT_ADD(ip6s_fragdropped, q6->ip6q_nfrag);
775                                 frag6_freef(q6, bucket);
776                         }
777                         IP6QB_UNLOCK(bucket);
778                         *mp = NULL;
779                         return (IPPROTO_DONE);
780                 }
781                 plen += af6->ip6af_frglen;
782         }
783         af6 = TAILQ_LAST(&q6->ip6q_frags, ip6fraghead);
784         if (af6->ip6af_mff) {
785                 if (q6->ip6q_nfrag > V_ip6_maxfragsperpacket) {
786                         IP6STAT_ADD(ip6s_fragdropped, q6->ip6q_nfrag);
787                         frag6_freef(q6, bucket);
788                 }
789                 IP6QB_UNLOCK(bucket);
790                 *mp = NULL;
791                 return (IPPROTO_DONE);
792         }
793
794         /* Reassembly is complete; concatenate fragments. */
795         ip6af = TAILQ_FIRST(&q6->ip6q_frags);
796         t = m = ip6af->ip6af_m;
797         TAILQ_REMOVE(&q6->ip6q_frags, ip6af, ip6af_tq);
798         while ((af6 = TAILQ_FIRST(&q6->ip6q_frags)) != NULL) {
799                 m->m_pkthdr.csum_flags &=
800                     af6->ip6af_m->m_pkthdr.csum_flags;
801                 m->m_pkthdr.csum_data +=
802                     af6->ip6af_m->m_pkthdr.csum_data;
803
804                 TAILQ_REMOVE(&q6->ip6q_frags, af6, ip6af_tq);
805                 t = m_last(t);
806                 m_adj(af6->ip6af_m, af6->ip6af_offset);
807                 m_demote_pkthdr(af6->ip6af_m);
808                 m_cat(t, af6->ip6af_m);
809                 free(af6, M_FRAG6);
810         }
811
812         while (m->m_pkthdr.csum_data & 0xffff0000)
813                 m->m_pkthdr.csum_data = (m->m_pkthdr.csum_data & 0xffff) +
814                     (m->m_pkthdr.csum_data >> 16);
815
816         /* Adjust offset to point where the original next header starts. */
817         offset = ip6af->ip6af_offset - sizeof(struct ip6_frag);
818         free(ip6af, M_FRAG6);
819         ip6 = mtod(m, struct ip6_hdr *);
820         ip6->ip6_plen = htons((u_short)plen + offset - sizeof(struct ip6_hdr));
821         if (q6->ip6q_ecn == IPTOS_ECN_CE)
822                 ip6->ip6_flow |= htonl(IPTOS_ECN_CE << 20);
823         nxt = q6->ip6q_nxt;
824
825         TAILQ_REMOVE(head, q6, ip6q_tq);
826         V_ip6qb[bucket].count--;
827         atomic_subtract_int(&frag6_nfrags, q6->ip6q_nfrag);
828
829         ip6_deletefraghdr(m, offset, M_NOWAIT);
830
831         /* Set nxt(-hdr field value) to the original value. */
832         m_copyback(m, ip6_get_prevhdr(m, offset), sizeof(uint8_t),
833             (caddr_t)&nxt);
834
835 #ifdef MAC
836         mac_ip6q_reassemble(q6, m);
837         mac_ip6q_destroy(q6);
838 #endif
839         free(q6, M_FRAG6);
840         atomic_subtract_int(&V_frag6_nfragpackets, 1);
841
842         if (m->m_flags & M_PKTHDR) { /* Isn't it always true? */
843
844                 plen = 0;
845                 for (t = m; t; t = t->m_next)
846                         plen += t->m_len;
847                 m->m_pkthdr.len = plen;
848                 /* Set a valid receive interface pointer. */
849                 m->m_pkthdr.rcvif = srcifp;
850         }
851
852 #ifdef RSS
853         mtag = m_tag_alloc(MTAG_ABI_IPV6, IPV6_TAG_DIRECT, sizeof(*ip6dc),
854             M_NOWAIT);
855         if (mtag == NULL)
856                 goto dropfrag;
857
858         ip6dc = (struct ip6_direct_ctx *)(mtag + 1);
859         ip6dc->ip6dc_nxt = nxt;
860         ip6dc->ip6dc_off = offset;
861
862         m_tag_prepend(m, mtag);
863 #endif
864
865         IP6QB_UNLOCK(bucket);
866         IP6STAT_INC(ip6s_reassembled);
867         in6_ifstat_inc(dstifp, ifs6_reass_ok);
868
869 #ifdef RSS
870         /* Queue/dispatch for reprocessing. */
871         netisr_dispatch(NETISR_IPV6_DIRECT, m);
872         *mp = NULL;
873         return (IPPROTO_DONE);
874 #endif
875
876         /* Tell launch routine the next header. */
877         *mp = m;
878         *offp = offset;
879
880         return (nxt);
881
882 dropfrag:
883         IP6QB_UNLOCK(bucket);
884 dropfrag2:
885         in6_ifstat_inc(dstifp, ifs6_reass_fail);
886         IP6STAT_INC(ip6s_fragdropped);
887         m_freem(m);
888         *mp = NULL;
889         return (IPPROTO_DONE);
890 }
891
892 /*
893  * IPv6 reassembling timer processing;
894  * if a timer expires on a reassembly queue, discard it.
895  */
896 void
897 frag6_slowtimo(void)
898 {
899         VNET_ITERATOR_DECL(vnet_iter);
900         struct ip6qhead *head;
901         struct ip6q *q6, *q6tmp;
902         uint32_t bucket;
903
904         VNET_LIST_RLOCK_NOSLEEP();
905         VNET_FOREACH(vnet_iter) {
906                 CURVNET_SET(vnet_iter);
907                 for (bucket = 0; bucket < IP6REASS_NHASH; bucket++) {
908                         IP6QB_LOCK(bucket);
909                         head = IP6QB_HEAD(bucket);
910                         TAILQ_FOREACH_SAFE(q6, head, ip6q_tq, q6tmp)
911                                 if (--q6->ip6q_ttl == 0) {
912                                         IP6STAT_ADD(ip6s_fragtimeout,
913                                                 q6->ip6q_nfrag);
914                                         /* XXX in6_ifstat_inc(ifp, ifs6_reass_fail) */
915                                         frag6_freef(q6, bucket);
916                                 }
917                         /*
918                          * If we are over the maximum number of fragments
919                          * (due to the limit being lowered), drain off
920                          * enough to get down to the new limit.
921                          * Note that we drain all reassembly queues if
922                          * maxfragpackets is 0 (fragmentation is disabled),
923                          * and do not enforce a limit when maxfragpackets
924                          * is negative.
925                          */
926                         while ((V_ip6_maxfragpackets == 0 ||
927                             (V_ip6_maxfragpackets > 0 &&
928                             V_ip6qb[bucket].count > V_ip6_maxfragbucketsize)) &&
929                             (q6 = TAILQ_LAST(head, ip6qhead)) != NULL) {
930                                 IP6STAT_ADD(ip6s_fragoverflow, q6->ip6q_nfrag);
931                                 /* XXX in6_ifstat_inc(ifp, ifs6_reass_fail) */
932                                 frag6_freef(q6, bucket);
933                         }
934                         IP6QB_UNLOCK(bucket);
935                 }
936                 /*
937                  * If we are still over the maximum number of fragmented
938                  * packets, drain off enough to get down to the new limit.
939                  */
940                 bucket = 0;
941                 while (V_ip6_maxfragpackets >= 0 &&
942                     atomic_load_int(&V_frag6_nfragpackets) >
943                     (u_int)V_ip6_maxfragpackets) {
944                         IP6QB_LOCK(bucket);
945                         q6 = TAILQ_LAST(IP6QB_HEAD(bucket), ip6qhead);
946                         if (q6 != NULL) {
947                                 IP6STAT_ADD(ip6s_fragoverflow, q6->ip6q_nfrag);
948                                 /* XXX in6_ifstat_inc(ifp, ifs6_reass_fail) */
949                                 frag6_freef(q6, bucket);
950                         }
951                         IP6QB_UNLOCK(bucket);
952                         bucket = (bucket + 1) % IP6REASS_NHASH;
953                 }
954                 CURVNET_RESTORE();
955         }
956         VNET_LIST_RUNLOCK_NOSLEEP();
957 }
958
959 /*
960  * Eventhandler to adjust limits in case nmbclusters change.
961  */
962 static void
963 frag6_change(void *tag)
964 {
965         VNET_ITERATOR_DECL(vnet_iter);
966
967         ip6_maxfrags = IP6_MAXFRAGS;
968         VNET_LIST_RLOCK_NOSLEEP();
969         VNET_FOREACH(vnet_iter) {
970                 CURVNET_SET(vnet_iter);
971                 V_ip6_maxfragpackets = IP6_MAXFRAGPACKETS;
972                 frag6_set_bucketsize();
973                 CURVNET_RESTORE();
974         }
975         VNET_LIST_RUNLOCK_NOSLEEP();
976 }
977
978 /*
979  * Initialise reassembly queue and fragment identifier.
980  */
981 void
982 frag6_init(void)
983 {
984         uint32_t bucket;
985
986         V_ip6_maxfragpackets = IP6_MAXFRAGPACKETS;
987         frag6_set_bucketsize();
988         for (bucket = 0; bucket < IP6REASS_NHASH; bucket++) {
989                 TAILQ_INIT(IP6QB_HEAD(bucket));
990                 mtx_init(&V_ip6qb[bucket].lock, "ip6qb", NULL, MTX_DEF);
991                 V_ip6qb[bucket].count = 0;
992         }
993         V_ip6qb_hashseed = arc4random();
994         V_ip6_maxfragsperpacket = 64;
995 #ifdef VIMAGE
996         V_frag6_on = true;
997 #endif
998         if (!IS_DEFAULT_VNET(curvnet))
999                 return;
1000
1001         ip6_maxfrags = IP6_MAXFRAGS;
1002         EVENTHANDLER_REGISTER(nmbclusters_change,
1003             frag6_change, NULL, EVENTHANDLER_PRI_ANY);
1004 }
1005
1006 /*
1007  * Drain off all datagram fragments.
1008  */
1009 static void
1010 frag6_drain_one(void)
1011 {
1012         struct ip6q *q6;
1013         uint32_t bucket;
1014
1015         for (bucket = 0; bucket < IP6REASS_NHASH; bucket++) {
1016                 IP6QB_LOCK(bucket);
1017                 while ((q6 = TAILQ_FIRST(IP6QB_HEAD(bucket))) != NULL) {
1018                         IP6STAT_INC(ip6s_fragdropped);
1019                         /* XXX in6_ifstat_inc(ifp, ifs6_reass_fail) */
1020                         frag6_freef(q6, bucket);
1021                 }
1022                 IP6QB_UNLOCK(bucket);
1023         }
1024 }
1025
1026 void
1027 frag6_drain(void)
1028 {
1029         VNET_ITERATOR_DECL(vnet_iter);
1030
1031         VNET_LIST_RLOCK_NOSLEEP();
1032         VNET_FOREACH(vnet_iter) {
1033                 CURVNET_SET(vnet_iter);
1034                 frag6_drain_one();
1035                 CURVNET_RESTORE();
1036         }
1037         VNET_LIST_RUNLOCK_NOSLEEP();
1038 }
1039
1040 #ifdef VIMAGE
1041 /*
1042  * Clear up IPv6 reassembly structures.
1043  */
1044 void
1045 frag6_destroy(void)
1046 {
1047         uint32_t bucket;
1048
1049         frag6_drain_one();
1050         V_frag6_on = false;
1051         for (bucket = 0; bucket < IP6REASS_NHASH; bucket++) {
1052                 KASSERT(V_ip6qb[bucket].count == 0,
1053                     ("%s: V_ip6qb[%d] (%p) count not 0 (%d)", __func__,
1054                     bucket, &V_ip6qb[bucket], V_ip6qb[bucket].count));
1055                 mtx_destroy(&V_ip6qb[bucket].lock);
1056         }
1057 }
1058 #endif