IP Range To CIDR Convertor

// Convert a given Ip range to CIDR notation.

# cat  rangeToCidr

  1. /* rangeToCidr.c - Convert Ip ranges to CIDR */ 
  2.  
  3. /* 
  4. modification history http://snippets.dzone.com/tag/cidr
  5. -------------------- 
  6. 01a,17sep08,karn written 
  7. */ 
  8.  
  9. /* includes */ 
  10.  
  11. #include<stdio.h> 
  12. #include<unistd.h> 
  13. #include<string.h> 
  14. #include<math.h> 
  15. #include<errno.h> 
  16. #include <sys/socket.h> 
  17. #include <netinet/in.h> 
  18. #include <arpa/inet.h> 
  19.  
  20. /* defines */ 
  21. //#define DBG 
  22. #ifdef DBG 
  23. #define DEBUG(x) fprintf(stderr,x) 
  24. #else 
  25. #define DEBUG 
  26. #endif /* DBG */ 
  27.  
  28. #define IP_BINARY_LENGTH 32+1  /* 32 bits ipv4 address +1 for null */ 
  29. #define IP_HEX_LENGTH    10    
  30. #define MAX_CIDR_MASK    32 
  31. #define MAX_CIDR_LEN     18+1   /*255.255.255.255/32*/ 
  32.  
  33. /* Forward declaratopms */ 
  34. void rangeToCidr(uint32_t from ,uint32_t to, 
  35.                  void (callback)(char *cidrNotation)); 
  36. int ipToBin(uint32_t ip , char * pOut); 
  37.  
  38. void printNotation(char *cidrNotation); 
  39.  
  40. /* Globals */ 
  41.  
  42.  
  43. /******************************************************************************* 
  44. * 
  45. * ipToBin - convert an ipv4 address to binary representation  
  46. *           and pads zeros to the beginning of the string if  
  47. *           the length is not 32  
  48. *           (Important for ranges like 10.10.0.1 - 20.20.20.20 ) 
  49. * 
  50. * ip   - ipv4 address on host order 
  51. * pOut - Buffer to store binary. 
  52. * 
  53. * RETURNS: OK or ERROR  
  54. */ 
  55.  
  56. int ipToBin(uint32_t ip , char * pOut) 
  57.     { 
  58.     char hex[IP_HEX_LENGTH]; 
  59.     int i; 
  60.     int result=0; 
  61.     int len; 
  62.     char pTmp[2]; 
  63.     int tmp; 
  64.     /* 
  65.      * XXX: Could use bit operations instead but was easier to debug 
  66.      */ 
  67.     char binMap[16][5] = {  
  68.                         "0000","0001","0010","0011""0100"
  69.                         "0101","0110","0111","1000""1001"
  70.                         "1010","1011","1100""1101","1110","1111"
  71.                         }; 
  72.     pTmp[1]=0x0; 
  73.     memset(hex,0x0,sizeof(hex)); 
  74.     len=sprintf(hex,"%x",ip); 
  75.  
  76.     for(i=0;i<len;i++) 
  77.         { 
  78.  
  79.         /* Ugly but to use strtol , we need the last byte as null */ 
  80.         pTmp[0]=hex[i]; 
  81.  
  82.         errno = 0; 
  83.         tmp = strtol(pTmp, 0x0, 16); 
  84.  
  85.         /* Should not happen */ 
  86.         if (errno != 0) 
  87.             { 
  88.             memset(pOut,'0',IP_BINARY_LENGTH -1); 
  89.             DEBUG ("strtol failed for hex 0x%s\n",pTmp); 
  90.             return -1; 
  91.             } 
  92.  
  93.         result+=sprintf(pOut+result,"%s",binMap[tmp]); 
  94.         } 
  95.  
  96.         DEBUG("bits %u printed for ip address for hex len %u\n",result,len); 
  97.         /* if length is not 32 , pad the start with zeros*/ 
  98.  
  99.     if(result < IP_BINARY_LENGTH-1) 
  100.         { 
  101.         char pSwap[IP_BINARY_LENGTH]; 
  102.         strncpy(pSwap,pOut,IP_BINARY_LENGTH); 
  103.         memset(pOut,'0',IP_BINARY_LENGTH); 
  104.         strncpy(pOut+IP_BINARY_LENGTH-1-result,pSwap,result); 
  105.         DEBUG("corrected length to 32\n"); 
  106.         } 
  107.  
  108.     else if (result > IP_BINARY_LENGTH-1) 
  109.         return -1; 
  110.  
  111.     /* Success */ 
  112.     return 0; 
  113.     } 
  114.  
  115. /******************************************************************************* 
  116. *  main :  
  117.  
  118. *  arg1 : Start Ip Address 
  119. *  arg2 : End Ip address 
  120. */ 
  121.  
  122. int main (int argc,char **argv) 
  123.     { 
  124.     long fromIp, toIp; 
  125.     struct in_addr addr; 
  126.     if(argc !=3 ) 
  127.         { 
  128.         printf("Usage: %s <from> <to>\n",argv[0]); 
  129.         return(0); 
  130.         } 
  131.  
  132.     /* All operation on host order */    
  133.     if (inet_aton(argv[1],&addr) == 0) 
  134.         goto error; 
  135.     fromIp = ntohl(addr.s_addr); 
  136.  
  137.     if (inet_aton(argv[2],&addr) ==0) 
  138.         goto error; 
  139.     toIp = ntohl(addr.s_addr); 
  140.  
  141.     rangeToCidr(fromIp,toIp,printNotation); 
  142.  
  143.     return 0; 
  144. error: 
  145.     printf("Invalid Argument\n"); 
  146.     return -EINVAL; 
  147.     } 
  148.  
  149.  
  150. /******************************************************************************* 
  151. * 
  152. * rangeToCidr - convert an ip Range to CIDR, and call 'callback' to handle 
  153. *               the value.  
  154. * 
  155. * from     - IP Range start address 
  156. * to       - IP Range end address 
  157. * callback - Callback function to handle cidr. 
  158. * RETURNS: OK or ERROR  
  159. */ 
  160.  
  161. void rangeToCidr(uint32_t from ,uint32_t to, 
  162.                  void (callback)(char *cidrNotation)) 
  163.     { 
  164.     int     cidrStart = 0; 
  165.     int     cidrEnd = MAX_CIDR_MASK - 1; 
  166.     long    newfrom; 
  167.     long    mask; 
  168.     char    fromIp[IP_BINARY_LENGTH]; 
  169.     char    toIp[IP_BINARY_LENGTH]; 
  170.     struct  in_addr addr; 
  171.     char    cidrNotation[MAX_CIDR_LEN]; 
  172.  
  173.     memset (fromIp,0x0,sizeof(fromIp)); 
  174.     memset (toIp,0x0,sizeof(toIp)); 
  175.  
  176.     if ( ipToBin(from,fromIp) != 0 )  
  177.         return
  178.     if ( ipToBin(to,toIp) != 0 ) 
  179.         return
  180.  
  181.     DEBUG ("from %lu to %lu\n", from,to); 
  182.     DEBUG("from %s\n",fromIp); 
  183.     DEBUG("to   %s\n",toIp); 
  184.  
  185.     if(from < to ) 
  186.         { 
  187.  
  188.         /* Compare the from and to address ranges to get the first 
  189.          * point of difference 
  190.          */ 
  191.  
  192.         while(fromIp[cidrStart]==toIp[cidrStart]) 
  193.             cidrStart ++; 
  194.         cidrStart = 32 - cidrStart -1 ; 
  195.         DEBUG("cidrStart is %u\n",cidrStart); 
  196.  
  197.         /* Starting from the found point of difference make all bits on the  
  198.          * right side zero  
  199.          */ 
  200.  
  201.         newfrom = from >> cidrStart +1  << cidrStart +1 ;         
  202.  
  203.         /* Starting from the end iterate reverse direction to find  
  204.          * cidrEnd 
  205.          */  
  206.         while( fromIp[cidrEnd] == '0' && toIp[cidrEnd] == '1'
  207.             cidrEnd --; 
  208.  
  209.         cidrEnd = MAX_CIDR_MASK - 1 - cidrEnd; 
  210.         DEBUG("cidrEnd is %u\n",cidrEnd); 
  211.  
  212.         if(cidrEnd <= cidrStart) 
  213.             { 
  214.             /*  
  215.              * Make all the bit-shifted bits equal to 1, for 
  216.              * iteration # 1. 
  217.              */ 
  218.              
  219.             mask = pow (2, cidrStart ) - 1; 
  220.             DEBUG("it1 is %lu \n",newfrom | mask ); 
  221.             rangeToCidr (from , newfrom | mask, callback); 
  222.             DEBUG("it2 is %lu \n",newfrom | 1 << cidrStart); 
  223.             rangeToCidr (newfrom | 1 <<  cidrStart ,to ,callback); 
  224.             } 
  225.         else 
  226.             { 
  227.             addr.s_addr = htonl(newfrom); 
  228.             sprintf(cidrNotation,"%s/%d",  
  229.                     inet_ntoa(addr), MAX_CIDR_MASK-cidrEnd); 
  230.             if (callback != NULL) 
  231.                 callback(cidrNotation); 
  232.             } 
  233.         } 
  234.  
  235.     else 
  236.         { 
  237.         addr.s_addr = htonl(from); 
  238.         sprintf(cidrNotation,"%s/%d",inet_ntoa(addr),MAX_CIDR_MASK); 
  239.         if(callback != NULL) 
  240.             callback(cidrNotation); 
  241.         } 
  242.     } 
  243.  
  244. /******************************************************************************* 
  245. * 
  246. * printNotation - This is an example callback function to handle cidr notation.  
  247. * 
  248. * RETURNS: 
  249. */ 
  250.  
  251. void printNotation(char *cidrNotation) 
  252.     printf("%s\n",cidrNotation); 

编译:

# gcc rangeToCidr.c -lm -o rang2cidr

Perl版本:

  1. #!/usr/bin/perl -w 
  2. # range2cidr.pl 
  3.  
  4. use Net::CIDR; 
  5. use Net::CIDR ':all'
  6.  
  7. if (@ARGV == 0) { 
  8.   die "Usage Example: $0 192.168.0.0-192.168.255.255 \n"
  9.  
  10. print join("\n", Net::CIDR::range2cidr("$ARGV[0]")) . "\n"

本日志由 flyinweb 于 2011-01-28 11:06:29 发表到 Linux 中,目前已经被浏览 1776 次,评论 0 次;

作者添加了以下标签: rangeToCidrrange2cidr

首页只显示了部分日志内容,要查看日志的全部内容请阅读全文