Модераторы: xvr

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Создание расширения для net-snmp 
V
    Опции темы
kyzia887
Дата 26.8.2011, 14:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 21
Регистрация: 26.8.2011

Репутация: 1
Всего: 1



Собственно вопрос возник в следующем:
требуется написать расширение для net-snmp под linux на С++. В этом я новичок и хотел бы попросить у вас совета где и что можно почитать на данную тему. При написании клиента с использование этой библиотеки вопросов особо не возникло, а вот с расширением увы =( Сразу скажу что гуглил и неоднократно (парюсь этим вопросом уже 2й день), но результатов почти ни каких. Варианты с примерами на Перле или Питоне тоже не катят, тк я с ними вообще не работал.

Сама задача заключается в следующем: при запросе по snmp (oid = произвольный набор к примеру задаю) мое расширение опрашивает некую программу и возвращает 1 - если та запущена, и 0 - если нет. Хотелось бы для примера хоть небольшой кусок кода глянуть чтобы понять как все это дело собрать воедино.

Заранее благодарен.
PM MAIL   Вверх
svlary
Дата 29.8.2011, 06:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 207
Регистрация: 8.9.2009

Репутация: 4
Всего: 4



Цитата
 В этом я новичок 

  В свое время я написал целиком и менеджера и агента для SNMP, но было это очень давно - больше 10 лет назад, так что - увы, почти ничего не помню...
Цитата
При написании клиента

Не очень понятно, что Вы имеете в виду... В SNMP используется терминология :
  • Менеджер - то, что использует сисадмин для настройки удаленных устройств
  • Агент - то, что работает на удаленных устройствах и обслуживает запросы менеджера

Цитата(kyzia887 @  26.8.2011,  14:57 Найти цитируемый пост)
где и что можно почитать на данную тему

 А на официальном сайте смотрели ? net-snmp.org

Цитата
Хотелось бы для примера хоть небольшой кусок кода глянуть чтобы понять как все это дело собрать воедино.


Ну, на sourceforge я, по запросу "snmp"  сразу нашел 376 результатов. smile Пожалуйста - скачивайте и изучайте! Боюсь только, что толку от этого будет немного. Потому,  что SNMP (несмотря на свое название) - штука очень сложная и запутанная.  И никакого "небольшого кусочка кода" просто-напросто не существует.  Насколько я помню, последовательность действий программиста, при необходимости расширения возможностей существующей SNMP системы, выглядит приблизительно так :
  • Выбираете OID для новых сущностей и согласовываете его между агентом и менеджером.
  • Прописываете его в MIB (и там и там...) и компилируете саму MIB для получения ее двоичного варианта.
  • Согласовывает формат ASN.1 кодирования для добавленного OID.
  • В агенте добавляете новую веточку "case <новый OID>:" для обработки запросов GET и GETNEXT
  • В менеджере добавляете возможность работы с новым OID

PM MAIL   Вверх
kyzia887
Дата 29.8.2011, 09:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 21
Регистрация: 26.8.2011

Репутация: 1
Всего: 1



Цитата

А на официальном сайте смотрели ? net-snmp.org


Да, перелопатил его. Как раз пример клиента / менеджера там неплохо на С описан и немного повозившись все заработало как часы, а вот расширение агента увы у них тока на перле.

Цитата

Ну, на sourceforge я, по запросу "snmp"  сразу нашел 376 результатов.


Спасибо за инфу, щас буду разбираться что к чему  smile 
PM MAIL   Вверх
kyzia887
Дата 30.8.2011, 14:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 21
Регистрация: 26.8.2011

Репутация: 1
Всего: 1



Разобрался с проблемой  smile 

Net-SNMP поддерживает возможность использовать подгружаемый внешний модуль (далее - библиотека). 
Для того чтобы собрать данную библиотеку следует рассмотреть приведенный пример: http://www.net-snmp.org/wiki/index.php/TUT...Loadable_Object

Опишу мои действия вкратце (может кому-нибудь пригодится еще):

1) Для начала написал как в примере 2 файла (заголовочный и исходного текста С):

Заголовочный файл "SNMPExtended.h"
Код

#ifndef SNMPEXTENDED_H
#define SNMPEXTENDED_H

#ifdef __cplusplus
extern "C" {
#endif

/*
 * function declarations
 */
void init_SNMPExtended(void);

#ifdef __cplusplus
}
#endif

#endif // SNMPEXTENDED_H
  

Файл исходного текста С "SNMPExtended.c"
Код

#include <net-snmp/net-snmp-config.h>
#include <net-snmp/net-snmp-includes.h>
#include <net-snmp/agent/net-snmp-agent-includes.h>
#include "SNMPExtended.h"

#ifdef __cplusplus
extern "C" {
#endif

/*
 * the variable we want to tie an OID to.  The agent will handle all
 * * GET and SET requests to this variable changing it's value as needed.
 */

static int SNMPExtended = 333;
static oid SNMPExtended_oid[] = { 1, 3, 6, 1, 4, 1, 8072, 2, 4, 1, 1, 333, 0 };

/*
 * our initialization routine, automatically called by the agent
 * (to get called, the function name must match init_FILENAME())
 */


void init_SNMPExtended(void)
{
   /*
    * a debugging statement.  Run the agent with -DnstAgentPluginObject to see
    * the output of this debugging statement.
    */
    DEBUGMSGTL(("SNMPExtended",
                "Initializing the SNMPExtended module\n"));


   /*
    * the line below registers our variables defined above as
    * accessible and makes it writable.  A read only version of any
    * of these registration would merely call
    * register_read_only_int_instance() instead.  The functions
    * called below should be consistent with your MIB, however.
    *
    * If we wanted a callback when the value was retrieved or set
    * (even though the details of doing this are handled for you),
    * you could change the NULL pointer below to a valid handler
    * function.
    */
    DEBUGMSGTL(("SNMPExtended",
                "Initalizing SNMPExtended scalar integer.  Default value = %d\n",
                SNMPExtended));

    netsnmp_register_int_instance("SNMPExtended",
                                  SNMPExtended_oid,
                                  OID_LENGTH(SNMPExtended_oid),
                                  &SNMPExtended, NULL);

    DEBUGMSGTL(("SNMPExtended",
                "Done initalizing SNMPExtended module\n"));
}


void deinit_SNMPExtended(void)
{
    unregister_mib(SNMPExtended_oid,OID_LENGTH(SNMPExtended_oid));
}

#ifdef __cplusplus
}
#endif



2) Далее собираю все это дело в нашу библиотеку:
Код

gcc -Wall -fPIC -c SNMPExtended.c
gcc -shared -o SNMPExtended.so SNMPExtended.o -ldl


3) Проверяем конфигурацию net-snmp:
Открываем файл /etc/snmp/snmpd.conf
В моем случае он имеет следующий вид:
Код

syslocation Server Room
syscontact Sysadmin (root@localhost)
rocommunity public 127.0.0.1
rwcommunity private 127.0.0.1


4) Далее создаем свой MIB-файл (отталкивался от примера):
NET-SNM-ITELECT-MIB.txt
Код

NET-SNMP-INTELECT-MIB DEFINITIONS ::= BEGIN

IMPORTS
    netSnmpExamples                FROM NET-SNMP-EXAMPLES-MIB
    OBJECT-TYPE, Integer32,
    MODULE-IDENTITY                FROM SNMPv2-SMI
    MODULE-COMPLIANCE, OBJECT-GROUP        FROM SNMPv2-CONF;

netSnmpIntelectMIB MODULE-IDENTITY
    LAST-UPDATE  "201108300000Z"        --30 august 2011
    ORGANIZATION "zzzz"
    CONTACT-INFO "zzzz"

    DESCRIPTION "Mib for intelect."

    ::= { netSnmpExamples 5 }

nstIntelectMibObjects        OBJECT IDENTIFIER ::= { netSnmpIntelectMIB 1 }

nstIntelectAgentModules        OBJECT IDENTIFIER ::= { nstIntelectMibObjects 1 }

SNMPExtended OBJECT-TYPE
    SYNTAX        Integer32
    MAX-ACCESS    read-write
    STATUS        current
    DESCRIPTION
          "This is test object for intelect"
    DEFVAL { 333 }
    ::= { nstIntelectAgentModules 1 }

END


И закидываем наш новый 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


Получаем что-то вроде этого:
Код

+--netSnmpIntelectMIB(5)
      |
     +-- nstIntelectMibObjects(1)
            |
            +--nstIntelectAgentModules(1)
                  |
                  +-- -RW- Integer32 SNMPExtended(1)


6) После всего выше перечисленного можно пойти двумя путями добавления нашей новой библиотеки в агент:
     - прописать ее в конфигурационном файле snmpd.conf (я выбрал этот вариант) (не нужно каждый раз регать наш 
        внешний модуль)

     - выполнить 7 пунктов, описанных в мануале (ссылка вначале сообщения) (данный вариант работает только до   
        тех пор, пока не перезагрузим агент net-snmp! После перезагрузки все настройки слетают!
)

В моем случае отредактированный конфигурационный файл стал выглядеть так:
/etc/snmp/snmpd.conf
Код

syslocation Server Room
syscontact Sysadmin (root@localhost)
rocommunity public 127.0.0.1
rwcommunity private 127.0.0.1
dlmod SNMPExtended /home/intelect/soft/SNMPExtended.so


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 - 30.8.2011, 14:52
PM MAIL   Вверх
svlary
Дата 31.8.2011, 05:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 207
Регистрация: 8.9.2009

Репутация: 4
Всего: 4



Лично мне Ваше сообщение было очень интересным. Вспомнил - сколько сам мучился с этим делом,  когда никакой net-snmp не было ! smile
Один момент не понял. Вот вы регистрируете функцию-обработчик данного OID:

Цитата(kyzia887 @  30.8.2011,  14:51 Найти цитируемый пост)
   netsnmp_register_int_instance("SNMPExtended",
                                  SNMPExtended_oid,
                                  OID_LENGTH(SNMPExtended_oid),
                                  &SNMPExtended, NULL);


Но где сама функция ? (SNMPExtended)
Т.е. каким образом получается значение объекта { 1, 3, 6, 1, 4, 1, 8072, 2, 4, 1, 1, 333, 0 } и каким образом агент вызывает эту функцию ? При чтении и при записи...

PM MAIL   Вверх
kyzia887
Дата 31.8.2011, 09:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 21
Регистрация: 26.8.2011

Репутация: 1
Всего: 1



Цитата(svlary @ 31.8.2011,  05:54)
Но где сама функция ? (SNMPExtended)
Т.е. каким образом получается значение объекта { 1, 3, 6, 1, 4, 1, 8072, 2, 4, 1, 1, 333, 0 } и каким образом агент вызывает эту функцию ? При чтении и при записи...

Как описывается в мануале, мы описываем инициализацию нашей библиотеки по средствам 
Код

void init_SNMPExtended(void)
{
...
}


и должны описать выгрузку нашей библиотеки по окончании работы
Код

void deinit_SNMPExtended(void)
{
...
}


т.е. общая структура получается void init_Название нашей библиотеки (void); и void deinit_Название (void);

