История следующая.
Пользователь клентской программы указал для некоторого устройства, опрашиваемого (чтение данных по некоторым OID) по SNMP - IP адрес, несовпадающий с IP адресом опрашиваемого устройства. В результате - клиентская программа с грохотом упала. В ходе "разбора полётов" было выяснено следующее:
Казалось бы, всё ясно - не используйте одинаковые 'community' для разных устройств, обрабатывайте правильно ответы на неправильные запросы и проблем не будет... Но.
В ходе более глубокого копания выяснилась некоторая неоднозначность возврата из функции snmp_sess_synch_response.
Берём устройство (или эмулятор) IP, OIDы и community которого мы знаем и обращаемся к нему с запросом данных по несуществующим у него OID (IP и commutity совпадают). Примерно так (часть кода пропущена):
struct snmp_session *sess;
struct snmp_pdu **response;
void *ptr=NULL;
snmp_sess_init(sess);
sess->version=SNMP_VERSION_2c;
sess->peername=ip;
sess->community=(unsigned char*)community;
sess->community_len = strlen(community);
ptr = snmp_sess_open(sess);
pdu=snmp_pdu_create(SNMP_MSG_GET);
snmp_parse_oid(buff, anOID, &anOID_len);
snmp_add_null_var(pdu, anOID, anOID_len);
int Ret = snmp_sess_synch_response(ptr, pdu, response);
Варианты возврата из последней функции (для разных, но несуществующих OID) следующие:
ПОЧЕМУ? Ведь проблема одна и та же - агент получил запрос на отсутствующую у него информацию. А потому что ответственность за ответ на запрос c неизвестным OID лежит на агенте SNMP, то есть на том, кто пишет софт для устройства или эмулятора. Ответственность эта - понимается по-разному.
Но не всё потеряно - даже в последнем варианте можно пойти дальше - и обработать возникшую ошибку. Попробуем проанализировать содержимое полученного ответа
netsnmp_variable_list *vars = pdu_receive->variables;
Список у нас содержит только одну переменную, поэтому посмотрим содержимое её поля type. В нашем случае имеем тип SNMP_NOSUCHINSTANCE.
И конечно, не следует забывать о функции snmp_sess_error. Она не всегда возвращает пустые данные.
Пользователь клентской программы указал для некоторого устройства, опрашиваемого (чтение данных по некоторым OID) по SNMP - IP адрес, несовпадающий с IP адресом опрашиваемого устройства. В результате - клиентская программа с грохотом упала. В ходе "разбора полётов" было выяснено следующее:
- В локальной сети находилось SNMP устройство другого типа ( и другого производителя) , опрашивать которое клиент не планировал и информацией об OID которого не располагал, но IP адрес которого был ошибочно введён.
- "Community" для чтения этих устройств совпали (да оно и понятно - 'public' - по умолчанию).
- Обработка ошибок от функции snmp_sess_synch_response в клиентской программе была организована из рук вон плохо - ну и понятно, возникло нарушение доступа к памяти и т.д. и т.п.
Казалось бы, всё ясно - не используйте одинаковые 'community' для разных устройств, обрабатывайте правильно ответы на неправильные запросы и проблем не будет... Но.
В ходе более глубокого копания выяснилась некоторая неоднозначность возврата из функции snmp_sess_synch_response.
Берём устройство (или эмулятор) IP, OIDы и community которого мы знаем и обращаемся к нему с запросом данных по несуществующим у него OID (IP и commutity совпадают). Примерно так (часть кода пропущена):
struct snmp_session *sess;
struct snmp_pdu **response;
void *ptr=NULL;
snmp_sess_init(sess);
sess->version=SNMP_VERSION_2c;
sess->peername=ip;
sess->community=(unsigned char*)community;
sess->community_len = strlen(community);
ptr = snmp_sess_open(sess);
pdu=snmp_pdu_create(SNMP_MSG_GET);
snmp_parse_oid(buff, anOID, &anOID_len);
snmp_add_null_var(pdu, anOID, anOID_len);
int Ret = snmp_sess_synch_response(ptr, pdu, response);
Варианты возврата из последней функции (для разных, но несуществующих OID) следующие:
- Ret==STAT_SUCCESS и (*response)->errstat==SNMP_ERR_NOSUCHNAME
- Ret==STAT_TIMEOUT и (*response)==NULL;
- Ret==STAT_SUCCESS и (*response)->errstat==SNMP_ERR_NOERROR;
ПОЧЕМУ? Ведь проблема одна и та же - агент получил запрос на отсутствующую у него информацию. А потому что ответственность за ответ на запрос c неизвестным OID лежит на агенте SNMP, то есть на том, кто пишет софт для устройства или эмулятора. Ответственность эта - понимается по-разному.
Но не всё потеряно - даже в последнем варианте можно пойти дальше - и обработать возникшую ошибку. Попробуем проанализировать содержимое полученного ответа
netsnmp_variable_list *vars = pdu_receive->variables;
Список у нас содержит только одну переменную, поэтому посмотрим содержимое её поля type. В нашем случае имеем тип SNMP_NOSUCHINSTANCE.
И конечно, не следует забывать о функции snmp_sess_error. Она не всегда возвращает пустые данные.
Комментариев нет:
Отправить комментарий