|
|
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) 1996 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: * File: zi.c ! 36: */ ! 37: #include <sysglue.h> ! 38: #include <at/appletalk.h> ! 39: #include <lap.h> ! 40: #include <routing_tables.h> ! 41: #define _AURP ! 42: #include <at_aurp.h> ! 43: #include <at/aurp.h> ! 44: ! 45: /* */ ! 46: void AURPsndZReq(state) ! 47: aurp_state_t *state; ! 48: { ! 49: gbuf_t *m; ! 50: int msize; ! 51: aurp_hdr_t *hdrp; ! 52: short *net, nets_cnt, net_sent=0, entry_num=0; ! 53: RT_entry *entry = RT_table; ! 54: ! 55: if (!state->get_zi || (state->rcv_state == AURPSTATE_Unconnected)) ! 56: return; ! 57: ! 58: l_more: ! 59: msize = sizeof(aurp_hdr_t); ! 60: if ((m = (gbuf_t *)gbuf_alloc(msize+AURP_MaxPktSize, PRI_MED)) == 0) { ! 61: dPrintf(D_M_AURP, D_L_WARNING, ("AURPsndZReq: node=%d, out of mblk\n", ! 62: state->rem_node)); ! 63: return; ! 64: } ! 65: gbuf_wset(m,msize); ! 66: ! 67: /* construct the ZI request packet */ ! 68: hdrp = (aurp_hdr_t *)gbuf_rptr(m); ! 69: hdrp->connection_id = state->rcv_connection_id; ! 70: hdrp->sequence_number = 0; ! 71: hdrp->command_code = AURPCMD_ZReq; ! 72: hdrp->flags = 0; ! 73: *(short *)(hdrp+1) = AURPSUBCODE_ZoneInfo1; ! 74: gbuf_winc(m,sizeof(short)); ! 75: ! 76: net = (short *)gbuf_wptr(m); ! 77: nets_cnt = 0; ! 78: ! 79: while (entry_num < RT_maxentry) { ! 80: /* ! 81: * scan the router table, and build the ZI request packet ! 82: * with the right entries, i.e., ! 83: * - entry in use and not of the net_port ! 84: * - with no zones and in an active state ! 85: * - talking to the right router ! 86: */ ! 87: if ( (entry->NetPort == net_port) && entry->NetStop && ! 88: ((entry->EntryState & 0x0F) >= RTE_STATE_SUSPECT) && ! 89: (!RT_ALL_ZONES_KNOWN(entry)) ) { ! 90: *net++ = (entry->NetStart) ? entry->NetStart : entry->NetStop; ! 91: nets_cnt++; ! 92: } ! 93: ! 94: if (nets_cnt >= 640) { ! 95: /* query only 640 networks per packet */ ! 96: dPrintf(D_M_AURP, D_L_INFO, ("AURPsndZReq: node=%d\n", ! 97: state->rem_node)); ! 98: gbuf_winc(m,(nets_cnt * sizeof(short))); ! 99: AURPsend(m, AUD_AURP, state->rem_node); ! 100: net_sent = 1; ! 101: goto l_more; ! 102: } ! 103: ! 104: entry_num++; ! 105: entry++; ! 106: } ! 107: ! 108: if (nets_cnt) { ! 109: dPrintf(D_M_AURP, D_L_INFO, ("AURPsndZReq: node=%d\n", ! 110: state->rem_node)); ! 111: gbuf_winc(m,(nets_cnt * sizeof(short))); ! 112: AURPsend(m, AUD_AURP, state->rem_node); ! 113: net_sent = 1; ! 114: } else ! 115: gbuf_freeb(m); ! 116: ! 117: if (!net_sent) ! 118: state->get_zi = 0; ! 119: } ! 120: ! 121: /* */ ! 122: void AURPsndZRsp(state, dat_m, flag) ! 123: aurp_state_t *state; ! 124: gbuf_t *dat_m; ! 125: int flag; ! 126: { ! 127: short len; ! 128: int msize, next_entry = 0; ! 129: gbuf_t *m; ! 130: aurp_hdr_t *hdrp; ! 131: ! 132: if ((state->snd_state == AURPSTATE_Unconnected) || (dat_m == 0)) ! 133: return; ! 134: msize = sizeof(aurp_hdr_t); ! 135: ! 136: do { ! 137: if ((m = (gbuf_t *)gbuf_alloc(msize+AURP_MaxPktSize, PRI_MED)) == 0) { ! 138: dPrintf(D_M_AURP, D_L_WARNING, ("AURPsndZRsp: node=%d, out of mblk\n", ! 139: state->rem_node)); ! 140: return; ! 141: } ! 142: gbuf_wset(m,msize); ! 143: ! 144: /* construct the ZI response packet */ ! 145: hdrp = (aurp_hdr_t *)gbuf_rptr(m); ! 146: hdrp->connection_id = state->snd_connection_id; ! 147: hdrp->sequence_number = 0; ! 148: hdrp->command_code = AURPCMD_ZRsp; ! 149: hdrp->flags = 0; ! 150: ! 151: /* get zone info of the local networks */ ! 152: next_entry = AURPgetzi(next_entry, gbuf_wptr(m), &len, dat_m, flag); ! 153: gbuf_winc(m,len); ! 154: ! 155: /* send the packet */ ! 156: dPrintf(D_M_AURP, D_L_INFO, ("AURPsndZRsp: len=%d\n", len)); ! 157: AURPsend(m, AUD_AURP, state->rem_node); ! 158: ! 159: } while (next_entry); ! 160: ! 161: gbuf_freem(dat_m); ! 162: } ! 163: ! 164: /* */ ! 165: void AURPsndGZN(state, dat_m) ! 166: aurp_state_t *state; ! 167: gbuf_t *dat_m; ! 168: { ! 169: short zname_len; ! 170: int msize; ! 171: gbuf_t *m; ! 172: aurp_hdr_t *hdrp; ! 173: ! 174: if (state->snd_state == AURPSTATE_Unconnected) ! 175: return; ! 176: ! 177: msize = sizeof(aurp_hdr_t); ! 178: if ((m = (gbuf_t *)gbuf_alloc(msize+AURP_MaxPktSize, PRI_MED)) == 0) { ! 179: dPrintf(D_M_AURP, D_L_WARNING, ("AURPsndGZN: node=%d, out of mblk\n", ! 180: state->rem_node)); ! 181: return; ! 182: } ! 183: gbuf_wset(m,msize); ! 184: ! 185: /* construct the GZN response packet */ ! 186: hdrp = (aurp_hdr_t *)gbuf_rptr(m); ! 187: hdrp->connection_id = state->snd_connection_id; ! 188: hdrp->sequence_number = 0; ! 189: hdrp->command_code = AURPCMD_ZRsp; ! 190: hdrp->flags = 0; ! 191: *(short *)(gbuf_wptr(m)) = AURPSUBCODE_GetZoneNets; ! 192: gbuf_winc(m,sizeof(short)); ! 193: zname_len = gbuf_len(dat_m); ! 194: bcopy(gbuf_rptr(dat_m), gbuf_wptr(m), zname_len); ! 195: gbuf_winc(m,zname_len); ! 196: *(short *)(gbuf_wptr(m)) = -1; /* number of tuples - proto not supported */ ! 197: gbuf_winc(m,sizeof(short)); ! 198: ! 199: /* send the packet */ ! 200: dPrintf(D_M_AURP, D_L_INFO, ("AURPsndGZN: count=%d\n", -1)); ! 201: AURPsend(m, AUD_AURP, state->rem_node); ! 202: } ! 203: ! 204: /* */ ! 205: void AURPsndGDZL(state, dat_m) ! 206: aurp_state_t *state; ! 207: gbuf_t *dat_m; ! 208: { ! 209: int msize; ! 210: gbuf_t *m; ! 211: aurp_hdr_t *hdrp; ! 212: ! 213: if (state->snd_state == AURPSTATE_Unconnected) ! 214: return; ! 215: ! 216: msize = sizeof(aurp_hdr_t); ! 217: if ((m = (gbuf_t *)gbuf_alloc(msize+AURP_MaxPktSize, PRI_MED)) == 0) { ! 218: dPrintf(D_M_AURP, D_L_WARNING, ("AURPsndGDZL: node=%d, out of mblk\n", ! 219: state->rem_node)); ! 220: return; ! 221: } ! 222: gbuf_wset(m,msize); ! 223: ! 224: /* construct the GDZL response packet */ ! 225: hdrp = (aurp_hdr_t *)gbuf_rptr(m); ! 226: hdrp->connection_id = state->snd_connection_id; ! 227: hdrp->sequence_number = 0; ! 228: hdrp->command_code = AURPCMD_ZRsp; ! 229: hdrp->flags = 0; ! 230: *(short *)(gbuf_wptr(m)) = AURPSUBCODE_GetDomainZoneList; ! 231: gbuf_winc(m,sizeof(short)); ! 232: *(short *)(gbuf_wptr(m)) = -1; /* start index - proto not supported */ ! 233: gbuf_winc(m,sizeof(short)); ! 234: ! 235: /* send the packet */ ! 236: dPrintf(D_M_AURP, D_L_INFO, ("AURPsndGDZL: index=%d\n", -1)); ! 237: AURPsend(m, AUD_AURP, state->rem_node); ! 238: } ! 239: ! 240: /* */ ! 241: void AURPrcvZReq(state, m) ! 242: aurp_state_t *state; ! 243: gbuf_t *m; ! 244: { ! 245: short sub_code; ! 246: aurp_hdr_t *hdrp = (aurp_hdr_t *)gbuf_rptr(m); ! 247: ! 248: /* make sure we're in a valid state to accept it */ ! 249: if (state->snd_state == AURPSTATE_Unconnected) { ! 250: dPrintf(D_M_AURP, D_L_WARNING, ("AURPrcvZReq: unexpected response\n")); ! 251: gbuf_freem(m); ! 252: return; ! 253: } ! 254: ! 255: /* check for the correct connection id */ ! 256: if (hdrp->connection_id != state->snd_connection_id) { ! 257: dPrintf(D_M_AURP, D_L_WARNING, ! 258: ("AURPrcvZReq: invalid connection id, r=%d, m=%d\n", ! 259: hdrp->connection_id, state->snd_connection_id)); ! 260: gbuf_freem(m); ! 261: return; ! 262: } ! 263: ! 264: gbuf_rinc(m,sizeof(*hdrp)); ! 265: sub_code = *(short *)gbuf_rptr(m); ! 266: gbuf_rinc(m,sizeof(short)); ! 267: ! 268: dPrintf(D_M_AURP, D_L_INFO, ("AURPrcvZReq: len=%d\n", gbuf_len(m))); ! 269: ! 270: switch (sub_code) { ! 271: case AURPSUBCODE_ZoneInfo1: ! 272: AURPsndZRsp(state, m, 0); ! 273: return; ! 274: ! 275: case AURPSUBCODE_GetZoneNets: ! 276: AURPsndGZN(state, m); ! 277: break; ! 278: ! 279: case AURPSUBCODE_GetDomainZoneList: ! 280: AURPsndGDZL(state, m); ! 281: break; ! 282: } ! 283: ! 284: gbuf_freem(m); ! 285: } ! 286: ! 287: /* */ ! 288: void AURPrcvZRsp(state, m) ! 289: aurp_state_t *state; ! 290: gbuf_t *m; ! 291: { ! 292: short sub_code, tuples_cnt; ! 293: aurp_hdr_t *hdrp = (aurp_hdr_t *)gbuf_rptr(m); ! 294: ! 295: /* make sure we're in a valid state to accept it */ ! 296: if (state->rcv_state == AURPSTATE_Unconnected) { ! 297: dPrintf(D_M_AURP, D_L_WARNING, ("AURPrcvZRsp: unexpected response\n")); ! 298: gbuf_freem(m); ! 299: return; ! 300: } ! 301: ! 302: /* check for the correct connection id */ ! 303: if (hdrp->connection_id != state->rcv_connection_id) { ! 304: dPrintf(D_M_AURP, D_L_WARNING, ! 305: ("AURPrcvZRsp: invalid connection id, r=%d, m=%d\n", ! 306: hdrp->connection_id, state->rcv_connection_id)); ! 307: gbuf_freem(m); ! 308: return; ! 309: } ! 310: ! 311: gbuf_rinc(m,sizeof(*hdrp)); ! 312: sub_code = *(short *)gbuf_rptr(m); ! 313: gbuf_rinc(m,sizeof(short)); ! 314: ! 315: dPrintf(D_M_AURP, D_L_INFO, ("AURPrcvZRsp: len=%d\n", gbuf_len(m))); ! 316: ! 317: switch (sub_code) { ! 318: case AURPSUBCODE_ZoneInfo1: ! 319: case AURPSUBCODE_ZoneInfo2: ! 320: tuples_cnt = *(short *)gbuf_rptr(m); ! 321: gbuf_rinc(m,sizeof(short)); ! 322: if (AURPsetzi(state->rem_node, m, sub_code, tuples_cnt)) { ! 323: dPrintf(D_M_AURP, D_L_ERROR, ! 324: ("AURPrcvZRsp: AURPsetzi() error\n")); ! 325: } ! 326: break; ! 327: ! 328: case AURPSUBCODE_GetZoneNets: ! 329: break; ! 330: ! 331: case AURPSUBCODE_GetDomainZoneList: ! 332: break; ! 333: } ! 334: ! 335: gbuf_freem(m); ! 336: } ! 337: ! 338: /* */ ! 339: int AURPgetzi(next_entry, buf, len, dat_m, flag) ! 340: int next_entry; ! 341: unsigned char *buf; ! 342: short *len; ! 343: gbuf_t *dat_m; ! 344: int flag; ! 345: { ! 346: static int i_sav=ZT_BYTES-1, j_sav=0, idx_sav=-1; ! 347: unsigned char ev, zname_len, *zmap, *zname_base, *zname_sav, *tuples_ptr; ! 348: unsigned short net_num, *net, zname_offset; ! 349: short *sub_codep, *tuples_cntp, tuples_cnt, dat_len; ! 350: int i, j, idx, nets_cnt; ! 351: RT_entry *entry; ! 352: ! 353: sub_codep = (short *)buf; ! 354: buf += sizeof(short); ! 355: tuples_cntp = (short *)buf; ! 356: buf += sizeof(short); ! 357: *len = sizeof(short) + sizeof(short); ! 358: zname_base = buf + sizeof(short); ! 359: dat_len = 0; ! 360: ! 361: /* set the subcode in the ZI response packet */ ! 362: *sub_codep = next_entry ? AURPSUBCODE_ZoneInfo2 : AURPSUBCODE_ZoneInfo1; ! 363: ! 364: switch (flag) { ! 365: case 0: /* zone info in response to ZI request */ ! 366: net = (unsigned short *)gbuf_rptr(dat_m); ! 367: nets_cnt = (gbuf_len(dat_m))/2; ! 368: break; ! 369: case 1: /* zone info in response to Ack of RI response */ ! 370: tuples_ptr = gbuf_rptr(dat_m); ! 371: nets_cnt = (gbuf_len(dat_m))/3; ! 372: next_entry = 0; ! 373: break; ! 374: case 2: /* zone info in response to Ack of RI update */ ! 375: tuples_ptr = gbuf_rptr(dat_m); ! 376: nets_cnt = (gbuf_len(dat_m))/4; ! 377: next_entry = 0; ! 378: break; ! 379: } ! 380: ! 381: /* ! 382: * for each network, find all the zones that it belongs to ! 383: */ ! 384: for (tuples_cnt=0; next_entry < nets_cnt; next_entry++) { ! 385: switch(flag) { ! 386: case 0: ! 387: net_num = net[next_entry]; ! 388: break; ! 389: case 1: ! 390: net_num = *(unsigned short *)tuples_ptr; ! 391: tuples_ptr += 3; ! 392: gbuf_rinc(dat_m,3); ! 393: if (tuples_ptr[-1] & 0x80) { ! 394: tuples_ptr += 3; ! 395: gbuf_rinc(dat_m,3); ! 396: next_entry++; ! 397: } ! 398: break; ! 399: case 2: ! 400: if (gbuf_len(dat_m) <= 0) { ! 401: next_entry = nets_cnt; ! 402: goto l_done; ! 403: } ! 404: ev = *tuples_ptr++; ! 405: net_num = *(unsigned short *)tuples_ptr; ! 406: tuples_ptr += 3; ! 407: gbuf_rinc(dat_m,4); ! 408: if (tuples_ptr[-1] & 0x80) { ! 409: tuples_ptr += 2; ! 410: gbuf_rinc(dat_m,2); ! 411: } ! 412: if (ev != AURPEV_NetAdded) ! 413: continue; ! 414: break; ! 415: } ! 416: ! 417: /* ! 418: * find the RT entry associated with the network ! 419: */ ! 420: if ((entry = RT_lookup(net_num)) == 0) { ! 421: dPrintf(D_M_AURP, D_L_WARNING, ("AURPgetzi: invalid net, %d\n", ! 422: net_num)); ! 423: continue; ! 424: } ! 425: if ( ((entry->EntryState & 0x0F) < RTE_STATE_SUSPECT) || ! 426: !RT_ALL_ZONES_KNOWN(entry) || ! 427: (entry->AURPFlag & AURP_NetHiden) ) { ! 428: dPrintf(D_M_AURP_LOW, D_L_INFO, ("AURPgetzi: zombie net, net=%d\n", ! 429: net_num)); ! 430: continue; ! 431: } ! 432: ! 433: if (entry->NetStart == 0) { ! 434: if ((idx = ZT_get_zindex(entry->ZoneBitMap)) == 0) ! 435: continue; ! 436: idx--; /* index in the zone table */ ! 437: zname_len = ZT_table[idx].Zone.len; ! 438: if (zname_len) { ! 439: *(unsigned short *)buf = net_num; ! 440: buf += sizeof(short); ! 441: if (idx == idx_sav) { ! 442: /* use the optimized format */ ! 443: zname_offset = zname_sav - zname_base; ! 444: *(unsigned short *)buf = (0x8000 | zname_offset); ! 445: buf += sizeof(short); ! 446: dat_len += 4; ! 447: } else { ! 448: /* use the long format */ ! 449: zname_sav = buf; ! 450: *buf++ = zname_len; ! 451: bcopy(ZT_table[idx].Zone.str, buf, zname_len); ! 452: buf += zname_len; ! 453: dat_len += (3 + zname_len); ! 454: } ! 455: tuples_cnt++; ! 456: idx_sav = idx; ! 457: } ! 458: ! 459: } else { ! 460: zmap = entry->ZoneBitMap; ! 461: for (i=i_sav; i >=0; i--) { ! 462: if (!zmap[i]) ! 463: continue; ! 464: ! 465: for (j=j_sav; j < 8; j++) { ! 466: if (!((zmap[i] << j) & 0x80)) ! 467: continue; ! 468: ! 469: idx = i*8 + j; /* index in the zone table */ ! 470: zname_len = ZT_table[idx].Zone.len; ! 471: if (zname_len) { ! 472: if ((dat_len+3+zname_len) > AURP_MaxPktSize) { ! 473: i_sav = i; ! 474: j_sav = j; ! 475: goto l_done; ! 476: } ! 477: ! 478: *(unsigned short *)buf = net_num; ! 479: buf += sizeof(short); ! 480: if (idx == idx_sav) { ! 481: /* use the optimized format */ ! 482: zname_offset = zname_sav - zname_base; ! 483: *(unsigned short *)buf = (0x8000 | zname_offset); ! 484: buf += sizeof(short); ! 485: dat_len += 4; ! 486: } else { ! 487: /* use the long format */ ! 488: zname_sav = buf; ! 489: *buf++ = zname_len; ! 490: bcopy(ZT_table[idx].Zone.str, buf, zname_len); ! 491: buf += zname_len; ! 492: dat_len += (3 + zname_len); ! 493: } ! 494: tuples_cnt++; ! 495: idx_sav = idx; ! 496: } ! 497: } ! 498: } ! 499: } ! 500: if ((dat_len+3+32) > AURP_MaxPktSize) { ! 501: next_entry++; ! 502: break; ! 503: } ! 504: } ! 505: i_sav = ZT_BYTES-1; ! 506: j_sav = 0; ! 507: ! 508: l_done: ! 509: *len += dat_len; ! 510: if (next_entry == nets_cnt) ! 511: next_entry = 0; ! 512: ! 513: /* set the subcode in the ZI response packet */ ! 514: if (next_entry) ! 515: *sub_codep = AURPSUBCODE_ZoneInfo2; ! 516: ! 517: /* set the tuples count in the ZI response packet */ ! 518: *tuples_cntp = tuples_cnt; ! 519: ! 520: idx_sav = -1; ! 521: return next_entry; ! 522: } ! 523: ! 524: /* */ ! 525: int AURPsetzi(node, m, sub_code, tuples_cnt) ! 526: unsigned char node; ! 527: gbuf_t *m; ! 528: short sub_code; ! 529: short tuples_cnt; ! 530: { ! 531: int rc, tuple_fmt; ! 532: unsigned short net_num, zname_offset; ! 533: unsigned char *buf = gbuf_rptr(m), *zname_base; ! 534: RT_entry *entry; ! 535: at_nvestr_t *zname; ! 536: ! 537: /* compute the base of the zone names of the optimized tuples */ ! 538: zname_base = buf + sizeof(short); ! 539: ! 540: /* process all tuples */ ! 541: while (tuples_cnt-- > 0) { ! 542: net_num = *(unsigned short *)buf; ! 543: buf += sizeof(short); ! 544: if (*buf & 0x80) { ! 545: /* optimized-format tuple */ ! 546: zname_offset = (*(unsigned short *)buf) & 0x7fff; ! 547: buf += sizeof(short); ! 548: zname = (at_nvestr_t *)(zname_base + zname_offset); ! 549: tuple_fmt = 0; ! 550: dPrintf(D_M_AURP_LOW, D_L_INFO, ! 551: ("AURPsetzi: optimized fmt, net=%d. zlen=%d, zoffset=%d\n ", ! 552: net_num, zname->len, zname_offset)); ! 553: } else { ! 554: /* long-format tuple */ ! 555: zname = (at_nvestr_t *)buf; ! 556: tuple_fmt = 1; ! 557: dPrintf(D_M_AURP_LOW, D_L_INFO, ! 558: ("AURPsetzi: long fmt, net=%d, zlen=%d\n ", ! 559: net_num, zname->len)); ! 560: } ! 561: ! 562: /* ! 563: * find the RT entry associated with the specified network ! 564: */ ! 565: if ((entry = RT_lookup(net_num)) == 0) { ! 566: dPrintf(D_M_AURP, D_L_WARNING, ! 567: ("AURPsetzi: invalid net, net=%d\n", net_num)); ! 568: } else { /* entry found */ ! 569: if (entry->EntryState >= RTE_STATE_SUSPECT) { ! 570: if ((rc = ZT_add_zname(zname)) == ZT_MAXEDOUT) { ! 571: dPrintf(D_M_AURP, D_L_WARNING, ! 572: ("AURPsetzi: ZT_table full\n")); ! 573: } else { ! 574: ZT_set_zmap(rc, entry->ZoneBitMap); ! 575: RT_SET_ZONE_KNOWN(entry); ! 576: } ! 577: } ! 578: } ! 579: if (tuple_fmt) ! 580: buf += zname->len+1; ! 581: } ! 582: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.