Updated DNS Zone Update tool for Hostmonster

A couple years ago I posted a slightly modified script for hostmonster to update the dns zone entries for subdomains. It used mechanize and ruby. However, since then my script broke as hostmonster made some changes to their backend. Another guy made some changes that seemed to work for a while, but again it has broken. My previous post about this is here.

The culprit seems to be the mixture of javascript / ajax and the fact that hostmonster returns an empty page when you append the /ajax onto the dnszone url. No worries though, I found another way to do it.

Using Watir and Headless, it is possible to achieve the same functionality.

You need to add a few things to ubuntu to make it work:
sudo apt-get install ruby ruby-dev xvfb
sudo gem install watir
sudo gem install headless

Here’s the updated script (note, you can still use the same cron jobs and ip scripts etc. from the previous two techniques.:

#!/usr/bin/ruby
(more…)

Hostmonster auto update IP address of subdomain

With my Hostmonster account, I host this website with my www.jasonernst.com domain, but I also have many other machines that are referred to with subdomains. For example, dev.jasonernst.com is my home machine and lab.jasonernst.com is my office machine at school.

However, as you can imagine with the home machine in particular the IP is prone to change occasionally since it is given from the ISP using DHCP. So I searched around for some script to be able to change the zone file in Hostmonster since this controls the IP addresses of all my subdomains.

** Of course the obvious and easy way to do this is with some kind of dyndns account, but I’m picky and like to have everything working under my own domain 😛

I was looking for some type of SSH script way to do it, but it looks like there is no easy way to do this, but I found a ruby script here: http://deathwarrior.wordpress.com/ which allows me to do what I want. Unfortunately the script was written a little while ago and some of it needs to be changed a bit to work.

The first part is the required libraries that must be installed. This has changed because the ruby-mechanize library does not seem to be found in the Ubuntu 12.04 repos. This should do the trick though:

sudo apt-get install libwww-mechanize-ruby ruby-json ruby

The other problem is in the ruby script itself. It seems verify_mode does not exist anymore, so just comment that line out. Another problem is the user-agent which does not seem to be found in the version I was using with Ubuntu. So you can change that to “Windows IE 7” and it should fix it. Here is the code with the changes:


#!/usr/bin/env ruby

require 'mechanize'
require 'json'

USERNAME = 'MY_USERNAME'
PASSWORD = 'MY_PASSWD'
DOMAIN = 'positrones.net'
SUBDOMAIN = 'my_subdomain'
ADDRESS = '0.0.0.0' # If nil then try to get automagicaly

URLS = {
'login' => 'https://login.hostmonster.com/?',
'drecords' => 'https://my.hostmonster.com/cgi/dm/zoneedit/ajax'
}

USER_AGENT = 'Windows IE 7'

m = Mechanize.new do |a|
#a.verify_mode = OpenSSL::SSL::VERIFY_NONE
a.user_agent_alias = USER_AGENT
end

def get_ip
r = Net::HTTP.get('jasonernst.com', '/ip.php')
ip = r.match(/\d{1,4}\.\d{1,4}\.\d{1,4}\.\d{1,4}/)

ip[0].to_s
end

# Do the login stuff
print "Checking user and password... "
page = m.get( URLS['login'] );
form = page.form_with( :name => 'theform' )
form['login'] = USERNAME
form['password'] = PASSWORD
send_button = form.button_with(:value => 'Login')
form.click_button(send_button)
page = page.links[0].click
puts "done!"

# Edit the DNS Zone
page = page.link_with(:text => 'DNS Zone Editor').click
print "Getting old zone records... "
json = JSON.parse( m.post( URLS['drecords'], {'op' => 'getzonerecords', 'domain' => DOMAIN} ).body )
puts "done!"

print "Trying to get subdomain old info... "
json['data'].each do |r|
if r['name'] == SUBDOMAIN
print "done!\nSaving new address[#{r['address']} => #{ADDRESS||get_ip}]... "
json = m.post( URLS['drecords'], {'op' => 'editzonerecord',
'domain' => DOMAIN,
'name' => SUBDOMAIN,
'orig__name' => SUBDOMAIN,
'address' => ADDRESS||get_ip,
'orig__adress' => r['address'],
'ttl' => r['ttl'],
'orig__ttl' => r['ttl'],
'Line' => r['Line'],
'type' => r['type']}
)
json = JSON.parse(json.body)

if( json['result'] == 1 )
puts "done!\nAddress changed succesfully!"
Kernel::exit(0)
else
puts "\nAn error has ocurred trying to save new address :("
Kernel::exit(1)
end
end
end

puts "The subdomain #{SUBDOMAIN} cannot be found!"
Kernel::exit(1)

The last thing that should be done is a server page somewhere for this code to find out it’s own IP address. All the page should return is the IP address itself, not any HTML. You can leave the default in the script which will use my IP script, or you can make your own. It’s as simple as this:

And one more thing, if you are so inclined is to add the script as a chronjob. I have mine set to run every hour, but you can do it more or less often according to your preferences.

crontab -e

I named put my script in a /scripts/ folder I made and named it “hostmonster-auto-ip.sh”

So the crontab entry is:

@hourly /scripts/hostmonster-auto-ip.sh

OpenGL Console Library for Blackberry Native SDK (Playbook)

Over the break, I decided to try my hand at some Blackberry native SDK programming since I recently got a playbook. I looked around the App World and noticed there weren’t any telnet/ssh tools available for free (that worked the way I wanted) so I thought this would be a good starter project.

However, for the look I wanted, I wanted to maximize the screen space for the console application to show as much text as possible and worked off the hello world example on the SDK webpage. Essentially, the simple “library” (note: library is used very loosely here) initializes the display, shows the keyboard and supports some simple output using putch and puts functions that I implemented. It can also show a blinking cursor and user input at a prompt. In case someone else can use the code I have made it available. Check back soon to see the source for the telnet portion of the app I made as well or look for it on the App World.

Simple Telnet - Example Application
Simple Telnet – Example Application using the conosole library

In order to use the library, you need to make use of the bbutil.c and bbutil.h files that are included in many of the examples provided by RIM. I have provided them here alongside my own code so that it is easier to follow along. I also provide two more files: glconsole.c and glconsole.h. You just need to #include “glconsole.h” in your source in order to use the library. All of the functions available to you are listed in the “glconsole.h” file as well. I will go over the important ones in this article.

First is gl_init(). This function initializes the library, the screen, font etc. This function should be called before using anything else in the library. Similarly, gl_cleanup() is used to free memory and should be called before your app is terminated.

After initialization, you may now use the puts and putch functions to display characters to the screen. gl_putch(char c) takes a single character and displays it onto the screen. It can handle newlines which are represented as ‘\n’ and tabs which are represented as ‘\t’. Backspaces by user input is handled as a ‘\b’ character. This is similar to how people on The osdev.rg website often handle character output in their custom operating systems. I’m not sure how it relates with normal c standards, but I imagine it is similar. Eventually I hope to implement a printf() type of function, but at the moment the putch() and puts() functions serve what I am doing well enough. Note: puts() is the same as putch() but instead takes a (char *) ie) a string. The string should also be null-terminated, or it will just continue until it hits a null character. The characters are automatically scrolled when the bottom of the screen is reached.

