Blame ipcalc.c

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
}