]> git.ipfire.org Git - ipfire-3.x.git/commitdiff
initscripts: Add ipcalc binary.
authorMichael Tremer <michael.tremer@ipfire.org>
Sat, 28 May 2011 23:19:37 +0000 (01:19 +0200)
committerMichael Tremer <michael.tremer@ipfire.org>
Sat, 28 May 2011 23:19:37 +0000 (01:19 +0200)
pkgs/initscripts/initscripts.nm
pkgs/initscripts/src/Makefile
pkgs/initscripts/src/ipcalc-tests [new file with mode: 0755]
pkgs/initscripts/src/ipcalc.1 [new file with mode: 0644]
pkgs/initscripts/src/ipcalc.c [new file with mode: 0644]

index de10dec612aabb64653b97e05eea14be0b56321e..6fef2055a3b4f32d567e266c68666e6161e76287 100644 (file)
@@ -27,7 +27,7 @@ include $(PKGROOT)/Include
 PKG_NAME       = initscripts
 PKG_EPOCH      = 1
 PKG_VER        = 2.99
-PKG_REL        = 3
+PKG_REL        = 4
 
 PKG_MAINTAINER =
 PKG_GROUPS     = Base System/Boot
@@ -35,7 +35,7 @@ PKG_URL        =
 PKG_LICENSE    = GPLv3+
 PKG_SUMMARY    = The set of scripts that initalize the system.
 
-PKG_BUILD_DEPS+= glib2-devel
+PKG_BUILD_DEPS+= glib2-devel popt-devel
 PKG_DEPS      += bash coreutils e2fsprogs grep iproute2 module-init-tools \
        procps sed system-release udev util-linux
 
@@ -54,6 +54,10 @@ define STAGE_BUILD
        cd $(DIR_APP)/src && make $(PARALLELISMFLAGS)
 endef
 
+define STAGE_TEST
+       cd $(DIR_APP)/src && make test
+endef
+
 define STAGE_INSTALL
        cd $(DIR_APP)/src && make install clean DESTDIR=$(BUILDROOT)
 
index a93390de2ba2630949f2c20b846dd7036a2d8164..bb486faa33de9cd038fdbe3364bc887718061bca 100644 (file)
@@ -1,5 +1,5 @@
 
-PROGS = console_check console_init securetty
+PROGS = console_check console_init ipcalc securetty
 
 CC = gcc
 CFLAGS += -D_GNU_SOURCE $(shell pkg-config --cflags glib-2.0)
@@ -9,17 +9,29 @@ all: $(PROGS)
 clean:
        rm -vf $(PROGS) *.o
 
-install:
-       -mkdir -pv $(DESTDIR)/lib/udev $(DESTDIR)/sbin
+test: ipcalc
+       ./ipcalc-tests
+
+install: $(PROGS)
+       # Install binaries
+       -mkdir -pv $(DESTDIR)/lib/udev $(DESTDIR)/{,s}bin
        install -v -m 755 console_check $(DESTDIR)/lib/udev/
        install -v -m 755 console_init $(DESTDIR)/lib/udev/
+       install -v -m 755 ipcalc $(DESTDIR)/bin
        install -v -m 755 securetty $(DESTDIR)/sbin
 
+       # Install man pages
+       -mkdir -pv $(DESTDIR)/usr/share/man/man1
+       install -v -m 644 ipcalc.1 $(DESTDIR)/usr/share/man/man1
+
 console_check: console_check.o
        $(CC) $(LDFLAGS) -o $@ $<
 
 console_init: console_init.o shvar.o
        $(CC) $(LDFLAGS) $(shell pkg-config --libs glib-2.0) -o $@ $?
 
+ipcalc: ipcalc.o
+       $(CC) $(LDFLAGS) -o $@ $< -lpopt
+
 securetty: securetty.o
        $(CC) $(LDFLAGS) -o $@ $<