The only other really important function is gl_render(). This function is what should be called everytime the screen needs to be refreshed. This is usually in a for loop within your main() function in your app.

It is also possible to resize the screen using the gl_resize() function. By default the screen starts at 80X29 which is the maximum size with no virtualkeyboard showing, at the font size I selected. When the keyboard shows up, it fits 80×14. In some sample code I’ll also show how keyboard input can be handled, how to blink the cursor and how to detect when the keyboard is shown or hidden.

For the rest of this guide, I’ll assume you are using the QNX Momentix IDE available from RIM’s developer website. To start, create a new project by going to File->New Blackberry Tablet OS C/C++ Project. Name it whatever you like, click next. Then choose the C language, and empty Application Project. You can now drag the gl_console.c, glconsole.h, bbutil.c and bbutil.h files into the src folder within the IDE to include them. You will probably want to copy the files and not link them when it asks. Before compiling, there are several libaries which must be linked to the project. You can do this by right clicking your project, going to properties. Then go to C/C++ General->Paths and Symbols->Libraries. Here you can add libraries. Each time you add one, be sure to check “add to all Configurations” so that you don’t need to do this again if you change from a device-debug to device-release build. The following libraries should be included:

  • bps
  • EGL
  • GLESv1_CM
  • freetype
  • png

