home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / sys / netiso / cltp_usrreq.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-06-27  |  9.0 KB  |  408 lines

  1. /*
  2.  * Copyright (c) 1989 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.  *    @(#)cltp_usrreq.c    7.6 (Berkeley) 6/27/91
  34.  */
  35.  
  36. #ifndef CLTPOVAL_SRC /* XXX -- till files gets changed */
  37. #include "param.h"
  38. #include "malloc.h"
  39. #include "mbuf.h"
  40. #include "protosw.h"
  41. #include "socket.h"
  42. #include "socketvar.h"
  43. #include "errno.h"
  44. #include "stat.h"
  45.  
  46. #include "../net/if.h"
  47. #include "../net/route.h"
  48.  
  49. #include "argo_debug.h"
  50. #include "iso.h"
  51. #include "iso_pcb.h"
  52. #include "iso_var.h"
  53. #include "clnp.h"
  54. #include "cltp_var.h"
  55. #endif
  56.  
  57. /*
  58.  * CLTP protocol implementation.
  59.  * Per ISO 8602, December, 1987.
  60.  */
  61. cltp_init()
  62. {
  63.  
  64.     cltb.isop_next = cltb.isop_prev = &cltb;
  65. }
  66.  
  67. int cltp_cksum = 1;
  68.  
  69.  
  70. /* ARGUSED */
  71. cltp_input(m0, srcsa, dstsa, cons_channel, output)
  72.     struct mbuf *m0;
  73.     struct sockaddr *srcsa, *dstsa;
  74.     u_int cons_channel;
  75.     int (*output)();
  76. {
  77.     register struct isopcb *isop;
  78.     register struct mbuf *m = m0;
  79.     register u_char *up = mtod(m, u_char *);
  80.     register struct sockaddr_iso *src = (struct sockaddr_iso *)srcsa;
  81.     int len, hdrlen = *up + 1, dlen = 0;
  82.     u_char *uplim = up + hdrlen;
  83.     caddr_t dtsap;
  84.  
  85.     for (len = 0; m; m = m->m_next)
  86.         len += m->m_len;
  87.     up += 2; /* skip header */
  88.     while (up < uplim) switch (*up) { /* process options */
  89.     case CLTPOVAL_SRC:
  90.         src->siso_tlen = up[1];
  91.         src->siso_len = up[1] + TSEL(src) - (caddr_t)src;
  92.         if (src->siso_len < sizeof(*src))
  93.             src->siso_len = sizeof(*src);
  94.         else if (src->siso_len > sizeof(*src)) {
  95.             MGET(m, M_DONTWAIT, MT_SONAME);
  96.             if (m == 0)
  97.                 goto bad;
  98.             m->m_len = src->siso_len;
  99.             src = mtod(m, struct sockaddr_iso *);
  100.             bcopy((caddr_t)srcsa, (caddr_t)src, srcsa->sa_len);
  101.         }
  102.         bcopy((caddr_t)up + 2, TSEL(src), up[1]);
  103.         up += 2 + src->siso_tlen;
  104.         continue;
  105.     
  106.     case CLTPOVAL_DST:
  107.         dtsap = 2 + (caddr_t)up;
  108.         dlen = up[1];
  109.         up += 2 + dlen;
  110.         continue;
  111.  
  112.     case CLTPOVAL_CSM:
  113.         if (iso_check_csum(m0, len)) {
  114.             cltpstat.cltps_badsum++;
  115.             goto bad;
  116.         }
  117.         up += 4;
  118.         continue;
  119.  
  120.     default:
  121.         printf("clts: unknown option (%x)\n", up[0]);
  122.         cltpstat.cltps_hdrops++;
  123.         goto bad;
  124.     }
  125.     if (dlen == 0 || src->siso_tlen == 0)
  126.         goto bad;
  127.     for (isop = cltb.isop_next;; isop = isop->isop_next) {
  128.         if (isop == &cltb) {
  129.             cltpstat.cltps_noport++;
  130.             goto bad;
  131.         }
  132.         if (isop->isop_laddr &&
  133.             bcmp(TSEL(isop->isop_laddr), dtsap, dlen) == 0)
  134.             break;
  135.     }
  136.     m = m0;
  137.     m->m_len -= hdrlen;
  138.     m->m_data += hdrlen;
  139.     if (sbappendaddr(&isop->isop_socket->so_rcv, (struct sockaddr *)src,
  140.         m, (struct mbuf *)0) == 0)
  141.         goto bad;
  142.     cltpstat.cltps_ipackets++;
  143.     sorwakeup(isop->isop_socket);
  144.     m0 = 0;
  145. bad:
  146.     if (src != (struct sockaddr_iso *)srcsa)
  147.         m_freem(dtom(src));
  148.     if (m0)
  149.         m_freem(m0);
  150.     return 0;
  151. }
  152.  
  153. /*
  154.  * Notify a cltp user of an asynchronous error;
  155.  * just wake up so that he can collect error status.
  156.  */
  157. cltp_notify(isop)
  158.     register struct isopcb *isop;
  159. {
  160.  
  161.     sorwakeup(isop->isop_socket);
  162.     sowwakeup(isop->isop_socket);
  163. }
  164.  
  165. cltp_ctlinput(cmd, sa)
  166.     int cmd;
  167.     struct sockaddr *sa;
  168. {
  169.     extern u_char inetctlerrmap[];
  170.     struct sockaddr_iso *siso;
  171.     int iso_rtchange();
  172.  
  173.     if ((unsigned)cmd > PRC_NCMDS)
  174.         return;
  175.     if (sa->sa_family != AF_ISO && sa->sa_family != AF_CCITT)
  176.         return;
  177.     siso = (struct sockaddr_iso *)sa;
  178.     if (siso == 0 || siso->siso_nlen == 0)
  179.         return;
  180.  
  181.     switch (cmd) {
  182.     case PRC_ROUTEDEAD:
  183.     case PRC_REDIRECT_NET:
  184.     case PRC_REDIRECT_HOST:
  185.     case PRC_REDIRECT_TOSNET:
  186.     case PRC_REDIRECT_TOSHOST:
  187.         iso_pcbnotify(&cltb, siso,
  188.                 (int)inetctlerrmap[cmd], iso_rtchange);
  189.         break;
  190.  
  191.     default:
  192.         if (inetctlerrmap[cmd] == 0)
  193.             return;        /* XXX */
  194.         iso_pcbnotify(&cltb, siso, (int)inetctlerrmap[cmd],
  195.             cltp_notify);
  196.     }
  197. }
  198.  
  199. cltp_output(isop, m)
  200.     register struct isopcb *isop;
  201.     register struct mbuf *m;
  202. {
  203.     register int len;
  204.     register struct sockaddr_iso *siso;
  205.     int hdrlen, error = 0, docsum;
  206.     register u_char *up;
  207.  
  208.     if (isop->isop_laddr == 0 || isop->isop_faddr == 0) {
  209.         error = ENOTCONN;
  210.         goto bad;
  211.     }
  212.     /*
  213.      * Calculate data length and get a mbuf for CLTP header.
  214.      */
  215.     hdrlen = 2 + 2 + isop->isop_laddr->siso_tlen
  216.            + 2 + isop->isop_faddr->siso_tlen;
  217.     if (docsum = /*isop->isop_flags & CLNP_NO_CKSUM*/ cltp_cksum)
  218.         hdrlen += 4;
  219.     M_PREPEND(m, hdrlen, M_WAIT);
  220.     len = m->m_pkthdr.len;
  221.     /*
  222.      * Fill in mbuf with extended CLTP header
  223.      */
  224.     up = mtod(m, u_char *);
  225.     up[0] = hdrlen - 1;
  226.     up[1] = UD_TPDU_type;
  227.     up[2] = CLTPOVAL_SRC;
  228.     up[3] = (siso = isop->isop_laddr)->siso_tlen;
  229.     up += 4;
  230.     bcopy(TSEL(siso), (caddr_t)up, siso->siso_tlen);
  231.     up += siso->siso_tlen;
  232.     up[0] = CLTPOVAL_DST;
  233.     up[1] = (siso = isop->isop_faddr)->siso_tlen;
  234.     up += 2;
  235.     bcopy(TSEL(siso), (caddr_t)up, siso->siso_tlen);
  236.     /*
  237.      * Stuff checksum and output datagram.
  238.      */
  239.     if (docsum) {
  240.         up += siso->siso_tlen;
  241.         up[0] = CLTPOVAL_CSM;
  242.         up[1] = 2;
  243.         iso_gen_csum(m, 2 + up - mtod(m, u_char *), len);
  244.     }
  245.     cltpstat.cltps_opackets++;
  246.     return (tpclnp_output(isop, m, len, !docsum));
  247. bad:
  248.     m_freem(m);
  249.     return (error);
  250. }
  251.  
  252. #ifndef TP_LOCAL
  253. /* XXXX should go in iso.h maybe? from tp_param.h, in any case */
  254. #define        TP_LOCAL                22
  255. #define        TP_FOREIGN                33
  256. #endif
  257.  
  258. u_long    cltp_sendspace = 9216;        /* really max datagram size */
  259. u_long    cltp_recvspace = 40 * (1024 + sizeof(struct sockaddr_iso));
  260.                     /* 40 1K datagrams */
  261.  
  262.  
  263. /*ARGSUSED*/
  264. cltp_usrreq(so, req, m, nam, control)
  265.     struct socket *so;
  266.     int req;
  267.     struct mbuf *m, *nam, *control;
  268. {
  269.     struct isopcb *isop = sotoisopcb(so);
  270.     int s, error = 0;
  271.  
  272.     if (req == PRU_CONTROL)
  273.         return (iso_control(so, (int)m, (caddr_t)nam,
  274.             (struct ifnet *)control));
  275.     if ((isop == NULL && req != PRU_ATTACH) ||
  276.         (control && control->m_len)) {
  277.         error = EINVAL;
  278.         goto release;
  279.     }
  280.     switch (req) {
  281.  
  282.     case PRU_ATTACH:
  283.         if (isop != NULL) {
  284.             error = EINVAL;
  285.             break;
  286.         }
  287.         error = iso_pcballoc(so, &cltb);
  288.         if (error)
  289.             break;
  290.         error = soreserve(so, cltp_sendspace, cltp_recvspace);
  291.         if (error)
  292.             break;
  293.         break;
  294.  
  295.     case PRU_DETACH:
  296.         iso_pcbdetach(isop);
  297.         break;
  298.  
  299.     case PRU_BIND:
  300.         error = iso_pcbbind(isop, nam);
  301.         break;
  302.  
  303.     case PRU_LISTEN:
  304.         error = EOPNOTSUPP;
  305.         break;
  306.  
  307.     case PRU_CONNECT:
  308.         if (isop->isop_faddr) {
  309.             error = EISCONN;
  310.             break;
  311.         }
  312.         error = iso_pcbconnect(isop, nam);
  313.         if (error == 0)
  314.             soisconnected(so);
  315.         break;
  316.  
  317.     case PRU_CONNECT2:
  318.         error = EOPNOTSUPP;
  319.         break;
  320.  
  321.     case PRU_ACCEPT:
  322.         error = EOPNOTSUPP;
  323.         break;
  324.  
  325.     case PRU_DISCONNECT:
  326.         if (isop->isop_faddr == 0) {
  327.             error = ENOTCONN;
  328.             break;
  329.         }
  330.         iso_pcbdisconnect(isop);
  331.         so->so_state &= ~SS_ISCONNECTED;        /* XXX */
  332.         break;
  333.  
  334.     case PRU_SHUTDOWN:
  335.         socantsendmore(so);
  336.         break;
  337.  
  338.     case PRU_SEND:
  339.         if (nam) {
  340.             if (isop->isop_faddr) {
  341.                 error = EISCONN;
  342.                 break;
  343.             }
  344.             /*
  345.              * Must block input while temporarily connected.
  346.              */
  347.             s = splnet();
  348.             error = iso_pcbconnect(isop, nam);
  349.             if (error) {
  350.                 splx(s);
  351.                 break;
  352.             }
  353.         } else {
  354.             if (isop->isop_faddr == 0) {
  355.                 error = ENOTCONN;
  356.                 break;
  357.             }
  358.         }
  359.         error = cltp_output(isop, m);
  360.         m = 0;
  361.         if (nam) {
  362.             iso_pcbdisconnect(isop);
  363.             splx(s);
  364.         }
  365.         break;
  366.  
  367.     case PRU_ABORT:
  368.         soisdisconnected(so);
  369.         iso_pcbdetach(isop);
  370.         break;
  371.  
  372.     case PRU_SOCKADDR:
  373.         iso_getnetaddr(isop, nam, TP_LOCAL);
  374.         break;
  375.  
  376.     case PRU_PEERADDR:
  377.         iso_getnetaddr(isop, nam, TP_FOREIGN);
  378.         break;
  379.  
  380.     case PRU_SENSE:
  381.         /*
  382.          * stat: don't bother with a blocksize.
  383.          */
  384.         return (0);
  385.  
  386.     case PRU_SENDOOB:
  387.     case PRU_FASTTIMO:
  388.     case PRU_SLOWTIMO:
  389.     case PRU_PROTORCV:
  390.     case PRU_PROTOSEND:
  391.         error =  EOPNOTSUPP;
  392.         break;
  393.  
  394.     case PRU_RCVD:
  395.     case PRU_RCVOOB:
  396.         return (EOPNOTSUPP);    /* do not free mbuf's */
  397.  
  398.     default:
  399.         panic("cltp_usrreq");
  400.     }
  401. release:
  402.     if (control != NULL)
  403.         m_freem(control);
  404.     if (m != NULL)
  405.         m_freem(m);
  406.     return (error);
  407. }
  408.