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