The agent side of the interface has to be integrated into individual
vendor implementations, many of which may have a unique
organizational structure in an attempt to address various performance
and storage constraints. This makes it infeasible to provide much
more than suggestions for SNMP agent implementers. Unfortunately,
this leaves room for a large amount of interpretation which can lead
to implementations that don't necessarily work they way they should-
-too much ambiguity can be a bad thing.
The following characteristics of an agent implementation are to be
considered mandatory:
DUPLICATE REGISTRATIONS
With this release of the protocol, order of registration is
significant. The last sub-agent to register a variable is the one
that is deemed to be authoritative. Variables implemented by the
base SNMP agent are considered to have been registered prior to any
sub-agent registrations. Thus sub-agents may re-implement support
for variables that were incorrectly implemented by a vendor.
AUTOMATIC DEREGISTRATION ON CLOSE
All SNMP DPI connections are carried over a stream connection. When
the connection is closed by the client (no matter what the cause),
the agent must automatically unregister all of the variables that
were registered by the sub-agent.
TIMELY RESPONSE CONSTRAINTS
A sub-agent must respond to a request in a timely fashion. In this
version of the protocol, we specify that a sub-agent must respond to
a request by the SNMP agent within 5 seconds. If the sub-agent does
not respond in time, the SNMP agent should terminate the connection
and unregister all of the variables that were previously registered
by the sub-agent in question.
NOTE: agent implementations that do not have access to a timer may
not be able to implement this. In that case, they leave themselves
open to being placed in a state where they are blocked forever if the
sub-agent malfunctions.
SUPPORT FOR MULTIPLE MIB VIEWS
Some agents allow different MIB views to be selected based on the
community name used. It is not the intention of this document to
pass judgement on the various approaches that have been proposed or
implemented, but instead merely to recognize the existence of
implementations that support this feature.
The point of this discussion is to specify clearly that objects
supported by an SNMP DPI sub-agent are to be registered under the MIB
view that was selected by the community name used in the SNMP GET
request that obtained the DPI_port value.
The SNMP DPI does not specify a reserved port, but instead sub-agents
bootstrap themselves by making an SNMP GET request for the DPI_port
variable. This variable represents the TCP port to which the sub-
agent should connect. It should be understood that there is no
reason why the SNMP agent cannot have several listens (passive opens)
active, each corresponding to a distinct MIB view. The port number
returned then would be different based on the community name used in
the SNMP GET request for the DPI_port variable.
CONSIDERATIONS FOR THE NEXT RELEASE
The SNMP DPI protocol makes provision for extension and parallel use
of potentially incompatible releases. The discussion above documents
the protocol as it is currently in use and has not discussed features
of interest that should be considered for a future revision.
UNREGISTER
For closure, an UNREGISTER request could be of use.
SUPPORT FOR ATOMIC SETS
The SNMP protocol [1] specifies that:
Each variable assignment specified by the SetRequest-PDU should be
effected as if simultaneously set with respect to all other
assignments specified in the same message.
The SNMP DPI has no provision for backing out a successfully
processed SET request if one of the subsequent variable assignments
fails. This omission is a reflection of several biases:
o the SNMP DPI was intended to be light-weight.
o a belief that the SNMP RFCprescribes semantics which are infeasible
to implement unless the range of applications is restricted.
It has been suggested that a new request, TEST_SET, be added to the
DPI protocol. Processing of a SET request would then be performed as
follows:
o all variables would be processed using TEST_SET unless any error
occurred. The subagents would verify that they could process the
request.
o if no error occurred, each of the variables would be reprocessed,
this time with a SET request.
A problem with such an approach is that it relies on the TEST_SET
operation to make an assertion that the request can be successfully
performed. If this is not possible, then it cannot be asserted that
the prescribed semantics will be provided. Such situations do exist,
for example, a SET request that causes the far-end channel service
unit to be looped up--one does not know if the operation will be
successful until it is performed.
SAMPLE SNMP DPI API IMPLEMENTATION
The following C language sources show an example implementation of
the SNMP DPI Application Programming Interface as it would be exposed
to the sub-agents.
SAMPLE SNMP DPI INCLUDE FILE
/* SNMP distributed program interface */
#define SNMP_DPI_GET 1
#define SNMP_DPI_GET_NEXT 2
#define SNMP_DPI_SET 3
#define SNMP_DPI_TRAP 4
#define SNMP_DPI_RESPONSE 5
#define SNMP_DPI_REGISTER 6
#define SNMP_DPI_PROTOCOL 2
#define SNMP_DPI_VERSION 1
#define SNMP_DPI_RELEASE 0
/* SNMP error codes from RFC1098 (1067) */
#define SNMP_NO_ERROR 0
#define SNMP_TOO_BIG 1
#define SNMP_NO_SUCH_NAME 2
#define SNMP_BAD_VALUE 3
#define SNMP_READ_ONLY 4
#define SNMP_GEN_ERR 5
/* variable types */
#define SNMP_TYPE_TEXT 0 /* textual representation */
#define SNMP_TYPE_NUMBER (128|1) /* number */
#define SNMP_TYPE_STRING 2 /* text string */
#define SNMP_TYPE_OBJECT 3 /* object identifier */
#define SNMP_TYPE_EMPTY 4 /* no value */
#define SNMP_TYPE_INTERNET (128|5) /* internet address */
#define SNMP_TYPE_COUNTER (128|6) /* counter */
#define SNMP_TYPE_GAUGE (128|7) /* gauge */
#define SNMP_TYPE_TICKS (128|8) /* time ticks (1/100th sec) */
#define SNMP_TYPE_MASK 0x7f /* mask for type */
struct dpi_get_packet {
char *object_id;
};
struct dpi_next_packet {
char *object_id;
char *group_id;
};
struct dpi_set_packet {
char *object_id;
unsigned char type;
unsigned short value_len;
char *value;
};
struct dpi_resp_packet {
unsigned char ret_code;
struct dpi_set_packet *ret_data;
};
struct dpi_trap_packet {
unsigned char generic;
unsigned char specific;
struct dpi_set_packet *info;
};
struct snmp_dpi_hdr {
unsigned char proto_major;
unsigned char proto_minor;
unsigned char proto_release;
unsigned char packet_type;
union {
struct dpi_get_packet *dpi_get;
struct dpi_next_packet *dpi_next;
struct dpi_set_packet *dpi_set;
struct dpi_resp_packet *dpi_response;
struct dpi_trap_packet *dpi_trap;
} packet_body;
};
extern struct snmp_dpi_hdr *pDPIpacket();
extern void fDPIparse();
extern unsigned char *mkMIBquery();
extern unsigned char *mkDPIregister();
extern unsigned char *mkDPIresponse();
extern unsigned char *mkDPItrap();
extern struct dpi_set_packet *mkDPIset();
SAMPLE QUERY_DPI_PORT() FUNCTION
#ifdef VM
#include <manifest.h>
#include <snmp_vm.h>
#include <bsdtime.h>
#include <bsdtypes.h>
#include <socket.h>
#include <in.h>
#include <netdb.h>
#include <inet.h>
#else
#include <sys/time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>
#endif
static unsigned char asn1_hdr[] = {0x30};
/* insert length of remaining packet, not including this */
static unsigned char version[] = {0x02, 0x01, 0x00, 0x04};
/* integer, len=1, value=0, string */
/* insert community name length and community name */
static unsigned char request[] = {
0xa0, 0x1b, /* get request, len=0x1b */
0x02, 0x01, 0x01, /* integer, len=1,request_id = 1 */
0x02, 0x01, 0x00, /* integer, len=1, error_status = 0 */
0x02, 0x01, 0x00, /* integer, len=1, error_index = 0 */
0x30, 0x10, /* varbind list, len=0x10 */
0x30, 0x0e, /* varbind , len=0x0e */
0x06, 0x0a, /* object ID, len=0x0a */
0x2b, 0x06, 0x01, 0x04, 0x01, 0x02, 0x02, 0x01, 0x01, 0x00,
0x05, 0x00 /* value, len = 0 */
};
static extract_DPI_port();
query_DPI_port(hostname, community_name)
char *hostname;
char *community_name;
{
int community_len;
int rc;
community_len = strlen(community_name);
rc = _query_DPI_port(hostname, community_name, community_len);
return (rc);
}
/* use if community_name has embedded nulls */
_query_DPI_port(hostname, community_name, community_len)
char *hostname;
char *community_name;
int community_len;
{
unsigned char packet[1024];
int packet_len;
int remaining_len;
int fd, rc, sock_len;
struct sockaddr_in sock, dest_sock;
struct timeval timeout;
unsigned long host_addr, read_mask;
int tries;
host_addr = lookup_host(hostname);
packet_len = 0;
bcopy(asn1_hdr, packet, sizeof(asn1_hdr));
packet_len += sizeof(asn1_hdr);
remaining_len = sizeof(version) + 1 +
community_len + sizeof(request);
packet[packet_len++] = remaining_len & 0xff;
bcopy(version, packet + packet_len, sizeof(version));
packet_len += sizeof(version);
packet[packet_len++] = community_len & 0xff;
bcopy(community_name, packet + packet_len, community_len);
packet_len += community_len;
bcopy(request, packet + packet_len, sizeof(request));
packet_len += sizeof(request);
fd = socket(AF_INET, SOCK_DGRAM, 0);
if (fd < 0) {
return (-1);
}
bzero(&sock, sizeof(sock));
sock.sin_family = AF_INET;
sock.sin_port = 0;
sock.sin_addr.s_addr = 0;
rc = bind(fd, &sock, sizeof(sock));
if (rc < 0)
return (-1);
timeout.tv_sec = 3;
timeout.tv_usec = 0;
bzero(&dest_sock, sizeof(dest_sock));
dest_sock.sin_family = AF_INET;
dest_sock.sin_port = htons(161);
dest_sock.sin_addr.s_addr = host_addr;
tries = 0;
while (++tries < 4) {
rc = sendto(fd, packet, packet_len, 0, &dest_sock,
sizeof(dest_sock));
read_mask = 1 << fd;
rc = select(read_mask + 1, &read_mask, 0, 0, &timeout);
if (rc <= 0)
continue;
sock_len = sizeof(dest_sock);
packet_len = recvfrom(fd, packet, sizeof(packet), 0,
&dest_sock, &sock_len);
if (packet_len <= 0) {
return (-1);
}
rc = extract_DPI_port(packet, packet_len);
return (rc);
}
return (-1);
}
static extract_DPI_port(packet, len)
unsigned char packet[];
int len;
{
int offset;
int port;
/* should do error checking (like for noSuchName) */
offset = len - 2;
port = (packet[offset] << 8) + packet[offset + 1];
return (port);
}
SAMPLE DPI FUNCTIONS
/* DPI parser */
#ifdef VM
#include "manifest.h"
#endif
#include "snmp_dpi.h"
static struct dpi_get_packet *pDPIget();
static struct dpi_next_packet *pDPInext();
static struct dpi_set_packet *pDPIset();
static struct dpi_trap_packet *pDPItrap();
static struct dpi_resp_packet *pDPIresponse();
static void fDPIget();
static void fDPInext();
static void fDPIset();
static void fDPItrap();
static void fDPIresponse();
static int cDPIget();
static int cDPInext();
static int cDPIset();
static int cDPItrap();
static int cDPIresponse();
static struct snmp_dpi_hdr *mkDPIhdr();
static struct dpi_get_packet *mkDPIget();
static struct dpi_next_packet *mkDPInext();
struct dpi_set_packet *mkDPIset();
extern char *malloc();
static unsigned char new_packet[1024];
static int packet_len;
struct snmp_dpi_hdr *pDPIpacket(packet)
unsigned char *packet;
{
struct snmp_dpi_hdr *hdr;
int len, offset;
hdr = (struct snmp_dpi_hdr *) malloc(sizeof(struct snmp_dpi_hdr));
if (hdr == 0)
return (0);
len = (packet[0] << 8) + packet[1];
len += 2;
offset = 2;
hdr->proto_major = packet[offset++];
hdr->proto_minor = packet[offset++];
hdr->proto_release = packet[offset++];
hdr->packet_type = packet[offset++];
switch (hdr->packet_type) {
case SNMP_DPI_GET:
case SNMP_DPI_REGISTER:
hdr->packet_body.dpi_get =
pDPIget(packet + offset, len - offset);
break;
case SNMP_DPI_GET_NEXT:
hdr->packet_body.dpi_next =
pDPInext(packet + offset, len - offset);
break;
case SNMP_DPI_SET:
hdr->packet_body.dpi_set =
pDPIset(packet + offset, len - offset);
break;
case SNMP_DPI_TRAP:
hdr->packet_body.dpi_trap =
pDPItrap(packet + offset, len - offset);
break;
case SNMP_DPI_RESPONSE:
hdr->packet_body.dpi_response =
pDPIresponse(packet + offset, len - offset);
break;
}
return (hdr);
}
static struct dpi_get_packet *pDPIget(packet, len)
unsigned char *packet;
int len;
{
struct dpi_get_packet *get;
int l;
get = (struct dpi_get_packet *)
malloc(sizeof(struct dpi_get_packet));
if (get == 0)
return (0);
l = strlen(packet) + 1;
get->object_id = malloc(l);
strcpy(get->object_id, packet);
return (get);
}
static struct dpi_next_packet *pDPInext(packet, len)
unsigned char *packet;
int len;
{
struct dpi_next_packet *next;
int l;
unsigned char *cp;
next = (struct dpi_next_packet *)
malloc(sizeof(struct dpi_next_packet));
if (next == 0)
return (0);
cp = packet;
l = strlen(cp) + 1;
next->object_id = malloc(l);
strcpy(next->object_id, cp);
cp += l;
l = strlen(cp) + 1;
next->group_id = malloc(l);
strcpy(next->group_id, cp);
return (next);
}
static struct dpi_set_packet *pDPIset(packet, len)
unsigned char *packet;
int len;
{
struct dpi_set_packet *set;
int l;
unsigned char *cp;
if (len == 0)
return (0); /* nothing to parse */
set = (struct dpi_set_packet *)
malloc(sizeof(struct dpi_set_packet));
if (set == 0)
return (0);
cp = packet;
l = strlen(cp) + 1;
set->object_id = malloc(l);
strcpy(set->object_id, cp);
cp += l;
set->type = *(cp++);
l = (*(cp++) << 8);
l += *(cp++);
set->value_len = l;
set->value = malloc(l);
bcopy(cp, set->value, l);
return (set);
}
static struct dpi_trap_packet *pDPItrap(packet, len)
unsigned char *packet;
int len;
{
struct dpi_trap_packet *trap;
trap = (struct dpi_trap_packet *)
malloc(sizeof(struct dpi_trap_packet));
if (trap == 0)
return (0);
trap->generic = *packet;
trap->specific = *(packet + 1);
trap->info = pDPIset(packet + 2, len - 2);
return (trap);
}
static struct dpi_resp_packet *pDPIresponse(packet, len)
unsigned char *packet;
int len;
{
struct dpi_resp_packet *resp;
resp = (struct dpi_resp_packet *)
malloc(sizeof(struct dpi_resp_packet));
if (resp == 0)
return (0);
resp->ret_code = *packet;
resp->ret_data = pDPIset(packet + 1, len - 1);
return (resp);
}
void fDPIparse(hdr)
struct snmp_dpi_hdr *hdr;
{
if (hdr == 0)
return;
switch (hdr->packet_type) {
case SNMP_DPI_GET:
case SNMP_DPI_REGISTER:
fDPIget(hdr);
break;
case SNMP_DPI_GET_NEXT:
fDPInext(hdr);
break;
case SNMP_DPI_SET:
fDPIset(hdr);
break;
case SNMP_DPI_TRAP:
fDPItrap(hdr);
break;
case SNMP_DPI_RESPONSE:
fDPIresponse(hdr);
break;
}
free(hdr);
}
static void fDPIget(hdr)
struct snmp_dpi_hdr *hdr;
{
struct dpi_get_packet *get;
get = hdr->packet_body.dpi_get;
if (get == 0)
return;
if (get->object_id)
free(get->object_id);
free(get);
}
static void fDPInext(hdr)
struct snmp_dpi_hdr *hdr;
{
struct dpi_next_packet *next;
next = hdr->packet_body.dpi_next;
if (next == 0)
return;
if (next->object_id)
free(next->object_id);
if (next->group_id)
free(next->group_id);
free(next);
}
static void fDPIset(hdr)
struct snmp_dpi_hdr *hdr;
{
struct dpi_set_packet *set;
set = hdr->packet_body.dpi_set;
if (set == 0)
return;
if (set->object_id)
free(set->object_id);
if (set->value)
free(set->value);
free(set);
}
static void fDPItrap(hdr)
struct snmp_dpi_hdr *hdr;
{
struct dpi_trap_packet *trap;
struct dpi_set_packet *set;
trap = hdr->packet_body.dpi_trap;
if (trap == 0)
return;
set = trap->info;
if (set != 0) {
if (set->object_id)
free(set->object_id);
if (set->value)
free(set->value);
free(set);
}
free(trap);
}
static void fDPIresponse(hdr)
struct snmp_dpi_hdr *hdr;
{
struct dpi_resp_packet *resp;
struct dpi_set_packet *set;
resp = hdr->packet_body.dpi_response;
if (resp == 0)
return;
set = resp->ret_data;
if (set != 0) {
if (set->object_id)
free(set->object_id);
if (set->value)
free(set->value);
free(set);
}
free(resp);
}
unsigned char *cDPIpacket(hdr)
struct snmp_dpi_hdr *hdr;
{
int rc, len;
if (hdr == 0) {
return (0);
}
packet_len = 2;
new_packet[packet_len++] = hdr->proto_major;
new_packet[packet_len++] = hdr->proto_minor;
new_packet[packet_len++] = hdr->proto_release;
new_packet[packet_len++] = hdr->packet_type;
switch (hdr->packet_type) {
case SNMP_DPI_GET:
case SNMP_DPI_REGISTER:
rc = cDPIget(hdr->packet_body.dpi_get);
break;
case SNMP_DPI_GET_NEXT:
rc = cDPInext(hdr->packet_body.dpi_next);
break;
case SNMP_DPI_SET:
rc = cDPIset(hdr->packet_body.dpi_set);
break;
case SNMP_DPI_TRAP:
rc = cDPItrap(hdr->packet_body.dpi_trap);
break;
case SNMP_DPI_RESPONSE:
rc = cDPIresponse(hdr->packet_body.dpi_response);
break;
}
if (rc == -1)
return (0);
len = packet_len - 2;
new_packet[1] = len & 0xff;
len >>= 8;
new_packet[0] = len & 0xff;
return (new_packet);
}
static int cDPIget(get)
struct dpi_get_packet *get;
{
if (get->object_id == 0)
return (-1);
strcpy(&new_packet[packet_len], get->object_id);
packet_len += strlen(get->object_id) + 1;
return (0);
}
static int cDPInext(next)
struct dpi_next_packet *next;
{
if (next->object_id == 0)
return (-1);
if (next->group_id == 0)
return (-1);
strcpy(&new_packet[packet_len], next->object_id);
packet_len += strlen(next->object_id) + 1;
strcpy(&new_packet[packet_len], next->group_id);
packet_len += strlen(next->group_id) + 1;
return (0);
}
static int cDPIset(set)
struct dpi_set_packet *set;
{
int len;
if (set->object_id == 0)
return (-1);
if ((set->value == 0) && (set->value_len != 0))
return (-1);
strcpy(&new_packet[packet_len], set->object_id);
packet_len += strlen(set->object_id) + 1;
new_packet[packet_len++] = set->type;
len = set->value_len >> 8;
new_packet[packet_len++] = len & 0xff;
new_packet[packet_len++] = set->value_len & 0xff;
bcopy(set->value, &new_packet[packet_len], set->value_len);
packet_len += set->value_len;
return (0);
}
static int cDPIresponse(resp)
struct dpi_resp_packet *resp;
{
int rc;
if (resp == 0)
return (-1);
new_packet[packet_len++] = resp->ret_code;
if (resp->ret_data != 0) {
rc = cDPIset(resp->ret_data);
} else
rc = 0;
return (rc);
}
static int cDPItrap(trap)
struct dpi_trap_packet *trap;
{
int rc;
new_packet[packet_len++] = trap->generic;
new_packet[packet_len++] = trap->specific;
if (trap->info != 0)
rc = cDPIset(trap->info);
else
rc = 0;
return (rc);
}
unsigned char *mkMIBquery(cmd, oid_name, group_oid, type, len, value)
int cmd;
char *oid_name, *group_oid;
int type, len;
char *value;
{
struct snmp_dpi_hdr *hdr;
unsigned char *cp;
hdr = mkDPIhdr(cmd);
if (hdr == 0)
return (0);
switch (hdr->packet_type) {
case SNMP_DPI_GET:
case SNMP_DPI_REGISTER:
hdr->packet_body.dpi_get = mkDPIget(oid_name);
break;
case SNMP_DPI_GET_NEXT:
hdr->packet_body.dpi_next = mkDPInext(oid_name, group_oid);
break;
case SNMP_DPI_SET:
hdr->packet_body.dpi_set =
mkDPIset(oid_name, type, len, value);
break;
}
cp = cDPIpacket(hdr);
fDPIparse(hdr);
return (cp);
}
unsigned char *mkDPIregister(oid_name)
char *oid_name;
{
return (mkMIBquery(SNMP_DPI_REGISTER, oid_name));
}
unsigned char *mkDPIresponse(ret_code, value_list)
int ret_code;
struct dpi_set_packet *value_list;
{
struct snmp_dpi_hdr *hdr;
struct dpi_resp_packet *resp;
unsigned char *cp;
hdr = mkDPIhdr(SNMP_DPI_RESPONSE);
resp = (struct dpi_resp_packet *)
malloc(sizeof(struct dpi_resp_packet));
if (resp == 0) {
free(hdr);
return (0);
}
hdr->packet_body.dpi_response = resp;
resp->ret_code = ret_code;
resp->ret_data = value_list;
cp = cDPIpacket(hdr);
fDPIparse(hdr);
return (cp);
}
unsigned char *mkDPItrap(generic, specific, value_list)
int generic, specific;
struct dpi_set_packet *value_list;
{
struct snmp_dpi_hdr *hdr;
struct dpi_trap_packet *trap;
unsigned char *cp;
hdr = mkDPIhdr(SNMP_DPI_TRAP);
trap = (struct dpi_trap_packet *)
malloc(sizeof(struct dpi_trap_packet));
if (trap == 0) {
free(hdr);
return (0);
}
hdr->packet_body.dpi_trap = trap;
trap->generic = generic;
trap->specific = specific;
trap->info = value_list;
cp = cDPIpacket(hdr);
fDPIparse(hdr);
return (cp);
}
static struct snmp_dpi_hdr *mkDPIhdr(type)
int type;
{
struct snmp_dpi_hdr *hdr;
hdr = (struct snmp_dpi_hdr *) malloc(sizeof(struct snmp_dpi_hdr));
if (hdr == 0)
return (0);
hdr->proto_major = SNMP_DPI_PROTOCOL;
hdr->proto_minor = SNMP_DPI_VERSION;
hdr->proto_release = SNMP_DPI_RELEASE;
hdr->packet_type = type;
return (hdr);
}
static struct dpi_get_packet *mkDPIget(oid_name)
char *oid_name;
{
struct dpi_get_packet *get;
int l;
get = (struct dpi_get_packet *)
malloc(sizeof(struct dpi_get_packet));
if (get == 0)
return (0);
l = strlen(oid_name) + 1;
get->object_id = malloc(l);
strcpy(get->object_id, oid_name);
return (get);
}
static struct dpi_next_packet *mkDPInext(oid_name, group_oid)
char *oid_name;
char *group_oid;
{
struct dpi_next_packet *next;
int l;
next = (struct dpi_next_packet *)
malloc(sizeof(struct dpi_next_packet));
if (next == 0)
return (0);
l = strlen(oid_name) + 1;
next->object_id = malloc(l);
strcpy(next->object_id, oid_name);
l = strlen(group_oid) + 1;
next->group_id = malloc(l);
strcpy(next->group_id, group_oid);
return (next);
}
struct dpi_set_packet *mkDPIset(oid_name, type, len, value)
char *oid_name;
int type;
int len;
char *value;
{
struct dpi_set_packet *set;
int l;
set = (struct dpi_set_packet *)
malloc(sizeof(struct dpi_set_packet));
if (set == 0)
return (0);
l = strlen(oid_name) + 1;
set->object_id = malloc(l);
strcpy(set->object_id, oid_name);
set->type = type;
set->value_len = len;
set->value = malloc(len);
bcopy(value, set->value, len);
return (set);
}
SAMPLE SOURCES FOR ANONYMOUS FTP
The complete source to two SNMP DPI-related programs is available for
anonymous ftp from the University of Toronto. The host name to use
is "vm.utcs.utoronto.ca" (128.100.100.2). The files are in the
"anonymou.204" minidisk, so one must issue a "cd anonymou.204" after
having logged in. Don't forget to use the binary transmission mode.
The Ping Engine
This program is an SNMP DPI sub-agent which allows network management
stations to perform remote PINGs. The source to this applications is
in the file "ping_eng.tarbin". The source to the SNMP DPI API is
also contained within the archive.
The DPI->SMUX daemon
This program illustrates what is required to include the SNMP DPI in
an SNMP agent. This is actually a SMUX-based agent that works with
the ISODE SNMP agent and provides an interface for SNMP DPI sub-
agents. The source to this program is in the file "dpid.tarbin".
ISODE 6.7, or later, is a prerequisite.
References
[1] Case, J., Fedor, M., Schoffstall, M., and J. Davin, "Simple
Network Management Protocol", RFC1157, SNMP Research,
Performance Systems International, Performance Systems
International, MIT Laboratory for Computer Science, May 1990.
[2] Information processing systems - Open Systems Interconnection,
"Specification of Abstract Syntax Notation One (ASN.1)",
International Organization for Standardization, International
Standard 8824, December 1987.
[3] Information processing systems - Open Systems Interconnection,
"Specification of Basic Encoding Rules for Abstract Syntax
Notation One (ASN.1)", International Organization for
Standardization, International Standard 8825, December 1987.
[4] McCloghrie K., and M. Rose, "Management Information Base for
Network Management of TCP/IP-based internets", RFC1156,
Performance Systems International and Hughes LAN Systems, May
1990.
[5] Rose, M., and K. McCloghrie, "Structure and Identification of
Management Information for TCP/IP-based internets", RFC1155,
Performance Systems International and Hughes LAN Systems, May
1990.
[6] International Business Machines, Inc., "TCP/IP for VM:
Programmer's Reference", SC31-6084-0, 1990.
[7] International Business Machines, Inc., "Virtual Machine System
Facilities for Programming, Release 6", SC24-5288-01, 1988.
[8] International Business Machines, Inc., "TCP/IP Version 1.1 for
OS/2 EE: Programmer's Reference", SC31-6077-1, 1990.
Security Considerations
Security issues are not discussed in this memo.
Authors' Addresses
Geoffrey C. Carpenter
IBM T. J. Watson Research Center
P. O. Box 218
Yorktown Heights, NY 10598
Phone: (914) 945-1970
Email: gcc@watson.ibm.com
Bert Wijnen
IBM International Operations
Watsonweg 2
1423 ND Uithoorn
The Netherlands
Phone: +31-2975-53316
Email: wijnen@uitvm2.iinus1.ibm.com