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