summaryrefslogtreecommitdiff
path: root/networking/ipcalc.c
diff options
context:
space:
mode:
Diffstat (limited to 'networking/ipcalc.c')
-rw-r--r--networking/ipcalc.c87
1 files changed, 78 insertions, 9 deletions
diff --git a/networking/ipcalc.c b/networking/ipcalc.c
index 94b747e..9578c82 100644
--- a/networking/ipcalc.c
+++ b/networking/ipcalc.c
@@ -40,11 +40,29 @@ static unsigned long get_netmask(unsigned long ipaddr)
return 0;
}
+#ifdef CONFIG_FEATURE_IPCALC_FANCY
+static int get_prefix(unsigned long netmask)
+{
+ unsigned long t;
+ int ret = 0;
+
+ for (t = 0; t < 32; t++) {
+ if (htonl(netmask) & (0x80000000 >> t)) {
+ ret ++;
+ } else {
+ break;
+ }
+ }
+ return ret;
+}
+#endif
+
#define NETMASK 0x01
#define BROADCAST 0x02
#define NETWORK 0x04
-#define HOSTNAME 0x08
-#define SILENT 0x10
+#define NETPREFIX 0x08
+#define HOSTNAME 0x10
+#define SILENT 0x80
int ipcalc_main(int argc, char **argv)
{
@@ -55,11 +73,18 @@ int ipcalc_main(int argc, char **argv)
unsigned long network;
unsigned long ipaddr;
+#ifdef CONFIG_FEATURE_IPCALC_FANCY
+ unsigned long netprefix = 0;
+ int have_netmask = 0;
+ char *ipstr, *prefixstr;
+#endif
+
static const struct option long_options[] = {
- {"netmask", no_argument, NULL, 'n'},
+ {"netmask", no_argument, NULL, 'm'},
{"broadcast", no_argument, NULL, 'b'},
- {"network", no_argument, NULL, 'w'},
+ {"network", no_argument, NULL, 'n'},
#ifdef CONFIG_FEATURE_IPCALC_FANCY
+ {"prefix", no_argument, NULL, 'p'},
{"hostname", no_argument, NULL, 'h'},
{"silent", no_argument, NULL, 's'},
#endif
@@ -69,11 +94,11 @@ int ipcalc_main(int argc, char **argv)
bb_applet_long_options = long_options;
mode = bb_getopt_ulflags(argc, argv,
#ifdef CONFIG_FEATURE_IPCALC_FANCY
- "nbwhs");
+ "mbnphs");
#else
- "nbw");
+ "mbn");
#endif
- if (mode & (BROADCAST | NETWORK)) {
+ if (mode & (BROADCAST | NETWORK | NETPREFIX)) {
if (argc - optind > 2) {
bb_show_usage();
}
@@ -83,16 +108,55 @@ int ipcalc_main(int argc, char **argv)
}
}
+#ifdef CONFIG_FEATURE_IPCALC_FANCY
+ prefixstr = ipstr = argv[optind];
+
+ while(*prefixstr) {
+ if (*prefixstr == '/') {
+ *prefixstr = (char)0;
+ prefixstr++;
+ if (*prefixstr) {
+ netprefix = atol(prefixstr);
+ if (netprefix > 32) {
+ IPCALC_MSG(bb_error_msg_and_die("bad IP prefix: %s\n", prefixstr),
+ exit(EXIT_FAILURE));
+ }
+ if (netprefix) {
+ netmask = 0x80000000;
+ netprefix--;
+ while(netprefix) {
+ netmask = 0x80000000 | (netmask >> 1);
+ netprefix--;
+ }
+ netmask = htonl(netmask);
+ }
+ /* Even if it was 0, we will signify that we have a netmask. This allows */
+ /* for specification of default routes, etc which have a 0 netmask/prefix */
+ have_netmask = 1;
+ }
+ break;
+ }
+ prefixstr++;
+ }
+ ipaddr = inet_addr(ipstr);
+#else
ipaddr = inet_addr(argv[optind]);
+#endif
if (ipaddr == INADDR_NONE) {
IPCALC_MSG(bb_error_msg_and_die("bad IP address: %s", argv[optind]),
exit(EXIT_FAILURE));
}
-
if (argc - optind == 2) {
- netmask = inet_addr(argv[optind + 1]);
+#ifdef CONFIG_FEATURE_IPCALC_FANCY
+ if (have_netmask == 1) {
+ IPCALC_MSG(bb_error_msg_and_die("Both prefix and netmask were specified, use one or the other.\n"),
+ exit(EXIT_FAILURE));
+ }
+ have_netmask = 1;
+#endif
+ netmask = inet_addr(argv[optind + 1]);
}
if (ipaddr == INADDR_NONE) {
@@ -118,7 +182,12 @@ int ipcalc_main(int argc, char **argv)
network = ipaddr & netmask;
printf("NETWORK=%s\n", inet_ntoa((*(struct in_addr *) &network)));
}
+
#ifdef CONFIG_FEATURE_IPCALC_FANCY
+ if (mode & NETPREFIX) {
+ printf("PREFIX=%i\n", get_prefix(netmask));
+ }
+
if (mode & HOSTNAME) {
struct hostent *hostinfo;
int x;