Saturday, July 21, 2007

Auto-Rebooting ADSL Routers Using Telnet

Auto-Rebooting ADSL Routers Using telnet



Out here in India, MTNL, BSNL, and other state-owned
ISPs provide ADSL broadband Internet services to subscribers via their
landline telephone connection.The subscribers have umpteen choices among
different schemes to suit their pockets and hunger. Some people find
the DSL-NU (night unlimited) plan a right balance between
price and performance, which allows people to download data
for free between 00:00 hours and 08:00 hours. However, the only
requirement MTNL states for this facility is that each subscriber must
reboot his/her router exactly at the beginning and at the end of this
period.

This means that if one has a subscription to this plan, one must
reboot one's' ADSL router/modem at exactly these times:



  • 00:00 hours (midnight)



  • 08:00 hours (8 A.M.)


This simple procedure can be done using one of several ways some of which may
be:



  1. Using the Web interface provided by the router.



  2. Using telnet to log into the router and issuing a command such as
    reboot at the command shell.



  3. Using SNMP with a program or script that handles
    managing and configuring the device.


There may be more ways to pull this off, but we will be concentrating on
using telnet. Throughout the rest of this article we will be using
GNU/Linux to demonstrate our sessions. Experienced Windows users can
easily translate this information to Windows (neat trick to avoid
supporting Windows unless I'm getting paid to ;).


Logging into the router using telnet


I'm using a D-Link DSL-502T ADSL router/modem for our
examples here. Start a terminal and type the following commands. The
output should be self-explanatory (if it isn't, you're not at the right
place :).

$ telnet 192.168.1.1
Trying 192.168.1.1...
Connected to 192.168.1.1.
Escape character is '^]'.

BusyBox on (none) login: admin
Password:

BusyBox v0.61.pre (2005.05.30-08:31+0000) Built-in shell (ash)
Enter 'help' for a list of built-in commands.

# ls
bin etc proc usr var.tar
dev lib sbin var

# cat /proc/cpuinfo
processor : 0
cpu model : MIPS 4KEc V4.8
BogoMIPS : 149.91
wait instruction : no
microsecond timers : yes
extra interrupt vector : yes
hardware watchpoint : yes
VCED exceptions : not available
VCEI exceptions : not available

# cat /proc/version
Linux version 2.4.17_mvl21-malta-mips_fp_le (jenny@fd6e)
(gcc version 2.95.3 20010315 (release/MontaVista)) #70
Mon May 30 16:34:48 CST 2005

# exit
Connection closed by foreign host.

$
Using telnet I connect to the router device at 192.168.1.1 using the
port 23 on which the Telnet daemon on the router listens. You can see
that I'm not bluffing by looking at this output from Nmap:

Starting Nmap 4.20 ( http://insecure.org ) at 2007-07-21 21:53 IST
Interesting ports on 192.168.1.1:
Not shown: 1693 closed ports
PORT STATE SERVICE VERSION
21/tcp open ftp NetGear DG632 router ftpd
22/tcp open ssh
23/tcp open telnet BusyBox telnetd
80/tcp open http D-Link DSL-502T
...
Uptime: 0.179 days (since Sat Jul 21 17:36:11 2007)
Network Distance: 1 hop
Service Info: Devices: router, broadband router
...
Right. So you noticed nmap claims an SSH daemon
process is running on the router, but that is slightly skewed. There
isn't one really. The interesting part is the line right below that
one.

23/tcp open  telnet  BusyBox telnetd
The router is running a telnetd (Telnet daemon) process that is
listening on port 23. Now if you look at the line right below this
line you will notice the reason why you are able to view Web pages off your router.

80/tcp open  http    D-Link DSL-502T
Your router runs an HTTP daemon that listens on port 80.
It serves Web pages stored somewhere on the router.

You can also see that the router also runs an FTP server,
which may be used by the router to allow uploading files to the router.

(Now, now, now, don't get too excited, smartypants! There is as much
space on the router as is necessary to store one
nanomicromilli-sized(?!) strand of hair. This is not your regular
Google Mail inbox with Gigabytes of ever-growing free space.)


Rebooting the Router


All that telnet gyaan may have taught you how to log into your router.
But the meat is missing. Yes, yes, I know you're raring for an answer
to "How do I reboot my router?" Log into your router and type:

# reboot
...have more patience?
I don't think so. The reboot command reboots your router, but it
blocks. This is where that escape character finds use. Remember seeing
this line when you connected to the router?

Escape character is '^]'.
That is precisely what we will be using to break out of this block.
^] is equivalent to pressing and holding Ctrl and then pressing
]. In common parlance, it may be expressed as C-] or
Ctrl-]. Get on with it laddy; press this key sequence and watch
what happens.

