source: MondoRescue/branches/3.3/mindi-busybox/networking/ipcalc.c@ 3621

Last change on this file since 3621 was 3621, checked in by Bruno Cornec, 7 years ago

New 3?3 banch for incorporation of latest busybox 1.25. Changing minor version to handle potential incompatibilities.

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