/*
- * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2000-2002 Apple Computer, Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
- * The contents of this file constitute Original Code as defined in and
- * are subject to the Apple Public Source License Version 1.1 (the
- * "License"). You may not use this file except in compliance with the
- * License. Please obtain a copy of the License at
- * http://www.apple.com/publicsource and read it before using this file.
+ * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
*
- * This Original Code and all software distributed under the License are
- * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
- * License for the specific language governing rights and limitations
- * under the License.
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
*
* @APPLE_LICENSE_HEADER_END@
*/
#include <net/route.h>
int soo_read __P((struct file *fp, struct uio *uio,
- struct ucred *cred));
+ struct ucred *cred, int flags, struct proc *p));
int soo_write __P((struct file *fp, struct uio *uio,
- struct ucred *cred));
+ struct ucred *cred, int flags, struct proc *p));
int soo_close __P((struct file *fp, struct proc *p));
-int soo_select __P((struct file *fp, int which, struct proc *p));
+int soo_select __P((struct file *fp, int which, void * wql, struct proc *p));
struct fileops socketops =
{ soo_read, soo_write, soo_ioctl, soo_select, soo_close };
/* ARGSUSED */
int
-soo_read(fp, uio, cred)
+soo_read(fp, uio, cred, flags, p)
struct file *fp;
struct uio *uio;
struct ucred *cred;
+ int flags;
+ struct proc *p;
{
- struct socket *so = (struct socket *)fp->f_data;
+ struct socket *so;
struct kextcb *kp;
int stat;
int (*fsoreceive) __P((struct socket *so,
struct uio *uio, struct mbuf **mp0,
struct mbuf **controlp, int *flagsp));
+
thread_funnel_switch(KERNEL_FUNNEL, NETWORK_FUNNEL);
+
+ if ((so = (struct socket *)fp->f_data) == NULL) {
+ /* This is not a valid open file descriptor */
+ thread_funnel_switch(NETWORK_FUNNEL, KERNEL_FUNNEL);
+ return (EBADF);
+ }
+
fsoreceive = so->so_proto->pr_usrreqs->pru_soreceive;
if (fsoreceive != soreceive)
{ kp = sotokextcb(so);
/* ARGSUSED */
int
-soo_write(fp, uio, cred)
+soo_write(fp, uio, cred, flags, p)
struct file *fp;
struct uio *uio;
struct ucred *cred;
+ int flags;
+ struct proc *p;
{
- struct socket *so = (struct socket *)fp->f_data;
+ struct socket *so;
int (*fsosend) __P((struct socket *so, struct sockaddr *addr,
struct uio *uio, struct mbuf *top,
struct mbuf *control, int flags));
int stat;
thread_funnel_switch(KERNEL_FUNNEL, NETWORK_FUNNEL);
+
+ if ((so = (struct socket *)fp->f_data) == NULL) {
+ /* This is not a valid open file descriptor */
+ thread_funnel_switch(NETWORK_FUNNEL, KERNEL_FUNNEL);
+ return (EBADF);
+ }
+
fsosend = so->so_proto->pr_usrreqs->pru_sosend;
if (fsosend != sosend)
{ kp = sotokextcb(so);
stat = (*fsosend)(so, 0, uio, 0, 0, 0);
thread_funnel_switch(NETWORK_FUNNEL, KERNEL_FUNNEL);
- return stat;
+
+ /* Generation of SIGPIPE can be controlled per socket */
+ if (stat == EPIPE && uio->uio_procp && !(so->so_flags & SOF_NOSIGPIPE))
+ psignal(uio->uio_procp, SIGPIPE);
+
+ return stat;
}
int
register caddr_t data;
struct proc *p;
{
- register struct socket *so = (struct socket *)fp->f_data;
-
+ register struct socket *so;
struct sockopt sopt;
struct kextcb *kp;
int error = 0;
- kp = sotokextcb(so);
- sopt.sopt_level = cmd;
- sopt.sopt_name = (int)data;
- sopt.sopt_p = p;
-
thread_funnel_switch(KERNEL_FUNNEL, NETWORK_FUNNEL);
+ if ((so = (struct socket *)fp->f_data) == NULL) {
+ /* This is not a valid open file descriptor */
+ thread_funnel_switch(NETWORK_FUNNEL, KERNEL_FUNNEL);
+ return (EBADF);
+ }
+
+ kp = sotokextcb(so);
+ sopt.sopt_level = cmd;
+ sopt.sopt_name = (int)data;
+ sopt.sopt_p = p;
+
while (kp)
{ if (kp->e_soif && kp->e_soif->sf_socontrol)
(*kp->e_soif->sf_socontrol)(so, &sopt, kp);
fp->f_flag |= FNONBLOCK;
so->so_state |= SS_NBIO;
so->so_options |= SO_DONTTRUNC | SO_WANTMORE;
+ so->so_flags |= SOF_NOSIGPIPE;
if (cloned_so && so != cloned_so) {
/* Flags options */
}
int
-soo_select(fp, which, p)
+soo_select(fp, which, wql, p)
struct file *fp;
int which;
+ void * wql;
struct proc *p;
{
register struct socket *so = (struct socket *)fp->f_data;
register int s = splnet();
int retnum=0;
-/* thread_funnel_switch(KERNEL_FUNNEL, NETWORK_FUNNEL); */
switch (which) {
case FREAD:
- so->so_rcv.sb_sel.si_flags |= SI_SBSEL;
+ so->so_rcv.sb_flags |= SB_SEL;
if (soreadable(so)) {
splx(s);
retnum = 1;
- so->so_rcv.sb_sel.si_flags &= ~SI_SBSEL;
+ so->so_rcv.sb_flags &= ~SB_SEL;
goto done;
}
- selrecord(p, &so->so_rcv.sb_sel);
+ selrecord(p, &so->so_rcv.sb_sel, wql);
break;
case FWRITE:
- so->so_snd.sb_sel.si_flags |= SI_SBSEL;
+ so->so_snd.sb_flags |= SB_SEL;
if (sowriteable(so)) {
splx(s);
retnum = 1;
- so->so_snd.sb_sel.si_flags &= ~SI_SBSEL;
+ so->so_snd.sb_flags &= ~SB_SEL;
goto done;
}
- selrecord(p, &so->so_snd.sb_sel);
+ selrecord(p, &so->so_snd.sb_sel, wql);
break;
case 0:
- so->so_rcv.sb_sel.si_flags |= SI_SBSEL;
+ so->so_rcv.sb_flags |= SB_SEL;
if (so->so_oobmark || (so->so_state & SS_RCVATMARK)) {
splx(s);
retnum = 1;
- so->so_rcv.sb_sel.si_flags &= ~SI_SBSEL;
+ so->so_rcv.sb_flags &= ~SB_SEL;
goto done;
}
- selrecord(p, &so->so_rcv.sb_sel);
+ selrecord(p, &so->so_rcv.sb_sel, wql);
break;
}
splx(s);
done:
-/* thread_funnel_switch(NETWORK_FUNNEL, KERNEL_FUNNEL); */
return (retnum);
}
register struct socket *so;
register struct stat *ub;
{
- int stat;
+ int stat;
+ /*
+ * DANGER: by the time we get the network funnel the socket
+ * may have been closed
+ */
thread_funnel_switch(KERNEL_FUNNEL, NETWORK_FUNNEL);
bzero((caddr_t)ub, sizeof (*ub));
ub->st_mode = S_IFSOCK;
{
int error = 0;
- if (fp->f_data) {
- thread_funnel_switch(KERNEL_FUNNEL, NETWORK_FUNNEL);
+ thread_funnel_switch(KERNEL_FUNNEL, NETWORK_FUNNEL);
+
+ if (fp->f_data)
error = soclose((struct socket *)fp->f_data);
- thread_funnel_switch(NETWORK_FUNNEL, KERNEL_FUNNEL);
- }
+
+ thread_funnel_switch(NETWORK_FUNNEL, KERNEL_FUNNEL);
fp->f_data = 0;
return (error);