воскресенье, 14 февраля 2016 г.

Исправление Python-прослойки библиотеки Net-SNMP во FreeBSD

Ещё одна заметка, ссылка на которую мне может в дальнейшем понадобиться. В целом заметка повторяет предыдущую, но адаптирована на этот раз применительно к FreeBSD.

Ниже описано, как я исправил отправку параметров типа IPADDR в запросах SNMP SET в пакете net-snmp-5.7.2_2 во FreeBSD 8.2 своим патчем.

Перейдём в каталог порта:
# cd /usr/ports/net-mgmt/net-snmp
Создадим в каталоге порта files файл патча под именем patch-python__netsnmp__client_intf.c со следующим содержимым:
--- python/netsnmp/client_intf.c        2010-02-10 15:04:31.000000000 +0500
+++ python.new/netsnmp/client_intf.c    2014-12-21 18:10:26.677816256 +0500
@@ -979,14 +979,20 @@

       case TYPE_IPADDR:
         vars->type = ASN_IPADDRESS;
-        vars->val.integer = (long *)malloc(sizeof(long));
+        in_addr_t addr = 0;
         if (val)
-            *(vars->val.integer) = inet_addr(val);
+            addr = inet_addr(val);
+
+        if (addr && (addr != -1)) {
+            vars->val.string = malloc(sizeof(in_addr_t));
+            vars->val_len = sizeof(in_addr_t);
+            memcpy(vars->val.string, &addr, sizeof(in_addr_t));
+        }
         else {
             ret = FAILURE;
-            *(vars->val.integer) = 0;
+            vars->val.string = (u_char*)strdup("");
+            vars->val_len = 0;
         }
-        vars->val_len = sizeof(long);
         break;

       case TYPE_OBJID:
@@ -2426,6 +2432,7 @@
          goto done;
        }
        memcpy(tmp_val_str, val, tmplen);
+        tmp_val_str[tmplen] = '\0';
        if (type==TYPE_INTEGER && use_enums && tp && tp->enums) {
          for(ep = tp->enums; ep; ep = ep->next) {
            if (val && !strcmp(ep->label, val)) {
Теперь очистим порт и распакуем исходники, не накладывая никаких патчей:
# make clean
# make extract
Перейдём в каталог с распакованными исходными текстами:
# cd work/net-snmp-5.7.2/
Наложим имеющийся патч, игнорируя пробелы и несовпадение номеров строк, указанных в патче:
# patch -Np0 --ignore-whitespace < ../../files/patch-python__netsnmp__client_intf.c
Перейдём в каталог порта и пересоздадим файл патча files/patch-python__netsnmp__client_intf.c, в котором теперь пробелы и номера строк выставятся так, чтобы соответствовать исходникам из порта:
# cd ../..
# make makepatch
Очистим теперь файлы, созданные портом:
# make clean
Распакуем и наложим на исходники все патчи, включая наш:
# make patch
Если ошибок не было, можно собрать порт:
# make
Если порт собрался успешно, его можно установить:
# make install
Если порт ранее уже был установлен из той же версии портов, с которой мы только что работали, то можно безболезненно заменить файлы порта:
# make deinstall
# make install
Если же имеющийся в системе пакет был установлен из другой версии портов, тогда для обновления этого порта и всех зависящих от него рекомендую воспользоваться инструментом portupgrade. Рассмотрение этого инструмента я оставлю за рамками этой заметки.

воскресенье, 7 февраля 2016 г.

Исправление Python-прослойки библиотеки Net-SNMP

Заметка, ссылка на которую мне может в дальнейшем понадобиться.

Из всех SNMP-модулей Python для работы с SNMP наименьшей гадостью мне показалась официальная прослойка библиотеки Net-SNMP для Python. Её разработчики не так прониклись Java-подходом, как разработчики библиотеки pysnmp, воспользоваться которой невозможно без написания трёхэтажного кода с использованием всех фабрик классов, прокси-классов и преобразования типов, родных для Python, в классы, используемые библиотекой. Библиотека pysnmp выглядит в Python совершенно чужеродно, потребляет мнго ресурсов и плохо документирована.

Прослойка библиотеки Net-SNMP для Python выглядит очень куцей, однако для моих нужд её оказывалось достаточно, пока я не попробовал с её помощью инициировать резервное копирование коммутатора. Оказалось, что в ней неправильно реализовано преобразование параметров типа IPADDR в запросах SNMP SET. Официальный патч в тот момент я не нашёл и решил попробовать исправить библиотеку самостоятельно, что мне и удалось. Официальный патч можно найти тут: Python bindings: Fix the out-of-bounds write. Я же подготовил свой патч, использование которого будет описано ниже.

Скачиваем патч:
$ wget http://stupin.su/files/netsnmp543_python_client.diff
Скачиваем и распаковываем в текущий каталог исходные тексты пакета:
# apt-get source libsnmp-python
Скачиваем и устанавливаем зависимости, необходимые для сборки пакета:
# apt-get build-dep net-snmp
Скачиваем и устанавливаем инструменты для сборки:
# apt-get install dpkg-dev
# apt-get install fakeroot
# apt-get install devscripts
Переходим в каталог с исходными текстами пакета и накладываем патч:
# cd net-snmp-5.4.3~dfsg/
# patch -Np0 --ignore-whitespace < ../netsnmp543_python_client.diff
Добавим наш патч в будущий пакет:
# dpkg-source --commit
Укажем имя патча snmp_set_fixed. В окне редактирования информации о патче введём что-нибудь подобное следующему (вплоть до двух нижних строчек, с которых начинается сам текст патча):
Description: Fixed snmp set operation in python-snmp
Fixed snmp set operation in python-snmp
 .
 net-snmp (5.4.3~dfsg-2.8+deb7u1) stable-proposed-updates; urgency=medium
 .
--- net-snmp-5.4.3~dfsg.orig/python/netsnmp/client_intf.c
+++ net-snmp-5.4.3~dfsg/python/netsnmp/client_intf.c
Теперь отметим изменения, внесённые в пакет:
# dch -i
В окне редактирования введём информацию о нашей версии пакета:
net-snmp (5.4.3~dfsg-2.8+deb7ufanet) UNRELEASED; urgency=low

  * Fixed snmp set in libsnmp-python

 -- Vladimir Stupin <vladimir@stupin.su>  Thu, 21 Jan 2016 16:58:40 +0500
Осталось собрать пакет:
# dpkg-buildpackage -us -uc -rfakeroot
Теперь его можно установить в систему:
# cd ..
# dpkg -i libsnmp-python_5.4.3~dfsg-2.8+deb7u1_amd64.deb