Initial s390-tools-2.0.0 import

This commit is based on the s390-tools-1.39.0 version.

Changes on top of s390-tools-1.39.0:

 - Add MIT license to all source files
 - Add LICENSE file
 - Transform REAMDE to README.md (markdown)
 - Add AUTHORS.md file
 - Add CONTRIBUTING.md file
 - Move changelog from README to CHANGELOG.md file

Reviewed-by: Stefan Haberland <sth@linux.vnet.ibm.com>
Signed-off-by: Michael Holzheu <holzheu@linux.vnet.ibm.com>
This commit is contained in:
Michael Holzheu
2017-08-07 16:13:17 +02:00
commit b627b8d8e1
647 changed files with 168974 additions and 0 deletions

40
osasnmpd/Makefile Normal file
View File

@@ -0,0 +1,40 @@
include ../common.mak
LDLIBS = `net-snmp-config --agent-libs`
CFLAGS += `net-snmp-config --cflags`
OBJS = ibmOSAMib.o ibmOSAMibUtil.o osasnmpd.o
ifeq (${HAVE_SNMP},0)
all:
$(SKIP) HAVE_SNMP=0
install:
$(SKIP) HAVE_SNMP=0
else
check_dep:
$(call check_dep, \
"osasnmpd", \
"net-snmp/net-snmp-config.h", \
"net-snmp-devel or libsnmp-dev", \
"HAVE_SNMP=0")
all: check_dep osasnmpd
osasnmpd: $(OBJS)
install: all
$(INSTALL) -d -m 755 $(DESTDIR)$(USRSBINDIR) $(DESTDIR)$(MANDIR)/man8
$(INSTALL) -g $(GROUP) -o $(OWNER) -m 755 osasnmpd \
$(DESTDIR)$(USRSBINDIR)
$(INSTALL) -g $(GROUP) -o $(OWNER) -m 644 osasnmpd.8 \
$(DESTDIR)$(MANDIR)/man8
endif
clean:
rm -f $(OBJS) osasnmpd core
.PHONY: all install clean

927
osasnmpd/ibmOSAMib.c Normal file
View File

@@ -0,0 +1,927 @@
/*
* osasnmpd - IBM OSA-Express network card SNMP subagent
*
* Basic MIB implementation module for the OSA-E subagent
*
* The code in this module is typical for a net-snmp MIB implementation
* information on how this works because the MIB layout is retrieved during
* startup of the subagent, the magic identifier is not used within this
* implementation. The var_ function uses the vp->type instead to distinct
* the OIDs.
*
* Copyright 2017 IBM Corp.
*
* 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 "lib/zt_common.h"
#include "ibmOSAMibUtil.h"
#include "ibmOSAMib.h"
/* ptr to OSA Express MIB information stored in linked lists */
TABLE_OID* oid_list_head;
/* ptr to interface information on this system */
IF_LIST* if_list;
int ifNumber;
/**********************************************************************
* init_ibmOSAMib():
* Initialization routine. This function is called when the agent
* starts up.
* parameters:
* IN uses global MIB data
* OUT none
* returns: none
*********************************************************************/
void init_ibmOSAMib(void) {
int i,
sd, /* socket descriptor */
error_code, /* holds errno value */
osaexp_num, /* number of OSA Express devices */
retc; /* return code from register_tables */
struct ifreq ifr; /* request structure for ioctl */
IPA_CMD_REG* ipa_reg_mib; /* structure for IPA REGISTER MIB command header */
char* buffer; /* a data buffer */
char time_buf[TIME_BUF_SIZE]; /* date/time buffer */
/* init head for Toplevel OID linked list */
oid_list_head = init_oid_list();
if ( oid_list_head == NULL )
{
fprintf( stderr, "init_ibmOSAMib(): "
"malloc() for OID list head failed\n"
"Cannot start subagent...exiting...\n");
exit(1);
}
/* GET net-snmp ifNumber/ifIndex/ifDescr from IF-MIB for all interfaces */
/* on this system */
ifNumber = query_IF_MIB( &if_list );
if ( ifNumber < 0 )
{
fprintf( stderr, "init_ibmOSAMib(): "
"could not obtain interface info from IF-MIB\n"
"check if: snmpd daemon is started and subagent "
"access control is correct\n"
"see agent log file for more details\n"
"Cannot start subagent...exiting...\n");
exit(1);
}
else if ( ifNumber == 0 )
{
get_time( time_buf );
snmp_log( LOG_ERR, "%s init_ibmOSAMib(): "
"SNMP reports no devices within IF-MIB"
" - starting subagent anyway\n", time_buf );
return;
} /* end if */
/* query OSA-E device driver for OSA-E devices and mark them in IF-MIB interface list */
osaexp_num = query_OSA_EXP ( &if_list, ifNumber );
if ( osaexp_num < 0 )
{
fprintf( stderr, "init_ibmOSAMib(): "
"OSA-E device driver query interface ioctl() failed\n"
"check agent log file for more details\n"
"Cannot start subagent...exiting...\n");
exit(1);
}
else if ( osaexp_num == 0 )
{
fprintf( stderr, "init_ibmOSAMib(): bad or no OSA-E devices reported\n"
"check agent log file for more details\n"
"Cannot start subagent...exiting...\n");
exit(1);
}
/* end if */
/* allocate area, that should contain retrieved MIB data for a single interface */
buffer = (char*) malloc ( MIB_AREA_LEN );
if ( buffer == NULL )
{
fprintf( stderr, "init_ibmOSAMib(): "
"malloc() for REGISTER MIB data buffer "
"failed\ninit_ibmOSAMib(): requested %d bytes\n"
"Cannot start subagent...exiting...\n",
MIB_AREA_LEN );
exit(1);
} /* end if */
/* open socket for ioctl */
sd = socket( AF_INET, SOCK_STREAM, 0 );
if ( sd < 0 )
{
error_code = errno;
fprintf( stderr, "init_ibmOSAMIB(): "
"error opening socket() - reason %s\n"
"Cannot start subagent...exiting...\n",
strerror( error_code ) );
exit(1);
} /* end if */
/* 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 */
ipa_reg_mib = (IPA_CMD_REG*) buffer; /* map command structure */
ipa_reg_mib->ioctl_cmd.data_len = /* length of IPA data area */
MIB_AREA_LEN - offsetof( IOCTL_CMD_HDR, ipa_cmd_hdr );
ipa_reg_mib->ioctl_cmd.req_len = /* length of IPA subcommand */
sizeof( ipa_reg_mib->ioctl_cmd );
ipa_reg_mib->ioctl_cmd.ipa_cmd_hdr.request = IPA_REG_MIB; /* IPA subcommand code */
ipa_reg_mib->ioctl_cmd.ipa_cmd_hdr.ifIndex = if_list[i].ifIndex; /* assign IF-MIB ifIndex */
ipa_reg_mib->ioctl_cmd.ipa_cmd_hdr.ret_code = 0;
ipa_reg_mib->ioctl_cmd.ipa_cmd_hdr.seq_num = 0; /* sequence number not used */
/* 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;
/* see if we got a common I/O error */
if ( error_code == -EIO )
{
get_time( time_buf );
snmp_log( LOG_ERR, "%s init_ibmOSAMib(): "
"ioctl() failed - reason %s for interface %s\n"
"init_ibmOSAMib(): start subagent anyway\n",
time_buf, strerror( error_code ), if_list[i].if_Name );
close( sd );
free( buffer );
return;
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:
fprintf( stderr, "init_ibmOSAMib(): "
"ioctl() failed - IPA command failed "
"init_ibmOSAMib(): "
"Can't get MIB information for network interface %s\n"
"Cannot start subagent...exiting...\n", if_list[i].if_Name );
break;
case IPA_NOT_SUPP:
fprintf( stderr, "init_ibmOSAMib(): "
"ioctl() failed - IPA command not supported "
"init_ibmOSAMib(): "
"Can't get MIB information for network interface %s\n"
"Cannot start subagent...exiting...\n", if_list[i].if_Name );
break;
case IPA_NO_DATA:
get_time( time_buf );
snmp_log( LOG_ERR, "%s init_ibmOSAMib(): "
"ioctl() failed - valid IPA command, but no"
" SNMP data is available for interface %s\n"
"init_ibmOSAMib(): start subagent anyway\n",
time_buf, if_list[i].if_Name );
close( sd );
free( buffer );
return;
break;
case -ENOMEM: /* should not happen in the near future ;-) */
fprintf( stderr, "init_ibmOSAMib(): "
"ioctl() failed - MIB data size > "
"constant MIB_AREA_LEN\n"
"init_ibmOSAMib(): "
"Enlarge constant for MIB_AREA_LEN within "
"ibmOSAMibDefs.h and recompile the subagent\n"
"init_ibmOSAMib(): "
"Can't get MIB information for network interfaces\n"
"Cannot start subagent...exiting...\n" );
break;
default:
fprintf( stderr, "init_ibmOSAMib(): "
"ioctl() failed - reason %s\n"
"init_ibmOSAMib(): "
"Can't get MIB information for network interface %s\n"
"Cannot start subagent...exiting...\n",
strerror( error_code ), if_list[i].if_Name );
break;
} /* end switch */
exit(1);
}
else if( ipa_reg_mib->ioctl_cmd.ipa_cmd_hdr.ret_code != 0 )
{
/* 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:
get_time( time_buf );
snmp_log( LOG_ERR, "%s init_ibmOSAMib(): "
"IPA SNMP subcommand failed\n"
"init_ibmOSAMib(): "
"IPA SNMP subcommand return code 0x%x\n"
"init_ibmOSAMib(): "
"Can't get MIB information for network interface %s\n"
"Cannot start subagent...exiting...\n", time_buf,
ipa_reg_mib->ioctl_cmd.ipa_cmd_hdr.ret_code,
if_list[i].if_Name );
break;
case IPA_SNMP_NOT_SUPP:
get_time( time_buf );
snmp_log( LOG_ERR, "%s init_ibmOSAMib(): "
"IPA SNMP subcommand failed - subcommand 0x%x "
"not supported\ninit_ibmOSAMib(): "
"Can't get MIB information for network interface %s\n"
"Cannot start subagent...exiting...\n", time_buf,
ipa_reg_mib->ioctl_cmd.ipa_cmd_hdr.request,
if_list[i].if_Name );
break;
case IPA_SNMP_NO_DATA:
get_time( time_buf );
snmp_log( LOG_ERR, "%s init_ibmOSAMib(): "
"IPA SNMP subcommand failed - no data available\n"
"init_ibmOSAMib(): "
"Can't get MIB information for network interface %s\n"
"Cannot start subagent...exiting...\n", time_buf,
if_list[i].if_Name );
break;
default:
get_time( time_buf );
snmp_log( LOG_ERR, "%s init_ibmOSAMib(): "
"IPA SNMP subcommand failed - undefined return code"
" 0x%x\ninit_ibmOSAMib(): "
"Can't get MIB information for network interface %s\n"
"Cannot start subagent...exiting...\n", time_buf,
ipa_reg_mib->ioctl_cmd.ipa_cmd_hdr.ret_code,
if_list[i].if_Name );
break;
} /* end switch */
exit(1);
} /* end if */
/* save microcode level */
if_list[i].ipa_ver = ipa_reg_mib->ioctl_cmd.ipa_cmd_hdr.ipa_ver;
/* register initial table information, that we got from IPAssists */
retc = register_tables ( buffer, oid_list_head );
if ( retc != 0 )
{
fprintf( stderr, "init_ibmOSAMib(): "
"register MIB data with subagent driving "
"code failed\ninit_ibmOSAMib(): for ifIndex %d ifDescr %s\n"
"check agent log file for more details\n"
"Cannot start subagent...exiting...\n",
if_list[i].ifIndex, if_list[i].if_Name );
exit(1);
} /* end if */
} /* end if */
} /* end for */
/* log IPA microcode level per interface */
for ( i=0; i < ifNumber; i++ )
{
if ( if_list[i].is_OSAEXP == TRUE )
snmp_log( LOG_INFO, "OSA-E microcode level is %x for interface %s\n",
if_list[i].ipa_ver,
if_list[i].if_Name );
} /* end for */
/* free resources */
close( sd );
free( buffer );
} /* end init_ibmOSAMib */
/**********************************************************************
* var_ibmOSAMib():
* This function is called every time the agent gets a request for
* any MIB data for the IBM OSA express MIB. It's up to this function
* to return the appropriate data back to the subagent driving code.
* This function supports all standard SNMIv2 data types.
* parameters:
* IN variable vp - entry in variableN array
* INOUT oid *name - OID from original request/OID being returned
* INOUT size_t *length - length of orig. OID/length of ret. OID
* IN int exact - exact/inexact request
* OUT size_t *var_len - length of answer being returned
* OUT WriteMethod **write_method - unused
* returns: NULL - vp entry does not match or instance wrong
* - something within ioctl handling failed
* else data returned as answer
*********************************************************************/
unsigned char* var_ibmOSAMib( struct variable *vp,
oid *name,
size_t *length,
int exact,
size_t *var_len,
WriteMethod **write_method)
{
/* variables for returning data back to the subagent driving code */
static long long_ret;
static unsigned char octetstr_buf[MAX_GET_DATA];
static oid objid[MAX_OID_LEN];
static struct counter64 osa_counter64;
long *ptr_long;
int *ptr_int;
unsigned char *ptr_uchar;
int ifIndex; /* IF-MIB ifIndex of the OSA device that is queried for data */
int offset; /* offset to returned data portion within GET command area */
char time_buf[TIME_BUF_SIZE]; /* date/time buffer */
IPA_CMD_GET *get_cmd; /* area for GET command */
IPA_GET_DATA *get_res; /* pointer to offset where data portion starts */
void *tmp_ptr;
/*
* This function compares the full OID that is passed in to the registered
* OIDs from this subagent.
* It is the IBM OSA Express specific version of the default
* header_simple_table() function, that is normally used in case of a simple
* table. Place a mutual exlusion lock around this operation to avoid
* interfering threads, when updating the internal MIB table thru thread
* update_mib_info()
*/
ifIndex = header_osa_table( vp, name, length, exact, var_len, write_method,
oid_list_head );
if ( ifIndex == MATCH_FAILED )
return NULL;
/* issue ioctl to query Get/Getnext request data */
offset = do_GET_ioctl ( ifIndex, name, *length, &get_cmd );
if ( offset < 0 )
{
return NULL;
}
/*
* return the result to subagent driving code
*/
/* map data portion returned by IPAssists */
/* # ptr GET command area + offset returned data portion */
/* # align PTR to 4 byte bdy where data portion starts */
tmp_ptr = (char*) get_cmd;
tmp_ptr += offset;
get_res = (IPA_GET_DATA*) (PTR_ALIGN4( tmp_ptr ));
switch( vp->type ) {
case ASN_INTEGER: case ASN_COUNTER: case ASN_GAUGE: case ASN_TIMETICKS:
/* ASN_UNSIGNED is same as ASN_GAUGE (RFC1902) */
if ( get_res->len == sizeof(int) )
{
ptr_int = (int*) get_res->data;
long_ret = (long) *ptr_int;
}
else
{
ptr_long = (long*) get_res->data;
long_ret = (long) *ptr_long;
} /* end if */
free( get_cmd );
return (unsigned char *) &long_ret;
break;
case ASN_COUNTER64:
if ( get_res->len > 8 )
{
get_time( time_buf );
snmp_log( LOG_ERR, "%s var_ibmOSAMib(): "
"IPA data length for ASN_COUNTER64 > 8 bytes\n"
"var_ibmOSAMib(): rejected Get/Getnext request\n", time_buf );
free( get_cmd );
return NULL;
} /* end if */
/* IPA returns 8 bytes for COUNTER64 */
ptr_int = (int*) get_res->data;
osa_counter64.high = (int) *ptr_int;
ptr_int++;
osa_counter64.low = (int) *ptr_int;
*var_len = sizeof( osa_counter64 );
free( get_cmd );
return (unsigned char *) &osa_counter64;
break;
case ASN_OPAQUE: /* old v1 type/included for compatibility */
case ASN_OCTET_STR: /* used for Binary data */
/* case Display String is handled within var_DisplayStr() */
if ( get_res->len > MAX_GET_DATA )
{
get_time( time_buf );
snmp_log( LOG_ERR, "%s var_ibmOSAMib(): "
"IPA data length %d for ASN_OCTET_STR > "
"MAX_GET_DATA (%d bytes)\n"
"var_ibmOSAMib(): rejected Get/Getnext request\n",
time_buf, get_res->len, MAX_GET_DATA );
free( get_cmd );
return NULL;
} /* end if */
*var_len = get_res->len;
ptr_uchar = (unsigned char*) get_res->data;
memcpy( octetstr_buf, ptr_uchar, *var_len );
free( get_cmd );
return (unsigned char *) octetstr_buf;
break;
case ASN_IPADDRESS:
/* IPA IpAddress within 4 bytes hex data */
ptr_int = (int*) get_res->data;
long_ret = (long) *ptr_int;
free( get_cmd );
return (unsigned char *) &long_ret;
break;
case ASN_OBJECT_ID:
/* IPA returned ObjectId as character string, have to convert... */
*var_len = str_to_oid_conv ( get_res->data, objid );
if ( *var_len == 0 )
{
get_time( time_buf );
snmp_log( LOG_ERR, "%s var_ibmOSAMib(): IPA returned bad ObjectId - "
"cannot convert net-snmp oid type\n"
"var_ibmOSAMib(): rejected Get/Getnext request\n", time_buf );
free( get_cmd );
return NULL;
} /* end if */
*var_len = (*var_len) * sizeof( oid );
free( get_cmd );
return (unsigned char *) &objid;
break;
default:
get_time( time_buf );
snmp_log( LOG_ERR, "%s var_ibmOSAMib(): "
"got a not known ASN data type %x\n"
"var_ibmOSAMib(): "
"rejected Get/Getnext request\n", time_buf, vp->type );
} /* end switch */
free( get_cmd );
return NULL;
} /* end var_ibmOSAMib */
/**********************************************************************
* var_DisplayStr():
* This function handles the special case for Display Strings, which are
* a textual convention to Octet Strings. The binary data case for
* Octet Strings is handled within var_ibmOSAMib().
* It's up to this function to return the appropriate data back to the
* subagent driving code.
* parameters:
* IN variable vp - entry in variableN array
* INOUT oid *name - OID from original request/OID being returned
* INOUT size_t *length - length of orig. OID/length of ret. OID
* IN int exact - exact/inexact request
* OUT size_t *var_len - length of answer being returned
* OUT WriteMethod **write_method - unused
* returns: NULL - vp entry does not match or instance wrong
* - something within ioctl handling failed
* else data returned as answer
*********************************************************************/
unsigned char* var_DisplayStr( struct variable *vp,
oid *name,
size_t *length,
int exact,
size_t *var_len,
WriteMethod **write_method)
{
/* variables for returning a display string to the subagent driving code */
static char string[SPRINT_MAX_LEN];
char time_buf[TIME_BUF_SIZE]; /* date/time buffer */
int ifIndex; /* IF-MIB ifIndex of the OSA device that is queried for data */
int offset; /* offset to returned data portion within GET command area */
IPA_CMD_GET *get_cmd; /* area for GET command */
IPA_GET_DATA *get_res; /* pointer to offset where data portion starts */
void *tmp_ptr;
/*
* This function compares the full OID that is passed in to the registered
* OIDs from this subagent.
* It is the IBM OSA Express specific version of the default
* header_simple_table() function, that is normally used in case of a simple
* table. Place a mutual exlusion lock around this operation to avoid
* interfering threads, when updating the internal MIB table thru thread
* update_mib_info()
*/
ifIndex = header_osa_table( vp, name, length, exact, var_len, write_method,
oid_list_head );
if ( ifIndex == MATCH_FAILED )
return NULL;
/* issue ioctl to query Get/Getnext request data */
offset = do_GET_ioctl ( ifIndex, name, *length, &get_cmd );
if ( offset < 0 )
{
return NULL;
}
/*
* return the result to subagent driving code
*/
/* map data portion returned by IPAssists */
/* # ptr GET command area + offset returned data portion */
/* # align PTR to 4 byte bdy where data portion starts */
tmp_ptr = (char*) get_cmd;
tmp_ptr += offset;
get_res = (IPA_GET_DATA*) (PTR_ALIGN4( tmp_ptr ));
if ( vp->type == ASN_OCTET_STR)
{
if ( get_res->len >= SPRINT_MAX_LEN )
{
get_time( time_buf );
snmp_log( LOG_ERR, "%s var_DisplayStr(): "
"IPA data length %d for Display "
"String >= SPRINT_MAX_LEN (%d bytes)\n"
"var_ibmOSAMib(): rejected Get/Getnext request\n"
,time_buf, get_res->len, SPRINT_MAX_LEN );
free( get_cmd );
return NULL;
} /* end if */
strncpy( string, get_res->data, get_res->len );
string[ get_res->len ] = '\0';
*var_len = strlen( string );
free( get_cmd );
return (unsigned char *) string;
}
else
{
get_time( time_buf );
snmp_log( LOG_ERR, "%s var_DisplayStr(): "
"expected a Display String here, "
"but got a different ASN data type: %x\n"
"var_DisplayStr(): "
"rejected Get/Getnext request\n", time_buf, vp->type );
} /* end if */
free( get_cmd );
return NULL;
} /* end var_DisplayStr */
/**********************************************************************
* do_GET_ioctl()
* This function handles the communication with an OSA Express Card
* to query the appropriate MIB information from IPAssists.
* An ioctl is used in order to qet the appropriate information.
* parameters:
* IN int ifIndex - IF-MIB interface index
* IN oid *name - OID being returned
* IN size_t len - length of ret. OID
* INOUT IPA_CMD_GET** cmd - GET command area
* returns: cmd_len - return offset to returned data
* -1 - ioctl() was not successful
*********************************************************************/
int do_GET_ioctl ( int ifIndex, oid *name, size_t len, IPA_CMD_GET **cmd )
{
int sd; /* socket descriptor */
int i, error_code;
char oid_str[MAX_OID_STR_LEN]; /* may hold an OID as string */
char time_buf[TIME_BUF_SIZE]; /* date/time buffer */
char device[IFNAME_MAXLEN] = "not_found"; /* device name for ioctl */
struct ifreq ifr; /* request structure for ioctl */
/* search device name in in global interface list for ifIndex */
for ( i=0; i < ifNumber; i++ )
{
if ( if_list[i].ifIndex == ifIndex )
{
strcpy( device, if_list[i].if_Name );
break;
}
} /* end for */
if ( strcmp( device, "not_found" ) == 0 )
{
get_time( time_buf );
snmp_log( LOG_ERR, "%s do_GET_ioctl(): "
"ifIndex %d is not recorded in "
"interface list\n"
"OSA Subagent MIB information may be incomplete!\n"
,time_buf, ifIndex );
return -1;
}
/*
* query IPAssists for data appropriate to the OID that we just validated
*/
/* convert Get/GetNext OID to a string used by IPA */
if( oid_to_str_conv ( name, len, oid_str ) == FALSE )
{
get_time( time_buf );
snmp_log( LOG_ERR, "%s do_GET_ioctl(): "
"cannot convert OID to string object\n"
"do_GET_ioctl(): rejected request\n", time_buf );
return -1;
}
/* allocate memory for Get/GetNext command area */
*cmd = ( IPA_CMD_GET* ) malloc( GET_AREA_LEN );
if ( *cmd == NULL )
{
get_time( time_buf );
snmp_log( LOG_ERR,
"%s do_GET_ioctl(): "
"malloc() for GET command area failed\n"
"do_GET_ioctl(): rejected request for .%s\n",
time_buf, oid_str );
return -1;
} /* end if */
/* set up input parameters in Get/GetNext command area */
/* size of IPA data area */
(*cmd)->ioctl_cmd.data_len =
GET_AREA_LEN - offsetof( IOCTL_CMD_HDR, ipa_cmd_hdr );
/* size of IPA GET subcommand padded to 4-byte bdy */
(*cmd)->ioctl_cmd.req_len =
(sizeof((*cmd)->ioctl_cmd) + strlen( oid_str ) + 1 + 3)&(~3);
/* set up input parameters in Get/GetNext command area */
(*cmd)->ioctl_cmd.ipa_cmd_hdr.request = IPA_GET_OID; /* IPA subcommand code */
(*cmd)->ioctl_cmd.ipa_cmd_hdr.ifIndex = ifIndex; /* assign IF-MIB ifIndex */
(*cmd)->ioctl_cmd.ipa_cmd_hdr.ret_code = 0;
(*cmd)->ioctl_cmd.ipa_cmd_hdr.seq_num = 0; /* sequence# is not used */
strcpy( (*cmd)->full_oid, oid_str ); /* requested OID */
/* (fully qualified) */
/*
* issue Get/GetNext command against IPAssists
*/
/* create socket for ioctl */
sd = socket( AF_INET, SOCK_STREAM, 0 );
if ( sd < 0 )
{
error_code = errno;
get_time( time_buf );
snmp_log(LOG_ERR, "%s do_GET_ioctl(): "
"error opening socket() - reason %s\n"
"do_GET_ioctl(): rejected request for .%s\n",
time_buf, strerror( error_code ), oid_str );
free( *cmd );
return -1;
} /* end if */
/* do ioctl */
strcpy( ifr.ifr_name, device );
ifr.ifr_ifru.ifru_data = (char*) (*cmd);
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 do_GET_ioctl(): "
"ioctl() failed - reason %s\n"
"do_GET_ioctl(): rejected request for .%s\n",
time_buf, strerror( error_code ), oid_str );
close( sd );
free( *cmd );
return -1;
} /* end if */
/* let's see, if we got a return code from IPAssists */
/* or if MIB buffer is exhausted */
switch ( (*cmd)->ioctl_cmd.ipa_cmd_hdr.ret_code ) {
case IPA_FAILED:
snmp_log( LOG_ERR, "%s do_GET_ioctl(): "
"ioctl() failed - IPA command failed\n"
"do_GET_ioctl(): rejected request for .%s\n",
time_buf, oid_str );
break;
case IPA_NOT_SUPP:
snmp_log( LOG_ERR, "%s do_GET_ioctl(): "
"ioctl() failed - IPA command not supported\n"
"do_GET_ioctl(): rejected request for .%s\n",
time_buf, oid_str );
break;
case IPA_NO_DATA:
snmp_log( LOG_ERR, "%s do_GET_ioctl(): "
"ioctl() failed - valid IPA command, but no "
"SNMP data is available\n"
"do_GET_ioctl(): rejected request for .%s\n",
time_buf, oid_str );
break;
case -ENOMEM:
snmp_log( LOG_ERR, "%s do_GET_ioctl(): "
"ioctl() failed - response data > "
"constant MAX_GET_DATA %d\n"
"do_GET_ioctl(): rejected request for .%s\n",
time_buf, MAX_GET_DATA, oid_str );
break;
default:
snmp_log(LOG_ERR, "%s do_GET_ioctl(): "
"ioctl() failed - reason %s\n"
"do_GET_ioctl(): rejected request for .%s\n",
time_buf, strerror( error_code ), oid_str );
break;
} /* end switch */
close( sd );
free( *cmd );
return -1;
} /* end if */
/* close socket */
close( sd );
/* now check IPA SNMP subcommand return code */
switch ( (*cmd)->ioctl_cmd.ipa_cmd_hdr.ret_code ) {
case IPA_SNMP_SUCCESS:
/* return offset to data portion */
return ( sizeof( IPA_CMD_GET ) + strlen( oid_str ) + 1 );
break;
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:
get_time( time_buf );
snmp_log( LOG_ERR, "%s do_GET_ioctl(): "
"IPA SNMP subcommand failed - cannot handle OID\n"
"do_GET_ioctl(): IPA SNMP subcommand return code 0x%x\n"
"do_GET_ioctl(): rejected request for .%s\n",
time_buf, (*cmd)->ioctl_cmd.ipa_cmd_hdr.ret_code, oid_str );
break;
case IPA_SNMP_NOT_SUPP:
get_time( time_buf );
snmp_log( LOG_ERR, "%s do_GET_ioctl(): "
"IPA SNMP subcommand failed - subcommand 0x%x not supported\n"
"do_GET_ioctl(): rejected request for .%s\n",
time_buf, (*cmd)->ioctl_cmd.ipa_cmd_hdr.request, oid_str );
break;
case IPA_SNMP_NO_DATA:
get_time( time_buf );
snmp_log( LOG_ERR, "%s do_GET_ioctl(): "
"IPA SNMP subcommand failed - no data available\n"
"do_GET_ioctl(): rejected request for .%s\n",
time_buf, oid_str );
break;
default:
get_time( time_buf );
snmp_log( LOG_ERR, "%s do_GET_ioctl(): "
"IPA SNMP subcommand failed - undefined return code 0x%x\n"
"do_GET_ioctl(): rejected request for .%s\n",
time_buf, (*cmd)->ioctl_cmd.ipa_cmd_hdr.ret_code, oid_str );
break;
} /* end switch */
/* return error */
free( *cmd );
return -1;
} /* end do_GET_ioctl */
/**********************************************************************
* write_ibmOSAMib():
* !!! Set processing is not supported in version 1.0.0 !!!
* !!! Function is defind as a skeleton for later use !!!
* This function handles any SET requests raised against the
* ibmOSAMib.
* The flow of actions is to preserve proper transaction handling
* with other transactions in the same set request.
* parameters:
* IN int action - current action state
* IN u_char *var_val - new variable value
* IN u_char var_val_type - data type of above variable
* IN size_t var_val_len - length of variable value
* IN u_char *statP - value that a GET request would return
* for this variable
* IN oid *name - OID to be set
* IN size_t name_len - len of OID to be set
* returns: SNMP_ERR_WRONGTYPE - wrong data type passed in
* SNMP_ERR_GENERR - general error occurred
* SNMP_ERR_UNDOFAILED - undo operation failed
* SNMP_ERR_NOERROR - variable set successful
*********************************************************************/
int write_ibmOSAMib( int action,
u_char *UNUSED(var_val),
u_char UNUSED(var_val_type),
size_t UNUSED(var_val_len),
u_char *UNUSED(statP),
oid *UNUSED(name),
size_t UNUSED(name_len) )
{
/* static unsigned char string[SPRINT_MAX_LEN]; */
/* int size; */
switch ( action ) {
case RESERVE1:
/* check to see that everything is possible */
break;
case RESERVE2:
/* allocate needed memory here */
break;
case FREE:
/* Release any resources that have been allocated */
break;
case ACTION:
/* Actually make the change requested. Note that anything done
here must be reversible in the UNDO case */
break;
case UNDO:
/* Back out any changes made in the ACTION case */
break;
case COMMIT:
/* Things are working well, so it's now safe to make the change
permanently. Make sure that anything done here can't fail! */
break;
}
return SNMP_ERR_NOERROR;
} /* end write_ibmOSAMib */

33
osasnmpd/ibmOSAMib.h Normal file
View File

@@ -0,0 +1,33 @@
/*
* osasnmpd - IBM OSA-Express network card SNMP subagent
*
* Include file for the OSA-E subagent MIB implementaton module.
* Defines function prototypes of the basic functions in 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.
*/
#ifndef _MIBGROUP_IBMOSAMIB_H
#define _MIBGROUP_IBMOSAMIB_H
/* we may use header_generic and header_simple_table from the util_funcs module */
config_require(util_funcs)
/* function prototypes */
void init_ibmOSAMib(void); /* register MIB data */
FindVarMethod var_ibmOSAMib; /* handle GET and GETNEXT requests */
/* for all SMIv2 standard types */
FindVarMethod var_DisplayStr; /* handle special case Display String */
WriteMethod write_ibmOSAMib; /* handle SET requests */
/* ioctl for Get/Getnext processing */
int do_GET_ioctl ( int, oid*, size_t, IPA_CMD_GET** );
#endif /* _MIBGROUP_IBMOSAMIB_H */

202
osasnmpd/ibmOSAMibDefs.h Normal file
View File

@@ -0,0 +1,202 @@
/*
* osasnmpd - IBM OSA-Express network card SNMP subagent
*
* Defines constants and data structures used by the OSA-E subagent.
*
* 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 <net-snmp/net-snmp-config.h>
#include <net-snmp/net-snmp-includes.h>
#include <net-snmp/agent/net-snmp-agent-includes.h>
#ifndef NETSNMP_DS_APPLICATION_ID
#define NETSNMP_DS_APPLICATION_ID DS_APPLICATION_ID
#endif
#ifndef NETSNMP_DS_AGENT_ROLE
#define NETSNMP_DS_AGENT_ROLE DS_AGENT_ROLE
#endif
#ifndef NETSNMP_DS_AGENT_X_SOCKET
#define NETSNMP_DS_AGENT_X_SOCKET DS_AGENT_X_SOCKET
#endif
/* version number of this agent */
/* default log file - don't change it here, use parameter -l */
#define OSAE_LOGFILE "/var/log/osasnmpd.log"
/* definitions for subagent to master agent definition */
#define NET_SNMP_PEERNAME "localhost"
#define NET_SNMP_COMMUNITY "public"
/* need this for OSA Express ioctl's */
#define QETH_PROCFILE "/proc/qeth"
#define QETH_IOC_MAGIC 'Z'
#define QETH_IOCPROC_REGISTER _IOW(QETH_IOC_MAGIC, 1, int)
#define QETH_UPDATE_MIB_SIGNAL SIGUSR1
#define QETH_QUERY_IPA_DATA _IOWR(QETH_IOC_MAGIC, 7, int )
#define QETH_CHECK_OSA_DEVICE _IOWR(QETH_IOC_MAGIC, 8, int )
#define IFNAME_MAXLEN 16 /* max length for linux interface names */
#define SUFFIX_MAXLEN 13 /* max length of suffix length for net-snmp */
#define MIB_AREA_LEN 25000 /* default size for register MIB data */
#define MAX_GET_DATA 4094 /* maximum GET response data length */
#define GET_AREA_LEN MAX_GET_DATA + 512 /* size for GET command area length */
#define TIME_BUF_SIZE 128 /* buffer size for date and time string */
#define MAX_OID_STR_LEN MAX_OID_LEN * 5 /* max OID string size */
/* definitions for 2.6 qeth */
#define QETH_SYSFILE "/sys/bus/ccwgroup/drivers/qeth/notifier_register"
#define SIOC_QETH_ADP_SET_SNMP_CONTROL (SIOCDEVPRIVATE + 5)
#define SIOC_QETH_GET_CARD_TYPE (SIOCDEVPRIVATE + 6)
/* some definitions for the linked lists compare and delete functions */
#define OID_FOUND 0
#define OID_NOT_FOUND 1
#define UNEXP_ERROR -1
#define INDEX_FOUND 0
#define INDEX_NOT_FOUND 1
#define IF_ENTRY 0
#define IND_LIST 1
/* additional access types and data types used by IPAssists */
#define IPA_WRONLY 0xF2
#define IPA_DISPLAYSTR ((u_char)0x09)
/* IPAssists SNMP subcommand codes */
#define IPA_REG_MIB 0x04
#define IPA_GET_OID 0x10
#define IPA_SET_OID 0x11
/*#define IPA_QUERY_ALERT 0x20*/
/*#define IPA_SET_TRAP 0x21*/
/* IPAssists command return codes */
#define IPA_SUCCESS 0x00
#define IPA_FAILED 0x01
#define IPA_NOT_SUPP 0x04
#define IPA_NO_DATA 0x08
/* IPAssists SNMP subcommand return codes */
#define IPA_SNMP_SUCCESS 0x00
#define IPA_SNMP_INV_TOPOID 0x01
#define IPA_SNMP_INV_GROUP 0x02
#define IPA_SNMP_INV_SUFFIX 0x04
#define IPA_SNMP_INV_INST 0x08
#define IPA_SNMP_OID_NREAD 0x10
#define IPA_SNMP_OID_NWRIT 0x20
#define IPA_SNMP_NOT_SUPP 0x40
#define IPA_SNMP_NO_DATA 0x80
#define PTR_ALIGN4(addr) ((long)((addr))+3)&(~3) /* align ptr 4-byte bdy */
/***************************************************************/
/* structure used for getting OSA-Express interfaces via ioctl */
/***************************************************************/
#define NAME_FILLED_IN 0x00000001
#define IFINDEX_FILLED_IN 0x00000002
/* version 0 */
typedef struct dev_list
{
char device_name[IFNAME_MAXLEN]; /* OSA-Exp device name (e.g. eth0) */
int if_index; /* interface index from kernel */
__u32 flags; /* device charateristics */
} __attribute__((packed)) DEV_LIST;
typedef struct osaexp_dev_ver0
{
__u32 version; /* structure version */
__u32 valid_fields; /* bitmask of fields that are really filled */
__u32 qeth_version; /* qeth driver version */
__u32 number_of_devices; /* number of OSA Express devices */
struct dev_list devices[0]; /* list of OSA Express devices */
} __attribute__((packed)) OSAEXP_DEV_VER0;
/***************************************************************/
/* ioctl data structure for IPAssists SNMP processing */
/***************************************************************/
typedef struct ioctl_cmd_hdr
{
int data_len; /* total length of buffer passed to ioctl */
/* following the first 16 bytes */
/* in this structure (i.e. starts at token) */
int req_len; /* length of IPAssists SNMP request */
int reserved1; /* unused */
int reserved2; /* unused */
struct {
char token[16]; /* not used */
int request; /* IPA subcommand code */
int ifIndex; /* IF-MIB ifIndex value for interface */
int ret_code; /* IPA return code */
int ipa_ver; /* IPA microcode level (4 hex digits to be shown as xx.yy) */
int seq_num; /* sequence number (currently not used) */
} ipa_cmd_hdr;
} __attribute__((packed)) IOCTL_CMD_HDR;
/***************************************************************/
/* structures for GET/GETNEXT IPAssists processing */
/***************************************************************/
typedef struct ipa_cmd_get
{
IOCTL_CMD_HDR ioctl_cmd; /* IOCTL command header */
char full_oid[0]; /* fully qualified OID for GET/GETNEXT */
} __attribute__((packed)) IPA_CMD_GET;
typedef struct ipa_get_data
{
int len; /* length of returned data from IPA */
char data[0]; /* data returned by IPA */
} __attribute__((packed)) IPA_GET_DATA;
/******************************************************************/
/* struct for IPAssists register MIB data processing */
/******************************************************************/
typedef struct ipa_cmd_reg
{
IOCTL_CMD_HDR ioctl_cmd; /* IPA subcommand header */
int table_cnt; /* number of table toplevel OIDs */
} __attribute__((packed)) IPA_CMD_REG;
/***************************************************************/
/* linked list for table OID housekeeping */
/***************************************************************/
typedef struct table_oid
{
oid *pObjid; /* registered table OID */
size_t length; /* length of subtree OID */
struct variable13 *var13ptr; /* ptr to variable_x list */
struct reg_indices *ind_list; /* ptr to registered indices */
struct table_oid *next; /* ptr to next entry in list */
} TABLE_OID;
/***************************************************************/
/* linked list for OSA Express interfaces housekeeping */
/***************************************************************/
typedef struct reg_indices
{
char *full_index; /* full index portion from IPA */
int ifIndex; /* ifIndex from IF-MIB */
struct reg_indices *next; /* ptr to next entry in list */
} REG_INDICES;
/*******************************************************************/
/* this list keeps information queried from the IF-MIB */
/*******************************************************************/
typedef struct if_List
{
int kerIndex; /* Linux kernel ifIndex */
int ifIndex; /* IF-MIB ifIndex */
short is_OSAEXP; /* TRUE if an OSA Express device */
char if_Name[IFNAME_MAXLEN]; /* interface name (e.g. eth0) */
int ipa_ver; /* IPA microcode level */
} IF_LIST;

1787
osasnmpd/ibmOSAMibUtil.c Normal file

File diff suppressed because it is too large Load Diff

100
osasnmpd/ibmOSAMibUtil.h Normal file
View File

@@ -0,0 +1,100 @@
/*
* osasnmpd - IBM OSA-Express network card SNMP subagent
*
* Prototypes for the utility functions within ibmOSAMibUtil.c
* It should be included in every module that belonging to the
* subagent.
*
* 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 <limits.h>
#include <math.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <linux/if.h>
#include <netinet/in.h> /* included because of "parse error before `get_myaddr'" */
/* in version 4.2.1 this headerfile was included from */
/* ucd-snmp-includes.h */
/* include local defintions of data structures for OSA Express subagent */
#include "ibmOSAMibDefs.h"
/************************
* function prototypes *
************************/
/* convert OID string returned by IPAssists to net-snmp oid type */
int str_to_oid_conv ( char*, oid* );
/* convert net-snmp oid type to OID string used by IPAssists */
int oid_to_str_conv ( oid*, size_t, char* );
/* convert IPA access type to net-snmp access type */
int get_acc_type ( int );
/* create pseudo node for toplevel OID linked list */
TABLE_OID* init_oid_list();
/* create pseudo node for index linked list */
REG_INDICES* init_ind_list();
/* inserts an OID after a given entry into the linked list */
TABLE_OID* oid_insert_after ( oid*, size_t, TABLE_OID* );
/* delete a whole Toplevel OID from the linked list including indices */
int delete_oid( oid*, size_t, TABLE_OID* );
/* remove index entries from Toplevel OID list */
int clear_oid_list( TABLE_OID* );
/* searches an OID in the OID linked list */
int search_oid ( oid*, size_t, TABLE_OID*, TABLE_OID** );
/* searches a Toplevel OID in a fully qualified OID */
int search_top_oid ( oid*, size_t, TABLE_OID*, TABLE_OID** );
/* inserts an index into the index linked list */
REG_INDICES* index_insert_after ( char*, int, REG_INDICES* );
/* delete a single entry from the index list or the whole list */
int delete_index( REG_INDICES*, int, int );
/* searches an index in the OID linked list */
int search_index ( char*, REG_INDICES*, REG_INDICES** );
/* main MIB information registry function */
int register_tables ( void*, TABLE_OID* );
/* validates request and sets up fully qualified query/set OID */
int header_osa_table( struct variable*, oid*, size_t*,int, size_t*,
WriteMethod**, TABLE_OID* );
/* functions checking for interface changes and updating MIB information */
void update_mib_info ( );
/* retrieves interface information from IF-MIB */
int query_IF_MIB( IF_LIST** );
/* retrieves OSA Express interface information from kernel */
int query_OSA_EXP ( IF_LIST** ,int );
/* get time of day */
int get_time( char* );
/* display help message */
void usage();

