view usr/src/cmd/picl/plugins/sun4v/lib/snmp/debug.c @ 3941:328be6a20f20

FWARC/2007/133 SNMP Domain Service FWARC/2007/138 Updates to PRI structures 6438074 customer requests ability to query power/fan status info from OS 6526169 prtdiag output doesn't have Memory Configuration Information 6531453 sun4v picl needs device labels in the devtree 6534449 Unable to send a domain services message larger than 4K
author venki
date Sat, 31 Mar 2007 18:24:05 -0700
parents
children
line wrap: on
line source

/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License (the "License").
 * You may not use this file except in compliance with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */

/*
 * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

#pragma ident	"%Z%%M%	%I%	%E% SMI"

#ifdef SNMP_DEBUG

/*
 * Debug routines
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <thread.h>
#include <synch.h>
#include <ctype.h>
#include <sys/types.h>
#include "asn1.h"
#include "pdu.h"
#include "snmplib.h"
#include "debug.h"

/*
 * Buffer and line limits
 */
#define	SNMP_DBLOCK_SZ		4096
#define	SNMP_DMAX_LINE		80
#define	SNMP_NCHARS_IN_A_ROW	16

/*
 * Debug flags
 */
#define	SNMP_DEBUG_CMD		0x01
#define	SNMP_DEBUG_VAR		0x02
#define	SNMP_DEBUG_PDU		0x04
#define	SNMP_DEBUG_ASN		0x08
#define	SNMP_DEBUG_PKT		0x10
#define	SNMP_DEBUG_IO		0x20

#define	SNMP_DEBUG_DEFAULT	0x15	/* cmd, pdu, pkt */
#define	SNMP_DEBUG_EXTENDED	0x35	/* cmd, pdu, pkt, io */
#define	SNMP_DEBUG_ALL		0x3f

/*
 * Formatting aids
 */
#define	SNMP_DCMD_INDENT	2
#define	SNMP_DVAR_INDENT	4
#define	SNMP_DPDU_INDENT	6
#define	SNMP_DASN_INDENT	8
#define	SNMP_DPKT_INDENT	10
#define	SNMP_DIO_INDENT		12

#define	SNMP_DHDR_PREFIX	(const char *)" ___ "
#define	SNMP_DHDR_SUFFIX	(const char *)" ___"
#define	SNMP_DTEXT_PREFIX	(const char *)"| "

/*
 * All debug vars are protected by a single lock
 */
static mutex_t	snmp_dbuf_lock;				/* debug lock */
static uint16_t	snmp_debug_flag = SNMP_DEBUG_EXTENDED;	/* debug flags */
static char	*snmp_dbuf = NULL;			/* the debug buffer */
static char	*snmp_dbuf_curp = NULL;			/* current dbuf index */
static char	*snmp_dbuf_tail = NULL;			/* current dbuf tail */
static int	snmp_dbuf_sz = 0;			/* current dbuf size */
static int	snmp_dbuf_overflow = 0;			/* no more memory */
static char	snmp_lbuf[SNMP_DMAX_LINE];		/* scratch space */

/*
 * Key-to-string
 */
typedef struct {
	int	key;
	char	*str;
} snmp_key_to_str_t;

static snmp_key_to_str_t snmp_cmds[] = {
	{ SNMP_MSG_GET, "SNMP_MSG_GET" },
	{ SNMP_MSG_GETNEXT, "SNMP_MSG_GETNEXT" },
	{ SNMP_MSG_RESPONSE, "SNMP_MSG_RESPONSE" },
	{ SNMP_MSG_SET, "SNMP_MSG_SET" },
	{ SNMP_MSG_TRAP, "SNMP_MSG_TRAP" },
	{ SNMP_MSG_GETBULK, "SNMP_MSG_GETBULK" },
	{ SNMP_MSG_INFORM, "SNMP_MSG_INFORM" },
	{ SNMP_MSG_TRAP2, "SNMP_MSG_TRAP2" },
	{ SNMP_MSG_REPORT, "SNMP_MSG_REPORT" }
};

