Changing the IP address on a Cisco switch

Cisco switches are a bit cryptic, but well documented. You can generally do just about anything with enough patience and Googling, but even simple configuration tasks can be difficult if you’re not familiar with the interface.

These are my 3 tips to configuring Cisco devices:

1. telnet
Always telnet or SSH to the switch to log on. Don’t use configuration utilities or a web interface, because everything that turns up on Google refers to the command-line interface.
2. enable
All of the fun options are hidden by default. Make liberal use of enable to do the serious work.
3. ?
Pressing ? pops up a list of ways you can finish off the current command.

For example: IP settings

The first step when moving around a used switch is to set it up for a different network. Here is where you will find the IP config:/p>

Log in:

telnet 10.1.x.x

Now enable the admin options:

example-switch>enable
Password: (type in your password)

Note that the prompt has changed from < to #. We can now change the IP and subnet mask of the switch:

example-switch#
interface vlan 1
ip address 10.1.x.x 255.255.x.x

Weird bug in iPad mail app

If you use the iPad mail app with Gmail, set up as an exchange account, you get a folder labelled [Gmail] which has your spam and starred mail folders.

But it turns out that an undocumented feature turns up if you also create a label called [Gmail]:

Labels and these special folders are different, so why are they getting mixed up? Or if they’re meant to be mixed- why are their two [Gmail] headings?

It seems to have slipped through the developers’ minds when they stored them in the same place, because the app behaves very inconsistently with this setup (variously duplicating labels and headings, and then leaving one list out of sync when changes are made).

Workaround: rename your labels:

I hope the developers are paying more attention next release- I’m only blogging this because there’s nothing much that google turned up about it.

Re-arranging columns on JTables

As I’m only new to Java UI work, I was surprised to see how easy it is to work with tables. A few things I’ve learnt:

  • JTables only show column headers if the table is placed inside a JScrollPane
  • It’s really annoying to drag-and-drop narrow, resizable columns, so turn off resizing.

I ended up with this user-rearrangeable table:

Basic code for this, thanks to Google Windowbuilder:

import java.awt.EventQueue;

import javax.swing.JFrame;
import javax.swing.JTable;
import javax.swing.table.DefaultTableModel;
import javax.swing.JScrollPane;

public class TableTestWindow {
	private JFrame frame;
	private JTable table;

