|
|
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) 1990, 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_x25subr.c 8.1 (Berkeley) 6/10/93 ! 58: */ ! 59: ! 60: #include <sys/param.h> ! 61: #include <sys/systm.h> ! 62: #include <sys/malloc.h> ! 63: #include <sys/mbuf.h> ! 64: #include <sys/protosw.h> ! 65: #include <sys/socket.h> ! 66: #include <sys/socketvar.h> ! 67: #include <sys/ioctl.h> ! 68: #include <sys/errno.h> ! 69: #include <sys/syslog.h> ! 70: ! 71: #include <net/if.h> ! 72: #include <net/if_types.h> ! 73: #include <net/netisr.h> ! 74: #include <net/route.h> ! 75: ! 76: #include <netccitt/x25.h> ! 77: #include <netccitt/x25err.h> ! 78: #include <netccitt/pk.h> ! 79: #include <netccitt/pk_var.h> ! 80: ! 81: #if INET ! 82: #include <netinet/in.h> ! 83: #include <netinet/in_var.h> ! 84: #endif ! 85: ! 86: #if NS ! 87: #include <netns/ns.h> ! 88: #include <netns/ns_if.h> ! 89: #endif ! 90: ! 91: #if ISO ! 92: int tp_incoming(); ! 93: #include <netiso/argo_debug.h> ! 94: #include <netiso/iso.h> ! 95: #include <netiso/iso_var.h> ! 96: #endif ! 97: ! 98: extern struct ifnet loif; ! 99: struct llinfo_x25 llinfo_x25 = {&llinfo_x25, &llinfo_x25}; ! 100: #ifndef _offsetof ! 101: #define _offsetof(t, m) ((int)((caddr_t)&((t *)0)->m)) ! 102: #endif ! 103: struct sockaddr *x25_dgram_sockmask; ! 104: struct sockaddr_x25 x25_dgmask = { ! 105: _offsetof(struct sockaddr_x25, x25_udata[1]), /* _len */ ! 106: 0, /* _family */ ! 107: 0, /* _net */ ! 108: { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* _addr */ ! 109: {0}, /* opts */ ! 110: -1, /* _udlen */ ! 111: {-1} /* _udata */ ! 112: }; ! 113: ! 114: struct if_x25stats { ! 115: int ifx_wrongplen; ! 116: int ifx_nophdr; ! 117: } if_x25stats; ! 118: int x25_autoconnect = 0; ! 119: ! 120: #define senderr(x) {error = x; goto bad;} ! 121: /* ! 122: * Ancillary routines ! 123: */ ! 124: static struct llinfo_x25 * ! 125: x25_lxalloc(rt) ! 126: register struct rtentry *rt; ! 127: { ! 128: register struct llinfo_x25 *lx; ! 129: register struct sockaddr *dst = rt_key(rt); ! 130: register struct ifaddr *ifa; ! 131: ! 132: MALLOC(lx, struct llinfo_x25 *, sizeof (*lx), M_PCB, M_NOWAIT); ! 133: if (lx == 0) ! 134: return lx; ! 135: Bzero(lx, sizeof(*lx)); ! 136: lx->lx_rt = rt; ! 137: lx->lx_family = dst->sa_family; ! 138: rt->rt_refcnt++; ! 139: if (rt->rt_llinfo) ! 140: insque(lx, (struct llinfo_x25 *)rt->rt_llinfo); ! 141: else { ! 142: rt->rt_llinfo = (caddr_t)lx; ! 143: insque(lx, &llinfo_x25); ! 144: } ! 145: for (ifa = rt->rt_ifp->if_addrlist; ifa; ifa = ifa->ifa_next) { ! 146: if (ifa->ifa_addr->sa_family == AF_CCITT) ! 147: lx->lx_ia = (struct x25_ifaddr *)ifa; ! 148: } ! 149: return lx; ! 150: } ! 151: x25_lxfree(lx) ! 152: register struct llinfo_x25 *lx; ! 153: { ! 154: register struct rtentry *rt = lx->lx_rt; ! 155: register struct pklcd *lcp = lx->lx_lcd; ! 156: ! 157: if (lcp) { ! 158: lcp->lcd_upper = 0; ! 159: pk_disconnect(lcp); ! 160: } ! 161: if ((rt->rt_llinfo == (caddr_t)lx) && (lx->lx_next->lx_rt == rt)) ! 162: rt->rt_llinfo = (caddr_t)lx->lx_next; ! 163: else ! 164: rt->rt_llinfo = 0; ! 165: RTFREE(rt); ! 166: remque(lx); ! 167: FREE(lx, M_PCB); ! 168: } ! 169: /* ! 170: * Process a x25 packet as datagram; ! 171: */ ! 172: x25_ifinput(lcp, m) ! 173: struct pklcd *lcp; ! 174: register struct mbuf *m; ! 175: { ! 176: struct llinfo_x25 *lx = (struct llinfo_x25 *)lcp->lcd_upnext; ! 177: register struct ifnet *ifp; ! 178: struct ifqueue *inq; ! 179: extern struct timeval time; ! 180: int s, len, isr; ! 181: ! 182: if (m == 0 || lcp->lcd_state != DATA_TRANSFER) { ! 183: x25_connect_callback(lcp, 0); ! 184: return; ! 185: } ! 186: pk_flowcontrol(lcp, 0, 1); /* Generate RR */ ! 187: ifp = m->m_pkthdr.rcvif; ! 188: ifp->if_lastchange = time; ! 189: switch (m->m_type) { ! 190: default: ! 191: if (m) ! 192: m_freem(m); ! 193: return; ! 194: ! 195: case MT_DATA: ! 196: /* FALLTHROUGH */; ! 197: } ! 198: switch (lx->lx_family) { ! 199: #if INET ! 200: case AF_INET: ! 201: isr = NETISR_IP; ! 202: inq = &ipintrq; ! 203: break; ! 204: ! 205: #endif ! 206: #if NS ! 207: case AF_NS: ! 208: isr = NETISR_NS; ! 209: inq = &nsintrq; ! 210: break; ! 211: ! 212: #endif ! 213: #if ISO ! 214: case AF_ISO: ! 215: isr = NETISR_ISO; ! 216: inq = &clnlintrq; ! 217: break; ! 218: #endif ! 219: default: ! 220: m_freem(m); ! 221: ifp->if_noproto++; ! 222: return; ! 223: } ! 224: s = splimp(); ! 225: schednetisr(isr); ! 226: if (IF_QFULL(inq)) { ! 227: IF_DROP(inq); ! 228: m_freem(m); ! 229: } else { ! 230: IF_ENQUEUE(inq, m); ! 231: ifp->if_ibytes += m->m_pkthdr.len; ! 232: } ! 233: splx(s); ! 234: } ! 235: x25_connect_callback(lcp, m) ! 236: register struct pklcd *lcp; ! 237: register struct mbuf *m; ! 238: { ! 239: register struct llinfo_x25 *lx = (struct llinfo_x25 *)lcp->lcd_upnext; ! 240: int do_clear = 1; ! 241: if (m == 0) ! 242: goto refused; ! 243: if (m->m_type != MT_CONTROL) { ! 244: printf("x25_connect_callback: should panic\n"); ! 245: goto refused; ! 246: } ! 247: switch (pk_decode(mtod(m, struct x25_packet *))) { ! 248: case CALL_ACCEPTED: ! 249: lcp->lcd_upper = x25_ifinput; ! 250: if (lcp->lcd_sb.sb_mb) ! 251: lcp->lcd_send(lcp); /* XXX start queued packets */ ! 252: return; ! 253: default: ! 254: do_clear = 0; ! 255: refused: ! 256: lcp->lcd_upper = 0; ! 257: lx->lx_lcd = 0; ! 258: if (do_clear) ! 259: pk_disconnect(lcp); ! 260: return; ! 261: } ! 262: } ! 263: #define SA(p) ((struct sockaddr *)(p)) ! 264: #define RT(p) ((struct rtentry *)(p)) ! 265: ! 266: x25_dgram_incoming(lcp, m0) ! 267: register struct pklcd *lcp; ! 268: struct mbuf *m0; ! 269: { ! 270: register struct rtentry *rt, *nrt; ! 271: register struct mbuf *m = m0->m_next; /* m0 has calling sockaddr_x25 */ ! 272: void x25_rtrequest(); ! 273: ! 274: rt = rtalloc1(SA(&lcp->lcd_faddr), 0); ! 275: if (rt == 0) { ! 276: refuse: lcp->lcd_upper = 0; ! 277: pk_close(lcp); ! 278: return; ! 279: } ! 280: rt->rt_refcnt--; ! 281: if ((nrt = RT(rt->rt_llinfo)) == 0 || rt_mask(rt) != x25_dgram_sockmask) ! 282: goto refuse; ! 283: if ((nrt->rt_flags & RTF_UP) == 0) { ! 284: rt->rt_llinfo = (caddr_t)rtalloc1(rt->rt_gateway, 0); ! 285: rtfree(nrt); ! 286: if ((nrt = RT(rt->rt_llinfo)) == 0) ! 287: goto refuse; ! 288: nrt->rt_refcnt--; ! 289: } ! 290: if (nrt->rt_ifa == 0 || nrt->rt_ifa->ifa_rtrequest != x25_rtrequest) ! 291: goto refuse; ! 292: lcp->lcd_send(lcp); /* confirm call */ ! 293: x25_rtattach(lcp, nrt); ! 294: m_freem(m); ! 295: } ! 296: ! 297: /* ! 298: * X.25 output routine. ! 299: */ ! 300: x25_ifoutput(ifp, m0, dst, rt) ! 301: struct ifnet *ifp; ! 302: struct mbuf *m0; ! 303: struct sockaddr *dst; ! 304: register struct rtentry *rt; ! 305: { ! 306: register struct mbuf *m = m0; ! 307: register struct llinfo_x25 *lx; ! 308: struct pklcd *lcp; ! 309: int s, error = 0; ! 310: ! 311: int plen; ! 312: for (plen = 0; m; m = m->m_next) ! 313: plen += m->m_len; ! 314: m = m0; ! 315: ! 316: if ((ifp->if_flags & IFF_UP) == 0) ! 317: senderr(ENETDOWN); ! 318: while (rt == 0 || (rt->rt_flags & RTF_GATEWAY)) { ! 319: if (rt) { ! 320: if (rt->rt_llinfo) { ! 321: rt = (struct rtentry *)rt->rt_llinfo; ! 322: continue; ! 323: } ! 324: dst = rt->rt_gateway; ! 325: } ! 326: if ((rt = rtalloc1(dst, 1)) == 0) ! 327: senderr(EHOSTUNREACH); ! 328: rt->rt_refcnt--; ! 329: } ! 330: /* ! 331: * Sanity checks. ! 332: */ ! 333: if ((rt->rt_ifp != ifp) || ! 334: (rt->rt_flags & (RTF_CLONING | RTF_GATEWAY)) || ! 335: ((lx = (struct llinfo_x25 *)rt->rt_llinfo) == 0)) { ! 336: senderr(ENETUNREACH); ! 337: } ! 338: if ((m->m_flags & M_PKTHDR) == 0) { ! 339: if_x25stats.ifx_nophdr++; ! 340: m = m_gethdr(M_NOWAIT, MT_HEADER); ! 341: if (m == 0) ! 342: senderr(ENOBUFS); ! 343: m->m_pkthdr.len = plen; ! 344: m->m_next = m0; ! 345: } ! 346: if (plen != m->m_pkthdr.len) { ! 347: if_x25stats.ifx_wrongplen++; ! 348: m->m_pkthdr.len = plen; ! 349: } ! 350: next_circuit: ! 351: lcp = lx->lx_lcd; ! 352: if (lcp == 0) { ! 353: lx->lx_lcd = lcp = pk_attach((struct socket *)0); ! 354: if (lcp == 0) ! 355: senderr(ENOBUFS); ! 356: lcp->lcd_upper = x25_connect_callback; ! 357: lcp->lcd_upnext = (caddr_t)lx; ! 358: lcp->lcd_packetsize = lx->lx_ia->ia_xc.xc_psize; ! 359: lcp->lcd_flags = X25_MBS_HOLD; ! 360: } ! 361: switch (lcp->lcd_state) { ! 362: case READY: ! 363: if (dst->sa_family == AF_INET && ! 364: ifp->if_type == IFT_X25DDN && ! 365: rt->rt_gateway->sa_family != AF_CCITT) ! 366: x25_ddnip_to_ccitt(dst, rt); ! 367: if (rt->rt_gateway->sa_family != AF_CCITT) { ! 368: if ((rt->rt_flags & RTF_XRESOLVE) == 0) ! 369: senderr(EHOSTUNREACH); ! 370: } else if (x25_autoconnect) ! 371: error = pk_connect(lcp, ! 372: (struct sockaddr_x25 *)rt->rt_gateway); ! 373: if (error) ! 374: senderr(error); ! 375: /* FALLTHROUGH */ ! 376: case SENT_CALL: ! 377: case DATA_TRANSFER: ! 378: if (sbspace(&lcp->lcd_sb) < 0) { ! 379: lx = lx->lx_next; ! 380: if (lx->lx_rt != rt) ! 381: senderr(ENOSPC); ! 382: goto next_circuit; ! 383: } ! 384: if (lx->lx_ia) ! 385: lcp->lcd_dg_timer = ! 386: lx->lx_ia->ia_xc.xc_dg_idletimo; ! 387: pk_send(lcp, m); ! 388: break; ! 389: default: ! 390: /* ! 391: * We count on the timer routine to close idle ! 392: * connections, if there are not enough circuits to go ! 393: * around. ! 394: * ! 395: * So throw away data for now. ! 396: * After we get it all working, we'll rewrite to handle ! 397: * actively closing connections (other than by timers), ! 398: * when circuits get tight. ! 399: * ! 400: * In the DDN case, the imp itself closes connections ! 401: * under heavy load. ! 402: */ ! 403: error = ENOBUFS; ! 404: bad: ! 405: if (m) ! 406: m_freem(m); ! 407: } ! 408: return (error); ! 409: } ! 410: ! 411: /* ! 412: * Simpleminded timer routine. ! 413: */ ! 414: x25_iftimeout(ifp) ! 415: struct ifnet *ifp; ! 416: { ! 417: register struct pkcb *pkcb = 0; ! 418: register struct pklcd **lcpp, *lcp; ! 419: int s = splimp(); ! 420: ! 421: FOR_ALL_PKCBS(pkcb) ! 422: if (pkcb->pk_ia->ia_ifp == ifp) ! 423: for (lcpp = pkcb->pk_chan + pkcb->pk_maxlcn; ! 424: --lcpp > pkcb->pk_chan;) ! 425: if ((lcp = *lcpp) && ! 426: lcp->lcd_state == DATA_TRANSFER && ! 427: (lcp->lcd_flags & X25_DG_CIRCUIT) && ! 428: (lcp->lcd_dg_timer && --lcp->lcd_dg_timer == 0)) { ! 429: lcp->lcd_upper(lcp, 0); ! 430: } ! 431: splx(s); ! 432: } ! 433: /* ! 434: * This routine gets called when validating additions of new routes ! 435: * or deletions of old ones. ! 436: */ ! 437: x25_rtrequest(cmd, rt, dst) ! 438: register struct rtentry *rt; ! 439: struct sockaddr *dst; ! 440: { ! 441: register struct llinfo_x25 *lx = (struct llinfo_x25 *)rt->rt_llinfo; ! 442: register struct sockaddr_x25 *sa =(struct sockaddr_x25 *)rt->rt_gateway; ! 443: register struct pklcd *lcp; ! 444: ! 445: /* would put this pk_init, except routing table doesn't ! 446: exist yet. */ ! 447: if (x25_dgram_sockmask == 0) { ! 448: struct radix_node *rn_addmask(); ! 449: x25_dgram_sockmask = ! 450: SA(rn_addmask((caddr_t)&x25_dgmask, 0, 4)->rn_key); ! 451: } ! 452: if (rt->rt_flags & RTF_GATEWAY) { ! 453: if (rt->rt_llinfo) ! 454: RTFREE((struct rtentry *)rt->rt_llinfo); ! 455: rt->rt_llinfo = (cmd == RTM_ADD) ? ! 456: (caddr_t)rtalloc1(rt->rt_gateway, 1) : 0; ! 457: return; ! 458: } ! 459: if ((rt->rt_flags & RTF_HOST) == 0) ! 460: return; ! 461: if (cmd == RTM_DELETE) { ! 462: while (rt->rt_llinfo) ! 463: x25_lxfree((struct llinfo *)rt->rt_llinfo); ! 464: x25_rtinvert(RTM_DELETE, rt->rt_gateway, rt); ! 465: return; ! 466: } ! 467: if (lx == 0 && (lx = x25_lxalloc(rt)) == 0) ! 468: return; ! 469: if ((lcp = lx->lx_lcd) && lcp->lcd_state != READY) { ! 470: /* ! 471: * This can only happen on a RTM_CHANGE operation ! 472: * though cmd will be RTM_ADD. ! 473: */ ! 474: if (lcp->lcd_ceaddr && ! 475: Bcmp(rt->rt_gateway, lcp->lcd_ceaddr, ! 476: lcp->lcd_ceaddr->x25_len) != 0) { ! 477: x25_rtinvert(RTM_DELETE, lcp->lcd_ceaddr, rt); ! 478: lcp->lcd_upper = 0; ! 479: pk_disconnect(lcp); ! 480: } ! 481: lcp = 0; ! 482: } ! 483: x25_rtinvert(RTM_ADD, rt->rt_gateway, rt); ! 484: } ! 485: ! 486: int x25_dont_rtinvert = 0; ! 487: ! 488: x25_rtinvert(cmd, sa, rt) ! 489: register struct sockaddr *sa; ! 490: register struct rtentry *rt; ! 491: { ! 492: struct rtentry *rt2 = 0; ! 493: /* ! 494: * rt_gateway contains PID indicating which proto ! 495: * family on the other end, so will be different ! 496: * from general host route via X.25. ! 497: */ ! 498: if (rt->rt_ifp->if_type == IFT_X25DDN || x25_dont_rtinvert) ! 499: return; ! 500: if (sa->sa_family != AF_CCITT) ! 501: return; ! 502: if (cmd != RTM_DELETE) { ! 503: rtrequest(RTM_ADD, sa, rt_key(rt), x25_dgram_sockmask, ! 504: RTF_PROTO2, &rt2); ! 505: if (rt2) { ! 506: rt2->rt_llinfo = (caddr_t) rt; ! 507: rt->rt_refcnt++; ! 508: } ! 509: return; ! 510: } ! 511: rt2 = rt; ! 512: if ((rt = rtalloc1(sa, 0)) == 0 || ! 513: (rt->rt_flags & RTF_PROTO2) == 0 || ! 514: rt->rt_llinfo != (caddr_t)rt2) { ! 515: printf("x25_rtchange: inverse route screwup\n"); ! 516: return; ! 517: } else ! 518: rt2->rt_refcnt--; ! 519: rtrequest(RTM_DELETE, sa, rt_key(rt2), x25_dgram_sockmask, ! 520: 0, (struct rtentry **) 0); ! 521: } ! 522: ! 523: static struct sockaddr_x25 blank_x25 = {sizeof blank_x25, AF_CCITT}; ! 524: /* ! 525: * IP to X25 address routine copyright ACC, used by permission. ! 526: */ ! 527: union imp_addr { ! 528: struct in_addr ip; ! 529: struct imp { ! 530: u_char s_net; ! 531: u_char s_host; ! 532: u_char s_lh; ! 533: u_char s_impno; ! 534: } imp; ! 535: }; ! 536: ! 537: /* ! 538: * The following is totally bogus and here only to preserve ! 539: * the IP to X.25 translation. ! 540: */ ! 541: x25_ddnip_to_ccitt(src, rt) ! 542: struct sockaddr_in *src; ! 543: register struct rtentry *rt; ! 544: { ! 545: register struct sockaddr_x25 *dst = (struct sockaddr_x25 *)rt->rt_gateway; ! 546: union imp_addr imp_addr; ! 547: int imp_no, imp_port, temp; ! 548: char *x25addr = dst->x25_addr; ! 549: ! 550: ! 551: imp_addr.ip = src->sin_addr; ! 552: *dst = blank_x25; ! 553: if ((imp_addr.imp.s_net & 0x80) == 0x00) { /* class A */ ! 554: imp_no = imp_addr.imp.s_impno; ! 555: imp_port = imp_addr.imp.s_host; ! 556: } else if ((imp_addr.imp.s_net & 0xc0) == 0x80) { /* class B */ ! 557: imp_no = imp_addr.imp.s_impno; ! 558: imp_port = imp_addr.imp.s_lh; ! 559: } else { /* class C */ ! 560: imp_no = imp_addr.imp.s_impno / 32; ! 561: imp_port = imp_addr.imp.s_impno % 32; ! 562: } ! 563: ! 564: x25addr[0] = 12; /* length */ ! 565: /* DNIC is cleared by struct copy above */ ! 566: ! 567: if (imp_port < 64) { /* Physical: 0000 0 IIIHH00 [SS] *//* s_impno ! 568: * -> III, s_host -> HH */ ! 569: x25addr[5] = 0; /* set flag bit */ ! 570: x25addr[6] = imp_no / 100; ! 571: x25addr[7] = (imp_no % 100) / 10; ! 572: x25addr[8] = imp_no % 10; ! 573: x25addr[9] = imp_port / 10; ! 574: x25addr[10] = imp_port % 10; ! 575: } else { /* Logical: 0000 1 RRRRR00 [SS] *//* s ! 576: * _host * 256 + s_impno -> RRRRR */ ! 577: temp = (imp_port << 8) + imp_no; ! 578: x25addr[5] = 1; ! 579: x25addr[6] = temp / 10000; ! 580: x25addr[7] = (temp % 10000) / 1000; ! 581: x25addr[8] = (temp % 1000) / 100; ! 582: x25addr[9] = (temp % 100) / 10; ! 583: x25addr[10] = temp % 10; ! 584: } ! 585: } ! 586: ! 587: /* ! 588: * This routine is a sketch and is not to be believed!!!!! ! 589: * ! 590: * This is a utility routine to be called by x25 devices when a ! 591: * call request is honored with the intent of starting datagram forwarding. ! 592: */ ! 593: x25_dg_rtinit(dst, ia, af) ! 594: struct sockaddr_x25 *dst; ! 595: register struct x25_ifaddr *ia; ! 596: { ! 597: struct sockaddr *sa = 0; ! 598: struct rtentry *rt; ! 599: struct in_addr my_addr; ! 600: static struct sockaddr_in sin = {sizeof(sin), AF_INET}; ! 601: ! 602: if (ia->ia_ifp->if_type == IFT_X25DDN && af == AF_INET) { ! 603: /* ! 604: * Inverse X25 to IP mapping copyright and courtesy ACC. ! 605: */ ! 606: int imp_no, imp_port, temp; ! 607: union imp_addr imp_addr; ! 608: { ! 609: /* ! 610: * First determine our IP addr for network ! 611: */ ! 612: register struct in_ifaddr *ina; ! 613: extern struct in_ifaddr *in_ifaddr; ! 614: ! 615: for (ina = in_ifaddr; ina; ina = ina->ia_next) ! 616: if (ina->ia_ifp == ia->ia_ifp) { ! 617: my_addr = ina->ia_addr.sin_addr; ! 618: break; ! 619: } ! 620: } ! 621: { ! 622: ! 623: register char *x25addr = dst->x25_addr; ! 624: ! 625: switch (x25addr[5] & 0x0f) { ! 626: case 0: /* Physical: 0000 0 IIIHH00 [SS] */ ! 627: imp_no = ! 628: ((int) (x25addr[6] & 0x0f) * 100) + ! 629: ((int) (x25addr[7] & 0x0f) * 10) + ! 630: ((int) (x25addr[8] & 0x0f)); ! 631: ! 632: ! 633: imp_port = ! 634: ((int) (x25addr[9] & 0x0f) * 10) + ! 635: ((int) (x25addr[10] & 0x0f)); ! 636: break; ! 637: case 1: /* Logical: 0000 1 RRRRR00 [SS] */ ! 638: temp = ((int) (x25addr[6] & 0x0f) * 10000) ! 639: + ((int) (x25addr[7] & 0x0f) * 1000) ! 640: + ((int) (x25addr[8] & 0x0f) * 100) ! 641: + ((int) (x25addr[9] & 0x0f) * 10) ! 642: + ((int) (x25addr[10] & 0x0f)); ! 643: ! 644: imp_port = temp >> 8; ! 645: imp_no = temp & 0xff; ! 646: break; ! 647: default: ! 648: return (0L); ! 649: } ! 650: imp_addr.ip = my_addr; ! 651: if ((imp_addr.imp.s_net & 0x80) == 0x00) { ! 652: /* class A */ ! 653: imp_addr.imp.s_host = imp_port; ! 654: imp_addr.imp.s_impno = imp_no; ! 655: imp_addr.imp.s_lh = 0; ! 656: } else if ((imp_addr.imp.s_net & 0xc0) == 0x80) { ! 657: /* class B */ ! 658: imp_addr.imp.s_lh = imp_port; ! 659: imp_addr.imp.s_impno = imp_no; ! 660: } else { ! 661: /* class C */ ! 662: imp_addr.imp.s_impno = (imp_no << 5) + imp_port; ! 663: } ! 664: } ! 665: sin.sin_addr = imp_addr.ip; ! 666: sa = (struct sockaddr *)&sin; ! 667: } else { ! 668: /* ! 669: * This uses the X25 routing table to do inverse ! 670: * lookup of x25 address to sockaddr. ! 671: */ ! 672: if (rt = rtalloc1(SA(dst), 0)) { ! 673: sa = rt->rt_gateway; ! 674: rt->rt_refcnt--; ! 675: } ! 676: } ! 677: /* ! 678: * Call to rtalloc1 will create rtentry for reverse path ! 679: * to callee by virtue of cloning magic and will allocate ! 680: * space for local control block. ! 681: */ ! 682: if (sa && (rt = rtalloc1(sa, 1))) ! 683: rt->rt_refcnt--; ! 684: } ! 685: int x25_startproto = 1; ! 686: ! 687: pk_init() ! 688: { ! 689: /* ! 690: * warning, sizeof (struct sockaddr_x25) > 32, ! 691: * but contains no data of interest beyond 32 ! 692: */ ! 693: if (x25_startproto) { ! 694: pk_protolisten(0xcc, 1, x25_dgram_incoming); ! 695: pk_protolisten(0x81, 1, x25_dgram_incoming); ! 696: } ! 697: } ! 698: ! 699: struct x25_dgproto { ! 700: u_char spi; ! 701: u_char spilen; ! 702: int (*f)(); ! 703: } x25_dgprototab[] = { ! 704: #if (ISO) && (TPCONS) ! 705: { 0x0, 0, tp_incoming}, ! 706: #endif ! 707: { 0xcc, 1, x25_dgram_incoming}, ! 708: { 0xcd, 1, x25_dgram_incoming}, ! 709: { 0x81, 1, x25_dgram_incoming}, ! 710: }; ! 711: ! 712: pk_user_protolisten(info) ! 713: register u_char *info; ! 714: { ! 715: register struct x25_dgproto *dp = x25_dgprototab ! 716: + ((sizeof x25_dgprototab) / (sizeof *dp)); ! 717: register struct pklcd *lcp; ! 718: ! 719: while (dp > x25_dgprototab) ! 720: if ((--dp)->spi == info[0]) ! 721: goto gotspi; ! 722: return ESRCH; ! 723: ! 724: gotspi: if (info[1]) ! 725: return pk_protolisten(dp->spi, dp->spilen, dp->f); ! 726: for (lcp = pk_listenhead; lcp; lcp = lcp->lcd_listen) ! 727: if (lcp->lcd_laddr.x25_udlen == dp->spilen && ! 728: Bcmp(&dp->spi, lcp->lcd_laddr.x25_udata, dp->spilen) == 0) { ! 729: pk_disconnect(lcp); ! 730: return 0; ! 731: } ! 732: return ESRCH; ! 733: } ! 734: ! 735: /* ! 736: * This routine transfers an X.25 circuit to or from a routing entry. ! 737: * If the supplied circuit is * in DATA_TRANSFER state, it is added to the ! 738: * routing entry. If freshly allocated, it glues back the vc from ! 739: * the rtentry to the socket. ! 740: */ ! 741: pk_rtattach(so, m0) ! 742: register struct socket *so; ! 743: struct mbuf *m0; ! 744: { ! 745: register struct pklcd *lcp = (struct pklcd *)so->so_pcb; ! 746: register struct mbuf *m = m0; ! 747: struct sockaddr *dst = mtod(m, struct sockaddr *); ! 748: register struct rtentry *rt = rtalloc1(dst, 0); ! 749: register struct llinfo_x25 *lx; ! 750: caddr_t cp; ! 751: #define ROUNDUP(a) \ ! 752: ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long)) ! 753: #define transfer_sockbuf(s, f, l) \ ! 754: while (m = (s)->sb_mb)\ ! 755: {(s)->sb_mb = m->m_act; m->m_act = 0; sbfree((s), m); f(l, m);} ! 756: ! 757: if (rt) ! 758: rt->rt_refcnt--; ! 759: cp = (dst->sa_len < m->m_len) ? ROUNDUP(dst->sa_len) + (caddr_t)dst : 0; ! 760: while (rt && ! 761: ((cp == 0 && rt_mask(rt) != 0) || ! 762: (cp != 0 && (rt_mask(rt) == 0 || ! 763: Bcmp(cp, rt_mask(rt), rt_mask(rt)->sa_len)) != 0))) ! 764: rt = (struct rtentry *)rt->rt_nodes->rn_dupedkey; ! 765: if (rt == 0 || (rt->rt_flags & RTF_GATEWAY) || ! 766: (lx = (struct llinfo_x25 *)rt->rt_llinfo) == 0) ! 767: return ESRCH; ! 768: if (lcp == 0) ! 769: return ENOTCONN; ! 770: switch (lcp->lcd_state) { ! 771: default: ! 772: return ENOTCONN; ! 773: ! 774: case READY: ! 775: /* Detach VC from rtentry */ ! 776: if (lx->lx_lcd == 0) ! 777: return ENOTCONN; ! 778: lcp->lcd_so = 0; ! 779: pk_close(lcp); ! 780: lcp = lx->lx_lcd; ! 781: if (lx->lx_next->lx_rt == rt) ! 782: x25_lxfree(lx); ! 783: lcp->lcd_so = so; ! 784: lcp->lcd_upper = 0; ! 785: lcp->lcd_upnext = 0; ! 786: transfer_sockbuf(&lcp->lcd_sb, sbappendrecord, &so->so_snd); ! 787: soisconnected(so); ! 788: return 0; ! 789: ! 790: case DATA_TRANSFER: ! 791: /* Add VC to rtentry */ ! 792: lcp->lcd_so = 0; ! 793: lcp->lcd_sb = so->so_snd; /* structure copy */ ! 794: bzero((caddr_t)&so->so_snd, sizeof(so->so_snd)); /* XXXXXX */ ! 795: so->so_pcb = 0; ! 796: x25_rtattach(lcp, rt); ! 797: transfer_sockbuf(&so->so_rcv, x25_ifinput, lcp); ! 798: soisdisconnected(so); ! 799: } ! 800: return 0; ! 801: } ! 802: x25_rtattach(lcp0, rt) ! 803: register struct pklcd *lcp0; ! 804: struct rtentry *rt; ! 805: { ! 806: register struct llinfo_x25 *lx = (struct llinfo_x25 *)rt->rt_llinfo; ! 807: register struct pklcd *lcp; ! 808: register struct mbuf *m; ! 809: if (lcp = lx->lx_lcd) { /* adding an additional VC */ ! 810: if (lcp->lcd_state == READY) { ! 811: transfer_sockbuf(&lcp->lcd_sb, pk_output, lcp0); ! 812: lcp->lcd_upper = 0; ! 813: pk_close(lcp); ! 814: } else { ! 815: lx = x25_lxalloc(rt); ! 816: if (lx == 0) ! 817: return ENOBUFS; ! 818: } ! 819: } ! 820: lx->lx_lcd = lcp = lcp0; ! 821: lcp->lcd_upper = x25_ifinput; ! 822: lcp->lcd_upnext = (caddr_t)lx; ! 823: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.