| 304 | |
| 305 | #ifdef INET |
| 306 | static int |
| 307 | checksum_ipv4(priv_p priv, struct mbuf *m, int l3_offset) |
| 308 | { |
| 309 | struct ip *ip4; |
| 310 | int pullup_len; |
| 311 | int hlen, plen; |
| 312 | int processed = 0; |
| 313 | |
| 314 | pullup_len = l3_offset; |
| 315 | |
| 316 | PULLUP_CHECK(m, sizeof(struct ip)); |
| 317 | ip4 = (struct ip *) mtodo(m, l3_offset); |
| 318 | |
| 319 | if (ip4->ip_v != IPVERSION) |
| 320 | return (EOPNOTSUPP); |
| 321 | |
| 322 | hlen = ip4->ip_hl << 2; |
| 323 | plen = ntohs(ip4->ip_len); |
| 324 | |
| 325 | if (hlen < sizeof(struct ip) || m->m_pkthdr.len < l3_offset + plen) |
| 326 | return (EINVAL); |
| 327 | |
| 328 | if (m->m_pkthdr.csum_flags & CSUM_IP) { |
| 329 | ip4->ip_sum = 0; |
| 330 | |
| 331 | if ((priv->conf->csum_offload & CSUM_IP) == 0) { |
| 332 | if (hlen == sizeof(struct ip)) |
| 333 | ip4->ip_sum = in_cksum_hdr(ip4); |
| 334 | else |
| 335 | ip4->ip_sum = in_cksum_skip(m, l3_offset + hlen, l3_offset); |
| 336 | |
| 337 | m->m_pkthdr.csum_flags &= ~CSUM_IP; |
| 338 | } |
| 339 | |
| 340 | processed = 1; |
| 341 | } |
| 342 | |
| 343 | pullup_len = l3_offset + hlen; |
| 344 | |
| 345 | /* We can not calculate a checksum fragmented packets */ |
| 346 | if (ip4->ip_off & htons(IP_MF|IP_OFFMASK)) { |
| 347 | m->m_pkthdr.csum_flags &= ~(CSUM_TCP|CSUM_UDP); |
| 348 | return (0); |
| 349 | } |
| 350 | |
| 351 | switch (ip4->ip_p) |
| 352 | { |
| 353 | case IPPROTO_TCP: |
| 354 | if (m->m_pkthdr.csum_flags & CSUM_TCP) { |
| 355 | struct tcphdr *th; |
| 356 | |
| 357 | PULLUP_CHECK(m, sizeof(struct tcphdr)); |
| 358 | th = (struct tcphdr *) mtodo(m, l3_offset + hlen); |
| 359 | |
| 360 | th->th_sum = in_pseudo(ip4->ip_src.s_addr, |
| 361 | ip4->ip_dst.s_addr, htons(ip4->ip_p + plen - hlen)); |
| 362 | |
| 363 | if ((priv->conf->csum_offload & CSUM_TCP) == 0) { |
no test coverage detected