| 180 | */ |
| 181 | #define M_IP_FRAG M_PROTO9 |
| 182 | struct mbuf * |
| 183 | ip_reass(struct mbuf *m) |
| 184 | { |
| 185 | struct ip *ip; |
| 186 | struct mbuf *p, *q, *nq, *t; |
| 187 | struct ipq *fp; |
| 188 | struct ifnet *srcifp; |
| 189 | struct ipqhead *head; |
| 190 | int i, hlen, next, tmpmax; |
| 191 | u_int8_t ecn, ecn0; |
| 192 | uint32_t hash, hashkey[3]; |
| 193 | #ifdef RSS |
| 194 | uint32_t rss_hash, rss_type; |
| 195 | #endif |
| 196 | |
| 197 | /* |
| 198 | * If no reassembling or maxfragsperpacket are 0, |
| 199 | * never accept fragments. |
| 200 | * Also, drop packet if it would exceed the maximum |
| 201 | * number of fragments. |
| 202 | */ |
| 203 | tmpmax = maxfrags; |
| 204 | if (V_noreass == 1 || V_maxfragsperpacket == 0 || |
| 205 | (tmpmax >= 0 && atomic_load_int(&nfrags) >= (u_int)tmpmax)) { |
| 206 | IPSTAT_INC(ips_fragments); |
| 207 | IPSTAT_INC(ips_fragdropped); |
| 208 | m_freem(m); |
| 209 | return (NULL); |
| 210 | } |
| 211 | |
| 212 | ip = mtod(m, struct ip *); |
| 213 | hlen = ip->ip_hl << 2; |
| 214 | |
| 215 | /* |
| 216 | * Adjust ip_len to not reflect header, |
| 217 | * convert offset of this to bytes. |
| 218 | */ |
| 219 | ip->ip_len = htons(ntohs(ip->ip_len) - hlen); |
| 220 | /* |
| 221 | * Make sure that fragments have a data length |
| 222 | * that's a non-zero multiple of 8 bytes, unless |
| 223 | * this is the last fragment. |
| 224 | */ |
| 225 | if (ip->ip_len == htons(0) || |
| 226 | ((ip->ip_off & htons(IP_MF)) && (ntohs(ip->ip_len) & 0x7) != 0)) { |
| 227 | IPSTAT_INC(ips_toosmall); /* XXX */ |
| 228 | IPSTAT_INC(ips_fragdropped); |
| 229 | m_freem(m); |
| 230 | return (NULL); |
| 231 | } |
| 232 | if (ip->ip_off & htons(IP_MF)) |
| 233 | m->m_flags |= M_IP_FRAG; |
| 234 | else |
| 235 | m->m_flags &= ~M_IP_FRAG; |
| 236 | ip->ip_off = htons(ntohs(ip->ip_off) << 3); |
| 237 | |
| 238 | /* |
| 239 | * Make sure the fragment lies within a packet of valid size. |
no test coverage detected