8 : Scripts for the Home Network

Thanks to broadband, most homes have a computer network. Diagnosing problems is harder and made worse by the expectations of relations! I would get calls from my parents – computer is not working. This was the key information for a vast variety of issues faced by them. Wouldn't it have been nice if I could just have signed into their computer and examined the problem. With the availability of even our so-called 'broadband', it is indeed viable.

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

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

The code has been tested on Fedora 9 but should work unchanged on Ubuntu and most distributions as well.

Finding the IP of the machine

Suppose the broadband modem is connected using the pppoe protocol. This is the easier case to handle. In this case the public IP is on the local system. You can find that out by using the command /sbin/ifconfig. 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 inet addr. 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, passing ppp0 as a parameter. 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 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 a script and 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:password@192.168.1.1/hwhtml/summary/sum.html'

return str(get_data(url))

The ideas behind the above code were discussed in last month's article. In the parser, you have written a trivial method to extract any data which 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:

['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 for the modem is 59.94.245.130. This is followed by the ip of the gateway and the netmask.

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

Sending the IP by Email

Since gmail is very common, you will use that as the example for sending the ip address to yourself. Here is the script you will need to write

import smtplib

recip = 'youremailid@yourdomain'

gmail_user = 'family.member@gmail.com'

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: family.member@gmail.com

Subject: IP Address

"""

msg = hdr + '\n' + get_ip() + '\n\n'

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, e.g. screen dumps, and create just the right tools to help you support your relations.

Ping the Hosts

Suppose there is a network problem, you will need to narrow down 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 could 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 will have used 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]

You 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 and reporting only the summary information. Next, you wait for each process to get over and then process the results. You will see an output like the following.

For a successful case:

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

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 which monitor the systems can help you prevent problems before they arise sitting anywhere in the world with a network connection. The downside is that your relations 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, e.g. by converting your scripts to one of the write-only scripting languages!


<Prev>  <Next>

Comments