telnet>
Wha? Another prompt? Yes, son. This is what we call the telnet
prompt. This is the prompt where you issue telnet commands. Type
close and press Return/Enter.

telnet> close
Connection closed.
$
Ah, the more familiar bash prompt appears and the Telnet
session ends.


"Right-o Mr. White Collar. What use is this information to me? I
thought all of this could be automated." you say. Patience, laddy.


Automate-It!


Expect is a tool for automating interactive terminal
sessions. Just the right thing for us to automate our little Telnet
session. The following script reboots your router provided the router
is configured to the default settings--the default user name and
password are admin and admin respectively, while the router
address is 192.168.1.1.

#!/usr/bin/expect
# Reboot router
# Copyright © 2007 Yesudeep Mangalapilly
#
# This file is part of RebootRouter.
#
# RebootRouter 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.
#
# RebootRouter 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 RebootRouter; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
# USA

spawn telnet 192.168.1.1 23

expect "login: "
send "admin\n"
expect "Password: "
send "admin\n"
expect "# "
send "reboot\n"

# We don't want expect to wait for more than a second
# to break out from blocks.
set timeout 1

# `reboot' blocks but we have expect wait for
# this prompt (which never appears) and time out eventually.
# od -c gives you character codes (type ^])
expect "# "
send "\035"

expect "telnet> "
send "close\n"
#expect "Connection closed."
exit
Nothing is exceptional about this script, except for one bit which
you might notice.


send "\035"
035 is octal for ^]. How did I find it? Good question. At your
terminal type:

$ od -c
^]

0000000 035 \n \n
0000003
$
I typed C-] followed by Return followed by another Return
followed by a C-d.


Generating the Script


I could use the above script alright, but what if I don't want
to edit the script because I could screw it up and then it wouldn't
work? To make it easier for users, I wrote a
Python script
that generates this script based on input, and just to add some more
features to it I tossed in generating Python and TST versions.

Just run this script as shown below:

$ python gen-rebootrouter.py

This program will generate rebootrouter scripts
for you tailored to your router configuration.

Please answer all the questions presented to you. You can press
the Enter/Return key on your keyboard without entering a value
to choose the default value (displayed in square brackets).

Router IP Address [192.168.1.1]:
Router Telnet Port [23]:
Router Username [admin]: root
Router Password [admin]:
Script Location [/home/you/Desktop/reboot-router]:
Generating /home/you/Desktop/rebootrouter.exp
Generating /home/you/Desktop/rebootrouter.py
Generating /home/you/Desktop/rebootrouter.tst

Running the Expect version


$ chmod +x rebootrouter.exp
$ ./rebootrouter.exp
Alternatively,

$ expect rebootrouter.exp

Running the Python version


You will need pexpect installed to use the Python version.

$ chmod +x rebootrouter.py
$ ./rebootrouter.py
Alternatively,

$ python rebootrouter.py

Running the TST version


You will need TST installed to issue this command.

C:\wherever\your\script\is> tst10.exe /r:rebootrouter.tst


Scheduling the Reboot on GNU/Linux


You can easily add a scheduled task to run a script at defined times.
Here's how you can set up a cronjob in accordance with the plan timings.

root@hostname:/root# export EDITOR='emacs -nw'
root@hostname:/root# crontab -e
# minute(0-59) h(0-23) day-of-month(1-31) month(1-12) day-of-week(0-6) command
0 0,08 * * * /usr/local/bin/rebootrouter.exp
Gnome Schedule is a graphical interface for cron
that you can use if you prefer.


