Since you're using cBPF (classic BPF), the only way to filter a set of IP addresses is to list them all:
bpf_filter = "ip and ("
for addr in addresses[:-1]:
bpf_filter = "%shost %s or " % (bpf_filter, addr)
bpf_filter = "%shost %s)" % (bpf_filter, addresses[-1])
Which, for a set of IP addresses [10.0.0.1, 10.0.0.2, 10.0.0.3]
, will return:
ip and (host 10.0.0.1 or host 10.0.0.2 or host 10.0.0.3)
Note: You need at least one IP address in your set for the above to work.
Why is this a limitation of cBPF?
The filter expression you give Scapy is then compiled to BPF bytecode. BPF bytecode disallows backward jumps (and therefore loops). This restriction is a simple way to ensure the filter will eventually halt when executed in the kernel.
If backward jumps were allowed, you could write some smarter lookup through your set of IP addresses. You could for example store them in a hash table and check the packet against the hash table in O(1). This is actually possible with eBPF, which, as far as I know, isn't supported by Scapy yet.