Here is a first tiny prototype of SNMP agent support using pysnmp.
Ryu is able to send SNMP trap as notification originator.
Right now it sends only coldStart trap.

Mib needs to be populated for Ryu to work as command responder.
At this point of time, there is no interesting information
populated yet.

thanks,

diff --git a/ryu/services/snmp/__init__.py b/ryu/services/snmp/__init__.py
new file mode 100644
index 0000000..340a423
--- /dev/null
+++ b/ryu/services/snmp/__init__.py
@@ -0,0 +1,15 @@
+# Copyright (C) 2013 Nippon Telegraph and Telephone Corporation.
+# Copyright (C) 2013 Isaku Yamahata <yamahata at private email ne jp>
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
diff --git a/ryu/services/snmp/agent.py b/ryu/services/snmp/agent.py
new file mode 100644
index 0000000..a1a2c61
--- /dev/null
+++ b/ryu/services/snmp/agent.py
@@ -0,0 +1,162 @@
+# Copyright (C) 2013 Nippon Telegraph and Telephone Corporation.
+# Copyright (C) 2013 Isaku Yamahata <yamahata at private email ne jp>
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+
+import os.path
+
+from oslo.config import cfg
+from pyasn1.compat.octets import null
+from pysnmp.entity import config
+from pysnmp.entity import engine
+from pysnmp.entity.rfc3413 import cmdrsp
+from pysnmp.entity.rfc3413 import context
+from pysnmp.entity.rfc3413 import ntforg
+from pysnmp.entity.rfc3413.oneliner import mibvar
+from pysnmp.carrier.asynsock.dgram import udp
+from pysnmp.proto.api import v2c
+from pysnmp.smi import builder
+from pysnmp.smi import view
+
+
+from ryu.base import app_manager
+from ryu.lib import hub
+
+
+CONF = cfg.CONF
+CONF.register_opts([
+    cfg.StrOpt('snmp-host', default='',
+               help='snmp IP address to get request'),
+    cfg.IntOpt('snmp-port', default=161,
+               help='snmp port to get request'),
+    cfg.StrOpt('snmp-target-host', default='127.0.0.1',
+               help='snmptrap target host ip address to send trap'),
+    cfg.IntOpt('snmp-target-port', default=162,
+               help='snmptrap port to send trap'),
+
+    cfg.StrOpt('snmp-notification-target', default='ryu-notification',
+               help='snmptrap target name'),
+
+    cfg.MultiStrOpt('mib-dir', default=[],
+                    help='directories to load MIBs'),
+])
+
+
+from pysnmp import debug
+debug.setLogger(debug.Debug('all'))
+
+
+class SNMPAgent(app_manager.RyuApp):
+    _DEFAULT_ENGINE_ID = '8000000001020304'
+    _DEFAULT_V3_USER = 'ryu-snmp-user'
+    _DEFAULT_SECURITY_NAME = 'ryu-creds'
+    _DEFAULT_NMS = 'ryu-nms'
+    # 'noAuthNoPriv', 'authNoPrive', 'authPriv'
+    _DEFAULT_SECURITY_LEVEL = 'authPriv'
+    _DEFAULT_AUTH = config.usmHMACMD5AuthProtocol       # 'SHA', 'MD5'
+    _DEFAULT_AUTH_KEY = 'authkey1'
+    _DEFAULT_PRIV = config.usmDESPrivProtocol           # 'DES', 'AES'
+    _DEFAULT_PRIV_KEY = 'privkey1'
+
+    _NOTIFICATION_NAME = 'ryu-notification'
+    _PARAMS_NAME = 'my-filter'
+    _TRANSPORT_TAG = 'all-my-managers'
+
+    def __init__(self, *args, **kwargs):
+        super(SNMPAgent, self).__init__(*args, **kwargs)
+        snmp_engine = engine.SnmpEngine(
+            v2c.OctetString(hexValue=self._DEFAULT_ENGINE_ID))
+        self._snmp_engine = snmp_engine
+
+        # TODO authProtocol, authKey, privProtocol, privKey, contextEngineId
+        config.addV3User(snmp_engine, self._DEFAULT_V3_USER,
+                         self._DEFAULT_AUTH, self._DEFAULT_AUTH_KEY,
+                         self._DEFAULT_PRIV, self._DEFAULT_PRIV_KEY)
+        config.addTargetParams(snmp_engine,
+                               self._DEFAULT_SECURITY_NAME,
+                               self._DEFAULT_V3_USER,
+                               self._DEFAULT_SECURITY_LEVEL)
+        udp_domain_name_target = udp.domainName + (1, )
+        config.addSocketTransport(
+            snmp_engine, udp_domain_name_target,
+            udp.UdpTransport().openClientMode())
+        config.addTargetAddr(snmp_engine,
+                             self._DEFAULT_NMS,
+                             udp_domain_name_target,
+                             (CONF.snmp_target_host, CONF.snmp_target_port),
+                             self._DEFAULT_SECURITY_NAME,
+                             tagList=self._TRANSPORT_TAG)
+        config.addNotificationTarget(snmp_engine,
+                                     self._NOTIFICATION_NAME,
+                                     self._PARAMS_NAME,
+                                     self._TRANSPORT_TAG,
+                                     'trap')
+        config.addContext(snmp_engine, '')
+        # Allow NOTIFY access to Agent's MIB by this SNMP model
+        config.addVacmUser(snmp_engine, 3,  # SNMPv3
+                           self._DEFAULT_V3_USER, self._DEFAULT_SECURITY_LEVEL,
+                           (), (), (1, 3, 6))
+        snmp_context = context.SnmpContext(snmp_engine)
+        self._snmp_context = snmp_context
+        self._ntf_org = ntforg.NotificationOriginator(snmp_context)
+
+        # command responder
+        config.addSocketTransport(
+            snmp_engine, udp.domainName + (2, ),
+            udp.UdpTransport().openServerMode((CONF.snmp_host,
+                                               CONF.snmp_port)))
+        mib_builder = self._snmp_context.getMibInstrum().getMibBuilder()
+        self._mib_builder = mib_builder
+
+        mib_sources = list(mib_builder.getMibSources())
+        mib_sources.append(builder.DirMibSource(os.path.join(
+            os.path.basename(__file__), 'mibs')))
+        mib_sources.append(builder.DirMibSource('.'))
+        mib_sources.extend([builder.DirMibSource(CONF.mib_dir)
+                            for mib_dir in CONF.mib_dir])
+        mib_builder.setMibSources(*mib_sources)
+
+        cmdrsp.GetCommandResponder(snmp_engine, snmp_context)
+        cmdrsp.NextCommandResponder(snmp_engine, snmp_context)
+        cmdrsp.BulkCommandResponder(snmp_engine, snmp_context)
+        cmdrsp.SetCommandResponder(snmp_engine, snmp_context)
+
+        # for MIB resolution
+        self._mib_view_controller = view.MibViewController(mib_builder)
+
+    def start(self):
+        self.threads.append(hub.spawn(self._loop))
+        # super(SNMPAgent, self).start()
+        sys_name = mibvar.MibVariable('SNMPv2-MIB', 'sysName', 0)
+        sys_name.resolveWithMib(self._mib_view_controller)
+        self.send_trap(('SNMPv2-MIB', 'coldStart'),
+                       ((sys_name, v2c.OctetString('Ryu-SNMP-agent')), ))
+
+    def _loop(self):
+        self._snmp_engine.transportDispatcher.jobStarted(1)
+        try:
+            self._snmp_engine.transportDispatcher.runDispatcher()
+        except:
+            self._snmp_engine.transportDispatcher.closeDispatcher()
+            raise
+
+    def send_trap(self, name, var_binds=(), cb_fun=None, cb_ctx=None,
+                  context_name=null, instance_index=None):
+        print var_binds
+        error_indication = self._ntf_org.sendNotification(
+            self._snmp_engine,
+            self._NOTIFICATION_NAME,
+            name, var_binds,
+            cb_fun, cb_ctx, context_name, instance_index)
diff --git a/ryu/services/snmp/mibs/__init__.py 
b/ryu/services/snmp/mibs/__init__.py
new file mode 100644
index 0000000..340a423
--- /dev/null
+++ b/ryu/services/snmp/mibs/__init__.py
@@ -0,0 +1,15 @@
+# Copyright (C) 2013 Nippon Telegraph and Telephone Corporation.
+# Copyright (C) 2013 Isaku Yamahata <yamahata at private email ne jp>
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.


-- 
yamahata

------------------------------------------------------------------------------
AlienVault Unified Security Management (USM) platform delivers complete
security visibility with the essential security capabilities. Easily and
efficiently configure, manage, and operate all of your security controls
from a single console and one unified framework. Download a free trial.
http://p.sf.net/sfu/alienvault_d2d
_______________________________________________
Ryu-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/ryu-devel

Reply via email to