Scripts for Home Network

Thanks to broadband, most homes have a computer network. However, I often get a call from my parents on how their computer is not working. This, in their minds, is the root cause for a vast variety of issues they face. Wouldn’t it be nice if I could just sign into their computer and examine the problem? Do you know that with the availability of ‘broadband’, this is, indeed, viable?

Python has excellent modules for network programming—the key modules are socket and threading. However, to monitor a network, you will need to write small scripts for specific tasks and not worry about the intricacies of network programming. So, you can feel confident about encouraging your relatives to switch to Linux and offer support to them remotely!

To log in to a remote computer, you will need to know its IP address. On a broadband connection, the IP address is typically not fixed. Once your script finds the IP, you have to be informed of it. The easiest way is for the script to mail it to you.

Note: The code I’ll present has been tested on Fedora 9, but should work unchanged on Ubuntu and most other distributions as well.

Finding the IP address of the machine

Let us suppose the broadband modem is connected using the pppoe protocol, which is easier to handle. In this case the public IP is on the local system. You can find that out by using the /sbin/ifconfig command. You should see an entry like ppp0 in addition to entries for lo and eth0. You are interested in the ppp0 entry and, in particular, the line related to the ‘inet addr’ entry. So, here is our little script using the versatile subprocess module added in Python 2.4:

from subprocess import Popen, PIPE
def get_ip():
     proc = Popen(['/sbin/ifconfig','ppp0'], stdout=PIPE, stderr=PIPE)
    output = proc.communicate()
    if output[1] != "":
        response = 'Error: ' + output[1]
    else:
        response = [line for line in output[0].split('n') if 'inet addr:' in line]
    return str(response)
print 'The IP is ', get_ip()

The above script opens a pair of pipes to the ifconfig command and passes ‘ppp0’ as a parameter. The communicate method returns a tuple for the stdout and stderr of the command. In this instance, if you find that stderr is not empty there must have been an error; otherwise, you split the stdout on a new line and select the line containing the IP address.

A second possibility is that the modem is set up as a router. So, the external IP is on the router. The home models come with a Web interface to the modem. You can call the relevant page using the following script and then access the data:

from sgmllib import SGMLParser
class selector(SGMLParser):
def reset(self):
SGMLParser.reset(self)
self.data = []

def handle_data(self, data):
if data.count(‘.’) >= 3:
self.data.append(data.strip())

import urllib
def get_data(url):
page = urllib.urlopen(url)
parser = selector()
parser.feed(page.read())
parser.close()
return parser.data
def get_ip():
url = 'http://admin:[email protected]/hwhtml/summary/sum.html'
return str(get_data(url))

The ideas behind the above code were discussed in last month’s article on the subject. In the parser, we wrote a trivial method to extract any data that looks like a URL. The base URL is for a Huawei modem supplied by BSNL. The user name and the password can be passed as a part of the URL. The resulting output will look like what’s shown below:

['D.57.2.17', '59.94.245.130', '59.94.240.1', '255.0.0.0', '192.168.1.1', '255.255.255.0']

In this case, the external IP address for the modem is 59.94.245.130. This is followed by the IP address of the gateway and the netmask.

By the way, in the last article, we had used urllib2. Authentication handling is a little more complex and flexible using urllib2; so, the above code used urllib instead and saved about five lines of code. In case you would like to explore authentication using urllib2, see www.voidspace.org.uk/python/articles/authentication.shtml.

Sending the IP address by e-mail

Since Gmail is very common, let us use that as the example to send the IP address to yourself. Here is the script you will need to write:

import smtplib
recip = 'youremailid@yourdomain'
gmail_user = '[email protected]'
gmail_pw = 'password'
smtpserver = smtplib.SMTP("smtp.gmail.com",587)
smtpserver.ehlo()
smtpserver.starttls()
smtpserver.ehlo()
smtpserver.login(gmail_user, gmail_pw )
hdr = """To: youremail@yourdomain
From: [email protected]
Subject: IP Address
"""
msg = hdr +  'n' + get_ip() + 'nn'
smtpserver.sendmail(gmail_user, recip, msg)
smtpserver.close()

You use the Python module smtplib. Gmail requires a secure connection and that the sender be authenticated. The complete message consists of a header with a blank line separating it from the message text. The text content is added by calling one of the get_ip methods you have written above.

You can use the email module to send mime attachments—for example, screen dumps—and create just the right tools to help you support your friends and relatives.

Ping the hosts

In case there is a network problem, you will need to narrow down to the cause. A home may have a netbook (or a laptop), a main desktop, a modem and wireless router. The netbook may be accessing media files on the main desktop. You can ping to each device to know if it is working. The advantage of the subprocess command is that you can start ping on each device without waiting for it to finish. You can use threads without the need to manage the complexity.

from subprocess import Popen, PIPE
#  The addresses of localhost, the wirless router, the modem, the main desktop
hosts = ['127.0.0.1','192.168.0.1', '192.168.1.1', '192.168.0.100']
procs = []
for host in hosts:
procs.append(Popen(['ping','-c2', '-i',  host], stdout=PIPE))
for proc in procs:
proc.wait()
for proc in procs:
print proc.communicate()[0]

Create a list of devices/hosts in which you are interested. You then start a ping process for each of the hosts, with parameters limiting the number of times you ping while reporting only the summary information. Next, you wait for each process to get over and then process the results. If successful, you will see an output like the following:

PING 127.0.0.1 (127.0.0.1) 56(84) bytes of data.
--- 127.0.0.1 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1008ms
rtt min/avg/max/mdev = 0.083/0.102/0.122/0.021 ms

While for an unsuccessful case…

PING 192.168.0.100 (192.168.0.100) 56(84) bytes of data.
--- 192.168.0.100 ping statistics ---
2 packets transmitted, 0 received, +2 errors, 100% packet loss, time 3001ms

The nice thing about scripts is that you can keep adding them to your armoury as and when you come across problems. For example, even though the disk capacities are very large, a partition may still run out of space. It can be very hard to figure out why some applications or even the GUI desktop just refuses to start. Unresponsive or erratic DNS servers can create a frustrating browsing experience.

Scripts that monitor the systems can help you prevent problems before they arise, while sitting anywhere in the world with just a network connection. The downside is that your relatives may not realise your contribution or utility! This can be a serious issue in the corporate environment, but you can always write scripts so that your presence is indispensable—for example, by converting your scripts to one of the write-only scripting languages!

All published articles are released under Creative Commons Attribution-NonCommercial 3.0 Unported License, unless otherwise noted.
Open Source For You is powered by WordPress, which gladly sits on top of a CentOS-based LEMP stack.

Creative Commons License.