For all I know (I've done very little network programming, and that
was years ago using plain TCP and UDP -- worse, on a VMS system so it
wasn't the "UNIX style" socket interface), your network stack may still
be overriding the packet at some lower level and inserting the IP
associated with the interface the packet went out on...
I've only been intermittently following this thread, but back when I
added Python's raw packet support for Unix, the socket module was a
_very_ thin wrapper for the underlying OS network socket API. The
behavior of various types of sockets was defined entirely by the
underlying OS.
So, if you're trying to do something obscure (which it seems you are),
asking people who know how to do it in C on the relevent OS is
probably the best approach.
Below are examples of sending and receiving a completely raw packet on
Linux (where you provide _all_ the bytes: the MAC addreses, the
Ethernet type, everything).
------------------------------send------------------------------
#!/usr/bin/python
import sys,os,socket,struct
from optparse import OptionParser
p = OptionParser()
p.add_option("-i","--interface",dest="interface",metavar="<name>",type='str',default="eth0")
options,args = p.parse_args()
if len(args) != 1:
sys.stderr.write("you must provide a destination MAC address\n")
sys.exit(1)
def toHex(s):
return " ".join([("%02x" % ord(c)) for c in s])
ethProto = 0x5678
dstMacStr = args[0]
dstMacAddr = "".join(map(chr,[int(x,16) for x in dstMacStr.split(":")]))
s = socket.socket(socket.AF_PACKET, socket.SOCK_RAW, ethProto)
s.bind((options.interface,ethProto))
ifName,ifProto,pktType,hwType,hwAddr = s.getsockname()
srcMacAddr = hwAddr
ethHeader = struct.pack("!6s6sh",dstMacAddr,srcMacAddr,ethProto)
packet = ethHeader + "some ASCII data here"
sys.stdout.write("tx: %s\n" % toHex(packet))
s.send(packet)
s.close()
-----------------------------------------------------------------
------------------------------recv------------------------------
#!/usr/bin/python
import sys,os,socket,struct
from optparse import OptionParser
p = OptionParser()
p.add_option("-i","--interface",dest="interface",metavar="<name>",type='str',default="eth0")
options,args = p.parse_args()
if len(args) != 0:
sys.stderr.write("no arguments accepted\n")
sys.exit(1)
def toHex(s):
return " ".join([("%02x" % ord(c)) for c in s])
ethProto = 0x5678
s = socket.socket(socket.AF_PACKET, socket.SOCK_RAW, ethProto)
s.bind((options.interface,ethProto))
packet = s.recv(4096)
sys.stdout.write("rx: %s\n" % toHex(packet))
s.close()