- комментарий 0:
From: kmeaw
Date: 2020-10-12 14:35:48Z
> Поискал информацию и
> говорит что туда нельзя link-local, а только routable адреса.
Зависит от реализации getaddrinfo. В musl такой проблемы нет.
В glibc, действительно, getaddrinfo и inet_pton не понимают zone
identifier в IPv6-адресах.
> В FreeBSD уже
> с 9.0 версии есть возможность собрать ядро полностью без IPv4 поддержки
> -- IPv6 only.
Я уже задавал этот вопрос на Хабре, но повторюсь, так как не получил
ответа — а как оно работает в FreeBSD? Я сходу не могу придумать, как
красиво отвязать реализацию TCP от IP (проблемы должны возникнуть,
например, при вычислении pseudoheader checksum).
> loopback блочное устройство на самом деле не такое уж и
> полноценное. Например мы можете сделать losetup, создав loopback block
> device, но например partition table с него не подгрузится
Для поддержания partition table нужно резервировать device minor
numbers. Поскольку пользователи гораздо чаще создают много loopback
devices, чем разделов на одном loopback device, по-умолчанию размер
выделяемого диапозона равен единице. Это несложно изменить, для этого
есть параметр max_part у модуля loop:
modprobe loop max_part=8
После чего вместь с /dev/loopX появятся устройства /dev/loopXpY.
--
kmeaw
- комментарий 1:
From: kmeaw
Date: 2020-10-12 15:01:10Z
Посмотрел в исходники glibc, и понял, что всё на самом деле не совсем
так.
Современные версии getaddrinfo вполне умеют scope identifier, и кладут
его в правильное место — в sockaddr_in6.sin6_scope_id.
А inet_pton(af=AF_INET6), которым пользуется парсер /etc/hosts,
возвращает результат в виде struct in6_addr. По-другому эта функция не
может работать (например, писать в sockaddr_in6 или записывать scope
identifier куда-то ещё), потому что это часть POSIX.
Проблема в glibc заключается в том, что парсер hosts использует
inet_pton, а не некую внутреннюю часть getaddrinfo. Полноценный
getaddrinfo он по понятным причинам использовать не может.
В musl же для этого используется внутренняя функция __lookup_ipliteral,
заполняющая уже внутреннюю struct address.
Я пока не могу придумать хороший способ написать программу, которая бы,
ограничиваясь только тем, что есть в POSIX, парсила бы IPv6 адрес в
struct sockaddr_in6 без работающего getaddrinfo (с работающим легко,
hints.ai_flags=AI_NUMERICHOST). Возможно, разработчики glibc считают,
что плохо в реализации libnss/files-hosts использовать функцию
getaddrinfo, которая, в свою очередь, сама использует libnss, порождая
циклическую зависимость, ведь чтобы её разорвать, придётся знать детали
реализации динамически загружаемой библиотеки (неизвестно какой, ведь
через nsswitch.conf пользователь может указать любую).
musl, в силу простоты своего дизайна, не пытается быть такой же
расширяемой, поэтому механизма, похожего на nss, там просто нет. Поэтому
и проблемы этой нет — функции могут использовать части друг-друга и
завязываться на детали реализации.
- комментарий 2:
From: Sergey Matveev
Date: 2020-10-12 15:06:29Z
*** kmeaw [2020-10-12 17:31]:
>Зависит от реализации getaddrinfo. В musl такой проблемы нет.
Учитывая что большинство GNU/Linux имеют glibc, это всё равно касается
большинства. Но здорово, буду знать про musl. У меня в голове GNU софт
выглядит как монструозный и огромный (то что я видел со своими
познаниями C -- это подтверждают), но при этом и самый фичастый и
навороченный. А тут вот обратное.
>Я уже задавал этот вопрос на Хабре, но повторюсь
Если речь про комментарии к статье про "FreeBSD гораздо лучше...", то я
там их довольно быстро уже перестал читать, ибо статья holywar-ная, и
поэтому там сплошные holywar-ы :-)
>а как оно работает в FreeBSD? Я сходу не могу придумать, как
>красиво отвязать реализацию TCP от IP (проблемы должны возникнуть,
>например, при вычислении pseudoheader checksum).
Как конкретно -- не отвечу, не смотрел глубоко. Когда делал IPsec ESP
стэк на Go, то много лазал по их коду и отмечал что нигде гвоздями
прибитых IPv4 не видел. Чисто технически/программерски: нет же проблем
сделать IPv4/IPv6-only код. Главное помнить что IP есть, как минимум,
двух версий и не делать hardcode.
https://wiki.freebsd.org/IPv6/IPv6OnlySnapshots
А в чём проблемы будут с псевдозаголовком в TCP? Он зависит от заголовка
IP, но ведь TCP/UDP/ICMP (про остальные не знаю) достаточно знать не
само значение псевдозаголовка (что может быть просто интерфейсным
вызовом сетевого уровня), а его уже посчитанное значение. Я возможно
рассматриваю только простейшие случаи, где всё гладко, но вот мне
пришлось при реализации IPsec ESP пересчитывать контрольные суммы для
TCP/UDP/ICMP пакетов и у меня такой код:
// Recompute checksums
if gotIPv6 {
csum = ipv6PseudoHdrCsum(src, dst)
} else {
csum = ipv4PseudoHdrCsum(src, dst)
}
switch nextHdr {
case gostipsec.ProtoTCP:
body[16] = 0
body[17] = 0
binary.BigEndian.PutUint16(
body[16:18],
tcpipCsum(csum, gostipsec.ProtoTCP, body),
)
case gostipsec.ProtoUDP:
body[6] = 0
body[7] = 0
binary.BigEndian.PutUint16(
body[6:8],
tcpipCsum(csum, gostipsec.ProtoUDP, body),
)
[...]
case gostipsec.ProtoICMPv6:
case gostipsec.ProtoICMP:
Где вообще у пакета просто мог бы быть .HdrCsum() интерфейс, который
выдал бы мне csum уже дальше используемый в конкретных транспортных
протоколах.
>Это несложно изменить, для этого есть параметр max_part у модуля loop:
Мне, как простому пользователю, это всё выглядит магией :-). Казалось
бы (для меня), простейшие действия, но требуют постоянно каких-то
донастроек, опций и конфигурирования. Я просто хочу получить loopback
блочное устройство! Как и кучу других вещей. И вот FreeBSD это даёт
именно как мне надо. Безусловно, всё то же самое касается и любой другой
ОС -- у всех свои за и против, но GNU/Linux точно не моё :-)
- комментарий 3:
From: Sergey Matveev
Date: 2020-10-12 15:11:39Z
*** kmeaw [2020-10-12 17:57]:
>Возможно, разработчики glibc считают,
>что плохо в реализации libnss/files-hosts использовать функцию
>getaddrinfo, которая, в свою очередь, сама использует libnss, порождая
>циклическую зависимость
Это первое что пришло мне в голову на вопрос "почему glibc использует
другую функцию". Логично и можно их понять.
>musl, в силу простоты своего дизайна, не пытается быть такой же
>расширяемой, поэтому механизма, похожего на nss, там просто нет.
И это тоже могу понять и уважать такой подход! В
aaf073b9d4b9bed91492e0af3ba9c09144849bb1 как раз тоже был показан подход
к isalnum() функции в musl и glibc. И у обоих есть же свои за и против!
Но, опять же, мне, как пользователю ОС, хотелось бы чтобы я мог
прописать link-local-ы в /etc/hosts, как это позволяет FreeBSD. И я хочу
так не потому что FreeBSD так умеет, а потому что я реально это хочу
сделать для своего же удобства :-)