在发送多播IPv6时使用SOCK_STREAM或SOCK_RAW

时间:2015-02-15 10:26:15

标签: python sockets networking ipv6 multicast

嘿伙计我有问题,我似乎无法找到有关在多播上发送原始数据包的文档,所有示例,解决方案和文档都以UDP使用为中心。

我以此为例:http://svn.python.org/projects/stackless/trunk/Demo/sockets/mcast.py

我只关心优化代码的发送部分:

import time
import struct
import socket
import sys

MYPORT = 8123
MYGROUP_6 = 'ff15:7079:7468:6f6e:6465:6d6f:6d63:6173'
MYTTL = 1 # Increase to reach other networks
group = MYGROUP_6

if "-s" in sys.argv[1:]:
    sender(group)
addrinfo = socket.getaddrinfo(group, None)[0]

s = socket.socket(addrinfo[0], socket.SOCK_DGRAM)

# Set Time-to-live (optional)
ttl_bin = struct.pack('@i', MYTTL)
s.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_MULTICAST_HOPS, ttl_bin)

while True:
    data = repr(time.time())
    s.sendto(data + '\0', (addrinfo[4][0], MYPORT))
    time.sleep(1)

现在在Multicast中发送UDP。我想要的是转换

s = socket.socket(addrinfo[0], socket.SOCK_DGRAM)

s = socket(AF_PACKET, SOCK_RAW, IPPROTO_ICMPV6)

或者至少将socket.SOCK_DGRAM更改为socket.SOCK_STREAM以发送TCP数据包。

我的目标是发送一个ICMPv6数据包,希望我可以将其原始发送,因为我使用VLAN,但是当我更改SOCK_DGRAM时,我将收到如下错误:

Traceback (most recent call last):
  File "/root/PycharmProjects/SlaacSecuritySolutionv3/ClassS3/SendTest.py", line 20, in <module>
    s.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_MULTICAST_HOPS, ttl_bin)
  File "/usr/lib/python2.7/socket.py", line 224, in meth
    return getattr(self._sock,name)(*args)
socket.error: [Errno 92] Protocol not available
当我将socket.socket更改为socket.AF_PACKET, socket.SOCK_RAW

时,同样如此

请帮助,我现在被困在这里好几天

2 个答案:

答案 0 :(得分:1)

#!/usr/bin/env python
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#~ Imports
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

import sys
import time
import socket
import select
import struct
import select
import time
from impacket import ImpactDecoder, ImpactPacket, IP6, ICMP6, version
from impacket import ImpactPacket
from netaddr import *

#~ Definitions
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

maddr = ('ff12::4242', 4242)

def ipv6Multicast(host='::1', maddr=maddr):
    haddr = socket.getaddrinfo(host, maddr[1], socket.AF_INET6, socket.IPPROTO_TCP)[0][-1]
    maddr = socket.getaddrinfo(maddr[0], maddr[1], socket.AF_INET6, socket.IPPROTO_TCP)[0][-1]

    sock = socket.socket(socket.AF_INET6, socket.SOCK_RAW, socket.IPPROTO_ICMPV6)
    sock.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_MULTICAST_LOOP, 1)
    sock.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_MULTICAST_HOPS, 5)

    ifn = struct.pack("I", haddr[3])
    sock.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_MULTICAST_IF, ifn)

    group = socket.inet_pton(socket.AF_INET6, maddr[0]) + ifn
    sock.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_JOIN_GROUP, group)

    #sock.bind(haddr)
    sock.setblocking(False)

    return sock, maddr

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#~ Main
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

if __name__=='__main__':
    # change host to use your IPv6 address...eth
    sock, maddr = ipv6Multicast(host='fe80::20c:29ff:fe23:8450')

    # send initial message
    msg = 'IPv6 multicast recipie'
    eth = ImpactPacket.Ethernet() 
    print maddr
    while 1:
         sock.sendto(eth.get_packet(),("ff12::4242",0))
         time.sleep(1

这是我向网络发送IPv6 ICMPv6数据包的解决方案,我使用impacket来构建数据包,但还没有数据。

如果执行它将发送malform ICMPv6数据包

答案 1 :(得分:0)

看起来您的问题是由尚未解决的问题造成的:https://bugs.python.org/issue6926

Windows平台上的Python编译缺少IPPROTO_IPV6常量。根据RFC3542,常量应该等于41,所以只需将socket.IPPROTO_IPV6更改为41。