├── .gitignore ├── LICENSE ├── README ├── netsnmp ├── __init__.py ├── client.py ├── client_intf.c ├── netsnmp-feature-definitions.h └── tests │ ├── __init__.py │ ├── snmpd.conf │ └── test.py └── setup.py /.gitignore: -------------------------------------------------------------------------------- 1 | build/ 2 | dist/ 3 | .*.swp 4 | .*.swo 5 | *.egg-info/ 6 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Various copyrights apply to this package, listed in various separate 2 | parts below. Please make sure that you read all the parts. 3 | 4 | ---- Part 1: Sparta, Inc (BSD) ----- 5 | 6 | Copyright (c) 2003-2010, Sparta, Inc 7 | All rights reserved. 8 | 9 | Redistribution and use in source and binary forms, with or without 10 | modification, are permitted provided that the following conditions are met: 11 | 12 | * Redistributions of source code must retain the above copyright notice, 13 | this list of conditions and the following disclaimer. 14 | 15 | * Redistributions in binary form must reproduce the above copyright 16 | notice, this list of conditions and the following disclaimer in the 17 | documentation and/or other materials provided with the distribution. 18 | 19 | * Neither the name of Sparta, Inc nor the names of its contributors may 20 | be used to endorse or promote products derived from this software 21 | without specific prior written permission. 22 | 23 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS 24 | IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 25 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 26 | PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR 27 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 28 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 29 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 30 | OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 31 | WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 32 | OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 33 | ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34 | 35 | ---- Part 2: ScienceLogic, LLC (BSD) ---- 36 | 37 | Copyright (c) 2006, ScienceLogic, LLC 38 | All rights reserved. 39 | 40 | Redistribution and use in source and binary forms, with or without 41 | modification, are permitted provided that the following conditions are 42 | met: 43 | 44 | * Redistributions of source code must retain the above copyright notice, 45 | this list of conditions and the following disclaimer. 46 | 47 | * Redistributions in binary form must reproduce the above copyright 48 | notice, this list of conditions and the following disclaimer in the 49 | documentation and/or other materials provided with the distribution. 50 | 51 | * Neither the name of ScienceLogic, LLC nor the names of its 52 | contributors may be used to endorse or promote products derived 53 | from this software without specific prior written permission. 54 | 55 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 56 | ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 57 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 58 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 59 | HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 60 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 61 | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 62 | OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 63 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 64 | TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE 65 | USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 66 | DAMAGE. 67 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | The Python 'netsnmp' Extension Module 2 | for the Net-SNMP Library 3 | 4 | Contents: 5 | Introduction: 6 | Availability: 7 | Contact: 8 | Supported Platforms: 9 | Release Notes: 10 | Installation: 11 | Operational Description: 12 | Trouble Shooting: 13 | Acknowledgments: 14 | License/Copyright: 15 | 16 | Introduction: 17 | 18 | This is the Python 'netsnmp' extension module. The 'netsnmp' module 19 | provides a full featured, tri-lingual SNMP (SNMPv3, SNMPv2c, 20 | SNMPv1) client API. The 'netsnmp' module internals rely on the 21 | Net-SNMP toolkit library. For information on the Net-SNMP library 22 | see the documentation provided with the Net-SNMP distribution or 23 | the project web page available on 'Source Forge': 24 | 25 | http://www.net-snmp.org/ 26 | 27 | Availability: 28 | 29 | The most recent release of the Python 'netsnmp' module can be found 30 | bundled with the latest Net-SNMP distribution available from: 31 | 32 | http://www.net-snmp.org/download.html 33 | 34 | Contact: 35 | 36 | The following mailing list should be consider the primary support 37 | mechanism for this module: 38 | 39 | net-snmp-users@lists.sourceforge.net mail list 40 | 41 | (see http://www.net-snmp.org/lists/users/ to subscribe) 42 | 43 | Supported Platforms: 44 | 45 | Linux 2.x 46 | Other UNIX/POSIX variants (untested) 47 | MS Windows (untested) 48 | 49 | Let us know where it *doesn't* work, as it should on most systems 50 | 51 | Release Notes: 52 | 53 | This initial alpha release of the Python 'netsnmp' extension module 54 | has been developed against net-snmp 5.4.pre1. 55 | 56 | Only syncronous, client-side functionality is implemented. 57 | 58 | Access to the parsed MIB database is not yet implemented. 59 | 60 | KNOWN BUGS: 61 | 62 | Too many to mention at this point 63 | 64 | Installation: 65 | 66 | Build and install the Net-SNMP package - see Net-SNMP README and 67 | INSTALL docs. 68 | 69 | Unix: 70 | 71 | cd net-snmp/python 72 | python setup.py build 73 | python setup.py test (requires a locally running agent w/ config provided) 74 | python setup.py install 75 | 76 | 77 | Operational Description: 78 | 79 | The basic operations of the SNMP protocol are provided by this 80 | module through an object oriented interface for modularity and ease 81 | of use. The primary class is netsnmp.Session which encapsulates 82 | the persistent aspects of a connection between the management 83 | application and the managed agent. This class supplies 'get', 84 | 'getnext', 'getbulk', 'set' and other method calls. 85 | 86 | A description of the fields which can be specified when instantiating an 87 | netsnmp.Session follows: 88 | 89 | netsnmp.Session(=, ... ) 90 | 91 | DestHost - default 'localhost', hostname or ip addr of SNMP agent 92 | Version - default '3', [1, 2 (equiv to 2c), 3] 93 | RemotePort - default '161', allow remote UDP port to be overridden 94 | Timeout - default '500000', micro-seconds before retry 95 | Retries - default '3', retries before failure 96 | RetryNoSuch - default '0', if enabled NOSUCH errors in 'get' pdus will 97 | be repaired, removing the varbind in error, and resent - 98 | undef will be returned for all NOSUCH varbinds, when set 99 | to '0' this feature is disabled and the entire get request 100 | will fail on any NOSUCH error (applies to v1 only) 101 | UseLongNames - set to non-zero to have for 'getnext' methods 102 | generated preferring longer Mib name convention (e.g., 103 | system.sysDescr vs just sysDescr) 104 | UseSprintValue - set to non-zero to have return values 105 | for 'get' and 'getnext' methods formatted with the libraries 106 | sprint_value function. This will result in certain data types 107 | being returned in non-canonical format Note: values returned 108 | with this option set may not be appropriate for 'set' 109 | operations (see discussion of value formats in 110 | description section) 111 | UseEnums - set to non-zero to have integer return values 112 | converted to enumeration identifiers if possible, 113 | these values will also be acceptable when supplied to 114 | 'set' operations 115 | UseNumeric - set to non-zero to have returned by the 'get' 116 | methods untranslated (i.e. dotted-decimal). Setting the 117 | UseLongNames value for the session is highly recommended. 118 | BestGuess - this setting controls how are parsed. setting 119 | to 0 causes a regular lookup. setting to 1 causes a regular 120 | expression match (defined as -Ib in snmpcmd). setting to 2 121 | causes a random access lookup (defined as -IR in snmpcmd). 122 | ErrorStr - read-only, holds the error message assoc. w/ last request 123 | ErrorNum - read-only, holds the snmp_err or status of last request 124 | ErrorInd - read-only, holds the snmp_err_index when appropriate 125 | 126 | SNMPv1/SNMPv2c options: 127 | Community - default 'public', SNMP community string (used for both R/W) 128 | 129 | SNMPv3 Options: 130 | SecName - default 'initial', security name (v3) 131 | SecLevel - default 'noAuthNoPriv', security level [noAuthNoPriv, 132 | authNoPriv, authPriv] (v3) 133 | ContextEngineId - default , context engineID, will be 134 | probed if not supplied (v3) 135 | Context - default '', context name (v3) 136 | 137 | SNMPv3 over TLS or DTLS options: 138 | OurIdentity - The fingerprint or file name for the local X.509 139 | certificate to use for our identity. Run 140 | net-snmp-cert to create and manage certificates. 141 | TheirIdentity - The fingerprint or file name for the local X.509 142 | certificate to use for their identity. 143 | TrustCert - A trusted certificate to use for validating 144 | certificates. Typically this would be a CA 145 | certificate. 146 | TheirHostname - Their hostname to expect. Either "TheirIdentity" 147 | or a trusted certificate plus a hostname is needed 148 | to validate the server is the proper server. 149 | 150 | SNMPv3 with USM security Options: 151 | SecEngineId - default , security engineID, will be probed if not 152 | supplied (v3) 153 | AuthProto - default 'MD5', authentication protocol [MD5, SHA] (v3) 154 | AuthPass - default , authentication passphrase 155 | PrivProto - default 'DES', privacy protocol [DES] (v3) 156 | PrivPass - default , privacy passphrase (v3) 157 | 158 | private: 159 | sess_ptr - internal field used to cache a created session structure 160 | 161 | methods: 162 | 163 | get() 164 | - SNMP GET a netsnmp.VarList object must be supplied, 165 | returns a tuple of values for each varbind in list 166 | 167 | getnext() 168 | - SNMP GETNEXT, a netsnmp.VarList object must be supplied 169 | returns retrieved value(s), VarList passed as arguments 170 | are updated to return a list of next lexicographical 171 | Varbind objects. returns a tuple of values for each 172 | varbind in list 173 | 174 | set() 175 | - SNMP SET, a netsnmp.VarList object must be supplied 176 | the value field in all Varbinds must be in a canonical 177 | format (i.e., well known format) to ensure unambiguous 178 | translation to SNMP MIB data value (see discussion of 179 | canonical value format description section), 180 | returns true on success or None on error. 181 | 182 | getbulk(, , ) 183 | - SNMP GETBULK, a netsnmp.VarList object must be supplied 184 | the single next lexico instance is fetched for the first 185 | n Varbinds in the list as defined by . 186 | For the remaining Varbinds, the next m lexico instances 187 | are retrieved each of the remaining Varbinds, 188 | where m is . Returns a tuple of values 189 | retrieved. 190 | 191 | walk() 192 | - Performs multiple GETNEXT requests in order to 193 | return a tuple of values retrieved from the MIB 194 | below the Varbind passed in. The VarList passed 195 | in will be updated to contain a complete set of 196 | Varbinds created for the results of the walk. 197 | 198 | Note that only one varbind should be contained in the 199 | VarList passed in. The code is structured to maybe 200 | handle this is the the future, but right now walking 201 | multiple trees at once is not yet supported and will 202 | produce insufficient results. 203 | 204 | 205 | Acceptable variable formats: 206 | 207 | netsnmp.VarList: - represents an list of Varbind objects to get or set. 208 | takes are arguments and unspecified number of Varbinds, 209 | or tuples which will be converted to Varbinds. 210 | 211 | 212 | netsnmp.Varbind: - represents a single MIB object to get or set 213 | implemented as Python[, , , ]. 214 | - one of the following forms: 215 | 1) leaf identifier (e.g., 'sysDescr') assumed to be 216 | unique for practical purposes 217 | 2) fully qualified identifier (e.g., 218 | '.iso.org.dod.internet.mgmt.mib-2.system.sysDescr') 219 | 3) fully qualified, dotted-decimal, numeric OID 220 | (e.g., '.1.3.6.1.2.1.1.1') 221 | - the dotted-decimal, instance identifier. for 222 | scalar MIB objects use '0' 223 | - the SNMP data value retrieved from or being set 224 | to the agents MIB. for set operations the 225 | format must be canonical to ensure unambiguous 226 | translation. The canonical forms are as follows: 227 | OBJECTID => dotted-decimal (e.g., .1.3.6.1.2.1.1.1) 228 | OCTETSTR => perl scalar containing octets, 229 | INTEGER => decimal signed integer (or enum), 230 | NETADDR => dotted-decimal, 231 | IPADDR => dotted-decimal, 232 | COUNTER => decimal unsigned integer, 233 | COUNTER64 => decimal unsigned integer, 234 | GAUGE, => decimal unsigned integer, 235 | UINTEGER, => decimal unsigned integer, 236 | TICKS, => decimal unsigned integer, 237 | OPAQUE => perl scalar containing octets, 238 | NULL, => perl scalar containing nothing, 239 | 240 | - SNMP data type (see list above), this field is 241 | populated by 'get' and 'getnext' operations. In 242 | some cases the programmer needs to populate this 243 | field when passing to a 'set' operation. this 244 | field need not be supplied when the attribute 245 | indicated by is already described in the 246 | parsed MIB. for 'set's, if a numeric OID is used 247 | and the object is not in the parsed MIB, 248 | the field must be supplied 249 | 250 | 251 | Python 'netsnmp' package variables and functions: 252 | 253 | 254 | netsnmp.verbose - default '0', 255 | controls warning/info output of themodule 256 | 0 => no output, 257 | 1 => enables warning/info 258 | 259 | (needs implementation) 260 | $SNMP::debugging - default '0', controls debugging output level 261 | within SNMP module and libsnmp 262 | 1 => enables 'SNMP::verbose' (see above) 263 | 2 => level 1 plus snmp_set_do_debugging(1), 264 | 3 => level 2 plus snmp_set_dump_packet(1) 265 | 266 | $SNMP::dump_packet - default '0', set [non-]zero to independently set 267 | snmp_set_dump_packet() 268 | 269 | Exported 'netsnmp' package utility functions: 270 | 271 | snmpget(, ) 272 | - takes args of netsnmp.Session preceded by those of the 273 | corresponding netsnmp.Session method. Returns a tuple with 274 | Varbind values fetched, and input is updated to contain 275 | complete Varbinds fetched. 276 | 277 | snmpgetnext(, ) 278 | - takes args of netsnmp.Session preceded by those of the 279 | corresponding netsnmp.Session method. Returns a tuple with 280 | Varbind values fetched, and input is updated to contain 281 | complete Varbinds fetched. 282 | 283 | snmpgetbulk(nonrepeaters, maxrepetitions,, ) 284 | - takes args of netsnmp.Session preceded by those of the 285 | corresponding netsnmp.Session method. Returns a tuple with 286 | Varbind values fetched, and VarList is updated to contain 287 | complete Varbinds fetched. 288 | 289 | snmpset(, ) 290 | - takes args of netsnmp.Session preceded by those of the 291 | corresponding netsnmp.Session method. returns True on success, 292 | otherwise False. 293 | 294 | snmpwalk(, )) 295 | - takes args of netsnmp.Session preceded by a Varbind or 296 | VarList from which the 'walk' operation will start. 297 | Returns a tuple of values retrieved from the MIB below 298 | the Varbind passed in. If a VarList is passed in it 299 | will be updated to contain a complete set of VarBinds 300 | created for the results of the walk. It is not 301 | recommended to pass in just a Varbind since you loose 302 | the ability to examine the returned OIDs. But, if only 303 | a Varbind is passed in it will be returned unaltered. 304 | 305 | Note that only one varbind should be contained in the 306 | VarList passed in. The code is structured to maybe 307 | handle this is the the future, but right now walking 308 | multiple trees at once is not yet supported and will 309 | produce insufficient results. 310 | 311 | Trouble Shooting: 312 | 313 | If problems occur there are number areas to look at to narrow down the 314 | possibilities. 315 | 316 | The first step should be to test the Net-SNMP installation 317 | independently from the Python 'netsnmp' Extension. 318 | 319 | Try running the apps from the Net-SNMP distribution. 320 | 321 | Make sure your agent (snmpd) is running and properly configured with 322 | read-write access for the community you are using. 323 | 324 | Ensure that your MIBs are installed and environment variables are set 325 | appropriately (see man mib_api) 326 | 327 | Be sure to ensure headers and libraries from old CMU installations are 328 | not being used by mistake (see -NET-SNMP-PATH). 329 | 330 | If the problem occurs during compilation/linking check that the snmp 331 | library being linked is actually the Net-SNMP library (there have been 332 | name conflicts with existing snmp libs). 333 | 334 | Also check that the header files are correct and up to date. 335 | 336 | Sometimes compiling the Net-SNMP library with 337 | 'position-independent-code' enabled is required (HPUX specifically). 338 | 339 | If you cannot resolve the problem you can email 340 | net-snmp-users@lists.sourceforge.net. 341 | 342 | Please give sufficient information to analyze the problem (OS type, 343 | versions for OS/python/net-SNMP/compiler, complete error output, etc.) 344 | 345 | Acknowledgments: 346 | 347 | Giovanni Marzot (the original author) 348 | ScienceLogic, LLC sponsored the initial development of this module. 349 | Wes Hardaker and the net-snmp-coders 350 | 351 | Thanks in advance to any who supply patches, suggestions and feedback. 352 | 353 | License: 354 | 355 | Please see the LICENSE file contained with this package 356 | 357 | Copyright: 358 | 359 | Copyright (c) 2006 G. S. Marzot. All rights reserved. 360 | This program is free software; you can redistribute it and/or 361 | modify it under the same terms as Net-SNMP itself. 362 | 363 | Copyright (c) 2006 SPARTA, Inc. All Rights Reserved. This 364 | program is free software; you can redistribute it and/or modify 365 | it under the same terms as Net-SNMP itself. 366 | -------------------------------------------------------------------------------- /netsnmp/__init__.py: -------------------------------------------------------------------------------- 1 | from .client import * 2 | -------------------------------------------------------------------------------- /netsnmp/client.py: -------------------------------------------------------------------------------- 1 | import string 2 | import re 3 | import types 4 | from sys import stderr 5 | from netsnmp import client_intf 6 | 7 | # control verbosity of error output 8 | verbose = 1 9 | 10 | secLevelMap = { 'noAuthNoPriv':1, 'authNoPriv':2, 'authPriv':3 } 11 | 12 | class Error(Exception): 13 | pass 14 | 15 | def _parse_session_args(kargs): 16 | sessArgs = { 17 | 'Version':3, 18 | 'DestHost':'localhost', 19 | 'Community':'public', 20 | 'Timeout':1000000, 21 | 'Retries':3, 22 | 'RemotePort':161, 23 | 'LocalPort':0, 24 | 'SecLevel':'noAuthNoPriv', 25 | 'SecName':'initial', 26 | 'PrivProto':'DEFAULT', 27 | 'PrivPass':'', 28 | 'AuthProto':'DEFAULT', 29 | 'AuthPass':'', 30 | 'ContextEngineId':'', 31 | 'SecEngineId':'', 32 | 'Context':'', 33 | 'Engineboots':0, 34 | 'Enginetime':0, 35 | 'UseNumeric':0, 36 | 'OurIdentity':'', 37 | 'TheirIdentity':'', 38 | 'TheirHostname':'', 39 | 'TrustCert':'' 40 | } 41 | keys = list(kargs.keys()) 42 | for key in keys: 43 | if key in sessArgs: 44 | sessArgs[key] = kargs[key] 45 | else: 46 | print("ERROR: unknown key", key, file=stderr) 47 | return sessArgs 48 | 49 | def STR(obj): 50 | if obj != None: 51 | obj = str(obj) 52 | return obj 53 | 54 | 55 | class Varbind(object): 56 | def __init__(self, tag=None, iid=None, val=None, type=None): 57 | self.tag = STR(tag) 58 | self.iid = STR(iid) 59 | self.val = val 60 | self.type = STR(type) 61 | # parse iid out of tag if needed 62 | if iid == None and tag != None: 63 | regex = re.compile(r'^((?:\.\d+)+|(?:\w+(?:[-:]*\w+)+))\.?(.*)$') 64 | match = regex.match(tag) 65 | if match: 66 | (self.tag, self.iid) = match.group(1,2) 67 | 68 | def __setattr__(self, name, val): 69 | if name == 'val': 70 | self.__dict__[name] = val 71 | else: 72 | self.__dict__[name] = STR(val) 73 | 74 | def print_str(self): 75 | return self.tag, self.iid, self.val, self.type 76 | 77 | 78 | class VarList(object): 79 | def __init__(self, *vs): 80 | self.varbinds = [] 81 | 82 | for var in vs: 83 | if isinstance(var, netsnmp.client.Varbind): 84 | self.varbinds.append(var) 85 | else: 86 | self.varbinds.append(Varbind(var)) 87 | 88 | def __len__(self): 89 | return len(self.varbinds) 90 | 91 | def __getitem__(self, index): 92 | return self.varbinds[index] 93 | 94 | def __setitem__(self, index, val): 95 | if isinstance(val, netsnmp.client.Varbind): 96 | self.varbinds[index] = val 97 | else: 98 | raise TypeError 99 | 100 | def __iter__(self): 101 | return iter(self.varbinds) 102 | 103 | def __delitem__(self, index): 104 | del self.varbinds[index] 105 | 106 | def __repr__(self): 107 | return repr(self.varbinds) 108 | 109 | def __getslice__(self, i, j): 110 | return self.varbinds[i:j] 111 | 112 | def append(self, *vars): 113 | for var in vars: 114 | if isinstance(var, netsnmp.client.Varbind): 115 | self.varbinds.append(var) 116 | else: 117 | raise TypeError 118 | 119 | 120 | 121 | class Session(object): 122 | def __init__(self, **args): 123 | self.sess_ptr = None 124 | self.UseLongNames = 0 125 | self.UseNumeric = 0 126 | self.UseSprintValue = 0 127 | self.UseEnums = 0 128 | self.BestGuess = 0 129 | self.RetryNoSuch = 0 130 | self.ErrorStr = '' 131 | self.ErrorNum = 0 132 | self.ErrorInd = 0 133 | 134 | sess_args = _parse_session_args(args) 135 | 136 | for k,v in list(sess_args.items()): 137 | self.__dict__[k] = v 138 | 139 | 140 | # check for transports that may be tunneled 141 | transportCheck = re.compile('^(tls|dtls|ssh)'); 142 | match = transportCheck.match(sess_args['DestHost']) 143 | 144 | err = None 145 | 146 | try: 147 | if match: 148 | self.sess_ptr = client_intf.session_tunneled( 149 | sess_args['Version'], 150 | sess_args['DestHost'], 151 | sess_args['LocalPort'], 152 | sess_args['Retries'], 153 | sess_args['Timeout'], 154 | sess_args['SecName'], 155 | secLevelMap[sess_args['SecLevel']], 156 | sess_args['ContextEngineId'], 157 | sess_args['Context'], 158 | sess_args['OurIdentity'], 159 | sess_args['TheirIdentity'], 160 | sess_args['TheirHostname'], 161 | sess_args['TrustCert'], 162 | ); 163 | elif sess_args['Version'] == 3: 164 | self.sess_ptr = client_intf.session_v3( 165 | sess_args['Version'], 166 | sess_args['DestHost'], 167 | sess_args['LocalPort'], 168 | sess_args['Retries'], 169 | sess_args['Timeout'], 170 | sess_args['SecName'], 171 | secLevelMap[sess_args['SecLevel']], 172 | sess_args['SecEngineId'], 173 | sess_args['ContextEngineId'], 174 | sess_args['Context'], 175 | sess_args['AuthProto'], 176 | sess_args['AuthPass'], 177 | sess_args['PrivProto'], 178 | sess_args['PrivPass'], 179 | sess_args['Engineboots'], 180 | sess_args['Enginetime']) 181 | else: 182 | self.sess_ptr = client_intf.session( 183 | sess_args['Version'], 184 | sess_args['Community'], 185 | sess_args['DestHost'], 186 | sess_args['LocalPort'], 187 | sess_args['Retries'], 188 | sess_args['Timeout']) 189 | except client_intf.Error as e: 190 | err = e.args[0].strip() 191 | if err[0] == '(' and err[-1] == ')': 192 | err = err[1:-1] 193 | 194 | # Re-wrap the error into a pure Python class to allow it to be pickled 195 | # and other things. To not have the original exception attached, save 196 | # only the string value of the exception. 197 | if err: 198 | raise Error(err) 199 | 200 | def get(self, varlist): 201 | res = client_intf.get(self, varlist) 202 | return res 203 | 204 | def set(self, varlist): 205 | res = client_intf.set(self, varlist) 206 | return res 207 | 208 | def getnext(self, varlist): 209 | res = client_intf.getnext(self, varlist) 210 | return res 211 | 212 | def getbulk(self, nonrepeaters, maxrepetitions, varlist): 213 | if self.Version == 1: 214 | return None 215 | res = client_intf.getbulk(self, nonrepeaters, maxrepetitions, varlist) 216 | return res 217 | 218 | def walk(self, varlist): 219 | res = client_intf.walk(self, varlist) 220 | return res 221 | 222 | def __del__(self): 223 | res = client_intf.delete_session(self) 224 | return res 225 | 226 | import netsnmp 227 | 228 | def snmpget(*args, **kargs): 229 | sess = Session(**kargs) 230 | var_list = VarList() 231 | for arg in args: 232 | if isinstance(arg, netsnmp.client.Varbind): 233 | var_list.append(arg) 234 | else: 235 | var_list.append(Varbind(arg)) 236 | res = sess.get(var_list) 237 | return res 238 | 239 | def snmpset(*args, **kargs): 240 | sess = Session(**kargs) 241 | var_list = VarList() 242 | for arg in args: 243 | if isinstance(arg, netsnmp.client.Varbind): 244 | var_list.append(arg) 245 | else: 246 | var_list.append(Varbind(arg)) 247 | res = sess.set(var_list) 248 | return res 249 | 250 | def snmpgetnext(*args, **kargs): 251 | sess = Session(**kargs) 252 | var_list = VarList() 253 | for arg in args: 254 | if isinstance(arg, netsnmp.client.Varbind): 255 | var_list.append(arg) 256 | else: 257 | var_list.append(Varbind(arg)) 258 | res = sess.getnext(var_list) 259 | return res 260 | 261 | def snmpgetbulk(nonrepeaters, maxrepetitions,*args, **kargs): 262 | sess = Session(**kargs) 263 | var_list = VarList() 264 | for arg in args: 265 | if isinstance(arg, netsnmp.client.Varbind): 266 | var_list.append(arg) 267 | else: 268 | var_list.append(Varbind(arg)) 269 | res = sess.getbulk(nonrepeaters, maxrepetitions, var_list) 270 | return res 271 | 272 | def snmpwalk(*args, **kargs): 273 | sess = Session(**kargs) 274 | if isinstance(args[0], netsnmp.client.VarList): 275 | var_list = args[0] 276 | else: 277 | var_list = VarList() 278 | for arg in args: 279 | if isinstance(arg, netsnmp.client.Varbind): 280 | var_list.append(arg) 281 | else: 282 | var_list.append(Varbind(arg)) 283 | res = sess.walk(var_list) 284 | return res 285 | 286 | -------------------------------------------------------------------------------- /netsnmp/client_intf.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #ifdef I_SYS_TIME 11 | #include 12 | #endif 13 | #include 14 | #include 15 | 16 | #ifdef HAVE_REGEX_H 17 | #include 18 | #endif 19 | 20 | #define SUCCESS 1 21 | #define FAILURE 0 22 | 23 | #define VARBIND_TAG_F 0 24 | #define VARBIND_IID_F 1 25 | #define VARBIND_VAL_F 2 26 | #define VARBIND_TYPE_F 3 27 | 28 | #define TYPE_UNKNOWN 0 29 | #define MAX_TYPE_NAME_LEN 32 30 | #define STR_BUF_SIZE (MAX_TYPE_NAME_LEN * MAX_OID_LEN) 31 | #define ENG_ID_BUF_SIZE 32 32 | 33 | #define NO_RETRY_NOSUCH 0 34 | 35 | /* these should be part of transform_oids.h ? */ 36 | #define USM_AUTH_PROTO_MD5_LEN 10 37 | #define USM_AUTH_PROTO_SHA_LEN 10 38 | #define USM_PRIV_PROTO_DES_LEN 10 39 | 40 | #define STRLEN(x) (x ? strlen(x) : 0) 41 | 42 | /* from perl/SNMP/perlsnmp.h: */ 43 | #ifndef timeradd 44 | #define timeradd(a, b, result) \ 45 | do { \ 46 | (result)->tv_sec = (a)->tv_sec + (b)->tv_sec; \ 47 | (result)->tv_usec = (a)->tv_usec + (b)->tv_usec; \ 48 | if ((result)->tv_usec >= 1000000) \ 49 | { \ 50 | ++(result)->tv_sec; \ 51 | (result)->tv_usec -= 1000000; \ 52 | } \ 53 | } while (0) 54 | #endif 55 | 56 | #ifndef timersub 57 | #define timersub(a, b, result) \ 58 | do { \ 59 | (result)->tv_sec = (a)->tv_sec - (b)->tv_sec; \ 60 | (result)->tv_usec = (a)->tv_usec - (b)->tv_usec; \ 61 | if ((result)->tv_usec < 0) { \ 62 | --(result)->tv_sec; \ 63 | (result)->tv_usec += 1000000; \ 64 | } \ 65 | } while (0) 66 | #endif 67 | 68 | typedef netsnmp_session SnmpSession; 69 | typedef struct tree SnmpMibNode; 70 | 71 | struct module_state { 72 | PyObject *error; 73 | }; 74 | 75 | static int __is_numeric_oid (char*); 76 | static int __is_leaf (struct tree*); 77 | static int __translate_appl_type (char*); 78 | static int __translate_asn_type (int); 79 | static int __snprint_value (char *, size_t, 80 | netsnmp_variable_list*, struct tree *, 81 | int, int); 82 | static int __sprint_num_objid (char *, oid *, int); 83 | static int __scan_num_objid (char *, oid *, size_t *); 84 | static int __get_type_str (int, char *); 85 | static int __get_label_iid (char *, char **, char **, int); 86 | static struct tree * __tag2oid (char *, char *, oid *, int *, int *, int); 87 | static int __concat_oid_str (oid *, int *, char *); 88 | static int __add_var_val_str (netsnmp_pdu *, oid *, int, char *, 89 | int, int); 90 | #define USE_NUMERIC_OIDS 0x08 91 | #define NON_LEAF_NAME 0x04 92 | #define USE_LONG_NAMES 0x02 93 | #define FAIL_ON_NULL_IID 0x01 94 | #define NO_FLAGS 0x00 95 | 96 | 97 | /* Wrapper around fprintf(stderr, ...) for clean and easy debug output. */ 98 | static int _debug_level = 0; 99 | #ifdef DEBUGGING 100 | #define DBPRT(severity, otherargs) \ 101 | do { \ 102 | if (_debug_level && severity <= _debug_level) { \ 103 | (void)printf(otherargs); \ 104 | } \ 105 | } while (/*CONSTCOND*/0) 106 | #else /* DEBUGGING */ 107 | #define DBPRT(severity, otherargs) /* Ignore */ 108 | #endif /* DEBUGGING */ 109 | 110 | #define SAFE_FREE(x) do {if (x != NULL) free(x);} while(/*CONSTCOND*/0) 111 | 112 | void 113 | __libraries_init(char *appname) 114 | { 115 | static int have_inited = 0; 116 | 117 | if (have_inited) 118 | return; 119 | have_inited = 1; 120 | 121 | snmp_set_quick_print(1); 122 | snmp_enable_stderrlog(); 123 | init_snmp(appname); 124 | 125 | netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_DONT_BREAKDOWN_OIDS, 1); 126 | netsnmp_ds_set_int(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_PRINT_SUFFIX_ONLY, 1); 127 | netsnmp_ds_set_int(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_OID_OUTPUT_FORMAT, 128 | NETSNMP_OID_OUTPUT_SUFFIX); 129 | } 130 | 131 | static int 132 | __is_numeric_oid (oidstr) 133 | char* oidstr; 134 | { 135 | if (!oidstr) return 0; 136 | for (; *oidstr; oidstr++) { 137 | if (isalpha((int)*oidstr)) return 0; 138 | } 139 | return(1); 140 | } 141 | 142 | static int 143 | __is_leaf (tp) 144 | struct tree* tp; 145 | { 146 | char buf[MAX_TYPE_NAME_LEN]; 147 | return (tp && (__get_type_str(tp->type,buf) || 148 | (tp->parent && __get_type_str(tp->parent->type,buf) ))); 149 | } 150 | 151 | static int 152 | __translate_appl_type(typestr) 153 | char* typestr; 154 | { 155 | if (typestr == NULL || *typestr == '\0') return TYPE_UNKNOWN; 156 | 157 | if (!strncasecmp(typestr,"INTEGER32",8)) 158 | return(TYPE_INTEGER32); 159 | if (!strncasecmp(typestr,"INTEGER",3)) 160 | return(TYPE_INTEGER); 161 | if (!strncasecmp(typestr,"UNSIGNED32",3)) 162 | return(TYPE_UNSIGNED32); 163 | if (!strcasecmp(typestr,"COUNTER")) /* check all in case counter64 */ 164 | return(TYPE_COUNTER); 165 | if (!strncasecmp(typestr,"GAUGE",3)) 166 | return(TYPE_GAUGE); 167 | if (!strncasecmp(typestr,"IPADDR",3)) 168 | return(TYPE_IPADDR); 169 | if (!strncasecmp(typestr,"OCTETSTR",3)) 170 | return(TYPE_OCTETSTR); 171 | if (!strncasecmp(typestr,"TICKS",3)) 172 | return(TYPE_TIMETICKS); 173 | if (!strncasecmp(typestr,"OPAQUE",3)) 174 | return(TYPE_OPAQUE); 175 | if (!strncasecmp(typestr,"OBJECTID",3)) 176 | return(TYPE_OBJID); 177 | if (!strncasecmp(typestr,"NETADDR",3)) 178 | return(TYPE_NETADDR); 179 | if (!strncasecmp(typestr,"COUNTER64",3)) 180 | return(TYPE_COUNTER64); 181 | if (!strncasecmp(typestr,"NULL",3)) 182 | return(TYPE_NULL); 183 | if (!strncasecmp(typestr,"BITS",3)) 184 | return(TYPE_BITSTRING); 185 | if (!strncasecmp(typestr,"ENDOFMIBVIEW",3)) 186 | return(SNMP_ENDOFMIBVIEW); 187 | if (!strncasecmp(typestr,"NOSUCHOBJECT",7)) 188 | return(SNMP_NOSUCHOBJECT); 189 | if (!strncasecmp(typestr,"NOSUCHINSTANCE",7)) 190 | return(SNMP_NOSUCHINSTANCE); 191 | if (!strncasecmp(typestr,"UINTEGER",3)) 192 | return(TYPE_UINTEGER); /* historic - should not show up */ 193 | /* but it does? */ 194 | if (!strncasecmp(typestr, "NOTIF", 3)) 195 | return(TYPE_NOTIFTYPE); 196 | if (!strncasecmp(typestr, "TRAP", 4)) 197 | return(TYPE_TRAPTYPE); 198 | return(TYPE_UNKNOWN); 199 | } 200 | 201 | static int 202 | __translate_asn_type(type) 203 | int type; 204 | { 205 | switch (type) { 206 | case ASN_INTEGER: 207 | return(TYPE_INTEGER); 208 | case ASN_OCTET_STR: 209 | return(TYPE_OCTETSTR); 210 | case ASN_OPAQUE: 211 | return(TYPE_OPAQUE); 212 | case ASN_OBJECT_ID: 213 | return(TYPE_OBJID); 214 | case ASN_TIMETICKS: 215 | return(TYPE_TIMETICKS); 216 | case ASN_GAUGE: 217 | return(TYPE_GAUGE); 218 | case ASN_COUNTER: 219 | return(TYPE_COUNTER); 220 | case ASN_IPADDRESS: 221 | return(TYPE_IPADDR); 222 | case ASN_BIT_STR: 223 | return(TYPE_BITSTRING); 224 | case ASN_NULL: 225 | return(TYPE_NULL); 226 | /* no translation for these exception type values */ 227 | case SNMP_ENDOFMIBVIEW: 228 | case SNMP_NOSUCHOBJECT: 229 | case SNMP_NOSUCHINSTANCE: 230 | return(type); 231 | case ASN_UINTEGER: 232 | return(TYPE_UINTEGER); 233 | case ASN_COUNTER64: 234 | return(TYPE_COUNTER64); 235 | default: 236 | fprintf(stderr, "translate_asn_type: unhandled asn type (%d)\n",type); 237 | return(TYPE_OTHER); 238 | } 239 | } 240 | 241 | #define USE_BASIC 0 242 | #define USE_ENUMS 1 243 | #define USE_SPRINT_VALUE 2 244 | static int 245 | __snprint_value (buf, buf_len, var, tp, type, flag) 246 | char * buf; 247 | size_t buf_len; 248 | netsnmp_variable_list * var; 249 | struct tree * tp; 250 | int type; 251 | int flag; 252 | { 253 | int len = 0; 254 | u_char* ip; 255 | struct enum_list *ep; 256 | 257 | 258 | buf[0] = '\0'; 259 | if (flag == USE_SPRINT_VALUE) { 260 | snprint_value(buf, buf_len, var->name, var->name_length, var); 261 | len = STRLEN(buf); 262 | } else { 263 | switch (var->type) { 264 | case ASN_INTEGER: 265 | if (flag == USE_ENUMS) { 266 | for(ep = tp->enums; ep; ep = ep->next) { 267 | if (ep->value == *var->val.integer) { 268 | strlcpy(buf, ep->label, buf_len); 269 | len = STRLEN(buf); 270 | break; 271 | } 272 | } 273 | } 274 | if (!len) { 275 | snprintf(buf, buf_len, "%ld", *var->val.integer); 276 | len = STRLEN(buf); 277 | } 278 | break; 279 | 280 | case ASN_GAUGE: 281 | case ASN_COUNTER: 282 | case ASN_TIMETICKS: 283 | case ASN_UINTEGER: 284 | snprintf(buf, buf_len, "%lu", (unsigned long) *var->val.integer); 285 | len = STRLEN(buf); 286 | break; 287 | 288 | case ASN_OCTET_STR: 289 | case ASN_OPAQUE: 290 | len = var->val_len; 291 | if (len > buf_len) 292 | len = buf_len; 293 | memcpy(buf, (char*)var->val.string, len); 294 | break; 295 | 296 | case ASN_IPADDRESS: 297 | ip = (u_char*)var->val.string; 298 | snprintf(buf, buf_len, "%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]); 299 | len = STRLEN(buf); 300 | break; 301 | 302 | case ASN_NULL: 303 | break; 304 | 305 | case ASN_OBJECT_ID: 306 | __sprint_num_objid(buf, (oid *)(var->val.objid), 307 | var->val_len/sizeof(oid)); 308 | len = STRLEN(buf); 309 | break; 310 | 311 | case SNMP_ENDOFMIBVIEW: 312 | snprintf(buf, buf_len, "%s", "ENDOFMIBVIEW"); 313 | break; 314 | case SNMP_NOSUCHOBJECT: 315 | snprintf(buf, buf_len, "%s", "NOSUCHOBJECT"); 316 | break; 317 | case SNMP_NOSUCHINSTANCE: 318 | snprintf(buf, buf_len, "%s", "NOSUCHINSTANCE"); 319 | break; 320 | 321 | case ASN_COUNTER64: 322 | #ifdef OPAQUE_SPECIAL_TYPES 323 | case ASN_OPAQUE_COUNTER64: 324 | case ASN_OPAQUE_U64: 325 | #endif 326 | printU64(buf,(struct counter64 *)var->val.counter64); 327 | len = STRLEN(buf); 328 | break; 329 | 330 | #ifdef OPAQUE_SPECIAL_TYPES 331 | case ASN_OPAQUE_I64: 332 | printI64(buf,(struct counter64 *)var->val.counter64); 333 | len = STRLEN(buf); 334 | break; 335 | #endif 336 | 337 | case ASN_BIT_STR: 338 | snprint_bitstring(buf, buf_len, var, NULL, NULL, NULL); 339 | len = STRLEN(buf); 340 | break; 341 | #ifdef OPAQUE_SPECIAL_TYPES 342 | case ASN_OPAQUE_FLOAT: 343 | if (var->val.floatVal) 344 | snprintf(buf, buf_len, "%f", *var->val.floatVal); 345 | break; 346 | 347 | case ASN_OPAQUE_DOUBLE: 348 | if (var->val.doubleVal) 349 | snprintf(buf, buf_len, "%f", *var->val.doubleVal); 350 | break; 351 | #endif 352 | 353 | case ASN_NSAP: 354 | default: 355 | fprintf(stderr,"snprint_value: asn type not handled %d\n",var->type); 356 | } 357 | } 358 | return(len); 359 | } 360 | 361 | static int 362 | __sprint_num_objid (buf, objid, len) 363 | char *buf; 364 | oid *objid; 365 | int len; 366 | { 367 | int i; 368 | buf[0] = '\0'; 369 | for (i=0; i < len; i++) { 370 | sprintf(buf,".%lu",*objid++); 371 | buf += STRLEN(buf); 372 | } 373 | return SUCCESS; 374 | } 375 | 376 | static int 377 | __scan_num_objid (buf, objid, len) 378 | char *buf; 379 | oid *objid; 380 | size_t *len; 381 | { 382 | char *cp; 383 | *len = 0; 384 | if (*buf == '.') buf++; 385 | cp = buf; 386 | while (*buf) { 387 | if (*buf++ == '.') { 388 | sscanf(cp, "%lu", objid++); 389 | /* *objid++ = atoi(cp); */ 390 | (*len)++; 391 | cp = buf; 392 | } else { 393 | if (isalpha((int)*buf)) { 394 | return FAILURE; 395 | } 396 | } 397 | } 398 | sscanf(cp, "%lu", objid++); 399 | /* *objid++ = atoi(cp); */ 400 | (*len)++; 401 | return SUCCESS; 402 | } 403 | 404 | static int 405 | __get_type_str (type, str) 406 | int type; 407 | char * str; 408 | { 409 | switch (type) { 410 | case TYPE_OBJID: 411 | strcpy(str, "OBJECTID"); 412 | break; 413 | case TYPE_OCTETSTR: 414 | strcpy(str, "OCTETSTR"); 415 | break; 416 | case TYPE_INTEGER: 417 | strcpy(str, "INTEGER"); 418 | break; 419 | case TYPE_INTEGER32: 420 | strcpy(str, "INTEGER32"); 421 | break; 422 | case TYPE_UNSIGNED32: 423 | strcpy(str, "UNSIGNED32"); 424 | break; 425 | case TYPE_NETADDR: 426 | strcpy(str, "NETADDR"); 427 | break; 428 | case TYPE_IPADDR: 429 | strcpy(str, "IPADDR"); 430 | break; 431 | case TYPE_COUNTER: 432 | strcpy(str, "COUNTER"); 433 | break; 434 | case TYPE_GAUGE: 435 | strcpy(str, "GAUGE"); 436 | break; 437 | case TYPE_TIMETICKS: 438 | strcpy(str, "TICKS"); 439 | break; 440 | case TYPE_OPAQUE: 441 | strcpy(str, "OPAQUE"); 442 | break; 443 | case TYPE_COUNTER64: 444 | strcpy(str, "COUNTER64"); 445 | break; 446 | case TYPE_NULL: 447 | strcpy(str, "NULL"); 448 | break; 449 | case SNMP_ENDOFMIBVIEW: 450 | strcpy(str, "ENDOFMIBVIEW"); 451 | break; 452 | case SNMP_NOSUCHOBJECT: 453 | strcpy(str, "NOSUCHOBJECT"); 454 | break; 455 | case SNMP_NOSUCHINSTANCE: 456 | strcpy(str, "NOSUCHINSTANCE"); 457 | break; 458 | case TYPE_UINTEGER: 459 | strcpy(str, "UINTEGER"); /* historic - should not show up */ 460 | /* but it does? */ 461 | break; 462 | case TYPE_NOTIFTYPE: 463 | strcpy(str, "NOTIF"); 464 | break; 465 | case TYPE_BITSTRING: 466 | strcpy(str, "BITS"); 467 | break; 468 | case TYPE_TRAPTYPE: 469 | strcpy(str, "TRAP"); 470 | break; 471 | case TYPE_OTHER: /* not sure if this is a valid leaf type?? */ 472 | case TYPE_NSAPADDRESS: 473 | default: /* unsupported types for now */ 474 | strcpy(str, ""); 475 | if (_debug_level) printf("__get_type_str:FAILURE(%d)\n", type); 476 | 477 | return(FAILURE); 478 | } 479 | return SUCCESS; 480 | } 481 | 482 | /* does a destructive disection of .... returning 483 | and in seperate strings (note: will destructively 484 | alter input string, 'name') */ 485 | static int 486 | __get_label_iid (name, last_label, iid, flag) 487 | char * name; 488 | char ** last_label; 489 | char ** iid; 490 | int flag; 491 | { 492 | char *lcp; 493 | char *icp; 494 | int len = STRLEN(name); 495 | int found_label = 0; 496 | 497 | *last_label = *iid = NULL; 498 | 499 | if (len == 0) return(FAILURE); 500 | 501 | /* Handle case where numeric oid's have been requested. The input 'name' 502 | ** in this case should be a numeric OID -- return failure if not. 503 | */ 504 | if ((flag & USE_NUMERIC_OIDS)) { 505 | if (!__is_numeric_oid(name)) 506 | return(FAILURE); 507 | 508 | /* Walk backward through the string, looking for first two '.' chars */ 509 | lcp = &(name[len]); 510 | icp = NULL; 511 | while (lcp > name) { 512 | if (*lcp == '.') { 513 | 514 | /* If this is the first occurence of '.', note it in icp. 515 | ** Otherwise, this must be the second occurrence, so break 516 | ** out of the loop. 517 | */ 518 | if (icp == NULL) 519 | icp = lcp; 520 | else 521 | break; 522 | } 523 | lcp --; 524 | } 525 | 526 | /* Make sure we found at least a label and index. */ 527 | if (!icp) 528 | return(FAILURE); 529 | 530 | /* Push forward past leading '.' chars and separate the strings. */ 531 | lcp ++; 532 | *icp ++ = '\0'; 533 | 534 | *last_label = (flag & USE_LONG_NAMES) ? name : lcp; 535 | *iid = icp; 536 | 537 | return(SUCCESS); 538 | } 539 | 540 | lcp = icp = &(name[len]); 541 | 542 | while (lcp > name) { 543 | if (*lcp == '.') { 544 | if (found_label) { 545 | lcp++; 546 | break; 547 | } else { 548 | icp = lcp; 549 | } 550 | } 551 | if (!found_label && isalpha((int)*lcp)) found_label = 1; 552 | lcp--; 553 | } 554 | 555 | if (!found_label || (!isdigit((int)*(icp+1)) && (flag & FAIL_ON_NULL_IID))) 556 | return(FAILURE); 557 | 558 | if (flag & NON_LEAF_NAME) { /* dont know where to start instance id */ 559 | /* put the whole thing in label */ 560 | icp = &(name[len]); 561 | flag |= USE_LONG_NAMES; 562 | /* special hack in case no mib loaded - object identifiers will 563 | * start with .iso......, in which case it is preferable 564 | * to make the label entirely numeric (i.e., convert "iso" => "1") 565 | */ 566 | if (*lcp == '.' && lcp == name) { 567 | if (!strncmp(".ccitt.",lcp,7)) { 568 | name += 2; 569 | *name = '.'; 570 | *(name+1) = '0'; 571 | } else if (!strncmp(".iso.",lcp,5)) { 572 | name += 2; 573 | *name = '.'; 574 | *(name+1) = '1'; 575 | } else if (!strncmp(".joint-iso-ccitt.",lcp,17)) { 576 | name += 2; 577 | *name = '.'; 578 | *(name+1) = '2'; 579 | } 580 | } 581 | } else if (*icp) { 582 | *(icp++) = '\0'; 583 | } 584 | *last_label = (flag & USE_LONG_NAMES ? name : lcp); 585 | 586 | *iid = icp; 587 | 588 | return(SUCCESS); 589 | } 590 | 591 | /* Convert a tag (string) to an OID array */ 592 | /* Tag can be either a symbolic name, or an OID string */ 593 | static struct tree * 594 | __tag2oid(tag, iid, oid_arr, oid_arr_len, type, best_guess) 595 | char * tag; 596 | char * iid; 597 | oid * oid_arr; 598 | int * oid_arr_len; 599 | int * type; 600 | int best_guess; 601 | { 602 | struct tree *tp = NULL; 603 | struct tree *rtp = NULL; 604 | oid newname[MAX_OID_LEN], *op; 605 | size_t newname_len = 0; 606 | 607 | if (type) *type = TYPE_UNKNOWN; 608 | if (oid_arr_len) *oid_arr_len = 0; 609 | if (!tag) goto done; 610 | 611 | /*********************************************************/ 612 | /* best_guess = 0 - same as no switches (read_objid) */ 613 | /* if multiple parts, or uses find_node */ 614 | /* if a single leaf */ 615 | /* best_guess = 1 - same as -Ib (get_wild_node) */ 616 | /* best_guess = 2 - same as -IR (get_node) */ 617 | /*********************************************************/ 618 | 619 | /* numeric scalar (1,2) */ 620 | /* single symbolic (1,2) */ 621 | /* single regex (1) */ 622 | /* partial full symbolic (2) */ 623 | /* full symbolic (2) */ 624 | /* module::single symbolic (2) */ 625 | /* module::partial full symbolic (2) */ 626 | if (best_guess == 1 || best_guess == 2) { 627 | if (!__scan_num_objid(tag, newname, &newname_len)) { /* make sure it's not a numeric tag */ 628 | newname_len = MAX_OID_LEN; 629 | if (best_guess == 2) { /* Random search -IR */ 630 | if (get_node(tag, newname, &newname_len)) { 631 | rtp = tp = get_tree(newname, newname_len, get_tree_head()); 632 | } 633 | } 634 | else if (best_guess == 1) { /* Regex search -Ib */ 635 | clear_tree_flags(get_tree_head()); 636 | if (get_wild_node(tag, newname, &newname_len)) { 637 | rtp = tp = get_tree(newname, newname_len, get_tree_head()); 638 | } 639 | } 640 | } 641 | else { 642 | rtp = tp = get_tree(newname, newname_len, get_tree_head()); 643 | } 644 | if (type) *type = (tp ? tp->type : TYPE_UNKNOWN); 645 | if ((oid_arr == NULL) || (oid_arr_len == NULL)) return rtp; 646 | memcpy(oid_arr,(char*)newname,newname_len*sizeof(oid)); 647 | *oid_arr_len = newname_len; 648 | } 649 | 650 | /* if best_guess is off and multi part tag or module::tag */ 651 | /* numeric scalar */ 652 | /* module::single symbolic */ 653 | /* module::partial full symbolic */ 654 | /* FULL symbolic OID */ 655 | else if (strchr(tag,'.') || strchr(tag,':')) { 656 | if (!__scan_num_objid(tag, newname, &newname_len)) { /* make sure it's not a numeric tag */ 657 | newname_len = MAX_OID_LEN; 658 | if (read_objid(tag, newname, &newname_len)) { /* long name */ 659 | rtp = tp = get_tree(newname, newname_len, get_tree_head()); 660 | } else { 661 | /* failed to parse the OID */ 662 | newname_len = 0; 663 | } 664 | } 665 | else { 666 | rtp = tp = get_tree(newname, newname_len, get_tree_head()); 667 | } 668 | if (type) *type = (tp ? tp->type : TYPE_UNKNOWN); 669 | if ((oid_arr == NULL) || (oid_arr_len == NULL)) return rtp; 670 | memcpy(oid_arr,(char*)newname,newname_len*sizeof(oid)); 671 | *oid_arr_len = newname_len; 672 | } 673 | 674 | /* else best_guess is off and it is a single leaf */ 675 | /* single symbolic */ 676 | else { 677 | rtp = tp = find_node(tag, get_tree_head()); 678 | if (tp) { 679 | if (type) *type = tp->type; 680 | if ((oid_arr == NULL) || (oid_arr_len == NULL)) return rtp; 681 | /* code taken from get_node in snmp_client.c */ 682 | for(op = newname + MAX_OID_LEN - 1; op >= newname; op--){ 683 | *op = tp->subid; 684 | tp = tp->parent; 685 | if (tp == NULL) 686 | break; 687 | } 688 | *oid_arr_len = newname + MAX_OID_LEN - op; 689 | memcpy(oid_arr, op, *oid_arr_len * sizeof(oid)); 690 | } else { 691 | return(rtp); /* HACK: otherwise, concat_oid_str confuses things */ 692 | } 693 | } 694 | done: 695 | if (iid && *iid && oid_arr_len) 696 | __concat_oid_str(oid_arr, oid_arr_len, iid); 697 | return(rtp); 698 | } 699 | 700 | /* function: __concat_oid_str 701 | * 702 | * This function converts a dotted-decimal string, soid_str, to an array 703 | * of oid types and concatenates them on doid_arr begining at the index 704 | * specified by doid_arr_len. 705 | * 706 | * returns : SUCCESS, FAILURE 707 | */ 708 | static int 709 | __concat_oid_str(doid_arr, doid_arr_len, soid_str) 710 | oid *doid_arr; 711 | int *doid_arr_len; 712 | char * soid_str; 713 | { 714 | char *soid_buf; 715 | char *cp; 716 | char *st; 717 | 718 | if (!soid_str || !*soid_str) return SUCCESS;/* successfully added nothing */ 719 | if (*soid_str == '.') soid_str++; 720 | soid_buf = strdup(soid_str); 721 | if (!soid_buf) 722 | return FAILURE; 723 | cp = strtok_r(soid_buf,".",&st); 724 | while (cp) { 725 | sscanf(cp, "%lu", &(doid_arr[(*doid_arr_len)++])); 726 | /* doid_arr[(*doid_arr_len)++] = atoi(cp); */ 727 | cp = strtok_r(NULL,".",&st); 728 | } 729 | free(soid_buf); 730 | return(SUCCESS); 731 | } 732 | 733 | /* 734 | * Ripped wholesale from library/tools.h from Net-SNMP 5.7.3 735 | * to remain compatible with versions 5.7.2 and earlier. 736 | */ 737 | static void *compat_netsnmp_memdup(const void *from, size_t size) { 738 | void *to = NULL; 739 | 740 | if (from) { 741 | to = malloc(size); 742 | if (to) 743 | memcpy(to, from, size); 744 | } 745 | return to; 746 | } 747 | 748 | /* 749 | * add a varbind to PDU 750 | */ 751 | static int 752 | __add_var_val_str(pdu, name, name_length, val, len, type) 753 | netsnmp_pdu *pdu; 754 | oid *name; 755 | int name_length; 756 | char * val; 757 | int len; 758 | int type; 759 | { 760 | netsnmp_variable_list *vars; 761 | oid oidbuf[MAX_OID_LEN]; 762 | int ret = SUCCESS; 763 | 764 | if (pdu->variables == NULL){ 765 | pdu->variables = vars = 766 | (netsnmp_variable_list *)calloc(1,sizeof(netsnmp_variable_list)); 767 | } else { 768 | for(vars = pdu->variables; 769 | vars->next_variable; 770 | vars = vars->next_variable) 771 | /*EXIT*/; 772 | vars->next_variable = 773 | (netsnmp_variable_list *)calloc(1,sizeof(netsnmp_variable_list)); 774 | vars = vars->next_variable; 775 | } 776 | 777 | vars->next_variable = NULL; 778 | vars->name = snmp_duplicate_objid(name, name_length); 779 | vars->name_length = name_length; 780 | switch (type) { 781 | case TYPE_INTEGER: 782 | case TYPE_INTEGER32: 783 | vars->type = ASN_INTEGER; 784 | vars->val.integer = malloc(sizeof(long)); 785 | if (val) 786 | *(vars->val.integer) = strtol(val,NULL,0); 787 | else { 788 | ret = FAILURE; 789 | *(vars->val.integer) = 0; 790 | } 791 | vars->val_len = sizeof(long); 792 | break; 793 | 794 | case TYPE_GAUGE: 795 | case TYPE_UNSIGNED32: 796 | vars->type = ASN_GAUGE; 797 | goto UINT; 798 | case TYPE_COUNTER: 799 | vars->type = ASN_COUNTER; 800 | goto UINT; 801 | case TYPE_TIMETICKS: 802 | vars->type = ASN_TIMETICKS; 803 | goto UINT; 804 | case TYPE_UINTEGER: 805 | vars->type = ASN_UINTEGER; 806 | UINT: 807 | vars->val.integer = malloc(sizeof(long)); 808 | if (val) 809 | sscanf(val,"%lu",vars->val.integer); 810 | else { 811 | ret = FAILURE; 812 | *(vars->val.integer) = 0; 813 | } 814 | vars->val_len = sizeof(long); 815 | break; 816 | 817 | case TYPE_OCTETSTR: 818 | vars->type = ASN_OCTET_STR; 819 | goto OCT; 820 | 821 | case TYPE_BITSTRING: 822 | vars->type = ASN_OCTET_STR; 823 | goto OCT; 824 | 825 | case TYPE_OPAQUE: 826 | vars->type = ASN_OCTET_STR; 827 | OCT: 828 | vars->val.string = malloc(len); 829 | vars->val_len = len; 830 | if (val && len) 831 | memcpy((char *)vars->val.string, val, len); 832 | else { 833 | ret = FAILURE; 834 | vars->val.string = (u_char*)strdup(""); 835 | vars->val_len = 0; 836 | } 837 | break; 838 | 839 | case TYPE_IPADDR: 840 | vars->type = ASN_IPADDRESS; 841 | { 842 | in_addr_t addr; 843 | 844 | if (val) 845 | addr = inet_addr(val); 846 | else { 847 | ret = FAILURE; 848 | addr = 0; 849 | } 850 | vars->val.integer = compat_netsnmp_memdup(&addr, sizeof(addr)); 851 | vars->val_len = sizeof(addr); 852 | } 853 | break; 854 | 855 | case TYPE_OBJID: 856 | vars->type = ASN_OBJECT_ID; 857 | vars->val_len = MAX_OID_LEN; 858 | /* if (read_objid(val, oidbuf, &(vars->val_len))) { */ 859 | /* tp = __tag2oid(val,NULL,oidbuf,&(vars->val_len),NULL,0); */ 860 | if (!val || !snmp_parse_oid(val, oidbuf, &vars->val_len)) { 861 | vars->val.objid = NULL; 862 | ret = FAILURE; 863 | } else { 864 | vars->val.objid = snmp_duplicate_objid(oidbuf, vars->val_len); 865 | vars->val_len *= sizeof(oid); 866 | } 867 | break; 868 | 869 | default: 870 | vars->type = ASN_NULL; 871 | vars->val_len = 0; 872 | vars->val.string = NULL; 873 | ret = FAILURE; 874 | } 875 | 876 | return ret; 877 | } 878 | 879 | /* takes ss and pdu as input and updates the 'response' argument */ 880 | /* the input 'pdu' argument will be freed */ 881 | static int 882 | __send_sync_pdu(netsnmp_session *ss, netsnmp_pdu *pdu, netsnmp_pdu **response, 883 | int retry_nosuch, char *err_str, int *err_num, int *err_ind) 884 | { 885 | int status = 0; 886 | long command = pdu->command; 887 | char *tmp_err_str; 888 | 889 | *err_num = 0; 890 | *err_ind = 0; 891 | *response = NULL; 892 | tmp_err_str = NULL; 893 | memset(err_str, '\0', STR_BUF_SIZE); 894 | 895 | if (ss == NULL) { 896 | *err_num = 0; 897 | *err_ind = SNMPERR_BAD_SESSION; 898 | status = SNMPERR_BAD_SESSION; 899 | strlcpy(err_str, snmp_api_errstring(*err_ind), STR_BUF_SIZE); 900 | goto done; 901 | } 902 | 903 | retry: 904 | 905 | Py_BEGIN_ALLOW_THREADS 906 | status = snmp_sess_synch_response(ss, pdu, response); 907 | Py_END_ALLOW_THREADS 908 | 909 | if ((*response == NULL) && (status == STAT_SUCCESS)) status = STAT_ERROR; 910 | 911 | switch (status) { 912 | case STAT_SUCCESS: 913 | switch ((*response)->errstat) { 914 | case SNMP_ERR_NOERROR: 915 | break; 916 | 917 | case SNMP_ERR_NOSUCHNAME: 918 | if (retry_nosuch && (pdu = snmp_fix_pdu(*response, command))) { 919 | if (*response) snmp_free_pdu(*response); 920 | goto retry; 921 | } 922 | 923 | /* Pv1, SNMPsec, Pv2p, v2c, v2u, v2*, and SNMPv3 PDUs */ 924 | case SNMP_ERR_TOOBIG: 925 | case SNMP_ERR_BADVALUE: 926 | case SNMP_ERR_READONLY: 927 | case SNMP_ERR_GENERR: 928 | /* in SNMPv2p, SNMPv2c, SNMPv2u, SNMPv2*, and SNMPv3 PDUs */ 929 | case SNMP_ERR_NOACCESS: 930 | case SNMP_ERR_WRONGTYPE: 931 | case SNMP_ERR_WRONGLENGTH: 932 | case SNMP_ERR_WRONGENCODING: 933 | case SNMP_ERR_WRONGVALUE: 934 | case SNMP_ERR_NOCREATION: 935 | case SNMP_ERR_INCONSISTENTVALUE: 936 | case SNMP_ERR_RESOURCEUNAVAILABLE: 937 | case SNMP_ERR_COMMITFAILED: 938 | case SNMP_ERR_UNDOFAILED: 939 | case SNMP_ERR_AUTHORIZATIONERROR: 940 | case SNMP_ERR_NOTWRITABLE: 941 | /* in SNMPv2c, SNMPv2u, SNMPv2*, and SNMPv3 PDUs */ 942 | case SNMP_ERR_INCONSISTENTNAME: 943 | default: 944 | strlcpy(err_str, (char*)snmp_errstring((*response)->errstat), 945 | STR_BUF_SIZE); 946 | *err_num = (int)(*response)->errstat; 947 | *err_ind = (*response)->errindex; 948 | status = (*response)->errstat; 949 | break; 950 | } 951 | break; 952 | 953 | case STAT_TIMEOUT: 954 | case STAT_ERROR: 955 | snmp_sess_error(ss, err_num, err_ind, &tmp_err_str); 956 | strlcpy(err_str, tmp_err_str, STR_BUF_SIZE); 957 | break; 958 | 959 | default: 960 | strcat(err_str, "send_sync_pdu: unknown status"); 961 | *err_num = ss->s_snmp_errno; 962 | break; 963 | } 964 | done: 965 | if (tmp_err_str) { 966 | free(tmp_err_str); 967 | } 968 | if (_debug_level && *err_num) printf("XXX sync PDU: %s\n", err_str); 969 | return(status); 970 | } 971 | 972 | static PyObject * exception(PyObject *m) { 973 | return ((struct module_state*)PyModule_GetState(m))->error; 974 | } 975 | 976 | static PyObject * 977 | py_netsnmp_construct_varbind(void) 978 | { 979 | PyObject *module; 980 | PyObject *dict; 981 | PyObject *callable; 982 | 983 | module = PyImport_ImportModule("netsnmp"); 984 | dict = PyModule_GetDict(module); 985 | 986 | callable = PyDict_GetItemString(dict, "Varbind"); 987 | 988 | return PyObject_CallFunction(callable, ""); 989 | } 990 | 991 | static int 992 | py_netsnmp_attr_set_string(PyObject *obj, char *attr_name, 993 | char *val, size_t len) 994 | { 995 | int ret = -1; 996 | if (obj && attr_name) { 997 | PyObject* val_obj = (val ? 998 | Py_BuildValue("s#", val, len) : 999 | Py_BuildValue("")); 1000 | ret = PyObject_SetAttrString(obj, attr_name, val_obj); 1001 | Py_DECREF(val_obj); 1002 | } 1003 | return ret; 1004 | } 1005 | 1006 | static int 1007 | py_netsnmp_attr_string(PyObject *obj, char * attr_name, char **val, 1008 | Py_ssize_t *len) 1009 | { 1010 | *val = NULL; 1011 | if (obj && attr_name && PyObject_HasAttrString(obj, attr_name)) { 1012 | PyObject *attr = PyObject_GetAttrString(obj, attr_name); 1013 | if (attr) { 1014 | *val = PyUnicode_AsUTF8AndSize(attr, len); 1015 | Py_DECREF(attr); 1016 | return 0; 1017 | } 1018 | } 1019 | 1020 | return -1; 1021 | } 1022 | 1023 | static int 1024 | py_netsnmp_attr_set_bytes(PyObject *obj, char *attr_name, 1025 | char *val, size_t len) 1026 | { 1027 | int ret = -1; 1028 | if (obj && attr_name) { 1029 | PyObject* val_obj = (val ? 1030 | PyBytes_FromStringAndSize(val, len) : 1031 | Py_BuildValue("")); 1032 | ret = PyObject_SetAttrString(obj, attr_name, val_obj); 1033 | Py_DECREF(val_obj); 1034 | } 1035 | return ret; 1036 | } 1037 | 1038 | static int 1039 | py_netsnmp_attr_bytes(PyObject *obj, char * attr_name, char **val, 1040 | Py_ssize_t *len) 1041 | { 1042 | *val = NULL; 1043 | if (obj && attr_name && PyObject_HasAttrString(obj, attr_name)) { 1044 | PyObject *attr = PyObject_GetAttrString(obj, attr_name); 1045 | if (attr) { 1046 | int retval; 1047 | retval = PyBytes_AsStringAndSize(attr, val, len); 1048 | Py_DECREF(attr); 1049 | return retval; 1050 | } 1051 | } 1052 | 1053 | return -1; 1054 | } 1055 | 1056 | static long long 1057 | py_netsnmp_attr_long(PyObject *obj, char * attr_name) 1058 | { 1059 | long long val = -1; 1060 | 1061 | if (obj && attr_name && PyObject_HasAttrString(obj, attr_name)) { 1062 | PyObject *attr = PyObject_GetAttrString(obj, attr_name); 1063 | if (attr) { 1064 | val = PyLong_AsLong(attr); 1065 | Py_DECREF(attr); 1066 | } 1067 | } 1068 | 1069 | return val; 1070 | } 1071 | 1072 | static void * 1073 | py_netsnmp_attr_void_ptr(PyObject *obj, char * attr_name) 1074 | { 1075 | void *val = NULL; 1076 | 1077 | if (obj && attr_name && PyObject_HasAttrString(obj, attr_name)) { 1078 | PyObject *attr = PyObject_GetAttrString(obj, attr_name); 1079 | if (attr) { 1080 | val = PyLong_AsVoidPtr(attr); 1081 | Py_DECREF(attr); 1082 | } 1083 | } 1084 | 1085 | return val; 1086 | } 1087 | 1088 | static int 1089 | py_netsnmp_verbose(void) 1090 | { 1091 | int verbose = 0; 1092 | PyObject *pkg = PyImport_ImportModule("netsnmp"); 1093 | if (pkg) { 1094 | verbose = py_netsnmp_attr_long(pkg, "verbose"); 1095 | Py_DECREF(pkg); 1096 | } 1097 | 1098 | return verbose; 1099 | } 1100 | 1101 | /** 1102 | * Update python session object error attributes. 1103 | * 1104 | * Copy the error info which may have been returned from __send_sync_pdu(...) 1105 | * into the python object. This will allow the python code to determine if 1106 | * an error occured during an snmp operation. 1107 | * 1108 | * Currently there are 3 attributes we care about 1109 | * 1110 | * ErrorNum - Copy of the value of netsnmp_session.s_errno. This is the system 1111 | * errno that was generated during our last call into the net-snmp library. 1112 | * 1113 | * ErrorInd - Copy of the value of netsmp_session.s_snmp_errno. These error 1114 | * numbers are separate from the system errno's and describe SNMP errors. 1115 | * 1116 | * ErrorStr - A string describing the ErrorInd that was returned during our last 1117 | * operation. 1118 | * 1119 | * @param[in] session The python object that represents our current Session 1120 | * @param[in|out] err_str A string describing err_ind 1121 | * @param[in|out] err_num The system errno currently stored by our session 1122 | * @param[in|out] err_ind The snmp errno currently stored by our session 1123 | */ 1124 | static void 1125 | __py_netsnmp_update_session_errors(PyObject *session, char *err_str, 1126 | int err_num, int err_ind) 1127 | { 1128 | PyObject *tmp_for_conversion; 1129 | 1130 | py_netsnmp_attr_set_string(session, "ErrorStr", err_str, STRLEN(err_str)); 1131 | 1132 | tmp_for_conversion = PyLong_FromLong(err_num); 1133 | PyObject_SetAttrString(session, "ErrorNum", tmp_for_conversion); 1134 | Py_DECREF(tmp_for_conversion); 1135 | 1136 | tmp_for_conversion = PyLong_FromLong(err_ind); 1137 | PyObject_SetAttrString(session, "ErrorInd", tmp_for_conversion); 1138 | Py_DECREF(tmp_for_conversion); 1139 | } 1140 | 1141 | static PyObject * 1142 | netsnmp_create_session(PyObject *self, PyObject *args) 1143 | { 1144 | int version; 1145 | char *community; 1146 | char *peer; 1147 | int lport; 1148 | int retries; 1149 | int timeout; 1150 | SnmpSession session = {0}; 1151 | SnmpSession *ss = NULL; 1152 | int verbose = py_netsnmp_verbose(); 1153 | 1154 | if (!PyArg_ParseTuple(args, "issiii", &version, 1155 | &community, &peer, &lport, 1156 | &retries, &timeout)) 1157 | return NULL; 1158 | 1159 | __libraries_init("python"); 1160 | 1161 | snmp_sess_init(&session); 1162 | 1163 | session.version = -1; 1164 | #ifndef DISABLE_SNMPV1 1165 | if (version == 1) { 1166 | session.version = SNMP_VERSION_1; 1167 | } 1168 | #endif 1169 | #ifndef DISABLE_SNMPV2C 1170 | if (version == 2) { 1171 | session.version = SNMP_VERSION_2c; 1172 | } 1173 | #endif 1174 | if (version == 3) { 1175 | session.version = SNMP_VERSION_3; 1176 | } 1177 | if (session.version == -1) { 1178 | PyErr_Format(exception(self), "Unsupported SNMP version (%d)", version); 1179 | goto end; 1180 | } 1181 | 1182 | session.community_len = STRLEN((char *)community); 1183 | session.community = (u_char *)community; 1184 | session.peername = peer; 1185 | session.local_port = lport; 1186 | session.retries = retries; /* 5 */ 1187 | session.timeout = timeout; /* 1000000L */ 1188 | session.authenticator = NULL; 1189 | 1190 | ss = snmp_sess_open(&session); 1191 | 1192 | if (ss == NULL) { 1193 | PyErr_SetString(exception(self), snmp_api_errstring(snmp_errno)); 1194 | } 1195 | 1196 | end: 1197 | if (PyErr_Occurred()) { 1198 | return NULL; 1199 | } 1200 | 1201 | return PyLong_FromVoidPtr((void *)ss); 1202 | } 1203 | 1204 | static PyObject * 1205 | netsnmp_create_session_v3(PyObject *self, PyObject *args) 1206 | { 1207 | int version; 1208 | char *peer; 1209 | int lport; 1210 | int retries; 1211 | int timeout; 1212 | char * sec_name; 1213 | int sec_level; 1214 | char * sec_eng_id; 1215 | char * context_eng_id; 1216 | char * context; 1217 | char * auth_proto; 1218 | char * auth_pass; 1219 | char * priv_proto; 1220 | char * priv_pass; 1221 | int eng_boots; 1222 | int eng_time; 1223 | SnmpSession session = {0}; 1224 | SnmpSession *ss = NULL; 1225 | int verbose = py_netsnmp_verbose(); 1226 | 1227 | if (!PyArg_ParseTuple(args, "isiiisisssssssii", &version, 1228 | &peer, &lport, &retries, &timeout, 1229 | &sec_name, &sec_level, &sec_eng_id, 1230 | &context_eng_id, &context, 1231 | &auth_proto, &auth_pass, 1232 | &priv_proto, &priv_pass, 1233 | &eng_boots, &eng_time)) 1234 | return NULL; 1235 | 1236 | __libraries_init("python"); 1237 | snmp_sess_init(&session); 1238 | 1239 | if (version == 3) { 1240 | session.version = SNMP_VERSION_3; 1241 | } else { 1242 | PyErr_Format(exception(self), "Unsupported SNMP version (%d)", version); 1243 | goto end; 1244 | } 1245 | 1246 | session.peername = peer; 1247 | session.retries = retries; /* 5 */ 1248 | session.timeout = timeout; /* 1000000L */ 1249 | session.authenticator = NULL; 1250 | session.contextNameLen = STRLEN(context); 1251 | session.contextName = context; 1252 | session.securityNameLen = STRLEN(sec_name); 1253 | session.securityName = sec_name; 1254 | session.securityLevel = sec_level; 1255 | session.securityModel = USM_SEC_MODEL_NUMBER; 1256 | session.securityEngineIDLen = 1257 | hex_to_binary2((unsigned char*)sec_eng_id, STRLEN(sec_eng_id), 1258 | (char **) &session.securityEngineID); 1259 | session.contextEngineIDLen = 1260 | hex_to_binary2((unsigned char*)sec_eng_id, STRLEN(sec_eng_id), 1261 | (char **) &session.contextEngineID); 1262 | session.engineBoots = eng_boots; 1263 | session.engineTime = eng_time; 1264 | 1265 | #ifndef DISABLE_MD5 1266 | if (!strcmp(auth_proto, "MD5")) { 1267 | session.securityAuthProto = 1268 | snmp_duplicate_objid(usmHMACMD5AuthProtocol, 1269 | USM_AUTH_PROTO_MD5_LEN); 1270 | session.securityAuthProtoLen = USM_AUTH_PROTO_MD5_LEN; 1271 | } else 1272 | #endif 1273 | if (!strcmp(auth_proto, "SHA")) { 1274 | session.securityAuthProto = 1275 | snmp_duplicate_objid(usmHMACSHA1AuthProtocol, 1276 | USM_AUTH_PROTO_SHA_LEN); 1277 | session.securityAuthProtoLen = USM_AUTH_PROTO_SHA_LEN; 1278 | } else if (!strcmp(auth_proto, "DEFAULT")) { 1279 | const oid* a = get_default_authtype(&session.securityAuthProtoLen); 1280 | session.securityAuthProto 1281 | = snmp_duplicate_objid(a, session.securityAuthProtoLen); 1282 | } else { 1283 | PyErr_Format(exception(self), "Unsupported authentication protocol (%s)", auth_proto); 1284 | goto end; 1285 | } 1286 | if (session.securityLevel >= SNMP_SEC_LEVEL_AUTHNOPRIV) { 1287 | if (STRLEN(auth_pass) > 0) { 1288 | session.securityAuthKeyLen = USM_AUTH_KU_LEN; 1289 | if (generate_Ku(session.securityAuthProto, 1290 | session.securityAuthProtoLen, 1291 | (u_char *)auth_pass, STRLEN(auth_pass), 1292 | session.securityAuthKey, 1293 | &session.securityAuthKeyLen) != SNMPERR_SUCCESS) { 1294 | goto error; 1295 | } 1296 | } 1297 | } 1298 | #ifndef DISABLE_DES 1299 | if (!strcmp(priv_proto, "DES")) { 1300 | session.securityPrivProto = 1301 | snmp_duplicate_objid(usmDESPrivProtocol, 1302 | USM_PRIV_PROTO_DES_LEN); 1303 | session.securityPrivProtoLen = USM_PRIV_PROTO_DES_LEN; 1304 | } else 1305 | #endif 1306 | if (!strncmp(priv_proto, "AES", 3)) { 1307 | session.securityPrivProto = 1308 | snmp_duplicate_objid(usmAESPrivProtocol, 1309 | USM_PRIV_PROTO_AES_LEN); 1310 | session.securityPrivProtoLen = USM_PRIV_PROTO_AES_LEN; 1311 | } else if (!strcmp(priv_proto, "DEFAULT")) { 1312 | const oid *p = get_default_privtype(&session.securityPrivProtoLen); 1313 | session.securityPrivProto 1314 | = snmp_duplicate_objid(p, session.securityPrivProtoLen); 1315 | } else { 1316 | PyErr_Format(exception(self), "Unsupported privacy protocol (%s)", priv_proto); 1317 | goto end; 1318 | } 1319 | 1320 | if (session.securityLevel >= SNMP_SEC_LEVEL_AUTHPRIV) { 1321 | session.securityPrivKeyLen = USM_PRIV_KU_LEN; 1322 | if (generate_Ku(session.securityAuthProto, 1323 | session.securityAuthProtoLen, 1324 | (u_char *)priv_pass, STRLEN(priv_pass), 1325 | session.securityPrivKey, 1326 | &session.securityPrivKeyLen) != SNMPERR_SUCCESS) { 1327 | goto error; 1328 | } 1329 | } 1330 | 1331 | ss = snmp_sess_open(&session); 1332 | 1333 | error: 1334 | if (ss == NULL) { 1335 | PyErr_SetString(exception(self), snmp_api_errstring(snmp_errno)); 1336 | } 1337 | end: 1338 | free (session.securityEngineID); 1339 | free (session.contextEngineID); 1340 | 1341 | if (PyErr_Occurred()) { 1342 | return NULL; 1343 | } 1344 | 1345 | return PyLong_FromVoidPtr((void *)ss); 1346 | } 1347 | 1348 | static PyObject * 1349 | netsnmp_create_session_tunneled(PyObject *self, PyObject *args) 1350 | { 1351 | int version; 1352 | char *peer; 1353 | int lport; 1354 | int retries; 1355 | int timeout; 1356 | char * sec_name; 1357 | int sec_level; 1358 | char * context_eng_id; 1359 | char * context; 1360 | char * our_identity; 1361 | char * their_identity; 1362 | char * their_hostname; 1363 | char * trust_cert; 1364 | SnmpSession session = {0}; 1365 | SnmpSession *ss = NULL; 1366 | int verbose = py_netsnmp_verbose(); 1367 | 1368 | if (!PyArg_ParseTuple(args, "isiiisissssss", &version, 1369 | &peer, &lport, &retries, &timeout, 1370 | &sec_name, &sec_level, 1371 | &context_eng_id, &context, 1372 | &our_identity, &their_identity, 1373 | &their_hostname, &trust_cert)) 1374 | return NULL; 1375 | 1376 | __libraries_init("python"); 1377 | snmp_sess_init(&session); 1378 | 1379 | if (version != 3) { 1380 | session.version = SNMP_VERSION_3; 1381 | if (verbose) 1382 | printf("Using version 3 as it's the only version that supports tunneling\n"); 1383 | } 1384 | 1385 | session.peername = peer; 1386 | session.retries = retries; /* 5 */ 1387 | session.timeout = timeout; /* 1000000L */ 1388 | session.contextNameLen = STRLEN(context); 1389 | session.contextName = context; 1390 | session.securityNameLen = STRLEN(sec_name); 1391 | session.securityName = sec_name; 1392 | session.securityLevel = sec_level; 1393 | session.securityModel = NETSNMP_TSM_SECURITY_MODEL; 1394 | 1395 | /* create the transport configuration store */ 1396 | if (!session.transport_configuration) { 1397 | netsnmp_container_init_list(); 1398 | session.transport_configuration = 1399 | netsnmp_container_find("transport_configuration:fifo"); 1400 | if (!session.transport_configuration) { 1401 | PyErr_SetString(exception(self), "Failed to initialize the transport configuration container"); 1402 | return NULL; 1403 | } 1404 | 1405 | session.transport_configuration->compare = 1406 | (netsnmp_container_compare*) 1407 | netsnmp_transport_config_compare; 1408 | } 1409 | 1410 | if (our_identity && our_identity[0] != '\0') 1411 | CONTAINER_INSERT(session.transport_configuration, 1412 | netsnmp_transport_create_config("localCert", 1413 | our_identity)); 1414 | 1415 | if (their_identity && their_identity[0] != '\0') 1416 | CONTAINER_INSERT(session.transport_configuration, 1417 | netsnmp_transport_create_config("peerCert", 1418 | their_identity)); 1419 | 1420 | if (their_hostname && their_hostname[0] != '\0') 1421 | CONTAINER_INSERT(session.transport_configuration, 1422 | netsnmp_transport_create_config("their_hostname", 1423 | their_hostname)); 1424 | 1425 | if (trust_cert && trust_cert[0] != '\0') 1426 | CONTAINER_INSERT(session.transport_configuration, 1427 | netsnmp_transport_create_config("trust_cert", 1428 | trust_cert)); 1429 | 1430 | ss = snmp_sess_open(&session); 1431 | 1432 | if (!ss) { 1433 | PyErr_SetString(exception(self), snmp_api_errstring(snmp_errno)); 1434 | } 1435 | 1436 | if (PyErr_Occurred()) { 1437 | return NULL; 1438 | } 1439 | 1440 | /* 1441 | * Note: on a 64-bit system the statement below discards the upper 32 bits of 1442 | * "ss", which is most likely a bug. 1443 | */ 1444 | return Py_BuildValue("i", (int)(uintptr_t)ss); 1445 | } 1446 | 1447 | static PyObject * 1448 | netsnmp_delete_session(PyObject *self, PyObject *args) 1449 | { 1450 | PyObject *session; 1451 | SnmpSession *ss = NULL; 1452 | 1453 | if (!PyArg_ParseTuple(args, "O", &session)) { 1454 | return NULL; 1455 | } 1456 | 1457 | ss = (SnmpSession *)py_netsnmp_attr_void_ptr(session, "sess_ptr"); 1458 | 1459 | snmp_sess_close(ss); 1460 | return (Py_BuildValue("")); 1461 | } 1462 | 1463 | 1464 | static PyObject * 1465 | netsnmp_get(PyObject *self, PyObject *args) 1466 | { 1467 | PyObject *session; 1468 | PyObject *varlist; 1469 | PyObject *varbind; 1470 | PyObject *val_tuple = NULL; 1471 | int varlist_len = 0; 1472 | int varlist_ind; 1473 | netsnmp_session *ss; 1474 | netsnmp_pdu *pdu, *response; 1475 | netsnmp_variable_list *vars; 1476 | struct tree *tp; 1477 | int len; 1478 | oid *oid_arr; 1479 | int oid_arr_len = MAX_OID_LEN; 1480 | int type; 1481 | char type_str[MAX_TYPE_NAME_LEN]; 1482 | u_char str_buf[STR_BUF_SIZE], *str_bufp = str_buf; 1483 | size_t str_buf_len = sizeof(str_buf); 1484 | size_t out_len = 0; 1485 | int buf_over = 0; 1486 | char *tag; 1487 | char *iid; 1488 | int getlabel_flag = NO_FLAGS; 1489 | int sprintval_flag = USE_BASIC; 1490 | int verbose = py_netsnmp_verbose(); 1491 | int old_format; 1492 | int best_guess; 1493 | int retry_nosuch; 1494 | int err_ind; 1495 | int err_num; 1496 | char err_str[STR_BUF_SIZE]; 1497 | char *tmpstr; 1498 | Py_ssize_t tmplen; 1499 | 1500 | oid_arr = calloc(MAX_OID_LEN, sizeof(oid)); 1501 | 1502 | if (oid_arr && args) { 1503 | 1504 | if (!PyArg_ParseTuple(args, "OO", &session, &varlist)) { 1505 | goto done; 1506 | } 1507 | 1508 | ss = (SnmpSession *)py_netsnmp_attr_void_ptr(session, "sess_ptr"); 1509 | 1510 | if (py_netsnmp_attr_string(session, "ErrorStr", &tmpstr, &tmplen) < 0) { 1511 | goto done; 1512 | } 1513 | 1514 | if (py_netsnmp_attr_long(session, "UseLongNames")) 1515 | getlabel_flag |= USE_LONG_NAMES; 1516 | if (py_netsnmp_attr_long(session, "UseNumeric")) 1517 | getlabel_flag |= USE_NUMERIC_OIDS; 1518 | if (py_netsnmp_attr_long(session, "UseEnums")) 1519 | sprintval_flag = USE_ENUMS; 1520 | if (py_netsnmp_attr_long(session, "UseSprintValue")) 1521 | sprintval_flag = USE_SPRINT_VALUE; 1522 | best_guess = py_netsnmp_attr_long(session, "BestGuess"); 1523 | retry_nosuch = py_netsnmp_attr_long(session, "RetryNoSuch"); 1524 | 1525 | pdu = snmp_pdu_create(SNMP_MSG_GET); 1526 | 1527 | if (varlist) { 1528 | PyObject *varlist_iter = PyObject_GetIter(varlist); 1529 | 1530 | while (varlist_iter && (varbind = PyIter_Next(varlist_iter))) { 1531 | if (py_netsnmp_attr_string(varbind, "tag", &tag, NULL) < 0 || 1532 | py_netsnmp_attr_string(varbind, "iid", &iid, NULL) < 0) 1533 | { 1534 | oid_arr_len = 0; 1535 | } else { 1536 | tp = __tag2oid(tag, iid, oid_arr, &oid_arr_len, NULL, best_guess); 1537 | } 1538 | 1539 | if (oid_arr_len) { 1540 | snmp_add_null_var(pdu, oid_arr, oid_arr_len); 1541 | varlist_len++; 1542 | } else { 1543 | if (verbose) 1544 | printf("error: get: unknown object ID (%s)", 1545 | (tag ? tag : "")); 1546 | snmp_free_pdu(pdu); 1547 | Py_DECREF(varbind); 1548 | goto done; 1549 | } 1550 | /* release reference when done */ 1551 | Py_DECREF(varbind); 1552 | } 1553 | 1554 | Py_DECREF(varlist_iter); 1555 | 1556 | if (PyErr_Occurred()) { 1557 | /* propagate error */ 1558 | if (verbose) 1559 | printf("error: get: unknown python error"); 1560 | snmp_free_pdu(pdu); 1561 | goto done; 1562 | } 1563 | } 1564 | 1565 | __send_sync_pdu(ss, pdu, &response, retry_nosuch, err_str, &err_num, 1566 | &err_ind); 1567 | __py_netsnmp_update_session_errors(session, err_str, err_num, err_ind); 1568 | 1569 | /* 1570 | ** Set up for numeric or full OID's, if necessary. Save the old 1571 | ** output format so that it can be restored when we finish -- this 1572 | ** is a library-wide global, and has to be set/restored for each 1573 | ** session. 1574 | */ 1575 | old_format = netsnmp_ds_get_int(NETSNMP_DS_LIBRARY_ID, 1576 | NETSNMP_DS_LIB_OID_OUTPUT_FORMAT); 1577 | 1578 | if (py_netsnmp_attr_long(session, "UseLongNames")) { 1579 | getlabel_flag |= USE_LONG_NAMES; 1580 | 1581 | netsnmp_ds_set_int(NETSNMP_DS_LIBRARY_ID, 1582 | NETSNMP_DS_LIB_OID_OUTPUT_FORMAT, 1583 | NETSNMP_OID_OUTPUT_FULL); 1584 | } 1585 | /* Setting UseNumeric forces UseLongNames on so check for UseNumeric 1586 | after UseLongNames (above) to make sure the final outcome of 1587 | NETSNMP_DS_LIB_OID_OUTPUT_FORMAT is NETSNMP_OID_OUTPUT_NUMERIC */ 1588 | if (py_netsnmp_attr_long(session, "UseNumeric")) { 1589 | getlabel_flag |= USE_LONG_NAMES; 1590 | getlabel_flag |= USE_NUMERIC_OIDS; 1591 | 1592 | netsnmp_ds_set_int(NETSNMP_DS_LIBRARY_ID, 1593 | NETSNMP_DS_LIB_OID_OUTPUT_FORMAT, 1594 | NETSNMP_OID_OUTPUT_NUMERIC); 1595 | } 1596 | 1597 | val_tuple = PyTuple_New(varlist_len); 1598 | /* initialize return tuple */ 1599 | for (varlist_ind = 0; varlist_ind < varlist_len; varlist_ind++) { 1600 | PyTuple_SetItem(val_tuple, varlist_ind, Py_BuildValue("")); 1601 | } 1602 | 1603 | for(vars = (response ? response->variables : NULL), varlist_ind = 0; 1604 | vars && (varlist_ind < varlist_len); 1605 | vars = vars->next_variable, varlist_ind++) { 1606 | 1607 | varbind = PySequence_GetItem(varlist, varlist_ind); 1608 | 1609 | if (PyObject_HasAttrString(varbind, "tag")) { 1610 | *str_buf = '.'; 1611 | *(str_buf+1) = '\0'; 1612 | out_len = 0; 1613 | tp = netsnmp_sprint_realloc_objid_tree(&str_bufp, &str_buf_len, 1614 | &out_len, 0, &buf_over, 1615 | vars->name,vars->name_length); 1616 | if (_debug_level) 1617 | printf("netsnmp_get:str_bufp:%s:%d:%d\n", str_bufp, 1618 | (int)str_buf_len, (int)out_len); 1619 | 1620 | str_buf[sizeof(str_buf)-1] = '\0'; 1621 | 1622 | if (__is_leaf(tp)) { 1623 | type = (tp->type ? tp->type : tp->parent->type); 1624 | getlabel_flag &= ~NON_LEAF_NAME; 1625 | if (_debug_level) printf("netsnmp_get:is_leaf:%d\n",type); 1626 | } else { 1627 | getlabel_flag |= NON_LEAF_NAME; 1628 | type = __translate_asn_type(vars->type); 1629 | if (_debug_level) printf("netsnmp_get:!is_leaf:%d\n",tp->type); 1630 | } 1631 | 1632 | if (_debug_level) printf("netsnmp_get:str_buf:%s\n",str_buf); 1633 | 1634 | __get_label_iid((char *) str_buf, &tag, &iid, getlabel_flag); 1635 | 1636 | py_netsnmp_attr_set_string(varbind, "tag", tag, STRLEN(tag)); 1637 | py_netsnmp_attr_set_string(varbind, "iid", iid, STRLEN(iid)); 1638 | 1639 | __get_type_str(type, type_str); 1640 | 1641 | py_netsnmp_attr_set_string(varbind, "type", type_str, strlen(type_str)); 1642 | 1643 | len = __snprint_value((char *) str_buf, sizeof(str_buf), 1644 | vars, tp, type, sprintval_flag); 1645 | str_buf[len] = '\0'; 1646 | py_netsnmp_attr_set_bytes(varbind, "val", (char *) str_buf, len); 1647 | 1648 | /* save in return tuple as well */ 1649 | if ((type == SNMP_ENDOFMIBVIEW) || 1650 | (type == SNMP_NOSUCHOBJECT) || 1651 | (type == SNMP_NOSUCHINSTANCE)) { 1652 | /* Translate error to None */ 1653 | PyTuple_SetItem(val_tuple, varlist_ind, 1654 | Py_BuildValue("")); 1655 | } else { 1656 | PyTuple_SetItem(val_tuple, varlist_ind, 1657 | PyBytes_FromStringAndSize(str_buf, len)); 1658 | } 1659 | Py_DECREF(varbind); 1660 | } else { 1661 | printf("netsnmp_get: bad varbind (%d)\n", varlist_ind); 1662 | Py_XDECREF(varbind); 1663 | } 1664 | } 1665 | 1666 | /* Reset the library's behavior for numeric/symbolic OID's. */ 1667 | netsnmp_ds_set_int(NETSNMP_DS_LIBRARY_ID, 1668 | NETSNMP_DS_LIB_OID_OUTPUT_FORMAT, 1669 | old_format); 1670 | 1671 | if (response) snmp_free_pdu(response); 1672 | } 1673 | 1674 | done: 1675 | SAFE_FREE(oid_arr); 1676 | return (val_tuple ? val_tuple : Py_BuildValue("")); 1677 | } 1678 | 1679 | static PyObject * 1680 | netsnmp_getnext(PyObject *self, PyObject *args) 1681 | { 1682 | PyObject *session; 1683 | PyObject *varlist; 1684 | PyObject *varbind; 1685 | PyObject *val_tuple = NULL; 1686 | int varlist_len = 0; 1687 | int varlist_ind; 1688 | netsnmp_session *ss; 1689 | netsnmp_pdu *pdu, *response; 1690 | netsnmp_variable_list *vars; 1691 | struct tree *tp; 1692 | int len; 1693 | oid *oid_arr; 1694 | int oid_arr_len = MAX_OID_LEN; 1695 | int type; 1696 | char type_str[MAX_TYPE_NAME_LEN]; 1697 | u_char str_buf[STR_BUF_SIZE], *str_bufp = str_buf; 1698 | size_t str_buf_len = sizeof(str_buf); 1699 | size_t out_len = 0; 1700 | int buf_over = 0; 1701 | char *tag; 1702 | char *iid = NULL; 1703 | int getlabel_flag = NO_FLAGS; 1704 | int sprintval_flag = USE_BASIC; 1705 | int verbose = py_netsnmp_verbose(); 1706 | int old_format; 1707 | int best_guess; 1708 | int retry_nosuch; 1709 | int err_ind; 1710 | int err_num; 1711 | char err_str[STR_BUF_SIZE]; 1712 | char *tmpstr; 1713 | Py_ssize_t tmplen; 1714 | 1715 | oid_arr = calloc(MAX_OID_LEN, sizeof(oid)); 1716 | 1717 | if (oid_arr && args) { 1718 | 1719 | if (!PyArg_ParseTuple(args, "OO", &session, &varlist)) { 1720 | goto done; 1721 | } 1722 | 1723 | ss = (SnmpSession *)py_netsnmp_attr_void_ptr(session, "sess_ptr"); 1724 | 1725 | if (py_netsnmp_attr_string(session, "ErrorStr", &tmpstr, &tmplen) < 0) { 1726 | goto done; 1727 | } 1728 | memcpy(&err_str, tmpstr, tmplen); 1729 | err_num = py_netsnmp_attr_long(session, "ErrorNum"); 1730 | err_ind = py_netsnmp_attr_long(session, "ErrorInd"); 1731 | 1732 | if (py_netsnmp_attr_long(session, "UseLongNames")) 1733 | getlabel_flag |= USE_LONG_NAMES; 1734 | if (py_netsnmp_attr_long(session, "UseNumeric")) 1735 | getlabel_flag |= USE_NUMERIC_OIDS; 1736 | if (py_netsnmp_attr_long(session, "UseEnums")) 1737 | sprintval_flag = USE_ENUMS; 1738 | if (py_netsnmp_attr_long(session, "UseSprintValue")) 1739 | sprintval_flag = USE_SPRINT_VALUE; 1740 | best_guess = py_netsnmp_attr_long(session, "BestGuess"); 1741 | retry_nosuch = py_netsnmp_attr_long(session, "RetryNoSuch"); 1742 | 1743 | pdu = snmp_pdu_create(SNMP_MSG_GETNEXT); 1744 | 1745 | if (varlist) { 1746 | PyObject *varlist_iter = PyObject_GetIter(varlist); 1747 | 1748 | while (varlist_iter && (varbind = PyIter_Next(varlist_iter))) { 1749 | if (py_netsnmp_attr_string(varbind, "tag", &tag, NULL) < 0 || 1750 | py_netsnmp_attr_string(varbind, "iid", &iid, NULL) < 0) 1751 | { 1752 | oid_arr_len = 0; 1753 | } else { 1754 | tp = __tag2oid(tag, iid, oid_arr, &oid_arr_len, NULL, best_guess); 1755 | } 1756 | 1757 | if (_debug_level) 1758 | printf("netsnmp_getnext: filling request: %s:%s:%d:%d\n", 1759 | tag, iid, oid_arr_len,best_guess); 1760 | 1761 | if (oid_arr_len) { 1762 | snmp_add_null_var(pdu, oid_arr, oid_arr_len); 1763 | varlist_len++; 1764 | } else { 1765 | if (verbose) 1766 | printf("error: get: unknown object ID (%s)", 1767 | (tag ? tag : "")); 1768 | snmp_free_pdu(pdu); 1769 | Py_DECREF(varbind); 1770 | goto done; 1771 | } 1772 | /* release reference when done */ 1773 | Py_DECREF(varbind); 1774 | } 1775 | 1776 | Py_DECREF(varlist_iter); 1777 | 1778 | if (PyErr_Occurred()) { 1779 | /* propagate error */ 1780 | if (verbose) 1781 | printf("error: get: unknown python error"); 1782 | snmp_free_pdu(pdu); 1783 | goto done; 1784 | } 1785 | } 1786 | 1787 | __send_sync_pdu(ss, pdu, &response, retry_nosuch, err_str, &err_num, 1788 | &err_ind); 1789 | __py_netsnmp_update_session_errors(session, err_str, err_num, err_ind); 1790 | 1791 | /* 1792 | ** Set up for numeric or full OID's, if necessary. Save the old 1793 | ** output format so that it can be restored when we finish -- this 1794 | ** is a library-wide global, and has to be set/restored for each 1795 | ** session. 1796 | */ 1797 | old_format = netsnmp_ds_get_int(NETSNMP_DS_LIBRARY_ID, 1798 | NETSNMP_DS_LIB_OID_OUTPUT_FORMAT); 1799 | 1800 | if (py_netsnmp_attr_long(session, "UseLongNames")) { 1801 | getlabel_flag |= USE_LONG_NAMES; 1802 | 1803 | netsnmp_ds_set_int(NETSNMP_DS_LIBRARY_ID, 1804 | NETSNMP_DS_LIB_OID_OUTPUT_FORMAT, 1805 | NETSNMP_OID_OUTPUT_FULL); 1806 | } 1807 | /* Setting UseNumeric forces UseLongNames on so check for UseNumeric 1808 | after UseLongNames (above) to make sure the final outcome of 1809 | NETSNMP_DS_LIB_OID_OUTPUT_FORMAT is NETSNMP_OID_OUTPUT_NUMERIC */ 1810 | if (py_netsnmp_attr_long(session, "UseNumeric")) { 1811 | getlabel_flag |= USE_LONG_NAMES; 1812 | getlabel_flag |= USE_NUMERIC_OIDS; 1813 | 1814 | netsnmp_ds_set_int(NETSNMP_DS_LIBRARY_ID, 1815 | NETSNMP_DS_LIB_OID_OUTPUT_FORMAT, 1816 | NETSNMP_OID_OUTPUT_NUMERIC); 1817 | } 1818 | 1819 | val_tuple = PyTuple_New(varlist_len); 1820 | /* initialize return tuple */ 1821 | val_tuple = PyTuple_New(varlist_len); 1822 | for (varlist_ind = 0; varlist_ind < varlist_len; varlist_ind++) { 1823 | PyTuple_SetItem(val_tuple, varlist_ind, Py_BuildValue("")); 1824 | } 1825 | 1826 | for(vars = (response ? response->variables : NULL), varlist_ind = 0; 1827 | vars && (varlist_ind < varlist_len); 1828 | vars = vars->next_variable, varlist_ind++) { 1829 | 1830 | varbind = PySequence_GetItem(varlist, varlist_ind); 1831 | 1832 | if (PyObject_HasAttrString(varbind, "tag")) { 1833 | *str_buf = '.'; 1834 | *(str_buf+1) = '\0'; 1835 | out_len = 0; 1836 | tp = netsnmp_sprint_realloc_objid_tree(&str_bufp, &str_buf_len, 1837 | &out_len, 0, &buf_over, 1838 | vars->name,vars->name_length); 1839 | str_buf[sizeof(str_buf)-1] = '\0'; 1840 | 1841 | if (__is_leaf(tp)) { 1842 | type = (tp->type ? tp->type : tp->parent->type); 1843 | getlabel_flag &= ~NON_LEAF_NAME; 1844 | } else { 1845 | getlabel_flag |= NON_LEAF_NAME; 1846 | type = __translate_asn_type(vars->type); 1847 | } 1848 | 1849 | __get_label_iid((char *) str_buf, &tag, &iid, getlabel_flag); 1850 | 1851 | if (_debug_level) 1852 | printf("netsnmp_getnext: filling response: %s:%s\n", tag, iid); 1853 | 1854 | py_netsnmp_attr_set_string(varbind, "tag", tag, STRLEN(tag)); 1855 | py_netsnmp_attr_set_string(varbind, "iid", iid, STRLEN(iid)); 1856 | 1857 | __get_type_str(type, type_str); 1858 | 1859 | py_netsnmp_attr_set_string(varbind, "type", type_str, 1860 | strlen(type_str)); 1861 | 1862 | len = __snprint_value((char *) str_buf, sizeof(str_buf), 1863 | vars, tp, type, sprintval_flag); 1864 | str_buf[len] = '\0'; 1865 | 1866 | py_netsnmp_attr_set_bytes(varbind, "val", (char *) str_buf, len); 1867 | 1868 | /* save in return tuple as well */ 1869 | if ((type == SNMP_ENDOFMIBVIEW) || 1870 | (type == SNMP_NOSUCHOBJECT) || 1871 | (type == SNMP_NOSUCHINSTANCE)) { 1872 | /* Translate error to None */ 1873 | PyTuple_SetItem(val_tuple, varlist_ind, 1874 | Py_BuildValue("")); 1875 | } else { 1876 | PyTuple_SetItem(val_tuple, varlist_ind, 1877 | PyBytes_FromStringAndSize(str_buf, len)); 1878 | } 1879 | Py_DECREF(varbind); 1880 | } else { 1881 | printf("netsnmp_getnext: bad varbind (%d)\n", varlist_ind); 1882 | Py_XDECREF(varbind); 1883 | } 1884 | } 1885 | 1886 | /* Reset the library's behavior for numeric/symbolic OID's. */ 1887 | netsnmp_ds_set_int(NETSNMP_DS_LIBRARY_ID, 1888 | NETSNMP_DS_LIB_OID_OUTPUT_FORMAT, 1889 | old_format); 1890 | 1891 | if (response) snmp_free_pdu(response); 1892 | } 1893 | 1894 | done: 1895 | SAFE_FREE(oid_arr); 1896 | return (val_tuple ? val_tuple : Py_BuildValue("")); 1897 | } 1898 | 1899 | static PyObject * 1900 | netsnmp_walk(PyObject *self, PyObject *args) 1901 | { 1902 | PyObject *session; 1903 | PyObject *varlist; 1904 | PyObject *varlist_iter; 1905 | PyObject *varbind; 1906 | PyObject *val_tuple = NULL; 1907 | PyObject *varbinds = NULL; 1908 | int varlist_len = 0; 1909 | int varlist_ind; 1910 | netsnmp_session *ss; 1911 | netsnmp_pdu *pdu, *response; 1912 | netsnmp_pdu *newpdu; 1913 | netsnmp_variable_list *vars, *oldvars; 1914 | struct tree *tp; 1915 | int len; 1916 | oid **oid_arr = NULL; 1917 | int *oid_arr_len = NULL; 1918 | oid **oid_arr_broken_check = NULL; 1919 | int *oid_arr_broken_check_len = NULL; 1920 | int type; 1921 | char type_str[MAX_TYPE_NAME_LEN]; 1922 | int status; 1923 | u_char str_buf[STR_BUF_SIZE], *str_bufp = str_buf; 1924 | size_t str_buf_len = sizeof(str_buf); 1925 | size_t out_len = 0; 1926 | int buf_over = 0; 1927 | char *tag; 1928 | char *iid = NULL; 1929 | int getlabel_flag = NO_FLAGS; 1930 | int sprintval_flag = USE_BASIC; 1931 | int verbose = py_netsnmp_verbose(); 1932 | int old_format; 1933 | int best_guess; 1934 | int retry_nosuch; 1935 | int err_ind; 1936 | int err_num; 1937 | char err_str[STR_BUF_SIZE]; 1938 | int notdone = 1; 1939 | int result_count = 0; 1940 | char *tmpstr; 1941 | Py_ssize_t tmplen; 1942 | 1943 | if (args) { 1944 | 1945 | if (!PyArg_ParseTuple(args, "OO", &session, &varlist)) { 1946 | goto done; 1947 | } 1948 | 1949 | if (!varlist) { 1950 | goto done; 1951 | } 1952 | 1953 | if ((varbinds = PyObject_GetAttrString(varlist, "varbinds")) == NULL) { 1954 | goto done; 1955 | } 1956 | ss = (SnmpSession *)py_netsnmp_attr_void_ptr(session, "sess_ptr"); 1957 | 1958 | if (py_netsnmp_attr_string(session, "ErrorStr", &tmpstr, &tmplen) < 0) { 1959 | goto done; 1960 | } 1961 | memcpy(&err_str, tmpstr, tmplen); 1962 | err_num = py_netsnmp_attr_long(session, "ErrorNum"); 1963 | err_ind = py_netsnmp_attr_long(session, "ErrorInd"); 1964 | 1965 | if (py_netsnmp_attr_long(session, "UseLongNames")) 1966 | getlabel_flag |= USE_LONG_NAMES; 1967 | if (py_netsnmp_attr_long(session, "UseNumeric")) 1968 | getlabel_flag |= USE_NUMERIC_OIDS; 1969 | if (py_netsnmp_attr_long(session, "UseEnums")) 1970 | sprintval_flag = USE_ENUMS; 1971 | if (py_netsnmp_attr_long(session, "UseSprintValue")) 1972 | sprintval_flag = USE_SPRINT_VALUE; 1973 | best_guess = py_netsnmp_attr_long(session, "BestGuess"); 1974 | retry_nosuch = py_netsnmp_attr_long(session, "RetryNoSuch"); 1975 | 1976 | pdu = snmp_pdu_create(SNMP_MSG_GETNEXT); 1977 | 1978 | /* we need an initial count for memory allocation */ 1979 | varlist_iter = PyObject_GetIter(varlist); 1980 | varlist_len = 0; 1981 | while (varlist_iter && (varbind = PyIter_Next(varlist_iter))) { 1982 | varlist_len++; 1983 | } 1984 | Py_DECREF(varlist_iter); 1985 | 1986 | oid_arr_len = calloc(varlist_len, sizeof(int)); 1987 | oid_arr_broken_check_len = calloc(varlist_len, sizeof(int)); 1988 | 1989 | oid_arr = calloc(varlist_len, sizeof(oid *)); 1990 | oid_arr_broken_check = calloc(varlist_len, sizeof(oid *)); 1991 | 1992 | for(varlist_ind = 0; varlist_ind < varlist_len; varlist_ind++) { 1993 | 1994 | oid_arr[varlist_ind] = calloc(MAX_OID_LEN, sizeof(oid)); 1995 | oid_arr_broken_check[varlist_ind] = calloc(MAX_OID_LEN, sizeof(oid)); 1996 | 1997 | oid_arr_len[varlist_ind] = MAX_OID_LEN; 1998 | oid_arr_broken_check_len[varlist_ind] = MAX_OID_LEN; 1999 | } 2000 | 2001 | /* get the initial starting oids*/ 2002 | varlist_iter = PyObject_GetIter(varlist); 2003 | varlist_ind = 0; 2004 | while (varlist_iter && (varbind = PyIter_Next(varlist_iter))) { 2005 | 2006 | if (py_netsnmp_attr_string(varbind, "tag", &tag, NULL) < 0 || 2007 | py_netsnmp_attr_string(varbind, "iid", &iid, NULL) < 0) 2008 | { 2009 | oid_arr_len[varlist_ind] = 0; 2010 | } else { 2011 | tp = __tag2oid(tag, iid, 2012 | oid_arr[varlist_ind], &oid_arr_len[varlist_ind], 2013 | NULL, best_guess); 2014 | } 2015 | 2016 | if (_debug_level) 2017 | printf("netsnmp_walk: filling request: %s:%s:%d:%d\n", 2018 | tag, iid, oid_arr_len[varlist_ind],best_guess); 2019 | 2020 | if (oid_arr_len[varlist_ind]) { 2021 | snmp_add_null_var(pdu, oid_arr[varlist_ind], oid_arr_len[varlist_ind]); 2022 | } else { 2023 | if (verbose) 2024 | printf("error: walk: unknown object ID (%s)", 2025 | (tag ? tag : "")); 2026 | snmp_free_pdu(pdu); 2027 | Py_DECREF(varbind); 2028 | goto done; 2029 | } 2030 | /* release reference when done */ 2031 | Py_DECREF(varbind); 2032 | varlist_ind++; 2033 | } 2034 | 2035 | if (varlist_iter) 2036 | Py_DECREF(varlist_iter); 2037 | 2038 | if (PyErr_Occurred()) { 2039 | /* propagate error */ 2040 | if (verbose) 2041 | printf("error: walk: unknown python error (varlist)"); 2042 | snmp_free_pdu(pdu); 2043 | goto done; 2044 | } 2045 | 2046 | /* pre-allocate the return tuples */ 2047 | val_tuple = PyTuple_New(0); 2048 | 2049 | if (!val_tuple) { 2050 | /* propagate error */ 2051 | if (verbose) 2052 | printf("error: walk: couldn't allocate a new value tuple"); 2053 | snmp_free_pdu(pdu); 2054 | goto done; 2055 | } 2056 | 2057 | /* 2058 | ** Set up for numeric or full OID's, if necessary. Save the old 2059 | ** output format so that it can be restored when we finish -- this 2060 | ** is a library-wide global, and has to be set/restored for each 2061 | ** session. 2062 | */ 2063 | old_format = netsnmp_ds_get_int(NETSNMP_DS_LIBRARY_ID, 2064 | NETSNMP_DS_LIB_OID_OUTPUT_FORMAT); 2065 | 2066 | if (py_netsnmp_attr_long(session, "UseLongNames")) { 2067 | getlabel_flag |= USE_LONG_NAMES; 2068 | 2069 | netsnmp_ds_set_int(NETSNMP_DS_LIBRARY_ID, 2070 | NETSNMP_DS_LIB_OID_OUTPUT_FORMAT, 2071 | NETSNMP_OID_OUTPUT_FULL); 2072 | } 2073 | 2074 | /* Setting UseNumeric forces UseLongNames on so check for UseNumeric 2075 | after UseLongNames (above) to make sure the final outcome of 2076 | NETSNMP_DS_LIB_OID_OUTPUT_FORMAT is NETSNMP_OID_OUTPUT_NUMERIC */ 2077 | if (py_netsnmp_attr_long(session, "UseNumeric")) { 2078 | getlabel_flag |= USE_LONG_NAMES; 2079 | getlabel_flag |= USE_NUMERIC_OIDS; 2080 | 2081 | netsnmp_ds_set_int(NETSNMP_DS_LIBRARY_ID, 2082 | NETSNMP_DS_LIB_OID_OUTPUT_FORMAT, 2083 | NETSNMP_OID_OUTPUT_NUMERIC); 2084 | } 2085 | 2086 | /* delete the existing varbinds that we'll replace */ 2087 | PySequence_DelSlice(varbinds, 0, PySequence_Length(varbinds)); 2088 | 2089 | if (PyErr_Occurred()) { 2090 | /* propagate error */ 2091 | if (verbose) 2092 | printf("error: walk: deleting old varbinds failed\n"); 2093 | snmp_free_pdu(pdu); 2094 | goto done; 2095 | } 2096 | 2097 | /* save the starting OID */ 2098 | 2099 | for(vars = pdu->variables, varlist_ind = 0; 2100 | vars != NULL; 2101 | vars = vars->next_variable, varlist_ind++) { 2102 | 2103 | oid_arr_broken_check[varlist_ind] = calloc(MAX_OID_LEN, sizeof(oid)); 2104 | 2105 | oid_arr_broken_check_len[varlist_ind] = vars->name_length; 2106 | memcpy(oid_arr_broken_check[varlist_ind], 2107 | vars->name, vars->name_length * sizeof(oid)); 2108 | } 2109 | 2110 | while(notdone) { 2111 | 2112 | status = __send_sync_pdu(ss, pdu, &response, retry_nosuch, 2113 | err_str, &err_num, &err_ind); 2114 | __py_netsnmp_update_session_errors(session, err_str, err_num, err_ind); 2115 | 2116 | if (!response || !response->variables || 2117 | status != STAT_SUCCESS || 2118 | response->errstat != SNMP_ERR_NOERROR) { 2119 | notdone = 0; 2120 | } else { 2121 | newpdu = snmp_pdu_create(SNMP_MSG_GETNEXT); 2122 | 2123 | for(vars = (response ? response->variables : NULL), 2124 | varlist_ind = 0, 2125 | oldvars = (pdu ? pdu->variables : NULL); 2126 | vars && (varlist_ind < varlist_len); 2127 | vars = vars->next_variable, varlist_ind++, 2128 | oldvars = (oldvars ? oldvars->next_variable : NULL)) { 2129 | 2130 | if ((vars->name_length < oid_arr_len[varlist_ind]) || 2131 | (memcmp(oid_arr[varlist_ind], vars->name, 2132 | oid_arr_len[varlist_ind] * sizeof(oid)) != 0)) { 2133 | notdone = 0; 2134 | break; 2135 | } 2136 | 2137 | if ((vars->type == SNMP_ENDOFMIBVIEW) || 2138 | (vars->type == SNMP_NOSUCHOBJECT) || 2139 | (vars->type == SNMP_NOSUCHINSTANCE)) { 2140 | notdone = 0; 2141 | break; 2142 | } 2143 | 2144 | if (snmp_oid_compare(vars->name, vars->name_length, 2145 | oid_arr_broken_check[varlist_ind], 2146 | oid_arr_broken_check_len[varlist_ind]) <= 0) { 2147 | /* The agent responded with an illegal response 2148 | as the returning OID was lexogragically less 2149 | then or equal to the requested OID... 2150 | We need to give up here because an infite 2151 | loop will result otherwise. 2152 | 2153 | XXX: this really should be an option to 2154 | continue like the -Cc option to the snmpwalk 2155 | application. 2156 | */ 2157 | notdone = 0; 2158 | break; 2159 | } 2160 | 2161 | varbind = py_netsnmp_construct_varbind(); 2162 | 2163 | if (PyObject_HasAttrString(varbind, "tag")) { 2164 | str_buf[0] = '.'; 2165 | str_buf[1] = '\0'; 2166 | out_len = 0; 2167 | tp = netsnmp_sprint_realloc_objid_tree(&str_bufp, &str_buf_len, 2168 | &out_len, 0, &buf_over, 2169 | vars->name,vars->name_length); 2170 | str_buf[sizeof(str_buf)-1] = '\0'; 2171 | 2172 | if (__is_leaf(tp)) { 2173 | type = (tp->type ? tp->type : tp->parent->type); 2174 | getlabel_flag &= ~NON_LEAF_NAME; 2175 | } else { 2176 | getlabel_flag |= NON_LEAF_NAME; 2177 | type = __translate_asn_type(vars->type); 2178 | } 2179 | 2180 | __get_label_iid((char *) str_buf, &tag, &iid, getlabel_flag); 2181 | 2182 | if (_debug_level) printf("netsnmp_walk: filling response: %s:%s\n", tag, iid); 2183 | 2184 | py_netsnmp_attr_set_string(varbind, "tag", tag, STRLEN(tag)); 2185 | py_netsnmp_attr_set_string(varbind, "iid", iid, STRLEN(iid)); 2186 | 2187 | __get_type_str(type, type_str); 2188 | 2189 | py_netsnmp_attr_set_string(varbind, "type", type_str, 2190 | strlen(type_str)); 2191 | 2192 | len = __snprint_value((char *) str_buf,sizeof(str_buf), 2193 | vars,tp,type,sprintval_flag); 2194 | str_buf[len] = '\0'; 2195 | 2196 | py_netsnmp_attr_set_bytes(varbind, "val", (char *) str_buf, 2197 | len); 2198 | 2199 | /* push the varbind onto the return varbinds */ 2200 | PyList_Append(varbinds, varbind); 2201 | 2202 | /* save in return tuple as well */ 2203 | /* save in return tuple as well - steals ref */ 2204 | _PyTuple_Resize(&val_tuple, result_count+1); 2205 | PyTuple_SetItem(val_tuple, result_count++, 2206 | PyBytes_FromStringAndSize(str_buf, len)); 2207 | } else { 2208 | /* Return None for this variable. */ 2209 | _PyTuple_Resize(&val_tuple, result_count+1); 2210 | PyTuple_SetItem(val_tuple, result_count++, Py_BuildValue("")); 2211 | printf("netsnmp_walk: bad varbind (%d)\n", varlist_ind); 2212 | } 2213 | Py_XDECREF(varbind); 2214 | 2215 | memcpy(oid_arr_broken_check[varlist_ind], vars->name, 2216 | sizeof(oid) * vars->name_length); 2217 | oid_arr_broken_check_len[varlist_ind] = vars->name_length; 2218 | 2219 | snmp_add_null_var(newpdu, vars->name, 2220 | vars->name_length); 2221 | } 2222 | pdu = newpdu; 2223 | } 2224 | if (response) 2225 | snmp_free_pdu(response); 2226 | } 2227 | 2228 | /* Reset the library's behavior for numeric/symbolic OID's. */ 2229 | netsnmp_ds_set_int(NETSNMP_DS_LIBRARY_ID, 2230 | NETSNMP_DS_LIB_OID_OUTPUT_FORMAT, 2231 | old_format); 2232 | 2233 | 2234 | if (PyErr_Occurred()) { 2235 | /* propagate error */ 2236 | if (verbose) 2237 | printf("error: walk response processing: unknown python error"); 2238 | Py_DECREF(val_tuple); 2239 | } 2240 | } 2241 | 2242 | done: 2243 | Py_XDECREF(varbinds); 2244 | SAFE_FREE(oid_arr_len); 2245 | SAFE_FREE(oid_arr_broken_check_len); 2246 | for(varlist_ind = 0; varlist_ind < varlist_len; varlist_ind ++) { 2247 | SAFE_FREE(oid_arr[varlist_ind]); 2248 | SAFE_FREE(oid_arr_broken_check[varlist_ind]); 2249 | } 2250 | SAFE_FREE(oid_arr); 2251 | SAFE_FREE(oid_arr_broken_check); 2252 | return (val_tuple ? val_tuple : Py_BuildValue("")); 2253 | } 2254 | 2255 | 2256 | static PyObject * 2257 | netsnmp_getbulk(PyObject *self, PyObject *args) 2258 | { 2259 | int nonrepeaters; 2260 | int maxrepetitions; 2261 | PyObject *session; 2262 | PyObject *varlist; 2263 | PyObject *varbinds; 2264 | PyObject *varbind; 2265 | PyObject *varbinds_iter; 2266 | PyObject *val_tuple = NULL; 2267 | int varbind_ind; 2268 | netsnmp_session *ss; 2269 | netsnmp_pdu *pdu, *response; 2270 | netsnmp_variable_list *vars; 2271 | struct tree *tp; 2272 | int len; 2273 | oid *oid_arr; 2274 | int oid_arr_len = MAX_OID_LEN; 2275 | int type; 2276 | char type_str[MAX_TYPE_NAME_LEN]; 2277 | u_char str_buf[STR_BUF_SIZE], *str_bufp = str_buf; 2278 | size_t str_buf_len = sizeof(str_buf); 2279 | size_t out_len = 0; 2280 | int buf_over = 0; 2281 | char *tag; 2282 | char *iid; 2283 | int getlabel_flag = NO_FLAGS; 2284 | int sprintval_flag = USE_BASIC; 2285 | int verbose = py_netsnmp_verbose(); 2286 | int old_format; 2287 | int best_guess; 2288 | int retry_nosuch; 2289 | int err_ind; 2290 | int err_num; 2291 | char err_str[STR_BUF_SIZE]; 2292 | char *tmpstr; 2293 | Py_ssize_t tmplen; 2294 | 2295 | oid_arr = calloc(MAX_OID_LEN, sizeof(oid)); 2296 | 2297 | if (oid_arr && args) { 2298 | 2299 | if (!PyArg_ParseTuple(args, "OiiO", &session, &nonrepeaters, 2300 | &maxrepetitions, &varlist)) { 2301 | goto done; 2302 | } 2303 | 2304 | if (varlist && (varbinds = PyObject_GetAttrString(varlist, "varbinds"))) { 2305 | 2306 | ss = (SnmpSession *)py_netsnmp_attr_void_ptr(session, "sess_ptr"); 2307 | 2308 | if (py_netsnmp_attr_string(session, "ErrorStr", &tmpstr, &tmplen) < 0) { 2309 | goto done; 2310 | } 2311 | memcpy(&err_str, tmpstr, tmplen); 2312 | err_num = py_netsnmp_attr_long(session, "ErrorNum"); 2313 | err_ind = py_netsnmp_attr_long(session, "ErrorInd"); 2314 | 2315 | if (py_netsnmp_attr_long(session, "UseLongNames")) 2316 | getlabel_flag |= USE_LONG_NAMES; 2317 | if (py_netsnmp_attr_long(session, "UseNumeric")) 2318 | getlabel_flag |= USE_NUMERIC_OIDS; 2319 | if (py_netsnmp_attr_long(session, "UseEnums")) 2320 | sprintval_flag = USE_ENUMS; 2321 | if (py_netsnmp_attr_long(session, "UseSprintValue")) 2322 | sprintval_flag = USE_SPRINT_VALUE; 2323 | best_guess = py_netsnmp_attr_long(session, "BestGuess"); 2324 | retry_nosuch = py_netsnmp_attr_long(session, "RetryNoSuch"); 2325 | 2326 | pdu = snmp_pdu_create(SNMP_MSG_GETBULK); 2327 | 2328 | pdu->errstat = nonrepeaters; 2329 | pdu->errindex = maxrepetitions; 2330 | 2331 | varbinds_iter = PyObject_GetIter(varbinds); 2332 | 2333 | while (varbinds_iter && (varbind = PyIter_Next(varbinds_iter))) { 2334 | if (py_netsnmp_attr_string(varbind, "tag", &tag, NULL) < 0 || 2335 | py_netsnmp_attr_string(varbind, "iid", &iid, NULL) < 0) 2336 | { 2337 | oid_arr_len = 0; 2338 | } else { 2339 | tp = __tag2oid(tag, iid, oid_arr, &oid_arr_len, NULL, best_guess); 2340 | } 2341 | 2342 | if (oid_arr_len) { 2343 | snmp_add_null_var(pdu, oid_arr, oid_arr_len); 2344 | } else { 2345 | if (verbose) 2346 | printf("error: get: unknown object ID (%s)", 2347 | (tag ? tag : "")); 2348 | snmp_free_pdu(pdu); 2349 | Py_DECREF(varbind); 2350 | goto done; 2351 | } 2352 | /* release reference when done */ 2353 | Py_DECREF(varbind); 2354 | } 2355 | 2356 | Py_DECREF(varbinds_iter); 2357 | 2358 | if (PyErr_Occurred()) { 2359 | /* propagate error */ 2360 | if (verbose) 2361 | printf("error: get: unknown python error"); 2362 | snmp_free_pdu(pdu); 2363 | goto done; 2364 | } 2365 | 2366 | __send_sync_pdu(ss, pdu, &response, retry_nosuch, err_str, &err_num, 2367 | &err_ind); 2368 | __py_netsnmp_update_session_errors(session, err_str, err_num, err_ind); 2369 | 2370 | /* 2371 | ** Set up for numeric or full OID's, if necessary. Save the old 2372 | ** output format so that it can be restored when we finish -- this 2373 | ** is a library-wide global, and has to be set/restored for each 2374 | ** session. 2375 | */ 2376 | old_format = netsnmp_ds_get_int(NETSNMP_DS_LIBRARY_ID, 2377 | NETSNMP_DS_LIB_OID_OUTPUT_FORMAT); 2378 | 2379 | if (py_netsnmp_attr_long(session, "UseLongNames")) { 2380 | getlabel_flag |= USE_LONG_NAMES; 2381 | 2382 | netsnmp_ds_set_int(NETSNMP_DS_LIBRARY_ID, 2383 | NETSNMP_DS_LIB_OID_OUTPUT_FORMAT, 2384 | NETSNMP_OID_OUTPUT_FULL); 2385 | } 2386 | /* Setting UseNumeric forces UseLongNames on so check for UseNumeric 2387 | after UseLongNames (above) to make sure the final outcome of 2388 | NETSNMP_DS_LIB_OID_OUTPUT_FORMAT is NETSNMP_OID_OUTPUT_NUMERIC */ 2389 | if (py_netsnmp_attr_long(session, "UseNumeric")) { 2390 | getlabel_flag |= USE_LONG_NAMES; 2391 | getlabel_flag |= USE_NUMERIC_OIDS; 2392 | 2393 | netsnmp_ds_set_int(NETSNMP_DS_LIBRARY_ID, 2394 | NETSNMP_DS_LIB_OID_OUTPUT_FORMAT, 2395 | NETSNMP_OID_OUTPUT_NUMERIC); 2396 | } 2397 | 2398 | /* create tuple in which to return results */ 2399 | val_tuple = PyTuple_New(0); 2400 | 2401 | if(response && response->variables) { 2402 | /* clear varlist to receive response varbinds*/ 2403 | PySequence_DelSlice(varbinds, 0, PySequence_Length(varbinds)); 2404 | 2405 | if (PyErr_Occurred()) { 2406 | /* propagate error */ 2407 | if (verbose) 2408 | printf("error: bulk: deleting old varbinds failed\n"); 2409 | snmp_free_pdu(pdu); 2410 | goto done; 2411 | } 2412 | 2413 | for(vars = response->variables, varbind_ind=0; 2414 | vars; 2415 | vars = vars->next_variable, varbind_ind++) { 2416 | 2417 | varbind = py_netsnmp_construct_varbind(); 2418 | 2419 | if (PyObject_HasAttrString(varbind, "tag")) { 2420 | *str_buf = '.'; 2421 | *(str_buf+1) = '\0'; 2422 | out_len = 0; 2423 | buf_over = 0; 2424 | str_bufp = str_buf; 2425 | tp = netsnmp_sprint_realloc_objid_tree(&str_bufp, &str_buf_len, 2426 | &out_len, 0, &buf_over, 2427 | vars->name,vars->name_length); 2428 | str_buf[sizeof(str_buf)-1] = '\0'; 2429 | if (__is_leaf(tp)) { 2430 | type = (tp->type ? tp->type : tp->parent->type); 2431 | getlabel_flag &= ~NON_LEAF_NAME; 2432 | } else { 2433 | getlabel_flag |= NON_LEAF_NAME; 2434 | type = __translate_asn_type(vars->type); 2435 | } 2436 | 2437 | __get_label_iid((char *) str_buf, &tag, &iid, getlabel_flag); 2438 | 2439 | py_netsnmp_attr_set_string(varbind, "tag", tag, STRLEN(tag)); 2440 | py_netsnmp_attr_set_string(varbind, "iid", iid, STRLEN(iid)); 2441 | 2442 | __get_type_str(type, type_str); 2443 | 2444 | py_netsnmp_attr_set_string(varbind, "type", type_str, 2445 | strlen(type_str)); 2446 | 2447 | len = __snprint_value((char *) str_buf, sizeof(str_buf), 2448 | vars, tp, type, sprintval_flag); 2449 | str_buf[len] = '\0'; 2450 | 2451 | py_netsnmp_attr_set_bytes(varbind, "val", (char *) str_buf, len); 2452 | 2453 | /* push varbind onto varbinds */ 2454 | PyList_Append(varbinds, varbind); 2455 | 2456 | /* save in return tuple as well - steals ref */ 2457 | _PyTuple_Resize(&val_tuple, varbind_ind+1); 2458 | PyTuple_SetItem(val_tuple, varbind_ind, 2459 | PyBytes_FromStringAndSize(str_buf, len)); 2460 | 2461 | Py_DECREF(varbind); 2462 | 2463 | } else { 2464 | PyObject *none = Py_BuildValue(""); /* new ref */ 2465 | /* not sure why making vabind failed - should not happen*/ 2466 | PyList_Append(varbinds, none); /* increments ref */ 2467 | /* Return None for this variable. */ 2468 | PyTuple_SetItem(val_tuple, varbind_ind, none); /* steals ref */ 2469 | Py_XDECREF(varbind); 2470 | } 2471 | } 2472 | } 2473 | 2474 | /* Reset the library's behavior for numeric/symbolic OID's. */ 2475 | netsnmp_ds_set_int(NETSNMP_DS_LIBRARY_ID, 2476 | NETSNMP_DS_LIB_OID_OUTPUT_FORMAT, 2477 | old_format); 2478 | 2479 | if (response) snmp_free_pdu(response); 2480 | 2481 | Py_DECREF(varbinds); 2482 | 2483 | } 2484 | 2485 | if (PyErr_Occurred()) { 2486 | /* propagate error */ 2487 | if (verbose) 2488 | printf("error: getbulk response processing: unknown python error"); 2489 | if (val_tuple) 2490 | Py_DECREF(val_tuple); 2491 | val_tuple = NULL; 2492 | } 2493 | } 2494 | 2495 | done: 2496 | SAFE_FREE(oid_arr); 2497 | return (val_tuple ? val_tuple : Py_BuildValue("")); 2498 | } 2499 | 2500 | static PyObject * 2501 | netsnmp_set(PyObject *self, PyObject *args) 2502 | { 2503 | PyObject *session; 2504 | PyObject *varlist; 2505 | PyObject *varbind; 2506 | PyObject *ret = NULL; 2507 | netsnmp_session *ss; 2508 | netsnmp_pdu *pdu, *response; 2509 | struct tree *tp; 2510 | char *tag; 2511 | char *iid; 2512 | char *val; 2513 | char *type_str; 2514 | int len; 2515 | oid *oid_arr; 2516 | int oid_arr_len = MAX_OID_LEN; 2517 | int type; 2518 | u_char tmp_val_str[STR_BUF_SIZE]; 2519 | int use_enums; 2520 | struct enum_list *ep; 2521 | int verbose = py_netsnmp_verbose(); 2522 | int best_guess; 2523 | int status; 2524 | int err_ind; 2525 | int err_num; 2526 | char err_str[STR_BUF_SIZE]; 2527 | char *tmpstr; 2528 | Py_ssize_t tmplen; 2529 | 2530 | oid_arr = calloc(MAX_OID_LEN, sizeof(oid)); 2531 | 2532 | if (oid_arr && args) { 2533 | 2534 | if (!PyArg_ParseTuple(args, "OO", &session, &varlist)) { 2535 | goto done; 2536 | } 2537 | 2538 | ss = (SnmpSession *)py_netsnmp_attr_void_ptr(session, "sess_ptr"); 2539 | 2540 | /* PyObject_SetAttrString(); */ 2541 | if (py_netsnmp_attr_string(session, "ErrorStr", &tmpstr, &tmplen) < 0) { 2542 | goto done; 2543 | } 2544 | 2545 | use_enums = py_netsnmp_attr_long(session, "UseEnums"); 2546 | 2547 | best_guess = py_netsnmp_attr_long(session, "BestGuess"); 2548 | 2549 | pdu = snmp_pdu_create(SNMP_MSG_SET); 2550 | 2551 | if (varlist) { 2552 | PyObject *varlist_iter = PyObject_GetIter(varlist); 2553 | 2554 | while (varlist_iter && (varbind = PyIter_Next(varlist_iter))) { 2555 | if (py_netsnmp_attr_string(varbind, "tag", &tag, NULL) < 0 || 2556 | py_netsnmp_attr_string(varbind, "iid", &iid, NULL) < 0) 2557 | { 2558 | oid_arr_len = 0; 2559 | } else { 2560 | tp = __tag2oid(tag, iid, oid_arr, &oid_arr_len, &type, best_guess); 2561 | } 2562 | 2563 | if (oid_arr_len==0) { 2564 | if (verbose) 2565 | printf("error: set: unknown object ID (%s)", 2566 | (tag?tag:"")); 2567 | snmp_free_pdu(pdu); 2568 | goto done; 2569 | } 2570 | 2571 | if (type == TYPE_UNKNOWN) { 2572 | if (py_netsnmp_attr_string(varbind, "type", &type_str, NULL) < 0) { 2573 | snmp_free_pdu(pdu); 2574 | goto done; 2575 | } 2576 | type = __translate_appl_type(type_str); 2577 | if (type == TYPE_UNKNOWN) { 2578 | if (verbose) 2579 | printf("error: set: no type found for object"); 2580 | snmp_free_pdu(pdu); 2581 | goto done; 2582 | } 2583 | } 2584 | 2585 | if (py_netsnmp_attr_bytes(varbind, "val", &val, &tmplen) < 0) { 2586 | snmp_free_pdu(pdu); 2587 | goto done; 2588 | } 2589 | memset(tmp_val_str, 0, sizeof(tmp_val_str)); 2590 | if ( tmplen >= sizeof(tmp_val_str)) { 2591 | tmplen = sizeof(tmp_val_str)-1; 2592 | } 2593 | memcpy(tmp_val_str, val, tmplen); 2594 | if (type==TYPE_INTEGER && use_enums && tp && tp->enums) { 2595 | for(ep = tp->enums; ep; ep = ep->next) { 2596 | if (val && !strcmp(ep->label, val)) { 2597 | snprintf((char *) tmp_val_str, sizeof(tmp_val_str), "%d", 2598 | ep->value); 2599 | break; 2600 | } 2601 | } 2602 | } 2603 | len = (int)tmplen; 2604 | status = __add_var_val_str(pdu, oid_arr, oid_arr_len, 2605 | (char *) tmp_val_str, len, type); 2606 | 2607 | if (verbose && status == FAILURE) 2608 | printf("error: set: adding variable/value to PDU"); 2609 | 2610 | /* release reference when done */ 2611 | Py_DECREF(varbind); 2612 | } 2613 | 2614 | Py_DECREF(varlist_iter); 2615 | 2616 | if (PyErr_Occurred()) { 2617 | /* propagate error */ 2618 | if (verbose) 2619 | printf("error: set: unknown python error"); 2620 | snmp_free_pdu(pdu); 2621 | goto done; 2622 | } 2623 | } 2624 | 2625 | status = __send_sync_pdu(ss, pdu, &response, NO_RETRY_NOSUCH, 2626 | err_str, &err_num, &err_ind); 2627 | __py_netsnmp_update_session_errors(session, err_str, err_num, err_ind); 2628 | 2629 | if (response) snmp_free_pdu(response); 2630 | 2631 | if (status == STAT_SUCCESS) 2632 | ret = Py_BuildValue("i",1); /* success, return True */ 2633 | else 2634 | ret = Py_BuildValue("i",0); /* fail, return False */ 2635 | } 2636 | done: 2637 | Py_XDECREF(varbind); 2638 | SAFE_FREE(oid_arr); 2639 | return (ret ? ret : Py_BuildValue("")); 2640 | } 2641 | 2642 | 2643 | static PyMethodDef module_methods[] = { 2644 | {"session", netsnmp_create_session, METH_VARARGS, 2645 | "create a netsnmp session."}, 2646 | {"session_v3", netsnmp_create_session_v3, METH_VARARGS, 2647 | "create a netsnmp session."}, 2648 | {"session_tunneled", netsnmp_create_session_tunneled, METH_VARARGS, 2649 | "create a tunneled netsnmp session over tls, dtls or ssh."}, 2650 | {"delete_session", netsnmp_delete_session, METH_VARARGS, 2651 | "create a netsnmp session."}, 2652 | {"get", netsnmp_get, METH_VARARGS, 2653 | "perform an SNMP GET operation."}, 2654 | {"getnext", netsnmp_getnext, METH_VARARGS, 2655 | "perform an SNMP GETNEXT operation."}, 2656 | {"getbulk", netsnmp_getbulk, METH_VARARGS, 2657 | "perform an SNMP GETBULK operation."}, 2658 | {"set", netsnmp_set, METH_VARARGS, 2659 | "perform an SNMP SET operation."}, 2660 | {"walk", netsnmp_walk, METH_VARARGS, 2661 | "perform an SNMP WALK operation."}, 2662 | {NULL, NULL, 0, NULL} /* Sentinel */ 2663 | }; 2664 | 2665 | static int module_traverse(PyObject *m, visitproc visit, void *arg) { 2666 | Py_VISIT(((struct module_state*)PyModule_GetState(m))->error); 2667 | return 0; 2668 | } 2669 | 2670 | static int module_clear(PyObject *m) { 2671 | Py_CLEAR(((struct module_state*)PyModule_GetState(m))->error); 2672 | return 0; 2673 | } 2674 | 2675 | static struct PyModuleDef moduledef = { 2676 | PyModuleDef_HEAD_INIT, 2677 | "client_intf", 2678 | NULL, 2679 | sizeof(struct module_state), 2680 | module_methods, 2681 | NULL, 2682 | module_traverse, 2683 | module_clear, 2684 | NULL 2685 | }; 2686 | 2687 | PyMODINIT_FUNC 2688 | PyInit_client_intf(void) 2689 | { 2690 | PyObject *module = PyModule_Create(&moduledef); 2691 | if (module == NULL) 2692 | return NULL; 2693 | struct module_state *st = PyModule_GetState(module); 2694 | 2695 | st->error = PyErr_NewException("client_intf.Error", NULL, NULL); 2696 | if (st->error == NULL) { 2697 | Py_DECREF(module); 2698 | return NULL; 2699 | } 2700 | 2701 | Py_INCREF(st->error); 2702 | PyModule_AddObject(module, "Error", st->error); 2703 | 2704 | return module; 2705 | } 2706 | -------------------------------------------------------------------------------- /netsnmp/netsnmp-feature-definitions.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | netsnmp_feature_require(snprint_value) 5 | netsnmp_feature_require(enable_stderrlog) 6 | 7 | -------------------------------------------------------------------------------- /netsnmp/tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bluecmd/python3-netsnmp/28106277f18acc4f66b4621408652217204d305b/netsnmp/tests/__init__.py -------------------------------------------------------------------------------- /netsnmp/tests/snmpd.conf: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # 3 | # EXAMPLE.conf: 4 | # An example configuration file for configuring the ucd-snmp snmpd agent. 5 | # 6 | ############################################################################### 7 | # 8 | # This file is intended to only be an example. If, however, you want 9 | # to use it, it should be placed in /usr/local/etc/snmp/snmpd.conf. 10 | # When the snmpd agent starts up, this is where it will look for it. 11 | # 12 | # You might be interested in generating your own snmpd.conf file using 13 | # the "snmpconf" program (perl script) instead. It's a nice menu 14 | # based interface to writing well commented configuration files. Try it! 15 | # 16 | # Note: This file is automatically generated from EXAMPLE.conf.def. 17 | # Do NOT read the EXAMPLE.conf.def file! Instead, after you have run 18 | # configure & make, and then make sure you read the EXAMPLE.conf file 19 | # instead, as it will tailor itself to your configuration. 20 | 21 | # All lines beginning with a '#' are comments and are intended for you 22 | # to read. All other lines are configuration commands for the agent. 23 | 24 | # 25 | # PLEASE: read the snmpd.conf(5) manual page as well! 26 | # 27 | 28 | 29 | ############################################################################### 30 | # Access Control 31 | ############################################################################### 32 | 33 | # YOU SHOULD CHANGE THE "COMMUNITY" TOKEN BELOW TO A NEW KEYWORD ONLY 34 | # KNOWN AT YOUR SITE. YOU *MUST* CHANGE THE NETWORK TOKEN BELOW TO 35 | # SOMETHING REFLECTING YOUR LOCAL NETWORK ADDRESS SPACE. 36 | 37 | # By far, the most common question I get about the agent is "why won't 38 | # it work?", when really it should be "how do I configure the agent to 39 | # allow me to access it?" 40 | # 41 | # By default, the agent responds to the "public" community for read 42 | # only access, if run out of the box without any configuration file in 43 | # place. The following examples show you other ways of configuring 44 | # the agent so that you can change the community names, and give 45 | # yourself write access as well. 46 | # 47 | # The following lines change the access permissions of the agent so 48 | # that the COMMUNITY string provides read-only access to your entire 49 | # NETWORK (EG: 10.10.10.0/24), and read/write access to only the 50 | # localhost (127.0.0.1, not its real ipaddress). 51 | # 52 | # For more information, read the FAQ as well as the snmpd.conf(5) 53 | # manual page. 54 | 55 | #### 56 | # First, map the community name (COMMUNITY) into a security name 57 | # (local and mynetwork, depending on where the request is coming 58 | # from): 59 | 60 | # sec.name source community 61 | com2sec local localhost public 62 | com2sec mynetwork 192.168.1.0/24 public 63 | 64 | #### 65 | # Second, map the security names into group names: 66 | 67 | # sec.model sec.name 68 | group MyRWGroup v1 local 69 | group MyRWGroup v2c local 70 | group MyRWGroup usm local 71 | group MyRWGroup usm initial 72 | group MyROGroup v1 mynetwork 73 | group MyROGroup v2c mynetwork 74 | group MyROGroup usm mynetwork 75 | 76 | #### 77 | # Third, create a view for us to let the groups have rights to: 78 | 79 | # incl/excl subtree mask 80 | view all included .1 80 81 | 82 | #### 83 | # Finally, grant the 2 groups access to the 1 view with different 84 | # write permissions: 85 | 86 | # context sec.model sec.level match read write notif 87 | access MyROGroup "" any noauth exact all none none 88 | access MyRWGroup "" any noauth exact all all none 89 | 90 | # ----------------------------------------------------------------------------- 91 | 92 | rwuser initial priv 93 | createUser initial MD5 auth_pass DES priv_pass 94 | 95 | ############################################################################### 96 | # System contact information 97 | # 98 | 99 | # It is also possible to set the sysContact and sysLocation system 100 | # variables through the snmpd.conf file. **PLEASE NOTE** that setting 101 | # the value of these objects here makes these objects READ-ONLY 102 | # (regardless of any access control settings). Any attempt to set the 103 | # value of an object whose value is given here will fail with an error 104 | # status of notWritable. 105 | 106 | # syslocation Right here, right now. 107 | syscontact G. S. Marzot 108 | 109 | # Example output of snmpwalk: 110 | # % snmpwalk -v 1 -c public localhost system 111 | # system.sysDescr.0 = "SunOS name sun4c" 112 | # system.sysObjectID.0 = OID: enterprises.ucdavis.ucdSnmpAgent.sunos4 113 | # system.sysUpTime.0 = Timeticks: (595637548) 68 days, 22:32:55 114 | # system.sysContact.0 = "Me " 115 | # system.sysName.0 = "name" 116 | # system.sysLocation.0 = "Right here, right now." 117 | # system.sysServices.0 = 72 118 | 119 | 120 | # ----------------------------------------------------------------------------- 121 | 122 | 123 | ############################################################################### 124 | # Process checks. 125 | # 126 | # The following are examples of how to use the agent to check for 127 | # processes running on the host. The syntax looks something like: 128 | # 129 | # proc NAME [MAX=0] [MIN=0] 130 | # 131 | # NAME: the name of the process to check for. It must match 132 | # exactly (ie, http will not find httpd processes). 133 | # MAX: the maximum number allowed to be running. Defaults to 0. 134 | # MIN: the minimum number to be running. Defaults to 0. 135 | 136 | # 137 | # Examples: 138 | # 139 | 140 | # Make sure mountd is running 141 | proc mountd 142 | 143 | # Make sure there are no more than 4 ntalkds running, but 0 is ok too. 144 | proc ntalkd 4 145 | 146 | # Make sure at least one sendmail, but less than or equal to 10 are running. 147 | proc sendmail 10 1 148 | 149 | # A snmpwalk of the prTable would look something like this: 150 | # 151 | # % snmpwalk -v 1 -c public localhost .1.3.6.1.4.1.2021.2 152 | # enterprises.ucdavis.procTable.prEntry.prIndex.1 = 1 153 | # enterprises.ucdavis.procTable.prEntry.prIndex.2 = 2 154 | # enterprises.ucdavis.procTable.prEntry.prIndex.3 = 3 155 | # enterprises.ucdavis.procTable.prEntry.prNames.1 = "mountd" 156 | # enterprises.ucdavis.procTable.prEntry.prNames.2 = "ntalkd" 157 | # enterprises.ucdavis.procTable.prEntry.prNames.3 = "sendmail" 158 | # enterprises.ucdavis.procTable.prEntry.prMin.1 = 0 159 | # enterprises.ucdavis.procTable.prEntry.prMin.2 = 0 160 | # enterprises.ucdavis.procTable.prEntry.prMin.3 = 1 161 | # enterprises.ucdavis.procTable.prEntry.prMax.1 = 0 162 | # enterprises.ucdavis.procTable.prEntry.prMax.2 = 4 163 | # enterprises.ucdavis.procTable.prEntry.prMax.3 = 10 164 | # enterprises.ucdavis.procTable.prEntry.prCount.1 = 0 165 | # enterprises.ucdavis.procTable.prEntry.prCount.2 = 0 166 | # enterprises.ucdavis.procTable.prEntry.prCount.3 = 1 167 | # enterprises.ucdavis.procTable.prEntry.prErrorFlag.1 = 1 168 | # enterprises.ucdavis.procTable.prEntry.prErrorFlag.2 = 0 169 | # enterprises.ucdavis.procTable.prEntry.prErrorFlag.3 = 0 170 | # enterprises.ucdavis.procTable.prEntry.prErrMessage.1 = "No mountd process running." 171 | # enterprises.ucdavis.procTable.prEntry.prErrMessage.2 = "" 172 | # enterprises.ucdavis.procTable.prEntry.prErrMessage.3 = "" 173 | # enterprises.ucdavis.procTable.prEntry.prErrFix.1 = 0 174 | # enterprises.ucdavis.procTable.prEntry.prErrFix.2 = 0 175 | # enterprises.ucdavis.procTable.prEntry.prErrFix.3 = 0 176 | # 177 | # Note that the errorFlag for mountd is set to 1 because one is not 178 | # running (in this case an rpc.mountd is, but thats not good enough), 179 | # and the ErrMessage tells you what's wrong. The configuration 180 | # imposed in the snmpd.conf file is also shown. 181 | # 182 | # Special Case: When the min and max numbers are both 0, it assumes 183 | # you want a max of infinity and a min of 1. 184 | # 185 | 186 | 187 | # ----------------------------------------------------------------------------- 188 | 189 | 190 | ############################################################################### 191 | # Executables/scripts 192 | # 193 | 194 | # 195 | # You can also have programs run by the agent that return a single 196 | # line of output and an exit code. Here are two examples. 197 | # 198 | # exec NAME PROGRAM [ARGS ...] 199 | # 200 | # NAME: A generic name. 201 | # PROGRAM: The program to run. Include the path! 202 | # ARGS: optional arguments to be passed to the program 203 | 204 | # a simple hello world 205 | exec echotest /bin/echo hello world 206 | 207 | # Run a shell script containing: 208 | # 209 | # #!/bin/sh 210 | # echo hello world 211 | # echo hi there 212 | # exit 35 213 | # 214 | # Note: this has been specifically commented out to prevent 215 | # accidental security holes due to someone else on your system writing 216 | # a /tmp/shtest before you do. Uncomment to use it. 217 | # 218 | #exec shelltest /bin/sh /tmp/shtest 219 | 220 | # Then, 221 | # % snmpwalk -v 1 -c public localhost .1.3.6.1.4.1.2021.8 222 | # enterprises.ucdavis.extTable.extEntry.extIndex.1 = 1 223 | # enterprises.ucdavis.extTable.extEntry.extIndex.2 = 2 224 | # enterprises.ucdavis.extTable.extEntry.extNames.1 = "echotest" 225 | # enterprises.ucdavis.extTable.extEntry.extNames.2 = "shelltest" 226 | # enterprises.ucdavis.extTable.extEntry.extCommand.1 = "/bin/echo hello world" 227 | # enterprises.ucdavis.extTable.extEntry.extCommand.2 = "/bin/sh /tmp/shtest" 228 | # enterprises.ucdavis.extTable.extEntry.extResult.1 = 0 229 | # enterprises.ucdavis.extTable.extEntry.extResult.2 = 35 230 | # enterprises.ucdavis.extTable.extEntry.extOutput.1 = "hello world." 231 | # enterprises.ucdavis.extTable.extEntry.extOutput.2 = "hello world." 232 | # enterprises.ucdavis.extTable.extEntry.extErrFix.1 = 0 233 | # enterprises.ucdavis.extTable.extEntry.extErrFix.2 = 0 234 | 235 | # Note that the second line of the /tmp/shtest shell script is cut 236 | # off. Also note that the exit status of 35 was returned. 237 | 238 | # ----------------------------------------------------------------------------- 239 | 240 | 241 | ############################################################################### 242 | # disk checks 243 | # 244 | 245 | # The agent can check the amount of available disk space, and make 246 | # sure it is above a set limit. 247 | 248 | # disk PATH [MIN=DEFDISKMINIMUMSPACE] 249 | # 250 | # PATH: mount path to the disk in question. 251 | # MIN: Disks with space below this value will have the Mib's errorFlag set. 252 | # Default value = DEFDISKMINIMUMSPACE. 253 | 254 | # Check the / partition and make sure it contains at least 10 megs. 255 | 256 | disk / 10000 257 | 258 | # % snmpwalk -v 1 -c public localhost .1.3.6.1.4.1.2021.9 259 | # enterprises.ucdavis.diskTable.dskEntry.diskIndex.1 = 0 260 | # enterprises.ucdavis.diskTable.dskEntry.diskPath.1 = "/" Hex: 2F 261 | # enterprises.ucdavis.diskTable.dskEntry.diskDevice.1 = "/dev/dsk/c201d6s0" 262 | # enterprises.ucdavis.diskTable.dskEntry.diskMinimum.1 = 10000 263 | # enterprises.ucdavis.diskTable.dskEntry.diskTotal.1 = 837130 264 | # enterprises.ucdavis.diskTable.dskEntry.diskAvail.1 = 316325 265 | # enterprises.ucdavis.diskTable.dskEntry.diskUsed.1 = 437092 266 | # enterprises.ucdavis.diskTable.dskEntry.diskPercent.1 = 58 267 | # enterprises.ucdavis.diskTable.dskEntry.diskErrorFlag.1 = 0 268 | # enterprises.ucdavis.diskTable.dskEntry.diskErrorMsg.1 = "" 269 | 270 | # ----------------------------------------------------------------------------- 271 | 272 | 273 | ############################################################################### 274 | # load average checks 275 | # 276 | 277 | # load [1MAX=DEFMAXLOADAVE] [5MAX=DEFMAXLOADAVE] [15MAX=DEFMAXLOADAVE] 278 | # 279 | # 1MAX: If the 1 minute load average is above this limit at query 280 | # time, the errorFlag will be set. 281 | # 5MAX: Similar, but for 5 min average. 282 | # 15MAX: Similar, but for 15 min average. 283 | 284 | # Check for loads: 285 | load 12 14 14 286 | 287 | # % snmpwalk -v 1 -c public localhost .1.3.6.1.4.1.2021.10 288 | # enterprises.ucdavis.loadTable.laEntry.loadaveIndex.1 = 1 289 | # enterprises.ucdavis.loadTable.laEntry.loadaveIndex.2 = 2 290 | # enterprises.ucdavis.loadTable.laEntry.loadaveIndex.3 = 3 291 | # enterprises.ucdavis.loadTable.laEntry.loadaveNames.1 = "Load-1" 292 | # enterprises.ucdavis.loadTable.laEntry.loadaveNames.2 = "Load-5" 293 | # enterprises.ucdavis.loadTable.laEntry.loadaveNames.3 = "Load-15" 294 | # enterprises.ucdavis.loadTable.laEntry.loadaveLoad.1 = "0.49" Hex: 30 2E 34 39 295 | # enterprises.ucdavis.loadTable.laEntry.loadaveLoad.2 = "0.31" Hex: 30 2E 33 31 296 | # enterprises.ucdavis.loadTable.laEntry.loadaveLoad.3 = "0.26" Hex: 30 2E 32 36 297 | # enterprises.ucdavis.loadTable.laEntry.loadaveConfig.1 = "12.00" 298 | # enterprises.ucdavis.loadTable.laEntry.loadaveConfig.2 = "14.00" 299 | # enterprises.ucdavis.loadTable.laEntry.loadaveConfig.3 = "14.00" 300 | # enterprises.ucdavis.loadTable.laEntry.loadaveErrorFlag.1 = 0 301 | # enterprises.ucdavis.loadTable.laEntry.loadaveErrorFlag.2 = 0 302 | # enterprises.ucdavis.loadTable.laEntry.loadaveErrorFlag.3 = 0 303 | # enterprises.ucdavis.loadTable.laEntry.loadaveErrMessage.1 = "" 304 | # enterprises.ucdavis.loadTable.laEntry.loadaveErrMessage.2 = "" 305 | # enterprises.ucdavis.loadTable.laEntry.loadaveErrMessage.3 = "" 306 | 307 | # ----------------------------------------------------------------------------- 308 | 309 | 310 | ############################################################################### 311 | # Extensible sections. 312 | # 313 | 314 | # This alleviates the multiple line output problem found in the 315 | # previous executable mib by placing each mib in its own mib table: 316 | 317 | # Run a shell script containing: 318 | # 319 | # #!/bin/sh 320 | # echo hello world 321 | # echo hi there 322 | # exit 35 323 | # 324 | # Note: this has been specifically commented out to prevent 325 | # accidental security holes due to someone else on your system writing 326 | # a /tmp/shtest before you do. Uncomment to use it. 327 | # 328 | # exec .1.3.6.1.4.1.2021.50 shelltest /bin/sh /tmp/shtest 329 | 330 | # % snmpwalk -v 1 -c public localhost .1.3.6.1.4.1.2021.50 331 | # enterprises.ucdavis.50.1.1 = 1 332 | # enterprises.ucdavis.50.2.1 = "shelltest" 333 | # enterprises.ucdavis.50.3.1 = "/bin/sh /tmp/shtest" 334 | # enterprises.ucdavis.50.100.1 = 35 335 | # enterprises.ucdavis.50.101.1 = "hello world." 336 | # enterprises.ucdavis.50.101.2 = "hi there." 337 | # enterprises.ucdavis.50.102.1 = 0 338 | 339 | # Now the Output has grown to two lines, and we can see the 'hi 340 | # there.' output as the second line from our shell script. 341 | # 342 | # Note that you must alter the mib.txt file to be correct if you want 343 | # the .50.* outputs above to change to reasonable text descriptions. 344 | 345 | # Other ideas: 346 | # 347 | # exec .1.3.6.1.4.1.2021.51 ps /bin/ps 348 | # exec .1.3.6.1.4.1.2021.52 top /usr/local/bin/top 349 | # exec .1.3.6.1.4.1.2021.53 mailq /usr/bin/mailq 350 | 351 | # ----------------------------------------------------------------------------- 352 | 353 | 354 | ############################################################################### 355 | # Pass through control. 356 | # 357 | 358 | # Usage: 359 | # pass MIBOID EXEC-COMMAND 360 | # 361 | # This will pass total control of the mib underneath the MIBOID 362 | # portion of the mib to the EXEC-COMMAND. 363 | # 364 | # Note: You'll have to change the path of the passtest script to your 365 | # source directory or install it in the given location. 366 | # 367 | # Example: (see the script for details) 368 | # (commented out here since it requires that you place the 369 | # script in the right location. (its not installed by default)) 370 | 371 | # pass .1.3.6.1.4.1.2021.255 /bin/sh PREFIX/local/passtest 372 | 373 | # % snmpwalk -v 1 -c public localhost .1.3.6.1.4.1.2021.255 374 | # enterprises.ucdavis.255.1 = "life the universe and everything" 375 | # enterprises.ucdavis.255.2.1 = 42 376 | # enterprises.ucdavis.255.2.2 = OID: 42.42.42 377 | # enterprises.ucdavis.255.3 = Timeticks: (363136200) 42 days, 0:42:42 378 | # enterprises.ucdavis.255.4 = IpAddress: 127.0.0.1 379 | # enterprises.ucdavis.255.5 = 42 380 | # enterprises.ucdavis.255.6 = Gauge: 42 381 | # 382 | # % snmpget -v 1 -c public localhost .1.3.6.1.4.1.2021.255.5 383 | # enterprises.ucdavis.255.5 = 42 384 | # 385 | # % snmpset -v 1 -c public localhost .1.3.6.1.4.1.2021.255.1 s "New string" 386 | # enterprises.ucdavis.255.1 = "New string" 387 | # 388 | 389 | # For specific usage information, see the man/snmpd.conf.5 manual page 390 | # as well as the local/passtest script used in the above example. 391 | 392 | ############################################################################### 393 | # Subagent control 394 | # 395 | 396 | # The agent can support subagents using a number of extension mechanisms. 397 | # From the 4.2.1 release, AgentX support is being compiled in by default. 398 | # However, this is still experimental code, so should not be used on 399 | # critical production systems. 400 | # Please see the file README.agentx for more details. 401 | # 402 | # If having read, marked, learnt and inwardly digested this information, 403 | # you decide that you do wish to make use of this mechanism, simply 404 | # uncomment the following directive. 405 | # 406 | # master agentx 407 | # 408 | # I repeat - this is *NOT* regarded as suitable for front-line production 409 | # systems, though it is probably stable enough for day-to-day use. 410 | # Probably. 411 | # 412 | # No refunds will be given. 413 | 414 | 415 | ############################################################################### 416 | # Further Information 417 | # 418 | # See the snmpd.conf manual page, and the output of "snmpd -H". 419 | # MUCH more can be done with the snmpd.conf than is shown as an 420 | # example here. 421 | 422 | certSecName 10 D020A78EAF99FCE276AA9F43063A69698E4F75D1 --rfc822 423 | rwuser -s tsm hardaker@wjh.hardakers.net 424 | 425 | trustCert D020A78EAF99FCE276AA9F43063A69698E4F75D1 426 | -------------------------------------------------------------------------------- /netsnmp/tests/test.py: -------------------------------------------------------------------------------- 1 | """ Runs all unit tests for the netsnmp package. """ 2 | # Copyright (c) 2006 Andy Gross. See LICENSE.txt for details. 3 | 4 | import sys 5 | import unittest 6 | import netsnmp 7 | import time 8 | 9 | class BasicTests(unittest.TestCase): 10 | def testFuncs(self): 11 | print("") 12 | var = netsnmp.Varbind('sysDescr.0') 13 | var = netsnmp.Varbind('sysDescr','0') 14 | var = netsnmp.Varbind( 15 | '.iso.org.dod.internet.mgmt.mib-2.system.sysDescr','0') 16 | var = netsnmp.Varbind( 17 | '.iso.org.dod.internet.mgmt.mib-2.system.sysDescr.0') 18 | var = netsnmp.Varbind('.1.3.6.1.2.1.1.1.0') 19 | 20 | var = netsnmp.Varbind('.1.3.6.1.2.1.1.1','0') 21 | 22 | print("---v1 GET tests -------------------------------------\n") 23 | res = netsnmp.snmpget(var, 24 | Version = 1, 25 | DestHost='localhost', 26 | Community='public') 27 | 28 | print("v1 snmpget result: ", res, "\n") 29 | 30 | print("v1 get var: ", var.tag, var.iid, "=", var.val, '(',var.type,')') 31 | 32 | print("---v1 GETNEXT tests-------------------------------------\n") 33 | res = netsnmp.snmpgetnext(var, 34 | Version = 1, 35 | DestHost='localhost', 36 | Community='public') 37 | 38 | print("v1 snmpgetnext result: ", res, "\n") 39 | 40 | print("v1 getnext var: ", var.tag, var.iid, "=", var.val, '(',var.type,')') 41 | 42 | print("---v1 SET tests-------------------------------------\n") 43 | var = netsnmp.Varbind('sysLocation','0', 'my new location') 44 | res = netsnmp.snmpset(var, 45 | Version = 1, 46 | DestHost='localhost', 47 | Community='public') 48 | 49 | print("v1 snmpset result: ", res, "\n") 50 | 51 | print("v1 set var: ", var.tag, var.iid, "=", var.val, '(',var.type,')') 52 | 53 | print("---v1 walk tests-------------------------------------\n") 54 | vars = netsnmp.VarList(netsnmp.Varbind('system')) 55 | 56 | print("v1 varlist walk in: ") 57 | for var in vars: 58 | print(" ",var.tag, var.iid, "=", var.val, '(',var.type,')') 59 | 60 | res = netsnmp.snmpwalk(vars, 61 | Version = 1, 62 | DestHost='localhost', 63 | Community='public') 64 | print("v1 snmpwalk result: ", res, "\n") 65 | 66 | for var in vars: 67 | print(var.tag, var.iid, "=", var.val, '(',var.type,')') 68 | 69 | 70 | print("---v1 walk 2-------------------------------------\n") 71 | 72 | print("v1 varbind walk in: ") 73 | var = netsnmp.Varbind('system') 74 | res = netsnmp.snmpwalk(var, 75 | Version = 1, 76 | DestHost='localhost', 77 | Community='public') 78 | print("v1 snmpwalk result (should be = orig): ", res, "\n") 79 | 80 | print(var.tag, var.iid, "=", var.val, '(',var.type,')') 81 | 82 | print("---v1 multi-varbind test-------------------------------------\n") 83 | sess = netsnmp.Session(Version=1, 84 | DestHost='localhost', 85 | Community='public') 86 | 87 | vars = netsnmp.VarList(netsnmp.Varbind('sysUpTime', 0), 88 | netsnmp.Varbind('sysContact', 0), 89 | netsnmp.Varbind('sysLocation', 0)) 90 | vals = sess.get(vars) 91 | print("v1 sess.get result: ", vals, "\n") 92 | 93 | for var in vars: 94 | print(var.tag, var.iid, "=", var.val, '(',var.type,')') 95 | 96 | vals = sess.getnext(vars) 97 | print("v1 sess.getnext result: ", vals, "\n") 98 | 99 | for var in vars: 100 | print(var.tag, var.iid, "=", var.val, '(',var.type,')') 101 | 102 | vars = netsnmp.VarList(netsnmp.Varbind('sysUpTime'), 103 | netsnmp.Varbind('sysORLastChange'), 104 | netsnmp.Varbind('sysORID'), 105 | netsnmp.Varbind('sysORDescr'), 106 | netsnmp.Varbind('sysORUpTime')) 107 | 108 | vals = sess.getbulk(2, 8, vars) 109 | print("v1 sess.getbulk result: ", vals, "\n") 110 | 111 | for var in vars: 112 | print(var.tag, var.iid, "=", var.val, '(',var.type,')') 113 | 114 | print("---v1 set2-------------------------------------\n") 115 | 116 | vars = netsnmp.VarList( 117 | netsnmp.Varbind('sysLocation', '0', 'my newer location')) 118 | res = sess.set(vars) 119 | print("v1 sess.set result: ", res, "\n") 120 | 121 | print("---v1 walk3-------------------------------------\n") 122 | vars = netsnmp.VarList(netsnmp.Varbind('system')) 123 | 124 | vals = sess.walk(vars) 125 | print("v1 sess.walk result: ", vals, "\n") 126 | 127 | for var in vars: 128 | print(" ",var.tag, var.iid, "=", var.val, '(',var.type,')') 129 | 130 | print("---v2c get-------------------------------------\n") 131 | 132 | sess = netsnmp.Session(Version=2, 133 | DestHost='localhost', 134 | Community='public') 135 | 136 | sess.UseEnums = 1 137 | sess.UseLongNames = 1 138 | 139 | vars = netsnmp.VarList(netsnmp.Varbind('sysUpTime', 0), 140 | netsnmp.Varbind('sysContact', 0), 141 | netsnmp.Varbind('sysLocation', 0)) 142 | vals = sess.get(vars) 143 | print("v2 sess.get result: ", vals, "\n") 144 | 145 | print("---v2c getnext-------------------------------------\n") 146 | 147 | for var in vars: 148 | print(var.tag, var.iid, "=", var.val, '(',var.type,')') 149 | print("\n") 150 | 151 | vals = sess.getnext(vars) 152 | print("v2 sess.getnext result: ", vals, "\n") 153 | 154 | for var in vars: 155 | print(var.tag, var.iid, "=", var.val, '(',var.type,')') 156 | print("\n") 157 | 158 | print("---v2c getbulk-------------------------------------\n") 159 | 160 | vars = netsnmp.VarList(netsnmp.Varbind('sysUpTime'), 161 | netsnmp.Varbind('sysORLastChange'), 162 | netsnmp.Varbind('sysORID'), 163 | netsnmp.Varbind('sysORDescr'), 164 | netsnmp.Varbind('sysORUpTime')) 165 | 166 | vals = sess.getbulk(2, 8, vars) 167 | print("v2 sess.getbulk result: ", vals, "\n") 168 | 169 | for var in vars: 170 | print(var.tag, var.iid, "=", var.val, '(',var.type,')') 171 | print("\n") 172 | 173 | print("---v2c set-------------------------------------\n") 174 | 175 | vars = netsnmp.VarList( 176 | netsnmp.Varbind('sysLocation','0','my even newer location')) 177 | 178 | res = sess.set(vars) 179 | print("v2 sess.set result: ", res, "\n") 180 | 181 | print("---v2c walk-------------------------------------\n") 182 | vars = netsnmp.VarList(netsnmp.Varbind('system')) 183 | 184 | vals = sess.walk(vars) 185 | print("v2 sess.walk result: ", vals, "\n") 186 | 187 | for var in vars: 188 | print(" ",var.tag, var.iid, "=", var.val, '(',var.type,')') 189 | 190 | print("---v3 setup-------------------------------------\n") 191 | sess = netsnmp.Session(Version=3, 192 | DestHost='localhost', 193 | SecLevel='authPriv', 194 | SecName='initial', 195 | PrivPass='priv_pass', 196 | AuthPass='auth_pass') 197 | 198 | sess.UseSprintValue = 1 199 | 200 | vars = netsnmp.VarList(netsnmp.Varbind('sysUpTime', 0), 201 | netsnmp.Varbind('sysContact', 0), 202 | netsnmp.Varbind('sysLocation', 0)) 203 | print("---v3 get-------------------------------------\n") 204 | vals = sess.get(vars) 205 | print("v3 sess.get result: ", vals, "\n") 206 | 207 | for var in vars: 208 | print(var.tag, var.iid, "=", var.val, '(',var.type,')') 209 | print("\n") 210 | 211 | print("---v3 getnext-------------------------------------\n") 212 | 213 | vals = sess.getnext(vars) 214 | print("v3 sess.getnext result: ", vals, "\n") 215 | 216 | for var in vars: 217 | print(var.tag, var.iid, "=", var.val, '(',var.type,')') 218 | print("\n") 219 | 220 | vars = netsnmp.VarList(netsnmp.Varbind('sysUpTime'), 221 | netsnmp.Varbind('sysORLastChange'), 222 | netsnmp.Varbind('sysORID'), 223 | netsnmp.Varbind('sysORDescr'), 224 | netsnmp.Varbind('sysORUpTime')) 225 | 226 | vals = sess.getbulk(2, 8, vars) 227 | print("v3 sess.getbulk result: ", vals, "\n") 228 | 229 | for var in vars: 230 | print(var.tag, var.iid, "=", var.val, '(',var.type,')') 231 | print("\n") 232 | 233 | print("---v3 set-------------------------------------\n") 234 | 235 | vars = netsnmp.VarList( 236 | netsnmp.Varbind('sysLocation','0', 'my final destination')) 237 | res = sess.set(vars) 238 | print("v3 sess.set result: ", res, "\n") 239 | 240 | print("---v3 walk-------------------------------------\n") 241 | vars = netsnmp.VarList(netsnmp.Varbind('system')) 242 | 243 | vals = sess.walk(vars) 244 | print("v3 sess.walk result: ", vals, "\n") 245 | 246 | for var in vars: 247 | print(" ",var.tag, var.iid, "=", var.val, '(',var.type,')') 248 | 249 | 250 | class SetTests(unittest.TestCase): 251 | def testFuncs(self): 252 | print("\n-------------- SET Test Start ----------------------------\n") 253 | 254 | var = netsnmp.Varbind('sysUpTime','0') 255 | res = netsnmp.snmpget(var, Version = 1, DestHost='localhost', 256 | Community='public') 257 | print("uptime = ", res[0]) 258 | 259 | 260 | var = netsnmp.Varbind('versionRestartAgent','0', 1) 261 | res = netsnmp.snmpset(var, Version = 1, DestHost='localhost', 262 | Community='public') 263 | 264 | var = netsnmp.Varbind('sysUpTime','0') 265 | res = netsnmp.snmpget(var, Version = 1, DestHost='localhost', 266 | Community='public') 267 | print("uptime = ", res[0]) 268 | 269 | var = netsnmp.Varbind('nsCacheEntry') 270 | res = netsnmp.snmpgetnext(var, Version = 1, DestHost='localhost', 271 | Community='public') 272 | print("var = ", var.tag, var.iid, "=", var.val, '(',var.type,')') 273 | 274 | var.val = 65 275 | res = netsnmp.snmpset(var, Version = 1, DestHost='localhost', 276 | Community='public') 277 | res = netsnmp.snmpget(var, Version = 1, DestHost='localhost', 278 | Community='public') 279 | print("var = ", var.tag, var.iid, "=", var.val, '(',var.type,')') 280 | 281 | sess = netsnmp.Session(Version = 1, DestHost='localhost', 282 | Community='public') 283 | 284 | vars = netsnmp.VarList(netsnmp.Varbind('.1.3.6.1.6.3.12.1.2.1.2.116.101.115.116','','.1.3.6.1.6.1.1'), 285 | netsnmp.Varbind('.1.3.6.1.6.3.12.1.2.1.3.116.101.115.116','','1234'), 286 | netsnmp.Varbind('.1.3.6.1.6.3.12.1.2.1.9.116.101.115.116','', 4)) 287 | res = sess.set(vars) 288 | 289 | print("res = ", res) 290 | 291 | vars = netsnmp.VarList(netsnmp.Varbind('snmpTargetAddrTDomain'), 292 | netsnmp.Varbind('snmpTargetAddrTAddress'), 293 | netsnmp.Varbind('snmpTargetAddrRowStatus')) 294 | 295 | res = sess.getnext(vars) 296 | 297 | for var in vars: 298 | print(var.tag, var.iid, "=", var.val, '(',var.type,')') 299 | print("\n") 300 | 301 | vars = netsnmp.VarList(netsnmp.Varbind('.1.3.6.1.6.3.12.1.2.1.9.116.101.115.116','', 6)) 302 | 303 | res = sess.set(vars) 304 | 305 | print("res = ", res) 306 | 307 | vars = netsnmp.VarList(netsnmp.Varbind('snmpTargetAddrTDomain'), 308 | netsnmp.Varbind('snmpTargetAddrTAddress'), 309 | netsnmp.Varbind('snmpTargetAddrRowStatus')) 310 | 311 | res = sess.getnext(vars) 312 | 313 | for var in vars: 314 | print(var.tag, var.iid, "=", var.val, '(',var.type,')') 315 | print("\n") 316 | 317 | print("\n-------------- SET Test End ----------------------------\n") 318 | 319 | 320 | if __name__=='__main__': 321 | unittest.main() 322 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | from distutils.core import setup, Extension 2 | from setuptools import setup, Extension, find_packages 3 | import os 4 | import re 5 | import string 6 | import sys 7 | 8 | args = sys.argv[:] 9 | for arg in args: 10 | if '--basedir' in arg: 11 | basedir = string.split(arg,'=')[1] 12 | sys.argv.remove(arg) 13 | 14 | netsnmp_libs = os.popen('net-snmp-config --libs').read() 15 | libdirs = re.findall(r" -L(\S+)", netsnmp_libs) 16 | incdirs = [] 17 | libs = re.findall(r" -l(\S+)", netsnmp_libs) 18 | 19 | setup( 20 | name="python3-netsnmp", version="1.1a1", 21 | description = 'The Net-SNMP Python Interface', 22 | long_description = ''' 23 | Python3 port of the official Net-SNMP Python bindings. 24 | 25 | Maintainer: Christian Svensson 26 | 27 | Source: https://github.com/bluecmd/python3-netsnmp 28 | ''', 29 | author = 'G. S. Marzot', 30 | author_email = 'giovanni.marzot@sparta.com', 31 | url = 'http://www.net-snmp.org', 32 | license="BSD", 33 | packages=find_packages(), 34 | test_suite = "netsnmp.tests.test", 35 | 36 | ext_modules = [ 37 | Extension("netsnmp.client_intf", ["netsnmp/client_intf.c"], 38 | library_dirs=libdirs, 39 | include_dirs=incdirs, 40 | libraries=libs ) 41 | ] 42 | ) 43 | --------------------------------------------------------------------------------