Skip to content

Commit

Permalink
fast input one million IP addresses
Browse files Browse the repository at this point in the history
  • Loading branch information
robertdavidgraham committed Jun 24, 2018
1 parent f5926c9 commit eed871c
Show file tree
Hide file tree
Showing 7 changed files with 235 additions and 3 deletions.
9 changes: 8 additions & 1 deletion src/main-conf.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include "templ-payloads.h"
#include "templ-port.h"
#include "crypto-base64.h"
#include "ranges-avl.h"
#include "script.h"
#include "masscan-app.h"
#include "unusedparm.h"
Expand Down Expand Up @@ -338,6 +339,7 @@ ranges_from_file(struct RangeList *ranges, const char *filename)
FILE *fp;
errno_t err;
unsigned line_number = 0;
struct RavlNode *ravl = ravl_create();


err = fopen_s(&fp, filename, "rt");
Expand Down Expand Up @@ -412,12 +414,17 @@ ranges_from_file(struct RangeList *ranges, const char *filename)
filename, line_number, offset, i, address);
exit(1);
} else {
rangelist_add_range(ranges, range.begin, range.end);
//rangelist_add_range(ranges, range.begin, range.end);
ravl = ravl_insert(range.begin, range.end, ravl);
}
}

}

ravl_enumerate(ravl, rangelist_add_range, ranges);

ravl_free(ravl);

fclose(fp);
}

