Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.python > #27479 > unrolled thread

How to set the socket type and the protocol of a socket using create_connection?

Started byGuillaume Comte <guillaume.comte10@gmail.com>
First post2012-08-20 02:14 -0700
Last post2012-08-23 13:53 +0000
Articles 17 — 6 participants

Back to article view | Back to comp.lang.python


Contents

  How to set the socket type and the protocol of a socket using create_connection? Guillaume Comte <guillaume.comte10@gmail.com> - 2012-08-20 02:14 -0700
    Re: How to set the socket type and the protocol of a socket using create_connection? Guillaume Comte <guillaume.comte10@gmail.com> - 2012-08-20 05:36 -0700
      Re: How to set the socket type and the protocol of a socket using create_connection? Hans Mulder <hansmu@xs4all.nl> - 2012-08-20 15:38 +0200
        Re: How to set the socket type and the protocol of a socket using create_connection? Guillaume Comte <guillaume.comte10@gmail.com> - 2012-08-20 08:04 -0700
          Re: How to set the socket type and the protocol of a socket using create_connection? Dave Angel <d@davea.name> - 2012-08-20 13:27 -0400
            Re: How to set the socket type and the protocol of a socket using create_connection? Guillaume Comte <guillaume.comte10@gmail.com> - 2012-08-21 10:00 -0700
            Re: How to set the socket type and the protocol of a socket using create_connection? Guillaume Comte <guillaume.comte10@gmail.com> - 2012-08-21 10:00 -0700
              Re: How to set the socket type and the protocol of a socket using create_connection? Dennis Lee Bieber <wlfraed@ix.netcom.com> - 2012-08-21 15:28 -0400
              Re: How to set the socket type and the protocol of a socket using create_connection? Dennis Lee Bieber <wlfraed@ix.netcom.com> - 2012-08-21 22:10 -0400
                Re: How to set the socket type and the protocol of a socket using create_connection? Guillaume Comte <guillaume.comte10@gmail.com> - 2012-08-22 00:29 -0700
                Re: How to set the socket type and the protocol of a socket using create_connection? Guillaume Comte <guillaume.comte10@gmail.com> - 2012-08-22 00:29 -0700
                  Re: How to set the socket type and the protocol of a socket using create_connection? Hans Mulder <hansmu@xs4all.nl> - 2012-08-22 11:03 +0200
                    Re: How to set the socket type and the protocol of a socket using create_connection? Guillaume Comte <guillaume.comte10@gmail.com> - 2012-08-22 02:21 -0700
        Re: How to set the socket type and the protocol of a socket using create_connection? Chris Angelico <rosuav@gmail.com> - 2012-08-21 01:38 +1000
    Re: How to set the socket type and the protocol of a socket using create_connection? Guillaume Comte <guillaume.comte10@gmail.com> - 2012-08-22 01:43 -0700
      Re: How to set the socket type and the protocol of a socket using create_connection? Dennis Lee Bieber <wlfraed@ix.netcom.com> - 2012-08-22 15:18 -0400
        Re: How to set the socket type and the protocol of a socket using create_connection? Grant Edwards <invalid@invalid.invalid> - 2012-08-23 13:53 +0000

#27479 — How to set the socket type and the protocol of a socket using create_connection?

FromGuillaume Comte <guillaume.comte10@gmail.com>
Date2012-08-20 02:14 -0700
SubjectHow to set the socket type and the protocol of a socket using create_connection?
Message-ID<cbafe578-0a1a-4d0b-82a5-54c9f84fcd67@googlegroups.com>
Hello everyone,

I want to use socket.create_connection(...) to set a source address in a ping implementation in python.

But how can I then set the type and the protocol? Because, before, I did:

icmp = socket.getprotobyname("icmp")
my_socket = socket.socket(socket.AF_INET, socket.SOCK_RAW, icmp)

But now, I do:

src_addr = socket.gethostbyname(src_addr)
dest_addr = socket.gethostbyname(dest_addr)
my_socket = socket.create_connection(dest_addr, socket.getdefaulttimeout(), src_addr)

Is there something like my_socket.setproto()? I haven't found such a function in the documentation.

Thank you,
Guillaume

[toc] | [next] | [standalone]


#27484

