so = soalloc(1);
if (so == NULL)
return (NULL);
+
+ /*
+ * Set the port prior to attaching the inpcb to the current
+ * cpu's protocol thread (which should be the current thread
+ * but might not be in all cases). This serializes any pcb ops
+ * which occur to our cpu allowing us to complete the attachment
+ * without racing anything.
+ */
+ sosetport(so, cpu_portfn(mycpu->gd_cpuid));
if ((head->so_options & SO_ACCEPTFILTER) != 0)
connstatus = 0;
so->so_head = head;
KASSERT(msg->nm_dispatch != NULL,
("netmsg_service isr %d badmsg\n",
msg->nm_lmsg.u.ms_result));
- msg->nm_dispatch(msg);
+ if (msg->nm_so &&
+ msg->nm_so->so_port != &td->td_msgport) {
+ /*
+ * Sockets undergoing connect or disconnect
+ * ops can change ports on us. Chase the
+ * port.
+ */
+ kprintf("netmsg_service_loop: Warning, "
+ "port changed so=%p\n", msg->nm_so);
+ lwkt_forwardmsg(msg->nm_so->so_port,
+ &msg->nm_lmsg);
+ } else {
+ /*
+ * We are on the correct port, dispatch it.
+ */
+ msg->nm_dispatch(msg);
+ }
if (--limit == 0)
break;
} while ((msg = lwkt_getport(&td->td_msgport)) != NULL);
{
LIST_INIT(&pcbinfo->pcblisthead);
pcbinfo->cpu = -1;
+ pcbinfo->portsave = kmalloc(sizeof(*pcbinfo->portsave), M_PCB,
+ M_WAITOK | M_ZERO);
}
/*
return (0);
}
+/*
+ * Unlink a pcb with the intention of moving it to another cpu with a
+ * different pcbinfo. While unlinked nothing should attempt to dereference
+ * inp_pcbinfo, NULL it out so we assert if it does.
+ */
+void
+in_pcbunlink(struct inpcb *inp, struct inpcbinfo *pcbinfo)
+{
+ KKASSERT(inp->inp_pcbinfo == pcbinfo);
+
+ LIST_REMOVE(inp, inp_list);
+ pcbinfo->ipi_count--;
+ inp->inp_pcbinfo = NULL;
+}
+
+/*
+ * Relink a pcb into a new pcbinfo.
+ */
+void
+in_pcblink(struct inpcb *inp, struct inpcbinfo *pcbinfo)
+{
+ KKASSERT(inp->inp_pcbinfo == NULL);
+ inp->inp_pcbinfo = pcbinfo;
+ LIST_INSERT_HEAD(&pcbinfo->pcblisthead, inp, inp_list);
+ pcbinfo->ipi_count++;
+}
+
int
in_pcbbind(struct inpcb *inp, struct sockaddr *nam, struct thread *td)
{
return (EADDRNOTAVAIL);
if (inp->inp_lport != 0 || inp->inp_laddr.s_addr != INADDR_ANY)
return (EINVAL); /* already bound */
+
if (!(so->so_options & (SO_REUSEADDR|SO_REUSEPORT)))
wild = 1; /* neither SO_REUSEADDR nor SO_REUSEPORT is set */
if (p)
cred = p->p_ucred;
+
+ /*
+ * This has to be atomic. If the porthash is shared across multiple
+ * protocol threads (aka tcp) then the token will be non-NULL.
+ */
+ if (pcbinfo->porttoken)
+ lwkt_gettoken(pcbinfo->porttoken);
+
if (nam != NULL) {
sin = (struct sockaddr_in *)nam;
- if (nam->sa_len != sizeof *sin)
- return (EINVAL);
+ if (nam->sa_len != sizeof *sin) {
+ error = EINVAL;
+ goto done;
+ }
#ifdef notdef
/*
* We should check the family, but old programs
* incorrectly fail to initialize it.
*/
- if (sin->sin_family != AF_INET)
- return (EAFNOSUPPORT);
+ if (sin->sin_family != AF_INET) {
+ error = EAFNOSUPPORT;
+ goto done;
+ }
#endif
- if (!prison_replace_wildcards(td, nam))
- return (EINVAL);
+ if (!prison_replace_wildcards(td, nam)) {
+ error = EINVAL;
+ goto done;
+ }
lport = sin->sin_port;
if (IN_MULTICAST(ntohl(sin->sin_addr.s_addr))) {
/*
} else if (sin->sin_addr.s_addr != INADDR_ANY) {
sin->sin_port = 0; /* yech... */
bzero(&sin->sin_zero, sizeof sin->sin_zero);
- if (ifa_ifwithaddr((struct sockaddr *)sin) == NULL)
- return (EADDRNOTAVAIL);
+ if (ifa_ifwithaddr((struct sockaddr *)sin) == NULL) {
+ error = EADDRNOTAVAIL;
+ goto done;
+ }
}
if (lport != 0) {
struct inpcb *t;
/* GROSS */
if (ntohs(lport) < IPPORT_RESERVED &&
- cred && priv_check_cred(cred, PRIV_NETINET_RESERVEDPORT, 0))
- return (EACCES);
+ cred &&
+ priv_check_cred(cred, PRIV_NETINET_RESERVEDPORT, 0)) {
+ error = EACCES;
+ goto done;
+ }
if (so->so_cred->cr_uid != 0 &&
!IN_MULTICAST(ntohl(sin->sin_addr.s_addr))) {
- t = in_pcblookup_local(inp->inp_pcbinfo,
- sin->sin_addr, lport,
- INPLOOKUP_WILDCARD, cred);
+ t = in_pcblookup_local(pcbinfo,
+ sin->sin_addr,
+ lport,
+ INPLOOKUP_WILDCARD,
+ cred);
if (t &&
(!in_nullhost(sin->sin_addr) ||
!in_nullhost(t->inp_laddr) ||
INP_SOCKAF(so) ==
INP_SOCKAF(t->inp_socket))
#endif
- return (EADDRINUSE);
+ {
+ error = EADDRINUSE;
+ goto done;
+ }
}
}
- if (cred && !prison_replace_wildcards(td, nam))
- return (EADDRNOTAVAIL);
+ if (cred && !prison_replace_wildcards(td, nam)) {
+ error = EADDRNOTAVAIL;
+ goto done;
+ }
t = in_pcblookup_local(pcbinfo, sin->sin_addr, lport,
wild, cred);
if (t && !(reuseport & t->inp_socket->so_options)) {
!in_nullhost(t->inp_laddr) ||
INP_SOCKAF(so) == INP_SOCKAF(t->inp_socket))
#endif
- return (EADDRINUSE);
+ {
+ error = EADDRINUSE;
+ goto done;
+ }
}
}
inp->inp_laddr = sin->sin_addr;
jsin.sin_addr.s_addr = inp->inp_laddr.s_addr;
if (!prison_replace_wildcards(td, (struct sockaddr *)&jsin)) {
inp->inp_laddr.s_addr = INADDR_ANY;
- return (EINVAL);
+ error = EINVAL;
+ goto done;
}
inp->inp_laddr.s_addr = jsin.sin_addr.s_addr;
if (cred &&
(error = priv_check_cred(cred, PRIV_NETINET_RESERVEDPORT, 0))) {
inp->inp_laddr.s_addr = INADDR_ANY;
- return (error);
+ goto done;
}
first = ipport_lowfirstauto; /* 1023 */
last = ipport_lowlastauto; /* 600 */
do {
if (count-- < 0) { /* completely used? */
inp->inp_laddr.s_addr = INADDR_ANY;
- return (EADDRNOTAVAIL);
+ error = EADDRNOTAVAIL;
+ goto done;
}
--*lastport;
if (*lastport > first || *lastport < last)
*lastport = first;
lport = htons(*lastport);
} while (in_pcblookup_local(pcbinfo, inp->inp_laddr,
- lport, wild, cred));
+ lport, wild, cred));
} else {
/*
* counting up
do {
if (count-- < 0) { /* completely used? */
inp->inp_laddr.s_addr = INADDR_ANY;
- return (EADDRNOTAVAIL);
+ error = EADDRNOTAVAIL;
+ goto done;
}
++*lastport;
if (*lastport < first || *lastport > last)
*lastport = first;
lport = htons(*lastport);
} while (in_pcblookup_local(pcbinfo, inp->inp_laddr,
- lport, wild, cred));
+ lport, wild, cred));
}
}
inp->inp_lport = lport;
if (!prison_replace_wildcards(td, (struct sockaddr*)&jsin)) {
inp->inp_laddr.s_addr = INADDR_ANY;
inp->inp_lport = 0;
- return (EINVAL);
+ error = EINVAL;
+ goto done;
}
inp->inp_laddr.s_addr = jsin.sin_addr.s_addr;
if (in_pcbinsporthash(inp) != 0) {
inp->inp_laddr.s_addr = INADDR_ANY;
inp->inp_lport = 0;
- return (EAGAIN);
+ error = EAGAIN;
+ goto done;
}
- return (0);
+ error = 0;
+done:
+ if (pcbinfo->porttoken)
+ lwkt_reltoken(pcbinfo->porttoken);
+ return error;
}
/*
return (error);
if (in_pcblookup_hash(inp->inp_cpcbinfo, sin->sin_addr, sin->sin_port,
- inp->inp_laddr.s_addr ? inp->inp_laddr : if_sin->sin_addr,
- inp->inp_lport, FALSE, NULL) != NULL) {
+ inp->inp_laddr.s_addr ?
+ inp->inp_laddr : if_sin->sin_addr,
+ inp->inp_lport, FALSE, NULL) != NULL) {
return (EADDRINUSE);
}
if (inp->inp_laddr.s_addr == INADDR_ANY) {
ipsec4_delete_pcbpolicy(inp);
#endif /*IPSEC*/
inp->inp_gencnt = ++ipi->ipi_gencnt;
+ KKASSERT((so->so_state & SS_ASSERTINPROG) == 0);
in_pcbremlists(inp);
so->so_pcb = NULL;
sofree(so); /* remove pcb ref */
struct inpcb *inp;
int matchwild = 3, wildcard;
u_short lport = lport_arg;
-
struct inpcbporthead *porthash;
struct inpcbport *phd;
struct inpcb *match = NULL;
/*
+ * If the porthashbase is shared across several cpus we need
+ * to lock.
+ */
+ if (pcbinfo->porttoken)
+ lwkt_gettoken(pcbinfo->porttoken);
+
+ /*
* Best fit PCB lookup.
*
* First see if this local port is in use by looking on the
* port hash list.
*/
- porthash = &pcbinfo->porthashbase[INP_PCBPORTHASH(lport,
- pcbinfo->porthashmask)];
+ porthash = &pcbinfo->porthashbase[
+ INP_PCBPORTHASH(lport, pcbinfo->porthashmask)];
LIST_FOREACH(phd, porthash, phd_hash) {
if (phd->phd_port == lport)
break;
}
}
}
+ if (pcbinfo->porttoken)
+ lwkt_reltoken(pcbinfo->porttoken);
return (match);
}
* Lookup PCB in hash list.
*/
struct inpcb *
-in_pcblookup_hash(struct inpcbinfo *pcbinfo, struct in_addr faddr, u_int fport_arg,
- struct in_addr laddr, u_int lport_arg, boolean_t wildcard,
- struct ifnet *ifp)
+in_pcblookup_hash(struct inpcbinfo *pcbinfo, struct in_addr faddr,
+ u_int fport_arg, struct in_addr laddr, u_int lport_arg,
+ boolean_t wildcard, struct ifnet *ifp)
{
struct inpcbhead *head;
struct inpcb *inp, *jinp=NULL;
struct inpcbport *phd;
/*
+ * If the porthashbase is shared across several cpus we need
+ * to lock.
+ */
+ if (pcbinfo->porttoken)
+ lwkt_gettoken(pcbinfo->porttoken);
+
+ /*
* Insert into the port hash table.
*/
pcbporthash = &pcbinfo->porthashbase[
INP_PCBPORTHASH(inp->inp_lport, pcbinfo->porthashmask)];
/* Go through port list and look for a head for this lport. */
- LIST_FOREACH(phd, pcbporthash, phd_hash)
+ LIST_FOREACH(phd, pcbporthash, phd_hash) {
if (phd->phd_port == inp->inp_lport)
break;
+ }
/* If none exists, malloc one and tack it on. */
if (phd == NULL) {
- MALLOC(phd, struct inpcbport *, sizeof(struct inpcbport),
- M_PCB, M_INTWAIT | M_NULLOK);
- if (phd == NULL)
- return (ENOBUFS); /* XXX */
+ KKASSERT(pcbinfo->portsave != NULL);
+ phd = pcbinfo->portsave;
+ pcbinfo->portsave = NULL;
phd->phd_port = inp->inp_lport;
LIST_INIT(&phd->phd_pcblist);
LIST_INSERT_HEAD(pcbporthash, phd, phd_hash);
inp->inp_phd = phd;
LIST_INSERT_HEAD(&phd->phd_pcblist, inp, inp_portlist);
+ if (pcbinfo->porttoken)
+ lwkt_reltoken(pcbinfo->porttoken);
+ if (pcbinfo->portsave == NULL) {
+ pcbinfo->portsave = kmalloc(sizeof(*pcbinfo->portsave),
+ M_PCB, M_INTWAIT | M_ZERO);
+ }
return (0);
}
u_short phd_port;
};
+struct lwkt_token;
+
struct inpcbinfo { /* XXX documentation, prefixes */
struct inpcbhead *hashbase;
u_long hashmask;
struct inpcbporthead *porthashbase;
u_long porthashmask;
+ struct lwkt_token *porttoken; /* if porthashbase is shared */
+ struct inpcbport *portsave; /* port allocation cache */
struct inpcontainerhead *wildcardhashbase;
u_long wildcardhashmask;
struct inpcbhead pcblisthead; /* head of queue of active pcb's */
void in_rtchange (struct inpcb *, int);
void in_pcbinfo_init (struct inpcbinfo *);
int in_pcballoc (struct socket *, struct inpcbinfo *);
+void in_pcbunlink (struct inpcb *, struct inpcbinfo *);
+void in_pcblink (struct inpcb *, struct inpcbinfo *);
int in_pcbbind (struct inpcb *, struct sockaddr *, struct thread *);
int in_pcbconnect (struct inpcb *, struct sockaddr *, struct thread *);
void in_pcbdetach (struct inpcb *);
#endif
/*
- * Initital port when creating the socket, generally before
- * binding or connect.
- */
-lwkt_port_t
-tcp_soport_attach(struct socket *so)
-{
- return(cpu_portfn(0));
-}
-
-/*
* This is used to map a socket to a message port for sendmsg() and friends.
* It is not called for any other purpose. In the case of TCP we just return
* the port already installed in the socket.
}
/*
- * Initital port when creating the socket, generally before
- * binding or connect.
- */
-lwkt_port_t
-udp_soport_attach(struct socket *so)
-{
- return(cpu_portfn(0));
-}
-
-/*
* This is used to map a socket to a message port for sendmsg() and friends.
* It is not called for any other purpose.
*
if (error)
return error;
lwkt_gettoken(&div_token);
+ so->so_port = cpu0_soport(so, NULL, NULL);
error = in_pcballoc(so, &divcbinfo);
if (error) {
lwkt_reltoken(&div_token);
* The socket is always "connected" because
* we always know "where" to send the packet.
*/
- so->so_port = cpu0_soport(so, NULL, NULL);
sosetstate(so, SS_ISCONNECTED);
lwkt_reltoken(&div_token);
return 0;
struct inpcbinfo tcbinfo[MAXCPU];
struct tcpcbackqhead tcpcbackq[MAXCPU];
+static struct lwkt_token tcp_port_token =
+ LWKT_TOKEN_MP_INITIALIZER(tcp_port_token);
+
int tcp_mssdflt = TCP_MSS;
SYSCTL_INT(_net_inet_tcp, TCPCTL_MSSDFLT, mssdflt, CTLFLAG_RW,
&tcp_mssdflt, 0, "Default TCP Maximum Segment Size");
void
tcp_init(void)
{
+ struct inpcbporthead *porthashbase;
struct inpcbinfo *ticb;
+ u_long porthashmask;
int hashsize = TCBHASHSIZE;
int cpu;
hashsize = 512; /* safe default */
}
tcp_tcbhashsize = hashsize;
+ porthashbase = hashinit(hashsize, M_PCB, &porthashmask);
for (cpu = 0; cpu < ncpus2; cpu++) {
ticb = &tcbinfo[cpu];
ticb->cpu = cpu;
ticb->hashbase = hashinit(hashsize, M_PCB,
&ticb->hashmask);
+ ticb->porthashbase = porthashbase;
+ ticb->porthashmask = porthashmask;
+ ticb->porttoken = &tcp_port_token;
+#if 0
ticb->porthashbase = hashinit(hashsize, M_PCB,
&ticb->porthashmask);
+#endif
ticb->wildcardhashbase = hashinit(hashsize, M_PCB,
&ticb->wildcardhashmask);
ticb->ipi_size = sizeof(struct inp_tp);
* as they would have been set up if we had created the
* connection when the SYN arrived. If we can't create
* the connection, abort it.
+ *
+ * Set the protocol processing port for the socket to the current
+ * port (that the connection came in on).
*/
so = sonewconn(lso, SS_ISCONNECTED);
if (so == NULL) {
}
/*
- * Set the protocol processing port for the socket to the current
- * port (that the connection came in on).
- */
- sosetport(so, &curthread->td_msgport);
-
- /*
* Insert new socket into hash list.
*/
inp = so->so_pcb;
inp->inp_lport = 0;
goto abort;
}
- linp = so->so_pcb;
+ linp = lso->so_pcb;
#ifdef IPSEC
/* copy old policy into new socket's */
if (ipsec_copy_policy(linp->inp_sp, inp->inp_sp))
port = tcp_addrport(inp->inp_faddr.s_addr, inp->inp_fport,
inp->inp_laddr.s_addr, inp->inp_lport);
}
+ if (port != &curthread->td_msgport) {
+ print_backtrace(-1);
+ kprintf("TCP PORT MISMATCH %p vs %p\n",
+ port, &curthread->td_msgport);
+ }
/*KKASSERT(port == &curthread->td_msgport);*/
tp = intotcpcb(inp);
/*
* TCP attaches to socket via pru_attach(), reserving space,
- * and an internet control block.
+ * and an internet control block. This is likely occuring on
+ * cpu0 and may have to move later when we bind/connect.
*/
static int
tcp_usr_attach(struct socket *so, int proto, struct pru_attach_info *ai)
* Create TCP timer message now; we are on the tcpcb's owner
* CPU/thread.
*/
- sosetport(so, &curthread->td_msgport);
tcp_create_timermsg(tp, &curthread->td_msgport);
/*
struct mbuf *nm_m;
};
+/*
+ * This is called in the target protocol processing thread. We must
+ * re-link our pcb to the new tcpcb
+ */
static void
tcp_connect_handler(netmsg_t netmsg)
{
struct netmsg_tcp_connect *msg = (void *)netmsg;
+ struct socket *so = netmsg->nm_so;
int error;
+ in_pcblink(so->so_pcb, &tcbinfo[mycpu->gd_cpuid]);
error = tcp_connect_oncpu(msg->nm_tp, msg->nm_flags, msg->nm_m,
msg->nm_sin, msg->nm_ifsin);
lwkt_replymsg(&msg->nm_netmsg.nm_lmsg, error);
struct inpcb *inp = tp->t_inpcb;
struct sockaddr_in *sin = (struct sockaddr_in *)nam;
struct sockaddr_in *if_sin;
+ struct socket *so;
int error;
#ifdef SMP
lwkt_port_t port;
return (error);
}
}
+ so = inp->inp_socket;
+ KKASSERT(so);
/*
* Calculate the correct protocol processing thread. The connect
- * operation must run there.
+ * operation must run there. Set the forwarding port before we
+ * forward the message or it will get bounced right back to us.
*/
error = in_pcbladdr(inp, nam, &if_sin, td);
if (error) {
bzero(ro, sizeof(*ro));
/*
- * NOTE: We haven't set so->so_port yet do not pass so
- * to netmsg_init() or it will be improperly forwarded.
+ * We are moving the protocol processing port the socket
+ * is on, we have to unlink here and re-link on the
+ * target cpu.
*/
- netmsg_init(&msg.nm_netmsg, NULL, &curthread->td_msgport,
+ in_pcbunlink(so->so_pcb, &tcbinfo[mycpu->gd_cpuid]);
+ sosetport(so, port);
+
+ netmsg_init(&msg.nm_netmsg, so, &curthread->td_msgport,
0, tcp_connect_handler);
msg.nm_tp = tp;
msg.nm_sin = sin;
error = tcp_connect_oncpu(tp, flags, m, sin, if_sin);
}
#else
+ KKASSERT(so->so_port == &curthread->td_msgport);
error = tcp_connect_oncpu(tp, flags, m, sin, if_sin);
#endif
return (error);
* Create TCP timer message now; we are on the tcpcb's owner
* CPU/thread.
*/
- sosetport(so, &curthread->td_msgport);
tcp_create_timermsg(tp, &curthread->td_msgport);
/* Compute window scaling to request. */
&tcp_recvspace , 0, "Maximum incoming TCP datagram size");
/*
- * Attach TCP protocol to socket, allocating
- * internet protocol control block, tcp control block,
- * bufer space, and entering LISTEN state if to accept connections.
+ * Attach TCP protocol to socket, allocating internet protocol control
+ * block, tcp control block, bufer space, and entering LISTEN state
+ * if to accept connections.
*/
static int
tcp_attach(struct socket *so, struct pru_attach_info *ai)
atomic_set_int(&so->so_rcv.ssb_flags, SSB_AUTOSIZE);
atomic_set_int(&so->so_snd.ssb_flags, SSB_AUTOSIZE);
cpu = mycpu->gd_cpuid;
+
+ /*
+ * Set the default port for protocol processing. This will likely
+ * change when we connect.
+ */
error = in_pcballoc(so, &tcbinfo[cpu]);
if (error)
return (error);
return (ENOBUFS);
}
tp->t_state = TCPS_CLOSED;
- so->so_port = tcp_soport_attach(so);
return (0);
}
struct lwkt_port *
tcp_soport(struct socket *, struct sockaddr *, struct mbuf **);
struct lwkt_port *
- tcp_soport_attach(struct socket *);
-struct lwkt_port *
tcp_ctlport(int, struct sockaddr *, void *);
struct tcpcb *
tcp_timers (struct tcpcb *, int);
error = in_pcballoc(so, &udbinfo);
if (error)
return error;
- so->so_port = udp_soport_attach(so);
+
+ /*
+ * Set default port for protocol processing prior to bind/connect.
+ */
+ sosetport(so, cpu_portfn(0));
inp = (struct inpcb *)so->so_pcb;
inp->inp_vflag |= INP_IPV4;
port = udp_addrport(sin->sin_addr.s_addr, sin->sin_port,
inp->inp_laddr.s_addr, inp->inp_lport);
#ifdef SMP
+ sosetport(so, port);
if (port != &curthread->td_msgport) {
struct netmsg_udp_connect msg;
struct route *ro = &inp->inp_route;
error = udp_connect_oncpu(so, td, sin, if_sin);
}
#else
+ KKASSERT(port == &curthread->td_msgport);
error = udp_connect_oncpu(so, td, sin, if_sin);
#endif
return (error);
* socket.
*/
soisconnected(so);
- sosetport(so, &curthread->td_msgport);
} else if (error == EAFNOSUPPORT) { /* connection dissolved */
/*
* Follow traditional BSD behavior and retain
int udp_shutdown (struct socket *so);
struct lwkt_port *udp_soport (struct socket *, struct sockaddr *,
struct mbuf **);
-struct lwkt_port *udp_soport_attach (struct socket *);
struct lwkt_port *udp_ctlport (int, struct sockaddr *, void *);
struct lwkt_port *udp_cport (int);
inp->inp_gencnt = ++ipi->ipi_gencnt;
in_pcbremlists(inp);
so->so_pcb = NULL;
+ KKASSERT((so->so_state & SS_ASSERTINPROG) == 0);
sofree(so); /* remove pcb ref */
if (inp->in6p_options)
struct inpcb *match = NULL;
/*
+ * If the porthashbase is shared across several cpus we need
+ * to lock.
+ */
+ if (pcbinfo->porttoken)
+ lwkt_gettoken(pcbinfo->porttoken);
+
+ /*
* Best fit PCB lookup.
*
* First see if this local port is in use by looking on the
* port hash list.
*/
- porthash = &pcbinfo->porthashbase[INP_PCBPORTHASH(lport,
- pcbinfo->porthashmask)];
+ porthash = &pcbinfo->porthashbase[
+ INP_PCBPORTHASH(lport, pcbinfo->porthashmask)];
LIST_FOREACH(phd, porthash, phd_hash) {
if (phd->phd_port == lport)
break;
}
+
if (phd != NULL) {
/*
* Port is in use by one or more PCBs. Look for best
}
}
}
+ if (pcbinfo->porttoken)
+ lwkt_reltoken(pcbinfo->porttoken);
+
return (match);
}
crit_exit();
if (error)
return error;
- so->so_port = udp_soport_attach(so);
+ sosetport(so, cpu_portfn(0));
inp = (struct inpcb *)so->so_pcb;
inp->inp_vflag |= INP_IPV6;
if (!ip6_v6only)
inp->inp_vflag &= ~INP_IPV4;
inp->inp_vflag |= INP_IPV6;
}
- /* sosetport(so, port); here, see udp v4 code */
soisconnected(so);
} else if (error == EAFNOSUPPORT) { /* connection dissolved */
/*