При запуске самого net-snmp (если в его конфигурационном файле прописано подключение нашей библиотеки) наша библиотека регистрируется и присваивает новому инстансу заданный в ней OID (естественно MIB файл тоже должен присутствовать как я писал ранее).

После того как net-snmp запуститься можно обращаться к нашему новому элементу двумя способами:
  •  ./snmpget -c public -v 2c localhost .1.3.6.1.4.1.8072.2.4.1.1.333.0
  •  ./snmpget -c public -v 2c localhost NET-SNMP-INTELECT-MIB::SNMPExtended.0
В обоих вариантах получим один и тот же ответ.

Лично я дописал несколько строк кода для вывода конкретного значения по запросу:
SNMPExtebded.cpp
Код

#include <net-snmp/net-snmp-config.h>
#include <net-snmp/net-snmp-includes.h>
#include <net-snmp/agent/net-snmp-agent-includes.h>
#include "SNMPExtended.h"

#include <QtSql>
#include <QFile>

#ifdef __cplusplus
extern "C" {
#endif

/*
 * the variable we want to tie an OID to.  The agent will handle all
 * * GET and SET requests to this variable changing it's value as needed.
 */

static int SNMPExtended = 0;
static oid SNMPExtended_oid[] = { 1, 3, 6, 1, 4, 1, 8072, 2, 4, 1, 1, 333, 0 };

/*
 * our initialization routine, automatically called by the agent
 * (to get called, the function name must match init_FILENAME())
 */


void init_SNMPExtended(void)
{

    QFile file;
    file.setFileName("SNMPExtended_LOG.txt");
    QTextStream out(&file);
    file.open(QIODevice::WriteOnly | QIODevice::Text);
    out << "-> Init - Ok\nSNMPExtended = " << SNMPExtended << endl;
    file.close();


   /*
    * a debugging statement.  Run the agent with -DnstAgentPluginObject to see
    * the output of this debugging statement.
    */
    DEBUGMSGTL(("SNMPExtended",
                "Initializing the SNMPExtended module\n"));


    file.open(QIODevice::Append | QIODevice::Text);
    out << "-> DEBUGMSGTL - Ok" << endl;
    file.close();

    /** Database connect **/
    int sizeOnDisk = 0;

    QSqlDatabase db = QSqlDatabase::addDatabase("QPSQL");
    db.setDatabaseName("bagira");
    db.setHostName("127.0.0.1");
    db.setUserName("postgres");
    db.setPassword("12345");
    if(!db.open())
    {
        /*
        QSqlError sqlError;
        sqlError = db.lastError();
        qDebug() << "DB connection failed! ERROR: " << sqlError.text();
        */
    }
    else
    {
        file.open(QIODevice::Append | QIODevice::Text);
        out << "-> DB open - Ok" << endl;
        file.close();

        QSqlQuery query;
        if(!query.exec("SELECT * FROM db_size_on_disk;"))
        {
            //qDebug() << "\nNot possible to read the table";
        }
        else
        {
            QSqlRecord rec = query.record();
            while(query.next())
            {
                sizeOnDisk = query.value(rec.indexOf("KB")).toInt();

                file.open(QIODevice::Append | QIODevice::Text);
                out << "-> DB size on disk = " << sizeOnDisk << endl;
                file.close();
            }
            SNMPExtended = sizeOnDisk;
        }
    }
    db.close();
    /** End database connect **/

    file.open(QIODevice::Append | QIODevice::Text);
    out << "-> DB close\nSNMPExtended = " << SNMPExtended << endl;
    file.close();

   /*
    * the line below registers our variables defined above as
    * accessible and makes it writable.  A read only version of any
    * of these registration would merely call
    * register_read_only_int_instance() instead.  The functions
    * called below should be consistent with your MIB, however.
    *
    * If we wanted a callback when the value was retrieved or set
    * (even though the details of doing this are handled for you),
    * you could change the NULL pointer below to a valid handler
    * function.
    */
    DEBUGMSGTL(("SNMPExtended",
                "Initalizing SNMPExtended scalar integer.  Default value = %d\n",
                SNMPExtended));

    file.open(QIODevice::Append | QIODevice::Text);
    out << "-> DEBUGMSGTL - Ok  Default value = " << SNMPExtended << endl;
    file.close();

    netsnmp_register_int_instance("SNMPExtended",
                                  SNMPExtended_oid,
                                  OID_LENGTH(SNMPExtended_oid),
                                  &SNMPExtended, NULL);

    file.open(QIODevice::Append | QIODevice::Text);
    out << "-> netsnmp_register_int_instance - Ok" << endl;
    file.close();

    DEBUGMSGTL(("SNMPExtended",
                "Done initalizing SNMPExtended module\n"));

    file.open(QIODevice::Append | QIODevice::Text);
    out << "-> DEBUGMSGTL - Done" << endl;
    file.close();
}


void deinit_SNMPExtended(void)
{
    unregister_mib(SNMPExtended_oid,OID_LENGTH(SNMPExtended_oid));

    QFile file;
    file.setFileName("SNMPExtended_LOG.txt");
    QTextStream out(&file);
    file.open(QIODevice::Append | QIODevice::Text);
    out << "-> unregister_mib - Ok" << endl;
    file.close();
}

#ifdef __cplusplus
}
#endif



Записывать значение так же как получать  smile 

