| 243 | } |
| 244 | |
| 245 | void |
| 246 | udp_ipsec_adjust_cksum(struct mbuf *m, struct secasvar *sav, int proto, |
| 247 | int skip) |
| 248 | { |
| 249 | struct ip *ip; |
| 250 | uint16_t cksum, off; |
| 251 | |
| 252 | IPSEC_ASSERT(sav->natt != NULL, ("NAT-T isn't required")); |
| 253 | IPSEC_ASSERT(proto == IPPROTO_UDP || proto == IPPROTO_TCP, |
| 254 | ("unexpected protocol %u", proto)); |
| 255 | |
| 256 | if (proto == IPPROTO_UDP) |
| 257 | off = offsetof(struct udphdr, uh_sum); |
| 258 | else |
| 259 | off = offsetof(struct tcphdr, th_sum); |
| 260 | |
| 261 | if (V_natt_cksum_policy == 0) { /* auto */ |
| 262 | if (sav->natt->cksum != 0) { |
| 263 | /* Incrementally recompute. */ |
| 264 | m_copydata(m, skip + off, sizeof(cksum), |
| 265 | (caddr_t)&cksum); |
| 266 | /* Do not adjust UDP checksum if it is zero. */ |
| 267 | if (proto == IPPROTO_UDP && cksum == 0) |
| 268 | return; |
| 269 | cksum = in_addword(cksum, sav->natt->cksum); |
| 270 | } else { |
| 271 | /* No OA from IKEd. */ |
| 272 | if (proto == IPPROTO_TCP) { |
| 273 | /* Ignore for TCP. */ |
| 274 | m->m_pkthdr.csum_data = 0xffff; |
| 275 | m->m_pkthdr.csum_flags |= (CSUM_DATA_VALID | |
| 276 | CSUM_PSEUDO_HDR); |
| 277 | return; |
| 278 | } |
| 279 | cksum = 0; /* Reset for UDP. */ |
| 280 | } |
| 281 | m_copyback(m, skip + off, sizeof(cksum), (caddr_t)&cksum); |
| 282 | } else { /* Fully recompute */ |
| 283 | ip = mtod(m, struct ip *); |
| 284 | cksum = in_pseudo(ip->ip_src.s_addr, ip->ip_dst.s_addr, |
| 285 | htons(m->m_pkthdr.len - skip + proto)); |
| 286 | m_copyback(m, skip + off, sizeof(cksum), (caddr_t)&cksum); |
| 287 | m->m_pkthdr.csum_flags = |
| 288 | (proto == IPPROTO_UDP) ? CSUM_UDP: CSUM_TCP; |
| 289 | m->m_pkthdr.csum_data = off; |
| 290 | in_delayed_cksum(m); |
| 291 | m->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA; |
| 292 | } |
| 293 | } |
no test coverage detected