Creating a protocol running at layer 3, may be a hard task. But there are
times where it needs to be done quick and easy, i.e for testing protocol before
implementing it directly to the operating system's kernel. Jpcap is a
open-source, multi platform Java libray that allows protocol designers to implement
their protocol amazingly fast.
Before start using Jpcap, WinPcap and Java SDK must be installed. Jpcap wan be downloaded from
here. The protocol that is going to be implemented is very simple.
It runs over Ethernet and it uses as addresses real names. The protocol is named
MyProtocol. The following topology is going to be used:
PC1: PC2:
mac address:00:03:0d:2e:79:68 -|switch|-mac address:00:90:96:1d:62:f8
MyProtocol address:Alice MyProtocol address:Bob
A MyProtocol packet consists of a header and a body. The
header has an 1 byte field for the local address length, an 1 byte field for the
remote address legth, the local address and the remote address. The body just
contains some data. In this example PC1 (Alice) will send "HELLO" to PC2 (Bob).
The code for the client is quite straightforward. Initially a
the network interface to be used is located, then the ethernet packet that will
carry the MyProtocol packet is constructed and finally the MyProtocol packed is
constructed. The code for the client follows
import java.util.Arrays;
import jpcap.*;
import jpcap.packet.*;
public class MyProtocol {
public static void main (String args[]){
//The local mac address
final byte[] localMacAddress ={0x00,0x03,0x0d,0x2e,0x79,0x68};
//The remote mac address
final byte[] remoteMacAddress={0x00,(byte)0x90,(byte)0x96,0x1d,0x62,(byte)0xf8};
//The index in the network interfaces list that holds the local device
int localDeviceIndex =-1;
//Obtain the list of network interfaces
NetworkInterface[] devices = JpcapCaptor.getDeviceList();
//Find the local device to use
for (int i = 0; i < devices.length; i++){
if (Arrays.equals(devices[i].mac_address,localMacAddress))
localDeviceIndex = i;
}
//Check wheather an interface with mac address same as the local mac
//address has been found
if (localDeviceIndex ==-1){ //it has not been found, break execution
System.out.println("A network interface with address equal " +
"to localMacAddress has not been found");
System.exit(-1);
}
//Create the data link packet
EthernetPacket ether=new EthernetPacket();
//Set the source address
ether.src_mac = localMacAddress;
//Set the destination address
ether.dst_mac = remoteMacAddress;
//Set the type code to a not common used value
ether.frametype = 0x0890;
//Create our protocol packet
/* Create a header. The header is of the form
*
* local address legth|remote address legth|local address|remote address
* 1 byte | 1 byte | n bytes | n bytes
*
* Suppose that the local address is Alice and the remote is Bob
*/
final byte[] myProtLcAddr = "Alice".getBytes();
final byte[] myProtRmAddr = "Bob".getBytes();
byte[] header = new byte[myProtLcAddr.length + myProtRmAddr.length + 2];
header[0] = (byte)myProtLcAddr.length;
header[1] = (byte)myProtRmAddr.length;
System.arraycopy(myProtLcAddr, 0, header, 2, myProtLcAddr.length);
System.arraycopy(myProtRmAddr, 0, header, 2 + myProtLcAddr.length, myProtRmAddr.length);
//Create the body. The body is just a hello message
byte[] body ="HELLO".getBytes();
//Build the packet
Packet packet = new Packet();
//Add the header and the body tou the packet
byte[] data = new byte[header.length + body.length];
System.arraycopy(header, 0, data, 0, header.length);
System.arraycopy(body, 0, data, header.length, body.length);
packet.data = data;
//Add the data link layer
packet.datalink = ether;
//Send the packet
try{
JpcapCaptor captor=JpcapCaptor.openDevice(devices[localDeviceIndex],1514,false,50);
JpcapSender sender = captor.getJpcapSenderInstance();
sender.sendPacket(packet);
System.out.println("Packet send");
}catch(Exception e){
System.out.println("Exception occured " + e.toString());
}
}
}
The server part is even simpler, the network interface is located and it is
set up to listen for specific ethernet type packets. The code follows
import java.util.Arrays;
import jpcap.*;
import jpcap.packet.*;
public class MyProtocolServer {
public static void main (String args[]){
//The local mac address
final byte[] localMacAddress ={0x00,(byte)0x90,(byte)0x96,0x1d,0x62,(byte)0xf8};
//The index in the network interfaces list that holds the local device
int localDeviceIndex =-1;
//Obtain the list of network interfaces
NetworkInterface[] devices = JpcapCaptor.getDeviceList();
//Find the local device to use
for (int i = 0; i < devices.length; i++){
if (Arrays.equals(devices[i].mac_address,localMacAddress))
localDeviceIndex = i;
}
//Check wheather an interface with mac address same as the local mac
//address has been found
if (localDeviceIndex ==-1){ //it has not been found, break execution
System.out.println("A network interface with address equal " +
"to localMacAddress has not been found");
System.exit(-1);
}
//Open the device and loop until a packet of type 0x0890 arrives
try{
JpcapCaptor captor=JpcapCaptor.openDevice(devices[localDeviceIndex],1514,false,50);
captor.setFilter("ether proto 0x0890", true);
boolean continueCapture = true;
while (continueCapture){
Packet packet = captor.getPacket();
if (packet !=null ){ // a packet has been captured
//retreive the sender address. The firt byte stores the length
//and the address starts from the 3rd byte
String remoteAddress = new String(packet.data,2,packet.data[0]);
System.out.println("Hello received from " + remoteAddress);
continueCapture = false;
}
}
}catch(Exception e){
System.out.println("Exception occured " + e.toString());
}
}
}