71
osasnmpd/osasnmpd.8 Normal file
View File

@@ -0,0 +1,71 @@
.\" Copyright 2017 IBM Corp.
.\" s390-tools is free software; you can redistribute it and/or modify
.\" it under the terms of the MIT license. See LICENSE for details.
.\"
.TH OSASNMPD 8 "Apr 2006" "s390-tools"
.SH NAME
osasnmpd \- IBM OSA-Express network card SNMP subagent.
.SH SYNOPSIS
\fBosasnmpd\fR [-h] [-v] [-f] [-l \fIlogfile\fR | -L] [-A] [-P \fIpidfile\fR]
[-x \fIagentx-socket\fR]
.SH DESCRIPTION
\fBosasnmpd\fR is an SNMP subagent for the net-snmp 5.1.x package.
It supports the MIBs provided by an IBM OSA-Express network card.
The subagent communicates via the AgentX protocol with the snmpd daemon.
Hence the snmpd daemon must be already started on the same system before
osasnmpd can start successfully.
.SH OPTIONS
.TP
\fB-h\fR
Print usage message and exit.
.TP
\fB-v\fR
Print Version information and exit.
.TP
\fB-f\fR
Don't fork() from the calling shell.
.TP
\fB-l\fR \fIlogfile\fR
Logs all output from the subagent (including stdout/stderr) to
\fIlogfile\fR.
.br
(By default logfile=/var/log/osasnmpd.log)
.TP
\fB-A\fR
Append to the logfile rather than truncating it.
.TP
\fB-L\fR
Print warnings/messages to stdout/stderr.
.TP
\fB-P\fR \fIpidfile\fR
Save the process ID of the subagent in \fIpidfile\fR.
.TP
\fB-x\fR \fIagentx-socket\fR
Uses the specified socket as AgentX connection rather than the
default '/var/agentx/master'. The socket can either be a Unix
domain socket path, or the address of a network interface.
If a network address of the form inet-addr:port is given, then
the subagent will use the port specified. If a network address
of the form inet-addr is given, then the subagent will use the
default AgentX port, 705.
The agentx sockets of the snmpd daemon and osasnmpd must match.
.SH AUTHOR
.nf
This man-page was written by Thomas Weber <tweber@de.ibm.com>
and is maintained by Ursula Braun <ursula.braun@de.ibm.com>
.fi
.SH SEE ALSO
.PP
snmpd(1),
snmp.conf(5),
snmpd.conf(5)

