- from binascii import hexlify
- from ctypes import create_string_buffer, addressof
- from socket import socket, AF_PACKET, SOCK_RAW, SOL_SOCKET
- from struct import pack, unpack
- # A subset of Berkeley Packet Filter constants and macros, as defined in
- # linux/filter.h.
- # Instruction classes
- BPF_LD = 0x00
- BPF_JMP = 0x05
- BPF_RET = 0x06
- # ld/ldx fields
- BPF_H = 0x08
- BPF_B = 0x10
- BPF_ABS = 0x20
- # alu/jmp fields
- BPF_JEQ = 0x10
- BPF_K = 0x00
- def bpf_jump(code, k, jt, jf):
- return pack('HBBI', code, jt, jf, k)
- def bpf_stmt(code, k):
- return bpf_jump(code, k, 0, 0)
- # Ordering of the filters is backwards of what would be intuitive for
- # performance reasons: the check that is most likely to fail is first.
- filters_list = [
- # Must have dst port 67. Load (BPF_LD) a half word value (BPF_H) in
- # ethernet frame at absolute byte offset 36 (BPF_ABS). If value is equal to
- # 67 then do not jump, else jump 5 statements.
- bpf_stmt(BPF_LD | BPF_H | BPF_ABS, 36),
- bpf_jump(BPF_JMP | BPF_JEQ | BPF_K, 67, 0, 5),
- # Must be UDP (check protocol field at byte offset 23)
- bpf_stmt(BPF_LD | BPF_B | BPF_ABS, 23),
- bpf_jump(BPF_JMP | BPF_JEQ | BPF_K, 0x11, 0, 3),
- # Must be IPv4 (check ethertype field at byte offset 12)
- bpf_stmt(BPF_LD | BPF_H | BPF_ABS, 12),
- bpf_jump(BPF_JMP | BPF_JEQ | BPF_K, 0x0800, 0, 1),
- bpf_stmt(BPF_RET | BPF_K, 0x0fffffff), # pass
- bpf_stmt(BPF_RET | BPF_K, 0), # reject
- ]
- # Create filters struct and fprog struct to be used by SO_ATTACH_FILTER, as
- # defined in linux/filter.h.
- filters = ''.join(filters_list)
- b = create_string_buffer(filters)
- mem_addr_of_filters = addressof(b)
- fprog = pack('HL', len(filters_list), mem_addr_of_filters)
- # As defined in asm/socket.h
- SO_ATTACH_FILTER = 26
- # Create listening socket with filters
- s = socket(AF_PACKET, SOCK_RAW, 0x0800)
- s.setsockopt(SOL_SOCKET, SO_ATTACH_FILTER, fprog)
- s.bind(('eth0', 0x0800))
- while True:
- data, addr = s.recvfrom(65565)
- print 'got data from', addr, ':', hexlify(data)
Friday, December 30, 2011
Raw sockets with BPF in Python
Update 2021: Note that this was written in 2011. Nowadays I'd not recommend doing it this way, but instead using BCC to write your filters in C, from within Python.
The following example shows the use of raw sockets where filtering is applied using BPF. It has only been tested on Linux.
The filter data structure is built up to form a machine language-like set of instructions that decide whether the packet should be passed to the raw socket or not. The filter is applied to the socket using SO_ATTACH_FILTER.
This specific example filters packets to only allow packets destined a DHCP server (UDP port 67).
Thursday, December 08, 2011
Simple heap implementation in C#
I recently needed a simple priority queue in C# and was surprised to find that there is neither anything called "priority queue" nor "min heap" or "max heap" in .NET (or at least I did not find it when I looked). Here is a textbook-like implementation I came up with:
- class MinHeap<T> where T : IComparable
- {
- private List<T> data = new List<T>();
- public void Insert(T o)
- {
- data.Add(o);
- int i = data.Count - 1;
- while (i > 0)
- {
- int j = (i + 1) / 2 - 1;
- // Check if the invariant holds for the element in data[i]
- T v = data[j];
- if (v.CompareTo(data[i]) < 0 || v.CompareTo(data[i]) == 0)
- {
- break;
- }
- // Swap the elements
- T tmp = data[i];
- data[i] = data[j];
- data[j] = tmp;
- i = j;
- }
- }
- public T ExtractMin()
- {
- if (data.Count < 0)
- {
- throw new ArgumentOutOfRangeException();
- }
- T min = data[0];
- data[0] = data[data.Count - 1];
- data.RemoveAt(data.Count - 1);
- this.MinHeapify(0);
- return min;
- }
- public T Peek()
- {
- return data[0];
- }
- public int Count
- {
- get { return data.Count; }
- }
- private void MinHeapify(int i)
- {
- int smallest;
- int l = 2 * (i + 1) - 1;
- int r = 2 * (i + 1) - 1 + 1;
- if (l < data.Count && (data[l].CompareTo(data[i]) < 0))
- {
- smallest = l;
- }
- else
- {
- smallest = i;
- }
- if (r < data.Count && (data[r].CompareTo(data[smallest]) < 0))
- {
- smallest = r;
- }
- if (smallest != i)
- {
- T tmp = data[i];
- data[i] = data[smallest];
- data[smallest] = tmp;
- this.MinHeapify(smallest);
- }
- }
- }
class MinHeap<T> where T : IComparable { private List<T> data = new List<T>(); public void Insert(T o) { data.Add(o); int i = data.Count - 1; while (i > 0) { int j = (i + 1) / 2 - 1; // Check if the invariant holds for the element in data[i] T v = data[j]; if (v.CompareTo(data[i]) < 0 || v.CompareTo(data[i]) == 0) { break; } // Swap the elements T tmp = data[i]; data[i] = data[j]; data[j] = tmp; i = j; } } public T ExtractMin() { if (data.Count < 0) { throw new ArgumentOutOfRangeException(); } T min = data[0]; data[0] = data[data.Count - 1]; data.RemoveAt(data.Count - 1); this.MinHeapify(0); return min; } public T Peek() { return data[0]; } public int Count { get { return data.Count; } } private void MinHeapify(int i) { int smallest; int l = 2 * (i + 1) - 1; int r = 2 * (i + 1) - 1 + 1; if (l < data.Count && (data[l].CompareTo(data[i]) < 0)) { smallest = l; } else { smallest = i; } if (r < data.Count && (data[r].CompareTo(data[smallest]) < 0)) { smallest = r; } if (smallest != i) { T tmp = data[i]; data[i] = data[smallest]; data[smallest] = tmp; this.MinHeapify(smallest); } } }
Subscribe to:
Posts (Atom)