468 lines
15 KiB
C
468 lines
15 KiB
C
/*
|
|
* Simple Network Management Protocol (RFC 1067).
|
|
*
|
|
*/
|
|
/**********************************************************************
|
|
Copyright 1988, 1989, 1991, 1992 by Carnegie Mellon University
|
|
|
|
All Rights Reserved
|
|
|
|
Permission to use, copy, modify, and distribute this software and its
|
|
documentation for any purpose and without fee is hereby granted,
|
|
provided that the above copyright notice appear in all copies and that
|
|
both that copyright notice and this permission notice appear in
|
|
supporting documentation, and that the name of CMU not be
|
|
used in advertising or publicity pertaining to distribution of the
|
|
software without specific, written prior permission.
|
|
|
|
CMU DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
|
|
ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
|
|
CMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
|
|
ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
|
|
WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
|
|
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
|
|
SOFTWARE.
|
|
******************************************************************/
|
|
|
|
#include <net-snmp/net-snmp-config.h>
|
|
#include <ctype.h>
|
|
|
|
#ifdef KINETICS
|
|
#include "gw.h"
|
|
#include "ab.h"
|
|
#include "inet.h"
|
|
#include "fp4/cmdmacro.h"
|
|
#include "fp4/pbuf.h"
|
|
#include "glob.h"
|
|
#endif
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
|
|
#include <sys/types.h>
|
|
#ifdef HAVE_STRING_H
|
|
#include <string.h>
|
|
#else
|
|
#include <strings.h>
|
|
#endif
|
|
#if HAVE_NETINET_IN_H
|
|
#include <netinet/in.h>
|
|
#endif
|
|
#ifdef HAVE_SYS_SELECT_H
|
|
#include <sys/select.h>
|
|
#endif
|
|
#ifndef NULL
|
|
#define NULL 0
|
|
#endif
|
|
|
|
#if HAVE_DMALLOC_H
|
|
#include <dmalloc.h>
|
|
#endif
|
|
|
|
#ifdef vms
|
|
#include <in.h>
|
|
#endif
|
|
|
|
#include <net-snmp/types.h>
|
|
#include <net-snmp/output_api.h>
|
|
|
|
#include <net-snmp/library/asn1.h>
|
|
#include <net-snmp/library/snmp.h> /* for "internal" definitions */
|
|
#include <net-snmp/library/snmp_api.h>
|
|
#include <net-snmp/library/mib.h>
|
|
|
|
/** @mainpage Net-SNMP Coding Documentation
|
|
* @section Introduction
|
|
|
|
This is the Net-SNMP coding and API reference documentation. It is
|
|
incomplete, but when combined with the manual page set and
|
|
tutorials forms a pretty comprehensive starting point.
|
|
|
|
@section Starting out
|
|
|
|
The best places to start learning are the @e Net-SNMP @e tutorial
|
|
(http://www.Net-SNMP.org/tutorial-5/) and the @e Modules and @e
|
|
Examples sections of this document.
|
|
|
|
*/
|
|
|
|
void
|
|
xdump(const void * data, size_t length, const char *prefix)
|
|
{
|
|
const u_char * const cp = (const u_char*)data;
|
|
int col, count;
|
|
char *buffer;
|
|
#ifndef NETSNMP_DISABLE_DYNAMIC_LOG_LEVEL
|
|
int debug_log_level = netsnmp_get_debug_log_level();
|
|
#else
|
|
#define debug_log_level LOG_DEBUG
|
|
#endif /* NETSNMP_DISABLE_DYNAMIC_LOG_LEVEL */
|
|
|
|
buffer = (char *) malloc(strlen(prefix) + 80);
|
|
if (!buffer) {
|
|
snmp_log(LOG_NOTICE,
|
|
"xdump: malloc failed. packet-dump skipped\n");
|
|
return;
|
|
}
|
|
|
|
count = 0;
|
|
while (count < (int) length) {
|
|
strcpy(buffer, prefix);
|
|
sprintf(buffer + strlen(buffer), "%.4d: ", count);
|
|
|
|
for (col = 0; ((count + col) < (int) length) && col < 16; col++) {
|
|
sprintf(buffer + strlen(buffer), "%02X ", cp[count + col]);
|
|
if (col % 4 == 3)
|
|
strcat(buffer, " ");
|
|
}
|
|
for (; col < 16; col++) { /* pad end of buffer with zeros */
|
|
strcat(buffer, " ");
|
|
if (col % 4 == 3)
|
|
strcat(buffer, " ");
|
|
}
|
|
strcat(buffer, " ");
|
|
for (col = 0; ((count + col) < (int) length) && col < 16; col++) {
|
|
buffer[col + 60] =
|
|
isprint(cp[count + col]) ? cp[count + col] : '.';
|
|
}
|
|
buffer[col + 60] = '\n';
|
|
buffer[col + 60 + 1] = 0;
|
|
snmp_log(debug_log_level, "%s", buffer);
|
|
count += col;
|
|
}
|
|
snmp_log(debug_log_level, "\n");
|
|
free(buffer);
|
|
|
|
} /* end xdump() */
|
|
|
|
/*
|
|
* u_char * snmp_parse_var_op(
|
|
* u_char *data IN - pointer to the start of object
|
|
* oid *var_name OUT - object id of variable
|
|
* int *var_name_len IN/OUT - length of variable name
|
|
* u_char *var_val_type OUT - type of variable (int or octet string) (one byte)
|
|
* int *var_val_len OUT - length of variable
|
|
* u_char **var_val OUT - pointer to ASN1 encoded value of variable
|
|
* int *listlength IN/OUT - number of valid bytes left in var_op_list
|
|
*/
|
|
|
|
u_char *
|
|
snmp_parse_var_op(u_char * data,
|
|
oid * var_name,
|
|
size_t * var_name_len,
|
|
u_char * var_val_type,
|
|
size_t * var_val_len,
|
|
u_char ** var_val, size_t * listlength)
|
|
{
|
|
u_char var_op_type;
|
|
size_t var_op_len = *listlength;
|
|
u_char *var_op_start = data;
|
|
|
|
data = asn_parse_sequence(data, &var_op_len, &var_op_type,
|
|
(ASN_SEQUENCE | ASN_CONSTRUCTOR), "var_op");
|
|
if (data == NULL) {
|
|
/*
|
|
* msg detail is set
|
|
*/
|
|
return NULL;
|
|
}
|
|
DEBUGDUMPHEADER("recv", "Name");
|
|
data =
|
|
asn_parse_objid(data, &var_op_len, &var_op_type, var_name,
|
|
var_name_len);
|
|
DEBUGINDENTLESS();
|
|
if (data == NULL) {
|
|
ERROR_MSG("No OID for variable");
|
|
return NULL;
|
|
}
|
|
if (var_op_type !=
|
|
(u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_OBJECT_ID))
|
|
return NULL;
|
|
*var_val = data; /* save pointer to this object */
|
|
/*
|
|
* find out what type of object this is
|
|
*/
|
|
data = asn_parse_header(data, &var_op_len, var_val_type);
|
|
if (data == NULL) {
|
|
ERROR_MSG("No header for value");
|
|
return NULL;
|
|
}
|
|
/*
|
|
* XXX no check for type!
|
|
*/
|
|
*var_val_len = var_op_len;
|
|
data += var_op_len;
|
|
*listlength -= (int) (data - var_op_start);
|
|
return data;
|
|
}
|
|
|
|
/*
|
|
* u_char * snmp_build_var_op(
|
|
* u_char *data IN - pointer to the beginning of the output buffer
|
|
* oid *var_name IN - object id of variable
|
|
* int *var_name_len IN - length of object id
|
|
* u_char var_val_type IN - type of variable
|
|
* int var_val_len IN - length of variable
|
|
* u_char *var_val IN - value of variable
|
|
* int *listlength IN/OUT - number of valid bytes left in
|
|
* output buffer
|
|
*/
|
|
|
|
u_char *
|
|
snmp_build_var_op(u_char * data,
|
|
oid * var_name,
|
|
size_t * var_name_len,
|
|
u_char var_val_type,
|
|
size_t var_val_len,
|
|
u_char * var_val, size_t * listlength)
|
|
{
|
|
size_t dummyLen, headerLen;
|
|
u_char *dataPtr;
|
|
|
|
dummyLen = *listlength;
|
|
dataPtr = data;
|
|
#if 0
|
|
data = asn_build_sequence(data, &dummyLen,
|
|
(u_char) (ASN_SEQUENCE | ASN_CONSTRUCTOR),
|
|
0);
|
|
if (data == NULL) {
|
|
return NULL;
|
|
}
|
|
#endif
|
|
if (dummyLen < 4)
|
|
return NULL;
|
|
data += 4;
|
|
dummyLen -= 4;
|
|
|
|
headerLen = data - dataPtr;
|
|
*listlength -= headerLen;
|
|
DEBUGDUMPHEADER("send", "Name");
|
|
data = asn_build_objid(data, listlength,
|
|
(u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE |
|
|
ASN_OBJECT_ID), var_name,
|
|
*var_name_len);
|
|
DEBUGINDENTLESS();
|
|
if (data == NULL) {
|
|
ERROR_MSG("Can't build OID for variable");
|
|
return NULL;
|
|
}
|
|
DEBUGDUMPHEADER("send", "Value");
|
|
switch (var_val_type) {
|
|
case ASN_INTEGER:
|
|
data = asn_build_int(data, listlength, var_val_type,
|
|
(long *) var_val, var_val_len);
|
|
break;
|
|
case ASN_GAUGE:
|
|
case ASN_COUNTER:
|
|
case ASN_TIMETICKS:
|
|
case ASN_UINTEGER:
|
|
data = asn_build_unsigned_int(data, listlength, var_val_type,
|
|
(u_long *) var_val, var_val_len);
|
|
break;
|
|
#ifdef NETSNMP_WITH_OPAQUE_SPECIAL_TYPES
|
|
case ASN_OPAQUE_COUNTER64:
|
|
case ASN_OPAQUE_U64:
|
|
#endif
|
|
case ASN_COUNTER64:
|
|
data = asn_build_unsigned_int64(data, listlength, var_val_type,
|
|
(struct counter64 *) var_val,
|
|
var_val_len);
|
|
break;
|
|
case ASN_OCTET_STR:
|
|
case ASN_IPADDRESS:
|
|
case ASN_OPAQUE:
|
|
case ASN_NSAP:
|
|
data = asn_build_string(data, listlength, var_val_type,
|
|
var_val, var_val_len);
|
|
break;
|
|
case ASN_OBJECT_ID:
|
|
data = asn_build_objid(data, listlength, var_val_type,
|
|
(oid *) var_val, var_val_len / sizeof(oid));
|
|
break;
|
|
case ASN_NULL:
|
|
data = asn_build_null(data, listlength, var_val_type);
|
|
break;
|
|
case ASN_BIT_STR:
|
|
data = asn_build_bitstring(data, listlength, var_val_type,
|
|
var_val, var_val_len);
|
|
break;
|
|
case SNMP_NOSUCHOBJECT:
|
|
case SNMP_NOSUCHINSTANCE:
|
|
case SNMP_ENDOFMIBVIEW:
|
|
data = asn_build_null(data, listlength, var_val_type);
|
|
break;
|
|
#ifdef NETSNMP_WITH_OPAQUE_SPECIAL_TYPES
|
|
case ASN_OPAQUE_FLOAT:
|
|
data = asn_build_float(data, listlength, var_val_type,
|
|
(float *) var_val, var_val_len);
|
|
break;
|
|
case ASN_OPAQUE_DOUBLE:
|
|
data = asn_build_double(data, listlength, var_val_type,
|
|
(double *) var_val, var_val_len);
|
|
break;
|
|
case ASN_OPAQUE_I64:
|
|
data = asn_build_signed_int64(data, listlength, var_val_type,
|
|
(struct counter64 *) var_val,
|
|
var_val_len);
|
|
break;
|
|
#endif /* NETSNMP_WITH_OPAQUE_SPECIAL_TYPES */
|
|
default:
|
|
{
|
|
char error_buf[64];
|
|
snprintf(error_buf, sizeof(error_buf),
|
|
"wrong type in snmp_build_var_op: %d", var_val_type);
|
|
ERROR_MSG(error_buf);
|
|
data = NULL;
|
|
}
|
|
}
|
|
DEBUGINDENTLESS();
|
|
if (data == NULL) {
|
|
return NULL;
|
|
}
|
|
dummyLen = (data - dataPtr) - headerLen;
|
|
|
|
asn_build_sequence(dataPtr, &dummyLen,
|
|
(u_char) (ASN_SEQUENCE | ASN_CONSTRUCTOR),
|
|
dummyLen);
|
|
return data;
|
|
}
|
|
|
|
#ifdef NETSNMP_USE_REVERSE_ASNENCODING
|
|
int
|
|
snmp_realloc_rbuild_var_op(u_char ** pkt, size_t * pkt_len,
|
|
size_t * offset, int allow_realloc,
|
|
const oid * var_name, size_t * var_name_len,
|
|
u_char var_val_type,
|
|
u_char * var_val, size_t var_val_len)
|
|
{
|
|
size_t start_offset = *offset;
|
|
int rc = 0;
|
|
|
|
/*
|
|
* Encode the value.
|
|
*/
|
|
DEBUGDUMPHEADER("send", "Value");
|
|
|
|
switch (var_val_type) {
|
|
case ASN_INTEGER:
|
|
rc = asn_realloc_rbuild_int(pkt, pkt_len, offset, allow_realloc,
|
|
var_val_type, (long *) var_val,
|
|
var_val_len);
|
|
break;
|
|
|
|
case ASN_GAUGE:
|
|
case ASN_COUNTER:
|
|
case ASN_TIMETICKS:
|
|
case ASN_UINTEGER:
|
|
rc = asn_realloc_rbuild_unsigned_int(pkt, pkt_len, offset,
|
|
allow_realloc, var_val_type,
|
|
(u_long *) var_val,
|
|
var_val_len);
|
|
break;
|
|
|
|
#ifdef NETSNMP_WITH_OPAQUE_SPECIAL_TYPES
|
|
case ASN_OPAQUE_COUNTER64:
|
|
case ASN_OPAQUE_U64:
|
|
#endif
|
|
case ASN_COUNTER64:
|
|
rc = asn_realloc_rbuild_unsigned_int64(pkt, pkt_len, offset,
|
|
allow_realloc, var_val_type,
|
|
(struct counter64 *)
|
|
var_val, var_val_len);
|
|
break;
|
|
|
|
case ASN_OCTET_STR:
|
|
case ASN_IPADDRESS:
|
|
case ASN_OPAQUE:
|
|
case ASN_NSAP:
|
|
rc = asn_realloc_rbuild_string(pkt, pkt_len, offset, allow_realloc,
|
|
var_val_type, var_val, var_val_len);
|
|
break;
|
|
|
|
case ASN_OBJECT_ID:
|
|
rc = asn_realloc_rbuild_objid(pkt, pkt_len, offset, allow_realloc,
|
|
var_val_type, (oid *) var_val,
|
|
var_val_len / sizeof(oid));
|
|
break;
|
|
|
|
case ASN_NULL:
|
|
rc = asn_realloc_rbuild_null(pkt, pkt_len, offset, allow_realloc,
|
|
var_val_type);
|
|
break;
|
|
|
|
case ASN_BIT_STR:
|
|
rc = asn_realloc_rbuild_bitstring(pkt, pkt_len, offset,
|
|
allow_realloc, var_val_type,
|
|
var_val, var_val_len);
|
|
break;
|
|
|
|
case SNMP_NOSUCHOBJECT:
|
|
case SNMP_NOSUCHINSTANCE:
|
|
case SNMP_ENDOFMIBVIEW:
|
|
rc = asn_realloc_rbuild_null(pkt, pkt_len, offset, allow_realloc,
|
|
var_val_type);
|
|
break;
|
|
|
|
#ifdef NETSNMP_WITH_OPAQUE_SPECIAL_TYPES
|
|
case ASN_OPAQUE_FLOAT:
|
|
rc = asn_realloc_rbuild_float(pkt, pkt_len, offset, allow_realloc,
|
|
var_val_type, (float *) var_val,
|
|
var_val_len);
|
|
break;
|
|
|
|
case ASN_OPAQUE_DOUBLE:
|
|
rc = asn_realloc_rbuild_double(pkt, pkt_len, offset, allow_realloc,
|
|
var_val_type, (double *) var_val,
|
|
var_val_len);
|
|
break;
|
|
|
|
case ASN_OPAQUE_I64:
|
|
rc = asn_realloc_rbuild_signed_int64(pkt, pkt_len, offset,
|
|
allow_realloc, var_val_type,
|
|
(struct counter64 *) var_val,
|
|
var_val_len);
|
|
break;
|
|
#endif /* NETSNMP_WITH_OPAQUE_SPECIAL_TYPES */
|
|
default:
|
|
{
|
|
char error_buf[64];
|
|
snprintf(error_buf, sizeof(error_buf),
|
|
"wrong type in snmp_realloc_rbuild_var_op: %d", var_val_type);
|
|
ERROR_MSG(error_buf);
|
|
rc = 0;
|
|
}
|
|
}
|
|
DEBUGINDENTLESS();
|
|
|
|
if (rc == 0) {
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* Build the OID.
|
|
*/
|
|
|
|
DEBUGDUMPHEADER("send", "Name");
|
|
rc = asn_realloc_rbuild_objid(pkt, pkt_len, offset, allow_realloc,
|
|
(u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE |
|
|
ASN_OBJECT_ID), var_name,
|
|
*var_name_len);
|
|
DEBUGINDENTLESS();
|
|
if (rc == 0) {
|
|
ERROR_MSG("Can't build OID for variable");
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* Build the sequence header.
|
|
*/
|
|
|
|
rc = asn_realloc_rbuild_sequence(pkt, pkt_len, offset, allow_realloc,
|
|
(u_char) (ASN_SEQUENCE |
|
|
ASN_CONSTRUCTOR),
|
|
*offset - start_offset);
|
|
return rc;
|
|
}
|
|
|
|
#endif /* NETSNMP_USE_REVERSE_ASNENCODING */
|