1 /*_############################################################################
6 _## -----------------------------------------------
7 _## Copyright (c) 2001-2010 Jochen Katz, Frank Fock
9 _## This software is based on SNMP++2.6 from Hewlett Packard:
11 _## Copyright (c) 1996
12 _## Hewlett-Packard Company
14 _## ATTENTION: USE OF THIS SOFTWARE IS SUBJECT TO THE FOLLOWING TERMS.
15 _## Permission to use, copy, modify, distribute and/or sell this software
16 _## and/or its documentation is hereby granted without fee. User agrees
17 _## to display the above copyright notice and this license notice in all
18 _## copies of the software and any documentation of the software. User
19 _## agrees to assume all liability for the use of the software;
20 _## Hewlett-Packard and Jochen Katz make no representations about the
21 _## suitability of this software for any purpose. It is provided
22 _## "AS-IS" without warranty of any kind, either express or implied. User
23 _## hereby grants a royalty-free license to any and all derivatives based
24 _## upon this software code base.
26 _## Stuttgart, Germany, Thu Sep 2 00:07:47 CEST 2010
28 _##########################################################################*/
30 // $Id: mp_v3.h 320 2007-11-08 22:05:23Z katz $
35 #include "snmp_pp/config_snmp_pp.h"
39 #include "snmp_pp/reentrant.h"
40 #include "snmp_pp/target.h"
42 #ifdef SNMP_PP_NAMESPACE
49 #define MAX_HOST_NAME_LENGTH 128
51 #define oidMPDGroup "1.3.6.1.6.3.11.2.1"
52 #define oidSnmpUnknownSecurityModels "1.3.6.1.6.3.11.2.1.1.0"
53 #define oidSnmpInvalidMsgs "1.3.6.1.6.3.11.2.1.2.0"
54 #define oidSnmpUnknownPDUHandlers "1.3.6.1.6.3.11.2.1.3.0"
56 /** @name Error codes of the v3MP */
58 #define SNMPv3_MP_ERROR -1400
59 #define SNMPv3_MP_OK -1401
60 #define SNMPv3_MP_UNSUPPORTED_SECURITY_MODEL -1402
61 #define SNMPv3_MP_NOT_IN_TIME_WINDOW -1403
62 #define SNMPv3_MP_DOUBLED_MESSAGE -1404
63 #define SNMPv3_MP_INVALID_MESSAGE -1405
64 #define SNMPv3_MP_INVALID_ENGINEID -1406
65 #define SNMPv3_MP_NOT_INITIALIZED -1407
66 #define SNMPv3_MP_PARSE_ERROR -1408
67 #define SNMPv3_MP_UNKNOWN_MSGID -1409
68 #define SNMPv3_MP_MATCH_ERROR -1410
69 #define SNMPv3_MP_COMMUNITY_ERROR -1411
70 #define SNMPv3_MP_WRONG_USER_NAME -1412
71 #define SNMPv3_MP_BUILD_ERROR -1413
72 #define SNMPv3_MP_USM_ERROR -1414
73 #define SNMPv3_MP_UNKNOWN_PDU_HANDLERS -1415
74 #define SNMPv3_MP_UNAVAILABLE_CONTEXT -1416
75 #define SNMPv3_MP_UNKNOWN_CONTEXT -1417
76 #define SNMPv3_MP_REPORT_SENT -1418
79 /** @name Statistics on error codes. */
81 #define SNMPv3_MP_MAX_ERROR SNMPv3_MP_ERROR
82 #define SNMPv3_MP_MIN_ERROR SNMPv3_MP_REPORT_SENT
83 #define SNMPv3_MP_ERRORCOUNT SNMPv3_MP_MAX_ERROR - SNMPv3_MP_MIN_ERROR
90 * The SNMPv3 Message Processing Model (v3MP).
92 * If SNMPv3 is used, the application needs to create _one_ object of
93 * this class. This object will automatically create an object of the
94 * USM class. A pointer to this object is returned from the get_usm()
95 * method. See the USM documentation for a description on how to create
98 * The only thing that may be configured after creation of the v3MP is
99 * the engine id table of the v3MP. Entries for other SNMP entities
100 * can be added through add_to_engine_id_table(). It is only required
101 * to add entries to this table if you want to disable engine id
102 * discovery and/or you don't want the delay caused by the automatic
103 * engine id discovery of SNMPv3.
107 friend class SnmpMessage;
108 friend class CSNMPMessageQueue;
111 * Initialize the v3MP.
113 * Set the engineID of this SNMP entity and the Snmp object used to
114 * send reports. This function creates a new USM object that can
115 * be configured after getting a pointer to it through get_usm().
117 * The user is responsible to save and restore and increment the
118 * snmpEngineBoots counter (The functions getBootCounter() and
119 * saveBootCounter() can be used to do this.).
121 * @param engine_id - The locale engine id
122 * @param engine_boots - The new value for the snmpEngineBoots counter
123 * @param construct_status - OUT: SNMPv3_MP_OK or SNMPv3_MP_ERROR
126 v3MP(const OctetStr& engine_id,
127 unsigned int engine_boots, int &construct_status);
130 * Get the engine id of this SNMP entity.
132 * @param id - OUT: The engineID of this SNMP entity
134 * @return - SNMPv3_MP_OK or SNMPv3_MP_ERROR
136 void get_local_engine_id(OctetStr &id) { id = own_engine_id_oct; };
139 * Get the engine id of this SNMP entity as a OctetStr reference.
141 * @return Local engine id.
143 const OctetStr& get_local_engine_id() const
144 { return own_engine_id_oct; };
147 * Get a pointer to the USM object that is used by the v3MP.
149 USM *get_usm() { return usm; };
152 * Free all allocated ressources of the v3MP and leave it in an
153 * uninitialized state. After a call to this function, you can use
154 * mpInit() to reinitialize the v3MP.
160 * Add an entry to the engine id table.
162 * In this table all known engine ids are stored. If the discovery
163 * mode of the USM is enabled, snmp++ will add entries to this table
164 * whenever a new engine id is dicovered.
166 * @param engine_id - The engine id
167 * @param host - The numerical IP address
168 * @param port - The port
170 * @return - SNMPv3_MP_ERROR, SNMPv3_MP_OK
172 int add_to_engine_id_table(const OctetStr &engine_id,
173 const OctetStr &host, int port)
174 { return engine_id_table.add_entry(engine_id, host, port); };
177 * Remove an entry from the engine id table.
179 * @param host - The numerical IP address
180 * @param port - The port
182 * @return - SNMPv3_MP_ERROR, SNMPv3_MP_OK
184 int remove_from_engine_id_table(const OctetStr &host, int port)
185 { return engine_id_table.delete_entry(host, port); };
188 * Remove an entry from the engine id table.
190 * @param engine_id - The engine id
192 * @return - SNMPv3_MP_ERROR, SNMPv3_MP_OK
194 int remove_from_engine_id_table(const OctetStr &engine_id)
195 { return engine_id_table.delete_entry(engine_id); };
198 * Get the engine id of the SNMP entity at the given host/port.
200 * @param engine_id - OUT: The engine id
201 * @param hostport - The numerical IP address and port
202 * (syntax: a.b.c.d/port)
204 * @return - SNMPv3_MP_NOT_INITIALIZED, SNMPv3_MP_ERROR,
207 int get_from_engine_id_table(OctetStr &engine_id,
208 const OctetStr &hostport) const
209 { return engine_id_table.get_entry(engine_id, hostport); };
212 * Get the engineID of the SNMP entity at the given host/port.
214 * @param engineID - OUT: The engineID
215 * @param host - The numerical IP address
216 * @param port - The port
218 * @return - SNMPv3_MP_NOT_INITIALIZED, SNMPv3_MP_ERROR,
221 int get_from_engine_id_table(OctetStr &engineID,
222 const OctetStr &host, int port) const
223 { return engine_id_table.get_entry(engineID, host, port); };
226 * Remove all entries from the engine id table.
228 * @return - SNMPv3_MP_NOT_INITIALIZED, SNMPv3_MP_ERROR,
231 int reset_engine_id_table()
232 { return engine_id_table.reset(); };
235 * Remove all occurences of this engine id from v3MP and USM.
237 * @param engine_id - The engine id to remove
239 * @return - SNMPv3_MP_NOT_INITIALIZED, SNMPv3_MP_ERROR,
242 int remove_engine_id(const OctetStr &engine_id);
244 // ----------[ Access to status counters for agent++ ]--------------
247 * Get the value of the status counter snmpUnknownSecurityModels.
249 * @return - The status counter
251 unsigned long get_stats_unknown_security_models() const
252 { return snmpUnknownSecurityModels; };
255 * Get the value of the status counter snmpInvalidMsgs.
257 * @return - The status counter
259 unsigned long get_stats_invalid_msgs() const
260 { return snmpInvalidMsgs; };
263 * Get the value of the status counter snmpUnknownPDUHandlers.
265 * @return - The status counter
267 unsigned long get_stats_unknown_pdu_handlers() const
268 { return snmpUnknownPDUHandlers; };
271 * Increment the value of the status counter snmpUnknownSecurityModels.
273 void inc_stats_unknown_security_models()
274 { snmpUnknownSecurityModels++; };
277 * Increment the value of the status counter snmpInvalidMsgs.
279 void inc_stats_invalid_msgs() { snmpInvalidMsgs++; };
282 * Increment the value of the status counter snmpUnknownPDUHandlers.
284 void inc_stats_unknown_pdu_handlers() { snmpUnknownPDUHandlers++; };
286 // temporary pointer will be removed...
292 * Parse the given buffer as a SNMPv3-Message.
294 * @param snmp_session - IN: The session used to receive the msg
295 * @param pdu - OUT: Parsed values are put into this struct
296 * @param inBuf - The buffer to parse
297 * @param inBufLength - The length of the buffer
298 * @param securityEngineID - OUT: The parsed securityEngineID
299 * @param securityName - OUT: The parsed securityName
300 * @param contextEngineID - OUT: The parsed contextEngineID
301 * @param contextName - OUT: The parsed contextName
302 * @param securityLevel - OUT: The parsed security level
303 * @param msgSecurityModel - OUT: The security model used
304 * @param spp_version - OUT: SNMP version (SNMPv3)
305 * @param from_address - Where the message came from (used to send
306 * a report if neccessary)
308 * @return - SNMPv3_MP_OK or any error listed in snmperr.h
310 int snmp_parse(Snmp *snmp_session,
311 struct snmp_pdu *pdu,
312 unsigned char *inBuf,
314 OctetStr &securityEngineID,
315 OctetStr &securityName,
316 OctetStr &contextEngineID,
317 OctetStr &contextName,
319 long &msgSecurityModel,
320 snmp_version &spp_version,
321 UdpAddress from_address);
324 * Tests if the given buffer contains a SNMPv3-Message. The buffer is
325 * only parsed to extract the version of the message, no other checks
328 * @param buffer - The message
329 * @param length - The length of the message
331 * @return - TRUE if the version could be extracted and it
332 * is a SNMPv3 message. On any error: FALSE.
335 static bool is_v3_msg( unsigned char *buffer, int length);
338 * Do the complete process of encoding the given values into the buffer
339 * ready to send to the target.
341 * @param pdu - The pdu structure
342 * @param packet - The buffer to store the serialized message
343 * @param out_length - IN: Length of the buffer,
344 * OUT: Length of the message
345 * @param securityEngineID - The securityEngineID
346 * @param securityNameIn - The securityName
347 * @param securityModel - Use this security model
348 * @param securityLevel - Use this security level
349 * @param contextEngineID - The contextEngineID
350 * @param contextName - The contextName
352 * @return - SNMPv3_MP_OK or any error listed in snmperr.h
354 int snmp_build(struct snmp_pdu *pdu,
355 unsigned char *packet,
356 int *out_length, // maximum Bytes in packet
357 const OctetStr &securityEngineID,
358 const OctetStr &securityNameIn,
359 int securityModel, int securityLevel,
360 const OctetStr &contextEngineID,
361 const OctetStr &contextName);
364 * Delete the entry with the given request id from the cache.
365 * This function is used in eventlist.cpp when a request
368 * @param requestID - The request id.
369 * @param local_request - Does the request id belong to a local or to
372 void delete_from_cache(unsigned long requestID,
373 const bool local_request = true)
374 { cache.delete_entry(requestID, local_request); };
379 * Delete the entry with the given request id from the cache.
380 * This function is used in agent++ RequestList.
382 * @param requestID - The request id.
383 * @param messageID - The message id.
384 * @param local_request - Does the request id belong to a local or to
387 void delete_from_cache(unsigned long requestID,
388 unsigned long messageID,
389 const bool local_request)
390 { cache.delete_entry(requestID, messageID, local_request); };
395 * Send a report message.
397 * @param scopedPDU - The scopedPDU as received. If the pdu is not
398 * encrypted, the request id is extracted
399 * @param scopedPDULength - The lkength of the scopedPDU
400 * @param pdu - The pdu structure.
401 * @param errorCode - The code of the error that occured.
402 * @param sLevel - Send the report with this security level.
403 * @param sModel - Use this security model.
404 * @param sName - Use this security name
405 * @param destination - Send the report to this address.
406 * @param snmp_session - Snmp session to use for sending a report
408 * @return - SNMPv3_MP_ERROR, SNMPv3_MP_OK
410 int send_report(unsigned char* scopedPDU, int scopedPDULength,
411 struct snmp_pdu *pdu, int errorCode, int sLevel,
412 int sModel, OctetStr &sName,
413 UdpAddress &destination, Snmp *snmp_session);
417 // =====================[ member classes ]==============================
420 * The engine id table is used to store known engine ids with
421 * corresponding hostadress and port.
423 class DLLOPT EngineIdTable
427 EngineIdTable(int initial_size = 10);
431 * Add an entry to the table.
433 * @param engine_id - The engineID
434 * @param host - The numerical IP address
435 * @param port - The port
437 * @return - SNMPv3_MP_ERROR, SNMPv3_MP_OK
439 int add_entry(const OctetStr &engine_id,
440 const OctetStr &host, int port);
443 * Get the engine_id of the SNMP entity at the given host/port.
445 * @param engine_id - OUT: The engineID
446 * @param hostport - The numerical IP address and port
447 * (syntax: a.b.c.d/port)
449 * @return - SNMPv3_MP_NOT_INITIALIZED, SNMPv3_MP_ERROR,
452 int get_entry(OctetStr &engine_id, const OctetStr &hostport) const;
455 * Get the engineID of the SNMP entity at the given host/port.
457 * @param engine_id - OUT: The engineID
458 * @param host - The numerical IP address
459 * @param port - The port
461 * @return - SNMPv3_MP_NOT_INITIALIZED, SNMPv3_MP_ERROR,
464 int get_entry(OctetStr &engine_id, const OctetStr &host, int port) const;
467 * Remove all entries from the engine id table.
469 * @return - SNMPv3_MP_NOT_INITIALIZED, SNMPv3_MP_ERROR,
475 * Remove the given engine id from the table.
477 * @param engine_id - The engine id to remove
479 * @return - SNMPv3_MP_NOT_INITIALIZED, SNMPv3_MP_ERROR,
482 int delete_entry(const OctetStr &engine_id);
485 * Remove the entry for the given address/port from the table.
487 * @param host - Numeric IP address
488 * @param port - listen port of the snmp entity
490 * @return - SNMPv3_MP_NOT_INITIALIZED, SNMPv3_MP_ERROR,
493 int delete_entry(const OctetStr &host, int port);
496 int initialize_table(const int size);
505 struct Entry_T *table;
506 int max_entries; ///< the maximum number of entries
507 int entries; ///< the current amount of entries
508 SNMP_PP_MUTABLE SnmpSynchronized lock;
513 * Holds cache entries for currently processed requests.
524 unsigned long req_id;
525 OctetStr sec_engine_id;
529 OctetStr context_engine_id;
530 OctetStr context_name;
531 struct SecurityStateReference *sec_state_ref;
537 * Add an entry to the cache.
539 * @param msg_id - The message id of the message
540 * @param req_id - The request id of the message
541 * @param sec_engine_id - The authoritative engineID
542 * @param sec_model - The security model used for this message
543 * @param sec_name - The name of the user
544 * @param sec_level - The security level used for this message
545 * @param context_engine_id - The context_engine_id
546 * @param context_name - The context_name
547 * @param sec_state_ref - The reference of the USM
548 * @param error_code - The code of the error that occured while
549 * parsing the received message
551 * @return - SNMPv3_MP_OK, SNMPv3_MP_ERROR or SNMPv3_DOUBLED_MESSAGE
552 * (an entry with the given values is already in the cache)
554 int add_entry(int msg_id, unsigned long req_id,
555 const OctetStr &sec_engine_id,
557 const OctetStr &sec_name,
559 const OctetStr &context_engine_id,
560 const OctetStr &context_name,
561 struct SecurityStateReference *sec_state_ref,
562 int error_code, bool local_request);
564 * Search the cache for a message id, return the error code and
565 * the sec_state_ref and delete the entry from the cache.
567 * @param msg_id - Search for this message id
568 * @param error_code - OUT: The error code of the received message
569 * @param sec_state_ref - IN: Pointer to a pointer of the structure
570 * OUT: The structure as received by the USM when
571 * the message was parsed.
573 * @return - SNMPv3_MP_ERROR, SNMPv3_MP_OK
575 int get_entry(int msg_id, bool local_request, int *error_code,
576 struct SecurityStateReference **sec_state_ref);
579 * Delete the entry with the given request id from the cache.
580 * This function is used in eventlist.cpp when a request
583 * @param req_id - The request id.
585 void delete_entry(unsigned long req_id, bool local_request);
588 * Delete the entry with the given request and message id from the cache.
590 * @param req_id - The request id.
591 * @param msg_id - The message id.
593 void delete_entry(unsigned long req_id, int msg_id,
597 * Search the cache for a message id, return the whole entry and
598 * delete the entry from the cache.
600 * @param searchedID - Search for this message id
601 * @param res - IN: Pointer to an empy structure
602 * OUT: The filled structure
604 * @return - SNMPv3_MP_ERROR, SNMPv3_MP_OK
606 int get_entry(int searchedID, bool local_request,
607 struct Cache::Entry_T *res);
609 void delete_content(struct Cache::Entry_T &ce);
611 void set_usm(USM *usm_to_use) { usm = usm_to_use; };
615 SNMP_PP_MUTABLE SnmpSynchronized lock;
617 struct Entry_T *table; ///< whole table
618 int max_entries; ///< the maximum number of entries
619 int entries; ///< the current amount of entries
624 // =====================[ member variables ]==============================
625 EngineIdTable engine_id_table;
628 // the engineID of this SNMP entity
629 unsigned char *own_engine_id;
630 int own_engine_id_len;
631 OctetStr own_engine_id_oct;
633 unsigned int cur_msg_id; ///< msgID to use for next message
634 SNMP_PP_MUTABLE SnmpSynchronized cur_msg_id_lock;
636 USM *usm; ///< the USM object used
639 unsigned int snmpUnknownSecurityModels;
640 unsigned int snmpInvalidMsgs;
641 unsigned int snmpUnknownPDUHandlers;
644 #ifdef SNMP_PP_NAMESPACE
645 } // end of namespace Snmp_pp