agent.c revision 7c478bd95313f5f23a4c958a745db2134aa03244
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (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 2004 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include "impl.h"
#include "error.h"
#include "trace.h"
#include "snmp.h"
#include "pdu.h"
#include "request.h"
#include "trap.h"
#include "node.h"
#include "access.h"
#if defined(_LP64)
#define COLUMN_OFFSET(x) (x) * 2
#else
#define COLUMN_OFFSET(x) (x)
#endif
#define OCTET_STRING 2
/***** LOCAL VARIABLES *****/
/*
* The idea of these cache variables is to avoid to call
* the same *(entry->get) function for variables contained
* in a single SNMP PDU.
*
* There is still a problem in this mechanism.
* When you query a whole table row by row and when
* you reached the end of the table, the *(entry->get)
* will be called several times:
* - for the first column, *(entry->get) will be called
* once to find that the end of the table is reached
* (==> the knowledge that we reached the last row is cached)
* and then *(entry->get) will be called on the first row of
* the same table (==> the first row is cached).
* - Same behaviour for all the remaining columns
*
* Possible solutions:
* - two caches but this implies the copy of the cached
* structures + all theis pointers
* - only one cache + caching the knowledge that we reached the last
* row ???
*
*/
static void *cache_output_pointer = NULL;
static int cache_output_snmp_error = -1;
/***** LOCAL FUNCTIONS *****/
/****************************************************************/
/* returns: */
/* 0 in case of success (the pdu should be sent */
/* back to its originator even if an SNMP error */
/* was detected) */
/* -1 in case of failure (no pdu should be sent */
/* back) */
{
int snmpEnableAuthTraps = FALSE;
{
error("BUG: agent_process(): pdu is NULL");
return -1;
}
/* check host */
{
error("agent_process(): unauthorized manager (%s)",
switch(snmpEnableAuthTraps)
{
case TRUE:
NULL, error_label))
{
error("trap_send_to_all_destinators() failed: %s\n",
}
break;
case FALSE:
default:
break;
}
return -1;
}
/* if mngr == NULL -> allow requests from any hosts */
/* check pdu type */
{
return -1;
}
/* check host */
{
/*
* Earlier, the community name is displayed here
* in this error message. But since these error
* messages are readable by all users, it is not advisible
* to display community names in the error messages.
*/
error("agent_process() : bad community from %s",
switch(snmpEnableAuthTraps)
{
case TRUE:
NULL, error_label))
{
error("trap_send_to_all_destinators() failed: %s\n",
}
break;
case FALSE:
default:
break;
}
return -1;
}
}
{
case GETNEXT_REQ_MSG:
{
return -1;
}
return 0;
case GET_REQ_MSG:
{
return -1;
}
return 0;
case SET_REQ_MSG:
{
case 0:
{
case 0:
case 1:
return 0;
case -1:
error("agent_set(SECOND_PASS) failed: %s",
return -1;
}
/* never reached */
break;
case 1:
return 0;
case -1:
error("agent_set(FIRST_PASS) failed: %s",
return -1;
}
}
/* never reached */
return -1;
}
/****************************************************************/
/* returns: */
/* 0 in case of success (the pdu should be sent */
/* back to its originator even if an SNMP error */
/* was detected) */
/* -1 in case of failure (no pdu should be sent */
/* back) */
{
int index = 1;
int snmp_error;
error_label[0] = '\0';
{
{
return 0;
}
/* we should not forget to free suffix.subids */
if(trace_level > 0)
{
trace("!! getnext(): processing the variable %s\n\n",
}
{
error("ASN.1 type (0x%x) is not NULL for node %s",
}
{
error("val is not NULL for node %s",
}
{
error("val_len is not 0 for node %s",
}
if(snmp_error != SNMP_ERR_NOERROR)
{
return 0;
}
index++;
}
return 0;
}
/* This function will free suffix->subids */
/* It returns a positive snmp_error code. */
static int
{
char *pointer;
int snmp_error;
int index_len;
/* create index struct */
int index_buffer[256];
int was_cached ;
int i;
int get_entry;
{
if(trace_level > 0)
{
trace("!! End of MIB\n\n");
}
return SNMP_ERR_NOSUCHNAME;
}
if(trace_level > 0)
trace("!! Trying %s with suffix %s\n\n",
{
case OBJECT:
{
case 0:
return SNMP_ERR_NOSUCHNAME;
{
case INTEGER:
case COUNTER:
case GAUGE:
case TIMETICKS:
break;
case OBJID:
if(snmp_error != SNMP_ERR_NOERROR &&
ssa_mem_free != 0){
}
break;
case STRING:
case IPADDRESS:
case OPAQUE:
if(snmp_error != SNMP_ERR_NOERROR &&
ssa_mem_free != 0){
}
break;
}
if(snmp_error != SNMP_ERR_NOERROR)
{
if(snmp_error < 0)
{
error("the get() method of %s returned %d",
}
return snmp_error;
}
/* variable->name */
/* variable->type */
/* variable->val, variable->val_len */
{
case INTEGER:
case COUNTER:
case GAUGE:
case TIMETICKS:
break;
case OBJID:
break;
case STRING:
case IPADDRESS:
case OPAQUE:
break;
}
return SNMP_ERR_NOERROR;
case 1:
{
return SNMP_ERR_NOSUCHNAME;
}
default:
return SNMP_ERR_NOSUCHNAME;
}
case COLUMN:
{
return SNMP_ERR_NOSUCHNAME;
}
return SNMP_ERR_NOSUCHNAME;
}
index_len = 0;
{
else
}
{
}
{
index[i] = 0;
}
for (i=0; i < index_len; i++)
{
was_cached = 1;
else
{
was_cached = 0;
break;
}
}
if (was_cached)
{
for (i=0;i < index_len; i++)
index[i]= cache_output_index[i];
}
else
{
{
}
for (i=0; i < index_len; i++)
cache_input_index[i] = index[i];
else
for (i=0; i< index_len; i++)
for (i=0; i < index_len; i++)
cache_output_index[i] = index[i];
}
{
if(snmp_error == END_OF_TABLE)
{
if(trace_level > 0)
{
trace("!! End of table %s\n\n",
}
}
if(snmp_error < 0)
{
error("the get() method of %s returned %d",
}
return snmp_error;
}
/* variable->name */
for (i=0; i < index_len; i++)
/* variable->type */
/* variable->val, variable->val_len */
{
case INTEGER:
case COUNTER:
case GAUGE:
case TIMETICKS:
break;
case OBJID:
/* fix the null subid */
}else{
}
break;
case STRING:
case IPADDRESS:
case OPAQUE:
}else{
}
break;
}
return SNMP_ERR_NOERROR;
case NODE:
}
/* never reached */
return -1;
}
/****************************************************************/
/* returns: */
/* 0 in case of success (the pdu should be sent */
/* back to its originator even if an SNMP error */
/* was detected) */
/* -1 in case of failure (no pdu should be sent */
/* back) */
{
int index_err = 1;
int snmp_error;
/* create index struct */
int index_buffer[256];
int was_cached;
int i;
int index_len;
error_label[0] = '\0';
{
{
return 0;
}
/* we should not forget to free suffix.subids */
if(trace_level > 0)
{
trace("!! get(): processing the variable %s\n\n",
}
{
error("agent_get(): ASN.1 type (0x%x) is not NULL for node %s",
}
{
}
{
}
{
case OBJECT:
{
SSAOidZero(&suffix);
return 0;
}
{
SSAOidZero(&suffix);
return 0;
}
{
case INTEGER:
case COUNTER:
case GAUGE:
case TIMETICKS:
break;
case OBJID:
if(snmp_error != SNMP_ERR_NOERROR &&
ssa_mem_free != 0){
}
break;
case STRING:
case IPADDRESS:
case OPAQUE:
if(snmp_error != SNMP_ERR_NOERROR &&
ssa_mem_free != 0){
}
break;
}
if(snmp_error != SNMP_ERR_NOERROR)
{
if(snmp_error < 0)
{
error("the get() method of %s returned %d",
}
SSAOidZero(&suffix);
return 0;
}
/* variable->name */
/* variable->type */
/* variable->val, variable->val_len */
{
case INTEGER:
case COUNTER:
case GAUGE:
case TIMETICKS:
break;
case OBJID:
if (ssa_mem_free != 0){
}
break;
case STRING:
case IPADDRESS:
case OPAQUE:
/*if(snmp_error != SNMP_ERR_NOERROR &&*/
if (ssa_mem_free != 0){
}
break;
}
break;
case COLUMN:
{
SSAOidZero(&suffix);
return 0;
}
SSAOidZero(&suffix);
return 0;
}
index_len = 0;
{
else
}
for (i=0; i < index_len; i++)
{
}
for (i=0; i < index_len; i++)
{
was_cached = 1;
else
{
was_cached = 0;
break;
}
}
if (was_cached)
{
}
else
{
{
}
for (i=0; i < index_len; i++)
cache_input_index[i] = index[i];
}
{
if(snmp_error < 0)
{
error("the get() method of %s returned %d",
}
SSAOidZero(&suffix);
return 0;
}
/* variable->type */
/* variable->val, variable->val_len */
{
case INTEGER:
case COUNTER:
case GAUGE:
case TIMETICKS:
break;
case OBJID:
break;
case STRING:
case IPADDRESS:
case OPAQUE:
break;
}
break;
case NODE:
SSAOidZero(&suffix);
return 0;
}
SSAOidZero(&suffix);
index_err++;
}
/* Moved this down from the column loop because the cache must be
freed only when the required columns in the row are all read.
- Added pointer check because pointer will point to nothing
if this is a non-column get.
- Added setting cache_output_pointer to NULL because if it is not
NULL, the next iteration of agent_process will try to delete it */
/* Bug fix 4127458 . Added check to see if entry has been initialized */
/* remember to turn off the caching */
}
return 0;
}
/****************************************************************/
/* returns */
/* 0 in case of success. If we are in the */
/* FIRST_PASS, we should go to the second pass. */
/* -1 in case of failure. If we are in the */
/* FIRST_PASS, we should not go to the */
/* second pass and no pdu should be sent back. */
/* 1 If we are in the FIRST_PASS, we should not go */
/* to the second pass but a pdu */
/* with an SNMP error should be sent back to its */
/* originator */
{
int index = 1;
int snmp_error;
int i;
/* create index struct */
int index_buffer[256];
error_label[0] = '\0';
{
{
return 1;
}
/* we should not forget to free suffix.subids */
if(trace_level > 0)
{
trace("!! set(%s): processing the variable %s\n\n",
}
/*
if(variable->val.string == NULL)
{
(void)sprintf(error_label, "val.string is NULL for node %s",
node->label);
SSAOidZero(&suffix);
return -1;
}
if(variable->val_len == 0)
{
(void)sprintf(error_label, "val_len is 0 for node %s",
node->label);
SSAOidZero(&suffix);
return -1;
}
*/
{
case OBJECT:
/* check the ASN.1 type */
{
SSAOidZero(&suffix);
return -1;
}
/* check the suffix */
{
SSAOidZero(&suffix);
return 1;
}
/* check the access */
{
SSAOidZero(&suffix);
return 1;
}
/* check the value length */
{
case INTEGER:
case COUNTER:
case GAUGE:
case TIMETICKS:
case IPADDRESS:
{
SSAOidZero(&suffix);
return -1;
}
{
SSAOidZero(&suffix);
return -1;
}
break;
}
/* in case of enumerated integer, check the value */
{
{
{
break;
}
}
{
SSAOidZero(&suffix);
return 1;
}
}
{
case INTEGER:
case COUNTER:
case GAUGE:
case TIMETICKS:
break;
case OBJID:
error_label)) {
SSAOidZero(&suffix);
return -1;
}
SSAOidZero(&oid);
break;
case STRING:
case IPADDRESS:
case OPAQUE:
SSAOidZero(&suffix);
return -1;
}
break;
}
if(snmp_error != SNMP_ERR_NOERROR)
{
if(snmp_error < 0)
{
error("the set(%s) method of %s returned %d",
}
SSAOidZero(&suffix);
return 1;
}
break;
case COLUMN:
/* check the ASN.1 type */
{
SSAOidZero(&suffix);
return -1;
}
/* check the suffix */
{
SSAOidZero(&suffix);
return 1;
}
/* check the access */
{
SSAOidZero(&suffix);
return 1;
}
/* check the value length */
{
case INTEGER:
case COUNTER:
case GAUGE:
case TIMETICKS:
case IPADDRESS:
{
SSAOidZero(&suffix);
return -1;
}
{
SSAOidZero(&suffix);
return -1;
}
break;
}
/* in case of enumerated integer, check the value */
{
{
{
break;
}
}
{
SSAOidZero(&suffix);
return 1;
}
}
{
case INTEGER:
case COUNTER:
case GAUGE:
case TIMETICKS:
break;
case OBJID:
SSAOidZero(&suffix);
return -1;
}
break;
case STRING:
case IPADDRESS:
case OPAQUE:
{
SSAOidZero(&suffix);
return -1;
}
break;
}
{
}
{
case INTEGER:
case COUNTER:
case GAUGE:
case TIMETICKS:
break;
case OBJID:
break;
case STRING:
case IPADDRESS:
case OPAQUE:
break;
}
{
case OBJID:
SSAOidZero(&oid);
break;
case STRING:
case IPADDRESS:
case OPAQUE:
break;
}
if(snmp_error != SNMP_ERR_NOERROR)
{
if(snmp_error < 0)
{
error("the set(%s) method of %s returned %d",
}
SSAOidZero(&suffix);
return 1;
}
break;
case NODE:
SSAOidZero(&suffix);
return 1;
}
SSAOidZero(&suffix);
index++;
}
return 0;
}
/****************************************************************/
/* flag == 0 means turn off auto mem free */
void SSAAutoMemFree(int flag)
{
ssa_mem_free = flag;
}