WedX - журнал о программировании и компьютерных науках

Неожиданные результаты

В нашей организации мы получаем ежедневный черный список (намного больше, так как это всего лишь фрагмент) в следующем формате:

172.44.12.0

198.168.1.5

10.10.0.0

192.168.78.6

192.168.22.22

111.111.0.0

222.222.0.0

12.12.12.12

Когда я запускаю программу после компиляции кода, я получаю:

1

1

1

1

1

1

1

1

Я использую C++ в среде Linux/Unix.

Пока что я просто выплевываю его, чтобы убедиться, что он правильно отформатирован.

Имя файла — blacklist.txt, который на данный момент содержит перечисленные выше IP-адреса. Я использую cout только для того, чтобы убедиться, что моя переменная определена правильно.

#include <iostream>
#include <vector>
#include <fstream>
#include <string>
#include <netinet/in.h>
#include <stdint.h>
#include <arpa/inet.h>

using namespace std;

bool is_match(std::string &hay_stack, std::string &srcip) {
    in_addr_t _ip = inet_addr(hay_stack.c_str());
    in_addr_t _IP = inet_addr(srcip.c_str());
    _ip = ntohl(_ip);
    _IP = ntohl(_IP);
    uint32_t mask=(_ip & 0x00ffffff == 0) ? 0xff000000 :
    (_ip & 0x0000ffff == 0 ? 0xffff0000 : 0);
    return ( (_ip & mask) == (_IP & mask) );
}

int main()
{
    vector<std::string> lines;
    lines.reserve(5000); //Assuming that the file to read can have max 5K lines

    string fileName("blacklist.txt");

    ifstream file;
    file.open(fileName.c_str());

    if(!file.is_open())
    {
        cerr<<"Error opening file : "<<fileName.c_str()<<endl;
        return -1;
    }

    //Read the lines and store it in the vector
    string line;
    while(getline(file,line))
    {
        lines.push_back(line);
    }

    file.close();

    //Dump all the lines in output
    for(unsigned int i = 0; i < lines.size(); i++)
    {
        string h = lines[i];
        string mi = "10.10.10.10";
        cout<<is_match(h,mi)<<endl;
    }

    return 0;
}

Я ожидаю, что вывод будет 10.10.10.10 (здесь какая-то подсеть хоста) 10.10.0.0 (и какая-то маска подсети здесь)

c++
02.03.2012

  • Я бы предположил, что «маска» постоянно оценивается до нуля. 03.03.2012
  • У вас есть конкретный вопрос или мы должны просто исправить программу для вас? 03.03.2012
  • Несмотря на то, что вы не задали вопрос, я все равно поставлю +1 за предоставление полной программы (sscce.org) и используя правильную идиому для чтения строк ввода. 03.03.2012

Ответы:


1

Вот где твоя проблема:

uint32_t mask=(_ip & 0x00ffffff == 0) ? 0xff000000 :
(_ip & 0x0000ffff == 0 ? 0xffff0000 : 0);
return ( (_ip & mask) == (_IP & mask) );

Если _ip имеет форму x.0.0.0, он сравнивает только x в _IP, а если _ip имеет форму x.y.0.0, он сравнивает только x и y в _IP, что нормально.

Но если _ip не в любом формате, вы устанавливаете маску на 0 ‹ - это проблема.

Когда вы берете (_ip & 0), результат всегда равен 0, аналогично с (_IP & 0). Это означает, что вы всегда возвращаете true для адресов с a.b.c.d, c != 0 или d != 0.

Вместо этого сделайте маску по умолчанию равной 0xffffffff, чтобы проверить полное совпадение.

Но оказывается, это не самая большая проблема. Большая проблема заключается в том, что == имеет более высокий приоритет оператора, чем &, поэтому ваш код на самом деле работает следующим образом:

uint32_t mask=(_ip & (0x00ffffff == 0)) ? 0xff000000 :
    (_ip & (0x0000ffff == 0) ? 0xffff0000 : 0);
return ( (_ip & mask) == (_IP & mask) );

В результате вы всегда будете получать 0 для маски. Вам нужно применить скобки, чтобы исправить это.

