diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 247925c6..31ab8db6 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -17,7 +17,7 @@ jobs: run: sudo apt-get install doxygen libsnmp-dev python3-pip texlive-latex-recommended texlive-fonts-recommended tex-gyre texlive-latex-extra latexmk - name: Install Python dependencies - run: pip3 install -r ${{github.workspace}}/doc/doc_requirements.txt + run: pip3 install -r ${{github.workspace}}/doc/requirements.txt - name: Show Python dependencies run: pip3 freeze diff --git a/.gitignore b/.gitignore index f783b9bb..524832e6 100644 --- a/.gitignore +++ b/.gitignore @@ -10,6 +10,10 @@ doc/_copied .cproject .project + +# Python files +*env* + # Object files *.o *.ko diff --git a/CHANGELOG.md b/CHANGELOG.md index 922d3254..24ef6cd9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,120 +6,120 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), ## [Unreleased] ## 2021-03-31 -### Changed +**Changed** - Update GSDML file to conformance class B ## 2021-03-24 -### Added +**Added** - Possibility to configure number of ports, without recompiling. ## 2021-03-03 -### Changed +**Changed** - Set thread priority and stack size via configuration ## 2021-02-19 -### Changed +**Changed** - Split options.h into two files. - Simplify configuration ## 2020-02-03 -### Added +**Added** - Improved support for multiple ports ## 2021-01-29 -### Changed +**Changed** - Move remaining Linux sample app files to src/ports/linux ## 2020-01-11 -### Added +**Added** - Support for multiple ports ## 2021-01-05 -### Added +**Added** - Additional API functions for low-level diagnostic handling ## 2020-12-22 -### Changed +**Changed** - Remove link status from configuration ## 2020-12-15 -### Changed +**Changed** - Use Profinet version 2.4 for the GSDML file - Changed default installation path for sample_app on Raspberry Pi ## 2020-12-11 -### Added +**Added** - Runtime data for multiple ports - Functionality to search for scripts in multiple locations for Linux ## 2020-12-07 -### Changed +**Changed** - Rename pnet_set_state() to pnet_set_primary_state() ## 2020-12-01 -### Added +**Added** - Changed informative callbacks to be void-functions. ## 2020-11-30 -### Added +**Added** - SNMP functionality for Linux ## 2020-11-20 -### Added +**Added** - Additional log level FATAL ## 2020-11-19 -### Added +**Added** - SNMP functionality for rt-kernel ## 2020-11-16 -### Added +**Added** - Support for multiple ports in configuration ## 2020-11-10 -### Changed +**Changed** - Remove LLDP TTL from configuration - Remove LLDP chassis ID from configuration ## 2020-11-03 -### Changed +**Changed** - Improve API for adding diagnosis - Use rtlabs-com/osal and rtlabs-com/cmake-tools as submodules ## 2020-10-28 -### Changed +**Changed** - Rename compile time constants for number of slots and subslots ## 2020-09-19 -### Changed +**Changed** - Modified public API for sending alarm ACK. ## 2020-08-24 -### Changed +**Changed** - Renamed configuration members related to I&M data ## 2020-08-18 -### Added +**Added** - Add min_device_interval to the configuration - Use cmake to set configurable build options ## 2020-06-15 -### Added +**Added** - New user callback for LED state change. ## 2020-06-11 -### Added +**Added** - New API function for application to perform a factory reset ## 2020-04-09 -### Added +**Added** - New user callback to indicate reset requests from the IO-controller. ## 2020-04-06 -### Changed +**Changed** - Changed the user API to use a handle to the p-net stack, and to allow user arguments to callbacks. ## 2020-03-27 -### Changed +**Changed** - Read MAC address also from Linux hardware. diff --git a/src/device/pf_cmrpc.c b/src/device/pf_cmrpc.c index 27ff09e8..d5400f42 100644 --- a/src/device/pf_cmrpc.c +++ b/src/device/pf_cmrpc.c @@ -61,6 +61,16 @@ #error "PNET_MAX_SESSION_BUFFER_SIZE must be less than or equal to 65535" #endif +/* Unless negotiated between server and client, a CL-PDU (header (80 bytes) + + * body) should not be larger than MustRecvFragSize (1464 bytes). This means + * that a CL-PDU body should not be larger than 1384 bytes. + * (See DCE 1.1: RPC, p. 578) + */ +#define PF_CMRPC_MUST_RECV_FRAG_SIZE (1464) +#define PF_CMRPC_PDU_HEADER_SIZE (80) +#define PF_CMRPC_MAX_PDU_BODY_SIZE \ + (PF_CMRPC_MUST_RECV_FRAG_SIZE - PF_CMRPC_PDU_HEADER_SIZE) + static const pf_uuid_t implicit_ar = {0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0}}; static const pf_uuid_t uuid_epmap_interface = { @@ -4326,7 +4336,16 @@ static int pf_cmrpc_dce_packet ( p_sess->get_info = get_info; memset (&p_sess->rpc_result, 0, sizeof (p_sess->rpc_result)); - if (rpc_req.flags.fragment == false) + if (rpc_req.length_of_body > PF_CMRPC_MAX_PDU_BODY_SIZE) + { + LOG_ERROR ( + PF_RPC_LOG, + "CMRPC(%d): RPC fragment too large (%hu bytes)." + " Check the conformance of the controller (PLC).\n", + __LINE__, + rpc_req.length_of_body); + } + else if (rpc_req.flags.fragment == false) { /* Incoming message is a request or response contained entirely in one * frame */ @@ -4438,7 +4457,45 @@ static int pf_cmrpc_dce_packet ( /* Decide what to do with incoming message */ /* Enter here _even_if_ an error is already detected because we may need * to generate an error response. */ - if ( + if (rpc_req.length_of_body > PF_CMRPC_MAX_PDU_BODY_SIZE) + { + /* The specifications do not clearly state what the response should + * be in this case. The current best guess is to send a Reject PDU. + */ + + /* Prepare the response */ + rpc_res = rpc_req; + rpc_res.packet_type = PF_RPC_PT_REJECT; + rpc_res.flags.last_fragment = false; + rpc_res.flags.fragment = false; + rpc_res.flags.no_fack = true; + rpc_res.flags.maybe = false; + rpc_res.flags.idempotent = true; + rpc_res.flags.broadcast = false; + rpc_res.flags2.cancel_pending = false; + rpc_res.length_of_body = sizeof (uint32_t); + rpc_res.fragment_nmb = 0; + rpc_res.is_big_endian = p_sess->is_big_endian; + + pf_put_dce_rpc_header ( + &rpc_res, + *p_res_len, + p_res, + &res_pos, + &length_of_body_pos); + + pf_put_uint32 ( + rpc_res.is_big_endian, + PF_RPC_NCA_PROTO_ERROR, + *p_res_len, + p_res, + &res_pos); + + pf_cmrpc_send_once_from_buffer (net, p_sess, p_res, res_pos, "REJECT"); + + p_sess->kill_session = is_new_session; + } + else if ( (rpc_req.flags.fragment == false) || (rpc_req.flags.last_fragment == true)) { diff --git a/src/pf_types.h b/src/pf_types.h index 34b0ff53..5b7e7b32 100644 --- a/src/pf_types.h +++ b/src/pf_types.h @@ -468,6 +468,26 @@ typedef struct pf_rpc_lookup_req uint16_t udpPort; } pf_rpc_lookup_req_t; +typedef enum +{ + PF_RPC_NCA_RPC_VERSION_MISMATCH = 0x1C000008, + PF_RPC_NCA_UNSPEC_REJECT = 0x1C000009, + PF_RPC_NCA_S_BAD_ACTID = 0x1C00000A, + PF_RPC_NCA_WHO_ARE_YOU_FAILED = 0x1C00000B, + PF_RPC_NCA_MANAGER_NOT_ENTERED = 0x1C00000C, + PF_RPC_NCA_UNSUPPORTED_AUTHN_LEVEL = 0x1C00001D, + PF_RPC_NCA_INVALID_CHECKSUM = 0x1C00001F, + PF_RPC_NCA_INVALID_CRC = 0x1C000020, + PF_RPC_NCA_OP_RNG_ERROR = 0x1C010002, + PF_RPC_NCA_UNK_IF = 0x1C010003, + PF_RPC_NCA_WRONG_BOOT_TIME = 0x1C010006, + PF_RPC_NCA_S_YOU_CRASHED = 0x1C010009, + PF_RPC_NCA_PROTO_ERROR = 0x1C01000B, + PF_RPC_NCA_OUT_ARGS_TOO_BIG = 0x1C010013, + PF_RPC_NCA_SERVER_TOO_BUSY = 0x1C010014, + PF_RPC_NCA_UNSUPPORTED_TYPE = 0x1C010017 +} pf_rpc_nca_reject_status_t; + /************************** Block header *************************************/ typedef enum pf_block_type_values