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) if (type_yang2asn1(ys, &asn1type, 1) < 0)
goto done; 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; goto done;
if (ret == 0){ if (ret == 0){
clixon_debug(CLIXON_DBG_SNMP, "%s", reason); clixon_debug(CLIXON_DBG_SNMP, "%s", reason);
@ -298,7 +298,7 @@ snmp_scalar_get(clixon_handle h,
} }
goto ok; 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; goto done;
if (ret == 0){ if (ret == 0){
clixon_debug(CLIXON_DBG_SNMP, "%s", reason); 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, "255a")==0 ||
strcmp(display_hint, "255t")==0)) strcmp(display_hint, "255t")==0))
at = CLIXON_ASN_FIXED_STRING; 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) if (asn1_type)
*asn1_type = at; *asn1_type = at;
@ -648,6 +654,7 @@ type_snmp2xml(yang_stmt *ys,
char *restype = NULL; /* resolved type */ char *restype = NULL; /* resolved type */
char *origtype = NULL; /* original type */ char *origtype = NULL; /* original type */
yang_stmt *yrestype = NULL; yang_stmt *yrestype = NULL;
cbuf *cb = NULL;
int ret; int ret;
clixon_debug(CLIXON_DBG_SNMP, ""); clixon_debug(CLIXON_DBG_SNMP, "");
@ -706,6 +713,20 @@ type_snmp2xml(yang_stmt *ys,
case ASN_GAUGE: // 0x42 case ASN_GAUGE: // 0x42
cv_uint32_set(cv, *requestvb->val.integer); cv_uint32_set(cv, *requestvb->val.integer);
break; 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:{ case ASN_IPADDRESS:{
struct in_addr addr; struct in_addr addr;
memcpy(&addr.s_addr, requestvb->val.string, 4); memcpy(&addr.s_addr, requestvb->val.string, 4);
@ -753,6 +774,8 @@ type_snmp2xml(yang_stmt *ys,
free(origtype); free(origtype);
if (cv) if (cv)
cv_free(cv); cv_free(cv);
if (cb)
cbuf_free(cb);
return retval; return retval;
fail: fail:
retval = 0; retval = 0;
@ -849,6 +872,7 @@ type_xml2snmp_pre(char *xmlstr0,
/*! Given snmp string value (as translated from XML) parse into snmp value /*! Given snmp string value (as translated from XML) parse into snmp value
* *
* @param[in] snmpstr SNMP type string * @param[in] snmpstr SNMP type string
* @param[in] ys YANG node
* @param[in,out] asn1type ASN.1 type id * @param[in,out] asn1type ASN.1 type id
* @param[out] snmpval Malloc:ed snmp type * @param[out] snmpval Malloc:ed snmp type
* @param[out] snmplen Length of snmp type * @param[out] snmplen Length of snmp type
@ -861,6 +885,7 @@ type_xml2snmp_pre(char *xmlstr0,
*/ */
int int
type_xml2snmp(char *snmpstr, type_xml2snmp(char *snmpstr,
yang_stmt *ys,
int *asn1type, int *asn1type,
u_char **snmpval, u_char **snmpval,
size_t *snmplen, size_t *snmplen,
@ -868,11 +893,16 @@ type_xml2snmp(char *snmpstr,
{ {
int retval = -1; int retval = -1;
int ret; int ret;
yang_stmt *yrestype; /* resolved type */
if (snmpval == NULL || snmplen == NULL){ if (snmpval == NULL || snmplen == NULL){
clixon_err(OE_UNIX, EINVAL, "snmpval or snmplen is NULL"); clixon_err(OE_UNIX, EINVAL, "snmpval or snmplen is NULL");
goto done; goto done;
} }
if (snmp_yang_type_get(ys, NULL, NULL, &yrestype, NULL)) // XXX yrestype
goto done;
switch (*asn1type){ switch (*asn1type){
case CLIXON_ASN_ROWSTATUS: case CLIXON_ASN_ROWSTATUS:
*asn1type = ASN_INTEGER; *asn1type = ASN_INTEGER;
@ -978,6 +1008,15 @@ type_xml2snmp(char *snmpstr,
} }
*asn1type = ASN_OCTET_STR; *asn1type = ASN_OCTET_STR;
break; 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: default:
assert(0); 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 * Must be back to proper net-snmp ASN_ types in type_snmp2xml and type_xml2snmp
* before calling netsnmp API * 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_EXTRAS 253 /* Special case clixon address >= this */
#define CLIXON_ASN_PHYS_ADDR 253 /* Special case phy-address */ #define CLIXON_ASN_PHYS_ADDR 253 /* Special case phy-address */
#define CLIXON_ASN_FIXED_STRING 254 /* RFC2578 Sec 7.7: String-valued, fixed-length */ #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, netsnmp_request_info *requests,
char **valstr); char **valstr);
int type_xml2snmp_pre(char *xmlstr, yang_stmt *ys, char **snmpstr); 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_yang2xpath(yang_stmt *ys, cvec *keyvec, char **xpath);
int snmp_str2oid(char *str, yang_stmt *yi, oid *objid, size_t *objidlen); 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); int snmp_oid2str(oid **oidi, size_t *oidilen, yang_stmt *yi, cg_var *cv);

View file

@ -223,6 +223,50 @@ ifIpAddr OBJECT-TYPE
DESCRIPTION DESCRIPTION
"IP address example." "IP address example."
::= { clixonExampleScalars 13 } ::= { 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 -- Example Tables

View file

@ -68,6 +68,7 @@ cat <<EOF > $fstate
<ifPromiscuousMode>true</ifPromiscuousMode> <ifPromiscuousMode>true</ifPromiscuousMode>
<ifCounterDiscontinuityTime>1234567890</ifCounterDiscontinuityTime> <ifCounterDiscontinuityTime>1234567890</ifCounterDiscontinuityTime>
<ifStackStatus>active</ifStackStatus> <ifStackStatus>active</ifStackStatus>
<bitTest>bit00 bit12 bit22 bit35</bitTest>
</clixonExampleScalars> </clixonExampleScalars>
<clixonIETFWGTable> <clixonIETFWGTable>
<clixonIETFWGEntry> <clixonIETFWGEntry>
@ -160,17 +161,20 @@ OID9="${MIB}.1.9.0" # ifHCInOctets 4294967296
OID10="${MIB}.1.10.0" # ifPromiscuousMode true(1) OID10="${MIB}.1.10.0" # ifPromiscuousMode true(1)
OID11="${MIB}.1.11.0" # ifCounterDiscontinuityTime 1234567890 TimeStamp OID11="${MIB}.1.11.0" # ifCounterDiscontinuityTime 1234567890 TimeStamp
OID12="${MIB}.1.12.0" # ifStackStatus active(1) OID12="${MIB}.1.12.0" # ifStackStatus active(1)
OID13="${MIB}.2.1" # netSnmpIETFWGTable OID13="${MIB}.1.13.0" # ifIpAddr
OID14="${MIB}.2.1.1" # netSnmpIETFWGEntry OID14="${MIB}.1.14.0" # bitTest bit00(0) bit12(12) bit22(22) bit35(35)
OID15="${MIB}.2.1.1.1.42" # nsIETFWGName
OID16="${MIB}.2.1.1.2.42" # nsIETFWGChair1 OID15="${MIB}.2.1" # netSnmpIETFWGTable
OID17="${MIB}.2.1.1.3.42" # nsIETFWGChair2 OID16="${MIB}.2.1.1" # netSnmpIETFWGEntry
OID18="${MIB}.2.2" # netSnmpHostsTable OID17="${MIB}.2.1.1.1.42" # nsIETFWGName
OID19="${MIB}.2.2.1.1.4.116.101.115.116" # netSnmpHostName OID18="${MIB}.2.1.1.2.42" # nsIETFWGChair1
OID20="${MIB}.2.2.1.2.4.116.101.115.116" # netSnmpHostAddressType OID19="${MIB}.2.1.1.3.42" # nsIETFWGChair2
OID21="${MIB}.2.2.1.3" # netSnmpHostAddress OID20="${MIB}.2.2" # netSnmpHostsTable
OID22="${MIB}.2.2.1.4" # netSnmpHostStorage OID21="${MIB}.2.2.1.1.4.116.101.115.116" # netSnmpHostName
OID23="${MIB}.2.2.1.5" # netSnmpHostRowStatus 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" NAME1="CLIXON-TYPES-MIB::clixonExampleInteger.0"
NAME2="CLIXON-TYPES-MIB::clixonExampleSleeper.0" NAME2="CLIXON-TYPES-MIB::clixonExampleSleeper.0"
@ -184,17 +188,20 @@ NAME9="CLIXON-TYPES-MIB::ifHCInOctets.0"
NAME10="CLIXON-TYPES-MIB::ifPromiscuousMode.0" NAME10="CLIXON-TYPES-MIB::ifPromiscuousMode.0"
NAME11="CLIXON-TYPES-MIB::ifCounterDiscontinuityTime.0" NAME11="CLIXON-TYPES-MIB::ifCounterDiscontinuityTime.0"
NAME12="CLIXON-TYPES-MIB::ifStackStatus.0" NAME12="CLIXON-TYPES-MIB::ifStackStatus.0"
NAME13="CLIXON-TYPES-MIB::netSnmpIETFWGTable" NAME13="CLIXON-TYPES-MIB::ifIpAddr.0"
NAME14="CLIXON-TYPES-MIB::netSnmpIETFWGEntry" NAME14="CLIXON-TYPES-MIB::bitTest.0"
NAME15="CLIXON-TYPES-MIB::nsIETFWGName"
NAME16="CLIXON-TYPES-MIB::nsIETFWGChair1" NAME15="CLIXON-TYPES-MIB::netSnmpIETFWGTable"
NAME17="CLIXON-TYPES-MIB::nsIETFWGChair2" NAME16="CLIXON-TYPES-MIB::netSnmpIETFWGEntry"
NAME18="CLIXON-TYPES-MIB::netSnmpHostsTable" NAME17="CLIXON-TYPES-MIB::nsIETFWGName"
NAME19="CLIXON-TYPES-MIB::netSnmpHostName" NAME18="CLIXON-TYPES-MIB::nsIETFWGChair1"
NAME20="CLIXON-TYPES-MIB::netSnmpHostAddressType" NAME19="CLIXON-TYPES-MIB::nsIETFWGChair2"
NAME21="CLIXON-TYPES-MIB::netSnmpHostAddress" NAME20="CLIXON-TYPES-MIB::netSnmpHostsTable"
NAME22="CLIXON-TYPES-MIB::netSnmpHostStorage" NAME21="CLIXON-TYPES-MIB::netSnmpHostName"
NAME23="CLIXON-TYPES-MIB::netSnmpHostRowStatus" NAME22="CLIXON-TYPES-MIB::netSnmpHostAddressType"
NAME23="CLIXON-TYPES-MIB::netSnmpHostAddress"
NAME24="CLIXON-TYPES-MIB::netSnmpHostStorage"
NAME25="CLIXON-TYPES-MIB::netSnmpHostRowStatus"
new "$snmpget" new "$snmpget"
@ -269,26 +276,30 @@ new "Get ifStackStatus"
validate_oid $OID12 $OID12 "INTEGER" 1 validate_oid $OID12 $OID12 "INTEGER" 1
validate_oid $NAME12 $NAME12 "INTEGER" "active(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" 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" 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" new "Test SNMP getnext netSnmpIETFWGTable"
validate_oid $OID15 $OID15 "INTEGER" 42 validate_oid $OID17 $OID17 "INTEGER" 42
new "Test SNMP get nsIETFWGName" new "Test SNMP get nsIETFWGName"
validate_oid $OID15 $OID15 "INTEGER" 42 validate_oid $OID17 $OID17 "INTEGER" 42
new "Test SNMP getnext nsIETFWGName" new "Test SNMP getnext nsIETFWGName"
expectpart "$($snmpgetnext $OID15)" 0 "STRING: \"Name1\"" expectpart "$($snmpgetnext $OID17)" 0 "STRING: \"Name1\""
new "Test SNMP getnext netSnmpHostsTable" new "Test SNMP getnext netSnmpHostsTable"
expectpart "$($snmpgetnext $OID18)" 0 "$OID19 = STRING: \"test\"" expectpart "$($snmpgetnext $OID20)" 0 "$OID21 = STRING: \"test\""
new "Test SNMP get netSnmpHostName" new "Test SNMP get netSnmpHostName"
expectpart "$($snmpget $OID19)" 0 "$OID19 = STRING: \"test\"" expectpart "$($snmpget $OID21)" 0 "$OID21 = STRING: \"test\""
new "Test SNMP getnext netSnmpHostName" 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" new "Negative test: Try to set object"
expectpart "$($snmpset $OID1 i 4 2> /dev/null)" 2 "^$" expectpart "$($snmpset $OID1 i 4 2> /dev/null)" 2 "^$"

View file

@ -174,7 +174,7 @@ function testrun()
"STRING") "STRING")
set_type="s" set_type="s"
;; ;;
"HEX STRING") "Hex-STRING")
set_type="x" set_type="x"
;; ;;
"TIMETICKS") "TIMETICKS")
@ -195,9 +195,12 @@ function testrun()
esac esac
new "Set $name via SNMP" new "Set $name via SNMP"
if [ $type == "STRING" ]; then if [ "$type" == "STRING" ]; then
echo "$snmpset $oid_in $set_type $value" echo "$snmpset $oid_in $set_type $value"
expectpart "$($snmpset $oid_in $set_type $value)" 0 "$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 else
echo "$snmpset $oid_in $set_type $value2" 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"
@ -206,6 +209,8 @@ function testrun()
new "Check $name via SNMP" new "Check $name via SNMP"
if [ "$type" == "STRING" ]; then if [ "$type" == "STRING" ]; then
expectpart "$($snmpget $oid_out)" 0 "$type:" "$value" expectpart "$($snmpget $oid_out)" 0 "$type:" "$value"
elif [ "$type" == "Hex-STRING" ]; then
expectpart "$($snmpget $oid_out)" 0 "$type:" ""$value""
else else
expectpart "$($snmpget $oid_out)" 0 "$type: $value2" expectpart "$($snmpget $oid_out)" 0 "$type: $value2"
fi fi
@ -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 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 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 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 # 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 #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