Changeset View
Changeset View
Standalone View
Standalone View
sys/netinet6/in6_pcb.c
Show First 20 Lines • Show All 107 Lines • ▼ Show 20 Lines | |||||
#include <netinet6/ip6_var.h> | #include <netinet6/ip6_var.h> | ||||
#include <netinet6/nd6.h> | #include <netinet6/nd6.h> | ||||
#include <netinet/in_pcb.h> | #include <netinet/in_pcb.h> | ||||
#include <netinet6/in6_pcb.h> | #include <netinet6/in6_pcb.h> | ||||
#include <netinet6/in6_fib.h> | #include <netinet6/in6_fib.h> | ||||
#include <netinet6/scope6_var.h> | #include <netinet6/scope6_var.h> | ||||
static struct inpcb *in6_pcblookup_hash_locked(struct inpcbinfo *, | |||||
struct in6_addr *, u_int, struct in6_addr *, u_int, int, struct ifnet *); | |||||
int | int | ||||
in6_pcbbind(struct inpcb *inp, struct sockaddr *nam, | in6_pcbbind(struct inpcb *inp, struct sockaddr *nam, | ||||
struct ucred *cred) | struct ucred *cred) | ||||
{ | { | ||||
struct socket *so = inp->inp_socket; | struct socket *so = inp->inp_socket; | ||||
struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)NULL; | struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)NULL; | ||||
struct inpcbinfo *pcbinfo = inp->inp_pcbinfo; | struct inpcbinfo *pcbinfo = inp->inp_pcbinfo; | ||||
u_short lport = 0; | u_short lport = 0; | ||||
▲ Show 20 Lines • Show All 285 Lines • ▼ Show 20 Lines | |||||
* then pick one. | * then pick one. | ||||
*/ | */ | ||||
int | int | ||||
in6_pcbconnect_mbuf(struct inpcb *inp, struct sockaddr *nam, | in6_pcbconnect_mbuf(struct inpcb *inp, struct sockaddr *nam, | ||||
struct ucred *cred, struct mbuf *m, bool rehash) | struct ucred *cred, struct mbuf *m, bool rehash) | ||||
{ | { | ||||
struct inpcbinfo *pcbinfo = inp->inp_pcbinfo; | struct inpcbinfo *pcbinfo = inp->inp_pcbinfo; | ||||
struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)nam; | struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)nam; | ||||
struct in6_addr addr6; | struct sockaddr_in6 laddr6; | ||||
int error; | int error; | ||||
bzero(&laddr6, sizeof(laddr6)); | |||||
laddr6.sin6_family = AF_INET6; | |||||
INP_WLOCK_ASSERT(inp); | INP_WLOCK_ASSERT(inp); | ||||
INP_HASH_WLOCK_ASSERT(pcbinfo); | INP_HASH_WLOCK_ASSERT(pcbinfo); | ||||
/* | /* | ||||
* Call inner routine, to assign local interface address. | * Call inner routine, to assign local interface address. | ||||
* in6_pcbladdr() may automatically fill in sin6_scope_id. | * in6_pcbladdr() may automatically fill in sin6_scope_id. | ||||
*/ | */ | ||||
if ((error = in6_pcbladdr(inp, nam, &addr6)) != 0) | if ((error = in6_pcbladdr(inp, nam, &laddr6.sin6_addr)) != 0) | ||||
Lint: Possible Spelling Mistake: Possible spelling error. You wrote 'nam', but did you mean 'name'? | |||||
return (error); | return (error); | ||||
if (in6_pcblookup_hash_locked(pcbinfo, &sin6->sin6_addr, | if (in6_pcblookup_hash_locked(pcbinfo, &sin6->sin6_addr, | ||||
sin6->sin6_port, | sin6->sin6_port, | ||||
IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr) | IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr) | ||||
? &addr6 : &inp->in6p_laddr, | ? &laddr6.sin6_addr : &inp->in6p_laddr, | ||||
inp->inp_lport, 0, NULL) != NULL) { | inp->inp_lport, 0, NULL) != NULL) { | ||||
return (EADDRINUSE); | return (EADDRINUSE); | ||||
} | } | ||||
if (IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr)) { | if (IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr)) { | ||||
if (inp->inp_lport == 0) { | if (inp->inp_lport == 0) { | ||||
/* | |||||
* rehash was required to be true in the past for | |||||
* this case; retain that convention. However, | |||||
* we now call in_pcb_lport_dest rather than | |||||
* in6_pcbbind; the former does not insert into | |||||
* the hash table, the latter does. Change rehash | |||||
* to false to do the in_pcbinshash below. | |||||
*/ | |||||
KASSERT(rehash == true, | KASSERT(rehash == true, | ||||
("Rehashing required for unbound inps")); | ("Rehashing required for unbound inps")); | ||||
error = in6_pcbbind(inp, (struct sockaddr *)0, cred); | rehash = false; | ||||
error = in_pcb_lport_dest(inp, | |||||
(struct sockaddr *) &laddr6, &inp->inp_lport, | |||||
(struct sockaddr *) sin6, sin6->sin6_port, cred, 0); | |||||
if (error) | if (error) | ||||
return (error); | return (error); | ||||
} | } | ||||
inp->in6p_laddr = addr6; | inp->in6p_laddr = laddr6.sin6_addr; | ||||
} | } | ||||
inp->in6p_faddr = sin6->sin6_addr; | inp->in6p_faddr = sin6->sin6_addr; | ||||
inp->inp_fport = sin6->sin6_port; | inp->inp_fport = sin6->sin6_port; | ||||
/* update flowinfo - draft-itojun-ipv6-flowlabel-api-00 */ | /* update flowinfo - draft-itojun-ipv6-flowlabel-api-00 */ | ||||
inp->inp_flow &= ~IPV6_FLOWLABEL_MASK; | inp->inp_flow &= ~IPV6_FLOWLABEL_MASK; | ||||
if (inp->inp_flags & IN6P_AUTOFLOWLABEL) | if (inp->inp_flags & IN6P_AUTOFLOWLABEL) | ||||
inp->inp_flow |= | inp->inp_flow |= | ||||
(htonl(ip6_randomflowlabel()) & IPV6_FLOWLABEL_MASK); | (htonl(ip6_randomflowlabel()) & IPV6_FLOWLABEL_MASK); | ||||
▲ Show 20 Lines • Show All 660 Lines • ▼ Show 20 Lines | #ifdef INVARIANTS | ||||
else | else | ||||
INP_RLOCK_ASSERT(inp); | INP_RLOCK_ASSERT(inp); | ||||
#endif | #endif | ||||
return (inp); | return (inp); | ||||
} | } | ||||
#endif /* PCBGROUP */ | #endif /* PCBGROUP */ | ||||
/* | /* | ||||
* Lookup PCB in hash list. | * Lookup PCB in hash list. Used in in_pcb.c as well as here. | ||||
*/ | */ | ||||
static struct inpcb * | struct inpcb * | ||||
in6_pcblookup_hash_locked(struct inpcbinfo *pcbinfo, struct in6_addr *faddr, | in6_pcblookup_hash_locked(struct inpcbinfo *pcbinfo, struct in6_addr *faddr, | ||||
u_int fport_arg, struct in6_addr *laddr, u_int lport_arg, | u_int fport_arg, struct in6_addr *laddr, u_int lport_arg, | ||||
int lookupflags, struct ifnet *ifp) | int lookupflags, struct ifnet *ifp) | ||||
{ | { | ||||
struct inpcbhead *head; | struct inpcbhead *head; | ||||
struct inpcb *inp, *tmpinp; | struct inpcb *inp, *tmpinp; | ||||
u_short fport = fport_arg, lport = lport_arg; | u_short fport = fport_arg, lport = lport_arg; | ||||
▲ Show 20 Lines • Show All 247 Lines • Show Last 20 Lines |
Possible spelling error. You wrote 'nam', but did you mean 'name'?