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