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