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