1# 2# python-netsnmpagent module 3# Copyright (c) 2013-2016 Pieter Hollants <pieter@hollants.com> 4# Licensed under the GNU Lesser Public License (LGPL) version 3 5# 6# net-snmp C API abstraction module 7# 8 9import ctypes, ctypes.util 10 11c_sizet_p = ctypes.POINTER(ctypes.c_size_t) 12 13# Make libnetsnmpagent available via Python's ctypes module. We do this globally 14# so we can define C function prototypes 15 16# Workaround for net-snmp 5.4.x that has a bug with unresolved dependencies 17# in its libraries (http://sf.net/p/net-snmp/bugs/2107): load netsnmphelpers 18# first 19try: 20 libnsh = ctypes.cdll.LoadLibrary(ctypes.util.find_library("netsnmphelpers")) 21except: 22 raise Exception("Could not load libnetsnmphelpers! Is net-snmp installed?") 23try: 24 libnsa = ctypes.cdll.LoadLibrary(ctypes.util.find_library("netsnmpagent")) 25except: 26 raise Exception("Could not load libnetsnmpagent! Is net-snmp installed?") 27 28# net-snmp <5.6.x had various functions in libnetsnmphelpers.so that were moved 29# to libnetsnmpagent.so in later versions. Use netsnmp_create_watcher_info as 30# a test and define a libnsX handle to abstract from the actually used library 31# version. 32try: 33 libnsa.netsnmp_create_watcher_info 34 libnsX = libnsa 35except AttributeError: 36 libnsX = libnsh 37 38# include/net-snmp/library/callback.h 39 40# Callback major types 41SNMP_CALLBACK_LIBRARY = 0 42SNMP_CALLBACK_APPLICATION = 1 43 44# SNMP_CALLBACK_LIBRARY minor types 45SNMP_CALLBACK_LOGGING = 4 46 47SNMPCallback = ctypes.CFUNCTYPE( 48 ctypes.c_int, # result type 49 ctypes.c_int, # int majorID 50 ctypes.c_int, # int minorID 51 ctypes.c_void_p, # void *serverarg 52 ctypes.c_void_p # void *clientarg 53) 54 55for f in [ libnsa.snmp_register_callback ]: 56 f.argtypes = [ 57 ctypes.c_int, # int major 58 ctypes.c_int, # int minor 59 SNMPCallback, # SNMPCallback *new_callback 60 ctypes.c_void_p # void *arg 61 ] 62 f.restype = int 63 64# include/net-snmp/agent/agent_callbacks.h 65SNMPD_CALLBACK_INDEX_STOP = 11 66 67# include/net-snmp/library/snmp_logging.h 68LOG_EMERG = 0 # system is unusable 69LOG_ALERT = 1 # action must be taken immediately 70LOG_CRIT = 2 # critical conditions 71LOG_ERR = 3 # error conditions 72LOG_WARNING = 4 # warning conditions 73LOG_NOTICE = 5 # normal but significant condition 74LOG_INFO = 6 # informational 75LOG_DEBUG = 7 # debug-level messages 76 77class snmp_log_message(ctypes.Structure): pass 78snmp_log_message_p = ctypes.POINTER(snmp_log_message) 79snmp_log_message._fields_ = [ 80 ("priority", ctypes.c_int), 81 ("msg", ctypes.c_char_p) 82] 83 84# include/net-snmp/library/snmp_api.h 85SNMPERR_SUCCESS = 0 86 87# include/net-snmp/library/default_store.h 88NETSNMP_DS_LIBRARY_ID = 0 89NETSNMP_DS_APPLICATION_ID = 1 90NETSNMP_DS_LIB_PERSISTENT_DIR = 8 91 92for f in [ libnsa.netsnmp_ds_set_boolean ]: 93 f.argtypes = [ 94 ctypes.c_int, # int storeid 95 ctypes.c_int, # int which 96 ctypes.c_int # int value 97 ] 98 f.restype = ctypes.c_int 99 100for f in [ libnsa.netsnmp_ds_set_string ]: 101 f.argtypes = [ 102 ctypes.c_int, # int storeid 103 ctypes.c_int, # int which 104 ctypes.c_char_p # const char *value 105 ] 106 f.restype = ctypes.c_int 107 108# include/net-snmp/agent/ds_agent.h 109NETSNMP_DS_AGENT_ROLE = 1 110NETSNMP_DS_AGENT_X_SOCKET = 1 111 112# include/net-snmp/library/snmp.h 113SNMP_ERR_NOERROR = 0 114 115for f in [ libnsa.init_snmp ]: 116 f.argtypes = [ 117 ctypes.c_char_p # const char *type 118 ] 119 f.restype = None 120 121for f in [ libnsa.snmp_shutdown ]: 122 f.argtypes = [ 123 ctypes.c_char_p # const char *type 124 ] 125 f.restype = None 126 127# include/net-snmp/library/oid.h 128c_oid = ctypes.c_ulong 129c_oid_p = ctypes.POINTER(c_oid) 130 131# include/net-snmp/types.h 132MAX_OID_LEN = 128 133 134# include/net-snmp/agent/snmp_vars.h 135for f in [ libnsa.init_agent ]: 136 f.argtypes = [ 137 ctypes.c_char_p # const char *app 138 ] 139 f.restype = ctypes.c_int 140 141for f in [ libnsa.shutdown_agent ]: 142 f.argtypes = None 143 f.restype = ctypes.c_int 144 145# include/net-snmp/library/parse.h 146class tree(ctypes.Structure): pass 147 148# include/net-snmp/mib_api.h 149for f in [ libnsa.netsnmp_init_mib ]: 150 f.argtypes = None 151 f.restype = None 152 153for f in [ libnsa.read_mib ]: 154 f.argtypes = [ 155 ctypes.c_char_p # const char *filename 156 ] 157 f.restype = ctypes.POINTER(tree) 158 159for f in [ libnsa.read_objid ]: 160 f.argtypes = [ 161 ctypes.c_char_p, # const char *input 162 c_oid_p, # oid *output 163 c_sizet_p # size_t *out_len 164 ] 165 f.restype = ctypes.c_int 166 167# include/net-snmp/agent/agent_handler.h 168HANDLER_CAN_GETANDGETNEXT = 0x01 169HANDLER_CAN_SET = 0x02 170HANDLER_CAN_RONLY = HANDLER_CAN_GETANDGETNEXT 171HANDLER_CAN_RWRITE = (HANDLER_CAN_GETANDGETNEXT | \ 172 HANDLER_CAN_SET) 173 174class netsnmp_mib_handler(ctypes.Structure): pass 175netsnmp_mib_handler_p = ctypes.POINTER(netsnmp_mib_handler) 176 177class netsnmp_handler_registration(ctypes.Structure): pass 178netsnmp_handler_registration_p = ctypes.POINTER(netsnmp_handler_registration) 179netsnmp_handler_registration._fields_ = [ 180 ("handlerName", ctypes.c_char_p), 181 ("contextName", ctypes.c_char_p), 182 ("rootoid", c_oid_p), 183 ("rootoid_len", ctypes.c_size_t), 184 ("handler", netsnmp_mib_handler_p), 185 ("modes", ctypes.c_int), 186 ("priority", ctypes.c_int), 187 ("range_subid", ctypes.c_int), 188 ("range_ubound", c_oid), 189 ("timeout", ctypes.c_int), 190 ("global_cacheid", ctypes.c_int), 191 ("my_reg_void", ctypes.c_void_p) 192] 193 194for f in [ libnsa.netsnmp_create_handler_registration ]: 195 f.argtypes = [ 196 ctypes.c_char_p, # const char *name 197 ctypes.c_void_p, # Netsnmp_Node_Handler *handler_access_method 198 c_oid_p, # const oid *reg_oid 199 ctypes.c_size_t, # size_t reg_oid_len 200 ctypes.c_int # int modes 201 ] 202 f.restype = netsnmp_handler_registration_p 203 204# include/net-snmp/library/asn1.h 205ASN_INTEGER = 0x02 206ASN_OCTET_STR = 0x04 207ASN_APPLICATION = 0x40 208 209# counter64 requires some extra work because it can't be reliably represented 210# by a single C data type 211class counter64(ctypes.Structure): 212 @property 213 def value(self): 214 return self.high << 32 | self.low 215 216 @value.setter 217 def value(self, val): 218 self.high = val >> 32 219 self.low = val & 0xFFFFFFFF 220 221 def __init__(self, initval=0): 222 ctypes.Structure.__init__(self, 0, 0) 223 self.value = initval 224counter64_p = ctypes.POINTER(counter64) 225counter64._fields_ = [ 226 ("high", ctypes.c_ulong), 227 ("low", ctypes.c_ulong) 228] 229 230# include/net-snmp/library/snmp_impl.h 231ASN_IPADDRESS = ASN_APPLICATION | 0 232ASN_COUNTER = ASN_APPLICATION | 1 233ASN_UNSIGNED = ASN_APPLICATION | 2 234ASN_TIMETICKS = ASN_APPLICATION | 3 235ASN_COUNTER64 = ASN_APPLICATION | 6 236 237# include/net-snmp/agent/watcher.h 238WATCHER_FIXED_SIZE = 0x01 239WATCHER_MAX_SIZE = 0x02 240 241class netsnmp_watcher_info(ctypes.Structure): pass 242netsnmp_watcher_info_p = ctypes.POINTER(netsnmp_watcher_info) 243netsnmp_watcher_info._fields_ = [ 244 ("data", ctypes.c_void_p), 245 ("data_size", ctypes.c_size_t), 246 ("max_size", ctypes.c_size_t), 247 ("type", ctypes.c_ubyte), 248 ("flags", ctypes.c_int) 249 # net-snmp 5.7.x knows data_size_p here as well but we ignore it for 250 # backwards compatibility with net-snmp 5.4.x. 251] 252 253for f in [ libnsX.netsnmp_create_watcher_info ]: 254 f.argtypes = [ 255 ctypes.c_void_p, # void *data 256 ctypes.c_size_t, # size_t size 257 ctypes.c_ubyte, # u_char type 258 ctypes.c_int # int flags 259 ] 260 f.restype = netsnmp_watcher_info_p 261 262for f in [ libnsX.netsnmp_register_watched_instance ]: 263 f.argtypes = [ 264 netsnmp_handler_registration_p, # netsnmp_handler_registration *reginfo 265 netsnmp_watcher_info_p # netsnmp_watcher_info *winfo 266 ] 267 f.restype = ctypes.c_int 268 269for f in [ libnsX.netsnmp_register_watched_scalar ]: 270 f.argtypes = [ 271 netsnmp_handler_registration_p, # netsnmp_handler_registration *reginfo 272 netsnmp_watcher_info_p # netsnmp_watcher_info *winfo 273 ] 274 f.restype = ctypes.c_int 275 276# include/net-snmp/types.h 277class netsnmp_variable_list(ctypes.Structure): pass 278netsnmp_variable_list_p = ctypes.POINTER(netsnmp_variable_list) 279netsnmp_variable_list_p_p = ctypes.POINTER(netsnmp_variable_list_p) 280 281# include/net-snmp/varbind_api.h 282for f in [ libnsa.snmp_varlist_add_variable ]: 283 f.argtypes = [ 284 netsnmp_variable_list_p_p, # netsnmp_variable_list **varlist 285 c_oid_p, # const oid *name 286 ctypes.c_size_t, # size_t name_length 287 ctypes.c_ubyte, # u_char type 288 ctypes.c_void_p, # const void *value 289 ctypes.c_size_t # size_t len 290 ] 291 f.restype = netsnmp_variable_list_p 292 293# include/net-snmp/agent/table_data.h 294class netsnmp_table_row(ctypes.Structure): pass 295netsnmp_table_row_p = ctypes.POINTER(netsnmp_table_row) 296netsnmp_table_row._fields_ = [ 297 ("indexes", netsnmp_variable_list_p), 298 ("index_oid", c_oid_p), 299 ("index_oid_len", ctypes.c_size_t), 300 ("data", ctypes.c_void_p), 301 ("next", netsnmp_table_row_p), 302 ("prev", netsnmp_table_row_p) 303] 304 305class netsnmp_table_data(ctypes.Structure): pass 306netsnmp_table_data_p = ctypes.POINTER(netsnmp_table_data) 307netsnmp_table_data._fields_ = [ 308 ("indexes_template", netsnmp_variable_list_p), 309 ("name", ctypes.c_char_p), 310 ("flags", ctypes.c_int), 311 ("store_indexes", ctypes.c_int), 312 ("first_row", netsnmp_table_row_p), 313 ("last_row", netsnmp_table_row_p) 314] 315 316# include/net-snmp/agent/table_dataset.h 317class netsnmp_table_data_set_storage_udata(ctypes.Union): pass 318netsnmp_table_data_set_storage_udata._fields_ = [ 319 ("voidp", ctypes.c_void_p), 320 ("integer", ctypes.POINTER(ctypes.c_long)), 321 ("string", ctypes.c_char_p), 322 ("objid", c_oid_p), 323 ("bitstring", ctypes.POINTER(ctypes.c_ubyte)), 324 ("counter64", ctypes.POINTER(counter64)), 325 ("floatVal", ctypes.POINTER(ctypes.c_float)), 326 ("doubleVal", ctypes.POINTER(ctypes.c_double)) 327] 328 329class netsnmp_table_data_set_storage(ctypes.Structure): pass 330netsnmp_table_data_set_storage_p = ctypes.POINTER(netsnmp_table_data_set_storage) 331netsnmp_table_data_set_storage._fields_ = [ 332 ("column", ctypes.c_uint), 333 ("writable", ctypes.c_byte), 334 ("change_ok_fn", ctypes.c_void_p), 335 ("my_change_data", ctypes.c_void_p), 336 ("type", ctypes.c_ubyte), 337 ("data", netsnmp_table_data_set_storage_udata), 338 ("data_len", ctypes.c_ulong), 339 ("next", netsnmp_table_data_set_storage_p) 340] 341 342class netsnmp_table_data_set(ctypes.Structure): pass 343netsnmp_table_data_set_p = ctypes.POINTER(netsnmp_table_data_set) 344netsnmp_table_data_set._fields_ = [ 345 ("table", netsnmp_table_data_p), 346 ("default_row", netsnmp_table_data_set_storage_p), 347 ("allow_creation", ctypes.c_int), 348 ("rowstatus_column", ctypes.c_uint) 349] 350 351for f in [ libnsX.netsnmp_create_table_data_set ]: 352 f.argtypes = [ 353 ctypes.c_char_p # const char *table_name 354 ] 355 f.restype = netsnmp_table_data_set_p 356 357for f in [ libnsX.netsnmp_table_dataset_add_row ]: 358 f.argtypes = [ 359 netsnmp_table_data_set_p, # netsnmp_table_data_set *table 360 netsnmp_table_row_p, # netsnmp_table_row *row 361 ] 362 f.restype = None 363 364for f in [ libnsX.netsnmp_table_data_set_create_row_from_defaults ]: 365 f.argtypes = [ 366 netsnmp_table_data_set_storage_p # netsnmp_table_data_set_storage *defrow 367 ] 368 f.restype = netsnmp_table_row_p 369 370for f in [ libnsX.netsnmp_table_set_add_default_row ]: 371 f.argtypes = [ 372 netsnmp_table_data_set_p, # netsnmp_table_data_set *table_set 373 ctypes.c_uint, # unsigned int column 374 ctypes.c_int, # int type 375 ctypes.c_int, # int writable 376 ctypes.c_void_p, # void *default_value 377 ctypes.c_size_t # size_t default_value_len 378 ] 379 f.restype = ctypes.c_int 380 381for f in [ libnsX.netsnmp_register_table_data_set ]: 382 f.argtypes = [ 383 netsnmp_handler_registration_p, # netsnmp_handler_registration *reginfo 384 netsnmp_table_data_set_p, # netsnmp_table_data_set *data_set 385 ctypes.c_void_p # netsnmp_table_registration_info *table_info 386 ] 387 f.restype = ctypes.c_int 388 389for f in [ libnsX.netsnmp_set_row_column ]: 390 f.argtypes = [ 391 netsnmp_table_row_p, # netsnmp_table_row *row 392 ctypes.c_uint, # unsigned int column 393 ctypes.c_int, # int type 394 ctypes.c_void_p, # const void *value 395 ctypes.c_size_t # size_t value_len 396 ] 397 f.restype = ctypes.c_int 398 399for f in [ libnsX.netsnmp_table_dataset_add_index ]: 400 f.argtypes = [ 401 netsnmp_table_data_set_p, # netsnmp_table_data_set *table 402 ctypes.c_ubyte # u_char type 403 ] 404 f.restype = None 405 406for f in [ libnsX.netsnmp_table_dataset_remove_and_delete_row ]: 407 f.argtypes = [ 408 netsnmp_table_data_set_p, # netsnmp_table_data_set *table 409 netsnmp_table_row_p # netsnmp_table_row *row 410 ] 411 412# include/net-snmp/agent/snmp_agent.h 413for f in [ libnsa.agent_check_and_process ]: 414 f.argtypes = [ 415 ctypes.c_int # int block 416 ] 417 f.restype = ctypes.c_int 418