* IPsec output logic for IPv4. */
| 183 | * IPsec output logic for IPv4. |
| 184 | */ |
| 185 | static int |
| 186 | ipsec4_perform_request(struct mbuf *m, struct secpolicy *sp, |
| 187 | struct inpcb *inp, u_int idx) |
| 188 | { |
| 189 | struct ipsec_ctx_data ctx; |
| 190 | union sockaddr_union *dst; |
| 191 | struct secasvar *sav; |
| 192 | struct ip *ip; |
| 193 | int error, i, off; |
| 194 | |
| 195 | IPSEC_ASSERT(idx < sp->tcount, ("Wrong IPsec request index %d", idx)); |
| 196 | |
| 197 | /* |
| 198 | * We hold the reference to SP. Content of SP couldn't be changed. |
| 199 | * Craft secasindex and do lookup for suitable SA. |
| 200 | * Then do encapsulation if needed and call xform's output. |
| 201 | * We need to store SP in the xform callback parameters. |
| 202 | * In xform callback we will extract SP and it can be used to |
| 203 | * determine next transform. At the end of transform we can |
| 204 | * release reference to SP. |
| 205 | */ |
| 206 | sav = ipsec4_allocsa(m, sp, &idx, &error); |
| 207 | if (sav == NULL) { |
| 208 | if (error == EJUSTRETURN) { /* No IPsec required */ |
| 209 | key_freesp(&sp); |
| 210 | return (error); |
| 211 | } |
| 212 | goto bad; |
| 213 | } |
| 214 | /* |
| 215 | * XXXAE: most likely ip_sum at this point is wrong. |
| 216 | */ |
| 217 | IPSEC_INIT_CTX(&ctx, &m, inp, sav, AF_INET, IPSEC_ENC_BEFORE); |
| 218 | if ((error = ipsec_run_hhooks(&ctx, HHOOK_TYPE_IPSEC_OUT)) != 0) |
| 219 | goto bad; |
| 220 | |
| 221 | ip = mtod(m, struct ip *); |
| 222 | dst = &sav->sah->saidx.dst; |
| 223 | /* Do the appropriate encapsulation, if necessary */ |
| 224 | if (sp->req[idx]->saidx.mode == IPSEC_MODE_TUNNEL || /* Tunnel requ'd */ |
| 225 | dst->sa.sa_family != AF_INET || /* PF mismatch */ |
| 226 | (dst->sa.sa_family == AF_INET && /* Proxy */ |
| 227 | dst->sin.sin_addr.s_addr != INADDR_ANY && |
| 228 | dst->sin.sin_addr.s_addr != ip->ip_dst.s_addr)) { |
| 229 | /* Fix IPv4 header checksum and length */ |
| 230 | ip->ip_len = htons(m->m_pkthdr.len); |
| 231 | ip->ip_sum = 0; |
| 232 | ip->ip_sum = in_cksum(m, ip->ip_hl << 2); |
| 233 | error = ipsec_encap(&m, &sav->sah->saidx); |
| 234 | if (error != 0) { |
| 235 | DPRINTF(("%s: encapsulation for SPI 0x%08x failed " |
| 236 | "with error %d\n", __func__, ntohl(sav->spi), |
| 237 | error)); |
| 238 | /* XXXAE: IPSEC_OSTAT_INC(tunnel); */ |
| 239 | goto bad; |
| 240 | } |
| 241 | inp = NULL; |
| 242 | } |
no test coverage detected