Здравствуй, Олл
(Slackware 12.2)
Пишу программу, работающую с сырыми сокетами. Нужно - в заголовок IP-пакетов подставлять адрес целевого хоста и свой адрес, с которого пакет уходит в сеть
Проблема: у меня есть несколько интерфейсов. Как (програмно) определить, с какого из них я буду посылать пакет?
Как сделано сейчас: отправляю целевому хосту ICMP/ECHO-пакет (формирование IP-заголовка оставляю за системой). Получаю ICMP/ECHO-REPLY пакет - и из него выдираю адрес своего интерфейса
Есть мнение, что netlink/rtnetlink мне поможет. Действительно ничего попроще нет?
Спасибо
Определение интерфейса - отправителя (сети, netlink, rtnetlink и иже с ними)
Модератор: Модераторы разделов
-
svary
- Сообщения: 49
- ОС: Linux FC-9
Re: Определение интерфейса - отправителя
Насколько я понимаю - никак. Если у Вас на компе стоит два интерфейса (пусть даже физически - на одной карточке), вопрос о том, куда именно уйдет пакет решает РОУТЕР, на основании информации о назначении пакета. Причем, для принятия такого решения, он вполне может "проконсультироваться" с DNS.
Но мне кажется совершенно надуманной сама постановка задачи. Это что - лаба по сетевому программированию ? :-) Если же на "том" конце соединения действительно необходимо узнать адрес отправителя, то это легко сделать с помощью системного вызова :
NAME
getpeername - get name of connected peer socket
SYNOPSIS
#include <sys/socket.h>
int getpeername(int s, struct sockaddr *name, socklen_t *namelen);
DESCRIPTION
getpeername() returns the name of the peer connected to socket s. The namelen argument should be ini-
tialized to indicate the amount of space pointed to by name. On return it contains the actual size of
the name returned (in bytes). The name is truncated if the buffer provided is too small.
-
Portnov
- Модератор
- Сообщения: 1786
- Статус: Матёрый линуксоид
- ОС: Debian testing/unstable
Re: Определение интерфейса - отправителя
Я в своё время сталкивался с таким вопросом. Точного решения не помню, но помню что выдрал его из исходников traceroute.
Работа: Ubuntu 9.10
Дом: Debian testing/unstable и на всякий случай winxp в virtualbox.
Для разнообразия: моя домашняя страница -http://iportnov.ru
Дом: Debian testing/unstable и на всякий случай winxp в virtualbox.
Для разнообразия: моя домашняя страница -http://iportnov.ru
-
Faurn
- Сообщения: 12
Re: Определение интерфейса - отправителя
Проблема в том, что самостоятельно формируя заголовок IP-пакета я должен самостоятельно же прописать в заголовке адрес отправителя - то бишь одного из своих интерфейсов.
Кроме того, для подсчета checksum TCP-пакета приходится брать поле "адрес отправителя" из заголовка IP-пакета.
Программа пишется исключительно just for fun
(Portnov) писал(а):Я в своё время сталкивался с таким вопросом. Точного решения не помню, но помню что выдрал его из исходников traceroute.
Спасибо за наводку. Посмотрим
-
Faurn
- Сообщения: 12
Re: Определение интерфейса - отправителя
Проблема решена. Спасибо traceroute, Portnov и функции getsockname
Кому интересно - код (местами, возможно, не особенно красивый):
Кому интересно - код (местами, возможно, не особенно красивый):
Код: Выделить всё
/* на входе: строка - IP-адрес целевого хоста,
на выходе: in_addr_t (uint32_t) - IP-адрес интерфейса,
с которого от нас уйдет пакет на целевой хост */
in_addr_t getMyIP(const char* dest)
{
int sock = socket(AF_INET,SOCK_RAW,IPPROTO_RAW);
if(sock == -1)
return -1;
struct sockaddr_in sa;
sa.sin_family = AF_INET;
sa.sin_port = 0;
sa.sin_addr.s_addr = inet_addr(dest);
if(connect(sock,(struct sockaddr*) &sa,sizeof(sa)) == -1)
{
close(sock);
return -1;
}
struct sockaddr addr;
socklen_t len = sizeof(addr);
if(getsockname(sock,&addr,&len))
{
close(sock);
return -1;
}
close(sock);
in_addr_t ret = ((struct sockaddr_in*) & addr)->sin_addr.s_addr;
return ret;
}-
svary
- Сообщения: 49
- ОС: Linux FC-9
Re: Определение интерфейса - отправителя
Интересно! Не знаю, насколько это существенно для Вас, но получается (как я и говорил),
что определить интерфейс отправки пакета можно только ПОСЛЕ установления соединения:
Код: Выделить всё
if(connect(sock,(struct sockaddr*) &sa,sizeof(sa)) == -1)В принципе, конечно, соединение устанавливать надо...
Но ведь Вы говорили о сырых пакетах, отправляемых без установления соединения ?
Или я неправильно понял ?