{"id":27858432,"url":"https://github.com/roboplc/snmp2","last_synced_at":"2025-05-04T14:10:21.855Z","repository":{"id":270150872,"uuid":"909472629","full_name":"roboplc/snmp2","owner":"roboplc","description":"Dependency-free basic SNMP v1/v2/v3 client in Rust.","archived":false,"fork":false,"pushed_at":"2025-04-02T21:34:29.000Z","size":81,"stargazers_count":30,"open_issues_count":0,"forks_count":5,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-05-04T05:03:48.979Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/roboplc.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-12-28T20:04:55.000Z","updated_at":"2025-04-21T09:03:15.000Z","dependencies_parsed_at":"2024-12-28T21:18:33.991Z","dependency_job_id":"a1d9a41e-54ad-4636-a80e-1f51b71a38db","html_url":"https://github.com/roboplc/snmp2","commit_stats":null,"previous_names":["roboplc/snmp2"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/roboplc%2Fsnmp2","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/roboplc%2Fsnmp2/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/roboplc%2Fsnmp2/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/roboplc%2Fsnmp2/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/roboplc","download_url":"https://codeload.github.com/roboplc/snmp2/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252344577,"owners_count":21732981,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-05-04T14:10:21.165Z","updated_at":"2025-05-04T14:10:21.838Z","avatar_url":"https://github.com/roboplc.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003ch2\u003e\n  RUST-SNMP\n  \u003ca href=\"https://crates.io/crates/snmp2\"\u003e\u003cimg alt=\"crates.io page\" src=\"https://img.shields.io/crates/v/snmp2.svg\"\u003e\u003c/img\u003e\u003c/a\u003e\n  \u003ca href=\"https://docs.rs/snmp2\"\u003e\u003cimg alt=\"docs.rs page\" src=\"https://docs.rs/snmp2/badge.svg\"\u003e\u003c/img\u003e\u003c/a\u003e\n  \u003ca href=\"https://github.com/roboplc/snmp2/actions/workflows/ci.yml\"\u003e\n    \u003cimg alt=\"GitHub Actions CI\" src=\"https://github.com/roboplc/snmp2/actions/workflows/ci.yml/badge.svg\"\u003e\u003c/img\u003e\n  \u003c/a\u003e\n\u003c/h2\u003e\n\nDependency-free basic SNMP v1/v2/v3 client in Rust.\n\nThis is a fork of the original [snmp](https://crates.io/crates/snmp) crate\nwhich has been abandoned long time ago.\n\nSNMP2 is a part of [RoboPLC](https://www.roboplc.com) project.\n\nNew features added to the fork:\n\n- SNMP v1 support (including v1 traps)\n- SNMP v3 authentication (MD5, SHA1, SHA224, SHA256, SHA384, SHA512)\n- SNMP v3 privacy (DES, AES128, AES192, AES256)\n- MIBs support (requires `mibs` feature and `libnetsnmp` library installed)\n- Async session (requires `tokio` feature)\n- Crate code has been refactored and cleaned up\n- OIDs have been migrated to\n  [asn1](https://docs.rs/asn1-rs/latest/asn1_rs/struct.Oid.html)\n- Improved PDU API, added trap handling examples\n\nSupports:\n\n- GET\n- GETNEXT\n- GETBULK\n- SET\n- Basic SNMP v1/v2 types\n- Synchronous/Asynchronous requests\n- UDP transport\n- MIBs (with `mibs` feature, requires `libnetsnmp`)\n- SNMP v3 (requires `v3` feature)\n\n# Examples\n\n## GET NEXT\n\n```rust,no_run\nuse std::time::Duration;\nuse snmp2::{SyncSession, Value, Oid};\n\nlet sys_descr_oid = Oid::from(\u0026[1,3,6,1,2,1,1,1,]).unwrap();\nlet agent_addr    = \"198.51.100.123:161\";\nlet community     = b\"f00b4r\";\nlet timeout       = Duration::from_secs(2);\n\nlet mut sess = SyncSession::new_v2c(agent_addr, community, Some(timeout), 0).unwrap();\nlet mut response = sess.getnext(\u0026sys_descr_oid).unwrap();\nif let Some((_oid, Value::OctetString(sys_descr))) = response.varbinds.next() {\n    println!(\"myrouter sysDescr: {}\", String::from_utf8_lossy(sys_descr));\n}\n```\n\n## GET BULK\n\n```rust,no_run\nuse std::time::Duration;\nuse snmp2::{SyncSession, Oid};\n\nlet system_oid      = Oid::from(\u0026[1,3,6,1,2,1,1,]).unwrap();\nlet agent_addr      = \"[2001:db8:f00:b413::abc]:161\";\nlet community       = b\"f00b4r\";\nlet timeout         = Duration::from_secs(2);\nlet non_repeaters   = 0;\nlet max_repetitions = 7; // number of items in \"system\" OID\n\nlet mut sess = SyncSession::new_v2c(agent_addr, community, Some(timeout), 0).unwrap();\nlet response = sess.getbulk(\u0026[\u0026system_oid], non_repeaters, max_repetitions).unwrap();\n\nfor (name, val) in response.varbinds {\n    println!(\"{} =\u003e {:?}\", name, val);\n}\n```\n\n## SET\n\n```rust,no_run\nuse std::time::Duration;\nuse snmp2::{SyncSession, Value, Oid};\n\nlet syscontact_oid  = Oid::from(\u0026[1,3,6,1,2,1,1,4,0]).unwrap();\nlet contact         = Value::OctetString(b\"Thomas A. Anderson\");\nlet agent_addr      = \"[2001:db8:f00:b413::abc]:161\";\nlet community       = b\"f00b4r\";\nlet timeout         = Duration::from_secs(2);\n\nlet mut sess = SyncSession::new_v2c(agent_addr, community, Some(timeout), 0).unwrap();\nlet response = sess.set(\u0026[(\u0026syscontact_oid, contact)]).unwrap();\n\nassert_eq!(response.error_status, snmp2::snmp::ERRSTATUS_NOERROR);\nfor (name, val) in response.varbinds {\n    println!(\"{} =\u003e {:?}\", name, val);\n}\n```\n\n## TRAPS\n\n```rust,no_run\nuse std::net::UdpSocket;\nuse snmp2::Pdu;\n\nlet socket = UdpSocket::bind(\"0.0.0.0:1162\").expect(\"Could not bind socket\");\nloop {\n    let mut buf = [0; 1500];\n    let size = socket.recv(\u0026mut buf).expect(\"Could not receive data\");\n    let data = \u0026buf[..size];\n    let pdu = Pdu::from_bytes(data).expect(\"Could not parse PDU\");\n    println!(\"Version: {}\", pdu.version().unwrap());\n    println!(\"Community: {}\", std::str::from_utf8(pdu.community).unwrap());\n    for (name, value) in pdu.varbinds {\n        println!(\"{}={:?}\", name, value);\n    }\n}\n```\n\n## Async session\n\n```rust,no_run\nuse std::time::Duration;\nuse snmp2::{AsyncSession, Value, Oid};\n\nasync fn get_next() {\n    // timeouts should be handled by the caller with `tokio::time::timeout`\n    let sys_descr_oid = Oid::from(\u0026[1,3,6,1,2,1,1,1,]).unwrap();\n    let agent_addr    = \"198.51.100.123:161\";\n    let community     = b\"f00b4r\";\n    let mut sess = AsyncSession::new_v2c(agent_addr, community, 0).await.unwrap();\n    let mut response = sess.getnext(\u0026sys_descr_oid).await.unwrap();\n    if let Some((_oid, Value::OctetString(sys_descr))) = response.varbinds.next() {\n        println!(\"myrouter sysDescr: {}\", String::from_utf8_lossy(sys_descr));\n    }\n}\n```\n\n## Working with MIBs\n\nPrepare the system\n\n```shell\napt-get install libsnmp-dev snmp-mibs-downloader\n```\n\n```rust,ignore\nuse snmp2::{mibs::{self, MibConversion as _}, Oid};\n\nmibs::init(\u0026mibs::Config::new().mibs(\u0026[\"./ibmConvergedPowerSystems.mib\"]))\n    .unwrap();\nlet snmp_oid = Oid::from(\u0026[1, 3, 6, 1, 4, 1, 2, 6, 201, 3]).unwrap();\nlet name = snmp_oid.mib_name().unwrap();\nassert_eq!(name, \"IBM-CPS-MIB::cpsSystemSendTrap\");\nlet snmp_oid2 = Oid::from_mib_name(\u0026name).unwrap();\nassert_eq!(snmp_oid, snmp_oid2);\n```\n\n# SNMPv3\n\n* Requires `v3` crate feature.\n\n* All cryptographic algorithms are provided by [openssl](https://www.openssl.org/).\n\n* For authentication, supports: MD5 (RFC3414), SHA1 (RFC3414) and non-standard\n  SHA224, SHA256, SHA384, SHA512.\n\n* For privacy, supports: DES (RFC3414), AES128-CFB (RFC3826) and non-standard\n  AES192-CFB, AES256-CFB. Additional/different AES modes are not supported and\n  may require patching the crate.\n\nNote: DES legacy encryption may be disabled in openssl by default or even not\nsupported at all. Refer to the library documentation how to enable it.\n\n## Example\n\nAuthentication: SHA1, encryption: AES128-CFB\n\n```rust,no_run\nuse snmp2::{SyncSession, v3, Oid};\nuse std::time::Duration;\n\n// the security parameters also keep authoritative engine ID and boot/time\n// counters. these can be either set or resolved/updated automatically.\nlet security = v3::Security::new(b\"public\", b\"secure\")\n    .with_auth_protocol(v3::AuthProtocol::Sha1)\n    .with_auth(v3::Auth::AuthPriv {\n        cipher: v3::Cipher::Aes128,\n        privacy_password: b\"secure-encrypt\".to_vec(),\n    });\nlet mut sess =\n    SyncSession::new_v3(\"192.168.1.1:161\", Some(Duration::from_secs(2)), 0, security).unwrap();\n// In case if engine_id is not provided in security parameters, it is necessary\n// to call init() method to send a blank unauthenticated request to the target\n// to get the engine_id.\nsess.init().unwrap();\nloop {\n    let res = match sess.get(\u0026Oid::from(\u0026[1, 3, 6, 1, 2, 1, 1, 3, 0]).unwrap()) {\n        Ok(r) =\u003e r,\n        // In case if the engine boot / time counters are not set in the security parameters or\n        // they have been changed on the target, e.g. after a reboot, the session returns\n        // an error with the AuthUpdated code. In this case, security parameters are automatically\n        // updated and the request should be repeated.\n        Err(snmp2::Error::AuthUpdated) =\u003e continue,\n        Err(e) =\u003e panic!(\"{}\", e),\n    };\n    println!(\"{} {:?}\", res.version().unwrap(), res.varbinds);\n    std::thread::sleep(Duration::from_secs(1));\n}\n```\n\n## Building\n\nIn case of problems (e.g. with [cross-rs](https://github.com/cross-rs/cross)),\nadd `openssl` with `vendored` feature:\n\n```shell\ncargo add openssl --features vendored\n```\n\n## FIPS-140 support\n\nThe crate uses openssl cryptography only and becomes FIPS-140 compliant as soon\nas FIPS mode is activated in `openssl`. Refer to the\n[openssl crate](https://docs.rs/openssl) crate and\n[openssl library](https://www.openssl.org/) documentation for more details.\n\n## MSRV\n\n1.68.0\n\n## Copyright\n\nCopyright 2016-2018 Hroi Sigurdsson\n\nCopyright 2024 Serhij Symonenko, [Bohemia Automation Limited](https://www.bohemia-automation.com)\n\nLicensed under the [Apache License, Version\n2.0](http://www.apache.org/licenses/LICENSE-2.0) or the [MIT\nlicense](http://opensource.org/licenses/MIT), at your option. This file may not\nbe copied, modified, or distributed except according to those terms.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Froboplc%2Fsnmp2","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Froboplc%2Fsnmp2","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Froboplc%2Fsnmp2/lists"}