Expand Down
10 changes: 10 additions & 0 deletions src/output.c
Original file line number Diff line number Diff line change
Expand Up @@ -671,11 +671,21 @@ oui_from_mac(const unsigned char mac[6])
{
unsigned oui = mac[0]<<16 | mac[1]<<8 | mac[2];
switch (oui) {
case 0x001075: return "Seagate";
case 0x001e06: return "Odroid";
case 0x3497f6: return "Asus";
case 0x38f73d: return "Amzon";
case 0x60a44c: return "Asus";
case 0x6c72e7: return "Apple";
case 0x9003b7: return "Parrot";
case 0x94dbc9: return "Azurewave";
case 0xb827eb: return "Raspberry Pi";
case 0xacbc32: return "Apple";
case 0x404a03: return "Zyxel";
case 0x000c29: return "VMware";
case 0x002590: return "Supermicro";
case 0xc0c1c0: return "Cisco-Linksys";
case 0xc05627: return "Belkin";
case 0x2c27d7: return "HP";
case 0x001132: return "Synology";
case 0x0022b0: return "D-Link";
Expand Down
187 changes: 187 additions & 0 deletions src/ranges-avl.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,187 @@
/***************************************************************************
RANGES - AVL TREE
Reading in a million UNSORTED IP addresses is slow, as in it could
takes hours. That's because the internal table is a linear sorted
array of entries. That means for every random IP address we add to
the list, we'll need to do a memmove() of a few megabytes of RAM.
The solution is to first read in the IP addresses in a sort-friendly
manner, such as a binary tree. However, a normal binary tree is bad
because if the input isn't random (already sorted), then we end up
creating a linked-list instead, and are back to the same problem
of taking hours to read in all the IP addresses.
To solve this, we first read in a file containing IP addresses into
an AVL tree. This will keep the tree balanced, preventing an unbalanced
tree. Thus, reading in a sorted and unsorted list is roughly the same
speed.
***************************************************************************/
#include "ranges-avl.h"
#include <stdio.h>
#include <stdlib.h>

#ifndef max
#define max(a,b) (((a) > (b)) ? (a) : (b))
#endif

struct RavlNode
{
unsigned ip_begin;
unsigned ip_end;
int height;
struct RavlNode* left;
struct RavlNode* right;
};


/***************************************************************************
***************************************************************************/
void
ravl_free(struct RavlNode *node)
{
if (node != NULL) {
ravl_free(node->left);
ravl_free(node->right);
free(node);
}
}



/***************************************************************************
***************************************************************************/
static int
height(const struct RavlNode *node)
{
if (node == NULL)
return -1;
else
return node->height;
}



/***************************************************************************
***************************************************************************/
static struct RavlNode *
single_rotate_with_left(struct RavlNode* k2)
{
struct RavlNode* k1 = NULL;

k1 = k2->left;
k2->left = k1->right;
k1->right = k2;

k2->height = max( height( k2->left ), height( k2->right ) ) + 1U;
k1->height = max( height( k1->left ), k2->height ) + 1U;
return k1; /* new root */
}


/***************************************************************************
***************************************************************************/
static struct RavlNode *
single_rotate_with_right(struct RavlNode* k1)
{
struct RavlNode* k2;

k2 = k1->right;
k1->right = k2->left;
k2->left = k1;

k1->height = max( height( k1->left ), height( k1->right ) ) + 1;
k2->height = max( height( k2->right ), k1->height ) + 1;

return k2; /* New root */
}


/***************************************************************************
***************************************************************************/
static struct RavlNode *
double_rotate_with_left(struct RavlNode* k3)
{
/* Rotate between k1 and k2 */
k3->left = single_rotate_with_right(k3->left);

/* Rotate between K3 and k2 */
return single_rotate_with_left(k3);
}


/***************************************************************************
***************************************************************************/
static struct RavlNode *
double_rotate_with_right( struct RavlNode* k1 )
{
/* rotate between K3 and k2 */
k1->right = single_rotate_with_left(k1->right);

/* rotate between k1 and k2 */
return single_rotate_with_right(k1);
}


/***************************************************************************
* Recursively insert and perhaps rebalance.
***************************************************************************/
struct RavlNode *
ravl_insert(unsigned ip_begin, unsigned ip_end, struct RavlNode *node)
{
if (node == NULL) {
node = malloc(sizeof(struct RavlNode));
node->ip_begin = ip_begin;
node->ip_end = ip_end;
node->height = 0;
node->left = node->right = NULL;
} else if (ip_begin < node->ip_begin) {
node->left = ravl_insert(ip_begin, ip_end, node->left);

if (height(node->left) - height(node->right) == 2) {
if (ip_begin < node->left->ip_begin)
node = single_rotate_with_left(node);
else
node = double_rotate_with_left(node);
}
} else if (ip_begin > node->ip_begin) {
node->right = ravl_insert(ip_begin, ip_end, node->right);

if (height(node->right) - height(node->left) == 2) {
if (ip_begin > node->right->ip_begin)
node = single_rotate_with_right(node);
else
node = double_rotate_with_right(node);
}
} else {
/* ip_begin == node->ip_begin*/
;
}

node->height = max( height( node->left ), height( node->right ) ) + 1;

return node;
}


/***************************************************************************
* Recursively enumerate the tree.
* This will be called to build the "rangelist_add()" function recursivley
* on all the nodes. Where this structure is a binary tree, the "rangelist"
* structure is a linear, sorted array. We'll essentially just be
* continuously appending all these nodes onto the end of the "rangelist"
* array.
***************************************************************************/
void
ravl_enumerate(struct RavlNode *node, RAVL_CALLBACK callback_func, void *callback_data)
{
if (node == NULL)
return;

callback_func(callback_data, node->ip_begin, node->ip_end);

ravl_enumerate(node->left, callback_func, callback_data);
ravl_enumerate(node->right, callback_func, callback_data);
}

20 changes: 20 additions & 0 deletions src/ranges-avl.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#ifndef RANGES_AVL_H
#define RANGES_AVL_H

struct RavlNode *
ravl_insert(unsigned ip_begin, unsigned ip_end, struct RavlNode *t);

void
ravl_free(struct RavlNode* node);

typedef void (*RAVL_CALLBACK)(void *callback_data, unsigned ip_begin, unsigned ip_end);

void
ravl_enumerate(struct RavlNode *t, RAVL_CALLBACK callback_func, void *callback_data);

#define ravl_create() (0)




#endif
4 changes: 2 additions & 2 deletions src/smack1.c
Original file line number Diff line number Diff line change
Expand Up @@ -1080,8 +1080,8 @@ smack_fixup_wildcards(struct SMACK *smack)
for (j=0; j<pat->pattern_length; j++) {
unsigned row = 0;
unsigned offset = 0;
size_t row_size = (1 << smack->row_shift);
transition_t *table;
size_t row_size = ((size_t)1 << smack->row_shift);
transition_t *table;
transition_t next_pattern;
transition_t base_state = (smack->is_anchor_begin?1:0);
size_t k;
Expand Down
2 changes: 2 additions & 0 deletions vs10/masscan.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@
<ClCompile Include="..\src\rand-blackrock.c" />
<ClCompile Include="..\src\rand-lcg.c" />
<ClCompile Include="..\src\rand-primegen.c" />
<ClCompile Include="..\src\ranges-avl.c" />
<ClCompile Include="..\src\ranges.c" />
<ClCompile Include="..\src\rawsock-arp.c" />
<ClCompile Include="..\src\rawsock-getif.c" />
Expand Down Expand Up @@ -163,6 +164,7 @@
<ClInclude Include="..\src\rand-blackrock.h" />
<ClInclude Include="..\src\rand-lcg.h" />
<ClInclude Include="..\src\rand-primegen.h" />
<ClInclude Include="..\src\ranges-avl.h" />
<ClInclude Include="..\src\ranges.h" />
<ClInclude Include="..\src\rawsock-pcap.h" />
<ClInclude Include="..\src\rawsock-pcapfile.h" />
Expand Down
6 changes: 6 additions & 0 deletions vs10/masscan.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,9 @@
<ClCompile Include="..\src\proto-ntlmssp.c">
<Filter>Source Files\proto</Filter>
</ClCompile>
<ClCompile Include="..\src\ranges-avl.c">
<Filter>Source Files\crypto</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\src\proto-arp.h">
Expand Down Expand Up @@ -509,6 +512,9 @@
<ClInclude Include="..\src\proto-ntlmssp.h">
<Filter>Source Files\proto</Filter>
</ClInclude>
<ClInclude Include="..\src\ranges-avl.h">
<Filter>Source Files\crypto</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="..\README.md" />
Expand Down

0 comments on commit eed871c

Please sign in to comment.