diff options
Diffstat (limited to 'busybox/networking/ipcalc.c')
-rw-r--r-- | busybox/networking/ipcalc.c | 224 |
1 files changed, 224 insertions, 0 deletions
diff --git a/busybox/networking/ipcalc.c b/busybox/networking/ipcalc.c new file mode 100644 index 000000000..bcd272b85 --- /dev/null +++ b/busybox/networking/ipcalc.c | |||
@@ -0,0 +1,224 @@ | |||
1 | /* vi: set sw=4 ts=4 ai: */ | ||
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 | |||
13 | #include <stdio.h> | ||
14 | #include <stdlib.h> | ||
15 | #include <ctype.h> | ||
16 | #include <getopt.h> | ||
17 | #include <sys/socket.h> | ||
18 | #include <netinet/in.h> | ||
19 | #include <arpa/inet.h> | ||
20 | |||
21 | #include "busybox.h" | ||
22 | |||
23 | #define IPCALC_MSG(CMD,ALTCMD) if (mode & SILENT) {ALTCMD;} else {CMD;} | ||
24 | |||
25 | #define CLASS_A_NETMASK ntohl(0xFF000000) | ||
26 | #define CLASS_B_NETMASK ntohl(0xFFFF0000) | ||
27 | #define CLASS_C_NETMASK ntohl(0xFFFFFF00) | ||
28 | |||
29 | static unsigned long get_netmask(unsigned long ipaddr) | ||
30 | { | ||
31 | ipaddr = htonl(ipaddr); | ||
32 | |||
33 | if ((ipaddr & 0xC0000000) == 0xC0000000) | ||
34 | return CLASS_C_NETMASK; | ||
35 | else if ((ipaddr & 0x80000000) == 0x80000000) | ||
36 | return CLASS_B_NETMASK; | ||
37 | else if ((ipaddr & 0x80000000) == 0) | ||
38 | return CLASS_A_NETMASK; | ||
39 | else | ||
40 | return 0; | ||
41 | } | ||
42 | |||
43 | #ifdef CONFIG_FEATURE_IPCALC_FANCY | ||
44 | static int get_prefix(unsigned long netmask) | ||
45 | { | ||
46 | unsigned long msk = 0x80000000; | ||
47 | int ret = 0; | ||
48 | |||
49 | netmask = htonl(netmask); | ||
50 | while(msk) { | ||
51 | if (netmask & msk) | ||
52 | ret++; | ||
53 | msk >>= 1; | ||
54 | } | ||
55 | return ret; | ||
56 | } | ||
57 | #endif | ||
58 | |||
59 | #define NETMASK 0x01 | ||
60 | #define BROADCAST 0x02 | ||
61 | #define NETWORK 0x04 | ||
62 | #define NETPREFIX 0x08 | ||
63 | #define HOSTNAME 0x10 | ||
64 | #define SILENT 0x20 | ||
65 | |||
66 | |||
67 | int ipcalc_main(int argc, char **argv) | ||
68 | { | ||
69 | unsigned long mode; | ||
70 | |||
71 | in_addr_t netmask; | ||
72 | in_addr_t broadcast; | ||
73 | in_addr_t network; | ||
74 | in_addr_t ipaddr; | ||
75 | struct in_addr a; | ||
76 | |||
77 | #ifdef CONFIG_FEATURE_IPCALC_FANCY | ||
78 | unsigned long netprefix = 0; | ||
79 | int have_netmask = 0; | ||
80 | char *ipstr, *prefixstr; | ||
81 | #endif | ||
82 | |||
83 | static const struct option long_options[] = { | ||
84 | {"netmask", no_argument, NULL, 'm'}, | ||
85 | {"broadcast", no_argument, NULL, 'b'}, | ||
86 | {"network", no_argument, NULL, 'n'}, | ||
87 | #ifdef CONFIG_FEATURE_IPCALC_FANCY | ||
88 | {"prefix", no_argument, NULL, 'p'}, | ||
89 | {"hostname", no_argument, NULL, 'h'}, | ||
90 | {"silent", no_argument, NULL, 's'}, | ||
91 | #endif | ||
92 | {NULL, 0, NULL, 0} | ||
93 | }; | ||
94 | |||
95 | bb_applet_long_options = long_options; | ||
96 | mode = bb_getopt_ulflags(argc, argv, | ||
97 | #ifdef CONFIG_FEATURE_IPCALC_FANCY | ||
98 | "mbnphs" | ||
99 | #else | ||
100 | "mbn" | ||
101 | #endif | ||
102 | ); | ||
103 | if (mode & (BROADCAST | NETWORK | NETPREFIX)) { | ||
104 | if (argc - optind > 2) { | ||
105 | bb_show_usage(); | ||
106 | } | ||
107 | } else { | ||
108 | if (argc - optind != 1) { | ||
109 | bb_show_usage(); | ||
110 | } | ||
111 | } | ||
112 | |||
113 | #ifdef CONFIG_FEATURE_IPCALC_FANCY | ||
114 | prefixstr = ipstr = argv[optind]; | ||
115 | |||
116 | while(*prefixstr) { | ||
117 | if (*prefixstr == '/') { | ||
118 | *prefixstr = (char)0; | ||
119 | prefixstr++; | ||
120 | if (*prefixstr) { | ||
121 | unsigned int msk; | ||
122 | |||
123 | if (safe_strtoul(prefixstr, &netprefix) || netprefix > 32) { | ||
124 | IPCALC_MSG(bb_error_msg_and_die("bad IP prefix: %s\n", prefixstr), | ||
125 | exit(EXIT_FAILURE)); | ||
126 | } | ||
127 | netmask = 0; | ||
128 | msk = 0x80000000; | ||
129 | while (netprefix > 0) { | ||
130 | netmask |= msk; | ||
131 | msk >>= 1; | ||
132 | netprefix--; | ||
133 | } | ||
134 | netmask = htonl(netmask); | ||
135 | /* Even if it was 0, we will signify that we have a netmask. This allows */ | ||
136 | /* for specification of default routes, etc which have a 0 netmask/prefix */ | ||
137 | have_netmask = 1; | ||
138 | } | ||
139 | break; | ||
140 | } | ||
141 | prefixstr++; | ||
142 | } | ||
143 | ipaddr = inet_aton(ipstr, &a); | ||
144 | #else | ||
145 | ipaddr = inet_aton(argv[optind], &a); | ||
146 | #endif | ||
147 | |||
148 | if (ipaddr == 0) { | ||
149 | IPCALC_MSG(bb_error_msg_and_die("bad IP address: %s", argv[optind]), | ||
150 | exit(EXIT_FAILURE)); | ||
151 | } | ||
152 | ipaddr = a.s_addr; | ||
153 | |||
154 | if (argc - optind == 2) { | ||
155 | #ifdef CONFIG_FEATURE_IPCALC_FANCY | ||
156 | if (have_netmask) { | ||
157 | IPCALC_MSG(bb_error_msg_and_die("Both prefix and netmask were specified, use one or the other.\n"), | ||
158 | exit(EXIT_FAILURE)); | ||
159 | } | ||
160 | |||
161 | #endif | ||
162 | netmask = inet_aton(argv[optind + 1], &a); | ||
163 | if (netmask == 0) { | ||
164 | IPCALC_MSG(bb_error_msg_and_die("bad netmask: %s", argv[optind + 1]), | ||
165 | exit(EXIT_FAILURE)); | ||
166 | } | ||
167 | netmask = a.s_addr; | ||
168 | } else { | ||
169 | #ifdef CONFIG_FEATURE_IPCALC_FANCY | ||
170 | |||
171 | if (!have_netmask) | ||
172 | #endif | ||
173 | /* JHC - If the netmask wasn't provided then calculate it */ | ||
174 | netmask = get_netmask(ipaddr); | ||
175 | } | ||
176 | |||
177 | if (mode & NETMASK) { | ||
178 | printf("NETMASK=%s\n", inet_ntoa((*(struct in_addr *) &netmask))); | ||
179 | } | ||
180 | |||
181 | if (mode & BROADCAST) { | ||
182 | broadcast = (ipaddr & netmask) | ~netmask; | ||
183 | printf("BROADCAST=%s\n", inet_ntoa((*(struct in_addr *) &broadcast))); | ||
184 | } | ||
185 | |||
186 | if (mode & NETWORK) { | ||
187 | network = ipaddr & netmask; | ||
188 | printf("NETWORK=%s\n", inet_ntoa((*(struct in_addr *) &network))); | ||
189 | } | ||
190 | |||
191 | #ifdef CONFIG_FEATURE_IPCALC_FANCY | ||
192 | if (mode & NETPREFIX) { | ||
193 | printf("PREFIX=%i\n", get_prefix(netmask)); | ||
194 | } | ||
195 | |||
196 | if (mode & HOSTNAME) { | ||
197 | struct hostent *hostinfo; | ||
198 | int x; | ||
199 | |||
200 | hostinfo = gethostbyaddr((char *) &ipaddr, sizeof(ipaddr), AF_INET); | ||
201 | if (!hostinfo) { | ||
202 | IPCALC_MSG(bb_herror_msg_and_die( | ||
203 | "cannot find hostname for %s", argv[optind]),); | ||
204 | exit(EXIT_FAILURE); | ||
205 | } | ||
206 | for (x = 0; hostinfo->h_name[x]; x++) { | ||
207 | hostinfo->h_name[x] = tolower(hostinfo->h_name[x]); | ||
208 | } | ||
209 | |||
210 | printf("HOSTNAME=%s\n", hostinfo->h_name); | ||
211 | } | ||
212 | #endif | ||
213 | |||
214 | return EXIT_SUCCESS; | ||
215 | } | ||
216 | |||
217 | /* END CODE */ | ||
218 | /* | ||
219 | Local Variables: | ||
220 | c-file-style: "linux" | ||
221 | c-basic-offset: 4 | ||
222 | tab-width: 4 | ||
223 | End: | ||
224 | */ | ||