Now that all this is setup, it is possible to start you main() function and use the library. If you like you can right click on your src folder and click “new file” and create a main.c file or whatever you like to name it. While this isn’t the typical way you would include a library into a project, this way lets you edit the library source to your liking in case you want to further extend it.

The following example shows a skeleton of what is required to get the code to display some text:

#include /* EXIT_FAILURE */
#include /* NULL */
#include /* BPS_SUCCESS */
#include /* screen_event_get_event() */
#include /* NAVIGATOR_EXIT */
#include "glconsole.h"

void handleScreenEvent(bps_event_t *event);

int main(int argc, char * argv[])
{
int exit_application = 0;

if(EXIT_SUCCESS != gl_init())
{
fprintf(stderr, "error init\n");
return 0;
}

gl_puts("Hello gl console world!\n");

for(;;)
{
bps_event_t *event = NULL;
if (bps_get_event(&event, 0) != BPS_SUCCESS)
return EXIT_FAILURE;

if (event)
{
int domain = bps_event_get_domain(event);

if (domain == screen_get_domain())
handleScreenEvent(event);
else if ((domain == navigator_get_domain()) && (NAVIGATOR_EXIT == bps_event_get_code(event)))
exit_application = 1;

if (exit_application)
break;
}
gl_render();
}

gl_cleanup();
return 0;
}

void handleScreenEvent(bps_event_t *event)
{
/* do normal event handling here, see other bb examples */
}

The key parts are calling gl_init() which initializes the library. Then within the main loop, the gl_render() function should be called which will actually render the text. Finally gl_cleanup() should be called before termination to properly free memory.

In the near future I plan to add some support to handle ansi encoded text (specifically for my telnet application) so that it can display colours and move the cursor around the screen using this standard.

Here are the files:
glconsole.h
glconsole.c

Creating a Bluetooth Access point (NAP) in Ubuntu 11.10

A Bluetooth NAP is similar to a Wi-Fi access point. In this case, we will be using NAP to share an Internet connection to another computer with Bluetooth. It is supposed to be able to support 7 or 8 devices connected at once in this manner. Eventually my personal goal is to use this in conjunction with a Wi-Fi connection to get slightly more speed at once or for some redundancy to help achieve a more ubiquitous/pervasive connection.

