source: branches/3.2/mindi-busybox/networking/ipcalc.c @ 3232

Last change on this file since 3232 was 3232, checked in by bruno, 5 years ago
  • Update mindi-busybox to 1.21.1
File size: 5.9 KB
Line 
1/* vi: set sw=4 ts=4: */
2/*
3 * Mini ipcalc implementation for busybox
4 *
5 * By Jordan Crouse <jordan@cosmicpenguin.net>
6 *    Stephan Linz  <linz@li-pro.net>
7 *
8 * This is a complete reimplementation of the ipcalc program
9 * from Red Hat.  I didn't look at their source code, but there
10 * is no denying that this is a loving reimplementation
11 *
12 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
13 */
14
15//usage:#define ipcalc_trivial_usage
16//usage:       "[OPTIONS] ADDRESS[[/]NETMASK] [NETMASK]"
17//usage:#define ipcalc_full_usage "\n\n"
18//usage:       "Calculate IP network settings from a IP address\n"
19//usage:    IF_FEATURE_IPCALC_LONG_OPTIONS(
20//usage:     "\n    -b,--broadcast  Display calculated broadcast address"
21//usage:     "\n    -n,--network    Display calculated network address"
22//usage:     "\n    -m,--netmask    Display default netmask for IP"
23//usage:    IF_FEATURE_IPCALC_FANCY(
24//usage:     "\n    -p,--prefix Display the prefix for IP/NETMASK"
25//usage:     "\n    -h,--hostname   Display first resolved host name"
26//usage:     "\n    -s,--silent Don't ever display error messages"
27//usage:    )
28//usage:    )
29//usage:    IF_NOT_FEATURE_IPCALC_LONG_OPTIONS(
30//usage:     "\n    -b  Display calculated broadcast address"
31//usage:     "\n    -n  Display calculated network address"
32//usage:     "\n    -m  Display default netmask for IP"
33//usage:    IF_FEATURE_IPCALC_FANCY(
34//usage:     "\n    -p  Display the prefix for IP/NETMASK"
35//usage:     "\n    -h  Display first resolved host name"
36//usage:     "\n    -s  Don't ever display error messages"
37//usage:    )
38//usage:    )
39
40#include "libbb.h"
41/* After libbb.h, because on some systems it needs other includes */
42#include <arpa/inet.h>
43
44#define CLASS_A_NETMASK ntohl(0xFF000000)
45#define CLASS_B_NETMASK ntohl(0xFFFF0000)
46#define CLASS_C_NETMASK ntohl(0xFFFFFF00)
47
48static unsigned long get_netmask(unsigned long ipaddr)
49{
50    ipaddr = htonl(ipaddr);
51
52    if ((ipaddr & 0xC0000000) == 0xC0000000)
53        return CLASS_C_NETMASK;
54    else if ((ipaddr & 0x80000000) == 0x80000000)
55        return CLASS_B_NETMASK;
56    else if ((ipaddr & 0x80000000) == 0)
57        return CLASS_A_NETMASK;
58    else
59        return 0;
60}
61
62#if ENABLE_FEATURE_IPCALC_FANCY
63static int get_prefix(unsigned long netmask)
64{
65    unsigned long msk = 0x80000000;
66    int ret = 0;
67
68    netmask = htonl(netmask);
69    while (msk) {
70        if (netmask & msk)
71            ret++;
72        msk >>= 1;
73    }
74    return ret;
75}
76#else
77int get_prefix(unsigned long netmask);
78#endif
79
80
81#define NETMASK   0x01
82#define BROADCAST 0x02
83#define NETWORK   0x04
84#define NETPREFIX 0x08
85#define HOSTNAME  0x10
86#define SILENT    0x20
87
88#if ENABLE_FEATURE_IPCALC_LONG_OPTIONS
89    static const char ipcalc_longopts[] ALIGN1 =
90        "netmask\0"   No_argument "m" // netmask from IP (assuming complete class A, B, or C network)
91        "broadcast\0" No_argument "b" // broadcast from IP [netmask]
92        "network\0"   No_argument "n" // network from IP [netmask]
93# if ENABLE_FEATURE_IPCALC_FANCY
94        "prefix\0"    No_argument "p" // prefix from IP[/prefix] [netmask]
95        "hostname\0"  No_argument "h" // hostname from IP
96        "silent\0"    No_argument "s" // don’t ever display error messages
97# endif
98        ;
99#endif
100
101int ipcalc_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
102int ipcalc_main(int argc UNUSED_PARAM, char **argv)
103{
104    unsigned opt;
105    bool have_netmask = 0;
106    struct in_addr s_netmask, s_broadcast, s_network, s_ipaddr;
107    /* struct in_addr { in_addr_t s_addr; }  and  in_addr_t
108     * (which in turn is just a typedef to uint32_t)
109     * are essentially the same type. A few macros for less verbosity: */
110#define netmask   (s_netmask.s_addr)
111#define broadcast (s_broadcast.s_addr)
112#define network   (s_network.s_addr)
113#define ipaddr    (s_ipaddr.s_addr)
114    char *ipstr;
115
116#if ENABLE_FEATURE_IPCALC_LONG_OPTIONS
117    applet_long_options = ipcalc_longopts;
118#endif
119    opt_complementary = "-1:?2"; /* minimum 1 arg, maximum 2 args */
120    opt = getopt32(argv, "mbn" IF_FEATURE_IPCALC_FANCY("phs"));
121    argv += optind;
122    if (opt & SILENT)
123        logmode = LOGMODE_NONE; /* suppress error_msg() output */
124    opt &= ~SILENT;
125    if (!(opt & (BROADCAST | NETWORK | NETPREFIX))) {
126        /* if no options at all or
127         * (no broadcast,network,prefix) and (two args)... */
128        if (!opt || argv[1])
129            bb_show_usage();
130    }
131
132    ipstr = argv[0];
133    if (ENABLE_FEATURE_IPCALC_FANCY) {
134        unsigned long netprefix = 0;
135        char *prefixstr;
136
137        prefixstr = ipstr;
138
139        while (*prefixstr) {
140            if (*prefixstr == '/') {
141                *prefixstr++ = '\0';
142                if (*prefixstr) {
143                    unsigned msk;
144                    netprefix = xatoul_range(prefixstr, 0, 32);
145                    netmask = 0;
146                    msk = 0x80000000;
147                    while (netprefix > 0) {
148                        netmask |= msk;
149                        msk >>= 1;
150                        netprefix--;
151                    }
152                    netmask = htonl(netmask);
153                    /* Even if it was 0, we will signify that we have a netmask. This allows */
154                    /* for specification of default routes, etc which have a 0 netmask/prefix */
155                    have_netmask = 1;
156                }
157                break;
158            }
159            prefixstr++;
160        }
161    }
162
163    if (inet_aton(ipstr, &s_ipaddr) == 0) {
164        bb_error_msg_and_die("bad IP address: %s", argv[0]);
165    }
166
167    if (argv[1]) {
168        if (ENABLE_FEATURE_IPCALC_FANCY && have_netmask) {
169            bb_error_msg_and_die("use prefix or netmask, not both");
170        }
171        if (inet_aton(argv[1], &s_netmask) == 0) {
172            bb_error_msg_and_die("bad netmask: %s", argv[1]);
173        }
174    } else {
175        /* JHC - If the netmask wasn't provided then calculate it */
176        if (!ENABLE_FEATURE_IPCALC_FANCY || !have_netmask)
177            netmask = get_netmask(ipaddr);
178    }
179
180    if (opt & NETMASK) {
181        printf("NETMASK=%s\n", inet_ntoa(s_netmask));
182    }
183
184    if (opt & BROADCAST) {
185        broadcast = (ipaddr & netmask) | ~netmask;
186        printf("BROADCAST=%s\n", inet_ntoa(s_broadcast));
187    }
188
189    if (opt & NETWORK) {
190        network = ipaddr & netmask;
191        printf("NETWORK=%s\n", inet_ntoa(s_network));
192    }
193
194    if (ENABLE_FEATURE_IPCALC_FANCY) {
195        if (opt & NETPREFIX) {
196            printf("PREFIX=%i\n", get_prefix(netmask));
197        }
198
199        if (opt & HOSTNAME) {
200            struct hostent *hostinfo;
201
202            hostinfo = gethostbyaddr((char *) &ipaddr, sizeof(ipaddr), AF_INET);
203            if (!hostinfo) {
204                bb_herror_msg_and_die("can't find hostname for %s", argv[0]);
205            }
206            str_tolower(hostinfo->h_name);
207
208            printf("HOSTNAME=%s\n", hostinfo->h_name);
209        }
210    }
211
212    return EXIT_SUCCESS;
213}
Note: See TracBrowser for help on using the repository browser.