воскресенье, 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

воскресенье, 31 января 2016 г.

Настройка TFTP-сервера tftpd-hpa во FreeBSD

Ранее я уже делал краткую заметку о том, как установить и настроить TFTP-сервер tftpd-hpa в Debian Wheezy: http://vladimir-stupin.blogspot.ru/2014/05/tftp-tftpd-hpa.html. Во FreeBSD подобная конфигурация настраивается аналогично. На всякий случай решил её зафиксировать тут, чтобы потом было на что сослаться (есть высокая вероятность, что сослаться неожиданно понадобится).

Если ранее на компьютере использовался TFTP-демон, запускаемый демоном inetd, отключим его в файле /etc/inetd.conf, закоментировав строчки, начинающиеся с tftp. Перезапускаем демона inetd:
# /etc/rc.d/inetd restart
Установим нового TFTP-демона из порта:
# cd /usr/ports/ftp/tftp-hpa
# make install
Включаем и настраиваем установленный TFTP-демон в файле /etc/rc.conf:
tftpd_enable="YES"
tftpd_flags="--ipv4 --secure --create --user tftp --umask 027 --permissive --address 0.0.0.0:69 /var/tftp"
Создаём группу и пользователя, от имени которых будет рабоатать TFTP-демон:
# pw group add tftp
# pw user add tftp -c 'TFTPd user' -d /var/tftp -g tftp -M 0750 -s /bin/nologin
Содаём каталог для файлов TFTP-демона, выставляем права доступа:
# mkdir /var/tftp
# chown tftp:tftp /var/tftp
# chmod u=rwx,g=rx,o= /var/tftp
Запускаем TFTP-демона:
# /usr/local/etc/rc.d/tftpd start