FromGuillaume Comte <guillaume.comte10@gmail.com>
Date2012-08-20 05:36 -0700
Message-ID<4edc5ccb-9121-47b0-8ad4-2bf106735532@googlegroups.com>
In reply to#27479
In fact, socket.create_connection is for TCP only so I cannot use it for a ping implementation. Does anyone have an idea about how to be able to set a source address for ICMP messages?

[toc] | [prev] | [next] | [standalone]


#27490

FromHans Mulder <hansmu@xs4all.nl>
Date2012-08-20 15:38 +0200
Message-ID<50323dc7$0$6841$e4fe514c@news2.news.xs4all.nl>
In reply to#27484
On 20/08/12 14:36:58, Guillaume Comte wrote:
> In fact, socket.create_connection is for TCP only so I cannot use it for a ping implementation.

Why are you trying to reimplement ping?

All OS'es I am aware of come with a working ping implementation.


> Does anyone have an idea about how to be able to set a source address for ICMP messages?

Did you try not setting it?

The default is probably your own IP address, which is the only
sensible value anyway.  Or are you trying to cause confusion
by sending ICMP packets with a forged source address?

-- HansM

[toc] | [prev] | [next] | [standalone]


#27500

FromGuillaume Comte <guillaume.comte10@gmail.com>
Date2012-08-20 08:04 -0700
Message-ID<c8381655-3c9a-4100-81af-bcd3f07414f0@googlegroups.com>
In reply to#27490
Le lundi 20 août 2012 15:38:14 UTC+2, Hans Mulder a écrit :
> On 20/08/12 14:36:58, Guillaume Comte wrote:
> 
> > In fact, socket.create_connection is for TCP only so I cannot use it for a ping implementation.
> 
> 
> 
> Why are you trying to reimplement ping?

Because I work on a network emulator and I want to check biterros patterns so I need to access the data of the packets. An dsince my test program is written in Python, it's easier to do it in Python.

> 
> 
> 
> All OS'es I am aware of come with a working ping implementation.
> 
> 
> 
> 
> 
> > Does anyone have an idea about how to be able to set a source address for ICMP messages?
> 
> 
> 
> Did you try not setting it?
> 
> 
> 
> The default is probably your own IP address, which is the only
> 
> sensible value anyway.  Or are you trying to cause confusion
> 
> by sending ICMP packets with a forged source address?

No, I want to do it on a machine with aliases as in:

ifconfig em0 10.0.1.1 netmask 255.255.255.0 alias
ifconfig em0 10.0.2.1 netmask 255.255.255.0 alias
ping -c4 -S 10.0.1.1 10.0.2.1


But I think I've found the solution: my_socket.bind((src_addr, 1))

> 
> 
> 
> -- HansM

[toc] | [prev] | [next] | [standalone]


#27512

FromDave Angel <d@davea.name>
Date2012-08-20 13:27 -0400
Message-ID<mailman.3568.1345483663.4697.python-list@python.org>
In reply to#27500
On 08/20/2012 11:04 AM, Guillaume Comte wrote:
> <SNIP>
> Because I work on a network emulator and I want to check biterros patterns so I need to access the data of the packets. An dsince my test program is written in Python, it's easier to do it in Python.

You should look up  scapy.

http://www.secdev.org/projects/scapy/


-- 

DaveA

[toc] | [prev] | [next] | [standalone]


#27574

FromGuillaume Comte <guillaume.comte10@gmail.com>
Date2012-08-21 10:00 -0700
Message-ID<mailman.3606.1345568436.4697.python-list@python.org>
In reply to#27512
Unfortunatly, my_socket.bind((src_addr, 1)) doesn't work. I get the error message: "socket.error: [Errno 49] Can't assign requested address"...

I've tried to change the protocol to IPPROTO_RAW. Here is a simple example of the code:



import socket
import os
import struct
import time
import select

ICMP_ECHO_REQUEST = 8
PACKET_SIZE = 64 # Bytes
TIMEOUT = 0.5 # Seconds

def do_one(src_addr, dest_addr):
    my_socket = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_RAW)

    if src_addr != None:
        src_addr = socket.gethostbyname(src_addr)
        my_socket.bind((src_addr, 1))

    my_id = os.getpid() & 0xFFFF

    print "id: " + str(my_id)

    print "sending..."
    send_one(dest_addr, my_socket, my_id)

    print "receiving..."
    id = receive_one(my_socket)
    if id == None:
        print "nothing received !"
    else:
        print "received id: " + str(id)

    my_socket.close()

