📄 uipc_sock.c
字号:
/* uipc_sock.c - uipc socket routines *//* Copyright 1984 - 2002 Wind River Systems, Inc. */#include "copyright_wrs.h"/* * Copyright (c) 1982, 1986, 1988, 1990, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)uipc_socket.c 8.6 (Berkeley) 5/2/95 *//*modification history--------------------01l,05jun02,vvv fixed Nagle for large writes (SPR #72213)01k,12oct01,rae merge from truestack ver 01r, base 01h (SPR #64845 etc)01j,07feb01,spm updated socket handling to detect memory allocation failures01i,24sep98,ham considered if(m->m_extSize<max_hdr) in sosend() SPR#22209.01h,26aug98,n_s optimized processing of uio buffer in sosend. spr #22246.01g,26aug98,n_s added return val check for MALLOC in socreate and for mBufClGet in soreceive. spr #22238.01f,11aug97,vin fixed problems in sosend, adjusted space in sosend01e,23jan97,vin added fix for SPR7502.01d,03dec96,vin replaced calloc(..) with MALLOC(..), free(..) with FREE(..)01c,22nov96,vin added cluster support, replaced m_get with mBufClGet and m_gethdr with mHdrClGet.01b,29aug96,vin added zerocopy interface. 01a,03mar96,vin created from BSD4.4lite2. Integrated with 02u of uipc_sock.c*/#include "vxWorks.h"#include "semLib.h"#include "memLib.h"#include "errno.h"#include "net/mbuf.h"#include "net/domain.h"#include "net/protosw.h"#include "sys/socket.h"#include "sys/times.h"#include "net/socketvar.h"#include "sys/ioctl.h"#include "net/uio.h"#include "net/route.h"#include "netinet/in.h"#include "net/if.h"#include "net/systm.h"#include "selectLib.h"#include "sockLib.h"#include "netLib.h"#ifdef WV_INSTRUMENTATION#ifdef INCLUDE_WVNET#include "wvNetLib.h"#endif#endif#ifdef WV_INSTRUMENTATION#ifdef INCLUDE_WVNET /* Set common fields of event identifiers for this module. */LOCAL UCHAR wvNetModuleId = WV_NET_UISOCK_MODULE; /* Value for uipc_sock.c */LOCAL UCHAR wvNetLocalFilter = WV_NET_NONE; /* Available event filter */LOCAL ULONG wvNetEventId; /* Event identifier: see wvNetLib.h */#endif /* INCLUDE_WVNET */#endifextern int uiomove();/* * Socket operation routines. * These routines are called by the routines in * sys_socket.c or from a system process, and * implement the semantics of socket operations by * switching out to the protocol specific routines. *//*ARGSUSED*/intsocreate(dom, aso, type, proto) int dom; struct socket **aso; register int type; int proto;{ register struct protosw *prp; register struct socket *so; register int error;#ifdef WV_INSTRUMENTATION#ifdef INCLUDE_WVNET /* WV_NET_VERBOSE event */ WV_NET_MARKER_0 (NET_AUX_EVENT, WV_NET_VERBOSE, 45, 11, WV_NETEVENT_SOCREATE_START)#endif /* INCLUDE_WVNET */#endif if (proto) prp = pffindproto(dom, proto, type); else prp = pffindtype(dom, type); if (prp == 0 || prp->pr_usrreq == 0) {#ifdef WV_INSTRUMENTATION#ifdef INCLUDE_WVNET /* WV_NET_ERROR event */ WV_NET_MARKER_3 (NET_AUX_EVENT, WV_NET_ERROR, 43, 6, WV_NETEVENT_SOCREATE_SEARCHFAIL, dom, proto, type)#endif /* INCLUDE_WVNET */#endif return (EPROTONOSUPPORT); } if (prp->pr_type != type) {/* XXX - This event does not occur because the search routines will always * return a protocol switch entry which matches the given type value.#ifdef WV_INSTRUMENTATION#ifdef INCLUDE_WVNET /@ WV_NET_ERROR event @/ WV_NET_MARKER_2 (NET_AUX_EVENT, WV_NET_ERROR, 44, 7, WV_NETEVENT_SOCREATE_BADTYPE, prp->pr_type, type)#endif /@ INCLUDE_WVNET @/#endif * XXX - end of unused event */ return (EPROTOTYPE); } MALLOC(so, struct socket *, sizeof(*so), MT_SOCKET, M_WAIT); if (so == (struct socket *) NULL) { return (ENOBUFS); } bzero((caddr_t)so, sizeof(*so)); so->so_options = 0; so->so_type = type; /* all sockets will be priveledged */ so->so_state = SS_PRIV; so->so_proto = prp; /* initialize socket semaphores */ so->so_timeoSem = semBCreate (SEM_Q_PRIORITY, SEM_EMPTY); if (so->so_timeoSem == NULL) { so->so_state |= SS_NOFDREF; sofree(so); return (ENOMEM); } so->so_rcv.sb_Sem = semBCreate (SEM_Q_PRIORITY, SEM_EMPTY); if (so->so_rcv.sb_Sem == NULL) { so->so_state |= SS_NOFDREF; sofree(so); return (ENOMEM); } so->so_snd.sb_Sem = semBCreate (SEM_Q_PRIORITY, SEM_EMPTY); if (so->so_snd.sb_Sem == NULL) { so->so_state |= SS_NOFDREF; sofree(so); return (ENOMEM); } so->so_rcv.sb_want = 0; so->so_snd.sb_want = 0; /* initialize the select stuff */ selWakeupListInit (&so->so_selWakeupList); so->selectFlag = TRUE; error = (*prp->pr_usrreq)(so, PRU_ATTACH, (struct mbuf *)0, (struct mbuf *)(long)proto, (struct mbuf *)0); if (error) { so->so_state |= SS_NOFDREF; sofree(so); return (error); } *aso = so; return (0);}intsobind(so, nam) struct socket *so; struct mbuf *nam;{ int s = splnet(); int error;#ifdef WV_INSTRUMENTATION#ifdef INCLUDE_WVNET /* WV_NET_VERBOSE event */ WV_NET_MARKER_1 (NET_AUX_EVENT, WV_NET_VERBOSE, 46, 12, WV_NETEVENT_SOBIND_START, so->so_fd)#endif /* INCLUDE_WVNET */#endif error = (*so->so_proto->pr_usrreq)(so, PRU_BIND, (struct mbuf *)0, nam, (struct mbuf *)0); splx(s); return (error);}intsolisten(so, backlog) register struct socket *so; int backlog;{ int s = splnet(), error;#ifdef WV_INSTRUMENTATION#ifdef INCLUDE_WVNET /* WV_NET_VERBOSE event */ WV_NET_MARKER_1 (NET_AUX_EVENT, WV_NET_VERBOSE, 47, 13, WV_NETEVENT_SOLISTEN_START, so->so_fd)#endif /* INCLUDE_WVNET */#endif error = (*so->so_proto->pr_usrreq)(so, PRU_LISTEN, (struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0); if (error) { splx(s); return (error); } if (so->so_q == 0) so->so_options |= SO_ACCEPTCONN; if (backlog < 0) backlog = 0; so->so_qlimit = min(backlog, SOMAXCONN); splx(s); return (0);}void sofree ( register struct socket *so ) {#ifdef WV_INSTRUMENTATION#ifdef INCLUDE_WVNET /* WV_NET_VERBOSE event */ WV_NET_MARKER_1 (NET_AUX_EVENT, WV_NET_VERBOSE, 48, 14, WV_NETEVENT_SOFREE_START, so->so_fd)#endif /* INCLUDE_WVNET */#endif if (so->so_state & SS_NOFDREF) { /* * Always remove semaphores when closing socket. Existing TCP * connections exit after the next test, preventing correct * reclamation of these objects. */ if (so->so_timeoSem) { semDelete (so->so_timeoSem); so->so_timeoSem = NULL; } if (so->so_snd.sb_Sem) { semDelete (so->so_snd.sb_Sem); so->so_snd.sb_Sem = NULL; } if (so->so_rcv.sb_Sem) { semDelete (so->so_rcv.sb_Sem); so->so_rcv.sb_Sem = NULL; } if (so->selectFlag) { selWakeupListTerm (&so->so_selWakeupList); so->selectFlag = FALSE; } } if (so->so_pcb || (so->so_state & SS_NOFDREF) == 0) return; if (so->so_head) { if (!soqremque (so, 0) && !soqremque (so, 1)) {#ifdef WV_INSTRUMENTATION#ifdef INCLUDE_WVNET /* WV_NET_EMERGENCY event */ WV_NET_MARKER_1 (NET_AUX_EVENT, WV_NET_EMERGENCY, 38, 1, WV_NETEVENT_SOFREE_PANIC, so->so_fd)#endif /* INCLUDE_WVNET */#endif panic ("sofree dq"); } so->so_head = 0; } sbrelease (&so->so_snd); sorflush (so); FREE (so, MT_SOCKET); }/* * Close a socket on last file table reference removal. * Initiate disconnect if connected. * Free socket when disconnect complete. */int soclose ( register struct socket *so ) { int s = splnet(); /* conservative */ int error = 0; SEL_WAKEUP_NODE *pWakeupNode; SEL_WAKEUP_LIST *pWakeupList;#ifdef WV_INSTRUMENTATION#ifdef INCLUDE_WVNET /* WV_NET_VERBOSE event */ WV_NET_MARKER_1 (NET_AUX_EVENT, WV_NET_VERBOSE, 49, 15, WV_NETEVENT_SOCLOSE_START, so->so_fd)#endif /* INCLUDE_WVNET */#endif if (so->so_options & SO_ACCEPTCONN) { while (so->so_q0) (void) soabort(so->so_q0); while (so->so_q) (void) soabort(so->so_q); } if (so->so_pcb == 0) goto discard; if (so->so_state & SS_ISCONNECTED) { if ((so->so_state & SS_ISDISCONNECTING) == 0) { error = sodisconnect(so); if (error) goto drop; } if (so->so_options & SO_LINGER) { if ( (so->so_state & SS_ISDISCONNECTING) && (so->so_state & SS_NBIO)) goto drop; while (so->so_state & SS_ISCONNECTED) {#ifdef WV_INSTRUMENTATION#ifdef INCLUDE_WVNET /* WV_NET_INFO event */ WV_NET_MARKER_1 (NET_AUX_EVENT, WV_NET_INFO, 52, 10, WV_NETEVENT_SOCLOSE_WAIT, so->so_fd)#endif /* INCLUDE_WVNET */#endif ksleep(so->so_timeoSem); } } }drop: if (so->so_pcb) { int error2 = (*so->so_proto->pr_usrreq) (so, PRU_DETACH, (struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0); if (error == 0) error = error2; }discard: /* clean up the select wakeup list for this socket */ pWakeupList = &so->so_selWakeupList; if (lstCount (&pWakeupList->wakeupList) != 0) { semTake (&pWakeupList->listMutex, WAIT_FOREVER); while ((pWakeupNode = (SEL_WAKEUP_NODE *) lstFirst (&pWakeupList->wakeupList))) soo_unselect (so, pWakeupNode); semGive (&pWakeupList->listMutex); } if (so->so_state & SS_NOFDREF) {#ifdef WV_INSTRUMENTATION#ifdef INCLUDE_WVNET /* WV_NET_EMERGENCY event */ WV_NET_MARKER_1 (NET_AUX_EVENT, WV_NET_EMERGENCY, 39, 2, WV_NETEVENT_SOCLOSE_PANIC, so->so_fd)#endif /* INCLUDE_WVNET */#endif panic ("soclose: NOFDREF"); } so->so_state |= SS_NOFDREF; sofree (so); splx (s); return (error); }/* * Must be called at splnet... */int soabort ( struct socket *so ) {#ifdef WV_INSTRUMENTATION#ifdef INCLUDE_WVNET /* WV_NET_VERBOSE event */ WV_NET_MARKER_1 (NET_AUX_EVENT, WV_NET_VERBOSE, 50, 16, WV_NETEVENT_SOABORT_START, so->so_fd)#endif /* INCLUDE_WVNET */#endif return ( (*so->so_proto->pr_usrreq) (so, PRU_ABORT, (struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0)); }intsoaccept(so, nam) register struct socket *so; struct mbuf *nam;{ int s = splnet(); int error;#ifdef WV_INSTRUMENTATION#ifdef INCLUDE_WVNET /* WV_NET_VERBOSE event */ WV_NET_MARKER_1 (NET_AUX_EVENT, WV_NET_VERBOSE, 51, 17, WV_NETEVENT_SOACCEPT_START, so->so_fd)#endif /* INCLUDE_WVNET */#endif if ( (so->so_state & SS_NOFDREF) == 0) {#ifdef WV_INSTRUMENTATION#ifdef INCLUDE_WVNET /* WV_NET_EMERGENCY event */ WV_NET_MARKER_1 (NET_AUX_EVENT, WV_NET_EMERGENCY, 40, 3, WV_NETEVENT_SOACCEPT_PANIC, so->so_fd)#endif /* INCLUDE_WVNET */#endif panic("soaccept: !NOFDREF"); } so->so_state &= ~SS_NOFDREF; error = (*so->so_proto->pr_usrreq)(so, PRU_ACCEPT, (struct mbuf *)0, nam, (struct mbuf *)0); splx (s); return (error); }intsoconnect(so, nam) register struct socket *so;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -