Perl TR-069 ACS server to manage CPE devices

After two years of hibernation, my efforts at implementing simple TR-069 server in perl is alive again. General motivation was to try out few new ADSL modems from ZTE with my server. And it wasn't easy...

General idea of my server is to do implementation which is easy to try and hopefully works with all quirks in existing implementations. And there are A LOT of quirks.

CWMP is basically a sick idea of twisting SOAP into something which will provide persistent connection to client which can be used to introspect device options and set them up. Back in 2007 when I started implementation, current version of TR-069 was 1.0. In meantime, DSL forum (which changed it's name to Broadband forum) decided to push out new TR-069 version 1.1, which I still haven't seen on any devices.

I have anticipated different implementations, so in first round of implementation I decided to parse XML using XML::Rules. This allowed me to use DSL-like language to implement extraction of interesting element from XML responses sent by CPE devices (CPEs are ADSL devices sitting in our homes). And that worked fairly well (at least it was tested with Thompson and Zyxel devices). Until, I got hold of ZTE device that is. It decided to return binary date inside one of XML tags (without CDATA around it) making XML::Parser on which XML::Rules depend bark.

So, I had to change XML parser. I opted for XML::Bare which doesn't have problems with invalid XML, but I had to implement rules part on my own. Which wasn't huge problem because I used only subset of functionality.

But then I tried to setup some data using SetParameterValues. And noticed that it doesn't work. This was strange, and after a two days of trials and errors I found out that ZTE devices require ParameterKey field in XML. Strange thing is that this parameter is defined as optional in TR-069 specification, and it isn't really used: it's enough to have just empty tag in generated XML to make ZTE device happy.

This is not only protocol violation which I found. Specification clearly defined that SOAPAction header is mandatory in all requests, but, ZTE decided not to send it at all. After all this you might wonder why would I like to put so much effort in implementing semi-defined protocol which is really useful only to IPSs. My initial motivation was to provide first free implementation of TR-069, but nowadays there are few TR-069 alternatives: OpenACS is probably best known, but it requires Java, JBOSS and MySQL just to get started.

And I didn't really care about user interface at all. I wanted to be able to write a small snippet of perl code which would allow easy customization of CPE configuration without going through user interface.

To do that, I decided to implement on-disk queue using IPC::DirQueue in which specific commands for clients are inserted and then sent one-by-one until queue for this client is empty. In current version all CPE parameters are first introspected (getting current values and writable status) and stored in simple YAML file on disk, allowing easy review or import into another system.

If you have fixed configuration which you want to push to all client, you can just create vendor.yaml file by copy/paste from file generated by CPE introspection and all CPEs pick up setting from it.

If you wanted to do something more complex (make a lookup into legacy database and deduce configuration from it, for example) you can always extend CWMP::Vendor with new perl function will implement something like this.

To make this even easier, I decided to move project to git (so perl-cwmp is now available on github) and setup publicly visible ACS server which you can use to check weather your CPE implementation of TR-069 will work with my server. This requires you to have administrative privileges on your CPE device, and probably isn't good idea if your provider is already managing your modem using TR-069. But, in that case, you won't be able to change it's setting anyway :-)

However, this would mean that you would have to send full passwords to me also (because TR-069 doesn't encrypts them) so basically you are forced to install version locally to try it out if you have any passwords in your configuration which you don't want to share with everyone.