316
osasnmpd/osasnmpd.c Normal file
View File

@@ -0,0 +1,316 @@
/*
* osasnmpd - IBM OSA-Express network card SNMP subagent
*
* OSA-E subagent main module
*
* This subagent extends the net-snmp master agent to support
* the Direct SNMP feature of zSeries OSA-E network cards.
* net-snmp AgentX support must be enabled to allow the
* subagent connecting to the master agent (snmpd).
*
* Copyright 2017 IBM Corp.
*
* 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 <getopt.h>
#include <linux/version.h>
#include <signal.h>
#include <sys/utsname.h>
#include "lib/zt_common.h"
#include "ibmOSAMibUtil.h"
#include "ibmOSAMib.h"
/* osasnmpd version */
#define COPYRIGHT "Copyright IBM Corp. 2003, 2017"
/* ptr to OSA Express MIB information stored in linked lists */
extern TABLE_OID* oid_list_head;
sig_atomic_t keep_running = 1;
sig_atomic_t interfaces_changed = 0;
/* signal handler for SIGTERM or SIGINT */
RETSIGTYPE
stop_server(int UNUSED(a))
{
keep_running = 0;
}
/* signal handler for SIGUSR1
* which is send by the kernel if the interface information changes
*/
RETSIGTYPE
on_interfaces_changed( int UNUSED(a) )
{
interfaces_changed++;
}
static void
sysfs_register()
{
int sys_fd;
char buf[10] = {0, };
sys_fd = open( QETH_SYSFILE, O_WRONLY );
if (sys_fd < 0) {
fprintf(stderr, "open(%s) failed - reason %s\n",
QETH_SYSFILE, strerror( errno ) );
exit(1);
}
sprintf(buf, "%d", QETH_UPDATE_MIB_SIGNAL);
/* register our process to receive SIGUSR1 on interface changes */
if(write(sys_fd, buf, 10) < 0){
fprintf(stderr, "registration with qeth driver failed - "
"reason %s\n", strerror( errno ) );
close(sys_fd);
exit(1);
}
close(sys_fd);
}
static void
sysfs_unregister()
{
int sys_fd;
sys_fd = open( QETH_SYSFILE, O_WRONLY );
if (sys_fd < 0) {
fprintf(stderr, "open(%s) failed - reason %s\n",
QETH_SYSFILE, strerror( errno ) );
exit(1);
}
/* unregister our process to receive SIGUSR1 on interface changes */
if(write(sys_fd, "unregister", 11) < 0){
fprintf(stderr, "deregistration with qeth driver failed - "
"reason %s\n", strerror( errno ) );
close(sys_fd);
exit(1);
}
close(sys_fd);
}
static struct option longopts[] = {
{"help",no_argument,0,'h'},
{"version",no_argument,0,'v'},
{"append",no_argument,0,'A'},
{"stderrlog",no_argument,0,'L'},
{"nofork",no_argument,0,'f'},
{"logfile",required_argument,0,'l'},
{"pidfile",required_argument,0,'P'},
{"sockaddr",required_argument,0,'x'},
{0,0,0,0}
};
#define OPTSTRING "hvALfl:A:P:x:"
/*
* main routine
*/
int main( int argc, char *argv[] )
{
TABLE_OID* li_ptr;
char oidstr[MAX_OID_STR_LEN];
char logfile[PATH_MAX + 1];
char pid_file[PATH_MAX + 1];
FILE *PID;
struct sigaction act;
int res,c,longIndex,rc;
unsigned char rel_a, rel_b, rel_c;
struct utsname buf;
char suffix[sizeof(buf.release)];
/* default settings, may be overridden by parameters */
int std_err_log = 0; /* 0=turn off stderr logging; 1=turn on */
/* if turned off; use file logging */
int dont_zero_log = 0; /* 0=clear logfile; 1=append to logfile */
int dont_fork = 0; /* 0=dont detach from shell; 1=detach */
int pid_file_set = 0;
strcpy( logfile, OSAE_LOGFILE ); /* default log file */
/* check for parameters */
while((c = getopt_long(argc, argv, OPTSTRING, longopts,
&longIndex)) != -1) {
switch (c) {
case 'h':
usage();
exit(0);
case 'v':
printf( "osasnmpd: version %s\n",
RELEASE_STRING);
printf( "%s\n" , COPYRIGHT );
exit(0);
case 'l':
if (strlen(optarg) > PATH_MAX)
{
fprintf( stderr, "osasnmpd: logfile "\
"path too long (limit %d "\
"chars)\n", PATH_MAX);
exit(1);
}
strncpy(logfile, optarg, PATH_MAX);
break;
case 'A':
dont_zero_log = 1;
break;
case 'L':
std_err_log=1;
break;
case 'f':
dont_fork = 1;
break;
case 'P':
if (strlen(optarg) > PATH_MAX)
{
fprintf( stderr, "osasnmpd: logfile "\
"path too long (limit %d "\
"chars)\n", PATH_MAX);
exit(1);
}
strncpy(pid_file,optarg,PATH_MAX);
pid_file_set = 1;
break;
case 'x':
netsnmp_ds_set_string(NETSNMP_DS_APPLICATION_ID,
NETSNMP_DS_AGENT_X_SOCKET, optarg);
break;
default:
fprintf(stderr, "Try 'osasnmpd --help' for more"
" information.\n");
exit(1);
} /* end switch */
} /* end-while */
while (optind < argc) {
fprintf(stderr, "osasnmpd: unrecognized argument '%s'\n",
argv[optind++]);
fprintf(stderr, "Try 'osasnmpd --help' for more"
" information.\n");
exit(1);
}
/* detach from shell (default) */
if (!dont_fork && fork() != 0)
exit(0);
/* create a pidfile if requested */
if (pid_file_set) {
if ((PID = fopen(pid_file, "w")) == NULL) {
snmp_log_perror("fopen");
fprintf(stderr, "osasnmpd: cannot create PIDFILE\n");
exit(1);
} else {
fprintf(PID, "%d\n", (int) getpid() );
fclose(PID);
}
}
/* enable logging to stderr or logfile */
if ( !std_err_log ) {
snmp_disable_stderrlog();
snmp_enable_filelog( logfile, dont_zero_log );
} else {
snmp_enable_stderrlog();
}
snmp_log(LOG_INFO, "IBM OSA-E NET-SNMP 5.1.x subagent version %s\n",
RELEASE_STRING );
/* make us a agentx client. */
netsnmp_ds_set_boolean(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_ROLE,
1);
/* initialize the agent library */
if ( init_agent("osasnmpd") != 0 ) {
fprintf(stderr, "osasnmpd: init_agent() failed\n"
"osasnmpd: check subagent logfile for detailed "
"information\n" );
exit(1);
}
/* initialize OSA Express MIB module here */
init_ibmOSAMib();
/* osasnmpd will be used to read osasnmpd.conf files. */
init_snmp("osasnmpd");
act.sa_flags = 0;
sigemptyset( &act.sa_mask );
/* handle termination requests (kill -TERM or kill -INT) */
act.sa_handler = stop_server;
if( sigaction( SIGTERM, &act, NULL ) < 0 ){
fprintf(stderr, "sigaction( SIGTERM, ... ) failed - "
"reason %s\n", strerror( errno ) );
exit( 1 );
}
act.sa_handler = stop_server;
if( sigaction( SIGINT, &act, NULL ) < 0 ){
fprintf(stderr, "sigaction( SIGINT, ... ) failed - reason %s\n",
strerror( errno ) );
exit( 1 );
}
/* handle iterface count change requests ( kill -SIGUSR1 ) */
act.sa_handler = on_interfaces_changed;
if( sigaction( SIGUSR1, &act, NULL ) ){
fprintf(stderr, "sigaction( SIGUSR1, ... ) failed - "
"reason %s\n", strerror( errno ) );
exit( 1 );
}
rc = uname(&buf);
if (!rc)
sscanf(buf.release, "%c.%c.%c-%s",
&rel_a, &rel_b, &rel_c, suffix);
if(KERNEL_VERSION(2,6,22) >= KERNEL_VERSION(rel_a, rel_b, rel_c))
sysfs_register();
signal(SIGALRM, update_mib_info);
snmp_log(LOG_INFO, "Initialization of OSA-E subagent successful...\n");
/* subagent main loop, that calls
* agent_check_and_process() in blocking mode
* */
while(keep_running) {
if( interfaces_changed > 0 ){
interfaces_changed = 0;
alarm(0); /* cancel a potentially scheduled alarm */
update_mib_info();
/* reschedule another update_mib_info() since
netsnmp does not update the interface counter
immediately, but within the next 60 seconds */
alarm(70);
} else
agent_check_and_process(1);
}
snmp_log(LOG_INFO, "Received TERM or STOP signal...shutting down "
"agent...\n");
/* unregister all Toplevel OIDs we support */
for(li_ptr = oid_list_head; li_ptr->next != NULL; li_ptr =li_ptr->next){
oid_to_str_conv((oid*)li_ptr->next->pObjid,
li_ptr->next->length, oidstr);
snmp_log(LOG_INFO, "unregister Toplevel OID .%s.....", oidstr );
res = unregister_mib(li_ptr->next->pObjid,
li_ptr->next->length);
if (res == MIB_UNREGISTERED_OK)
snmp_log(LOG_INFO, "successful\n");
else
snmp_log(LOG_INFO, "failed %d\n",res);
}
if(KERNEL_VERSION(2,6,22) >= KERNEL_VERSION(rel_a, rel_b, rel_c))
sysfs_unregister();
snmp_shutdown("osasnmpd");
return 0;
}