Logo Search packages:      
Sourcecode: airport-utils version File versions  Download package

AirportBaseStationConfigurator.java

/*
 * AirportBaseStationConfigurator
 *
 * Copyright (C) 2000, Jonathan Sevy <jsevy@mcs.drexel.edu>
 *
 * 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)
            {}
      }
      

}

Generated by  Doxygen 1.6.0   Back to index