Единственный минус - я пока что не знаю как сделать эти данные обновляемыми, т.е. в моем случае размер БД запишется в переменную только при инициализации библиотеки и все, и если мы к примеру при старте не смогли подключиться к БД то в значении будет висеть 0 и он уже не обновиться даже если подключение вновь появится =( Может конечно нужно настраивать сам net-snmp, пока не знаю... Думаю над этим вопросом. Тут еще возникает необходимость в обработке netsnmpset, т.е. чтобы не ставить это значение в переменную. а производить какие-то манипуляции скажем с БД и не более (значение инстанса при этом должно остаться прежним)...

Это сообщение отредактировал(а) kyzia887 - 31.8.2011, 10:06
PM MAIL   Вверх
fish9370
Дата 31.8.2011, 10:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 663
Регистрация: 15.4.2007
Где: Москва

Репутация: 2
Всего: 1



kyzia887, спасибо, интересная статья.. плюсанул..


--------------------
undefined
PM MAIL WWW ICQ   Вверх
svlary
Дата 1.9.2011, 05:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 207
Регистрация: 8.9.2009

Репутация: 4
Всего: 4



Цитата(kyzia887 @  31.8.2011,  09:59 Найти цитируемый пост)
размер БД запишется в переменную только при инициализации библиотеки и все

Вот здесь :
Код

SNMPExtended = sizeOnDisk;

Т.е, получается, что Вы регистрируете не функцию доступа, а переменную, хранящую значение для MIB.
Действительно, у Вас она получает значение только при инициализации всей MIB. 
Цитата(kyzia887 @  31.8.2011,  09:59 Найти цитируемый пост)
Думаю над этим вопросом.

Мой вопрос был как раз про это... Насколько я помню,  мне пришлось найти обработчик 
Код
OID=1.3.6.1.4.1.<ID фирмы>

Вставить туда проверку на код нашей фирмы. Если код совпадал, то вызывался мой обработчик оставшейся части OID, который и делал проверку на то, какая именно переменная обрабатывается и что с ней надо делать (код запроса). 
И только после этого реализовывалась семантика запроса.... 
PM MAIL   Вверх
kyzia887
Дата 1.9.2011, 14:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 21
Регистрация: 26.8.2011

Репутация: 1
Всего: 1



Цитата(svlary @ 1.9.2011,  05:49)
Мой вопрос был как раз про это... Насколько я помню,  мне пришлось найти обработчик 
Код
OID=1.3.6.1.4.1.<ID фирмы>

Вставить туда проверку на код нашей фирмы. Если код совпадал, то вызывался мой обработчик оставшейся части OID, который и делал проверку...

Разобрался с обработкой (по крайней мере на данном этапе мне этого должно хватить)  smile 
Пришлось переписать немного код. Теперь он выглядит следующим образом:
SNMPExtended.h
Код

#ifndef SNMPEXTENDED_H
#define SNMPEXTENDED_H

#ifdef __cplusplus
extern "C" {
#endif

#include <net-snmp/net-snmp-config.h>
#include <net-snmp/net-snmp-includes.h>
#include <net-snmp/agent/net-snmp-agent-includes.h>

/*
 * function declarations
 */
void init_SNMPExtended(void);
int database_size();
int handle_node_snmpExtended(netsnmp_mib_handler          *handler,
                             netsnmp_handler_registration *reginfo,
                             netsnmp_agent_request_info   *reqinfo,
                             netsnmp_request_info         *requests);
void deinit_SNMPExtended(void);

#ifdef __cplusplus
}
#endif

#endif // SNMPEXTENDED_H


SNMPExtended.cpp
Код

#include "SNMPExtended.h"

#include <QtSql>
#include <QFile>

#ifdef __cplusplus
extern "C" {
#endif

/*
 * the variable we want to tie an OID to.  The agent will handle all
 * * GET and SET requests to this variable changing it's value as needed.
 */
static int SNMPExtended = 0;
static oid SNMPExtended_oid[] = { 1, 3, 6, 1, 4, 1, 8072, 2, 5, 1, 1, 1, 0 };

/*
 * our initialization routine, automatically called by the agent
 * (to get called, the function name must match init_FILENAME())
 */

void init_SNMPExtended(void)
{
    // - LOG -
    QFile file;
    file.setFileName("SNMPExtended_LOG.txt");
    QTextStream out(&file);
    file.open(QIODevice::WriteOnly | QIODevice::Text);
    out << "-> Init - Ok\n-> SNMPExtended = " << SNMPExtended << endl;
    file.close();
    // - LOG -

    DEBUGMSGTL(("SNMPExtended",
                "Initializing the SNMPExtended module\n"));


    // - LOG -
    file.open(QIODevice::Append | QIODevice::Text);
    out << "-> DEBUGMSGTL: Initializing the SNMPExtended module - Ok" << endl;
    file.close();
    // - LOG -

    //create handler registration
    netsnmp_handler_registration *my_test;

    my_test = netsnmp_create_handler_registration("Test SNMP Extended",
                                                  handle_node_snmpExtended,
                                                  SNMPExtended_oid,
                                                  OID_LENGTH(SNMPExtended_oid),
                                                  HANDLER_CAN_RWRITE);
    //register new instance
    netsnmp_register_instance(my_test);

    DEBUGMSGTL(("SNMPExtended",
                "Done initalizing SNMPExtended module\n"));

    // - LOG -
    file.open(QIODevice::Append | QIODevice::Text);
    out << "-> DEBUGMSGTL: Done initalizing SNMPExtended module." << endl;
    file.close();
    // - LOG -
}

int database_size()
{
    // - LOG -
    QFile file;
    file.setFileName("SNMPExtended_LOG.txt");
    QTextStream out(&file);
    file.open(QIODevice::Append | QIODevice::Text);
    out << "-> Init DataBase size func - Done" << endl;
    file.close();
    // - LOG -

    int sizeOnDisk = -1;

    /** Database connect **/
    QSqlDatabase db = QSqlDatabase::addDatabase("QPSQL");
    db.setDatabaseName("bagira");
    db.setHostName("192.168.16.38");
    db.setUserName("postgres");
    db.setPassword("12345678");
    if(!db.open())
    {
        // - LOG -
        file.open(QIODevice::Append | QIODevice::Text);
        out << "-> DataBase open - Error!" << endl;
        file.close();
        // - LOG -
    }
    else
    {
        // - LOG -
        file.open(QIODevice::Append | QIODevice::Text);
        out << "-> DataBase open - Ok" << endl;
        file.close();
        // - LOG -

        QSqlQuery query;
        if(!query.exec("SELECT * FROM db_size_on_disk;"))
        {
            // - LOG -
            file.open(QIODevice::Append | QIODevice::Text);
            out << "-> DataBase - Not possible to read the table!" << endl;
            file.close();
            // - LOG -
        }
        else
        {
            QSqlRecord rec = query.record();
            while(query.next())
            {
                sizeOnDisk = query.value(rec.indexOf("KB")).toInt();

                // - LOG -
                file.open(QIODevice::Append | QIODevice::Text);
                out << "-> DataBase size on disk = " << sizeOnDisk << endl;
                file.close();
                // - LOG -
            }
        }
    }
    db.close();

    // - LOG -
    file.open(QIODevice::Append | QIODevice::Text);
    out << "-> DataBase close - Ok  Return value = " << sizeOnDisk << endl;
    file.close();
    // - LOG -
    /** End database connect **/

    return sizeOnDisk;
}

int handle_node_snmpExtended(netsnmp_mib_handler          *handler,
                             netsnmp_handler_registration *reginfo,
                             netsnmp_agent_request_info   *reqinfo,
                             netsnmp_request_info         *requests)
{
    struct snmp_pdu *response;
    struct variable_list *vars;

    u_long bytesWaiting = -12345;

    DEBUGMSGTL(("SNMPExtended",
                "Initalizing SNMPExtended scalar integer.  Default value = %d\n",
                SNMPExtended));

    QFile file;
    file.setFileName("SNMPExtended_LOG.txt");
    QTextStream out(&file);

    //       ->> snmpget -c public -v 2c localhost .1.3.6.1.4.1.8072.2.5.1.1.1.0
    //return ->> NET-SNMP-EXAMPLES-MIB::netSnmpExamples.5.1.1.1.0 = INTEGER: 38048
    if (reqinfo->mode == MODE_GET)
    {
        // - LOG -
        file.open(QIODevice::Append | QIODevice::Text);
        out << "\n---> handle_node_snmpExtended Init - Ok\n-> DEBUGMSGTL - Ok  Default value = " << SNMPExtended << endl;
        file.close();
        // - LOG -

        SNMPExtended = database_size(); //get database size

        bytesWaiting = (u_long) SNMPExtended;
        snmp_set_var_typed_value(requests->requestvb, ASN_INTEGER, (u_char *) & bytesWaiting, sizeof(int)); //set value

        // - LOG -
        file.open(QIODevice::Append | QIODevice::Text);
        out << "-> MODE_GET - Ok  Value = " << bytesWaiting << endl;
        file.close();
        // - LOG -

        return SNMP_ERR_NOERROR;
    }

    //       ->> snmpset -c private -v 2c localhost .1.3.6.1.4.1.8072.2.5.1.1.1.0 i 12345
    //return ->> NET-SNMP-EXAMPLES-MIB::netSnmpExamples.5.1.1.1.0 = INTEGER: 12345
    //----------------------------------- ore --------------------------------------------
    //       ->> snmpset -c private -v 2c localhost .1.3.6.1.4.1.8072.2.5.1.1.1.0 i 111
    //return ->> NET-SNMP-EXAMPLES-MIB::netSnmpExamples.5.1.1.1.0 = INTEGER: 2
    if (reqinfo->mode == MODE_SET_COMMIT)
    {
        // - LOG -
        file.open(QIODevice::Append | QIODevice::Text);
        out << "\n---> handle_node_snmpExtended Init - Ok\n-> DEBUGMSGTL - Ok  Default value = " << SNMPExtended << endl;
        file.close();
        // - LOG -

        response = reqinfo->asp->orig_pdu;
        vars = response->variables;

        int varInt = -111;

        if(vars->type == ASN_INTEGER)
        {
            varInt = (int) *vars->val.integer;

            if(111 == varInt)
            {
                bytesWaiting = 2;
            }
            else
            {
                bytesWaiting = (u_long) varInt;
            }
        }
        else
            return SNMP_ERR_GENERR;

        SNMPExtended = (int) bytesWaiting; //save default value
        snmp_set_var_typed_value(requests->requestvb, ASN_INTEGER, (u_char *) & bytesWaiting, sizeof(int)); //set value

        // - LOG -
        file.open(QIODevice::Append | QIODevice::Text);
        out << "-> MODE_SET_COMMIT - Ok  Value = " << bytesWaiting << endl;
        file.close();
        // - LOG -

        return SNMP_ERR_NOERROR;
    }
    else
    {
        //if other MODE
        return SNMP_ERR_NOERROR;
    }
}

void deinit_SNMPExtended(void)
{
    unregister_mib(SNMPExtended_oid,OID_LENGTH(SNMPExtended_oid));

    // - LOG -
    QFile file;
    file.setFileName("SNMPExtended_LOG.txt");
    QTextStream out(&file);
    file.open(QIODevice::Append | QIODevice::Text);
    out << "-> Unregister_mib - Ok" << endl;
    file.close();
    // - LOG -
}

#ifdef __cplusplus
}
#endif


Прокомментировал все что могло бы вызвать вопросы в самом коде.
MIB-файл и настройки net-snmp не трогал.
Данный вариант обрабатывает каждый запрос который поступает от клиента/менеджера:

Код

intelect@linux-bf9n:/usr/bin> ./snmpset -c private -v 2c localhost .1.3.6.1.4.1.8072.2.5.1.1.1.0 i 11123
NET-SNMP-EXAMPLES-MIB::netSnmpExamples.5.1.1.1.0 = INTEGER: 11123

intelect@linux-bf9n:/usr/bin> ./snmpget -c public -v 2c localhost .1.3.6.1.4.1.8072.2.5.1.1.1.0
NET-SNMP-EXAMPLES-MIB::netSnmpExamples.5.1.1.1.0 = INTEGER: 38048

intelect@linux-bf9n:/usr/bin> ./snmpset -c private -v 2c localhost .1.3.6.1.4.1.8072.2.5.1.1.1.0 i 111
NET-SNMP-EXAMPLES-MIB::netSnmpExamples.5.1.1.1.0 = INTEGER: 2
 

Надеюсь не зря разгребал эту штуку   smile  и это еще кому-то пригодиться  smile 
PM MAIL   Вверх
svlary
Дата 2.9.2011, 05:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 207
Регистрация: 8.9.2009

Репутация: 4
Всего: 4



Цитата(kyzia887 @  1.9.2011,  14:35 Найти цитируемый пост)
это еще кому-то пригодиться

  Ну, во всяком случае, мне было очень интересно ! smile Спасибо !
PM MAIL   Вверх
kyzia887
Дата 7.9.2011, 13:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 21
Регистрация: 26.8.2011

Репутация: 1
Всего: 1



Довинтил во все выше описанное еще создание таблицы. 
MIB-файл теперь имеет следующую структуру:
NET-SNM-ITELECT-MIB.txt
Код

NET-SNMP-INTELECT-MIB DEFINITIONS ::= BEGIN
IMPORTS
    netSnmpExamples                FROM NET-SNMP-EXAMPLES-MIB
    OBJECT-TYPE, Integer32,
    MODULE-IDENTITY                FROM SNMPv2-SMI
    MODULE-COMPLIANCE, OBJECT-GROUP        FROM SNMPv2-CONF;

netSnmpIntelectMIB MODULE-IDENTITY
    LAST-UPDATE  "201108300000Z"        --30 august 2011
    ORGANIZATION "zzzz"
    CONTACT-INFO "zzzz"
    DESCRIPTION "Mib for intelect."
    ::= { netSnmpExamples 5 }

nstIntelectMibObjects        OBJECT IDENTIFIER ::= { netSnmpIntelectMIB 1 }

nstIntelectAgentModules        OBJECT IDENTIFIER ::= { nstIntelectMibObjects 1 }

nstIntelectTables        OBJECT IDENTIFIER ::= { nstIntelectAgentModules 1 }

SNMPExtended OBJECT-TYPE
    SYNTAX        Integer32
    MAX-ACCESS    read-write
    STATUS        current
    DESCRIPTION
          "This is test object for intelect"
    DEFVAL { 333 }
    ::= { nstIntelectAgentModules 1 }

MyTestTables OBJECT-TYPE
    SYNTAX        SEQUENCE OF NSTMyTestTables
    MAX-ACCESS    read-only
    STATUS        current
    DESCRIPTION
        "This test tables"
    ::= { nstIntelectTables 1 }

nstMyTestTables OBJECT-TYPE
    SYNTAX        NSTMyTestTables
    MAX-ACCESS    read-only
    STATUS        current
    DESCRIPTION
        "A row value"
    INDEX { nstTableColumn }
    ::= { MyTestTables 1 }

NSTMyTestTables ::= SEQUENCE {
    nstTableColumn        INTEGER,
    nstTableColumnNext    INTEGER
}

nstTableColumn OBJECT-TYPE
    SYNTAX        INTEGER
    MAX-ACCESS    read-only
    STATUS        current
    DESCRIPTION " "

    ::= { nstMyTestTables 1 }

nstTableColumnNext OBJECT-TYPE
    SYNTAX        INTEGER
    MAX-ACCESS    read-only
    STATUS        current
    DESCRIPTION " "

    ::= { nstMyTestTables 2 }

END


Проверяем структуру нового MIB-файла (см. выше) и должны получить что-то вроде этого:
Код

+--netSnmpIntelectMIB(5)
      |
     +-- nstIntelectMibObjects(1)
            |
            +--nstIntelectAgentModules(1)
                  |
                  +-- -RW- Integer32 SNMPExtended(1)
                  |
                  +--MyTestTables(1)
                  |     |
                  |     +--nstMyTestTables(1)
                  |           |  Index: nstTableColumn
                  |           |
                  |           +-- -R-- INTEGER   nstTableColumn(1)
                  |           +-- -R-- INTEGER   nstTableColumnNext(2)
                  |                  
                  +--nstIntelectTables(1)


Конфигурационный файл Net-SNMP стал выглядеть так (подключаю дополнительный новый модуль, который будет создавать таблицу):
snmpd.conf
Код

syslocation Server Room
syscontact Sysadmin (root@localhost)
rocommunity public 127.0.0.1
rwcommunity private 127.0.0.1
dlmod SNMPExtended /home/intelect/soft/SNMPExtended.so
dlmod MyTestTables     /home/intelect/soft/MyTestTables.so


Сам код имеет следующий вид:
MyTestTables.h
Код

#ifndef MYTESTTABLES_H
#define MYTESTTABLES_H

#ifdef __cplusplus
extern "C" {
#endif

#include <net-snmp/net-snmp-config.h>
#include <net-snmp/net-snmp-includes.h>
#include <net-snmp/agent/net-snmp-agent-includes.h>

// function declarations
void init_MyTestTables(void);
int handle_node_MyTestTables(netsnmp_mib_handler          *handler,
                             netsnmp_handler_registration *reginfo,
                             netsnmp_agent_request_info   *reqinfo,
                             netsnmp_request_info         *requests);
void deinit_MyTestTables(void);

#ifdef __cplusplus
}
#endif

#endif // MYTESTTABLES_H



MyTestTables.cpp
Код

#include "MyTestTables.h"

#ifdef __cplusplus
extern "C" {
#endif

netsnmp_table_data_set *table_set;
oid MyTestTables_oid[] = { 1, 3, 6, 1, 4, 1, 8072, 2, 5, 1, 1, 1 };

void init_MyTestTables(void)
{
    DEBUGMSGTL(("MyTestTables",
                "Initializing the MyTestTables module\n"));

    table_set = netsnmp_create_table_data_set("MyTestTables");

    // allow the creation of new rows via SNMP SETs
    table_set->allow_creation = 1;

    // set up what a row "should" look like, starting with the index
    netsnmp_table_dataset_add_index(table_set, ASN_INTEGER);

    // define what the columns should look like.
    netsnmp_table_set_add_default_row(table_set,
                                      // column 2 = INTEGER,
                                      // writable = 1,
                                      // default value = NULL,
                                      // default value len = 0
                                      2, ASN_INTEGER, 1, NULL, 0);

    // if we wanted to handle specific data in a specific way, or note
    // when requests came in we could change the NULL below to a valid
    // handler method in which we could over ride the default
    // behaviour of the table_dataset helper
    netsnmp_handler_registration *MyTestTablesModule;
    MyTestTablesModule = netsnmp_create_handler_registration("Module MyTestTables",
                                                             handle_node_MyTestTables,
                                                             MyTestTables_oid,
                                                             OID_LENGTH(MyTestTables_oid),
                                                             HANDLER_CAN_RONLY);


    netsnmp_register_table_data_set(MyTestTablesModule,
                                    table_set,
                                    NULL);

    // register the table
    netsnmp_register_auto_data_table(table_set, NULL);

    DEBUGMSGTL(("MyTestTables",
                "Done initalizing MyTestTables module\n"));
}

int handle_node_MyTestTables(netsnmp_mib_handler *handler,
                             netsnmp_handler_registration *reginfo,
                             netsnmp_agent_request_info *reqinfo,
                             netsnmp_request_info *requests)
{
    int numberProc = 5;
    for(int i = 0; i < numberProc; i++)
    {
        //add row in table
        // create the a row for the table, and add the data
        netsnmp_table_row *row;
        row = netsnmp_create_table_data_row();

        // set the index to the table row
        u_long tableIndex = (u_long) i;
        netsnmp_table_row_add_index(row, ASN_INTEGER, (u_char*) & tableIndex, sizeof(int));

        // set column 2 to be the table
        u_long tableValue = (u_long) (numberProc + i);
        netsnmp_set_row_column(row, 2, ASN_INTEGER, (u_char *) & tableValue, sizeof(int));
        netsnmp_mark_row_column_writable(row, 2, 1);  // make writable via SETs

        // add the row to the table
        netsnmp_table_dataset_add_row(table_set, row);
    }

    return SNMP_ERR_NOERROR;
}

void deinit_MyTestTables(void)
{
    netsnmp_table_dataset_remove_and_delete_row(table_set, NULL);
    netsnmp_delete_table_data_set(table_set);
    table_set = NULL;
}

#ifdef __cplusplus
}
#endif


При запросе информации получим следующее:
Код

intelect@linux-bf9n:/usr/bin> ./snmpwalk -c public -v 2c localhost .1.3.6.1.4.1.8072.2.5.1.1.1.1.2
NET-SNMP-EXAMPLES-MIB::netSnmpExamples.5.1.1.1.1.2.0 = INTEGER: 5
NET-SNMP-EXAMPLES-MIB::netSnmpExamples.5.1.1.1.1.2.1 = INTEGER: 6
NET-SNMP-EXAMPLES-MIB::netSnmpExamples.5.1.1.1.1.2.2 = INTEGER: 7
NET-SNMP-EXAMPLES-MIB::netSnmpExamples.5.1.1.1.1.2.3 = INTEGER: 8
NET-SNMP-EXAMPLES-MIB::netSnmpExamples.5.1.1.1.1.2.4 = INTEGER: 9


Если возникнут вопросы, пишите, попробую объяснить или разбраться что к чему  smile 
PM MAIL   Вверх
kyzia887
Дата 9.9.2011, 10:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 21
Регистрация: 26.8.2011

Репутация: 1
Всего: 1



Небольшое дополнение по таблицам  smile 
Для того чтобы таблица каждый раз пересоздавала строки переписал код следующим образом:
MyTestTables.cpp
Код

#include "MyTestTables.h"
#ifdef __cplusplus
extern "C" {
#endif

int numberProcessFound = 0; //defaul number process
netsnmp_table_data_set *table_set;
oid MyTestTables_oid[] = { 1, 3, 6, 1, 4, 1, 8072, 2, 5, 1, 1, 1 };
void init_MyTestTables(void)
{
    DEBUGMSGTL(("MyTestTables",
                "Initializing the MyTestTables module\n"));
    table_set = netsnmp_create_table_data_set("MyTestTables");
    // allow the creation of new rows via SNMP SETs
    table_set->allow_creation = 1;
    // set up what a row "should" look like, starting with the index
    netsnmp_table_dataset_add_index(table_set, ASN_INTEGER);
    // define what the columns should look like.
    netsnmp_table_set_add_default_row(table_set,
                                      // column 2 = INTEGER,
                                      // writable = 1,
                                      // default value = NULL,
                                      // default value len = 0
                                      2, ASN_INTEGER, 1, NULL, 0);
    // if we wanted to handle specific data in a specific way, or note
    // when requests came in we could change the NULL below to a valid
    // handler method in which we could over ride the default
    // behaviour of the table_dataset helper
    netsnmp_handler_registration *MyTestTablesModule;
    MyTestTablesModule = netsnmp_create_handler_registration("Module MyTestTables",
                                                             handle_node_MyTestTables,
                                                             MyTestTables_oid,
                                                             OID_LENGTH(MyTestTables_oid),
                                                             HANDLER_CAN_RONLY);
    netsnmp_register_table_data_set(MyTestTablesModule,
                                    table_set,
                                    NULL);
    // register the table
    netsnmp_register_auto_data_table(table_set, NULL);
    DEBUGMSGTL(("MyTestTables",
                "Done initalizing MyTestTables module\n"));
}
int handle_node_MyTestTables(netsnmp_mib_handler *handler,
                             netsnmp_handler_registration *reginfo,
                             netsnmp_agent_request_info *reqinfo,
                             netsnmp_request_info *requests)
{
    /** delete all row **/
    if(numberProcessFound != 0)
    {
        netsnmp_table_row *firstRow = netsnmp_table_data_set_get_first_row(table_set);
        while(firstRow != NULL)
        {
            netsnmp_table_row *nextRow = netsnmp_table_data_set_get_next_row(table_set, firstRow);
            netsnmp_table_dataset_remove_row(table_set, firstRow);
            firstRow = nextRow;
        }
    }
    /** -------------- **/

    int numberProc = 5;
    numberProcessFound = numberProc; //set new defaul number process

    for(int i = 0; i < numberProc; i++)
    {
        //add row in table
        // create the a row for the table, and add the data
        netsnmp_table_row *row;
        row = netsnmp_create_table_data_row();
        // set the index to the table row
        u_long tableIndex = (u_long) i;
        netsnmp_table_row_add_index(row, ASN_INTEGER, (u_char*) & tableIndex, sizeof(int));
        // set column 2 to be the table
        u_long tableValue = (u_long) (numberProc + i);
        netsnmp_set_row_column(row, 2, ASN_INTEGER, (u_char *) & tableValue, sizeof(int));
        netsnmp_mark_row_column_writable(row, 2, 1);  // make writable via SETs
        // add the row to the table
        netsnmp_table_dataset_add_row(table_set, row);
    }
    return SNMP_ERR_NOERROR;
}
void deinit_MyTestTables(void)
{
    netsnmp_table_dataset_remove_and_delete_row(table_set, NULL);
    netsnmp_delete_table_data_set(table_set);
    table_set = NULL;
}
#ifdef __cplusplus
}
#endif


Все остальное осталось прежним. Всем успехов  smile 

Это сообщение отредактировал(а) kyzia887 - 9.9.2011, 10:39
PM MAIL   Вверх
azote
Дата 30.10.2012, 12:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 1
Регистрация: 30.10.2012

Репутация: нет
Всего: нет



Спасибо за статью. 
Есть такой вопрос. Могу ли я как-то создать обработчик всех OID'ов начиная с определенного, например, .1.3.6.1.4.1.8072...., и уже в своем обработчике перебирать дочерние номера и решать какому из них какое значение устанавливать?
Ведь, как я понял, у Вас в примере показывается, как обрабатывать определенные значения OID'ов.
И еще вопрос. Могу ли я создать подобное расширение агента без внедрение соответствующего MIB-модуля?
PM MAIL   Вверх
kyzia887
Дата 21.12.2012, 15:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 21
Регистрация: 26.8.2011

Репутация: 1
Всего: 1



Цитата

Спасибо за статью. 
Есть такой вопрос. Могу ли я как-то создать обработчик всех OID'ов начиная с определенного, например, .1.3.6.1.4.1.8072...., и уже в своем обработчике перебирать дочерние номера и решать какому из них какое значение устанавливать?
Ведь, как я понял, у Вас в примере показывается, как обрабатывать определенные значения OID'ов.
И еще вопрос. Могу ли я создать подобное расширение агента без внедрение соответствующего MIB-модуля? 


Вот на счет первого вопроса к сожалению не подскажу, т.к. сам это задачу не решал, а по поводу внедрения MIB-файла, то вроде бы можно и без него.  smile 
PM MAIL   Вверх
igormat
  Дата 17.9.2013, 11:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 3
Регистрация: 17.9.2013

Репутация: нет
Всего: нет



Добрый день, а никто не может посоветовать литературу по Net-SNMP с точки зрения девелоперов? А то туториалы на официальном сайте очень скудные.
PM MAIL   Вверх
Страницы: (3) Все [1] 2 3 
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С/С++: Программирование под Unix/Linux"
xvr
  • Проставьте несколько ключевых слов темы, чтобы её можно было легче найти.
  • Не забывайте пользоваться кнопкой "Код".
  • Вопросы мобильной разработки тут
  • Телепатов на форуме нет! Задавайте чёткий, конкретный и полный вопрос. Указывайте полностью ошибки компилятора и компоновщика.
  • Новое сообщение должно иметь прямое отношение к разделу форума. Флуд, флейм, оффтопик запрещены.
  • Категорически запрещается обсуждение вареза, "кряков", взлома программ и т.д.

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, xvr.

 
 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Программирование под Unix/Linux | Следующая тема »


 




[ Время генерации скрипта: 0.2105 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.