static snmp_key_to_str_t snmp_vartypes[] = {
	{ ASN_BOOLEAN, "ASN_BOOLEAN" },
	{ ASN_INTEGER, "ASN_INTEGER" },
	{ ASN_BIT_STR, "ASN_BIT_STR" },
	{ ASN_OCTET_STR, "ASN_OCTET_STR" },
	{ ASN_NULL, "ASN_NULL" },
	{ ASN_OBJECT_ID, "ASN_OBJECT_ID" },
	{ ASN_SEQUENCE, "ASN_SEQUENCE" }
};

static snmp_key_to_str_t snmp_asnencodings[] = {
	{ SNMP_DASN_SEQUENCE, "ASN SEQUENCE" },
	{ SNMP_DASN_LENGTH, "ASN LENGTH" },
	{ SNMP_DASN_INT, "ASN INT" },
	{ SNMP_DASN_OCTET_STR, "ASN OCTET STR" },
	{ SNMP_DASN_OID, "ASN OBJECT ID" },
	{ SNMP_DASN_NULL, "ASN NULL" }
};

static char *debug_tags[] = {
	"SNMP Command Request",
	"Null Var",
	"Response Var",
	"Request PDU",
	"Response PDU",
	"Request Packet",
	"Response Packet",
	"WRITE",
	"IOCTL",
	"READ",
	"SENDTO",
	"RECVFROM"
};
static const int n_tags = sizeof (debug_tags) / sizeof (char *);

/*
 * Helpers
 */
static char	*snmp_cmdstr_lookup(int cmd);
static char	*snmp_vtypestr_lookup(int vtype);
static char	*snmp_asnencoding_lookup(int asnkey);
static void	snmp_get_dumpchars(uchar_t *abuf, uchar_t *p, int nchars);
static void	snmp_log_append(char *bufp);
static void	snmp_dbuf_realloc(void);

void
snmp_debug_init(void)
{
	(void) mutex_init(&snmp_dbuf_lock, USYNC_THREAD, NULL);

	(void) mutex_lock(&snmp_dbuf_lock);
	snmp_dbuf_realloc();
	if (snmp_dbuf == NULL)
		snmp_debug_flag = 0;	/* really tragic */
	(void) mutex_unlock(&snmp_dbuf_lock);
}

void
snmp_log_cmd(uint_t tag, int cmd, int n_oids, char *oidstr, int row)
{
	char	*cmdstr;
	int	i;

	if (oidstr == NULL)
		return;

	(void) mutex_lock(&snmp_dbuf_lock);

	if ((snmp_debug_flag & SNMP_DEBUG_CMD) == 0) {
		(void) mutex_unlock(&snmp_dbuf_lock);
		return;
	}

	snmp_log_append("\n");

	if (tag < n_tags) {
		(void) snprintf(snmp_lbuf, SNMP_DMAX_LINE, "%*c%s%s%s\n",
		    SNMP_DCMD_INDENT, ' ', SNMP_DHDR_PREFIX,
		    debug_tags[tag], SNMP_DHDR_SUFFIX);
		snmp_log_append(snmp_lbuf);
	}

	if ((cmdstr = snmp_cmdstr_lookup(cmd)) == NULL) {
		(void) snprintf(snmp_lbuf, SNMP_DMAX_LINE, "%*c%sCMD=%#x\n",
		    SNMP_DCMD_INDENT, ' ', SNMP_DTEXT_PREFIX, cmd);
	} else {
		(void) snprintf(snmp_lbuf, SNMP_DMAX_LINE, "%*c%s%s\n",
		    SNMP_DCMD_INDENT, ' ', SNMP_DTEXT_PREFIX, cmdstr);
	}
	snmp_log_append(snmp_lbuf);

	for (i = 0; i < n_oids; i++) {
		(void) snprintf(snmp_lbuf, SNMP_DMAX_LINE, "%*c%s  %s.%d\n",
		    SNMP_DCMD_INDENT, ' ', SNMP_DTEXT_PREFIX,
		    oidstr, row);
		snmp_log_append(snmp_lbuf);

		oidstr += strlen(oidstr) + 1;
	}

	(void) mutex_unlock(&snmp_dbuf_lock);
}

