James Mertz
James Mertz

Reputation: 8759

How do I implement a raw frame capture using Python 3.3?

Note: I'm not sure if this is a programming issue, or a hardware/OS specific related issue.

I'm trying to capture raw ethernet frames using Python 3.3's socket class. Looking directly at the example from the PyDoc's website:

import socket
import struct


# CAN frame packing/unpacking (see 'struct can_frame' in <linux/can.h>)

can_frame_fmt = "=IB3x8s"
can_frame_size = struct.calcsize(can_frame_fmt)

def build_can_frame(can_id, data):
    can_dlc = len(data)
    data = data.ljust(8, b'\x00')
    return struct.pack(can_frame_fmt, can_id, can_dlc, data)

def dissect_can_frame(frame):
    can_id, can_dlc, data = struct.unpack(can_frame_fmt, frame)
    return (can_id, can_dlc, data[:can_dlc])


# create a raw socket and bind it to the 'vcan0' interface
s = socket.socket(socket.AF_CAN, socket.SOCK_RAW, socket.CAN_RAW)
s.bind(('vcan0',))

while True:
    cf, addr = s.recvfrom(can_frame_size)

    print('Received: can_id=%x, can_dlc=%x, data=%s' % dissect_can_frame(cf))

    try:
        s.send(cf)
    except OSError:
        print('Error sending CAN frame')

    try:
        s.send(build_can_frame(0x01, b'\x01\x02\x03'))
    except OSError:
        print('Error sending CAN frame')

I get the following error:

OSError: [Errno 97] Address family not supported by protocol.

breaking at this specific line:

s = socket.socket(socket.AF_CAN, socket.SOCK_RAW, socket.CAN_RAW)

The only changes I've made to the code was the actual interface name (i.e. 'em1'). I'm using Fedora 15.

Looking further into the Python Source code it appears that the AF_CAN (address family) and the CAN_RAW (protocol) aren't the correct pair.

How do I capture raw ethernet frames for further processing?


Ultimately what I need to be able to do is capture raw ethernet frames and process them as this come into the system.

Upvotes: 1

Views: 1053

Answers (1)

James Mertz
James Mertz

Reputation: 8759

I was finally able to do this with the following:

import socket
import struct
import time


s = socket.socket(socket.AF_PACKET, socket.SOCK_RAW, socket.ntohs(0x0003))

test = []

while(1):
    now = time.time()
    message = s.recv(4096)
    # Process the message from here

Upvotes: 1

Related Questions