* Like in RFC2460, in RFC8200, fragment and reassembly rules do not agree with * each other, in terms of next header field handling in fragment header. * While the sender will use the same value for all of the fragmented packets, * receiver is suggested not to check for consistency. * * Fragment rules (p18,p19): * (2) A Fragment header containing: * The Next Header value that identifies th
| 357 | * Fragment input. |
| 358 | */ |
| 359 | int |
| 360 | frag6_input(struct mbuf **mp, int *offp, int proto) |
| 361 | { |
| 362 | struct mbuf *m, *t; |
| 363 | struct ip6_hdr *ip6; |
| 364 | struct ip6_frag *ip6f; |
| 365 | struct ip6qhead *head; |
| 366 | struct ip6q *q6; |
| 367 | struct ip6asfrag *af6, *ip6af, *af6tmp; |
| 368 | struct in6_ifaddr *ia6; |
| 369 | struct ifnet *dstifp, *srcifp; |
| 370 | uint32_t hashkey[(sizeof(struct in6_addr) * 2 + |
| 371 | sizeof(ip6f->ip6f_ident)) / sizeof(uint32_t)]; |
| 372 | uint32_t bucket, *hashkeyp; |
| 373 | int fragoff, frgpartlen; /* Must be larger than uint16_t. */ |
| 374 | int nxt, offset, plen; |
| 375 | uint8_t ecn, ecn0; |
| 376 | bool only_frag; |
| 377 | #ifdef RSS |
| 378 | struct ip6_direct_ctx *ip6dc; |
| 379 | struct m_tag *mtag; |
| 380 | #endif |
| 381 | |
| 382 | m = *mp; |
| 383 | offset = *offp; |
| 384 | |
| 385 | M_ASSERTPKTHDR(m); |
| 386 | |
| 387 | if (m->m_len < offset + sizeof(struct ip6_frag)) { |
| 388 | m = m_pullup(m, offset + sizeof(struct ip6_frag)); |
| 389 | if (m == NULL) { |
| 390 | IP6STAT_INC(ip6s_exthdrtoolong); |
| 391 | *mp = NULL; |
| 392 | return (IPPROTO_DONE); |
| 393 | } |
| 394 | } |
| 395 | ip6 = mtod(m, struct ip6_hdr *); |
| 396 | |
| 397 | dstifp = NULL; |
| 398 | /* Find the destination interface of the packet. */ |
| 399 | ia6 = in6ifa_ifwithaddr(&ip6->ip6_dst, 0 /* XXX */); |
| 400 | if (ia6 != NULL) { |
| 401 | dstifp = ia6->ia_ifp; |
| 402 | ifa_free(&ia6->ia_ifa); |
| 403 | } |
| 404 | |
| 405 | /* Jumbo payload cannot contain a fragment header. */ |
| 406 | if (ip6->ip6_plen == 0) { |
| 407 | icmp6_error(m, ICMP6_PARAM_PROB, ICMP6_PARAMPROB_HEADER, offset); |
| 408 | in6_ifstat_inc(dstifp, ifs6_reass_fail); |
| 409 | *mp = NULL; |
| 410 | return (IPPROTO_DONE); |
| 411 | } |
| 412 | |
| 413 | /* |
| 414 | * Check whether fragment packet's fragment length is a |
| 415 | * multiple of 8 octets (unless it is the last one). |
| 416 | * sizeof(struct ip6_frag) == 8 |
no test coverage detected