├── .github └── workflows │ └── build.yml ├── .gitignore ├── .php_cs ├── CHANGELOG.md ├── LICENSE ├── README.md ├── composer.json ├── docs ├── Client │ ├── Configuration.md │ ├── General-Usage.md │ ├── Request-Types.md │ └── SNMP-Walk.md └── Server │ └── Trap-Sink.md ├── phpspec.yml ├── phpstan.neon ├── phpunit.xml.dist ├── src └── FreeDSx │ └── Snmp │ ├── Exception │ ├── ConnectionException.php │ ├── EndOfWalkException.php │ ├── InvalidArgumentException.php │ ├── ProtocolException.php │ ├── RediscoveryNeededException.php │ ├── RuntimeException.php │ ├── SecurityModelException.php │ ├── SnmpAuthenticationException.php │ ├── SnmpEncryptionException.php │ ├── SnmpRequestException.php │ └── UnexpectedValueException.php │ ├── Message │ ├── AbstractMessage.php │ ├── AbstractMessageV3.php │ ├── EngineId.php │ ├── ErrorStatus.php │ ├── MessageHeader.php │ ├── Pdu.php │ ├── Request │ │ ├── MessageRequest.php │ │ ├── MessageRequestInterface.php │ │ ├── MessageRequestTrait.php │ │ ├── MessageRequestV1.php │ │ ├── MessageRequestV2.php │ │ └── MessageRequestV3.php │ ├── Response │ │ ├── MessageResponse.php │ │ ├── MessageResponseInterface.php │ │ ├── MessageResponseTrait.php │ │ ├── MessageResponseV1.php │ │ ├── MessageResponseV2.php │ │ └── MessageResponseV3.php │ ├── ScopedPdu.php │ ├── ScopedPduRequest.php │ ├── ScopedPduResponse.php │ └── Security │ │ ├── SecurityParametersInterface.php │ │ └── UsmSecurityParameters.php │ ├── Module │ ├── Authentication │ │ ├── AuthenticationModule.php │ │ └── AuthenticationModuleInterface.php │ ├── Privacy │ │ ├── AESPrivacyModule.php │ │ ├── DES3PrivacyModule.php │ │ ├── DESPrivacyModule.php │ │ ├── DESPrivacyTrait.php │ │ ├── PrivacyModuleInterface.php │ │ └── PrivacyTrait.php │ └── SecurityModel │ │ ├── SecurityModelModuleInterface.php │ │ ├── UserSecurityModelModule.php │ │ └── Usm │ │ ├── TimeSync.php │ │ └── UsmUser.php │ ├── Oid.php │ ├── OidList.php │ ├── OidValues.php │ ├── Protocol │ ├── ClientProtocolHandler.php │ ├── Factory │ │ ├── AuthenticationModuleFactory.php │ │ ├── OidValueFactory.php │ │ ├── PrivacyModuleFactory.php │ │ ├── RequestFactory.php │ │ ├── ResponseFactory.php │ │ ├── SecurityModelModuleFactory.php │ │ └── SecurityParametersFactory.php │ ├── IdGeneratorTrait.php │ ├── ProtocolElementInterface.php │ ├── ProtocolTrait.php │ ├── SnmpEncoder.php │ └── TrapProtocolHandler.php │ ├── Request │ ├── GetBulkRequest.php │ ├── GetNextRequest.php │ ├── GetRequest.php │ ├── InformRequest.php │ ├── RequestInterface.php │ ├── RequestTrait.php │ ├── SetRequest.php │ ├── TrapTrait.php │ ├── TrapV1Request.php │ └── TrapV2Request.php │ ├── Requests.php │ ├── Response │ ├── ReportResponse.php │ ├── Response.php │ └── ResponseInterface.php │ ├── Server │ └── ServerRunner │ │ ├── ServerRunnerInterface.php │ │ └── TrapServerRunner.php │ ├── SnmpClient.php │ ├── SnmpWalk.php │ ├── Trap │ ├── TrapContext.php │ └── TrapListenerInterface.php │ ├── TrapSink.php │ └── Value │ ├── AbstractValue.php │ ├── ArbitraryValue.php │ ├── BigCounterValue.php │ ├── CounterValue.php │ ├── IntegerValue.php │ ├── IpAddressValue.php │ ├── OidValue.php │ ├── StringValue.php │ ├── TimeTicksValue.php │ └── UnsignedIntegerValue.php └── tests ├── bin └── trapsink.php ├── integration └── FreeDSx │ └── Snmp │ ├── SnmpClientTest.php │ ├── SnmpWalkTest.php │ ├── TestCase.php │ └── TrapSinkTest.php ├── resources └── snmpd.conf └── spec └── FreeDSx └── Snmp ├── Exception ├── ConnectionExceptionSpec.php ├── InvalidArgumentExceptionSpec.php ├── ProtocolExceptionSpec.php ├── RediscoveryNeededExceptionSpec.php ├── RuntimeExceptionSpec.php ├── SecurityModelExceptionSpec.php ├── SnmpAuthenticationExceptionSpec.php ├── SnmpEncryptionExceptionSpec.php ├── SnmpRequestExceptionSpec.php └── UnexpectedValueExceptionSpec.php ├── Message ├── EngineIdSpec.php ├── MessageHeaderSpec.php ├── PduSpec.php ├── Request │ ├── MessageRequestSpec.php │ ├── MessageRequestV1Spec.php │ ├── MessageRequestV2Spec.php │ └── MessageRequestV3Spec.php ├── Response │ ├── MessageResponseSpec.php │ ├── MessageResponseV1Spec.php │ ├── MessageResponseV2Spec.php │ └── MessageResponseV3Spec.php ├── ScopedPduRequestSpec.php ├── ScopedPduResponseSpec.php └── Security │ └── UsmSecurityParametersSpec.php ├── Module ├── Authentication │ └── AuthenticationModuleSpec.php ├── Privacy │ ├── AESPrivacyModuleSpec.php │ ├── DES3PrivacyModuleSpec.php │ └── DESPrivacyModuleSpec.php └── SecurityModel │ ├── UserSecurityModelModuleSpec.php │ └── Usm │ ├── TimeSyncSpec.php │ └── UsmUserSpec.php ├── OidListSpec.php ├── OidSpec.php ├── OidValuesSpec.php ├── Protocol ├── ClientProtocolHandlerSpec.php ├── Factory │ ├── AuthenticationModuleFactorySpec.php │ ├── OidValueFactorySpec.php │ ├── PrivacyModuleFactorySpec.php │ ├── RequestFactorySpec.php │ ├── ResponseFactorySpec.php │ ├── SecurityModelModuleFactorySpec.php │ └── SecurityParametersFactorySpec.php ├── SnmpEncoderSpec.php └── TrapProtocolHandlerSpec.php ├── Request ├── GetBulkRequestSpec.php ├── GetNextRequestSpec.php ├── GetRequestSpec.php ├── InformRequestSpec.php ├── SetRequestSpec.php ├── TrapV1RequestSpec.php └── TrapV2RequestSpec.php ├── RequestsSpec.php ├── Response ├── ReportResponseSpec.php └── ResponseSpec.php ├── Server └── ServerRunner │ └── TrapServerRunnerSpec.php ├── SnmpClientSpec.php ├── SnmpWalkSpec.php ├── Trap └── TrapContextSpec.php ├── TrapSinkSpec.php └── Value ├── ArbitraryValueSpec.php ├── BigCounterValueSpec.php ├── CounterValueSpec.php ├── IntegerValueSpec.php ├── IpAddressValueSpec.php ├── OidValueSpec.php ├── StringValueSpec.php ├── TimeTicksValueSpec.php └── UnsignedIntegerValueSpec.php /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: Build 2 | on: [push, pull_request] 3 | jobs: 4 | static-analysis: 5 | runs-on: ubuntu-latest 6 | name: Static Analysis 7 | steps: 8 | - name: Checkout 9 | uses: actions/checkout@v2 10 | 11 | - name: Setup PHP 12 | uses: shivammathur/setup-php@v2 13 | with: 14 | php-version: '7.1' 15 | tools: composer:v2 16 | 17 | - name: Get Composer Cache Directory 18 | id: composer-cache 19 | run: echo "::set-output name=dir::$(composer config cache-files-dir)" 20 | 21 | - name: Install Composer Dependencies 22 | run: composer install --no-progress --no-suggest --prefer-dist --optimize-autoloader 23 | 24 | - name: Cache Dependencies 25 | uses: actions/cache@v1 26 | with: 27 | path: ${{ steps.composer-cache.outputs.dir }} 28 | key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} 29 | restore-keys: ${{ runner.os }}-composer- 30 | 31 | - name: Run Static Analysis 32 | run: composer analyse 33 | 34 | tests: 35 | runs-on: ${{ matrix.operating-system }} 36 | strategy: 37 | fail-fast: false 38 | matrix: 39 | operating-system: [ubuntu-latest, windows-latest] 40 | php-versions: ['7.1', '7.2', '7.3', '7.4', '8.0', '8.1', '8.2'] 41 | name: Unit Tests for PHP ${{ matrix.php-versions }} on ${{ matrix.operating-system }} 42 | steps: 43 | - name: Checkout 44 | uses: actions/checkout@v2 45 | 46 | - name: Setup PHP 47 | uses: shivammathur/setup-php@v2 48 | with: 49 | php-version: ${{ matrix.php-versions }} 50 | tools: composer:v2 51 | coverage: pcov 52 | 53 | - name: Start SNMP Container 54 | if: ${{ matrix.operating-system == 'ubuntu-latest' }} 55 | run: | 56 | docker run \ 57 | --name snmpd \ 58 | -d \ 59 | -p 10161:161/udp \ 60 | -v "$(pwd)/tests/resources/snmpd.conf":/etc/snmpd/snmpd.custom.conf \ 61 | polinux/snmpd \ 62 | -c /etc/snmpd/snmpd.custom.conf 63 | 64 | - name: Get Composer Cache Directory 65 | id: composer-cache 66 | run: echo "::set-output name=dir::$(composer config cache-files-dir)" 67 | 68 | - name: Install Composer dependencies 69 | if: ${{ matrix.php-versions != '8.1' }} 70 | run: composer install --no-progress --no-suggest --prefer-dist --optimize-autoloader 71 | 72 | - name: Install Composer dependencies (8.1) 73 | if: ${{ matrix.php-versions == '8.1' }} 74 | run: composer install --no-progress --no-suggest --prefer-dist --optimize-autoloader --ignore-platform-reqs 75 | 76 | - name: Cache dependencies 77 | uses: actions/cache@v1 78 | with: 79 | path: ${{ steps.composer-cache.outputs.dir }} 80 | key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} 81 | restore-keys: ${{ runner.os }}-composer- 82 | 83 | - name: Run Unit Tests 84 | run: composer test-spec 85 | 86 | - name: Run Integration Tests 87 | if: ${{ matrix.operating-system == 'ubuntu-latest' }} 88 | run: composer test-integration 89 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | composer.lock 2 | composer.phar 3 | vendor/ 4 | .phpunit.*.cache 5 | -------------------------------------------------------------------------------- /.php_cs: -------------------------------------------------------------------------------- 1 | exclude('tests') 4 | ->notPath('src/Symfony/Component/Translation/Tests/fixtures/resources.php') 5 | ->in(__DIR__.'/src') 6 | ; 7 | 8 | return PhpCsFixer\Config::create() 9 | ->setRules([ 10 | '@PSR2' => true, 11 | 'array_syntax' => ['syntax' => 'short'], 12 | ]) 13 | ->setFinder($finder) 14 | ; 15 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | CHANGELOG 2 | ========= 3 | 4 | 0.5.0 (2022-01-29) 5 | ------------------ 6 | * Many static analysis fixes. The PhpStan level is now set to max. 7 | * Integration tests added for the client and the trap sink. 8 | * Fix potential issues with inform requests where the port is not properly interpreted. 9 | 10 | 0.4.2 (2021-12-11) 11 | ------------------ 12 | * Support PHP 8.0 / 8.1. 13 | * Add a method to close the underlying socket connection on the client. 14 | 15 | 0.4.1 (2021-11-25) 16 | ------------------ 17 | * Fix a bug with v3 authentication with certain devices (missing contextEngineId). 18 | * PHPStan introduced for static analysis (@simPod). 19 | 20 | 0.4.0 (2019-03-11) 21 | ------------------ 22 | * Update the ASN.1 / Socket versions for performance / memory improvements. 23 | * The SnmpWalk helper will now default to sending getBulk requests if the SNMP version is 2 or 3. 24 | * Added a getOid() method to SnmpWalk as an alias of next(). 25 | * Allow a leading dot "." on OIDs being sent. It will strip the dot when encoding. 26 | 27 | 0.3.2 (2018-10-02) 28 | ------------------ 29 | * Fix privacy handling in the trap sink. 30 | * Be more defensive about how exceptions are handled in the trap sink. 31 | * Throw a more descriptive message if a PDU cannot be assembled after being decrypted. 32 | * Update the privacy interface to be consistent. 33 | * Add more specs around USM response types and privacy in general. 34 | 35 | 0.3.1 (2018-09-16) 36 | ------------------ 37 | * Fix handling of 64-bit counters (BigCounter). Suggest the GMP extension. 38 | 39 | 0.3.0 (2018-09-15) 40 | ------------------ 41 | * Provide a trap sink class to act as a server and collect incoming traps. 42 | * Add better engine ID handling / the ability to generate and parse engine IDs. 43 | * SNMP v3 traps are now sent using a locally generated engine ID / time. 44 | * The context_engine_id option has been renamed to engine_id. 45 | * Correct the order of the EngineId check on incoming messages. 46 | * Validate the time window on incoming messages. 47 | * Update the cached time, if applicable, based off current remote engine time. 48 | 49 | 0.2.0 (2018-08-19) 50 | ------------------ 51 | * Provide an SNMP walker helper class with a simple API. 52 | * Add better USM time synchronization. 53 | * Authenticate incoming messages for USM. 54 | * Generate proper IDs for SNMP v3 PDUs. 55 | * Validate the ID number that was received. 56 | * Restrict SNMP versions to only the PDUs that they support. 57 | * Provide better USM related error messages. 58 | * Throw an SnmpRequestException on unhandled Report PDUs. 59 | * Make the SNMP Message nullable for SnmpRequestExceptions. 60 | 61 | 0.1.0 (2018-08-04) 62 | ------------------ 63 | * Tagging initial release. 64 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Chad Sikorra 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # FreeDSx SNMP ![](https://github.com/FreeDSx/SNMP/workflows/Build/badge.svg) 2 | FreeDSx SNMP is a pure PHP SNMP library. It has no requirement on the core PHP SNMP extension. It implements SNMP 3 | client functionality described in [RFC 3412](https://tools.ietf.org/html/rfc3412) / [RFC 3416](https://tools.ietf.org/html/rfc3416) / [RFC 3414](https://tools.ietf.org/html/rfc3414). 4 | It also includes functionality described in various other RFCs, such as SHA2 authentication ([RFC 7860](https://tools.ietf.org/html/rfc7860)) and strong encryption 5 | mechanisms ([3DES](https://tools.ietf.org/html/draft-reeder-snmpv3-usm-3desede-00) / [AES-192-256](https://tools.ietf.org/html/draft-blumenthal-aes-usm-04)). 6 | Some main features include: 7 | 8 | * SNMP version 1, 2, and 3 support. 9 | * Supports all authentication mechanisms (md5, sha1, sha224, sha256, sha384, sha512). 10 | * Supports all privacy encryption mechanisms (des, 3des, aes128, aes192, aes256). 11 | * Supports all client request types (Get, GetNext, GetBulk, Set, Inform, TrapV1, TrapV2). 12 | * Supports sending SNMPv1 and SNMPv2 traps (including inform requests). 13 | * Trap Sink server for receiving and processing incoming traps. 14 | 15 | The OpenSSL extension is required for privacy / encryption support. The GMP extension is required for 64-bit counters (BigCounter). 16 | 17 | # Documentation 18 | 19 | * [SNMP Client](/docs/Client) 20 | * [Configuration](/docs/Client/Configuration.md) 21 | * [General Usage](/docs/Client/General-Usage.md) 22 | * [Request Types](/docs/Client/Request-Types.md) 23 | * [SNMP Walk](/docs/Client/SNMP-Walk.md) 24 | * [SNMP Server](/docs/Server) 25 | * [Trap Sink](/docs/Server/Trap-Sink.md) 26 | 27 | # Getting Started 28 | 29 | Install via composer: 30 | 31 | ```bash 32 | composer require freedsx/snmp 33 | ``` 34 | 35 | Use the SnmpClient class and the helper classes: 36 | 37 | ```php 38 | use FreeDSx\Snmp\SnmpClient; 39 | 40 | $snmp = new SnmpClient([ 41 | 'host' => 'servername', 42 | 'version' => 2, 43 | 'community' => 'secret', 44 | ]); 45 | 46 | # Get a specific OID value as a string... 47 | echo $snmp->getValue('1.3.6.1.2.1').PHP_EOL; 48 | 49 | # Get a specific OID as an object... 50 | $oid = $snmp->getOid('1.3.6.1.2.1'); 51 | var_dump($oid); 52 | 53 | echo sprintf("%s == %s", $oid->getOid(), (string) $oid->getValue()).PHP_EOL; 54 | 55 | # Get multiple OIDs and iterate through them as needed... 56 | $oids = $snmp->get('1.3.6.1.2.1.1.1', '1.3.6.1.2.1.1.3', '1.3.6.1.2.1.1.5'); 57 | 58 | foreach($oids as $oid) { 59 | echo sprintf("%s == %s", $oid->getOid(), (string) $oid->getValue()).PHP_EOL; 60 | } 61 | 62 | # Using the SnmpClient, get the helper class for an SNMP walk... 63 | $walk = $snmp->walk(); 64 | 65 | # Keep the walk going until there are no more OIDs left 66 | while($walk->hasOids()) { 67 | try { 68 | # Get the next OID in the walk 69 | $oid = $walk->next(); 70 | echo sprintf("%s = %s", $oid->getOid(), $oid->getValue()).PHP_EOL; 71 | } catch (\Exception $e) { 72 | # If we had an issue, display it here (network timeout, etc) 73 | echo "Unable to retrieve OID. ".$e->getMessage().PHP_EOL; 74 | } 75 | } 76 | 77 | echo sprintf("Walked a total of %s OIDs.", $walk->count()).PHP_EOL; 78 | ``` 79 | 80 | For a complete configuration reference please see the [configuration doc](/docs/Client/Configuration.md). There are also 81 | SNMP v3 examples for [NoAuthNoPriv](/docs/Client/General-Usage.md#noauthnopriv), [AuthNoPriv](/docs/Client/General-Usage.md#authnopriv), and [AuthPriv](/docs/Client/General-Usage.md#authpriv) 82 | in the [general usage doc](/docs/Client/General-Usage.md). 83 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "freedsx/snmp", 3 | "description": "A Pure PHP SNMP Library", 4 | "homepage": "https://github.com/FreeDSx/SNMP", 5 | "keywords": [ 6 | "SNMP" 7 | ], 8 | "license": "MIT", 9 | "authors": [ 10 | { 11 | "name": "Chad Sikorra", 12 | "email": "Chad.Sikorra@gmail.com" 13 | } 14 | ], 15 | "require": { 16 | "php": ">=7.1", 17 | "freedsx/asn1": ">=0.4.0", 18 | "freedsx/socket": ">=0.3.0" 19 | }, 20 | "require-dev": { 21 | "friendsofphp/php-cs-fixer": "^2", 22 | "phpspec/phpspec": "^5.1|^6.1|^7.1", 23 | "phpstan/phpstan": "^0.11|^0.12", 24 | "phpunit/phpunit": "^7.5|^8.5|^9.5", 25 | "symfony/process": "^3|^4|^5" 26 | }, 27 | "suggest": { 28 | "ext-openssl": "For SNMP privacy encryption support.", 29 | "ext-gmp": "Needed for counter64 bigint SNMP values." 30 | }, 31 | "autoload": { 32 | "psr-4": {"FreeDSx\\Snmp\\": "src/FreeDSx/Snmp"} 33 | }, 34 | "autoload-dev": { 35 | "psr-4": { 36 | "integration\\FreeDSx\\Snmp\\": "tests/integration/FreeDSx/Snmp", 37 | "spec\\FreeDSx\\Snmp\\": "tests/spec/FreeDSx/Snmp" 38 | } 39 | }, 40 | "config": { 41 | "sort-packages": true 42 | }, 43 | "scripts": { 44 | "cs-fix": [ 45 | "@putenv PHP_CS_FIXER_IGNORE_ENV=1", 46 | "php-cs-fixer fix src/ --rules=@PSR2" 47 | ], 48 | "analyse": [ 49 | "phpstan analyse" 50 | ], 51 | "test-spec": [ 52 | "phpspec run --format=pretty --no-interaction" 53 | ], 54 | "test-integration": [ 55 | "phpunit --testsuite integration" 56 | ] 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /phpspec.yml: -------------------------------------------------------------------------------- 1 | suites: 2 | default: 3 | spec_path: tests/ 4 | src_path: src/ 5 | -------------------------------------------------------------------------------- /phpstan.neon: -------------------------------------------------------------------------------- 1 | parameters: 2 | checkMissingIterableValueType: false 3 | treatPhpDocTypesAsCertain: false 4 | checkGenericClassInNonGenericObjectType: false 5 | level: max 6 | paths: 7 | - %currentWorkingDirectory%/src 8 | ignoreErrors: 9 | - '#Unsafe usage of new static\(\).#' 10 | - '#function call_user_func expects callable\(\)\: mixed#' 11 | reportUnmatchedIgnoredErrors: false 12 | -------------------------------------------------------------------------------- /phpunit.xml.dist: -------------------------------------------------------------------------------- 1 | 2 | 14 | 15 | 16 | 17 | src 18 | 19 | 20 | 21 | 22 | 23 | ./tests/integration 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /src/FreeDSx/Snmp/Exception/ConnectionException.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | 11 | namespace FreeDSx\Snmp\Exception; 12 | 13 | /** 14 | * Represents an SNMP connection exception. 15 | * 16 | * @author Chad Sikorra 17 | */ 18 | class ConnectionException extends \Exception 19 | { 20 | } 21 | -------------------------------------------------------------------------------- /src/FreeDSx/Snmp/Exception/EndOfWalkException.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | 11 | namespace FreeDSx\Snmp\Exception; 12 | 13 | /** 14 | * Thrown if at the end of a SNMP walk but the next OID was requested. 15 | * 16 | * @author Chad Sikorra 17 | */ 18 | class EndOfWalkException extends \Exception 19 | { 20 | } 21 | -------------------------------------------------------------------------------- /src/FreeDSx/Snmp/Exception/InvalidArgumentException.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | 11 | namespace FreeDSx\Snmp\Exception; 12 | 13 | /** 14 | * Represents an invalid argument exception. 15 | * 16 | * @author Chad Sikorra 17 | */ 18 | class InvalidArgumentException extends \InvalidArgumentException 19 | { 20 | } 21 | -------------------------------------------------------------------------------- /src/FreeDSx/Snmp/Exception/ProtocolException.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | 11 | namespace FreeDSx\Snmp\Exception; 12 | 13 | /** 14 | * Used to represent SNMP protocol specific issues. 15 | * 16 | * @author Chad Sikorra 17 | */ 18 | class ProtocolException extends \Exception 19 | { 20 | } 21 | -------------------------------------------------------------------------------- /src/FreeDSx/Snmp/Exception/RediscoveryNeededException.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | 11 | namespace FreeDSx\Snmp\Exception; 12 | 13 | /** 14 | * Thrown from the security model module if a rediscovery is needed at a point other than the initial discovery check. 15 | * 16 | * @author Chad Sikorra 17 | */ 18 | class RediscoveryNeededException extends SnmpRequestException 19 | { 20 | } 21 | -------------------------------------------------------------------------------- /src/FreeDSx/Snmp/Exception/RuntimeException.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | 11 | namespace FreeDSx\Snmp\Exception; 12 | 13 | /** 14 | * Represents a runtime exception. 15 | * 16 | * @author Chad Sikorra 17 | */ 18 | class RuntimeException extends \RuntimeException 19 | { 20 | } 21 | -------------------------------------------------------------------------------- /src/FreeDSx/Snmp/Exception/SecurityModelException.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | 11 | namespace FreeDSx\Snmp\Exception; 12 | 13 | /** 14 | * Thrown from the security model module for issues they encounter. 15 | * 16 | * @author Chad Sikorra 17 | */ 18 | class SecurityModelException extends \Exception 19 | { 20 | } 21 | -------------------------------------------------------------------------------- /src/FreeDSx/Snmp/Exception/SnmpAuthenticationException.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | 11 | namespace FreeDSx\Snmp\Exception; 12 | 13 | /** 14 | * Thrown on SNMP authentication related issues. 15 | * 16 | * @author Chad Sikorra 17 | */ 18 | class SnmpAuthenticationException extends \Exception 19 | { 20 | } 21 | -------------------------------------------------------------------------------- /src/FreeDSx/Snmp/Exception/SnmpEncryptionException.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | 11 | namespace FreeDSx\Snmp\Exception; 12 | 13 | /** 14 | * Thrown on SNMP encryption related issues. 15 | * 16 | * @author Chad Sikorra 17 | */ 18 | class SnmpEncryptionException extends \Exception 19 | { 20 | } 21 | -------------------------------------------------------------------------------- /src/FreeDSx/Snmp/Exception/UnexpectedValueException.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | 11 | namespace FreeDSx\Snmp\Exception; 12 | 13 | /** 14 | * Represents an unexpected value exception. 15 | * 16 | * @author Chad Sikorra 17 | */ 18 | class UnexpectedValueException extends \UnexpectedValueException 19 | { 20 | } 21 | -------------------------------------------------------------------------------- /src/FreeDSx/Snmp/Message/AbstractMessage.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | 11 | namespace FreeDSx\Snmp\Message; 12 | 13 | use FreeDSx\Asn1\Asn1; 14 | use FreeDSx\Asn1\Type\AbstractType; 15 | use FreeDSx\Asn1\Type\IntegerType; 16 | use FreeDSx\Asn1\Type\OctetStringType; 17 | use FreeDSx\Asn1\Type\SequenceType; 18 | use FreeDSx\Snmp\Exception\ProtocolException; 19 | use FreeDSx\Socket\PduInterface; 20 | 21 | /** 22 | * Represents a base for an SNMPv1/v2 Message. 23 | * 24 | * Message ::= 25 | * SEQUENCE { 26 | * version -- version-1 for this RFC 27 | * INTEGER { 28 | * version-1(0) 29 | * }, 30 | * 31 | * community -- community name 32 | * OCTET STRING, 33 | * 34 | * data -- e.g., PDUs if trivial 35 | * ANY -- authentication is being used 36 | * } 37 | * 38 | * @author Chad Sikorra 39 | */ 40 | abstract class AbstractMessage implements PduInterface 41 | { 42 | protected const VERSION = null; 43 | 44 | /** 45 | * @var string 46 | */ 47 | protected $community; 48 | 49 | /** 50 | * @var Pdu 51 | */ 52 | protected $pdu; 53 | 54 | /** 55 | * @param string $community 56 | */ 57 | public function __construct(string $community) 58 | { 59 | $this->community = $community; 60 | } 61 | 62 | public function getCommunity() : string 63 | { 64 | return $this->community; 65 | } 66 | 67 | /** 68 | * @return int 69 | */ 70 | public function getVersion() : int 71 | { 72 | return static::VERSION; 73 | } 74 | 75 | /** 76 | * {@inheritdoc} 77 | */ 78 | public function toAsn1() : AbstractType 79 | { 80 | return Asn1::sequence( 81 | Asn1::integer(static::VERSION), 82 | Asn1::octetString($this->community), 83 | $this->pdu->toAsn1() 84 | ); 85 | } 86 | 87 | /** 88 | * @param AbstractType $asn1 89 | * @return string 90 | * @throws ProtocolException 91 | */ 92 | protected static function parseCommunity(AbstractType $asn1) 93 | { 94 | if (!($asn1 instanceof SequenceType && count($asn1->getChildren()) === 3)) { 95 | throw new ProtocolException('The SNMP message must be a sequence with at least 3 elements.'); 96 | } 97 | $version = $asn1->getChild(0); 98 | if (!($version instanceof IntegerType && $version->getValue() === static::VERSION)) { 99 | throw new ProtocolException(sprintf( 100 | 'Expected SNMP version %s, got %s.', 101 | static::VERSION, 102 | is_null($version) ? 0 : $version->getValue() 103 | )); 104 | } 105 | $community = $asn1->getChild(1); 106 | if (!$community instanceof OctetStringType) { 107 | throw new ProtocolException(sprintf( 108 | 'Expected an octet string type for the community, got %s.', 109 | $community ? get_class($community) : 'null' 110 | )); 111 | } 112 | 113 | return $community->getValue(); 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /src/FreeDSx/Snmp/Message/ErrorStatus.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | 11 | namespace FreeDSx\Snmp\Message; 12 | 13 | /** 14 | * Possible error status values. RFC 3416 Section 3. 15 | * 16 | * @author Chad Sikorra 17 | */ 18 | class ErrorStatus 19 | { 20 | public const NO_ERROR = 0; 21 | 22 | public const TOO_BIG = 1; 23 | 24 | public const NO_SUCH_NAME = 2; 25 | 26 | public const BAD_VALUE = 3; 27 | 28 | public const READ_ONLY = 4; 29 | 30 | public const GEN_ERROR = 5; 31 | 32 | public const NO_ACCESS = 6; 33 | 34 | public const WRONG_TYPE = 7; 35 | 36 | public const WRONG_LENGTH = 8; 37 | 38 | public const WRONG_ENCODING = 9; 39 | 40 | public const WRONG_VALUE = 10; 41 | 42 | public const NO_CREATION = 11; 43 | 44 | public const INCONSISTENT_VALUE = 12; 45 | 46 | public const RESOURCE_UNAVAILABLE = 13; 47 | 48 | public const COMMIT_FAILED = 14; 49 | 50 | public const UNDO_FAILED = 15; 51 | 52 | public const AUTHORIZATION_ERROR = 16; 53 | 54 | public const NOT_WRITABLE = 17; 55 | 56 | public const INCONSISTENT_NAME = 18; 57 | } 58 | -------------------------------------------------------------------------------- /src/FreeDSx/Snmp/Message/Request/MessageRequest.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | 11 | namespace FreeDSx\Snmp\Message\Request; 12 | 13 | use FreeDSx\Asn1\Type\AbstractType; 14 | use FreeDSx\Asn1\Type\IntegerType; 15 | use FreeDSx\Asn1\Type\SequenceType; 16 | use FreeDSx\Snmp\Exception\ProtocolException; 17 | use FreeDSx\Snmp\Message\AbstractMessage; 18 | use FreeDSx\Socket\PduInterface; 19 | 20 | /** 21 | * Basically used as a factory from the message queue to determine what message request to instantiate. 22 | * 23 | * @author Chad Sikorra 24 | */ 25 | class MessageRequest extends AbstractMessage implements PduInterface 26 | { 27 | /** 28 | * @var array 29 | */ 30 | protected static $map = [ 31 | 0 => MessageRequestV1::class, 32 | 1 => MessageRequestV2::class, 33 | 3 => MessageRequestV3::class, 34 | ]; 35 | 36 | public function __construct() 37 | { 38 | parent::__construct(''); 39 | } 40 | 41 | /** 42 | * {@inheritdoc} 43 | */ 44 | public static function fromAsn1(AbstractType $asn1) 45 | { 46 | if (!($asn1 instanceof SequenceType && $asn1->getChild(0) instanceof IntegerType)) { 47 | throw new ProtocolException('The SNMP message is malformed.'); 48 | } 49 | $version = $asn1->getChild(0)->getValue(); 50 | 51 | if (!isset(self::$map[$version])) { 52 | throw new ProtocolException(sprintf( 53 | 'The SNMP version %s is not supported.', 54 | $version 55 | )); 56 | } 57 | 58 | return \call_user_func(self::$map[$version].'::fromAsn1', $asn1); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/FreeDSx/Snmp/Message/Request/MessageRequestInterface.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | 11 | namespace FreeDSx\Snmp\Message\Request; 12 | 13 | use FreeDSx\Snmp\Message\Pdu; 14 | use FreeDSx\Socket\PduInterface; 15 | 16 | /** 17 | * Interface for an SNMP message used in a request. 18 | * 19 | * @author Chad Sikorra 20 | */ 21 | interface MessageRequestInterface extends PduInterface 22 | { 23 | /** 24 | * @return int 25 | */ 26 | public function getVersion() : int; 27 | 28 | /** 29 | * @return Pdu 30 | */ 31 | public function getRequest() : Pdu; 32 | 33 | /** 34 | * @param Pdu $request 35 | * @return $this 36 | */ 37 | public function setRequest(Pdu $request); 38 | } 39 | -------------------------------------------------------------------------------- /src/FreeDSx/Snmp/Message/Request/MessageRequestTrait.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | 11 | namespace FreeDSx\Snmp\Message\Request; 12 | 13 | use FreeDSx\Snmp\Message\Pdu; 14 | 15 | /** 16 | * Exposes the request PDU. 17 | * 18 | * @author Chad Sikorra 19 | */ 20 | trait MessageRequestTrait 21 | { 22 | /** 23 | * @return Pdu 24 | */ 25 | public function getRequest(): Pdu 26 | { 27 | return $this->pdu; 28 | } 29 | 30 | /** 31 | * @param Pdu $request 32 | * @return $this 33 | */ 34 | public function setRequest(Pdu $request) 35 | { 36 | $this->pdu = $request; 37 | 38 | return $this; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/FreeDSx/Snmp/Message/Request/MessageRequestV1.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | 11 | namespace FreeDSx\Snmp\Message\Request; 12 | 13 | use FreeDSx\Asn1\Type\AbstractType; 14 | use FreeDSx\Snmp\Exception\ProtocolException; 15 | use FreeDSx\Snmp\Message\AbstractMessage; 16 | use FreeDSx\Snmp\Message\Pdu; 17 | use FreeDSx\Snmp\Protocol\Factory\RequestFactory; 18 | 19 | /** 20 | * Represents a SNMPv1 Message Request. 21 | * 22 | * @author Chad Sikorra 23 | */ 24 | class MessageRequestV1 extends AbstractMessage implements MessageRequestInterface 25 | { 26 | use MessageRequestTrait; 27 | 28 | protected const VERSION = 0; 29 | 30 | /** 31 | * @param string $community 32 | * @param Pdu $request 33 | */ 34 | public function __construct( 35 | string $community, 36 | Pdu $request 37 | ) { 38 | $this->pdu = $request; 39 | parent::__construct($community); 40 | } 41 | 42 | /** 43 | * @param string $community 44 | * @return $this 45 | */ 46 | public function setCommunity(string $community): self 47 | { 48 | $this->community = $community; 49 | 50 | return $this; 51 | } 52 | 53 | /** 54 | * @param AbstractType $asn1 55 | * @return MessageRequestV1 56 | * @throws \FreeDSx\Snmp\Exception\ProtocolException 57 | */ 58 | public static function fromAsn1(AbstractType $asn1) 59 | { 60 | $pdu = $asn1->getChild(2); 61 | if ($pdu === null) { 62 | throw new ProtocolException('The request is malformed'); 63 | } 64 | 65 | return new static( 66 | static::parseCommunity($asn1), 67 | RequestFactory::get($pdu) 68 | ); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/FreeDSx/Snmp/Message/Request/MessageRequestV2.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | 11 | namespace FreeDSx\Snmp\Message\Request; 12 | 13 | use FreeDSx\Asn1\Type\AbstractType; 14 | use FreeDSx\Snmp\Exception\ProtocolException; 15 | use FreeDSx\Snmp\Message\AbstractMessage; 16 | use FreeDSx\Snmp\Message\Pdu; 17 | use FreeDSx\Snmp\Protocol\Factory\RequestFactory; 18 | 19 | /** 20 | * Represents a SNMPv2 Message Request. 21 | * 22 | * @author Chad Sikorra 23 | */ 24 | class MessageRequestV2 extends AbstractMessage implements MessageRequestInterface 25 | { 26 | use MessageRequestTrait; 27 | 28 | protected const VERSION = 1; 29 | 30 | /** 31 | * @param string $community 32 | * @param Pdu $request 33 | */ 34 | public function __construct( 35 | string $community, 36 | Pdu $request 37 | ) { 38 | $this->pdu = $request; 39 | parent::__construct($community); 40 | } 41 | 42 | /** 43 | * @param string $community 44 | * @return $this 45 | */ 46 | public function setCommunity(string $community): self 47 | { 48 | $this->community = $community; 49 | 50 | return $this; 51 | } 52 | 53 | /** 54 | * {@inheritdoc} 55 | * @throws ProtocolException 56 | */ 57 | public static function fromAsn1(AbstractType $asn1) 58 | { 59 | $pdu = $asn1->getChild(2); 60 | if ($pdu === null) { 61 | throw new ProtocolException('The request is malformed'); 62 | } 63 | 64 | return new static( 65 | static::parseCommunity($asn1), 66 | RequestFactory::get($pdu) 67 | ); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/FreeDSx/Snmp/Message/Response/MessageResponse.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | 11 | namespace FreeDSx\Snmp\Message\Response; 12 | 13 | use FreeDSx\Asn1\Type\AbstractType; 14 | use FreeDSx\Asn1\Type\IntegerType; 15 | use FreeDSx\Asn1\Type\SequenceType; 16 | use FreeDSx\Snmp\Exception\ProtocolException; 17 | use FreeDSx\Snmp\Message\AbstractMessage; 18 | use FreeDSx\Socket\PduInterface; 19 | 20 | /** 21 | * Basically used as a factory from the message queue to determine what message response to instantiate. 22 | * 23 | * @author Chad Sikorra 24 | */ 25 | class MessageResponse extends AbstractMessage implements PduInterface 26 | { 27 | /** 28 | * @var array 29 | */ 30 | protected static $map = [ 31 | 0 => MessageResponseV1::class, 32 | 1 => MessageResponseV2::class, 33 | 3 => MessageResponseV3::class, 34 | ]; 35 | 36 | public function __construct() 37 | { 38 | parent::__construct(''); 39 | } 40 | 41 | /** 42 | * @param int $version 43 | * @param MessageResponseInterface $response 44 | */ 45 | public static function setConstructor(int $version, MessageResponseInterface $response) : void 46 | { 47 | self::$map[$version] = get_class($response); 48 | } 49 | 50 | /** 51 | * {@inheritdoc} 52 | */ 53 | public static function fromAsn1(AbstractType $asn1) 54 | { 55 | if (!($asn1 instanceof SequenceType && $asn1->getChild(0) instanceof IntegerType)) { 56 | throw new ProtocolException('The SNMP message is malformed.'); 57 | } 58 | $version = $asn1->getChild(0)->getValue(); 59 | 60 | if (!isset(self::$map[$version])) { 61 | throw new ProtocolException(sprintf( 62 | 'The SNMP version %s is not supported.', 63 | $version 64 | )); 65 | } 66 | 67 | return \call_user_func(self::$map[$version].'::fromAsn1', $asn1); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/FreeDSx/Snmp/Message/Response/MessageResponseInterface.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | 11 | namespace FreeDSx\Snmp\Message\Response; 12 | 13 | use FreeDSx\Snmp\Message\Pdu; 14 | 15 | /** 16 | * Interface for an SNMP message used in a response. 17 | * 18 | * @author Chad Sikorra 19 | */ 20 | interface MessageResponseInterface 21 | { 22 | /** 23 | * @return int 24 | */ 25 | public function getVersion() : int; 26 | 27 | /** 28 | * @return Pdu 29 | */ 30 | public function getResponse() : Pdu; 31 | } 32 | -------------------------------------------------------------------------------- /src/FreeDSx/Snmp/Message/Response/MessageResponseTrait.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | 11 | namespace FreeDSx\Snmp\Message\Response; 12 | 13 | use FreeDSx\Snmp\Message\Pdu; 14 | 15 | /** 16 | * Used to implement the message response interface. 17 | * 18 | * @author Chad Sikorra 19 | */ 20 | trait MessageResponseTrait 21 | { 22 | /** 23 | * @return Pdu 24 | */ 25 | public function getResponse() : Pdu 26 | { 27 | return $this->pdu; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/FreeDSx/Snmp/Message/Response/MessageResponseV1.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | 11 | namespace FreeDSx\Snmp\Message\Response; 12 | 13 | use FreeDSx\Asn1\Type\AbstractType; 14 | use FreeDSx\Snmp\Exception\ProtocolException; 15 | use FreeDSx\Snmp\Message\AbstractMessage; 16 | use FreeDSx\Snmp\Message\Pdu; 17 | use FreeDSx\Snmp\Protocol\Factory\ResponseFactory; 18 | 19 | /** 20 | * Represents a SNMPv1 Message Response. 21 | * 22 | * @author Chad Sikorra 23 | */ 24 | class MessageResponseV1 extends AbstractMessage implements MessageResponseInterface 25 | { 26 | protected const VERSION = 0; 27 | 28 | use MessageResponseTrait; 29 | 30 | /** 31 | * @param string $community 32 | * @param Pdu $response 33 | */ 34 | public function __construct( 35 | string $community, 36 | Pdu $response 37 | ) { 38 | $this->pdu = $response; 39 | parent::__construct($community); 40 | } 41 | 42 | /** 43 | * @param AbstractType $asn1 44 | * @return MessageResponseV1 45 | * @throws ProtocolException 46 | */ 47 | public static function fromAsn1(AbstractType $asn1): MessageResponseV1 48 | { 49 | $pdu = $asn1->getChild(2); 50 | if ($pdu == null) { 51 | throw new ProtocolException('The response is malformed.'); 52 | } 53 | 54 | return new static( 55 | static::parseCommunity($asn1), 56 | ResponseFactory::get($pdu) 57 | ); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/FreeDSx/Snmp/Message/Response/MessageResponseV2.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | 11 | namespace FreeDSx\Snmp\Message\Response; 12 | 13 | use FreeDSx\Asn1\Type\AbstractType; 14 | use FreeDSx\Snmp\Exception\ProtocolException; 15 | use FreeDSx\Snmp\Message\AbstractMessage; 16 | use FreeDSx\Snmp\Message\Pdu; 17 | use FreeDSx\Snmp\Protocol\Factory\ResponseFactory; 18 | 19 | /** 20 | * Represents a SNMPv2 Message Response. 21 | * 22 | * @author Chad Sikorra 23 | */ 24 | class MessageResponseV2 extends AbstractMessage implements MessageResponseInterface 25 | { 26 | protected const VERSION = 1; 27 | 28 | use MessageResponseTrait; 29 | 30 | /** 31 | * @param string $community 32 | * @param Pdu $response 33 | */ 34 | public function __construct(string $community, Pdu $response) 35 | { 36 | $this->pdu = $response; 37 | parent::__construct($community); 38 | } 39 | 40 | /** 41 | * {@inheritdoc} 42 | * @throws ProtocolException 43 | */ 44 | public static function fromAsn1(AbstractType $asn1): MessageResponseV2 45 | { 46 | $pdu = $asn1->getChild(2); 47 | if ($pdu == null) { 48 | throw new ProtocolException('The response is malformed.'); 49 | } 50 | 51 | return new static( 52 | static::parseCommunity($asn1), 53 | ResponseFactory::get($pdu) 54 | ); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/FreeDSx/Snmp/Message/Response/MessageResponseV3.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | 11 | namespace FreeDSx\Snmp\Message\Response; 12 | 13 | use FreeDSx\Asn1\Type\AbstractType; 14 | use FreeDSx\Asn1\Type\OctetStringType; 15 | use FreeDSx\Asn1\Type\SequenceType; 16 | use FreeDSx\Snmp\Exception\ProtocolException; 17 | use FreeDSx\Snmp\Exception\RuntimeException; 18 | use FreeDSx\Snmp\Message\AbstractMessageV3; 19 | use FreeDSx\Snmp\Message\MessageHeader; 20 | use FreeDSx\Snmp\Message\Pdu; 21 | use FreeDSx\Snmp\Message\ScopedPduResponse; 22 | use FreeDSx\Snmp\Message\Security\SecurityParametersInterface; 23 | 24 | /** 25 | * Represents a SNMPv3 Message Response. 26 | * 27 | * @author Chad Sikorra 28 | */ 29 | class MessageResponseV3 extends AbstractMessageV3 implements MessageResponseInterface 30 | { 31 | /** 32 | * @var ScopedPduResponse|null 33 | */ 34 | protected $scopedPdu; 35 | 36 | /** 37 | * @param MessageHeader $header 38 | * @param ScopedPduResponse|null $scopedPdu 39 | * @param null|string $encryptedPdu 40 | * @param SecurityParametersInterface|null $securityParams 41 | */ 42 | public function __construct( 43 | MessageHeader $header, 44 | ?ScopedPduResponse $scopedPdu, 45 | $encryptedPdu = null, 46 | ?SecurityParametersInterface $securityParams = null 47 | ) { 48 | parent::__construct( 49 | $header, 50 | $scopedPdu, 51 | $encryptedPdu, 52 | $securityParams 53 | ); 54 | } 55 | 56 | /** 57 | * @return Pdu 58 | */ 59 | public function getResponse(): Pdu 60 | { 61 | if ($this->scopedPdu === null) { 62 | throw new RuntimeException('The scopedPdu is not set.'); 63 | } 64 | 65 | return $this->scopedPdu->getResponse(); 66 | } 67 | 68 | /** 69 | * @return ScopedPduResponse|null 70 | */ 71 | public function getScopedPdu() : ?ScopedPduResponse 72 | { 73 | return $this->scopedPdu; 74 | } 75 | 76 | /** 77 | * @return null|string 78 | */ 79 | public function getEncryptedPdu(): ?string 80 | { 81 | return $this->encryptedPdu; 82 | } 83 | 84 | /** 85 | * @inheritDoc 86 | * @throws ProtocolException 87 | */ 88 | public static function fromAsn1(AbstractType $asn1): MessageResponseV3 89 | { 90 | list($header, $securityParams, $pdu) = self::parseCommonElements($asn1); 91 | 92 | $encryptedPdu = null; 93 | $scopedPdu = null; 94 | if ($pdu instanceof OctetStringType) { 95 | $encryptedPdu = $pdu->getValue(); 96 | } elseif ($pdu instanceof SequenceType) { 97 | $scopedPdu = ScopedPduResponse::fromAsn1($pdu); 98 | } else { 99 | throw new ProtocolException(sprintf( 100 | 'Expected either an octet string or sequence for scoped pdu data, got %s.', 101 | get_class($pdu) 102 | )); 103 | } 104 | 105 | return new self( 106 | $header, 107 | $scopedPdu, 108 | $encryptedPdu, 109 | $securityParams 110 | ); 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /src/FreeDSx/Snmp/Message/ScopedPduRequest.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | 11 | namespace FreeDSx\Snmp\Message; 12 | 13 | use FreeDSx\Asn1\Type\AbstractType; 14 | use FreeDSx\Snmp\Protocol\Factory\RequestFactory; 15 | 16 | /** 17 | * Represents a Scoped PDU request. 18 | * 19 | * @author Chad Sikorra 20 | */ 21 | class ScopedPduRequest extends ScopedPdu 22 | { 23 | /** 24 | * @param Pdu $request 25 | * @param null|EngineId $contextEngineId 26 | * @param string $contextName 27 | */ 28 | public function __construct( 29 | Pdu $request, 30 | ?EngineId $contextEngineId = null, 31 | string $contextName = '' 32 | ) { 33 | parent::__construct( 34 | $request, 35 | $contextEngineId, 36 | $contextName 37 | ); 38 | } 39 | 40 | /** 41 | * @param string $contextName 42 | * @return $this 43 | */ 44 | public function setContextName(string $contextName) 45 | { 46 | $this->contextName = $contextName; 47 | 48 | return $this; 49 | } 50 | 51 | /** 52 | * @param null|EngineId $contextEngineId 53 | * @return $this 54 | */ 55 | public function setContextEngineId(?EngineId $contextEngineId) 56 | { 57 | $this->contextEngineId = $contextEngineId; 58 | 59 | return $this; 60 | } 61 | 62 | /** 63 | * @return Pdu 64 | */ 65 | public function getRequest(): Pdu 66 | { 67 | return $this->pdu; 68 | } 69 | 70 | /** 71 | * @param Pdu $request 72 | * @return $this 73 | */ 74 | public function setRequest(Pdu $request) 75 | { 76 | $this->pdu = $request; 77 | 78 | return $this; 79 | } 80 | 81 | /** 82 | * {@inheritdoc} 83 | */ 84 | public static function fromAsn1(AbstractType $type) 85 | { 86 | list($engineId, $contextName, $pdu) = self::parseBaseElements($type); 87 | 88 | return new self( 89 | RequestFactory::get($pdu), 90 | $engineId, 91 | $contextName 92 | ); 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /src/FreeDSx/Snmp/Message/ScopedPduResponse.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | 11 | namespace FreeDSx\Snmp\Message; 12 | 13 | use FreeDSx\Asn1\Type\AbstractType; 14 | use FreeDSx\Snmp\Protocol\Factory\ResponseFactory; 15 | 16 | /** 17 | * Represents a Scoped PDU response. 18 | * 19 | * @author Chad Sikorra 20 | */ 21 | class ScopedPduResponse extends ScopedPdu 22 | { 23 | /** 24 | * @param Pdu $response 25 | * @param null|EngineId $contextEngineId 26 | * @param string $contextName 27 | */ 28 | public function __construct( 29 | Pdu $response, 30 | ?EngineId $contextEngineId = null, 31 | string $contextName = '' 32 | ) { 33 | parent::__construct($response, $contextEngineId, $contextName); 34 | } 35 | 36 | /** 37 | * @return Pdu 38 | */ 39 | public function getResponse() : Pdu 40 | { 41 | return $this->pdu; 42 | } 43 | 44 | /** 45 | * {@inheritdoc} 46 | */ 47 | public static function fromAsn1(AbstractType $type) 48 | { 49 | list($engineId, $contextName, $pdu) = self::parseBaseElements($type); 50 | 51 | return new self( 52 | ResponseFactory::get($pdu), 53 | $engineId, 54 | $contextName 55 | ); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/FreeDSx/Snmp/Message/Security/SecurityParametersInterface.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | 11 | namespace FreeDSx\Snmp\Message\Security; 12 | 13 | use FreeDSx\Snmp\Protocol\ProtocolElementInterface; 14 | 15 | /** 16 | * Implements the Security Parameter portion of the SNMPv3 Message. 17 | * 18 | * @author Chad Sikorra 19 | */ 20 | interface SecurityParametersInterface extends ProtocolElementInterface 21 | { 22 | /** 23 | * Represents the msgSecurityModel to be used in the header. 24 | * 25 | * @return int 26 | */ 27 | public function getSecurityModel() : int; 28 | } 29 | -------------------------------------------------------------------------------- /src/FreeDSx/Snmp/Module/Authentication/AuthenticationModuleInterface.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | 11 | namespace FreeDSx\Snmp\Module\Authentication; 12 | 13 | use FreeDSx\Snmp\Exception\SnmpAuthenticationException; 14 | use FreeDSx\Snmp\Message\AbstractMessageV3; 15 | use FreeDSx\Snmp\Message\EngineId; 16 | 17 | /** 18 | * RFC 3414, Section 1.6.1. 19 | * 20 | * Represents the needed methods for an authentication module. 21 | * 22 | * @author Chad Sikorra 23 | */ 24 | interface AuthenticationModuleInterface 25 | { 26 | /** 27 | * Authenticate an incoming message according to an algorithm. 28 | * 29 | * @param AbstractMessageV3 $message 30 | * @param string $password 31 | * @throws SnmpAuthenticationException 32 | * @return AbstractMessageV3 33 | */ 34 | public function authenticateIncomingMsg( 35 | AbstractMessageV3 $message, 36 | string $password 37 | ): AbstractMessageV3; 38 | 39 | /** 40 | * Authenticate an outgoing message according to an algorithm. 41 | * 42 | * @param AbstractMessageV3 $message 43 | * @param string $password 44 | * @throws SnmpAuthenticationException 45 | * @return AbstractMessageV3 46 | */ 47 | public function authenticateOutgoingMsg( 48 | AbstractMessageV3 $message, 49 | string $password 50 | ): AbstractMessageV3; 51 | 52 | /** 53 | * @param string $password 54 | * @param EngineId $engineId 55 | * @return string 56 | */ 57 | public function generateKey( 58 | string $password, 59 | EngineId $engineId 60 | ): string; 61 | 62 | public function hash(string $value) : string; 63 | 64 | /** 65 | * Get the algorithms supported as an array of string names. 66 | * 67 | * @return string[] 68 | */ 69 | public static function supports() : array; 70 | } 71 | -------------------------------------------------------------------------------- /src/FreeDSx/Snmp/Module/Privacy/DESPrivacyModule.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | 11 | namespace FreeDSx\Snmp\Module\Privacy; 12 | 13 | use FreeDSx\Snmp\Message\Security\UsmSecurityParameters; 14 | use FreeDSx\Snmp\Module\Authentication\AuthenticationModuleInterface; 15 | 16 | /** 17 | * RFC 3414 18 | * 19 | * DES privacy mechanisms for encrypting / decrypting the ScopedPDU. 20 | * 21 | * @author Chad Sikorra 22 | */ 23 | class DESPrivacyModule implements PrivacyModuleInterface 24 | { 25 | use PrivacyTrait, 26 | DESPrivacyTrait; 27 | 28 | protected const ALIASES = [ 29 | 'des' => 'des-cbc', 30 | ]; 31 | 32 | protected const ALGORITHMS = [ 33 | 'des', 34 | 'des-cbc', 35 | ]; 36 | 37 | /** 38 | * {@inheritdoc} 39 | */ 40 | public static function supports() : array 41 | { 42 | return self::ALGORITHMS; 43 | } 44 | 45 | /** 46 | * {@inheritdoc} 47 | */ 48 | protected function toKeySaltIV(string $cryptKey, UsmSecurityParameters $usm, AuthenticationModuleInterface $authMod, ?string $salt = null) : array 49 | { 50 | # The first 8 octets of the 16-octet secret (private privacy key) are 51 | # used as a DES key. Since DES uses only 56 bits, the Least 52 | # Significant Bit in each octet is disregarded. 53 | $key = \substr($cryptKey, 0, 8); 54 | # The last 8 octets of the 16-octet secret (private privacy key) are used as pre-IV. 55 | $preIV = \substr($cryptKey, 8, 8); 56 | 57 | # The 32-bit snmpEngineBoots is converted to the first 4 octets (Most 58 | # Significant Byte first) of our "salt". The 32-bit integer is then 59 | # converted to the last 4 octet (Most Significant Byte first) of our 60 | # "salt". 61 | if ($salt === null) { 62 | $salt = $this->intToSaltBytes($usm->getEngineBoots(), 24).$this->intToSaltBytes($this->localBoot, 24); 63 | } 64 | 65 | return ['key' => $key, 'salt' => $salt, 'iv' => $this->generateIV($preIV, $salt)]; 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/FreeDSx/Snmp/Module/Privacy/DESPrivacyTrait.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | 11 | namespace FreeDSx\Snmp\Module\Privacy; 12 | 13 | use FreeDSx\Snmp\Exception\SnmpEncryptionException; 14 | 15 | /** 16 | * Common methods shared by DES / 3DES privacy mechanisms. 17 | * 18 | * @author Chad Sikorra 19 | */ 20 | trait DESPrivacyTrait 21 | { 22 | /** 23 | * @param string $algorithm 24 | * @param int|null $localBoot 25 | * @throws \Exception 26 | */ 27 | public function __construct(string $algorithm, ?int $localBoot = null) 28 | { 29 | $this->algorithm = $algorithm; 30 | $this->localBoot = ($localBoot === null) ? \random_int(0, self::$maxSalt) : $localBoot; 31 | } 32 | 33 | /** 34 | * @param string $preIV 35 | * @param string $salt 36 | * @return string 37 | */ 38 | protected function generateIV(string $preIV, string $salt) : string 39 | { 40 | $iv = ''; 41 | 42 | # The resulting "salt" is then XOR-ed with the pre-IV to obtain the IV. 43 | for ($i = 0; $i < 8; $i++) { 44 | $iv .= \chr(\ord($salt[$i]) ^ \ord($preIV[$i])); 45 | } 46 | 47 | return $iv; 48 | } 49 | 50 | /** 51 | * {@inheritdoc} 52 | */ 53 | protected function validateEncodedPdu(string $scopedPdu) : string 54 | { 55 | $pduLength = \strlen($scopedPdu); 56 | 57 | if (($mod = $pduLength % 8)) { 58 | $scopedPdu .= \str_repeat("\x00", (8 - $mod)); 59 | } 60 | 61 | return $scopedPdu; 62 | } 63 | 64 | /** 65 | * {@inheritdoc} 66 | */ 67 | protected function validateEncryptedPdu(string $encryptedPdu) : string 68 | { 69 | if (\strlen($encryptedPdu) % 8) { 70 | throw new SnmpEncryptionException('The encrypted PDU must be a multiple of 8 octets, but it is not'); 71 | } 72 | 73 | return $encryptedPdu; 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/FreeDSx/Snmp/Module/Privacy/PrivacyModuleInterface.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | 11 | namespace FreeDSx\Snmp\Module\Privacy; 12 | 13 | use FreeDSx\Snmp\Exception\SnmpEncryptionException; 14 | use FreeDSx\Snmp\Message\AbstractMessageV3; 15 | use FreeDSx\Snmp\Message\Request\MessageRequestV3; 16 | use FreeDSx\Snmp\Message\Response\MessageResponseV3; 17 | use FreeDSx\Snmp\Module\Authentication\AuthenticationModuleInterface; 18 | 19 | /** 20 | * RFC 3414, Section 1.6.2. 21 | * 22 | * Represents the needed methods for a privacy module. 23 | * 24 | * @author Chad Sikorra 25 | */ 26 | interface PrivacyModuleInterface 27 | { 28 | /** 29 | * Decrypt message data according to the algorithm. 30 | * 31 | * @param AbstractMessageV3 $message 32 | * @param AuthenticationModuleInterface $authMod 33 | * @param string $privPwd 34 | * @return AbstractMessageV3 35 | * @throws SnmpEncryptionException 36 | */ 37 | public function decryptData(AbstractMessageV3 $message, AuthenticationModuleInterface $authMod, string $privPwd) : AbstractMessageV3; 38 | 39 | /** 40 | * Encrypt message data according to the algorithm. 41 | * 42 | * @param AbstractMessageV3 $message 43 | * @param AuthenticationModuleInterface $authMod 44 | * @param string $privPwd 45 | * @return AbstractMessageV3|MessageRequestV3|MessageResponseV3 46 | * @throws SnmpEncryptionException 47 | */ 48 | public function encryptData(AbstractMessageV3 $message, AuthenticationModuleInterface $authMod, string $privPwd) : AbstractMessageV3; 49 | 50 | /** 51 | * Get the supported mechanisms of the module as an array of strings. 52 | * 53 | * @return string[] 54 | */ 55 | public static function supports() : array; 56 | } 57 | -------------------------------------------------------------------------------- /src/FreeDSx/Snmp/Module/SecurityModel/Usm/TimeSync.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | 11 | namespace FreeDSx\Snmp\Module\SecurityModel\Usm; 12 | 13 | 14 | /** 15 | * Holds some time logic related to synchronization for an engine. 16 | * 17 | * RFC 3414. 18 | * 19 | * @author Chad Sikorra 20 | */ 21 | class TimeSync 22 | { 23 | /** 24 | * @var int 25 | */ 26 | protected $engineBoot; 27 | 28 | /** 29 | * @var int 30 | */ 31 | protected $engineTime; 32 | 33 | /** 34 | * @var \DateTime 35 | */ 36 | protected $whenSynced; 37 | 38 | /** 39 | * @param int $engineBoot 40 | * @param int $engineTime 41 | * @param \DateTime|null $whenSynced 42 | */ 43 | public function __construct(int $engineBoot, int $engineTime, ?\DateTime $whenSynced = null) 44 | { 45 | $this->engineBoot = $engineBoot; 46 | $this->engineTime = $engineTime; 47 | $this->whenSynced = $whenSynced ?: new \DateTime(); 48 | } 49 | 50 | /** 51 | * @return int 52 | */ 53 | public function getEngineBoot() : int 54 | { 55 | return $this->engineBoot; 56 | } 57 | 58 | /** 59 | * @return int 60 | */ 61 | public function getEngineTime(): int 62 | { 63 | return $this->engineTime; 64 | } 65 | 66 | /** 67 | * @return \DateTime 68 | */ 69 | public function getWhenSynced() : \DateTime 70 | { 71 | return $this->whenSynced; 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/FreeDSx/Snmp/OidValues.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | 11 | namespace FreeDSx\Snmp; 12 | 13 | use FreeDSx\Snmp\Value\ArbitraryValue; 14 | use FreeDSx\Snmp\Value\BigCounterValue; 15 | use FreeDSx\Snmp\Value\CounterValue; 16 | use FreeDSx\Snmp\Value\IntegerValue; 17 | use FreeDSx\Snmp\Value\IpAddressValue; 18 | use FreeDSx\Snmp\Value\OidValue; 19 | use FreeDSx\Snmp\Value\StringValue; 20 | use FreeDSx\Snmp\Value\TimeTicksValue; 21 | use FreeDSx\Snmp\Value\UnsignedIntegerValue; 22 | 23 | /** 24 | * Factory methods to build OID values. 25 | * 26 | * @author Chad Sikorra 27 | */ 28 | class OidValues 29 | { 30 | /** 31 | * @param mixed $value 32 | */ 33 | public static function arbitrary($value) : ArbitraryValue 34 | { 35 | return new ArbitraryValue($value); 36 | } 37 | 38 | /** 39 | * @param int $value 40 | * @return IntegerValue 41 | */ 42 | public static function integer(int $value) : IntegerValue 43 | { 44 | return new IntegerValue($value); 45 | } 46 | 47 | /** 48 | * @param string $value 49 | * @return StringValue 50 | */ 51 | public static function string(string $value) : StringValue 52 | { 53 | return new StringValue($value); 54 | } 55 | 56 | /** 57 | * @param int|string $value 58 | * @return BigCounterValue 59 | */ 60 | public static function bigCounter($value) : BigCounterValue 61 | { 62 | return new BigCounterValue($value); 63 | } 64 | 65 | /** 66 | * @param int $value 67 | * @return CounterValue 68 | */ 69 | public static function counter(int $value) : CounterValue 70 | { 71 | return new CounterValue($value); 72 | } 73 | 74 | /** 75 | * @param string $value 76 | * @return IpAddressValue 77 | */ 78 | public static function ipAddress(string $value) : IpAddressValue 79 | { 80 | return new IpAddressValue($value); 81 | } 82 | 83 | /** 84 | * @param int $value 85 | * @return TimeTicksValue 86 | */ 87 | public static function timeticks(int $value) : TimeTicksValue 88 | { 89 | return new TimeTicksValue($value); 90 | } 91 | 92 | /** 93 | * @param int $value 94 | * @return UnsignedIntegerValue 95 | */ 96 | public static function unsignedInteger(int $value) : UnsignedIntegerValue 97 | { 98 | return new UnsignedIntegerValue($value); 99 | } 100 | 101 | /** 102 | * @param string $oid 103 | * @return OidValue 104 | */ 105 | public static function oid(string $oid) : OidValue 106 | { 107 | return new OidValue($oid); 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /src/FreeDSx/Snmp/Protocol/Factory/AuthenticationModuleFactory.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | 11 | namespace FreeDSx\Snmp\Protocol\Factory; 12 | 13 | use FreeDSx\Snmp\Exception\InvalidArgumentException; 14 | use FreeDSx\Snmp\Module\Authentication\AuthenticationModuleInterface; 15 | use FreeDSx\Snmp\Module\Authentication\AuthenticationModule; 16 | 17 | /** 18 | * Gets the authentication module to use for a specific authentication mechanism. 19 | * 20 | * @author Chad Sikorra 21 | */ 22 | class AuthenticationModuleFactory 23 | { 24 | /** 25 | * @var array 26 | */ 27 | protected $modules; 28 | 29 | public function __construct() 30 | { 31 | $module = AuthenticationModule::class; 32 | 33 | foreach (\call_user_func($module.'::supports') as $algorithm) { 34 | $this->modules[$algorithm] = $module; 35 | } 36 | } 37 | 38 | /** 39 | * @param string $algorithm 40 | * @return AuthenticationModuleInterface 41 | */ 42 | public function get(string $algorithm) : AuthenticationModuleInterface 43 | { 44 | if (!isset($this->modules[$algorithm])) { 45 | throw new InvalidArgumentException(sprintf( 46 | 'The authentication mechanism "%s" is not recognized. Valid mechanisms are: %s', 47 | $algorithm, 48 | implode(', ', array_keys($this->modules)) 49 | )); 50 | } 51 | 52 | return new $this->modules[$algorithm]($algorithm); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/FreeDSx/Snmp/Protocol/Factory/OidValueFactory.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | 11 | namespace FreeDSx\Snmp\Protocol\Factory; 12 | 13 | use FreeDSx\Asn1\Type\AbstractType; 14 | use FreeDSx\Asn1\Type\IntegerType; 15 | use FreeDSx\Asn1\Type\OctetStringType; 16 | use FreeDSx\Asn1\Type\OidType; 17 | use FreeDSx\Snmp\Exception\ProtocolException; 18 | use FreeDSx\Snmp\Value\AbstractValue; 19 | use FreeDSx\Snmp\Value\ArbitraryValue; 20 | use FreeDSx\Snmp\Value\BigCounterValue; 21 | use FreeDSx\Snmp\Value\CounterValue; 22 | use FreeDSx\Snmp\Value\IntegerValue; 23 | use FreeDSx\Snmp\Value\IpAddressValue; 24 | use FreeDSx\Snmp\Value\OidValue; 25 | use FreeDSx\Snmp\Value\StringValue; 26 | use FreeDSx\Snmp\Value\TimeTicksValue; 27 | use FreeDSx\Snmp\Value\UnsignedIntegerValue; 28 | 29 | /** 30 | * Map a VarBind value to an OidValue type. 31 | * 32 | * @author Chad Sikorra 33 | */ 34 | class OidValueFactory 35 | { 36 | /** 37 | * @var array 38 | */ 39 | protected static $appMap = [ 40 | 0 => IpAddressValue::class, 41 | 1 => CounterValue::class, 42 | 2 => UnsignedIntegerValue::class, 43 | 3 => TimeTicksValue::class, 44 | 4 => ArbitraryValue::class, 45 | 6 => BigCounterValue::class, 46 | ]; 47 | 48 | /** 49 | * @var array 50 | */ 51 | protected static $simpleMap = [ 52 | IntegerType::class => IntegerValue::class, 53 | OctetStringType::class => StringValue::class, 54 | OidType::class => OidValue::class, 55 | ]; 56 | 57 | /** 58 | * @param AbstractType $type 59 | * @return AbstractValue 60 | * @throws ProtocolException 61 | */ 62 | public static function get(AbstractType $type) 63 | { 64 | if (isset(self::$simpleMap[\get_class($type)])) { 65 | return \call_user_func(self::$simpleMap[\get_class($type)].'::fromAsn1', $type); 66 | } elseif ($type->getTagClass() === AbstractType::TAG_CLASS_APPLICATION && isset(self::$appMap[$type->getTagNumber()])) { 67 | return \call_user_func(self::$appMap[$type->getTagNumber()].'::fromAsn1', $type); 68 | } else { 69 | throw new ProtocolException(sprintf( 70 | 'The SNMP VarBind value from ASN.1 type %s and tag %s is not recognized.', 71 | get_class($type), 72 | $type->getTagNumber() 73 | )); 74 | } 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /src/FreeDSx/Snmp/Protocol/Factory/PrivacyModuleFactory.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | 11 | namespace FreeDSx\Snmp\Protocol\Factory; 12 | 13 | use FreeDSx\Snmp\Exception\InvalidArgumentException; 14 | use FreeDSx\Snmp\Module\Privacy\AESPrivacyModule; 15 | use FreeDSx\Snmp\Module\Privacy\DES3PrivacyModule; 16 | use FreeDSx\Snmp\Module\Privacy\DESPrivacyModule; 17 | use FreeDSx\Snmp\Module\Privacy\PrivacyModuleInterface; 18 | 19 | /** 20 | * Gets the privacy module for a specific mechanism. 21 | * 22 | * @author Chad Sikorra 23 | */ 24 | class PrivacyModuleFactory 25 | { 26 | /** 27 | * @var array 28 | */ 29 | protected $modules; 30 | 31 | public function __construct() 32 | { 33 | $desModule = DESPrivacyModule::class; 34 | $des3Module = DES3PrivacyModule::class; 35 | $aesModule = AESPrivacyModule::class; 36 | 37 | foreach ([$desModule, $des3Module, $aesModule] as $module) { 38 | foreach (\call_user_func($module.'::supports') as $algorithm) { 39 | $this->modules[$algorithm] = $module; 40 | } 41 | } 42 | } 43 | 44 | /** 45 | * @param string $algorithm 46 | * @param int|null $boot 47 | * @return PrivacyModuleInterface 48 | */ 49 | public function get(string $algorithm, ?int $boot = null) : PrivacyModuleInterface 50 | { 51 | if (!isset($this->modules[$algorithm])) { 52 | throw new InvalidArgumentException(sprintf( 53 | 'The privacy mechanism "%s" is not recognized. Valid mechanisms are: %s', 54 | $algorithm, 55 | implode(', ', array_keys($this->modules)) 56 | )); 57 | } 58 | 59 | return new $this->modules[$algorithm]($algorithm, $boot); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/FreeDSx/Snmp/Protocol/Factory/RequestFactory.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | 11 | namespace FreeDSx\Snmp\Protocol\Factory; 12 | 13 | use FreeDSx\Asn1\Type\AbstractType; 14 | use FreeDSx\Snmp\Exception\ProtocolException; 15 | use FreeDSx\Snmp\Message\Pdu; 16 | use FreeDSx\Snmp\Request\GetBulkRequest; 17 | use FreeDSx\Snmp\Request\GetNextRequest; 18 | use FreeDSx\Snmp\Request\GetRequest; 19 | use FreeDSx\Snmp\Request\InformRequest; 20 | use FreeDSx\Snmp\Request\SetRequest; 21 | use FreeDSx\Snmp\Request\TrapV1Request; 22 | use FreeDSx\Snmp\Request\TrapV2Request; 23 | 24 | /** 25 | * Resolves specific ASN.1 app tags to their Request classes. 26 | * 27 | * @author Chad Sikorra 28 | */ 29 | class RequestFactory 30 | { 31 | /** 32 | * @var array 33 | */ 34 | protected static $map = [ 35 | 0 => GetRequest::class, 36 | 1 => GetNextRequest::class, 37 | 3 => SetRequest::class, 38 | 4 => TrapV1Request::class, 39 | 5 => GetBulkRequest::class, 40 | 6 => InformRequest::class, 41 | 7 => TrapV2Request::class, 42 | ]; 43 | 44 | /** 45 | * @param AbstractType $type 46 | * @return Pdu 47 | * @throws ProtocolException 48 | */ 49 | public static function get(AbstractType $type) : Pdu 50 | { 51 | if (!isset(self::$map[$type->getTagNumber()])) { 52 | throw new ProtocolException(sprintf( 53 | 'The PDU number %s is not recognized.', 54 | $type->getTagNumber() 55 | )); 56 | } 57 | 58 | return \call_user_func( 59 | self::$map[$type->getTagNumber()].'::fromAsn1', 60 | $type 61 | ); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/FreeDSx/Snmp/Protocol/Factory/ResponseFactory.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | 11 | namespace FreeDSx\Snmp\Protocol\Factory; 12 | 13 | use FreeDSx\Asn1\Type\AbstractType; 14 | use FreeDSx\Snmp\Exception\ProtocolException; 15 | use FreeDSx\Snmp\Message\Pdu; 16 | use FreeDSx\Snmp\Response\Response; 17 | use FreeDSx\Snmp\Response\ReportResponse; 18 | 19 | /** 20 | * Maps the PDU type to the response class. 21 | * 22 | * @author Chad Sikorra 23 | */ 24 | class ResponseFactory 25 | { 26 | /** 27 | * @var array 28 | */ 29 | protected static $map = [ 30 | 2 => Response::class, 31 | 8 => ReportResponse::class, 32 | ]; 33 | 34 | /** 35 | * @param AbstractType $type 36 | * @return Pdu 37 | * @throws ProtocolException 38 | */ 39 | public static function get(AbstractType $type) : Pdu 40 | { 41 | if (!isset(self::$map[$type->getTagNumber()])) { 42 | throw new ProtocolException(sprintf( 43 | 'The PDU number %s is not recognized.', 44 | $type->getTagNumber() 45 | )); 46 | } 47 | 48 | return \call_user_func( 49 | self::$map[$type->getTagNumber()].'::fromAsn1', 50 | $type 51 | ); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/FreeDSx/Snmp/Protocol/Factory/SecurityModelModuleFactory.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | 11 | namespace FreeDSx\Snmp\Protocol\Factory; 12 | 13 | use FreeDSx\Snmp\Exception\ProtocolException; 14 | use FreeDSx\Snmp\Module\SecurityModel\SecurityModelModuleInterface; 15 | use FreeDSx\Snmp\Module\SecurityModel\UserSecurityModelModule; 16 | 17 | /** 18 | * Given a security model integer, get the class that handles its logic. 19 | * 20 | * @author Chad Sikorra 21 | */ 22 | class SecurityModelModuleFactory 23 | { 24 | /** 25 | * @var array 26 | */ 27 | protected $map = []; 28 | 29 | /** 30 | * @var SecurityModelModuleInterface[] 31 | */ 32 | protected $loaded = []; 33 | 34 | public function __construct() 35 | { 36 | $module = UserSecurityModelModule::class; 37 | $this->map[\call_user_func($module.'::supports')] = $module; 38 | } 39 | 40 | /** 41 | * @param int $securityModel 42 | * @return SecurityModelModuleInterface 43 | * @throws ProtocolException 44 | */ 45 | public function get(int $securityModel) : SecurityModelModuleInterface 46 | { 47 | if (!isset($this->map[$securityModel])) { 48 | throw new ProtocolException(sprintf( 49 | 'The security model %s is not supported. Supported security models are: %s', 50 | $securityModel, 51 | implode(', ', array_keys($this->map)) 52 | )); 53 | } 54 | if (!isset($this->loaded[$securityModel])) { 55 | $this->loaded[$securityModel] = new $this->map[$securityModel](); 56 | } 57 | 58 | return $this->loaded[$securityModel]; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/FreeDSx/Snmp/Protocol/Factory/SecurityParametersFactory.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | 11 | namespace FreeDSx\Snmp\Protocol\Factory; 12 | 13 | use FreeDSx\Asn1\Type\AbstractType; 14 | use FreeDSx\Snmp\Exception\InvalidArgumentException; 15 | use FreeDSx\Snmp\Exception\ProtocolException; 16 | use FreeDSx\Snmp\Message\Security\SecurityParametersInterface; 17 | use FreeDSx\Snmp\Message\Security\UsmSecurityParameters; 18 | 19 | /** 20 | * Construct the security parameters class based off the security model. 21 | * 22 | * @author Chad Sikorra 23 | */ 24 | class SecurityParametersFactory 25 | { 26 | /** 27 | * @var array 28 | */ 29 | protected static $map = [ 30 | 3 => UsmSecurityParameters::class, 31 | ]; 32 | 33 | /** 34 | * @param int $securityModel 35 | * @param AbstractType $type 36 | * @return SecurityParametersInterface 37 | * @throws ProtocolException 38 | */ 39 | public static function get(int $securityModel, AbstractType $type) : SecurityParametersInterface 40 | { 41 | if (!isset(self::$map[$securityModel])) { 42 | throw new ProtocolException(sprintf( 43 | 'The security model %s is not recognized.', 44 | $securityModel 45 | )); 46 | } 47 | 48 | return \call_user_func( 49 | self::$map[$securityModel] . '::fromAsn1', 50 | $type 51 | ); 52 | } 53 | 54 | /** 55 | * @param class-string $class 56 | */ 57 | public static function set(string $class) : void 58 | { 59 | if (!\in_array(SecurityParametersInterface::class, (array)class_implements($class), true)) { 60 | throw new InvalidArgumentException(sprintf( 61 | 'The security parameters "%s" must implement "%s", but it does not.', 62 | $class, 63 | SecurityParametersInterface::class 64 | )); 65 | } 66 | try { 67 | self::$map[(new $class())->getSecurityModel()] = $class; 68 | } catch (\Throwable $e) { 69 | throw new InvalidArgumentException(sprintf( 70 | 'Unable to instantiate security paramters module "%s".', 71 | $class 72 | )); 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/FreeDSx/Snmp/Protocol/IdGeneratorTrait.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | 11 | namespace FreeDSx\Snmp\Protocol; 12 | 13 | /** 14 | * ID generator logic is used in a few different spots. Isolate it to this trait. 15 | * 16 | * @author Chad Sikorra 17 | */ 18 | trait IdGeneratorTrait 19 | { 20 | /** 21 | * The max value for a request id. 22 | * 23 | * @var int 24 | */ 25 | protected static $maxId = 2147483647; 26 | 27 | /** 28 | * The minimum value for a request id. 29 | * 30 | * @var int 31 | */ 32 | protected static $minId = -214783648; 33 | 34 | /** @var mixed[] */ 35 | private $options = []; 36 | 37 | /** 38 | * @param int|null $min 39 | * @param int|null $max 40 | * @return int 41 | * @throws \Exception 42 | */ 43 | protected function generateId(?int $min = null, ?int $max = null) : int 44 | { 45 | $min = $this->options['id_min'] ?? $min ?? self::$minId; 46 | $max = $this->options['id_max'] ?? $max ?? self::$maxId; 47 | 48 | return \random_int($min, $max); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/FreeDSx/Snmp/Protocol/ProtocolElementInterface.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | 11 | namespace FreeDSx\Snmp\Protocol; 12 | 13 | use FreeDSx\Asn1\Type\AbstractType; 14 | 15 | /** 16 | * Methods needed to transform an object to/from ASN1 representation. 17 | * 18 | * @author Chad Sikorra 19 | */ 20 | interface ProtocolElementInterface 21 | { 22 | /** 23 | * Returns the Asn1 representation of an object that can be used by an encoder. 24 | * 25 | * @return AbstractType 26 | */ 27 | public function toAsn1() : AbstractType; 28 | 29 | /** 30 | * @param AbstractType $type 31 | * @return mixed 32 | */ 33 | public static function fromAsn1(AbstractType $type); 34 | } 35 | -------------------------------------------------------------------------------- /src/FreeDSx/Snmp/Protocol/SnmpEncoder.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | 11 | namespace FreeDSx\Snmp\Protocol; 12 | 13 | use FreeDSx\Asn1\Encoder\BerEncoder; 14 | use FreeDSx\Asn1\Type\AbstractType; 15 | 16 | /** 17 | * Specifies SNMP specific BER encoding rules defined in RFC 3417, Section 8: 18 | * 19 | * (1) When encoding the length field, only the definite form is used; 20 | * use of the indefinite form encoding is prohibited. Note that 21 | * when using the definite-long form, it is permissible to use 22 | * more than the minimum number of length octets necessary to 23 | * encode the length field. 24 | * 25 | * (2) When encoding the value field, the primitive form shall be used 26 | * for all simple types, i.e., INTEGER, OCTET STRING, and OBJECT 27 | * IDENTIFIER (either IMPLICIT or explicit). The constructed form 28 | * of encoding shall be used only for structured types, i.e., a 29 | * SEQUENCE or an IMPLICIT SEQUENCE. 30 | * 31 | * (3) When encoding an object whose syntax is described using the 32 | * BITS construct, the value is encoded as an OCTET STRING, in 33 | * which all the named bits in (the definition of) the bitstring, 34 | * commencing with the first bit and proceeding to the last bit, 35 | * are placed in bits 8 (high order bit) to 1 (low order bit) of 36 | * the first octet, followed by bits 8 to 1 of each subsequent 37 | * octet in turn, followed by as many bits as are needed of the 38 | * final subsequent octet, commencing with bit 8. Remaining bits, 39 | * if any, of the final octet are set to zero on generation and 40 | * ignored on receipt. 41 | * 42 | * @see https://tools.ietf.org/html/rfc3417#section-8 43 | * @author Chad Sikorra 44 | */ 45 | class SnmpEncoder extends BerEncoder 46 | { 47 | public function __construct() 48 | { 49 | parent::__construct(['primitive_only' => [AbstractType::TAG_TYPE_OCTET_STRING]]); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/FreeDSx/Snmp/Request/GetBulkRequest.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | 11 | namespace FreeDSx\Snmp\Request; 12 | 13 | use FreeDSx\Asn1\Type\AbstractType; 14 | use FreeDSx\Snmp\Message\Pdu; 15 | use FreeDSx\Snmp\OidList; 16 | 17 | /** 18 | * Represents a GetBulk Request. 19 | * 20 | * @author Chad Sikorra 21 | */ 22 | class GetBulkRequest extends Pdu implements RequestInterface 23 | { 24 | use RequestTrait; 25 | 26 | protected const TAG = 5; 27 | 28 | /** 29 | * @var bool 30 | */ 31 | protected $includeValues = false; 32 | 33 | /** 34 | * @param int $maxRepetitions 35 | * @param int $nonRepeaters 36 | * @param OidList $oids 37 | */ 38 | public function __construct(int $maxRepetitions, int $nonRepeaters, OidList $oids) 39 | { 40 | parent::__construct(0, $nonRepeaters, $maxRepetitions, $oids); 41 | } 42 | 43 | /** 44 | * @return int 45 | */ 46 | public function getMaxRepetitions() : int 47 | { 48 | return $this->errorIndex; 49 | } 50 | 51 | /** 52 | * @param int $maxRepetitions 53 | * @return $this 54 | */ 55 | public function setMaxRepetitions(int $maxRepetitions) 56 | { 57 | $this->errorIndex = $maxRepetitions; 58 | 59 | return $this; 60 | } 61 | 62 | /** 63 | * @return int 64 | */ 65 | public function getNonRepeaters() : int 66 | { 67 | return $this->errorStatus; 68 | } 69 | 70 | /** 71 | * @param int $nonRepeaters 72 | * @return $this 73 | */ 74 | public function setNonRepeaters(int $nonRepeaters) 75 | { 76 | $this->errorStatus = $nonRepeaters; 77 | 78 | return $this; 79 | } 80 | 81 | /** 82 | * {@inheritdoc} 83 | */ 84 | public static function fromAsn1(AbstractType $type) 85 | { 86 | list($id, $errorStatus, $errorIndex, $oidList) = parent::getBaseElements($type); 87 | 88 | $bulkRequest = new self( 89 | $errorIndex, 90 | $errorStatus, 91 | $oidList 92 | ); 93 | $bulkRequest->id = $id; 94 | 95 | return $bulkRequest; 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /src/FreeDSx/Snmp/Request/GetNextRequest.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | 11 | namespace FreeDSx\Snmp\Request; 12 | 13 | use FreeDSx\Asn1\Type\AbstractType; 14 | use FreeDSx\Snmp\Message\Pdu; 15 | use FreeDSx\Snmp\OidList; 16 | 17 | /** 18 | * Represents an GetNext request. 19 | * 20 | * @author Chad Sikorra 21 | */ 22 | class GetNextRequest extends Pdu implements RequestInterface 23 | { 24 | use RequestTrait; 25 | 26 | protected const TAG = 1; 27 | 28 | /** 29 | * @var bool 30 | */ 31 | protected $includeValues = false; 32 | 33 | /** 34 | * @param OidList ...$oids 35 | */ 36 | public function __construct(OidList $oids) 37 | { 38 | parent::__construct(0, 0, 0, $oids); 39 | } 40 | 41 | /** 42 | * {@inheritdoc} 43 | */ 44 | public static function fromAsn1(AbstractType $type) 45 | { 46 | [$id, $errorStatus, $errorIndex, $oidList] = parent::getBaseElements($type); 47 | 48 | $nextRequest = new self($oidList); 49 | $nextRequest->id = $id; 50 | $nextRequest->errorStatus = $errorStatus; 51 | $nextRequest->errorIndex = $errorIndex; 52 | 53 | return $nextRequest; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/FreeDSx/Snmp/Request/GetRequest.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | 11 | namespace FreeDSx\Snmp\Request; 12 | 13 | use FreeDSx\Asn1\Type\AbstractType; 14 | use FreeDSx\Snmp\Message\Pdu; 15 | use FreeDSx\Snmp\OidList; 16 | 17 | /** 18 | * Represents a Get Request. 19 | * 20 | * @author Chad Sikorra 21 | */ 22 | class GetRequest extends Pdu implements RequestInterface 23 | { 24 | use RequestTrait; 25 | 26 | protected const TAG = 0; 27 | 28 | /** 29 | * @var bool 30 | */ 31 | protected $includeValues = false; 32 | 33 | /** 34 | * @param OidList $oids 35 | */ 36 | public function __construct(OidList $oids) 37 | { 38 | parent::__construct(0, 0, 0, $oids); 39 | } 40 | 41 | /** 42 | * {@inheritdoc} 43 | */ 44 | public static function fromAsn1(AbstractType $type) 45 | { 46 | list($id, $errorStatus, $errorIndex, $oidList) = parent::getBaseElements($type); 47 | 48 | $getRequest = new self($oidList); 49 | $getRequest->id = $id; 50 | $getRequest->errorStatus = $errorStatus; 51 | $getRequest->errorIndex = $errorIndex; 52 | 53 | return $getRequest; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/FreeDSx/Snmp/Request/InformRequest.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | 11 | namespace FreeDSx\Snmp\Request; 12 | 13 | use FreeDSx\Snmp\Message\Pdu; 14 | 15 | /** 16 | * Represents an Inform Request. 17 | * 18 | * @author Chad Sikorra 19 | */ 20 | class InformRequest extends Pdu implements RequestInterface 21 | { 22 | use TrapTrait, 23 | RequestTrait; 24 | 25 | protected const TAG = 6; 26 | } 27 | -------------------------------------------------------------------------------- /src/FreeDSx/Snmp/Request/RequestInterface.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | 11 | namespace FreeDSx\Snmp\Request; 12 | 13 | use FreeDSx\Snmp\Protocol\ProtocolElementInterface; 14 | 15 | /** 16 | * Interface that SNMP requests must implement. 17 | * 18 | * @author Chad Sikorra 19 | */ 20 | interface RequestInterface extends ProtocolElementInterface 21 | { 22 | /** 23 | * @return int 24 | */ 25 | public function getPduTag() : int; 26 | } 27 | -------------------------------------------------------------------------------- /src/FreeDSx/Snmp/Request/RequestTrait.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | 11 | namespace FreeDSx\Snmp\Request; 12 | 13 | use FreeDSx\Snmp\OidList; 14 | 15 | /** 16 | * Common elements of the SNMP request. 17 | * 18 | * @author Chad Sikorra 19 | */ 20 | trait RequestTrait 21 | { 22 | /** 23 | * @param OidList $oids 24 | * @return $this 25 | */ 26 | public function setOids(OidList $oids) 27 | { 28 | $this->oids = $oids; 29 | 30 | return $this; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/FreeDSx/Snmp/Request/SetRequest.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | 11 | namespace FreeDSx\Snmp\Request; 12 | 13 | use FreeDSx\Asn1\Type\AbstractType; 14 | use FreeDSx\Snmp\Message\Pdu; 15 | use FreeDSx\Snmp\OidList; 16 | 17 | /** 18 | * Represents a SetRequest. 19 | * 20 | * @author Chad Sikorra 21 | */ 22 | class SetRequest extends Pdu implements RequestInterface 23 | { 24 | use RequestTrait; 25 | 26 | protected const TAG = 3; 27 | 28 | /** 29 | * @param OidList $oids 30 | */ 31 | public function __construct(OidList $oids) 32 | { 33 | parent::__construct(0, 0, 0, $oids); 34 | } 35 | 36 | /** 37 | * {@inheritdoc} 38 | */ 39 | public static function fromAsn1(AbstractType $type) 40 | { 41 | list($id, $errorStatus, $errorIndex, $oidList) = parent::getBaseElements($type); 42 | 43 | $setRequest = new self($oidList); 44 | $setRequest->id = $id; 45 | $setRequest->errorStatus = $errorStatus; 46 | $setRequest->errorIndex = $errorIndex; 47 | 48 | return $setRequest; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/FreeDSx/Snmp/Request/TrapV2Request.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | 11 | namespace FreeDSx\Snmp\Request; 12 | 13 | use FreeDSx\Snmp\Message\Pdu; 14 | 15 | /** 16 | * RFC 3416, Section 4.2.6. Represents an SNMP v2 trap. 17 | * 18 | * @author Chad Sikorra 19 | */ 20 | class TrapV2Request extends Pdu implements RequestInterface 21 | { 22 | use TrapTrait, 23 | RequestTrait; 24 | 25 | protected const TAG = 7; 26 | } 27 | -------------------------------------------------------------------------------- /src/FreeDSx/Snmp/Response/ReportResponse.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | 11 | namespace FreeDSx\Snmp\Response; 12 | 13 | use FreeDSx\Snmp\Message\Pdu; 14 | 15 | /** 16 | * Represents a report response. RFC 3416, Section 3. 17 | * 18 | * @author Chad Sikorra 19 | */ 20 | class ReportResponse extends Pdu implements ResponseInterface 21 | { 22 | protected const TAG = 8; 23 | } 24 | -------------------------------------------------------------------------------- /src/FreeDSx/Snmp/Response/Response.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | 11 | namespace FreeDSx\Snmp\Response; 12 | 13 | use FreeDSx\Snmp\Message\Pdu; 14 | 15 | /** 16 | * Represents an SNMP Response PDU. 17 | * 18 | * @author Chad Sikorra 19 | */ 20 | class Response extends Pdu implements ResponseInterface 21 | { 22 | protected const TAG = 2; 23 | } 24 | -------------------------------------------------------------------------------- /src/FreeDSx/Snmp/Response/ResponseInterface.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | 11 | namespace FreeDSx\Snmp\Response; 12 | 13 | use FreeDSx\Snmp\Protocol\ProtocolElementInterface; 14 | 15 | /** 16 | * Interface that SNMP responses must implement. 17 | * 18 | * @author Chad Sikorra 19 | */ 20 | interface ResponseInterface extends ProtocolElementInterface 21 | { 22 | /** 23 | * @return int 24 | */ 25 | public function getPduTag() : int; 26 | } 27 | -------------------------------------------------------------------------------- /src/FreeDSx/Snmp/Server/ServerRunner/ServerRunnerInterface.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | 11 | namespace FreeDSx\Snmp\Server\ServerRunner; 12 | 13 | use FreeDSx\Socket\SocketServer; 14 | 15 | /** 16 | * Runs the server to support various transports / handling logic, etc. 17 | * 18 | * @author Chad Sikorra 19 | */ 20 | interface ServerRunnerInterface 21 | { 22 | /** 23 | * Runs the socket server to accept incoming client connections and dispatch them where needed. 24 | * 25 | * @param SocketServer $server 26 | */ 27 | public function run(SocketServer $server) : void; 28 | } 29 | -------------------------------------------------------------------------------- /src/FreeDSx/Snmp/Server/ServerRunner/TrapServerRunner.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | 11 | namespace FreeDSx\Snmp\Server\ServerRunner; 12 | 13 | use FreeDSx\Snmp\Protocol\TrapProtocolHandler; 14 | use FreeDSx\Socket\SocketServer; 15 | 16 | /** 17 | * Server for synchronous trap request handling. 18 | * 19 | * @author Chad Sikorra 20 | */ 21 | class TrapServerRunner implements ServerRunnerInterface 22 | { 23 | /** 24 | * @var array 25 | */ 26 | protected $options; 27 | 28 | /** 29 | * @var TrapProtocolHandler 30 | */ 31 | protected $handler; 32 | 33 | /** 34 | * @param TrapProtocolHandler $handler 35 | * @param array $options 36 | */ 37 | public function __construct(TrapProtocolHandler $handler, array $options = []) 38 | { 39 | $this->options = $options; 40 | $this->handler = $handler; 41 | } 42 | 43 | /** 44 | * {@inheritdoc} 45 | */ 46 | public function run(SocketServer $server) : void 47 | { 48 | while ($data = $server->receive($ipAddress)) { 49 | try { 50 | $this->handler->handle($ipAddress, $data, $this->options); 51 | } catch (\Exception|\Throwable $e) { 52 | } 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/FreeDSx/Snmp/Trap/TrapContext.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | 11 | namespace FreeDSx\Snmp\Trap; 12 | 13 | use FreeDSx\Snmp\Message\Pdu; 14 | use FreeDSx\Snmp\Message\Request\MessageRequestInterface; 15 | use FreeDSx\Snmp\Request\InformRequest; 16 | use FreeDSx\Snmp\Request\TrapV1Request; 17 | use FreeDSx\Snmp\Request\TrapV2Request; 18 | 19 | /** 20 | * Represents the context of the incoming trap request. 21 | * 22 | * @author Chad Sikorra 23 | */ 24 | class TrapContext 25 | { 26 | /** 27 | * @var string 28 | */ 29 | protected $ipAddress; 30 | 31 | /** 32 | * @var int 33 | */ 34 | protected $version; 35 | 36 | /** 37 | * @var MessageRequestInterface 38 | */ 39 | protected $message; 40 | 41 | /** 42 | * @param string $ipAddress 43 | * @param int $version 44 | * @param MessageRequestInterface $message 45 | */ 46 | public function __construct(string $ipAddress, int $version, MessageRequestInterface $message) 47 | { 48 | $this->ipAddress = $ipAddress; 49 | $this->version = $version; 50 | $this->message = $message; 51 | } 52 | 53 | /** 54 | * @return MessageRequestInterface 55 | */ 56 | public function getMessage() : MessageRequestInterface 57 | { 58 | return $this->message; 59 | } 60 | 61 | /** 62 | * Get the IP address that sent the trap. 63 | * 64 | * @return string 65 | */ 66 | public function getIpAddress() : string 67 | { 68 | return $this->ipAddress; 69 | } 70 | 71 | /** 72 | * @return Pdu|InformRequest|TrapV1Request|TrapV2Request 73 | */ 74 | public function getTrap(): Pdu 75 | { 76 | return $this->message->getRequest(); 77 | } 78 | 79 | /** 80 | * Get the SNMP version for the incoming trap. 81 | * 82 | * @return int 83 | */ 84 | public function getVersion() : int 85 | { 86 | return $this->version; 87 | } 88 | 89 | /** 90 | * @return bool 91 | */ 92 | public function isTrapV1() : bool 93 | { 94 | return ($this->message->getRequest() instanceof TrapV1Request); 95 | } 96 | 97 | /** 98 | * @return bool 99 | */ 100 | public function isTrapV2() : bool 101 | { 102 | return ($this->message->getRequest() instanceof TrapV2Request); 103 | } 104 | 105 | /** 106 | * @return bool 107 | */ 108 | public function isInformRequest() : bool 109 | { 110 | return ($this->message->getRequest() instanceof InformRequest); 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /src/FreeDSx/Snmp/Trap/TrapListenerInterface.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | 11 | namespace FreeDSx\Snmp\Trap; 12 | 13 | use FreeDSx\Snmp\Message\EngineId; 14 | use FreeDSx\Snmp\Module\SecurityModel\Usm\UsmUser; 15 | 16 | /** 17 | * Interface used in the trap sink to act on received traps. 18 | * 19 | * @author Chad Sikorra 20 | */ 21 | interface TrapListenerInterface 22 | { 23 | /** 24 | * Whether or not the host should be accepted. Return true to allow the trap, return false to deny it. 25 | * 26 | * @param string $ip 27 | * @return bool 28 | */ 29 | public function accept(string $ip) : bool; 30 | 31 | /** 32 | * Given an engineId/IP address, get the USM user information associated with it. This information is used to potentially 33 | * authenticate and/or decrypt an incoming SNMP v3 trap using the USM security model. 34 | * 35 | * To ignore a request by a specific engine ID and user, return null. 36 | * 37 | * @param EngineId $engineId 38 | * @param string $ipAddress 39 | * @param string $user 40 | * @return UsmUser 41 | */ 42 | public function getUsmUser(EngineId $engineId, string $ipAddress, string $user) : ?UsmUser; 43 | 44 | /** 45 | * Handle a received trap. 46 | * 47 | * @param TrapContext $context 48 | */ 49 | public function receive(TrapContext $context) : void; 50 | } 51 | -------------------------------------------------------------------------------- /src/FreeDSx/Snmp/TrapSink.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | 11 | namespace FreeDSx\Snmp; 12 | 13 | use FreeDSx\Snmp\Exception\ConnectionException; 14 | use FreeDSx\Snmp\Protocol\TrapProtocolHandler; 15 | use FreeDSx\Snmp\Server\ServerRunner\TrapServerRunner; 16 | use FreeDSx\Snmp\Server\ServerRunner\ServerRunnerInterface; 17 | use FreeDSx\Snmp\Trap\TrapListenerInterface; 18 | use FreeDSx\Socket\SocketServer; 19 | 20 | /** 21 | * Trap Sink to receive SNMP traps from remote hosts and take action on them. 22 | * 23 | * @author Chad Sikorra 24 | */ 25 | class TrapSink 26 | { 27 | /** 28 | * @var array 29 | */ 30 | protected $options =[ 31 | # The IP address to bind to 32 | 'ip' => '0.0.0.0', 33 | # The port that the traps will come in on 34 | 'port' => 162, 35 | 'transport' => 'udp', 36 | # If specified, only allow this SNMP version. 37 | 'version' => null, 38 | # If specified, only allow traps with this community string 39 | 'community' => null, 40 | # If specified, only these IPs are allowed (array or single IP) 41 | 'whitelist' => null, 42 | 'timeout_connect' => 5, 43 | ]; 44 | 45 | /** 46 | * @var TrapServerRunner|null 47 | */ 48 | protected $server; 49 | 50 | /** 51 | * @var TrapListenerInterface 52 | */ 53 | protected $listener; 54 | 55 | /** 56 | * @param TrapListenerInterface $listener 57 | * @param array $options 58 | */ 59 | public function __construct(TrapListenerInterface $listener, array $options = []) 60 | { 61 | $this->options = array_merge($this->options, $options); 62 | $this->listener = $listener; 63 | } 64 | 65 | /** 66 | * Start listening for traps. 67 | * 68 | * @throws ConnectionException 69 | */ 70 | public function listen() : void 71 | { 72 | try { 73 | $this->server()->run(SocketServer::bindUdp($this->options['ip'], $this->options['port'])); 74 | } catch (\FreeDSx\Socket\Exception\ConnectionException $e) { 75 | throw new ConnectionException($e->getMessage(), $e->getCode(), $e); 76 | } 77 | } 78 | 79 | /** 80 | * @return array 81 | */ 82 | public function getOptions() : array 83 | { 84 | return $this->options; 85 | } 86 | 87 | /** 88 | * @param array $options 89 | * @return $this 90 | */ 91 | public function setOptions(array $options) 92 | { 93 | $this->options = array_merge($this->options, $options); 94 | 95 | return $this; 96 | } 97 | 98 | /** 99 | * @param TrapServerRunner $server 100 | * @return $this 101 | */ 102 | public function setServer(TrapServerRunner $server) 103 | { 104 | $this->server = $server; 105 | 106 | return $this; 107 | } 108 | 109 | /** 110 | * @return ServerRunnerInterface 111 | */ 112 | protected function server() : ServerRunnerInterface 113 | { 114 | if (!$this->server) { 115 | $this->server = new TrapServerRunner( 116 | new TrapProtocolHandler($this->listener, $this->options), 117 | $this->options 118 | ); 119 | } 120 | 121 | return $this->server; 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /src/FreeDSx/Snmp/Value/AbstractValue.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | 11 | namespace FreeDSx\Snmp\Value; 12 | 13 | use FreeDSx\Asn1\Asn1; 14 | use FreeDSx\Asn1\Type\AbstractType; 15 | use FreeDSx\Asn1\Type\IncompleteType; 16 | use FreeDSx\Snmp\Exception\ProtocolException; 17 | use FreeDSx\Snmp\Protocol\ProtocolElementInterface; 18 | use FreeDSx\Snmp\Protocol\SnmpEncoder; 19 | 20 | /** 21 | * A base OID value / string representation. 22 | * 23 | * @author Chad Sikorra 24 | */ 25 | abstract class AbstractValue implements ProtocolElementInterface 26 | { 27 | protected const ASN1_TYPE = null; 28 | 29 | protected const ASN1_TAG = null; 30 | 31 | protected const ASN1_CLASS = null; 32 | 33 | /** 34 | * @var mixed 35 | */ 36 | protected $value; 37 | 38 | /** 39 | * @param mixed $value 40 | */ 41 | public function equals($value, bool $strict = true) : bool 42 | { 43 | if ($strict) { 44 | return $this->value === $value; 45 | } 46 | 47 | return $this->value == $value; 48 | } 49 | 50 | /** 51 | * @return string 52 | */ 53 | public function __toString() 54 | { 55 | return (string) $this->value; 56 | } 57 | 58 | /** 59 | * {@inheritdoc} 60 | */ 61 | public function toAsn1() : AbstractType 62 | { 63 | $typeClass = static::ASN1_CLASS; 64 | 65 | return Asn1::application( 66 | static::ASN1_TAG, 67 | new $typeClass($this->value) 68 | ); 69 | } 70 | 71 | /** 72 | * {@inheritdoc} 73 | */ 74 | public static function fromAsn1(AbstractType $type) 75 | { 76 | if (static::ASN1_TAG !== null && $type->getTagNumber() !== static::ASN1_TAG) { 77 | throw new ProtocolException(sprintf( 78 | 'Expected tag number %s for class "%s". Got %s.', 79 | static::ASN1_TAG, 80 | static::class, 81 | $type->getTagNumber() 82 | )); 83 | } 84 | if (!$type instanceof IncompleteType) { 85 | throw new ProtocolException(sprintf( 86 | 'Expected an IncompleteType. Got %s.', 87 | get_class($type) 88 | )); 89 | } 90 | 91 | return new static( 92 | (new SnmpEncoder()) 93 | ->complete($type, static::ASN1_TYPE) 94 | ->getValue() 95 | ); 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /src/FreeDSx/Snmp/Value/ArbitraryValue.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | 11 | namespace FreeDSx\Snmp\Value; 12 | 13 | use FreeDSx\Asn1\Type\AbstractType; 14 | use FreeDSx\Asn1\Type\OctetStringType; 15 | 16 | /** 17 | * Represents an SNMP opaque value. 18 | * 19 | * @author Chad Sikorra 20 | */ 21 | class ArbitraryValue extends AbstractValue 22 | { 23 | protected const ASN1_TYPE = AbstractType::TAG_TYPE_OCTET_STRING; 24 | 25 | protected const ASN1_TAG = 4; 26 | 27 | protected const ASN1_CLASS = OctetStringType::class; 28 | 29 | /** 30 | * @param mixed $value 31 | */ 32 | public function __construct($value) 33 | { 34 | $this->value = $value; 35 | } 36 | 37 | /** 38 | * @return mixed 39 | */ 40 | public function getValue() 41 | { 42 | return $this->value; 43 | } 44 | 45 | /** 46 | * @param mixed $value 47 | * @return $this 48 | */ 49 | public function setValue($value) 50 | { 51 | $this->value = $value; 52 | 53 | return $this; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/FreeDSx/Snmp/Value/BigCounterValue.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | 11 | namespace FreeDSx\Snmp\Value; 12 | 13 | use FreeDSx\Asn1\Type\AbstractType; 14 | use FreeDSx\Asn1\Type\IntegerType; 15 | use FreeDSx\Snmp\Exception\InvalidArgumentException; 16 | 17 | /** 18 | * Represents a big counter value. 19 | * 20 | * @author Chad Sikorra 21 | */ 22 | class BigCounterValue extends AbstractValue 23 | { 24 | protected const ASN1_TYPE = AbstractType::TAG_TYPE_INTEGER; 25 | 26 | protected const ASN1_TAG = 6; 27 | 28 | protected const ASN1_CLASS = IntegerType::class; 29 | 30 | /** 31 | * @param int|string $value 32 | */ 33 | public function __construct($value) 34 | { 35 | $this->validate($value); 36 | $this->value = $value; 37 | } 38 | 39 | /** 40 | * @return string|int 41 | */ 42 | public function getValue() 43 | { 44 | return $this->value; 45 | } 46 | 47 | /** 48 | * @param int|string $value 49 | * @return BigCounterValue 50 | */ 51 | public function setValue($value) 52 | { 53 | $this->validate($value); 54 | $this->value = $value; 55 | 56 | return $this; 57 | } 58 | 59 | /** 60 | * Whether or not the contained value is larger than the PHP_INT_MAX value (represented as a string value). 61 | * 62 | * @return bool 63 | */ 64 | public function isBigInt() : bool 65 | { 66 | if (\is_int($this->value)) { 67 | return false; 68 | } 69 | 70 | return \is_float($this->value + 0); 71 | } 72 | 73 | /** 74 | * @param mixed $integer 75 | */ 76 | protected function validate($integer) : void 77 | { 78 | if (\is_int($integer)) { 79 | return; 80 | } 81 | if (\is_string($integer) && \is_numeric($integer) && \strpos($integer, '.') === false) { 82 | return; 83 | } 84 | 85 | throw new InvalidArgumentException('The value passed to the BigCounter class must be numeric.'); 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /src/FreeDSx/Snmp/Value/CounterValue.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | 11 | namespace FreeDSx\Snmp\Value; 12 | 13 | use FreeDSx\Asn1\Type\AbstractType; 14 | use FreeDSx\Asn1\Type\IntegerType; 15 | 16 | /** 17 | * Represents an SNMP counter value. 18 | * 19 | * @author Chad Sikorra 20 | */ 21 | class CounterValue extends AbstractValue 22 | { 23 | protected const ASN1_TYPE = AbstractType::TAG_TYPE_INTEGER; 24 | 25 | protected const ASN1_TAG = 1; 26 | 27 | protected const ASN1_CLASS = IntegerType::class; 28 | 29 | public function __construct(int $value) 30 | { 31 | $this->value = $value; 32 | } 33 | 34 | /** 35 | * @return int 36 | */ 37 | public function getValue(): int 38 | { 39 | return $this->value; 40 | } 41 | 42 | /** 43 | * @param int $value 44 | */ 45 | public function setValue(int $value): void 46 | { 47 | $this->value = $value; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/FreeDSx/Snmp/Value/IntegerValue.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | 11 | namespace FreeDSx\Snmp\Value; 12 | 13 | use FreeDSx\Asn1\Asn1; 14 | use FreeDSx\Asn1\Type\AbstractType; 15 | use FreeDSx\Asn1\Type\IntegerType; 16 | use FreeDSx\Snmp\Exception\ProtocolException; 17 | 18 | /** 19 | * Represents a simple integer type. 20 | * 21 | * @author Chad Sikorra 22 | */ 23 | class IntegerValue extends AbstractValue 24 | { 25 | /** 26 | * @param int $value 27 | */ 28 | public function __construct(int $value) 29 | { 30 | $this->value = $value; 31 | } 32 | 33 | /** 34 | * @return int 35 | */ 36 | public function getValue(): int 37 | { 38 | return $this->value; 39 | } 40 | 41 | /** 42 | * @param int $value 43 | * @return IntegerValue 44 | */ 45 | public function setValue(int $value) 46 | { 47 | $this->value = $value; 48 | 49 | return $this; 50 | } 51 | 52 | /** 53 | * {@inheritdoc} 54 | */ 55 | public function toAsn1(): AbstractType 56 | { 57 | return Asn1::integer($this->value); 58 | } 59 | 60 | /** 61 | * {@inheritdoc} 62 | */ 63 | public static function fromAsn1(AbstractType $type) 64 | { 65 | if (!$type instanceof IntegerType) { 66 | throw new ProtocolException(sprintf( 67 | 'The simple integer value must be an ASN.1 integer type. Got %s.', 68 | get_class($type) 69 | )); 70 | } 71 | 72 | return new self($type->getValue()); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/FreeDSx/Snmp/Value/IpAddressValue.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | 11 | namespace FreeDSx\Snmp\Value; 12 | 13 | use FreeDSx\Asn1\Asn1; 14 | use FreeDSx\Asn1\Type\AbstractType; 15 | use FreeDSx\Asn1\Type\OctetStringType; 16 | use FreeDSx\Snmp\Exception\ProtocolException; 17 | 18 | /** 19 | * Represents an IP address value (from network byte order). 20 | * 21 | * @author Chad Sikorra 22 | */ 23 | class IpAddressValue extends AbstractValue 24 | { 25 | protected const ASN1_TYPE = AbstractType::TAG_TYPE_OCTET_STRING; 26 | 27 | protected const ASN1_TAG = 0; 28 | 29 | protected const ASN1_CLASS = OctetStringType::class; 30 | 31 | /** 32 | * @param string $value 33 | */ 34 | public function __construct(string $value) 35 | { 36 | $this->value = $value; 37 | } 38 | 39 | public function setValue(string $value) : void 40 | { 41 | $this->value = $value; 42 | } 43 | 44 | /** 45 | * @return string 46 | */ 47 | public function getValue() : string 48 | { 49 | return $this->value; 50 | } 51 | 52 | /** 53 | * {@inheritdoc} 54 | */ 55 | public function toAsn1(): AbstractType 56 | { 57 | return Asn1::application( 58 | self::ASN1_TAG, 59 | Asn1::octetString(\pack('N', \ip2long($this->value))) 60 | ); 61 | } 62 | 63 | /** 64 | * {@inheritdoc} 65 | */ 66 | public static function fromAsn1(AbstractType $type) 67 | { 68 | $ip = parent::fromAsn1($type); 69 | 70 | $value = @\unpack("Nip", $ip->value); 71 | if (!(is_array($value) && isset($value['ip']) && is_int($value['ip']))) { 72 | throw new ProtocolException('Unable to parse IP address value.'); 73 | } 74 | $ip->value = \long2ip($value['ip']); 75 | 76 | return $ip; 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /src/FreeDSx/Snmp/Value/OidValue.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | 11 | namespace FreeDSx\Snmp\Value; 12 | 13 | use FreeDSx\Asn1\Asn1; 14 | use FreeDSx\Asn1\Type\AbstractType; 15 | use FreeDSx\Asn1\Type\OidType; 16 | use FreeDSx\Snmp\Exception\ProtocolException; 17 | 18 | /** 19 | * Represents a simple OID value. 20 | * 21 | * @author Chad Sikorra 22 | */ 23 | class OidValue extends AbstractValue 24 | { 25 | /** 26 | * @param string $value 27 | */ 28 | public function __construct(string $value) 29 | { 30 | $this->value = $value; 31 | } 32 | 33 | /** 34 | * @return string 35 | */ 36 | public function getValue(): string 37 | { 38 | return $this->value; 39 | } 40 | 41 | /** 42 | * @param string $value 43 | * @return OidValue 44 | */ 45 | public function setValue(string $value) 46 | { 47 | $this->value = $value; 48 | 49 | return $this; 50 | } 51 | 52 | /** 53 | * {@inheritdoc} 54 | */ 55 | public function toAsn1(): AbstractType 56 | { 57 | return Asn1::oid($this->value); 58 | } 59 | 60 | /** 61 | * {@inheritdoc} 62 | */ 63 | public static function fromAsn1(AbstractType $type) 64 | { 65 | if (!$type instanceof OidType) { 66 | throw new ProtocolException(sprintf( 67 | 'The simple oid value must be an ASN.1 OID type. Got %s.', 68 | get_class($type) 69 | )); 70 | } 71 | 72 | return new self($type->getValue()); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/FreeDSx/Snmp/Value/StringValue.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | 11 | namespace FreeDSx\Snmp\Value; 12 | 13 | use FreeDSx\Asn1\Asn1; 14 | use FreeDSx\Asn1\Type\AbstractType; 15 | use FreeDSx\Asn1\Type\OctetStringType; 16 | use FreeDSx\Snmp\Exception\ProtocolException; 17 | 18 | /** 19 | * Represents a simple string type value. 20 | * 21 | * @author Chad Sikorra 22 | */ 23 | class StringValue extends AbstractValue 24 | { 25 | /** 26 | * @param string $value 27 | */ 28 | public function __construct($value) 29 | { 30 | $this->value = $value; 31 | } 32 | 33 | /** 34 | * @return string 35 | */ 36 | public function getValue() 37 | { 38 | return $this->value; 39 | } 40 | 41 | /** 42 | * @param mixed $value 43 | * @return StringValue 44 | */ 45 | public function setValue($value) 46 | { 47 | $this->value = $value; 48 | 49 | return $this; 50 | } 51 | 52 | /** 53 | * {@inheritdoc} 54 | */ 55 | public function toAsn1(): AbstractType 56 | { 57 | return Asn1::octetString($this->value); 58 | } 59 | 60 | /** 61 | * {@inheritdoc} 62 | */ 63 | public static function fromAsn1(AbstractType $type) 64 | { 65 | if (!$type instanceof OctetStringType) { 66 | throw new ProtocolException(sprintf( 67 | 'The simple string value must be an ASN.1 octet string type. Got %s.', 68 | get_class($type) 69 | )); 70 | } 71 | 72 | return new self($type->getValue()); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/FreeDSx/Snmp/Value/TimeTicksValue.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | 11 | namespace FreeDSx\Snmp\Value; 12 | 13 | use FreeDSx\Asn1\Type\AbstractType; 14 | use FreeDSx\Asn1\Type\IntegerType; 15 | 16 | /** 17 | * Represents an SNMP time ticks value. 18 | * 19 | * @author Chad Sikorra 20 | */ 21 | class TimeTicksValue extends AbstractValue 22 | { 23 | protected const ASN1_TYPE = AbstractType::TAG_TYPE_INTEGER; 24 | 25 | protected const ASN1_TAG = 3; 26 | 27 | protected const ASN1_CLASS = IntegerType::class; 28 | 29 | public function __construct(int $value) 30 | { 31 | $this->value = $value; 32 | } 33 | 34 | /** 35 | * @param int $value 36 | * @return TimeTicksValue 37 | */ 38 | public function setValue(int $value) 39 | { 40 | $this->value = $value; 41 | 42 | return $this; 43 | } 44 | 45 | /** 46 | * @return int 47 | */ 48 | public function getValue() : int 49 | { 50 | return $this->value; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/FreeDSx/Snmp/Value/UnsignedIntegerValue.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | 11 | namespace FreeDSx\Snmp\Value; 12 | 13 | use FreeDSx\Asn1\Type\AbstractType; 14 | use FreeDSx\Asn1\Type\IntegerType; 15 | 16 | /** 17 | * Represents an SNMP unsigned integer value. 18 | * 19 | * @author Chad Sikorra 20 | */ 21 | class UnsignedIntegerValue extends AbstractValue 22 | { 23 | protected const ASN1_TYPE = AbstractType::TAG_TYPE_INTEGER; 24 | 25 | protected const ASN1_TAG = 2; 26 | 27 | protected const ASN1_CLASS = IntegerType::class; 28 | 29 | /** 30 | * @param int $value 31 | */ 32 | public function __construct(int $value) 33 | { 34 | $this->value = $value; 35 | } 36 | 37 | /** 38 | * @return int 39 | */ 40 | public function getValue() : int 41 | { 42 | return $this->value; 43 | } 44 | 45 | /** 46 | * @param int $value 47 | * @return UnsignedIntegerValue 48 | */ 49 | public function setValue(int $value) 50 | { 51 | $this->value = $value; 52 | 53 | return $this; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /tests/bin/trapsink.php: -------------------------------------------------------------------------------- 1 | getTrap(); 30 | $version = $context->getVersion(); 31 | $ip = $context->getIpAddress(); 32 | 33 | if ($trap instanceof TrapV2Request) { 34 | echo "---received---, IP: $ip, Version: $version, Trap: {$trap->getTrapOid()->getValue()}"; 35 | } elseif ($trap instanceof TrapV1Request) { 36 | echo "---received---, IP: $ip, Version: $version, Trap: {$trap->getEnterprise()}"; 37 | } 38 | } 39 | }; 40 | 41 | echo "server starting..."; 42 | 43 | $sink = new TrapSink( 44 | $listener, 45 | [ 46 | 'port' => 10162, 47 | ] 48 | ); 49 | $sink->listen(); 50 | -------------------------------------------------------------------------------- /tests/integration/FreeDSx/Snmp/SnmpClientTest.php: -------------------------------------------------------------------------------- 1 | subject = $this->makeClient(); 20 | } 21 | 22 | public function testGetReturnsOidListWithValue(): void 23 | { 24 | $value = $this->subject->get('1.3.6.1.2.1.1.1.0'); 25 | 26 | $this->assertCount(1, $value); 27 | $this->assertStringContainsStringIgnoringCase( 28 | 'Linux', 29 | (string)$value->first()->getValue() 30 | ); 31 | } 32 | 33 | public function testGetValueReturnsSingleOidValue(): void 34 | { 35 | $value = $this->subject->getValue('1.3.6.1.2.1.1.1.0'); 36 | 37 | $this->assertIsString($value); 38 | $this->assertStringContainsStringIgnoringCase( 39 | 'Linux', 40 | $value 41 | ); 42 | } 43 | 44 | public function testGetOidReturnsSingleOid(): void 45 | { 46 | $oid = $this->subject->getOid('1.3.6.1.2.1.1.1.0'); 47 | 48 | $this->assertInstanceOf( 49 | Oid::class, 50 | $oid 51 | ); 52 | $this->assertStringContainsStringIgnoringCase( 53 | 'Linux', 54 | $oid->getValue() 55 | ); 56 | } 57 | 58 | /** 59 | * In theory, the test below should work. When SNMPv2-MIB::snmpSetSerialNo is used, it should just increment. 60 | * Perhaps something wrong with the config, or it is specific to the use in docker? Needs investigation. 61 | * 62 | * For now this just tests that the "set" was attempted, and we expect a message back that it was rejected. 63 | */ 64 | public function testItCanModifyAnOidValueWithSet(): void 65 | { 66 | $this->subject = $this->makeClient(['community' => getenv('SNMP_COMMUNITY_RW')]); 67 | $value = $this->subject->getValue('1.3.6.1.6.3.1.1.6.1.0'); 68 | 69 | $message = ''; 70 | try { 71 | $this->subject->set(Oid::fromInteger( 72 | '1.3.6.1.6.3.1.1.6.1.0', 73 | (int)$value 74 | )); 75 | } catch (SnmpRequestException $e) { 76 | $message = $e->getMessage(); 77 | } 78 | 79 | $this->assertStringContainsString( 80 | '(WrongLength)', 81 | $message 82 | ); 83 | } 84 | 85 | public function testGetNextReturnsTheNextOid(): void 86 | { 87 | $oid = $this->subject->getNext('1.3.6.1.2.1.1.1.0')->first(); 88 | 89 | $this->assertNotNull($oid); 90 | $this->assertEquals( 91 | '1.3.6.1.2.1.1.2.0', 92 | $oid->getOid() 93 | ); 94 | } 95 | 96 | public function testGetBulkReturnsAllExpected(): void 97 | { 98 | $oids = $this->subject->getBulk( 99 | 9, 100 | 0, 101 | '1.3.6.1.2.1.1.1' 102 | ); 103 | $first = $oids->first(); 104 | $last = $oids->last(); 105 | 106 | $this->assertCount( 107 | 9, 108 | $oids 109 | ); 110 | $this->assertEquals( 111 | '1.3.6.1.2.1.1.1.0', 112 | $first->getOid() 113 | ); 114 | $this->assertEquals( 115 | '1.3.6.1.2.1.1.9.1.2.2', 116 | $last->getOid() 117 | ); 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /tests/integration/FreeDSx/Snmp/SnmpWalkTest.php: -------------------------------------------------------------------------------- 1 | client = $this->makeClient(); 19 | } 20 | 21 | public function testItWalksAllOids() 22 | { 23 | $walk = $this->client->walk(); 24 | 25 | while($walk->hasOids()) { 26 | $oid = $walk->next(); 27 | 28 | $this->assertInstanceOf( 29 | Oid::class, 30 | $oid 31 | ); 32 | } 33 | 34 | $this->assertGreaterThan( 35 | 1, 36 | $walk->count() 37 | ); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /tests/integration/FreeDSx/Snmp/TestCase.php: -------------------------------------------------------------------------------- 1 | defaultOptions(), 14 | $options 15 | )); 16 | } 17 | 18 | private function defaultOptions(): array 19 | { 20 | return [ 21 | 'version' => 2, 22 | 'community' => getenv('SNMP_COMMUNITY_RO'), 23 | 'user' => getenv('SNMP_USER'), 24 | 'use_auth' => true, 25 | 'auth_pwd' => getenv('SNMP_PASS_USER'), 26 | 'auth_mech' => 'md5', 27 | 'use_priv' => false, 28 | 'priv_mech' => 'des', 29 | 'priv_pwd' => getenv('SNMP_PASS_PRIV'), 30 | 'host' => getenv('SNMP_SERVER'), 31 | 'port' => (int) getenv('SNMP_PORT'), 32 | ]; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /tests/resources/snmpd.conf: -------------------------------------------------------------------------------- 1 | #### 2 | # First, map the community name "public" into a "security name" 3 | 4 | # sec.name source community 5 | com2sec notConfigUser default public 6 | com2sec configUser default secret 7 | 8 | #### 9 | # Second, map the security name into a group name: 10 | 11 | # groupName securityModel securityName 12 | group notConfigGroup v1 notConfigUser 13 | group notConfigGroup v2c notConfigUser 14 | group configGroup v2c configUser 15 | 16 | #### 17 | # Third, create a view for us to let the group have rights to: 18 | 19 | # Make at least snmpwalk -v 1 localhost -c public system fast again. 20 | # name incl/excl subtree mask(optional) 21 | view systemview included .1.3.6.1.2.1.1 22 | view systemview included .1.3.6.1.2.1.25.1.1 23 | view all included .1 24 | 25 | #### 26 | # Finally, grant the group read-only access to the systemview view. 27 | 28 | # group context sec.model sec.level prefix read write notif 29 | access notConfigGroup "" any noauth exact systemview none none 30 | access configGroup "" any noauth exact all all none 31 | 32 | syslocation Unknown (edit /etc/snmp/snmpd.conf) 33 | syscontact Root (configure /etc/snmp/snmp.local.conf) 34 | 35 | dontLogTCPWrappersConnects yes 36 | -------------------------------------------------------------------------------- /tests/spec/FreeDSx/Snmp/Exception/ConnectionExceptionSpec.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | 11 | namespace spec\FreeDSx\Snmp\Exception; 12 | 13 | use FreeDSx\Snmp\Exception\ConnectionException; 14 | use PhpSpec\ObjectBehavior; 15 | 16 | class ConnectionExceptionSpec extends ObjectBehavior 17 | { 18 | function it_is_initializable() 19 | { 20 | $this->shouldHaveType(ConnectionException::class); 21 | } 22 | 23 | function it_should_extend_exception() 24 | { 25 | $this->shouldBeAnInstanceOf(\Exception::class); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /tests/spec/FreeDSx/Snmp/Exception/InvalidArgumentExceptionSpec.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | 11 | namespace spec\FreeDSx\Snmp\Exception; 12 | 13 | use FreeDSx\Snmp\Exception\InvalidArgumentException; 14 | use PhpSpec\ObjectBehavior; 15 | 16 | class InvalidArgumentExceptionSpec extends ObjectBehavior 17 | { 18 | function it_is_initializable() 19 | { 20 | $this->shouldHaveType(InvalidArgumentException::class); 21 | } 22 | 23 | function it_should_extend_the_root_invalid_argument_exception() 24 | { 25 | $this->shouldBeAnInstanceOf(\InvalidArgumentException::class); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /tests/spec/FreeDSx/Snmp/Exception/ProtocolExceptionSpec.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | 11 | namespace spec\FreeDSx\Snmp\Exception; 12 | 13 | use FreeDSx\Snmp\Exception\ProtocolException; 14 | use PhpSpec\ObjectBehavior; 15 | 16 | class ProtocolExceptionSpec extends ObjectBehavior 17 | { 18 | function it_is_initializable() 19 | { 20 | $this->shouldHaveType(ProtocolException::class); 21 | } 22 | 23 | function it_should_extend_exception() 24 | { 25 | $this->shouldBeAnInstanceOf(\Exception::class); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /tests/spec/FreeDSx/Snmp/Exception/RediscoveryNeededExceptionSpec.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | 11 | namespace spec\FreeDSx\Snmp\Exception; 12 | 13 | use FreeDSx\Snmp\Exception\RediscoveryNeededException; 14 | use FreeDSx\Snmp\Exception\SnmpRequestException; 15 | use FreeDSx\Snmp\Message\MessageHeader; 16 | use FreeDSx\Snmp\Message\Response\MessageResponseV3; 17 | use FreeDSx\Snmp\Message\ScopedPduResponse; 18 | use FreeDSx\Snmp\Oid; 19 | use FreeDSx\Snmp\OidList; 20 | use FreeDSx\Snmp\Response\ReportResponse; 21 | use PhpSpec\ObjectBehavior; 22 | 23 | class RediscoveryNeededExceptionSpec extends ObjectBehavior 24 | { 25 | function let() 26 | { 27 | $this->beConstructedWith(new MessageResponseV3( 28 | new MessageHeader(1), 29 | new ScopedPduResponse(new ReportResponse(1, 2, 1, new OidList(new Oid('1.2.3')))) 30 | )); 31 | } 32 | 33 | function it_is_initializable() 34 | { 35 | $this->shouldHaveType(RediscoveryNeededException::class); 36 | } 37 | 38 | function it_should_be_an_instance_of_snmp_request_exception() 39 | { 40 | $this->shouldBeAnInstanceOf(SnmpRequestException::class); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /tests/spec/FreeDSx/Snmp/Exception/RuntimeExceptionSpec.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | 11 | namespace spec\FreeDSx\Snmp\Exception; 12 | 13 | use FreeDSx\Snmp\Exception\RuntimeException; 14 | use PhpSpec\ObjectBehavior; 15 | 16 | class RuntimeExceptionSpec extends ObjectBehavior 17 | { 18 | function it_is_initializable() 19 | { 20 | $this->shouldHaveType(RuntimeException::class); 21 | } 22 | 23 | function it_should_extend_the_root_runtime_exception() 24 | { 25 | $this->shouldBeAnInstanceOf(\RuntimeException::class); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /tests/spec/FreeDSx/Snmp/Exception/SecurityModelExceptionSpec.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | 11 | namespace spec\FreeDSx\Snmp\Exception; 12 | 13 | use FreeDSx\Snmp\Exception\SecurityModelException; 14 | use PhpSpec\ObjectBehavior; 15 | 16 | class SecurityModelExceptionSpec extends ObjectBehavior 17 | { 18 | function it_is_initializable() 19 | { 20 | $this->shouldHaveType(SecurityModelException::class); 21 | } 22 | 23 | function it_should_extend_exception() 24 | { 25 | $this->shouldBeAnInstanceOf(\Exception::class); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /tests/spec/FreeDSx/Snmp/Exception/SnmpAuthenticationExceptionSpec.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | 11 | namespace spec\FreeDSx\Snmp\Exception; 12 | 13 | use FreeDSx\Snmp\Exception\SnmpAuthenticationException; 14 | use PhpSpec\ObjectBehavior; 15 | 16 | class SnmpAuthenticationExceptionSpec extends ObjectBehavior 17 | { 18 | function it_is_initializable() 19 | { 20 | $this->shouldHaveType(SnmpAuthenticationException::class); 21 | } 22 | 23 | function it_should_extend_exception() 24 | { 25 | $this->shouldBeAnInstanceOf(\Exception::class); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /tests/spec/FreeDSx/Snmp/Exception/SnmpEncryptionExceptionSpec.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | 11 | namespace spec\FreeDSx\Snmp\Exception; 12 | 13 | use FreeDSx\Snmp\Exception\SnmpEncryptionException; 14 | use PhpSpec\ObjectBehavior; 15 | 16 | class SnmpEncryptionExceptionSpec extends ObjectBehavior 17 | { 18 | function it_is_initializable() 19 | { 20 | $this->shouldHaveType(SnmpEncryptionException::class); 21 | } 22 | 23 | function it_should_extend_exception() 24 | { 25 | $this->shouldBeAnInstanceOf(\Exception::class); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /tests/spec/FreeDSx/Snmp/Exception/SnmpRequestExceptionSpec.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | 11 | namespace spec\FreeDSx\Snmp\Exception; 12 | 13 | use FreeDSx\Snmp\Exception\SnmpRequestException; 14 | use FreeDSx\Snmp\Message\ErrorStatus; 15 | use FreeDSx\Snmp\Message\Response\MessageResponseInterface; 16 | use FreeDSx\Snmp\Message\Response\MessageResponseV2; 17 | use FreeDSx\Snmp\Oid; 18 | use FreeDSx\Snmp\OidList; 19 | use FreeDSx\Snmp\Response\Response; 20 | use FreeDSx\Snmp\Response\ResponseInterface; 21 | use PhpSpec\ObjectBehavior; 22 | 23 | class SnmpRequestExceptionSpec extends ObjectBehavior 24 | { 25 | function let() 26 | { 27 | $this->beConstructedWith(new MessageResponseV2('foo', new Response(1, 2, 1, new OidList( 28 | new Oid('1.2.3') 29 | )))); 30 | } 31 | 32 | function it_is_initializable() 33 | { 34 | $this->shouldHaveType(SnmpRequestException::class); 35 | } 36 | 37 | function it_should_extend_exception() 38 | { 39 | $this->shouldBeAnInstanceOf(\Exception::class); 40 | } 41 | 42 | function it_should_get_the_snmp_message() 43 | { 44 | $this->getSnmpMessage()->shouldBeAnInstanceOf(MessageResponseInterface::class); 45 | } 46 | 47 | function it_should_get_the_snmp_response() 48 | { 49 | $this->getResponse()->shouldBeAnInstanceOf(ResponseInterface::class); 50 | } 51 | 52 | function it_should_get_the_formatted_message() 53 | { 54 | $this->getMessage()->shouldBeEqualTo('The requested OID (1.2.3) cannot be returned (NoSuchName).'); 55 | } 56 | 57 | function it_should_allow_overriding_the_message_if_specified_on_construction(MessageResponseInterface $response) 58 | { 59 | $this->beConstructedWith(new MessageResponseV2('foo', new Response(1, ErrorStatus::GEN_ERROR)), 'foo'); 60 | 61 | $this->getMessage()->shouldBeEqualTo('foo'); 62 | } 63 | 64 | function it_should_allow_the_snmp_message_to_be_nullable() 65 | { 66 | $this->beConstructedWith(null, 'foo'); 67 | 68 | $this->getMessage()->shouldBeEqualTo('foo'); 69 | $this->getSnmpMessage()->shouldBeNull(); 70 | $this->getResponse()->shouldBeNull(); 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /tests/spec/FreeDSx/Snmp/Exception/UnexpectedValueExceptionSpec.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | 11 | namespace spec\FreeDSx\Snmp\Exception; 12 | 13 | use FreeDSx\Snmp\Exception\UnexpectedValueException; 14 | use PhpSpec\ObjectBehavior; 15 | 16 | class UnexpectedValueExceptionSpec extends ObjectBehavior 17 | { 18 | function it_is_initializable() 19 | { 20 | $this->shouldHaveType(UnexpectedValueException::class); 21 | } 22 | 23 | function it_should_extend_UnexpectedValueException() 24 | { 25 | $this->shouldBeAnInstanceOf(\UnexpectedValueException::class); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /tests/spec/FreeDSx/Snmp/Message/PduSpec.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | 11 | namespace spec\FreeDSx\Snmp\Message; 12 | 13 | use FreeDSx\Asn1\Asn1; 14 | use FreeDSx\Asn1\Type\IncompleteType; 15 | use FreeDSx\Snmp\Message\Pdu; 16 | use FreeDSx\Snmp\OidList; 17 | use FreeDSx\Snmp\Protocol\ProtocolElementInterface; 18 | use FreeDSx\Snmp\Protocol\SnmpEncoder; 19 | use PhpSpec\ObjectBehavior; 20 | 21 | class PduSpec extends ObjectBehavior 22 | { 23 | function let() 24 | { 25 | $this->beConstructedWith(1); 26 | } 27 | 28 | function it_is_initializable() 29 | { 30 | $this->shouldHaveType(Pdu::class); 31 | } 32 | 33 | function it_should_implement_protocol_element_interface() 34 | { 35 | $this->shouldImplement(ProtocolElementInterface::class); 36 | } 37 | 38 | function it_should_get_the_id() 39 | { 40 | $this->getId()->shouldBeEqualTo(1); 41 | } 42 | 43 | function it_should_get_the_error_status() 44 | { 45 | $this->getErrorStatus()->shouldBeEqualTo(0); 46 | } 47 | 48 | function it_should_get_the_error_index() 49 | { 50 | $this->getErrorIndex()->shouldBeEqualTo(0); 51 | } 52 | 53 | function it_should_get_the_oid_list() 54 | { 55 | $this->getOids()->shouldBeLike(new OidList()); 56 | } 57 | 58 | function it_should_have_an_ASN1_representation() 59 | { 60 | $this->toAsn1()->shouldBeLike(Asn1::context(0, Asn1::sequence( 61 | Asn1::integer(1), 62 | Asn1::integer(0), 63 | Asn1::integer(0), 64 | Asn1::sequenceOf() 65 | ))); 66 | } 67 | 68 | function it_should_be_constructed_from_an_ASN1_representation() 69 | { 70 | $pdu = Asn1::sequence( 71 | Asn1::integer(1), 72 | Asn1::integer(0), 73 | Asn1::integer(0), 74 | Asn1::sequenceOf() 75 | ); 76 | 77 | $encoder = new SnmpEncoder(); 78 | $pduEncoded = ''; 79 | foreach ($pdu as $element) { 80 | $pduEncoded .= $encoder->encode($element); 81 | } 82 | 83 | $pdu = new IncompleteType($pduEncoded); 84 | $pdu = Asn1::context(0, $pdu)->setIsConstructed(true); 85 | 86 | $this::fromAsn1($pdu)->shouldBeLike(new Pdu(1)); 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /tests/spec/FreeDSx/Snmp/Message/Request/MessageRequestV1Spec.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | 11 | namespace spec\FreeDSx\Snmp\Message\Request; 12 | 13 | use FreeDSx\Asn1\Asn1; 14 | use FreeDSx\Asn1\Type\IncompleteType; 15 | use FreeDSx\Snmp\Message\AbstractMessage; 16 | use FreeDSx\Snmp\Message\Request\MessageRequestInterface; 17 | use FreeDSx\Snmp\Message\Request\MessageRequestV1; 18 | use FreeDSx\Snmp\OidList; 19 | use FreeDSx\Snmp\Protocol\SnmpEncoder; 20 | use FreeDSx\Snmp\Request\GetRequest; 21 | use PhpSpec\ObjectBehavior; 22 | 23 | class MessageRequestV1Spec extends ObjectBehavior 24 | { 25 | function let() 26 | { 27 | $this->beConstructedWith('foo', new GetRequest(new OidList())); 28 | } 29 | 30 | function it_is_initializable() 31 | { 32 | $this->shouldHaveType(MessageRequestV1::class); 33 | } 34 | 35 | function it_should_implement_MessageRequestInterface() 36 | { 37 | $this->shouldImplement(MessageRequestInterface::class); 38 | } 39 | 40 | function it_should_extend_abstract_message() 41 | { 42 | $this->shouldBeAnInstanceOf(AbstractMessage::class); 43 | } 44 | 45 | function it_should_get_the_community() 46 | { 47 | $this->getCommunity()->shouldBeEqualTo('foo'); 48 | } 49 | 50 | function it_should_set_the_community() 51 | { 52 | $this->setCommunity('bar'); 53 | 54 | $this->getCommunity()->shouldBeEqualTo('bar'); 55 | } 56 | 57 | function it_should_get_the_version() 58 | { 59 | $this->getVersion()->shouldBeEqualTo(0); 60 | } 61 | 62 | function it_should_have_an_ASN1_representation() 63 | { 64 | $this->toAsn1()->shouldBeLike(Asn1::sequence( 65 | Asn1::integer(0), 66 | Asn1::octetString('foo'), 67 | (new GetRequest(new OidList()))->toAsn1() 68 | )); 69 | } 70 | 71 | function it_should_be_constructed_from_an_ASN1_representation() 72 | { 73 | $encoder = new SnmpEncoder(); 74 | 75 | $pdu = ''; 76 | foreach ((new GetRequest(new OidList()))->toAsn1() as $child) { 77 | $pdu .= $encoder->encode($child); 78 | } 79 | 80 | $this::fromAsn1(Asn1::sequence( 81 | Asn1::integer(0), 82 | Asn1::octetString('foo'), 83 | Asn1::context(0, new IncompleteType($pdu))->setIsConstructed(true) 84 | 85 | ))->shouldBeLike(new MessageRequestV1('foo', new GetRequest(new OidList()))); 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /tests/spec/FreeDSx/Snmp/Message/Request/MessageRequestV2Spec.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | 11 | namespace spec\FreeDSx\Snmp\Message\Request; 12 | 13 | use FreeDSx\Asn1\Asn1; 14 | use FreeDSx\Asn1\Type\IncompleteType; 15 | use FreeDSx\Snmp\Message\AbstractMessage; 16 | use FreeDSx\Snmp\Message\Request\MessageRequestInterface; 17 | use FreeDSx\Snmp\Message\Request\MessageRequestV2; 18 | use FreeDSx\Snmp\OidList; 19 | use FreeDSx\Snmp\Protocol\SnmpEncoder; 20 | use FreeDSx\Snmp\Request\GetRequest; 21 | use PhpSpec\ObjectBehavior; 22 | 23 | class MessageRequestV2Spec extends ObjectBehavior 24 | { 25 | function let() 26 | { 27 | $this->beConstructedWith('foo', new GetRequest(new OidList())); 28 | } 29 | 30 | function it_is_initializable() 31 | { 32 | $this->shouldHaveType(MessageRequestV2::class); 33 | } 34 | 35 | function it_should_implement_MessageRequestInterface() 36 | { 37 | $this->shouldImplement(MessageRequestInterface::class); 38 | } 39 | 40 | function it_should_extend_abstract_message() 41 | { 42 | $this->shouldBeAnInstanceOf(AbstractMessage::class); 43 | } 44 | 45 | function it_should_get_the_community() 46 | { 47 | $this->getCommunity()->shouldBeEqualTo('foo'); 48 | } 49 | 50 | function it_should_set_the_community() 51 | { 52 | $this->setCommunity('bar'); 53 | 54 | $this->getCommunity()->shouldBeEqualTo('bar'); 55 | } 56 | 57 | function it_should_get_the_version() 58 | { 59 | $this->getVersion()->shouldBeEqualTo(1); 60 | } 61 | 62 | function it_should_have_an_ASN1_representation() 63 | { 64 | $this->toAsn1()->shouldBeLike(Asn1::sequence( 65 | Asn1::integer(1), 66 | Asn1::octetString('foo'), 67 | (new GetRequest(new OidList()))->toAsn1() 68 | )); 69 | } 70 | 71 | function it_should_be_constructed_from_an_ASN1_representation() 72 | { 73 | $encoder = new SnmpEncoder(); 74 | 75 | $pdu = ''; 76 | foreach ((new GetRequest(new OidList()))->toAsn1() as $child) { 77 | $pdu .= $encoder->encode($child); 78 | } 79 | 80 | $this::fromAsn1(Asn1::sequence( 81 | Asn1::integer(1), 82 | Asn1::octetString('foo'), 83 | Asn1::context(0, new IncompleteType($pdu))->setIsConstructed(true) 84 | 85 | ))->shouldBeLike(new MessageRequestV2('foo', new GetRequest(new OidList()))); 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /tests/spec/FreeDSx/Snmp/Message/Response/MessageResponseV1Spec.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | 11 | namespace spec\FreeDSx\Snmp\Message\Response; 12 | 13 | use FreeDSx\Asn1\Asn1; 14 | use FreeDSx\Asn1\Type\IncompleteType; 15 | use FreeDSx\Snmp\Message\AbstractMessage; 16 | use FreeDSx\Snmp\Message\Response\MessageResponseInterface; 17 | use FreeDSx\Snmp\Message\Response\MessageResponseV1; 18 | use FreeDSx\Snmp\Protocol\SnmpEncoder; 19 | use FreeDSx\Snmp\Response\Response; 20 | use PhpSpec\ObjectBehavior; 21 | 22 | class MessageResponseV1Spec extends ObjectBehavior 23 | { 24 | function let() 25 | { 26 | $this->beConstructedWith('foo', new Response(0)); 27 | } 28 | 29 | function it_is_initializable() 30 | { 31 | $this->shouldHaveType(MessageResponseV1::class); 32 | } 33 | 34 | function it_should_implement_MessageResponseInterface() 35 | { 36 | $this->shouldImplement(MessageResponseInterface::class); 37 | } 38 | 39 | function it_should_extend_abstract_message() 40 | { 41 | $this->shouldBeAnInstanceOf(AbstractMessage::class); 42 | } 43 | 44 | function it_should_get_the_community() 45 | { 46 | $this->getCommunity()->shouldBeEqualTo('foo'); 47 | } 48 | 49 | function it_should_get_the_version() 50 | { 51 | $this->getVersion()->shouldBeEqualTo(0); 52 | } 53 | 54 | function it_should_have_an_ASN1_representation() 55 | { 56 | $this->toAsn1()->shouldBeLike(Asn1::sequence( 57 | Asn1::integer(0), 58 | Asn1::octetString('foo'), 59 | (new Response(0))->toAsn1() 60 | )); 61 | } 62 | 63 | function it_should_be_constructed_from_an_ASN1_representation() 64 | { 65 | $encoder = new SnmpEncoder(); 66 | 67 | $pdu = ''; 68 | foreach ((new Response(0))->toAsn1() as $child) { 69 | $pdu .= $encoder->encode($child); 70 | } 71 | 72 | $this::fromAsn1(Asn1::sequence( 73 | Asn1::integer(0), 74 | Asn1::octetString('foo'), 75 | Asn1::context(2, new IncompleteType($pdu))->setIsConstructed(true) 76 | 77 | ))->shouldBeLike(new MessageResponseV1('foo', new Response(0))); 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /tests/spec/FreeDSx/Snmp/Message/Response/MessageResponseV2Spec.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | 11 | namespace spec\FreeDSx\Snmp\Message\Response; 12 | 13 | use FreeDSx\Asn1\Asn1; 14 | use FreeDSx\Asn1\Type\IncompleteType; 15 | use FreeDSx\Snmp\Message\AbstractMessage; 16 | use FreeDSx\Snmp\Message\Response\MessageResponseInterface; 17 | use FreeDSx\Snmp\Message\Response\MessageResponseV2; 18 | use FreeDSx\Snmp\Protocol\SnmpEncoder; 19 | use FreeDSx\Snmp\Response\Response; 20 | use PhpSpec\ObjectBehavior; 21 | 22 | class MessageResponseV2Spec extends ObjectBehavior 23 | { 24 | function let() 25 | { 26 | $this->beConstructedWith('foo', new Response(0)); 27 | } 28 | 29 | function it_is_initializable() 30 | { 31 | $this->shouldHaveType(MessageResponseV2::class); 32 | } 33 | 34 | function it_should_implement_MessageResponseInterface() 35 | { 36 | $this->shouldImplement(MessageResponseInterface::class); 37 | } 38 | 39 | function it_should_extend_abstract_message() 40 | { 41 | $this->shouldBeAnInstanceOf(AbstractMessage::class); 42 | } 43 | 44 | function it_should_get_the_community() 45 | { 46 | $this->getCommunity()->shouldBeEqualTo('foo'); 47 | } 48 | 49 | function it_should_get_the_version() 50 | { 51 | $this->getVersion()->shouldBeEqualTo(1); 52 | } 53 | 54 | function it_should_have_an_ASN1_representation() 55 | { 56 | $this->toAsn1()->shouldBeLike(Asn1::sequence( 57 | Asn1::integer(1), 58 | Asn1::octetString('foo'), 59 | (new Response(0))->toAsn1() 60 | )); 61 | } 62 | 63 | function it_should_be_constructed_from_an_ASN1_representation() 64 | { 65 | $encoder = new SnmpEncoder(); 66 | 67 | $pdu = ''; 68 | foreach ((new Response(0))->toAsn1() as $child) { 69 | $pdu .= $encoder->encode($child); 70 | } 71 | 72 | $this::fromAsn1(Asn1::sequence( 73 | Asn1::integer(1), 74 | Asn1::octetString('foo'), 75 | Asn1::context(2, new IncompleteType($pdu))->setIsConstructed(true) 76 | 77 | ))->shouldBeLike(new MessageResponseV2('foo', new Response(0))); 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /tests/spec/FreeDSx/Snmp/Message/ScopedPduResponseSpec.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | 11 | namespace spec\FreeDSx\Snmp\Message; 12 | 13 | use FreeDSx\Asn1\Asn1; 14 | use FreeDSx\Asn1\Type\IncompleteType; 15 | use FreeDSx\Snmp\Message\EngineId; 16 | use FreeDSx\Snmp\Message\Pdu; 17 | use FreeDSx\Snmp\Message\ScopedPdu; 18 | use FreeDSx\Snmp\Message\ScopedPduResponse; 19 | use FreeDSx\Snmp\Protocol\ProtocolElementInterface; 20 | use FreeDSx\Snmp\Protocol\SnmpEncoder; 21 | use FreeDSx\Snmp\Request\RequestInterface; 22 | use FreeDSx\Snmp\Response\Response; 23 | use FreeDSx\Snmp\Response\ResponseInterface; 24 | use PhpSpec\ObjectBehavior; 25 | 26 | class ScopedPduResponseSpec extends ObjectBehavior 27 | { 28 | function let(ResponseInterface $response) 29 | { 30 | $response->beADoubleOf(Pdu::class); 31 | $response->toAsn1()->willReturn(Asn1::sequence()); 32 | 33 | $this->beConstructedWith($response); 34 | } 35 | 36 | function it_is_initializable() 37 | { 38 | $this->shouldHaveType(ScopedPduResponse::class); 39 | } 40 | 41 | function it_should_implement_protocol_element_interface() 42 | { 43 | $this->shouldImplement(ProtocolElementInterface::class); 44 | } 45 | 46 | function it_should_be_an_instance_of_scoped_pdu() 47 | { 48 | $this->shouldBeAnInstanceOf(ScopedPdu::class); 49 | } 50 | 51 | function it_should_only_allow_a_response_pdu(RequestInterface $request) 52 | { 53 | $this->beConstructedWith($request); 54 | $this->shouldThrow(\Throwable::class)->duringInstantiation(); 55 | } 56 | 57 | function it_should_get_the_response_pdu($response) 58 | { 59 | $this->getResponse()->shouldBeEqualTo($response); 60 | } 61 | 62 | function it_should_get_the_context_name() 63 | { 64 | $this->getContextName()->shouldBeEqualTo(''); 65 | } 66 | 67 | function it_should_get_the_context_engine_id() 68 | { 69 | $this->getContextEngineId()->shouldBeNull(); 70 | } 71 | 72 | function it_should_have_an_ASN1_representation($response) 73 | { 74 | $response->toAsn1()->shouldBeCalled(); 75 | 76 | $this->toAsn1()->shouldBeLike(Asn1::sequence( 77 | Asn1::octetString(''), 78 | Asn1::octetString(''), 79 | Asn1::sequence() 80 | )); 81 | } 82 | 83 | function it_should_be_constructed_from_an_ASN1_representation() 84 | { 85 | $pdu = Asn1::sequence( 86 | Asn1::integer(0), 87 | Asn1::integer(0), 88 | Asn1::integer(0), 89 | Asn1::sequenceOf() 90 | ); 91 | 92 | $encoder = new SnmpEncoder(); 93 | $pduEncoded = ''; 94 | foreach ($pdu as $element) { 95 | $pduEncoded .= $encoder->encode($element); 96 | } 97 | 98 | $pdu = new IncompleteType($pduEncoded); 99 | $pdu = Asn1::context(2, $pdu)->setIsConstructed(true); 100 | 101 | $this::fromAsn1(Asn1::sequence( 102 | Asn1::octetString(EngineId::fromText('foo')->toBinary()), 103 | Asn1::octetString('bar'), 104 | $pdu 105 | ))->shouldBeLike(new ScopedPduResponse(new Response(0), EngineId::fromText('foo'), 'bar')); 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /tests/spec/FreeDSx/Snmp/Message/Security/UsmSecurityParametersSpec.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | 11 | namespace spec\FreeDSx\Snmp\Message\Security; 12 | 13 | use FreeDSx\Asn1\Asn1; 14 | use FreeDSx\Snmp\Message\EngineId; 15 | use FreeDSx\Snmp\Message\Security\SecurityParametersInterface; 16 | use FreeDSx\Snmp\Message\Security\UsmSecurityParameters; 17 | use FreeDSx\Snmp\Protocol\SnmpEncoder; 18 | use PhpSpec\ObjectBehavior; 19 | 20 | class UsmSecurityParametersSpec extends ObjectBehavior 21 | { 22 | function let() 23 | { 24 | $this->beConstructedWith(EngineId::fromText('foo'), 1, 2, 'bar', 'auth', 'priv'); 25 | } 26 | 27 | function it_is_initializable() 28 | { 29 | $this->shouldHaveType(UsmSecurityParameters::class); 30 | } 31 | 32 | function it_should_implement_the_security_parameters_interface() 33 | { 34 | $this->shouldImplement(SecurityParametersInterface::class); 35 | } 36 | 37 | function it_should_get_the_security_model_number() 38 | { 39 | $this->getSecurityModel()->shouldBeEqualTo(3); 40 | } 41 | 42 | function it_should_get_the_engine_id() 43 | { 44 | $this->getEngineId()->shouldBeLike(EngineId::fromText('foo')); 45 | } 46 | 47 | function it_should_get_the_engine_boots() 48 | { 49 | $this->getEngineBoots()->shouldBeEqualTo(1); 50 | } 51 | 52 | function it_should_get_the_engine_time() 53 | { 54 | $this->getEngineTime()->shouldBeEqualTo(2); 55 | } 56 | 57 | function it_should_get_the_username() 58 | { 59 | $this->getUsername()->shouldBeEqualTo('bar'); 60 | } 61 | 62 | function it_should_get_the_auth_params() 63 | { 64 | $this->getAuthParams()->shouldBeEqualTo('auth'); 65 | } 66 | 67 | function it_should_get_the_priv_params() 68 | { 69 | $this->getPrivacyParams()->shouldBeEqualTo('priv'); 70 | } 71 | 72 | function it_should_have_an_ASN1_representation() 73 | { 74 | $this->toAsn1()->shouldBeLike( 75 | Asn1::sequence( 76 | Asn1::octetString(EngineId::fromText('foo')->toBinary()), 77 | Asn1::integer(1), 78 | Asn1::integer(2), 79 | Asn1::octetString('bar'), 80 | Asn1::octetString('auth'), 81 | Asn1::octetString('priv') 82 | ) 83 | ); 84 | } 85 | 86 | function it_should_be_constructed_from_an_ASN1_representation() 87 | { 88 | $this::fromAsn1(Asn1::octetString((new SnmpEncoder())->encode(Asn1::sequence( 89 | Asn1::octetString(EngineId::fromText('foo')->toBinary()), 90 | Asn1::integer(1), 91 | Asn1::integer(2), 92 | Asn1::octetString('bar'), 93 | Asn1::octetString('auth'), 94 | Asn1::octetString('priv') 95 | ))))->shouldBeLike( 96 | new UsmSecurityParameters(EngineId::fromText('foo'), 1, 2, 'bar', 'auth', 'priv') 97 | ); 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /tests/spec/FreeDSx/Snmp/Module/SecurityModel/Usm/TimeSyncSpec.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | 11 | namespace spec\FreeDSx\Snmp\Module\SecurityModel\Usm; 12 | 13 | use FreeDSx\Snmp\Module\SecurityModel\Usm\TimeSync; 14 | use PhpSpec\ObjectBehavior; 15 | 16 | class TimeSyncSpec extends ObjectBehavior 17 | { 18 | function let() 19 | { 20 | $this->beConstructedWith(1, 2); 21 | } 22 | 23 | function it_is_initializable() 24 | { 25 | $this->shouldHaveType(TimeSync::class); 26 | } 27 | 28 | function it_should_get_the_boot_time() 29 | { 30 | $this->getEngineBoot()->shouldBeEqualTo(1); 31 | } 32 | 33 | function it_should_get_the_engine_time() 34 | { 35 | $this->getEngineTime()->shouldBeEqualTo(2); 36 | } 37 | 38 | function it_should_get_when_the_time_was_synced() 39 | { 40 | $this->getWhenSynced()->shouldBeAnInstanceOf(\DateTime::class); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /tests/spec/FreeDSx/Snmp/Module/SecurityModel/Usm/UsmUserSpec.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | 11 | namespace spec\FreeDSx\Snmp\Module\SecurityModel\Usm; 12 | 13 | use FreeDSx\Snmp\Module\SecurityModel\Usm\UsmUser; 14 | use PhpSpec\ObjectBehavior; 15 | 16 | class UsmUserSpec extends ObjectBehavior 17 | { 18 | function let() 19 | { 20 | $this->beConstructedWith('foo'); 21 | } 22 | 23 | function it_is_initializable() 24 | { 25 | $this->shouldHaveType(UsmUser::class); 26 | } 27 | 28 | function it_should_get_the_auth_password() 29 | { 30 | $this->getAuthPassword()->shouldBeNull(); 31 | $this->setAuthPassword('foobar123'); 32 | $this->getAuthPassword()->shouldBeEqualTo('foobar123'); 33 | } 34 | 35 | function it_should_get_the_priv_password() 36 | { 37 | $this->getPrivPassword()->shouldBeNull(); 38 | $this->setPrivPassword('foobar123'); 39 | $this->getPrivPassword()->shouldBeEqualTo('foobar123'); 40 | } 41 | 42 | function it_should_get_the_auth_mech() 43 | { 44 | $this->getAuthMech()->shouldBeNull(); 45 | $this->setAuthMech('sha1'); 46 | $this->getAuthMech()->shouldBeEqualTo('sha1'); 47 | } 48 | 49 | function it_should_get_the_priv_mech() 50 | { 51 | $this->getPrivMech()->shouldBeNull(); 52 | $this->setPrivMech('des'); 53 | $this->getPrivMech()->shouldBeEqualTo('des'); 54 | } 55 | 56 | function it_should_get_the_username() 57 | { 58 | $this->getUser()->shouldBeEqualTo('foo'); 59 | $this->setUser('bar'); 60 | $this->getUser()->shouldBeEqualTo('bar'); 61 | } 62 | 63 | function it_should_get_whether_or_not_the_user_requires_authentication() 64 | { 65 | $this->getUseAuth()->shouldBeEqualTo(false); 66 | $this->setUseAuth(true); 67 | $this->getUseAuth()->shouldBeEqualTo(true); 68 | } 69 | 70 | function it_should_get_whether_or_not_the_user_requires_privacy() 71 | { 72 | $this->getUsePriv()->shouldBeEqualTo(false); 73 | $this->setUsePriv(true); 74 | $this->getUsePriv()->shouldBeEqualTo(true); 75 | } 76 | 77 | function it_should_construct_a_user_with_authentication() 78 | { 79 | $this::withAuthentication('user1', 'password123', 'sha512')->shouldBeLike( 80 | (new UsmUser('user1', false, true))->setAuthMech('sha512')->setAuthPassword('password123') 81 | ); 82 | } 83 | 84 | function it_should_construct_a_user_with_privacy() 85 | { 86 | $this::withPrivacy('user1', 'password123', 'sha512', 'password456','aes128')->shouldBeLike( 87 | (new UsmUser('user1', true, true))->setAuthMech('sha512')->setAuthPassword('password123')->setPrivMech('aes128')->setPrivPassword('password456') 88 | ); 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /tests/spec/FreeDSx/Snmp/OidValuesSpec.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | 11 | namespace spec\FreeDSx\Snmp; 12 | 13 | use FreeDSx\Snmp\OidValues; 14 | use FreeDSx\Snmp\Value\ArbitraryValue; 15 | use FreeDSx\Snmp\Value\BigCounterValue; 16 | use FreeDSx\Snmp\Value\CounterValue; 17 | use FreeDSx\Snmp\Value\IntegerValue; 18 | use FreeDSx\Snmp\Value\IpAddressValue; 19 | use FreeDSx\Snmp\Value\StringValue; 20 | use FreeDSx\Snmp\Value\TimeTicksValue; 21 | use FreeDSx\Snmp\Value\UnsignedIntegerValue; 22 | use PhpSpec\ObjectBehavior; 23 | 24 | class OidValuesSpec extends ObjectBehavior 25 | { 26 | function it_is_initializable() 27 | { 28 | $this->shouldHaveType(OidValues::class); 29 | } 30 | 31 | function it_should_get_an_arbitrary_value() 32 | { 33 | $this::arbitrary('foo')->shouldBeLike(new ArbitraryValue('foo')); 34 | } 35 | 36 | function it_should_get_an_integer_value() 37 | { 38 | $this::integer(1)->shouldBeLike(new IntegerValue(1)); 39 | } 40 | 41 | function it_should_get_a_string_value() 42 | { 43 | $this::string('foo')->shouldBeLike(new StringValue('foo')); 44 | } 45 | 46 | function it_should_get_a_big_counter_value() 47 | { 48 | $this::bigCounter(1)->shouldBeLike(new BigCounterValue(1)); 49 | } 50 | 51 | function it_should_get_a_big_counter_value_with_a_numeric_string() 52 | { 53 | $this::bigCounter('123456789')->shouldBeLike(new BigCounterValue('123456789')); 54 | } 55 | 56 | function it_should_get_a_counter_value() 57 | { 58 | $this::counter(1)->shouldBeLike(new CounterValue(1)); 59 | } 60 | 61 | function it_should_get_an_ip_address_value() 62 | { 63 | $this::ipAddress('127.0.0.1')->shouldBeLike(new IpAddressValue('127.0.0.1')); 64 | } 65 | 66 | function it_should_get_a_timeticks_value() 67 | { 68 | $this::timeticks(1)->shouldBeLike(new TimeTicksValue(1)); 69 | } 70 | 71 | function it_should_get_an_unsigned_int_value() 72 | { 73 | $this::unsignedInteger(2)->shouldBeLike(new UnsignedIntegerValue(2)); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /tests/spec/FreeDSx/Snmp/Protocol/Factory/AuthenticationModuleFactorySpec.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | 11 | namespace spec\FreeDSx\Snmp\Protocol\Factory; 12 | 13 | use FreeDSx\Snmp\Exception\InvalidArgumentException; 14 | use FreeDSx\Snmp\Protocol\Factory\AuthenticationModuleFactory; 15 | use FreeDSx\Snmp\Module\Authentication\AuthenticationModule; 16 | use PhpSpec\ObjectBehavior; 17 | 18 | class AuthenticationModuleFactorySpec extends ObjectBehavior 19 | { 20 | function it_is_initializable() 21 | { 22 | $this->shouldHaveType(AuthenticationModuleFactory::class); 23 | } 24 | 25 | function it_should_get_the_auth_module_for_md5() 26 | { 27 | $this->get('md5')->shouldBeLike(new AuthenticationModule('md5')); 28 | } 29 | 30 | function it_should_get_the_auth_module_for_sha1() 31 | { 32 | $this->get('sha1')->shouldBeLike(new AuthenticationModule('sha1')); 33 | } 34 | 35 | function it_should_get_the_auth_module_for_sha224() 36 | { 37 | $this->get('sha224')->shouldBeLike(new AuthenticationModule('sha224')); 38 | } 39 | 40 | function it_should_get_the_auth_module_for_sha256() 41 | { 42 | $this->get('sha256')->shouldBeLike(new AuthenticationModule('sha256')); 43 | } 44 | 45 | function it_should_get_the_auth_module_for_sha384() 46 | { 47 | $this->get('sha384')->shouldBeLike(new AuthenticationModule('sha384')); 48 | } 49 | 50 | function it_should_get_the_auth_module_for_sha512() 51 | { 52 | $this->get('sha512')->shouldBeLike(new AuthenticationModule('sha512')); 53 | } 54 | 55 | function it_should_throw_an_exception_for_an_auth_module_that_doesnt_exist() 56 | { 57 | $this->shouldThrow(InvalidArgumentException::class)->during('get', ['bar']); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /tests/spec/FreeDSx/Snmp/Protocol/Factory/OidValueFactorySpec.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | 11 | namespace spec\FreeDSx\Snmp\Protocol\Factory; 12 | 13 | use FreeDSx\Asn1\Asn1; 14 | use FreeDSx\Asn1\Type\IncompleteType; 15 | use FreeDSx\Snmp\Exception\ProtocolException; 16 | use FreeDSx\Snmp\OidValues; 17 | use FreeDSx\Snmp\Protocol\Factory\OidValueFactory; 18 | use PhpSpec\ObjectBehavior; 19 | 20 | class OidValueFactorySpec extends ObjectBehavior 21 | { 22 | function it_is_initializable() 23 | { 24 | $this->shouldHaveType(OidValueFactory::class); 25 | } 26 | 27 | function it_should_get_the_ip_address_value_object() 28 | { 29 | $this::get(Asn1::application(0, new IncompleteType(hex2bin('7f000001'))))->shouldBeLike(OidValues::ipAddress('127.0.0.1')); 30 | } 31 | 32 | function it_should_get_the_counter_value_object() 33 | { 34 | $this::get(Asn1::application(1, new IncompleteType("\x09")))->shouldBeLike(OidValues::counter(9)); 35 | } 36 | 37 | function it_should_get_the_unsigned_integer_value_object() 38 | { 39 | $this::get(Asn1::application(2, new IncompleteType("\x09")))->shouldBeLike(OidValues::unsignedInteger(9)); 40 | } 41 | 42 | function it_should_get_the_timeticks_value_object() 43 | { 44 | $this::get(Asn1::application(3, new IncompleteType("\x09")))->shouldBeLike(OidValues::timeticks(9)); 45 | } 46 | 47 | function it_should_get_the_arbitrary_value_object() 48 | { 49 | $this::get(Asn1::application(4, new IncompleteType("foo")))->shouldBeLike(OidValues::arbitrary('foo')); 50 | } 51 | 52 | function it_should_get_the_big_counter_value_object() 53 | { 54 | $this::get(Asn1::application(6, new IncompleteType("\x09")))->shouldBeLike(OidValues::bigCounter(9)); 55 | } 56 | 57 | function it_should_get_the_integer_type_value_object() 58 | { 59 | $this::get(OidValues::integer(1)->toAsn1())->shouldBeLike(OidValues::integer(1)); 60 | } 61 | 62 | function it_should_get_the_string_type_value_object() 63 | { 64 | $this::get(OidValues::string('foo')->toAsn1())->shouldBeLike(OidValues::string('foo')); 65 | } 66 | 67 | function it_should_get_the_oid_type_value_object() 68 | { 69 | $this::get(OidValues::oid('1.2.3')->toAsn1())->shouldBeLike(OidValues::oid('1.2.3')); 70 | } 71 | 72 | function it_should_throw_an_exception_if_the_value_type_doesnt_have_a_mapping() 73 | { 74 | $this->shouldThrow(ProtocolException::class)->during('get', [Asn1::null()]); 75 | $this->shouldThrow(ProtocolException::class)->during('get', [Asn1::application(99, new IncompleteType("foo"))]); 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /tests/spec/FreeDSx/Snmp/Protocol/Factory/PrivacyModuleFactorySpec.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | 11 | namespace spec\FreeDSx\Snmp\Protocol\Factory; 12 | 13 | use FreeDSx\Snmp\Exception\InvalidArgumentException; 14 | use FreeDSx\Snmp\Protocol\Factory\PrivacyModuleFactory; 15 | use FreeDSx\Snmp\Module\Privacy\AESPrivacyModule; 16 | use FreeDSx\Snmp\Module\Privacy\DES3PrivacyModule; 17 | use FreeDSx\Snmp\Module\Privacy\DESPrivacyModule; 18 | use PhpSpec\ObjectBehavior; 19 | 20 | class PrivacyModuleFactorySpec extends ObjectBehavior 21 | { 22 | function it_is_initializable() 23 | { 24 | $this->shouldHaveType(PrivacyModuleFactory::class); 25 | } 26 | 27 | function it_should_get_the_des_based_privacy_module() 28 | { 29 | $this->get('des', 1)->shouldBeLike(new DESPrivacyModule('des', 1)); 30 | $this->get('des-cbc', 1)->shouldBeLike(new DESPrivacyModule('des-cbc', 1)); 31 | } 32 | 33 | function it_should_get_the_aes_based_privacy_modules() 34 | { 35 | $this->get('aes', 1)->shouldBeLike(new AESPrivacyModule('aes', 1)); 36 | $this->get('aes128',1)->shouldBeLike(new AESPrivacyModule('aes128', 1)); 37 | $this->get('aes192', 1)->shouldBeLike(new AESPrivacyModule('aes192', 1)); 38 | $this->get('aes256', 1)->shouldBeLike(new AESPrivacyModule('aes256', 1)); 39 | $this->get('aes192blu', 1)->shouldBeLike(new AESPrivacyModule('aes192blu', 1)); 40 | $this->get('aes256blu', 1)->shouldBeLike(new AESPrivacyModule('aes256blu', 1)); 41 | $this->get('aes-128-cfb', 1)->shouldBeLike(new AESPrivacyModule('aes-128-cfb', 1)); 42 | $this->get('aes-192-cfb', 1)->shouldBeLike(new AESPrivacyModule('aes-192-cfb', 1)); 43 | $this->get('aes-256-cfb', 1)->shouldBeLike(new AESPrivacyModule('aes-256-cfb', 1)); 44 | } 45 | 46 | function it_should_get_the_3des_based_privacy_module() 47 | { 48 | $this->get('3des', 1)->shouldBeAnInstanceOf(new DES3PrivacyModule('3des', 1)); 49 | $this->get('des-ede3-cbc', 1)->shouldBeAnInstanceOf(new DES3PrivacyModule('des-ede3-cbc', 1)); 50 | } 51 | 52 | function it_should_throw_an_exception_if_the_privacy_mechanism_doesnt_exist() 53 | { 54 | $this->shouldThrow(InvalidArgumentException::class)->during('get', ['bar']); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /tests/spec/FreeDSx/Snmp/Protocol/Factory/ResponseFactorySpec.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | 11 | namespace spec\FreeDSx\Snmp\Protocol\Factory; 12 | 13 | use FreeDSx\Asn1\Asn1; 14 | use FreeDSx\Asn1\Type\IncompleteType; 15 | use FreeDSx\Snmp\Exception\ProtocolException; 16 | use FreeDSx\Snmp\OidValues; 17 | use FreeDSx\Snmp\Protocol\Factory\ResponseFactory; 18 | use FreeDSx\Snmp\Protocol\SnmpEncoder; 19 | use FreeDSx\Snmp\Response\ReportResponse; 20 | use FreeDSx\Snmp\Response\Response; 21 | use PhpSpec\ObjectBehavior; 22 | 23 | class ResponseFactorySpec extends ObjectBehavior 24 | { 25 | /** 26 | * @var IncompleteType 27 | */ 28 | protected $pdu; 29 | 30 | function let() 31 | { 32 | $this->pdu = Asn1::sequence( 33 | Asn1::integer(1), 34 | Asn1::integer(2), 35 | Asn1::integer(1), 36 | Asn1::sequenceOf( 37 | Asn1::sequence( 38 | Asn1::oid('1.2.3'), 39 | OidValues::counter(1)->toAsn1() 40 | ) 41 | ) 42 | ); 43 | 44 | $encoder = new SnmpEncoder(); 45 | $pduEncoded = ''; 46 | foreach ($this->pdu as $element) { 47 | $pduEncoded .= $encoder->encode($element); 48 | } 49 | 50 | $this->pdu = new IncompleteType($pduEncoded); 51 | $this->pdu = Asn1::context(2, $this->pdu)->setIsConstructed(true); 52 | } 53 | 54 | function it_is_initializable() 55 | { 56 | $this->shouldHaveType(ResponseFactory::class); 57 | } 58 | 59 | function it_should_get_the_response_type_object() 60 | { 61 | $this->pdu->setTagNumber(2); 62 | 63 | $this::get($this->pdu)->shouldBeAnInstanceOf(Response::class); 64 | } 65 | 66 | function it_should_get_the_report_response_type_object() 67 | { 68 | $this->pdu->setTagNumber(8); 69 | 70 | $this::get($this->pdu)->shouldBeAnInstanceOf(ReportResponse::class); 71 | } 72 | 73 | function it_should_throw_an_exception_if_the_response_type_is_not_recognized() 74 | { 75 | $this->pdu->setTagNumber(99); 76 | 77 | $this->shouldThrow(ProtocolException::class)->during('get', [$this->pdu]); 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /tests/spec/FreeDSx/Snmp/Protocol/Factory/SecurityModelModuleFactorySpec.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | 11 | namespace spec\FreeDSx\Snmp\Protocol\Factory; 12 | 13 | use FreeDSx\Snmp\Exception\ProtocolException; 14 | use FreeDSx\Snmp\Protocol\Factory\SecurityModelModuleFactory; 15 | use FreeDSx\Snmp\Module\SecurityModel\UserSecurityModelModule; 16 | use PhpSpec\ObjectBehavior; 17 | 18 | class SecurityModelModuleFactorySpec extends ObjectBehavior 19 | { 20 | function it_is_initializable() 21 | { 22 | $this->shouldHaveType(SecurityModelModuleFactory::class); 23 | } 24 | 25 | function it_should_get_the_user_security_model() 26 | { 27 | $this->get(3)->shouldBeAnInstanceOf(UserSecurityModelModule::class); 28 | } 29 | 30 | function it_should_throw_an_exception_if_the_security_model_is_not_supported() 31 | { 32 | $this->shouldThrow(ProtocolException::class)->during('get', [9000]); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /tests/spec/FreeDSx/Snmp/Protocol/Factory/SecurityParametersFactorySpec.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | 11 | namespace spec\FreeDSx\Snmp\Protocol\Factory; 12 | 13 | use FreeDSx\Asn1\Asn1; 14 | use FreeDSx\Asn1\Type\AbstractType; 15 | use FreeDSx\Snmp\Exception\ProtocolException; 16 | use FreeDSx\Snmp\Message\EngineId; 17 | use FreeDSx\Snmp\Message\Security\SecurityParametersInterface; 18 | use FreeDSx\Snmp\Message\Security\UsmSecurityParameters; 19 | use FreeDSx\Snmp\Protocol\Factory\SecurityParametersFactory; 20 | use FreeDSx\Snmp\Protocol\SnmpEncoder; 21 | use PhpSpec\ObjectBehavior; 22 | 23 | class SecurityParametersFactorySpec extends ObjectBehavior 24 | { 25 | function it_is_initializable() 26 | { 27 | $this->shouldHaveType(SecurityParametersFactory::class); 28 | } 29 | 30 | function it_should_get_the_USM_security_parameters() 31 | { 32 | $this::get(3, Asn1::octetString((new SnmpEncoder())->encode(Asn1::sequence( 33 | Asn1::octetString(EngineId::fromText('foobar')->toBinary()), 34 | Asn1::integer(0), 35 | Asn1::integer(0), 36 | Asn1::octetString('foo'), 37 | Asn1::octetString(''), 38 | Asn1::octetString('') 39 | ))))->shouldBeAnInstanceOf(UsmSecurityParameters::class); 40 | } 41 | 42 | function it_should_set_the_security_parameters_for_a_class() 43 | { 44 | $class = new class implements SecurityParametersInterface { 45 | public function toAsn1(): AbstractType{} 46 | public static function fromAsn1(AbstractType $type){ 47 | return new self(); 48 | } 49 | public function getSecurityModel(): int 50 | { 51 | return 99; 52 | } 53 | }; 54 | 55 | $this::set(get_class($class)); 56 | $this::get(99, Asn1::octetString(''))->shouldBeAnInstanceOf($class); 57 | } 58 | 59 | function it_should_throw_an_exception_if_the_security_model_is_not_recognized() 60 | { 61 | $this->shouldThrow(ProtocolException::class)->during('get', [4, Asn1::octetString('')]); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /tests/spec/FreeDSx/Snmp/Protocol/SnmpEncoderSpec.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | 11 | namespace spec\FreeDSx\Snmp\Protocol; 12 | 13 | use FreeDSx\Asn1\Encoder\BerEncoder; 14 | use FreeDSx\Asn1\Type\AbstractType; 15 | use FreeDSx\Snmp\Protocol\SnmpEncoder; 16 | use PhpSpec\ObjectBehavior; 17 | 18 | class SnmpEncoderSpec extends ObjectBehavior 19 | { 20 | function it_is_initializable() 21 | { 22 | $this->shouldHaveType(SnmpEncoder::class); 23 | } 24 | 25 | function it_should_be_an_instance_of_a_ber_encoder() 26 | { 27 | $this->shouldBeAnInstanceOf(BerEncoder::class); 28 | } 29 | 30 | function it_should_only_allow_octet_strings_as_primitives() 31 | { 32 | $this->getOptions()->shouldNotHaveKeyWithValue('primitive_only',AbstractType::TAG_TYPE_OCTET_STRING); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /tests/spec/FreeDSx/Snmp/Request/SetRequestSpec.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | 11 | namespace spec\FreeDSx\Snmp\Request; 12 | 13 | use FreeDSx\Asn1\Asn1; 14 | use FreeDSx\Asn1\Type\IncompleteType; 15 | use FreeDSx\Snmp\Message\Pdu; 16 | use FreeDSx\Snmp\Oid; 17 | use FreeDSx\Snmp\OidList; 18 | use FreeDSx\Snmp\OidValues; 19 | use FreeDSx\Snmp\Protocol\SnmpEncoder; 20 | use FreeDSx\Snmp\Request\RequestInterface; 21 | use FreeDSx\Snmp\Request\SetRequest; 22 | use PhpSpec\ObjectBehavior; 23 | 24 | class SetRequestSpec extends ObjectBehavior 25 | { 26 | function let() 27 | { 28 | $this->beConstructedWith(new OidList(Oid::fromInteger('1.2', 1), Oid::fromString('1.2.3', 'foo'))); 29 | } 30 | 31 | function it_is_initializable() 32 | { 33 | $this->shouldHaveType(SetRequest::class); 34 | } 35 | 36 | function it_should_implement_the_request_interface() 37 | { 38 | $this->shouldImplement(RequestInterface::class); 39 | } 40 | 41 | function it_should_be_an_instance_of_a_PDU() 42 | { 43 | $this->shouldImplement(Pdu::class); 44 | } 45 | 46 | function it_should_get_the_oid_list() 47 | { 48 | $this->getOids()->shouldBeLike(new OidList(Oid::fromInteger('1.2', 1), Oid::fromString('1.2.3', 'foo'))); 49 | } 50 | 51 | function it_should_set_the_oid_list() 52 | { 53 | $this->setOids(new OidList(Oid::fromInteger('1.2.3',5))); 54 | $this->getOids()->shouldBeLike(new OidList(Oid::fromInteger('1.2.3',5))); 55 | } 56 | 57 | function it_should_get_the_pdu_tag() 58 | { 59 | $this->getPduTag()->shouldBeEqualTo(3); 60 | } 61 | 62 | function it_should_have_an_ASN1_representation() 63 | { 64 | $this->toAsn1()->shouldBeLike( 65 | Asn1::context(3, Asn1::sequence( 66 | Asn1::integer(0), 67 | Asn1::integer(0), 68 | Asn1::integer(0), 69 | Asn1::sequenceOf( 70 | Asn1::sequence( 71 | Asn1::oid('1.2'), 72 | OidValues::integer(1)->toAsn1() 73 | ), 74 | Asn1::sequence( 75 | Asn1::oid('1.2.3'), 76 | OidValues::string('foo')->toAsn1() 77 | ) 78 | ) 79 | )) 80 | ); 81 | } 82 | 83 | function it_should_be_constructed_from_an_ASN1_representation() 84 | { 85 | $pdu = Asn1::sequence( 86 | Asn1::integer(0), 87 | Asn1::integer(0), 88 | Asn1::integer(0), 89 | Asn1::sequenceOf( 90 | Asn1::sequence( 91 | Asn1::oid('1.2.3'), 92 | OidValues::string('foo')->toAsn1() 93 | ) 94 | ) 95 | ); 96 | 97 | $encoder = new SnmpEncoder(); 98 | $pduEncoded = ''; 99 | foreach ($pdu as $element) { 100 | $pduEncoded .= $encoder->encode($element); 101 | } 102 | 103 | $pdu = new IncompleteType($pduEncoded); 104 | $pdu = Asn1::context(3, $pdu)->setIsConstructed(true); 105 | 106 | $this::fromAsn1($pdu)->shouldBeLike(new SetRequest(new OidList(Oid::fromString('1.2.3', 'foo')))); 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /tests/spec/FreeDSx/Snmp/RequestsSpec.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | 11 | namespace spec\FreeDSx\Snmp; 12 | 13 | use FreeDSx\Snmp\Oid; 14 | use FreeDSx\Snmp\OidList; 15 | use FreeDSx\Snmp\OidValues; 16 | use FreeDSx\Snmp\Request\GetBulkRequest; 17 | use FreeDSx\Snmp\Request\GetNextRequest; 18 | use FreeDSx\Snmp\Request\GetRequest; 19 | use FreeDSx\Snmp\Request\InformRequest; 20 | use FreeDSx\Snmp\Request\SetRequest; 21 | use FreeDSx\Snmp\Request\TrapV1Request; 22 | use FreeDSx\Snmp\Request\TrapV2Request; 23 | use FreeDSx\Snmp\Requests; 24 | use FreeDSx\Snmp\Value\IntegerValue; 25 | use PhpSpec\ObjectBehavior; 26 | 27 | class RequestsSpec extends ObjectBehavior 28 | { 29 | function it_is_initializable() 30 | { 31 | $this->shouldHaveType(Requests::class); 32 | } 33 | 34 | function it_should_get_a_bulk_request() 35 | { 36 | $this::getBulk(1, 2, '1.2.3.4.5')->shouldBeLike(new GetBulkRequest(1, 2, new OidList(new Oid('1.2.3.4.5')))); 37 | } 38 | 39 | function it_should_get_a_get_request() 40 | { 41 | $this::get('1.2.3.4.5')->shouldBeLike(new GetRequest(new OidList(new Oid('1.2.3.4.5')))); 42 | } 43 | 44 | function it_should_get_a_get_next_request() 45 | { 46 | $this::getNext('1.2.3.4.5')->shouldBeLike(new GetNextRequest(new OidList(new Oid('1.2.3.4.5')))); 47 | } 48 | 49 | function it_should_get_a_set_request() 50 | { 51 | $this::set(Oid::fromInteger('1.2.3.4.5', 5))->shouldBeLike(new SetRequest(new OidList(new Oid('1.2.3.4.5', new IntegerValue(5))))); 52 | } 53 | 54 | function it_should_get_a_trap_v1_request() 55 | { 56 | $this::trapV1('foo', '127.0.0.1', 1, 2, 3, new Oid('1.2.3.4.5'))->shouldBeLike( 57 | new TrapV1Request('foo', OidValues::ipAddress('127.0.0.1'), 1, 2, OidValues::timeticks(3), new OidList(new Oid('1.2.3.4.5'))) 58 | ); 59 | } 60 | 61 | function it_should_get_a_trap_v2_request() 62 | { 63 | $this::trap(OidValues::timeticks(1), OidValues::oid('1.2.3.4.5'), Oid::fromCounter('1.2.3.4.5', 1))->shouldBeLike( 64 | new TrapV2Request(OidValues::timeticks(1), OidValues::oid('1.2.3.4.5'), new OidList(Oid::fromCounter('1.2.3.4.5', 1))) 65 | ); 66 | } 67 | 68 | function it_should_get_an_inform_request() 69 | { 70 | $this::inform(OidValues::timeticks(1), OidValues::oid('1.2.3.4.5'), Oid::fromCounter('1.2.3.4.5', 1))->shouldBeLike( 71 | new InformRequest(OidValues::timeticks(1), OidValues::oid('1.2.3.4.5'), new OidList(Oid::fromCounter('1.2.3.4.5', 1))) 72 | ); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /tests/spec/FreeDSx/Snmp/Response/ReportResponseSpec.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | 11 | namespace spec\FreeDSx\Snmp\Response; 12 | 13 | use FreeDSx\Asn1\Asn1; 14 | use FreeDSx\Asn1\Type\IncompleteType; 15 | use FreeDSx\Snmp\Message\Pdu; 16 | use FreeDSx\Snmp\Oid; 17 | use FreeDSx\Snmp\OidList; 18 | use FreeDSx\Snmp\OidValues; 19 | use FreeDSx\Snmp\Protocol\SnmpEncoder; 20 | use FreeDSx\Snmp\Response\ReportResponse; 21 | use FreeDSx\Snmp\Response\ResponseInterface; 22 | use PhpSpec\ObjectBehavior; 23 | 24 | class ReportResponseSpec extends ObjectBehavior 25 | { 26 | function let() 27 | { 28 | $this->beConstructedWith(1, 2, 1, new OidList(Oid::fromCounter('1.2.3', 1))); 29 | } 30 | 31 | function it_is_initializable() 32 | { 33 | $this->shouldHaveType(ReportResponse::class); 34 | } 35 | 36 | function it_should_implement_the_response_interface() 37 | { 38 | $this->shouldImplement(ResponseInterface::class); 39 | } 40 | 41 | function it_should_be_an_instance_of_a_PDU() 42 | { 43 | $this->shouldBeAnInstanceOf(Pdu::class); 44 | } 45 | 46 | function it_should_get_the_oid_list() 47 | { 48 | $this->getOids()->shouldBeLike(new OidList(Oid::fromCounter('1.2.3', 1))); 49 | } 50 | 51 | function it_should_get_the_id() 52 | { 53 | $this->getId()->shouldBeEqualTo(1); 54 | } 55 | 56 | function it_should_get_the_error_status() 57 | { 58 | $this->getErrorStatus()->shouldBeEqualTo(2); 59 | } 60 | 61 | function it_should_get_the_error_index() 62 | { 63 | $this->getErrorIndex()->shouldBeEqualTo(1); 64 | } 65 | 66 | function it_should_get_the_pdu_tag() 67 | { 68 | $this->getPduTag()->shouldBeEqualTo(8); 69 | } 70 | 71 | function it_should_have_an_ASN1_representation() 72 | { 73 | $this->toAsn1()->shouldBeLike(Asn1::context(8, Asn1::sequence( 74 | Asn1::integer(1), 75 | Asn1::integer(2), 76 | Asn1::integer(1), 77 | Asn1::sequenceOf( 78 | Asn1::sequence( 79 | Asn1::oid('1.2.3'), 80 | OidValues::counter(1)->toAsn1() 81 | ) 82 | ) 83 | ))); 84 | } 85 | 86 | function it_should_be_constructed_from_an_ASN1_representation() 87 | { 88 | $pdu = Asn1::sequence( 89 | Asn1::integer(1), 90 | Asn1::integer(2), 91 | Asn1::integer(1), 92 | Asn1::sequenceOf( 93 | Asn1::sequence( 94 | Asn1::oid('1.2.3'), 95 | OidValues::counter(1)->toAsn1() 96 | ) 97 | ) 98 | ); 99 | 100 | $encoder = new SnmpEncoder(); 101 | $pduEncoded = ''; 102 | foreach ($pdu as $element) { 103 | $pduEncoded .= $encoder->encode($element); 104 | } 105 | 106 | $pdu = new IncompleteType($pduEncoded); 107 | $pdu = Asn1::context(8, $pdu)->setIsConstructed(true); 108 | 109 | $this::fromAsn1($pdu)->shouldBeLike(new ReportResponse(1, 2, 1, new OidList(Oid::fromCounter('1.2.3', 1)))); 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /tests/spec/FreeDSx/Snmp/Response/ResponseSpec.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | 11 | namespace spec\FreeDSx\Snmp\Response; 12 | 13 | use FreeDSx\Asn1\Asn1; 14 | use FreeDSx\Asn1\Type\IncompleteType; 15 | use FreeDSx\Snmp\Message\Pdu; 16 | use FreeDSx\Snmp\Oid; 17 | use FreeDSx\Snmp\OidList; 18 | use FreeDSx\Snmp\OidValues; 19 | use FreeDSx\Snmp\Protocol\SnmpEncoder; 20 | use FreeDSx\Snmp\Response\Response; 21 | use FreeDSx\Snmp\Response\ResponseInterface; 22 | use PhpSpec\ObjectBehavior; 23 | 24 | class ResponseSpec extends ObjectBehavior 25 | { 26 | function let() 27 | { 28 | $this->beConstructedWith(1, 2, 1, new OidList(Oid::fromCounter('1.2.3', 1))); 29 | } 30 | 31 | function it_is_initializable() 32 | { 33 | $this->shouldHaveType(Response::class); 34 | } 35 | 36 | function it_should_implement_the_response_interface() 37 | { 38 | $this->shouldImplement(ResponseInterface::class); 39 | } 40 | 41 | function it_should_be_an_instance_of_a_PDU() 42 | { 43 | $this->shouldBeAnInstanceOf(Pdu::class); 44 | } 45 | 46 | function it_should_get_the_oid_list() 47 | { 48 | $this->getOids()->shouldBeLike(new OidList(Oid::fromCounter('1.2.3', 1))); 49 | } 50 | 51 | function it_should_get_the_id() 52 | { 53 | $this->getId()->shouldBeEqualTo(1); 54 | } 55 | 56 | function it_should_get_the_error_status() 57 | { 58 | $this->getErrorStatus()->shouldBeEqualTo(2); 59 | } 60 | 61 | function it_should_get_the_error_index() 62 | { 63 | $this->getErrorIndex()->shouldBeEqualTo(1); 64 | } 65 | 66 | function it_should_get_the_pdu_tag() 67 | { 68 | $this->getPduTag()->shouldBeEqualTo(2); 69 | } 70 | 71 | function it_should_have_an_ASN1_representation() 72 | { 73 | $this->toAsn1()->shouldBeLike(Asn1::context(2, Asn1::sequence( 74 | Asn1::integer(1), 75 | Asn1::integer(2), 76 | Asn1::integer(1), 77 | Asn1::sequenceOf( 78 | Asn1::sequence( 79 | Asn1::oid('1.2.3'), 80 | OidValues::counter(1)->toAsn1() 81 | ) 82 | ) 83 | ))); 84 | } 85 | 86 | function it_should_be_constructed_from_an_ASN1_representation() 87 | { 88 | $pdu = Asn1::sequence( 89 | Asn1::integer(1), 90 | Asn1::integer(2), 91 | Asn1::integer(1), 92 | Asn1::sequenceOf( 93 | Asn1::sequence( 94 | Asn1::oid('1.2.3'), 95 | OidValues::counter(1)->toAsn1() 96 | ) 97 | ) 98 | ); 99 | 100 | $encoder = new SnmpEncoder(); 101 | $pduEncoded = ''; 102 | foreach ($pdu as $element) { 103 | $pduEncoded .= $encoder->encode($element); 104 | } 105 | 106 | $pdu = new IncompleteType($pduEncoded); 107 | $pdu = Asn1::context(2, $pdu)->setIsConstructed(true); 108 | 109 | $this::fromAsn1($pdu)->shouldBeLike(new Response(1, 2, 1, new OidList(Oid::fromCounter('1.2.3', 1)))); 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /tests/spec/FreeDSx/Snmp/Server/ServerRunner/TrapServerRunnerSpec.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | 11 | namespace spec\FreeDSx\Snmp\Server\ServerRunner; 12 | 13 | use FreeDSx\Snmp\Protocol\TrapProtocolHandler; 14 | use FreeDSx\Snmp\Server\ServerRunner\ServerRunnerInterface; 15 | use FreeDSx\Snmp\Server\ServerRunner\TrapServerRunner; 16 | use PhpSpec\ObjectBehavior; 17 | 18 | /** 19 | * @todo Cannot get spec to work correctly with the run method against the SocketServer. Need to revist. 20 | */ 21 | class TrapServerRunnerSpec extends ObjectBehavior 22 | { 23 | function let(TrapProtocolHandler $handler) 24 | { 25 | $this->beConstructedWith($handler); 26 | } 27 | 28 | function it_is_initializable() 29 | { 30 | $this->shouldHaveType(TrapServerRunner::class); 31 | } 32 | 33 | function it_should_implement_the_server_runner_interface() 34 | { 35 | $this->shouldImplement(ServerRunnerInterface::class); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /tests/spec/FreeDSx/Snmp/Trap/TrapContextSpec.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | 11 | namespace spec\FreeDSx\Snmp\Trap; 12 | 13 | use FreeDSx\Snmp\Message\MessageHeader; 14 | use FreeDSx\Snmp\Message\Request\MessageRequestV3; 15 | use FreeDSx\Snmp\Message\ScopedPduRequest; 16 | use FreeDSx\Snmp\Oid; 17 | use FreeDSx\Snmp\OidList; 18 | use FreeDSx\Snmp\OidValues; 19 | use FreeDSx\Snmp\Request\InformRequest; 20 | use FreeDSx\Snmp\Request\TrapV1Request; 21 | use FreeDSx\Snmp\Request\TrapV2Request; 22 | use FreeDSx\Snmp\Trap\TrapContext; 23 | use PhpSpec\ObjectBehavior; 24 | 25 | class TrapContextSpec extends ObjectBehavior 26 | { 27 | protected $scopedPdu; 28 | 29 | function let() 30 | { 31 | $this->scopedPdu = new ScopedPduRequest(new TrapV2Request(OidValues::timeticks(2), OidValues::oid('1.2.3'), new OidList( 32 | Oid::fromCounter('1.2.3.4', 5) 33 | ))); 34 | $this->beConstructedWith('192.168.1.1', 3, new MessageRequestV3( 35 | new MessageHeader(1, MessageHeader::FLAG_AUTH_PRIV, 3), 36 | $this->scopedPdu 37 | )); 38 | } 39 | 40 | function it_is_initializable() 41 | { 42 | $this->shouldHaveType(TrapContext::class); 43 | } 44 | 45 | function it_should_get_the_IP_address_the_trap_originated_from() 46 | { 47 | $this->getIpAddress()->shouldBeEqualTo('192.168.1.1'); 48 | } 49 | 50 | function it_should_get_the_snmp_version_of_the_incoming_trap() 51 | { 52 | $this->getVersion()->shouldBeEqualTo(3); 53 | } 54 | 55 | function it_should_get_the_complete_SNMP_message() 56 | { 57 | $this->getMessage()->shouldBeAnInstanceOf(MessageRequestV3::class); 58 | } 59 | 60 | function it_should_get_the_trap_request() 61 | { 62 | $this->getTrap()->shouldBeLike(new TrapV2Request(OidValues::timeticks(2), OidValues::oid('1.2.3'), new OidList( 63 | Oid::fromCounter('1.2.3.4', 5) 64 | ))); 65 | } 66 | 67 | function it_should_check_when_the_trap_is_a_v1_trap() 68 | { 69 | $this->isTrapV1()->shouldBeEqualTo(false); 70 | } 71 | 72 | function it_should_check_when_the_trap_is_not_a_v1_trap() 73 | { 74 | $this->scopedPdu->setRequest(new TrapV1Request('1.2.3', OidValues::ipAddress('192.168.1.1'), 1, 2, OidValues::timeticks(1), new OidList())); 75 | $this->isTrapV1()->shouldBeEqualTo(true); 76 | } 77 | 78 | function it_should_check_when_the_trap_is_a_v2_trap() 79 | { 80 | $this->isTrapV2()->shouldBeEqualTo(true); 81 | } 82 | 83 | function it_should_check_when_the_trap_is_not_a_v2_trap() 84 | { 85 | $this->scopedPdu->setRequest(new TrapV1Request('1.2.3', OidValues::ipAddress('192.168.1.1'), 1, 2, OidValues::timeticks(1), new OidList())); 86 | $this->isTrapV2()->shouldBeEqualTo(false); 87 | } 88 | 89 | function it_should_check_when_the_trap_is_not_an_inform_request() 90 | { 91 | $this->isInformRequest()->shouldBeEqualTo(false); 92 | } 93 | 94 | function it_should_check_when_the_trap_is_an_inform_request() 95 | { 96 | $this->scopedPdu->setRequest(new InformRequest(OidValues::timeticks(1), OidValues::oid('1.2.3'), new OidList())); 97 | $this->isInformRequest()->shouldBeEqualTo(true); 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /tests/spec/FreeDSx/Snmp/TrapSinkSpec.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | 11 | namespace spec\FreeDSx\Snmp; 12 | 13 | use FreeDSx\Snmp\Server\ServerRunner\TrapServerRunner; 14 | use FreeDSx\Snmp\Trap\TrapListenerInterface; 15 | use FreeDSx\Snmp\TrapSink; 16 | use FreeDSx\Socket\Socket; 17 | use PhpSpec\ObjectBehavior; 18 | use Prophecy\Argument; 19 | 20 | class TrapSinkSpec extends ObjectBehavior 21 | { 22 | function let(TrapListenerInterface $listener) 23 | { 24 | $this->beConstructedWith($listener); 25 | } 26 | 27 | function it_is_initializable() 28 | { 29 | $this->shouldHaveType(TrapSink::class); 30 | } 31 | 32 | function it_should_get_the_options() 33 | { 34 | $this->getOptions()->shouldBeEqualTo([ 35 | 'ip' => '0.0.0.0', 36 | 'port' => 162, 37 | 'transport' => 'udp', 38 | 'version' => null, 39 | 'community' => null, 40 | 'whitelist' => null, 41 | 'timeout_connect' => 5, 42 | ]); 43 | } 44 | 45 | function it_should_set_the_server_runner(TrapServerRunner $runner) 46 | { 47 | $this->setServer($runner); 48 | } 49 | 50 | function it_should_listen_for_traps(TrapServerRunner $runner, $listener) 51 | { 52 | $this->beConstructedWith($listener, ['port' => 11162]); 53 | $this->setServer($runner); 54 | 55 | $runner->run(Argument::type(Socket::class))->shouldBeCalled(); 56 | $this->listen(); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /tests/spec/FreeDSx/Snmp/Value/ArbitraryValueSpec.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | 11 | namespace spec\FreeDSx\Snmp\Value; 12 | 13 | use FreeDSx\Asn1\Asn1; 14 | use FreeDSx\Asn1\Type\IncompleteType; 15 | use FreeDSx\Snmp\Protocol\ProtocolElementInterface; 16 | use FreeDSx\Snmp\Value\AbstractValue; 17 | use FreeDSx\Snmp\Value\ArbitraryValue; 18 | use PhpSpec\ObjectBehavior; 19 | 20 | class ArbitraryValueSpec extends ObjectBehavior 21 | { 22 | function let() 23 | { 24 | $this->beConstructedWith('foo'); 25 | } 26 | 27 | function it_is_initializable() 28 | { 29 | $this->shouldHaveType(ArbitraryValue::class); 30 | } 31 | 32 | function it_should_extend_the_abstract_value() 33 | { 34 | $this->shouldBeAnInstanceOf(AbstractValue::class); 35 | } 36 | 37 | function it_should_implement_the_ProtocolElementInterface() 38 | { 39 | $this->shouldImplement(ProtocolElementInterface::class); 40 | } 41 | 42 | function it_should_get_the_value() 43 | { 44 | $this->getValue()->shouldBeEqualTo('foo'); 45 | } 46 | 47 | function it_should_set_the_value() 48 | { 49 | $this->setValue('bar'); 50 | $this->getValue()->shouldBeEqualTo('bar'); 51 | } 52 | 53 | function it_should_check_if_the_value_equals_a_specific_value() 54 | { 55 | $this->equals('foo')->shouldBeEqualTo(true); 56 | $this->equals('bar')->shouldBeEqualTo(false); 57 | } 58 | 59 | function it_should_check_if_the_value_equals_a_specific_value_non_strict() 60 | { 61 | $this->equals('foo', true)->shouldBeEqualTo(true); 62 | $this->equals('bar', false)->shouldBeEqualTo(false); 63 | } 64 | 65 | function it_should_have_a_string_representation() 66 | { 67 | $this->__toString()->shouldBeEqualTo('foo'); 68 | } 69 | 70 | function it_should_have_an_ASN1_representation() 71 | { 72 | $this->toAsn1()->shouldBeLike(Asn1::application(4, Asn1::octetString('foo'))); 73 | } 74 | 75 | function it_should_be_constructed_from_an_ASN1_representation() 76 | { 77 | $this::fromAsn1(Asn1::application(4, new IncompleteType('foo')))->shouldBeLike(new ArbitraryValue('foo')); 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /tests/spec/FreeDSx/Snmp/Value/CounterValueSpec.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | 11 | namespace spec\FreeDSx\Snmp\Value; 12 | 13 | use FreeDSx\Asn1\Asn1; 14 | use FreeDSx\Asn1\Type\IncompleteType; 15 | use FreeDSx\Snmp\Protocol\ProtocolElementInterface; 16 | use FreeDSx\Snmp\Value\AbstractValue; 17 | use FreeDSx\Snmp\Value\CounterValue; 18 | use PhpSpec\ObjectBehavior; 19 | 20 | class CounterValueSpec extends ObjectBehavior 21 | { 22 | function let() 23 | { 24 | $this->beConstructedWith(9); 25 | } 26 | 27 | function it_is_initializable() 28 | { 29 | $this->shouldHaveType(CounterValue::class); 30 | } 31 | 32 | function it_should_extend_the_abstract_value() 33 | { 34 | $this->shouldBeAnInstanceOf(AbstractValue::class); 35 | } 36 | 37 | function it_should_implement_the_ProtocolElementInterface() 38 | { 39 | $this->shouldImplement(ProtocolElementInterface::class); 40 | } 41 | 42 | function it_should_get_the_value() 43 | { 44 | $this->getValue()->shouldBeEqualTo(9); 45 | } 46 | 47 | function it_should_set_the_value() 48 | { 49 | $this->setValue(1); 50 | $this->getValue()->shouldBeEqualTo(1); 51 | } 52 | 53 | function it_should_check_if_the_value_equals_a_specific_value() 54 | { 55 | $this->equals(9)->shouldBeEqualTo(true); 56 | $this->equals(1)->shouldBeEqualTo(false); 57 | } 58 | 59 | function it_should_check_if_the_value_equals_a_specific_value_non_strict() 60 | { 61 | $this->equals('9', false)->shouldBeEqualTo(true); 62 | } 63 | 64 | function it_should_have_a_string_representation() 65 | { 66 | $this->__toString()->shouldBeEqualTo('9'); 67 | } 68 | 69 | function it_should_have_an_ASN1_representation() 70 | { 71 | $this->toAsn1()->shouldBeLike(Asn1::application(1, Asn1::integer(9))); 72 | } 73 | 74 | function it_should_be_constructed_from_an_ASN1_representation() 75 | { 76 | $this::fromAsn1(Asn1::application(1, new IncompleteType("\x09")))->shouldBeLike(new CounterValue(9)); 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /tests/spec/FreeDSx/Snmp/Value/IntegerValueSpec.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | 11 | namespace spec\FreeDSx\Snmp\Value; 12 | 13 | use FreeDSx\Asn1\Asn1; 14 | use FreeDSx\Snmp\Protocol\ProtocolElementInterface; 15 | use FreeDSx\Snmp\Value\AbstractValue; 16 | use FreeDSx\Snmp\Value\IntegerValue; 17 | use PhpSpec\ObjectBehavior; 18 | 19 | class IntegerValueSpec extends ObjectBehavior 20 | { 21 | function let() 22 | { 23 | $this->beConstructedWith(9); 24 | } 25 | 26 | function it_is_initializable() 27 | { 28 | $this->shouldHaveType(IntegerValue::class); 29 | } 30 | 31 | function it_should_extend_the_abstract_value() 32 | { 33 | $this->shouldBeAnInstanceOf(AbstractValue::class); 34 | } 35 | 36 | function it_should_implement_the_ProtocolElementInterface() 37 | { 38 | $this->shouldImplement(ProtocolElementInterface::class); 39 | } 40 | 41 | function it_should_get_the_value() 42 | { 43 | $this->getValue()->shouldBeEqualTo(9); 44 | } 45 | 46 | function it_should_set_the_value() 47 | { 48 | $this->setValue(1); 49 | $this->getValue()->shouldBeEqualTo(1); 50 | } 51 | 52 | function it_should_check_if_the_value_equals_a_specific_value() 53 | { 54 | $this->equals(9)->shouldBeEqualTo(true); 55 | $this->equals(1)->shouldBeEqualTo(false); 56 | } 57 | 58 | function it_should_check_if_the_value_equals_a_specific_value_non_strict() 59 | { 60 | $this->equals('9', false)->shouldBeEqualTo(true); 61 | } 62 | 63 | function it_should_have_a_string_representation() 64 | { 65 | $this->__toString()->shouldBeEqualTo('9'); 66 | } 67 | 68 | function it_should_have_an_ASN1_representation() 69 | { 70 | $this->toAsn1()->shouldBeLike(Asn1::integer(9)); 71 | } 72 | 73 | function it_should_be_constructed_from_an_ASN1_representation() 74 | { 75 | $this::fromAsn1(Asn1::integer(9))->shouldBeLike(new IntegerValue(9)); 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /tests/spec/FreeDSx/Snmp/Value/IpAddressValueSpec.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | 11 | namespace spec\FreeDSx\Snmp\Value; 12 | 13 | use FreeDSx\Asn1\Asn1; 14 | use FreeDSx\Asn1\Type\IncompleteType; 15 | use FreeDSx\Snmp\Protocol\ProtocolElementInterface; 16 | use FreeDSx\Snmp\Value\AbstractValue; 17 | use FreeDSx\Snmp\Value\IpAddressValue; 18 | use PhpSpec\ObjectBehavior; 19 | 20 | class IpAddressValueSpec extends ObjectBehavior 21 | { 22 | function let() 23 | { 24 | $this->beConstructedWith('127.0.0.1'); 25 | } 26 | 27 | function it_is_initializable() 28 | { 29 | $this->shouldHaveType(IpAddressValue::class); 30 | } 31 | 32 | function it_should_extend_the_abstract_value() 33 | { 34 | $this->shouldBeAnInstanceOf(AbstractValue::class); 35 | } 36 | 37 | function it_should_implement_the_ProtocolElementInterface() 38 | { 39 | $this->shouldImplement(ProtocolElementInterface::class); 40 | } 41 | 42 | function it_should_get_the_value() 43 | { 44 | $this->getValue()->shouldBeEqualTo('127.0.0.1'); 45 | } 46 | 47 | function it_should_set_the_value() 48 | { 49 | $this->setValue('127.0.0.2'); 50 | $this->getValue()->shouldBeEqualTo('127.0.0.2'); 51 | } 52 | 53 | function it_should_check_if_the_value_equals_a_specific_value() 54 | { 55 | $this->equals('127.0.0.1')->shouldBeEqualTo(true); 56 | $this->equals('127.0.0.2')->shouldBeEqualTo(false); 57 | } 58 | 59 | function it_should_have_a_string_representation() 60 | { 61 | $this->__toString()->shouldBeEqualTo('127.0.0.1'); 62 | } 63 | 64 | function it_should_have_an_ASN1_representation() 65 | { 66 | $this->toAsn1()->shouldBeLike(Asn1::application(0, Asn1::octetString(hex2bin('7f000001')))); 67 | } 68 | 69 | function it_should_be_constructed_from_an_ASN1_representation() 70 | { 71 | $this::fromAsn1(Asn1::application(0, new IncompleteType(hex2bin('7f000001'))))->shouldBeLike(new IpAddressValue('127.0.0.1')); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /tests/spec/FreeDSx/Snmp/Value/OidValueSpec.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | 11 | namespace spec\FreeDSx\Snmp\Value; 12 | 13 | use FreeDSx\Asn1\Asn1; 14 | use FreeDSx\Snmp\Protocol\ProtocolElementInterface; 15 | use FreeDSx\Snmp\Value\AbstractValue; 16 | use FreeDSx\Snmp\Value\OidValue; 17 | use PhpSpec\ObjectBehavior; 18 | 19 | class OidValueSpec extends ObjectBehavior 20 | { 21 | function let() 22 | { 23 | $this->beConstructedWith('1.2.3'); 24 | } 25 | 26 | function it_is_initializable() 27 | { 28 | $this->shouldHaveType(OidValue::class); 29 | } 30 | 31 | function it_should_extend_the_abstract_value() 32 | { 33 | $this->shouldBeAnInstanceOf(AbstractValue::class); 34 | } 35 | 36 | function it_should_implement_the_ProtocolElementInterface() 37 | { 38 | $this->shouldImplement(ProtocolElementInterface::class); 39 | } 40 | 41 | function it_should_get_the_value() 42 | { 43 | $this->getValue()->shouldBeEqualTo('1.2.3'); 44 | } 45 | 46 | function it_should_set_the_value() 47 | { 48 | $this->setValue('1.2'); 49 | $this->getValue()->shouldBeEqualTo('1.2'); 50 | } 51 | 52 | function it_should_check_if_the_value_equals_a_specific_value() 53 | { 54 | $this->equals('1.2.3')->shouldBeEqualTo(true); 55 | $this->equals('bar')->shouldBeEqualTo(false); 56 | } 57 | 58 | function it_should_have_a_string_representation() 59 | { 60 | $this->__toString()->shouldBeEqualTo('1.2.3'); 61 | } 62 | 63 | function it_should_have_an_ASN1_representation() 64 | { 65 | $this->toAsn1()->shouldBeLike(Asn1::oid('1.2.3')); 66 | } 67 | 68 | function it_should_be_constructed_from_an_ASN1_representation() 69 | { 70 | $this::fromAsn1(Asn1::oid('1.2.3'))->shouldBeLike(new OidValue('1.2.3')); 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /tests/spec/FreeDSx/Snmp/Value/StringValueSpec.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | 11 | namespace spec\FreeDSx\Snmp\Value; 12 | 13 | use FreeDSx\Asn1\Asn1; 14 | use FreeDSx\Snmp\Protocol\ProtocolElementInterface; 15 | use FreeDSx\Snmp\Value\AbstractValue; 16 | use FreeDSx\Snmp\Value\StringValue; 17 | use PhpSpec\ObjectBehavior; 18 | 19 | class StringValueSpec extends ObjectBehavior 20 | { 21 | function let() 22 | { 23 | $this->beConstructedWith('foo'); 24 | } 25 | 26 | function it_is_initializable() 27 | { 28 | $this->shouldHaveType(StringValue::class); 29 | } 30 | 31 | function it_should_extend_the_abstract_value() 32 | { 33 | $this->shouldBeAnInstanceOf(AbstractValue::class); 34 | } 35 | 36 | function it_should_implement_the_ProtocolElementInterface() 37 | { 38 | $this->shouldImplement(ProtocolElementInterface::class); 39 | } 40 | 41 | function it_should_get_the_value() 42 | { 43 | $this->getValue()->shouldBeEqualTo('foo'); 44 | } 45 | 46 | function it_should_set_the_value() 47 | { 48 | $this->setValue('bar'); 49 | $this->getValue()->shouldBeEqualTo('bar'); 50 | } 51 | 52 | function it_should_check_if_the_value_equals_a_specific_value() 53 | { 54 | $this->equals('foo')->shouldBeEqualTo(true); 55 | $this->equals('bar')->shouldBeEqualTo(false); 56 | } 57 | 58 | function it_should_have_a_string_representation() 59 | { 60 | $this->__toString()->shouldBeEqualTo('foo'); 61 | } 62 | 63 | function it_should_have_an_ASN1_representation() 64 | { 65 | $this->toAsn1()->shouldBeLike(Asn1::octetString('foo')); 66 | } 67 | 68 | function it_should_be_constructed_from_an_ASN1_representation() 69 | { 70 | $this::fromAsn1(Asn1::octetString('foo'))->shouldBeLike(new StringValue('foo')); 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /tests/spec/FreeDSx/Snmp/Value/TimeTicksValueSpec.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | 11 | namespace spec\FreeDSx\Snmp\Value; 12 | 13 | use FreeDSx\Asn1\Asn1; 14 | use FreeDSx\Asn1\Type\IncompleteType; 15 | use FreeDSx\Snmp\Protocol\ProtocolElementInterface; 16 | use FreeDSx\Snmp\Value\AbstractValue; 17 | use FreeDSx\Snmp\Value\TimeTicksValue; 18 | use PhpSpec\ObjectBehavior; 19 | 20 | class TimeTicksValueSpec extends ObjectBehavior 21 | { 22 | function let() 23 | { 24 | $this->beConstructedWith(9); 25 | } 26 | 27 | function it_is_initializable() 28 | { 29 | $this->shouldHaveType(TimeTicksValue::class); 30 | } 31 | 32 | function it_should_extend_the_abstract_value() 33 | { 34 | $this->shouldBeAnInstanceOf(AbstractValue::class); 35 | } 36 | 37 | function it_should_implement_the_ProtocolElementInterface() 38 | { 39 | $this->shouldImplement(ProtocolElementInterface::class); 40 | } 41 | 42 | function it_should_get_the_value() 43 | { 44 | $this->getValue()->shouldBeEqualTo(9); 45 | } 46 | 47 | function it_should_set_the_value() 48 | { 49 | $this->setValue(1); 50 | $this->getValue()->shouldBeEqualTo(1); 51 | } 52 | 53 | function it_should_check_if_the_value_equals_a_specific_value() 54 | { 55 | $this->equals(9)->shouldBeEqualTo(true); 56 | $this->equals(1)->shouldBeEqualTo(false); 57 | } 58 | 59 | function it_should_check_if_the_value_equals_a_specific_value_non_strict() 60 | { 61 | $this->equals('9', false)->shouldBeEqualTo(true); 62 | } 63 | 64 | function it_should_have_a_string_representation() 65 | { 66 | $this->__toString()->shouldBeEqualTo('9'); 67 | } 68 | 69 | function it_should_have_an_ASN1_representation() 70 | { 71 | $this->toAsn1()->shouldBeLike(Asn1::application(3, Asn1::integer(9))); 72 | } 73 | 74 | function it_should_be_constructed_from_an_ASN1_representation() 75 | { 76 | $this::fromAsn1(Asn1::application(3, new IncompleteType("\x09")))->shouldBeLike(new TimeTicksValue(9)); 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /tests/spec/FreeDSx/Snmp/Value/UnsignedIntegerValueSpec.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | 11 | namespace spec\FreeDSx\Snmp\Value; 12 | 13 | use FreeDSx\Asn1\Asn1; 14 | use FreeDSx\Asn1\Type\IncompleteType; 15 | use FreeDSx\Snmp\Protocol\ProtocolElementInterface; 16 | use FreeDSx\Snmp\Value\AbstractValue; 17 | use FreeDSx\Snmp\Value\UnsignedIntegerValue; 18 | use PhpSpec\ObjectBehavior; 19 | 20 | class UnsignedIntegerValueSpec extends ObjectBehavior 21 | { 22 | function let() 23 | { 24 | $this->beConstructedWith(9); 25 | } 26 | 27 | function it_is_initializable() 28 | { 29 | $this->shouldHaveType(UnsignedIntegerValue::class); 30 | } 31 | 32 | function it_should_extend_the_abstract_value() 33 | { 34 | $this->shouldBeAnInstanceOf(AbstractValue::class); 35 | } 36 | 37 | function it_should_implement_the_ProtocolElementInterface() 38 | { 39 | $this->shouldImplement(ProtocolElementInterface::class); 40 | } 41 | 42 | function it_should_get_the_value() 43 | { 44 | $this->getValue()->shouldBeEqualTo(9); 45 | } 46 | 47 | function it_should_set_the_value() 48 | { 49 | $this->setValue(1); 50 | $this->getValue()->shouldBeEqualTo(1); 51 | } 52 | 53 | function it_should_check_if_the_value_equals_a_specific_value() 54 | { 55 | $this->equals(9)->shouldBeEqualTo(true); 56 | $this->equals(1)->shouldBeEqualTo(false); 57 | } 58 | 59 | function it_should_check_if_the_value_equals_a_specific_value_non_strict() 60 | { 61 | $this->equals('9', false)->shouldBeEqualTo(true); 62 | } 63 | 64 | function it_should_have_a_string_representation() 65 | { 66 | $this->__toString()->shouldBeEqualTo('9'); 67 | } 68 | 69 | function it_should_have_an_ASN1_representation() 70 | { 71 | $this->toAsn1()->shouldBeLike(Asn1::application(2, Asn1::integer(9))); 72 | } 73 | 74 | function it_should_be_constructed_from_an_ASN1_representation() 75 | { 76 | $this::fromAsn1(Asn1::application(2, new IncompleteType("\x09")))->shouldBeLike(new UnsignedIntegerValue(9)); 77 | } 78 | } 79 | --------------------------------------------------------------------------------