* Make sure our (source) address is set to something meaningful to this * jail. * * Returns 0 if jail doesn't restrict IPv4 or if address belongs to jail, * EADDRNOTAVAIL if the address doesn't belong, or EAFNOSUPPORT if the jail * doesn't allow IPv4. Address passed in in NBO and returned in NBO. */
| 282 | * doesn't allow IPv4. Address passed in in NBO and returned in NBO. |
| 283 | */ |
| 284 | int |
| 285 | prison_local_ip4(struct ucred *cred, struct in_addr *ia) |
| 286 | { |
| 287 | struct prison *pr; |
| 288 | struct in_addr ia0; |
| 289 | int error; |
| 290 | |
| 291 | KASSERT(cred != NULL, ("%s: cred is NULL", __func__)); |
| 292 | KASSERT(ia != NULL, ("%s: ia is NULL", __func__)); |
| 293 | |
| 294 | pr = cred->cr_prison; |
| 295 | if (!(pr->pr_flags & PR_IP4)) |
| 296 | return (0); |
| 297 | mtx_lock(&pr->pr_mtx); |
| 298 | if (!(pr->pr_flags & PR_IP4)) { |
| 299 | mtx_unlock(&pr->pr_mtx); |
| 300 | return (0); |
| 301 | } |
| 302 | if (pr->pr_ip4 == NULL) { |
| 303 | mtx_unlock(&pr->pr_mtx); |
| 304 | return (EAFNOSUPPORT); |
| 305 | } |
| 306 | |
| 307 | ia0.s_addr = ntohl(ia->s_addr); |
| 308 | |
| 309 | if (ia0.s_addr == INADDR_ANY) { |
| 310 | /* |
| 311 | * In case there is only 1 IPv4 address, bind directly. |
| 312 | */ |
| 313 | if (pr->pr_ip4s == 1) |
| 314 | ia->s_addr = pr->pr_ip4[0].s_addr; |
| 315 | mtx_unlock(&pr->pr_mtx); |
| 316 | return (0); |
| 317 | } |
| 318 | |
| 319 | error = prison_check_ip4_locked(pr, ia); |
| 320 | if (error == EADDRNOTAVAIL && ia0.s_addr == INADDR_LOOPBACK) { |
| 321 | ia->s_addr = pr->pr_ip4[0].s_addr; |
| 322 | error = 0; |
| 323 | } |
| 324 | |
| 325 | mtx_unlock(&pr->pr_mtx); |
| 326 | return (error); |
| 327 | } |
| 328 | |
| 329 | /* |
| 330 | * Rewrite destination address in case we will connect to loopback address. |
no test coverage detected