| 329 | } |
| 330 | |
| 331 | static void |
| 332 | ipsec_cachepolicy(struct inpcb *inp, struct secpolicy *sp, u_int dir) |
| 333 | { |
| 334 | uint32_t genid; |
| 335 | int downgrade; |
| 336 | |
| 337 | INP_LOCK_ASSERT(inp); |
| 338 | |
| 339 | if (dir == IPSEC_DIR_OUTBOUND) { |
| 340 | /* Do we have configured PCB policy? */ |
| 341 | if (inp->inp_sp->flags & INP_OUTBOUND_POLICY) |
| 342 | return; |
| 343 | /* Another thread has already set cached policy */ |
| 344 | if (inp->inp_sp->sp_out != NULL) |
| 345 | return; |
| 346 | /* |
| 347 | * Do not cache OUTBOUND policy if PCB isn't connected, |
| 348 | * i.e. foreign address is INADDR_ANY/UNSPECIFIED. |
| 349 | */ |
| 350 | #ifdef INET |
| 351 | if ((inp->inp_vflag & INP_IPV4) != 0 && |
| 352 | inp->inp_faddr.s_addr == INADDR_ANY) |
| 353 | return; |
| 354 | #endif |
| 355 | #ifdef INET6 |
| 356 | if ((inp->inp_vflag & INP_IPV6) != 0 && |
| 357 | IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_faddr)) |
| 358 | return; |
| 359 | #endif |
| 360 | } else { |
| 361 | /* Do we have configured PCB policy? */ |
| 362 | if (inp->inp_sp->flags & INP_INBOUND_POLICY) |
| 363 | return; |
| 364 | /* Another thread has already set cached policy */ |
| 365 | if (inp->inp_sp->sp_in != NULL) |
| 366 | return; |
| 367 | /* |
| 368 | * Do not cache INBOUND policy for listen socket, |
| 369 | * that is bound to INADDR_ANY/UNSPECIFIED address. |
| 370 | */ |
| 371 | #ifdef INET |
| 372 | if ((inp->inp_vflag & INP_IPV4) != 0 && |
| 373 | inp->inp_faddr.s_addr == INADDR_ANY) |
| 374 | return; |
| 375 | #endif |
| 376 | #ifdef INET6 |
| 377 | if ((inp->inp_vflag & INP_IPV6) != 0 && |
| 378 | IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_faddr)) |
| 379 | return; |
| 380 | #endif |
| 381 | } |
| 382 | downgrade = 0; |
| 383 | if (!INP_WLOCKED(inp)) { |
| 384 | if ((downgrade = INP_TRY_UPGRADE(inp)) == 0) |
| 385 | return; |
| 386 | } |
| 387 | if (dir == IPSEC_DIR_OUTBOUND) |
| 388 | inp->inp_sp->sp_out = sp; |
no test coverage detected