LINUX.ORG.RU

Сокеты по UDP


0

0

Для работы с дейтаграммами я на стороне клиента создаю сокет вызовом socket а затем позылаю желанному серваку запрос sendto. Вопрос когда сокету система присваивает адресс? В момент первого обращения к send, recv, getsockname и пр?

anonymous

Ответ на: комментарий от klalafuda

Там куда вы меня послали ответа на этот вопрос нет. И вообще connect в приведенном мной примере не используется.

anonymous
()
Ответ на: комментарий от anonymous

> Там куда вы меня послали ответа на этот вопрос нет. И вообще connect в приведенном мной примере не используется.

хорошо, тогда наводящий вопрос: какому именно сокету?

// wbr

klalafuda ★☆☆
()

Поправьте меня, если я ошибаюсь - в стандартах это не определено/не требуется. Для UDP сокета, из которого идет передача, адрес автоматически не присваивается, пока не будет явно не будет вызван bind(). Но я видел реализации, где это не так.

anonymous
()
Ответ на: комментарий от anonymous

Уважаемый анонимус а что по вашему принимающая сторона получает в аргументе from при вызове вот этой функции:
ssize_t
recvfrom(int s, void * restrict buf, size_t len, int flags,
struct sockaddr * restrict from, socklen_t * restrict fromlen);
Вот интересно когда оно (адресс) ассоциируется с сокетом. (С учетом что я могу, но не вызываю bind)?

anonymous
()
Ответ на: комментарий от anonymous

В параметре from будет адрес интерфейса, c которого датаграмма ушла. Это значение хранится в IP хедере. В UDP хедере хранится необязательный параметр - значение исходящего порта.

anonymous
()
Ответ на: комментарий от anonymous

> Вот интересно когда оно (адресс) ассоциируется с сокетом. (С учетом что я могу, но не вызываю bind)?

по всей видимости в ядре в момент привязки исходящего пакета к конкретному интерфейсу, через который он будет передан на сервер?

// wbr

klalafuda ★☆☆
()
Ответ на: комментарий от anonymous

Ананимус а вы гений однако, особенно понравилось это:

>В UDP хедере хранится необязательный параметр - значение исходящего порта

что курили что он стал необязательным???

и контрольный вопрос - если он необязательный то как тогда сервер может ответить на адресс который он прочитал в переменную from. Или будете утверждать, что полученное из recvfrom значение from я не могу использовать в sendto?

Собственно IP+порт и есть адресс сокета, и сокет с ним ассоциирован, или как иначе клиентское приложение ответы получает?

anonymous
()
Ответ на: комментарий от klalafuda

Следовательно getsockname должно возвращать ошибку если передачи небыло а интерфейсов в системе много (читай два) так? но такое поведение не в SUS не в POSIX непрописано.

anonymous
()
Ответ на: комментарий от anonymous

> Следовательно getsockname должно возвращать ошибку если передачи небыло а интерфейсов в системе много (читай два) так? но такое поведение не в SUS не в POSIX непрописано.

судя по вопросу я так понимаю, что она возвращает что-то отличное от ошибки? что, если не секрет?

// wbr

klalafuda ★☆☆
()
Ответ на: комментарий от klalafuda

Неполенился своял прогу:

#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <netinet/in.h>
#include <arpa/inet.h>

int main(int argc, char* argv[])
{
int soc, res;
struct sockaddr_in addr;
socklen_t len;
char buf[INET_ADDRSTRLEN];

len= sizeof(struct sockaddr_in);
printf("len: %u\n", len);

soc = socket(PF_INET, SOCK_DGRAM, 0);
res = getsockname(soc, (struct sockaddr*)&addr, &len);

printf("socket: %u\n", soc);
printf("res: %u\n", res);

if ( !res )
{
inet_ntop(AF_INET, &addr.sin_addr, buf, INET_ADDRSTRLEN);
printf("IP: %s port: %u\n", buf, ntohs(addr.sin_port));
}
}

Результат:
len: 16
socket: 3
res: 0
IP: 0.0.0.0 port: 0

Прикольно... щас допилю чтоб чтонибудб кудато посылало и посмотрим на изменения...

А ошибку она (getsockname) действительно не возвращает.

anonymous
()
Ответ на: комментарий от anonymous

добавил еще это:

addr1.sin_family = AF_INET;
addr1.sin_port = htons(53);
res = inet_pton(AF_INET, "192.168.7.1", &dns);
addr1.sin_addr.s_addr = dns;

