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

Cache object: 804e7210c6d45e230a13f4bdae1919e1


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