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.24 2005/02/26 22:39:50 perry 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.24 2005/02/26 22:39:50 perry 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 idp_input(struct mbuf *m, ...)
   73 {
   74         struct nspcb *nsp;
   75         struct idp *idp = mtod(m, struct idp *);
   76         struct ifnet *ifp = m->m_pkthdr.rcvif;
   77         va_list ap;
   78 
   79         va_start(ap, m);
   80         nsp = va_arg(ap, struct nspcb *);
   81         va_end(ap);
   82 
   83         if (nsp==0)
   84                 panic("No nspcb");
   85         /*
   86          * Construct sockaddr format source address.
   87          * Stuff source address and datagram in user buffer.
   88          */
   89         idp_ns.sns_addr = idp->idp_sna;
   90         if (ns_neteqnn(idp->idp_sna.x_net, ns_zeronet) && ifp) {
   91                 struct ifaddr *ifa;
   92 
   93                 for (ifa = ifp->if_addrlist.tqh_first; ifa != 0;
   94                     ifa = ifa->ifa_list.tqe_next) {
   95                         if (ifa->ifa_addr->sa_family == AF_NS) {
   96                                 idp_ns.sns_addr.x_net =
   97                                         IA_SNS(ifa)->sns_addr.x_net;
   98                                 break;
   99                         }
  100                 }
  101         }
  102         nsp->nsp_rpt = idp->idp_pt;
  103         if ( ! (nsp->nsp_flags & NSP_RAWIN) ) {
  104                 m->m_len -= sizeof (struct idp);
  105                 m->m_pkthdr.len -= sizeof (struct idp);
  106                 m->m_data += sizeof (struct idp);
  107         }
  108         if (sbappendaddr(&nsp->nsp_socket->so_rcv, snstosa(&idp_ns), m,
  109             (struct mbuf *)0) == 0)
  110                 goto bad;
  111         sorwakeup(nsp->nsp_socket);
  112         return;
  113 bad:
  114         m_freem(m);
  115 }
  116 
  117 void
  118 idp_abort(struct nspcb *nsp)
  119 {
  120         struct socket *so = nsp->nsp_socket;
  121 
  122         ns_pcbdisconnect(nsp);
  123         soisdisconnected(so);
  124 }
  125 /*
  126  * Drop connection, reporting
  127  * the specified error.
  128  */
  129 void
  130 idp_drop(struct nspcb *nsp, int errno)
  131 {
  132         struct socket *so = nsp->nsp_socket;
  133 
  134 #if 0
  135         /*
  136          * someday, in the xerox world
  137          * we will generate error protocol packets
  138          * announcing that the socket has gone away.
  139          */
  140         if (TCPS_HAVERCVDSYN(tp->t_state)) {
  141                 tp->t_state = TCPS_CLOSED;
  142                 (void) tcp_output(tp);
  143         }
  144 #endif
  145         so->so_error = errno;
  146         ns_pcbdisconnect(nsp);
  147         soisdisconnected(so);
  148 }
  149 
  150 int
  151 idp_output(struct mbuf *m0, ...)
  152 {
  153         struct nspcb *nsp;
  154         struct mbuf *m;
  155         struct idp *idp;
  156         int len = m0->m_pkthdr.len;
  157         struct mbuf *mprev = NULL;
  158         extern int idpcksum;
  159         va_list ap;
  160 
  161         va_start(ap, m0);
  162         nsp = va_arg(ap, struct nspcb *);
  163         va_end(ap);
  164 
  165         /*
  166          * Make sure packet is actually of even length.
  167          */
  168 
  169         if (len & 1) {
  170                 m = mprev;
  171                 if ((m->m_flags & M_EXT) == 0 &&
  172                         (m->m_len + m->m_data < &m->m_dat[MLEN])) {
  173                         m->m_len++;
  174                 } else {
  175                         struct mbuf *m1 = m_get(M_DONTWAIT, MT_DATA);
  176 
  177                         if (m1 == 0) {
  178                                 m_freem(m0);
  179                                 return (ENOBUFS);
  180                         }
  181                         m1->m_len = 1;
  182                         * mtod(m1, char *) = 0;
  183                         m->m_next = m1;
  184                 }
  185                 m0->m_pkthdr.len++;
  186         }
  187 
  188         /*
  189          * Fill in mbuf with extended IDP header
  190          * and addresses and length put into network format.
  191          */
  192         m = m0;
  193         if (nsp->nsp_flags & NSP_RAWOUT) {
  194                 idp = mtod(m, struct idp *);
  195         } else {
  196                 M_PREPEND(m, sizeof (struct idp), M_DONTWAIT);
  197                 if (m == 0)
  198                         return (ENOBUFS);
  199                 idp = mtod(m, struct idp *);
  200                 idp->idp_tc = 0;
  201                 idp->idp_pt = nsp->nsp_dpt;
  202                 idp->idp_sna = nsp->nsp_laddr;
  203                 idp->idp_dna = nsp->nsp_faddr;
  204                 len += sizeof (struct idp);
  205         }
  206 
  207         idp->idp_len = htons((u_int16_t)len);
  208 
  209         if (idpcksum) {
  210                 idp->idp_sum = 0;
  211                 len = ((len - 1) | 1) + 1;
  212                 idp->idp_sum = ns_cksum(m, len);
  213         } else
  214                 idp->idp_sum = 0xffff;
  215 
  216         /*
  217          * Use cached route for previous datagram if
  218          * possible.  If the previous net was the same
  219          * and the interface was a broadcast medium, or
  220          * if the previous destination was identical,
  221          * then we are ok.
  222          *
  223          * NB: We don't handle broadcasts because that
  224          *     would require 3 subroutine calls.
  225          */
  226         return (ns_output(m, &nsp->nsp_route,
  227             nsp->nsp_socket->so_options & (SO_DONTROUTE | SO_BROADCAST)));
  228 }
  229 /* ARGSUSED */
  230 int
  231 idp_ctloutput(int req, struct socket *so, int level, int name,
  232         struct mbuf **value)
  233 {
  234         struct mbuf *m;
  235         struct nspcb *nsp = sotonspcb(so);
  236         int mask, error = 0;
  237 
  238         if (nsp == NULL)
  239                 return (EINVAL);
  240 
  241         switch (req) {
  242 
  243         case PRCO_GETOPT:
  244                 if (value==NULL)
  245                         return (EINVAL);
  246                 m = m_get(M_DONTWAIT, MT_DATA);
  247                 if (m==NULL)
  248                         return (ENOBUFS);
  249                 switch (name) {
  250 
  251                 case SO_ALL_PACKETS:
  252                         mask = NSP_ALL_PACKETS;
  253                         goto get_flags;
  254 
  255                 case SO_HEADERS_ON_INPUT:
  256                         mask = NSP_RAWIN;
  257                         goto get_flags;
  258 
  259                 case SO_HEADERS_ON_OUTPUT:
  260                         mask = NSP_RAWOUT;
  261                 get_flags:
  262                         m->m_len = sizeof(short);
  263                         *mtod(m, short *) = nsp->nsp_flags & mask;
  264                         break;
  265 
  266                 case SO_DEFAULT_HEADERS:
  267                         m->m_len = sizeof(struct idp);
  268                         {
  269                                 struct idp *idp = mtod(m, struct idp *);
  270                                 idp->idp_len = 0;
  271                                 idp->idp_sum = 0;
  272                                 idp->idp_tc = 0;
  273                                 idp->idp_pt = nsp->nsp_dpt;
  274                                 idp->idp_dna = nsp->nsp_faddr;
  275                                 idp->idp_sna = nsp->nsp_laddr;
  276                         }
  277                         break;
  278 
  279                 case SO_SEQNO:
  280                         m->m_len = sizeof(long);
  281                         *mtod(m, long *) = ns_pexseq++;
  282                         break;
  283 
  284                 default:
  285                         error = EINVAL;
  286                 }
  287                 *value = m;
  288                 break;
  289 
  290         case PRCO_SETOPT:
  291                 switch (name) {
  292                         int *ok;
  293 
  294                 case SO_ALL_PACKETS:
  295                         mask = NSP_ALL_PACKETS;
  296                         goto set_head;
  297 
  298                 case SO_HEADERS_ON_INPUT:
  299                         mask = NSP_RAWIN;
  300                         goto set_head;
  301 
  302                 case SO_HEADERS_ON_OUTPUT:
  303                         mask = NSP_RAWOUT;
  304                 set_head:
  305                         if (value && *value) {
  306                                 ok = mtod(*value, int *);
  307                                 if (*ok)
  308                                         nsp->nsp_flags |= mask;
  309                                 else
  310                                         nsp->nsp_flags &= ~mask;
  311                         } else error = EINVAL;
  312                         break;
  313 
  314                 case SO_DEFAULT_HEADERS:
  315                         {
  316                                 struct idp *idp
  317                                     = mtod(*value, struct idp *);
  318                                 nsp->nsp_dpt = idp->idp_pt;
  319                         }
  320                         break;
  321 #ifdef NSIP
  322 
  323                 case SO_NSIP_ROUTE:
  324                         error = nsip_route(*value);
  325                         break;
  326 #endif /* NSIP */
  327                 default:
  328                         error = EINVAL;
  329                 }
  330                 if (value && *value)
  331                         m_freem(*value);
  332                 break;
  333         }
  334         return (error);
  335 }
  336 
  337 u_long  idp_sendspace = 2048;
  338 u_long  idp_recvspace = 2048;
  339 
  340 /*ARGSUSED*/
  341 int
  342 idp_usrreq(struct socket *so, int req, struct mbuf *m, struct mbuf *nam,
  343         struct mbuf *control, struct proc *p)
  344 {
  345         struct nspcb *nsp;
  346         int s;
  347         int error = 0;
  348 
  349         if (req == PRU_CONTROL)
  350                 return (ns_control(so, (u_long)m, (caddr_t)nam,
  351                     (struct ifnet *)control, p));
  352 
  353         if (req == PRU_PURGEIF) {
  354                 ns_purgeif((struct ifnet *)control);
  355                 return (0);
  356         }
  357 
  358         s = splsoftnet();
  359         nsp = sotonspcb(so);
  360         if (nsp == 0 && req != PRU_ATTACH) {
  361                 error = EINVAL;
  362                 goto release;
  363         }
  364 
  365         switch (req) {
  366 
  367         case PRU_ATTACH:
  368                 if (nsp != 0) {
  369                         error = EISCONN;
  370                         break;
  371                 }
  372                 if ((error = soreserve(so, idp_sendspace, idp_recvspace)) ||
  373                     (error = ns_pcballoc(so, &nspcb)))
  374                         break;
  375                 break;
  376 
  377         case PRU_DETACH:
  378                 ns_pcbdetach(nsp);
  379                 break;
  380 
  381         case PRU_BIND:
  382                 error = ns_pcbbind(nsp, nam, p);
  383                 break;
  384 
  385         case PRU_LISTEN:
  386                 error = EOPNOTSUPP;
  387                 break;
  388 
  389         case PRU_CONNECT:
  390                 error = ns_pcbconnect(nsp, nam);
  391                 if (error)
  392                         break;
  393                 soisconnected(so);
  394                 break;
  395 
  396         case PRU_CONNECT2:
  397                 error = EOPNOTSUPP;
  398                 break;
  399 
  400         case PRU_DISCONNECT:
  401                 soisdisconnected(so);
  402                 ns_pcbdisconnect(nsp);
  403                 break;
  404 
  405         case PRU_SHUTDOWN:
  406                 socantsendmore(so);
  407                 break;
  408 
  409         case PRU_RCVD:
  410                 error = EOPNOTSUPP;
  411                 break;
  412 
  413         case PRU_SEND:
  414         {
  415                 struct ns_addr laddr;
  416 
  417                 if (nam) {
  418                         laddr = nsp->nsp_laddr;
  419                         if ((so->so_state & SS_ISCONNECTED) != 0) {
  420                                 error = EISCONN;
  421                                 break;
  422                         }
  423                         error = ns_pcbconnect(nsp, nam);
  424                         if (error)
  425                                 break;
  426                 } else {
  427                         if ((so->so_state & SS_ISCONNECTED) == 0) {
  428                                 error = ENOTCONN;
  429                                 break;
  430                         }
  431                 }
  432                 error = idp_output(m, nsp);
  433                 if (nam) {
  434                         ns_pcbdisconnect(nsp);
  435                         nsp->nsp_laddr = laddr;
  436                 }
  437         }
  438                 break;
  439 
  440         case PRU_SENSE:
  441                 /*
  442                  * stat: don't bother with a blocksize.
  443                  */
  444                 splx(s);
  445                 return (0);
  446 
  447         /*
  448          * Not supported.
  449          */
  450         case PRU_RCVOOB:
  451                 error = EOPNOTSUPP;
  452                 break;
  453 
  454         case PRU_SENDOOB:
  455                 m_freem(m);
  456                 error = EOPNOTSUPP;
  457                 break;
  458 
  459         case PRU_SOCKADDR:
  460                 ns_setsockaddr(nsp, nam);
  461                 break;
  462 
  463         case PRU_PEERADDR:
  464                 ns_setpeeraddr(nsp, nam);
  465                 break;
  466 
  467         default:
  468                 panic("idp_usrreq");
  469         }
  470 
  471 release:
  472         splx(s);
  473         return (error);
  474 }
  475 
  476 /*ARGSUSED*/
  477 int
  478 idp_raw_usrreq(struct socket *so, int req, struct mbuf *m, struct mbuf *nam,
  479         struct mbuf *control, struct proc *p)
  480 {
  481         int error = 0;
  482         struct nspcb *nsp = sotonspcb(so);
  483 
  484         switch (req) {
  485 
  486         case PRU_ATTACH:
  487                 if (nsp != 0) {
  488                         error = EISCONN;
  489                         break;
  490                 }
  491                 if (p == 0 || (error = suser(p->p_ucred, &p->p_acflag))) {
  492                         error = EACCES;
  493                         break;
  494                 }
  495                 if ((error = soreserve(so, idp_sendspace, idp_recvspace)) ||
  496                     (error = ns_pcballoc(so, &nspcb)))
  497                         break;
  498                 nsp = sotonspcb(so);
  499                 nsp->nsp_faddr.x_host = ns_broadhost;
  500                 nsp->nsp_flags = NSP_RAWIN | NSP_RAWOUT;
  501                 break;
  502 
  503         default:
  504                 error = idp_usrreq(so, req, m, nam, control, p);
  505                 break;
  506         }
  507         return (error);
  508 }

Cache object: 67ae68cb1361d2eb562ecc68cfeb9013


[ 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.