airport2config-2.0.1/0000755000175000017500000000000010420575267014010 5ustar julienjulienairport2config-2.0.1/AUTHORS0000444000175000017500000000041210420574751015050 0ustar julienjulienAirportBaseStationConfigurator http://gicl.cs.drexel.edu/sevy/airport Jon Sevy Geometric and Intelligent Computing Laboratory Department of Mathematics and Computer Science Drexel University http://gicl.cs.drexel.edu/sevy airport2config-2.0.1/AirportBaseStationConfigurator.java0000644000175000017500000012321410012317201022771 0ustar julienjulien/* * AirportBaseStationConfigurator * * Copyright (C) 2000, Jonathan Sevy * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ import java.util.*; import java.net.*; import java.awt.*; import javax.swing.*; import javax.swing.border.*; import javax.swing.plaf.*; import java.awt.event.*; import java.io.*; import java.util.zip.*; import airport.*; public class AirportBaseStationConfigurator extends JFrame implements ActionListener { public static final String aboutString = "Airport Base Station Configurator "; JButton discoverDevicesButton, retrieveItemButton, updateBaseStationButton, rebootBaseStationButton; JTextField hostIDField; JTextField communityField; GridBagLayout mainLayout = new GridBagLayout(); MenuBar theMenubar; Menu fileMenu; MenuItem quitItem, openItem, saveItem, aboutItem, uploadFirmwareItem; AirportInfo airportInfo = null; AirportInfoTabbedPane infoPane = null; JTextArea messagesArea; // WindowCloseAdapter to catch window close-box closings private class WindowCloseAdapter extends WindowAdapter { public void windowClosing(WindowEvent e) { System.exit(0); } }; public AirportBaseStationConfigurator() { airportInfo = new AirportInfo(); setUpDisplay(); } private void setUpDisplay() { // set fonts to smaller-than-normal size, for compaction! UIManager manager = new UIManager(); FontUIResource appFont = new FontUIResource("SansSerif", Font.PLAIN, 10); UIDefaults defaults = manager.getLookAndFeelDefaults(); Enumeration keys = defaults.keys(); while (keys.hasMoreElements()) { String nextKey = (String)(keys.nextElement()); if ((nextKey.indexOf("font") > -1) || (nextKey.indexOf("Font") > -1)) { manager.put(nextKey, appFont); } } // add WindowCloseAdapter to catch window close-box closings // thanks to Jer for this one! addWindowListener(new WindowCloseAdapter()); this.setTitle("AirPort Base Station Configurator"); this.getRootPane().setBorder(new BevelBorder(BevelBorder.RAISED)); theMenubar = new MenuBar(); this.setMenuBar(theMenubar); fileMenu = new Menu("File"); openItem = new MenuItem("Open saved settings..."); openItem.setShortcut(new MenuShortcut('o')); openItem.setActionCommand("open settings"); openItem.addActionListener(this); fileMenu.add(openItem); saveItem = new MenuItem("Save settings..."); saveItem.setShortcut(new MenuShortcut('s')); saveItem.setActionCommand("save settings"); saveItem.addActionListener(this); fileMenu.add(saveItem); fileMenu.addSeparator(); uploadFirmwareItem = new MenuItem("Upload new base station firmware..."); uploadFirmwareItem.setActionCommand("upload firmware"); uploadFirmwareItem.addActionListener(this); fileMenu.add(uploadFirmwareItem); fileMenu.addSeparator(); aboutItem = new MenuItem("About..."); aboutItem.setActionCommand("about"); aboutItem.addActionListener(this); fileMenu.add(aboutItem); quitItem = new MenuItem("Quit"); quitItem.setShortcut(new MenuShortcut('q')); quitItem.setActionCommand("quit"); quitItem.addActionListener(this); fileMenu.add(quitItem); theMenubar.add(fileMenu); JLabel hostIDLabel = new JLabel("Device address:"); hostIDField = new JTextField(10); hostIDField.setText("10.0.1.1"); JLabel communityLabel = new JLabel("Password:"); communityField = new JPasswordField(10); //communityField = new JTextField(10); //communityField.setText("public"); discoverDevicesButton = new JButton("Discover Devices"); discoverDevicesButton.setActionCommand("discover devices"); discoverDevicesButton.addActionListener(this); retrieveItemButton = new JButton("Retrieve Settings"); retrieveItemButton.setActionCommand("retrieve data"); retrieveItemButton.addActionListener(this); updateBaseStationButton = new JButton("Update Base Station"); updateBaseStationButton.setActionCommand("update base station"); updateBaseStationButton.addActionListener(this); updateBaseStationButton.setEnabled(false); //initially disabled until read in or open settings rebootBaseStationButton = new JButton("Reboot Base Station"); rebootBaseStationButton.setActionCommand("reboot base station"); rebootBaseStationButton.addActionListener(this); // set params for layout manager GridBagLayout theLayout = new GridBagLayout(); GridBagConstraints c = new GridBagConstraints(); c.gridwidth = 1; c.gridheight = 1; c.fill = GridBagConstraints.NONE; c.ipadx = 0; c.ipady = 0; Insets theMargin = new Insets(2,2,2,2); c.insets = theMargin; c.anchor = GridBagConstraints.CENTER; c.weightx = .5; c.weighty = .5; JPanel buttonPanel = new JPanel(); buttonPanel.setLayout(theLayout); c.gridx = 1; c.gridy = 1; theLayout.setConstraints(discoverDevicesButton, c); buttonPanel.add(discoverDevicesButton); c.gridx = 2; c.gridy = 1; theLayout.setConstraints(retrieveItemButton, c); buttonPanel.add(retrieveItemButton); c.gridx = 3; c.gridy = 1; theLayout.setConstraints(updateBaseStationButton, c); buttonPanel.add(updateBaseStationButton); /* c.gridx = 4; c.gridy = 1; theLayout.setConstraints(rebootBaseStationButton, c); buttonPanel.add(rebootBaseStationButton); */ JPanel hostPanel = new JPanel(); hostPanel.setLayout(theLayout); c.gridx = 1; c.gridy = 1; theLayout.setConstraints(hostIDLabel, c); hostPanel.add(hostIDLabel); c.gridx = 2; c.gridy = 1; theLayout.setConstraints(hostIDField, c); hostPanel.add(hostIDField); c.gridx = 3; c.gridy = 1; theLayout.setConstraints(communityLabel, c); hostPanel.add(communityLabel); c.gridx = 4; c.gridy = 1; theLayout.setConstraints(communityField, c); hostPanel.add(communityField); infoPane = new AirportInfoTabbedPane(airportInfo); JPanel messagesPanel = new JPanel(); messagesPanel.setLayout(theLayout); messagesArea = new JTextArea(4,60); JScrollPane messagesScroll = new JScrollPane(messagesArea); c.gridx = 1; c.gridy = 1; JLabel messagesLabel = new JLabel("Messages:"); theLayout.setConstraints(messagesLabel, c); messagesPanel.add(messagesLabel); c.gridx = 1; c.gridy = 2; theLayout.setConstraints(messagesScroll, c); messagesPanel.add(messagesScroll); this.getContentPane().setLayout(mainLayout); c.gridx = 1; c.gridy = 1; mainLayout.setConstraints(hostPanel, c); this.getContentPane().add(hostPanel); c.gridx = 1; c.gridy = 2; mainLayout.setConstraints(buttonPanel, c); this.getContentPane().add(buttonPanel); c.gridx = 1; c.gridy = 3; mainLayout.setConstraints(infoPane, c); this.getContentPane().add(infoPane); c.gridx = 1; c.gridy = 4; mainLayout.setConstraints(messagesPanel, c); this.getContentPane().add(messagesPanel); c.gridx = 1; c.gridy = 5; JLabel authorLabel = new JLabel(" Version 2.1 J. Sevy, April 2003 "); authorLabel.setFont(new Font("SansSerif", Font.ITALIC, 8)); mainLayout.setConstraints(authorLabel, c); this.getContentPane().add(authorLabel); } public void actionPerformed(ActionEvent theEvent) // respond to button pushes, menu selections { String command = theEvent.getActionCommand(); if (command.equals("quit")) { System.exit(0); } if (command == "about") { AboutDialog aboutDialog = new AboutDialog(this); } if (command.equals("discover devices")) { AirportDiscoverer discoverer = new AirportDiscoverer(); } if (command.equals("retrieve data")) { try { String password = communityField.getText(); InetAddress hostAddress = InetAddress.getByName(hostIDField.getText()); messagesArea.append("Retrieving settings from base station " + hostAddress + "......\n"); byte[] requestPayload = airportInfo.getRequestBytes(); Airport2ProtocolMessage requestMessage = new Airport2ProtocolMessage(Airport2ProtocolMessage.READ, password, requestPayload, requestPayload.length); // open socket int port = 5009; Socket configSocket = new Socket(hostAddress, port); // set socket timeout to 15 seconds configSocket.setSoTimeout(15000); DataInputStream inputStream = new DataInputStream(configSocket.getInputStream()); OutputStream outputStream = configSocket.getOutputStream(); outputStream.write(requestMessage.getBytes()); outputStream.flush(); /* System.out.println("Request header bytes:"); System.out.println(printHexBytes(requestMessage.getBytes())); */ outputStream.write(requestPayload); outputStream.flush(); // get and process response byte[] responseHeader = new byte[128]; inputStream.readFully(responseHeader); // create temp buffer to hold retrieved config; 20k should suffice... byte[] responsePayload = new byte[4096]; // read info try { inputStream.readFully(responsePayload); } catch (EOFException e) { // this is expected; we _should_ reach the end of the stream before filling the buffer... } /* numBytes = 0; int newNumBytes = 0; while( ((newNumBytes = inputStream.read(responsePayload, numBytes, responsePayload.length - numBytes)) >= 0 ) && (numBytes < responsePayload.length) ) { System.out.println("Read " + newNumBytes + " bytes."); numBytes += newNumBytes; } */ //System.out.println("done."); //System.out.println("Read " + numBytes + " bytes total."); inputStream.close(); outputStream.close(); configSocket.close(); // see if shift key held down when menu selected; if so, save settings // exactly as downloaded, i.e., without writing from windows; for // testing purposes boolean shiftKeyDown = ((theEvent.getModifiers() & ActionEvent.SHIFT_MASK) > 0); if (shiftKeyDown) { FileDialog fd = new FileDialog(this, "Save downloaded settings (without change) as...", FileDialog.SAVE); fd.show(); byte[] fileBytes = airportInfo.getUpdateBytes(); if (fd.getFile() != null) { File newFile = new File(fd.getDirectory(), fd.getFile()); DataOutputStream fStream = new DataOutputStream(new FileOutputStream(newFile)); // compute a checksum on the data, and pre-pend it to the file int checksum = computeChecksum(responsePayload); fStream.writeInt(checksum); fStream.write(responsePayload); fStream.flush(); fStream.close(); } } // check to see if we retrieved valid data from the base station try { airportInfo = new AirportInfo(responsePayload); messagesArea.append("Settings retrieved.\n"); // now refresh display this.refreshInfoPane(); // enable updating updateBaseStationButton.setEnabled(true); } catch(IllegalArgumentException ex) { // thrown by AirportInfo constructor if no data retrieved messagesArea.append("Error retrieving settings (check password)\n"); } } catch(UnknownHostException e) { messagesArea.append("Error retrieving settings: unknown host.\n"); } catch(SocketException e) { messagesArea.append("Error retrieving settings: " + e + "\n"); } catch(IOException e) { messagesArea.append("Error retrieving settings: timed out waiting for response.\n"); } catch (Exception e) { messagesArea.append("Error retrieving settings: " + e.getMessage() + "\n"); } } if (command.equals("save settings")) { try { // see if shift key held down when menu selected; if so, save settings // exactly as downloaded, i.e., without writing from windows; for // testing purposes boolean shiftKeyDown = ((theEvent.getModifiers() & ActionEvent.SHIFT_MASK) > 0); FileDialog fd; if (!shiftKeyDown) { infoPane.writeData(); setDependentData(); setStaticData(); performConsistencyChecks(); fd = new FileDialog(this, "Save current settings as...", FileDialog.SAVE); } else { fd = new FileDialog(this, "Save downloaded settings (without change) as...", FileDialog.SAVE); } fd.show(); byte[] fileBytes = airportInfo.getUpdateBytes(); if (fd.getFile() != null) { File newFile = new File(fd.getDirectory(), fd.getFile()); DataOutputStream fStream = new DataOutputStream(new FileOutputStream(newFile)); // compute a checksum on the data, and pre-pend it to the file int checksum = computeChecksum(fileBytes); fStream.writeInt(checksum); fStream.write(fileBytes); fStream.flush(); fStream.close(); } } catch (ValueFormatException ve) { messagesArea.append("Problem with supplied value: " + ve.getMessage() + "\n"); } catch (Exception e) { messagesArea.append("Error saving settings: " + e.getMessage() + "\n"); } } if (command.equals("update base station")) { try { infoPane.writeData(); setDependentData(); setStaticData(); performConsistencyChecks(); String password = communityField.getText(); InetAddress hostAddress = InetAddress.getByName(hostIDField.getText()); messagesArea.append("Updating settings to base station " + hostAddress + "......\n"); byte[] requestPayload = airportInfo.getUpdateBytes(); Airport2ProtocolMessage requestMessage = new Airport2ProtocolMessage(Airport2ProtocolMessage.WRITE, password, requestPayload, requestPayload.length); // open socket int port = 5009; Socket configSocket = new Socket(hostAddress, port); // set socket timeout to 15 seconds configSocket.setSoTimeout(15000); DataInputStream inputStream = new DataInputStream(configSocket.getInputStream()); OutputStream outputStream = configSocket.getOutputStream(); outputStream.write(requestMessage.getBytes()); outputStream.flush(); /* System.out.println("Request header bytes:"); System.out.println(printHexBytes(requestMessage.getBytes())); */ outputStream.write(requestPayload); outputStream.flush(); /* System.out.println("Request header payload:"); System.out.println(printHexBytes(requestPayload)); */ // get and process response byte[] responseHeader = new byte[128]; inputStream.readFully(responseHeader); /* System.out.println("Response header bytes:"); System.out.println(printHexBytes(responseHeader)); */ // create temp buffer to hold retrieved config; 20k should suffice... byte[] responsePayload = new byte[4096]; // read info int numBytes = inputStream.read(responsePayload); //System.out.println("done."); //System.out.println("Read " + numBytes + " bytes."); inputStream.close(); outputStream.close(); configSocket.close(); if (numBytes > 0) { //airportInfo = new AirportInfo(responsePayload); messagesArea.append("Settings updated.\n"); } else { messagesArea.append("\nError updating settings (check password)\n"); } } catch (ValueFormatException ve) { messagesArea.append("Problem with supplied value: " + ve.getMessage() + "\n"); } catch(UnknownHostException e) { messagesArea.append("Error updating settings: unknown host.\n"); } catch(SocketException e) { messagesArea.append("Error updating settings: " + e + "\n"); } catch(IOException e) { messagesArea.append("Error updating settings: timed out waiting for response.\n"); } catch (Exception e) { messagesArea.append("Error updating settings: " + e.getMessage() + "\n"); } } if (command.equals("reboot base station")) { try { String password = communityField.getText(); InetAddress hostAddress = InetAddress.getByName(hostIDField.getText()); messagesArea.append("Rebooting base station " + hostAddress + "......\n"); // get just the reboot info record byte[] requestPayload = airportInfo.get("acRB").getUpdateBytes(); Airport2ProtocolMessage requestMessage = new Airport2ProtocolMessage(Airport2ProtocolMessage.WRITE, password, requestPayload, requestPayload.length); // open socket int port = 5009; Socket configSocket = new Socket(hostAddress, port); // set socket timeout to 15 seconds configSocket.setSoTimeout(15000); DataInputStream inputStream = new DataInputStream(configSocket.getInputStream()); OutputStream outputStream = configSocket.getOutputStream(); outputStream.write(requestMessage.getBytes()); outputStream.flush(); /* System.out.println("Request header bytes:"); System.out.println(printHexBytes(requestMessage.getBytes())); */ outputStream.write(requestPayload); outputStream.flush(); /* System.out.println("Request header payload:"); System.out.println(printHexBytes(requestPayload)); */ // get and process response byte[] responseHeader = new byte[128]; inputStream.readFully(responseHeader); /* System.out.println("Response header bytes:"); System.out.println(printHexBytes(responseHeader)); */ // create temp buffer to hold retrieved config; 20k should suffice... byte[] responsePayload = new byte[4096]; // read info int numBytes = inputStream.read(responsePayload); //System.out.println("done."); //System.out.println("Read " + numBytes + " bytes."); inputStream.close(); outputStream.close(); configSocket.close(); if (numBytes > 0) { messagesArea.append("Base station rebooting.\n"); } else { messagesArea.append("\nError rebooting base station (check password)\n"); } } catch(UnknownHostException e) { messagesArea.append("Error rebooting base station: unknown host.\n"); } catch(SocketException e) { messagesArea.append("Error rebooting base station: " + e + "\n"); } catch(IOException e) { messagesArea.append("Error rebooting base station: timed out waiting for response.\n"); } catch (Exception e) { messagesArea.append("Error rebooting base station: " + e.getMessage() + "\n"); } } if (command.equals("open settings")) { try { FileDialog fd = new FileDialog(this, "Open settings file...", FileDialog.LOAD); fd.show(); if (fd.getFile() != null) { File newFile = new File(fd.getDirectory(), fd.getFile()); DataInputStream fStream = new DataInputStream(new FileInputStream(newFile)); int existingChecksum = fStream.readInt(); byte[] newBytes = new byte[(int)newFile.length() - 4]; fStream.readFully(newBytes); fStream.close(); // check checksum to make sure block is valid, at least... int computedChecksum = computeChecksum(newBytes); if (computedChecksum == existingChecksum) { airportInfo = new AirportInfo(newBytes); messagesArea.append("Settings opened.\n"); // now refresh display of data this.refreshInfoPane(); // enable updating updateBaseStationButton.setEnabled(true); } else { messagesArea.append("Invalid configuration file.\n"); } } } catch (Exception e) { messagesArea.append("Error opening settings: " + e.getMessage() + "\n"); } } if (command.equals("upload firmware")) { try { FileDialog fd = new FileDialog(this, "Select firmware file...", FileDialog.LOAD); fd.show(); if (fd.getFile() != null) { File firmwareFile = new File(fd.getDirectory(), fd.getFile()); DataInputStream fStream = new DataInputStream(new FileInputStream(firmwareFile)); int fileLength = (int)firmwareFile.length(); // read in firmware image int flashSize = 0x180000; byte[] firmwareBytes = new byte[flashSize]; // check first to see if this should be interpreted as a MacBinary file; // read 128 bytes for header, and check if have type/creator fields // first make sure file big enough to hold MacBinary header if (fileLength < 128) throw new Exception("invalid firmware file."); // read in MacBinary header, for verification purposes fStream.read(firmwareBytes, 0, 128); /* System.out.println("Mac file header:"); System.out.println(printHexBytes(macFileHeader)); */ int dataLength = 0; // get file type and creator String fileTypeCreator = new String(firmwareBytes, 65, 8); if (fileTypeCreator.equals("bin21wcu")) { System.out.println("Mac file"); // it's a Mac file; get length of data fork for (int i = 83; i < 87; i++) { dataLength *= 256; int byteValue = (int)firmwareBytes[i]; if (byteValue < 0) byteValue += 256; dataLength += byteValue; } /* System.out.println("Data length bytes: " + hexByte(macFileHeader[83]) + " " + hexByte(macFileHeader[84]) + " " + hexByte(macFileHeader[85]) + " " + hexByte(macFileHeader[86]) + " " ); */ if (fileLength - 128 < dataLength) throw new Exception("invalid firmware file."); // read in firmware bytes, overwriting Mac header fStream.read(firmwareBytes, 0, dataLength); } else { // no Mac header - just straight firmware // read in remaining stuff System.out.println("Not a Mac file"); dataLength = fileLength; fStream.read(firmwareBytes, 128, fileLength); } //System.out.println("Read bytes: 0x" + Integer.toHexString(numbytes) + " of 0x" + Integer.toHexString(dataLength)); fStream.close(); // compute CRC32 on firmware image, up to the checksum... /* CRC32 crc = new CRC32(); crc.update(firmwareBytes, 0, flashSize - 4); System.out.println("CRC32 checksum: 0x" + Long.toHexString(crc.getValue())); crc.reset(); crc.update(firmwareBytes, 0, dataLength - 4); System.out.println("CRC32 checksum: 0x" + Long.toHexString(crc.getValue())); Adler32 adler = new Adler32(); adler.update(firmwareBytes, 0, flashSize - 4); System.out.println("Adler32 checksum: 0x" + Long.toHexString(adler.getValue())); adler.reset(); adler.update(firmwareBytes, 0, dataLength - 4); System.out.println("Adler32 checksum: 0x" + Long.toHexString(adler.getValue())); long testSum = 0; for (int i = 0; i < dataLength - 4; i++) { testSum += firmwareBytes[i]; if (firmwareBytes[i] < 0) testSum += 256; } System.out.println("Test sum: 0x" + Long.toHexString(testSum)); */ System.out.println("Original checksum: " + hexByte(firmwareBytes[dataLength - 8]) + " " + hexByte(firmwareBytes[dataLength - 7]) + " " + hexByte(firmwareBytes[dataLength - 6]) + " " + hexByte(firmwareBytes[dataLength - 5]) + " " + hexByte(firmwareBytes[dataLength - 4]) + " " + hexByte(firmwareBytes[dataLength - 3]) + " " + hexByte(firmwareBytes[dataLength - 2]) + " " + hexByte(firmwareBytes[dataLength - 1]) + " " ); // move checksum on firmware file to last 8 bytes ... firmwareBytes[flashSize - 8] = firmwareBytes[dataLength - 8]; firmwareBytes[flashSize - 7] = firmwareBytes[dataLength - 7]; firmwareBytes[flashSize - 6] = firmwareBytes[dataLength - 6]; firmwareBytes[flashSize - 5] = firmwareBytes[dataLength - 5]; //firmwareBytes[flashSize - 4] = firmwareBytes[dataLength - 4]; //firmwareBytes[flashSize - 3] = firmwareBytes[dataLength - 3]; //firmwareBytes[flashSize - 2] = firmwareBytes[dataLength - 2]; //firmwareBytes[flashSize - 1] = firmwareBytes[dataLength - 1]; firmwareBytes[dataLength - 8] = 0; firmwareBytes[dataLength - 7] = 0; firmwareBytes[dataLength - 6] = 0; firmwareBytes[dataLength - 5] = 0; firmwareBytes[dataLength - 4] = 0; firmwareBytes[dataLength - 3] = 0; firmwareBytes[dataLength - 2] = 0; firmwareBytes[dataLength - 1] = 0; // compute Adler32 on firmware image, up to the checksum... Adler32 adler = new Adler32(); adler.update(firmwareBytes, 0, flashSize - 4); long adlerValue = adler.getValue(); System.out.println("Adler32 checksum: 0x" + Long.toHexString(adlerValue)); firmwareBytes[flashSize - 4] = (byte)((adlerValue & 0xFF000000) >> 24); firmwareBytes[flashSize - 3] = (byte)((adlerValue & 0x00FF0000) >> 16); firmwareBytes[flashSize - 2] = (byte)((adlerValue & 0x0000FF00) >> 8); firmwareBytes[flashSize - 1] = (byte)(adlerValue & 0x000000FF); System.out.println("Firmware checksum: " + hexByte(firmwareBytes[flashSize - 8]) + " " + hexByte(firmwareBytes[flashSize - 7]) + " " + hexByte(firmwareBytes[flashSize - 6]) + " " + hexByte(firmwareBytes[flashSize - 5]) + " " + hexByte(firmwareBytes[flashSize - 4]) + " " + hexByte(firmwareBytes[flashSize - 3]) + " " + hexByte(firmwareBytes[flashSize - 2]) + " " + hexByte(firmwareBytes[flashSize - 1]) + " " ); // put up a dialog permitting the user to select uploading the current settings, if // they're valid... String messageString = "Upload firmware to base station " + hostIDField.getText() + "?"; String response = new String("Cancel"); String[] possibleValues = { "Upload firmware", "Cancel" }; int selectedValue = JOptionPane.showOptionDialog(null, messageString, "Firmware Upload", JOptionPane.YES_NO_OPTION, JOptionPane.INFORMATION_MESSAGE, null, possibleValues, possibleValues[0]); if ( !(selectedValue == JOptionPane.CLOSED_OPTION) ) response = possibleValues[selectedValue]; if (response.equals("Upload firmware")) { // transmit firmware info String password = communityField.getText(); InetAddress hostAddress = InetAddress.getByName(hostIDField.getText()); // open socket int port = 5009; Socket configSocket = new Socket(hostAddress, port); // set socket timeout to 45 seconds configSocket.setSoTimeout(45000); DataInputStream inputStream = new DataInputStream(configSocket.getInputStream()); OutputStream outputStream = configSocket.getOutputStream(); Airport2ProtocolMessage requestMessage = new Airport2ProtocolMessage(Airport2ProtocolMessage.WRITE_RAW, password, firmwareBytes, firmwareBytes.length); outputStream.write(requestMessage.getBytes()); outputStream.flush(); /* System.out.println("Request header bytes:"); System.out.println(printHexBytes(requestMessage.getBytes())); */ outputStream.write(firmwareBytes); outputStream.flush(); /* System.out.println("Request header payload:"); System.out.println(printHexBytes(requestPayload)); */ // get and process response byte[] responseHeader = new byte[128]; inputStream.readFully(responseHeader); /* System.out.println("Response header bytes:"); System.out.println(printHexBytes(responseHeader)); */ Airport2ProtocolMessage responseMessage = new Airport2ProtocolMessage(responseHeader); //System.out.println(responseMessage.toString()); // check status field, to see if successful if (responseMessage.status < 0) throw new Exception("base station refused update - invalid firmware file"); // now reboot base station to get it to read the new firmware image messagesArea.append("Rebooting base station " + hostAddress + "......\n"); // get just the reboot info record byte[] requestPayload = airportInfo.get("acRB").getUpdateBytes(); requestMessage = new Airport2ProtocolMessage(Airport2ProtocolMessage.WRITE, password, requestPayload, requestPayload.length); // open new socket configSocket = new Socket(hostAddress, port); // set socket timeout to 15 seconds configSocket.setSoTimeout(15000); inputStream = new DataInputStream(configSocket.getInputStream()); outputStream = configSocket.getOutputStream(); outputStream.write(requestMessage.getBytes()); outputStream.flush(); /* System.out.println("Request header bytes:"); System.out.println(printHexBytes(requestMessage.getBytes())); */ outputStream.write(requestPayload); outputStream.flush(); /* System.out.println("Request header payload:"); System.out.println(printHexBytes(requestPayload)); */ // get and process response responseHeader = new byte[128]; inputStream.readFully(responseHeader); /* System.out.println("Response header bytes:"); System.out.println(printHexBytes(responseHeader)); */ responseMessage = new Airport2ProtocolMessage(responseHeader); //System.out.println(responseMessage.toString()); // check status field, to see if successful if (responseMessage.status < 0) throw new Exception("base station refused to reboot!"); // create temp buffer to hold response message... byte[] responsePayload = new byte[4096]; // read info int numBytes = inputStream.read(responsePayload); //System.out.println("done."); //System.out.println("Read " + numBytes + " bytes."); inputStream.close(); outputStream.close(); configSocket.close(); if (numBytes > 0) { //airportInfo = new AirportInfo(responsePayload); messagesArea.append("Base station rebooting.\n"); } else { messagesArea.append("\nError rebooting base station (check password)\n"); } } } } catch(UnknownHostException e) { messagesArea.append("Error updating firmware: unknown host.\n"); } catch(SocketException e) { messagesArea.append("Error updating firmware: " + e + "\n"); } catch(IOException e) { messagesArea.append("Error updating firmware: timed out waiting for response - check password.\n"); } catch (Exception e) { messagesArea.append("Error updating firmware: " + e.getMessage() + "\n"); } } } private String hexByte(byte b) { int pos = b; if (pos < 0) pos += 256; String returnString = new String(); returnString += Integer.toHexString(pos/16); returnString += Integer.toHexString(pos%16); return returnString; } private void refreshInfoPane() { // first, remove current infoPane this.remove(infoPane); //now create new tabbed pane to hold info infoPane = new AirportInfoTabbedPane(airportInfo); // set params for layout manager GridBagConstraints c = new GridBagConstraints(); c.gridwidth = 1; c.gridheight = 1; c.fill = GridBagConstraints.NONE; c.ipadx = 0; c.ipady = 0; Insets theMargin = new Insets(2,2,2,2); c.insets = theMargin; c.anchor = GridBagConstraints.CENTER; c.weightx = .5; c.weighty = .5; // then add pane to frame c.gridx = 1; c.gridy = 3; mainLayout.setConstraints(infoPane, c); this.getContentPane().add(infoPane); // call validate to update display this.validate(); } private void setDependentData() throws ValueFormatException { // if connecting to WAN through modem, and DHCP service selected on Ethernet, // deliver also on WAN interface AirportInfoRecord configInterfaceRecord = airportInfo.get("waIn"); AirportInfoRecord dhcpLANRecord = airportInfo.get("laDS"); AirportInfoRecord dhcpWANRecord = airportInfo.get("waDS"); if (configInterfaceRecord.toString().equals("00000004")) { // connecting through modem: turn on DHCP service through WAN interface // if also configured to go through LAN interface if (dhcpLANRecord.toString().equals("01")) { dhcpWANRecord.setBytesFromString("01"); } else { dhcpWANRecord.setBytesFromString("00"); } } } private void performConsistencyChecks() throws ValueFormatException { // check that manual Ethernet config is being used if DHCP without NAT is selected // necessary since the WAN address configured becomes the gateway delivered by DHCP AirportInfoRecord wanConfigRecord = airportInfo.get("waCV"); AirportInfoRecord natRecord = airportInfo.get("raNA"); AirportInfoRecord dhcpWirelessRecord = airportInfo.get("raDS"); AirportInfoRecord dhcpLANRecord = airportInfo.get("laDS"); AirportInfoRecord dhcpWANRecord = airportInfo.get("waDS"); if (natRecord.toString().equals("00")) { // NAT off - wireless bridge mode // see if DHCP service is being provided if (dhcpWirelessRecord.toString().equals("01") || dhcpLANRecord.toString().equals("01") || dhcpWANRecord.toString().equals("01")) { // make sure manual Ethernet config is being provided; // if not, throw a ValueFormatException if (!wanConfigRecord.toString().equals("00000400")) { throw new ValueFormatException("Must use manual Ethernet configuration (Network Panel) when providing DHCP service (DHCP Panel)\nin transparent bridge mode (Bridging Panel)"); } } } // if using manual Ethernet config,check that base station IP address, router address and mask are consistent if (wanConfigRecord.toString().equals("00000400")) { byte[] wanIPBytes = airportInfo.get("waIP").getValue(); byte[] wanRouterIPBytes = airportInfo.get("waRA").getValue(); byte[] wanMaskBytes = airportInfo.get("waSM").getValue(); wanRouterIPBytes = maskBytes(wanRouterIPBytes, wanMaskBytes); wanIPBytes = maskBytes(wanIPBytes, wanMaskBytes); if ( !arraysEqual(wanRouterIPBytes, wanIPBytes) ) { throw new ValueFormatException("Router IP address inconsistent with base station IP address and subnet mask (Network Panel)"); } } // check that router address lies in DHCP subnet when providing DHCP service // look at different fields depending on whether providing NAT or doing transparent bridging // see if DHCP service is being provided if (dhcpWirelessRecord.toString().equals("01") || dhcpLANRecord.toString().equals("01") || dhcpWANRecord.toString().equals("01")) { byte[] dhcpBeginBytes = airportInfo.get("dhBg").getValue(); byte[] dhcpEndBytes = airportInfo.get("dhEn").getValue(); if (natRecord.toString().equals("00")) { // NAT off - wireless bridge mode // check WAN IP address, subnet mask; will have already checked above that // manual config is being used byte[] wanRouterIPBytes = airportInfo.get("waRA").getValue(); byte[] wanMaskBytes = airportInfo.get("waSM").getValue(); wanRouterIPBytes = maskBytes(wanRouterIPBytes, wanMaskBytes); dhcpBeginBytes = maskBytes(dhcpBeginBytes, wanMaskBytes); dhcpEndBytes = maskBytes(dhcpEndBytes, wanMaskBytes); if ( !arraysEqual(wanRouterIPBytes, dhcpBeginBytes) || !arraysEqual(wanRouterIPBytes, dhcpEndBytes)) { throw new ValueFormatException("DHCP range (DHCP Panel) inconssistent with router IP address and subnet mask (Network Panel)"); } } else { // NAT on // check LAN IP address, subnet mask byte[] lanIPBytes = airportInfo.get("laIP").getValue(); byte[] lanMaskBytes = airportInfo.get("laSM").getValue(); lanIPBytes = maskBytes(lanIPBytes, lanMaskBytes); dhcpBeginBytes = maskBytes(dhcpBeginBytes, lanMaskBytes); dhcpEndBytes = maskBytes(dhcpEndBytes, lanMaskBytes); if ( !arraysEqual(lanIPBytes, dhcpBeginBytes) || !arraysEqual(lanIPBytes, dhcpEndBytes)) { throw new ValueFormatException("DHCP range (DHCP Panel) inconsistent with base station private LAN IP address and subnet mask (Bridging Panel)"); } } } } private void setStaticData() throws ValueFormatException { // set read community password field AirportInfoRecord readCommunityRecord = airportInfo.get("syPR"); readCommunityRecord.setBytesFromString("public"); // Set community name into password field so base station will know what to use after reboot! // Find out if there's an entry in the main panel; if so, use this, otherwise use // current community name field AirportInfoRecord communityNameRecord = airportInfo.get("syPW"); String communityName = communityNameRecord.toString(); if (communityName.equals("")) communityName = communityField.getText(); communityNameRecord.setBytesFromString(communityName); } private int computeChecksum(byte[] fileBytes) { int checksum = 0; for (int i = 0; i < fileBytes.length; i++) { checksum += fileBytes[i]; } return checksum; } private String printHexBytes(byte[] bytes) { String returnString = new String(); for(int i = 0; i < bytes.length; i++) { returnString += hexByte(bytes[i]) + " "; if (((i+1)%16) == 0) returnString += "\n"; } return returnString; } private static boolean arraysEqual(byte[] a, byte[] b) { if (a.length != b.length) { return false; } else { for (int i = 0; i < a.length; i++) { if (a[i] != b[i]) return false; } } return true; } private static byte[] maskBytes(byte[] inBytes, byte[] mask) { byte[] maskedBytes = new byte[inBytes.length]; for (int i = 0; i < inBytes.length; i++) { maskedBytes[i] = (byte)(inBytes[i] & mask[i % inBytes.length]); } return maskedBytes; } public static void main(String args[]) { try { AirportBaseStationConfigurator theApp = new AirportBaseStationConfigurator(); theApp.pack(); // tweak app size to make it a little larger than necessary, to address the // "shrunken textfields" problem arising from the layout manager packing stuff // a little too tightly. Dimension dim = theApp.getSize(); dim.height += 20; dim.width += 20; theApp.setSize(dim); theApp.show(); } catch (Exception e) {} } }airport2config-2.0.1/COPYING0000444000175000017500000004363107503646703015052 0ustar julienjulien GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) 19yy This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) 19yy name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. airport2config-2.0.1/airport/0000755000175000017500000000000010420572732015462 5ustar julienjulienairport2config-2.0.1/airport/AirportAccessControlTable.java0000644000175000017500000002126507503646703023416 0ustar julienjulien/* * AirportBaseStationConfigurator * * Copyright (C) 2000, Jonathan Sevy * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ package airport; import java.awt.*; import java.awt.event.*; import java.util.*; import java.io.*; import javax.swing.*; import javax.swing.event.*; import javax.swing.table.*; /** * Handles display and updating of MAC addresses and host names used for access control on the * wireless LAN. */ public class AirportAccessControlTable extends AirportInfoPanel { private AirportInfo airportInfo; private Vector addressVector; private JTable table; private AbstractTableModel tableModel; /** * Table model which maintains list of MAC addresses and host names. */ private class AccessAddressTableModel extends AbstractTableModel { public int getColumnCount() { return 2; } public int getRowCount() { return AirportInfo.MAX_NUM_MAC_ADDRESSES; } public boolean isCellEditable(int row, int col) { if (row <= addressVector.size()) return true; else return false; } public String getColumnName(int col) { if (col == 0) return "MAC address"; else return "Host name (opt)"; } public Object getValueAt(int row, int col) { if (row < addressVector.size()) return ((String[])addressVector.elementAt(row))[col]; else return ""; } public void setValueAt(Object newValue, int row, int col) { if (newValue instanceof String) { if (row < addressVector.size()) { String[] addressEntry = (String[])addressVector.elementAt(row); addressEntry[col] = (String)newValue; } else { String[] addressEntry = {"",""}; addressEntry[col] = (String)newValue; addressVector.insertElementAt(addressEntry, addressVector.size()); } } } } /** * Create new table based on data in airportInfo. */ public AirportAccessControlTable(AirportInfo airportInfo) { this.airportInfo = airportInfo; setUpDisplay(); } private void setUpDisplay() { refreshDisplay(); } /** * Write the MAC addresses and hostnames in the list as concatenated 40-byte strings. Format is: * - first 8 bytes get number of port maps * - next 8 bytes are 0 * - following are concatenated MAC address / hostname blocks * @throws ValueFormatException Thrown if either a MAC address is malformed, or hostname * is too long. Also sets editting focus to the offending cell. */ public void writeValue() throws ValueFormatException { // first, record changes if cell currently being edited TableCellEditor editor = table.getCellEditor(); if(editor != null) editor.stopCellEditing(); int numMacAddresses = 0; Vector addressRecordVector = new Vector(); Vector nameRecordVector = new Vector(); for (int i = 0; i < addressVector.size(); i++) { try { // these only get augmented if address is OK (and non-null) if (! ((String[])this.addressVector.elementAt(i))[0].equals("")) { // create a new info record to qualify the address and convert to bytes AirportInfoRecord addressRecord = new AirportInfoRecord("temp", "temp", AirportInfoRecord.BYTE_STRING, AirportInfoRecord.UNENCRYPTED, 6); addressRecord.setBytesFromString(((String[])this.addressVector.elementAt(i))[0]); addressRecordVector.add(addressRecord); numMacAddresses++; } else { // skip this record continue; } } catch (ValueFormatException e) { table.editCellAt(i,0); throw e; } try { AirportInfoRecord nameRecord = new AirportInfoRecord("temp", "temp", AirportInfoRecord.CHAR_STRING, AirportInfoRecord.UNENCRYPTED, 32); nameRecord.setBytesFromString(((String[])this.addressVector.elementAt(i))[1]); // now expand size of byte array to 34 bytes by appending 0's ByteArrayOutputStream outStream = new ByteArrayOutputStream(); try { outStream.write(nameRecord.value); byte[] padBytes = new byte[34 - nameRecord.value.length]; outStream.write(padBytes); } catch (IOException e) { // shouldn't ever happen... } nameRecord.value = outStream.toByteArray(); nameRecordVector.add(nameRecord); } catch (ValueFormatException e) { table.editCellAt(i,1); throw e; } } // now create concatenation try { ByteArrayOutputStream outStream = new ByteArrayOutputStream(); // write 4-byte padding of 0's byte[] zeroBytes = new byte[4]; outStream.write(zeroBytes); // do length; use info record to create 4-byte value AirportInfoRecord sizeRecord = new AirportInfoRecord("temp", "temp", AirportInfoRecord.UNSIGNED_INTEGER, AirportInfoRecord.UNENCRYPTED, 4); sizeRecord.setBytesFromString(Integer.toString(numMacAddresses)); outStream.write(sizeRecord.value); // write 8-byte padding of 0's zeroBytes = new byte[8]; outStream.write(zeroBytes); // now write addresses and hostnames for (int i = 0; i < numMacAddresses; i++) { outStream.write(((AirportInfoRecord)addressRecordVector.elementAt(i)).value); outStream.write(((AirportInfoRecord)nameRecordVector.elementAt(i)).value); } // now use this to set the value of the associated info record AirportInfoRecord accessControlRecord = airportInfo.get("acTa"); accessControlRecord.setValue(outStream.toByteArray()); // also, set access control switch: on if any Mac entries, off otherwise /** * Access control switch: * 00 = no access control * 01 = access control used */ String accessSwitchValue = new String(); if (numMacAddresses > 0) accessSwitchValue = "01"; else accessSwitchValue = "00"; AirportInfoRecord accessControlSwitchRecord = airportInfo.get("acEn"); accessControlSwitchRecord.setBytesFromString(accessSwitchValue); } catch (IOException e) { // shouldn't ever happen... } } /** * Refresh the display based on the current data in the associated info record */ public void refreshDisplay() { // create new addressVector, with appropriate size addressVector = new Vector(); AirportInfoRecord accessControlRecord = airportInfo.get("acTa"); byte[] accessControlBytes = accessControlRecord.getValue(); DataInputStream inStream = new DataInputStream(new ByteArrayInputStream(accessControlBytes)); try { // Read first 4 bytes of 0 padding inStream.skip(4); // Read in number of Mac addresses (next 4 bytes) int numMacAddresses = inStream.readInt(); // Read next 8 bytes of 0 padding inStream.skip(8); for (int i = 0; i < numMacAddresses; i++) { byte[] addressBytes = new byte[6]; inStream.read(addressBytes); AirportInfoRecord addressRecord = new AirportInfoRecord("temp", "temp", AirportInfoRecord.BYTE_STRING, AirportInfoRecord.UNENCRYPTED, 6, addressBytes); byte[] nameBytes = new byte[34]; inStream.read(nameBytes); AirportInfoRecord nameRecord = new AirportInfoRecord("temp", "temp", AirportInfoRecord.CHAR_STRING, AirportInfoRecord.UNENCRYPTED, 34, nameBytes); String[] addressEntry = new String[2]; addressEntry[0] = addressRecord.toString(); addressEntry[1] = nameRecord.toString(); addressVector.insertElementAt(addressEntry, addressVector.size()); } this.removeAll(); tableModel = new AccessAddressTableModel(); table = new JTable(tableModel); table.setCellSelectionEnabled(true); table.setPreferredScrollableViewportSize(new Dimension(350,200)); JScrollPane scrollPane = new JScrollPane(table); this.add(scrollPane); } catch (IOException e) { // shouldn't ever happen... } } }airport2config-2.0.1/airport/AirportBridgingPanel.java0000644000175000017500000001417507503646703022413 0ustar julienjulien/* * AirportBaseStationConfigurator * * Copyright (C) 2000, Jonathan Sevy * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ package airport; import java.awt.*; import javax.swing.*; /** * Panel which maintains data relevant to bridging (plus address allocation via DHCP and NAT). */ public class AirportBridgingPanel extends AirportInfoPanel { private AirportInfoRadioButton transparentBridgeButton, natButton; private ButtonGroup radioButtonGroup; private AirportInfoPanel natInfoPanel; private AirportInfoCheckBox natOnEthernetCheckbox, disableBridgingCheckbox; private AirportInfoLabelledTextField natInboundPrivateAddressBase, natInboundPrivateAddressMask; //private AirportInfoTextField natOutboundPrivateAddressBase, natOutboundPrivateAddressMask; private AirportInfo theInfo; /** * Create new panel based on data referenced through the supplied AirportInfo object. */ public AirportBridgingPanel(AirportInfo theInfo) { this.theInfo = theInfo; /** * Transparent bridge/NAT switch: * 00 = act as transparent bridge * 01 = NAT on */ transparentBridgeButton = new AirportInfoRadioButton("Act as transparent bridge (no NAT)"); transparentBridgeButton.addInfoRecord(theInfo.get("raNA"), "00"); // make sure bridging is enabled transparentBridgeButton.addInfoRecord(theInfo.get("raWB"), "01"); natButton = new AirportInfoRadioButton("Provide network address translation (NAT)"); natButton.addInfoRecord(theInfo.get("raNA"), "01"); radioButtonGroup = new ButtonGroup(); radioButtonGroup.add(transparentBridgeButton); radioButtonGroup.add(natButton); natInboundPrivateAddressBase = new AirportInfoLabelledTextField("Private LAN base station address", theInfo.get("laIP")); natInboundPrivateAddressMask = new AirportInfoLabelledTextField("Private LAN subnet mask", theInfo.get("laSM")); // these two won't appear, but will instead be set from above two when value is written //natOutboundPrivateAddressBase = new AirportInfoTextField(theInfo.get("NAT outbound private IP address")); //natOutboundPrivateAddressMask = new AirportInfoTextField(theInfo.get("NAT outbound private subnet mask")); //*****natOnEthernetCheckbox = new AirportInfoCheckBox("Provide NAT on Ethernet port, too",theInfo.get("Ethernet DHCP switch"), "40", "00"); disableBridgingCheckbox = new AirportInfoCheckBox("Disable bridging between Ethernet port and wireless LAN",theInfo.get("raWB"), "00", "01"); // create panel to hold NAT info to be disabled when in transparent bridge mode natInfoPanel = new AirportInfoPanel(); setUpDisplay(); } private void setUpDisplay() { //this.setOpaque(true); //this.setBackground(Color.white); // set params for layout manager GridBagLayout theLayout = new GridBagLayout(); GridBagConstraints c = new GridBagConstraints(); c.gridwidth = 1; c.gridheight = 1; c.fill = GridBagConstraints.NONE; c.ipadx = 0; c.ipady = 0; Insets theMargin = new Insets(2,2,2,2); c.insets = theMargin; c.anchor = GridBagConstraints.CENTER; c.weightx = 0; c.weighty = 0; JLabel theLabel; // add stuff to NAT panel natInfoPanel.setLayout(theLayout); c.anchor = GridBagConstraints.EAST; c.gridx = 1; c.gridy = 1; theLayout.setConstraints(natInboundPrivateAddressBase, c); natInfoPanel.add(natInboundPrivateAddressBase); c.gridx = 1; c.gridy = 2; theLayout.setConstraints(natInboundPrivateAddressMask, c); natInfoPanel.add(natInboundPrivateAddressMask); c.anchor = GridBagConstraints.WEST; c.gridx = 1; c.gridy = 3; theLayout.setConstraints(disableBridgingCheckbox, c); natInfoPanel.add(disableBridgingCheckbox); // add stuff to this this.setLayout(theLayout); c.anchor = GridBagConstraints.WEST; c.gridx = 1; c.gridy = 1; theLayout.setConstraints(transparentBridgeButton, c); this.add(transparentBridgeButton); c.gridx = 1; c.gridy = 2; theLayout.setConstraints(natButton, c); this.add(natButton); c.gridx = 1; c.gridy = 3; theLayout.setConstraints(natInfoPanel, c); this.add(natInfoPanel); // make natInfoPanel enabled status dependent on button status natButton.addItemListener(natInfoPanel); natInfoPanel.setEnabled(natButton.isSelected()); } public void writeValue() throws ValueFormatException { super.writeValue(); if (natInfoPanel.isEnabled()) { // sanity-check the private IP address to make sure it's not 0.0.0.0, // to correct an issue with the RG-1000; write and read the value to // eliminate spaces, etc. natInboundPrivateAddressBase.writeValue(); String privateIP = theInfo.get("laIP").toString(); if (privateIP.equals("0.0.0.0")) { // select text in panel natInboundPrivateAddressBase.theField.selectAll(); natInboundPrivateAddressBase.theField.requestFocus(); // throw exception throw new ValueFormatException("Private LAN IP address in Bridging panel can't be 0.0.0.0"); } // write private address base and subnet mask into outgoing NAT fields; // incoming fields are attached to the info text fields //natOutboundPrivateAddressBase.writeValue(natInboundPrivateAddressBase.getText()); //natOutboundPrivateAddressMask.writeValue(natInboundPrivateAddressMask.getText()); } } }airport2config-2.0.1/airport/AirportLoginInfoPanel.java0000644000175000017500000000666707503646703022561 0ustar julienjulien/* * AirportBaseStationConfigurator * * Copyright (C) 2000, Jonathan Sevy * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ package airport; import java.awt.*; import javax.swing.*; /** * Panel which maintains data pertaining to modem connection login, with settings for * username, password and login string. */ public class AirportLoginInfoPanel extends AirportInfoPanel { private AirportUsernamePanel usernamePanel; //private AirportLoginStringTable loginStringTable; //private AirportInfoRadioButton userPassButton, loginStringButton; //private ButtonGroup loginSelectGroup; public AirportLoginInfoPanel(AirportInfo theInfo) { /* loginStringButton = new AirportInfoRadioButton("Use login script:"); userPassButton = new AirportInfoRadioButton("Use Username/Password:"); loginSelectGroup = new ButtonGroup(); loginSelectGroup.add(loginStringButton); loginSelectGroup.add(userPassButton); */ // panel holding dial-up username / password usernamePanel = new AirportUsernamePanel(theInfo); // table maintaining login string info //loginStringTable = new AirportLoginStringTable(theInfo); setUpDisplay(); } public void setUpDisplay() { // set params for layout manager GridBagLayout theLayout = new GridBagLayout(); GridBagConstraints c = new GridBagConstraints(); c.gridwidth = 1; c.gridheight = 1; c.fill = GridBagConstraints.NONE; c.ipadx = 0; c.ipady = 0; c.insets = new Insets(2,2,2,2); c.anchor = GridBagConstraints.CENTER; c.weightx = .5; c.weighty = .5; JLabel label; this.setLayout(theLayout); // add components c.insets = new Insets(8,2,2,2); c.gridx = 1; c.gridy = 1; theLayout.setConstraints(usernamePanel, c); this.add(usernamePanel); /* c.anchor = GridBagConstraints.WEST; c.insets = new Insets(8,2,2,2); c.gridx = 1; c.gridy = 2; theLayout.setConstraints(userPassButton, c); this.add(userPassButton); c.insets = new Insets(2,2,2,2); c.gridx = 1; c.gridy = 3; theLayout.setConstraints(loginStringButton, c); this.add(loginStringButton); c.anchor = GridBagConstraints.CENTER; c.insets = new Insets(8,2,2,2); c.gridx = 1; c.gridy = 4; theLayout.setConstraints(loginStringTable, c); this.add(loginStringTable); // make login string table enabling dependent on button settings loginStringButton.addItemListener(loginStringTable); loginStringTable.setEnabled(loginStringButton.isSelected()); // make username/password panel enabling dependent on button settings userPassButton.addItemListener(usernamePanel); usernamePanel.setEnabled(userPassButton.isSelected()); */ } }airport2config-2.0.1/airport/AirportDHCPRangePanel.java0000644000175000017500000000641207503646703022354 0ustar julienjulien/* * AirportBaseStationConfigurator * * Copyright (C) 2000, Jonathan Sevy * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ package airport; import java.awt.*; import javax.swing.*; /** * Sub-panel of bridging panel which maintains range of addresses served by base station when * acting as DHCP or NAT server. */ public class AirportDHCPRangePanel extends AirportInfoPanel { private AirportInfoTextField dhcpStartField, dhcpEndField; /** * Create new panel with start and end address for range taken from byte block referenced * in supplied AirportInfo object. */ public AirportDHCPRangePanel(AirportInfo theInfo) { dhcpStartField = new AirportInfoTextField(theInfo.get("dhBg")); dhcpEndField = new AirportInfoTextField(theInfo.get("dhEn")); setUpDisplay(); } /** * Create new panel with specified start and end address for range. Used to set default values * when required (e.g., range for NAT). */ public AirportDHCPRangePanel(AirportInfo theInfo, String defaultStartAddress, String defaultEndAddress) // use supplied default values, unless empty string supplied, whence use retrieved value { dhcpStartField = new AirportInfoTextField(theInfo.get("dhBg")); dhcpStartField.setText(defaultStartAddress); dhcpEndField = new AirportInfoTextField(theInfo.get("dhEn")); dhcpEndField.setText(defaultEndAddress); setUpDisplay(); } private void setUpDisplay() { // set params for layout manager GridBagLayout theLayout = new GridBagLayout(); GridBagConstraints c = new GridBagConstraints(); c.gridwidth = 1; c.gridheight = 1; c.fill = GridBagConstraints.NONE; c.ipadx = 0; c.ipady = 0; Insets theMargin = new Insets(2,2,2,2); c.insets = theMargin; c.anchor = GridBagConstraints.CENTER; c.weightx = .5; c.weighty = .5; JLabel theLabel; // textfields; put in panel this.setLayout(theLayout); c.anchor = GridBagConstraints.EAST; c.gridx = 1; c.gridy = 1; theLabel = new JLabel("Address range start"); theLayout.setConstraints(theLabel, c); this.add(theLabel); c.gridx = 1; c.gridy = 2; theLabel = new JLabel("Address range end"); theLayout.setConstraints(theLabel, c); this.add(theLabel); c.anchor = GridBagConstraints.WEST; c.gridx = 2; c.gridy = 1; theLayout.setConstraints(dhcpStartField, c); this.add(dhcpStartField); c.gridx = 2; c.gridy = 2; theLayout.setConstraints(dhcpEndField, c); this.add(dhcpEndField); } }airport2config-2.0.1/airport/AirportDiscoverer.java0000644000175000017500000001730007503646703022004 0ustar julienjulien/* * AirportBaseStationConfigurator * * Copyright (C) 2000, Jonathan Sevy * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ package airport; import java.util.*; import java.net.*; import java.awt.*; import java.awt.event.*; import java.io.*; import javax.swing.*; /** * Broadcasts discovery packet, waits for responses. Displays responding devices' IP addresses, * names, and device-type identifying strings. */ public class AirportDiscoverer extends JFrame implements ActionListener, Runnable { JButton stopDiscoveryButton, closeButton; JTextArea theArea; Thread discoveryThread; public AirportDiscoverer() { setUpDisplay(); this.pack(); this.show(); discoveryThread = new Thread(this); discoveryThread.start(); } private void setUpDisplay() { this.setTitle("Base Station Discovery"); stopDiscoveryButton = new JButton("Stop Discovery"); stopDiscoveryButton.setActionCommand("stop discovery"); stopDiscoveryButton.addActionListener(this); closeButton = new JButton("Close"); closeButton.setActionCommand("close"); closeButton.addActionListener(this); theArea = new JTextArea(20,70); theArea.setLineWrap(true); theArea.setFont(new Font("Monospaced", Font.PLAIN, 10)); JScrollPane messagesScroll = new JScrollPane(theArea); // set params for layout manager GridBagLayout theLayout = new GridBagLayout(); GridBagConstraints c = new GridBagConstraints(); c.gridwidth = 1; c.gridheight = 1; c.fill = GridBagConstraints.NONE; c.ipadx = 0; c.ipady = 0; Insets theMargin = new Insets(2,2,2,2); c.insets = theMargin; c.anchor = GridBagConstraints.CENTER; c.weightx = .5; c.weighty = .5; JPanel buttonPanel = new JPanel(); buttonPanel.setLayout(theLayout); c.gridx = 1; c.gridy = 1; theLayout.setConstraints(stopDiscoveryButton, c); buttonPanel.add(stopDiscoveryButton); c.gridx = 2; c.gridy = 1; theLayout.setConstraints(closeButton, c); buttonPanel.add(closeButton); this.getContentPane().setLayout(new BorderLayout(5,5)); this.getContentPane().add("North", buttonPanel); this.getContentPane().add("Center", messagesScroll); } public void actionPerformed(ActionEvent theEvent) // respond to button pushes, menu selections { String command = theEvent.getActionCommand(); try { if (command == "close") { discoveryThread.interrupt(); this.hide(); this.dispose(); } if (command == "stop discovery") { discoveryThread.interrupt(); } } catch (Exception e) { } } public void run() { try { DatagramSocket dSocket = new DatagramSocket(); dSocket.setSoTimeout(1000); //1 second int AIRPORT_PORT = 192; InetAddress broadcastAddress = InetAddress.getByName("255.255.255.255"); byte[] bytes = new byte[116]; // from sniffs bytes[0] = (byte)0x01; DatagramPacket outPacket = new DatagramPacket(bytes, bytes.length, broadcastAddress, AIRPORT_PORT); dSocket.send(outPacket); while(! discoveryThread.interrupted()) { //bytes = new byte[116]; // from sniffs DatagramPacket inPacket = new DatagramPacket(bytes, bytes.length); try { dSocket.receive(inPacket); bytes = inPacket.getData(); String sourceAddress = inPacket.getAddress().getHostAddress(); // parse info in response packet /* System.out.println("Returned Message bytes:"); for (int i = 0; i < bytes.length; ++i) System.out.print(hexByte(bytes[i]) + " "); */ AirportDiscoveryInfo theInfo = new AirportDiscoveryInfo(bytes); long upTime = Long.parseLong(theInfo.get("Base station uptime").toString()); upTime = upTime / 100; // put into seconds // change to days:hours:minutes format long days = upTime / (3600 * 24); long hours = (upTime / 3600) % 24; long minutes = (upTime / 60) % 60; long seconds = upTime % 60; String dayString = new String(); dayString += days; String hourString = new String(); hourString += hours; if (hourString.length() < 2) hourString = "0" + hourString; // make hours, minutes and seconds have 2 digits String minuteString = new String(); minuteString += minutes; if (minuteString.length() < 2) minuteString = "0" + minuteString; String secondString = new String(); secondString += seconds; if (secondString.length() < 2) secondString = "0" + secondString; String timeString = dayString + ":" + hourString + ":" + minuteString; theArea.append("Access point found:\n"); theArea.append(" Local LAN IP address: " + theInfo.get("Base station IP address").toString() + "\n"); theArea.append(" External IP address: " + sourceAddress + "\n"); theArea.append(" MAC address: " + theInfo.get("Base station Mac address").toString() + "\n"); theArea.append(" Device name: " + theInfo.get("System name").toString() + "\n"); theArea.append(" Device type: " + theInfo.get("Device identifying string").toString() + "\n"); theArea.append(" Uptime (days:hrs:mins): " + timeString + "\n"); /* // now send out some SNMP requests to retrieve additional info from // the responding station; would really like to ARP on the MAC address // in case the returned IP address is unhappy (e.g., 0.0.0.0).... try { String community = "public"; int version = 0; // SNMPv1 InetAddress hostAddress = InetAddress.getByName(theInfo.get("waIP").toString()); SNMPv1CommunicationInterface comInterface = new SNMPv1CommunicationInterface(version, hostAddress, community); String itemID = ""; SNMPVarBindList newVars = comInterface.getMIBEntry(itemID); SNMPSequence pair = (SNMPSequence)(newVars.getSNMPObjectAt(0)); SNMPObject snmpValue = pair.getSNMPObjectAt(1); theArea.append("External IP adress: " + snmpValue.toString() + "\n"); } catch(Exception e) { // do nothing; problem getting SNMP stuff... } */ theArea.append("\n"); } catch (InterruptedIOException e) { // will get here if nothing received in 1 second; used to check if interrupted // by user! } } } catch(Exception e) { theArea.append("Exception during discovery: " + e + "\n"); } theArea.append("Discovery finished.\n"); } private String hexByte(byte b) { int pos = b; if (pos < 0) pos += 256; String returnString = new String(); returnString += Integer.toHexString(pos/16); returnString += Integer.toHexString(pos%16); return returnString; } }airport2config-2.0.1/airport/AirportDiscoveryInfo.java0000644000175000017500000000731507503646703022467 0ustar julienjulien/* * AirportBaseStationConfigurator * * Copyright (C) 2000, Jonathan Sevy * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ package airport; import java.util.*; /** * Collects together information about the location of pieces of information * in the 116-byte Discovery memory block, and creates appropriate AirportInfoRecords * (with ByteBlockWindows into the underlying ByteBlock) to read and write * the information. */ public class AirportDiscoveryInfo extends Hashtable { /** * Create new */ public AirportDiscoveryInfo(byte[] baseBlock) { int baseStartIndex; int maxSize; int dataType; int encryption; byte[] bytes; String name; /** * Base station MAC address */ baseStartIndex = 0x024; maxSize = 6; bytes = new byte[maxSize]; for (int i = 0; i < maxSize; i++) bytes[i] = baseBlock[baseStartIndex + i]; encryption = AirportInfoRecord.UNENCRYPTED; dataType = AirportInfoRecord.BYTE_STRING; name = "Base station Mac address"; this.put(name, new AirportInfoRecord(name, name, dataType, encryption, maxSize, bytes)); /** * Base station IP address: byte 2*16 + 13 */ baseStartIndex = 0x02C; maxSize = 4; bytes = new byte[maxSize]; for (int i = 0; i < maxSize; i++) bytes[i] = baseBlock[baseStartIndex + i]; encryption = AirportInfoRecord.UNENCRYPTED; dataType = AirportInfoRecord.IP_ADDRESS; name = "Base station IP address"; this.put(name, new AirportInfoRecord(name, name, dataType, encryption, maxSize, bytes)); /** * Base station name: byte 3*16 + 1 */ baseStartIndex = 0x030; maxSize = 32; bytes = new byte[maxSize]; for (int i = 0; i < maxSize; i++) bytes[i] = baseBlock[baseStartIndex + i]; encryption = AirportInfoRecord.UNENCRYPTED; dataType = AirportInfoRecord.CHAR_STRING; name = "System name"; this.put(name, new AirportInfoRecord(name, name, dataType, encryption, maxSize, bytes)); /** * Base station uptime: byte 5*16 + 1 */ baseStartIndex = 0x050; maxSize = 4; bytes = new byte[maxSize]; for (int i = 0; i < maxSize; i++) bytes[i] = baseBlock[baseStartIndex + i]; encryption = AirportInfoRecord.UNENCRYPTED; dataType = AirportInfoRecord.UNSIGNED_INTEGER; name = "Base station uptime"; this.put(name, new AirportInfoRecord(name, name, dataType, encryption, maxSize, bytes)); /** * Device identifying string: byte 5*16 + 5 */ baseStartIndex = 0x054; maxSize = 32; bytes = new byte[maxSize]; for (int i = 0; i < maxSize; i++) bytes[i] = baseBlock[baseStartIndex + i]; encryption = AirportInfoRecord.UNENCRYPTED; dataType = AirportInfoRecord.CHAR_STRING; name = "Device identifying string"; this.put(name, new AirportInfoRecord(name, name, dataType, encryption, maxSize, bytes)); } public AirportInfoRecord get(String name) { return (AirportInfoRecord)super.get(name); } }airport2config-2.0.1/airport/AirportEthernetConfigPanel.java0000644000175000017500000001735007503646703023570 0ustar julienjulien/* * AirportBaseStationConfigurator * * Copyright (C) 2000, Jonathan Sevy * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ package airport; import java.awt.*; import java.awt.event.*; import javax.swing.*; /** * Panel maintaining configuration information for Ethernet network connection. */ public class AirportEthernetConfigPanel extends AirportInfoPanel implements ItemListener { private AirportInfoRadioButton dhcpConfigButton, manualConfigButton, pppoeButton; private AirportInfoPanel manualIPConfigPanel, ethernetButtonPanel, dhcpIPConfigPanel, dhcpClientIDPanel, pppoeClientIDPanel; private AirportInfoTextField dhcpClientIDField; private ButtonGroup dhcpManualButtonGroup; /** * Create new panel with information from supplied AirportInfo object. */ public AirportEthernetConfigPanel(AirportInfo theInfo) { /** * Base station configuration mode switch: byte 1*16 + 8, MASK 20 * 00 = manual or modem station config * 20 = DHCP station config */ dhcpConfigButton = new AirportInfoRadioButton("DHCP configuration of base station"); dhcpConfigButton.addInfoRecord(theInfo.get("waCV"), "00000300"); manualConfigButton = new AirportInfoRadioButton("Manual configuration of base station"); manualConfigButton.addInfoRecord(theInfo.get("waCV"), "00000400"); pppoeButton = new AirportInfoRadioButton("PPPoE configuration of base station"); pppoeButton.addInfoRecord(theInfo.get("waCV"), "00000900"); dhcpManualButtonGroup = new ButtonGroup(); dhcpManualButtonGroup.add(dhcpConfigButton); dhcpManualButtonGroup.add(manualConfigButton); dhcpManualButtonGroup.add(pppoeButton); manualIPConfigPanel = new AirportIPConfigPanel(theInfo); dhcpClientIDField = new AirportInfoTextField(theInfo.get("waDC"), 20); pppoeClientIDPanel = new AirportPPPoEConfigPanel(theInfo); /* Set base station IP address and router IP address: .1.3.6.1.4.1.762.2.3.1.1.5 Base station IP address: byte 6*16 + 11 Router IP address and mask: byte 7*16 + 1 Manual config: set values as specified DHCP config, modem config: set default IP address router is left as is */ // dhcp config panel just used to write default IP info into block when // dhcp config desired; panel not displayed! //String defaultIPAddress = "192.42.249.12"; //dhcpIPConfigPanel = new AirportIPConfigPanel(theInfo, defaultIPAddress, "", ""); // just use retrieved info for all fields dhcpIPConfigPanel = new AirportIPConfigPanel(theInfo, "", "", ""); setUpDisplay(); } private void setUpDisplay() { // set params for layout manager GridBagLayout theLayout = new GridBagLayout(); GridBagConstraints c = new GridBagConstraints(); c.gridwidth = 1; c.gridheight = 1; c.fill = GridBagConstraints.NONE; c.ipadx = 0; c.ipady = 0; Insets theMargin = new Insets(2,2,2,2); c.insets = theMargin; c.anchor = GridBagConstraints.CENTER; c.weightx = 0; c.weighty = 0; JLabel theLabel; dhcpClientIDPanel = new AirportInfoPanel(); dhcpClientIDPanel.setLayout(theLayout); c.gridx = 1; c.gridy = 1; c.anchor = GridBagConstraints.EAST; theLabel = new JLabel("DHCP client ID"); theLayout.setConstraints(theLabel, c); dhcpClientIDPanel.add(theLabel); c.gridx = 2; c.gridy = 1; c.anchor = GridBagConstraints.WEST; theLayout.setConstraints(dhcpClientIDField, c); dhcpClientIDPanel.add(dhcpClientIDField); ethernetButtonPanel = new AirportInfoPanel(); ethernetButtonPanel.setLayout(theLayout); c.gridx = 1; c.gridy = 1; theLayout.setConstraints(dhcpConfigButton, c); ethernetButtonPanel.add(dhcpConfigButton); c.gridx = 1; c.gridy = 2; theLayout.setConstraints(manualConfigButton, c); ethernetButtonPanel.add(manualConfigButton); c.gridx = 1; c.gridy = 3; theLayout.setConstraints(pppoeButton, c); ethernetButtonPanel.add(pppoeButton); this.setLayout(theLayout); // add components c.anchor = GridBagConstraints.CENTER; c.gridx = 1; c.gridy = 1; theLayout.setConstraints(ethernetButtonPanel, c); this.add(ethernetButtonPanel); c.gridx = 2; c.gridy = 1; theLayout.setConstraints(manualIPConfigPanel, c); this.add(manualIPConfigPanel); c.gridx = 2; c.gridy = 1; theLayout.setConstraints(dhcpClientIDPanel, c); this.add(dhcpClientIDPanel); c.gridx = 2; c.gridy = 1; theLayout.setConstraints(pppoeClientIDPanel, c); this.add(pppoeClientIDPanel); // never visible c.gridx = 2; c.gridy = 1; theLayout.setConstraints(dhcpIPConfigPanel, c); this.add(dhcpIPConfigPanel); // panel never visible; just used to set default data when selected dhcpIPConfigPanel.setVisible(false); // make manual config panel visibility and enabling dependent on button setting manualConfigButton.addItemListener(manualIPConfigPanel); manualConfigButton.addItemListener(this); manualIPConfigPanel.setEnabled(manualConfigButton.isSelected()); manualIPConfigPanel.setVisible(manualConfigButton.isSelected()); // make dhcp config panel enabling dependent on button setting (but never visible) dhcpConfigButton.addItemListener(dhcpIPConfigPanel); pppoeButton.addItemListener(dhcpIPConfigPanel); dhcpIPConfigPanel.setEnabled(dhcpConfigButton.isSelected() || pppoeButton.isSelected()); // make DHCP client ID panel visibility and enabling dependent on button setting dhcpConfigButton.addItemListener(dhcpClientIDPanel); dhcpConfigButton.addItemListener(this); dhcpClientIDPanel.setEnabled(dhcpConfigButton.isSelected()); dhcpClientIDPanel.setVisible(dhcpConfigButton.isSelected()); // make PPPoE client ID panel visibility and enabling dependent on button setting pppoeButton.addItemListener(pppoeClientIDPanel); pppoeButton.addItemListener(this); pppoeClientIDPanel.setEnabled(pppoeButton.isSelected()); pppoeClientIDPanel.setVisible(pppoeButton.isSelected()); } public void setEnabled(boolean enabled) { super.setEnabled(enabled); // create special setting status for subpanels manualIPConfigPanel.setEnabled(enabled && manualConfigButton.isSelected()); dhcpIPConfigPanel.setEnabled(enabled && (dhcpConfigButton.isSelected() || pppoeButton.isSelected())); dhcpClientIDPanel.setEnabled(enabled && dhcpConfigButton.isSelected()); pppoeClientIDPanel.setEnabled(enabled && pppoeButton.isSelected()); } /** * Used to trigger contained panels to be visible or not; panels themselves * are responsible for enabling/disabling themselves by virtue of being registered * as ItemListeners themselves. */ public void itemStateChanged(ItemEvent e) { super.itemStateChanged(e); manualIPConfigPanel.setVisible(manualConfigButton.isSelected()); dhcpClientIDPanel.setVisible(dhcpConfigButton.isSelected()); pppoeClientIDPanel.setVisible(pppoeButton.isSelected()); } }airport2config-2.0.1/airport/AirportIPConfigPanel.java0000644000175000017500000000767607503646703022334 0ustar julienjulien/* * AirportBaseStationConfigurator * * Copyright (C) 2000, Jonathan Sevy * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ package airport; import java.awt.*; import javax.swing.*; /** * Panel which maintains data relevant to base station and router IP address, and subnet mask. * Contained as subpanel within AirportNetworkPanel. */ public class AirportIPConfigPanel extends AirportInfoPanel { private AirportInfoTextField ipAddressField, subnetMaskField, routerIPAddressField; public AirportIPConfigPanel(AirportInfo theInfo) // use retrieved values as default values { ipAddressField = new AirportInfoTextField((AirportInfoRecord)theInfo.get("waIP")); subnetMaskField = new AirportInfoTextField((AirportInfoRecord)theInfo.get("waSM")); routerIPAddressField = new AirportInfoTextField((AirportInfoRecord)theInfo.get("waRA")); setUpDisplay(); } public AirportIPConfigPanel(AirportInfo theInfo, String defaultIPAddress, String defaultSubnetMask, String defaultRouterIPAddress) // use supplied default values, unless empty string supplied, whence use retrieved value { ipAddressField = new AirportInfoTextField((AirportInfoRecord)theInfo.get("waIP")); if(!defaultIPAddress.equals("")) ipAddressField.setText(defaultIPAddress); subnetMaskField = new AirportInfoTextField((AirportInfoRecord)theInfo.get("waSM")); if(!defaultSubnetMask.equals("")) subnetMaskField.setText(defaultSubnetMask); routerIPAddressField = new AirportInfoTextField((AirportInfoRecord)theInfo.get("waRA")); if(!defaultRouterIPAddress.equals("")) routerIPAddressField.setText(defaultRouterIPAddress); setUpDisplay(); } private void setUpDisplay() { // set params for layout manager GridBagLayout theLayout = new GridBagLayout(); GridBagConstraints c = new GridBagConstraints(); c.gridwidth = 1; c.gridheight = 1; c.fill = GridBagConstraints.NONE; c.ipadx = 0; c.ipady = 0; Insets theMargin = new Insets(2,2,2,2); c.insets = theMargin; c.anchor = GridBagConstraints.CENTER; c.weightx = .5; c.weighty = .5; JLabel label; this.setLayout(theLayout); // add components c.gridwidth = 1; c.anchor = GridBagConstraints.EAST; c.gridx = 1; c.gridy = 1; label = new JLabel("IP address"); theLayout.setConstraints(label, c); this.add(label); c.anchor = GridBagConstraints.WEST; c.gridx = 2; c.gridy = 1; theLayout.setConstraints(ipAddressField, c); this.add(ipAddressField); c.anchor = GridBagConstraints.EAST; c.gridx = 1; c.gridy = 2; label = new JLabel("Subnet mask"); theLayout.setConstraints(label, c); this.add(label); c.anchor = GridBagConstraints.WEST; c.gridx = 2; c.gridy = 2; theLayout.setConstraints(subnetMaskField, c); this.add(subnetMaskField); c.anchor = GridBagConstraints.EAST; c.gridx = 1; c.gridy = 3; label = new JLabel("Router address"); theLayout.setConstraints(label, c); this.add(label); c.anchor = GridBagConstraints.WEST; c.gridx = 2; c.gridy = 3; theLayout.setConstraints(routerIPAddressField, c); this.add(routerIPAddressField); } }airport2config-2.0.1/airport/AirportInfo.java0000644000175000017500000005765007745620710020604 0ustar julienjulien/* * AirportBaseStationConfigurator * * Copyright (C) 2000, Jonathan Sevy * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ package airport; import java.util.*; import java.io.*; //import AirportBaseStationConfigurator; public class AirportInfo extends Hashtable { public static final int MAX_NUM_MAC_ADDRESSES = 256; public static final int MAX_NUM_PORT_MAPS = 20; public static final int MAX_NUM_SNMP_ACCESS_ENTRIES = 5; public static final int MAX_NUM_LOGIN_CHARS = 127; public AirportInfo() { initializeHashtable(); } public AirportInfo(byte[] retrievedBytes) throws IllegalArgumentException { int count = 0; byte[] invalidBytes = {(byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xF6}; ByteArrayInputStream byteStream = new ByteArrayInputStream(retrievedBytes); initializeHashtable(); while (byteStream.available() > 0) { // read the tag byte[] tagBytes = new byte[4]; byteStream.read(tagBytes, 0, 4); String tag = new String(tagBytes); // break if tag is all zeros: end of info in array if (tag.equals("\0\0\0\0")) break; // get the corresponding element AirportInfoRecord element = this.get(tag); // increment count; used at end to determine if we got any valid info count++; // check to make sure the element's not null, in case have received // unknown tag: just ignore if null if (element != null) { //read the encryption byte[] encryptionBytes = new byte[4]; byteStream.read(encryptionBytes, 0, 4); element.encryption = getIntegerValue(encryptionBytes); //read the length byte[] lengthBytes = new byte[4]; byteStream.read(lengthBytes, 0, 4); int length = getIntegerValue(lengthBytes); //read the value byte[] valueBytes = new byte[length]; byteStream.read(valueBytes, 0, length); if (element.encryption == AirportInfoRecord.ENCRYPTED) valueBytes = AirportInfoRecord.decryptBytes(AirportInfoRecord.cipherBytes, valueBytes); // check if the value being sent is 0xFFFFFF6; this indicates // the current value is invalid - just leave as 0. Ignore for // IP addresses, though... if (!arraysEqual(valueBytes, invalidBytes) || (element.dataType == AirportInfoRecord.IP_ADDRESS)) element.value = valueBytes; //System.out.println("Tag " + tag + ": " + element.toString()); } else { // just add an entry in hashtable element = new AirportInfoRecord(); // assign the tag element.tag = tag; //read the encryption byte[] encryptionBytes = new byte[4]; byteStream.read(encryptionBytes, 0, 4); element.encryption = getIntegerValue(encryptionBytes); //read the length byte[] lengthBytes = new byte[4]; byteStream.read(lengthBytes, 0, 4); int length = getIntegerValue(lengthBytes); element.maxLength = length; //read the value byte[] valueBytes = new byte[length]; byteStream.read(valueBytes, 0, length); if (element.encryption == AirportInfoRecord.ENCRYPTED) valueBytes = AirportInfoRecord.decryptBytes(AirportInfoRecord.cipherBytes, valueBytes); // check if the value being sent is 0xFFFFFF6; this indicates // the current value is invalid - just leave as 0. Ignore for // IP addresses, though... if (!arraysEqual(valueBytes, invalidBytes) || (element.dataType == AirportInfoRecord.IP_ADDRESS)) element.value = valueBytes; else element.value = new byte[element.maxLength]; // add the element this.put(tag, element); //System.out.println("Unused tag " + tag + ": " + element.toString()); } } if (count == 0) { // no data retrieved; throw exception! throw new IllegalArgumentException("No information retrieved from base station!"); } } private void initializeHashtable() { // populate the hashtable int maxSize; int dataType; int encryption; String description; String tag; // Trap community password: omitted // Read community password: maxSize = 32; dataType = AirportInfoRecord.CHAR_STRING; encryption = AirportInfoRecord.ENCRYPTED; description = "Read community"; tag = "syPR"; this.put(tag, new AirportInfoRecord(tag, description, dataType, encryption, maxSize)); // Read/write community password: maxSize = 32; dataType = AirportInfoRecord.CHAR_STRING; encryption = AirportInfoRecord.ENCRYPTED; description = "Read/write community"; tag = "syPW"; this.put(tag, new AirportInfoRecord(tag, description, dataType, encryption, maxSize)); // Remaining community password count: omitted // Remaining community password: omitted // Configuration mode switch: // Modem config: 00 00 09 00 // Ethernet manual: 00 00 04 00 // Ethernet DHCP: 00 00 03 00 // Ethernet PPPoE: 00 00 09 00 // maxSize = 4; dataType = AirportInfoRecord.BYTE_STRING; encryption = AirportInfoRecord.UNENCRYPTED; description = "Configuration mode"; tag = "waCV"; this.put(tag, new AirportInfoRecord(tag, description, dataType, encryption, maxSize)); // Ethernet/Modem switch: // 00000004 = modem // 00000010 = Ethernet (hex) maxSize = 4; dataType = AirportInfoRecord.BYTE_STRING; encryption = AirportInfoRecord.UNENCRYPTED; description = "Ethernet/Modem switch 1"; tag = "waIn"; this.put(tag, new AirportInfoRecord(tag, description, dataType, encryption, maxSize)); // Microwave robustness flag: // 00 = off // 01 = on maxSize = 1; dataType = AirportInfoRecord.BYTE; encryption = AirportInfoRecord.UNENCRYPTED; description = "Microwave robustness flag"; tag = "raRo"; this.put(tag, new AirportInfoRecord(tag, description, dataType, encryption, maxSize)); // RTS/CTS flag: not present // Closed network flag: // 00 = open // 01 = closed maxSize = 1; dataType = AirportInfoRecord.BYTE; encryption = AirportInfoRecord.UNENCRYPTED; description = "Closed network flag"; tag = "raCl"; this.put(tag, new AirportInfoRecord(tag, description, dataType, encryption, maxSize)); // Deny unencrypted data flag: not present // Access point density, multicast rate: // // Multicast rate: 01 = 1 Mbps, 02 = 2 Mbps, 55 = 5.5 Mbps, 11 = 11 Mbps - all hex // Density: 1 = low, 2 = medium, 3 = high // // large medium small // 1 Mbps OK OK OK // 2 Mbps OK OK OK // 5.5 Mbps na OK OK // 11 Mbps na na OK maxSize = 4; dataType = AirportInfoRecord.BYTE_STRING; encryption = AirportInfoRecord.UNENCRYPTED; description = "Access point density"; tag = "raDe"; this.put(tag, new AirportInfoRecord(tag, description, dataType, encryption, maxSize)); maxSize = 4; dataType = AirportInfoRecord.BYTE_STRING; encryption = AirportInfoRecord.UNENCRYPTED; description = "Multicast rate"; tag = "raMu"; this.put(tag, new AirportInfoRecord(tag, description, dataType, encryption, maxSize)); // Select encryption key to use: not present // Wireless channel: maxSize = 4; dataType = AirportInfoRecord.UNSIGNED_INTEGER; encryption = AirportInfoRecord.UNENCRYPTED; description = "Wireless channel"; tag = "raCh"; this.put(tag, new AirportInfoRecord(tag, description, dataType, encryption, maxSize)); // Modem timeout, in seconds: maxSize = 4; dataType = AirportInfoRecord.UNSIGNED_INTEGER; encryption = AirportInfoRecord.UNENCRYPTED; description = "Modem timeout"; tag = "moID"; this.put(tag, new AirportInfoRecord(tag, description, dataType, encryption, maxSize)); // Dialing type: // 00 = tone // 01 = pulse maxSize = 1; dataType = AirportInfoRecord.BYTE; encryption = AirportInfoRecord.UNENCRYPTED; description = "Dialing type (tone or pulse)"; tag = "moPD"; this.put(tag, new AirportInfoRecord(tag, description, dataType, encryption, maxSize)); // Dialing type: // 00 = auto dial off // 01 = auto dial on maxSize = 1; dataType = AirportInfoRecord.BYTE; encryption = AirportInfoRecord.UNENCRYPTED; description = "Automatic dial"; tag = "moAD"; this.put(tag, new AirportInfoRecord(tag, description, dataType, encryption, maxSize)); // RTS Threshold: not present // max value 2347 // // Phone country code: // // US standard = 32 32 = 22 decimal // Singapore = 34 37 // Switzerland = 31 35 maxSize = 4; dataType = AirportInfoRecord.UNSIGNED_INTEGER; encryption = AirportInfoRecord.UNENCRYPTED; description = "Phone country code"; tag = "moCC"; this.put(tag, new AirportInfoRecord(tag, description, dataType, encryption, maxSize)); // Modem country code combo box index maxSize = 4; dataType = AirportInfoRecord.UNSIGNED_INTEGER; encryption = AirportInfoRecord.UNENCRYPTED; description = "Modem country code combo box index"; tag = "moCI"; this.put(tag, new AirportInfoRecord(tag, description, dataType, encryption, maxSize)); // Network name: maxSize = 32; dataType = AirportInfoRecord.CHAR_STRING; encryption = AirportInfoRecord.ENCRYPTED; description = "Network name"; tag = "raNm"; this.put(tag, new AirportInfoRecord(tag, description, dataType, encryption, maxSize)); // // Modem stuff: // maxSize = 32; dataType = AirportInfoRecord.CHAR_STRING; encryption = AirportInfoRecord.ENCRYPTED; description = "Primary phone number"; tag = "moPN"; this.put(tag, new AirportInfoRecord(tag, description, dataType, encryption, maxSize)); maxSize = 32; dataType = AirportInfoRecord.CHAR_STRING; encryption = AirportInfoRecord.ENCRYPTED; description = "Secondary phone number"; tag = "moAP"; this.put(tag, new AirportInfoRecord(tag, description, dataType, encryption, maxSize)); // // PPPoE idle timeout, in seconds: // 0 = don't disconnect // maxSize = 4; dataType = AirportInfoRecord.UNSIGNED_INTEGER; encryption = AirportInfoRecord.UNENCRYPTED; description = "PPPoE idle timeout"; tag = "peID"; this.put(tag, new AirportInfoRecord(tag, description, dataType, encryption, maxSize)); // PPPoE auto connect: // 00 = off // 01 = on maxSize = 1; dataType = AirportInfoRecord.BYTE; encryption = AirportInfoRecord.UNENCRYPTED; description = "PPPoE auto connect"; tag = "peAC"; this.put(tag, new AirportInfoRecord(tag, description, dataType, encryption, maxSize)); // PPPoE stay connected: // 00 = no // 01 = yes maxSize = 1; dataType = AirportInfoRecord.BYTE; encryption = AirportInfoRecord.UNENCRYPTED; description = "PPPoE stay connected"; tag = "peSC"; this.put(tag, new AirportInfoRecord(tag, description, dataType, encryption, maxSize)); // Encryption flag field: // 00 = no encryption // 01 = 40-bit // 02 = 128-bit maxSize = 4; dataType = AirportInfoRecord.BYTE_STRING; encryption = AirportInfoRecord.UNENCRYPTED; description = "Encryption switch"; tag = "raWM"; this.put(tag, new AirportInfoRecord(tag, description, dataType, encryption, maxSize)); // Encryption key: maxSize = 13; dataType = AirportInfoRecord.BYTE_STRING; encryption = AirportInfoRecord.ENCRYPTED; description = "Encryption key"; tag = "raWE"; this.put(tag, new AirportInfoRecord(tag, description, dataType, encryption, maxSize)); // Private LAN base station address and subnet mask: maxSize = 4; dataType = AirportInfoRecord.IP_ADDRESS; encryption = AirportInfoRecord.ENCRYPTED; description = "Private LAN base station address"; tag = "laIP"; this.put(tag, new AirportInfoRecord(tag, description, dataType, encryption, maxSize)); maxSize = 4; dataType = AirportInfoRecord.IP_ADDRESS; encryption = AirportInfoRecord.ENCRYPTED; description = "Private LAN subnet mask"; tag = "laSM"; this.put(tag, new AirportInfoRecord(tag, description, dataType, encryption, maxSize)); // syslog host facility(0 - 8): omitted // // Bridging switch: // 00 = don't bridge // 01 = bridge maxSize = 1; dataType = AirportInfoRecord.BYTE; encryption = AirportInfoRecord.UNENCRYPTED; description = "Wireless to Ethernet bridging switch"; tag = "raWB"; this.put(tag, new AirportInfoRecord(tag, description, dataType, encryption, maxSize)); // Access control switch: // 00 = no access control // 01 = access control used maxSize = 1; dataType = AirportInfoRecord.BYTE; encryption = AirportInfoRecord.UNENCRYPTED; description = "Access control switch"; tag = "acEn"; this.put(tag, new AirportInfoRecord(tag, description, dataType, encryption, maxSize)); // Access control info: maxSize = 16; dataType = AirportInfoRecord.BYTE_STRING; encryption = AirportInfoRecord.ENCRYPTED; description = "Access control info"; tag = "acTa"; this.put(tag, new AirportInfoRecord(tag, description, dataType, encryption, maxSize)); // DHCP service on wireless: // 00 = no DHCP service // 01 = DHCP on, using specified range of IP addresses maxSize = 1; dataType = AirportInfoRecord.BYTE; encryption = AirportInfoRecord.ENCRYPTED; description = "Wireless DHCP switch"; tag = "raDS"; this.put(tag, new AirportInfoRecord(tag, description, dataType, encryption, maxSize)); // DHCP service on LAN Ethernet: // 00 = no DHCP service // 01 = DHCP on maxSize = 1; dataType = AirportInfoRecord.BYTE; encryption = AirportInfoRecord.UNENCRYPTED; description = "LAN Ethernet DHCP switch"; tag = "laDS"; this.put(tag, new AirportInfoRecord(tag, description, dataType, encryption, maxSize)); // DHCP service on WAN Ethernet: // 00 = no DHCP service // 01 = DHCP on maxSize = 1; dataType = AirportInfoRecord.BYTE; encryption = AirportInfoRecord.ENCRYPTED; description = "WAN Ethernet DHCP switch"; tag = "waDS"; this.put(tag, new AirportInfoRecord(tag, description, dataType, encryption, maxSize)); // NAT switch: // 00 = NAT off // 01 = NAT on maxSize = 1; dataType = AirportInfoRecord.BYTE; encryption = AirportInfoRecord.UNENCRYPTED; description = "NAT switch"; tag = "raNA"; this.put(tag, new AirportInfoRecord(tag, description, dataType, encryption, maxSize)); // Watchdog reboot timer switch: omit // Base station IP address: 0x46A maxSize = 4; dataType = AirportInfoRecord.IP_ADDRESS; encryption = AirportInfoRecord.ENCRYPTED; description = "Base station IP address"; tag = "waIP"; this.put(tag, new AirportInfoRecord(tag, description, dataType, encryption, maxSize)); // Default TTL, for use with NAT(?): omitted // Router IP address and mask: 0x470, 0x474 maxSize = 4; dataType = AirportInfoRecord.IP_ADDRESS; encryption = AirportInfoRecord.ENCRYPTED; description = "Router IP address"; tag = "waRA"; this.put(tag, new AirportInfoRecord(tag, description, dataType, encryption, maxSize)); maxSize = 4; dataType = AirportInfoRecord.IP_ADDRESS; encryption = AirportInfoRecord.ENCRYPTED; description = "Subnet mask"; tag = "waSM"; this.put(tag, new AirportInfoRecord(tag, description, dataType, encryption, maxSize)); // 0x0478: syslog IP address // 0x047C: trap host IP address // // Names of base station, contact person maxSize = 32; dataType = AirportInfoRecord.CHAR_STRING; encryption = AirportInfoRecord.ENCRYPTED; description = "Contact person name"; tag = "syCt"; this.put(tag, new AirportInfoRecord(tag, description, dataType, encryption, maxSize)); maxSize = 32; dataType = AirportInfoRecord.CHAR_STRING; encryption = AirportInfoRecord.ENCRYPTED; description = "Base station name"; tag = "syNm"; this.put(tag, new AirportInfoRecord(tag, description, dataType, encryption, maxSize)); // Base station location: maxSize = 32; dataType = AirportInfoRecord.CHAR_STRING; encryption = AirportInfoRecord.ENCRYPTED; description = "Base station location"; tag = "syLo"; this.put(tag, new AirportInfoRecord(tag, description, dataType, encryption, maxSize)); // DHCP client ID: maxSize = 32; // guess dataType = AirportInfoRecord.CHAR_STRING; encryption = AirportInfoRecord.ENCRYPTED; description = "DHCP client ID"; tag = "waDC"; this.put(tag, new AirportInfoRecord(tag, description, dataType, encryption, maxSize)); // DHCP address range to serve: // starting address: 0xCF2 // ending address: 0xCF6 maxSize = 4; dataType = AirportInfoRecord.IP_ADDRESS; encryption = AirportInfoRecord.ENCRYPTED; description = "DHCP address range start"; tag = "dhBg"; this.put(tag, new AirportInfoRecord(tag, description, dataType, encryption, maxSize)); maxSize = 4; dataType = AirportInfoRecord.IP_ADDRESS; encryption = AirportInfoRecord.ENCRYPTED; description = "DHCP address range end"; tag = "dhEn"; this.put(tag, new AirportInfoRecord(tag, description, dataType, encryption, maxSize)); // DNS servers: maxSize = 4; dataType = AirportInfoRecord.IP_ADDRESS; encryption = AirportInfoRecord.ENCRYPTED; description = "Primary DNS server"; tag = "waD1"; this.put(tag, new AirportInfoRecord(tag, description, dataType, encryption, maxSize)); maxSize = 4; dataType = AirportInfoRecord.IP_ADDRESS; encryption = AirportInfoRecord.ENCRYPTED; description = "Secondary DNS server"; tag = "waD2"; this.put(tag, new AirportInfoRecord(tag, description, dataType, encryption, maxSize)); // DHCP lease time: // 4-byte unsigned integer giving lease time in seconds maxSize = 4; dataType = AirportInfoRecord.UNSIGNED_INTEGER; encryption = AirportInfoRecord.ENCRYPTED; description = "DHCP lease time"; tag = "dhLe"; this.put(tag, new AirportInfoRecord(tag, description, dataType, encryption, maxSize)); // Domain name (from DNS setting window): 0xD0A maxSize = 32; dataType = AirportInfoRecord.CHAR_STRING; encryption = AirportInfoRecord.ENCRYPTED; description = "Domain name"; tag = "waDN"; this.put(tag, new AirportInfoRecord(tag, description, dataType, encryption, maxSize)); // Port mapping functions: maxSize = 16; dataType = AirportInfoRecord.BYTE_STRING; encryption = AirportInfoRecord.ENCRYPTED; description = "Port mapping"; tag = "pmTa"; this.put(tag, new AirportInfoRecord(tag, description, dataType, encryption, maxSize)); // Username@domain, password maxSize = 64; // guess dataType = AirportInfoRecord.CHAR_STRING; encryption = AirportInfoRecord.ENCRYPTED; description = "Dial-up username"; tag = "moUN"; this.put(tag, new AirportInfoRecord(tag, description, dataType, encryption, maxSize)); maxSize = 64; // guess dataType = AirportInfoRecord.CHAR_STRING; encryption = AirportInfoRecord.ENCRYPTED; description = "Dial-up password"; tag = "moPW"; this.put(tag, new AirportInfoRecord(tag, description, dataType, encryption, maxSize)); maxSize = 64; // guess dataType = AirportInfoRecord.CHAR_STRING; encryption = AirportInfoRecord.ENCRYPTED; description = "PPPoE username"; tag = "peUN"; this.put(tag, new AirportInfoRecord(tag, description, dataType, encryption, maxSize)); maxSize = 64; // guess dataType = AirportInfoRecord.CHAR_STRING; encryption = AirportInfoRecord.ENCRYPTED; description = "PPPoE password"; tag = "pePW"; this.put(tag, new AirportInfoRecord(tag, description, dataType, encryption, maxSize)); // PPPoE Service Name maxSize = 64; // guess! dataType = AirportInfoRecord.CHAR_STRING; encryption = AirportInfoRecord.ENCRYPTED; description = "PPPoE service name"; tag = "peSN"; this.put(tag, new AirportInfoRecord(tag, description, dataType, encryption, maxSize)); // Reboot signal maxSize = 0; dataType = AirportInfoRecord.BYTE; encryption = AirportInfoRecord.UNENCRYPTED; description = "Reboot flag"; tag = "acRB"; this.put(tag, new AirportInfoRecord(tag, description, dataType, encryption, maxSize)); } public AirportInfoRecord get(String name) { //System.out.println("Get info record " + name); return (AirportInfoRecord)super.get(name); } public byte[] getUpdateBytes() { ByteArrayOutputStream outStream = new ByteArrayOutputStream(); Enumeration elementEnumeration = this.elements(); while (elementEnumeration.hasMoreElements()) { AirportInfoRecord nextElement = (AirportInfoRecord)elementEnumeration.nextElement(); try { outStream.write(nextElement.getUpdateBytes()); //System.out.println("Update bytes: tag " + nextElement.tag + ": " + nextElement.toString()); } catch (IOException e) { // can't happen } } return outStream.toByteArray(); } public byte[] getRequestBytes() { ByteArrayOutputStream outStream = new ByteArrayOutputStream(); Enumeration elementEnumeration = this.elements(); while (elementEnumeration.hasMoreElements()) { AirportInfoRecord nextElement = (AirportInfoRecord)elementEnumeration.nextElement(); try { outStream.write(nextElement.getRequestBytes()); } catch (IOException e) { // can't happen } } return outStream.toByteArray(); } public String toString() { String returnText = new String(); Enumeration elementEnumeration = this.elements(); while (elementEnumeration.hasMoreElements()) { AirportInfoRecord theElement = (AirportInfoRecord)elementEnumeration.nextElement(); returnText += theElement.toString(); returnText += "\n"; } return returnText; } private int getIntegerValue(byte[] valueBytes) { int value = 0; for (int i = 0; i < valueBytes.length; i++) { int absValue = valueBytes[i]; if (absValue < 0) absValue += 256; value = value*256 + absValue; } return value; } private static boolean arraysEqual(byte[] a, byte[] b) { if (a.length != b.length) { return false; } else { for (int i = 0; i < a.length; i++) { if (a[i] != b[i]) return false; } } return true; } }airport2config-2.0.1/airport/AirportInfoCheckBox.java0000644000175000017500000001135107503646703022201 0ustar julienjulien/* * AirportBaseStationConfigurator * * Copyright (C) 2000, Jonathan Sevy * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ package airport; import java.awt.*; import java.util.*; import javax.swing.*; /** * Checkbox displaying and setting specific piece of Airport info. Provides facilities * for reading from / writing to multiple AirportInfoRecords, and specifying the value(s) * for each corresponding to the selected and unselected states. */ public class AirportInfoCheckBox extends JCheckBox implements AirportInfoComponent { private Vector theRecords; private class RecordSettings { public AirportInfoRecord theRecord; public String selectedValue; public String unselectedValue; public void writeValue(boolean selected) throws ValueFormatException { if (selected) { theRecord.setBytesFromString(selectedValue); } else { theRecord.setBytesFromString(unselectedValue); } } } /** * Create new checkbox with given label and no associated AirportInfoRecords. */ public AirportInfoCheckBox(String label) { super(label); theRecords = new Vector(); //redisplay done automatically when records added } /** * Create new checkbox with given label and supplied AirportInfoRecord, with selectedValue * and unselectedValue strings stored for subsequent writing (as appropriate). State of * checkbox set according to value in underlying byte block. */ public AirportInfoCheckBox(String label, AirportInfoRecord theRecord, String selectedValue, String unselectedValue) { super(label); theRecords = new Vector(); addInfoRecord(theRecord, selectedValue, unselectedValue); //redisplay done automatically by addInfoRecord } /** * Add additional AirportInfoRecord to list of byte block fields, with selectedValue * and unselectedValue strings stored for subsequent writing (as appropriate). State of * checkbox set according to value in all underlying byte blocks - if inconsistent, * set to unselected. */ public void addInfoRecord(AirportInfoRecord theRecord, String selectedValue, String unselectedValue) { RecordSettings recordSettings = new RecordSettings(); recordSettings.theRecord = theRecord; recordSettings.selectedValue = selectedValue; recordSettings.unselectedValue = unselectedValue; theRecords.insertElementAt(recordSettings, theRecords.size()); refreshDisplay(); } public void refreshDisplay() { boolean selected = true; Enumeration elements = theRecords.elements(); while (elements.hasMoreElements()) { RecordSettings nextSettings = (RecordSettings)elements.nextElement(); String currentValue = nextSettings.theRecord.toString(); String selectedValue = nextSettings.selectedValue; // convert to integers to compare - but assume use hex for selectedValue! try { int selectedInt = Integer.parseInt(selectedValue, 16); int currentInt; if(nextSettings.theRecord.dataType == AirportInfoRecord.UNSIGNED_INTEGER) { // the toString method returns a base-10 value string currentInt = Integer.parseInt(currentValue, 10); } else { // others, either BYTE or BYTE_STRING, return a base-16 value currentInt = Integer.parseInt(currentValue, 16); } if(currentInt != selectedInt) { selected = false; } } catch (NumberFormatException e) { System.out.println("Checkbox " + this.getLabel() + ", number format exception"); selected = false; } } this.setSelected(selected); } /** * Write values to all of associated AirportInfoRecords according to selected state * of checkbox. */ public void writeValue() throws ValueFormatException { boolean selected = this.isSelected(); Enumeration elements = theRecords.elements(); while (elements.hasMoreElements()) ((RecordSettings)elements.nextElement()).writeValue(selected); } }airport2config-2.0.1/airport/AirportInfoComboBox.java0000644000175000017500000000666107503646703022233 0ustar julienjulien/* * AirportBaseStationConfigurator * * Copyright (C) 2000, Jonathan Sevy * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ package airport; import java.awt.*; import java.awt.event.*; import java.util.*; import javax.swing.*; /** * A ComboBox subclass for reading from and writing to an AirportInfoRecord. */ public class AirportInfoComboBox extends AirportInfoPanel implements AirportInfoComponent { private AirportInfoRecord theRecord; private JComboBox comboBox; /** * Associates ComboBox entry with value to be written; toString() method ensures * that itemLabel is displayed in ComboBox list */ private class Association { public Association(String itemLabel, String valueString) { this.itemLabel = itemLabel; this.valueString = valueString; } String itemLabel; String valueString; public String toString() { return itemLabel; } } /** * Creates ComboBox with given label associated with specified AirportInfoRecord. */ public AirportInfoComboBox(String label, AirportInfoRecord theRecord) { JLabel theLabel = new JLabel(label); comboBox = new JComboBox(); this.add("West", theLabel); this.add("East", comboBox); this.theRecord = theRecord; // display refreshed when items added } /** * Add item to ComboBox list, with specified item label and associated value string to * be written if item is selected. */ public void addItemAndValue(String itemLabel, String valueString) { // create an association object, and add it to the combo box Association newItem = new Association(itemLabel, valueString); comboBox.addItem(newItem); refreshDisplay(); } /** * Read current value in associated AirportInfoRecord, and set ComboBox to display * corresponding item. */ public void refreshDisplay() { // determine which label is associated with the current value, and select it String currentValue = theRecord.toString(); int i; for (i = 0; i < comboBox.getItemCount(); i++) { Association nextItem = (Association)(comboBox.getItemAt(i)); if (nextItem.valueString.equalsIgnoreCase(currentValue)) { comboBox.setSelectedIndex(i); break; } } /* if (i == comboBox.getItemCount()) { System.out.println("Didn't find combobox item: " + currentValue); } */ } /** * Write the value corresponding to the currently selected item into the associated * AirportInfoRecord. */ public void writeValue() throws ValueFormatException { Association theItem = (Association)(comboBox.getSelectedItem()); theRecord.setBytesFromString(theItem.valueString); } }airport2config-2.0.1/airport/AirportInfoComponent.java0000644000175000017500000000243707503646703022462 0ustar julienjulien/* * AirportBaseStationConfigurator * * Copyright (C) 2000, Jonathan Sevy * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ package airport; /** * Interface for all components which display and edit Airport configuration information. */ public interface AirportInfoComponent { /** * Component should re-read data from the AirportInfoRecord containing its data. */ public void refreshDisplay(); /** * Component should write data to the AirportInfoRecord containing its data. */ public void writeValue() throws ValueFormatException; }airport2config-2.0.1/airport/AirportInfoLabelledTextField.java0000644000175000017500000001007007503646703024025 0ustar julienjulien/* * AirportBaseStationConfigurator * * Copyright (C) 2000, Jonathan Sevy * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ package airport; import java.awt.*; import javax.swing.*; /** * Creates a labelled text box to display and edit the information in an AirportInfoRecord. * Size of textfield is set automatically according to datatype. */ public class AirportInfoLabelledTextField extends AirportInfoPanel { public String name; public JTextField theField; private AirportInfoRecord theRecord; /** * Creates new display for viewing and editing the information in the supplied * AirportInfoRecord. Size of textfield is supplied. */ public AirportInfoLabelledTextField(String name, AirportInfoRecord theRecord, int fieldSize) { this.name = name; this.theRecord = theRecord; JLabel l = new JLabel(name); theField = new JTextField(fieldSize); this.setLayout(new BorderLayout(5,5)); this.add("West", l); this.add("East", theField); refreshDisplay(); } /** * Creates new display for viewing and editing the information in the supplied * AirportInfoRecord. Size of textfield is set automatically according to datatype. */ public AirportInfoLabelledTextField(String name, AirportInfoRecord theRecord) { this.name = name; this.theRecord = theRecord; setUpDisplay(); refreshDisplay(); } private void setUpDisplay() { JLabel l = new JLabel(name); //determine how large the text field should be to display the value int fieldSize = theRecord.maxLength; switch (theRecord.dataType) { case AirportInfoRecord.CHAR_STRING: { // do nothing; field size OK as number of bytes break; } case AirportInfoRecord.PHONE_NUMBER: { fieldSize = 20; // should be enough for all digits and spaces break; } case AirportInfoRecord.IP_ADDRESS: { fieldSize = 15; break; } case AirportInfoRecord.UNSIGNED_INTEGER: case AirportInfoRecord.BYTE: case AirportInfoRecord.BYTE_STRING: default: { fieldSize *= 3; // to hold hex string: 2 chars per byte, plus space break; } } if (fieldSize > 40) fieldSize = 40; theField = new JTextField(fieldSize); this.setLayout(new BorderLayout(5,5)); this.add("West", l); this.add("East", theField); } /** * Read value from associated AirportInfoRecord window, and display value. */ public void refreshDisplay() { theField.setText(theRecord.toString()); } /** * Write value currently displayed into associated AirportInfoRecord window. */ public void writeValue() throws ValueFormatException { try { theRecord.setBytesFromString(theField.getText()); } catch (ValueFormatException e) { theField.selectAll(); theField.requestFocus(); throw e; } } /** * Write supplied value, rather than that currently displayed, into associated * AirportInfoRecord window. */ public void writeValue(String newValue) throws ValueFormatException { theField.setText(newValue); writeValue(); refreshDisplay(); } /** * Utility method to get text in enclosed textfield */ public String getText() { return theField.getText(); } }airport2config-2.0.1/airport/AirportInfoListDisplay.java0000644000175000017500000000753007503646703022760 0ustar julienjulien/* * AirportBaseStationConfigurator * * Copyright (C) 2000, Jonathan Sevy * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ package airport; import java.util.*; import java.net.*; import java.awt.*; import javax.swing.*; import java.awt.event.*; import java.io.*; /** * A utility class that displays all of the information in the associated AirportInfo * object. Creates an AirportInfoLabelledTextField (labelled text box) for each piece of * information, and displays these in a scrollable pane. */ public class AirportInfoListDisplay extends JPanel implements Scrollable { /** * Create the display for the information contained in airportInfo. */ public AirportInfoListDisplay(AirportInfo airportInfo) { setUpDisplay(airportInfo); } private void setUpDisplay(AirportInfo airportInfo) { // set params for layout manager GridBagLayout theLayout = new GridBagLayout(); GridBagConstraints c = new GridBagConstraints(); c.gridwidth = 1; c.gridheight = 1; c.fill = GridBagConstraints.NONE; c.ipadx = 0; c.ipady = 0; Insets theMargin = new Insets(2,2,2,2); c.insets = theMargin; c.anchor = GridBagConstraints.CENTER; c.weightx = .5; c.weighty = .5; //this.setBackground(Color.white); //this.setOpaque(true); this.setLayout(theLayout); Enumeration keys = airportInfo.keys(); int i = 1; while (keys.hasMoreElements()) { String name = (String)keys.nextElement(); //if (name.endsWith("?")) { AirportInfoRecord nextRecord = airportInfo.get(name); AirportInfoLabelledTextField theDisplay = new AirportInfoLabelledTextField(name, nextRecord); c.gridx = 1; c.gridy = i; theLayout.setConstraints(theDisplay, c); this.add(theDisplay); i++; } } } public Dimension getPreferredScrollableViewportSize() { Dimension d; //d = getPreferredSize(); d = new Dimension(600,200); //System.out.println("preferred size returned: " + d.getHeight() + ", " + d.getWidth()); return d; } public int getScrollableBlockIncrement(Rectangle visibleRect, int orientation, int direction) // Components that display logical rows or columns should compute the scroll increment that // will completely expose one block of rows or columns, depending on the value of orientation. { return 10; } public boolean getScrollableTracksViewportHeight() // Return true if a viewport should always force the height of this Scrollable to // match the height of the viewport. { return false; } public boolean getScrollableTracksViewportWidth() // Return true if a viewport should always force the width of this Scrollable to // match the width of the viewport. { return false; } public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation, int direction) // Components that display logical rows or columns should compute the scroll increment // that will completely expose one new row or column, depending on the value of orientation. { return 10; } }airport2config-2.0.1/airport/AirportInfoPanel.java0000644000175000017500000000620007503646703021547 0ustar julienjulien/* * AirportBaseStationConfigurator * * Copyright (C) 2000, Jonathan Sevy * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ package airport; import java.awt.*; import java.awt.event.*; import javax.swing.*; /** * Superclass for all panels displaying info with AirportInfoComponents. When * enabled, has all AirportInfoComponents write their values; if not enabled, * component values not written. */ public class AirportInfoPanel extends JPanel implements AirportInfoComponent, ItemListener { /** * If panel enabled, instruct all contained AirportInfoComponents to write * their values; if not enabled, no writing. */ public void writeValue() throws ValueFormatException { if (this.isEnabled()) { Component[] components = this.getComponents(); for (int i = 0; i < components.length; i++) if (components[i] instanceof AirportInfoComponent) { try { ((AirportInfoComponent)components[i]).writeValue(); } catch (ValueFormatException e) { // set focus to offending component (if it's not itself a container) if ( !(components[i] instanceof Container)) components[i].requestFocus(); throw e; // so can display this panel } } } } /** * Instruct all contained AirportInfoComponents to read their values from * their associated AirportInfoRecords, and update their displays accordingly. */ public void refreshDisplay() { Component[] components = this.getComponents(); for (int i = 0; i < components.length; i++) if (components[i] instanceof AirportInfoComponent) ((AirportInfoComponent)components[i]).refreshDisplay(); } /** * Used to trigger this panel to be enabled or disabled, by registering it * as a ChangeListener with an AbstractButton instance. When disabled, * contained components won't write their values to underlying ByteBlock. */ public void itemStateChanged(ItemEvent e) { if (e.getStateChange() == ItemEvent.SELECTED) this.setEnabled(true); else this.setEnabled(false); } /** * Enable and disable contained components. */ public void setEnabled(boolean enabled) { Component[] components = this.getComponents(); super.setEnabled(enabled); for (int i = 0; i < components.length; i++) components[i].setEnabled(enabled); } }airport2config-2.0.1/airport/AirportInfoRadioButton.java0000644000175000017500000001077407503646703022755 0ustar julienjulien/* * AirportBaseStationConfigurator * * Copyright (C) 2000, Jonathan Sevy * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ package airport; import java.awt.*; import java.util.*; import javax.swing.*; /** * Radio button displaying state of and setting value of specific piece of Airport info. * Provides facilities for reading from / writing to multiple AirportInfoRecords, and * specifying the value for each corresponding to the selected state. */ public class AirportInfoRadioButton extends JRadioButton implements AirportInfoComponent { private Vector theRecords; private class RecordSettings { public AirportInfoRecord theRecord; public String selectedValue; public void writeValue() throws ValueFormatException { theRecord.setBytesFromString(selectedValue); } } /** * Create new radio button with given label and no associated AirportInfoRecords. */ public AirportInfoRadioButton(String label) { super(label); theRecords = new Vector(); //redisplay done automatically when new record added } /** * Create new radio button with given label and supplied AirportInfoRecord, with * selectedValue string stored for subsequent writing (as appropriate). State of * radio button set according to value in underlying byte block. */ public AirportInfoRadioButton(String label, AirportInfoRecord theRecord, String selectedValue) { super(label); theRecords = new Vector(); addInfoRecord(theRecord, selectedValue); //redisplay done automatically by addInfoRecord } /** * Add additional AirportInfoRecord to list of byte block fields, with selectedValue * string stored for subsequent writing (as appropriate). State of checkbox set according * to value in all underlying byte blocks - if inconsistent, set to unselected. */ public void addInfoRecord(AirportInfoRecord theRecord, String selectedValue) { RecordSettings recordSettings = new RecordSettings(); recordSettings.theRecord = theRecord; recordSettings.selectedValue = selectedValue; theRecords.insertElementAt(recordSettings, theRecords.size()); refreshDisplay(); } public void refreshDisplay() { boolean selected = true; Enumeration elements = theRecords.elements(); while (elements.hasMoreElements()) { RecordSettings nextSettings = (RecordSettings)elements.nextElement(); String currentValue = nextSettings.theRecord.toString(); String selectedValue = nextSettings.selectedValue; // convert to integers to compare - but assume use hex for selectedValue! try { int selectedInt = Integer.parseInt(selectedValue, 16); int currentInt; if(nextSettings.theRecord.dataType == AirportInfoRecord.UNSIGNED_INTEGER) { // the toString method returns a base-10 value string currentInt = Integer.parseInt(currentValue, 10); } else { // others, either BYTE or BYTE_STRING, return a base-16 value currentInt = Integer.parseInt(currentValue, 16); } if(currentInt != selectedInt) selected = false; } catch (NumberFormatException e) { System.out.println("Radio button " + this.getLabel() + ", number format exception"); selected = false; } } this.setSelected(selected); } /** * Write values to all of associated AirportInfoRecords if checkbox selected. */ public void writeValue() throws ValueFormatException { boolean selected = this.isSelected(); if (selected) { Enumeration elements = theRecords.elements(); while (elements.hasMoreElements()) { RecordSettings nextSettings = (RecordSettings)elements.nextElement(); nextSettings.writeValue(); } } } }airport2config-2.0.1/airport/AirportInfoRecord.java0000644000175000017500000003715507503646703021743 0ustar julienjulien/* * AirportBaseStationConfigurator * * Copyright (C) 2000, Jonathan Sevy * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ package airport; import java.math.*; import java.util.*; import java.io.*; /** * This class defines a structure to hold information about the location and format (type) * of a piece of information in the Airport memory block. Location is specified by a triple: * the object identifier number (1 to 68), row in the block (0 to 15), and column (0 to 15), * where the ByteBlockWindow begins; size of the window is specified by giving the number of * rows and columns in the window; and the datatype is specified as one of the class's constants. * * The class also implements a toString() method which provides a pretty-printed representation * of the value in the window based on its datatype, and a setBytesFromString() method which * writes a value to the window given an appropriately formatted String representation. */ public class AirportInfoRecord { public static final int CHAR_STRING = 0; public static final int IP_ADDRESS = 1; public static final int BYTE_STRING = 2; public static final int PHONE_NUMBER = 3; public static final int UNSIGNED_INTEGER = 4; public static final int BYTE = 5; public static final int LITTLE_ENDIAN_UNSIGNED_INTEGER = 6; public static final int UNENCRYPTED = 0; public static final int ENCRYPTED = 2; public String tag; public String description; public int dataType; public int encryption; public int maxLength; public byte[] value; public static byte[] cipherBytes = { (byte)0x0e, (byte)0x39, (byte)0xf8, (byte)0x05, (byte)0xc4, (byte)0x01, (byte)0x55, (byte)0x4f, (byte)0x0c, (byte)0xac, (byte)0x85, (byte)0x7d, (byte)0x86, (byte)0x8a, (byte)0xb5, (byte)0x17, (byte)0x3e, (byte)0x09, (byte)0xc8, (byte)0x35, (byte)0xf4, (byte)0x31, (byte)0x65, (byte)0x7f, (byte)0x3c, (byte)0x9c, (byte)0xb5, (byte)0x6d, (byte)0x96, (byte)0x9a, (byte)0xa5, (byte)0x07, (byte)0x2e, (byte)0x19, (byte)0xd8, (byte)0x25, (byte)0xe4, (byte)0x21, (byte)0x75, (byte)0x6f, (byte)0x2c, (byte)0x8c, (byte)0xa5, (byte)0x9d, (byte)0x66, (byte)0x6a, (byte)0x55, (byte)0xf7, (byte)0xde, (byte)0xe9, (byte)0x28, (byte)0xd5, (byte)0x14, (byte)0xd1, (byte)0x85, (byte)0x9f, (byte)0xdc, (byte)0x7c, (byte)0x55, (byte)0x8d, (byte)0x76, (byte)0x7a, (byte)0x45, (byte)0xe7, (byte)0xce, (byte)0xf9, (byte)0x38, (byte)0xc5, (byte)0x04, (byte)0xc1, (byte)0x95, (byte)0x8f, (byte)0xcc, (byte)0x6c, (byte)0x45, (byte)0xbd, (byte)0x46, (byte)0x4a, (byte)0x75, (byte)0xd7, (byte)0xfe, (byte)0xc9, (byte)0x08, (byte)0xf5, (byte)0x34, (byte)0xf1, (byte)0xa5, (byte)0xbf, (byte)0xfc, (byte)0x5c, (byte)0x75, (byte)0xad, (byte)0x56, (byte)0x5a, (byte)0x65, (byte)0xc7, (byte)0xee, (byte)0xd9, (byte)0x18, (byte)0xe5, (byte)0x24, (byte)0xe1, (byte)0xb5, (byte)0xaf, (byte)0xec, (byte)0x4c, (byte)0x65, (byte)0xdd, (byte)0x26, (byte)0x2a, (byte)0x15, (byte)0xb7, (byte)0x9e, (byte)0xa9, (byte)0x68, (byte)0x95, (byte)0x54, (byte)0x91, (byte)0xc5, (byte)0xdf, (byte)0x9c, (byte)0x3c, (byte)0x15, (byte)0xcd, (byte)0x36, (byte)0x3a, (byte)0x05, (byte)0xa7, (byte)0x8e, (byte)0xb9, (byte)0x78, (byte)0x85, (byte)0x44, (byte)0x81, (byte)0xd5, (byte)0xcf, (byte)0x8c, (byte)0x2c, (byte)0x05, (byte)0xfd, (byte)0x06, (byte)0x0a, (byte)0x35, (byte)0x97, (byte)0xbe, (byte)0x89, (byte)0x48, (byte)0xb5, (byte)0x74, (byte)0xb1, (byte)0xe5, (byte)0xff, (byte)0xbc, (byte)0x1c, (byte)0x35, (byte)0xed, (byte)0x16, (byte)0x1a, (byte)0x25, (byte)0x87, (byte)0xae, (byte)0x99, (byte)0x58, (byte)0xa5, (byte)0x64, (byte)0xa1, (byte)0xf5, (byte)0xef, (byte)0xac, (byte)0x0c, (byte)0x25, (byte)0x1d, (byte)0xe6, (byte)0xea, (byte)0xd5, (byte)0x77, (byte)0x5e, (byte)0x69, (byte)0xa8, (byte)0x55, (byte)0x94, (byte)0x51, (byte)0x05, (byte)0x1f, (byte)0x5c, (byte)0xfc, (byte)0xd5, (byte)0x0d, (byte)0xf6, (byte)0xfa, (byte)0xc5, (byte)0x67, (byte)0x4e, (byte)0x79, (byte)0xb8, (byte)0x45, (byte)0x84, (byte)0x41, (byte)0x15, (byte)0x0f, (byte)0x4c, (byte)0xec, (byte)0xc5, (byte)0x3d, (byte)0xc6, (byte)0xca, (byte)0xf5, (byte)0x57, (byte)0x7e, (byte)0x49, (byte)0x88, (byte)0x75, (byte)0xb4, (byte)0x71, (byte)0x25, (byte)0x3f, (byte)0x7c, (byte)0xdc, (byte)0xf5, (byte)0x2d, (byte)0xd6, (byte)0xda, (byte)0xe5, (byte)0x47, (byte)0x6e, (byte)0x59, (byte)0x98, (byte)0x65, (byte)0xa4, (byte)0x61, (byte)0x35, (byte)0x2f, (byte)0x6c, (byte)0xcc, (byte)0xe5, (byte)0x5d, (byte)0xa6, (byte)0xaa, (byte)0x95, (byte)0x37, (byte)0x1e, (byte)0x29, (byte)0xe8, (byte)0x15, (byte)0xd4, (byte)0x11, (byte)0x45, (byte)0x5f, (byte)0x1c, (byte)0xbc, (byte)0x95, (byte)0x4d, (byte)0xb6, (byte)0xba, (byte)0x85, (byte)0x27 }; /** * Create a new record with the specified parameters */ public AirportInfoRecord(String tag, String description, int dataType, int encryption, int maxLength, byte[] value) { this.tag = tag; this.description = description; this.dataType = dataType; this.encryption = encryption; this.maxLength = maxLength; this.value = value; } public AirportInfoRecord(String tag, String description, int dataType, int encryption, int maxLength) { this.tag = tag; this.description = description; this.maxLength = maxLength; this.dataType = dataType; this.encryption = encryption; this.value = new byte[maxLength]; } public AirportInfoRecord() { this.tag = ""; this.description = ""; this.dataType = CHAR_STRING; this.encryption = UNENCRYPTED; this.maxLength = 0; this.value = new byte[0]; } /** * Clear all bytes in the underlying ByteBlockWindow. */ public void clearWindow() { this.value = new byte[0]; } /** * Method which provides a pretty-printed representation of the value bytes * based on its datatype. */ public String toString() { String returnString = new String(); byte[] bytes = value; switch (dataType) { case UNSIGNED_INTEGER: { try { returnString = convertToUnsignedInteger(bytes); } catch (NumberFormatException e) { returnString = hexBytes(bytes); } break; } case LITTLE_ENDIAN_UNSIGNED_INTEGER: { try { bytes = reverseBytes(bytes); returnString = convertToUnsignedInteger(bytes); } catch (NumberFormatException e) { returnString = hexBytes(bytes); } break; } case CHAR_STRING: case PHONE_NUMBER: { returnString = convertToCharString(bytes); break; } case IP_ADDRESS: { returnString = convertToIPAddress(bytes); break; } case BYTE: case BYTE_STRING: default: { returnString = hexBytes(bytes); break; } } return returnString; } private String convertToCharString(byte[] bytes) { String charString; if (bytes.length == 0) { charString = ""; } else { charString = new String(bytes); // trim 0's int endIndex = charString.indexOf('\0'); if (endIndex >= 0) charString = charString.substring(0, endIndex); } return charString; } private String convertToUnsignedInteger(byte[] bytes) { BigInteger bigInt = new BigInteger(1, bytes); return bigInt.toString(); } private String convertToIPAddress(byte[] bytes) { String returnString = new String(); int value; for (int i = 0; i < bytes.length - 1; i++) { value = bytes[i]; if (value < 0) value += 256; returnString += value + "."; } value = bytes[bytes.length - 1]; if (value < 0) value += 256; returnString += value; return returnString; } /** * Writes value bytes given an appropriately formatted String representation for * the value. */ public void setBytesFromString(String valueString) throws ValueFormatException { byte[] bytes; switch (dataType) { case UNSIGNED_INTEGER: { bytes = convertFromUnsignedInteger(valueString); break; } case LITTLE_ENDIAN_UNSIGNED_INTEGER: { bytes = convertFromUnsignedInteger(valueString); bytes = reverseBytes(bytes); break; } case CHAR_STRING: case PHONE_NUMBER: { if (valueString.length() > maxLength - 1) { // System.out.println("Value format exception at " + OIDNum + " " + OIDRow + " " + OIDCol); throw new ValueFormatException("Maximum " + (maxLength - 1) + " characters."); } else bytes = valueString.getBytes(); break; } case IP_ADDRESS: { bytes = convertFromIPv4Address(valueString); break; } case BYTE: case BYTE_STRING: default: { bytes = convertFromHexString(valueString); break; } } this.value = bytes; } private byte[] convertFromIPv4Address(String addressString) throws ValueFormatException { // might be partial address byte[] bytes = new byte[maxLength]; int i = 0; int value; StringTokenizer st = new StringTokenizer(addressString, "."); if (st.countTokens() != maxLength) { if (st.countTokens() == 4) throw new ValueFormatException("Bad IP address: must be of form a.b.c.d, with a,b,c and d between 0 and 255."); else throw new ValueFormatException("Bad dotted address supplied: should have " + maxLength + " components."); } while (st.hasMoreTokens()) { try { String component = st.nextToken(); value = Integer.parseInt(component); if ((value < 0) || (value > 255)) throw new ValueFormatException("Bad IP address: must be of form a.b.c.d, with a,b,c and d between 0 and 255."); else { bytes[i] = (byte)value; i++; } } catch (NumberFormatException e) { throw new ValueFormatException("Bad IP address: must be of form a.b.c.d, with a,b,c and d between 0 and 255."); } } return bytes; } private byte[] convertFromUnsignedInteger(String valueString) throws ValueFormatException { int length = maxLength; byte[] bytes = new byte[length]; try { int minValue = 0; long maxValue = 1; for (int i = 0; i < length; i++) { maxValue *= 256; } maxValue -= 1; long value = Long.parseLong(valueString); if ((value < minValue) || (value > maxValue)) throw new ValueFormatException("Value must be between " + minValue + " and " + maxValue + "."); for (int i = 0; i < length; i++) { bytes[length - i - 1] = (byte)(value%256); value = value/256; } } catch (NumberFormatException e) { throw new ValueFormatException("Bad number format."); } return bytes; } private byte[] convertFromHexString(String hexString) throws ValueFormatException { byte[] bytes = new byte[this.maxLength]; // eliminate spaces in string hexString.trim(); int index; while((index = hexString.indexOf(' ')) != -1) { hexString = hexString.substring(0,index) + hexString.substring(index+1); } // make sure have even number of hex digits if (2 * (hexString.length()/2) != hexString.length()) throw new ValueFormatException("Must have an even number of hexadecimal digits."); // make sure don't have wrong number of bytes if ((this.maxLength > 0) && (hexString.length() / 2 != maxLength)) throw new ValueFormatException("Too many hexadecimal digits (must have " + 2*maxLength + " hex digits)."); for (int i = 0; i < (hexString.length()/2); i++) { // get next pair of digits String digitString = hexString.substring(2*i,2*i+2); try { int value = Integer.parseInt(digitString, 16); bytes[i] = (byte)value; } catch (NumberFormatException e) { throw new ValueFormatException("Entries must be hexadecimal digits (0 through 9 and a through f or A through F) or spaces."); } } return bytes; } private byte[] reverseBytes(byte[] inBytes) { int length = inBytes.length; byte[] outBytes = new byte[length]; for (int i = 0; i < length; i++) { outBytes[i] = inBytes[length - i - 1]; } return outBytes; } public byte[] getValue() { return value; } public void setValue(byte[] bytes) { // just set value array value = bytes; } public byte[] getUpdateBytes() { // serialize all the fields ByteArrayOutputStream byteStream = new ByteArrayOutputStream(); DataOutputStream outStream = new DataOutputStream(byteStream); try { outStream.writeBytes(tag); outStream.writeInt(encryption); outStream.writeInt(value.length); if (value.length > 0) { // encrypt bytes if needed if (this.encryption == ENCRYPTED) { outStream.write(encryptBytes(cipherBytes, value)); } else { outStream.write(value); } } } catch(IOException e) { // IOException should never occur... } return byteStream.toByteArray(); } public byte[] getRequestBytes() { // serialize all the fields ByteArrayOutputStream byteStream = new ByteArrayOutputStream(128); DataOutputStream outStream = new DataOutputStream(byteStream); try { outStream.writeBytes(tag); outStream.writeInt(encryption); outStream.writeInt(0); } catch(IOException e) { // IOException should never occur... } return byteStream.toByteArray(); } public static byte[] decryptBytes(byte[] cipherString, byte[] encryptedString) { byte[] returnBytes = new byte[encryptedString.length]; // just xor each byte in encryptedString with cipherString int length = encryptedString.length; for (int i = 0; i < length; i++) { returnBytes[i] = (byte)(encryptedString[i] ^ cipherString[i%256]); } return returnBytes; } public static byte[] encryptBytes(byte[] cipherString, byte[] encryptedString) { return decryptBytes(cipherString, encryptedString); } private int getIntegerValue(byte[] valueBytes) { int value = 0; for (int i = 0; i < valueBytes.length; i++) { int absValue = valueBytes[i]; if (absValue < 0) absValue += 256; value = value*256 + absValue; } return value; } private String hexByte(byte b) { int pos = b; if (pos < 0) pos += 256; String returnString = new String(); returnString += Integer.toHexString(pos/16); returnString += Integer.toHexString(pos%16); return returnString; } private String hexBytes(byte[] bytes) { String returnString = new String(); for(int i = 0; i < bytes.length; i++) { returnString += hexByte(bytes[i]); } return returnString; } }airport2config-2.0.1/airport/AirportInfoRecordDisplay.java0000644000175000017500000000642607503646703023266 0ustar julienjulien/* * AirportBaseStationConfigurator * * Copyright (C) 2000, Jonathan Sevy * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ package airport; import java.awt.*; import javax.swing.*; /** * Creates a labelled text box to display and edit the information in an AirportInfoRecord. * Size of textfield is set automatically according to datatype. */ public class AirportInfoRecordDisplay extends AirportInfoPanel { public String name; public JTextField theField; private AirportInfoRecord theRecord; /** * Creates new display for viewing and editing the information in the supplied * AirportInfoRecord. Size of textfield is set automatically according to datatype. */ public AirportInfoRecordDisplay(String name, AirportInfoRecord theRecord) { this.name = name; this.theRecord = theRecord; setUpDisplay(); refreshDisplay(); } private void setUpDisplay() { JLabel l = new JLabel(name); //determine how large the text field should be to display the value int fieldSize = theRecord.maxLength; switch (theRecord.dataType) { case AirportInfoRecord.CHAR_STRING: { // do nothing; field size OK as number of bytes break; } case AirportInfoRecord.PHONE_NUMBER: { fieldSize = 20; // should be enough for all digits and spaces break; } case AirportInfoRecord.IP_ADDRESS: { fieldSize = 15; break; } case AirportInfoRecord.UNSIGNED_INTEGER: case AirportInfoRecord.BYTE: case AirportInfoRecord.BYTE_STRING: default: { fieldSize *= 3; // to hold hex string: 2 chars per byte, plus space break; } } if (fieldSize > 40) fieldSize = 40; theField = new JTextField(fieldSize); this.setLayout(new BorderLayout(5,5)); this.add("West", l); this.add("East", theField); } /** * Read value from associated AirportInfoRecord window, and display value. */ public void refreshDisplay() { theField.setText(theRecord.toString()); } /** * Write value currently displayed into associated AirportInfoRecord window. */ public void writeValue() throws ValueFormatException { theRecord.setBytesFromString(theField.getText()); } /** * Write supplied value, rather than that currently displayed, into associated * AirportInfoRecord window. */ public void writeValue(String newValue) throws ValueFormatException { theField.setText(newValue); writeValue(); refreshDisplay(); } }airport2config-2.0.1/airport/AirportInfoTabbedPane.java0000644000175000017500000000646207503646703022507 0ustar julienjulien/* * AirportBaseStationConfigurator * * Copyright (C) 2000, Jonathan Sevy * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ package airport; import java.awt.*; import java.awt.event.*; import javax.swing.*; /** * Tabbed pane holding panels which present various configuration information. */ public class AirportInfoTabbedPane extends JTabbedPane { /** * Create new tabbed pane holding panels which present various configuration information. * The supplied AirportInfo instance is passed to the contained panels. */ public AirportInfoTabbedPane(AirportInfo airportInfo) { setUpDisplay(airportInfo); } private void setUpDisplay(AirportInfo airportInfo) { AirportInfoPanel mainPanel = new AirportMainPanel(airportInfo); AirportInfoPanel wirelessPanel = new AirportWirelessPanel(airportInfo); AirportInfoPanel connectionPanel = new AirportNetworkPanel(airportInfo); AirportInfoPanel bridgingPanel = new AirportBridgingPanel(airportInfo); AirportInfoPanel dhcpPanel = new AirportDHCPPanel(airportInfo); AirportInfoPanel accessTablePanel = new AirportAccessControlTable(airportInfo); AirportInfoPanel portMapTablePanel = new AirportPortMappingPanel(airportInfo); AirportInfoPanel advancedPanel = new AirportAdvancedPanel(airportInfo); //AirportInfoPanel loginPanel = new AirportLoginInfoPanel(airportInfo); this.addTab("Main", mainPanel); this.addTab("Wireless LAN Settings", wirelessPanel); this.addTab("Network Connection", connectionPanel); this.addTab("Bridging Functions", bridgingPanel); this.addTab("DHCP Functions", dhcpPanel); this.addTab("Access Control", accessTablePanel); this.addTab("Port Mappings", portMapTablePanel); this.addTab("Advanced Settings", advancedPanel); } /** * Instruct all contained panels to write their settings to the associated AirportInfoRecords, * and update displays accordingly. (Note that only the enabled AirportInfoComponents contained * in the panels will write their values.) */ public void writeData() throws ValueFormatException { int numTabs = this.getTabCount(); for (int i = 0; i < numTabs; i++) { Component nextPanel = this.getComponentAt(i); if (nextPanel instanceof AirportInfoPanel) { try { ((AirportInfoPanel)nextPanel).writeValue(); } catch (ValueFormatException e) { // display offending panel; component will have already requested focus this.setSelectedIndex(i); throw e; // terminate operation } } } } }airport2config-2.0.1/airport/AirportInfoTextField.java0000644000175000017500000000666207503646703022414 0ustar julienjulien/* * AirportBaseStationConfigurator * * Copyright (C) 2000, Jonathan Sevy * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ package airport; import java.awt.*; import javax.swing.*; /** * Creates a text box to display and edit information in an AirportInfoRecord. * Size of textfield is set automatically according to datatype. */ public class AirportInfoTextField extends JTextField implements AirportInfoComponent { private AirportInfoRecord theRecord; /** * Creates new textfield to display and edit information in an AirportInfoRecord. * Size of textfield is set automatically according to datatype. */ public AirportInfoTextField(AirportInfoRecord theRecord) { super(); this.theRecord = theRecord; //determine how large the text field should be to display the value int fieldSize = theRecord.maxLength; switch (theRecord.dataType) { case AirportInfoRecord.CHAR_STRING: { // do nothing; field size OK as number of bytes break; } case AirportInfoRecord.PHONE_NUMBER: { fieldSize = 20; // should be enough for all digits and spaces break; } case AirportInfoRecord.IP_ADDRESS: { fieldSize = 15; break; } case AirportInfoRecord.UNSIGNED_INTEGER: case AirportInfoRecord.BYTE: case AirportInfoRecord.BYTE_STRING: default: { fieldSize *= 3; // to hold hex string: 2 chars per byte, plus space break; // or integer value } } if (fieldSize > 40) fieldSize = 40; this.setColumns(fieldSize); refreshDisplay(); } /** * Creates new textfield to display and edit information in an AirportInfoRecord. * Size of textfield is supplied as argument. */ public AirportInfoTextField(AirportInfoRecord theRecord, int fieldSize) { super(); this.theRecord = theRecord; this.setColumns(fieldSize); refreshDisplay(); } /** * Read value from associated AirportInfoRecord window, and display value. */ public void refreshDisplay() { setText(theRecord.toString()); } /** * Write value currently displayed into associated AirportInfoRecord window. */ public void writeValue() throws ValueFormatException { try { theRecord.setBytesFromString(getText()); } catch (ValueFormatException e) { this.selectAll(); this.requestFocus(); throw e; } } /** * Write supplied value, rather than that currently displayed, into associated * AirportInfoRecord window. */ public void writeValue(String newValue) throws ValueFormatException { setText(newValue); writeValue(); refreshDisplay(); } }airport2config-2.0.1/airport/AirportMainPanel.java0000644000175000017500000001000207503646703021533 0ustar julienjulien/* * AirportBaseStationConfigurator * * Copyright (C) 2000, Jonathan Sevy * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ package airport; import java.awt.*; import javax.swing.*; /** * Panel which maintains basic base station information: name, location, and contact individual. * Also provides textfield for entering new community name (base station password). */ public class AirportMainPanel extends AirportInfoPanel { private JTextField baseStationNameField, baseStationLocationField; private JTextField baseStationContactField, baseStationPasswordField; public AirportMainPanel(AirportInfo theInfo) { AirportInfoRecord nextRecord; nextRecord = theInfo.get("syNm"); baseStationNameField = new AirportInfoTextField(nextRecord); nextRecord = theInfo.get("syLo"); baseStationLocationField = new AirportInfoTextField(nextRecord); nextRecord = theInfo.get("syCt"); baseStationContactField = new AirportInfoTextField(nextRecord); nextRecord = theInfo.get("syPW"); baseStationPasswordField = new AirportInfoTextField(nextRecord); baseStationPasswordField.setText(""); setUpDisplay(); } private void setUpDisplay() { // set params for layout manager GridBagLayout theLayout = new GridBagLayout(); GridBagConstraints c = new GridBagConstraints(); c.gridwidth = 1; c.gridheight = 1; c.fill = GridBagConstraints.NONE; c.ipadx = 0; c.ipady = 0; c.insets = new Insets(2,2,2,2); c.anchor = GridBagConstraints.CENTER; c.weightx = 0; c.weighty = 0; JLabel theLabel; this.setLayout(theLayout); c.anchor = GridBagConstraints.EAST; c.gridx = 1; c.gridy = 1; theLabel = new JLabel("Base station name"); theLayout.setConstraints(theLabel, c); this.add(theLabel); c.anchor = GridBagConstraints.WEST; c.gridx = 2; c.gridy = 1; theLayout.setConstraints(baseStationNameField, c); this.add(baseStationNameField); c.anchor = GridBagConstraints.EAST; c.gridx = 1; c.gridy = 2; theLabel = new JLabel("Base station location"); theLayout.setConstraints(theLabel, c); this.add(theLabel); c.anchor = GridBagConstraints.WEST; c.gridx = 2; c.gridy = 2; theLayout.setConstraints(baseStationLocationField, c); this.add(baseStationLocationField); c.anchor = GridBagConstraints.EAST; c.gridx = 1; c.gridy = 3; theLabel = new JLabel("Contact person name"); theLayout.setConstraints(theLabel, c); this.add(theLabel); c.anchor = GridBagConstraints.WEST; c.gridx = 2; c.gridy = 3; theLayout.setConstraints(baseStationContactField, c); this.add(baseStationContactField); c.insets = new Insets(20,2,2,2); c.anchor = GridBagConstraints.EAST; c.gridx = 1; c.gridy = 4; theLabel = new JLabel("Password"); theLayout.setConstraints(theLabel, c); this.add(theLabel); c.anchor = GridBagConstraints.WEST; c.gridx = 2; c.gridy = 4; theLayout.setConstraints(baseStationPasswordField, c); this.add(baseStationPasswordField); c.insets = new Insets(2,2,2,2); c.anchor = GridBagConstraints.WEST; c.gridx = 2; c.gridy = 5; theLabel = new JLabel("(enter only if to be changed)"); theLayout.setConstraints(theLabel, c); this.add(theLabel); } }airport2config-2.0.1/airport/AirportModemConfigPanel.java0000644000175000017500000001115207503646703023045 0ustar julienjulien/* * AirportBaseStationConfigurator * * Copyright (C) 2000, Jonathan Sevy * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ package airport; import java.awt.*; import java.awt.event.*; import javax.swing.*; /** * Panel which maintains data pertaining to modem configuration. Has settings for phone number, * username and password, and the like. */ public class AirportModemConfigPanel extends AirportInfoPanel implements ActionListener { private AirportPhoneNumberPanel phoneNumberPanel; private AirportLoginInfoDialog loginDialog; private AirportInfoLabelledTextField modemTimeoutField; private AirportInfoComboBox tonePulseDialingBox; private AirportInfoCheckBox automaticDialingCheckbox; private JButton loginButton; private AirportInfo theInfo; public AirportModemConfigPanel(AirportInfo theInfo) { this.theInfo = theInfo; // panel holding phone number, modem init string info phoneNumberPanel = new AirportPhoneNumberPanel(theInfo); // Button to show login panel when pressed... loginButton = new JButton("Username/Password"); loginButton.setActionCommand("show login panel"); loginButton.addActionListener(this); modemTimeoutField = new AirportInfoLabelledTextField("Modem timeout (seconds)", theInfo.get("moID")); tonePulseDialingBox = new AirportInfoComboBox("Tone or pulse (rotary) dialing", theInfo.get("moPD")); tonePulseDialingBox.addItemAndValue("Tone", "00"); tonePulseDialingBox.addItemAndValue("Pulse", "01"); automaticDialingCheckbox = new AirportInfoCheckBox("Automatic dialing", theInfo.get("moAD"), "01", "00"); setUpDisplay(); } public void setUpDisplay() { // set params for layout manager GridBagLayout theLayout = new GridBagLayout(); GridBagConstraints c = new GridBagConstraints(); c.gridwidth = 1; c.gridheight = 1; c.fill = GridBagConstraints.NONE; c.ipadx = 0; c.ipady = 0; c.insets = new Insets(2,10,2,10); c.anchor = GridBagConstraints.CENTER; c.weightx = .5; c.weighty = .5; this.setLayout(theLayout); c.gridwidth = 2; // add components c.anchor = GridBagConstraints.CENTER; c.gridx = 1; c.gridy = 1; theLayout.setConstraints(phoneNumberPanel, c); this.add(phoneNumberPanel); c.gridwidth = 1; c.anchor = GridBagConstraints.WEST; c.gridx = 2; c.gridy = 2; theLayout.setConstraints(loginButton, c); this.add(loginButton); c.gridwidth = 1; c.gridx = 2; c.gridy = 3; theLayout.setConstraints(automaticDialingCheckbox, c); this.add(automaticDialingCheckbox); c.gridheight = 1; c.gridx = 1; c.gridy = 2; theLayout.setConstraints(modemTimeoutField, c); this.add(modemTimeoutField); c.gridx = 1; c.gridy = 3; theLayout.setConstraints(tonePulseDialingBox, c); this.add(tonePulseDialingBox); } public void actionPerformed(ActionEvent theEvent) // respond to button pushes { String command = theEvent.getActionCommand(); if (command.equals("show login panel")) { // get top-level Frame to associate modal dialog with so will be minimzed and // maximized correctly. Component owner = this; while ( !((owner == null) || (owner instanceof Frame)) ) owner = owner.getParent(); Frame owningFrame = (Frame)owner; // create and display modal dialog holding dial-up username / password and login script loginDialog = new AirportLoginInfoDialog(owningFrame, "Login Information", true, theInfo); loginDialog.pack(); // tweak app size to make it a little larger than necessary, to address the // "shrunken textfields" problem arising from the layout manager packing stuff // a little too tightly. Dimension dim = loginDialog.getSize(); dim.height += 20; dim.width += 20; loginDialog.setSize(dim); loginDialog.show(); } } }airport2config-2.0.1/airport/AirportNetworkPanel.java0000644000175000017500000001504307503646703022312 0ustar julienjulien/* * AirportBaseStationConfigurator * * Copyright (C) 2000, Jonathan Sevy * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ package airport; import java.awt.*; import java.awt.event.*; import javax.swing.*; /** * Panel which maintains data relevant to base station network connection. Has radio button selection * for modem vs Ethernet connection of base station to external network, plus DNS server fields. * Has subpanels for configuring the network connection: modem panel with settings for phone number, * username and password, and the like; Ethernet panel with choice of manual or DHCP config, plus * settings for base station IP address, router address and mask. These subpanels are enabled only * when associated connection method is selected. */ public class AirportNetworkPanel extends AirportInfoPanel implements ItemListener { private AirportInfoRadioButton modemButton, ethernetButton; private AirportInfoTextField primaryDNSField, secondaryDNSField, domainNameField; private AirportInfoPanel ethernetConfigPanel, modemConfigPanel, dnsPanel; private ButtonGroup modemEthernetButtonGroup; public AirportNetworkPanel(AirportInfo theInfo) { modemButton = new AirportInfoRadioButton("Connect to network through modem"); modemButton.addInfoRecord(theInfo.get("waIn"), "00000004"); modemButton.addInfoRecord(theInfo.get("waCV"), "00000900"); ethernetButton = new AirportInfoRadioButton("Connect to network through Ethernet port"); ethernetButton.addInfoRecord(theInfo.get("waIn"), "00000010"); // CV field set in sub-panel modemEthernetButtonGroup = new ButtonGroup(); modemEthernetButtonGroup.add(modemButton); modemEthernetButtonGroup.add(ethernetButton); primaryDNSField = new AirportInfoTextField(theInfo.get("waD1")); secondaryDNSField = new AirportInfoTextField(theInfo.get("waD2")); domainNameField = new AirportInfoTextField(theInfo.get("waDN")); ethernetConfigPanel = new AirportEthernetConfigPanel(theInfo); modemConfigPanel = new AirportModemConfigPanel(theInfo); setUpDisplay(); } public void setUpDisplay() { // set params for layout manager GridBagLayout theLayout = new GridBagLayout(); GridBagConstraints c = new GridBagConstraints(); c.gridwidth = 1; c.gridheight = 1; c.fill = GridBagConstraints.NONE; c.ipadx = 0; c.ipady = 0; Insets theMargin = new Insets(2,2,2,2); c.insets = theMargin; c.anchor = GridBagConstraints.CENTER; c.weightx = .5; c.weighty = .5; JLabel label; /* // create and lay out button panel AirportInfoPanel buttonPanel = new AirportInfoPanel(); buttonPanel.setLayout(theLayout); // add components c.anchor = GridBagConstraints.CENTER; c.gridx = 2; c.gridy = 1; theLayout.setConstraints(modemButton, c); buttonPanel.add(modemButton); c.gridx = 1; c.gridy = 1; theLayout.setConstraints(ethernetButton, c); buttonPanel.add(ethernetButton); */ // create and lay out DNS panel dnsPanel = new AirportInfoPanel(); dnsPanel.setLayout(theLayout); // add components c.anchor = GridBagConstraints.EAST; c.gridx = 1; c.gridy = 1; label = new JLabel("Primary DNS server IP address"); theLayout.setConstraints(label, c); dnsPanel.add(label); c.anchor = GridBagConstraints.WEST; c.gridx = 2; c.gridy = 1; theLayout.setConstraints(primaryDNSField, c); dnsPanel.add(primaryDNSField); c.anchor = GridBagConstraints.EAST; c.gridx = 1; c.gridy = 2; label = new JLabel("Secondary DNS server IP address"); theLayout.setConstraints(label, c); dnsPanel.add(label); c.anchor = GridBagConstraints.WEST; c.gridx = 2; c.gridy = 2; theLayout.setConstraints(secondaryDNSField, c); dnsPanel.add(secondaryDNSField); c.anchor = GridBagConstraints.EAST; c.gridx = 1; c.gridy = 3; label = new JLabel("Domain name"); theLayout.setConstraints(label, c); dnsPanel.add(label); c.anchor = GridBagConstraints.WEST; c.gridx = 2; c.gridy = 3; theLayout.setConstraints(domainNameField, c); dnsPanel.add(domainNameField); // now add panels to this this.setLayout(theLayout); c.anchor = GridBagConstraints.CENTER; c.gridx = 1; c.gridy = 1; theLayout.setConstraints(ethernetButton, c); this.add(ethernetButton); c.gridx = 2; c.gridy = 1; theLayout.setConstraints(modemButton, c); this.add(modemButton); c.gridwidth = 2; c.gridx = 1; c.gridy = 2; theLayout.setConstraints(ethernetConfigPanel, c); this.add(ethernetConfigPanel); c.gridx = 1; c.gridy = 2; theLayout.setConstraints(modemConfigPanel, c); this.add(modemConfigPanel); c.gridwidth = 2; c.gridx = 1; c.gridy = 3; theLayout.setConstraints(dnsPanel, c); this.add(dnsPanel); // make modem and ethernet config panel enablings dependent on button settings modemButton.addItemListener(modemConfigPanel); modemButton.addItemListener(this); modemConfigPanel.setEnabled(modemButton.isSelected()); modemConfigPanel.setVisible(modemButton.isSelected()); ethernetButton.addItemListener(ethernetConfigPanel); ethernetButton.addItemListener(this); ethernetConfigPanel.setEnabled(ethernetButton.isSelected()); ethernetConfigPanel.setVisible(ethernetButton.isSelected()); } /** * Used to trigger contained panels to be visible or not; panels themselves * are responsible for enabling/disabling themselves by virtue of being registered * as ItemListeners themselves. */ public void itemStateChanged(ItemEvent e) { modemConfigPanel.setVisible(modemButton.isSelected()); ethernetConfigPanel.setVisible(ethernetButton.isSelected()); } }airport2config-2.0.1/airport/AirportPhoneNumberPanel.java0000644000175000017500000001557107503646703023111 0ustar julienjulien/* * AirportBaseStationConfigurator * * Copyright (C) 2000, Jonathan Sevy * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ package airport; import java.awt.*; import javax.swing.*; /** * Utility subpanel which maintains dial-up phone number info. Could be easily extended to also permit * secondary phone number and modem initialization string editting. */ public class AirportPhoneNumberPanel extends AirportInfoPanel { private AirportInfo airportInfo; private AirportInfoTextField modemInitField, primaryPhoneField, secondaryPhoneField; private AirportInfoComboBox countryCodeBox; public AirportPhoneNumberPanel(AirportInfo airportInfo) { super(); this.airportInfo = airportInfo; primaryPhoneField = new AirportInfoTextField(airportInfo.get("moPN"), 10); secondaryPhoneField = new AirportInfoTextField(airportInfo.get("moAP"), 10); // holds configuration info for telephone system countryCodeBox = new AirportInfoComboBox("Country", airportInfo.get("moCC")); // add settings for each different country system; each group is same! countryCodeBox.addItemAndValue("North America", "22"); countryCodeBox.addItemAndValue("Guam (same as North America)", "22"); countryCodeBox.addItemAndValue("Hong Kong (same as North America)", "22"); countryCodeBox.addItemAndValue("India (same as North America)", "22"); countryCodeBox.addItemAndValue("Latin America (same as North America)", "22"); countryCodeBox.addItemAndValue("Phillipines (same as North America)", "22"); countryCodeBox.addItemAndValue("Thailand (same as North America)", "22"); countryCodeBox.addItemAndValue("Singapore", "47"); countryCodeBox.addItemAndValue("China (same as Singapore)", "47"); countryCodeBox.addItemAndValue("Czech Republic (same as Singapore)", "47"); countryCodeBox.addItemAndValue("Slovak Republic (same as Singapore)", "47"); countryCodeBox.addItemAndValue("Korea (same as Singapore)", "47"); countryCodeBox.addItemAndValue("Malaysia (same as Singapore)", "47"); countryCodeBox.addItemAndValue("Poland (same as Singapore)", "47"); countryCodeBox.addItemAndValue("Taiwan (same as Singapore)", "47"); countryCodeBox.addItemAndValue("Switzerland", "15"); countryCodeBox.addItemAndValue("Portugal (same as Switzerland)", "15"); countryCodeBox.addItemAndValue("Spain (same as Switzerland)", "15"); countryCodeBox.addItemAndValue("Finland", "4"); countryCodeBox.addItemAndValue("Germany (same as Finland)", "4"); countryCodeBox.addItemAndValue("Iceland (same as Finland)", "4"); countryCodeBox.addItemAndValue("Netherlands (same as Finland)", "4"); countryCodeBox.addItemAndValue("Australia", "40"); countryCodeBox.addItemAndValue("South Africa (same as Australia)", "40"); countryCodeBox.addItemAndValue("United Kingdom", "16"); countryCodeBox.addItemAndValue("Belgium (same as United Kingdom)", "16"); countryCodeBox.addItemAndValue("Denmark (same as United Kingdom)", "16"); countryCodeBox.addItemAndValue("Greece (same as United Kingdom)", "16"); countryCodeBox.addItemAndValue("Ireland (same as United Kingdom)", "16"); countryCodeBox.addItemAndValue("Norway (same as United Kingdom)", "16"); countryCodeBox.addItemAndValue("New Zealand", "48"); countryCodeBox.addItemAndValue("France", "5"); countryCodeBox.addItemAndValue("Japan", "43"); countryCodeBox.addItemAndValue("Austria", "1"); countryCodeBox.addItemAndValue("Italy", "8"); countryCodeBox.addItemAndValue("Sweden", "14"); //System.out.println("moCI: " + airportInfo.get("moCI").toString()); setUpDisplay(); } private void setUpDisplay() { JLabel modemInitLabel = new JLabel("Modem init string"); JLabel primaryPhoneLabel = new JLabel("Phone number"); JLabel secondaryPhoneLabel = new JLabel("Secondary phone number"); // set params for layout manager GridBagLayout theLayout = new GridBagLayout(); GridBagConstraints c = new GridBagConstraints(); c.gridwidth = 1; c.gridheight = 1; c.fill = GridBagConstraints.NONE; c.ipadx = 0; c.ipady = 0; Insets theMargin = new Insets(2,2,2,2); c.insets = theMargin; c.anchor = GridBagConstraints.CENTER; c.weightx = .5; c.weighty = .5; this.setLayout(theLayout); // add stuff: just single phone number for now! c.anchor = GridBagConstraints.EAST; c.gridx = 1; c.gridy = 1; theLayout.setConstraints(primaryPhoneLabel, c); this.add(primaryPhoneLabel); c.anchor = GridBagConstraints.WEST; c.gridx = 2; c.gridy = 1; theLayout.setConstraints(primaryPhoneField, c); this.add(primaryPhoneField); // also modem init string, for Steve Palm /* c.anchor = GridBagConstraints.EAST; c.gridx = 1; c.gridy = 2; theLayout.setConstraints(modemInitLabel, c); this.add(modemInitLabel); c.anchor = GridBagConstraints.WEST; c.gridx = 2; c.gridy = 2; theLayout.setConstraints(modemInitField, c); this.add(modemInitField); */ // and modem country code box c.gridwidth = 2; c.gridx = 1; c.gridy = 3; theLayout.setConstraints(countryCodeBox, c); this.add(countryCodeBox); refreshDisplay(); } public void writeValue() throws ValueFormatException { super.writeValue(); // The following doesn't really need to be done; it just sets the // combobox index, so the exact correct entry will be displayed (e.g., // even though UK and Greece use the same country code, make sure // Greece is displayed when the configuration is retrieved if that is // what was selected when the base station was updated. // The index values just correspond to the index in the combo box // in Apple's software; thus the wrong stuff will be displayed only // if Apple's tool is used... /* AirportInfoRecord modemCountryFlagRecord = airportInfo.get("moCI"); AirportInfoRecord modemCountryCodeRecord = airportInfo.get("moCC"); if (modemCountryCodeRecord.toString().equals("22")) { modemCountryFlagRecord.setBytesFromString("00000000"); } else { modemCountryFlagRecord.setBytesFromString("00000001"); } */ } }airport2config-2.0.1/airport/AirportPortMappingTable.java0000644000175000017500000002141107503646703023105 0ustar julienjulien/* * AirportBaseStationConfigurator * * Copyright (C) 2000, Jonathan Sevy * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ package airport; import java.awt.*; import java.awt.event.*; import java.util.*; import java.io.*; import javax.swing.*; import javax.swing.event.*; import javax.swing.table.*; /** * Handles display and updating of port mapping information. */ public class AirportPortMappingTable extends AirportInfoPanel { private AirportInfo airportInfo; private Vector addressVector; private JTable table; private AbstractTableModel tableModel; /** * Table model which maintains list of port mappings. */ private class PortMappingTableModel extends AbstractTableModel { public int getColumnCount() { return 3; } public int getRowCount() { return AirportInfo.MAX_NUM_PORT_MAPS; } public boolean isCellEditable(int row, int col) { if (row <= addressVector.size()) return true; else return false; } public String getColumnName(int col) { switch (col) { case 0: return "Public port number"; case 1: return "Private IP address"; case 2: return "Private port number"; default: return ""; } } public Object getValueAt(int row, int col) { if (row < addressVector.size()) return ((String[])addressVector.elementAt(row))[col]; else return ""; } public void setValueAt(Object newValue, int row, int col) { if (newValue instanceof String) { if (row < addressVector.size()) { String[] addressEntry = (String[])addressVector.elementAt(row); addressEntry[col] = (String)newValue; } else { String[] addressEntry = {"","",""}; addressEntry[col] = (String)newValue; addressVector.insertElementAt(addressEntry, addressVector.size()); } } } } /** * Create new table based on data in airportInfo. */ public AirportPortMappingTable(AirportInfo airportInfo) { this.airportInfo = airportInfo; setUpDisplay(); } private void setUpDisplay() { refreshDisplay(); } /** * Write the MAC addresses and hostnames in the list into the appropriate locations * in the byte block referenced by the AirportInfo object supplied in the constructor. * @throws ValueFormatException Thrown if either an IP address is malformed, or ports * are incorrect. Also sets editting focus to the offending cell. */ public void writeValue() throws ValueFormatException { // first, record changes if cell currently being edited TableCellEditor editor = table.getCellEditor(); if(editor != null) editor.stopCellEditing(); int numMacAddresses = 0; Vector publicPortVector = new Vector(); Vector privateIPVector = new Vector(); Vector privatePortVector = new Vector(); for (int i = 0; i < addressVector.size(); i++) { try { // these only get augmented if address is OK (and non-null) if (! ((String[])this.addressVector.elementAt(i))[0].equals("")) { // create a new info record to qualify the address and convert to bytes AirportInfoRecord publicPortRecord = new AirportInfoRecord("temp", "temp", AirportInfoRecord.UNSIGNED_INTEGER, AirportInfoRecord.UNENCRYPTED, 2); publicPortRecord.setBytesFromString(((String[])this.addressVector.elementAt(i))[0]); publicPortVector.add(publicPortRecord); numMacAddresses++; } else { // skip this record continue; } } catch (ValueFormatException e) { table.editCellAt(i,0); throw e; } try { // create a new info record to qualify the address and convert to bytes AirportInfoRecord privateIPRecord = new AirportInfoRecord("temp", "temp", AirportInfoRecord.IP_ADDRESS, AirportInfoRecord.UNENCRYPTED, 4); privateIPRecord.setBytesFromString(((String[])this.addressVector.elementAt(i))[1]); privateIPVector.add(privateIPRecord); } catch (ValueFormatException e) { table.editCellAt(i,1); throw e; } try { // create a new info record to qualify the address and convert to bytes AirportInfoRecord privatePortRecord = new AirportInfoRecord("temp", "temp", AirportInfoRecord.UNSIGNED_INTEGER, AirportInfoRecord.UNENCRYPTED, 2); privatePortRecord.setBytesFromString(((String[])this.addressVector.elementAt(i))[2]); privatePortVector.add(privatePortRecord); } catch (ValueFormatException e) { table.editCellAt(i,2); throw e; } } // now create concatenation try { ByteArrayOutputStream outStream = new ByteArrayOutputStream(); byte[] zeroBytes = new byte[4]; outStream.write(zeroBytes); // do length; use info record to create 8-byte value AirportInfoRecord sizeRecord = new AirportInfoRecord("temp", "temp", AirportInfoRecord.UNSIGNED_INTEGER, AirportInfoRecord.UNENCRYPTED, 4); sizeRecord.setBytesFromString(Integer.toString(numMacAddresses)); outStream.write(sizeRecord.value); // write 8-byte padding of 0's zeroBytes = new byte[8]; outStream.write(zeroBytes); // now write addresses and hostnames for (int i = 0; i < numMacAddresses; i++) { outStream.write(((AirportInfoRecord)privateIPVector.elementAt(i)).value); outStream.write(((AirportInfoRecord)privatePortVector.elementAt(i)).value); outStream.write(((AirportInfoRecord)publicPortVector.elementAt(i)).value); } // now use this to set the value of the associated info record AirportInfoRecord accessControlRecord = airportInfo.get("pmTa"); accessControlRecord.setValue(outStream.toByteArray()); } catch (IOException e) { // shouldn't ever happen... } } /** * Refresh the display based on the current data in the underlying byte block. */ public void refreshDisplay() { AirportInfoRecord portMapRecord = airportInfo.get("pmTa"); byte[] portMapBytes = portMapRecord.getValue(); DataInputStream inStream = new DataInputStream(new ByteArrayInputStream(portMapBytes)); try { // Read first 4 bytes of 0 padding inStream.skip(4); // Read in number of Mac addresses (next 4 bytes) int numPortMaps = inStream.readInt(); // Read next 8 bytes of 0 padding inStream.skip(8); // create new addressVector, with appropriate size addressVector = new Vector(); for (int i = 0; i < numPortMaps; i++) { byte[] addressBytes = new byte[4]; inStream.read(addressBytes); AirportInfoRecord privateIPRecord = new AirportInfoRecord("temp", "temp", AirportInfoRecord.IP_ADDRESS, AirportInfoRecord.UNENCRYPTED, 4, addressBytes); byte[] privatePortBytes = new byte[2]; inStream.read(privatePortBytes); AirportInfoRecord privatePortRecord = new AirportInfoRecord("temp", "temp", AirportInfoRecord.UNSIGNED_INTEGER, AirportInfoRecord.UNENCRYPTED, 2, privatePortBytes); byte[] publicPortBytes = new byte[2]; inStream.read(publicPortBytes); AirportInfoRecord publicPortRecord = new AirportInfoRecord("temp", "temp", AirportInfoRecord.UNSIGNED_INTEGER, AirportInfoRecord.UNENCRYPTED, 2, publicPortBytes); String[] addressEntry = new String[3]; addressEntry[0] = publicPortRecord.toString(); addressEntry[1] = privateIPRecord.toString(); addressEntry[2] = privatePortRecord.toString(); addressVector.insertElementAt(addressEntry, addressVector.size()); } this.removeAll(); tableModel = new PortMappingTableModel(); table = new JTable(tableModel); table.setCellSelectionEnabled(true); table.setPreferredScrollableViewportSize(new Dimension(350,200)); JScrollPane scrollPane = new JScrollPane(table); this.add(scrollPane); } catch (IOException e) { // shouldn't ever happen... } } }airport2config-2.0.1/airport/AirportUsernamePanel.java0000644000175000017500000000520307503646703022435 0ustar julienjulien/* * AirportBaseStationConfigurator * * Copyright (C) 2000, Jonathan Sevy * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ package airport; import java.awt.*; import javax.swing.*; /** * Utility subpanel which maintains dial-up username and password. */ public class AirportUsernamePanel extends AirportInfoPanel { private AirportInfoTextField modemUsernameField, modemPasswordField; public AirportUsernamePanel(AirportInfo airportInfo) { super(); modemUsernameField = new AirportInfoTextField(airportInfo.get("moUN"), 24); modemPasswordField = new AirportInfoTextField(airportInfo.get("moPW"), 24); setUpDisplay(); } private void setUpDisplay() { JLabel usernameLabel = new JLabel("User name"); JLabel passwordLabel = new JLabel("Password"); // set params for layout manager GridBagLayout theLayout = new GridBagLayout(); GridBagConstraints c = new GridBagConstraints(); c.gridwidth = 1; c.gridheight = 1; c.fill = GridBagConstraints.NONE; c.ipadx = 0; c.ipady = 0; Insets theMargin = new Insets(2,2,2,2); c.insets = theMargin; c.anchor = GridBagConstraints.CENTER; c.weightx = .5; c.weighty = .5; this.setLayout(theLayout); // add stuff c.anchor = GridBagConstraints.EAST; c.gridx = 1; c.gridy = 1; theLayout.setConstraints(usernameLabel, c); this.add(usernameLabel); c.anchor = GridBagConstraints.WEST; c.gridx = 2; c.gridy = 1; theLayout.setConstraints(modemUsernameField, c); this.add(modemUsernameField); c.anchor = GridBagConstraints.EAST; c.gridx = 1; c.gridy = 2; theLayout.setConstraints(passwordLabel, c); this.add(passwordLabel); c.anchor = GridBagConstraints.WEST; c.gridx = 2; c.gridy = 2; theLayout.setConstraints(modemPasswordField, c); this.add(modemPasswordField); refreshDisplay(); } }airport2config-2.0.1/airport/AirportWirelessPanel.java0000644000175000017500000000670707503646703022465 0ustar julienjulien/* * AirportBaseStationConfigurator * * Copyright (C) 2000, Jonathan Sevy * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ package airport; import java.awt.*; import javax.swing.*; /** * Panel which maintains wireless LAN information: network name, channel, and encryption switch and key. * Note that encryption key is supplied as 10-digit hex string (with no "0x" prefix). */ public class AirportWirelessPanel extends AirportInfoPanel { private AirportInfoLabelledTextField networkNameField; private AirportInfoCheckBox closedNetworkBox, microwaveRobustnessBox; private AirportInfoComboBox channelBox; private AirportEncryptionPanel encryptionPanel; public AirportWirelessPanel(AirportInfo theInfo) { networkNameField = new AirportInfoLabelledTextField("Network name", theInfo.get("raNm")); closedNetworkBox = new AirportInfoCheckBox("Closed network"); closedNetworkBox.addInfoRecord(theInfo.get("raCl"), "01", "00"); microwaveRobustnessBox = new AirportInfoCheckBox("Microwave robustness"); microwaveRobustnessBox.addInfoRecord(theInfo.get("raRo"), "01", "00"); channelBox = new AirportInfoComboBox("Channel", theInfo.get("raCh")); for (int i = 1; i < 12; i++) channelBox.addItemAndValue(Integer.toString(i), Integer.toString(i)); encryptionPanel = new AirportEncryptionPanel(theInfo); setUpDisplay(); } public void setUpDisplay() { // set params for layout manager GridBagLayout theLayout = new GridBagLayout(); GridBagConstraints c = new GridBagConstraints(); c.gridwidth = 1; c.gridheight = 1; c.fill = GridBagConstraints.NONE; c.ipadx = 0; c.ipady = 0; c.insets = new Insets(2,2,2,2); c.anchor = GridBagConstraints.CENTER; c.weightx = 0; c.weighty = 0; this.setLayout(theLayout); JLabel theLabel; c.insets = new Insets(2,2,2,2); c.anchor = GridBagConstraints.CENTER; c.gridwidth = 2; c.gridx = 1; c.gridy = 1; theLayout.setConstraints(networkNameField, c); this.add(networkNameField); c.anchor = GridBagConstraints.WEST; c.gridwidth = 1; c.gridx = 1; c.gridy = 2; theLayout.setConstraints(channelBox, c); this.add(channelBox); c.anchor = GridBagConstraints.CENTER; c.gridx = 2; c.gridy = 2; theLayout.setConstraints(closedNetworkBox, c); this.add(closedNetworkBox); c.anchor = GridBagConstraints.WEST; c.gridwidth = 2; c.gridx = 1; c.gridy = 3; theLayout.setConstraints(microwaveRobustnessBox, c); this.add(microwaveRobustnessBox); c.anchor = GridBagConstraints.CENTER; c.gridx = 1; c.gridy = 4; theLayout.setConstraints(encryptionPanel, c); this.add(encryptionPanel); } }airport2config-2.0.1/airport/ValueFormatException.java0000644000175000017500000000227707503646703022451 0ustar julienjulien/* * AirportBaseStationConfigurator * * Copyright (C) 2000, Jonathan Sevy * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ package airport; /** * Used to report incorrect value format messages, when inappropriate string has been supplied * in a textfield. */ public class ValueFormatException extends Exception { /** * Construct new exception with specified error message. */ public ValueFormatException(String specifics) { super(specifics); } }airport2config-2.0.1/airport/package.html0000644000175000017500000000475607503646703017767 0ustar julienjulien Airport package The airport package provides many classes useful for reading and writing configuration information from and to an Apple AirPort Base Station.

The configuration information is contained in a 17 k byte memory block that's conveniently viewed as a block with 1088 rows and 16 columns. In fact, the information is exchanged as 68 265-byte SNMPOctetStrings; information is retrieved by sending SNMP Get Requests for OID's 1.3.6.1.4.1.762.2.2.1.1.1 through 1.3.6.1.4.1.762.2.2.1.1.68, and is updated by sending SNMP Set Requests to OID's 1.3.6.1.4.1.762.2.3.1.1.1 through
1.3.6.1.4.1.762.2.3.1.1.68. Due to the necessity of the base station's "burning" received values into its EPROM (so they're maintained even if the unit is powered down), the above 68 Set Requests are followed by two additional Sets, to OID's 1.3.6.1.4.1.762.2.1.2.0 and 1.3.6.1.4.1.762.2.1.3.0, each sending an SNMPInteger with the number of bytes to be "burned in" to the EPROM (only 17336 bytes - not quite all of the 17 k-bytes sent, interestingly.)

When the 17 kB block has been retrieved from a base station, it is used to define a 1088 by 16 byte ByteBlock, which then has a number of windows defined into it enclosing various pieces of information. The ByteBlockWindows are actually defined from within AirportInfoRecord objects, which create the window and also associate a data type with the field. The datatype determines how information is translated between the byte representation and an editable String representation.

A number of user interface components are defined as AirportInfoComponent subclasses, which display and update the information contained in some region of the ByteBlock specified by an AirportInfoRecord. At the top level are AirportInfoPanels, which contain AirportInfoComponents and instruct these to write their values to the underlying windows in the byte block. Other subclasses provide buttons, checkboxes, and editable text fields; some of these may provide facilites for being associated with multiple AirportInfoRecords, for simultaneously writing into multiple fields. See the individual class documents for details. airport2config-2.0.1/airport/AirportDHCPPanel.java0000644000175000017500000001002407535016763021373 0ustar julienjulien/* * AirportBaseStationConfigurator * * Copyright (C) 2000, Jonathan Sevy * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ package airport; import java.awt.*; import javax.swing.*; /** * Panel which maintains data relevant to bridging (plus address allocation via DHCP and NAT). */ public class AirportDHCPPanel extends AirportInfoPanel { private AirportInfoCheckBox dhcpCheckbox; private AirportDHCPRangePanel dhcpRangePanel; private AirportInfoPanel dhcpInfoPanel; private AirportInfoLabelledScaledValueField dhcpLeaseTime; private AirportInfo theInfo; /** * Create new panel based on data referenced through the supplied AirportInfo object. */ public AirportDHCPPanel(AirportInfo theInfo) { /** * DHCP switch: * 00 = no DHCP service provided * 80 = DHCP on, using specified range of IP addresses */ this.theInfo = theInfo; dhcpRangePanel = new AirportDHCPRangePanel(theInfo); // create textfield for DHCP lease time dhcpLeaseTime = new AirportInfoLabelledScaledValueField("DHCP lease time (minutes)", theInfo.get("dhLe"), 60); //dhcpLeaseTime = new AirportInfoLabelledScaledValueField("DHCP lease time (seconds)", theInfo.get("dhLe"), 1); dhcpCheckbox = new AirportInfoCheckBox("Distribute addresses to wireless and wired hosts using DHCP",theInfo.get("raDS"), "01", "00"); // create panel to hold info to be disabled when no DHCP service provided dhcpInfoPanel = new AirportInfoPanel(); setUpDisplay(); } private void setUpDisplay() { // set params for layout manager GridBagLayout theLayout = new GridBagLayout(); GridBagConstraints c = new GridBagConstraints(); c.gridwidth = 1; c.gridheight = 1; c.fill = GridBagConstraints.NONE; c.ipadx = 0; c.ipady = 0; Insets theMargin = new Insets(2,2,2,2); c.insets = theMargin; c.anchor = GridBagConstraints.CENTER; c.weightx = 0; c.weighty = 0; JLabel theLabel; // add stuff to panel dhcpInfoPanel.setLayout(theLayout); c.anchor = GridBagConstraints.WEST; c.gridx = 1; c.gridy = 1; theLayout.setConstraints(dhcpRangePanel, c); dhcpInfoPanel.add(dhcpRangePanel); c.gridx = 1; c.gridy = 2; theLayout.setConstraints(dhcpLeaseTime, c); dhcpInfoPanel.add(dhcpLeaseTime); // add stuff to this this.setLayout(theLayout); c.anchor = GridBagConstraints.WEST; c.gridx = 1; c.gridy = 1; theLayout.setConstraints(dhcpCheckbox, c); this.add(dhcpCheckbox); c.gridx = 1; c.gridy = 2; theLayout.setConstraints(dhcpInfoPanel, c); this.add(dhcpInfoPanel); // make dhcpInfoPanel highlighting dependent on button setting dhcpCheckbox.addItemListener(dhcpInfoPanel); dhcpInfoPanel.setEnabled(dhcpCheckbox.isSelected()); } public void writeValue() throws ValueFormatException { super.writeValue(); // turn off DHCP service on LAN if not selected for wireless hosts // only turned on for WAN if connecting by modem - WAN setting done // in setDependentData() funtion AirportInfoRecord dhcpLANRecord = theInfo.get("laDS"); if (dhcpCheckbox.isSelected()) { dhcpLANRecord.setBytesFromString("01"); } else { dhcpLANRecord.setBytesFromString("00"); } } }airport2config-2.0.1/airport/AirportUsernamePPPoEClientIDPanel.java0000644000175000017500000000615307503646703024662 0ustar julienjulien/* * AirportBaseStationConfigurator * * Copyright (C) 2000, Jonathan Sevy * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ package airport; import java.awt.*; import javax.swing.*; /** * Utility subpanel which maintains dial-up username and password. */ public class AirportUsernamePPPoEClientIDPanel extends AirportInfoPanel { private JTextField pppoeUsernameField, pppoePasswordField, pppoeClientIDField; public AirportUsernamePPPoEClientIDPanel(AirportInfo airportInfo) { super(); pppoeUsernameField = new AirportInfoTextField(airportInfo.get("peUN"), 24); pppoePasswordField = new AirportInfoTextField(airportInfo.get("pePW"), 24); pppoeClientIDField = new AirportInfoTextField(airportInfo.get("peSN"), 24); setUpDisplay(); } private void setUpDisplay() { JLabel usernameLabel = new JLabel("User name"); JLabel passwordLabel = new JLabel("Password"); JLabel pppoeClientIDLabel = new JLabel("Service name"); // set params for layout manager GridBagLayout theLayout = new GridBagLayout(); GridBagConstraints c = new GridBagConstraints(); c.gridwidth = 1; c.gridheight = 1; c.fill = GridBagConstraints.NONE; c.ipadx = 0; c.ipady = 0; Insets theMargin = new Insets(2,2,2,2); c.insets = theMargin; c.anchor = GridBagConstraints.CENTER; c.weightx = .5; c.weighty = .5; this.setLayout(theLayout); // add stuff c.anchor = GridBagConstraints.EAST; c.gridx = 1; c.gridy = 1; theLayout.setConstraints(usernameLabel, c); this.add(usernameLabel); c.anchor = GridBagConstraints.WEST; c.gridx = 2; c.gridy = 1; theLayout.setConstraints(pppoeUsernameField, c); this.add(pppoeUsernameField); c.anchor = GridBagConstraints.EAST; c.gridx = 1; c.gridy = 2; theLayout.setConstraints(passwordLabel, c); this.add(passwordLabel); c.anchor = GridBagConstraints.WEST; c.gridx = 2; c.gridy = 2; theLayout.setConstraints(pppoePasswordField, c); this.add(pppoePasswordField); c.anchor = GridBagConstraints.EAST; c.gridx = 1; c.gridy = 3; theLayout.setConstraints(pppoeClientIDLabel, c); this.add(pppoeClientIDLabel); c.anchor = GridBagConstraints.WEST; c.gridx = 2; c.gridy = 3; theLayout.setConstraints(pppoeClientIDField, c); this.add(pppoeClientIDField); refreshDisplay(); } }airport2config-2.0.1/airport/AirportEncryptionPanel.java0000644000175000017500000001100310420574317022774 0ustar julienjulien/* * AirportBaseStationConfigurator * * Copyright (C) 2000, Jonathan Sevy * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ package airport; import java.awt.*; import javax.swing.*; /** * Panel which maintains wireless LAN information: network name, channel, and encryption switch and key. * Note that encryption key is supplied as 10-digit hex string (with no "0x" prefix). */ public class AirportEncryptionPanel extends AirportInfoPanel { private AirportInfoLabelledTextField encryptionKeyField; private AirportInfoRadioButton noEncryptionButton, keySize40Button, keySize128Button; private ButtonGroup buttonGroup; //private AirportInfoCheckBox allowUnencryptedDataBox; AirportInfo theInfo; public AirportEncryptionPanel(AirportInfo theInfo) { this.theInfo = theInfo; noEncryptionButton = new AirportInfoRadioButton("No encryption"); noEncryptionButton.addInfoRecord(theInfo.get("raWM"), "00000000"); keySize40Button = new AirportInfoRadioButton("Use 40-bit encryption"); keySize40Button.addInfoRecord(theInfo.get("raWM"), "00000001"); keySize128Button = new AirportInfoRadioButton("Use 128-bit encryption"); keySize128Button.addInfoRecord(theInfo.get("raWM"), "00000002"); buttonGroup = new ButtonGroup(); buttonGroup.add(noEncryptionButton); buttonGroup.add(keySize40Button); buttonGroup.add(keySize128Button); encryptionKeyField = new AirportInfoLabelledTextField("Encryption key:", theInfo.get("raWE"), 20); /** * Deny unencrypted data flag: * byte 6*16 + 9, mask 0x80 (bit 8) * 00 = allow all packets * 80 = allow only encrypted packets */ //allowUnencryptedDataBox = new AirportInfoCheckBox("Allow unencrypted data"); //allowUnencryptedDataBox.addInfoRecord(theInfo.get("Deny unencrypted data flag"), "00", "80"); setUpDisplay(); } public void setUpDisplay() { // set params for layout manager GridBagLayout theLayout = new GridBagLayout(); GridBagConstraints c = new GridBagConstraints(); c.gridwidth = 1; c.gridheight = 1; c.fill = GridBagConstraints.NONE; c.ipadx = 0; c.ipady = 0; c.insets = new Insets(2,2,2,2); c.anchor = GridBagConstraints.CENTER; c.weightx = .5; c.weighty = .5; AirportInfoPanel encryptionPanel = new AirportInfoPanel(); encryptionPanel.add(encryptionKeyField); this.setLayout(theLayout); JLabel theLabel; c.anchor = GridBagConstraints.WEST; c.gridx = 1; c.gridy = 1; theLayout.setConstraints(noEncryptionButton, c); this.add(noEncryptionButton); c.anchor = GridBagConstraints.WEST; c.gridx = 1; c.gridy = 2; theLayout.setConstraints(keySize40Button, c); this.add(keySize40Button); c.anchor = GridBagConstraints.WEST; c.gridx = 1; c.gridy = 3; theLayout.setConstraints(keySize128Button, c); this.add(keySize128Button); c.anchor = GridBagConstraints.CENTER; c.gridx = 1; c.gridy = 4; theLayout.setConstraints(encryptionPanel, c); this.add(encryptionPanel); keySize40Button.addItemListener(encryptionPanel); keySize128Button.addItemListener(encryptionPanel); encryptionPanel.setEnabled(keySize40Button.isSelected() || keySize128Button.isSelected()); } public void writeValue() throws ValueFormatException { // set maxSize of encryption key field based on button selection AirportInfoRecord keyRecord = theInfo.get("raWE"); // set max size accordingly; write operation will throw exception if needed if (keySize40Button.isSelected()) { keyRecord.maxLength = 5; encryptionKeyField.writeValue(); } else if (keySize128Button.isSelected()) { keyRecord.maxLength = 13; encryptionKeyField.writeValue(); } super.writeValue(); } }airport2config-2.0.1/airport/AirportDistanceRatePanel.java0000644000175000017500000001555707503646704023242 0ustar julienjulien/* * AirportBaseStationConfigurator * * Copyright (C) 2000, Jonathan Sevy * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ package airport; import java.awt.*; import javax.swing.*; /** * Panel which maintains wireless LAN information: network name, channel, and encryption switch and key. * Note that encryption key is supplied as 10-digit hex string (with no "0x" prefix). */ public class AirportDistanceRatePanel extends AirportInfoPanel { private AirportInfoRadioButton large1MbpsButton, large2MbpsButton; private AirportInfoRadioButton medium1MbpsButton, medium2MbpsButton, medium5MbpsButton; private AirportInfoRadioButton small1MbpsButton, small2MbpsButton, small5MbpsButton, small11MbpsButton; private ButtonGroup buttonGroup; public AirportDistanceRatePanel(AirportInfo theInfo) { /** * Access point density, multicast rate: * * Multicast rate: 01 = 1 Mbps, 02 = 2 Mbps, 55 = 5.5 Mbps, 11 = 11 Mbps * Density: 1 = low, 2 = medium, 3 = high * * large medium small * 1 Mbps OK OK OK * 2 Mbps OK OK OK * 5.5 Mbps na OK OK * 11 Mbps na na OK */ large1MbpsButton = new AirportInfoRadioButton(""); large1MbpsButton.addInfoRecord(theInfo.get("raDe"), "00000001"); large1MbpsButton.addInfoRecord(theInfo.get("raMu"), "00000001"); medium1MbpsButton = new AirportInfoRadioButton(""); medium1MbpsButton.addInfoRecord(theInfo.get("raDe"), "00000002"); medium1MbpsButton.addInfoRecord(theInfo.get("raMu"), "00000001"); small1MbpsButton = new AirportInfoRadioButton(""); small1MbpsButton.addInfoRecord(theInfo.get("raDe"), "00000003"); small1MbpsButton.addInfoRecord(theInfo.get("raMu"), "00000001"); large2MbpsButton = new AirportInfoRadioButton(""); large2MbpsButton.addInfoRecord(theInfo.get("raDe"), "00000001"); large2MbpsButton.addInfoRecord(theInfo.get("raMu"), "00000002"); medium2MbpsButton = new AirportInfoRadioButton(""); medium2MbpsButton.addInfoRecord(theInfo.get("raDe"), "00000002"); medium2MbpsButton.addInfoRecord(theInfo.get("raMu"), "00000002"); small2MbpsButton = new AirportInfoRadioButton(""); small2MbpsButton.addInfoRecord(theInfo.get("raDe"), "00000003"); small2MbpsButton.addInfoRecord(theInfo.get("raMu"), "00000002"); medium5MbpsButton = new AirportInfoRadioButton(""); medium5MbpsButton.addInfoRecord(theInfo.get("raDe"), "00000002"); medium5MbpsButton.addInfoRecord(theInfo.get("raMu"), "00000055"); small5MbpsButton = new AirportInfoRadioButton(""); small5MbpsButton.addInfoRecord(theInfo.get("raDe"), "00000003"); small5MbpsButton.addInfoRecord(theInfo.get("raMu"), "00000055"); small11MbpsButton = new AirportInfoRadioButton(""); small11MbpsButton.addInfoRecord(theInfo.get("raDe"), "00000003"); small11MbpsButton.addInfoRecord(theInfo.get("raMu"), "00000011"); buttonGroup = new ButtonGroup(); buttonGroup.add(large1MbpsButton); buttonGroup.add(medium1MbpsButton); buttonGroup.add(small1MbpsButton); buttonGroup.add(large2MbpsButton); buttonGroup.add(medium2MbpsButton); buttonGroup.add(small2MbpsButton); buttonGroup.add(medium5MbpsButton); buttonGroup.add(small5MbpsButton); buttonGroup.add(small11MbpsButton); setUpDisplay(); } public void setUpDisplay() { // set params for layout manager GridBagLayout theLayout = new GridBagLayout(); GridBagConstraints c = new GridBagConstraints(); c.gridwidth = 1; c.gridheight = 1; c.fill = GridBagConstraints.NONE; c.ipadx = 0; c.ipady = 0; c.insets = new Insets(2,2,2,2); c.anchor = GridBagConstraints.CENTER; c.weightx = .5; c.weighty = .5; this.setLayout(theLayout); JLabel theLabel; c.gridwidth = 3; c.gridx = 2; c.gridy = 1; theLabel = new JLabel("Distance between access points"); theLayout.setConstraints(theLabel, c); this.add(theLabel); c.gridwidth = 1; c.insets = new Insets(2,10,8,10); c.gridx = 1; c.gridy = 2; theLabel = new JLabel("Rate:"); theLayout.setConstraints(theLabel, c); this.add(theLabel); c.gridx = 2; c.gridy = 2; theLabel = new JLabel("Large "); theLayout.setConstraints(theLabel, c); this.add(theLabel); c.gridx = 3; c.gridy = 2; theLabel = new JLabel("Medium"); theLayout.setConstraints(theLabel, c); this.add(theLabel); c.gridx = 4; c.gridy = 2; theLabel = new JLabel("Small "); theLayout.setConstraints(theLabel, c); this.add(theLabel); c.insets = new Insets(2,2,2,2); c.gridx = 1; c.gridy = 3; theLabel = new JLabel("1 Mbps"); theLayout.setConstraints(theLabel, c); this.add(theLabel); c.gridx = 2; c.gridy = 3; theLayout.setConstraints(large1MbpsButton, c); this.add(large1MbpsButton); c.gridx = 3; c.gridy = 3; theLayout.setConstraints(medium1MbpsButton, c); this.add(medium1MbpsButton); c.gridx = 4; c.gridy = 3; theLayout.setConstraints(small1MbpsButton, c); this.add(small1MbpsButton); c.gridx = 1; c.gridy = 4; theLabel = new JLabel("2 Mbps"); theLayout.setConstraints(theLabel, c); this.add(theLabel); c.gridx = 2; c.gridy = 4; theLayout.setConstraints(large2MbpsButton, c); this.add(large2MbpsButton); c.gridx = 3; c.gridy = 4; theLayout.setConstraints(medium2MbpsButton, c); this.add(medium2MbpsButton); c.gridx = 4; c.gridy = 4; theLayout.setConstraints(small2MbpsButton, c); this.add(small2MbpsButton); c.gridx = 1; c.gridy = 5; theLabel = new JLabel("5.5 Mbps"); theLayout.setConstraints(theLabel, c); this.add(theLabel); c.gridx = 3; c.gridy = 5; theLayout.setConstraints(medium5MbpsButton, c); this.add(medium5MbpsButton); c.gridx = 4; c.gridy = 5; theLayout.setConstraints(small5MbpsButton, c); this.add(small5MbpsButton); c.gridx = 1; c.gridy = 6; theLabel = new JLabel("11 Mbps"); theLayout.setConstraints(theLabel, c); this.add(theLabel); c.gridx = 4; c.gridy = 6; theLayout.setConstraints(small11MbpsButton, c); this.add(small11MbpsButton); } }airport2config-2.0.1/airport/AirportSNMPPanel.java0000644000175000017500000001034007503646704021432 0ustar julienjulien/* * AirportBaseStationConfigurator * * Copyright (C) 2000, Jonathan Sevy * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ package airport; import java.awt.*; import javax.swing.*; /** * Panel which maintains wireless LAN information: network name, channel, and encryption switch and key. * Note that encryption key is supplied as 10-digit hex string (with no "0x" prefix). */ public class AirportSNMPPanel extends AirportInfoPanel { private AirportInfoLabelledTextField trapHostPasswordField, trapHostIPAddressField, syslogHostIPAddressField; private AirportInfoComboBox syslogHostFacilityBox; //private AirportSNMPAccessControlTable snmpAccessControlTable; public AirportSNMPPanel(AirportInfo theInfo) { /* 0x0478: syslog IP address 0x0440: syslog host facility(0 - 8) 0x047C: trap host IP address 0x0056: trap host password 0x0076: read password */ trapHostPasswordField = new AirportInfoLabelledTextField("Trap host password:", theInfo.get("Trap community")); trapHostIPAddressField = new AirportInfoLabelledTextField("Trap host IP address:", theInfo.get("Trap host IP address")); syslogHostIPAddressField = new AirportInfoLabelledTextField("Syslog host IP address:", theInfo.get("Syslog host IP address")); syslogHostFacilityBox = new AirportInfoComboBox("Syslog host facility", theInfo.get("Syslog host facility")); for (int i = 0; i < 9; i++) syslogHostFacilityBox.addItemAndValue(Integer.toString(i), Integer.toString(i)); /** * * SNMP access control list: require multi-block windows * * 0x0636: number of entries (0-5) * * 0x0638, 0x063a, 0x063c, 0x063e, 0x0640: first two octets of IP addresses * 0x0642, 0x0644, 0x0646, 0x0648, 0x064a: second two octets of IP addresses * * 0x064c, 0x064e, 0x0650, 0x0652, 0x0654: first two octets of masks * 0x0656, 0x0658, 0x065a, 0x065c, 0x065e: second two octets of masks * * 0x0660, 0x0662, 0x0664, 0x0666, 0x0668: interfaces: 2-byte little-endian (any = ff ff) */ // Nuts! The base station doesn't restrict SNMP access.... :-( //snmpAccessControlTable = new AirportSNMPAccessControlTable(theInfo); setUpDisplay(); } public void setUpDisplay() { // set params for layout manager GridBagLayout theLayout = new GridBagLayout(); GridBagConstraints c = new GridBagConstraints(); c.gridwidth = 1; c.gridheight = 1; c.fill = GridBagConstraints.NONE; c.ipadx = 0; c.ipady = 0; c.insets = new Insets(8,2,2,2); c.anchor = GridBagConstraints.CENTER; c.weightx = 0; c.weighty = 0; this.setLayout(theLayout); JLabel theLabel; c.gridx = 1; c.gridy = 1; theLayout.setConstraints(trapHostIPAddressField, c); this.add(trapHostIPAddressField); c.gridx = 2; c.gridy = 1; theLayout.setConstraints(trapHostPasswordField, c); this.add(trapHostPasswordField); c.gridx = 1; c.gridy = 2; theLayout.setConstraints(syslogHostIPAddressField, c); this.add(syslogHostIPAddressField); c.gridx = 2; c.gridy = 2; theLayout.setConstraints(syslogHostFacilityBox, c); this.add(syslogHostFacilityBox); c.gridwidth = 2; /* c.gridx = 1; c.gridy = 3; theLabel = new JLabel("SNMP Access Control List"); theLayout.setConstraints(theLabel, c); this.add(theLabel); c.gridx = 1; c.gridy = 4; theLayout.setConstraints(snmpAccessControlTable, c); this.add(snmpAccessControlTable); */ } }airport2config-2.0.1/airport/AirportAdvancedPanel.java0000644000175000017500000000424707503646704022373 0ustar julienjulien/* * AirportBaseStationConfigurator * * Copyright (C) 2000, Jonathan Sevy * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ package airport; import java.awt.*; import javax.swing.*; /** * Panel which maintains wireless LAN information: network name, channel, and encryption switch and key. * Note that encryption key is supplied as 10-digit hex string (with no "0x" prefix). */ public class AirportAdvancedPanel extends AirportInfoPanel { private AirportDistanceRatePanel distanceRatePanel; public AirportAdvancedPanel(AirportInfo theInfo) { distanceRatePanel = new AirportDistanceRatePanel(theInfo); setUpDisplay(); } public void setUpDisplay() { // set params for layout manager GridBagLayout theLayout = new GridBagLayout(); GridBagConstraints c = new GridBagConstraints(); c.gridwidth = 1; c.gridheight = 1; c.fill = GridBagConstraints.NONE; c.ipadx = 0; c.ipady = 0; c.insets = new Insets(8,2,2,2); c.anchor = GridBagConstraints.CENTER; c.weightx = 0; c.weighty = 0; this.setLayout(theLayout); JLabel theLabel; c.gridx = 1; c.gridy = 1; theLabel = new JLabel("Wireless LAN Multicast Rate / Access Point Separation Setting"); theLayout.setConstraints(theLabel, c); this.add(theLabel); c.gridx = 1; c.gridy = 2; theLayout.setConstraints(distanceRatePanel, c); this.add(distanceRatePanel); } }airport2config-2.0.1/airport/AirportSNMPAccessControlTable.java0000644000175000017500000003454307503646704024120 0ustar julienjulien/* * AirportBaseStationConfigurator * * Copyright (C) 2000, Jonathan Sevy * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ package airport; import java.awt.*; import java.awt.event.*; import java.util.*; import javax.swing.*; import javax.swing.event.*; import javax.swing.table.*; /** * Handles display and updating of IP addresses, masks and interface numbers used for SNMP access control. */ public class AirportSNMPAccessControlTable extends AirportInfoPanel { private AirportInfo airportInfo; private Vector addressVector; private JTable table; private AbstractTableModel tableModel; private JComboBox interfaceComboBox; private Hashtable interfaceNameToNumberHashtable, interfaceNumberToNameHashtable; /** * Table model which maintains list of IP addresses, masks and interface numbers. */ private class AccessAddressTableModel extends AbstractTableModel { public int getColumnCount() { return 3; } public int getRowCount() { return AirportInfo.MAX_NUM_SNMP_ACCESS_ENTRIES; } public boolean isCellEditable(int row, int col) { if (row <= addressVector.size()) return true; else return false; } public String getColumnName(int col) { switch (col) { case 0: return "IP address"; case 1: return "Address mask"; default: return "Interface"; } } /* * JTable uses this method to determine the default renderer/ * editor for each cell. */ public Class getColumnClass(int column) { String temp = ""; return temp.getClass(); } public Object getValueAt(int row, int col) { if (row < addressVector.size()) { return ((String[])addressVector.elementAt(row))[col]; } else return ""; } public void setValueAt(Object newValue, int row, int col) { if (row < addressVector.size()) { String[] addressEntry = (String[])addressVector.elementAt(row); addressEntry[col] = (String)newValue; } else { String[] addressEntry = {"", "", ""}; addressEntry[col] = (String)newValue; addressVector.insertElementAt(addressEntry, addressVector.size()); } fireTableCellUpdated(row, col); } } /** * Create new table based on data in airportInfo. */ public AirportSNMPAccessControlTable(AirportInfo airportInfo) { this.airportInfo = airportInfo; interfaceComboBox = new JComboBox(); interfaceComboBox.addItem("All"); interfaceComboBox.addItem("Ethernet"); interfaceComboBox.addItem("Wireless"); interfaceComboBox.addItem("Modem"); interfaceNameToNumberHashtable = new Hashtable(); interfaceNameToNumberHashtable.put("Ethernet", "0"); interfaceNameToNumberHashtable.put("Wireless", "1"); interfaceNameToNumberHashtable.put("Modem", "2"); interfaceNameToNumberHashtable.put("All", "65535"); interfaceNumberToNameHashtable = new Hashtable(); interfaceNumberToNameHashtable.put("0", "Ethernet"); interfaceNumberToNameHashtable.put("1", "Wireless"); interfaceNumberToNameHashtable.put("2", "Modem"); interfaceNumberToNameHashtable.put("65535", "All"); setUpDisplay(); } private void setUpDisplay() { refreshDisplay(); } /** * Write the IP addresses and masks in the list into the appropriate locations * in the byte block referenced by the AirportInfo object supplied in the constructor. * @throws ValueFormatException Thrown if an IP address or mask is malformed. Also sets * editting focus to the offending cell. */ public void writeValue() throws ValueFormatException { int baseStartIndex, numRows, numCols, dataType; // first, record changes if cell currently being edited TableCellEditor editor = table.getCellEditor(); if(editor != null) editor.stopCellEditing(); ByteBlock baseBlock = airportInfo.baseBlock; // erase current blocks of info baseStartIndex = 0x0638; numRows = 1; numCols = 10 * AirportInfo.MAX_NUM_SNMP_ACCESS_ENTRIES; dataType = AirportInfoRecord.BYTE_STRING; AirportInfoRecord portMapBlockRecord = new AirportInfoRecord(baseStartIndex, numRows, numCols, dataType, baseBlock); portMapBlockRecord.clearWindow(); //create new info records /* * * SNMP access control list: require multi-block windows * * 0x0636: number of entries (0-5) * * 0x0638, 0x063a, 0x063c, 0x063e, 0x0640: first two octets of IP addresses * 0x0642, 0x0644, 0x0646, 0x0648, 0x064a: second two octets of IP addresses * * 0x064c, 0x064e, 0x0650, 0x0652, 0x0654: first two octets of masks * 0x0656, 0x0658, 0x065a, 0x065c, 0x065e: second two octets of masks * * 0x0660, 0x0662, 0x0664, 0x0666, 0x0668: interfaces: 2-byte little-endian (any = ff ff) */ int numSNMPEntries = 0; int ipAddressStartIndex = 0x0638; int ipAddressBeginningNumRows = 1; int ipAddressBeginningNumCols = 2; int ipAddressEndingIndex = 0x0642; int ipAddressEndingNumRows = 1; int ipAddressEndingNumCols = 2; int ipAddressDataType = AirportInfoRecord.IP_ADDRESS; int ipMaskStartIndex = 0x064c; int ipMaskBeginningNumRows = 1; int ipMaskBeginningNumCols = 2; int ipMaskEndingIndex = 0x0656; int ipMaskEndingNumRows = 1; int ipMaskEndingNumCols = 2; int ipMaskDataType = AirportInfoRecord.IP_ADDRESS; int interfaceNumberStartIndex = 0x0660; int interfaceNumberNumRows = 1; int interfaceNumberNumCols = 2; int interfaceNumberDataType = AirportInfoRecord.LITTLE_ENDIAN_UNSIGNED_INTEGER; for (int i = 0; i < addressVector.size(); i++) { String ipAddress = ((String[])addressVector.elementAt(i))[0]; String ipMask = ((String[])addressVector.elementAt(i))[1]; String interfaceName = ((String[])addressVector.elementAt(i))[2]; // if null row, just ignore if (! (ipAddress.equals(""))) { // null address or port throws exception when write to info records try { // need to have a multi window since address octets not contiguous! ByteBlockMultiWindow ipAddressWindow = new ByteBlockMultiWindow(); ByteBlockWindow ipAddressBeginningWindow = new ByteBlockRectangularWindow(ipAddressStartIndex, ipAddressBeginningNumRows, ipAddressBeginningNumCols, baseBlock); ipAddressWindow.addWindow(ipAddressBeginningWindow); ByteBlockWindow ipAddressEndingWindow = new ByteBlockRectangularWindow(ipAddressEndingIndex, ipAddressEndingNumRows, ipAddressEndingNumCols, baseBlock); ipAddressWindow.addWindow(ipAddressEndingWindow); AirportInfoRecord ipAddressRecord = new AirportInfoRecord(ipAddressDataType, ipAddressWindow); ipAddressRecord.setBytesFromString(ipAddress); } catch (ValueFormatException e) { table.editCellAt(i,0); throw e; } try { // need to have a multi window since address octets not contiguous! ByteBlockMultiWindow ipMaskWindow = new ByteBlockMultiWindow(); ByteBlockWindow ipMaskBeginningWindow = new ByteBlockRectangularWindow(ipMaskStartIndex, ipMaskBeginningNumRows, ipMaskBeginningNumCols, baseBlock); ipMaskWindow.addWindow(ipMaskBeginningWindow); ByteBlockWindow ipMaskEndingWindow = new ByteBlockRectangularWindow(ipMaskEndingIndex, ipMaskEndingNumRows, ipMaskEndingNumCols, baseBlock); ipMaskWindow.addWindow(ipMaskEndingWindow); AirportInfoRecord ipMaskRecord = new AirportInfoRecord(ipMaskDataType, ipMaskWindow); ipMaskRecord.setBytesFromString(ipMask); } catch (ValueFormatException e) { table.editCellAt(i,1); throw e; } try { AirportInfoRecord interfaceNumberRecord = new AirportInfoRecord(interfaceNumberStartIndex, interfaceNumberNumRows, interfaceNumberNumCols, interfaceNumberDataType, baseBlock); // need to convert name to number using Hashtable String interfaceNumber = (String)interfaceNameToNumberHashtable.get(interfaceName); interfaceNumberRecord.setBytesFromString(interfaceNumber); } catch (ValueFormatException e) { table.editCellAt(i,2); throw e; } // augment port map count, start indices ipAddressStartIndex += 2; ipAddressEndingIndex += 2; ipMaskStartIndex += 2; ipMaskEndingIndex += 2; interfaceNumberStartIndex += 2; numSNMPEntries++; } } // finally, write the number of addresses written AirportInfoRecord snmpAccessControlCountRecord = airportInfo.get("SNMP access control list length"); String countString = new String(); countString += numSNMPEntries; snmpAccessControlCountRecord.setBytesFromString(countString); } /** * Refresh the display based on the current data in the underlying byte block. */ public void refreshDisplay() { ByteBlock baseBlock = airportInfo.baseBlock; /* * * SNMP access control list: require multi-block windows * * 0x0636: number of entries (0-5) * * 0x0638, 0x063a, 0x063c, 0x063e, 0x0640: first two octets of IP addresses * 0x0642, 0x0644, 0x0646, 0x0648, 0x064a: second two octets of IP addresses * * 0x064c, 0x064e, 0x0650, 0x0652, 0x0654: first two octets of masks * 0x0656, 0x0658, 0x065a, 0x065c, 0x065e: second two octets of masks * * 0x0660, 0x0662, 0x0664, 0x0666, 0x0668: interfaces: 2-byte little-endian (any = ff ff) */ AirportInfoRecord snmpAccessControlCountRecord = airportInfo.get("SNMP access control list length"); // Read in appropriate number of Mac addresses String countString = snmpAccessControlCountRecord.toString(); int numSNMPEntries = 0; try { numSNMPEntries = Integer.parseInt(countString); } catch(NumberFormatException e) { System.out.println("Problem with number of SNMP access control entries"); } // create new addressVector, with appropriate size addressVector = new Vector(); int ipAddressStartIndex = 0x0638; int ipAddressBeginningNumRows = 1; int ipAddressBeginningNumCols = 2; int ipAddressEndingIndex = 0x0642; int ipAddressEndingNumRows = 1; int ipAddressEndingNumCols = 2; int ipAddressDataType = AirportInfoRecord.IP_ADDRESS; int ipMaskStartIndex = 0x064c; int ipMaskBeginningNumRows = 1; int ipMaskBeginningNumCols = 2; int ipMaskEndingIndex = 0x0656; int ipMaskEndingNumRows = 1; int ipMaskEndingNumCols = 2; int ipMaskDataType = AirportInfoRecord.IP_ADDRESS; int interfaceNumberStartIndex = 0x0660; int interfaceNumberNumRows = 1; int interfaceNumberNumCols = 2; int interfaceNumberDataType = AirportInfoRecord.LITTLE_ENDIAN_UNSIGNED_INTEGER; for (int i = 0; i < numSNMPEntries; i++) { // need to have a multi window since IP address octets not contiguous! ByteBlockMultiWindow ipAddressWindow = new ByteBlockMultiWindow(); ByteBlockWindow ipAddressBeginningWindow = new ByteBlockRectangularWindow(ipAddressStartIndex, ipAddressBeginningNumRows, ipAddressBeginningNumCols, baseBlock); ipAddressWindow.addWindow(ipAddressBeginningWindow); ByteBlockWindow ipAddressEndingWindow = new ByteBlockRectangularWindow(ipAddressEndingIndex, ipAddressEndingNumRows, ipAddressEndingNumCols, baseBlock); ipAddressWindow.addWindow(ipAddressEndingWindow); AirportInfoRecord ipAddressRecord = new AirportInfoRecord(ipAddressDataType, ipAddressWindow); ByteBlockMultiWindow ipMaskWindow = new ByteBlockMultiWindow(); ByteBlockWindow ipMaskBeginningWindow = new ByteBlockRectangularWindow(ipMaskStartIndex, ipMaskBeginningNumRows, ipMaskBeginningNumCols, baseBlock); ipMaskWindow.addWindow(ipMaskBeginningWindow); ByteBlockWindow ipMaskEndingWindow = new ByteBlockRectangularWindow(ipMaskEndingIndex, ipMaskEndingNumRows, ipMaskEndingNumCols, baseBlock); ipMaskWindow.addWindow(ipMaskEndingWindow); AirportInfoRecord ipMaskRecord = new AirportInfoRecord(ipMaskDataType, ipMaskWindow); AirportInfoRecord interfaceNumberRecord = new AirportInfoRecord(interfaceNumberStartIndex, interfaceNumberNumRows, interfaceNumberNumCols, interfaceNumberDataType, baseBlock); String[] addressEntry = new String[3]; addressEntry[0] = ipAddressRecord.toString(); addressEntry[1] = ipMaskRecord.toString(); // need to convert number to name using Hashtable String interfaceNumber = interfaceNumberRecord.toString(); System.out.println("Interface number: " + interfaceNumber); addressEntry[2] = (String)interfaceNumberToNameHashtable.get(interfaceNumber); System.out.println("Interface value: " + addressEntry[2]); addressVector.insertElementAt(addressEntry, addressVector.size()); ipAddressStartIndex += 2; ipAddressEndingIndex += 2; ipMaskStartIndex += 2; ipMaskEndingIndex += 2; interfaceNumberStartIndex += 2; } this.removeAll(); tableModel = new AccessAddressTableModel(); table = new JTable(tableModel); table.setCellSelectionEnabled(true); //Set up the editor for the interface column. table.getColumn("Interface").setCellEditor(new DefaultCellEditor(interfaceComboBox)); table.setPreferredScrollableViewportSize(new Dimension(300,80)); JScrollPane scrollPane = new JScrollPane(table); this.add(scrollPane); } }airport2config-2.0.1/airport/AirportLoginStringTable.java0000644000175000017500000002601207503646704023107 0ustar julienjulien/* * AirportBaseStationConfigurator * * Copyright (C) 2000, Jonathan Sevy * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ package airport; import java.awt.*; import java.awt.event.*; import java.util.*; import java.io.*; import javax.swing.*; import javax.swing.event.*; import javax.swing.table.*; /** * Handles display and updating of entries used in login string. */ public class AirportLoginStringTable extends AirportInfoPanel { private AirportInfo airportInfo; private Vector tableContentsVector; private JTable table; private JScrollPane tableScrollPane; private AbstractTableModel tableModel; private JComboBox elementTypeComboBox; private final int MAX_NUM_LOGIN_STRING_ENTRIES = 20; /** * Table model which maintains list of login string elements. */ private class LoginStringTableModel extends AbstractTableModel { public int getColumnCount() { return 3; } public int getRowCount() { return MAX_NUM_LOGIN_STRING_ENTRIES; } public boolean isCellEditable(int row, int col) { if (row <= tableContentsVector.size()) { if (col < 2) return true; else // carriage return column; editable only if send or receive (not delay) { if (row == tableContentsVector.size()) return false; else { Object[] currentRow = (Object[])tableContentsVector.elementAt(row); if ( ((String)currentRow[0]).equals("Send string") || ((String)currentRow[0]).equals("Expect string") ) return true; else return false; } } } else return false; } public String getColumnName(int col) { switch (col) { case 0: return "Element type"; case 1: return "Value"; default: return "Carriage return"; } } /* * JTable uses this method to determine the default renderer/ * editor for each cell. */ public Class getColumnClass(int column) { String stringDummy = ""; Boolean booleanDummy = new Boolean(true); switch (column) { case 0: return stringDummy.getClass(); case 1: return stringDummy.getClass(); default: return booleanDummy.getClass(); } } public Object getValueAt(int row, int col) { //System.out.println("Get value: " + row + ", " + col); if (row < tableContentsVector.size()) { return ((Object[])tableContentsVector.elementAt(row))[col]; } else { if (col < 2) return ""; else return new Boolean(false); } } public void setValueAt(Object newValue, int row, int col) { if (row < tableContentsVector.size()) { Object[] addressEntry = (Object[])tableContentsVector.elementAt(row); addressEntry[col] = newValue; // if change type to "delay", erase cr entry if ( (col == 0) && (((String)newValue).equals("Delay (seconds)")) ) { addressEntry[2] = new Boolean(false); fireTableCellUpdated(row, 2); } } else { Object[] addressEntry = {"", "", new Boolean(false)}; addressEntry[col] = newValue; tableContentsVector.insertElementAt(addressEntry, tableContentsVector.size()); } //System.out.println("New value: " + newValue); fireTableCellUpdated(row, col); } } /** * Create new table based on data in airportInfo. */ public AirportLoginStringTable(AirportInfo airportInfo) { this.airportInfo = airportInfo; tableContentsVector = new Vector(); elementTypeComboBox = new JComboBox(); elementTypeComboBox.addItem(""); elementTypeComboBox.addItem("Expect string"); elementTypeComboBox.addItem("Send string"); elementTypeComboBox.addItem("Delay (seconds)"); setUpDisplay(); } private void setUpDisplay() { refreshDisplay(); } /** * Write the modem string information into the appropriate location * in the byte block referenced by the AirportInfo object supplied in the constructor. * @throws ValueFormatException Thrown if an entry is malformed. Also sets * editting focus to the offending cell. */ public void writeValue() throws ValueFormatException { // first, record changes if cell currently being edited TableCellEditor editor = table.getCellEditor(); if(editor != null) editor.stopCellEditing(); ByteArrayOutputStream outStream = new ByteArrayOutputStream(); for (int i = 0; i < tableContentsVector.size(); i++) { String elementTypeString = (String)((Object[])tableContentsVector.elementAt(i))[0]; String elementValueString = (String)((Object[])tableContentsVector.elementAt(i))[1]; boolean carriageReturnFlag = ((Boolean)((Object[])tableContentsVector.elementAt(i))[2]).booleanValue(); // if null type, just ignore if (!(elementTypeString.equals(""))) { try { // set start byte: // Send string = 0x40, Expect string = 0x80, Delay = 0xC0 // plus number of characters to follow, or delay value if (elementTypeString.equals("Expect string") || elementTypeString.equals("Send string")) { byte startByte; if (elementTypeString.equals("Expect string")) startByte = (byte)0x80; else if (elementTypeString.equals("Send string")) startByte = (byte)0x40; else startByte = (byte)0x00; startByte += elementValueString.length(); if (carriageReturnFlag == true) ++startByte; outStream.write(startByte); byte[] valueBytes = elementValueString.getBytes(); try { outStream.write(valueBytes); } catch (IOException e) { // won't happen } if (carriageReturnFlag == true) { outStream.write((byte)0x0D); // CR in ACSCII } } else if (elementTypeString.equals("Delay (seconds)")) { int delayValue = Integer.parseInt(elementValueString); outStream.write((byte)(0xC0 + delayValue)); if ((delayValue < 0) || (delayValue > 63)) { table.editCellAt(i,1); throw new ValueFormatException("Delay must be between 0 and 63 seconds"); } } } catch (NumberFormatException e) { table.editCellAt(i,1); throw new ValueFormatException("Bad delay value"); } catch (ArrayIndexOutOfBoundsException e) { throw new ValueFormatException("Login string too long (maximum size 127 characters)"); } } } byte[] bytes = outStream.toByteArray(); // set modem and pppoe username fields with this stuff; erase password records AirportInfoRecord modemUsernameRecord = (AirportInfoRecord)airportInfo.get("moUN"); modemUsernameRecord.setValue(bytes); AirportInfoRecord modemPasswordRecord = (AirportInfoRecord)airportInfo.get("moPW"); modemPasswordRecord.setValue(new byte[0]); AirportInfoRecord pppoeUsernameRecord = (AirportInfoRecord)airportInfo.get("peUN"); pppoeUsernameRecord.setValue(bytes); AirportInfoRecord pppoePasswordRecord = (AirportInfoRecord)airportInfo.get("pePW"); pppoePasswordRecord.setValue(new byte[0]); } /** * Refresh the display based on the current data in the underlying byte block. */ public void refreshDisplay() { AirportInfoRecord modemUsernameRecord = (AirportInfoRecord)airportInfo.get("moUN"); byte[] loginBytes = modemUsernameRecord.getValue(); int currentPosition = 0; WhileLoop: while (currentPosition < loginBytes.length) { int typeAndLength = loginBytes[currentPosition]; ++currentPosition; // make positive if (typeAndLength < 0) typeAndLength += 256; int length = typeAndLength % 64; int type = typeAndLength - length; switch (type) { case 0xC0: // delay entry { Object[] addressEntry = {"Delay (seconds)", Integer.toString(length), new Boolean(false)}; tableContentsVector.insertElementAt(addressEntry, tableContentsVector.size()); break; } case 0x40: // send string, receive string entry case 0x80: { String valueString = new String(loginBytes); valueString = valueString.substring(currentPosition, currentPosition + length); currentPosition += length; boolean crFlag; if (loginBytes[currentPosition - 1] == 0x0d) // see if last char is CR { // if last char is CR, strip it off and set crFlag valueString = valueString.substring(0, length - 1); crFlag = true; } else { crFlag = false; } Object[] addressEntry = new Object[3]; addressEntry[1] = valueString; addressEntry[2] = new Boolean(crFlag); if (type == 0x40) { addressEntry[0] = "Send string"; } else // (type == 0x80) { addressEntry[0] = "Expect string"; } tableContentsVector.insertElementAt(addressEntry, tableContentsVector.size()); break; } default: { // break out of while loop... break WhileLoop; } } } // remove all components... this.removeAll(); // create new table model and table... tableModel = new LoginStringTableModel(); table = new JTable(tableModel); table.setCellSelectionEnabled(true); //Set the editor for the interface column. table.getColumn("Element type").setCellEditor(new DefaultCellEditor(elementTypeComboBox)); table.setPreferredScrollableViewportSize(new Dimension(300,150)); // add it to a scroll pane tableScrollPane = new JScrollPane(table); this.add(tableScrollPane); } /** * Enable and disable JTable as well as any other contained components. */ public void setEnabled(boolean enabled) { super.setEnabled(enabled); table.setEnabled(enabled); } }airport2config-2.0.1/airport/AirportLoginInfoDialog.java0000644000175000017500000000731407503646704022710 0ustar julienjulien/* * AirportBaseStationConfigurator * * Copyright (C) 2000, Jonathan Sevy * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ package airport; import java.awt.*; import java.awt.event.*; import javax.swing.*; /** * Frame which presents data pertaining to modem login info. */ public class AirportLoginInfoDialog extends JDialog implements ActionListener { private AirportLoginInfoPanel loginPanel; private JButton okButton, cancelButton; private JTextArea messagesArea; public AirportLoginInfoDialog(Frame owner, String title, boolean modal, AirportInfo theInfo) { super(owner, title, modal); // close only on Cancel or OK button press this.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); // panel holding login info loginPanel = new AirportLoginInfoPanel(theInfo); setUpDisplay(); } public void setUpDisplay() { okButton = new JButton("OK"); okButton.setActionCommand("ok"); okButton.addActionListener(this); cancelButton = new JButton("Cancel"); cancelButton.setActionCommand("cancel"); cancelButton.addActionListener(this); messagesArea = new JTextArea(4,60); JScrollPane messagesScroll = new JScrollPane(messagesArea); // set params for layout manager GridBagLayout theLayout = new GridBagLayout(); GridBagConstraints c = new GridBagConstraints(); c.gridwidth = 1; c.gridheight = 1; c.fill = GridBagConstraints.NONE; c.ipadx = 0; c.ipady = 0; c.insets = new Insets(2,2,2,2); c.anchor = GridBagConstraints.CENTER; c.weightx = .5; c.weighty = .5; this.getContentPane().setLayout(theLayout); // add components c.gridwidth = 2; c.gridx = 1; c.gridy = 1; theLayout.setConstraints(loginPanel, c); this.getContentPane().add(loginPanel); c.gridwidth = 1; c.gridx = 1; c.gridy = 2; theLayout.setConstraints(okButton, c); this.getContentPane().add(okButton); c.gridx = 2; c.gridy = 2; theLayout.setConstraints(cancelButton, c); this.getContentPane().add(cancelButton); c.gridwidth = 2; c.gridx = 1; c.gridy = 3; JLabel messageLabel = new JLabel("Messages"); theLayout.setConstraints(messageLabel, c); this.getContentPane().add(messageLabel); c.gridwidth = 2; c.gridx = 1; c.gridy = 4; theLayout.setConstraints(messagesScroll, c); this.getContentPane().add(messagesScroll); } public void actionPerformed(ActionEvent theEvent) // respond to button pushes { String command = theEvent.getActionCommand(); if (command.equals("ok")) { try { loginPanel.writeValue(); this.setVisible(false); this.dispose(); } catch (ValueFormatException ve) { messagesArea.append("Problem with supplied value: " + ve.getMessage() + "\n"); } } if (command.equals("cancel")) { this.setVisible(false); this.dispose(); } } }airport2config-2.0.1/airport/AirportPPPoELoginInfoDialog.java0000644000175000017500000000735607503646704023562 0ustar julienjulien/* * AirportBaseStationConfigurator * * Copyright (C) 2000, Jonathan Sevy * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ package airport; import java.awt.*; import java.awt.event.*; import javax.swing.*; /** * Frame which presents data pertaining to modem login info. */ public class AirportPPPoELoginInfoDialog extends JDialog implements ActionListener { private AirportUsernamePPPoEClientIDPanel loginPanel; private JButton okButton, cancelButton; private JTextArea messagesArea; public AirportPPPoELoginInfoDialog(Frame owner, String title, boolean modal, AirportInfo theInfo) { super(owner, title, modal); // close only on Cancel or OK button press this.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); // panel holding login info loginPanel = new AirportUsernamePPPoEClientIDPanel(theInfo); setUpDisplay(); } public void setUpDisplay() { okButton = new JButton("OK"); okButton.setActionCommand("ok"); okButton.addActionListener(this); cancelButton = new JButton("Cancel"); cancelButton.setActionCommand("cancel"); cancelButton.addActionListener(this); messagesArea = new JTextArea(4,60); JScrollPane messagesScroll = new JScrollPane(messagesArea); // set params for layout manager GridBagLayout theLayout = new GridBagLayout(); GridBagConstraints c = new GridBagConstraints(); c.gridwidth = 1; c.gridheight = 1; c.fill = GridBagConstraints.NONE; c.ipadx = 0; c.ipady = 0; c.insets = new Insets(2,2,2,2); c.anchor = GridBagConstraints.CENTER; c.weightx = .5; c.weighty = .5; this.getContentPane().setLayout(theLayout); // add components c.gridwidth = 2; c.gridx = 1; c.gridy = 1; theLayout.setConstraints(loginPanel, c); this.getContentPane().add(loginPanel); c.gridwidth = 1; c.gridx = 1; c.gridy = 2; theLayout.setConstraints(okButton, c); this.getContentPane().add(okButton); c.gridx = 2; c.gridy = 2; theLayout.setConstraints(cancelButton, c); this.getContentPane().add(cancelButton); c.gridwidth = 2; c.gridx = 1; c.gridy = 3; JLabel messageLabel = new JLabel("Messages"); theLayout.setConstraints(messageLabel, c); this.getContentPane().add(messageLabel); c.gridwidth = 2; c.gridx = 1; c.gridy = 4; theLayout.setConstraints(messagesScroll, c); this.getContentPane().add(messagesScroll); } public void actionPerformed(ActionEvent theEvent) // respond to button pushes { String command = theEvent.getActionCommand(); if (command.equals("ok")) { try { loginPanel.writeValue(); this.setVisible(false); this.dispose(); } catch (ValueFormatException ve) { messagesArea.append("Problem with supplied value: " + ve.getMessage() + "\n"); } } if (command.equals("cancel")) { this.setVisible(false); this.dispose(); } } }airport2config-2.0.1/airport/AirportPortMappingPanel.java0000644000175000017500000000376607503646704023133 0ustar julienjulien/* * AirportBaseStationConfigurator * * Copyright (C) 2000, Jonathan Sevy * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ package airport; import java.awt.*; import javax.swing.*; /** * Panel which maintains basic base station information: name, location, and contact individual. * Also provides textfield for entering new community name (base station password). */ public class AirportPortMappingPanel extends AirportInfoPanel { private AirportPortMappingTable portMappingTable; public AirportPortMappingPanel(AirportInfo theInfo) { portMappingTable = new AirportPortMappingTable(theInfo); setUpDisplay(); } private void setUpDisplay() { // set params for layout manager GridBagLayout theLayout = new GridBagLayout(); GridBagConstraints c = new GridBagConstraints(); c.gridwidth = 1; c.gridheight = 1; c.fill = GridBagConstraints.NONE; c.ipadx = 0; c.ipady = 0; c.insets = new Insets(2,2,2,2); c.anchor = GridBagConstraints.CENTER; c.weightx = 0; c.weighty = 0; JLabel theLabel; this.setLayout(theLayout); c.gridx = 1; c.gridy = 1; c.anchor = GridBagConstraints.CENTER; theLayout.setConstraints(portMappingTable, c); this.add(portMappingTable); } }airport2config-2.0.1/airport/AirportPPPoEConfigPanel.java0000644000175000017500000001461507503646704022737 0ustar julienjulien/* * AirportBaseStationConfigurator * * Copyright (C) 2000, Jonathan Sevy * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ package airport; import java.awt.*; import java.awt.event.*; import javax.swing.*; /** * Panel maintaining configuration information for Ethernet network connection. */ public class AirportPPPoEConfigPanel extends AirportInfoPanel implements ActionListener { private JButton loginButton; private ButtonGroup connectionGroup; private AirportInfoRadioButton pppoeAlwaysStayConnectedButton, pppoeAutomaticConnectButton, pppoeManualConnectButton; private AirportInfoLabelledScaledValueField pppoeDisconnectTimeoutField; private AirportInfo theInfo; private AirportInfoPanel pppoeDisconnectTimeoutPanel; /** * Create new panel with information from supplied AirportInfo object. */ public AirportPPPoEConfigPanel(AirportInfo theInfo) { this.theInfo = theInfo; pppoeAlwaysStayConnectedButton = new AirportInfoRadioButton("Always stay connected"); pppoeAlwaysStayConnectedButton.addInfoRecord(theInfo.get("peSC"), "01"); pppoeAlwaysStayConnectedButton.addInfoRecord(theInfo.get("peAC"), "01"); pppoeAlwaysStayConnectedButton.addInfoRecord(theInfo.get("peID"), "0"); pppoeAutomaticConnectButton = new AirportInfoRadioButton("Connect automatically"); pppoeAutomaticConnectButton.addInfoRecord(theInfo.get("peAC"), "01"); pppoeAutomaticConnectButton.addInfoRecord(theInfo.get("peSC"), "00"); pppoeManualConnectButton = new AirportInfoRadioButton("Don't connect automatically"); pppoeManualConnectButton.addInfoRecord(theInfo.get("peAC"), "00"); pppoeManualConnectButton.addInfoRecord(theInfo.get("peSC"), "00"); connectionGroup = new ButtonGroup(); connectionGroup.add(pppoeAlwaysStayConnectedButton); connectionGroup.add(pppoeAutomaticConnectButton); connectionGroup.add(pppoeManualConnectButton); pppoeDisconnectTimeoutField = new AirportInfoLabelledScaledValueField("PPPoE idle timeout (minutes; 0 = never)", theInfo.get("peID"), 60); setUpDisplay(); } private void setUpDisplay() { // set params for layout manager GridBagLayout theLayout = new GridBagLayout(); GridBagConstraints c = new GridBagConstraints(); c.gridwidth = 1; c.gridheight = 1; c.fill = GridBagConstraints.NONE; c.ipadx = 0; c.ipady = 0; Insets theMargin = new Insets(1,1,1,1); c.insets = theMargin; c.anchor = GridBagConstraints.CENTER; c.weightx = .5; c.weighty = .5; JLabel theLabel; // Button to show login panel when pressed... loginButton = new JButton("Username/Password"); loginButton.setActionCommand("show login panel"); loginButton.addActionListener(this); // panel for PPPoE timeout field pppoeDisconnectTimeoutPanel = new AirportInfoPanel(); pppoeDisconnectTimeoutPanel.add(pppoeDisconnectTimeoutField); this.setLayout(theLayout); c.gridx = 1; c.gridy = 2; c.gridwidth = 1; theLayout.setConstraints(pppoeAlwaysStayConnectedButton, c); this.add(pppoeAlwaysStayConnectedButton); c.gridx = 1; c.gridy = 3; theLayout.setConstraints(pppoeAutomaticConnectButton, c); this.add(pppoeAutomaticConnectButton); c.gridx = 1; c.gridy = 4; theLayout.setConstraints(pppoeManualConnectButton, c); this.add(pppoeManualConnectButton); c.gridx = 2; c.gridy = 2; c.gridheight = 3; c.anchor = GridBagConstraints.CENTER; theLayout.setConstraints(loginButton, c); this.add(loginButton); c.gridx = 1; c.gridy = 5; c.gridwidth = 2; c.anchor = GridBagConstraints.WEST; theLayout.setConstraints(pppoeDisconnectTimeoutPanel, c); this.add(pppoeDisconnectTimeoutPanel); // make pppoeDisconnectTimeoutPanel enabling dependent on connect status pppoeAutomaticConnectButton.addItemListener(pppoeDisconnectTimeoutPanel); pppoeManualConnectButton.addItemListener(pppoeDisconnectTimeoutPanel); // pppoeDisconnectTimeoutPanel.setEnabled(pppoeAutomaticConnectButton.isSelected() || pppoeManualConnectButton.isSelected()); pppoeDisconnectTimeoutPanel.setEnabled(pppoeAutomaticConnectButton.isSelected() || pppoeManualConnectButton.isSelected()); } /** * Override base class method to enable and disable contained components. */ public void setEnabled(boolean enabled) { super.setEnabled(enabled); if (enabled == true) { // if enabling, set enabling of pppoeDisconnectTimeoutPanel pppoeDisconnectTimeoutPanel.setEnabled(pppoeAutomaticConnectButton.isSelected() || pppoeManualConnectButton.isSelected()); } } public void actionPerformed(ActionEvent theEvent) // respond to button pushes { String command = theEvent.getActionCommand(); if (command.equals("show login panel")) { // get top-level Frame to associate modal dialog with so will be minimzed and // maximized correctly. Component owner = this; while ( !((owner == null) || (owner instanceof Frame)) ) owner = owner.getParent(); Frame owningFrame = (Frame)owner; // create and display modal dialog holding dial-up username / password and login script AirportPPPoELoginInfoDialog loginDialog = new AirportPPPoELoginInfoDialog(owningFrame, "PPPoE Login Information", true, theInfo); loginDialog.pack(); // tweak app size to make it a little larger than necessary, to address the // "shrunken textfields" problem arising from the layout manager packing stuff // a little too tightly. Dimension dim = loginDialog.getSize(); dim.height += 20; dim.width += 20; loginDialog.setSize(dim); loginDialog.show(); } } }airport2config-2.0.1/airport/AirportInfoScaledValueField.java0000644000175000017500000001003407503646704023645 0ustar julienjulien/* * AirportBaseStationConfigurator * * Copyright (C) 2000, Jonathan Sevy * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ package airport; import java.awt.*; import javax.swing.*; /** * Creates a text box to display and edit information in an AirportInfoRecord. * Size of textfield is set automatically according to datatype. */ public class AirportInfoScaledValueField extends JTextField implements AirportInfoComponent { private AirportInfoRecord theRecord; private int scalingFactor; /** * Creates new textfield to display and edit value information in an AirportInfoRecord. * Size of textfield is set automatically according to value size and scaling. */ public AirportInfoScaledValueField(AirportInfoRecord theRecord, int scalingFactor) { super(); this.theRecord = theRecord; this.scalingFactor = scalingFactor; //determine how large the text field should be to display the value int fieldSize = theRecord.maxLength; fieldSize *= 3; // to hold hex string: 2 chars per byte, plus space if (fieldSize > 40) fieldSize = 40; this.setColumns(fieldSize); refreshDisplay(); } /** * Creates new textfield to display and edit information in an AirportInfoRecord. * Size of textfield is supplied as argument. */ public AirportInfoScaledValueField(AirportInfoRecord theRecord, int scalingFactor, int fieldSize) { super(); this.theRecord = theRecord; this.scalingFactor = scalingFactor; this.setColumns(fieldSize); refreshDisplay(); } /** * Read value from associated AirportInfoRecord window, and display value. */ public void refreshDisplay() { try { long storedValue = Long.parseLong(theRecord.toString()); long displayValue = storedValue/scalingFactor; String valueString = new String(); valueString += displayValue; setText(valueString); } catch (NumberFormatException e) { // won't happen! } } /** * Write value currently displayed into associated AirportInfoRecord window. */ public void writeValue() throws ValueFormatException { long displayValue = 0; try { displayValue = Long.parseLong(getText()); } catch (NumberFormatException e) { this.selectAll(); this.requestFocus(); throw new ValueFormatException("Bad number format."); } // see how big the value can be int numBytes = theRecord.maxLength; long minValue = 0; long maxValue = 1; for (int i = 0; i < numBytes; i++) { maxValue *= 256; } maxValue -= 1; maxValue /= scalingFactor; if ((displayValue < minValue) || (displayValue > maxValue)) { this.selectAll(); this.requestFocus(); throw new ValueFormatException("Value must be between " + minValue + " and " + maxValue + "."); } long storedValue = displayValue*scalingFactor; String valueString = new String(); valueString += storedValue; theRecord.setBytesFromString(valueString); } /** * Write supplied value, rather than that currently displayed, into associated * AirportInfoRecord window. */ public void writeValue(String newValue) throws ValueFormatException { setText(newValue); writeValue(); refreshDisplay(); } }airport2config-2.0.1/airport/AirportInfoLabelledScaledValueField.java0000644000175000017500000000626307503646704025303 0ustar julienjulien/* * AirportBaseStationConfigurator * * Copyright (C) 2000, Jonathan Sevy * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ package airport; import java.awt.*; import javax.swing.*; /** * Creates a labelled text box to display and edit the information in an AirportInfoRecord. * Size of textfield is set automatically according to datatype. */ public class AirportInfoLabelledScaledValueField extends AirportInfoPanel { public String name; public AirportInfoScaledValueField theField; private AirportInfoRecord theRecord; /** * Creates new display for viewing and editing the information in the supplied * AirportInfoRecord. Size of textfield is supplied. */ public AirportInfoLabelledScaledValueField(String name, AirportInfoRecord theRecord, int scalingFactor, int fieldSize) { this.name = name; this.theRecord = theRecord; JLabel l = new JLabel(name); theField = new AirportInfoScaledValueField(theRecord, scalingFactor, fieldSize); this.setLayout(new BorderLayout(2,2)); this.add("West", l); this.add("East", theField); refreshDisplay(); } /** * Creates new display for viewing and editing the information in the supplied * AirportInfoRecord. Size of textfield is set automatically according to datatype. */ public AirportInfoLabelledScaledValueField(String name, AirportInfoRecord theRecord, int scalingFactor) { this.name = name; this.theRecord = theRecord; JLabel l = new JLabel(name); theField = new AirportInfoScaledValueField(theRecord, scalingFactor); this.setLayout(new BorderLayout(5,5)); this.add("West", l); this.add("East", theField); refreshDisplay(); } /** * Read value from associated AirportInfoRecord window, and display value. */ public void refreshDisplay() { theField.refreshDisplay(); } /** * Write value currently displayed into associated AirportInfoRecord window. */ public void writeValue() throws ValueFormatException { theField.writeValue(); } /** * Write supplied value, rather than that currently displayed, into associated * AirportInfoRecord window. */ public void writeValue(String newValue) throws ValueFormatException { theField.writeValue(newValue); } /** * Utility method to get text in enclosed textfield */ public String getText() { return theField.getText(); } }airport2config-2.0.1/airport/Airport2InfoElement.java0000644000175000017500000001240607503646704022171 0ustar julienjulien/* * Airport2InfoElement * * Copyright (C) 2002, Jonathan Sevy * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ import java.io.*; public class Airport2InfoElement { public String tag; public int dataType; public int encryption; public int length; public byte[] value; public static byte[] cipherBytes = {(byte)0x0e, (byte)0x39, (byte)0xf8, (byte)0x05, (byte)0xc4, (byte)0x01, (byte)0x55, (byte)0x4f, (byte)0x0c, (byte)0xac, (byte)0x85, (byte)0x7d, (byte)0x86, (byte)0x8a, (byte)0xb5, (byte)0x17, (byte)0x3e, (byte)0x09, (byte)0xc8, (byte)0x35, (byte)0xf4, (byte)0x31, (byte)0x65, (byte)0x7f, (byte)0x3c, (byte)0x9c, (byte)0xb5, (byte)0x6d, (byte)0x96, (byte)0x9a, (byte)0xa5, (byte)0x07, (byte)0x2e, (byte)0x19, (byte)0xd8, (byte)0x25, (byte)0xe4, (byte)0x21, (byte)0x75, (byte)0x6f, (byte)0x2c, (byte)0x8c, (byte)0xa5, (byte)0x9d, (byte)0x66, (byte)0x6a, (byte)0x55, (byte)0xf7, (byte)0xde, (byte)0xe9, (byte)0x28, (byte)0xd5, (byte)0x14, (byte)0xd1, (byte)0x85, (byte)0x9f, (byte)0xdc, (byte)0x7c, (byte)0x55, (byte)0x8d, (byte)0x76, (byte)0x7a, (byte)0x45, (byte)0xe7}; public Airport2InfoElement(String tag, int encryption, int length, byte[] value) { this.tag = tag; this.encryption = encryption; this.length = length; this.value = value; } public Airport2InfoElement(String tag, int encryption, String stringValue) { this.tag = tag; this.encryption = encryption; this.length = stringValue.length(); this.value = stringValue.getBytes(); if (encryption == 2) { this.value = encryptBytes(cipherBytes, this.value); } } public Airport2InfoElement() { this.tag = ""; this.encryption = 0; this.length = 0; this.value = null; } public int getSize() { int size = tag.length() + 4 + 4; if (value != null) size += value.length; return (size); } public byte[] getBytes() { // serialize all the fields ByteArrayOutputStream byteStream = new ByteArrayOutputStream(128); DataOutputStream outStream = new DataOutputStream(byteStream); try { outStream.writeBytes(tag); outStream.writeInt(encryption); outStream.writeInt(length); if (value != null) outStream.write(value); } catch(IOException e) { // IOException should never occur... } return byteStream.toByteArray(); } public String toString() { String returnText = new String(); returnText += "Name: " + this.tag + "\n"; returnText += " encryption: " + this.encryption + "\n"; returnText += " length: " + this.length + "\n"; if (this.length == 0) { returnText += " value: \n"; } else { if (this.encryption == 2) { returnText += " value (hex): " + new String(hexBytes(decryptBytes(cipherBytes, this.value))) + "\n"; returnText += " value (char): " + new String(decryptBytes(cipherBytes, this.value)) + "\n"; } else { returnText += " value (hex): " + new String(hexBytes(this.value)) + "\n"; returnText += " value (char): " + new String(this.value) + "\n"; } } returnText += "\n"; return returnText; } public static byte[] decryptBytes(byte[] cipherString, byte[] encryptedString) { byte[] returnBytes = new byte[encryptedString.length]; // just xor each byte in encryptedString with cipherString int length = encryptedString.length; if(cipherString.length < encryptedString.length) length = cipherString.length; for (int i = 0; i < length; i++) { returnBytes[i] = (byte)(encryptedString[i] ^ cipherString[i]); } return returnBytes; } public static byte[] encryptBytes(byte[] cipherString, byte[] encryptedString) { return decryptBytes(cipherString, encryptedString); } private int getIntegerValue(byte[] valueBytes) { int value = 0; for (int i = 0; i < valueBytes.length; i++) { int absValue = valueBytes[i]; if (absValue < 0) absValue += 256; value = value*256 + absValue; } return value; } private String hexByte(byte b) { int pos = b; if (pos < 0) pos += 256; String returnString = new String(); returnString += Integer.toHexString(pos/16); returnString += Integer.toHexString(pos%16); return returnString; } private String hexBytes(byte[] bytes) { String returnString = new String(); for(int i = 0; i < bytes.length; i++) { returnString += hexByte(bytes[i]) + " "; } return returnString; } }airport2config-2.0.1/airport/Airport2InfoElementVector.java0000644000175000017500000000700207503646704023350 0ustar julienjulien/* * Airport2Analyzer * * Copyright (C) 2002, Jonathan Sevy * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ import java.util.*; import java.io.*; public class Airport2InfoElementVector { private Vector infoElementVector; public Airport2InfoElementVector() { infoElementVector = new Vector(); } public Airport2InfoElementVector(byte[] retrievedBytes, int numBytes) { infoElementVector = new Vector(); ByteArrayInputStream byteStream = new ByteArrayInputStream(retrievedBytes, 0, numBytes); while (byteStream.available() > 0) { Airport2InfoElement element = new Airport2InfoElement(); // read the tag byte[] tagBytes = new byte[4]; byteStream.read(tagBytes, 0, 4); element.tag = new String(tagBytes); //read the type byte[] typeBytes = new byte[4]; byteStream.read(typeBytes, 0, 4); element.type = getIntegerValue(typeBytes); //read the length byte[] lengthBytes = new byte[4]; byteStream.read(lengthBytes, 0, 4); element.length = getIntegerValue(lengthBytes); //read the value byte[] valueBytes = new byte[element.length]; byteStream.read(valueBytes, 0, element.length); element.value = valueBytes; infoElementVector.add(element); } } public void add(Airport2InfoElement element) { infoElementVector.add(element); } public Airport2InfoElement elementAt(int i) { return (Airport2InfoElement)infoElementVector.elementAt(i); } public byte[] getBytes() { int totalSize = 0; for (int i = 0; i < infoElementVector.size(); i++) { totalSize += this.elementAt(i).getSize(); } byte[] returnBytes = new byte[totalSize]; int startPosition = 0; for (int i = 0; i < infoElementVector.size(); i++) { byte[] elementBytes = this.elementAt(i).getBytes(); if (elementBytes != null) { for (int j = 0; j < elementBytes.length; j++) returnBytes[startPosition + j] = elementBytes[j]; startPosition += elementBytes.length; } } return returnBytes; } public String toString() { String returnText = new String(); for (int i = 0; i < infoElementVector.size(); i++) { Airport2InfoElement theElement = (Airport2InfoElement)infoElementVector.elementAt(i); returnText += theElement.toString(); returnText += "\n"; } return returnText; } private int getIntegerValue(byte[] valueBytes) { int value = 0; for (int i = 0; i < valueBytes.length; i++) { int absValue = valueBytes[i]; if (absValue < 0) absValue += 256; value = value*256 + absValue; } return value; } public int size() { return infoElementVector.size(); } }airport2config-2.0.1/airport/Airport2ProtocolMessage.java0000644000175000017500000001311507636716373023077 0ustar julienjulien package airport; import java.io.*; import java.util.zip.*; public class Airport2ProtocolMessage { public String messageTag = "acpp"; public int unknownField1 = 1; public int messageChecksum = 0; public int payloadChecksum = 0; public int payloadSize; public byte[] unknownField2 = new byte[8]; public int messageType; // download = 0x14, upload = 0x15, upload raw bytes = 0x03 public int status = 0; // non-zero indicastes error public byte[] unknownField3 = new byte[12]; public byte[] password = new byte[32]; public byte[] unknownField4 = new byte[48]; public static final int READ = 0x14; public static final int WRITE = 0x15; public static final int WRITE_RAW = 0x03; public Airport2ProtocolMessage(int messageType, String password, byte[] payloadBytes, int payloadSize) { // set payload size and checksum if ((messageType == READ) || (messageType == WRITE_RAW)) { this.payloadSize = payloadSize; this.payloadChecksum = computeChecksum(payloadBytes, payloadSize); } else { this.payloadSize = -1; this.payloadChecksum = 1; } // set message type this.messageType = messageType; // set encrypted password bytes byte[] passwordBytes = password.getBytes(); int length = passwordBytes.length; if (length > 32) length = 32; for (int i = 0; i < length; i++) { this.password[i] = passwordBytes[i]; } this.password = AirportInfoRecord.encryptBytes(AirportInfoRecord.cipherBytes, this.password); // get current message bytes, and use to compute checksum (including magic number) this.messageChecksum = computeChecksum(this.getBytes(), 128); } public Airport2ProtocolMessage(byte[] headerBytes) throws ValueFormatException { // read fields from supplied header if (headerBytes.length != 128) throw new ValueFormatException("Bad header size"); DataInputStream inputStream = new DataInputStream(new ByteArrayInputStream(headerBytes)); try { byte[] tagBytes = new byte[4]; inputStream.readFully(tagBytes); messageTag = new String(tagBytes); if (!messageTag.equals("acpp")) throw new ValueFormatException("Header tag incorrect"); unknownField1 = inputStream.readInt(); messageChecksum = inputStream.readInt(); payloadChecksum = inputStream.readInt(); payloadSize = inputStream.readInt(); inputStream.read(unknownField2, 0, unknownField2.length); messageType = inputStream.readInt(); status = inputStream.readInt(); inputStream.read(unknownField3, 0, unknownField3.length); inputStream.read(password, 0, password.length); inputStream.read(unknownField4, 0, unknownField4.length); } catch (IOException e) { throw new ValueFormatException("Bad header field encountered"); } } public byte[] getBytes() { // serialize all the fields ByteArrayOutputStream byteStream = new ByteArrayOutputStream(128); DataOutputStream outStream = new DataOutputStream(byteStream); try { outStream.writeBytes(messageTag); outStream.writeInt(unknownField1); outStream.writeInt(messageChecksum); outStream.writeInt(payloadChecksum); outStream.writeInt(payloadSize); outStream.write(unknownField2); outStream.writeInt(messageType); outStream.writeInt(status); outStream.write(unknownField3); outStream.write(password); outStream.write(unknownField4); } catch(IOException e) { System.out.println("Error getting protocol message bytes"); } return byteStream.toByteArray(); } private int computeChecksum(byte[] fileBytes, int length) { Adler32 adler = new Adler32(); adler.update(fileBytes, 0, length); return (int)adler.getValue(); } private int oldComputeChecksum(byte[] fileBytes, int length) { int checksum; // multiply each byte by descending sequence for weighted checksum long weightedChecksum = 0; long ordinaryChecksum = 0; for (int i = 0; i < length; i++) { int byteValue = fileBytes[i]; if (byteValue < 0) byteValue += 256; ordinaryChecksum += byteValue; weightedChecksum += byteValue * (length - i); } //System.out.println("Checksums: ordinary = 0x" + Long.toHexString(ordinaryChecksum) + ", weighted = 0x" + Long.toHexString(weightedChecksum)); ordinaryChecksum += 1; weightedChecksum += length; // boil checksums down to 16 bits while (ordinaryChecksum > 0x0000FFFF) { long upperHalf = ordinaryChecksum >> 16; long lowerHalf = ordinaryChecksum & 0x0000FFFF; ordinaryChecksum = lowerHalf + (upperHalf * 0x0F); } while (weightedChecksum > 0x0000FFFF) { long upperHalf = weightedChecksum >> 16; long lowerHalf = weightedChecksum & 0x0000FFFF; weightedChecksum = lowerHalf + (upperHalf * 0x0F); } // combine 16-bit checksums into 32 bit checksum checksum = (int)(ordinaryChecksum | (weightedChecksum << 16)); return checksum; } public String toString() { String result = new String("Airport protocol message:\n"); result += " messageTag: " + messageTag + "\n"; result += " messageChecksum: 0x" + Integer.toHexString(messageChecksum) + "\n"; result += " payloadChecksum: 0x" + Integer.toHexString(payloadChecksum) + "\n"; result += " payloadSize: 0x" + Integer.toHexString(payloadSize) + "\n"; result += " messageType: 0x" + Integer.toHexString(messageType) + "\n"; result += " status: 0x" + Integer.toHexString(status) + "\n"; return result; } }airport2config-2.0.1/AirportBaseStation128BitConfigurator.java0000644000175000017500000010710407503646704023713 0ustar julienjulien/* * AirportBaseStationConfigurator * * Copyright (C) 2000, Jonathan Sevy * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ import java.util.*; import java.net.*; import java.awt.*; import javax.swing.*; import javax.swing.border.*; import javax.swing.plaf.*; import java.awt.event.*; import java.io.*; import byteblock.*; import snmp.*; import airport.*; public class AirportBaseStationConfigurator extends JFrame implements ActionListener { public static final String encryptionKeySizeString = "0D"; public static final int encryptionKeySize = 13; public static final String aboutString = "Airport Base Station Configurator 128-bit Encryption "; JButton discoverDevicesButton, retrieveItemButton, updateBaseStationButton; JTextField hostIDField; JTextField communityField; GridBagLayout mainLayout = new GridBagLayout(); MenuBar theMenubar; Menu fileMenu; MenuItem quitItem, openItem, saveItem, aboutItem, uploadFirmwareItem; private final int baseBlockSize = 68*16*16; private ByteBlock baseBlock = new ByteBlock(68*16, 16); private final int configurationSize = 17336; // total number of significant bytes, including checksum AirportInfo airportInfo; AirportInfoTabbedPane infoPane; JTextArea messagesArea; SNMPv1CommunicationInterface comInterface; SNMPVarBindList retrievedVars; // WindowCloseAdapter to catch window close-box closings private class WindowCloseAdapter extends WindowAdapter { public void windowClosing(WindowEvent e) { System.exit(0); } }; public AirportBaseStationConfigurator() { airportInfo = new AirportInfo(baseBlock); setUpDisplay(); retrievedVars = new SNMPVarBindList(); } private void setUpDisplay() { // set fonts to smaller-than-normal size, for compaction! UIManager manager = new UIManager(); FontUIResource appFont = new FontUIResource("SansSerif", Font.PLAIN, 10); UIDefaults defaults = manager.getLookAndFeelDefaults(); Enumeration keys = defaults.keys(); while (keys.hasMoreElements()) { String nextKey = (String)(keys.nextElement()); if ((nextKey.indexOf("font") > -1) || (nextKey.indexOf("Font") > -1)) { manager.put(nextKey, appFont); } } // add WindowCloseAdapter to catch window close-box closings // thanks to Jer for this one! addWindowListener(new WindowCloseAdapter()); this.setTitle("AirPort Base Station 128-Bit Encryption Configurator"); this.getRootPane().setBorder(new BevelBorder(BevelBorder.RAISED)); theMenubar = new MenuBar(); this.setMenuBar(theMenubar); fileMenu = new Menu("File"); openItem = new MenuItem("Open saved settings..."); openItem.setShortcut(new MenuShortcut('o')); openItem.setActionCommand("open settings"); openItem.addActionListener(this); fileMenu.add(openItem); saveItem = new MenuItem("Save settings..."); saveItem.setShortcut(new MenuShortcut('s')); saveItem.setActionCommand("save settings"); saveItem.addActionListener(this); fileMenu.add(saveItem); fileMenu.addSeparator(); uploadFirmwareItem = new MenuItem("Upload new base station firmware..."); uploadFirmwareItem.setActionCommand("upload firmware"); uploadFirmwareItem.addActionListener(this); fileMenu.add(uploadFirmwareItem); fileMenu.addSeparator(); aboutItem = new MenuItem("About..."); aboutItem.setActionCommand("about"); aboutItem.addActionListener(this); fileMenu.add(aboutItem); quitItem = new MenuItem("Quit"); quitItem.setShortcut(new MenuShortcut('q')); quitItem.setActionCommand("quit"); quitItem.addActionListener(this); fileMenu.add(quitItem); theMenubar.add(fileMenu); JLabel hostIDLabel = new JLabel("Device address:"); hostIDField = new JTextField(10); hostIDField.setText("10.0.1.1"); JLabel communityLabel = new JLabel("Community name (password):"); communityField = new JPasswordField(10); //communityField = new JTextField(10); //communityField.setText("public"); discoverDevicesButton = new JButton("Discover Devices"); discoverDevicesButton.setActionCommand("discover devices"); discoverDevicesButton.addActionListener(this); retrieveItemButton = new JButton("Retrieve Settings"); retrieveItemButton.setActionCommand("retrieve data"); retrieveItemButton.addActionListener(this); updateBaseStationButton = new JButton("Update Base Station"); updateBaseStationButton.setActionCommand("update base station"); updateBaseStationButton.addActionListener(this); updateBaseStationButton.setEnabled(false); //initially disabled until read in or open settings // set params for layout manager GridBagLayout theLayout = new GridBagLayout(); GridBagConstraints c = new GridBagConstraints(); c.gridwidth = 1; c.gridheight = 1; c.fill = GridBagConstraints.NONE; c.ipadx = 0; c.ipady = 0; Insets theMargin = new Insets(2,2,2,2); c.insets = theMargin; c.anchor = GridBagConstraints.CENTER; c.weightx = .5; c.weighty = .5; JPanel buttonPanel = new JPanel(); buttonPanel.setLayout(theLayout); c.gridx = 1; c.gridy = 1; theLayout.setConstraints(discoverDevicesButton, c); buttonPanel.add(discoverDevicesButton); c.gridx = 2; c.gridy = 1; theLayout.setConstraints(retrieveItemButton, c); buttonPanel.add(retrieveItemButton); c.gridx = 3; c.gridy = 1; theLayout.setConstraints(updateBaseStationButton, c); buttonPanel.add(updateBaseStationButton); JPanel hostPanel = new JPanel(); hostPanel.setLayout(theLayout); c.gridx = 1; c.gridy = 1; theLayout.setConstraints(hostIDLabel, c); hostPanel.add(hostIDLabel); c.gridx = 2; c.gridy = 1; theLayout.setConstraints(hostIDField, c); hostPanel.add(hostIDField); c.gridx = 3; c.gridy = 1; theLayout.setConstraints(communityLabel, c); hostPanel.add(communityLabel); c.gridx = 4; c.gridy = 1; theLayout.setConstraints(communityField, c); hostPanel.add(communityField); infoPane = new AirportInfoTabbedPane(airportInfo); JPanel messagesPanel = new JPanel(); messagesPanel.setLayout(theLayout); messagesArea = new JTextArea(4,60); JScrollPane messagesScroll = new JScrollPane(messagesArea); c.gridx = 1; c.gridy = 1; JLabel messagesLabel = new JLabel("Messages:"); theLayout.setConstraints(messagesLabel, c); messagesPanel.add(messagesLabel); c.gridx = 1; c.gridy = 2; theLayout.setConstraints(messagesScroll, c); messagesPanel.add(messagesScroll); this.getContentPane().setLayout(mainLayout); c.gridx = 1; c.gridy = 1; mainLayout.setConstraints(hostPanel, c); this.getContentPane().add(hostPanel); c.gridx = 1; c.gridy = 2; mainLayout.setConstraints(buttonPanel, c); this.getContentPane().add(buttonPanel); c.gridx = 1; c.gridy = 3; mainLayout.setConstraints(infoPane, c); this.getContentPane().add(infoPane); c.gridx = 1; c.gridy = 4; mainLayout.setConstraints(messagesPanel, c); this.getContentPane().add(messagesPanel); c.gridx = 1; c.gridy = 5; JLabel authorLabel = new JLabel(" Version 1.5.2/128 J. Sevy, November 2001 "); authorLabel.setFont(new Font("SansSerif", Font.ITALIC, 8)); mainLayout.setConstraints(authorLabel, c); this.getContentPane().add(authorLabel); } public void actionPerformed(ActionEvent theEvent) // respond to button pushes, menu selections { String command = theEvent.getActionCommand(); if (command == "quit") { System.exit(0); } if (command == "about") { AboutDialog aboutDialog = new AboutDialog(this); } if (command == "discover devices") { AirportDiscoverer discoverer = new AirportDiscoverer(); } if (command == "retrieve data") { try { if (comInterface != null) comInterface.closeConnection(); String community = communityField.getText(); InetAddress hostAddress = InetAddress.getByName(hostIDField.getText()); int version = 0; // SNMPv1 messagesArea.append("Retrieving settings from base station " + hostAddress + "......\n"); comInterface = new SNMPv1CommunicationInterface(version, hostAddress, community); for (int k = 1; k <= 68; k++) { String itemID = "1.3.6.1.4.1.762.2.2.1.1." + k; SNMPVarBindList newVars = comInterface.getMIBEntry(itemID); SNMPSequence pair = (SNMPSequence)(newVars.getSNMPObjectAt(0)); SNMPOctetString value = (SNMPOctetString)(pair.getSNMPObjectAt(1)); // get the 256 bytes byte[] bytes = (byte[])value.getValue(); // create a window to write bytes into int startIndex = (k-1)*256; int rows = 16; int cols = 16; ByteBlockRectangularWindow currentBlock = new ByteBlockRectangularWindow(startIndex, rows, cols, baseBlock); // write the bytes currentBlock.writeBytes(bytes); } // would like to check checksum to make sure retrieved block is valid, at least... // however, base station doesn't return valid checksum when data retrieved - // it's just a partial echo of the last checksum sent to it :-( messagesArea.append("Settings retrieved.\n"); // now refresh display this.refreshInfoPane(); // enable updating updateBaseStationButton.setEnabled(true); } catch(UnknownHostException e) { messagesArea.append("Error retrieving settings: unknown host.\n"); } catch(SocketException e) { messagesArea.append("Error retrieving settings: " + e + "\n"); } catch(IOException e) { messagesArea.append("Error retrieving settings: timed out waiting for response.\n"); } catch (SNMPBadValueException e) { // will never occur! messagesArea.append("Error retrieving settings: bad SNMP value received.\n"); } catch (SNMPGetException e) { messagesArea.append("Error retrieving settings: incorrect community name (password).\n"); } catch (Exception e) { messagesArea.append("Error retrieving settings: " + e.getMessage() + "\n"); } } if (command == "save settings") { try { infoPane.writeData(); setDependentData(); setStaticData(); setChecksum(baseBlock, configurationSize - 2); FileDialog fd = new FileDialog(this, "Save current settings as...", FileDialog.SAVE); fd.show(); if (fd.getFile() != null) { File newFile = new File(fd.getDirectory(), fd.getFile()); FileOutputStream fStream = new FileOutputStream(newFile); fStream.write(baseBlock.bytes, 0, configurationSize); fStream.flush(); fStream.close(); } } catch (ValueFormatException ve) { messagesArea.append("Problem with supplied value: " + ve.getMessage() + "\n"); } catch (Exception e) { messagesArea.append("Error saving settings: " + e.getMessage() + "\n"); } } if (command == "update base station") { try { infoPane.writeData(); setDependentData(); setStaticData(); setChecksum(baseBlock, configurationSize - 2); // second checksum set in transmitBlocks() // configurationSize = 17336 indicates number of bytes to burn to prom: // includes first checksum (but not second, which is "transmission" // checksum - added by transmitBlocks method) transmitBlocks(baseBlock, configurationSize); } catch (ValueFormatException ve) { messagesArea.append("Problem with supplied value: " + ve.getMessage() + "\n"); } } if (command == "open settings") { try { FileDialog fd = new FileDialog(this, "Open settings file...", FileDialog.LOAD); fd.show(); if (fd.getFile() != null) { File newFile = new File(fd.getDirectory(), fd.getFile()); FileInputStream fStream = new FileInputStream(newFile); byte[] newBytes = new byte[17408]; fStream.read(newBytes); fStream.close(); // check checksum to make sure block is valid, at least... // save current bytes in case new ones invalid byte[] currentBytes = baseBlock.bytes; baseBlock.bytes = newBytes; // make sure checksum is valid, to verify this is a valid settings file // first make sure file big enough to even check checksum! if ( (newFile.length() < configurationSize) || (!checksumValid()) ) { // reset base block to current bytes baseBlock.bytes = currentBytes; throw new Exception("invalid settings file."); } // now refresh display of data this.refreshInfoPane(); // enable updating updateBaseStationButton.setEnabled(true); } } catch (Exception e) { messagesArea.append("Error opening settings: " + e.getMessage() + "\n"); } } if (command == "upload firmware") { try { FileDialog fd = new FileDialog(this, "Select firmware file...", FileDialog.LOAD); fd.show(); if (fd.getFile() != null) { File firmwareFile = new File(fd.getDirectory(), fd.getFile()); FileInputStream fStream = new FileInputStream(firmwareFile); int fileLength = (int)firmwareFile.length(); // determine number of 256-byte blocks that need to be sent int numBlocks = (int)Math.ceil((double)fileLength/256); // create underlying ByteBlock with appropriate number of sub-blocks ByteBlock firmwareBlock = new ByteBlock(numBlocks*16, 16); fStream.read(firmwareBlock.bytes); fStream.close(); // verify this is a valid firmware file; can unfortunately only verify the embedded // configuration checksum.... AND apparently the Apple-supplied formware files computed the // checksum before the community name default passwords (4 "public" and one count of 06) // were inserted. Thus the checksum computation differs by 0xA02 for these files, // so the checksum check is a little weird.... // first make sure file big enough to even check checksum! if (fileLength < configurationSize) { throw new Exception("invalid firmware file."); } else if ( (!appleFirmwareChecksumValid(firmwareBlock)) && (!checksumValid(firmwareBlock)) ) { throw new Exception("invalid firmware file."); } // put up a dialog permitting the user to select uploading the current settings, if // they're valid... String messageString = "Upload firmware to base station " + hostIDField.getText() + "?"; String response = new String("Cancel"); // see if current settings are valid; if so, these become upload option if (updateBaseStationButton.isEnabled()) { String[] possibleValues = { "Upload firmware with current settings", "Upload firmware with default settings", "Cancel" }; int selectedValue = JOptionPane.showOptionDialog(null, messageString, "Firmware Upload", JOptionPane.YES_NO_OPTION, JOptionPane.INFORMATION_MESSAGE, null, possibleValues, possibleValues[0]); if ( !(selectedValue == JOptionPane.CLOSED_OPTION) ) response = possibleValues[selectedValue]; } else { String[] possibleValues = { "Upload firmware with default settings", "Cancel" }; int selectedValue = JOptionPane.showOptionDialog(null, messageString, "Firmware Upload", JOptionPane.YES_NO_OPTION, JOptionPane.INFORMATION_MESSAGE, null, possibleValues, possibleValues[0]); if ( !(selectedValue == JOptionPane.CLOSED_OPTION) ) response = possibleValues[selectedValue]; } // if current settings selected, upload these to base station with firmware; // if not, leave default settings alone in firmware bytes if (response.equals("Upload firmware with current settings")) { // note that current settings could throw ValueFormatException! infoPane.writeData(); setDependentData(); setStaticData(); setCommunityNames(); // so base station will know what to use after reset!! setChecksum(baseBlock, configurationSize - 2); // copy current setting bytes into firmware bytes for (int i = 0; i < configurationSize; i++) firmwareBlock.bytes[i] = baseBlock.bytes[i]; // now transmit info transmitBlocks(firmwareBlock, fileLength); } else if (response.equals("Upload firmware with default settings")) { // just transmit firmware info with default settings transmitBlocks(firmwareBlock, fileLength); } } } catch (ValueFormatException ve) { messagesArea.append("Problem with supplied value: " + ve.getMessage() + "\n"); } catch (Exception e) { messagesArea.append("Error updating firmware: " + e.getMessage() + "\n"); } } } private void refreshInfoPane() { // first, remove current infoPane this.remove(infoPane); //now create new tabbed pane to hold info infoPane = new AirportInfoTabbedPane(airportInfo); // set params for layout manager GridBagConstraints c = new GridBagConstraints(); c.gridwidth = 1; c.gridheight = 1; c.fill = GridBagConstraints.NONE; c.ipadx = 0; c.ipady = 0; Insets theMargin = new Insets(2,2,2,2); c.insets = theMargin; c.anchor = GridBagConstraints.CENTER; c.weightx = .5; c.weighty = .5; // then add pane to frame c.gridx = 1; c.gridy = 3; mainLayout.setConstraints(infoPane, c); this.getContentPane().add(infoPane); // call validate to update display this.validate(); } private void setDependentData() throws ValueFormatException { /* * Write values for DHCP/NAT-delivered base station IP address, router * IP address, mask; do here since requires "cross-reference" between data * in separate panels. */ boolean ethernetConnection = false, modemConnection = false; // flags specifying base station connection and boolean dhcpConfig = false, manualConfig = false; // configuration style boolean natEnabled = false, dhcpEnabled = false; // flags indicating address delivery services of base station boolean portMappingEnabled = false; // set flags for Ethernet/Modem mode AirportInfoRecord ethernetModemSwitch1Record = airportInfo.get("waIn"); String ethernetModemSwitch1Setting = ethernetModemSwitch1Record.toString(); AirportInfoRecord ethernetModemSwitch2Record = airportInfo.get("Configuration interface"); String ethernetModemSwitch2Setting = ethernetModemSwitch2Record.toString(); if (ethernetModemSwitch1Setting.equals("60") || ethernetModemSwitch2Setting.equals("00")) ethernetConnection = true; if (ethernetModemSwitch1Setting.equals("62") || ethernetModemSwitch2Setting.equals("03")) modemConnection = true; //set flags for base station configuration mode AirportInfoRecord baseConfigModeRecord = airportInfo.get("Base station configuration mode switch"); String baseConfigModeSetting = baseConfigModeRecord.toString(); if (baseConfigModeSetting.equals("00")) manualConfig = true; if (baseConfigModeSetting.equals("20")) dhcpConfig = true; // set flags for NAT/DHCP mode AirportInfoRecord dhcpSwitchRecord = airportInfo.get("laDS"); String dhcpSetting = dhcpSwitchRecord.toString(); if (dhcpSetting.equals("80")) dhcpEnabled = true; AirportInfoRecord natSwitchRecord = airportInfo.get("raNA"); String natSetting = natSwitchRecord.toString(); if (natSetting.equals("02")) natEnabled = true; // set flag for port mapping AirportInfoRecord portMappingSwitchRecord = airportInfo.get("Port mapping switch"); String portMappingSwitchSetting = portMappingSwitchRecord.toString(); if (portMappingSwitchSetting.equals("04")) portMappingEnabled = true; // get records for setting dependent data AirportInfoRecord natInboundPrivateIPAddressRecord = airportInfo.get("NAT inbound private IP address"); AirportInfoRecord natInboundPrivateSubnetMaskRecord = airportInfo.get("NAT inbound private subnet mask"); AirportInfoRecord natOutboundPrivateIPAddressRecord = airportInfo.get("NAT outbound private IP address"); AirportInfoRecord natOutboundPrivateSubnetMaskRecord = airportInfo.get("NAT outbound private subnet mask"); AirportInfoRecord natOutboundPublicIPAddressRecord = airportInfo.get("NAT outbound public IP address"); AirportInfoRecord natOutboundPublicSubnetMaskRecord = airportInfo.get("NAT outbound public subnet mask"); AirportInfoRecord dhcpServerRouterIPAddressRecord = airportInfo.get("DHCP server router address"); AirportInfoRecord dhcpServerSubnetMaskRecord = airportInfo.get("DHCP server subnet mask"); AirportInfoRecord baseStationIPAddressRecord = airportInfo.get("waIP"); AirportInfoRecord subnetMaskRecord = airportInfo.get("waSM"); AirportInfoRecord routerIPAddressRecord = airportInfo.get("waRA"); // when NAT enabled, set data that depends on settings from other panels if (natEnabled) { // set NAT outbound IP address and mask if (modemConnection) { natOutboundPublicIPAddressRecord.setBytesFromString("0.0.0.0"); natOutboundPublicSubnetMaskRecord.setBytesFromString("255.255.255.0"); } if (ethernetConnection) { if (manualConfig) { natOutboundPublicIPAddressRecord.setBytesFromString(baseStationIPAddressRecord.toString()); natOutboundPublicSubnetMaskRecord.setBytesFromString(subnetMaskRecord.toString()); } else if (dhcpConfig) { natOutboundPublicIPAddressRecord.setBytesFromString("0.0.0.0"); natOutboundPublicSubnetMaskRecord.setBytesFromString("255.255.255.0"); } } } // if serving DHCP, set router and subnet mask if (dhcpEnabled) { if (natEnabled) { // use private network parameters dhcpServerRouterIPAddressRecord.setBytesFromString(natInboundPrivateIPAddressRecord.toString()); dhcpServerSubnetMaskRecord.setBytesFromString(natInboundPrivateSubnetMaskRecord.toString()); } else { // use global base station parameters dhcpServerRouterIPAddressRecord.setBytesFromString(routerIPAddressRecord.toString()); dhcpServerSubnetMaskRecord.setBytesFromString(subnetMaskRecord.toString()); } } // if port mapping, and using manual Ethernet config, need to put in base station IP address // as the public IP address in the port maps if (portMappingEnabled && ethernetConnection && manualConfig) { // get count of port maps AirportInfoRecord portMappingCountRecord = airportInfo.get("Count of port mappings"); int portMapCount = Integer.parseInt(portMappingCountRecord.toString()); // get starting indices and other parameters for the byte block multi-windows // that will hold the public IP address for port mapping, which is just the // manually configured base station IP address int publicIPStartIndex = 0xD72; int publicIPBeginningNumRows = 1; int publicIPBeginningNumCols = 2; int publicIPEndingIndex = 0xD9A; int publicIPEndingNumRows = 1; int publicIPEndingNumCols = 2; int publicIPDataType = AirportInfoRecord.IP_ADDRESS; //set the public IP address for each port map for (int i = 0; i < portMapCount; i++) { // need to use a multi-window, since the first two and last two octets are separated ByteBlockMultiWindow publicIPWindow = new ByteBlockMultiWindow(); ByteBlockWindow publicIPBeginningWindow = new ByteBlockRectangularWindow(publicIPStartIndex, publicIPBeginningNumRows, publicIPBeginningNumCols, baseBlock); publicIPWindow.addWindow(publicIPBeginningWindow); ByteBlockWindow publicIPEndingWindow = new ByteBlockRectangularWindow(publicIPEndingIndex, publicIPEndingNumRows, publicIPEndingNumCols, baseBlock); publicIPWindow.addWindow(publicIPEndingWindow); AirportInfoRecord publicIPRecord = new AirportInfoRecord(publicIPDataType, publicIPWindow); publicIPRecord.setBytesFromString(baseStationIPAddressRecord.toString()); // augment addresses publicIPStartIndex += 2; publicIPEndingIndex += 2; } } } private void setStaticData() throws ValueFormatException { // set read community password field AirportInfoRecord readCommunityRecord = airportInfo.get("syPR"); readCommunityRecord.setBytesFromString("public"); /* // set miscellaneous switches that are sometimes zero in "plain vanilla" config files String miscellaneousSetting; AirportInfoRecord miscellaneousRecord1 = airportInfo.get("Miscellaneous switch 1"); miscellaneousSetting = miscellaneousRecord1.toString(); if (miscellaneousSetting.equals("00")) miscellaneousRecord1.setBytesFromString("01"); AirportInfoRecord miscellaneousRecord2 = airportInfo.get("Miscellaneous switch 2"); miscellaneousSetting = miscellaneousRecord2.toString(); if (miscellaneousSetting.equals("00")) miscellaneousRecord2.setBytesFromString("01"); */ } private void setCommunityNames() throws ValueFormatException { // Set community name into password field so base station will know what to use after reboot! // Find out if there's an entry in the main panel; if so, use this, otherwise use // current community name field AirportInfoRecord communityNameRecord = airportInfo.get("syPW"); String communityName = communityNameRecord.toString(); if (communityName.equals("")) communityName = communityField.getText(); communityNameRecord.setBytesFromString(communityName); //System.out.println("Community name: " + communityName); // set trap community password field AirportInfoRecord trapCommunityRecord = airportInfo.get("Trap community"); trapCommunityRecord.setBytesFromString("public"); // set remaining community password field (and count field) AirportInfoRecord remainingCommunityCountRecord = airportInfo.get("Remaining community count"); remainingCommunityCountRecord.setBytesFromString("06"); AirportInfoRecord remainingCommunityRecord = airportInfo.get("Remaining community"); remainingCommunityRecord.setBytesFromString("public"); } private void transmitBlocks(ByteBlock byteBlock, int numBytes) { try { String community = communityField.getText(); InetAddress hostAddress = InetAddress.getByName(hostIDField.getText()); messagesArea.append("Sending data to base station " + hostAddress + "......\n"); if (comInterface == null) { int version = 0; // SNMPv1 comInterface = new SNMPv1CommunicationInterface(version, hostAddress, community); } comInterface.requestID = 1; byte[] bytes = byteBlock.bytes; // determine number of 256-byte blocks that need to be sent int numBlocks = (int)Math.ceil((double)(numBytes + 2)/256); // +2 leaves room for transmission checksum // send all but last block for (int k = 1; k < numBlocks; k++) { String itemID = "1.3.6.1.4.1.762.2.3.1.1." + k; // create new 256 byte array byte[] newBytes = new byte[256]; // copy block of 256 bytes from given bytes to new array for (int j = 0; j < 256; j++) { newBytes[j] = bytes[256*(k-1) + j]; } // create SNMP octet string from these bytes SNMPOctetString theObject = new SNMPOctetString(newBytes); // send the bytes SNMPVarBindList newVars = comInterface.setMIBEntry(itemID, theObject); } // now send last block String itemID = "1.3.6.1.4.1.762.2.3.1.1." + numBlocks; // create new 256 byte array byte[] newBytes = new byte[256]; // copy remaining bytes from given bytes to new array int endPosition = numBytes - (numBlocks-1)*256; for (int j = 0; j < endPosition; j++) { newBytes[j] = bytes[256*(numBlocks-1) + j]; } // now set transmission checksum as 2 bytes following last (legitimate) bytes; // note that number of blocks was chosen to be (numBytes+2)/256, ensuring room ByteBlock lastBlock = new ByteBlock(16, 16, newBytes); short checksum = computeChecksum(byteBlock.bytes, numBytes); setChecksum(checksum, lastBlock, endPosition); // create SNMP octet string from these bytes SNMPOctetString theObject = new SNMPOctetString(lastBlock.bytes); // send the bytes SNMPVarBindList newVars = comInterface.setMIBEntry(itemID, theObject); // now send reset signal: indicates number of bytes to burn to prom. // also indicates location of checksum SNMPInteger numBytesWritten = new SNMPInteger(numBytes); //System.out.println("Number of bytes to burn in: " + numBytesWritten); itemID = "1.3.6.1.4.1.762.2.1.2.0"; newVars = comInterface.setMIBEntry(itemID, numBytesWritten); itemID = "1.3.6.1.4.1.762.2.1.3.0"; newVars = comInterface.setMIBEntry(itemID, numBytesWritten); messagesArea.append("Data transmitted; base station restarting.\n"); } catch(UnknownHostException e) { messagesArea.append("Error transmitting data: unknown host.\n"); } catch(SocketException e) { messagesArea.append("Error transmitting data: " + e.getMessage() + "\n"); } catch(IOException e) { messagesArea.append("Error transmitting data: timed out waiting for response.\n"); } catch (SNMPSetException e) { messagesArea.append("Error transmitting data: " + e.getMessage() + "\n"); } catch (SNMPBadValueException e) { // will never occur! messagesArea.append("Error transmitting data: bad SNMP value.\n"); } } /* * Compute the 2-byte checksum for the bytes up to (but not including) the indicated position */ private short computeChecksum(byte[] bytes, int position) { short sum = 0; for (int i = 0; i < position; i++) { sum += bytes[i]; if(bytes[i] < 0) sum += 256; } return sum; } private void setChecksum(short sum, ByteBlock byteBlock, int position) { String checksumString = littleEndianHexString(sum); // create info record to write into int numRows = 1; int numCols = 2; int baseStartIndex = position; ByteBlockWindow checksumWindow = new ByteBlockRectangularWindow(baseStartIndex, numRows, numCols, byteBlock); int dataType = AirportInfoRecord.BYTE_STRING; AirportInfoRecord checksumRecord = new AirportInfoRecord(dataType, checksumWindow); checksumRecord.byteBlockWindow.clearBytes(); // write in new checksum try { checksumRecord.setBytesFromString(checksumString); } catch (ValueFormatException ve) { // won't occur! messagesArea.append("Problem writing checksum with value " + checksumString + ".\n"); } } /* * Convenience method for writing checksum value into same block it's computed from. This * is the usual case for config files; however, the more general routine is used to set * the transmission checksum immediately following the transmitted data bytes. */ private void setChecksum(ByteBlock byteBlock, int position) { short sum = computeChecksum(byteBlock.bytes, position); setChecksum(sum, byteBlock, position); } /** * Return little-endian hex string */ private String littleEndianHexString(short value) { int intValue = value; intValue = intValue & 0xFFFF; int switched = ((intValue << 8) | (intValue >>> 8)) & 0xFFFF; String returnString = Integer.toHexString(switched); // add leading zeros if needed while (returnString.length() < 4) returnString = "0" + returnString; return returnString; } /** * Used to validate checksum in stored settings, to ensure file is legitimate! Verify just * first checksum, for compatibility with Apple configurator's stored settings. */ private boolean checksumValid(ByteBlock byteBlock) { short sum = computeChecksum(byteBlock.bytes, configurationSize - 2); String computedChecksumString = littleEndianHexString(sum); //System.out.println("Computed checksum: " + computedChecksumString); // get configuration checksum from block int baseStartIndex = 0x43B6; int numRows = 1; int numCols = 2; int dataType = AirportInfoRecord.BYTE_STRING; AirportInfoRecord checksumRecord = new AirportInfoRecord(baseStartIndex, numRows, numCols, dataType, byteBlock); String existingChecksumString = checksumRecord.toString(); //System.out.println("Existing checksum: " + existingChecksumString); if (computedChecksumString.equals(existingChecksumString)) return true; else return false; } private boolean checksumValid() { return checksumValid(baseBlock); } // Apparently the Apple-supplied firmware files computed the // checksum before the community name default passwords (4 "public" and one count of 06) // were inserted. Thus the checksum computation should differ by 0xA02 for these files. // Thus the need for this "hacked" checksum validation.... private boolean appleFirmwareChecksumValid(ByteBlock byteBlock) { short sum = computeChecksum(byteBlock.bytes, configurationSize - 2); sum -= 0xA02; String computedChecksumString = littleEndianHexString(sum); //System.out.println("Computed checksum: " + computedChecksumString); // get configuration checksum from block int baseStartIndex = 0x43B6; int numRows = 1; int numCols = 2; int dataType = AirportInfoRecord.BYTE_STRING; AirportInfoRecord checksumRecord = new AirportInfoRecord(baseStartIndex, numRows, numCols, dataType, byteBlock); String existingChecksumString = checksumRecord.toString(); //System.out.println("Existing checksum: " + existingChecksumString); if (computedChecksumString.equals(existingChecksumString)) return true; else return false; } public static void main(String args[]) { try { AirportBaseStationConfigurator theApp = new AirportBaseStationConfigurator(); theApp.pack(); // tweak app size to make it a little larger than necessary, to address the // "shrunken textfields" problem arising from the layout manager packing stuff // a little too tightly. Dimension dim = theApp.getSize(); dim.height += 20; dim.width += 20; theApp.setSize(dim); theApp.show(); } catch (Exception e) {} } }airport2config-2.0.1/AirportBaseStationConfiguratorMicro.java0000644000175000017500000010722307503646704024015 0ustar julienjulien/* * AirportBaseStationConfigurator * * Copyright (C) 2000, Jonathan Sevy * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ import java.util.*; import java.net.*; import java.awt.*; import javax.swing.*; import javax.swing.border.*; import javax.swing.plaf.*; import java.awt.event.*; import java.io.*; import byteblock.*; import snmp.*; import airport.*; public class AirportBaseStationConfigurator extends JFrame implements ActionListener { public static final String encryptionKeySizeString = "05"; public static final int encryptionKeySize = 5; public static final String aboutString = "Airport Base Station Configurator Micro Edition "; JButton discoverDevicesButton, retrieveItemButton, updateBaseStationButton; JTextField hostIDField; JTextField communityField; GridBagLayout mainLayout = new GridBagLayout(); MenuBar theMenubar; Menu fileMenu; MenuItem quitItem, openItem, saveItem, aboutItem, uploadFirmwareItem; private final int baseBlockSize = 68*16*16; private ByteBlock baseBlock = new ByteBlock(68*16, 16); private final int configurationSize = 17336; // total number of significant bytes, including checksum AirportInfo airportInfo; AirportInfoTabbedPane infoPane; JTextArea messagesArea; SNMPv1CommunicationInterface comInterface; SNMPVarBindList retrievedVars; // WindowCloseAdapter to catch window close-box closings private class WindowCloseAdapter extends WindowAdapter { public void windowClosing(WindowEvent e) { System.exit(0); } }; public AirportBaseStationConfigurator() { airportInfo = new AirportInfo(baseBlock); setUpDisplay(); retrievedVars = new SNMPVarBindList(); } private void setUpDisplay() { // set fonts to smaller-than-normal size, for compaction! UIManager manager = new UIManager(); FontUIResource appFont = new FontUIResource("SansSerif", Font.PLAIN, 10); UIDefaults defaults = manager.getLookAndFeelDefaults(); Enumeration keys = defaults.keys(); while (keys.hasMoreElements()) { String nextKey = (String)(keys.nextElement()); if ((nextKey.indexOf("font") > -1) || (nextKey.indexOf("Font") > -1)) { manager.put(nextKey, appFont); } } // add WindowCloseAdapter to catch window close-box closings // thanks to Jer for this one! addWindowListener(new WindowCloseAdapter()); this.setTitle("AirPort Base Station Configurator"); this.getRootPane().setBorder(new BevelBorder(BevelBorder.RAISED)); theMenubar = new MenuBar(); this.setMenuBar(theMenubar); fileMenu = new Menu("File"); openItem = new MenuItem("Open saved settings..."); openItem.setShortcut(new MenuShortcut('o')); openItem.setActionCommand("open settings"); openItem.addActionListener(this); fileMenu.add(openItem); saveItem = new MenuItem("Save settings..."); saveItem.setShortcut(new MenuShortcut('s')); saveItem.setActionCommand("save settings"); saveItem.addActionListener(this); fileMenu.add(saveItem); fileMenu.addSeparator(); uploadFirmwareItem = new MenuItem("Upload new base station firmware..."); uploadFirmwareItem.setActionCommand("upload firmware"); uploadFirmwareItem.addActionListener(this); fileMenu.add(uploadFirmwareItem); fileMenu.addSeparator(); aboutItem = new MenuItem("About..."); aboutItem.setActionCommand("about"); aboutItem.addActionListener(this); fileMenu.add(aboutItem); fileMenu.addSeparator(); quitItem = new MenuItem("Quit"); quitItem.setShortcut(new MenuShortcut('q')); quitItem.setActionCommand("quit"); quitItem.addActionListener(this); fileMenu.add(quitItem); theMenubar.add(fileMenu); JLabel hostIDLabel = new JLabel("Device address:"); hostIDField = new JTextField(10); hostIDField.setText("10.0.1.1"); JLabel communityLabel = new JLabel("Community name (password):"); communityField = new JPasswordField(10); //communityField = new JTextField(10); //communityField.setText("public"); discoverDevicesButton = new JButton("Discover Devices"); discoverDevicesButton.setActionCommand("discover devices"); discoverDevicesButton.addActionListener(this); retrieveItemButton = new JButton("Retrieve Settings"); retrieveItemButton.setActionCommand("retrieve data"); retrieveItemButton.addActionListener(this); updateBaseStationButton = new JButton("Update Base Station"); updateBaseStationButton.setActionCommand("update base station"); updateBaseStationButton.addActionListener(this); updateBaseStationButton.setEnabled(false); //initially disabled until read in or open settings // set params for layout manager GridBagLayout theLayout = new GridBagLayout(); GridBagConstraints c = new GridBagConstraints(); c.gridwidth = 1; c.gridheight = 1; c.fill = GridBagConstraints.NONE; c.ipadx = 0; c.ipady = 0; Insets theMargin = new Insets(2,2,2,2); c.insets = theMargin; c.anchor = GridBagConstraints.CENTER; c.weightx = .5; c.weighty = .5; JPanel buttonPanel = new JPanel(); buttonPanel.setLayout(theLayout); c.gridx = 1; c.gridy = 1; theLayout.setConstraints(discoverDevicesButton, c); buttonPanel.add(discoverDevicesButton); c.gridx = 2; c.gridy = 1; theLayout.setConstraints(retrieveItemButton, c); buttonPanel.add(retrieveItemButton); c.gridx = 3; c.gridy = 1; theLayout.setConstraints(updateBaseStationButton, c); buttonPanel.add(updateBaseStationButton); JPanel hostPanel = new JPanel(); hostPanel.setLayout(theLayout); c.gridx = 1; c.gridy = 1; theLayout.setConstraints(hostIDLabel, c); hostPanel.add(hostIDLabel); c.gridx = 2; c.gridy = 1; theLayout.setConstraints(hostIDField, c); hostPanel.add(hostIDField); c.gridx = 3; c.gridy = 1; theLayout.setConstraints(communityLabel, c); hostPanel.add(communityLabel); c.gridx = 4; c.gridy = 1; theLayout.setConstraints(communityField, c); hostPanel.add(communityField); infoPane = new AirportInfoTabbedPane(airportInfo); JPanel messagesPanel = new JPanel(); messagesPanel.setLayout(theLayout); messagesArea = new JTextArea(2,60); JScrollPane messagesScroll = new JScrollPane(messagesArea); messagesScroll.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); /* c.gridx = 1; c.gridy = 1; JLabel messagesLabel = new JLabel("Messages:"); theLayout.setConstraints(messagesLabel, c); messagesPanel.add(messagesLabel); c.gridx = 1; c.gridy = 2; theLayout.setConstraints(messagesScroll, c); messagesPanel.add(messagesScroll); */ this.getContentPane().setLayout(mainLayout); c.gridx = 1; c.gridy = 1; mainLayout.setConstraints(hostPanel, c); this.getContentPane().add(hostPanel); c.gridx = 1; c.gridy = 2; mainLayout.setConstraints(buttonPanel, c); this.getContentPane().add(buttonPanel); c.gridx = 1; c.gridy = 3; mainLayout.setConstraints(infoPane, c); this.getContentPane().add(infoPane); c.gridx = 1; c.gridy = 4; mainLayout.setConstraints(messagesScroll, c); this.getContentPane().add(messagesScroll); } public void actionPerformed(ActionEvent theEvent) // respond to button pushes, menu selections { String command = theEvent.getActionCommand(); if (command.equals("quit")) { System.exit(0); } if (command == "about") { AboutDialog aboutDialog = new AboutDialog(this); } if (command.equals("discover devices")) { AirportDiscoverer discoverer = new AirportDiscoverer(); } if (command.equals("retrieve data")) { try { if (comInterface != null) comInterface.closeConnection(); String community = communityField.getText(); InetAddress hostAddress = InetAddress.getByName(hostIDField.getText()); int version = 0; // SNMPv1 messagesArea.append("Retrieving settings from base station " + hostAddress + "......\n"); comInterface = new SNMPv1CommunicationInterface(version, hostAddress, community); for (int k = 1; k <= 68; k++) { String itemID = "1.3.6.1.4.1.762.2.2.1.1." + k; SNMPVarBindList newVars = comInterface.getMIBEntry(itemID); SNMPSequence pair = (SNMPSequence)(newVars.getSNMPObjectAt(0)); SNMPOctetString value = (SNMPOctetString)(pair.getSNMPObjectAt(1)); // get the 256 bytes byte[] bytes = (byte[])value.getValue(); // create a window to write bytes into int startIndex = (k-1)*256; int rows = 16; int cols = 16; ByteBlockRectangularWindow currentBlock = new ByteBlockRectangularWindow(startIndex, rows, cols, baseBlock); // write the bytes currentBlock.writeBytes(bytes); } // would like to check checksum to make sure retrieved block is valid, at least... // however, base station doesn't return valid checksum when data retrieved - // it's just a partial echo of the last checksum sent to it :-( messagesArea.append("Settings retrieved.\n"); // now refresh display this.refreshInfoPane(); // enable updating updateBaseStationButton.setEnabled(true); } catch(UnknownHostException e) { messagesArea.append("Error retrieving settings: unknown host.\n"); } catch(SocketException e) { messagesArea.append("Error retrieving settings: " + e + "\n"); } catch(IOException e) { messagesArea.append("Error retrieving settings: timed out waiting for response.\n"); } catch (SNMPBadValueException e) { // will never occur! messagesArea.append("Error retrieving settings: bad SNMP value received.\n"); } catch (SNMPGetException e) { messagesArea.append("Error retrieving settings: incorrect community name (password).\n"); } catch (Exception e) { messagesArea.append("Error retrieving settings: " + e.getMessage() + "\n"); } } if (command.equals("save settings")) { try { infoPane.writeData(); setDependentData(); setStaticData(); setChecksum(baseBlock, configurationSize - 2); FileDialog fd = new FileDialog(this, "Save current settings as...", FileDialog.SAVE); fd.show(); if (fd.getFile() != null) { File newFile = new File(fd.getDirectory(), fd.getFile()); FileOutputStream fStream = new FileOutputStream(newFile); fStream.write(baseBlock.bytes, 0, configurationSize); fStream.flush(); fStream.close(); } } catch (ValueFormatException ve) { messagesArea.append("Problem with supplied value: " + ve.getMessage() + "\n"); } catch (Exception e) { messagesArea.append("Error saving settings: " + e.getMessage() + "\n"); } } if (command.equals("update base station")) { try { infoPane.writeData(); setDependentData(); setStaticData(); setChecksum(baseBlock, configurationSize - 2); // second checksum set in transmitBlocks() // configurationSize = 17336 indicates number of bytes to burn to prom: // includes first checksum (but not second, which is "transmission" // checksum - added by transmitBlocks method) transmitBlocks(baseBlock, configurationSize); } catch (ValueFormatException ve) { messagesArea.append("Problem with supplied value: " + ve.getMessage() + "\n"); } } if (command.equals("open settings")) { try { FileDialog fd = new FileDialog(this, "Open settings file...", FileDialog.LOAD); fd.show(); if (fd.getFile() != null) { File newFile = new File(fd.getDirectory(), fd.getFile()); FileInputStream fStream = new FileInputStream(newFile); byte[] newBytes = new byte[17408]; fStream.read(newBytes); fStream.close(); // check checksum to make sure block is valid, at least... // save current bytes in case new ones invalid byte[] currentBytes = baseBlock.bytes; baseBlock.bytes = newBytes; // see if shift key held down while open selected; if so, don't check checksum boolean shiftKeyDown = ((theEvent.getModifiers() & ActionEvent.SHIFT_MASK) > 0); // make sure checksum is valid, to verify this is a valid settings file // first make sure file big enough to even check checksum! if ( (newFile.length() < configurationSize) || (!shiftKeyDown && !checksumValid()) ) { // reset base block to current bytes baseBlock.bytes = currentBytes; throw new Exception("invalid settings file."); } // now refresh display of data this.refreshInfoPane(); // enable updating updateBaseStationButton.setEnabled(true); } } catch (Exception e) { messagesArea.append("Error opening settings: " + e.getMessage() + "\n"); } } if (command.equals("upload firmware")) { try { FileDialog fd = new FileDialog(this, "Select firmware file...", FileDialog.LOAD); fd.show(); if (fd.getFile() != null) { File firmwareFile = new File(fd.getDirectory(), fd.getFile()); FileInputStream fStream = new FileInputStream(firmwareFile); int fileLength = (int)firmwareFile.length(); // determine number of 256-byte blocks that need to be sent int numBlocks = (int)Math.ceil((double)fileLength/256); // create underlying ByteBlock with appropriate number of sub-blocks ByteBlock firmwareBlock = new ByteBlock(numBlocks*16, 16); fStream.read(firmwareBlock.bytes); fStream.close(); // verify this is a valid firmware file; can unfortunately only verify the embedded // configuration checksum.... AND apparently the Apple-supplied formware files computed the // checksum before the community name default passwords (4 "public" and one count of 06) // were inserted. Thus the checksum computation differs by 0xA02 for these files, // so the checksum check is a little weird.... // first make sure file big enough to even check checksum! if (fileLength < configurationSize) { throw new Exception("invalid firmware file."); } else if ( (!appleFirmwareChecksumValid(firmwareBlock)) && (!checksumValid(firmwareBlock)) ) { throw new Exception("invalid firmware file."); } // put up a dialog permitting the user to select uploading the current settings, if // they're valid... String messageString = "Upload firmware to base station " + hostIDField.getText() + "?"; String response = new String("Cancel"); // see if current settings are valid; if so, these become upload option if (updateBaseStationButton.isEnabled()) { String[] possibleValues = { "Upload firmware with current settings", "Upload firmware with default settings", "Cancel" }; int selectedValue = JOptionPane.showOptionDialog(null, messageString, "Firmware Upload", JOptionPane.YES_NO_OPTION, JOptionPane.INFORMATION_MESSAGE, null, possibleValues, possibleValues[0]); if ( !(selectedValue == JOptionPane.CLOSED_OPTION) ) response = possibleValues[selectedValue]; } else { String[] possibleValues = { "Upload firmware with default settings", "Cancel" }; int selectedValue = JOptionPane.showOptionDialog(null, messageString, "Firmware Upload", JOptionPane.YES_NO_OPTION, JOptionPane.INFORMATION_MESSAGE, null, possibleValues, possibleValues[0]); if ( !(selectedValue == JOptionPane.CLOSED_OPTION) ) response = possibleValues[selectedValue]; } // if current settings selected, upload these to base station with firmware; // if not, leave default settings alone in firmware bytes if (response.equals("Upload firmware with current settings")) { // note that current settings could throw ValueFormatException! infoPane.writeData(); setDependentData(); setStaticData(); setCommunityNames(); // so base station will know what to use after reset!! setChecksum(baseBlock, configurationSize - 2); // copy current setting bytes into firmware bytes for (int i = 0; i < configurationSize; i++) firmwareBlock.bytes[i] = baseBlock.bytes[i]; // now transmit info transmitBlocks(firmwareBlock, fileLength); } else if (response.equals("Upload firmware with default settings")) { // just transmit firmware info with default settings transmitBlocks(firmwareBlock, fileLength); } } } catch (ValueFormatException ve) { messagesArea.append("Problem with supplied value: " + ve.getMessage() + "\n"); } catch (Exception e) { messagesArea.append("Error updating firmware: " + e.getMessage() + "\n"); } } } private void refreshInfoPane() { // first, remove current infoPane this.remove(infoPane); //now create new tabbed pane to hold info infoPane = new AirportInfoTabbedPane(airportInfo); // set params for layout manager GridBagConstraints c = new GridBagConstraints(); c.gridwidth = 1; c.gridheight = 1; c.fill = GridBagConstraints.NONE; c.ipadx = 0; c.ipady = 0; Insets theMargin = new Insets(2,2,2,2); c.insets = theMargin; c.anchor = GridBagConstraints.CENTER; c.weightx = .5; c.weighty = .5; // then add pane to frame c.gridx = 1; c.gridy = 3; mainLayout.setConstraints(infoPane, c); this.getContentPane().add(infoPane); // call validate to update display this.validate(); } private void setDependentData() throws ValueFormatException { /* * Write values for DHCP/NAT-delivered base station IP address, router * IP address, mask; do here since requires "cross-reference" between data * in separate panels. */ boolean ethernetConnection = false, modemConnection = false; // flags specifying base station connection and boolean dhcpConfig = false, manualConfig = false; // configuration style boolean natEnabled = false, dhcpEnabled = false; // flags indicating address delivery services of base station boolean portMappingEnabled = false; // set flags for Ethernet/Modem mode AirportInfoRecord ethernetModemSwitch1Record = airportInfo.get("waIn"); String ethernetModemSwitch1Setting = ethernetModemSwitch1Record.toString(); AirportInfoRecord ethernetModemSwitch2Record = airportInfo.get("Configuration interface"); String ethernetModemSwitch2Setting = ethernetModemSwitch2Record.toString(); if (ethernetModemSwitch1Setting.equals("60") || ethernetModemSwitch2Setting.equals("00")) ethernetConnection = true; if (ethernetModemSwitch1Setting.equals("62") || ethernetModemSwitch2Setting.equals("03")) modemConnection = true; //set flags for base station configuration mode AirportInfoRecord baseConfigModeRecord = airportInfo.get("Base station configuration mode switch"); String baseConfigModeSetting = baseConfigModeRecord.toString(); if (baseConfigModeSetting.equals("00")) manualConfig = true; if (baseConfigModeSetting.equals("20")) dhcpConfig = true; // set flags for NAT/DHCP mode AirportInfoRecord dhcpSwitchRecord = airportInfo.get("laDS"); String dhcpSetting = dhcpSwitchRecord.toString(); if (dhcpSetting.equals("80")) dhcpEnabled = true; AirportInfoRecord natSwitchRecord = airportInfo.get("raNA"); String natSetting = natSwitchRecord.toString(); if (natSetting.equals("02")) natEnabled = true; // set flag for port mapping AirportInfoRecord portMappingSwitchRecord = airportInfo.get("Port mapping switch"); String portMappingSwitchSetting = portMappingSwitchRecord.toString(); if (portMappingSwitchSetting.equals("04")) portMappingEnabled = true; // get records for setting dependent data AirportInfoRecord natInboundPrivateIPAddressRecord = airportInfo.get("NAT inbound private IP address"); AirportInfoRecord natInboundPrivateSubnetMaskRecord = airportInfo.get("NAT inbound private subnet mask"); AirportInfoRecord natOutboundPrivateIPAddressRecord = airportInfo.get("NAT outbound private IP address"); AirportInfoRecord natOutboundPrivateSubnetMaskRecord = airportInfo.get("NAT outbound private subnet mask"); AirportInfoRecord natOutboundPublicIPAddressRecord = airportInfo.get("NAT outbound public IP address"); AirportInfoRecord natOutboundPublicSubnetMaskRecord = airportInfo.get("NAT outbound public subnet mask"); AirportInfoRecord dhcpServerRouterIPAddressRecord = airportInfo.get("DHCP server router address"); AirportInfoRecord dhcpServerSubnetMaskRecord = airportInfo.get("DHCP server subnet mask"); AirportInfoRecord baseStationIPAddressRecord = airportInfo.get("waIP"); AirportInfoRecord subnetMaskRecord = airportInfo.get("waSM"); AirportInfoRecord routerIPAddressRecord = airportInfo.get("waRA"); // when NAT enabled, set data that depends on settings from other panels if (natEnabled) { // set NAT outbound IP address and mask if (modemConnection) { natOutboundPublicIPAddressRecord.setBytesFromString("0.0.0.0"); natOutboundPublicSubnetMaskRecord.setBytesFromString("255.255.255.0"); } if (ethernetConnection) { if (manualConfig) { natOutboundPublicIPAddressRecord.setBytesFromString(baseStationIPAddressRecord.toString()); natOutboundPublicSubnetMaskRecord.setBytesFromString(subnetMaskRecord.toString()); } else if (dhcpConfig) { natOutboundPublicIPAddressRecord.setBytesFromString("0.0.0.0"); natOutboundPublicSubnetMaskRecord.setBytesFromString("255.255.255.0"); } } } // if serving DHCP, set router and subnet mask if (dhcpEnabled) { if (natEnabled) { // use private network parameters dhcpServerRouterIPAddressRecord.setBytesFromString(natInboundPrivateIPAddressRecord.toString()); dhcpServerSubnetMaskRecord.setBytesFromString(natInboundPrivateSubnetMaskRecord.toString()); } else { // use global base station parameters dhcpServerRouterIPAddressRecord.setBytesFromString(routerIPAddressRecord.toString()); dhcpServerSubnetMaskRecord.setBytesFromString(subnetMaskRecord.toString()); } } // if port mapping, and using manual Ethernet config, need to put in base station IP address // as the public IP address in the port maps if (portMappingEnabled && ethernetConnection && manualConfig) { // get count of port maps AirportInfoRecord portMappingCountRecord = airportInfo.get("Count of port mappings"); int portMapCount = Integer.parseInt(portMappingCountRecord.toString()); // get starting indices and other parameters for the byte block multi-windows // that will hold the public IP address for port mapping, which is just the // manually configured base station IP address int publicIPStartIndex = 0xD72; int publicIPBeginningNumRows = 1; int publicIPBeginningNumCols = 2; int publicIPEndingIndex = 0xD9A; int publicIPEndingNumRows = 1; int publicIPEndingNumCols = 2; int publicIPDataType = AirportInfoRecord.IP_ADDRESS; //set the public IP address for each port map for (int i = 0; i < portMapCount; i++) { // need to use a multi-window, since the first two and last two octets are separated ByteBlockMultiWindow publicIPWindow = new ByteBlockMultiWindow(); ByteBlockWindow publicIPBeginningWindow = new ByteBlockRectangularWindow(publicIPStartIndex, publicIPBeginningNumRows, publicIPBeginningNumCols, baseBlock); publicIPWindow.addWindow(publicIPBeginningWindow); ByteBlockWindow publicIPEndingWindow = new ByteBlockRectangularWindow(publicIPEndingIndex, publicIPEndingNumRows, publicIPEndingNumCols, baseBlock); publicIPWindow.addWindow(publicIPEndingWindow); AirportInfoRecord publicIPRecord = new AirportInfoRecord(publicIPDataType, publicIPWindow); publicIPRecord.setBytesFromString(baseStationIPAddressRecord.toString()); // augment addresses publicIPStartIndex += 2; publicIPEndingIndex += 2; } } } private void setStaticData() throws ValueFormatException { // set read community password field AirportInfoRecord readCommunityRecord = airportInfo.get("syPR"); readCommunityRecord.setBytesFromString("public"); /* // set miscellaneous switches that are sometimes zero in "plain vanilla" config files String miscellaneousSetting; AirportInfoRecord miscellaneousRecord1 = airportInfo.get("Miscellaneous switch 1"); miscellaneousSetting = miscellaneousRecord1.toString(); if (miscellaneousSetting.equals("00")) miscellaneousRecord1.setBytesFromString("01"); AirportInfoRecord miscellaneousRecord2 = airportInfo.get("Miscellaneous switch 2"); miscellaneousSetting = miscellaneousRecord2.toString(); if (miscellaneousSetting.equals("00")) miscellaneousRecord2.setBytesFromString("01"); */ } private void setCommunityNames() throws ValueFormatException { // Set community name into password field so base station will know what to use after reboot! // Find out if there's an entry in the main panel; if so, use this, otherwise use // current community name field AirportInfoRecord communityNameRecord = airportInfo.get("syPW"); String communityName = communityNameRecord.toString(); if (communityName.equals("")) communityName = communityField.getText(); communityNameRecord.setBytesFromString(communityName); //System.out.println("Community name: " + communityName); // set trap community password field AirportInfoRecord trapCommunityRecord = airportInfo.get("Trap community"); trapCommunityRecord.setBytesFromString("public"); // set remaining community password field (and count field) AirportInfoRecord remainingCommunityCountRecord = airportInfo.get("Remaining community count"); remainingCommunityCountRecord.setBytesFromString("06"); AirportInfoRecord remainingCommunityRecord = airportInfo.get("Remaining community"); remainingCommunityRecord.setBytesFromString("public"); } private void transmitBlocks(ByteBlock byteBlock, int numBytes) { try { String community = communityField.getText(); InetAddress hostAddress = InetAddress.getByName(hostIDField.getText()); messagesArea.append("Sending data to base station " + hostAddress + "......\n"); if (comInterface == null) { int version = 0; // SNMPv1 comInterface = new SNMPv1CommunicationInterface(version, hostAddress, community); } comInterface.requestID = 1; byte[] bytes = byteBlock.bytes; // determine number of 256-byte blocks that need to be sent int numBlocks = (int)Math.ceil((double)(numBytes + 2)/256); // +2 leaves room for transmission checksum // send all but last block for (int k = 1; k < numBlocks; k++) { String itemID = "1.3.6.1.4.1.762.2.3.1.1." + k; // create new 256 byte array byte[] newBytes = new byte[256]; // copy block of 256 bytes from given bytes to new array for (int j = 0; j < 256; j++) { newBytes[j] = bytes[256*(k-1) + j]; } // create SNMP octet string from these bytes SNMPOctetString theObject = new SNMPOctetString(newBytes); // send the bytes SNMPVarBindList newVars = comInterface.setMIBEntry(itemID, theObject); } // now send last block String itemID = "1.3.6.1.4.1.762.2.3.1.1." + numBlocks; // create new 256 byte array byte[] newBytes = new byte[256]; // copy remaining bytes from given bytes to new array int endPosition = numBytes - (numBlocks-1)*256; for (int j = 0; j < endPosition; j++) { newBytes[j] = bytes[256*(numBlocks-1) + j]; } // now set transmission checksum as 2 bytes following last (legitimate) bytes; // note that number of blocks was chosen to be (numBytes+2)/256, ensuring room ByteBlock lastBlock = new ByteBlock(16, 16, newBytes); short checksum = computeChecksum(byteBlock.bytes, numBytes); setChecksum(checksum, lastBlock, endPosition); // create SNMP octet string from these bytes SNMPOctetString theObject = new SNMPOctetString(lastBlock.bytes); // send the bytes SNMPVarBindList newVars = comInterface.setMIBEntry(itemID, theObject); // now send reset signal: indicates number of bytes to burn to prom. // also indicates location of checksum SNMPInteger numBytesWritten = new SNMPInteger(numBytes); //System.out.println("Number of bytes to burn in: " + numBytesWritten); itemID = "1.3.6.1.4.1.762.2.1.2.0"; newVars = comInterface.setMIBEntry(itemID, numBytesWritten); itemID = "1.3.6.1.4.1.762.2.1.3.0"; newVars = comInterface.setMIBEntry(itemID, numBytesWritten); messagesArea.append("Data transmitted; base station restarting.\n"); } catch(UnknownHostException e) { messagesArea.append("Error transmitting data: unknown host.\n"); } catch(SocketException e) { messagesArea.append("Error transmitting data: " + e.getMessage() + "\n"); } catch(IOException e) { messagesArea.append("Error transmitting data: timed out waiting for response.\n"); } catch (SNMPSetException e) { messagesArea.append("Error transmitting data: " + e.getMessage() + "\n"); } catch (SNMPBadValueException e) { // will never occur! messagesArea.append("Error transmitting data: bad SNMP value.\n"); } } /* * Compute the 2-byte checksum for the bytes up to (but not including) the indicated position */ private short computeChecksum(byte[] bytes, int position) { short sum = 0; for (int i = 0; i < position; i++) { sum += bytes[i]; if(bytes[i] < 0) sum += 256; } return sum; } private void setChecksum(short sum, ByteBlock byteBlock, int position) { String checksumString = littleEndianHexString(sum); // create info record to write into int numRows = 1; int numCols = 2; int baseStartIndex = position; ByteBlockWindow checksumWindow = new ByteBlockRectangularWindow(baseStartIndex, numRows, numCols, byteBlock); int dataType = AirportInfoRecord.BYTE_STRING; AirportInfoRecord checksumRecord = new AirportInfoRecord(dataType, checksumWindow); checksumRecord.byteBlockWindow.clearBytes(); // write in new checksum try { checksumRecord.setBytesFromString(checksumString); } catch (ValueFormatException ve) { // won't occur! messagesArea.append("Problem writing checksum with value " + checksumString + ".\n"); } } /* * Convenience method for writing checksum value into same block it's computed from. This * is the usual case for config files; however, the more general routine is used to set * the transmission checksum immediately following the transmitted data bytes. */ private void setChecksum(ByteBlock byteBlock, int position) { short sum = computeChecksum(byteBlock.bytes, position); setChecksum(sum, byteBlock, position); } /** * Return little-endian hex string */ private String littleEndianHexString(short value) { int intValue = value; intValue = intValue & 0xFFFF; int switched = ((intValue << 8) | (intValue >>> 8)) & 0xFFFF; String returnString = Integer.toHexString(switched); // add leading zeros if needed while (returnString.length() < 4) returnString = "0" + returnString; return returnString; } /** * Used to validate checksum in stored settings, to ensure file is legitimate! Verify just * first checksum, for compatibility with Apple configurator's stored settings. */ private boolean checksumValid(ByteBlock byteBlock) { short sum = computeChecksum(byteBlock.bytes, configurationSize - 2); String computedChecksumString = littleEndianHexString(sum); //System.out.println("Computed checksum: " + computedChecksumString); // get configuration checksum from block int baseStartIndex = 0x43B6; int numRows = 1; int numCols = 2; int dataType = AirportInfoRecord.BYTE_STRING; AirportInfoRecord checksumRecord = new AirportInfoRecord(baseStartIndex, numRows, numCols, dataType, byteBlock); String existingChecksumString = checksumRecord.toString(); //System.out.println("Existing checksum: " + existingChecksumString); if (computedChecksumString.equals(existingChecksumString)) return true; else return false; } private boolean checksumValid() { return checksumValid(baseBlock); } // Apparently the Apple-supplied firmware files computed the // checksum before the community name default passwords (4 "public" and one count of 06) // were inserted. Thus the checksum computation should differ by 0xA02 for these files. // Thus the need for this "hacked" checksum validation.... private boolean appleFirmwareChecksumValid(ByteBlock byteBlock) { short sum = computeChecksum(byteBlock.bytes, configurationSize - 2); sum -= 0xA02; String computedChecksumString = littleEndianHexString(sum); //System.out.println("Computed checksum: " + computedChecksumString); // get configuration checksum from block int baseStartIndex = 0x43B6; int numRows = 1; int numCols = 2; int dataType = AirportInfoRecord.BYTE_STRING; AirportInfoRecord checksumRecord = new AirportInfoRecord(baseStartIndex, numRows, numCols, dataType, byteBlock); String existingChecksumString = checksumRecord.toString(); //System.out.println("Existing checksum: " + existingChecksumString); if (computedChecksumString.equals(existingChecksumString)) return true; else return false; } public static void main(String args[]) { try { AirportBaseStationConfigurator theApp = new AirportBaseStationConfigurator(); theApp.pack(); // tweak app size to make it a little larger than necessary, to address the // "shrunken textfields" problem arising from the layout manager packing stuff // a little too tightly. Dimension dim = theApp.getSize(); //dim.height += 10; dim.width += 20; theApp.setSize(dim); //theApp.setSize(640,480); theApp.show(); } catch (Exception e) {} } }airport2config-2.0.1/AboutDialog.java0000644000175000017500000001177007637442276017064 0ustar julienjulien/* * SNMP Inquisitor * * Copyright (C) 2000, Jonathan Sevy * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ import java.awt.*; import java.awt.event.*; import javax.swing.*; import java.io.*; public class AboutDialog extends JDialog implements Runnable, ActionListener { private JLabel aboutLabel1 = new JLabel(" "); private JLabel aboutLabel2 = new JLabel(" "); private JLabel aboutLabel3 = new JLabel(" "); private JLabel aboutLabel4 = new JLabel(" "); private String aboutString1 = AirportBaseStationConfigurator.aboutString; private String aboutString2 = "Version 2.1 "; private String aboutString3 = "J. Sevy "; private String aboutString4 = "April 2003 "; private JButton okButton; Thread displayThread; public AboutDialog(JFrame parent) { super(parent, "About...", true /*modal*/); this.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE); Font titleFont = new Font("SansSerif",Font.BOLD + Font.ITALIC, 12); Font labelFont = new Font("SansSerif",Font.PLAIN, 10); aboutLabel1.setText(aboutString1); aboutLabel2.setText(aboutString2); aboutLabel3.setText(aboutString3); aboutLabel4.setText(aboutString4); aboutLabel1.setFont(titleFont); aboutLabel2.setFont(labelFont); aboutLabel3.setFont(labelFont); aboutLabel4.setFont(labelFont); setUpDisplay(); this.setLocation(Math.round((parent.size().width - this.size().width)/2), Math.round((parent.size().height - this.size().height)/2)); // create and start display thread displayThread = new Thread(this); displayThread.start(); this.show(); } public void hide() { super.hide(); // interrupt thread so it can exit.. displayThread.interrupt(); } private void setUpDisplay() { // set params for layout manager GridBagLayout theLayout = new GridBagLayout(); GridBagConstraints c = new GridBagConstraints(); c.gridwidth = 1; c.gridheight = 1; c.fill = GridBagConstraints.NONE; c.ipadx = 0; c.ipady = 0; c.insets = new Insets(2,2,2,2); c.anchor = GridBagConstraints.CENTER; c.weightx = 0; c.weighty = 0; JPanel aboutPanel = new JPanel(); aboutPanel.setLayout(theLayout); c.gridx = 1; c.gridy = 1; theLayout.setConstraints(aboutLabel1, c); aboutPanel.add(aboutLabel1); c.gridx = 1; c.gridy = 2; theLayout.setConstraints(aboutLabel2, c); aboutPanel.add(aboutLabel2); c.gridx = 1; c.gridy = 3; theLayout.setConstraints(aboutLabel3, c); aboutPanel.add(aboutLabel3); c.gridx = 1; c.gridy = 4; theLayout.setConstraints(aboutLabel4, c); aboutPanel.add(aboutLabel4); okButton = new JButton("OK"); okButton.setActionCommand("ok"); okButton.addActionListener(this); this.getRootPane().setDefaultButton(okButton); this.getContentPane().setLayout(theLayout); c.insets = new Insets(8,8,8,8); c.gridx = 1; c.gridy = 1; theLayout.setConstraints(aboutPanel, c); this.getContentPane().add(aboutPanel); c.gridx = 1; c.gridy = 2; theLayout.setConstraints(okButton, c); this.getContentPane().add(okButton); this.pack(); //this.setSize(300, 180); } public void actionPerformed(ActionEvent theEvent) // respond to button pushes, menu selections { String command = theEvent.getActionCommand(); if (command.equals("ok")) { this.hide(); } } public void run() { try { Color textColor = new Color(255, 0, 255); aboutLabel1.setForeground(textColor); /* aboutLabel1.setSize(0, 30); for (int i = 0; i < this.getWidth() - 20; i++) { aboutLabel1.setSize(i, 30); Thread.currentThread().sleep(6); } */ // change color of other strings... int numSteps = 255; for (int i = 0; i < numSteps; i++) { textColor = new Color(255, 255-i, i); aboutLabel2.setForeground(textColor); aboutLabel3.setForeground(textColor); aboutLabel4.setForeground(textColor); Thread.currentThread().sleep(20); } } catch(Exception e) { // don't bother informing of exception; just exit... //System.out.println(e); } // later! } }airport2config-2.0.1/AirportBaseStationMultiConfigurator.java0000644000175000017500000012122307503646704024032 0ustar julienjulien/* * AirportBaseStationConfigurator * * Copyright (C) 2000, Jonathan Sevy * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ import java.util.*; import java.net.*; import java.awt.*; import javax.swing.*; import javax.swing.border.*; import javax.swing.plaf.*; import java.awt.event.*; import java.io.*; import byteblock.*; import snmp.*; import airport.*; public class AirportBaseStationConfigurator extends JFrame implements ActionListener { public static final String encryptionKeySizeString = "05"; public static final int encryptionKeySize = 5; public static final String aboutString = "Airport Base Station Multiple Configurator "; JButton discoverDevicesButton, retrieveItemButton, updateBaseStationButton, updateAllButton, addAddressButton; //JTextField hostIDField; JComboBox addressBox; JTextField communityField; GridBagLayout mainLayout = new GridBagLayout(); MenuBar theMenubar; Menu fileMenu; MenuItem quitItem, openItem, saveItem, aboutItem, uploadFirmwareItem, uploadFirmwareToAllItem, openAddressListItem, saveAddressListItem; private final int baseBlockSize = 68*16*16; private ByteBlock baseBlock = new ByteBlock(68*16, 16); private final int configurationSize = 17336; // total number of significant bytes, including checksum AirportInfo airportInfo; AirportInfoTabbedPane infoPane; JTextArea messagesArea; SNMPv1CommunicationInterface comInterface; SNMPVarBindList retrievedVars; // WindowCloseAdapter to catch window close-box closings private class WindowCloseAdapter extends WindowAdapter { public void windowClosing(WindowEvent e) { System.exit(0); } }; public AirportBaseStationConfigurator() { airportInfo = new AirportInfo(baseBlock); setUpDisplay(); retrievedVars = new SNMPVarBindList(); } private void setUpDisplay() { // set fonts to smaller-than-normal size, for compaction! UIManager manager = new UIManager(); FontUIResource appFont = new FontUIResource("SansSerif", Font.PLAIN, 10); UIDefaults defaults = manager.getLookAndFeelDefaults(); Enumeration keys = defaults.keys(); while (keys.hasMoreElements()) { String nextKey = (String)(keys.nextElement()); if ((nextKey.indexOf("font") > -1) || (nextKey.indexOf("Font") > -1)) { manager.put(nextKey, appFont); } } // add WindowCloseAdapter to catch window close-box closings // thanks to Jer for this one! addWindowListener(new WindowCloseAdapter()); this.setTitle("AirPort Base Station Configurator"); this.getRootPane().setBorder(new BevelBorder(BevelBorder.RAISED)); theMenubar = new MenuBar(); this.setMenuBar(theMenubar); fileMenu = new Menu("File"); openItem = new MenuItem("Open saved settings..."); openItem.setShortcut(new MenuShortcut('o')); openItem.setActionCommand("open settings"); openItem.addActionListener(this); fileMenu.add(openItem); saveItem = new MenuItem("Save settings..."); saveItem.setShortcut(new MenuShortcut('s')); saveItem.setActionCommand("save settings"); saveItem.addActionListener(this); fileMenu.add(saveItem); fileMenu.addSeparator(); openAddressListItem = new MenuItem("Open address list..."); openAddressListItem.setActionCommand("open address list"); openAddressListItem.addActionListener(this); fileMenu.add(openAddressListItem); saveAddressListItem = new MenuItem("Save address list..."); saveAddressListItem.setActionCommand("save address list"); saveAddressListItem.addActionListener(this); fileMenu.add(saveAddressListItem); fileMenu.addSeparator(); uploadFirmwareItem = new MenuItem("Upload new base station firmware to selected base station..."); uploadFirmwareItem.setActionCommand("upload firmware"); uploadFirmwareItem.addActionListener(this); fileMenu.add(uploadFirmwareItem); uploadFirmwareToAllItem = new MenuItem("Upload new base station firmware to all base stations..."); uploadFirmwareToAllItem.setActionCommand("upload firmware to all"); uploadFirmwareToAllItem.addActionListener(this); fileMenu.add(uploadFirmwareToAllItem); fileMenu.addSeparator(); aboutItem = new MenuItem("About..."); aboutItem.setActionCommand("about"); aboutItem.addActionListener(this); fileMenu.add(aboutItem); quitItem = new MenuItem("Quit"); quitItem.setShortcut(new MenuShortcut('q')); quitItem.setActionCommand("quit"); quitItem.addActionListener(this); fileMenu.add(quitItem); theMenubar.add(fileMenu); JLabel hostIDLabel = new JLabel("Device address:"); addressBox = new JComboBox(); addressBox.addItem("10.0.1.1"); JLabel communityLabel = new JLabel("Community name (password):"); communityField = new JPasswordField(10); //communityField = new JTextField(10); //communityField.setText("public"); addAddressButton = new JButton("Add Address"); addAddressButton.setActionCommand("add address"); addAddressButton.addActionListener(this); discoverDevicesButton = new JButton("Discover Devices"); discoverDevicesButton.setActionCommand("discover devices"); discoverDevicesButton.addActionListener(this); retrieveItemButton = new JButton("Retrieve Settings"); retrieveItemButton.setActionCommand("retrieve data"); retrieveItemButton.addActionListener(this); updateBaseStationButton = new JButton("Update Selected Base Station"); updateBaseStationButton.setActionCommand("update base station"); updateBaseStationButton.addActionListener(this); updateBaseStationButton.setEnabled(false); //initially disabled until read in or open settings updateAllButton = new JButton("Update All Base Stations"); updateAllButton.setActionCommand("update all base stations"); updateAllButton.addActionListener(this); updateAllButton.setEnabled(false); //initially disabled until read in or open settings // set params for layout manager GridBagLayout theLayout = new GridBagLayout(); GridBagConstraints c = new GridBagConstraints(); c.gridwidth = 1; c.gridheight = 1; c.fill = GridBagConstraints.NONE; c.ipadx = 0; c.ipady = 0; Insets theMargin = new Insets(2,2,2,2); c.insets = theMargin; c.anchor = GridBagConstraints.CENTER; c.weightx = .5; c.weighty = .5; JPanel buttonPanel = new JPanel(); buttonPanel.setLayout(theLayout); c.gridx = 1; c.gridy = 1; theLayout.setConstraints(discoverDevicesButton, c); buttonPanel.add(discoverDevicesButton); c.gridx = 2; c.gridy = 1; theLayout.setConstraints(retrieveItemButton, c); buttonPanel.add(retrieveItemButton); c.gridx = 3; c.gridy = 1; theLayout.setConstraints(updateBaseStationButton, c); buttonPanel.add(updateBaseStationButton); c.gridx = 4; c.gridy = 1; theLayout.setConstraints(updateAllButton, c); buttonPanel.add(updateAllButton); JPanel hostPanel = new JPanel(); hostPanel.setLayout(theLayout); c.gridx = 1; c.gridy = 1; theLayout.setConstraints(hostIDLabel, c); hostPanel.add(hostIDLabel); c.gridx = 2; c.gridy = 1; theLayout.setConstraints(addressBox, c); hostPanel.add(addressBox); c.gridx = 3; c.gridy = 1; theLayout.setConstraints(addAddressButton, c); hostPanel.add(addAddressButton); c.gridx = 4; c.gridy = 1; theLayout.setConstraints(communityLabel, c); hostPanel.add(communityLabel); c.gridx = 5; c.gridy = 1; theLayout.setConstraints(communityField, c); hostPanel.add(communityField); infoPane = new AirportInfoTabbedPane(airportInfo); JPanel messagesPanel = new JPanel(); messagesPanel.setLayout(theLayout); messagesArea = new JTextArea(4,60); JScrollPane messagesScroll = new JScrollPane(messagesArea); c.gridx = 1; c.gridy = 1; JLabel messagesLabel = new JLabel("Messages:"); theLayout.setConstraints(messagesLabel, c); messagesPanel.add(messagesLabel); c.gridx = 1; c.gridy = 2; theLayout.setConstraints(messagesScroll, c); messagesPanel.add(messagesScroll); this.getContentPane().setLayout(mainLayout); c.gridx = 1; c.gridy = 1; mainLayout.setConstraints(hostPanel, c); this.getContentPane().add(hostPanel); c.gridx = 1; c.gridy = 2; mainLayout.setConstraints(buttonPanel, c); this.getContentPane().add(buttonPanel); c.gridx = 1; c.gridy = 3; mainLayout.setConstraints(infoPane, c); this.getContentPane().add(infoPane); c.gridx = 1; c.gridy = 4; mainLayout.setConstraints(messagesPanel, c); this.getContentPane().add(messagesPanel); c.gridx = 1; c.gridy = 5; JLabel authorLabel = new JLabel(" Version 1.5.2 J. Sevy, November 2001 "); authorLabel.setFont(new Font("SansSerif", Font.ITALIC, 8)); mainLayout.setConstraints(authorLabel, c); this.getContentPane().add(authorLabel); } public void actionPerformed(ActionEvent theEvent) // respond to button pushes, menu selections { String command = theEvent.getActionCommand(); if (command.equals("quit")) { System.exit(0); } if (command == "about") { AboutDialog aboutDialog = new AboutDialog(this); } if (command == "add address") { String newAddress = JOptionPane.showInputDialog("Enter new IP address"); if ( !((newAddress == null) || (newAddress.equals(""))) ) addressBox.addItem(newAddress); } if (command.equals("discover devices")) { AirportDiscoverer discoverer = new AirportDiscoverer(); } if (command.equals("retrieve data")) { try { if (comInterface != null) comInterface.closeConnection(); String community = communityField.getText(); InetAddress hostAddress = InetAddress.getByName((String)addressBox.getSelectedItem()); int version = 0; // SNMPv1 messagesArea.append("Retrieving settings from base station " + hostAddress + "......\n"); comInterface = new SNMPv1CommunicationInterface(version, hostAddress, community); for (int k = 1; k <= 68; k++) { String itemID = "1.3.6.1.4.1.762.2.2.1.1." + k; SNMPVarBindList newVars = comInterface.getMIBEntry(itemID); SNMPSequence pair = (SNMPSequence)(newVars.getSNMPObjectAt(0)); SNMPOctetString value = (SNMPOctetString)(pair.getSNMPObjectAt(1)); // get the 256 bytes byte[] bytes = (byte[])value.getValue(); // create a window to write bytes into int startIndex = (k-1)*256; int rows = 16; int cols = 16; ByteBlockRectangularWindow currentBlock = new ByteBlockRectangularWindow(startIndex, rows, cols, baseBlock); // write the bytes currentBlock.writeBytes(bytes); } // would like to check checksum to make sure retrieved block is valid, at least... // however, base station doesn't return valid checksum when data retrieved - // it's just a partial echo of the last checksum sent to it :-( messagesArea.append("Settings retrieved.\n"); // now refresh display this.refreshInfoPane(); // enable updating updateBaseStationButton.setEnabled(true); updateAllButton.setEnabled(true); } catch(UnknownHostException e) { messagesArea.append("Error retrieving settings: unknown host.\n"); } catch(SocketException e) { messagesArea.append("Error retrieving settings: " + e + "\n"); } catch(IOException e) { messagesArea.append("Error retrieving settings: timed out waiting for response.\n"); } catch (SNMPBadValueException e) { // will never occur! messagesArea.append("Error retrieving settings: bad SNMP value received.\n"); } catch (SNMPGetException e) { messagesArea.append("Error retrieving settings: incorrect community name (password).\n"); } catch (Exception e) { messagesArea.append("Error retrieving settings: " + e.getMessage() + "\n"); } } if (command.equals("save settings")) { try { infoPane.writeData(); setDependentData(); setStaticData(); setChecksum(baseBlock, configurationSize - 2); FileDialog fd = new FileDialog(this, "Save current settings as...", FileDialog.SAVE); fd.show(); if (fd.getFile() != null) { File newFile = new File(fd.getDirectory(), fd.getFile()); FileOutputStream fStream = new FileOutputStream(newFile); fStream.write(baseBlock.bytes, 0, configurationSize); fStream.flush(); fStream.close(); } } catch (ValueFormatException ve) { messagesArea.append("Problem with supplied value: " + ve.getMessage() + "\n"); } catch (Exception e) { messagesArea.append("Error saving settings: " + e.getMessage() + "\n"); } } if (command.equals("update base station") || command.equals("update all base stations")) { try { infoPane.writeData(); setDependentData(); setStaticData(); setChecksum(baseBlock, configurationSize - 2); // second checksum set in transmitBlocks() // configurationSize = 17336 indicates number of bytes to burn to prom: // includes first checksum (but not second, which is "transmission" // checksum - added by transmitBlocks method) if (command.equals("update base station")) { String baseStationAddress = (String)addressBox.getSelectedItem(); transmitBlocks(baseBlock, configurationSize, baseStationAddress); } else if (command.equals("update all base stations")) { for (int i = 0; i < addressBox.getItemCount(); i++) { String baseStationAddress = (String)addressBox.getItemAt(i); transmitBlocks(baseBlock, configurationSize, baseStationAddress); } } } catch (ValueFormatException ve) { messagesArea.append("Problem with supplied value: " + ve.getMessage() + "\n"); } } if (command.equals("open settings")) { try { FileDialog fd = new FileDialog(this, "Open settings file...", FileDialog.LOAD); fd.show(); if (fd.getFile() != null) { File newFile = new File(fd.getDirectory(), fd.getFile()); FileInputStream fStream = new FileInputStream(newFile); byte[] newBytes = new byte[17408]; fStream.read(newBytes); fStream.close(); // check checksum to make sure block is valid, at least... // save current bytes in case new ones invalid byte[] currentBytes = baseBlock.bytes; baseBlock.bytes = newBytes; // see if shift key held down while open selected; if so, don't check checksum boolean shiftKeyDown = ((theEvent.getModifiers() & ActionEvent.SHIFT_MASK) > 0); // make sure checksum is valid, to verify this is a valid settings file // first make sure file big enough to even check checksum! if ( (newFile.length() < configurationSize) || (!shiftKeyDown && !checksumValid()) ) { // reset base block to current bytes baseBlock.bytes = currentBytes; throw new Exception("invalid settings file."); } // now refresh display of data this.refreshInfoPane(); // enable updating updateBaseStationButton.setEnabled(true); } } catch (Exception e) { messagesArea.append("Error opening settings: " + e.getMessage() + "\n"); } } if (command.equals("open address list")) { try { FileDialog fd = new FileDialog(this, "Open base station address list...", FileDialog.LOAD); fd.show(); if (fd.getFile() != null) { File newFile = new File(fd.getDirectory(), fd.getFile()); BufferedReader fReader = new BufferedReader(new FileReader(newFile)); // reinitialize address combo box addressBox.removeAllItems(); String nextAddress; // assume have one address per line while ((nextAddress = fReader.readLine()) != null) { addressBox.addItem(nextAddress); } // if no addresses added, add default address 10.0.1.1 if (addressBox.getItemCount() == 0) { addressBox.addItem("10.0.1.1"); } } } catch (Exception e) { messagesArea.append("Error opening address list: " + e.getMessage() + "\n"); } } if (command.equals("save address list")) { try { FileDialog fd = new FileDialog(this, "Save current address list as...", FileDialog.SAVE); fd.show(); if (fd.getFile() != null) { File newFile = new File(fd.getDirectory(), fd.getFile()); FileWriter fStream = new FileWriter(newFile); for (int i = 0; i < addressBox.getItemCount(); i++) { String baseStationAddress = (String)addressBox.getItemAt(i); fStream.write(baseStationAddress + "\n"); } fStream.close(); } } catch (Exception e) { messagesArea.append("Error saving address list: " + e.getMessage() + "\n"); } } if (command.equals("upload firmware") || command.equals("upload firmware to all")) { try { FileDialog fd = new FileDialog(this, "Select firmware file...", FileDialog.LOAD); fd.show(); if (fd.getFile() != null) { File firmwareFile = new File(fd.getDirectory(), fd.getFile()); FileInputStream fStream = new FileInputStream(firmwareFile); int fileLength = (int)firmwareFile.length(); // determine number of 256-byte blocks that need to be sent int numBlocks = (int)Math.ceil((double)fileLength/256); // create underlying ByteBlock with appropriate number of sub-blocks ByteBlock firmwareBlock = new ByteBlock(numBlocks*16, 16); fStream.read(firmwareBlock.bytes); fStream.close(); // verify this is a valid firmware file; can unfortunately only verify the embedded // configuration checksum.... AND apparently the Apple-supplied formware files computed the // checksum before the community name default passwords (4 "public" and one count of 06) // were inserted. Thus the checksum computation differs by 0xA02 for these files, // so the checksum check is a little weird.... // first make sure file big enough to even check checksum! if (fileLength < configurationSize) { throw new Exception("invalid firmware file."); } else if ( (!appleFirmwareChecksumValid(firmwareBlock)) && (!checksumValid(firmwareBlock)) ) { throw new Exception("invalid firmware file."); } // put up a dialog permitting the user to select uploading the current settings, if // they're valid... String messageString = "Upload firmware to base station " + (String)addressBox.getSelectedItem() + "?"; String response = new String("Cancel"); // see if current settings are valid; if so, these become upload option if (updateBaseStationButton.isEnabled()) { String[] possibleValues = { "Upload firmware with current settings", "Upload firmware with default settings", "Cancel" }; int selectedValue = JOptionPane.showOptionDialog(null, messageString, "Firmware Upload", JOptionPane.YES_NO_OPTION, JOptionPane.INFORMATION_MESSAGE, null, possibleValues, possibleValues[0]); if ( !(selectedValue == JOptionPane.CLOSED_OPTION) ) response = possibleValues[selectedValue]; } else { String[] possibleValues = { "Upload firmware with default settings", "Cancel" }; int selectedValue = JOptionPane.showOptionDialog(null, messageString, "Firmware Upload", JOptionPane.YES_NO_OPTION, JOptionPane.INFORMATION_MESSAGE, null, possibleValues, possibleValues[0]); if ( !(selectedValue == JOptionPane.CLOSED_OPTION) ) response = possibleValues[selectedValue]; } // if current settings selected, upload these to base station with firmware; // if not, leave default settings alone in firmware bytes if (response.equals("Upload firmware with current settings")) { // note that current settings could throw ValueFormatException! infoPane.writeData(); setDependentData(); setStaticData(); setCommunityNames(); // so base station will know what to use after reset!! setChecksum(baseBlock, configurationSize - 2); // copy current setting bytes into firmware bytes for (int i = 0; i < configurationSize; i++) firmwareBlock.bytes[i] = baseBlock.bytes[i]; // now transmit info if (command.equals("upload firmware")) { String baseStationAddress = (String)addressBox.getSelectedItem(); transmitBlocks(firmwareBlock, fileLength, baseStationAddress); } else if (command.equals("upload firmware to all")) { for (int i = 0; i < addressBox.getItemCount(); i++) { String baseStationAddress = (String)addressBox.getItemAt(i); transmitBlocks(firmwareBlock, fileLength, baseStationAddress); } } } else if (response.equals("Upload firmware with default settings")) { if (command.equals("upload firmware")) { String baseStationAddress = (String)addressBox.getSelectedItem(); transmitBlocks(firmwareBlock, fileLength, baseStationAddress); } else if (command.equals("upload firmware to all")) { for (int i = 0; i < addressBox.getItemCount(); i++) { String baseStationAddress = (String)addressBox.getItemAt(i); transmitBlocks(firmwareBlock, fileLength, baseStationAddress); } } } } } catch (ValueFormatException ve) { messagesArea.append("Problem with supplied value: " + ve.getMessage() + "\n"); } catch (Exception e) { messagesArea.append("Error updating firmware: " + e.getMessage() + "\n"); } } } private void refreshInfoPane() { // first, remove current infoPane this.remove(infoPane); //now create new tabbed pane to hold info infoPane = new AirportInfoTabbedPane(airportInfo); // set params for layout manager GridBagConstraints c = new GridBagConstraints(); c.gridwidth = 1; c.gridheight = 1; c.fill = GridBagConstraints.NONE; c.ipadx = 0; c.ipady = 0; Insets theMargin = new Insets(2,2,2,2); c.insets = theMargin; c.anchor = GridBagConstraints.CENTER; c.weightx = .5; c.weighty = .5; // then add pane to frame c.gridx = 1; c.gridy = 3; mainLayout.setConstraints(infoPane, c); this.getContentPane().add(infoPane); // call validate to update display this.validate(); } private void setDependentData() throws ValueFormatException { /* * Write values for DHCP/NAT-delivered base station IP address, router * IP address, mask; do here since requires "cross-reference" between data * in separate panels. */ boolean ethernetConnection = false, modemConnection = false; // flags specifying base station connection and boolean dhcpConfig = false, manualConfig = false; // configuration style boolean natEnabled = false, dhcpEnabled = false; // flags indicating address delivery services of base station boolean portMappingEnabled = false; // set flags for Ethernet/Modem mode AirportInfoRecord ethernetModemSwitch1Record = airportInfo.get("waIn"); String ethernetModemSwitch1Setting = ethernetModemSwitch1Record.toString(); AirportInfoRecord ethernetModemSwitch2Record = airportInfo.get("Configuration interface"); String ethernetModemSwitch2Setting = ethernetModemSwitch2Record.toString(); if (ethernetModemSwitch1Setting.equals("60") || ethernetModemSwitch2Setting.equals("00")) ethernetConnection = true; if (ethernetModemSwitch1Setting.equals("62") || ethernetModemSwitch2Setting.equals("03")) modemConnection = true; //set flags for base station configuration mode AirportInfoRecord baseConfigModeRecord = airportInfo.get("Base station configuration mode switch"); String baseConfigModeSetting = baseConfigModeRecord.toString(); if (baseConfigModeSetting.equals("00")) manualConfig = true; if (baseConfigModeSetting.equals("20")) dhcpConfig = true; // set flags for NAT/DHCP mode AirportInfoRecord dhcpSwitchRecord = airportInfo.get("laDS"); String dhcpSetting = dhcpSwitchRecord.toString(); if (dhcpSetting.equals("80")) dhcpEnabled = true; AirportInfoRecord natSwitchRecord = airportInfo.get("raNA"); String natSetting = natSwitchRecord.toString(); if (natSetting.equals("02")) natEnabled = true; // set flag for port mapping AirportInfoRecord portMappingSwitchRecord = airportInfo.get("Port mapping switch"); String portMappingSwitchSetting = portMappingSwitchRecord.toString(); if (portMappingSwitchSetting.equals("04")) portMappingEnabled = true; // get records for setting dependent data AirportInfoRecord natInboundPrivateIPAddressRecord = airportInfo.get("NAT inbound private IP address"); AirportInfoRecord natInboundPrivateSubnetMaskRecord = airportInfo.get("NAT inbound private subnet mask"); AirportInfoRecord natOutboundPrivateIPAddressRecord = airportInfo.get("NAT outbound private IP address"); AirportInfoRecord natOutboundPrivateSubnetMaskRecord = airportInfo.get("NAT outbound private subnet mask"); AirportInfoRecord natOutboundPublicIPAddressRecord = airportInfo.get("NAT outbound public IP address"); AirportInfoRecord natOutboundPublicSubnetMaskRecord = airportInfo.get("NAT outbound public subnet mask"); AirportInfoRecord dhcpServerRouterIPAddressRecord = airportInfo.get("DHCP server router address"); AirportInfoRecord dhcpServerSubnetMaskRecord = airportInfo.get("DHCP server subnet mask"); AirportInfoRecord baseStationIPAddressRecord = airportInfo.get("waIP"); AirportInfoRecord subnetMaskRecord = airportInfo.get("waSM"); AirportInfoRecord routerIPAddressRecord = airportInfo.get("waRA"); // when NAT enabled, set data that depends on settings from other panels if (natEnabled) { // set NAT outbound IP address and mask if (modemConnection) { natOutboundPublicIPAddressRecord.setBytesFromString("0.0.0.0"); natOutboundPublicSubnetMaskRecord.setBytesFromString("255.255.255.0"); } if (ethernetConnection) { if (manualConfig) { natOutboundPublicIPAddressRecord.setBytesFromString(baseStationIPAddressRecord.toString()); natOutboundPublicSubnetMaskRecord.setBytesFromString(subnetMaskRecord.toString()); } else if (dhcpConfig) { natOutboundPublicIPAddressRecord.setBytesFromString("0.0.0.0"); natOutboundPublicSubnetMaskRecord.setBytesFromString("255.255.255.0"); } } } // if serving DHCP, set router and subnet mask if (dhcpEnabled) { if (natEnabled) { // use private network parameters dhcpServerRouterIPAddressRecord.setBytesFromString(natInboundPrivateIPAddressRecord.toString()); dhcpServerSubnetMaskRecord.setBytesFromString(natInboundPrivateSubnetMaskRecord.toString()); } else { // use global base station parameters dhcpServerRouterIPAddressRecord.setBytesFromString(routerIPAddressRecord.toString()); dhcpServerSubnetMaskRecord.setBytesFromString(subnetMaskRecord.toString()); } } // if port mapping, and using manual Ethernet config, need to put in base station IP address // as the public IP address in the port maps if (portMappingEnabled && ethernetConnection && manualConfig) { // get count of port maps AirportInfoRecord portMappingCountRecord = airportInfo.get("Count of port mappings"); int portMapCount = Integer.parseInt(portMappingCountRecord.toString()); // get starting indices and other parameters for the byte block multi-windows // that will hold the public IP address for port mapping, which is just the // manually configured base station IP address int publicIPStartIndex = 0xD72; int publicIPBeginningNumRows = 1; int publicIPBeginningNumCols = 2; int publicIPEndingIndex = 0xD9A; int publicIPEndingNumRows = 1; int publicIPEndingNumCols = 2; int publicIPDataType = AirportInfoRecord.IP_ADDRESS; //set the public IP address for each port map for (int i = 0; i < portMapCount; i++) { // need to use a multi-window, since the first two and last two octets are separated ByteBlockMultiWindow publicIPWindow = new ByteBlockMultiWindow(); ByteBlockWindow publicIPBeginningWindow = new ByteBlockRectangularWindow(publicIPStartIndex, publicIPBeginningNumRows, publicIPBeginningNumCols, baseBlock); publicIPWindow.addWindow(publicIPBeginningWindow); ByteBlockWindow publicIPEndingWindow = new ByteBlockRectangularWindow(publicIPEndingIndex, publicIPEndingNumRows, publicIPEndingNumCols, baseBlock); publicIPWindow.addWindow(publicIPEndingWindow); AirportInfoRecord publicIPRecord = new AirportInfoRecord(publicIPDataType, publicIPWindow); publicIPRecord.setBytesFromString(baseStationIPAddressRecord.toString()); // augment addresses publicIPStartIndex += 2; publicIPEndingIndex += 2; } } } private void setStaticData() throws ValueFormatException { // set read community password field AirportInfoRecord readCommunityRecord = airportInfo.get("syPR"); readCommunityRecord.setBytesFromString("public"); /* // set miscellaneous switches that are sometimes zero in "plain vanilla" config files String miscellaneousSetting; AirportInfoRecord miscellaneousRecord1 = airportInfo.get("Miscellaneous switch 1"); miscellaneousSetting = miscellaneousRecord1.toString(); if (miscellaneousSetting.equals("00")) miscellaneousRecord1.setBytesFromString("01"); AirportInfoRecord miscellaneousRecord2 = airportInfo.get("Miscellaneous switch 2"); miscellaneousSetting = miscellaneousRecord2.toString(); if (miscellaneousSetting.equals("00")) miscellaneousRecord2.setBytesFromString("01"); */ } private void setCommunityNames() throws ValueFormatException { // Set community name into password field so base station will know what to use after reboot! // Find out if there's an entry in the main panel; if so, use this, otherwise use // current community name field AirportInfoRecord communityNameRecord = airportInfo.get("syPW"); String communityName = communityNameRecord.toString(); if (communityName.equals("")) communityName = communityField.getText(); communityNameRecord.setBytesFromString(communityName); //System.out.println("Community name: " + communityName); // set trap community password field AirportInfoRecord trapCommunityRecord = airportInfo.get("Trap community"); trapCommunityRecord.setBytesFromString("public"); // set remaining community password field (and count field) AirportInfoRecord remainingCommunityCountRecord = airportInfo.get("Remaining community count"); remainingCommunityCountRecord.setBytesFromString("06"); AirportInfoRecord remainingCommunityRecord = airportInfo.get("Remaining community"); remainingCommunityRecord.setBytesFromString("public"); } private void transmitBlocks(ByteBlock byteBlock, int numBytes, String hostAddressString) { try { String community = communityField.getText(); InetAddress hostAddress = InetAddress.getByName(hostAddressString); messagesArea.append("Sending data to base station " + hostAddress + "......\n"); if (comInterface == null) { int version = 0; // SNMPv1 comInterface = new SNMPv1CommunicationInterface(version, hostAddress, community); } comInterface.requestID = 1; byte[] bytes = byteBlock.bytes; // determine number of 256-byte blocks that need to be sent int numBlocks = (int)Math.ceil((double)(numBytes + 2)/256); // +2 leaves room for transmission checksum // send all but last block for (int k = 1; k < numBlocks; k++) { String itemID = "1.3.6.1.4.1.762.2.3.1.1." + k; // create new 256 byte array byte[] newBytes = new byte[256]; // copy block of 256 bytes from given bytes to new array for (int j = 0; j < 256; j++) { newBytes[j] = bytes[256*(k-1) + j]; } // create SNMP octet string from these bytes SNMPOctetString theObject = new SNMPOctetString(newBytes); // send the bytes SNMPVarBindList newVars = comInterface.setMIBEntry(itemID, theObject); } // now send last block String itemID = "1.3.6.1.4.1.762.2.3.1.1." + numBlocks; // create new 256 byte array byte[] newBytes = new byte[256]; // copy remaining bytes from given bytes to new array int endPosition = numBytes - (numBlocks-1)*256; for (int j = 0; j < endPosition; j++) { newBytes[j] = bytes[256*(numBlocks-1) + j]; } // now set transmission checksum as 2 bytes following last (legitimate) bytes; // note that number of blocks was chosen to be (numBytes+2)/256, ensuring room ByteBlock lastBlock = new ByteBlock(16, 16, newBytes); short checksum = computeChecksum(byteBlock.bytes, numBytes); setChecksum(checksum, lastBlock, endPosition); // create SNMP octet string from these bytes SNMPOctetString theObject = new SNMPOctetString(lastBlock.bytes); // send the bytes SNMPVarBindList newVars = comInterface.setMIBEntry(itemID, theObject); // now send reset signal: indicates number of bytes to burn to prom. // also indicates location of checksum SNMPInteger numBytesWritten = new SNMPInteger(numBytes); //System.out.println("Number of bytes to burn in: " + numBytesWritten); itemID = "1.3.6.1.4.1.762.2.1.2.0"; newVars = comInterface.setMIBEntry(itemID, numBytesWritten); itemID = "1.3.6.1.4.1.762.2.1.3.0"; newVars = comInterface.setMIBEntry(itemID, numBytesWritten); messagesArea.append("Data transmitted; base station restarting.\n"); } catch(UnknownHostException e) { messagesArea.append("Error transmitting data: unknown host.\n"); } catch(SocketException e) { messagesArea.append("Error transmitting data: " + e.getMessage() + "\n"); } catch(IOException e) { messagesArea.append("Error transmitting data: timed out waiting for response.\n"); } catch (SNMPSetException e) { messagesArea.append("Error transmitting data: " + e.getMessage() + "\n"); } catch (SNMPBadValueException e) { // will never occur! messagesArea.append("Error transmitting data: bad SNMP value.\n"); } } /* * Compute the 2-byte checksum for the bytes up to (but not including) the indicated position */ private short computeChecksum(byte[] bytes, int position) { short sum = 0; for (int i = 0; i < position; i++) { sum += bytes[i]; if(bytes[i] < 0) sum += 256; } return sum; } private void setChecksum(short sum, ByteBlock byteBlock, int position) { String checksumString = littleEndianHexString(sum); // create info record to write into int numRows = 1; int numCols = 2; int baseStartIndex = position; ByteBlockWindow checksumWindow = new ByteBlockRectangularWindow(baseStartIndex, numRows, numCols, byteBlock); int dataType = AirportInfoRecord.BYTE_STRING; AirportInfoRecord checksumRecord = new AirportInfoRecord(dataType, checksumWindow); checksumRecord.byteBlockWindow.clearBytes(); // write in new checksum try { checksumRecord.setBytesFromString(checksumString); } catch (ValueFormatException ve) { // won't occur! messagesArea.append("Problem writing checksum with value " + checksumString + ".\n"); } } /* * Convenience method for writing checksum value into same block it's computed from. This * is the usual case for config files; however, the more general routine is used to set * the transmission checksum immediately following the transmitted data bytes. */ private void setChecksum(ByteBlock byteBlock, int position) { short sum = computeChecksum(byteBlock.bytes, position); setChecksum(sum, byteBlock, position); } /** * Return little-endian hex string */ private String littleEndianHexString(short value) { int intValue = value; intValue = intValue & 0xFFFF; int switched = ((intValue << 8) | (intValue >>> 8)) & 0xFFFF; String returnString = Integer.toHexString(switched); // add leading zeros if needed while (returnString.length() < 4) returnString = "0" + returnString; return returnString; } /** * Used to validate checksum in stored settings, to ensure file is legitimate! Verify just * first checksum, for compatibility with Apple configurator's stored settings. */ private boolean checksumValid(ByteBlock byteBlock) { short sum = computeChecksum(byteBlock.bytes, configurationSize - 2); String computedChecksumString = littleEndianHexString(sum); //System.out.println("Computed checksum: " + computedChecksumString); // get configuration checksum from block int baseStartIndex = 0x43B6; int numRows = 1; int numCols = 2; int dataType = AirportInfoRecord.BYTE_STRING; AirportInfoRecord checksumRecord = new AirportInfoRecord(baseStartIndex, numRows, numCols, dataType, byteBlock); String existingChecksumString = checksumRecord.toString(); //System.out.println("Existing checksum: " + existingChecksumString); if (computedChecksumString.equals(existingChecksumString)) return true; else return false; } private boolean checksumValid() { return checksumValid(baseBlock); } // Apparently the Apple-supplied firmware files computed the // checksum before the community name default passwords (4 "public" and one count of 06) // were inserted. Thus the checksum computation should differ by 0xA02 for these files. // Thus the need for this "hacked" checksum validation.... private boolean appleFirmwareChecksumValid(ByteBlock byteBlock) { short sum = computeChecksum(byteBlock.bytes, configurationSize - 2); sum -= 0xA02; String computedChecksumString = littleEndianHexString(sum); //System.out.println("Computed checksum: " + computedChecksumString); // get configuration checksum from block int baseStartIndex = 0x43B6; int numRows = 1; int numCols = 2; int dataType = AirportInfoRecord.BYTE_STRING; AirportInfoRecord checksumRecord = new AirportInfoRecord(baseStartIndex, numRows, numCols, dataType, byteBlock); String existingChecksumString = checksumRecord.toString(); //System.out.println("Existing checksum: " + existingChecksumString); if (computedChecksumString.equals(existingChecksumString)) return true; else return false; } public static void main(String args[]) { try { AirportBaseStationConfigurator theApp = new AirportBaseStationConfigurator(); theApp.pack(); // tweak app size to make it a little larger than necessary, to address the // "shrunken textfields" problem arising from the layout manager packing stuff // a little too tightly. Dimension dim = theApp.getSize(); dim.height += 20; dim.width += 20; theApp.setSize(dim); theApp.show(); } catch (Exception e) {} } }airport2config-2.0.1/AirportBaseStationCLI.java0000644000175000017500000011644107761252707020774 0ustar julienjulien/* * AirportBaseStationConfigurator * * Copyright (C) 2000, Jonathan Sevy * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ import java.util.*; import java.net.*; import java.awt.event.*; import java.io.*; import java.util.zip.*; import airport.*; public class AirportBaseStationCLI implements ActionListener, Runnable { public static final String aboutString = "Airport Base Station Configurator "; AirportInfo airportInfo; String password = ""; String baseStationAddress = "10.0.1.1"; // don't allow updating until settings opened or retrieved boolean updateBaseStationEnabled = false; BufferedReader inStream; public AirportBaseStationCLI() { airportInfo = new AirportInfo(); inStream = new BufferedReader(new InputStreamReader(System.in)); } public void actionPerformed(ActionEvent theEvent) // respond to button pushes, menu selections { String command = theEvent.getActionCommand(); if (command.equals("quit")) { System.exit(0); } if (command == "about") { //AboutDialog aboutDialog = new AboutDialog(this); } if (command.equals("discover devices")) { //AirportDiscoverer discoverer = new AirportDiscoverer(); } if (command.equals("retrieve data")) { try { InetAddress hostAddress = InetAddress.getByName(baseStationAddress); System.out.println("Retrieving settings from base station " + hostAddress + "......\n"); byte[] requestPayload = airportInfo.getRequestBytes(); Airport2ProtocolMessage requestMessage = new Airport2ProtocolMessage(Airport2ProtocolMessage.READ, password, requestPayload, requestPayload.length); // open socket int port = 5009; Socket configSocket = new Socket(hostAddress, port); // set socket timeout to 15 seconds configSocket.setSoTimeout(15000); DataInputStream inputStream = new DataInputStream(configSocket.getInputStream()); OutputStream outputStream = configSocket.getOutputStream(); outputStream.write(requestMessage.getBytes()); outputStream.flush(); /* System.out.println("Request header bytes:"); System.out.println(printHexBytes(requestMessage.getBytes())); */ outputStream.write(requestPayload); outputStream.flush(); // get and process response byte[] responseHeader = new byte[128]; inputStream.readFully(responseHeader); // create temp buffer to hold retrieved config; 20k should suffice... byte[] responsePayload = new byte[4096]; // read info try { inputStream.readFully(responsePayload); } catch (EOFException e) { // this is expected; we _should_ reach the end of the stream before filling the buffer... } /* numBytes = 0; int newNumBytes = 0; while( ((newNumBytes = inputStream.read(responsePayload, numBytes, responsePayload.length - numBytes)) >= 0 ) && (numBytes < responsePayload.length) ) { System.out.println("Read " + newNumBytes + " bytes."); numBytes += newNumBytes; } */ //System.out.println("done."); //System.out.println("Read " + numBytes + " bytes total."); inputStream.close(); outputStream.close(); configSocket.close(); // check to see if we retrieved valid data from the base station try { airportInfo = new AirportInfo(responsePayload); System.out.println("Settings retrieved.\n"); // enable updating updateBaseStationEnabled = true; } catch(IllegalArgumentException ex) { // thrown by AirportInfo constructor if no data retrieved System.out.println("Error retrieving settings (check password)\n"); } } catch(UnknownHostException e) { System.out.println("Error retrieving settings: unknown host.\n"); } catch(SocketException e) { System.out.println("Error retrieving settings: " + e + "\n"); } catch(IOException e) { System.out.println("Error retrieving settings: timed out waiting for response.\n"); } catch (Exception e) { System.out.println("Error retrieving settings: " + e.getMessage() + "\n"); } } if (command.equals("save settings")) { if (!updateBaseStationEnabled) { System.out.println("Must retrieve or open settings first."); return; } try { System.out.print("Enter path to settings file (or hit return to cancel): "); String filePath = inStream.readLine(); if (!filePath.equals("")) { File newFile = new File(filePath); DataOutputStream fStream = new DataOutputStream(new FileOutputStream(newFile)); setDependentData(); setStaticData(); performConsistencyChecks(); byte[] fileBytes = airportInfo.getUpdateBytes(); // compute a checksum on the data, and pre-pend it to the file int checksum = computeChecksum(fileBytes); fStream.writeInt(checksum); fStream.write(fileBytes); fStream.flush(); fStream.close(); } } catch (ValueFormatException ve) { System.out.println("Problem with supplied value: " + ve.getMessage() + "\n"); } catch (Exception e) { System.out.println("Error saving settings: " + e.getMessage() + "\n"); } } if (command.equals("update base station")) { if (!updateBaseStationEnabled) { System.out.println("Must retrieve or open settings first."); return; } try { setDependentData(); setStaticData(); performConsistencyChecks(); InetAddress hostAddress = InetAddress.getByName(baseStationAddress); System.out.println("Updating settings to base station " + hostAddress + "......\n"); byte[] requestPayload = airportInfo.getUpdateBytes(); Airport2ProtocolMessage requestMessage = new Airport2ProtocolMessage(Airport2ProtocolMessage.WRITE, password, requestPayload, requestPayload.length); // open socket int port = 5009; Socket configSocket = new Socket(hostAddress, port); // set socket timeout to 15 seconds configSocket.setSoTimeout(15000); DataInputStream inputStream = new DataInputStream(configSocket.getInputStream()); OutputStream outputStream = configSocket.getOutputStream(); outputStream.write(requestMessage.getBytes()); outputStream.flush(); /* System.out.println("Request header bytes:"); System.out.println(printHexBytes(requestMessage.getBytes())); */ outputStream.write(requestPayload); outputStream.flush(); /* System.out.println("Request header payload:"); System.out.println(printHexBytes(requestPayload)); */ // get and process response byte[] responseHeader = new byte[128]; inputStream.readFully(responseHeader); /* System.out.println("Response header bytes:"); System.out.println(printHexBytes(responseHeader)); */ // create temp buffer to hold retrieved config; 20k should suffice... byte[] responsePayload = new byte[4096]; // read info int numBytes = inputStream.read(responsePayload); //System.out.println("done."); //System.out.println("Read " + numBytes + " bytes."); inputStream.close(); outputStream.close(); configSocket.close(); if (numBytes > 0) { //airportInfo = new AirportInfo(responsePayload); System.out.println("Settings updated.\n"); } else { System.out.println("\nError updating settings (check password)\n"); } } catch (ValueFormatException ve) { System.out.println("Problem with supplied value: " + ve.getMessage() + "\n"); } catch(UnknownHostException e) { System.out.println("Error updating settings: unknown host.\n"); } catch(SocketException e) { System.out.println("Error updating settings: " + e + "\n"); } catch(IOException e) { System.out.println("Error updating settings: timed out waiting for response.\n"); } catch (Exception e) { System.out.println("Error updating settings: " + e.getMessage() + "\n"); } } if (command.equals("reboot base station")) { try { InetAddress hostAddress = InetAddress.getByName(baseStationAddress); System.out.println("Rebooting base station " + hostAddress + "......\n"); // get just the reboot info record byte[] requestPayload = airportInfo.get("acRB").getUpdateBytes(); Airport2ProtocolMessage requestMessage = new Airport2ProtocolMessage(Airport2ProtocolMessage.WRITE, password, requestPayload, requestPayload.length); // open socket int port = 5009; Socket configSocket = new Socket(hostAddress, port); // set socket timeout to 15 seconds configSocket.setSoTimeout(15000); DataInputStream inputStream = new DataInputStream(configSocket.getInputStream()); OutputStream outputStream = configSocket.getOutputStream(); outputStream.write(requestMessage.getBytes()); outputStream.flush(); /* System.out.println("Request header bytes:"); System.out.println(printHexBytes(requestMessage.getBytes())); */ outputStream.write(requestPayload); outputStream.flush(); /* System.out.println("Request header payload:"); System.out.println(printHexBytes(requestPayload)); */ // get and process response byte[] responseHeader = new byte[128]; inputStream.readFully(responseHeader); /* System.out.println("Response header bytes:"); System.out.println(printHexBytes(responseHeader)); */ // create temp buffer to hold retrieved config; 20k should suffice... byte[] responsePayload = new byte[4096]; // read info int numBytes = inputStream.read(responsePayload); //System.out.println("done."); //System.out.println("Read " + numBytes + " bytes."); inputStream.close(); outputStream.close(); configSocket.close(); if (numBytes > 0) { System.out.println("Base station rebooting.\n"); } else { System.out.println("\nError rebooting base station (check password)\n"); } } catch(UnknownHostException e) { System.out.println("Error rebooting base station: unknown host.\n"); } catch(SocketException e) { System.out.println("Error rebooting base station: " + e + "\n"); } catch(IOException e) { System.out.println("Error rebooting base station: timed out waiting for response.\n"); } catch (Exception e) { System.out.println("Error rebooting base station: " + e.getMessage() + "\n"); } } if (command.equals("open settings")) { try { System.out.print("Enter path to settings file (or hit return to cancel): "); String filePath = inStream.readLine(); if (!filePath.equals("")) { File newFile = new File(filePath); DataInputStream fStream = new DataInputStream(new FileInputStream(newFile)); int existingChecksum = fStream.readInt(); byte[] newBytes = new byte[(int)newFile.length() - 4]; fStream.readFully(newBytes); fStream.close(); // check checksum to make sure block is valid, at least... int computedChecksum = computeChecksum(newBytes); if (computedChecksum == existingChecksum) { airportInfo = new AirportInfo(newBytes); System.out.println("Settings opened.\n"); // enable updating updateBaseStationEnabled = true; } else { System.out.println("Invalid configuration file.\n"); } } } catch (Exception e) { System.out.println("Error opening settings: " + e.getMessage() + "\n"); } } if (command.equals("upload firmware")) { try { System.out.println("Enter path to settings file (or hit return to cancel):"); String filePath = inStream.readLine(); if (!filePath.equals("")) { File firmwareFile = new File(filePath); DataInputStream fStream = new DataInputStream(new FileInputStream(firmwareFile)); int fileLength = (int)firmwareFile.length(); // read in firmware image int flashSize = 0x180000; byte[] firmwareBytes = new byte[flashSize]; // check first to see if this should be interpreted as a MacBinary file; // read 128 bytes for header, and check if have type/creator fields // first make sure file big enough to hold MacBinary header if (fileLength < 128) throw new Exception("invalid firmware file."); // read in MacBinary header, for verification purposes fStream.read(firmwareBytes, 0, 128); /* System.out.println("Mac file header:"); System.out.println(printHexBytes(macFileHeader)); */ int dataLength = 0; // get file type and creator String fileTypeCreator = new String(firmwareBytes, 65, 8); if (fileTypeCreator.equals("bin21wcu")) { System.out.println("Mac file"); // it's a Mac file; get length of data fork for (int i = 83; i < 87; i++) { dataLength *= 256; int byteValue = (int)firmwareBytes[i]; if (byteValue < 0) byteValue += 256; dataLength += byteValue; } /* System.out.println("Data length bytes: " + hexByte(macFileHeader[83]) + " " + hexByte(macFileHeader[84]) + " " + hexByte(macFileHeader[85]) + " " + hexByte(macFileHeader[86]) + " " ); */ if (fileLength - 128 < dataLength) throw new Exception("invalid firmware file."); // read in firmware bytes, overwriting Mac header fStream.read(firmwareBytes, 0, dataLength); } else { // no Mac header - just straight firmware // read in remaining stuff System.out.println("Not a Mac file"); dataLength = fileLength; fStream.read(firmwareBytes, 128, fileLength); } //System.out.println("Read bytes: 0x" + Integer.toHexString(numbytes) + " of 0x" + Integer.toHexString(dataLength)); fStream.close(); // move checksum on firmware file to last 8 bytes ... firmwareBytes[flashSize - 8] = firmwareBytes[dataLength - 8]; firmwareBytes[flashSize - 7] = firmwareBytes[dataLength - 7]; firmwareBytes[flashSize - 6] = firmwareBytes[dataLength - 6]; firmwareBytes[flashSize - 5] = firmwareBytes[dataLength - 5]; firmwareBytes[flashSize - 4] = firmwareBytes[dataLength - 4]; firmwareBytes[flashSize - 3] = firmwareBytes[dataLength - 3]; firmwareBytes[flashSize - 2] = firmwareBytes[dataLength - 2]; firmwareBytes[flashSize - 1] = firmwareBytes[dataLength - 1]; firmwareBytes[dataLength - 8] = 0; firmwareBytes[dataLength - 7] = 0; firmwareBytes[dataLength - 6] = 0; firmwareBytes[dataLength - 5] = 0; firmwareBytes[dataLength - 4] = 0; firmwareBytes[dataLength - 3] = 0; firmwareBytes[dataLength - 2] = 0; firmwareBytes[dataLength - 1] = 0; /* // compute CRC32 on firmware image, up to the checksum... CRC32 crc = new CRC32(); crc.update(firmwareBytes, 0, flashSize); System.out.println("CRC32 checksum: 0x" + Long.toHexString(crc.getValue())); Adler32 adler = new Adler32(); adler.update(firmwareBytes, 0, flashSize); System.out.println("Adler32 checksum: 0x" + Long.toHexString(adler.getValue())); */ /* System.out.println("Firmware checksum: " + hexByte(firmwareBytes[flashSize - 8]) + " " + hexByte(firmwareBytes[flashSize - 7]) + " " + hexByte(firmwareBytes[flashSize - 6]) + " " + hexByte(firmwareBytes[flashSize - 5]) + " " + hexByte(firmwareBytes[flashSize - 4]) + " " + hexByte(firmwareBytes[flashSize - 3]) + " " + hexByte(firmwareBytes[flashSize - 2]) + " " + hexByte(firmwareBytes[flashSize - 1]) + " " ); */ // put up a dialog permitting the user to select uploading the current settings, if // they're valid... System.out.println("Upload firmware to base station " + baseStationAddress + "? (y or n)"); String response = inStream.readLine(); char responseChar = response.charAt(0); if ((responseChar == 'y') || (responseChar == 'Y')) { // transmit firmware info InetAddress hostAddress = InetAddress.getByName(baseStationAddress); // open socket int port = 5009; Socket configSocket = new Socket(hostAddress, port); // set socket timeout to 45 seconds configSocket.setSoTimeout(45000); DataInputStream inputStream = new DataInputStream(configSocket.getInputStream()); OutputStream outputStream = configSocket.getOutputStream(); Airport2ProtocolMessage requestMessage = new Airport2ProtocolMessage(Airport2ProtocolMessage.WRITE_RAW, password, firmwareBytes, firmwareBytes.length); outputStream.write(requestMessage.getBytes()); outputStream.flush(); /* System.out.println("Request header bytes:"); System.out.println(printHexBytes(requestMessage.getBytes())); */ outputStream.write(firmwareBytes); outputStream.flush(); /* System.out.println("Request header payload:"); System.out.println(printHexBytes(requestPayload)); */ // get and process response byte[] responseHeader = new byte[128]; inputStream.readFully(responseHeader); /* System.out.println("Response header bytes:"); System.out.println(printHexBytes(responseHeader)); */ Airport2ProtocolMessage responseMessage = new Airport2ProtocolMessage(responseHeader); //System.out.println(responseMessage.toString()); // check status field, to see if successful if (responseMessage.status < 0) throw new Exception("base station refused update - invalid firmware file"); // now reboot base station to get it to read the new firmware image System.out.println("Rebooting base station " + hostAddress + "......\n"); // get just the reboot info record byte[] requestPayload = airportInfo.get("acRB").getUpdateBytes(); requestMessage = new Airport2ProtocolMessage(Airport2ProtocolMessage.WRITE, password, requestPayload, requestPayload.length); // open new socket configSocket = new Socket(hostAddress, port); // set socket timeout to 15 seconds configSocket.setSoTimeout(15000); inputStream = new DataInputStream(configSocket.getInputStream()); outputStream = configSocket.getOutputStream(); outputStream.write(requestMessage.getBytes()); outputStream.flush(); /* System.out.println("Request header bytes:"); System.out.println(printHexBytes(requestMessage.getBytes())); */ outputStream.write(requestPayload); outputStream.flush(); /* System.out.println("Request header payload:"); System.out.println(printHexBytes(requestPayload)); */ // get and process response responseHeader = new byte[128]; inputStream.readFully(responseHeader); /* System.out.println("Response header bytes:"); System.out.println(printHexBytes(responseHeader)); */ responseMessage = new Airport2ProtocolMessage(responseHeader); //System.out.println(responseMessage.toString()); // check status field, to see if successful if (responseMessage.status < 0) throw new Exception("base station refused to reboot!"); // create temp buffer to hold response message... byte[] responsePayload = new byte[4096]; // read info int numBytes = inputStream.read(responsePayload); //System.out.println("done."); //System.out.println("Read " + numBytes + " bytes."); inputStream.close(); outputStream.close(); configSocket.close(); if (numBytes > 0) { //airportInfo = new AirportInfo(responsePayload); System.out.println("Base station rebooting.\n"); } else { System.out.println("\nError rebooting base station (check password)\n"); } } } } catch(UnknownHostException e) { System.out.println("Error updating firmware: unknown host.\n"); } catch(SocketException e) { System.out.println("Error updating firmware: " + e + "\n"); } catch(IOException e) { System.out.println("Error updating firmware: timed out waiting for response - check password.\n"); } catch (Exception e) { System.out.println("Error updating firmware: " + e.getMessage() + "\n"); } } } private String hexByte(byte b) { int pos = b; if (pos < 0) pos += 256; String returnString = new String(); returnString += Integer.toHexString(pos/16); returnString += Integer.toHexString(pos%16); return returnString; } private void setDependentData() throws ValueFormatException { // if connecting to WAN through modem, and DHCP service selected on Ethernet, // deliver also on WAN interface AirportInfoRecord configInterfaceRecord = airportInfo.get("waIn"); AirportInfoRecord dhcpLANRecord = airportInfo.get("laDS"); AirportInfoRecord dhcpWANRecord = airportInfo.get("waDS"); if (configInterfaceRecord.toString().equals("00000004")) { // connecting through modem: turn on DHCP service through WAN interface // if also configured to go through LAN interface if (dhcpLANRecord.toString().equals("01")) { dhcpWANRecord.setBytesFromString("01"); } else { dhcpWANRecord.setBytesFromString("00"); } } } private void performConsistencyChecks() throws ValueFormatException { // check that manual Ethernet config is being used if DHCP without NAT is selected // necessary since the WAN address configured becomes the gateway delivered by DHCP AirportInfoRecord wanConfigRecord = airportInfo.get("waCV"); AirportInfoRecord natRecord = airportInfo.get("raNA"); AirportInfoRecord dhcpWirelessRecord = airportInfo.get("raDS"); AirportInfoRecord dhcpLANRecord = airportInfo.get("laDS"); AirportInfoRecord dhcpWANRecord = airportInfo.get("waDS"); if (natRecord.toString().equals("00")) { // NAT off - wireless bridge mode // see if DHCP service is being provided if (dhcpWirelessRecord.toString().equals("01") || dhcpLANRecord.toString().equals("01") || dhcpWANRecord.toString().equals("01")) { // make sure manual Ethernet config is being provided; // if not, throw a ValueFormatException if (!wanConfigRecord.toString().equals("00000400")) { throw new ValueFormatException("Must use manual Ethernet configuration (Network Panel) when providing DHCP service (DHCP Panel)\nin transparent bridge mode (Bridging Panel)"); } } } // if using manual Ethernet config, check that base station IP address, router address and mask are consistent if (wanConfigRecord.toString().equals("00000400")) { byte[] wanIPBytes = airportInfo.get("waIP").getValue(); byte[] wanRouterIPBytes = airportInfo.get("waRA").getValue(); byte[] wanMaskBytes = airportInfo.get("waSM").getValue(); wanRouterIPBytes = maskBytes(wanRouterIPBytes, wanMaskBytes); wanIPBytes = maskBytes(wanIPBytes, wanMaskBytes); if ( !arraysEqual(wanRouterIPBytes, wanIPBytes) ) { throw new ValueFormatException("Router IP address inconsistent with base station IP address and subnet mask (Network Panel)"); } } // check that router address lies in DHCP subnet when providing DHCP service // look at different fields depending on whether providing NAT or doing transparent bridging // see if DHCP service is being provided if (dhcpWirelessRecord.toString().equals("01") || dhcpLANRecord.toString().equals("01") || dhcpWANRecord.toString().equals("01")) { byte[] dhcpBeginBytes = airportInfo.get("dhBg").getValue(); byte[] dhcpEndBytes = airportInfo.get("dhEn").getValue(); if (natRecord.toString().equals("00")) { // NAT off - wireless bridge mode // check WAN IP address, subnet mask; will have already checked above that // manual config is being used byte[] wanRouterIPBytes = airportInfo.get("waRA").getValue(); byte[] wanMaskBytes = airportInfo.get("waSM").getValue(); wanRouterIPBytes = maskBytes(wanRouterIPBytes, wanMaskBytes); dhcpBeginBytes = maskBytes(dhcpBeginBytes, wanMaskBytes); dhcpEndBytes = maskBytes(dhcpEndBytes, wanMaskBytes); if ( !arraysEqual(wanRouterIPBytes, dhcpBeginBytes) || !arraysEqual(wanRouterIPBytes, dhcpEndBytes)) { throw new ValueFormatException("DHCP range (DHCP Panel) inconssistent with router IP address and subnet mask (Network Panel)"); } } else { // NAT on // check LAN IP address, subnet mask byte[] lanIPBytes = airportInfo.get("laIP").getValue(); byte[] lanMaskBytes = airportInfo.get("laSM").getValue(); lanIPBytes = maskBytes(lanIPBytes, lanMaskBytes); dhcpBeginBytes = maskBytes(dhcpBeginBytes, lanMaskBytes); dhcpEndBytes = maskBytes(dhcpEndBytes, lanMaskBytes); if ( !arraysEqual(lanIPBytes, dhcpBeginBytes) || !arraysEqual(lanIPBytes, dhcpEndBytes)) { throw new ValueFormatException("DHCP range (DHCP Panel) inconsistent with base station private LAN IP address and subnet mask (Bridging Panel)"); } } } } private void setStaticData() throws ValueFormatException { // set read community password field AirportInfoRecord readCommunityRecord = airportInfo.get("syPR"); readCommunityRecord.setBytesFromString("public"); // Set community name into password field so base station will know what to use after reboot! // Find out if there's an entry in the main panel; if so, use this, otherwise use // current community name field AirportInfoRecord communityNameRecord = airportInfo.get("syPW"); String communityName = communityNameRecord.toString(); if (communityName.equals("")) communityName = password; communityNameRecord.setBytesFromString(communityName); } private int computeChecksum(byte[] fileBytes) { int checksum = 0; for (int i = 0; i < fileBytes.length; i++) { checksum += fileBytes[i]; } return checksum; } private String printHexBytes(byte[] bytes) { String returnString = new String(); for(int i = 0; i < bytes.length; i++) { returnString += hexByte(bytes[i]) + " "; if (((i+1)%16) == 0) returnString += "\n"; } return returnString; } private static boolean arraysEqual(byte[] a, byte[] b) { if (a.length != b.length) { return false; } else { for (int i = 0; i < a.length; i++) { if (a[i] != b[i]) return false; } } return true; } private static byte[] maskBytes(byte[] inBytes, byte[] mask) { byte[] maskedBytes = new byte[inBytes.length]; for (int i = 0; i < inBytes.length; i++) { maskedBytes[i] = (byte)(inBytes[i] & mask[i % inBytes.length]); } return maskedBytes; } private void setValue(StringTokenizer st) { if (!updateBaseStationEnabled) { System.out.println("Must retrieve or open settings first."); return; } if (!st.hasMoreTokens()) { System.out.println("Must supply a key and value (write )"); return; } String key = st.nextToken(); AirportInfoRecord element = (AirportInfoRecord)airportInfo.get(key); if (element == null) { System.out.println(key + ": No such element"); return; } if (!st.hasMoreTokens()) { System.out.println("Must supply a key and value (write )"); return; } String value = st.nextToken(); try { element.setBytesFromString(value); System.out.println(key + ": " + element.toString()); System.out.println(element.description); System.out.println(""); } catch (ValueFormatException e) { System.out.println("Problem with supplied value: " + e.getMessage()); } } private void getValue(StringTokenizer st) { if (!updateBaseStationEnabled) { System.out.println("Must retrieve or open settings first."); return; } if (!st.hasMoreTokens()) { System.out.println("All values:"); Enumeration keys = airportInfo.keys(); while (keys.hasMoreElements()) { String key = (String)keys.nextElement(); AirportInfoRecord element = (AirportInfoRecord)airportInfo.get(key); System.out.println(key + ": " + element.toString()); System.out.println(element.description); System.out.println(""); } return; } String key = st.nextToken(); AirportInfoRecord element = (AirportInfoRecord)airportInfo.get(key); if (element != null) { System.out.println(key + ": " + element.toString()); System.out.println(element.description); System.out.println(""); } else { System.out.println(key + ": No such element"); } } private void setBaseStationAddress(StringTokenizer st) { if (!st.hasMoreTokens()) { System.out.println("Current base station address: " + baseStationAddress); return; } baseStationAddress = st.nextToken(); System.out.println("Set base station address to " + baseStationAddress); } private void setPassword(StringTokenizer st) { if (!st.hasMoreTokens()) { System.out.println("Current password: " + password); return; } password = st.nextToken(); System.out.println("Set password to " + password); } private void printInfo() { System.out.println("AirPort Base Station CLI"); System.out.println("Command-line configuration utility for Snow and Extreme AirPort base stations"); System.out.println("Version 1.0, October 2003"); System.out.println(""); System.out.println("Jonathan Sevy"); System.out.println("http://gicl.mcs.drexel.edu/people/sevy"); System.out.println("jsevy@mcs.drexel.edu"); System.out.println(""); } private void printHelp() { System.out.println("Commands:"); System.out.println(""); System.out.println(" quit"); System.out.println(" q"); System.out.println(" quit the application"); System.out.println(""); System.out.println(""); System.out.println(" boot"); System.out.println(" b"); System.out.println(" reboot the base station"); System.out.println(""); System.out.println(""); System.out.println(" address "); System.out.println(" a "); System.out.println(" set address of base station"); System.out.println(""); System.out.println(""); System.out.println(" password "); System.out.println(" p "); System.out.println(" set password to use for accessing base station"); System.out.println(""); System.out.println(""); System.out.println(" retrieve"); System.out.println(" r"); System.out.println(" retrieve settings from base station"); System.out.println(""); System.out.println(""); System.out.println(" update"); System.out.println(" u"); System.out.println(" update settings to base station"); System.out.println(""); System.out.println(""); System.out.println(" save "); System.out.println(" s "); System.out.println(" save settings to specified file"); System.out.println(" will be prompted for file path"); System.out.println(""); System.out.println(""); System.out.println(" open"); System.out.println(" o"); System.out.println(" open saved settings from file;"); System.out.println(" will be prompted for file path"); System.out.println(""); System.out.println(""); System.out.println(" write "); System.out.println(" w "); System.out.println(" change the value for the specified key"); System.out.println(""); System.out.println(""); System.out.println(" get"); System.out.println(" g"); System.out.println(" get "); System.out.println(" g "); System.out.println(" get the value for the specified key,"); System.out.println(" or get the values corresponding to all keys"); System.out.println(" if no key specified"); System.out.println(""); System.out.println(""); System.out.println(" info"); System.out.println(" i"); System.out.println(" print out application info"); System.out.println(""); System.out.println(""); System.out.println(" help"); System.out.println(" h"); System.out.println(" print out this help message"); System.out.println(""); System.out.println(""); } private void processInput(String inputString) { StringTokenizer st = new StringTokenizer(inputString); if (!st.hasMoreTokens()) return; String command = st.nextToken(); char commandChar = command.charAt(0); switch (commandChar) { case 'a': { setBaseStationAddress(st); break; } case 'p': { setPassword(st); break; } case 'r': { ActionEvent event = new ActionEvent(this, 0, "retrieve data"); actionPerformed(event); break; } case 'u': { ActionEvent event = new ActionEvent(this, 0, "update base station"); actionPerformed(event); break; } case 'w': { setValue(st); break; } case 'g': { getValue(st); break; } case 'o': { ActionEvent event = new ActionEvent(this, 0, "open settings"); actionPerformed(event); break; } case 's': { ActionEvent event = new ActionEvent(this, 0, "save settings"); actionPerformed(event); break; } case 'q': { ActionEvent event = new ActionEvent(this, 0, "quit"); actionPerformed(event); break; } case 'b': { ActionEvent event = new ActionEvent(this, 0, "reboot base station"); actionPerformed(event); break; } case 'i': { printInfo(); break; } case 'h': { printHelp(); break; } default: { break; } } } public void run() { String inputString; System.out.println("AirPort Base Station Configurator CLI"); while (true) { System.out.print("> "); try { inputString = inStream.readLine(); processInput(inputString); } catch (Exception e) { System.out.println("Problem reading input: " + e); } } } public static void main(String args[]) { try { AirportBaseStationCLI theApp = new AirportBaseStationCLI(); theApp.run(); } catch (Exception e) {} } }