136403Ssklower /*********************************************************** 236403Ssklower Copyright IBM Corporation 1987 336403Ssklower 436403Ssklower All Rights Reserved 536403Ssklower 636403Ssklower Permission to use, copy, modify, and distribute this software and its 736403Ssklower documentation for any purpose and without fee is hereby granted, 836403Ssklower provided that the above copyright notice appear in all copies and that 936403Ssklower both that copyright notice and this permission notice appear in 1036403Ssklower supporting documentation, and that the name of IBM not be 1136403Ssklower used in advertising or publicity pertaining to distribution of the 1236403Ssklower software without specific, written prior permission. 1336403Ssklower 1436403Ssklower IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 1536403Ssklower ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 1636403Ssklower IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 1736403Ssklower ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 1836403Ssklower WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 1936403Ssklower ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 2036403Ssklower SOFTWARE. 2136403Ssklower 2236403Ssklower ******************************************************************/ 2336403Ssklower 2436403Ssklower /* 2536403Ssklower * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison 2636403Ssklower */ 2736403Ssklower /* 2836403Ssklower * ARGO TP 2937469Ssklower * $Header: /var/src/sys/netiso/RCS/tp_iso.c,v 5.1 89/02/09 16:20:51 hagens Exp $ 3037469Ssklower * $Source: /var/src/sys/netiso/RCS/tp_iso.c,v $ 31*39927Ssklower * @(#)tp_iso.c 7.6 (Berkeley) 01/16/90 3236403Ssklower * 3336403Ssklower * Here is where you find the iso-dependent code. We've tried 3436403Ssklower * keep all net-level and (primarily) address-family-dependent stuff 3536403Ssklower * out of the tp source, and everthing here is reached indirectly 3636403Ssklower * through a switch table (struct nl_protosw *) tpcb->tp_nlproto 3736403Ssklower * (see tp_pcb.c). 3836403Ssklower * The routines here are: 3936403Ssklower * iso_getsufx: gets transport suffix out of an isopcb structure. 4036403Ssklower * iso_putsufx: put transport suffix into an isopcb structure. 4136403Ssklower * iso_putnetaddr: put a whole net addr into an isopcb. 4236403Ssklower * iso_getnetaddr: get a whole net addr from an isopcb. 4336403Ssklower * iso_recycle_suffix: clear suffix for reuse in isopcb 4436403Ssklower * tpclnp_ctlinput: handle ER CNLPdu : icmp-like stuff 4536403Ssklower * tpclnp_mtu: figure out what size tpdu to use 4636403Ssklower * tpclnp_input: take a pkt from clnp, strip off its clnp header, 4736403Ssklower * give to tp 4836403Ssklower * tpclnp_output_dg: package a pkt for clnp given 2 addresses & some data 4936403Ssklower * tpclnp_output: package a pkt for clnp given an isopcb & some data 5036403Ssklower */ 5136403Ssklower 5236403Ssklower #ifndef lint 5337469Ssklower static char *rcsid = "$Header: /var/src/sys/netiso/RCS/tp_iso.c,v 5.1 89/02/09 16:20:51 hagens Exp $"; 5436403Ssklower #endif lint 5536403Ssklower 5636403Ssklower #ifdef ISO 5736403Ssklower 5837469Ssklower #include "param.h" 5937469Ssklower #include "socket.h" 6037469Ssklower #include "socketvar.h" 6137469Ssklower #include "domain.h" 6237469Ssklower #include "malloc.h" 6337469Ssklower #include "mbuf.h" 6437469Ssklower #include "errno.h" 6537469Ssklower #include "time.h" 6637469Ssklower #include "protosw.h" 6737469Ssklower 6836403Ssklower #include "../net/if.h" 6936403Ssklower #include "../net/route.h" 7036403Ssklower 7137469Ssklower #include "argo_debug.h" 7237469Ssklower #include "tp_param.h" 7337469Ssklower #include "tp_stat.h" 7437469Ssklower #include "tp_pcb.h" 7537469Ssklower #include "tp_trace.h" 7637469Ssklower #include "tp_stat.h" 7737469Ssklower #include "tp_tpdu.h" 7837469Ssklower #include "tp_clnp.h" 7939926Ssklower #include "cltp_var.h" 8036403Ssklower 8136403Ssklower /* 8236403Ssklower * CALLED FROM: 8336403Ssklower * pr_usrreq() on PRU_BIND, PRU_CONNECT, PRU_ACCEPT, and PRU_PEERADDR 8437469Ssklower * FUNCTION, ARGUMENTS: 8536403Ssklower * The argument (which) takes the value TP_LOCAL or TP_FOREIGN. 8636403Ssklower */ 8736403Ssklower 8837469Ssklower iso_getsufx(isop, lenp, data_out, which) 8936403Ssklower struct isopcb *isop; 9037469Ssklower u_short *lenp; 9137469Ssklower caddr_t data_out; 9236403Ssklower int which; 9336403Ssklower { 9437469Ssklower register struct sockaddr_iso *addr = 0; 9537469Ssklower 9636403Ssklower switch (which) { 9736403Ssklower case TP_LOCAL: 9837469Ssklower addr = isop->isop_laddr; 9937469Ssklower break; 10036403Ssklower 10136403Ssklower case TP_FOREIGN: 10237469Ssklower addr = isop->isop_faddr; 10336403Ssklower } 10437469Ssklower if (addr) 10538841Ssklower bcopy(TSEL(addr), data_out, (*lenp = addr->siso_tlen)); 10636403Ssklower } 10736403Ssklower 10836403Ssklower /* CALLED FROM: 10936403Ssklower * tp_newsocket(); i.e., when a connection is being established by an 11036403Ssklower * incoming CR_TPDU. 11136403Ssklower * 11236403Ssklower * FUNCTION, ARGUMENTS: 11336403Ssklower * Put a transport suffix (found in name) into an isopcb structure (isop). 11436403Ssklower * The argument (which) takes the value TP_LOCAL or TP_FOREIGN. 11536403Ssklower */ 11636403Ssklower void 11737469Ssklower iso_putsufx(isop, sufxloc, sufxlen, which) 11836403Ssklower struct isopcb *isop; 11937469Ssklower caddr_t sufxloc; 12037469Ssklower int sufxlen, which; 12136403Ssklower { 12237469Ssklower struct sockaddr_iso **dst, *backup; 12337469Ssklower register struct sockaddr_iso *addr; 12437469Ssklower struct mbuf *m; 12537469Ssklower int len; 12637469Ssklower 12736403Ssklower switch (which) { 12837469Ssklower default: 12937469Ssklower return; 13037469Ssklower 13136403Ssklower case TP_LOCAL: 13237469Ssklower dst = &isop->isop_laddr; 13337469Ssklower backup = &isop->isop_sladdr; 13436403Ssklower break; 13537469Ssklower 13636403Ssklower case TP_FOREIGN: 13737469Ssklower dst = &isop->isop_faddr; 13837469Ssklower backup = &isop->isop_sfaddr; 13936403Ssklower } 14037469Ssklower if ((addr = *dst) == 0) { 14137469Ssklower addr = *dst = backup; 14237469Ssklower addr->siso_nlen = 0; 14338841Ssklower addr->siso_slen = 0; 14438841Ssklower addr->siso_plen = 0; 14537469Ssklower printf("iso_putsufx on un-initialized isopcb\n"); 14637469Ssklower } 14737469Ssklower len = sufxlen + addr->siso_nlen + 14838841Ssklower (sizeof(*addr) - sizeof(addr->siso_data)); 14937469Ssklower if (addr == backup) { 15038841Ssklower if (len > sizeof(*addr)) { 15137469Ssklower m = m_getclr(M_DONTWAIT, MT_SONAME); 15237469Ssklower if (m == 0) 15337469Ssklower return; 15437469Ssklower addr = *dst = mtod(m, struct sockaddr_iso *); 15537469Ssklower *addr = *backup; 15637469Ssklower m->m_len = len; 15737469Ssklower } 15838841Ssklower } 15937469Ssklower bcopy(sufxloc, TSEL(addr), sufxlen); 16038841Ssklower addr->siso_tlen = sufxlen; 16137469Ssklower addr->siso_len = len; 16236403Ssklower } 16336403Ssklower 16436403Ssklower /* 16536403Ssklower * CALLED FROM: 16636403Ssklower * tp.trans whenever we go into REFWAIT state. 16736403Ssklower * FUNCTION and ARGUMENT: 16836403Ssklower * Called when a ref is frozen, to allow the suffix to be reused. 16936403Ssklower * (isop) is the net level pcb. This really shouldn't have to be 17036403Ssklower * done in a NET level pcb but... for the internet world that just 17136403Ssklower * the way it is done in BSD... 17236403Ssklower * The alternative is to have the port unusable until the reference 17336403Ssklower * timer goes off. 17436403Ssklower */ 17536403Ssklower void 17636403Ssklower iso_recycle_tsuffix(isop) 17736403Ssklower struct isopcb *isop; 17836403Ssklower { 17938841Ssklower isop->isop_laddr->siso_tlen = isop->isop_faddr->siso_tlen = 0; 18036403Ssklower } 18136403Ssklower 18236403Ssklower /* 18336403Ssklower * CALLED FROM: 18436403Ssklower * tp_newsocket(); i.e., when a connection is being established by an 18536403Ssklower * incoming CR_TPDU. 18636403Ssklower * 18736403Ssklower * FUNCTION and ARGUMENTS: 18836403Ssklower * Copy a whole net addr from a struct sockaddr (name). 18936403Ssklower * into an isopcb (isop). 19036403Ssklower * The argument (which) takes values TP_LOCAL or TP_FOREIGN 19136403Ssklower */ 19236403Ssklower void 19336403Ssklower iso_putnetaddr(isop, name, which) 19436403Ssklower register struct isopcb *isop; 19536403Ssklower struct sockaddr_iso *name; 19636403Ssklower int which; 19736403Ssklower { 19837469Ssklower struct sockaddr_iso **sisop, *backup; 19937469Ssklower register struct sockaddr_iso *siso; 20037469Ssklower 20136403Ssklower switch (which) { 20236403Ssklower case TP_LOCAL: 20337469Ssklower sisop = &isop->isop_laddr; 20437469Ssklower backup = &isop->isop_sladdr; 20536403Ssklower break; 20636403Ssklower case TP_FOREIGN: 20737469Ssklower sisop = &isop->isop_faddr; 20837469Ssklower backup = &isop->isop_sfaddr; 20936403Ssklower } 21037469Ssklower siso = ((*sisop == 0) ? (*sisop = backup) : *sisop); 21137469Ssklower IFDEBUG(D_TPISO) 21237469Ssklower printf("ISO_PUTNETADDR\n"); 21337469Ssklower dump_isoaddr(isop->isop_faddr); 21437469Ssklower ENDDEBUG 21537469Ssklower siso->siso_addr = name->siso_addr; 21636403Ssklower } 21736403Ssklower 21836403Ssklower /* 21936403Ssklower * CALLED FROM: 22036403Ssklower * pr_usrreq() PRU_SOCKADDR, PRU_ACCEPT, PRU_PEERADDR 22136403Ssklower * FUNCTION and ARGUMENTS: 22236403Ssklower * Copy a whole net addr from an isopcb (isop) into 22336403Ssklower * a struct sockaddr (name). 22436403Ssklower * The argument (which) takes values TP_LOCAL or TP_FOREIGN. 22536403Ssklower */ 22636403Ssklower 22736403Ssklower void 22836403Ssklower iso_getnetaddr( isop, name, which) 22936403Ssklower struct isopcb *isop; 23037469Ssklower struct mbuf *name; 23136403Ssklower int which; 23236403Ssklower { 23337469Ssklower struct sockaddr_iso *siso = 23437469Ssklower (which == TP_LOCAL ? isop->isop_laddr : isop->isop_faddr); 23537469Ssklower if (siso) 23637469Ssklower bcopy((caddr_t)siso, mtod(name, caddr_t), 23737469Ssklower (unsigned)(name->m_len = siso->siso_len)); 23837469Ssklower else 23937469Ssklower name->m_len = 0; 24036403Ssklower } 24136403Ssklower 24236403Ssklower /* 24336403Ssklower * CALLED FROM: 24436403Ssklower * tp_input() on incoming CR, CC, and pr_usrreq() for PRU_CONNECT 24536403Ssklower * FUNCTION, ARGUMENTS, SIDE EFFECTS and RETURN VALUE: 24636403Ssklower * Determine the proper maximum transmission unit, i.e., MTU, to use, given 24736403Ssklower * a) the header size for the network protocol and the max transmission 24836403Ssklower * unit on the subnet interface, determined from the information in (isop), 24936403Ssklower * b) the max size negotiated so far (negot) 25036403Ssklower * c) the window size used by the tp connection (found in so), 25136403Ssklower * 25236403Ssklower * The result is put in the integer *size in its integer form and in 25336403Ssklower * *negot in its logarithmic form. 25436403Ssklower * 25536403Ssklower * The rules are: 25636403Ssklower * a) can only negotiate down from the value found in *negot. 25736403Ssklower * b) the MTU must be < the windowsize, 25836403Ssklower * c) If src and dest are on the same net, 25936403Ssklower * we will negotiate the closest size larger than MTU but really USE 26036403Ssklower * the actual device mtu - ll hdr sizes. 26136403Ssklower * otherwise we negotiate the closest size smaller than MTU - ll hdr sizes. 26236403Ssklower */ 26336403Ssklower 26436403Ssklower void 26536403Ssklower tpclnp_mtu(so, isop, size, negot ) 26636403Ssklower struct socket *so; 26736403Ssklower struct isopcb *isop; 26836403Ssklower int *size; 26936403Ssklower u_char *negot; 27036403Ssklower { 27139230Ssklower struct ifnet *ifp = 0; 27239230Ssklower struct iso_ifaddr *ia = 0; 27336403Ssklower register int i; 27436403Ssklower int windowsize = so->so_rcv.sb_hiwat; 27536403Ssklower int clnp_size; 27636403Ssklower int sizeismtu = 0; 27739230Ssklower register struct rtentry *rt = isop->isop_route.ro_rt; 27836403Ssklower 27936403Ssklower IFDEBUG(D_CONN) 28036403Ssklower printf("tpclnp_mtu(0x%x,0x%x,0x%x,0x%x)\n", so, isop, size, negot); 28136403Ssklower ENDDEBUG 28236403Ssklower IFTRACE(D_CONN) 28336403Ssklower tptrace(TPPTmisc, "ENTER GET MTU: size negot \n",*size, *negot, 0, 0); 28436403Ssklower ENDTRACE 28536403Ssklower 28636403Ssklower *size = 1 << *negot; 28736403Ssklower 28836403Ssklower if( *size > windowsize ) { 28936403Ssklower *size = windowsize; 29036403Ssklower } 29136403Ssklower 29239230Ssklower if (rt == 0 || (rt->rt_flags & RTF_UP == 0) || 29339230Ssklower (ia = (struct iso_ifaddr *)rt->rt_ifa) == 0 || 29439230Ssklower (ifp = ia->ia_ifp) == 0) { 29539230Ssklower IFDEBUG(D_CONN) 29639230Ssklower printf("tpclnp_mtu routing abort rt=0x%x ia=0x%x ifp=0x%x\n", 29739230Ssklower rt, ia, ifp) 29839230Ssklower ENDDEBUG 29936403Ssklower return; 30039230Ssklower } 30136403Ssklower 30236403Ssklower /* TODO - make this indirect off the socket structure to the 30336403Ssklower * network layer to get headersize 30436403Ssklower */ 30537469Ssklower if (isop->isop_laddr) 30637469Ssklower clnp_size = clnp_hdrsize(isop->isop_laddr->siso_addr.isoa_len); 30737469Ssklower else 30837469Ssklower clnp_size = 20; 30936403Ssklower 31036403Ssklower if(*size > ifp->if_mtu - clnp_size) { 31136403Ssklower *size = ifp->if_mtu - clnp_size; 31236403Ssklower sizeismtu = 1; 31336403Ssklower } 31437469Ssklower /* have to transform size to the log2 of size */ 31537469Ssklower for(i=TP_MIN_TPDUSIZE; (i<TP_MAX_TPDUSIZE && ((1<<i) <= *size)) ; i++) 31637469Ssklower ; 31737469Ssklower i--; 31837469Ssklower 31936403Ssklower IFTRACE(D_CONN) 32036403Ssklower tptrace(TPPTmisc, "GET MTU MID: tpcb size negot i \n", 32136403Ssklower *size, *negot, i, 0); 32236403Ssklower ENDTRACE 32336403Ssklower 32439926Ssklower *size = 1<<i; 32536403Ssklower *negot = i; 32636403Ssklower 32736403Ssklower IFDEBUG(D_CONN) 32836403Ssklower printf("GET MTU RETURNS: ifp %s size 0x%x negot 0x%x\n", 32936403Ssklower ifp->if_name, *size, *negot); 33036403Ssklower ENDDEBUG 33136403Ssklower IFTRACE(D_CONN) 33236403Ssklower tptrace(TPPTmisc, "EXIT GET MTU: tpcb size negot \n", 33336403Ssklower *size, *negot, 0, 0); 33436403Ssklower ENDTRACE 33536403Ssklower } 33636403Ssklower 33736403Ssklower 33836403Ssklower /* 33936403Ssklower * CALLED FROM: 34036403Ssklower * tp_emit() 34136403Ssklower * FUNCTION and ARGUMENTS: 34236403Ssklower * Take a packet(m0) from tp and package it so that clnp will accept it. 34336403Ssklower * This means prepending space for the clnp header and filling in a few 34436403Ssklower * of the fields. 34536403Ssklower * inp is the isopcb structure; datalen is the length of the data in the 34636403Ssklower * mbuf string m0. 34736403Ssklower * RETURN VALUE: 34836403Ssklower * whatever (E*) is returned form the net layer output routine. 34936403Ssklower */ 35036403Ssklower 35136403Ssklower int 35236403Ssklower tpclnp_output(isop, m0, datalen, nochksum) 35336403Ssklower struct isopcb *isop; 35436403Ssklower struct mbuf *m0; 35536403Ssklower int datalen; 35636403Ssklower int nochksum; 35736403Ssklower { 35837469Ssklower register struct mbuf *m = m0; 35936403Ssklower IncStat(ts_tpdu_sent); 36036403Ssklower 36136403Ssklower IFDEBUG(D_TPISO) 36236403Ssklower struct tpdu *hdr = mtod(m0, struct tpdu *); 36336403Ssklower 36436403Ssklower printf( 36536403Ssklower "abt to call clnp_output: datalen 0x%x, hdr.li 0x%x, hdr.dutype 0x%x nocsum x%x dst addr:\n", 36636403Ssklower datalen, 36736403Ssklower (int)hdr->tpdu_li, (int)hdr->tpdu_type, nochksum); 36837469Ssklower dump_isoaddr(isop->isop_faddr); 36936403Ssklower printf("\nsrc addr:\n"); 37037469Ssklower dump_isoaddr(isop->isop_laddr); 37136403Ssklower dump_mbuf(m0, "at tpclnp_output"); 37236403Ssklower ENDDEBUG 37336403Ssklower 37436403Ssklower return 37538841Ssklower clnp_output(m0, isop, datalen, /* flags */nochksum ? CLNP_NO_CKSUM : 0); 37636403Ssklower } 37736403Ssklower 37836403Ssklower /* 37936403Ssklower * CALLED FROM: 38036403Ssklower * tp_error_emit() 38136403Ssklower * FUNCTION and ARGUMENTS: 38236403Ssklower * This is a copy of tpclnp_output that takes the addresses 38336403Ssklower * instead of a pcb. It's used by the tp_error_emit, when we 38436403Ssklower * don't have an iso_pcb with which to call the normal output rtn. 38536403Ssklower * RETURN VALUE: 38636403Ssklower * ENOBUFS or 38736403Ssklower * whatever (E*) is returned form the net layer output routine. 38836403Ssklower */ 38936403Ssklower 39036403Ssklower int 39136403Ssklower tpclnp_output_dg(laddr, faddr, m0, datalen, ro, nochksum) 39236403Ssklower struct iso_addr *laddr, *faddr; 39336403Ssklower struct mbuf *m0; 39436403Ssklower int datalen; 39536403Ssklower struct route *ro; 39636403Ssklower int nochksum; 39736403Ssklower { 39836403Ssklower struct isopcb tmppcb; 39936403Ssklower int err; 40036403Ssklower int flags; 40137469Ssklower register struct mbuf *m = m0; 40236403Ssklower 40336403Ssklower IFDEBUG(D_TPISO) 40436403Ssklower printf("tpclnp_output_dg datalen 0x%x m0 0x%x\n", datalen, m0); 40536403Ssklower ENDDEBUG 40636403Ssklower 40736403Ssklower /* 40836403Ssklower * Fill in minimal portion of isopcb so that clnp can send the 40936403Ssklower * packet. 41036403Ssklower */ 41136403Ssklower bzero((caddr_t)&tmppcb, sizeof(tmppcb)); 41237469Ssklower tmppcb.isop_laddr = &tmppcb.isop_sladdr; 41337469Ssklower tmppcb.isop_laddr->siso_addr = *laddr; 41437469Ssklower tmppcb.isop_faddr = &tmppcb.isop_sfaddr; 41537469Ssklower tmppcb.isop_faddr->siso_addr = *faddr; 41636403Ssklower 41736403Ssklower IFDEBUG(D_TPISO) 41836403Ssklower printf("tpclnp_output_dg faddr: \n"); 41937469Ssklower dump_isoaddr(&tmppcb.isop_sfaddr); 42036403Ssklower printf("\ntpclnp_output_dg laddr: \n"); 42137469Ssklower dump_isoaddr(&tmppcb.isop_sladdr); 42236403Ssklower printf("\n"); 42336403Ssklower ENDDEBUG 42436403Ssklower 42536403Ssklower /* 42636403Ssklower * Do not use packet cache since this is a one shot error packet 42736403Ssklower */ 42836403Ssklower flags = (CLNP_NOCACHE|(nochksum?CLNP_NO_CKSUM:0)); 42936403Ssklower 43036403Ssklower IncStat(ts_tpdu_sent); 43136403Ssklower 43238841Ssklower err = clnp_output(m0, &tmppcb, datalen, flags); 43336403Ssklower 43436403Ssklower /* 43536403Ssklower * Free route allocated by clnp (if the route was indeed allocated) 43636403Ssklower */ 43736403Ssklower if (tmppcb.isop_route.ro_rt) 43836403Ssklower RTFREE(tmppcb.isop_route.ro_rt); 43936403Ssklower 44036403Ssklower return(err); 44136403Ssklower } 44236403Ssklower /* 44336403Ssklower * CALLED FROM: 44436403Ssklower * clnp's input routine, indirectly through the protosw. 44536403Ssklower * FUNCTION and ARGUMENTS: 44636403Ssklower * Take a packet (m) from clnp, strip off the clnp header and give it to tp 44736403Ssklower * No return value. 44836403Ssklower */ 44936403Ssklower ProtoHook 450*39927Ssklower tpclnp_input(m, src, dst, clnp_len, ce_bit) 45139926Ssklower register struct mbuf *m; 45239926Ssklower struct sockaddr_iso *src, *dst; 453*39927Ssklower int clnp_len, ce_bit; 45436403Ssklower { 45536403Ssklower int s = splnet(); 45637469Ssklower struct mbuf *tp_inputprep(); 45739926Ssklower int tp_input(), cltp_input(), (*input)() = tp_input; 45836403Ssklower 45936403Ssklower IncStat(ts_pkt_rcvd); 46036403Ssklower 46136403Ssklower IFDEBUG(D_TPINPUT) 46236403Ssklower printf("tpclnp_input: m 0x%x clnp_len 0x%x\n", m, clnp_len); 46336403Ssklower dump_mbuf(m, "at tpclnp_input"); 46436403Ssklower ENDDEBUG 46536403Ssklower /* 46636403Ssklower * CLNP gives us an mbuf chain WITH the clnp header pulled up, 46736403Ssklower * and the length of the clnp header. 46836403Ssklower * First, strip off the Clnp header. leave the mbuf there for the 46936403Ssklower * pullup that follows. 47036403Ssklower */ 47136403Ssklower 47236403Ssklower m->m_len -= clnp_len; 47337469Ssklower m->m_data += clnp_len; 47436403Ssklower 47537469Ssklower m = tp_inputprep(m); 47639926Ssklower if (m == 0) 47739926Ssklower return 0; 47839926Ssklower if (mtod(m, u_char *)[1] == UD_TPDU_type) 47939926Ssklower input = cltp_input; 48036403Ssklower 48136403Ssklower IFDEBUG(D_TPINPUT) 48236403Ssklower dump_mbuf(m, "after tpclnp_input both pullups"); 48336403Ssklower ENDDEBUG 48436403Ssklower 48536403Ssklower IFDEBUG(D_TPISO) 48639926Ssklower printf("calling %sinput : src 0x%x, dst 0x%x, src addr:\n", 48739926Ssklower (input == tp_input ? "tp_" : "clts_"), src, dst); 48839926Ssklower dump_isoaddr(src); 48936403Ssklower printf(" dst addr:\n"); 49039926Ssklower dump_isoaddr(dst); 49136403Ssklower ENDDEBUG 49236403Ssklower 49339926Ssklower (void) (*input)(m, (struct sockaddr *)src, (struct sockaddr *)dst, 494*39927Ssklower 0, tpclnp_output_dg, ce_bit); 49536403Ssklower 49636403Ssklower IFDEBUG(D_QUENCH) 49736403Ssklower { 49836403Ssklower if(time.tv_usec & 0x4 && time.tv_usec & 0x40) { 49936403Ssklower printf("tpclnp_input: FAKING %s\n", 50036403Ssklower tp_stat.ts_pkt_rcvd & 0x1?"QUENCH":"QUENCH2"); 50136403Ssklower if(tp_stat.ts_pkt_rcvd & 0x1) { 50236403Ssklower tpclnp_ctlinput(PRC_QUENCH, &src); 50336403Ssklower } else { 50436403Ssklower tpclnp_ctlinput(PRC_QUENCH2, &src); 50536403Ssklower } 50636403Ssklower } 50736403Ssklower } 50836403Ssklower ENDDEBUG 50936403Ssklower 51036403Ssklower splx(s); 51136403Ssklower return 0; 51236403Ssklower } 51336403Ssklower 51436403Ssklower ProtoHook 51536403Ssklower iso_rtchange() 51636403Ssklower { 51736403Ssklower return 0; 51836403Ssklower } 51936403Ssklower 52036403Ssklower /* 52136403Ssklower * CALLED FROM: 52236403Ssklower * tpclnp_ctlinput() 52336403Ssklower * FUNCTION and ARGUMENTS: 52436403Ssklower * find the tpcb pointer and pass it to tp_quench 52536403Ssklower */ 52636403Ssklower void 52736403Ssklower tpiso_decbit(isop) 52836403Ssklower struct isopcb *isop; 52936403Ssklower { 53037469Ssklower tp_quench((struct tp_pcb *)isop->isop_socket->so_tpcb, PRC_QUENCH2); 53136403Ssklower } 53236403Ssklower /* 53336403Ssklower * CALLED FROM: 53436403Ssklower * tpclnp_ctlinput() 53536403Ssklower * FUNCTION and ARGUMENTS: 53636403Ssklower * find the tpcb pointer and pass it to tp_quench 53736403Ssklower */ 53836403Ssklower void 53936403Ssklower tpiso_quench(isop) 54036403Ssklower struct isopcb *isop; 54136403Ssklower { 54237469Ssklower tp_quench((struct tp_pcb *)isop->isop_socket->so_tpcb, PRC_QUENCH); 54336403Ssklower } 54436403Ssklower 54536403Ssklower /* 54636403Ssklower * CALLED FROM: 54736403Ssklower * The network layer through the protosw table. 54836403Ssklower * FUNCTION and ARGUMENTS: 54936403Ssklower * When clnp an ICMP-like msg this gets called. 55036403Ssklower * It either returns an error status to the user or 55136403Ssklower * it causes all connections on this address to be aborted 55236403Ssklower * by calling the appropriate xx_notify() routine. 55336403Ssklower * (cmd) is the type of ICMP error. 55436403Ssklower * (siso) is the address of the guy who sent the ER CLNPDU 55536403Ssklower */ 55636403Ssklower ProtoHook 55736403Ssklower tpclnp_ctlinput(cmd, siso) 55836403Ssklower int cmd; 55936403Ssklower struct sockaddr_iso *siso; 56036403Ssklower { 56136403Ssklower extern u_char inetctlerrmap[]; 56236403Ssklower extern ProtoHook tpiso_abort(); 56336403Ssklower extern ProtoHook iso_rtchange(); 56436403Ssklower extern ProtoHook tpiso_reset(); 56537469Ssklower void iso_pcbnotify(); 56636403Ssklower 56736403Ssklower IFDEBUG(D_TPINPUT) 56839926Ssklower printf("tpclnp_ctlinput1: cmd 0x%x addr: \n", cmd); 56939926Ssklower dump_isoaddr(siso); 57036403Ssklower ENDDEBUG 57136403Ssklower 57236403Ssklower if (cmd < 0 || cmd > PRC_NCMDS) 57336403Ssklower return 0; 57439926Ssklower if (siso->siso_family != AF_ISO) 57539926Ssklower return 0; 57636403Ssklower switch (cmd) { 57736403Ssklower 57836403Ssklower case PRC_QUENCH2: 57939926Ssklower iso_pcbnotify(&tp_isopcb, siso, 0, (int (*)())tpiso_decbit); 58036403Ssklower break; 58136403Ssklower 58236403Ssklower case PRC_QUENCH: 58339926Ssklower iso_pcbnotify(&tp_isopcb, siso, 0, (int (*)())tpiso_quench); 58436403Ssklower break; 58536403Ssklower 58636403Ssklower case PRC_TIMXCEED_REASS: 58736403Ssklower case PRC_ROUTEDEAD: 58839926Ssklower iso_pcbnotify(&tp_isopcb, siso, 0, tpiso_reset); 58936403Ssklower break; 59036403Ssklower 59136403Ssklower case PRC_HOSTUNREACH: 59236403Ssklower case PRC_UNREACH_NET: 59336403Ssklower case PRC_IFDOWN: 59436403Ssklower case PRC_HOSTDEAD: 59539926Ssklower iso_pcbnotify(&tp_isopcb, siso, 59636403Ssklower (int)inetctlerrmap[cmd], iso_rtchange); 59736403Ssklower break; 59836403Ssklower 59936403Ssklower default: 60036403Ssklower /* 60136403Ssklower case PRC_MSGSIZE: 60236403Ssklower case PRC_UNREACH_HOST: 60336403Ssklower case PRC_UNREACH_PROTOCOL: 60436403Ssklower case PRC_UNREACH_PORT: 60536403Ssklower case PRC_UNREACH_NEEDFRAG: 60636403Ssklower case PRC_UNREACH_SRCFAIL: 60736403Ssklower case PRC_REDIRECT_NET: 60836403Ssklower case PRC_REDIRECT_HOST: 60936403Ssklower case PRC_REDIRECT_TOSNET: 61036403Ssklower case PRC_REDIRECT_TOSHOST: 61136403Ssklower case PRC_TIMXCEED_INTRANS: 61236403Ssklower case PRC_PARAMPROB: 61336403Ssklower */ 61439926Ssklower iso_pcbnotify(&tp_isopcb, siso, (int)inetctlerrmap[cmd], tpiso_abort); 61536403Ssklower break; 61636403Ssklower } 61736403Ssklower return 0; 61836403Ssklower } 61939926Ssklower /* 62039926Ssklower * XXX - Variant which is called by clnp_er.c with an isoaddr rather 62139926Ssklower * than a sockaddr_iso. 62239926Ssklower */ 62336403Ssklower 62439926Ssklower static struct sockaddr_iso siso = {sizeof(siso), AF_ISO}; 62539926Ssklower tpclnp_ctlinput1(cmd, isoa) 62639926Ssklower int cmd; 62739926Ssklower struct iso_addr *isoa; 62839926Ssklower { 62939926Ssklower bzero((caddr_t)&siso.siso_addr, sizeof(siso.siso_addr)); 63039926Ssklower bcopy((caddr_t)isoa, (caddr_t)&siso.siso_addr, isoa->isoa_len); 63139926Ssklower tpclnp_ctlinput(cmd, &siso); 63239926Ssklower } 63339926Ssklower 63436403Ssklower /* 63536403Ssklower * These next 2 routines are 63636403Ssklower * CALLED FROM: 63736403Ssklower * xxx_notify() from tp_ctlinput() when 63836403Ssklower * net level gets some ICMP-equiv. type event. 63936403Ssklower * FUNCTION and ARGUMENTS: 64036403Ssklower * Cause the connection to be aborted with some sort of error 64136403Ssklower * reason indicating that the network layer caused the abort. 64236403Ssklower * Fakes an ER TPDU so we can go through the driver. 64336403Ssklower * abort always aborts the TP connection. 64436403Ssklower * reset may or may not, depending on the TP class that's in use. 64536403Ssklower */ 64636403Ssklower ProtoHook 64736403Ssklower tpiso_abort(isop) 64836403Ssklower struct isopcb *isop; 64936403Ssklower { 65036403Ssklower struct tp_event e; 65136403Ssklower 65236403Ssklower IFDEBUG(D_CONN) 65336403Ssklower printf("tpiso_abort 0x%x\n", isop); 65436403Ssklower ENDDEBUG 65536403Ssklower e.ev_number = ER_TPDU; 65636403Ssklower e.ATTR(ER_TPDU).e_reason = ECONNABORTED; 65736403Ssklower return tp_driver((struct tp_pcb *)isop->isop_socket->so_tpcb, &e); 65836403Ssklower } 65936403Ssklower 66036403Ssklower ProtoHook 66136403Ssklower tpiso_reset(isop) 66236403Ssklower struct isopcb *isop; 66336403Ssklower { 66436403Ssklower struct tp_event e; 66536403Ssklower 66636403Ssklower e.ev_number = T_NETRESET; 66736403Ssklower return tp_driver((struct tp_pcb *)isop->isop_socket->so_tpcb, &e); 66836403Ssklower 66936403Ssklower } 67036403Ssklower 67139926Ssklower #include "cltp_usrreq.c" 67236403Ssklower #endif ISO 673