Sending multicast packet with source IP equal to virtual interface IP in Python

1

I have a system with a virtual network interface eth0:1, and I want to send multicast packets that have a source IP of that interface. However, my packets end up with the source IP for eth0. How do I get the correct source IP in my multicast packets?

The commands used to create the iface/route

sudo ifconfig eth0:1 plumb
sudo ifconfig eth0:1 192.168.123.123 netmask 255.255.255.0 up
sudo ip route add 224.1.1.0/24 dev eth0:1 src 192.168.123.123

After which the interfaces look like this;

eth0   Link encap:Ethernet  HWaddr fa:16:3e:9d:94:c2
       inet addr:14.0.0.2  Bcast:14.0.0.255  Mask:255.255.255.0
       UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1

eth0:1 Link encap:Ethernet  HWaddr fa:16:3e:9d:94:c2
       inet addr:192.168.123.123  Bcast:192.168.123.255  Mask:255.255.255.0
       UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1

routes look like this;

default via 14.0.0.1  metric 100
14.0.0.0/24  proto kernel  scope link  src 14.0.0.2
192.168.123.0/24  proto kernel  scope link  src 192.168.123.123
224.1.1.0/24 dev eth0 scope link  src 192.168.123.123

A directed udp packet sent to 192.168.123.123:5007 gets the correct source IP of 192.168.123.123, but a multicast packet to 224.1.1.1:5007 gets a source IP of 14.0.0.2.

The python script I'm using to generate the packets is this;

MCAST_GRP = '224.1.1.1'
MCAST_PORT = 5007

MY_IP = '192.168.123.123'

def send_mcast():
    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

    sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    try:
        sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1)
    except AttributeError:
        pass # Some systems don't support SO_REUSEPORT

    sock.setsockopt(socket.SOL_IP, socket.IP_MULTICAST_TTL, 2)
    sock.setsockopt(socket.SOL_IP, socket.IP_MULTICAST_LOOP, 1)

    sock.setsockopt(socket.SOL_IP, socket.IP_MULTICAST_IF, socket.inet_aton(MY_IP))

    print "Sending: robot"
    sock.sendto("robot", (MCAST_GRP, MCAST_PORT))

def send_direct():
    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

    sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    try:
        sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1)
    except AttributeError:
        pass # Some systems don't support SO_REUSEPORT

    print "Sending: robot"
    sock.sendto("robot", (MY_IP, MCAST_PORT))

CAB

Posted 2014-03-25T15:49:57.990

Reputation: 183

Answers

1

After trying several variations on 'ip route add' and none of them working, I stumbled on mac vlan which works exactly as desired. Here are the commands for setting it up;

sudo ip link add link eth0 mac0 type macvlan
sudo ifconfig mac0 plumb
sudo ifconfig mac0 192.168.123.123 netmask 255.255.255.0 up
sudo ip route add 224.1.1.0/24 dev mac0

this gives an interface;

eth0  Link encap:Ethernet  HWaddr fa:16:3e:9d:94:c2
      inet addr:14.0.0.2  Bcast:14.0.0.255  Mask:255.255.255.0

mac0  Link encap:Ethernet  HWaddr 62:c8:10:38:dc:9a
      inet addr:192.168.123.123  Bcast:192.168.123.255  Mask:255.255.255.0

and a route;

224.1.1.0/24 dev mac0  scope link

CAB

Posted 2014-03-25T15:49:57.990

Reputation: 183

0

I believe you need to use the socket.bind(address) without the port.

docs.python.org/2/library/socket.html

Also, I recommend not using an address on eth0 when youre using sub-interfaces. Move it to 0:0

Also, unless you're using SSM, the source interface is irrelevant with multicast.

Hope that helps!

Coldburn

Posted 2014-03-25T15:49:57.990

Reputation: 1

thanks. bind is not needed at all - will edit question. Not using SSM, but the receiver is checking the source IP. – CAB – 2014-03-25T19:35:33.463