...is hard. It's one thing to learn how to do simple math equations to figure out how many hosts can be on a network or to covert CIDR notation to a quad-dotted submask, but it's completely another thing to write an application in a language you barely speak—especially when this application needs 100% accuracy.

I'm going to give a quick run over of what and why I did it. It'll probably sound way more complicated than it really is.

from the top

I'd first like to mention that my code sucks. Like, sucks bad. It's full of anonymous functions calling themselves immediately after they finish, and the whole thing is around 250 lines when it could easily be around 100. But it works, and the cleaning will come later.

I started by listing all potential submask values. I made a list where I have all values from to, and each value is inside an if statement. Now, this will change in the future when I made it into a for loop and an array of data, but until then if the user inputs a particular submask or /CIDR then it'll write both to the screen.

the hosts

Next I figure out how many hosts the network can hold with this equation:

(p >= 2) ? m.innerHTML = (Math.pow(2, (32 - p)) - 2) + h : m.innerHTML = 0 + h;

That basically says if the CIDR number is greater than zero then take 2, raise it to the power of 32 minus the CIDR number, then subtract two. I subtract the CIDR number from 32 because the CIDR describes the "ON" bits, while the possible hosts are located in the "OFF" bits. Since there's 32 possible bits, I invert the bits by taking the "ON" from the total.

ip classes

This is fairly straight forward. I take the IP the user provides me, split it up into separate parts on the decimals, and store it in an array. I then take the first value in the array and compare it to a set of if statements. If the IP value falls within a certain range, then the corresponding class will be written to the screen.

if ((p >= 0) && (p < 128)) g.innerHTML = "Class A";
if ((p >= 128) && (p < 192)) g.innerHTML = "Class B";
if ((p >= 192) && (p < 224)) g.innerHTML = "Class C";
if ((p >= 224) && (p < 240)) g.innerHTML = "Class D";
if ((p >= 240) && (p < 256)) g.innerHTML = "Class E";

the hard part

If I was writing this in C or Python there are packages I could use to convert an int -> bin. Then I could use basic functions to do some math, then convert the bin -> int. However, the closest JavaScript can do is parseInt(string, radix).toString(base). That sucks. It's saying to parse this string as an integer with the radix you pass it, then convert that to a string with whatever base you specified.

It doesn't work very well, especially when you're doing some math while trying to convert the specific values you want to binary. Instead of doing that, I decided to do a slightly more rudimentary method.

What I do is pretend I'm using binary, but use the CIDR number instead. Since the CIDR denotes the "ON" bits, and we know there's 32 bits total, the CIDR will tell us how many octets are filled with "ON" bits. Each bit inside an octet's value will be, from right to left, 1, 2, 4, 8, 16, 32, 64, and 128.

My favorite JavaScript operator is the modulo (%). It works like the division sign, but instead of returning how many times the divisor goes into the dividend, it returns what's left over after you evenly divide the numbers. 10 % 8 will return 2. 142 % 1 = 0. 10 % 3 = 1.

If we take the CIDR number % 8, it'll tell us how many "ON" bits are left over after we get past all the filled octets. Once we've determined that number, we'll have to figure out how to make it usable.

Even though we know the bits values and the number of bits, everything's backwards. In order to save ourselves from writing unnecessary code (lol), we'll do something like this:

foo = 8 - bar,
baz = (Math.pow(2, foo)),

The number we're looking for is 'baz'. The number we got from the modulo is 'bar'. 'Foo' is going to be the middle number—the one we use to do some fun math.

If we subtract our modulo from 8, we get the opposite side of the spectrum. We then need to get the correct bit value, which will be 2 to the power of the bit position. This will give us the bit value we want, which in turn lets us figure out the network ID.

If you're doing everything by hand, usually you'd add the bit value to itself until it's less than or equal to the respective IP segment (e.g. /8 would the third IP segment, a /4 the second, and so on). But we can do that without using any loops. Just take the IP segment's value, divide it by the bit value, use Math.floor in order to ignore the remainder, and then we can multiply that value by the bit value. This will give us the max value we can use without going into a new network. The broadcast bit value is one less than the network bit value.

x = (Math.floor(a[0] / F)),
e = x * F,
c = e + l;

maximum subnets

The maximum subnets a submask can be described like this:

(Math.floor(Math.pow(2, (r - n))))

Where r is the CIDR number and n is the number of full octets. And that's about it.

all together now

In short, it was a great learning experience. I learned how to write better JavaScript (I'm in the process of reworking my code to make it much, much better). I learned CIDR notation and how to properly subnet networks. I also learned that I can easily lose track of time and be up until 3 A.M. trying to get what I'm working on to work correctly. Zzzzz.

| |
comments powered by Disqus