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