LinkedIn Sourceforge Twitter

Vincent's Blog

Pleasure in the job puts perfection in the work (Aristote)

Network Manager Control for OpenBSD

Posted on 2017-10-23 10:12:00 from Vincent in Open Bsd

I propose you a small script allowing you to easily manage your networks connections. This script is integrated within the openbox dynamic menus. Moreover, it allow you to automatically have the connections you have pre-defined based.


I was frustrated to not be able to swap quickly from one network interface to an another, to connect simply and quickly to my wifi, to my cable connection, to the wifi of a friend, ...
Every time you have to type the ifconfig commands, .... This is nice, but boring. Surely, when you are in a middle of a presentation and you just want a quick connection to your mobile in tethering mode.
Thanks to OpenBSD those commands are not so hard, but this frustrate me to not be able to do it with one click. Directly from my windows environment. Since I'm using Openbox, from a menu of openbox.

So, I've looked around to see what is currently existing.
One tool I've found was netctl. The idea is to have a repository of hostname.if files ready to use for different cases.
The idea sounds great, but I had some difficulties to use it.
But what annoys me the most, is that it modify the current hostname.if files in /etc.
To my eyes, I would avoid to modify those files because they are my working basis. I want to rely on them and make sure that my network will be back to a normal mode after a reboot.
Nevertheless, if I've well understood netctl, you have a feature where it will look for the predefined network config matching the environment where you are. Very cool.

So, after having played with netctl, look for alternative on internet, I've decided to create nmctl. A small python script which just perform the mandatory network commands.

1. nmctl: a Network Manager Control tool for OpenBSD

Nmctl a small tool that allow you to manage your network connections.
Why python ? Just because it's the easiest programming language for me. But I should maybe rewrite it in shell, more standard in the OpenBSD world than python.

1.1. download and install

I've put nmctl on my sourceforge account here
You can dowload the last version here
To install you just have to run: make install (as root)

The per-requists are:
- having python2.7 installed
- Since nmctl must be run as root, I strongly recommend you to run it via doas.

1.2. The config file

First you have to create a config and store it in /etc/nmctl.conf.
This file must respect few rules:

  • Each block must starts with a line having the following format: '''<-name->:<-interface->'''
  • Each following lines must start by at least one space. Those lines have more or less the same format as for hostname.if.
  • You have to create a block with the name "open". This will be used to establish a connection to the Open Wifi around you (in restaurant for example)
  • The order of those elements is important. In case you use the -restart option, nmctl will try each of those network configs one after one until it can ping www.google.com. (if you wan to ping something else, you can change it in the python script if you want).
  • You can use external commands. Just preced them with the "!".
  • You have macors. Macros allow you to perform some actions. The 2 currently implemented are '''<-nwid->''' and '''<-random mac->'''.
  • You can use keywords. Currently the only one implemented is "dhcp"

Basically you can put all commands that nmctl will apply to the interface to which those commands are referring to. So, you will always have "ifconfig <-interface-> <-command you type in the config file->".
Check the manpage of ifconfig to see how flexible command is.

You have currently 2 macros:
- <-nwid-> which refers to the "nwid <-nwid name->" when you select an Open Wifi with the -open option of nmctl.
- <-random mac-> is a macro generating a random mac address. This is useful test a dhcp server for example.

The keyword "dhcp" will trigger a command like "dhclient <-interface->".

1.3. Config file sample.

Let me show you one nmctl.conf example. It speaks by itself.

#the name open is required for Open wifi. 
#this is the interface that nmctl will take to establish a connection
#We must put the macro <nwid>. This is where nmctl will put the nwid command
#and the selected openwifi selected by the parameter --open
open:iwn0
 !route flush
 <nwid> -wpa
 dhcp

cable:em0
 !route flush
 dhcp

lgg4:iwn0
 !route flush
 nwid LGG4s_8114 wpakey aanotherpassword
 dhcp

home:iwn0
 !route flush
 nwid Linksys19594 wpakey apassword
 dhcp

college:iwn0
 !route flush
 nwid john wpakey haahaaaguessme
 dhcp

cable_fixip:em0
 !route flush
 inet 192.168.3.3 netmask 255.255.255.0
 !route add -host default 192.168.3.1

#with this network interface I'm using the macro <random mac> 
#which will do what you guess it will do :-)
cable_random:em0
 !route flush
 lladdr <random mac>
 dhcp

In this config we have several cable's networks associated with my interface "em0" and several wifi networks associated with my wireless interface "iwn0".
You see that you can switch from dhcp, to fixed IP and even you can play with the random mac address macro.

Thanks to the network called "open", you can connect to any open wifi system. To do that, just type ''' nmctl --open <-name of the open wifi->'''

So, now, with just one command you can switch from one network configuration to an another one.
That's become cool :-).

2. Integration with openbox

Thanks to the dynamic menu feature of oenbox, you can have your different pre-defined networks under one click of your mouse.

For that, you just have to add, at the most appropriate place for you, the following code in your ./config/openbox/menu.xml

<menu id="network-menu" label="Network">
  <menu id="wifi-list" label="Wifi configured"  execute="doas /usr/local/bin/nmctl --list" />
  <menu id="wifi-scan" label="Wifi scan"  execute="doas /usr/local/bin/nmctl --scan" />
  <separator />

The results are:

