text: Today's Page Hits: 211Shepler asked me offline why I wasn't looking at inet_ntoa(3SOCKET) for Reversing a network address from an uint_t. His email was dry, but I think there was a "D'oh!" in there somewhere.
  I had considered those routines, but I went with the stuff in mountd because for the standalone, we don't have sockets being attached. In the finished product, I'll be looking at this. Also, since I will need to support IPv6, I'll have more need to not be doing my own parsing. But for right now, I'm going to proceed without IPv6 and without inet_aton(3SOCKET).
  Okay, I did two things with the little network parsing code:
  And here is the code:
  #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/types.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> /* * */ int spe_bitcount (unsigned int n) { int count = 8 * sizeof(int) ; n ^= (unsigned int) -1 ; while (n) { count-- ; n &= (n - 1) ; } return (count); } int main (int argc, char *argv[]) { char *p = argv[1]; char *junk; uint_t addr = 0, mask = 0; uint_t rev; int i; int shift; int t; char sep = ' '; unsigned char b = 0; for (i = 0; i < 4; i++) { t = strtol(p, &junk, 10); if (junk && junk[0] == '/' && i == 3) { b = 1; } else if (junk && junk[0] != '.' && junk[0] != '\0') { fprintf(stderr, "%s is wrong in the %d octet," " %s has non-digits as |%s|\n", argv[1], i+1, p, junk); exit (-1); } else if (t > 255 || t < 0) { fprintf(stderr, "%s is wrong in the %d octet," " %d is out of range\n", argv[1], i+1, t); exit (-1); } addr |= t << ((3-i) * 8); p = strchr(p, '.'); if (p == NULL) break; p++; } if (b) { p = &junk[1]; /* advance over '/' */ t = strtol(p, &junk, 10); if (junk && junk[0] != '\0') { fprintf(stderr, "%s is wrong in the netmask," " %s has non-digits as |%s|\n", argv[1], p, junk); exit (-1); } else if (t < 0 || t > 32) { fprintf(stderr, "%s is wrong in the netmask," " %d is out of range\n", argv[1], t); exit (-1); } mask = t ? ~0 << ((sizeof (struct in_addr) * NBBY) - t) : 0; } else { if ((addr & 0x00ffffff) == 0) mask = 0xff000000; else if ((addr & 0x0000ffff) == 0) mask = 0xffff0000; else if ((addr & 0x000000ff) == 0) mask = 0xffffff00; else mask = 0xffffffff; } printf("%s yields %u (%u) and that reverse maps to ", argv[1], addr, mask); for (i = 0; i < 4; i++) { shift = ((3-i) * 8); rev = (addr & (0xff << shift)) >> shift; printf("%c%u", sep, rev); sep = '.'; } sep = '('; t = 0; for (i = 0; i < 4; i++) { shift = ((3-i) * 8); rev = (mask & (0xff << shift)) >> shift; printf("%c%u", sep, rev); sep = '.'; } t = spe_bitcount(mask); printf(" - %u)\n", t); return (0); }
  And some test runs:
  % ./a.out 192.168.2.0/23 192.168.2.0/23 yields 3232236032 (4294966784) and that reverse maps to 192.168.2.0(255.255.254.0 - 23) % ./a.out 192.168.2.0/24 192.168.2.0/24 yields 3232236032 (4294967040) and that reverse maps to 192.168.2.0(255.255.255.0 - 24) % ./a.out 192.168.2.0/31 192.168.2.0/31 yields 3232236032 (4294967294) and that reverse maps to 192.168.2.0(255.255.255.254 - 31) % ./a.out 192.168.2.0/32 192.168.2.0/32 yields 3232236032 (4294967295) and that reverse maps to 192.168.2.0(255.255.255.255 - 32) % ./a.out 192.168.2.0/0 192.168.2.0/0 yields 3232236032 (0) and that reverse maps to 192.168.2.0(0.0.0.0 - 0) % ./a.out 192.168.2.0/1 192.168.2.0/1 yields 3232236032 (2147483648) and that reverse maps to 192.168.2.0(128.0.0.0 - 1) % ./a.out 192.168.2.0/8 192.168.2.0/8 yields 3232236032 (4278190080) and that reverse maps to 192.168.2.0(255.0.0.0 - 8) % ./a.out 192.168.2.0/33 192.168.2.0/33 is wrong in the netmask, 33 is out of range
  I just need to stuff this code into my prototype.
  If the interfaces unsatisfactory, you could have
  copied the source and made updates instead of
  starting from scratch. :-)
  Posted by Spencer on January 22, 2008 at 03:01 PM CST #