ip_matcher_ranges.mjs 2.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. #!/usr/bin/env node
  2. // @ts-check
  3. import minimist from 'minimist'
  4. import { fileURLToPath } from 'node:url'
  5. /**
  6. * Converts an integer to its corresponding IPv4 address string representation
  7. *
  8. * @param {number} int
  9. * @returns {string}
  10. */
  11. const intToIp = int =>
  12. [
  13. (int >>> 24) & 0xff,
  14. (int >>> 16) & 0xff,
  15. (int >>> 8) & 0xff,
  16. int & 0xff,
  17. ].join('.')
  18. /**
  19. * Convert CIDR to IP range
  20. *
  21. * @param {string} cidr
  22. * @returns {{min: string, max: string}}
  23. */
  24. const cidrToRange = cidr => {
  25. const [ip, prefixLength] = cidr.split('/')
  26. const prefix = parseInt(prefixLength)
  27. // Convert IP to 32-bit integer
  28. const ipParts = ip.split('.').map(part => parseInt(part))
  29. const ipInt =
  30. (ipParts[0] << 24) + (ipParts[1] << 16) + (ipParts[2] << 8) + ipParts[3]
  31. // Calculate network mask
  32. const mask = (0xffffffff << (32 - prefix)) >>> 0
  33. // Calculate network and broadcast addresses
  34. const network = (ipInt & mask) >>> 0
  35. const broadcast = (network | (0xffffffff >>> prefix)) >>> 0
  36. return {
  37. min: intToIp(network),
  38. max: intToIp(broadcast),
  39. }
  40. }
  41. /**
  42. * Converts an array of CIDR ranges into a single string representation.
  43. * Each CIDR range is converted into its corresponding minimum and maximum IP range,
  44. * formatted as "min..max". All resultant ranges are joined by a comma.
  45. *
  46. * @param {string[]} cidrRanges - An array of CIDR range strings to be converted.
  47. * @returns {string} A string representation of the converted ranges where each
  48. * range is formatted as "min..max" and joined by commas.
  49. */
  50. export const convertCidrRanges = cidrRanges =>
  51. cidrRanges
  52. .map(cidr => {
  53. const range = cidrToRange(cidr)
  54. return `${range.min}..${range.max}`
  55. })
  56. .join(',')
  57. // Only run CLI if this file is executed directly
  58. if (fileURLToPath(import.meta.url) === process.argv[1]) {
  59. const argv = minimist(process.argv.slice(2))
  60. if (argv._.length === 0) {
  61. console.log('Usage: node scripts/ip_matcher_ranges.mjs <cidr1> [cidr2] ...')
  62. console.log(
  63. 'Example: node scripts/ip_matcher_ranges.mjs 192.168.1.0/24 10.0.0.0/8'
  64. )
  65. process.exit(1)
  66. }
  67. console.log(convertCidrRanges(argv._))
  68. }