| 115 | #include <netinet6/scope6_var.h> |
| 116 | |
| 117 | int |
| 118 | in6_pcbbind(struct inpcb *inp, struct sockaddr *nam, |
| 119 | struct ucred *cred) |
| 120 | { |
| 121 | struct socket *so = inp->inp_socket; |
| 122 | struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)NULL; |
| 123 | struct inpcbinfo *pcbinfo = inp->inp_pcbinfo; |
| 124 | u_short lport = 0; |
| 125 | int error, lookupflags = 0; |
| 126 | int reuseport = (so->so_options & SO_REUSEPORT); |
| 127 | |
| 128 | /* |
| 129 | * XXX: Maybe we could let SO_REUSEPORT_LB set SO_REUSEPORT bit here |
| 130 | * so that we don't have to add to the (already messy) code below. |
| 131 | */ |
| 132 | int reuseport_lb = (so->so_options & SO_REUSEPORT_LB); |
| 133 | |
| 134 | INP_WLOCK_ASSERT(inp); |
| 135 | INP_HASH_WLOCK_ASSERT(pcbinfo); |
| 136 | |
| 137 | if (CK_STAILQ_EMPTY(&V_in6_ifaddrhead)) /* XXX broken! */ |
| 138 | return (EADDRNOTAVAIL); |
| 139 | if (inp->inp_lport || !IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr)) |
| 140 | return (EINVAL); |
| 141 | if ((so->so_options & (SO_REUSEADDR|SO_REUSEPORT|SO_REUSEPORT_LB)) == 0) |
| 142 | lookupflags = INPLOOKUP_WILDCARD; |
| 143 | if (nam == NULL) { |
| 144 | if ((error = prison_local_ip6(cred, &inp->in6p_laddr, |
| 145 | ((inp->inp_flags & IN6P_IPV6_V6ONLY) != 0))) != 0) |
| 146 | return (error); |
| 147 | } else { |
| 148 | sin6 = (struct sockaddr_in6 *)nam; |
| 149 | if (nam->sa_len != sizeof(*sin6)) |
| 150 | return (EINVAL); |
| 151 | /* |
| 152 | * family check. |
| 153 | */ |
| 154 | if (nam->sa_family != AF_INET6) |
| 155 | return (EAFNOSUPPORT); |
| 156 | |
| 157 | if ((error = sa6_embedscope(sin6, V_ip6_use_defzone)) != 0) |
| 158 | return(error); |
| 159 | |
| 160 | if ((error = prison_local_ip6(cred, &sin6->sin6_addr, |
| 161 | ((inp->inp_flags & IN6P_IPV6_V6ONLY) != 0))) != 0) |
| 162 | return (error); |
| 163 | |
| 164 | lport = sin6->sin6_port; |
| 165 | if (IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) { |
| 166 | /* |
| 167 | * Treat SO_REUSEADDR as SO_REUSEPORT for multicast; |
| 168 | * allow compepte duplication of binding if |
| 169 | * SO_REUSEPORT is set, or if SO_REUSEADDR is set |
| 170 | * and a multicast address is bound on both |
| 171 | * new and duplicated sockets. |
| 172 | */ |
| 173 | if ((so->so_options & (SO_REUSEADDR|SO_REUSEPORT)) != 0) |
| 174 | reuseport = SO_REUSEADDR|SO_REUSEPORT; |
no test coverage detected