From 33787d486ae532acfd941e87c00648ab3482e554 Mon Sep 17 00:00:00 2001 From: grossmj Date: Fri, 27 Jun 2014 07:26:47 -0600 Subject: [PATCH] New feature: packet capture for the Ethernet hub and Ethernet, ATM and Frame relay switches. --- gns3server/modules/dynamips/backends/atmsw.py | 83 ++++++++++++++++++ .../modules/dynamips/backends/ethhub.py | 85 ++++++++++++++++++- gns3server/modules/dynamips/backends/ethsw.py | 83 ++++++++++++++++++ gns3server/modules/dynamips/backends/frsw.py | 83 ++++++++++++++++++ .../modules/dynamips/nodes/atm_switch.py | 52 ++++++++++++ .../modules/dynamips/nodes/ethernet_switch.py | 52 ++++++++++++ .../dynamips/nodes/frame_relay_switch.py | 52 ++++++++++++ gns3server/modules/dynamips/nodes/hub.py | 52 ++++++++++++ gns3server/modules/dynamips/nodes/router.py | 16 ++-- gns3server/modules/dynamips/schemas/atmsw.py | 56 ++++++++++++ gns3server/modules/dynamips/schemas/ethhub.py | 56 ++++++++++++ gns3server/modules/dynamips/schemas/ethsw.py | 56 ++++++++++++ gns3server/modules/dynamips/schemas/frsw.py | 56 ++++++++++++ 13 files changed, 776 insertions(+), 6 deletions(-) diff --git a/gns3server/modules/dynamips/backends/atmsw.py b/gns3server/modules/dynamips/backends/atmsw.py index 5f4ab494..2ce0410b 100644 --- a/gns3server/modules/dynamips/backends/atmsw.py +++ b/gns3server/modules/dynamips/backends/atmsw.py @@ -16,6 +16,7 @@ # along with this program. If not, see . import re +import os from gns3server.modules import IModule from ..nodes.atm_switch import ATMSwitch from ..dynamips_error import DynamipsError @@ -26,6 +27,8 @@ from ..schemas.atmsw import ATMSW_UPDATE_SCHEMA from ..schemas.atmsw import ATMSW_ALLOCATE_UDP_PORT_SCHEMA from ..schemas.atmsw import ATMSW_ADD_NIO_SCHEMA from ..schemas.atmsw import ATMSW_DELETE_NIO_SCHEMA +from ..schemas.atmsw import ATMSW_START_CAPTURE_SCHEMA +from ..schemas.atmsw import ATMSW_STOP_CAPTURE_SCHEMA import logging log = logging.getLogger(__name__) @@ -310,3 +313,83 @@ class ATMSW(object): return self.send_response(True) + + @IModule.route("dynamips.atmsw.start_capture") + def atmsw_start_capture(self, request): + """ + Starts a packet capture. + + Mandatory request parameters: + - id (vm identifier) + - port (port identifier) + - port_id (port identifier) + - capture_file_name + + Optional request parameters: + - data_link_type (PCAP DLT_* value) + + Response parameters: + - port_id (port identifier) + - capture_file_path (path to the capture file) + + :param request: JSON request + """ + + # validate the request + if not self.validate_request(request, ATMSW_START_CAPTURE_SCHEMA): + return + + # get the ATM switch instance + atmsw = self.get_device_instance(request["id"], self._atm_switches) + if not atmsw: + return + + port = request["port"] + capture_file_name = request["capture_file_name"] + data_link_type = request.get("data_link_type") + + try: + capture_file_path = os.path.join(atmsw.hypervisor.working_dir, "captures", capture_file_name) + atmsw.start_capture(port, capture_file_path, data_link_type) + except DynamipsError as e: + self.send_custom_error(str(e)) + return + + response = {"port_id": request["port_id"], + "capture_file_path": capture_file_path} + self.send_response(response) + + @IModule.route("dynamips.atmsw.stop_capture") + def atmsw_stop_capture(self, request): + """ + Stops a packet capture. + + Mandatory request parameters: + - id (vm identifier) + - port_id (port identifier) + - port (port number) + + Response parameters: + - port_id (port identifier) + + :param request: JSON request + """ + + # validate the request + if not self.validate_request(request, ATMSW_STOP_CAPTURE_SCHEMA): + return + + # get the ATM switch instance + atmsw = self.get_device_instance(request["id"], self._atm_switches) + if not atmsw: + return + + port = request["port"] + try: + atmsw.stop_capture(port) + except DynamipsError as e: + self.send_custom_error(str(e)) + return + + response = {"port_id": request["port_id"]} + self.send_response(response) diff --git a/gns3server/modules/dynamips/backends/ethhub.py b/gns3server/modules/dynamips/backends/ethhub.py index c09703c2..97c9df7f 100644 --- a/gns3server/modules/dynamips/backends/ethhub.py +++ b/gns3server/modules/dynamips/backends/ethhub.py @@ -15,6 +15,7 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . +import os from gns3server.modules import IModule from ..nodes.hub import Hub from ..dynamips_error import DynamipsError @@ -25,6 +26,8 @@ from ..schemas.ethhub import ETHHUB_UPDATE_SCHEMA from ..schemas.ethhub import ETHHUB_ALLOCATE_UDP_PORT_SCHEMA from ..schemas.ethhub import ETHHUB_ADD_NIO_SCHEMA from ..schemas.ethhub import ETHHUB_DELETE_NIO_SCHEMA +from ..schemas.ethhub import ETHHUB_START_CAPTURE_SCHEMA +from ..schemas.ethhub import ETHHUB_STOP_CAPTURE_SCHEMA import logging log = logging.getLogger(__name__) @@ -236,7 +239,7 @@ class ETHHUB(object): self.send_response({"port_id": request["port_id"]}) @IModule.route("dynamips.ethhub.delete_nio") - def ethsw_delete_nio(self, request): + def ethhub_delete_nio(self, request): """ Deletes an NIO (Network Input/Output). @@ -268,3 +271,83 @@ class ETHHUB(object): return self.send_response(True) + + @IModule.route("dynamips.ethhub.start_capture") + def ethhub_start_capture(self, request): + """ + Starts a packet capture. + + Mandatory request parameters: + - id (vm identifier) + - port (port identifier) + - port_id (port identifier) + - capture_file_name + + Optional request parameters: + - data_link_type (PCAP DLT_* value) + + Response parameters: + - port_id (port identifier) + - capture_file_path (path to the capture file) + + :param request: JSON request + """ + + # validate the request + if not self.validate_request(request, ETHHUB_START_CAPTURE_SCHEMA): + return + + # get the Ethernet hub instance + ethhub = self.get_device_instance(request["id"], self._ethernet_hubs) + if not ethhub: + return + + port = request["port"] + capture_file_name = request["capture_file_name"] + data_link_type = request.get("data_link_type") + + try: + capture_file_path = os.path.join(ethhub.hypervisor.working_dir, "captures", capture_file_name) + ethhub.start_capture(port, capture_file_path, data_link_type) + except DynamipsError as e: + self.send_custom_error(str(e)) + return + + response = {"port_id": request["port_id"], + "capture_file_path": capture_file_path} + self.send_response(response) + + @IModule.route("dynamips.ethhub.stop_capture") + def ethhub_stop_capture(self, request): + """ + Stops a packet capture. + + Mandatory request parameters: + - id (vm identifier) + - port_id (port identifier) + - port (port number) + + Response parameters: + - port_id (port identifier) + + :param request: JSON request + """ + + # validate the request + if not self.validate_request(request, ETHHUB_STOP_CAPTURE_SCHEMA): + return + + # get the Ethernet hub instance + ethhub = self.get_device_instance(request["id"], self._ethernet_hubs) + if not ethhub: + return + + port = request["port"] + try: + ethhub.stop_capture(port) + except DynamipsError as e: + self.send_custom_error(str(e)) + return + + response = {"port_id": request["port_id"]} + self.send_response(response) diff --git a/gns3server/modules/dynamips/backends/ethsw.py b/gns3server/modules/dynamips/backends/ethsw.py index a59ec4b7..e251e158 100644 --- a/gns3server/modules/dynamips/backends/ethsw.py +++ b/gns3server/modules/dynamips/backends/ethsw.py @@ -15,6 +15,7 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . +import os from gns3server.modules import IModule from ..nodes.ethernet_switch import EthernetSwitch from ..dynamips_error import DynamipsError @@ -25,6 +26,8 @@ from ..schemas.ethsw import ETHSW_UPDATE_SCHEMA from ..schemas.ethsw import ETHSW_ALLOCATE_UDP_PORT_SCHEMA from ..schemas.ethsw import ETHSW_ADD_NIO_SCHEMA from ..schemas.ethsw import ETHSW_DELETE_NIO_SCHEMA +from ..schemas.ethsw import ETHSW_START_CAPTURE_SCHEMA +from ..schemas.ethsw import ETHSW_STOP_CAPTURE_SCHEMA import logging log = logging.getLogger(__name__) @@ -297,3 +300,83 @@ class ETHSW(object): return self.send_response(True) + + @IModule.route("dynamips.ethsw.start_capture") + def ethsw_start_capture(self, request): + """ + Starts a packet capture. + + Mandatory request parameters: + - id (vm identifier) + - port (port identifier) + - port_id (port identifier) + - capture_file_name + + Optional request parameters: + - data_link_type (PCAP DLT_* value) + + Response parameters: + - port_id (port identifier) + - capture_file_path (path to the capture file) + + :param request: JSON request + """ + + # validate the request + if not self.validate_request(request, ETHSW_START_CAPTURE_SCHEMA): + return + + # get the Ethernet switch instance + ethsw = self.get_device_instance(request["id"], self._ethernet_switches) + if not ethsw: + return + + port = request["port"] + capture_file_name = request["capture_file_name"] + data_link_type = request.get("data_link_type") + + try: + capture_file_path = os.path.join(ethsw.hypervisor.working_dir, "captures", capture_file_name) + ethsw.start_capture(port, capture_file_path, data_link_type) + except DynamipsError as e: + self.send_custom_error(str(e)) + return + + response = {"port_id": request["port_id"], + "capture_file_path": capture_file_path} + self.send_response(response) + + @IModule.route("dynamips.ethsw.stop_capture") + def ethsw_stop_capture(self, request): + """ + Stops a packet capture. + + Mandatory request parameters: + - id (vm identifier) + - port_id (port identifier) + - port (port number) + + Response parameters: + - port_id (port identifier) + + :param request: JSON request + """ + + # validate the request + if not self.validate_request(request, ETHSW_STOP_CAPTURE_SCHEMA): + return + + # get the Ethernet switch instance + ethsw = self.get_device_instance(request["id"], self._ethernet_switches) + if not ethsw: + return + + port = request["port"] + try: + ethsw.stop_capture(port) + except DynamipsError as e: + self.send_custom_error(str(e)) + return + + response = {"port_id": request["port_id"]} + self.send_response(response) diff --git a/gns3server/modules/dynamips/backends/frsw.py b/gns3server/modules/dynamips/backends/frsw.py index cae6923f..ed63f501 100644 --- a/gns3server/modules/dynamips/backends/frsw.py +++ b/gns3server/modules/dynamips/backends/frsw.py @@ -15,6 +15,7 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . +import os from gns3server.modules import IModule from ..nodes.frame_relay_switch import FrameRelaySwitch from ..dynamips_error import DynamipsError @@ -25,6 +26,8 @@ from ..schemas.frsw import FRSW_UPDATE_SCHEMA from ..schemas.frsw import FRSW_ALLOCATE_UDP_PORT_SCHEMA from ..schemas.frsw import FRSW_ADD_NIO_SCHEMA from ..schemas.frsw import FRSW_DELETE_NIO_SCHEMA +from ..schemas.frsw import FRSW_START_CAPTURE_SCHEMA +from ..schemas.frsw import FRSW_STOP_CAPTURE_SCHEMA import logging log = logging.getLogger(__name__) @@ -289,3 +292,83 @@ class FRSW(object): return self.send_response(True) + + @IModule.route("dynamips.frsw.start_capture") + def frsw_start_capture(self, request): + """ + Starts a packet capture. + + Mandatory request parameters: + - id (vm identifier) + - port (port identifier) + - port_id (port identifier) + - capture_file_name + + Optional request parameters: + - data_link_type (PCAP DLT_* value) + + Response parameters: + - port_id (port identifier) + - capture_file_path (path to the capture file) + + :param request: JSON request + """ + + # validate the request + if not self.validate_request(request, FRSW_START_CAPTURE_SCHEMA): + return + + # get the Frame relay switch instance + frsw = self.get_device_instance(request["id"], self._frame_relay_switches) + if not frsw: + return + + port = request["port"] + capture_file_name = request["capture_file_name"] + data_link_type = request.get("data_link_type") + + try: + capture_file_path = os.path.join(frsw.hypervisor.working_dir, "captures", capture_file_name) + frsw.start_capture(port, capture_file_path, data_link_type) + except DynamipsError as e: + self.send_custom_error(str(e)) + return + + response = {"port_id": request["port_id"], + "capture_file_path": capture_file_path} + self.send_response(response) + + @IModule.route("dynamips.frsw.stop_capture") + def frsw_stop_capture(self, request): + """ + Stops a packet capture. + + Mandatory request parameters: + - id (vm identifier) + - port_id (port identifier) + - port (port number) + + Response parameters: + - port_id (port identifier) + + :param request: JSON request + """ + + # validate the request + if not self.validate_request(request, FRSW_STOP_CAPTURE_SCHEMA): + return + + # get the Frame relay switch instance + frsw = self.get_device_instance(request["id"], self._frame_relay_switches) + if not frsw: + return + + port = request["port"] + try: + frsw.stop_capture(port) + except DynamipsError as e: + self.send_custom_error(str(e)) + return + + response = {"port_id": request["port_id"]} + self.send_response(response) diff --git a/gns3server/modules/dynamips/nodes/atm_switch.py b/gns3server/modules/dynamips/nodes/atm_switch.py index 00fb967c..0c382c44 100644 --- a/gns3server/modules/dynamips/nodes/atm_switch.py +++ b/gns3server/modules/dynamips/nodes/atm_switch.py @@ -20,6 +20,7 @@ Interface for Dynamips virtual ATM switch module ("atmsw"). http://github.com/GNS3/dynamips/blob/master/README.hypervisor#L593 """ +import os from ..dynamips_error import DynamipsError import logging @@ -351,3 +352,54 @@ class ATMSwitch(object): vpi2=vpi2, vci2=vci2)) del self._mapping[(port1, vpi1, vci1)] + + def start_capture(self, port, output_file, data_link_type="DLT_ATM_RFC1483"): + """ + Starts a packet capture. + + :param port: allocated port + :param output_file: PCAP destination file for the capture + :param data_link_type: PCAP data link type (DLT_*), default is DLT_ATM_RFC1483 + """ + + if port not in self._nios: + raise DynamipsError("Port {} is not allocated".format(port)) + + nio = self._nios[port] + + data_link_type = data_link_type.lower() + if data_link_type.startswith("dlt_"): + data_link_type = data_link_type[4:] + + if nio.input_filter[0] is not None and nio.output_filter[0] is not None: + raise DynamipsError("Port {} has already a filter applied".format(port)) + + try: + os.makedirs(os.path.dirname(output_file)) + except FileExistsError: + pass + except OSError as e: + raise DynamipsError("Could not create captures directory {}".format(e)) + + nio.bind_filter("both", "capture") + nio.setup_filter("both", "{} {}".format(data_link_type, output_file)) + + log.info("ATM switch {name} [id={id}]: starting packet capture on {port}".format(name=self._name, + id=self._id, + port=port)) + + def stop_capture(self, port): + """ + Stops a packet capture. + + :param port: allocated port + """ + + if port not in self._nios: + raise DynamipsError("Port {} is not allocated".format(port)) + + nio = self._nios[port] + nio.unbind_filter("both") + log.info("ATM switch {name} [id={id}]: stopping packet capture on {port}".format(name=self._name, + id=self._id, + port=port)) diff --git a/gns3server/modules/dynamips/nodes/ethernet_switch.py b/gns3server/modules/dynamips/nodes/ethernet_switch.py index 9363bafb..45cc25c0 100644 --- a/gns3server/modules/dynamips/nodes/ethernet_switch.py +++ b/gns3server/modules/dynamips/nodes/ethernet_switch.py @@ -20,6 +20,7 @@ Interface for Dynamips virtual Ethernet switch module ("ethsw"). http://github.com/GNS3/dynamips/blob/master/README.hypervisor#L558 """ +import os from ..dynamips_error import DynamipsError import logging @@ -287,3 +288,54 @@ class EthernetSwitch(object): """ self._hypervisor.send("ethsw clear_mac_addr_table {}".format(self._name)) + + def start_capture(self, port, output_file, data_link_type="DLT_EN10MB"): + """ + Starts a packet capture. + + :param port: allocated port + :param output_file: PCAP destination file for the capture + :param data_link_type: PCAP data link type (DLT_*), default is DLT_EN10MB + """ + + if port not in self._nios: + raise DynamipsError("Port {} is not allocated".format(port)) + + nio = self._nios[port] + + data_link_type = data_link_type.lower() + if data_link_type.startswith("dlt_"): + data_link_type = data_link_type[4:] + + if nio.input_filter[0] is not None and nio.output_filter[0] is not None: + raise DynamipsError("Port {} has already a filter applied".format(port)) + + try: + os.makedirs(os.path.dirname(output_file)) + except FileExistsError: + pass + except OSError as e: + raise DynamipsError("Could not create captures directory {}".format(e)) + + nio.bind_filter("both", "capture") + nio.setup_filter("both", "{} {}".format(data_link_type, output_file)) + + log.info("Ethernet switch {name} [id={id}]: starting packet capture on {port}".format(name=self._name, + id=self._id, + port=port)) + + def stop_capture(self, port): + """ + Stops a packet capture. + + :param port: allocated port + """ + + if port not in self._nios: + raise DynamipsError("Port {} is not allocated".format(port)) + + nio = self._nios[port] + nio.unbind_filter("both") + log.info("Ethernet switch {name} [id={id}]: stopping packet capture on {port}".format(name=self._name, + id=self._id, + port=port)) diff --git a/gns3server/modules/dynamips/nodes/frame_relay_switch.py b/gns3server/modules/dynamips/nodes/frame_relay_switch.py index e096c137..0b44fbea 100644 --- a/gns3server/modules/dynamips/nodes/frame_relay_switch.py +++ b/gns3server/modules/dynamips/nodes/frame_relay_switch.py @@ -20,6 +20,7 @@ Interface for Dynamips virtual Frame-Relay switch module. http://github.com/GNS3/dynamips/blob/master/README.hypervisor#L642 """ +import os from ..dynamips_error import DynamipsError import logging @@ -273,3 +274,54 @@ class FrameRelaySwitch(object): port2=port2, dlci2=dlci2)) del self._mapping[(port1, dlci1)] + + def start_capture(self, port, output_file, data_link_type="DLT_FRELAY"): + """ + Starts a packet capture. + + :param port: allocated port + :param output_file: PCAP destination file for the capture + :param data_link_type: PCAP data link type (DLT_*), default is DLT_FRELAY + """ + + if port not in self._nios: + raise DynamipsError("Port {} is not allocated".format(port)) + + nio = self._nios[port] + + data_link_type = data_link_type.lower() + if data_link_type.startswith("dlt_"): + data_link_type = data_link_type[4:] + + if nio.input_filter[0] is not None and nio.output_filter[0] is not None: + raise DynamipsError("Port {} has already a filter applied".format(port)) + + try: + os.makedirs(os.path.dirname(output_file)) + except FileExistsError: + pass + except OSError as e: + raise DynamipsError("Could not create captures directory {}".format(e)) + + nio.bind_filter("both", "capture") + nio.setup_filter("both", "{} {}".format(data_link_type, output_file)) + + log.info("Frame relay switch {name} [id={id}]: starting packet capture on {port}".format(name=self._name, + id=self._id, + port=port)) + + def stop_capture(self, port): + """ + Stops a packet capture. + + :param port: allocated port + """ + + if port not in self._nios: + raise DynamipsError("Port {} is not allocated".format(port)) + + nio = self._nios[port] + nio.unbind_filter("both") + log.info("Frame relay switch {name} [id={id}]: stopping packet capture on {port}".format(name=self._name, + id=self._id, + port=port)) diff --git a/gns3server/modules/dynamips/nodes/hub.py b/gns3server/modules/dynamips/nodes/hub.py index b32ff944..6f7f0e59 100644 --- a/gns3server/modules/dynamips/nodes/hub.py +++ b/gns3server/modules/dynamips/nodes/hub.py @@ -19,6 +19,7 @@ Hub object that uses the Bridge interface to create a hub with ports. """ +import os from .bridge import Bridge from ..dynamips_error import DynamipsError @@ -134,3 +135,54 @@ class Hub(Bridge): del self._mapping[port] return nio + + def start_capture(self, port, output_file, data_link_type="DLT_EN10MB"): + """ + Starts a packet capture. + + :param port: allocated port + :param output_file: PCAP destination file for the capture + :param data_link_type: PCAP data link type (DLT_*), default is DLT_EN10MB + """ + + if port not in self._mapping: + raise DynamipsError("Port {} is not allocated".format(port)) + + nio = self._mapping[port] + + data_link_type = data_link_type.lower() + if data_link_type.startswith("dlt_"): + data_link_type = data_link_type[4:] + + if nio.input_filter[0] is not None and nio.output_filter[0] is not None: + raise DynamipsError("Port {} has already a filter applied".format(port)) + + try: + os.makedirs(os.path.dirname(output_file)) + except FileExistsError: + pass + except OSError as e: + raise DynamipsError("Could not create captures directory {}".format(e)) + + nio.bind_filter("both", "capture") + nio.setup_filter("both", "{} {}".format(data_link_type, output_file)) + + log.info("Ethernet hub {name} [id={id}]: starting packet capture on {port}".format(name=self._name, + id=self._id, + port=port)) + + def stop_capture(self, port): + """ + Stops a packet capture. + + :param port: allocated port + """ + + if port not in self._mapping: + raise DynamipsError("Port {} is not allocated".format(port)) + + nio = self._mapping[port] + nio.unbind_filter("both") + log.info("Ethernet hub {name} [id={id}]: stopping packet capture on {port}".format(name=self._name, + id=self._id, + port=port)) diff --git a/gns3server/modules/dynamips/nodes/router.py b/gns3server/modules/dynamips/nodes/router.py index 7fc15e5a..9c08ec77 100644 --- a/gns3server/modules/dynamips/nodes/router.py +++ b/gns3server/modules/dynamips/nodes/router.py @@ -1578,11 +1578,11 @@ class Router(object): nio.bind_filter("both", "capture") nio.setup_filter("both", "{} {}".format(data_link_type, output_file)) - log.info("router {name} [id={id}]: capturing on port {slot_id}/{port_id}".format(name=self._name, - id=self._id, - nio_name=nio.name, - slot_id=slot_id, - port_id=port_id)) + log.info("router {name} [id={id}]: starting packet capture on port {slot_id}/{port_id}".format(name=self._name, + id=self._id, + nio_name=nio.name, + slot_id=slot_id, + port_id=port_id)) def stop_capture(self, slot_id, port_id): """ @@ -1604,6 +1604,12 @@ class Router(object): nio = adapter.get_nio(port_id) nio.unbind_filter("both") + log.info("router {name} [id={id}]: stopping packet capture on port {slot_id}/{port_id}".format(name=self._name, + id=self._id, + nio_name=nio.name, + slot_id=slot_id, + port_id=port_id)) + def _create_slots(self, numslots): """ Creates the appropriate number of slots for this router. diff --git a/gns3server/modules/dynamips/schemas/atmsw.py b/gns3server/modules/dynamips/schemas/atmsw.py index cddea592..37669478 100644 --- a/gns3server/modules/dynamips/schemas/atmsw.py +++ b/gns3server/modules/dynamips/schemas/atmsw.py @@ -264,3 +264,59 @@ ATMSW_DELETE_NIO_SCHEMA = { "additionalProperties": False, "required": ["id", "port"] } + +ATMSW_START_CAPTURE_SCHEMA = { + "$schema": "http://json-schema.org/draft-04/schema#", + "description": "Request validation to start a packet capture on an ATM switch instance port", + "type": "object", + "properties": { + "id": { + "description": "ATM switch instance ID", + "type": "integer" + }, + "port_id": { + "description": "Unique port identifier for the ATM switch instance", + "type": "integer" + }, + "port": { + "description": "Port number", + "type": "integer", + "minimum": 1, + }, + "capture_file_name": { + "description": "Capture file name", + "type": "string", + "minLength": 1, + }, + "data_link_type": { + "description": "PCAP data link type", + "type": "string", + "minLength": 1, + }, + }, + "additionalProperties": False, + "required": ["id", "port_id", "port", "capture_file_name"] +} + +ATMSW_STOP_CAPTURE_SCHEMA = { + "$schema": "http://json-schema.org/draft-04/schema#", + "description": "Request validation to stop a packet capture on an ATM switch instance port", + "type": "object", + "properties": { + "id": { + "description": "ATM switch instance ID", + "type": "integer" + }, + "port_id": { + "description": "Unique port identifier for the ATM switch instance", + "type": "integer" + }, + "port": { + "description": "Port number", + "type": "integer", + "minimum": 1, + }, + }, + "additionalProperties": False, + "required": ["id", "port_id", "port"] +} diff --git a/gns3server/modules/dynamips/schemas/ethhub.py b/gns3server/modules/dynamips/schemas/ethhub.py index 50470bcc..1002a696 100644 --- a/gns3server/modules/dynamips/schemas/ethhub.py +++ b/gns3server/modules/dynamips/schemas/ethhub.py @@ -261,3 +261,59 @@ ETHHUB_DELETE_NIO_SCHEMA = { "additionalProperties": False, "required": ["id", "port"] } + +ETHHUB_START_CAPTURE_SCHEMA = { + "$schema": "http://json-schema.org/draft-04/schema#", + "description": "Request validation to start a packet capture on an Ethernet hub instance port", + "type": "object", + "properties": { + "id": { + "description": "Ethernet hub instance ID", + "type": "integer" + }, + "port_id": { + "description": "Unique port identifier for the Ethernet hub instance", + "type": "integer" + }, + "port": { + "description": "Port number", + "type": "integer", + "minimum": 1, + }, + "capture_file_name": { + "description": "Capture file name", + "type": "string", + "minLength": 1, + }, + "data_link_type": { + "description": "PCAP data link type", + "type": "string", + "minLength": 1, + }, + }, + "additionalProperties": False, + "required": ["id", "port_id", "port", "capture_file_name"] +} + +ETHHUB_STOP_CAPTURE_SCHEMA = { + "$schema": "http://json-schema.org/draft-04/schema#", + "description": "Request validation to stop a packet capture on an Ethernet hub instance port", + "type": "object", + "properties": { + "id": { + "description": "Ethernet hub instance ID", + "type": "integer" + }, + "port_id": { + "description": "Unique port identifier for the Ethernet hub instance", + "type": "integer" + }, + "port": { + "description": "Port number", + "type": "integer", + "minimum": 1, + }, + }, + "additionalProperties": False, + "required": ["id", "port_id", "port"] +} diff --git a/gns3server/modules/dynamips/schemas/ethsw.py b/gns3server/modules/dynamips/schemas/ethsw.py index 92f47b80..aeac7023 100644 --- a/gns3server/modules/dynamips/schemas/ethsw.py +++ b/gns3server/modules/dynamips/schemas/ethsw.py @@ -290,3 +290,59 @@ ETHSW_DELETE_NIO_SCHEMA = { "additionalProperties": False, "required": ["id", "port"] } + +ETHSW_START_CAPTURE_SCHEMA = { + "$schema": "http://json-schema.org/draft-04/schema#", + "description": "Request validation to start a packet capture on an Ethernet switch instance port", + "type": "object", + "properties": { + "id": { + "description": "Ethernet switch instance ID", + "type": "integer" + }, + "port_id": { + "description": "Unique port identifier for the Ethernet switch instance", + "type": "integer" + }, + "port": { + "description": "Port number", + "type": "integer", + "minimum": 1, + }, + "capture_file_name": { + "description": "Capture file name", + "type": "string", + "minLength": 1, + }, + "data_link_type": { + "description": "PCAP data link type", + "type": "string", + "minLength": 1, + }, + }, + "additionalProperties": False, + "required": ["id", "port_id", "port", "capture_file_name"] +} + +ETHSW_STOP_CAPTURE_SCHEMA = { + "$schema": "http://json-schema.org/draft-04/schema#", + "description": "Request validation to stop a packet capture on an Ethernet switch instance port", + "type": "object", + "properties": { + "id": { + "description": "Ethernet switch instance ID", + "type": "integer" + }, + "port_id": { + "description": "Unique port identifier for the Ethernet switch instance", + "type": "integer" + }, + "port": { + "description": "Port number", + "type": "integer", + "minimum": 1, + }, + }, + "additionalProperties": False, + "required": ["id", "port_id", "port"] +} diff --git a/gns3server/modules/dynamips/schemas/frsw.py b/gns3server/modules/dynamips/schemas/frsw.py index b5b6ebdb..835e47a7 100644 --- a/gns3server/modules/dynamips/schemas/frsw.py +++ b/gns3server/modules/dynamips/schemas/frsw.py @@ -264,3 +264,59 @@ FRSW_DELETE_NIO_SCHEMA = { "additionalProperties": False, "required": ["id", "port"] } + +FRSW_START_CAPTURE_SCHEMA = { + "$schema": "http://json-schema.org/draft-04/schema#", + "description": "Request validation to start a packet capture on a Frame relay switch instance port", + "type": "object", + "properties": { + "id": { + "description": "Frame relay switch instance ID", + "type": "integer" + }, + "port_id": { + "description": "Unique port identifier for the Frame relay instance", + "type": "integer" + }, + "port": { + "description": "Port number", + "type": "integer", + "minimum": 1, + }, + "capture_file_name": { + "description": "Capture file name", + "type": "string", + "minLength": 1, + }, + "data_link_type": { + "description": "PCAP data link type", + "type": "string", + "minLength": 1, + }, + }, + "additionalProperties": False, + "required": ["id", "port_id", "port", "capture_file_name"] +} + +FRSW_STOP_CAPTURE_SCHEMA = { + "$schema": "http://json-schema.org/draft-04/schema#", + "description": "Request validation to stop a packet capture on a Frame relay switch instance port", + "type": "object", + "properties": { + "id": { + "description": "Frame relay switch instance ID", + "type": "integer" + }, + "port_id": { + "description": "Unique port identifier for the Frame relay instance", + "type": "integer" + }, + "port": { + "description": "Port number", + "type": "integer", + "minimum": 1, + }, + }, + "additionalProperties": False, + "required": ["id", "port_id", "port"] +}