* allocating a usable SA entry for a *INBOUND* packet. * Must call key_freesav() later. * OUT: positive: pointer to a usable sav (i.e. MATURE or DYING state). * NULL: not found, or error occurred. * * According to RFC 2401 SA is uniquely identified by a triple SPI, * destination address, and security protocol. But according to RFC 4301, * SPI by itself suffices to specify an SA. * * Note
| 1089 | * keep source address in IPsec SA. We see a tricky situation here. |
| 1090 | */ |
| 1091 | struct secasvar * |
| 1092 | key_allocsa(union sockaddr_union *dst, uint8_t proto, uint32_t spi) |
| 1093 | { |
| 1094 | SAHTREE_RLOCK_TRACKER; |
| 1095 | struct secasvar *sav; |
| 1096 | |
| 1097 | IPSEC_ASSERT(proto == IPPROTO_ESP || proto == IPPROTO_AH || |
| 1098 | proto == IPPROTO_IPCOMP, ("unexpected security protocol %u", |
| 1099 | proto)); |
| 1100 | |
| 1101 | SAHTREE_RLOCK(); |
| 1102 | LIST_FOREACH(sav, SAVHASH_HASH(spi), spihash) { |
| 1103 | if (sav->spi == spi) |
| 1104 | break; |
| 1105 | } |
| 1106 | /* |
| 1107 | * We use single SPI namespace for all protocols, so it is |
| 1108 | * impossible to have SPI duplicates in the SAVHASH. |
| 1109 | */ |
| 1110 | if (sav != NULL) { |
| 1111 | if (sav->state != SADB_SASTATE_LARVAL && |
| 1112 | sav->sah->saidx.proto == proto && |
| 1113 | key_sockaddrcmp(&dst->sa, |
| 1114 | &sav->sah->saidx.dst.sa, 0) == 0) |
| 1115 | SAV_ADDREF(sav); |
| 1116 | else |
| 1117 | sav = NULL; |
| 1118 | } |
| 1119 | SAHTREE_RUNLOCK(); |
| 1120 | |
| 1121 | if (sav == NULL) { |
| 1122 | KEYDBG(IPSEC_STAMP, |
| 1123 | char buf[IPSEC_ADDRSTRLEN]; |
| 1124 | printf("%s: SA not found for spi %u proto %u dst %s\n", |
| 1125 | __func__, ntohl(spi), proto, ipsec_address(dst, buf, |
| 1126 | sizeof(buf)))); |
| 1127 | } else { |
| 1128 | KEYDBG(IPSEC_STAMP, |
| 1129 | printf("%s: return SA(%p)\n", __func__, sav)); |
| 1130 | KEYDBG(IPSEC_DATA, kdebug_secasv(sav)); |
| 1131 | } |
| 1132 | return (sav); |
| 1133 | } |
| 1134 | |
| 1135 | struct secasvar * |
| 1136 | key_allocsa_tunnel(union sockaddr_union *src, union sockaddr_union *dst, |
no test coverage detected