def checksum(source_string):
    ...

def send_one(addr, my_socket, id):
    # Header: type (8), code (8), checksum (16), id (16), sequence number (16)
    cs = 0
    header = struct.pack("bbHHh", ICMP_ECHO_REQUEST, 0, cs, socket.htons(id), 0)
    data = PACKET_SIZE * "G"

    cs = checksum(header + data)

    header = struct.pack("bbHHh", ICMP_ECHO_REQUEST, 0, socket.htons(cs), socket.htons(id), 0)
    packet = header + data

    my_socket.sendto(packet, (socket.gethostbyname(addr), 1))

def receive_one(my_socket):
    while True:
        what_ready = select.select([my_socket], [], [], TIMEOUT)
        if what_ready[0] == []:
            return None

        received_packet = my_socket.recvfrom(1024)[0]
        header = received_packet[20:28]
        id = struct.unpack("bbHHh", header)[3]
        return socket.ntohs(id)

if __name__ == "__main__":

    import sys
    dst = sys.argv[1]
    print "dst: " + dst
    try:
        src = sys.argv[2]
        print "src: " + src
    except IndexError:
        src = None
    do_one(src, dst)


But when I try to set a source address, I still get the same error message...

Does anyone know how I could build the IP header (I don't even know if it can be the solution but it's worth a try...)?

[toc] | [prev] | [next] | [standalone]


#27575

FromGuillaume Comte <guillaume.comte10@gmail.com>
Date2012-08-21 10:00 -0700
Message-ID<7e4fbbae-a70f-42fc-82c9-a03f1a118136@googlegroups.com>
In reply to#27512
Unfortunatly, my_socket.bind((src_addr, 1)) doesn't work. I get the error message: "socket.error: [Errno 49] Can't assign requested address"...

I've tried to change the protocol to IPPROTO_RAW. Here is a simple example of the code:



import socket
import os
import struct
import time
import select

ICMP_ECHO_REQUEST = 8
PACKET_SIZE = 64 # Bytes
TIMEOUT = 0.5 # Seconds

def do_one(src_addr, dest_addr):
    my_socket = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_RAW)

    if src_addr != None:
        src_addr = socket.gethostbyname(src_addr)
        my_socket.bind((src_addr, 1))

    my_id = os.getpid() & 0xFFFF

    print "id: " + str(my_id)

    print "sending..."
    send_one(dest_addr, my_socket, my_id)

    print "receiving..."
    id = receive_one(my_socket)
    if id == None:
        print "nothing received !"
    else:
        print "received id: " + str(id)

    my_socket.close()

def checksum(source_string):
    ...

def send_one(addr, my_socket, id):
    # Header: type (8), code (8), checksum (16), id (16), sequence number (16)
    cs = 0
    header = struct.pack("bbHHh", ICMP_ECHO_REQUEST, 0, cs, socket.htons(id), 0)
    data = PACKET_SIZE * "G"

    cs = checksum(header + data)

    header = struct.pack("bbHHh", ICMP_ECHO_REQUEST, 0, socket.htons(cs), socket.htons(id), 0)
    packet = header + data

    my_socket.sendto(packet, (socket.gethostbyname(addr), 1))

def receive_one(my_socket):
    while True:
        what_ready = select.select([my_socket], [], [], TIMEOUT)
        if what_ready[0] == []:
            return None

        received_packet = my_socket.recvfrom(1024)[0]
        header = received_packet[20:28]
        id = struct.unpack("bbHHh", header)[3]
        return socket.ntohs(id)

if __name__ == "__main__":

    import sys
    dst = sys.argv[1]
    print "dst: " + dst
    try:
        src = sys.argv[2]
        print "src: " + src
    except IndexError:
        src = None
    do_one(src, dst)


But when I try to set a source address, I still get the same error message...

Does anyone know how I could build the IP header (I don't even know if it can be the solution but it's worth a try...)?

[toc] | [prev] | [next] | [standalone]


#27591

FromDennis Lee Bieber <wlfraed@ix.netcom.com>
Date2012-08-21 15:28 -0400
Message-ID<mailman.3617.1345577311.4697.python-list@python.org>
In reply to#27575
On Tue, 21 Aug 2012 10:00:28 -0700 (PDT), Guillaume Comte
<guillaume.comte10@gmail.com> declaimed the following in
gmane.comp.python.general:

> Unfortunatly, my_socket.bind((src_addr, 1)) doesn't work. I get the error message: "socket.error: [Errno 49] Can't assign requested address"...

	Port #1 is in the range of OS privileged ports; you may need root
privileges to bind to it.

http://www.w3.org/Daemon/User/Installation/PrivilegedPorts.html

{Note: one link I hit indicates that M$ Windows does not have this
restriction; and 

>>> s = socket.socket(socket.AF_INET)
>>> s.bind(("", 1))
>>> 

seems to confirm that... OTOH: specifying an invalid IP address
regardless of port produces

>>> s.bind(("192.168.1.10", 1))
Traceback (most recent call last):
  File "<interactive input>", line 1, in <module>
  File "<string>", line 1, in bind
error: (10049, "Can't assign requested address")
>>> 

whereas using the DHCP assigned address gave

>>> s.close()
>>> s = socket.socket(socket.AF_INET)
>>> s.bind(("192.168.2.101", 1))
>>> 
}
-- 
	Wulfraed                 Dennis Lee Bieber         AF6VN
        wlfraed@ix.netcom.com    HTTP://wlfraed.home.netcom.com/

[toc] | [prev] | [next] | [standalone]


#27598

FromDennis Lee Bieber <wlfraed@ix.netcom.com>
Date2012-08-21 22:10 -0400
Message-ID<mailman.3623.1345601437.4697.python-list@python.org>
In reply to#27575
On Tue, 21 Aug 2012 10:00:28 -0700 (PDT), Guillaume Comte
<guillaume.comte10@gmail.com> declaimed the following in
gmane.comp.python.general:

	A later follow-up
> Unfortunatly, my_socket.bind((src_addr, 1)) doesn't work. I get the error message: "socket.error: [Errno 49] Can't assign requested address"...
> 

	Since .bind() is used to set up a /listener/, the network stack
(LINK layer) probably has to be tied to the IP address; that is, a valid
"source" address needs to be supplied to .bind.


> But when I try to set a source address, I still get the same error message...
> 
> Does anyone know how I could build the IP header (I don't even know if it can be the solution but it's worth a try...)?

	Based upon http://linux.die.net/man/7/raw "Raw sockets allow new
IPv4 protocols to be implemented in user space. A raw socket receives or
sends the raw datagram not including link level headers. " implies that
you need to build the entire IP packet for your ICMP message... That
means you do NOT use socket methods to set fields -- you'll probably
have to use something like the struct module to lay out the entire IP
packet /including/ header contents, and then pass that as-is to the
socket.

-- 
	Wulfraed                 Dennis Lee Bieber         AF6VN
        wlfraed@ix.netcom.com    HTTP://wlfraed.home.netcom.com/

[toc] | [prev] | [next] | [standalone]


#27611

FromGuillaume Comte <guillaume.comte10@gmail.com>
Date2012-08-22 00:29 -0700
Message-ID<4416da62-a6ba-4264-b33d-6015f9b2e582@googlegroups.com>
In reply to#27598
Le mercredi 22 août 2012 04:10:43 UTC+2, Dennis Lee Bieber a écrit :
> On Tue, 21 Aug 2012 10:00:28 -0700 (PDT), Guillaume Comte
> 
> <guillaume.comte10@gmail.com> declaimed the following in
> 
> gmane.comp.python.general:
> 
> 
> 
> 	A later follow-up
> 
> > Unfortunatly, my_socket.bind((src_addr, 1)) doesn't work. I get the error message: "socket.error: [Errno 49] Can't assign requested address"...
> 
> > 
> 
> 
> 
> 	Since .bind() is used to set up a /listener/, the network stack
> 
> (LINK layer) probably has to be tied to the IP address; that is, a valid
> 
> "source" address needs to be supplied to .bind.
> 
Do you mean that an alias is not a valid source address? Because ping.c can do it...

I've also tried changing the port to 3333 or 8080 but the same error happens.
> 
> 
> 
> 
> > But when I try to set a source address, I still get the same error message...
> 
> > 
> 
> > Does anyone know how I could build the IP header (I don't even know if it can be the solution but it's worth a try...)?
> 
> 
> 
> 	Based upon http://linux.die.net/man/7/raw "Raw sockets allow new
> 
> IPv4 protocols to be implemented in user space. A raw socket receives or
> 
> sends the raw datagram not including link level headers. " implies that
> 
> you need to build the entire IP packet for your ICMP message... That
> 
> means you do NOT use socket methods to set fields -- you'll probably
> 
> have to use something like the struct module to lay out the entire IP
> 
> packet /including/ header contents, and then pass that as-is to the
> 
> socket.
> 
> 
> 
> -- 
> 
> 	Wulfraed                 Dennis Lee Bieber         AF6VN
> 
>         wlfraed@ix.netcom.com    HTTP://wlfraed.home.netcom.com/

[toc] | [prev] | [next] | [standalone]


#27612

FromGuillaume Comte <guillaume.comte10@gmail.com>
Date2012-08-22 00:29 -0700
Message-ID<mailman.3635.1345620586.4697.python-list@python.org>
In reply to#27598
Le mercredi 22 août 2012 04:10:43 UTC+2, Dennis Lee Bieber a écrit :
> On Tue, 21 Aug 2012 10:00:28 -0700 (PDT), Guillaume Comte
> 
> <guillaume.comte10@gmail.com> declaimed the following in
> 
> gmane.comp.python.general:
> 
> 
> 
> 	A later follow-up
> 
> > Unfortunatly, my_socket.bind((src_addr, 1)) doesn't work. I get the error message: "socket.error: [Errno 49] Can't assign requested address"...
> 
> > 
> 
> 
> 
> 	Since .bind() is used to set up a /listener/, the network stack
> 
> (LINK layer) probably has to be tied to the IP address; that is, a valid
> 
> "source" address needs to be supplied to .bind.
> 
Do you mean that an alias is not a valid source address? Because ping.c can do it...

I've also tried changing the port to 3333 or 8080 but the same error happens.
> 
> 
> 
> 
> > But when I try to set a source address, I still get the same error message...
> 
> > 
> 
> > Does anyone know how I could build the IP header (I don't even know if it can be the solution but it's worth a try...)?
> 
> 
> 
> 	Based upon http://linux.die.net/man/7/raw "Raw sockets allow new
> 
> IPv4 protocols to be implemented in user space. A raw socket receives or
> 
> sends the raw datagram not including link level headers. " implies that
> 
> you need to build the entire IP packet for your ICMP message... That
> 
> means you do NOT use socket methods to set fields -- you'll probably
> 
> have to use something like the struct module to lay out the entire IP
> 
> packet /including/ header contents, and then pass that as-is to the
> 
> socket.
> 
> 
> 
> -- 
> 
> 	Wulfraed                 Dennis Lee Bieber         AF6VN
> 
>         wlfraed@ix.netcom.com    HTTP://wlfraed.home.netcom.com/

[toc] | [prev] | [next] | [standalone]


#27621

FromHans Mulder <hansmu@xs4all.nl>
Date2012-08-22 11:03 +0200
Message-ID<5034a050$0$6904$e4fe514c@news2.news.xs4all.nl>
In reply to#27612
On 22/08/12 09:29:37, Guillaume Comte wrote:
> Le mercredi 22 août 2012 04:10:43 UTC+2, Dennis Lee Bieber a écrit :
>> On Tue, 21 Aug 2012 10:00:28 -0700 (PDT), Guillaume Comte
>> <guillaume.comte10@gmail.com> declaimed the following in
>> gmane.comp.python.general:

>> 	A later follow-up

>>> Unfortunately, my_socket.bind((src_addr, 1)) doesn't work. I get the
>>> error message: "socket.error: [Errno 49] Can't assign requested address"...

>> 	Since .bind() is used to set up a /listener/, the network stack

Not necessarily.  That is, a listener is normally  bound to a
specific port, since otherwise the client doesn't know what port
to connect to (unless you provide that factoid on another port).

But nothing prevents a client from binding its socket to a
specific port number.  These days, that doesn't buy you much,
but in the old days, some services would only talk to clients
using privileged port numbers (<1024).

