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