pdu.c revision 4f90901ff7a0693b0be018de6dcfff7c6e11d734
/*
* 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
* 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"
/*
* SNMP PDU and packet transport related routines
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "asn1.h"
#include "pdu.h"
#include "debug.h"
/*
* Static declarations
*/
static int snmp_add_null_vars(snmp_pdu_t *, char *, int, int);
static void snmp_free_null_vars(pdu_varlist_t *);
/*
* Allocates and creates a PDU for the specified SNMP command. Currently
* only SNMP_MSG_GET, SNMP_MSG_GETNEXT and SNMP_MSG_GETBULK are supported
*/
{
(cmd != SNMP_MSG_GETBULK)) {
return (NULL);
}
return (NULL);
} else if (cmd == SNMP_MSG_GETBULK) {
pdu->non_repeaters = 0;
}
return (NULL);
}
pdu->reply_pktsz = 0;
return (pdu);
}
/*
* Builds a complete ASN.1 encoded snmp message packet out of the PDU.
* Currently the maximum request packet is limited to SNMP_DEF_PKTBUF_SZ.
* Since we only send SNMP_MSG_GET, SNMP_MSG_GETNEXT and SNMP_MSG_GETBULK,
* as long as the number of bulk oids are not *too* many, we're safe with
* this limit (the typical packet size of a bulk request of 10 vars is
* around 250 bytes).
*/
int
{
return (-1);
/*
* Let's start with the ASN sequence tag. Set the length
* to 0 initially and fill it up once the message packetizing
* is complete.
*/
return (-1);
}
msg_seq_end = p;
/*
* Store the version
*/
return (-1);
}
/*
* Store the community string
*/
if (p == NULL) {
return (-1);
}
/*
* Build the PDU
*/
return (-1);
}
/*
* Complete the message pkt by updating the message sequence length
*/
seqlen = p - msg_seq_end;
/*
* Calculate packet size and return
*/
return (0);
}
/*
* Makes a PDU out of a reply packet. The reply message is parsed
* and if the reqid of the incoming packet does not match the reqid
* we're waiting for, an error is returned. The PDU is allocated
* inside this routine and must be freed by the caller once it is no
* longer needed.
*/
{
uchar_t *p;
return (NULL);
/*
* Try to parse the ASN sequence out of the beginning of the reply
* packet. If we don't find a sequence at the beginning, something's
* wrong.
*/
return (NULL);
}
/*
* Now try to parse the version out of the packet
*/
return (NULL);
}
return (NULL);
}
/*
* Parse the community string (space allocated by asn_parse_string)
*/
if (p == NULL) {
return (NULL);
}
/*
* Parse the PDU part of the message
*/
return (NULL);
}
return (reply_pdu);
}
/*
* Convert the OID strings into the standard PDU oid form (sequence of
* integer subids) and add them to the PDU's variable list. Note that
* this is used only for preparing the request messages (GET, GETNEXT
* and GETBULK), so the values of the variables are always null.
*/
static int
{
char *p;
int i;
p = oidstrs;
for (i = 0; i < n_oids; i++) {
return (-1);
} else if (i == 0) {
varblock_p = vp;
} else {
}
return (-1);
}
p += strlen(p) + 1;
}
/*
* append the varlist to the PDU
*/
else {
;
}
return (0);
}
/*
* Some assumptions are in place here to eliminate unnecessary complexity.
* All OID strings passed are assumed to be in the numeric string form, have
* only customer, this is quite reasonable.
*/
static oid *
{
int i, count;
char *p, *q;
char *oidstr_dup;
return (NULL);
break;
}
/*
* Add one more to count for 'row'. Need special processing
* for SNMP_MSG_GETNEXT and SNMP_MSG_GETBULK requests; see
* comment below.
*/
count++;
}
return (NULL);
free((void *) p);
return (NULL);
}
p = oidstr_dup;
for (i = 0; i < count - 1; i++) {
if (q = strchr(p, '.'))
*q = 0;
p = q + 1;
}
/*
* For SNMP_MSG_GET, the leaf subid will simply be the row#.
*
* For SNMP_MSG_GETBULK, if the row# passed is greater than 0,
* we pass 'row-1' as the leaf subid, to include the item that
* is of interest to us. If the row# is less than or equal to 0,
* we will simply ignore it and pass only the prefix part of the
* oidstr. For this case, our count would have been 1 less than
* usual, and we are yet to save the last subid.
*
* For SNMP_MSG_GETNEXT, if the row# passed is less than 0,
* we'll simply ignore it and pass only the prefix part of the
* oidstr. For this case, our count would have been 1 less than
* usual, and we are yet to save the last subid. If the row#
* passed is greater than or equal to 0, we'll simply pass it
* verbatim, as the leaf subid.
*/
switch (cmd) {
case SNMP_MSG_GET:
break;
case SNMP_MSG_GETBULK:
if (row > 0)
else
break;
case SNMP_MSG_GETNEXT:
if (row < 0)
else
break;
}
free((void *) oidstr_dup);
return (objid);
}
/*
* Builds the PDU part of the snmp message packet.
*/
static uchar_t *
{
uchar_t *p;
/*
* Build ASN sequence for the PDU command (length will be
* updated later once the entire command is completely formed)
*/
pdu_seq_begin = buf;
if (p == NULL)
return (NULL);
pdu_seq_end = p;
/*
* Build the request id
*/
return (NULL);
/*
* Build the non-repeaters and max-repetitions for SNMP_MSG_GETBULK
* (same as error status and error index for other message types)
*/
return (NULL);
return (NULL);
/*
* Build ASN sequence for the variables list (update length
* after building the varlist)
*/
varlist_seq_begin = p;
return (NULL);
varlist_seq_end = p;
/*
* Build the variables list
*/
if (p == NULL)
return (NULL);
}
/*
* Now update the varlist sequence length
*/
seqlen = p - varlist_seq_end;
/*
* And finally, update the length for the PDU sequence
*/
seqlen = p - pdu_seq_end;
seqlen);
return (p);
}
/*
* Builds an object variable into the snmp message packet. Although the
* code is here to build variables of basic types such as integer, object id
* and strings, the only type of variable we ever send via snmp request
* messages is the ASN_NULL type.
*/
static uchar_t *
{
uchar_t *p, *varseq_end;
/*
* Each variable binding is in turn defined as a 'SEQUENCE of' by
* the SNMP PDU format, so we'll prepare the sequence and fill up
* the length later. Sigh!
*/
return (NULL);
varseq_end = p;
/*
* Build the object id
*/
return (NULL);
/*
* Currently we only ever build ASN_NULL vars while sending requests,
* since we support only SNMP_MSG_GET, SNMP_MSG_GETNEXT and
* SNMP_MSG_GETBULK.
*/
switch (val_type) {
case ASN_INTEGER:
if (p == NULL)
return (NULL);
break;
case ASN_OBJECT_ID:
if (p == NULL)
return (NULL);
break;
case ASN_OCTET_STR:
if (p == NULL)
return (NULL);
break;
case ASN_NULL:
return (NULL);
break;
default:
return (NULL);
}
/*
* Rebuild the variable sequence length
*/
seqlen = p - varseq_end;
return (p);
}
/*
* Parse the PDU portion of the incoming snmp message into the reply_pdu.
* Space for all structure members are allocated as needed and must be freed
* by the caller when these are no longer needed.
*/
static uchar_t *
{
uchar_t *p;
/*
* Parse the PDU header out of the message
*/
return (NULL);
return (NULL);
/*
* Parse the request id and verify that this is the response
* we're expecting.
*/
return (NULL);
return (NULL);
/*
* Parse the error-status and error-index values
*/
return (NULL);
return (NULL);
/*
* Parse the header for the variables list sequence.
*/
return (NULL);
while (((int)*msgsz_p) > 0) {
return (NULL);
else
return (NULL);
}
return (p);
}
/*
* Allocate and parse the next variable into the varlist
*/
static uchar_t *
{
uchar_t *p;
/*
* Parse this variable's sequence
*/
return (NULL);
/*
* Parse the variable's object identifier
*/
if (p == NULL)
return (NULL);
/*
* Parse the object's value
*/
return (NULL);
return (p);
}
void
{
if (pdu) {
}
}
}
static void
{
}
}