Use NetworkManager to launch scripts based on Network Location

NetworkManager is fast becoming the de facto network provider in desktop Linux distributions. The reason it's so popular is that it "does the right thing" 99% of the time. However, there's not many examples out there that extend that functionality. NetworkManager provides hooks in which you can have scripts launch when network settings change. In today's post, I will show you how to launch the Synergy client whenever you plug into your corporate network.

I'm lazy. I hate having to fire up my Synergy client on my laptop to connect to my desktop at work when I get to work everyday. Now, I could just fire up the Synergy client at boot, but when I'm at home if I have the VPN connected, Synergy will hook up and I don't want it to.

I needed a way to fire a script that says "if I'm on this network, then fire up synergyc, otherwise do nothing". Writing the script was pretty easy, but I was stumped on how to get to run not only at bootup, but whenever I change networks -- I very often suspend my laptop at night at home and resume it at work the next morning.

It turns out that NetworkManager has a piece called NetworkManagerDispatcher that does all of this for us. Any script in /etc/NetworkManager/dispatcher.d will be called with two arguments, the name of the interface, and the status of the interface (up/down).

If a picture is worth a thousand words, scripts are worth a million, so let's get to it.

First, a little background is needed. I know that I am on my corporate network if my eth0 interface has obtained an IP in the 10.0.0.0/8 subnet. Without further ado, I present to you /etc/NetworkManager/dispatcher.d/99smartsynergy.sh:

  1. #!/bin/sh
  2.  
  3. IF=$1
  4. STATUS=$2
  5. USER=justintime
  6.  
  7. wait_for_process() {
  8.   PNAME=$1
  9.   PID=`/usr/bin/pgrep $PNAME`
  10.   while [ -z "$PID" ]; do
  11.         sleep 3;
  12.         PID=`/usr/bin/pgrep $PNAME`
  13.   done
  14. }
  15.  
  16. start_synergy() {
  17.      wait_for_process nm-applet
  18.      /bin/su $USER -c "/usr/bin/synergyc $1"
  19. }
  20.  
  21. if [ "$IF" = "eth0" ] && [ "$STATUS" = "up" ]; then
  22.  
  23.         #LAN Subnet at work
  24.         NETMASK="10.0.0.0/8"
  25.         if [ -n "`/sbin/ip addr show $IF to $NETMASK`" ]; then
  26.                 ARGS="jentoo.bucklehq.com"
  27.                 start_synergy $ARGS
  28.                 exit $?
  29.         fi
  30.  
  31. fi

The IF and STATUS variables are those fed in from NetworkManager. The USER variable is the user that I run synergyc as. You could add some intelligence here, but it was overkill for my situation.

The if at the bottom states that we are only concerned if the interface eth0 has changed it's status to "up". I then use the /sbin/ip command to determine if eth0 is within the 10.0.0.0/8 subnet. If so, then I call start_synergy, passing it my desktop's hostname.

Within the start_synergy() function we call the wait_for_process function, passing it nm-applet. We need this function because if we try to run synergyc before I've logged in via GDM, it will exit (this happens on bootup). By calling wait_for_process, we create a way to make synergyc wait until after the nm-applet (NetworkManager Applet) has started. Finally, once nm-applet has been detected as running, the script executes synergyc, and exits.

TODO's

  • I should probably create a function that kills the remaining synergyc processes when eth0 goes down.
  • If there's already a synergyc running, we should just exit as the client will continue to try to reconnect.

Conclusion

The purpose of this article wasn't to show you how to launch synergyc (although I think it's really handy), it was to get the creative juices flowing. Have you already utilized NetworkManagerDispatcher for something? What would you like to have it do? Comment away!

Your rating: None Average: 5 (3 votes)

Comments

Network Manager dispatcher scripts.

I'm not familiar with the synergy, but I have seen a few public wifi hotspots that use 10.0.0.0 addresses. If this is a problem for someone trying to use your script, perhaps they could change the conditional to check for a known hostname or ip address on the local subnet.

Wish I could share your enthusiasm for NM. From my personal experience I'd give it about a 70% "does the right thing" rating!

Good point on that. You

Good point on that. You could also make sure that a hostname could resolve, which would do the same thing. In this particular case, Synergy would not connect, and just sit in the background trying to connect every 60 seconds. Not ideal, but not the end of the world either.

Sorry your experience isn't as good as mine with NM. Have you been using a recent version? I've had the best luck with the one that comes with Ubuntu Intrepid (0.70 off the top of my head) - are you using a recent release?

Justin

"NetworkManager is fast

"NetworkManager is fast becoming the de facto network provider in desktop Linux distributions. The reason it's so popular is that it "does the right thing" 99% of the time. However, there's not many examples out there that extend that functionality. NetworkManager provides hooks in which you can have scripts launch when network settings change. In today's post, I will show you how to launch the Synergy client whenever you plug into your corporate network."
Thanks for the information

Use arp to detect specific networks

Private networks with NATs are common in WiFi hotspots nowadays, so relying on the IP address is not enough. In my scripts, I've added tests to check the MAC address of
the gateways using arp:

test=`arp -a 10.0.0.1`
if [[ "$test" =~ 01:23:45:67:89:a0 ]]; then
...
fi

This gets a little cumbersome if the network has several gateways. But with bash you can use arrays and for loops.

Identify wireless network by SSID

Thanks for the info.

I regularly connect to a wireless network that uses a web-based form (SSL encrypted) for the submission of login credentials before it will allow access to the Internet. This gets annoying very quickly, especially when you have to open a web browser specifically to log into the network before, for example, your weather applet can update or your mail client will work properly.

I have written a (fairly quick and dirty) script which uses wget to submit the login details, but since upgrading to KDE 4.x I had lost the ability to have it run when the network is connected. The method you describe here should allow me to work around that limitation.

If you need to run a script after connecting to a specific wireless network, the command iwgetid --raw can be used to obtain the SSID of the currently connected wireless network (on Ubuntu, at least).

GPRS network filtering

Excellent information, thanks. I just wrote a little script to check the location of my GPRS connection (via whatismyip), and warn me if I'm roaming.

Mount NFS when VPN is connected

I'd like to mount NFS drives when connected to VPN. I've created a file 99mountNFS.sh. What am I missing? I'm working with Ubuntu if that matters. Thanks!


#!/bin/sh

IF=$1
STATUS=$2

if ["$IF" = "tun0"] && ["$STATUS" = "up"]; then
sudo mount / //
fi

if ["$IF" = "tun0"] && ["$STATUS" = "down"]; then
sudo umount /
fi

How do you do check based on which SSID you're connected to

heading says it all:

 

I want to run a script based on the SSID im connected to, not just whether my wlan0 interface is up or not.  IP address doesn't help as 192.168.1.x is quite common on most APs

iwconfig maybe?

It's been a long time, but I think iwconfig can get that for you?

iwconfig solution:

Yepp, that did the trick:

 

SSID=$(/sbin/iwconfig $IFACE | sed -r -n '/SSID/{s/.*SSID:"([^"]+)".*/\1/g;p;q}' )

Post new comment

The content of this field is kept private and will not be shown publicly.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Allowed HTML tags: <a> <p> <span> <div> <h1> <h2> <h3> <h4> <h5> <h6> <img> <map> <area> <hr> <br> <br /> <ul> <ol> <li> <dl> <dt> <dd> <table> <tr> <td> <em> <b> <u> <i> <strong> <font> <del> <ins> <sub> <sup> <quote> <blockquote> <pre> <address> <code> <cite> <embed> <object> <param> <strike> <caption>
  • Lines and paragraphs break automatically.

More information about formatting options