home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / sys / netns / idp_usrreq.c next >
Encoding:
C/C++ Source or Header  |  1991-06-27  |  11.6 KB  |  567 lines

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