Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
Форум программистов > C/C++: Программирование под Unix/Linux > Создание расширения для net-snmp |
Автор: kyzia887 26.8.2011, 14:57 |
Собственно вопрос возник в следующем: требуется написать расширение для net-snmp под linux на С++. В этом я новичок и хотел бы попросить у вас совета где и что можно почитать на данную тему. При написании клиента с использование этой библиотеки вопросов особо не возникло, а вот с расширением увы =( Сразу скажу что гуглил и неоднократно (парюсь этим вопросом уже 2й день), но результатов почти ни каких. Варианты с примерами на Перле или Питоне тоже не катят, тк я с ними вообще не работал. Сама задача заключается в следующем: при запросе по snmp (oid = произвольный набор к примеру задаю) мое расширение опрашивает некую программу и возвращает 1 - если та запущена, и 0 - если нет. Хотелось бы для примера хоть небольшой кусок кода глянуть чтобы понять как все это дело собрать воедино. Заранее благодарен. |
Автор: svlary 29.8.2011, 06:34 | ||||||
В свое время я написал целиком и менеджера и агента для SNMP, но было это очень давно - больше 10 лет назад, так что - увы, почти ничего не помню...
Не очень понятно, что Вы имеете в виду... В SNMP используется терминология :
А на официальном сайте смотрели ? http://www.net-snmp.org/
Ну, на http://sourceforge.net/ я, по запросу "snmp" сразу нашел 376 результатов. ![]()
|
Автор: kyzia887 29.8.2011, 09:49 | ||||
Да, перелопатил его. Как раз пример клиента / менеджера там неплохо на С описан и немного повозившись все заработало как часы, а вот расширение агента увы у них тока на перле.
Спасибо за инфу, щас буду разбираться что к чему ![]() |
Автор: kyzia887 30.8.2011, 14:51 | ||||||||||||||
Разобрался с проблемой ![]() Net-SNMP поддерживает возможность использовать подгружаемый внешний модуль (далее - библиотека). Для того чтобы собрать данную библиотеку следует рассмотреть приведенный пример: http://www.net-snmp.org/wiki/index.php/TUT:Writing_a_Dynamically_Loadable_Object Опишу мои действия вкратце (может кому-нибудь пригодится еще): 1) Для начала написал как в примере 2 файла (заголовочный и исходного текста С): Заголовочный файл "SNMPExtended.h"
Файл исходного текста С "SNMPExtended.c"
2) Далее собираю все это дело в нашу библиотеку:
3) Проверяем конфигурацию net-snmp: Открываем файл /etc/snmp/snmpd.conf В моем случае он имеет следующий вид:
4) Далее создаем свой MIB-файл (отталкивался от примера): NET-SNM-ITELECT-MIB.txt
И закидываем наш новый MIB к остальным MIB-файлам: /usr/share/snmp/mibs/ После чего перезапускаем агент net-snmp: cd /etc/init.d/ ./snmpd restart 5) Проверяем структуру нашего нового MIB-файла: cd /usr/bin ./snmptranslate -M+. -mNET-SNMP-INTELECT-MIB -Tp -IR netSnmpIntelectMIB Получаем что-то вроде этого:
6) После всего выше перечисленного можно пойти двумя путями добавления нашей новой библиотеки в агент: - прописать ее в конфигурационном файле snmpd.conf (я выбрал этот вариант) (не нужно каждый раз регать наш внешний модуль) - выполнить 7 пунктов, описанных в мануале (ссылка вначале сообщения) (данный вариант работает только до тех пор, пока не перезагрузим агент net-snmp! После перезагрузки все настройки слетают!) В моем случае отредактированный конфигурационный файл стал выглядеть так: /etc/snmp/snmpd.conf
7) Перезапускаем агент net-snmp и запрашиваем необходимую нам информацию: cd /usr/bin ./snmpget -c public -v 2c localhost .1.3.6.1.4.1.8072.2.4.1.1.333.0 Получим: NET-SNMP-EXAMPLES-MIB::netSnmpExamples.4.1.1.333.0 = INTEGER: 333 |
Автор: kyzia887 31.8.2011, 09:59 | ||||||||
Как описывается в мануале, мы описываем инициализацию нашей библиотеки по средствам
и должны описать выгрузку нашей библиотеки по окончании работы
т.е. общая структура получается void init_Название нашей библиотеки (void); и void deinit_Название (void); При запуске самого net-snmp (если в его конфигурационном файле прописано подключение нашей библиотеки) наша библиотека регистрируется и присваивает новому инстансу заданный в ней OID (естественно MIB файл тоже должен присутствовать как я писал ранее). После того как net-snmp запуститься можно обращаться к нашему новому элементу двумя способами:
Лично я дописал несколько строк кода для вывода конкретного значения по запросу: SNMPExtebded.cpp
Записывать значение так же как получать ![]() Единственный минус - я пока что не знаю как сделать эти данные обновляемыми, т.е. в моем случае размер БД запишется в переменную только при инициализации библиотеки и все, и если мы к примеру при старте не смогли подключиться к БД то в значении будет висеть 0 и он уже не обновиться даже если подключение вновь появится =( Может конечно нужно настраивать сам net-snmp, пока не знаю... Думаю над этим вопросом. Тут еще возникает необходимость в обработке netsnmpset, т.е. чтобы не ставить это значение в переменную. а производить какие-то манипуляции скажем с БД и не более (значение инстанса при этом должно остаться прежним)... |
Автор: fish9370 31.8.2011, 10:39 |
kyzia887, спасибо, интересная статья.. плюсанул.. |
Автор: svlary 1.9.2011, 05:49 | ||||||
Вот здесь :
Т.е, получается, что Вы регистрируете не функцию доступа, а переменную, хранящую значение для MIB. Действительно, у Вас она получает значение только при инициализации всей MIB. Мой вопрос был как раз про это... Насколько я помню, мне пришлось найти обработчик
Вставить туда проверку на код нашей фирмы. Если код совпадал, то вызывался мой обработчик оставшейся части OID, который и делал проверку на то, какая именно переменная обрабатывается и что с ней надо делать (код запроса). И только после этого реализовывалась семантика запроса.... |
Автор: kyzia887 1.9.2011, 14:35 | ||||||||||
Разобрался с обработкой (по крайней мере на данном этапе мне этого должно хватить) ![]() Пришлось переписать немного код. Теперь он выглядит следующим образом: SNMPExtended.h
SNMPExtended.cpp
Прокомментировал все что могло бы вызвать вопросы в самом коде. MIB-файл и настройки net-snmp не трогал. Данный вариант обрабатывает каждый запрос который поступает от клиента/менеджера:
Надеюсь не зря разгребал эту штуку ![]() ![]() |
Автор: svlary 2.9.2011, 05:35 |
Ну, во всяком случае, мне было очень интересно ! ![]() |
Автор: kyzia887 7.9.2011, 13:42 | ||||||||||||
Довинтил во все выше описанное еще создание таблицы. MIB-файл теперь имеет следующую структуру: NET-SNM-ITELECT-MIB.txt
Проверяем структуру нового MIB-файла (см. выше) и должны получить что-то вроде этого:
Конфигурационный файл Net-SNMP стал выглядеть так (подключаю дополнительный новый модуль, который будет создавать таблицу): snmpd.conf
Сам код имеет следующий вид: MyTestTables.h
MyTestTables.cpp
При запросе информации получим следующее:
Если возникнут вопросы, пишите, попробую объяснить или разбраться что к чему ![]() |
Автор: kyzia887 9.9.2011, 10:36 | ||
Небольшое дополнение по таблицам ![]() Для того чтобы таблица каждый раз пересоздавала строки переписал код следующим образом: MyTestTables.cpp
Все остальное осталось прежним. Всем успехов ![]() |
Автор: azote 30.10.2012, 12:50 |
Спасибо за статью. Есть такой вопрос. Могу ли я как-то создать обработчик всех OID'ов начиная с определенного, например, .1.3.6.1.4.1.8072...., и уже в своем обработчике перебирать дочерние номера и решать какому из них какое значение устанавливать? Ведь, как я понял, у Вас в примере показывается, как обрабатывать определенные значения OID'ов. И еще вопрос. Могу ли я создать подобное расширение агента без внедрение соответствующего MIB-модуля? |
Автор: kyzia887 21.12.2012, 15:40 | ||
Вот на счет первого вопроса к сожалению не подскажу, т.к. сам это задачу не решал, а по поводу внедрения MIB-файла, то вроде бы можно и без него. ![]() |
Автор: igormat 17.9.2013, 11:33 |
Добрый день, а никто не может посоветовать литературу по Net-SNMP с точки зрения девелоперов? А то туториалы на официальном сайте очень скудные. |
Автор: kyzia887 17.9.2013, 11:37 | ||
Лично я, когда занимался этим вопросом, так толком ни чего и не нашел, кроме различных статей и офф. сайта. |
Автор: igormat 17.9.2013, 14:09 |
Тогда вопрос. Как из запроса вычленить нужную ячейку таблицы и ответить? Из предыдущего примера не видно где именно задается значение в ОТВЕТЕ. Или же мы просто задаем значение в таблице, а уже сам Net-SNMP достает значение? |
Автор: igormat 17.9.2013, 17:46 |
И не могли бы привести статьи касаемо обработки таблиц в Net-SNMP? |
Автор: Vorlon 16.10.2013, 11:01 | ||
kyzia887, здравствуй. Если при общении с роутером на основе примера
No such Object available on this agent at this OID - с чем это связано? Что необходимо сделать на уровне кода, чтобы роутер всё-таки ответил? (Только учусь и страдаю) Добавлено через 9 минут и 31 секунду Пример - если необходимо - сразу готов сюда выложить. ) |
Автор: kyzia887 16.10.2013, 11:11 | ||
Скорее всего у вас не подключен MIB файл с OID-ом по которому вы обращаетесь. Посмотрите в начале темы, я там описывал как что делал. Но это все проверялось на локальных машинах. Железки я вообще не трогал, т.к. это не требовалось. |
Автор: Vorlon 16.10.2013, 11:16 |
MIB-файл есть. Для его подключения надо обязательно создавать SNMPExtended.c и h и собирать в so? Можно MIB-файл напрямую привязать в snmpd.conf? Добавлено через 8 минут и 9 секунд Или по имени и пути MIB-файла привязать его в самом коде, например, в конструкторе? |
Автор: kyzia887 16.10.2013, 12:53 |
MIB файл только описывает что и как запрашивать. Файл библиотеки (*.so - linux, *.dll - windows) собственно и выдает результат. |
Автор: kyzia887 11.2.2014, 12:46 | ||||||||||||||||
Внесу небольшие поправки во все выше описанное. Прошло чуть меньше 3-х лет и мне снова пришлось залезть в свои исходники и наклепать очередной модуль для Net-SNMP. Увы. Он не завелся вот так сразу, что было для меня весьма удивительно, ведь делал все в точности как сам же и писал ранее. Опишу две основные ошибки:
PS: Использовал Qt 4.8.4 PhoenixNetSnmpTableModule.pro
PhoenixNetSnmpTableModule.h
PhoenixNetSnmpTableModule.cpp
NET-SNMP-PHOENIX-MIB.txt (копируем в /usr/share/snmp/mibs/)
snmpd.conf (/etc/snmp/snmpd.conf)
Теперь главные моменты:
PS: Если у вас не работает ваш модуль (ошибка из серии: No such Object available on this agent at this OID), то проверить из-за чего можно командой:
Если расширение не загрузилось, то будет хоть как-то описана причина. Например:
Может возникнуть косяк из-за того что Net-SNMP не подгрузит MIB. Выполняем следующее:
Ниже прикладываю исходники (мало ли что) ![]() |
Автор: mchertz 23.6.2014, 16:25 |
Спасибо автору=) |
Автор: WOLFY17 26.4.2017, 13:34 |
kyzia887, спасибо за подробное описание. Не могу понять некоторых вещей: 1. Для чего мы создаём пункты таблицы в MIB, если мы её создаём на уровне кода? 2. В каком случае должен вызываться обработчик, к которому привязана таблица (т. е. после какой команды из консоли). я думал что после snmpset или snmpget того OIDа, на котором висит таблица, но это не работает. Вообще не очень понимаю по какому принципу работает таблица Поясни, если не тяжело) |
Автор: kyzia887 27.4.2017, 13:46 | ||||||
1. Для чего мы создаём пункты таблицы в MIB - для себя и для сторонних разработчиков, если они захотят запросить ваши данные (ведь MIB содержит описание возвращаемых данных) 2. В каком случае должен вызываться обработчик, к которому привязана таблица - после запроса snmpwalk или snmpgetnext В том примере, который я описал, таблица не имеет постоянного размера (может быть 1 или N строк в зависимости от конфигурационного файла самого модуля), поэтому в своем коде я запрашивал эти данные командой snmpwalk, т.к. она выгрузит вам все дочерние элементы этой таблицы. Например oid таблицы = .1.2.3.4.5, тогда все строки которые вы создадите будут имет oid-ы: 1 - .1.2.3.4.5.1 2 - .1.2.3.4.5.2 N - .1.2.3.4.5.N Пример запроса таблицы:
А вот уже единичное значение (например sysname oid = 1.3.6.1.2.1.1.5 ) нужно запрашивать через snmpget. Пример запроса sysname:
К слову, если углубиться в код команды snmpwalk, то это лишь запросы snmpgetnext, выполняющиеся до тех пор, пока возвращаемые данные являются дочерними элементами таблицы. |
Автор: WOLFY17 2.5.2017, 11:37 | ||||
kyzia887, Спасибо за ответ, не думал, что дождусь ответа через 3 года после активности в теме)) А почему мы в коде пишем oid таблицы 1.3.6.1.4.1.8072.2.5.1.1.1.1.2, если, судя по MIB, она будет иметь oid 1.3.6.1.4.1.8072.2.5.1.1.1.1, что означает последняя двойка в записи oid в коде? Кстати, при запросе получаю следующие значения
iso.3.6.1.4.1.8072.2.5.1.1.1.1.2 - это oid таблицы из кода; предпоследняя цифра 2 -это, я так понимаю, столбец, который мы заполняем в строке; последние цифры 0-4 это, наверное, индексы (кстати, вы не могли бы пояснить что они означают? ведь мы указали таблицу, создали запись в ней(строку), указали поле (столбец), что же тогда обозначает этот индекс?) А вот откуда появилась единица между oid'ом таблицы и номером столбца (iso.3.6.1.4.1.8072.2.5.1.1.1.1.2.1.2.0) я понять никак не могу)) Может это порядковый номер записи? Если так, то как тогда создать вторую запись в таблице? А как в данном случае запрашивать конкретное значение из таблицы? Команда snmpget по oid не работает:
Заранее спасибо за ответ) |
Автор: katenka141 19.5.2017, 00:13 |
Есть такой вопрос. Могу ли я как-то создать обработчик всех OID'ов начиная с определенного, например, .1.3.6.1.4.1.8072...., и уже в своем обработчике перебирать дочерние номера и решать какому из них какое значение устанавливать? Ведь, как я понял, у Вас в примере показывается, как обрабатывать определенные значения OID'ов. И еще вопрос. Могу ли я создать подобное расширение агента без внедрение соответствующего MIB-модуля? ege.org.ru ege.net.ru |
Автор: kyzia887 19.5.2017, 16:01 |
Боюсь что конкретное значение врядли получиться запросить, либо пробовать команду snmpgetnext. А для более точного понимания что и как происходит попробуйте воспользоваться каким-нибудь MIB-браузером (qtmib, oid view и т.д.), он вам более детально все должен показать. |
Автор: kyzia887 19.5.2017, 16:18 | ||
1. Могу ли я как-то создать обработчик всех OID'ов начиная с определенного - могу ошибаться, но вроде бы нет. Тут более точно можно сказать, если детально изучить интерфейсы, которые предоставляет net-snmp. 2. Могу ли я создать подобное расширение агента без внедрение соответствующего MIB-модуля? - если я не ошибаюсь, то да, можете. Вроде бы net-snmp служба (snmpd) не лезет в MIB-файл, а зачитывает OID из модуля при его регистрации. |
Автор: WOLFY17 16.8.2017, 15:52 |
kyzia887, У меня почему-то оба примера (MyTestTables и PhoenixServicesTable) выдают данные только начиная со второго запроса snmpwalk. На первом выдают ошибку "No Such Object available on this agent at this OID". С первого запроса данные выдаются только если таблица заполнялась в функции инициализации, сразу при создании таблицы. И то такое ощущение, что выдаются те данные, которые были записаны при инициализации, а не те, которые были записаны уже в обработчике запроса. У тебя не возникало такой проблемы? |
Автор: kyzia887 17.8.2017, 11:05 | ||
У меня была аналогичная ситуация, и если честно, то я ее не исправил, т.к. не было времени разбираться. Буду признателен, если ты найдешь решение и опишешь его тут. |
Автор: WOLFY17 21.8.2017, 09:19 | ||
Я пока понял, что таблице нужна первоначальная, если можно так выразиться, "инициализация", то есть до запроса. Если её не сделать (то есть на заполнить таблицу чем либо), то будет происходить то, что происходит. Я пока делаю так - в функции init_<> создаю таблицу, заполняю её какими-либо данными и после этого в обработчике запросов всё работает корректно. Но появилась другая проблема: команда snmpwalk просто выполняет последовательные запросы командами GET и GETNEXT для каждого отдельного поля: есть 10 полей-будет 10 запросов разных OIDов. То есть сама по себе таблица как таковая не запрашивается, просто все запросы сводятся к одному обработчику. Отсюда возникает небольшая сложность, касающаяся того как же заполнять таблицу? Строка (row) формируется целиком и уже после формирования добавляется в таблицу. А растягивать её формирование на несколько запросов, в каждом их которых будет заполняться одно поле-не очень хорошая идея. С другой стороны, и перезаписывать всю таблицу с одними и теми же данными 10 раз в каждом из запросов тоже не есть хорошо + в этом случае нужно следить за актуальностью данных. |
Автор: kyzia887 22.12.2017, 11:25 | ||
Это нормальное поведение, ведь snmpwalk выпоняет последовательно GETNEXT запросы, пока не выберет все данные из таблицы. |
Автор: WOLFY17 13.2.2019, 14:16 |
kyzia887, попробую ещё раз возродить тему)) Вы не пробовали не отвечать на запросы с помощью net-snmp, а наоборот - самому запрашивать данные у устройства в своём приложении? То есть, может быть есть у net-snmp какой-то API для пользовательского кода, аналог snmpget. Если вы сталкивались с такой задачей буду очень благодарен, если поделитесь информацией)) |
Автор: kyzia887 24.11.2020, 14:22 | ||
Добрый день. Прошло много времени, но я отвечу)) Библиотека net-snmp позволяет выполнять весь спектр клиентских запросов. Пример использования проще всего посмотреть в исходниках где реализованы клиенты (snmpget, snmpwalk и тд). Могу сказать сразу, что библиотека net-snmp не поддерживаем многопоточность в рамках клиентских запросов. Эти факторы нужно учитывать заранее. |