summaryrefslogtreecommitdiffstats
path: root/sys/netipx/ipx_pcb.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/netipx/ipx_pcb.c')
-rw-r--r--sys/netipx/ipx_pcb.c34
1 files changed, 27 insertions, 7 deletions
diff --git a/sys/netipx/ipx_pcb.c b/sys/netipx/ipx_pcb.c
index 4c8eba0..77fbfe8 100644
--- a/sys/netipx/ipx_pcb.c
+++ b/sys/netipx/ipx_pcb.c
@@ -158,7 +158,6 @@ noname:
int
ipx_pcbconnect(struct ipxpcb *ipxp, struct sockaddr *nam, struct thread *td)
{
- struct ipx_ifaddr *ia;
struct sockaddr_ipx *sipx = (struct sockaddr_ipx *)nam;
struct ipx_addr *dst;
struct route *ro;
@@ -167,8 +166,6 @@ ipx_pcbconnect(struct ipxpcb *ipxp, struct sockaddr *nam, struct thread *td)
IPX_LIST_LOCK_ASSERT();
IPX_LOCK_ASSERT(ipxp);
- ia = NULL;
-
if (sipx->sipx_family != AF_IPX)
return (EAFNOSUPPORT);
if (sipx->sipx_port == 0 || ipx_nullhost(sipx->sipx_addr))
@@ -213,6 +210,8 @@ ipx_pcbconnect(struct ipxpcb *ipxp, struct sockaddr *nam, struct thread *td)
rtalloc_ign(ro, 0);
}
if (ipx_neteqnn(ipxp->ipxp_laddr.x_net, ipx_zeronet)) {
+ struct ipx_ifaddr *ia = NULL;
+
/*
* If route is known or can be allocated now,
* our src addr is taken from the i/f, else punt.
@@ -225,8 +224,10 @@ ipx_pcbconnect(struct ipxpcb *ipxp, struct sockaddr *nam, struct thread *td)
if (ro->ro_rt != NULL && (ifp = ro->ro_rt->rt_ifp) != NULL) {
IPX_IFADDR_RLOCK();
for (ia = ipx_ifaddr; ia != NULL; ia = ia->ia_next)
- if (ia->ia_ifp == ifp)
+ if (ia->ia_ifp == ifp) {
+ ifa_ref(&ia->ia_ifa);
break;
+ }
IPX_IFADDR_RUNLOCK();
}
if (ia == NULL) {
@@ -235,16 +236,28 @@ ipx_pcbconnect(struct ipxpcb *ipxp, struct sockaddr *nam, struct thread *td)
ia = (struct ipx_ifaddr *)
ifa_ifwithdstaddr((struct sockaddr *)sipx);
sipx->sipx_addr.x_port = fport;
- if (ia == NULL)
+ if (ia == NULL) {
+ IPX_IFADDR_RLOCK();
ia = ipx_iaonnetof(&sipx->sipx_addr);
- if (ia == NULL)
+ if (ia != NULL)
+ ifa_ref(&ia->ia_ifa);
+ IPX_IFADDR_RUNLOCK();
+ }
+ if (ia == NULL) {
+ IPX_IFADDR_RLOCK();
ia = ipx_ifaddr;
+ if (ia != NULL)
+ ifa_ref(&ia->ia_ifa);
+ IPX_IFADDR_RUNLOCK();
+ }
if (ia == NULL)
return (EADDRNOTAVAIL);
}
ipxp->ipxp_laddr.x_net = satoipx_addr(ia->ia_addr).x_net;
+ ifa_free(&ia->ia_ifa);
}
if (ipx_nullhost(ipxp->ipxp_laddr)) {
+ struct ipx_ifaddr *ia = NULL;
/*
* If route is known or can be allocated now,
* our src addr is taken from the i/f, else punt.
@@ -257,8 +270,10 @@ ipx_pcbconnect(struct ipxpcb *ipxp, struct sockaddr *nam, struct thread *td)
if (ro->ro_rt != NULL && (ifp = ro->ro_rt->rt_ifp) != NULL) {
IPX_IFADDR_RLOCK();
for (ia = ipx_ifaddr; ia != NULL; ia = ia->ia_next)
- if (ia->ia_ifp == ifp)
+ if (ia->ia_ifp == ifp) {
+ ifa_ref(&ia->ia_ifa);
break;
+ }
IPX_IFADDR_RUNLOCK();
}
if (ia == NULL) {
@@ -270,17 +285,22 @@ ipx_pcbconnect(struct ipxpcb *ipxp, struct sockaddr *nam, struct thread *td)
if (ia == NULL) {
IPX_IFADDR_RLOCK();
ia = ipx_iaonnetof(&sipx->sipx_addr);
+ if (ia != NULL)
+ ifa_ref(&ia->ia_ifa);
IPX_IFADDR_RUNLOCK();
}
if (ia == NULL) {
IPX_IFADDR_RLOCK();
ia = ipx_ifaddr;
+ if (ia != NULL)
+ ifa_ref(&ia->ia_ifa);
IPX_IFADDR_RUNLOCK();
}
if (ia == NULL)
return (EADDRNOTAVAIL);
}
ipxp->ipxp_laddr.x_host = satoipx_addr(ia->ia_addr).x_host;
+ ifa_free(&ia->ia_ifa);
}
if (ipx_pcblookup(&sipx->sipx_addr, ipxp->ipxp_lport, 0))
return (EADDRINUSE);
OpenPOWER on IntegriCloud