printf("res: %u\n", res);
inet_ntop(AF_INET, &addr1.sin_addr.s_addr, buf, INET_ADDRSTRLEN);
printf("IP: %s port: %u\n", buf, ntohs(addr1.sin_port));

c = 1;
res = sendto(soc, &c, 1, 0, (struct sockaddr*)&addr1, len);
printf("res: %u\n", res);

res = getsockname(soc, (struct sockaddr*)&addr, &len);
printf("res: %u len: %u\n", res, len);
if ( !res )
{
inet_ntop(AF_INET, &addr.sin_addr, buf, INET_ADDRSTRLEN);
printf("IP: %s port: %u\n", buf, ntohs(addr.sin_port));
}

в итоге результат такой:

len: 16
socket: 3
res: 0
IP: 0.0.0.0 port: 0
res: 1
IP: 192.168.7.1 port: 53
res: 1
res: 0 len: 16
IP: 0.0.0.0 port: 57132

Резюме: В канонической реализации стека (а испытывал на фряхе, а именно стек BSD является канонической реализацией) сокету назначается порт но НЕ интерфейс... Так что если на машине два интерфейса то послав сообщение по одному из них я могу получить ответ с другого (гипотетически) так? ГДЕ логика???

anonymous
()
Ответ на: комментарий от anonymous

> Резюме: В канонической реализации стека (а испытывал на фряхе, а именно стек BSD является канонической реализацией) сокету назначается порт но НЕ интерфейс... Так что если на машине два интерфейса то послав сообщение по одному из них я могу получить ответ с другого (гипотетически) так? ГДЕ логика???

ну если правила маршрутизации позволят, то получите. а если их ещё и в бонд объединить, то точно получите. ну и что собственно? детали того, кто когда и куда через какой физический интерфейс уходит - это не проблема прилижения.

// wbr

klalafuda ★☆☆
()
Ответ на: комментарий от klalafuda

Нет возникает вопрос как ограничить прием сообщений UDP из конкретной подсети (читай с одного сетевого интерфейса)? Иными словами куда ушел от туда И ТОЛЬКО ОТ ТУДА принимаем ответы?

anonymous
()
Ответ на: комментарий от anonymous

а ну да в recvfrom могу проверить кто отслал ответ...

anonymous
()
Ответ на: комментарий от anonymous

> Нет возникает вопрос как ограничить прием сообщений UDP из конкретной подсети (читай с одного сетевого интерфейса)? Иными словами куда ушел от туда И ТОЛЬКО ОТ ТУДА принимаем ответы?

eth0: 192.168.1.2/24
eth1: 10.1.2.3/8

пакет ушёл на адрес a.b.c.d в соотв. с правилами маршрутизации, скажем, через eth0. и исходящий IP адрес у пакета соотв. будет 192.168.1.2. и сервер, получив этот пакет, по всей видимости будет слать ответ на этот же адрес. и придёт он по всей очевидности через eth0 но не eth1.

// wbr

klalafuda ★☆☆
()
Ответ на: комментарий от klalafuda

Если его кто-то не подделает в сетке на другом интерфейсе... Я про такие атаки речь веду. Какая от них защита?

anonymous
()
Ответ на: комментарий от anonymous

> Если его кто-то не подделает в сетке на другом интерфейсе... Я про такие атаки речь веду. Какая от них защита?

ну от этого никто, в общем случае, не застрахован. ну подделает, ну придёт пакет с левого хоста. для этого уже есть уровень приложения, который реализует те или иные меры аутентификации, защиты целостности передаваемых данных и пр.

// wbr

klalafuda ★☆☆
()
Ответ на: комментарий от anonymous

> Если его кто-то не подделает в сетке на другом интерфейсе... Я про такие атаки речь веду. Какая от них защита?

или вы имеете ввиду вопрос "как слушать UDP пакеты с конкретного IP адреса а не со всего мира?".

// wbr

klalafuda ★☆☆
()
Ответ на: комментарий от klalafuda

Вообще ОС моглабы и не принимать ответные датаграмы с интерфейсов через которые никогда не уходили запросы... ибо приход таких ответов нелогичен. Это же элементарные меры сетевой защиты. А дальше будет разбираться приложение.

anonymous
()
Ответ на: комментарий от klalafuda

Я имею ввиду как клиенту слушать ОТВЕТЫ на UDP запросы на КОНКРЕТНОМ IP. Если у машины два IP то слушать ответы только на том IP с которого ушел запрос. А за этим IP хоть полмира неважно. Не принимать запросы с того интерфейса через который не уходили запросы.

