## Introduction

In the second part of the article, I will try to explain functions I used inside the application together with a technique for how to find adjacent subnets.

**(Follow the link for the first part of this article: Subnetting with IPv6 Part 1/2[^] )**

## About this Application

First start by checking the entered value to see either the user entered a valid IPv6 address or not. For this purpose, the function `IsAddressCorrect()`

** **gets the entered `string`

, and does the necessary checks on it, and returns either **'**`true`

**'** or **'**`false`

**'** boolean value depending on the check result.

public boolean IsAddressCorrect(String sin) {
int nDC = 0;
int nC = 0;
sin = sin.trim();
String s = sin;
char[] chars = s.toCharArray();
if (s.isEmpty()) {
errmsg = "> Empty address";
return false;
}
if (s.equals("::")) {
errmsg = "> Undefined";
return false;
}
if ((s.length() <= 1) || (s.contains(":::"))) {
errmsg = "> Not valid";
return false;
}
if (!Pattern.matches("^[0-9A-Fa-f:]+$", s)) {
errmsg = "> Not valid hex-digit";
return false;
}
if (chars[0] == ':' && chars[1] != ':') {
errmsg = "> Not valid: ':'";
return false;
}
if (chars[s.length() - 1] == ':' && chars[s.length() - 2] != ':') {
errmsg = "> Not valid: ':'";
return false;
}
String[] sa = s.split(":", -1);
for (int j = 0; j < sa.length; j++) {
if (sa[j].length() > 4) {
errmsg = "> More than 2 bytes";
return false;
}
}
s = sin;
nDC = s.split("::", -1).length - 1;
s = s.replace("::", "**");
nC = s.split(":", -1).length - 1;
if (nDC > 1) {
errmsg = "> DoubleColon can only appear once";
return false;
}
if (nDC == 0 && nC != 7) {
errmsg = "> Not valid, there must be 7 colons";
return false;
}
s = sin;
int sL = s.length();
if ((chars[0] == ':' && chars[1] == ':')
|| (chars[sL - 1] == ':' && chars[sL - 2] == ':')) {
if (nDC == 1 && nC > 6) {
errmsg = "> Excessive colons";
return false;
}
}
else if (nDC == 1 && nC > 5) {
errmsg = "> Excessive colons";
return false;
}
errmsg = "> ok";
return true;
}

If the entered value is a valid IPv6 address, then we need to formalize the entered address into 16 Bytes hexadecimal value in order to perform our calculations on it. The function `FormalizeAddress()`

gets a valid IPv6 address as `string`

, places the necessary amount of zeros if the address is compressed, and then returns 16 Bytes formal IPv6 address as `BigInteger`

data type.

public BigInteger FormalizeAddr(String sin) {
String[] Resv6 = new String[]{"0000", "0000", "0000",
"0000", "0000", "0000",
"0000", "0000"};
BigInteger Finalv6 = BigInteger.ZERO;
sin = sin.trim();
String s = sin;
String[] sa = s.split(":", -1);
int nC = 0;
s = s.replace("::", "**");
nC = s.split(":", -1).length - 1;
for (int k = 0; k < sa.length; k++) {
if (sa[k].length() == 0) {
continue;
} else {
sa[k] = String.format("%4s", sa[k]).replace(' ', '0');
}
}
if ((sa[sa.length - 1].length() == 0)
&& (sa[sa.length - 2].length() == 0)) {
int t = nC + 1;
for (int i = 0; i < t; i++) {
Resv6[i] = sa[i];
}
} else if (sa[0].length() == 0 && sa[1].length() == 0) {
int t = nC + 1;
for (int i = 0; i < t; i++) {
Resv6[7 - i] = sa[sa.length - 1 - i];
}
} else {
int idx = Arrays.asList(sa).indexOf("");
for (int i = 0; i < idx; i++) {
Resv6[i] = sa[i];
}
for (int i = 0; i < sa.length - idx - 1; i++) {
Resv6[7 - i] = sa[sa.length - 1 - i];
}
}
s = "";
for (int i = 0; i < 8; i++) {
s += Resv6[i];
}
Finalv6 = new BigInteger(s, 16);
return Finalv6;
};

