|
|
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-1998 Apple Computer, Inc. ! 24: * All Rights Reserved. ! 25: */ ! 26: ! 27: /* ! 28: * 09/07/95 - Modified for performance (Tuyen Nguyen) ! 29: * Modified for MP, 1996 by Tuyen Nguyen ! 30: * Modified, April 9, 1997 by Tuyen Nguyen for MacOSX. ! 31: */ ! 32: #include <sys/errno.h> ! 33: #include <sys/types.h> ! 34: #include <sys/param.h> ! 35: #include <machine/spl.h> ! 36: #include <sys/systm.h> ! 37: #include <sys/kernel.h> ! 38: #include <sys/proc.h> ! 39: #include <sys/filedesc.h> ! 40: #include <sys/fcntl.h> ! 41: #include <sys/mbuf.h> ! 42: #include <sys/socket.h> ! 43: #include <sys/socketvar.h> ! 44: #include <sys/time.h> ! 45: #include <sys/ioctl.h> ! 46: #include <sys/malloc.h> ! 47: ! 48: #include <net/if.h> ! 49: ! 50: #include <netat/sysglue.h> ! 51: #include <netat/appletalk.h> ! 52: #include <netat/ddp.h> ! 53: #include <netat/at_snmp.h> ! 54: #include <netat/at_pcb.h> ! 55: #include <netat/debug.h> ! 56: #include <netat/at_var.h> ! 57: #include <netat/adsp.h> ! 58: #include <netat/adsp_internal.h> ! 59: ! 60: void SndMsgUp(); ! 61: void adsp_rput(); ! 62: static void adsp_iocack(); ! 63: static void adsp_iocnak(); ! 64: void adsp_dequeue_ccb(); ! 65: unsigned char adspAssignSocket(); ! 66: int adspallocate(), adsprelease(); ! 67: int adspInited = 0; ! 68: ! 69: atlock_t adspall_lock; ! 70: atlock_t adspgen_lock; ! 71: GLOBAL adspGlobal; ! 72: ! 73: /**********/ ! 74: ! 75: int adsp_pidM[256]; ! 76: char adsp_inputC[256]; ! 77: CCB *adsp_inputQ[256]; ! 78: ! 79: extern char ot_adsp_socketM[]; ! 80: extern at_ifaddr_t *ifID_home; ! 81: ! 82: CCB *ccb_used_list; ! 83: ! 84: void adsp_input(mp) ! 85: gbuf_t *mp; ! 86: { ! 87: gref_t *gref; ! 88: CCBPtr sp; ! 89: at_ddp_t *p; ! 90: int s, l; ! 91: gbuf_t *mb; ! 92: ! 93: switch (gbuf_type(mp)) { ! 94: case MSG_DATA: ! 95: p = (at_ddp_t *)gbuf_rptr(mp); ! 96: ATDISABLE(s, adspall_lock); ! 97: sp = adsp_inputQ[p->dst_socket]; ! 98: if ((sp == 0) || (sp->gref==0) || (sp->state==sClosed)) ! 99: { ! 100: ATENABLE(s, adspall_lock); ! 101: gbuf_freem(mp); ! 102: return; ! 103: } ! 104: else if (sp->otccbLink != 0) { ! 105: do { ! 106: if ((sp->remoteAddress.a.node == p->src_node) ! 107: && (sp->remoteAddress.a.socket == p->src_socket) ! 108: && (sp->remoteAddress.a.net == NET_VALUE(p->src_net))) ! 109: break; ! 110: } while ((sp = sp->otccbLink) != 0); ! 111: if (sp == 0) ! 112: { ! 113: ATENABLE(s, adspall_lock); ! 114: gbuf_freem(mp); ! 115: return; ! 116: } ! 117: } ! 118: if (sp->lockFlag) { ! 119: gbuf_next(mp) = 0; ! 120: if (sp->deferred_mb) { ! 121: for (mb=sp->deferred_mb; gbuf_next(mb); mb=gbuf_next(mb)) ; ! 122: gbuf_next(mb) = mp; ! 123: } else ! 124: sp->deferred_mb = mp; ! 125: ATENABLE(s, adspall_lock); ! 126: return; ! 127: } ! 128: ATDISABLE(l, sp->lockRemove); ! 129: sp->lockFlag = 1; ! 130: ATENABLE(l, adspall_lock); ! 131: while (mp) { ! 132: adsp_rput(sp->gref, mp); ! 133: if ((mp = sp->deferred_mb) != 0) { ! 134: sp->deferred_mb = gbuf_next(mp); ! 135: gbuf_next(mp) = 0; ! 136: } ! 137: } ! 138: sp->lockFlag = 0; ! 139: ATENABLE(s, sp->lockRemove); ! 140: return; ! 141: ! 142: case MSG_IOCACK: ! 143: case MSG_IOCNAK: ! 144: gref = (gref_t *)((ioc_t *)gbuf_rptr(mp))->ioc_private; ! 145: break; ! 146: ! 147: case MSG_IOCTL: ! 148: #ifdef APPLETALK_DEBUG ! 149: kprintf("unexpected MSG_IOCTL in adsp_input()"); ! 150: #endif ! 151: /* fall through */ ! 152: ! 153: default: ! 154: gbuf_freem(mp); ! 155: return; ! 156: } ! 157: ! 158: adsp_rput(gref, mp); ! 159: } ! 160: ! 161: /**********/ ! 162: int adsp_readable(gref) ! 163: gref_t *gref; ! 164: { ! 165: int rc; ! 166: CCBPtr sp; ! 167: ! 168: sp = (CCBPtr)gbuf_rptr(((gbuf_t *)gref->info)); ! 169: rc = sp->rData; ! 170: ! 171: return rc; ! 172: } ! 173: ! 174: int adsp_writeable(gref) ! 175: gref_t *gref; ! 176: { ! 177: int s, rc; ! 178: CCBPtr sp; ! 179: ! 180: sp = (CCBPtr)gbuf_rptr(((gbuf_t *)gref->info)); ! 181: ATDISABLE(s, sp->lock); ! 182: rc = CalcSendQFree(sp); ! 183: ATENABLE(s, sp->lock); ! 184: ! 185: return rc; ! 186: } ! 187: ! 188: static void adsp_init() ! 189: { ! 190: adspInited++; ! 191: InitGlobals(); ! 192: ccb_used_list = 0; ! 193: bzero(adsp_pidM, sizeof(adsp_pidM)); ! 194: bzero(adsp_inputC, sizeof(adsp_inputC)); ! 195: bzero(adsp_inputQ, sizeof(adsp_inputQ)); ! 196: } ! 197: ! 198: /* ! 199: * Description: ! 200: * ADSP open and close routines. These routines ! 201: * initalize and release the ADSP structures. They do not ! 202: * have anything to do with "connections" ! 203: */ ! 204: ! 205: int adsp_open(gref) ! 206: gref_t *gref; ! 207: { ! 208: register CCBPtr sp; ! 209: int s; ! 210: ! 211: if (!adspInited) ! 212: adsp_init(); ! 213: ! 214: if (!adspAllocateCCB(gref)) ! 215: return(ENOBUFS); /* can't get buffers */ ! 216: ! 217: sp = (CCBPtr)gbuf_rptr(((gbuf_t *)gref->info)); ! 218: gref->readable = adsp_readable; ! 219: gref->writeable = adsp_writeable; ! 220: ATDISABLE(s, adspall_lock); ! 221: if ((sp->otccbLink = ccb_used_list) != 0) ! 222: sp->otccbLink->ccbLink = sp; ! 223: ccb_used_list = sp; ! 224: ATENABLE(s, adspall_lock); ! 225: return 0; ! 226: } ! 227: ! 228: int adsp_close(gref) ! 229: gref_t *gref; ! 230: { ! 231: int s, l; ! 232: unsigned char localSocket; ! 233: ! 234: /* make sure we've not yet removed the CCB (e.g., due to TrashSession) */ ! 235: ATDISABLE(l, adspgen_lock); ! 236: if (gref->info) { ! 237: CCBPtr sp = (CCBPtr)gbuf_rptr(((gbuf_t *)gref->info)); ! 238: ATDISABLE(s, sp->lock); ! 239: ATENABLE(s, adspgen_lock); ! 240: localSocket = sp->localSocket; ! 241: ATENABLE(l, sp->lock); ! 242: if (localSocket) ! 243: adspRelease(gref); ! 244: else ! 245: { ! 246: adsp_dequeue_ccb(sp); ! 247: gbuf_freeb((gbuf_t *)gref->info); ! 248: } ! 249: } else ! 250: ATENABLE(l, adspgen_lock); ! 251: return 0; ! 252: } ! 253: ! 254: ! 255: /* ! 256: * Name: ! 257: * adsp_rput ! 258: * ! 259: * Description: ! 260: * ADSP streams read put and service routines. ! 261: */ ! 262: ! 263: void adsp_rput(gref, mp) ! 264: gref_t *gref; /* READ queue */ ! 265: gbuf_t *mp; ! 266: { ! 267: switch (gbuf_type(mp)) { ! 268: case MSG_HANGUP: ! 269: case MSG_IOCACK: ! 270: case MSG_IOCNAK: ! 271: switch (adspReadHandler(gref, mp)) { ! 272: case STR_PUTNEXT: ! 273: atalk_putnext(gref, mp); ! 274: break; ! 275: case STR_IGNORE: ! 276: break; ! 277: } ! 278: break; ! 279: case MSG_ERROR: ! 280: #ifdef APPLETALK_DEBUG ! 281: kprintf("adsp_rput received MSG_ERROR"); ! 282: #endif ! 283: /* fall through */ ! 284: default: ! 285: CheckReadQueue(gbuf_rptr(((gbuf_t *)gref->info))); ! 286: CheckSend(gbuf_rptr(((gbuf_t *)gref->info))); ! 287: ! 288: switch (gbuf_type(mp)) { ! 289: case MSG_IOCTL: ! 290: case MSG_DATA: ! 291: case MSG_PROTO: ! 292: if (adspReadHandler(gref, mp) == STR_PUTNEXT) ! 293: atalk_putnext(gref, mp); ! 294: break; ! 295: default: ! 296: atalk_putnext(gref, mp); ! 297: break; ! 298: } ! 299: } ! 300: } ! 301: ! 302: /* ! 303: * Name: ! 304: * adsp_wput ! 305: * ! 306: * Description: ! 307: * ADSP streams write put and service routines. ! 308: * ! 309: */ ! 310: ! 311: int adsp_wput(gref, mp) ! 312: gref_t *gref; /* WRITE queue */ ! 313: gbuf_t *mp; ! 314: { ! 315: int rc; ! 316: int s; ! 317: gbuf_t *xm; ! 318: ioc_t *iocbp; ! 319: CCBPtr sp = (CCBPtr)gbuf_rptr(((gbuf_t *)gref->info)); ! 320: ! 321: if (gbuf_type(mp) == MSG_IOCTL) { ! 322: iocbp = (ioc_t *)gbuf_rptr(mp); ! 323: switch (iocbp->ioc_cmd) { ! 324: case ADSPBINDREQ: ! 325: { ! 326: unsigned char v; ! 327: ! 328: if (gbuf_cont(mp) == NULL) { ! 329: iocbp->ioc_rval = -1; ! 330: adsp_iocnak(gref, mp, EINVAL); ! 331: } ! 332: v = *(unsigned char *)gbuf_rptr(gbuf_cont(mp)); ! 333: ATDISABLE(s, adspall_lock); ! 334: if ( (v != 0) ! 335: && ((v > DDP_SOCKET_LAST) || (v < 2) ! 336: || (adsp_inputQ[v] != 0) ! 337: || (ot_adsp_socketM[v] != 0)) ) { ! 338: ATENABLE(s, adspall_lock); ! 339: iocbp->ioc_rval = -1; ! 340: adsp_iocnak(gref, mp, EINVAL); ! 341: } ! 342: else { ! 343: if (v == 0) { ! 344: ATENABLE(s, adspall_lock); ! 345: if ((v = adspAssignSocket(gref, 0)) == 0) { ! 346: iocbp->ioc_rval = -1; ! 347: adsp_iocnak(gref, mp, EINVAL); ! 348: return 0; ! 349: } ! 350: } else { ! 351: adsp_inputC[v] = 1; ! 352: adsp_inputQ[v] = sp; ! 353: adsp_pidM[v] = sp->pid; ! 354: ATENABLE(s, adspall_lock); ! 355: adsp_dequeue_ccb(sp); ! 356: } ! 357: *(unsigned char *)gbuf_rptr(gbuf_cont(mp)) = v; ! 358: sp->localSocket = v; ! 359: iocbp->ioc_rval = 0; ! 360: adsp_iocack(gref, mp); ! 361: } ! 362: return 0; ! 363: } ! 364: ! 365: case ADSPGETSOCK: ! 366: case ADSPGETPEER: ! 367: { ! 368: at_inet_t *addr; ! 369: ! 370: if (((xm = gbuf_cont(mp)) == NULL) ! 371: && ((xm = gbuf_alloc(sizeof(at_inet_t), PRI_MED)) == NULL)) { ! 372: iocbp->ioc_rval = -1; ! 373: adsp_iocnak(gref, mp, ENOBUFS); ! 374: return 0; ! 375: } ! 376: gbuf_cont(mp) = xm; ! 377: gbuf_wset(xm,sizeof(at_inet_t)); ! 378: addr = (at_inet_t *)gbuf_rptr(xm); ! 379: if (iocbp->ioc_cmd == ADSPGETSOCK) { ! 380: /* Obtain Network and Node Id's from DDP */ ! 381: /* *** was ddp_get_cfg() *** */ ! 382: addr->net = ifID_home->ifThisNode.s_net; ! 383: addr->node = ifID_home->ifThisNode.s_node; ! 384: addr->socket = (sp)? sp->localSocket: 0; ! 385: } else ! 386: if (sp) ! 387: *addr = sp->remoteAddress.a; ! 388: else { ! 389: addr->net = 0; ! 390: addr->node = 0; ! 391: addr->socket = 0; ! 392: } ! 393: iocbp->ioc_rval = 0; ! 394: adsp_iocack(gref, mp); ! 395: return 0; ! 396: } ! 397: case DDP_IOC_GET_CFG: ! 398: /* respond to an DDP_IOC_GET_CFG sent on an adsp fd */ ! 399: if (((xm = gbuf_cont(mp)) == NULL) && ! 400: (xm = gbuf_alloc(sizeof(at_inet_t), PRI_MED)) == NULL) { ! 401: iocbp->ioc_rval = -1; ! 402: adsp_iocnak(gref, mp, ENOBUFS); ! 403: return 0; ! 404: } ! 405: gbuf_cont(mp) = xm; ! 406: gbuf_wset(xm, sizeof(ddp_addr_t)); ! 407: /* Obtain Network and Node Id's from DDP */ ! 408: { ! 409: /* *** was ddp_get_cfg() *** */ ! 410: ddp_addr_t *cfgp = ! 411: (ddp_addr_t *)gbuf_rptr(gbuf_cont(mp)); ! 412: cfgp->inet.net = ifID_home->ifThisNode.s_net; ! 413: cfgp->inet.node = ifID_home->ifThisNode.s_node; ! 414: cfgp->inet.socket = (sp)? sp->localSocket: 0; ! 415: cfgp->ddptype = DDP_ADSP; ! 416: } ! 417: iocbp->ioc_rval = 0; ! 418: adsp_iocack(gref, mp); ! 419: return 0; ! 420: } /* switch */ ! 421: } ! 422: ! 423: if (!gref->info) ! 424: gbuf_freem(mp); ! 425: else { ! 426: ATDISABLE(s, sp->lockClose); ! 427: rc = adspWriteHandler(gref, mp); ! 428: ATENABLE(s, sp->lockClose); ! 429: ! 430: switch (rc) { ! 431: case STR_PUTNEXT: ! 432: if (gbuf_type(mp) == MSG_IOCTL) { ! 433: iocbp = (ioc_t *)gbuf_rptr(mp); ! 434: iocbp->ioc_private = (void *)gref; ! 435: } ! 436: DDP_OUTPUT(mp); ! 437: break; ! 438: case STR_IGNORE: ! 439: case STR_IGNORE+99: ! 440: break; ! 441: default: ! 442: gbuf_freem(mp); ! 443: break; ! 444: } ! 445: } ! 446: ! 447: return 0; ! 448: } /* adsp_wput */ ! 449: ! 450: void adspioc_ack(errno, m, gref) ! 451: int errno; ! 452: gbuf_t *m; ! 453: gref_t *gref; ! 454: { ! 455: ioc_t *iocbp; ! 456: ! 457: if (m == NULL) ! 458: return; ! 459: iocbp = (ioc_t *) gbuf_rptr(m); ! 460: ! 461: iocbp->ioc_error = errno; /* set the errno */ ! 462: iocbp->ioc_count = gbuf_msgsize(gbuf_cont(m)); ! 463: if (gbuf_type(m) == MSG_IOCTL) /* if an ioctl, this is an ack */ ! 464: gbuf_set_type(m, MSG_IOCACK); /* and ALWAYS update the user */ ! 465: /* ioctl structure */ ! 466: trace_mbufs(D_M_ADSP,"A ", m); ! 467: SndMsgUp(gref, m); ! 468: } ! 469: ! 470: static void adsp_iocack(gref, m) ! 471: gref_t *gref; ! 472: register gbuf_t *m; ! 473: { ! 474: if (gbuf_type(m) == MSG_IOCTL) ! 475: gbuf_set_type(m, MSG_IOCACK); ! 476: ! 477: if (gbuf_cont(m)) ! 478: ((ioc_t *)gbuf_rptr(m))->ioc_count = gbuf_msgsize(gbuf_cont(m)); ! 479: else ! 480: ((ioc_t *)gbuf_rptr(m))->ioc_count = 0; ! 481: ! 482: SndMsgUp(gref, m); ! 483: } ! 484: ! 485: ! 486: static void adsp_iocnak(gref, m, err) ! 487: gref_t *gref; ! 488: register gbuf_t *m; ! 489: register int err; ! 490: { ! 491: if (gbuf_type(m) == MSG_IOCTL) ! 492: gbuf_set_type(m, MSG_IOCNAK); ! 493: ((ioc_t *)gbuf_rptr(m))->ioc_count = 0; ! 494: ! 495: if (err == 0) ! 496: err = ENXIO; ! 497: ((ioc_t *)gbuf_rptr(m))->ioc_error = err; ! 498: ! 499: if (gbuf_cont(m)) { ! 500: gbuf_freem(gbuf_cont(m)); ! 501: gbuf_cont(m) = NULL; ! 502: } ! 503: SndMsgUp(gref, m); ! 504: } ! 505: ! 506: unsigned char ! 507: adspAssignSocket(gref, flag) ! 508: gref_t *gref; ! 509: int flag; ! 510: { ! 511: unsigned char sVal, sMax, sMin, sSav, inputC; ! 512: CCBPtr sp; ! 513: int s; ! 514: ! 515: sMax = flag ? DDP_SOCKET_LAST-46 : DDP_SOCKET_LAST-6; ! 516: sMin = DDP_SOCKET_1st_DYNAMIC-64; ! 517: ! 518: ATDISABLE(s, adspall_lock); ! 519: for (inputC=255, sVal=sMax; sVal >= sMin; sVal--) { ! 520: if (!ot_adsp_socketM[sVal]) { ! 521: if (!adsp_inputQ[sVal]) ! 522: break; ! 523: else if (flag) { ! 524: if ((adsp_inputC[sVal] < inputC) ! 525: && (adsp_inputQ[sVal]->state == sOpen)) { ! 526: inputC = adsp_inputC[sVal]; ! 527: sSav = sVal; ! 528: } ! 529: } ! 530: } ! 531: } ! 532: ! 533: if (sVal < sMin) { ! 534: if (!flag || (inputC == 255)) { ! 535: ATENABLE(s, adspall_lock); ! 536: return 0; ! 537: } ! 538: sVal = sSav; ! 539: } ! 540: sp = (CCBPtr)gbuf_rptr(((gbuf_t *)gref->info)); ! 541: ATENABLE(s, adspall_lock); ! 542: adsp_dequeue_ccb(sp); ! 543: ATDISABLE(s, adspall_lock); ! 544: adsp_inputC[sVal]++; ! 545: sp->otccbLink = adsp_inputQ[sVal]; ! 546: adsp_inputQ[sVal] = sp; ! 547: if (!flag) ! 548: adsp_pidM[sVal] = sp->pid; ! 549: ATENABLE(s, adspall_lock); ! 550: return sVal; ! 551: } ! 552: ! 553: int ! 554: adspDeassignSocket(sp) ! 555: CCBPtr sp; ! 556: { ! 557: unsigned char sVal; ! 558: CCBPtr curr_sp; ! 559: CCBPtr prev_sp; ! 560: int pid = 0; ! 561: int s, l; ! 562: ! 563: dPrintf(D_M_ADSP, D_L_TRACE, ("adspDeassignSocket: pid=%d,s=%d\n", ! 564: sp->pid, sp->localSocket)); ! 565: ATDISABLE(s, adspall_lock); ! 566: sVal = sp->localSocket; ! 567: if ((curr_sp = adsp_inputQ[sVal]) != 0) { ! 568: prev_sp = 0; ! 569: while (curr_sp != sp) { ! 570: prev_sp = curr_sp; ! 571: curr_sp = curr_sp->otccbLink; ! 572: } ! 573: if (curr_sp) { ! 574: ATDISABLE(l, sp->lockRemove); ! 575: if (prev_sp) ! 576: prev_sp->otccbLink = sp->otccbLink; ! 577: else ! 578: adsp_inputQ[sVal] = sp->otccbLink; ! 579: ATENABLE(l, sp->lockRemove); ! 580: if (adsp_inputQ[sVal]) ! 581: adsp_inputC[sVal]--; ! 582: else { ! 583: pid = adsp_pidM[sVal]; ! 584: adsp_inputC[sVal] = 0; ! 585: adsp_pidM[sVal] = 0; ! 586: } ! 587: sp->ccbLink = 0; ! 588: sp->otccbLink = 0; ! 589: sp->localSocket = 0; ! 590: ATENABLE(s, adspall_lock); ! 591: return pid ? 0 : 1; ! 592: } ! 593: } ! 594: ATENABLE(s, adspall_lock); ! 595: ! 596: dPrintf(D_M_ADSP, D_L_ERROR, ! 597: ("adspDeassignSocket: closing, no CCB block, trouble ahead\n")); ! 598: return -1; ! 599: } /* adspDeassignSocket */ ! 600: ! 601: /* ! 602: * remove CCB from the use list ! 603: */ ! 604: void ! 605: adsp_dequeue_ccb(sp) ! 606: CCB *sp; ! 607: { ! 608: int s; ! 609: ! 610: ATDISABLE(s, adspall_lock); ! 611: if (sp == ccb_used_list) { ! 612: if ((ccb_used_list = sp->otccbLink) != 0) ! 613: sp->otccbLink->ccbLink = 0; ! 614: } else if (sp->ccbLink) { ! 615: if ((sp->ccbLink->otccbLink = sp->otccbLink) != 0) ! 616: sp->otccbLink->ccbLink = sp->ccbLink; ! 617: } ! 618: ! 619: sp->otccbLink = 0; ! 620: sp->ccbLink = 0; ! 621: ATENABLE(s, adspall_lock); ! 622: } ! 623: ! 624: void SndMsgUp(gref, mp) ! 625: gref_t *gref; /* WRITE queue */ ! 626: gbuf_t *mp; ! 627: { ! 628: /* ! 629: dPrintf(D_M_ADSP, D_L_TRACE, ! 630: ("SndMsgUp: gref=0x%x, mbuf=0x%x\n", (unsigned)gref, (unsigned)mp)); ! 631: trace_mbufs(D_M_ADSP, " m", mp); ! 632: */ ! 633: atalk_putnext(gref, mp); ! 634: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.