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*39230Ssklower * @(#)tp_iso.c 7.4 (Berkeley) 09/26/89 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" 7936403Ssklower 8036403Ssklower /* 8136403Ssklower * CALLED FROM: 8236403Ssklower * pr_usrreq() on PRU_BIND, PRU_CONNECT, PRU_ACCEPT, and PRU_PEERADDR 8337469Ssklower * FUNCTION, ARGUMENTS: 8436403Ssklower * The argument (which) takes the value TP_LOCAL or TP_FOREIGN. 8536403Ssklower */ 8636403Ssklower 8737469Ssklower iso_getsufx(isop, lenp, data_out, which) 8836403Ssklower struct isopcb *isop; 8937469Ssklower u_short *lenp; 9037469Ssklower caddr_t data_out; 9136403Ssklower int which; 9236403Ssklower { 9337469Ssklower register struct sockaddr_iso *addr = 0; 9437469Ssklower 9536403Ssklower switch (which) { 9636403Ssklower case TP_LOCAL: 9737469Ssklower addr = isop->isop_laddr; 9837469Ssklower break; 9936403Ssklower 10036403Ssklower case TP_FOREIGN: 10137469Ssklower addr = isop->isop_faddr; 10236403Ssklower } 10337469Ssklower if (addr) 10438841Ssklower bcopy(TSEL(addr), data_out, (*lenp = addr->siso_tlen)); 10536403Ssklower } 10636403Ssklower 10736403Ssklower /* CALLED FROM: 10836403Ssklower * tp_newsocket(); i.e., when a connection is being established by an 10936403Ssklower * incoming CR_TPDU. 11036403Ssklower * 11136403Ssklower * FUNCTION, ARGUMENTS: 11236403Ssklower * Put a transport suffix (found in name) into an isopcb structure (isop). 11336403Ssklower * The argument (which) takes the value TP_LOCAL or TP_FOREIGN. 11436403Ssklower */ 11536403Ssklower void 11637469Ssklower iso_putsufx(isop, sufxloc, sufxlen, which) 11736403Ssklower struct isopcb *isop; 11837469Ssklower caddr_t sufxloc; 11937469Ssklower int sufxlen, which; 12036403Ssklower { 12137469Ssklower struct sockaddr_iso **dst, *backup; 12237469Ssklower register struct sockaddr_iso *addr; 12337469Ssklower struct mbuf *m; 12437469Ssklower int len; 12537469Ssklower 12636403Ssklower switch (which) { 12737469Ssklower default: 12837469Ssklower return; 12937469Ssklower 13036403Ssklower case TP_LOCAL: 13137469Ssklower dst = &isop->isop_laddr; 13237469Ssklower backup = &isop->isop_sladdr; 13336403Ssklower break; 13437469Ssklower 13536403Ssklower case TP_FOREIGN: 13637469Ssklower dst = &isop->isop_faddr; 13737469Ssklower backup = &isop->isop_sfaddr; 13836403Ssklower } 13937469Ssklower if ((addr = *dst) == 0) { 14037469Ssklower addr = *dst = backup; 14137469Ssklower addr->siso_nlen = 0; 14238841Ssklower addr->siso_slen = 0; 14338841Ssklower addr->siso_plen = 0; 14437469Ssklower printf("iso_putsufx on un-initialized isopcb\n"); 14537469Ssklower } 14637469Ssklower len = sufxlen + addr->siso_nlen + 14738841Ssklower (sizeof(*addr) - sizeof(addr->siso_data)); 14837469Ssklower if (addr == backup) { 14938841Ssklower if (len > sizeof(*addr)) { 15037469Ssklower m = m_getclr(M_DONTWAIT, MT_SONAME); 15137469Ssklower if (m == 0) 15237469Ssklower return; 15337469Ssklower addr = *dst = mtod(m, struct sockaddr_iso *); 15437469Ssklower *addr = *backup; 15537469Ssklower m->m_len = len; 15637469Ssklower } 15738841Ssklower } 15837469Ssklower bcopy(sufxloc, TSEL(addr), sufxlen); 15938841Ssklower addr->siso_tlen = sufxlen; 16037469Ssklower addr->siso_len = len; 16136403Ssklower } 16236403Ssklower 16336403Ssklower /* 16436403Ssklower * CALLED FROM: 16536403Ssklower * tp.trans whenever we go into REFWAIT state. 16636403Ssklower * FUNCTION and ARGUMENT: 16736403Ssklower * Called when a ref is frozen, to allow the suffix to be reused. 16836403Ssklower * (isop) is the net level pcb. This really shouldn't have to be 16936403Ssklower * done in a NET level pcb but... for the internet world that just 17036403Ssklower * the way it is done in BSD... 17136403Ssklower * The alternative is to have the port unusable until the reference 17236403Ssklower * timer goes off. 17336403Ssklower */ 17436403Ssklower void 17536403Ssklower iso_recycle_tsuffix(isop) 17636403Ssklower struct isopcb *isop; 17736403Ssklower { 17838841Ssklower isop->isop_laddr->siso_tlen = isop->isop_faddr->siso_tlen = 0; 17936403Ssklower } 18036403Ssklower 18136403Ssklower /* 18236403Ssklower * CALLED FROM: 18336403Ssklower * tp_newsocket(); i.e., when a connection is being established by an 18436403Ssklower * incoming CR_TPDU. 18536403Ssklower * 18636403Ssklower * FUNCTION and ARGUMENTS: 18736403Ssklower * Copy a whole net addr from a struct sockaddr (name). 18836403Ssklower * into an isopcb (isop). 18936403Ssklower * The argument (which) takes values TP_LOCAL or TP_FOREIGN 19036403Ssklower */ 19136403Ssklower void 19236403Ssklower iso_putnetaddr(isop, name, which) 19336403Ssklower register struct isopcb *isop; 19436403Ssklower struct sockaddr_iso *name; 19536403Ssklower int which; 19636403Ssklower { 19737469Ssklower struct sockaddr_iso **sisop, *backup; 19837469Ssklower register struct sockaddr_iso *siso; 19937469Ssklower 20036403Ssklower switch (which) { 20136403Ssklower case TP_LOCAL: 20237469Ssklower sisop = &isop->isop_laddr; 20337469Ssklower backup = &isop->isop_sladdr; 20436403Ssklower break; 20536403Ssklower case TP_FOREIGN: 20637469Ssklower sisop = &isop->isop_faddr; 20737469Ssklower backup = &isop->isop_sfaddr; 20836403Ssklower } 20937469Ssklower siso = ((*sisop == 0) ? (*sisop = backup) : *sisop); 21037469Ssklower IFDEBUG(D_TPISO) 21137469Ssklower printf("ISO_PUTNETADDR\n"); 21237469Ssklower dump_isoaddr(isop->isop_faddr); 21337469Ssklower ENDDEBUG 21437469Ssklower siso->siso_addr = name->siso_addr; 21536403Ssklower } 21636403Ssklower 21736403Ssklower /* 21836403Ssklower * CALLED FROM: 21936403Ssklower * pr_usrreq() PRU_SOCKADDR, PRU_ACCEPT, PRU_PEERADDR 22036403Ssklower * FUNCTION and ARGUMENTS: 22136403Ssklower * Copy a whole net addr from an isopcb (isop) into 22236403Ssklower * a struct sockaddr (name). 22336403Ssklower * The argument (which) takes values TP_LOCAL or TP_FOREIGN. 22436403Ssklower */ 22536403Ssklower 22636403Ssklower void 22736403Ssklower iso_getnetaddr( isop, name, which) 22836403Ssklower struct isopcb *isop; 22937469Ssklower struct mbuf *name; 23036403Ssklower int which; 23136403Ssklower { 23237469Ssklower struct sockaddr_iso *siso = 23337469Ssklower (which == TP_LOCAL ? isop->isop_laddr : isop->isop_faddr); 23437469Ssklower if (siso) 23537469Ssklower bcopy((caddr_t)siso, mtod(name, caddr_t), 23637469Ssklower (unsigned)(name->m_len = siso->siso_len)); 23737469Ssklower else 23837469Ssklower name->m_len = 0; 23936403Ssklower } 24036403Ssklower 24136403Ssklower /* 24236403Ssklower * CALLED FROM: 24336403Ssklower * tp_input() on incoming CR, CC, and pr_usrreq() for PRU_CONNECT 24436403Ssklower * FUNCTION, ARGUMENTS, SIDE EFFECTS and RETURN VALUE: 24536403Ssklower * Determine the proper maximum transmission unit, i.e., MTU, to use, given 24636403Ssklower * a) the header size for the network protocol and the max transmission 24736403Ssklower * unit on the subnet interface, determined from the information in (isop), 24836403Ssklower * b) the max size negotiated so far (negot) 24936403Ssklower * c) the window size used by the tp connection (found in so), 25036403Ssklower * 25136403Ssklower * The result is put in the integer *size in its integer form and in 25236403Ssklower * *negot in its logarithmic form. 25336403Ssklower * 25436403Ssklower * The rules are: 25536403Ssklower * a) can only negotiate down from the value found in *negot. 25636403Ssklower * b) the MTU must be < the windowsize, 25736403Ssklower * c) If src and dest are on the same net, 25836403Ssklower * we will negotiate the closest size larger than MTU but really USE 25936403Ssklower * the actual device mtu - ll hdr sizes. 26036403Ssklower * otherwise we negotiate the closest size smaller than MTU - ll hdr sizes. 26136403Ssklower */ 26236403Ssklower 26336403Ssklower void 26436403Ssklower tpclnp_mtu(so, isop, size, negot ) 26536403Ssklower struct socket *so; 26636403Ssklower struct isopcb *isop; 26736403Ssklower int *size; 26836403Ssklower u_char *negot; 26936403Ssklower { 270*39230Ssklower struct ifnet *ifp = 0; 271*39230Ssklower struct iso_ifaddr *ia = 0; 27236403Ssklower register int i; 27336403Ssklower int windowsize = so->so_rcv.sb_hiwat; 27436403Ssklower int clnp_size; 27536403Ssklower int sizeismtu = 0; 276*39230Ssklower register struct rtentry *rt = isop->isop_route.ro_rt; 27736403Ssklower 27836403Ssklower IFDEBUG(D_CONN) 27936403Ssklower printf("tpclnp_mtu(0x%x,0x%x,0x%x,0x%x)\n", so, isop, size, negot); 28036403Ssklower ENDDEBUG 28136403Ssklower IFTRACE(D_CONN) 28236403Ssklower tptrace(TPPTmisc, "ENTER GET MTU: size negot \n",*size, *negot, 0, 0); 28336403Ssklower ENDTRACE 28436403Ssklower 28536403Ssklower *size = 1 << *negot; 28636403Ssklower 28736403Ssklower if( *size > windowsize ) { 28836403Ssklower *size = windowsize; 28936403Ssklower } 29036403Ssklower 291*39230Ssklower if (rt == 0 || (rt->rt_flags & RTF_UP == 0) || 292*39230Ssklower (ia = (struct iso_ifaddr *)rt->rt_ifa) == 0 || 293*39230Ssklower (ifp = ia->ia_ifp) == 0) { 294*39230Ssklower IFDEBUG(D_CONN) 295*39230Ssklower printf("tpclnp_mtu routing abort rt=0x%x ia=0x%x ifp=0x%x\n", 296*39230Ssklower rt, ia, ifp) 297*39230Ssklower ENDDEBUG 29836403Ssklower return; 299*39230Ssklower } 30036403Ssklower 30136403Ssklower /* TODO - make this indirect off the socket structure to the 30236403Ssklower * network layer to get headersize 30336403Ssklower */ 30437469Ssklower if (isop->isop_laddr) 30537469Ssklower clnp_size = clnp_hdrsize(isop->isop_laddr->siso_addr.isoa_len); 30637469Ssklower else 30737469Ssklower clnp_size = 20; 30836403Ssklower 30936403Ssklower if(*size > ifp->if_mtu - clnp_size) { 31036403Ssklower *size = ifp->if_mtu - clnp_size; 31136403Ssklower sizeismtu = 1; 31236403Ssklower } 31337469Ssklower /* have to transform size to the log2 of size */ 31437469Ssklower for(i=TP_MIN_TPDUSIZE; (i<TP_MAX_TPDUSIZE && ((1<<i) <= *size)) ; i++) 31537469Ssklower ; 31637469Ssklower i--; 31737469Ssklower 31836403Ssklower IFTRACE(D_CONN) 31936403Ssklower tptrace(TPPTmisc, "GET MTU MID: tpcb size negot i \n", 32036403Ssklower *size, *negot, i, 0); 32136403Ssklower ENDTRACE 32236403Ssklower 32336403Ssklower /* are we on the same LAN? if so, negotiate one tpdu size larger, 32436403Ssklower * and actually send the real mtu size 32536403Ssklower */ 32637469Ssklower if (iso_localifa(isop->isop_faddr)) { 32736403Ssklower i++; 32836403Ssklower } else { 32936403Ssklower *size = 1<<i; 33036403Ssklower } 33136403Ssklower *negot = i; 33236403Ssklower 33336403Ssklower IFDEBUG(D_CONN) 33436403Ssklower printf("GET MTU RETURNS: ifp %s size 0x%x negot 0x%x\n", 33536403Ssklower ifp->if_name, *size, *negot); 33636403Ssklower ENDDEBUG 33736403Ssklower IFTRACE(D_CONN) 33836403Ssklower tptrace(TPPTmisc, "EXIT GET MTU: tpcb size negot \n", 33936403Ssklower *size, *negot, 0, 0); 34036403Ssklower ENDTRACE 34136403Ssklower } 34236403Ssklower 34336403Ssklower 34436403Ssklower /* 34536403Ssklower * CALLED FROM: 34636403Ssklower * tp_emit() 34736403Ssklower * FUNCTION and ARGUMENTS: 34836403Ssklower * Take a packet(m0) from tp and package it so that clnp will accept it. 34936403Ssklower * This means prepending space for the clnp header and filling in a few 35036403Ssklower * of the fields. 35136403Ssklower * inp is the isopcb structure; datalen is the length of the data in the 35236403Ssklower * mbuf string m0. 35336403Ssklower * RETURN VALUE: 35436403Ssklower * whatever (E*) is returned form the net layer output routine. 35536403Ssklower */ 35636403Ssklower 35736403Ssklower int 35836403Ssklower tpclnp_output(isop, m0, datalen, nochksum) 35936403Ssklower struct isopcb *isop; 36036403Ssklower struct mbuf *m0; 36136403Ssklower int datalen; 36236403Ssklower int nochksum; 36336403Ssklower { 36437469Ssklower register struct mbuf *m = m0; 36536403Ssklower IncStat(ts_tpdu_sent); 36636403Ssklower 36736403Ssklower IFDEBUG(D_TPISO) 36836403Ssklower struct tpdu *hdr = mtod(m0, struct tpdu *); 36936403Ssklower 37036403Ssklower printf( 37136403Ssklower "abt to call clnp_output: datalen 0x%x, hdr.li 0x%x, hdr.dutype 0x%x nocsum x%x dst addr:\n", 37236403Ssklower datalen, 37336403Ssklower (int)hdr->tpdu_li, (int)hdr->tpdu_type, nochksum); 37437469Ssklower dump_isoaddr(isop->isop_faddr); 37536403Ssklower printf("\nsrc addr:\n"); 37637469Ssklower dump_isoaddr(isop->isop_laddr); 37736403Ssklower dump_mbuf(m0, "at tpclnp_output"); 37836403Ssklower ENDDEBUG 37936403Ssklower 38036403Ssklower return 38138841Ssklower clnp_output(m0, isop, datalen, /* flags */nochksum ? CLNP_NO_CKSUM : 0); 38236403Ssklower } 38336403Ssklower 38436403Ssklower /* 38536403Ssklower * CALLED FROM: 38636403Ssklower * tp_error_emit() 38736403Ssklower * FUNCTION and ARGUMENTS: 38836403Ssklower * This is a copy of tpclnp_output that takes the addresses 38936403Ssklower * instead of a pcb. It's used by the tp_error_emit, when we 39036403Ssklower * don't have an iso_pcb with which to call the normal output rtn. 39136403Ssklower * RETURN VALUE: 39236403Ssklower * ENOBUFS or 39336403Ssklower * whatever (E*) is returned form the net layer output routine. 39436403Ssklower */ 39536403Ssklower 39636403Ssklower int 39736403Ssklower tpclnp_output_dg(laddr, faddr, m0, datalen, ro, nochksum) 39836403Ssklower struct iso_addr *laddr, *faddr; 39936403Ssklower struct mbuf *m0; 40036403Ssklower int datalen; 40136403Ssklower struct route *ro; 40236403Ssklower int nochksum; 40336403Ssklower { 40436403Ssklower struct isopcb tmppcb; 40536403Ssklower int err; 40636403Ssklower int flags; 40737469Ssklower register struct mbuf *m = m0; 40836403Ssklower 40936403Ssklower IFDEBUG(D_TPISO) 41036403Ssklower printf("tpclnp_output_dg datalen 0x%x m0 0x%x\n", datalen, m0); 41136403Ssklower ENDDEBUG 41236403Ssklower 41336403Ssklower /* 41436403Ssklower * Fill in minimal portion of isopcb so that clnp can send the 41536403Ssklower * packet. 41636403Ssklower */ 41736403Ssklower bzero((caddr_t)&tmppcb, sizeof(tmppcb)); 41837469Ssklower tmppcb.isop_laddr = &tmppcb.isop_sladdr; 41937469Ssklower tmppcb.isop_laddr->siso_addr = *laddr; 42037469Ssklower tmppcb.isop_faddr = &tmppcb.isop_sfaddr; 42137469Ssklower tmppcb.isop_faddr->siso_addr = *faddr; 42236403Ssklower 42336403Ssklower IFDEBUG(D_TPISO) 42436403Ssklower printf("tpclnp_output_dg faddr: \n"); 42537469Ssklower dump_isoaddr(&tmppcb.isop_sfaddr); 42636403Ssklower printf("\ntpclnp_output_dg laddr: \n"); 42737469Ssklower dump_isoaddr(&tmppcb.isop_sladdr); 42836403Ssklower printf("\n"); 42936403Ssklower ENDDEBUG 43036403Ssklower 43136403Ssklower /* 43236403Ssklower * Do not use packet cache since this is a one shot error packet 43336403Ssklower */ 43436403Ssklower flags = (CLNP_NOCACHE|(nochksum?CLNP_NO_CKSUM:0)); 43536403Ssklower 43636403Ssklower IncStat(ts_tpdu_sent); 43736403Ssklower 43838841Ssklower err = clnp_output(m0, &tmppcb, datalen, flags); 43936403Ssklower 44036403Ssklower /* 44136403Ssklower * Free route allocated by clnp (if the route was indeed allocated) 44236403Ssklower */ 44336403Ssklower if (tmppcb.isop_route.ro_rt) 44436403Ssklower RTFREE(tmppcb.isop_route.ro_rt); 44536403Ssklower 44636403Ssklower return(err); 44736403Ssklower } 44837469Ssklower extern struct sockaddr_iso blank_siso; 44936403Ssklower /* 45036403Ssklower * CALLED FROM: 45136403Ssklower * clnp's input routine, indirectly through the protosw. 45236403Ssklower * FUNCTION and ARGUMENTS: 45336403Ssklower * Take a packet (m) from clnp, strip off the clnp header and give it to tp 45436403Ssklower * No return value. 45536403Ssklower */ 45636403Ssklower ProtoHook 45736403Ssklower tpclnp_input(m, faddr, laddr, clnp_len) 45836403Ssklower struct mbuf *m; 45936403Ssklower struct iso_addr *faddr, *laddr; 46036403Ssklower int clnp_len; 46136403Ssklower { 46236403Ssklower struct sockaddr_iso src, dst; 46336403Ssklower int s = splnet(); 46437469Ssklower struct mbuf *tp_inputprep(); 46536403Ssklower 46636403Ssklower IncStat(ts_pkt_rcvd); 46736403Ssklower 46836403Ssklower IFDEBUG(D_TPINPUT) 46936403Ssklower printf("tpclnp_input: m 0x%x clnp_len 0x%x\n", m, clnp_len); 47036403Ssklower dump_mbuf(m, "at tpclnp_input"); 47136403Ssklower ENDDEBUG 47236403Ssklower /* 47336403Ssklower * CLNP gives us an mbuf chain WITH the clnp header pulled up, 47436403Ssklower * and the length of the clnp header. 47536403Ssklower * First, strip off the Clnp header. leave the mbuf there for the 47636403Ssklower * pullup that follows. 47736403Ssklower */ 47836403Ssklower 47936403Ssklower m->m_len -= clnp_len; 48037469Ssklower m->m_data += clnp_len; 48136403Ssklower 48237469Ssklower m = tp_inputprep(m); 48336403Ssklower 48436403Ssklower IFDEBUG(D_TPINPUT) 48536403Ssklower dump_mbuf(m, "after tpclnp_input both pullups"); 48636403Ssklower ENDDEBUG 48736403Ssklower 48837469Ssklower src = blank_siso; dst = blank_siso; 48937469Ssklower bcopy((caddr_t)faddr, (caddr_t)&src.siso_addr, 1 + faddr->isoa_len); 49037469Ssklower bcopy((caddr_t)laddr, (caddr_t)&dst.siso_addr, 1 + laddr->isoa_len); 49136403Ssklower 49236403Ssklower IFDEBUG(D_TPISO) 49336403Ssklower printf("calling tp_input: &src 0x%x &dst 0x%x, src addr:\n", 49436403Ssklower &src, &dst); 49536403Ssklower printf(" dst addr:\n"); 49636403Ssklower dump_isoaddr(&src); 49736403Ssklower dump_isoaddr(&dst); 49836403Ssklower ENDDEBUG 49936403Ssklower 50037469Ssklower (void) tp_input(m, (struct sockaddr *)&src, (struct sockaddr *)&dst, 50137469Ssklower 0, tpclnp_output_dg); 50236403Ssklower 50336403Ssklower IFDEBUG(D_QUENCH) 50436403Ssklower { 50536403Ssklower if(time.tv_usec & 0x4 && time.tv_usec & 0x40) { 50636403Ssklower printf("tpclnp_input: FAKING %s\n", 50736403Ssklower tp_stat.ts_pkt_rcvd & 0x1?"QUENCH":"QUENCH2"); 50836403Ssklower if(tp_stat.ts_pkt_rcvd & 0x1) { 50936403Ssklower tpclnp_ctlinput(PRC_QUENCH, &src); 51036403Ssklower } else { 51136403Ssklower tpclnp_ctlinput(PRC_QUENCH2, &src); 51236403Ssklower } 51336403Ssklower } 51436403Ssklower } 51536403Ssklower ENDDEBUG 51636403Ssklower 51736403Ssklower splx(s); 51836403Ssklower return 0; 51936403Ssklower } 52036403Ssklower 52136403Ssklower ProtoHook 52236403Ssklower iso_rtchange() 52336403Ssklower { 52436403Ssklower return 0; 52536403Ssklower } 52636403Ssklower 52736403Ssklower /* 52836403Ssklower * CALLED FROM: 52936403Ssklower * tpclnp_ctlinput() 53036403Ssklower * FUNCTION and ARGUMENTS: 53136403Ssklower * find the tpcb pointer and pass it to tp_quench 53236403Ssklower */ 53336403Ssklower void 53436403Ssklower tpiso_decbit(isop) 53536403Ssklower struct isopcb *isop; 53636403Ssklower { 53737469Ssklower tp_quench((struct tp_pcb *)isop->isop_socket->so_tpcb, PRC_QUENCH2); 53836403Ssklower } 53936403Ssklower /* 54036403Ssklower * CALLED FROM: 54136403Ssklower * tpclnp_ctlinput() 54236403Ssklower * FUNCTION and ARGUMENTS: 54336403Ssklower * find the tpcb pointer and pass it to tp_quench 54436403Ssklower */ 54536403Ssklower void 54636403Ssklower tpiso_quench(isop) 54736403Ssklower struct isopcb *isop; 54836403Ssklower { 54937469Ssklower tp_quench((struct tp_pcb *)isop->isop_socket->so_tpcb, PRC_QUENCH); 55036403Ssklower } 55136403Ssklower 55236403Ssklower /* 55336403Ssklower * CALLED FROM: 55436403Ssklower * The network layer through the protosw table. 55536403Ssklower * FUNCTION and ARGUMENTS: 55636403Ssklower * When clnp an ICMP-like msg this gets called. 55736403Ssklower * It either returns an error status to the user or 55836403Ssklower * it causes all connections on this address to be aborted 55936403Ssklower * by calling the appropriate xx_notify() routine. 56036403Ssklower * (cmd) is the type of ICMP error. 56136403Ssklower * (siso) is the address of the guy who sent the ER CLNPDU 56236403Ssklower */ 56336403Ssklower ProtoHook 56436403Ssklower tpclnp_ctlinput(cmd, siso) 56536403Ssklower int cmd; 56636403Ssklower struct sockaddr_iso *siso; 56736403Ssklower { 56837469Ssklower return tpclnp_ctlinput1(cmd, &siso->siso_addr); 56937469Ssklower } 57037469Ssklower 57137469Ssklower /* 57237469Ssklower * Entry to ctlinput with argument of an iso_addr rather than a sockaddr 57337469Ssklower */ 57437469Ssklower ProtoHook 57537469Ssklower tpclnp_ctlinput1(cmd, isoa) 57637469Ssklower int cmd; 57737469Ssklower struct iso_addr *isoa; 57837469Ssklower { 57936403Ssklower extern u_char inetctlerrmap[]; 58036403Ssklower extern ProtoHook tpiso_abort(); 58136403Ssklower extern ProtoHook iso_rtchange(); 58236403Ssklower extern ProtoHook tpiso_reset(); 58337469Ssklower void iso_pcbnotify(); 58436403Ssklower 58536403Ssklower IFDEBUG(D_TPINPUT) 58637469Ssklower printf("tpclnp_ctlinput1: cmd 0x%x addr: %s\n", cmd, 58737469Ssklower clnp_iso_addrp(isoa)); 58836403Ssklower ENDDEBUG 58936403Ssklower 59036403Ssklower if (cmd < 0 || cmd > PRC_NCMDS) 59136403Ssklower return 0; 59236403Ssklower switch (cmd) { 59336403Ssklower 59436403Ssklower case PRC_QUENCH2: 59537469Ssklower iso_pcbnotify(&tp_isopcb, isoa, 0, (int (*)())tpiso_decbit); 59636403Ssklower break; 59736403Ssklower 59836403Ssklower case PRC_QUENCH: 59937469Ssklower iso_pcbnotify(&tp_isopcb, isoa, 0, (int (*)())tpiso_quench); 60036403Ssklower break; 60136403Ssklower 60236403Ssklower case PRC_TIMXCEED_REASS: 60336403Ssklower case PRC_ROUTEDEAD: 60437469Ssklower iso_pcbnotify(&tp_isopcb, isoa, 0, tpiso_reset); 60536403Ssklower break; 60636403Ssklower 60736403Ssklower case PRC_HOSTUNREACH: 60836403Ssklower case PRC_UNREACH_NET: 60936403Ssklower case PRC_IFDOWN: 61036403Ssklower case PRC_HOSTDEAD: 61137469Ssklower iso_pcbnotify(&tp_isopcb, isoa, 61236403Ssklower (int)inetctlerrmap[cmd], iso_rtchange); 61336403Ssklower break; 61436403Ssklower 61536403Ssklower default: 61636403Ssklower /* 61736403Ssklower case PRC_MSGSIZE: 61836403Ssklower case PRC_UNREACH_HOST: 61936403Ssklower case PRC_UNREACH_PROTOCOL: 62036403Ssklower case PRC_UNREACH_PORT: 62136403Ssklower case PRC_UNREACH_NEEDFRAG: 62236403Ssklower case PRC_UNREACH_SRCFAIL: 62336403Ssklower case PRC_REDIRECT_NET: 62436403Ssklower case PRC_REDIRECT_HOST: 62536403Ssklower case PRC_REDIRECT_TOSNET: 62636403Ssklower case PRC_REDIRECT_TOSHOST: 62736403Ssklower case PRC_TIMXCEED_INTRANS: 62836403Ssklower case PRC_PARAMPROB: 62936403Ssklower */ 63037469Ssklower iso_pcbnotify(&tp_isopcb, isoa, (int)inetctlerrmap[cmd], tpiso_abort); 63136403Ssklower break; 63236403Ssklower } 63336403Ssklower return 0; 63436403Ssklower } 63536403Ssklower 63636403Ssklower /* 63736403Ssklower * These next 2 routines are 63836403Ssklower * CALLED FROM: 63936403Ssklower * xxx_notify() from tp_ctlinput() when 64036403Ssklower * net level gets some ICMP-equiv. type event. 64136403Ssklower * FUNCTION and ARGUMENTS: 64236403Ssklower * Cause the connection to be aborted with some sort of error 64336403Ssklower * reason indicating that the network layer caused the abort. 64436403Ssklower * Fakes an ER TPDU so we can go through the driver. 64536403Ssklower * abort always aborts the TP connection. 64636403Ssklower * reset may or may not, depending on the TP class that's in use. 64736403Ssklower */ 64836403Ssklower ProtoHook 64936403Ssklower tpiso_abort(isop) 65036403Ssklower struct isopcb *isop; 65136403Ssklower { 65236403Ssklower struct tp_event e; 65336403Ssklower 65436403Ssklower IFDEBUG(D_CONN) 65536403Ssklower printf("tpiso_abort 0x%x\n", isop); 65636403Ssklower ENDDEBUG 65736403Ssklower e.ev_number = ER_TPDU; 65836403Ssklower e.ATTR(ER_TPDU).e_reason = ECONNABORTED; 65936403Ssklower return tp_driver((struct tp_pcb *)isop->isop_socket->so_tpcb, &e); 66036403Ssklower } 66136403Ssklower 66236403Ssklower ProtoHook 66336403Ssklower tpiso_reset(isop) 66436403Ssklower struct isopcb *isop; 66536403Ssklower { 66636403Ssklower struct tp_event e; 66736403Ssklower 66836403Ssklower e.ev_number = T_NETRESET; 66936403Ssklower return tp_driver((struct tp_pcb *)isop->isop_socket->so_tpcb, &e); 67036403Ssklower 67136403Ssklower } 67236403Ssklower 67336403Ssklower #endif ISO 674