1*0Sstevel@tonic-gate /* 2*0Sstevel@tonic-gate * Copyright 2001-2002 Sun Microsystems, Inc. All rights reserved. 3*0Sstevel@tonic-gate * Use is subject to license terms. 4*0Sstevel@tonic-gate */ 5*0Sstevel@tonic-gate 6*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 7*0Sstevel@tonic-gate 8*0Sstevel@tonic-gate /* 9*0Sstevel@tonic-gate * usr/src/cmd/cmd-inet/usr.bin/telnet/ring.c 10*0Sstevel@tonic-gate */ 11*0Sstevel@tonic-gate 12*0Sstevel@tonic-gate /* 13*0Sstevel@tonic-gate * Copyright (c) 1988, 1993 14*0Sstevel@tonic-gate * The Regents of the University of California. All rights reserved. 15*0Sstevel@tonic-gate * 16*0Sstevel@tonic-gate * Redistribution and use in source and binary forms, with or without 17*0Sstevel@tonic-gate * modification, are permitted provided that the following conditions 18*0Sstevel@tonic-gate * are met: 19*0Sstevel@tonic-gate * 1. Redistributions of source code must retain the above copyright 20*0Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer. 21*0Sstevel@tonic-gate * 2. Redistributions in binary form must reproduce the above copyright 22*0Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer in the 23*0Sstevel@tonic-gate * documentation and/or other materials provided with the distribution. 24*0Sstevel@tonic-gate * 3. All advertising materials mentioning features or use of this software 25*0Sstevel@tonic-gate * must display the following acknowledgement: 26*0Sstevel@tonic-gate * This product includes software developed by the University of 27*0Sstevel@tonic-gate * California, Berkeley and its contributors. 28*0Sstevel@tonic-gate * 4. Neither the name of the University nor the names of its contributors 29*0Sstevel@tonic-gate * may be used to endorse or promote products derived from this software 30*0Sstevel@tonic-gate * without specific prior written permission. 31*0Sstevel@tonic-gate * 32*0Sstevel@tonic-gate * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 33*0Sstevel@tonic-gate * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 34*0Sstevel@tonic-gate * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 35*0Sstevel@tonic-gate * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 36*0Sstevel@tonic-gate * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 37*0Sstevel@tonic-gate * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 38*0Sstevel@tonic-gate * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 39*0Sstevel@tonic-gate * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 40*0Sstevel@tonic-gate * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 41*0Sstevel@tonic-gate * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 42*0Sstevel@tonic-gate * SUCH DAMAGE. 43*0Sstevel@tonic-gate */ 44*0Sstevel@tonic-gate 45*0Sstevel@tonic-gate #ifndef lint 46*0Sstevel@tonic-gate static char sccsid[] = "@(#)ring.c 8.1 (Berkeley) 6/6/93"; 47*0Sstevel@tonic-gate #endif /* not lint */ 48*0Sstevel@tonic-gate 49*0Sstevel@tonic-gate /* 50*0Sstevel@tonic-gate * This defines a structure for a ring buffer. 51*0Sstevel@tonic-gate * 52*0Sstevel@tonic-gate * The circular buffer has two parts: 53*0Sstevel@tonic-gate * ((( 54*0Sstevel@tonic-gate * full: [consume, supply) 55*0Sstevel@tonic-gate * empty: [supply, consume) 56*0Sstevel@tonic-gate * ]]] 57*0Sstevel@tonic-gate * 58*0Sstevel@tonic-gate */ 59*0Sstevel@tonic-gate 60*0Sstevel@tonic-gate #include <stdio.h> 61*0Sstevel@tonic-gate #include <errno.h> 62*0Sstevel@tonic-gate #include <string.h> 63*0Sstevel@tonic-gate 64*0Sstevel@tonic-gate #include <sys/types.h> 65*0Sstevel@tonic-gate #include <sys/socket.h> 66*0Sstevel@tonic-gate #include <sys/sysmacros.h> 67*0Sstevel@tonic-gate 68*0Sstevel@tonic-gate #include "ring.h" 69*0Sstevel@tonic-gate #include "general.h" 70*0Sstevel@tonic-gate 71*0Sstevel@tonic-gate 72*0Sstevel@tonic-gate #define ring_subtract(d, a, b) (((a)-(b) >= 0)? \ 73*0Sstevel@tonic-gate (a)-(b): (((a)-(b))+(d)->size)) 74*0Sstevel@tonic-gate 75*0Sstevel@tonic-gate #define ring_increment(d, a, c) (((a)+(c) < (d)->top)? \ 76*0Sstevel@tonic-gate (a)+(c) : (((a)+(c))-(d)->size)) 77*0Sstevel@tonic-gate 78*0Sstevel@tonic-gate #define ring_decrement(d, a, c) (((a)-(c) >= (d)->bottom)? \ 79*0Sstevel@tonic-gate (a)-(c) : (((a)-(c))-(d)->size)) 80*0Sstevel@tonic-gate 81*0Sstevel@tonic-gate 82*0Sstevel@tonic-gate /* 83*0Sstevel@tonic-gate * The following is a clock, used to determine full, empty, etc. 84*0Sstevel@tonic-gate * 85*0Sstevel@tonic-gate * There is some trickiness here. Since the ring buffers are initialized 86*0Sstevel@tonic-gate * to ZERO on allocation, we need to make sure, when interpreting the 87*0Sstevel@tonic-gate * clock, that when the times are EQUAL, then the buffer is FULL. 88*0Sstevel@tonic-gate */ 89*0Sstevel@tonic-gate ulong_t ring_clock = 0; 90*0Sstevel@tonic-gate 91*0Sstevel@tonic-gate 92*0Sstevel@tonic-gate #define ring_empty(d) (((d)->consume == (d)->supply) && \ 93*0Sstevel@tonic-gate ((d)->consumetime >= (d)->supplytime)) 94*0Sstevel@tonic-gate #define ring_full(d) (((d)->supply == (d)->consume) && \ 95*0Sstevel@tonic-gate ((d)->supplytime > (d)->consumetime)) 96*0Sstevel@tonic-gate 97*0Sstevel@tonic-gate 98*0Sstevel@tonic-gate 99*0Sstevel@tonic-gate 100*0Sstevel@tonic-gate 101*0Sstevel@tonic-gate /* Buffer state transition routines */ 102*0Sstevel@tonic-gate 103*0Sstevel@tonic-gate ring_init(ring, buffer, count) 104*0Sstevel@tonic-gate Ring *ring; 105*0Sstevel@tonic-gate unsigned char *buffer; 106*0Sstevel@tonic-gate int count; 107*0Sstevel@tonic-gate { 108*0Sstevel@tonic-gate (void) memset(ring, 0, sizeof (*ring)); 109*0Sstevel@tonic-gate 110*0Sstevel@tonic-gate ring->size = count; 111*0Sstevel@tonic-gate 112*0Sstevel@tonic-gate ring->supply = ring->consume = ring->bottom = buffer; 113*0Sstevel@tonic-gate 114*0Sstevel@tonic-gate ring->top = ring->bottom+ring->size; 115*0Sstevel@tonic-gate 116*0Sstevel@tonic-gate ring->clearto = 0; 117*0Sstevel@tonic-gate 118*0Sstevel@tonic-gate return (1); 119*0Sstevel@tonic-gate } 120*0Sstevel@tonic-gate 121*0Sstevel@tonic-gate /* Mark routines */ 122*0Sstevel@tonic-gate 123*0Sstevel@tonic-gate /* 124*0Sstevel@tonic-gate * Mark the most recently supplied byte. 125*0Sstevel@tonic-gate */ 126*0Sstevel@tonic-gate 127*0Sstevel@tonic-gate void 128*0Sstevel@tonic-gate ring_mark(ring) 129*0Sstevel@tonic-gate Ring *ring; 130*0Sstevel@tonic-gate { 131*0Sstevel@tonic-gate ring->mark = ring_decrement(ring, ring->supply, 1); 132*0Sstevel@tonic-gate } 133*0Sstevel@tonic-gate 134*0Sstevel@tonic-gate /* 135*0Sstevel@tonic-gate * Is the ring pointing to the mark? 136*0Sstevel@tonic-gate */ 137*0Sstevel@tonic-gate 138*0Sstevel@tonic-gate int 139*0Sstevel@tonic-gate ring_at_mark(ring) 140*0Sstevel@tonic-gate Ring *ring; 141*0Sstevel@tonic-gate { 142*0Sstevel@tonic-gate if (ring->mark == ring->consume) { 143*0Sstevel@tonic-gate return (1); 144*0Sstevel@tonic-gate } else { 145*0Sstevel@tonic-gate return (0); 146*0Sstevel@tonic-gate } 147*0Sstevel@tonic-gate } 148*0Sstevel@tonic-gate 149*0Sstevel@tonic-gate /* 150*0Sstevel@tonic-gate * Clear any mark set on the ring. 151*0Sstevel@tonic-gate */ 152*0Sstevel@tonic-gate 153*0Sstevel@tonic-gate void 154*0Sstevel@tonic-gate ring_clear_mark(ring) 155*0Sstevel@tonic-gate Ring *ring; 156*0Sstevel@tonic-gate { 157*0Sstevel@tonic-gate ring->mark = 0; 158*0Sstevel@tonic-gate } 159*0Sstevel@tonic-gate 160*0Sstevel@tonic-gate /* 161*0Sstevel@tonic-gate * Add characters from current segment to ring buffer. 162*0Sstevel@tonic-gate */ 163*0Sstevel@tonic-gate void 164*0Sstevel@tonic-gate ring_supplied(ring, count) 165*0Sstevel@tonic-gate Ring *ring; 166*0Sstevel@tonic-gate int count; 167*0Sstevel@tonic-gate { 168*0Sstevel@tonic-gate ring->supply = ring_increment(ring, ring->supply, count); 169*0Sstevel@tonic-gate ring->supplytime = ++ring_clock; 170*0Sstevel@tonic-gate } 171*0Sstevel@tonic-gate 172*0Sstevel@tonic-gate /* 173*0Sstevel@tonic-gate * We have just consumed "c" bytes. 174*0Sstevel@tonic-gate */ 175*0Sstevel@tonic-gate void 176*0Sstevel@tonic-gate ring_consumed(ring, count) 177*0Sstevel@tonic-gate Ring *ring; 178*0Sstevel@tonic-gate int count; 179*0Sstevel@tonic-gate { 180*0Sstevel@tonic-gate if (count == 0) /* don't update anything */ 181*0Sstevel@tonic-gate return; 182*0Sstevel@tonic-gate 183*0Sstevel@tonic-gate if (ring->mark && 184*0Sstevel@tonic-gate (ring_subtract(ring, ring->mark, ring->consume) < count)) { 185*0Sstevel@tonic-gate ring->mark = 0; 186*0Sstevel@tonic-gate } 187*0Sstevel@tonic-gate 188*0Sstevel@tonic-gate if (ring->consume < ring->clearto && 189*0Sstevel@tonic-gate ring->clearto <= ring->consume + count) 190*0Sstevel@tonic-gate ring->clearto = 0; 191*0Sstevel@tonic-gate else if (ring->consume + count > ring->top && 192*0Sstevel@tonic-gate ring->bottom <= ring->clearto && 193*0Sstevel@tonic-gate ring->bottom + ((ring->consume + count) - ring->top)) 194*0Sstevel@tonic-gate ring->clearto = 0; 195*0Sstevel@tonic-gate 196*0Sstevel@tonic-gate ring->consume = ring_increment(ring, ring->consume, count); 197*0Sstevel@tonic-gate ring->consumetime = ++ring_clock; 198*0Sstevel@tonic-gate /* 199*0Sstevel@tonic-gate * Try to encourage "ring_empty_consecutive()" to be large. 200*0Sstevel@tonic-gate */ 201*0Sstevel@tonic-gate if (ring_empty(ring)) { 202*0Sstevel@tonic-gate ring->consume = ring->supply = ring->bottom; 203*0Sstevel@tonic-gate } 204*0Sstevel@tonic-gate } 205*0Sstevel@tonic-gate 206*0Sstevel@tonic-gate 207*0Sstevel@tonic-gate 208*0Sstevel@tonic-gate /* Buffer state query routines */ 209*0Sstevel@tonic-gate 210*0Sstevel@tonic-gate 211*0Sstevel@tonic-gate /* Number of bytes that may be supplied */ 212*0Sstevel@tonic-gate int 213*0Sstevel@tonic-gate ring_empty_count(ring) 214*0Sstevel@tonic-gate Ring *ring; 215*0Sstevel@tonic-gate { 216*0Sstevel@tonic-gate if (ring_empty(ring)) { /* if empty */ 217*0Sstevel@tonic-gate return (ring->size); 218*0Sstevel@tonic-gate } else { 219*0Sstevel@tonic-gate return (ring_subtract(ring, ring->consume, ring->supply)); 220*0Sstevel@tonic-gate } 221*0Sstevel@tonic-gate } 222*0Sstevel@tonic-gate 223*0Sstevel@tonic-gate /* number of CONSECUTIVE bytes that may be supplied */ 224*0Sstevel@tonic-gate int 225*0Sstevel@tonic-gate ring_empty_consecutive(ring) 226*0Sstevel@tonic-gate Ring *ring; 227*0Sstevel@tonic-gate { 228*0Sstevel@tonic-gate if ((ring->consume < ring->supply) || ring_empty(ring)) { 229*0Sstevel@tonic-gate /* 230*0Sstevel@tonic-gate * if consume is "below" supply, or empty, then 231*0Sstevel@tonic-gate * return distance to the top 232*0Sstevel@tonic-gate */ 233*0Sstevel@tonic-gate return (ring_subtract(ring, ring->top, ring->supply)); 234*0Sstevel@tonic-gate } else { 235*0Sstevel@tonic-gate /* 236*0Sstevel@tonic-gate * else, return what we may. 237*0Sstevel@tonic-gate */ 238*0Sstevel@tonic-gate return (ring_subtract(ring, ring->consume, ring->supply)); 239*0Sstevel@tonic-gate } 240*0Sstevel@tonic-gate } 241*0Sstevel@tonic-gate 242*0Sstevel@tonic-gate /* 243*0Sstevel@tonic-gate * Return the number of bytes that are available for consuming 244*0Sstevel@tonic-gate * (but don't give more than enough to get to cross over set mark) 245*0Sstevel@tonic-gate */ 246*0Sstevel@tonic-gate 247*0Sstevel@tonic-gate int 248*0Sstevel@tonic-gate ring_full_count(ring) 249*0Sstevel@tonic-gate Ring *ring; 250*0Sstevel@tonic-gate { 251*0Sstevel@tonic-gate if ((ring->mark == 0) || (ring->mark == ring->consume)) { 252*0Sstevel@tonic-gate if (ring_full(ring)) { 253*0Sstevel@tonic-gate return (ring->size); /* nothing consumed, but full */ 254*0Sstevel@tonic-gate } else { 255*0Sstevel@tonic-gate return (ring_subtract(ring, ring->supply, 256*0Sstevel@tonic-gate ring->consume)); 257*0Sstevel@tonic-gate } 258*0Sstevel@tonic-gate } else { 259*0Sstevel@tonic-gate return (ring_subtract(ring, ring->mark, ring->consume)); 260*0Sstevel@tonic-gate } 261*0Sstevel@tonic-gate } 262*0Sstevel@tonic-gate 263*0Sstevel@tonic-gate /* 264*0Sstevel@tonic-gate * Return the number of CONSECUTIVE bytes available for consuming. 265*0Sstevel@tonic-gate * However, don't return more than enough to cross over set mark. 266*0Sstevel@tonic-gate */ 267*0Sstevel@tonic-gate int 268*0Sstevel@tonic-gate ring_full_consecutive(ring) 269*0Sstevel@tonic-gate Ring *ring; 270*0Sstevel@tonic-gate { 271*0Sstevel@tonic-gate if ((ring->mark == 0) || (ring->mark == ring->consume)) { 272*0Sstevel@tonic-gate if ((ring->supply < ring->consume) || ring_full(ring)) { 273*0Sstevel@tonic-gate return (ring_subtract(ring, ring->top, ring->consume)); 274*0Sstevel@tonic-gate } else { 275*0Sstevel@tonic-gate return (ring_subtract(ring, ring->supply, 276*0Sstevel@tonic-gate ring->consume)); 277*0Sstevel@tonic-gate } 278*0Sstevel@tonic-gate } else { 279*0Sstevel@tonic-gate if (ring->mark < ring->consume) { 280*0Sstevel@tonic-gate return (ring_subtract(ring, ring->top, ring->consume)); 281*0Sstevel@tonic-gate } else { /* Else, distance to mark */ 282*0Sstevel@tonic-gate return (ring_subtract(ring, ring->mark, ring->consume)); 283*0Sstevel@tonic-gate } 284*0Sstevel@tonic-gate } 285*0Sstevel@tonic-gate } 286*0Sstevel@tonic-gate 287*0Sstevel@tonic-gate /* 288*0Sstevel@tonic-gate * Move data into the "supply" portion of of the ring buffer. 289*0Sstevel@tonic-gate */ 290*0Sstevel@tonic-gate void 291*0Sstevel@tonic-gate ring_supply_data(ring, buffer, count) 292*0Sstevel@tonic-gate Ring *ring; 293*0Sstevel@tonic-gate unsigned char *buffer; 294*0Sstevel@tonic-gate int count; 295*0Sstevel@tonic-gate { 296*0Sstevel@tonic-gate int i; 297*0Sstevel@tonic-gate 298*0Sstevel@tonic-gate while (count) { 299*0Sstevel@tonic-gate i = MIN(count, ring_empty_consecutive(ring)); 300*0Sstevel@tonic-gate (void) memcpy(ring->supply, buffer, i); 301*0Sstevel@tonic-gate ring_supplied(ring, i); 302*0Sstevel@tonic-gate count -= i; 303*0Sstevel@tonic-gate buffer += i; 304*0Sstevel@tonic-gate } 305*0Sstevel@tonic-gate } 306*0Sstevel@tonic-gate 307*0Sstevel@tonic-gate #ifdef notdef 308*0Sstevel@tonic-gate 309*0Sstevel@tonic-gate /* 310*0Sstevel@tonic-gate * Move data from the "consume" portion of the ring buffer 311*0Sstevel@tonic-gate */ 312*0Sstevel@tonic-gate void 313*0Sstevel@tonic-gate ring_consume_data(ring, buffer, count) 314*0Sstevel@tonic-gate Ring *ring; 315*0Sstevel@tonic-gate unsigned char *buffer; 316*0Sstevel@tonic-gate int count; 317*0Sstevel@tonic-gate { 318*0Sstevel@tonic-gate int i; 319*0Sstevel@tonic-gate 320*0Sstevel@tonic-gate while (count) { 321*0Sstevel@tonic-gate i = MIN(count, ring_full_consecutive(ring)); 322*0Sstevel@tonic-gate memcpy(buffer, ring->consume, i); 323*0Sstevel@tonic-gate ring_consumed(ring, i); 324*0Sstevel@tonic-gate count -= i; 325*0Sstevel@tonic-gate buffer += i; 326*0Sstevel@tonic-gate } 327*0Sstevel@tonic-gate } 328*0Sstevel@tonic-gate #endif 329*0Sstevel@tonic-gate 330*0Sstevel@tonic-gate void 331*0Sstevel@tonic-gate ring_encrypt(ring, encryptor) 332*0Sstevel@tonic-gate Ring *ring; 333*0Sstevel@tonic-gate void (*encryptor)(); 334*0Sstevel@tonic-gate { 335*0Sstevel@tonic-gate unsigned char *s, *c; 336*0Sstevel@tonic-gate 337*0Sstevel@tonic-gate if (ring_empty(ring) || ring->clearto == ring->supply) 338*0Sstevel@tonic-gate return; 339*0Sstevel@tonic-gate 340*0Sstevel@tonic-gate if ((c = ring->clearto) == NULL) 341*0Sstevel@tonic-gate c = ring->consume; 342*0Sstevel@tonic-gate 343*0Sstevel@tonic-gate s = ring->supply; 344*0Sstevel@tonic-gate 345*0Sstevel@tonic-gate if (s <= c) { 346*0Sstevel@tonic-gate (*encryptor)(c, ring->top - c); 347*0Sstevel@tonic-gate (*encryptor)(ring->bottom, s - ring->bottom); 348*0Sstevel@tonic-gate } else 349*0Sstevel@tonic-gate (*encryptor)(c, s - c); 350*0Sstevel@tonic-gate 351*0Sstevel@tonic-gate ring->clearto = ring->supply; 352*0Sstevel@tonic-gate } 353*0Sstevel@tonic-gate 354*0Sstevel@tonic-gate void 355*0Sstevel@tonic-gate ring_clearto(ring) 356*0Sstevel@tonic-gate Ring *ring; 357*0Sstevel@tonic-gate { 358*0Sstevel@tonic-gate if (!ring_empty(ring)) 359*0Sstevel@tonic-gate ring->clearto = ring->supply; 360*0Sstevel@tonic-gate else 361*0Sstevel@tonic-gate ring->clearto = 0; 362*0Sstevel@tonic-gate } 363