Conclusion


While all of this mumbojumbo does make life a bit easier for us
subscribers, there are other details to ponder about:


  1. MTNL specifies time as 00:00 hours and 08:00 hours but does not
    tell us the time zone (we could assume IST but we do not know
    how MTNL synchronizes time).

    $  curl --head http://register.mtnl.net.in
    HTTP/1.1 200 OK
    X-Powered-By: Servlet/2.4
    ETag: W/"2997-1180610225437"
    Last-Modified: Thu, 31 May 2007 11:17:05 GMT
    Content-Type: text/html
    Content-Length: 2997
    Date: Sat, 21 Jul 2007 19:28:17 GMT
    Server: Sun-Java-System/Application-Server
    Can we use this information to synchronize time?




  2. The above scripts are not good examples of security. In fact, there
    is little security in the way they have been written. The passwords
    are visible in plain unencoded text to anybody who wishes to view
    them!




  3. Scripting telnet may be appropriate if you have one or two
    routers. What does one do when one has a dozen or more?




That being said, I'm working on a somewhat better version suited more
toward the liking of administrators, which has a lot more bells and
whistles than these scripts. It'll be out when the time is ripe.

That's it for now. Happy hacking.

Sunday, February 25, 2007

Programming Fonts

Need a good mono-space font to use when writing and reading code?
During the years that I have been programming, I have come across a few excellent fonts that I regularly use when writing code. Two of them come from Apple, one from Microsoft's typography, and one from Bitstream. There are others that I experiment with to from time-to-time, but I don't generally tend to stick with them.

What are they?
In order of personal preference:
  1. Monaco (Apple; commercial)
  2. Consolas (Microsoft; commercial)
  3. Anonymous (Applet; free)
  4. Vera Sans Mono (Bitstream; free)
Previews:
Short descriptions and preview of these fonts follow.

Monaco, 9p
t on Linux.
Monaco comes with OS X and looks pretty slick.


Consolas, 11pt on Linux.
This font seems to be an enhanced version of Lucida Monospace.
It suits the terminal and your code.


Anonymous, 9pt on Linux.
Anonymous is a well-designed font for code. A slashed-zero is a highlight of this font.


Vera Sans Mono, 10pt on Linux.
Vera Sans Mono comes for free from Bitstreams foundry that was donated to the GNOME project.



I seem to like Monaco more than any other font for coding.

Thursday, May 25, 2006

MinGW What?

From the MinGW Website:

A collection of freely available and freely distributable Windows specific header files and import libraries combined with GNU toolsets that allow one to produce native Windows programs that do not rely on any 3rd-party C runtime DLLs.

Why do I need it?

MinGW offers you native Windows versions of the GNU Compiler Collection (GCC) and several other developer tools that help you create applications using C, C++, Objective-C, Ada, Fortran, etc. for free. You no longer need to worry about purchasing an expensive compiler suite for your development purposes. GCC is known to work on several platforms and architectures, and is one of the most standards-compliant (not entirely in some areas) compiler collections available.


How do I install it?

Apparently, this is the one question that I find a lot of people asking. The reason is that the MinGW downloads section appears overly complicated to the absolute beginner. Fear not, however, my dear friend--installing and getting MinGW to work is not as difficult as it might appear to be.

There are two approaches to installing MinGW:
  1. Web installer guided installation
  2. Manual installation
1. Web Installation

Using the web installer is the easiest way to install MinGW on your Windows system. All you need to do is download the installer program from www.mingw.org, run the program, and follow the instructions presented. I recommend using this method to people that are new to MinGW. However, note that the web installer does not install everything that MinGW has to offer.

The current installer program is available here:
http://prdownloads.sf.net/mingw/MinGW-5.0.2.exe?download

(Please see the "Telling Windows about MinGW" section below for post-install configuration instructions.)

2. Manual Installation

Manual installation is not for the faint of heart, right? Wrong! It's extremely easy to do, but it is easy to screw up too. Do not be afraid because you can always start afresh.

