The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/netns/idp_usrreq.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      $NetBSD: idp_usrreq.c,v 1.22 2003/08/07 16:33:44 agc Exp $      */
    2 
    3 /*
    4  * Copyright (c) 1984, 1985, 1986, 1987, 1993
    5  *      The Regents of the University of California.  All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions and the following disclaimer.
   12  * 2. Redistributions in binary form must reproduce the above copyright
   13  *    notice, this list of conditions and the following disclaimer in the
   14  *    documentation and/or other materials provided with the distribution.
   15  * 3. Neither the name of the University nor the names of its contributors
   16  *    may be used to endorse or promote products derived from this software
   17  *    without specific prior written permission.
   18  *
   19  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   22  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   29  * SUCH DAMAGE.
   30  *
   31  *      @(#)idp_usrreq.c        8.2 (Berkeley) 1/9/95
   32  */
   33 
   34 #include <sys/cdefs.h>
   35 __KERNEL_RCSID(0, "$NetBSD: idp_usrreq.c,v 1.22 2003/08/07 16:33:44 agc Exp $");
   36 
   37 #include "opt_ns.h"                     /* NSIP: Xerox NS over IP */
   38 
   39 #include <sys/param.h>
   40 #include <sys/systm.h>
   41 #include <sys/malloc.h>
   42 #include <sys/mbuf.h>
   43 #include <sys/protosw.h>
   44 #include <sys/socket.h>
   45 #include <sys/socketvar.h>
   46 #include <sys/errno.h>
   47 #include <sys/stat.h>
   48 #include <sys/proc.h>
   49 
   50 #include <net/if.h>
   51 #include <net/route.h>
   52 
   53 #include <netns/ns.h>
   54 #include <netns/ns_pcb.h>
   55 #include <netns/ns_if.h>
   56 #include <netns/ns_var.h>
   57 #include <netns/idp.h>
   58 #include <netns/idp_var.h>
   59 #include <netns/ns_error.h>
   60 
   61 #include <machine/stdarg.h>
   62 /*
   63  * IDP protocol implementation.
   64  */
   65 
   66 struct  sockaddr_ns idp_ns = { sizeof(idp_ns), AF_NS };
   67 
   68 /*
   69  *  This may also be called for raw listeners.
   70  */
   71 void
   72 #if __STDC__
   73 idp_input(struct mbuf *m, ...)
   74 #else
   75 idp_input(m, va_alist)
   76         struct mbuf *m;
   77         va_dcl
   78 #endif
   79 {
   80         struct nspcb *nsp;
   81         struct idp *idp = mtod(m, struct idp *);
   82         struct ifnet *ifp = m->m_pkthdr.rcvif;
   83         va_list ap;
   84 
   85         va_start(ap, m);
   86         nsp = va_arg(ap, struct nspcb *);
   87         va_end(ap);
   88 
   89         if (nsp==0)
   90                 panic("No nspcb");
   91         /*
   92          * Construct sockaddr format source address.
   93          * Stuff source address and datagram in user buffer.
   94          */
   95         idp_ns.sns_addr = idp->idp_sna;
   96         if (ns_neteqnn(idp->idp_sna.x_net, ns_zeronet) && ifp) {
   97                 struct ifaddr *ifa;
   98 
   99                 for (ifa = ifp->if_addrlist.tqh_first; ifa != 0;
  100                     ifa = ifa->ifa_list.tqe_next) {
  101                         if (ifa->ifa_addr->sa_family == AF_NS) {
  102                                 idp_ns.sns_addr.x_net =
  103                                         IA_SNS(ifa)->sns_addr.x_net;
  104                                 break;
  105                         }
  106                 }
  107         }
  108         nsp->nsp_rpt = idp->idp_pt;
  109         if ( ! (nsp->nsp_flags & NSP_RAWIN) ) {
  110                 m->m_len -= sizeof (struct idp);
  111                 m->m_pkthdr.len -= sizeof (struct idp);
  112                 m->m_data += sizeof (struct idp);
  113         }
  114         if (sbappendaddr(&nsp->nsp_socket->so_rcv, snstosa(&idp_ns), m,
  115             (struct mbuf *)0) == 0)
  116                 goto bad;
  117         sorwakeup(nsp->nsp_socket);
  118         return;
  119 bad:
  120         m_freem(m);
  121 }
  122 
  123 void
  124 idp_abort(nsp)
  125         struct nspcb *nsp;
  126 {
  127         struct socket *so = nsp->nsp_socket;
  128 
  129         ns_pcbdisconnect(nsp);
  130         soisdisconnected(so);
  131 }
  132 /*
  133  * Drop connection, reporting
  134  * the specified error.
  135  */
  136 void
  137 idp_drop(nsp, errno)
  138         struct nspcb *nsp;
  139         int errno;
  140 {
  141         struct socket *so = nsp->nsp_socket;
  142 
  143 #if 0
  144         /*
  145          * someday, in the xerox world
  146          * we will generate error protocol packets
  147          * announcing that the socket has gone away.
  148          */
  149         if (TCPS_HAVERCVDSYN(tp->t_state)) {
  150                 tp->t_state = TCPS_CLOSED;
  151                 (void) tcp_output(tp);
  152         }
  153 #endif
  154         so->so_error = errno;
  155         ns_pcbdisconnect(nsp);
  156         soisdisconnected(so);
  157 }
  158 
  159 int
  160 #if __STDC__
  161 idp_output(struct mbuf *m0, ...)
  162 #else
  163 idp_output(m0, va_alist)
  164         struct mbuf *m0;
  165         va_dcl
  166 #endif
  167 {
  168         struct nspcb *nsp;
  169         struct mbuf *m;
  170         struct idp *idp;
  171         int len = m0->m_pkthdr.len;
  172         struct mbuf *mprev = NULL;
  173         extern int idpcksum;
  174         va_list ap;
  175 
  176         va_start(ap, m0);
  177         nsp = va_arg(ap, struct nspcb *);
  178         va_end(ap);
  179 
  180         /*
  181          * Make sure packet is actually of even length.
  182          */
  183         
  184         if (len & 1) {
  185                 m = mprev;
  186                 if ((m->m_flags & M_EXT) == 0 &&
  187                         (m->m_len + m->m_data < &m->m_dat[MLEN])) {
  188                         m->m_len++;
  189                 } else {
  190                         struct mbuf *m1 = m_get(M_DONTWAIT, MT_DATA);
  191 
  192                         if (m1 == 0) {
  193                                 m_freem(m0);
  194                                 return (ENOBUFS);
  195                         }
  196                         m1->m_len = 1;
  197                         * mtod(m1, char *) = 0;
  198                         m->m_next = m1;
  199                 }
  200                 m0->m_pkthdr.len++;
  201         }
  202 
  203         /*
  204          * Fill in mbuf with extended IDP header
  205          * and addresses and length put into network format.
  206          */
  207         m = m0;
  208         if (nsp->nsp_flags & NSP_RAWOUT) {
  209                 idp = mtod(m, struct idp *);
  210         } else {
  211                 M_PREPEND(m, sizeof (struct idp), M_DONTWAIT);
  212                 if (m == 0)
  213                         return (ENOBUFS);
  214                 idp = mtod(m, struct idp *);
  215                 idp->idp_tc = 0;
  216                 idp->idp_pt = nsp->nsp_dpt;
  217                 idp->idp_sna = nsp->nsp_laddr;
  218                 idp->idp_dna = nsp->nsp_faddr;
  219                 len += sizeof (struct idp);
  220         }
  221 
  222         idp->idp_len = htons((u_int16_t)len);
  223 
  224         if (idpcksum) {
  225                 idp->idp_sum = 0;
  226                 len = ((len - 1) | 1) + 1;
  227                 idp->idp_sum = ns_cksum(m, len);
  228         } else
  229                 idp->idp_sum = 0xffff;
  230 
  231         /*
  232          * Use cached route for previous datagram if
  233          * possible.  If the previous net was the same
  234          * and the interface was a broadcast medium, or
  235          * if the previous destination was identical,
  236          * then we are ok.
  237          *
  238          * NB: We don't handle broadcasts because that
  239          *     would require 3 subroutine calls.
  240          */
  241         return (ns_output(m, &nsp->nsp_route,
  242             nsp->nsp_socket->so_options & (SO_DONTROUTE | SO_BROADCAST)));
  243 }
  244 /* ARGSUSED */
  245 int
  246 idp_ctloutput(req, so, level, name, value)
  247         int req, level;
  248         struct socket *so;
  249         int name;
  250         struct mbuf **value;
  251 {
  252         struct mbuf *m;
  253         struct nspcb *nsp = sotonspcb(so);
  254         int mask, error = 0;
  255 
  256         if (nsp == NULL)
  257                 return (EINVAL);
  258 
  259         switch (req) {
  260 
  261         case PRCO_GETOPT:
  262                 if (value==NULL)
  263                         return (EINVAL);
  264                 m = m_get(M_DONTWAIT, MT_DATA);
  265                 if (m==NULL)
  266                         return (ENOBUFS);
  267                 switch (name) {
  268 
  269                 case SO_ALL_PACKETS:
  270                         mask = NSP_ALL_PACKETS;
  271                         goto get_flags;
  272 
  273                 case SO_HEADERS_ON_INPUT:
  274                         mask = NSP_RAWIN;
  275                         goto get_flags;
  276                         
  277                 case SO_HEADERS_ON_OUTPUT:
  278                         mask = NSP_RAWOUT;
  279                 get_flags:
  280                         m->m_len = sizeof(short);
  281                         *mtod(m, short *) = nsp->nsp_flags & mask;
  282                         break;
  283 
  284                 case SO_DEFAULT_HEADERS:
  285                         m->m_len = sizeof(struct idp);
  286                         {
  287                                 struct idp *idp = mtod(m, struct idp *);
  288                                 idp->idp_len = 0;
  289                                 idp->idp_sum = 0;
  290                                 idp->idp_tc = 0;
  291                                 idp->idp_pt = nsp->nsp_dpt;
  292                                 idp->idp_dna = nsp->nsp_faddr;
  293                                 idp->idp_sna = nsp->nsp_laddr;
  294                         }
  295                         break;
  296 
  297                 case SO_SEQNO:
  298                         m->m_len = sizeof(long);
  299                         *mtod(m, long *) = ns_pexseq++;
  300                         break;
  301 
  302                 default:
  303                         error = EINVAL;
  304                 }
  305                 *value = m;
  306                 break;
  307 
  308         case PRCO_SETOPT:
  309                 switch (name) {
  310                         int *ok;
  311 
  312                 case SO_ALL_PACKETS:
  313                         mask = NSP_ALL_PACKETS;
  314                         goto set_head;
  315 
  316                 case SO_HEADERS_ON_INPUT:
  317                         mask = NSP_RAWIN;
  318                         goto set_head;
  319 
  320                 case SO_HEADERS_ON_OUTPUT:
  321                         mask = NSP_RAWOUT;
  322                 set_head:
  323                         if (value && *value) {
  324                                 ok = mtod(*value, int *);
  325                                 if (*ok)
  326                                         nsp->nsp_flags |= mask;
  327                                 else
  328                                         nsp->nsp_flags &= ~mask;
  329                         } else error = EINVAL;
  330                         break;
  331 
  332                 case SO_DEFAULT_HEADERS:
  333                         {
  334                                 struct idp *idp
  335                                     = mtod(*value, struct idp *);
  336                                 nsp->nsp_dpt = idp->idp_pt;
  337                         }
  338                         break;
  339 #ifdef NSIP
  340 
  341                 case SO_NSIP_ROUTE:
  342                         error = nsip_route(*value);
  343                         break;
  344 #endif /* NSIP */
  345                 default:
  346                         error = EINVAL;
  347                 }
  348                 if (value && *value)
  349                         m_freem(*value);
  350                 break;
  351         }
  352         return (error);
  353 }
  354 
  355 u_long  idp_sendspace = 2048;
  356 u_long  idp_recvspace = 2048;
  357 
  358 /*ARGSUSED*/
  359 int
  360 idp_usrreq(so, req, m, nam, control, p)
  361         struct socket *so;
  362         int req;
  363         struct mbuf *m, *nam, *control;
  364         struct proc *p;
  365 {
  366         struct nspcb *nsp;
  367         int s;
  368         int error = 0;
  369 
  370         if (req == PRU_CONTROL)
  371                 return (ns_control(so, (u_long)m, (caddr_t)nam,
  372                     (struct ifnet *)control, p));
  373 
  374         if (req == PRU_PURGEIF) {
  375                 ns_purgeif((struct ifnet *)control);
  376                 return (0);
  377         }
  378 
  379         s = splsoftnet();
  380         nsp = sotonspcb(so);
  381         if (nsp == 0 && req != PRU_ATTACH) {
  382                 error = EINVAL;
  383                 goto release;
  384         }
  385 
  386         switch (req) {
  387 
  388         case PRU_ATTACH:
  389                 if (nsp != 0) {
  390                         error = EISCONN;
  391                         break;
  392                 }
  393                 if ((error = soreserve(so, idp_sendspace, idp_recvspace)) ||
  394                     (error = ns_pcballoc(so, &nspcb)))
  395                         break;
  396                 break;
  397 
  398         case PRU_DETACH:
  399                 ns_pcbdetach(nsp);
  400                 break;
  401 
  402         case PRU_BIND:
  403                 error = ns_pcbbind(nsp, nam, p);
  404                 break;
  405 
  406         case PRU_LISTEN:
  407                 error = EOPNOTSUPP;
  408                 break;
  409 
  410         case PRU_CONNECT:
  411                 error = ns_pcbconnect(nsp, nam);
  412                 if (error)
  413                         break;
  414                 soisconnected(so);
  415                 break;
  416 
  417         case PRU_CONNECT2:
  418                 error = EOPNOTSUPP;
  419                 break;
  420 
  421         case PRU_DISCONNECT:
  422                 soisdisconnected(so);
  423                 ns_pcbdisconnect(nsp);
  424                 break;
  425 
  426         case PRU_SHUTDOWN:
  427                 socantsendmore(so);
  428                 break;
  429 
  430         case PRU_RCVD:
  431                 error = EOPNOTSUPP;
  432                 break;
  433 
  434         case PRU_SEND:
  435         {
  436                 struct ns_addr laddr;
  437 
  438                 if (nam) {
  439                         laddr = nsp->nsp_laddr;
  440                         if ((so->so_state & SS_ISCONNECTED) != 0) {
  441                                 error = EISCONN;
  442                                 break;
  443                         }
  444                         error = ns_pcbconnect(nsp, nam);
  445                         if (error)
  446                                 break;
  447                 } else {
  448                         if ((so->so_state & SS_ISCONNECTED) == 0) {
  449                                 error = ENOTCONN;
  450                                 break;
  451                         }
  452                 }
  453                 error = idp_output(m, nsp);
  454                 if (nam) {
  455                         ns_pcbdisconnect(nsp);
  456                         nsp->nsp_laddr = laddr;
  457                 }
  458         }
  459                 break;
  460 
  461         case PRU_SENSE:
  462                 /*
  463                  * stat: don't bother with a blocksize.
  464                  */
  465                 splx(s);
  466                 return (0);
  467 
  468         /*
  469          * Not supported.
  470          */
  471         case PRU_RCVOOB:
  472                 error = EOPNOTSUPP;
  473                 break;
  474 
  475         case PRU_SENDOOB:
  476                 m_freem(m);
  477                 error = EOPNOTSUPP;
  478                 break;
  479 
  480         case PRU_SOCKADDR:
  481                 ns_setsockaddr(nsp, nam);
  482                 break;
  483 
  484         case PRU_PEERADDR:
  485                 ns_setpeeraddr(nsp, nam);
  486                 break;
  487 
  488         default:
  489                 panic("idp_usrreq");
  490         }
  491 
  492 release:
  493         splx(s);
  494         return (error);
  495 }
  496 
  497 /*ARGSUSED*/
  498 int
  499 idp_raw_usrreq(so, req, m, nam, control, p)
  500         struct socket *so;
  501         int req;
  502         struct mbuf *m, *nam, *control;
  503         struct proc *p;
  504 {
  505         int error = 0;
  506         struct nspcb *nsp = sotonspcb(so);
  507 
  508         switch (req) {
  509 
  510         case PRU_ATTACH:
  511                 if (nsp != 0) {
  512                         error = EISCONN;
  513                         break;
  514                 }
  515                 if (p == 0 || (error = suser(p->p_ucred, &p->p_acflag))) {
  516                         error = EACCES;
  517                         break;
  518                 }
  519                 if ((error = soreserve(so, idp_sendspace, idp_recvspace)) ||
  520                     (error = ns_pcballoc(so, &nspcb)))
  521                         break;
  522                 nsp = sotonspcb(so);
  523                 nsp->nsp_faddr.x_host = ns_broadhost;
  524                 nsp->nsp_flags = NSP_RAWIN | NSP_RAWOUT;
  525                 break;
  526 
  527         default:
  528                 error = idp_usrreq(so, req, m, nam, control, p);
  529                 break;
  530         }
  531         return (error);
  532 }
  533 

Cache object: 77dc1b66d70a31ac388c6ea0a5a72d82


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.