diff options
author | Victor Lowther <victor.lowther@gmail.com> | 2009-07-29 16:49:42 -0400 |
---|---|---|
committer | Bill Nottingham <notting@redhat.com> | 2009-07-29 16:49:42 -0400 |
commit | 7e28ab4bc109ab4440751fe3a4cb44365ccb2301 (patch) | |
tree | f12e07c377b60de3956d9da857f6b3671f1776e0 /src/ipcalc.c | |
parent | 05c3dddbb545edfee0afa6c5238357edb555a77d (diff) | |
download | initscripts-7e28ab4bc109ab4440751fe3a4cb44365ccb2301.tar initscripts-7e28ab4bc109ab4440751fe3a4cb44365ccb2301.tar.gz initscripts-7e28ab4bc109ab4440751fe3a4cb44365ccb2301.tar.bz2 initscripts-7e28ab4bc109ab4440751fe3a4cb44365ccb2301.tar.xz initscripts-7e28ab4bc109ab4440751fe3a4cb44365ccb2301.zip |
Various ipdates to ipcalc to make it more useful.
0 is a perfectly good prefix length. All the cool default routes use it.
Autodetect if we are passed an IPv6 address and shift modes accordingly.
Check prefixes as well as addresses when checking for validity.
Diffstat (limited to 'src/ipcalc.c')
-rw-r--r-- | src/ipcalc.c | 69 |
1 files changed, 42 insertions, 27 deletions
diff --git a/src/ipcalc.c b/src/ipcalc.c index ebb7f61a..6f1be64b 100644 --- a/src/ipcalc.c +++ b/src/ipcalc.c @@ -65,7 +65,11 @@ struct in_addr prefix2mask(int prefix) { struct in_addr mask; memset(&mask, 0, sizeof(mask)); - mask.s_addr = htonl(~((1 << (32 - prefix)) - 1)); + if (prefix) { + mask.s_addr = htonl(~((1 << (32 - prefix)) - 1)); + } else { + mask.s_addr = htonl(0); + } return mask; } @@ -80,14 +84,11 @@ struct in_addr prefix2mask(int prefix) { \return the number of significant bits. */ int mask2prefix(struct in_addr mask) { - int i; - int ipbits = sizeof(struct in_addr) * 8; - int count = ipbits; - uint32_t saddr = mask.s_addr; - - for (i = 0; i < ipbits; i++) { - if (!(ntohl(saddr) & ((2 << i) - 1))) - count--; + int count; + uint32_t saddr = ntohl(mask.s_addr); + + for (count=0; saddr > 0; count++) { + saddr=saddr << 1; } return count; @@ -224,7 +225,7 @@ int main(int argc, const char **argv) { char namebuf[INET6_ADDRSTRLEN+1]; struct in_addr ip, netmask, network, broadcast; struct in6_addr ip6; - int prefix = 0; + int prefix = -1; char errBuf[250]; struct poptOption optionsTable[] = { { "check", 'c', 0, &doCheck, 0, @@ -270,17 +271,23 @@ int main(int argc, const char **argv) { return 1; } + /* if there is a : in the address, it is an IPv6 address */ + if (strchr(ipStr,':') != NULL) { + familyIPv6=1; + } + if (strchr(ipStr,'/') != NULL) { prefixStr = strchr(ipStr, '/') + 1; prefixStr--; *prefixStr = '\0'; /* fix up ipStr */ prefixStr++; - } else + } else { prefixStr = NULL; + } if (prefixStr != NULL) { prefix = atoi(prefixStr); - if (prefix == 0) { + if (prefix < 0 || ((familyIPv6 && prefix > 128) || (!familyIPv6 && prefix > 32))) { if (!beSilent) fprintf(stderr, "ipcalc: bad prefix: %s\n", prefixStr); return 1; @@ -288,13 +295,13 @@ int main(int argc, const char **argv) { } if (showBroadcast || showNetwork || showPrefix) { - if (!(netmaskStr = (char *) poptGetArg(optCon)) && (prefix == 0)) { + if (!(netmaskStr = (char *) poptGetArg(optCon)) && (prefix < 0)) { if (!beSilent) { fprintf(stderr, "ipcalc: netmask or prefix expected\n"); poptPrintHelp(optCon, stderr, 0); } return 1; - } else if (netmaskStr && prefix != 0) { + } else if (netmaskStr && prefix >= 0) { if (!beSilent) { fprintf(stderr, "ipcalc: both netmask and prefix specified\n"); poptPrintHelp(optCon, stderr, 0); @@ -318,8 +325,18 @@ int main(int argc, const char **argv) { return 1; } + if (!familyIPv4 && !familyIPv6) + familyIPv4 = 1; + + if (familyIPv4 && familyIPv6) { + if (!beSilent) { + fprintf(stderr, "ipcalc: cannot specify both address families\n"); + } + return 1; + } + /* Handle CIDR entries such as 172/8 */ - if (prefix) { + if (prefix >= 0) { char *tmp = ipStr; int i; @@ -341,21 +358,15 @@ int main(int argc, const char **argv) { } } - if (!familyIPv4 && !familyIPv6) - familyIPv4 = 1; - - if (familyIPv4 && familyIPv6) { - if (!beSilent) { - fprintf(stderr, "ipcalc: cannot specify both address families\n"); - } - return 1; - } - if (familyIPv4) { if (inet_pton(AF_INET, ipStr, &ip) <= 0) { if (!beSilent) fprintf(stderr, "ipcalc: bad IPv4 address: %s\n", ipStr); return 1; + } else if (prefix > 32) { + if (!beSilent) + fprintf(stderr, "ipcalc: bad IPv4 prefix %d\n", prefix); + return 1; } else { if (doCheck) return 0; @@ -367,6 +378,10 @@ int main(int argc, const char **argv) { if (!beSilent) fprintf(stderr, "ipcalc: bad IPv6 address: %s\n", ipStr); return 1; + } else if (prefix > 128) { + if (!beSilent) + fprintf(stderr, "ipcalc: bad IPv6 prefix %d\n", prefix); + return 1; } else { if (doCheck) return 0; @@ -392,7 +407,7 @@ int main(int argc, const char **argv) { /* we know what we want to display now, so display it. */ if (showNetmask) { - if (prefix) { + if (prefix >= 0) { netmask = prefix2mask(prefix); } else { netmask = default_netmask(ip); @@ -410,7 +425,7 @@ int main(int argc, const char **argv) { } if (showPrefix) { - if (!prefix) + if (prefix == -1) prefix = mask2prefix(ip); printf("PREFIX=%d\n", prefix); } |