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

  1. /*-
  2.  * Copyright (c) 1991 The 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.  *    @(#)tp_iso.c    7.11 (Berkeley) 5/6/91
  34.  */
  35.  
  36. /***********************************************************
  37.         Copyright IBM Corporation 1987
  38.  
  39.                       All Rights Reserved
  40.  
  41. Permission to use, copy, modify, and distribute this software and its 
  42. documentation for any purpose and without fee is hereby granted, 
  43. provided that the above copyright notice appear in all copies and that
  44. both that copyright notice and this permission notice appear in 
  45. supporting documentation, and that the name of IBM not be
  46. used in advertising or publicity pertaining to distribution of the
  47. software without specific, written prior permission.  
  48.  
  49. IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
  50. ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
  51. IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
  52. ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
  53. WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
  54. ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
  55. SOFTWARE.
  56.  
  57. ******************************************************************/
  58.  
  59. /*
  60.  * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison
  61.  */
  62. /* 
  63.  * ARGO TP
  64.  * $Header: /var/src/sys/netiso/RCS/tp_iso.c,v 5.1 89/02/09 16:20:51 hagens Exp $
  65.  * $Source: /var/src/sys/netiso/RCS/tp_iso.c,v $
  66.  *
  67.  * Here is where you find the iso-dependent code.  We've tried
  68.  * keep all net-level and (primarily) address-family-dependent stuff
  69.  * out of the tp source, and everthing here is reached indirectly
  70.  * through a switch table (struct nl_protosw *) tpcb->tp_nlproto 
  71.  * (see tp_pcb.c). 
  72.  * The routines here are:
  73.  *         iso_getsufx: gets transport suffix out of an isopcb structure.
  74.  *         iso_putsufx: put transport suffix into an isopcb structure.
  75.  *        iso_putnetaddr: put a whole net addr into an isopcb.
  76.  *        iso_getnetaddr: get a whole net addr from an isopcb.
  77.  *        iso_cmpnetaddr: compare a whole net addr from an isopcb.
  78.  *        iso_recycle_suffix: clear suffix for reuse in isopcb
  79.  *         tpclnp_ctlinput: handle ER CNLPdu : icmp-like stuff
  80.  *         tpclnp_mtu: figure out what size tpdu to use
  81.  *        tpclnp_input: take a pkt from clnp, strip off its clnp header, 
  82.  *                give to tp
  83.  *        tpclnp_output_dg: package a pkt for clnp given 2 addresses & some data
  84.  *        tpclnp_output: package a pkt for clnp given an isopcb & some data
  85.  */
  86.  
  87. #ifdef ISO
  88.  
  89. #include "param.h"
  90. #include "socket.h"
  91. #include "socketvar.h"
  92. #include "domain.h"
  93. #include "malloc.h"
  94. #include "mbuf.h"
  95. #include "errno.h"
  96. #include "time.h"
  97. #include "protosw.h"
  98.  
  99. #include "../net/if.h"
  100. #include "../net/route.h"
  101.  
  102. #include "argo_debug.h"
  103. #include "tp_param.h"
  104. #include "tp_stat.h"
  105. #include "tp_pcb.h"
  106. #include "tp_trace.h"
  107. #include "tp_stat.h"
  108. #include "tp_tpdu.h"
  109. #include "tp_clnp.h"
  110. #include "cltp_var.h"
  111.  
  112. /*
  113.  * CALLED FROM:
  114.  *     pr_usrreq() on PRU_BIND, PRU_CONNECT, PRU_ACCEPT, and PRU_PEERADDR
  115.  * FUNCTION, ARGUMENTS:
  116.  *     The argument (which) takes the value TP_LOCAL or TP_FOREIGN.
  117.  */
  118.  
  119. iso_getsufx(isop, lenp, data_out, which)
  120.     struct isopcb *isop;
  121.     u_short *lenp;
  122.     caddr_t data_out;
  123.     int which;
  124. {
  125.     register struct sockaddr_iso *addr = 0;
  126.  
  127.     switch (which) {
  128.     case TP_LOCAL:
  129.         addr = isop->isop_laddr;
  130.         break;
  131.  
  132.     case TP_FOREIGN:
  133.         addr = isop->isop_faddr;
  134.     }
  135.     if (addr)
  136.         bcopy(TSEL(addr), data_out, (*lenp = addr->siso_tlen));
  137. }
  138.  
  139. /* CALLED FROM:
  140.  *     tp_newsocket(); i.e., when a connection is being established by an
  141.  *     incoming CR_TPDU.
  142.  *
  143.  * FUNCTION, ARGUMENTS:
  144.  *     Put a transport suffix (found in name) into an isopcb structure (isop).
  145.  *     The argument (which) takes the value TP_LOCAL or TP_FOREIGN.
  146.  */
  147. void
  148. iso_putsufx(isop, sufxloc, sufxlen, which)
  149.     struct isopcb *isop;
  150.     caddr_t sufxloc;
  151.     int sufxlen, which;
  152. {
  153.     struct sockaddr_iso **dst, *backup;
  154.     register struct sockaddr_iso *addr;
  155.     struct mbuf *m;
  156.     int len;
  157.  
  158.     switch (which) {
  159.     default:
  160.         return;
  161.  
  162.     case TP_LOCAL:
  163.         dst = &isop->isop_laddr;
  164.         backup = &isop->isop_sladdr;
  165.         break;
  166.  
  167.     case TP_FOREIGN:
  168.         dst = &isop->isop_faddr;
  169.         backup = &isop->isop_sfaddr;
  170.     }
  171.     if ((addr = *dst) == 0) {
  172.         addr = *dst = backup;
  173.         addr->siso_nlen = 0;
  174.         addr->siso_slen = 0;
  175.         addr->siso_plen = 0;
  176.         printf("iso_putsufx on un-initialized isopcb\n");
  177.     }
  178.     len = sufxlen + addr->siso_nlen +
  179.             (sizeof(*addr) - sizeof(addr->siso_data));
  180.     if (addr == backup) {
  181.         if (len > sizeof(*addr)) {
  182.                 m = m_getclr(M_DONTWAIT, MT_SONAME);
  183.                 if (m == 0)
  184.                     return;
  185.                 addr = *dst = mtod(m, struct sockaddr_iso *);
  186.                 *addr = *backup;
  187.                 m->m_len = len;
  188.         }
  189.     }
  190.     bcopy(sufxloc, TSEL(addr), sufxlen);
  191.     addr->siso_tlen = sufxlen;
  192.     addr->siso_len = len;
  193. }
  194.  
  195. /*
  196.  * CALLED FROM:
  197.  *     tp.trans whenever we go into REFWAIT state.
  198.  * FUNCTION and ARGUMENT:
  199.  *     Called when a ref is frozen, to allow the suffix to be reused. 
  200.  *     (isop) is the net level pcb.  This really shouldn't have to be
  201.  *     done in a NET level pcb but... for the internet world that just
  202.  *     the way it is done in BSD...
  203.  *     The alternative is to have the port unusable until the reference
  204.  *     timer goes off.
  205.  */
  206. void
  207. iso_recycle_tsuffix(isop)
  208.     struct isopcb    *isop;
  209. {
  210.     isop->isop_laddr->siso_tlen = isop->isop_faddr->siso_tlen = 0;
  211. }
  212.  
  213. /*
  214.  * CALLED FROM:
  215.  *     tp_newsocket(); i.e., when a connection is being established by an
  216.  *     incoming CR_TPDU.
  217.  *
  218.  * FUNCTION and ARGUMENTS:
  219.  *     Copy a whole net addr from a struct sockaddr (name).
  220.  *     into an isopcb (isop).
  221.  *     The argument (which) takes values TP_LOCAL or TP_FOREIGN
  222.  */ 
  223. void
  224. iso_putnetaddr(isop, name, which)
  225.     register struct isopcb    *isop;
  226.     struct sockaddr_iso    *name;
  227.     int which;
  228. {
  229.     struct sockaddr_iso **sisop, *backup;
  230.     register struct sockaddr_iso *siso;
  231.  
  232.     switch (which) {
  233.     default:
  234.         printf("iso_putnetaddr: should panic\n");
  235.         return;
  236.     case TP_LOCAL:
  237.         sisop = &isop->isop_laddr;
  238.         backup = &isop->isop_sladdr;
  239.         break;
  240.     case TP_FOREIGN:
  241.         sisop = &isop->isop_faddr;
  242.         backup = &isop->isop_sfaddr;
  243.     }
  244.     siso = ((*sisop == 0) ? (*sisop = backup) : *sisop);
  245.     IFDEBUG(D_TPISO)
  246.         printf("ISO_PUTNETADDR\n");
  247.         dump_isoaddr(isop->isop_faddr);
  248.     ENDDEBUG
  249.     siso->siso_addr = name->siso_addr;
  250. }
  251.  
  252. /*
  253.  * CALLED FROM:
  254.  *     tp_input() when a connection is being established by an
  255.  *     incoming CR_TPDU, and considered for interception.
  256.  *
  257.  * FUNCTION and ARGUMENTS:
  258.  *     compare a whole net addr from a struct sockaddr (name),
  259.  *     with that implicitly stored in an isopcb (isop).
  260.  *     The argument (which) takes values TP_LOCAL or TP_FOREIGN.
  261.  */ 
  262. iso_cmpnetaddr(isop, name, which)
  263.     register struct isopcb    *isop;
  264.     register struct sockaddr_iso    *name;
  265.     int which;
  266. {
  267.     struct sockaddr_iso **sisop, *backup;
  268.     register struct sockaddr_iso *siso;
  269.  
  270.     switch (which) {
  271.     default:
  272.         printf("iso_cmpnetaddr: should panic\n");
  273.         return 0;
  274.     case TP_LOCAL:
  275.         sisop = &isop->isop_laddr;
  276.         backup = &isop->isop_sladdr;
  277.         break;
  278.     case TP_FOREIGN:
  279.         sisop = &isop->isop_faddr;
  280.         backup = &isop->isop_sfaddr;
  281.     }
  282.     siso = ((*sisop == 0) ? (*sisop = backup) : *sisop);
  283.     IFDEBUG(D_TPISO)
  284.         printf("ISO_CMPNETADDR\n");
  285.         dump_isoaddr(siso);
  286.     ENDDEBUG
  287.     if (name->siso_tlen && bcmp(TSEL(name), TSEL(siso), name->siso_tlen))
  288.         return (0);
  289.     return (bcmp((caddr_t)name->siso_data,
  290.              (caddr_t)siso->siso_data, name->siso_nlen) == 0);
  291. }
  292.  
  293. /*
  294.  * CALLED FROM:
  295.  *  pr_usrreq() PRU_SOCKADDR, PRU_ACCEPT, PRU_PEERADDR
  296.  * FUNCTION and ARGUMENTS:
  297.  *     Copy a whole net addr from an isopcb (isop) into
  298.  *     a struct sockaddr (name).
  299.  *     The argument (which) takes values TP_LOCAL or TP_FOREIGN.
  300.  */ 
  301.  
  302. void
  303. iso_getnetaddr( isop, name, which)
  304.     struct isopcb *isop;
  305.     struct mbuf *name;
  306.     int which;
  307. {
  308.     struct sockaddr_iso *siso =
  309.         (which == TP_LOCAL ? isop->isop_laddr : isop->isop_faddr);
  310.     if (siso)
  311.         bcopy((caddr_t)siso, mtod(name, caddr_t),
  312.                 (unsigned)(name->m_len = siso->siso_len));
  313.     else
  314.         name->m_len = 0;
  315. }
  316.  
  317. /*
  318.  * CALLED FROM:
  319.  *  tp_input() on incoming CR, CC, and pr_usrreq() for PRU_CONNECT
  320.  * FUNCTION, ARGUMENTS, SIDE EFFECTS and RETURN VALUE:
  321.  * Determine the proper maximum transmission unit, i.e., MTU, to use, given
  322.  * a) the header size for the network protocol and the max transmission
  323.  *      unit on the subnet interface, determined from the information in (isop),
  324.  * b) the max size negotiated so far (negot)
  325.  * c) the window size used by the tp connection (found in so),
  326.  *
  327.  * The result is put in the integer *size in its integer form and in
  328.  * *negot in its logarithmic form.  
  329.  * 
  330.  * The rules are:
  331.  * a) can only negotiate down from the value found in *negot.
  332.  * b) the MTU must be < the windowsize,
  333.  * c) If src and dest are on the same net,
  334.  *       we will negotiate the closest size larger than  MTU but really USE 
  335.  *    the actual device mtu - ll hdr sizes.
  336.  *   otherwise we negotiate the closest size smaller than MTU - ll hdr sizes.
  337.  */
  338.  
  339. void
  340. tpclnp_mtu(so, isop, size, negot )
  341.     struct socket *so;
  342.     struct isopcb *isop;
  343.     int *size;
  344.     u_char *negot;
  345. {
  346.     struct ifnet *ifp = 0;
  347.     struct iso_ifaddr *ia = 0;
  348.     register int i;
  349.     int windowsize = so->so_rcv.sb_hiwat;
  350.     int clnp_size, mtu;
  351.     int sizeismtu = 0;
  352.     register struct rtentry *rt = isop->isop_route.ro_rt;
  353.  
  354.     IFDEBUG(D_CONN)
  355.         printf("tpclnp_mtu(0x%x,0x%x,0x%x,0x%x)\n", so, isop, size, negot);
  356.     ENDDEBUG
  357.     IFTRACE(D_CONN)
  358.         tptrace(TPPTmisc, "ENTER GET MTU: size negot \n",*size, *negot, 0, 0);
  359.     ENDTRACE
  360.  
  361.     *size = 1 << *negot;
  362.  
  363.     if( *size > windowsize ) {
  364.         *size = windowsize;
  365.     }
  366.  
  367.     if (rt == 0 || (rt->rt_flags & RTF_UP == 0) ||
  368.         (ia = (struct iso_ifaddr *)rt->rt_ifa) == 0 ||
  369.         (ifp = ia->ia_ifp) == 0) {
  370.         IFDEBUG(D_CONN)
  371.             printf("tpclnp_mtu routing abort rt=0x%x ia=0x%x ifp=0x%x\n",
  372.                     rt, ia, ifp)
  373.         ENDDEBUG
  374.         return;
  375.     }
  376.  
  377.  
  378.  
  379.     /* TODO - make this indirect off the socket structure to the
  380.      * network layer to get headersize
  381.      */
  382.     clnp_size = sizeof(struct clnp_fixed) + sizeof(struct clnp_segment) +
  383.             2 * sizeof(struct iso_addr);
  384.     mtu = SN_MTU(ifp, rt) - clnp_size;
  385.     if(*size > mtu) {
  386.         *size = mtu;
  387.         sizeismtu = 1;
  388.     }
  389.     /* have to transform size to the log2 of size */
  390.     for(i=TP_MIN_TPDUSIZE; (i<=TP_MAX_TPDUSIZE && ((1<<i) <= *size)) ; i++)
  391.         ;
  392.     i--;
  393.  
  394.     IFTRACE(D_CONN)
  395.         tptrace(TPPTmisc, "GET MTU MID: tpcb size negot i \n",
  396.         *size, *negot, i, 0);
  397.     ENDTRACE
  398.  
  399.     *size = 1<<i;
  400.     *negot = i;
  401.  
  402.     IFDEBUG(D_CONN)
  403.         printf("GET MTU RETURNS: ifp %s size 0x%x negot 0x%x\n",
  404.         ifp->if_name,    *size, *negot);
  405.     ENDDEBUG
  406.     IFTRACE(D_CONN)
  407.         tptrace(TPPTmisc, "EXIT GET MTU: tpcb size negot \n",
  408.         *size, *negot, 0, 0);
  409.     ENDTRACE
  410. }
  411.  
  412.  
  413. /*
  414.  * CALLED FROM:
  415.  *  tp_emit()
  416.  * FUNCTION and ARGUMENTS:
  417.  *  Take a packet(m0) from tp and package it so that clnp will accept it.
  418.  *  This means prepending space for the clnp header and filling in a few
  419.  *  of the fields.
  420.  *  inp is the isopcb structure; datalen is the length of the data in the
  421.  *  mbuf string m0.
  422.  * RETURN VALUE:
  423.  *  whatever (E*) is returned form the net layer output routine.
  424.  */
  425.  
  426. int
  427. tpclnp_output(isop, m0, datalen, nochksum)
  428.     struct isopcb        *isop;
  429.     struct mbuf         *m0;
  430.     int                 datalen;
  431.     int                    nochksum;
  432. {
  433.     register struct mbuf *m = m0;
  434.     IncStat(ts_tpdu_sent);
  435.  
  436.     IFDEBUG(D_TPISO)
  437.         struct tpdu *hdr = mtod(m0, struct tpdu *);
  438.  
  439.         printf(
  440. "abt to call clnp_output: datalen 0x%x, hdr.li 0x%x, hdr.dutype 0x%x nocsum x%x dst addr:\n",
  441.             datalen,
  442.             (int)hdr->tpdu_li, (int)hdr->tpdu_type, nochksum);
  443.         dump_isoaddr(isop->isop_faddr);
  444.         printf("\nsrc addr:\n");
  445.         dump_isoaddr(isop->isop_laddr);
  446.         dump_mbuf(m0, "at tpclnp_output");
  447.     ENDDEBUG
  448.  
  449.     return 
  450.         clnp_output(m0, isop, datalen,  /* flags */nochksum ? CLNP_NO_CKSUM : 0);
  451. }
  452.  
  453. /*
  454.  * CALLED FROM:
  455.  *  tp_error_emit()
  456.  * FUNCTION and ARGUMENTS:
  457.  *  This is a copy of tpclnp_output that takes the addresses
  458.  *  instead of a pcb.  It's used by the tp_error_emit, when we
  459.  *  don't have an iso_pcb with which to call the normal output rtn.
  460.  * RETURN VALUE:
  461.  *  ENOBUFS or
  462.  *  whatever (E*) is returned form the net layer output routine.
  463.  */
  464.  
  465. int
  466. tpclnp_output_dg(laddr, faddr, m0, datalen, ro, nochksum)
  467.     struct iso_addr        *laddr, *faddr;
  468.     struct mbuf         *m0;
  469.     int                 datalen;
  470.     struct route         *ro;
  471.     int                    nochksum;
  472. {
  473.     struct isopcb        tmppcb;
  474.     int                    err;
  475.     int                    flags;
  476.     register struct mbuf *m = m0;
  477.  
  478.     IFDEBUG(D_TPISO)
  479.         printf("tpclnp_output_dg  datalen 0x%x m0 0x%x\n", datalen, m0);
  480.     ENDDEBUG
  481.  
  482.     /*
  483.      *    Fill in minimal portion of isopcb so that clnp can send the
  484.      *    packet.
  485.      */
  486.     bzero((caddr_t)&tmppcb, sizeof(tmppcb));
  487.     tmppcb.isop_laddr = &tmppcb.isop_sladdr;
  488.     tmppcb.isop_laddr->siso_addr = *laddr;
  489.     tmppcb.isop_faddr = &tmppcb.isop_sfaddr;
  490.     tmppcb.isop_faddr->siso_addr = *faddr;
  491.  
  492.     IFDEBUG(D_TPISO)
  493.         printf("tpclnp_output_dg  faddr: \n");
  494.         dump_isoaddr(&tmppcb.isop_sfaddr);
  495.         printf("\ntpclnp_output_dg  laddr: \n");
  496.         dump_isoaddr(&tmppcb.isop_sladdr);
  497.         printf("\n");
  498.     ENDDEBUG
  499.  
  500.     /*
  501.      *    Do not use packet cache since this is a one shot error packet
  502.      */
  503.     flags = (CLNP_NOCACHE|(nochksum?CLNP_NO_CKSUM:0));
  504.  
  505.     IncStat(ts_tpdu_sent);
  506.  
  507.     err = clnp_output(m0, &tmppcb, datalen,  flags);
  508.     
  509.     /*
  510.      *    Free route allocated by clnp (if the route was indeed allocated)
  511.      */
  512.     if (tmppcb.isop_route.ro_rt)
  513.         RTFREE(tmppcb.isop_route.ro_rt);
  514.     
  515.     return(err);
  516. }
  517. /*
  518.  * CALLED FROM:
  519.  *     clnp's input routine, indirectly through the protosw.
  520.  * FUNCTION and ARGUMENTS:
  521.  * Take a packet (m) from clnp, strip off the clnp header and give it to tp
  522.  * No return value.  
  523.  */
  524. ProtoHook
  525. tpclnp_input(m, src, dst, clnp_len, ce_bit)
  526.     register struct mbuf *m;
  527.     struct sockaddr_iso *src, *dst;
  528.     int clnp_len, ce_bit;
  529. {
  530.     int s = splnet();
  531.     struct mbuf *tp_inputprep();
  532.     int tp_input(), cltp_input(), (*input)() = tp_input;
  533.  
  534.     IncStat(ts_pkt_rcvd);
  535.  
  536.     IFDEBUG(D_TPINPUT)
  537.         printf("tpclnp_input: m 0x%x clnp_len 0x%x\n", m, clnp_len);
  538.         dump_mbuf(m, "at tpclnp_input");
  539.     ENDDEBUG
  540.     /*
  541.      * CLNP gives us an mbuf chain WITH the clnp header pulled up,
  542.      * and the length of the clnp header.
  543.      * First, strip off the Clnp header. leave the mbuf there for the
  544.      * pullup that follows.
  545.      */
  546.  
  547.     m->m_len -= clnp_len;
  548.     m->m_data += clnp_len;
  549.  
  550.     m = tp_inputprep(m);
  551.     if (m == 0)
  552.         return 0;
  553.     if (mtod(m, u_char *)[1] == UD_TPDU_type)
  554.         input = cltp_input;
  555.  
  556.     IFDEBUG(D_TPINPUT)
  557.         dump_mbuf(m, "after tpclnp_input both pullups");
  558.     ENDDEBUG
  559.  
  560.     IFDEBUG(D_TPISO)
  561.         printf("calling %sinput : src 0x%x, dst 0x%x, src addr:\n", 
  562.             (input == tp_input ? "tp_" : "clts_"), src, dst);
  563.         dump_isoaddr(src);
  564.         printf(" dst addr:\n");
  565.         dump_isoaddr(dst);
  566.     ENDDEBUG
  567.  
  568.     (void) (*input)(m, (struct sockaddr *)src, (struct sockaddr *)dst,
  569.                 0, tpclnp_output_dg, ce_bit);
  570.  
  571.     IFDEBUG(D_QUENCH)
  572.         { 
  573.             if(time.tv_usec & 0x4 && time.tv_usec & 0x40) {
  574.                 printf("tpclnp_input: FAKING %s\n", 
  575.                     tp_stat.ts_pkt_rcvd & 0x1?"QUENCH":"QUENCH2");
  576.                 if(tp_stat.ts_pkt_rcvd & 0x1) {
  577.                     tpclnp_ctlinput(PRC_QUENCH, &src);
  578.                 } else {
  579.                     tpclnp_ctlinput(PRC_QUENCH2, &src);
  580.                 }
  581.             }
  582.         }
  583.     ENDDEBUG
  584.  
  585.     splx(s);
  586.     return 0;
  587. }
  588.  
  589. ProtoHook
  590. iso_rtchange()
  591. {
  592.     return 0;
  593. }
  594.  
  595. /*
  596.  * CALLED FROM:
  597.  *  tpclnp_ctlinput()
  598.  * FUNCTION and ARGUMENTS:
  599.  *  find the tpcb pointer and pass it to tp_quench
  600.  */
  601. void
  602. tpiso_decbit(isop)
  603.     struct isopcb *isop;
  604. {
  605.     tp_quench((struct tp_pcb *)isop->isop_socket->so_tpcb, PRC_QUENCH2);
  606. }
  607. /*
  608.  * CALLED FROM:
  609.  *  tpclnp_ctlinput()
  610.  * FUNCTION and ARGUMENTS:
  611.  *  find the tpcb pointer and pass it to tp_quench
  612.  */
  613. void
  614. tpiso_quench(isop)
  615.     struct isopcb *isop;
  616. {
  617.     tp_quench((struct tp_pcb *)isop->isop_socket->so_tpcb, PRC_QUENCH);
  618. }
  619.  
  620. /*
  621.  * CALLED FROM:
  622.  *  The network layer through the protosw table.
  623.  * FUNCTION and ARGUMENTS:
  624.  *    When clnp an ICMP-like msg this gets called.
  625.  *    It either returns an error status to the user or
  626.  *    it causes all connections on this address to be aborted
  627.  *    by calling the appropriate xx_notify() routine.
  628.  *    (cmd) is the type of ICMP error.   
  629.  *     (siso) is the address of the guy who sent the ER CLNPDU
  630.  */
  631. ProtoHook
  632. tpclnp_ctlinput(cmd, siso)
  633.     int cmd;
  634.     struct sockaddr_iso *siso;
  635. {
  636.     extern u_char inetctlerrmap[];
  637.     extern ProtoHook tpiso_abort();
  638.     extern ProtoHook iso_rtchange();
  639.     extern ProtoHook tpiso_reset();
  640.     void iso_pcbnotify();
  641.  
  642.     IFDEBUG(D_TPINPUT)
  643.         printf("tpclnp_ctlinput1: cmd 0x%x addr: \n", cmd);
  644.         dump_isoaddr(siso);
  645.     ENDDEBUG
  646.  
  647.     if (cmd < 0 || cmd > PRC_NCMDS)
  648.         return 0;
  649.     if (siso->siso_family != AF_ISO)
  650.         return 0;
  651.     switch (cmd) {
  652.  
  653.         case    PRC_QUENCH2:
  654.             iso_pcbnotify(&tp_isopcb, siso, 0, (int (*)())tpiso_decbit);
  655.             break;
  656.  
  657.         case    PRC_QUENCH:
  658.             iso_pcbnotify(&tp_isopcb, siso, 0, (int (*)())tpiso_quench);
  659.             break;
  660.  
  661.         case    PRC_TIMXCEED_REASS:
  662.         case    PRC_ROUTEDEAD:
  663.             iso_pcbnotify(&tp_isopcb, siso, 0, tpiso_reset);
  664.             break;
  665.  
  666.         case    PRC_HOSTUNREACH:
  667.         case    PRC_UNREACH_NET:
  668.         case    PRC_IFDOWN:
  669.         case    PRC_HOSTDEAD:
  670.             iso_pcbnotify(&tp_isopcb, siso,
  671.                     (int)inetctlerrmap[cmd], iso_rtchange);
  672.             break;
  673.  
  674.         default:
  675.         /*
  676.         case    PRC_MSGSIZE:
  677.         case    PRC_UNREACH_HOST:
  678.         case    PRC_UNREACH_PROTOCOL:
  679.         case    PRC_UNREACH_PORT:
  680.         case    PRC_UNREACH_NEEDFRAG:
  681.         case    PRC_UNREACH_SRCFAIL:
  682.         case    PRC_REDIRECT_NET:
  683.         case    PRC_REDIRECT_HOST:
  684.         case    PRC_REDIRECT_TOSNET:
  685.         case    PRC_REDIRECT_TOSHOST:
  686.         case    PRC_TIMXCEED_INTRANS:
  687.         case    PRC_PARAMPROB:
  688.         */
  689.         iso_pcbnotify(&tp_isopcb, siso, (int)inetctlerrmap[cmd], tpiso_abort);
  690.         break;
  691.     }
  692.     return 0;
  693. }
  694. /*
  695.  * XXX - Variant which is called by clnp_er.c with an isoaddr rather
  696.  * than a sockaddr_iso.
  697.  */
  698.  
  699. static struct sockaddr_iso siso = {sizeof(siso), AF_ISO};
  700. tpclnp_ctlinput1(cmd, isoa)
  701.     int cmd;
  702.     struct iso_addr *isoa;
  703. {
  704.     bzero((caddr_t)&siso.siso_addr, sizeof(siso.siso_addr));
  705.     bcopy((caddr_t)isoa, (caddr_t)&siso.siso_addr, isoa->isoa_len);
  706.     tpclnp_ctlinput(cmd, &siso);
  707. }
  708.  
  709. /*
  710.  * These next 2 routines are
  711.  * CALLED FROM:
  712.  *    xxx_notify() from tp_ctlinput() when
  713.  *  net level gets some ICMP-equiv. type event.
  714.  * FUNCTION and ARGUMENTS:
  715.  *  Cause the connection to be aborted with some sort of error
  716.  *  reason indicating that the network layer caused the abort.
  717.  *  Fakes an ER TPDU so we can go through the driver.
  718.  *  abort always aborts the TP connection.
  719.  *  reset may or may not, depending on the TP class that's in use.
  720.  */
  721. ProtoHook
  722. tpiso_abort(isop)
  723.     struct isopcb *isop;
  724. {
  725.     struct tp_event e;
  726.  
  727.     IFDEBUG(D_CONN)
  728.         printf("tpiso_abort 0x%x\n", isop);
  729.     ENDDEBUG
  730.     e.ev_number = ER_TPDU;
  731.     e.ATTR(ER_TPDU).e_reason = ECONNABORTED;
  732.     return  tp_driver((struct tp_pcb *)isop->isop_socket->so_tpcb, &e);
  733. }
  734.  
  735. ProtoHook
  736. tpiso_reset(isop)
  737.     struct isopcb *isop;
  738. {
  739.     struct tp_event e;
  740.  
  741.     e.ev_number = T_NETRESET;
  742.     return tp_driver((struct tp_pcb *)isop->isop_socket->so_tpcb, &e);
  743.  
  744. }
  745.  
  746. #endif ISO
  747.