|
|
1.1 ! root 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: * ! 33: * @(#)if_cons.c 7.10 (Berkeley) 5/29/91 ! 34: */ ! 35: ! 36: /*********************************************************** ! 37: Copyright IBM Corporation 1987 ! 38: ! 39: All Rights Reserved ! 40: ! 41: Permission to use, copy, modify, and distribute this software and its ! 42: documentation for any purpose and without fee is hereby granted, ! 43: provided that the above copyright notice appear in all copies and that ! 44: both that copyright notice and this permission notice appear in ! 45: supporting documentation, and that the name of IBM not be ! 46: used in advertising or publicity pertaining to distribution of the ! 47: software without specific, written prior permission. ! 48: ! 49: IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ! 50: ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL ! 51: IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ! 52: ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, ! 53: WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ! 54: ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS ! 55: SOFTWARE. ! 56: ! 57: ******************************************************************/ ! 58: ! 59: /* ! 60: * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison ! 61: */ ! 62: /* ! 63: * $Header: if_cons.c,v 4.7 88/08/11 15:52:55 nhall Exp $ ! 64: * $Source: /usr/argo/sys/netiso/RCS/if_cons.c,v $ ! 65: * ! 66: * cons.c - Connection Oriented Network Service: ! 67: * including support for a) user transport-level service, ! 68: * b) COSNS below CLNP, and c) CONS below TP. ! 69: */ ! 70: ! 71: #ifdef TPCONS ! 72: #ifdef KERNEL ! 73: #ifdef ARGO_DEBUG ! 74: #define Static ! 75: unsigned LAST_CALL_PCB; ! 76: #else ARGO_DEBUG ! 77: #define Static static ! 78: #endif ARGO_DEBUG ! 79: ! 80: ! 81: ! 82: #ifndef SOCK_STREAM ! 83: #include "param.h" ! 84: #include "systm.h" ! 85: #include "mbuf.h" ! 86: #include "protosw.h" ! 87: #include "socket.h" ! 88: #include "socketvar.h" ! 89: #include "errno.h" ! 90: #include "ioctl.h" ! 91: #include "tsleep.h" ! 92: ! 93: #include "../net/if.h" ! 94: #include "../net/netisr.h" ! 95: #include "../net/route.h" ! 96: ! 97: #include "iso_errno.h" ! 98: #include "argo_debug.h" ! 99: #include "tp_trace.h" ! 100: #include "iso.h" ! 101: #include "cons.h" ! 102: #include "iso_pcb.h" ! 103: ! 104: #include "../netccitt/x25.h" ! 105: #include "../netccitt/pk.h" ! 106: #include "../netccitt/pk_var.h" ! 107: #endif ! 108: ! 109: #ifdef ARGO_DEBUG ! 110: #define MT_XCONN 0x50 ! 111: #define MT_XCLOSE 0x51 ! 112: #define MT_XCONFIRM 0x52 ! 113: #define MT_XDATA 0x53 ! 114: #define MT_XHEADER 0x54 ! 115: #else ! 116: #define MT_XCONN MT_DATA ! 117: #define MT_XCLOSE MT_DATA ! 118: #define MT_XCONFIRM MT_DATA ! 119: #define MT_XDATA MT_DATA ! 120: #define MT_XHEADER MT_HEADER ! 121: #endif ARGO_DEBUG ! 122: ! 123: #define DONTCLEAR -1 ! 124: ! 125: /********************************************************************* ! 126: * cons.c - CONS interface to the x.25 layer ! 127: * ! 128: * TODO: figure out what resources we might run out of besides mbufs. ! 129: * If we run out of any of them (including mbufs) close and recycle ! 130: * lru x% of the connections, for some parameter x. ! 131: * ! 132: * There are 2 interfaces from above: ! 133: * 1) from TP0: ! 134: * cons CO network service ! 135: * TP associates a transport connection with a network connection. ! 136: * cons_output( isop, m, len, isdgm==0 ) ! 137: * co_flags == 0 ! 138: * 2) from TP4: ! 139: * It's a datagram service, like clnp is. - even though it calls ! 140: * cons_output( isop, m, len, isdgm==1 ) ! 141: * it eventually goes through ! 142: * cosns_output(ifp, m, dst). ! 143: * TP4 permits multiplexing (reuse, possibly simultaneously) of the ! 144: * network connections. ! 145: * This means that many sockets (many tpcbs) may be associated with ! 146: * this pklcd, hence cannot have a back ptr from pklcd to a tpcb. ! 147: * co_flags & CONSF_DGM ! 148: * co_socket is null since there may be many sockets that use this pklcd. ! 149: * ! 150: NOTE: ! 151: streams would really be nice. sigh. ! 152: NOTE: ! 153: PVCs could be handled by config-ing a cons with an address and with the ! 154: IFF_POINTTOPOINT flag on. This code would then have to skip the ! 155: connection setup stuff for pt-to-pt links. ! 156: ! 157: ! 158: *********************************************************************/ ! 159: ! 160: ! 161: #define CONS_IFQMAXLEN 5 ! 162: ! 163: ! 164: /* protosw pointers for getting to higher layer */ ! 165: Static struct protosw *CLNP_proto; ! 166: Static struct protosw *TP_proto; ! 167: Static struct protosw *X25_proto; ! 168: Static int issue_clear_req(); ! 169: ! 170: #ifndef PHASEONE ! 171: extern struct ifaddr *ifa_ifwithnet(); ! 172: #endif PHASEONE ! 173: ! 174: extern struct ifaddr *ifa_ifwithaddr(); ! 175: ! 176: Static struct socket dummysocket; /* for use by cosns */ ! 177: ! 178: extern struct isopcb tp_isopcb; /* chain of all TP pcbs */ ! 179: struct isopcb tp_incoming_pending; /* incoming connections ! 180: for TP, pending */ ! 181: ! 182: struct isopcb *Xpcblist[] = { ! 183: &tp_incoming_pending, ! 184: &tp_isopcb, ! 185: (struct isopcb *)0 ! 186: }; ! 187: ! 188: Static int parse_facil(), NSAPtoDTE(), make_partial_x25_packet(); ! 189: Static int FACILtoNSAP(), DTEtoNSAP(); ! 190: Static struct pklcd *cons_chan_to_pcb(); ! 191: ! 192: #define HIGH_NIBBLE 1 ! 193: #define LOW_NIBBLE 0 ! 194: ! 195: /* ! 196: * NAME: nibble_copy() ! 197: * FUNCTION and ARGUMENTS: ! 198: * copies (len) nibbles from (src_octet), high or low nibble ! 199: * to (dst_octet), high or low nibble, ! 200: * src_nibble & dst_nibble should be: ! 201: * HIGH_NIBBLE (1) if leftmost 4 bits/ most significant nibble ! 202: * LOW_NIBBLE (0) if rightmost 4 bits/ least significant nibble ! 203: * RETURNS: VOID ! 204: */ ! 205: void ! 206: nibble_copy(src_octet, src_nibble, dst_octet, dst_nibble, len) ! 207: register char *src_octet; ! 208: register char *dst_octet; ! 209: register unsigned src_nibble; ! 210: register unsigned dst_nibble; ! 211: int len; ! 212: { ! 213: ! 214: register i; ! 215: register unsigned dshift, sshift; ! 216: ! 217: IFDEBUG(D_CADDR) ! 218: printf("nibble_copy ( 0x%x, 0x%x, 0x%x, 0x%x 0x%x)\n", ! 219: src_octet, src_nibble, dst_octet, dst_nibble, len); ! 220: ENDDEBUG ! 221: #define SHIFT 0x4 ! 222: ! 223: dshift = dst_nibble << 2; ! 224: sshift = src_nibble << 2; ! 225: ! 226: for (i=0; i<len; i++) { ! 227: /* clear dst_nibble */ ! 228: *dst_octet &= ~(0xf<< dshift); ! 229: ! 230: /* set dst nibble */ ! 231: *dst_octet |= ( 0xf & (*src_octet >> sshift))<< dshift; ! 232: ! 233: dshift ^= SHIFT; ! 234: sshift ^= SHIFT; ! 235: src_nibble = 1-src_nibble; ! 236: dst_nibble = 1-dst_nibble; ! 237: src_octet += src_nibble; ! 238: dst_octet += dst_nibble; ! 239: } ! 240: IFDEBUG(D_CADDR) ! 241: printf("nibble_copy DONE\n"); ! 242: ENDDEBUG ! 243: } ! 244: ! 245: /* ! 246: * NAME: nibble_match() ! 247: * FUNCTION and ARGUMENTS: ! 248: * compares src_octet/src_nibble and dst_octet/dst_nibble for len nibbles. ! 249: * RETURNS: 0 if they differ, 1 if they are the same. ! 250: */ ! 251: int ! 252: nibble_match( src_octet, src_nibble, dst_octet, dst_nibble, len) ! 253: register char *src_octet; ! 254: register char *dst_octet; ! 255: register unsigned src_nibble; ! 256: register unsigned dst_nibble; ! 257: int len; ! 258: { ! 259: ! 260: register i; ! 261: register unsigned dshift, sshift; ! 262: u_char nibble_a, nibble_b; ! 263: ! 264: IFDEBUG(D_CADDR) ! 265: printf("nibble_match ( 0x%x, 0x%x, 0x%x, 0x%x 0x%x)\n", ! 266: src_octet, src_nibble, dst_octet, dst_nibble, len); ! 267: ENDDEBUG ! 268: #define SHIFT 0x4 ! 269: ! 270: dshift = dst_nibble << 2; ! 271: sshift = src_nibble << 2; ! 272: ! 273: for (i=0; i<len; i++) { ! 274: nibble_b = ((*dst_octet)>>dshift) & 0xf; ! 275: nibble_a = ( 0xf & (*src_octet >> sshift)); ! 276: if (nibble_b != nibble_a) ! 277: return 0; ! 278: ! 279: dshift ^= SHIFT; ! 280: sshift ^= SHIFT; ! 281: src_nibble = 1-src_nibble; ! 282: dst_nibble = 1-dst_nibble; ! 283: src_octet += src_nibble; ! 284: dst_octet += dst_nibble; ! 285: } ! 286: IFDEBUG(D_CADDR) ! 287: printf("nibble_match DONE\n"); ! 288: ENDDEBUG ! 289: return 1; ! 290: } ! 291: ! 292: /* ! 293: **************************** NET PROTOCOL cons *************************** ! 294: */ ! 295: /* ! 296: * NAME: cons_init() ! 297: * CALLED FROM: ! 298: * autoconf ! 299: * FUNCTION: ! 300: * initialize the protocol ! 301: */ ! 302: cons_init() ! 303: { ! 304: int tp_incoming(), clnp_incoming(); ! 305: ! 306: ! 307: CLNP_proto = pffindproto(AF_ISO, ISOPROTO_CLNP, SOCK_DGRAM); ! 308: X25_proto = pffindproto(AF_ISO, ISOPROTO_X25, SOCK_STREAM); ! 309: TP_proto = pffindproto(AF_ISO, ISOPROTO_TP0, SOCK_SEQPACKET); ! 310: IFDEBUG(D_CCONS) ! 311: printf("cons_init end : cnlp_proto 0x%x cons proto 0x%x tp proto 0x%x\n", ! 312: CLNP_proto, X25_proto, TP_proto); ! 313: ENDDEBUG ! 314: #ifdef notdef ! 315: pk_protolisten(0x81, 0, clnp_incoming); ! 316: pk_protolisten(0x82, 0, esis_incoming); ! 317: pk_protolisten(0x84, 0, tp8878_A_incoming); ! 318: pk_protolisten(0, 0, tp_incoming); ! 319: #endif ! 320: } ! 321: ! 322: tp_incoming(lcp, m) ! 323: struct pklcd *lcp; ! 324: register struct mbuf *m; ! 325: { ! 326: register struct isopcb *isop; ! 327: extern struct isopcb tp_isopcb; ! 328: int cons_tpinput(); ! 329: ! 330: if (iso_pcballoc((struct socket *)0, &tp_incoming_pending)) { ! 331: pk_close(lcp); ! 332: return; ! 333: } ! 334: isop = tp_incoming_pending.isop_next; ! 335: lcp->lcd_upper = cons_tpinput; ! 336: lcp->lcd_upnext = (caddr_t)isop; ! 337: lcp->lcd_send(lcp); /* Confirms call */ ! 338: isop->isop_chan = (caddr_t)lcp; ! 339: isop->isop_laddr = &isop->isop_sladdr; ! 340: isop->isop_faddr = &isop->isop_sfaddr; ! 341: DTEtoNSAP(isop->isop_laddr, &lcp->lcd_laddr); ! 342: DTEtoNSAP(isop->isop_faddr, &lcp->lcd_faddr); ! 343: parse_facil(isop, lcp, &(mtod(m, struct x25_packet *)->packet_data), ! 344: m->m_pkthdr.len - PKHEADERLN); ! 345: } ! 346: ! 347: cons_tpinput(lcp, m0) ! 348: struct mbuf *m0; ! 349: struct pklcd *lcp; ! 350: { ! 351: register struct isopcb *isop = (struct isopcb *)lcp->lcd_upnext; ! 352: register struct x25_packet *xp; ! 353: int cmd; ! 354: ! 355: if (isop == 0) ! 356: return; ! 357: if (m0 == 0) { ! 358: isop->isop_chan = 0; ! 359: isop->isop_refcnt = 0; ! 360: lcp->lcd_upnext = 0; ! 361: lcp->lcd_upper = 0; ! 362: goto dead; ! 363: } ! 364: switch(m0->m_type) { ! 365: case MT_DATA: ! 366: case MT_OOBDATA: ! 367: tpcons_input(m0, isop->isop_faddr, isop->isop_laddr, ! 368: (struct socket *)0, (caddr_t)lcp); ! 369: return; ! 370: ! 371: case MT_CONTROL: ! 372: switch (pk_decode(mtod(m0, struct x25_packet *))) { ! 373: ! 374: case RR: ! 375: cmd = PRC_CONS_SEND_DONE; ! 376: break; ! 377: ! 378: case CALL_ACCEPTED: ! 379: if (lcp->lcd_sb.sb_mb) ! 380: lcp->lcd_send(lcp); /* XXX - fix this */ ! 381: /*FALLTHROUGH*/ ! 382: default: ! 383: return; ! 384: ! 385: dead: ! 386: case RESET: ! 387: case CLEAR: ! 388: case CLEAR_CONF: ! 389: cmd = PRC_ROUTEDEAD; ! 390: } ! 391: tpcons_ctlinput(cmd, isop->isop_faddr, isop); ! 392: } ! 393: } ! 394: ! 395: /* ! 396: * NAME: cons_connect() ! 397: * CALLED FROM: ! 398: * tpcons_pcbconnect() when opening a new connection. ! 399: * FUNCTION anD ARGUMENTS: ! 400: * Figures out which device to use, finding a route if one doesn't ! 401: * already exist. ! 402: * RETURN VALUE: ! 403: * returns E* ! 404: */ ! 405: cons_connect(isop) ! 406: register struct isopcb *isop; ! 407: { ! 408: register struct pklcd *lcp = (struct pklcd *)isop->isop_chan; ! 409: register struct mbuf *m; ! 410: struct ifaddr *ifa; ! 411: int error; ! 412: ! 413: IFDEBUG(D_CCONN) ! 414: printf("cons_connect(0x%x): ", isop); ! 415: dump_isoaddr(isop->isop_faddr); ! 416: printf("myaddr: "); ! 417: dump_isoaddr(isop->isop_laddr); ! 418: printf("\n" ); ! 419: ENDDEBUG ! 420: NSAPtoDTE(isop->isop_faddr, &lcp->lcd_faddr); ! 421: lcp->lcd_upper = cons_tpinput; ! 422: lcp->lcd_upnext = (caddr_t)isop; ! 423: IFDEBUG(D_CCONN) ! 424: printf( ! 425: "calling make_partial_x25_packet( 0x%x, 0x%x, 0x%x)\n", ! 426: &lcp->lcd_faddr, &lcp->lcd_laddr, ! 427: isop->isop_socket->so_proto->pr_protocol); ! 428: ENDDEBUG ! 429: if ((error = make_partial_x25_packet(isop, lcp, m)) == 0) ! 430: error = pk_connect(lcp, &lcp->lcd_faddr); ! 431: return error; ! 432: } ! 433: ! 434: /* ! 435: **************************** DEVICE cons *************************** ! 436: */ ! 437: ! 438: ! 439: /* ! 440: * NAME: cons_ctlinput() ! 441: * CALLED FROM: ! 442: * lower layer when ECN_CLEAR occurs : this routine is here ! 443: * for consistency - cons subnet service calls its higher layer ! 444: * through the protosw entry. ! 445: * FUNCTION & ARGUMENTS: ! 446: * cmd is a PRC_* command, list found in ../sys/protosw.h ! 447: * copcb is the obvious. ! 448: * This serves the higher-layer cons service. ! 449: * NOTE: this takes 3rd arg. because cons uses it to inform itself ! 450: * of things (timeouts, etc) but has a pcb instead of an address. ! 451: */ ! 452: cons_ctlinput(cmd, sa, copcb) ! 453: int cmd; ! 454: struct sockaddr *sa; ! 455: register struct pklcd *copcb; ! 456: { ! 457: } ! 458: ! 459: ! 460: find_error_reason( xp ) ! 461: register struct x25_packet *xp; ! 462: { ! 463: extern u_char x25_error_stats[]; ! 464: int error, cause; ! 465: ! 466: if (xp) { ! 467: cause = 4[(char *)xp]; ! 468: switch (cause) { ! 469: case 0x00: ! 470: case 0x80: ! 471: /* DTE originated; look at the diagnostic */ ! 472: error = (CONL_ERROR_MASK | cause); ! 473: goto done; ! 474: ! 475: case 0x01: /* number busy */ ! 476: case 0x81: ! 477: case 0x09: /* Out of order */ ! 478: case 0x89: ! 479: case 0x11: /* Remot Procedure Error */ ! 480: case 0x91: ! 481: case 0x19: /* reverse charging accept not subscribed */ ! 482: case 0x99: ! 483: case 0x21: /* Incampat destination */ ! 484: case 0xa1: ! 485: case 0x29: /* fast select accept not subscribed */ ! 486: case 0xa9: ! 487: case 0x39: /* ship absent */ ! 488: case 0xb9: ! 489: case 0x03: /* invalid facil request */ ! 490: case 0x83: ! 491: case 0x0b: /* access barred */ ! 492: case 0x8b: ! 493: case 0x13: /* local procedure error */ ! 494: case 0x93: ! 495: case 0x05: /* network congestion */ ! 496: case 0x85: ! 497: case 0x8d: /* not obtainable */ ! 498: case 0x0d: ! 499: case 0x95: /* RPOA out of order */ ! 500: case 0x15: ! 501: /* take out bit 8 ! 502: * so we don't have to have so many perror entries ! 503: */ ! 504: error = (CONL_ERROR_MASK | 0x100 | (cause & ~0x80)); ! 505: goto done; ! 506: ! 507: case 0xc1: /* gateway-detected proc error */ ! 508: case 0xc3: /* gateway congestion */ ! 509: ! 510: error = (CONL_ERROR_MASK | 0x100 | cause); ! 511: goto done; ! 512: } ! 513: } ! 514: /* otherwise, a *hopefully* valid perror exists in the e_reason field */ ! 515: error = xp->packet_data; ! 516: if (error = 0) { ! 517: printf("Incoming PKT TYPE 0x%x with reason 0x%x\n", ! 518: pk_decode(xp), ! 519: cause); ! 520: error = E_CO_HLI_DISCA; ! 521: } ! 522: ! 523: done: ! 524: return error; ! 525: } ! 526: ! 527: ! 528: ! 529: #endif KERNEL ! 530: ! 531: /* ! 532: * NAME: make_partial_x25_packet() ! 533: * ! 534: * FUNCTION and ARGUMENTS: ! 535: * Makes part of an X.25 call packet, for use by x25. ! 536: * (src) and (dst) are the NSAP-addresses of source and destination. ! 537: * (buf) is a ptr to a buffer into which to write this partial header. ! 538: * ! 539: * 0 Facility length (in octets) ! 540: * 1 Facility field, which is a set of: ! 541: * m facil code ! 542: * m+1 facil param len (for >2-byte facilities) in octets ! 543: * m+2..p facil param field ! 544: * q user data (protocol identification octet) ! 545: * ! 546: * ! 547: * RETURNS: ! 548: * 0 if OK ! 549: * E* if failed. ! 550: * ! 551: * SIDE EFFECTS: ! 552: * Stores facilites mbuf in X.25 control block, where the connect ! 553: * routine knows where to look for it. ! 554: */ ! 555: ! 556: #ifdef X25_1984 ! 557: int cons_use_facils = 1; ! 558: #else X25_1984 ! 559: int cons_use_facils = 0; ! 560: #endif X25_1984 ! 561: ! 562: int cons_use_udata = 1; /* KLUDGE FOR DEBUGGING */ ! 563: ! 564: Static int ! 565: make_partial_x25_packet(isop, lcp) ! 566: struct isopcb *isop; ! 567: struct pklcd *lcp; ! 568: { ! 569: u_int proto; ! 570: int flag; ! 571: caddr_t buf; ! 572: register caddr_t ptr; ! 573: register int len = 0; ! 574: int buflen =0; ! 575: caddr_t facil_len; ! 576: int oddness = 0; ! 577: struct mbuf *m; ! 578: ! 579: ! 580: IFDEBUG(D_CCONN) ! 581: printf("make_partial_x25_packet(0x%x, 0x%x, 0x%x, 0x%x, 0x%x)\n", ! 582: isop->isop_laddr, isop->isop_faddr, proto, m, flag); ! 583: ENDDEBUG ! 584: if (cons_use_udata) { ! 585: if (isop->isop_x25crud_len > 0) { ! 586: /* ! 587: * The user specified something. Stick it in ! 588: */ ! 589: bcopy(isop->isop_x25crud, lcp->lcd_faddr.x25_udata, ! 590: isop->isop_x25crud_len); ! 591: lcp->lcd_faddr.x25_udlen = isop->isop_x25crud_len; ! 592: } ! 593: } ! 594: ! 595: if (cons_use_facils == 0) { ! 596: lcp->lcd_facilities = 0; ! 597: return 0; ! 598: } ! 599: MGETHDR(m, MT_DATA, M_WAITOK); ! 600: if (m == 0) ! 601: return ENOBUFS; ! 602: buf = mtod(m, caddr_t); ! 603: ptr = buf; ! 604: ! 605: /* ptr now points to facil length (len of whole facil field in OCTETS */ ! 606: facil_len = ptr ++; ! 607: m->m_len = 0; ! 608: pk_build_facilities(m, &lcp->lcd_faddr, 0); ! 609: ! 610: IFDEBUG(D_CADDR) ! 611: printf("make_partial calling: ptr 0x%x, len 0x%x\n", ptr, ! 612: isop->isop_laddr->siso_addr.isoa_len); ! 613: ENDDEBUG ! 614: if (cons_use_facils) { ! 615: *ptr++ = 0; /* Marker to separate X.25 facitilies from CCITT ones */ ! 616: *ptr++ = 0x0f; ! 617: *ptr = 0xcb; /* calling facility code */ ! 618: ptr ++; ! 619: ptr ++; /* leave room for facil param len (in OCTETS + 1) */ ! 620: ptr ++; /* leave room for the facil param len (in nibbles), ! 621: * high two bits of which indicate full/partial NSAP ! 622: */ ! 623: len = isop->isop_laddr->siso_addr.isoa_len; ! 624: bcopy( isop->isop_laddr->siso_data, ptr, len); ! 625: *(ptr-2) = len+1; /* facil param len in octets */ ! 626: *(ptr-1) = len<<1; /* facil param len in nibbles */ ! 627: ptr += len; ! 628: ! 629: IFDEBUG(D_CADDR) ! 630: printf("make_partial called: ptr 0x%x, len 0x%x\n", ptr, ! 631: isop->isop_faddr->siso_addr.isoa_len); ! 632: ENDDEBUG ! 633: *ptr = 0xc9; /* called facility code */ ! 634: ptr ++; ! 635: ptr ++; /* leave room for facil param len (in OCTETS + 1) */ ! 636: ptr ++; /* leave room for the facil param len (in nibbles), ! 637: * high two bits of which indicate full/partial NSAP ! 638: */ ! 639: len = isop->isop_faddr->siso_nlen; ! 640: bcopy(isop->isop_faddr->siso_data, ptr, len); ! 641: *(ptr-2) = len+1; /* facil param len = addr len + 1 for each of these ! 642: * two length fields, in octets */ ! 643: *(ptr-1) = len<<1; /* facil param len in nibbles */ ! 644: ptr += len; ! 645: ! 646: } ! 647: *facil_len = ptr - facil_len - 1; ! 648: if (*facil_len > MAX_FACILITIES) ! 649: return E_CO_PNA_LONG; ! 650: ! 651: buflen = (int)(ptr - buf); ! 652: ! 653: IFDEBUG(D_CDUMP_REQ) ! 654: register int i; ! 655: ! 656: printf("ECN_CONNECT DATA buf 0x%x len %d (0x%x)\n", ! 657: buf, buflen, buflen); ! 658: for( i=0; i < buflen; ) { ! 659: printf("+%d: %x %x %x %x %x %x %x %x\n", ! 660: i, ! 661: *(buf+i), *(buf+i+1), *(buf+i+2), *(buf+i+3), ! 662: *(buf+i+4), *(buf+i+5), *(buf+i+6), *(buf+i+7)); ! 663: i+=8; ! 664: } ! 665: ENDDEBUG ! 666: IFDEBUG(D_CADDR) ! 667: printf("make_partial returns buf 0x%x size 0x%x bytes\n", ! 668: mtod(m, caddr_t), buflen); ! 669: ENDDEBUG ! 670: ! 671: if (buflen > MHLEN) ! 672: return E_CO_PNA_LONG; ! 673: ! 674: m->m_pkthdr.len = m->m_len = buflen; ! 675: lcp->lcd_facilities = m; ! 676: return 0; ! 677: } ! 678: ! 679: /* ! 680: * NAME: NSAPtoDTE() ! 681: * CALLED FROM: ! 682: * make_partial_x25_packet() ! 683: * FUNCTION and ARGUMENTS: ! 684: * get a DTE address from an NSAP-address (struct sockaddr_iso) ! 685: * (dst_octet) is the octet into which to begin stashing the DTE addr ! 686: * (dst_nibble) takes 0 or 1. 1 means begin filling in the DTE addr ! 687: * in the high-order nibble of dst_octet. 0 means low-order nibble. ! 688: * (addr) is the NSAP-address ! 689: * (flag) is true if the transport suffix is to become the ! 690: * last two digits of the DTE address ! 691: * A DTE address is a series of ASCII digits ! 692: * ! 693: * A DTE address may have leading zeros. The are significant. ! 694: * 1 digit per nibble, may be an odd number of nibbles. ! 695: * ! 696: * An NSAP-address has the DTE address in the IDI. Leading zeros are ! 697: * significant. Trailing hex f indicates the end of the DTE address. ! 698: * The IDI is a series of BCD digits, one per nibble. ! 699: * ! 700: * RETURNS ! 701: * # significant digits in the DTE address, -1 if error. ! 702: */ ! 703: ! 704: Static int ! 705: NSAPtoDTE(siso, sx25) ! 706: register struct sockaddr_iso *siso; ! 707: register struct sockaddr_x25 *sx25; ! 708: { ! 709: int dtelen = -1; ! 710: ! 711: IFDEBUG(D_CADDR) ! 712: printf("NSAPtoDTE: nsap: %s\n", clnp_iso_addrp(&siso->siso_addr)); ! 713: ENDDEBUG ! 714: ! 715: if (siso->siso_data[0] == AFI_37) { ! 716: register char *out = sx25->x25_addr; ! 717: register char *in = siso->siso_data + 1; ! 718: register int nibble; ! 719: char *lim = siso->siso_data + siso->siso_nlen; ! 720: char *olim = out+15; ! 721: int lowNibble = 0; ! 722: ! 723: while (in < lim) { ! 724: nibble = ((lowNibble ? *in++ : (*in >> 4)) & 0xf) | 0x30; ! 725: lowNibble ^= 1; ! 726: if (nibble != 0x3f && out < olim) ! 727: *out++ = nibble; ! 728: } ! 729: dtelen = out - sx25->x25_addr; ! 730: *out++ = 0; ! 731: } else { ! 732: register struct rtentry *rt = rtalloc1(siso, 1); ! 733: /* error = iso_8208snparesolve(addr, x121string, &x121strlen);*/ ! 734: ! 735: if (rt) { ! 736: register struct sockaddr_x25 *sxx = ! 737: (struct sockaddr_x25 *)rt->rt_gateway; ! 738: register char *in = sxx->x25_addr; ! 739: ! 740: rt->rt_use--; ! 741: if (sxx && sxx->x25_family == AF_CCITT) { ! 742: bcopy(sx25->x25_addr, sxx->x25_addr, sizeof(sx25->x25_addr)); ! 743: while (*in++) {} ! 744: dtelen = in - sxx->x25_addr; ! 745: } ! 746: } ! 747: } ! 748: return dtelen; ! 749: } ! 750: ! 751: /* ! 752: * NAME: FACILtoNSAP() ! 753: * CALLED FROM: ! 754: * parse_facil() ! 755: * FUNCTION and ARGUMENTS: ! 756: * Creates and NSAP in the sockaddr_iso (addr) from the ! 757: * x.25 facility found at buf - 1. ! 758: * RETURNS: ! 759: * length of parameter if ok, -1 if error. ! 760: */ ! 761: ! 762: Static int ! 763: FACILtoNSAP(addr, buf) ! 764: u_char *buf; ! 765: register struct sockaddr_iso *addr; ! 766: { ! 767: int len_in_nibbles, param_len = *buf++; ! 768: u_char buf_len; /* in bytes */ ! 769: ! 770: IFDEBUG(D_CADDR) ! 771: printf("FACILtoNSAP( 0x%x, 0x%x, 0x%x )\n", ! 772: buf, buf_len, addr ); ! 773: ENDDEBUG ! 774: ! 775: len_in_nibbles = *buf & 0x3f; ! 776: buf_len = (len_in_nibbles + 1) >> 1; ! 777: /* despite the fact that X.25 makes us put a length in nibbles ! 778: * here, the NSAP-addrs are always in full octets ! 779: */ ! 780: switch (*buf++ & 0xc0) { ! 781: case 0: ! 782: /* Entire OSI NSAP address */ ! 783: bcopy((caddr_t)buf, addr->siso_data, addr->siso_nlen = buf_len); ! 784: break; ! 785: ! 786: case 40: ! 787: /* Partial OSI NSAP address, assume trailing */ ! 788: if (buf_len + addr->siso_nlen > sizeof(addr->siso_addr)) ! 789: return -1; ! 790: bcopy((caddr_t)buf, TSEL(addr), buf_len); ! 791: addr->siso_nlen += buf_len; ! 792: break; ! 793: ! 794: default: ! 795: /* Rather than blow away the connection, just ignore and use ! 796: NSAP from DTE */; ! 797: } ! 798: return param_len; ! 799: } ! 800: ! 801: static ! 802: init_siso(siso) ! 803: register struct sockaddr_iso *siso; ! 804: { ! 805: siso->siso_len = sizeof (*siso); ! 806: siso->siso_family = AF_ISO; ! 807: siso->siso_data[0] = AFI_37; ! 808: siso->siso_nlen = 8; ! 809: } ! 810: ! 811: /* ! 812: * NAME: DTEtoNSAP() ! 813: * CALLED FROM: ! 814: * parse_facil() ! 815: * FUNCTION and ARGUMENTS: ! 816: * Creates a type 37 NSAP in the sockaddr_iso (addr) ! 817: * from a DTE address found in a sockaddr_x25. ! 818: * ! 819: * RETURNS: ! 820: * 0 if ok; E* otherwise. ! 821: */ ! 822: ! 823: Static int ! 824: DTEtoNSAP(addr, sx) ! 825: struct sockaddr_iso *addr; ! 826: struct sockaddr_x25 *sx; ! 827: { ! 828: register char *in, *out; ! 829: register int first; ! 830: int pad_tail = 0; ! 831: int src_len; ! 832: ! 833: ! 834: init_siso(addr); ! 835: src_len = strlen(sx->x25_addr); ! 836: in = sx->x25_addr; ! 837: out = addr->siso_data + 1; ! 838: if (*in == '0' && (src_len & 1 == 0)) { ! 839: pad_tail = 0xf; ! 840: src_len++; ! 841: } ! 842: for (first = 0; src_len > 0; src_len --) { ! 843: first |= *in++; ! 844: if (src_len & 1) { ! 845: *out++ = first; ! 846: first = 0; ! 847: } ! 848: else first <<= 4; ! 849: } ! 850: if (pad_tail) ! 851: out[-1] |= 0xf; ! 852: return 0; /* ok */ ! 853: } ! 854: ! 855: /* ! 856: * FUNCTION and ARGUMENTS: ! 857: * parses (buf_len) bytes beginning at (buf) and finds ! 858: * a called nsap, a calling nsap, and protocol identifier. ! 859: * RETURNS: ! 860: * 0 if ok, E* otherwise. ! 861: */ ! 862: ! 863: static int ! 864: parse_facil(lcp, isop, buf, buf_len) ! 865: caddr_t buf; ! 866: u_char buf_len; /* in bytes */ ! 867: struct isopcb *isop; ! 868: struct pklcd *lcp; ! 869: { ! 870: register struct sockaddr_iso *called = isop->isop_laddr; ! 871: register struct sockaddr_iso *calling = isop->isop_faddr; ! 872: register int i; ! 873: register u_char *ptr = (u_char *)buf; ! 874: u_char *ptr_lim, *facil_lim; ! 875: int facil_param_len, facil_len; ! 876: ! 877: IFDEBUG(D_CADDR) ! 878: printf("parse_facil(0x%x, 0x%x, 0x%x, 0x%x)\n", ! 879: buf, buf_len, called, calling); ! 880: dump_buf(buf, buf_len); ! 881: ENDDEBUG ! 882: ! 883: /* find the beginnings of the facility fields in buf ! 884: * by skipping over the called & calling DTE addresses ! 885: * i <- # nibbles in called + # nibbles in calling ! 886: * i += 1 so that an odd nibble gets rounded up to even ! 887: * before dividing by 2, then divide by two to get # octets ! 888: */ ! 889: i = (int)(*ptr >> 4) + (int)(*ptr&0xf); ! 890: i++; ! 891: ptr += i >> 1; ! 892: ptr ++; /* plus one for the DTE lengths byte */ ! 893: ! 894: /* ptr now is at facil_length field */ ! 895: facil_len = *ptr++; ! 896: facil_lim = ptr + facil_len; ! 897: IFDEBUG(D_CADDR) ! 898: printf("parse_facils: facil length is 0x%x\n", (int) facil_len); ! 899: ENDDEBUG ! 900: ! 901: while (ptr <= facil_lim) { ! 902: /* get NSAP addresses from facilities */ ! 903: switch (*ptr++) { ! 904: case 0xcb: ! 905: /* calling NSAP */ ! 906: facil_param_len = FACILtoNSAP(isop->isop_faddr, ptr); ! 907: break; ! 908: case 0xc9: ! 909: /* called NSAP */ ! 910: facil_param_len = FACILtoNSAP(isop->isop_laddr, ptr); ! 911: break; ! 912: ! 913: /* from here to default are legit cases that I ignore */ ! 914: /* variable length */ ! 915: case 0xca: /* end-to-end transit delay negot */ ! 916: case 0xc6: /* network user id */ ! 917: case 0xc5: /* charging info : indicating monetary unit */ ! 918: case 0xc2: /* charging info : indicating segment count */ ! 919: case 0xc1: /* charging info : indicating call duration */ ! 920: case 0xc4: /* RPOA extended format */ ! 921: case 0xc3: /* call redirection notification */ ! 922: facil_param_len = 0; ! 923: break; ! 924: ! 925: /* 1 octet */ ! 926: case 0x0a: /* min. throughput class negot */ ! 927: case 0x02: /* throughput class */ ! 928: case 0x03: case 0x47: /* CUG shit */ ! 929: case 0x0b: /* expedited data negot */ ! 930: case 0x01: /* Fast select or reverse charging ! 931: (example of intelligent protocol design) */ ! 932: case 0x04: /* charging info : requesting service */ ! 933: case 0x08: /* called line addr modified notification */ ! 934: facil_param_len = 1; ! 935: break; ! 936: ! 937: /* any 2 octets */ ! 938: case 0x42: /* pkt size */ ! 939: case 0x43: /* win size */ ! 940: case 0x44: /* RPOA basic format */ ! 941: case 0x41: /* bilateral CUG shit */ ! 942: case 0x49: /* transit delay selection and indication */ ! 943: facil_param_len = 2; ! 944: break; ! 945: ! 946: /* don't have any 3 octets */ ! 947: /* ! 948: facil_param_len = 3; ! 949: */ ! 950: default: ! 951: printf( ! 952: "BOGUS FACILITY CODE facil_len 0x%x *facil_len 0x%x, ptr 0x%x *ptr 0x%x\n", ! 953: ptr, facil_len, ptr - 1, ptr[-1]); ! 954: /* facil that we don't handle */ ! 955: return E_CO_HLI_REJI; ! 956: } ! 957: if (facil_param_len == -1) ! 958: return E_CO_REG_ICDA; ! 959: if (facil_param_len == 0) /* variable length */ ! 960: facil_param_len = (int)*ptr; /* 1 + the real facil param */ ! 961: ptr += facil_param_len; ! 962: } ! 963: return 0; ! 964: } ! 965: ! 966: #endif TPCONS
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.