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

Last change on this file since 3734 was 3621, checked in by Bruno Cornec, 10 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.