'scapy.all' has no attribute 'get_if_raw_hwaddr'
Hey everybody, I first of all want to let you all know how awesome this module is!! Anyways, I had to work a bit to get it working. I am using python 3.9.5 with scapy 2.6.0 and, when running the first example in the readme, it fails. Here's the code:
from ESPythoNOW import *
import time
def callback(from_mac, to_mac, msg):
print("ESP-NOW message from %s to %s: %s" % (from_mac, to_mac, msg))
espnow = ESPythoNow(interface="wlan0mon", callback=callback)
espnow.start()
while True:
msg=b'\x01'
espnow.send("FF:FF:FF:FF:FF:FF", msg)
time.sleep(3)
And, when ran with sudo python test.py, it fails with:
Traceback (most recent call last):
File "/home/mindyourbusiness/fix_espnow/ESPythoNOW/test.py", line 7, in <module>
espnow = ESPythoNow(interface="wlan0mon", callback=callback)
File "/home/mindyourbusiness/fix_espnow/ESPythoNOW/ESPythoNOW.py", line 38, in __init__
self.local_hw_mac = self.hw_mac_as_str(self.interface) # Interface's actual HW MAC
File "/home/mindyourbusiness/fix_espnow/ESPythoNOW/ESPythoNOW.py", line 248, in hw_mac_as_str
return ("%02X:" * 6)[:-1] % tuple(scapy.orb(x) for x in scapy.get_if_raw_hwaddr(self.l2_socket.iface)[1])
AttributeError: module 'scapy.all' has no attribute 'get_if_raw_hwaddr'
I think I got it to work with my pull request:
Line 247 defines the function hw_mac_as_str in a pretty weird way (it's got an unused argument(interface) and reconstructs the string version of the interface's mac address. What's the point of that if there's scapy's get_if_hwaddr function for it?
I fixed it (now there are no errors and Wireshark detects the packets) and am about to open a PR, once I figure out how to upload the fix... Give me a few minutes so I can feel the glory of publishing my first PR please :-)
Here's the pull request. #4
There's a problem: Wireshark sees the packets but the esp8266 doesn't receive them. That's weird. Here's the sender code
from ESPythoNOW import *
import time
def callback(from_mac, to_mac, msg):
print("ESP-NOW message from %s to %s: %s" % (from_mac, to_mac, msg))
espnow = ESPythoNow(interface="wlan0mon", callback=callback)
espnow.start()
while True:
msg=b'\x01\x10'
espnow.send("d8:bf:c0:11:2e:cd", msg)
time.sleep(3)
And here's the esp8266 code:
//I mostly copied this code : https://randomnerdtutorials.com/esp-now-esp8266-nodemcu-arduino-ide/
#include <Arduino.h>
#include <espnow.h>
#include <ESP8266WiFi.h>
// Structure example to receive data
// Must match the sender structure
typedef struct struct_message {
uint8_t a, b;
} struct_message;
// Create a struct_message called myData
struct_message myData;
// Callback function that will be executed when data is received
void OnDataRecv(uint8_t * mac, uint8_t *incomingData, uint8_t len) {
memcpy(&myData, incomingData, sizeof(myData));
Serial.print("Bytes received: ");
Serial.println(len);
Serial.print("a: ");
Serial.println(myData.a);
Serial.print("b: ");
Serial.println(myData.b);
Serial.println();
}
void setup() {
// Initialize Serial Monitor
Serial.begin(115200);
// Set device as a Wi-Fi Station
WiFi.mode(WIFI_STA);
// Init ESP-NOW
if (esp_now_init() != 0) {
Serial.println("Error initializing ESP-NOW");
return;
}
// Once ESPNow is successfully Init, we will register for recv CB to
// get recv packer info
esp_now_set_self_role(ESP_NOW_ROLE_SLAVE);
esp_now_register_recv_cb(OnDataRecv);
Serial.println(WiFi.channel());
}
void loop() {
yield();
}
The receiver mac and channel is right (1) The esp doesn't send any serial packets...
Must be some differences in the scapy versions, I'll do some testing when I have some time and get back to you on this and the PR.
There's a problem: Wireshark sees the packets but the esp8266 doesn't receive them. That's weird. Here's the sender code
from ESPythoNOW import * import time def callback(from_mac, to_mac, msg): print("ESP-NOW message from %s to %s: %s" % (from_mac, to_mac, msg)) espnow = ESPythoNow(interface="wlan0mon", callback=callback) espnow.start() while True: msg=b'\x01\x10' espnow.send("d8:bf:c0:11:2e:cd", msg) time.sleep(3)And here's the esp8266 code:
//I mostly copied this code : https://randomnerdtutorials.com/esp-now-esp8266-nodemcu-arduino-ide/ #include <Arduino.h> #include <espnow.h> #include <ESP8266WiFi.h> // Structure example to receive data // Must match the sender structure typedef struct struct_message { uint8_t a, b; } struct_message; // Create a struct_message called myData struct_message myData; // Callback function that will be executed when data is received void OnDataRecv(uint8_t * mac, uint8_t *incomingData, uint8_t len) { memcpy(&myData, incomingData, sizeof(myData)); Serial.print("Bytes received: "); Serial.println(len); Serial.print("a: "); Serial.println(myData.a); Serial.print("b: "); Serial.println(myData.b); Serial.println(); } void setup() { // Initialize Serial Monitor Serial.begin(115200); // Set device as a Wi-Fi Station WiFi.mode(WIFI_STA); // Init ESP-NOW if (esp_now_init() != 0) { Serial.println("Error initializing ESP-NOW"); return; } // Once ESPNow is successfully Init, we will register for recv CB to // get recv packer info esp_now_set_self_role(ESP_NOW_ROLE_SLAVE); esp_now_register_recv_cb(OnDataRecv); Serial.println(WiFi.channel()); } void loop() { yield(); }The receiver mac and channel is right (1) The esp doesn't send any serial packets...
Is your Linux setup receiving messages with your changes?
I tried running the code on a laptop and a desktop which both have interfaces that support monitor mode and packet injection (I tested them with airplay and they work). However, the sender computer receives its own packets via Wireshark but the receiver rarely does. in about 1 h of tinkering I managed to get the packages received by the receiver only once and only in Wireshark. When they are received I can read their content in Wireshark but espythonow does not show them. And yes, I set the correct receiver mac... It's as if only a specified set of channels works. Edit for clarity: I didn't check if the sender can receive its own packets via the library. I will
A couple things to check:
What is the output (if any) from prep.sh being run with the correct interface and channel set?
Try adding adding accept_all
espnow = ESPythoNow(interface="wlan0mon", callback=callback, accept_all=True)
Can you describe your setup? I'll have time to examine this problem more deeply in about a week.
sudo bash prep.sh wlan0mon 8
Returns nothing and effectively works (it does almost exactly what I did manually: Iwconfig:
wlan0mon IEEE 802.11 Mode:Monitor Frequency:2.447 GHz Tx-Power=20 dBm
Retry short limit:7 RTS thr=2347 B Fragment thr:off
Power Management:on
I also enabled the accept_all flag and it now somehow works: When either computer sends a message to the other one, the library on the recipient side sees the packet! It reads "ESP-NOW message from [src mac] to [destination mac]: b''" where destination mac is the mac of the computer that's outputting the text. So it works. However, the message is read as empty.
To sum up, I now used the prep script and enabled that accept_all flag. I can now receive the packets but not the messages.
Also, if I turn off the accept_all flag the program stops outputting data (even though its the right receiver mac). That's weird.
Edit: Wireshark on the sender side shows that each packet gets retransmitted a few times and only the first transmission contains the intended message. On the other hand, Wireshark on the receiver side never shows the payload.
accept_all should only mean it will accept any message no matter the recipient MAC. Sound like there may be a MAC address mismatch.
As for the missing function, I used/use scapy version 2.5.0 for development, so the function must be removed for version 2.6.0. I'll take a look.
There was a reason for the strange method of gathering the local MAC, I'll have to try and track down why I did it like that initially. It may be related to local MAC spoofing.
I'll keeping looking.
Hi guys, I was trying to test this, and I have the same issue. I tried with the PR mentioned but nothing. With the PR I don't have any error, but the sniffer example don't capture nothing. I tried with all channels but nothing. Also my wireless device supports monitor mode, I guess, because the iwconfing command show this:
lp4s0 IEEE 802.11 Mode:Monitor Frequency:2.447 GHz Tx-Power=3 dBm
Retry short limit:7 RTS thr:off Fragment thr:off
Power Management:on
And lshw command show:
capabilities: pciexpress msi pm bus_master cap_list logical wireless
configuration: broadcast=yes driver=mt7921e driverversion=6.1.0-0.deb11.17-amd6
Also I did the steps for run this with privileges. But I have some doubts with this step:
sudo setcap cap_net_raw=eip env/bin/python_netraw
One question, I was trying it with a esp32 that is sending packages from C++, don't matter right?
Hi guys, I was trying to test this, and I have the same issue. I tried with the PR mentioned but nothing. With the PR I don't have any error, but the sniffer example don't capture nothing. I tried with all channels but nothing. Also my wireless device supports monitor mode, I guess, because the iwconfing command show this:
lp4s0 IEEE 802.11 Mode:Monitor Frequency:2.447 GHz Tx-Power=3 dBm Retry short limit:7 RTS thr:off Fragment thr:off Power Management:onAnd lshw command show:
capabilities: pciexpress msi pm bus_master cap_list logical wireless configuration: broadcast=yes driver=mt7921e driverversion=6.1.0-0.deb11.17-amd6Also I did the steps for run this with privileges. But I have some doubts with this step:
sudo setcap cap_net_raw=eip env/bin/python_netrawOne question, I was trying it with a esp32 that is sending packages from C++, don't matter right?
What does your python code look like? What does your ESP code look like?
Hi again,
I found the solution in my case, following the next steps:
- I used the PR #4
- I ran the aircrack kill process:
sudo airmon-ng check kill - I putted the mode monitor with aircrack:
sudo airmon-ng start wlp4s0 - I ran the prep.sh script but using the channel 1:
sudo bash prep.sh wlp4s0 1
And I have messages with the sniffer sample like this:
ESP-NOW message from 74:4D:BD:81:4E:FC to FF:FF:FF:FF:FF:FF: b'\xec\x13\x12d\x16\x8a))\x80\xb4~4\x94\xb9\xa0\x02\x8a(\xa0\x02\x92\x96\x92\x80\x1ai\r8\xd2\x11Lci)i(\x00\xa2\x8a(\x00\xa2\x8a(\x00\xa2\x8a(\x00\xa2\x92\x8a`\x14\xb4RP\x01E\x14R\x00\xa2\x8a(\x01E-6\x94P\x03\xa9i\xb4\xb4\x00\xb4RR\xd2\x01)\xc2\x9b\xde\x94\x1a\x00u%\x14P \xa2\x8a(\x00\xa2\x8aJ\x00\xff\xd9'
One question please, is possible use nanopb (protocol buffers) with this Python package? I'm coding the messages from the ESP32 using nanopb.
Thanks, pretty nice Python package.
What does your python code look like? What does your ESP code look like?
Sorry, I didn't reload the page and I didn't seen this question.
My Python code is the sample sniffer code without any change, but using the PR #4 My ESP32 code is my ESPNowCam library, I'm sending messages from an ESP32 XIAO Camera, using one of my samples, the XIAO-fpv-sender sample of this library