views:

2981

answers:

5

I am writing an application to test a network driver for handling corrupted data. And I thought of sending this data using raw socket, so it will not be corrected by the sending machine's TCP-IP stack.

I am writing this application solely on Linux. I have code examples of using raw sockets in system-calls, but I would really like to keep my test as dynamic as possible, and write most if not all of it in Python.

I have googled the web a bit for explanations and examples of the usage of raw sockets in python, but haven't found anything really enlightening. Just a a very old code example that demonstrates the idea, but in no means work.

From what I gathered, Raw Socket usage in Python is nearly identical in semantics to UNIX's raw socket, but without the structs that define the packets structure.

I was wondering if it would even be better not to write the raw socket part of the test in Python, but in C with system-calls, and call it from the main Python code?

A: 

The socket class should help. If not you'll need to either write a Python module in C or just use C. See http://mail.python.org/pipermail/python-list/2001-April/077454.html.

Basic Googling found that.

I have reviewed this post on my first googling escapades, and didn't find that very helpful. Most the discussion is there is very out-dated. `AF_PACKET` no longer appears in Python.
Avihu Turzion
A: 

Is this the old code you mentioned finding? It looks sensible to me, but I haven't tested it myself (or used raw sockets much). This example from the documentation shows how to use raw sockets to sniff packets, and it looks similar enough.

unwind
**This is exactly the code example I was talking about!**. It's problem is that it's use of initilizations of the socket, and protocols are completely deprecated. Moreover, I think it's a sort of mish-mash of server and client sides into one concept app.
Avihu Turzion
Right, it seems the AF_PACKET address family is no longer around. The second example (reproduced in Bastien's answer) uses AF_INET, I guess that might make sense. If all you want to test is sending data (to check for e.g. pattern-based corruption or whatever), the addressing shouldn't matter. I think the first example "mixes concepts" by doing a totally synchronous send followed by receive call. Not very common or nice, but should be legal.
unwind
+3  A: 

Sockets system calls (or Winsocks, on Windows), are already wrapped in the standard module socket: intro, reference.

I've never used raw sockets but it looks like they can be used with this module:

The last example shows how to write a very simple network sniffer with raw sockets on Windows. The example requires administrator privileges to modify the interface:

import socket

# the public network interface
HOST = socket.gethostbyname(socket.gethostname())

# create a raw socket and bind it to the public interface
s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_IP)
s.bind((HOST, 0))

# Include IP headers
s.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, 1)

# receive all packages
s.ioctl(socket.SIO_RCVALL, socket.RCVALL_ON)

# receive a package
print s.recvfrom(65565)

# disabled promiscuous mode
s.ioctl(socket.SIO_RCVALL, socket.RCVALL_OFF)
Bastien Léonard
This is exactly the code example unwind links to in his answer. It's a good one, but I need to know how I send raw data. In all my attempts based on these examples, the raw data I built simply wasn't sent. Even when I tried sending raw sampled packets, that did work instead of building my own.
Avihu Turzion
Aditya Sehgal
and when I said TCP or UDP, I really meant any protocol on top of IP that you want to build yourself.
Aditya Sehgal
A: 

i've a similar problem trying to send out raw ip packets. in fact the kernel must be responsible to lookup MAC addresses (ethernet). otherwise it won't know where to send the packets. if i figure out how it works, i'll report back. OR: If someone has a solution, please report it. I've tried with this code so far, but w/o luck:

self.rawserver = socket.socket(socket.AF_INET, socket.SOCK_RAW, self.proto) self.rawserver.bind((self.interface, self.proto))

+2  A: 

Eventually the best solution for this case was to write the entire thing in C, because it's not a big application, so it would've incurred greater penalty to write such a small thing in more than 1 language.

After much toying with both the C and python RAW sockets, I eventually preferred the C RAW sockets. RAW sockets require bit-level modifications of less than 8 bit groups for writing the packet headers. Sometimes writing only 4 bits or less. python defines no assistance to this, whereas Linux C has a full API for this.

But I definitely believe that if only this little bit of header initialization was handled conveniently in python, I would've never used C here.

Avihu Turzion
This doesn't answer the question.
Beau Martínez
I agree that as an overall point of view of whether Python RAW sockets are preferred to C RAW sockets, this doesn't answer the question. But eventually this related to the problem I was dealing with at the time, and this solved the issue, and hence was the correct answer as far as I'm concerned.
Avihu Turzion