10Sstevel@tonic-gate /*
2*9600SNobutomo.Nakano@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
30Sstevel@tonic-gate * Use is subject to license terms.
40Sstevel@tonic-gate */
50Sstevel@tonic-gate /*
60Sstevel@tonic-gate * Author: Tatu Ylonen <ylo@cs.hut.fi>
70Sstevel@tonic-gate * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
80Sstevel@tonic-gate * All rights reserved
90Sstevel@tonic-gate * Auxiliary functions for storing and retrieving various data types to/from
100Sstevel@tonic-gate * Buffers.
110Sstevel@tonic-gate *
120Sstevel@tonic-gate * As far as I am concerned, the code I have written for this software
130Sstevel@tonic-gate * can be used freely for any purpose. Any derived versions of this
140Sstevel@tonic-gate * software must be clearly marked as such, and if the derived work is
150Sstevel@tonic-gate * incompatible with the protocol description in the RFC file, it must be
160Sstevel@tonic-gate * called by a name other than "ssh" or "Secure Shell".
170Sstevel@tonic-gate *
180Sstevel@tonic-gate *
190Sstevel@tonic-gate * SSH2 packet format added by Markus Friedl
200Sstevel@tonic-gate * Copyright (c) 2000 Markus Friedl. All rights reserved.
210Sstevel@tonic-gate *
220Sstevel@tonic-gate * Redistribution and use in source and binary forms, with or without
230Sstevel@tonic-gate * modification, are permitted provided that the following conditions
240Sstevel@tonic-gate * are met:
250Sstevel@tonic-gate * 1. Redistributions of source code must retain the above copyright
260Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer.
270Sstevel@tonic-gate * 2. Redistributions in binary form must reproduce the above copyright
280Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer in the
290Sstevel@tonic-gate * documentation and/or other materials provided with the distribution.
300Sstevel@tonic-gate *
310Sstevel@tonic-gate * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
320Sstevel@tonic-gate * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
330Sstevel@tonic-gate * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
340Sstevel@tonic-gate * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
350Sstevel@tonic-gate * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
360Sstevel@tonic-gate * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
370Sstevel@tonic-gate * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
380Sstevel@tonic-gate * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
390Sstevel@tonic-gate * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
400Sstevel@tonic-gate * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
410Sstevel@tonic-gate */
420Sstevel@tonic-gate
430Sstevel@tonic-gate #include "includes.h"
440Sstevel@tonic-gate RCSID("$OpenBSD: bufaux.c,v 1.27 2002/06/26 08:53:12 markus Exp $");
450Sstevel@tonic-gate
460Sstevel@tonic-gate #include <langinfo.h>
470Sstevel@tonic-gate #include <openssl/bn.h>
480Sstevel@tonic-gate #include "bufaux.h"
490Sstevel@tonic-gate #include "xmalloc.h"
500Sstevel@tonic-gate #include "getput.h"
510Sstevel@tonic-gate #include "log.h"
520Sstevel@tonic-gate #include "g11n.h"
530Sstevel@tonic-gate
540Sstevel@tonic-gate /*
550Sstevel@tonic-gate * Stores an BIGNUM in the buffer with a 2-byte msb first bit count, followed
560Sstevel@tonic-gate * by (bits+7)/8 bytes of binary data, msb first.
570Sstevel@tonic-gate */
582757Sjp161948 int
buffer_put_bignum_ret(Buffer * buffer,const BIGNUM * value)592757Sjp161948 buffer_put_bignum_ret(Buffer *buffer, const BIGNUM *value)
600Sstevel@tonic-gate {
610Sstevel@tonic-gate int bits = BN_num_bits(value);
620Sstevel@tonic-gate int bin_size = (bits + 7) / 8;
630Sstevel@tonic-gate u_char *buf = xmalloc(bin_size);
640Sstevel@tonic-gate int oi;
650Sstevel@tonic-gate char msg[2];
660Sstevel@tonic-gate
670Sstevel@tonic-gate /* Get the value of in binary */
680Sstevel@tonic-gate oi = BN_bn2bin(value, buf);
692757Sjp161948 if (oi != bin_size) {
702757Sjp161948 error("buffer_put_bignum_ret: BN_bn2bin() failed: oi %d != bin_size %d",
710Sstevel@tonic-gate oi, bin_size);
722757Sjp161948 xfree(buf);
732757Sjp161948 return (-1);
742757Sjp161948 }
750Sstevel@tonic-gate
760Sstevel@tonic-gate /* Store the number of bits in the buffer in two bytes, msb first. */
770Sstevel@tonic-gate PUT_16BIT(msg, bits);
780Sstevel@tonic-gate buffer_append(buffer, msg, 2);
790Sstevel@tonic-gate /* Store the binary data. */
800Sstevel@tonic-gate buffer_append(buffer, (char *)buf, oi);
810Sstevel@tonic-gate
820Sstevel@tonic-gate memset(buf, 0, bin_size);
830Sstevel@tonic-gate xfree(buf);
842757Sjp161948
852757Sjp161948 return (0);
862757Sjp161948 }
872757Sjp161948
882757Sjp161948 void
buffer_put_bignum(Buffer * buffer,const BIGNUM * value)892757Sjp161948 buffer_put_bignum(Buffer *buffer, const BIGNUM *value)
902757Sjp161948 {
912757Sjp161948 if (buffer_put_bignum_ret(buffer, value) == -1)
922757Sjp161948 fatal("buffer_put_bignum: buffer error");
930Sstevel@tonic-gate }
940Sstevel@tonic-gate
950Sstevel@tonic-gate /*
960Sstevel@tonic-gate * Retrieves an BIGNUM from the buffer.
970Sstevel@tonic-gate */
982757Sjp161948 int
buffer_get_bignum_ret(Buffer * buffer,BIGNUM * value)992757Sjp161948 buffer_get_bignum_ret(Buffer *buffer, BIGNUM *value)
1000Sstevel@tonic-gate {
1012757Sjp161948 u_int bits, bytes;
1020Sstevel@tonic-gate u_char buf[2], *bin;
1030Sstevel@tonic-gate
1040Sstevel@tonic-gate /* Get the number for bits. */
1052757Sjp161948 if (buffer_get_ret(buffer, (char *) buf, 2) == -1) {
1062757Sjp161948 error("buffer_get_bignum_ret: invalid length");
1072757Sjp161948 return (-1);
1082757Sjp161948 }
1090Sstevel@tonic-gate bits = GET_16BIT(buf);
1100Sstevel@tonic-gate /* Compute the number of binary bytes that follow. */
1110Sstevel@tonic-gate bytes = (bits + 7) / 8;
1122757Sjp161948 if (bytes > 8 * 1024) {
1132757Sjp161948 error("buffer_get_bignum_ret: cannot handle BN of size %d", bytes);
1142757Sjp161948 return (-1);
1152757Sjp161948 }
1162757Sjp161948 if (buffer_len(buffer) < bytes) {
1172757Sjp161948 error("buffer_get_bignum_ret: input buffer too small");
1182757Sjp161948 return (-1);
1192757Sjp161948 }
1200Sstevel@tonic-gate bin = buffer_ptr(buffer);
1210Sstevel@tonic-gate BN_bin2bn(bin, bytes, value);
1222757Sjp161948 if (buffer_consume_ret(buffer, bytes) == -1) {
1232757Sjp161948 error("buffer_get_bignum_ret: buffer_consume failed");
1242757Sjp161948 return (-1);
1252757Sjp161948 }
1262757Sjp161948 return (0);
1272757Sjp161948 }
1282757Sjp161948
1292757Sjp161948 void
buffer_get_bignum(Buffer * buffer,BIGNUM * value)1302757Sjp161948 buffer_get_bignum(Buffer *buffer, BIGNUM *value)
1312757Sjp161948 {
1322757Sjp161948 if (buffer_get_bignum_ret(buffer, value) == -1)
1332757Sjp161948 fatal("buffer_get_bignum: buffer error");
1340Sstevel@tonic-gate }
1350Sstevel@tonic-gate
1360Sstevel@tonic-gate /*
1370Sstevel@tonic-gate * Stores an BIGNUM in the buffer in SSH2 format.
1380Sstevel@tonic-gate */
1392757Sjp161948 int
buffer_put_bignum2_ret(Buffer * buffer,const BIGNUM * value)1402757Sjp161948 buffer_put_bignum2_ret(Buffer *buffer, const BIGNUM *value)
1410Sstevel@tonic-gate {
1422757Sjp161948 u_int bytes;
1432757Sjp161948 u_char *buf;
1440Sstevel@tonic-gate int oi;
1452757Sjp161948 u_int hasnohigh = 0;
1460Sstevel@tonic-gate
1472757Sjp161948 if (BN_is_zero(value)) {
1482757Sjp161948 buffer_put_int(buffer, 0);
1492757Sjp161948 return 0;
1502757Sjp161948 }
1512757Sjp161948 if (value->neg) {
1522757Sjp161948 error("buffer_put_bignum2_ret: negative numbers not supported");
1532757Sjp161948 return (-1);
1542757Sjp161948 }
1552757Sjp161948 bytes = BN_num_bytes(value) + 1; /* extra padding byte */
1562757Sjp161948 if (bytes < 2) {
1572757Sjp161948 error("buffer_put_bignum2_ret: BN too small");
1582757Sjp161948 return (-1);
1592757Sjp161948 }
1602757Sjp161948 buf = xmalloc(bytes);
1612757Sjp161948 buf[0] = 0x00;
1620Sstevel@tonic-gate /* Get the value of in binary */
1630Sstevel@tonic-gate oi = BN_bn2bin(value, buf+1);
1642757Sjp161948 if (oi < 0 || (u_int)oi != bytes - 1) {
1652757Sjp161948 error("buffer_put_bignum2_ret: BN_bn2bin() failed: "
1662757Sjp161948 "oi %d != bin_size %d", oi, bytes);
1672757Sjp161948 xfree(buf);
1682757Sjp161948 return (-1);
1692757Sjp161948 }
1700Sstevel@tonic-gate hasnohigh = (buf[1] & 0x80) ? 0 : 1;
1710Sstevel@tonic-gate buffer_put_string(buffer, buf+hasnohigh, bytes-hasnohigh);
1720Sstevel@tonic-gate memset(buf, 0, bytes);
1730Sstevel@tonic-gate xfree(buf);
1742757Sjp161948 return (0);
1752757Sjp161948 }
1762757Sjp161948
1772757Sjp161948 void
buffer_put_bignum2(Buffer * buffer,const BIGNUM * value)1782757Sjp161948 buffer_put_bignum2(Buffer *buffer, const BIGNUM *value)
1792757Sjp161948 {
1802757Sjp161948 if (buffer_put_bignum2_ret(buffer, value) == -1)
1812757Sjp161948 fatal("buffer_put_bignum2: buffer error");
1820Sstevel@tonic-gate }
1830Sstevel@tonic-gate
1840Sstevel@tonic-gate /* XXX does not handle negative BNs */
1852757Sjp161948 int
buffer_get_bignum2_ret(Buffer * buffer,BIGNUM * value)1862757Sjp161948 buffer_get_bignum2_ret(Buffer *buffer, BIGNUM *value)
1872757Sjp161948 {
1882757Sjp161948 u_int len;
1892757Sjp161948 u_char *bin;
1902757Sjp161948
1912757Sjp161948 if ((bin = buffer_get_string_ret(buffer, &len)) == NULL) {
1922757Sjp161948 error("buffer_get_bignum2_ret: invalid bignum");
1932757Sjp161948 return (-1);
1942757Sjp161948 }
1952757Sjp161948
1962757Sjp161948 if (len > 0 && (bin[0] & 0x80)) {
1972757Sjp161948 error("buffer_get_bignum2_ret: negative numbers not supported");
1982757Sjp161948 xfree(bin);
1992757Sjp161948 return (-1);
2002757Sjp161948 }
2012757Sjp161948 if (len > 8 * 1024) {
2022757Sjp161948 error("buffer_get_bignum2_ret: cannot handle BN of size %d", len);
2032757Sjp161948 xfree(bin);
2042757Sjp161948 return (-1);
2052757Sjp161948 }
2062757Sjp161948 BN_bin2bn(bin, len, value);
2072757Sjp161948 xfree(bin);
2082757Sjp161948 return (0);
2092757Sjp161948 }
2102757Sjp161948
2110Sstevel@tonic-gate void
buffer_get_bignum2(Buffer * buffer,BIGNUM * value)2120Sstevel@tonic-gate buffer_get_bignum2(Buffer *buffer, BIGNUM *value)
2130Sstevel@tonic-gate {
2142757Sjp161948 if (buffer_get_bignum2_ret(buffer, value) == -1)
2152757Sjp161948 fatal("buffer_get_bignum2: buffer error");
2162757Sjp161948 }
2170Sstevel@tonic-gate
2180Sstevel@tonic-gate /*
2190Sstevel@tonic-gate * Returns integers from the buffer (msb first).
2200Sstevel@tonic-gate */
2210Sstevel@tonic-gate
2222757Sjp161948 int
buffer_get_short_ret(u_short * ret,Buffer * buffer)2232757Sjp161948 buffer_get_short_ret(u_short *ret, Buffer *buffer)
2242757Sjp161948 {
2252757Sjp161948 u_char buf[2];
2262757Sjp161948
2272757Sjp161948 if (buffer_get_ret(buffer, (char *) buf, 2) == -1)
2282757Sjp161948 return (-1);
2292757Sjp161948 *ret = GET_16BIT(buf);
2302757Sjp161948 return (0);
2312757Sjp161948 }
2322757Sjp161948
2330Sstevel@tonic-gate u_short
buffer_get_short(Buffer * buffer)2340Sstevel@tonic-gate buffer_get_short(Buffer *buffer)
2350Sstevel@tonic-gate {
2362757Sjp161948 u_short ret;
2372757Sjp161948
2382757Sjp161948 if (buffer_get_short_ret(&ret, buffer) == -1)
2392757Sjp161948 fatal("buffer_get_short: buffer error");
2402757Sjp161948
2412757Sjp161948 return (ret);
2422757Sjp161948 }
2430Sstevel@tonic-gate
2442757Sjp161948 int
buffer_get_int_ret(u_int * ret,Buffer * buffer)2452757Sjp161948 buffer_get_int_ret(u_int *ret, Buffer *buffer)
2462757Sjp161948 {
2472757Sjp161948 u_char buf[4];
2482757Sjp161948
2492757Sjp161948 if (buffer_get_ret(buffer, (char *) buf, 4) == -1)
2502757Sjp161948 return (-1);
2512757Sjp161948 *ret = GET_32BIT(buf);
2522757Sjp161948 return (0);
2530Sstevel@tonic-gate }
2540Sstevel@tonic-gate
2550Sstevel@tonic-gate u_int
buffer_get_int(Buffer * buffer)2560Sstevel@tonic-gate buffer_get_int(Buffer *buffer)
2570Sstevel@tonic-gate {
2582757Sjp161948 u_int ret;
2590Sstevel@tonic-gate
2602757Sjp161948 if (buffer_get_int_ret(&ret, buffer) == -1)
2612757Sjp161948 fatal("buffer_get_int: buffer error");
2622757Sjp161948
2632757Sjp161948 return (ret);
2640Sstevel@tonic-gate }
2650Sstevel@tonic-gate
2660Sstevel@tonic-gate #ifdef HAVE_U_INT64_T
2672757Sjp161948 int
buffer_get_int64_ret(u_int64_t * ret,Buffer * buffer)2682757Sjp161948 buffer_get_int64_ret(u_int64_t *ret, Buffer *buffer)
2692757Sjp161948 {
2702757Sjp161948 u_char buf[8];
2712757Sjp161948
2722757Sjp161948 if (buffer_get_ret(buffer, (char *) buf, 8) == -1)
2732757Sjp161948 return (-1);
2742757Sjp161948 *ret = GET_64BIT(buf);
2752757Sjp161948 return (0);
2762757Sjp161948 }
2772757Sjp161948
2780Sstevel@tonic-gate u_int64_t
buffer_get_int64(Buffer * buffer)2790Sstevel@tonic-gate buffer_get_int64(Buffer *buffer)
2800Sstevel@tonic-gate {
2812757Sjp161948 u_int64_t ret;
2820Sstevel@tonic-gate
2832757Sjp161948 if (buffer_get_int64_ret(&ret, buffer) == -1)
2842757Sjp161948 fatal("buffer_get_int: buffer error");
2852757Sjp161948
2862757Sjp161948 return (ret);
2870Sstevel@tonic-gate }
2880Sstevel@tonic-gate #endif
2890Sstevel@tonic-gate
2900Sstevel@tonic-gate /*
2910Sstevel@tonic-gate * Stores integers in the buffer, msb first.
2920Sstevel@tonic-gate */
2930Sstevel@tonic-gate void
buffer_put_short(Buffer * buffer,u_short value)2940Sstevel@tonic-gate buffer_put_short(Buffer *buffer, u_short value)
2950Sstevel@tonic-gate {
2960Sstevel@tonic-gate char buf[2];
2970Sstevel@tonic-gate
2980Sstevel@tonic-gate PUT_16BIT(buf, value);
2990Sstevel@tonic-gate buffer_append(buffer, buf, 2);
3000Sstevel@tonic-gate }
3010Sstevel@tonic-gate
3020Sstevel@tonic-gate void
buffer_put_int(Buffer * buffer,u_int value)3030Sstevel@tonic-gate buffer_put_int(Buffer *buffer, u_int value)
3040Sstevel@tonic-gate {
3050Sstevel@tonic-gate char buf[4];
3060Sstevel@tonic-gate
3070Sstevel@tonic-gate PUT_32BIT(buf, value);
3080Sstevel@tonic-gate buffer_append(buffer, buf, 4);
3090Sstevel@tonic-gate }
3100Sstevel@tonic-gate
3110Sstevel@tonic-gate #ifdef HAVE_U_INT64_T
3120Sstevel@tonic-gate void
buffer_put_int64(Buffer * buffer,u_int64_t value)3130Sstevel@tonic-gate buffer_put_int64(Buffer *buffer, u_int64_t value)
3140Sstevel@tonic-gate {
3150Sstevel@tonic-gate char buf[8];
3160Sstevel@tonic-gate
3170Sstevel@tonic-gate PUT_64BIT(buf, value);
3180Sstevel@tonic-gate buffer_append(buffer, buf, 8);
3190Sstevel@tonic-gate }
3200Sstevel@tonic-gate #endif
3210Sstevel@tonic-gate
3220Sstevel@tonic-gate /*
3230Sstevel@tonic-gate * Returns an arbitrary binary string from the buffer. The string cannot
3240Sstevel@tonic-gate * be longer than 256k. The returned value points to memory allocated
3250Sstevel@tonic-gate * with xmalloc; it is the responsibility of the calling function to free
3260Sstevel@tonic-gate * the data. If length_ptr is non-NULL, the length of the returned data
3270Sstevel@tonic-gate * will be stored there. A null character will be automatically appended
3280Sstevel@tonic-gate * to the returned string, and is not counted in length.
3290Sstevel@tonic-gate */
3300Sstevel@tonic-gate void *
buffer_get_string_ret(Buffer * buffer,u_int * length_ptr)3312757Sjp161948 buffer_get_string_ret(Buffer *buffer, u_int *length_ptr)
3320Sstevel@tonic-gate {
3330Sstevel@tonic-gate u_char *value;
3340Sstevel@tonic-gate u_int len;
3350Sstevel@tonic-gate
3360Sstevel@tonic-gate /* Get the length. */
3370Sstevel@tonic-gate len = buffer_get_int(buffer);
3382757Sjp161948 if (len > 256 * 1024) {
3392757Sjp161948 error("buffer_get_string_ret: bad string length %u", len);
3402757Sjp161948 return (NULL);
3412757Sjp161948 }
3420Sstevel@tonic-gate /* Allocate space for the string. Add one byte for a null character. */
3430Sstevel@tonic-gate value = xmalloc(len + 1);
3440Sstevel@tonic-gate /* Get the string. */
3452757Sjp161948 if (buffer_get_ret(buffer, value, len) == -1) {
3462757Sjp161948 error("buffer_get_string_ret: buffer_get failed");
3472757Sjp161948 xfree(value);
3482757Sjp161948 return (NULL);
3492757Sjp161948 }
3500Sstevel@tonic-gate /* Append a null character to make processing easier. */
3510Sstevel@tonic-gate value[len] = 0;
3520Sstevel@tonic-gate /* Optionally return the length of the string. */
3530Sstevel@tonic-gate if (length_ptr)
3540Sstevel@tonic-gate *length_ptr = len;
3552757Sjp161948 return (value);
3560Sstevel@tonic-gate }
3572757Sjp161948
3582757Sjp161948 void *
buffer_get_string(Buffer * buffer,u_int * length_ptr)3592757Sjp161948 buffer_get_string(Buffer *buffer, u_int *length_ptr)
3602757Sjp161948 {
3612757Sjp161948 void *ret;
3622757Sjp161948
3632757Sjp161948 if ((ret = buffer_get_string_ret(buffer, length_ptr)) == NULL)
3642757Sjp161948 fatal("buffer_get_string: buffer error");
3652757Sjp161948 return (ret);
3662757Sjp161948 }
3672757Sjp161948
3680Sstevel@tonic-gate char *
buffer_get_utf8_string(Buffer * buffer,uint_t * length_ptr)369*9600SNobutomo.Nakano@Sun.COM buffer_get_utf8_string(Buffer *buffer, uint_t *length_ptr)
3700Sstevel@tonic-gate {
371*9600SNobutomo.Nakano@Sun.COM char *value, *converted, *estr;
372*9600SNobutomo.Nakano@Sun.COM uint_t len;
3730Sstevel@tonic-gate
374*9600SNobutomo.Nakano@Sun.COM if ((value = buffer_get_string(buffer, &len)) == NULL)
375*9600SNobutomo.Nakano@Sun.COM return (value);
3760Sstevel@tonic-gate
377*9600SNobutomo.Nakano@Sun.COM converted = g11n_convert_from_utf8(value, &len, &estr);
378*9600SNobutomo.Nakano@Sun.COM if (converted == NULL) {
379*9600SNobutomo.Nakano@Sun.COM if (estr != NULL)
380*9600SNobutomo.Nakano@Sun.COM error("invalid UTF-8 sequence: %s", estr);
381*9600SNobutomo.Nakano@Sun.COM converted = value;
382*9600SNobutomo.Nakano@Sun.COM } else {
383*9600SNobutomo.Nakano@Sun.COM xfree(value);
3840Sstevel@tonic-gate }
3850Sstevel@tonic-gate
386*9600SNobutomo.Nakano@Sun.COM if (length_ptr != NULL)
387*9600SNobutomo.Nakano@Sun.COM *length_ptr = len;
3880Sstevel@tonic-gate
389*9600SNobutomo.Nakano@Sun.COM return (converted);
3900Sstevel@tonic-gate }
3910Sstevel@tonic-gate
3920Sstevel@tonic-gate /*
3930Sstevel@tonic-gate * Stores and arbitrary binary string in the buffer.
3940Sstevel@tonic-gate */
3950Sstevel@tonic-gate void
buffer_put_string(Buffer * buffer,const void * buf,u_int len)3960Sstevel@tonic-gate buffer_put_string(Buffer *buffer, const void *buf, u_int len)
3970Sstevel@tonic-gate {
3980Sstevel@tonic-gate buffer_put_int(buffer, len);
3990Sstevel@tonic-gate buffer_append(buffer, buf, len);
4000Sstevel@tonic-gate }
4010Sstevel@tonic-gate void
buffer_put_cstring(Buffer * buffer,const char * s)4020Sstevel@tonic-gate buffer_put_cstring(Buffer *buffer, const char *s)
4030Sstevel@tonic-gate {
4040Sstevel@tonic-gate if (s == NULL)
4050Sstevel@tonic-gate fatal("buffer_put_cstring: s == NULL");
4060Sstevel@tonic-gate buffer_put_string(buffer, s, strlen(s));
4070Sstevel@tonic-gate }
4080Sstevel@tonic-gate
4090Sstevel@tonic-gate /*
4100Sstevel@tonic-gate * UTF-8 versions of the above.
4110Sstevel@tonic-gate */
4120Sstevel@tonic-gate void
buffer_put_utf8_string(Buffer * buffer,const char * s,uint_t len)413*9600SNobutomo.Nakano@Sun.COM buffer_put_utf8_string(Buffer *buffer, const char *s, uint_t len)
4140Sstevel@tonic-gate {
415*9600SNobutomo.Nakano@Sun.COM char *converted, *estr;
416*9600SNobutomo.Nakano@Sun.COM uint_t nlen = len;
4170Sstevel@tonic-gate
418*9600SNobutomo.Nakano@Sun.COM converted = g11n_convert_to_utf8(s, &nlen, 0, &estr);
419*9600SNobutomo.Nakano@Sun.COM if (converted == NULL) {
420*9600SNobutomo.Nakano@Sun.COM if (estr != NULL)
421*9600SNobutomo.Nakano@Sun.COM error("Can't convert to UTF-8: %s", estr);
422*9600SNobutomo.Nakano@Sun.COM converted = (char *)s;
423*9600SNobutomo.Nakano@Sun.COM }
4240Sstevel@tonic-gate
425*9600SNobutomo.Nakano@Sun.COM buffer_put_string(buffer, converted, nlen);
4260Sstevel@tonic-gate
427*9600SNobutomo.Nakano@Sun.COM if (converted != s)
428*9600SNobutomo.Nakano@Sun.COM xfree(converted);
4290Sstevel@tonic-gate }
4300Sstevel@tonic-gate
431*9600SNobutomo.Nakano@Sun.COM void
buffer_put_utf8_cstring(Buffer * buffer,const char * s)432*9600SNobutomo.Nakano@Sun.COM buffer_put_utf8_cstring(Buffer *buffer, const char *s)
433*9600SNobutomo.Nakano@Sun.COM {
434*9600SNobutomo.Nakano@Sun.COM buffer_put_utf8_string(buffer, s, strlen(s));
435*9600SNobutomo.Nakano@Sun.COM }
4360Sstevel@tonic-gate
4370Sstevel@tonic-gate /*
4380Sstevel@tonic-gate * Returns a character from the buffer (0 - 255).
4390Sstevel@tonic-gate */
4400Sstevel@tonic-gate int
buffer_get_char_ret(char * ret,Buffer * buffer)4412757Sjp161948 buffer_get_char_ret(char *ret, Buffer *buffer)
4422757Sjp161948 {
4432757Sjp161948 if (buffer_get_ret(buffer, ret, 1) == -1) {
4442757Sjp161948 error("buffer_get_char_ret: buffer_get_ret failed");
4452757Sjp161948 return (-1);
4462757Sjp161948 }
4472757Sjp161948 return (0);
4482757Sjp161948 }
4492757Sjp161948
4502757Sjp161948 int
buffer_get_char(Buffer * buffer)4510Sstevel@tonic-gate buffer_get_char(Buffer *buffer)
4520Sstevel@tonic-gate {
4530Sstevel@tonic-gate char ch;
4540Sstevel@tonic-gate
4552757Sjp161948 if (buffer_get_char_ret(&ch, buffer) == -1)
4562757Sjp161948 fatal("buffer_get_char: buffer error");
4570Sstevel@tonic-gate return (u_char) ch;
4580Sstevel@tonic-gate }
4590Sstevel@tonic-gate
4600Sstevel@tonic-gate /*
4610Sstevel@tonic-gate * Stores a character in the buffer.
4620Sstevel@tonic-gate */
4630Sstevel@tonic-gate void
buffer_put_char(Buffer * buffer,int value)4640Sstevel@tonic-gate buffer_put_char(Buffer *buffer, int value)
4650Sstevel@tonic-gate {
4660Sstevel@tonic-gate char ch = value;
4670Sstevel@tonic-gate
4680Sstevel@tonic-gate buffer_append(buffer, &ch, 1);
4690Sstevel@tonic-gate }
470