Author Topic: CIDR check  (Read 1885 times)

0 Members and 1 Guest are viewing this topic.

Offline Xires

  • Noob Eater
  • Administrator
  • Knight
  • *
  • Posts: 379
  • Cookies: 149
    • View Profile
    • Feed The Trolls - Xires
CIDR check
« on: July 17, 2013, 12:10:33 pm »
This is a small program that I wrote to include in a networking library for work so that we could do some quick-ish network checks & generate network ranges for IP addresses found in the config file.  One important part was ensuring that we could read & generate a network range for IPs entered either by themselves(assuming a /32), with CIDR or with dotted-quad netmask.
Code: (c) [Select]
/* cidr.c - v1.5 : 2013-07-17 - Xires <xires012@gmail.com>
 *
 * COMPILE: gcc -Wall -Wextra -W -ansi -o cidr{,.c}
 *
 * RUN:
 *   ./cidr <IPADDR>[/(CIDR|NETMASK)]
 *      IPADDR   = dotted-quad IP address
 *      CIDR   = CIDR mask
 *      NETMASK = dotted-quad netmask
 *
 * NOTE:
 *      -pedantic cannot be used because of the %hh type-conversion specifier
 *      This code tries to maintain network-byte-order (big-endian).
 *      This code is meant to be run on a little-endian system.
 */
#include <stdio.h>      /* for I/O */
#include <stdint.h>      /* uint8_t */
#include <arpa/inet.h>   /* ntohl() */

/* msk2int():
 * shift 0xFFFFFFFF(32 'on' bits) right by 'n' places
 * return the negation('on' bits become 'off', 'off' bits become 'on')
 *
 * 11111111 11111111 11111111 11111111 >> 24
 * 00000000 00000000 00000000 11111111
 *
 *~00000000 00000000 00000000 11111111
 * 11111111 11111111 11111111 00000000
 */
#define msk2int(n) ((unsigned int) ~(0xFFFFFFFFUL >> n))
#define cnt_bits(n) seander(n)   /* modularity; replace seander() with new alg */

/* a union lets us represent the same section of memory in multiple ways */
union ipv4_u {   /* represents an IPv4 address */
   uint8_t         oct[4];   /* each octet of dotted-quad representation */
   unsigned int   ipl;   /* single 32-bit representation */
};

typedef struct cidr_s {   /* a netblock */
   union ipv4_u   ipv4;   /* IP address */
   union ipv4_u   mask;   /* netmask */
   union ipv4_u   bgn;   /* beginning of network */
   union ipv4_u   end;   /* end/broadcast of network */
} cidr_t;

/* Seander is a known bit-counting algorithm */
unsigned int seander(unsigned int n) {   /* counts the bits that are 'on' */
   n = n - ((n >> 1) & 0x55555555);
   n = (n & 0x33333333) + ((n >> 2) & 0x33333333);
   return(
      (
         (
            (
               n + (n >> 4)
            ) & 0xF0F0F0F
         ) * 0x1010101
      ) >> 24
   );
}

int main(int argc, char **argv) {
   int      cnt = 0;   /* number of items read from sscanf() operation */
   cidr_t   cidr;      /* the netblock we're working with */

   if (argc < 2) return (fprintf(stderr, "Must supply CIDR argument.\n"), 1);

   cnt = sscanf(   /* sscanf() returns number of input items read */
      argv[1],
      "%hhu.%hhu.%hhu.%hhu/%hhu.%hhu.%hhu.%hhu",
      &cidr.ipv4.oct[3],
      &cidr.ipv4.oct[2],
      &cidr.ipv4.oct[1],
      &cidr.ipv4.oct[0],
      &cidr.mask.oct[3],
      &cidr.mask.oct[2],
      &cidr.mask.oct[1],
      &cidr.mask.oct[0]
   );   /* maybe reverse scan order for big-endian systems */

   switch (cnt) {   /* check the number of arguments read */
      case 4:
         cidr.mask.ipl = 32;   /* A.B.C.D */
      case 5:               /* A.B.C.D/CIDR */
         cidr.mask.ipl = msk2int(ntohl(cidr.mask.ipl));   /* reinterpret mask */
         break;
      case 8:               /* A.B.C.D/W.X.Y.Z */
         break;
      default:            /* anything else */
         return (fprintf(stderr, "Invalid CIDR argument: %u\n", cnt), ~cnt);
   }

   cidr.bgn.ipl = (cidr.ipv4.ipl & cidr.mask.ipl);   /* only keep useful bits */
   cidr.end.ipl = ((cidr.ipv4.ipl & cidr.mask.ipl) | ~cidr.mask.ipl); /* max */

   /* test reports */
   printf(   /* spit everything out, in proper order */
      "IP:\t%u.%u.%u.%u\nMsk:\t%u.%u.%u.%u\nBgn:\t%u.%u.%u.%u\nEnd:\t%u.%u.%u.%u\n",
      cidr.ipv4.oct[3],
      cidr.ipv4.oct[2],
      cidr.ipv4.oct[1],
      cidr.ipv4.oct[0],
      cidr.mask.oct[3],
      cidr.mask.oct[2],
      cidr.mask.oct[1],
      cidr.mask.oct[0],
      cidr.bgn.oct[3],
      cidr.bgn.oct[2],
      cidr.bgn.oct[1],
      cidr.bgn.oct[0],
      cidr.end.oct[3],
      cidr.end.oct[2],
      cidr.end.oct[1],
      cidr.end.oct[0]
   );

   printf(   /* spit out unsigned int representations; big-endian */
      "IP:\t%u\nMsk:\t%u\nBgn:\t%u\nEnd:\t%u\n",
      cidr.ipv4.ipl,
      cidr.mask.ipl,
      cidr.bgn.ipl,
      cidr.end.ipl
   );

   printf(   /* output possible CIDR entries for conf file */
      "conf:\t%u.%u.%u.%u/%u\n\t%u.%u.%u.%u/%u\n",
      cidr.ipv4.oct[3],
      cidr.ipv4.oct[2],
      cidr.ipv4.oct[1],
      cidr.ipv4.oct[0],
      cnt_bits(cidr.mask.ipl),
      cidr.bgn.oct[3],
      cidr.bgn.oct[2],
      cidr.bgn.oct[1],
      cidr.bgn.oct[0],
      cnt_bits(cidr.mask.ipl)
   );

   return 0;
}
« Last Edit: July 17, 2013, 04:34:28 pm by Xires »
-Xires

Offline Deque

  • P.I.N.N.
  • Global Moderator
  • Overlord
  • *
  • Posts: 1203
  • Cookies: 518
  • Programmer, Malware Analyst
    • View Profile
Re: CIDR check
« Reply #1 on: July 17, 2013, 12:51:42 pm »
Ha, I really don't know much when it comes to networking. So sorry for the lack of feedback from my side. The code looks pretty well written (which isn't a surprise). I can't help but give you a cockie cookie.
« Last Edit: July 17, 2013, 06:45:31 pm by Deque »

Offline Xires

  • Noob Eater
  • Administrator
  • Knight
  • *
  • Posts: 379
  • Cookies: 149
    • View Profile
    • Feed The Trolls - Xires
Re: CIDR check
« Reply #2 on: July 17, 2013, 12:55:49 pm »
Thanks, though I think I'd prefer cookies to cockies.

Anywho..source updated with some comments.  Anyone with questions should feel free to ask(as always).
-Xires

Offline Deque

  • P.I.N.N.
  • Global Moderator
  • Overlord
  • *
  • Posts: 1203
  • Cookies: 518
  • Programmer, Malware Analyst
    • View Profile
Re: CIDR check
« Reply #3 on: July 17, 2013, 06:46:09 pm »
Thanks, though I think I'd prefer cookies to cockies.

Anywho..source updated with some comments.  Anyone with questions should feel free to ask(as always).

 ;D Sorry for the misspelling.

Offline bluechill

  • Cybermancer
  • Royal Highness
  • ****
  • Posts: 682
  • Cookies: 344
  • I am the existence in these walls
    • View Profile
Re: CIDR check
« Reply #4 on: July 21, 2013, 05:20:02 am »
Thanks, though I think I'd prefer cookies to cockies.

Why wouldn't you like cocks? they're fun right? right?
I have dreamed a dream, but now that dream has gone from me.  In its place now exists my own reality, a reality which I have created for myself by myself.

Offline Xires

  • Noob Eater
  • Administrator
  • Knight
  • *
  • Posts: 379
  • Cookies: 149
    • View Profile
    • Feed The Trolls - Xires
Re: CIDR check
« Reply #5 on: July 22, 2013, 09:10:49 am »
Why wouldn't you like cocks? they're fun right? right?

They're just not to my taste.
-Xires