3

My Raspberry pi is connected to my home wifi network. This wifi network have a captive portal and hence each time I need to sign in the captive portal to use the internet. Now I am trying to automate the sign in procedure. I have prepared a script for that and now my confusion is that "where to put that script".

I need to run the script only when a successful connection is established with the wifi network. How can I do that?

I have searched google and it found that to put the script in /etc/if-up.d but it won't work for me, it work only when we do sudo ifup wlan0.

mcv
  • 73
  • 1
  • 8

2 Answers2

4

To run a script when the WiFi is connected you can use wpa_cli. In man wpa_cli you find for option -a:

-a file
Run in daemon mode executing the action file based on events from wpa_supplicant. The specified file will be executed with the first argument set to interface name and second to "CONNECTED" or "DISCONNECTED" depending on the event. This can be used to execute networking tools required to configure the interface.

Additionally, three environmental variables are available to the file:
WPA_CTRL_DIR, WPA_ID, and WPA_ID_STR. WPA_CTRL_DIR contains the absolute path to the ctrl_interface socket. WPA_ID contains the unique network_id identifier assigned to the active network, and WPA_ID_STR contains the content of the id_str option.

As template file you can use something like this:

#!/bin/sh
# redirect all output into a logfile
exec 1>> /tmp/test.log 2>&1

case "$1" in
wlan0)
    case "$2" in
    CONNECTED)
        # do stuff on connect with wlan0
        echo wlan0 connected
        ;;
    DISCONNECTED)
        # do stuff on disconnect with wlan0
        echo wlan0 disconnected
        ;;
    *)
        >&2 echo empty or undefined event for wlan0: "$2"
        exit 1
        ;;
    esac
    ;;

wlan1)
    case "$2" in
    CONNECTED)
        # do stuff on connect with wlan1
        echo wlan1 connected
        ;;
    DISCONNECTED)
        # do stuff on disconnect with wlan1
        echo wlan1 disconnected
        ;;
    *)
        >&2 echo empty or undefined event for wlan1: "$2"
        exit 1
        ;;
    esac
    ;;

*)
    >&2 echo empty or undefined interface: "$1"
    exit 1
    ;;
esac

Don't forget to make the script executable with chmod +x script.sh. Then execute it with:

rpi ~$ wpa_cli -i wlan0 -a /home/pi/path/to/script.sh

# Or if necessary as root:
rpi ~$ sudo wpa_cli -i wlan0 -a /path/to/script.sh

If you want to run it as daemon then add option -B.

Ingo
  • 40,606
  • 15
  • 76
  • 189
  • As you said, it works fine but when I do the same in daemon mode, it won't work. `ps aux` command shows that the script is running on the background. Help me? – mcv Apr 10 '19 at 04:08
  • @mcv You are right. The script and the test calls where a bit buggy. I have corrected the script with some lines, mainly the second and third. The problem was that the output wasn't seen because in daemon mode there is no terminal. I have redirected the output into a file `/tmp/test.log`. In addition `wpa_cli` needs the right interface to manage. I have added option `-i wlan0` to the test commands. – Ingo Apr 11 '19 at 16:24
  • Am non sure I see how to do this based on which SSID? For example, if I have a dev SSID as 'home' and a prod wifi ssid as "prod" should I add another case statement for one of the environment variables? – leeprevost Jul 06 '22 at 17:14
2

There is no easy way to do this out of the box. With systemd you have to listen to D-Bus messages to find out when a connection is established. Try networkd-dispatcher, as suggested in the post.

You can run scripts depending on the link operational status. Interface name, among some other parameters, is transmitted to your script as an IFACE environment variable.