Before I tell you what you need to download, let's look at the several tools that MinGW has to offer to you.

  1. Compilers/Interpreters for several languages including C, C++, Objective-C, Java, Ada, and Fortran.
  2. Debuggers and crash reporting tools.
  3. Assembler/Disassembler.
  4. Tools to play with binary executables and object files (GNU Binutils).
  5. A cut-down UNIX shell like environment called MSYS.
  6. Some GNU utilities.
  7. Windows API header files.
  8. Build tools including GNU make, autoconf, automake, and libtool.
  9. Some MinGW-specific tools.
If you do not know what these tools are, no worries. We just need to get some of them installed properly and we'll be good to go.

MinGW makes three types of release:

  1. Candidate - The future
  2. Current - The present
  3. Previous - The past

I generally settle for the candidate release, but for a production environment you might need to choose a rather stable and well-tested release (ask your project coordinator/systems administrator for help with this). Within each release there are two types of compressed archives: source (src) tarballs and binary (bin) tarballs. You most certainly need the binary tarballs.

Tar files (.tar) are commonly referred to as tarballs. These can be compressed by tools like gzip or bzip2 to create compressed tarballs (.tar.gz or .tar.bz2).
Downloading MinGW

The files that you will need to get are enlisted below. (Please note that the version numbers displayed here may not match those on the MinGW download page--use your judgment and proceed.)

gcc-core-3.4.5-20060117-1.tar.gz - (required) The core gcc compiler.
gcc-g++-3.4.5-20060117-1.tar.gz - C++ compiler and libraries
gcc-objc-3.4.5-20060117-1.tar.gz - Objective-C compiler and runtime
gcc-java-3.4.5-20060117-1.tar.gz - Java compiler and associated libraries
gcc-g77-3.4.5-20060117-1.tar.gz - Fortran 77 compiler
gcc-ada-3.4.5-20060117-1.tar.gz - Ada compiler
binutils-2.16.91-20060119-1.tar.gz - Linker, Assembler, Disassembler, tools to play with object and executable files, etc.
mingw-utils-0.3.tar.gz - General GNU tools built specifically for use with MinGW.
w32api-3.6.tar.gz - Windows API header files.
gdb-5.2.1-1.exe - GNU Debugger (GDB)
mingw32-make-3.80.0-3.exe - GNU Make

What next?

  1. Once you have obtained all these files, place all of them into a single directory.
  2. Create a directory called "mingw" in this directory.
  3. Extract the contents of the files ending with .tar.gz in their names into the mingw directory. (If you are asked to overwrite files, please choose to.)
  4. Copy this directory over to your system root drive partition (C: for most folks) so the path where MinGW is located now becomes X:\mingw, for example, where X is your system root drive letter.
  5. Run the GDB and MinGW32-Make installers and install them in X:\mingw.
That's it? Not yet, smartypants. We have one step remaining. The most important one that is common to both the web installer and the manual installation. That is the subject of the next section.

Telling Windows About MinGW
Have you ever wondered how when you type and execute a particular command in the Command Window, Windows figures out exactly where the executable for that command is located and runs it? Well, you don't need to be a rocket scientist to figure out that this information must have been told to Windows by someone and that it is stored somewhere.

In our case, here, you're the one that tells Windows where MinGW is installed and to do just that, you need to edit the system registry (*shudder*). Not really. I was just kidding. All you need to do is edit the environment variable, Path, and append X:\mingw\bin to it--remember that ';' is used as a path separator on Windows.

Very Important Note: I won't be teaching you how to set up an environment variable. You can ask Google, Luke! Or, perhaps, I can write another blog entry describing how to work with environment variables in the near future.

How do I use it?

Good question. We are going to use the GCC C compiler in our simple example that follows. Create a text file and add the following code to it. Save the file with the name 'first.c' sans quotes.


#include <stdio.h>

int
main (void)
{
puts ("Ah! My program compiles and runs\n");
return 0;
}



Now open a command window and 'cd' to the directory where you saved your source file. Then type out this command.


C:\home\code\c> gcc -ansi -pedantic -W -Wall -O2 -o first first.c

C:\home\code\c> first.exe
Ah! My program compiles and runs


C:\home\code\c>


Your program works and so does MinGW. *drumroll* That's it for now, though. Adios.