📄 pk_usrreq.c
字号:
/* * Copyright (c) University of British Columbia, 1984 * Copyright (C) Computer Science Department IV, * University of Erlangen-Nuremberg, Germany, 1992 * Copyright (c) 1991, 1992, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by the * Laboratory for Computation Vision and the Computer Science Department * of the the University of British Columbia and the Computer Science * Department (IV) of the University of Erlangen-Nuremberg, Germany. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)pk_usrreq.c 8.1 (Berkeley) 6/10/93 */#include <sys/param.h>#include <sys/systm.h>#include <sys/mbuf.h>#include <sys/socket.h>#include <sys/socketvar.h>#include <sys/protosw.h>#include <sys/errno.h>#include <sys/ioctl.h>#include <sys/stat.h>#include <net/if.h>#include <net/if_types.h>#include <net/route.h>#include <netccitt/x25.h>#include <netccitt/pk.h>#include <netccitt/pk_var.h>static old_to_new();static new_to_old();/* * * X.25 Packet level protocol interface to socket abstraction. * * Process an X.25 user request on a logical channel. If this is a send * request then m is the mbuf chain of the send data. If this is a timer * expiration (called from the software clock routine) them timertype is * the particular timer. * */pk_usrreq (so, req, m, nam, control)struct socket *so;int req;register struct mbuf *m, *nam;struct mbuf *control;{ register struct pklcd *lcp = (struct pklcd *) so -> so_pcb; register int error = 0; if (req == PRU_CONTROL) return (pk_control (so, (int)m, (caddr_t)nam, (struct ifnet *)control)); if (control && control -> m_len) { error = EINVAL; goto release; } if (lcp == NULL && req != PRU_ATTACH) { error = EINVAL; goto release; }/* pk_trace (pkcbhead, TR_USER, (struct pklcd *)0, req, (struct x25_packet *)0);*/ switch (req) { /* * X.25 attaches to socket via PRU_ATTACH and allocates a logical * channel descriptor. If the socket is to receive connections, * then the LISTEN state is entered. */ case PRU_ATTACH: if (lcp) { error = EISCONN; /* Socket already connected. */ break; } lcp = pk_attach (so); if (lcp == 0) error = ENOBUFS; break; /* * Detach a logical channel from the socket. If the state of the * channel is embryonic, simply discard it. Otherwise we have to * initiate a PRU_DISCONNECT which will finish later. */ case PRU_DETACH: pk_disconnect (lcp); break; /* * Give the socket an address. */ case PRU_BIND: if (nam -> m_len == sizeof (struct x25_sockaddr)) old_to_new (nam); error = pk_bind (lcp, nam); break; /* * Prepare to accept connections. */ case PRU_LISTEN: error = pk_listen (lcp); break; /* * Initiate a CALL REQUEST to peer entity. Enter state SENT_CALL * and mark the socket as connecting. Set timer waiting for * CALL ACCEPT or CLEAR. */ case PRU_CONNECT: if (nam -> m_len == sizeof (struct x25_sockaddr)) old_to_new (nam); if (pk_checksockaddr (nam)) return (EINVAL); error = pk_connect (lcp, mtod (nam, struct sockaddr_x25 *)); break; /* * Initiate a disconnect to peer entity via a CLEAR REQUEST packet. * The socket will be disconnected when we receive a confirmation * or a clear collision. */ case PRU_DISCONNECT: pk_disconnect (lcp); break; /* * Accept an INCOMING CALL. Most of the work has already been done * by pk_input. Just return the callers address to the user. */ case PRU_ACCEPT: if (lcp -> lcd_craddr == NULL) break; bcopy ((caddr_t)lcp -> lcd_craddr, mtod (nam, caddr_t), sizeof (struct sockaddr_x25)); nam -> m_len = sizeof (struct sockaddr_x25); if (lcp -> lcd_flags & X25_OLDSOCKADDR) new_to_old (nam); break; /* * After a receive, we should send a RR. */ case PRU_RCVD: pk_flowcontrol (lcp, /*sbspace (&so -> so_rcv) <= */ 0, 1); break; /* * Send INTERRUPT packet. */ case PRU_SENDOOB: if (m == 0) { MGETHDR(m, M_WAITOK, MT_OOBDATA); m -> m_pkthdr.len = m -> m_len = 1; *mtod (m, octet *) = 0; } if (m -> m_pkthdr.len > 32) { m_freem (m); error = EMSGSIZE; break; } MCHTYPE(m, MT_OOBDATA); /* FALLTHROUGH */ /* * Do send by placing data on the socket output queue. */ case PRU_SEND: if (control) { register struct cmsghdr *ch = mtod (m, struct cmsghdr *); control -> m_len -= sizeof (*ch); control -> m_data += sizeof (*ch); error = pk_ctloutput (PRCO_SETOPT, so, ch -> cmsg_level, ch -> cmsg_type, &control); } if (error == 0 && m) error = pk_send (lcp, m); break; /* * Abort a virtual circuit. For example all completed calls * waiting acceptance. */ case PRU_ABORT: pk_disconnect (lcp); break; /* Begin unimplemented hooks. */ case PRU_SHUTDOWN: error = EOPNOTSUPP; break; case PRU_CONTROL: error = EOPNOTSUPP; break; case PRU_SENSE: #ifdef BSD4_3 ((struct stat *)m) -> st_blksize = so -> so_snd.sb_hiwat;#else error = EOPNOTSUPP;#endif break; /* End unimplemented hooks. */ case PRU_SOCKADDR: if (lcp -> lcd_ceaddr == 0) return (EADDRNOTAVAIL); nam -> m_len = sizeof (struct sockaddr_x25); bcopy ((caddr_t)lcp -> lcd_ceaddr, mtod (nam, caddr_t), sizeof (struct sockaddr_x25)); if (lcp -> lcd_flags & X25_OLDSOCKADDR) new_to_old (nam); break; case PRU_PEERADDR: if (lcp -> lcd_state != DATA_TRANSFER) return (ENOTCONN); nam -> m_len = sizeof (struct sockaddr_x25); bcopy (lcp -> lcd_craddr ? (caddr_t)lcp -> lcd_craddr : (caddr_t)lcp -> lcd_ceaddr, mtod (nam, caddr_t), sizeof (struct sockaddr_x25)); if (lcp -> lcd_flags & X25_OLDSOCKADDR) new_to_old (nam); break; /* * Receive INTERRUPT packet. */ case PRU_RCVOOB: if (so -> so_options & SO_OOBINLINE) { register struct mbuf *n = so -> so_rcv.sb_mb; if (n && n -> m_type == MT_OOBDATA) { unsigned len = n -> m_pkthdr.len; so -> so_rcv.sb_mb = n -> m_nextpkt; if (len != n -> m_len && (n = m_pullup (n, len)) == 0) break; m -> m_len = len; bcopy (mtod (m, caddr_t), mtod (n, caddr_t), len); m_freem (n); } break; } m -> m_len = 1; *mtod (m, char *) = lcp -> lcd_intrdata; break; default: panic ("pk_usrreq"); }release: if (control != NULL) m_freem (control); return (error);}/* * If you want to use UBC X.25 level 3 in conjunction with some * other X.25 level 2 driver, have the ifp -> if_ioctl routine * assign pk_start to ia -> ia_start when called with SIOCSIFCONF_X25. *//* ARGSUSED */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -