SNMP Support for display-hint "255t" for fixed string translation

This commit is contained in:
Olof hagsand 2022-07-09 12:41:58 +02:00
parent 4cf1d04cb7
commit d79d0aa933
3 changed files with 61 additions and 35 deletions

View file

@ -111,10 +111,8 @@ static const map_str2int snmp_type_map[] = {
{NULL, -1}
};
//#define CLIXON_ASN_PHYS_ADDR 0x4242 /* Special case phy-address */
//#define CLIXON_ASN_ADMIN_STRING 0x4243 /* Special case SnmpAdminString */
#define CLIXON_ASN_PHYS_ADDR 253 /* Special case phy-address */
#define CLIXON_ASN_ADMIN_STRING 254 /* Special case SnmpAdminString */
#define CLIXON_ASN_FIXED_STRING 254 /* RFC2578 Sec 7.7: String-valued, fixed-length */
/* Map between clixon "orig" resolved type and ASN.1 types.
*/
@ -130,7 +128,6 @@ static const map_str2int snmp_orig_map[] = {
{"InetAddress", ASN_IPADDRESS}, // 0x40 / 64 (Dont see this being used)
{"ipv4-address", ASN_IPADDRESS}, // 0x40 / 64 (This is used instead)
{"phys-address", CLIXON_ASN_PHYS_ADDR}, /* Clixon extended string type */
{"SnmpAdminString", CLIXON_ASN_ADMIN_STRING}, /* cf extension display-type 255T? */
{NULL, -1}
};
@ -436,15 +433,16 @@ type_yang2asn1(yang_stmt *ys,
char *restype; /* resolved type */
char *origtype = NULL; /* original type */
int at;
yang_stmt *yrestype = NULL;
/* Get yang type of leaf and translate to ASN.1 */
if (snmp_yang_type_get(ys, NULL, &origtype, NULL, &restype) < 0)
if (snmp_yang_type_get(ys, NULL, &origtype, &yrestype, &restype) < 0)
goto done;
/* Translate to asn.1
* First try original type, first type
*/
if ((at = clicon_str2int(snmp_orig_map, origtype)) >= 0 &&
(extended || (at != CLIXON_ASN_PHYS_ADDR && at != CLIXON_ASN_ADMIN_STRING))){
(extended || (at != CLIXON_ASN_PHYS_ADDR && at != CLIXON_ASN_FIXED_STRING))){
;
}
/* Then try fully resolved type */
@ -453,6 +451,16 @@ type_yang2asn1(yang_stmt *ys,
yang_argument_get(ys), restype);
goto done;
}
if (extended && at == ASN_OCTET_STR && yrestype){
yang_stmt *yrp;
char *display_hint = NULL;
yrp = yang_parent_get(yrestype);
if (yang_extension_value(yrp, "display-hint", IETF_YANG_SMIV2_NS, NULL, &display_hint) < 0)
goto done;
/* RFC2578/2579 but maybe all strings with display-hint should use this, eg exist>0? */
if (display_hint && strcmp(display_hint, "255t")==0)
at = CLIXON_ASN_FIXED_STRING;
}
if (asn1_type)
*asn1_type = at;
retval = 0;
@ -550,7 +558,7 @@ type_snmp2xml(yang_stmt *ys,
cv_string_set(cv, inet_ntoa(addr));
break;
}
case CLIXON_ASN_ADMIN_STRING:
case CLIXON_ASN_FIXED_STRING:
cv_string_set(cv, (char*)requestvb->val.string);
*asn1type = ASN_OCTET_STR;
break;
@ -783,7 +791,7 @@ type_xml2snmp(char *snmpstr,
*asn1type = ASN_OCTET_STR;
break;
}
case CLIXON_ASN_ADMIN_STRING: /* OCTET-STRING with decrement length */
case CLIXON_ASN_FIXED_STRING: /* OCTET-STRING with decrement length */
*snmplen = strlen(snmpstr);
if ((*snmpval = (u_char*)strdup((snmpstr))) == NULL){
clicon_err(OE_UNIX, errno, "strdup");
@ -951,11 +959,12 @@ snmp_str2oid(char *str,
/*! Translate from SMI OID representation to name
* For ints this is one to one, eg 42 -> 42
* But for eg strings this is more comples, eg foo -> 3.6.22.22 (or something,...)
* But for eg strings this is more complex, eg foo -> 3.6.22.22 (or something,...)
* @param[in,out] oidi ObjID vector
* @param[in,out] oidilen Length of ObjID vector
* @param[in] yk Yang statement of key
* @param[out] cv CLIgen variable string notation as "x.y.z"
* @see rfc2578 Section 7.7
*/
int
snmp_oid2str(oid **oidi,
@ -969,7 +978,7 @@ snmp_oid2str(oid **oidi,
cbuf *enc = NULL;
size_t len;
if (type_yang2asn1(yk, &asn1_type, 0) < 0)
if (type_yang2asn1(yk, &asn1_type, 1) < 0)
goto done;
if ((enc = cbuf_new()) == NULL){
clicon_err(OE_UNIX, errno, "cbuf_new");
@ -984,12 +993,18 @@ snmp_oid2str(oid **oidi,
case ASN_IPADDRESS:
cprintf(enc, "%lu", (*oidi)[i++]);
break;
case CLIXON_ASN_PHYS_ADDR: /* XXX may need special mapping: ether_aton() ? */
case ASN_OCTET_STR: /* decode from N.c.c.c.c */
len = (*oidi)[i++];
for (; i<len+1; i++){
cprintf(enc, "%c", (char)((*oidi)[i]&0xff));
}
break;
case CLIXON_ASN_FIXED_STRING: // XXX
for (; i<7; i++){
cprintf(enc, "%c", (char)((*oidi)[i]&0xff));
}
break;
default:
break;
}

View file

@ -155,9 +155,18 @@ There are also client-cert tests, eg `test_ssl_certs.sh`
Clixon snmp frontend tests require a running netsnmpd and converted YANG files from MIB.
Netsnmpd is 5.9 or later and can be started via systemd. For the tests
to run, the systems IFMIB should be disabled: `-I -ifTable,ifNumber,ifXTable`
to run, the systems IFMIB should be disabled: `-I -ifTable,ifNumber,ifXTable`, etc.
Converted YANG files are available at `https://github.com/clicon/mib-yangs` or alternatively use `smidump` version 0.5 or later.
Converted YANG files are available at `https://github.com/clicon/mib-yangs` or alternatively use `smidump` version 0.5 or later. Clixon expects them to be at `/usr/local/share/mib-yangs/` by default, or configured by `--with-mib-generated-yang-dir=DIR`.
You also need to configure a unix socket for agent. Example of /etc/snmp/snmpd.conf:
```
master agentx
agentaddress 127.0.0.1,[::1]
rwcommunity public localhost
agentXSocket unix:/var/run/snmp.sock
agentxperms 777 777
```
## Known issues

View file

@ -1,7 +1,6 @@
#!/usr/bin/env bash
# snmpset. This requires deviation of MIB-YANG to make write operations
# Get default value, set new value via SNMP and check it, set new value via NETCONF and check
# Selected types from CLIXON/IF-MIB/ENTITY mib
# SNMP table rowstatus tests
#
# Magic line must be first in script (see README.md)
s="$_" ; . ./lib.sh || if [ "$s" = $0 ]; then exit 0; else return 0; fi
@ -102,34 +101,37 @@ function testrun_createAndGo()
{
new "createAndGo"
expectpart "$($snmpset SNMP-NOTIFICATION-MIB::snmpNotifyTag.'notify1' = 2)" 0 "Error in packet."
new "Configuring a value without a row is a failure"
echo "$snmpset SNMP-NOTIFICATION-MIB::snmpNotifyTag.\'notify1\' = 2"
expectpart "$($snmpset SNMP-NOTIFICATION-MIB::snmpNotifyTag.\'notify1\' = 2)" 0 "Error in packet."
new "RowStatus is active after createAndGo; can configure additional values afterwards"
echo "$snmpset SNMP-NOTIFICATION-MIB::snmpNotifyRowStatus.\'notify1\' = createAndGo SNMP-NOTIFICATION-MIB::snmpNotifyTag.'notify1' = 2"
expectpart "$($snmpset SNMP-NOTIFICATION-MIB::snmpNotifyRowStatus.\'notify1\' = createAndGo SNMP-NOTIFICATION-MIB::snmpNotifyTag.\'notify1\' = 2)" 0 "SNMP-NOTIFICATION-MIB::snmpNotifyRowStatus.'notify1' = INTEGER: createAndGo(4)"
expectpart "$($snmpset SNMP-NOTIFICATION-MIB::snmpNotifyRowStatus.'notify1' = createAndGo SNMP-NOTIFICATION-MIB::snmpNotifyTag.'notify1' = 2)" 0 "SNMP-NOTIFICATION-MIB::snmpNotifyRowStatus.'notify1' = INTEGER: createAndGo(4)"
expectpart "$($snmpget SNMP-NOTIFICATION-MIB::snmpNotifyRowStatus.\'notify1\')" 0 "SNMP-NOTIFICATION-MIB::snmpNotifyRowStatus.'notify1' = INTEGER: active(1)"
expectpart "$($snmpget SNMP-NOTIFICATION-MIB::snmpNotifyRowStatus.'notify1')" 0 "SNMP-NOTIFICATION-MIB::snmpNotifyRowStatus.'notify1' = INTEGER: active(1)"
expectpart "$($snmpget SNMP-NOTIFICATION-MIB::snmpNotifyTag.\'notify1\')" 0 "SNMP-NOTIFICATION-MIB::snmpNotifyTag.'notify1' = 2"
expectpart "$($snmpget SNMP-NOTIFICATION-MIB::snmpNotifyTag.'notify1')" 0 "SNMP-NOTIFICATION-MIB::snmpNotifyTag.'notify1' = 2"
expectpart "$($snmpset SNMP-NOTIFICATION-MIB::snmpNotifyStorageType.'notify1' = 1)" 0 "SNMP-NOTIFICATION-MIB::snmpNotifyStorageType.'notify1' = 1"
expectpart "$($snmpset SNMP-NOTIFICATION-MIB::snmpNotifyStorageType.\'notify1\' = 1)" 0 "SNMP-NOTIFICATION-MIB::snmpNotifyStorageType.'notify1' = 1"
}
function testrun_createAndWait()
{
new "createAndWait"
expectpart "$($snmpset SNMP-NOTIFICATION-MIB::snmpNotifyRowStatus.'notify1' = createAndWait SNMP-NOTIFICATION-MIB::snmpNotifyTag.'notify1' = 2)" 0 "SNMP-NOTIFICATION-MIB::snmpNotifyRowStatus.'notify1' = createAndWait"
expectpart "$($snmpset SNMP-NOTIFICATION-MIB::snmpNotifyRowStatus.\'notify1\' = createAndWait SNMP-NOTIFICATION-MIB::snmpNotifyTag.'notify1' = 2)" 0 "SNMP-NOTIFICATION-MIB::snmpNotifyRowStatus.'notify1' = createAndWait"
expectpart "$($snmpget SNMP-NOTIFICATION-MIB::snmpNotifyTag.'notify1')" 0 "SNMP-NOTIFICATION-MIB::snmpNotifyTag.'notify1' = 2"
expectpart "$($snmpget SNMP-NOTIFICATION-MIB::snmpNotifyTag.\'notify1\')" 0 "SNMP-NOTIFICATION-MIB::snmpNotifyTag.'notify1' = 2"
expectpart "$($snmpget SNMP-NOTIFICATION-MIB::snmpNotifyRowStatus.'notify1')" 0 "SNMP-NOTIFICATION-MIB::snmpNotifyRowStatus.'notify1' = INTEGER: notInService(2)"
expectpart "$($snmpget SNMP-NOTIFICATION-MIB::snmpNotifyRowStatus.\'notify1\')" 0 "SNMP-NOTIFICATION-MIB::snmpNotifyRowStatus.'notify1' = INTEGER: notInService(2)"
expectpart "$($snmpset SNMP-NOTIFICATION-MIB::snmpNotifyStorageType.'notify1' = 1)" 0 "SNMP-NOTIFICATION-MIB::snmpNotifyStorageType.'notify1' = 1"
expectpart "$($snmpset SNMP-NOTIFICATION-MIB::snmpNotifyStorageType.\'notify1\' = 1)" 0 "SNMP-NOTIFICATION-MIB::snmpNotifyStorageType.'notify1' = 1"
expectpart "$($snmpset SNMP-NOTIFICATION-MIB::snmpNotifyRowStatus.'notify1' = active)" 0 "SNMP-NOTIFICATION-MIB::snmpNotifyRowStatus.'notify1' = active"
expectpart "$($snmpset SNMP-NOTIFICATION-MIB::snmpNotifyRowStatus.\'notify1\' = active)" 0 "SNMP-NOTIFICATION-MIB::snmpNotifyRowStatus.'notify1' = active"
expectpart "$($snmpset SNMP-NOTIFICATION-MIB::snmpNotifyStorageType.'notify1' = 5)" 0 "SNMP-NOTIFICATION-MIB::snmpNotifyStorageType.'notify1' = 5"
expectpart "$($snmpset SNMP-NOTIFICATION-MIB::snmpNotifyStorageType.\'notify1\' = 5)" 0 "SNMP-NOTIFICATION-MIB::snmpNotifyStorageType.'notify1' = 5"
expectpart "$($snmpset SNMP-NOTIFICATION-MIB::snmpNotifyRowStatus.'notify1' = createAndWait)" 0 "SNMP-NOTIFICATION-MIB::snmpNotifyRowStatus.'notify1' = createAndWait"
expectpart "$($snmpset SNMP-NOTIFICATION-MIB::snmpNotifyRowStatus.\'notify1\' = createAndWait)" 0 "SNMP-NOTIFICATION-MIB::snmpNotifyRowStatus.'notify1' = createAndWait"
expectpart "$($snmpset SNMP-NOTIFICATION-MIB::snmpNotifyRowStatus.'notify2' = createAndGo)" 0 "SNMP-NOTIFICATION-MIB::snmpNotifyRowStatus.'notify2' = createAndGo"
@ -137,20 +139,20 @@ function testrun_createAndWait()
expectpart "$($snmpset SNMP-NOTIFICATION-MIB::snmpNotifyRowStatus.'notify3' = active)" 0 "SNMP-NOTIFICATION-MIB::snmpNotifyRowStatus.'notify3' = active"
expectpart "$($snmpget SNMP-NOTIFICATION-MIB::snmpNotifyRowStatus.'notify1')" 0 "SNMP-NOTIFICATION-MIB::snmpNotifyRowStatus.'notify1' = INTEGER: notInService(2)"
expectpart "$($snmpget SNMP-NOTIFICATION-MIB::snmpNotifyRowStatus.\'notify1\')" 0 "SNMP-NOTIFICATION-MIB::snmpNotifyRowStatus.'notify1' = INTEGER: notInService(2)"
}
function testrun_removeRows()
{
new "removeRows"
expectpart "$($snmpset SNMP-NOTIFICATION-MIB::snmpNotifyRowStatus.'notify1' = createAndGo)" 0 "SNMP-NOTIFICATION-MIB::snmpNotifyRowStatus.'notify1'"
expectpart "$($snmpset SNMP-NOTIFICATION-MIB::snmpNotifyRowStatus.\'notify1\' = createAndGo)" 0 "SNMP-NOTIFICATION-MIB::snmpNotifyRowStatus.'notify1'"
expectpart "$($snmpset SNMP-NOTIFICATION-MIB::snmpNotifyRowStatus.'notify1' = destroy)" 0 "SNMP-NOTIFICATION-MIB::snmpNotifyRowStatus.'notify1' = destroy"
expectpart "$($snmpset SNMP-NOTIFICATION-MIB::snmpNotifyRowStatus.\'notify1\' = destroy)" 0 "SNMP-NOTIFICATION-MIB::snmpNotifyRowStatus.'notify1' = destroy"
expectpart "$($snmpset SNMP-NOTIFICATION-MIB::snmpNotifyRowStatus.'notify1')" 0 "SNMP-NOTIFICATION-MIB::snmpNotifyRowStatus.'notify1'"
expectpart "$($snmpset SNMP-NOTIFICATION-MIB::snmpNotifyRowStatus.\'notify1\')" 0 "SNMP-NOTIFICATION-MIB::snmpNotifyRowStatus.'notify1'"
expectpart "$($snmpget SNMP-NOTIFICATION-MIB::snmpNotifyRowStatus.'notify1')" 0 "No Such Instance currently exists at this OID)"
expectpart "$($snmpget SNMP-NOTIFICATION-MIB::snmpNotifyRowStatus.\'notify1\')" 0 "No Such Instance currently exists at this OID)"
}
function testexit()
@ -161,7 +163,7 @@ function testexit()
new "SNMP tests"
testinit
if [ -n "$SNMP_DEBUG" ]; then
if $snmp_debug; then
testrun_createAndGo
testrun_createAndWait
testrun_removeRows