inet6.py revision b5d49cd73a38b87d2a62a74452d3cb0932e6aa7b
1c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#! /usr/bin/env python
2c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
3c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil##                                                                         ##
4614f54fc4b269030ba2934b6c353fb43de886e04Phil## inet6.py --- IPv6 support for Scapy                                     ##
5614f54fc4b269030ba2934b6c353fb43de886e04Phil##              see http://natisbad.org/IPv6/                              ##
6614f54fc4b269030ba2934b6c353fb43de886e04Phil##              for more informations                                      ##
7c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil##                                                                         ##
8c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil## Copyright (C) 2005  Guillaume Valadon <guedou@hongo.wide.ad.jp>         ##
9c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil##                     Arnaud Ebalard <arnaud.ebalard@eads.net>            ##
10c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil##                                                                         ##
11c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil## This program is free software; you can redistribute it and/or modify it ##
12c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil## under the terms of the GNU General Public License version 2 as          ##
13614f54fc4b269030ba2934b6c353fb43de886e04Phil## published by the Free Software Foundation.                              ##
14c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil##                                                                         ##
15c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil## This program is distributed in the hope that it will be useful, but     ##
16c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil## WITHOUT ANY WARRANTY; without even the implied warranty of              ##
17c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU       ##
18c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil## General Public License for more details.                                ##
19c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil##                                                                         ##
20c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
21c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
22614f54fc4b269030ba2934b6c353fb43de886e04Phil
23d7dd2222e18718ea755fe780e8ef422901ba5b0bPhilimport socket
24d7dd2222e18718ea755fe780e8ef422901ba5b0bPhilif not socket.has_ipv6:
25d7dd2222e18718ea755fe780e8ef422901ba5b0bPhil    raise socket.error("can't use AF_INET6, IPv6 is disabled")
2681dfaee354bef2beea581a3c83a33c856ade45e5Dirk Lossif not hasattr(socket, "IPPROTO_IPV6"):
2781dfaee354bef2beea581a3c83a33c856ade45e5Dirk Loss    # Workaround for http://bugs.python.org/issue6926
2881dfaee354bef2beea581a3c83a33c856ade45e5Dirk Loss    socket.IPPROTO_IPV6 = 41
29d7dd2222e18718ea755fe780e8ef422901ba5b0bPhil
30d7dd2222e18718ea755fe780e8ef422901ba5b0bPhilfrom scapy.config import conf
31614f54fc4b269030ba2934b6c353fb43de886e04Philfrom scapy.layers.l2 import *
32614f54fc4b269030ba2934b6c353fb43de886e04Philfrom scapy.layers.inet import *
33614f54fc4b269030ba2934b6c353fb43de886e04Philfrom scapy.fields import *
34614f54fc4b269030ba2934b6c353fb43de886e04Philfrom scapy.packet import *
35614f54fc4b269030ba2934b6c353fb43de886e04Philfrom scapy.volatile import *
36614f54fc4b269030ba2934b6c353fb43de886e04Philfrom scapy.sendrecv import sr,sr1,srp1
37614f54fc4b269030ba2934b6c353fb43de886e04Philfrom scapy.as_resolvers import AS_resolver_riswhois
38614f54fc4b269030ba2934b6c353fb43de886e04Philfrom scapy.supersocket import SuperSocket,L3RawSocket
39614f54fc4b269030ba2934b6c353fb43de886e04Philfrom scapy.arch import *
4072461d0c00f182855906e57dcf6223aa9f1d8b31Philfrom scapy.utils6 import *
41c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
42c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
43c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
44c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# Helpers                                                                  ##
45c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
46c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
47c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhildef get_cls(name, fallback_cls):
48614f54fc4b269030ba2934b6c353fb43de886e04Phil    return globals().get(name, fallback_cls)
49c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
50c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
51c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil##########################
52c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil## Neighbor cache stuff ##
53c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil##########################
54c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
55f631c21842a8c9cd2e9ca4fb2eccb6b08f030e31Philconf.netcache.new_cache("in6_neighbor", 120)
56c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
57c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhildef neighsol(addr, src, iface, timeout=1, chainCC=0):
58c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    """
59c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    Sends an ICMPv6 Neighbor Solicitation message to get the MAC address
60c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    of the neighbor with specified IPv6 address addr. 'src' address is
61c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    used as source of the message. Message is sent on iface. By default,
62c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    timeout waiting for an answer is 1 second.
63c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
64c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    If no answer is gathered, None is returned. Else, the answer is
65c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    returned (ethernet frame).
66c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    """
67c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
68c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    nsma = in6_getnsma(inet_pton(socket.AF_INET6, addr))
69c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    d = inet_ntop(socket.AF_INET6, nsma)
70c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    dm = in6_getnsmac(nsma)
71c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    p = Ether(dst=dm)/IPv6(dst=d, src=src, hlim=255)
72c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    p /= ICMPv6ND_NS(tgt=addr)
73c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    p /= ICMPv6NDOptSrcLLAddr(lladdr=get_if_hwaddr(iface))
74c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    res = srp1(p,type=ETH_P_IPV6, iface=iface, timeout=1, verbose=0,
75c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               chainCC=chainCC)
76c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
77c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    return res
78c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
79c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhildef getmacbyip6(ip6, chainCC=0):
80c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    """
81c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    Returns the mac address to be used for provided 'ip6' peer.
82c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    neighborCache.get() method is used on instantiated neighbor cache.
83c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    Resolution mechanism is described in associated doc string.
84c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
85c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    (chainCC parameter value ends up being passed to sending function
86c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil     used to perform the resolution, if needed)
87c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    """
88f631c21842a8c9cd2e9ca4fb2eccb6b08f030e31Phil
89f631c21842a8c9cd2e9ca4fb2eccb6b08f030e31Phil    if in6_ismaddr(ip6): # Multicast
90f631c21842a8c9cd2e9ca4fb2eccb6b08f030e31Phil        mac = in6_getnsmac(inet_pton(socket.AF_INET6, ip6))
91f631c21842a8c9cd2e9ca4fb2eccb6b08f030e31Phil        return mac
92f631c21842a8c9cd2e9ca4fb2eccb6b08f030e31Phil
93f631c21842a8c9cd2e9ca4fb2eccb6b08f030e31Phil    iff,a,nh = conf.route6.route(ip6, dev=conf.iface6)
94f631c21842a8c9cd2e9ca4fb2eccb6b08f030e31Phil
95f631c21842a8c9cd2e9ca4fb2eccb6b08f030e31Phil    if iff == LOOPBACK_NAME:
96f631c21842a8c9cd2e9ca4fb2eccb6b08f030e31Phil        return "ff:ff:ff:ff:ff:ff"
97f631c21842a8c9cd2e9ca4fb2eccb6b08f030e31Phil
98f631c21842a8c9cd2e9ca4fb2eccb6b08f030e31Phil    if nh != '::':
99f631c21842a8c9cd2e9ca4fb2eccb6b08f030e31Phil        ip6 = nh # Found next hop
100f631c21842a8c9cd2e9ca4fb2eccb6b08f030e31Phil
101f631c21842a8c9cd2e9ca4fb2eccb6b08f030e31Phil    mac = conf.netcache.in6_neighbor.get(ip6)
102f631c21842a8c9cd2e9ca4fb2eccb6b08f030e31Phil    if mac:
103f631c21842a8c9cd2e9ca4fb2eccb6b08f030e31Phil        return mac
104f631c21842a8c9cd2e9ca4fb2eccb6b08f030e31Phil
105f631c21842a8c9cd2e9ca4fb2eccb6b08f030e31Phil    res = neighsol(ip6, a, iff, chainCC=chainCC)
106f631c21842a8c9cd2e9ca4fb2eccb6b08f030e31Phil
107f631c21842a8c9cd2e9ca4fb2eccb6b08f030e31Phil    if res is not None:
108f631c21842a8c9cd2e9ca4fb2eccb6b08f030e31Phil        mac = res.src
109f631c21842a8c9cd2e9ca4fb2eccb6b08f030e31Phil        conf.netcache.in6_neighbor[ip6] = mac
110f631c21842a8c9cd2e9ca4fb2eccb6b08f030e31Phil        return mac
111f631c21842a8c9cd2e9ca4fb2eccb6b08f030e31Phil
112f631c21842a8c9cd2e9ca4fb2eccb6b08f030e31Phil    return None
113c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
114c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
115c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
116c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
117c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil###              IPv6 addresses manipulation routines                     ###
118c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
119c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
120c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
121c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass Net6(Gen): # syntax ex. fec0::/126
122c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    """Generate a list of IPv6s from a network address or a name"""
123c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ipv6"
124c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    ipaddress = re.compile(r"^([a-fA-F0-9:]+)(/[1]?[0-3]?[0-9])?$")
125c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
126c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def __init__(self, net):
127c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        self.repr = net
128c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
129c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        tmp = net.split('/')+["128"]
130c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if not self.ipaddress.match(net):
131c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            tmp[0]=socket.getaddrinfo(tmp[0], None, socket.AF_INET6)[0][-1][0]
132c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
133c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        netmask = int(tmp[1])
13477132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        self.net = inet_pton(socket.AF_INET6, tmp[0])
135c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        self.mask = in6_cidr2mask(netmask)
13677132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        self.plen = netmask
137c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
138c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def __iter__(self):
139c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        def m8(i):
14077132687c31a9d3f30c3992c70eb24d1ac0948a7Phil            if i % 8 == 0:
141c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                return i
142c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        tuple = filter(lambda x: m8(x), xrange(8, 129))
143c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
144c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        a = in6_and(self.net, self.mask)
145c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        tmp = map(lambda x:  x, struct.unpack('16B', a))
146c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
147c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        def parse_digit(a, netmask):
148c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            netmask = min(8,max(netmask,0))
149c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            a = (int(a) & (0xffL<<netmask),(int(a) | (0xffL>>(8-netmask)))+1)
150c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return a
151c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        self.parsed = map(lambda x,y: parse_digit(x,y), tmp, map(lambda x,nm=self.plen: x-nm, tuple))
152c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
153c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        def rec(n, l):
15477132687c31a9d3f30c3992c70eb24d1ac0948a7Phil            if n and  n % 2 == 0:
15577132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                sep = ':'
15677132687c31a9d3f30c3992c70eb24d1ac0948a7Phil            else:
157c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                sep = ''
158c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            if n == 16:
15977132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                return l
160c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            else:
16177132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                ll = []
16277132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                for i in xrange(*self.parsed[n]):
16377132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                    for y in l:
16477132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                        ll += [y+sep+'%.2x'%i]
16577132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                return rec(n+1, ll)
166c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
167c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return iter(rec(0, ['']))
168c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
169c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def __repr__(self):
170c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return "<Net6 %s>" % self.repr
171c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
172c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
173c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
174c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
175c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
176c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
177c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
178c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
179c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil###                              IPv6 Class                               ###
180c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
181c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
182c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
183c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass IP6Field(Field):
184c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def __init__(self, name, default):
185c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        Field.__init__(self, name, default, "16s")
186c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def h2i(self, pkt, x):
187c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if type(x) is str:
188c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            try:
18977132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                x = in6_ptop(x)
190c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            except socket.error:
191c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                x = Net6(x)
192c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        elif type(x) is list:
193c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            x = map(Net6, x)
194c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return x
195c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def i2m(self, pkt, x):
196c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return inet_pton(socket.AF_INET6, x)
197c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def m2i(self, pkt, x):
198c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return inet_ntop(socket.AF_INET6, x)
199c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def any2i(self, pkt, x):
200c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return self.h2i(pkt,x)
201c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def i2repr(self, pkt, x):
202c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if x is None:
20377132687c31a9d3f30c3992c70eb24d1ac0948a7Phil            return self.i2h(pkt,x)
20477132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        elif not isinstance(x, Net6) and not type(x) is list:
20577132687c31a9d3f30c3992c70eb24d1ac0948a7Phil            if in6_isaddrTeredo(x):   # print Teredo info
20677132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                server, flag, maddr, mport = teredoAddrExtractInfo(x)
20777132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                return "%s [Teredo srv: %s cli: %s:%s]" % (self.i2h(pkt, x), server, maddr,mport)
20877132687c31a9d3f30c3992c70eb24d1ac0948a7Phil            elif in6_isaddr6to4(x):   # print encapsulated address
209c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                vaddr = in6_6to4ExtractAddr(x)
21077132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                return "%s [6to4 GW: %s]" % (self.i2h(pkt, x), vaddr)
21177132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        return self.i2h(pkt, x)       # No specific information to return
21251db482d4ed62a5eb7b70c0c4f7a3954d41b6165Phil    def randval(self):
21351db482d4ed62a5eb7b70c0c4f7a3954d41b6165Phil        return RandIP6()
214c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
215c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass SourceIP6Field(IP6Field):
216c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def __init__(self, name, dstname):
217c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        IP6Field.__init__(self, name, None)
218c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        self.dstname = dstname
219c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def i2m(self, pkt, x):
220c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if x is None:
221c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            dst=getattr(pkt,self.dstname)
222c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            iff,x,nh = conf.route6.route(dst)
223c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return IP6Field.i2m(self, pkt, x)
224c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def i2h(self, pkt, x):
225c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if x is None:
226c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            dst=getattr(pkt,self.dstname)
227c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            if isinstance(dst,Gen):
228c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                r = map(conf.route6.route, dst)
229c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                r.sort()
230c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                if r[0] == r[-1]:
231c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    x=r[0][1]
232c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                else:
233c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    warning("More than one possible route for %s"%repr(dst))
234c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    return None
235c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            else:
23677132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                iff,x,nh = conf.route6.route(dst)
237c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return IP6Field.i2h(self, pkt, x)
238c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
239c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilipv6nh = { 0:"Hop-by-Hop Option Header",
240c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil           4:"IP",
241c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil           6:"TCP",
242c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil          17:"UDP",
243c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil          41:"IPv6",
244c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil          43:"Routing Header",
245c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil          44:"Fragment Header",
246c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil          47:"GRE",
247c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil          50:"ESP Header",
248c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil          51:"AH Header",
249c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil          58:"ICMPv6",
250c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil          59:"No Next Header",
251c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil          60:"Destination Option Header",
252c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil         135:"Mobility Header"}
253c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
254c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilipv6nhcls = {  0: "IPv6ExtHdrHopByHop",
255c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               4: "IP",
256c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               6: "TCP",
257c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               17: "UDP",
258c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               43: "IPv6ExtHdrRouting",
259c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               44: "IPv6ExtHdrFragment",
260c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil              #50: "IPv6ExtHrESP",
261c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil              #51: "IPv6ExtHdrAH",
26277132687c31a9d3f30c3992c70eb24d1ac0948a7Phil               58: "ICMPv6Unknown",
263c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               59: "Raw",
264c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               60: "IPv6ExtHdrDestOpt" }
265c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
266c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass IP6ListField(StrField):
267c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    islist = 1
268c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def __init__(self, name, default, count_from=None, length_from=None):
269c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if default is None:
270c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            default = []
271c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        StrField.__init__(self, name, default)
272c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        self.count_from = count_from
273c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        self.length_from = length_from
274c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
275c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def i2len(self, pkt, i):
276c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return 16*len(i)
277c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
278c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def i2count(self, pkt, i):
279c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if type(i) is list:
280c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return len(i)
281c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return 0
282c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
283c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def getfield(self, pkt, s):
284c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        c = l = None
285c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if self.length_from is not None:
286c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            l = self.length_from(pkt)
287c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        elif self.count_from is not None:
288c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            c = self.count_from(pkt)
289c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
290c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        lst = []
291c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        ret = ""
292c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        remain = s
293c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if l is not None:
294c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            remain,ret = s[:l],s[l:]
295c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        while remain:
296c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            if c is not None:
297c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                if c <= 0:
298c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    break
299c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                c -= 1
300c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            addr = inet_ntop(socket.AF_INET6, remain[:16])
301c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            lst.append(addr)
302c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            remain = remain[16:]
303c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return remain+ret,lst
304c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
305c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def i2m(self, pkt, x):
30677132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        s = ''
307c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        for y in x:
308c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            try:
309c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                y = inet_pton(socket.AF_INET6, y)
310c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            except:
311c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                y = socket.getaddrinfo(y, None, socket.AF_INET6)[0][-1][0]
312c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                y = inet_pton(socket.AF_INET6, y)
313c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            s += y
31477132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        return s
315c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
316c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def i2repr(self,pkt,x):
317c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        s = []
31877132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        if x == None:
31977132687c31a9d3f30c3992c70eb24d1ac0948a7Phil            return "[]"
32077132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        for y in x:
32177132687c31a9d3f30c3992c70eb24d1ac0948a7Phil            s.append('%s' % y)
322c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return "[ %s ]" % (", ".join(s))
32377132687c31a9d3f30c3992c70eb24d1ac0948a7Phil
32477132687c31a9d3f30c3992c70eb24d1ac0948a7Philclass _IPv6GuessPayload:
325c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "Dummy class that implements guess_payload_class() for IPv6"
326c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def default_payload_class(self,p):
327c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if self.nh == 58 and len(p) > 2:
328c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            t = ord(p[0])
329c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            if t == 139 or t == 140: # Node Info Query
330c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                return _niquery_guesser(p)
331c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return get_cls(icmp6typescls.get(t,"Raw"), "Raw")
332c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        elif self.nh == 135 and len(p) > 3:
333c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return _mip6_mhtype2cls.get(ord(p[2]), MIP6MH_Generic)
33477132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        else:
33577132687c31a9d3f30c3992c70eb24d1ac0948a7Phil            return get_cls(ipv6nhcls.get(self.nh,"Raw"), "Raw")
336c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
337c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass IPv6(_IPv6GuessPayload, Packet, IPTools):
338c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "IPv6"
339c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ BitField("version" , 6 , 4),
340c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    BitField("tc", 0, 8), #TODO: IPv6, ByteField ?
34177132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                    BitField("fl", 0, 20),
34277132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                    ShortField("plen", None),
343c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteEnumField("nh", 59, ipv6nh),
344c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("hlim", 64),
345c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    SourceIP6Field("src", "dst"), # dst is for src @ selection
346c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    IP6Field("dst", "::1") ]
347614f54fc4b269030ba2934b6c353fb43de886e04Phil
348614f54fc4b269030ba2934b6c353fb43de886e04Phil    def route(self):
349614f54fc4b269030ba2934b6c353fb43de886e04Phil        dst = self.dst
350614f54fc4b269030ba2934b6c353fb43de886e04Phil        if isinstance(dst,Gen):
351614f54fc4b269030ba2934b6c353fb43de886e04Phil            dst = iter(dst).next()
352614f54fc4b269030ba2934b6c353fb43de886e04Phil        return conf.route6.route(dst)
353614f54fc4b269030ba2934b6c353fb43de886e04Phil
354c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def mysummary(self):
355c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return "%s > %s (%i)" % (self.src,self.dst, self.nh)
356c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
357c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def post_build(self, p, pay):
35877132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        p += pay
359c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if self.plen is None:
360c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            l = len(p) - 40
361c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            p = p[:4]+struct.pack("!H", l)+p[6:]
362c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return p
363c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
364c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def extract_padding(self, s):
365c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        l = self.plen
366c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return s[:l], s[l:]
367c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
368c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def hashret(self):
369c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if self.nh == 58 and isinstance(self.payload, _ICMPv6):
370c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            if self.payload.type < 128:
371c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                return self.payload.payload.hashret()
372c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            elif (self.payload.type in [133,134,135,136,144,145]):
373c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                return struct.pack("B", self.nh)+self.payload.hashret()
374c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
37577132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        nh = self.nh
37677132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        sd = self.dst
37777132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        ss = self.src
378c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if self.nh == 43 and isinstance(self.payload, IPv6ExtHdrRouting):
37977132687c31a9d3f30c3992c70eb24d1ac0948a7Phil            # With routing header, the destination is the last
38077132687c31a9d3f30c3992c70eb24d1ac0948a7Phil            # address of the IPv6 list if segleft > 0
38177132687c31a9d3f30c3992c70eb24d1ac0948a7Phil            nh = self.payload.nh
38277132687c31a9d3f30c3992c70eb24d1ac0948a7Phil            try:
38377132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                sd = self.addresses[-1]
38477132687c31a9d3f30c3992c70eb24d1ac0948a7Phil            except IndexError:
38577132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                sd = '::1'
38677132687c31a9d3f30c3992c70eb24d1ac0948a7Phil            # TODO: big bug with ICMPv6 error messages as the destination of IPerror6
38777132687c31a9d3f30c3992c70eb24d1ac0948a7Phil            #       could be anything from the original list ...
38877132687c31a9d3f30c3992c70eb24d1ac0948a7Phil            if 1:
38977132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                sd = inet_pton(socket.AF_INET6, sd)
39077132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                for a in self.addresses:
39177132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                    a = inet_pton(socket.AF_INET6, a)
39277132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                    sd = strxor(sd, a)
39377132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                sd = inet_ntop(socket.AF_INET6, sd)
394c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
395c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if self.nh == 44 and isinstance(self.payload, IPv6ExtHdrFragment):
396c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            nh = self.payload.nh
397c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
398c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if self.nh == 0 and isinstance(self.payload, IPv6ExtHdrHopByHop):
399c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            nh = self.payload.nh
400c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
401c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if self.nh == 60 and isinstance(self.payload, IPv6ExtHdrDestOpt):
402c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            foundhao = None
403c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            for o in self.payload.options:
404c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                if isinstance(o, HAO):
405c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    foundhao = o
406c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            if foundhao:
407c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                nh = self.payload.nh # XXX what if another extension follows ?
408c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                ss = foundhao.hoa
409c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
410c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if conf.checkIPsrc and conf.checkIPaddr:
411c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            sd = inet_pton(socket.AF_INET6, sd)
412c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            ss = inet_pton(socket.AF_INET6, self.src)
413c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return struct.pack("B",nh)+self.payload.hashret()
414c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        else:
415c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return struct.pack("B", nh)+self.payload.hashret()
416c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
417c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def answers(self, other):
418c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if not isinstance(other, IPv6): # self is reply, other is request
419c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return False
420c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if conf.checkIPaddr:
421c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            ss = inet_pton(socket.AF_INET6, self.src)
422c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            sd = inet_pton(socket.AF_INET6, self.dst)
423c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            os = inet_pton(socket.AF_INET6, other.src)
424c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            od = inet_pton(socket.AF_INET6, other.dst)
42577132687c31a9d3f30c3992c70eb24d1ac0948a7Phil            # request was sent to a multicast address (other.dst)
426c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            # Check reply destination addr matches request source addr (i.e
427c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            # sd == os) except when reply is multicasted too
428c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            # XXX test mcast scope matching ?
429c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            if in6_ismaddr(other.dst):
430c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                if in6_ismaddr(self.dst):
431c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    if ((od == sd) or
432c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                        (in6_isaddrllallnodes(self.dst) and in6_isaddrllallservers(other.dst))):
433c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                         return self.payload.answers(other.payload)
434c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    return False
435c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                if (os == sd):
436c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    return self.payload.answers(other.payload)
437c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                return False
438c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            elif (sd != os): # or ss != od): <- removed for ICMP errors
439c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                return False
440c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if self.nh == 58 and isinstance(self.payload, _ICMPv6) and self.payload.type < 128:
441c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            # ICMPv6 Error message -> generated by IPv6 packet
442c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            # Note : at the moment, we jump the ICMPv6 specific class
443c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            # to call answers() method of erroneous packet (over
444c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            # initial packet). There can be cases where an ICMPv6 error
445c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            # class could implement a specific answers method that perform
446c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            # a specific task. Currently, don't see any use ...
447c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return self.payload.payload.answers(other)
448c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        elif other.nh == 0 and isinstance(other.payload, IPv6ExtHdrHopByHop):
449c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return self.payload.answers(other.payload.payload)
450c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        elif other.nh == 44 and isinstance(other.payload, IPv6ExtHdrFragment):
451c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return self.payload.answers(other.payload.payload)
452c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        elif other.nh == 43 and isinstance(other.payload, IPv6ExtHdrRouting):
453c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return self.payload.answers(other.payload.payload) # Buggy if self.payload is a IPv6ExtHdrRouting
454c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        elif other.nh == 60 and isinstance(other.payload, IPv6ExtHdrDestOpt):
455c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return self.payload.payload.answers(other.payload.payload)
456c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        elif self.nh == 60 and isinstance(self.payload, IPv6ExtHdrDestOpt): # BU in reply to BRR, for instance
457c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return self.payload.payload.answers(other.payload)
458c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        else:
459c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            if (self.nh != other.nh):
460c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                return False
461c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return self.payload.answers(other.payload)
462c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
463614f54fc4b269030ba2934b6c353fb43de886e04Phil
464614f54fc4b269030ba2934b6c353fb43de886e04Philconf.neighbor.register_l3(Ether, IPv6, lambda l2,l3: getmacbyip6(l3.dst))
465614f54fc4b269030ba2934b6c353fb43de886e04Phil
466c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
467c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass IPerror6(IPv6):
468c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "IPv6 in ICMPv6"
469c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def answers(self, other):
470c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if not isinstance(other, IPv6):
471c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return False
47277132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        sd = inet_pton(socket.AF_INET6, self.dst)
47377132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        ss = inet_pton(socket.AF_INET6, self.src)
47477132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        od = inet_pton(socket.AF_INET6, other.dst)
47577132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        os = inet_pton(socket.AF_INET6, other.src)
476c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
47777132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        # Make sure that the ICMPv6 error is related to the packet scapy sent
47877132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        if isinstance(self.underlayer, _ICMPv6) and self.underlayer.type < 128:
479c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
480c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            # find upper layer for self (possible citation)
481c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            selfup = self.payload
482c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            while selfup is not None and isinstance(selfup, _IPv6ExtHdr):
483c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                selfup = selfup.payload
484c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
485c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            # find upper layer for other (initial packet). Also look for RH
486c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            otherup = other.payload
487c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            request_has_rh = False
488c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            while otherup is not None and isinstance(otherup, _IPv6ExtHdr):
489c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                if isinstance(otherup, IPv6ExtHdrRouting):
490c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    request_has_rh = True
491c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                otherup = otherup.payload
492c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
49377132687c31a9d3f30c3992c70eb24d1ac0948a7Phil            if ((ss == os and sd == od) or      # <- Basic case
494c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                (ss == os and request_has_rh)): # <- Request has a RH :
495c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                                #    don't check dst address
496c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
497c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                # Let's deal with possible MSS Clamping
498c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                if (isinstance(selfup, TCP) and
499c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    isinstance(otherup, TCP) and
500c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    selfup.options != otherup.options): # seems clamped
501c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
502c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    # Save fields modified by MSS clamping
503c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    old_otherup_opts    = otherup.options
504c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    old_otherup_cksum   = otherup.chksum
505c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    old_otherup_dataofs = otherup.dataofs
506c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    old_selfup_opts     = selfup.options
507c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    old_selfup_cksum    = selfup.chksum
508c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    old_selfup_dataofs  = selfup.dataofs
509c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
510c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    # Nullify them
511c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    otherup.options = []
512c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    otherup.chksum  = 0
513c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    otherup.dataofs = 0
514c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    selfup.options  = []
515c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    selfup.chksum   = 0
516c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    selfup.dataofs  = 0
517c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
518c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    # Test it and save result
519c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    s1 = str(selfup)
520c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    s2 = str(otherup)
521c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    l = min(len(s1), len(s2))
522c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    res = s1[:l] == s2[:l]
523c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
524c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    # recall saved values
525c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    otherup.options = old_otherup_opts
526c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    otherup.chksum  = old_otherup_cksum
527c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    otherup.dataofs = old_otherup_dataofs
528c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    selfup.options  = old_selfup_opts
529c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    selfup.chksum   = old_selfup_cksum
530c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    selfup.dataofs  = old_selfup_dataofs
531c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
532c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    return res
533c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
534c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                s1 = str(selfup)
535c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                s2 = str(otherup)
536c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                l = min(len(s1), len(s2))
537c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                return s1[:l] == s2[:l]
538c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
539c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return False
540c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
541c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def mysummary(self):
542c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return Packet.mysummary(self)
543c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
544c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
545c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
546c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
547c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil###                 Upper Layer Checksum computation                      ###
548c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
549c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
550c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
551c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass PseudoIPv6(Packet): # IPv6 Pseudo-header for checksum computation
552c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "Pseudo IPv6 Header"
553c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ IP6Field("src", "::"),
554c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    IP6Field("dst", "::"),
55577132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                    ShortField("uplen", None),
556c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    BitField("zero", 0, 24),
557c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("nh", 0) ]
558c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
559c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhildef in6_chksum(nh, u, p):
560c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    """
561c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    Performs IPv6 Upper Layer checksum computation. Provided parameters are:
562c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
563c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    - 'nh' : value of upper layer protocol
564c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    - 'u'  : upper layer instance (TCP, UDP, ICMPv6*, ). Instance must be
565c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             provided with all under layers (IPv6 and all extension headers,
566c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             for example)
567c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    - 'p'  : the payload of the upper layer provided as a string
568c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
569c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    Functions operate by filling a pseudo header class instance (PseudoIPv6)
570c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    with
571c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    - Next Header value
572c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    - the address of _final_ destination (if some Routing Header with non
573c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    segleft field is present in underlayer classes, last address is used.)
574c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    - the address of _real_ source (basically the source address of an
575c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    IPv6 class instance available in the underlayer or the source address
576c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    in HAO option if some Destination Option header found in underlayer
577c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    includes this option).
578c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    - the length is the length of provided payload string ('p')
579c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    """
580c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
581c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    ph6 = PseudoIPv6()
582c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    ph6.nh = nh
583c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    rthdr = 0
584c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    hahdr = 0
585c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    final_dest_addr_found = 0
586c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    while u != None and not isinstance(u, IPv6):
58777132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        if (isinstance(u, IPv6ExtHdrRouting) and
58877132687c31a9d3f30c3992c70eb24d1ac0948a7Phil            u.segleft != 0 and len(u.addresses) != 0 and
589c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            final_dest_addr_found == 0):
59077132687c31a9d3f30c3992c70eb24d1ac0948a7Phil            rthdr = u.addresses[-1]
591c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            final_dest_addr_found = 1
59277132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        elif (isinstance(u, IPv6ExtHdrDestOpt) and (len(u.options) == 1) and
593c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             isinstance(u.options[0], HAO)):
594c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             hahdr  = u.options[0].hoa
59577132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        u = u.underlayer
596c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    if u is None:
59777132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        warning("No IPv6 underlayer to compute checksum. Leaving null.")
59877132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        return 0
59977132687c31a9d3f30c3992c70eb24d1ac0948a7Phil    if hahdr:
60077132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        ph6.src = hahdr
601c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    else:
602c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        ph6.src = u.src
603c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    if rthdr:
60477132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        ph6.dst = rthdr
605c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    else:
60677132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        ph6.dst = u.dst
607c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    ph6.uplen = len(p)
608c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    ph6s = str(ph6)
609c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    return checksum(ph6s+p)
610c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
611c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
612c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
613c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
614c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil###                         Extension Headers                             ###
615c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
616c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
617c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
618c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
619c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# Inherited by all extension header classes
620c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass _IPv6ExtHdr(_IPv6GuessPayload, Packet):
621c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = 'Abstract IPV6 Option Header'
622c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    aliastypes = [IPv6, IPerror6] # TODO ...
623c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
624c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
625c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#################### IPv6 options for Extension Headers #####################
626c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
627c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil_hbhopts = { 0x00: "Pad1",
628c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             0x01: "PadN",
629c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             0x04: "Tunnel Encapsulation Limit",
630c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             0x05: "Router Alert",
631c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             0x06: "Quick-Start",
632c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             0xc2: "Jumbo Payload",
633c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             0xc9: "Home Address Option" }
634c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
635c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass _OTypeField(ByteEnumField):
636c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    """
637c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    Modified BytEnumField that displays information regarding the IPv6 option
638c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    based on its option type value (What should be done by nodes that process
639c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    the option if they do not understand it ...)
640c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
641c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    It is used by Jumbo, Pad1, PadN, RouterAlert, HAO options
642c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    """
643c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    pol = {0x00: "00: skip",
644c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil           0x40: "01: discard",
645c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil           0x80: "10: discard+ICMP",
646c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil           0xC0: "11: discard+ICMP not mcast"}
647c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
648c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    enroutechange = {0x00: "0: Don't change en-route",
649c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                 0x20: "1: May change en-route" }
650c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
651c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def i2repr(self, pkt, x):
652c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        s = self.i2s.get(x, repr(x))
653c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        polstr = self.pol[(x & 0xC0)]
654c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        enroutechangestr = self.enroutechange[(x & 0x20)]
655c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return "%s [%s, %s]" % (s, polstr, enroutechangestr)
656c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
657c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass HBHOptUnknown(Packet): # IPv6 Hop-By-Hop Option
658c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "Scapy6 Unknown Option"
659c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [_OTypeField("otype", 0x01, _hbhopts),
660c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   FieldLenField("optlen", None, length_of="optdata", fmt="B"),
661c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   StrLenField("optdata", "",
662c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                               length_from = lambda pkt: pkt.optlen) ]
663c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def alignment_delta(self, curpos): # By default, no alignment requirement
664c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        """
665c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        As specified in section 4.2 of RFC 2460, every options has
666c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        an alignment requirement ususally expressed xn+y, meaning
667c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        the Option Type must appear at an integer multiple of x octest
668c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        from the start of the header, plus y octet.
669c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
670c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        That function is provided the current position from the
671c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        start of the header and returns required padding length.
672c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        """
673c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return 0
674c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
675c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass Pad1(Packet): # IPv6 Hop-By-Hop Option
676c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "Pad1"
677c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ _OTypeField("otype", 0x00, _hbhopts) ]
678c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def alignment_delta(self, curpos): # No alignment requirement
679c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return 0
680c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
681c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass PadN(Packet): # IPv6 Hop-By-Hop Option
682c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "PadN"
683c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [_OTypeField("otype", 0x01, _hbhopts),
684c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   FieldLenField("optlen", None, length_of="optdata", fmt="B"),
685c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   StrLenField("optdata", "",
686c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                               length_from = lambda pkt: pkt.optlen)]
687c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def alignment_delta(self, curpos): # No alignment requirement
688c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return 0
689c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
690c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass RouterAlert(Packet): # RFC 2711 - IPv6 Hop-By-Hop Option
691c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "Router Alert"
692c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [_OTypeField("otype", 0x05, _hbhopts),
693c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   ByteField("optlen", 2),
694c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   ShortEnumField("value", None,
695c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                  { 0: "Datagram contains a MLD message",
696c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                    1: "Datagram contains RSVP message",
697c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                    2: "Datagram contains an Active Network message" }) ]
698c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    # TODO : Check IANA has not defined new values for value field of RouterAlertOption
699c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    # TODO : now that we have that option, we should do something in MLD class that need it
700c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def alignment_delta(self, curpos): # alignment requirement : 2n+0
701c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        x = 2 ; y = 0
702c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        delta = x*((curpos - y + x - 1)/x) + y - curpos
703c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return delta
704c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
705c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass Jumbo(Packet): # IPv6 Hop-By-Hop Option
706c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "Jumbo Payload"
707c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [_OTypeField("otype", 0xC2, _hbhopts),
708c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   ByteField("optlen", 4),
709c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   IntField("jumboplen", None) ]
710c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def alignment_delta(self, curpos): # alignment requirement : 4n+2
711c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        x = 4 ; y = 2
712c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        delta = x*((curpos - y + x - 1)/x) + y - curpos
713c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return delta
714c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
715c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass HAO(Packet): # IPv6 Destination Options Header Option
716c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "Home Address Option"
717c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [_OTypeField("otype", 0xC9, _hbhopts),
718c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   ByteField("optlen", 16),
719c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   IP6Field("hoa", "::") ]
720c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def alignment_delta(self, curpos): # alignment requirement : 8n+6
721c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        x = 8 ; y = 6
722c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        delta = x*((curpos - y + x - 1)/x) + y - curpos
723c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return delta
724c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
725c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil_hbhoptcls = { 0x00: Pad1,
726c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               0x01: PadN,
727c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               0x05: RouterAlert,
728c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               0xC2: Jumbo,
729c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               0xC9: HAO }
730c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
731c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
732c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil######################## Hop-by-Hop Extension Header ########################
733c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
734c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass _HopByHopOptionsField(PacketListField):
735c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    islist = 1
736c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    holds_packet = 1
737c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def __init__(self, name, default, cls, curpos, count_from=None, length_from=None):
738c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        self.curpos = curpos
739c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        PacketListField.__init__(self, name, default, cls, count_from=count_from, length_from=length_from)
740c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
741c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def i2len(self, pkt, i):
742c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        l = len(self.i2m(pkt, i))
743c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return l
744c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
745c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def i2count(self, pkt, i):
746c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if type(i) is list:
747c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return len(i)
748c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return 0
749c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
750c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def getfield(self, pkt, s):
751c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        c = l = None
752c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if self.length_from is not None:
753c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            l = self.length_from(pkt)
754c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        elif self.count_from is not None:
755c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            c = self.count_from(pkt)
756c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
757c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        opt = []
758c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        ret = ""
759c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        x = s
760c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if l is not None:
761c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            x,ret = s[:l],s[l:]
762c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        while x:
763c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            if c is not None:
764c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                if c <= 0:
765c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    break
766c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                c -= 1
767c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            o = ord(x[0]) # Option type
768c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            cls = self.cls
769c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            if _hbhoptcls.has_key(o):
770c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                cls = _hbhoptcls[o]
771c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            try:
772c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                op = cls(x)
773c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            except:
774c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                op = self.cls(x)
775c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            opt.append(op)
776c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            if isinstance(op.payload, Raw):
777c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                x = op.payload.load
778c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                del(op.payload)
779c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            else:
780c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                x = ""
781c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return x+ret,opt
782c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
783c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def i2m(self, pkt, x):
784c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        autopad = None
785c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        try:
786c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            autopad = getattr(pkt, "autopad") # Hack : 'autopad' phantom field
787c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        except:
788c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            autopad = 1
789c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
790c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if not autopad:
791c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return "".join(map(str, x))
792c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
793c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        curpos = self.curpos
794c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        s = ""
795c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        for p in x:
796c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            d = p.alignment_delta(curpos)
797c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            curpos += d
798c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            if d == 1:
799c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                s += str(Pad1())
800c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            elif d != 0:
801c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                s += str(PadN(optdata='\x00'*(d-2)))
802c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            pstr = str(p)
803c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            curpos += len(pstr)
804c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            s += pstr
805c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
806c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        # Let's make the class including our option field
807c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        # a multiple of 8 octets long
808c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        d = curpos % 8
809c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if d == 0:
810c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return s
811c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        d = 8 - d
812c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if d == 1:
813c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            s += str(Pad1())
814c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        elif d != 0:
815c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            s += str(PadN(optdata='\x00'*(d-2)))
816c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
817c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return s
818c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
819c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def addfield(self, pkt, s, val):
820c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return s+self.i2m(pkt, val)
821c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
822c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass _PhantomAutoPadField(ByteField):
823c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def addfield(self, pkt, s, val):
824c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return s
825c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
826c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def getfield(self, pkt, s):
827c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return s, 1
828c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
829c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def i2repr(self, pkt, x):
830c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if x:
831c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return "On"
832c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return "Off"
833c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
834c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
835c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass IPv6ExtHdrHopByHop(_IPv6ExtHdr):
836c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "IPv6 Extension Header - Hop-by-Hop Options Header"
837c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("nh", 59, ipv6nh),
838c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    FieldLenField("len", None, length_of="options", fmt="B",
839c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                  adjust = lambda pkt,x: (x+2+7)/8 - 1),
840c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    _PhantomAutoPadField("autopad", 1), # autopad activated by default
84177132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                    _HopByHopOptionsField("options", [], HBHOptUnknown, 2,
842c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                          length_from = lambda pkt: (8*(pkt.len+1))-2) ]
843c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    overload_fields = {IPv6: { "nh": 0 }}
844c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
845c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
846c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil######################## Destination Option Header ##########################
847c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
848c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass IPv6ExtHdrDestOpt(_IPv6ExtHdr):
849c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "IPv6 Extension Header - Destination Options Header"
850c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("nh", 59, ipv6nh),
851c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    FieldLenField("len", None, length_of="options", fmt="B",
852c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                  adjust = lambda pkt,x: (x+2+7)/8 - 1),
853c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    _PhantomAutoPadField("autopad", 1), # autopad activated by default
85477132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                    _HopByHopOptionsField("options", [], HBHOptUnknown, 2,
855c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                          length_from = lambda pkt: (8*(pkt.len+1))-2) ]
856c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    overload_fields = {IPv6: { "nh": 60 }}
857c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
858c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
859c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil############################# Routing Header ################################
860c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
861c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass IPv6ExtHdrRouting(_IPv6ExtHdr):
862c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "IPv6 Option Header Routing"
863c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("nh", 59, ipv6nh),
864c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    FieldLenField("len", None, count_of="addresses", fmt="B",
865c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                  adjust = lambda pkt,x:2*x), # in 8 bytes blocks
866c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("type", 0),
867c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("segleft", None),
868c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    BitField("reserved", 0, 32), # There is meaning in this field ...
86977132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                    IP6ListField("addresses", [],
870c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                 length_from = lambda pkt: 8*pkt.len)]
871c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    overload_fields = {IPv6: { "nh": 43 }}
872c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
873c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def post_build(self, pkt, pay):
874c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if self.segleft is None:
875c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            pkt = pkt[:3]+struct.pack("B", len(self.addresses))+pkt[4:]
876c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return _IPv6ExtHdr.post_build(self, pkt, pay)
877c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
878c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil########################### Fragmentation Header ############################
879c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
88077132687c31a9d3f30c3992c70eb24d1ac0948a7Philclass IPv6ExtHdrFragment(_IPv6ExtHdr):
881c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "IPv6 Extension Header - Fragmentation header"
882c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("nh", 59, ipv6nh),
883c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    BitField("res1", 0, 8),
88477132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                    BitField("offset", 0, 13),
88577132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                    BitField("res2", 0, 2),
88677132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                    BitField("m", 0, 1),
88777132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                    IntField("id", None) ]
888c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    overload_fields = {IPv6: { "nh": 44 }}
889c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
890c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
891c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhildef defragment6(pktlist):
892c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    """
893c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    Performs defragmentation of a list of IPv6 packets. Packets are reordered.
894c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    Crap is dropped. What lacks is completed by 'X' characters.
895c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    """
896c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
897c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    l = filter(lambda x: IPv6ExtHdrFragment in x, pktlist) # remove non fragments
898c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    if not l:
899c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return []
900c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
901c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    id = l[0][IPv6ExtHdrFragment].id
902c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
903c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    llen = len(l)
904c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    l = filter(lambda x: x[IPv6ExtHdrFragment].id == id, l)
905c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    if len(l) != llen:
906c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        warning("defragment6: some fragmented packets have been removed from list")
907c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    llen = len(l)
908c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
909c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    # reorder fragments
910c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    i = 0
911c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    res = []
912c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    while l:
913c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        min_pos = 0
914c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        min_offset  = l[0][IPv6ExtHdrFragment].offset
915c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        for p in l:
916c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            cur_offset = p[IPv6ExtHdrFragment].offset
917c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            if cur_offset < min_offset:
918c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                min_pos = 0
919c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                min_offset  = cur_offset
920c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        res.append(l[min_pos])
921c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        del(l[min_pos])
922c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
923c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    # regenerate the fragmentable part
924c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fragmentable = ""
925c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    for p in res:
926c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        q=p[IPv6ExtHdrFragment]
927c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        offset = 8*q.offset
928c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if offset != len(fragmentable):
929c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            warning("Expected an offset of %d. Found %d. Padding with XXXX" % (len(fragmentable), offset))
930c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        fragmentable += "X"*(offset - len(fragmentable))
931c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        fragmentable += str(q.payload)
932c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
933c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    # Regenerate the unfragmentable part.
934c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    q = res[0]
935c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    nh = q[IPv6ExtHdrFragment].nh
936c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    q[IPv6ExtHdrFragment].underlayer.nh = nh
937c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    q[IPv6ExtHdrFragment].underlayer.payload = None
938c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    q /= Raw(load=fragmentable)
939c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
940c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    return IPv6(str(q))
941c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
942c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
943c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhildef fragment6(pkt, fragSize):
944c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    """
945c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    Performs fragmentation of an IPv6 packet. Provided packet ('pkt') must already
946c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    contain an IPv6ExtHdrFragment() class. 'fragSize' argument is the expected
947c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    maximum size of fragments (MTU). The list of packets is returned.
948c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
949c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    If packet does not contain an IPv6ExtHdrFragment class, it is returned in
950c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    result list.
951c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    """
952c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
953c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    pkt = pkt.copy()
954c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    s = str(pkt) # for instantiation to get upper layer checksum right
955c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
956c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    if len(s) <= fragSize:
957c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return [pkt]
958c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
959c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    if not IPv6ExtHdrFragment in pkt:
960c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        # TODO : automatically add a fragment before upper Layer
961c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        #        at the moment, we do nothing and return initial packet
962c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        #        as single element of a list
963c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return [pkt]
964c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
965c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    # Fragmentable part : fake IPv6 for Fragmentable part length computation
966c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fragPart = pkt[IPv6ExtHdrFragment].payload
967c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    tmp = str(IPv6(src="::1", dst="::1")/fragPart)
968c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fragPartLen = len(tmp) - 40  # basic IPv6 header length
969c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fragPartStr = s[-fragPartLen:]
970c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
971c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    # Grab Next Header for use in Fragment Header
972c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    nh = IPv6(tmp[:40]).nh
973c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
974c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    # Keep fragment header
975c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fragHeader = pkt[IPv6ExtHdrFragment]
976c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fragHeader.payload = None # detach payload
977c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
978c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    # Unfragmentable Part
979c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    unfragPartLen = len(s) - fragPartLen - 8
980c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    unfragPart = pkt
981c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    pkt[IPv6ExtHdrFragment].underlayer.payload = None # detach payload
982c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
983c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    # Cut the fragmentable part to fit fragSize. Inner fragments have
984c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    # a length that is an integer multiple of 8 octets. last Frag MTU
985c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    # can be anything below MTU
986c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    lastFragSize = fragSize - unfragPartLen - 8
987c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    innerFragSize = lastFragSize - (lastFragSize % 8)
988c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
989c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    if lastFragSize <= 0 or innerFragSize == 0:
990c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        warning("Provided fragment size value is too low. " +
991c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                "Should be more than %d" % (unfragPartLen + 8))
992c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return [unfragPart/fragHeader/fragPart]
993c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
994c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    remain = fragPartStr
995c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    res = []
996c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fragOffset = 0     # offset, incremeted during creation
997c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fragId = random.randint(0,0xffffffff) # random id ...
998c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    if fragHeader.id is not None:  # ... except id provided by user
999c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        fragId = fragHeader.id
1000c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fragHeader.m = 1
1001c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fragHeader.id = fragId
1002c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fragHeader.nh = nh
1003c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1004c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    # Main loop : cut, fit to FRAGSIZEs, fragOffset, Id ...
1005c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    while True:
1006c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if (len(remain) > lastFragSize):
1007c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            tmp = remain[:innerFragSize]
1008c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            remain = remain[innerFragSize:]
1009c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            fragHeader.offset = fragOffset    # update offset
1010c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            fragOffset += (innerFragSize / 8)  # compute new one
1011c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            if IPv6 in unfragPart:
1012c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                unfragPart[IPv6].plen = None
1013c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            tempo = unfragPart/fragHeader/Raw(load=tmp)
1014c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            res.append(tempo)
1015c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        else:
1016c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            fragHeader.offset = fragOffset    # update offSet
1017c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            fragHeader.m = 0
1018c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            if IPv6 in unfragPart:
1019c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                unfragPart[IPv6].plen = None
1020c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            tempo = unfragPart/fragHeader/Raw(load=remain)
1021c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            res.append(tempo)
1022c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            break
1023c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    return res
1024c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1025c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1026c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil############################### AH Header ###################################
1027c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1028c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# class _AHFieldLenField(FieldLenField):
1029c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#     def getfield(self, pkt, s):
1030c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#         l = getattr(pkt, self.fld)
1031c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#         l = (l*8)-self.shift
1032c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#         i = self.m2i(pkt, s[:l])
1033c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#         return s[l:],i
1034c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1035c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# class _AHICVStrLenField(StrLenField):
1036c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#     def i2len(self, pkt, x):
1037c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1038c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1039c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1040c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# class IPv6ExtHdrAH(_IPv6ExtHdr):
1041c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#     name = "IPv6 Extension Header - AH"
1042c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#     fields_desc = [ ByteEnumField("nh", 59, ipv6nh),
1043c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#                     _AHFieldLenField("len", None, "icv"),
1044c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#                     ShortField("res", 0),
1045c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#                     IntField("spi", 0),
1046c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#                     IntField("sn", 0),
1047c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#                     _AHICVStrLenField("icv", None, "len", shift=2) ]
1048c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#     overload_fields = {IPv6: { "nh": 51 }}
1049c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1050c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#     def post_build(self, pkt, pay):
1051c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#         if self.len is None:
1052c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#             pkt = pkt[0]+struct.pack("!B", 2*len(self.addresses))+pkt[2:]
1053c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#         if self.segleft is None:
1054c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#             pkt = pkt[:3]+struct.pack("!B", len(self.addresses))+pkt[4:]
1055c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#         return _IPv6ExtHdr.post_build(self, pkt, pay)
1056c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1057c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1058c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil############################### ESP Header ##################################
1059c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1060c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# class IPv6ExtHdrESP(_IPv6extHdr):
1061c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#     name = "IPv6 Extension Header - ESP"
1062c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#     fields_desc = [ IntField("spi", 0),
1063c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#                     IntField("sn", 0),
1064c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#                     # there is things to extract from IKE work
1065c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#                     ]
1066c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#     overloads_fields = {IPv6: { "nh": 50 }}
1067c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1068c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1069c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1070c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
1071c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
1072c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil###                           ICMPv6* Classes                             ###
1073c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
1074c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
1075c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1076c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilicmp6typescls = {    1: "ICMPv6DestUnreach",
1077c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                     2: "ICMPv6PacketTooBig",
1078c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                     3: "ICMPv6TimeExceeded",
1079c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                     4: "ICMPv6ParamProblem",
1080c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   128: "ICMPv6EchoRequest",
1081c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   129: "ICMPv6EchoReply",
1082c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   130: "ICMPv6MLQuery",
1083c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   131: "ICMPv6MLReport",
1084c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   132: "ICMPv6MLDone",
1085c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   133: "ICMPv6ND_RS",
1086c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   134: "ICMPv6ND_RA",
1087c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   135: "ICMPv6ND_NS",
1088c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   136: "ICMPv6ND_NA",
1089c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   137: "ICMPv6ND_Redirect",
1090c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                  #138: Do Me - RFC 2894 - Seems painful
1091c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   139: "ICMPv6NIQuery",
1092c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   140: "ICMPv6NIReply",
1093c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   141: "ICMPv6ND_INDSol",
1094c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   142: "ICMPv6ND_INDAdv",
1095c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                  #143: Do Me - RFC 3810
109677132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                   144: "ICMPv6HAADRequest",
109777132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                   145: "ICMPv6HAADReply",
109877132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                   146: "ICMPv6MPSol",
109977132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                   147: "ICMPv6MPAdv",
1100c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                  #148: Do Me - SEND related - RFC 3971
1101c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                  #149: Do Me - SEND related - RFC 3971
1102c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   151: "ICMPv6MRD_Advertisement",
1103c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   152: "ICMPv6MRD_Solicitation",
1104c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   153: "ICMPv6MRD_Termination",
110577132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                   }
1106c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1107c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilicmp6types = { 1 : "Destination unreachable",
1108c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               2 : "Packet too big",
110977132687c31a9d3f30c3992c70eb24d1ac0948a7Phil               3 : "Time exceeded",
1110c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               4 : "Parameter problem",
1111c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             100 : "Private Experimentation",
1112c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             101 : "Private Experimentation",
1113c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             128 : "Echo Request",
1114c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             129 : "Echo Reply",
1115c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             130 : "MLD Query",
111677132687c31a9d3f30c3992c70eb24d1ac0948a7Phil             131 : "MLD Report",
111777132687c31a9d3f30c3992c70eb24d1ac0948a7Phil             132 : "MLD Done",
111877132687c31a9d3f30c3992c70eb24d1ac0948a7Phil             133 : "Router Solicitation",
111977132687c31a9d3f30c3992c70eb24d1ac0948a7Phil             134 : "Router Advertisement",
112077132687c31a9d3f30c3992c70eb24d1ac0948a7Phil             135 : "Neighbor Solicitation",
112177132687c31a9d3f30c3992c70eb24d1ac0948a7Phil             136 : "Neighbor Advertisement",
112277132687c31a9d3f30c3992c70eb24d1ac0948a7Phil             137 : "Redirect Message",
112377132687c31a9d3f30c3992c70eb24d1ac0948a7Phil             138 : "Router Renumbering",
112477132687c31a9d3f30c3992c70eb24d1ac0948a7Phil             139 : "ICMP Node Information Query",
112577132687c31a9d3f30c3992c70eb24d1ac0948a7Phil             140 : "ICMP Node Information Response",
112677132687c31a9d3f30c3992c70eb24d1ac0948a7Phil             141 : "Inverse Neighbor Discovery Solicitation Message",
112777132687c31a9d3f30c3992c70eb24d1ac0948a7Phil             142 : "Inverse Neighbor Discovery Advertisement Message",
112877132687c31a9d3f30c3992c70eb24d1ac0948a7Phil             143 : "Version 2 Multicast Listener Report",
112977132687c31a9d3f30c3992c70eb24d1ac0948a7Phil             144 : "Home Agent Address Discovery Request Message",
113077132687c31a9d3f30c3992c70eb24d1ac0948a7Phil             145 : "Home Agent Address Discovery Reply Message",
113177132687c31a9d3f30c3992c70eb24d1ac0948a7Phil             146 : "Mobile Prefix Solicitation",
113277132687c31a9d3f30c3992c70eb24d1ac0948a7Phil             147 : "Mobile Prefix Advertisement",
113377132687c31a9d3f30c3992c70eb24d1ac0948a7Phil             148 : "Certification Path Solicitation",
113477132687c31a9d3f30c3992c70eb24d1ac0948a7Phil             149 : "Certification Path Advertisement",
1135c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             151 : "Multicast Router Advertisement",
1136c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             152 : "Multicast Router Solicitation",
1137c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             153 : "Multicast Router Termination",
1138c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             200 : "Private Experimentation",
1139c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             201 : "Private Experimentation" }
1140c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1141c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1142c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass _ICMPv6(Packet):
1143c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 dummy class"
1144c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    overload_fields = {IPv6: {"nh": 58}}
1145c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def post_build(self, p, pay):
114677132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        p += pay
1147c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if self.cksum == None:
114877132687c31a9d3f30c3992c70eb24d1ac0948a7Phil            chksum = in6_chksum(58, self.underlayer, p)
114977132687c31a9d3f30c3992c70eb24d1ac0948a7Phil            p = p[:2]+struct.pack("!H", chksum)+p[4:]
115077132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        return p
1151c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1152c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def hashret(self):
1153c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return self.payload.hashret()
1154c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1155c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def answers(self, other):
1156c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        # isinstance(self.underlayer, _IPv6ExtHdr) may introduce a bug ...
115777132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        if (isinstance(self.underlayer, IPerror6) or
1158c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            isinstance(self.underlayer, _IPv6ExtHdr) and
1159c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            isinstance(other, _ICMPv6)):
116077132687c31a9d3f30c3992c70eb24d1ac0948a7Phil            if not ((self.type == other.type) and
116177132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                    (self.code == other.code)):
116277132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                return 0
116377132687c31a9d3f30c3992c70eb24d1ac0948a7Phil            return 1
116477132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        return 0
1165c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1166c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1167c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass _ICMPv6Error(_ICMPv6):
1168c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 errors dummy class"
1169c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def guess_payload_class(self,p):
117077132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        return IPerror6
1171c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1172c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6Unknown(_ICMPv6):
1173c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "Scapy6 ICMPv6 fallback class"
1174c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("type",1, icmp6types),
1175c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("code",0),
1176c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("cksum", None),
1177c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    StrField("msgbody", "")]
1178c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1179c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1180c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil################################## RFC 2460 #################################
1181c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1182c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6DestUnreach(_ICMPv6Error):
1183c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Destination Unreachable"
1184c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("type",1, icmp6types),
1185c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteEnumField("code",0, { 0: "No route to destination",
1186c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                              1: "Communication with destination administratively prohibited",
1187c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                              2: "Beyond scope of source address",
1188c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                              3: "Address unreachable",
1189c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                              4: "Port unreachable" }),
1190c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("cksum", None),
1191c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XIntField("unused",0x00000000)]
1192c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1193c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6PacketTooBig(_ICMPv6Error):
1194c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Packet Too Big"
1195c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("type",2, icmp6types),
1196c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("code",0),
1197c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("cksum", None),
1198c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    IntField("mtu",1280)]
1199c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1200c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6TimeExceeded(_ICMPv6Error):
1201c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Time Exceeded"
1202c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("type",3, icmp6types),
1203c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("code",{ 0: "hop limit exceeded in transit",
1204c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                       1: "fragment reassembly time exceeded"}),
1205c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("cksum", None),
1206c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XIntField("unused",0x00000000)]
1207c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1208c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# The default pointer value is set to the next header field of
1209c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# the encapsulated IPv6 packet
1210c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6ParamProblem(_ICMPv6Error):
1211c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Parameter Problem"
1212c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("type",4, icmp6types),
1213c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteEnumField("code",0, {0: "erroneous header field encountered",
1214c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                             1: "unrecognized Next Header type encountered",
1215c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                             2: "unrecognized IPv6 option encountered"}),
1216c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("cksum", None),
1217c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    IntField("ptr",6)]
1218c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1219c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6EchoRequest(_ICMPv6):
1220c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Echo Request"
1221c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("type", 128, icmp6types),
1222c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("code", 0),
1223c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("cksum", None),
1224c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("id",0),
1225c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("seq",0),
1226c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    StrField("data", "")]
1227c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def mysummary(self):
1228c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return self.sprintf("%name% (id: %id% seq: %seq%)")
1229c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def hashret(self):
1230c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return struct.pack("HH",self.id,self.seq)+self.payload.hashret()
1231c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1232c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1233c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6EchoReply(ICMPv6EchoRequest):
1234c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Echo Reply"
1235c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    type = 129
1236c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def answers(self, other):
1237c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        # We could match data content between request and reply.
1238c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return (isinstance(other, ICMPv6EchoRequest) and
1239c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                self.id == other.id and self.seq == other.seq and
1240c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                self.data == other.data)
1241c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1242c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1243c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil############ ICMPv6 Multicast Listener Discovery (RFC3810) ##################
1244c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1245c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# tous les messages MLD sont emis avec une adresse source lien-locale
1246c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# -> Y veiller dans le post_build si aucune n'est specifiee
1247c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# La valeur de Hop-Limit doit etre de 1
1248c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# "and an IPv6 Router Alert option in a Hop-by-Hop Options
1249c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# header. (The router alert option is necessary to cause routers to
1250c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# examine MLD messages sent to multicast addresses in which the router
1251c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# itself has no interest"
1252c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass _ICMPv6ML(_ICMPv6):
1253c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("type", 130, icmp6types),
1254c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("code", 0),
1255c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("cksum", None),
1256c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ShortField("mrd", 0),
1257c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ShortField("reserved", 0),
1258c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    IP6Field("mladdr",None)]
1259c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1260c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# general queries are sent to the link-scope all-nodes multicast
1261c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# address ff02::1, with a multicast address field of 0 and a MRD of
1262c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# [Query Response Interval]
1263c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# Default value for mladdr is set to 0 for a General Query, and
1264c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# overloaded by the user for a Multicast Address specific query
1265c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# TODO : See what we can do to automatically include a Router Alert
1266c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#        Option in a Destination Option Header.
1267c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6MLQuery(_ICMPv6ML): # RFC 2710
1268c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "MLD - Multicast Listener Query"
1269c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    type   = 130
1270c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    mrd    = 10000
1271c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    mladdr = "::" # 10s for mrd
1272c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    overload_fields = {IPv6: { "dst": "ff02::1", "hlim": 1 }}
1273c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def hashret(self):
1274c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if self.mladdr != "::":
1275c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return struct.pack("HH",self.mladdr)+self.payload.hashret()
1276c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        else:
1277c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return self.payload.hashret()
1278c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1279c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1280c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# TODO : See what we can do to automatically include a Router Alert
1281c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#        Option in a Destination Option Header.
1282c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6MLReport(_ICMPv6ML): # RFC 2710
1283c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "MLD - Multicast Listener Report"
1284c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    type = 131
1285c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    overload_fields = {IPv6: {"hlim": 1}}
1286c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    # implementer le hashret et le answers
1287c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1288c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# When a node ceases to listen to a multicast address on an interface,
1289c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# it SHOULD send a single Done message to the link-scope all-routers
1290c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# multicast address (FF02::2), carrying in its multicast address field
1291c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# the address to which it is ceasing to listen
1292c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# TODO : See what we can do to automatically include a Router Alert
1293c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#        Option in a Destination Option Header.
1294c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6MLDone(_ICMPv6ML): # RFC 2710
1295c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "MLD - Multicast Listener Done"
1296c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    type = 132
1297c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    overload_fields = {IPv6: { "dst": "ff02::2", "hlim": 1}}
1298c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1299c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1300c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil########## ICMPv6 MRD - Multicast Router Discovery (RFC 4286) ###############
1301c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1302c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# TODO:
1303c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# - 04/09/06 troglocan : find a way to automatically add a router alert
1304c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#            option for all MRD packets. This could be done in a specific
1305c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#            way when IPv6 is the under layer with some specific keyword
1306c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#            like 'exthdr'. This would allow to keep compatibility with
1307c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#            providing IPv6 fields to be overloaded in fields_desc.
1308c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#
1309c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#            At the moment, if user inserts an IPv6 Router alert option
1310c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#            none of the IPv6 default values of IPv6 layer will be set.
1311c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1312c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6MRD_Advertisement(_ICMPv6):
1313c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Multicast Router Discovery Advertisement"
1314c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ByteEnumField("type", 151, icmp6types),
1315c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   ByteField("advinter", 20),
1316c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   XShortField("cksum", None),
1317c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   ShortField("queryint", 0),
1318c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   ShortField("robustness", 0)]
1319c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    overload_fields = {IPv6: { "nh": 58, "hlim": 1, "dst": "ff02::2"}}
1320c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                       # IPv6 Router Alert requires manual inclusion
1321c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def extract_padding(self, s):
1322c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return s[:8], s[8:]
1323c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1324c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6MRD_Solicitation(_ICMPv6):
1325c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Multicast Router Discovery Solicitation"
1326c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ByteEnumField("type", 152, icmp6types),
1327c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   ByteField("res", 0),
1328c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   XShortField("cksum", None) ]
1329c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    overload_fields = {IPv6: { "nh": 58, "hlim": 1, "dst": "ff02::2"}}
1330c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                       # IPv6 Router Alert requires manual inclusion
1331c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def extract_padding(self, s):
1332c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return s[:4], s[4:]
1333c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1334c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6MRD_Termination(_ICMPv6):
1335c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Multicast Router Discovery Termination"
1336c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ByteEnumField("type", 153, icmp6types),
1337c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   ByteField("res", 0),
1338c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   XShortField("cksum", None) ]
1339c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    overload_fields = {IPv6: { "nh": 58, "hlim": 1, "dst": "ff02::6A"}}
1340c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                       # IPv6 Router Alert requires manual inclusion
1341c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def extract_padding(self, s):
1342c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return s[:4], s[4:]
1343c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1344c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1345c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil################### ICMPv6 Neighbor Discovery (RFC 2461) ####################
1346c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1347c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilicmp6ndopts = { 1: "Source Link-Layer Address",
1348c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                2: "Target Link-Layer Address",
1349c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                3: "Prefix Information",
1350c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                4: "Redirected Header",
1351c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                5: "MTU",
1352c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                6: "NBMA Shortcut Limit Option", # RFC2491
1353c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                7: "Advertisement Interval Option",
1354c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                8: "Home Agent Information Option",
1355c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                9: "Source Address List",
1356c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               10: "Target Address List",
1357c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               11: "CGA Option",            # RFC 3971
1358c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               12: "RSA Signature Option",  # RFC 3971
1359c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               13: "Timestamp Option",      # RFC 3971
1360c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               14: "Nonce option",          # RFC 3971
1361c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               15: "Trust Anchor Option",   # RFC 3971
1362c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               16: "Certificate Option",    # RFC 3971
1363c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               17: "IP Address Option",                             # RFC 4068
1364c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               18: "New Router Prefix Information Option",          # RFC 4068
1365c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               19: "Link-layer Address Option",                     # RFC 4068
1366c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               20: "Neighbor Advertisement Acknowledgement Option",
1367c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               21: "CARD Request Option", # RFC 4065/4066/4067
1368c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               22: "CARD Reply Option",   # RFC 4065/4066/4067
1369c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               23: "MAP Option",          # RFC 4140
1370c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               24: "Route Information Option",  # RFC 4191
1371c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               25: "Recusive DNS Server Option",
1372c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               26: "IPv6 Router Advertisement Flags Option"
1373c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                }
1374c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1375c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilicmp6ndoptscls = { 1: "ICMPv6NDOptSrcLLAddr",
1376c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   2: "ICMPv6NDOptDstLLAddr",
1377c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   3: "ICMPv6NDOptPrefixInfo",
1378c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   4: "ICMPv6NDOptRedirectedHdr",
1379c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   5: "ICMPv6NDOptMTU",
1380c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   6: "ICMPv6NDOptShortcutLimit",
1381c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   7: "ICMPv6NDOptAdvInterval",
1382c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   8: "ICMPv6NDOptHAInfo",
1383c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   9: "ICMPv6NDOptSrcAddrList",
1384c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                  10: "ICMPv6NDOptTgtAddrList",
1385c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                  #11: Do Me,
1386c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                  #12: Do Me,
1387c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                  #13: Do Me,
1388c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                  #14: Do Me,
1389c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                  #15: Do Me,
1390c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                  #16: Do Me,
1391c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                  17: "ICMPv6NDOptIPAddr",
1392c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                  18: "ICMPv6NDOptNewRtrPrefix",
1393c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                  19: "ICMPv6NDOptLLA",
1394c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                  #18: Do Me,
1395c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                  #19: Do Me,
1396c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                  #20: Do Me,
1397c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                  #21: Do Me,
1398c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                  #22: Do Me,
1399c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                  23: "ICMPv6NDOptMAP",
1400c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                  24: "ICMPv6NDOptRouteInfo",
1401c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                  25: "ICMPv6NDOptRDNSS",
1402c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                  26: "ICMPv6NDOptEFA"
1403c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                  }
1404c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1405c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass _ICMPv6NDGuessPayload:
1406c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "Dummy ND class that implements guess_payload_class()"
1407c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def guess_payload_class(self,p):
1408c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if len(p) > 1:
1409c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return get_cls(icmp6ndoptscls.get(ord(p[0]),"Raw"), "Raw") # s/Raw/ICMPv6NDOptUnknown/g ?
1410c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1411c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1412c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# Beginning of ICMPv6 Neighbor Discovery Options.
1413c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1414c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6NDOptUnknown(_ICMPv6NDGuessPayload, Packet):
1415c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Neighbor Discovery Option - Scapy Unimplemented"
1416c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteField("type",None),
1417c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    FieldLenField("len",None,length_of="data",fmt="B",
1418c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                  adjust = lambda pkt,x: x+2),
1419c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    StrLenField("data","",
1420c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                length_from = lambda pkt: pkt.len-2) ]
1421c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1422c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# NOTE: len includes type and len field. Expressed in unit of 8 bytes
1423c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# TODO: Revoir le coup du ETHER_ANY
1424c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6NDOptSrcLLAddr(_ICMPv6NDGuessPayload, Packet):
1425c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Neighbor Discovery Option - Source Link-Layer Address"
1426c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteField("type", 1),
1427c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("len", 1),
1428c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    MACField("lladdr", ETHER_ANY) ]
142977132687c31a9d3f30c3992c70eb24d1ac0948a7Phil    def mysummary(self):
1430c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return self.sprintf("%name% %lladdr%")
1431c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1432c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6NDOptDstLLAddr(ICMPv6NDOptSrcLLAddr):
1433c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Neighbor Discovery Option - Destination Link-Layer Address"
1434c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    type = 2
1435c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1436c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6NDOptPrefixInfo(_ICMPv6NDGuessPayload, Packet):
1437c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Neighbor Discovery Option - Prefix Information"
1438c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteField("type",3),
1439c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("len",4),
1440c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("prefixlen",None),
1441c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    BitField("L",1,1),
1442c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    BitField("A",1,1),
1443c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    BitField("R",0,1),
1444c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    BitField("res1",0,5),
1445c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XIntField("validlifetime",0xffffffffL),
1446c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XIntField("preferredlifetime",0xffffffffL),
1447c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XIntField("res2",0x00000000),
1448c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    IP6Field("prefix","::") ]
144977132687c31a9d3f30c3992c70eb24d1ac0948a7Phil    def mysummary(self):
1450c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return self.sprintf("%name% %prefix%")
1451c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1452c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# TODO: We should also limit the size of included packet to something
1453c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# like (initiallen - 40 - 2)
1454c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass TruncPktLenField(PacketLenField):
1455c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1456c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def __init__(self, name, default, cls, cur_shift, length_from=None, shift=0):
1457c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        PacketLenField.__init__(self, name, default, cls, length_from=length_from)
1458c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        self.cur_shift = cur_shift
1459c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1460c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def getfield(self, pkt, s):
1461c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        l = self.length_from(pkt)
1462c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        i = self.m2i(pkt, s[:l])
1463c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return s[l:],i
1464c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1465c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def m2i(self, pkt, m):
1466c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        s = None
1467c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        try: # It can happen we have sth shorter than 40 bytes
1468c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            s = self.cls(m)
1469c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        except:
1470c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return Raw(m)
1471c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return s
1472c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1473c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def i2m(self, pkt, x):
1474c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        s = str(x)
1475c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        l = len(s)
1476c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        r = (l + self.cur_shift) % 8
1477c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        l = l - r
1478c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return s[:l]
1479c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1480c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def i2len(self, pkt, i):
1481c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return len(self.i2m(pkt, i))
1482c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1483c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1484c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# Faire un post_build pour le recalcul de la taille (en multiple de 8 octets)
1485c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6NDOptRedirectedHdr(_ICMPv6NDGuessPayload, Packet):
1486c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Neighbor Discovery Option - Redirected Header"
1487c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteField("type",4),
1488c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    FieldLenField("len", None, length_of="pkt", fmt="B",
1489c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                  adjust = lambda pkt,x:(x+4)/8),
1490b5d49cd73a38b87d2a62a74452d3cb0932e6aa7bJochen Bartl                    StrFixedLenField("res", "\x00"*6, 6),
1491c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    TruncPktLenField("pkt", "", IPv6, 4,
1492c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                     length_from = lambda pkt: 8*pkt.len-4) ]
1493c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1494c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# See which value should be used for default MTU instead of 1280
1495c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6NDOptMTU(_ICMPv6NDGuessPayload, Packet):
1496c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Neighbor Discovery Option - MTU"
1497c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteField("type",5),
1498c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("len",1),
1499c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("res",0),
1500c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    IntField("mtu",1280)]
1501c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1502c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6NDOptShortcutLimit(_ICMPv6NDGuessPayload, Packet): # RFC 2491
1503c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Neighbor Discovery Option - NBMA Shortcut Limit"
1504c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteField("type", 6),
1505c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("len", 1),
1506c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("shortcutlim", 40), # XXX
1507c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("res1", 0),
1508c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    IntField("res2", 0) ]
1509c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1510c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6NDOptAdvInterval(_ICMPv6NDGuessPayload, Packet):
1511c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Neighbor Discovery - Interval Advertisement"
1512c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteField("type",7),
1513c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("len",1),
1514c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ShortField("res", 0),
1515c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    IntField("advint", 0) ]
151677132687c31a9d3f30c3992c70eb24d1ac0948a7Phil    def mysummary(self):
1517c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return self.sprintf("%name% %advint% milliseconds")
1518c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
151977132687c31a9d3f30c3992c70eb24d1ac0948a7Philclass ICMPv6NDOptHAInfo(_ICMPv6NDGuessPayload, Packet):
1520c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Neighbor Discovery - Home Agent Information"
1521c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteField("type",8),
1522c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("len",1),
1523c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ShortField("res", 0),
1524c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ShortField("pref", 0),
1525c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ShortField("lifetime", 1)]
152677132687c31a9d3f30c3992c70eb24d1ac0948a7Phil    def mysummary(self):
1527c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return self.sprintf("%name% %pref% %lifetime% seconds")
1528c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1529c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# type 9  : See ICMPv6NDOptSrcAddrList class below in IND (RFC 3122) support
1530c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1531c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# type 10 : See ICMPv6NDOptTgtAddrList class below in IND (RFC 3122) support
1532c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
153377132687c31a9d3f30c3992c70eb24d1ac0948a7Philclass ICMPv6NDOptIPAddr(_ICMPv6NDGuessPayload, Packet):  # RFC 4068
1534c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Neighbor Discovery - IP Address Option (FH for MIPv6)"
1535c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteField("type",17),
1536c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("len", 3),
1537c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteEnumField("optcode", 1, {1: "Old Care-Of Address",
1538c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                                 2: "New Care-Of Address",
1539c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                                 3: "NAR's IP address" }),
1540c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("plen", 64),
1541c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    IntField("res", 0),
1542c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    IP6Field("addr", "::") ]
1543c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1544c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6NDOptNewRtrPrefix(_ICMPv6NDGuessPayload, Packet): # RFC 4068
1545c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Neighbor Discovery - New Router Prefix Information Option (FH for MIPv6)"
1546c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteField("type",18),
1547c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("len", 3),
1548c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("optcode", 0),
1549c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("plen", 64),
1550c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    IntField("res", 0),
1551c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    IP6Field("prefix", "::") ]
1552c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1553c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil_rfc4068_lla_optcode = {0: "Wildcard requesting resolution for all nearby AP",
1554c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                        1: "LLA for the new AP",
1555c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                        2: "LLA of the MN",
1556c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                        3: "LLA of the NAR",
1557c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                        4: "LLA of the src of TrSolPr or PrRtAdv msg",
1558c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                        5: "AP identified by LLA belongs to current iface of router",
1559c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                        6: "No preifx info available for AP identified by the LLA",
1560c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                        7: "No fast handovers support for AP identified by the LLA" }
1561c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
156277132687c31a9d3f30c3992c70eb24d1ac0948a7Philclass ICMPv6NDOptLLA(_ICMPv6NDGuessPayload, Packet):     # RFC 4068
1563c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Neighbor Discovery - Link-Layer Address (LLA) Option (FH for MIPv6)"
1564c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteField("type", 19),
1565c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("len", 1),
1566c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteEnumField("optcode", 0, _rfc4068_lla_optcode),
1567c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    MACField("lla", ETHER_ANY) ] # We only support ethernet
1568c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
156977132687c31a9d3f30c3992c70eb24d1ac0948a7Philclass ICMPv6NDOptMAP(_ICMPv6NDGuessPayload, Packet):     # RFC 4140
1570c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Neighbor Discovery - MAP Option"
1571c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteField("type", 23),
1572c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("len", 3),
1573c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    BitField("dist", 1, 4),
1574c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    BitField("pref", 15, 4), # highest availability
1575c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    BitField("R", 1, 1),
1576c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    BitField("res", 0, 7),
1577c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    IntField("validlifetime", 0xffffffff),
1578c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    IP6Field("addr", "::") ]
1579c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1580c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1581c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass IP6PrefixField(IP6Field):
1582c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def __init__(self, name, default):
1583c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        IP6Field.__init__(self, name, default)
1584c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        self.length_from = lambda pkt: 8*(pkt.len - 1)
1585c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1586c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def addfield(self, pkt, s, val):
1587c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return s + self.i2m(pkt, val)
1588c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1589c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def getfield(self, pkt, s):
1590c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        l = self.length_from(pkt)
1591c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        p = s[:l]
1592c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if l < 16:
1593c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            p += '\x00'*(16-l)
1594c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return s[l:], self.m2i(pkt,p)
1595c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1596c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def i2len(self, pkt, x):
1597c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return len(self.i2m(pkt, x))
1598c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1599c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def i2m(self, pkt, x):
1600c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        l = pkt.len
1601c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1602c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if x is None:
1603c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            x = "::"
1604c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            if l is None:
1605c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                l = 1
1606c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        x = inet_pton(socket.AF_INET6, x)
1607c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1608c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if l is None:
1609c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return x
1610c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if l in [0, 1]:
1611c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return ""
1612c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if l in [2, 3]:
1613c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return x[:8*(l-1)]
1614c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1615c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return x + '\x00'*8*(l-3)
1616c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1617c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6NDOptRouteInfo(_ICMPv6NDGuessPayload, Packet): # RFC 4191
1618c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Neighbor Discovery Option - Route Information Option"
1619c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteField("type",24),
1620c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    FieldLenField("len", None, length_of="prefix", fmt="B",
1621c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                  adjust = lambda pkt,x: x/8 + 1),
1622c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("plen", None),
1623c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    BitField("res1",0,3),
1624c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    BitField("prf",0,2),
1625c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    BitField("res2",0,3),
1626c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    IntField("rtlifetime", 0xffffffff),
1627c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    IP6PrefixField("prefix", None) ]
1628c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1629c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6NDOptRDNSS(_ICMPv6NDGuessPayload, Packet): # RFC 5006
1630c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Neighbor Discovery Option - Recursive DNS Server Option"
1631c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteField("type", 25),
1632c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    FieldLenField("len", None, count_of="dns", fmt="B",
1633c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                  adjust = lambda pkt,x: 2*x+1),
1634c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ShortField("res", None),
1635c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    IntField("lifetime", 0xffffffff),
1636c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    IP6ListField("dns", [],
1637c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                 length_from = lambda pkt: 8*(pkt.len-1)) ]
1638c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1639c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6NDOptEFA(_ICMPv6NDGuessPayload, Packet): # RFC 5175 (prev. 5075)
1640c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Neighbor Discovery Option - Expanded Flags Option"
1641c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteField("type", 26),
1642c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("len", 1),
1643c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    BitField("res", 0, 48) ]
1644c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1645c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# End of ICMPv6 Neighbor Discovery Options.
1646c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1647c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6ND_RS(_ICMPv6NDGuessPayload, _ICMPv6):
1648c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Neighbor Discovery - Router Solicitation"
1649c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("type", 133, icmp6types),
1650c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("code",0),
1651c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("cksum", None),
1652c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    IntField("res",0) ]
1653c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    overload_fields = {IPv6: { "nh": 58, "dst": "ff02::2", "hlim": 255 }}
1654c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1655c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6ND_RA(_ICMPv6NDGuessPayload, _ICMPv6):
1656c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Neighbor Discovery - Router Advertisement"
1657c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("type", 134, icmp6types),
1658c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("code",0),
1659c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("cksum", None),
1660c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("chlim",0),
1661c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    BitField("M",0,1),
1662c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    BitField("O",0,1),
1663c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    BitField("H",0,1),
1664c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    BitEnumField("prf",1,2, { 0: "Medium (default)",
1665c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                              1: "High",
1666c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                              2: "Reserved",
1667c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                              3: "Low" } ), # RFC 4191
1668c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    BitField("P",0,1),
1669c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    BitField("res",0,2),
1670c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ShortField("routerlifetime",1800),
1671c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    IntField("reachabletime",0),
1672c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    IntField("retranstimer",0) ]
1673c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    overload_fields = {IPv6: { "nh": 58, "dst": "ff02::1", "hlim": 255 }}
1674c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1675c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def answers(self, other):
1676c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return isinstance(other, ICMPv6ND_RS)
1677c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1678c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6ND_NS(_ICMPv6NDGuessPayload, _ICMPv6, Packet):
1679c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Neighbor Discovery - Neighbor Solicitation"
1680c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("type",135, icmp6types),
1681c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("code",0),
1682c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("cksum", None),
1683c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    BitField("R",0,1),
1684c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    BitField("S",0,1),
1685c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    BitField("O",0,1),
1686c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XBitField("res",0,29),
1687c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    IP6Field("tgt","::") ]
1688c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    overload_fields = {IPv6: { "nh": 58, "dst": "ff02::1", "hlim": 255 }}
1689c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1690c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def mysummary(self):
1691c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return self.sprintf("%name% (tgt: %tgt%)")
1692c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1693c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def hashret(self):
1694c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return self.tgt+self.payload.hashret()
1695c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1696c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6ND_NA(ICMPv6ND_NS):
1697c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Neighbor Discovery - Neighbor Advertisement"
1698c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    type = 136
1699c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    R    = 1
1700c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    O    = 1
1701c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1702c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def answers(self, other):
170377132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        return isinstance(other, ICMPv6ND_NS) and self.tgt == other.tgt
1704c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1705c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# associated possible options : target link-layer option, Redirected header
1706c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6ND_Redirect(_ICMPv6NDGuessPayload, _ICMPv6, Packet):
1707c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Neighbor Discovery - Redirect"
1708c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("type",137, icmp6types),
1709c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("code",0),
1710c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("cksum", None),
1711c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XIntField("res",0),
1712c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    IP6Field("tgt","::"),
1713c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    IP6Field("dst","::") ]
1714c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    overload_fields = {IPv6: { "nh": 58, "dst": "ff02::1", "hlim": 255 }}
1715c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1716c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1717c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1718c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil################ ICMPv6 Inverse Neighbor Discovery (RFC 3122) ###############
1719c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1720c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6NDOptSrcAddrList(_ICMPv6NDGuessPayload, Packet):
1721c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Inverse Neighbor Discovery Option - Source Address List"
1722c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteField("type",9),
1723c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    FieldLenField("len", None, count_of="addrlist", fmt="B",
1724c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                  adjust = lambda pkt,x: 2*x+1),
1725c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    StrFixedLenField("res", "\x00"*6, 6),
1726c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    IP6ListField("addrlist", [],
1727c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                length_from = lambda pkt: 8*(pkt.len-1)) ]
1728c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1729c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6NDOptTgtAddrList(ICMPv6NDOptSrcAddrList):
1730c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Inverse Neighbor Discovery Option - Target Address List"
1731c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    type = 10
1732c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1733c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1734c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# RFC3122
1735c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# Options requises : source lladdr et target lladdr
1736c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# Autres options valides : source address list, MTU
1737c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# - Comme precise dans le document, il serait bien de prendre l'adresse L2
1738c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#   demandee dans l'option requise target lladdr et l'utiliser au niveau
1739c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#   de l'adresse destination ethernet si aucune adresse n'est precisee
1740c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# - ca semble pas forcement pratique si l'utilisateur doit preciser toutes
1741c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#   les options.
1742c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# Ether() must use the target lladdr as destination
1743c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6ND_INDSol(_ICMPv6NDGuessPayload, _ICMPv6):
1744c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Inverse Neighbor Discovery Solicitation"
1745c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("type",141, icmp6types),
1746c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("code",0),
1747c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("cksum",None),
1748c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XIntField("reserved",0) ]
1749c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    overload_fields = {IPv6: { "nh": 58, "dst": "ff02::1", "hlim": 255 }}
1750c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1751c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# Options requises :  target lladdr, target address list
1752c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# Autres options valides : MTU
1753c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6ND_INDAdv(_ICMPv6NDGuessPayload, _ICMPv6):
1754c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Inverse Neighbor Discovery Advertisement"
1755c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("type",142, icmp6types),
1756c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("code",0),
1757c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("cksum",None),
1758c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XIntField("reserved",0) ]
1759c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    overload_fields = {IPv6: { "nh": 58, "dst": "ff02::1", "hlim": 255 }}
1760c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1761c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1762c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil###############################################################################
1763c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# ICMPv6 Node Information Queries (RFC 4620)
1764c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil###############################################################################
1765c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1766c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# [ ] Add automatic destination address computation using computeNIGroupAddr
1767c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#     in IPv6 class (Scapy6 modification when integrated) if :
1768c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#     - it is not provided
1769c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#     - upper layer is ICMPv6NIQueryName() with a valid value
1770c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# [ ] Try to be liberal in what we accept as internal values for _explicit_
1771c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#     DNS elements provided by users. Any string should be considered
1772c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#     valid and kept like it has been provided. At the moment, i2repr() will
1773c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#     crash on many inputs
1774c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# [ ] Do the documentation
1775c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# [ ] Add regression tests
1776c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# [ ] Perform test against real machines (NOOP reply is proof of implementation).
1777c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# [ ] Check if there are differences between different stacks. Among *BSD,
1778c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#     with others.
1779c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# [ ] Deal with flags in a consistent way.
1780c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# [ ] Implement compression in names2dnsrepr() and decompresiion in
1781c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#     dnsrepr2names(). Should be deactivable.
1782c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1783c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilicmp6_niqtypes = { 0: "NOOP",
1784c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                  2: "Node Name",
1785c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                  3: "IPv6 Address",
1786c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                  4: "IPv4 Address" }
1787c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1788c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1789c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass _ICMPv6NIHashret:
1790c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def hashret(self):
1791c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return self.nonce
1792c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1793c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass _ICMPv6NIAnswers:
1794c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def answers(self, other):
1795c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return self.nonce == other.nonce
1796c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1797c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# Buggy; always returns the same value during a session
1798c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass NonceField(StrFixedLenField):
1799c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def __init__(self, name, default=None):
1800c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        StrFixedLenField.__init__(self, name, default, 8)
1801c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if default is None:
1802c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            self.default = self.randval()
1803c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1804c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# Compute the NI group Address. Can take a FQDN as input parameter
1805c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhildef computeNIGroupAddr(name):
1806c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    import md5
1807c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = name.lower().split(".")[0]
1808c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    record = chr(len(name))+name
1809c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    h = md5.new(record)
1810c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    h = h.digest()
1811c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    addr = "ff02::2:%2x%2x:%2x%2x" % struct.unpack("BBBB", h[:4])
1812c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    return addr
1813c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1814c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1815c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# Here is the deal. First, that protocol is a piece of shit. Then, we
1816c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# provide 4 classes for the different kinds of Requests (one for every
1817c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# valid qtype: NOOP, Node Name, IPv6@, IPv4@). They all share the same
1818c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# data field class that is made to be smart by guessing the specifc
1819c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# type of value provided :
1820c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#
1821c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# - IPv6 if acceptable for inet_pton(AF_INET6, ): code is set to 0,
1822c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#   if not overriden by user
1823c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# - IPv4 if acceptable for inet_pton(AF_INET,  ): code is set to 2,
1824c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#   if not overriden
1825c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# - Name in the other cases: code is set to 0, if not overriden by user
1826c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#
1827c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# Internal storage, is not only the value, but the a pair providing
1828c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# the type and the value (1 is IPv6@, 1 is Name or string, 2 is IPv4@)
1829c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#
1830c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# Note : I merged getfield() and m2i(). m2i() should not be called
1831c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#        directly anyway. Same remark for addfield() and i2m()
1832c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#
1833c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# -- arno
1834c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1835c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# "The type of information present in the Data field of a query is
1836c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#  declared by the ICMP Code, whereas the type of information in a
1837c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#  Reply is determined by the Qtype"
1838c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1839c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhildef names2dnsrepr(x):
1840c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    """
1841c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    Take as input a list of DNS names or a single DNS name
1842c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    and encode it in DNS format (with possible compression)
1843c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    If a string that is already a DNS name in DNS format
1844c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    is passed, it is returned unmodified. Result is a string.
1845c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    !!!  At the moment, compression is not implemented  !!!
1846c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    """
1847c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1848c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    if type(x) is str:
1849c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if x and x[-1] == '\x00': # stupid heuristic
1850c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return x
1851c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        x = [x]
1852c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1853c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    res = []
1854c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    for n in x:
1855c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        termin = "\x00"
1856c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if n.count('.') == 0: # single-component gets one more
1857c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            termin += '\x00'
1858c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        n = "".join(map(lambda y: chr(len(y))+y, n.split("."))) + termin
1859c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        res.append(n)
1860c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    return "".join(res)
1861c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1862c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1863c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhildef dnsrepr2names(x):
1864c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    """
1865c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    Take as input a DNS encoded string (possibly compressed)
1866c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    and returns a list of DNS names contained in it.
1867c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    If provided string is already in printable format
1868c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    (does not end with a null character, a one element list
1869c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    is returned). Result is a list.
1870c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    """
1871c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    res = []
1872c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    cur = ""
1873c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    while x:
1874c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        l = ord(x[0])
1875c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        x = x[1:]
1876c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if l == 0:
1877c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            if cur and cur[-1] == '.':
1878c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                cur = cur[:-1]
1879c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            res.append(cur)
1880c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            cur = ""
1881c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            if x and ord(x[0]) == 0: # single component
1882c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                x = x[1:]
1883c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            continue
1884c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if l & 0xc0: # XXX TODO : work on that -- arno
1885c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            raise Exception("DNS message can't be compressed at this point!")
1886c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        else:
1887c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            cur += x[:l]+"."
1888c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            x = x[l:]
1889c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    return res
1890c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1891c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1892c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass NIQueryDataField(StrField):
1893c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def __init__(self, name, default):
1894c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        StrField.__init__(self, name, default)
1895c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1896c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def i2h(self, pkt, x):
1897c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if x is None:
1898c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return x
1899c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        t,val = x
1900c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if t == 1:
1901c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            val = dnsrepr2names(val)[0]
1902c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return val
1903c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1904c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def h2i(self, pkt, x):
1905c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if x is tuple and type(x[0]) is int:
1906c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return x
1907c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1908c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        val = None
1909c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        try: # Try IPv6
1910c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            inet_pton(socket.AF_INET6, x)
1911c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            val = (0, x)
1912c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        except:
1913c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            try: # Try IPv4
1914c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                inet_pton(socket.AF_INET, x)
1915c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                val = (2, x)
1916c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            except: # Try DNS
1917c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                if x is None:
1918c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    x = ""
1919c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                x = names2dnsrepr(x)
1920c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                val = (1, x)
1921c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return val
1922c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1923c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def i2repr(self, pkt, x):
1924c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        t,val = x
1925c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if t == 1: # DNS Name
1926c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            # we don't use dnsrepr2names() to deal with
1927c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            # possible weird data extracted info
1928c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            res = []
1929c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            weird = None
1930c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            while val:
1931c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                l = ord(val[0])
1932c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                val = val[1:]
1933c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                if l == 0:
1934c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    if (len(res) > 1 and val): # fqdn with data behind
1935c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                        weird = val
1936c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    elif len(val) > 1: # single label with data behind
1937c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                        weird = val[1:]
1938c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    break
1939c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                res.append(val[:l]+".")
1940c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                val = val[l:]
1941c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            tmp = "".join(res)
1942c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            if tmp and tmp[-1] == '.':
1943c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                tmp = tmp[:-1]
1944c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return tmp
1945c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return repr(val)
1946c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1947c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def getfield(self, pkt, s):
1948c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        qtype = getattr(pkt, "qtype")
1949c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if qtype == 0: # NOOP
1950c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return s, (0, "")
1951c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        else:
1952c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            code = getattr(pkt, "code")
1953c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            if code == 0:   # IPv6 Addr
1954c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                return s[16:], (0, inet_ntop(socket.AF_INET6, s[:16]))
1955c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            elif code == 2: # IPv4 Addr
1956c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                return s[4:], (2, inet_ntop(socket.AF_INET, s[:4]))
1957c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            else:           # Name or Unknown
1958c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                return "", (1, s)
1959c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1960c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def addfield(self, pkt, s, val):
1961c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if ((type(val) is tuple and val[1] is None) or
1962c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            val is None):
1963c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            val = (1, "")
1964c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        t = val[0]
1965c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if t == 1:
1966c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return s + val[1]
1967c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        elif t == 0:
1968c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return s + inet_pton(socket.AF_INET6, val[1])
1969c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        else:
1970c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return s + inet_pton(socket.AF_INET, val[1])
1971c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1972c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass NIQueryCodeField(ByteEnumField):
1973c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def i2m(self, pkt, x):
1974c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if x is None:
1975c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            d = pkt.getfieldval("data")
1976c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            if d is None:
1977c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                return 1
1978c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            elif d[0] == 0: # IPv6 address
1979c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                return 0
1980c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            elif d[0] == 1: # Name
1981c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                return 1
1982c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            elif d[0] == 2: # IPv4 address
1983c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                return 2
1984c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            else:
1985c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                return 1
1986c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return x
1987c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1988c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1989c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil_niquery_code = {0: "IPv6 Query", 1: "Name Query", 2: "IPv4 Query"}
1990c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1991c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#_niquery_flags = {  2: "All unicast addresses", 4: "IPv4 addresses",
199277132687c31a9d3f30c3992c70eb24d1ac0948a7Phil#                    8: "Link-local addresses", 16: "Site-local addresses",
1993c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#                   32: "Global addresses" }
1994c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
1995c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# "This NI type has no defined flags and never has a Data Field". Used
1996c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# to know if the destination is up and implements NI protocol.
1997c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6NIQueryNOOP(_ICMPv6NIHashret, _ICMPv6):
1998c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Node Information Query - NOOP Query"
1999c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("type", 139, icmp6types),
2000c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    NIQueryCodeField("code", None, _niquery_code),
2001c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("cksum", None),
2002c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ShortEnumField("qtype", 0, icmp6_niqtypes),
200377132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                    BitField("unused", 0, 10),
2004c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    FlagsField("flags", 0, 6, "TACLSG"),
200577132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                    NonceField("nonce", None),
2006c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    NIQueryDataField("data", None) ]
2007c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2008c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6NIQueryName(ICMPv6NIQueryNOOP):
2009c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Node Information Query - IPv6 Name Query"
2010c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    qtype = 2
2011c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2012c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# We ask for the IPv6 address of the peer
2013c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6NIQueryIPv6(ICMPv6NIQueryNOOP):
2014c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Node Information Query - IPv6 Address Query"
2015c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    qtype = 3
2016c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    flags = 0x3E
2017c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2018c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6NIQueryIPv4(ICMPv6NIQueryNOOP):
2019c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Node Information Query - IPv4 Address Query"
2020c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    qtype = 4
2021c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2022c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil_nireply_code = { 0: "Successful Reply",
2023c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                  1: "Response Refusal",
2024c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                  3: "Unknown query type" }
2025c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2026c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil_nireply_flags = {  1: "Reply set incomplete",
2027c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    2: "All unicast addresses",
2028c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    4: "IPv4 addresses",
2029c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    8: "Link-local addresses",
2030c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   16: "Site-local addresses",
2031c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                   32: "Global addresses" }
2032c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2033c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# Internal repr is one of those :
2034c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# (0, "some string") : unknow qtype value are mapped to that one
2035c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# (3, [ (ttl, ip6), ... ])
2036c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# (4, [ (ttl, ip4), ... ])
2037c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# (2, [ttl, dns_names]) : dns_names is one string that contains
2038c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#     all the DNS names. Internally it is kept ready to be sent
2039c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#     (undissected). i2repr() decode it for user. This is to
2040c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#     make build after dissection bijective.
2041c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#
2042c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# I also merged getfield() and m2i(), and addfield() and i2m().
2043c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass NIReplyDataField(StrField):
2044c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2045c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def i2h(self, pkt, x):
2046c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if x is None:
2047c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return x
2048c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        t,val = x
2049c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if t == 2:
2050c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            ttl, dnsnames = val
2051c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            val = [ttl] + dnsrepr2names(dnsnames)
2052c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return val
2053c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2054c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def h2i(self, pkt, x):
2055c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        qtype = 0 # We will decode it as string if not
2056c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                  # overridden through 'qtype' in pkt
2057c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2058c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        # No user hint, let's use 'qtype' value for that purpose
2059c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if type(x) is not tuple:
2060c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            if pkt is not None:
2061c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                qtype = getattr(pkt, "qtype")
2062c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        else:
2063c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            qtype = x[0]
2064c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            x = x[1]
2065c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2066c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        # From that point on, x is the value (second element of the tuple)
2067c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2068c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if qtype == 2: # DNS name
2069c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            if type(x) is str: # listify the string
2070c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                x = [x]
2071c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            if type(x) is list and x and type(x[0]) is not int: # ttl was omitted : use 0
2072c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                x = [0] + x
2073c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            ttl = x[0]
2074c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            names = x[1:]
2075c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return (2, [ttl, names2dnsrepr(names)])
2076c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2077c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        elif qtype in [3, 4]: # IPv4 or IPv6 addr
2078c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            if type(x) is str:
2079c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                x = [x] # User directly provided an IP, instead of list
2080c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2081c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            # List elements are not tuples, user probably
2082c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            # omitted ttl value : we will use 0 instead
2083c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            def addttl(x):
2084c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                if type(x) is str:
2085c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    return (0, x)
2086c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                return x
2087c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2088c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return (qtype, map(addttl, x))
2089c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2090c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return (qtype, x)
2091c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2092c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2093c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def addfield(self, pkt, s, val):
2094c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        t,tmp = val
2095c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if tmp is None:
2096c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            tmp = ""
2097c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if t == 2:
2098c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            ttl,dnsstr = tmp
2099c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return s+ struct.pack("!I", ttl) + dnsstr
2100c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        elif t == 3:
2101c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return s + "".join(map(lambda (x,y): struct.pack("!I", x)+inet_pton(socket.AF_INET6, y), tmp))
2102c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        elif t == 4:
2103c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return s + "".join(map(lambda (x,y): struct.pack("!I", x)+inet_pton(socket.AF_INET, y), tmp))
2104c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        else:
2105c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return s + tmp
2106c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2107c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def getfield(self, pkt, s):
2108c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        code = getattr(pkt, "code")
2109c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if code != 0:
2110c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return s, (0, "")
2111c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2112c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        qtype = getattr(pkt, "qtype")
2113c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if qtype == 0: # NOOP
2114c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return s, (0, "")
2115c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2116c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        elif qtype == 2:
2117c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            if len(s) < 4:
2118c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                return s, (0, "")
2119c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            ttl = struct.unpack("!I", s[:4])[0]
2120c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return "", (2, [ttl, s[4:]])
2121c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2122c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        elif qtype == 3: # IPv6 addresses with TTLs
2123c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            # XXX TODO : get the real length
2124c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            res = []
2125c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            while len(s) >= 20: # 4 + 16
2126c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                ttl = struct.unpack("!I", s[:4])[0]
2127c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                ip  = inet_ntop(socket.AF_INET6, s[4:20])
2128c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                res.append((ttl, ip))
2129c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                s = s[20:]
2130c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return s, (3, res)
2131c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2132c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        elif qtype == 4: # IPv4 addresses with TTLs
2133c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            # XXX TODO : get the real length
2134c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            res = []
2135c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            while len(s) >= 8: # 4 + 4
2136c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                ttl = struct.unpack("!I", s[:4])[0]
2137c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                ip  = inet_ntop(socket.AF_INET, s[4:8])
2138c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                res.append((ttl, ip))
2139c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                s = s[8:]
2140c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return s, (4, res)
2141c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        else:
2142c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            # XXX TODO : implement me and deal with real length
2143c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return "", (0, s)
2144c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2145c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def i2repr(self, pkt, x):
2146c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if x is None:
2147c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return "[]"
2148c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2149c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if type(x) is tuple and len(x) == 2:
2150c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            t, val = x
2151c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            if t == 2: # DNS names
2152c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                ttl,l = val
2153c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                l = dnsrepr2names(l)
2154c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                return "ttl:%d %s" % (ttl, ", ".join(l))
2155c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            elif t == 3 or t == 4:
2156c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                return "[ %s ]" % (", ".join(map(lambda (x,y): "(%d, %s)" % (x, y), val)))
2157c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return repr(val)
2158c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return repr(x) # XXX should not happen
2159c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2160c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# By default, sent responses have code set to 0 (successful)
2161c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6NIReplyNOOP(_ICMPv6NIAnswers, _ICMPv6NIHashret, _ICMPv6):
2162c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Node Information Reply - NOOP Reply"
2163c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("type", 140, icmp6types),
2164c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteEnumField("code", 0, _nireply_code),
2165c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("cksum", None),
2166c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ShortEnumField("qtype", 0, icmp6_niqtypes),
216777132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                    BitField("unused", 0, 10),
2168c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    FlagsField("flags", 0, 6, "TACLSG"),
216977132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                    NonceField("nonce", None),
2170c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    NIReplyDataField("data", None)]
2171c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2172c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6NIReplyName(ICMPv6NIReplyNOOP):
2173c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Node Information Reply - Node Names"
2174c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    qtype = 2
2175c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2176c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6NIReplyIPv6(ICMPv6NIReplyNOOP):
2177c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Node Information Reply - IPv6 addresses"
2178c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    qtype = 3
2179c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2180c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6NIReplyIPv4(ICMPv6NIReplyNOOP):
2181c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Node Information Reply - IPv4 addresses"
2182c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    qtype = 4
2183c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2184c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6NIReplyRefuse(ICMPv6NIReplyNOOP):
2185c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Node Information Reply - Responder refuses to supply answer"
2186c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    code = 1
2187c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2188c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6NIReplyUnknown(ICMPv6NIReplyNOOP):
2189c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "ICMPv6 Node Information Reply - Qtype unknown to the responder"
2190c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    code = 2
2191c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2192c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2193c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhildef _niquery_guesser(p):
2194c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    cls = Raw
2195c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    type = ord(p[0])
2196c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    if type == 139: # Node Info Query specific stuff
2197c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if len(p) > 6:
2198c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            qtype, = struct.unpack("!H", p[4:6])
2199c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            cls = { 0: ICMPv6NIQueryNOOP,
2200c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    2: ICMPv6NIQueryName,
2201c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    3: ICMPv6NIQueryIPv6,
2202c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    4: ICMPv6NIQueryIPv4 }.get(qtype, Raw)
2203c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    elif type == 140: # Node Info Reply specific stuff
2204c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        code = ord(p[1])
2205c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if code == 0:
2206c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            if len(p) > 6:
2207c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                qtype, = struct.unpack("!H", p[4:6])
2208c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                cls = { 2: ICMPv6NIReplyName,
2209c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                        3: ICMPv6NIReplyIPv6,
2210c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                        4: ICMPv6NIReplyIPv4 }.get(qtype, ICMPv6NIReplyNOOP)
2211c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        elif code == 1:
2212c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            cls = ICMPv6NIReplyRefuse
2213c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        elif code == 2:
2214c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            cls = ICMPv6NIReplyUnknown
2215c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    return cls
2216c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2217c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2218c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
2219c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
2220c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil###             Mobile IPv6 (RFC 3775) and Nemo (RFC 3963)                ###
2221c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
2222c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
2223c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2224c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# Mobile IPv6 ICMPv6 related classes
2225c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2226c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6HAADRequest(_ICMPv6):
2227c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = 'ICMPv6 Home Agent Address Discovery Request'
2228c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("type", 144, icmp6types),
2229c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("code", 0),
2230c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("cksum", None),
2231c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("id", None),
2232c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    BitEnumField("R", 1, 1, {1: 'MR'}),
2233c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XBitField("res", 0, 15) ]
2234c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def hashret(self):
2235c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return struct.pack("!H",self.id)+self.payload.hashret()
2236c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2237c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6HAADReply(_ICMPv6):
2238c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = 'ICMPv6 Home Agent Address Discovery Reply'
2239c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("type", 145, icmp6types),
2240c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("code", 0),
2241c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("cksum", None),
2242c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("id", None),
2243c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    BitEnumField("R", 1, 1, {1: 'MR'}),
2244c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XBitField("res", 0, 15),
2245c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    IP6ListField('addresses', None) ]
2246c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def hashret(self):
2247c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return struct.pack("!H",self.id)+self.payload.hashret()
2248c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2249c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def answers(self, other):
2250c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if not isinstance(other, ICMPv6HAADRequest):
2251c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return 0
2252c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return self.id == other.id
2253c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2254c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6MPSol(_ICMPv6):
2255c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = 'ICMPv6 Mobile Prefix Solicitation'
2256c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("type", 146, icmp6types),
2257c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("code", 0),
2258c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("cksum", None),
2259c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("id", None),
2260c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("res", 0) ]
2261c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def _hashret(self):
2262c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return struct.pack("!H",self.id)
2263c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2264c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass ICMPv6MPAdv(_ICMPv6NDGuessPayload, _ICMPv6):
2265c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = 'ICMPv6 Mobile Prefix Advertisement'
2266c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("type", 147, icmp6types),
2267c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("code", 0),
2268c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("cksum", None),
2269c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("id", None),
2270c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    BitEnumField("flags", 2, 2, {2: 'M', 1:'O'}),
2271c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XBitField("res", 0, 14) ]
2272c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def hashret(self):
2273c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return struct.pack("!H",self.id)
2274c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2275c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def answers(self, other):
2276c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return isinstance(other, ICMPv6MPSol)
2277c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2278c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# Mobile IPv6 Options classes
2279c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2280c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2281c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil_mobopttypes = { 2: "Binding Refresh Advice",
2282c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                 3: "Alternate Care-of Address",
2283c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                 4: "Nonce Indices",
2284c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                 5: "Binding Authorization Data",
2285c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                 6: "Mobile Network Prefix (RFC3963)",
2286c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                 7: "Link-Layer Address (RFC4068)",
2287c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                 8: "Mobile Node Identifier (RFC4283)",
2288c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                 9: "Mobility Message Authentication (RFC4285)",
2289c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                 10: "Replay Protection (RFC4285)",
2290c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                 11: "CGA Parameters Request (RFC4866)",
2291c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                 12: "CGA Parameters (RFC4866)",
2292c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                 13: "Signature (RFC4866)",
2293c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                 14: "Home Keygen Token (RFC4866)",
2294c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                 15: "Care-of Test Init (RFC4866)",
2295c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                 16: "Care-of Test (RFC4866)" }
2296c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2297c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2298c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass _MIP6OptAlign:
2299c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    """ Mobile IPv6 options have alignment requirements of the form x*n+y.
2300c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    This class is inherited by all MIPv6 options to help in computing the
2301c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    required Padding for that option, i.e. the need for a Pad1 or PadN
2302c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    option before it. They only need to provide x and y as class
2303c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    parameters. (x=0 and y=0 are used when no alignment is required)"""
2304c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def alignment_delta(self, curpos):
2305c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil      x = self.x ; y = self.y
2306c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil      if x == 0 and y ==0:
2307c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil          return 0
2308c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil      delta = x*((curpos - y + x - 1)/x) + y - curpos
2309c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil      return delta
2310c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2311c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2312c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass MIP6OptBRAdvice(_MIP6OptAlign, Packet):
2313c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = 'Mobile IPv6 Option - Binding Refresh Advice'
2314c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField('otype', 2, _mobopttypes),
2315c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField('olen', 2),
2316c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ShortField('rinter', 0) ]
2317c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    x = 2 ; y = 0# alignment requirement: 2n
2318c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2319c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass MIP6OptAltCoA(_MIP6OptAlign, Packet):
2320c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = 'MIPv6 Option - Alternate Care-of Address'
2321c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField('otype', 3, _mobopttypes),
2322c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField('olen', 16),
2323c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    IP6Field("acoa", "::") ]
2324c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    x = 8 ; y = 6 # alignment requirement: 8n+6
2325c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
232677132687c31a9d3f30c3992c70eb24d1ac0948a7Philclass MIP6OptNonceIndices(_MIP6OptAlign, Packet):
2327c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = 'MIPv6 Option - Nonce Indices'
2328c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField('otype', 4, _mobopttypes),
2329c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField('olen', 16),
2330c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ShortField('hni', 0),
2331c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ShortField('coni', 0) ]
2332c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    x = 2 ; y = 0 # alignment requirement: 2n
2333c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
233477132687c31a9d3f30c3992c70eb24d1ac0948a7Philclass MIP6OptBindingAuthData(_MIP6OptAlign, Packet):
2335c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = 'MIPv6 Option - Binding Authorization Data'
2336c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField('otype', 5, _mobopttypes),
2337c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField('olen', 16),
2338c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    BitField('authenticator', 0, 96) ]
2339c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    x = 8 ; y = 2 # alignment requirement: 8n+2
2340c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2341c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass MIP6OptMobNetPrefix(_MIP6OptAlign, Packet): # NEMO - RFC 3963
2342c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = 'NEMO Option - Mobile Network Prefix'
2343c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("otype", 6, _mobopttypes),
23445bbe280843fec8d5955914c78f52cb9cef7d61a4Phil                    ByteField("olen", 18),
2345c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("reserved", 0),
2346c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("plen", 64),
2347c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    IP6Field("prefix", "::") ]
2348c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    x = 8 ; y = 4 # alignment requirement: 8n+4
2349c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2350c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass MIP6OptLLAddr(_MIP6OptAlign, Packet): # Sect 6.4.4 of RFC 4068
2351c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "MIPv6 Option - Link-Layer Address (MH-LLA)"
2352c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("otype", 7, _mobopttypes),
2353c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("olen", 7),
2354c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteEnumField("ocode", 2, _rfc4068_lla_optcode),
2355c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("pad", 0),
2356c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    MACField("lla", ETHER_ANY) ] # Only support ethernet
2357c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    x = 0 ; y = 0 # alignment requirement: none
2358c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2359c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass MIP6OptMNID(_MIP6OptAlign, Packet): # RFC 4283
2360c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "MIPv6 Option - Mobile Node Identifier"
2361c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("otype", 8, _mobopttypes),
2362c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    FieldLenField("olen", None, length_of="id", fmt="B",
2363c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                  adjust = lambda pkt,x: x+1),
2364c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteEnumField("subtype", 1, {1: "NAI"}),
2365c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    StrLenField("id", "",
2366c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                length_from = lambda pkt: pkt.olen-1) ]
2367c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    x = 0 ; y = 0 # alignment requirement: none
2368c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2369c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# We only support decoding and basic build. Automatic HMAC computation is
2370c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# too much work for our current needs. It is left to the user (I mean ...
2371c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# you). --arno
2372c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass MIP6OptMsgAuth(_MIP6OptAlign, Packet): # RFC 4285 (Sect. 5)
2373c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "MIPv6 Option - Mobility Message Authentication"
2374c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("otype", 9, _mobopttypes),
2375c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    FieldLenField("olen", None, length_of="authdata", fmt="B",
2376c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                  adjust = lambda pkt,x: x+5),
2377c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteEnumField("subtype", 1, {1: "MN-HA authentication mobility option",
2378c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                                 2: "MN-AAA authentication mobility option"}),
2379c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    IntField("mspi", None),
2380c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    StrLenField("authdata", "A"*12,
2381c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                length_from = lambda pkt: pkt.olen-5) ]
2382c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    x = 4 ; y = 1 # alignment requirement: 4n+1
2383c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2384c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# Extracted from RFC 1305 (NTP) :
2385c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# NTP timestamps are represented as a 64-bit unsigned fixed-point number,
2386c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# in seconds relative to 0h on 1 January 1900. The integer part is in the
2387c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# first 32 bits and the fraction part in the last 32 bits.
2388c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass NTPTimestampField(LongField):
2389c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    epoch = (1900, 1, 1, 0, 0, 0, 5, 1, 0)
2390c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def i2repr(self, pkt, x):
2391c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if x < ((50*31536000)<<32):
2392c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return "Some date a few decades ago (%d)" % x
2393c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2394c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        # delta from epoch (= (1900, 1, 1, 0, 0, 0, 5, 1, 0)) to
2395c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        # January 1st 1970 :
2396c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        delta = -2209075761
2397c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        i = int(x >> 32)
2398c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        j = float(x & 0xffffffff) * 2.0**-32
2399c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        res = i + j + delta
2400c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        from time import strftime
2401c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        t = time.strftime("%a, %d %b %Y %H:%M:%S +0000", time.gmtime(res))
2402c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2403c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return "%s (%d)" % (t, x)
2404c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2405c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass MIP6OptReplayProtection(_MIP6OptAlign, Packet): # RFC 4285 (Sect. 6)
2406c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "MIPv6 option - Replay Protection"
2407c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("otype", 10, _mobopttypes),
2408c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("olen", 8),
2409c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    NTPTimestampField("timestamp", 0) ]
2410c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    x = 8 ; y = 2 # alignment requirement: 8n+2
2411c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2412c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass MIP6OptCGAParamsReq(_MIP6OptAlign, Packet): # RFC 4866 (Sect. 5.6)
2413c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "MIPv6 option - CGA Parameters Request"
2414c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("otype", 11, _mobopttypes),
2415c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("olen", 0) ]
2416c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    x = 0 ; y = 0 # alignment requirement: none
2417c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2418c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# XXX TODO: deal with CGA param fragmentation and build of defragmented
2419c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# XXX       version. Passing of a big CGAParam structure should be
2420c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# XXX       simplified. Make it hold packets, by the way  --arno
2421c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass MIP6OptCGAParams(_MIP6OptAlign, Packet): # RFC 4866 (Sect. 5.1)
2422c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "MIPv6 option - CGA Parameters"
2423c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("otype", 12, _mobopttypes),
2424c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    FieldLenField("olen", None, length_of="cgaparams", fmt="B"),
2425c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    StrLenField("cgaparams", "",
2426c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                length_from = lambda pkt: pkt.olen) ]
2427c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    x = 0 ; y = 0 # alignment requirement: none
2428c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2429c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass MIP6OptSignature(_MIP6OptAlign, Packet): # RFC 4866 (Sect. 5.2)
2430c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "MIPv6 option - Signature"
2431c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("otype", 13, _mobopttypes),
2432c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    FieldLenField("olen", None, length_of="sig", fmt="B"),
2433c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    StrLenField("sig", "",
2434c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                length_from = lambda pkt: pkt.olen) ]
2435c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    x = 0 ; y = 0 # alignment requirement: none
2436c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2437c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass MIP6OptHomeKeygenToken(_MIP6OptAlign, Packet): # RFC 4866 (Sect. 5.3)
2438c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "MIPv6 option - Home Keygen Token"
2439c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("otype", 14, _mobopttypes),
2440c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    FieldLenField("olen", None, length_of="hkt", fmt="B"),
2441c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    StrLenField("hkt", "",
2442c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                length_from = lambda pkt: pkt.olen) ]
2443c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    x = 0 ; y = 0 # alignment requirement: none
2444c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2445c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass MIP6OptCareOfTestInit(_MIP6OptAlign, Packet): # RFC 4866 (Sect. 5.4)
2446c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "MIPv6 option - Care-of Test Init"
2447c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("otype", 15, _mobopttypes),
2448c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("olen", 0) ]
2449c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    x = 0 ; y = 0 # alignment requirement: none
2450c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2451c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass MIP6OptCareOfTest(_MIP6OptAlign, Packet): # RFC 4866 (Sect. 5.5)
2452c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "MIPv6 option - Care-of Test"
2453c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("otype", 16, _mobopttypes),
2454c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    FieldLenField("olen", None, length_of="cokt", fmt="B"),
2455c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    StrLenField("cokt", '\x00'*8,
2456c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                length_from = lambda pkt: pkt.olen) ]
2457c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    x = 0 ; y = 0 # alignment requirement: none
2458c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2459c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass MIP6OptUnknown(_MIP6OptAlign, Packet):
2460c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = 'Scapy6 - Unknown Mobility Option'
2461c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("otype", 6, _mobopttypes),
2462c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    FieldLenField("olen", None, length_of="odata", fmt="B"),
2463c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    StrLenField("odata", "",
2464c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                length_from = lambda pkt: pkt.olen) ]
2465c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    x = 0 ; y = 0 # alignment requirement: none
2466c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2467c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilmoboptcls = {  0: Pad1,
2468c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               1: PadN,
2469c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               2: MIP6OptBRAdvice,
2470c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               3: MIP6OptAltCoA,
2471c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               4: MIP6OptNonceIndices,
2472c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               5: MIP6OptBindingAuthData,
2473c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               6: MIP6OptMobNetPrefix,
2474c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               7: MIP6OptLLAddr,
2475c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               8: MIP6OptMNID,
2476c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               9: MIP6OptMsgAuth,
2477c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil              10: MIP6OptReplayProtection,
2478c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil              11: MIP6OptCGAParamsReq,
2479c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil              12: MIP6OptCGAParams,
2480c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil              13: MIP6OptSignature,
2481c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil              14: MIP6OptHomeKeygenToken,
2482c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil              15: MIP6OptCareOfTestInit,
2483c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil              16: MIP6OptCareOfTest }
2484c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2485c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2486c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# Main Mobile IPv6 Classes
2487c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2488c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilmhtypes = {  0: 'BRR',
2489c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             1: 'HoTI',
2490c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             2: 'CoTI',
2491c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             3: 'HoT',
2492c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             4: 'CoT',
2493c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             5: 'BU',
2494c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             6: 'BA',
2495c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             7: 'BE',
2496c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             8: 'Fast BU',
2497c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             9: 'Fast BA',
2498c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            10: 'Fast NA' }
2499c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2500c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# From http://www.iana.org/assignments/mobility-parameters
2501c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilbastatus = {   0: 'Binding Update accepted',
2502c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil               1: 'Accepted but prefix discovery necessary',
2503c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             128: 'Reason unspecified',
2504c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             129: 'Administratively prohibited',
2505c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             130: 'Insufficient resources',
2506c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             131: 'Home registration not supported',
2507c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             132: 'Not home subnet',
2508c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             133: 'Not home agent for this mobile node',
2509c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             134: 'Duplicate Address Detection failed',
2510c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             135: 'Sequence number out of window',
2511c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             136: 'Expired home nonce index',
2512c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             137: 'Expired care-of nonce index',
2513c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             138: 'Expired nonces',
2514c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             139: 'Registration type change disallowed',
2515c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             140: 'Mobile Router Operation not permitted',
2516c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             141: 'Invalid Prefix',
2517c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             142: 'Not Authorized for Prefix',
2518c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             143: 'Forwarding Setup failed (prefixes missing)',
2519c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             144: 'MIPV6-ID-MISMATCH',
2520c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             145: 'MIPV6-MESG-ID-REQD',
2521c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             146: 'MIPV6-AUTH-FAIL',
2522c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             147: 'Permanent home keygen token unavailable',
2523c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             148: 'CGA and signature verification failed',
2524c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             149: 'Permanent home keygen token exists',
2525c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil             150: 'Non-null home nonce index expected' }
2526c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2527c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2528c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass _MobilityHeader(Packet):
2529c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = 'Dummy IPv6 Mobility Header'
2530c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    overload_fields = { IPv6: { "nh": 135 }}
2531c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2532c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def post_build(self, p, pay):
2533c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        p += pay
2534c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        l = self.len
2535c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if self.len is None:
2536c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            l = (len(p)-8)/8
2537c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        p = p[0] + struct.pack("B", l) + p[2:]
2538c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if self.cksum is None:
2539c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            cksum = in6_chksum(135, self.underlayer, p)
2540c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        else:
2541c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            cksum = self.cksum
2542c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        p = p[:4]+struct.pack("!H", cksum)+p[6:]
2543c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return p
2544c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2545c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2546c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass MIP6MH_Generic(_MobilityHeader): # Mainly for decoding of unknown msg
2547c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "IPv6 Mobility Header - Generic Message"
2548c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("nh", 59, ipv6nh),
2549c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("len", None),
2550c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteEnumField("mhtype", None, mhtypes),
2551c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("res", None),
2552c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("cksum", None),
2553c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    StrLenField("msg", "\x00"*2,
2554c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                length_from = lambda pkt: 8*pkt.len-6) ]
2555c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2556c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2557c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2558c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# TODO: make a generic _OptionsField
2559c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass _MobilityOptionsField(PacketListField):
2560c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    islist = 1
2561c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    holds_packet = 1
2562c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2563c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def __init__(self, name, default, cls, curpos, count_from=None, length_from=None):
2564c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        self.curpos = curpos
2565c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        PacketListField.__init__(self, name, default, cls, count_from=count_from, length_from=length_from)
2566c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2567c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def getfield(self, pkt, s):
2568c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        l = self.length_from(pkt)
2569c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return s[l:],self.m2i(pkt, s[:l])
2570c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2571c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def i2len(self, pkt, i):
2572c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return len(self.i2m(pkt, i))
2573c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2574c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def m2i(self, pkt, x):
2575c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        opt = []
2576c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        while x:
2577c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            o = ord(x[0]) # Option type
2578c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            cls = self.cls
2579c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            if moboptcls.has_key(o):
2580c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                cls = moboptcls[o]
2581c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            try:
2582c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                op = cls(x)
2583c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            except:
2584c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                op = self.cls(x)
2585c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            opt.append(op)
2586c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            if isinstance(op.payload, Raw):
2587c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                x = op.payload.load
2588c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                del(op.payload)
2589c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            else:
2590c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                x = ""
2591c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return opt
2592c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2593c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def i2m(self, pkt, x):
2594c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        autopad = None
2595c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        try:
2596c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            autopad = getattr(pkt, "autopad") # Hack : 'autopad' phantom field
2597c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        except:
2598c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            autopad = 1
2599c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2600c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if not autopad:
2601c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return "".join(map(str, x))
2602c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2603c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        curpos = self.curpos
2604c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        s = ""
2605c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        for p in x:
2606c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            d = p.alignment_delta(curpos)
2607c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            curpos += d
2608c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            if d == 1:
2609c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                s += str(Pad1())
2610c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            elif d != 0:
2611c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                s += str(PadN(optdata='\x00'*(d-2)))
2612c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            pstr = str(p)
2613c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            curpos += len(pstr)
2614c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            s += pstr
2615c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2616c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        # Let's make the class including our option field
2617c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        # a multiple of 8 octets long
2618c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        d = curpos % 8
2619c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if d == 0:
2620c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return s
2621c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        d = 8 - d
2622c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if d == 1:
2623c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            s += str(Pad1())
2624c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        elif d != 0:
2625c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            s += str(PadN(optdata='\x00'*(d-2)))
2626c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2627c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return s
2628c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2629c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def addfield(self, pkt, s, val):
2630c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return s+self.i2m(pkt, val)
2631c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2632c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass MIP6MH_BRR(_MobilityHeader):
2633c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "IPv6 Mobility Header - Binding Refresh Request"
2634c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("nh", 59, ipv6nh),
2635c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("len", None),
2636c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteEnumField("mhtype", 0, mhtypes),
2637c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("res", None),
2638c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("cksum", None),
2639c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ShortField("res2", None),
2640c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    _PhantomAutoPadField("autopad", 1), # autopad activated by default
2641c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    _MobilityOptionsField("options", [], MIP6OptUnknown, 8,
2642c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                          length_from = lambda pkt: 8*pkt.len) ]
2643c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    overload_fields = { IPv6: { "nh": 135 } }
2644c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def hashret(self):
2645c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        # Hack: BRR, BU and BA have the same hashret that returns the same
2646c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        #       value "\x00\x08\x09" (concatenation of mhtypes). This is
2647c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        #       because we need match BA with BU and BU with BRR. --arno
2648c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return "\x00\x08\x09"
2649c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2650c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass MIP6MH_HoTI(_MobilityHeader):
2651c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "IPv6 Mobility Header - Home Test Init"
2652c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("nh", 59, ipv6nh),
2653c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("len", None),
2654c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteEnumField("mhtype", 1, mhtypes),
2655c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("res", None),
2656c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("cksum", None),
2657c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    StrFixedLenField("cookie", "\x00"*8, 8),
2658c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    _PhantomAutoPadField("autopad", 1), # autopad activated by default
2659c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    _MobilityOptionsField("options", [], MIP6OptUnknown, 16,
2660c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                          length_from = lambda pkt: 8*(pkt.len-1)) ]
2661c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    overload_fields = { IPv6: { "nh": 135 } }
2662c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def hashret(self):
2663c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return self.cookie
2664c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2665c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass MIP6MH_CoTI(MIP6MH_HoTI):
2666c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "IPv6 Mobility Header - Care-of Test Init"
2667c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    mhtype = 2
2668c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def hashret(self):
2669c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return self.cookie
2670c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2671c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass MIP6MH_HoT(_MobilityHeader):
2672c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "IPv6 Mobility Header - Home Test"
2673c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("nh", 59, ipv6nh),
2674c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("len", None),
2675c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteEnumField("mhtype", 3, mhtypes),
2676c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("res", None),
2677c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("cksum", None),
2678c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ShortField("index", None),
2679c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    StrFixedLenField("cookie", "\x00"*8, 8),
2680c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    StrFixedLenField("token", "\x00"*8, 8),
2681c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    _PhantomAutoPadField("autopad", 1), # autopad activated by default
2682c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    _MobilityOptionsField("options", [], MIP6OptUnknown, 24,
2683c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                          length_from = lambda pkt: 8*(pkt.len-2)) ]
2684c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    overload_fields = { IPv6: { "nh": 135 } }
2685c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def hashret(self):
2686c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return self.cookie
2687c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def answers(self):
2688c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if (isinstance(other, MIP6MH_HoTI) and
2689c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            self.cookie == other.cookie):
2690c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return 1
2691c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return 0
2692c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2693c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass MIP6MH_CoT(MIP6MH_HoT):
2694c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "IPv6 Mobility Header - Care-of Test"
2695c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    mhtype = 4
2696c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def hashret(self):
2697c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return self.cookie
2698c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2699c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def answers(self):
2700c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if (isinstance(other, MIP6MH_CoTI) and
2701c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            self.cookie == other.cookie):
2702c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return 1
2703c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return 0
2704c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2705c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass LifetimeField(ShortField):
2706c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def i2repr(self, pkt, x):
2707c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return "%d sec" % (4*x)
2708c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2709c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass MIP6MH_BU(_MobilityHeader):
2710c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "IPv6 Mobility Header - Binding Update"
2711c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("nh", 59, ipv6nh),
2712c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("len", None), # unit == 8 bytes (excluding the first 8 bytes)
2713c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteEnumField("mhtype", 5, mhtypes),
2714c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("res", None),
2715c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("cksum", None),
2716c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("seq", None), # TODO: ShortNonceField
2717571ee9a1f1431f1ec7e654b5ee991e2118b994efPhil                    FlagsField("flags", "KHA", 7, "PRMKLHA"),
2718571ee9a1f1431f1ec7e654b5ee991e2118b994efPhil                    XBitField("reserved", 0, 9),
2719c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    LifetimeField("mhtime", 3), # unit == 4 seconds
2720c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    _PhantomAutoPadField("autopad", 1), # autopad activated by default
2721c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    _MobilityOptionsField("options", [], MIP6OptUnknown, 12,
2722c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                          length_from = lambda pkt: 8*pkt.len - 4) ]
2723c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    overload_fields = { IPv6: { "nh": 135 } }
2724c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2725c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def hashret(self): # Hack: see comment in MIP6MH_BRR.hashret()
2726c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return "\x00\x08\x09"
2727c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2728c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def answers(self, other):
2729c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if isinstance(other, MIP6MH_BRR):
2730c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return 1
2731c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return 0
2732c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2733c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass MIP6MH_BA(_MobilityHeader):
2734c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "IPv6 Mobility Header - Binding ACK"
2735c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("nh", 59, ipv6nh),
2736c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("len", None), # unit == 8 bytes (excluding the first 8 bytes)
2737c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteEnumField("mhtype", 6, mhtypes),
2738c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("res", None),
2739c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("cksum", None),
2740c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteEnumField("status", 0, bastatus),
2741571ee9a1f1431f1ec7e654b5ee991e2118b994efPhil                    FlagsField("flags", "K", 3, "PRK"),
2742571ee9a1f1431f1ec7e654b5ee991e2118b994efPhil                    XBitField("res2", None, 5),
2743c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("seq", None), # TODO: ShortNonceField
2744c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("mhtime", 0), # unit == 4 seconds
2745c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    _PhantomAutoPadField("autopad", 1), # autopad activated by default
2746c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    _MobilityOptionsField("options", [], MIP6OptUnknown, 12,
2747c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                          length_from = lambda pkt: 8*pkt.len-4) ]
2748c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    overload_fields = { IPv6: { "nh": 135 }}
2749c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2750c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def hashret(self): # Hack: see comment in MIP6MH_BRR.hashret()
2751c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return "\x00\x08\x09"
2752c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2753c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def answers(self, other):
2754c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if (isinstance(other, MIP6MH_BU) and
2755c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            other.mhtype == 5 and
2756c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            self.mhtype == 6 and
2757c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            other.flags & 0x1 and # Ack request flags is set
2758c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            self.seq == other.seq):
2759c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            return 1
2760c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return 0
2761c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2762c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil_bestatus = { 1: 'Unknown binding for Home Address destination option',
2763c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil              2: 'Unrecognized MH Type value' }
2764c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2765c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil# TODO: match Binding Error to its stimulus
2766c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass MIP6MH_BE(_MobilityHeader):
2767c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    name = "IPv6 Mobility Header - Binding Error"
2768c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    fields_desc = [ ByteEnumField("nh", 59, ipv6nh),
2769c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("len", None), # unit == 8 bytes (excluding the first 8 bytes)
2770c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteEnumField("mhtype", 7, mhtypes),
2771c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("res", 0),
2772c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    XShortField("cksum", None),
2773c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteEnumField("status", 0, _bestatus),
2774c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    ByteField("reserved", 0),
2775c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    IP6Field("ha", "::"),
2776c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    _MobilityOptionsField("options", [], MIP6OptUnknown, 24,
2777c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                          length_from = lambda pkt: 8*(pkt.len-2)) ]
2778c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    overload_fields = { IPv6: { "nh": 135 }}
2779c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2780c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil_mip6_mhtype2cls = { 0: MIP6MH_BRR,
2781c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                     1: MIP6MH_HoTI,
2782c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                     2: MIP6MH_CoTI,
2783c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                     3: MIP6MH_HoT,
2784c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                     4: MIP6MH_CoT,
2785c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                     5: MIP6MH_BU,
2786c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                     6: MIP6MH_BA,
2787c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                     7: MIP6MH_BE }
2788c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2789c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2790c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
2791c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
2792c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil###                             Traceroute6                               ###
2793c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
2794c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
2795c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2796c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass  AS_resolver6(AS_resolver_riswhois):
2797c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def _resolve_one(self, ip):
2798c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        """
2799c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        overloaded version to provide a Whois resolution on the
2800c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        embedded IPv4 address if the address is 6to4 or Teredo.
2801c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        Otherwise, the native IPv6 address is passed.
2802c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        """
2803c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2804c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if in6_isaddr6to4(ip): # for 6to4, use embedded @
2805c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            tmp = inet_pton(socket.AF_INET6, ip)
2806c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            addr = inet_ntop(socket.AF_INET, tmp[2:6])
2807c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        elif in6_isaddrTeredo(ip): # for Teredo, use mapped address
2808c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            addr = teredoAddrExtractInfo(ip)[2]
2809c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        else:
2810c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            addr = ip
2811c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2812c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        _, asn, desc = AS_resolver_riswhois._resolve_one(self, addr)
2813c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2814c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return ip,asn,desc
2815c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2816c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass TracerouteResult6(TracerouteResult):
2817c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def show(self):
2818c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return self.make_table(lambda (s,r): (s.sprintf("%-42s,IPv6.dst%:{TCP:tcp%TCP.dport%}{UDP:udp%UDP.dport%}{ICMPv6EchoRequest:IER}"), # TODO: ICMPv6 !
2819c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                              s.hlim,
2820c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                                              r.sprintf("%-42s,IPv6.src% {TCP:%TCP.flags%}"+
282177132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                                                        "{ICMPv6DestUnreach:%ir,type%}{ICMPv6PacketTooBig:%ir,type%}"+
282277132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                                                        "{ICMPv6TimeExceeded:%ir,type%}{ICMPv6ParamProblem:%ir,type%}"+
282377132687c31a9d3f30c3992c70eb24d1ac0948a7Phil                                                        "{ICMPv6EchoReply:%ir,type%}")))
2824c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2825c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def get_trace(self):
2826c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        trace = {}
2827c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2828c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        for s,r in self.res:
2829c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            if IPv6 not in s:
2830c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                continue
2831c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            d = s[IPv6].dst
2832c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            if d not in trace:
2833c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                trace[d] = {}
2834c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2835c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            t = not (ICMPv6TimeExceeded in r or
2836c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                     ICMPv6DestUnreach in r or
2837c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                     ICMPv6PacketTooBig in r or
2838c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                     ICMPv6ParamProblem in r)
2839c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2840c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            trace[d][s[IPv6].hlim] = r[IPv6].src, t
2841c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2842c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        for k in trace.values():
2843c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            m = filter(lambda x: k[x][1], k.keys())
2844c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            if not m:
2845c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                continue
2846c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            m = min(m)
2847c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil            for l in k.keys():
2848c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                if l > m:
2849c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                    del(k[l])
2850c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2851c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        return trace
2852c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2853c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def graph(self, ASres=AS_resolver6(), **kargs):
2854c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        TracerouteResult.graph(self, ASres=ASres, **kargs)
2855c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2856c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhildef traceroute6(target, dport=80, minttl=1, maxttl=30, sport=RandShort(),
2857c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                l4 = None, timeout=2, verbose=None, **kargs):
2858c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    """
2859c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    Instant TCP traceroute using IPv6 :
2860c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    traceroute6(target, [maxttl=30], [dport=80], [sport=80]) -> None
2861c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    """
2862c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    if verbose is None:
2863c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        verbose = conf.verb
2864c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2865c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    if l4 is None:
2866c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        a,b = sr(IPv6(dst=target, hlim=(minttl,maxttl))/TCP(seq=RandInt(),sport=sport, dport=dport),
2867c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                 timeout=timeout, filter="icmp6 or tcp", verbose=verbose, **kargs)
2868c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    else:
2869c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        a,b = sr(IPv6(dst=target, hlim=(minttl,maxttl))/l4,
2870c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil                 timeout=timeout, verbose=verbose, **kargs)
2871c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2872c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    a = TracerouteResult6(a.res)
2873c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2874c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    if verbose:
2875c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        a.display()
2876c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2877c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    return a,b
2878c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2879c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
2880c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
2881c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil###                                Sockets                                ###
2882c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
2883c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
2884c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2885c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass L3RawSocket6(L3RawSocket):
2886c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    def __init__(self, type = ETH_P_IPV6, filter=None, iface=None, promisc=None, nofilter=0):
2887c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        L3RawSocket.__init__(self, type, filter, iface, promisc)
288877132687c31a9d3f30c3992c70eb24d1ac0948a7Phil        # NOTE: if fragmentation is needed, it will be done by the kernel (RFC 2292)
2889c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        self.outs = socket.socket(socket.AF_INET6, socket.SOCK_RAW, socket.IPPROTO_RAW)
2890c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        self.ins = socket.socket(socket.AF_PACKET, socket.SOCK_RAW, socket.htons(type))
2891c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2892c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhildef IPv6inIP(dst='203.178.135.36', src=None):
2893c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil  _IPv6inIP.dst = dst
2894c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil  _IPv6inIP.src = src
2895c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil  if not conf.L3socket == _IPv6inIP:
2896c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    _IPv6inIP.cls = conf.L3socket
2897c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil  else:
2898c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    del(conf.L3socket)
2899c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil  return _IPv6inIP
2900c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2901c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilclass _IPv6inIP(SuperSocket):
2902c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil  dst = '127.0.0.1'
2903c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil  src = None
2904c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil  cls = None
2905c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2906c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil  def __init__(self, family=socket.AF_INET6, type=socket.SOCK_STREAM, proto=0, **args):
2907c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    SuperSocket.__init__(self, family, type, proto)
2908c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    self.worker = self.cls(**args)
2909c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2910c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil  def set(self, dst, src=None):
2911c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    _IPv6inIP.src = src
2912c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    _IPv6inIP.dst = dst
2913c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2914c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil  def nonblock_recv(self):
2915c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    p = self.worker.nonblock_recv()
2916c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    return self._recv(p)
2917c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2918c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil  def recv(self, x):
2919c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    p = self.worker.recv(x)
2920c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    return self._recv(p, x)
2921c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2922c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil  def _recv(self, p, x=MTU):
2923c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    if p is None:
2924c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil      return p
2925c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    elif isinstance(p, IP):
2926c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil      # TODO: verify checksum
2927c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil      if p.src == self.dst and p.proto == socket.IPPROTO_IPV6:
2928c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil        if isinstance(p.payload, IPv6):
2929c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil          return p.payload
2930c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    return p
2931c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2932c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil  def send(self, x):
2933c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil    return self.worker.send(IP(dst=self.dst, src=self.src, proto=socket.IPPROTO_IPV6)/x)
2934c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2935c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2936c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
2937c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
2938c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil###                          Layers binding                               ###
2939c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
2940c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil#############################################################################
2941c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2942614f54fc4b269030ba2934b6c353fb43de886e04Philconf.l3types.register(ETH_P_IPV6, IPv6)
2943614f54fc4b269030ba2934b6c353fb43de886e04Philconf.l2types.register(31, IPv6)
2944c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2945c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilbind_layers(Ether,     IPv6,     type = 0x86dd )
2946e0602343e528b8c9a53f20a0a40994eb1bb33436rbu@localhost.localdomainbind_layers(CookedLinux, IPv6,   proto = 0x86dd )
2947c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilbind_layers(IPerror6,  TCPerror, nh = socket.IPPROTO_TCP )
2948c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilbind_layers(IPerror6,  UDPerror, nh = socket.IPPROTO_UDP )
2949c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilbind_layers(IPv6,      TCP,      nh = socket.IPPROTO_TCP )
2950c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilbind_layers(IPv6,      UDP,      nh = socket.IPPROTO_UDP )
2951c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilbind_layers(IP,        IPv6,     proto = socket.IPPROTO_IPV6 )
2952c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhilbind_layers(IPv6,      IPv6,     nh = socket.IPPROTO_IPV6 )
2953c0ae52849d8287e63ed3bebc36af2da3ff8aba3cPhil
2954