0

I'm trying to change this implementation of ping so I can set a different source address for the messages. What I want to do is exactly the same thing that the -S option of the original ping can do:

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

This works of course but I would like to do the same thing with Python.

Mogsdad
  • 44,709
  • 21
  • 151
  • 275
gcomte
  • 51
  • 1
  • 7

1 Answers1

3

The sample code you are showing is using a IPPROTO_ICMP socket, that can be bound to a specific address using bind().

So, just after the my_socket = socket.socket(socket.AF_INET, socket.SOCK_RAW, icmp) line, you can add:

my_socket.bind((your_source_address, 0))

The second argument in the tuple is the port number, that seems to be ignored by IPPROTO_ICMP.

Note that the operating system may not allow you to bind the socket to an arbitrary address, but only a valid address belonging to your host, maybe this is enough for your use case. If you want to set a completely arbitrary source address, you may need to use a IPPROTO_RAW socket instead, and then build the whole IP packet header yourself. See this question for some pointers: How Do I Use Raw Socket in Python?

Community
  • 1
  • 1
ehabkost
  • 411
  • 3
  • 5
  • Thanks a lot! I think it's exactly what I needed. I didn't understand the bind() function this way. I'll try and let you know. – gcomte Aug 20 '12 at 14:26
  • @gcomte If it helped to solve the problem, mark the question as answered, so it could help other people to. – Rostyslav Dzinko Aug 20 '12 at 15:17
  • It doesn't work... `socket.error: [Errno 49] Can't assign requested address` – gcomte Aug 21 '12 at 08:24
  • @gcomte: this error message means the OS is rejecting the address you are trying to set. Maybe you it does not belong to your host, or maybe it's just because if you set the port number as 1. – ehabkost Sep 05 '12 at 14:34