Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 17 Jun 2006 20:41:48 GMT
From:      Clément Lecigne <clem1@FreeBSD.org>
To:        Perforce Change Reviews <perforce@FreeBSD.org>
Subject:   PERFORCE change 99463 for review
Message-ID:  <200606172041.k5HKfmC9005327@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=99463

Change 99463 by clem1@clem1_ipv6vulns on 2006/06/17 20:41:06

	icmp6 improvements plus basic samples, new connectors and python bpf wrapper.	

Affected files ...

.. //depot/projects/soc2006/clem1_ipv6vulns/pcs/bpf/bpfmodule.c#1 add
.. //depot/projects/soc2006/clem1_ipv6vulns/pcs/pcs/packets/icmpv6.py#2 edit
.. //depot/projects/soc2006/clem1_ipv6vulns/pcs/pcs/packets/nd6.py#2 delete
.. //depot/projects/soc2006/clem1_ipv6vulns/pcs/pcs/packets/pseudoipv6.py#1 add
.. //depot/projects/soc2006/clem1_ipv6vulns/pcs/pcs/pcs.py#2 edit
.. //depot/projects/soc2006/clem1_ipv6vulns/pcs/samples/ping6.py#1 add
.. //depot/projects/soc2006/clem1_ipv6vulns/pcs/samples/rawping6.py#1 add
.. //depot/projects/soc2006/clem1_ipv6vulns/pcs/setup.py#2 edit

Differences ...

==== //depot/projects/soc2006/clem1_ipv6vulns/pcs/pcs/packets/icmpv6.py#2 (text+ko) ====

@@ -36,15 +36,122 @@
 
 import pcs
 import struct
+from pseudoipv6 import *
 
+ND_ROUTER_SOLICIT = 133
+ND_ROUTER_ADVERT = 134	
+ND_NEIGHBOR_SOLICIT = 135	
+ND_NEIGHBOR_ADVERT = 136	
+ND_REDIRECT = 137
+ICMP6_ROUTER_RENUMBERING = 138	
+ICMP6_WRUREQUEST = 139	
+ICMP6_WRUREPLY = 140	
+ICMP6_DST_UNREACH = 1
+ICMP6_PACKET_TOO_BIG = 2
+ICMP6_TIME_EXCEEDED = 3
+ICMP6_PARAM_PROB = 4
+ICMP6_ECHO_REQUEST = 128	
+ICMP6_ECHO_REPLY = 129
+
+op = 0
+
 class icmpv6(pcs.Packet):
 
     layout = pcs.Layout()
 
-    def __init__(self, bytes = None):
-        type = pcs.Field("type", 8)
+    def __init__(self, type = 0, bytes = None):
+        """icmpv6 header RFC2463 and RFC2461"""
+        ty = pcs.Field("type", 8, default = type)
         code = pcs.Field("code", 8)
         cksum = pcs.Field("checksum", 16)
-        pcs.Packet.__init__(self, [type, code, cksum], bytes)
+        if type == ICMP6_ECHO_REQUEST or type == ICMP6_ECHO_REPLY:
+            id = pcs.Field("id", 16)
+            seq = pcs.Field("sequence", 16)
+            pcs.Packet.__init__(self, [ty, code, cksum, id, seq], bytes)
+        elif type == ICMP6_TIME_EXCEEDED or type == ICMP6_DST_UNREACH or type == ND_ROUTER_SOLICIT:
+            unused = pcs.Field("unused", 32)
+            pcs.Packet.__init__(self, [ty, code, cksum, unused], bytes)
+        elif type == ICMP6_PARAM_PROB:
+            pointer = pcs.Field("pointer", 32)
+            pcs.Packet.__init__(self, [ty, code, cksum, pointer], bytes)
+        elif type == ICMP6_PACKET_TOO_BIG:
+            mtu = pcs.Field("mtu", 32)
+            pcs.Packet.__init__(self, [ty, code, cksum, mtu], bytes)
+        #elif type == ICMP6_WRUREQUEST or type == ICMP6_WRUREPLY:
+        elif type == ND_ROUTER_ADVERT:
+            chp = pcs.Field("current_hop_limit", 8)
+            m = pcs.Field("m", 1)
+            o = pcs.Field("o", 1)
+            unused = pcs.Field("unused", 6)
+            rlf = pcs.Field("router_lifetime", 16)
+            rct = pcs.Field("reachable_time", 32)
+            rtt = pcs.Field("retrans_timer", 32)
+            pcs.Packet.__init__(self, [ty, code, cksum, chp, m, o, unused, rlt, rct, rtt], bytes)
+        elif type == ND_NEIGHBOR_SOLICIT:
+            reserved = pcs.Field("reserved", 32)
+            target = pcs.Field("target", 16 * 8)
+            pcs.Packet.__init__(self, [ty, code, cksum, reserved, target], bytes)
+        elif type == ND_NEIGHBOR_ADVERT:
+            r = pcs.Field("router", 1)
+            s = pcs.Field("solicited", 1)
+            o = pcs.Field("override", 1)
+            reserved = pcs.Field("reserved", 29)
+            target = pcs.Field("target", 16 * 8)
+            pcs.Packet.__init__(self, [ty, code, cksum, r, s, o, reserved, target], bytes)
+        else:
+            pcs.Packet.__init__(self, [ty, code, cksum], bytes)
+
+    def option(self, type = 0):
+        """add icmp6 option header RFC2461"""
+        global op
+        op += 1
+        ty = pcs.Field("type" + str(op), 8, default = type)
+        length = pcs.Field("length" + str(op), 8)
+        # Source Link-Layer Address.
+        if type == 1:
+            source = pcs.Field("source" + str(op), 48)
+            pcs.Packet.__add__(self, [ty, length, source])
+        # Target Link-Layer Address
+        elif type == 2:
+            target = pcs.Field("target" + str(op), 48)
+            pcs.Packet.__add__(self, [ty, length, target])
+        # Prefix Information.
+        elif type == 3:
+            plength = pcs.Field("prefix_length" + str(op), 8)
+            l = pcs.Field("L" + str(op), 1)
+            a = pcs.Field("A" + str(op), 1)
+            reserved1 = pcs.Field("reserved1" + str(op), 6)
+            vlf = pcs.Field("valid_lifetime" + str(op), 32)
+            plf = pcs.Field("preferred_lifetime" + str(op), 32)
+            reserved2 = pcs.Field("reserved2" + str(op), 32)
+            prefix = pcs.Field("prefix" + str(op), 48)
+            pcs.Packet.__add__(self, [ty, length, plength, l, a, reserved1, vlf, plf, reserved2, prefix])
+        # Redirected Header.
+        elif type == 4:
+            reserved = pcs.Field("reserved" + str(op), 48)
+            pcs.Packet.__add__(self, [ty, length, reserved])
+        # MTU 
+        elif type == 5:
+            reserved = pcs.Field("reserved" + str(op), 16)
+            mtu = pcs.Field("mtu" + str(op), 32)
+            pcs.Packet.__add__(self, [ty, length, reserved, mtu])
+        else:
+            pcs.Packet.__add__(self, [ty, length])
 
