summaryrefslogtreecommitdiffstats
path: root/sys/netipx/spx_usrreq.c
diff options
context:
space:
mode:
authorrwatson <rwatson@FreeBSD.org>2006-03-25 14:44:05 +0000
committerrwatson <rwatson@FreeBSD.org>2006-03-25 14:44:05 +0000
commit5e979685ba07d87041c8320cb22dcf77ce2efed5 (patch)
treeb6c3d624b99e7e2d34fffd5cb6a430411e900052 /sys/netipx/spx_usrreq.c
parent2856a58cbd34cfee4e1c6f14e170922f5e740d7d (diff)
downloadFreeBSD-src-5e979685ba07d87041c8320cb22dcf77ce2efed5.zip
FreeBSD-src-5e979685ba07d87041c8320cb22dcf77ce2efed5.tar.gz
In spx_ctloutput(), acquire the ipxp lock around read operations,
especially reads of spx header structures, which will now be cached in the stack until they can be copied out after releasing the lock. Panic if a bad socket option direction is passed in by the caller. MFC after: 1 month
Diffstat (limited to 'sys/netipx/spx_usrreq.c')
-rw-r--r--sys/netipx/spx_usrreq.c40
1 files changed, 25 insertions, 15 deletions
diff --git a/sys/netipx/spx_usrreq.c b/sys/netipx/spx_usrreq.c
index 98d548c..7ef9d9d 100644
--- a/sys/netipx/spx_usrreq.c
+++ b/sys/netipx/spx_usrreq.c
@@ -1145,27 +1145,30 @@ spx_setpersist(struct spxpcb *cb)
int
spx_ctloutput(struct socket *so, struct sockopt *sopt)
{
- struct ipxpcb *ipxp = sotoipxpcb(so);
+ struct spxhdr spxhdr;
+ struct ipxpcb *ipxp;
struct spxpcb *cb;
int mask, error;
short soptval;
u_short usoptval;
int optval;
- error = 0;
-
/*
* This will have to be changed when we do more general stacking of
* protocols.
*/
if (sopt->sopt_level != IPXPROTO_SPX)
return (ipx_ctloutput(so, sopt));
+
+ ipxp = sotoipxpcb(so);
if (ipxp == NULL)
return (EINVAL);
- else
- cb = ipxtospxpcb(ipxp);
+
+ IPX_LOCK(ipxp);
+ cb = ipxtospxpcb(ipxp);
KASSERT(cb != NULL, ("spx_ctloutput: cb == NULL"));
+ error = 0;
switch (sopt->sopt_dir) {
case SOPT_GET:
switch (sopt->sopt_name) {
@@ -1176,30 +1179,33 @@ spx_ctloutput(struct socket *so, struct sockopt *sopt)
case SO_HEADERS_ON_OUTPUT:
mask = SF_HO;
get_flags:
- /* Unlocked read. */
soptval = cb->s_flags & mask;
- error = sooptcopyout(sopt, &soptval, sizeof soptval);
+ IPX_UNLOCK(ipxp);
+ error = sooptcopyout(sopt, &soptval,
+ sizeof(soptval));
break;
case SO_MTU:
- /* Unlocked read. */
usoptval = cb->s_mtu;
- error = sooptcopyout(sopt, &usoptval, sizeof usoptval);
+ IPX_UNLOCK(ipxp);
+ error = sooptcopyout(sopt, &usoptval,
+ sizeof(usoptval));
break;
case SO_LAST_HEADER:
- /* Unlocked read. */
- error = sooptcopyout(sopt, &cb->s_rhdr,
- sizeof cb->s_rhdr);
+ spxhdr = cb->s_rhdr;
+ IPX_UNLOCK(ipxp);
+ error = sooptcopyout(sopt, &spxhdr, sizeof(spxhdr));
break;
case SO_DEFAULT_HEADERS:
- /* Unlocked read. */
- error = sooptcopyout(sopt, &cb->s_shdr,
- sizeof cb->s_shdr);
+ spxhdr = cb->s_shdr;
+ IPX_UNLOCK(ipxp);
+ error = sooptcopyout(sopt, &spxhdr, sizeof(spxhdr));
break;
default:
+ IPX_UNLOCK(ipxp);
error = ENOPROTOOPT;
}
break;
@@ -1209,6 +1215,7 @@ spx_ctloutput(struct socket *so, struct sockopt *sopt)
* XXX Why are these shorts on get and ints on set? That
* doesn't make any sense...
*/
+ IPX_UNLOCK(ipxp);
switch (sopt->sopt_name) {
case SO_HEADERS_ON_INPUT:
mask = SF_HI;
@@ -1278,6 +1285,9 @@ spx_ctloutput(struct socket *so, struct sockopt *sopt)
error = ENOPROTOOPT;
}
break;
+
+ default:
+ panic("spx_ctloutput: bad socket option direction");
}
return (error);
}
OpenPOWER on IntegriCloud