Files
s390-tools/osasnmpd/ibmOSAMibUtil.c
Aswin Karuvally a05935cca9 osasnmpd: Fix SNMP non-compliance
Update osasnmpd to support Object ID Sub-IDs with length up-to and
including 10 digits, in line with SNMP specification. While at it, also
replace sprintf() calls with snprintf(). Together, these changes
contribute to better memory safety.

Suggested-by: Alexandra Winter <wintera@linux.ibm.com>
Reviewed-by: Hidayath Khan <hidayath@linux.ibm.com>
Signed-off-by: Aswin Karuvally <aswin@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2026-07-22 17:44:10 +02:00

1776 lines
58 KiB
C

/*
* osasnmpd - IBM OSA-Express network card SNMP subagent
*
* Collection of utility functions used by the MIB implementation
* module.
*
* Copyright IBM Corp. 2002, 2017
*
* s390-tools is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See LICENSE for details.
*/
#include <errno.h>
#include <fcntl.h>
#include <signal.h>
#include <stddef.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <time.h>
#include "ibmOSAMibUtil.h"
#include "ibmOSAMib.h"
/* ptr to interface information on this system */
extern IF_LIST* if_list;
extern int ifNumber;
extern TABLE_OID* oid_list_head;
/* proc file filedescriptor. opened in osasnmpd.c */
extern int proc_fd;
/**********************************************************************
* str_to_oid_conv():
* This function converts an OID string in an OID u_long array used
* by net-snmp.
* parameters:
* IN char* uc_oid: OID string separated by dots
* OUT oid* ul_oid: OID u_long array
* returns: int count - number of OID identifiers found within OID
* string; 0 if OID string was invalid
*********************************************************************/
int str_to_oid_conv ( char* uc_oid, oid* ul_oid )
{
short valid = TRUE;
int count = 0;
char* pos_strt = uc_oid;
char* pos_end;
/* got non-empty oid string */
if ( strlen( uc_oid ) > 0 )
{
do {
/* found a dot, skip it */
if ( *pos_strt == '.' )
{
pos_strt++;
if ( *pos_strt == '\0') /* found ending dot - valid - */
break;
}
/* found no dot and but expected one, indicate invalid OID */
else if (count > 0)
{
valid = FALSE;
break;
} /* end if */
/* convert oid digit into data type oid (unsigned long) */
ul_oid[count] = (oid) strtoul( pos_strt, &pos_end, 10);
/* check result from conversion */
if (pos_strt == pos_end || ul_oid[count] == ULONG_MAX)
{
valid = FALSE;
break;
}
/* adjust to next OID digit */
pos_strt = pos_end;
count++;
}
while ( *pos_end != '\0' && count < MAX_OID_LEN );
}
else
/* indicate invalid OID */
valid = FALSE;
/* if OID was valid, return number of OID identifiers */
if (!valid)
return 0;
else
return count;
} /* end str_to_oid_conv() */
/**********************************************************************
* oid_to_str_conv():
* This function converts a net-snmp OID u_long array into an OID
* string separated by dots.
* parameters:
* IN oid* ul_oid: OID u_long array
* IN size_t length: OID length
* OUT char* uc_oid: OID string including dots (no leading dot)
* returns: TRUE - conversion was successful
* FALSE - conversion failed
*********************************************************************/
int oid_to_str_conv (oid* ul_oid, size_t length, char* uc_oid )
{
#define MAX_CHARS 22 /* size of buffer */
int i;
short valid = TRUE;
char buffer[MAX_CHARS]; /* buffer used for conversion */
/* got invalid OID length */
if ( length != 0 && length <= MAX_OID_LEN )
{
/* init return string */
uc_oid[0] = '\0';
for ( i=0; i < (int)length; i++)
{
/* convert and append OID digit to return string */
if (i == 0)
snprintf( buffer, sizeof(buffer), "%lu", ul_oid[i] );
else
snprintf( buffer, sizeof(buffer), ".%lu", ul_oid[i] );
strcat( uc_oid, buffer );
} /* end for */
}
else
/* indicate invalid OID */
valid = FALSE;
/* if OID conversion was successful, indicate success */
return valid;
} /* end oid_to_str_conv() */
/**********************************************************************
* init_oid_list():
* This function initializes the head of the linked list structure to
* maintain the IPAssists MIB information. It is called at subagent
* startup.
*
* parameters:
* INOUT none
* returns: TABLE_OID* - head of linked list (pseudo node)
* NULL - if malloc() for head failed
*
*********************************************************************/
TABLE_OID* init_oid_list ()
{
TABLE_OID* head;
/* allocate list head */
head = (TABLE_OID*) malloc( sizeof *head );
if ( head != NULL )
head->next = NULL;
return head;
} /* init_oid_list() */
/**********************************************************************
* search_oid():
* This function searches the linked OID list for a given OID and
* returns a ptr to the element if it is an exact match, otherwise the
* previous (smaller) OID in the list is returned.
*
* parameters:
* IN oid* s_oid - Toplevel OID to search for
* IN size_t len - length of this OID
* IN TABLE_OID* lhead - ptr to list head
* OUT TABLE_OID** curr - ptr to entry in list
* returns: 0 - exact match - OID exists in list
* 1 - not found, curr point to possible insertion point
* -1 - got unexpected return code from snmp_oid_compare()
*
*********************************************************************/
int search_oid ( oid* s_oid, size_t len, TABLE_OID* lhead, TABLE_OID** curr )
{
/* loop through list and compare OIDs */
/* fyi - snmp_oid_compare() is a function from the net-snmp agent extension API */
for( *curr=lhead; (*curr)->next != NULL; *curr=(*curr)->next )
{
switch
( snmp_oid_compare( s_oid, len, (*curr)->next->pObjid,
(*curr)->next->length ))
{
case 0: /* exact OID match - curr->next points to entry */
*curr = (*curr)->next;
return OID_FOUND;
break;
case 1: /* search OID still greater - goto next entry */
break;
case -1: /* next entry is greater than search OID */
return OID_NOT_FOUND;
break;
default: /* unexpected return code from snmp_oid_compare */
return UNEXP_ERROR;
} /* end switch */
} /* end for */
/* we're at the head or the end of linked list */
/* curr points to head or last element in list, good insertion points */
return OID_NOT_FOUND;
} /* search_oid() */
/**********************************************************************
* search_top_oid():
* This function searches for a fully qualified OID a matching Toplevel
* OID from the linked list.
* It returns a pointer to the element if it is an exact match.
* Otherwise the return OID is set to NULL.
*
* parameters:
* IN oid* s_oid - Fully qualified OID
* IN size_t len - length of this OID
* IN TABLE_OID* lhead - ptr to list head
* OUT TABLE_OID** curr - ptr to entry in list
* returns: 0 - exact match - appropriate Toplevel OID found
* 1 - not found, curr set to NULL
* -1 - got unexpected return code from snmp_oid_compare()
*
*********************************************************************/
int search_top_oid ( oid* s_oid, size_t len,
TABLE_OID* lhead, TABLE_OID** curr )
{
/* loop through list and compare OIDs */
/* snmp_oid_compare() is a taken from the net-snmp agent extension API */
for( *curr=lhead; (*curr)->next != NULL; *curr=(*curr)->next )
{
/* fully qualified OID must be greater than our Toplevel OID */
if ( len > (*curr)->next->length ) {
switch
( snmp_oid_compare( s_oid, (*curr)->next->length ,
(*curr)->next->pObjid, (*curr)->next->length ))
{
case 0: /* exact OID match - curr->next points to entry */
*curr = (*curr)->next;
return OID_FOUND;
break;
case 1: /* search OID still greater - goto next entry */
break;
case -1: /* next entry is greater than search OID */
*curr = NULL;
return OID_NOT_FOUND;
break;
default: /* unexpected return code from snmp_oid_compare */
*curr = NULL;
return UNEXP_ERROR;
} /* end switch */
} /* end if */
} /* end for */
/* we're at the head or the end of linked list */
/* curr points to head or last element in list */
*curr = NULL;
return OID_NOT_FOUND;
} /* search_top_oid() */
/**********************************************************************
* oid_insert_after():
* This function initializes and adds a new entry to the OID linked
* list after entry pre_oid.
*
* parameters:
* IN oid* i_oid - Toplevel OID to add
* IN size_t len - length of this OID
* IN TABLE_OID* pre_oid - add Toplevel OID after this entry
* returns: TABLE_OID* - PTR to newly inserted entry
* NULL - if malloc() for new entry failed
*********************************************************************/
TABLE_OID* oid_insert_after ( oid* i_oid, size_t len, TABLE_OID* pre_oid )
{
TABLE_OID *new_entry;
new_entry = (TABLE_OID*) malloc( sizeof *new_entry );
if ( new_entry == NULL )
return NULL;
/* allocate head for index list */
new_entry->ind_list = init_ind_list();
if ( new_entry->ind_list == NULL )
{
free ( new_entry );
return NULL;
} /* end if */
/* assign OID and length */
new_entry->pObjid = i_oid;
new_entry->length = len;
new_entry->var13ptr = NULL;
/* insert */
new_entry->next = pre_oid->next;
pre_oid->next = new_entry;
return new_entry;
} /* oid_insert_after()*/
/**********************************************************************
* delete_oid():
* This function deletes a Toplevel OID entry from the Toplevel OID
* linked list.
*
* parameters:
* IN oid *d_oid - Toplevel OID to delete
* IN size_t len - length of this OID
* IN TABLE_OID *lhead - head of Toplevel OID linked list
* returns: none
*
*********************************************************************/
int delete_oid( oid* d_oid, size_t len, TABLE_OID* lhead )
{
TABLE_OID *curr, *del_entry;
/* loop through list and compare OIDs */
/* snmp_oid_compare() is taken from the net-snmp agent extension API */
for( curr=lhead; curr->next != NULL; curr=curr->next )
{
if ( snmp_oid_compare( d_oid, len, curr->next->pObjid,
curr->next->length ) == 0 )
{
del_entry = curr->next;
curr->next = curr->next->next;
free( del_entry->pObjid );
free( del_entry->var13ptr );
/* index list not empty, free index list first */
if ( del_entry->ind_list->next != NULL )
delete_index( del_entry->ind_list, 0, IND_LIST );
/* free index list head */
free( del_entry->ind_list );
free( del_entry );
break;
} /* end if */
} /* end for */
return 0;
} /* delete_oid() */
/**********************************************************************
* clear_oid_list():
* This function removes all index entries from the Toplevel OID
* linked list.
*
* parameters:
* IN TABLE_OID *lhead - head of Toplevel OID linked list
* returns: none
*
*********************************************************************/
int clear_oid_list( TABLE_OID* lhead )
{
TABLE_OID *curr, *clr_entry;
/* loop through list and clean entries */
for( curr=lhead; curr->next != NULL; curr=curr->next )
{
clr_entry = curr->next;
/* index list not empty, free index list first */
if ( clr_entry->ind_list->next != NULL )
delete_index( clr_entry->ind_list, 0, IND_LIST );
} /* end for */
return 0;
} /* clear_oid_list() */
/**********************************************************************
* init_ind_list():
* This function initializes the head of the linked list structure to
* maintain index portion information. This is called when a new
* Toplevel OID is inserted in the Toplevel OID linked list.
*
* parameters:
* INOUT none
* returns: TABLE_OID* - head of linked list (pseudo node)
* NULL - if malloc() for head failed
*
*********************************************************************/
REG_INDICES* init_ind_list ( )
{
REG_INDICES* ihead;
/* allocate list head */
ihead = (REG_INDICES*) malloc( sizeof *ihead );
if ( ihead != NULL )
ihead->next = NULL;
return ihead;
} /* init_ind_list() */
/**********************************************************************
* index_insert_after():
* This function adds a new index entry to the index linked list
*
* parameters:
* IN char* i_index - index to add
* IN int ifIndex - appropriate IF-MIB ifIndex
* IN REG_INDICES* pre_ind - add index after this entry
* returns: REG_INDICES* - PTR to newly inserted entry
* NULL - if malloc() for new entry failed
*********************************************************************/
REG_INDICES* index_insert_after ( char* i_index, int ifIndex,
REG_INDICES* pre_ind )
{
REG_INDICES *new_entry;
new_entry = (REG_INDICES*) malloc( sizeof *new_entry );
if ( new_entry == NULL )
return NULL;
/* assign index and ifIndex */
new_entry->full_index = i_index;
new_entry->ifIndex = ifIndex;
/* insert */
new_entry->next = pre_ind->next;
pre_ind->next = new_entry;
return new_entry;
} /* index_insert_after()*/
/**********************************************************************
* delete_index():
* This function deletes an entry in the index linked list indexed by
* ifIndex or removes the whole index linked list if desired.
*
* parameters:
* IN REG_INDICES *lhead - head of index linked list
* IN int ifIndex - ifIndex to remove from list
* IN int del_type - deletion type (IF_ENTRY/IND_LIST)
* returns: none
*
*********************************************************************/
int delete_index( REG_INDICES* lhead, int ifIndex, int del_type )
{
REG_INDICES *curr, *del_entry;
if (del_type == IF_ENTRY ) {
/* loop through list and compare ifIndex */
curr = lhead;
while ( curr->next != NULL )
{
if ( curr->next->ifIndex == ifIndex ) {
del_entry = curr->next;
curr->next = curr->next->next;
free( del_entry->full_index );
free( del_entry );
} /* end if */
else
curr=curr->next;
} /* end while */
}
else if ( del_type == IND_LIST ) {
/* loop through list delete one entry after another */
curr = lhead;
while ( curr->next !=NULL )
{
del_entry = curr->next;
curr->next = curr->next->next;
free( del_entry->full_index );
free( del_entry );
} /* end while */
} /* end if */
return 0;
} /* delete_index() */
/**********************************************************************
* search_index():
* This function searches the linked index list for a given index and
* returns a ptr to the element if it is an exact match, otherwise the
* previous (smaller) index in the list is returned.
*
* parameters:
* IN index* s_index - index to search for
* IN REG_INDICES* lhead - ptr to list head
* OUT REG_INDICES** curr - ptr to entry in list
* returns: 0 - exact match - index exists in list
* 1 - not found, curr point to possible insertion point
*
*********************************************************************/
int search_index ( char* s_index, REG_INDICES* lhead, REG_INDICES** curr )
{
int oid_len1, oid_len2;
oid ind_oid1[MAX_OID_LEN]; /* temporary net-snmp oids */
oid ind_oid2[MAX_OID_LEN];
/* loop through list and compare indices */
for( *curr=lhead; (*curr)->next != NULL; *curr=(*curr)->next )
{
oid_len1 = str_to_oid_conv( (char*) s_index, ind_oid1 );
oid_len2 = str_to_oid_conv( (char*) (*curr)->next->full_index,
ind_oid2 );
switch
( snmp_oid_compare( ind_oid1, oid_len1, ind_oid2, oid_len2 ) )
{
case 0: /* exact index match - curr->next points to entry */
/* exact index match - curr-> points to entry */
*curr = (*curr)->next;
return INDEX_FOUND;
break;
case 1: /* search index still greater - goto next entry */
continue;
break;
case -1: /* next entry is greater than search index */
/* next entry is greater than search index */
return INDEX_NOT_FOUND;
break;
default: /* unexpected return code from snmp_oid_compare */
return UNEXP_ERROR;
} /* end switch */
} /* end for */
/* we're at the head or the end of linked list */
/* curr points to head or last element in list, good insertion points */
return INDEX_NOT_FOUND;
} /* search_index() */
/**********************************************************************
* register_tables()
* Parses MIB information returned by IPAssists and registers OID
* suffixes with net-snmp subagent driving code using the REGISTER_MIB
* macro. Also puts data from the MIB information returned by IPAssists
* into local data structures to maintain index information.
*
* This functions only maps the header of the IPAssists MIB info.
* The table data is parsed through the void mib_data_ptr.
*
* IPAssists MIB information layout:
*
* header information:
* INOUT int request
* INOUT int interface number/ifIndex
* INOUT int return code from IPAssists
* INOUT int IPAssists version
* INOUT int sequence number of this response
* OUT int number of returned table information for that interface
*
* Repeated information:
* OUT string Toplevel OID for a table (including dots)
* OUT int number of OID suffixes for that table
*
* Repeated OID suffix information for a single table and every index:
* OUT int object access type
* OUT int object data type
* OUT string OID suffix for object
* OUT string OID index portion
*
* parameters:
* IN struct table: MIB information returned by IPAssists
* IN TABLE_OID* lhead: head of toplevel OID linked list
* returns: 0 - SUCCESS
* -1 - Registration not performed due to error;
* an appropriate log entry is made
*
*********************************************************************/
int register_tables ( void* mib_data,
TABLE_OID* lhead )
{
int i, j, suf_def, suf_cnt, src_oid, src_ind;
int oid_len, oid_acc, oid_typ;
oid t_oid[MAX_OID_LEN]; /* temporary net-snmp oid */
oid *top_oid;
char *new_index;
char toid_str[MAX_OID_STR_LEN];
char time_buf[TIME_BUF_SIZE]; /* date/time buffer */
IPA_CMD_REG *mib_data_hdr; /* ptr to IPAssists hdr information */
char *last_suffix; /* last suffix in suffix list */
void *mib_data_ptr; /* ptr to parse IPAssists MIB info */
TABLE_OID *oid_ptr, *ins_oid = NULL; /* ptr into Toplevel OID linked list */
REG_INDICES *ind_ptr; /* ptr into index linked list */
/* ptr to net-snmp variable13 structs that will contain the suffix
information registered with subagent driving code */
struct variable13 *table_vars, *new_area;
/* point to beginning of MIB information (header) */
mib_data_hdr = ( IPA_CMD_REG* ) mib_data;
/* set parse ptr behind header information; first Toplevel OID */
mib_data_ptr = ( char* ) mib_data_hdr + sizeof( IPA_CMD_REG );
/************************************/
/* loop through returned table data */
/************************************/
for ( i=0; i < mib_data_hdr->table_cnt; i++ ) {
/****************************************************/
/* get Toplevel oid that we want to register under */
/****************************************************/
/* adjust parse ptr to next Toplevel OID (skip padding) */
mib_data_ptr = (int*) (PTR_ALIGN4(mib_data_ptr));
/* convert string OID to net-snmp oid type */
strncpy( toid_str, (char*) mib_data_ptr, MAX_OID_STR_LEN );
toid_str[ MAX_OID_STR_LEN-1 ] = '\0';
oid_len = str_to_oid_conv( (char*) mib_data_ptr, t_oid );
if ( oid_len == 0 ) {
get_time( time_buf );
snmp_log( LOG_ERR,
"%s register_tables(): str to oid conversion failed "
"(Toplvl OID) .%s\nOSA Subagent MIB information may be incomplete!\n"
,time_buf, toid_str );
return -1;
} /* end if */
/* save Toplevel OID in order to register it later */
top_oid = (oid*) malloc ( oid_len * sizeof(oid) );
if ( top_oid == NULL ) {
get_time( time_buf );
snmp_log( LOG_ERR,
"%s register_tables(): malloc() for variable top_oid failed\n"
"register_tables(): Toplevel OID .%s\n"
"OSA Subagent MIB information may be incomplete!\n",
time_buf, toid_str );
return -1;
} /* end if */
memcpy( top_oid, t_oid, oid_len * sizeof(oid) );
/* is retrieved Toplevel OID already in linked list? */
src_oid = search_oid( top_oid, oid_len, lhead, &oid_ptr );
if ( src_oid == UNEXP_ERROR ) {
get_time( time_buf );
snmp_log( LOG_ERR,
"%s register_tables(): Unexpected return code from"
" function search_oid() for Toplevel OID .%s\n"
"OSA Subagent MIB information may be incomplete!\n",
time_buf, toid_str );
free( top_oid );
return -1;
}
/* put this Toplevel OID into the linked list, if OID was not found */
else if ( src_oid == OID_NOT_FOUND ) {
ins_oid = oid_insert_after( top_oid, oid_len, oid_ptr );
if ( ins_oid == NULL ) {
get_time( time_buf );
snmp_log( LOG_ERR,
"%s register_tables(): malloc() for new entry in "
"OID list failed for Toplevel OID .%s\nOSA Subagent "
"MIB information may be incomplete!\n", time_buf, toid_str );
free( top_oid );
return -1;
} /* end if */
} /* end if */
/* if OID was found, set insert OID to exact match OID */
else /* src_oid == OID_FOUND */
ins_oid = oid_ptr;
/****************************************************************/
/* add suffixes to variable_x structure for macro REGISTER_MIB */
/****************************************************************/
last_suffix = NULL; /* initialize compare ptr */
table_vars = NULL; /* initialize variable_x ptr */
suf_def = 0; /* number of suffixes */
/* point to suffix entries */
mib_data_ptr += (strlen(mib_data_ptr)+1);
mib_data_ptr = (int*) (PTR_ALIGN4(mib_data_ptr));
/* get number of attached suffix OIDs */
suf_cnt = *((int*) mib_data_ptr);
/* loop through suffix list */
for ( j=0;j < suf_cnt; j++ )
{
/* adjust parse ptr to access type
(align pointer if it follows a string) */
if ( j == 0 )
mib_data_ptr += sizeof( int );
else
{
mib_data_ptr += (strlen(mib_data_ptr)+1);
mib_data_ptr = (int*) (PTR_ALIGN4(mib_data_ptr));
} /* end if */
/* save object access type for registering later */
oid_acc = *((int*) mib_data_ptr);
/* adjust ptr and save object data type for registering later */
mib_data_ptr += sizeof( int );
oid_typ = *((int*) mib_data_ptr);
/* adjust ptr to OID suffix string */
mib_data_ptr += sizeof( int );
/* need to register suffixes only, if I have a new Toplevel OID */
if ( src_oid == OID_NOT_FOUND ) {
/* init last_suffix here, if loop entered the first time */
if ( j==0 )
last_suffix = (char*) mib_data_ptr;
/* check wether last and current OID suffixes match */
/* yes-don't need to register suffix again, goto register index portion */
/* no -add suffix to variable_x list */
if ( (strcmp( last_suffix, (char*) mib_data_ptr ) !=0) || j==0 )
{
suf_def++; /* increase count of suffix definitions */
last_suffix = (char*) mib_data_ptr; /* save suffix */
/* allocate one entry within variable_x struct */
new_area = (struct variable13*)
realloc( table_vars, suf_def * sizeof( struct variable13));
if ( new_area == NULL )
{
get_time( time_buf );
snmp_log( LOG_ERR, "%s register_tables(): "
"realloc() for variable_x structure failed\n"
"register_tables(): for Toplevel OID .%s\n"
"OSA Subagent MIB information may be incomplete!\n",
time_buf, toid_str );
/* remove all memory for this Toplevel OID allocated so far */
free(table_vars);
delete_oid( ins_oid->pObjid, ins_oid->length, lhead );
return -1;
} /* end if */
else
/* reassign table_vars */
table_vars = new_area;
/* convert suffix OID string to net-snmp oid type */
oid_len = str_to_oid_conv( (char*) mib_data_ptr, t_oid );
if ( oid_len == 0 ) {
get_time( time_buf );
snmp_log( LOG_ERR, "%s register_tables(): "
"suffix str to oid conversion failed "
"for Toplevel OID .%s\nOSA Subagent MIB information may "
"be incomplete!\n", time_buf, toid_str );
/* remove all memory for this Toplevel OID allocated so far */
free(table_vars);
delete_oid( ins_oid->pObjid, ins_oid->length, lhead );
return -1;
} /* end if */
/*******************************/
/* set up variable_x structure */
/*******************************/
table_vars[suf_def-1].magic = 0; /* magic is not used */
if ( oid_typ == IPA_DISPLAYSTR ) /* set object type */
table_vars[suf_def-1].type = ASN_OCTET_STR;
else
table_vars[suf_def-1].type = oid_typ;
if ( oid_acc == IPA_WRONLY ) /* have no WRITE ONLY */
table_vars[suf_def-1].acl = RWRITE; /* set to type RWRITE */
else
table_vars[suf_def-1].acl = oid_acc; /* set given object type */
if ( oid_typ == IPA_DISPLAYSTR ) /* set callback functions */
table_vars[suf_def-1].findVar = var_DisplayStr;
else
table_vars[suf_def-1].findVar = var_ibmOSAMib;
table_vars[suf_def-1].namelen = oid_len; /* OID suffix len */
if ( oid_len <= SUFFIX_MAXLEN ) /* set OID suffix */
memcpy( table_vars[suf_def-1].name, t_oid, oid_len * sizeof( oid ));
else
{
get_time( time_buf );
snmp_log( LOG_ERR,
"%s register_tables(): OID suffix length exceeded "
"for Toplevel OID .%s\nSuffix OID length %d\n"
"OSA Subagent MIB information may be incomplete!\n",
time_buf, toid_str, oid_len );
/* remove all memory for this Toplevel OID allocated so far */
free(table_vars);
delete_oid( ins_oid->pObjid, ins_oid->length, lhead );
return -1;
} /* end if */
} /* end if */
} /* end if register_suffix part */
/****************************************************************/
/* add index to index linked list under this Toplevel OID entry */
/****************************************************************/
/* adjust ptr to index portion */
mib_data_ptr = (char*) (mib_data_ptr + (strlen(mib_data_ptr)+1));
/* search index list for this index */
src_ind = search_index( (char*) mib_data_ptr, ins_oid->ind_list, &ind_ptr );
/* if index is not found in the linked list, add index */
if ( src_ind == INDEX_NOT_FOUND ) {
new_index = (char*) malloc( strlen( (char*) mib_data_ptr ) + 1 );
if ( new_index == NULL ) {
get_time( time_buf );
snmp_log( LOG_ERR, "%s register_tables(): "
"malloc() for new index entry failed\n"
"register_tables(): for Toplevel OID .%s\n"
"OSA Subagent MIB information may be incomplete!\n",
time_buf, toid_str);
if ( src_oid == OID_NOT_FOUND ) {
free(table_vars);
delete_oid( ins_oid->pObjid, ins_oid->length, lhead );
}
return -1;
} /* end if */
strcpy( new_index, (char*) mib_data_ptr );
index_insert_after( new_index,
mib_data_hdr->ioctl_cmd.ipa_cmd_hdr.ifIndex,
ind_ptr );
} /* end if */
} /* end for (j) */
/* new Toplevel OID?: yes, then register with agent to add this table */
/* note - register_mib() is taken from the net-snmp agent extension API */
if ( src_oid == OID_NOT_FOUND )
{
if ( register_mib( "ibmOSAMib",(struct variable*) table_vars,
sizeof(struct variable13), suf_def,
top_oid, ins_oid->length ) != MIB_REGISTERED_OK )
{
get_time( time_buf );
snmp_log( LOG_ERR, "%s register_tables(): "
"API function register_mib() failed\n"
"register_tables(): for Toplevel OID .%s\n"
"OSA Subagent MIB information may be incomplete!\n",
time_buf, toid_str );
/* remove all memory for this Toplevel OID allocated so far */
free(table_vars);
delete_oid( ins_oid->pObjid, ins_oid->length, lhead );
return -1;
} /* end if */
else
{
get_time( time_buf );
snmp_log( LOG_INFO, "%s registered Toplevel OID .%s\n",
time_buf, toid_str );
} /* end if */
} /* end if */
/* save variable_x ptr to free allocated memory later, if needed */
ins_oid->var13ptr = table_vars;
/* adjust ptr to next Toplevel OID */
mib_data_ptr = (char*) (mib_data_ptr + (strlen(mib_data_ptr)+1));
} /* end for (i) */
return 0;
} /* end register_tables() */
/************************************************************************
* header_osa_table()
* Compare 'name' to vp->name for the best match or an exact match.
* Store result OID in 'name', including the index that matches best.
* Return matching net-snmp ifIndex to caller.
*
* parameters:
* IN struct variable *vp - ptr to registered subagent MIB data
* INOUT oid *name - fully instantiated OID name
* INOUT size_t *length - length of this OID
* IN int exact - TRUE if an GET match is desired
* OUT size_t *var_len - hook for size of returned data type
* IN WriteMethod **write_method - hook for write method (UNUSED)
* IN TABLE_OID *lhead - ptr to Toplevel OID list head
*
* returns:
* ifIndex - ifIndex in this OID
* -1 (MATCH_FAILED) - no suitable match found
*
************************************************************************/
int header_osa_table( struct variable *vp, oid *name, size_t *length,
int exact, size_t *var_len,
WriteMethod **write_method, TABLE_OID *lhead )
{
int interface = -1;
int i, res, conv;
size_t index_len; /* length of index portion */
oid newname[MAX_OID_LEN]; /* temporary return OID */
oid buffer[MAX_OID_LEN]; /* temporary converion buffer */
char name_index[MAX_OID_STR_LEN];
char time_buf[TIME_BUF_SIZE]; /* date/time buffer */
/* ptr into OID and index linked lists */
TABLE_OID *ptr_oid;
REG_INDICES *ptr_ind;
int found_OID = FALSE;
/* some debugging calls */
DEBUGMSGTL(("ibmOSAMib-Subagent", "header_osa_table: "));
DEBUGMSGOID(("ibmOSAMib-Subagent", name, *length));
DEBUGMSG(("ibmOSAMib-Subagent"," exact=%d\n", exact));
/* OID compare */
/* set 'res' to -1 name < vp->name */
/* 1 name > vp->name */
/* 0 exact match */
for ( i=0, res=0; (i < (int) vp->namelen) && (i < (int) (*length)) && !res; i++ )
{
if ( name[i] != vp->name[i] ) {
if ( name[i] < vp->name[i] )
res = -1;
else
res = 1;
} /* end if */
} /* end for */
DEBUGMSG(("ibmOSAMib-Subagent", " snmp_oid_compare: %d\n", res));
/* (GETNEXT AND search OID still greater) OR (GET AND not-exact OIDs) */
/* yes - indicate match failed */
if ( (!exact && (res > 0)) || (exact && (res != 0)) ) {
if (var_len)
*var_len = 0;
return MATCH_FAILED;
} /* end if */
/* init temporary return OID */
memset(newname, 0, sizeof(newname));
/******************************************/
/* handle GET requests with matching OIDs */
/******************************************/
if ( exact && res == 0 )
{
/* got a too short OID */
if ( (*length) <= vp->namelen ) {
if (var_len)
*var_len = 0;
return MATCH_FAILED;
}
else
/* determine length of attached index */
index_len = (int) (*length) - (int) vp->namelen;
DEBUGMSG(("ibmOSAMib-Subagent",
" header_osa_table - GET index length: %zd\n", index_len));
/* search our internal linked list for a matching Toplevel OID */
res = search_top_oid ( (oid*) vp->name, (size_t) vp->namelen,
lhead, &ptr_oid );
/* found a matching Toplevel OID, now look for index portion */
if ( res == OID_FOUND ) {
DEBUGMSGOID(("ibmOSAMib-Subagent:header_osa_table - Toplevel OID found",
ptr_oid->pObjid, ptr_oid->length));
/* convert index portion to string */
conv = oid_to_str_conv ( (oid*) &name[vp->namelen],
index_len, name_index );
DEBUGMSG(("ibmOSAMib-Subagent"," index portion=%s\n", name_index));
if (conv == TRUE) {
res = search_index ( name_index,
(REG_INDICES*) ptr_oid->ind_list, &ptr_ind );
/* found a matching index, OID for GET request exists! */
if ( res == INDEX_FOUND ) {
DEBUGMSG(("ibmOSAMib-Subagent"," index found in linked list\n"));
/* return appropriate ifIndex responsible for that OID */
interface = ptr_ind->ifIndex;
/* set up return OID */
memmove( newname, name, (*length) * sizeof(oid) );
found_OID = TRUE;
} /* end if */
} /* end if */
} /* end if */
} /* end if */
/***************************/
/* handle GETNEXT requests */
/***************************/
else if ( !exact && res <= 0 )
{
/* OID too short or switched to next suffix */
/* adjust length and attach first index */
if ( (int) (*length) <= (int) vp->namelen || res < 0 )
{
DEBUGMSG(("ibmOSAMib-Subagent",
" GETNEXT - length <= vp->namelen OR snmp_oid_compare < 0"));
/* search our internal linked list for a matching Toplevel OID */
res = search_top_oid ( (oid*) vp->name, vp->namelen, lhead, &ptr_oid );
/* found a matching Toplevel OID, now look for index portion */
if ( res == OID_FOUND ) {
DEBUGMSGOID(("ibmOSAMib-Subagent:header_osa_table - Toplevel OID found",
ptr_oid->pObjid, ptr_oid->length));
/* set up return OID */
memmove( newname, vp->name, (int) vp->namelen * sizeof(oid) );
*length = vp->namelen;
/* retrieve first index under this Toplevel OID and attach to newname */
if ( ptr_oid->ind_list->next != NULL ) {
index_len = str_to_oid_conv ( ptr_oid->ind_list->next->full_index,
buffer );
if ( index_len != 0 && ( (vp->namelen + index_len) <= MAX_OID_LEN ) ) {
memmove ( &newname[vp->namelen], buffer, index_len * sizeof(oid) );
*length = *length + index_len;
DEBUGMSG(("ibmOSAMib-Subagent"," index portion to attach=%s\n"
,ptr_oid->ind_list->next->full_index ));
/* return appropriate ifIndex responsible for that OID */
interface = ptr_oid->ind_list->next->ifIndex;
found_OID = TRUE;
}
else
{
get_time( time_buf );
snmp_log( LOG_ERR, "%s header_osa_table(): "
"(GETNEXT-1) index list corrupted\n"
"OSA Subagent MIB information may be incomplete!\n",
time_buf );
} /* end if */
} /* end if */
} /* end if */
}
/* 'true' GETNEXT case */
else
{
DEBUGMSG(("ibmOSAMib-Subagent",
" GETNEXT - length > vp->namelen"));
/* search our internal linked list for a matching Toplevel OID */
res = search_top_oid ( (oid*) name, (int) (*length),
lhead, &ptr_oid );
/* found a matching Toplevel OID, now look for index portion */
if ( res == OID_FOUND ) {
DEBUGMSGOID(("ibmOSAMib-Subagent: "
"header_osa_table - Toplevel OID found",
ptr_oid->pObjid, ptr_oid->length));
/* search the index attached to 'name' in the index list */
/* determine length of attached index and convert to a string */
index_len = (int) (*length) - (int) vp->namelen;
conv = oid_to_str_conv ( (oid*) &name[vp->namelen],
index_len, name_index );
if (conv == TRUE) {
res = search_index ( name_index,
(REG_INDICES*) ptr_oid->ind_list, &ptr_ind );
/* next index is the one we're looking for */
/* if next index is NULL; return MATCH FAILED(goto next suffix) */
if( ptr_ind->next != NULL ) {
index_len = str_to_oid_conv( ptr_ind->next->full_index, buffer);
if ( index_len != 0 && ( (vp->namelen + index_len) <= MAX_OID_LEN ) ) {
DEBUGMSG(("ibmOSAMib-Subagent"," index portion to attach=%s\n"
,ptr_ind->next->full_index ));
/* set up return OID */
*length = vp->namelen;
memmove( newname, name, vp->namelen * sizeof(oid) );
memmove( &newname[vp->namelen], buffer, index_len * sizeof(oid) );
*length = *length + index_len;
/* return appropriate ifIndex responsible for that OID */
interface = ptr_ind->next->ifIndex;
found_OID = TRUE;
} /* end if */
else
{
get_time( time_buf );
snmp_log( LOG_ERR, "%s header_osa_table(): "
"(GETNEXT-2) index list corrupted\n"
"OSA Subagent MIB information may be incomplete!\n",
time_buf );
} /* end if */
} /* end if */
} /* end */
}
else
{
get_time( time_buf );
snmp_log( LOG_ERR, "%s header_osa_table(): "
"(GETNEXT-2) Toplevel OID not found\n"
"OSA Subagent MIB information may be incomplete!\n",
time_buf );
} /* end if */
} /* end if - handle GETNEXT requests */
}
/* return MATCH_FAILED, if no appropriate OID was found */
if ( !found_OID )
{
if (var_len)
*var_len = 0;
return MATCH_FAILED;
}
else
{
/* finalize OID to be returned */
memmove(name, newname, (*length) * sizeof(oid));
if (write_method)
*write_method = 0;
if (var_len)
*var_len = sizeof(long); /* default data type long */
return interface;
} /* end if */
} /* end header_osa_table */
/************************************************************************
* update_mib_info()
* Whenever a network interface appears or disappears the MIB and/or
* interface information has to be updated, this fuction is called.
*
* parameters:
* none
* returns:
* none
*
************************************************************************/
void update_mib_info ()
{
TABLE_OID *mib_info = oid_list_head;
char time_buf[TIME_BUF_SIZE]; /* date/time buffer */
int i, retc,
sd, /* socket descriptors */
error_code, /* used to save errno */
if_num, /* number of network interfaces */
osaexp_num; /* number of OSA-E devices */
struct ifreq ifr; /* request structure for ioctl */
IPA_CMD_REG* ipa_reg_mib; /* structure for IPA REGISTER MIB command header */
IF_LIST* tmp_list; /* temporary interfaces list */
char* buffer; /* a data buffer */
/* Retrieve ifNumber/ifIndex/ifDescr newly from IF-MIB for all interfaces */
/* retrieve data in temporary list first */
if_num = query_IF_MIB( &tmp_list );
if ( if_num < 0 )
{
get_time( time_buf );
snmp_log( LOG_ERR, "%s update_mib_info(): "
"could not get interface info from IF-MIB\n"
"update_mib_info(): check previous messages for more details\n"
"update_mib_info(): keeping original interface lists\n",
time_buf );
return;
}
/* query OSA-E device driver for OSA-E devices
* and mark them in IF-MIB interface list
* */
osaexp_num = query_OSA_EXP( &tmp_list, if_num );
if ( osaexp_num == 0 )
{
get_time( time_buf );
snmp_log( LOG_ERR, "%s update_mib_info(): "
"no or bad OSA Express devices reported"
" - continue processing\n"
"update_mib_info(): "
"if available, see previous message for reason\n"
"update_mib_info(): freeing interface lists\n",
time_buf );
free( tmp_list );
/* remove all index entries from Toplevel OID
* linked list and store ifNumber
* */
clear_oid_list( mib_info );
ifNumber = if_num;
return;
} /* end if */
/* allocate area, that should contain retrieved MIB
* data for a single interface
* */
buffer = (char*) malloc( MIB_AREA_LEN );
if ( buffer == NULL )
{
get_time( time_buf );
snmp_log( LOG_ERR, "%s update_mib_info(): "
"malloc() for REGISTER MIB data buffer "
"failed\nupdate_mib_info(): requested %d bytes\n"
"update_mib_info(): keeping original interface lists\n",
time_buf, MIB_AREA_LEN );
free( tmp_list );
return;
} /* end if */
/* socket for query MIB information ioctl */
sd = socket( AF_INET, SOCK_STREAM, 0 );
if ( sd < 0 )
{
error_code = errno;
get_time( time_buf );
snmp_log(LOG_ERR, "%s update_mib_info(): "
"error opening socket() - reason %s\n"
"update_mib_info(): cannot update OSA-E MIB information\n"
"update_mib_info(): keeping original interface lists\n",
time_buf, strerror( error_code ) );
free( tmp_list );
free( buffer );
return;
} /* end if */
/* free original interface list and assign the new one (global data) */
if ( if_list != NULL )
free( if_list );
ifNumber = if_num;
if_list = tmp_list;
/* free entire MIB lists that we maintain so far */
clear_oid_list( mib_info );
/* walk through interface list and query MIB data
* for all OSA-E devices register MIB data with
* subagent driving code afterwards
* */
for ( i=0; i < ifNumber; i++ )
{
if ( if_list[i].is_OSAEXP == TRUE )
{
/* clear buffer */
memset( buffer, 0, MIB_AREA_LEN );
/* setup ioctl buffer with request and input parameters */
/* map command structure */
ipa_reg_mib = (IPA_CMD_REG*) buffer;
/* size of IPA data area */
ipa_reg_mib->ioctl_cmd.data_len =
MIB_AREA_LEN - offsetof( IOCTL_CMD_HDR, ipa_cmd_hdr );
/* length of IPA subcommand */
ipa_reg_mib->ioctl_cmd.req_len =
sizeof( ipa_reg_mib->ioctl_cmd.ipa_cmd_hdr );
/* set input parameters for IPA Register MIB command */
ipa_reg_mib->ioctl_cmd.ipa_cmd_hdr.request = IPA_REG_MIB;
ipa_reg_mib->ioctl_cmd.ipa_cmd_hdr.ifIndex = if_list[i].ifIndex;
ipa_reg_mib->ioctl_cmd.ipa_cmd_hdr.ret_code = 0;
ipa_reg_mib->ioctl_cmd.ipa_cmd_hdr.seq_num = 0;
/* do ioctl() */
strcpy( ifr.ifr_name, if_list[i].if_Name ); /* add interface name */
ifr.ifr_ifru.ifru_data = (char*) buffer; /* add data buffer */
if ( ioctl( sd,SIOC_QETH_ADP_SET_SNMP_CONTROL, &ifr ) < 0 )
{
error_code = errno;
get_time( time_buf );
/* see if we got a common I/O error */
if ( error_code == -EIO )
{
snmp_log( LOG_ERR, "%s update_mib_info(): "
"ioctl() failed - reason %s for interface %s\n"
"update_mib_info(): "
"MIB information may be incomplete\n",
time_buf, strerror( error_code ),
if_list[i].if_Name );
continue;
break;
} /* end if */
/* let's see, if we got a return code from IPAssists */
/* or if MIB buffer is exhausted */
switch ( ipa_reg_mib->ioctl_cmd.ipa_cmd_hdr.ret_code ) {
case IPA_FAILED:
snmp_log( LOG_ERR, "%s update_mib_info(): "
"ioctl() failed - IPA command failed\n"
"update_mib_info(): for interface %s\n"
"update_mib_info(): MIB information may be incomplete\n",
time_buf, if_list[i].if_Name );
continue;
break;
case IPA_NOT_SUPP:
snmp_log( LOG_ERR, "%s update_mib_info(): "
"ioctl() failed - IPA command not supported\n"
"update_mib_info(): for interface %s\n"
"update_mib_info(): MIB information may be incomplete\n",
time_buf, if_list[i].if_Name );
continue;
break;
case IPA_NO_DATA:
snmp_log( LOG_ERR, "%s update_mib_info(): "
"ioctl() failed - valid IPA command, but no"
"SNMP data is available for interface %s\n"
"update_mib_info(): MIB information may be incomplete\n",
time_buf, if_list[i].if_Name );
continue;
break;
case -ENOMEM: /* should not happen in the near future ;-) */
snmp_log( LOG_ERR, "%s update_mib_info(): "
"ioctl() failed - MIB data size > "
"constant MIB_AREA_LEN for interface %s\n"
"update_mib_info(): "
"Enlarge constant for MIB_AREA_LEN "
"within ibmOSAMibDefs.h and "
"recompile the subagent\n"
"update_mib_info(): MIB information may be incomplete\n",
time_buf, if_list[i].if_Name );
continue;
break;
default:
snmp_log( LOG_ERR, "%s update_mib_info(): "
"ioctl() failed - reason %s "
"for interface %s\n"
"update_mib_info(): MIB information may be incomplete\n",
time_buf, strerror( error_code ), if_list[i].if_Name );
continue;
break;
} /* end switch */
}
else if ( ipa_reg_mib->ioctl_cmd.ipa_cmd_hdr.ret_code != 0 )
{
get_time( time_buf );
/* now check IPA SNMP subcommand return code */
switch ( ipa_reg_mib->ioctl_cmd.ipa_cmd_hdr.ret_code ) {
case IPA_SNMP_INV_TOPOID:
case IPA_SNMP_INV_GROUP:
case IPA_SNMP_INV_SUFFIX:
case IPA_SNMP_INV_INST:
case IPA_SNMP_OID_NREAD:
case IPA_SNMP_OID_NWRIT:
snmp_log( LOG_ERR, "%s update_mib_info(): "
"IPA SNMP subcommand failed - "
"return code 0x%x for interface %s\n"
"update_mib_info(): MIB information may be incomplete\n",
time_buf,
ipa_reg_mib->ioctl_cmd.ipa_cmd_hdr.ret_code,
if_list[i].if_Name );
continue;
break;
case IPA_SNMP_NOT_SUPP:
snmp_log( LOG_ERR, "%s update_mib_info(): "
"IPA SNMP subcommand failed - "
"subcommand 0x%x for interface %s\n"
"update_mib_info(): MIB information may be incomplete\n",
time_buf,
ipa_reg_mib->ioctl_cmd.ipa_cmd_hdr.request,
if_list[i].if_Name );
continue;
break;
case IPA_SNMP_NO_DATA:
snmp_log( LOG_ERR, "%s update_mib_info(): "
"IPA SNMP subcommand failed - "
"no data available for interface %s\n"
"update_mib_info(): MIB information may be incomplete\n",
time_buf, if_list[i].if_Name );
continue;
break;
default:
snmp_log( LOG_ERR, "%s update_mib_info(): "
"IPA SNMP subcommand failed - "
"undefined return code 0x%x for interface %s\n"
"update_mib_info(): MIB information may be incomplete\n",
time_buf,
ipa_reg_mib->ioctl_cmd.ipa_cmd_hdr.ret_code,
if_list[i].if_Name );
continue;
break;
} /* end switch */
} /* end if */
/* register MIB tables information, that we got from IPAssists */
retc = register_tables ( buffer, mib_info );
if ( retc != 0 )
{
get_time( time_buf );
snmp_log( LOG_ERR, "%s update_mib_info(): "
"register MIB data with subagent "
"driving code failed\nupdate_mib_info(): for interface %s\n"
"update_mib_info(): check previous messages for "
"more details\nupdate_mib_info(): MIB information may be "
"incomplete\n", time_buf, if_list[i].if_Name );
continue;
} /* end if */
} /* end if */
} /* end for */
get_time( time_buf );
snmp_log( LOG_INFO, "%s *** OSA-E interface change indicated ***\n"
"%s *** Reinitialized MIB information ***\n",
time_buf, time_buf );
close( sd );
free( buffer );
} /* end update_mib_info */
/**********************************************************************
* query_IF_MIB():
* Retrieve ifIndex values for all OSA devices residing on this
* system. Use SNMP to query the master agent for ifNumber and
* ifIndex/ifDescr values from the standard IF-MIB.
* Then figure out which of these devices are OSA Express devices.
* parameters:
* INOUT IF_LIST** ifList: List of network interfaces on this system
* returns: int if_Number - number of network interfaces on this system
* system (>=0)
* -1 -an error occurred , no valid info avail
*********************************************************************/
int query_IF_MIB ( IF_LIST** ifList )
{
char time_buf[TIME_BUF_SIZE]; /* date/time buffer */
/* data structures for SNMP API */
struct snmp_session session, *ss;
struct snmp_pdu *pdu;
struct snmp_pdu *response;
struct variable_list *vars;
void *sessp;
int status, have_info, valid;
/* define static OIDs for if_Number, ifIndex and ifDescr from IF-MIB */
size_t ifNumber_OIDlen = 9,
ifIndex_OIDlen = 11,
ifDescr_OIDlen = 11;
oid ifNumber_OID[9] = { 1,3,6,1,2,1,2,1,0 },
ifIndex_OID[11] = { 1,3,6,1,2,1,2,2,1,1,0 },
ifDescr_OID[11] = { 1,3,6,1,2,1,2,2,1,2,0 };
int i, if_Number, count;
/* Initialize the SNMP library */
DEBUGMSGTL(("query_IF_MIB"," about to query IF-MIB information using SNMP\n"));
/* Initialize a "session" for localhost */
have_info = TRUE;
valid = TRUE;
if_Number = 0;
snmp_sess_init( &session );
session.peername = NET_SNMP_PEERNAME;
session.version = SNMP_VERSION_2c; /* use SNMPv2c */
/* SNMPv2c community name */
session.community = (unsigned char*)NET_SNMP_COMMUNITY;
session.community_len = strlen((const char*)session.community);
session.timeout = 300 * 1000000L;
/* Open the session */
sessp = snmp_sess_open( &session );
if ( sessp == NULL ) {
get_time( time_buf );
snmp_log(LOG_ERR,
"%s query_IF_MIB(): snmp_sess_open() failed\n", time_buf );
return -1;
} /* end if */
ss = snmp_sess_session( sessp );
/* Create and send synchronous GET PDU for if_Number */
pdu = snmp_pdu_create(SNMP_MSG_GET);
snmp_add_null_var( pdu, ifNumber_OID, ifNumber_OIDlen );
status = snmp_sess_synch_response( sessp, pdu, &response);
/* Process the response and get ifIndex/ifDescr table entries */
if (status == STAT_SUCCESS && response->errstat == SNMP_ERR_NOERROR)
{
/* get value for if_Number */
if ( response->variables->val.integer == NULL )
{
get_time( time_buf );
snmp_log(LOG_ERR, "%s query_IF_MIB(): Get(if_Number) Error in packet\n"
"Reason: response->variables->val.integer == NULL\n",
time_buf);
snmp_free_pdu(response);
return -1;
} /* end if */
count = (int) *(response->variables->val.integer);
snmp_free_pdu(response);
if ( count == 0 )
{
snmp_sess_close( sessp );
return 0;
} /* end if */
/* allocate memory for interface list */
*ifList = (IF_LIST*) malloc((sizeof(IF_LIST) * count));
if (*ifList == NULL)
{
get_time( time_buf );
snmp_log(LOG_ERR,
"%s query_IF_MIB(): malloc() for ifList structure failed!\n",
time_buf);
snmp_sess_close( sessp );
return -1;
} /* end if */
/* if have interfaces, issue GETNEXT PDUs for ifIndex/ifDescr table entries */
for ( i=0; i < count; i++ )
{
pdu = snmp_pdu_create( SNMP_MSG_GETNEXT );
snmp_add_null_var( pdu, ifIndex_OID, ifIndex_OIDlen );
snmp_add_null_var( pdu, ifDescr_OID, ifDescr_OIDlen );
status = snmp_sess_synch_response( sessp, pdu, &response );
if (status == STAT_SUCCESS && response->errstat == SNMP_ERR_NOERROR)
{
/* set device to default value false;
* device type is determined later
* */
(*ifList)[i].is_OSAEXP = FALSE;
(*ifList)[i].kerIndex = 0;
(*ifList)[i].ifIndex = 0;
/* get values for ifIndex/ifDescr from response PDU
* FIXME: (workaround) compare ifDescr values
* and omit double entries
* */
for(vars = response->variables; vars; vars = vars->next_variable)
{
if( vars->type == ASN_INTEGER )
(*ifList)[if_Number].ifIndex = (int) *(vars->val.integer);
else if( vars->type == ASN_OCTET_STR
&& vars->val_len <= IFNAME_MAXLEN )
{
if ( if_Number == 0 )
{
strncpy((char*)((*ifList)[0]).if_Name,
(const char*)vars->val.string, vars->val_len);
(*ifList)[0].if_Name[vars->val_len] = '\0';
}
else
{
if (strncmp((const char*)(*ifList)[if_Number-1].if_Name,
(const char*)vars->val.string,
vars->val_len) !=0)
{
strncpy((char*)(*ifList)[if_Number].if_Name,
(const char*)vars->val.string,
vars->val_len);
(*ifList)[if_Number].if_Name[vars->val_len] = '\0';
valid = TRUE;
}
else
valid = FALSE;
} /* end if */
}
else
{
get_time( time_buf );
snmp_log(LOG_ERR, "%s query_IF_MIB(): GetNext(ifIndex;ifDescr)"
" response PDU has invalid data\n", time_buf );
free( *ifList );
snmp_free_pdu(response);
snmp_sess_close( sessp );
return -1;
} /* end if */
} /* end for */
if ( valid == TRUE )
if_Number++;
}
else
{
/* FAILURE GETNEXT */
if (status == STAT_SUCCESS)
{
get_time( time_buf );
snmp_log(LOG_ERR, "%s query_IF_MIB(): GetNext(ifIndex,ifDescr) "
"Error in packet\n"
"Reason: %s\n",time_buf, snmp_errstring(response->errstat));
}
else
snmp_sess_perror("query_IF_MIB(): GetNext(ifIndex;ifDescr)", ss);
if (response)
snmp_free_pdu(response);
free( *ifList );
have_info = FALSE;
break;
} /* end if */
/* store current ifIndex in OIDs for next GetNext request */
ifIndex_OID[ifIndex_OIDlen-1] = (*ifList)[i].ifIndex;
ifDescr_OID[ifDescr_OIDlen-1] = (*ifList)[i].ifIndex;
snmp_free_pdu( response );
} /* end for */
}
else
{
/* FAILURE GET if_Number */
if (status == STAT_SUCCESS)
{
get_time( time_buf );
snmp_log(LOG_ERR, "%s query_IF_MIB(): Get(if_Number) Error in packet\n"
"Reason: %s\n", time_buf, snmp_errstring(response->errstat));
}
else
snmp_sess_perror("query_IF_MIB(): Get(if_Number)", ss);
if (response)
snmp_free_pdu(response);
have_info = FALSE;
} /* end if */
/* Cleanup */
snmp_sess_close( sessp );
if ( have_info )
return ( if_Number );
else
return -1;
} /* end query_IF_MIB() */
/**********************************************************************
* query_OSA_EXP():
* Retrieve device characteristics for OSA Express devices and mark
* OSA Express devices in the interface list from IF-MIB.
* parameters:
* INOUT IF_LIST** ifList: List of network interfaces on this system
* IN int if_Number: number of network interfaces
* returns: int num - number of OSA Express devices found on this
* system (>=0)
*********************************************************************/
unsigned int query_OSA_EXP ( IF_LIST** ifList, int if_Number )
{
int j, num = 0;
char time_buf[TIME_BUF_SIZE]; /* date/time buffer */
int sd;
struct ifreq ifr;
/*open socket to get information if device is an OSA device*/
if ( (sd = socket(AF_INET,SOCK_STREAM,0)) < 0 ) {
snmp_log( LOG_ERR,"%s query_OSA_EXP(): "
"socket failed\n"
"query_OSA_EXP(): cancel init or update "
"of MIB information\n",time_buf );
return 0;
}
/* walk through IF-MIB interface list and mark OSA Express interfaces */
for ( j=0; j < if_Number; j++ ) {
int ret=0;
memset(&ifr,0,sizeof(ifr));
strncpy(ifr.ifr_name, (*ifList)[j].if_Name,IFNAME_MAXLEN);
ret = ioctl(sd, SIOC_QETH_GET_CARD_TYPE, &ifr);
if (ret>0) {
(*ifList)[j].is_OSAEXP = TRUE;
(*ifList)[j].kerIndex = (*ifList)[j].ifIndex;
num++;
}
} /* end for */
close(sd);
return num;
} /* end query_OSA_EXP() */
/**********************************************************************
* get_time():
* gets current time of day string and returns it as
* MONTH DAY HH:MM:SS
* returns: string with date and time
*********************************************************************/
int get_time( char* buffer )
{
time_t curtime;
struct tm *loctime;
curtime = time(NULL);
loctime = localtime( &curtime );
strftime( buffer, TIME_BUF_SIZE, "%b %d %T", loctime );
return 0;
} /* end get_time () */
static const char* usage_text[] = {
"Usage: osasnmpd [-h] [-v] [-l LOGFILE] [-A] [-f] [-L] [-P PIDFILE]",
" [-x SOCKADDR]",
"",
"-h, --help This usage message",
"-v, --version Version information",
"-l, --logfile LOGFILE Print warnings/messages to LOGFILE",
"-A, --append Append to the logfile rather than truncating it",
"-L, --stderrlog Print warnings/messages to stdout/err",
"-f, --nofork Do not fork() from the calling shell",
"-P, --pidfile PIDFILE Save the process ID of the subagent in PIDFILE",
"-x, --sockaddr SOCKADDR Bind AgentX port to this address",
""
};
/**********************************************************************
* usage():
* prints help message with descriptions of available parameters
* IN name of subagent
* returns: none
*********************************************************************/
void usage()
{
unsigned int i;
for (i=0; i < sizeof(usage_text) / sizeof(usage_text[0]); i++)
printf("%s\n", usage_text[i]);
exit(0);
} /* end usage() */