/* * Subnetting.java -- Java Applet/application * Copyright (C) 2000 Petteri Kettunen * * 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 * */ /* * $Revision: 1.2 $ * * Comments? Suggestions? -> petterik@iki.fi */ import java.applet.Applet; import java.awt.*; import java.awt.event.*; import java.io.*; import java.lang.*; import java.net.*; import java.util.StringTokenizer; import java.math.*; public class Subnetting extends Applet implements ItemListener, ActionListener { TextArea taResult; TextField tfIP; Choice chNWBits, chSNBits; Checkbox cbZeroSN; Button calcButton; int iNWBits = 0, iSNBits = 0, iDefaultNWBits = 24; boolean bDefaultZeroSN = false; // affects only Applet final static String sVersion = "0.9b"; // applet inits public void init() { setBackground(Color.white); chNWBits = new Choice(); chSNBits = new Choice(); taResult = new TextArea("", 24, 80); taResult.setFont(new Font("Courier", Font.PLAIN, 12)); taResult.setText(getSplashText()); for (int i = 0; i <= 32; i++) { chNWBits.addItem("" + i); chSNBits.addItem("" + i); } if (iDefaultNWBits > 0 && iDefaultNWBits <= 32) { chNWBits.select(iNWBits = iDefaultNWBits); } //setLayout(new GridLayout(4)); add(tfIP = new TextField("127.0.0.1", 18)); add(new Label("NW Bits")); add(chNWBits); chNWBits.addItemListener(this); add(new Label("SN Bits")); add(chSNBits); chSNBits.addItemListener(this); add(cbZeroSN = new Checkbox("zero subnet", bDefaultZeroSN)); add(calcButton = new Button("Calculate")); calcButton.addActionListener(this); add("South", taResult); } public String getAppletInfo() { String info = "Subnetting.java " + sVersion + "\nby Petteri Kettunen "; return info; } /* TODO... public String[][] getParameterInfo() { String[][] info = { {"IMAGE_DIR", "string", "Image directory relative to Applet."}, }; return info; } */ public void start() { //panel.start(); } public void stop() { //panel.stop(); } public void destroy() { //remove(panel); //remove(controls); } private static String getSplashText() { return "'Subnetting.java' version " + sVersion + " Copyright (C) 2000 Petteri Kettunen.\n\n'Subnetting.java' comes with ABSOLUTELY NO WARRANTY. This is free software,\nand you are welcome to redistribute it under certain conditions; see the\nsource code or URL http://www.iki.fi/petterik/ for details.\n\n"; } // octet to 'bit' string private static String o2b(int iOctet) { String res = ""; int val = iOctet; for (int t = 128; t > 0; t /=2) { if (val >= t) { res = res.concat("1"); val -= t; } else { res = res.concat("0"); } } return res; } // convert four bits to hex string private static String b2h(String sBits) { String res; int val = b2o(sBits); switch(val) { case 15: res = "f"; break; case 14: res = "e"; break; case 13: res = "d"; break; case 12: res = "c"; break; case 11: res = "b"; break; case 10: res = "a"; break; default: res = "" + val; } return res; } // 'bit' string to octet private static int b2o(String sBits) { if (sBits.length() == 4) { return Integer.valueOf(sBits.substring(0, 1)).intValue() * 8 + Integer.valueOf(sBits.substring(1, 2)).intValue() * 4 + Integer.valueOf(sBits.substring(2, 3)).intValue() * 2 + Integer.valueOf(sBits.substring(3, 4)).intValue(); } return Integer.valueOf(sBits.substring(0,1)).intValue() * 128 + Integer.valueOf(sBits.substring(1, 2)).intValue() * 64 + Integer.valueOf(sBits.substring(2, 3)).intValue() * 32 + Integer.valueOf(sBits.substring(3, 4)).intValue() * 16 + Integer.valueOf(sBits.substring(4, 5)).intValue() * 8 + Integer.valueOf(sBits.substring(5, 6)).intValue() * 4 + Integer.valueOf(sBits.substring(6, 7)).intValue() * 2 + Integer.valueOf(sBits.substring(7)).intValue(); } // subnet mask: network and subnet bits 1, host bits 0 private static String getNetmaskStr(int iNW, int iSN) { String res = ""; int n = iNW + iSN, i = 0; while (i++ < n) { res = res.concat("1"); } while (i++ <= 32) { res = res.concat("0"); } return res; } // mask IP with network mask private static String getNetwork(String sIPBits, String sNWMaskBits) { String res = ""; int i = 0; while (i < 32) { if (sNWMaskBits.substring(i, i+1).equals("1")) { res = res.concat(sIPBits.substring(i, i+1)); } else { res = res.concat("0"); } i++; } return res; } // subnet address: all host bits are 0 private static String getSN(String sNWBits, String sSNBits) { String res = sNWBits + sSNBits; while (res.length() < 32) { res = res.concat("0"); } return res; } // broadcast address: all host bits are 1 private static String getBcast(String sNWBits, String sSNBits) { String res = sNWBits + sSNBits; while (res.length() < 32) { res = res.concat("1"); } return res; } // first host: subnet address + 1 private static String getFirstHost(String sSN) { return sSN.substring(0,24) + o2b(b2o(sSN.substring(24)) + 1); } // last host: broadcast - 1 private static String getLastHost(String sBcast) { return sBcast.substring(0,24) + o2b(b2o(sBcast.substring(24)) - 1); } // make IP to human-readable format private static String decodeIP(String bits) { String [] octets = new String[4]; String [] hex = new String[8]; octets[0] = bits.substring(0,8); hex[0] = b2h(octets[0].substring(0,4)); hex[1] = b2h(octets[0].substring(4)); octets[1] = bits.substring(8,16); hex[2] = b2h(octets[1].substring(0,4)); hex[3] = b2h(octets[1].substring(4)); octets[2] = bits.substring(16,24); hex[4] = b2h(octets[2].substring(0,4)); hex[5] = b2h(octets[2].substring(4)); octets[3] = bits.substring(24,32); hex[6] = b2h(octets[3].substring(0,4)); hex[7] = b2h(octets[3].substring(4)); return octets[0] + "." + octets[1] + "." + octets[2] + "." + octets[3] + " " + hex[0] + hex[1] + hex[2] + hex[3] + hex[4] + hex[5] + hex[6] + hex[7] + " " + b2o(octets[0]) + "." + b2o(octets[1]) + "." + b2o(octets[2]) + "." + b2o(octets[3]); } // the main calculator function private static String calcSubnetting(String sIP, int iNW, int iSN, boolean bZeroSN) { int i, nSubnets; String res = ""; String [] octet = new String[4]; StringTokenizer st; int [] iOctet = new int[4]; // catch some pathological cases... if (iNW < 0) { return "ERROR: negative number of network bits\n"; } if (iSN < 0) { return "ERROR: negative number of subnet bits\n"; } if (iNW == 0) { return "ERROR: network bits equals to zero - no network?\n"; } if ((iNW + iSN) > 32) { return "ERROR: the sum of network and subnet bits is over 32\n"; } // get the IP try { st = new StringTokenizer(sIP, "."); for (i = 0; i != 4; i++) { octet[i] = st.nextToken(); iOctet[i] = Integer.valueOf(octet[i]).intValue(); } } catch (Exception e) { return "ERROR: Invalid IP address string '" + sIP + "'\n"; } // extract and check the values of octets for (i = 0; i != 4; i++) { if (iOctet[i] < 0 || iOctet[i] > 255) { return "Invalid IP address '" + sIP + "' -- all octets should be in range 0-255\n"; } } String nmStr = getNetmaskStr(iNW, iSN); String nwMaskStr = getNetmaskStr(iNW, 0); String ipBits = o2b(iOctet[0]) + o2b(iOctet[1]) + o2b(iOctet[2]) + o2b(iOctet[3]); String nwStr = getNetwork(ipBits, nwMaskStr); int nSubs = (int)Math.pow(2, iSN); if (iSN == 0) { // subnet calculation will not take place nSubnets = 0; } else { if (bZeroSN) { i = 0; nSubnets = nSubs; } else { nSubs -= 1; i = 1; nSubnets = nSubs - 1; } } res = res.concat("\nnetwork bits " + iNW + ", subnet bits " + iSN + ", zero subnet " + (bZeroSN ? "on" : "off") + ", total subnets " + nSubnets + "\n\n"); res = res.concat("network " + decodeIP(nwStr) + "\n"); res = res.concat("network mask " + decodeIP(nwMaskStr) + "\n"); //res = res.concat("IP address " + decodeIP(ipBits) + "\n"); res = res.concat("netmask " + decodeIP(nmStr) + "\n\n"); String stub = nwStr.substring(0, iNW); // catch this here so the applet can be used for checking netmask if (iSN == 0) { res = res.concat("WARNING: subnet bits equals to zero - no subnetting?\n"); return res; } if (bZeroSN == false && iSN == 1) { res = res.concat("ERROR: one subnet bit while zero subnet not allowed\n"); return res; } while (i < nSubs) { String sSubnetPart = o2b(i).substring(8 - iSN); String snAddress = getSN(stub, sSubnetPart); String sFirstHost = getFirstHost(snAddress); String bcAddress = getBcast(stub, sSubnetPart); String sLastHost = getLastHost(bcAddress); res = res.concat(" subnet " + i + ":\n"); res = res.concat(" network " + decodeIP(snAddress) + "\n"); res = res.concat(" first host " + decodeIP(sFirstHost) + "\n"); res = res.concat(" last host " + decodeIP(sLastHost) + "\n"); res = res.concat(" broadcast " + decodeIP(bcAddress) + "\n"); i++; } return res; } // check for choice events public void itemStateChanged(ItemEvent e) { if (e.getSource() == chNWBits) { iNWBits = Integer.valueOf(chNWBits.getSelectedItem()).intValue(); } else if (e.getSource() == chSNBits) { iSNBits = Integer.valueOf(chSNBits.getSelectedItem()).intValue(); } } // check for valid button events public void actionPerformed(ActionEvent ev) { String buttonLabel = ev.getActionCommand(); if (buttonLabel.equals("Calculate")) { taResult.setText(calcSubnetting(tfIP.getText().trim(), iNWBits, iSNBits, cbZeroSN.getState())); } } // entry point of the program when run as application public static void main(String[] args) { if (args.length != 4) { System.out.println("usage: java Subnetting "); System.exit(1); } String sIP = args[0]; int iNW = Integer.valueOf(args[1]).intValue(); int iSN = Integer.valueOf(args[2]).intValue(); int snflag = Integer.valueOf(args[3]).intValue(); System.out.print(getSplashText()); System.out.print(calcSubnetting(sIP, iNW, iSN, (snflag != 0))); } }