OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-2.0/] [packages/] [net/] [tcpip/] [v2_0/] [src/] [sys/] [kern/] [sockio.c] - Diff between revs 27 and 174

Only display areas with differences | Details | Blame | View Log

Rev 27 Rev 174
//==========================================================================
//==========================================================================
//
//
//      sys/kern/sockio.c
//      sys/kern/sockio.c
//
//
//     Socket interface to Fileio subsystem
//     Socket interface to Fileio subsystem
//
//
//==========================================================================
//==========================================================================
//####BSDCOPYRIGHTBEGIN####
//####BSDCOPYRIGHTBEGIN####
//
//
// -------------------------------------------
// -------------------------------------------
//
//
// Portions of this software may have been derived from OpenBSD or other sources,
// Portions of this software may have been derived from OpenBSD or other sources,
// and are covered by the appropriate copyright disclaimers included herein.
// and are covered by the appropriate copyright disclaimers included herein.
//
//
// -------------------------------------------
// -------------------------------------------
//
//
//####BSDCOPYRIGHTEND####
//####BSDCOPYRIGHTEND####
//==========================================================================
//==========================================================================
//#####DESCRIPTIONBEGIN####
//#####DESCRIPTIONBEGIN####
//
//
// Author(s):    nickg
// Author(s):    nickg
// Contributors: nickg
// Contributors: nickg
// Date:         2000-06-06
// Date:         2000-06-06
// Purpose:      
// Purpose:      
// Description:  
// Description:  
//              
//              
//
//
//####DESCRIPTIONEND####
//####DESCRIPTIONEND####
//
//
//==========================================================================
//==========================================================================
 
 
/*
/*
 * Copyright (c) 1982, 1986, 1991, 1993
 * Copyright (c) 1982, 1986, 1991, 1993
 *      The Regents of the University of California.  All rights reserved.
 *      The Regents of the University of California.  All rights reserved.
 * (c) UNIX System Laboratories, Inc.
 * (c) UNIX System Laboratories, Inc.
 * All or some portions of this file are derived from material licensed
 * All or some portions of this file are derived from material licensed
 * to the University of California by American Telephone and Telegraph
 * to the University of California by American Telephone and Telegraph
 * Co. or Unix System Laboratories, Inc. and are reproduced herein with
 * Co. or Unix System Laboratories, Inc. and are reproduced herein with
 * the permission of UNIX System Laboratories, Inc.
 * the permission of UNIX System Laboratories, Inc.
 *
 *
 * Redistribution and use in source and binary forms, with or without
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * modification, are permitted provided that the following conditions
 * are met:
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *    documentation and/or other materials provided with the distribution.
 * 3. All advertising materials mentioning features or use of this software
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *    must display the following acknowledgement:
 *      This product includes software developed by the University of
 *      This product includes software developed by the University of
 *      California, Berkeley and its contributors.
 *      California, Berkeley and its contributors.
 * 4. Neither the name of the University nor the names of 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
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *    without specific prior written permission.
 *
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * 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
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * SUCH DAMAGE.
 *
 *
 */
 */
//==========================================================================
//==========================================================================
 
 
#include <pkgconf/net.h>
#include <pkgconf/net.h>
#include <pkgconf/io_fileio.h>
#include <pkgconf/io_fileio.h>
 
 
#include <sys/types.h>
#include <sys/types.h>
 
 
#include <cyg/io/file.h>
#include <cyg/io/file.h>
 
 
#include <cyg/fileio/fileio.h>
#include <cyg/fileio/fileio.h>
#include <cyg/fileio/sockio.h>
#include <cyg/fileio/sockio.h>
 
 
#include <sys/param.h>
#include <sys/param.h>
#include <sys/mbuf.h>
#include <sys/mbuf.h>
#include <sys/protosw.h>
#include <sys/protosw.h>
#include <sys/socket.h>
#include <sys/socket.h>
#include <sys/socketvar.h>
#include <sys/socketvar.h>
#include <sys/ioctl.h>
#include <sys/ioctl.h>
 
 
#include <net/if.h>
#include <net/if.h>
#include <net/route.h>
#include <net/route.h>
 
 
//==========================================================================
//==========================================================================
// Forward definitions
// Forward definitions
 
 
static int     bsd_init( cyg_nstab_entry *nste );
static int     bsd_init( cyg_nstab_entry *nste );
static int     bsd_socket( cyg_nstab_entry *nste, int domain, int type,
static int     bsd_socket( cyg_nstab_entry *nste, int domain, int type,
                       int protocol, cyg_file *file );
                       int protocol, cyg_file *file );
 
 
static int bsd_bind      ( cyg_file *fp, const sockaddr *sa, socklen_t len );
static int bsd_bind      ( cyg_file *fp, const sockaddr *sa, socklen_t len );
static int bsd_connect   ( cyg_file *fp, const sockaddr *sa, socklen_t len );
static int bsd_connect   ( cyg_file *fp, const sockaddr *sa, socklen_t len );
static int bsd_accept    ( cyg_file *fp, cyg_file *new_fp,
static int bsd_accept    ( cyg_file *fp, cyg_file *new_fp,
                           struct sockaddr *name, socklen_t *anamelen );
                           struct sockaddr *name, socklen_t *anamelen );
static int bsd_listen    ( cyg_file *fp, int len );
static int bsd_listen    ( cyg_file *fp, int len );
static int bsd_getname   ( cyg_file *fp, sockaddr *sa, socklen_t *len, int peer );
static int bsd_getname   ( cyg_file *fp, sockaddr *sa, socklen_t *len, int peer );
static int bsd_shutdown  ( cyg_file *fp, int flags );
static int bsd_shutdown  ( cyg_file *fp, int flags );
static int bsd_getsockopt( cyg_file *fp, int level, int optname,
static int bsd_getsockopt( cyg_file *fp, int level, int optname,
                           void *optval, socklen_t *optlen);
                           void *optval, socklen_t *optlen);
static int bsd_setsockopt( cyg_file *fp, int level, int optname,
static int bsd_setsockopt( cyg_file *fp, int level, int optname,
                           const void *optval, socklen_t optlen);
                           const void *optval, socklen_t optlen);
static int bsd_sendmsg   ( cyg_file *fp, const struct msghdr *m,
static int bsd_sendmsg   ( cyg_file *fp, const struct msghdr *m,
                               int flags, ssize_t *retsize );
                               int flags, ssize_t *retsize );
static int bsd_recvmsg   ( cyg_file *fp, struct msghdr *m,
static int bsd_recvmsg   ( cyg_file *fp, struct msghdr *m,
                               socklen_t *namelen, ssize_t *retsize );
                               socklen_t *namelen, ssize_t *retsize );
 
 
 
 
