Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Set Station MAC address & validate connect SSID len #5571

Merged
merged 7 commits into from Nov 16, 2021
Merged

Set Station MAC address & validate connect SSID len #5571

merged 7 commits into from Nov 16, 2021

Conversation

anecdata
Copy link
Member

@anecdata anecdata commented Nov 11, 2021

Allow Station MAC address to be set for MAC address randomization, private wifi address, etc., just like the big kids do.

For example, wifi.radio.mac_address = bytes((0x7E, 0xDF, 0xA1, 0xFF, 0xFF, 0xFF)) changes the MAC address of the Station and it connects to wifi, shows up on the router with the new address, and operates as expected.

Tested the following error scenarios successfully:

  • ValueError: Invalid MAC address - too short, too long
  • TypeError: object with buffer protocol required - None; MAC not of a buffer protocol type
  • RuntimeError: Invalid multicast MAC address - any MAC address where bit 0 of the first octet is 1
  • RuntimeError: Can't set MAC address while connected - wifi can be enabled / started, but station can't be connected to an AP
  • RuntimeError: Station must be started - MAC address can't be set if wifi mode is not STA or STA+AP

Also added input validation for SSID length in the connect() function (max 32 bytes allowed):
wifi.radio.connect("*"*33, secrets["password"]) results in a ValueError
[thanks for finding that bug @jepler]

@anecdata anecdata added the espressif applies to multiple Espressif chips label Nov 12, 2021
@anecdata
Copy link
Member Author

anecdata commented Nov 12, 2021

uh-oh, now what, feather_m0_adalogger for de_DE failed... shorten my exception strings?

@dhalbert
Copy link
Collaborator

dhalbert commented Nov 12, 2021

uh-oh, now what, feather_m0_adalogger for de_DE failed... shorten my exception strings?

This code is not included in feather_m0_adalogger, so the problem is something else. I build 7.1.0-beta.0 last night without difficulty, so this is surprising. I will take a look and try to replicate the overflow here.

@anecdata
Copy link
Member Author

anecdata commented Nov 12, 2021

Old bug was in wifi init: station was started manually using ESP API rather than using common_hal_wifi_radio_start_station, leaving self->sta_mode = 0; This was OK on most typical runs, but caused problems when going into and out of station mode later. The manual start station was an artifact from when set_mode/common_hal_wifi_radio_start_station did more than just manage the wifi mode.

wifi.radio.mac_address behaves like wifi.radio.hostname, but not exactly. The Espressif docs are a little ambiguous. set_hostname is a NETIF API, set_mac_address is a WIFI API. You can change hostname any time after wifi init, but if there is a station connected to an AP, the hostname won't take effect until the next re-connection. You can change mac_address only while wifi mode is Station (or Station + AP), but similar to hostname with respect to active AP connection. Either can be changed when wifi is stopped/!enabled, but of course they won't take effect until the next re-connection.

So now things should be more robust with respect to wifi starts/enables and stops/disables, station mode starting and stopping, etc.:

Adafruit CircuitPython 7.0.0-rc.1-823-ge4f06f69c-dirty on 2021-11-12; Gravitech Cucumber R with ESP32S2
>>> import wifi
>>> from secrets import secrets
>>> 
>>> # after init, wifi is started/enabled, wifi mode is station, and there is no connection
>>> wifi.radio.hostname
'cucumber_r'
>>> f'{wifi.radio.mac_address[0]:02X}'
'7C'
>>> 
>>> # unlike hostname, wifi mode must be station to set mac_address
>>> wifi.radio.stop_station()
>>> wifi.radio.hostname = "hostname7A".encode()
>>> wifi.radio.hostname
'hostname7A'
>>> wifi.radio.mac_address = bytes((0x7A, 0xDF, 0xA1, 0xFF, 0xFF, 0xFF))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
RuntimeError: Station must be started
>>> 
>>> # put wifi mode back to station
>>> wifi.radio.start_station()
>>> 
>>> wifi.radio.mac_address = bytes((0x7A, 0xDF, 0xA1, 0xFF, 0xFF, 0xFF))
>>> f'{wifi.radio.mac_address[0]:02X}'
'7A'
>>> 
>>> wifi.radio.connect(secrets["ssid"], secrets["password"])
>>> # ESP32-S2 now shows up in router with hostname "hostname7A" and MAC address 7A:DF:A1:FF:FF:FF
>>> 
>>> # now stop wifi and set new hostname and MAC address
>>> wifi.radio.enabled = False
>>> wifi.radio.hostname = "hostname78".encode()
>>> wifi.radio.hostname
'hostname78'
>>> wifi.radio.mac_address = bytes((0x78, 0xDF, 0xA1, 0xFF, 0xFF, 0xFF))
>>> f'{wifi.radio.mac_address[0]:02X}'
'78'
>>> 
>>> # now start wifi and connect
>>> wifi.radio.enabled = True
>>> wifi.radio.connect(secrets["ssid"], secrets["password"])
>>> # ESP32-S2 now shows up in router with hostname "hostname78" and MAC address 78:DF:A1:FF:FF:FF

Copy link
Collaborator

@microdev1 microdev1 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! Thanks @anecdata.

@dhalbert dhalbert merged commit bd22667 into adafruit:main Nov 16, 2021
@anecdata anecdata deleted the set_mac branch November 16, 2021 01:54
@anecdata anecdata mentioned this pull request Nov 16, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement espressif applies to multiple Espressif chips network
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants