/*------------------------------------------------------------------------------- DatagramBridge A stupid class that can go away once we get signed applets. The whole raison d'etre here is to bypass java security. Some people want to write to arbitrary sockets on other machines, which is a Bad Thing from a security standpoint for an applet. However, it's OK for a stand-alone java program to do this. So the idea here is that the applet writes packets to a Java process on the same machine. Since the java process isn't in an applet, it can write where ever it pleases. It simply passes on the packets to the machine we wanted to go to in the first place. Suckage, since this chews up performance, at some unknown level. Kinda ugly, too. On the positive side, it's pretty simple code. Could be worse. Could be raining. http://www.npsnet.org/~mcgredo HISTORY 22Feb97 DMcG New (Deadlines? What deadlines?) ---------------------------------------------------------------------------------------*/ package mil.navy.nps.bridge; // package to which we belong import java.io.*; import java.lang.*; import java.net.*; class DatagramBridge extends Object { private DatagramSocket inputSocket = null; // socket we listen on private DatagramSocket outputSocket = null; // socket we write to private int inputSocketNumber = -1; // input socket number (set by param) private int outputSocketNumber = -1; // output socket number (set by param) private int destinationSocketNumber = -1; // destination socket number (set by param) private String destinationMachine = null; // name of machine we're sending to (set by param) private InetAddress destMachineInet = null; // Inet address; cached to save DNS server hits public static final int MAX_PACKET_SIZE = 1500; // MTU, more or less. May cause probs with FDDI, // but just about all DIS packets are smaller than MTU. public DatagramBridge(int pInputSocketNumber, // INPUT: socket to listen on int pOutputSocketNumber, // INPUT: socket we write on String pDestMachineName, // INPUT: name of machine we're sending to int pDestSocketNumber) // INPUT: socket to write to on foreign machine { // Create a couple sockets try { inputSocket = new DatagramSocket(pInputSocketNumber); outputSocket = new DatagramSocket(pOutputSocketNumber); } catch(SocketException sockEx) { throw new RuntimeException("couldn't create one or both sockets"); } inputSocketNumber = pInputSocketNumber; outputSocketNumber = pOutputSocketNumber; destinationSocketNumber = pDestSocketNumber; destinationMachine = pDestMachineName; // find this once, then keep it. Saves a bunch of lookups. try { destMachineInet = InetAddress.getByName(destinationMachine); } catch(UnknownHostException unkHost) { throw new RuntimeException("can't find hostname"); } return; } public void bridge() { // Go to it. Listen for a datagram packet, get it, and send it off. // You can probably optimize the snot out of this naive implementation. DatagramPacket inDgram = null; DatagramPacket outDgram = null; byte ibuff[] = null; while(true) { ibuff = new byte[MAX_PACKET_SIZE]; inDgram = new DatagramPacket(ibuff, ibuff.length); System.out.println("reading..."); // Read a datagram into the new buffer. try { inputSocket.receive(inDgram); } catch(IOException ioe) { throw new RuntimeException("error reading from socket"); } System.out.println("writing..."); // create a new outgoing datagram from the incoming datagram's data. outDgram = new DatagramPacket(inDgram.getData(), // data from incoming datagram inDgram.getLength(), // length of data destMachineInet, // machine we're sending to destinationSocketNumber); // socket on machine we're sending to try { outputSocket.send(outDgram); } catch(IOException ioe) { throw new RuntimeException("error sending to output socket"); } } // end of endless loop } // end of bridge public static void main(String args[]) { DatagramBridge dgramBridge = null; String paramDestMachine = null; String paramInputSocketNo = null; String paramOutputSocketNo = null; String paramDestSocketNo = null; int idx; // pick up parameters from command line // Error checking? Shyeah, right. Can't use getParameter, since this isn't an applet. for(idx = 0; idx < args.length; idx++) { if(args[idx].equals("-inputSockNo")) { paramInputSocketNo = args[idx+1]; System.out.println("got command line arg of -inputSockNo with value of " + paramInputSocketNo); } if(args[idx].equals("-outputSockNo")) { paramOutputSocketNo = args[idx+1]; System.out.println("got command line arg of -outputSockNo with value of " + paramOutputSocketNo); } if(args[idx].equals("-destMachine")) { paramDestMachine = args[idx+1]; System.out.println("got command line arg of -destMachine with value of " + paramDestMachine); } if(args[idx].equals("-destSockNo")) { paramDestSocketNo = args[idx+1]; System.out.println("got command line arg of -destSockNo with value of " + paramDestSocketNo); } if((args[idx].equals("-h")) || (args[idx].equals("-?") ) ) { // Provide some help from the command line. System.out.println("Command line options: "); System.out.println(" -inputSockNo local socket to listen on"); System.out.println(" -outputSockNo local socket to write on"); System.out.println(" -destMachine machine to send to"); System.out.println(" -destSockNo remote socket to write to"); return; } } dgramBridge = new DatagramBridge( Integer.valueOf(paramInputSocketNo).intValue(), Integer.valueOf(paramOutputSocketNo).intValue(), paramDestMachine, Integer.valueOf(paramDestSocketNo).intValue()); dgramBridge.bridge(); // loop forever. } // end of main } // end of DatagramBridge