// File operations
// File operations
static int bsd_read      (struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio);
static int bsd_read      (struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio);
static int bsd_write     (struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio);
static int bsd_write     (struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio);
static int bsd_lseek     (struct CYG_FILE_TAG *fp, off_t *pos, int whence );
static int bsd_lseek     (struct CYG_FILE_TAG *fp, off_t *pos, int whence );
static int bsd_ioctl     (struct CYG_FILE_TAG *fp, CYG_ADDRWORD com,
static int bsd_ioctl     (struct CYG_FILE_TAG *fp, CYG_ADDRWORD com,
                                CYG_ADDRWORD data);
                                CYG_ADDRWORD data);
static int bsd_select    (struct CYG_FILE_TAG *fp, int which, CYG_ADDRWORD info);
static int bsd_select    (struct CYG_FILE_TAG *fp, int which, CYG_ADDRWORD info);
static int bsd_fsync     (struct CYG_FILE_TAG *fp, int mode );
static int bsd_fsync     (struct CYG_FILE_TAG *fp, int mode );
static int bsd_close     (struct CYG_FILE_TAG *fp);
static int bsd_close     (struct CYG_FILE_TAG *fp);
static int bsd_fstat     (struct CYG_FILE_TAG *fp, struct stat *buf );
static int bsd_fstat     (struct CYG_FILE_TAG *fp, struct stat *buf );
static int bsd_getinfo   (struct CYG_FILE_TAG *fp, int key, void *buf, int len );
static int bsd_getinfo   (struct CYG_FILE_TAG *fp, int key, void *buf, int len );
static int bsd_setinfo   (struct CYG_FILE_TAG *fp, int key, void *buf, int len );
static int bsd_setinfo   (struct CYG_FILE_TAG *fp, int key, void *buf, int len );
 
 
static int
static int
bsd_recvit(cyg_file *fp, struct msghdr *mp, socklen_t *namelenp, ssize_t *retsize);
bsd_recvit(cyg_file *fp, struct msghdr *mp, socklen_t *namelenp, ssize_t *retsize);
static int
static int
bsd_sendit(cyg_file *fp, const struct msghdr *mp, int flags, ssize_t *retsize);
bsd_sendit(cyg_file *fp, const struct msghdr *mp, int flags, ssize_t *retsize);
 
 
 
 
//==========================================================================
//==========================================================================
// Table entrys
// Table entrys
 
 
NSTAB_ENTRY( bsd_nste, 0,
NSTAB_ENTRY( bsd_nste, 0,
             "bsd_tcpip",
             "bsd_tcpip",
             "",
             "",
             0,
             0,
             bsd_init,
             bsd_init,
             bsd_socket);
             bsd_socket);
 
 
struct cyg_sock_ops bsd_sockops =
struct cyg_sock_ops bsd_sockops =
{
{
    bsd_bind,
    bsd_bind,
    bsd_connect,
    bsd_connect,
    bsd_accept,
    bsd_accept,
    bsd_listen,
    bsd_listen,
    bsd_getname,
    bsd_getname,
    bsd_shutdown,
    bsd_shutdown,
    bsd_getsockopt,
    bsd_getsockopt,
    bsd_setsockopt,
    bsd_setsockopt,
    bsd_sendmsg,
    bsd_sendmsg,
    bsd_recvmsg
    bsd_recvmsg
};
};
 
 
cyg_fileops bsd_sock_fileops =
cyg_fileops bsd_sock_fileops =
{
{
    bsd_read,
    bsd_read,
    bsd_write,
    bsd_write,
    bsd_lseek,
    bsd_lseek,
    bsd_ioctl,
    bsd_ioctl,
    bsd_select,
    bsd_select,
    bsd_fsync,
    bsd_fsync,
    bsd_close,
    bsd_close,
    bsd_fstat,
    bsd_fstat,
    bsd_getinfo,
    bsd_getinfo,
    bsd_setinfo
    bsd_setinfo
};
};
 
 
//==========================================================================
//==========================================================================
// NStab functions
// NStab functions
 
 
 
 
 
 
// -------------------------------------------------------------------------
// -------------------------------------------------------------------------
 
 
static int     bsd_init( cyg_nstab_entry *nste )
static int     bsd_init( cyg_nstab_entry *nste )
{
{
    // Initialization already handled via constructor
    // Initialization already handled via constructor
 
 
    return ENOERR;
    return ENOERR;
}
}
 
 
// -------------------------------------------------------------------------
// -------------------------------------------------------------------------
 
 
static int     bsd_socket( cyg_nstab_entry *nste, int domain, int type,
static int     bsd_socket( cyg_nstab_entry *nste, int domain, int type,
                       int protocol, cyg_file *file )
                       int protocol, cyg_file *file )
{
{
    int error = 0;
    int error = 0;
    struct socket *so;
    struct socket *so;
 
 
    error = socreate( domain, &so, type, protocol );
    error = socreate( domain, &so, type, protocol );
 
 
    if( error == ENOERR )
    if( error == ENOERR )
    {
    {
 
 
        cyg_selinit(&so->so_rcv.sb_sel);
        cyg_selinit(&so->so_rcv.sb_sel);
        cyg_selinit(&so->so_snd.sb_sel);
        cyg_selinit(&so->so_snd.sb_sel);
 
 
        file->f_flag   |= CYG_FREAD|CYG_FWRITE;
        file->f_flag   |= CYG_FREAD|CYG_FWRITE;
        file->f_type    = CYG_FILE_TYPE_SOCKET;
        file->f_type    = CYG_FILE_TYPE_SOCKET;
        file->f_ops     = &bsd_sock_fileops;
        file->f_ops     = &bsd_sock_fileops;
        file->f_offset  = 0;
        file->f_offset  = 0;
        file->f_data    = (CYG_ADDRWORD)so;
        file->f_data    = (CYG_ADDRWORD)so;
        file->f_xops    = (CYG_ADDRWORD)&bsd_sockops;
        file->f_xops    = (CYG_ADDRWORD)&bsd_sockops;
    }
    }
 
 
    return error;
    return error;
}
}
 
 
 
 
//==========================================================================
//==========================================================================
// Sockops functions
// Sockops functions
 
 
// -------------------------------------------------------------------------
// -------------------------------------------------------------------------
 
 
static int bsd_bind      ( cyg_file *fp, const sockaddr *sa, socklen_t len )
static int bsd_bind      ( cyg_file *fp, const sockaddr *sa, socklen_t len )
{
{
    struct mbuf *nam;
    struct mbuf *nam;
    int error;
    int error;
 
 
    error = sockargs(&nam, (caddr_t)sa, len, MT_SONAME);
    error = sockargs(&nam, (caddr_t)sa, len, MT_SONAME);
 
 
    if (error)
    if (error)
        return (error);
        return (error);
 
 
    error = sobind((struct socket *)fp->f_data, nam);
    error = sobind((struct socket *)fp->f_data, nam);
 
 
    m_freem(nam);
    m_freem(nam);
 
 
    return error;
    return error;
}
}
 
 
// -------------------------------------------------------------------------
// -------------------------------------------------------------------------
 
 
static int bsd_connect   ( cyg_file *fp, const sockaddr *sa, socklen_t len )
static int bsd_connect   ( cyg_file *fp, const sockaddr *sa, socklen_t len )
{
{
    register struct socket *so;
    register struct socket *so;
    struct mbuf *nam;
    struct mbuf *nam;
    int error, s;
    int error, s;
 
 
    so = (struct socket *)fp->f_data;
    so = (struct socket *)fp->f_data;
 
 
    if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTING))
    if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTING))
        return (EALREADY);
        return (EALREADY);
 
 
    error = sockargs(&nam, (caddr_t)sa, len, MT_SONAME);
    error = sockargs(&nam, (caddr_t)sa, len, MT_SONAME);
 
 
    if (error)
    if (error)
        return (error);
        return (error);
 
 
    error = soconnect(so, nam);
    error = soconnect(so, nam);
    if (error)
    if (error)
        goto bad;
        goto bad;
 
 
    if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTING)) {
    if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTING)) {
        m_freem(nam);
        m_freem(nam);
        return (EINPROGRESS);
        return (EINPROGRESS);
    }
    }
 
 
    s = splsoftnet();
    s = splsoftnet();
    while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0) {
    while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0) {
        error = tsleep((caddr_t)&so->so_timeo, PSOCK | PCATCH,
        error = tsleep((caddr_t)&so->so_timeo, PSOCK | PCATCH,
                       netcon, 0);
                       netcon, 0);
        if (error)
        if (error)
            break;
            break;
    }
    }
 
 
    if (error == 0) {
    if (error == 0) {
        error = so->so_error;
        error = so->so_error;
        so->so_error = 0;
        so->so_error = 0;
    }
    }
 
 
    splx(s);
    splx(s);
 
 
