From a31c7b2eb22d15f1ca6c2d6bca257faa2315fcf7 Mon Sep 17 00:00:00 2001 From: Stefan Zegenhagen Date: Mon, 10 Jun 2013 11:07:00 +0200 Subject: SNMP/VACM: bugfix for vacmViewTreeFamilyMask Dear all, it's almost a year since I sent the patch attached to this e-mail, and I just found out that I have not yet gotten a response to it. I would consider this patch important because it fixes an issue with the interpretation of data that might be critical for SNMPv3 operation. I confirmed at that time that erlangs interpretation of vacmViewTreeFamilyMask is indeed not interoperable with other SNMP stacks. Kind regards, > > > the implementation of SNMP-VIEW-BASED-ACM.mib assumes that the input for > > > vacmViewTreeFamilyMask is an OID consisting of 1's and 0's only to form > > > the mask. However, the MIB states that the input should be a bitstring. > > > > > > The OID representation of the mask is useful in the code as it speeds up > > > time-critical code paths when checking access permissions for EACH SNMP > > > access. Reading/writing the view mask objects is less time-critical. > > > > > > Therefore, to fix the issue, convert between OID representation and > > > bitstring when the vacmViewTreeFamilyMask objects are accessed. This is > > > done by the patch attached to this e-mail. > > > I'm very sorry for the troubles that I am causing but it seems that the > previous version of the patch did more than it should: the OID-bitstring > conversion was also applied to other tables in the same MIB on > get/get-next requests. > > The version of the patch that is attached to this e-mail restricts the > OID-bitstring conversion to vacmViewTreeFamilyMask alone. -- Dr. Stefan Zegenhagen arcutronix GmbH Garbsener Landstr. 10 30419 Hannover Germany Tel: +49 511 277-2734 Fax: +49 511 277-2709 Email: stefan.zegenhagen@arcutronix.com Web: www.arcutronix.com *Synchronize the Ethernet* General Managers: Dipl. Ing. Juergen Schroeder, Dr. Josef Gfrerer - Legal Form: GmbH, Registered office: Hannover, HRB 202442, Amtsgericht Hannover; Ust-Id: DE257551767. Please consider the environment before printing this message. >From aa2acfb8a0b5ae05fc5ba982d78ee5607384a2be Mon Sep 17 00:00:00 2001 From: Stefan Zegenhagen Date: Wed, 1 Aug 2012 09:56:15 +0200 Subject: [PATCH] bugfix for vacmViewTreeFamilyMask The vacmViewTreeFamilyMask is defined to be a bit string in the MIB, not an OID. However, the MIB implementation assumed the latter, effectively rendering all attempts to read/set masks via SNMP unsuccessful. Since the mask is used in hot paths (e.g. access permission checks for each SNMP operation, the OID representation of the mask has benefits (e.g. faster processing). Therefore, convert the bitstring to/from its OID representation when reading/setting any mask object. --- lib/snmp/src/agent/snmp_view_based_acm_mib.erl | 91 ++++++++++++++++++++++++-- 1 file changed, 85 insertions(+), 6 deletions(-) diff --git a/lib/snmp/src/agent/snmp_view_based_acm_mib.erl b/lib/snmp/src/agent/snmp_view_based_acm_mib.erl index ad9540e886..0acef780f8 100644 --- a/lib/snmp/src/agent/snmp_view_based_acm_mib.erl +++ b/lib/snmp/src/agent/snmp_view_based_acm_mib.erl @@ -957,9 +957,9 @@ verify_vacmViewTreeFamilyTable_col(?vacmViewTreeFamilyMask, Mask) -> null -> []; [] -> []; _ -> - case (catch snmp_conf:check_oid(Mask)) of + case (catch check_mask(Mask)) of ok -> - Mask; + mask2oid(Mask); _ -> wrongValue(?vacmViewTreeFamilyMask) end @@ -975,7 +975,54 @@ verify_vacmViewTreeFamilyTable_col(?vacmViewTreeFamilyType, Type) -> end; verify_vacmViewTreeFamilyTable_col(_, Val) -> Val. - + + +check_mask([]) -> + ok; +check_mask([Head | Tail]) when is_integer(Head) -> +% we can cause exception here because the caller catches + if + Head > -1 andalso Head < 256 -> + check_mask(Tail) + end. + +% internally (for easier computations), the mask is stored +% as OID and not as bit-field. Therefore, we have to convert +% the bitstring to a list of integers before storing it. +mask2oid(Mask) -> + Func = fun(Byte) -> + % what's a nice syntax for extracting bits + % from a byte??? + <> = <>, + [A, B, C, D, E, F, G, H] + end, + lists:flatten(lists:map(Func, Mask)). + +oid2mask(Oid) -> + % convert all suboids to either 1 or 0 for sure + Func = fun + (0) -> 0; + (_) -> 1 + end, + oid2mask(lists:map(Func, Oid), []). + +oid2mask([], Mask) -> + % end-of-list, return bitstring + lists:reverse(Mask); +oid2mask(Oid, Mask) -> + % check whether we've got at least 8 sub-identifiers. if not, + % extend with 1's until there are enough to fill a byte + NOid = case length(Oid) of + Small when Small < 8 -> + Oid ++ lists:duplicate(8-Small, 1); + _ -> + Oid + end, + % extract sufficient suboids for 8 bits + [A, B, C, D, E, F, G, H | Tail] = NOid, + <> = <>, + oid2mask(Tail, [Byte | Mask]). + table_next(Name, RestOid) -> snmp_generic:table_next(db(Name), RestOid). @@ -1014,11 +1061,43 @@ stc(vacmSecurityToGroupTable) -> ?vacmSecurityToGroupStorageType; stc(vacmViewTreeFamilyTable) -> ?vacmViewTreeFamilyStorageType. next(Name, RowIndex, Cols) -> - snmp_generic:handle_table_next(db(Name), RowIndex, Cols, - fa(Name), foi(Name), noc(Name)). + Ans = snmp_generic:handle_table_next(db(Name), RowIndex, Cols, + fa(Name), foi(Name), noc(Name)), + patch_next(Name, Ans). get(Name, RowIndex, Cols) -> - snmp_generic:handle_table_get(db(Name), RowIndex, Cols, foi(Name)). + Ans = snmp_generic:handle_table_get(db(Name), RowIndex, Cols, foi(Name)), + patch(Name, Cols, Ans). + + +patch(Name, Cols, Ans) when is_list(Ans) -> + % function to patch returned values + Func = fun + ({Col, {value, Val}}) -> {value, do_patch(Name, Col, Val)}; + ({_, Other}) -> Other + end, + % merge column numbers and return values. there must be as much + % return values as there are columns requested + Tmp = lists:zip(Cols, Ans), + % and patch all values + lists:map(Func, Tmp); +patch(_, _, Ans) -> + Ans. + +patch_next(Name, Ans) when is_list(Ans) -> + Func = fun + ({[C | _] = Idx, Val}) -> {Idx, do_patch(Name, C, Val)}; + (Other) -> Other + end, + lists:map(Func, Ans); +patch_next(_, Ans) -> + Ans. + +do_patch(vacmViewTreeFamilyTable, ?vacmViewTreeFamilyMask, Val) -> + oid2mask(Val); +do_patch(_, _, Val) -> + Val. + wrongValue(V) -> throw({wrongValue, V}). -- cgit v1.2.3 From 7147e7a36b8a22ba6345356aa786029bab66f4e6 Mon Sep 17 00:00:00 2001 From: Micael Karlberg Date: Wed, 3 Jul 2013 09:39:40 +0200 Subject: [snmp/agent] Local DB counter increment wrap error The counter increment function in the local-db was incorrect. It did not handle counter wrap correctly. OTP-11192 --- lib/snmp/doc/src/notes.xml | 58 +++++++++++++++++++++++++++++++++++ lib/snmp/src/agent/snmpa_local_db.erl | 2 +- lib/snmp/src/app/snmp.appup.src | 20 ++++++++++++ lib/snmp/vsn.mk | 2 +- 4 files changed, 80 insertions(+), 2 deletions(-) diff --git a/lib/snmp/doc/src/notes.xml b/lib/snmp/doc/src/notes.xml index 80de9738f1..40e761b2af 100644 --- a/lib/snmp/doc/src/notes.xml +++ b/lib/snmp/doc/src/notes.xml @@ -33,6 +33,64 @@ +
+ SNMP Development Toolkit 4.24.1 +

Version 4.24.1 supports code replacement in runtime from/to + version 4.24, 4.23.1 and 4.23.

+ +
+ Improvements and new features +

-

+ + + +
+ +
+ Fixed Bugs and Malfunctions + + + + +

[agent] The counter increment function in the local-db was + incorrect. It did not handle counter wrap correctly.

+

Own Id: OTP-11192

+
+ +
+ +
+ +
+ Incompatibilities +

-

+ + +
+ +
+ +
SNMP Development Toolkit 4.24

Version 4.24 supports code replacement in runtime from/to diff --git a/lib/snmp/src/agent/snmpa_local_db.erl b/lib/snmp/src/agent/snmpa_local_db.erl index 2c0cad807a..5198c6ec4e 100644 --- a/lib/snmp/src/agent/snmpa_local_db.erl +++ b/lib/snmp/src/agent/snmpa_local_db.erl @@ -583,7 +583,7 @@ handle_cast({variable_inc, Name, Db, N}, State) -> {value, Val} -> Val; _ -> 0 end, - insert(Db, Name, M+N rem 4294967296, State), + insert(Db, Name, (M+N) rem 4294967296, State), {noreply, State}; handle_cast({verbosity,Verbosity}, State) -> diff --git a/lib/snmp/src/app/snmp.appup.src b/lib/snmp/src/app/snmp.appup.src index 7ffa4a725d..53de57efd3 100644 --- a/lib/snmp/src/app/snmp.appup.src +++ b/lib/snmp/src/app/snmp.appup.src @@ -17,18 +17,38 @@ %% %CopyrightEnd% %% + {"%VSN%", %% ----- U p g r a d e ------------------------------------------------------- +%% Instruction examples: +%% {restart_application, snmp} +%% {load_module, snmp_pdus, soft_purge, soft_purge, []} +%% {update, snmpa_local_db, soft, soft_purge, soft_purge, []} +%% {add_module, snmpm_net_if_mt} + [ + {"4.24", + [ + {update, snmpa_local_db, soft, soft_purge, soft_purge, []} + ] + }, {"4.23.1", [{restart_application, snmp}]}, {"4.23", [{restart_application, snmp}]} ], %% ------D o w n g r a d e --------------------------------------------------- +%% Instruction examples: +%% {remove, {snmpm_net_if_mt, soft_purge, soft_purge}} + [ + {"4.24", + [ + {update, snmpa_local_db, soft, soft_purge, soft_purge, []} + ] + }, {"4.23.1", [{restart_application, snmp}]}, {"4.23", [{restart_application, snmp}]} ] diff --git a/lib/snmp/vsn.mk b/lib/snmp/vsn.mk index 0e48e7ea56..e987649e11 100644 --- a/lib/snmp/vsn.mk +++ b/lib/snmp/vsn.mk @@ -18,6 +18,6 @@ # %CopyrightEnd% APPLICATION = snmp -SNMP_VSN = 4.24 +SNMP_VSN = 4.24.1 PRE_VSN = APP_VSN = "$(APPLICATION)-$(SNMP_VSN)$(PRE_VSN)" -- cgit v1.2.3 From a6ba7a3327b146d8472b154cc8ba4544f9d4d0fe Mon Sep 17 00:00:00 2001 From: Micael Karlberg Date: Tue, 25 Jun 2013 12:38:17 +0200 Subject: [snmp/agent] Cleanup, renaming, appup, proper version and release notes Add utility functions for checking view masks. Code cleanup, function renaming and comment fix (%% instead of %). Also updated the mask check in the vacm config file check function. Finally, release notes and some cosmetic changes to the agent config-file(s) user guide chapter. --- lib/snmp/doc/src/notes.xml | 74 +++++++ lib/snmp/doc/src/snmp_agent_config_files.xml | 260 ++++++++++++------------- lib/snmp/src/agent/snmp_view_based_acm_mib.erl | 206 +++++++++++--------- lib/snmp/src/app/snmp.appup.src | 12 ++ lib/snmp/src/misc/snmp_conf.erl | 35 +++- lib/snmp/vsn.mk | 2 +- 6 files changed, 355 insertions(+), 234 deletions(-) diff --git a/lib/snmp/doc/src/notes.xml b/lib/snmp/doc/src/notes.xml index 80de9738f1..9f668bf28a 100644 --- a/lib/snmp/doc/src/notes.xml +++ b/lib/snmp/doc/src/notes.xml @@ -33,6 +33,80 @@ +

+ SNMP Development Toolkit 4.24.1 +

Version 4.24.1 supports code replacement in runtime from/to + version 4.24, 4.23.1 and 4.23.

+ +
+ Improvements and new features +

-

+ + + +
+ +
+ Fixed Bugs and Malfunctions + + + + +

[agent] Reading the value of the vacmViewTreeFamilyMask returns + it in the wrong (internal bitlist) format.

+

The vacmViewTreeFamilyMask is defined as a bit string in the MIB + (OCTET STRING). Internally a bitlist (list of 1's and 0's, + see vacm config file + for more info) is used. + However, the MIB implementation assumed the latter, effectively + rendering all attempts to read/set masks via SNMP unsuccessful.

+

Since the mask is used in hot paths (e.g. access permission checks + for each SNMP operation, the bitlist representation of the mask has + benefits (e.g. faster processing). Reading/writing the view mask + objects is less time-critical. Therefore, to fix the issue, convert + between the bitlist (internal) representation and bitstring + (external) when the vacmViewTreeFamilyMask objects are accessed.

+

Also, the check of the vacm config file was invalid with + regard to the mask value. It was assumed to be a proper oid, which + is not strictly the case (see bitlist above).

+

Own Id: OTP-11177

+

Stefan Zegenhagen

+
+ +
+ +
+ +
+ Incompatibilities +

-

+ + +
+ +
+ +
SNMP Development Toolkit 4.24

Version 4.24 supports code replacement in runtime from/to diff --git a/lib/snmp/doc/src/snmp_agent_config_files.xml b/lib/snmp/doc/src/snmp_agent_config_files.xml index bd5c537522..866b00b77b 100644 --- a/lib/snmp/doc/src/snmp_agent_config_files.xml +++ b/lib/snmp/doc/src/snmp_agent_config_files.xml @@ -4,7 +4,7 @@

- 19972011 + 19972013 Ericsson AB. All Rights Reserved. @@ -32,13 +32,15 @@ snmp_agent_config_files.xml

All configuration data must be included in configuration files - that are located in the configuration directory. The name of this - directory is given in the config_dir configuration - parameter. These files are read at start-up, and are used to - initialize the SNMPv2-MIB or STANDARD-MIB, SNMP-FRAMEWORK-MIB, - SNMP-MPD-MIB, SNMP-VIEW-BASED-ACM-MIB, SNMP-COMMUNITY-MIB, - SNMP-USER-BASED-SM-MIB, SNMP-TARGET-MIB and SNMP-NOTIFICATION-MIB - (refer to the Management of the Agent for a description of the MIBs).

+ that are located in the configuration directory. The name of this + directory is given in the config_dir configuration + parameter. These files are read at start-up, and are used to + initialize the SNMPv2-MIB or STANDARD-MIB, SNMP-FRAMEWORK-MIB, + SNMP-MPD-MIB, SNMP-VIEW-BASED-ACM-MIB, SNMP-COMMUNITY-MIB, + SNMP-USER-BASED-SM-MIB, SNMP-TARGET-MIB and SNMP-NOTIFICATION-MIB + (refer to the + Management of the Agent + for a description of the MIBs).

The files are:

@@ -79,35 +81,35 @@

The directory where the configuration files are found is given as - a parameter to the agent.

+ a parameter to the agent.

The entry format in all files are Erlang terms, separated by a - '.' and a newline. In the following sections, the - formats of these terms are described. Comments may be specified as - ordinary Erlang comments.

+ '.' and a newline. In the following sections, the + formats of these terms are described. Comments may be specified as + ordinary Erlang comments.

Syntax errors in these files are discovered and reported with the - function config_err/2 of the error report module at start-up.

- + function config_err/2 of the error report module at start-up.

+ + +
- Agent Information

The agent information should be stored in a file called - agent.conf. -

-

Each entry is a tuple of size two: -

+ agent.conf.

+

Each entry is a tuple of size two:

{AgentVariable, Value}.

- AgentVariable is one of the variables is - SNMP-FRAMEWORK-MIB or one of the internal variables - intAgentUDPPort, which defines which UDP port the agent - listens to, or intAgentIpAddress, which defines the IP - address of the agent. + +

AgentVariable is one of the variables is + SNMP-FRAMEWORK-MIB or one of the internal variables + intAgentUDPPort, which defines which UDP port the agent + listens to, or intAgentIpAddress, which defines the IP + address of the agent.

- Value is the value for the variable. + +

Value is the value for the variable.

-

The following example shows a agent.conf file: -

+

The following example shows a agent.conf file:

 {intAgentUDPPort, 4000}.
 {intAgentIpAddress,[141,213,11,24]}.
@@ -115,49 +117,47 @@
 {snmpEngineMaxPacketSize, 484}.
     

The value of snmpEngineID is a string, which for a - deployed agent should have a very specific structure. See - RFC 2271/2571 for details. -

+ deployed agent should have a very specific structure. See + RFC 2271/2571 for details.

+ +
- Contexts

The context information should be stored in a file called - context.conf. The default context "" - need not be present. -

+ context.conf. The default context "" + need not be present.

Each row defines a context in the agent. This information is - used in the table vacmContextTable in the - SNMP-VIEW-BASED-ACM-MIB. -

-

Each entry is a term: -

+ used in the table vacmContextTable in the + SNMP-VIEW-BASED-ACM-MIB.

+

Each entry is a term:

ContextName.

- ContextName is a string. + +

ContextName is a string.

+ +
- System Information

The system information should be stored in a file called - standard.conf. -

-

Each entry is a tuple of size two: -

+ standard.conf.

+

Each entry is a tuple of size two:

{SystemVariable, Value}.

- SystemVariable is one of the variables in the - system group, or snmpEnableAuthenTraps. + +

SystemVariable is one of the variables in the + system group, or snmpEnableAuthenTraps.

- Value is the value for the variable. + +

Value is the value for the variable.

-

The following example shows a valid standard.conf file: -

+

The following example shows a valid standard.conf file:

 {sysDescr, "Erlang SNMP agent"}.
 {sysObjectID, [1,2,3]}.
@@ -167,59 +167,60 @@
 {snmpEnableAuthenTraps, enabled}.
     

A value must be provided for all variables, which lack default - values in the MIB. -

+ values in the MIB.

+ +
- Communities

The community information should be stored in a file called - community.conf. It must be present if the agent is - configured for SNMPv1 or SNMPv2c. -

+ community.conf. It must be present if the agent is + configured for SNMPv1 or SNMPv2c.

An SNMP community is a relationship between an SNMP agent and a set of SNMP managers that defines authentication, access control and proxy characteristics.

The corresponding table is snmpCommunityTable in the - SNMP-COMMUNITY-MIB.

+ SNMP-COMMUNITY-MIB.

Each entry is a term:

-

{CommunityIndex, CommunityName, SecurityName, ContextName, TransportTag}.

+

{CommunityIndex, CommunityName, SecurityName, ContextName, TransportTag}.

- CommunityIndex is a non-empty string. + +

CommunityIndex is a non-empty string.

- CommunityName is a string. + +

CommunityName is a string.

- SecurityName is a string. + +

SecurityName is a string.

- ContextName is a string. + +

ContextName is a string.

- TransportTag is a string. + +

TransportTag is a string.

+ +
- MIB Views for VACM

The information about MIB Views for VACM should be stored in a - file called - vacm.conf. -

+ file called vacm.conf.

The corresponding tables are vacmSecurityToGroupTable, - vacmAccessTable and vacmViewTreeFamilyTable in the - SNMP-VIEW-BASED-ACM-MIB. -

+ vacmAccessTable and vacmViewTreeFamilyTable in the + SNMP-VIEW-BASED-ACM-MIB.

Each entry is one of the terms, one entry corresponds to one - row in one of the tables. -

+ row in one of the tables.

{vacmSecurityToGroup, SecModel, SecName, GroupName}.

{vacmAccess, GroupName, Prefix, SecModel, SecLevel, Match, ReadView, WriteView, NotifyView}.

{vacmViewTreeFamily, ViewIndex, ViewSubtree, ViewStatus, ViewMask}.

SecModel is any, v1, v2c, or - usm.

+ usm.

SecName is a string.

@@ -232,7 +233,7 @@

SecLevel is noAuthNoPriv, authNoPriv, - or authPriv

+ or authPriv

Match is prefix or exact.

@@ -244,8 +245,7 @@

WriteView is a string.

-

NotifyView is a string. -

+

NotifyView is a string.

ViewIndex is an integer.

@@ -258,33 +258,29 @@

ViewMask is either null or a list of ones and - zeros. Ones nominate that an exact match is used for this - sub-identifier. Zeros are wild-cards which match any - sub-identifier. If the mask is shorter than the sub-tree, the - tail is regarded as all ones. null is shorthand for a - mask with all ones.

+ zeros. Ones nominate that an exact match is used for this + sub-identifier. Zeros are wild-cards which match any + sub-identifier. If the mask is shorter than the sub-tree, the + tail is regarded as all ones. null is shorthand for a + mask with all ones.

+ +
- Security data for USM

The information about Security data for USM should be stored in a - file called - usm.conf, which must be present if the agent is configured - for SNMPv3. -

+ file called usm.conf, which must be present if the agent is + configured for SNMPv3.

The corresponding table is usmUserTable in the - SNMP-USER-BASED-SM-MIB. -

-

Each entry is a term: -

+ SNMP-USER-BASED-SM-MIB.

+

Each entry is a term:

{EngineID, UserName, SecName, Clone, AuthP, AuthKeyC, OwnAuthKeyC, PrivP, PrivKeyC, OwnPrivKeyC, Public, AuthKey, PrivKey}.

-

EngineID is a string. -

+

EngineID is a string.

UserName is a string.

@@ -297,7 +293,7 @@

AuthP is a usmNoAuthProtocol, - usmHMACMD5AuthProtocol, or usmHMACSHAAuthProtocol.

+ usmHMACMD5AuthProtocol, or usmHMACSHAAuthProtocol.

AuthKeyC is a string.

@@ -307,7 +303,7 @@

PrivP is a usmNoPrivProtocol, - usmDESPrivProtocol or usmAesCfb128Protocol.

+ usmDESPrivProtocol or usmAesCfb128Protocol.

PrivKeyC is a string.

@@ -319,66 +315,59 @@

Public is a string.

-

AuthKey is a list (of integer). This is the User's secret - localized authentication key. It is not visible in the MIB. The length - of this key needs to be 16 if usmHMACMD5AuthProtocol is used, and - 20 if usmHMACSHAAuthProtocol is used.

+

AuthKey is a list (of integer). This is the User's secret + localized authentication key. It is not visible in the MIB. The length + of this key needs to be 16 if usmHMACMD5AuthProtocol is used, + and 20 if usmHMACSHAAuthProtocol is used.

PrivKey is a list (of integer). This is the User's secret - localized encryption key. It is not visible in the MIB. The length - of this key needs to be 16 if usmDESPrivProtocol or - usmAesCfb128Protocol is used. -

+ localized encryption key. It is not visible in the MIB. The length + of this key needs to be 16 if usmDESPrivProtocol or + usmAesCfb128Protocol is used.

+ +
- Notify Definitions

The information about Notify Definitions should be stored in a - file called - notify.conf. -

+ file called notify.conf.

The corresponding table is snmpNotifyTable in the - SNMP-NOTIFICATION-MIB. -

-

Each entry is a term: -

+ SNMP-NOTIFICATION-MIB.

+

Each entry is a term:

{NotifyName, Tag, Type}.

-

NotifyName is a unique non-empty string. -

+

NotifyName is a unique non-empty string.

-

Tag is a string. -

+

Tag is a string.

-

Type is trap or inform. -

+

Type is trap or inform.

+ +
- Target Address Definitions

The information about Target Address Definitions should be - stored in a file called target_addr.conf.

+ stored in a file called target_addr.conf.

The corresponding tables are snmpTargetAddrTable in the - SNMP-TARGET-MIB and snmpTargetAddrExtTable in the - SNMP-COMMUNITY-MIB.

+ SNMP-TARGET-MIB and snmpTargetAddrExtTable in the + SNMP-COMMUNITY-MIB.

Each entry is a term:

{TargetName, Ip, Udp, Timeout, RetryCount, TagList, ParamsName, EngineId}.

or

{TargetName, Ip, Udp, Timeout, RetryCount, TagList, ParamsName, EngineId, TMask, MaxMessageSize}.

or

-{TargetName, Domain, Ip, Udp, Timeout, RetryCount, TagList, ParamsName, EngineId, TMask, MaxMessageSize}.

+{TargetName, Domain, Ip, Udp, Timeout, RetryCount, TagList, ParamsName, EngineId, TMask, MaxMessageSize}.

-

TargetName is a unique non-empty string. -

+

TargetName is a unique non-empty string.

Domain is one of the atoms: @@ -414,40 +403,37 @@

Note that if EngineId has the value discovery, - the agent cannot send - inform messages to that manager until it has performed the - discovery process with that manager.

+ the agent cannot send + inform messages to that manager until it has performed the + discovery process with that manager.

+ +
- Target Parameters Definitions

The information about Target Parameters Definitions should be - stored in a file called target_params.conf.

+ stored in a file called target_params.conf.

The corresponding table is snmpTargetParamsTable in the - SNMP-TARGET-MIB.

+ SNMP-TARGET-MIB.

Each entry is a term:

{ParamsName, MPModel, SecurityModel, SecurityName, SecurityLevel}.

-

ParamsName is a unique non-empty string. -

+

ParamsName is a unique non-empty string.

MPModel is v1, v2c or v3

-

SecurityModel is v1, v2c, or usm. -

+

SecurityModel is v1, v2c, or usm.

-

SecurityName is a string. -

+

SecurityName is a string.

SecurityLevel is noAuthNoPriv, authNoPriv - or authPriv. -

+ or authPriv.

diff --git a/lib/snmp/src/agent/snmp_view_based_acm_mib.erl b/lib/snmp/src/agent/snmp_view_based_acm_mib.erl index 0acef780f8..c0177b1cea 100644 --- a/lib/snmp/src/agent/snmp_view_based_acm_mib.erl +++ b/lib/snmp/src/agent/snmp_view_based_acm_mib.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1999-2012. All Rights Reserved. +%% Copyright Ericsson AB 1999-2013. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -49,6 +49,14 @@ -endif. +-type internal_view_mask() :: null | [internal_view_mask_element()]. +-type internal_view_mask_element() :: 0 | 1. + +-type external_view_mask() :: octet_string(). % At most length of 16 octet +-type octet_string() :: [octet()]. +-type octet() :: byte(). + + %%----------------------------------------------------------------- %% Func: configure/1 %% Args: Dir is the directory where the configuration files are found. @@ -160,14 +168,7 @@ check_vacm({vacmViewTreeFamily, ViewName, Tree, Type, Mask}) -> {ok, TypeVal} = snmp_conf:check_atom(Type, [{included, ?view_included}, {excluded, ?view_excluded}]), - MaskVal = - case (catch snmp_conf:check_atom(Mask, [{null, []}])) of - {error, _} -> - snmp_conf:check_oid(Mask), - Mask; - {ok, X} -> - X - end, + {ok, MaskVal} = snmp_conf:check_imask(Mask), Vacm = {ViewName, Tree, MaskVal, TypeVal, ?'StorageType_nonVolatile', ?'RowStatus_active'}, {ok, {vacmViewTreeFamily, Vacm}}; @@ -194,8 +195,8 @@ init_tabs(Sec2Group, Access, View) -> ok. init_sec2group_table([Row | T]) -> -%% ?vtrace("init security-to-group table: " -%% "~n Row: ~p",[Row]), + %% ?vtrace("init security-to-group table: " + %% "~n Row: ~p",[Row]), Key1 = element(1, Row), Key2 = element(2, Row), Key = [Key1, length(Key2) | Key2], @@ -953,13 +954,23 @@ verify_vacmViewTreeFamilyTable_col(?vacmViewTreeFamilySubtree, Tree) -> wrongValue(?vacmViewTreeFamilySubtree) end; verify_vacmViewTreeFamilyTable_col(?vacmViewTreeFamilyMask, Mask) -> + %% Mask here is in the "external" format. That is, according + %% to the MIB, which means that its an OCTET STRING of max 16 + %% octets. + %% We however store the mask as a list of 1's (exact) and + %% 0's (wildcard), which means we have to convert the mask. case Mask of - null -> []; - [] -> []; + %% The Mask can only have this value if the vacmViewTreeFamilyTable + %% is called locally! + null -> + []; + [] -> + []; _ -> - case (catch check_mask(Mask)) of - ok -> - mask2oid(Mask); + %% Check and convert to our internal format + case check_mask(Mask) of + {ok, IMask} -> + IMask; _ -> wrongValue(?vacmViewTreeFamilyMask) end @@ -975,53 +986,60 @@ verify_vacmViewTreeFamilyTable_col(?vacmViewTreeFamilyType, Type) -> end; verify_vacmViewTreeFamilyTable_col(_, Val) -> Val. + +check_mask(Mask) when is_list(Mask) andalso (length(Mask) =< 16) -> + try + begin + {ok, emask2imask(Mask)} + end + catch + throw:{error, _} -> + {error, {bad_mask, Mask}}; + T:E -> + {error, {bad_mask, Mask, T, E}} + end; +check_mask(BadMask) -> + {error, {bad_mask, BadMask}}. + +-spec emask2imask(EMask :: external_view_mask()) -> + IMask :: internal_view_mask(). + +%% Convert an External Mask (OCTET STRING) to Internal Mask (list of 0 or 1) +emask2imask(EMask) -> + lists:flatten([octet2bits(Octet) || Octet <- EMask]). + +octet2bits(Octet) + when is_integer(Octet) andalso (Octet >= 16#00) andalso (16#FF >= Octet) -> + <> = <>, + [A, B, C, D, E, F, G, H]; +octet2bits(BadOctet) -> + throw({error, {bad_octet, BadOctet}}). + +-spec imask2emask(IMask :: internal_view_mask()) -> + EMask :: external_view_mask(). + +%% Convert an Internal Mask (list of 0 or 1) to External Mask (OCTET STRING) +imask2emask(IMask) -> + imask2emask(IMask, []). + +imask2emask([], EMask) -> + lists:reverse(EMask); +imask2emask(IMask, EMask) -> + %% Make sure we have atleast 8 bits + %% (maybe extend with 1's) + IMask2 = + case length(IMask) of + Small when Small < 8 -> + IMask ++ lists:duplicate(8-Small, 1); + _ -> + IMask + end, + %% Extract 8 bits + [A, B, C, D, E, F, G, H | IMaskRest] = IMask2, + <> = <>, + imask2emask(IMaskRest, [Octet | EMask]). -check_mask([]) -> - ok; -check_mask([Head | Tail]) when is_integer(Head) -> -% we can cause exception here because the caller catches - if - Head > -1 andalso Head < 256 -> - check_mask(Tail) - end. - -% internally (for easier computations), the mask is stored -% as OID and not as bit-field. Therefore, we have to convert -% the bitstring to a list of integers before storing it. -mask2oid(Mask) -> - Func = fun(Byte) -> - % what's a nice syntax for extracting bits - % from a byte??? - <> = <>, - [A, B, C, D, E, F, G, H] - end, - lists:flatten(lists:map(Func, Mask)). - -oid2mask(Oid) -> - % convert all suboids to either 1 or 0 for sure - Func = fun - (0) -> 0; - (_) -> 1 - end, - oid2mask(lists:map(Func, Oid), []). - -oid2mask([], Mask) -> - % end-of-list, return bitstring - lists:reverse(Mask); -oid2mask(Oid, Mask) -> - % check whether we've got at least 8 sub-identifiers. if not, - % extend with 1's until there are enough to fill a byte - NOid = case length(Oid) of - Small when Small < 8 -> - Oid ++ lists:duplicate(8-Small, 1); - _ -> - Oid - end, - % extract sufficient suboids for 8 bits - [A, B, C, D, E, F, G, H | Tail] = NOid, - <> = <>, - oid2mask(Tail, [Byte | Mask]). table_next(Name, RestOid) -> @@ -1061,42 +1079,40 @@ stc(vacmSecurityToGroupTable) -> ?vacmSecurityToGroupStorageType; stc(vacmViewTreeFamilyTable) -> ?vacmViewTreeFamilyStorageType. next(Name, RowIndex, Cols) -> - Ans = snmp_generic:handle_table_next(db(Name), RowIndex, Cols, - fa(Name), foi(Name), noc(Name)), - patch_next(Name, Ans). + Result = snmp_generic:handle_table_next(db(Name), RowIndex, Cols, + fa(Name), foi(Name), noc(Name)), + externalize_next(Name, Result). get(Name, RowIndex, Cols) -> - Ans = snmp_generic:handle_table_get(db(Name), RowIndex, Cols, foi(Name)), - patch(Name, Cols, Ans). - - -patch(Name, Cols, Ans) when is_list(Ans) -> - % function to patch returned values - Func = fun - ({Col, {value, Val}}) -> {value, do_patch(Name, Col, Val)}; - ({_, Other}) -> Other - end, - % merge column numbers and return values. there must be as much - % return values as there are columns requested - Tmp = lists:zip(Cols, Ans), - % and patch all values - lists:map(Func, Tmp); -patch(_, _, Ans) -> - Ans. - -patch_next(Name, Ans) when is_list(Ans) -> - Func = fun - ({[C | _] = Idx, Val}) -> {Idx, do_patch(Name, C, Val)}; - (Other) -> Other - end, - lists:map(Func, Ans); -patch_next(_, Ans) -> - Ans. - -do_patch(vacmViewTreeFamilyTable, ?vacmViewTreeFamilyMask, Val) -> - oid2mask(Val); -do_patch(_, _, Val) -> - Val. + Result = snmp_generic:handle_table_get(db(Name), RowIndex, Cols, + foi(Name)), + externalize_get(Name, Cols, Result). + + +externalize_next(Name, Result) when is_list(Result) -> + F = fun({[Col | _] = Idx, Val}) -> {Idx, externalize(Name, Col, Val)}; + (Other) -> Other + end, + [F(R) || R <- Result]; +externalize_next(_, Result) -> + Result. + + +externalize_get(Name, Cols, Result) when is_list(Result) -> + %% Patch returned values + F = fun({Col, {value, Val}}) -> {value, externalize(Name, Col, Val)}; + ({_, Other}) -> Other + end, + %% Merge column numbers and return values. there must be as much + %% return values as there are columns requested. And then patch all values + [F(R) || R <- lists:zip(Cols, Result)]; +externalize_get(_, _, Result) -> + Result. + +externalize(vacmViewTreeFamilyTable, ?vacmViewTreeFamilyMask, Val) -> + imask2emask(Val); +externalize(_, _, Val) -> + Val. wrongValue(V) -> throw({wrongValue, V}). diff --git a/lib/snmp/src/app/snmp.appup.src b/lib/snmp/src/app/snmp.appup.src index 7ffa4a725d..106fed749d 100644 --- a/lib/snmp/src/app/snmp.appup.src +++ b/lib/snmp/src/app/snmp.appup.src @@ -22,6 +22,12 @@ %% ----- U p g r a d e ------------------------------------------------------- [ + {"4.24", + [ + {load_module, snmp_conf, soft_purge, soft_purge, []}, + {load_module, snmp_view_based_acm_mib, soft_purge, soft_purge, [snmp_conf]} + ] + }, {"4.23.1", [{restart_application, snmp}]}, {"4.23", [{restart_application, snmp}]} ], @@ -29,6 +35,12 @@ %% ------D o w n g r a d e --------------------------------------------------- [ + {"4.24", + [ + {load_module, snmp_conf, soft_purge, soft_purge, []}, + {load_module, snmp_view_based_acm_mib, soft_purge, soft_purge, [snmp_conf]} + ] + }, {"4.23.1", [{restart_application, snmp}]}, {"4.23", [{restart_application, snmp}]} ] diff --git a/lib/snmp/src/misc/snmp_conf.erl b/lib/snmp/src/misc/snmp_conf.erl index e1e7fab57b..46625989d5 100644 --- a/lib/snmp/src/misc/snmp_conf.erl +++ b/lib/snmp/src/misc/snmp_conf.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2012. All Rights Reserved. +%% Copyright Ericsson AB 1996-2013. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -50,6 +50,7 @@ check_packet_size/1, check_oid/1, + check_imask/1, check_emask/1, check_mp_model/1, check_sec_model/1, check_sec_model/2, check_sec_model/3, @@ -488,6 +489,7 @@ do_check_timer(WaitFor, Factor, Incr, Retry) -> check_integer(Retry, {gte, 0}), ok. + %% --------- all_domains() -> @@ -616,6 +618,37 @@ check_oid(X) -> error({invalid_object_identifier, X}). +%% --------- + +%% Check a (view) mask in the internal form (all 0 and 1): +check_imask(null) -> + {ok, []}; +check_imask(IMask) when is_list(IMask) -> + do_check_imask(IMask), + {ok, IMask}. + +do_check_imask([0|IMask]) -> + do_check_imask(IMask); +do_check_imask([1|IMask]) -> + do_check_imask(IMask); +do_check_imask([X|_]) -> + error({invalid_internal_mask_element, X}). + + +%% Check a (view) mask in the external form (according to MIB, +%% an OCTET STRING of at most length 16). +check_emask(EMask) when is_list(EMask) andalso (length(EMask) =< 16) -> + do_check_emask(EMask). + +do_check_emask([]) -> + ok; +do_check_emask([X|EMask]) + when is_integer(X) andalso (X >= 16#00) andalso (X =< 16#FF) -> + do_check_emask(EMask); +do_check_emask([X|_]) -> + error({invalid_external_mask_element, X}). + + %% --------- all_integer([H|T]) when is_integer(H) -> all_integer(T); diff --git a/lib/snmp/vsn.mk b/lib/snmp/vsn.mk index 0e48e7ea56..e987649e11 100644 --- a/lib/snmp/vsn.mk +++ b/lib/snmp/vsn.mk @@ -18,6 +18,6 @@ # %CopyrightEnd% APPLICATION = snmp -SNMP_VSN = 4.24 +SNMP_VSN = 4.24.1 PRE_VSN = APP_VSN = "$(APPLICATION)-$(SNMP_VSN)$(PRE_VSN)" -- cgit v1.2.3