|
|
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) University of British Columbia, 1984 ! 24: * Copyright (C) Computer Science Department IV, ! 25: * University of Erlangen-Nuremberg, Germany, 1992 ! 26: * Copyright (c) 1991, 1992, 1993 ! 27: * The Regents of the University of California. All rights reserved. ! 28: * ! 29: * This code is derived from software contributed to Berkeley by the ! 30: * Laboratory for Computation Vision and the Computer Science Department ! 31: * of the the University of British Columbia and the Computer Science ! 32: * Department (IV) of the University of Erlangen-Nuremberg, Germany. ! 33: * ! 34: * Redistribution and use in source and binary forms, with or without ! 35: * modification, are permitted provided that the following conditions ! 36: * are met: ! 37: * 1. Redistributions of source code must retain the above copyright ! 38: * notice, this list of conditions and the following disclaimer. ! 39: * 2. Redistributions in binary form must reproduce the above copyright ! 40: * notice, this list of conditions and the following disclaimer in the ! 41: * documentation and/or other materials provided with the distribution. ! 42: * 3. All advertising materials mentioning features or use of this software ! 43: * must display the following acknowledgement: ! 44: * This product includes software developed by the University of ! 45: * California, Berkeley and its contributors. ! 46: * 4. Neither the name of the University nor the names of its contributors ! 47: * may be used to endorse or promote products derived from this software ! 48: * without specific prior written permission. ! 49: * ! 50: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ! 51: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ! 52: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ! 53: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE ! 54: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ! 55: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ! 56: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ! 57: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ! 58: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ! 59: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ! 60: * SUCH DAMAGE. ! 61: * ! 62: * @(#)pk_usrreq.c 8.1 (Berkeley) 6/10/93 ! 63: */ ! 64: ! 65: #include <sys/param.h> ! 66: #include <sys/systm.h> ! 67: #include <sys/mbuf.h> ! 68: #include <sys/socket.h> ! 69: #include <sys/socketvar.h> ! 70: #include <sys/protosw.h> ! 71: #include <sys/errno.h> ! 72: #include <sys/ioctl.h> ! 73: #include <sys/stat.h> ! 74: #include <sys/malloc.h> ! 75: ! 76: #include <net/if.h> ! 77: #include <net/if_types.h> ! 78: #include <net/route.h> ! 79: ! 80: #include <netccitt/x25.h> ! 81: #include <netccitt/pk.h> ! 82: #include <netccitt/pk_var.h> ! 83: ! 84: static old_to_new(); ! 85: static new_to_old(); ! 86: /* ! 87: * ! 88: * X.25 Packet level protocol interface to socket abstraction. ! 89: * ! 90: * Process an X.25 user request on a logical channel. If this is a send ! 91: * request then m is the mbuf chain of the send data. If this is a timer ! 92: * expiration (called from the software clock routine) them timertype is ! 93: * the particular timer. ! 94: * ! 95: */ ! 96: ! 97: pk_usrreq (so, req, m, nam, control) ! 98: struct socket *so; ! 99: int req; ! 100: register struct mbuf *m, *nam; ! 101: struct mbuf *control; ! 102: { ! 103: register struct pklcd *lcp = (struct pklcd *) so -> so_pcb; ! 104: register int error = 0; ! 105: ! 106: if (req == PRU_CONTROL) ! 107: return (pk_control (so, (int)m, (caddr_t)nam, ! 108: (struct ifnet *)control)); ! 109: if (control && control -> m_len) { ! 110: error = EINVAL; ! 111: goto release; ! 112: } ! 113: if (lcp == NULL && req != PRU_ATTACH) { ! 114: error = EINVAL; ! 115: goto release; ! 116: } ! 117: ! 118: /* ! 119: pk_trace (pkcbhead, TR_USER, (struct pklcd *)0, ! 120: req, (struct x25_packet *)0); ! 121: */ ! 122: ! 123: switch (req) { ! 124: /* ! 125: * X.25 attaches to socket via PRU_ATTACH and allocates a logical ! 126: * channel descriptor. If the socket is to receive connections, ! 127: * then the LISTEN state is entered. ! 128: */ ! 129: case PRU_ATTACH: ! 130: if (lcp) { ! 131: error = EISCONN; ! 132: /* Socket already connected. */ ! 133: break; ! 134: } ! 135: lcp = pk_attach (so); ! 136: if (lcp == 0) ! 137: error = ENOBUFS; ! 138: break; ! 139: ! 140: /* ! 141: * Detach a logical channel from the socket. If the state of the ! 142: * channel is embryonic, simply discard it. Otherwise we have to ! 143: * initiate a PRU_DISCONNECT which will finish later. ! 144: */ ! 145: case PRU_DETACH: ! 146: pk_disconnect (lcp); ! 147: break; ! 148: ! 149: /* ! 150: * Give the socket an address. ! 151: */ ! 152: case PRU_BIND: ! 153: if (nam -> m_len == sizeof (struct x25_sockaddr)) ! 154: old_to_new (nam); ! 155: error = pk_bind (lcp, nam); ! 156: break; ! 157: ! 158: /* ! 159: * Prepare to accept connections. ! 160: */ ! 161: case PRU_LISTEN: ! 162: error = pk_listen (lcp); ! 163: break; ! 164: ! 165: /* ! 166: * Initiate a CALL REQUEST to peer entity. Enter state SENT_CALL ! 167: * and mark the socket as connecting. Set timer waiting for ! 168: * CALL ACCEPT or CLEAR. ! 169: */ ! 170: case PRU_CONNECT: ! 171: if (nam -> m_len == sizeof (struct x25_sockaddr)) ! 172: old_to_new (nam); ! 173: if (pk_checksockaddr (nam)) ! 174: return (EINVAL); ! 175: error = pk_connect (lcp, mtod (nam, struct sockaddr_x25 *)); ! 176: break; ! 177: ! 178: /* ! 179: * Initiate a disconnect to peer entity via a CLEAR REQUEST packet. ! 180: * The socket will be disconnected when we receive a confirmation ! 181: * or a clear collision. ! 182: */ ! 183: case PRU_DISCONNECT: ! 184: pk_disconnect (lcp); ! 185: break; ! 186: ! 187: /* ! 188: * Accept an INCOMING CALL. Most of the work has already been done ! 189: * by pk_input. Just return the callers address to the user. ! 190: */ ! 191: case PRU_ACCEPT: ! 192: if (lcp -> lcd_craddr == NULL) ! 193: break; ! 194: bcopy ((caddr_t)lcp -> lcd_craddr, mtod (nam, caddr_t), ! 195: sizeof (struct sockaddr_x25)); ! 196: nam -> m_len = sizeof (struct sockaddr_x25); ! 197: if (lcp -> lcd_flags & X25_OLDSOCKADDR) ! 198: new_to_old (nam); ! 199: break; ! 200: ! 201: /* ! 202: * After a receive, we should send a RR. ! 203: */ ! 204: case PRU_RCVD: ! 205: pk_flowcontrol (lcp, /*sbspace (&so -> so_rcv) <= */ 0, 1); ! 206: break; ! 207: ! 208: /* ! 209: * Send INTERRUPT packet. ! 210: */ ! 211: case PRU_SENDOOB: ! 212: if (m == 0) { ! 213: MGETHDR(m, M_WAITOK, MT_OOBDATA); ! 214: m -> m_pkthdr.len = m -> m_len = 1; ! 215: *mtod (m, octet *) = 0; ! 216: } ! 217: if (m -> m_pkthdr.len > 32) { ! 218: m_freem (m); ! 219: error = EMSGSIZE; ! 220: break; ! 221: } ! 222: MCHTYPE(m, MT_OOBDATA); ! 223: /* FALLTHROUGH */ ! 224: ! 225: /* ! 226: * Do send by placing data on the socket output queue. ! 227: */ ! 228: case PRU_SEND: ! 229: if (control) { ! 230: register struct cmsghdr *ch = mtod (m, struct cmsghdr *); ! 231: control -> m_len -= sizeof (*ch); ! 232: control -> m_data += sizeof (*ch); ! 233: error = pk_ctloutput (PRCO_SETOPT, so, ch -> cmsg_level, ! 234: ch -> cmsg_type, &control); ! 235: } ! 236: if (error == 0 && m) ! 237: error = pk_send (lcp, m); ! 238: break; ! 239: ! 240: /* ! 241: * Abort a virtual circuit. For example all completed calls ! 242: * waiting acceptance. ! 243: */ ! 244: case PRU_ABORT: ! 245: pk_disconnect (lcp); ! 246: break; ! 247: ! 248: /* Begin unimplemented hooks. */ ! 249: ! 250: case PRU_SHUTDOWN: ! 251: error = EOPNOTSUPP; ! 252: break; ! 253: ! 254: case PRU_CONTROL: ! 255: error = EOPNOTSUPP; ! 256: break; ! 257: ! 258: case PRU_SENSE: ! 259: #ifdef BSD4_3 ! 260: ((struct stat *)m) -> st_blksize = so -> so_snd.sb_hiwat; ! 261: #else ! 262: error = EOPNOTSUPP; ! 263: #endif ! 264: break; ! 265: ! 266: /* End unimplemented hooks. */ ! 267: ! 268: case PRU_SOCKADDR: ! 269: if (lcp -> lcd_ceaddr == 0) ! 270: return (EADDRNOTAVAIL); ! 271: nam -> m_len = sizeof (struct sockaddr_x25); ! 272: bcopy ((caddr_t)lcp -> lcd_ceaddr, mtod (nam, caddr_t), ! 273: sizeof (struct sockaddr_x25)); ! 274: if (lcp -> lcd_flags & X25_OLDSOCKADDR) ! 275: new_to_old (nam); ! 276: break; ! 277: ! 278: case PRU_PEERADDR: ! 279: if (lcp -> lcd_state != DATA_TRANSFER) ! 280: return (ENOTCONN); ! 281: nam -> m_len = sizeof (struct sockaddr_x25); ! 282: bcopy (lcp -> lcd_craddr ? (caddr_t)lcp -> lcd_craddr : ! 283: (caddr_t)lcp -> lcd_ceaddr, ! 284: mtod (nam, caddr_t), sizeof (struct sockaddr_x25)); ! 285: if (lcp -> lcd_flags & X25_OLDSOCKADDR) ! 286: new_to_old (nam); ! 287: break; ! 288: ! 289: /* ! 290: * Receive INTERRUPT packet. ! 291: */ ! 292: case PRU_RCVOOB: ! 293: if (so -> so_options & SO_OOBINLINE) { ! 294: register struct mbuf *n = so -> so_rcv.sb_mb; ! 295: if (n && n -> m_type == MT_OOBDATA) { ! 296: unsigned len = n -> m_pkthdr.len; ! 297: so -> so_rcv.sb_mb = n -> m_nextpkt; ! 298: if (len != n -> m_len && ! 299: (n = m_pullup (n, len)) == 0) ! 300: break; ! 301: m -> m_len = len; ! 302: bcopy (mtod (m, caddr_t), mtod (n, caddr_t), len); ! 303: m_freem (n); ! 304: } ! 305: break; ! 306: } ! 307: m -> m_len = 1; ! 308: *mtod (m, char *) = lcp -> lcd_intrdata; ! 309: break; ! 310: ! 311: default: ! 312: panic ("pk_usrreq"); ! 313: } ! 314: release: ! 315: if (control != NULL) ! 316: m_freem (control); ! 317: return (error); ! 318: } ! 319: ! 320: /* ! 321: * If you want to use UBC X.25 level 3 in conjunction with some ! 322: * other X.25 level 2 driver, have the ifp -> if_ioctl routine ! 323: * assign pk_start to ia -> ia_start when called with SIOCSIFCONF_X25. ! 324: */ ! 325: /* ARGSUSED */ ! 326: pk_start (lcp) ! 327: register struct pklcd *lcp; ! 328: { ! 329: pk_output (lcp); ! 330: return (0); /* XXX pk_output should return a value */ ! 331: } ! 332: ! 333: #ifndef _offsetof ! 334: #define _offsetof(t, m) ((int)((caddr_t)&((t *)0)->m)) ! 335: #endif ! 336: struct sockaddr_x25 pk_sockmask = { ! 337: _offsetof(struct sockaddr_x25, x25_addr[0]), /* x25_len */ ! 338: 0, /* x25_family */ ! 339: -1, /* x25_net id */ ! 340: }; ! 341: ! 342: /*ARGSUSED*/ ! 343: pk_control (so, cmd, data, ifp) ! 344: struct socket *so; ! 345: int cmd; ! 346: caddr_t data; ! 347: register struct ifnet *ifp; ! 348: { ! 349: register struct ifreq_x25 *ifr = (struct ifreq_x25 *)data; ! 350: register struct ifaddr *ifa = 0; ! 351: register struct x25_ifaddr *ia = 0; ! 352: struct pklcd *dev_lcp = 0; ! 353: int error, s, old_maxlcn; ! 354: unsigned n; ! 355: ! 356: /* ! 357: * Find address for this interface, if it exists. ! 358: */ ! 359: if (ifp) ! 360: for (ifa = ifp -> if_addrlist; ifa; ifa = ifa -> ifa_next) ! 361: if (ifa -> ifa_addr -> sa_family == AF_CCITT) ! 362: break; ! 363: ! 364: ia = (struct x25_ifaddr *)ifa; ! 365: switch (cmd) { ! 366: case SIOCGIFCONF_X25: ! 367: if (ifa == 0) ! 368: return (EADDRNOTAVAIL); ! 369: ifr -> ifr_xc = ia -> ia_xc; ! 370: return (0); ! 371: ! 372: case SIOCSIFCONF_X25: ! 373: if ((so->so_state & SS_PRIV) == 0) ! 374: return (EPERM); ! 375: if (ifp == 0) ! 376: panic ("pk_control"); ! 377: if (ifa == (struct ifaddr *)0) { ! 378: register struct mbuf *m; ! 379: ! 380: MALLOC(ia, struct x25_ifaddr *, sizeof (*ia), ! 381: M_IFADDR, M_WAITOK); ! 382: if (ia == 0) ! 383: return (ENOBUFS); ! 384: bzero ((caddr_t)ia, sizeof (*ia)); ! 385: if (ifa = ifp -> if_addrlist) { ! 386: for ( ; ifa -> ifa_next; ifa = ifa -> ifa_next) ! 387: ; ! 388: ifa -> ifa_next = &ia -> ia_ifa; ! 389: } else ! 390: ifp -> if_addrlist = &ia -> ia_ifa; ! 391: ifa = &ia -> ia_ifa; ! 392: ifa -> ifa_netmask = (struct sockaddr *)&pk_sockmask; ! 393: ifa -> ifa_addr = (struct sockaddr *)&ia -> ia_xc.xc_addr; ! 394: ifa -> ifa_dstaddr = (struct sockaddr *)&ia -> ia_dstaddr; /* XXX */ ! 395: ia -> ia_ifp = ifp; ! 396: ia -> ia_dstaddr.x25_family = AF_CCITT; ! 397: ia -> ia_dstaddr.x25_len = pk_sockmask.x25_len; ! 398: } else if (ISISO8802(ifp) == 0) { ! 399: rtinit (ifa, (int)RTM_DELETE, 0); ! 400: } ! 401: old_maxlcn = ia -> ia_maxlcn; ! 402: ia -> ia_xc = ifr -> ifr_xc; ! 403: ia -> ia_dstaddr.x25_net = ia -> ia_xc.xc_addr.x25_net; ! 404: if (ia -> ia_maxlcn != old_maxlcn && old_maxlcn != 0) { ! 405: /* VERY messy XXX */ ! 406: register struct pkcb *pkp; ! 407: FOR_ALL_PKCBS(pkp) ! 408: if (pkp -> pk_ia == ia) ! 409: pk_resize (pkp); ! 410: } ! 411: /* ! 412: * Give the interface a chance to initialize if this ! 413: p * is its first address, and to validate the address. ! 414: */ ! 415: ia -> ia_start = pk_start; ! 416: s = splimp(); ! 417: if (ifp -> if_ioctl) ! 418: error = (*ifp -> if_ioctl)(ifp, SIOCSIFCONF_X25, ! 419: (caddr_t) ifa); ! 420: if (error) ! 421: ifp -> if_flags &= ~IFF_UP; ! 422: else if (ISISO8802(ifp) == 0) ! 423: error = rtinit (ifa, (int)RTM_ADD, RTF_UP); ! 424: splx (s); ! 425: return (error); ! 426: ! 427: default: ! 428: if (ifp == 0 || ifp -> if_ioctl == 0) ! 429: return (EOPNOTSUPP); ! 430: return ((*ifp -> if_ioctl)(ifp, cmd, data)); ! 431: } ! 432: } ! 433: ! 434: pk_ctloutput (cmd, so, level, optname, mp) ! 435: struct socket *so; ! 436: struct mbuf **mp; ! 437: int cmd, level, optname; ! 438: { ! 439: register struct mbuf *m = *mp; ! 440: register struct pklcd *lcp = (struct pklcd *) so -> so_pcb; ! 441: int error = EOPNOTSUPP; ! 442: ! 443: if (m == 0) ! 444: return (EINVAL); ! 445: if (cmd == PRCO_SETOPT) switch (optname) { ! 446: case PK_FACILITIES: ! 447: if (m == 0) ! 448: return (EINVAL); ! 449: lcp -> lcd_facilities = m; ! 450: *mp = 0; ! 451: return (0); ! 452: ! 453: case PK_ACCTFILE: ! 454: if ((so->so_state & SS_PRIV) == 0) ! 455: error = EPERM; ! 456: else if (m -> m_len) ! 457: error = pk_accton (mtod (m, char *)); ! 458: else ! 459: error = pk_accton ((char *)0); ! 460: break; ! 461: ! 462: case PK_RTATTACH: ! 463: error = pk_rtattach (so, m); ! 464: break; ! 465: ! 466: case PK_PRLISTEN: ! 467: error = pk_user_protolisten (mtod (m, u_char *)); ! 468: } ! 469: if (*mp) { ! 470: (void) m_freem (*mp); ! 471: *mp = 0; ! 472: } ! 473: return (error); ! 474: ! 475: } ! 476: ! 477: ! 478: /* ! 479: * Do an in-place conversion of an "old style" ! 480: * socket address to the new style ! 481: */ ! 482: ! 483: static ! 484: old_to_new (m) ! 485: register struct mbuf *m; ! 486: { ! 487: register struct x25_sockaddr *oldp; ! 488: register struct sockaddr_x25 *newp; ! 489: register char *ocp, *ncp; ! 490: struct sockaddr_x25 new; ! 491: ! 492: oldp = mtod (m, struct x25_sockaddr *); ! 493: newp = &new; ! 494: bzero ((caddr_t)newp, sizeof (*newp)); ! 495: ! 496: newp -> x25_family = AF_CCITT; ! 497: newp -> x25_len = sizeof(*newp); ! 498: newp -> x25_opts.op_flags = (oldp -> xaddr_facilities & X25_REVERSE_CHARGE) ! 499: | X25_MQBIT | X25_OLDSOCKADDR; ! 500: if (oldp -> xaddr_facilities & XS_HIPRIO) /* Datapac specific */ ! 501: newp -> x25_opts.op_psize = X25_PS128; ! 502: bcopy ((caddr_t)oldp -> xaddr_addr, newp -> x25_addr, ! 503: (unsigned)min (oldp -> xaddr_len, sizeof (newp -> x25_addr) - 1)); ! 504: if (bcmp ((caddr_t)oldp -> xaddr_proto, newp -> x25_udata, 4) != 0) { ! 505: bcopy ((caddr_t)oldp -> xaddr_proto, newp -> x25_udata, 4); ! 506: newp -> x25_udlen = 4; ! 507: } ! 508: ocp = (caddr_t)oldp -> xaddr_userdata; ! 509: ncp = newp -> x25_udata + 4; ! 510: while (*ocp && ocp < (caddr_t)oldp -> xaddr_userdata + 12) { ! 511: if (newp -> x25_udlen == 0) ! 512: newp -> x25_udlen = 4; ! 513: *ncp++ = *ocp++; ! 514: newp -> x25_udlen++; ! 515: } ! 516: bcopy ((caddr_t)newp, mtod (m, char *), sizeof (*newp)); ! 517: m -> m_len = sizeof (*newp); ! 518: } ! 519: ! 520: /* ! 521: * Do an in-place conversion of a new style ! 522: * socket address to the old style ! 523: */ ! 524: ! 525: static ! 526: new_to_old (m) ! 527: register struct mbuf *m; ! 528: { ! 529: register struct x25_sockaddr *oldp; ! 530: register struct sockaddr_x25 *newp; ! 531: register char *ocp, *ncp; ! 532: struct x25_sockaddr old; ! 533: ! 534: oldp = &old; ! 535: newp = mtod (m, struct sockaddr_x25 *); ! 536: bzero ((caddr_t)oldp, sizeof (*oldp)); ! 537: ! 538: oldp -> xaddr_facilities = newp -> x25_opts.op_flags & X25_REVERSE_CHARGE; ! 539: if (newp -> x25_opts.op_psize == X25_PS128) ! 540: oldp -> xaddr_facilities |= XS_HIPRIO; /* Datapac specific */ ! 541: ocp = (char *)oldp -> xaddr_addr; ! 542: ncp = newp -> x25_addr; ! 543: while (*ncp) { ! 544: *ocp++ = *ncp++; ! 545: oldp -> xaddr_len++; ! 546: } ! 547: ! 548: bcopy (newp -> x25_udata, (caddr_t)oldp -> xaddr_proto, 4); ! 549: if (newp -> x25_udlen > 4) ! 550: bcopy (newp -> x25_udata + 4, (caddr_t)oldp -> xaddr_userdata, ! 551: (unsigned)(newp -> x25_udlen - 4)); ! 552: ! 553: bcopy ((caddr_t)oldp, mtod (m, char *), sizeof (*oldp)); ! 554: m -> m_len = sizeof (*oldp); ! 555: } ! 556: ! 557: ! 558: pk_checksockaddr (m) ! 559: struct mbuf *m; ! 560: { ! 561: register struct sockaddr_x25 *sa = mtod (m, struct sockaddr_x25 *); ! 562: register char *cp; ! 563: ! 564: if (m -> m_len != sizeof (struct sockaddr_x25)) ! 565: return (1); ! 566: if (sa -> x25_family != AF_CCITT || ! 567: sa -> x25_udlen > sizeof (sa -> x25_udata)) ! 568: return (1); ! 569: for (cp = sa -> x25_addr; *cp; cp++) { ! 570: if (*cp < '0' || *cp > '9' || ! 571: cp >= &sa -> x25_addr[sizeof (sa -> x25_addr) - 1]) ! 572: return (1); ! 573: } ! 574: return (0); ! 575: } ! 576: ! 577: pk_send (lcp, m) ! 578: struct pklcd *lcp; ! 579: register struct mbuf *m; ! 580: { ! 581: int mqbit = 0, error = 0; ! 582: register struct x25_packet *xp; ! 583: register struct socket *so; ! 584: ! 585: if (m -> m_type == MT_OOBDATA) { ! 586: if (lcp -> lcd_intrconf_pending) ! 587: error = ETOOMANYREFS; ! 588: if (m -> m_pkthdr.len > 32) ! 589: error = EMSGSIZE; ! 590: M_PREPEND(m, PKHEADERLN, M_WAITOK); ! 591: if (m == 0 || error) ! 592: goto bad; ! 593: *(mtod (m, octet *)) = 0; ! 594: xp = mtod (m, struct x25_packet *); ! 595: X25SBITS(xp -> bits, fmt_identifier, 1); ! 596: xp -> packet_type = X25_INTERRUPT; ! 597: SET_LCN(xp, lcp -> lcd_lcn); ! 598: sbinsertoob ( (so = lcp -> lcd_so) ? ! 599: &so -> so_snd : &lcp -> lcd_sb, m); ! 600: goto send; ! 601: } ! 602: /* ! 603: * Application has elected (at call setup time) to prepend ! 604: * a control byte to each packet written indicating m-bit ! 605: * and q-bit status. Examine and then discard this byte. ! 606: */ ! 607: if (lcp -> lcd_flags & X25_MQBIT) { ! 608: if (m -> m_len < 1) { ! 609: m_freem (m); ! 610: return (EMSGSIZE); ! 611: } ! 612: mqbit = *(mtod (m, u_char *)); ! 613: m -> m_len--; ! 614: m -> m_data++; ! 615: m -> m_pkthdr.len--; ! 616: } ! 617: error = pk_fragment (lcp, m, mqbit & 0x80, mqbit & 0x40, 1); ! 618: send: ! 619: if (error == 0 && lcp -> lcd_state == DATA_TRANSFER) ! 620: lcp -> lcd_send (lcp); /* XXXXXXXXX fix pk_output!!! */ ! 621: return (error); ! 622: bad: ! 623: if (m) ! 624: m_freem (m); ! 625: return (error); ! 626: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.