Making long transmissions behind Echolink’s back

Good news today! After various trials and errors, REAST’s new Raspberry Pi-based system transmitted both the WIA and VK7 regional news, driven by a web-based scheduler.

The Raspberry Pi is a combination Echolink/IRLP node so it already has an attached radio. The existing interface has PTT control, a sound card connected to the radio and the ability to check if the channel is occupied, an important feature. Channel occupation is not something you get with a basic DIY interface so it’s nice to take advantage of it.

The Echolink software itself is a large modular collection of binaries and shell scripts that invoke each other to get their job done. This makes it straightforward to tap in and automate transmissions by running shell commands.

So far so good. Any automated system just needs to run the right commands at the right time. The only trouble is that the files we need to transmit for our broadcast are about half an hour long. (They contain station identifications at several points so it’s legal but it’s a single continuous transmission.)

As I discovered, Echolink has extensive watchdog features to make sure the radio doesn’t activate PTT for more than 5 minutes. This appears to be a hard limit that is not controllable from the configuration. For the purposes of Echolink and IRLP that’s very reasonable but it’s a major inconvenience for our broadcasts!

The watchdog is somewhere inside the compiled binaries while the actual shutdown of the radio occurs in shell scripts. At first I tried modifying the shell scripts but this quickly turned into whack-a-mole as there are various ways it can fail. After a second interrupted broadcast I decided this wasn’t good enough—Echolink should be completely prevented from knowing that we’re transmitting.

I’m not really familiar with Echolink so I had a look around with strace. I found that the readinput command is tracking PTT, COS and DTMF codes by reading 9 of the Raspberry Pi’s GPIO pins. The most important ones are these:

What I really want to do is intercept the request every time Echolink tries to read one of these values. If we’re in the middle of a transmission from the automatic system we should report “yes the channel is occupied” and “no we’re not transmitting”. To Echolink it will appear that some other station is hogging the repeater. It won’t try to transmit anything and it will just sit tight until it finishes.

How will we know if an automatic transmission is underway? I modified my code so that while it’s transmitting it will create a file called web_tx inside the local directory. When it finishes transmitting it will delete it again. Therefore whenever Echolink tries to read the GPIO we simply need to check whether a web_tx file exists at that path. If it exists, provide the fake response. If it doesn’t exist, let Echolink read the real value.

The actual mechanism for intercepting the reads requires a bunch of code. I wrote my replacement open(), read(), and close() functions in C and compiled them into a shared object. By setting the LD_PRELOAD environment variable to point to my shared object all of Echolink’s file operations end up filtered by my custom code. In a fairly roundabout way it does what I described in the last two paragraphs.

The only remaining trick is to make sure the right environment variables are set for Echolink software, but not for the web server that’s playing the long files. All of the scripts already load their environment from the file located at custom/environment so I just had to add my own settings to that. LIBC_SO and WEB_TX_OVERRIDE are parameters to the interception code.

So that the automation server knows what’s really going on I need to clear out the variable when I run it:

There’s also a persistent service called tbd. I honestly don’t know what it does so I decided to give it the same variables by changing /etc/init.d/tbd to the following:

And with that everything is working nicely. The only catch is that I have defeated Echolink’s watchdog. I’ll need to make sure that we have some form of hardware-based timeout at an appropriate length, perhaps 45 minutes, just in case the Pi crashes during transmission.

With the basics working I can now spend some time improving the code and securing it so it can go on the public internet.

This entry was posted in programming, radio. Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *