SNMP++  3.6.3
uxsnmp.h
Go to the documentation of this file.
1 /*_############################################################################
2  _##
3  _## uxsnmp.h
4  _##
5  _## SNMP++ v3.4
6  _## -----------------------------------------------
7  _## Copyright (c) 2001-2021 Jochen Katz, Frank Fock
8  _##
9  _## This software is based on SNMP++2.6 from Hewlett Packard:
10  _##
11  _## Copyright (c) 1996
12  _## Hewlett-Packard Company
13  _##
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, Frank Fock, and Jochen Katz make no representations
21  _## about the 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.
25  _##
26  _##########################################################################*/
27 
28 #ifndef _SNMP_UXSNMP_H_
29 #define _SNMP_UXSNMP_H_
30 
31 #include <libsnmp.h>
32 #include "snmp_pp/reentrant.h"
33 #include "snmp_pp/target.h"
34 #include "snmp_pp/oid.h"
35 #include "snmp_pp/address.h"
36 
37 #ifdef SNMP_PP_NAMESPACE
38 namespace Snmp_pp {
39 #endif
40 
41 #define SNMP_PP_WITH_UDPADDR // Snmp class has constructor with UdpAddress
42 
43 //-----[ internally used defines ]----------------------------------------
44 #define MAXNAME 80 // maximum name length
45 #define MAX_ADDR_LEN 10 // maximum address len, ipx is 4+6
46 #ifndef INVALID_SOCKET
47 #define INVALID_SOCKET ((SnmpSocket)(~0)) // value for invalid socket
48 #endif
49 
50 //-----[ async defines for engine ]---------------------------------------
51 #define sNMP_PDU_GET_ASYNC 21
52 #define sNMP_PDU_GETNEXT_ASYNC 22
53 #define sNMP_PDU_SET_ASYNC 23
54 #define sNMP_PDU_GETBULK_ASYNC 24
55 #define sNMP_PDU_INFORM_ASYNC 25
56 
57 //------[ forward declaration of Snmp class ]-----------------------------
58 class Snmp;
59 class EventListHolder;
60 class Pdu;
61 class v3MP;
62 class CSNMPMessage;
63 
64 //-----------[ async methods callback ]-----------------------------------
65 /**
66  * Async methods of the class Snmp require the caller to provide a
67  * callback address of a function with this typedef.
68  *
69  * @note It is not allowed to call any synchronous Snmp methods within the
70  * callback. Async methods are allowed.
71  *
72  * @param reason - Reason for callback (see snmperrs.h)
73  * @param session - Pointer to Snmp object that was used to send the request
74  * @param pdu - The received Pdu if reason indicates a received message
75  * @param target - source target
76  * @param data - Pointer passed to the async method
77  */
78 typedef void (*snmp_callback)(int reason, Snmp *session,
79  Pdu &pdu, SnmpTarget &target, void *data);
80 
81 
82 /**
83  * Set the FD_CLOEXEC flag on the given socket.
84  * @param fd - The socket
85  * @return true on success
86  */
88 
89 //------------[ SNMP Class Def ]---------------------------------------------
90 //
91 /**
92  * SNMP class definition. The Snmp class provides an object oriented
93  * approach to SNMP. The SNMP class is an encapsulation of SNMP
94  * sessions, get, set and get next operations. The class manages all SNMP
95  * resources and provides complete retry and timeout capability.
96  *
97  * This class is thread save.
98  *
99  * @note If you use the async methods to send requests you MUST call
100  * Snmp::eventListHolder->SNMPProcessPendingEvents() while waiting
101  * for the responses. This function triggers the resend of
102  * packets and calls your callback function if the response is
103  * received.
104  *
105  * @note Call srand() before creating the first Snmp object.
106  */
108 {
109  friend class CSNMPMessage;
110 
111  public:
112  //------------------[ constructors ]----------------------------------
113 
114  /** @name Constructors and Destructor */
115  //@{
116 
117  /**
118  * Construct a new SNMP session using the given UDP port.
119  *
120  * @param status
121  * after creation of the session this parameter will
122  * hold the creation status.
123  * @param port
124  * an UDP port to be used for the session. With the default
125  * value "0", a random free port will be assigned by the
126  * operating system, which is Ok for most use cases.
127  * @param bind_ipv6
128  * Set this to true if IPv6 should be used. The default is
129  * IPv4.
130  */
131  Snmp(int &status, const unsigned short port = 0,
132  const bool bind_ipv6 = false);
133 
134  /**
135  * Construct a new SNMP session using the given UDP address.
136  * Thus, binds the session on a specific IPv4 or IPv6 address.
137  *
138  * @param status
139  * after creation of the session this parameter will
140  * hold the creation status.
141  * @param addr
142  * an UDP address to be used for the session
143  */
144  Snmp(int &status, const UdpAddress &addr);
145 
146  /**
147  * Construct a new SNMP session using the given UDP addresses.
148  * Using this constructor will bind to both IPv4 and IPv6 ports.
149  *
150  * @param status
151  * after creation of the session this parameter will
152  * hold the creation status.
153  * @param addr_v4
154  * an IPv4 UDP address to be used for the session
155  * @param addr_v6
156  * an IPv6 UDP address to be used for the session
157  */
158  Snmp(int &status, const UdpAddress& addr_v4, const UdpAddress& addr_v6);
159 
160  //-------------------[ destructor ]------------------------------------
161  /**
162  * Destructor.
163  */
164  virtual ~Snmp();
165 
166  //@}
167 
168  //--------[ Get the version of the snmp++ library ]--------------------
169  /**
170  * Get the version of the snmp++ library.
171  *
172  * @return The version of the snmp++ lib at runtime.
173  */
174  static const char *get_version();
175 
176 
177  //-------------------[ returns error string ]--------------------------
178  /**
179  * Returns a human readable error string.
180  *
181  * @param c - Error code returned by any method of this class
182  * @return Null terminated error string.
183  */
184  static const char *error_msg(const int c);
185 #ifdef _SNMPv3
186  /**
187  * Returns the error code for a SNMPv3 report Oid.
188  * If a report message is returned, then the contained Oid can be
189  * used to get a error code.
190  *
191  * @param v3Oid - Oid of a SNMPv3 report Pdu
192  * @return Error code.
193  */
194  static int error_code(const Oid& v3Oid);
195 
196  /**
197  * Returns a human readable error string.
198  * If a report message is returned, then the contained Oid can be
199  * used to get a error string.
200  *
201  * @param v3Oid - Oid of a SNMPv3 report Pdu
202  * @return Null terminated error string.
203  */
204  static const char* error_msg(const Oid& v3Oid)
205  { return error_msg(error_code(v3Oid)); }
206 
207  v3MP* get_mpv3() { return mpv3; }
208 
209  /**
210  * Sets the v3MP to be used by this Snmp session.
211  * @param v3mp
212  * a v3 message processing model.
213  * @since 3.4.0
214  */
215  virtual void set_mpv3(v3MP* v3mp) { mpv3 = v3mp; }
216 #endif
217 
218  //------------------------[ Windows Sockets ]----------------------------
219 
220  /**
221  * Initialize the Winsock library (WSAStartup).
222  *
223  * @note on Win32 this method *must* be called before creating Snmp or
224  * Address objects.
225  */
226  static void socket_startup();
227 
228 
229  /**
230  * Shut down the Winsock library (WSACleanup).
231  */
232  static void socket_cleanup();
233 
234  //------------------------[ send requests ]------------------------------
235 
236  /** @name Sending SNMP Pdus
237  */
238  //@{
239 
240  /**
241  * Send a blocking SNMP-GET request.
242  *
243  * @param pdu - Pdu to send
244  * @param target - Target for the get
245  *
246  * @return SNMP_CLASS_SUCCESS or a negative error code
247  */
248  virtual int get(Pdu &pdu, SnmpTarget &target);
249 
250  /**
251  * Send a async SNMP-GET request.
252  *
253  * @param pdu - Pdu to send
254  * @param target - Target for the get
255  * @param callback - User callback function to use
256  * @param callback_data - User definable data pointer
257  *
258  * @return SNMP_CLASS_SUCCESS or a negative error code
259  */
260  virtual int get(Pdu &pdu, SnmpTarget &target,
261  const snmp_callback callback,
262  const void *callback_data = 0);
263 
264  /**
265  * Send a blocking SNMP-GETNEXT request.
266  *
267  * @param pdu - Pdu to send
268  * @param target - Target for the getnext
269  *
270  * @return SNMP_CLASS_SUCCESS or a negative error code
271  */
272  virtual int get_next(Pdu &pdu, SnmpTarget &target);
273 
274  /**
275  * Send a async SNMP-GETNEXT request.
276  *
277  * @param pdu - Pdu to send
278  * @param target - Target for the getnext
279  * @param callback - User callback function to use
280  * @param callback_data - User definable data pointer
281  *
282  * @return SNMP_CLASS_SUCCESS or a negative error code
283  */
284  virtual int get_next(Pdu &pdu, SnmpTarget &target,
285  const snmp_callback callback,
286  const void *callback_data = 0);
287 
288  /**
289  * Send a blocking SNMP-SET request.
290  *
291  * @param pdu - Pdu to send
292  * @param target - Target for the set
293  *
294  * @return SNMP_CLASS_SUCCES or a negative error code
295  */
296  virtual int set(Pdu &pdu, SnmpTarget &target);
297 
298  /**
299  * Send a async SNMP-SET request.
300  *
301  * @param pdu - Pdu to send
302  * @param target - Target for the set
303  * @param callback - User callback function to use
304  * @param callback_data - User definable data pointer
305  *
306  * @return SNMP_CLASS_SUCCESS or a negative error code
307  */
308  virtual int set(Pdu &pdu, SnmpTarget &target,
309  const snmp_callback callback,
310  const void * callback_data = 0);
311 
312  /**
313  * Send a blocking SNMP-GETBULK request.
314  *
315  * @param pdu - Pdu to send
316  * @param target - Target for the getbulk
317  * @param non_repeaters - number of non repeaters
318  * @param max_reps - maximum number of repetitions
319  *
320  * @return SNMP_CLASS_SUCCESS or a negative error code
321  */
322  virtual int get_bulk(Pdu &pdu, SnmpTarget &target,
323  const int non_repeaters, const int max_reps);
324 
325  /**
326  * Send a async SNMP-GETBULK request.
327  *
328  * @param pdu - Pdu to send
329  * @param target - Target for the getbulk
330  * @param non_repeaters - number of non repeaters
331  * @param max_reps - maximum number of repetitions
332  * @param callback - User callback function to use
333  * @param callback_data - User definable data pointer
334  *
335  * @return SNMP_CLASS_SUCCESS or a negative error code
336  */
337  virtual int get_bulk(Pdu &pdu, SnmpTarget &target,
338  const int non_repeaters, const int max_reps,
339  const snmp_callback callback,
340  const void *callback_data = 0);
341 
342  /**
343  * Send a SNMP-TRAP.
344  *
345  * @param pdu - Pdu to send
346  * @param target - Target for the trap
347  *
348  * @return SNMP_CLASS_SUCCES or a negative error code
349  */
350  virtual int trap(Pdu &pdu, const SnmpTarget &target);
351 
352 
353  /**
354  * Send a SNMPv3-REPORT.
355  *
356  * @param pdu - Pdu to send
357  * @param target - Target for the report (must be a UTarget)
358  *
359  * @return SNMP_CLASS_SUCCESS or a negative error code
360  */
361  virtual int report(Pdu &pdu, SnmpTarget &target);
362 
363  /**
364  * Send a blocking INFORM-REQ.
365  *
366  * @param pdu - Pdu to send
367  * @param target - Target for the inform
368  *
369  * @return SNMP_CLASS_SUCCESS or a negative error code
370  */
371  virtual int inform(Pdu &pdu, SnmpTarget &target);
372 
373  /**
374  * Send a async INFORM-REQ.
375  *
376  * @param pdu - Pdu to send
377  * @param target - Target for the inform
378  * @param callback - User callback function to use
379  * @param callback_data - User definable data pointer
380  *
381  * @return SNMP_CLASS_SUCCESS or a negative error code
382  */
383  virtual int inform(Pdu &pdu, SnmpTarget &target,
384  const snmp_callback callback,
385  const void * callback_data = 0);
386 
387  /**
388  * Send a RESPONSE.
389  *
390  * @param pdu - Pdu to send
391  * @param target - Target for the response
392  * @param fd - file descriptor to use, should be the one
393  * that was passed to the callback function
394  *
395  * @return SNMP_CLASS_SUCCES or a negative error code
396  */
397  virtual int response(Pdu &pdu, SnmpTarget &target,
399 
400 
401  /**
402  * Send a SNMP Broadcast message.
403  *
404  * This member function sends out a valid SNMP message to a
405  * broadcast address and waits for responses. The source addresses
406  * of the response messages are added to the collection.
407  *
408  * The message is sent only once.
409  *
410  * @note SNMP_BROADCAST has to be defined in config_snmp_pp.h.
411  *
412  * @note There is no SNMP standard that defines "SNMP Broadcast
413  * discovery". SNMP agents are not forced to answer requests
414  * that are sent to a broadcast address.
415  *
416  * @note Do not use this method while waiting for other responses,
417  * as these responses will be added to the collection and dropped
418  * by this method. Solution for this problem: Use a special
419  * Snmp object only for broadcasts.
420  *
421  * @param addresses - The addresses of the agents, that answered.
422  * @param timeout_sec - Timeout in seconds
423  * @param addr - Broadcast address
424  * @param version - SNMP version to use
425  * @param community - Only needed for SNMPv1/v2c, defaults to "public"
426  *
427  */
428  virtual int broadcast_discovery(UdpAddressCollection &addresses,
429  const int timeout_sec,
430  const UdpAddress &addr,
431  const snmp_version version,
432  const OctetStr *community = 0);
433 
434 #ifdef _SNMPv3
435  virtual int engine_id_discovery(OctetStr &engine_id,
436  const int timeout_sec,
437  const UdpAddress &addr);
438 #endif
439  //@}
440 
441  /**
442  * Cancel a pending request.
443  *
444  * @param rid - The request id to cancel
445  *
446  * @return SNMP_CLASS_SUCCES or SNMP_CLASS_INVALID_REQID on failure
447  */
448  virtual int cancel(const unsigned long rid);
449 
450 
451  /** @name Trap and Inform handling
452  */
453  //@{
454 
455  /**
456  * Set the port for listening to traps and informs.
457  *
458  * @note This function must be called before notify_register(),
459  * otherwise the default port is used.
460  */
461  virtual void notify_set_listen_port(const int port);
462 
463  /**
464  * Get the port that is used for listening to traps and informs.
465  */
466  virtual int notify_get_listen_port();
467 
468  /**
469  * Register to get traps and informs.
470  *
471  * @note Every call to one of the notify_register() methods overwrites
472  * the previous given values.
473  *
474  * @param trapids - trap ids to listen for
475  * @param targets - targets to listen for
476  * @param callback - User callback function to use
477  * @param callback_data - User definable data pointer
478  *
479  * @return SNMP_CLASS_SUCCESS, SNMP_CLASS_TL_FAILED or SNMP_CLASS_TL_IN_USE
480  */
481  virtual int notify_register(const OidCollection &trapids,
482  const TargetCollection &targets,
483  const snmp_callback callback,
484  const void *callback_data=0);
485 
486  /**
487  * Unregister to get traps and informs.
488  * Undo the call to notify_register().
489  *
490  * @return Always SNMP_CLASS_SUCCESS
491  */
492  virtual int notify_unregister();
493 
494  /**
495  * Get notify register info.
496  *
497  * @param trapids - ids listened for
498  * @param targets - targets listened for
499  *
500  * @return SNMP_CLASS_SUCCESS or SNMP_CLASS_INVALID if not registered
501  */
502  virtual int get_notify_filter(OidCollection &trapids,
503  TargetCollection &targets);
504 
505  //-----------------------[ access the trap reception info ]---------------
506  /**
507  * Get a pointer to the callback function used for trap reception.
508  *
509  * @return Pointer to the function set through notify_register()
510  */
511  snmp_callback get_notify_callback() { return notifycallback; };
512 
513  /**
514  * Get a pointer to the data that is passed to the callback function.
515  *
516  * @return Pointer to the data set through notify_register()
517  */
518  void *get_notify_callback_data() { return notifycallback_data; };
519 
520  //@}
521 
522  /**
523  * Send raw UDP data.
524  * This method may be used to send any data to the recepient.
525  *
526  * @param send_buf - Data buffer
527  * @param send_len - Length of the data
528  * @param address - Recipient
529  * @param fd - socket to use, if not specified, the socket of the
530  * object is used
531  *
532  * @return 0 on success, -1 on failure
533  */
534  virtual int send_raw_data(unsigned char *send_buf,
535  size_t send_len, UdpAddress &address,
537 
538  const IpAddress &get_listen_address() const {return listen_address; };
539 
540  /**
541  * Start one thread listening for responses and notifications.
542  * This method is used to start response and notification processing in a
543  * multi threaded setup.
544  *
545  * @note start_poll_thread() itself is not thread safe. The caller must make
546  * sure that only one thread is calling start_poll_thread() or
547  * stop_poll_thread() at any point in time.
548  *
549  * @param timeout - Timeout for each call of the select() or poll()
550  * system call.
551  *
552  * @return true if the thread is now running and false if it failed to start.
553  */
554  bool start_poll_thread(const int timeout);
555 
556  /**
557  * Stop the thread listening for responses and notifications.
558  * This method is used to stop the thread started with start_poll_thread().
559  *
560  * @note stop_poll_thread() itself is not thread safe. The caller must make
561  * sure that only one thread is calling start_poll_thread() or
562  * stop_poll_thread() at any point in time.
563  */
564  void stop_poll_thread();
565 
566  EventListHolder *get_eventListHolder() { return eventListHolder; };
567 
568 protected:
569 
570  /**
571  * Check for the status of the worker thread.
572  * @return true - if running, false - otherwise
573  */
574  bool is_running() const
575  { return m_isThreadRunning; };
576 
577  /**
578  * This is a working thread for the recovery of the pending events.
579  *
580  * @param snmp [in] pointer to the whole object
581  *
582  * @return 0 - if successful,
583  * 1 - in the case of error
584  */
585 #ifdef WIN32
586  static int process_thread(Snmp *snmp);
587 #else
588  static void* process_thread(void *snmp);
589 #endif
590 
591  protected:
592 
593  /**
594  * Generate a unique (for this Snmp object) request id.
595  *
596  * @return Unique id between PDU_MIN_RID and PDU_MAX_RID
597  */
598  long MyMakeReqId();
599 
600  /**
601  * Common init function used by constructors.
602  */
603  void init(int& status, IpAddress*[2],
604  const unsigned short port_v4, const unsigned short port_v6);
605 
606  /**
607  * Set the notify timestamp of a trap pdu if the user did not set it.
608  */
609  void check_notify_timestamp(Pdu &pdu);
610 
611  //-----------[ Snmp Engine ]----------------------------------------
612  /**
613  * gets, sets and get nexts go through here....
614  * This mf does all snmp sending and reception
615  * except for traps which are sent using trap().
616  *
617  * @note that for a UTarget with an empty engine id the
618  * Utarget::set_engine_id() may be called.
619  */
620  int snmp_engine( Pdu &pdu, // pdu to use
621  long int non_reps, // get bulk only
622  long int max_reps, // get bulk only
623  SnmpTarget &target, // destination target
624  const snmp_callback cb, // async callback function
625  const void *cbd, // callback data
627  int reports_received = 0,
628  CSNMPMessage *snmp_message = nullptr);
629 
630  //--------[ map action ]------------------------------------------------
631  // map the snmp++ action to a SMI pdu type
632  void map_action(unsigned short action, unsigned short &pdu_action);
633  void map_action_to_async(unsigned short pdu_action, unsigned short &action);
634 
635 #ifdef _SNMPv3
636  /**
637  * Internal used callback data structure for async v3 requests.
638  */
640  {
641  Pdu *pdu; ///< The Pdu that was sent
642  long int non_reps; ///< For GET-BULK requests
643  long int max_reps; ///< For GET-BULK requests
644  SnmpTarget *target; ///< Pointer to the Target object to use
645  snmp_callback oldCallback; ///< User callback function
646  const void *cbd; ///< User callback data
647  int reports_received; ///< How many reports are already received
648  };
649 
650  friend void v3CallBack(int reason, Snmp *snmp, Pdu &pdu,
651  SnmpTarget &target, void *v3cd);
652  friend void deleteV3Callback(struct Snmp::V3CallBackData *&cbData);
653 
655 #endif
656 
657  //---[ instance variables ]
659 #ifdef SNMP_PP_IPv6
660  SnmpSocket iv_snmp_session_ipv6;
661 #endif
662 
664  unsigned long current_rid; // current rid to use
665 
666  // inform receive member variables
669 
670  // this member var will simulate a global var
672 
673 private:
674 
677 
678  // Keep track of the thread.
679 #ifdef _THREADS
680 #ifdef WIN32
681  HANDLE m_hThread;
682 #elif defined (CPU) && CPU == PPC603
683  int m_hThread;
684 #else
685  pthread_t m_hThread;
686 #endif
687 #endif
688 };
689 
690 #ifdef SNMP_PP_NAMESPACE
691 } // end of namespace Snmp_pp
692 #endif
693 
694 #endif // _SNMP_UXSNMP_H_
Pdu * pdu
The Pdu that was sent.
Definition: uxsnmp.h:641
virtual void set_mpv3(v3MP *v3mp)
Sets the v3MP to be used by this Snmp session.
Definition: uxsnmp.h:215
const void * cbd
User callback data.
Definition: uxsnmp.h:646
EventListHolder * eventListHolder
Definition: uxsnmp.h:671
SnmpTarget * target
Pointer to the Target object to use.
Definition: uxsnmp.h:644
void * get_notify_callback_data()
Get a pointer to the data that is passed to the callback function.
Definition: uxsnmp.h:518
void(* snmp_callback)(int reason, Snmp *session, Pdu &pdu, SnmpTarget &target, void *data)
Async methods of the class Snmp require the caller to provide a callback address of a function with t...
Definition: uxsnmp.h:78
v3MP * get_mpv3()
Definition: uxsnmp.h:207
unsigned long current_rid
Definition: uxsnmp.h:664
v3MP * mpv3
Definition: uxsnmp.h:654
SNMP class definition.
Definition: uxsnmp.h:107
SnmpSocket iv_snmp_session
Definition: uxsnmp.h:658
pthread_t m_hThread
Definition: uxsnmp.h:685
void * notifycallback_data
Definition: uxsnmp.h:668
#define DLLOPT
The Object Identifier Class.
Definition: oid.h:90
The SNMPv3 Message Processing Model (v3MP).
Definition: mp_v3.h:107
bool is_running() const
Check for the status of the worker thread.
Definition: uxsnmp.h:574
long int non_reps
For GET-BULK requests.
Definition: uxsnmp.h:642
snmp_version
The SNMP version to use is passed with this enum.
Definition: target.h:76
#define INVALID_SOCKET
Definition: uxsnmp.h:47
Definition: octet.h:67
snmp_callback notifycallback
Definition: uxsnmp.h:667
Internal used callback data structure for async v3 requests.
Definition: uxsnmp.h:639
IpAddress listen_address
Definition: uxsnmp.h:663
int m_pollTimeOut
Definition: uxsnmp.h:676
long int max_reps
For GET-BULK requests.
Definition: uxsnmp.h:643
snmp_callback get_notify_callback()
Get a pointer to the callback function used for trap reception.
Definition: uxsnmp.h:511
const IpAddress & get_listen_address() const
Definition: uxsnmp.h:538
int SnmpSocket
snmp_callback oldCallback
User callback function.
Definition: uxsnmp.h:645
int reports_received
How many reports are already received.
Definition: uxsnmp.h:647
static const char * error_msg(const Oid &v3Oid)
Returns a human readable error string.
Definition: uxsnmp.h:204
Pdu class...
Definition: pdu.h:82
bool setCloseOnExecFlag(SnmpSocket fd)
Set the FD_CLOEXEC flag on the given socket.
bool m_isThreadRunning
Definition: uxsnmp.h:675
Abstract class used to provide a virtual interface into Targets.
Definition: target.h:93
EventListHolder * get_eventListHolder()
Definition: uxsnmp.h:566