diff --git a/apps/snmp/snmp_handler.c b/apps/snmp/snmp_handler.c index 9b98669f..3e948fd9 100644 --- a/apps/snmp/snmp_handler.c +++ b/apps/snmp/snmp_handler.c @@ -69,43 +69,44 @@ snmp_common_handler(netsnmp_mib_handler *handler, { int retval = -1; netsnmp_variable_list *requestvb; /* sub of requests */ - clixon_snmp_handle *sh; char oidstr0[MAX_OID_LEN*2] = {0,}; char oidstr1[MAX_OID_LEN*2] = {0,}; char oidstr2[MAX_OID_LEN*2] = {0,}; + if (requests == NULL || shp == NULL){ + clicon_err(OE_XML, EINVAL, "requests or shp is null"); + goto done; + } requestvb = requests->requestvb; if (snprint_objid(oidstr0, sizeof(oidstr0), requestvb->name, requestvb->name_length) < 0){ clicon_err(OE_XML, 0, "snprint_objid buffer too small"); + goto done; } - if ((sh = (clixon_snmp_handle*)handler->myvoid) != NULL){ - if (snprint_objid(oidstr1, sizeof(oidstr1), - nhreg->rootoid, nhreg->rootoid_len) < 0){ - clicon_err(OE_XML, 0, "snprint_objid buffer too small"); - goto done; - } - if (snprint_objid(oidstr2, sizeof(oidstr2), - sh->sh_oid, sh->sh_oidlen) < 0){ - clicon_err(OE_XML, 0, "snprint_objid buffer too small"); - goto done; - } - if (shp) - *shp = sh; - if (strcmp(oidstr0, oidstr2) == 0) - clicon_debug(1, "%s \"%s\" %s inclusive:%d %s", __FUNCTION__, - oidstr2, - snmp_msg_int2str(reqinfo->mode), - requests->inclusive, tablehandler?"table":""); - else - clicon_debug(1, "%s \"%s\"/\"%s\" %s inclusive:%d %s", __FUNCTION__, - oidstr2, oidstr0, - snmp_msg_int2str(reqinfo->mode), - requests->inclusive, tablehandler?"table":""); + if ((*shp = (clixon_snmp_handle*)handler->myvoid) == NULL){ + clicon_err(OE_XML, 0, "No myvoid handler"); + goto done; } - else{ - assert(0); + if (snprint_objid(oidstr1, sizeof(oidstr1), + nhreg->rootoid, nhreg->rootoid_len) < 0){ + clicon_err(OE_XML, 0, "snprint_objid buffer too small"); + goto done; } + if (snprint_objid(oidstr2, sizeof(oidstr2), + (*shp)->sh_oid, (*shp)->sh_oidlen) < 0){ + clicon_err(OE_XML, 0, "snprint_objid buffer too small"); + goto done; + } + if (strcmp(oidstr0, oidstr2) == 0) + clicon_debug(1, "%s \"%s\" %s inclusive:%d %s", __FUNCTION__, + oidstr2, + snmp_msg_int2str(reqinfo->mode), + requests->inclusive, tablehandler?"table":""); + else + clicon_debug(1, "%s \"%s\"/\"%s\" %s inclusive:%d %s", __FUNCTION__, + oidstr2, oidstr0, + snmp_msg_int2str(reqinfo->mode), + requests->inclusive, tablehandler?"table":""); retval = 0; done: @@ -140,6 +141,7 @@ clixon_snmp_table_handler(netsnmp_mib_handler *handler, cbuf *cb = NULL; int ret; + clicon_debug(2, "%s", __FUNCTION__); if ((ret = snmp_common_handler(handler, nhreg, reqinfo, requests, &sh, 1)) < 0) goto done; switch(reqinfo->mode){ @@ -253,7 +255,7 @@ snmp_scalar_get(clicon_handle h, } if (type_yang2asn1(ys, &asn1type) < 0) goto done; - if ((ret = type_snmpstr2val(snmpstr, asn1type, &snmpval, &snmplen, &reason)) < 0) + if ((ret = type_snmpstr2val(snmpstr, &asn1type, &snmpval, &snmplen, &reason)) < 0) goto done; if (ret == 0){ clicon_debug(1, "%s %s", __FUNCTION__, reason); @@ -365,14 +367,10 @@ clixon_snmp_scalar_handler(netsnmp_mib_handler *handler, int asn1_type; netsnmp_variable_list *requestvb = requests->requestvb; + clicon_debug(2, "%s", __FUNCTION__); if (snmp_common_handler(handler, nhreg, reqinfo, requests, &sh, 0) < 0) goto done; ys = sh->sh_ys; -#if 0 /* If oid match fails */ - netsnmp_set_request_error(reqinfo, requests, - SNMP_NOSUCHOBJECT); - return SNMP_ERR_NOERROR; -#endif /* see net-snmp/agent/snmp_agent.h / net-snmp/library/snmp.h */ switch (reqinfo->mode) { case MODE_GET: /* 160 */ @@ -387,9 +385,11 @@ clixon_snmp_scalar_handler(netsnmp_mib_handler *handler, /* Translate from YANG ys leaf type to SNMP asn1.1 type ids (not value), also cvtype */ if (type_yang2asn1(ys, &asn1_type) < 0) goto done; - if (requestvb->type != asn1_type) + if (requestvb->type != asn1_type){ + clicon_debug(1, "%s Expected type:%d, got: %d", __FUNCTION__, requestvb->type, asn1_type); netsnmp_set_request_error(reqinfo, requests, SNMP_ERR_WRONGTYPE); + } break; case MODE_SET_RESERVE2: /* 1 */ break; diff --git a/apps/snmp/snmp_lib.c b/apps/snmp/snmp_lib.c index 115dd9da..fc84954a 100644 --- a/apps/snmp/snmp_lib.c +++ b/apps/snmp/snmp_lib.c @@ -57,6 +57,7 @@ #include #include #include +#include /* ether_aton */ /* net-snmp */ #include @@ -101,20 +102,23 @@ static const map_str2int snmp_type_map[] = { {"enumeration", ASN_INTEGER}, // 2 special case {"uint32", ASN_GAUGE}, // 0x42 / 66 {"uint32", ASN_COUNTER}, // 0x41 / 65 + {"uint32", ASN_TIMETICKS}, // 0x43 / 67 {"uint64", ASN_COUNTER64}, // 0x46 / 70 {"boolean", ASN_INTEGER}, // 2 special case -> enumeration {NULL, -1} }; +#define CLIXON_ASN_PHYS_ADDR 0x4242 /* Map between SNMP message / mode str and int form */ static const map_str2int snmp_msg_map[] = { - {"MODE_SET_RESERVE1", MODE_SET_RESERVE1}, - {"MODE_SET_RESERVE2", MODE_SET_RESERVE2}, - {"MODE_SET_ACTION", MODE_SET_ACTION}, - {"MODE_SET_COMMIT", MODE_SET_COMMIT}, - {"MODE_GET", MODE_GET}, // 160 - {"MODE_GETNEXT", MODE_GETNEXT}, // 161 + {"MODE_SET_RESERVE1", MODE_SET_RESERVE1}, // 0 + {"MODE_SET_RESERVE2", MODE_SET_RESERVE2}, // 1 + {"MODE_SET_ACTION", MODE_SET_ACTION}, // 2 + {"MODE_SET_COMMIT", MODE_SET_COMMIT}, // 3 + {"MODE_SET_FREE", MODE_SET_FREE}, // 4 + {"MODE_GET", MODE_GET}, // 160 + {"MODE_GETNEXT", MODE_GETNEXT}, // 161 {NULL, -1} }; @@ -187,6 +191,16 @@ type_yang2asn1(yang_stmt *ys, else if (strcmp(origtype, "object-identifier-128")==0){ at = ASN_OBJECT_ID; } + else if (strcmp(origtype, "binary")==0){ + at = ASN_OCTET_STR; + } + else if (strcmp(origtype, "timeticks")==0){ + at = ASN_TIMETICKS; /* Clixon extended string type */ + } + else if (strcmp(origtype, "phys-address")==0){ + at = CLIXON_ASN_PHYS_ADDR; /* Clixon extended string type */ + } + /* translate to asn.1 */ else if ((at = clicon_str2int(snmp_type_map, restype)) < 0){ clicon_err(OE_YANG, 0, "No snmp translation for YANG %s type:%s", @@ -248,6 +262,7 @@ type_snmp2xml(yang_stmt *ys, goto done; } switch (requestvb->type){ + case ASN_TIMETICKS: // 67 case ASN_INTEGER: // 2 if (cvtype == CGV_STRING){ /* special case for enum */ char *xmlstr; @@ -342,8 +357,10 @@ type_xml2snmpstr(char *xmlstr, if (strcmp(restype, "enumeration") == 0){ /* special case for enum */ if ((ret = yang_enum2valstr(yrestype, xmlstr, &str)) < 0) goto done; - if (ret == 0) + if (ret == 0){ + clicon_debug(1, "Invalid enum valstr %s", xmlstr); goto fail; + } } /* special case for bool: although smidump translates TruthValue to boolean * and there is an ASN_BOOLEAN constant: @@ -374,18 +391,20 @@ type_xml2snmpstr(char *xmlstr, /*! Given snmp string value (as translated frm XML) parse into snmp value * - * @param[in] snmpstr SNMP type string - * @param[in] asn1type ASN.1 type id - * @param[out] snmpval Malloc:ed snmp type - * @param[out] snmplen Length of snmp type - * @param[out] reason Error reason if retval is 0 - * @retval 1 OK - * @retval 0 Invalid - * @retval -1 Error + * @param[in] snmpstr SNMP type string + * @param[in,out] asn1type ASN.1 type id + * @param[out] snmpval Malloc:ed snmp type + * @param[out] snmplen Length of snmp type + * @param[out] reason Error reason if retval is 0 + * @retval 1 OK + * @retval 0 Invalid + * @retval -1 Error + * @note asn1type can be rewritten from CLIXON_ASN_ to ASN_ + * XXX See sprint_realloc_timeticks */ int type_snmpstr2val(char *snmpstr, - int asn1type, + int *asn1type, u_char **snmpval, size_t *snmplen, char **reason) @@ -397,7 +416,7 @@ type_snmpstr2val(char *snmpstr, clicon_err(OE_UNIX, EINVAL, "snmpval or snmplen is NULL"); goto done; } - switch (asn1type){ + switch (*asn1type){ case ASN_INTEGER: // 2 *snmplen = 4; if ((*snmpval = malloc(*snmplen)) == NULL){ @@ -409,6 +428,7 @@ type_snmpstr2val(char *snmpstr, if (ret == 0) goto fail; break; + case ASN_TIMETICKS: case ASN_COUNTER: // 0x41 case ASN_GAUGE: // 0x42 *snmplen = 4; @@ -422,7 +442,21 @@ type_snmpstr2val(char *snmpstr, goto fail; break; - case ASN_OBJECT_ID: // 6 + case ASN_OBJECT_ID:{ // 6 + oid oid1[MAX_OID_LEN] = {0,}; + size_t sz1 = MAX_OID_LEN; + if (snmp_parse_oid(snmpstr, oid1, &sz1) == NULL){ + clicon_debug(1, "Failed to parse OID %s", snmpstr); + goto fail; + } + *snmplen = sizeof(oid)*sz1; + if ((*snmpval = malloc(*snmplen)) == NULL){ + clicon_err(OE_UNIX, errno, "malloc"); + goto done; + } + memcpy(*snmpval, oid1, *snmplen); + break; + } case ASN_OCTET_STR: // 4 *snmplen = strlen(snmpstr)+1; if ((*snmpval = (u_char*)strdup((snmpstr))) == NULL){ @@ -448,6 +482,22 @@ type_snmpstr2val(char *snmpstr, goto fail; } break; + case CLIXON_ASN_PHYS_ADDR:{ + struct ether_addr *eaddr; + *snmplen = sizeof(*eaddr); + if ((*snmpval = malloc(*snmplen + 1)) == NULL){ + clicon_err(OE_UNIX, errno, "malloc"); + goto done; + } + memset(*snmpval, 0, *snmplen + 1); + if ((eaddr = ether_aton(snmpstr)) == NULL){ + clicon_debug(1, "ether_aton(%s)", snmpstr); + goto fail; + } + memcpy(*snmpval, eaddr, sizeof(*eaddr)); + *asn1type = ASN_OCTET_STR; + break; + } default: assert(0); } diff --git a/apps/snmp/snmp_lib.h b/apps/snmp/snmp_lib.h index db9f7ed2..d0f4fbef 100644 --- a/apps/snmp/snmp_lib.h +++ b/apps/snmp/snmp_lib.h @@ -68,7 +68,7 @@ int type_snmp2xml(yang_stmt *ys, netsnmp_request_info *requests, char **valstr); int type_xml2snmpstr(char *xmlstr, yang_stmt *ys, char **snmpstr); -int type_snmpstr2val(char *snmpstr, int asn1type, u_char **snmpval, size_t *snmplen, char **reason); +int type_snmpstr2val(char *snmpstr, int *asn1type, u_char **snmpval, size_t *snmplen, char **reason); int yang2xpath(yang_stmt *ys, cvec *keyvec, char **xpath); #endif /* _SNMP_LIB_H_ */ diff --git a/test/test_snmp_ifmib.sh b/test/test_snmp_ifmib.sh index 1e57bca2..cb6dce51 100755 --- a/test/test_snmp_ifmib.sh +++ b/test/test_snmp_ifmib.sh @@ -77,15 +77,17 @@ cat < $fstate 0 123 124 + 124 125 126 127 128 129 + 129 130 131 132 - + SNMPv2-SMI::zeroDotZero 2 @@ -164,100 +166,76 @@ MIB=".1.3.6.1.2.1" for (( i=1; i<23; i++ )); do eval OID${i}="${MIB}.2.2.1.$i.1" done -if false; then -OID1="${MIB}.2.2.1.1.1" -OID2="${MIB}.2.2.1.2.1" -OID3="${MIB}.2.2.1.3.1" -OID4="${MIB}.2.2.1.4.1" -OID5="${MIB}.2.2.1.5.1" -OID6="${MIB}.2.2.1.6.1" -OID7="${MIB}.2.2.1.7.1" -OID8="${MIB}.2.2.1.8.1" -OID9="${MIB}.2.2.1.9.1" -OID10="${MIB}.2.2.1.10.1" -OID11="${MIB}.2.2.1.11.1" -OID12="${MIB}.2.2.1.12.1" -OID13="${MIB}.2.2.1.13.1" -OID14="${MIB}.2.2.1.14.1" -OID15="${MIB}.2.2.1.15.1" -OID16="${MIB}.2.2.1.16.1" -OID17="${MIB}.2.2.1.17.1" -OID18="${MIB}.2.2.1.18.1" -OID19="${MIB}.2.2.1.19.1" -OID20="${MIB}.2.2.1.20.1" -OID21="${MIB}.2.2.1.21.1" -OID22="${MIB}.2.2.1.22.1" -fi new "$snmpget" new "Test SNMP get all entries in ifTable" -new "Test $OID2" +new "Test $OID1 ifIndex" expectpart "$($snmpget $OID1)" 0 "$OID1 = INTEGER: 1" -new "Test $OID2" +new "Test $OID2 ifDescr" expectpart "$($snmpget $OID2)" 0 "$OID2 = STRING: Test" -new "Test $OID3" +new "Test $OID3 ifType" expectpart "$($snmpget $OID3)" 0 "$OID3 = INTEGER: ethernetCsmacd(6)" -new "Test $OID4" +new "Test $OID4 ifMtu" expectpart "$($snmpget $OID4)" 0 "$OID4 = INTEGER: 1500" -new "Test $OID5" +new "Test $OID5 ifSpeed" expectpart "$($snmpget $OID5)" 0 "$OID5 = Gauge32: 10000000" -new "Test $OID6" -#expectpart "$($snmpget $OID6)" 0 "$OID6 = STRING: aa.bb:cc:dd:ee:ff" +new "Test $OID6 ifPhysAddress yang:phys-address" +expectpart "$($snmpget $OID6)" 0 "$OID6 = STRING: aa.bb:cc:dd:ee:ff" -new "Test $OID7" +new "Test $OID7 ifAdminStatus" expectpart "$($snmpget $OID7)" 0 "$OID7 = INTEGER: testing(3)" -new "Test $OID8" +new "Test $OID8 ifOperStatus" expectpart "$($snmpget $OID8)" 0 "$OID8 = INTEGER: up(1)" -new "Test $OID9" -#expectpart "$($snmpget $OID9)" 0 "$OID9 = Timeticks: (0) 0:00:00.00" +new "Test $OID9 ifLastChange" +expectpart "$($snmpget $OID9)" 0 "$OID9 = Timeticks: (0) 0:00:00.00" -new "Test $OID10" +new "Test $OID10 ifInOctets" expectpart "$($snmpget $OID10)" 0 "$OID10 = Counter32: 123" -new "Test $OID11" +new "Test $OID11 ifInUcastPkts" expectpart "$($snmpget $OID11)" 0 "$OID11 = Counter32: 124" -new "Test $OID12" -#expectpart "$($snmpget $OID12)" 0 "$OID12 = Counter32: 125" +new "Test $OID12 ifInNUcastPkts" +expectpart "$($snmpget $OID12)" 0 "$OID12 = Counter32: 124" -new "Test $OID13" +new "Test $OID13 ifInDiscards" expectpart "$($snmpget $OID13)" 0 "$OID13 = Counter32: 125" -new "Test $OID14" +new "Test $OID14 ifInErrors" expectpart "$($snmpget $OID14)" 0 "$OID14 = Counter32: 126" -new "Test $OID15" +new "Test $OID15 ifInUnknownProtos" expectpart "$($snmpget $OID15)" 0 "$OID15 = Counter32: 127" -new "Test $OID16" +new "Test $OID16 ifOutOctets" expectpart "$($snmpget $OID16)" 0 "$OID16 = Counter32: 128" -new "Test $OID17" +new "Test $OID17 ifOutUcastPkts" expectpart "$($snmpget $OID17)" 0 "$OID17 = Counter32: 129" -new "Test $OID18" -#expectpart "$($snmpget $OID18)" 0 "$OID18 = Counter32: 130" +new "Test $OID18 ifOutNUcastPkts" +expectpart "$($snmpget $OID18)" 0 "$OID18 = Counter32: 129" -new "Test $OID19" +new "Test $OID19 ifOutDiscards" expectpart "$($snmpget $OID19)" 0 "$OID19 = Counter32: 130" -new "Test $OID20" +new "Test $OID20 ifOutErrors" expectpart "$($snmpget $OID20)" 0 "$OID20 = Counter32: 131" -new "Test $OID21" +new "Test $OID21 ifOutQLen" expectpart "$($snmpget $OID21)" 0 "$OID21 = Gauge32: 132" -new "Test $OID22" -#expectpart "$($snmpget $OID22)" 0 "$OID22 = OID: SNMPv2-SMI::zeroDotZero" +new "Test $OID22 ifSpecific" +expectpart "$($snmpget $OID22)" 0 "$OID22 = OID: .0.0" new "Cleaning up" testexit diff --git a/test/test_snmp_set.sh b/test/test_snmp_set.sh index 79d836e1..627ba8b9 100755 --- a/test/test_snmp_set.sh +++ b/test/test_snmp_set.sh @@ -160,17 +160,17 @@ expectpart "$($snmpget $OID)" 0 "$OID = $TYPE: $VALUE" NAME=ifTableLastChange OID=$OID4 -VALUE=12345678 -TYPE=Gauge32 # TimeTicks +VALUE=12345 # (12345) 0:02:03.45 +TYPE=TimeTicks new "Get $NAME" expectpart "$($snmpget $OID)" 0 "$OID = No Such Instance currently exists at this OID" new "Set $NAME $VALUE" -expectpart "$($snmpset $OID u $VALUE)" 0 "$OID = $TYPE: $VALUE" +expectpart "$($snmpset $OID t $VALUE)" 0 "$OID = $TYPE: ($VALUE) 0:02:03.45" new "Get $NAME $VALUE" -expectpart "$($snmpget $OID)" 0 "$OID = $TYPE: $VALUE" +expectpart "$($snmpget $OID)" 0 "$OID = $TYPE: ($VALUE) 0:02:03.45" NAME=ifType OID=$OID5 @@ -205,19 +205,6 @@ expectpart "$($snmpset $OID i $VALUE)" 0 "$OID = $TYPE: $VALUE" new "Get $NAME $VALUE" expectpart "$($snmpget $OID)" 0 "$OID = $TYPE: $VALUE" -NAME=ifInOctets -OID=$OID8 -VALUE=123456 -TYPE=Counter32 - -new "Set $NAME $VALUE" -# XXXYYY -#expectpart "$($snmpset $OID u $VALUE)" 0 "$OID = $TYPE: $VALUE" - -new "Get $NAME $VALUE" -# XXXYYY -#expectpart "$($snmpget $OID)" 0 "$OID = $TYPE: $VALUE" - NAME=ifPromiscuousMode OID=$OID10 VALUE=1 # true(1) diff --git a/test/test_snmp_table.sh b/test/test_snmp_table.sh index 6532dbf3..ac5d4fbc 100755 --- a/test/test_snmp_table.sh +++ b/test/test_snmp_table.sh @@ -116,11 +116,11 @@ function testexit() new "SNMP table tests" testinit -new "Test SNMP table for netSnmpIETFWGTable" -# XXXYYY -#expectpart "$($snmptable $OID)" 0 "SNMP table: NET-SNMP-EXAMPLES-MIB::netSnmpIETFWGTable" "Russ Mundy" "David Harrington" - if false; then # NOT YET + new "Test SNMP table for netSnmpIETFWGTable" + expectpart "$($snmptable $OID)" 0 "SNMP table: NET-SNMP-EXAMPLES-MIB::netSnmpIETFWGTable" "Russ Mundy" "David Harrington" + + new "Set new value for one cell" expectpart "$($snmpset $OID_SET s newstring)" 0 "$OID_SET = STRING: \"newstring\"" diff --git a/test/test_snmp_types.sh b/test/test_snmp_types.sh index ebe07f68..51135676 100755 --- a/test/test_snmp_types.sh +++ b/test/test_snmp_types.sh @@ -62,7 +62,7 @@ cat < $fstate 0x7fffffff -1 This is not default - 12345678 + 12345 modem 123123123 testing @@ -189,12 +189,12 @@ new "Get $NAME $VALUE" expectpart "$($snmpget $OID)" 0 "$OID = $TYPE: $VALUE" new "Test SNMP getnext netSnmpExampleString" -expectpart "$($snmpgetnext $OID3)" 0 "$OID4 = Gauge32: 12345678" +expectpart "$($snmpgetnext $OID3)" 0 "$OID4 = Timeticks: (12345) 0:02:03.45" NAME=ifTableLastChange OID=$OID4 -VALUE=12345678 -TYPE=Gauge32 # TimeTicks +VALUE="(12345) 0:02:03.45" +TYPE=TimeTicks new "Get $NAME $VALUE" expectpart "$($snmpget $OID)" 0 "$OID = $TYPE: $VALUE" @@ -271,7 +271,7 @@ expectpart "$($snmpgetnext $OID10)" 0 "$OID11 = Gauge32: 1234567890" NAME=ifCounterDiscontinuityTime OID=$OID11 VALUE=1234567890 -TYPE=Gauge32 # TimeStamp +TYPE=Gauge32 # timestamp new "Get $NAME $VALUE" expectpart "$($snmpget $OID)" 0 "$OID = $TYPE: $VALUE" @@ -292,21 +292,23 @@ expectpart "$($snmpgetnext $OID12)" 0 "" # XXX table OID #----------------- table +# the index/key netSnmpHostName has type binary translates to string +# which requires a transaltion to numeric OID which is NYI +if false; then new "Test SNMP table netSnmpIETFWGTable" -#XXXYYY -#expectpart "$($snmptable $OID13)" 0 "Name1" "Name2" +expectpart "$($snmptable $OID13)" 0 "Name1" "Name2" new "Test SNMP getnext netSnmpIETFWGTable" -#XXXYYY -#expectpart "$($snmpgetnext $OID13)" 0 "" +expectpart "$($snmpgetnext $OID13)" 0 "" new "Test SNMP table netSnmpHostsTable" -#XXXYYY -#expectpart "$($snmptable $OID18)" 0 "10.20.30.40" # Should verify all columns +expectpart "$($snmptable $OID18)" 0 "10.20.30.40" # Should verify all columns new "Test SNMP getnext netSnmpHostsTable $OID18" expectpart "$($snmpgetnext $OID18)" 0 "" +fi + new "Cleaning up" testexit