Page 1 of 2 12 LastLast
Results 1 to 10 of 12

Thread: IP Sorting Stuff

  1. #1
    Administrator James's Avatar
    Join Date
    May 2010
    Location
    on the intraweb
    Posts
    3,180

    Default IP Sorting Stuff

    The following function does the following:

    1. Reads from a file
    2. IP Validation (without effecting wildcards)
    3. Sorts the list of IP's from the file specified above
    4. Remove duplicates
    5. Deletes the ports from any IP's that includes the port
    6. Outputs the final results to a new text file

    Todo:
    1. Include wildcard support

    Code:
    #include "stdafx.h"
    #include <iostream>
    #include <fstream>
    #include <map>
    #include <string>
    #include <vector>
    #include <algorithm>
    #include <functional>
    #include <ws2tcpip.h>
    
    
    #pragma comment(lib, "Ws2_32.lib")
    
    
    bool StringIPCompare( const std::string& a, const std::string& b )
    {
        static  std::string localA;
        static  std::string localB;
        static  std::string ipPartsA[4];
        static  std::string ipPartsB[4];
    
    
        localA = a;
        localB = b;
        localA += ".";
        localB += ".";
    
    
        for( unsigned int i = 0; i < 4; i++ )
        {
            size_t dotPos = localA.find_first_of( '.' );
            if( dotPos == std::string::npos )
                continue;
    
    
            ipPartsA[i] = localA.substr( 0, dotPos );
            localA.erase( 0, dotPos + 1 );
    
    
            dotPos = localB.find_first_of( '.' );
            if( dotPos == std::string::npos )
                continue;
    
    
            ipPartsB[i] = localB.substr( 0, dotPos );
            localB.erase( 0, dotPos + 1 );
        }
    
    
        for( unsigned int i = 0; i < 4; i++ )
        {
            //Add logic here that checks for wildcards or other specialties and handles them accordingly
            //Example: if you want wildcards to always top the list of similar IPs:
            if( ipPartsA[i] == ipPartsB[i] )
                continue;
    
    
            if( ipPartsA[i] == "*" )
                return true;
    
    
            if( ipPartsB[i] == "*" )
                return false;
    
    
            unsigned int uintA;
            unsigned int uintB;
    
    
            sscanf_s( ipPartsA[i].c_str(), "%u", &uintA );
            sscanf_s( ipPartsB[i].c_str(), "%u", &uintB );
    
    
            if( uintA > uintB ) //If any number we encounter in A's parts is larger than B's equivalent we know A is bigger than B and can return false
                return false;
    
    
            else if( uintA < uintB )
                return true;
        }
    
    
        return false;
    }
    
    
    int _tmain(int argc, _TCHAR* argv[])
    {
        struct sockaddr_in sa;
    
    
        std::fstream ipFilterInput;
        ipFilterInput.open("ipfilter.cfg", std::ios::in );
        
        std::fstream ipFilterOutput;
        ipFilterOutput.open("ipfilter2.cfg", std::ios::out );
        
        std::vector<std::string> ip;
        std::string current;
        
        while(getline(ipFilterInput,current))
        {
            //Delete Ports from IP's with port numbers
            std::string::size_type pos = current.find(":"); 
            
            if(pos != std::string::npos) 
                current.erase(pos);
    
    
            //Validate IP, but don't include wildcards '*'
            if((inet_pton(AF_INET, current.c_str(), &(sa.sin_addr)) != 1) && !current.find("*"))
            {
                //If the return value is not 1, then the address is invalid and should be deleted
                current.erase();
            }
    
    
            ip.push_back(current);
        }
    
    
        std::vector<std::string> value = ip;
    
    
        //Sort Function
        std::sort(value.begin(), value.end(), StringIPCompare);
        
        //Delete Duplicates
        value.erase(std::unique(value.begin(), value.end()), value.end());
        
        //Print Results
        copy(value.begin(), value.end(), std::ostream_iterator<std::string> (ipFilterOutput, "\n"));
    
    
        ipFilterOutput.close();
        ipFilterInput.close();
    
    
        system("Pause");
        return 0;
    }

    EDIT 7-8-16
    Updated code is on 2nd page 1st post.

  2. #2
    Administrator JoTo's Avatar
    Join Date
    May 2010
    Location
    www.scapp.net
    Posts
    1,953

    Default

    Code:
      if( uintA > uintB ) //If any number we encounter in A's parts is larger than B's equivalent we know A is bigger than B and can return false
                return false;
    that assumption will not work.
    a: 1.192.100.100
    b: 2.3.100.100

    I would have thought you made a handcrafted IP validation

  3. #3
    Administrator James's Avatar
    Join Date
    May 2010
    Location
    on the intraweb
    Posts
    3,180

    Default

    Haha, Actually I found a glitch with the validation that I need to fix, so I may write a custom one, but usually, I try not to overcomplicate my work if it can be done in a simpler fashion.

    And with regards to the sorting, I just tested it out with those 2 ip's and they sorted correctly Joto.

    snippit after I ran the app
    Code:
    1.192.100.100
    2.3.100.100
    2.82.225.101
    2.82.232.30
    2.82.238.104
    2.83.141.217
    2.83.191.218
    2.88.49.114
    2.89.114.96
    2.91.40.124
    It checks each octet and if you look at the first octet 1 < 2 so then
    1.192.100.100 would be sorted before 2.3.100.100

  4. #4
    Administrator JoTo's Avatar
    Join Date
    May 2010
    Location
    www.scapp.net
    Posts
    1,953

    Default

    ye your right, I oversaw that part: else if( uintA < uintB )

  5. #5

    Default

    Did you tried to use qsort ? http://www.cplusplus.com/reference/cstdlib/qsort/

    this works with array of char, so this would be :

    PHP Code:
    int compar(const voida, const voidb)
    {
         
    chars1 = *(char**)a;
         
    chars2 = *(char**)b;

         return 
    stricmp(s1s2);
    }

    int main(void)
    {
        
    charnames[] = { "Array""of""character""192.168.1.1""292.4.29.5""123.24.1.2""98.3.1.2"};
        
    int i;

        
    qsort(namesSIZEOF(names), sizeof(char*), compar);

        for (
    0SIZEOF(names); ++i)
            
    printf("%s\n"names[i]); // Print the array (arranged)

        
    return 0;

    The output would be :

    Code:
    123.24.1.2
    192.168.1.1
    292.4.29.5
    98.3.1.2
    Array
    character
    of
    This would make thing easier.
    Last edited by Ley0k; July 10th, 2013 at 09:26 AM.

  6. #6
    Administrator James's Avatar
    Join Date
    May 2010
    Location
    on the intraweb
    Posts
    3,180

    Default

    The problem though is lexicographic sorting Leyok. That was the tricky part for me. Take a look at your output:
    Code:
    292.4.29.5
    98.3.1.2
    98 < 292, so it should actually come before all the numbers in your array.

    And with regards to validation, here is what I have so far, but I need to rework it a bit:
    Code:
    std::vector<int> octets;
    std::string temp;
    
    
    while(getline(ipFilterInput,current))
    {	
    	//Delete Ports from IP's with port numbers	
    	std::string::size_type pos = current.find(":"); 
    		
    	if(pos != std::string::npos) 
    	current.erase(pos);
    
    
    	//Validate IP, but don't include wildcards '*'
    	std::stringstream ss(current);
    
    
    	//get each octet
    	while(getline(ss,temp,'.'))			
    		octets.push_back(atoi(temp.c_str()));
    
    
    	for(unsigned i = 0; i < octets.size(); i++)
    	{
    		//std::cout << octets[i] << std::endl;
    		if(isdigit(octets[i]) && octets[i] <= 255)
    			continue;
    		else
    			current.erase();
    	}
    
    
    	system("Pause");
    
    
            ip.push_back(current);
    }

  7. #7
    Developer Sor's Avatar
    Join Date
    Aug 2010
    Location
    The Medieval City of Bruges
    Posts
    747

    Default

    I think you need to compare strings in natural order: http://sourcefrog.net/projects/natsort/
    Morpheus Script (MoH) => You try to shoot yourself in the foot only to discover that MorpheusScript already shot your foot for you.

  8. #8
    Administrator James's Avatar
    Join Date
    May 2010
    Location
    on the intraweb
    Posts
    3,180

    Default

    Bringing this thread back to life. I noticed a few glitches that I would like to fix. I made some minor adjustments to the code. Here is the current source.


    #include "stdafx.h"
    #include <iostream>
    #include <fstream>
    #include <map>
    #include <string>
    #include <vector>
    #include <algorithm>
    #include <functional>
    #include <ws2tcpip.h>
    #include <sstream>
    #include <locale>
    #include <iterator>


    #pragma comment(lib, "Ws2_32.lib")


    struct sockaddr_in sa;


    bool StringIPCompare( const std::string& a, const std::string& b )
    {
    static std::string localA;
    static std::string localB;
    static std::string ipPartsA[4];
    static std::string ipPartsB[4];


    localA = a;
    localB = b;
    localA += ".";
    localB += ".";


    for( unsigned int i = 0; i < 4; i++ )
    {
    size_t dotPos = localA.find_first_of( '.' );


    if( dotPos == std::string::npos )
    continue;


    ipPartsA[i] = localA.substr( 0, dotPos );
    localA.erase( 0, dotPos + 1 );


    dotPos = localB.find_first_of( '.' );


    if( dotPos == std::string::npos )
    continue;


    ipPartsB[i] = localB.substr( 0, dotPos );
    localB.erase( 0, dotPos + 1 );
    }


    for( unsigned int i = 0; i < 4; i++ )
    {
    //Add logic here that checks for wildcards or other specialties and handles them accordingly
    //Example: if you want wildcards to always top the list of similar IPs:
    if( ipPartsA[i] == ipPartsB[i] )
    continue;


    if( ipPartsA[i] == "*" )
    return true;


    if( ipPartsB[i] == "*" )
    return false;


    unsigned int uintA;
    unsigned int uintB;


    sscanf_s( ipPartsA[i].c_str(), "%u", &uintA );
    sscanf_s( ipPartsB[i].c_str(), "%u", &uintB );


    if( uintA > uintB ) //If any number we encounter in A's parts is larger than B's equivalent we know A is bigger than B and can return false
    return false;


    else if( uintA < uintB )
    return true;
    }
    return false;
    }


    int _tmain(int argc, _TCHAR* argv[])
    {
    std::fstream ipFilterInput;
    ipFilterInput.open("ipfilter.cfg", std::ios::in );

    std::fstream ipFilterOutput;
    ipFilterOutput.open("ipfilter2.cfg", std::ios::out );

    std::vector<std::string> ip;
    std::string current;


    std::size_t badIP;
    std::size_t blankSpace;

    std::vector<int> octets;
    std::string temp;


    std::vector<std::string> value;


    while(getline(ipFilterInput,current))
    {
    //Delete Ports from IP's with port numbers
    std::string::size_type pos = current.find(":");


    if(pos != std::string::npos)
    current.erase(pos);


    //Validate IP, but don't include wildcards '*'
    if((inet_pton(AF_INET, current.c_str(), &(sa.sin_addr)) != 1))
    {
    badIP = current.find("*");


    if(badIP != std::string::npos)
    {
    //These IP's fail the inet_pton() function because they have a wildcard which technically is invalid
    //However we will exempt this logic for now because we don't want to filter out wildcards
    //printf("A: %s\n", current.c_str());
    }
    else
    {
    current.erase();
    }
    }
    ip.push_back(current);
    }


    value = ip;


    //Sort Function
    std::sort(value.begin(), value.end(), StringIPCompare);

    //Delete Duplicates
    value.erase(std::unique(value.begin(), value.end()), value.end());


    //Print Results
    copy(value.begin(), value.end(), std::ostream_iterator<std::string> (ipFilterOutput, "\n"));


    ipFilterOutput.close();
    ipFilterInput.close();


    return 0;
    }


    The line I highlighted in red is the area I am having an issue with. Basically just to break it down.. The function inet_pton(), is used to check if the IP is valid.
    I have an additional check to see if there are any wildcards “*” and if so, then they should be excluded from being removed.
    In the ipconfig.cfg file though, there were IP’s that were outside of the range for example 298.298.20.17.

    So I check that, and when I come across an IP out of range I use:


    current.erase();


    To remove that line. The issue I’m running into is that it doesn’t remove the line either. There is a break in between the next IP, and I want to remove these “whitespace”

    Here are some things I have tried, and none of these gave me the results I wanted. I know some of the syntax below is off, but just to give you a general idea of what I did.


    //This value is NOT a valid IP because it exceeds or is under the proper ipv4 address range 0.0.0.0 - 255.255.255.255
    //current.erase(current.begin(), current.end());
    //current.erase(std::unique(current.begin(), current.end()), current.end());
    //printf("B: %s\n", current.c_str());
    //current.erase(current.begin(), current.end());
    //current.erase(std::unique(current.begin(), current.end()), current.end());
    /*
    current.erase();

    blankSpace = current.find_last_not_of(" \n\r\t")+1;

    if(badIP != std::string::npos)
    {
    printf("Blank space not found\n");
    }
    else
    {
    current.push_back(current - 1);
    //printf("Blank space found\n");
    }
    */

    //current.erase(current.find_last_not_of(" \n\r\t")+1);
    //current.erase(std::unique(current.begin(), current.end(), (char a, char b) { return a == '\n' && b == '\n'; }), current.end());


    Any thoughts? I’m sure I’m over complicating this…



  9. #9
    Developer RyBack's Avatar
    Join Date
    Apr 2014
    Location
    In Front of the screen
    Posts
    1,603

    Default

    	while(getline(ipFilterInput,current))
    {
    //Delete Ports from IP's with port numbers
    std::string::size_type pos = current.find(":");

    if(pos != std::string::npos)
    current.erase(pos);

    //Validate IP, but don't include wildcards '*'
    if((inet_pton(AF_INET, current.c_str(), &(sa.sin_addr)) != 1))
    {
    badIP = current.find("*");

    if(badIP != std::string::npos)
    {
    //These IP's fail the inet_pton() function because they have a wildcard which technically is invalid
    //However we will exempt this logic for now because we don't want to filter out wildcards
    //printf("A: %s\n", current.c_str());
    ip.push_back(current);
    }
    }
    else
    ip.push_back(current);
    }


    maybe ?

  10. #10

    Default

    No the issue is that you seem to always push the IP string into the vector even if it's invalid.


    if(badIP != std::string::npos)
    {
    //These IP's fail the inet_pton() function because they have a wildcard which technically is invalid
    //However we will exempt this logic for now because we don't want to filter out wildcards
    //printf("A: %s\n", current.c_str());
    ip.push_back(current);
    }


    This should now push the IP to the vector only if it's valid, avoiding empty strings.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •