uipc.p1 - part1 of part5
Bradley Smith
bes at holin.ATT.COM
Sun Aug 13 02:35:25 AEST 1989
: This is a shar archive. Extract with sh, not csh.
: This archive ends with exit, so do not worry about trailing junk.
if test -f 'src'
then rm 'src'
fi
if test -d 'src'
then :
else echo 'Making src/'
mkdir 'src'
fi
chmod 'u=rwx,g=rx,o=rx' 'src'
echo 'Extracting src/socket1.c'
sed 's/^X//' > src/socket1.c << '+ END-OF-FILE src/socket1.c'
X#ifndef LINT
Xstatic char * sccsdef = "@(#)socket1.c 1.1 (Alex Crain) 6/20/89";
X#endif
X
X/*
X * socket.c - high level socket routines
X *
X * Written by Alex Crain.
X *
X * This file is based in the Berkeley file uipc_socket.c,
X * but is *not* guarenteed to be in any way compatable. It is
X * close enough to the Berkeley code that the following applies...
X *
X * Copyright (c) 1982, 1986, 1988 Regents of the University of California.
X * All rights reserved.
X *
X * Redistribution and use in source and binary forms are permitted
X * provided that this notice is preserved and that due credit is given
X * to the University of California at Berkeley. The name of the University
X * may not be used to endorse or promote products derived from this
X * software without specific prior written permission. This software
X * is provided "as is" without express or implied warranty.
X *
X */
X
X#include <sys/types.h>
X#include <sys/param.h>
X#include <sys/systm.h>
X#include <sys/user.h>
X#include <sys/proc.h>
X#include <sys/file.h>
X#include <sys/var.h>
X#include <sys/errno.h>
X#include <uipc/mbuf.h>
X#include <uipc/socket.h>
X#include <uipc/socketvar.h>
X#include <uipc/domain.h>
X#include <uipc/protosw.h>
X#include <uipc/fproto.h>
X
X
Xint
Xsocreate (domain, sop, type, proto)
X int domain;
X struct socket ** sop;
X int type, proto;
X{
X register struct protosw * prp;
X struct socket * so;
X struct mbuf * m;
X int error = 0;
X
X if (proto)
X prp = pffindproto (domain, proto, type);
X else
X prp = pffindtype (domain, type);
X
X if (prp == 0)
X return EPROTONOSUPPORT;
X
X if (prp->pr_type != type)
X return EPROTOTYPE;
X
X m = m_getclr (M_WAIT, MT_SOCKET);
X so = mtod (m, struct socket *);
X
X so->so_options = 0;
X so->so_state = (suser () ? SS_PRIV : 0);
X so->so_type = type;
X so->so_proto = prp;
X
X if (error = (* prp->pr_usrreq) (so, PRU_ATTACH, (struct mbuf *) 0,
X (struct mbuf *) proto, (struct mbuf *) 0))
X {
X so->so_state |= SS_NOFDREF;
X sofree(so);
X return error;
X }
X * sop = so;
X return 0;
X}
X
Xint
Xsobind (so, nam)
X struct socket * so;
X struct mbuf * nam;
X{
X int s = splnet ();
X int error = (* so->so_proto->pr_usrreq) (so, PRU_BIND,
X (struct mbuf *) 0, nam, (struct mbuf *) 0);
X
X splx (s);
X return error;
X}
X
Xint
Xsolisten (so, backlog)
X struct socket * so;
X int backlog;
X{
X int s = splnet ();
X int error;
X if (error = (* so->so_proto->pr_usrreq) (so, PRU_LISTEN,
X (struct mbuf *) 0, (struct mbuf *) 0, (struct mbuf *) 0))
X goto bad;
X if (so->so_q == 0)
X {
X so->so_q = so;
X so->so_q0 = so;
X so->so_options |= SO_ACCEPTCONN;
X }
X
X if (backlog < 0)
X backlog = 0;
X so->so_qlimit = MIN (backlog, SOMAXCONN);
X bad:
X splx (s);
X return error;
X}
X
Xvoid
Xsofree (so)
X struct socket * so;
X{
X if (so->so_pcb || (so->so_state & SS_NOFDREF) == 0)
X return;
X if (so->so_head)
X {
X if (! soqremque (so, 0) && ! soqremque (so, 1))
X panic ("sofree dq");
X so->so_head = 0;
X }
X sbrelease (&so->so_snd);
X sorflush (so);
X (void) m_free (dtom (so));
X}
X
Xint
Xsoclose (so)
X struct socket * so;
X{
X int s = splnet ();
X int error = 0;
X
X if (so->so_options & SO_ACCEPTCONN)
X {
X while (so->so_q0 != so)
X (void) soabort (so->so_q0);
X while (so->so_q != so)
X (void) soabort (so->so_q);
X }
X if (so->so_pcb == 0)
X goto discard;
X if (so->so_state & SS_ISCONNECTED)
X {
X if ((so->so_state & SS_ISDISCONNECTING) == 0)
X if (error = sodisconnect (so))
X goto drop;
X if (so->so_options & SO_LINGER)
X {
X if ((so->so_state & SS_ISDISCONNECTING) &&
X (so->so_state & SS_NBIO))
X goto drop;
X while (so->so_state & SS_ISCONNECTED)
X (void) sleep ((caddr_t) &so->so_timeo, PZERO + 1);
X }
X }
X
X drop:
X if (so->so_pcb)
X {
X int error2 = (* so->so_proto->pr_usrreq) (so, PRU_DETACH,
X (struct mbuf *) 0, (struct mbuf *) 0, (struct mbuf *) 0);
X if (error == 0)
X error = error2;
X }
X
X discard:
X if (so->so_state & SS_NOFDREF)
X panic ("soclose: NODEREF");
X so->so_state |= SS_NOFDREF;
X sofree (so);
X splx (s);
X return error;
X}
X
Xint
Xsoabort (so)
X struct socket * so;
X{
X return (* so->so_proto->pr_usrreq) (so, PRU_ABORT,
X (struct mbuf *) 0, (struct mbuf *) 0, (struct mbuf *) 0);
X}
X
Xint
Xsoaccept (so, nam)
X struct socket * so;
X struct mbuf * nam;
X{
X int s = splnet ();
X int error;
X
X if ((so->so_state & SS_NOFDREF) == 0)
X panic ("soaccept: !NOFDREF");
X so->so_state &= ~SS_NOFDREF;
X error = (* so->so_proto->pr_usrreq) (so, PRU_ACCEPT,
X (struct mbuf *) 0, nam, (struct mbuf *) 0);
X splx (s);
X return (error);
X}
X
Xint
Xsoconnect (so, nam)
X struct socket * so;
X struct mbuf * nam;
X{
X int s;
X int error;
X
X if (so->so_options & SO_ACCEPTCONN)
X return EOPNOTSUPP;
X s = splnet ();
X if (so->so_state & (SS_ISCONNECTED | SS_ISCONNECTING) &&
X ((so->so_proto->pr_flags & PR_CONNREQUIRED) ||
X (error = sodisconnect (so))))
X error = EISCONN;
X else
X error = (* so->so_proto->pr_usrreq) (so, PRU_CONNECT,
X (struct mbuf *) 0, nam, (struct mbuf *) 0);
X splx (s);
X return error;
X}
X
Xint
Xsoconnect2 (so1, so2)
X struct socket * so1, * so2;
X{
X int s = splnet ();
X int error = (* so1->so_proto->pr_usrreq) (so1, PRU_CONNECT2,
X (struct mbuf *) 0, (struct mbuf *) so2, (struct mbuf *) 0);
X splx (s);
X return error;
X}
X
Xint
Xsodisconnect (so)
X struct socket * so;
X{
X int s = splnet ();
X int error;
X
X if ((so->so_state & SS_ISCONNECTED) == 0)
X {
X error = ENOTCONN;
X goto bad;
X }
X if (so->so_state & SS_ISDISCONNECTING)
X {
X error = EALREADY;
X goto bad;
X }
X error = (* so->so_proto->pr_usrreq) (so, PRU_DISCONNECT,
X (struct mbuf *) 0, (struct mbuf *) 0, (struct mbuf *) 0);
X bad:
X splx (s);
X return error;
X}
X
Xint
Xsosend (so, nam, flags, rights)
X struct socket * so;
X struct mbuf * nam;
X int flags;
X struct mbuf * rights;
X{
X int space, s, rlen = 0, dontroute;
X int len, error = 0, first = 1;
X struct mbuf ** mb, * top = 0, * m;
X
X /*
X * barf if we want to send one big chunk and don't have the space.
X */
X if (sendallatonce (so) && u.u_count > so->so_snd.sb_hiwat)
X return (EMSGSIZE);
X
X dontroute = (flags & MSG_DONTROUTE) &&
X (so->so_options & SO_DONTROUTE) == 0 &&
X (so->so_proto->pr_flags & PR_ATOMIC);
X
X if (rights)
X rlen = rights->m_len;
X
X#define snderr(errno) { error = errno; splx (s); goto release; }
X
X restart:
X sblock (&so->so_snd);
X
X do {
X s = splnet ();
X
X /* check out our basic requirements. */
X
X if (so->so_state & SS_CANTSENDMORE)
X snderr (EPIPE);
X
X if (so->so_error)
X {
X error = so->so_error;
X so->so_error = 0;
X splx (s);
X goto release;
X }
X
X if ((so->so_state & SS_ISCONNECTED) == 0)
X {
X if (so->so_proto->pr_flags & PR_CONNREQUIRED)
X snderr (ENOTCONN);
X if (nam == 0)
X snderr (EDESTADDRREQ);
X }
X if (flags & MSG_OOB)
X space = 1024;
X else
X {
X space = sbspace (&so->so_snd);
X
X /*
X * If we need more room, wait for it.
X */
X if (space <= rlen ||
X sendallatonce (so) && space < u.u_count + rlen)
X {
X if (so->so_state & SS_NBIO)
X {
X if (first)
X error = EWOULDBLOCK;
X splx (s);
X goto release;
X }
X sbunlock (&so->so_snd);
X sbwait (&so->so_snd);
X splx (s);
X goto restart;
X }
X }
X
X splx (s);
X
X
X /*
X * We have the room, we've done sanity checks.
X * Now make an mbuf chain out of our data, waiting if necessarry.
X */
X mb = ⊤
X space -= rlen;
X while (space > 0 && u.u_count)
X {
X MGET (m, M_WAIT, MT_DATA);
X len = MIN (MIN (MLEN, u.u_count), space);
X space -= len;
X iomove (mtod (m, caddr_t), len, IO_WRITE);
X m->m_len = len;
X * mb = m;
X if (error = u.u_error)
X goto release;
X mb = &m->m_next;
X#ifdef DEBUG
X dump_mbuf(m,"sosendit");
X#endif
X }
X if (dontroute)
X so->so_options |= SO_DONTROUTE;
X
X /*
X * write mbuf to socket.
X */
X s = splnet ();
X error = (* so->so_proto->pr_usrreq) (so,
X (flags & MSG_OOB) ? PRU_SENDOOB : PRU_SEND,
X top, (caddr_t) nam, rights);
X splx (s);
X if (dontroute)
X so->so_options &= ~SO_DONTROUTE;
X rights = top = (struct mbuf *) 0;
X rlen = first = 0;
X } while (error == 0 && u.u_count);
X
X release:
X sbunlock (&so->so_snd);
X
X if(select_sleep) {
X select_sleep = 0;
X wakeup((caddr_t) &select_sleep_addr);
X }
X
X if (top)
X m_freem (top);
X if (error == EPIPE)
X psignal (u.u_procp, SIGPIPE);
X return error;
X}
X
Xint
Xsoreceive (so, nam, flags, rights)
X struct socket * so;
X struct mbuf ** nam;
X int flags;
X struct mbuf ** rights;
X{
X struct mbuf * m, * nextrecord;
X int len, error = 0, s, moff, offset;
X struct protosw * pr = so->so_proto;
X
X if (rights)
X * rights = (struct mbuf *) 0; /* if we have a rights, zero it */
X if (nam)
X * nam = (struct mbuf *) 0; /* zero from buffer address */
X if (flags & MSG_OOB)
X {
X m = m_get (M_WAIT, MT_DATA);
X if (error = (* pr->pr_usrreq) (so, PRU_RCVOOB, m,
X (struct mbuf *) (flags & MSG_PEEK),
X (struct mbuf *) 0))
X goto bad;
X do {
X len = MIN (u.u_count, m->m_len);
X iomove (mtod (m, caddr_t), len, IO_READ);
X m = m_free (m);
X } while (u.u_count && (error = u.u_error) == 0 && m);
X bad:
X if (m)
X m_freem (m);
X return error;
X }
X
X#ifdef DEBUG
X dump_mbuf (dtom (so),"sorecieve");
X#endif
X restart:
X sblock (&so->so_rcv);
X s = splnet ();
X
X if (so->so_rcv.sb_cc == 0) /* if there is no chars in buffer */
X {
X if (so->so_error) /* if there is an error affecting connection */
X {
X error = so->so_error;
X so->so_error = 0;
X goto release;
X }
X/* if ((so->so_state & SS_ISCONNECTED) == 0 &&
X (pr->pr_flags & PR_CONNREQUIRED))
X {
X error = ENOTCONN;
X goto release;
X } */
X if (so->so_state & SS_CANTRCVMORE || u.u_count == 0)
X goto release;
X if (so->so_state & SS_NBIO) /* if nonblocking return EWOULDBLOCK */
X {
X error = EWOULDBLOCK;
X goto release;
X }
X sbunlock (&so->so_rcv);
X sbwait (&so->so_rcv);
X splx (s);
X goto restart;
X }
X
X /* this checks the mbuf chain to see if there is data */
X if ((m = so->so_rcv.sb_mb) == (struct mbuf *) 0)
X panic ("receive 1");
X nextrecord = m->m_act;
X if (pr->pr_flags & PR_ADDR)
X {
X if (m->m_type != MT_SONAME)
X panic ("receive 1a");
X if (flags & MSG_PEEK)
X {
X if (nam)
X * nam = m_copy (m, 0, m->m_len);
X m = m->m_next;
X }
X else
X {
X sbfree (&so->so_rcv, m);
X if (nam)
X {
X * nam = m;
X m = m->m_next;
X (* nam)->m_next = (struct mbuf *) 0;
X so->so_rcv.sb_mb = m;
X }
X else
X {
X MFREE (m, so->so_rcv.sb_mb);
X m = so->so_rcv.sb_mb;
X }
X if (m)
X m->m_act = nextrecord;
X }
X }
X if (m && m->m_type == MT_RIGHTS)
X {
X if ((pr->pr_flags & PR_RIGHTS) == 0)
X panic ("receive 2");
X if (flags & MSG_PEEK)
X {
X if (rights)
X * rights = m_copy (m, 0, m->m_len);
X m = m->m_next;
X }
X else
X {
X sbfree (&so->so_rcv, m);
X if (rights)
X {
X * rights = m;
X so->so_rcv.sb_mb = m->m_next;
X m->m_next = (struct mbuf *) 0;
X m = so->so_rcv.sb_mb;
X }
X else
X {
X MFREE (m, so->so_rcv.sb_mb);
X m = so->so_rcv.sb_mb;
X }
X if (m)
X m->m_act = nextrecord;
X }
X }
X moff = 0;
X offset = 0;
X while (m && u.u_count != 0 && error == 0)
X {
X if (m->m_type != MT_DATA && m->m_type != MT_HEADER)
X panic ("receive 3");
X len = u.u_count;
X so->so_state &= ~SS_RCVATMARK;
X if (so->so_oobmark && len > so->so_oobmark - offset)
X len = so->so_oobmark - offset;
X if (len > m->m_len - moff)
X len = m->m_len - moff;
X splx (s);
X
X iomove (mtod (m, caddr_t) + moff, (int) len, IO_READ);
X error = u.u_error;
X
X s = splnet ();
X if (len == m->m_len - moff)
X {
X if (flags & MSG_PEEK)
X {
X m = m->m_next;
X moff = 0;
X }
X else
X {
X nextrecord = m->m_act;
X sbfree (&so->so_rcv, m);
X MFREE (m, so->so_rcv.sb_mb);
X if (m = so->so_rcv.sb_mb)
X m->m_act = nextrecord;
X }
X }
X else
X {
X if (flags & MSG_PEEK)
X moff += len;
X else
X {
X m->m_off += len;
X m->m_len -= len;
X so->so_rcv.sb_cc -= len;
X }
X }
X if (so->so_oobmark)
X {
X if ((flags & MSG_PEEK) == 0)
X {
X so->so_oobmark -= len;
X if (so->so_oobmark == 0)
X {
X so->so_state |= SS_RCVATMARK;
X break;
X }
X }
X else
X offset += len;
X }
X }
X if ((flags & MSG_PEEK) == 0)
X {
X if (m == 0)
X so->so_rcv.sb_mb = nextrecord;
X else if (pr->pr_flags & PR_ATOMIC)
X (void) sbdroprecord (&so->so_rcv);
X if (pr->pr_flags & PR_WANTRCVD && so->so_pcb)
X (* pr->pr_usrreq) (so, PRU_RCVD, (struct mbuf *) 0,
X (struct mbuf *) 0, (struct mbuf *) 0);
X if (error == 0 && rights && * rights &&
X pr->pr_domain->dom_externalize)
X error = (* pr->pr_domain->dom_externalize) (* rights);
X }
X
X release:
X sbunlock (&so->so_rcv);
X splx (s);
X return error;
X}
X
Xvoid
Xsorflush (so)
X struct socket * so;
X{
X struct sockbuf * sb = &so->so_rcv;
X struct protosw * pr = so->so_proto;
X int s;
X struct sockbuf asb;
X
X sblock (sb);
X s = splimp ();
X socantrcvmore (so);
X sbunlock (sb);
X
X if(select_sleep) {
X select_sleep = 0;
X wakeup((caddr_t) &select_sleep_addr);
X }
X
X asb = * sb;
X bzero ((caddr_t) sb, sizeof (* sb));
X splx (s);
X if (pr->pr_flags & PR_RIGHTS && pr->pr_domain->dom_dispose)
X (* pr->pr_domain->dom_dispose) (asb.sb_mb);
X sbrelease (&asb);
X}
X
Xint
Xsosetopt (so, level, optname, m0)
X struct socket * so;
X int level, optname;
X struct mbuf * m0;
X{
X int error = 0;
X struct mbuf * m = m0;
X
X if (level != SOL_SOCKET)
X {
X if (so->so_proto && so->so_proto->pr_ctloutput)
X return (* so->so_proto->pr_ctloutput)
X (PRCO_SETOPT, so, level, optname, &m0);
X error = ENOPROTOOPT;
X }
X else
X {
X switch (optname)
X {
X case SO_LINGER:
X if (m == NULL || m->m_len != sizeof (struct linger))
X {
X error = EINVAL;
X goto bad;
X }
X so->so_linger = mtod (m, struct linger *)->l_linger;
X /* fall through ... */
X
X case SO_DEBUG:
X case SO_KEEPALIVE:
X case SO_DONTROUTE:
X case SO_USELOOPBACK:
X case SO_BROADCAST:
X case SO_REUSEADDR:
X case SO_OOBINLINE:
X if (m == (struct mbuf *) 0 || m->m_len < sizeof (int))
X {
X error = EINVAL;
X goto bad;
X }
X if (* mtod (m, int *))
X so->so_options |= optname;
X else
X so->so_options &= ~optname;
X break;
X
X case SO_SNDBUF:
X case SO_RCVBUF:
X case SO_SNDLOWAT:
X case SO_RCVLOWAT:
X case SO_SNDTIMEO:
X case SO_RCVTIMEO:
X
X if (m == (struct mbuf *) 0 || m->m_len < sizeof (int))
X {
X error = EINVAL;
X goto bad;
X }
X switch (optname)
X {
X case SO_SNDBUF:
X if (sbreserve (&so->so_rcv, * mtod (m, int *)) == 0)
X {
X error = ENOBUFS;
X goto bad;
X }
X break;
X
X case SO_RCVBUF:
X if (sbreserve (&so->so_rcv, * mtod (m, int *)) == 0)
X {
X error = ENOBUFS;
X goto bad;
X }
X break;
X
X case SO_SNDLOWAT:
X so->so_snd.sb_lowat = * mtod (m, int *);
X break;
X
X case SO_RCVLOWAT:
X so->so_rcv.sb_lowat = * mtod (m, int *);
X break;
X
X case SO_SNDTIMEO:
X so->so_snd.sb_timeo = * mtod (m, int *);
X break;
X
X case SO_RCVTIMEO:
X so->so_rcv.sb_timeo = * mtod (m, int *);
X break;
X }
X break;
X
X default:
X error = ENOPROTOOPT;
X break;
X }
X }
X bad:
X if (m)
X (void) m_free (m);
X return error;
X}
X
Xint
Xsogetopt (so, level, optname, mp)
X struct socket * so;
X int level, optname;
X struct mbuf ** mp;
X{
X struct mbuf * m;
X
X if (level != SOL_SOCKET)
X {
X if (so->so_proto && so->so_proto->pr_ctloutput)
X return (* so->so_proto->pr_ctloutput)
X (PRCO_GETOPT, so, level, optname, mp);
X else
X return ENOPROTOOPT;
X }
X else
X {
X m = m_get (M_WAIT, MT_SOOPTS);
X m->m_len = sizeof (int);
X
X switch (optname)
X {
X case SO_LINGER:
X m->m_len = sizeof (struct linger);
X mtod (m, struct linger *)->l_onoff = so->so_options & SO_LINGER;
X mtod (m, struct linger *)->l_linger = so->so_linger;
X break;
X
X
X case SO_DEBUG:
X case SO_KEEPALIVE:
X case SO_DONTROUTE:
X case SO_USELOOPBACK:
X case SO_BROADCAST:
X case SO_REUSEADDR:
X case SO_OOBINLINE:
X * mtod (m, int *) = so->so_options & optname;
X break;
X
X case SO_TYPE:
X * mtod (m, int *) = so->so_type;
X break;
X
X case SO_ERROR:
X * mtod (m, int *) = so->so_error;
X break;
X
X case SO_SNDBUF:
X * mtod (m, int *) = so->so_snd.sb_hiwat;
X break;
X
X case SO_RCVBUF:
X * mtod (m, int *) = so->so_rcv.sb_hiwat;
X break;
X
X case SO_SNDLOWAT:
X * mtod (m, int *) = so->so_snd.sb_lowat;
X break;
X
X case SO_RCVLOWAT:
X * mtod (m, int *) = so->so_rcv.sb_lowat;
X break;
X
X case SO_SNDTIMEO:
X * mtod (m, int *) = so->so_snd.sb_timeo;
X break;
X
X case SO_RCVTIMEO:
X * mtod (m, int *) = so->so_rcv.sb_timeo;
X break;
X
X default:
X (void) m_free (m);
X return ENOPROTOOPT;
X }
X * mp = m;
X return 0;
X }
X}
X
Xvoid
Xsohasoutofband (so)
X struct socket * so;
X{
X struct proc * p;
X
X if (so->so_pgrp < 0)
X signal (-so->so_pgrp, SIGURG);
X else if (so->so_pgrp)
X for (p = proc; p < (struct proc *) v.ve_proc; p = p->p_xlink)
X if (p->p_pid == so->so_pgrp)
X {
X psignal (p, SIGURG);
X break;
X }
X#ifdef SB_COLL
X if (so->so_rcv.sb_sel)
X {
X selwakeup (so->so_rcv.sb_sel, so->so_rcv.sb_flags & SB_COLL);
X so->so_rcv,sb_sel = 0;
X so->so_rcv.sb_flags &= ~SB_COLL;
X }
X#endif
X}
+ END-OF-FILE src/socket1.c
chmod 'u=rw,g=rw,o=rw' 'src/socket1.c'
echo ' -rw-rw-rw- 1 bes HSJ 18033 Aug 12 12:27 src/socket1.c (as sent)'
echo ' \c'
/bin/ls -l src/socket1.c
echo 'Extracting src/socket2.c'
sed 's/^X//' > src/socket2.c << '+ END-OF-FILE src/socket2.c'
X#ifndef LINT
Xstatic char * sccsdef = "@(#)socket2.c 1.1 (Alex Crain) 6/20/89";
X#endif
X
X/*
X * socket2.c - low level socket routines
X *
X * Written by Alex Crain.
X *
X * This file is based in the Berkeley file uipc_socket2.c,
X * but is *not* guarenteed to be in any way compatable. It is
X * close enough to the Berkeley code that the following applies...
X *
X * Copyright (c) 1982, 1986, 1988 Regents of the University of California.
X * All rights reserved.
X *
X * Redistribution and use in source and binary forms are permitted
X * provided that this notice is preserved and that due credit is given
X * to the University of California at Berkeley. The name of the University
X * may not be used to endorse or promote products derived from this
X * software without specific prior written permission. This software
X * is provided "as is" without express or implied warranty.
X *
X */
X
X
X#include <sys/types.h>
X#include <sys/param.h>
X#include <sys/systm.h>
X#include <sys/errno.h>
X#include <sys/proc.h>
X#include <sys/var.h>
X#include <uipc/mbuf.h>
X#include <uipc/socket.h>
X#include <uipc/socketvar.h>
X#include <uipc/protosw.h>
X#include <uipc/domain.h>
X#include <uipc/fproto.h>
X
Xvoid
Xsoisconnecting (so)
X struct socket * so;
X{
X so->so_state &= ~(SS_ISCONNECTED | SS_ISDISCONNECTING);
X so->so_state |= SS_ISCONNECTING;
X wakeup ((caddr_t) &so->so_timeo);
X}
X
Xvoid
Xsoisconnected (so)
X struct socket * so;
X{
X struct socket * head = so->so_head;
X
X if (head)
X {
X if (soqremque (so, 0) == 0)
X panic ("soisconnected");
X soinsque (head, so, 1);
X sorwakeup (head);
X wakeup ((caddr_t) &head->so_timeo);
X }
X
X so->so_state &= ~(SS_ISCONNECTING | SS_ISDISCONNECTING);
X so->so_state |= SS_ISCONNECTED;
X wakeup ((caddr_t) &so->so_timeo);
X sorwakeup (so);
X sowwakeup (so);
X}
X
Xvoid
Xsoisdisconnecting (so)
X struct socket * so;
X{
X so->so_state &= ~SS_ISCONNECTING;
X so->so_state |= (SS_ISDISCONNECTING | SS_CANTRCVMORE | SS_CANTSENDMORE);
X wakeup ((caddr_t) &so->so_timeo);
X sorwakeup (so);
X sowwakeup (so);
X}
X
Xvoid
Xsoisdisconnected (so)
X struct socket * so;
X{
X so->so_state &= ~(SS_ISCONNECTING | SS_ISCONNECTED | SS_ISDISCONNECTING);
X so->so_state |= (SS_CANTRCVMORE | SS_CANTSENDMORE);
X wakeup ((caddr_t) &so->so_timeo);
X sorwakeup (so);
X sowwakeup (so);
X}
X
Xstruct socket *
Xsonewconn (head)
X struct socket * head;
X{
X struct socket * so;
X struct mbuf * m;
X
X if (head->so_qlen + head->so_q0len > 3 * head->so_qlimit / 2)
X goto bad;
X if ((m = m_getclr(M_DONTWAIT, MT_SOCKET)) == (struct mbuf *) 0)
X goto bad;
X so = mtod (m, struct socket *);
X so->so_type = head->so_type;
X so->so_options = head->so_options & ~SO_ACCEPTCONN;
X so->so_linger = head->so_linger;
X so->so_state = head->so_state | SS_NOFDREF;
X so->so_proto = head->so_proto;
X so->so_timeo = head->so_timeo;
X so->so_pgrp = head->so_pgrp;
X soinsque (head, so, 0);
X if ((* so->so_proto->pr_usrreq) (so, PRU_ATTACH,
X (struct mbuf *) 0, (struct mbuf *) 0, (struct mbuf *) 0))
X {
X (void) soqremque (so, 0);
X (void) m_free (m);
X goto bad;
X }
X return (so);
X bad:
X return (struct socket *) 0;
X}
X
Xvoid
Xsoinsque (head, so, q)
X struct socket * head, * so;
X int q;
X{
X so->so_head = head;
X if (q == 0)
X {
X head->so_q0len++;
X so->so_q0 = head->so_q0;
X head->so_q0 = so;
X }
X else
X {
X head->so_qlen++;
X so->so_q = head->so_q;
X head->so_q = so;
X }
X}
X
Xint
Xsoqremque (so, q)
X struct socket * so;
X int q;
X{
X struct socket * head, * prev, * next;
X
X head = so->so_head;
X prev = head;
X for (;;)
X {
X next = q ? prev->so_q : prev->so_q0;
X if (next == so)
X break;
X if (next == head)
X return 0;
X prev = next;
X }
X if (q == 0)
X {
X prev->so_q0 = next->so_q0;
X head->so_q0len--;
X }
X else
X {
X prev->so_q = next->so_q;
X head->so_qlen--;
X }
X next->so_q0 = next->so_q = 0;
X next->so_head = 0;
X return 1;
X}
X
Xvoid
Xsocantsendmore (so)
X struct socket * so;
X{
X so->so_state |= SS_CANTSENDMORE;
X sowwakeup (so);
X}
X
Xvoid
Xsocantrcvmore (so)
X struct socket * so;
X{
X so->so_state |= SS_CANTRCVMORE;
X sorwakeup (so);
X}
X
X#ifdef SB_COLL
Xvoid
Xsbselqueue (sb)
X struct sockbuf * sb;
X{
X struct proc * p;
X
X if ((p = sb->sb_sel) && p->p_wchan == (caddr_t) &selwait)
X sb->sb_flags |= SB_COLL;
X else
X sb->sb_sel = u.u_procp;
X}
X#endif
X
Xvoid
Xsbwait (sb)
X struct sockbuf * sb;
X{
X sb->sb_flags |= SB_WAIT;
X (void) sleep ((caddr_t) &sb->sb_cc, PZERO + 1);
X}
X
Xvoid
Xsbwakeup (sb)
X struct sockbuf * sb;
X{
X#ifdef SB_COLL
X if (sb->sb_sel)
X {
X selwakeup (sb->sb_sel, sb->sb_flags & SB_COLL);
X sb->sb_sel = 0;
X sb->sb_flags &= ~SB_COLL;
X }
X#endif
X if (sb->sb_flags & SB_WAIT)
X {
X sb->sb_flags &= ~SB_WAIT;
X wakeup ((caddr_t) &sb->sb_cc);
X }
X}
X
X/* ARGSUSED */
Xvoid
Xsowakeup (so, sb)
X struct socket * so;
X struct sockbuf * sb;
X{
X struct proc * p;
X
X sbwakeup (sb);
X
X if (so->so_state & SS_ASYNC)
X {
X if (so->so_pgrp < 0)
X signal (-so->so_pgrp, SIGIO);
X else if (so->so_pgrp)
X for (p = proc; p < (struct proc *) v.ve_proc; p = p->p_xlink)
X if (p->p_pid == so->so_pgrp)
X {
X psignal (p, SIGURG);
X break;
X }
X }
X}
X
X/*
X * Socket buffer utiliy routines.
X */
X
Xint
Xsoreserve (so, sndcc, rcvcc)
X struct socket * so;
X int sndcc, rcvcc;
X{
X if (sbreserve (&so->so_snd, sndcc) == 0)
X goto bad1;
X if (sbreserve (&so->so_rcv, rcvcc) == 0)
X goto bad2;
X return 0;
X bad2:
X sbrelease (&so->so_snd);
X bad1:
X return ENOBUFS;
X}
X
X/*
X * Reserve mbufs for a socketbuf.
X */
X
Xint
Xsbreserve (sb, cc)
X struct sockbuf * sb;
X{
X sb->sb_hiwat = cc;
X sb->sb_mbmax = cc * 2;
X return 1;
X}
X
Xvoid
Xsbrelease (sb)
X struct sockbuf * sb;
X{
X sbflush (sb);
X sb->sb_hiwat = sb->sb_mbmax = 0;
X}
X
Xvoid
Xsbappend (sb, m)
X struct sockbuf * sb;
X struct mbuf * m;
X{
X struct mbuf * n;
X
X if (m == 0)
X return;
X if (n = sb->sb_mb)
X {
X while (n->m_act)
X n = n->m_act;
X while (n->m_next)
X n = n->m_next;
X }
X sbcompress (sb, m, n);
X}
X
Xvoid
Xsbappendrecord (sb, m0)
X struct sockbuf * sb;
X struct mbuf * m0;
X{
X struct mbuf * m;
X
X if (m0 == 0)
X return;
X
X if (m = sb->sb_mb)
X while (m->m_act)
X m = m->m_act;
X
X sballoc (sb, m0);
X if (m)
X m->m_act = m0;
X else
X sb->sb_mb = m0;
X m = m0->m_next;
X m0->m_next = 0;
X sbcompress (sb, m, m0);
X}
X
Xint
Xsbappendaddr (sb, asa, m0, rights0)
X struct sockbuf * sb;
X struct sockaddr * asa;
X struct mbuf * rights0, * m0;
X{
X struct mbuf * m, * n;
X int space = sizeof (* asa);
X
X for (m = m0; m; m = m->m_next)
X space += m->m_len;
X if (rights0)
X space += rights0->m_len;
X if (space > sbspace (sb))
X return 0;
X MGET (m, M_DONTWAIT, MT_SONAME);
X if (m == 0)
X return 0;
X * mtod (m, struct sockaddr *) = * asa;
X m->m_len = sizeof (* asa);
X if (rights0 && rights0->m_len)
X {
X if ((m->m_next = m_copy (rights0, 0, rights0->m_len)) == 0)
X {
X m_freem (m);
X return 0;
X }
X sballoc (sb, m->m_next);
X }
X sballoc (sb, m);
X if (n = sb->sb_mb)
X {
X while (n->m_act)
X n = n->m_act;
X n->m_act = m;
X }
X else
X sb->sb_mb = m;
X if (m->m_next)
X m = m->m_next;
X if (m0)
X sbcompress (sb, m0, m);
X return 1;
X}
X
Xint
Xsbappendrights (sb, m0, rights)
X struct sockbuf * sb;
X struct mbuf * rights, * m0;
X{
X struct mbuf * m, * n;
X int space = 0;
X
X if (rights == 0)
X panic ("sbappendrights");
X for (m = m0; m; m = m->m_next)
X space += m->m_len;
X space += rights->m_len;
X if (space > sbspace (sb))
X return 0;
X if ((m = m_copy (rights, 0, rights->m_len)) == 0)
X return 0;
X sballoc (sb, m);
X if (n = sb->sb_mb)
X {
X while (n->m_act)
X n = n->m_act;
X n->m_act = m;
X }
X else
X sb->sb_mb = m;
X if (m0)
X sbcompress (sb, m0, m);
X return 1;
X}
X
Xvoid
Xsbcompress (sb, m, n)
X struct sockbuf * sb;
X struct mbuf * m, * n;
X{
X while (m)
X {
X if (m->m_len == 0)
X {
X m = m_free (m);
X continue;
X }
X if (n && n->m_off <= MMAXOFF && m->m_off <= MMAXOFF &&
X (n->m_off + n->m_len + m->m_len <= MMAXOFF &&
X n->m_type == m->m_type))
X {
X bcopy (mtod (m, caddr_t), mtod (n, caddr_t) + n->m_len,
X (unsigned) m->m_len);
X n->m_len += m->m_len;
X sb->sb_cc += m->m_len;
X m = m_free (m);
X continue;
X }
X sballoc (sb, m);
X if (n)
X n->m_next = m;
X else
X sb->sb_mb = m;
X n = m;
X m = m->m_next;
X n->m_next = 0;
X }
X}
X
Xvoid
Xsbflush (sb)
X struct sockbuf * sb;
X{
X if (sb->sb_flags & SB_LOCK)
X panic ("sbflush");
X while (sb->sb_mbcnt)
X sbdrop (sb, (int) sb->sb_cc);
X if (sb->sb_cc || sb->sb_mbcnt || sb->sb_mb)
X panic ("sbflush 2");
X}
X
X/*
X * Throw away len bytes from sb, starting at the beginning.
X */
X
Xvoid
Xsbdrop (sb, len)
X struct sockbuf * sb;
X int len;
X{
X register struct mbuf * m, * mn;
X struct mbuf * next;
X
X next = (m = sb->sb_mb) ? m->m_act : 0;
X
X while (len > 0)
X {
X if (m == 0)
X {
X if (next == 0)
X panic ("sbdrop");
X m = next;
X next = m->m_act;
X continue;
X }
X
X if (m->m_len > len)
X {
X m->m_len -= len;
X m->m_off += len;
X sb->sb_cc -= len;
X break;
X }
X
X len -= m->m_len;
X sbfree (sb, m);
X MFREE (m, mn);
X m = mn;
X }
X
X while (m && m->m_len == 0) /* when is this case necessary? */
X {
X sbfree (sb, m);
X MFREE (m, mn);
X m = mn;
X }
X
X if (m)
X {
X sb->sb_mb = m;
X m->m_act = next;
X }
X else
X sb->sb_mb = next;
X}
X
Xvoid
Xsbdroprecord (sb)
X struct sockbuf * sb;
X{
X struct mbuf * m, * mn;
X
X m = sb->sb_mb;
X if (m)
X {
X sb->sb_mb = m->m_act;
X do
X {
X sbfree (sb, m);
X MFREE (m, mn);
X }
X while (m - mn);
X }
X}
+ END-OF-FILE src/socket2.c
chmod 'u=rw,g=rw,o=rw' 'src/socket2.c'
echo ' -rw-rw-rw- 1 bes HSJ 9907 Aug 12 12:27 src/socket2.c (as sent)'
echo ' \c'
/bin/ls -l src/socket2.c
echo 'Extracting src/syscalls.c'
sed 's/^X//' > src/syscalls.c << '+ END-OF-FILE src/syscalls.c'
X#ifndef LINT
Xstatic char * sccsdef = "@(#)syscalls.c 1.1 (Alex Crain) 6/20/89";
X#endif
X
X/*
X * syscalls.c - system call kernal interface routines.
X *
X * Written by Alex Crain.
X *
X * This file is based in the Berkeley file uipc_syscalls.c,
X * but is *not* guarenteed to be in any way compatable. It is
X * close enough to the Berkeley code that the following applies...
X *
X * Copyright (c) 1982, 1986, 1988 Regents of the University of California.
X * All rights reserved.
X *
X * Redistribution and use in source and binary forms are permitted
X * provided that this notice is preserved and that due credit is given
X * to the University of California at Berkeley. The name of the University
X * may not be used to endorse or promote products derived from this
X * software without specific prior written permission. This software
X * is provided "as is" without express or implied warranty.
X *
X */
X
X#include <sys/types.h>
X#include <sys/param.h>
X#include <sys/systm.h>
X#include <sys/user.h>
X#include <sys/file.h>
X#include <sys/buf.h>
X#include <sys/errno.h>
X#include <sys/systm.h>
X#include <sys/tty.h>
X#include <uipc/mbuf.h>
X#include <uipc/socket.h>
X#include <uipc/socketvar.h>
X#include <uipc/domain.h>
X#include <uipc/protosw.h>
X#include <uipc/un.h>
X#include <uipc/fproto.h>
X#include <uipc/pty.h>
X
Xstruct file * getsock ();
X
X/*
X * socket (domain, type, protocol)
X *
X * Create a socket and add it to the processes open file table. This involves
X * some creativity, because the file structure is really too small for our
X * uses. The kernal only knows about inodes, so there is no f_type slot.
X * Instead, the kernal looks for a NULL f_inode, which means that we are a
X * socket. Unfortunately, this means that there is no room in the file
X * structure for the socket address, so we keep all of our sockets in a linear
X * table, and store the table offset in f_offset, which has no meaning here
X * anyway. (see the macros filesock() and sockoffet() in conf.h).
X */
X
Xint select_sleep; /* value to say if we need to wakeup */
Xint select_sleep_addr; /* address we select on if wait in select */
X/*
X * this is hard coded righ now....for test only...soon it will be
X * loaded in at boot time so that it is not hard coded
X */
Xint so_win_major = 0; /* major device of window */
Xunsigned int so_win_tty = 0; /* address of wintty */
X
Xsosetup() /* setup variables */
X{
X register struct a {
X int w_major;
X unsigned int w_tty;
X } * uap = (struct a *) u.u_ap;
X
X so_win_major = uap->w_major;
X so_win_tty = uap->w_tty;
X}
X
Xsoselect ()
X{
X register struct a {
X int nfds;
X int *readfds;
X int *writefds;
X int *execptfds;
X } * uap = (struct a *) u.u_ap;
X int i,mask, cnt, *rds;
X int k,l, j;
X struct file *fp;
X struct inode *ip;
X struct tty *tp;
X struct socket *so;
X
X rds = uap->readfds;
X if(rds) { /* have readbitmask */
X for(cnt=0,i=0;i < uap->nfds; i++) {
X u.u_error = 0; /* reset it */
X mask = 1 << i;
X if(*rds & mask) { /* is this one? */
X fp = getsock(i);
X if(fp != 0) { /* valid socket */
X so = filesock(fp);
X if((so->so_rcv.sb_mb != 0) &&
X (so->so_rcv.sb_cc != 0)) {
X /* has buffer & has chars */
X cnt++;
X } else {
X *rds &= ~mask;
X }
X } else if((fp = getf(i)) != 0) { /* valid open file */
X ip = fp->f_inode;
X if(major(ip->i_rdev) == pty_major) {
X /* got a pty file descriptor */
X if(Master(ip->i_rdev) == True) {
X /* get slot in tty table */
X k = minor(ip->i_rdev) - PTYCNT;
X tp = &pts_tty[k]; /* ok */
X }else { /* normal slot */
X k = minor(ip->i_rdev) - PTYCNT;
X tp = &pts_tty[k]; /* ok */
X }
X /* check buffer address */
X if(tp->t_tbuf.c_count) {
X /* ok to read */
X cnt++;
X }else {
X *rds &= ~mask;
X }
X }else if(major(ip->i_rdev) == so_win_major) {
X /* got a window file descriptor */
X /* take off 1 for aligment */
X k = minor(ip->i_rdev) - 1;
X k *= sizeof(struct tty);
X tp = (struct tty *) (unsigned) (so_win_tty + k);
X /* check buffer */
X k = tp->t_rawq.c_cc;
X if(k)
X cnt++;
X else
X *rds &= ~mask;
X
X } else {
X *rds &= ~mask;
X }
X } else {
X *rds &= ~mask;
X }
X }
X }
X }
X if(cnt) {
X u.u_rval1 = cnt;
X return;
X }
X select_sleep = 1;
X /* sleep until worked up */
X sleep( (caddr_t) &select_sleep_addr, PZERO+1 );
X /* we are here so we let it know that we are ready */
X u.u_rval1 = 0;
X return;
X}
X
Xsocket ()
X{
X register struct a {
X int domain;
X int type;
X int proto;
X } * uap = (struct a *) u.u_ap;
X
X struct socket * so;
X struct file *fp;
X
X if ((fp = falloc ((struct inode *) 0, FREAD| FWRITE)) == NULL)
X return;
X
X if (u.u_error = socreate (uap->domain, &so, uap->type, uap->proto))
X goto bad;
X
X fp->f_offset = sockoffset (so);
X return;
X
X bad:
X u.u_ofile[u.u_rval1] = 0;
X fp->f_count = 0;
X fp->f_next = ffreelist;
X ffreelist = fp;
X}
X
Xbind ()
X{
X struct a {
X int s;
X caddr_t name;
X int namelen;
X } * uap = (struct a *) u.u_ap;
X
X struct file * fp;
X struct mbuf * nam;
X
X if ((fp = getsock (uap->s)) == 0)
X return;
X
X if (u.u_error = sockargs (&nam, uap->name, uap->namelen, MT_SONAME))
X return;
X
X u.u_error = sobind (filesock (fp), nam);
X m_freem (nam);
X}
X
Xlisten ()
X{
X struct a {
X int s;
X int backlog;
X } * uap = (struct a *) u.u_ap;
X struct file * fp;
X
X if ((fp = getsock (uap->s)) == 0)
X return;
X
X u.u_error = solisten (filesock (fp), uap->backlog);
X}
X
Xaccept ()
X{
X struct a {
X int s;
X caddr_t name;
X int * anamelen;
X } * uap = (struct a *) u.u_ap;
X struct file * fp;
X struct mbuf * nam;
X int namelen;
X int s;
X struct socket * so;
X
X if (uap->name == 0)
X goto noname;
X
X if (u.u_error = copyin ((caddr_t) uap->anamelen, (caddr_t) &namelen,
X sizeof (namelen)))
X return;
X
X if (useracc ((caddr_t) uap->name, (u_int) namelen, UACC_WRITE) == 0)
X {
X u.u_error = EFAULT;
X return;
X }
X
X noname:
X if ((fp = getsock (uap->s)) == 0)
X return;
X s = splnet ();
X so = filesock (fp);
X if ((so->so_options & SO_ACCEPTCONN) == 0)
X {
X u.u_error = EINVAL;
X goto bad;
X }
X if ((so->so_state & SS_NBIO) && so->so_qlen == 0)
X {
X u.u_error = EWOULDBLOCK;
X goto bad;
X }
X while (so->so_qlen == 0 && so->so_error == 0)
X {
X if (so->so_state & SS_CANTRCVMORE)
X {
X so->so_error = ECONNABORTED;
X break;
X }
X sleep ((caddr_t) &so->so_timeo, PZERO+1);
X }
X
X if (so->so_error)
X {
X u.u_error = so->so_error;
X so->so_error = 0;
X goto bad;
X }
X
X if ((fp = falloc ((struct inode *) 0, FREAD| FWRITE)) == 0)
X goto bad;
X else
X {
X struct socket * so2 = so->so_q;
X if (soqremque (so2, 1) == 0)
X panic ("accept");
X so = so2;
X }
X
X fp->f_offset = sockoffset (so);
X nam = m_get (M_WAIT, MT_SONAME);
X (void) soaccept (so, nam);
X
X if (uap->name)
X {
X if (namelen > nam->m_len)
X namelen = nam->m_len;
X (void) copyout (mtod (nam, caddr_t), (caddr_t) uap->name,
X (u_int) namelen);
X (void) copyout ((caddr_t) &namelen, (caddr_t) uap->anamelen,
X sizeof (*uap->anamelen));
X }
X m_freem (nam);
X
X bad:
X splx (s);
X return;
X}
X
Xconnect ()
X{
X struct a {
X int s;
X caddr_t name;
X int namelen;
X } * uap = (struct a *) u.u_ap;
X struct file * fp;
X struct socket * so;
X struct mbuf * nam;
X int s;
X
X if ((fp = getsock (uap->s)) == 0)
X return;
X
X so = filesock (fp);
X
X if ((so->so_state & SS_NBIO) &&
X (so->so_state & SS_ISCONNECTING))
X {
X u.u_error = EALREADY;
X return;
X }
X
X if (u.u_error = sockargs (&nam, uap->name, uap->namelen, MT_SONAME))
X return;
X
X if (u.u_error = soconnect (so, nam))
X goto bad;
X
X if ((so->so_state & SS_NBIO) &&
X (so->so_state & SS_ISCONNECTING))
X {
X u.u_error = EINPROGRESS;
X m_freem (nam);
X return;
X }
X
X s = splnet ();
X
X if (setjmp (u.u_qsav))
X {
X if (u.u_error == 0)
X u.u_error = EINTR;
X goto bad2;
X }
X
X while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0)
X sleep ((caddr_t) &so->so_timeo, PZERO + 1);
X
X u.u_error = so->so_error;
X so->so_error = 0;
X
X bad2:
X splx (s);
X
X bad:
X so->so_state &= ~SS_ISCONNECTING;
X m_freem (nam);
X}
X
Xsocketpair ()
X{
X struct a {
X int domain;
X int type;
X int proto;
X int * rsv;
X } * uap = (struct a *) u.u_ap;
X
X register struct file * fp1, * fp2;
X struct socket * so1, * so2;
X int sv[2];
X
X /*
X * verify that uap->rsv is in the users address space & writeable.
X * UACC_READ and UACC_WRITE are defined in <uipc/conf.h>.
X */
X if (useracc ((caddr_t) uap->rsv, sizeof (int) * 2, UACC_WRITE) == 0)
X {
X u.u_error = EFAULT;
X return;
X }
X
X /*
X * Create some sockets (2).
X */
X if (u.u_error = socreate (uap->domain, &so1, uap->type, uap->proto))
X return;
X
X if (u.u_error = socreate (uap->domain, &so2, uap->type, uap->proto))
X goto free1;
X
X /*
X * assign them to file structures in the open file table.
X */
X if ((fp1 = falloc ((struct inode *) 0, FREAD | FWRITE)) == NULL)
X goto free2;
X sv[0] = u.u_rval1;
X fp1->f_offset = sockoffset (so1);
X
X if ((fp2 = falloc ((struct inode *) 0, FREAD | FWRITE)) == NULL)
X goto free3;
X sv[1] = u.u_rval1;
X fp2->f_offset = sockoffset (so2);
X
X /*
X * Connect them together.
X */
X
X if (u.u_error = soconnect2 (so1, so2))
X goto free4;
X
X /*
X * DATAGRAMS need to be connected both ways
X */
X if (uap->type == SOCK_DGRAM)
X if (u.u_error = soconnect2 (so2, so1))
X goto free4;
X
X /*
X * done, return 0 and pass the file descriptors back.
X */
X u.u_rval1 = 0;
X copyout ((caddr_t) sv, (caddr_t) uap->rsv, 2 * sizeof (int));
X return;
X
X free4:
X fp2->f_count = 0;
X fp2->f_next = ffreelist;
X ffreelist = fp2;
X
X free3:
X fp1->f_count = 0;
X fp1->f_next = ffreelist;
X ffreelist = fp1;
X
X free2:
X (void) soclose (so2);
X
X free1:
X (void) soclose (so1);
X}
X
Xsendto ()
X{
X struct a {
X int s;
X caddr_t buf;
X int len;
X int flags;
X caddr_t to;
X int tolen;
X } * uap = (struct a *) u.u_ap;
X
X struct msghdr msg;
X
X msg.msg_name = uap->to;
X msg.msg_namelen = uap->tolen;
X msg.msg_accrights = (caddr_t) 0;
X msg.msg_accrightslen = 0;
X
X u.u_base = uap->buf;
X u.u_count = uap->len;
X u.u_segflg = 0;
X
X sendit (uap->s, &msg, uap->flags);
X}
X
Xsend ()
X{
X struct a {
X int s;
X caddr_t buf;
X int len;
X int flags;
X } * uap = (struct a *) u.u_ap;
X
X struct msghdr msg;
X
X msg.msg_name = (caddr_t) 0;
X msg.msg_namelen = 0;
X msg.msg_accrights = (caddr_t) 0;
X msg.msg_accrightslen = 0;
X
X u.u_base = uap->buf;
X u.u_count = uap->len;
X u.u_segflg = 0;
X
X sendit (uap->s, &msg, uap->flags);
X}
X
Xvoid
Xsendit (s, mp, flags)
X int s;
X struct msghdr * mp;
X int flags;
X{
X struct file * fp;
X struct mbuf * to, * rights;
X
X if ((fp = getsock (s)) == 0)
X return;
X
X if (u.u_count != 0 && useracc (u.u_base, u.u_count, UACC_READ) == 0)
X {
X u.u_error = EFAULT;
X return;
X }
X
X if (mp->msg_name)
X {
X if (u.u_error = sockargs (&to, mp->msg_name, mp->msg_namelen,MT_SONAME))
X return;
X }
X else
X to = (struct mbuf *) 0;
X
X if (mp->msg_accrights)
X {
X if (u.u_error = sockargs (&to, mp->msg_accrights, mp->msg_accrightslen,
X MT_SONAME))
X goto bad;
X }
X else
X rights = (struct mbuf *) 0;
X
X u.u_error = sosend (filesock (fp), to, flags, rights);
X
X if (rights)
X m_freem (rights);
X
X bad:
X if (to)
X m_freem (to);
X}
X
Xrecvfrom ()
X{
X struct a {
X int s;
X caddr_t buf;
X int len;
X int flags;
X caddr_t from;
X int * fromlenaddr;
X } * uap = (struct a *) u.u_ap;
X
X struct msghdr msg;
X
X msg.msg_name = uap->from;
X if (u.u_error = copyin ((caddr_t) uap->fromlenaddr,
X (caddr_t) &msg.msg_namelen,
X sizeof (msg.msg_namelen)))
X return;
X
X msg.msg_accrights = (caddr_t) 0;
X msg.msg_accrightslen = 0;
X
X u.u_base = uap->buf;
X u.u_count = uap->len;
X u.u_segflg = 0;
X
X recvit (uap->s, &msg, uap->flags, (caddr_t) uap->fromlenaddr, (caddr_t) 0);
X}
X
Xrecv ()
X{
X struct a {
X int s;
X caddr_t buf;
X int len;
X int flags;
X } * uap = (struct a *) u.u_ap;
X
X struct msghdr msg;
X
X msg.msg_name = (caddr_t) 0;
X msg.msg_namelen = 0;
X msg.msg_accrights = (caddr_t) 0;
X msg.msg_accrightslen = 0;
X
X u.u_base = uap->buf;
X u.u_count = uap->len;
X u.u_segflg = 0;
X
X recvit (uap->s, &msg, uap->flags, (caddr_t) 0, (caddr_t) 0);
X}
X
Xvoid
Xrecvit (s, mp, flags, namelenp, rightslenp)
X int s;
X struct msghdr * mp;
X int flags;
X caddr_t namelenp, rightslenp;
X{
X struct file * fp;
X struct mbuf * from, * rights;
X int len;
X
X if ((fp = getsock (s)) == 0)
X return;
X
X if (u.u_count != 0 && useracc (u.u_base, u.u_count, UACC_WRITE) == 0)
X {
X u.u_error = EFAULT;
X return;
X }
X
X u.u_error = soreceive (filesock (fp), &from, flags, &rights);
X
X if (mp->msg_name)
X {
X len = mp->msg_namelen;
X if (len <= 0 || from == (struct mbuf *) 0)
X len = 0;
X else
X {
X if (len > from->m_len)
X len = from->m_len;
X (void) copyout ((caddr_t) mtod (from, caddr_t),
X (caddr_t) mp->msg_name, (unsigned) len);
X }
X (void) copyout ((caddr_t) &len, namelenp, sizeof (int));
X }
X
X if (mp->msg_accrights)
X {
X len = mp->msg_accrightslen;
X if (len <= 0 || rights == (struct mbuf *) 0)
X len = 0;
X else
X {
X if (len > rights->m_len)
X len = rights->m_len;
X (void) copyout ((caddr_t) mtod (rights, caddr_t),
X (caddr_t) mp->msg_accrights, (unsigned) len);
X }
X (void) copyout ((caddr_t) &len, rightslenp, sizeof (int));
X }
X
X if (rights)
X m_freem (rights);
X if (from)
X m_freem (from);
X}
X
Xsetsockopt ()
X{
X struct a {
X int s;
X int level;
X int name;
X caddr_t val;
X int valsize;
X } * uap = (struct a *) u.u_ap;
X struct file * fp;
X struct mbuf * m = (struct mbuf *) 0;
X
X if ((fp = getsock (uap->s)) == 0)
X return;
X
X if (uap->valsize > MLEN)
X {
X u.u_error = EINVAL;
X return;
X }
X if (uap->val)
X {
X m = m_get (M_WAIT, MT_SOOPTS);
X if (m == (struct mbuf *) 0)
X {
X u.u_error = ENOBUFS;
X return;
X }
X if (u.u_error = copyin (uap->val, mtod (m, caddr_t),
X (u_int) uap->valsize))
X {
X (void) m_freem (m);
X return;
X }
X m->m_len = uap->valsize;
X }
X u.u_error = sosetopt (filesock (fp), uap->level, uap->name, m);
X}
X
Xgetsockopt ()
X{
X struct a {
X int s;
X int level;
X int name;
X caddr_t val;
X int * avalsize;
X } * uap = (struct a *) u.u_ap;
X struct file * fp;
X struct mbuf * m = (struct mbuf *) 0;
X int valsize;
X
X if ((fp = getsock (uap->s)) == 0)
X return;
X
X if (uap->val)
X {
X if (u.u_error = copyin ((caddr_t) uap->avalsize, (caddr_t) &valsize,
X sizeof (valsize)))
X return;
X }
X else
X valsize = 0;
X
X if (u.u_error = sogetopt (filesock (fp), uap->level, uap->name, &m))
X goto bad;
X
X if (uap->val && valsize && m != (struct mbuf *) 0)
X {
X if (valsize > m->m_len)
X valsize = m->m_len;
X if (u.u_error = copyout (mtod (m, caddr_t), uap->val, (u_int) valsize))
X goto bad;
X u.u_error = copyout ((caddr_t) &valsize, (caddr_t) uap->avalsize,
X sizeof (valsize));
X }
X bad:
X if (m != (struct mbuf *) 0)
X (void) m_freem (m);
X}
X
Xsockpipe ()
X{
X register struct file * fpr, * fpw;
X struct socket * sor, * sow;
X int r;
X
X /*
X * Create some sockets (2).
X */
X if (u.u_error = socreate (AF_UNIX, &sor, SOCK_STREAM, 0))
X return;
X
X if (u.u_error = socreate (AF_UNIX, &sow, SOCK_STREAM, 0))
X goto free1;
X
X /*
X * assign them to file structures in the open file table.
X */
X if ((fpr = falloc ((struct inode *) 0, FREAD | FWRITE)) == NULL)
X goto free2;
X fpr->f_offset = sockoffset (sor);
X r = u.u_rval1;
X
X if ((fpw = falloc ((struct inode *) 0, FREAD | FWRITE)) == NULL)
X goto free3;
X fpw->f_offset = sockoffset (sow);
X u.u_rval2 = u.u_rval1;
X u.u_rval1 = r;
X
X /*
X * Connect them together.
X */
X
X if (u.u_error = unp_connect2 (sow, sor))
X goto free4;
X
X /*
X * Close one direction.
X */
X
X sor->so_state |= SS_CANTSENDMORE;
X sow->so_state |= SS_CANTRCVMORE;
X return;
X
X free4:
X fpw->f_count = 0;
X fpw->f_next = ffreelist;
X ffreelist = fpw;
X
X free3:
X fpr->f_count = 0;
X fpr->f_next = ffreelist;
X ffreelist = fpr;
X
X free2:
X (void) soclose (sow);
X
X free1:
X (void) soclose (sor);
X}
X
Xvoid
Xgetsockname ()
X{
X struct a {
X int fdes;
X caddr_t asa;
X int * alen;
X } * uap = (struct a *) u.u_ap;
X struct file * fp;
X struct socket * so;
X struct mbuf * m;
X int len;
X
X if ((fp = getsock (uap->fdes)) == 0)
X return;
X if (u.u_error = copyin ((caddr_t) uap->alen, (caddr_t) &len, sizeof (len)))
X return;
X so = filesock (fp);
X if ((m = m_getclr (M_WAIT, MT_SONAME)) == (struct mbuf *) 0)
X {
X u.u_error = ENOBUFS;
X return;
X }
X if (u.u_error = (* so->so_proto->pr_usrreq) (so, PRU_SOCKADDR,
X (struct mbuf *) 0, m, (struct mbuf *) 0))
X goto bad;
X if (len > m->m_len)
X len = m->m_len;
X if (u.u_error = copyout (mtod (m, caddr_t), (caddr_t) uap->asa,
X (u_int) len))
X goto bad;
X u.u_error = copyout ((caddr_t) &len, (caddr_t) uap->alen,
X sizeof (len));
X bad:
X m_freem (m);
X}
X
X
X/*
X * System call helper functions
X */
X
Xint
Xsockargs (aname, name, namelen, type)
X struct mbuf ** aname;
X caddr_t name;
X int namelen, type;
X{
X struct mbuf * m;
X int error;
X
X if (namelen > MLEN)
X return EINVAL;
X
X if ((m = m_get (M_WAIT, type)) == NULL)
X return ENOBUFS;
X
X m->m_len = namelen;
X
X if (error = copyin (name, mtod (m, caddr_t), (u_int) namelen))
X (void) m_free (m);
X else
X * aname = m;
X
X return error;
X}
X
X/* given a file descriptor see if it is a socket file descriptor */
Xstruct file *
Xgetsock (fd)
X int fd;
X{
X struct file * fp;
X
X /* given an fd, see if it is a valid fd, ie in file table*/
X if ((fp = getf (fd)) == NULL)
X return 0;
X
X if (fp->f_inode)
X {
X u.u_error = ENOTSOCK;
X return 0;
X }
X
X return fp;
X}
+ END-OF-FILE src/syscalls.c
chmod 'u=rw,g=rw,o=rw' 'src/syscalls.c'
echo ' -rw-rw-rw- 1 bes HSJ 18437 Aug 12 12:27 src/syscalls.c (as sent)'
echo ' \c'
/bin/ls -l src/syscalls.c
echo 'Extracting src/sysent.m4'
sed 's/^X//' > src/sysent.m4 << '+ END-OF-FILE src/sysent.m4'
Xdivert(-1)
X#
X# @(#)sysent.m4 1.1 (Alex Crain) 6/20/89
X#
X# sysent.m4 - generate a sysent.h file from sysconfig.m4
X#
Xdefine(DEFSYSCALL,`define(`SYSENT_OFFSET',incr(SYSENT_OFFSET)){$1,$2},')
Xdefine(DEFINE,`#define $1 $2')
Xdefine(REALTIME,1)
Xdivert
X
X/*
X * sysent.h - system call entry definitions.
X *
X * DO NOT EDIT THIS FILE! It is generated by sysent.m4.
X */
X
X/*
X * The new sysent structure. This looks just like the original sysent
X * structure, see <sys/systm.h>. The order is critical, and the array
X * offsets must be equal to SYSL_<call name> - SYSL_FIRST.
X *
X * The original sysent structure is not used because it defines sy_call
X * as an int function instead of void.
X */
X
Xstruct void_sysent {
X char sy_narg;
X int (*sy_call)();
X} sysentries[] = {
Xinclude(../sysconfig.m4)
X};
X
XDEFINE(SYSL_LOCSYS,SYSL_SYSCALL)
XDEFINE(SYSL_FIRST,SYSENT_START)
XDEFINE(SYSL_LAST,SYSENT_OFFSET)
+ END-OF-FILE src/sysent.m4
chmod 'u=rw,g=rw,o=rw' 'src/sysent.m4'
echo ' -rw-rw-rw- 1 bes HSJ 893 Aug 12 12:27 src/sysent.m4 (as sent)'
echo ' \c'
/bin/ls -l src/sysent.m4
echo 'Extracting src/usrreq.c'
sed 's/^X//' > src/usrreq.c << '+ END-OF-FILE src/usrreq.c'
X#ifndef LINT
Xstatic char * sccsdef = "@(#)usrreq.c 1.1 (Alex Crain) 6/20/89";
X#endif
X
X/*
X * usrreq.c - Unix domain functions.
X *
X * Written by Alex Crain.
X *
X * This file is based in the Berkeley file uipc_socket.c,
X * but is *not* guarenteed to be in any way compatable. It is
X * close enough to the Berkeley code that the following applies...
X *
X * Copyright (c) 1982, 1986, 1988 Regents of the University of California.
X * All rights reserved.
X *
X * Redistribution and use in source and binary forms are permitted
X * provided that this notice is preserved and that due credit is given
X * to the University of California at Berkeley. The name of the University
X * may not be used to endorse or promote products derived from this
X * software without specific prior written permission. This software
X * is provided "as is" without express or implied warranty.
X *
X */
X
X#include <sys/types.h>
X#include <uipc/conf.h>
X#include <sys/param.h>
X#include <sys/systm.h>
X#include <sys/user.h>
X#include <sys/inode.h>
X#include <sys/proc.h>
X#include <sys/stat.h>
X#include <sys/var.h>
X#include <sys/tune.h>
X#include <sys/errno.h>
X#include <uipc/mbuf.h>
X#include <uipc/socket.h>
X#include <uipc/socketvar.h>
X#include <uipc/protosw.h>
X#include <uipc/domain.h>
X#include <uipc/unpcb.h>
X#include <uipc/un.h>
X#include <uipc/fproto.h>
X
Xstruct sockaddr sun_noname = { AF_UNIX };
Xino_t unp_ino;
X
Xint
Xuipc_usrreq (so, req, m, nam, rights)
X struct socket * so;
X int req;
X struct mbuf * m, * nam, * rights;
X{
X struct unpcb * unp = sotounpcb (so);
X struct socket * so2;
X int error = 0;
X
X if (req == PRU_CONTROL)
X return EOPNOTSUPP;
X
X if (req != PRU_SEND && rights && rights->m_len)
X {
X error = EOPNOTSUPP;
X goto release;
X }
X
X if (unp == (struct unpcb *) 0 && req != PRU_ATTACH)
X {
X error = EINVAL;
X goto release;
X }
X
X switch (req)
X {
X case PRU_ATTACH:
X if (unp)
X {
X error = EISCONN;
X break;
X }
X error = unp_attach (so);
X break;
X
X case PRU_DETACH:
X unp_detach (unp);
X break;
X
X case PRU_BIND:
X error = unp_bind (unp, nam);
X break;
X
X case PRU_LISTEN:
X if (unp->unp_inode == 0)
X error = EINVAL;
X break;
X
X case PRU_CONNECT:
X error = unp_connect (so, nam);
X break;
X
X case PRU_CONNECT2:
X error = unp_connect2 (so, (struct socket *) nam);
X break;
X
X case PRU_DISCONNECT:
X unp_disconnect (unp);
X break;
X
X case PRU_ACCEPT:
X if (unp->unp_conn && unp->unp_conn->unp_addr)
X {
X nam->m_len = unp->unp_conn->unp_addr->m_len;
X bcopy (mtod (unp->unp_conn->unp_addr, caddr_t),
X mtod (nam, caddr_t), (unsigned) nam->m_len);
X }
X else
X {
X nam->m_len = sizeof (sun_noname);
X * (mtod (nam, struct sockaddr *)) = sun_noname;
X }
X break;
X
X case PRU_SHUTDOWN:
X socantsendmore (so);
X unp_usrclosed (unp);
X break;
X
X case PRU_RCVD:
X switch (so->so_type)
X {
X case SOCK_DGRAM:
X panic ("uipc 1");
X /* NOTREACHED */;
X
X case SOCK_STREAM:
X#define rcv (&so->so_rcv)
X#define snd (&so2->so_snd)
X if (unp->unp_conn == 0)
X break;
X /*
X * Adjust backpressure on sender
X * and wakeup any waiting to write.
X */
X so2 = unp->unp_conn->unp_socket;
X snd->sb_mbmax += unp->unp_mbcnt - rcv->sb_mbcnt;
X unp->unp_mbcnt = rcv->sb_mbcnt;
X snd->sb_hiwat += unp->unp_cc - rcv->sb_cc;
X unp->unp_cc = rcv->sb_cc;
X sowwakeup (so2);
X#undef snd
X#undef rcv
X break;
X
X default:
X panic ("uipc 2");
X }
X break;
X
X case PRU_SEND:
X if (rights && (error = unp_internalize (rights)))
X break;
X
X switch (so->so_type)
X {
X case SOCK_DGRAM:
X {
X struct sockaddr * from;
X
X if (nam)
X {
X if (unp->unp_conn)
X {
X error = EISCONN;
X break;
X }
X if (error = unp_connect (so, nam))
X break;
X }
X else
X {
X if (unp->unp_conn == 0)
X {
X error = ENOTCONN;
X break;
X }
X }
X so2 = unp->unp_conn->unp_socket;
X if (unp->unp_addr)
X from = mtod (unp->unp_addr, struct sockaddr *);
X else
X from = &sun_noname;
X if (sbspace (&so2->so_rcv) > 0 &&
X sbappendaddr (&so2->so_rcv, from, m, rights))
X {
X sorwakeup (so2);
X m = 0;
X }
X else
X error = ENOBUFS;
X if (nam)
X unp_disconnect (unp);
X break;
X }
X
X case SOCK_STREAM:
X#define rcv (&so2->so_rcv)
X#define snd (&so->so_snd)
X if (so->so_state & SS_CANTSENDMORE)
X {
X error = EPIPE;
X break;
X }
X if (unp->unp_conn == 0)
X panic ("uipc 3");
X so2 = unp->unp_conn->unp_socket;
X /*
X * Send to paired receive port, and then reduce
X * senders hiwater makrs to maintain backpressure.
X * Wake up readers.
X */
X if (rights)
X (void) sbappendrights (rcv, m, rights);
X else
X sbappend (rcv, m);
X snd->sb_mbmax -= rcv->sb_mbcnt - unp->unp_conn->unp_mbcnt;
X unp->unp_conn->unp_mbcnt = rcv->sb_mbcnt;
X snd->sb_hiwat -= rcv->sb_cc - unp->unp_conn->unp_cc;
X unp->unp_conn->unp_cc = rcv->sb_cc;
X sorwakeup (so2);
X m = 0;
X break;
X#undef snd
X#undef rcv
X
X default:
X panic ("uipc 4");
X }
X break;
X
X case PRU_SENSE:
X/* ((struct stat *) m)->st_blksize = so->so_snd.sb_hiwat; */
X if (so->so_type == SOCK_STREAM && unp->unp_conn != 0)
X {
X so2 = unp->unp_conn->unp_socket;
X/* ((struct stat *) m)->st_blksize += so2->so_rcv.sb_cc; */
X }
X ((struct stat *) m)->st_dev = NODEV;
X if (unp->unp_ino == 0)
X unp->unp_ino = unp_ino++;
X ((struct stat *) m)->st_ino = unp->unp_ino;
X return 0;
X
X case PRU_ABORT:
X unp_drop(unp, ECONNABORTED);
X break;
X
X case PRU_RCVOOB:
X return EOPNOTSUPP;
X
X case PRU_SENDOOB:
X error = EOPNOTSUPP;
X break;
X
X case PRU_SOCKADDR:
X break;
X
X case PRU_PEERADDR:
X if (unp->unp_conn && unp->unp_conn->unp_addr)
X {
X nam->m_len = unp->unp_conn->unp_addr->m_len;
X bcopy (mtod (unp->unp_conn->unp_addr, caddr_t),
X mtod (nam, caddr_t), (unsigned) nam->m_len);
X }
X break;
X
X case PRU_SLOWTIMO:
X break;
X
X default:
X panic ("prusrreq");
X }
X
X release:
X if (m)
X m_freem (m);
X return error;
X}
X
X#define UNPST_SENDSPACE 4096
X#define UNPST_RECVSPACE 4096
X#define UNPDG_SENDSPACE 2048 /* max datagram size */
X#define UNPDG_RECVSPACE 2048
X
Xint unp_rights;
X
Xint
Xunp_attach (so)
X struct socket * so;
X{
X struct mbuf * m;
X struct unpcb * unp;
X int error = 0;
X
X switch (so->so_type)
X {
X case SOCK_DGRAM:
X error = soreserve (so, UNPDG_SENDSPACE, UNPDG_RECVSPACE);
X break;
X
X case SOCK_STREAM:
X error = soreserve (so, UNPST_SENDSPACE, UNPST_RECVSPACE);
X break;
X }
X if (error)
X return error;
X
X if ((m = m_getclr (M_DONTWAIT, MT_PCB)) == NULL)
X return ENOBUFS;
X
X unp = mtod(m, struct unpcb *);
X so->so_pcb = (caddr_t) unp;
X unp->unp_socket = so;
X
X return 0;
X}
X
Xvoid
Xunp_detach (unp)
X struct unpcb * unp;
X{
X if (unp->unp_inode)
X {
X unp->unp_inode->i_socket = 0;
X iput (unp->unp_inode);
X unp->unp_inode = 0;
X }
X if (unp->unp_conn)
X unp_disconnect (unp);
X while (unp->unp_refs)
X unp_drop (unp->unp_refs, ECONNRESET);
X soisdisconnected (unp->unp_socket);
X unp->unp_socket->so_pcb = 0;
X m_freem (unp->unp_addr);
X (void) m_free (dtom (unp));
X if (unp_rights)
X unp_gc ();
X}
X
Xint
Xunp_bind (unp, nam)
X struct unpcb * unp;
X struct mbuf * nam;
X{
X struct sockaddr_un * soun = mtod (nam, struct sockaddr_un *);
X struct inode * ip;
X int error;
X
X if (unp->unp_inode != NULL || nam->m_len == MLEN)
X return EINVAL;
X
X *(mtod (nam, caddr_t) + nam->m_len) = '\0';
X u.u_dirp = soun->sun_path;
X
X if (ip = namei (schar, 1))
X {
X iput (ip);
X return EADDRINUSE;
X }
X
X if (error = u.u_error)
X {
X u.u_error = 0;
X return error;
X }
X
X if ((ip = maknode (IFREG | 0777)) == NULL)
X {
X error = u.u_error;
X u.u_error = 0;
X return error;
X }
X
X ip->i_uid = u.u_uid;
X ip->i_gid = u.u_gid;
X ip->i_socket = unp->unp_socket;
X unp->unp_inode = ip;
X unp->unp_addr = m_copy (nam, 0, (int) M_COPYALL);
X prele (ip);
X return 0;
X}
X
Xint
Xunp_connect (so, nam)
X struct socket * so;
X struct mbuf * nam;
X{
X struct sockaddr_un * soun = mtod (nam, struct sockaddr_un *);
X struct inode * ip;
X int error;
X struct socket * so2;
X caddr_t dirp = u.u_dirp;
X caddr_t base = u.u_base;
X unsigned count = u.u_count;
X
X if ((nam->m_len + (nam->m_off - MMINOFF)) == MLEN)
X {
X error = EMSGSIZE;
X goto bad0;
X }
X * (mtod (nam, caddr_t) + nam->m_len) = '\0';
X u.u_dirp = soun->sun_path;
X if ((ip = namei (schar, 0)) == 0)
X {
X error = u.u_error;
X u.u_error = 0;
X goto bad0;
X }
X if (access (ip, IWRITE))
X {
X error = u.u_error;
X u.u_error = 0;
X goto bad;
X }
X if ((so2 = ip->i_socket) == 0)
X {
X error = ECONNREFUSED;
X goto bad;
X }
X if (so2->so_type != so->so_type)
X {
X error = EPROTOTYPE;
X goto bad;
X }
X if (so->so_proto->pr_flags & PR_CONNREQUIRED &&
X ((so2->so_options & SO_ACCEPTCONN) == 0 ||
X (so2 = sonewconn (so2)) == 0))
X {
X error = ECHILD; /* ECONNREFUSED;*/
X goto bad;
X }
X error = unp_connect2 (so, so2);
X bad:
X iput (ip);
X bad0:
X u.u_base = base;
X u.u_count = count;
X u.u_dirp = dirp;
X return error;
X}
X
Xint
Xunp_connect2 (so1, so2)
X struct socket * so1, * so2;
X{
X struct unpcb * unp1, * unp2;
X
X if (so2->so_type != so1->so_type)
X return EPROTOTYPE;
X unp1 = sotounpcb (so1);
X unp2 = sotounpcb (so2);
X unp1->unp_conn = unp2;
X switch (so1->so_type)
X {
X case SOCK_DGRAM:
X unp1->unp_nextref = unp2->unp_refs;
X unp2->unp_refs = unp1;
X soisconnected (so1);
X break;
X
X case SOCK_STREAM:
X unp2->unp_conn = unp1;
X soisconnected (so1);
X soisconnected (so2);
X break;
X
X default:
X panic ("unp_connect 2");
X }
X return 0;
X}
X
Xvoid
Xunp_disconnect (unp)
X struct unpcb * unp;
X{
X struct unpcb * unp2 = unp->unp_conn;
X
X if (unp2 == 0)
X return;
X unp->unp_conn = 0;
X switch (unp->unp_socket->so_type)
X {
X case SOCK_DGRAM:
X if (unp2->unp_refs == unp)
X unp2->unp_refs = unp->unp_nextref;
X else
X {
X unp2 = unp2->unp_refs;
X for (;;)
X {
X if (unp2 == 0)
X panic ("unp_disconnect");
X if (unp2->unp_nextref == unp)
X break;
X unp2 = unp2->unp_nextref;
X }
X unp2->unp_nextref = unp->unp_nextref;
X }
X unp->unp_nextref = 0;
X unp->unp_socket->so_state &= ~SS_ISCONNECTED;
X break;
X
X case SOCK_STREAM:
X soisdisconnected (unp->unp_socket);
X unp2->unp_conn = 0;
X soisdisconnected (unp2->unp_socket);
X break;
X }
X}
X
X/* ARGSUSED */
Xvoid
Xunp_usrclosed (unp)
X struct unpcb * unp;
X{
X /* do not very much */
X ;
X}
X
Xvoid
Xunp_drop (unp, errno)
X struct unpcb * unp;
X int errno;
X{
X struct socket * so = unp->unp_socket;
X
X so->so_error = errno;
X unp_disconnect (unp);
X if (so->so_head)
X {
X so->so_pcb = (caddr_t) 0;
X m_freem (unp->unp_addr);
X (void) m_free (dtom (unp));
X sofree (so);
X }
X}
X
Xushort f_msgcount[NFILEMAX];
X#define fptoi(FP) (((FP)-file)/sizeof (struct file))
X
X/* ARGSUSED */
Xint
Xunp_externalize (rights)
X struct mbuf * rights;
X{
X int newfds = rights->m_len / sizeof (int);
X int i, f;
X struct file ** rp = mtod (rights, struct file **);
X struct file * fp;
X
X if (newfds > ufavail ())
X {
X for (i = 0; i < newfds; i++)
X {
X fp = *rp;
X unp_discard (fp);
X * rp++ = 0;
X }
X return EMSGSIZE;
X }
X for (i = 0, f = 0; i < newfds; i++)
X {
X f = ufalloc (f);
X if (f < 0)
X panic ("unp_externalize");
X fp = * rp;
X u.u_ofile[f] = fp;
X f_msgcount[fptoi (fp)]--;
X unp_rights --;
X * (int *) rp++ = f;
X }
X return 0;
X}
X
X/* ARGSUSED */
Xint
Xunp_internalize (rights)
X struct mbuf * rights;
X{
X struct file ** rp, * fp;
X int oldfds = rights->m_len / sizeof (int);
X int i;
X
X rp = mtod (rights, struct file **);
X
X for (i = 0; i < oldfds; i++)
X if (getf (* (int *) rp++) == 0)
X return EBADF;
X
X rp = mtod (rights, struct file **);
X
X for (i = 0; i < oldfds; i++)
X {
X fp = getf (* (int *) rp);
X * rp++ = fp;
X fp->f_count++;
X f_msgcount[fptoi (fp)]++;
X unp_rights++;
X }
X return 0;
X}
X
Xint unp_defer, unp_gcing;
Xextern struct domain unixdomain;
X
Xvoid
Xunp_gc ()
X{
X struct file * fp;
X struct socket * so;
X int i;
X
X if (unp_gcing)
X return;
X unp_gcing = 1;
X restart:
X unp_defer = 0;
X for (fp = file; fp < (struct file *) v.ve_file; fp++)
X fp->f_flag &= ~(FMARK | FDEFER);
X do
X {
X for (fp = file; fp < (struct file *) v.ve_file; fp++)
X {
X if (fp->f_count == 0)
X continue;
X if (fp->f_flag & FDEFER)
X {
X fp->f_flag &= ~FDEFER;
X unp_defer--;
X }
X else
X {
X if (fp->f_flag & FMARK)
X continue;
X if (fp->f_count == f_msgcount[fptoi (fp)])
X continue;
X fp->f_flag |= FMARK;
X }
X if (fp->f_inode)
X continue;
X so = filesock (fp);
X if (so->so_proto->pr_domain != &unixdomain ||
X so->so_proto->pr_flags & PR_RIGHTS)
X continue;
X if (so->so_rcv.sb_flags & SB_LOCK)
X {
X sbwait (&so->so_rcv);
X goto restart;
X }
X unp_scan (so->so_rcv.sb_mb, (int (*)()) unp_mark);
X }
X } while (unp_defer);
X for (fp = file, i = 0; fp < (struct file *) v.ve_file; fp++, i++)
X {
X if (fp->f_count == 0)
X continue;
X if (fp->f_count == f_msgcount[i] &&
X (fp->f_flag & FMARK) == 0)
X while (f_msgcount[i])
X unp_discard (fp);
X }
X unp_gcing = 0;
X}
X
Xvoid
Xunp_dispose (m)
X struct mbuf * m;
X{
X void unp_discard ();
X
X if (m)
X unp_scan (m, (int (*)()) unp_discard);
X}
X
X/* ARGSUSED */
Xvoid
Xunp_scan (m0, op)
X struct mbuf * m0;
X int (* op)();
X{
X struct mbuf * m;
X struct file ** rp;
X int i;
X int qfds;
X
X while (m0)
X {
X for (m = m0; m; m = m->m_next)
X if (m->m_type == MT_RIGHTS && m->m_len)
X {
X qfds = m->m_len / sizeof (struct file **);
X rp = mtod (m, struct file **);
X for (i = 0; i < qfds; i++)
X (* op) (* rp++);
X break;
X }
X m0 = m0->m_act;
X }
X}
X
Xvoid
Xunp_mark (fp)
X struct file * fp;
X{
X if (fp->f_flag & FMARK)
X return;
X unp_defer++;
X fp->f_flag |= (FMARK | FDEFER);
X}
X
Xvoid
Xunp_discard (fp)
X struct file * fp;
X{
X f_msgcount[fptoi (fp)]--;
X unp_rights--;
X closef (fp);
X}
X
+ END-OF-FILE src/usrreq.c
chmod 'u=rw,g=rw,o=rw' 'src/usrreq.c'
echo ' -rw-rw-rw- 1 bes HSJ 14693 Aug 12 12:27 src/usrreq.c (as sent)'
echo ' \c'
/bin/ls -l src/usrreq.c
exit 0
--
Bradley Smith
Computer Systems Offer Integration Laboratory
AT&T Bell Labs, Holmdel, NJ
201-949-0090 att!holin!bes or bes at holin.ATT.COM
More information about the Comp.sys.att
mailing list