|
|
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) 1988, 1989, 1997, 1998 Apple Computer, Inc. ! 27: * ! 28: * The information contained herein is subject to change without ! 29: * notice and should not be construed as a commitment by Apple ! 30: * Computer, Inc. Apple Computer, Inc. assumes no responsibility ! 31: * for any errors that may appear. ! 32: * ! 33: * Confidential and Proprietary to Apple Computer, Inc. ! 34: */ ! 35: ! 36: /* ddp_proto.c: 2.0, 1.23; 10/18/93; Apple Computer, Inc. */ ! 37: ! 38: #include <sysglue.h> ! 39: #ifdef _AIX ! 40: #include <sys/sysmacros.h> ! 41: #endif ! 42: #include <sys/buf.h> ! 43: #include <at/appletalk.h> ! 44: #include <atlog.h> ! 45: #include <lap.h> ! 46: #include <at/ddp.h> ! 47: #include <at/zip.h> ! 48: #include <at/at_lap.h> ! 49: #include <at_ddp.h> ! 50: #include <at/elap.h> ! 51: #include <h/at_elap.h> ! 52: ! 53: extern atlock_t ddpall_lock; ! 54: extern atlock_t ddpinp_lock; ! 55: extern int ot_protoCnt; ! 56: ! 57: #define DDPCLONEMIN 1 ! 58: ! 59: /* Pointer to LAP interface which DDP addresses are tied to */ ! 60: extern at_if_t *ifID_table[]; ! 61: ! 62: ddp_dev_t ddp_devs[DDP_SOCKET_LAST+1]; ! 63: ! 64: static void ddp_stop_ack(); ! 65: char ddp_off_flag; ! 66: static gbuf_t *ddp_ack_m; ! 67: static gref_t *ddp_ack_gref; ! 68: ! 69: int ! 70: lap_open(gref) ! 71: gref_t *gref; ! 72: { ! 73: int rc; ! 74: ! 75: if ((rc = ddp_open(gref)) == 0) ! 76: ((ddp_dev_t *)gref->info)->pid = 0; ! 77: return rc; ! 78: } ! 79: ! 80: int ! 81: ddp_open(gref) ! 82: gref_t *gref; ! 83: { ! 84: int s; ! 85: int i; ! 86: ! 87: if ((ot_protoCnt >= 3) && !ifID_table[IFID_HOME]) { ! 88: return(ENETDOWN); ! 89: } ! 90: ! 91: /* ! 92: * If not ready, return error ! 93: */ ! 94: if (ddp_off_flag) ! 95: return ENOTREADY; ! 96: ! 97: /* Look for an unused minor number */ ! 98: ATDISABLE(s, ddpall_lock); ! 99: for (i=DDPCLONEMIN; i <= DDP_SOCKET_LAST; i++) { ! 100: if (!ddp_devs[i].flags) { ! 101: break; /* Either ALLOCATED or SHUTDOWN */ ! 102: } ! 103: } ! 104: ! 105: if (i > DDP_SOCKET_LAST) { ! 106: ATENABLE(s, ddpall_lock); ! 107: return(EADDRNOTAVAIL); ! 108: } ! 109: ! 110: /* If we arrive here, i is the minor number to be ! 111: * allocated for this stream. ! 112: */ ! 113: ddp_devs[i].flags |= DDPF_ALLOCATED; ! 114: ddp_devs[i].proto = 0; ! 115: ddp_devs[i].sock_entry = NULL; ! 116: ddp_devs[i].pid = gref->pid; ! 117: gref->info = (void *)&ddp_devs[i]; ! 118: ATENABLE(s, ddpall_lock); ! 119: ! 120: return(0); ! 121: } ! 122: ! 123: int ! 124: ddp_close(gref) ! 125: gref_t *gref; ! 126: { ! 127: int s; ! 128: int rc = 0; ! 129: ! 130: /* ! 131: * Free the entry for this queue in the ddp_devs table. ! 132: * Can clear both DDPF_ALLOCATED, DDPF_SHUTDOWN since this is the ! 133: * "last close" for this device. ! 134: */ ! 135: ATDISABLE(s, ddpall_lock); ! 136: ((ddp_dev_t *)gref->info)->flags = 0; ! 137: ! 138: /* protect against the case where close is done on socket that's ! 139: * not bound ! 140: */ ! 141: if (DDP_SOCKENTRY(gref)) ! 142: rc = ddp_close_socket(DDP_SOCKENTRY(gref)); ! 143: ATENABLE(s, ddpall_lock); ! 144: return rc; ! 145: } ! 146: ! 147: int ddp_putmsg(gref, mp) ! 148: gref_t *gref; ! 149: gbuf_t *mp; ! 150: { ! 151: extern char ot_protoT[]; ! 152: ddp_socket_t socket; ! 153: register ioc_t *iocbp; ! 154: register int error; ! 155: at_ddp_t *ddp; ! 156: at_inet_t *addr; ! 157: gbuf_t *ymp; ! 158: union at_ddpopt *ddpopt; ! 159: ! 160: switch(gbuf_type(mp)) { ! 161: case MSG_DATA : ! 162: /* If this message is going out on a socket that's not bound, ! 163: * nail it. ! 164: */ ! 165: ddp = (at_ddp_t *)gbuf_rptr(mp); ! 166: if (ot_protoT[ddp->type]) { ! 167: if ((gref == 0) || !DDP_SOCKENTRY(gref)) { ! 168: int src_addr_included = ((ddp->type==3) && ddp->src_node)? 1 : 0; ! 169: if (ddp_output(&mp, ddp->src_socket, src_addr_included) != 0) { ! 170: do { ! 171: ymp = gbuf_next(mp); ! 172: gbuf_next(mp) = 0; ! 173: gbuf_freem(mp); ! 174: mp = ymp; ! 175: } while (mp); ! 176: } ! 177: return; ! 178: } ! 179: } ! 180: if (gref && !DDP_SOCKENTRY(gref)) { ! 181: data_error(ENOTCONN, mp, gref); ! 182: return; ! 183: } ! 184: ! 185: if ((error = ddp_output(&mp, DDP_SOCKNUM(gref), 0)) != 0) ! 186: if (gref) ! 187: data_error(error, mp, gref); ! 188: else ! 189: gbuf_freem(mp); ! 190: return; ! 191: ! 192: case MSG_IOCTL : ! 193: iocbp = (ioc_t *)gbuf_rptr(mp); ! 194: if (DDP_IOC_MYIOCTL(iocbp->ioc_cmd)) { ! 195: switch(iocbp->ioc_cmd) { ! 196: case DDP_IOC_GET_CFG : ! 197: if (gbuf_cont(mp)) ! 198: gbuf_freem(gbuf_cont(mp)); ! 199: if ((gbuf_cont(mp) = gbuf_alloc(sizeof(at_ddp_cfg_t), ! 200: PRI_MED)) == NULL) { ! 201: if (gref == 0) { ! 202: iocbp->ioc_error = ENOBUFS; ! 203: gbuf_set_type(mp, MSG_IOCNAK); ! 204: if (iocbp->ioc_error == 3) ! 205: atp_input(mp); ! 206: else ! 207: adsp_input(mp); ! 208: } else ! 209: ioc_ack(ENOBUFS, mp, gref); ! 210: break; ! 211: } ! 212: if (gref == 0) { ! 213: ddp_get_cfg((at_ddp_cfg_t *)gbuf_rptr(gbuf_cont(mp)), ! 214: iocbp->ioc_count); ! 215: } else ! 216: ddp_get_cfg((at_ddp_cfg_t *)gbuf_rptr(gbuf_cont(mp)), ! 217: DDP_SOCKNUM(gref)); ! 218: gbuf_wset(gbuf_cont(mp),sizeof(at_ddp_cfg_t)); ! 219: iocbp->ioc_count = sizeof(at_ddp_cfg_t); ! 220: if (gref == 0) { ! 221: gbuf_set_type(mp, MSG_IOCACK); ! 222: error = iocbp->ioc_error; ! 223: iocbp->ioc_error = 0; ! 224: if (error == 3) ! 225: atp_input(mp); ! 226: else ! 227: adsp_input(mp); ! 228: } else ! 229: ioc_ack(0, mp, gref); ! 230: break; ! 231: case DDP_IOC_GET_STATS : ! 232: if (gbuf_cont(mp)) ! 233: gbuf_freem(gbuf_cont(mp)); ! 234: if ((gbuf_cont(mp) = gbuf_alloc(sizeof(at_ddp_stats_t), ! 235: PRI_MED)) == NULL) { ! 236: ioc_ack(ENOBUFS, mp, gref); ! 237: break; ! 238: } ! 239: ddp_get_stats( ! 240: (at_ddp_stats_t *)gbuf_rptr(gbuf_cont(mp))); ! 241: gbuf_wset(gbuf_cont(mp),sizeof(at_ddp_stats_t)); ! 242: iocbp->ioc_count = sizeof(at_ddp_stats_t); ! 243: ioc_ack(0, mp, gref); ! 244: break; ! 245: case DDP_IOC_BIND_SOCK : ! 246: if ((iocbp->ioc_count < sizeof(at_socket)) || ! 247: (gbuf_cont(mp) == NULL) || ! 248: (gbuf_len(gbuf_cont(mp)) < sizeof(at_socket))) { ! 249: ioc_ack(EMSGSIZE, mp, gref); ! 250: break; ! 251: } ! 252: socket.number= *(at_socket *)gbuf_rptr(gbuf_cont(mp)); ! 253: socket.flags = 0; ! 254: socket.sock_u.gref = gref; ! 255: socket.dev = (void *)gref->info; ! 256: if ((error = ddp_bind_socket(&socket)) != 0) { ! 257: ioc_ack(error, mp, gref); ! 258: break; ! 259: } else { ! 260: DDP_SOCKENTRY(gref) = &ddp_socket[socket.number]; ! 261: DDP_SOCKENTRY(gref)->otChecksum = 0; ! 262: DDP_SOCKENTRY(gref)->otType = 0; ! 263: DDP_SOCKENTRY(gref)->otPeerAddr = 0; ! 264: ddp_socket[socket.number].dev = (void *)gref->info; ! 265: *(at_socket *)gbuf_rptr(gbuf_cont(mp)) = socket.number; ! 266: ioc_ack(0, mp, gref); ! 267: } ! 268: break; ! 269: case DDP_IOC_SET_PROTO : ! 270: ((ddp_dev_t *)gref->info)->proto = *(u_char *)gbuf_rptr(gbuf_cont(mp)); ! 271: ioc_ack(0, mp, gref); ! 272: break; ! 273: case DDP_IOC_SET_OPTS: ! 274: if (DDP_SOCKENTRY(gref) == NULL) { ! 275: ioc_ack(ENOTREADY, mp, gref); ! 276: break; ! 277: } ! 278: if (gbuf_cont(mp) != NULL) { ! 279: ddpopt = (union at_ddpopt *)gbuf_rptr(gbuf_cont(mp)); ! 280: DDP_SOCKENTRY(gref)->otChecksum = ddpopt->ct.checksum; ! 281: DDP_SOCKENTRY(gref)->otType = ddpopt->ct.type; ! 282: } ! 283: ioc_ack(0, mp, gref); ! 284: break; ! 285: case DDP_IOC_GET_OPTS: ! 286: if (DDP_SOCKENTRY(gref) == NULL) { ! 287: ioc_ack(ENOTREADY, mp, gref); ! 288: break; ! 289: } ! 290: if ((gbuf_cont(mp) == NULL) ! 291: && (gbuf_cont(mp) = gbuf_alloc(sizeof(union at_ddpopt), ! 292: PRI_MED)) == NULL) { ! 293: ioc_ack(ENOBUFS, mp, gref); ! 294: break; ! 295: } ! 296: gbuf_wset(gbuf_cont(mp),sizeof(union at_ddpopt)); ! 297: ddpopt = (union at_ddpopt *)gbuf_rptr(gbuf_cont(mp)); ! 298: ddpopt->ct.checksum = DDP_SOCKENTRY(gref)->otChecksum; ! 299: ddpopt->ct.type = DDP_SOCKENTRY(gref)->otType; ! 300: ioc_ack(0, mp, gref); ! 301: break; ! 302: case DDP_IOC_GET_SOCK: ! 303: case DDP_IOC_GET_PEER: ! 304: if (DDP_SOCKENTRY(gref) == NULL) { ! 305: ioc_ack(ENOTREADY, mp, gref); ! 306: break; ! 307: } ! 308: if ((gbuf_cont(mp) == NULL) ! 309: && (gbuf_cont(mp) = gbuf_alloc(sizeof(at_inet_t), ! 310: PRI_MED)) == NULL) { ! 311: ioc_ack(ENOBUFS, mp, gref); ! 312: break; ! 313: } ! 314: gbuf_wset(gbuf_cont(mp),sizeof(at_inet_t)); ! 315: addr = (at_inet_t *)gbuf_rptr(gbuf_cont(mp)); ! 316: if (iocbp->ioc_cmd == DDP_IOC_GET_SOCK) { ! 317: bzero((char *)addr, sizeof(at_inet_t)); ! 318: addr->socket = DDP_SOCKENTRY(gref)->number; ! 319: if (ifID_table[IFID_HOME]) { ! 320: addr->node = ! 321: ifID_table[IFID_HOME]->ifThisNode.atalk_node; ! 322: *(unsigned short *)addr->net = *(unsigned short *) ! 323: ifID_table[IFID_HOME]->ifThisNode.atalk_net; ! 324: } ! 325: } else ! 326: *addr = *(at_inet_t *)&DDP_SOCKENTRY(gref)->otPeerAddr; ! 327: ioc_ack(0, mp, gref); ! 328: break; ! 329: case DDP_IOC_SET_PEER: ! 330: if (DDP_SOCKENTRY(gref) == NULL) { ! 331: ioc_ack(ENOTREADY, mp, gref); ! 332: break; ! 333: } ! 334: if (gbuf_cont(mp) == NULL) { ! 335: ioc_ack(EINVAL, mp, gref); ! 336: break; ! 337: } ! 338: *(at_inet_t *)&DDP_SOCKENTRY(gref)->otPeerAddr = ! 339: *(at_inet_t *)gbuf_rptr(gbuf_cont(mp)); ! 340: ioc_ack(0, mp, gref); ! 341: break; ! 342: } ! 343: } else if (ZIP_IOC_MYIOCTL(iocbp->ioc_cmd)) { ! 344: zip_ioctl(gref, mp); ! 345: break; ! 346: } else { ! 347: /* Unknown ioctl */ ! 348: ioc_ack(EINVAL, mp, gref); ! 349: } ! 350: break; ! 351: case MSG_PROTO: ! 352: if (((ddp_dev_t *)gref->info)->flags & DDPF_SI) ! 353: si_ddp_proto_req(gref, mp); ! 354: else ! 355: gbuf_freem(mp); ! 356: break; ! 357: case MSG_CTL: ! 358: /* *** this should never happen *** */ ! 359: kprintf("ddp_putmsg: MSG_CTL received/n"); ! 360: gbuf_freem(mp); ! 361: break; ! 362: case MSG_IOCACK: ! 363: ddp_stop_ack(gref, mp); ! 364: break; ! 365: default : ! 366: gbuf_freem(mp); ! 367: break; ! 368: } ! 369: return; ! 370: } /* ddp_putmsg */ ! 371: ! 372: char * ! 373: ddps_init() ! 374: { register int i; ! 375: register ddp_dev_t *d; ! 376: ! 377: for (i=0, d=ddp_devs; i < DDP_SOCKET_LAST;i++, d++) ! 378: d->sock_entry = NULL; ! 379: ! 380: /* A non-zero value to keep ddp_init happy */ ! 381: return ((char *)1); ! 382: } ! 383: ! 384: ! 385: int ddps_shutdown(grefInput) ! 386: gref_t *grefInput; ! 387: { ! 388: /* Network is shutting down... send error messages up on each open ! 389: * socket ! 390: */ ! 391: register gbuf_t *mp, *mp2; ! 392: register gref_t *gref; ! 393: register at_socket socket; ! 394: register ddp_socket_t *socketp; ! 395: register int do_timeout = 0; ! 396: ! 397: if ((mp = gbuf_alloc(1, PRI_HI)) == NULL) { ! 398: goto later; ! 399: } ! 400: ! 401: gbuf_wset(mp, 1); ! 402: gbuf_set_type(mp, MSG_ERROR); ! 403: *gbuf_rptr(mp) = ESHUTDOWN; ! 404: ! 405: for (socket = 1, socketp = &ddp_socket[1]; socket <= DDP_SOCKET_LAST; ! 406: socket++, socketp++) { ! 407: if (gref = socketp->sock_u.gref) { ! 408: if (mp2 = (gbuf_t *)gbuf_copym(mp)) { ! 409: if (socketp->flags & DDP_CALL_HANDLER) ! 410: (*socketp->sock_u.handler)(mp2, 0); ! 411: else ! 412: atalk_putnext(gref, mp2); ! 413: } else { ! 414: /* Out of buffers, wait a while... ! 415: */ ! 416: do_timeout = 1; ! 417: ddp_devs[socketp->number].flags ! 418: |= DDPF_SHUTDOWN; ! 419: continue; ! 420: } ! 421: } ! 422: } ! 423: ! 424: gbuf_freem(mp); ! 425: if (do_timeout) ! 426: goto later; ! 427: return; ! 428: ! 429: later: ! 430: atalk_timeout(ddps_shutdown, grefInput, SYS_HZ/10); ! 431: return; ! 432: } ! 433: ! 434: gbuf_t *ddp_compress_msg(mp) ! 435: register gbuf_t *mp; ! 436: { ! 437: register gbuf_t *tmp; ! 438: ! 439: while (gbuf_len(mp) == 0) { ! 440: tmp = mp; ! 441: mp = gbuf_cont(mp); ! 442: gbuf_freeb(tmp); ! 443: ! 444: if (mp == NULL) ! 445: break; ! 446: } ! 447: return (mp); ! 448: } ! 449: ! 450: int ! 451: si_ddp_proto_req(gref, mp) ! 452: gref_t *gref; ! 453: gbuf_t *mp; ! 454: { ! 455: at_ddp_t *ddp; ! 456: at_inet_t *remaddr; ! 457: gbuf_t *xmp = gbuf_cont(mp); ! 458: ! 459: if ((DDP_SOCKENTRY(gref) == NULL) || (xmp == NULL)) { ! 460: gbuf_freem(mp); ! 461: return(-1); ! 462: } ! 463: ! 464: if (gbuf_len(mp) == 1) { ! 465: remaddr = (at_inet_t *)&DDP_SOCKENTRY(gref)->otPeerAddr; ! 466: if (remaddr->socket == 0) { ! 467: gbuf_freem(mp); ! 468: return(-1); ! 469: } ! 470: } else ! 471: remaddr = (at_inet_t *)gbuf_rptr(mp); ! 472: ! 473: gbuf_rinc(xmp,DDP_X_HDR_SIZE); ! 474: ddp = (at_ddp_t *)gbuf_rptr(mp); ! 475: *(unsigned short *)&ddp->checksum = DDP_SOCKENTRY(gref)->otChecksum; ! 476: ddp->length = gbuf_len(xmp); ! 477: ddp->dst_socket = remaddr->socket; ! 478: ddp->dst_node = remaddr->node; ! 479: ddp->type = DDP_SOCKENTRY(gref)->otType; ! 480: *(unsigned short *)&ddp->dst_net = *(unsigned short *)&remaddr->net; ! 481: gbuf_freeb(mp); ! 482: if (ddp_output(&xmp, DDP_SOCKENTRY(gref)->number, 0) != 0) { ! 483: gbuf_freem(xmp); ! 484: return(-1); ! 485: } ! 486: ! 487: return( 0); ! 488: } ! 489: ! 490: int ! 491: si_ddp_input(gref, mp) ! 492: gref_t *gref; ! 493: gbuf_t *mp; ! 494: { ! 495: gbuf_t *xmp; ! 496: at_ddp_t *ddp; ! 497: at_inet_t *remaddr; ! 498: ! 499: /* ! 500: * allocate a buffer for the M_PROTO ! 501: */ ! 502: if ((xmp = gbuf_alloc(sizeof(at_inet_t), PRI_MED)) == NULL) { ! 503: gbuf_freem(mp); ! 504: return(ENOBUFS); ! 505: } ! 506: gbuf_cont(xmp) = mp; ! 507: ! 508: /* ! 509: * construct the M_PROTO ! 510: */ ! 511: ddp = (at_ddp_t *)gbuf_rptr(mp); ! 512: gbuf_rinc(mp,DDP_X_HDR_SIZE); ! 513: gbuf_wset(xmp,sizeof(at_inet_t)); ! 514: remaddr = (at_inet_t *)gbuf_rptr(xmp); ! 515: remaddr->socket = ddp->src_socket; ! 516: remaddr->node = ddp->src_node; ! 517: *(unsigned short *)&remaddr->net = *(unsigned short *)&ddp->src_net; ! 518: gbuf_set_type(xmp, MSG_PROTO); ! 519: ! 520: /* ! 521: * send the M_PROTO upstream ! 522: */ ! 523: atalk_putnext(gref, xmp); ! 524: return(0); ! 525: } ! 526: ! 527: /* ! 528: * stop DDP now ! 529: */ ! 530: void ! 531: ddp_stop(mioc, gref) ! 532: gbuf_t *mioc; ! 533: gref_t *gref; ! 534: { ! 535: unsigned char flag; ! 536: int k, s, *x_wptr; ! 537: ddp_dev_t *dev; ! 538: gbuf_t *m = gbuf_cont(mioc); ! 539: ! 540: ATDISABLE(s, ddpinp_lock); ! 541: if ((flag = *gbuf_rptr(m)) != 0) ! 542: ddp_off_flag = 1; ! 543: ! 544: x_wptr = (int *)gbuf_wptr(m); ! 545: for (k=0; k < (DDP_SOCKET_LAST+1); k++) { ! 546: dev = &ddp_devs[k]; ! 547: if ((dev->flags == 0) || (dev->pid == 0)) ! 548: continue; ! 549: *(int *)gbuf_wptr(m) = dev->pid; ! 550: gbuf_winc(m,sizeof(int)); ! 551: } ! 552: ATENABLE(s, ddpinp_lock); ! 553: ! 554: while (x_wptr != (int *)gbuf_wptr(m)) { ! 555: dPrintf(D_M_DDP,D_L_TRACE, ("ddp_stop: pid=%d\n", *x_wptr)); ! 556: x_wptr++; ! 557: } ! 558: ! 559: ddp_ack_m = mioc; ! 560: ddp_ack_gref = gref; ! 561: gbuf_rptr(m)[1] = 0; ! 562: gbuf_set_type(m, MSG_IOCTL); ! 563: atp_input(m); ! 564: } ! 565: ! 566: static void ! 567: ddp_stop_ack(gref, m) ! 568: gref_t *gref; ! 569: gbuf_t *m; ! 570: { ! 571: static int gotADSPinput = 0; ! 572: ! 573: if (!gotADSPinput) { ! 574: dPrintf(D_M_DDP,D_L_INFO, ! 575: ("ddp_stop_ack: CHECK_STATE...1\n")); ! 576: gotADSPinput = 1; ! 577: gbuf_set_type(m, MSG_IOCTL); ! 578: adsp_input(m); ! 579: } else { ! 580: dPrintf(D_M_DDP,D_L_INFO, ! 581: ("ddp_stop_ack: CHECK_STATE...2\n")); ! 582: gotADSPinput = 0; ! 583: gbuf_rinc(m,sizeof(int)); ! 584: gbuf_set_type(m, MSG_DATA); ! 585: ((ioc_t *)gbuf_rptr(ddp_ack_m))->ioc_count = gbuf_msgsize(m); ! 586: ioc_ack(0, ddp_ack_m, ddp_ack_gref); ! 587: } ! 588: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.