void
snmp_log_var(uint_t tag, pdu_varlist_t *vp)
{
	char	*vts;

	if (vp == NULL)
		return;

	(void) mutex_lock(&snmp_dbuf_lock);

	if ((snmp_debug_flag & SNMP_DEBUG_VAR) == 0) {
		(void) mutex_unlock(&snmp_dbuf_lock);
		return;
	}

	snmp_log_append("\n");

	if (tag < n_tags) {
		(void) snprintf(snmp_lbuf, SNMP_DMAX_LINE, "%*c%s%s%s\n",
		    SNMP_DVAR_INDENT, ' ', SNMP_DHDR_PREFIX,
		    debug_tags[tag], SNMP_DHDR_SUFFIX);
		snmp_log_append(snmp_lbuf);
	}

	(void) snprintf(snmp_lbuf, SNMP_DMAX_LINE, "%*c%snextvar = %#x\n",
	    SNMP_DVAR_INDENT, ' ', SNMP_DTEXT_PREFIX, vp->nextvar);
	snmp_log_append(snmp_lbuf);

	(void) snprintf(snmp_lbuf, SNMP_DMAX_LINE, "%*c%sname = %#x\n",
	    SNMP_DVAR_INDENT, ' ', SNMP_DTEXT_PREFIX, vp->name);
	snmp_log_append(snmp_lbuf);

	(void) snprintf(snmp_lbuf, SNMP_DMAX_LINE, "%*c%sname_len = %u\n",
	    SNMP_DVAR_INDENT, ' ', SNMP_DTEXT_PREFIX, vp->name_len);
	snmp_log_append(snmp_lbuf);

	(void) snprintf(snmp_lbuf, SNMP_DMAX_LINE, "%*c%sval.ptr = %#x\n",
	    SNMP_DVAR_INDENT, ' ', SNMP_DTEXT_PREFIX, vp->val.str);
	snmp_log_append(snmp_lbuf);

	(void) snprintf(snmp_lbuf, SNMP_DMAX_LINE, "%*c%sval_len = %u\n",
	    SNMP_DVAR_INDENT, ' ', SNMP_DTEXT_PREFIX, vp->val_len);
	snmp_log_append(snmp_lbuf);

	if ((vts = snmp_vtypestr_lookup(vp->type)) == NULL) {
		(void) snprintf(snmp_lbuf, SNMP_DMAX_LINE, "%*c%stype = %#x\n",
		    SNMP_DVAR_INDENT, ' ', SNMP_DTEXT_PREFIX, vp->type);
	} else {
		(void) snprintf(snmp_lbuf, SNMP_DMAX_LINE, "%*c%stype = %s\n",
		    SNMP_DVAR_INDENT, ' ', SNMP_DTEXT_PREFIX, vts);
	}
	snmp_log_append(snmp_lbuf);

	(void) mutex_unlock(&snmp_dbuf_lock);
}