I just have 2 wifi available around me.

In this case, you see the different networks as defined in the config file just above.

3. Automatically identify your available connection and connect to it in one go

But the most interesting part, is coming from a loop through all of your defined networks.
This loop is reachable via the -restart option.

Basically the idea is to loop from the first network config to the last and test a ping for each of them. Once the ping works, we break the loop and keep this setting.

Thus where ever you are, you just have to initiate a nmctl -restart and you will be connected to the network you have defined for this place. There is one small exception, the open-wifis. We do not include them in this loop exercise.

Thus the way you define your config file is important.
Since the network called "open" is dedicated to "open wifi", it will not be part of this scan exercise. I propose you keep it at the first place.

Then, in my case, if my mobile, called lgg4, is open and visible by my laptop, I will connect it immediately.
Second, I check if my "home wifi" is visible.
Third, if I have a cable connected on my laptop, I'm using this connection and do a dhcp command.
Then, I check to see if my laptop is not viewing the "college" wifi.
? and so on until a ping command works.

If you do not have a cable in your laptop and if none of your pre-defined wifi connections are visible, the scan will stop.

3.1 examples

No cable connected, no pre-defined wifi around me:

t420:~$ time doas nmctl -r 
nwids around you:  bbox2-d954
    0m02.97s real     0m00.08s user     0m00.11s system
t420:~$ 
t420:~$

I'm at home and my wifi router is running:

t420:~$ time doas nmctl -r 
nwids around you:  Linksys19594 bbox2-d954
ifconfig em0 down: 0
default              fw                   done
fw                   00:22:4d:ac:30:fd    done
nas                  link#2               done
route flush: 0
ifconfig iwn0 nwid Linksys19594  ...: 0
iwn0: no link ........... sleeping
dhclient iwn0: 0
Done.
PING www.google.com (216.58.212.164): 56 data bytes
64 bytes from 216.58.212.164: icmp_seq=0 ttl=52 time=12.758 ms

--- www.google.com ping statistics ---
1 packets transmitted, 1 packets received, 0.0% packet loss
round-trip min/avg/max/std-dev = 12.758/12.758/12.758/0.000 ms
ping -c1 -w2 www.google.com: 0
    0m22.49s real     0m00.08s user     0m00.11s system
t420:~$

I'm at home but tethering is active on my mobile:

t420:~$ 
t420:~$ time doas nmctl -r 
nwids around you:  Linksys19594 bbox2-d954 LGG4s_8114
ifconfig em0 down: 0
default              fw                   done
fw                   00:22:4d:ac:30:fd    done
nas                  link#2               done
route flush: 0
ifconfig iwn0 nwid LGG4s_8114  ...: 0
iwn0: DHCPDISCOVER - interval 1
iwn0: DHCPDISCOVER - interval 2
iwn0: DHCPOFFER from 192.168.43.1 (a0:91:69:be:10:49)
iwn0: DHCPREQUEST to 255.255.255.255
iwn0: DHCPACK from 192.168.43.1 (a0:91:69:be:10:49)
iwn0: bound to 192.168.43.214 -- renewal in 1800 seconds
dhclient iwn0: 0
Done.
ping: Warning: www.google.com has multiple addresses; using 173.194.69.99
PING www.google.com (173.194.69.99): 56 data bytes
64 bytes from 173.194.69.99: icmp_seq=0 ttl=43 time=42.863 ms

--- www.google.com ping statistics ---
1 packets transmitted, 1 packets received, 0.0% packet loss
round-trip min/avg/max/std-dev = 42.863/42.863/42.863/0.000 ms
ping -c1 -w2 www.google.com: 0
    0m13.78s real     0m00.08s user     0m00.13s system
t420:~$

Same situation, but I cut the tethering just after the scan. Thus the dhcp command will not succeed.
We see that, after timeouts, nmctl see that the ping is failing (return code 1), thus he pass to the next possible pre-defined network.

t420:~$ time doas nmctl -r 
nwids around you:  Linksys19594 bbox2-d954 LGG4s_8114
ifconfig em0 down: 0
default              192.168.43.1         done
192.168.43.1         a0:91:69:be:10:49    done
route flush: 0
ifconfig iwn0 nwid LGG4s_8114  ...: 0
iwn0: no link ........... sleeping
dhclient iwn0: 0
Done.
ping: no address associated with name
ping -c1 -w2 www.google.com: 1
ifconfig em0 down: 0
192.168.43.1         link#2               done
route flush: 0
ifconfig iwn0 nwid Linksys19594  ...: 0
iwn0: DHCPREQUEST to 255.255.255.255
iwn0: DHCPACK from 192.168.3.1 (00:22:4d:ac:30:fd)
iwn0: bound to 192.168.3.16 -- renewal in 302400 seconds
dhclient iwn0: 0
Done.
PING www.google.com (216.58.212.164): 56 data bytes
64 bytes from 216.58.212.164: icmp_seq=0 ttl=52 time=12.654 ms

--- www.google.com ping statistics ---
1 packets transmitted, 1 packets received, 0.0% packet loss
round-trip min/avg/max/std-dev = 12.654/12.654/12.654/0.000 ms
ping -c1 -w2 www.google.com: 0
    3m34.85s real     0m00.17s user     0m00.20s system
t420:~$


0, 0
displayed: 424



How much does 3 plus 2 ?