149268Sbostic /*- 2*63222Sbostic * Copyright (c) 1991, 1993 3*63222Sbostic * The Regents of the University of California. All rights reserved. 449268Sbostic * 549268Sbostic * %sccs.include.redist.c% 649268Sbostic * 7*63222Sbostic * @(#)tp_iso.c 8.1 (Berkeley) 06/10/93 849268Sbostic */ 949268Sbostic 1036403Ssklower /*********************************************************** 1136403Ssklower Copyright IBM Corporation 1987 1236403Ssklower 1336403Ssklower All Rights Reserved 1436403Ssklower 1536403Ssklower Permission to use, copy, modify, and distribute this software and its 1636403Ssklower documentation for any purpose and without fee is hereby granted, 1736403Ssklower provided that the above copyright notice appear in all copies and that 1836403Ssklower both that copyright notice and this permission notice appear in 1936403Ssklower supporting documentation, and that the name of IBM not be 2036403Ssklower used in advertising or publicity pertaining to distribution of the 2136403Ssklower software without specific, written prior permission. 2236403Ssklower 2336403Ssklower IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 2436403Ssklower ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 2536403Ssklower IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 2636403Ssklower ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 2736403Ssklower WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 2836403Ssklower ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 2936403Ssklower SOFTWARE. 3036403Ssklower 3136403Ssklower ******************************************************************/ 3236403Ssklower 3336403Ssklower /* 3436403Ssklower * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison 3536403Ssklower */ 3636403Ssklower /* 3736403Ssklower * ARGO TP 3837469Ssklower * $Header: /var/src/sys/netiso/RCS/tp_iso.c,v 5.1 89/02/09 16:20:51 hagens Exp $ 3937469Ssklower * $Source: /var/src/sys/netiso/RCS/tp_iso.c,v $ 4036403Ssklower * 4136403Ssklower * Here is where you find the iso-dependent code. We've tried 4236403Ssklower * keep all net-level and (primarily) address-family-dependent stuff 4336403Ssklower * out of the tp source, and everthing here is reached indirectly 4436403Ssklower * through a switch table (struct nl_protosw *) tpcb->tp_nlproto 4536403Ssklower * (see tp_pcb.c). 4636403Ssklower * The routines here are: 4736403Ssklower * iso_getsufx: gets transport suffix out of an isopcb structure. 4836403Ssklower * iso_putsufx: put transport suffix into an isopcb structure. 4936403Ssklower * iso_putnetaddr: put a whole net addr into an isopcb. 5036403Ssklower * iso_getnetaddr: get a whole net addr from an isopcb. 5144422Ssklower * iso_cmpnetaddr: compare a whole net addr from an isopcb. 5236403Ssklower * iso_recycle_suffix: clear suffix for reuse in isopcb 5336403Ssklower * tpclnp_ctlinput: handle ER CNLPdu : icmp-like stuff 5436403Ssklower * tpclnp_mtu: figure out what size tpdu to use 5536403Ssklower * tpclnp_input: take a pkt from clnp, strip off its clnp header, 5636403Ssklower * give to tp 5736403Ssklower * tpclnp_output_dg: package a pkt for clnp given 2 addresses & some data 5836403Ssklower * tpclnp_output: package a pkt for clnp given an isopcb & some data 5936403Ssklower */ 6036403Ssklower 6136403Ssklower #ifdef ISO 6236403Ssklower 6356533Sbostic #include <sys/param.h> 6456533Sbostic #include <sys/socket.h> 6556533Sbostic #include <sys/socketvar.h> 6656533Sbostic #include <sys/domain.h> 6756533Sbostic #include <sys/malloc.h> 6856533Sbostic #include <sys/mbuf.h> 6956533Sbostic #include <sys/errno.h> 7056533Sbostic #include <sys/time.h> 7156533Sbostic #include <sys/protosw.h> 7237469Ssklower 7356533Sbostic #include <net/if.h> 7456533Sbostic #include <net/route.h> 7536403Ssklower 7656533Sbostic #include <netiso/argo_debug.h> 7756533Sbostic #include <netiso/tp_param.h> 7856533Sbostic #include <netiso/tp_stat.h> 7956533Sbostic #include <netiso/tp_pcb.h> 8056533Sbostic #include <netiso/tp_trace.h> 8156533Sbostic #include <netiso/tp_stat.h> 8256533Sbostic #include <netiso/tp_tpdu.h> 8356533Sbostic #include <netiso/tp_clnp.h> 8456533Sbostic #include <netiso/cltp_var.h> 8536403Ssklower 8636403Ssklower /* 8736403Ssklower * CALLED FROM: 8836403Ssklower * pr_usrreq() on PRU_BIND, PRU_CONNECT, PRU_ACCEPT, and PRU_PEERADDR 8937469Ssklower * FUNCTION, ARGUMENTS: 9036403Ssklower * The argument (which) takes the value TP_LOCAL or TP_FOREIGN. 9136403Ssklower */ 9236403Ssklower 9337469Ssklower iso_getsufx(isop, lenp, data_out, which) 9436403Ssklower struct isopcb *isop; 9537469Ssklower u_short *lenp; 9637469Ssklower caddr_t data_out; 9736403Ssklower int which; 9836403Ssklower { 9937469Ssklower register struct sockaddr_iso *addr = 0; 10037469Ssklower 10136403Ssklower switch (which) { 10236403Ssklower case TP_LOCAL: 10337469Ssklower addr = isop->isop_laddr; 10437469Ssklower break; 10536403Ssklower 10636403Ssklower case TP_FOREIGN: 10737469Ssklower addr = isop->isop_faddr; 10836403Ssklower } 10937469Ssklower if (addr) 11038841Ssklower bcopy(TSEL(addr), data_out, (*lenp = addr->siso_tlen)); 11136403Ssklower } 11236403Ssklower 11336403Ssklower /* CALLED FROM: 11436403Ssklower * tp_newsocket(); i.e., when a connection is being established by an 11536403Ssklower * incoming CR_TPDU. 11636403Ssklower * 11736403Ssklower * FUNCTION, ARGUMENTS: 11836403Ssklower * Put a transport suffix (found in name) into an isopcb structure (isop). 11936403Ssklower * The argument (which) takes the value TP_LOCAL or TP_FOREIGN. 12036403Ssklower */ 12136403Ssklower void 12237469Ssklower iso_putsufx(isop, sufxloc, sufxlen, which) 12336403Ssklower struct isopcb *isop; 12437469Ssklower caddr_t sufxloc; 12537469Ssklower int sufxlen, which; 12636403Ssklower { 12737469Ssklower struct sockaddr_iso **dst, *backup; 12837469Ssklower register struct sockaddr_iso *addr; 12937469Ssklower struct mbuf *m; 13037469Ssklower int len; 13137469Ssklower 13236403Ssklower switch (which) { 13337469Ssklower default: 13437469Ssklower return; 13537469Ssklower 13636403Ssklower case TP_LOCAL: 13737469Ssklower dst = &isop->isop_laddr; 13837469Ssklower backup = &isop->isop_sladdr; 13936403Ssklower break; 14037469Ssklower 14136403Ssklower case TP_FOREIGN: 14237469Ssklower dst = &isop->isop_faddr; 14337469Ssklower backup = &isop->isop_sfaddr; 14436403Ssklower } 14537469Ssklower if ((addr = *dst) == 0) { 14637469Ssklower addr = *dst = backup; 14737469Ssklower addr->siso_nlen = 0; 14838841Ssklower addr->siso_slen = 0; 14938841Ssklower addr->siso_plen = 0; 15037469Ssklower printf("iso_putsufx on un-initialized isopcb\n"); 15137469Ssklower } 15237469Ssklower len = sufxlen + addr->siso_nlen + 15338841Ssklower (sizeof(*addr) - sizeof(addr->siso_data)); 15437469Ssklower if (addr == backup) { 15538841Ssklower if (len > sizeof(*addr)) { 15637469Ssklower m = m_getclr(M_DONTWAIT, MT_SONAME); 15737469Ssklower if (m == 0) 15837469Ssklower return; 15937469Ssklower addr = *dst = mtod(m, struct sockaddr_iso *); 16037469Ssklower *addr = *backup; 16137469Ssklower m->m_len = len; 16237469Ssklower } 16338841Ssklower } 16437469Ssklower bcopy(sufxloc, TSEL(addr), sufxlen); 16538841Ssklower addr->siso_tlen = sufxlen; 16637469Ssklower addr->siso_len = len; 16736403Ssklower } 16836403Ssklower 16936403Ssklower /* 17036403Ssklower * CALLED FROM: 17136403Ssklower * tp.trans whenever we go into REFWAIT state. 17236403Ssklower * FUNCTION and ARGUMENT: 17336403Ssklower * Called when a ref is frozen, to allow the suffix to be reused. 17436403Ssklower * (isop) is the net level pcb. This really shouldn't have to be 17536403Ssklower * done in a NET level pcb but... for the internet world that just 17636403Ssklower * the way it is done in BSD... 17736403Ssklower * The alternative is to have the port unusable until the reference 17836403Ssklower * timer goes off. 17936403Ssklower */ 18036403Ssklower void 18136403Ssklower iso_recycle_tsuffix(isop) 18236403Ssklower struct isopcb *isop; 18336403Ssklower { 18438841Ssklower isop->isop_laddr->siso_tlen = isop->isop_faddr->siso_tlen = 0; 18536403Ssklower } 18636403Ssklower 18736403Ssklower /* 18836403Ssklower * CALLED FROM: 18936403Ssklower * tp_newsocket(); i.e., when a connection is being established by an 19036403Ssklower * incoming CR_TPDU. 19136403Ssklower * 19236403Ssklower * FUNCTION and ARGUMENTS: 19336403Ssklower * Copy a whole net addr from a struct sockaddr (name). 19436403Ssklower * into an isopcb (isop). 19536403Ssklower * The argument (which) takes values TP_LOCAL or TP_FOREIGN 19636403Ssklower */ 19736403Ssklower void 19836403Ssklower iso_putnetaddr(isop, name, which) 19936403Ssklower register struct isopcb *isop; 20036403Ssklower struct sockaddr_iso *name; 20136403Ssklower int which; 20236403Ssklower { 20337469Ssklower struct sockaddr_iso **sisop, *backup; 20437469Ssklower register struct sockaddr_iso *siso; 20537469Ssklower 20636403Ssklower switch (which) { 20744422Ssklower default: 20844422Ssklower printf("iso_putnetaddr: should panic\n"); 20944422Ssklower return; 21036403Ssklower case TP_LOCAL: 21137469Ssklower sisop = &isop->isop_laddr; 21237469Ssklower backup = &isop->isop_sladdr; 21336403Ssklower break; 21436403Ssklower case TP_FOREIGN: 21537469Ssklower sisop = &isop->isop_faddr; 21637469Ssklower backup = &isop->isop_sfaddr; 21736403Ssklower } 21837469Ssklower siso = ((*sisop == 0) ? (*sisop = backup) : *sisop); 21937469Ssklower IFDEBUG(D_TPISO) 22037469Ssklower printf("ISO_PUTNETADDR\n"); 22137469Ssklower dump_isoaddr(isop->isop_faddr); 22237469Ssklower ENDDEBUG 22337469Ssklower siso->siso_addr = name->siso_addr; 22436403Ssklower } 22536403Ssklower 22636403Ssklower /* 22736403Ssklower * CALLED FROM: 22844422Ssklower * tp_input() when a connection is being established by an 22944422Ssklower * incoming CR_TPDU, and considered for interception. 23044422Ssklower * 23144422Ssklower * FUNCTION and ARGUMENTS: 23244422Ssklower * compare a whole net addr from a struct sockaddr (name), 23344422Ssklower * with that implicitly stored in an isopcb (isop). 23444422Ssklower * The argument (which) takes values TP_LOCAL or TP_FOREIGN. 23544422Ssklower */ 23644422Ssklower iso_cmpnetaddr(isop, name, which) 23744422Ssklower register struct isopcb *isop; 23844422Ssklower register struct sockaddr_iso *name; 23944422Ssklower int which; 24044422Ssklower { 24144422Ssklower struct sockaddr_iso **sisop, *backup; 24244422Ssklower register struct sockaddr_iso *siso; 24344422Ssklower 24444422Ssklower switch (which) { 24544422Ssklower default: 24644422Ssklower printf("iso_cmpnetaddr: should panic\n"); 24744422Ssklower return 0; 24844422Ssklower case TP_LOCAL: 24944422Ssklower sisop = &isop->isop_laddr; 25044422Ssklower backup = &isop->isop_sladdr; 25144422Ssklower break; 25244422Ssklower case TP_FOREIGN: 25344422Ssklower sisop = &isop->isop_faddr; 25444422Ssklower backup = &isop->isop_sfaddr; 25544422Ssklower } 25644422Ssklower siso = ((*sisop == 0) ? (*sisop = backup) : *sisop); 25744422Ssklower IFDEBUG(D_TPISO) 25844422Ssklower printf("ISO_CMPNETADDR\n"); 25944422Ssklower dump_isoaddr(siso); 26044422Ssklower ENDDEBUG 26144422Ssklower if (name->siso_tlen && bcmp(TSEL(name), TSEL(siso), name->siso_tlen)) 26244422Ssklower return (0); 26344422Ssklower return (bcmp((caddr_t)name->siso_data, 26444422Ssklower (caddr_t)siso->siso_data, name->siso_nlen) == 0); 26544422Ssklower } 26644422Ssklower 26744422Ssklower /* 26844422Ssklower * CALLED FROM: 26936403Ssklower * pr_usrreq() PRU_SOCKADDR, PRU_ACCEPT, PRU_PEERADDR 27036403Ssklower * FUNCTION and ARGUMENTS: 27136403Ssklower * Copy a whole net addr from an isopcb (isop) into 27236403Ssklower * a struct sockaddr (name). 27336403Ssklower * The argument (which) takes values TP_LOCAL or TP_FOREIGN. 27436403Ssklower */ 27536403Ssklower 27636403Ssklower void 27736403Ssklower iso_getnetaddr( isop, name, which) 27836403Ssklower struct isopcb *isop; 27937469Ssklower struct mbuf *name; 28036403Ssklower int which; 28136403Ssklower { 28237469Ssklower struct sockaddr_iso *siso = 28337469Ssklower (which == TP_LOCAL ? isop->isop_laddr : isop->isop_faddr); 28437469Ssklower if (siso) 28537469Ssklower bcopy((caddr_t)siso, mtod(name, caddr_t), 28637469Ssklower (unsigned)(name->m_len = siso->siso_len)); 28737469Ssklower else 28837469Ssklower name->m_len = 0; 28936403Ssklower } 29036403Ssklower /* 29151246Ssklower * NAME: tpclnp_mtu() 29251246Ssklower * 29336403Ssklower * CALLED FROM: 29451246Ssklower * tp_route_to() on incoming CR, CC, and pr_usrreq() for PRU_CONNECT 29536403Ssklower * 29651246Ssklower * FUNCTION, ARGUMENTS, and RETURN VALUE: 29751246Ssklower * 29851246Ssklower * Perform subnetwork dependent part of determining MTU information. 29951246Ssklower * It appears that setting a double pointer to the rtentry associated with 30051246Ssklower * the destination, and returning the header size for the network protocol 30151246Ssklower * suffices. 30236403Ssklower * 30351246Ssklower * SIDE EFFECTS: 30451246Ssklower * Sets tp_routep pointer in pcb. 30551246Ssklower * 30651246Ssklower * NOTES: 30736403Ssklower */ 30851246Ssklower tpclnp_mtu(tpcb) 30951246Ssklower register struct tp_pcb *tpcb; 31036403Ssklower { 31151246Ssklower struct isopcb *isop = (struct isopcb *)tpcb->tp_npcb; 31236403Ssklower 31336403Ssklower IFDEBUG(D_CONN) 31451246Ssklower printf("tpclnp_mtu(tpcb)\n", tpcb); 31536403Ssklower ENDDEBUG 31651246Ssklower tpcb->tp_routep = &(isop->isop_route.ro_rt); 31751246Ssklower if (tpcb->tp_netservice == ISO_CONS) 31851246Ssklower return 0; 31951246Ssklower else 32051246Ssklower return (sizeof(struct clnp_fixed) + sizeof(struct clnp_segment) + 32151246Ssklower 2 * sizeof(struct iso_addr)); 32236403Ssklower 32336403Ssklower } 32436403Ssklower 32536403Ssklower /* 32636403Ssklower * CALLED FROM: 32736403Ssklower * tp_emit() 32836403Ssklower * FUNCTION and ARGUMENTS: 32936403Ssklower * Take a packet(m0) from tp and package it so that clnp will accept it. 33036403Ssklower * This means prepending space for the clnp header and filling in a few 33136403Ssklower * of the fields. 33251246Ssklower * isop is the isopcb structure; datalen is the length of the data in the 33336403Ssklower * mbuf string m0. 33436403Ssklower * RETURN VALUE: 33536403Ssklower * whatever (E*) is returned form the net layer output routine. 33636403Ssklower */ 33736403Ssklower 33836403Ssklower int 33936403Ssklower tpclnp_output(isop, m0, datalen, nochksum) 34036403Ssklower struct isopcb *isop; 34136403Ssklower struct mbuf *m0; 34236403Ssklower int datalen; 34336403Ssklower int nochksum; 34436403Ssklower { 34537469Ssklower register struct mbuf *m = m0; 34636403Ssklower IncStat(ts_tpdu_sent); 34736403Ssklower 34836403Ssklower IFDEBUG(D_TPISO) 34936403Ssklower struct tpdu *hdr = mtod(m0, struct tpdu *); 35036403Ssklower 35136403Ssklower printf( 35236403Ssklower "abt to call clnp_output: datalen 0x%x, hdr.li 0x%x, hdr.dutype 0x%x nocsum x%x dst addr:\n", 35336403Ssklower datalen, 35436403Ssklower (int)hdr->tpdu_li, (int)hdr->tpdu_type, nochksum); 35537469Ssklower dump_isoaddr(isop->isop_faddr); 35636403Ssklower printf("\nsrc addr:\n"); 35737469Ssklower dump_isoaddr(isop->isop_laddr); 35836403Ssklower dump_mbuf(m0, "at tpclnp_output"); 35936403Ssklower ENDDEBUG 36036403Ssklower 36136403Ssklower return 36238841Ssklower clnp_output(m0, isop, datalen, /* flags */nochksum ? CLNP_NO_CKSUM : 0); 36336403Ssklower } 36436403Ssklower 36536403Ssklower /* 36636403Ssklower * CALLED FROM: 36736403Ssklower * tp_error_emit() 36836403Ssklower * FUNCTION and ARGUMENTS: 36936403Ssklower * This is a copy of tpclnp_output that takes the addresses 37036403Ssklower * instead of a pcb. It's used by the tp_error_emit, when we 37136403Ssklower * don't have an iso_pcb with which to call the normal output rtn. 37236403Ssklower * RETURN VALUE: 37336403Ssklower * ENOBUFS or 37436403Ssklower * whatever (E*) is returned form the net layer output routine. 37536403Ssklower */ 37636403Ssklower 37736403Ssklower int 37836403Ssklower tpclnp_output_dg(laddr, faddr, m0, datalen, ro, nochksum) 37936403Ssklower struct iso_addr *laddr, *faddr; 38036403Ssklower struct mbuf *m0; 38136403Ssklower int datalen; 38236403Ssklower struct route *ro; 38336403Ssklower int nochksum; 38436403Ssklower { 38536403Ssklower struct isopcb tmppcb; 38636403Ssklower int err; 38736403Ssklower int flags; 38837469Ssklower register struct mbuf *m = m0; 38936403Ssklower 39036403Ssklower IFDEBUG(D_TPISO) 39136403Ssklower printf("tpclnp_output_dg datalen 0x%x m0 0x%x\n", datalen, m0); 39236403Ssklower ENDDEBUG 39336403Ssklower 39436403Ssklower /* 39536403Ssklower * Fill in minimal portion of isopcb so that clnp can send the 39636403Ssklower * packet. 39736403Ssklower */ 39836403Ssklower bzero((caddr_t)&tmppcb, sizeof(tmppcb)); 39937469Ssklower tmppcb.isop_laddr = &tmppcb.isop_sladdr; 40037469Ssklower tmppcb.isop_laddr->siso_addr = *laddr; 40137469Ssklower tmppcb.isop_faddr = &tmppcb.isop_sfaddr; 40237469Ssklower tmppcb.isop_faddr->siso_addr = *faddr; 40336403Ssklower 40436403Ssklower IFDEBUG(D_TPISO) 40536403Ssklower printf("tpclnp_output_dg faddr: \n"); 40637469Ssklower dump_isoaddr(&tmppcb.isop_sfaddr); 40736403Ssklower printf("\ntpclnp_output_dg laddr: \n"); 40837469Ssklower dump_isoaddr(&tmppcb.isop_sladdr); 40936403Ssklower printf("\n"); 41036403Ssklower ENDDEBUG 41136403Ssklower 41236403Ssklower /* 41336403Ssklower * Do not use packet cache since this is a one shot error packet 41436403Ssklower */ 41536403Ssklower flags = (CLNP_NOCACHE|(nochksum?CLNP_NO_CKSUM:0)); 41636403Ssklower 41736403Ssklower IncStat(ts_tpdu_sent); 41836403Ssklower 41938841Ssklower err = clnp_output(m0, &tmppcb, datalen, flags); 42036403Ssklower 42136403Ssklower /* 42236403Ssklower * Free route allocated by clnp (if the route was indeed allocated) 42336403Ssklower */ 42436403Ssklower if (tmppcb.isop_route.ro_rt) 42536403Ssklower RTFREE(tmppcb.isop_route.ro_rt); 42636403Ssklower 42736403Ssklower return(err); 42836403Ssklower } 42936403Ssklower /* 43036403Ssklower * CALLED FROM: 43136403Ssklower * clnp's input routine, indirectly through the protosw. 43236403Ssklower * FUNCTION and ARGUMENTS: 43336403Ssklower * Take a packet (m) from clnp, strip off the clnp header and give it to tp 43436403Ssklower * No return value. 43536403Ssklower */ 43636403Ssklower ProtoHook 43739927Ssklower tpclnp_input(m, src, dst, clnp_len, ce_bit) 43839926Ssklower register struct mbuf *m; 43939926Ssklower struct sockaddr_iso *src, *dst; 44039927Ssklower int clnp_len, ce_bit; 44136403Ssklower { 44237469Ssklower struct mbuf *tp_inputprep(); 44339926Ssklower int tp_input(), cltp_input(), (*input)() = tp_input; 44436403Ssklower 44536403Ssklower IncStat(ts_pkt_rcvd); 44636403Ssklower 44736403Ssklower IFDEBUG(D_TPINPUT) 44836403Ssklower printf("tpclnp_input: m 0x%x clnp_len 0x%x\n", m, clnp_len); 44936403Ssklower dump_mbuf(m, "at tpclnp_input"); 45036403Ssklower ENDDEBUG 45136403Ssklower /* 45236403Ssklower * CLNP gives us an mbuf chain WITH the clnp header pulled up, 45336403Ssklower * and the length of the clnp header. 45436403Ssklower * First, strip off the Clnp header. leave the mbuf there for the 45536403Ssklower * pullup that follows. 45636403Ssklower */ 45736403Ssklower m->m_len -= clnp_len; 45837469Ssklower m->m_data += clnp_len; 45956911Ssklower m->m_pkthdr.len -= clnp_len; 46056911Ssklower /* XXXX: should probably be in clnp_input */ 46156911Ssklower switch (dst->siso_data[dst->siso_nlen - 1]) { 46256911Ssklower #ifdef TUBA 46356911Ssklower case ISOPROTO_TCP: 46456911Ssklower return (tuba_tcpinput(m, src, dst)); 46556911Ssklower #endif 46656911Ssklower case 0: 46756911Ssklower if (m->m_len == 0 && (m = m_pullup(m, 1)) == 0) 46856911Ssklower return 0; 46956911Ssklower if (*(mtod(m, u_char *)) == ISO10747_IDRP) 47056911Ssklower return (idrp_input(m, src, dst)); 47156911Ssklower } 47237469Ssklower m = tp_inputprep(m); 47339926Ssklower if (m == 0) 47439926Ssklower return 0; 47539926Ssklower if (mtod(m, u_char *)[1] == UD_TPDU_type) 47639926Ssklower input = cltp_input; 47736403Ssklower 47836403Ssklower IFDEBUG(D_TPINPUT) 47936403Ssklower dump_mbuf(m, "after tpclnp_input both pullups"); 48036403Ssklower ENDDEBUG 48136403Ssklower 48236403Ssklower IFDEBUG(D_TPISO) 48339926Ssklower printf("calling %sinput : src 0x%x, dst 0x%x, src addr:\n", 48439926Ssklower (input == tp_input ? "tp_" : "clts_"), src, dst); 48539926Ssklower dump_isoaddr(src); 48636403Ssklower printf(" dst addr:\n"); 48739926Ssklower dump_isoaddr(dst); 48836403Ssklower ENDDEBUG 48936403Ssklower 49039926Ssklower (void) (*input)(m, (struct sockaddr *)src, (struct sockaddr *)dst, 49139927Ssklower 0, tpclnp_output_dg, ce_bit); 49236403Ssklower 49336403Ssklower IFDEBUG(D_QUENCH) 49436403Ssklower { 49536403Ssklower if(time.tv_usec & 0x4 && time.tv_usec & 0x40) { 49636403Ssklower printf("tpclnp_input: FAKING %s\n", 49736403Ssklower tp_stat.ts_pkt_rcvd & 0x1?"QUENCH":"QUENCH2"); 49836403Ssklower if(tp_stat.ts_pkt_rcvd & 0x1) { 49936403Ssklower tpclnp_ctlinput(PRC_QUENCH, &src); 50036403Ssklower } else { 50136403Ssklower tpclnp_ctlinput(PRC_QUENCH2, &src); 50236403Ssklower } 50336403Ssklower } 50436403Ssklower } 50536403Ssklower ENDDEBUG 50636403Ssklower 50736403Ssklower return 0; 50836403Ssklower } 50936403Ssklower 51036403Ssklower ProtoHook 51136403Ssklower iso_rtchange() 51236403Ssklower { 51336403Ssklower return 0; 51436403Ssklower } 51536403Ssklower 51636403Ssklower /* 51736403Ssklower * CALLED FROM: 51836403Ssklower * tpclnp_ctlinput() 51936403Ssklower * FUNCTION and ARGUMENTS: 52036403Ssklower * find the tpcb pointer and pass it to tp_quench 52136403Ssklower */ 52236403Ssklower void 52336403Ssklower tpiso_decbit(isop) 52436403Ssklower struct isopcb *isop; 52536403Ssklower { 52650435Ssklower tp_quench((struct tp_pcb *)isop->isop_socket->so_pcb, PRC_QUENCH2); 52736403Ssklower } 52836403Ssklower /* 52936403Ssklower * CALLED FROM: 53036403Ssklower * tpclnp_ctlinput() 53136403Ssklower * FUNCTION and ARGUMENTS: 53236403Ssklower * find the tpcb pointer and pass it to tp_quench 53336403Ssklower */ 53436403Ssklower void 53536403Ssklower tpiso_quench(isop) 53636403Ssklower struct isopcb *isop; 53736403Ssklower { 53850435Ssklower tp_quench((struct tp_pcb *)isop->isop_socket->so_pcb, PRC_QUENCH); 53936403Ssklower } 54036403Ssklower 54136403Ssklower /* 54236403Ssklower * CALLED FROM: 54336403Ssklower * The network layer through the protosw table. 54436403Ssklower * FUNCTION and ARGUMENTS: 54536403Ssklower * When clnp an ICMP-like msg this gets called. 54636403Ssklower * It either returns an error status to the user or 54736403Ssklower * it causes all connections on this address to be aborted 54836403Ssklower * by calling the appropriate xx_notify() routine. 54936403Ssklower * (cmd) is the type of ICMP error. 55036403Ssklower * (siso) is the address of the guy who sent the ER CLNPDU 55136403Ssklower */ 55236403Ssklower ProtoHook 55336403Ssklower tpclnp_ctlinput(cmd, siso) 55436403Ssklower int cmd; 55536403Ssklower struct sockaddr_iso *siso; 55636403Ssklower { 55736403Ssklower extern u_char inetctlerrmap[]; 55836403Ssklower extern ProtoHook tpiso_abort(); 55936403Ssklower extern ProtoHook iso_rtchange(); 56036403Ssklower extern ProtoHook tpiso_reset(); 56137469Ssklower void iso_pcbnotify(); 56236403Ssklower 56336403Ssklower IFDEBUG(D_TPINPUT) 56439926Ssklower printf("tpclnp_ctlinput1: cmd 0x%x addr: \n", cmd); 56539926Ssklower dump_isoaddr(siso); 56636403Ssklower ENDDEBUG 56736403Ssklower 56836403Ssklower if (cmd < 0 || cmd > PRC_NCMDS) 56936403Ssklower return 0; 57039926Ssklower if (siso->siso_family != AF_ISO) 57139926Ssklower return 0; 57236403Ssklower switch (cmd) { 57336403Ssklower 57436403Ssklower case PRC_QUENCH2: 57539926Ssklower iso_pcbnotify(&tp_isopcb, siso, 0, (int (*)())tpiso_decbit); 57636403Ssklower break; 57736403Ssklower 57836403Ssklower case PRC_QUENCH: 57939926Ssklower iso_pcbnotify(&tp_isopcb, siso, 0, (int (*)())tpiso_quench); 58036403Ssklower break; 58136403Ssklower 58236403Ssklower case PRC_TIMXCEED_REASS: 58336403Ssklower case PRC_ROUTEDEAD: 58439926Ssklower iso_pcbnotify(&tp_isopcb, siso, 0, tpiso_reset); 58536403Ssklower break; 58636403Ssklower 58736403Ssklower case PRC_HOSTUNREACH: 58836403Ssklower case PRC_UNREACH_NET: 58936403Ssklower case PRC_IFDOWN: 59036403Ssklower case PRC_HOSTDEAD: 59139926Ssklower iso_pcbnotify(&tp_isopcb, siso, 59236403Ssklower (int)inetctlerrmap[cmd], iso_rtchange); 59336403Ssklower break; 59436403Ssklower 59536403Ssklower default: 59636403Ssklower /* 59736403Ssklower case PRC_MSGSIZE: 59836403Ssklower case PRC_UNREACH_HOST: 59936403Ssklower case PRC_UNREACH_PROTOCOL: 60036403Ssklower case PRC_UNREACH_PORT: 60136403Ssklower case PRC_UNREACH_NEEDFRAG: 60236403Ssklower case PRC_UNREACH_SRCFAIL: 60336403Ssklower case PRC_REDIRECT_NET: 60436403Ssklower case PRC_REDIRECT_HOST: 60536403Ssklower case PRC_REDIRECT_TOSNET: 60636403Ssklower case PRC_REDIRECT_TOSHOST: 60736403Ssklower case PRC_TIMXCEED_INTRANS: 60836403Ssklower case PRC_PARAMPROB: 60936403Ssklower */ 61039926Ssklower iso_pcbnotify(&tp_isopcb, siso, (int)inetctlerrmap[cmd], tpiso_abort); 61136403Ssklower break; 61236403Ssklower } 61336403Ssklower return 0; 61436403Ssklower } 61539926Ssklower /* 61639926Ssklower * XXX - Variant which is called by clnp_er.c with an isoaddr rather 61739926Ssklower * than a sockaddr_iso. 61839926Ssklower */ 61936403Ssklower 62039926Ssklower static struct sockaddr_iso siso = {sizeof(siso), AF_ISO}; 62139926Ssklower tpclnp_ctlinput1(cmd, isoa) 62239926Ssklower int cmd; 62339926Ssklower struct iso_addr *isoa; 62439926Ssklower { 62539926Ssklower bzero((caddr_t)&siso.siso_addr, sizeof(siso.siso_addr)); 62639926Ssklower bcopy((caddr_t)isoa, (caddr_t)&siso.siso_addr, isoa->isoa_len); 62739926Ssklower tpclnp_ctlinput(cmd, &siso); 62839926Ssklower } 62939926Ssklower 63036403Ssklower /* 63136403Ssklower * These next 2 routines are 63236403Ssklower * CALLED FROM: 63336403Ssklower * xxx_notify() from tp_ctlinput() when 63436403Ssklower * net level gets some ICMP-equiv. type event. 63536403Ssklower * FUNCTION and ARGUMENTS: 63636403Ssklower * Cause the connection to be aborted with some sort of error 63736403Ssklower * reason indicating that the network layer caused the abort. 63836403Ssklower * Fakes an ER TPDU so we can go through the driver. 63936403Ssklower * abort always aborts the TP connection. 64036403Ssklower * reset may or may not, depending on the TP class that's in use. 64136403Ssklower */ 64236403Ssklower ProtoHook 64336403Ssklower tpiso_abort(isop) 64436403Ssklower struct isopcb *isop; 64536403Ssklower { 64636403Ssklower struct tp_event e; 64736403Ssklower 64836403Ssklower IFDEBUG(D_CONN) 64936403Ssklower printf("tpiso_abort 0x%x\n", isop); 65036403Ssklower ENDDEBUG 65136403Ssklower e.ev_number = ER_TPDU; 65236403Ssklower e.ATTR(ER_TPDU).e_reason = ECONNABORTED; 65350435Ssklower return tp_driver((struct tp_pcb *)isop->isop_socket->so_pcb, &e); 65436403Ssklower } 65536403Ssklower 65636403Ssklower ProtoHook 65736403Ssklower tpiso_reset(isop) 65836403Ssklower struct isopcb *isop; 65936403Ssklower { 66036403Ssklower struct tp_event e; 66136403Ssklower 66236403Ssklower e.ev_number = T_NETRESET; 66350435Ssklower return tp_driver((struct tp_pcb *)isop->isop_socket->so_pcb, &e); 66436403Ssklower 66536403Ssklower } 66636403Ssklower 66760359Sbostic #endif /* ISO */ 668