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} {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_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. /* 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) {"InetAddress", ASN_IPADDRESS}, // 0x40 / 64 (Dont see this being used)
{"ipv4-address", ASN_IPADDRESS}, // 0x40 / 64 (This is used instead) {"ipv4-address", ASN_IPADDRESS}, // 0x40 / 64 (This is used instead)
{"phys-address", CLIXON_ASN_PHYS_ADDR}, /* Clixon extended string type */ {"phys-address", CLIXON_ASN_PHYS_ADDR}, /* Clixon extended string type */
{"SnmpAdminString", CLIXON_ASN_ADMIN_STRING}, /* cf extension display-type 255T? */
{NULL, -1} {NULL, -1}
}; };
@ -436,15 +433,16 @@ type_yang2asn1(yang_stmt *ys,
char *restype; /* resolved type */ char *restype; /* resolved type */
char *origtype = NULL; /* original type */ char *origtype = NULL; /* original type */
int at; int at;
yang_stmt *yrestype = NULL;
/* Get yang type of leaf and translate to ASN.1 */ /* 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; goto done;
/* Translate to asn.1 /* Translate to asn.1
* First try original type, first type * First try original type, first type
*/ */
if ((at = clicon_str2int(snmp_orig_map, origtype)) >= 0 && 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 */ /* Then try fully resolved type */
@ -453,6 +451,16 @@ type_yang2asn1(yang_stmt *ys,
yang_argument_get(ys), restype); yang_argument_get(ys), restype);
goto done; 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) if (asn1_type)
*asn1_type = at; *asn1_type = at;
retval = 0; retval = 0;
@ -550,7 +558,7 @@ type_snmp2xml(yang_stmt *ys,
cv_string_set(cv, inet_ntoa(addr)); cv_string_set(cv, inet_ntoa(addr));
break; break;
} }
case CLIXON_ASN_ADMIN_STRING: case CLIXON_ASN_FIXED_STRING:
cv_string_set(cv, (char*)requestvb->val.string); cv_string_set(cv, (char*)requestvb->val.string);
*asn1type = ASN_OCTET_STR; *asn1type = ASN_OCTET_STR;
break; break;
@ -783,7 +791,7 @@ type_xml2snmp(char *snmpstr,
*asn1type = ASN_OCTET_STR; *asn1type = ASN_OCTET_STR;
break; break;
} }
case CLIXON_ASN_ADMIN_STRING: /* OCTET-STRING with decrement length */ case CLIXON_ASN_FIXED_STRING: /* OCTET-STRING with decrement length */
*snmplen = strlen(snmpstr); *snmplen = strlen(snmpstr);
if ((*snmpval = (u_char*)strdup((snmpstr))) == NULL){ if ((*snmpval = (u_char*)strdup((snmpstr))) == NULL){
clicon_err(OE_UNIX, errno, "strdup"); clicon_err(OE_UNIX, errno, "strdup");
@ -951,11 +959,12 @@ snmp_str2oid(char *str,
/*! Translate from SMI OID representation to name /*! Translate from SMI OID representation to name
* For ints this is one to one, eg 42 -> 42 * 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] oidi ObjID vector
* @param[in,out] oidilen Length of ObjID vector * @param[in,out] oidilen Length of ObjID vector
* @param[in] yk Yang statement of key * @param[in] yk Yang statement of key
* @param[out] cv CLIgen variable string notation as "x.y.z" * @param[out] cv CLIgen variable string notation as "x.y.z"
* @see rfc2578 Section 7.7
*/ */
int int
snmp_oid2str(oid **oidi, snmp_oid2str(oid **oidi,
@ -969,7 +978,7 @@ snmp_oid2str(oid **oidi,
cbuf *enc = NULL; cbuf *enc = NULL;
size_t len; size_t len;
if (type_yang2asn1(yk, &asn1_type, 0) < 0) if (type_yang2asn1(yk, &asn1_type, 1) < 0)
goto done; goto done;
if ((enc = cbuf_new()) == NULL){ if ((enc = cbuf_new()) == NULL){
clicon_err(OE_UNIX, errno, "cbuf_new"); clicon_err(OE_UNIX, errno, "cbuf_new");
@ -984,12 +993,18 @@ snmp_oid2str(oid **oidi,
case ASN_IPADDRESS: case ASN_IPADDRESS:
cprintf(enc, "%lu", (*oidi)[i++]); cprintf(enc, "%lu", (*oidi)[i++]);
break; break;
case CLIXON_ASN_PHYS_ADDR: /* XXX may need special mapping: ether_aton() ? */
case ASN_OCTET_STR: /* decode from N.c.c.c.c */ case ASN_OCTET_STR: /* decode from N.c.c.c.c */
len = (*oidi)[i++]; len = (*oidi)[i++];
for (; i<len+1; i++){ for (; i<len+1; i++){
cprintf(enc, "%c", (char)((*oidi)[i]&0xff)); cprintf(enc, "%c", (char)((*oidi)[i]&0xff));
} }
break; break;
case CLIXON_ASN_FIXED_STRING: // XXX
for (; i<7; i++){
cprintf(enc, "%c", (char)((*oidi)[i]&0xff));
}
break;
default: default:
break; 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. 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 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 ## Known issues

View file

@ -1,7 +1,6 @@
#!/usr/bin/env bash #!/usr/bin/env bash
# snmpset. This requires deviation of MIB-YANG to make write operations # SNMP table rowstatus tests
# 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
# Magic line must be first in script (see README.md) # Magic line must be first in script (see README.md)
s="$_" ; . ./lib.sh || if [ "$s" = $0 ]; then exit 0; else return 0; fi s="$_" ; . ./lib.sh || if [ "$s" = $0 ]; then exit 0; else return 0; fi
@ -102,34 +101,37 @@ function testrun_createAndGo()
{ {
new "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() function testrun_createAndWait()
{ {
new "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" 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 "$($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() function testrun_removeRows()
{ {
new "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() function testexit()
@ -161,7 +163,7 @@ function testexit()
new "SNMP tests" new "SNMP tests"
testinit testinit
if [ -n "$SNMP_DEBUG" ]; then if $snmp_debug; then
testrun_createAndGo testrun_createAndGo
testrun_createAndWait testrun_createAndWait
testrun_removeRows testrun_removeRows