-    
+    def cksum(self, ip, data = ""):
+        """return icmpv6 checksum if we send packet through 
+        raw link level (i.e bpf)"""
+        total = 0
+        p6 = pseudoipv6()
+        p6.src = ip.src
+        p6.dst = ip.dst
+        p6.length = len(self.getbytes()) + len (data)
+        p6.next_header = ip.next_header
+        pkt = p6.getbytes() + self.getbytes() + data
+        if len(pkt) % 2 == 1:
+            pkt += "\0"
+        for i in range(len(pkt)/2):
+            total += (struct.unpack("!H", pkt[2*i:2*i+2])[0])
+        total = (total >> 16) + (total & 0xffff)
+        total += total >> 16
+        return  ~total

==== //depot/projects/soc2006/clem1_ipv6vulns/pcs/pcs/pcs.py#2 (text+ko) ====

@@ -169,6 +169,11 @@
         if bytes != None:
             self.decode(bytes)
 
+    def __add__(self, layout = None):
+        for field in layout:
+            self.layout.append(field)
+        self._needencode = True
+
     def __setattr__(self, name, value):
         """Setting the layout is a special case because of the
         ramifications this has on the packet.  Only fields represented
@@ -345,27 +350,44 @@
     unifying mechanism so you can write packets over any of the
     available APIs and the connector will do the right thing."""
 
-    def __init__(name, mode, arg):
-        import socket
+    def __init__(self, name, arg = ""):
+        from socket import *
+        import bpf
+        connectors = [ "IPV4", "IPV6", "ICMP6", "UDP6", "TCP6", "ICMP", "UDP", "TCP",  "BPF", "PCAP" ]
+        self.bsd = 0
         if name not in connectors:
             raise InvalidConnectorError
-        if name == "TCP":
-            self.sock = socket(socket.AF_INET, socket.SOCK_STREAM)
-        elif name == "UDP":
-            self.sock = socket(socket.AF_INET, socket.SOCK_DGRAM)
+        if name == "IPV4":
+            self.sock = socket(AF_INET, SOCK_RAW, arg)
+            self.sock.setsockopt(IPPROTO_IP, IP_HDRINCL, 1)
+        elif name == "ICMP6":
+            self.sock = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6)
         elif name == "TCP6":
-            self.sock = socket(socket.AF_INET6, socket.SOCK_STREAM)
+            self.sock = socket(AF_INET6, SOCK_RAW, IPPROTO_TCP)
+        elif name == "TCP":
+            self.sock = socket(AF_INET, SOCK_RAW, IPPROTO_TCP)
         elif name == "UDP6":
-            self.sock = socket(socket.AF_INET6, socket.SOCK_DGRAM)
+            self.sock = socket(AF_INET6, SOCK_RAW, IPPROTO_UDP)
+        elif name == "UDP":
+            self.sock = socket(AF_INET, SOCK_RAW, IPPROTO_UDP)
+        elif name == "IPV6" or name == "BPF":
+            if re.search("bsd|BSD", sys.platform):
+                self.sock = bpf.open(arg)
+                self.bsd = 1
+            else:
+                self.sock = socket(PF_PACKET, SOCK_RAW)
+                sock.bind((arg, 0x86dd))
         elif name == "PCAP":
             self.sock = pcap.pcap(arg)
 
     def read():
         pass
 
-    def write():
-        pass
-
-    def close():
-        pass
-
+    def write(self, packet, ip = ""):
+        if self.bsd:
+            self.sock.write(packet)
+        else:
+            self.sock.sendto(packet, (ip, 0))
+    
+    def close(self):
+            self.sock.close()

==== //depot/projects/soc2006/clem1_ipv6vulns/pcs/setup.py#2 (text+ko) ====

@@ -36,9 +36,11 @@
 # Description: The setup script for all of the Packet Construction Set
 
 
-from distutils.core import setup
+from distutils.core import setup, Extension
 from pcs import pcs
 
+bpf = Extension('bpf', sources = ['bpf/bpfmodule.c'])
+
 setup(name='pcs',
       version = '0.1',
       description = 'Packet Construction Set',
@@ -46,4 +48,5 @@
       author_email = 'gnn@neville-neil.com',
       url = 'http://pcs.sf.net',
       packages = ['pcs', 'pcs.packets'],
+      ext_modules = [bpf],
      )



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200606172041.k5HKfmC9005327>