📄 bsdsocklib.c
字号:
/* bsdSockLib.c - UNIX BSD 4.4 compatible socket library *//* Copyright 1984 - 1999 Wind River Systems, Inc. */#include "copyright_wrs.h"/*modification history--------------------01p,16mar99,spm recovered orphaned code from tor2_0_x branch (SPR #25770)01o,02dec98,n_s fixed sendmsg and recvmsg. spr 2355201n,10nov98,spm unmapped closed socket file descriptors (SPR #21583)01m,26aug98,n_s added return val check to mBufClGet in accept (). spr #22238.01l,17mar98,vin fixed a nonblocking I/O bug SPR 20542.01k,17mar98,jmb Merge patch by jmb from 03nov97: set small receive buffer which HPSIM is TCP client. (SPR 8709) 01j,17mar98,jmb Merge patch by jmb from 31oct97: Set receive buffer when HPSIM is a TCP server. Work-aroun for MTU mismatch and pty problem in the SLIP connection. (SPR 8709)01i,10dec97,sgv fixed a bug in recvmsg, intialized control and from variables to NULL. 01h,06oct97,sgv fixed sendmsg/recvmsg call, mbufs are not freed when EINVAL is returned01g,06oct97,spm added optional binary compatibility for BSD 4.3 applications01f,25jul97,vin fixed so_accept function call, saved new fd in the socket structure.01e,03dec96,vin changed m_getclr to fit the new declaration.01d,22nov96,vin modified for BSD44.01c,07aug95,dzb NOMANUAL on headers.01b,25jul95,dzb changed to just use DEV_HDR device header.01a,21jul95,dzb created from sockLib.c, ver 04g.*//*This library provides UNIX BSD 4.4 compatible socket calls. These callsmay be used to open, close, read, and write sockets, either on the sameCPU or over a network. The calling sequences of these routines areidentical to UNIX BSD 4.4.ADDRESS FAMILYVxWorks sockets support only the Internet Domain address family; useAF_INET for the <domain> argument in subroutines that require it.There is no support for the UNIX Domain address family.IOCTL FUNCTIONSSockets respond to the following ioctl() functions. These functions aredefined in the header files ioLib.h and ioctl.h..iP "FIONBIO" 18 3Turns on/off non-blocking I/O..CS on = TRUE; status = ioctl (sFd, FIONBIO, &on);.CE.iP "FIONREAD"Reports the number of bytes available to read on the socket. On the returnof ioctl(), <bytesAvailable> has the number of bytes available to readon the socket..CS status = ioctl (sFd, FIONREAD, &bytesAvailable);.CE.iP "SIOCATMARK"Reports whether there is out-of-band data to be read on the socket. Onthe return of ioctl(), <atMark> will be TRUE (1) if there is out-of-banddata, otherwise it will be FALSE (0)..CS status = ioctl (sFd, SIOCATMARK, &atMark);.CEINCLUDE FILES: types.h, bsdSockLib.h, socketvar.hSEE ALSO: netLib,.pG "Network"NOMANUAL*/#include "vxWorks.h"#include "sockFunc.h"#include "bsdSockMap.h" /* map socket routines to bsdxxx() */#include "strLib.h"#include "errnoLib.h"#include "netLib.h"#include "ioLib.h"#include "iosLib.h"#include "tickLib.h"#include "vwModNum.h"#include "net/systm.h"#include "net/mbuf.h"#include "net/protosw.h"#include "net/socketvar.h"#include "net/uio.h"#include "bsdSockLib.h"#include "netinet/in.h"IMPORT STATUS soo_ioctl (); /* for call into sys_socket.c *//* locals */LOCAL DEV_HDR bsdSockDev; /* BSD-specific device header */LOCAL int bsdSockDrvNum; /* BSD socket driver number */LOCAL char * bsdSockName = "(socket)"; /* file name of BSD sockets *//* globals */BOOL bsdSock43ApiFlag = FALSE; /* Provide backward binary */ /* compatibility for BSD 4.3? */ /* (Set TRUE by default with */ /* BSD43_COMPATIBLE in configAll.h). */IMPORT SOCK_FUNC ** pSockFdMap;/* declare BSD socket interface function table */SOCK_FUNC bsdSockFunc = { (FUNCPTR) sockLibInit, (FUNCPTR) accept, (FUNCPTR) bind, (FUNCPTR) connect, (FUNCPTR) connectWithTimeout, (FUNCPTR) getpeername, (FUNCPTR) getsockname, (FUNCPTR) listen, (FUNCPTR) recv, (FUNCPTR) recvfrom, (FUNCPTR) recvmsg, (FUNCPTR) send, (FUNCPTR) sendto, (FUNCPTR) sendmsg, (FUNCPTR) shutdown, (FUNCPTR) socket, (FUNCPTR) getsockopt, (FUNCPTR) setsockopt };/* forward declarations */LOCAL STATUS bsdSockClose (struct socket *so);LOCAL int bsdSockWrite (struct socket *so, char *buf, int bufLen);LOCAL int bsdSockRead (struct socket *so, caddr_t buf, int bufLen);LOCAL int bsdSockargs (struct mbuf ** aname, caddr_t name, int namelen, int type);LOCAL void bsdSockAddrRevert (struct sockaddr *);/********************************************************************************* bsdSockLibInit - install the BSD "socket driver" into the I/O system** bsdSockLibInit must be called once at configuration time before any socket* operations are performed.** RETURNS: a pointer to the BSD socket table, or NULL.** NOMANUAL*/SOCK_FUNC * sockLibInit (void) { if (bsdSockDrvNum > 0) return (&bsdSockFunc); if ((bsdSockDrvNum = iosDrvInstall ((FUNCPTR) NULL, (FUNCPTR) NULL, (FUNCPTR) NULL, (FUNCPTR) bsdSockClose, (FUNCPTR) bsdSockRead, (FUNCPTR) bsdSockWrite, (FUNCPTR) soo_ioctl)) == ERROR) return (NULL); bsdSockDev.drvNum = bsdSockDrvNum; /* to please I/O system */ bsdSockDev.name = bsdSockName; /* for iosFdSet name optimiz. */ return (&bsdSockFunc); }/********************************************************************************* bsdSocket - open a socket** This routine opens a socket and returns a socket descriptor.* The socket descriptor is passed to the other socket routines to identify the* socket. The socket descriptor is a standard I/O system file descriptor* (fd) and can be used with the close(), read(), write(), and ioctl() routines.** Available socket types include:* .iP SOCK_STREAM 18* connection-based (stream) socket.* .iP SOCK_DGRAM* datagram (UDP) socket.* .iP SOCK_RAW* raw socket.* .LP** RETURNS: A socket descriptor, or ERROR.** NOMANUAL*/int socket ( int domain, /* address family (e.g. AF_INET) */ int type, /* SOCK_STREAM, SOCK_DGRAM, or SOCK_RAW */ int protocol /* socket protocol (usually 0) */ ) { struct socket *so; int fd; FAST int spl = splnet (); int status = socreate (domain, &so, type, protocol); splx (spl); if (status) { netErrnoSet (status); return (ERROR); } /* stick the socket into a file descriptor */ if ((fd = iosFdNew ((DEV_HDR *) &bsdSockDev, bsdSockName, (int) so)) == ERROR) { (void)bsdSockClose (so); return (ERROR); } /* save fd in the socket structure */ so->so_fd = fd; return (fd); }/********************************************************************************* bsdSockClose - close a socket** bsdSockClose is called by the I/O system to close a socket.**/LOCAL STATUS bsdSockClose ( struct socket *so ) { FAST int ret; FAST int sx; int fd; sx = splnet (); fd = so->so_fd; if (so->so_state & SS_NOFDREF) ret = 0; else ret = soclose (so); splx (sx); /* * Remove the mapping installed by the switchboard. Performing this * step here is ugly, but the alternative is worse. */ pSockFdMap [fd] = NULL; return (ret); }/********************************************************************************* bsdBind - bind a name to a socket** This routine associates a network address (also referred to as its "name")* with a specified socket so that other processes can connect or send to it.* When a socket is created with socket(), it belongs to an address family* but has no assigned name.** RETURNS:* OK, or ERROR if there is an invalid socket, the address is either* unavailable or in use, or the socket is already bound.** NOMANUAL*/STATUS bind ( int s, /* socket descriptor */ struct sockaddr *name, /* name to be bound */ int namelen /* length of name */ ) { struct mbuf *nam; int status; struct socket *so; /* extract the socket from the fd */ if ((so = (struct socket *) iosFdValue (s)) == (struct socket *) ERROR) return (ERROR); status = bsdSockargs (&nam, (caddr_t) name, namelen, MT_SONAME); if (status) { netErrnoSet (status); return (ERROR); } status = sobind (so, nam); if (status) { netErrnoSet (status); m_freem (nam); return (ERROR); } m_freem (nam); return (OK); }/********************************************************************************* bsdListen - enable connections to a socket** This routine enables connections to a socket. It also specifies the* maximum number of unaccepted connections that can be pending at one time* (<backlog>). After enabling connections with listen(), connections are* actually accepted by accept().** RETURNS: OK, or ERROR if the socket is invalid or unable to listen.** NOMANUAL*/STATUS listen ( int s, /* socket descriptor */ int backlog /* number of connections to queue */ ) { FAST int status; FAST struct socket *so; /* extract the socket from the fd */ if ((so = (struct socket *) iosFdValue (s)) == (struct socket *) ERROR) return (ERROR); status = solisten (so, backlog); if (status) { netErrnoSet (status); return (ERROR); }#if (CPU == SIMHPPA)/* * Set the size of the receive buffer. * This is the way (without rewriting the user app) to get * data from the master to auto-segment and fit in the pty. */{ int bLen = 660; return (setsockopt (s, SOL_SOCKET, SO_RCVBUF, &bLen, sizeof (bLen)));}#endif return (OK); }/********************************************************************************* bsdAccept - accept a connection from a socket** This routine accepts a connection on a socket, and returns a new socket* created for the connection. The socket must be bound to an address with* bind(), and enabled for connections by a call to listen(). The accept()* routine dequeues the first connection and creates a new socket with the* same properties as <s>. It blocks the caller until a connection is* present, unless the socket is marked as non-blocking.** The parameter <addrlen> should be initialized to the size of the available* buffer pointed to by <addr>. Upon return, <addrlen> contains the size in* bytes of the peer's address stored in <addr>.** RETURNS* A socket descriptor, or ERROR if the call fails.** NOMANUAL*/int accept ( int s, /* socket descriptor */ struct sockaddr *addr, /* peer address */ int *addrlen /* peer address length */ ) { struct mbuf *nam; int namelen = *addrlen; int slev; FAST struct socket *so; FAST int fd; /* extract the socket from the fd */ if ((so = (struct socket *) iosFdValue (s)) == (struct socket *) ERROR) return (ERROR); slev = splnet (); if ((so->so_options & SO_ACCEPTCONN) == 0) { netErrnoSet (EINVAL); splx (slev); return (ERROR); } if ((so->so_state & SS_NBIO) && so->so_qlen == 0) { netErrnoSet (EWOULDBLOCK); splx(slev); return (ERROR); } while (so->so_qlen == 0 && so->so_error == 0) { if (so->so_state & SS_CANTRCVMORE) { so->so_error = ECONNABORTED; break; } ksleep (&so->so_timeoSem); } if (so->so_error) { netErrnoSet ((int) so->so_error); so->so_error = 0; splx (slev); return (ERROR); } if ( (nam = mBufClGet (M_WAIT, MT_SONAME, CL_SIZE_128, TRUE)) == NULL) { netErrnoSet (ENOBUFS); splx (slev); return (ERROR); } { struct socket *aso = so->so_q; if (soqremque(aso, 1) == 0) panic ("accept"); so = aso; } (void) soaccept (so, nam); if (addr) { if (namelen > nam->m_len) namelen = nam->m_len; /* XXX SHOULD COPY OUT A CHAIN HERE */ (void) copyout (mtod(nam, caddr_t), (caddr_t)addr, namelen); (void) copyout ((caddr_t)&namelen, (caddr_t)addrlen, sizeof (*addrlen)); if (bsdSock43ApiFlag) { /* Convert the address structure contents to the BSD 4.3 format. */ bsdSockAddrRevert (addr); } } m_freem (nam); splx (slev); /* put the new socket into an fd */ if ((fd = iosFdNew ((DEV_HDR *) &bsdSockDev, bsdSockName, (int) so)) == ERROR) { (void)bsdSockClose (so); return (ERROR); } /* save fd in the socket structure */ so->so_fd = fd; return (fd); }/********************************************************************************* bsdConnect - initiate a connection to a socket** If <s> is a socket of type SOCK_STREAM, this routine establishes a virtual* circuit between <s> and another socket specified by <name>. If <s> is of* type SOCK_DGRAM, it permanently specifies the peer to which messages* are sent. If <s> is of type SOCK_RAW, it specifies the raw socket upon* which data is to be sent and received. The <name> parameter specifies the* address of the other socket.** RETURNS* OK, or ERROR if the call fails.** NOMANUAL*/STATUS connect ( int s, /* socket descriptor */ struct sockaddr *name, /* addr of socket to connect */ int namelen /* length of name, in bytes */ ) { struct mbuf *nam; int slev; int status; FAST struct socket *so; /* extract the socket from the fd */ if ((so = (struct socket *) iosFdValue (s)) == (struct socket *) ERROR) return (ERROR); if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTING)) { netErrnoSet (EALREADY); return (ERROR); } status = bsdSockargs (&nam, (caddr_t)name, namelen, MT_SONAME); if (status) { netErrnoSet (status); return (ERROR); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -