#pike __REAL_VERSION__ |
|
|
|
|
|
|
#include "snmp_globals.h" |
#include "snmp_errors.h" |
|
inherit "protocol"; |
|
private array get_community_list=({}); |
private array set_community_list=({}); |
private array managers_list=({}); |
private mapping oid_get_callbacks=([]); |
private mapping oid_set_callbacks=([]); |
private int managers_security_mode=0; |
private int thread_running=0; |
|
private void request_received(mapping rdata) { |
|
set_blocking(); |
mapping rv=decode_asn1_msg(rdata); |
|
mapping varlist=([]); |
|
array n=indices(rv); |
|
if(rv[n[0]]) |
{ |
if(managers_security_mode && !has_value(managers_list, |
get_host_from_ip(rdata->ip))) |
|
|
{ |
return; |
} |
if(rv[n[0]]->op==Protocols.SNMP.REQUEST_GET || rv[n[0]]->op==Protocols.SNMP.REQUEST_GETNEXT) |
{ |
if(!has_value(get_community_list, rv[n[0]]->community)) |
|
{ |
return; |
} |
foreach(rv[n[0]]->attribute, mapping att) |
{ |
foreach(indices(att), string oid) |
{ |
if(oid_get_callbacks[oid]) |
{ |
mixed r=oid_get_callbacks[oid](oid, rv[n[0]]); |
if(r[0]==0) |
{ |
return_error(rv, @r[1..]); |
return; |
} |
else varlist[oid]=r[1..]; |
} |
else if(oid_get_callbacks["*"]) |
{ |
mixed r=oid_get_callbacks["*"](oid, rv[n[0]]); |
if(r[0]==0) |
{ |
return_error(rv, @r[1..]); |
return; |
} |
else varlist[oid]=r[1..]; |
} |
} |
} |
if(varlist && sizeof(varlist)>0) |
get_response(varlist, rv); |
} |
else if(rv[n[0]]->op==Protocols.SNMP.REQUEST_SET) |
{ |
if(!has_value(set_community_list, rv[n[0]]->community)) |
|
{ |
return; |
} |
foreach(rv[n[0]]->attribute, mapping att) |
{ |
foreach(indices(att), string oid) |
{ |
if(oid_set_callbacks[oid]) |
{ |
mixed r=oid_set_callbacks[oid](oid, att[oid], rv[n[0]]); |
if(r[0]==0) |
{ |
return_error(rv, @r[1..]); |
return; |
} |
else; |
} |
else if(oid_set_callbacks["*"]) |
{ |
mixed r=oid_set_callbacks["*"](oid, att[oid], rv[n[0]]); |
if(r[0]==0) |
{ |
return_error(rv, @r[1..]); |
return; |
} |
else; |
} |
else |
{ |
return_error(rv, Protocols.SNMP.ERROR_NOSUCHNAME, |
get_index_number(oid, rv[n[0]])); |
return; |
} |
} |
} |
|
return_error(rv, Protocols.SNMP.ERROR_NOERROR, 0); |
} |
else |
{ |
error("unsupported request type " + rv[n[0]]->op + "\n"); |
} |
} |
} |
|
|
|
|
|
|
|
|
|
|
|
|
void create(int|void port, string|void addr) { |
int p=port||SNMP_DEFAULT_PORT; |
|
if(addr) |
::create(0, 0, p, addr); |
else |
::create(0, 0, p); |
|
::set_read_callback(request_received); |
::set_nonblocking(); |
} |
|
|
void set_threaded() |
{ |
#if constant (thread_create) |
if(!thread_running) |
{ |
::set_blocking(); |
thread_running=1; |
run_handler_thread(); |
} |
#endif |
} |
|
#if constant (thread_create) |
void run_handler_thread() |
{ |
thread_create(handler); |
} |
|
void handler() |
{ |
do |
{ |
mixed r=read(); |
if(r) request_received(r); |
} |
while(1); |
|
} |
#endif |
|
|
|
|
|
|
|
|
void set_managers_only(int yesno) |
{ |
managers_security_mode=yesno; |
} |
|
|
|
|
|
|
|
|
void set_get_communities(array communities) |
{ |
get_community_list=communities; |
} |
|
|
|
|
|
|
|
|
void set_set_communities(array communities) |
{ |
set_community_list=communities; |
} |
|
|
|
|
|
|
|
|
void set_managers(array managers) |
{ |
managers_list=managers; |
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void set_set_oid_callback(string oid, function cb) |
{ |
if(oid=="*"); |
else if(!oid || !is_valid_oid(oid)) |
error("set_set_oid_callback(): invalid or no oid specified.\n"); |
|
oid_set_callbacks[oid]=cb; |
|
} |
|
|
|
|
|
|
|
|
|
int clear_set_oid_callback(string oid) |
{ |
if(oid=="*"); |
else if(!oid || !is_valid_oid(oid)) |
error("clear_set_oid_callback(): invalid or no oid specified.\n"); |
if(oid_set_callbacks[oid]) |
{ |
m_delete(oid_set_callbacks, oid); |
return 1; |
} |
else return 0; |
} |
|
|
|
|
|
|
|
|
|
void|function get_set_oid_callback(string oid) |
{ |
if(oid=="*"); |
else if(!oid || !is_valid_oid(oid)) |
error("get_set_oid_callback(): invalid or no oid specified.\n"); |
if(oid_set_callbacks[oid]) |
return oid_set_callbacks[oid]; |
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void set_get_oid_callback(string oid, function cb) |
{ |
if(oid=="*"); |
else if(!oid || !is_valid_oid(oid)) |
error("set_get_oid_callback(): invalid or no oid specified.\n"); |
|
oid_get_callbacks[oid]=cb; |
|
} |
|
|
|
|
|
|
|
|
|
int clear_get_oid_callback(string oid) |
{ |
if(oid=="*"); |
else if(!oid || !is_valid_oid(oid)) |
error("clear_get_oid_callback(): invalid or no oid specified.\n"); |
if(oid_get_callbacks[oid]) |
{ |
m_delete(oid_get_callbacks, oid); |
return 1; |
} |
else return 0; |
} |
|
|
|
|
|
|
|
|
|
void|function get_get_oid_callback(string oid) |
{ |
if(oid=="*"); |
else if(!oid || !is_valid_oid(oid)) |
error("get_get_oid_callback(): invalid or no oid specified.\n"); |
if(oid_get_callbacks[oid]) |
return oid_get_callbacks[oid]; |
} |
|
private int is_valid_oid(string oid) |
{ |
foreach(oid/".", string c) |
{ |
string x; |
sscanf(c, "%[0-9]", x); |
if(c!=x) return 0; |
} |
return 1; |
} |
|
private string get_host_from_ip(string ip) |
{ |
string host=System.gethostbyaddr(ip)[0]; |
return host; |
} |
|
private void return_error(mapping rv, int errstatus, int errindex) |
{ |
get_response(([]), rv, errstatus, errindex); |
return; |
} |
|
int get_index_number(string o, mapping r) |
{ |
for(int i=0; i< sizeof(r->attribute); i++) |
{ |
if(r->attribute[i][o]) |
return i; |
} |
return -1; |
} |
|
|