bad:
bad:
    so->so_state &= ~SS_ISCONNECTING;
    so->so_state &= ~SS_ISCONNECTING;
    m_freem(nam);
    m_freem(nam);
 
 
    return error;
    return error;
}
}
 
 
// -------------------------------------------------------------------------
// -------------------------------------------------------------------------
 
 
static int bsd_accept    ( cyg_file *fp, cyg_file *new_fp,
static int bsd_accept    ( cyg_file *fp, cyg_file *new_fp,
                           struct sockaddr *name, socklen_t *anamelen )
                           struct sockaddr *name, socklen_t *anamelen )
{
{
    struct mbuf *nam;
    struct mbuf *nam;
    socklen_t namelen = 0;
    socklen_t namelen = 0;
    int error = 0, s;
    int error = 0, s;
    register struct socket *so;
    register struct socket *so;
 
 
    if( anamelen != NULL )
    if( anamelen != NULL )
        namelen = *anamelen;
        namelen = *anamelen;
 
 
    s = splsoftnet();
    s = splsoftnet();
    so = (struct socket *)fp->f_data;
    so = (struct socket *)fp->f_data;
 
 
    if ((so->so_options & SO_ACCEPTCONN) == 0) {
    if ((so->so_options & SO_ACCEPTCONN) == 0) {
        splx(s);
        splx(s);
        return (EINVAL);
        return (EINVAL);
    }
    }
 
 
    if ((so->so_state & SS_NBIO) && so->so_qlen == 0) {
    if ((so->so_state & SS_NBIO) && so->so_qlen == 0) {
        splx(s);
        splx(s);
        return (EWOULDBLOCK);
        return (EWOULDBLOCK);
    }
    }
 
 
    while (so->so_qlen == 0 && so->so_error == 0) {
    while (so->so_qlen == 0 && so->so_error == 0) {
        if (so->so_state & SS_CANTRCVMORE) {
        if (so->so_state & SS_CANTRCVMORE) {
            so->so_error = ECONNABORTED;
            so->so_error = ECONNABORTED;
            break;
            break;
        }
        }
        error = tsleep((caddr_t)&so->so_timeo, PSOCK | PCATCH,
        error = tsleep((caddr_t)&so->so_timeo, PSOCK | PCATCH,
                       netcon, 0);
                       netcon, 0);
        if (error) {
        if (error) {
            splx(s);
            splx(s);
            return (error);
            return (error);
        }
        }
    }
    }
 
 
    if (so->so_error) {
    if (so->so_error) {
        error = so->so_error;
        error = so->so_error;
        so->so_error = 0;
        so->so_error = 0;
        splx(s);
        splx(s);
        return (error);
        return (error);
    }
    }
 
 
    {
    {
        struct socket *aso = so->so_q;
        struct socket *aso = so->so_q;
        if (soqremque(aso, 1) == 0)
        if (soqremque(aso, 1) == 0)
            panic("accept");
            panic("accept");
        so = aso;
        so = aso;
    }
    }
 
 
    cyg_selinit(&so->so_rcv.sb_sel);
    cyg_selinit(&so->so_rcv.sb_sel);
    cyg_selinit(&so->so_snd.sb_sel);
    cyg_selinit(&so->so_snd.sb_sel);
 
 
    new_fp->f_type      = DTYPE_SOCKET;
    new_fp->f_type      = DTYPE_SOCKET;
    new_fp->f_flag     |= FREAD|FWRITE;
    new_fp->f_flag     |= FREAD|FWRITE;
    new_fp->f_offset    = 0;
    new_fp->f_offset    = 0;
    new_fp->f_ops       = &bsd_sock_fileops;
    new_fp->f_ops       = &bsd_sock_fileops;
    new_fp->f_data      = (CYG_ADDRWORD)so;
    new_fp->f_data      = (CYG_ADDRWORD)so;
    new_fp->f_xops      = (CYG_ADDRWORD)&bsd_sockops;
    new_fp->f_xops      = (CYG_ADDRWORD)&bsd_sockops;
 
 
    nam = m_get(M_WAIT, MT_SONAME);
    nam = m_get(M_WAIT, MT_SONAME);
    (void) soaccept(so, nam);
    (void) soaccept(so, nam);
    if (name) {
    if (name) {
        if (namelen > nam->m_len)
        if (namelen > nam->m_len)
            namelen = nam->m_len;
            namelen = nam->m_len;
        /* SHOULD COPY OUT A CHAIN HERE */
        /* SHOULD COPY OUT A CHAIN HERE */
        if ((error = copyout(mtod(nam, caddr_t),
        if ((error = copyout(mtod(nam, caddr_t),
                             (caddr_t)name, namelen)) == 0)
                             (caddr_t)name, namelen)) == 0)
            *anamelen = namelen;
            *anamelen = namelen;
    }
    }
    m_freem(nam);
    m_freem(nam);
    splx(s);
    splx(s);
 
 
    return (error);
    return (error);
}
}
 
 
// -------------------------------------------------------------------------
// -------------------------------------------------------------------------
 
 
static int bsd_listen    ( cyg_file *fp, int backlog )
static int bsd_listen    ( cyg_file *fp, int backlog )
{
{
    return (solisten((struct socket *)fp->f_data, backlog));
    return (solisten((struct socket *)fp->f_data, backlog));
}
}
 
 
// -------------------------------------------------------------------------
// -------------------------------------------------------------------------
 
 
static int bsd_getname   ( cyg_file *fp, sockaddr *asa, socklen_t *alen, int peer )
static int bsd_getname   ( cyg_file *fp, sockaddr *asa, socklen_t *alen, int peer )
{
{
    register struct socket *so;
    register struct socket *so;
    struct mbuf *m;
    struct mbuf *m;
    socklen_t len = 0;
    socklen_t len = 0;
    int error;
    int error;
    int type = peer ? PRU_PEERADDR : PRU_SOCKADDR;
    int type = peer ? PRU_PEERADDR : PRU_SOCKADDR;
 
 
    if( alen != NULL )
    if( alen != NULL )
        len = *alen;
        len = *alen;
 
 
    so = (struct socket *)fp->f_data;
    so = (struct socket *)fp->f_data;
 
 
    if ( peer && (so->so_state & (SS_ISCONNECTED|SS_ISCONFIRMING)) == 0)
    if ( peer && (so->so_state & (SS_ISCONNECTED|SS_ISCONFIRMING)) == 0)
        return (ENOTCONN);
        return (ENOTCONN);
 
 
    m = m_getclr(M_WAIT, MT_SONAME);
    m = m_getclr(M_WAIT, MT_SONAME);
    if (m == NULL)
    if (m == NULL)
        return (ENOBUFS);
        return (ENOBUFS);
 
 
    error = (*so->so_proto->pr_usrreq)(so, type, 0, m, 0);
    error = (*so->so_proto->pr_usrreq)(so, type, 0, m, 0);
    if (error)
    if (error)
        goto bad;
        goto bad;
 
 
    if (len > m->m_len)
    if (len > m->m_len)
        len = m->m_len;
        len = m->m_len;
 
 
    error = copyout(mtod(m, caddr_t), (caddr_t)asa, len);
    error = copyout(mtod(m, caddr_t), (caddr_t)asa, len);
 
 
    if (error == 0)
    if (error == 0)
        *alen = len;
        *alen = len;
 
 
bad:
bad:
    m_freem(m);
    m_freem(m);
 
 
    return (error);
    return (error);
}
}
 
 
// -------------------------------------------------------------------------
// -------------------------------------------------------------------------
 
 
static int bsd_shutdown  ( cyg_file *fp, int how )
static int bsd_shutdown  ( cyg_file *fp, int how )
{
{
    return (soshutdown((struct socket *)fp->f_data, how));
    return (soshutdown((struct socket *)fp->f_data, how));
}
}
 
 
// -------------------------------------------------------------------------
// -------------------------------------------------------------------------
 
 
static int bsd_getsockopt( cyg_file *fp, int level, int optname,
static int bsd_getsockopt( cyg_file *fp, int level, int optname,
                           void *optval, socklen_t *optlen)
                           void *optval, socklen_t *optlen)
{
{
    struct mbuf *m = NULL;
    struct mbuf *m = NULL;
    socklen_t valsize = 0;
    socklen_t valsize = 0;
    int error;
    int error;
 
 
    if( optval != NULL && optlen != NULL )
    if( optval != NULL && optlen != NULL )
        valsize = *optlen;
        valsize = *optlen;
 
 
    error = sogetopt((struct socket *)fp->f_data, level, optname, &m);
    error = sogetopt((struct socket *)fp->f_data, level, optname, &m);
 
 
    if( error == ENOERR && valsize != 0 && m != NULL)
    if( error == ENOERR && valsize != 0 && m != NULL)
    {
    {
        if (valsize > m->m_len)
        if (valsize > m->m_len)
            valsize = m->m_len;
            valsize = m->m_len;
 
 
        error = copyout(mtod(m, caddr_t), optval, valsize);
        error = copyout(mtod(m, caddr_t), optval, valsize);
 
 
        if( error == ENOERR )
        if( error == ENOERR )
            *optlen = valsize;
            *optlen = valsize;
 
 
    }
    }
 
 
    if (m != NULL)
    if (m != NULL)
        (void) m_free(m);
        (void) m_free(m);
    return (error);
    return (error);
}
}
 
 
// -------------------------------------------------------------------------
// -------------------------------------------------------------------------
 
 
static int bsd_setsockopt( cyg_file *fp, int level, int optname,
static int bsd_setsockopt( cyg_file *fp, int level, int optname,
                           const void *optval, socklen_t optlen)
                           const void *optval, socklen_t optlen)
{
{
    int error;
    int error;
    struct mbuf *m = NULL;
    struct mbuf *m = NULL;
 
 
    if( optlen > MCLBYTES )
    if( optlen > MCLBYTES )
        return EINVAL;
        return EINVAL;
 
 
    if (optval != NULL) {
    if (optval != NULL) {
        m = m_get(M_WAIT, MT_SOOPTS);
        m = m_get(M_WAIT, MT_SOOPTS);
        if (optlen > MLEN) {
        if (optlen > MLEN) {
            MCLGET(m, M_DONTWAIT);
            MCLGET(m, M_DONTWAIT);
            if ((m->m_flags & M_EXT) == 0) {
            if ((m->m_flags & M_EXT) == 0) {
                m_freem(m);
                m_freem(m);
                return (ENOBUFS);
                return (ENOBUFS);
            }
            }
        }
        }
        if (m == NULL)
        if (m == NULL)
            return (ENOBUFS);
            return (ENOBUFS);
        error = copyin(optval, mtod(m, caddr_t), optlen);
        error = copyin(optval, mtod(m, caddr_t), optlen);
        if (error) {
        if (error) {
            (void) m_free(m);
            (void) m_free(m);
            return (error);
            return (error);
        }
        }
        m->m_len = optlen;
        m->m_len = optlen;
    }
    }
 
 
    return (sosetopt((struct socket *)fp->f_data, level, optname, m));
    return (sosetopt((struct socket *)fp->f_data, level, optname, m));
}
}
 
 
// -------------------------------------------------------------------------
// -------------------------------------------------------------------------
 
 
static int bsd_sendmsg   ( cyg_file *fp, const struct msghdr *m, int flags, ssize_t *retsize )
static int bsd_sendmsg   ( cyg_file *fp, const struct msghdr *m, int flags, ssize_t *retsize )
{
{
    return bsd_sendit( fp, m, flags, retsize);
    return bsd_sendit( fp, m, flags, retsize);
}
}
 
 
// -------------------------------------------------------------------------
// -------------------------------------------------------------------------
 
 
static int bsd_recvmsg   ( cyg_file *fp, struct msghdr *m, socklen_t *namelen, ssize_t *retsize )
static int bsd_recvmsg   ( cyg_file *fp, struct msghdr *m, socklen_t *namelen, ssize_t *retsize )
{
{
    return bsd_recvit( fp, m, namelen, retsize);
    return bsd_recvit( fp, m, namelen, retsize);
}
}
 
 
//==========================================================================
//==========================================================================
// File system call functions
// File system call functions
 
 
// -------------------------------------------------------------------------
// -------------------------------------------------------------------------
 
 
static int bsd_read      (struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio)
static int bsd_read      (struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio)
{
{
    return (soreceive((struct socket *)fp->f_data, (struct mbuf **)0,
    return (soreceive((struct socket *)fp->f_data, (struct mbuf **)0,
                      uio, (struct mbuf **)0, (struct mbuf **)0, (int *)0));
                      uio, (struct mbuf **)0, (struct mbuf **)0, (int *)0));
}
}
 
 
// -------------------------------------------------------------------------
// -------------------------------------------------------------------------
 
 
static int bsd_write     (struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio)
static int bsd_write     (struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio)
{
{
        return (sosend((struct socket *)fp->f_data, (struct mbuf *)0,
        return (sosend((struct socket *)fp->f_data, (struct mbuf *)0,
                uio, (struct mbuf *)0, (struct mbuf *)0, 0));
                uio, (struct mbuf *)0, (struct mbuf *)0, 0));
}
}
 
 
// -------------------------------------------------------------------------
// -------------------------------------------------------------------------
 
 
static int bsd_lseek     (struct CYG_FILE_TAG *fp, off_t *pos, int whence )
static int bsd_lseek     (struct CYG_FILE_TAG *fp, off_t *pos, int whence )
{
{
    return ESPIPE;
    return ESPIPE;
}
}
 
 
// -------------------------------------------------------------------------
// -------------------------------------------------------------------------
 
 
static int bsd_ioctl     (struct CYG_FILE_TAG *fp, CYG_ADDRWORD cmd,
static int bsd_ioctl     (struct CYG_FILE_TAG *fp, CYG_ADDRWORD cmd,
                                CYG_ADDRWORD data)
                                CYG_ADDRWORD data)
{
{
        register struct socket *so = (struct socket *)fp->f_data;
        register struct socket *so = (struct socket *)fp->f_data;
        void *p = 0;
        void *p = 0;
 
 
        switch (cmd) {
        switch (cmd) {
 
 
        case FIONBIO:
        case FIONBIO:
                if (*(int *)data)
                if (*(int *)data)
                        so->so_state |= SS_NBIO;
                        so->so_state |= SS_NBIO;
                else
                else
                        so->so_state &= ~SS_NBIO;
                        so->so_state &= ~SS_NBIO;
                return (0);
                return (0);
 
 
        case FIOASYNC:
        case FIOASYNC:
                if (*(int *)data) {
                if (*(int *)data) {
                        so->so_state |= SS_ASYNC;
                        so->so_state |= SS_ASYNC;
                        so->so_rcv.sb_flags |= SB_ASYNC;
                        so->so_rcv.sb_flags |= SB_ASYNC;
                        so->so_snd.sb_flags |= SB_ASYNC;
                        so->so_snd.sb_flags |= SB_ASYNC;
                } else {
                } else {
                        so->so_state &= ~SS_ASYNC;
                        so->so_state &= ~SS_ASYNC;
                        so->so_rcv.sb_flags &= ~SB_ASYNC;
                        so->so_rcv.sb_flags &= ~SB_ASYNC;
                        so->so_snd.sb_flags &= ~SB_ASYNC;
                        so->so_snd.sb_flags &= ~SB_ASYNC;
                }
                }
                return (0);
                return (0);
 
 
        case FIONREAD:
        case FIONREAD:
                *(int *)data = so->so_rcv.sb_cc;
                *(int *)data = so->so_rcv.sb_cc;
                return (0);
                return (0);
 
 
        case SIOCATMARK:
        case SIOCATMARK:
                *(int *)data = (so->so_state&SS_RCVATMARK) != 0;
                *(int *)data = (so->so_state&SS_RCVATMARK) != 0;
                return (0);
                return (0);
        }
        }
        /*
        /*
         * Interface/routing/protocol specific ioctls:
         * Interface/routing/protocol specific ioctls:
         * interface and routing ioctls should have a
         * interface and routing ioctls should have a
         * different entry since a socket's unnecessary
         * different entry since a socket's unnecessary
         */
         */
        if (IOCGROUP(cmd) == 'i')
        if (IOCGROUP(cmd) == 'i')
                return (ifioctl(so, (u_long)cmd, (caddr_t)data, p));
                return (ifioctl(so, (u_long)cmd, (caddr_t)data, p));
        if (IOCGROUP(cmd) == 'r')
        if (IOCGROUP(cmd) == 'r')
                return (rtioctl((u_long)cmd, (caddr_t)data, p));
                return (rtioctl((u_long)cmd, (caddr_t)data, p));
        return ((*so->so_proto->pr_usrreq)(so, PRU_CONTROL,
        return ((*so->so_proto->pr_usrreq)(so, PRU_CONTROL,
            (struct mbuf *)cmd, (struct mbuf *)data, (struct mbuf *)0));
            (struct mbuf *)cmd, (struct mbuf *)data, (struct mbuf *)0));
 
 
}
}
 
 
// -------------------------------------------------------------------------
// -------------------------------------------------------------------------
 
 
static int bsd_select    (struct CYG_FILE_TAG *fp, int which, CYG_ADDRWORD info)
static int bsd_select    (struct CYG_FILE_TAG *fp, int which, CYG_ADDRWORD info)
{
{
    register struct socket *so = (struct socket *)fp->f_data;
    register struct socket *so = (struct socket *)fp->f_data;
    register int s = splsoftnet();
    register int s = splsoftnet();
 
 
    switch (which) {
    switch (which) {
 
 
    case FREAD:
    case FREAD:
        if (soreadable(so)) {
        if (soreadable(so)) {
            splx(s);
            splx(s);
            return (1);
            return (1);
        }
        }
        cyg_selrecord(info, &so->so_rcv.sb_sel);
        cyg_selrecord(info, &so->so_rcv.sb_sel);
        so->so_rcv.sb_flags |= SB_SEL;
        so->so_rcv.sb_flags |= SB_SEL;
        break;
        break;
 
 
    case FWRITE:
    case FWRITE:
        if (sowriteable(so)) {
        if (sowriteable(so)) {
            splx(s);
            splx(s);
            return (1);
            return (1);
        }
        }
        cyg_selrecord(info, &so->so_snd.sb_sel);
        cyg_selrecord(info, &so->so_snd.sb_sel);
        so->so_snd.sb_flags |= SB_SEL;
        so->so_snd.sb_flags |= SB_SEL;
        break;
        break;
 
 
    case 0:
    case 0:
        if (so->so_oobmark || (so->so_state & SS_RCVATMARK)) {
        if (so->so_oobmark || (so->so_state & SS_RCVATMARK)) {
            splx(s);
            splx(s);
            return (1);
            return (1);
        }
        }
        cyg_selrecord(info, &so->so_rcv.sb_sel);
        cyg_selrecord(info, &so->so_rcv.sb_sel);
        so->so_rcv.sb_flags |= SB_SEL;
        so->so_rcv.sb_flags |= SB_SEL;
        break;
        break;
    }
    }
    splx(s);
    splx(s);
 
 
    return ENOERR;
    return ENOERR;
}
}
 
 
// -------------------------------------------------------------------------
// -------------------------------------------------------------------------
 
 
static int bsd_fsync     (struct CYG_FILE_TAG *fp, int mode )
static int bsd_fsync     (struct CYG_FILE_TAG *fp, int mode )
{
{
    // FIXME: call some sort of flush IOCTL?
    // FIXME: call some sort of flush IOCTL?
    return 0;
    return 0;
}
}
 
 
// -------------------------------------------------------------------------
// -------------------------------------------------------------------------
 
 
static int bsd_close     (struct CYG_FILE_TAG *fp)
static int bsd_close     (struct CYG_FILE_TAG *fp)
{
{
    int error = 0;
    int error = 0;
 
 
    if (fp->f_data)
    if (fp->f_data)
        error = soclose((struct socket *)fp->f_data);
        error = soclose((struct socket *)fp->f_data);
    fp->f_data = 0;
    fp->f_data = 0;
    return (error);
    return (error);
}
}
 
 
// -------------------------------------------------------------------------
// -------------------------------------------------------------------------
 
 
static int bsd_fstat     (struct CYG_FILE_TAG *fp, struct stat *buf )
static int bsd_fstat     (struct CYG_FILE_TAG *fp, struct stat *buf )
{
{
    register struct socket *so = (struct socket *)fp->f_data;
    register struct socket *so = (struct socket *)fp->f_data;
 
 
    bzero((caddr_t)buf, sizeof (*buf));
    bzero((caddr_t)buf, sizeof (*buf));
 
 
    // Mark socket as a fifo for now. We need to add socket types to
    // Mark socket as a fifo for now. We need to add socket types to
    // sys/stat.h.
    // sys/stat.h.
    buf->st_mode = __stat_mode_FIFO;
    buf->st_mode = __stat_mode_FIFO;
 
 
    return ((*so->so_proto->pr_usrreq)(so, PRU_SENSE,
    return ((*so->so_proto->pr_usrreq)(so, PRU_SENSE,
                                       (struct mbuf *)buf,
                                       (struct mbuf *)buf,
                                       (struct mbuf *)0,
                                       (struct mbuf *)0,
                                       (struct mbuf *)0));
                                       (struct mbuf *)0));
}
}
 
 
// -------------------------------------------------------------------------
// -------------------------------------------------------------------------
 
 
static int bsd_getinfo   (struct CYG_FILE_TAG *fp, int key, void *buf, int len )
static int bsd_getinfo   (struct CYG_FILE_TAG *fp, int key, void *buf, int len )
{
{
    return ENOSYS;
    return ENOSYS;
}
}
 
 
// -------------------------------------------------------------------------
// -------------------------------------------------------------------------
 
 
static int bsd_setinfo   (struct CYG_FILE_TAG *fp, int key, void *buf, int len )
static int bsd_setinfo   (struct CYG_FILE_TAG *fp, int key, void *buf, int len )
{
{
    return ENOSYS;
    return ENOSYS;
}
}
 
 
 
 
 
 
//==========================================================================
//==========================================================================
// Select support
// Select support
 
 
// -------------------------------------------------------------------------
// -------------------------------------------------------------------------
// This function is called by the lower layers to record the
// This function is called by the lower layers to record the
// fact that a particular 'select' event is being requested.
// fact that a particular 'select' event is being requested.
//
//
 
 
void
void
selrecord(void *selector, struct selinfo *info)
selrecord(void *selector, struct selinfo *info)
{
{
    // Unused by this implementation
    // Unused by this implementation
}
}
 
 
// -------------------------------------------------------------------------
// -------------------------------------------------------------------------
// This function is called to indicate that a 'select' event
// This function is called to indicate that a 'select' event
// may have occurred.
// may have occurred.
//
//
 
 
void
void
selwakeup(struct selinfo *info)
selwakeup(struct selinfo *info)
{
{
    cyg_selwakeup( info );
    cyg_selwakeup( info );
}
}
 
 
//==========================================================================
//==========================================================================
// Misc support functions
// Misc support functions
 
 
int
int
sockargs(mp, buf, buflen, type)
sockargs(mp, buf, buflen, type)
        struct mbuf **mp;
        struct mbuf **mp;
        caddr_t buf;
        caddr_t buf;
        socklen_t buflen;
        socklen_t buflen;
        int type;
        int type;
{
{
        register struct sockaddr *sa;
        register struct sockaddr *sa;
        register struct mbuf *m;
        register struct mbuf *m;
        int error;
        int error;
 
 
        if (buflen > MLEN) {
        if (buflen > MLEN) {
#ifdef COMPAT_OLDSOCK
#ifdef COMPAT_OLDSOCK
                if (type == MT_SONAME && buflen <= 112)
                if (type == MT_SONAME && buflen <= 112)
                        buflen = MLEN;          /* unix domain compat. hack */
                        buflen = MLEN;          /* unix domain compat. hack */
                else
                else
#endif
#endif
                return (EINVAL);
                return (EINVAL);
        }
        }
        m = m_get(M_WAIT, type);
        m = m_get(M_WAIT, type);
        if (m == NULL)
        if (m == NULL)
                return (ENOBUFS);
                return (ENOBUFS);
        m->m_len = buflen;
        m->m_len = buflen;
        error = copyin(buf, mtod(m, caddr_t), buflen);
        error = copyin(buf, mtod(m, caddr_t), buflen);
        if (error) {
        if (error) {
                (void) m_free(m);
                (void) m_free(m);
                return (error);
                return (error);
        }
        }
        *mp = m;
        *mp = m;
        if (type == MT_SONAME) {
        if (type == MT_SONAME) {
                sa = mtod(m, struct sockaddr *);
                sa = mtod(m, struct sockaddr *);
 
 
#if defined(COMPAT_OLDSOCK) && BYTE_ORDER != BIG_ENDIAN
#if defined(COMPAT_OLDSOCK) && BYTE_ORDER != BIG_ENDIAN
                if (sa->sa_family == 0 && sa->sa_len < AF_MAX)
                if (sa->sa_family == 0 && sa->sa_len < AF_MAX)
                        sa->sa_family = sa->sa_len;
                        sa->sa_family = sa->sa_len;
#endif
#endif
                sa->sa_len = buflen;
                sa->sa_len = buflen;
        }
        }
        return (0);
        return (0);
}
}
 
 
 
 
// -------------------------------------------------------------------------
// -------------------------------------------------------------------------
// bsd_recvit()
// bsd_recvit()
// Support for message reception. This is a lightly edited version of the
// Support for message reception. This is a lightly edited version of the
// recvit() function is uipc_syscalls.c.
// recvit() function is uipc_syscalls.c.
 
 
static int
static int
bsd_recvit(cyg_file *fp, struct msghdr *mp, socklen_t *namelenp, ssize_t *retsize)
bsd_recvit(cyg_file *fp, struct msghdr *mp, socklen_t *namelenp, ssize_t *retsize)
{
{
        struct uio auio;
        struct uio auio;
        register struct iovec *iov;
        register struct iovec *iov;
        register int i;
        register int i;
        size_t len;
        size_t len;
        int error;
        int error;
        struct mbuf *from = 0, *control = 0;
        struct mbuf *from = 0, *control = 0;
 
 
        auio.uio_iov = mp->msg_iov;
        auio.uio_iov = mp->msg_iov;
        auio.uio_iovcnt = mp->msg_iovlen;
        auio.uio_iovcnt = mp->msg_iovlen;
        auio.uio_segflg = UIO_USERSPACE;
        auio.uio_segflg = UIO_USERSPACE;
        auio.uio_rw = UIO_READ;
        auio.uio_rw = UIO_READ;
        auio.uio_offset = 0;                     /* XXX */
        auio.uio_offset = 0;                     /* XXX */
        auio.uio_resid = 0;
        auio.uio_resid = 0;
        iov = mp->msg_iov;
        iov = mp->msg_iov;
        for (i = 0; i < mp->msg_iovlen; i++, iov++) {
        for (i = 0; i < mp->msg_iovlen; i++, iov++) {
                /* Don't allow sum > SSIZE_MAX */
                /* Don't allow sum > SSIZE_MAX */
                if (iov->iov_len > SSIZE_MAX ||
                if (iov->iov_len > SSIZE_MAX ||
                    (auio.uio_resid += iov->iov_len) > SSIZE_MAX)
                    (auio.uio_resid += iov->iov_len) > SSIZE_MAX)
                        return (EINVAL);
                        return (EINVAL);
        }
        }
 
 
        len = auio.uio_resid;
        len = auio.uio_resid;
        error = soreceive((struct socket *)fp->f_data, &from, &auio,
        error = soreceive((struct socket *)fp->f_data, &from, &auio,
                          NULL, mp->msg_control ? &control : NULL,
                          NULL, mp->msg_control ? &control : NULL,
                          &mp->msg_flags);
                          &mp->msg_flags);
        if (error) {
        if (error) {
                if (auio.uio_resid != len &&
                if (auio.uio_resid != len &&
                    (error == EINTR || error == EWOULDBLOCK))
                    (error == EINTR || error == EWOULDBLOCK))
                        error = 0;
                        error = 0;
        }
        }
        if (error)
        if (error)
                goto out;
                goto out;
        *retsize = len - auio.uio_resid;
        *retsize = len - auio.uio_resid;
        if (mp->msg_name) {
        if (mp->msg_name) {
                len = mp->msg_namelen;
                len = mp->msg_namelen;
                if (len <= 0 || from == 0)
                if (len <= 0 || from == 0)
                        len = 0;
                        len = 0;
                else {
                else {
                        /* save sa_len before it is destroyed by MSG_COMPAT */
                        /* save sa_len before it is destroyed by MSG_COMPAT */
                        if (len > from->m_len)
                        if (len > from->m_len)
                                len = from->m_len;
                                len = from->m_len;
                        /* else if len < from->m_len ??? */
                        /* else if len < from->m_len ??? */
#ifdef COMPAT_OLDSOCK
#ifdef COMPAT_OLDSOCK
                        if (mp->msg_flags & MSG_COMPAT)
                        if (mp->msg_flags & MSG_COMPAT)
                                mtod(from, struct osockaddr *)->sa_family =
                                mtod(from, struct osockaddr *)->sa_family =
                                    mtod(from, struct sockaddr *)->sa_family;
                                    mtod(from, struct sockaddr *)->sa_family;
#endif
#endif
                        error = copyout(mtod(from, caddr_t),
                        error = copyout(mtod(from, caddr_t),
                            (caddr_t)mp->msg_name, (unsigned)len);
                            (caddr_t)mp->msg_name, (unsigned)len);
                        if (error)
                        if (error)
                                goto out;
                                goto out;
                }
                }
                mp->msg_namelen = len;
                mp->msg_namelen = len;
                if (namelenp ) {
                if (namelenp ) {
                        *namelenp = len;
                        *namelenp = len;
#ifdef COMPAT_OLDSOCK
#ifdef COMPAT_OLDSOCK
                        if (mp->msg_flags & MSG_COMPAT)
                        if (mp->msg_flags & MSG_COMPAT)
                                error = 0;       /* old recvfrom didn't check */
                                error = 0;       /* old recvfrom didn't check */
                        else
                        else
#endif
#endif
                        goto out;
                        goto out;
                }
                }
        }
        }
        if (mp->msg_control) {
        if (mp->msg_control) {
#ifdef COMPAT_OLDSOCK
#ifdef COMPAT_OLDSOCK
                /*
                /*
                 * We assume that old recvmsg calls won't receive access
                 * We assume that old recvmsg calls won't receive access
                 * rights and other control info, esp. as control info
                 * rights and other control info, esp. as control info
                 * is always optional and those options didn't exist in 4.3.
                 * is always optional and those options didn't exist in 4.3.
                 * If we receive rights, trim the cmsghdr; anything else
                 * If we receive rights, trim the cmsghdr; anything else
                 * is tossed.
                 * is tossed.
                 */
                 */
                if (control && mp->msg_flags & MSG_COMPAT) {
                if (control && mp->msg_flags & MSG_COMPAT) {
                        if (mtod(control, struct cmsghdr *)->cmsg_level !=
                        if (mtod(control, struct cmsghdr *)->cmsg_level !=
                            SOL_SOCKET ||
                            SOL_SOCKET ||
                            mtod(control, struct cmsghdr *)->cmsg_type !=
                            mtod(control, struct cmsghdr *)->cmsg_type !=
                            SCM_RIGHTS) {
                            SCM_RIGHTS) {
                                mp->msg_controllen = 0;
                                mp->msg_controllen = 0;
                                goto out;
                                goto out;
                        }
                        }
                        control->m_len -= sizeof (struct cmsghdr);
                        control->m_len -= sizeof (struct cmsghdr);
                        control->m_data += sizeof (struct cmsghdr);
                        control->m_data += sizeof (struct cmsghdr);
                }
                }
#endif
#endif
                len = mp->msg_controllen;
                len = mp->msg_controllen;
                if (len <= 0 || control == 0)
                if (len <= 0 || control == 0)
                        len = 0;
                        len = 0;
                else {
                else {
                        struct mbuf *m = control;
                        struct mbuf *m = control;
                        caddr_t p = (caddr_t)mp->msg_control;
                        caddr_t p = (caddr_t)mp->msg_control;
 
 
                        do {
                        do {
                                i = m->m_len;
                                i = m->m_len;
                                if (len < i) {
                                if (len < i) {
                                        mp->msg_flags |= MSG_CTRUNC;
                                        mp->msg_flags |= MSG_CTRUNC;
                                        i = len;
                                        i = len;
                                }
                                }
                                error = copyout(mtod(m, caddr_t), p,
                                error = copyout(mtod(m, caddr_t), p,
                                    (unsigned)i);
                                    (unsigned)i);
                                if (m->m_next)
                                if (m->m_next)
                                        i = ALIGN(i);
                                        i = ALIGN(i);
                                p += i;
                                p += i;
                                len -= i;
                                len -= i;
                                if (error != 0 || len <= 0)
                                if (error != 0 || len <= 0)
                                        break;
                                        break;
                        } while ((m = m->m_next) != NULL);
                        } while ((m = m->m_next) != NULL);
                        len = p - (caddr_t)mp->msg_control;
                        len = p - (caddr_t)mp->msg_control;
                }
                }
                mp->msg_controllen = len;
                mp->msg_controllen = len;
        }
        }
out:
out:
        if (from)
        if (from)
                m_freem(from);
                m_freem(from);
        if (control)
        if (control)
                m_freem(control);
                m_freem(control);
        return (error);
        return (error);
}
}
 
 
// -------------------------------------------------------------------------
// -------------------------------------------------------------------------
// sendit()
// sendit()
// Support for message transmission. This is a lightly edited version of the
// Support for message transmission. This is a lightly edited version of the
// synonymous function is uipc_syscalls.c.
// synonymous function is uipc_syscalls.c.
 
 
static int
static int
bsd_sendit(cyg_file *fp, const struct msghdr *mp, int flags, ssize_t *retsize)
bsd_sendit(cyg_file *fp, const struct msghdr *mp, int flags, ssize_t *retsize)
{
{
        struct uio auio;
        struct uio auio;
        register struct iovec *iov;
        register struct iovec *iov;
        register int i;
        register int i;
        struct mbuf *to, *control;
        struct mbuf *to, *control;
        int len, error;
        int len, error;
 
 
        auio.uio_iov = mp->msg_iov;
        auio.uio_iov = mp->msg_iov;
        auio.uio_iovcnt = mp->msg_iovlen;
        auio.uio_iovcnt = mp->msg_iovlen;
        auio.uio_segflg = UIO_USERSPACE;
        auio.uio_segflg = UIO_USERSPACE;
        auio.uio_rw = UIO_WRITE;
        auio.uio_rw = UIO_WRITE;
        auio.uio_offset = 0;                     /* XXX */
        auio.uio_offset = 0;                     /* XXX */
        auio.uio_resid = 0;
        auio.uio_resid = 0;
        iov = mp->msg_iov;
        iov = mp->msg_iov;
        for (i = 0; i < mp->msg_iovlen; i++, iov++) {
        for (i = 0; i < mp->msg_iovlen; i++, iov++) {
                /* Don't allow sum > SSIZE_MAX */
                /* Don't allow sum > SSIZE_MAX */
                if (iov->iov_len > SSIZE_MAX ||
                if (iov->iov_len > SSIZE_MAX ||
                    (auio.uio_resid += iov->iov_len) > SSIZE_MAX)
                    (auio.uio_resid += iov->iov_len) > SSIZE_MAX)
                        return (EINVAL);
                        return (EINVAL);
        }
        }
        if (mp->msg_name) {
        if (mp->msg_name) {
                error = sockargs(&to, mp->msg_name, mp->msg_namelen,
                error = sockargs(&to, mp->msg_name, mp->msg_namelen,
                                 MT_SONAME);
                                 MT_SONAME);
                if (error)
                if (error)
                        return (error);
                        return (error);
        } else
        } else
                to = 0;
                to = 0;
        if (mp->msg_control) {
        if (mp->msg_control) {
                if (mp->msg_controllen < sizeof(struct cmsghdr)
                if (mp->msg_controllen < sizeof(struct cmsghdr)
#ifdef COMPAT_OLDSOCK
#ifdef COMPAT_OLDSOCK
                    && mp->msg_flags != MSG_COMPAT
                    && mp->msg_flags != MSG_COMPAT
#endif
#endif
                ) {
                ) {
                        error = EINVAL;
                        error = EINVAL;
                        goto bad;
                        goto bad;
                }
                }
                error = sockargs(&control, mp->msg_control,
                error = sockargs(&control, mp->msg_control,
                                 mp->msg_controllen, MT_CONTROL);
                                 mp->msg_controllen, MT_CONTROL);
                if (error)
                if (error)
                        goto bad;
                        goto bad;
#ifdef COMPAT_OLDSOCK
#ifdef COMPAT_OLDSOCK
                if (mp->msg_flags == MSG_COMPAT) {
                if (mp->msg_flags == MSG_COMPAT) {
                        register struct cmsghdr *cm;
                        register struct cmsghdr *cm;
 
 
                        M_PREPEND(control, sizeof(*cm), M_WAIT);
                        M_PREPEND(control, sizeof(*cm), M_WAIT);
                        if (control == 0) {
                        if (control == 0) {
                                error = ENOBUFS;
                                error = ENOBUFS;
                                goto bad;
                                goto bad;
                        } else {
                        } else {
                                cm = mtod(control, struct cmsghdr *);
                                cm = mtod(control, struct cmsghdr *);
                                cm->cmsg_len = control->m_len;
                                cm->cmsg_len = control->m_len;
                                cm->cmsg_level = SOL_SOCKET;
                                cm->cmsg_level = SOL_SOCKET;
                                cm->cmsg_type = SCM_RIGHTS;
                                cm->cmsg_type = SCM_RIGHTS;
                        }
                        }
                }
                }
#endif
#endif
        } else
        } else
                control = 0;
                control = 0;
 
 
        len = auio.uio_resid;
        len = auio.uio_resid;
        error = sosend((struct socket *)fp->f_data, to, &auio,
        error = sosend((struct socket *)fp->f_data, to, &auio,
                       NULL, control, flags);
                       NULL, control, flags);
        if (error) {
        if (error) {
                if (auio.uio_resid != len &&
                if (auio.uio_resid != len &&
                    (error == EINTR || error == EWOULDBLOCK))
                    (error == EINTR || error == EWOULDBLOCK))
                        error = 0;
                        error = 0;
#ifndef __ECOS
#ifndef __ECOS
                if (error == EPIPE)
                if (error == EPIPE)
                        psignal(p, SIGPIPE);
                        psignal(p, SIGPIPE);
#endif
#endif
        }
        }
        if (error == 0)
        if (error == 0)
                *retsize = len - auio.uio_resid;
                *retsize = len - auio.uio_resid;
bad:
bad:
        if (to)
        if (to)
                m_freem(to);
                m_freem(to);
        return (error);
        return (error);
}
}
 
 
 
 
//==========================================================================
//==========================================================================
// End of sockio.c
// End of sockio.c
 
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.