summaryrefslogtreecommitdiffstats
path: root/3rdparty/openpgm-svn-r1085/pgm/snmp.c
diff options
context:
space:
mode:
Diffstat (limited to '3rdparty/openpgm-svn-r1085/pgm/snmp.c')
-rw-r--r--3rdparty/openpgm-svn-r1085/pgm/snmp.c222
1 files changed, 222 insertions, 0 deletions
diff --git a/3rdparty/openpgm-svn-r1085/pgm/snmp.c b/3rdparty/openpgm-svn-r1085/pgm/snmp.c
new file mode 100644
index 0000000..5673878
--- /dev/null
+++ b/3rdparty/openpgm-svn-r1085/pgm/snmp.c
@@ -0,0 +1,222 @@
+/* vim:ts=8:sts=8:sw=4:noai:noexpandtab
+ *
+ * SNMP agent, single session.
+ *
+ * Copyright (c) 2006-2010 Miru Limited.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <net-snmp/net-snmp-config.h>
+#include <net-snmp/net-snmp-includes.h>
+#include <net-snmp/agent/net-snmp-agent-includes.h>
+
+#include <errno.h>
+#include <impl/i18n.h>
+#include <impl/framework.h>
+
+#include "pgm/snmp.h"
+#include "impl/pgmMIB.h"
+
+
+/* globals */
+
+bool pgm_agentx_subagent = TRUE;
+char* pgm_agentx_socket = NULL;
+char* pgm_snmp_appname = "PGM";
+
+/* locals */
+
+#ifndef _WIN32
+static pthread_t snmp_thread;
+static void* snmp_routine (void*);
+#else
+static HANDLE snmp_thread;
+static unsigned __stdcall snmp_routine (void*);
+#endif
+static pgm_notify_t snmp_notify = PGM_NOTIFY_INIT;
+static volatile uint32_t snmp_ref_count = 0;
+
+
+/* Calling application needs to redirect SNMP logging before prior to this
+ * function.
+ */
+
+bool
+pgm_snmp_init (
+ pgm_error_t** error
+ )
+{
+ if (pgm_atomic_exchange_and_add32 (&snmp_ref_count, 1) > 0)
+ return TRUE;
+
+ if (pgm_agentx_subagent)
+ {
+ pgm_minor (_("Configuring as SNMP AgentX sub-agent."));
+ if (pgm_agentx_socket)
+ {
+ pgm_minor (_("Using AgentX socket %s."), pgm_agentx_socket);
+ netsnmp_ds_set_string (NETSNMP_DS_APPLICATION_ID,
+ NETSNMP_DS_AGENT_X_SOCKET,
+ pgm_agentx_socket);
+ }
+ netsnmp_ds_set_boolean (NETSNMP_DS_APPLICATION_ID,
+ NETSNMP_DS_AGENT_ROLE,
+ TRUE);
+ }
+
+ pgm_minor (_("Initialising SNMP agent."));
+ if (0 != init_agent (pgm_snmp_appname)) {
+ pgm_set_error (error,
+ PGM_ERROR_DOMAIN_SNMP,
+ PGM_ERROR_FAILED,
+ _("Initialise SNMP agent: see SNMP log for further details."));
+ goto err_cleanup;
+ }
+
+ if (!pgm_mib_init (error)) {
+ goto err_cleanup;
+ }
+
+/* read config and parse mib */
+ pgm_minor (_("Initialising SNMP."));
+ init_snmp (pgm_snmp_appname);
+
+ if (!pgm_agentx_subagent)
+ {
+ pgm_minor (_("Connecting to SNMP master agent."));
+ if (0 != init_master_agent ()) {
+ pgm_set_error (error,
+ PGM_ERROR_DOMAIN_SNMP,
+ PGM_ERROR_FAILED,
+ _("Initialise SNMP master agent: see SNMP log for further details."));
+ snmp_shutdown (pgm_snmp_appname);
+ goto err_cleanup;
+ }
+ }
+
+/* create notification channel */
+ if (0 != pgm_notify_init (&snmp_notify)) {
+ pgm_set_error (error,
+ PGM_ERROR_DOMAIN_SNMP,
+ pgm_error_from_errno (errno),
+ _("Creating SNMP notification channel: %s"),
+ strerror (errno));
+ snmp_shutdown (pgm_snmp_appname);
+ goto err_cleanup;
+ }
+
+/* spawn thread to handle SNMP requests */
+#ifndef _WIN32
+ const int status = pthread_create (&snmp_thread, NULL, &snmp_routine, NULL);
+ if (0 != status) {
+ pgm_set_error (error,
+ PGM_ERROR_DOMAIN_SNMP,
+ pgm_error_from_errno (errno),
+ _("Creating SNMP thread: %s"),
+ strerror (errno));
+ snmp_shutdown (pgm_snmp_appname);
+ goto err_cleanup;
+ }
+#else
+ snmp_thread = (HANDLE)_beginthreadex (NULL, 0, &snmp_routine, NULL, 0, NULL);
+ const int save_errno = errno;
+ if (0 == snmp_thread) {
+ pgm_set_error (error,
+ PGM_ERROR_DOMAIN_SNMP,
+ pgm_error_from_errno (save_errno),
+ _("Creating SNMP thread: %s"),
+ strerror (save_errno));
+ snmp_shutdown (pgm_snmp_appname);
+ goto err_cleanup;
+ }
+#endif /* _WIN32 */
+ return TRUE;
+err_cleanup:
+ if (pgm_notify_is_valid (&snmp_notify)) {
+ pgm_notify_destroy (&snmp_notify);
+ }
+ pgm_atomic_dec32 (&snmp_ref_count);
+ return FALSE;
+}
+
+/* Terminate SNMP thread and free resources.
+ */
+
+bool
+pgm_snmp_shutdown (void)
+{
+ pgm_return_val_if_fail (pgm_atomic_read32 (&snmp_ref_count) > 0, FALSE);
+
+ if (pgm_atomic_exchange_and_add32 (&snmp_ref_count, (uint32_t)-1) != 1)
+ return TRUE;
+
+ pgm_notify_send (&snmp_notify);
+#ifndef _WIN32
+ pthread_join (snmp_thread, NULL);
+#else
+ CloseHandle (snmp_thread);
+#endif
+ pgm_notify_destroy (&snmp_notify);
+ snmp_shutdown (pgm_snmp_appname);
+ return TRUE;
+}
+
+/* Thread routine for processing SNMP requests
+ */
+
+static
+#ifndef _WIN32
+void*
+#else
+unsigned
+__stdcall
+#endif
+snmp_routine (
+ PGM_GNUC_UNUSED void* arg
+ )
+{
+ const int notify_fd = pgm_notify_get_fd (&snmp_notify);
+
+ for (;;)
+ {
+ int fds = 0, block = 1;
+ fd_set fdset;
+ struct timeval timeout;
+
+ FD_ZERO(&fdset);
+ snmp_select_info (&fds, &fdset, &timeout, &block);
+ FD_SET(notify_fd, &fdset);
+ if (notify_fd+1 > fds)
+ fds = notify_fd+1;
+ fds = select (fds, &fdset, NULL, NULL, block ? NULL : &timeout);
+ if (FD_ISSET(notify_fd, &fdset))
+ break;
+ if (fds)
+ snmp_read (&fdset);
+ else
+ snmp_timeout();
+ }
+
+/* cleanup */
+#ifndef _WIN32
+ return NULL;
+#else
+ _endthread();
+ return 0;
+#endif /* WIN32 */
+}
+
+/* eof */