void
snmp_log_pdu(uint_t tag, snmp_pdu_t *pdu)
{
	char	*cmdstr;

	if (pdu == NULL)
		return;

	(void) mutex_lock(&snmp_dbuf_lock);

	if ((snmp_debug_flag & SNMP_DEBUG_PDU) == 0) {
		(void) mutex_unlock(&snmp_dbuf_lock);
		return;
	}

	snmp_log_append("\n");

	if (tag < n_tags) {
		(void) snprintf(snmp_lbuf, SNMP_DMAX_LINE, "%*c%s%s%s\n",
		    SNMP_DPDU_INDENT, ' ', SNMP_DHDR_PREFIX,
		    debug_tags[tag], SNMP_DHDR_SUFFIX);
		snmp_log_append(snmp_lbuf);
	}

	(void) snprintf(snmp_lbuf, SNMP_DMAX_LINE, "%*c%sversion = %d\n",
	    SNMP_DPDU_INDENT, ' ', SNMP_DTEXT_PREFIX, pdu->version);
	snmp_log_append(snmp_lbuf);

	if (pdu->community) {
		(void) snprintf(snmp_lbuf, SNMP_DMAX_LINE,
		    "%*c%scommunity = %s\n", SNMP_DPDU_INDENT, ' ',
		    SNMP_DTEXT_PREFIX, pdu->community);
	} else {
		(void) snprintf(snmp_lbuf, SNMP_DMAX_LINE,
		    "%*c%scommunity = %#x\n", SNMP_DPDU_INDENT, ' ',
		    SNMP_DTEXT_PREFIX, pdu->community);
	}
	snmp_log_append(snmp_lbuf);

	(void) snprintf(snmp_lbuf, SNMP_DMAX_LINE, "%*c%scommunity_len = %u\n",
	    SNMP_DPDU_INDENT, ' ', SNMP_DTEXT_PREFIX, pdu->community_len);
	snmp_log_append(snmp_lbuf);

	if ((cmdstr = snmp_cmdstr_lookup(pdu->command)) == NULL) {
		(void) snprintf(snmp_lbuf, SNMP_DMAX_LINE,
		    "%*c%scommand = %#x\n", SNMP_DPDU_INDENT, ' ',
		    SNMP_DTEXT_PREFIX, pdu->command);
	} else {
		(void) snprintf(snmp_lbuf, SNMP_DMAX_LINE,
		    "%*c%scommand = %s\n", SNMP_DPDU_INDENT, ' ',
		    SNMP_DTEXT_PREFIX, cmdstr);
	}
	snmp_log_append(snmp_lbuf);

	(void) snprintf(snmp_lbuf, SNMP_DMAX_LINE, "%*c%sreqid = %d\n",
	    SNMP_DPDU_INDENT, ' ', SNMP_DTEXT_PREFIX, pdu->reqid);
	snmp_log_append(snmp_lbuf);

	(void) snprintf(snmp_lbuf, SNMP_DMAX_LINE,
	    "%*c%serrstat = %#x (non-repeaters)\n", SNMP_DPDU_INDENT, ' ',
	    SNMP_DTEXT_PREFIX, pdu->errstat);
	snmp_log_append(snmp_lbuf);

	(void) snprintf(snmp_lbuf, SNMP_DMAX_LINE,
	    "%*c%serrindex = %u (max-reps)\n", SNMP_DPDU_INDENT, ' ',
	    SNMP_DTEXT_PREFIX, pdu->errindex);
	snmp_log_append(snmp_lbuf);

	(void) snprintf(snmp_lbuf, SNMP_DMAX_LINE, "%*c%svars = %#x\n",
	    SNMP_DPDU_INDENT, ' ', SNMP_DTEXT_PREFIX, pdu->vars);
	snmp_log_append(snmp_lbuf);

	(void) snprintf(snmp_lbuf, SNMP_DMAX_LINE, "%*c%sreq_pkt = %#x\n",
	    SNMP_DPDU_INDENT, ' ', SNMP_DTEXT_PREFIX, pdu->req_pkt);
	snmp_log_append(snmp_lbuf);

	(void) snprintf(snmp_lbuf, SNMP_DMAX_LINE, "%*c%sreq_pktsz = %u\n",
	    SNMP_DPDU_INDENT, ' ', SNMP_DTEXT_PREFIX, pdu->req_pktsz);
	snmp_log_append(snmp_lbuf);

	(void) snprintf(snmp_lbuf, SNMP_DMAX_LINE, "%*c%sreply_pkt = %#x\n",
	    SNMP_DPDU_INDENT, ' ', SNMP_DTEXT_PREFIX, pdu->reply_pkt);
	snmp_log_append(snmp_lbuf);

	(void) snprintf(snmp_lbuf, SNMP_DMAX_LINE, "%*c%sreply_pktsz = %u\n",
	    SNMP_DPDU_INDENT, ' ', SNMP_DTEXT_PREFIX, pdu->reply_pktsz);
	snmp_log_append(snmp_lbuf);

	snmp_log_append("\n");

	(void) mutex_unlock(&snmp_dbuf_lock);
}

