diff options
-rw-r--r-- | networking/Config.in | 4 | ||||
-rw-r--r-- | networking/ipcalc.c | 87 |
2 files changed, 80 insertions, 11 deletions
diff --git a/networking/Config.in b/networking/Config.in index 754d8d9f9..2705980bb 100644 --- a/networking/Config.in +++ b/networking/Config.in @@ -376,11 +376,11 @@ config CONFIG_IPCALC resulting broadcast, network, and host range. config CONFIG_FEATURE_IPCALC_FANCY - bool " Fancy IPCALC, more options, adds 300 bytes" + bool " Fancy IPCALC, more options, adds 1 kbyte" default y depends on CONFIG_IPCALC help - Adds the fields hostname and silent to the output of "ipcalc". + Adds the options hostname, prefix and silent to the output of "ipcalc". config CONFIG_IPADDR bool "ipaddr" diff --git a/networking/ipcalc.c b/networking/ipcalc.c index 94b747ef6..9578c8266 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; |