	/**
	 * Launch the application.
	 */
	public static void main(String[] args) {
		EventQueue.invokeLater(new Runnable() {
			public void run() {
				try {
					TableTestWindow window = new TableTestWindow();
					window.frame.setVisible(true);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		});
	}

	/**
	 * Create the application.
	 */
	public TableTestWindow() {
		initialize();
	}

	/**
	 * Initialize the contents of the frame.
	 */
	private void initialize() {
		frame = new JFrame();
		frame.setBounds(100, 100, 525, 520);
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.getContentPane().setLayout(null);

		JScrollPane scrollPane = new JScrollPane();
		scrollPane.setBounds(12, 12, 460, 440);
		frame.getContentPane().add(scrollPane);

		table = new JTable();
		table.setFillsViewportHeight(true);
		scrollPane.setViewportView(table);
		table.setRowSelectionAllowed(false);
		table.setColumnSelectionAllowed(true);
		table.setModel(new DefaultTableModel(
			new Object[][] {
				{null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null},
				{null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null},
				{null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null},
				{null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null},
				{null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null},
				{null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null},
				{null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null},
				{null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null},
				{null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null},
				{null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null},
				{null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null},
				{null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null},
				{null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null},
				{null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null},
				{null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null},
				{null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null},
				{null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null},
				{null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null},
				{null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null},
				{null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null},
				{null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null},
				{null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null},
				{null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null},
				{null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null},
				{null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null},
				{null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null},
			},
			new String[] {
				"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"
			}
		) {
			/**
			 * Java coughs up warnings if we dont do this
			 */
			private static final long serialVersionUID = 1L;

			public Class getColumnClass(int columnIndex) {
				return String.class;
			}

			public boolean isCellEditable(int row, int column) {
				return false;
			}
		});

		for(int i = 0; i < 26; i++) {
			table.getColumnModel().getColumn(i).setResizable(false);
			table.getColumnModel().getColumn(i).setPreferredWidth(20);
		}

	}
}

Moodlification

Moodle is an alright piece of software, but if you ever try to discuss code, it will mangle it and create a horrible mess.

To mitigate this, write your posts in HTML view, and paste your code as it appears after running it through this moodlify.php script:

#!/usr/bin/php
<?php
/* moodlify.php -- whitespace fixes for code to post on moodle */
if(!isset($argv[1])) {
    echo "Usage: " . $argv[0] . " [file]\n";
    exit(0);
}
$file = $argv[1];
if(!file_exists($file) || !$code = file_get_contents($file)) {
    echo "Could not open file: ".$argv[1]."\n";
    exit(1);
}

/* Series of find-replaces to strip whitespace */
$code = htmlentities($code); /* < > " ' etc */
$code = str_replace("\t", "    ", $code); /* Tabs (4 spaces)*/

$code = str_replace("  ", "&nbsp;&nbsp;", $code); /* Double-spaces */
$code = str_replace("\n", "<br />", $code); /* Newlines */
$code = "<div style=\"padding-left:4em;\"><code>".$code."</code></div>\n";

/* Output options */
if(isset($argv[2])) {
    file_put_contents($argv[2], $code);
} else {
    echo $code;
}?>

And moodle will never mangle your code again!

Australian telephone tones

I made this set of telephone tones for an IP-PBX running asterisk. A lot of telephone-related audio files on the Internet seem to be recordings of actual beeps, so the quality is not great. Given that they are trivial to synthesise with Audacity, I made these:

To convert them to .ulaw format for asterisk (click here to download archive), I saved them as a .wav file and ran this bash script over the directory:

#!/bin/bash
for a in *.wav; do
    sox $a -r 8000 -t ul $a.ulaw
done

Making tones for other countries

Get a copy of the document "Various tones used in national networks (According to ITU-T Recommendation E.180) (03/1998)". It describes the tones used in most of the world. There is also a Cisco tones database, which has slightly different numbers.

Open up Audacity and use the Generate → Tones feature to make the first beep. Where there are multiple frequencies, make each frequency in different tracks, then merge them into a single track.

Use Generate → Silence to add the delay on the end, then continue from there

Afterward, you need to normalise the volume. Read the number from the volume Cisco tones database, then use Effect → Amplify, and set the new peak volume to the value shown — for the above tones this is -10 or -13dB.

HP Mini 210 review

I used a HP Mini 210 netbook for around 18 months. It costed just $329 AUD when I bought it, and had Windows XP and a 160GB hard drive.

I was originally interested in dual-booting Windows alongside Linux, but HP support proved to be very stubborn and would not provide recovery disks or the Windows licence key, so I ran it with only Linux instead.

Here are some features to note:

  • An SD card can be placed in the slot and stays out of the way.
  • The VGA port makes it suitable for doing presentations.
  • The battery life is not fantastic. Around 3 hours when new, and reduced to just 20 minutes or so by the first year.
  • Not particularly durable. The right-click stopped working on the mousepad after a while. I enabled mac-style gestures in Ubuntu to overcome this.
  • The ventilation is poor. It has no vents on the bottom at all, which is great for keeping the inside dry, but it has a very weak fan and does not handle heavy loads gracefully.

Some things you can do to improve it.

  • As soon as I found out how to open the case (video), I got an Intel SSD, which was quite expensive, but can be used in whatever netbook you have. It makes it quieter, faster, more power efficient, and removes the shock-sensitivity that plagues notebook hard-drives.
  • Consider getting a high-capacity battery. I replaced the dead standard size one with a cheap 3rd-party battery (link), but it could still do with more power.
  • The default install is filled with crapware. Either reinstall windows or run something else. GNU/Linux compatibility is great, and it also runs Windows 7 with no worries. It turns out your Windows XP key is inside the case, so open it up and use it.

It was a good laptop for the price, but not exceptionally fast, durable, or long in its battery life. This netbook should be purchased with the understanding that it will have a short life.

Alphanumeric phone numbers

Some popular phone numbers (eg. 1300-FOOBAR) are not numbers at all. If you are running a VOIP server then you may be interested in this snippet of PHP code to convert them into actual numbers, allowing users to dial by typing the more familiar form.

function normaliseTelephoneNumber($start) {
	/* Return an extension with numbers substituted in place of letters for dialling */
	$map = array(	"A" => "2", "B" => "2", "C" => "2",
			"D" => "3", "E" => "3", "F" => "3",
			"G" => "4", "H" => "4", "I" => "4",
			"J" => "5", "J" => "5", "L" => "5",
			"M" => "6", "N" => "6", "O" => "6",
			"P" => "7", "Q" => "7", "R" => "7", "S" => "7",
			"T" => "8", "U" => "8", "V" => "8",
			"W" => "9", "X" => "9", "Y" => "9", "Z" => "9",
			"+" => "+", "*" => "*", "#" => "#");
	$new = "";
	$hasnumber = false;
	$ext = strtoupper($start);
	for($i = 0; $i < strlen($ext); $i++) {
		$c = substr($ext, $i, 1);
		if(isset($map[$c])) {
			$new .= $map[$c];
			if($hasnumber == false) {
				/* No numbers before letters */
				return $start;
			}
		} else if(is_numeric($c)) {
			$new .= $c;
			$hasnumber = true;
		}
	}

	if($hasnumber == true) {
		return $new; /* Return numeric version as appropriate */
	} else {
		return $start; /* Leaves full words like "joe" or "bazza" unchanged */
	}
	return $new;
}

Note that this will only alter the number if it begins with numbers. This is to make sure that (at least in my case) the local network extensions don't get messed with:

echo normaliseTelephoneNumber("1300-FOOBAR")."n"; /* 1300366227 */
echo normaliseTelephoneNumber("mike")."n"; /* mike */