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