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