Annotation of /trunk/mkinitrd-magellan/busybox/networking/ipcalc.c
Parent Directory | Revision Log
Revision 532 -
(hide annotations)
(download)
Sat Sep 1 22:45:15 2007 UTC (16 years, 8 months ago) by niro
File MIME type: text/plain
File size: 4572 byte(s)
Sat Sep 1 22:45:15 2007 UTC (16 years, 8 months ago) by niro
File MIME type: text/plain
File size: 4572 byte(s)
-import if magellan mkinitrd; it is a fork of redhats mkinitrd-5.0.8 with all magellan patches and features; deprecates magellan-src/mkinitrd
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 | |||
15 | #include "busybox.h" | ||
16 | #include <ctype.h> | ||
17 | #include <getopt.h> | ||
18 | #include <sys/socket.h> | ||
19 | #include <arpa/inet.h> | ||
20 | |||
21 | #define CLASS_A_NETMASK ntohl(0xFF000000) | ||
22 | #define CLASS_B_NETMASK ntohl(0xFFFF0000) | ||
23 | #define CLASS_C_NETMASK ntohl(0xFFFFFF00) | ||
24 | |||
25 | static unsigned long get_netmask(unsigned long ipaddr) | ||
26 | { | ||
27 | ipaddr = htonl(ipaddr); | ||
28 | |||
29 | if ((ipaddr & 0xC0000000) == 0xC0000000) | ||
30 | return CLASS_C_NETMASK; | ||
31 | else if ((ipaddr & 0x80000000) == 0x80000000) | ||
32 | return CLASS_B_NETMASK; | ||
33 | else if ((ipaddr & 0x80000000) == 0) | ||
34 | return CLASS_A_NETMASK; | ||
35 | else | ||
36 | return 0; | ||
37 | } | ||
38 | |||
39 | #ifdef CONFIG_FEATURE_IPCALC_FANCY | ||
40 | static int get_prefix(unsigned long netmask) | ||
41 | { | ||
42 | unsigned long msk = 0x80000000; | ||
43 | int ret = 0; | ||
44 | |||
45 | netmask = htonl(netmask); | ||
46 | while (msk) { | ||
47 | if (netmask & msk) | ||
48 | ret++; | ||
49 | msk >>= 1; | ||
50 | } | ||
51 | return ret; | ||
52 | } | ||
53 | #else | ||
54 | int get_prefix(unsigned long netmask); | ||
55 | #endif | ||
56 | |||
57 | |||
58 | #define NETMASK 0x01 | ||
59 | #define BROADCAST 0x02 | ||
60 | #define NETWORK 0x04 | ||
61 | #define NETPREFIX 0x08 | ||
62 | #define HOSTNAME 0x10 | ||
63 | #define SILENT 0x20 | ||
64 | |||
65 | #if ENABLE_FEATURE_IPCALC_LONG_OPTIONS | ||
66 | static const struct option long_options[] = { | ||
67 | { "netmask", no_argument, NULL, 'm' }, | ||
68 | { "broadcast", no_argument, NULL, 'b' }, | ||
69 | { "network", no_argument, NULL, 'n' }, | ||
70 | # if ENABLE_FEATURE_IPCALC_FANCY | ||
71 | { "prefix", no_argument, NULL, 'p' }, | ||
72 | { "hostname", no_argument, NULL, 'h' }, | ||
73 | { "silent", no_argument, NULL, 's' }, | ||
74 | # endif | ||
75 | { NULL, 0, NULL, 0 } | ||
76 | }; | ||
77 | #endif | ||
78 | |||
79 | int ipcalc_main(int argc, char **argv) | ||
80 | { | ||
81 | unsigned opt; | ||
82 | int have_netmask = 0; | ||
83 | in_addr_t netmask, broadcast, network, ipaddr; | ||
84 | struct in_addr a; | ||
85 | char *ipstr; | ||
86 | |||
87 | #if ENABLE_FEATURE_IPCALC_LONG_OPTIONS | ||
88 | applet_long_options = long_options; | ||
89 | #endif | ||
90 | opt = getopt32(argc, argv, "mbn" USE_FEATURE_IPCALC_FANCY("phs")); | ||
91 | argc -= optind; | ||
92 | argv += optind; | ||
93 | if (opt & (BROADCAST | NETWORK | NETPREFIX)) { | ||
94 | if (argc > 2 || argc <= 0) | ||
95 | bb_show_usage(); | ||
96 | } else { | ||
97 | if (argc != 1) | ||
98 | bb_show_usage(); | ||
99 | } | ||
100 | if (opt & SILENT) | ||
101 | logmode = LOGMODE_NONE; /* Suppress error_msg() output */ | ||
102 | |||
103 | ipstr = argv[0]; | ||
104 | if (ENABLE_FEATURE_IPCALC_FANCY) { | ||
105 | unsigned long netprefix = 0; | ||
106 | char *prefixstr; | ||
107 | |||
108 | prefixstr = ipstr; | ||
109 | |||
110 | while (*prefixstr) { | ||
111 | if (*prefixstr == '/') { | ||
112 | *prefixstr = (char)0; | ||
113 | prefixstr++; | ||
114 | if (*prefixstr) { | ||
115 | unsigned msk; | ||
116 | netprefix = xatoul_range(prefixstr, 0, 32); | ||
117 | netmask = 0; | ||
118 | msk = 0x80000000; | ||
119 | while (netprefix > 0) { | ||
120 | netmask |= msk; | ||
121 | msk >>= 1; | ||
122 | netprefix--; | ||
123 | } | ||
124 | netmask = htonl(netmask); | ||
125 | /* Even if it was 0, we will signify that we have a netmask. This allows */ | ||
126 | /* for specification of default routes, etc which have a 0 netmask/prefix */ | ||
127 | have_netmask = 1; | ||
128 | } | ||
129 | break; | ||
130 | } | ||
131 | prefixstr++; | ||
132 | } | ||
133 | } | ||
134 | ipaddr = inet_aton(ipstr, &a); | ||
135 | |||
136 | if (ipaddr == 0) { | ||
137 | bb_error_msg_and_die("bad IP address: %s", argv[0]); | ||
138 | } | ||
139 | ipaddr = a.s_addr; | ||
140 | |||
141 | if (argc == 2) { | ||
142 | if (ENABLE_FEATURE_IPCALC_FANCY && have_netmask) { | ||
143 | bb_error_msg_and_die("use prefix or netmask, not both"); | ||
144 | } | ||
145 | |||
146 | netmask = inet_aton(argv[1], &a); | ||
147 | if (netmask == 0) { | ||
148 | bb_error_msg_and_die("bad netmask: %s", argv[1]); | ||
149 | } | ||
150 | netmask = a.s_addr; | ||
151 | } else { | ||
152 | |||
153 | /* JHC - If the netmask wasn't provided then calculate it */ | ||
154 | if (!ENABLE_FEATURE_IPCALC_FANCY || !have_netmask) | ||
155 | netmask = get_netmask(ipaddr); | ||
156 | } | ||
157 | |||
158 | if (opt & NETMASK) { | ||
159 | printf("NETMASK=%s\n", inet_ntoa((*(struct in_addr *) &netmask))); | ||
160 | } | ||
161 | |||
162 | if (opt & BROADCAST) { | ||
163 | broadcast = (ipaddr & netmask) | ~netmask; | ||
164 | printf("BROADCAST=%s\n", inet_ntoa((*(struct in_addr *) &broadcast))); | ||
165 | } | ||
166 | |||
167 | if (opt & NETWORK) { | ||
168 | network = ipaddr & netmask; | ||
169 | printf("NETWORK=%s\n", inet_ntoa((*(struct in_addr *) &network))); | ||
170 | } | ||
171 | |||
172 | if (ENABLE_FEATURE_IPCALC_FANCY) { | ||
173 | if (opt & NETPREFIX) { | ||
174 | printf("PREFIX=%i\n", get_prefix(netmask)); | ||
175 | } | ||
176 | |||
177 | if (opt & HOSTNAME) { | ||
178 | struct hostent *hostinfo; | ||
179 | int x; | ||
180 | |||
181 | hostinfo = gethostbyaddr((char *) &ipaddr, sizeof(ipaddr), AF_INET); | ||
182 | if (!hostinfo) { | ||
183 | bb_herror_msg_and_die("cannot find hostname for %s", argv[0]); | ||
184 | } | ||
185 | for (x = 0; hostinfo->h_name[x]; x++) { | ||
186 | hostinfo->h_name[x] = tolower(hostinfo->h_name[x]); | ||
187 | } | ||
188 | |||
189 | printf("HOSTNAME=%s\n", hostinfo->h_name); | ||
190 | } | ||
191 | } | ||
192 | |||
193 | return EXIT_SUCCESS; | ||
194 | } |