Rtnetlink - Как запросить таблицу, кроме RT_TABLE_MAINC++

Программы на C++. Форум разработчиков
Ответить
Anonymous
 Rtnetlink - Как запросить таблицу, кроме RT_TABLE_MAIN

Сообщение Anonymous »

У меня есть система Linux (Ubuntu 20.04, в этом тесте) с несколькими таблицами маршрутизации. < /p>

Код: Выделить всё

> sudo cat /etc/iproute2/rt_tables
#
# reserved values
#
255     local
254     main
253     default
0       unspec
#
# local
#
1       mytable

< /code>
Таблица Mytable имеет маршрут: < /p>
> ip route show table 1
10.0.0.0/8 via 172.40.50.1 dev ens192
< /code>
и основная таблица имеет маршрут по умолчанию: < /p>
> ip route show
default via 172.40.60.1 dev ens192 proto static metric 100
...
Но никаких других маршрутов для сети 10.0.0.0/8. Я заполняю поле rtm_table в моем сообщении NetLink следующим образом: < /p>
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include

class RtNetlink
{
public:
RtNetlink()
{
m_sockfd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
m_message = (struct nlmsghdr *)m_buffer;
}

~RtNetlink()
{
::close(m_sockfd);
}

bool send_message(struct nlmsghdr * msg, int msg_size)
{
struct sockaddr_nl nladdr;

memset(&nladdr, 0, sizeof(nladdr));
nladdr.nl_family = AF_NETLINK;

sendto(m_sockfd, msg, msg_size, 0, (struct sockaddr *)&nladdr, sizeof(nladdr));
m_message_size = 0;
m_is_done = false;
m_message = (struct nlmsghdr *)m_buffer;

return true;
}

const struct nlmsghdr * get_next_message()
{
struct nlmsghdr * ret = NULL;

if (m_is_done)
{
return NULL;
}

if (NLMSG_OK(m_message, m_message_size))
{
if (m_message->nlmsg_type == NLMSG_DONE)
{
m_is_done = true;
return NULL;
}
}
else
{
m_message_size = recv(m_sockfd, m_buffer, sizeof(m_buffer), 0);
m_message = (struct nlmsghdr *)m_buffer;

if (! (m_message->nlmsg_flags & NLM_F_MULTI))
{
m_is_done = true;
}
else if (m_message->nlmsg_type == NLMSG_DONE)
{
m_is_done = true;
return NULL;
}
}

ret = m_message;
m_message = NLMSG_NEXT(m_message, m_message_size);
return ret;
}

private:
char m_buffer[16384];
struct nlmsghdr * m_message;
int m_message_size{0};
bool m_is_done{true};
int m_sockfd{-1};
};

bool get_gateway(const char* destination, int table)
{
RtNetlink nlcomm;
struct {
struct nlmsghdr header;
struct rtmsg message;
unsigned char buffer[256];
} request;
struct rtattr * attributes[RTA_MAX + 1];

in_addr in;
inet_aton(destination, &in);
unsigned char *dest_bytes = (unsigned char*)&in.s_addr;
int dest_len = sizeof(struct in_addr);

memset(&request, 0, sizeof(request));

request.header.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
request.header.nlmsg_flags = NLM_F_REQUEST;
request.header.nlmsg_type = RTM_GETROUTE;
request.header.nlmsg_seq = lrand48();
request.message.rtm_family = AF_INET;
request.message.rtm_table = table;

struct rtattr * rta = (struct rtattr *)(((char *)&request.header) + NLMSG_ALIGN(request.header.nlmsg_len));
rta->rta_type = RTA_DST;
rta->rta_len = RTA_LENGTH(dest_len);
memcpy(RTA_DATA(rta), dest_bytes, dest_len);
request.header.nlmsg_len = NLMSG_ALIGN(request.header.nlmsg_len) + rta->rta_len;

nlcomm.send_message(&request.header, request.header.nlmsg_len);

const struct nlmsghdr * response;
while ((response = nlcomm.get_next_message()) != NULL)
{
struct rtmsg * rmsg = (struct rtmsg *)NLMSG_DATA(response);
memset(attributes, 0, sizeof(attributes));

int rlen;
int from_table=-1;
for (rta = (struct rtattr *)RTM_RTA(rmsg), rlen = RTM_PAYLOAD(response);
RTA_OK(rta, rlen);
rta = RTA_NEXT(rta, rlen))
{
if (rta->rta_type < RTA_MAX)
{
attributes[rta->rta_type] = rta;
if (rta->rta_type == RTA_TABLE)
{
from_table = *((int *)RTA_DATA(attributes[RTA_TABLE]));
printf("Found table %d\n", from_table);
}
if (rta->rta_type == RTA_GATEWAY)
{
printf("Probed table %d, found answer in table %d\n", table, from_table);
}
}
}
}
return true;
}

int main(int argc, char **argv)
{
get_gateway(argv[1], atoi(argv[2]));
}
< /code>
зонд работает, но rta_table всегда rt_table_main: < /p>

> ./a.out 10.2.3.4 1
Found table 254
Probed table 1, found answer in table 254
> ./a.out 10.2.3.4 2
Found table 254
Probed table 2, found answer in table 254
> ./a.out 10.2.3.4 254
Found table 254
Probed table 254, found answer in table 254
> ./a.out 10.2.3.4 255
Found table 254
Probed table 255, found answer in table 254
< /code>
Итак, пара вопросов: < /p>

Мое понимание здесь неверно? Разве невозможно исследовать произвольные таблицы?>

Подробнее здесь: https://stackoverflow.com/questions/755 ... table-main
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C++»