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