IPv6 and SIP

Project goals

The purpose of this project is to implement an IPv6 tunnel in pure Java which will be deployed on J2SE and on the Android platform. With the aid of this library it will be possible to use IPv6 on an IPv4 only Android phone and/or network. A web-applet will be implemented using the same library to allow IPv6 SIP calls from a web page.

Also the Android Linux kernel will be upgraded with IPv6. The project is sponsored by NLnet Foundation.

Implementation

In this project jipv6 will be used and improved as a base for the IPv6 tunnel functionality. The goal is to implement it in such a way that existing Java applications can use the tunnel with a minimum of changes to the source code.

M1

M1 has been implemented as a proof of concept. The Android application ipv6 can be downloaded. This application is an UDP server on port 1234. When you send text a response will appear with the text capitalized.

Screenshot of ipv6 application running on an Android

screenshot of nc6 which is used as an UDP client communicating with Android UDP server through port 1234

M2: jipv6 extentions

Preliminary jipv6 javadoc is available. The nl.mansoft package contains a class Jipv6DatagramSocketImpl which implements DatagramSocketImpl . The documentation will be soon improved and the jipv6 extensions will published on sourceforge.

The java program below can act as a IPv6 server and IPv6 client. The server echos the ASCII string in uppercase, the client sends the current date as an ASCII string to the server:
package nl.mansoft;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.util.Date;
import java.util.logging.Level;
import java.util.logging.Logger;

public class Jipv6UDPTest {
    public static void ClientTest(String hostname) throws IOException 
    {
		System.out.println("ClientTest()");
		InetAddress address = InetAddress.getByName(hostname);
		// get a datagram socket
		DatagramSocket socket = new DatagramSocket();
//		DatagramSocket socket = new DatagramSocket(10001);
//		socket.connect(address, 1234);

		// send request
		byte[] buf = new byte[256];
		DatagramPacket packet = new DatagramPacket(buf, buf.length, address, 1234);
//		DatagramPacket packet = new DatagramPacket(buf, buf.length);
		packet.setData(new Date().toString().getBytes());
		socket.send(packet);

		// get response
		packet = new DatagramPacket(buf, buf.length);
		socket.receive(packet);

		// display response
		String received = new String(packet.getData(), 0, packet.getLength());
		System.out.println("Response: " + received);

		socket.close();
    }
    
    public static void ServertTest() throws IOException 
    {
		System.out.println("ServerTest()");
		// get a datagram socket
		DatagramSocket socket = new DatagramSocket(1234);

		byte[] buf = new byte[256];
		DatagramPacket packet = new DatagramPacket(buf, buf.length);

        while (true)
        {
            // get request
            packet = new DatagramPacket(buf, buf.length);
            socket.receive(packet);
            String data = new String(packet.getData(), 0, packet.getLength());

            // send response
            packet.setData(data.toUpperCase().getBytes());
            socket.send(packet);
        }
//		socket.close();
    }
    public static void Test(String[] args) throws IOException
    {
        if (args.length == 1)
            ServertTest();
        else
            ClientTest(args[1]);
    }
    
    public static void Usage()
    {
        System.out.println("Jipv6UDPTest  [IPv6 server]");
    }
	public static void main(String[] args){
        if (args.length == 0)
        {
            Usage();
        }
        else
        {
            try {
                Jipv6DatagramSocketImpl.connect6bed4(args[0]);
                DatagramSocket.setDatagramSocketImplFactory(new Jipv6DatagramSocketImplFactory());
                Test(args);
            } catch (IOException ex) {
                Logger.getLogger(Jipv6UDPTest.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
	}
}
This class is included in jipv6.jar. To test the IPv6 functionality you can run one program instance as a server:
java -cp jipv6.jar nl.mansoft.Jipv6UDPTest 145.100.190.242
145.100.190.242 is the address of a 6bed4 server. The output shows which IPv6 address is allocated to the test program. Use this address to start the client. Note that the server and client can run on different systems behind different NATs and that, thanks to IPv6, no port forwarding is needed.
java -cp jipv6.jar nl.mansoft.Jipv6UDPTest 145.100.190.242 
When all goes well you should see something like this in the output of the client
*** Tunneled packet received!!!
IPv6 packet received!
IPv6: from 2001:0610:0188:2001:524b:5922:c79e:0012
 to 2001:0610:0188:2001:524b:5922:c7a0:0012
 NxHdr: 17
#### PACKET FOR ME!!! 17
UDP Packet srcPort: 1234 destPort: 44444
UDP length: 36
Receiving packet...
Response: TUE NOV 15 16:32:44 CET 2011

Issues with jipv6 DatagramSocketImpl

IPv4 no longer available

Once DatagramSocket.setDatagramSocketImplFactory(new Jipv6DatagramSocketImplFactory()) is called only tunneled IPv6 traffic can be used. It would be better when the original Java IP stack is used when working with IPv4.

DNS not available when using applets or webstart

When a computer doesn't have a public IPv6 address InetAddress.getByName doesn't ever return DNS AAAA records when using the standard DNS resolver. One can use the shipped JNDI DNS resolver which can be activated by specifying Java system properties -Dsun.net.spi.nameservice.provider.1=dns,sun -Dsun.net.spi.nameservice.nameservers=2001:4860:4860::8888. An IPv6 nameserver must be specified since only IPv6 is available, see above. 2001:4860:4860::8888 is a public Google DNS server. Unfortunately these system properties aren't considered 'secure' when using JNLP with applets or webstartable applications and will not be passed to the Java VM. Therefore I have implemented
public static InetAddress nl.mansoft.Jipv6Utils.getByName(String hostName) throws UnknownHostException
This static method has the same semantics as java.net.InetAddress.getByName(String hostName) and can be used as a replacement.

Timeline

ActivityWeek #Milestone
Proof of Concept: IPv6 connectivity through jipv6 library9 
Proof of Concept: IPv6 connectivity through jipv6 library Android10M1
Implement SocketImpl en DatagramSocketImpl so Java applications can use jipv6 transparently12-19M2
Implement SIP webapplet using Peers35-44M5
Packaging of Peers webapplet45M6
Web-startable Peers46-47M7