Xref: utzoo unix-pc.sources:361 comp.sys.att:7289 Path: utzoo!attcan!uunet!tut.cis.ohio-state.edu!mailrus!rutgers!mit-eddie!bu-cs!att!dptg!holin!bes From: bes@holin.ATT.COM (Bradley Smith) Newsgroups: unix-pc.sources,comp.sys.att Subject: uipc.p1 - part1 of part5 Message-ID: <648@holin.ATT.COM> Date: 12 Aug 89 16:35:25 GMT Distribution: unix-pc Organization: AT&T Bell Labs, OIL, Holmdel, NJ Lines: 3092 : 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 X#include X#include X#include X#include X#include X#include X#include X#include X#include X#include X#include X#include X#include 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 X#include X#include X#include X#include X#include X#include X#include X#include X#include X#include X#include 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 X#include X#include X#include X#include X#include X#include X#include X#include X#include X#include X#include X#include X#include X#include X#include X#include 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 . 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 . The order is critical, and the array X * offsets must be equal to SYSL_ - 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 X#include X#include X#include X#include X#include X#include X#include X#include X#include X#include X#include X#include X#include X#include X#include X#include X#include X#include 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@holin.ATT.COM