|
|
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) 1995 Apple Computer, Inc. ! 24: * ! 25: * Change Log: ! 26: * Created, March 17, 1997 by Tuyen Nguyen for MacOSX. ! 27: */ ! 28: ! 29: #include <sys/errno.h> ! 30: #include <sys/types.h> ! 31: #include <sys/param.h> ! 32: #include <machine/spl.h> ! 33: #include <sys/systm.h> ! 34: #include <sys/kernel.h> ! 35: #include <sys/proc.h> ! 36: #include <sys/filedesc.h> ! 37: #include <sys/fcntl.h> ! 38: #include <sys/mbuf.h> ! 39: #include <sys/ioctl.h> ! 40: #include <sys/malloc.h> ! 41: #include <sys/socket.h> ! 42: #include <sys/socketvar.h> ! 43: #include <sys/ioccom.h> ! 44: ! 45: #include <sys/sysctl.h> ! 46: ! 47: #include <net/if.h> ! 48: ! 49: #include <netat/sysglue.h> ! 50: #include <netat/appletalk.h> ! 51: #include <netat/ddp.h> ! 52: #include <netat/at_pcb.h> ! 53: #include <netat/at_var.h> ! 54: #include <netat/routing_tables.h> ! 55: #include <netat/debug.h> ! 56: ! 57: extern struct atpcb ddp_head; ! 58: ! 59: extern void ! 60: ddp_putmsg(gref_t *gref, gbuf_t *m), ! 61: elap_wput(gref_t *gref, gbuf_t *m), ! 62: atp_wput(gref_t *gref, gbuf_t *m), ! 63: asp_wput(gref_t *gref, gbuf_t *m), ! 64: #ifdef AURP_SUPPORT ! 65: aurp_wput(gref_t *gref, gbuf_t *m), ! 66: #endif ! 67: adsp_wput(gref_t *gref, gbuf_t *m); ! 68: ! 69: void atalk_putnext(gref_t *gref, gbuf_t *m); ! 70: static int gref_close(gref_t *gref); ! 71: ! 72: SYSCTL_DECL(_net_appletalk); ! 73: dbgBits_t dbgBits; ! 74: SYSCTL_STRUCT(_net_appletalk, OID_AUTO, debug, CTLFLAG_WR, ! 75: &dbgBits, dbgBits, "Appletalk Debug Flags"); ! 76: volatile int RouterMix = RT_MIX_DEFAULT; /* default for nbr of ppsec */ ! 77: SYSCTL_INT(_net_appletalk, OID_AUTO, routermix, CTLFLAG_WR, ! 78: &RouterMix, 0, "Appletalk RouterMix"); ! 79: ! 80: atlock_t refall_lock; ! 81: ! 82: static void gref_wput(gref, m) ! 83: gref_t *gref; ! 84: gbuf_t *m; ! 85: { ! 86: switch (gref->proto) { ! 87: case ATPROTO_DDP: ! 88: ddp_putmsg(gref, m); break; ! 89: case ATPROTO_LAP: ! 90: elap_wput(gref, m); break; ! 91: case ATPROTO_ATP: ! 92: atp_wput(gref, m); break; ! 93: case ATPROTO_ASP: ! 94: asp_wput(gref, m); break; ! 95: #ifdef AURP_SUPPORT ! 96: case ATPROTO_AURP: ! 97: aurp_wput(gref, m); break; ! 98: #endif ! 99: case ATPROTO_ADSP: ! 100: adsp_wput(gref, m); break; ! 101: case ATPROTO_NONE: ! 102: if (gbuf_type(m) == MSG_IOCTL) { ! 103: gbuf_freem(gbuf_cont(m)); ! 104: gbuf_cont(m) = 0; ! 105: ((ioc_t *)gbuf_rptr(m))->ioc_rval = -1; ! 106: ((ioc_t *)gbuf_rptr(m))->ioc_error = EPROTO; ! 107: gbuf_set_type(m, MSG_IOCNAK); ! 108: atalk_putnext(gref, m); ! 109: } else ! 110: gbuf_freem(m); ! 111: break; ! 112: default: ! 113: gbuf_freem(m); ! 114: break; ! 115: } ! 116: } ! 117: ! 118: int _ATsocket(proto, err, proc) ! 119: int proto; ! 120: int *err; ! 121: void *proc; ! 122: { ! 123: int fd; ! 124: gref_t *gref; ! 125: ! 126: /* make sure the specified protocol id is valid */ ! 127: switch (proto) { ! 128: ! 129: /* ATPROTO_DDP and ATPROTO_LAP have been replaced with ! 130: BSD-style socket interface. */ ! 131: ! 132: case ATPROTO_ATP: ! 133: case ATPROTO_ASP: ! 134: case ATPROTO_AURP: ! 135: case ATPROTO_ADSP: ! 136: break; ! 137: default: ! 138: *err = EPROTOTYPE; ! 139: #ifdef APPLETALK_DEBUG ! 140: kprintf("_ATsocket: error EPROTOTYPE =%d\n", *err); ! 141: #endif ! 142: return -1; ! 143: } ! 144: ! 145: /* allocate a protocol channel */ ! 146: if ((*err = gref_alloc(&gref)) != 0) { ! 147: #ifdef APPLETALK_DEBUG ! 148: kprintf("_ATsocket: error gref_open =%d\n", *err); ! 149: #endif ! 150: return -1; ! 151: } ! 152: gref->proto = proto; ! 153: gref->pid = ((struct proc *)proc)->p_pid; ! 154: ! 155: /* open the specified protocol */ ! 156: switch (gref->proto) { ! 157: ! 158: /* ATPROTO_DDP and ATPROTO_LAP have been replaced with ! 159: BSD-style socket interface. */ ! 160: ! 161: case ATPROTO_ATP: ! 162: *err = atp_open(gref, 1); break; ! 163: case ATPROTO_ASP: ! 164: *err = asp_open(gref); break; ! 165: #ifdef AURP_SUPPORT ! 166: case ATPROTO_AURP: ! 167: *err = aurp_open(gref); break; ! 168: #endif ! 169: case ATPROTO_ADSP: ! 170: *err = adsp_open(gref); break; ! 171: } ! 172: ! 173: /* create the descriptor for the channel */ ! 174: if (*err) { ! 175: #ifdef APPLETALK_DEBUG ! 176: kprintf("_ATsocket: open failed for %d proto; err = %d\n", ! 177: gref->proto, *err); ! 178: #endif ! 179: gref->proto = ATPROTO_NONE; ! 180: } ! 181: if (*err || (*err = atalk_openref(gref, &fd, proc))) { ! 182: #ifdef APPLETALK_DEBUG ! 183: kprintf("_ATsocket: error atalk_openref =%d\n", *err); ! 184: #endif ! 185: (void)gref_close(gref); ! 186: return -1; ! 187: } ! 188: /* ! 189: kprintf("_ATsocket: proto=%d return=%d fd=%d\n", proto, *err, fd); ! 190: */ ! 191: return fd; ! 192: } /* _ATsocket */ ! 193: ! 194: int _ATgetmsg(fd, ctlptr, datptr, flags, err, proc) ! 195: int fd; ! 196: strbuf_t *ctlptr; ! 197: strbuf_t *datptr; ! 198: int *flags; ! 199: int *err; ! 200: void *proc; ! 201: { ! 202: int rc = -1; ! 203: gref_t *gref; ! 204: ! 205: if ((*err = atalk_getref(0, fd, &gref, proc)) == 0) { ! 206: switch (gref->proto) { ! 207: case ATPROTO_ASP: ! 208: rc = ASPgetmsg(gref, ctlptr, datptr, flags, err); break; ! 209: case ATPROTO_AURP: ! 210: #ifdef AURP_SUPPORT ! 211: rc = AURPgetmsg(err); break; ! 212: #endif ! 213: default: ! 214: *err = EPROTONOSUPPORT; break; ! 215: } ! 216: } ! 217: ! 218: ! 219: /* kprintf("_ATgetmsg: return=%d\n", *err);*/ ! 220: return rc; ! 221: } ! 222: ! 223: int _ATputmsg(fd, ctlptr, datptr, flags, err, proc) ! 224: int fd; ! 225: strbuf_t *ctlptr; ! 226: strbuf_t *datptr; ! 227: int flags; ! 228: int *err; ! 229: void *proc; ! 230: { ! 231: int rc = -1; ! 232: gref_t *gref; ! 233: ! 234: if ((*err = atalk_getref(0, fd, &gref, proc)) == 0) { ! 235: switch (gref->proto) { ! 236: case ATPROTO_ASP: ! 237: rc = ASPputmsg(gref, ctlptr, datptr, flags, err); break; ! 238: default: ! 239: *err = EPROTONOSUPPORT; break; ! 240: } ! 241: } ! 242: ! 243: /* kprintf("_ATputmsg: return=%d\n", *err); */ ! 244: return rc; ! 245: } ! 246: ! 247: int _ATclose(fp, proc) ! 248: void *fp; ! 249: void *proc; ! 250: { ! 251: int err; ! 252: gref_t *gref; ! 253: ! 254: if ((err = atalk_closeref(fp, &gref)) != 0) ! 255: return err; ! 256: ! 257: (void)gref_close(gref); ! 258: return 0; ! 259: } ! 260: ! 261: int _ATrw(fp, rw, uio, ext) ! 262: void *fp; ! 263: enum uio_rw rw; ! 264: struct uio *uio; ! 265: int ext; ! 266: { ! 267: int s, err, len, clen = 0, res; ! 268: gref_t *gref; ! 269: gbuf_t *m, *mhead, *mprev; ! 270: ! 271: if ((err = atalk_getref(fp, 0, &gref, 0)) != 0) ! 272: return err; ! 273: ! 274: if ((len = uio->uio_resid) == 0) ! 275: return 0; ! 276: ! 277: ATDISABLE(s, gref->lock); ! 278: if (gref->errno) { ! 279: ATENABLE(s, gref->lock); ! 280: return (int)gref->errno; ! 281: } ! 282: ! 283: if (rw == UIO_READ) { ! 284: KERNEL_DEBUG(DBG_ADSP_ATRW, 0, gref, len, gref->rdhead, 0); ! 285: while ((gref->errno == 0) && ((mhead = gref->rdhead) == 0)) { ! 286: gref->sevents |= POLLMSG; ! 287: err = tsleep(&gref->event, PSOCK | PCATCH, "AT read", 0); ! 288: gref->sevents &= ~POLLMSG; ! 289: if (err != 0) { ! 290: ATENABLE(s, gref->lock); ! 291: return err; ! 292: } ! 293: KERNEL_DEBUG(DBG_ADSP_ATRW, 1, gref, gref->rdhead, mhead, gbuf_next(mhead)); ! 294: } ! 295: ! 296: if (gref->errno) { ! 297: ATENABLE(s, gref->lock); ! 298: return EPIPE; ! 299: } ! 300: if ((gref->rdhead = gbuf_next(mhead)) == 0) ! 301: gref->rdtail = 0; ! 302: ! 303: KERNEL_DEBUG(DBG_ADSP_ATRW, 2, gref, gref->rdhead, mhead, gbuf_next(mhead)); ! 304: ! 305: ATENABLE(s, gref->lock); ! 306: ! 307: //##### LD TEST 08/05 ! 308: // simple_lock(&gref->lock); ! 309: ! 310: gbuf_next(mhead) = 0; ! 311: ! 312: for (mprev=0, m=mhead; m && len; len-=clen) { ! 313: if ((clen = gbuf_len(m)) > 0) { ! 314: if (clen > len) ! 315: clen = len; ! 316: uio->uio_rw = UIO_READ; ! 317: if ((res = uiomove((caddr_t)gbuf_rptr(m), ! 318: clen, uio))) { ! 319: KERNEL_DEBUG(DBG_ADSP_ATRW, 3, m, clen, ! 320: len, gbuf_cont(m)); ! 321: break; ! 322: } ! 323: if (gbuf_len(m) > len) { ! 324: gbuf_rinc(m,clen); ! 325: break; ! 326: } ! 327: } ! 328: mprev = m; ! 329: m = gbuf_cont(m); ! 330: } ! 331: if (m) { ! 332: KERNEL_DEBUG(DBG_ADSP_ATRW, 4, m, gbuf_len(m), mprev, gref->rdhead); ! 333: if (mprev) ! 334: gbuf_cont(mprev) = 0; ! 335: else ! 336: mhead = 0; ! 337: ATDISABLE(s, gref->lock); ! 338: if (gref->rdhead == 0) ! 339: gref->rdtail = m; ! 340: gbuf_next(m) = gref->rdhead; ! 341: gref->rdhead = m; ! 342: ATENABLE(s, gref->lock); ! 343: } ! 344: if (mhead) ! 345: gbuf_freem(mhead); ! 346: //### LD TEST ! 347: // simple_unlock(&gref->lock); ! 348: } else { ! 349: if (gref->writeable) { ! 350: while (!(*gref->writeable)(gref)) { ! 351: /* flow control on, wait to be enabled to write */ ! 352: gref->sevents |= POLLSYNC; ! 353: err = tsleep(&gref->event, PSOCK | PCATCH, "AT write", 0); ! 354: gref->sevents &= ~POLLSYNC; ! 355: if (err != 0) { ! 356: ATENABLE(s, gref->lock); ! 357: return err; ! 358: } ! 359: } ! 360: } ! 361: ! 362: ATENABLE(s, gref->lock); ! 363: ! 364: /* allocate a buffer to copy in the write data */ ! 365: if ((m = gbuf_alloc(AT_WR_OFFSET+len, PRI_MED)) == 0) ! 366: return ENOBUFS; ! 367: gbuf_rinc(m,AT_WR_OFFSET); ! 368: gbuf_wset(m,len); ! 369: ! 370: /* copy in the write data */ ! 371: uio->uio_rw = UIO_WRITE; ! 372: if ((res = uiomove((caddr_t)gbuf_rptr(m), len, uio))) { ! 373: #ifdef APPLETALK_DEBUG ! 374: kprintf("_ATrw: UIO_WRITE: res=%d\n", res); ! 375: #endif ! 376: gbuf_freeb(m); ! 377: return EIO; ! 378: } ! 379: ! 380: /* forward the write data to the appropriate protocol module */ ! 381: gref_wput(gref, m); ! 382: } ! 383: ! 384: return 0; ! 385: } /* _ATrw */ ! 386: ! 387: int _ATread(fp, uio, cred) ! 388: void *fp; ! 389: struct uio *uio; ! 390: void *cred; ! 391: { ! 392: return _ATrw(fp, UIO_READ, uio, 0); ! 393: } ! 394: ! 395: int _ATwrite(fp, uio, cred) ! 396: void *fp; ! 397: struct uio *uio; ! 398: void *cred; ! 399: { ! 400: return _ATrw(fp, UIO_WRITE, uio, 0); ! 401: } ! 402: ! 403: /* Most of the processing from _ATioctl, so that it can be called ! 404: from the new select code */ ! 405: int at_ioctl(gref, cmd, arg) ! 406: gref_t *gref; ! 407: register caddr_t arg; ! 408: { ! 409: int s, err = 0, len; ! 410: gbuf_t *m, *mdata; ! 411: ioc_t *ioc; ! 412: ioccmd_t ioccmd; ! 413: ! 414: /* error if not for us */ ! 415: if ((cmd & 0xffff) != 0xff99) ! 416: return EOPNOTSUPP; ! 417: ! 418: /* copy in ioc command info */ ! 419: /* ! 420: kprintf("at_ioctl: arg ioccmd.ic_cmd=%x ic_len=%x gref->lock=%x, gref->event=%x\n", ! 421: ((ioccmd_t *)arg)->ic_cmd, ((ioccmd_t *)arg)->ic_len, ! 422: gref->lock, gref->event); ! 423: */ ! 424: if ((err = copyin((caddr_t)arg, ! 425: (caddr_t)&ioccmd, sizeof(ioccmd_t))) != 0) { ! 426: #ifdef APPLETALK_DEBUG ! 427: kprintf("at_ioctl: err = %d, copyin(%x, %x, %d)\n", err, ! 428: (caddr_t)arg, (caddr_t)&ioccmd, sizeof(ioccmd_t)); ! 429: #endif ! 430: return err; ! 431: } ! 432: ! 433: /* allocate a buffer to create an ioc command */ ! 434: if ((m = gbuf_alloc(sizeof(ioc_t), PRI_HI)) == 0) ! 435: return ENOBUFS; ! 436: gbuf_wset(m,sizeof(ioc_t)); ! 437: gbuf_set_type(m, MSG_IOCTL); ! 438: ! 439: /* create the ioc command */ ! 440: if (ioccmd.ic_len) { ! 441: if ((gbuf_cont(m) = gbuf_alloc(ioccmd.ic_len, PRI_HI)) == 0) { ! 442: gbuf_freem(m); ! 443: #ifdef APPLETALK_DEBUG ! 444: kprintf("at_ioctl: gbuf_alloc err=%d\n",ENOBUFS); ! 445: #endif ! 446: return ENOBUFS; ! 447: } ! 448: gbuf_wset(gbuf_cont(m),ioccmd.ic_len); ! 449: if ((err = copyin((caddr_t)ioccmd.ic_dp, ! 450: (caddr_t)gbuf_rptr(gbuf_cont(m)), ioccmd.ic_len)) != 0) { ! 451: gbuf_freem(m); ! 452: return err; ! 453: } ! 454: } ! 455: ioc = (ioc_t *)gbuf_rptr(m); ! 456: ioc->ioc_cmd = ioccmd.ic_cmd; ! 457: ioc->ioc_count = ioccmd.ic_len; ! 458: ioc->ioc_error = 0; ! 459: ioc->ioc_rval = 0; ! 460: ! 461: /* send the ioc command to the appropriate recipient */ ! 462: gref_wput(gref, m); ! 463: ! 464: /* wait for the ioc ack */ ! 465: ATDISABLE(s, gref->lock); ! 466: while ((m = gref->ichead) == 0) { ! 467: gref->sevents |= POLLPRI; ! 468: #ifdef APPLETALK_DEBUG ! 469: kprintf("sleep gref = 0x%x\n", (unsigned)gref); ! 470: #endif ! 471: err = tsleep(&gref->iocevent, PSOCK | PCATCH, "AT ioctl", 0); ! 472: gref->sevents &= ~POLLPRI; ! 473: if (err != 0) { ! 474: ATENABLE(s, gref->lock); ! 475: #ifdef APPLETALK_DEBUG ! 476: kprintf("at_ioctl: EINTR\n"); ! 477: #endif ! 478: return err; ! 479: } ! 480: } ! 481: ! 482: /* PR-2224797 */ ! 483: if (gbuf_next(m) == m) /* error case */ ! 484: gbuf_next(m) = 0; ! 485: ! 486: gref->ichead = gbuf_next(m); ! 487: ! 488: ATENABLE(s, gref->lock); ! 489: ! 490: #ifdef APPLETALK_DEBUG ! 491: kprintf("at_ioctl: woke up from ioc sleep gref = 0x%x\n", ! 492: (unsigned)gref); ! 493: #endif ! 494: /* process the ioc response */ ! 495: ioc = (ioc_t *)gbuf_rptr(m); ! 496: if ((err = ioc->ioc_error) == 0) { ! 497: ioccmd.ic_timout = ioc->ioc_rval; ! 498: ioccmd.ic_len = 0; ! 499: mdata = gbuf_cont(m); ! 500: if (mdata && ioccmd.ic_dp) { ! 501: ioccmd.ic_len = gbuf_msgsize(mdata); ! 502: for (len=0; mdata; mdata=gbuf_cont(mdata)) { ! 503: if ((err = copyout((caddr_t)gbuf_rptr(mdata), ! 504: (caddr_t)&ioccmd.ic_dp[len], gbuf_len(mdata))) < 0) { ! 505: #ifdef APPLETALK_DEBUG ! 506: kprintf("at_ioctl: len=%d error copyout=%d from=%x to=%x gbuf_len=%x\n", ! 507: len, err, (caddr_t)gbuf_rptr(mdata), ! 508: (caddr_t)&ioccmd.ic_dp[len], gbuf_len(mdata)); ! 509: #endif ! 510: goto l_done; ! 511: } ! 512: len += gbuf_len(mdata); ! 513: } ! 514: } ! 515: if ((err = copyout((caddr_t)&ioccmd, ! 516: (caddr_t)arg, sizeof(ioccmd_t))) != 0) { ! 517: #ifdef APPLETALK_DEBUG ! 518: kprintf("at_ioctl: error copyout2=%d from=%x to=%x len=%d\n", ! 519: err, &ioccmd, arg, sizeof(ioccmd_t)); ! 520: #endif ! 521: goto l_done; ! 522: } ! 523: } ! 524: ! 525: l_done: ! 526: gbuf_freem(m); ! 527: /*kprintf("at_ioctl: I_done=%d\n", err);*/ ! 528: return err; ! 529: } /* at_ioctl */ ! 530: ! 531: int _ATioctl(fp, cmd, arg, proc) ! 532: void *fp; ! 533: u_long cmd; ! 534: register caddr_t arg; ! 535: void *proc; ! 536: { ! 537: int err; ! 538: gref_t *gref; ! 539: ! 540: if ((err = atalk_getref(fp, 0, &gref, 0)) != 0) { ! 541: #ifdef APPLETALK_DEBUG ! 542: kprintf("_ATioctl: atalk_getref err = %d\n", err); ! 543: #endif ! 544: return err; ! 545: } ! 546: ! 547: return((err = at_ioctl(gref, cmd, arg))); ! 548: } ! 549: ! 550: int _ATselect(fp, which, proc) ! 551: void *fp; ! 552: int which; ! 553: void *proc; ! 554: { ! 555: int s, err, rc = 0; ! 556: gref_t *gref; ! 557: ! 558: if ((err = atalk_getref(fp, 0, &gref, 0)) != 0) ! 559: return err; ! 560: ! 561: ATDISABLE(s, gref->lock); ! 562: if (which == FREAD) { ! 563: if (gref->rdhead || (gref->readable && (*gref->readable)(gref))) ! 564: rc = 1; ! 565: else { ! 566: gref->sevents |= POLLIN; ! 567: selrecord(proc, &gref->si); ! 568: } ! 569: } ! 570: ! 571: else if (which == POLLOUT) { ! 572: if (gref->writeable) { ! 573: if ((*gref->writeable)(gref)) ! 574: rc = 1; ! 575: else { ! 576: gref->sevents |= POLLOUT; ! 577: selrecord(proc, &gref->si); ! 578: } ! 579: } else ! 580: rc = 1; ! 581: } ! 582: ATENABLE(s, gref->lock); ! 583: ! 584: return rc; ! 585: } ! 586: ! 587: void atalk_putnext(gref, m) ! 588: gref_t *gref; ! 589: gbuf_t *m; ! 590: { ! 591: int s; ! 592: ! 593: ATDISABLE(s, gref->lock); ! 594: ! 595: /* *** potential leak? *** */ ! 596: gbuf_next(m) = 0; ! 597: ! 598: switch (gbuf_type(m)) { ! 599: case MSG_IOCACK: ! 600: case MSG_IOCNAK: ! 601: if (gref->ichead) ! 602: gbuf_next(gref->ichead) = m; ! 603: else { ! 604: gref->ichead = m; ! 605: if (gref->sevents & POLLPRI) { ! 606: #ifdef APPLETALK_DEBUG ! 607: kprintf("wakeup gref = 0x%x\n", (unsigned)gref); ! 608: #endif ! 609: thread_wakeup(&gref->iocevent); ! 610: } ! 611: } ! 612: break; ! 613: case MSG_ERROR: ! 614: /* *** this processing was moved to atalk_notify *** */ ! 615: panic("atalk_putnext receved MSG_ERROR"); ! 616: break; ! 617: default: ! 618: if (gref->errno) ! 619: gbuf_freem(m); ! 620: else ! 621: if (gref->rdhead) { ! 622: gbuf_next(gref->rdtail) = m; ! 623: gref->rdtail = m; ! 624: } else { ! 625: gref->rdhead = m; ! 626: if (gref->sevents & POLLMSG) { ! 627: gref->sevents &= ~POLLMSG; ! 628: thread_wakeup(&gref->event); ! 629: } ! 630: if (gref->sevents & POLLIN) { ! 631: gref->sevents &= ~POLLIN; ! 632: selwakeup(&gref->si); ! 633: } ! 634: gref->rdtail = m; ! 635: } ! 636: } /* switch gbuf_type(m) */ ! 637: ! 638: ATENABLE(s, gref->lock); ! 639: } /* atalk_putnext */ ! 640: ! 641: void atalk_enablew(gref) ! 642: gref_t *gref; ! 643: { ! 644: if (gref->sevents & POLLSYNC) ! 645: thread_wakeup(&gref->event); ! 646: } ! 647: ! 648: void atalk_flush(gref) ! 649: gref_t *gref; ! 650: { ! 651: int s; ! 652: ! 653: ATDISABLE(s, gref->lock); ! 654: if (gref->rdhead) { ! 655: gbuf_freel(gref->rdhead); ! 656: gref->rdhead = 0; ! 657: } ! 658: if (gref->ichead) { ! 659: gbuf_freel(gref->ichead); ! 660: gref->ichead = 0; ! 661: } ! 662: ATENABLE(s, gref->lock); ! 663: } ! 664: ! 665: /* ! 666: * Notify an appletalk user of an asynchronous error; ! 667: * just wake up so that he can collect error status. ! 668: */ ! 669: /* *** separate out the error wakeup stuff to eliminate use ! 670: of MSG_ERROR and atalk_putnext(), moving towards ! 671: standard socket code ! 672: *** */ ! 673: void atalk_notify(gref, errno) ! 674: register gref_t *gref; ! 675: int errno; ! 676: { ! 677: /* *** code from udp_notify() in netinet/udp_usrreq.c ! 678: inp->inp_socket->so_error = errno; ! 679: sorwakeup(inp->inp_socket); ! 680: sowwakeup(inp->inp_socket); ! 681: *** */ ! 682: ! 683: int s; ! 684: ATDISABLE(s, gref->lock); ! 685: ! 686: if (gref->errno == 0) { ! 687: gref->errno = errno; ! 688: if (gref->rdhead) { ! 689: gbuf_freel(gref->rdhead); ! 690: gref->rdhead = 0; ! 691: } ! 692: if (gref->sevents & POLLMSG) { ! 693: gref->sevents &= ~POLLMSG; ! 694: thread_wakeup(&gref->event); ! 695: } ! 696: if (gref->sevents & POLLIN) { ! 697: gref->sevents &= ~POLLIN; ! 698: selwakeup(&gref->si); ! 699: } ! 700: } ! 701: ATENABLE(s, gref->lock); ! 702: } /* atalk_notify */ ! 703: ! 704: void atalk_notify_sel(gref) ! 705: gref_t *gref; ! 706: { ! 707: int s; ! 708: ! 709: ATDISABLE(s, gref->lock); ! 710: if (gref->sevents & POLLIN) { ! 711: gref->sevents &= ~POLLIN; ! 712: selwakeup(&gref->si); ! 713: } ! 714: ATENABLE(s, gref->lock); ! 715: } ! 716: ! 717: int atalk_peek(gref, event) ! 718: gref_t *gref; ! 719: unsigned char *event; ! 720: { ! 721: int s, rc; ! 722: ! 723: ATDISABLE(s, gref->lock); ! 724: if (gref->rdhead) { ! 725: *event = *gbuf_rptr(gref->rdhead); ! 726: rc = 0; ! 727: } else ! 728: rc = -1; ! 729: ATENABLE(s, gref->lock); ! 730: ! 731: return rc; ! 732: } ! 733: ! 734: static gbuf_t *trace_msg; ! 735: ! 736: void atalk_settrace(str, p1, p2, p3, p4, p5) ! 737: char *str; ! 738: { ! 739: int len; ! 740: gbuf_t *m, *nextm; ! 741: char trace_buf[256]; ! 742: ! 743: sprintf(trace_buf, str, p1, p2, p3, p4, p5); ! 744: len = strlen(trace_buf); ! 745: #ifdef APPLETALK_DEBUG ! 746: kprintf("atalk_settrace: gbufalloc size=%d\n", len+1); ! 747: #endif ! 748: if ((m = gbuf_alloc(len+1, PRI_MED)) == 0) ! 749: return; ! 750: gbuf_wset(m,len); ! 751: strcpy(gbuf_rptr(m), trace_buf); ! 752: if (trace_msg) { ! 753: for (nextm=trace_msg; gbuf_cont(nextm); nextm=gbuf_cont(nextm)) ; ! 754: gbuf_cont(nextm) = m; ! 755: } else ! 756: trace_msg = m; ! 757: } ! 758: ! 759: void atalk_gettrace(m) ! 760: gbuf_t *m; ! 761: { ! 762: if (trace_msg) { ! 763: gbuf_cont(m) = trace_msg; ! 764: trace_msg = 0; ! 765: } ! 766: } ! 767: ! 768: #define GREF_PER_BLK 32 ! 769: static gref_t *gref_free_list = 0; ! 770: ! 771: int gref_alloc(grefp) ! 772: gref_t **grefp; ! 773: { ! 774: extern gbuf_t *atp_resource_m; ! 775: int i, s; ! 776: gbuf_t *m; ! 777: gref_t *gref, *gref_array; ! 778: ! 779: *grefp = (gref_t *)NULL; ! 780: ! 781: ATDISABLE(s, refall_lock); ! 782: if (gref_free_list == 0) { ! 783: ATENABLE(s, refall_lock); ! 784: #ifdef APPLETALK_DEBUG ! 785: kprintf("gref_alloc: gbufalloc size=%d\n", GREF_PER_BLK*sizeof(gref_t)); ! 786: #endif ! 787: if ((m = gbuf_alloc(GREF_PER_BLK*sizeof(gref_t),PRI_HI)) == 0) ! 788: return ENOBUFS; ! 789: bzero(gbuf_rptr(m), GREF_PER_BLK*sizeof(gref_t)); ! 790: gref_array = (gref_t *)gbuf_rptr(m); ! 791: for (i=0; i < GREF_PER_BLK-1; i++) ! 792: gref_array[i].atpcb_next = (gref_t *)&gref_array[i+1]; ! 793: ATDISABLE(s, refall_lock); ! 794: gbuf_cont(m) = atp_resource_m; ! 795: atp_resource_m = m; ! 796: gref_array[i].atpcb_next = gref_free_list; ! 797: gref_free_list = (gref_t *)&gref_array[0]; ! 798: } ! 799: ! 800: gref = gref_free_list; ! 801: gref_free_list = gref->atpcb_next; ! 802: ATENABLE(s, refall_lock); ! 803: ATLOCKINIT(gref->lock); ! 804: //### LD Test 08/05/98 ! 805: // simple_lock_init(&gref->lock); ! 806: ATEVENTINIT(gref->event); ! 807: ATEVENTINIT(gref->iocevent); ! 808: ! 809: /* *** just for now *** */ ! 810: gref->atpcb_socket = (struct socket *)NULL; ! 811: ! 812: *grefp = gref; ! 813: return 0; ! 814: } /* gref_alloc */ ! 815: ! 816: static int gref_close(gref) ! 817: gref_t *gref; ! 818: { ! 819: int s, rc; ! 820: ! 821: switch (gref->proto) { ! 822: ! 823: /* ATPROTO_DDP and ATPROTO_LAP have been replaced with ! 824: BSD-style socket interface. */ ! 825: ! 826: case ATPROTO_ATP: ! 827: rc = atp_close(gref, 1); break; ! 828: case ATPROTO_ASP: ! 829: rc = asp_close(gref); break; ! 830: #ifdef AURP_SUPPORT ! 831: case ATPROTO_AURP: ! 832: rc = aurp_close(gref); break; ! 833: break; ! 834: #endif ! 835: case ATPROTO_ADSP: ! 836: rc = adsp_close(gref); break; ! 837: default: ! 838: rc = 0; ! 839: break; ! 840: } ! 841: ! 842: if (rc == 0) { ! 843: atalk_flush(gref); ! 844: selthreadclear(&gref->si); ! 845: ! 846: /* from original gref_free() */ ! 847: ATDISABLE(s, refall_lock); ! 848: bzero((char *)gref, sizeof(gref_t)); ! 849: gref->atpcb_next = gref_free_list; ! 850: gref_free_list = gref; ! 851: ATENABLE(s, refall_lock); ! 852: } ! 853: ! 854: return rc; ! 855: } ! 856: ! 857: /* ! 858: Buffer Routines ! 859: ! 860: *** Some to be replaced with mbuf routines, some to be re-written ! 861: as mbuf routines (and moved to kern/uicp_mbuf.c or sys/mbuf.h?). ! 862: *** ! 863: ! 864: */ ! 865: ! 866: /* ! 867: * LD 5/12/97 Added for MacOSX, defines a m_clattach function that: ! 868: * "Allocates an mbuf structure and attaches an external cluster." ! 869: */ ! 870: ! 871: struct mbuf *m_clattach(extbuf, extfree, extsize, extarg, wait) ! 872: caddr_t extbuf; ! 873: int (*extfree)(); ! 874: int extsize; ! 875: int extarg; ! 876: int wait; ! 877: { ! 878: struct mbuf *m; ! 879: ! 880: if ((m = m_gethdr(wait, MSG_DATA)) == NULL) ! 881: return (NULL); ! 882: ! 883: m->m_ext.ext_buf = extbuf; ! 884: m->m_ext.ext_free = extfree; ! 885: m->m_ext.ext_size = extsize; ! 886: m->m_ext.ext_arg = extarg; ! 887: m->m_ext.ext_refs.forward = ! 888: m->m_ext.ext_refs.backward = &m->m_ext.ext_refs; ! 889: m->m_data = extbuf; ! 890: m->m_flags |= M_EXT; ! 891: ! 892: return (m); ! 893: } ! 894: ! 895: /* ! 896: Used as the "free" routine for over-size clusters allocated using ! 897: m_lgbuf_alloc(). ! 898: */ ! 899: ! 900: void m_lgbuf_free(buf, size, arg) ! 901: void *buf; ! 902: int size, arg; /* not needed, but they're in m_free() */ ! 903: { ! 904: FREE(buf, M_MCLUST); ! 905: } ! 906: ! 907: /* ! 908: Used to allocate an mbuf when there is the possibility that it may ! 909: need to be larger than the size of a standard cluster. ! 910: */ ! 911: ! 912: struct mbuf *m_lgbuf_alloc(size, wait) ! 913: int size, wait; ! 914: { ! 915: struct mbuf *m; ! 916: ! 917: /* If size is too large, allocate a cluster, otherwise, use the ! 918: standard mbuf allocation routines.*/ ! 919: if (size > MCLBYTES) { ! 920: void *buf; ! 921: if (NULL == ! 922: (buf = (void *)_MALLOC(size, M_MCLUST, ! 923: (wait)? M_WAITOK: M_NOWAIT))) { ! 924: return(NULL); ! 925: } ! 926: if (NULL == ! 927: (m = m_clattach(buf, m_lgbuf_free, size, 0, ! 928: (wait)? M_WAIT: M_DONTWAIT))) { ! 929: m_lgbuf_free(buf); ! 930: return(NULL); ! 931: } ! 932: } else { ! 933: m = m_gethdr(((wait)? M_WAIT: M_DONTWAIT), MSG_DATA); ! 934: if (m && (size > MHLEN)) { ! 935: MCLGET(m, ((wait)? M_WAIT: M_DONTWAIT)); ! 936: if (!(m->m_flags & M_EXT)) { ! 937: (void)m_free(m); ! 938: return(NULL); ! 939: } ! 940: } ! 941: } ! 942: ! 943: return(m); ! 944: } /* m_lgbuf_alloc */ ! 945: ! 946: /* ! 947: gbuf_alloc() is a wrapper for m_lgbuf_alloc(), which is used to ! 948: allocate an mbuf when there is the possibility that it may need ! 949: to be larger than the size of a standard cluster. ! 950: ! 951: gbuf_alloc() sets the mbuf lengths, unlike the standard mbuf routines. ! 952: */ ! 953: ! 954: gbuf_t *gbuf_alloc_wait(size, wait) ! 955: int size, wait; ! 956: { ! 957: gbuf_t *m = (gbuf_t *)m_lgbuf_alloc(size, wait); ! 958: ! 959: /* Standard mbuf allocation routines assume that the caller ! 960: will set the size. */ ! 961: if (m) { ! 962: (struct mbuf *)m->m_pkthdr.len = size; ! 963: (struct mbuf *)m->m_len = size; ! 964: } ! 965: ! 966: return(m); ! 967: } ! 968: ! 969: int gbuf_msgsize(m) ! 970: gbuf_t *m; ! 971: { ! 972: int size; ! 973: ! 974: for (size=0; m; m=gbuf_cont(m)) ! 975: size += gbuf_len(m); ! 976: return size; ! 977: } ! 978: ! 979: int append_copy(m1, m2, wait) ! 980: struct mbuf *m1, *m2; ! 981: int wait; ! 982: { ! 983: if ((!(m1->m_flags & M_EXT)) && (!(m2->m_flags & M_EXT)) && ! 984: (m_trailingspace(m1) >= m2->m_len)) { ! 985: /* splat the data from one into the other */ ! 986: bcopy(mtod(m2, caddr_t), mtod(m1, caddr_t) + m1->m_len, ! 987: (u_int)m2->m_len); ! 988: m1->m_len += m2->m_len; ! 989: if (m1->m_flags & M_PKTHDR) ! 990: m1->m_pkthdr.len += m2->m_len; ! 991: return 1; ! 992: } ! 993: if ((m1->m_next = m_copym(m2, 0, m2->m_len, ! 994: (wait)? M_WAIT: M_DONTWAIT)) == NULL) ! 995: return 0; ! 996: return 1; ! 997: } /* append_copy */ ! 998: ! 999: /* ! 1000: Copy an mbuf chain, referencing existing external storage, if any. ! 1001: Leave space for a header in the new chain, if the space has been ! 1002: left in the origin chain. ! 1003: */ ! 1004: struct mbuf *copy_pkt(mlist, pad) ! 1005: struct mbuf *mlist; /* the mbuf chain to be copied */ ! 1006: int pad; /* hint as to how long the header might be ! 1007: If pad is < 0, leave the same amount of space ! 1008: as there was in the original. */ ! 1009: { ! 1010: struct mbuf *new_m; ! 1011: int len; ! 1012: ! 1013: if (pad < 0) ! 1014: len = m_leadingspace(mlist); ! 1015: else ! 1016: len = min(pad, m_leadingspace(mlist)); ! 1017: ! 1018: /* preserve space for the header at the beginning of the mbuf */ ! 1019: if (len) { ! 1020: mlist->m_data -= (len); ! 1021: mlist->m_len += (len); ! 1022: if (mlist->m_flags & M_PKTHDR) ! 1023: mlist->m_pkthdr.len += (len); ! 1024: new_m = m_copym(mlist, 0, M_COPYALL, M_DONTWAIT); ! 1025: m_adj(mlist, len); ! 1026: m_adj(new_m, len); ! 1027: } else ! 1028: new_m = m_copym(mlist, 0, M_COPYALL, M_DONTWAIT); ! 1029: ! 1030: return(new_m); ! 1031: } ! 1032: ! 1033: void gbuf_linkb(m1, m2) ! 1034: gbuf_t *m1; ! 1035: gbuf_t *m2; ! 1036: { ! 1037: while (gbuf_cont(m1) != 0) ! 1038: m1 = gbuf_cont(m1); ! 1039: gbuf_cont(m1) = m2; ! 1040: } ! 1041: ! 1042: void gbuf_linkpkt(m1, m2) ! 1043: gbuf_t *m1; ! 1044: gbuf_t *m2; ! 1045: { ! 1046: while (gbuf_next(m1) != 0) ! 1047: m1 = gbuf_next(m1); ! 1048: gbuf_next(m1) = m2; ! 1049: } ! 1050: ! 1051: int gbuf_freel(m) ! 1052: gbuf_t *m; ! 1053: { ! 1054: gbuf_t *tmp_m; ! 1055: ! 1056: while ((tmp_m = m) != 0) { ! 1057: m = gbuf_next(m); ! 1058: gbuf_next(tmp_m) = 0; ! 1059: gbuf_freem(tmp_m); ! 1060: } ! 1061: return (0); ! 1062: } ! 1063: ! 1064: /* free empty mbufs at the front of the chain */ ! 1065: gbuf_t *gbuf_strip(m) ! 1066: gbuf_t *m; ! 1067: { ! 1068: gbuf_t *tmp_m; ! 1069: ! 1070: while (m && gbuf_len(m) == 0) { ! 1071: tmp_m = m; ! 1072: m = gbuf_cont(m); ! 1073: gbuf_freeb(tmp_m); ! 1074: } ! 1075: return(m); ! 1076: } ! 1077: ! 1078: /**************************************/ ! 1079: ! 1080: int ddp_adjmsg(m, len) ! 1081: gbuf_t *m; ! 1082: int len; ! 1083: { ! 1084: int buf_len; ! 1085: gbuf_t *curr_m, *prev_m; ! 1086: ! 1087: if (m == (gbuf_t *)0) ! 1088: return 0; ! 1089: ! 1090: if (len > 0) { ! 1091: for (curr_m=m; curr_m;) { ! 1092: buf_len = gbuf_len(curr_m); ! 1093: if (len < buf_len) { ! 1094: gbuf_rinc(curr_m,len); ! 1095: return 1; ! 1096: } ! 1097: len -= buf_len; ! 1098: gbuf_rinc(curr_m,buf_len); ! 1099: if ((curr_m = gbuf_cont(curr_m)) == 0) { ! 1100: gbuf_freem(m); ! 1101: return 0; ! 1102: } ! 1103: } ! 1104: ! 1105: } else if (len < 0) { ! 1106: len = -len; ! 1107: l_cont: prev_m = 0; ! 1108: for (curr_m=m; gbuf_cont(curr_m); ! 1109: prev_m=curr_m, curr_m=gbuf_cont(curr_m)) ; ! 1110: buf_len = gbuf_len(curr_m); ! 1111: if (len < buf_len) { ! 1112: gbuf_wdec(curr_m,len); ! 1113: return 1; ! 1114: } ! 1115: if (prev_m == 0) ! 1116: return 0; ! 1117: gbuf_cont(prev_m) = 0; ! 1118: gbuf_freeb(curr_m); ! 1119: len -= buf_len; ! 1120: goto l_cont; ! 1121: ! 1122: } else ! 1123: return 1; ! 1124: } ! 1125: ! 1126: /* ! 1127: * The message chain, m is grown in size by len contiguous bytes. ! 1128: * If len is non-negative, len bytes are added to the ! 1129: * end of the gbuf_t chain. If len is negative, the ! 1130: * bytes are added to the front. ddp_growmsg only adds bytes to ! 1131: * message blocks of the same type. ! 1132: * It returns a pointer to the new gbuf_t on sucess, 0 on failure. ! 1133: */ ! 1134: ! 1135: gbuf_t *ddp_growmsg(mp, len) ! 1136: gbuf_t *mp; ! 1137: int len; ! 1138: { ! 1139: gbuf_t *m, *d; ! 1140: ! 1141: if ((m = mp) == (gbuf_t *) 0) ! 1142: return ((gbuf_t *) 0); ! 1143: ! 1144: if (len <= 0) { ! 1145: len = -len; ! 1146: if ((d = gbuf_alloc(len, PRI_MED)) == 0) ! 1147: return ((gbuf_t *) 0); ! 1148: gbuf_set_type(d, gbuf_type(m)); ! 1149: gbuf_wset(d,len); ! 1150: /* link in new gbuf_t */ ! 1151: gbuf_cont(d) = m; ! 1152: return (d); ! 1153: ! 1154: } else { ! 1155: register int count; ! 1156: /* ! 1157: * Add to tail. ! 1158: */ ! 1159: if ((count = gbuf_msgsize(m)) < 0) ! 1160: return ((gbuf_t *) 0); ! 1161: /* find end of chain */ ! 1162: for ( ; m; m = gbuf_cont(m)) { ! 1163: if (gbuf_len(m) >= count) ! 1164: break; ! 1165: count -= gbuf_len(m); ! 1166: } ! 1167: /* m now points to gbuf_t to add to */ ! 1168: if ((d = gbuf_alloc(len, PRI_MED)) == 0) ! 1169: return ((gbuf_t *) 0); ! 1170: gbuf_set_type(d, gbuf_type(m)); ! 1171: /* link in new gbuf_t */ ! 1172: gbuf_cont(d) = gbuf_cont(m); ! 1173: gbuf_cont(m) = d; ! 1174: gbuf_wset(d,len); ! 1175: return (d); ! 1176: } ! 1177: } ! 1178: ! 1179: /* ! 1180: * return the MSG_IOCACK/MSG_IOCNAK. Note that the same message ! 1181: * block is used as the vehicle, and that if there is an error return, ! 1182: * then linked blocks are lopped off. BEWARE of multiple references. ! 1183: * Used by other appletalk modules, so it is not static! ! 1184: */ ! 1185: ! 1186: void ioc_ack(errno, m, gref) ! 1187: int errno; ! 1188: register gbuf_t *m; ! 1189: register gref_t *gref; ! 1190: { ! 1191: ioc_t *iocbp = (ioc_t *)gbuf_rptr(m); ! 1192: ! 1193: /*kprintf("ioc_ack: m=%x gref=%x errno=%d\n", m, gref, errno);*/ ! 1194: if ((iocbp->ioc_error = errno) != 0) ! 1195: { /* errno != 0, then there is an error, get rid of linked blocks! */ ! 1196: ! 1197: if (gbuf_cont(m)) { ! 1198: gbuf_freem(gbuf_cont(m)); ! 1199: gbuf_cont(m) = 0; ! 1200: } ! 1201: gbuf_set_type(m, MSG_IOCNAK); ! 1202: iocbp->ioc_count = 0; /* only make zero length if error */ ! 1203: iocbp->ioc_rval = -1; ! 1204: } else ! 1205: gbuf_set_type(m, MSG_IOCACK); ! 1206: ! 1207: atalk_putnext(gref, m); ! 1208: } ! 1209:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.