From: <jo...@us...> - 2009-05-24 22:11:14
|
Revision: 537 http://mspsim.svn.sourceforge.net/mspsim/?rev=537&view=rev Author: joxe Date: 2009-05-24 22:11:04 +0000 (Sun, 24 May 2009) Log Message: ----------- improved TSP tunnel client, added tunnel CLI command - improved RA to work better Modified Paths: -------------- mspsim/se/sics/mspsim/cli/MiscCommands.java mspsim/se/sics/mspsim/net/HC01Packeter.java mspsim/se/sics/mspsim/net/ICMP6Packet.java mspsim/se/sics/mspsim/net/ICMP6PacketHandler.java mspsim/se/sics/mspsim/net/IPStack.java mspsim/se/sics/mspsim/net/IPv6Packet.java mspsim/se/sics/mspsim/net/LoWPANHandler.java mspsim/se/sics/mspsim/net/Packet.java mspsim/se/sics/mspsim/net/TSPClient.java mspsim/se/sics/mspsim/platform/GenericNode.java Added Paths: ----------- mspsim/se/sics/mspsim/cli/NetCommands.java mspsim/se/sics/mspsim/net/BytePayload.java mspsim/se/sics/mspsim/net/NetworkInterface.java Modified: mspsim/se/sics/mspsim/cli/MiscCommands.java =================================================================== --- mspsim/se/sics/mspsim/cli/MiscCommands.java 2009-05-23 21:43:41 UTC (rev 536) +++ mspsim/se/sics/mspsim/cli/MiscCommands.java 2009-05-24 22:11:04 UTC (rev 537) @@ -314,35 +314,6 @@ context.executeCommand(command); } }); - handler.registerCommand("rfanalyzer", new BasicLineCommand("analyze radio packets", "") { - CC2420PacketHandler listener; - CommandContext context; - public int executeCommand(CommandContext context) { - this.context = context; - MSP430 cpu = (MSP430) registry.getComponent(MSP430.class); - listener = new CC2420PacketHandler(cpu); - listener.setOutput(context.out); - IEEE802154Handler ieeeHandler = new IEEE802154Handler(); - listener.addUpperLayerHandler(0, ieeeHandler); - ieeeHandler.setLowerLayerHandler(listener); - IPStack ipStack = new IPStack(); - LoWPANHandler lowpanHandler = new LoWPANHandler(ipStack); - ieeeHandler.addUpperLayerHandler(0, lowpanHandler); - lowpanHandler.setLowerLayerHandler(ieeeHandler); - ipStack.setLinkLayerHandler(lowpanHandler); - return 0; - } - public void lineRead(String line) { - if (listener != null) { - byte[] data = Utils.hexconv(line); - for (int i = 0; i < data.length; i++) { - //context.out.println("Byte " + i + " = " + ((int) data[i] & 0xff)); - // Currently it will autoprint when packet is ready... - listener.receivedByte(data[i]); - } - } - } - }); handler.registerCommand("rflistener", new BasicLineCommand("an rflisteer", "[input|output] <rf-chip>") { CommandContext context; Added: mspsim/se/sics/mspsim/cli/NetCommands.java =================================================================== --- mspsim/se/sics/mspsim/cli/NetCommands.java (rev 0) +++ mspsim/se/sics/mspsim/cli/NetCommands.java 2009-05-24 22:11:04 UTC (rev 537) @@ -0,0 +1,68 @@ +/** + * + */ +package se.sics.mspsim.cli; + +import se.sics.mspsim.core.MSP430; +import se.sics.mspsim.net.CC2420PacketHandler; +import se.sics.mspsim.net.IEEE802154Handler; +import se.sics.mspsim.net.IPStack; +import se.sics.mspsim.net.LoWPANHandler; +import se.sics.mspsim.util.ComponentRegistry; +import se.sics.mspsim.util.Utils; + +/** + * @author joakim + * + */ +public class NetCommands implements CommandBundle { + + private IPStack ipStack; + public void setupCommands(final ComponentRegistry registry, CommandHandler handler) { + + handler.registerCommand("ipstack", new BasicLineCommand("setup 802.15.4/IP stack", "") { + CC2420PacketHandler listener; + CommandContext context; + public int executeCommand(CommandContext context) { + this.context = context; + MSP430 cpu = (MSP430) registry.getComponent(MSP430.class); + listener = new CC2420PacketHandler(cpu); + listener.setOutput(context.out); + IEEE802154Handler ieeeHandler = new IEEE802154Handler(); + listener.addUpperLayerHandler(0, ieeeHandler); + ieeeHandler.setLowerLayerHandler(listener); + ipStack = new IPStack(); + LoWPANHandler lowpanHandler = new LoWPANHandler(ipStack); + ieeeHandler.addUpperLayerHandler(0, lowpanHandler); + lowpanHandler.setLowerLayerHandler(ieeeHandler); + ipStack.setLinkLayerHandler(lowpanHandler); + context.err.print("IP Stack started"); + return 0; + } + + public void lineRead(String line) { + if (listener != null) { + byte[] data = Utils.hexconv(line); + for (int i = 0; i < data.length; i++) { + //context.out.println("Byte " + i + " = " + ((int) data[i] & 0xff)); + // Currently it will autoprint when packet is ready... + listener.receivedByte(data[i]); + } + } + } + }); + + handler.registerCommand("tspstart", new BasicCommand("starts a TSP tunnel", "<server> <user> <password>") { + public int executeCommand(CommandContext context) { + if (ipStack.startTSPTunnel(context.getArgument(0), + context.getArgument(1), context.getArgument(2))) { + context.out.print("TSP Tunnel started"); + return 0; + } else { + context.out.print("TSP Tunnel failed"); + return 1; + } + } + }); + } +} Added: mspsim/se/sics/mspsim/net/BytePayload.java =================================================================== --- mspsim/se/sics/mspsim/net/BytePayload.java (rev 0) +++ mspsim/se/sics/mspsim/net/BytePayload.java 2009-05-24 22:11:04 UTC (rev 537) @@ -0,0 +1,25 @@ +package se.sics.mspsim.net; + +/* keep the packet payload untouched ... */ +public class BytePayload implements IPPayload { + + byte[] payloadData; + byte dispatch; + + public BytePayload(IPv6Packet packet) { + parsePacketData(packet); + } + + public byte[] generatePacketData(IPv6Packet packet) { + return payloadData; + } + + public byte getDispatch() { + return dispatch; + } + + public void parsePacketData(IPv6Packet packet) { + dispatch = packet.getDispatch(); + payloadData = packet.getPayload(); + } +} Modified: mspsim/se/sics/mspsim/net/HC01Packeter.java =================================================================== --- mspsim/se/sics/mspsim/net/HC01Packeter.java 2009-05-23 21:43:41 UTC (rev 536) +++ mspsim/se/sics/mspsim/net/HC01Packeter.java 2009-05-24 22:11:04 UTC (rev 537) @@ -185,7 +185,7 @@ /* write version and flow if needed */ if ((enc1 & IPHC_VF_C) == 0) { - pos += packet.writeVFlow(data, pos); + pos += writeVFlow(packet, data, pos); } /* write traffic class if needed */ if ((enc1 & IPHC_TC_C) == 0) { @@ -315,6 +315,14 @@ return dataPacket; } + public int writeVFlow(IPv6Packet packet, byte[] data, int pos) { + data[pos++] = (byte) (0x60 | (packet.flowLabel >> 16) & 0x0f); + data[pos++] = (byte)((packet.flowLabel >> 8) & 0xff); + data[pos++] = (byte) (packet.flowLabel & 0xff); + return 3; + } + + public void parsePacketData(IPv6Packet packet) { /* first two is ... */ int pos = 2; Modified: mspsim/se/sics/mspsim/net/ICMP6Packet.java =================================================================== --- mspsim/se/sics/mspsim/net/ICMP6Packet.java 2009-05-23 21:43:41 UTC (rev 536) +++ mspsim/se/sics/mspsim/net/ICMP6Packet.java 2009-05-24 22:11:04 UTC (rev 537) @@ -2,6 +2,8 @@ import java.io.PrintStream; import java.util.ArrayList; +import se.sics.mspsim.util.Utils; + public class ICMP6Packet implements IPPayload { public static final int DISPATCH = 58; @@ -45,18 +47,20 @@ byte hopLimit = (byte) 128; byte autoConfigFlags; - int routerLifetime = 600; /* time in seconds for keeping the router as default */ - int reachableTime = 10000; /* time in millis when node still should be counted as reachable */ - int retransmissionTimer = 1000; /* time in millis between solicitations */ + int routerLifetime = 100; /* time in seconds for keeping the router as default */ + int reachableTime = 360000; /* time in millis when node still should be counted as reachable */ + int retransmissionTimer = 0; /* time in millis between solicitations */ int mtuSize = 1280; + byte[] echoData; + private ArrayList<byte[]> options = new ArrayList<byte[]>(); /* prefix info option - type = 3, len = 4 (64x4 bits), prefix = 64 bits */ private final static byte[] defaultPrefixInfo = new byte[] {3, 4, 64, (byte) (ON_LINK | AUTOCONFIG), - 0, 0, 1, 0, /* valid lifetime - 256 seconds for now*/ - 0, 1, 0, 0, /* prefered lifetime - 65535 seconds lifetime of autoconf addr */ + (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, /* valid lifetime -1 seconds for now*/ + (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, /* prefered lifetime -1 seconds lifetime of autoconf addr */ 0, 0, 0, 0, /* reserved */ /* the prefix ... */ (byte)0xaa, (byte)0xaa, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 @@ -70,6 +74,8 @@ options.clear(); byte[] prefixInfo = new byte[defaultPrefixInfo.length]; System.arraycopy(defaultPrefixInfo, 0, prefixInfo, 0, defaultPrefixInfo.length); + byte[] prefix = stack.prefix; + System.arraycopy(prefix, 0, prefixInfo, 16, prefix.length); options.add(prefixInfo); options.add(mtuOption); addLinkOption(SOURCE_LINKADDR, llAddr); @@ -97,6 +103,14 @@ return null; } + public byte[] getEchoData() { + return echoData; + } + + public void setEchoData(byte[] edata) { + echoData = edata; + } + public void printPacket(PrintStream out) { String typeS = "" + type; if (type >= 128) { @@ -119,6 +133,7 @@ System.out.println(" routerLifeTime: " + routerLifetime + " (sec)"); System.out.println(" reachableTime: " + reachableTime + " (msec)"); System.out.println(" retransmissionTimer: " + retransmissionTimer + " (msec)"); + System.out.println(" autoConf: " + autoConfigFlags); byte[] prefixInfo = getOption(PREFIX_INFO); int bits = prefixInfo[2]; int bytes = bits / 8; @@ -128,6 +143,8 @@ if ((i & 1) == 1) out.print(":"); } out.println("/" + bits); + out.println("RA Valid Lifetime: " + Packet.get32(prefixInfo, 4)); + out.println("RA Pref. Lifetime: " + Packet.get32(prefixInfo, 8)); byte[] srcLink = getOption(SOURCE_LINKADDR); if (srcLink != null) { /* assuming 8 bytes for the mac ??? */ @@ -153,7 +170,11 @@ case ECHO_REPLY: id = packet.get16(4); seqNo = packet.get16(6); - handleOptions(packet, 8); + int dataLen = packet.getPayloadLength() - 8; + if (dataLen > 0) { + echoData = new byte[dataLen]; + packet.copy(8, echoData, 0, dataLen); + } break; case NEIGHBOR_SOLICITATION: case NEIGHBOR_ADVERTISEMENT: @@ -219,7 +240,11 @@ buffer[pos++] = (byte) (id & 0xff); buffer[pos++] = (byte) (seqNo >> 8); buffer[pos++] = (byte) (seqNo & 0xff); - pos = addOptions(buffer, pos); + if (echoData != null) { + for (int i = 0; i < echoData.length; i++) { + buffer[pos++] = echoData[i]; + } + } break; case NEIGHBOR_SOLICITATION: case NEIGHBOR_ADVERTISEMENT: @@ -279,4 +304,17 @@ public byte getDispatch() { return DISPATCH; } + + + public static void main(String[] args) { + byte[] pData = Utils.hexconv("6000000000403a3f200105c01000000a00000000000001ad200105c011024e000212740504030201800070e3de1b00011b87194ad859000008090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f3031323334353637"); + IPv6Packet packet = new IPv6Packet(); + packet.setBytes(pData); + packet.parsePacketData(packet); + if (packet.nextHeader == 58) { + ICMP6Packet icmpPacket = new ICMP6Packet(); + icmpPacket.parsePacketData(packet); + icmpPacket.printPacket(System.out); + } + } } Modified: mspsim/se/sics/mspsim/net/ICMP6PacketHandler.java =================================================================== --- mspsim/se/sics/mspsim/net/ICMP6PacketHandler.java 2009-05-23 21:43:41 UTC (rev 536) +++ mspsim/se/sics/mspsim/net/ICMP6PacketHandler.java 2009-05-24 22:11:04 UTC (rev 537) @@ -29,7 +29,7 @@ // is this ok? ipp.destAddress = packet.sourceAddress; ipp.sourceAddress = ipStack.myLocalIPAddress; - ipStack.sendPacket(ipp); + ipStack.sendPacket(ipp, packet.netInterface); break; case ICMP6Packet.ECHO_REPLY: System.out.println("ICMP6 got echo reply!!"); @@ -50,7 +50,7 @@ // is this ok? ipp.destAddress = packet.sourceAddress; ipp.sourceAddress = ipStack.myLocalIPAddress; - ipStack.sendPacket(ipp); + ipStack.sendPacket(ipp, packet.netInterface); break; case ICMP6Packet.ROUTER_SOLICITATION: if (ipStack.isRouter()) { @@ -71,8 +71,9 @@ ipp.sourceAddress = ipStack.myLocalIPAddress; System.out.print("Created ICMP6 RA for "); IPv6Packet.printAddress(System.out, ipp.destAddress); + packet.printPacket(System.out); - ipStack.sendPacket(ipp); + ipStack.sendPacket(ipp, packet.netInterface); } break; } Modified: mspsim/se/sics/mspsim/net/IPStack.java =================================================================== --- mspsim/se/sics/mspsim/net/IPStack.java 2009-05-23 21:43:41 UTC (rev 536) +++ mspsim/se/sics/mspsim/net/IPStack.java 2009-05-24 22:11:04 UTC (rev 537) @@ -46,9 +46,10 @@ import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; +import java.net.SocketException; +import java.net.UnknownHostException; import java.util.Arrays; -import se.sics.mspsim.core.MSP430; import se.sics.mspsim.util.Utils; public class IPStack { @@ -56,7 +57,9 @@ public static final byte[] ALL_NODES = {(byte) 0xff, 0x02, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}; public static final byte[] ALL_ROUTERS = {(byte) 0xff, 0x02, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 1}; + 0, 0, 0, 0, 0, 0, 0, 2}; + public static final byte[] UNSPECIFIED = {(byte) 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0}; byte[] prefix = null; int prefixSize = 0; @@ -77,10 +80,15 @@ /* is router -> router behavior */ private boolean isRouter = true; + + private IPPacketer tunnelPacketer = new IPv6Packet(); + private TSPClient tunnel; /* this needs to be generalized later... and down to lowpan too... */ //private HC01Packeter ipPacketer = new HC01Packeter(); - + + // TODO: read from configfile... + public IPStack() { icmp6Handler = new ICMP6PacketHandler(this); prefix = new byte[] {(byte) 0xaa, (byte)0xaa, 0, 0, 0, 0, 0, 0}; @@ -88,6 +96,20 @@ configureIPAddress(); } + public boolean startTSPTunnel(String server, String user, String password) { + try { + tunnel = new TSPClient(server, user, password); + tunnel.setIPStack(this); + tunnel.waitSetup(); + return tunnel.isReady(); + } catch (SocketException e) { + e.printStackTrace(); + } catch (UnknownHostException e) { + e.printStackTrace(); + } + return false; + } + public void setLinkLayerHandler(PacketHandler handler) { linkLayerHandler = handler; } @@ -98,6 +120,22 @@ configureIPAddress(); } + public boolean isOnLink(byte[] address) { + /* bc or link local */ + if (address[0] == ((byte) 0xff) || (address[0] == ((byte) 0xfe) && + address[1] == ((byte)0x80))) { + return true; + } + + /* unspecified - on link ?? */ + if (Arrays.equals(UNSPECIFIED, address)) return true; + /* prefix match? */ + for (int i = 0; i < prefixSize / 8; i++) { + if (address[i] != prefix[i]) return false; + } + return true; + } + public void configureIPAddress() { if (prefix != null) { System.arraycopy(prefix, 0, myIPAddress, 0, prefixSize / 8); @@ -107,6 +145,9 @@ } /* autoconfig ?? */ myLocalIPAddress[8] = myIPAddress[8] = (byte) (myIPAddress[8] ^ 0x02); + + System.out.println("***** Prefix Set / IP address: "); + IPv6Packet.printAddress(System.out, myIPAddress); } private boolean findRoute(IPv6Packet packet) { @@ -135,24 +176,74 @@ macAddr[0] = (byte) (macAddr[0] ^ 0x02); } - public void sendPacket(IPv6Packet packet) { + /* send a packet - can be bound for specific interface */ + public void sendPacket(IPv6Packet packet, NetworkInterface nIf) { /* find route checks if there are link addr, and otherwise sets them */ - if (findRoute(packet)) { - linkLayerHandler.sendPacket(packet); + if (nIf == linkLayerHandler || + (nIf == null) && isOnLink(packet.getDestinationAddress())) { + if (findRoute(packet)) { + linkLayerHandler.sendPacket(packet); + } + } else { + System.out.println("*** Should go out on tunnel: "); + System.out.print("MyAddress: "); + IPv6Packet.printAddress(System.out, myIPAddress); + System.out.print(", Dest: "); + IPv6Packet.printAddress(System.out, packet.getDestinationAddress()); + if (tunnel.isReady()) { + tunnel.sendPacket(packet); + } } } public void receivePacket(IPv6Packet packet) { - System.out.println("IPv6 packet received!!!"); + System.out.println("IPv6 packet received!"); packet.printPacket(System.out); - switch (packet.nextHeader) { - case ICMP6Packet.DISPATCH: - icmp6Handler.handlePacket(packet); - break; + if (!isOnLink(packet.getDestinationAddress()) && + packet.netInterface != tunnel) { + System.out.println("**** Should go out on tunnel!!!!"); + if (packet.ipPayload == null) { + packet.setIPPayload(new BytePayload(packet)); + } + /* will this work ??? */ + System.out.print("MyAddress: "); + IPv6Packet.printAddress(System.out, myIPAddress); + System.out.print(", Dest: "); + IPv6Packet.printAddress(System.out, packet.getDestinationAddress()); + if (tunnel.isReady()) { + tunnel.sendPacket(packet); + } + } else if (isForMe(packet.getDestinationAddress())){ + System.out.println("#### PACKET FOR ME!!!"); + switch (packet.nextHeader) { + case ICMP6Packet.DISPATCH: + icmp6Handler.handlePacket(packet); + break; + } + } else if (packet.netInterface != linkLayerHandler) { + /* Can not be from link layer (default) -- */ + /* if HC01 - we need to handle UDP at least... */ + System.out.println("#### PACKET FOR: " + packet.getDestinationAddress() + " sent to link"); + if (packet.ipPayload == null) { + packet.setIPPayload(new BytePayload(packet)); + if (findRoute(packet)) { + linkLayerHandler.sendPacket(packet); + } + } } } - + + /* is the packet for me ? */ + private boolean isForMe(byte[] address) { + if (Arrays.equals(myIPAddress, address) || + Arrays.equals(myLocalIPAddress, address)) return true; + if (isRouter && Arrays.equals(ALL_ROUTERS, address)) return true; + if (Arrays.equals(ALL_NODES, address)) return true; + if (Arrays.equals(UNSPECIFIED, address)) return true; + return false; + } + public void setLinkLayerAddress(byte[] addr) { myLinkAddress = addr; } Modified: mspsim/se/sics/mspsim/net/IPv6Packet.java =================================================================== --- mspsim/se/sics/mspsim/net/IPv6Packet.java 2009-05-23 21:43:41 UTC (rev 536) +++ mspsim/se/sics/mspsim/net/IPv6Packet.java 2009-05-24 22:11:04 UTC (rev 537) @@ -43,6 +43,8 @@ import java.io.PrintStream; +import se.sics.mspsim.util.Utils; + /** * @author Joakim Eriksson, SICS * @@ -50,6 +52,7 @@ public class IPv6Packet extends Packet implements IPPacketer { public static final int ICMP6_DISPATCH = 58; + public static final boolean DEBUG = true; int version; int trafficClass; @@ -62,6 +65,7 @@ int ipLen = 0; int payloadLen = 0; IPPayload ipPayload; + public NetworkInterface netInterface; public IPv6Packet() { version = 6; @@ -107,8 +111,13 @@ } /* this is for setting raw packet data */ +//TODO: should not take an argument here??? it should parse its own +// data array??? public void parsePacketData(IPv6Packet packet) { version = (packet.getData(0) & 0xff) >> 4; + if (DEBUG) { + System.out.println("IPv6Packet: version: " + version); + } if (version != 6) { return; } @@ -119,7 +128,7 @@ packet.getData(3) & 0xff; payloadLen = ((packet.getData(4) & 0xff) << 8) + packet.getData(5); nextHeader = packet.getData(6); - hopLimit = packet.getData(7); + hopLimit = packet.getData(7) & 0xff; packet.copy(8, sourceAddress, 0, 16); packet.copy(24, destAddress, 0, 16); // move position 40 bytes forward for handling next headers / payload @@ -172,13 +181,6 @@ return sum; } - public int writeVFlow(byte[] data, int pos) { - data[pos++] = (byte) (0x60 | (flowLabel >> 16) & 0x0f); - data[pos++] = (byte)((flowLabel >> 8) & 0xff); - data[pos++] = (byte) (flowLabel & 0xff); - return 3; - } - public static boolean isMACBased(byte[] address, byte[] macAddress) { if (address[8] == (macAddress[0] ^ 0x02)) { for (int i = 1; i < macAddress.length; i++) { @@ -209,10 +211,32 @@ return nextHeader; } - @Override + // TODO: should not take an argument here - should be this packet + // that should be generating the data??? public byte[] generatePacketData(IPv6Packet packet) { - // TODO Auto-generated method stub - return null; + byte[] payload = ipPayload.generatePacketData(packet); + int size = 40 + payload.length; + byte[] dataPacket = new byte[size]; + + dataPacket[0] = (byte) (0x60 | (trafficClass >> 4) & 0x0f); + dataPacket[1] = (byte) (((trafficClass & 0xf) << 4) | + ((flowLabel >> 16) & 0xf)); + dataPacket[2] = (byte) ((trafficClass >> 8) & 0xff); + dataPacket[3] = (byte) (trafficClass & 0xff); + + dataPacket[4] = (byte) ((payload.length >> 8) & 0xff); + dataPacket[5] = (byte) (payload.length & 0xff); + + dataPacket[6] = (byte) (nextHeader & 0xff); + dataPacket[7] = (byte) (hopLimit & 0xff); + + int pos = 8; + System.arraycopy(packet.getSourceAddress(), 0, dataPacket, pos, 16); + pos += 16; + System.arraycopy(packet.getDestinationAddress(), 0, dataPacket, pos, 16); + pos += 16; + System.arraycopy(payload, 0, dataPacket, 40, payload.length); + return dataPacket; } public IPPayload getIPPayload() { @@ -232,4 +256,12 @@ out.print(":"); } } + + public static void main(String[] args) { + byte[] data = Utils.hexconv("6000000000200001fe80000000000000023048fffe904cd2ff02000000000000000000026c5b5f303a000100050200008300527800000000ff02000000000000000000026c5b5f30"); + IPv6Packet packet = new IPv6Packet(); + packet.setBytes(data); + packet.parsePacketData(packet); + packet.printPacket(System.out); + } } \ No newline at end of file Modified: mspsim/se/sics/mspsim/net/LoWPANHandler.java =================================================================== --- mspsim/se/sics/mspsim/net/LoWPANHandler.java 2009-05-23 21:43:41 UTC (rev 536) +++ mspsim/se/sics/mspsim/net/LoWPANHandler.java 2009-05-24 22:11:04 UTC (rev 537) @@ -39,7 +39,7 @@ */ package se.sics.mspsim.net; -public class LoWPANHandler extends AbstractPacketHandler { +public class LoWPANHandler extends AbstractPacketHandler implements NetworkInterface { private IPStack ipStack; @@ -47,6 +47,10 @@ ipStack = stack; } + public String getName() { + return "6lowpan"; + } + public void packetReceived(Packet packet) { /* create IP packet based on the correct dispatch */ IPv6Packet ipPacket = new IPv6Packet(packet); @@ -57,6 +61,7 @@ if (dispatch == ipStack.getDefaultPacketer().getDispatch()) { ipStack.getDefaultPacketer().parsePacketData(ipPacket); /* send in the packet */ + ipPacket.netInterface = this; ipStack.receivePacket(ipPacket); } } Added: mspsim/se/sics/mspsim/net/NetworkInterface.java =================================================================== --- mspsim/se/sics/mspsim/net/NetworkInterface.java (rev 0) +++ mspsim/se/sics/mspsim/net/NetworkInterface.java 2009-05-24 22:11:04 UTC (rev 537) @@ -0,0 +1,5 @@ +package se.sics.mspsim.net; + +public interface NetworkInterface { + public String getName(); +} Modified: mspsim/se/sics/mspsim/net/Packet.java =================================================================== --- mspsim/se/sics/mspsim/net/Packet.java 2009-05-23 21:43:41 UTC (rev 536) +++ mspsim/se/sics/mspsim/net/Packet.java 2009-05-24 22:11:04 UTC (rev 537) @@ -124,13 +124,33 @@ public int get32(int pos) { pos = currentPos + pos; - if (packetData.length > pos + 3) + if (packetData.length >= pos + 3) { return ((packetData[pos] & 0xff) << 24) | ((packetData[pos + 1] & 0xff) << 16) | ((packetData[pos + 2] & 0xff) << 8) | (packetData[pos + 3] & 0xff); + } return 0; } + + public static int get32(byte[] data, int pos) { + if (data.length >= pos + 3) { + return ((data[pos] & 0xff) << 24) | + ((data[pos + 1] & 0xff) << 16) | + ((data[pos + 2] & 0xff) << 8) | + (data[pos + 3] & 0xff); + } + return 0; + } + + public static int get16(byte[] data, int pos) { + if (data.length >= pos + 1) { + return ((data[pos] & 0xff) << 8) | + ((data[pos + 1] & 0xff) << 0); + } + return 0; + } + public int get16(int pos) { pos = currentPos + pos; Modified: mspsim/se/sics/mspsim/net/TSPClient.java =================================================================== --- mspsim/se/sics/mspsim/net/TSPClient.java 2009-05-23 21:43:41 UTC (rev 536) +++ mspsim/se/sics/mspsim/net/TSPClient.java 2009-05-24 22:11:04 UTC (rev 537) @@ -9,7 +9,7 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; -public class TSPClient { +public class TSPClient implements NetworkInterface { public static final int DEFAULT_PORT = 3653; private static final byte[] VERSION = "VERSION=2.0.0\r\n".getBytes(); @@ -17,13 +17,14 @@ private static final byte[] AUTH_ANON = "AUTHENTICATE ANONYMOUS\r\b".getBytes(); enum WriterState {WAIT, STARTED, CAPABILITIES_RECEIVED, AUTHENTICATE_REQ_OK, TUNNEL_CONF_RECEIVED, TUNNEL_UP}; - enum ReaderState {CAP_EXPECTED, AUTH_OK_EXPECTED, TUNNEL_CONF_EXPECTED, + enum ReaderState {CAP_EXPECTED, AUTH_ACK_EXPECTED, AUTH_OK_EXPECTED, TUNNEL_CONF_EXPECTED, TUNNEL_UP}; private static final Pattern prefixPattern = Pattern.compile("(?m).+?<prefix (.+?)>(.+?)</prefix>"); - + private IPStack ipStack; + WriterState writerState = WriterState.STARTED; ReaderState readerState = ReaderState.CAP_EXPECTED; @@ -35,8 +36,16 @@ private String user; private String password; + private boolean userLoggedIn = false; public TSPClient(String host) throws SocketException, UnknownHostException { + this(host, null, null); + } + + public TSPClient(String host, String user, String password) throws SocketException, UnknownHostException { + this.user = user; + this.password = password; + connection = new DatagramSocket(); serverAddr = InetAddress.getByName(host); //connection.connect(serverAddr, DEFAULT_PORT); @@ -67,6 +76,18 @@ new Thread(reader).start(); } + public String getName() { + return "tsp"; + } + + public void setIPStack(IPStack ipStack) { + this.ipStack = ipStack; + } + + public boolean isReady() { + return writerState == WriterState.TUNNEL_UP; + } + int wWait = 0; private void writer() throws IOException, InterruptedException { System.out.println("Writer started. sending version..."); @@ -87,18 +108,22 @@ System.out.println("Writer: sending AUTH"); if (user == null) { sendPacket(AUTH_ANON); + setReaderState(ReaderState.AUTH_OK_EXPECTED, WriterState.WAIT); } else { sendPacket(AUTH_PLAIN); + setReaderState(ReaderState.AUTH_ACK_EXPECTED, WriterState.WAIT); } - setReaderState(ReaderState.AUTH_OK_EXPECTED, WriterState.WAIT); break; case AUTHENTICATE_REQ_OK: - if (user == null) { + if (user == null || userLoggedIn) { sendTunnelReq(); + setReaderState(ReaderState.TUNNEL_CONF_EXPECTED, WriterState.WAIT); } else { // send login with user/pass!!! + sendAuth(); + userLoggedIn = true; + setReaderState(ReaderState.AUTH_OK_EXPECTED, WriterState.WAIT); } - setReaderState(ReaderState.TUNNEL_CONF_EXPECTED, WriterState.WAIT); break; case TUNNEL_CONF_RECEIVED: String accept = "<tunnel action=\"accept\"></tunnel>\r\n"; @@ -106,6 +131,7 @@ sendPacket(accept.getBytes()); System.out.println("*** Tunnel UP!"); setReaderState(ReaderState.TUNNEL_UP, WriterState.TUNNEL_UP); + notifyReady(); break; case TUNNEL_UP: /* all ok - do nothing but sleep.*/ @@ -117,15 +143,28 @@ } } } + + private synchronized void notifyReady() { + notifyAll(); + } + private void sendAuth() throws IOException { + String auth = "\0" + user + "\0" + password + "\r\n"; + sendPacket(auth.getBytes()); + } + private void sendTunnelReq() throws IOException { InetAddress myAddr = InetAddress.getLocalHost(); byte[] addr = myAddr.getAddress(); String myAddress = String.format("%d.%d.%d.%d", addr[0] & 0xff, addr[1] & 0xff, addr[2] & 0xff, addr[3] & 0xff); + String router = ""; + if (user != null) { + router = "<router><prefix length=\"64\"/></router>"; + } String tunnelConf = "<tunnel action=\"create\" type=\"v6udpv4\"><client><address type=\"ipv4\">" + - myAddress + "</address><keepalive interval=\"30\"></keepalive>" + + myAddress + "</address><keepalive interval=\"30\"></keepalive>" + router + "</client></tunnel>\r\n"; tunnelConf = "Content-length: " + tunnelConf.length() + "\r\n" + tunnelConf; @@ -161,7 +200,11 @@ case CAP_EXPECTED: writerState = WriterState.CAPABILITIES_RECEIVED; break; + case AUTH_ACK_EXPECTED: + writerState = WriterState.AUTHENTICATE_REQ_OK; + break; case AUTH_OK_EXPECTED: + // Check if auth is really ok!!! writerState = WriterState.AUTHENTICATE_REQ_OK; break; case TUNNEL_CONF_EXPECTED: @@ -169,18 +212,44 @@ Matcher m = prefixPattern.matcher(sData); if (m.find()) { System.out.println("Prefix: " + m.group(2) + " arg:" + m.group(1)); + if (ipStack != null) { + byte[] prefix = getPrefix(m.group(2)); + /* this is hardcoded for 64 bits for now */ + ipStack.setPrefix(prefix, 64); + } } } writerState = WriterState.TUNNEL_CONF_RECEIVED; break; case TUNNEL_UP: System.out.println("*** Tunneled packet received!!!"); + if (ipStack != null) { + IPv6Packet packet = new IPv6Packet(); + packet.setBytes(data, 0, receiveP.getLength()); + packet.parsePacketData(packet); + packet.netInterface = this; + ipStack.receivePacket(packet); + } break; } } } - + // handles format XXXX:XXXX:XXXX ... + private byte[] getPrefix(String prefix) { + prefix = prefix.trim(); + String[] parts = prefix.split(":"); + // each XXXX should be two bytes... + byte[] prefixBytes = new byte[parts.length * 2]; + for (int i = 0; i < parts.length; i++) { + System.out.println("## Parsing: " + parts[i]); + int val = Integer.parseInt(parts[i], 16); + prefixBytes[i * 2] = (byte) (val >> 8); + prefixBytes[i * 2 + 1] = (byte) (val & 0xff); + } + return prefixBytes; + } + private void sendPacket(byte[] packetData) throws IOException { byte[] pData = new byte[8 + packetData.length]; pData[0] = (byte) (0xf0 | (seq >>24) & 0xf); @@ -203,8 +272,23 @@ new String(packetData)); } + + public void sendPacket(IPv6Packet packet) { + byte[] data = packet.generatePacketData(packet); + System.out.println("Sending IPv6Packet on tunnel: " + data); + System.out.print("Packet: "); + packet.printPacket(System.out); + System.out.println(); + try { + sendPacket(data); + } catch (IOException e) { + e.printStackTrace(); + } + } + + public static void main(String[] args) throws UnknownHostException, IOException { // Pattern pattern = Pattern.compile("(?m).+?<server>(.+?)</server>.+?"); // String data = "<tunnel action=\"info\" type=\"v6udpv4\" lifetime=\"604800\">" + @@ -229,7 +313,21 @@ // System.out.println("No match"); // } // - - TSPClient tspc = new TSPClient(args[0]); + if (args.length == 1) { + TSPClient tspc = new TSPClient(args[0]); + } else if (args.length == 3) { + TSPClient tspc = new TSPClient(args[0], args[1], args[2]); + } } + + public synchronized boolean waitSetup() { + if (!isReady()) { + try { + wait(1000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + return isReady(); + } } Modified: mspsim/se/sics/mspsim/platform/GenericNode.java =================================================================== --- mspsim/se/sics/mspsim/platform/GenericNode.java 2009-05-23 21:43:41 UTC (rev 536) +++ mspsim/se/sics/mspsim/platform/GenericNode.java 2009-05-24 22:11:04 UTC (rev 537) @@ -46,6 +46,7 @@ import se.sics.mspsim.cli.CommandHandler; import se.sics.mspsim.cli.DebugCommands; import se.sics.mspsim.cli.MiscCommands; +import se.sics.mspsim.cli.NetCommands; import se.sics.mspsim.cli.ProfilerCommands; import se.sics.mspsim.cli.StreamCommandHandler; import se.sics.mspsim.cli.WindowCommands; @@ -200,6 +201,7 @@ registry.registerComponent("statcmd", new StatCommands(cpu, stats)); registry.registerComponent("wincmd", new WindowCommands()); registry.registerComponent("profilecmd", new ProfilerCommands()); + registry.registerComponent("netcmd", new NetCommands()); // Monitor execution cpu.setMonitorExec(true); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |