149268Sbostic /*- 249268Sbostic * Copyright (c) 1991 The Regents of the University of California. 349268Sbostic * All rights reserved. 449268Sbostic * 549268Sbostic * %sccs.include.redist.c% 649268Sbostic * 7*56533Sbostic * @(#)tp_iso.c 7.14 (Berkeley) 10/11/92 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 63*56533Sbostic #include <sys/param.h> 64*56533Sbostic #include <sys/socket.h> 65*56533Sbostic #include <sys/socketvar.h> 66*56533Sbostic #include <sys/domain.h> 67*56533Sbostic #include <sys/malloc.h> 68*56533Sbostic #include <sys/mbuf.h> 69*56533Sbostic #include <sys/errno.h> 70*56533Sbostic #include <sys/time.h> 71*56533Sbostic #include <sys/protosw.h> 7237469Ssklower 73*56533Sbostic #include <net/if.h> 74*56533Sbostic #include <net/route.h> 7536403Ssklower 76*56533Sbostic #include <netiso/argo_debug.h> 77*56533Sbostic #include <netiso/tp_param.h> 78*56533Sbostic #include <netiso/tp_stat.h> 79*56533Sbostic #include <netiso/tp_pcb.h> 80*56533Sbostic #include <netiso/tp_trace.h> 81*56533Sbostic #include <netiso/tp_stat.h> 82*56533Sbostic #include <netiso/tp_tpdu.h> 83*56533Sbostic #include <netiso/tp_clnp.h> 84*56533Sbostic #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 { 44236403Ssklower int s = splnet(); 44337469Ssklower struct mbuf *tp_inputprep(); 44439926Ssklower int tp_input(), cltp_input(), (*input)() = tp_input; 44536403Ssklower 44636403Ssklower IncStat(ts_pkt_rcvd); 44736403Ssklower 44836403Ssklower IFDEBUG(D_TPINPUT) 44936403Ssklower printf("tpclnp_input: m 0x%x clnp_len 0x%x\n", m, clnp_len); 45036403Ssklower dump_mbuf(m, "at tpclnp_input"); 45136403Ssklower ENDDEBUG 45236403Ssklower /* 45336403Ssklower * CLNP gives us an mbuf chain WITH the clnp header pulled up, 45436403Ssklower * and the length of the clnp header. 45536403Ssklower * First, strip off the Clnp header. leave the mbuf there for the 45636403Ssklower * pullup that follows. 45736403Ssklower */ 45836403Ssklower 45936403Ssklower m->m_len -= clnp_len; 46037469Ssklower m->m_data += clnp_len; 46136403Ssklower 46237469Ssklower m = tp_inputprep(m); 46339926Ssklower if (m == 0) 46439926Ssklower return 0; 46539926Ssklower if (mtod(m, u_char *)[1] == UD_TPDU_type) 46639926Ssklower input = cltp_input; 46736403Ssklower 46836403Ssklower IFDEBUG(D_TPINPUT) 46936403Ssklower dump_mbuf(m, "after tpclnp_input both pullups"); 47036403Ssklower ENDDEBUG 47136403Ssklower 47236403Ssklower IFDEBUG(D_TPISO) 47339926Ssklower printf("calling %sinput : src 0x%x, dst 0x%x, src addr:\n", 47439926Ssklower (input == tp_input ? "tp_" : "clts_"), src, dst); 47539926Ssklower dump_isoaddr(src); 47636403Ssklower printf(" dst addr:\n"); 47739926Ssklower dump_isoaddr(dst); 47836403Ssklower ENDDEBUG 47936403Ssklower 48039926Ssklower (void) (*input)(m, (struct sockaddr *)src, (struct sockaddr *)dst, 48139927Ssklower 0, tpclnp_output_dg, ce_bit); 48236403Ssklower 48336403Ssklower IFDEBUG(D_QUENCH) 48436403Ssklower { 48536403Ssklower if(time.tv_usec & 0x4 && time.tv_usec & 0x40) { 48636403Ssklower printf("tpclnp_input: FAKING %s\n", 48736403Ssklower tp_stat.ts_pkt_rcvd & 0x1?"QUENCH":"QUENCH2"); 48836403Ssklower if(tp_stat.ts_pkt_rcvd & 0x1) { 48936403Ssklower tpclnp_ctlinput(PRC_QUENCH, &src); 49036403Ssklower } else { 49136403Ssklower tpclnp_ctlinput(PRC_QUENCH2, &src); 49236403Ssklower } 49336403Ssklower } 49436403Ssklower } 49536403Ssklower ENDDEBUG 49636403Ssklower 49736403Ssklower splx(s); 49836403Ssklower return 0; 49936403Ssklower } 50036403Ssklower 50136403Ssklower ProtoHook 50236403Ssklower iso_rtchange() 50336403Ssklower { 50436403Ssklower return 0; 50536403Ssklower } 50636403Ssklower 50736403Ssklower /* 50836403Ssklower * CALLED FROM: 50936403Ssklower * tpclnp_ctlinput() 51036403Ssklower * FUNCTION and ARGUMENTS: 51136403Ssklower * find the tpcb pointer and pass it to tp_quench 51236403Ssklower */ 51336403Ssklower void 51436403Ssklower tpiso_decbit(isop) 51536403Ssklower struct isopcb *isop; 51636403Ssklower { 51750435Ssklower tp_quench((struct tp_pcb *)isop->isop_socket->so_pcb, PRC_QUENCH2); 51836403Ssklower } 51936403Ssklower /* 52036403Ssklower * CALLED FROM: 52136403Ssklower * tpclnp_ctlinput() 52236403Ssklower * FUNCTION and ARGUMENTS: 52336403Ssklower * find the tpcb pointer and pass it to tp_quench 52436403Ssklower */ 52536403Ssklower void 52636403Ssklower tpiso_quench(isop) 52736403Ssklower struct isopcb *isop; 52836403Ssklower { 52950435Ssklower tp_quench((struct tp_pcb *)isop->isop_socket->so_pcb, PRC_QUENCH); 53036403Ssklower } 53136403Ssklower 53236403Ssklower /* 53336403Ssklower * CALLED FROM: 53436403Ssklower * The network layer through the protosw table. 53536403Ssklower * FUNCTION and ARGUMENTS: 53636403Ssklower * When clnp an ICMP-like msg this gets called. 53736403Ssklower * It either returns an error status to the user or 53836403Ssklower * it causes all connections on this address to be aborted 53936403Ssklower * by calling the appropriate xx_notify() routine. 54036403Ssklower * (cmd) is the type of ICMP error. 54136403Ssklower * (siso) is the address of the guy who sent the ER CLNPDU 54236403Ssklower */ 54336403Ssklower ProtoHook 54436403Ssklower tpclnp_ctlinput(cmd, siso) 54536403Ssklower int cmd; 54636403Ssklower struct sockaddr_iso *siso; 54736403Ssklower { 54836403Ssklower extern u_char inetctlerrmap[]; 54936403Ssklower extern ProtoHook tpiso_abort(); 55036403Ssklower extern ProtoHook iso_rtchange(); 55136403Ssklower extern ProtoHook tpiso_reset(); 55237469Ssklower void iso_pcbnotify(); 55336403Ssklower 55436403Ssklower IFDEBUG(D_TPINPUT) 55539926Ssklower printf("tpclnp_ctlinput1: cmd 0x%x addr: \n", cmd); 55639926Ssklower dump_isoaddr(siso); 55736403Ssklower ENDDEBUG 55836403Ssklower 55936403Ssklower if (cmd < 0 || cmd > PRC_NCMDS) 56036403Ssklower return 0; 56139926Ssklower if (siso->siso_family != AF_ISO) 56239926Ssklower return 0; 56336403Ssklower switch (cmd) { 56436403Ssklower 56536403Ssklower case PRC_QUENCH2: 56639926Ssklower iso_pcbnotify(&tp_isopcb, siso, 0, (int (*)())tpiso_decbit); 56736403Ssklower break; 56836403Ssklower 56936403Ssklower case PRC_QUENCH: 57039926Ssklower iso_pcbnotify(&tp_isopcb, siso, 0, (int (*)())tpiso_quench); 57136403Ssklower break; 57236403Ssklower 57336403Ssklower case PRC_TIMXCEED_REASS: 57436403Ssklower case PRC_ROUTEDEAD: 57539926Ssklower iso_pcbnotify(&tp_isopcb, siso, 0, tpiso_reset); 57636403Ssklower break; 57736403Ssklower 57836403Ssklower case PRC_HOSTUNREACH: 57936403Ssklower case PRC_UNREACH_NET: 58036403Ssklower case PRC_IFDOWN: 58136403Ssklower case PRC_HOSTDEAD: 58239926Ssklower iso_pcbnotify(&tp_isopcb, siso, 58336403Ssklower (int)inetctlerrmap[cmd], iso_rtchange); 58436403Ssklower break; 58536403Ssklower 58636403Ssklower default: 58736403Ssklower /* 58836403Ssklower case PRC_MSGSIZE: 58936403Ssklower case PRC_UNREACH_HOST: 59036403Ssklower case PRC_UNREACH_PROTOCOL: 59136403Ssklower case PRC_UNREACH_PORT: 59236403Ssklower case PRC_UNREACH_NEEDFRAG: 59336403Ssklower case PRC_UNREACH_SRCFAIL: 59436403Ssklower case PRC_REDIRECT_NET: 59536403Ssklower case PRC_REDIRECT_HOST: 59636403Ssklower case PRC_REDIRECT_TOSNET: 59736403Ssklower case PRC_REDIRECT_TOSHOST: 59836403Ssklower case PRC_TIMXCEED_INTRANS: 59936403Ssklower case PRC_PARAMPROB: 60036403Ssklower */ 60139926Ssklower iso_pcbnotify(&tp_isopcb, siso, (int)inetctlerrmap[cmd], tpiso_abort); 60236403Ssklower break; 60336403Ssklower } 60436403Ssklower return 0; 60536403Ssklower } 60639926Ssklower /* 60739926Ssklower * XXX - Variant which is called by clnp_er.c with an isoaddr rather 60839926Ssklower * than a sockaddr_iso. 60939926Ssklower */ 61036403Ssklower 61139926Ssklower static struct sockaddr_iso siso = {sizeof(siso), AF_ISO}; 61239926Ssklower tpclnp_ctlinput1(cmd, isoa) 61339926Ssklower int cmd; 61439926Ssklower struct iso_addr *isoa; 61539926Ssklower { 61639926Ssklower bzero((caddr_t)&siso.siso_addr, sizeof(siso.siso_addr)); 61739926Ssklower bcopy((caddr_t)isoa, (caddr_t)&siso.siso_addr, isoa->isoa_len); 61839926Ssklower tpclnp_ctlinput(cmd, &siso); 61939926Ssklower } 62039926Ssklower 62136403Ssklower /* 62236403Ssklower * These next 2 routines are 62336403Ssklower * CALLED FROM: 62436403Ssklower * xxx_notify() from tp_ctlinput() when 62536403Ssklower * net level gets some ICMP-equiv. type event. 62636403Ssklower * FUNCTION and ARGUMENTS: 62736403Ssklower * Cause the connection to be aborted with some sort of error 62836403Ssklower * reason indicating that the network layer caused the abort. 62936403Ssklower * Fakes an ER TPDU so we can go through the driver. 63036403Ssklower * abort always aborts the TP connection. 63136403Ssklower * reset may or may not, depending on the TP class that's in use. 63236403Ssklower */ 63336403Ssklower ProtoHook 63436403Ssklower tpiso_abort(isop) 63536403Ssklower struct isopcb *isop; 63636403Ssklower { 63736403Ssklower struct tp_event e; 63836403Ssklower 63936403Ssklower IFDEBUG(D_CONN) 64036403Ssklower printf("tpiso_abort 0x%x\n", isop); 64136403Ssklower ENDDEBUG 64236403Ssklower e.ev_number = ER_TPDU; 64336403Ssklower e.ATTR(ER_TPDU).e_reason = ECONNABORTED; 64450435Ssklower return tp_driver((struct tp_pcb *)isop->isop_socket->so_pcb, &e); 64536403Ssklower } 64636403Ssklower 64736403Ssklower ProtoHook 64836403Ssklower tpiso_reset(isop) 64936403Ssklower struct isopcb *isop; 65036403Ssklower { 65136403Ssklower struct tp_event e; 65236403Ssklower 65336403Ssklower e.ev_number = T_NETRESET; 65450435Ssklower return tp_driver((struct tp_pcb *)isop->isop_socket->so_pcb, &e); 65536403Ssklower 65636403Ssklower } 65736403Ssklower 65836403Ssklower #endif ISO 659