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