netlink_client
Данный проект создан для упрощения работы с конфигурацией сетевых интерфейсов в linux. Более подробную информацию можно узнать на хабре.
Структура репозитория
В папке scripts хранятся необходимые для работы скрипты.
В папке src хранится исходный код проекта.
Среда разработки
Для разработки требуется следующее:
1. c++ компилятор для сборки
2. make для сборки
3. docker для тестирования
4. strace для изучения пакетов
Сборка
Сборка производится в хостовой системе.
Для сборки достаточно просто вызвать make
в корне. Все бинарные файлы будут находиться в папке src.
Тестирование
Для проверки программ используется docker контейнер. Его использование необязательно, но лучше проводить все изменения интерфейсов в контейнере.
Для создания контейнера выполните скрипт create_image.sh
, лежащий в папке scripts.
Первый запуск
Перед началом работы откройте два терминала.
1. В первом терминале выполните команду make
для сборки проекта.
2. Во втором терминале запустите docker контейнер с помощью скрипта launch_container.sh
.
3. В первом терминале перейдите в сетевой namespace контейнера с помощью скрипта to_docker_ns.sh
Теперь в первом терминале можно выполнять make для сборки проекта и запускать готовые программы, а во втором можно производить настройку системы.
Примеры
Пример 1
В примере демонстрируется самый базовый функционал: создание интерфейса, его изменение и удаление, а также вывод его названия.
Выполните все пункты шага “Первый запуск”. Запустите первый пример, его исполняемый файл называется example1 и он находится в папке src.
Во втором терминале создайте простой dummy интерфейс с помощью команды:
ip link add dev dummy0 type dummy
Вы получите примерно такой вывод:
New interface: 2
name="dummy0"
Для удаления этого интерфейса используйте команду:
ip link del dev dummy0 type dummy
Пример 2
В этом примере демонстрируется более сложное сообщение, имеющее вложенные атрибуты. Выполните все пункты шага “Первый запуск”. Запустите второй пример, его исполняемый файл называется example2 и он находится в папке src.
Во втором терминале создайте bridge интерфейс с помощью команды:
ip link add dev bridge0 type bridge
Вы получите примерно такой вывод:
New interface: 3
name="bridge0"
type="bridge"
Для удаления этого интерфейса используйте команду:
ip link del dev bridge0 type bridge
Пример 3
В данном примере показывается пример возможных ошибок. Выполните все пункты шага “Первый запуск”. Запустите второй пример, его исполняемый файл называется example3 и он находится в папке src.
Создайте один dummy интерфейс и один bridge с помощью команд:
ip link add dev dummy0 type dummy
ip link add dev bridge0 type bridge
Если вы сделали это ранее, то этот шаг можно пропустить.
Добавьте dummy интерфейс в bridge с помощью команды
ip link set dev dummy0 master bridge0
Добавьте интерфейс в диапазон вланов:
bridge vlan add vid 10-20 dev dummy0
Добавьте интерфейс в один vlan
bridge vlan add vid 25 dev dummy0
Давайте посмотрим на код из примера
if (flag & BRIDGE_VLAN_INFO_RANGE_BEGIN)
{
vlan_range_begin = vlan_id;
}
else if (flag & BRIDGE_VLAN_INFO_RANGE_END)
{
for (int i = vlan_range_begin; i <= vlan_id; ++i)
std::cout << i << std::endl;
}
else
{
std::cout << vlan_id << std::endl;
}
Вы получите примерно такой вывод:
New interface: 2
name="dummy0"
Vlans: 1 10 11 12 13 14 15 16 17 18 19 20 25
Если вы посмотрите код, то заметите, что в флаге может передаваться значение начала и конца интервала вланов.
Для удаления интерфейса из влана можно использовать следующие команды:
bridge vlan del vid 10-20 dev dummy0
bridge vlan del vid 25 dev dummy0
Отправка запросов
Если вам нужно получить конфигурацию системы на момент запуска вашей программы, то в сокет нужно отправить запрос и потом можно будет обработать его. Функция для запроса находится в файле send.cpp.
Запустите эту программу для обработки всех интерфейсов в вашей системе.
Внешний поллинг
Если вы хотите интегрировать код в свой проект и у вас уже используется поллинг, то вы легко можете сделать это, так как netlink_client поддерживает это.
Вы должны вызвать метод init для инициализации клиента, а затем передать сокет в ваш epoll. Получить сокет можно с помощью метода get_netlink_socket. Для вызова обработки сообщений используйте метод handle_netlink_message.
Пример того как это можно сделать находится в файле external_epoll.cpp
Дебаг
Для упрощения разработки в классе netlink_client предусмотрена возможность сохранения сообщений в файл. Сообщение обрабатываются в одном из трех методов: handle_rtm_newlink_message, handle_rtm_dellink_message, handle_nlmsg_error_message. В любом из них доступна переменная is_debug_message с помощью которой можно определить необходимость сохраненния сообения в файл.
Также можно поменять шаблон названия файлов. Для этого нужно поменять значение переменной debug_filename.
virtual void handle_rtm_newlink_message(ifinfomsg& message_interface_info, char* data_buf, const std::uint32_t& data_len) noexcept override
{
// No saving message
}
virtual void handle_rtm_dellink_message(ifinfomsg& message_interface_info, char* data_buf, const std::uint32_t& data_len) noexcept override
{
// Save message as file with name debug<packet_counter>
is_debug_message = true;
}
virtual void handle_nlmsg_error_message(int error_code) noexcept override
{
// Save message as file with name my_debug<packet_counter>
is_debug_message = true;
debug_filename = "my_debug";
}
Документация
Для генерации документации вам потребуется doxygen и graphviz. Запустите скрипт gendoc.sh для генерации документации.
Описание
Простая обертка над netlink для работы с конфигурацией сетевых интерфейсов