I'm trying to break the /etc/network/interfaces file format on Ubuntu to the individual stanzas (as the man page calls them).
This is the sample interfaces file I test my script against:
# The loopback network interface
auto lo
iface lo inet loopback
auto eth0
iface eth0 inet static
address 192.168.2.7
netmask 255.255.255.0
network 192.168.2.0
broadcast 192.168.2.255
gateway 192.0.2.254
dns-nameservers 12.34.56.78 12.34.56.79
auto eth0:0
allow-hotplug eth0:0
iface eth0:0 inet static
address 192.168.1.43
netmask 255.255.255.0
auto eth1
iface eth1 inet dhcp
auto eth2
iface eth2 inet6 static
address 2001:db8::c0ca:1eaf
netmask 64
gateway 2001:db8::1ead:ed:beef
auto br0
iface br0 inet static
address 10.10.0.15
netmask 255.255.255.0
gateway 10.10.0.1
bridge_ports eth0 eth1
up /usr/sbin/brctl stp br0 on
What I need is an array of strings holding each stanza (iface, mapping, auto, allow-\w+, source(-\w+)? and comments) along with all the text that follows it until the start of next stanza.
I've tried code like this, which sounds like it should work, but it captures all stanzas in one string:
re.split(r'^(iface|mapping|auto|allow-\w+|source(-\w)?|#.*)[.\n]+?',
open('/etc/network/interfaces').read(), flags=re.MULTILINE)
How can I correct the regex to achieve this?
Python version is 2.7
You don't need a regex:
def stanza(fle):
with open(fle) as f:
vals = ("iface", "mapping", "auto", "allow-", "source")
tmp = []
for line in f:
if line.startswith(vals):
yield tmp
tmp = [line]
else:
tmp.append(line)
if tmp:
yield tmp
from pprint import pprint as pp
pp(list(stanza("foo.txt")))
Output:
[['# The loopback network interface\n'],
['auto lo\n'],
['iface lo inet loopback\n', '\n'],
['auto eth0\n'],
['iface eth0 inet static\n',
' address 192.168.2.7\n',
' netmask 255.255.255.0\n',
' network 192.168.2.0\n',
' broadcast 192.168.2.255\n',
' gateway 192.0.2.254\n',
' dns-nameservers 12.34.56.78 12.34.56.79\n',
'\n'],
['auto eth0:0\n'],
['allow-hotplug eth0:0\n'],
['iface eth0:0 inet static\n',
' address 192.168.1.43\n',
' netmask 255.255.255.0\n',
'\n'],
['auto eth1\n'],
['iface eth1 inet dhcp\n', '\n'],
['auto eth2\n'],
['iface eth2 inet6 static\n',
' address 2001:db8::c0ca:1eaf\n',
' netmask 64\n',
' gateway 2001:db8::1ead:ed:beef\n',
'\n'],
['auto br0\n'],
['iface br0 inet static\n',
' address 10.10.0.15\n',
' netmask 255.255.255.0\n',
' gateway 10.10.0.1\n',
' bridge_ports eth0 eth1\n',
' up /usr/sbin/brctl stp br0 on']]
If you want to remove the whitespace strip it off with line.strip().
Related
I have 2 files 1st one is original data and 2nd one is after some modification (eg - network/storage level). So I want to compare 1st file with new one and create a file with what new added / modified lines.
for eg:
file1 - original file
Route table:
Route table:
10.208.85.0/26 dev eth3 proto kernel scope link src 10.1.108.12
148.89.140.0/22 via 192.168.10.1 dev eth0
148.89.168.0/21 via 192.168.10.1 dev eth0
151.87.44.0/23 via 192.168.10.1 dev eth0
151.87.46.0/23 via 192.168.10.1 dev eth0
192.55.16.128/28 via 192.168.10.1 dev eth0
192.55.28.32/27 via 192.168.10.1 dev eth0
192.55.28.64/28 via 192.168.10.1 dev eth0
192.55.192.96/27 via 192.168.10.1 dev eth0
192.60.136.0/22 via 192.168.10.1 dev eth0
192.62.212.64/26 via 192.168.10.1 dev eth0
Disks:
Disk /dev/sda: 96 GiB, 103079215104 bytes, 201326592 sectors
/dev/sda1 * 2048 1060863 1058816 517M 83 Linux
/dev/sda2 1060864 201326591 200265728 95.5G 8e Linux LVM
file2 - Modified
Route table:
10.208.85.0/26 dev eth3 proto kernel scope link src 10.1.108.12
10.123.17.64/26 via 10.1.208.1 dev eth2
148.89.140.0/22 via 192.168.10.1 dev eth0
148.89.168.0/21 via 192.168.10.1 dev eth0
151.87.44.0/23 via 192.168.10.1 dev eth0
151.87.46.0/23 via 192.168.10.1 dev eth0
192.55.16.128/28 via 192.168.10.1 dev eth0
192.55.28.32/27 via 192.168.10.1 dev eth0
192.55.28.64/28 via 192.168.10.1 dev eth0
192.55.192.96/27 via 192.168.10.1 dev eth0
192.60.136.0/22 via 192.168.10.1 dev eth0
192.62.212.64/26 via 192.168.10.1 dev eth0
Disks:
Disk /dev/sda: 128 GiB, 137438953472 bytes, 201326592 sectors
/dev/sda1 * 2048 1060863 1058816 517M 83 Linux
/dev/sda2 1060864 201326591 200265728 95.5G 8e Linux LVM
I am looking an output something like (another file )
Added : 10.123.17.64/26 via 10.1.208.1 dev eth2
Modified : Disk /dev/sda: 128 GiB, 137438953472 bytes, 201326592 sectors
Please help
As starting point, you can use difflib:
from difflib import Differ
with (open('file1.txt') as file_1,
open('file2.txt') as file_2):
differ = Differ()
for line in differ.compare(file_1.readlines(), file_2.readlines()):
if line[0] in list('+-?'):
print(line.strip())
Output:
+ 10.123.17.64/26 via 10.1.208.1 dev eth2
- Disk /dev/sda: 96 GiB, 103079215104 bytes, 201326592 sectors
? ^^ - - -----
+ Disk /dev/sda: 128 GiB, 137438953472 bytes, 201326592 sectors
? ^^^ +++ ++++
In linux you can use diff to compare files line by line.
Let us consider the 2 example files provided in your question.
The Command:
diff /tmp/file1.txt /tmp/file2.txt
The Output:
2a3
> 10.123.17.64/26 via 10.1.208.1 dev eth2
15c16
< Disk /dev/sda: 96 GiB, 103079215104 bytes, 201326592 sectors
---
> Disk /dev/sda: 128 GiB, 137438953472 bytes, 201326592 sectors
The Command to generate the desired output:
diff /tmp/file1.txt /tmp/file2.txt | sed -e ':begin;$!N;s/---\n>/Modified: /;tbegin' -e 's/>/Added: /g' | egrep 'Added|Modified'
The Desired Output:
Added: 10.123.17.64/26 via 10.1.208.1 dev eth2
Modified: Disk /dev/sda: 128 GiB, 137438953472 bytes, 201326592 sectors
I have a raspberry pi that is both connected to the internet via Wlan and a local device via Ethernet. So it has two IPs; one for each endpoint.
This is how it looks like simplified when running ifconfig; with different IPs for privacy
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 189.168.200.110 netmask 0.0.0.0 broadcast 255.255.255.255
wlan0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 189.168.201.79 netmask 255.255.255.0 broadcast 192.168.1.255
This is the code that python is using to send a message to the device through the Ethernet with that gateway's ip
TCP_PORT = 3001
SERVER_IP_AD = "189.168.200.110"
CLIENT_IP_AD = "189.168.200.155"
BROADCAST_IP = "255.255.255.255"
def sendMessage(self, file_path, client_ip=CLIENT_IP_AD):
print('message en route')
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((self.SERVER_IP_AD, 0))
s.connect((client_ip, self.TCP_PORT)) #**ERROR IS HERE**
MESSAGE = self.openFile(file_path)
s.send(MESSAGE.encode())
data = s.recv(self.BUFFER_SIZE)
s.close()
return data
Using wireshark I can see that the package is being sent through the Wlan interface instead of the Ethernet interface with the correct IP source and IP destination.
How do I tell python to use the correct interface when sending out the package?
In my opinion, you can establish Tcp connection with Ethernet, cause there isn't shaking hands by Ethernet
And, you shouldn't use s.bind() and s.connect() at the same time. Because the former is for UDP client, and the later is for TCP client. Have a try with only s.bind().
First time posting an ongoing learning about Python.
Currently, I'm stuck with a very simple thing: I've a router's output - a list called "interfaces" - which, when printed, looks like this:
set interfaces ge-0/0/0 unit 0 family inet address 192.168.15.66/24
set interfaces ge-0/0/1 unit 0 family inet dhcp
set interfaces ge-0/0/2 unit 0 family inet address 1.1.1.1/30
set interfaces ge-0/0/2 unit 0 family inet address 192.168.99.1/30
Using re module (findall), I'm finding and matching some keywords that I need, like this:
pattern1 = re.compile(r'ge.{1,7}')
pattern2 = re.compile(r'dhcp')
matched1 = pattern1.findall(interfaces)
matched2 = pattern2.findall(interfaces)
At this point, question is: If the line(?) of this router output contains the word "dhcp", I would like to save/store that value and grab the interface name/number too. In the example above, the interface cointaining "dhcp" is 'ge-0/0/1'. Do you guys have an idea if i'm going on the right path?
Is the model (get two regex) useful, to then merge both value into a dictionary, to then print using return?
How can I parse the rest of router code lines, to look for this "dhcp" value and then if no match can return a "none" or "not present" output?
Expected output will look like this (I'm using "return tabulate" to print the output):
| interface | service |
|-------------+------------|
| ge-0/0/0 | none |
| ge-0/0/1 | dhcp |
| ge-0/0/2 | none |
Any guidance, will be welcomed.
Thanks.
EDIT: Thanks both for your answers so far. I'm adding more info since probably is key.
The way I get that router output is using SaltStack integrated modules. I'm running that python file from the Salt Master, using the following syntax:
interfaces = __salt__['net.cli']('show configuration interfaces | display set', format='xml')['out']['show configuration interfaces | display set']
I sincerely hope that output is in fact a list.
In the meantime, I did another try using the following below:
def dhcp():
interfaces = __salt__['net.cli']('show configuration interfaces | display set', format='xml')['out']['show configuration interfaces | display set']
pattern = re.findall(r'ge.{1,7}', interfaces)
pattern1 = re.findall(r'dhcp', interfaces)
return pattern, pattern1
The output was this:
outright ~ sudo salt 'vsrx1' red.dhcp
vsrx1:
|_
- ge-0/0/0
- ge-0/0/0
- ge-0/0/0
- ge-0/0/0
- ge-0/0/1
- ge-0/0/2
- ge-0/0/2
|_
- dhcp
Printing the list alone (using --> return("List is: " + str(pattern)) )
outright ~ sudo salt 'vsrx1' red.dhcp
vsrx1:
List is: ['ge-0/0/0 ', 'ge-0/0/0 ', 'ge-0/0/0 ', 'ge-0/0/0 ', 'ge-0/0/1 ', 'ge-0/0/2 ', 'ge-0/0/2 ']
I do apologies if the way to express the issue is technically poor. I'm still learning the terminology in general.
You seem to me that you are on the right track. Here is my interpretation of what I think you are asking for. Hope this helps.
Note: I did this through my phone, so please excuse incorrect indentations
import re
s = ["set interfaces ge-0/0/0 unit 0 family inet address 192.168.15.66/24",
"set interfaces ge-0/0/1 unit 0 family inet dhcp", "set interfaces ge-0/0/2 unit 0 family inet address 1.1.1.1/30",
"set interfaces ge-0/0/2 unit 0 family inet address 192.168.99.1/30"]
print("interfaces | services")
mydict ={}
def parse_addresses():
for i in s:
interface = re.search(r"ge.{1,7}", i)
if "dhcp" in i:
service = "dhcp"
mydict.setdefault("router",{interface.group(): service})
else:
service = "None"
print(f"{interface.group()} | {service}")
if bool(mydict):
return mydict
return "None"
print(parse_addresses())
I am not sure how you get the router's output. But this should work
If your data is in this form
interface_list = ['set interfaces ge-0/0/0 unit 0 family inet address 192.168.15.66/24',
'set interfaces ge-0/0/1 unit 0 family inet dhcp',
'set interfaces ge-0/0/2 unit 0 family inet address 1.1.1.1/30',
'set interfaces ge-0/0/2 unit 0 family inet address 192.168.99.1/30']
Then
interface_dict = {}
for element in interface_list:
element_list = element.split(" ")
if element_list[7] =='dhcp':
interface_dict[element_list[2]] = 'dhcp'
else:
interface_dict[element_list[2]] = 'none'
print(interface_dict)
will give you
{'ge-0/0/0': 'none', 'ge-0/0/1': 'dhcp', 'ge-0/0/2': 'none'}
You can then change the dictionary to the dataframe
import pandas as pd
df = pd.Series(interface_dict).to_frame().reset_index().rename(columns={'index':'interface', 0:'service'})
df
interface service
0 ge-0/0/0 none
1 ge-0/0/1 dhcp
2 ge-0/0/2 none
Thanks to all who viewed and oriented me in several possible directions.
I'm answering to my own question (90% at least). My final script follows (And yes, I know that my code can be 100% improved, but is what I did to reach my goal):
def final():
interfaces = []
output_table1 = []
output_table2 = []
interfaces = __salt__['net.cli']('show configuration interfaces | display set', format='xml')['out']['show configuration interfaces | display set']
# Saving output into a file for further use
with open("/srv/salt/_modules/aaa.txt", "w") as file:
file.write(interfaces)
# Regex patterns to match things
regex1 = re.compile(r'(ge.{1,7}.{7}).*?(?=sampling)')
match_reg1 = regex1.finditer(interfaces)
regex2 = re.compile(r'ge.{1,7}.{7}')
match_reg2 = regex2.finditer(interfaces)
# IF stataments and FOR, to match and append items
if match_reg1:
output_table1.insert(0, "Sampled interfaces")
for match1 in match_reg1:
output_table1.append(match1.group(1))
if match_reg2:
output_table2.insert(0, "Not sampled interfaces")
for match2 in match_reg2:
output_table2.append(match2.group())
# Differences between two tables:
difference_list = []
for item in output_table2:
if item not in output_table1:
difference_list.append(item)
final = []
final.insert(0, "To enable sampling, insert the following on target device")
for line in difference_list:
final.append("set interfaces " + line + "family inet sampling [input/output]")
return output_table1, difference_list, final
After above, my output was:
terminal# sudo salt 'vsrx1' red.final
vsrx1:
|_
- Sampled interfaces
- ge-0/0/1 unit 0
- ge-0/0/1 unit 0
|_
- Not sampled interfaces
- ge-0/0/0 descrip
- ge-0/0/0 unit 0
- ge-0/0/2 unit 0
- ge-0/0/2 unit 0
|_
- To enable sampling, insert the following on target device
- set interfaces Not sampled interfacesfamily inet sampling [input/output]
- set interfaces ge-0/0/0 descripfamily inet sampling [input/output]
- set interfaces ge-0/0/0 unit 0 family inet sampling [input/output]
- set interfaces ge-0/0/2 unit 0 family inet sampling [input/output]
- set interfaces ge-0/0/2 unit 0 family inet sampling [input/output]
Please remember that I'm using Saltstack proxy minions to pull information from that Juniper vSRX device. I now need to practice more REGEX to remove all unnecesary output data and be more accurated on what I want to see, like the example above (is still dirty), but the basic goal was achived.
Another challenge that I had at the beginning was to understand the output of that "interfaces = salt['net.cli']('show configuration interfaces..." was because I thought every router command line was an item/line inside my list. When saving it in "aaa.txt" file and then printing it, it was printed different from what I had in mind:
This is the file opened by VisualCode (file called aaa.txt):
set interfaces ge-0/0/0 description vsrx1_descr_test
set interfaces ge-0/0/0 unit 0 family inet address 192.168.15.66/24
set interfaces ge-0/0/1 unit 0 family inet sampling input
set interfaces ge-0/0/1 unit 0 family inet sampling output
set interfaces ge-0/0/1 unit 0 family inet dhcp
set interfaces ge-0/0/2 unit 0 family inet address 1.1.1.1/30
set interfaces ge-0/0/2 unit 0 family inet address 192.168.99.1/30
This is the file printed by the function:
terminal# sudo salt 'vsrx1' red.final
vsrx1:
set interfaces ge-0/0/0 description vsrx1_descr_test
set interfaces ge-0/0/0 unit 0 family inet address 192.168.15.66/24
set interfaces ge-0/0/1 unit 0 family inet sampling input
set interfaces ge-0/0/1 unit 0 family inet sampling output
set interfaces ge-0/0/1 unit 0 family inet dhcp
set interfaces ge-0/0/2 unit 0 family inet address 1.1.1.1/30
set interfaces ge-0/0/2 unit 0 family inet address 192.168.99.1/30
And when changes the SALT function like:
interfaces = __salt__['net.cli']('show configuration interfaces | display set', format='xml')['out']['show configuration interfaces | display set']"
to this:
interfaces = __salt__['net.cli']('show configuration interfaces | display set', format='xml')['out']
The output was printed vertically, like this:
s
e
t
i
n
t
e
r
and so on. I broke my head with that one.
Hope this helps. And as always, any correction is welcomed.
Cristian.
I'm using Mininet's API with python, right now all these addresses are on the same subnet for the network that connects the 3 routers (192.168.1.0/24) how do I make these unique? Do I change the netmasks?
r1.cmd('ifconfig r1-eth0 inet 10.1.1.3 netmask 255.255.255.0')
#connect routers
r1.cmd('ifconfig r1-eth1 inet 192.168.1.1 netmask 255.255.255.0')
r1.cmd('ifconfig r1-eth2 inet 192.168.1.3 netmask 255.255.255.0')
r2.cmd('ifconfig r2-eth0 inet 192.168.1.2 netmask 255.255.255.0')
r2.cmd('ifconfig r2-eth1 inet 192.168.1.5 netmask 255.255.255.0')
r2.cmd('ifconfig r2-eth2 inet 10.1.2.6 netmask 255.255.255.0')
r3.cmd('ifconfig r3-eth0 inet 192.168.1.4 netmask 255.255.255.0')
r3.cmd('ifconfig r3-eth1 inet 192.168.1.6 netmask 255.255.255.0')
r3.cmd('ifconfig r3-eth2 inet 10.1.3.27 netmask 255.255.255.0')
# Add static routes
info( '*** Adding static routes\n')
r1.cmd('ip route add 10.1.9.1/24 via 192.168.1.2 dev r1-eth1')
r2.cmd('ip route add 10.1.9.2/24 via 192.168.1.1 dev r2-eth0')
r1.cmd('ip route add 10.1.7.1/24 via 192.168.1.4 dev r1-eth2')
r3.cmd('ip route add 10.1.7.2/24 via 192.168.1.3 dev r3-eth0')
r2.cmd('ip route add 10.1.8.2/24 via 192.168.1.6 dev r2-eth1')
r3.cmd('ip route add 10.1.8.1/24 via 192.168.1.5 dev r3-eth1')
On my mac the wireless interface is the en1 interface. I can put the interface into monitor mode using mac's airport application but then it doesn't work with the scapy module when i use python 3. How can i make this work?
Thanks in advance
ifconfig output
lo0: flags=8049<UP,LOOPBACK,RUNNING,MULTICAST> mtu 16384
options=3<RXCSUM,TXCSUM>
inet6 ::1 prefixlen 128
inet 127.0.0.1 netmask 0xff000000
inet6 fe80::1%lo0 prefixlen 64 scopeid 0x1
nd6 options=1<PERFORMNUD>
gif0: flags=8010<POINTOPOINT,MULTICAST> mtu 1280
stf0: flags=0<> mtu 1280
en0: flags=8863<UP,BROADCAST,SMART,RUNNING,SIMPLEX,MULTICAST> mtu 1500
options=10b<RXCSUM,TXCSUM,VLAN_HWTAGGING,AV>
nd6 options=1<PERFORMNUD>
media: autoselect (none)
status: inactive
fw0: flags=8863<UP,BROADCAST,SMART,RUNNING,SIMPLEX,MULTICAST> mtu 4078
lladdr 00:3e:e1:ff:fe:0f:0a:4a
nd6 options=1<PERFORMNUD>
media: autoselect <full-duplex>
status: inactive
en1: flags=8863<UP,BROADCAST,SMART,RUNNING,SIMPLEX,MULTICAST> mtu 1500
inet6 fe80::7ed1:c3ff:fe6e:eeda%en1 prefixlen 64 scopeid 0x6
inet 192.168.1.2 netmask 0xffffff00 broadcast 192.168.1.255
nd6 options=1<PERFORMNUD>
media: autoselect
status: active
en2: flags=8963<UP,BROADCAST,SMART,RUNNING,PROMISC,SIMPLEX,MULTICAST> mtu 1500
options=60<TSO4,TSO6>
media: autoselect <full-duplex>
status: inactive
p2p0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> mtu 2304
media: autoselect
status: inactive
awdl0: flags=8943<UP,BROADCAST,RUNNING,PROMISC,SIMPLEX,MULTICAST> mtu 1452
inet6 fe80::18b8:64ff:fec8:85%awdl0 prefixlen 64 scopeid 0x9
nd6 options=1<PERFORMNUD>
media: autoselect
status: active
bridge0: flags=8863<UP,BROADCAST,SMART,RUNNING,SIMPLEX,MULTICAST> mtu 1500
options=63<RXCSUM,TXCSUM,TSO4,TSO6>
Configuration:
id 0:0:0:0:0:0 priority 0 hellotime 0 fwddelay 0
maxage 0 holdcnt 0 proto stp maxaddr 100 timeout 1200
root id 0:0:0:0:0:0 priority 0 ifcost 0 port 0
ipfilter disabled flags 0x2
member: en2 flags=3<LEARNING,DISCOVER>
ifmaxaddr 0 port 7 priority 0 path cost 0
nd6 options=1<PERFORMNUD>
media: <unknown type>
status: inactive
Python Script To Detected Packets (After putting en1 into mon mode using airport)
from scapy.all import *
def pktIdentifier(pkt):
if pkt.haslayer(Dot11Beacon):
print ("[+] Detected 802.11 Beacon Frame")
elif pkt.haslayer(Dot11ProbeReq):
print ("[+] Detected 802.11 Probe Frame")
elif pkt.haslayer(TCP):
print ("[+] Detected TCP Packet")
elif pky.haslayer(UDP):
print ("[+] Detected UDP Packet")
conf.iface = 'en1'
sniff(prn=pktIdentifier)
Output of conf.route
Network Netmask Gateway Iface Output IP
0.0.0.0 0.0.0.0 192.168.0.1 en1 192.168.0.7
127.0.0.0 255.0.0.0 0.0.0.0 lo0 127.0.0.1
127.0.0.1 255.255.255.255 0.0.0.0 lo0 127.0.0.1
169.254.0.0 255.255.0.0 0.0.0.0 en1 192.168.0.7
192.168.0.0 255.255.255.0 0.0.0.0 en1 192.168.0.7
192.168.0.1 255.255.255.255 0.0.0.0 en1 192.168.0.7
192.168.0.1 255.255.255.255 0.0.0.0 en1 192.168.0.7
192.168.0.7 255.255.255.255 0.0.0.0 en1 192.168.0.7
192.168.0.255 255.255.255.255 0.0.0.0 en1 192.168.0.7
Short Answer: You could MonkeyPatch the _PcapWrapper_pypcap class. An example Code is provided below.
Slightly Longer Answer: On Mac OS X scapy sniffs on interfaces through libpcap. Instead of calling pcap_open_live we call pcap_create, pcap_set_rfmon and pcap_activate (in this order). This will set the interface in monitor mode and start capturing. I tested the following MonkeyPatch under scapy-python3 (0.21) and macOS Sierra 10.12.6. Make sure you run this Code with admin rights.
from scapy.all import *
import scapy.arch.pcapdnet
from ctypes import POINTER, byref, create_string_buffer
from ctypes.util import find_library
class _PcapWrapper_pypcap_monkeypatched(scapy.arch.pcapdnet._PcapWrapper_pypcap):
def __init__(self, device, snaplen, promisc, to_ms):
self.errbuf = create_string_buffer(PCAP_ERRBUF_SIZE)
self.iface = create_string_buffer(device.encode('ascii'))
#self.pcap = pcap_open_live(self.iface, snaplen, promisc, to_ms, self.errbuf)
STRING = c_char_p
_lib_name = find_library("pcap")
if not _lib_name:
raise OSError("Cannot fine libpcap.so library")
_lib=CDLL(_lib_name)
pcap_create = _lib.pcap_create
pcap_create.restype = POINTER(pcap_t)
pcap_create.argtypes = [STRING, STRING]
pcap_set_rfmon = _lib.pcap_set_rfmon
pcap_set_rfmon.restype = c_int
pcap_set_rfmon.argtypes = [POINTER(pcap_t), c_int]
pcap_activate = _lib.pcap_activate
pcap_activate.restype = c_int
pcap_activate.argtypes = [POINTER(pcap_t)]
self.pcap = pcap_create(self.iface, self.errbuf)
pcap_set_rfmon(self.pcap, 1)
pcap_activate(self.pcap)
self.header = POINTER(pcap_pkthdr)()
self.pkt_data = POINTER(c_ubyte)()
self.bpf_program = bpf_program()
scapy.arch.pcapdnet._PcapWrapper_pypcap = _PcapWrapper_pypcap_monkeypatched
def pktIdentifier(pkt):
if pkt.haslayer(Dot11Beacon):
print("[+] Detected 802.11 Beacon Frame")
elif pkt.haslayer(Dot11ProbeReq):
print("[+] Detected 802.11 Probe Frame")
sniff(iface="en0", prn=pktIdentifier)
When using the sniff function setting monitor=True on Mac OS Catalina always works for me. Example: scapy.all.sniff(iface='en0, monitor=True) then obviously what ever other functions you want.
This is a possible answer: http://www.cqure.net/wp/2014/04/scapy-with-wifi-monitor-rfmon-mode-on-os-x/
If you will file a bug on http://github.com/phaethon/scapy I will assist with patching part.