diff --git a/pkgs/initscripts/src/ipcalc-tests b/pkgs/initscripts/src/ipcalc-tests
new file mode 100755 (executable)
index 0000000..ebb777d
--- /dev/null
@@ -0,0 +1,98 @@
+#!/bin/bash
+#
+# Run some simple ipcalc tests.
+#
+# Adapted from: Matej Susta <msusta@redhat.com>
+#
+#   Copyright (c) 2009 Red Hat, Inc. All rights reserved.
+#
+#   This copyrighted material is made available to anyone wishing
+#   to use, modify, copy, or redistribute it subject to the terms
+#   and conditions of the GNU General Public License version 2.
+#
+#   This program is distributed in the hope that it will be
+#   useful, but WITHOUT ANY WARRANTY; without even the implied
+#   warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+#   PURPOSE. See the GNU General Public License for more details.
+#
+#   You should have received a copy of the GNU General Public
+#   License along with this program; if not, write to the Free
+#   Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+#   Boston, MA 02110-1301, USA.
+
+bin=./ipcalc
+exitcode=0
+
+ok() {
+       echo "ok."
+}
+
+fail() {
+       echo "FAILED!"
+       exitcode=$((exitcode+1))
+       echo -e "Output was:\n$output"
+}
+
+TestSuccess() {
+       echo -n "Checking $@... "
+       output=$(sh -c "$1" 2>&1)
+       rc=$?
+       [ $rc -eq 0 ] && ok || fail $output
+}
+
+TestFailure() {
+       echo -n "Checking $@... "
+       output=$(sh -c "$1" 2>&1)
+       rc=$?
+       [ $rc -eq 0 ] && fail $output || ok 
+}
+
+TestOutput() {
+       echo -n "Checking $1... "
+       output=$(sh -c "$1" 2>&1)
+       rc=$?
+       [ "$output" = "$2" ] && ok || fail $output
+}
+
+echo -n "Checking for ipcalc binary... "
+[ -x $bin ] || { fail ; exit $exitcode ; }
+
+TestSuccess "$bin --help"
+
+TestSuccess "$bin -c 127.0.0.1"
+TestSuccess "$bin -c -6 ::1"
+TestSuccess "$bin -c ::1"
+
+TestSuccess "$bin -c 192.168.1.1"
+TestSuccess "$bin -c -6 2a01:198:200:300::2"
+TestSuccess "$bin -c -6 2a01:198:200:300:0000:0000:0000:2"
+TestSuccess "$bin -c -6 2a01:0198:0200:0300:0000:0000:0000:0002"
+TestSuccess "$bin -c -6 ::1/128"
+TestSuccess "$bin -c -6 fec0::1:0:0:c0a8:8002/64"
+
+TestFailure "$bin -c -6 gggg::"
+TestFailure "$bin -b -6 ::1/128"
+TestFailure "$bin -c -4 -6 2a01:198:200:300:0000:0000:0000:2"
+TestFailure "$bin -c -4 -6 127.0.0.1"
+TestFailure "$bin -c -6 127.0.0.1"
+TestFailure "$bin -c ::1/999"
+TestFailure "$bin -m 192.168.1.1/-1"
+TestFailure "$bin -m 192.168.1.1/64"
+TestFailure "$bin -m 192.168.1.1/99999"
+
+TestOutput "$bin -b 192.168.1.1/24" "BROADCAST=192.168.1.255"
+TestOutput "$bin -b 192.168.1.1 255.255.255.0" "BROADCAST=192.168.1.255"
+TestOutput "$bin -m 192.168.1.1/24" "NETMASK=255.255.255.0"
+TestOutput "$bin -p 192.168.1.1 255.255.255.0" "PREFIX=24"
+TestOutput "$bin -p 192.168.1.1 255.255.255.255" "PREFIX=32"
+TestOutput "$bin -p 192.168.1.1 0.0.0.0" "PREFIX=0"
+TestOutput "$bin -p 172.16.59.222 255.255.252.0" "PREFIX=22"
+TestOutput "$bin -m 172.16.59.222/22" "NETMASK=255.255.252.0"
+TestOutput "$bin -m 192.168.1.1" "NETMASK=255.255.255.0"
+TestOutput "$bin -m 10.1.2.3" "NETMASK=255.0.0.0"
+TestOutput "$bin -m 129.22.4.3" "NETMASK=255.255.0.0"
+TestOutput "$bin -n 192.168.1.1/32" "NETWORK=192.168.1.1"
+TestOutput "$bin -n 192.168.1.1/0" "NETWORK=0.0.0.0"
+
+echo "$exitcode test(s) failed."
+exit $exitcode
diff --git a/pkgs/initscripts/src/ipcalc.1 b/pkgs/initscripts/src/ipcalc.1
new file mode 100644 (file)
index 0000000..30e0b20
--- /dev/null
@@ -0,0 +1,73 @@
+.TH IPCALC 1 "April 30 2001" "Red Hat, Inc." \" -*- nroff -*-
+.SH NAME
+ipcalc \- perform simple manipulation of IP addresses
+.SH SYNOPSIS
+.B ipcalc
+[\fIOPTION\fR]... <\fBIP address\fR>[\fI/prefix\fR] [\fInetmask\fR]
+
+.SH DESCRIPTION
+\fBipcalc\fR provides a simple way to calculate IP information for a host.
+The various options specify what information \fBipcalc\fR should display
+on standard out. Multiple options may be specified.  An IP address to
+operate on must always be specified.  Most operations also require a
+netmask or a CIDR prefix as well.
+
+.SH OPTIONS
+.TP
+.TP
+\fB\-c\fR, \fB\-\-check\fR
+Validate the IP address under the specified family.  If no address
+family is specified, IPv4 is assumed.
+
+.TP
+\fB\-4\fR, \fB\-\-ipv4\fR
+Specify IPv4 address family (default).
+
+.TP
+\fB\-6\fR, \fB\-\-ipv6\fR
+Specify IPv6 address family.
+
+.TP
+\fB\-b\fR, \fB\-\-broadcast\fR
+Display the broadcast address for the given IP address and netmask.
+
+.TP
+\fB\-h\fR, \fB\-\-hostname\fR
+Display the hostname for the given IP address.
+
+.TP
+\fB\-m\fR, \fB\-\-netmask\fR
+Calculate the netmask for the given IP address. It assumes that the IP
+address is in a complete class A, B, or C network. Many networks do
+not use the default netmasks, in which case an inappropriate value will
+be returned.
+
+.TP
+\fB\-p\fR, \fB\-\-prefix\fR
+Show the prefix for the given mask/IP address.
+
+.TP
+\fB\-n\fR, \fB\-\-network\fR 
+Display the network address for the given IP address and netmask.
+
+.TP
+\fB\-s\fR, \fB\-\-silent\fR 
+Don't ever display error messages.
+
+.SH AUTHORS
+.nf
+Erik Troan <ewt@redhat.com>
+.nf
+Preston Brown <pbrown@redhat.com>
+
+.TP
+IPv6 supported wedged in by David Cantrell <dcantrell@redhat.com>
+.fi
+.SH "REPORTING BUGS"
+Report bugs at http://bugzilla.redhat.com/
+.SH COPYRIGHT
+Copyright \(co 1997-2008 Red Hat, Inc.
+.br
+This is free software; see the source for copying conditions.  There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.
diff --git a/pkgs/initscripts/src/ipcalc.c b/pkgs/initscripts/src/ipcalc.c
new file mode 100644 (file)
index 0000000..8deccca
--- /dev/null
@@ -0,0 +1,476 @@
+/*
+ * Copyright (c) 1997-2009 Red Hat, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ *
+ * Authors:
+ *   Erik Troan <ewt@redhat.com>
+ *   Preston Brown <pbrown@redhat.com>
+ *   David Cantrell <dcantrell@redhat.com>
+ */
+
+#include <ctype.h>
+#include <popt.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+
+/*!
+  \file ipcalc.c
+  \brief provides utilities for manipulating IP addresses.
+
+  ipcalc provides utilities and a front-end command line interface for
+  manipulating IP addresses, and calculating various aspects of an ip
+  address/netmask/network address/prefix/etc.
+
+  Functionality can be accessed from other languages from the library
+  interface, documented here.  To use ipcalc from the shell, read the
+  ipcalc(1) manual page.
+
+  When passing parameters to the various functions, take note of whether they
+  take host byte order or network byte order.  Most take host byte order, and
+  return host byte order, but there are some exceptions.
+*/
+
+/*!
+  \fn struct in_addr prefix2mask(int bits)
+  \brief creates a netmask from a specified number of bits
+
+  This function converts a prefix length to a netmask.  As CIDR (classless
+  internet domain internet domain routing) has taken off, more an more IP
+  addresses are being specified in the format address/prefix
+  (i.e. 192.168.2.3/24, with a corresponding netmask 255.255.255.0).  If you
+  need to see what netmask corresponds to the prefix part of the address, this
+  is the function.  See also \ref mask2prefix.
+
+  \param prefix is the number of bits to create a mask for.
+  \return a network mask, in network byte order.
+*/
+struct in_addr prefix2mask(int prefix) {
+    struct in_addr mask;
+    memset(&mask, 0, sizeof(mask));
+    if (prefix) {
+        mask.s_addr = htonl(~((1 << (32 - prefix)) - 1));
+    } else {
+        mask.s_addr = htonl(0);
+    }
+    return mask;
+}
+
+/*!
+  \fn int mask2prefix(struct in_addr mask)
+  \brief calculates the number of bits masked off by a netmask.
+
+  This function calculates the significant bits in an IP address as specified by
+  a netmask.  See also \ref prefix2mask.
+
+  \param mask is the netmask, specified as an struct in_addr in network byte order.
+  \return the number of significant bits.  */
+int mask2prefix(struct in_addr mask)
+{
+    int count;
+    uint32_t saddr = ntohl(mask.s_addr);
+
+    for (count=0; saddr > 0; count++) {
+        saddr=saddr << 1;
+    }
+
+    return count;
+}
+
+/*!
+  \fn struct in_addr default_netmask(struct in_addr addr)
+
+  \brief returns the default (canonical) netmask associated with specified IP
+  address.
+
+  When the Internet was originally set up, various ranges of IP addresses were
+  segmented into three network classes: A, B, and C.  This function will return
+  a netmask that is associated with the IP address specified defining where it
+  falls in the predefined classes.
+
+  \param addr an IP address in network byte order.
+  \return a netmask in network byte order.  */
+struct in_addr default_netmask(struct in_addr addr)
+{
+    uint32_t saddr = addr.s_addr;
+    struct in_addr mask;
+
+    memset(&mask, 0, sizeof(mask));
+
+    if (((ntohl(saddr) & 0xFF000000) >> 24) <= 127)
+        mask.s_addr = htonl(0xFF000000);
+    else if (((ntohl(saddr) & 0xFF000000) >> 24) <= 191)
+        mask.s_addr = htonl(0xFFFF0000);
+    else
+        mask.s_addr = htonl(0xFFFFFF00);
+
+    return mask;
+}
+
+/*!
+  \fn struct in_addr calc_broadcast(struct in_addr addr, int prefix)
+
+  \brief calculate broadcast address given an IP address and a prefix length.
+
+  \param addr an IP address in network byte order.
+  \param prefix a prefix length.
+
+  \return the calculated broadcast address for the network, in network byte
+  order.
+*/
+struct in_addr calc_broadcast(struct in_addr addr, int prefix)
+{
+    struct in_addr mask = prefix2mask(prefix);
+    struct in_addr broadcast;
+
+    memset(&broadcast, 0, sizeof(broadcast));
+    broadcast.s_addr = (addr.s_addr & mask.s_addr) | ~mask.s_addr;
+    return broadcast;
+}
+
+/*!
+  \fn struct in_addr calc_network(struct in_addr addr, int prefix)
+  \brief calculates the network address for a specified address and prefix.
+
+  \param addr an IP address, in network byte order
+  \param prefix the network prefix
+  \return the base address of the network that addr is associated with, in
+  network byte order.
+*/
+struct in_addr calc_network(struct in_addr addr, int prefix)
+{
+    struct in_addr mask = prefix2mask(prefix);
+    struct in_addr network;
+
+    memset(&network, 0, sizeof(network));
+    network.s_addr = addr.s_addr & mask.s_addr;
+    return network;
+}
+
+/*!
+  \fn const char *get_hostname(int family, void *addr)
+  \brief returns the hostname associated with the specified IP address
+
+  \param family the address family, either AF_INET or AF_INET6.
+  \param addr an IP address to find a hostname for, in network byte order,
+  should either be a pointer to a struct in_addr or a struct in6_addr.
+
+  \return a hostname, or NULL if one cannot be determined.  Hostname is stored
+  in a static buffer that may disappear at any time, the caller should copy the
+  data if it needs permanent storage.
+*/
+char *get_hostname(int family, void *addr)
+{
+    struct hostent * hostinfo = NULL;
+    int x;
+    struct in_addr addr4;
+    struct in6_addr addr6;
+
+    if (family == AF_INET) {
+        memset(&addr4, 0, sizeof(addr4));
+        memcpy(&addr4, addr, sizeof(addr4));
+        hostinfo = gethostbyaddr((const void *) &addr4,
+                                 sizeof(addr4), family);
+    } else if (family == AF_INET6) {
+        memset(&addr6, 0, sizeof(addr6));
+        memcpy(&addr6, addr, sizeof(addr6));
+        hostinfo = gethostbyaddr((const void *) &addr6,
+                                 sizeof(addr6), family);
+    }
+
+    if (!hostinfo)
+        return NULL;
+
+    for (x=0; hostinfo->h_name[x]; x++) {
+        hostinfo->h_name[x] = tolower(hostinfo->h_name[x]);
+    }
+    return hostinfo->h_name;
+}
+
+/*!
+  \fn main(int argc, const char **argv)
+  \brief wrapper program for ipcalc functions.
+
+  This is a wrapper program for the functions that the ipcalc library provides.
+  It can be used from shell scripts or directly from the command line.
+
+  For more information, please see the ipcalc(1) man page.
+*/
+int main(int argc, const char **argv) {
+    int showBroadcast = 0, showPrefix = 0, showNetwork = 0;
+    int showHostname = 0, showNetmask = 0;
+    int beSilent = 0;
+    int doCheck = 0, familyIPv4 = 0, familyIPv6 = 0;
+    int rc;
+    poptContext optCon;
+    char *ipStr, *prefixStr, *netmaskStr, *chptr;
+    char *hostName = NULL;
+    char namebuf[INET6_ADDRSTRLEN+1];
+    struct in_addr ip, netmask, network, broadcast;
+    struct in6_addr ip6;
+    int prefix = -1;
+    char errBuf[250];
+    struct poptOption optionsTable[] = {
+        { "check", 'c', 0, &doCheck, 0,
+          "Validate IP address for specified address family", },
+        { "ipv4", '4', 0, &familyIPv4, 0,
+          "IPv4 address family (default)", },
+        { "ipv6", '6', 0, &familyIPv6, 0,
+          "IPv6 address family", },
+        { "broadcast", 'b', 0, &showBroadcast, 0,
+          "Display calculated broadcast address", },
+        { "hostname", 'h', 0, &showHostname, 0,
+          "Show hostname determined via DNS" },
+        { "netmask", 'm', 0, &showNetmask, 0,
+          "Display default netmask for IP (class A, B, or C)" },
+        { "network", 'n', 0, &showNetwork, 0,
+          "Display network address", },
+        { "prefix", 'p', 0, &showPrefix, 0,
+          "Display network prefix", },
+        { "silent", 's', 0, &beSilent, 0,
+          "Don't ever display error messages" },
+        POPT_AUTOHELP
+        { NULL, '\0', 0, 0, 0, NULL, NULL }
+    };
+
+    optCon = poptGetContext("ipcalc", argc, argv, optionsTable, 0);
+    poptReadDefaultConfig(optCon, 1);
+
+    if ((rc = poptGetNextOpt(optCon)) < -1) {
+        if (!beSilent) {
+            fprintf(stderr, "ipcalc: bad argument %s: %s\n",
+                    poptBadOption(optCon, POPT_BADOPTION_NOALIAS),
+                    poptStrerror(rc));
+            poptPrintHelp(optCon, stderr, 0);
+        }
+        return 1;
+    }
+
+    if (!(ipStr = (char *) poptGetArg(optCon))) {
+        if (!beSilent) {
+            fprintf(stderr, "ipcalc: ip address expected\n");
+            poptPrintHelp(optCon, stderr, 0);
+        }
+        return 1;
+    }
+
+    /* if there is a : in the address, it is an IPv6 address */
+    if (strchr(ipStr,':') != NULL) {
+        familyIPv6=1;
+    }
+
+    if (strchr(ipStr,'/') != NULL) {
+        prefixStr = strchr(ipStr, '/') + 1;
+        prefixStr--;
+        *prefixStr = '\0';  /* fix up ipStr */
+        prefixStr++;
+    } else {
+        prefixStr = NULL;
+    }
+
+    if (prefixStr != NULL) {
+        prefix = atoi(prefixStr);
+        if (prefix < 0 || ((familyIPv6 && prefix > 128) || (!familyIPv6 && prefix > 32))) {
+            if (!beSilent)
+                fprintf(stderr, "ipcalc: bad prefix: %s\n", prefixStr);
+            return 1;
+        }
+    }
+
+    if (showBroadcast || showNetwork || showPrefix) {
+        if (!(netmaskStr = (char *) poptGetArg(optCon)) && (prefix < 0)) {
+            if (!beSilent) {
+                fprintf(stderr, "ipcalc: netmask or prefix expected\n");
+                poptPrintHelp(optCon, stderr, 0);
+            }
+            return 1;
+        } else if (netmaskStr && prefix >= 0) {
+            if (!beSilent) {
+                fprintf(stderr, "ipcalc: both netmask and prefix specified\n");
+                poptPrintHelp(optCon, stderr, 0);
+            }
+            return 1;
+        } else if (netmaskStr) {
+            if (inet_pton(AF_INET, netmaskStr, &netmask) <= 0) {
+                if (!beSilent)
+                    fprintf(stderr, "ipcalc: bad netmask: %s\n", netmaskStr);
+                return 1;
+            }
+            prefix = mask2prefix(netmask);
+        }
+    }
+
+    if ((chptr = (char *) poptGetArg(optCon))) {
+        if (!beSilent) {
+            fprintf(stderr, "ipcalc: unexpected argument: %s\n", chptr);
+            poptPrintHelp(optCon, stderr, 0);
+        }
+        return 1;
+    }
+
+    if (!familyIPv4 && !familyIPv6)
+        familyIPv4 = 1;
+
+    if (familyIPv4 && familyIPv6) {
+        if (!beSilent) {
+            fprintf(stderr, "ipcalc: cannot specify both address families\n");
+        }
+        return 1;
+    }
+
+    /* Handle CIDR entries such as 172/8 */
+    if (prefix >= 0 && familyIPv4) {
+        char *tmp = ipStr;
+        int i;
+
+        for (i=3; i> 0; i--) {
+            tmp = strchr(tmp,'.');
+            if (!tmp)
+                break;
+            else
+                tmp++;
+        }
+
+        tmp = NULL;
+        for (; i>0; i--) {
+            if (asprintf(&tmp, "%s.0", ipStr) == -1) {
+                fprintf(stderr, "Memory allocation failure line %d\n", __LINE__);
+                abort();
+            }
+            ipStr = tmp;
+        }
+    }
+
+    if (familyIPv4) {
+        if (inet_pton(AF_INET, ipStr, &ip) <= 0) {
+            if (!beSilent)
+                fprintf(stderr, "ipcalc: bad IPv4 address: %s\n", ipStr);
+            return 1;
+        } else if (prefix > 32) {
+            if (!beSilent)
+                fprintf(stderr, "ipcalc: bad IPv4 prefix %d\n", prefix);
+            return 1;
+        } else {
+            if (doCheck)
+                return 0;
+        }
+    }
+
+    if (familyIPv6) {
+        if (inet_pton(AF_INET6, ipStr, &ip6) <= 0) {
+            if (!beSilent)
+                fprintf(stderr, "ipcalc: bad IPv6 address: %s\n", ipStr);
+            return 1;
+        } else if (prefix > 128) {
+            if (!beSilent)
+                fprintf(stderr, "ipcalc: bad IPv6 prefix %d\n", prefix);
+            return 1;
+        } else {
+            if (doCheck)
+                return 0;
+        }
+    }
+
+    if (familyIPv6 &&
+        (showBroadcast || showNetmask || showNetwork || showPrefix)) {
+        if (!beSilent) {
+            fprintf(stderr, "ipcalc: unable to show setting for IPv6\n");
+        }
+        return 1;
+    }
+
+    if (familyIPv4 &&
+        !(showNetmask|showPrefix|showBroadcast|showNetwork|showHostname)) {
+        poptPrintHelp(optCon, stderr, 0);
+        return 1;
+    }
+
+    poptFreeContext(optCon);
+
+    /* we know what we want to display now, so display it. */
+
+    if (showNetmask) {
+        if (prefix >= 0) {
+            netmask = prefix2mask(prefix);
+        } else {
+            netmask = default_netmask(ip);
+            prefix = mask2prefix(netmask);
+        }
+
+        memset(&namebuf, '\0', sizeof(namebuf));
+
+        if (inet_ntop(AF_INET, &netmask, namebuf, INET_ADDRSTRLEN) == NULL) {
+            fprintf(stderr, "Memory allocation failure line %d\n", __LINE__);
+            abort();
+        }
+
+        printf("NETMASK=%s\n", namebuf);
+    }
+
+    if (showPrefix) {
+        if (prefix == -1)
+            prefix = mask2prefix(ip);
+        printf("PREFIX=%d\n", prefix);
+    }
+
+    if (showBroadcast) {
+        broadcast = calc_broadcast(ip, prefix);
+        memset(&namebuf, '\0', sizeof(namebuf));
+
+        if (inet_ntop(AF_INET, &broadcast, namebuf, INET_ADDRSTRLEN) == NULL) {
+            fprintf(stderr, "Memory allocation failure line %d\n", __LINE__);
+            abort();
+        }
+
+        printf("BROADCAST=%s\n", namebuf);
+    }
+
+    if (showNetwork) {
+        network = calc_network(ip, prefix);
+        memset(&namebuf, '\0', sizeof(namebuf));
+
+        if (inet_ntop(AF_INET, &network, namebuf, INET_ADDRSTRLEN) == NULL) {
+            fprintf(stderr, "Memory allocation failure line %d\n", __LINE__);
+            abort();
+        }
+
+        printf("NETWORK=%s\n", namebuf);
+    }
+
+    if (showHostname) {
+        if (familyIPv4) {
+            hostName = get_hostname(AF_INET, &ip);
+        } else if (familyIPv6) {
+            hostName = get_hostname(AF_INET6, &ip6);
+        }
+
+        if (hostName == NULL) {
+            if (!beSilent) {
+                sprintf(errBuf, "ipcalc: cannot find hostname for %s", ipStr);
+                herror(errBuf);
+            }
+            return 1;
+        }
+
+        printf("HOSTNAME=%s\n", hostName);
+    }
+
+    return 0;
+}