c: увеличение октетов адреса IPv4 в сетевом порядке байтов - PullRequest
0 голосов
/ 13 апреля 2020

В следующем коде addr_min и addr_max представляют собой 32-разрядные значения без знака, представляющие адрес IPv4, и они расположены в сетевом порядке байтов, то есть в формате с прямым порядком байтов:

uint32_t addr;
for (addr = addr_min; addr <= addr_max; addr = addr + htonl(1)) {
   ...
}

Итак предполагая, что я хочу перебрать адрес 1.2.0.0 и постепенно увеличивать третий и четвертый октеты, получая в общей сложности 65534 адреса (addr_max, когда напечатано показывает feff0201). Я ожидал, что приведенный выше код сработает, вместо этого он только изменит 4-й октет на значение 0xfe и никогда не коснется третьего.

Что я, возможно, делаю неправильно?

1 Ответ

2 голосов
/ 13 апреля 2020

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

Быстрый ответ таков:

uint32_t val_n = htonl(init_val);
val_n += htonl(1);

не эквивалентно

uint32_t val = init_val;
val += 1;
uint32_t val_n = htonl(val);

Где val и init_val - обычные значения порядка хостов, а val_n - кодированные порядковые номера сети.

Значения сетевых порядков не нужны для арифметического c напрямую. Вы не знаете, какое значение htonl(1) добавит к вашему значению, и вы не знаете, что при его добавлении следующий байт перевернется после того, как вы доберетесь до 255 на младшем байте. Не рассматривайте значения сетевого порядка как числа, думайте о них как о непрозрачных значениях со значением.

Сохраняйте все, с чем вы работаете, в порядке хоста, как действительные числа:

uint32_t addr;
for (addr = addr_min; addr <= addr_max; addr += 1) {
    uint32_t addr_net_order = htonl(addr);
    ...
}

где addr, addr_min и addr_max - все порядки хостов , т.е. , если addr_min должно быть 1.2.0.0, addr_min = 0x01020000.

...