/usr/share/perl5/Net/SNMP.pm is in libnet-snmp-perl 6.0.1-3.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 2609 2610 2611 2612 2613 2614 2615 2616 2617 2618 2619 2620 2621 2622 2623 2624 2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 2677 2678 2679 2680 2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 2692 2693 2694 2695 2696 2697 2698 2699 2700 2701 2702 2703 2704 2705 2706 2707 2708 2709 2710 2711 2712 2713 2714 2715 2716 2717 2718 2719 2720 2721 2722 2723 2724 2725 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 2737 2738 2739 2740 2741 2742 2743 2744 2745 2746 2747 2748 2749 2750 2751 2752 2753 2754 2755 2756 2757 2758 2759 2760 2761 2762 2763 2764 2765 2766 2767 2768 2769 2770 2771 2772 2773 2774 2775 2776 2777 2778 2779 2780 2781 2782 2783 2784 2785 2786 2787 2788 2789 2790 2791 2792 2793 2794 2795 2796 2797 2798 2799 2800 2801 2802 2803 2804 2805 2806 2807 2808 2809 2810 2811 2812 2813 2814 2815 2816 2817 2818 2819 2820 2821 2822 2823 2824 2825 2826 2827 2828 2829 2830 2831 2832 2833 2834 2835 2836 2837 2838 2839 2840 2841 2842 2843 2844 2845 2846 2847 2848 2849 2850 2851 2852 2853 2854 2855 2856 2857 2858 2859 2860 2861 2862 2863 2864 2865 2866 2867 2868 2869 2870 2871 2872 2873 2874 2875 2876 2877 2878 2879 2880 2881 2882 2883 2884 2885 2886 2887 2888 2889 2890 2891 2892 2893 2894 2895 2896 2897 2898 2899 2900 2901 2902 2903 2904 2905 2906 2907 2908 2909 2910 2911 2912 2913 2914 2915 2916 2917 2918 2919 2920 2921 2922 2923 2924 2925 2926 2927 2928 2929 2930 2931 2932 2933 2934 2935 2936 2937 2938 2939 2940 2941 2942 2943 2944 2945 2946 2947 2948 2949 2950 2951 2952 2953 2954 2955 2956 2957 2958 2959 2960 2961 2962 2963 2964 2965 2966 2967 2968 2969 2970 2971 2972 2973 2974 2975 2976 2977 2978 2979 2980 2981 2982 2983 2984 2985 2986 2987 2988 2989 2990 2991 2992 2993 2994 2995 2996 2997 2998 2999 3000 3001 3002 3003 3004 3005 3006 3007 3008 3009 3010 3011 3012 3013 3014 3015 3016 3017 3018 3019 3020 3021 3022 3023 3024 3025 3026 3027 3028 3029 3030 3031 3032 3033 3034 3035 3036 3037 3038 3039 3040 3041 3042 3043 3044 3045 3046 3047 3048 3049 3050 3051 3052 3053 3054 3055 3056 3057 3058 3059 3060 3061 3062 3063 3064 3065 3066 3067 3068 3069 3070 3071 3072 3073 3074 3075 3076 3077 3078 3079 3080 3081 3082 3083 3084 3085 3086 3087 3088 3089 3090 3091 3092 3093 3094 3095 3096 3097 3098 3099 3100 3101 3102 3103 3104 3105 3106 3107 3108 3109 3110 3111 3112 3113 3114 3115 3116 3117 3118 3119 3120 3121 3122 3123 3124 3125 3126 3127 3128 3129 3130 3131 3132 3133 3134 3135 3136 3137 3138 3139 3140 3141 3142 3143 3144 3145 3146 3147 3148 3149 3150 3151 3152 3153 3154 3155 3156 3157 3158 3159 3160 3161 3162 3163 3164 3165 3166 3167 3168 3169 3170 3171 3172 3173 3174 3175 3176 3177 3178 3179 3180 3181 3182 3183 3184 3185 3186 3187 3188 3189 3190 3191 3192 3193 3194 3195 3196 3197 3198 3199 3200 3201 3202 3203 3204 3205 3206 3207 3208 3209 3210 3211 3212 3213 3214 3215 3216 3217 3218 3219 3220 3221 3222 3223 3224 3225 3226 3227 3228 3229 3230 3231 3232 3233 3234 3235 3236 3237 3238 3239 3240 3241 3242 3243 3244 3245 3246 3247 3248 3249 3250 3251 3252 3253 3254 3255 3256 3257 3258 3259 3260 3261 3262 3263 3264 3265 3266 3267 3268 3269 3270 3271 3272 3273 3274 3275 3276 3277 3278 3279 3280 3281 3282 3283 3284 3285 3286 3287 3288 3289 3290 3291 3292 3293 3294 3295 3296 3297 3298 3299 3300 3301 3302 3303 3304 3305 3306 3307 3308 3309 3310 3311 3312 3313 3314 3315 3316 3317 3318 3319 3320 3321 3322 3323 3324 3325 3326 3327 3328 3329 3330 3331 3332 3333 3334 3335 3336 3337 3338 3339 3340 3341 3342 3343 3344 3345 3346 3347 3348 3349 3350 3351 3352 3353 3354 3355 3356 3357 3358 3359 3360 3361 3362 3363 3364 3365 3366 3367 3368 3369 3370 3371 3372 3373 3374 3375 3376 3377 3378 3379 3380 3381 3382 3383 3384 3385 3386 3387 3388 3389 3390 3391 3392 3393 3394 3395 3396 3397 3398 3399 3400 3401 3402 3403 3404 3405 3406 3407 3408 3409 3410 3411 3412 3413 3414 3415 3416 3417 3418 3419 3420 3421 3422 3423 3424 3425 3426 3427 3428 3429 3430 3431 3432 3433 3434 3435 3436 3437 3438 3439 3440 3441 3442 3443 3444 3445 3446 3447 3448 3449 3450 3451 3452 3453 3454 3455 3456 3457 3458 3459 3460 3461 3462 3463 3464 3465 3466 3467 3468 3469 3470 3471 3472 3473 3474 3475 3476 3477 3478 3479 3480 3481 3482 3483 3484 3485 3486 3487 3488 3489 3490 3491 3492 3493 3494 3495 3496 3497 3498 3499 3500 3501 3502 3503 3504 3505 3506 3507 3508 3509 3510 3511 3512 3513 3514 3515 3516 3517 3518 3519 3520 3521 3522 3523 3524 3525 3526 3527 3528 3529 3530 3531 3532 3533 3534 3535 3536 3537 3538 3539 3540 3541 3542 3543 3544 3545 3546 3547 3548 3549 3550 3551 3552 3553 3554 3555 3556 3557 3558 3559 3560 3561 3562 3563 3564 3565 3566 3567 3568 3569 3570 3571 3572 3573 3574 3575 3576 3577 3578 3579 3580 3581 3582 3583 3584 3585 3586 3587 3588 3589 3590 3591 3592 | # -*- mode: perl -*-
# ============================================================================
package Net::SNMP;
# $Id: SNMP.pm,v 6.1 2010/09/10 00:01:22 dtown Rel $
# Copyright (c) 1998-2010 David M. Town <dtown@cpan.org>
# All rights reserved.
# This program is free software; you may redistribute it and/or modify it
# under the same terms as the Perl 5 programming language system itself.
# Release 4.0.0 of the Net::SNMP module was dedicated to those who died in
# the September 11, 2001 terrorist attacks on the United States of America.
# ============================================================================
=head1 NAME
Net::SNMP - Object oriented interface to SNMP
=head1 SYNOPSIS
The Net::SNMP module implements an object oriented interface to the Simple
Network Management Protocol. Perl applications can use the module to retrieve
or update information on a remote host using the SNMP protocol. The module
supports SNMP version-1, SNMP version-2c (Community-Based SNMPv2), and SNMP
version-3. The Net::SNMP module assumes that the user has a basic understanding
of the Simple Network Management Protocol and related network management
concepts.
=head1 DESCRIPTION
The Net::SNMP module abstracts the intricate details of the Simple Network
Management Protocol by providing a high level programming interface to the
protocol. Each Net::SNMP object provides a one-to-one mapping between a Perl
object and a remote SNMP agent or manager. Once an object is created, it can
be used to perform the basic protocol exchange actions defined by SNMP.
A Net::SNMP object can be created such that it has either "blocking" or
"non-blocking" properties. By default, the methods used to send SNMP messages
do not return until the protocol exchange has completed successfully or a
timeout period has expired. This behavior gives the object a "blocking"
property because the flow of the code is stopped until the method returns.
The optional named argument B<-nonblocking> can be passed to the object
constructor with a true value to give the object "non-blocking" behavior.
A method invoked by a non-blocking object queues the SNMP message and returns
immediately, allowing the flow of the code to continue. The queued SNMP
messages are not sent until an event loop is entered by calling the
C<snmp_dispatcher()> method. When the SNMP messages are sent, any response to
the messages invokes the subroutine defined by the user when the message was
originally queued. The event loop exits when all messages have been removed
from the queue by either receiving a response, or by exceeding the number of
retries at the Transport Layer.
=head2 Blocking Objects
The default behavior of the methods associated with a Net::SNMP object is to
block the code flow until the method completes. For methods that initiate a
SNMP protocol exchange requiring a response, a hash reference containing the
results of the query is returned. The undefined value is returned by all
methods when a failure has occurred. The C<error()> method can be used to
determine the cause of the failure.
The hash reference returned by a SNMP protocol exchange points to a hash
constructed from the VarBindList contained in the SNMP response message. The
hash is created using the ObjectName and the ObjectSyntax pairs in the
VarBindList. The keys of the hash consist of the OBJECT IDENTIFIERs in dotted
notation corresponding to each ObjectName in the VarBindList. The value of
each hash entry is set equal to the value of the corresponding ObjectSyntax.
This hash reference can also be retrieved using the C<var_bind_list()> method.
=head2 Non-blocking Objects
When a Net::SNMP object is created having non-blocking behavior, the invocation
of a method associated with the object returns immediately, allowing the flow
of the code to continue. When a method is invoked that would initiate a SNMP
protocol exchange requiring a response, either a true value (i.e. 0x1) is
returned immediately or the undefined value is returned if there was a failure.
The C<error()> method can be used to determine the cause of the failure.
The contents of the VarBindList contained in the SNMP response message can be
retrieved by calling the C<var_bind_list()> method using the object reference
passed as the first argument to the callback. The value returned by the
C<var_bind_list()> method is a hash reference created using the ObjectName and
the ObjectSyntax pairs in the VarBindList. The keys of the hash consist of
the OBJECT IDENTIFIERs in dotted notation corresponding to each ObjectName
in the VarBindList. The value of each hash entry is set equal to the value of
the corresponding ObjectSyntax. The undefined value is returned if there has
been a failure and the C<error()> method may be used to determine the reason.
=cut
# ============================================================================
use strict;
## Validate the version of Perl
BEGIN
{
die 'Perl version 5.6.0 or greater is required' if ($] < 5.006);
}
## Version of the Net::SNMP module
our $VERSION = 'v6.0.1';
$VERSION = eval $VERSION;
## Load our modules
use Net::SNMP::Dispatcher();
use Net::SNMP::PDU qw( :ALL !DEBUG_INFO );
use Net::SNMP::Security();
use Net::SNMP::Transport qw( :ports );
## Handle importing/exporting of symbols
use base qw( Exporter );
our @EXPORT = qw(
INTEGER INTEGER32 OCTET_STRING OBJECT_IDENTIFIER IPADDRESS COUNTER
COUNTER32 GAUGE GAUGE32 UNSIGNED32 TIMETICKS OPAQUE COUNTER64 NOSUCHOBJECT
NOSUCHINSTANCE ENDOFMIBVIEW snmp_dispatcher
);
our @EXPORT_OK = qw( oid_context_match );
our %EXPORT_TAGS = (
asn1 => [
qw( INTEGER INTEGER32 OCTET_STRING NULL OBJECT_IDENTIFIER SEQUENCE
IPADDRESS COUNTER COUNTER32 GAUGE GAUGE32 UNSIGNED32 TIMETICKS
OPAQUE COUNTER64 NOSUCHOBJECT NOSUCHINSTANCE ENDOFMIBVIEW
GET_REQUEST GET_NEXT_REQUEST GET_RESPONSE SET_REQUEST TRAP
GET_BULK_REQUEST INFORM_REQUEST SNMPV2_TRAP REPORT )
],
debug => [
qw( DEBUG_ALL DEBUG_NONE DEBUG_MESSAGE DEBUG_TRANSPORT DEBUG_DISPATCHER
DEBUG_PROCESSING DEBUG_SECURITY snmp_debug )
],
generictrap => [
qw( COLD_START WARM_START LINK_DOWN LINK_UP AUTHENTICATION_FAILURE
EGP_NEIGHBOR_LOSS ENTERPRISE_SPECIFIC )
],
snmp => [
qw( SNMP_VERSION_1 SNMP_VERSION_2C SNMP_VERSION_3 SNMP_PORT
SNMP_TRAP_PORT snmp_debug snmp_dispatcher snmp_dispatch_once
snmp_type_ntop oid_base_match oid_lex_cmp oid_lex_sort ticks_to_time )
],
translate => [
qw( TRANSLATE_NONE TRANSLATE_OCTET_STRING TRANSLATE_NULL
TRANSLATE_TIMETICKS TRANSLATE_OPAQUE TRANSLATE_NOSUCHOBJECT
TRANSLATE_NOSUCHINSTANCE TRANSLATE_ENDOFMIBVIEW TRANSLATE_UNSIGNED
TRANSLATE_ALL )
],
);
Exporter::export_ok_tags( qw( asn1 debug generictrap snmp translate ) );
$EXPORT_TAGS{ALL} = [ @EXPORT_OK ];
## Debugging bit masks
sub DEBUG_ALL { 0xff } # All
sub DEBUG_NONE { 0x00 } # None
sub DEBUG_MESSAGE { 0x02 } # Message/PDU encoding/decoding
sub DEBUG_TRANSPORT { 0x04 } # Transport Layer
sub DEBUG_DISPATCHER { 0x08 } # Dispatcher
sub DEBUG_PROCESSING { 0x10 } # Message Processing
sub DEBUG_SECURITY { 0x20 } # Security
## Package variables
our $DEBUG = DEBUG_NONE; # Debug mask
our $DISPATCHER; # Dispatcher instance
our $BLOCKING = 0; # Count of blocking objects
our $NONBLOCKING = 0; # Count of non-blocking objects
BEGIN
{
# Validate the creation of the Dispatcher object.
if (!defined ($DISPATCHER = Net::SNMP::Dispatcher->instance())) {
die 'FATAL: Failed to create Dispatcher instance';
}
# In older versions of Perl, the UNIVERSAL::VERSION() method does not
# handle version defined as v-strings gracefully. We provide our
# own handling of versions to account for this.
if ($] < 5.009) {
*VERSION = \&require_version;
}
}
# [public methods] -----------------------------------------------------------
=head1 METHODS
When named arguments are expected by the methods, two different styles are
supported. All examples in this documentation use the dashed-option style:
$object->method(-argument => $value);
However, the IO:: style is also allowed:
$object->method(Argument => $value);
=over
=item Non-blocking Objects Arguments
When a Net::SNMP object has been created with a "non-blocking" property, most
methods that generate a SNMP message take additional arguments to support this
property.
=over
=item Callback
Most methods associated with a non-blocking object have an optional named
argument called B<-callback>. The B<-callback> argument expects a reference
to a subroutine or to an array whose first element must be a reference to a
subroutine. The subroutine defined by the B<-callback> option is executed when
a response to a SNMP message is received, an error condition has occurred, or
the number of retries for the message has been exceeded.
When the B<-callback> argument only contains a subroutine reference, the
subroutine is evaluated passing a reference to the original Net::SNMP object
as the only parameter. If the B<-callback> argument was defined as an array
reference, all elements in the array are passed to subroutine after the
reference to the Net::SNMP object. The first element, which is required to be
a reference to a subroutine, is removed before the remaining arguments are
passed to that subroutine.
Once one method is invoked with the B<-callback> argument, this argument stays
with the object and is used by any further calls to methods using the
B<-callback> option if the argument is absent. The undefined value may be
passed to the B<-callback> argument to delete the callback.
B<NOTE:> The subroutine being passed with the B<-callback> named argument
should not cause blocking itself. This will cause all the actions in the event
loop to be stopped, defeating the non-blocking property of the Net::SNMP
module.
=item Delay
An optional argument B<-delay> can also be passed to non-blocking objects. The
B<-delay> argument instructs the object to wait the number of seconds passed
to the argument before executing the SNMP protocol exchange. The delay period
starts when the event loop is entered. The B<-delay> parameter is applied to
all methods associated with the object once it is specified. The delay value
must be set back to 0 seconds to disable the delay parameter.
=back
=item SNMPv3 Arguments
A SNMP context is a collection of management information accessible by a SNMP
entity. An item of management information may exist in more than one context
and a SNMP entity potentially has access to many contexts. The combination of
a contextEngineID and a contextName unambiguously identifies a context within
an administrative domain. In a SNMPv3 message, the contextEngineID and
contextName are included as part of the scopedPDU. All methods that generate
a SNMP message optionally take a B<-contextengineid> and B<-contextname>
argument to configure these fields.
=over
=item Context Engine ID
The B<-contextengineid> argument expects a hexadecimal string representing
the desired contextEngineID. The string must be 10 to 64 characters (5 to
32 octets) long and can be prefixed with an optional "0x". Once the
B<-contextengineid> is specified it stays with the object until it is changed
again or reset to default by passing in the undefined value. By default, the
contextEngineID is set to match the authoritativeEngineID of the authoritative
SNMP engine.
=item Context Name
The contextName is passed as a string which must be 0 to 32 octets in length
using the B<-contextname> argument. The contextName stays with the object
until it is changed. The contextName defaults to an empty string which
represents the "default" context.
=back
=back
=cut
{
my @trans_argv = qw(
hostname (?:de?st|peer)?(?:addr|port) (?:src|sock|local)(?:addr|port)
maxmsgsize mtu retries timeout domain listen
);
sub new
{
my ($class, %argv) = @_;
# Create a new data structure for the object
my $this = bless {
'_callback' => undef, # Callback
'_context_engine_id' => undef, # contextEngineID
'_context_name' => undef, # contextName
'_delay' => 0, # Message delay
'_hostname' => q{}, # Hostname
'_discovery_queue' => [], # Pending message queue
'_error' => undef, # Error message
'_nonblocking' => FALSE, # [Non-]blocking flag
'_pdu' => undef, # Message/PDU object
'_security' => undef, # Security Model object
'_translate' => TRANSLATE_ALL, # Translation mask
'_transport' => undef, # Transport Domain object
'_transport_argv' => [], # Transport object argv
'_version' => SNMP_VERSION_1, # SNMP version
}, $class;
# Parse the passed arguments
for (keys %argv) {
if (/^-?debug$/i) {
$this->debug(delete $argv{$_});
} elsif (/^-?nonblocking$/i) {
$this->{_nonblocking} = (delete $argv{$_}) ? TRUE : FALSE;
} elsif (/^-?translate$/i) {
$this->translate(delete $argv{$_});
} elsif (/^-?version$/i) {
$this->_version($argv{$_});
} else {
# Pull out arguments associated with the Transport Domain.
my $key = $_;
for (@trans_argv) {
if ($key =~ /^-?$_$/i) {
push @{$this->{_transport_argv}}, $key, delete $argv{$key};
last;
}
}
}
if (defined $this->{_error}) {
$this->_object_type_validate();
return wantarray ? (undef, $this->{_error}) : undef;
}
}
# We must validate the object type to prevent blocking and
# non-blocking object from existing at the same time.
if (!defined $this->_object_type_validate()) {
return wantarray ? (undef, $this->{_error}) : undef;
}
# Create a Security Model object
($this->{_security}, $this->{_error}) = Net::SNMP::Security->new(%argv);
if (!defined $this->{_security}) {
return wantarray ? (undef, $this->{_error}) : undef;
}
$this->_error_clear();
# Return the object and empty error message (in list context)
return wantarray ? ($this, q{}) : $this;
}
}
sub open
{
my ($this) = @_;
# Clear any previous errors
$this->_error_clear();
# Create a Transport Domain object
($this->{_transport}, $this->{_error}) = Net::SNMP::Transport->new(
@{$this->{_transport_argv}}
);
if (!defined $this->{_transport}) {
return $this->_error();
}
$this->_error_clear();
# Keep a copy of the hostname
$this->{_hostname} = $this->{_transport}->dest_hostname();
# Perform SNMPv3 authoritative engine discovery.
if ($this->version() == SNMP_VERSION_3) {
$this->_perform_discovery();
}
return defined($this->{_error}) ? $this->_error() : $this->{_transport};
}
=head2 session() - create a new Net::SNMP object
($session, $error) = Net::SNMP->session(
[-hostname => $hostname,]
[-port => $port,]
[-localaddr => $localaddr,]
[-localport => $localport,]
[-nonblocking => $boolean,]
[-version => $version,]
[-domain => $domain,]
[-timeout => $seconds,]
[-retries => $count,]
[-maxmsgsize => $octets,]
[-translate => $translate,]
[-debug => $bitmask,]
[-community => $community,] # v1/v2c
[-username => $username,] # v3
[-authkey => $authkey,] # v3
[-authpassword => $authpasswd,] # v3
[-authprotocol => $authproto,] # v3
[-privkey => $privkey,] # v3
[-privpassword => $privpasswd,] # v3
[-privprotocol => $privproto,] # v3
);
This is the constructor for Net::SNMP objects. In scalar context, a
reference to a new Net::SNMP object is returned if the creation of the object
is successful. In list context, a reference to a new Net::SNMP object and an
empty error message string is returned. If a failure occurs, the object
reference is returned as the undefined value. The error string may be used
to determine the cause of the error.
Most of the named arguments passed to the constructor define basic attributes
for the object and are not modifiable after the object has been created. The
B<-timeout>, B<-retries>, B<-maxmsgsize>, B<-translate>, and B<-debug>
arguments are modifiable using an accessor method. See their corresponding
method definitions for a complete description of their usage, default values,
and valid ranges.
=over
=item Transport Domain Arguments
The Net::SNMP module uses UDP/IPv4 as the default Transport Domain to exchange
SNMP messages between the local and remote devices. The module also supports
UDP/IPv6, TCP/IPv4, and TCP/IPv6 as alternative Transport Domains. The
B<-domain> argument can be used to change the Transport Domain by setting the
value to one of the following strings: 'udp6', 'udp/ipv6'; 'tcp', 'tcp4',
'tcp/ipv4'; 'tcp6', or 'tcp/ipv6'. The B<-domain> argument also accepts
the strings 'udp', 'udp4', or 'udp/ipv4' which correspond to the default
Transport Domain of UDP/IPv4.
The transport address of the destination SNMP device can be specified using
the B<-hostname> argument. This argument is optional and defaults to
"localhost". The destination port number can be specified as part of the
transport address or by using the B<-port> argument. Either a numeric port
number or a textual service name can be specified. A numeric port number in
parentheses can optionally follow the service name. This port number will
be used if the service name cannot be resolved. If the destination port number
is not specified, the well-known SNMP port number 161 is used.
By default the source transport address and port number are assigned
dynamically by the local device on which the Net::SNMP module is being used.
This dynamic assignment can be overridden by using the B<-localaddr> and
B<-localport> arguments. These arguments accept the same values as the
B<-hostname> and B<-port> arguments respectively. The resolved address must
correspond to a valid address of an interface on the local device.
When using an IPv4 Transport Domain, the transport address can be specified
as either an IP network hostname or an IPv4 address in standard dotted notation.
The port information can be optionally appended to the hostname or address
delimited by a colon. The accepted IPv4 transport address formats are
C<address>, C<address:port>, C<hostname>, and C<hostname:port>.
When using an IPv6 Transport Domain, the transport address can be specified
as an IP hostname (which will be looked up as a DNS quad-A record) or an IPv6
address in presentation format. The port information can optionally be
included following a colon after the hostname or address. When including this
information after an IPv6 address, the address must be enclosed in square
brackets. The scope zone index (described in RFC 4007) can be specified after
the address as a decimal value delimited by a percent sign. The accepted
transport address formats for IPv6 are C<address>, C<address%zone>,
C<[address]:port>, C<[address%zone]:port>, C<hostname>, and C<hostname:port>.
=item Security Model Arguments
The B<-version> argument controls which other arguments are expected or
required by the C<session()> constructor. The Net::SNMP module supports
SNMPv1, SNMPv2c, and SNMPv3. The module defaults to SNMPv1 if no B<-version>
argument is specified. The B<-version> argument expects either a digit (i.e.
'1', '2', or '3') or a string specifying the version (i.e. 'snmpv1',
'snmpv2c', or 'snmpv3') to define the SNMP version.
The Security Model used by the Net::SNMP object is based on the SNMP version
associated with the object. If the SNMP version is SNMPv1 or SNMPv2c a
Community-based Security Model will be used, while the User-based Security
Model (USM) will be used if the version is SNMPv3.
=over
=item Community-based Security Model Argument
If the Security Model is Community-based, the only argument available is the
B<-community> argument. This argument expects a string that is to be used as
the SNMP community name. By default the community name is set to 'public'
if the argument is not present.
=item User-based Security Model Arguments
The User-based Security Model (USM) used by SNMPv3 requires that a securityName
be specified using the B<-username> argument. The creation of a Net::SNMP
object with the version set to SNMPv3 will fail if the B<-username> argument
is not present. The B<-username> argument expects a string 1 to 32 octets
in length.
Different levels of security are allowed by the User-based Security Model which
address authentication and privacy concerns. A SNMPv3 Net::SNMP object will
derive the security level (securityLevel) based on which of the following
arguments are specified.
By default a securityLevel of 'noAuthNoPriv' is assumed. If the B<-authkey>
or B<-authpassword> arguments are specified, the securityLevel becomes
'authNoPriv'. The B<-authpassword> argument expects a string which is at
least 1 octet in length. Optionally, the B<-authkey> argument can be used so
that a plain text password does not have to be specified in a script. The
B<-authkey> argument expects a hexadecimal string produced by localizing the
password with the authoritativeEngineID for the specific destination device.
The C<snmpkey> utility included with the distribution can be used to create
the hexadecimal string (see L<snmpkey>).
Two different hash algorithms are defined by SNMPv3 which can be used by the
Security Model for authentication. These algorithms are HMAC-MD5-96 "MD5"
(RFC 1321) and HMAC-SHA-96 "SHA-1" (NIST FIPS PUB 180-1). The default
algorithm used by the module is HMAC-MD5-96. This behavior can be changed by
using the B<-authprotocol> argument. This argument expects either the string
'md5' or 'sha' to be passed to modify the hash algorithm.
By specifying the arguments B<-privkey> or B<-privpassword> the securityLevel
associated with the object becomes 'authPriv'. According to SNMPv3, privacy
requires the use of authentication. Therefore, if either of these two
arguments are present and the B<-authkey> or B<-authpassword> arguments are
missing, the creation of the object fails. The B<-privkey> and
B<-privpassword> arguments expect the same input as the B<-authkey> and
B<-authpassword> arguments respectively.
The User-based Security Model described in RFC 3414 defines a single encryption
protocol to be used for privacy. This protocol, CBC-DES "DES" (NIST FIPS PUB
46-1), is used by default or if the string 'des' is passed to the
B<-privprotocol> argument. The module also supports RFC 3826 which describes
the use of CFB128-AES-128 "AES" (NIST FIPS PUB 197) in the USM. The AES
encryption protocol can be selected by passing 'aes' or 'aes128' to the
B<-privprotocol> argument. By working with the Extended Security Options
Consortium L<http://www.snmp.com/protocol/eso.shtml>, the module also supports
CBC-3DES-EDE "Triple-DES" (NIST FIPS 46-3) in the User-based Security Model.
This is defined in the draft
L<http://www.snmp.com/eso/draft-reeder-snmpv3-usm-3desede-00.txt>. The
Triple-DES encryption protocol can be selected using the B<-privprotocol>
argument with the string '3des' or '3desede'.
=back
=back
=cut
sub session
{
my $class = shift;
my ($this, $error) = $class->new(@_);
if (defined $this) {
if (!defined $this->open()) {
return wantarray ? (undef, $this->error()) : undef;
}
}
return wantarray ? ($this, $error) : $this;
}
sub manager
{
goto &session;
}
=head2 close() - clear the Transport Domain associated with the object
$session->close();
This method clears the Transport Domain and any errors associated with the
object. Once closed, the Net::SNMP object can no longer be used to send or
receive SNMP messages.
=cut
sub close
{
my ($this) = @_;
$this->_error_clear();
$this->{_pdu} = undef;
$this->{_transport} = undef;
return;
}
=head2 snmp_dispatcher() - enter the non-blocking object event loop
$session->snmp_dispatcher();
This method enters the event loop associated with non-blocking Net::SNMP
objects. The method exits when all queued SNMP messages have received a
response or have timed out at the Transport Layer. This method is also
exported as the stand alone function C<snmp_dispatcher()> by default
(see L<"EXPORTS">).
=cut
sub snmp_dispatcher
{
return $DISPATCHER->loop();
}
sub snmp_event_loop
{
require Carp;
Carp::croak('snmp_event_loop() is obsolete, use snmp_dispatcher() instead');
goto &snmp_dispatcher;
}
sub snmp_dispatch_once
{
return $DISPATCHER->one_event();
}
=head2 get_request() - send a SNMP get-request to the remote agent
$result = $session->get_request(
[-callback => sub {},] # non-blocking
[-delay => $seconds,] # non-blocking
[-contextengineid => $engine_id,] # v3
[-contextname => $name,] # v3
-varbindlist => \@oids,
);
This method performs a SNMP get-request query to gather data from the remote
agent on the host associated with the Net::SNMP object. The message is built
using the list of OBJECT IDENTIFIERs in dotted notation passed to the method
as an array reference using the B<-varbindlist> argument. Each OBJECT
IDENTIFIER is placed into a single SNMP GetRequest-PDU in the same order that
it held in the original list.
A reference to a hash is returned in blocking mode which contains the contents
of the VarBindList. In non-blocking mode, a true value is returned when no
error has occurred. In either mode, the undefined value is returned when an
error has occurred. The C<error()> method may be used to determine the cause
of the failure.
=cut
sub get_request
{
my $this = shift;
$this->_error_clear();
my @argv;
if (!defined $this->_prepare_argv([qw( -callback
-delay
-contextengineid
-contextname
-varbindlist )], \@_, \@argv))
{
return $this->_error();
}
if (!defined $this->_create_pdu()) {
return $this->_error();
}
if (!defined $this->{_pdu}->prepare_get_request(@argv)) {
return $this->_error($this->{_pdu}->error());
}
return $this->_send_pdu();
}
=head2 get_next_request() - send a SNMP get-next-request to the remote agent
$result = $session->get_next_request(
[-callback => sub {},] # non-blocking
[-delay => $seconds,] # non-blocking
[-contextengineid => $engine_id,] # v3
[-contextname => $name,] # v3
-varbindlist => \@oids,
);
This method performs a SNMP get-next-request query to gather data from the
remote agent on the host associated with the Net::SNMP object. The message
is built using the list of OBJECT IDENTIFIERs in dotted notation passed to the
method as an array reference using the B<-varbindlist> argument. Each OBJECT
IDENTIFER is placed into a single SNMP GetNextRequest-PDU in the same order
that it held in the original list.
A reference to a hash is returned in blocking mode which contains the contents
of the VarBindList. In non-blocking mode, a true value is returned when no
error has occurred. In either mode, the undefined value is returned when an
error has occurred. The C<error()> method may be used to determine the cause
of the failure.
=cut
sub get_next_request
{
my $this = shift;
$this->_error_clear();
my @argv;
if (!defined $this->_prepare_argv([qw( -callback
-delay
-contextengineid
-contextname
-varbindlist )], \@_, \@argv))
{
return $this->_error();
}
if (!defined $this->_create_pdu()) {
return $this->_error();
}
if (!defined $this->{_pdu}->prepare_get_next_request(@argv)) {
return $this->_error($this->{_pdu}->error());
}
return $this->_send_pdu();
}
=head2 set_request() - send a SNMP set-request to the remote agent
$result = $session->set_request(
[-callback => sub {},] # non-blocking
[-delay => $seconds,] # non-blocking
[-contextengineid => $engine_id,] # v3
[-contextname => $name,] # v3
-varbindlist => \@oid_value,
);
This method is used to modify data on the remote agent that is associated
with the Net::SNMP object using a SNMP set-request. The message is built
using a list of values consisting of groups of an OBJECT IDENTIFIER, an object
type, and the actual value to be set. This list is passed to the method as
an array reference using the B<-varbindlist> argument. The OBJECT IDENTIFIERs
in each trio are to be in dotted notation. The object type is an octet
corresponding to the ASN.1 type of value that is to be set. Each of the
supported ASN.1 types have been defined and are exported by the package by
default (see L<"EXPORTS">).
A reference to a hash is returned in blocking mode which contains the contents
of the VarBindList. In non-blocking mode, a true value is returned when no
error has occurred. In either mode, the undefined value is returned when an
error has occurred. The C<error()> method may be used to determine the cause
of the failure.
=cut
sub set_request
{
my $this = shift;
$this->_error_clear();
my @argv;
if (!defined $this->_prepare_argv([qw( -callback
-delay
-contextengineid
-contextname
-varbindlist )], \@_, \@argv))
{
return $this->_error();
}
if (!defined $this->_create_pdu()) {
return $this->_error();
}
if (!defined $this->{_pdu}->prepare_set_request(@argv)) {
return $this->_error($this->{_pdu}->error());
}
return $this->_send_pdu();
}
=head2 trap() - send a SNMP trap to the remote manager
$result = $session->trap(
[-delay => $seconds,] # non-blocking
[-enterprise => $oid,]
[-agentaddr => $ipaddress,]
[-generictrap => $generic,]
[-specifictrap => $specific,]
[-timestamp => $timeticks,]
-varbindlist => \@oid_value,
);
This method sends a SNMP trap to the remote manager associated with the
Net::SNMP object. All arguments are optional and will be given the following
defaults in the absence of a corresponding named argument:
=over
=item *
The default value for the trap B<-enterprise> is "1.3.6.1.4.1", which
corresponds to "iso.org.dod.internet.private.enterprises". The enterprise
value is expected to be an OBJECT IDENTIFER in dotted notation.
=item *
When the Transport Domain is UDP/IPv4 or TCP/IPv4, the default value for the
trap B<-agentaddr> is the IP address associated with the interface on which
the trap will be transmitted. For other Transport Domains the B<-agentaddr>
is defaulted to "0.0.0.0". When specified, the agent-addr is expected to be
an IpAddress in dotted notation.
=item *
The default value for the B<-generictrap> type is 6 which corresponds to
"enterpriseSpecific". The generic-trap types are defined and can be exported
upon request (see L<"EXPORTS">).
=item *
The default value for the B<-specifictrap> type is 0. No pre-defined values
are available for specific-trap types.
=item *
The default value for the trap B<-timestamp> is the "uptime" of the script.
The "uptime" of the script is the number of hundredths of seconds that have
elapsed since the script began running. The time-stamp is expected to be a
TimeTicks number in hundredths of seconds.
=item *
The default value for the trap B<-varbindlist> is an empty array reference.
The variable-bindings are expected to be in an array format consisting of
groups of an OBJECT IDENTIFIER, an object type, and the actual value of the
object. This is identical to the list expected by the C<set_request()> method.
The OBJECT IDENTIFIERs in each trio are to be in dotted notation. The object
type is an octet corresponding to the ASN.1 type for the value. Each of the
supported types have been defined and are exported by default (see
L<"EXPORTS">).
=back
A true value is returned when the method is successful. The undefined value
is returned when a failure has occurred. The C<error()> method can be used to
determine the cause of the failure. Since there are no acknowledgements for
Trap-PDUs, there is no way to determine if the remote host actually received
the trap.
B<NOTE:> When the object is in non-blocking mode, the trap is not sent until
the event loop is entered and no callback is ever executed.
B<NOTE:> This method can only be used when the version of the object is set to
SNMPv1.
=cut
sub trap
{
my $this = shift;
$this->_error_clear();
my @argv;
if (!defined $this->_prepare_argv([qw( -delay
-enterprise
-agentaddr
-generictrap
-specifictrap
-timestamp
-varbindlist )], \@_, \@argv))
{
return $this->_error();
}
if (!defined $this->_create_pdu()) {
return $this->_error();
}
if (!defined $this->{_pdu}->prepare_trap(@argv)) {
return $this->_error($this->{_pdu}->error());
}
$this->_send_pdu();
return defined($this->{_error}) ? $this->_error() : TRUE;
}
=head2 get_bulk_request() - send a SNMP get-bulk-request to the remote agent
$result = $session->get_bulk_request(
[-callback => sub {},] # non-blocking
[-delay => $seconds,] # non-blocking
[-contextengineid => $engine_id,] # v3
[-contextname => $name,] # v3
[-nonrepeaters => $non_reps,]
[-maxrepetitions => $max_reps,]
-varbindlist => \@oids,
);
This method performs a SNMP get-bulk-request query to gather data from the
remote agent on the host associated with the Net::SNMP object. All arguments
are optional except B<-varbindlist> and will be given the following defaults
in the absence of a corresponding named argument:
=over
=item *
The default value for the get-bulk-request B<-nonrepeaters> is 0. The
non-repeaters value specifies the number of variables in the
variable-bindings list for which a single successor is to be returned.
=item *
The default value for the get-bulk-request B<-maxrepetitions> is 0. The
max-repetitions value specifies the number of successors to be returned for
the remaining variables in the variable-bindings list.
=item *
The B<-varbindlist> argument expects an array reference consisting of a list of
OBJECT IDENTIFIERs in dotted notation. Each OBJECT IDENTIFER is placed into a
single SNMP GetBulkRequest-PDU in the same order that it held in the original
list.
=back
A reference to a hash is returned in blocking mode which contains the contents
of the VarBindList. In non-blocking mode, a true value is returned when no
error has occurred. In either mode, the undefined value is returned when an
error has occurred. The C<error()> method may be used to determine the cause
of the failure.
B<NOTE:> This method can only be used when the version of the object is set to
SNMPv2c or SNMPv3.
=cut
sub get_bulk_request
{
my $this = shift;
$this->_error_clear();
my @argv;
if (!defined $this->_prepare_argv([qw( -callback
-delay
-contextengineid
-contextname
-nonrepeaters
-maxrepetitions
-varbindlist )], \@_, \@argv))
{
return $this->_error();
}
if (!defined $this->_create_pdu()) {
return $this->_error();
}
if (!defined $this->{_pdu}->prepare_get_bulk_request(@argv)) {
return $this->_error($this->{_pdu}->error());
}
return $this->_send_pdu();
}
=head2 inform_request() - send a SNMP inform-request to the remote manager
$result = $session->inform_request(
[-callback => sub {},] # non-blocking
[-delay => $seconds,] # non-blocking
[-contextengineid => $engine_id,] # v3
[-contextname => $name,] # v3
-varbindlist => \@oid_value,
);
This method is used to provide management information to the remote manager
associated with the Net::SNMP object using an inform-request. The message is
built using a list of values consisting of groups of an OBJECT IDENTIFIER,
an object type, and the actual value to be identified. This list is passed
to the method as an array reference using the B<-varbindlist> argument. The
OBJECT IDENTIFIERs in each trio are to be in dotted notation. The object type
is an octet corresponding to the ASN.1 type of value that is to be identified.
Each of the supported ASN.1 types have been defined and are exported by the
package by default (see L<"EXPORTS">).
The first two variable-bindings fields in the inform-request are specified
by SNMPv2 and should be:
=over
=item *
sysUpTime.0 - ('1.3.6.1.2.1.1.3.0', TIMETICKS, $timeticks)
=item *
snmpTrapOID.0 - ('1.3.6.1.6.3.1.1.4.1.0', OBJECT_IDENTIFIER, $oid)
=back
A reference to a hash is returned in blocking mode which contains the contents
of the VarBindList. In non-blocking mode, a true value is returned when no
error has occurred. In either mode, the undefined value is returned when an
error has occurred. The C<error()> method may be used to determine the cause
of the failure.
B<NOTE:> This method can only be used when the version of the object is set to
SNMPv2c or SNMPv3.
=cut
sub inform_request
{
my $this = shift;
$this->_error_clear();
my @argv;
if (!defined $this->_prepare_argv([qw( -callback
-delay
-contextengineid
-contextname
-varbindlist )], \@_, \@argv))
{
return $this->_error();
}
if (!defined $this->_create_pdu()) {
return $this->_error();
}
if (!defined $this->{_pdu}->prepare_inform_request(@argv)) {
return $this->_error($this->{_pdu}->error());
}
return $this->_send_pdu();
}
=head2 snmpv2_trap() - send a SNMP snmpV2-trap to the remote manager
$result = $session->snmpv2_trap(
[-delay => $seconds,] # non-blocking
-varbindlist => \@oid_value,
);
This method sends a snmpV2-trap to the remote manager associated with the
Net::SNMP object. The message is built using a list of values consisting of
groups of an OBJECT IDENTIFIER, an object type, and the actual value to be
identified. This list is passed to the method as an array reference using the
B<-varbindlist> argument. The OBJECT IDENTIFIERs in each trio are to be in
dotted notation. The object type is an octet corresponding to the ASN.1 type
of value that is to be identified. Each of the supported ASN.1 types have
been defined and are exported by the package by default (see L<"EXPORTS">).
The first two variable-bindings fields in the snmpV2-trap are specified by
SNMPv2 and should be:
=over
=item *
sysUpTime.0 - ('1.3.6.1.2.1.1.3.0', TIMETICKS, $timeticks)
=item *
snmpTrapOID.0 - ('1.3.6.1.6.3.1.1.4.1.0', OBJECT_IDENTIFIER, $oid)
=back
A true value is returned when the method is successful. The undefined value
is returned when a failure has occurred. The C<error()> method can be used
to determine the cause of the failure. Since there are no acknowledgements for
SNMPv2-Trap-PDUs, there is no way to determine if the remote host actually
received the snmpV2-trap.
B<NOTE:> When the object is in non-blocking mode, the snmpV2-trap is not sent
until the event loop is entered and no callback is ever executed.
B<NOTE:> This method can only be used when the version of the object is set to
SNMPv2c. SNMPv2-Trap-PDUs are supported by SNMPv3, but require the sender of
the message to be an authoritative SNMP engine which is not currently supported
by the Net::SNMP module.
=cut
sub snmpv2_trap
{
my $this = shift;
$this->_error_clear();
my @argv;
if (!defined $this->_prepare_argv([qw( -delay
-contextengineid
-contextname
-varbindlist )], \@_, \@argv))
{
return $this->_error();
}
if (!defined $this->_create_pdu()) {
return $this->_error();
}
if (!defined $this->{_pdu}->prepare_snmpv2_trap(@argv)) {
return $this->_error($this->{_pdu}->error());
}
$this->_send_pdu();
return defined($this->{_error}) ? $this->_error() : TRUE;
}
=head2 get_table() - retrieve a table from the remote agent
$result = $session->get_table(
[-callback => sub {},] # non-blocking
[-delay => $seconds,] # non-blocking
[-contextengineid => $engine_id,] # v3
[-contextname => $name,] # v3
-baseoid => $oid,
[-maxrepetitions => $max_reps,] # v2c/v3
);
This method performs repeated SNMP get-next-request or get-bulk-request
(when using SNMPv2c or SNMPv3) queries to gather data from the remote agent
on the host associated with the Net::SNMP object. The first message sent
is built using the OBJECT IDENTIFIER in dotted notation passed to the method
by the B<-baseoid> argument. Repeated SNMP requests are issued until the
OBJECT IDENTIFIER in the response is no longer a child of the base OBJECT
IDENTIFIER.
The B<-maxrepetitions> argument can be used to specify the max-repetitions
value that is passed to the get-bulk-requests when using SNMPv2c or SNMPv3.
If this argument is not present, a value is calculated based on the maximum
message size for the Net::SNMP object. If the value is set to 1 or less,
get-next-requests will be used for the queries instead of get-bulk-requests.
A reference to a hash is returned in blocking mode which contains the contents
of the VarBindList. In non-blocking mode, a true value is returned when no
error has occurred. In either mode, the undefined value is returned when an
error has occurred. The C<error()> method may be used to determine the cause
of the failure.
B<WARNING:> Results from this method can become very large if the base
OBJECT IDENTIFIER is close to the root of the SNMP MIB tree.
=cut
sub get_table
{
my $this = shift;
$this->_error_clear();
my @argv;
# Validate the passed arguments. For backwards compatiblity
# see if the first argument is an OBJECT IDENTIFIER and then
# act accordingly.
if ((@_) && ($_[0] =~ m/^\.?\d+(?:\.\d+)* *$/)) {
unshift @_, '-baseoid'; # XXX: Side effects?
}
if (!defined $this->_prepare_argv([qw( -callback
-delay
-contextengineid
-contextname
-baseoid
-maxrepetitions )], \@_, \@argv))
{
return $this->_error();
}
if ($argv[0] !~ m/^\.?\d+(?:\.\d+)* *$/) {
return $this->_error(
'The base OBJECT IDENTIFIER "%s" is expected in dotted decimal ' .
'notation', $argv[0]
);
}
# Create a new PDU.
if (!defined $this->_create_pdu()) {
return $this->_error();
}
# Create table of values that need passed along with the
# callbacks. This just prevents a big argument list.
my $argv = {
base_oid => $argv[0],
callback => $this->{_pdu}->callback(),
max_reps => 5, # Also used as a limit for loop detection.
repeat_cnt => 0,
table => undef,
types => undef,
use_bulk => FALSE
};
# Override the callback now that we have stored it.
$this->{_pdu}->callback(
sub
{
$this->{_pdu} = $_[0];
$this->_error_clear();
if ($this->{_pdu}->error()) {
$this->_error($this->{_pdu}->error());
}
$this->_get_table_cb($argv);
return;
}
);
# Determine if we are going to use get-next-requests or get-bulk-requests
# based on the SNMP version and the -maxrepetitions argument.
if ($this->version() == SNMP_VERSION_1) {
if (defined $argv[1]) {
return $this->_error(
'The max-repetitions argument is not applicable when using SNMPv1'
);
}
} else {
if (!defined $argv[1]) {
$argv->{use_bulk} = TRUE;
$argv->{max_reps} = $this->_msg_size_max_reps();
} elsif ($argv[1] > 1) {
$argv->{use_bulk} = TRUE;
$argv->{max_reps} = $argv[1];
}
}
# Create either a get-next-request or get-bulk-request PDU.
if ($argv->{use_bulk}) {
if (!defined $this->{_pdu}->prepare_get_bulk_request(0,
$argv->{max_reps},
[$argv[0]]))
{
return $this->_error($this->{_pdu}->error());
}
} else {
if (!defined $this->{_pdu}->prepare_get_next_request([$argv[0]])) {
return $this->_error($this->{_pdu}->error());
}
}
return $this->_send_pdu();
}
=head2 get_entries() - retrieve table entries from the remote agent
$result = $session->get_entries(
[-callback => sub {},] # non-blocking
[-delay => $seconds,] # non-blocking
[-contextengineid => $engine_id,] # v3
[-contextname => $name,] # v3
-columns => \@columns,
[-startindex => $start,]
[-endindex => $end,]
[-maxrepetitions => $max_reps,] # v2c/v3
);
This method performs repeated SNMP get-next-request or get-bulk-request
(when using SNMPv2c or SNMPv3) queries to gather data from the remote agent
on the host associated with the Net::SNMP object. Each message specifically
requests data for each OBJECT IDENTIFIER specified in the B<-columns> array.
The OBJECT IDENTIFIERs must correspond to column entries for a conceptual row
in a table. They may however be columns in different tables as long as each
table is indexed the same way. The optional B<-startindex> and B<-endindex>
arguments may be specified to limit the query to specific rows in the table(s).
The B<-startindex> can be specified as a single decimal value or in dotted
notation if the index associated with the entry so requires. If the
B<-startindex> is specified, it will be include as part of the query results.
If no B<-startindex> is specified, the first request message will be sent
without an index. To insure that the B<-startindex> is included, the last
sub-identifier in the index is decremented by one. If the last sub-identifier
has a value of zero, the sub-identifier is removed from the index.
The optional B<-endindex> argument can be specified as a single decimal value
or in dotted notation. If the B<-endindex> is specified, it will be included
as part of the query results. If no B<-endindex> is specified, repeated SNMP
requests are issued until the response no longer returns entries matching
any of the columns specified in the B<-columns> array.
The B<-maxrepetitions> argument can be used to specify the max-repetitions
value that is passed to the get-bulk-requests when using SNMPv2c or SNMPv3.
If this argument is not present, a value is calculated based on the maximum
message size of the object and the number of columns specified in the
B<-columns> array. If the value is set to 1 or less, get-next-requests will
be used for the queries instead of get-bulk-requests.
A reference to a hash is returned in blocking mode which contains the contents
of the VarBindList. In non-blocking mode, a true value is returned when no
error has occurred. In either mode, the undefined value is returned when an
error has occurred. The C<error()> method may be used to determine the cause
of the failure.
=cut
sub get_entries
{
my $this = shift;
$this->_error_clear();
my @argv;
# Validate the passed arguments.
if (!defined $this->_prepare_argv([qw( -callback
-delay
-contextengineid
-contextname
-entryoid
-columns
-startindex
-endindex
-maxrepetitions
-rowcallback )], \@_, \@argv))
{
return $this->_error();
}
if (ref $argv[1] ne 'ARRAY') {
return $this->_error('The columns argument expects an array reference');
}
if (!scalar @{$argv[1]}) {
return $this->_error('An empty columns list was specified');
}
# The syntax of get_entries() changes between release 4.1.0 and
# release 4.1.1. For backwards compatibility, we assume the old
# syntax is being used if the "-entryoid" argument is present
# and we silently convert to the new syntax.
if (defined $argv[0]) {
# XXX: Argument deprecated after v5.2.0, obsolete in 6.0.1.
require Carp;
Carp::croak(
'The entryoid argument is obsolete, use the columns argument ' .
'with a list of column OBJECT IDENTIFIERs'
);
if ($argv[0] !~ m/^\.?\d+(?:\.\d+)* *$/) {
return $this->_error(
'The entryoid value "%s" is expected in dotted decimal notation',
$argv[0]
);
}
my $columns = {};
for (@{$argv[1]}) {
if (!m/^\d+$/) {
return $this->_error(
'The columns list value "%s" is expected in positive numeric ' .
'format', $_
);
}
if (exists $columns->{$_}) {
return $this->_error(
'The columns list value "%s" is duplicated in the columns list',
$_
);
} else {
$columns->{$_} = $_;
}
}
# Now create the new syntax for the columns list.
$argv[1] = [];
for (sort { $a <=> $b } (keys %{$columns})) {
push @{$argv[1]}, join q{.}, $argv[0], $_;
}
}
# Validate the column list.
for (@{$argv[1]}) {
if (!m/^\.?\d+(?:\.\d+)* *$/) {
return $this->_error(
'The columns list OBJECT IDENTIFIER "%s" is expected in dotted ' .
'decimal notation', $_
);
}
}
my $start_index = undef;
if (defined $argv[2]) {
if ($argv[2] !~ m/^\d+(?:\.\d+)*$/) {
return $this->_error(
'The start index "%s" is expected in dotted decimal notation',
$argv[2]
);
}
my @subids = split m/\./, $argv[2];
if ($subids[-1] > 0) {
$subids[-1]--;
} else {
pop @subids;
}
$start_index = (@subids) ? join(q{.}, @subids) : q{};
}
if (defined $argv[3]) {
if ($argv[3] !~ /^\d+(?:\.\d+)*$/) {
return $this->_error(
'The end index "%s" is expected in dotted decimal notation',
$argv[3]
);
}
if (defined $argv[2]) {
if (oid_lex_cmp($argv[2], $argv[3]) > 0) {
return $this->_error(
'The end index cannot be less than the start index'
);
}
}
}
# Undocumented and unsupported "-rowcallback" argument.
if (defined $argv[5]) {
if (ref $argv[5] eq 'CODE') {
$argv[5] = [$argv[5]];
} elsif ((ref($argv[5]) ne 'ARRAY') || (ref($argv[5]->[0]) ne 'CODE')) {
return $this->_error('The syntax of the row callback is invalid');
}
}
# Create a new PDU.
if (!defined $this->_create_pdu()) {
return $this->_error();
}
# Create table of values that need passed along with the
# callbacks. This just prevents a big argument list.
my $argv = {
callback => $this->{_pdu}->callback(),
columns => $argv[1],
end_index => $argv[3],
entries => undef,
last_index => undef,
max_reps => 0,
row_callback => $argv[5],
start_index => $argv[2],
types => undef,
use_bulk => FALSE
};
# Override the callback now that we have stored it.
$this->{_pdu}->callback(
sub
{
$this->{_pdu} = $_[0];
$this->_error_clear();
if ($this->{_pdu}->error()) {
$this->_error($this->{_pdu}->error());
}
$this->_get_entries_cb($argv);
return;
}
);
# Create the varBindList by indexing each column with the start index.
my $vbl =
[
map {
(defined $start_index) ? join q{.}, $_, $start_index : $_
} @{$argv->{columns}}
];
# Determine if we are going to use get-next-requests or get-bulk-requests
# based on the SNMP version and the -maxrepetitions argument.
if ($this->version() == SNMP_VERSION_1) {
if (defined $argv[4]) {
return $this->_error(
'The max-repetitions argument is not applicable when using SNMPv1'
);
}
} else {
if (!defined $argv[4]) {
$argv->{use_bulk} = TRUE;
# Scale the max-repetitions based on the number of columns.
$argv->{max_reps} =
int($this->_msg_size_max_reps() / @{$argv->{columns}}) + 1;
} elsif ($argv[4] > 1) {
$argv->{use_bulk} = TRUE;
$argv->{max_reps} = $argv[4];
}
}
# Create either a get-next-request or get-bulk-request PDU.
if ($argv->{use_bulk}) {
if (!defined $this->{_pdu}->prepare_get_bulk_request(0,
$argv->{max_reps},
$vbl))
{
return $this->_error($this->{_pdu}->error());
}
} else {
if (!defined $this->{_pdu}->prepare_get_next_request($vbl)) {
return $this->_error($this->{_pdu}->error());
}
}
return $this->_send_pdu();
}
=head2 version() - get the SNMP version from the object
$rfc_version = $session->version();
This method returns the current value for the SNMP version associated with
the object. The returned value is the corresponding version number defined by
the RFCs for the protocol version field (i.e. SNMPv1 == 0, SNMPv2c == 1, and
SNMPv3 == 3). The RFC versions are defined as constant by the module and can
be exported by request (see L<"EXPORTS">).
=cut
sub version
{
my ($this) = @_;
return $this->_error('The SNMP version is not modifiable') if (@_ == 2);
return $this->{_version};
}
=head2 error() - get the current error message from the object
$error_message = $session->error();
This method returns a text string explaining the reason for the last error.
An empty string is returned if no error has occurred.
=cut
sub error
{
return $_[0]->{_error} || q{};
}
=head2 hostname() - get the hostname associated with the object
$hostname = $session->hostname();
This method returns the parsed hostname string that is associated with the
object. Any port information and formatting that can be included with the
corresponding C<session()> constructor argument will be stripped and not
included as part of the returned string.
=cut
sub hostname
{
return $_[0]->{_hostname};
}
=head2 error_status() - get the current SNMP error-status from the object
$error_status = $session->error_status();
This method returns the numeric value of the error-status contained in the
last SNMP message received by the object.
=cut
sub error_status
{
return defined($_[0]->{_pdu}) ? $_[0]->{_pdu}->error_status() : 0;
}
=head2 error_index() - get the current SNMP error-index from the object
$error_index = $session->error_index();
This method returns the numeric value of the error-index contained in the
last SNMP message received by the object.
=cut
sub error_index
{
return defined($_[0]->{_pdu}) ? $_[0]->{_pdu}->error_index() : 0;
}
=head2 var_bind_list() - get the hash reference for the VarBindList values
$values = $session->var_bind_list();
This method returns a hash reference created using the ObjectName and the
ObjectSyntax pairs in the VarBindList of the last SNMP message received by
the object. The keys of the hash consist of the OBJECT IDENTIFIERs in dotted
notation corresponding to each ObjectName in the VarBindList. If any of the
OBJECT IDENTIFIERs passed to the request method began with a leading dot, all
of the OBJECT IDENTIFIER hash keys will be prefixed with a leading dot. If
duplicate OBJECT IDENTIFIERs are present in the VarBindList they will be
padded with spaces to make them an unique hash key. The value of each hash
entry is set equal to the value of the corresponding ObjectSyntax. The
undefined value is returned if there has been a failure.
=cut
sub var_bind_list
{
return defined($_[0]->{_pdu}) ? $_[0]->{_pdu}->var_bind_list() : undef;
}
=head2 var_bind_names() - get the array of the ObjectNames in the VarBindList
@names = $session->var_bind_names();
This method returns an array containing the OBJECT IDENTIFIERs corresponding
to the ObjectNames in the VarBindList in the order that they were received
in the last SNMP message. The entries in the array will map directly to the
keys in the hash reference returned by the methods that perform SNMP message
exchanges and by the C<var_bind_list()> and C<var_bind_types()> methods. The
array returned for the convenience methods C<get_table()> and C<get_entries()>
will be in lexicographical order. An empty array is returned if there has been
a failure.
=cut
sub var_bind_names
{
return defined($_[0]->{_pdu}) ? @{$_[0]->{_pdu}->var_bind_names()} : ();
}
=head2 var_bind_types() - get the hash reference for the VarBindList ASN.1 types
$types = $session->var_bind_types();
This method returns a hash reference created using the ObjectName and the ASN.1
type of the ObjectSyntax in the VarBindList of the last SNMP message received
by the object. The keys of the hash consist of the OBJECT IDENTIFIERs in
dotted notation corresponding to each ObjectName in the VarBindList. The
value of each hash entry is set equal to the ASN.1 type of the corresponding
ObjectSyntax. Constants for the supported ASN.1 types have been defined and
are exported by the package by default (see L<"EXPORTS">). The undefined value
is returned if there has been a failure.
=cut
sub var_bind_types
{
return defined($_[0]->{_pdu}) ? $_[0]->{_pdu}->var_bind_types() : undef;
}
=head2 timeout() - set or get the current timeout period for the object
$seconds = $session->timeout([$seconds]);
This method returns the current value for the Transport Layer timeout for
the Net::SNMP object. This value is the number of seconds that the object
will wait for a response from the agent on the remote host. The default
timeout is 5.0 seconds.
If a parameter is specified, the timeout for the object is set to the provided
value if it falls within the range 1.0 to 60.0 seconds. The undefined value
is returned upon an error and the C<error()> method may be used to determine
the cause.
=cut
sub timeout
{
my $this = shift;
if (!defined $this->{_transport}) {
return $this->_error('The session is closed');
}
if (defined (my $timeout = $this->{_transport}->timeout(@_))) {
return $timeout;
}
return $this->_error($this->{_transport}->error());
}
=head2 retries() - set or get the current retry count for the object
$count = $session->retries([$count]);
This method returns the current value for the number of times to retry
sending a SNMP message to the remote host. The default number of retries
is 1.
If a parameter is specified, the number of retries for the object is set to
the provided value if it falls within the range 0 to 20. The undefined value
is returned upon an error and the C<error()> method may be used to determine
the cause.
=cut
sub retries
{
my $this = shift;
if (!defined $this->{_transport}) {
return $this->_error('The session is closed');
}
if (defined (my $retries = $this->{_transport}->retries(@_))) {
return $retries;
}
return $this->_error($this->{_transport}->error());
}
=head2 max_msg_size() - set or get the current maxMsgSize for the object
$octets = $session->max_msg_size([$octets]);
This method returns the current value for the maximum message size
(maxMsgSize) for the Net::SNMP object. This value is the largest message size
in octets that can be prepared or processed by the object. The default
maxMsgSize is 1472 octets for UDP/IPv4, 1452 octets for UDP/IPv6, 1460 octets
for TCP/IPv4, and 1440 octets for TCP/IPv6.
If a parameter is specified, the maxMsgSize is set to the provided
value if it falls within the range 484 to 65535 octets. The undefined
value is returned upon an error and the C<error()> method may be used to
determine the cause.
B<NOTE:> When using SNMPv3, the maxMsgSize is actually contained in the SNMP
message (as msgMaxSize). If the value received from a remote device is less
than the current maxMsgSize, the size is automatically adjusted to be the
lower value.
=cut
sub max_msg_size
{
my $this = shift;
if (!defined $this->{_transport}) {
return $this->_error('The session is closed');
}
if (defined (my $max_size = $this->{_transport}->max_msg_size(@_))) {
return $max_size;
}
return $this->_error($this->{_transport}->error());
}
sub mtu
{
goto &max_msg_size;
}
=head2 translate() - enable or disable the translation mode for the object
$mask = $session->translate([
$mode |
[ # Perl anonymous ARRAY reference
['-all' => $mode0,]
['-octetstring' => $mode1,]
['-null' => $mode2,]
['-timeticks' => $mode3,]
['-opaque' => $mode4,]
['-nosuchobject' => $mode5,]
['-nosuchinstance' => $mode6,]
['-endofmibview' => $mode7,]
['-unsigned' => $mode8]
]
]);
When the object decodes the GetResponse-PDU that is returned in response to
a SNMP message, certain values are translated into a more "human readable"
form. By default the following translations occur:
=over
=item *
OCTET STRINGs and Opaques containing any octet which is not part of the
character set defined as a DisplayString in RFC 2679 are converted into a
hexadecimal representation prefixed with "0x". The control codes NUL(0x00),
BEL(0x07), BS(0x08), HT(0x09), LF(0x0A), VT(0x0b), FF(0x0C), and CR(0x0D)
are part of the character set and will not trigger translation. The sequence
'CR x' for any x other than LF or NUL is illegal and will trigger translation.
=item *
TimeTicks integer values are converted to a time format.
=item *
NULL values return the string "NULL" instead of an empty string.
=item *
noSuchObject exception values return the string "noSuchObject" instead of an
empty string.
=item *
noSuchInstance exception values return the string "noSuchInstance" instead of
an empty string.
=item *
endOfMibView exception values return the string "endOfMibView" instead of an
empty string.
=item *
Counter64, Counter, Gauge, and TimeTick values that have been incorrectly
encoded as signed negative values are returned as unsigned values.
=back
The C<translate()> method can be invoked with two different types of arguments.
If the argument passed is any Perl variable type except an array reference,
the translation mode for all ASN.1 types is set to either enabled or disabled,
depending on the value of the passed parameter. Any value that Perl would
treat as a true value will set the mode to be enabled for all types, while a
false value will disable translation for all types.
A reference to an array can be passed to the C<translate()> method in order to
define the translation mode on a per ASN.1 type basis. The array is expected
to contain a list of named argument pairs for each ASN.1 type that is to
be modified. The arguments in the list are applied in the order that they
are passed in via the array. Arguments at the end of the list supersede
those passed earlier in the list. The argument "-all" can be used to specify
that the mode is to apply to all ASN.1 types. Only the arguments for the
ASN.1 types that are to be modified need to be included in the list.
The C<translate()> method returns a bit mask indicating which ASN.1 types
are to be translated. Definitions of the bit to ASN.1 type mappings can be
exported using the I<:translate> tag (see L<"EXPORTS">). The undefined value
is returned upon an error and the C<error()> method may be used to determine
the cause.
=cut
sub translate
{
my ($this, $mask) = @_;
if (@_ != 2) {
return $this->{_translate};
}
if (ref($mask) ne 'ARRAY') {
# Behave like we did before, do (not) translate everything
$this->_translate_mask($_[1], TRANSLATE_ALL);
} else {
# Allow the user to turn off and on specific translations. An
# array is used so the order of the arguments controls how the
# mask is defined.
my @argv = @{$mask};
my $arg;
while (defined ($arg = shift @argv)) {
if ($arg =~ /^-?all$/i) {
$this->_translate_mask(shift(@argv), TRANSLATE_ALL);
} elsif ($arg =~ /^-?none$/i) {
$this->_translate_mask(!(shift @argv), TRANSLATE_ALL);
} elsif ($arg =~ /^-?octet_?string$/i) {
$this->_translate_mask(shift(@argv), TRANSLATE_OCTET_STRING);
} elsif ($arg =~ /^-?null$/i) {
$this->_translate_mask(shift(@argv), TRANSLATE_NULL);
} elsif ($arg =~ /^-?timeticks$/i) {
$this->_translate_mask(shift(@argv), TRANSLATE_TIMETICKS);
} elsif ($arg =~ /^-?opaque$/i) {
$this->_translate_mask(shift(@argv), TRANSLATE_OPAQUE);
} elsif ($arg =~ /^-?nosuchobject$/i) {
$this->_translate_mask(shift(@argv), TRANSLATE_NOSUCHOBJECT);
} elsif ($arg =~ /^-?nosuchinstance$/i) {
$this->_translate_mask(shift(@argv), TRANSLATE_NOSUCHINSTANCE);
} elsif ($arg =~ /^-?endofmibview$/i) {
$this->_translate_mask(shift(@argv), TRANSLATE_ENDOFMIBVIEW);
} elsif ($arg =~ /^-?unsigned$/i) {
$this->_translate_mask(shift(@argv), TRANSLATE_UNSIGNED);
} else {
return $this->_error(
'The translate argument "%s" is unknown', $arg
);
}
}
}
DEBUG_INFO('translate mask = 0x%02x', $this->{_translate});
return $this->{_translate};
}
=head2 debug() - set or get the debug mode for the module
$mask = $session->debug([$mask]);
This method is used to enable or disable debugging for the Net::SNMP module.
Debugging can be enabled on a per component level as defined by a bit mask
passed to the C<debug()> method. The bit mask is broken up as follows:
=over
=item *
0x02 - Message or PDU encoding and decoding
=item *
0x04 - Transport Layer
=item *
0x08 - Dispatcher
=item *
0x10 - Message Processing
=item *
0x20 - Security
=back
Symbols representing these bit mask values are defined by the module and can
be exported using the I<:debug> tag (see L<"EXPORTS">). If a non-numeric
value is passed to the C<debug()> method, it is evaluated in boolean context.
Debugging for all of the components is then enabled or disabled based on the
resulting truth value.
The current debugging mask is returned by the method. Debugging can also be
enabled using the stand alone function C<snmp_debug()>. This function can be
exported by request (see L<"EXPORTS">).
=cut
sub debug
{
my (undef, $mask) = @_;
if (@_ == 2) {
$DEBUG = ($mask =~ /^\d+$/) ? $mask : ($mask) ? DEBUG_ALL : DEBUG_NONE;
eval { Net::SNMP::Message->debug($DEBUG & DEBUG_MESSAGE); };
eval { Net::SNMP::Transport->debug($DEBUG & DEBUG_TRANSPORT); };
eval { Net::SNMP::Dispatcher->debug($DEBUG & DEBUG_DISPATCHER); };
eval { Net::SNMP::MessageProcessing->debug($DEBUG & DEBUG_PROCESSING); };
eval { Net::SNMP::Security->debug($DEBUG & DEBUG_SECURITY); };
}
return $DEBUG;
}
sub snmp_debug
{
return debug(undef, $_[0]);
}
sub pdu
{
return $_[0]->{_pdu};
}
sub nonblocking
{
return $_[0]->{_nonblocking};
}
sub security
{
return $_[0]->{_security};
}
sub transport
{
return $_[0]->{_transport};
}
=head1 SUBROUTINES
=head2 oid_base_match() - determine if an OID has a specified OID base
$value = oid_base_match($base_oid, $oid);
This function takes two OBJECT IDENTIFIERs in dotted notation and returns a
true value (i.e. 0x1) if the second OBJECT IDENTIFIER is equal to or is a
child of the first OBJECT IDENTIFIER in the SNMP Management Information Base
(MIB). This function can be used in conjunction with the C<get-next-request()>
or C<get-bulk-request()> methods to determine when a OBJECT IDENTIFIER in the
GetResponse-PDU is no longer in the desired MIB tree branch.
=cut
sub oid_base_match
{
my ($base, $oid) = @_;
defined $base || return FALSE;
defined $oid || return FALSE;
$base =~ s/^\.//o;
$oid =~ s/^\.//o;
$base = pack 'N*', split m/\./, $base;
$oid = pack 'N*', split m/\./, $oid;
return (substr($oid, 0, length $base) eq $base) ? TRUE : FALSE;
}
sub oid_context_match
{
require Carp;
Carp::croak(
'oid_context_match() is obsolete, use oid_base_match() instead'
);
goto &oid_base_match;
}
=head2 oid_lex_cmp() - compare two OBJECT IDENTIFIERs lexicographically
$cmp = oid_lex_cmp($oid1, $oid2);
This function takes two OBJECT IDENTIFIERs in dotted notation and returns one
of the values 1, 0, -1 if $oid1 is respectively lexicographically greater,
equal, or less than $oid2.
=cut
sub oid_lex_cmp
{
my ($aa, $bb) = @_;
for ($aa, $bb) {
s/^\.//;
s/ /\.0/g;
$_ = pack 'N*', split m/\./;
}
return $aa cmp $bb;
}
=head2 oid_lex_sort() - sort a list of OBJECT IDENTIFIERs lexicographically
@sorted_oids = oid_lex_sort(@oids);
This function takes a list of OBJECT IDENTIFIERs in dotted notation and returns
the listed sorted in lexicographical order.
=cut
sub oid_lex_sort
{
if (@_ <= 1) {
return @_;
}
return map { $_->[0] }
sort { $a->[1] cmp $b->[1] }
map
{
my $oid = $_;
$oid =~ s/^\.//;
$oid =~ s/ /\.0/g;
[$_, pack 'N*', split m/\./, $oid]
} @_;
}
=head2 snmp_type_ntop() - convert an ASN.1 type to presentation format
$text = snmp_type_ntop($type);
This function takes an ASN.1 type octet and returns a text string suitable for
presentation. Some ASN.1 type definitions map to the same octet value when
encoded. This method cannot distinguish between these multiple mappings and
the most basic type name will be returned.
=cut
sub snmp_type_ntop
{
goto &asn1_itoa;
}
=head2 ticks_to_time() - convert TimeTicks to formatted time
$time = ticks_to_time($timeticks);
This function takes an ASN.1 TimeTicks value and returns a string representing
the time defined by the value. The TimeTicks value is expected to be a
non-negative integer value representing the time in hundredths of a second
since some epoch. The returned string will display the time in days, hours,
and seconds format according to the value of the TimeTicks argument.
=cut
sub ticks_to_time
{
goto &asn1_ticks_to_time;
}
sub DESTROY
{
my ($this) = @_;
# We decrement the object type count when the object goes out of
# existance. We assume that _object_type_validate() was called for
# every creation or else we die.
if ($this->{_nonblocking}) {
if (--$NONBLOCKING < 0) {
die 'FATAL: Invalid non-blocking object count';
}
} else {
if (--$BLOCKING < 0) {
die 'FATAL: Invalid blocking object count';
}
}
}
# [private methods] ----------------------------------------------------------
sub _send_pdu
{
my ($this) = @_;
# Check to see if we are still in the process of discovering the
# authoritative SNMP engine. If we are, queue the PDU if we are
# running in non-blocking mode.
if ($this->{_nonblocking} && !$this->{_security}->discovered()) {
push @{$this->{_discovery_queue}}, [$this->{_pdu}, $this->{_delay}];
return TRUE;
}
# Hand the PDU off to the Dispatcher
$DISPATCHER->send_pdu($this->{_pdu}, $this->{_delay});
# Activate the dispatcher if we are blocking
if (!$this->{_nonblocking}) {
snmp_dispatcher();
}
# Return according to blocking mode
return ($this->{_nonblocking}) ? TRUE : $this->var_bind_list();
}
sub _create_pdu
{
my ($this) = @_;
# Create the new PDU
($this->{_pdu}, $this->{_error}) = Net::SNMP::PDU->new(
-version => $this->{_version},
-security => $this->{_security},
-transport => $this->{_transport},
-translate => $this->{_translate},
-callback => $this->_callback_closure(),
-requestid => $DISPATCHER->msg_handle_alloc(),
defined($this->{_context_engine_id}) ?
(-contextengineid => $this->{_context_engine_id}) : (),
defined($this->{_context_name}) ?
(-contextname => $this->{_context_name}) : (),
);
if (!defined $this->{_pdu}) {
return $this->_error();
}
$this->_error_clear();
# Return the PDU
return $this->{_pdu};
}
{
my $versions = {
'(?:snmp)?v?1', SNMP_VERSION_1,
'(?:snmp)?v?2c?', SNMP_VERSION_2C,
'(?:snmp)?v?3', SNMP_VERSION_3,
};
sub _version
{
my ($this, $version) = @_;
# XXX: The passed $version is updated as a side effect.
# Clear any previous error message.
$this->_error_clear();
if ($version eq q{}) {
return $this->_error('An empty SNMP version was specified');
}
for (keys %{$versions}) {
if ($version =~ m/^$_$/i) {
$_[1] = $this->{_version} = $versions->{$_};
return TRUE;
}
}
return $this->_error('The SNMP version "%s" is unknown', $version);
}
}
{
# Arguments that apply to the object.
my $obj_args = {
-callback => \&_callback, # non-blocking only
-contextengineid => \&_context_engine_id, # v3 only
-contextname => \&_context_name, # v3 only
-delay => \&_delay, # non-blocking only
};
sub _prepare_argv
{
my ($this, $allowed, $named, $unnamed) = @_;
# XXX: Argument $unnamed is updated by reference.
my %argv;
# For backwards compatibility, check to see if the first
# argument is an OBJECT IDENTIFIER in dotted notation. If it
# is, assign it to the -varbindlist argument.
if ((@{$named}) && ($named->[0] =~ m/^\.?\d+(?:\.\d+)* *$/)) {
$argv{-varbindlist} = $named;
} else {
%argv = @{$named};
}
# Go through the passed argument list and see if the argument is
# allowed. If it is, see if it applies to the object and has a
# matching method call or add it the the new argv list to be
# returned by this method.
my %new_args;
for my $key (keys %argv) {
my @match = grep { /^-?\Q$key\E$/i } @{$allowed};
if (@match == 1) {
if (exists $obj_args->{$match[0]}) {
if (!defined $this->${\$obj_args->{$match[0]}}($argv{$key})) {
return $this->_error();
}
} else {
$new_args{$match[0]} = $argv{$key};
}
} else {
return $this->_error('The argument "%s" is unknown', $key);
}
}
# Create a new ordered unnamed argument list based on the allowed
# list passed, ignoring those that applied to the object.
for (@{$allowed}) {
next if exists $obj_args->{$_};
push @{$unnamed}, exists($new_args{$_}) ? $new_args{$_} : undef;
}
return TRUE;
}
}
sub _callback
{
my ($this, $callback) = @_;
# We validate the callback argument and then create an anonymous
# array where the first element is the subroutine reference and
# the second element is an array reference containing arguments
# to pass to the subroutine.
if (!$this->{_nonblocking}) {
return $this->_error(
'The callback argument is not applicable to blocking objects'
);
}
my @argv;
if (!defined $callback) {
$this->{_callback} = undef;
return TRUE;
} elsif ((ref($callback) eq 'ARRAY') && (ref($callback->[0]) eq 'CODE')) {
($callback, @argv) = @{$callback};
} elsif (ref($callback) ne 'CODE') {
return $this->_error('The syntax of the callback is invalid');
}
$this->{_callback} = [$callback, \@argv];
return TRUE;
}
sub _callback_closure
{
my ($this) = @_;
# When a response message is received, the Dispatcher will create
# a new PDU object and assign the callback to that object. The
# callback is then executed passing a reference to the PDU object
# as the first argument. We use a closure to assign that passed
# reference to the Net:SNMP object and then invoke the user defined
# callback.
if (!$this->{_nonblocking} || !defined $this->{_callback}) {
return sub
{
$this->{_pdu} = $_[0];
$this->_error_clear();
if ($this->{_pdu}->error()) {
$this->_error($this->{_pdu}->error());
}
return;
};
}
my ($callback, $argv) = @{$this->{_callback}};
return sub
{
$this->{_pdu} = $_[0];
$this->_error_clear();
if ($this->{_pdu}->error()) {
$this->_error($this->{_pdu}->error());
}
$callback->($this, @{$argv});
return;
};
}
sub _context_engine_id
{
my ($this, $context_engine_id) = @_;
$this->_error_clear();
if ($this->version() != SNMP_VERSION_3) {
return $this->_error(
'The contextEngineID argument is only supported in SNMPv3'
);
}
if (!defined $context_engine_id) {
$this->{_context_engine_id} = undef;
} elsif ($context_engine_id =~ m/^(?:0x)?([A-F0-9]+)$/i) {
my $cei = pack 'H*', length($1) % 2 ? '0'.$1 : $1;
my $len = length $cei;
if ($len < 5 || $len > 32) {
return $this->_error(
'The contextEngineID length of %d is out of range (5..32)', $len
);
}
$this->{_context_engine_id} = $cei;
} else {
return $this->_error(
'The contextEngineID "%s" is expected in hexadecimal format',
$context_engine_id
);
}
return TRUE;
}
sub _context_name
{
my ($this, $context_name) = @_;
$this->_error_clear();
if ($this->version() != SNMP_VERSION_3) {
return $this->_error(
'The contextName argument is only supported in SNMPv3'
);
}
if (!defined $context_name) {
$this->{_context_name} = undef;
} elsif (length($context_name) <= 32) {
$this->{_context_name} = $context_name;
} else {
return $this->_error(
'The contextName length of %d is out of range (0..32)',
length $context_name
);
}
return TRUE;
}
sub _delay
{
my ($this, $delay) = @_;
$this->_error_clear();
if (!$this->{_nonblocking}) {
return $this->_error(
'The delay argument is not applicable to blocking objects'
);
}
if ($delay !~ /^\d+(?:\.\d+)?$/) {
return $this->_error(
'The delay value "%s" is expected in positive numeric format', $delay
);
}
if ($delay < 0 || $delay > 31556926) { # Seconds in a year...
return $this->_error(
'The delay value "%s" is out of range (0..31556926)', $delay
);
}
$this->{_delay} = $delay;
return TRUE;
}
sub _object_type_validate
{
my ($this) = @_;
# Since both non-blocking and blocking objects use the same
# Dispatcher instance, allowing both objects types to exist at
# the same time would cause problems. This method is called
# by the constructor to track the object counts based on the
# non-blocking property and returns an error if the two types
# would exist at the same time.
my $count = ($this->{_nonblocking}) ? ++$NONBLOCKING : ++$BLOCKING;
if ($this->{_nonblocking} && $BLOCKING) {
return $this->_error(
'Cannot create non-blocking objects when blocking objects exist'
);
} elsif (!$this->{_nonblocking} && $NONBLOCKING) {
return $this->_error(
'Cannot create blocking objects when non-blocking objects exist'
);
}
return $count;
}
sub _perform_discovery
{
my ($this) = @_;
return TRUE if ($this->{_security}->discovered());
# RFC 3414 - Section 4: "Discovery... ...may be accomplished by
# generating a Request message with a securityLevel of noAuthNoPriv,
# a msgUserName of zero-length, a msgAuthoritativeEngineID value of
# zero length, and the varBindList left empty."
# Create a new PDU
if (!defined $this->_create_pdu()) {
return $this->_discovery_failed();
}
# Create the callback and assign it to the PDU
$this->{_pdu}->callback(
sub
{
$this->{_pdu} = $_[0];
$this->_error_clear();
if ($this->{_pdu}->error()) {
$this->_error($this->{_pdu}->error() . ' during discovery');
}
$this->_discovery_engine_id_cb();
return;
}
);
# Prepare an empty get-request
if (!defined $this->{_pdu}->prepare_get_request()) {
$this->_error($this->{_pdu}->error());
return $this->_discovery_failed();
}
# Send the PDU
$DISPATCHER->send_pdu($this->{_pdu}, 0);
if (!$this->{_nonblocking}) {
snmp_dispatcher();
}
return ($this->{_error}) ? $this->_error() : TRUE;
}
sub _discovery_engine_id_cb
{
my ($this) = @_;
# "The response to this message will be a Report message containing
# the snmpEngineID of the authoritative SNMP engine... ...with the
# usmStatsUnknownEngineIDs counter in the varBindList." If another
# error is returned, we assume snmpEngineID discovery has failed.
if ($this->{_error} !~ /usmStatsUnknownEngineIDs/) {
return $this->_discovery_failed();
}
# Clear the usmStatsUnknownEngineIDs error
$this->_error_clear();
# If the security model indicates that discovery is complete,
# we send any pending messages and return success. If discovery
# is not complete, we probably need to synchronize with the
# remote authoritative engine.
if ($this->{_security}->discovered()) {
DEBUG_INFO('discovery complete');
return $this->_discovery_complete();
}
# "If authenticated communication is required, then the discovery
# process should also establish time synchronization with the
# authoritative SNMP engine. This may be accomplished by sending
# an authenticated Request message..."
# Create a new PDU
if (!defined $this->_create_pdu()) {
return $this->_discovery_failed();
}
# Create the callback and assign it to the PDU
$this->{_pdu}->callback(
sub
{
$this->{_pdu} = $_[0];
$this->_error_clear();
if ($this->{_pdu}->error()) {
$this->_error($this->{_pdu}->error() . ' during synchronization');
}
$this->_discovery_synchronization_cb();
return;
}
);
# Prepare an empty get-request
if (!defined $this->{_pdu}->prepare_get_request()) {
$this->_error($this->{_pdu}->error());
return $this->_discovery_failed();
}
# Send the PDU
$DISPATCHER->send_pdu($this->{_pdu}, 0);
if (!$this->{_nonblocking}) {
snmp_dispatcher();
}
return ($this->{_error}) ? $this->_error() : TRUE;
}
sub _discovery_synchronization_cb
{
my ($this) = @_;
# "The response... ...will be a Report message containing the up
# to date values of the authoritative SNMP engine's snmpEngineBoots
# and snmpEngineTime... It also contains the usmStatsNotInTimeWindows
# counter in the varBindList..." If another error is returned, we
# assume that the synchronization has failed.
if (($this->{_security}->discovered()) &&
($this->{_error} =~ /usmStatsNotInTimeWindows/))
{
$this->_error_clear();
DEBUG_INFO('discovery and synchronization complete');
return $this->_discovery_complete();
}
# If we received the usmStatsNotInTimeWindows report or no error, but
# we are still not synchronized, provide a generic error message.
if ((!$this->{_error}) || ($this->{_error} =~ /usmStatsNotInTimeWindows/)) {
$this->_error_clear();
$this->_error('Time synchronization failed during discovery');
}
DEBUG_INFO('synchronization failed');
return $this->_discovery_failed();
}
sub _discovery_failed
{
my ($this) = @_;
# The discovery process has failed, clear the current PDU and the
# Transport Domain so no one can use this object to send messages.
$this->{_pdu} = undef;
$this->{_transport} = undef;
# Inform the command generator about the current error.
while (my $q = shift @{$this->{_discovery_queue}}) {
$q->[0]->status_information($this->{_error});
}
return $this->_error();
}
sub _discovery_complete
{
my ($this) = @_;
# Discovery is complete, send any pending messages.
while (my $q = shift @{$this->{_discovery_queue}}) {
$DISPATCHER->send_pdu(@{$q});
}
return ($this->{_error}) ? $this->_error() : TRUE;
}
sub _translate_mask
{
my ($this, $enable, $mask) = @_;
# Define the translate bitmask for the object based on the
# passed truth value and mask.
if ($enable) {
$this->{_translate} |= $mask; # Enable
} else {
$this->{_translate} &= ~$mask; # Disable
}
return $this->{_translate};
}
sub _msg_size_max_reps
{
my ($this) = @_;
# Use the maxMsgSize of the object to produce a max-repetitions
# value. This is an attempt to avoid exceeding the maxMsgSize
# in the responses to get-bulk-requests. The scaling factor
# of 0.017 produces a value of 25 with the default maxMsgSize of
# 1472. This was the old hardcoded value used by get_table().
if (!defined $this->{_transport}) {
return 25;
}
return int $this->{_transport}->max_msg_size() * 0.017;
}
sub _get_table_cb
{
my ($this, $argv) = @_;
# Use get-next-requests or get-bulk-requests until the response is
# not a subtree of the base OBJECT IDENTIFIER. Return the table only
# if there are no errors other than a noSuchName(2) error since the
# table could be at the end of the tree. Also return the table when
# the value of the OID equals endOfMibView(2) when using SNMPv2c.
# Get the current callback.
my $callback = $this->{_pdu}->callback();
# Assign the user callback to the PDU.
$this->{_pdu}->callback($argv->{callback});
my $list = $this->var_bind_list();
my $types = $this->var_bind_types();
my @names = $this->var_bind_names();
my $next = undef;
while (@names) {
$next = shift @names;
# Check to see if we are still in the correct subtree and have
# not received a endOfMibView exception.
if (!oid_base_match($argv->{base_oid}, $next) ||
($types->{$next} == ENDOFMIBVIEW))
{
$next = undef; # End of table.
last;
}
# Add the entry to the table only if it is not already present
# and check to make sure that the remote host does not respond
# incorrectly causing the requests to loop forever.
if (!exists $argv->{table}->{$next}) {
$argv->{table}->{$next} = $list->{$next};
$argv->{types}->{$next} = $types->{$next};
} elsif (++$argv->{repeat_cnt} > $argv->{max_reps}) {
$this->{_pdu}->status_information(
'A loop was detected with the table on the remote host'
);
return;
}
}
# Queue the next request if we are not at the end of the table.
if (defined $next) {
$this->_get_table_entries_request_next($argv, $callback, [$next]);
return;
}
# Clear the PDU error on a noSuchName(2) error status.
if ($this->error_status() == 2) {
$this->{_pdu}->error(undef);
}
# Check for an empty or nonexistent table.
if (!$this->{_pdu}->error() && !defined $argv->{table}) {
$this->{_pdu}->error('The requested table is empty or does not exist');
}
# Copy the table to the var_bind_list.
$this->{_pdu}->var_bind_list($argv->{table}, $argv->{types});
# Notify the command generator to process the results.
$this->{_pdu}->process_response_pdu();
return;
}
sub _get_entries_cb
{
my ($this, $argv) = @_;
# Get the current callback.
my $callback = $this->{_pdu}->callback();
# Assign the user callback to the PDU.
$this->{_pdu}->callback($argv->{callback});
# Iterate through the response OBJECT IDENTIFIERs. The response(s)
# will (should) be grouped in the same order as the columns that
# were requested. We use this assumption to map the response(s) to
# get-next/bulk-requests. When using get-bulk-requests, "holes" in
# the table may cause certain columns to run ahead or behind other
# columns, so we cache all entries and sort it out when processing
# the row.
my $list = $this->var_bind_list();
my $types = $this->var_bind_types();
my @names = $this->var_bind_names();
my $max_index = (defined $argv->{last_index}) ? $argv->{last_index} : '0';
my $last_entry = TRUE;
my $cache = {};
while (@names) {
my @row = ();
my $row_index = undef;
# Match up the responses to the requested columns.
for my $col_num (0 .. $#{$argv->{columns}}) {
my $name = shift @names;
if (!defined $name) {
# Due to transport layer limitations, the response could have
# been truncated, so do not consider this the last entry.
DEBUG_INFO('column number / oid number mismatch');
$last_entry = FALSE;
@row = ();
last;
}
my $column = quotemeta $argv->{columns}->[$col_num];
my $index;
if ($name =~ m/$column\.(\d+(:?\.\d+)*)/) {
# Requested column and response column match up.
$index = $1;
} else {
# The response column does not map to the the request, there
# could be a "hole" or we are out of entries.
DEBUG_INFO('last_entry: column mismatch: %s', $name);
$last_entry = TRUE;
next;
}
DEBUG_INFO('found index [%s]', $index);
# Validate the index of the response.
if ((defined $argv->{start_index}) &&
(oid_lex_cmp($index, $argv->{start_index}) < 0))
{
DEBUG_INFO(
'index [%s] less than start_index [%s]',
$index, $argv->{start_index}
);
if (oid_lex_cmp($index, $max_index) > 0) {
$max_index = $index;
$last_entry = FALSE;
DEBUG_INFO('new max_index [%s]', $max_index);
}
next;
} elsif ((defined $argv->{end_index}) &&
(oid_lex_cmp($index, $argv->{end_index}) > 0))
{
DEBUG_INFO(
'last_entry: index [%s] greater than end_index [%s]',
$index, $argv->{end_index}
);
$last_entry = TRUE;
next;
}
# Cache the current column since it falls into the requested range.
$cache->{$index}->[$col_num] = $name;
# To handle "holes" in the conceptual row, checks need to be made
# so that the lowest index for each group of responses is used.
if (!defined $row_index) {
$row_index = $index;
}
my $index_cmp = oid_lex_cmp($index, $row_index);
if ($index_cmp == 0) {
# The index for this response entry matches, so fill in
# the corresponding row entry.
$row[$col_num] = $name;
} elsif ($index_cmp < 0) {
# The index for this response is less than the current index,
# so we throw out everything and start over.
@row = ();
$row_index = $index;
$row[$col_num] = $name;
DEBUG_INFO('new minimum row_index [%s]', $row_index);
} else {
# There must be a "hole" in the row, do nothing here since this
# entry was cached and will hopefully be taken care of later.
DEBUG_INFO(
'index [%s] greater than current row_index [%s]',
$index, $row_index
);
}
}
# No row information found, continue.
if (!@row || !defined $row_index) {
next;
}
# Now store the results for the conceptual row.
for my $col_num (0 .. $#{$argv->{columns}}) {
# Check for cached values that may have been lost due to "holes".
if (!defined $row[$col_num]) {
if (defined $cache->{$row_index}->[$col_num]) {
DEBUG_INFO('using cache: %s', $cache->{$row_index}->[$col_num]);
$row[$col_num] = $cache->{$row_index}->[$col_num];
} else {
next;
}
}
# Actually store the results.
if (!exists $argv->{entries}->{$row[$col_num]}) {
$last_entry = FALSE;
$argv->{entries}->{$row[$col_num]} = $list->{$row[$col_num]};
$argv->{types}->{$row[$col_num]} = $types->{$row[$col_num]};
} else {
DEBUG_INFO('not adding duplicate: %s', $row[$col_num]);
}
}
# Execute the row callback if it is defined.
$this->_get_entries_exec_row_cb($argv, $row_index, \@row);
# Store the maximum index found to be used for the next request.
if (oid_lex_cmp($row_index, $max_index) > 0) {
$max_index = $row_index;
DEBUG_INFO('new max_index [%s]', $max_index);
}
}
# Make sure we are not stuck (looping) on a single index.
if (defined $argv->{last_index}) {
if (oid_lex_cmp($max_index, $argv->{last_index}) > 0) {
$argv->{last_index} = $max_index;
} elsif ($last_entry == FALSE) {
DEBUG_INFO(
'last_entry: max_index [%s] not greater than last_index [%s])',
$max_index, $argv->{last_index}
);
$last_entry = TRUE;
}
} else {
$argv->{last_index} = $max_index;
}
# If we have not reached the last requested entry, generate another
# get-next/bulk-request message.
if ($last_entry == FALSE) {
my $vbl = [ map { join q{.}, $_, $max_index } @{$argv->{columns}} ];
$this->_get_table_entries_request_next($argv, $callback, $vbl);
return;
}
# Clear the PDU error on a noSuchName(2) error status.
if ($this->error_status() == 2) {
$this->{_pdu}->error(undef);
}
# Check for an empty or nonexistent table.
if (!$this->{_pdu}->error() && !defined $argv->{entries}) {
$this->{_pdu}->error('The requested entries are empty or do not exist');
}
# Copy the table to the var_bind_list.
$this->{_pdu}->var_bind_list($argv->{entries}, $argv->{types});
# Execute the row callback, if there has been an error.
if ($this->{_pdu}->error()) {
$this->_get_entries_exec_row_cb($argv, 0, []);
}
# Notify the command generator to process the results.
$this->{_pdu}->process_response_pdu();
return;
}
sub _get_table_entries_request_next
{
my ($this, $argv, $callback, $vbl) = @_;
# Copy the current PDU for use in error conditions.
my $pdu = $this->{_pdu};
# Create a new PDU.
if (!defined $this->_create_pdu()) {
$pdu->status_information($this->error());
return;
}
# Override the callback with the saved callback.
$this->{_pdu}->callback($callback);
# Use the contextEngineID and contextName from the previous request
# because the values stored in the object could change.
if (defined $pdu->context_engine_id()) {
$this->{_pdu}->context_engine_id($pdu->context_engine_id());
}
if (defined $pdu->context_name()) {
$this->{_pdu}->context_name($pdu->context_name());
}
# Create the appropriate request.
if ($argv->{use_bulk}) {
if (!defined $this->{_pdu}->prepare_get_bulk_request(0,
$argv->{max_reps},
$vbl))
{
$pdu->status_information($this->{_pdu}->error());
return;
}
} else {
if (!defined $this->{_pdu}->prepare_get_next_request($vbl)) {
$pdu->status_information($this->{_pdu}->error());
return;
}
}
# Send the next PDU with no delay.
$DISPATCHER->send_pdu($this->{_pdu}, 0);
return;
}
sub _get_entries_exec_row_cb
{
my ($this, $argv, $index, $row) = @_;
return if !defined $argv->{row_callback};
my ($cb, @argv) = @{$argv->{row_callback}};
# Add the "values" found for each column to the front of the
# callback argument list.
for (my $col_num = $#{$argv->{columns}}; $col_num >= 0; --$col_num) {
if (defined $row->[$col_num]) {
unshift @argv, $argv->{entries}->{$row->[$col_num]};
} else {
unshift @argv, undef;
}
}
# Prepend the index for the conceptual row.
unshift @argv, $index;
return eval { $cb->(@argv); };
}
sub _error
{
my $this = shift;
# If the PDU callback is still defined when an error occurs, it
# needs to be cleared to prevent the closure from holding up the
# reference count of the object that created the closure.
if (defined $this->{_pdu} && defined $this->{_pdu}->callback()) {
$this->{_pdu}->callback(undef);
}
if (!defined $this->{_error}) {
$this->{_error} = (@_ > 1) ? sprintf(shift(@_), @_) : $_[0];
if ($this->debug()) {
printf "error: [%d] %s(): %s\n",
(caller 0)[2], (caller 1)[3], $this->{_error};
}
}
return;
}
sub _error_clear
{
return $_[0]->{_error} = undef;
}
sub require_version
{
my ($this, @argv) = @_;
# Provide our own method for handling x.y.z version checks and the return
# value of VERISON() in older implementations of Perl. V-string versions
# in Perl 5.10.0 are now treated as version objects and handled properly.
if (@argv > 0) {
my $wanted = $argv[0];
if ($wanted =~ /(\d+)\.(\d{1,3})\.(\d{1,3})/) {
$argv[0] = sprintf '%d.%03d%03d', $1, $2, $3;
}
}
my $version = eval
{
sprintf '%d.%03d%03d', unpack 'C*', $this->UNIVERSAL::VERSION(@argv);
};
if ($@) {
local $_ = $@;
s/ at(?:.*)\n//;
require Carp;
Carp::croak($_);
}
return $version;
}
sub DEBUG_INFO
{
return $DEBUG if (!$DEBUG);
return printf
sprintf('debug: [%d] %s(): ', (caller 0)[2], (caller 1)[3]) .
((@_ > 1) ? shift(@_) : '%s') .
"\n",
@_;
}
# [end Net::SNMP code] -------------------------------------------------------
1;
__END__
# [documentation] ------------------------------------------------------------
=head1 EXPORTS
The Net::SNMP module uses the F<Exporter> module to export useful constants
and subroutines. These exportable symbols are defined below and follow the
rules and conventions of the F<Exporter> module (see L<Exporter>).
=over
=item Default
&snmp_dispatcher, INTEGER, INTEGER32, OCTET_STRING, OBJECT_IDENTIFIER,
IPADDRESS, COUNTER, COUNTER32, GAUGE, GAUGE32, UNSIGNED32, TIMETICKS,
OPAQUE, COUNTER64, NOSUCHOBJECT, NOSUCHINSTANCE, ENDOFMIBVIEW
=item Exportable
&snmp_debug, &snmp_dispatcher, &snmp_type_ntop, &oid_base_match, &oid_lex_cmp,
&oid_lex_sort,&ticks_to_time, INTEGER, INTEGER32, OCTET_STRING, NULL,
OBJECT_IDENTIFIER, SEQUENCE, IPADDRESS, COUNTER, COUNTER32, GAUGE, GAUGE32,
UNSIGNED32, TIMETICKS, OPAQUE, COUNTER64, NOSUCHOBJECT, NOSUCHINSTANCE,
ENDOFMIBVIEW, GET_REQUEST, GET_NEXT_REQUEST, GET_RESPONSE, SET_REQUEST, TRAP,
GET_BULK_REQUEST, INFORM_REQUEST, SNMPV2_TRAP, REPORT, DEBUG_ALL, DEBUG_NONE,
DEBUG_MESSAGE, DEBUG_TRANSPORT, DEBUG_DISPATCHER,DEBUG_PROCESSING,
DEBUG_SECURITY, COLD_START, WARM_START, LINK_DOWN, LINK_UP,
AUTHENTICATION_FAILURE, EGP_NEIGHBOR_LOSS, ENTERPRISE_SPECIFIC,
SNMP_VERSION_1, SNMP_VERSION_2C, SNMP_VERSION_3, SNMP_PORT, SNMP_TRAP_PORT,
TRANSLATE_NONE,TRANSLATE_OCTET_STRING, TRANSLATE_NULL, TRANSLATE_TIMETICKS,
TRANSLATE_OPAQUE,TRANSLATE_NOSUCHOBJECT, TRANSLATE_NOSUCHINSTANCE,
TRANSLATE_ENDOFMIBVIEW, TRANSLATE_UNSIGNED, TRANSLATE_ALL
=item Tags
=over
=item :asn1
INTEGER, INTEGER32, OCTET_STRING, NULL, OBJECT_IDENTIFIER, SEQUENCE,
IPADDRESS, COUNTER, COUNTER32, GAUGE, GAUGE32, UNSIGNED32, TIMETICKS, OPAQUE,
COUNTER64, NOSUCHOBJECT, NOSUCHINSTANCE, ENDOFMIBVIEW, GET_REQUEST,
GET_NEXT_REQUEST, GET_RESPONSE, SET_REQUEST, TRAP, GET_BULK_REQUEST,
INFORM_REQUEST, SNMPV2_TRAP, REPORT
=item :debug
&snmp_debug, DEBUG_ALL, DEBUG_NONE, DEBUG_MESSAGE, DEBUG_TRANSPORT,
DEBUG_DISPATCHER, DEBUG_PROCESSING, DEBUG_SECURITY
=item :generictrap
COLD_START, WARM_START, LINK_DOWN, LINK_UP, AUTHENTICATION_FAILURE,
EGP_NEIGHBOR_LOSS, ENTERPRISE_SPECIFIC
=item :snmp
&snmp_debug, &snmp_dispatcher, &snmp_type_ntop, &oid_base_match, &oid_lex_cmp,
&oid_lex_sort, &ticks_to_time, SNMP_VERSION_1, SNMP_VERSION_2C, SNMP_VERSION_3,
SNMP_PORT, SNMP_TRAP_PORT
=item :translate
TRANSLATE_NONE, TRANSLATE_OCTET_STRING, TRANSLATE_NULL, TRANSLATE_TIMETICKS,
TRANSLATE_OPAQUE, TRANSLATE_NOSUCHOBJECT, TRANSLATE_NOSUCHINSTANCE,
TRANSLATE_ENDOFMIBVIEW, TRANSLATE_UNSIGNED, TRANSLATE_ALL
=item :ALL
All of the above exportable items.
=back
=back
=head1 EXAMPLES
=head2 1. Blocking SNMPv1 get-request for sysUpTime
This example gets the sysUpTime from a remote host.
#! /usr/local/bin/perl
use strict;
use warnings;
use Net::SNMP;
my $OID_sysUpTime = '1.3.6.1.2.1.1.3.0';
my ($session, $error) = Net::SNMP->session(
-hostname => shift || 'localhost',
-community => shift || 'public',
);
if (!defined $session) {
printf "ERROR: %s.\n", $error;
exit 1;
}
my $result = $session->get_request(-varbindlist => [ $OID_sysUpTime ],);
if (!defined $result) {
printf "ERROR: %s.\n", $session->error();
$session->close();
exit 1;
}
printf "The sysUpTime for host '%s' is %s.\n",
$session->hostname(), $result->{$OID_sysUpTime};
$session->close();
exit 0;
=head2 2. Blocking SNMPv3 set-request of sysContact
This example sets the sysContact information on the remote host to
"Help Desk x911". The named arguments passed to the C<session()> constructor
are for the demonstration of syntax only. These parameters will need to be
set according to the SNMPv3 parameters of the remote host. The C<snmpkey>
utility included with the distribution can be used to create the key values.
#! /usr/local/bin/perl
use strict;
use warnings;
use Net::SNMP;
my $OID_sysContact = '1.3.6.1.2.1.1.4.0';
my ($session, $error) = Net::SNMP->session(
-hostname => 'myv3host.example.com',
-version => 'snmpv3',
-username => 'myv3Username',
-authprotocol => 'sha1',
-authkey => '0x6695febc9288e36282235fc7151f128497b38f3f',
-privprotocol => 'des',
-privkey => '0x6695febc9288e36282235fc7151f1284',
);
if (!defined $session) {
printf "ERROR: %s.\n", $error;
exit 1;
}
my $result = $session->set_request(
-varbindlist => [ $OID_sysContact, OCTET_STRING, 'Help Desk x911' ],
);
if (!defined $result) {
printf "ERROR: %s.\n", $session->error();
$session->close();
exit 1;
}
printf "The sysContact for host '%s' was set to '%s'.\n",
$session->hostname(), $result->{$OID_sysContact};
$session->close();
exit 0;
=head2 3. Non-blocking SNMPv2c get-bulk-request for ifTable
This example gets the contents of the ifTable by sending get-bulk-requests
until the responses are no longer part of the ifTable. The ifTable can also
be retrieved using the C<get_table()> method. The ifPhysAddress object in
the table has a syntax of an OCTET STRING. By default, translation is enabled
and non-printable OCTET STRINGs are translated into a hexadecimal format.
Sometimes the OCTET STRING contains all printable characters and this produces
unexpected output when it is not translated. The example turns off translation
for OCTET STRINGs and specifically formats the output for the ifPhysAddress
objects.
#! /usr/local/bin/perl
use strict;
use warnings;
use Net::SNMP qw(:snmp);
my $OID_ifTable = '1.3.6.1.2.1.2.2';
my $OID_ifPhysAddress = '1.3.6.1.2.1.2.2.1.6';
my ($session, $error) = Net::SNMP->session(
-hostname => shift || 'localhost',
-community => shift || 'public',
-nonblocking => 1,
-translate => [-octetstring => 0],
-version => 'snmpv2c',
);
if (!defined $session) {
printf "ERROR: %s.\n", $error;
exit 1;
}
my %table; # Hash to store the results
my $result = $session->get_bulk_request(
-varbindlist => [ $OID_ifTable ],
-callback => [ \&table_callback, \%table ],
-maxrepetitions => 10,
);
if (!defined $result) {
printf "ERROR: %s\n", $session->error();
$session->close();
exit 1;
}
# Now initiate the SNMP message exchange.
snmp_dispatcher();
$session->close();
# Print the results, specifically formatting ifPhysAddress.
for my $oid (oid_lex_sort(keys %table)) {
if (!oid_base_match($OID_ifPhysAddress, $oid)) {
printf "%s = %s\n", $oid, $table{$oid};
} else {
printf "%s = %s\n", $oid, unpack 'H*', $table{$oid};
}
}
exit 0;
sub table_callback
{
my ($session, $table) = @_;
my $list = $session->var_bind_list();
if (!defined $list) {
printf "ERROR: %s\n", $session->error();
return;
}
# Loop through each of the OIDs in the response and assign
# the key/value pairs to the reference that was passed with
# the callback. Make sure that we are still in the table
# before assigning the key/values.
my @names = $session->var_bind_names();
my $next = undef;
while (@names) {
$next = shift @names;
if (!oid_base_match($OID_ifTable, $next)) {
return; # Table is done.
}
$table->{$next} = $list->{$next};
}
# Table is not done, send another request, starting at the last
# OBJECT IDENTIFIER in the response. No need to include the
# calback argument, the same callback that was specified for the
# original request will be used.
my $result = $session->get_bulk_request(
-varbindlist => [ $next ],
-maxrepetitions => 10,
);
if (!defined $result) {
printf "ERROR: %s.\n", $session->error();
}
return;
}
=head2 4. Non-blocking SNMPv1 get-request and set-request on multiple hosts
This example first polls several hosts for their sysUpTime. If the poll of
the host is successful, the sysContact and sysLocation information is set on
the host. The sysContact information is hardcoded to "Help Desk x911" while
the sysLocation information is passed as an argument to the callback.
#! /usr/local/bin/perl
use strict;
use warnings;
use Net::SNMP;
my $OID_sysUpTime = '1.3.6.1.2.1.1.3.0';
my $OID_sysContact = '1.3.6.1.2.1.1.4.0';
my $OID_sysLocation = '1.3.6.1.2.1.1.6.0';
# Hash of hosts and location data.
my %host_data = (
'10.1.1.2' => 'Building 1, Second Floor',
'10.2.1.1' => 'Building 2, First Floor',
'localhost' => 'Right here!',
);
# Create a session for each host and queue a get-request for sysUpTime.
for my $host (keys %host_data) {
my ($session, $error) = Net::SNMP->session(
-hostname => $host,
-community => 'private',
-nonblocking => 1,
);
if (!defined $session) {
printf "ERROR: Failed to create session for host '%s': %s.\n",
$host, $error;
next;
}
my $result = $session->get_request(
-varbindlist => [ $OID_sysUpTime ],
-callback => [ \&get_callback, $host_data{$host} ],
);
if (!defined $result) {
printf "ERROR: Failed to queue get request for host '%s': %s.\n",
$session->hostname(), $session->error();
}
}
# Now initiate the SNMP message exchange.
snmp_dispatcher();
exit 0;
sub get_callback
{
my ($session, $location) = @_;
my $result = $session->var_bind_list();
if (!defined $result) {
printf "ERROR: Get request failed for host '%s': %s.\n",
$session->hostname(), $session->error();
return;
}
printf "The sysUpTime for host '%s' is %s.\n",
$session->hostname(), $result->{$OID_sysUpTime};
# Now set the sysContact and sysLocation for the host.
$result = $session->set_request(
-varbindlist =>
[
$OID_sysContact, OCTET_STRING, 'Help Desk x911',
$OID_sysLocation, OCTET_STRING, $location,
],
-callback => \&set_callback,
);
if (!defined $result) {
printf "ERROR: Failed to queue set request for host '%s': %s.\n",
$session->hostname(), $session->error();
}
return;
}
sub set_callback
{
my ($session) = @_;
my $result = $session->var_bind_list();
if (defined $result) {
printf "The sysContact for host '%s' was set to '%s'.\n",
$session->hostname(), $result->{$OID_sysContact};
printf "The sysLocation for host '%s' was set to '%s'.\n",
$session->hostname(), $result->{$OID_sysLocation};
} else {
printf "ERROR: Set request failed for host '%s': %s.\n",
$session->hostname(), $session->error();
}
return;
}
=head1 REQUIREMENTS
=over
=item *
The Net::SNMP module uses syntax that is not supported in versions of Perl
earlier than v5.6.0.
=item *
The non-core modules F<Crypt::DES>, F<Digest::MD5>, and
F<Digest::HMAC> are required to support SNMPv3.
=item *
In order to support the AES Cipher Algorithm as a SNMPv3 privacy protocol, the
non-core module F<Crypt::Rijndael> is needed.
=item *
To use UDP/IPv6 or TCP/IPv6 as a Transport Domain, the non-core module
F<Socket6> is needed.
=back
=head1 AUTHOR
David M. Town E<lt>dtown@cpan.orgE<gt>
=head1 ACKNOWLEDGMENTS
The original concept for this module was based on F<SNMP_Session.pm>
written by Simon Leinen E<lt>simon@switch.chE<gt>.
The Abstract Syntax Notation One (ASN.1) encode and decode methods were
originally derived by example from the CMU SNMP package whose copyright
follows: Copyright (c) 1988, 1989, 1991, 1992 by Carnegie Mellon University.
All rights reserved.
=head1 LICENSE AND COPYRIGHT
Copyright (c) 1998-2010 David M. Town. All rights reserved.
This program is free software; you may redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.
=cut
# ============================================================================
1; # [end Net::SNMP]
|