From 3abfb1f6d7f9ed0496e8f9290cae4adc266e7637 Mon Sep 17 00:00:00 2001
From: "th.l" <thl-cmk@outlook.com>
Date: Tue, 26 Dec 2023 18:21:09 +0100
Subject: [PATCH] update project

---
 README.md                              |   2 +-
 agent_based/inv_ipv4_routes.py         | 185 +++++++++++++++++++++++++
 mkp/inv_ipv4_routes-0.0.1-20231227.mkp | Bin 0 -> 2610 bytes
 packages/inv_ipv4_routes               |  12 ++
 web/plugins/views/inv_ipv4_routes.py   |  29 ++++
 5 files changed, 227 insertions(+), 1 deletion(-)
 create mode 100644 agent_based/inv_ipv4_routes.py
 create mode 100644 mkp/inv_ipv4_routes-0.0.1-20231227.mkp
 create mode 100644 packages/inv_ipv4_routes
 create mode 100644 web/plugins/views/inv_ipv4_routes.py

diff --git a/README.md b/README.md
index 9209cf4..2f8f741 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-[PACKAGE]: ../../raw/master/packagee-0.1.2-20230706.mkp "package-0.1.2-20230706.mkp"
+[PACKAGE]: ../../raw/master/mkp/inv_ipv4_routes-0.0.1-20231227.mkp "inv_ipv4_routes-0.0.1-20231227.mkp"
 # Title
 
 A short description about the plugin
