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