사용자 도구

사이트 도구


kb:cidrnetworkmask

차이

문서의 선택한 두 판 사이의 차이를 보여줍니다.

차이 보기로 링크

kb:cidrnetworkmask [2014/11/06 19:11] (현재)
줄 1: 줄 1:
 +====== CIDR Network Mask ======
 +"​58.17.128.0/​17"​과 같은 형식의 주소 지정 방식. 라우터 같은 곳에서 많이 사용한다. 특정 IP에서의 접속을 막아달라고 이 형식의 리스트가 올 때도 있다.
 +
 +
 +====== CIDR 방식의 주소 목록 조회하기 ======
 +특정 주소가 목록에 들어있는지 알아내기
 +
 +"​58.17.128.0/​17"​ 형식의 문자열은 시작 IP와 끝 IP 사이의 범위로 변환할 수 있다. 이를 컬렉션에다 집어넣어둔 다음, 입력으로 들어온 IP를 포함하는 범위가 있는지 체크하면 된다. 아래의 구현은 그냥 배열로 목록을 관리하고 있으나, [[IntervalTree]] 같은 데이터 구조를 이용하면 좀 더 나은(?) 프로그램을 만들 수 있다.
 +
 +<code cpp>
 +class cCidrMask
 +{
 +private:
 +    struct MASK
 +    {
 +        unsigned int StartIP; ///< 시작 IP
 +        unsigned int EndIP; ​  ///<​ 끝 IP
 +    };
 +
 +    std::​vector<​MASK>​ m_MaskArray;​ ///< CIDR 마스크의 배열
 +
 +
 +public:
 +    /// \brief 생성자
 +    cCidrMask() {}
 +
 +    /// \brief 소멸자
 +    ~cCidrMask() { m_MaskArray.clear();​ }
 +
 +
 +public:
 +    /// \brief CIDR 마스크를 추가한다.
 +    /// \param cidr "​58.14.0.0/​16"​ 같은 형식의 문자열
 +    /// \return bool 무사히 추가했다면 true, 잘못된 문자열이라면 false
 +    bool Add(const std::​string&​ cidr)
 +    {
 +        bool success = false;
 +
 +        size_t pos = cidr.find_first_of('/'​);​
 +        if (pos != std::​string::​npos)
 +        {
 +            std::string elements[2] = { cidr.substr(0,​ pos), cidr.substr(pos+1) };
 +
 +            unsigned int ip        = IP2Int(elements[0].c_str());​
 +            int          bits      = atoi(elements[1].c_str());​
 +            unsigned int mask      = ~(0xFFFFFFFF >> bits); ​
 +            unsigned int network ​  = ip & mask;
 +            unsigned int broadcast = network + ~mask; ​
 +            unsigned int usable ​   = (bits > 30) ? 0 : (broadcast - network - 1);
 +
 +            if (usable > 0)
 +            {
 +                MASK mask;
 +                mask.StartIP = network + 1;
 +                mask.EndIP = broadcast - 1;
 +                m_MaskArray.push_back(mask);​
 +                success = true;
 +            }
 +        }
 +
 +        return success;
 +    }
 +
 +    /// \brief 주어진 IP가 추가한 마스크 중의 하나에 포함되는지를 체크한다.
 +    /// \param address 체크할 IP 주소 문자열 "​58.14.0.0"​
 +    /// \return bool 포함되어 있다면 true, 포함되어 있지 않다면 false
 +    bool Exist(const std::​string&​ address) const
 +    {
 +        unsigned int converted = IP2Int(address.c_str());​
 +
 +        bool exist = false;
 +
 +        for (size_t i=0; i<​m_MaskArray.size();​ ++i)
 +        {
 +            if (m_MaskArray[i].StartIP <= converted && converted <= m_MaskArray[i].EndIP)
 +            {
 +                exist = true;
 +                break;
 +            }
 +        }
 +
 +        return exist;
 +    }
 +
 +    ​
 +private: ​   ​
 +    /// \brief 문자열 형태의 IP 주소를 4바이트 숫자로 변환
 +    unsigned int IP2Int(const std::​string&​ ip)
 +    {
 +        char buf[256] = {0, };
 +        strcpy_s(buf,​ ARRAYSIZE(buf),​ ip.c_str());​
 +
 +        unsigned int converted = 0;
 +        unsigned int count = 0;
 +        unsigned int bits = 24;
 +
 +        LPSTR context = NULL;
 +        LPSTR token = strtok_s(buf,​ "​.",​ &​context);​
 +        while (token && count < 4)
 +        {
 +            converted += (static_cast<​unsigned int>​(atoi(token))) << bits;
 +
 +            bits -= 8;
 +            count += 1;
 +
 +            token = strtok_s(NULL,​ "​.",​ &​context);​
 +        }
 +
 +        return converted; ​       ​
 +    }
 +};
 +</​code>​
 +
 +<code cpp>
 +cCidrMask mask;
 +mask.Add("​58.17.128.0/​17"​);​
 +bool a = mask.Exist("​58.17.127.1"​);​
 +bool b = mask.Exist("​58.17.128.1"​);​
 +bool c = mask.Exist("​58.17.128.2"​);​
 +</​code>​
 +
 +====== 링크 ======
 +  * [[http://​www.4dnstools.com/​cidrnetmask.html]]
  
kb/cidrnetworkmask.txt · 마지막으로 수정됨: 2014/11/06 19:11 (바깥 편집)