anonymous
()
Ответ на: комментарий от anonymous

> Я имею ввиду как клиенту слушать ОТВЕТЫ на UDP запросы на КОНКРЕТНОМ IP

И что, bind не помогает?

tailgunner ★★★★★
()
Ответ на: комментарий от anonymous

> Вообще ОС моглабы и не принимать ответные датаграмы с интерфейсов через которые никогда не уходили запросы... ибо приход таких ответов нелогичен. Это же элементарные меры сетевой защиты. А дальше будет разбираться приложение.

или я что-то не понимаю, или у кого-то небольшая каша в голове. начнем с того, что OS по очевидным причинам не делит UDP датаграммы на ответные, неответные и пр. есть датаграмма, её можно передать или принять и отдать на обработку приложению через соотв. сокет. а решать, что с ней делать и должна ли она здесь быть или не должна - это уже не проблема OS.

// wbr

klalafuda ★☆☆
()
Ответ на: комментарий от klalafuda

Когда я явно вызываю bind я привязываю сокет к КОНКРЕТНОМУ IP и конкретному порту, я немогу получить UDP датаграму этим приложением если она придет по этому порту но на другой IP.

Почему при автоматичском назначении адреса сокету он не привязывается к конкретному IP, а привязывается ко всем интерфейсам в системе? Именно этот факт я и считаю странным.

Ядру накакать ответная эта датаграмма или нет оно об этом не знает и это правда. Но когда оно знает что рандомно назначила приложению порт и при этом привязала сокет ко всему что можно... а потом еще и принимать на этот порт пакеты со всех интерфейсов в системе глупо. Или с тех интерфейсов по которым не было исходящей активности.

ЗЫ. сейчас речь идет не о том как сделать а о том почему так сделано а не иначе, и то что можно вызывать bind всем известно, спасибо за совет но он не в теме

anonymous
()
Ответ на: комментарий от anonymous

Чувак что ты курил ? Я тоже хочу.

Ответь себе на другой вопрос
а нафига системе делать лишнюю работу ?
Вот мне лично пофигу откуда придет ответ,
если ТЕБЕ не пофигу - ради бога, озаботься,
подпиши свой пакет каким-нибудь способом
чтобы ты ТОЧНО знал что он пришел откуда надо.
Причем тут система к твоей шизанутости ?

У меня в роутере 4 интерфеса трафик уходит
по одним правилам, приходит по другим,
и я очень рад что система не парит мне мозг
по этому поводу.

anonymous
()
Ответ на: комментарий от anonymous

> Вообще ОС моглабы и не принимать ответные датаграмы с интерфейсов через которые никогда не уходили запросы... ибо приход таких ответов нелогичен.

UDP это connectionless-протокол. Нет у него понятия "ответ" и "соединение". Делай как говорят доки, т.е. забинди на ADDR_ANY сокет и делай с него sendto/recvfrom.

true_admin ★★★★★
()
Ответ на: комментарий от true_admin

Елки что не ясно что на ADDR_ANY оно биндится по дефолту?????? В этом и вопрос почему по дефолту стоит ADDR_ANY! Читайте внимательней что написано.

anonymous
()
Ответ на: комментарий от anonymous

а ты посмотри на какое сообщение я отвечал.

Что именно тебя не устраивает в том что по-дефолту ядро само определит наиболее подходящий адрес для отправки?

true_admin ★★★★★
()
Ответ на: комментарий от true_admin

Меня не устраивает то, что ядро по дефолту не приводит привязку сокета к IP а открывает его для всех интерфейсов.

anonymous
()
Ответ на: комментарий от anonymous

>Так что если на машине два интерфейса то послав сообщение по одному из них я могу получить ответ с другого (гипотетически) так? ГДЕ логика???

уХАХАХА? Книжечки по сетям для кого пишут, мой дорогой друг? Ан нед, вам бы стразу какашку лепить... ;)

anonymous
()
Ответ на: комментарий от anonymous

Для вас и пишут, мы свои уже прочитали.

anonymous
()
Ответ на: комментарий от anonymous

> Меня не устраивает то, что ядро по дефолту не приводит привязку сокета к IP а открывает его для всех интерфейсов.

и что мешает изменить это? А главное, чем это плохо?

Про книжки уже писали...

true_admin ★★★★★
()
Ответ на: комментарий от true_admin

> А главное, чем это плохо?

Ну совершенно же понятно, что ядро должно привязываться к интерфейсу, выбираемому RNG.

tailgunner ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.