void
snmp_log_asn(int key, uchar_t *pkt, size_t pktsz)
{
	char	*p, *asnstr;
	int	i, len;
	size_t	nrows, nrem;

	if (pkt == NULL)
		return;

	(void) mutex_lock(&snmp_dbuf_lock);

	if ((snmp_debug_flag & SNMP_DEBUG_ASN) == 0) {
		(void) mutex_unlock(&snmp_dbuf_lock);
		return;
	}

	if ((asnstr = snmp_asnencoding_lookup(key)) == NULL) {
		(void) snprintf(snmp_lbuf, SNMP_DMAX_LINE, "%*c%sASNKEY=%#x\n",
		    SNMP_DASN_INDENT, ' ', SNMP_DTEXT_PREFIX, key);
	} else {
		(void) snprintf(snmp_lbuf, SNMP_DMAX_LINE, "%*c%s%s\n",
		    SNMP_DASN_INDENT, ' ', SNMP_DTEXT_PREFIX, asnstr);
	}
	snmp_log_append(snmp_lbuf);

	nrows = pktsz / 16;
	for (i = 0; i < nrows; i++) {
		(void) snprintf(snmp_lbuf, SNMP_DMAX_LINE, "%*c%s  "
		    "%02x %02x %02x %02x %02x %02x %02x %02x "
		    "%02x %02x %02x %02x %02x %02x %02x %02x\n",
		    SNMP_DASN_INDENT, ' ', SNMP_DTEXT_PREFIX,
		    pkt[0], pkt[1], pkt[2], pkt[3], pkt[4], pkt[5],
		    pkt[6], pkt[7], pkt[8], pkt[9], pkt[10], pkt[11],
		    pkt[12], pkt[13], pkt[14], pkt[15]);

		pkt += 16;
		snmp_log_append(snmp_lbuf);
	}

	(void) snprintf(snmp_lbuf, SNMP_DMAX_LINE, "%*c%s ",
	    SNMP_DASN_INDENT, ' ', SNMP_DTEXT_PREFIX);

	p = snmp_lbuf + SNMP_DASN_INDENT + strlen(SNMP_DTEXT_PREFIX) + 1;
	len = SNMP_DMAX_LINE - SNMP_DASN_INDENT - strlen(SNMP_DTEXT_PREFIX) - 1;

	nrem = pktsz % 16;
	for (i = 0; i < nrem; i++) {
		(void) snprintf(p, len, " %02x", pkt[i]);

		p += 3;
		len -= 3;
	}
	(void) snprintf(p, len, "\n");
	snmp_log_append(snmp_lbuf);

	(void) mutex_unlock(&snmp_dbuf_lock);
}

void
snmp_log_pkt(uint_t tag, uchar_t *pkt, size_t pktsz)
{
	uchar_t	ascii[SNMP_NCHARS_IN_A_ROW + 1];
	uchar_t	*p = pkt;
	char	*bufp;
	int	nrows, nrem;
	int	i, len;

	if (pkt == NULL)
		return;

	(void) mutex_lock(&snmp_dbuf_lock);

	if ((snmp_debug_flag & SNMP_DEBUG_PKT) == 0) {
		(void) mutex_unlock(&snmp_dbuf_lock);
		return;
	}

	snmp_log_append("\n");

	if (tag < n_tags) {
		(void) snprintf(snmp_lbuf, SNMP_DMAX_LINE, "%*c%s%s%s\n",
		    SNMP_DPKT_INDENT, ' ',
		    SNMP_DHDR_PREFIX, debug_tags[tag], SNMP_DHDR_SUFFIX);
		snmp_log_append(snmp_lbuf);
	}

	nrows = pktsz / SNMP_NCHARS_IN_A_ROW;
	nrem = pktsz % SNMP_NCHARS_IN_A_ROW;

	for (i = 0; i < nrows; i++) {
		snmp_get_dumpchars(ascii, p, SNMP_NCHARS_IN_A_ROW);
		(void) snprintf(snmp_lbuf, SNMP_DMAX_LINE, "%*c%s"
		    "%02x %02x %02x %02x %02x %02x %02x %02x "
		    "%02x %02x %02x %02x %02x %02x %02x %02x "
		    "%s\n",
		    SNMP_DPKT_INDENT, ' ', SNMP_DTEXT_PREFIX,
		    p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7],
		    p[8], p[9], p[10], p[11], p[12], p[13], p[14], p[15],
		    ascii);
		p += 16;

		snmp_log_append(snmp_lbuf);
	}

	(void) snprintf(snmp_lbuf, SNMP_DMAX_LINE, "%*c%s",
	    SNMP_DPKT_INDENT, ' ', SNMP_DTEXT_PREFIX);

	snmp_get_dumpchars(ascii, p, nrem);

	bufp = snmp_lbuf + SNMP_DPKT_INDENT + strlen(SNMP_DTEXT_PREFIX);
	len = SNMP_DMAX_LINE - SNMP_DPKT_INDENT + strlen(SNMP_DTEXT_PREFIX);
	for (i = 0; i < 16; i++) {
		if (i < nrem)
			(void) snprintf(bufp, len, "%02x ", p[i]);
		else
			(void) snprintf(bufp, len, "   ");

		bufp += 3;
		len -= 3;
	}
	(void) snprintf(bufp, len, "%s\n", ascii);
	snmp_log_append(snmp_lbuf);

	(void) mutex_unlock(&snmp_dbuf_lock);
}