>> (LINK layer) probably has to be tied to the IP address; that is, a valid
>> "source" address needs to be supplied to .bind.

> Do you mean that an alias is not a valid source address? Because ping.c can do it...

> I've also tried changing the port to 3333 or 8080 but the same error happens.

On my laptop, 0 appears to be the only port number that bind accepts
for a raw socket.  Other numbers I tried all raise "socket.error:
[Errno 49] Can't assign requested address".

But this might depend on your OS.  What OS are you using?

Hope this helps,

-- HansM

[toc] | [prev] | [next] | [standalone]


#27622

FromGuillaume Comte <guillaume.comte10@gmail.com>
Date2012-08-22 02:21 -0700
Message-ID<5cb21fea-1550-4c4f-8157-8193c4ebd9d7@googlegroups.com>
In reply to#27621
Le mercredi 22 août 2012 11:03:11 UTC+2, Hans Mulder a écrit :

> 
> On my laptop, 0 appears to be the only port number that bind accepts
> 
> for a raw socket.  Other numbers I tried all raise "socket.error:
> 
> [Errno 49] Can't assign requested address".
> 
> 
> 
> But this might depend on your OS.  What OS are you using?
> 

I'm using FreeBSD 7.3

[toc] | [prev] | [next] | [standalone]


#27502

FromChris Angelico <rosuav@gmail.com>
Date2012-08-21 01:38 +1000
Message-ID<mailman.3562.1345477085.4697.python-list@python.org>
In reply to#27490
On Mon, Aug 20, 2012 at 11:38 PM, Hans Mulder <hansmu@xs4all.nl> wrote:
> Why are you trying to reimplement ping?
>
> All OS'es I am aware of come with a working ping implementation.

For some definition of "working", at least. I've never managed to get
MS Windows to ping broadcast, for instance.

A Google search for 'python ping' comes up with a few good answers,
though. You may want to have a look at some of them; if nothing else,
you'll get confirmation that what you're doing corresponds to what
someone else has done (which isn't proof you're doing the right thing,
but it does suggest it).

ChrisA

[toc] | [prev] | [next] | [standalone]


#27620

FromGuillaume Comte <guillaume.comte10@gmail.com>
Date2012-08-22 01:43 -0700
Message-ID<32176aa4-4b9d-44a6-8729-958e3c251955@googlegroups.com>
In reply to#27479
I've managed to build the IP header. I've put the source and destination addresses in this header but it doesn't change the real source address...

I'm trying to read the ping source code but I'm lost...

[toc] | [prev] | [next] | [standalone]


#27676

FromDennis Lee Bieber <wlfraed@ix.netcom.com>
Date2012-08-22 15:18 -0400
Message-ID<mailman.3681.1345663132.4697.python-list@python.org>
In reply to#27620
On Wed, 22 Aug 2012 01:43:19 -0700 (PDT), Guillaume Comte
<guillaume.comte10@gmail.com> declaimed the following in
gmane.comp.python.general:

> I've managed to build the IP header. I've put the source and destination addresses in this header but it doesn't change the real source address...
>

	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...
-- 
	Wulfraed                 Dennis Lee Bieber         AF6VN
        wlfraed@ix.netcom.com    HTTP://wlfraed.home.netcom.com/

[toc] | [prev] | [next] | [standalone]


#27731

FromGrant Edwards <invalid@invalid.invalid>
Date2012-08-23 13:53 +0000
Message-ID<k15cl7$820$1@reader1.panix.com>
In reply to#27676
On 2012-08-22, Dennis Lee Bieber <wlfraed@ix.netcom.com> wrote:
> On Wed, 22 Aug 2012 01:43:19 -0700 (PDT), Guillaume Comte
><guillaume.comte10@gmail.com> declaimed the following in
> gmane.comp.python.general:
>
>> I've managed to build the IP header. I've put the source and destination addresses in this header but it doesn't change the real source address...
>
> 	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()
-----------------------------------------------------------------

-- 
Grant Edwards               grant.b.edwards        Yow! I'm changing the
                                  at               CHANNEL ... But all I get
                              gmail.com            is commercials for "RONCO
                                                   MIRACLE BAMBOO STEAMERS"!

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.python


csiph-web