* Set up a bind operation on a PCB, performing port allocation * as required, but do not actually modify the PCB. Callers can * either complete the bind by setting inp_laddr/inp_lport and * calling in_pcbinshash(), or they can just use the resulting * port and address to authorise the sending of a once-off packet. * * On error, the values of *laddrp and *lportp are not changed. */
| 998 | * On error, the values of *laddrp and *lportp are not changed. |
| 999 | */ |
| 1000 | int |
| 1001 | in_pcbbind_setup(struct inpcb *inp, struct sockaddr *nam, in_addr_t *laddrp, |
| 1002 | u_short *lportp, struct ucred *cred) |
| 1003 | { |
| 1004 | struct socket *so = inp->inp_socket; |
| 1005 | struct sockaddr_in *sin; |
| 1006 | struct inpcbinfo *pcbinfo = inp->inp_pcbinfo; |
| 1007 | struct in_addr laddr; |
| 1008 | u_short lport = 0; |
| 1009 | int lookupflags = 0, reuseport = (so->so_options & SO_REUSEPORT); |
| 1010 | int error; |
| 1011 | |
| 1012 | /* |
| 1013 | * XXX: Maybe we could let SO_REUSEPORT_LB set SO_REUSEPORT bit here |
| 1014 | * so that we don't have to add to the (already messy) code below. |
| 1015 | */ |
| 1016 | int reuseport_lb = (so->so_options & SO_REUSEPORT_LB); |
| 1017 | |
| 1018 | /* |
| 1019 | * No state changes, so read locks are sufficient here. |
| 1020 | */ |
| 1021 | INP_LOCK_ASSERT(inp); |
| 1022 | INP_HASH_LOCK_ASSERT(pcbinfo); |
| 1023 | |
| 1024 | if (CK_STAILQ_EMPTY(&V_in_ifaddrhead)) /* XXX broken! */ |
| 1025 | return (EADDRNOTAVAIL); |
| 1026 | laddr.s_addr = *laddrp; |
| 1027 | if (nam != NULL && laddr.s_addr != INADDR_ANY) |
| 1028 | return (EINVAL); |
| 1029 | if ((so->so_options & (SO_REUSEADDR|SO_REUSEPORT|SO_REUSEPORT_LB)) == 0) |
| 1030 | lookupflags = INPLOOKUP_WILDCARD; |
| 1031 | if (nam == NULL) { |
| 1032 | if ((error = prison_local_ip4(cred, &laddr)) != 0) |
| 1033 | return (error); |
| 1034 | } else { |
| 1035 | sin = (struct sockaddr_in *)nam; |
| 1036 | if (nam->sa_len != sizeof (*sin)) |
| 1037 | return (EINVAL); |
| 1038 | #ifdef notdef |
| 1039 | /* |
| 1040 | * We should check the family, but old programs |
| 1041 | * incorrectly fail to initialize it. |
| 1042 | */ |
| 1043 | if (sin->sin_family != AF_INET) |
| 1044 | return (EAFNOSUPPORT); |
| 1045 | #endif |
| 1046 | error = prison_local_ip4(cred, &sin->sin_addr); |
| 1047 | if (error) |
| 1048 | return (error); |
| 1049 | if (sin->sin_port != *lportp) { |
| 1050 | /* Don't allow the port to change. */ |
| 1051 | if (*lportp != 0) |
| 1052 | return (EINVAL); |
| 1053 | lport = sin->sin_port; |
| 1054 | } |
| 1055 | /* NB: lport is left as 0 if the port isn't being changed. */ |
| 1056 | if (IN_MULTICAST(ntohl(sin->sin_addr.s_addr))) { |
| 1057 | /* |
no test coverage detected