c код для действительной маски сети
Есть ли способ проверить, что 32-битная маска сети действительна или не использует побитовый оператор?
Я должен проверить со стороны msb, что '1' находятся в непрерывном потоке или нет. Например, 11111111.0.0.0 (255.0.0.0) является действительным, а 11111101.0.0.0 (253.0.0.0) - нет.
2 ответа
Первое, что нужно сделать, это проверить, что маска сети не равна нулю (неприятный крайний случай). Учитывая, что это нормально, вам нужно принять побитовое обратное.
uint32_t y = ~x;
Затем добавьте один
uint32_t z = y + 1;
Тогда если x
была правильная маска сети, в ней будет установлено не более 1 бита.
Чтобы проверить это, просто и z
с z - 1
, который случается y
, Результат будет нулевым, если все в порядке, ненулевым в противном случае.
valid = (z & y) == 0;
Чтобы проверить недействительную маску сети, вы можете использовать следующий простой алгоритм:
mask & (~mask >> 1)
Это даст оценку 1 для недопустимой маски сети и 0 для действительной маски сети.
Действительная сетевая маска не может иметь ноль с одним справа от него. Все нули должны иметь еще один ноль справа от него или быть битом 0. Если вы возьмете те, которые дополняют (~) сетевой маски, которая имеет ноль с единицей справа от нее, и сдвинете ее вправо на одну битовую позицию, вы выровняете единицу в сетевой маске с единицей в сдвинутом дополнении сетевой маски. AND'объединение этих двух значений приведет к получению недопустимой маски сети.
Обязательно используйте ntohl() для преобразования сетевой маски в порядок байтов хоста, прежде чем применять этот алгоритм, если он находится в сетевом порядке байтов. Кроме того, вам необходимо выполнить специальные проверки для 0xffffffff и 0x00000000, если вы хотите исключить их.
Примечание. Из-за правил приоритета и ассоциативности C для операторов скобки, показанные в алгоритме, не нужны, но я добавил их, чтобы облегчить понимание кода в случае, если вы не всегда помните правила приоритетности и ассоциативности.
int is_netmask_valid(uint32_t mask)
{
if (mask == 0) return 0;
if (mask & (~mask >> 1)) {
return 0;
} else {
return 1;
}
}