diff --git a/agent_based/inv_ipv4_routes.py b/agent_based/inv_ipv4_routes.py
new file mode 100644
index 0000000..81c85ee
--- /dev/null
+++ b/agent_based/inv_ipv4_routes.py
@@ -0,0 +1,185 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+#
+# License: GNU General Public License v2
+#
+# Author: thl-cmk[at]outlook[dot]com
+# URL   : https://thl-cmk.hopto.org
+# Date  : 2023-12-27
+# File  : inv_ipv4_route.py
+#
+# inventory of IPv4 routing information
+
+
+import ipaddress
+from dataclasses import dataclass
+from typing import List
+
+from cmk.base.plugins.agent_based.agent_based_api.v1 import (
+    OIDEnd,
+)
+from cmk.base.plugins.agent_based.agent_based_api.v1 import (
+    register,
+    SNMPTree,
+    TableRow,
+    exists,
+    render,
+)
+from cmk.base.plugins.agent_based.agent_based_api.v1.type_defs import (
+    StringTable,
+    InventoryResult,
+)
+
+_route_type = {
+    '1': 'other',
+    '2': 'reject',
+    '3': 'local',
+    '4': 'remote',
+}
+_route_status = {
+    '1': 'active',
+    '2': 'not in service',
+    '3': 'not ready',
+    '4': 'create and go',
+    '5': 'create and wait',
+    '6': 'destroy',
+}
+
+_route_protocol = {
+    '1': 'other',
+    '2': 'local',
+    '3': 'net mgmt',
+    '4': 'ICMP',
+    '5': 'egp',
+    '6': 'ggp',
+    '7': 'hello',
+    '8': 'RIP',
+    '9': 'ISIS',
+    '10': 'esIs',
+    '11': 'Cisco IGRP',
+    '12': 'bbnSpfIgp',
+    '13': 'OSPF',
+    '14': 'BGP',
+    '15': 'idpr',
+    '16': 'Cisco EIGRP',
+    '17': 'dvmrp',
+}
+
+
+@dataclass(frozen=True)
+class Ipv4Route:
+    age: int | None
+    cidr: int
+    destination: str
+    if_index: int
+    if_name: str
+    netmask: str
+    next_hop: str
+    protocol: str
+    status: str
+    type: str
+
+
+def parse_inv_ipv4_routes(string_table: List[StringTable]) -> List[Ipv4Route]:
+    routes, if_info = string_table
+
+    interface_by_index = {if_index: if_name for if_index, if_name in if_info}
+
+    ipv4_routes = []
+    for destination, netmask, next_hop, if_index, route_type, protocol, age, status in routes:
+        ipv4 = ipaddress.IPv4Network(address=f'{destination}/{netmask}', strict=False)
+        ipv4_routes.append(
+            Ipv4Route(
+                age=int(age) if age.isdigit() else None,
+                cidr=int(ipv4.prefixlen),
+                destination=str(destination),
+                if_index=int(if_index),
+                if_name=str(interface_by_index.get(if_index, f'unknown ({if_index})')),
+                netmask=str(netmask),
+                next_hop=str(next_hop),
+                protocol=_route_protocol.get(protocol, f'unknown ({protocol})'),
+                status=_route_status.get(status, f'unknown ({status})'),
+                type=_route_type.get(route_type, f'unknown ({route_type})'),
+            )
+        )
+
+    return ipv4_routes
+
+
+def inventory_ipv4_routes(section: List[Ipv4Route]) -> InventoryResult:
+    path = ['networking', 'routes']
+
+    for ipv4_route in section:
+        key_columns = {
+            'target': f'{ipv4_route.destination}/{ipv4_route.cidr}',
+            'gateway': ipv4_route.next_hop,
+        }
+        inventory_columns = {
+            # 'age': render.timespan(ipv4_route.age),
+            'device': ipv4_route.if_name,
+            'protocol': ipv4_route.protocol,
+            'status': ipv4_route.status,
+            'type': ipv4_route.type,
+        }
+        if ipv4_route.age:
+            inventory_columns['age'] = render.timespan(ipv4_route.age)
+
+        yield TableRow(
+            path=path,
+            key_columns=key_columns,
+            inventory_columns=inventory_columns
+        )
+
+
+register.snmp_section(
+    name='inv_ipv4_routes',
+    parse_function=parse_inv_ipv4_routes,
+    fetch=[
+        SNMPTree(
+            base='.1.3.6.1.2.1.4.24.4.1',  # IP-MIB::ipCidrRouteEntry
+            oids=[
+                '1',  # ipCidrRouteDest
+                '2',  # ipCidrRouteMask
+                '4',  # ipCidrRouteNextHop
+                '5',  # ipCidrRouteIfIndex
+                '6',  # ipCidrRouteType
+                '7',  # ipCidrRouteProto
+                '8',  # ipCidrRouteAge
+                '16'  # ipCidrRouteStatus
+
+            ]
+        ),
+        SNMPTree(
+            base='.1.3.6.1.2.1.31.1.1.1',  #
+            oids=[
+                OIDEnd(),  # ifIndex
+                '1',  # ifName
+            ]),
+    ],
+    detect=exists('.1.3.6.1.2.1.4.24.4.1.1.*'),  #
+)
+
+register.inventory_plugin(
+    name='inv_ipv4_routes',
+    inventory_function=inventory_ipv4_routes,
+)
+
+# IP-MIB::ip.24.7.1.7.2.16.255.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.2.0.0.0.0 = INTEGER: 10501
+#                          FE  80  0 0 0 0 0 0 0 0 0 0 0 0 0 0 12 0 3 a4  a  2 0 0 0 0
+# IP-MIB::ip.24.7.1.7.4.20.254.128.0.0.0.0.0.0.0.0.0.0.0.0.0.0.18.0.3.164.10.2.0.0.0.0 = INTEGER: 10501
+# IP-MIB::ip.24.7.1.7.4.20.254.128.0.0.0.0.0.0.0.0.0.0.0.0.0.0.18.0.3.201.10.2.0.0.0.0 = INTEGER: 1
+# IP-MIB::ip.24.7.1.7.4.20.254.128.0.0.0.0.0.0.0.0.0.0.0.0.0.1.18.0.3.164.128.2.0.0.0.0 = INTEGER: 10501
+# IP-MIB::ip.24.7.1.7.4.20.254.128.0.0.0.0.0.0.1.146.1.104.0.0.0.1.18.0.3.201.128.2.0.0.0.0 = INTEGER: 1
+
+
+# IP-MIB::ip.24.7.1.7.2.16.255.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.2.0.0.0.0 = INTEGER: 10501
+#                          FE  80  0 0 0 0 0 0 0 0 0 0 0 0 0 0 12 0 3 a4  a  2 0 0 0 0
+# IP-MIB::ip.24.7.1.7.4.20.254.128.0.0.0.0.0.0.0.0.0.0.0.0.0.0. 18.0.3.164. 10.2.0.0.0.0 = INTEGER: 10501
+# IP-MIB::ip.24.7.1.7.4.20.254.128.0.0.0.0.0.0.0.0.0.0.0.0.0.0. 18.0.3.201. 10.2.0.0.0.0 = INTEGER: 1
+# IP-MIB::ip.24.7.1.7.4.20.254.128.0.0.0.0.0.0.0.0.0.0.0.0.0.0. 18.0.3.210. 10.2.0.0.0.0 = INTEGER: 10
+#                          1   2   3 4 5 6 7 8 9 0 1 2 3 4 5 6
+# IP-MIB::ip.24.7.1.7.4.20.254.128.0.0.0.0.0.0.0.0.0.0.0.0.0.1.18.0.3.164.128.2.0.0.0.0 = INTEGER: 10501
+#                          fe  80  0 0 0 0 0 0 1 92  1 68  0 0 0 1  -> fe80::192:168:0:1
+# IP-MIB::ip.24.7.1.7.4.20.254.128.0.0.0.0.0.0.1.146.1.104.0.0.0.1 .18.0.3.201. 128.2.0.0.0.0 = INTEGER: 1
+#                          FE  80  0 0 0 0 0 0 B6  E9  B0  FF  FE  57 FB  41  12 0 3 D2   80  2 0 0 0 0
+# IP-MIB::ip.24.7.1.7.4.20.254.128.0.0.0.0.0.0.182.233.176.255.254.87.251.65. 18.0.3.210. 128.2.0.0.0.0 = INTEGER: 10
diff --git a/mkp/inv_ipv4_routes-0.0.1-20231227.mkp b/mkp/inv_ipv4_routes-0.0.1-20231227.mkp
new file mode 100644
index 0000000000000000000000000000000000000000..4570c23729a78e06d8488f74909cfa40e54d75ae
GIT binary patch
literal 2610
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
DI{+s)

literal 0
HcmV?d00001

diff --git a/packages/inv_ipv4_routes b/packages/inv_ipv4_routes
new file mode 100644
index 0000000..08cde07
--- /dev/null
+++ b/packages/inv_ipv4_routes
@@ -0,0 +1,12 @@
+{'author': 'Th.L. (thl-cmk[at]outlook[dot]com)',
+ 'description': 'Adds the IPv4 routes of a device monitored via SNMP to the '
+                'inventory\n',
+ 'download_url': 'https://thl-cmk.hopto.org',
+ 'files': {'agent_based': ['inv_ipv4_routes.py'],
+           'web': ['plugins/views/inv_ipv4_routes.py']},
+ 'name': 'inv_ipv4_routes',
+ 'title': 'Inventory of IPv4 routes',
+ 'version': '0.0.1-20231227',
+ 'version.min_required': '2.2.0b1',
+ 'version.packaged': '2.2.0p14',
+ 'version.usable_until': '2.3.0p1'}
diff --git a/web/plugins/views/inv_ipv4_routes.py b/web/plugins/views/inv_ipv4_routes.py
new file mode 100644
index 0000000..eb44dfb
--- /dev/null
+++ b/web/plugins/views/inv_ipv4_routes.py
@@ -0,0 +1,29 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+#
+# License: GNU General Public License v2
+#
+# Author: thl-cmk[at]outlook[dot]com
+# URL   : https://thl-cmk.hopto.org
+# Date  : 2023-12-27
+# File  : inv_ip_addresses.py
+
+from cmk.gui.views.inventory.registry import inventory_displayhints
+from cmk.gui.i18n import _l
+
+inventory_displayhints.update({
+    ".networking.routes:": {
+        "title": _l("Routes"),
+        "keyorder": ["target", "device", "type", "gateway"],
+        'view': 'inviproutes_of_host',
+    },
+    ".networking.routes:*.target": {"title": _l("Target"), "paint": "ipv4_network"},
+    ".networking.routes:*.device": {"title": _l("Device")},
+    ".networking.routes:*.type": {"title": _l("Type of route"), "paint": "route_type"},
+    ".networking.routes:*.gateway": {"title": _l("Gateway")},
+
+    ".networking.routes:*.protocol": {"title": _l("Protocol")},
+    ".networking.routes:*.status": {"title": _l("Status")},
+    ".networking.routes:*.age": {"title": _l("Age")},
+
+})
-- 
GitLab