|
Packit |
71e9d6 |
/*
|
|
Packit |
71e9d6 |
* Copyright (c) 1997-2015 Red Hat, Inc. All rights reserved.
|
|
Packit |
71e9d6 |
*
|
|
Packit |
71e9d6 |
* This program is free software; you can redistribute it and/or modify
|
|
Packit |
71e9d6 |
* it under the terms of the GNU General Public License, version 2,
|
|
Packit |
71e9d6 |
* as published by the Free Software Foundation.
|
|
Packit |
71e9d6 |
*
|
|
Packit |
71e9d6 |
* This program is distributed in the hope that it will be useful,
|
|
Packit |
71e9d6 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
71e9d6 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
Packit |
71e9d6 |
* GNU General Public License for more details.
|
|
Packit |
71e9d6 |
*
|
|
Packit |
71e9d6 |
* You should have received a copy of the GNU General Public License
|
|
Packit |
71e9d6 |
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
Packit |
71e9d6 |
*
|
|
Packit |
71e9d6 |
* Authors:
|
|
Packit |
71e9d6 |
* Nikos Mavrogiannopoulos <nmav@redhat.com>
|
|
Packit |
71e9d6 |
* Erik Troan <ewt@redhat.com>
|
|
Packit |
71e9d6 |
* Preston Brown <pbrown@redhat.com>
|
|
Packit |
71e9d6 |
* David Cantrell <dcantrell@redhat.com>
|
|
Packit |
71e9d6 |
*/
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
#define _GNU_SOURCE /* asprintf */
|
|
Packit |
71e9d6 |
#include <ctype.h>
|
|
Packit |
71e9d6 |
#include <getopt.h>
|
|
Packit |
71e9d6 |
#include <stdio.h>
|
|
Packit |
71e9d6 |
#include <stdlib.h>
|
|
Packit |
71e9d6 |
#include <stdarg.h>
|
|
Packit |
71e9d6 |
#include <string.h>
|
|
Packit |
71e9d6 |
#include <sys/socket.h>
|
|
Packit |
71e9d6 |
#include <sys/types.h>
|
|
Packit |
71e9d6 |
#include <sys/stat.h> /* open */
|
|
Packit |
71e9d6 |
#include <fcntl.h> /* open */
|
|
Packit |
71e9d6 |
#include <unistd.h> /* read */
|
|
Packit |
71e9d6 |
#include <netinet/in.h>
|
|
Packit |
71e9d6 |
#include <arpa/inet.h>
|
|
Packit |
71e9d6 |
#include <netdb.h>
|
|
Packit |
71e9d6 |
#include <errno.h>
|
|
Packit |
71e9d6 |
#include <time.h> /* clock_gettime */
|
|
Packit |
71e9d6 |
#include "ipcalc.h"
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
int beSilent = 0;
|
|
Packit |
71e9d6 |
static unsigned colors = 0;
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
/*!
|
|
Packit |
71e9d6 |
\file ipcalc.c
|
|
Packit |
71e9d6 |
\brief provides utilities for manipulating IP addresses.
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
ipcalc provides utilities and a front-end command line interface for
|
|
Packit |
71e9d6 |
manipulating IP addresses, and calculating various aspects of an ip
|
|
Packit |
71e9d6 |
address/netmask/network address/prefix/etc.
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
Functionality can be accessed from other languages from the library
|
|
Packit |
71e9d6 |
interface, documented here. To use ipcalc from the shell, read the
|
|
Packit |
71e9d6 |
ipcalc(1) manual page.
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
When passing parameters to the various functions, take note of whether they
|
|
Packit |
71e9d6 |
take host byte order or network byte order. Most take host byte order, and
|
|
Packit |
71e9d6 |
return host byte order, but there are some exceptions.
|
|
Packit |
71e9d6 |
*/
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
static int safe_atoi(const char *s, int *ret_i)
|
|
Packit |
71e9d6 |
{
|
|
Packit |
71e9d6 |
char *x = NULL;
|
|
Packit |
71e9d6 |
long l;
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
errno = 0;
|
|
Packit |
71e9d6 |
l = strtol(s, &x, 0);
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
if (!x || x == s || *x || errno)
|
|
Packit |
71e9d6 |
return errno > 0 ? -errno : -EINVAL;
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
if ((long)(int)l != l)
|
|
Packit |
71e9d6 |
return -ERANGE;
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
*ret_i = (int)l;
|
|
Packit |
71e9d6 |
return 0;
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
/*!
|
|
Packit |
71e9d6 |
\fn char safe_strdup(const char *s)
|
|
Packit |
71e9d6 |
\brief strdup(3) that checks memory allocation or fail
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
This function does the same as strdup(3) with additional memory allocation
|
|
Packit |
71e9d6 |
check. When check fails the function will cause program to exit.
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
\param string to be duplicated
|
|
Packit |
71e9d6 |
\return allocated duplicate
|
|
Packit |
71e9d6 |
*/
|
|
Packit |
71e9d6 |
extern char __attribute__((warn_unused_result)) *safe_strdup(const char *str)
|
|
Packit |
71e9d6 |
{
|
|
Packit |
71e9d6 |
char *ret;
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
if (!str)
|
|
Packit |
71e9d6 |
return NULL;
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
ret = strdup(str);
|
|
Packit |
71e9d6 |
if (!ret) {
|
|
Packit |
71e9d6 |
fprintf(stderr, "Memory allocation failure\n");
|
|
Packit |
71e9d6 |
exit(1);
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
return ret;
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
/*!
|
|
Packit |
71e9d6 |
\fn uint32_t prefix2mask(int bits)
|
|
Packit |
71e9d6 |
\brief creates a netmask from a specified number of bits
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
This function converts a prefix length to a netmask. As CIDR (classless
|
|
Packit |
71e9d6 |
internet domain internet domain routing) has taken off, more an more IP
|
|
Packit |
71e9d6 |
addresses are being specified in the format address/prefix
|
|
Packit |
71e9d6 |
(i.e. 192.168.2.3/24, with a corresponding netmask 255.255.255.0). If you
|
|
Packit |
71e9d6 |
need to see what netmask corresponds to the prefix part of the address, this
|
|
Packit |
71e9d6 |
is the function. See also \ref mask2prefix.
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
\param prefix is the number of bits to create a mask for.
|
|
Packit |
71e9d6 |
\return a network mask, in network byte order.
|
|
Packit |
71e9d6 |
*/
|
|
Packit |
71e9d6 |
uint32_t prefix2mask(int prefix)
|
|
Packit |
71e9d6 |
{
|
|
Packit |
71e9d6 |
struct in_addr mask;
|
|
Packit |
71e9d6 |
memset(&mask, 0, sizeof(mask));
|
|
Packit |
71e9d6 |
if (prefix) {
|
|
Packit |
71e9d6 |
return htonl(~((1 << (32 - prefix)) - 1));
|
|
Packit |
71e9d6 |
} else {
|
|
Packit |
71e9d6 |
return htonl(0);
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
/*!
|
|
Packit |
71e9d6 |
\fn struct in_addr calc_broadcast(struct in_addr addr, int prefix)
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
\brief calculate broadcast address given an IP address and a prefix length.
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
\param addr an IP address in network byte order.
|
|
Packit |
71e9d6 |
\param prefix a prefix length.
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
\return the calculated broadcast address for the network, in network byte
|
|
Packit |
71e9d6 |
order.
|
|
Packit |
71e9d6 |
*/
|
|
Packit |
71e9d6 |
static struct in_addr calc_broadcast(struct in_addr addr, int prefix)
|
|
Packit |
71e9d6 |
{
|
|
Packit |
71e9d6 |
struct in_addr mask;
|
|
Packit |
71e9d6 |
struct in_addr broadcast;
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
mask.s_addr = prefix2mask(prefix);
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
memset(&broadcast, 0, sizeof(broadcast));
|
|
rpm-build |
8213c1 |
|
|
rpm-build |
8213c1 |
/* if prefix is set to 31 return 255.255.255.255 (RFC3021) */
|
|
rpm-build |
8213c1 |
if (mask.s_addr == htonl(0xFFFFFFFE))
|
|
rpm-build |
8213c1 |
broadcast.s_addr = htonl(0xFFFFFFFF);
|
|
rpm-build |
8213c1 |
else
|
|
rpm-build |
8213c1 |
broadcast.s_addr = (addr.s_addr & mask.s_addr) | ~mask.s_addr;
|
|
Packit |
71e9d6 |
return broadcast;
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
/*!
|
|
Packit |
71e9d6 |
\fn struct in_addr calc_network(struct in_addr addr, int prefix)
|
|
Packit |
71e9d6 |
\brief calculates the network address for a specified address and prefix.
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
\param addr an IP address, in network byte order
|
|
Packit |
71e9d6 |
\param prefix the network prefix
|
|
Packit |
71e9d6 |
\return the base address of the network that addr is associated with, in
|
|
Packit |
71e9d6 |
network byte order.
|
|
Packit |
71e9d6 |
*/
|
|
Packit |
71e9d6 |
static struct in_addr calc_network(struct in_addr addr, int prefix)
|
|
Packit |
71e9d6 |
{
|
|
Packit |
71e9d6 |
struct in_addr mask;
|
|
Packit |
71e9d6 |
struct in_addr network;
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
mask.s_addr = prefix2mask(prefix);
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
memset(&network, 0, sizeof(network));
|
|
Packit |
71e9d6 |
network.s_addr = addr.s_addr & mask.s_addr;
|
|
Packit |
71e9d6 |
return network;
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
/*!
|
|
Packit |
71e9d6 |
\fn const char *get_hostname(int family, void *addr)
|
|
Packit |
71e9d6 |
\brief returns the hostname associated with the specified IP address
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
\param family the address family, either AF_INET or AF_INET6.
|
|
Packit |
71e9d6 |
\param addr an IP address to find a hostname for, in network byte order,
|
|
Packit |
71e9d6 |
should either be a pointer to a struct in_addr or a struct in6_addr.
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
\return a hostname, or NULL if one cannot be determined. Hostname is stored
|
|
Packit |
71e9d6 |
in an allocated buffer.
|
|
Packit |
71e9d6 |
*/
|
|
Packit |
71e9d6 |
static char *get_hostname(int family, void *addr)
|
|
Packit |
71e9d6 |
{
|
|
Packit |
71e9d6 |
static char hostname[NI_MAXHOST];
|
|
Packit |
71e9d6 |
int ret = -1;
|
|
Packit |
71e9d6 |
struct sockaddr_in addr4;
|
|
Packit |
71e9d6 |
struct sockaddr_in6 addr6;
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
if (family == AF_INET) {
|
|
Packit |
71e9d6 |
memset(&addr4, 0, sizeof(addr4));
|
|
Packit |
71e9d6 |
addr4.sin_family = AF_INET;
|
|
Packit |
71e9d6 |
memcpy(&addr4.sin_addr, addr, sizeof(struct in_addr));
|
|
Packit |
71e9d6 |
ret = getnameinfo((struct sockaddr*)&addr4, sizeof(addr4), hostname, sizeof(hostname), NULL, 0, 0);
|
|
Packit |
71e9d6 |
} else if (family == AF_INET6) {
|
|
Packit |
71e9d6 |
memset(&addr6, 0, sizeof(addr6));
|
|
Packit |
71e9d6 |
addr6.sin6_family = AF_INET6;
|
|
Packit |
71e9d6 |
memcpy(&addr6.sin6_addr, addr, sizeof(struct in6_addr));
|
|
Packit |
71e9d6 |
ret = getnameinfo((struct sockaddr*)&addr6, sizeof(addr6), hostname, sizeof(hostname), NULL, 0, 0);
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
if (ret != 0)
|
|
Packit |
71e9d6 |
return NULL;
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
return safe_strdup(hostname);
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
/*!
|
|
Packit |
71e9d6 |
\fn const char *get_ip_address(int family, void *addr)
|
|
Packit |
71e9d6 |
\brief returns the IP address associated with the specified hostname
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
\param family the requested address family or AF_UNSPEC for any
|
|
Packit |
71e9d6 |
\param host a hostname
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
\return an IP address, or NULL if one cannot be determined. The IP is stored
|
|
Packit |
71e9d6 |
in an allocated buffer.
|
|
Packit |
71e9d6 |
*/
|
|
Packit |
71e9d6 |
static char *get_ip_address(int family, const char *host)
|
|
Packit |
71e9d6 |
{
|
|
Packit |
71e9d6 |
struct addrinfo *res, *rp;
|
|
Packit |
71e9d6 |
struct addrinfo hints;
|
|
Packit |
71e9d6 |
int err;
|
|
Packit |
71e9d6 |
static char ipname[64];
|
|
Packit |
71e9d6 |
void *addr;
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
memset(&hints, 0, sizeof(hints));
|
|
Packit |
71e9d6 |
hints.ai_family = family;
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
err = getaddrinfo(host, NULL, &hints, &res;;
|
|
Packit |
71e9d6 |
if (err != 0)
|
|
Packit |
71e9d6 |
return NULL;
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
for (rp=res;rp!=NULL;rp=rp->ai_next) {
|
|
Packit |
71e9d6 |
if (rp->ai_family == AF_INET)
|
|
Packit |
71e9d6 |
addr = (&((struct sockaddr_in *)(rp->ai_addr))->sin_addr);
|
|
Packit |
71e9d6 |
else
|
|
Packit |
71e9d6 |
addr = (&((struct sockaddr_in6 *)(rp->ai_addr))->sin6_addr);
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
if (inet_ntop(rp->ai_family, addr, ipname, sizeof(ipname)) != NULL) {
|
|
Packit |
71e9d6 |
freeaddrinfo(res);
|
|
Packit |
71e9d6 |
return safe_strdup(ipname);
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
freeaddrinfo(res);
|
|
Packit |
71e9d6 |
return NULL;
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
static int bit_count(uint32_t i)
|
|
Packit |
71e9d6 |
{
|
|
Packit |
71e9d6 |
int c = 0;
|
|
Packit |
71e9d6 |
unsigned int seen_one = 0;
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
while (i > 0) {
|
|
Packit |
71e9d6 |
if (i & 1) {
|
|
Packit |
71e9d6 |
seen_one = 1;
|
|
Packit |
71e9d6 |
c++;
|
|
Packit |
71e9d6 |
} else {
|
|
Packit |
71e9d6 |
if (seen_one) {
|
|
Packit |
71e9d6 |
return -1;
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
i >>= 1;
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
return c;
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
/*!
|
|
Packit |
71e9d6 |
\fn int mask2prefix(struct in_addr mask)
|
|
Packit |
71e9d6 |
\brief calculates the number of bits masked off by a netmask.
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
This function calculates the significant bits in an IP address as specified by
|
|
Packit |
71e9d6 |
a netmask. See also \ref prefix2mask.
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
\param mask is the netmask, specified as an struct in_addr in network byte order.
|
|
Packit |
71e9d6 |
\return the number of significant bits. */
|
|
Packit |
71e9d6 |
static int mask2prefix(struct in_addr mask)
|
|
Packit |
71e9d6 |
{
|
|
Packit |
71e9d6 |
return bit_count(ntohl(mask.s_addr));
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
static
|
|
Packit |
71e9d6 |
int ipv4_mask_to_int(const char *prefix)
|
|
Packit |
71e9d6 |
{
|
|
Packit |
71e9d6 |
int ret;
|
|
Packit |
71e9d6 |
struct in_addr in;
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
ret = inet_pton(AF_INET, prefix, &in);
|
|
Packit |
71e9d6 |
if (ret == 0)
|
|
Packit |
71e9d6 |
return -1;
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
return mask2prefix(in);
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
/* Returns powers of two in textual format */
|
|
Packit |
71e9d6 |
static const char *p2_table(unsigned pow)
|
|
Packit |
71e9d6 |
{
|
|
Packit |
71e9d6 |
static const char *pow2[] = {
|
|
Packit |
71e9d6 |
"1",
|
|
Packit |
71e9d6 |
"2",
|
|
Packit |
71e9d6 |
"4",
|
|
Packit |
71e9d6 |
"8",
|
|
Packit |
71e9d6 |
"16",
|
|
Packit |
71e9d6 |
"32",
|
|
Packit |
71e9d6 |
"64",
|
|
Packit |
71e9d6 |
"128",
|
|
Packit |
71e9d6 |
"256",
|
|
Packit |
71e9d6 |
"512",
|
|
Packit |
71e9d6 |
"1024",
|
|
Packit |
71e9d6 |
"2048",
|
|
Packit |
71e9d6 |
"4096",
|
|
Packit |
71e9d6 |
"8192",
|
|
Packit |
71e9d6 |
"16384",
|
|
Packit |
71e9d6 |
"32768",
|
|
Packit |
71e9d6 |
"65536",
|
|
Packit |
71e9d6 |
"131072",
|
|
Packit |
71e9d6 |
"262144",
|
|
Packit |
71e9d6 |
"524288",
|
|
Packit |
71e9d6 |
"1048576",
|
|
Packit |
71e9d6 |
"2097152",
|
|
Packit |
71e9d6 |
"4194304",
|
|
Packit |
71e9d6 |
"8388608",
|
|
Packit |
71e9d6 |
"16777216",
|
|
Packit |
71e9d6 |
"33554432",
|
|
Packit |
71e9d6 |
"67108864",
|
|
Packit |
71e9d6 |
"134217728",
|
|
Packit |
71e9d6 |
"268435456",
|
|
Packit |
71e9d6 |
"536870912",
|
|
Packit |
71e9d6 |
"1073741824",
|
|
Packit |
71e9d6 |
"2147483648",
|
|
Packit |
71e9d6 |
"4294967296",
|
|
Packit |
71e9d6 |
"8589934592",
|
|
Packit |
71e9d6 |
"17179869184",
|
|
Packit |
71e9d6 |
"34359738368",
|
|
Packit |
71e9d6 |
"68719476736",
|
|
Packit |
71e9d6 |
"137438953472",
|
|
Packit |
71e9d6 |
"274877906944",
|
|
Packit |
71e9d6 |
"549755813888",
|
|
Packit |
71e9d6 |
"1099511627776",
|
|
Packit |
71e9d6 |
"2199023255552",
|
|
Packit |
71e9d6 |
"4398046511104",
|
|
Packit |
71e9d6 |
"8796093022208",
|
|
Packit |
71e9d6 |
"17592186044416",
|
|
Packit |
71e9d6 |
"35184372088832",
|
|
Packit |
71e9d6 |
"70368744177664",
|
|
Packit |
71e9d6 |
"140737488355328",
|
|
Packit |
71e9d6 |
"281474976710656",
|
|
Packit |
71e9d6 |
"562949953421312",
|
|
Packit |
71e9d6 |
"1125899906842624",
|
|
Packit |
71e9d6 |
"2251799813685248",
|
|
Packit |
71e9d6 |
"4503599627370496",
|
|
Packit |
71e9d6 |
"9007199254740992",
|
|
Packit |
71e9d6 |
"18014398509481984",
|
|
Packit |
71e9d6 |
"36028797018963968",
|
|
Packit |
71e9d6 |
"72057594037927936",
|
|
Packit |
71e9d6 |
"144115188075855872",
|
|
Packit |
71e9d6 |
"288230376151711744",
|
|
Packit |
71e9d6 |
"576460752303423488",
|
|
Packit |
71e9d6 |
"1152921504606846976",
|
|
Packit |
71e9d6 |
"2305843009213693952",
|
|
Packit |
71e9d6 |
"4611686018427387904",
|
|
Packit |
71e9d6 |
"9223372036854775808",
|
|
Packit |
71e9d6 |
"18446744073709551616",
|
|
Packit |
71e9d6 |
"36893488147419103232",
|
|
Packit |
71e9d6 |
"73786976294838206464",
|
|
Packit |
71e9d6 |
"147573952589676412928",
|
|
Packit |
71e9d6 |
"295147905179352825856",
|
|
Packit |
71e9d6 |
"590295810358705651712",
|
|
Packit |
71e9d6 |
"1180591620717411303424",
|
|
Packit |
71e9d6 |
"2361183241434822606848",
|
|
Packit |
71e9d6 |
"4722366482869645213696",
|
|
Packit |
71e9d6 |
"9444732965739290427392",
|
|
Packit |
71e9d6 |
"18889465931478580854784",
|
|
Packit |
71e9d6 |
"37778931862957161709568",
|
|
Packit |
71e9d6 |
"75557863725914323419136",
|
|
Packit |
71e9d6 |
"151115727451828646838272",
|
|
Packit |
71e9d6 |
"302231454903657293676544",
|
|
Packit |
71e9d6 |
"604462909807314587353088",
|
|
Packit |
71e9d6 |
"1208925819614629174706176",
|
|
Packit |
71e9d6 |
"2417851639229258349412352",
|
|
Packit |
71e9d6 |
"4835703278458516698824704",
|
|
Packit |
71e9d6 |
"9671406556917033397649408",
|
|
Packit |
71e9d6 |
"19342813113834066795298816",
|
|
Packit |
71e9d6 |
"38685626227668133590597632",
|
|
Packit |
71e9d6 |
"77371252455336267181195264",
|
|
Packit |
71e9d6 |
"154742504910672534362390528",
|
|
Packit |
71e9d6 |
"309485009821345068724781056",
|
|
Packit |
71e9d6 |
"618970019642690137449562112",
|
|
Packit |
71e9d6 |
"1237940039285380274899124224",
|
|
Packit |
71e9d6 |
"2475880078570760549798248448",
|
|
Packit |
71e9d6 |
"4951760157141521099596496896",
|
|
Packit |
71e9d6 |
"9903520314283042199192993792",
|
|
Packit |
71e9d6 |
"19807040628566084398385987584",
|
|
Packit |
71e9d6 |
"39614081257132168796771975168",
|
|
Packit |
71e9d6 |
"79228162514264337593543950336",
|
|
Packit |
71e9d6 |
"158456325028528675187087900672",
|
|
Packit |
71e9d6 |
"316912650057057350374175801344",
|
|
Packit |
71e9d6 |
"633825300114114700748351602688",
|
|
Packit |
71e9d6 |
"1267650600228229401496703205376",
|
|
Packit |
71e9d6 |
"2535301200456458802993406410752",
|
|
Packit |
71e9d6 |
"5070602400912917605986812821504",
|
|
Packit |
71e9d6 |
"10141204801825835211973625643008",
|
|
Packit |
71e9d6 |
"20282409603651670423947251286016",
|
|
Packit |
71e9d6 |
"40564819207303340847894502572032",
|
|
Packit |
71e9d6 |
"81129638414606681695789005144064",
|
|
Packit |
71e9d6 |
"162259276829213363391578010288128",
|
|
Packit |
71e9d6 |
"324518553658426726783156020576256",
|
|
Packit |
71e9d6 |
"649037107316853453566312041152512",
|
|
Packit |
71e9d6 |
"1298074214633706907132624082305024",
|
|
Packit |
71e9d6 |
"2596148429267413814265248164610048",
|
|
Packit |
71e9d6 |
"5192296858534827628530496329220096",
|
|
Packit |
71e9d6 |
"10384593717069655257060992658440192",
|
|
Packit |
71e9d6 |
"20769187434139310514121985316880384",
|
|
Packit |
71e9d6 |
"41538374868278621028243970633760768",
|
|
Packit |
71e9d6 |
"83076749736557242056487941267521536",
|
|
Packit |
71e9d6 |
"166153499473114484112975882535043072",
|
|
Packit |
71e9d6 |
"332306998946228968225951765070086144",
|
|
Packit |
71e9d6 |
"664613997892457936451903530140172288",
|
|
Packit |
71e9d6 |
"1329227995784915872903807060280344576",
|
|
Packit |
71e9d6 |
"2658455991569831745807614120560689152",
|
|
Packit |
71e9d6 |
"5316911983139663491615228241121378304",
|
|
Packit |
71e9d6 |
"10633823966279326983230456482242756608",
|
|
Packit |
71e9d6 |
"21267647932558653966460912964485513216",
|
|
Packit |
71e9d6 |
"42535295865117307932921825928971026432",
|
|
Packit |
71e9d6 |
"85070591730234615865843651857942052864",
|
|
Packit |
71e9d6 |
"170141183460469231731687303715884105728",
|
|
Packit |
71e9d6 |
};
|
|
Packit |
71e9d6 |
if (pow <= 127)
|
|
Packit |
71e9d6 |
return pow2[pow];
|
|
Packit |
71e9d6 |
return "";
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
static const char *ipv4_net_to_type(struct in_addr net)
|
|
Packit |
71e9d6 |
{
|
|
Packit |
71e9d6 |
unsigned byte1 = (ntohl(net.s_addr) >> 24) & 0xff;
|
|
Packit |
71e9d6 |
unsigned byte2 = (ntohl(net.s_addr) >> 16) & 0xff;
|
|
Packit |
71e9d6 |
unsigned byte3 = (ntohl(net.s_addr) >> 8) & 0xff;
|
|
Packit |
71e9d6 |
unsigned byte4 = (ntohl(net.s_addr)) & 0xff;
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
/* based on IANA's iana-ipv4-special-registry and ipv4-address-space
|
|
Packit |
71e9d6 |
* Updated: 2015-05-12
|
|
Packit |
71e9d6 |
*/
|
|
Packit |
71e9d6 |
if (byte1 == 0) {
|
|
Packit |
71e9d6 |
return "This host on this network";
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
if (byte1 == 10) {
|
|
Packit |
71e9d6 |
return "Private Use";
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
if (byte1 == 100 && (byte2 & 0xc0) == 64) {
|
|
Packit |
71e9d6 |
return "Shared Address Space";
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
if (byte1 == 127) {
|
|
Packit |
71e9d6 |
return "Loopback";
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
if (byte1 == 169 && byte2 == 254) {
|
|
Packit |
71e9d6 |
return "Link Local";
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
if (byte1 == 172 && (byte2 & 0xf0) == 16) {
|
|
Packit |
71e9d6 |
return "Private Use";
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
if (byte1 == 192 && byte2 == 0 && byte3 == 0) {
|
|
Packit |
71e9d6 |
return "IETF Protocol Assignments";
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
if (byte1 == 192 && byte2 == 2 && byte3 == 0) {
|
|
Packit |
71e9d6 |
return "Documentation (TEST-NET-1)";
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
if (byte1 == 192 && byte2 == 51 && byte3 == 100) {
|
|
Packit |
71e9d6 |
return "Documentation (TEST-NET-2)";
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
if (byte1 == 203 && byte2 == 0 && byte3 == 113) {
|
|
Packit |
71e9d6 |
return "Documentation (TEST-NET-3)";
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
if (byte1 == 192 && byte2 == 88 && byte3 == 99) {
|
|
Packit |
71e9d6 |
return "6 to 4 Relay Anycast (Deprecated)";
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
if (byte1 == 192 && byte2 == 52 && byte3 == 193) {
|
|
Packit |
71e9d6 |
return "AMT";
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
if (byte1 == 192 && byte2 == 168) {
|
|
Packit |
71e9d6 |
return "Private Use";
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
if (byte1 == 255 && byte2 == 255 && byte3 == 255 && byte4 == 255) {
|
|
Packit |
71e9d6 |
return "Limited Broadcast";
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
if (byte1 == 198 && (byte2 & 0xfe) == 18) {
|
|
Packit |
71e9d6 |
return "Benchmarking";
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
if (byte1 >= 224 && byte1 <= 239) {
|
|
Packit |
71e9d6 |
return "Multicast";
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
if ((byte1 & 0xf0) == 240) {
|
|
Packit |
71e9d6 |
return "Reserved";
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
return "Internet";
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
static
|
|
Packit |
71e9d6 |
const char *ipv4_net_to_class(struct in_addr net)
|
|
Packit |
71e9d6 |
{
|
|
Packit |
71e9d6 |
unsigned byte1 = (ntohl(net.s_addr) >> 24) & 0xff;
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
if (byte1 < 128) {
|
|
Packit |
71e9d6 |
return "Class A";
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
if (byte1 >= 128 && byte1 < 192) {
|
|
Packit |
71e9d6 |
return "Class B";
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
if (byte1 >= 192 && byte1 < 224) {
|
|
Packit |
71e9d6 |
return "Class C";
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
if (byte1 >= 224 && byte1 < 239) {
|
|
Packit |
71e9d6 |
return "Class D";
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
return "Class E";
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
static
|
|
Packit |
71e9d6 |
unsigned default_ipv4_prefix(struct in_addr net)
|
|
Packit |
71e9d6 |
{
|
|
Packit |
71e9d6 |
unsigned byte1 = (ntohl(net.s_addr) >> 24) & 0xff;
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
if (byte1 < 128) {
|
|
Packit |
71e9d6 |
return 8;
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
if (byte1 >= 128 && byte1 < 192) {
|
|
Packit |
71e9d6 |
return 16;
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
if (byte1 >= 192 && byte1 < 224) {
|
|
Packit |
71e9d6 |
return 24;
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
return 24;
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
char *ipv4_prefix_to_hosts(char *hosts, unsigned hosts_size, unsigned prefix)
|
|
Packit |
71e9d6 |
{
|
|
Packit |
71e9d6 |
unsigned tmp;
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
if (prefix >= 31) {
|
|
Packit |
71e9d6 |
snprintf(hosts, hosts_size, "%s", p2_table(32 - prefix));
|
|
Packit |
71e9d6 |
} else {
|
|
Packit |
71e9d6 |
tmp = (1 << (32 - prefix)) - 2;
|
|
Packit |
71e9d6 |
snprintf(hosts, hosts_size, "%u", tmp);
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
return hosts;
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
char *ipv6_prefix_to_hosts(char *hosts, unsigned hosts_size, unsigned prefix)
|
|
Packit |
71e9d6 |
{
|
|
Packit |
71e9d6 |
snprintf(hosts, hosts_size, "%s", p2_table(128 - prefix));
|
|
Packit |
71e9d6 |
return hosts;
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
static
|
|
Packit |
71e9d6 |
int get_ipv4_info(const char *ipStr, int prefix, ip_info_st * info,
|
|
Packit |
71e9d6 |
unsigned flags)
|
|
Packit |
71e9d6 |
{
|
|
Packit |
71e9d6 |
struct in_addr ip, netmask, network, broadcast, minhost, maxhost;
|
|
Packit |
71e9d6 |
char namebuf[INET_ADDRSTRLEN + 1];
|
|
Packit |
71e9d6 |
char errBuf[250];
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
memset(info, 0, sizeof(*info));
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
if (inet_pton(AF_INET, ipStr, &ip) <= 0) {
|
|
Packit |
71e9d6 |
if (!beSilent)
|
|
Packit |
71e9d6 |
fprintf(stderr, "ipcalc: bad IPv4 address: %s\n",
|
|
Packit |
71e9d6 |
ipStr);
|
|
Packit |
71e9d6 |
return -1;
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
/* Handle CIDR entries such as 172/8 */
|
|
Packit |
71e9d6 |
if (prefix >= 0) {
|
|
Packit |
71e9d6 |
char *tmp = (char *)ipStr;
|
|
Packit |
71e9d6 |
int i;
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
for (i = 3; i > 0; i--) {
|
|
Packit |
71e9d6 |
tmp = strchr(tmp, '.');
|
|
Packit |
71e9d6 |
if (!tmp)
|
|
Packit |
71e9d6 |
break;
|
|
Packit |
71e9d6 |
else
|
|
Packit |
71e9d6 |
tmp++;
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
tmp = NULL;
|
|
Packit |
71e9d6 |
for (; i > 0; i--) {
|
|
Packit |
71e9d6 |
if (asprintf(&tmp, "%s.0", ipStr) == -1) {
|
|
Packit |
71e9d6 |
fprintf(stderr,
|
|
Packit |
71e9d6 |
"Memory allocation failure line %d\n",
|
|
Packit |
71e9d6 |
__LINE__);
|
|
Packit |
71e9d6 |
abort();
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
ipStr = tmp;
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
} else { /* assume good old days classful Internet */
|
|
Packit |
71e9d6 |
if (flags & FLAG_ASSUME_CLASS_PREFIX)
|
|
Packit |
71e9d6 |
prefix = default_ipv4_prefix(ip);
|
|
Packit |
71e9d6 |
else
|
|
Packit |
71e9d6 |
prefix = 32;
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
if (prefix > 32) {
|
|
Packit |
71e9d6 |
if (!beSilent)
|
|
Packit |
71e9d6 |
fprintf(stderr, "ipcalc: bad IPv4 prefix %d\n", prefix);
|
|
Packit |
71e9d6 |
return -1;
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
if (inet_ntop(AF_INET, &ip, namebuf, sizeof(namebuf)) == 0) {
|
|
Packit |
71e9d6 |
if (!beSilent)
|
|
Packit |
71e9d6 |
fprintf(stderr,
|
|
Packit |
71e9d6 |
"ipcalc: error calculating the IPv4 network\n");
|
|
Packit |
71e9d6 |
return -1;
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
info->ip = safe_strdup(namebuf);
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
netmask.s_addr = prefix2mask(prefix);
|
|
Packit |
71e9d6 |
memset(namebuf, '\0', sizeof(namebuf));
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
if (inet_ntop(AF_INET, &netmask, namebuf, INET_ADDRSTRLEN) == NULL) {
|
|
Packit |
71e9d6 |
fprintf(stderr, "Memory allocation failure line %d\n",
|
|
Packit |
71e9d6 |
__LINE__);
|
|
Packit |
71e9d6 |
abort();
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
info->netmask = safe_strdup(namebuf);
|
|
Packit |
71e9d6 |
info->prefix = prefix;
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
broadcast = calc_broadcast(ip, prefix);
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
memset(namebuf, '\0', sizeof(namebuf));
|
|
Packit |
71e9d6 |
if (inet_ntop(AF_INET, &broadcast, namebuf, INET_ADDRSTRLEN) == NULL) {
|
|
Packit |
71e9d6 |
fprintf(stderr, "Memory allocation failure line %d\n",
|
|
Packit |
71e9d6 |
__LINE__);
|
|
Packit |
71e9d6 |
abort();
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
info->broadcast = safe_strdup(namebuf);
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
network = calc_network(ip, prefix);
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
info->reverse_dns = calc_reverse_dns4(network, prefix, network, broadcast);
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
memset(namebuf, '\0', sizeof(namebuf));
|
|
Packit |
71e9d6 |
if (inet_ntop(AF_INET, &network, namebuf, INET_ADDRSTRLEN) == NULL) {
|
|
Packit |
71e9d6 |
fprintf(stderr, "Memory allocation failure line %d\n",
|
|
Packit |
71e9d6 |
__LINE__);
|
|
Packit |
71e9d6 |
abort();
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
info->network = safe_strdup(namebuf);
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
info->type = ipv4_net_to_type(network);
|
|
Packit |
71e9d6 |
info->class = ipv4_net_to_class(network);
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
if (prefix < 32) {
|
|
Packit |
71e9d6 |
memcpy(&minhost, &network, sizeof(minhost));
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
if (prefix <= 30)
|
|
Packit |
71e9d6 |
minhost.s_addr = htonl(ntohl(minhost.s_addr) | 1);
|
|
Packit |
71e9d6 |
if (inet_ntop(AF_INET, &minhost, namebuf, INET_ADDRSTRLEN) ==
|
|
Packit |
71e9d6 |
NULL) {
|
|
Packit |
71e9d6 |
fprintf(stderr, "Memory allocation failure line %d\n",
|
|
Packit |
71e9d6 |
__LINE__);
|
|
Packit |
71e9d6 |
abort();
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
info->hostmin = safe_strdup(namebuf);
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
memcpy(&maxhost, &network, sizeof(minhost));
|
|
Packit |
71e9d6 |
maxhost.s_addr |= ~netmask.s_addr;
|
|
Packit |
71e9d6 |
if (prefix <= 30) {
|
|
Packit |
71e9d6 |
maxhost.s_addr = htonl(ntohl(maxhost.s_addr) - 1);
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
if (inet_ntop(AF_INET, &maxhost, namebuf, sizeof(namebuf)) == 0) {
|
|
Packit |
71e9d6 |
if (!beSilent)
|
|
Packit |
71e9d6 |
fprintf(stderr,
|
|
Packit |
71e9d6 |
"ipcalc: error calculating the IPv4 network\n");
|
|
Packit |
71e9d6 |
return -1;
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
info->hostmax = safe_strdup(namebuf);
|
|
Packit |
71e9d6 |
} else {
|
|
Packit |
71e9d6 |
info->hostmin = info->network;
|
|
Packit |
71e9d6 |
info->hostmax = info->network;
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
ipv4_prefix_to_hosts(info->hosts, sizeof(info->hosts), prefix);
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
if (flags & FLAG_GET_GEOIP) {
|
|
Packit |
71e9d6 |
geo_ip_lookup(ipStr, &info->geoip_country, &info->geoip_ccode, &info->geoip_city, &info->geoip_coord);
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
if (flags & FLAG_RESOLVE_HOST) {
|
|
Packit |
71e9d6 |
info->hostname = get_hostname(AF_INET, &ip);
|
|
Packit |
71e9d6 |
if (info->hostname == NULL) {
|
|
Packit |
71e9d6 |
if (!beSilent) {
|
|
Packit |
71e9d6 |
sprintf(errBuf,
|
|
Packit |
71e9d6 |
"ipcalc: cannot find hostname for %s",
|
|
Packit |
71e9d6 |
ipStr);
|
|
Packit |
71e9d6 |
herror(errBuf);
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
return -1;
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
return 0;
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
int ipv6_prefix_to_mask(unsigned prefix, struct in6_addr *mask)
|
|
Packit |
71e9d6 |
{
|
|
Packit |
71e9d6 |
struct in6_addr in6;
|
|
Packit |
71e9d6 |
int i, j;
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
if (prefix > 128)
|
|
Packit |
71e9d6 |
return -1;
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
memset(&in6, 0x0, sizeof(in6));
|
|
Packit |
71e9d6 |
for (i = prefix, j = 0; i > 0; i -= 8, j++) {
|
|
Packit |
71e9d6 |
if (i >= 8) {
|
|
Packit |
71e9d6 |
in6.s6_addr[j] = 0xff;
|
|
Packit |
71e9d6 |
} else {
|
|
Packit |
71e9d6 |
in6.s6_addr[j] = (unsigned long)(0xffU << (8 - i));
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
memcpy(mask, &in6, sizeof(*mask));
|
|
Packit |
71e9d6 |
return 0;
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
static char *ipv6_mask_to_str(const struct in6_addr *mask)
|
|
Packit |
71e9d6 |
{
|
|
Packit |
71e9d6 |
char buf[128];
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
if (inet_ntop(AF_INET6, mask, buf, sizeof(buf)) == NULL)
|
|
Packit |
71e9d6 |
return NULL;
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
return safe_strdup(buf);
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
static const char *ipv6_net_to_type(struct in6_addr *net, int prefix)
|
|
Packit |
71e9d6 |
{
|
|
Packit |
71e9d6 |
uint16_t word1 = net->s6_addr[0] << 8 | net->s6_addr[1];
|
|
Packit |
71e9d6 |
uint16_t word2 = net->s6_addr[2] << 8 | net->s6_addr[3];
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
/* based on IANA's iana-ipv6-special-registry and ipv6-address-space
|
|
Packit |
71e9d6 |
* Updated: 2015-05-12
|
|
Packit |
71e9d6 |
*/
|
|
Packit |
71e9d6 |
if (prefix == 128 && memcmp
|
|
Packit |
71e9d6 |
(net->s6_addr,
|
|
Packit |
71e9d6 |
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01",
|
|
Packit |
71e9d6 |
16) == 0)
|
|
Packit |
71e9d6 |
return "Loopback Address";
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
if (prefix == 128 && memcmp
|
|
Packit |
71e9d6 |
(net->s6_addr,
|
|
Packit |
71e9d6 |
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
|
|
Packit |
71e9d6 |
16) == 0)
|
|
Packit |
71e9d6 |
return "Unspecified Address";
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
if (prefix >= 96 && memcmp
|
|
Packit |
71e9d6 |
(net->s6_addr, "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff",
|
|
Packit |
71e9d6 |
12) == 0)
|
|
Packit |
71e9d6 |
return "IPv4-mapped Address";
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
if (prefix >= 96 && memcmp
|
|
Packit |
71e9d6 |
(net->s6_addr, "\x00\x64\xff\x9b\x00\x00\x00\x00\x00\x00\x00\x00",
|
|
Packit |
71e9d6 |
12) == 0)
|
|
Packit |
71e9d6 |
return "IPv4-IPv6 Translat.";
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
if (prefix >= 96 && memcmp
|
|
Packit |
71e9d6 |
(net->s6_addr, "\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
|
|
Packit |
71e9d6 |
12) == 0)
|
|
Packit |
71e9d6 |
return "Discard-Only Address Block";
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
if ((word1 & 0xfffe) == 0x2001 && word2 == 0)
|
|
Packit |
71e9d6 |
return "IETF Protocol Assignments";
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
if ((word1 & 0xe000) == 0x2000) {
|
|
Packit |
71e9d6 |
return "Global Unicast";
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
if (((net->s6_addr[0] & 0xfe) == 0xfc)) {
|
|
Packit |
71e9d6 |
return "Unique Local Unicast";
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
if ((word1 & 0xffc0) == 0xfe80) {
|
|
Packit |
71e9d6 |
return "Link-Scoped Unicast";
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
if ((net->s6_addr[0] & 0xff) == 0xff) {
|
|
Packit |
71e9d6 |
return "Multicast";
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
if ((word1 & 0xfffe) == 0x2002)
|
|
Packit |
71e9d6 |
return "6to4";
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
return "Reserved";
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
static
|
|
Packit |
71e9d6 |
char *expand_ipv6(struct in6_addr *ip6)
|
|
Packit |
71e9d6 |
{
|
|
Packit |
71e9d6 |
char buf[128];
|
|
Packit |
71e9d6 |
char *p;
|
|
Packit |
71e9d6 |
unsigned i;
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
p = buf;
|
|
Packit |
71e9d6 |
for (i = 0; i < 16; i++) {
|
|
Packit |
71e9d6 |
sprintf(p, "%.2x", (unsigned)ip6->s6_addr[i]);
|
|
Packit |
71e9d6 |
p += 2;
|
|
Packit |
71e9d6 |
if (i % 2 != 0 && i != 15) {
|
|
Packit |
71e9d6 |
*p = ':';
|
|
Packit |
71e9d6 |
p++;
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
*p = 0;
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
return safe_strdup(buf);
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
static
|
|
Packit |
71e9d6 |
int get_ipv6_info(const char *ipStr, int prefix, ip_info_st * info,
|
|
Packit |
71e9d6 |
unsigned flags)
|
|
Packit |
71e9d6 |
{
|
|
Packit |
71e9d6 |
struct in6_addr ip6, mask, network;
|
|
Packit |
71e9d6 |
char errBuf[250];
|
|
Packit |
71e9d6 |
unsigned i;
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
memset(info, 0, sizeof(*info));
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
if (inet_pton(AF_INET6, ipStr, &ip6) <= 0) {
|
|
Packit |
71e9d6 |
if (!beSilent)
|
|
Packit |
71e9d6 |
fprintf(stderr, "ipcalc: bad IPv6 address: %s\n",
|
|
Packit |
71e9d6 |
ipStr);
|
|
Packit |
71e9d6 |
return -1;
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
/* expand */
|
|
Packit |
71e9d6 |
info->expanded_ip = expand_ipv6(&ip6;;
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
if (inet_ntop(AF_INET6, &ip6, errBuf, sizeof(errBuf)) == 0) {
|
|
Packit |
71e9d6 |
if (!beSilent)
|
|
Packit |
71e9d6 |
fprintf(stderr,
|
|
Packit |
71e9d6 |
"ipcalc: error calculating the IPv6 network\n");
|
|
Packit |
71e9d6 |
return -1;
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
info->ip = safe_strdup(errBuf);
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
if (prefix > 128) {
|
|
Packit |
71e9d6 |
if (!beSilent)
|
|
Packit |
71e9d6 |
fprintf(stderr, "ipcalc: bad IPv6 prefix: %d\n",
|
|
Packit |
71e9d6 |
prefix);
|
|
Packit |
71e9d6 |
return -1;
|
|
Packit |
71e9d6 |
} else if (prefix < 0) {
|
|
Packit |
71e9d6 |
prefix = 128;
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
info->prefix = prefix;
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
if (ipv6_prefix_to_mask(prefix, &mask) == -1) {
|
|
Packit |
71e9d6 |
if (!beSilent)
|
|
Packit |
71e9d6 |
fprintf(stderr,
|
|
Packit |
71e9d6 |
"ipcalc: error converting IPv6 prefix: %d\n",
|
|
Packit |
71e9d6 |
prefix);
|
|
Packit |
71e9d6 |
return -1;
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
info->netmask = ipv6_mask_to_str(&mask);
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
for (i = 0; i < sizeof(struct in6_addr); i++)
|
|
Packit |
71e9d6 |
network.s6_addr[i] = ip6.s6_addr[i] & mask.s6_addr[i];
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
if (inet_ntop(AF_INET6, &network, errBuf, sizeof(errBuf)) == 0) {
|
|
Packit |
71e9d6 |
if (!beSilent)
|
|
Packit |
71e9d6 |
fprintf(stderr,
|
|
Packit |
71e9d6 |
"ipcalc: error calculating the IPv6 network\n");
|
|
Packit |
71e9d6 |
return -1;
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
info->network = safe_strdup(errBuf);
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
info->expanded_network = expand_ipv6(&network);
|
|
Packit |
71e9d6 |
info->type = ipv6_net_to_type(&network, prefix);
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
info->reverse_dns = calc_reverse_dns6(&network, prefix);
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
if (prefix < 128) {
|
|
Packit |
71e9d6 |
info->hostmin = safe_strdup(errBuf);
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
for (i = 0; i < sizeof(struct in6_addr); i++)
|
|
Packit |
71e9d6 |
network.s6_addr[i] |= ~mask.s6_addr[i];
|
|
Packit |
71e9d6 |
if (inet_ntop(AF_INET6, &network, errBuf, sizeof(errBuf)) == 0) {
|
|
Packit |
71e9d6 |
if (!beSilent)
|
|
Packit |
71e9d6 |
fprintf(stderr,
|
|
Packit |
71e9d6 |
"ipcalc: error calculating the IPv6 network\n");
|
|
Packit |
71e9d6 |
return -1;
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
info->hostmax = safe_strdup(errBuf);
|
|
Packit |
71e9d6 |
} else {
|
|
Packit |
71e9d6 |
info->hostmin = info->network;
|
|
Packit |
71e9d6 |
info->hostmax = info->network;
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
ipv6_prefix_to_hosts(info->hosts, sizeof(info->hosts), prefix);
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
if (flags & FLAG_GET_GEOIP) {
|
|
Packit |
71e9d6 |
geo_ip_lookup(ipStr, &info->geoip_country, &info->geoip_ccode, &info->geoip_city, &info->geoip_coord);
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
if (flags & FLAG_RESOLVE_HOST) {
|
|
Packit |
71e9d6 |
info->hostname = get_hostname(AF_INET6, &ip6;;
|
|
Packit |
71e9d6 |
if (info->hostname == NULL) {
|
|
Packit |
71e9d6 |
if (!beSilent) {
|
|
Packit |
71e9d6 |
sprintf(errBuf,
|
|
Packit |
71e9d6 |
"ipcalc: cannot find hostname for %s",
|
|
Packit |
71e9d6 |
ipStr);
|
|
Packit |
71e9d6 |
herror(errBuf);
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
return -1;
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
return 0;
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
static int randomize(void *ptr, unsigned size)
|
|
Packit |
71e9d6 |
{
|
|
Packit |
71e9d6 |
int fd, ret;
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
fd = open("/dev/urandom", O_RDONLY);
|
|
Packit |
71e9d6 |
if (fd < 0)
|
|
Packit |
71e9d6 |
return -1;
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
ret = read(fd, ptr, size);
|
|
Packit |
71e9d6 |
close(fd);
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
if (ret != size) {
|
|
Packit |
71e9d6 |
return -1;
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
return 0;
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
static char *generate_ip_network(int ipv6, unsigned prefix)
|
|
Packit |
71e9d6 |
{
|
|
Packit |
71e9d6 |
struct timespec ts;
|
|
Packit |
71e9d6 |
char ipbuf[64];
|
|
Packit |
71e9d6 |
char *p = NULL;
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
if (clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ts) < 0)
|
|
Packit |
71e9d6 |
return NULL;
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
if (ipv6) {
|
|
Packit |
71e9d6 |
struct in6_addr net;
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
net.s6_addr[0] = 0xfc;
|
|
Packit |
71e9d6 |
net.s6_addr[0] |= ts.tv_nsec & 1;
|
|
Packit |
71e9d6 |
if (randomize(&net.s6_addr[1], 15) < 0)
|
|
Packit |
71e9d6 |
return NULL;
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
if (inet_ntop(AF_INET6, &net, ipbuf, sizeof(ipbuf)) == NULL)
|
|
Packit |
71e9d6 |
return NULL;
|
|
Packit |
71e9d6 |
} else {
|
|
Packit |
71e9d6 |
struct in_addr net;
|
|
Packit |
71e9d6 |
unsigned c = ts.tv_nsec % 4;
|
|
Packit |
71e9d6 |
uint8_t bytes[4];
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
if (randomize(bytes, 4) < 0)
|
|
Packit |
71e9d6 |
return NULL;
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
if (prefix >= 16 && c < 2) {
|
|
Packit |
71e9d6 |
if (c == 1) {
|
|
Packit |
71e9d6 |
bytes[0] = 192;
|
|
Packit |
71e9d6 |
bytes[1] = 168;
|
|
Packit |
71e9d6 |
} else {
|
|
Packit |
71e9d6 |
bytes[0] = 172;
|
|
Packit |
71e9d6 |
bytes[1] = 16 | ((ts.tv_nsec >> 4) & 0x0f);
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
} else {
|
|
Packit |
71e9d6 |
bytes[0] = 10;
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
memcpy(&net.s_addr, bytes, 4);
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
if (inet_ntop(AF_INET, &net, ipbuf, sizeof(ipbuf)) == NULL)
|
|
Packit |
71e9d6 |
return NULL;
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
if (asprintf(&p, "%s/%u", ipbuf, prefix) == -1)
|
|
Packit |
71e9d6 |
return NULL;
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
return p;
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
static
|
|
Packit |
71e9d6 |
int str_to_prefix(int *ipv6, const char *prefixStr, unsigned fix)
|
|
Packit |
71e9d6 |
{
|
|
Packit |
71e9d6 |
int prefix = -1, r;
|
|
Packit |
71e9d6 |
if (!(*ipv6) && strchr(prefixStr, '.')) { /* prefix is 255.x.x.x */
|
|
Packit |
71e9d6 |
prefix = ipv4_mask_to_int(prefixStr);
|
|
Packit |
71e9d6 |
} else {
|
|
Packit |
71e9d6 |
r = safe_atoi(prefixStr, &prefix);
|
|
Packit |
71e9d6 |
if (r != 0) {
|
|
Packit |
71e9d6 |
return -1;
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
if (fix && (prefix > 32 && !(*ipv6)))
|
|
Packit |
71e9d6 |
*ipv6 = 1;
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
if (prefix < 0 || (((*ipv6) && prefix > 128) || (!(*ipv6) && prefix > 32))) {
|
|
Packit |
71e9d6 |
return -1;
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
return prefix;
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
#define OPT_ALLINFO 1
|
|
Packit |
71e9d6 |
#define OPT_MINADDR 2
|
|
Packit |
71e9d6 |
#define OPT_MAXADDR 3
|
|
Packit |
71e9d6 |
#define OPT_ADDRESSES 4
|
|
Packit |
71e9d6 |
#define OPT_ADDRSPACE 5
|
|
Packit |
71e9d6 |
#define OPT_USAGE 6
|
|
Packit |
71e9d6 |
#define OPT_REVERSE 7
|
|
Packit |
71e9d6 |
#define OPT_CLASS_PREFIX 8
|
|
Packit |
71e9d6 |
#define OPT_NO_DECORATE 9
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
static const struct option long_options[] = {
|
|
Packit |
71e9d6 |
{"check", 0, 0, 'c'},
|
|
Packit |
71e9d6 |
{"random-private", 1, 0, 'r'},
|
|
Packit |
71e9d6 |
{"split", 1, 0, 'S'},
|
|
Packit |
71e9d6 |
{"info", 0, 0, 'i'},
|
|
Packit |
71e9d6 |
{"all-info", 0, 0, OPT_ALLINFO},
|
|
Packit |
71e9d6 |
{"ipv4", 0, 0, '4'},
|
|
Packit |
71e9d6 |
{"ipv6", 0, 0, '6'},
|
|
Packit |
71e9d6 |
{"broadcast", 0, 0, 'b'},
|
|
Packit |
71e9d6 |
{"hostname", 0, 0, 'h'},
|
|
Packit |
71e9d6 |
{"lookup-host", 1, 0, 'o'},
|
|
Packit |
71e9d6 |
{"reverse-dns", 0, 0, OPT_REVERSE},
|
|
Packit |
71e9d6 |
#if defined(USE_GEOIP) || defined(USE_MAXMIND)
|
|
Packit |
71e9d6 |
{"geoinfo", 0, 0, 'g'},
|
|
Packit |
71e9d6 |
#endif
|
|
Packit |
71e9d6 |
{"netmask", 0, 0, 'm'},
|
|
Packit |
71e9d6 |
{"network", 0, 0, 'n'},
|
|
Packit |
71e9d6 |
{"prefix", 0, 0, 'p'},
|
|
Packit |
71e9d6 |
{"class-prefix", 0, 0, OPT_CLASS_PREFIX},
|
|
Packit |
71e9d6 |
{"minaddr", 0, 0, OPT_MINADDR},
|
|
Packit |
71e9d6 |
{"maxaddr", 0, 0, OPT_MAXADDR},
|
|
Packit |
71e9d6 |
{"addresses", 0, 0, OPT_ADDRESSES},
|
|
Packit |
71e9d6 |
{"addrspace", 0, 0, OPT_ADDRSPACE},
|
|
Packit |
71e9d6 |
{"silent", 0, 0, 's'},
|
|
Packit |
71e9d6 |
{"no-decorate", 0, 0, OPT_NO_DECORATE},
|
|
Packit |
71e9d6 |
{"version", 0, 0, 'v'},
|
|
Packit |
71e9d6 |
{"help", 0, 0, '?'},
|
|
Packit |
71e9d6 |
{"usage", 0, 0, OPT_USAGE},
|
|
Packit |
71e9d6 |
{NULL, 0, 0, 0}
|
|
Packit |
71e9d6 |
};
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
static
|
|
Packit |
71e9d6 |
void usage(unsigned verbose)
|
|
Packit |
71e9d6 |
{
|
|
Packit |
71e9d6 |
if (verbose) {
|
|
Packit |
71e9d6 |
fprintf(stderr, "Usage: ipcalc [OPTION...]\n");
|
|
Packit |
71e9d6 |
fprintf(stderr, " -c, --check Validate IP address\n");
|
|
Packit |
71e9d6 |
fprintf(stderr, " -r, --random-private=PREFIX Generate a random private IP network using\n");
|
|
Packit |
71e9d6 |
fprintf(stderr, " -S, --split=PREFIX Split the provided network using the\n");
|
|
Packit |
71e9d6 |
fprintf(stderr, " provided prefix/netmask\n");
|
|
Packit |
71e9d6 |
fprintf(stderr, " -i, --info Print information on the provided IP address\n");
|
|
Packit |
71e9d6 |
fprintf(stderr, " (default)\n");
|
|
Packit |
71e9d6 |
fprintf(stderr, " --all-info Print verbose information on the provided IP\n");
|
|
Packit |
71e9d6 |
fprintf(stderr, " address\n");
|
|
Packit |
71e9d6 |
fprintf(stderr, " --reverse-dns Print network in a the reverse DNS format\n");
|
|
Packit |
71e9d6 |
fprintf(stderr, " -4, --ipv4 Explicitly specify the IPv4 address family\n");
|
|
Packit |
71e9d6 |
fprintf(stderr, " -6, --ipv6 Explicitly specify the IPv6 address family\n");
|
|
Packit |
71e9d6 |
fprintf(stderr, "\n");
|
|
Packit |
71e9d6 |
fprintf(stderr, "Specific info options:\n");
|
|
Packit |
71e9d6 |
fprintf(stderr, " -b, --broadcast Display calculated broadcast address\n");
|
|
Packit |
71e9d6 |
fprintf(stderr, " -m, --netmask Display netmask for IP\n");
|
|
Packit |
71e9d6 |
fprintf(stderr, " -n, --network Display network address\n");
|
|
Packit |
71e9d6 |
fprintf(stderr, " -p, --prefix Display network prefix\n");
|
|
Packit |
71e9d6 |
fprintf(stderr, " --minaddr Display the minimum address in the network\n");
|
|
Packit |
71e9d6 |
fprintf(stderr, " --maxaddr Display the maximum address in the network\n");
|
|
Packit |
71e9d6 |
fprintf(stderr, " --addresses Display the maximum number of addresses in\n");
|
|
Packit |
71e9d6 |
fprintf(stderr, " the network\n");
|
|
Packit |
71e9d6 |
fprintf(stderr, " --addrspace Display the address space the network\n");
|
|
Packit |
71e9d6 |
fprintf(stderr, " resides on\n");
|
|
Packit |
71e9d6 |
fprintf(stderr, " -h, --hostname Show hostname determined via DNS\n");
|
|
Packit |
71e9d6 |
fprintf(stderr, " -o, --lookup-host=STRING Show IP as determined via DNS\n");
|
|
Packit |
71e9d6 |
#if defined(USE_GEOIP) || defined(USE_MAXMIND)
|
|
Packit |
71e9d6 |
fprintf(stderr, " -g, --geoinfo Show Geographic information about the\n");
|
|
Packit |
71e9d6 |
fprintf(stderr, " provided IP\n");
|
|
Packit |
71e9d6 |
#endif
|
|
Packit |
71e9d6 |
fprintf(stderr, "\n");
|
|
Packit |
71e9d6 |
fprintf(stderr, "Other options:\n");
|
|
Packit |
71e9d6 |
fprintf(stderr, " --class-prefix When specified the default prefix will be determined\n");
|
|
Packit |
71e9d6 |
fprintf(stderr, " by the IPv4 address class\n");
|
|
Packit |
71e9d6 |
fprintf(stderr, " --no-decorate Print only the requested information\n");
|
|
Packit |
71e9d6 |
fprintf(stderr, " -s, --silent Don't ever display error messages\n");
|
|
Packit |
71e9d6 |
fprintf(stderr, " -v, --version Display program version\n");
|
|
Packit |
71e9d6 |
fprintf(stderr, " -?, --help Show this help message\n");
|
|
Packit |
71e9d6 |
fprintf(stderr, " --usage Display brief usage message\n");
|
|
Packit |
71e9d6 |
} else {
|
|
Packit |
71e9d6 |
fprintf(stderr, "Usage: ipcalc [-46sv?] [-c|--check] [-r|--random-private=STRING] [-i|--info]\n");
|
|
Packit |
71e9d6 |
fprintf(stderr, " [--all-info] [-4|--ipv4] [-6|--ipv6] [-b|--broadcast]\n");
|
|
Packit |
71e9d6 |
fprintf(stderr, " [-h|--hostname] [-o|--lookup-host=STRING] [-g|--geoinfo]\n");
|
|
Packit |
71e9d6 |
fprintf(stderr, " [-m|--netmask] [-n|--network] [-p|--prefix] [--minaddr] [--maxaddr]\n");
|
|
Packit |
71e9d6 |
fprintf(stderr, " [--addresses] [--addrspace] [-s|--silent] [-v|--version]\n");
|
|
Packit |
71e9d6 |
fprintf(stderr, " [--reverse-dns] [--class-prefix]\n");
|
|
Packit |
71e9d6 |
fprintf(stderr, " [-?|--help] [--usage]\n");
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
void
|
|
Packit |
71e9d6 |
__attribute__ ((format(printf, 3, 4)))
|
|
Packit |
71e9d6 |
color_printf(const char *color, const char *title, const char *fmt, ...)
|
|
Packit |
71e9d6 |
{
|
|
Packit |
71e9d6 |
va_list args;
|
|
Packit |
71e9d6 |
int ret;
|
|
Packit |
71e9d6 |
char *str = NULL;
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
va_start(args, fmt);
|
|
Packit |
71e9d6 |
ret = vasprintf(&str, fmt, args);
|
|
Packit |
71e9d6 |
va_end(args);
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
if (ret < 0)
|
|
Packit |
71e9d6 |
return;
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
fputs(title, stdout);
|
|
Packit |
71e9d6 |
if (colors)
|
|
Packit |
71e9d6 |
fputs(color, stdout);
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
fputs(str, stdout);
|
|
Packit |
71e9d6 |
if (colors)
|
|
Packit |
71e9d6 |
fputs(KRESET, stdout);
|
|
Packit |
71e9d6 |
free(str);
|
|
Packit |
71e9d6 |
return;
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
/*!
|
|
Packit |
71e9d6 |
\fn main(int argc, const char **argv)
|
|
Packit |
71e9d6 |
\brief wrapper program for ipcalc functions.
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
This is a wrapper program for the functions that the ipcalc library provides.
|
|
Packit |
71e9d6 |
It can be used from shell scripts or directly from the command line.
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
For more information, please see the ipcalc(1) man page.
|
|
Packit |
71e9d6 |
*/
|
|
Packit |
71e9d6 |
int main(int argc, char **argv)
|
|
Packit |
71e9d6 |
{
|
|
Packit |
71e9d6 |
int doCheck = 0;
|
|
Packit |
71e9d6 |
int familyIPv4 = 0, familyIPv6 = 0;
|
|
Packit |
71e9d6 |
char *randomStr = NULL;
|
|
Packit |
71e9d6 |
char *hostname = NULL;
|
|
Packit |
71e9d6 |
char *splitStr = NULL;
|
|
Packit |
71e9d6 |
int doVersion = 0;
|
|
Packit |
71e9d6 |
char *ipStr = NULL, *prefixStr = NULL, *netmaskStr = NULL, *chptr = NULL;
|
|
Packit |
71e9d6 |
int prefix = -1, splitPrefix = -1;
|
|
Packit |
71e9d6 |
ip_info_st info;
|
|
Packit |
71e9d6 |
unsigned flags = 0;
|
|
Packit |
71e9d6 |
int r = 0;
|
|
Packit |
71e9d6 |
int c;
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
while (1) {
|
|
Packit |
71e9d6 |
c = getopt_long(argc, argv, "S:cr:i46bho:gmnpsv", long_options, NULL);
|
|
Packit |
71e9d6 |
if (c == -1)
|
|
Packit |
71e9d6 |
break;
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
switch(c) {
|
|
Packit |
71e9d6 |
case 'c':
|
|
Packit |
71e9d6 |
flags |= FLAG_CHECK_ADDRESS;
|
|
Packit |
71e9d6 |
break;
|
|
Packit |
71e9d6 |
case 'S':
|
|
Packit |
71e9d6 |
flags |= FLAG_SPLIT;
|
|
Packit |
71e9d6 |
splitStr = safe_strdup(optarg);
|
|
Packit |
71e9d6 |
if (splitStr == NULL) exit(1);
|
|
Packit |
71e9d6 |
break;
|
|
Packit |
71e9d6 |
case 'r':
|
|
Packit |
71e9d6 |
randomStr = safe_strdup(optarg);
|
|
Packit |
71e9d6 |
if (randomStr == NULL) exit(1);
|
|
Packit |
71e9d6 |
break;
|
|
Packit |
71e9d6 |
case 'i':
|
|
Packit |
71e9d6 |
flags |= FLAG_SHOW_INFO;
|
|
Packit |
71e9d6 |
break;
|
|
Packit |
71e9d6 |
case OPT_ALLINFO:
|
|
Packit |
71e9d6 |
flags |= FLAG_SHOW_ALL_INFO;
|
|
Packit |
71e9d6 |
break;
|
|
Packit |
71e9d6 |
case OPT_CLASS_PREFIX:
|
|
Packit |
71e9d6 |
flags |= FLAG_ASSUME_CLASS_PREFIX;
|
|
Packit |
71e9d6 |
break;
|
|
Packit |
71e9d6 |
case OPT_REVERSE:
|
|
Packit |
71e9d6 |
flags |= FLAG_SHOW_REVERSE;
|
|
Packit |
71e9d6 |
break;
|
|
Packit |
71e9d6 |
case '4':
|
|
Packit |
71e9d6 |
familyIPv4 = 1;
|
|
Packit |
71e9d6 |
break;
|
|
Packit |
71e9d6 |
case '6':
|
|
Packit |
71e9d6 |
familyIPv6 = 1;
|
|
Packit |
71e9d6 |
break;
|
|
Packit |
71e9d6 |
case 'b':
|
|
Packit |
71e9d6 |
flags |= FLAG_SHOW_BROADCAST;
|
|
Packit |
71e9d6 |
break;
|
|
Packit |
71e9d6 |
case 'h':
|
|
Packit |
71e9d6 |
flags |= FLAG_RESOLVE_HOST;
|
|
Packit |
71e9d6 |
break;
|
|
Packit |
71e9d6 |
case 'o':
|
|
Packit |
71e9d6 |
hostname = safe_strdup(optarg);
|
|
Packit |
71e9d6 |
if (hostname == NULL) exit(1);
|
|
Packit |
71e9d6 |
break;
|
|
Packit |
71e9d6 |
case 'g':
|
|
Packit |
71e9d6 |
flags |= FLAG_SHOW_GEOIP;
|
|
Packit |
71e9d6 |
break;
|
|
Packit |
71e9d6 |
case 'm':
|
|
Packit |
71e9d6 |
flags |= FLAG_SHOW_NETMASK;
|
|
Packit |
71e9d6 |
break;
|
|
Packit |
71e9d6 |
case 'n':
|
|
Packit |
71e9d6 |
flags |= FLAG_SHOW_NETWORK;
|
|
Packit |
71e9d6 |
break;
|
|
Packit |
71e9d6 |
case 'p':
|
|
Packit |
71e9d6 |
flags |= FLAG_SHOW_PREFIX;
|
|
Packit |
71e9d6 |
break;
|
|
Packit |
71e9d6 |
case OPT_MINADDR:
|
|
Packit |
71e9d6 |
flags |= FLAG_SHOW_MINADDR;
|
|
Packit |
71e9d6 |
break;
|
|
Packit |
71e9d6 |
case OPT_MAXADDR:
|
|
Packit |
71e9d6 |
flags |= FLAG_SHOW_MAXADDR;
|
|
Packit |
71e9d6 |
break;
|
|
Packit |
71e9d6 |
case OPT_ADDRESSES:
|
|
Packit |
71e9d6 |
flags |= FLAG_SHOW_ADDRESSES;
|
|
Packit |
71e9d6 |
break;
|
|
Packit |
71e9d6 |
case OPT_ADDRSPACE:
|
|
Packit |
71e9d6 |
flags |= FLAG_SHOW_ADDRSPACE;
|
|
Packit |
71e9d6 |
break;
|
|
Packit |
71e9d6 |
case OPT_NO_DECORATE:
|
|
Packit |
71e9d6 |
flags |= FLAG_NO_DECORATE;
|
|
Packit |
71e9d6 |
break;
|
|
Packit |
71e9d6 |
case 's':
|
|
Packit |
71e9d6 |
beSilent = 1;
|
|
Packit |
71e9d6 |
break;
|
|
Packit |
71e9d6 |
case 'v':
|
|
Packit |
71e9d6 |
doVersion = 1;
|
|
Packit |
71e9d6 |
break;
|
|
Packit |
71e9d6 |
case OPT_USAGE:
|
|
Packit |
71e9d6 |
usage(0);
|
|
Packit |
71e9d6 |
exit(0);
|
|
Packit |
71e9d6 |
case '?':
|
|
Packit |
71e9d6 |
usage(1);
|
|
Packit |
71e9d6 |
exit(0);
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
if (optind < argc) {
|
|
Packit |
71e9d6 |
ipStr = argv[optind++];
|
|
Packit |
71e9d6 |
if (optind < argc)
|
|
Packit |
71e9d6 |
chptr = argv[optind++];
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
if (doVersion) {
|
|
Packit |
71e9d6 |
printf("ipcalc %s\n", VERSION);
|
|
Packit |
71e9d6 |
return 0;
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
if (familyIPv6 && familyIPv4) {
|
|
Packit |
71e9d6 |
if (!beSilent)
|
|
Packit |
71e9d6 |
fprintf(stderr,
|
|
Packit |
71e9d6 |
"ipcalc: you cannot specify both IPv4 and IPv6\n");
|
|
Packit |
71e9d6 |
return 1;
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
if (hostname)
|
|
Packit |
71e9d6 |
flags |= FLAG_RESOLVE_IP;
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
if (geo_setup() == 0 &&
|
|
Packit |
71e9d6 |
((flags & FLAG_SHOW_ALL_INFO) == FLAG_SHOW_ALL_INFO))
|
|
Packit |
71e9d6 |
flags |= FLAG_GET_GEOIP;
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
if ((hostname && randomStr) || (hostname && splitStr) || (randomStr && splitStr)) {
|
|
Packit |
71e9d6 |
if (!beSilent)
|
|
Packit |
71e9d6 |
fprintf(stderr,
|
|
Packit |
71e9d6 |
"ipcalc: you cannot mix these options\n");
|
|
Packit |
71e9d6 |
return 1;
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
if (hostname == NULL && randomStr == NULL && !ipStr) {
|
|
Packit |
71e9d6 |
if (!beSilent) {
|
|
Packit |
71e9d6 |
fprintf(stderr,
|
|
Packit |
71e9d6 |
"ipcalc: ip address expected\n");
|
|
Packit |
71e9d6 |
usage(1);
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
return 1;
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
/* resolve IP address if a hostname was given */
|
|
Packit |
71e9d6 |
if (hostname) {
|
|
Packit |
71e9d6 |
int family = AF_UNSPEC;
|
|
Packit |
71e9d6 |
if (familyIPv6)
|
|
Packit |
71e9d6 |
family = AF_INET6;
|
|
Packit |
71e9d6 |
else if (familyIPv4)
|
|
Packit |
71e9d6 |
family = AF_INET;
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
ipStr = get_ip_address(family, hostname);
|
|
Packit |
71e9d6 |
if (ipStr == NULL) {
|
|
Packit |
71e9d6 |
if (!beSilent)
|
|
Packit |
71e9d6 |
fprintf(stderr,
|
|
Packit |
71e9d6 |
"ipcalc: could not resolve %s\n", hostname);
|
|
Packit |
71e9d6 |
return 1;
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
} else if (randomStr) { /* generate a random private network if asked */
|
|
Packit |
71e9d6 |
prefix = str_to_prefix(&familyIPv6, randomStr, 1);
|
|
Packit |
71e9d6 |
if (prefix < 0) {
|
|
Packit |
71e9d6 |
if (!beSilent)
|
|
Packit |
71e9d6 |
fprintf(stderr,
|
|
Packit |
71e9d6 |
"ipcalc: bad %s prefix: %s\n", familyIPv6?"IPv6":"IPv4", randomStr);
|
|
Packit |
71e9d6 |
return 1;
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
ipStr = generate_ip_network(familyIPv6, prefix);
|
|
Packit |
71e9d6 |
if (ipStr == NULL) {
|
|
Packit |
71e9d6 |
if (!beSilent)
|
|
Packit |
71e9d6 |
fprintf(stderr,
|
|
Packit |
71e9d6 |
"ipcalc: cannot generate network with prefix: %u\n",
|
|
Packit |
71e9d6 |
prefix);
|
|
Packit |
71e9d6 |
return 1;
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
} else if (splitStr) {
|
|
Packit |
71e9d6 |
splitPrefix = str_to_prefix(&familyIPv6, splitStr, 1);
|
|
Packit |
71e9d6 |
if (splitPrefix < 0) {
|
|
Packit |
71e9d6 |
if (!beSilent)
|
|
Packit |
71e9d6 |
fprintf(stderr,
|
|
Packit |
71e9d6 |
"ipcalc: bad %s prefix: %s\n", familyIPv6?"IPv6":"IPv4", splitStr);
|
|
Packit |
71e9d6 |
return 1;
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
/* if there is a : in the address, it is an IPv6 address.
|
|
Packit |
71e9d6 |
* Note that we allow -4, and -6 to be given explicitly, so
|
|
Packit |
71e9d6 |
* that the tool can be used to check for a valid IPv4 or IPv6
|
|
Packit |
71e9d6 |
* address.
|
|
Packit |
71e9d6 |
*/
|
|
Packit |
71e9d6 |
if (familyIPv4 == 0 && strchr(ipStr, ':') != NULL) {
|
|
Packit |
71e9d6 |
familyIPv6 = 1;
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
if (chptr) {
|
|
Packit |
71e9d6 |
if (familyIPv6 == 0) {
|
|
Packit |
71e9d6 |
prefixStr = chptr;
|
|
Packit |
71e9d6 |
} else {
|
|
Packit |
71e9d6 |
if (!beSilent) {
|
|
Packit |
71e9d6 |
fprintf(stderr, "ipcalc: unexpected argument: %s\n",
|
|
Packit |
71e9d6 |
chptr);
|
|
Packit |
71e9d6 |
usage(1);
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
return 1;
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
if (prefixStr == NULL && strchr(ipStr, '/') != NULL) {
|
|
Packit |
71e9d6 |
prefixStr = strchr(ipStr, '/');
|
|
Packit |
71e9d6 |
*prefixStr = '\0'; /* fix up ipStr */
|
|
Packit |
71e9d6 |
prefixStr++;
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
if (prefixStr != NULL) {
|
|
Packit |
71e9d6 |
prefix = str_to_prefix(&familyIPv6, prefixStr, 0);
|
|
Packit |
71e9d6 |
if (prefix < 0) {
|
|
Packit |
71e9d6 |
if (!beSilent)
|
|
Packit |
71e9d6 |
fprintf(stderr,
|
|
Packit |
71e9d6 |
"ipcalc: bad %s prefix: %s\n", familyIPv6?"IPv6":"IPv4", prefixStr);
|
|
Packit |
71e9d6 |
return 1;
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
if (familyIPv6) {
|
|
Packit |
71e9d6 |
r = get_ipv6_info(ipStr, prefix, &info, flags);
|
|
Packit |
71e9d6 |
} else {
|
|
Packit |
71e9d6 |
if ((flags & FLAG_SHOW_BROADCAST) || (flags & FLAG_SHOW_NETWORK) || (flags & FLAG_SHOW_PREFIX)) {
|
|
Packit |
71e9d6 |
if (netmaskStr && prefix >= 0) {
|
|
Packit |
71e9d6 |
if (!beSilent) {
|
|
Packit |
71e9d6 |
fprintf(stderr,
|
|
Packit |
71e9d6 |
"ipcalc: both netmask and prefix specified\n");
|
|
Packit |
71e9d6 |
usage(1);
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
return 1;
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
if (prefix == -1 && netmaskStr) {
|
|
Packit |
71e9d6 |
prefix = ipv4_mask_to_int(netmaskStr);
|
|
Packit |
71e9d6 |
if (prefix < 0) {
|
|
Packit |
71e9d6 |
if (!beSilent)
|
|
Packit |
71e9d6 |
fprintf(stderr,
|
|
Packit |
71e9d6 |
"ipcalc: bad IPv4 prefix: %s\n", prefixStr);
|
|
Packit |
71e9d6 |
return 1;
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
r = get_ipv4_info(ipStr, prefix, &info, flags);
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
if (r < 0) {
|
|
Packit |
71e9d6 |
return 1;
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
if (doCheck)
|
|
Packit |
71e9d6 |
return 0;
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
/* if no option is given, print information on IP */
|
|
Packit |
71e9d6 |
if (!(flags & FLAGS_TO_IGNORE_MASK)) {
|
|
Packit |
71e9d6 |
flags |= FLAG_SHOW_INFO;
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
if (isatty(STDOUT_FILENO) != 0)
|
|
Packit |
71e9d6 |
colors = 1;
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
/* we know what we want to display now, so display it. */
|
|
Packit |
71e9d6 |
if (flags & FLAG_SHOW_INFO && !(flags & FLAG_SPLIT)) {
|
|
Packit |
71e9d6 |
unsigned single_host = 0;
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
if ((familyIPv6 && info.prefix == 128) ||
|
|
Packit |
71e9d6 |
(!familyIPv6 && info.prefix == 32)) {
|
|
Packit |
71e9d6 |
single_host = 1;
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
if ((!randomStr || single_host) &&
|
|
Packit |
71e9d6 |
(single_host || strcmp(info.network, info.ip) != 0)) {
|
|
Packit |
71e9d6 |
if (info.expanded_ip)
|
|
Packit |
71e9d6 |
default_printf("Full Address:\t", "%s\n", info.expanded_ip);
|
|
Packit |
71e9d6 |
default_printf("Address:\t", "%s\n", info.ip);
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
if (!single_host) {
|
|
Packit |
71e9d6 |
if (info.expanded_network) {
|
|
Packit |
71e9d6 |
default_printf("Full Network:\t", "%s/%u\n", info.expanded_network, info.prefix);
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
default_printf("Network:\t", "%s/%u\n", info.network, info.prefix);
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
default_printf("Netmask:\t", "%s = %u\n", info.netmask, info.prefix);
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
if (info.broadcast)
|
|
Packit |
71e9d6 |
default_printf("Broadcast:\t", "%s\n", info.broadcast);
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
if (((flags & FLAG_SHOW_ALL_INFO) == FLAG_SHOW_ALL_INFO) && info.reverse_dns)
|
|
Packit |
71e9d6 |
default_printf("Reverse DNS:\t", "%s\n", info.reverse_dns);
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
if (!single_host) {
|
|
Packit |
71e9d6 |
printf("\n");
|
|
Packit |
71e9d6 |
if (info.type)
|
|
Packit |
71e9d6 |
dist_printf("Address space:\t", "%s\n", info.type);
|
|
Packit |
71e9d6 |
if (info.class)
|
|
Packit |
71e9d6 |
dist_printf("Address class:\t", "%s\n", info.class);
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
if (info.hostmin)
|
|
Packit |
71e9d6 |
default_printf("HostMin:\t", "%s\n", info.hostmin);
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
if (info.hostmax)
|
|
Packit |
71e9d6 |
default_printf("HostMax:\t", "%s\n", info.hostmax);
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
if (familyIPv6 && info.prefix < 112)
|
|
Packit |
71e9d6 |
default_printf("Hosts/Net:\t", "2^(%u) = %s\n", 128-info.prefix, info.hosts);
|
|
Packit |
71e9d6 |
else
|
|
Packit |
71e9d6 |
default_printf("Hosts/Net:\t", "%s\n", info.hosts);
|
|
Packit |
71e9d6 |
} else {
|
|
Packit |
71e9d6 |
if (info.type)
|
|
Packit |
71e9d6 |
dist_printf("Address space:\t", "%s\n", info.type);
|
|
Packit |
71e9d6 |
if (info.class)
|
|
Packit |
71e9d6 |
dist_printf("Address class:\t", "%s\n", info.class);
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
if (info.geoip_country || info.geoip_city || info.geoip_coord) {
|
|
Packit |
71e9d6 |
printf("\n");
|
|
Packit |
71e9d6 |
if (info.geoip_ccode)
|
|
Packit |
71e9d6 |
dist_printf("Country code:\t", "%s\n", info.geoip_ccode);
|
|
Packit |
71e9d6 |
if (info.geoip_country)
|
|
Packit |
71e9d6 |
dist_printf("Country:\t", "%s\n", info.geoip_country);
|
|
Packit |
71e9d6 |
if (info.geoip_city)
|
|
Packit |
71e9d6 |
dist_printf("City:\t\t", "%s\n", info.geoip_city);
|
|
Packit |
71e9d6 |
if (info.geoip_coord)
|
|
Packit |
71e9d6 |
dist_printf("Coordinates:\t", "%s\n", info.geoip_coord);
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
} else if (!(flags & FLAG_SHOW_INFO)) {
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
if (flags & FLAG_SHOW_NETMASK) {
|
|
Packit |
71e9d6 |
printf("NETMASK=%s\n", info.netmask);
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
if (flags & FLAG_SHOW_PREFIX) {
|
|
Packit |
71e9d6 |
printf("PREFIX=%u\n", info.prefix);
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
if ((flags & FLAG_SHOW_BROADCAST) && !familyIPv6) {
|
|
Packit |
71e9d6 |
printf("BROADCAST=%s\n", info.broadcast);
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
if (flags & FLAG_SHOW_NETWORK) {
|
|
Packit |
71e9d6 |
printf("NETWORK=%s\n", info.network);
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
if (flags & FLAG_SHOW_REVERSE) {
|
|
Packit |
71e9d6 |
printf("REVERSEDNS=%s\n", info.reverse_dns);
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
if ((flags & FLAG_SHOW_MINADDR) && info.hostmin) {
|
|
Packit |
71e9d6 |
printf("MINADDR=%s\n", info.hostmin);
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
if ((flags & FLAG_SHOW_MAXADDR) && info.hostmax) {
|
|
Packit |
71e9d6 |
printf("MAXADDR=%s\n", info.hostmax);
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
if ((flags & FLAG_SHOW_ADDRSPACE) && info.type) {
|
|
Packit |
71e9d6 |
if (strchr(info.type, ' ') != NULL)
|
|
Packit |
71e9d6 |
printf("ADDRSPACE=\"%s\"\n", info.type);
|
|
Packit |
71e9d6 |
else
|
|
Packit |
71e9d6 |
printf("ADDRSPACE=%s\n", info.type);
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
if ((flags & FLAG_SHOW_ADDRESSES) && info.hosts[0]) {
|
|
Packit |
71e9d6 |
if (strchr(info.hosts, ' ') != NULL)
|
|
Packit |
71e9d6 |
printf("ADDRESSES=\"%s\"\n", info.hosts);
|
|
Packit |
71e9d6 |
else
|
|
Packit |
71e9d6 |
printf("ADDRESSES=%s\n", info.hosts);
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
if ((flags & FLAG_RESOLVE_HOST) && info.hostname) {
|
|
Packit |
71e9d6 |
printf("HOSTNAME=%s\n", info.hostname);
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
if (flags & FLAG_RESOLVE_IP) {
|
|
Packit |
71e9d6 |
printf("ADDRESS=%s\n", ipStr);
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
if ((flags & FLAG_SHOW_GEOIP) == FLAG_SHOW_GEOIP) {
|
|
Packit |
71e9d6 |
if (info.geoip_ccode)
|
|
Packit |
71e9d6 |
printf("COUNTRYCODE=%s\n", info.geoip_ccode);
|
|
Packit |
71e9d6 |
if (info.geoip_country) {
|
|
Packit |
71e9d6 |
if (strchr(info.geoip_country, ' ') != NULL)
|
|
Packit |
71e9d6 |
printf("COUNTRY=\"%s\"\n", info.geoip_country);
|
|
Packit |
71e9d6 |
else
|
|
Packit |
71e9d6 |
printf("COUNTRY=%s\n", info.geoip_country);
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
if (info.geoip_city) {
|
|
Packit |
71e9d6 |
if (strchr(info.geoip_city, ' ') != NULL) {
|
|
Packit |
71e9d6 |
printf("CITY=\"%s\"\n", info.geoip_city);
|
|
Packit |
71e9d6 |
} else {
|
|
Packit |
71e9d6 |
printf("CITY=%s\n", info.geoip_city);
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
if (info.geoip_coord)
|
|
Packit |
71e9d6 |
printf("COORDINATES=\"%s\"\n", info.geoip_coord);
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
if (flags & FLAG_SPLIT) {
|
|
Packit |
71e9d6 |
if (familyIPv6) {
|
|
Packit |
71e9d6 |
show_split_networks_v6(splitPrefix, &info, flags);
|
|
Packit |
71e9d6 |
} else {
|
|
Packit |
71e9d6 |
show_split_networks_v4(splitPrefix, &info, flags);
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
}
|
|
Packit |
71e9d6 |
|
|
Packit |
71e9d6 |
return 0;
|
|
Packit |
71e9d6 |
}
|