sockio.c

来自「eCos操作系统源码」· C语言 代码 · 共 1,076 行 · 第 1/2 页

C
1,076
字号
    error = sogetopt((struct socket *)fp->f_data, &opt);    if (error == 0) {        *optlen = opt.sopt_valsize;    }    return (error);}// -------------------------------------------------------------------------static int bsd_setsockopt(cyg_file *fp, int level, int optname,               const void *optval, socklen_t optlen){    struct sockopt opt;    opt.sopt_dir = SOPT_SET;    opt.sopt_level = level;    opt.sopt_name = optname;    opt.sopt_val = (void *)optval;    opt.sopt_valsize = optlen;    opt.sopt_p = 0;        return sosetopt((struct socket *)fp->f_data, &opt);}// -------------------------------------------------------------------------static int bsd_sendmsg(cyg_file *fp, const struct msghdr *m, int flags, ssize_t *retsize){    return bsd_sendit(fp, m, flags, retsize);}// -------------------------------------------------------------------------static int bsd_recvmsg(cyg_file *fp, struct msghdr *m, socklen_t *namelen, ssize_t *retsize){    return bsd_recvit(fp, m, namelen, retsize);}//==========================================================================// File system call functions// -------------------------------------------------------------------------static int bsd_read(struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio){    return (soreceive((struct socket *)fp->f_data, (struct sockaddr **)0,                      uio, (struct mbuf **)0, (struct mbuf **)0, (int *)0));}// -------------------------------------------------------------------------static int bsd_write(struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio){    return (sosend((struct socket *)fp->f_data, (struct sockaddr *)0,                   uio, (struct mbuf *)0, (struct mbuf *)0, 0, 0));}// -------------------------------------------------------------------------static int bsd_lseek(struct CYG_FILE_TAG *fp, off_t *pos, int whence){    return ESPIPE;}// -------------------------------------------------------------------------static int bsd_ioctl(struct CYG_FILE_TAG *fp, CYG_ADDRWORD cmd, CYG_ADDRWORD data){    struct socket *so = (struct socket *)fp->f_data;    void *p = 0;    switch (cmd) {    case FIONBIO:        if (*(int *)data)            so->so_state |= SS_NBIO;        else            so->so_state &= ~SS_NBIO;        return (0);    case FIOASYNC:        if (*(int *)data) {            so->so_state |= SS_ASYNC;            so->so_rcv.sb_flags |= SB_ASYNC;            so->so_snd.sb_flags |= SB_ASYNC;        } else {            so->so_state &= ~SS_ASYNC;            so->so_rcv.sb_flags &= ~SB_ASYNC;            so->so_snd.sb_flags &= ~SB_ASYNC;        }        return (0);    case FIONREAD:        *(int *)data = so->so_rcv.sb_cc;        return (0);    case SIOCATMARK:        *(int *)data = (so->so_state&SS_RCVATMARK) != 0;        return (0);    }    /*     * Interface/routing/protocol specific ioctls:     * interface and routing ioctls should have a     * different entry since a socket's unnecessary     */    if (IOCGROUP(cmd) == 'i')        return (ifioctl(so, (u_long)cmd, (caddr_t)data, p));    if (IOCGROUP(cmd) == 'r')        return (rtioctl((u_long)cmd, (caddr_t)data, p));    return ((*so->so_proto->pr_usrreqs->pru_control)(so, cmd, (caddr_t)data, 0, 0));}#if 0  // DEBUG supportstatic int bsd_ioctl(struct CYG_FILE_TAG *fp, CYG_ADDRWORD cmd, CYG_ADDRWORD data){    int res = _bsd_ioctl(fp, cmd, data);    diag_printf("ioctl(%x,%x) = %x\n", cmd, data, res);    return res;}#endif// -------------------------------------------------------------------------static int bsd_select(struct CYG_FILE_TAG *fp, int which, CYG_ADDRWORD info){    register struct socket *so = (struct socket *)fp->f_data;    register int s = splsoftnet();    switch (which) {    case FREAD:        if (soreadable(so)) {            splx(s);            return (1);        }        cyg_selrecord(info, &so->so_rcv.sb_sel);        so->so_rcv.sb_flags |= SB_SEL;        break;    case FWRITE:        if (sowriteable(so)) {            splx(s);            return (1);        }        cyg_selrecord(info, &so->so_snd.sb_sel);        so->so_snd.sb_flags |= SB_SEL;        break;    case 0:        if (so->so_oobmark || (so->so_state & SS_RCVATMARK)) {            splx(s);            return (1);        }        cyg_selrecord(info, &so->so_rcv.sb_sel);        so->so_rcv.sb_flags |= SB_SEL;        break;    }    splx(s);        return ENOERR;}// -------------------------------------------------------------------------static int bsd_fsync(struct CYG_FILE_TAG *fp, int mode){    // FIXME: call some sort of flush IOCTL?    return 0;}// -------------------------------------------------------------------------static int bsd_close(struct CYG_FILE_TAG *fp){    int error = 0;    if (fp->f_data)        error = soclose((struct socket *)fp->f_data);    fp->f_data = 0;    return (error);}// -------------------------------------------------------------------------static int bsd_fstat(struct CYG_FILE_TAG *fp, struct stat *buf){    register struct socket *so = (struct socket *)fp->f_data;    bzero((caddr_t)buf, sizeof (*buf));    // Mark socket as a fifo for now. We need to add socket types to    // sys/stat.h.    buf->st_mode = __stat_mode_FIFO;        return ((*so->so_proto->pr_usrreqs->pru_sense)(so, buf));}// -------------------------------------------------------------------------static int bsd_getinfo(struct CYG_FILE_TAG *fp, int key, void *buf, int len){    return ENOSYS;}// -------------------------------------------------------------------------static int bsd_setinfo(struct CYG_FILE_TAG *fp, int key, void *buf, int len){    return ENOSYS;}#if 0//==========================================================================// Select support// -------------------------------------------------------------------------// This function is called by the lower layers to record the// fact that a particular 'select' event is being requested.//void        selrecord(void *selector, struct selinfo *info){    // Unused by this implementation}// -------------------------------------------------------------------------// This function is called to indicate that a 'select' event// may have occurred.//void    selwakeup(struct selinfo *info){    cyg_selwakeup( info);}#endif//==========================================================================// Misc support functionsintsockargs(mp, buf, buflen, type)	struct mbuf **mp;	caddr_t buf;	int buflen;	int type;{	register struct sockaddr *sa;	register struct mbuf *m;	int error;	if (buflen > MLEN) {#ifdef COMPAT_OLDSOCK		if (type == MT_SONAME && buflen <= 112)			buflen = MLEN;		/* unix domain compat. hack */		else#endif		return (EINVAL);	}	m = m_get(M_WAIT, type);	if (m == NULL)		return (ENOBUFS);	m->m_len = buflen;	error = copyin(buf, mtod(m, caddr_t), buflen);	if (error) {		(void) m_free(m);		return (error);	}	*mp = m;	if (type == MT_SONAME) {		sa = mtod(m, struct sockaddr *);#if defined(COMPAT_OLDSOCK) && BYTE_ORDER != BIG_ENDIAN		if (sa->sa_family == 0 && sa->sa_len < AF_MAX)			sa->sa_family = sa->sa_len;#endif		sa->sa_len = buflen;	}	return (0);}// -------------------------------------------------------------------------// bsd_recvit()// Support for message reception. This is a lightly edited version of the// recvit() function is uipc_syscalls.c.static intbsd_recvit(cyg_file *fp, struct msghdr *mp, socklen_t *namelenp, ssize_t *retsize){    struct uio auio;    struct iovec *iov;    int i;    size_t len;    int error;    struct mbuf *m, *control = 0;    caddr_t ctlbuf;    struct socket *so;    struct sockaddr *fromsa = 0;    auio.uio_iov = mp->msg_iov;    auio.uio_iovcnt = mp->msg_iovlen;    auio.uio_segflg = UIO_USERSPACE;    auio.uio_rw = UIO_READ;    auio.uio_offset = 0;			/* XXX */    auio.uio_resid = 0;    iov = mp->msg_iov;    for (i = 0; i < mp->msg_iovlen; i++, iov++) {        /* Don't allow sum > SSIZE_MAX */        if (iov->iov_len > SSIZE_MAX ||            (auio.uio_resid += iov->iov_len) > SSIZE_MAX)            return (EINVAL);    }    len = auio.uio_resid;    so = (struct socket *)fp->f_data;    error = so->so_proto->pr_usrreqs->pru_soreceive(so, &fromsa, &auio,                                                    (struct mbuf **)0, mp->msg_control ? &control : (struct mbuf **)0,                                                    &mp->msg_flags);    if (error) {        if (auio.uio_resid != len &&             (error == EINTR || error == EWOULDBLOCK))            error = 0;    }    if (error)        goto out;    *retsize = len - auio.uio_resid;    if (mp->msg_name) {        len = mp->msg_namelen;        if (len <= 0 || fromsa == 0)            len = 0;        else {            /* save sa_len before it is destroyed by MSG_COMPAT */            if (len > fromsa->sa_len)                len = fromsa->sa_len;#ifdef COMPAT_OLDSOCK            if (mp->msg_flags & MSG_COMPAT)                ((struct osockaddr *)fromsa)->sa_family =                    fromsa->sa_family;#endif            error = copyout(fromsa,			    (caddr_t)mp->msg_name, (unsigned)len);            if (error)                goto out;        }        mp->msg_namelen = len;        if (namelenp) {            *namelenp = len;#ifdef COMPAT_OLDSOCK            if (mp->msg_flags & MSG_COMPAT)                error = 0;	/* old recvfrom didn't check */            else#endif                goto out;        }    }    if (mp->msg_control) {#ifdef COMPAT_OLDSOCK        /*         * We assume that old recvmsg calls won't receive access         * rights and other control info, esp. as control info         * is always optional and those options didn't exist in 4.3.         * If we receive rights, trim the cmsghdr; anything else         * is tossed.         */        if (control && mp->msg_flags & MSG_COMPAT) {            if (mtod(control, struct cmsghdr *)->cmsg_level !=                SOL_SOCKET ||                mtod(control, struct cmsghdr *)->cmsg_type !=                SCM_RIGHTS) {                mp->msg_controllen = 0;                goto out;            }            control->m_len -= sizeof (struct cmsghdr);            control->m_data += sizeof (struct cmsghdr);        }#endif        len = mp->msg_controllen;        m = control;        mp->msg_controllen = 0;        ctlbuf = (caddr_t) mp->msg_control;        while (m && len > 0) {            unsigned int tocopy;            if (len >= m->m_len)                 tocopy = m->m_len;            else {                mp->msg_flags |= MSG_CTRUNC;                tocopy = len;            }		            if ((error = copyout((caddr_t)mtod(m, caddr_t),                                 ctlbuf, tocopy)) != 0)                goto out;            ctlbuf += tocopy;            len -= tocopy;            m = m->m_next;        }        mp->msg_controllen = ctlbuf - (caddr_t)mp->msg_control;    } out:    if (fromsa)        FREE(fromsa, M_SONAME);    if (control)        m_freem(control);    return (error);}// -------------------------------------------------------------------------// sendit()// Support for message transmission. This is a lightly edited version of the// synonymous function is uipc_syscalls.c.static intbsd_sendit(cyg_file *fp, const struct msghdr *mp, int flags, ssize_t *retsize){    struct uio auio;    register struct iovec *iov;    register int i;    struct mbuf *control;    struct sockaddr *to;    int len, error;    struct socket *so;	    auio.uio_iov = mp->msg_iov;    auio.uio_iovcnt = mp->msg_iovlen;    auio.uio_segflg = UIO_USERSPACE;    auio.uio_rw = UIO_WRITE;    auio.uio_offset = 0;			/* XXX */    auio.uio_resid = 0;    iov = mp->msg_iov;    for (i = 0; i < mp->msg_iovlen; i++, iov++) {        /* Don't allow sum > SSIZE_MAX */        if (iov->iov_len > SSIZE_MAX ||            (auio.uio_resid += iov->iov_len) > SSIZE_MAX)            return (EINVAL);    }    if (mp->msg_name) {        error = getsockaddr(&to, mp->msg_name, mp->msg_namelen);        if (error) {            return (error);        }    } else {        to = 0;    }    if (mp->msg_control) {        if (mp->msg_controllen < sizeof(struct cmsghdr)#ifdef COMPAT_OLDSOCK            && mp->msg_flags != MSG_COMPAT#endif            ) {            error = EINVAL;            goto bad;        }        error = sockargs(&control, mp->msg_control,                         mp->msg_controllen, MT_CONTROL);        if (error)            goto bad;#ifdef COMPAT_OLDSOCK        if (mp->msg_flags == MSG_COMPAT) {            register struct cmsghdr *cm;            M_PREPEND(control, sizeof(*cm), M_WAIT);            if (control == 0) {                error = ENOBUFS;                goto bad;            } else {                cm = mtod(control, struct cmsghdr *);                cm->cmsg_len = control->m_len;                cm->cmsg_level = SOL_SOCKET;                cm->cmsg_type = SCM_RIGHTS;            }        }#endif    } else        control = 0;    len = auio.uio_resid;    so = (struct socket *)fp->f_data;    error = so->so_proto->pr_usrreqs->pru_sosend(so, to, &auio, 0, control,                                                 flags, 0);    if (error) {        if (auio.uio_resid != len && (error == EINTR || error == EWOULDBLOCK))            error = 0;    }    if (error == 0)        *retsize = len - auio.uio_resid; bad:    if (to)        FREE(to, M_SONAME);    return (error);}static intgetsockaddr(struct sockaddr **namp, caddr_t uaddr, size_t len){	struct sockaddr *sa;	int error;	if (len > SOCK_MAXADDRLEN)		return ENAMETOOLONG;	MALLOC(sa, struct sockaddr *, len, M_SONAME, M_WAITOK);	error = copyin(uaddr, sa, len);	if (error) {		FREE(sa, M_SONAME);	} else {#if defined(COMPAT_OLDSOCK) && BYTE_ORDER != BIG_ENDIAN		if (sa->sa_family == 0 && sa->sa_len < AF_MAX)			sa->sa_family = sa->sa_len;#endif		sa->sa_len = len;		*namp = sa;	}	return error;}//==========================================================================// End of sockio.c

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?