Итак, в заключение ваш код должен измениться и выглядеть следующим образом:

uint32_t mask=( (_ip & 0x00ffffff) == 0) ? 0xff000000 :
    ( (_ip & 0x0000ffff) == 0 ? 0xffff0000 : 0xffffffff);
return ( (_ip & mask) == (_IP & mask) );
02.03.2012
  • Большое спасибо, я новичок в программировании, я потратил всего несколько часов на изучение C++. 03.03.2012
  • Большое спасибо, я новичок в программировании, теперь я получаю только нули. Должен ли я не возвращать другое значение для совпадения (10.10.10.10 находится в подсети 10.10.0.0), чтобы я ожидал другого результата от других значений, содержащихся в файле blacklist.txt? 03.03.2012
  • Оказывается, существовала еще более тонкая проблема приоритета операций. Я обновил свой ответ, чтобы объяснить это. 03.03.2012

  • 2

    Ответ на неявный вопрос: "Почему моя программа работает не так, как я ожидал?"

    Я ожидаю, что вывод будет 10.10.10.10 (здесь какая-то подсеть хоста) 10.10.0.0 (и какая-то маска подсети здесь)

    Я не знаю, почему вы этого ожидаете. В вашем коде (если файл открывается успешно) есть только один оператор печати:

    cout<<is_match(h,mi)<<endl;
    

    Функция is_match всегда возвращает логическое значение, либо true, либо false. При печати он всегда будет либо 1, либо 0 соответственно. В вашей программе просто нет кода, который мог бы напечатать IP-адрес или сетевую маску.

    02.03.2012
  • И поскольку это логическое значение всегда истинно... что бы он ни пытался сделать в is_match()... не работает. 03.03.2012
  • Я пытаюсь взять 10.10.10.10 и посмотреть, соответствует ли он чему-либо в файле blacklist.txt. Поскольку записи, представляющие собой диапазон сети, не содержат маски подсети, я предполагаю, что мне нужно назначить маску этим адресам и посмотреть, попадает ли мой хост в этот диапазон. 03.03.2012
  • Думаю, я только что понял. Изменено == на ‹=. 03.03.2012
  • Новые материалы

    Как создать диаграмму градиентной кисти с помощью D3.js
    Резюме: Из этого туториала Вы узнаете, как добавить градиентную кисть к диаграмме с областями в D3.js. Мы добавим градиент к значениям SVG и применим градиент в качестве заливки к диаграмме с..

    Я хотел выучить язык программирования MVC4, но не мог выучить его раньше, потому что это выглядит сложно…
    Просто начните и учитесь самостоятельно Я хотел выучить язык программирования MVC4, но не мог выучить его раньше, потому что он кажется мне сложным, и я бросил его. Это в основном инструмент..

    Лицензии с открытым исходным кодом: руководство для разработчиков и создателей
    В динамичном мире разработки программного обеспечения открытый исходный код стал мощной парадигмой, способствующей сотрудничеству, инновациям и прогрессу, движимому сообществом. В основе..

    Объяснение документов 02: BERT
    BERT представил двухступенчатую структуру обучения: предварительное обучение и тонкая настройка. Во время предварительного обучения модель обучается на неразмеченных данных с помощью..

    Как проанализировать работу вашего классификатора?
    Не всегда просто знать, какие показатели использовать С развитием глубокого обучения все больше и больше людей учатся обучать свой первый классификатор. Но как только вы закончите..

    Работа с цепями Маркова, часть 4 (Машинное обучение)
    Нелинейные цепи Маркова с агрегатором и их приложения (arXiv) Автор : Бар Лайт Аннотация: Изучаются свойства подкласса случайных процессов, называемых дискретными нелинейными цепями Маркова..

    Crazy Laravel Livewire упростил мне создание электронной коммерции (панель администратора и API) [Часть 3]
    Как вы сегодня, ребята? В этой части мы создадим CRUD для данных о продукте. Думаю, в этой части я не буду слишком много делиться теорией, но чаще буду делиться своим кодом. Потому что..


    Для любых предложений по сайту: [email protected]