Connecting the device to a wifi behind a captive

Can you please paste here what you do more specifically?

Isn’t dnsmasq started automatically on balenaOS and used by NetworkManager for it’s configuration? And is the DBUS API of dnsmasq on the host OS available from within a container?

Asking this because I’m following this topic and it’d be nice for our own application to set DNS records on dnsmasq instead of running our own dnsmasq in a container (balenaOS 2.49.0)

@bversluijs There is a dnsmasq instance running in the host OS, but it is only used for providing hostname resolution for containers. This instance has DBUS API enabled and is reachable from the containers. If one is looking to launch a WiFi hotspot, then this is a different use-case and will need launching a separate dnsmasq instance.

this is the code that starts the wifi, from a container with the priviliges, it works, but i need to make the connection not to set a gw in the phones that are connecting to this AP.
i did find parameters that can make the AP not pass the routing, and it achieves what i need besides the fact that i cant control the server IP.
this is the change:
s_ip4 = dbus.Dictionary({‘method’: ‘link-local’, ‘ignore-auto-routes’: dbus.Boolean(True), ‘ignore-auto-dns’: dbus.Boolean(True)})

def SetWifiHotspot(self,AP_ID,iface,ssid_name,password,operation):

    our_uuid = '2b0d0f1d-b79d-43af-bde1-71744625642e'

    s_con = dbus.Dictionary({

        'type': '802-11-wireless',

        'uuid': our_uuid,

        'id': AP_ID})

    s_wifi = dbus.Dictionary({

        'ssid': dbus.ByteArray(ssid_name.encode("utf-8")),

        'mode': "ap",

        'band': "bg",

        'channel': dbus.UInt32(1)})

    s_wsec = dbus.Dictionary({

        'key-mgmt': 'wpa-psk',

        'psk': password})

    s_ip4 = dbus.Dictionary({'method': 'shared'})

    s_ip6 = dbus.Dictionary({'method': 'ignore'})

    con = dbus.Dictionary({

        'connection': s_con,

        '802-11-wireless': s_wifi,

        '802-11-wireless-security': s_wsec,

        'ipv4': s_ip4,

        'ipv6': s_ip6

        })

    bus = dbus.SystemBus()

    service_name = "org.freedesktop.NetworkManager"

    proxy = bus.get_object(service_name, "/org/freedesktop/NetworkManager/Settings")

    settings = dbus.Interface(proxy, "org.freedesktop.NetworkManager.Settings")

    proxy = bus.get_object(service_name, "/org/freedesktop/NetworkManager")

    nm = dbus.Interface(proxy, "org.freedesktop.NetworkManager")

    devpath = nm.GetDeviceByIpIface(iface)

    # Find our existing hotspot connection

    connection_path = None

    for path in settings.ListConnections():

        proxy = bus.get_object(service_name, path)

        settings_connection = dbus.Interface(proxy, "org.freedesktop.NetworkManager.Settings.Connection")

        config = settings_connection.GetSettings()

        if config['connection']['uuid'] == our_uuid:

            connection_path = path

            break

    # If the hotspot connection didn't already exist, add it

    if not connection_path:

        connection_path = settings.AddConnection(con)

        print('Couldnt find connection, adding connection')

    # Now start or stop the hotspot on the requested device

    proxy = bus.get_object(service_name, devpath)

    device = dbus.Interface(proxy, "org.freedesktop.NetworkManager.Device")

    if operation == "up":

        acpath = nm.ActivateConnection(connection_path, devpath, "/")

        proxy = bus.get_object(service_name, acpath)

        active_props = dbus.Interface(proxy, "org.freedesktop.DBus.Properties")

        # Wait for the hotspot to start up

        start = time.time()

        while time.time() < start + 10:

            state = active_props.Get("org.freedesktop.NetworkManager.Connection.Active", "State")

            if state == 2:  # NM_ACTIVE_CONNECTION_STATE_ACTIVATED

                print("Access point started")

                return True

            time.sleep(1)

        print("Failed to start access point")

        return False

    elif operation == "down":

        print('Putting down connection')

        device.Disconnect()

    else:

        print("up or down operations for wifi")

        return False

I see. You are setting the shared method for ipv4 configuration, which will make NetworkManager start a dnsmasq instance in the background.

You will need to use manual method to achieve what you want instead. When you use the manual method, then you will have to start dnsmasq as NetworkManager will not start it automatically. You can check how we do that in WiFi Connect here: https://github.com/balena-io/wifi-connect/blob/master/src/dnsmasq.rs

Also check this for how we define manual: https://github.com/balena-io-modules/network-manager/blob/master/src/dbus_nm.rs#L304-L310

This sets the method to manual and sets a static IP address for the device. In this case 192.168.42.1.

@majorz any update regarding the support of network manager? you said that you tried to patch NetworkManager and almost got it to work.

Hi, I stumbled among issues with some drivers which made the investigation harder and afterwards I never had a chance to continue further. I created a new GitHub issue to track the progress on this, but the investigation will not restart soon as I have some other time consuming fixes to work till I get there: https://github.com/balena-os/meta-balena/issues/2030.
Thanks,
Zahari