| 107 | |
| 108 | #ifdef INET |
| 109 | static struct secasvar * |
| 110 | ipsec4_allocsa(struct mbuf *m, struct secpolicy *sp, u_int *pidx, int *error) |
| 111 | { |
| 112 | struct secasindex *saidx, tmpsaidx; |
| 113 | struct ipsecrequest *isr; |
| 114 | struct sockaddr_in *sin; |
| 115 | struct secasvar *sav; |
| 116 | struct ip *ip; |
| 117 | |
| 118 | /* |
| 119 | * Check system global policy controls. |
| 120 | */ |
| 121 | next: |
| 122 | isr = sp->req[*pidx]; |
| 123 | if ((isr->saidx.proto == IPPROTO_ESP && !V_esp_enable) || |
| 124 | (isr->saidx.proto == IPPROTO_AH && !V_ah_enable) || |
| 125 | (isr->saidx.proto == IPPROTO_IPCOMP && !V_ipcomp_enable)) { |
| 126 | DPRINTF(("%s: IPsec outbound packet dropped due" |
| 127 | " to policy (check your sysctls)\n", __func__)); |
| 128 | IPSEC_OSTAT_INC(isr->saidx.proto, pdrops); |
| 129 | *error = EHOSTUNREACH; |
| 130 | return (NULL); |
| 131 | } |
| 132 | /* |
| 133 | * Craft SA index to search for proper SA. Note that |
| 134 | * we only initialize unspecified SA peers for transport |
| 135 | * mode; for tunnel mode they must already be filled in. |
| 136 | */ |
| 137 | if (isr->saidx.mode == IPSEC_MODE_TRANSPORT) { |
| 138 | saidx = &tmpsaidx; |
| 139 | *saidx = isr->saidx; |
| 140 | ip = mtod(m, struct ip *); |
| 141 | if (saidx->src.sa.sa_len == 0) { |
| 142 | sin = &saidx->src.sin; |
| 143 | sin->sin_len = sizeof(*sin); |
| 144 | sin->sin_family = AF_INET; |
| 145 | sin->sin_port = IPSEC_PORT_ANY; |
| 146 | sin->sin_addr = ip->ip_src; |
| 147 | } |
| 148 | if (saidx->dst.sa.sa_len == 0) { |
| 149 | sin = &saidx->dst.sin; |
| 150 | sin->sin_len = sizeof(*sin); |
| 151 | sin->sin_family = AF_INET; |
| 152 | sin->sin_port = IPSEC_PORT_ANY; |
| 153 | sin->sin_addr = ip->ip_dst; |
| 154 | } |
| 155 | } else |
| 156 | saidx = &sp->req[*pidx]->saidx; |
| 157 | /* |
| 158 | * Lookup SA and validate it. |
| 159 | */ |
| 160 | sav = key_allocsa_policy(sp, saidx, error); |
| 161 | if (sav == NULL) { |
| 162 | IPSECSTAT_INC(ips_out_nosa); |
| 163 | if (*error != 0) |
| 164 | return (NULL); |
| 165 | if (ipsec_get_reqlevel(sp, *pidx) != IPSEC_LEVEL_REQUIRE) { |
| 166 | /* |
no test coverage detected