It turns out what should be a simple process is a bit tricky in Ubuntu. You would expect to be able to create an IP access point fairly easily so that you can share your Internet connection to other devices using Bluetooth. (It turns out it may be possible with Blueman – http://blog.larsstrand.org/2009/04/sharing-internet-connection-over.html, but I’ve never had any luck with setting it up this way.) Here’s some of the steps and resources I used to get it to work. I am using one laptop with a generic usb dongle and another toshiba netbook with built-in Bluetooth for this.

Before anything is started, you need to make sure the devices are paired and trusted with one another. I found the easiest way to get this to work is with blueman (it is in the Ubuntu repos). Also it seems to work better if you initiate the pairing from the client (the computer not sharing the connection).

First, you need a bridge interface. This is easy enough in Ubuntu, by editing the /etc/network/interfaces file. If the interface you wish to share is eth0 (if you want to share a Wi-Fi connection instead, you could switch this with something like wlan0 or whatever your Wi-Fi interface is), you could add something like this:

auto br1
iface br1 inet dhcp
	bridge_ports eth0
	bridge_fd 9
	bridge_hello 2
	bridge_maxage 12
	bridge_stp off

Next you need to make sure both computers can see each other via Bluetooth. This requires enabling scanning and turning the NAP into a master and the client(s) into slaves. This can be done as follows:

sudo hciconfig hci0 piscan

and

sudo hciconfig hci0 lm MASTER,ACCEPT

or

sudo hciconfig hci0 lm SLAVE,ACCEPT

You can now check to see if each of the computers can see each other on bluetooth by running:

hcitool scan

where you should be able to see the opposite computer on each.

Next you want to start the NAP server on the computer you wish to share the connection from. (This is the computer with the bridge device). This script, which is available on the git repository will allow you to start up the NAP server. (it may also be possible to use pand, but I haven’t had any luck yet with it)
This script is called test-nap. It takes a single argument, which is the name of the bridge device. So in our case we would first need to chmod +x the file (to make it executable), then run it like this:

./test-nap br1
#!/usr/bin/python

import sys
import time
import dbus
from optparse import OptionParser, make_option

bus = dbus.SystemBus()

manager = dbus.Interface(bus.get_object("org.bluez", "/"),
"org.bluez.Manager")

option_list = [
make_option("-i", "--device", action="store",
type="string", dest="dev_id"),
]
parser = OptionParser(option_list=option_list)

(options, args) = parser.parse_args()

if options.dev_id:
adapter_path = manager.FindAdapter(options.dev_id)
else:
adapter_path = manager.DefaultAdapter()

server = dbus.Interface(bus.get_object("org.bluez", adapter_path),
"org.bluez.NetworkServer")

service = "nap"

if (len(args) < 1): bridge = "tether" else: bridge = args[0] server.Register(service, bridge) print "Server for %s registered for %s" % (service, bridge) print "Press CTRL-C to disconnect" try: time.sleep(1000) print "Terminating connection" except: pass server.Unregister(service)

After this, you can search from the client to see if the NAP service can be discovered with the command:

sdptool search NAP

You should be able to see the NAP service from your server machine at this point.

The last thing to do is edit the /etc/network/interfaces file on the client side (the device which will connect to the Internet via Bluetooth. When pand connects, it uses a bnep0 interface. You need to add the following to your file:

iface bnep0 inet dhcp

Now we are ready to connect. This is how you connect:

pand -c 
sudo ifup bnep0

Links:

uShare autostart – Ubuntu 11.04

Previously, I installed ushare easily on Ubuntu following a process similar to this: https://help.ubuntu.com/community/Xbox360Media

I’ve recently become annoyed that ushare hasn’t been autostarting in Ubuntu 11.04. I suspect it may have something to do with the fact that I am using the same machine to host vpn so I have a bridged connection br0 as my main connection. The default script in /etc/init.d/ushare should be able to autostart, and I have tried adding it to rc.d using variation of this command “sudo update-rc.d ushare defaults 80”, however it fails to start. I have no trouble running it manually with the “/etc/init.d/ushare start” command however. So I’m guessing it is just trying to start before the network interfaces come up and failing. The workaround I found tries to solve this by explicitly running after the interface is up. The way to do it, is to add it to the “/etc/network/interfaces” file using something called “post-up”. Since I wanted to have ushare run after my br0 interface is brought up, I added it like at the bottom of the br0 section, see below:

iface br0 inet static
address 192.168.0.198
netmask 255.255.255.0
gateway 192.168.0.1
bridge_ports eth1
post-up /etc/init.d/ushare start

And, now on restart “ps ax | grep ushare” shows the process running. I am also able to connect on my xbox just as before 🙂

Sources: http://www.cyberciti.biz/tips/how-do-i-run-firewall-script-as-soon-as-eth0-interface-brings-up.html