#include "prips.h"
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#if !defined(INET_ADDRSTRLEN)
#define INET_ADDRSTRLEN 16
#endif
/**********************************************/
/* Turn an IP address in dotted decimal into */
/* a number. This function also works for */
/* partial addresses. */
/**********************************************/
unsigned long numberize(const char *addr)
{
unsigned long sin_addr;
int retval;
retval = inet_pton(AF_INET, addr, &sin_addr);
/* invalid address or error in inet_pton() */
if(retval == 0 || retval == -1)
return -1;
return ntohl(sin_addr);
}
/**********************************************/
/* Converts an IP address into dotted decimal */
/* format. Note that this function cannot be */
/* used twice in one instruction (e.g. printf */
/* ("%s%s",denumberize(x),denumberize(y))); */
/* because the return value is static. */
/**********************************************/
const char *denumberize(unsigned long addr)
{
static char buffer[INET_ADDRSTRLEN];
unsigned long addr_nl = htonl(addr);
if(!inet_ntop(AF_INET, &addr_nl, buffer, sizeof(buffer)))
return NULL;
return buffer;
}
/**********************************************/
/* Given start and end IP addresses, we try */
/* to find the offset used to print the range */
/* in CIDR notation. */
/**********************************************/
const char *cidrize(unsigned long start, unsigned long end)
{
unsigned long base;
int offset = 0;
static char *buffer[BUF_SIZE];
/* find the mask (offset) by finding the
* highest bit set differently in the start
* and end addresses.
*/
unsigned long diff = start ^ end;
/* find the highest bit set in diff */
int i;
for(i=1; i <= 32; i++)
{
if (diff == 0)
{
offset = i - 1;
break;
}
diff = diff >> 1;
}
/* clear out the bits below the mask */
base = (start >> offset) << offset;
snprintf((char *) buffer, BUF_SIZE, "%s/%d",
denumberize(base), 32 - offset);
return((char *) buffer);
}
/***********************************************/
/* Takes offset (number of bits from the left */
/* of addr) and subtracts it from the number */
/* of possible bits. The number of possible */
/* bits is the number of bits left for hosts. */
/* We then return last host address. */
/***********************************************/
unsigned long add_offset(const char *addr, int offset)
{
unsigned long naddr;
if(offset > 32 || offset < 0)
{
fprintf(stderr, "CIDR offsets are between 0 and 32\n");
exit(1);
}
naddr = numberize(addr);
if((naddr << offset) != 0)
{
fprintf(stderr,
"CIDR base address didn't start at subnet boundary\n");
exit(1);
}
return (int) pow(2, 32 - offset) + naddr -1;
}
unsigned long set_bits_from_right(int bits)
{
register int i;
unsigned long number = 0;
for(i = 0; i < bits; i++)
number += (int) pow(2, i);
return number;
}
int count_on_bits(unsigned long number)
{
unsigned long mask = 1;
int i, on_bits = 0;
mask <<= 31;
for(i = 0; i < 32; i++)
{
if(mask & number)
on_bits++;
number <<= 1;
}
return on_bits;
}
char get_class(unsigned long address)
{
unsigned long addr;
char class;
addr = (address & 0xff000000) >> 24;
if (addr < 127)
class = 'a';
else if (addr >= 127 && addr < 192)
class = 'b';
else if (addr >= 192 && addr < 224)
class = 'c';
else
class = 'd';
return class;
}
syntax highlighted by Code2HTML, v. 0.9.1