* Set up for a connect from a socket to the specified address. * On entry, *laddrp and *lportp should contain the current local * address and port for the PCB; these are updated to the values * that should be placed in inp_laddr and inp_lport to complete * the connect. * * On success, *faddrp and *fportp will be set to the remote address * and port. These are not updated in the error case.
| 1455 | * is set to NULL. |
| 1456 | */ |
| 1457 | int |
| 1458 | in_pcbconnect_setup(struct inpcb *inp, struct sockaddr *nam, |
| 1459 | in_addr_t *laddrp, u_short *lportp, in_addr_t *faddrp, u_short *fportp, |
| 1460 | struct inpcb **oinpp, struct ucred *cred) |
| 1461 | { |
| 1462 | struct rm_priotracker in_ifa_tracker; |
| 1463 | struct sockaddr_in *sin = (struct sockaddr_in *)nam; |
| 1464 | struct in_ifaddr *ia; |
| 1465 | struct inpcb *oinp; |
| 1466 | struct in_addr laddr, faddr; |
| 1467 | u_short lport, fport; |
| 1468 | int error; |
| 1469 | |
| 1470 | /* |
| 1471 | * Because a global state change doesn't actually occur here, a read |
| 1472 | * lock is sufficient. |
| 1473 | */ |
| 1474 | NET_EPOCH_ASSERT(); |
| 1475 | INP_LOCK_ASSERT(inp); |
| 1476 | INP_HASH_LOCK_ASSERT(inp->inp_pcbinfo); |
| 1477 | |
| 1478 | if (oinpp != NULL) |
| 1479 | *oinpp = NULL; |
| 1480 | if (nam->sa_len != sizeof (*sin)) |
| 1481 | return (EINVAL); |
| 1482 | if (sin->sin_family != AF_INET) |
| 1483 | return (EAFNOSUPPORT); |
| 1484 | if (sin->sin_port == 0) |
| 1485 | return (EADDRNOTAVAIL); |
| 1486 | laddr.s_addr = *laddrp; |
| 1487 | lport = *lportp; |
| 1488 | faddr = sin->sin_addr; |
| 1489 | fport = sin->sin_port; |
| 1490 | #ifdef ROUTE_MPATH |
| 1491 | if (CALC_FLOWID_OUTBOUND) { |
| 1492 | uint32_t hash_val, hash_type; |
| 1493 | |
| 1494 | hash_val = fib4_calc_software_hash(laddr, faddr, 0, fport, |
| 1495 | inp->inp_socket->so_proto->pr_protocol, &hash_type); |
| 1496 | |
| 1497 | inp->inp_flowid = hash_val; |
| 1498 | inp->inp_flowtype = hash_type; |
| 1499 | } |
| 1500 | #endif |
| 1501 | if (!CK_STAILQ_EMPTY(&V_in_ifaddrhead)) { |
| 1502 | /* |
| 1503 | * If the destination address is INADDR_ANY, |
| 1504 | * use the primary local address. |
| 1505 | * If the supplied address is INADDR_BROADCAST, |
| 1506 | * and the primary interface supports broadcast, |
| 1507 | * choose the broadcast address for that interface. |
| 1508 | */ |
| 1509 | if (faddr.s_addr == INADDR_ANY) { |
| 1510 | IN_IFADDR_RLOCK(&in_ifa_tracker); |
| 1511 | faddr = |
| 1512 | IA_SIN(CK_STAILQ_FIRST(&V_in_ifaddrhead))->sin_addr; |
| 1513 | IN_IFADDR_RUNLOCK(&in_ifa_tracker); |
| 1514 | if (cred != NULL && |
no test coverage detected