Implement SNMP bits data type support

This commit is contained in:
Mico Micic 2024-03-03 19:36:45 +01:00 committed by Olof Hagsand
parent dcfa367b3d
commit 5c05748cfe
6 changed files with 138 additions and 37 deletions

View file

@ -178,7 +178,7 @@ snmp_scalar_return(cxobj *xs,
}
if (type_yang2asn1(ys, &asn1type, 1) < 0)
goto done;
if ((ret = type_xml2snmp(xmlstr, &asn1type, &snmpval, &snmplen, &reason)) < 0)
if ((ret = type_xml2snmp(xmlstr, ys, &asn1type, &snmpval, &snmplen, &reason)) < 0)
goto done;
if (ret == 0){
clixon_debug(CLIXON_DBG_SNMP, "%s", reason);
@ -298,7 +298,7 @@ snmp_scalar_get(clixon_handle h,
}
goto ok;
}
if ((ret = type_xml2snmp(xmlstr, &asn1type, &snmpval, &snmplen, &reason)) < 0)
if ((ret = type_xml2snmp(xmlstr, ys, &asn1type, &snmpval, &snmplen, &reason)) < 0)
goto done;
if (ret == 0){
clixon_debug(CLIXON_DBG_SNMP, "%s", reason);

View file

@ -611,6 +611,12 @@ type_yang2asn1(yang_stmt *ys,
(strcmp(display_hint, "255a")==0 ||
strcmp(display_hint, "255t")==0))
at = CLIXON_ASN_FIXED_STRING;
/* Special case for bits type because netsnmp lib returns ASN_OCTET_STRING. In this case
we have to define an extended type to be able to handle bits type correctly later on. */
if (strcmp(restype, "bits") == 0){
at = CLIXON_ASN_BIT_STRING;
}
}
if (asn1_type)
*asn1_type = at;
@ -648,6 +654,7 @@ type_snmp2xml(yang_stmt *ys,
char *restype = NULL; /* resolved type */
char *origtype = NULL; /* original type */
yang_stmt *yrestype = NULL;
cbuf *cb = NULL;
int ret;
clixon_debug(CLIXON_DBG_SNMP, "");
@ -706,6 +713,20 @@ type_snmp2xml(yang_stmt *ys,
case ASN_GAUGE: // 0x42
cv_uint32_set(cv, *requestvb->val.integer);
break;
case CLIXON_ASN_BIT_STRING:{ /* special case for bit string */
if ((cb = cbuf_new()) == NULL){
clixon_err(OE_UNIX, errno, "cbuf_new");
goto done;
}
if ((ret = yang_val2bitsstr(yrestype, requestvb->val.bitstring, requestvb->val_len, cb)) < 0)
goto done;
if (ret == 0){
clixon_debug(CLIXON_DBG_DEFAULT, "Invalid bits value");
goto fail;
}
cv_strncpy(cv, cbuf_get(cb), cbuf_len(cb));
break;
}
case ASN_IPADDRESS:{
struct in_addr addr;
memcpy(&addr.s_addr, requestvb->val.string, 4);
@ -753,6 +774,8 @@ type_snmp2xml(yang_stmt *ys,
free(origtype);
if (cv)
cv_free(cv);
if (cb)
cbuf_free(cb);
return retval;
fail:
retval = 0;
@ -849,6 +872,7 @@ type_xml2snmp_pre(char *xmlstr0,
/*! Given snmp string value (as translated from XML) parse into snmp value
*
* @param[in] snmpstr SNMP type string
* @param[in] ys YANG node
* @param[in,out] asn1type ASN.1 type id
* @param[out] snmpval Malloc:ed snmp type
* @param[out] snmplen Length of snmp type
@ -861,18 +885,24 @@ type_xml2snmp_pre(char *xmlstr0,
*/
int
type_xml2snmp(char *snmpstr,
yang_stmt *ys,
int *asn1type,
u_char **snmpval,
size_t *snmplen,
char **reason)
{
int retval = -1;
int ret;
int retval = -1;
int ret;
yang_stmt *yrestype; /* resolved type */
if (snmpval == NULL || snmplen == NULL){
clixon_err(OE_UNIX, EINVAL, "snmpval or snmplen is NULL");
goto done;
}
if (snmp_yang_type_get(ys, NULL, NULL, &yrestype, NULL)) // XXX yrestype
goto done;
switch (*asn1type){
case CLIXON_ASN_ROWSTATUS:
*asn1type = ASN_INTEGER;
@ -978,6 +1008,15 @@ type_xml2snmp(char *snmpstr,
}
*asn1type = ASN_OCTET_STR;
break;
case CLIXON_ASN_BIT_STRING:
if ((ret = yang_bitsstr2val(yrestype, snmpstr, snmpval, snmplen)) < 0)
goto done;
if (ret == 0){
clixon_debug(CLIXON_DBG_DEFAULT, "Invalid bits valstr %s", snmpstr);
goto fail;
}
*asn1type = ASN_OCTET_STR;
break;
default:
assert(0);
}

View file

@ -54,6 +54,7 @@ extern "C" {
* Must be back to proper net-snmp ASN_ types in type_snmp2xml and type_xml2snmp
* before calling netsnmp API
*/
#define CLIXON_ASN_BIT_STRING 252 /* Special case used to identify a bit string data type */
#define CLIXON_ASN_EXTRAS 253 /* Special case clixon address >= this */
#define CLIXON_ASN_PHYS_ADDR 253 /* Special case phy-address */
#define CLIXON_ASN_FIXED_STRING 254 /* RFC2578 Sec 7.7: String-valued, fixed-length */
@ -101,7 +102,7 @@ int type_snmp2xml(yang_stmt *ys,
netsnmp_request_info *requests,
char **valstr);
int type_xml2snmp_pre(char *xmlstr, yang_stmt *ys, char **snmpstr);
int type_xml2snmp(char *snmpstr, int *asn1type, u_char **snmpval, size_t *snmplen, char **reason);
int type_xml2snmp(char *snmpstr, yang_stmt *ys, int *asn1type, u_char **snmpval, size_t *snmplen, char **reason);
int snmp_yang2xpath(yang_stmt *ys, cvec *keyvec, char **xpath);
int snmp_str2oid(char *str, yang_stmt *yi, oid *objid, size_t *objidlen);
int snmp_oid2str(oid **oidi, size_t *oidilen, yang_stmt *yi, cg_var *cv);

View file

@ -223,6 +223,50 @@ ifIpAddr OBJECT-TYPE
DESCRIPTION
"IP address example."
::= { clixonExampleScalars 13 }
bitTest OBJECT-TYPE
SYNTAX BITS {
bit00 (0),
bit01 (1),
bit02 (2),
bit03 (3),
bit04 (4),
bit05 (5),
bit06 (6),
bit07 (7),
bit08 (8),
bit09 (9),
bit10 (10),
bit11 (11),
bit12 (12),
bit13 (13),
bit14 (14),
bit15 (15),
bit16 (16),
bit17 (17),
bit18 (18),
bit19 (19),
bit20 (20),
bit21 (21),
bit22 (22),
bit23 (23),
bit24 (24),
bit25 (25),
bit26 (26),
bit27 (27),
bit28 (28),
bit29 (29),
bit30 (30),
bit31 (31),
bit32 (32),
bit33 (33),
bit34 (34),
bit35 (35)
}
MAX-ACCESS read-write
STATUS current
DESCRIPTION
"Simple bits value used for testing."
::= { clixonExampleScalars 14 }
--
-- Example Tables

View file

@ -68,6 +68,7 @@ cat <<EOF > $fstate
<ifPromiscuousMode>true</ifPromiscuousMode>
<ifCounterDiscontinuityTime>1234567890</ifCounterDiscontinuityTime>
<ifStackStatus>active</ifStackStatus>
<bitTest>bit00 bit12 bit22 bit35</bitTest>
</clixonExampleScalars>
<clixonIETFWGTable>
<clixonIETFWGEntry>
@ -160,17 +161,20 @@ OID9="${MIB}.1.9.0" # ifHCInOctets 4294967296
OID10="${MIB}.1.10.0" # ifPromiscuousMode true(1)
OID11="${MIB}.1.11.0" # ifCounterDiscontinuityTime 1234567890 TimeStamp
OID12="${MIB}.1.12.0" # ifStackStatus active(1)
OID13="${MIB}.2.1" # netSnmpIETFWGTable
OID14="${MIB}.2.1.1" # netSnmpIETFWGEntry
OID15="${MIB}.2.1.1.1.42" # nsIETFWGName
OID16="${MIB}.2.1.1.2.42" # nsIETFWGChair1
OID17="${MIB}.2.1.1.3.42" # nsIETFWGChair2
OID18="${MIB}.2.2" # netSnmpHostsTable
OID19="${MIB}.2.2.1.1.4.116.101.115.116" # netSnmpHostName
OID20="${MIB}.2.2.1.2.4.116.101.115.116" # netSnmpHostAddressType
OID21="${MIB}.2.2.1.3" # netSnmpHostAddress
OID22="${MIB}.2.2.1.4" # netSnmpHostStorage
OID23="${MIB}.2.2.1.5" # netSnmpHostRowStatus
OID13="${MIB}.1.13.0" # ifIpAddr
OID14="${MIB}.1.14.0" # bitTest bit00(0) bit12(12) bit22(22) bit35(35)
OID15="${MIB}.2.1" # netSnmpIETFWGTable
OID16="${MIB}.2.1.1" # netSnmpIETFWGEntry
OID17="${MIB}.2.1.1.1.42" # nsIETFWGName
OID18="${MIB}.2.1.1.2.42" # nsIETFWGChair1
OID19="${MIB}.2.1.1.3.42" # nsIETFWGChair2
OID20="${MIB}.2.2" # netSnmpHostsTable
OID21="${MIB}.2.2.1.1.4.116.101.115.116" # netSnmpHostName
OID22="${MIB}.2.2.1.2.4.116.101.115.116" # netSnmpHostAddressType
OID23="${MIB}.2.2.1.3" # netSnmpHostAddress
OID24="${MIB}.2.2.1.4" # netSnmpHostStorage
OID25="${MIB}.2.2.1.5" # netSnmpHostRowStatus
NAME1="CLIXON-TYPES-MIB::clixonExampleInteger.0"
NAME2="CLIXON-TYPES-MIB::clixonExampleSleeper.0"
@ -184,17 +188,20 @@ NAME9="CLIXON-TYPES-MIB::ifHCInOctets.0"
NAME10="CLIXON-TYPES-MIB::ifPromiscuousMode.0"
NAME11="CLIXON-TYPES-MIB::ifCounterDiscontinuityTime.0"
NAME12="CLIXON-TYPES-MIB::ifStackStatus.0"
NAME13="CLIXON-TYPES-MIB::netSnmpIETFWGTable"
NAME14="CLIXON-TYPES-MIB::netSnmpIETFWGEntry"
NAME15="CLIXON-TYPES-MIB::nsIETFWGName"
NAME16="CLIXON-TYPES-MIB::nsIETFWGChair1"
NAME17="CLIXON-TYPES-MIB::nsIETFWGChair2"
NAME18="CLIXON-TYPES-MIB::netSnmpHostsTable"
NAME19="CLIXON-TYPES-MIB::netSnmpHostName"
NAME20="CLIXON-TYPES-MIB::netSnmpHostAddressType"
NAME21="CLIXON-TYPES-MIB::netSnmpHostAddress"
NAME22="CLIXON-TYPES-MIB::netSnmpHostStorage"
NAME23="CLIXON-TYPES-MIB::netSnmpHostRowStatus"
NAME13="CLIXON-TYPES-MIB::ifIpAddr.0"
NAME14="CLIXON-TYPES-MIB::bitTest.0"
NAME15="CLIXON-TYPES-MIB::netSnmpIETFWGTable"
NAME16="CLIXON-TYPES-MIB::netSnmpIETFWGEntry"
NAME17="CLIXON-TYPES-MIB::nsIETFWGName"
NAME18="CLIXON-TYPES-MIB::nsIETFWGChair1"
NAME19="CLIXON-TYPES-MIB::nsIETFWGChair2"
NAME20="CLIXON-TYPES-MIB::netSnmpHostsTable"
NAME21="CLIXON-TYPES-MIB::netSnmpHostName"
NAME22="CLIXON-TYPES-MIB::netSnmpHostAddressType"
NAME23="CLIXON-TYPES-MIB::netSnmpHostAddress"
NAME24="CLIXON-TYPES-MIB::netSnmpHostStorage"
NAME25="CLIXON-TYPES-MIB::netSnmpHostRowStatus"
new "$snmpget"
@ -269,26 +276,30 @@ new "Get ifStackStatus"
validate_oid $OID12 $OID12 "INTEGER" 1
validate_oid $NAME12 $NAME12 "INTEGER" "active(1)"
new "Get bitTest"
validate_oid $OID14 $OID14 "Hex-STRING" "80 08 02 00 10"
validate_oid $NAME14 $NAME14 "BITS" "80 08 02 00 10 bit00(0) bit12(12) bit22(22) bit35(35)"
new "Get bulk OIDs"
expectpart "$($snmpbulkget $OID1)" 0 "$OID2 = INTEGER: -1" "$OID3 = STRING: \"This is not default\"" "$OID4 = Timeticks: (12345) 0:02:03.45" "$OID5 = INTEGER: 48" "$OID6 = Gauge32: 123123123" "$OID7 = INTEGER: 3" "$OID8 = Counter32: 123456" "$OID9 = Counter64: 4294967296" "$OID10 = INTEGER: 1" "$OID11 = Timeticks: (1234567890) 142 days, 21:21:18.90"
new "Test SNMP getnext netSnmpIETFWGTable"
validate_oid $OID15 $OID15 "INTEGER" 42
validate_oid $OID17 $OID17 "INTEGER" 42
new "Test SNMP get nsIETFWGName"
validate_oid $OID15 $OID15 "INTEGER" 42
validate_oid $OID17 $OID17 "INTEGER" 42
new "Test SNMP getnext nsIETFWGName"
expectpart "$($snmpgetnext $OID15)" 0 "STRING: \"Name1\""
expectpart "$($snmpgetnext $OID17)" 0 "STRING: \"Name1\""
new "Test SNMP getnext netSnmpHostsTable"
expectpart "$($snmpgetnext $OID18)" 0 "$OID19 = STRING: \"test\""
expectpart "$($snmpgetnext $OID20)" 0 "$OID21 = STRING: \"test\""
new "Test SNMP get netSnmpHostName"
expectpart "$($snmpget $OID19)" 0 "$OID19 = STRING: \"test\""
expectpart "$($snmpget $OID21)" 0 "$OID21 = STRING: \"test\""
new "Test SNMP getnext netSnmpHostName"
expectpart "$($snmpgetnext $OID19)" 0 "$OID20 = INTEGER: 1"
expectpart "$($snmpgetnext $OID21)" 0 "$OID22 = INTEGER: 1"
new "Negative test: Try to set object"
expectpart "$($snmpset $OID1 i 4 2> /dev/null)" 2 "^$"

View file

@ -174,7 +174,7 @@ function testrun()
"STRING")
set_type="s"
;;
"HEX STRING")
"Hex-STRING")
set_type="x"
;;
"TIMETICKS")
@ -195,23 +195,28 @@ function testrun()
esac
new "Set $name via SNMP"
if [ $type == "STRING" ]; then
if [ "$type" == "STRING" ]; then
echo "$snmpset $oid_in $set_type $value"
expectpart "$($snmpset $oid_in $set_type $value)" 0 "$type:" "$value"
elif [ "$type" == "Hex-STRING" ]; then
echo "$snmpset $oid_in $set_type \"$value\""
expectpart "$($snmpset $oid_in $set_type "$value")" 0 "$type:" ""$value""
else
echo "$snmpset $oid_in $set_type $value2"
expectpart "$($snmpset $oid_in $set_type $value)" 0 "$type: $value2"
expectpart "$($snmpset $oid_in $set_type $value)" 0 "$type: $value2"
fi
new "Check $name via SNMP"
if [ "$type" == "STRING" ]; then
expectpart "$($snmpget $oid_out)" 0 "$type:" "$value"
elif [ "$type" == "Hex-STRING" ]; then
expectpart "$($snmpget $oid_out)" 0 "$type:" ""$value""
else
expectpart "$($snmpget $oid_out)" 0 "$type: $value2"
fi
new "Check $name via CLI"
expectpart "$($clixon_cli -1 -f $cfg show config xml)" 0 "<$name>$xvalue</$name>"
expectpart "$($clixon_cli -1 -f $cfg show config xml)" 0 "<$name>$xvalue</$name>"
}
function testexit(){
@ -241,6 +246,7 @@ testrun clixonExampleSleeper INTEGER -1 -1 -1 ${MIB}.1.2.0 ${MIB}.1.2.0
testrun clixonExampleString STRING foobar foobar foobar ${MIB}.1.3.0 ${MIB}.1.3.0
testrun ifPromiscuousMode INTEGER 1 1 true ${MIB}.1.10.0 ${MIB}.1.10.0 # boolean
testrun ifIpAddr IPADDRESS 1.2.3.4 1.2.3.4 1.2.3.4 ${MIB}.1.13.0 ${MIB}.1.13.0 # InetAddress
testrun bitTest "Hex-STRING" "00 20 00 00 00" "00 20 00 00 00" "bit10" ${MIB}.1.14.0 ${MIB}.1.14.0 # bitTest
# XXX It was supposed to test writing hardware address type, but it is also read-only
#testrun ifPhysAddress STRING ff:ee:dd:cc:bb:aa ff:ee:dd:cc:bb:aa ff:ee:dd:cc:bb:aa ${IFMIB}.2.2.1.6.1