void
snmp_log_io(uint_t tag, int a1, uint_t a2, uint_t a3)
{
	(void) mutex_lock(&snmp_dbuf_lock);

	if ((snmp_debug_flag & SNMP_DEBUG_IO) == 0) {
		(void) mutex_unlock(&snmp_dbuf_lock);
		return;
	}

	snmp_log_append("\n");

	if (tag < n_tags) {
		(void) snprintf(snmp_lbuf, SNMP_DMAX_LINE,
		    "%*c%s%s(%d, %#x, %#x)\n", SNMP_DIO_INDENT, ' ',
		    SNMP_DTEXT_PREFIX, debug_tags[tag], a1, a2, a3);
	} else {
		(void) snprintf(snmp_lbuf, SNMP_DMAX_LINE,
		    "%*c%s%#x(%d, %#x, %#x)\n", SNMP_DIO_INDENT, ' ',
		    SNMP_DTEXT_PREFIX, tag, a1, a2, a3);
	}

	snmp_log_append(snmp_lbuf);

	(void) mutex_unlock(&snmp_dbuf_lock);
}

static char *
snmp_cmdstr_lookup(int cmd)
{
	int	nelem = sizeof (snmp_cmds) / sizeof (snmp_key_to_str_t);
	int	i;

	for (i = 0; i < nelem; i++) {
		if (snmp_cmds[i].key == cmd)
			return (snmp_cmds[i].str);
	}

	return (NULL);
}

static char *
snmp_vtypestr_lookup(int vtype)
{
	int	nelem = sizeof (snmp_vartypes) / sizeof (snmp_key_to_str_t);
	int	i;

	for (i = 0; i < nelem; i++) {
		if (snmp_vartypes[i].key == vtype)
			return (snmp_vartypes[i].str);
	}

	return (NULL);
}

static char *
snmp_asnencoding_lookup(int asnkey)
{
	int	nelem = sizeof (snmp_asnencodings) / sizeof (snmp_key_to_str_t);
	int	i;

	for (i = 0; i < nelem; i++) {
		if (snmp_asnencodings[i].key == asnkey)
			return (snmp_asnencodings[i].str);
	}

	return (NULL);
}

static void
snmp_get_dumpchars(uchar_t *abuf, uchar_t *p, int nchars)
{
	int	i;

	if (nchars > SNMP_NCHARS_IN_A_ROW)
		nchars = SNMP_NCHARS_IN_A_ROW;

	abuf[nchars] = 0;
	for (i = 0; i < nchars; i++)
		abuf[i] = isprint(p[i]) ? p[i] : '.';
}

static void
snmp_log_append(char *bufp)
{
	int	len;

	len = strlen(bufp);
	if ((snmp_dbuf_curp + len) >= snmp_dbuf_tail)
		snmp_dbuf_realloc();

	(void) strcpy(snmp_dbuf_curp, bufp);

	snmp_dbuf_curp += len;
}

static void
snmp_dbuf_realloc(void)
{
	char	*p;
	size_t	offset = 0;
	size_t	count;

	count = snmp_dbuf_sz + SNMP_DBLOCK_SZ;
	if ((p = (char *)calloc(count, 1)) == NULL) {
		snmp_dbuf_overflow++;
		snmp_dbuf_curp = snmp_dbuf;
		return;
	}

	if (snmp_dbuf) {
		offset = snmp_dbuf_curp - snmp_dbuf;
		(void) memcpy(p, snmp_dbuf, snmp_dbuf_sz);
		free(snmp_dbuf);
	}

	snmp_dbuf = p;
	snmp_dbuf_sz += SNMP_DBLOCK_SZ;

	snmp_dbuf_curp = snmp_dbuf + offset;
	snmp_dbuf_tail = snmp_dbuf + snmp_dbuf_sz;
}

#endif