These two functions above may also be combined in a **general class library** to validate and formalize an IPv6 address but *I did not do it here*. Instead I wrote them in a separate class, for the sake of keeping the functions of the application **simple and visible for everybody**.

As I try to explain in the 'Subnetting with IPv6 Part1/2' article, it is easy and obvious to find the subnet start and end addresses of a given address by using the /prefix-length value. The function `StartEndAddresses()`

below takes an IPv6 address and returns the subnet start and end addresses inside `SEaddress`

object.

public SEaddress StartEndAddresses(SEaddress input) {
BigInteger mask = new BigInteger("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 16);
mask = mask.shiftRight(input.slash);
input.End = mask.or(input.Resultv6);
mask = mask.not();
input.Start = mask.and(input.Resultv6);
return input;
}

where `SEaddress`

is a storage object:

public class SEaddress {
public BigInteger Resultv6 = BigInteger.ZERO;
public BigInteger Start = BigInteger.ZERO;
public BigInteger End = BigInteger.ZERO;
public int slash = 0;
public int subnetslash = 0;
public BigInteger subnetidx = BigInteger.ZERO;
}

Another issue is how to find the neighboring or adjacent subnet addresses, or subnets that comes just after our subnet? In other words, how can we **move or walk through the adjacent subnet address spaces?**

Very easy and simple way of achieving this is to get the end address, and increment by one which gives the start address of the adjacent subnet address. By using this start address, find the end address, then increment by one which will give the second adjacent subnet address, and so on. As you notice, we are now able to move or walk through the subnet address spaces with this algorithm.

An iterative procedure to obtain the adjacent subnet addresses might be:

**Step 1.** Get the IPv6 address **Step 2.** Find the subnet start address **Step 3.** Find the subnet end address **Step 4.** Increment the subnet end address by one. The start address of the next subnet obtained. **Step 5.** Go to step 3 with the address found in Step 4

For the subnetting, we borrow the bits by using the second slider or track bar. Despite the fact that we can easily find our subnets, now another question is what is the index number of our subnet and how can we find the index number of it? i.e. is it 4^{th} subnet, or 5^{th}, or 6^{th}, or which?

The answer is **inside the address** itself and we can extract this index number from the address.

Actually, using the second slider, i.e. borrowing the bits, we are creating the subnet index numbers, too.

The interval between the two sliders has our subnet index number. For example, if we drag the first slider to /48 and the second slider to /52, it means that we borrow 4-bits and created 2^{4}=16 different subnets having index values from 0 to 15.

So how can we handle finding the index value in our application? We can copy the bits in this interval by means of testing the bits and then setting it into our index variable. For testing the bit, we can perform the bitwise operation **(number &(1<< i ))**, where i is an integer to shift. If the result is 1, then the bit at that position is 1, otherwise it is zero.

The code might be (this little part is also inside the `StartEndAddresses()`

function):

input.subnetidx = BigInteger.ZERO;
int delta = input.subnetslash - input.slash - 1;
for (int i = (127 - input.slash); i > (127 - input.subnetslash); i--) {
if (input.Start.testBit(i) == true) {
input.subnetidx = input.subnetidx.setBit(delta);
}
else {
input.subnetidx = input.subnetidx.clearBit(delta);
}
delta--;
}
return input;

Up to this point, we know how to find the subnet start/end addresses and subnet indexes. What is left is to produce these values in a simple for loop with an 'upto' limit variable, e.g. :

for (count = 0; count < upto; count++) {
subnets = Subnetting(subnets);
subnets.Start = subnets.End.add(BigInteger.ONE);
}

## History

- 29 September 2013, v1.0
- 16 November 2013, C# v1.1 : Added new v1.8 C# application.
- 12 December 2013, C# v1.2 : A few typing corrections and added v1.10 C# application.
- 26 January 2014, C# v1.3 : Added new v1.11 C# application.
- 15 October 2017, C# v3.6 : Added new/updated C# application.
- 13 November 2017, Java v2.0 : Added new v2.0 Java application based on JavaFX. a